diff --git a/Marlin/src/Marlin.cpp b/Marlin/src/Marlin.cpp
index dcd8599af..25cb73444 100644
--- a/Marlin/src/Marlin.cpp
+++ b/Marlin/src/Marlin.cpp
@@ -272,24 +272,6 @@ static millis_t stepper_inactive_time = (DEFAULT_STEPPER_DEACTIVE_TIME) * 1000UL
baricuda_e_to_p_pressure = 0;
#endif
-#if ENABLED(FWRETRACT) // Initialized by settings.load()...
- bool autoretract_enabled, // M209 S - Autoretract switch
- retracted[EXTRUDERS] = { false }; // Which extruders are currently retracted
- float retract_length, // M207 S - G10 Retract length
- retract_feedrate_mm_s, // M207 F - G10 Retract feedrate
- retract_zlift, // M207 Z - G10 Retract hop size
- retract_recover_length, // M208 S - G11 Recover length
- retract_recover_feedrate_mm_s, // M208 F - G11 Recover feedrate
- swap_retract_length, // M207 W - G10 Swap Retract length
- swap_retract_recover_length, // M208 W - G11 Swap Recover length
- swap_retract_recover_feedrate_mm_s; // M208 R - G11 Swap Recover feedrate
- #if EXTRUDERS > 1
- bool retracted_swap[EXTRUDERS] = { false }; // Which extruders are swap-retracted
- #else
- constexpr bool retracted_swap[1] = { false };
- #endif
-#endif // FWRETRACT
-
#if HAS_POWER_SWITCH
bool powersupply_on =
#if ENABLED(PS_DEFAULT_OFF)
@@ -2322,132 +2304,6 @@ static void homeaxis(const AxisEnum axis) {
#endif
} // homeaxis()
-#if ENABLED(FWRETRACT)
-
- /**
- * Retract or recover according to firmware settings
- *
- * This function handles retract/recover moves for G10 and G11,
- * plus auto-retract moves sent from G0/G1 when E-only moves are done.
- *
- * To simplify the logic, doubled retract/recover moves are ignored.
- *
- * Note: Z lift is done transparently to the planner. Aborting
- * a print between G10 and G11 may corrupt the Z position.
- *
- * Note: Auto-retract will apply the set Z hop in addition to any Z hop
- * included in the G-code. Use M207 Z0 to to prevent double hop.
- */
- void retract(const bool retracting
- #if EXTRUDERS > 1
- , bool swapping = false
- #endif
- ) {
-
- static float hop_height, // Remember where the Z height started
- hop_amount = 0.0; // Total amount lifted, for use in recover
-
- // Simply never allow two retracts or recovers in a row
- if (retracted[active_extruder] == retracting) return;
-
- #if EXTRUDERS < 2
- bool swapping = false;
- #endif
- if (!retracting) swapping = retracted_swap[active_extruder];
-
- /* // debugging
- SERIAL_ECHOLNPAIR("retracting ", retracting);
- SERIAL_ECHOLNPAIR("swapping ", swapping);
- SERIAL_ECHOLNPAIR("active extruder ", active_extruder);
- for (uint8_t i = 0; i < EXTRUDERS; ++i) {
- SERIAL_ECHOPAIR("retracted[", i);
- SERIAL_ECHOLNPAIR("] ", retracted[i]);
- SERIAL_ECHOPAIR("retracted_swap[", i);
- SERIAL_ECHOLNPAIR("] ", retracted_swap[i]);
- }
- SERIAL_ECHOLNPAIR("current_position[z] ", current_position[Z_AXIS]);
- SERIAL_ECHOLNPAIR("hop_amount ", hop_amount);
- //*/
-
- const bool has_zhop = retract_zlift > 0.01; // Is there a hop set?
-
- const float old_feedrate_mm_s = feedrate_mm_s;
- const int16_t old_flow = flow_percentage[active_extruder];
-
- // Don't apply flow multiplication to retract/recover
- flow_percentage[active_extruder] = 100;
-
- // The current position will be the destination for E and Z moves
- set_destination_to_current();
-
- if (retracting) {
- // Remember the Z height since G-code may include its own Z-hop
- // For best results turn off Z hop if G-code already includes it
- hop_height = destination[Z_AXIS];
-
- // Retract by moving from a faux E position back to the current E position
- feedrate_mm_s = retract_feedrate_mm_s;
- current_position[E_AXIS] += (swapping ? swap_retract_length : retract_length) / volumetric_multiplier[active_extruder];
- sync_plan_position_e();
- prepare_move_to_destination();
-
- // Is a Z hop set, and has the hop not yet been done?
- if (has_zhop) {
- hop_amount += retract_zlift; // Carriage is raised for retraction hop
- current_position[Z_AXIS] -= retract_zlift; // Pretend current pos is lower. Next move raises Z.
- SYNC_PLAN_POSITION_KINEMATIC(); // Set the planner to the new position
- prepare_move_to_destination(); // Raise up to the old current pos
- }
- }
- else {
- // If a hop was done and Z hasn't changed, undo the Z hop
- if (hop_amount && NEAR(hop_height, destination[Z_AXIS])) {
- current_position[Z_AXIS] += hop_amount; // Pretend current pos is higher. Next move lowers Z.
- SYNC_PLAN_POSITION_KINEMATIC(); // Set the planner to the new position
- prepare_move_to_destination(); // Lower to the old current pos
- hop_amount = 0.0;
- }
-
- // A retract multiplier has been added here to get faster swap recovery
- feedrate_mm_s = swapping ? swap_retract_recover_feedrate_mm_s : retract_recover_feedrate_mm_s;
-
- const float move_e = swapping ? swap_retract_length + swap_retract_recover_length : retract_length + retract_recover_length;
- current_position[E_AXIS] -= move_e / volumetric_multiplier[active_extruder];
- sync_plan_position_e();
-
- prepare_move_to_destination(); // Recover E
- }
-
- // Restore flow and feedrate
- flow_percentage[active_extruder] = old_flow;
- feedrate_mm_s = old_feedrate_mm_s;
-
- // The active extruder is now retracted or recovered
- retracted[active_extruder] = retracting;
-
- // If swap retract/recover then update the retracted_swap flag too
- #if EXTRUDERS > 1
- if (swapping) retracted_swap[active_extruder] = retracting;
- #endif
-
- /* // debugging
- SERIAL_ECHOLNPAIR("retracting ", retracting);
- SERIAL_ECHOLNPAIR("swapping ", swapping);
- SERIAL_ECHOLNPAIR("active_extruder ", active_extruder);
- for (uint8_t i = 0; i < EXTRUDERS; ++i) {
- SERIAL_ECHOPAIR("retracted[", i);
- SERIAL_ECHOLNPAIR("] ", retracted[i]);
- SERIAL_ECHOPAIR("retracted_swap[", i);
- SERIAL_ECHOLNPAIR("] ", retracted_swap[i]);
- }
- SERIAL_ECHOLNPAIR("current_position[z] ", current_position[Z_AXIS]);
- SERIAL_ECHOLNPAIR("hop_amount ", hop_amount);
- //*/
-
- } // retract()
-
-#endif // FWRETRACT
-
#if ENABLED(MIXING_EXTRUDER)
void normalize_mix() {
@@ -2547,10 +2403,6 @@ void dwell(millis_t time) {
#include "gcode/motion/G5.h"
#endif
-#if ENABLED(FWRETRACT)
- #include "gcode/feature/fwretract/G10_G11.h"
-#endif
-
#if ENABLED(NOZZLE_CLEAN_FEATURE)
#include "gcode/feature/clean/G12.h"
#endif
diff --git a/Marlin/src/Marlin.h b/Marlin/src/Marlin.h
index cd131be93..f56dd4e1d 100644
--- a/Marlin/src/Marlin.h
+++ b/Marlin/src/Marlin.h
@@ -302,18 +302,6 @@ extern float soft_endstop_min[XYZ], soft_endstop_max[XYZ];
extern int lpq_len;
#endif
-#if ENABLED(FWRETRACT)
- extern bool autoretract_enabled; // M209 S - Autoretract switch
- extern float retract_length, // M207 S - G10 Retract length
- retract_feedrate_mm_s, // M207 F - G10 Retract feedrate
- retract_zlift, // M207 Z - G10 Retract hop size
- retract_recover_length, // M208 S - G11 Recover length
- retract_recover_feedrate_mm_s, // M208 F - G11 Recover feedrate
- swap_retract_length, // M207 W - G10 Swap Retract length
- swap_retract_recover_length, // M208 W - G11 Swap Recover length
- swap_retract_recover_feedrate_mm_s; // M208 R - G11 Swap Recover feedrate
-#endif
-
// Print job timer
#if ENABLED(PRINTCOUNTER)
extern PrintCounter print_job_timer;
diff --git a/Marlin/src/feature/fwretract.cpp b/Marlin/src/feature/fwretract.cpp
new file mode 100644
index 000000000..60191f84e
--- /dev/null
+++ b/Marlin/src/feature/fwretract.cpp
@@ -0,0 +1,185 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+/**
+ * fwretract.cpp - Implement firmware-based retraction
+ */
+
+#include "../inc/MarlinConfig.h"
+
+#if ENABLED(FWRETRACT)
+
+#include "fwretract.h"
+
+FWRetract fwretract; // Single instance
+
+#include "../module/motion.h"
+
+bool FWRetract::autoretract_enabled, // M209 S - Autoretract switch
+ FWRetract::retracted[EXTRUDERS] = { false }; // Which extruders are currently retracted
+float FWRetract::retract_length, // M207 S - G10 Retract length
+ FWRetract::retract_feedrate_mm_s, // M207 F - G10 Retract feedrate
+ FWRetract::retract_zlift, // M207 Z - G10 Retract hop size
+ FWRetract::retract_recover_length, // M208 S - G11 Recover length
+ FWRetract::retract_recover_feedrate_mm_s, // M208 F - G11 Recover feedrate
+ FWRetract::swap_retract_length, // M207 W - G10 Swap Retract length
+ FWRetract::swap_retract_recover_length, // M208 W - G11 Swap Recover length
+ FWRetract::swap_retract_recover_feedrate_mm_s; // M208 R - G11 Swap Recover feedrate
+#if EXTRUDERS > 1
+ bool FWRetract::retracted_swap[EXTRUDERS] = { false }; // Which extruders are swap-retracted
+#endif
+
+void FWRetract::reset() {
+ autoretract_enabled = false;
+ retract_length = RETRACT_LENGTH;
+ retract_feedrate_mm_s = RETRACT_FEEDRATE;
+ retract_zlift = RETRACT_ZLIFT;
+ retract_recover_length = RETRACT_RECOVER_LENGTH;
+ retract_recover_feedrate_mm_s = RETRACT_RECOVER_FEEDRATE;
+ swap_retract_length = RETRACT_LENGTH_SWAP;
+ swap_retract_recover_length = RETRACT_RECOVER_LENGTH_SWAP;
+ swap_retract_recover_feedrate_mm_s = RETRACT_RECOVER_FEEDRATE_SWAP;
+}
+
+/**
+ * Retract or recover according to firmware settings
+ *
+ * This function handles retract/recover moves for G10 and G11,
+ * plus auto-retract moves sent from G0/G1 when E-only moves are done.
+ *
+ * To simplify the logic, doubled retract/recover moves are ignored.
+ *
+ * Note: Z lift is done transparently to the planner. Aborting
+ * a print between G10 and G11 may corrupt the Z position.
+ *
+ * Note: Auto-retract will apply the set Z hop in addition to any Z hop
+ * included in the G-code. Use M207 Z0 to to prevent double hop.
+ */
+void FWRetract::retract(const bool retracting
+ #if EXTRUDERS > 1
+ , bool swapping /* =false */
+ #endif
+) {
+
+ static float hop_height, // Remember where the Z height started
+ hop_amount = 0.0; // Total amount lifted, for use in recover
+
+ // Simply never allow two retracts or recovers in a row
+ if (retracted[active_extruder] == retracting) return;
+
+ #if EXTRUDERS < 2
+ bool swapping = false;
+ #endif
+ if (!retracting) swapping = retracted_swap[active_extruder];
+
+ /* // debugging
+ SERIAL_ECHOLNPAIR("retracting ", retracting);
+ SERIAL_ECHOLNPAIR("swapping ", swapping);
+ SERIAL_ECHOLNPAIR("active extruder ", active_extruder);
+ for (uint8_t i = 0; i < EXTRUDERS; ++i) {
+ SERIAL_ECHOPAIR("retracted[", i);
+ SERIAL_ECHOLNPAIR("] ", retracted[i]);
+ SERIAL_ECHOPAIR("retracted_swap[", i);
+ SERIAL_ECHOLNPAIR("] ", retracted_swap[i]);
+ }
+ SERIAL_ECHOLNPAIR("current_position[z] ", current_position[Z_AXIS]);
+ SERIAL_ECHOLNPAIR("hop_amount ", hop_amount);
+ //*/
+
+ const bool has_zhop = retract_zlift > 0.01; // Is there a hop set?
+
+ const float old_feedrate_mm_s = feedrate_mm_s;
+ const int16_t old_flow = flow_percentage[active_extruder];
+
+ // Don't apply flow multiplication to retract/recover
+ flow_percentage[active_extruder] = 100;
+
+ // The current position will be the destination for E and Z moves
+ set_destination_to_current();
+
+ if (retracting) {
+ // Remember the Z height since G-code may include its own Z-hop
+ // For best results turn off Z hop if G-code already includes it
+ hop_height = destination[Z_AXIS];
+
+ // Retract by moving from a faux E position back to the current E position
+ feedrate_mm_s = retract_feedrate_mm_s;
+ current_position[E_AXIS] += (swapping ? swap_retract_length : retract_length) / volumetric_multiplier[active_extruder];
+ sync_plan_position_e();
+ prepare_move_to_destination();
+
+ // Is a Z hop set, and has the hop not yet been done?
+ if (has_zhop) {
+ hop_amount += retract_zlift; // Carriage is raised for retraction hop
+ current_position[Z_AXIS] -= retract_zlift; // Pretend current pos is lower. Next move raises Z.
+ SYNC_PLAN_POSITION_KINEMATIC(); // Set the planner to the new position
+ prepare_move_to_destination(); // Raise up to the old current pos
+ }
+ }
+ else {
+ // If a hop was done and Z hasn't changed, undo the Z hop
+ if (hop_amount && NEAR(hop_height, destination[Z_AXIS])) {
+ current_position[Z_AXIS] += hop_amount; // Pretend current pos is higher. Next move lowers Z.
+ SYNC_PLAN_POSITION_KINEMATIC(); // Set the planner to the new position
+ prepare_move_to_destination(); // Lower to the old current pos
+ hop_amount = 0.0;
+ }
+
+ // A retract multiplier has been added here to get faster swap recovery
+ feedrate_mm_s = swapping ? swap_retract_recover_feedrate_mm_s : retract_recover_feedrate_mm_s;
+
+ const float move_e = swapping ? swap_retract_length + swap_retract_recover_length : retract_length + retract_recover_length;
+ current_position[E_AXIS] -= move_e / volumetric_multiplier[active_extruder];
+ sync_plan_position_e();
+
+ prepare_move_to_destination(); // Recover E
+ }
+
+ // Restore flow and feedrate
+ flow_percentage[active_extruder] = old_flow;
+ feedrate_mm_s = old_feedrate_mm_s;
+
+ // The active extruder is now retracted or recovered
+ retracted[active_extruder] = retracting;
+
+ // If swap retract/recover then update the retracted_swap flag too
+ #if EXTRUDERS > 1
+ if (swapping) retracted_swap[active_extruder] = retracting;
+ #endif
+
+ /* // debugging
+ SERIAL_ECHOLNPAIR("retracting ", retracting);
+ SERIAL_ECHOLNPAIR("swapping ", swapping);
+ SERIAL_ECHOLNPAIR("active_extruder ", active_extruder);
+ for (uint8_t i = 0; i < EXTRUDERS; ++i) {
+ SERIAL_ECHOPAIR("retracted[", i);
+ SERIAL_ECHOLNPAIR("] ", retracted[i]);
+ SERIAL_ECHOPAIR("retracted_swap[", i);
+ SERIAL_ECHOLNPAIR("] ", retracted_swap[i]);
+ }
+ SERIAL_ECHOLNPAIR("current_position[z] ", current_position[Z_AXIS]);
+ SERIAL_ECHOLNPAIR("hop_amount ", hop_amount);
+ //*/
+
+} // retract()
+
+#endif // FWRETRACT
diff --git a/Marlin/src/feature/fwretract.h b/Marlin/src/feature/fwretract.h
new file mode 100644
index 000000000..ed6b50d06
--- /dev/null
+++ b/Marlin/src/feature/fwretract.h
@@ -0,0 +1,65 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+/**
+ * fwretract.h - Define firmware-based retraction interface
+ */
+
+#ifndef FWRETRACT_H
+#define FWRETRACT_H
+
+#include "../inc/MarlinConfig.h"
+
+class FWRetract {
+public:
+ static bool autoretract_enabled, // M209 S - Autoretract switch
+ retracted[EXTRUDERS]; // Which extruders are currently retracted
+ static float retract_length, // M207 S - G10 Retract length
+ retract_feedrate_mm_s, // M207 F - G10 Retract feedrate
+ retract_zlift, // M207 Z - G10 Retract hop size
+ retract_recover_length, // M208 S - G11 Recover length
+ retract_recover_feedrate_mm_s, // M208 F - G11 Recover feedrate
+ swap_retract_length, // M207 W - G10 Swap Retract length
+ swap_retract_recover_length, // M208 W - G11 Swap Recover length
+ swap_retract_recover_feedrate_mm_s; // M208 R - G11 Swap Recover feedrate
+
+ #if EXTRUDERS > 1
+ static bool retracted_swap[EXTRUDERS]; // Which extruders are swap-retracted
+ #else
+ static bool constexpr retracted_swap[1] = { false };
+ #endif
+
+ FWRetract() {}
+
+ static void reset();
+
+ static void retract(const bool retracting
+ #if EXTRUDERS > 1
+ , bool swapping = false
+ #endif
+ );
+
+};
+
+extern FWRetract fwretract;
+
+#endif // FWRETRACT_H
diff --git a/Marlin/src/gcode/feature/fwretract/G10_G11.h b/Marlin/src/gcode/feature/fwretract/G10_G11.cpp
similarity index 74%
rename from Marlin/src/gcode/feature/fwretract/G10_G11.h
rename to Marlin/src/gcode/feature/fwretract/G10_G11.cpp
index be8df5039..86c1037a7 100644
--- a/Marlin/src/gcode/feature/fwretract/G10_G11.h
+++ b/Marlin/src/gcode/feature/fwretract/G10_G11.cpp
@@ -20,15 +20,23 @@
*
*/
+#include "../../../inc/MarlinConfig.h"
+
+#if ENABLED(FWRETRACT)
+
+#include "../../../feature/fwretract.h"
+#include "../../gcode.h"
+#include "../../../module/motion.h"
+
/**
* G10 - Retract filament according to settings of M207
*/
-void gcode_G10() {
+void GcodeSuite::G10() {
#if EXTRUDERS > 1
const bool rs = parser.boolval('S');
- retracted_swap[active_extruder] = rs; // Use 'S' for swap, default to false
+ fwretract.retracted_swap[active_extruder] = rs; // Use 'S' for swap, default to false
#endif
- retract(true
+ fwretract.retract(true
#if EXTRUDERS > 1
, rs
#endif
@@ -38,4 +46,6 @@ void gcode_G10() {
/**
* G11 - Recover filament according to settings of M208
*/
-void gcode_G11() { retract(false); }
+void GcodeSuite::G11() { fwretract.retract(false); }
+
+#endif // FWRETRACT
diff --git a/Marlin/src/gcode/feature/fwretract/M207.h b/Marlin/src/gcode/feature/fwretract/M207.cpp
similarity index 66%
rename from Marlin/src/gcode/feature/fwretract/M207.h
rename to Marlin/src/gcode/feature/fwretract/M207.cpp
index 07ca82e33..07a043faf 100644
--- a/Marlin/src/gcode/feature/fwretract/M207.h
+++ b/Marlin/src/gcode/feature/fwretract/M207.cpp
@@ -20,6 +20,13 @@
*
*/
+#include "../../../inc/MarlinConfig.h"
+
+#if ENABLED(FWRETRACT)
+
+#include "../../../feature/fwretract.h"
+#include "../../gcode.h"
+
/**
* M207: Set firmware retraction values
*
@@ -28,9 +35,11 @@
* F[units/min] retract_feedrate_mm_s
* Z[units] retract_zlift
*/
-void gcode_M207() {
- if (parser.seen('S')) retract_length = parser.value_axis_units(E_AXIS);
- if (parser.seen('F')) retract_feedrate_mm_s = MMM_TO_MMS(parser.value_axis_units(E_AXIS));
- if (parser.seen('Z')) retract_zlift = parser.value_linear_units();
- if (parser.seen('W')) swap_retract_length = parser.value_axis_units(E_AXIS);
+void GcodeSuite::M207() {
+ if (parser.seen('S')) fwretract.retract_length = parser.value_axis_units(E_AXIS);
+ if (parser.seen('F')) fwretract.retract_feedrate_mm_s = MMM_TO_MMS(parser.value_axis_units(E_AXIS));
+ if (parser.seen('Z')) fwretract.retract_zlift = parser.value_linear_units();
+ if (parser.seen('W')) fwretract.swap_retract_length = parser.value_axis_units(E_AXIS);
}
+
+#endif // FWRETRACT
diff --git a/Marlin/src/gcode/feature/fwretract/M208.h b/Marlin/src/gcode/feature/fwretract/M208.cpp
similarity index 65%
rename from Marlin/src/gcode/feature/fwretract/M208.h
rename to Marlin/src/gcode/feature/fwretract/M208.cpp
index c5cabb714..85d234f41 100644
--- a/Marlin/src/gcode/feature/fwretract/M208.h
+++ b/Marlin/src/gcode/feature/fwretract/M208.cpp
@@ -20,6 +20,13 @@
*
*/
+#include "../../../inc/MarlinConfig.h"
+
+#if ENABLED(FWRETRACT)
+
+#include "../../../feature/fwretract.h"
+#include "../../gcode.h"
+
/**
* M208: Set firmware un-retraction values
*
@@ -28,9 +35,11 @@
* F[units/min] retract_recover_feedrate_mm_s
* R[units/min] swap_retract_recover_feedrate_mm_s
*/
-void gcode_M208() {
- if (parser.seen('S')) retract_recover_length = parser.value_axis_units(E_AXIS);
- if (parser.seen('F')) retract_recover_feedrate_mm_s = MMM_TO_MMS(parser.value_axis_units(E_AXIS));
- if (parser.seen('R')) swap_retract_recover_feedrate_mm_s = MMM_TO_MMS(parser.value_axis_units(E_AXIS));
- if (parser.seen('W')) swap_retract_recover_length = parser.value_axis_units(E_AXIS);
+void GcodeSuite::M208() {
+ if (parser.seen('S')) fwretract.retract_recover_length = parser.value_axis_units(E_AXIS);
+ if (parser.seen('F')) fwretract.retract_recover_feedrate_mm_s = MMM_TO_MMS(parser.value_axis_units(E_AXIS));
+ if (parser.seen('R')) fwretract.swap_retract_recover_feedrate_mm_s = MMM_TO_MMS(parser.value_axis_units(E_AXIS));
+ if (parser.seen('W')) fwretract.swap_retract_recover_length = parser.value_axis_units(E_AXIS);
}
+
+#endif // FWRETRACT
diff --git a/Marlin/src/gcode/feature/fwretract/M209.h b/Marlin/src/gcode/feature/fwretract/M209.cpp
similarity index 77%
rename from Marlin/src/gcode/feature/fwretract/M209.h
rename to Marlin/src/gcode/feature/fwretract/M209.cpp
index 9e92d100c..7d5a334b8 100644
--- a/Marlin/src/gcode/feature/fwretract/M209.h
+++ b/Marlin/src/gcode/feature/fwretract/M209.cpp
@@ -20,16 +20,25 @@
*
*/
+#include "../../../inc/MarlinConfig.h"
+
+#if ENABLED(FWRETRACT)
+
+#include "../../../feature/fwretract.h"
+#include "../../gcode.h"
+
/**
* M209: Enable automatic retract (M209 S1)
* For slicers that don't support G10/11, reversed extrude-only
* moves will be classified as retraction.
*/
-void gcode_M209() {
+void GcodeSuite::M209() {
if (MIN_AUTORETRACT <= MAX_AUTORETRACT) {
if (parser.seen('S')) {
- autoretract_enabled = parser.value_bool();
- for (uint8_t i = 0; i < EXTRUDERS; i++) retracted[i] = false;
+ fwretract.autoretract_enabled = parser.value_bool();
+ for (uint8_t i = 0; i < EXTRUDERS; i++) fwretract.retracted[i] = false;
}
}
}
+
+#endif // FWRETRACT
diff --git a/Marlin/src/gcode/gcode.cpp b/Marlin/src/gcode/gcode.cpp
index 367725fe5..7fd4f0df3 100644
--- a/Marlin/src/gcode/gcode.cpp
+++ b/Marlin/src/gcode/gcode.cpp
@@ -754,16 +754,10 @@ void GcodeSuite::process_next_command() {
#endif
#if ENABLED(FWRETRACT)
- case 207: // M207: Set Retract Length, Feedrate, and Z lift
- M207();
- break;
- case 208: // M208: Set Recover (unretract) Additional Length and Feedrate
- M208();
- break;
- case 209: // M209: Turn Automatic Retract Detection on/off
- if (MIN_AUTORETRACT <= MAX_AUTORETRACT) M209();
- break;
- #endif // FWRETRACT
+ case 207: M207(); break; // M207: Set Retract Length, Feedrate, and Z lift
+ case 208: M208(); break; // M208: Set Recover (unretract) Additional Length and Feedrate
+ case 209: if (MIN_AUTORETRACT <= MAX_AUTORETRACT) M209(); break; // M209: Turn Automatic Retract Detection on/off
+ #endif
case 211: // M211: Enable, Disable, and/or Report software endstops
gcode_M211();
diff --git a/Marlin/src/gcode/motion/G0_G1.cpp b/Marlin/src/gcode/motion/G0_G1.cpp
index 4ec0221e4..d2fe3f98b 100644
--- a/Marlin/src/gcode/motion/G0_G1.cpp
+++ b/Marlin/src/gcode/motion/G0_G1.cpp
@@ -25,6 +25,10 @@
#include "../../Marlin.h"
+#if ENABLED(FWRETRACT)
+ #include "../../feature/fwretract.h"
+#endif
+
#include "../../sd/cardreader.h"
extern float destination[XYZE];
@@ -41,18 +45,20 @@ void GcodeSuite::G0_G1(
get_destination_from_command(); // For X Y Z E F
#if ENABLED(FWRETRACT)
+
if (MIN_AUTORETRACT <= MAX_AUTORETRACT) {
// When M209 Autoretract is enabled, convert E-only moves to firmware retract/recover moves
- if (autoretract_enabled && parser.seen('E') && !(parser.seen('X') || parser.seen('Y') || parser.seen('Z'))) {
+ if (fwretract.autoretract_enabled && parser.seen('E') && !(parser.seen('X') || parser.seen('Y') || parser.seen('Z'))) {
const float echange = destination[E_AXIS] - current_position[E_AXIS];
// Is this a retract or recover move?
- if (WITHIN(FABS(echange), MIN_AUTORETRACT, MAX_AUTORETRACT) && retracted[active_extruder] == (echange > 0.0)) {
+ if (WITHIN(FABS(echange), MIN_AUTORETRACT, MAX_AUTORETRACT) && fwretract.retracted[active_extruder] == (echange > 0.0)) {
current_position[E_AXIS] = destination[E_AXIS]; // Hide a G1-based retract/recover from calculations
sync_plan_position_e(); // AND from the planner
- return retract(echange < 0.0); // Firmware-based retract/recover (double-retract ignored)
+ return fwretract.retract(echange < 0.0); // Firmware-based retract/recover (double-retract ignored)
}
}
}
+
#endif // FWRETRACT
#if IS_SCARA
diff --git a/Marlin/src/lcd/ultralcd.cpp b/Marlin/src/lcd/ultralcd.cpp
index 34012b4ba..72a2288c6 100644
--- a/Marlin/src/lcd/ultralcd.cpp
+++ b/Marlin/src/lcd/ultralcd.cpp
@@ -164,6 +164,7 @@ uint16_t max_display_update_time = 0;
#endif
#if ENABLED(FWRETRACT)
+ #include "../feature/fwretract.h"
void lcd_control_retract_menu();
#endif
@@ -3477,18 +3478,18 @@ void kill_screen(const char* lcd_msg) {
void lcd_control_retract_menu() {
START_MENU();
MENU_BACK(MSG_CONTROL);
- MENU_ITEM_EDIT(bool, MSG_AUTORETRACT, &autoretract_enabled);
- MENU_ITEM_EDIT(float52, MSG_CONTROL_RETRACT, &retract_length, 0, 100);
+ MENU_ITEM_EDIT(bool, MSG_AUTORETRACT, &fwretract.autoretract_enabled);
+ MENU_ITEM_EDIT(float52, MSG_CONTROL_RETRACT, &fwretract.retract_length, 0, 100);
#if EXTRUDERS > 1
- MENU_ITEM_EDIT(float52, MSG_CONTROL_RETRACT_SWAP, &swap_retract_length, 0, 100);
+ MENU_ITEM_EDIT(float52, MSG_CONTROL_RETRACT_SWAP, &fwretract.swap_retract_length, 0, 100);
#endif
- MENU_ITEM_EDIT(float3, MSG_CONTROL_RETRACTF, &retract_feedrate_mm_s, 1, 999);
- MENU_ITEM_EDIT(float52, MSG_CONTROL_RETRACT_ZLIFT, &retract_zlift, 0, 999);
- MENU_ITEM_EDIT(float52, MSG_CONTROL_RETRACT_RECOVER, &retract_recover_length, -100, 100);
+ MENU_ITEM_EDIT(float3, MSG_CONTROL_RETRACTF, &fwretract.retract_feedrate_mm_s, 1, 999);
+ MENU_ITEM_EDIT(float52, MSG_CONTROL_RETRACT_ZLIFT, &fwretract.retract_zlift, 0, 999);
+ MENU_ITEM_EDIT(float52, MSG_CONTROL_RETRACT_RECOVER, &fwretract.retract_recover_length, -100, 100);
#if EXTRUDERS > 1
- MENU_ITEM_EDIT(float52, MSG_CONTROL_RETRACT_RECOVER_SWAP, &swap_retract_recover_length, -100, 100);
+ MENU_ITEM_EDIT(float52, MSG_CONTROL_RETRACT_RECOVER_SWAP, &fwretract.swap_retract_recover_length, -100, 100);
#endif
- MENU_ITEM_EDIT(float3, MSG_CONTROL_RETRACT_RECOVERF, &retract_recover_feedrate_mm_s, 1, 999);
+ MENU_ITEM_EDIT(float3, MSG_CONTROL_RETRACT_RECOVERF, &fwretract.retract_recover_feedrate_mm_s, 1, 999);
END_MENU();
}
diff --git a/Marlin/src/module/configuration_store.cpp b/Marlin/src/module/configuration_store.cpp
index 362f629de..898c496cd 100644
--- a/Marlin/src/module/configuration_store.cpp
+++ b/Marlin/src/module/configuration_store.cpp
@@ -205,6 +205,10 @@ MarlinSettings settings;
extern void refresh_bed_level();
#endif
+#if ENABLED(FWRETRACT)
+ #include "../gcode/feature/fwretract/fwretract.h"
+#endif
+
/**
* Post-process after Retrieve or Reset
*/
@@ -492,24 +496,20 @@ void MarlinSettings::postprocess() {
#if DISABLED(FWRETRACT)
const bool autoretract_enabled = false;
- const float retract_length = 3,
- retract_feedrate_mm_s = 45,
- retract_zlift = 0,
- retract_recover_length = 0,
- retract_recover_feedrate_mm_s = 0,
- swap_retract_length = 13,
- swap_retract_recover_length = 0,
- swap_retract_recover_feedrate_mm_s = 8;
+ const float autoretract_defaults[] = { 3, 45, 0, 0, 0, 13, 0, 8 };
+ EEPROM_WRITE(autoretract_enabled);
+ EEPROM_WRITE(autoretract_defaults);
+ #else
+ EEPROM_WRITE(fwretract.autoretract_enabled);
+ EEPROM_WRITE(fwretract.retract_length);
+ EEPROM_WRITE(fwretract.retract_feedrate_mm_s);
+ EEPROM_WRITE(fwretract.retract_zlift);
+ EEPROM_WRITE(fwretract.retract_recover_length);
+ EEPROM_WRITE(fwretract.retract_recover_feedrate_mm_s);
+ EEPROM_WRITE(fwretract.swap_retract_length);
+ EEPROM_WRITE(fwretract.swap_retract_recover_length);
+ EEPROM_WRITE(fwretract.swap_retract_recover_feedrate_mm_s);
#endif
- EEPROM_WRITE(autoretract_enabled);
- EEPROM_WRITE(retract_length);
- EEPROM_WRITE(retract_feedrate_mm_s);
- EEPROM_WRITE(retract_zlift);
- EEPROM_WRITE(retract_recover_length);
- EEPROM_WRITE(retract_recover_feedrate_mm_s);
- EEPROM_WRITE(swap_retract_length);
- EEPROM_WRITE(swap_retract_recover_length);
- EEPROM_WRITE(swap_retract_recover_feedrate_mm_s);
EEPROM_WRITE(volumetric_enabled);
@@ -883,15 +883,15 @@ void MarlinSettings::postprocess() {
EEPROM_READ(lcd_contrast);
#if ENABLED(FWRETRACT)
- EEPROM_READ(autoretract_enabled);
- EEPROM_READ(retract_length);
- EEPROM_READ(retract_feedrate_mm_s);
- EEPROM_READ(retract_zlift);
- EEPROM_READ(retract_recover_length);
- EEPROM_READ(retract_recover_feedrate_mm_s);
- EEPROM_READ(swap_retract_length);
- EEPROM_READ(swap_retract_recover_length);
- EEPROM_READ(swap_retract_recover_feedrate_mm_s);
+ EEPROM_READ(fwretract.autoretract_enabled);
+ EEPROM_READ(fwretract.retract_length);
+ EEPROM_READ(fwretract.retract_feedrate_mm_s);
+ EEPROM_READ(fwretract.retract_zlift);
+ EEPROM_READ(fwretract.retract_recover_length);
+ EEPROM_READ(fwretract.retract_recover_feedrate_mm_s);
+ EEPROM_READ(fwretract.swap_retract_length);
+ EEPROM_READ(fwretract.swap_retract_recover_length);
+ EEPROM_READ(fwretract.swap_retract_recover_feedrate_mm_s);
#else
EEPROM_READ(dummyb);
for (uint8_t q=8; q--;) EEPROM_READ(dummy);
@@ -1256,16 +1256,8 @@ void MarlinSettings::reset() {
#endif
#if ENABLED(FWRETRACT)
- autoretract_enabled = false;
- retract_length = RETRACT_LENGTH;
- retract_feedrate_mm_s = RETRACT_FEEDRATE;
- retract_zlift = RETRACT_ZLIFT;
- retract_recover_length = RETRACT_RECOVER_LENGTH;
- retract_recover_feedrate_mm_s = RETRACT_RECOVER_FEEDRATE;
- swap_retract_length = RETRACT_LENGTH_SWAP;
- swap_retract_recover_length = RETRACT_RECOVER_LENGTH_SWAP;
- swap_retract_recover_feedrate_mm_s = RETRACT_RECOVER_FEEDRATE_SWAP;
- #endif // FWRETRACT
+ fwretract.reset();
+ #endif
volumetric_enabled =
#if ENABLED(VOLUMETRIC_DEFAULT_ON)
@@ -1716,26 +1708,26 @@ void MarlinSettings::reset() {
SERIAL_ECHOLNPGM("Retract: S F Z");
}
CONFIG_ECHO_START;
- SERIAL_ECHOPAIR(" M207 S", LINEAR_UNIT(retract_length));
- SERIAL_ECHOPAIR(" W", LINEAR_UNIT(swap_retract_length));
- SERIAL_ECHOPAIR(" F", MMS_TO_MMM(LINEAR_UNIT(retract_feedrate_mm_s)));
- SERIAL_ECHOLNPAIR(" Z", LINEAR_UNIT(retract_zlift));
+ SERIAL_ECHOPAIR(" M207 S", LINEAR_UNIT(fwretract.retract_length));
+ SERIAL_ECHOPAIR(" W", LINEAR_UNIT(fwretract.swap_retract_length));
+ SERIAL_ECHOPAIR(" F", MMS_TO_MMM(LINEAR_UNIT(fwretract.retract_feedrate_mm_s)));
+ SERIAL_ECHOLNPAIR(" Z", LINEAR_UNIT(fwretract.retract_zlift));
if (!forReplay) {
CONFIG_ECHO_START;
SERIAL_ECHOLNPGM("Recover: S F");
}
CONFIG_ECHO_START;
- SERIAL_ECHOPAIR(" M208 S", LINEAR_UNIT(retract_recover_length));
- SERIAL_ECHOPAIR(" W", LINEAR_UNIT(swap_retract_recover_length));
- SERIAL_ECHOLNPAIR(" F", MMS_TO_MMM(LINEAR_UNIT(retract_recover_feedrate_mm_s)));
+ SERIAL_ECHOPAIR(" M208 S", LINEAR_UNIT(fwretract.retract_recover_length));
+ SERIAL_ECHOPAIR(" W", LINEAR_UNIT(fwretract.swap_retract_recover_length));
+ SERIAL_ECHOLNPAIR(" F", MMS_TO_MMM(LINEAR_UNIT(fwretract.retract_recover_feedrate_mm_s)));
if (!forReplay) {
CONFIG_ECHO_START;
SERIAL_ECHOLNPGM("Auto-Retract: S=0 to disable, 1 to interpret E-only moves as retract/recover");
}
CONFIG_ECHO_START;
- SERIAL_ECHOLNPAIR(" M209 S", autoretract_enabled ? 1 : 0);
+ SERIAL_ECHOLNPAIR(" M209 S", fwretract.autoretract_enabled ? 1 : 0);
#endif // FWRETRACT