aboutsummaryrefslogtreecommitdiff
path: root/Marlin/src/gcode/control
diff options
context:
space:
mode:
authorGeorgiy Bondarenko <69736697+nehilo@users.noreply.github.com>2021-03-04 20:54:23 +0300
committerGeorgiy Bondarenko <69736697+nehilo@users.noreply.github.com>2021-03-04 20:54:23 +0300
commite8701195e66f2d27ffe17fb514eae8173795aaf7 (patch)
tree9f519c4abf6556b9ae7190a6210d87ead1dfadde /Marlin/src/gcode/control
downloadkp3s-lgvl-e8701195e66f2d27ffe17fb514eae8173795aaf7.tar.xz
kp3s-lgvl-e8701195e66f2d27ffe17fb514eae8173795aaf7.zip
Initial commit
Diffstat (limited to 'Marlin/src/gcode/control')
-rw-r--r--Marlin/src/gcode/control/M108_M112_M410.cpp56
-rw-r--r--Marlin/src/gcode/control/M111.cpp77
-rw-r--r--Marlin/src/gcode/control/M120_M121.cpp34
-rw-r--r--Marlin/src/gcode/control/M17_M18_M84.cpp69
-rw-r--r--Marlin/src/gcode/control/M211.cpp46
-rw-r--r--Marlin/src/gcode/control/M226.cpp60
-rw-r--r--Marlin/src/gcode/control/M280.cpp55
-rw-r--r--Marlin/src/gcode/control/M3-M5.cpp140
-rw-r--r--Marlin/src/gcode/control/M350_M351.cpp64
-rw-r--r--Marlin/src/gcode/control/M380_M381.cpp56
-rw-r--r--Marlin/src/gcode/control/M400.cpp33
-rw-r--r--Marlin/src/gcode/control/M42.cpp107
-rw-r--r--Marlin/src/gcode/control/M605.cpp185
-rw-r--r--Marlin/src/gcode/control/M7-M9.cpp63
-rw-r--r--Marlin/src/gcode/control/M80_M81.cpp113
-rw-r--r--Marlin/src/gcode/control/M85.cpp35
-rw-r--r--Marlin/src/gcode/control/M993_M994.cpp88
-rw-r--r--Marlin/src/gcode/control/M997.cpp36
-rw-r--r--Marlin/src/gcode/control/M999.cpp45
-rw-r--r--Marlin/src/gcode/control/T.cpp70
20 files changed, 1432 insertions, 0 deletions
diff --git a/Marlin/src/gcode/control/M108_M112_M410.cpp b/Marlin/src/gcode/control/M108_M112_M410.cpp
new file mode 100644
index 0000000..309c806
--- /dev/null
+++ b/Marlin/src/gcode/control/M108_M112_M410.cpp
@@ -0,0 +1,56 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "../../inc/MarlinConfig.h"
+
+#if DISABLED(EMERGENCY_PARSER)
+
+#include "../gcode.h"
+#include "../../MarlinCore.h" // for wait_for_heatup, kill, M112_KILL_STR
+#include "../../module/motion.h" // for quickstop_stepper
+
+/**
+ * M108: Stop the waiting for heaters in M109, M190, M303. Does not affect the target temperature.
+ */
+void GcodeSuite::M108() {
+ TERN_(HAS_RESUME_CONTINUE, wait_for_user = false);
+ wait_for_heatup = false;
+}
+
+/**
+ * M112: Full Shutdown
+ */
+void GcodeSuite::M112() {
+ kill(M112_KILL_STR, nullptr, true);
+}
+
+/**
+ * M410: Quickstop - Abort all planned moves
+ *
+ * This will stop the carriages mid-move, so most likely they
+ * will be out of sync with the stepper position after this.
+ */
+void GcodeSuite::M410() {
+ quickstop_stepper();
+}
+
+#endif // !EMERGENCY_PARSER
diff --git a/Marlin/src/gcode/control/M111.cpp b/Marlin/src/gcode/control/M111.cpp
new file mode 100644
index 0000000..38cb065
--- /dev/null
+++ b/Marlin/src/gcode/control/M111.cpp
@@ -0,0 +1,77 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "../gcode.h"
+
+/**
+ * M111: Set the debug level
+ */
+void GcodeSuite::M111() {
+ if (parser.seen('S')) marlin_debug_flags = parser.byteval('S');
+
+ static PGMSTR(str_debug_1, STR_DEBUG_ECHO);
+ static PGMSTR(str_debug_2, STR_DEBUG_INFO);
+ static PGMSTR(str_debug_4, STR_DEBUG_ERRORS);
+ static PGMSTR(str_debug_8, STR_DEBUG_DRYRUN);
+ static PGMSTR(str_debug_16, STR_DEBUG_COMMUNICATION);
+ #if ENABLED(DEBUG_LEVELING_FEATURE)
+ static PGMSTR(str_debug_lvl, STR_DEBUG_LEVELING);
+ #endif
+
+ static PGM_P const debug_strings[] PROGMEM = {
+ str_debug_1, str_debug_2, str_debug_4, str_debug_8, str_debug_16,
+ TERN_(DEBUG_LEVELING_FEATURE, str_debug_lvl)
+ };
+
+ SERIAL_ECHO_START();
+ SERIAL_ECHOPGM(STR_DEBUG_PREFIX);
+ if (marlin_debug_flags) {
+ uint8_t comma = 0;
+ LOOP_L_N(i, COUNT(debug_strings)) {
+ if (TEST(marlin_debug_flags, i)) {
+ if (comma++) SERIAL_CHAR(',');
+ serialprintPGM((char*)pgm_read_ptr(&debug_strings[i]));
+ }
+ }
+ }
+ else {
+ SERIAL_ECHOPGM(STR_DEBUG_OFF);
+ #if !defined(__AVR__) || !defined(USBCON)
+ #if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
+ SERIAL_ECHOPAIR("\nBuffer Overruns: ", MYSERIAL0.buffer_overruns());
+ #endif
+
+ #if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
+ SERIAL_ECHOPAIR("\nFraming Errors: ", MYSERIAL0.framing_errors());
+ #endif
+
+ #if ENABLED(SERIAL_STATS_DROPPED_RX)
+ SERIAL_ECHOPAIR("\nDropped bytes: ", MYSERIAL0.dropped());
+ #endif
+
+ #if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
+ SERIAL_ECHOPAIR("\nMax RX Queue Size: ", MYSERIAL0.rxMaxEnqueued());
+ #endif
+ #endif // !__AVR__ || !USBCON
+ }
+ SERIAL_EOL();
+}
diff --git a/Marlin/src/gcode/control/M120_M121.cpp b/Marlin/src/gcode/control/M120_M121.cpp
new file mode 100644
index 0000000..570f2e9
--- /dev/null
+++ b/Marlin/src/gcode/control/M120_M121.cpp
@@ -0,0 +1,34 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "../gcode.h"
+#include "../../module/endstops.h"
+
+/**
+ * M120: Enable endstops and set non-homing endstop state to "enabled"
+ */
+void GcodeSuite::M120() { endstops.enable_globally(true); }
+
+/**
+ * M121: Disable endstops and set non-homing endstop state to "disabled"
+ */
+void GcodeSuite::M121() { endstops.enable_globally(false); }
diff --git a/Marlin/src/gcode/control/M17_M18_M84.cpp b/Marlin/src/gcode/control/M17_M18_M84.cpp
new file mode 100644
index 0000000..b35b465
--- /dev/null
+++ b/Marlin/src/gcode/control/M17_M18_M84.cpp
@@ -0,0 +1,69 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "../gcode.h"
+#include "../../MarlinCore.h" // for stepper_inactive_time, disable_e_steppers
+#include "../../lcd/marlinui.h"
+#include "../../module/stepper.h"
+
+#if ENABLED(AUTO_BED_LEVELING_UBL)
+ #include "../../feature/bedlevel/bedlevel.h"
+#endif
+
+/**
+ * M17: Enable stepper motors
+ */
+void GcodeSuite::M17() {
+ if (parser.seen("XYZE")) {
+ if (parser.seen('X')) ENABLE_AXIS_X();
+ if (parser.seen('Y')) ENABLE_AXIS_Y();
+ if (parser.seen('Z')) ENABLE_AXIS_Z();
+ if (TERN0(HAS_E_STEPPER_ENABLE, parser.seen('E'))) enable_e_steppers();
+ }
+ else {
+ LCD_MESSAGEPGM(MSG_NO_MOVE);
+ enable_all_steppers();
+ }
+}
+
+/**
+ * M18, M84: Disable stepper motors
+ */
+void GcodeSuite::M18_M84() {
+ if (parser.seenval('S')) {
+ reset_stepper_timeout();
+ stepper_inactive_time = parser.value_millis_from_seconds();
+ }
+ else {
+ if (parser.seen("XYZE")) {
+ planner.synchronize();
+ if (parser.seen('X')) DISABLE_AXIS_X();
+ if (parser.seen('Y')) DISABLE_AXIS_Y();
+ if (parser.seen('Z')) DISABLE_AXIS_Z();
+ if (TERN0(HAS_E_STEPPER_ENABLE, parser.seen('E'))) disable_e_steppers();
+ }
+ else
+ planner.finish_and_disable();
+
+ TERN_(AUTO_BED_LEVELING_UBL, ubl.steppers_were_disabled());
+ }
+}
diff --git a/Marlin/src/gcode/control/M211.cpp b/Marlin/src/gcode/control/M211.cpp
new file mode 100644
index 0000000..2049f1e
--- /dev/null
+++ b/Marlin/src/gcode/control/M211.cpp
@@ -0,0 +1,46 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "../../inc/MarlinConfigPre.h"
+
+#if HAS_SOFTWARE_ENDSTOPS
+
+#include "../gcode.h"
+#include "../../module/motion.h"
+
+/**
+ * M211: Enable, Disable, and/or Report software endstops
+ *
+ * Usage: M211 S1 to enable, M211 S0 to disable, M211 alone for report
+ */
+void GcodeSuite::M211() {
+ const xyz_pos_t l_soft_min = soft_endstop.min.asLogical(),
+ l_soft_max = soft_endstop.max.asLogical();
+ SERIAL_ECHO_START();
+ SERIAL_ECHOPGM(STR_SOFT_ENDSTOPS);
+ if (parser.seen('S')) soft_endstop._enabled = parser.value_bool();
+ serialprint_onoff(soft_endstop._enabled);
+ print_xyz(l_soft_min, PSTR(STR_SOFT_MIN), PSTR(" "));
+ print_xyz(l_soft_max, PSTR(STR_SOFT_MAX));
+}
+
+#endif
diff --git a/Marlin/src/gcode/control/M226.cpp b/Marlin/src/gcode/control/M226.cpp
new file mode 100644
index 0000000..63f022e
--- /dev/null
+++ b/Marlin/src/gcode/control/M226.cpp
@@ -0,0 +1,60 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "../../inc/MarlinConfig.h"
+
+#if ENABLED(DIRECT_PIN_CONTROL)
+
+#include "../gcode.h"
+#include "../../MarlinCore.h" // for pin_is_protected and idle()
+#include "../../module/stepper.h"
+
+void protected_pin_err();
+
+/**
+ * M226: Wait until the specified pin reaches the state required (M226 P<pin> S<state>)
+ */
+void GcodeSuite::M226() {
+ if (parser.seen('P')) {
+ const int pin_number = PARSED_PIN_INDEX('P', 0),
+ pin_state = parser.intval('S', -1); // required pin state - default is inverted
+ const pin_t pin = GET_PIN_MAP_PIN(pin_number);
+
+ if (WITHIN(pin_state, -1, 1) && pin > -1) {
+ if (pin_is_protected(pin))
+ protected_pin_err();
+ else {
+ int target = LOW;
+ planner.synchronize();
+ pinMode(pin, INPUT);
+ switch (pin_state) {
+ case 1: target = HIGH; break;
+ case 0: target = LOW; break;
+ case -1: target = !extDigitalRead(pin); break;
+ }
+ while (int(extDigitalRead(pin)) != target) idle();
+ }
+ } // pin_state -1 0 1 && pin > -1
+ } // parser.seen('P')
+}
+
+#endif // DIRECT_PIN_CONTROL
diff --git a/Marlin/src/gcode/control/M280.cpp b/Marlin/src/gcode/control/M280.cpp
new file mode 100644
index 0000000..6ccbb7b
--- /dev/null
+++ b/Marlin/src/gcode/control/M280.cpp
@@ -0,0 +1,55 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "../../inc/MarlinConfig.h"
+
+#if HAS_SERVOS
+
+#include "../gcode.h"
+#include "../../module/servo.h"
+
+/**
+ * M280: Get or set servo position. P<index> [S<angle>]
+ */
+void GcodeSuite::M280() {
+ if (!parser.seen('P')) return;
+ const int servo_index = parser.value_int();
+ if (WITHIN(servo_index, 0, NUM_SERVOS - 1)) {
+ if (parser.seen('S')) {
+ const int a = parser.value_int();
+ if (a == -1)
+ servo[servo_index].detach();
+ else
+ MOVE_SERVO(servo_index, a);
+ }
+ else {
+ SERIAL_ECHO_START();
+ SERIAL_ECHOLNPAIR(" Servo ", servo_index, ": ", servo[servo_index].read());
+ }
+ }
+ else {
+ SERIAL_ERROR_START();
+ SERIAL_ECHOLNPAIR("Servo ", servo_index, " out of range");
+ }
+}
+
+#endif // HAS_SERVOS
diff --git a/Marlin/src/gcode/control/M3-M5.cpp b/Marlin/src/gcode/control/M3-M5.cpp
new file mode 100644
index 0000000..711bb7e
--- /dev/null
+++ b/Marlin/src/gcode/control/M3-M5.cpp
@@ -0,0 +1,140 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "../../inc/MarlinConfig.h"
+
+#if HAS_CUTTER
+
+#include "../gcode.h"
+#include "../../feature/spindle_laser.h"
+#include "../../module/stepper.h"
+
+/**
+ * Laser:
+ * M3 - Laser ON/Power (Ramped power)
+ * M4 - Laser ON/Power (Continuous power)
+ *
+ * Spindle:
+ * M3 - Spindle ON (Clockwise)
+ * M4 - Spindle ON (Counter-clockwise)
+ *
+ * Parameters:
+ * S<power> - Set power. S0 will turn the spindle/laser off, except in relative mode.
+ * O<ocr> - Set power and OCR (oscillator count register)
+ *
+ * If no PWM pin is defined then M3/M4 just turns it on.
+ *
+ * At least 12.8KHz (50Hz * 256) is needed for Spindle PWM.
+ * Hardware PWM is required on AVR. ISRs are too slow.
+ *
+ * NOTE: WGM for timers 3, 4, and 5 must be either Mode 1 or Mode 5.
+ * No other settings give a PWM signal that goes from 0 to 5 volts.
+ *
+ * The system automatically sets WGM to Mode 1, so no special
+ * initialization is needed.
+ *
+ * WGM bits for timer 2 are automatically set by the system to
+ * Mode 1. This produces an acceptable 0 to 5 volt signal.
+ * No special initialization is needed.
+ *
+ * NOTE: A minimum PWM frequency of 50 Hz is needed. All prescaler
+ * factors for timers 2, 3, 4, and 5 are acceptable.
+ *
+ * SPINDLE_LASER_ENA_PIN needs an external pullup or it may power on
+ * the spindle/laser during power-up or when connecting to the host
+ * (usually goes through a reset which sets all I/O pins to tri-state)
+ *
+ * PWM duty cycle goes from 0 (off) to 255 (always on).
+ */
+void GcodeSuite::M3_M4(const bool is_M4) {
+ auto get_s_power = [] {
+ if (parser.seenval('S')) {
+ const float spwr = parser.value_float();
+ #if ENABLED(SPINDLE_SERVO)
+ cutter.unitPower = spwr;
+ #else
+ cutter.unitPower = TERN(SPINDLE_LASER_PWM,
+ cutter.power_to_range(cutter_power_t(round(spwr))),
+ spwr > 0 ? 255 : 0);
+ #endif
+ }
+ else
+ cutter.unitPower = cutter.cpwr_to_upwr(SPEED_POWER_STARTUP);
+ return cutter.unitPower;
+ };
+
+ #if ENABLED(LASER_POWER_INLINE)
+ if (parser.seen('I') == DISABLED(LASER_POWER_INLINE_INVERT)) {
+ // Laser power in inline mode
+ cutter.inline_direction(is_M4); // Should always be unused
+ #if ENABLED(SPINDLE_LASER_PWM)
+ if (parser.seen('O')) {
+ cutter.unitPower = cutter.power_to_range(parser.value_byte(), 0);
+ cutter.inline_ocr_power(cutter.unitPower); // The OCR is a value from 0 to 255 (uint8_t)
+ }
+ else
+ cutter.inline_power(cutter.upower_to_ocr(get_s_power()));
+ #else
+ cutter.set_inline_enabled(true);
+ #endif
+ return;
+ }
+ // Non-inline, standard case
+ cutter.inline_disable(); // Prevent future blocks re-setting the power
+ #endif
+
+ planner.synchronize(); // Wait for previous movement commands (G0/G0/G2/G3) to complete before changing power
+ cutter.set_reverse(is_M4);
+
+ #if ENABLED(SPINDLE_LASER_PWM)
+ if (parser.seenval('O')) {
+ cutter.unitPower = cutter.power_to_range(parser.value_byte(), 0);
+ cutter.set_ocr_power(cutter.unitPower); // The OCR is a value from 0 to 255 (uint8_t)
+ }
+ else
+ cutter.set_power(cutter.upower_to_ocr(get_s_power()));
+ #elif ENABLED(SPINDLE_SERVO)
+ cutter.set_power(get_s_power());
+ #else
+ cutter.set_enabled(true);
+ #endif
+ cutter.menuPower = cutter.unitPower;
+}
+
+/**
+ * M5 - Cutter OFF (when moves are complete)
+ */
+void GcodeSuite::M5() {
+ #if ENABLED(LASER_POWER_INLINE)
+ if (parser.seen('I') == DISABLED(LASER_POWER_INLINE_INVERT)) {
+ cutter.set_inline_enabled(false); // Laser power in inline mode
+ return;
+ }
+ // Non-inline, standard case
+ cutter.inline_disable(); // Prevent future blocks re-setting the power
+ #endif
+ planner.synchronize();
+ cutter.set_enabled(false);
+ cutter.menuPower = cutter.unitPower;
+}
+
+#endif // HAS_CUTTER
diff --git a/Marlin/src/gcode/control/M350_M351.cpp b/Marlin/src/gcode/control/M350_M351.cpp
new file mode 100644
index 0000000..463bd2a
--- /dev/null
+++ b/Marlin/src/gcode/control/M350_M351.cpp
@@ -0,0 +1,64 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "../../inc/MarlinConfig.h"
+
+#if HAS_MICROSTEPS
+
+#include "../gcode.h"
+#include "../../module/stepper.h"
+
+/**
+ * M350: Set axis microstepping modes. S sets mode for all drivers.
+ *
+ * Warning: Steps-per-unit remains unchanged.
+ */
+void GcodeSuite::M350() {
+ if (parser.seen('S')) LOOP_LE_N(i, 4) stepper.microstep_mode(i, parser.value_byte());
+ LOOP_XYZE(i) if (parser.seen(axis_codes[i])) stepper.microstep_mode(i, parser.value_byte());
+ if (parser.seen('B')) stepper.microstep_mode(4, parser.value_byte());
+ stepper.microstep_readings();
+}
+
+/**
+ * M351: Toggle MS1 MS2 pins directly with axis codes X Y Z E B
+ * S# determines MS1, MS2 or MS3, X# sets the pin high/low.
+ */
+void GcodeSuite::M351() {
+ if (parser.seenval('S')) switch (parser.value_byte()) {
+ case 1:
+ LOOP_XYZE(i) if (parser.seenval(axis_codes[i])) stepper.microstep_ms(i, parser.value_byte(), -1, -1);
+ if (parser.seenval('B')) stepper.microstep_ms(4, parser.value_byte(), -1, -1);
+ break;
+ case 2:
+ LOOP_XYZE(i) if (parser.seenval(axis_codes[i])) stepper.microstep_ms(i, -1, parser.value_byte(), -1);
+ if (parser.seenval('B')) stepper.microstep_ms(4, -1, parser.value_byte(), -1);
+ break;
+ case 3:
+ LOOP_XYZE(i) if (parser.seenval(axis_codes[i])) stepper.microstep_ms(i, -1, -1, parser.value_byte());
+ if (parser.seenval('B')) stepper.microstep_ms(4, -1, -1, parser.value_byte());
+ break;
+ }
+ stepper.microstep_readings();
+}
+
+#endif // HAS_MICROSTEPS
diff --git a/Marlin/src/gcode/control/M380_M381.cpp b/Marlin/src/gcode/control/M380_M381.cpp
new file mode 100644
index 0000000..3f5b252
--- /dev/null
+++ b/Marlin/src/gcode/control/M380_M381.cpp
@@ -0,0 +1,56 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "../../inc/MarlinConfig.h"
+
+#if EITHER(EXT_SOLENOID, MANUAL_SOLENOID_CONTROL)
+
+#include "../gcode.h"
+#include "../../feature/solenoid.h"
+#include "../../module/motion.h"
+
+/**
+ * M380: Enable solenoid on the active extruder
+ *
+ * S<index> to specify a solenoid (Requires MANUAL_SOLENOID_CONTROL)
+ */
+void GcodeSuite::M380() {
+ #if ENABLED(MANUAL_SOLENOID_CONTROL)
+ enable_solenoid(parser.intval('S', active_extruder));
+ #else
+ enable_solenoid_on_active_extruder();
+ #endif
+}
+
+/**
+ * M381: Disable all solenoids if EXT_SOLENOID
+ * Disable selected/active solenoid if MANUAL_SOLENOID_CONTROL
+ */
+void GcodeSuite::M381() {
+ #if ENABLED(MANUAL_SOLENOID_CONTROL)
+ disable_solenoid(parser.intval('S', active_extruder));
+ #else
+ disable_all_solenoids();
+ #endif
+}
+
+#endif // EXT_SOLENOID || MANUAL_SOLENOID_CONTROL
diff --git a/Marlin/src/gcode/control/M400.cpp b/Marlin/src/gcode/control/M400.cpp
new file mode 100644
index 0000000..9a5ad4e
--- /dev/null
+++ b/Marlin/src/gcode/control/M400.cpp
@@ -0,0 +1,33 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "../gcode.h"
+#include "../../module/stepper.h"
+
+/**
+ * M400: Finish all moves
+ */
+void GcodeSuite::M400() {
+
+ planner.synchronize();
+
+}
diff --git a/Marlin/src/gcode/control/M42.cpp b/Marlin/src/gcode/control/M42.cpp
new file mode 100644
index 0000000..6ef8455
--- /dev/null
+++ b/Marlin/src/gcode/control/M42.cpp
@@ -0,0 +1,107 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "../../inc/MarlinConfig.h"
+
+#if ENABLED(DIRECT_PIN_CONTROL)
+
+#include "../gcode.h"
+#include "../../MarlinCore.h" // for pin_is_protected
+
+#if HAS_FAN
+ #include "../../module/temperature.h"
+#endif
+
+void protected_pin_err() {
+ SERIAL_ERROR_MSG(STR_ERR_PROTECTED_PIN);
+}
+
+/**
+ * M42: Change pin status via GCode
+ *
+ * P<pin> Pin number (LED if omitted)
+ * For LPC1768 specify pin P1_02 as M42 P102,
+ * P1_20 as M42 P120, etc.
+ *
+ * S<byte> Pin status from 0 - 255
+ * I Flag to ignore Marlin's pin protection
+ *
+ * M<mode> Pin mode: 0=INPUT 1=OUTPUT 2=INPUT_PULLUP 3=INPUT_PULLDOWN
+ */
+void GcodeSuite::M42() {
+ const int pin_index = PARSED_PIN_INDEX('P', GET_PIN_MAP_INDEX(LED_PIN));
+ if (pin_index < 0) return;
+
+ const pin_t pin = GET_PIN_MAP_PIN(pin_index);
+
+ if (!parser.boolval('I') && pin_is_protected(pin)) return protected_pin_err();
+
+ if (parser.seenval('M')) {
+ switch (parser.value_byte()) {
+ case 0: pinMode(pin, INPUT); break;
+ case 1: pinMode(pin, OUTPUT); break;
+ case 2: pinMode(pin, INPUT_PULLUP); break;
+ #ifdef INPUT_PULLDOWN
+ case 3: pinMode(pin, INPUT_PULLDOWN); break;
+ #endif
+ default: SERIAL_ECHOLNPGM("Invalid Pin Mode"); return;
+ }
+ }
+
+ if (!parser.seenval('S')) return;
+ const byte pin_status = parser.value_byte();
+
+ #if HAS_FAN
+ switch (pin) {
+ #if HAS_FAN0
+ case FAN0_PIN: thermalManager.fan_speed[0] = pin_status; return;
+ #endif
+ #if HAS_FAN1
+ case FAN1_PIN: thermalManager.fan_speed[1] = pin_status; return;
+ #endif
+ #if HAS_FAN2
+ case FAN2_PIN: thermalManager.fan_speed[2] = pin_status; return;
+ #endif
+ #if HAS_FAN3
+ case FAN3_PIN: thermalManager.fan_speed[3] = pin_status; return;
+ #endif
+ #if HAS_FAN4
+ case FAN4_PIN: thermalManager.fan_speed[4] = pin_status; return;
+ #endif
+ #if HAS_FAN5
+ case FAN5_PIN: thermalManager.fan_speed[5] = pin_status; return;
+ #endif
+ #if HAS_FAN6
+ case FAN6_PIN: thermalManager.fan_speed[6] = pin_status; return;
+ #endif
+ #if HAS_FAN7
+ case FAN7_PIN: thermalManager.fan_speed[7] = pin_status; return;
+ #endif
+ }
+ #endif
+
+ pinMode(pin, OUTPUT);
+ extDigitalWrite(pin, pin_status);
+ analogWrite(pin, pin_status);
+}
+
+#endif // DIRECT_PIN_CONTROL
diff --git a/Marlin/src/gcode/control/M605.cpp b/Marlin/src/gcode/control/M605.cpp
new file mode 100644
index 0000000..0d7a9f4
--- /dev/null
+++ b/Marlin/src/gcode/control/M605.cpp
@@ -0,0 +1,185 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "../../inc/MarlinConfig.h"
+
+#if HAS_DUPLICATION_MODE
+
+//#define DEBUG_DXC_MODE
+
+#include "../gcode.h"
+#include "../../module/motion.h"
+#include "../../module/stepper.h"
+#include "../../module/tool_change.h"
+#include "../../module/planner.h"
+
+#define DEBUG_OUT ENABLED(DEBUG_DXC_MODE)
+#include "../../core/debug_out.h"
+
+#if ENABLED(DUAL_X_CARRIAGE)
+
+ /**
+ * M605: Set dual x-carriage movement mode
+ *
+ * M605 S0 : (FULL_CONTROL) The slicer has full control over both X-carriages and can achieve optimal travel
+ * results as long as it supports dual X-carriages.
+ *
+ * M605 S1 : (AUTO_PARK) The firmware automatically parks and unparks the X-carriages on tool-change so that
+ * additional slicer support is not required.
+ *
+ * M605 S2 X R : (DUPLICATION) The firmware moves the second X-carriage and extruder in synchronization with
+ * the first X-carriage and extruder, to print 2 copies of the same object at the same time.
+ * Set the constant X-offset and temperature differential with M605 S2 X[offs] R[deg] and
+ * follow with "M605 S2" to initiate duplicated movement. For example, use "M605 S2 X100 R2" to
+ * make a copy 100mm to the right with E1 2° hotter than E0.
+ *
+ * M605 S3 : (MIRRORED) Formbot/Vivedino-inspired mirrored mode in which the second extruder duplicates
+ * the movement of the first except the second extruder is reversed in the X axis.
+ * The temperature differential and initial X offset must be set with "M605 S2 X[offs] R[deg]",
+ * then followed by "M605 S3" to initiate mirrored movement.
+ *
+ * M605 W : IDEX What? command.
+ *
+ * Note: the X axis should be homed after changing Dual X-carriage mode.
+ */
+ void GcodeSuite::M605() {
+ planner.synchronize();
+
+ if (parser.seen('S')) {
+ const DualXMode previous_mode = dual_x_carriage_mode;
+
+ dual_x_carriage_mode = (DualXMode)parser.value_byte();
+ idex_set_mirrored_mode(false);
+
+ if (dual_x_carriage_mode == DXC_MIRRORED_MODE) {
+ if (previous_mode != DXC_DUPLICATION_MODE) {
+ SERIAL_ECHOLNPGM("Printer must be in DXC_DUPLICATION_MODE prior to ");
+ SERIAL_ECHOLNPGM("specifying DXC_MIRRORED_MODE.");
+ dual_x_carriage_mode = DEFAULT_DUAL_X_CARRIAGE_MODE;
+ return;
+ }
+ idex_set_mirrored_mode(true);
+ float x_jog = current_position.x - .1;
+ for (uint8_t i = 2; --i;) {
+ planner.buffer_line(x_jog, current_position.y, current_position.z, current_position.e, feedrate_mm_s, 0);
+ x_jog += .1;
+ }
+ return;
+ }
+
+ switch (dual_x_carriage_mode) {
+ case DXC_FULL_CONTROL_MODE:
+ case DXC_AUTO_PARK_MODE:
+ break;
+ case DXC_DUPLICATION_MODE:
+ // Set the X offset, but no less than the safety gap
+ if (parser.seen('X')) duplicate_extruder_x_offset = _MAX(parser.value_linear_units(), (X2_MIN_POS) - (X1_MIN_POS));
+ if (parser.seen('R')) duplicate_extruder_temp_offset = parser.value_celsius_diff();
+ // Always switch back to tool 0
+ if (active_extruder != 0) tool_change(0);
+ break;
+ default:
+ dual_x_carriage_mode = DEFAULT_DUAL_X_CARRIAGE_MODE;
+ break;
+ }
+ idex_set_parked(false);
+ set_duplication_enabled(false);
+
+ #ifdef EVENT_GCODE_IDEX_AFTER_MODECHANGE
+ gcode.process_subcommands_now_P(PSTR(EVENT_GCODE_IDEX_AFTER_MODECHANGE));
+ #endif
+ }
+ else if (!parser.seen('W')) // if no S or W parameter, the DXC mode gets reset to the user's default
+ dual_x_carriage_mode = DEFAULT_DUAL_X_CARRIAGE_MODE;
+
+ #ifdef DEBUG_DXC_MODE
+
+ if (parser.seen('W')) {
+ DEBUG_ECHO_START();
+ DEBUG_ECHOPGM("Dual X Carriage Mode ");
+ switch (dual_x_carriage_mode) {
+ case DXC_FULL_CONTROL_MODE: DEBUG_ECHOPGM("FULL_CONTROL"); break;
+ case DXC_AUTO_PARK_MODE: DEBUG_ECHOPGM("AUTO_PARK"); break;
+ case DXC_DUPLICATION_MODE: DEBUG_ECHOPGM("DUPLICATION"); break;
+ case DXC_MIRRORED_MODE: DEBUG_ECHOPGM("MIRRORED"); break;
+ }
+ DEBUG_ECHOPAIR("\nActive Ext: ", int(active_extruder));
+ if (!active_extruder_parked) DEBUG_ECHOPGM(" NOT ");
+ DEBUG_ECHOPGM(" parked.");
+ DEBUG_ECHOPAIR("\nactive_extruder_x_pos: ", current_position.x);
+ DEBUG_ECHOPAIR("\ninactive_extruder_x: ", inactive_extruder_x);
+ DEBUG_ECHOPAIR("\nextruder_duplication_enabled: ", int(extruder_duplication_enabled));
+ DEBUG_ECHOPAIR("\nduplicate_extruder_x_offset: ", duplicate_extruder_x_offset);
+ DEBUG_ECHOPAIR("\nduplicate_extruder_temp_offset: ", duplicate_extruder_temp_offset);
+ DEBUG_ECHOPAIR("\ndelayed_move_time: ", delayed_move_time);
+ DEBUG_ECHOPAIR("\nX1 Home X: ", x_home_pos(0), "\nX1_MIN_POS=", int(X1_MIN_POS), "\nX1_MAX_POS=", int(X1_MAX_POS));
+ DEBUG_ECHOPAIR("\nX2 Home X: ", x_home_pos(1), "\nX2_MIN_POS=", int(X2_MIN_POS), "\nX2_MAX_POS=", int(X2_MAX_POS));
+ DEBUG_ECHOPAIR("\nX2_HOME_DIR=", int(X2_HOME_DIR), "\nX2_HOME_POS=", int(X2_HOME_POS));
+ DEBUG_ECHOPAIR("\nDEFAULT_DUAL_X_CARRIAGE_MODE=", STRINGIFY(DEFAULT_DUAL_X_CARRIAGE_MODE));
+ DEBUG_ECHOPAIR("\toolchange_settings.z_raise=", toolchange_settings.z_raise);
+ DEBUG_ECHOPAIR("\nDEFAULT_DUPLICATION_X_OFFSET=", int(DEFAULT_DUPLICATION_X_OFFSET));
+ DEBUG_EOL();
+
+ HOTEND_LOOP() {
+ DEBUG_ECHOPAIR_P(SP_T_STR, int(e));
+ LOOP_XYZ(a) DEBUG_ECHOPAIR(" hotend_offset[", int(e), "].", XYZ_CHAR(a) | 0x20, "=", hotend_offset[e][a]);
+ DEBUG_EOL();
+ }
+ DEBUG_EOL();
+ }
+ #endif // DEBUG_DXC_MODE
+ }
+
+#elif ENABLED(MULTI_NOZZLE_DUPLICATION)
+
+ /**
+ * M605: Set multi-nozzle duplication mode
+ *
+ * S2 - Enable duplication mode
+ * P[mask] - Bit-mask of nozzles to include in the duplication set.
+ * A value of 0 disables duplication.
+ * E[index] - Last nozzle index to include in the duplication set.
+ * A value of 0 disables duplication.
+ */
+ void GcodeSuite::M605() {
+ bool ena = false;
+ if (parser.seen("EPS")) {
+ planner.synchronize();
+ if (parser.seenval('P')) duplication_e_mask = parser.value_int(); // Set the mask directly
+ else if (parser.seenval('E')) duplication_e_mask = pow(2, parser.value_int() + 1) - 1; // Set the mask by E index
+ ena = (2 == parser.intval('S', extruder_duplication_enabled ? 2 : 0));
+ set_duplication_enabled(ena && (duplication_e_mask >= 3));
+ }
+ SERIAL_ECHO_START();
+ SERIAL_ECHOPGM(STR_DUPLICATION_MODE);
+ serialprint_onoff(extruder_duplication_enabled);
+ if (ena) {
+ SERIAL_ECHOPGM(" ( ");
+ HOTEND_LOOP() if (TEST(duplication_e_mask, e)) { SERIAL_ECHO(e); SERIAL_CHAR(' '); }
+ SERIAL_CHAR(')');
+ }
+ SERIAL_EOL();
+ }
+
+#endif // MULTI_NOZZLE_DUPLICATION
+
+#endif // HAS_DUPICATION_MODE
diff --git a/Marlin/src/gcode/control/M7-M9.cpp b/Marlin/src/gcode/control/M7-M9.cpp
new file mode 100644
index 0000000..a33e432
--- /dev/null
+++ b/Marlin/src/gcode/control/M7-M9.cpp
@@ -0,0 +1,63 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "../../inc/MarlinConfig.h"
+
+#if ENABLED(COOLANT_CONTROL)
+
+#include "../gcode.h"
+#include "../../module/planner.h"
+
+#if ENABLED(COOLANT_MIST)
+ /**
+ * M7: Mist Coolant On
+ */
+ void GcodeSuite::M7() {
+ planner.synchronize(); // Wait for move to arrive
+ WRITE(COOLANT_MIST_PIN, !(COOLANT_MIST_INVERT)); // Turn on Mist coolant
+ }
+#endif
+
+#if ENABLED(COOLANT_FLOOD)
+ /**
+ * M8: Flood Coolant On
+ */
+ void GcodeSuite::M8() {
+ planner.synchronize(); // Wait for move to arrive
+ WRITE(COOLANT_FLOOD_PIN, !(COOLANT_FLOOD_INVERT)); // Turn on Flood coolant
+ }
+#endif
+
+/**
+ * M9: Coolant OFF
+ */
+void GcodeSuite::M9() {
+ planner.synchronize(); // Wait for move to arrive
+ #if ENABLED(COOLANT_MIST)
+ WRITE(COOLANT_MIST_PIN, COOLANT_MIST_INVERT); // Turn off Mist coolant
+ #endif
+ #if ENABLED(COOLANT_FLOOD)
+ WRITE(COOLANT_FLOOD_PIN, COOLANT_FLOOD_INVERT); // Turn off Flood coolant
+ #endif
+}
+
+#endif // COOLANT_CONTROL
diff --git a/Marlin/src/gcode/control/M80_M81.cpp b/Marlin/src/gcode/control/M80_M81.cpp
new file mode 100644
index 0000000..394b06d
--- /dev/null
+++ b/Marlin/src/gcode/control/M80_M81.cpp
@@ -0,0 +1,113 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "../gcode.h"
+
+#include "../../module/temperature.h"
+#include "../../module/planner.h" // for planner.finish_and_disable
+#include "../../module/printcounter.h" // for print_job_timer.stop
+#include "../../lcd/marlinui.h" // for LCD_MESSAGEPGM_P
+
+#include "../../inc/MarlinConfig.h"
+
+#if HAS_SUICIDE
+ #include "../../MarlinCore.h"
+#endif
+
+#if ENABLED(PSU_CONTROL)
+
+ #if ENABLED(AUTO_POWER_CONTROL)
+ #include "../../feature/power.h"
+ #else
+ void restore_stepper_drivers();
+ #endif
+
+ // Could be moved to a feature, but this is all the data
+ bool powersupply_on;
+
+ #if HAS_TRINAMIC_CONFIG
+ #include "../../feature/tmc_util.h"
+ #endif
+
+ /**
+ * M80 : Turn on the Power Supply
+ * M80 S : Report the current state and exit
+ */
+ void GcodeSuite::M80() {
+
+ // S: Report the current power supply state and exit
+ if (parser.seen('S')) {
+ serialprintPGM(powersupply_on ? PSTR("PS:1\n") : PSTR("PS:0\n"));
+ return;
+ }
+
+ PSU_ON();
+
+ /**
+ * If you have a switch on suicide pin, this is useful
+ * if you want to start another print with suicide feature after
+ * a print without suicide...
+ */
+ #if HAS_SUICIDE
+ OUT_WRITE(SUICIDE_PIN, !SUICIDE_PIN_INVERTING);
+ #endif
+
+ #if DISABLED(AUTO_POWER_CONTROL)
+ safe_delay(PSU_POWERUP_DELAY);
+ restore_stepper_drivers();
+ TERN_(HAS_TRINAMIC_CONFIG, safe_delay(PSU_POWERUP_DELAY));
+ #endif
+
+ TERN_(HAS_LCD_MENU, ui.reset_status());
+ }
+
+#endif // PSU_CONTROL
+
+/**
+ * M81: Turn off Power, including Power Supply, if there is one.
+ *
+ * This code should ALWAYS be available for FULL SHUTDOWN!
+ */
+void GcodeSuite::M81() {
+ thermalManager.disable_all_heaters();
+ planner.finish_and_disable();
+
+ print_job_timer.stop();
+
+ #if HAS_FAN
+ thermalManager.zero_fan_speeds();
+ #if ENABLED(PROBING_FANS_OFF)
+ thermalManager.fans_paused = false;
+ ZERO(thermalManager.saved_fan_speed);
+ #endif
+ #endif
+
+ safe_delay(1000); // Wait 1 second before switching off
+
+ #if HAS_SUICIDE
+ suicide();
+ #elif ENABLED(PSU_CONTROL)
+ PSU_OFF_SOON();
+ #endif
+
+ LCD_MESSAGEPGM_P(PSTR(MACHINE_NAME " " STR_OFF "."));
+}
diff --git a/Marlin/src/gcode/control/M85.cpp b/Marlin/src/gcode/control/M85.cpp
new file mode 100644
index 0000000..9c8c02c
--- /dev/null
+++ b/Marlin/src/gcode/control/M85.cpp
@@ -0,0 +1,35 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "../gcode.h"
+
+/**
+ * M85: Set inactivity shutdown timer with parameter S<seconds>. To disable set zero (default)
+ */
+void GcodeSuite::M85() {
+
+ if (parser.seen('S')) {
+ reset_stepper_timeout();
+ max_inactive_time = parser.value_millis_from_seconds();
+ }
+
+}
diff --git a/Marlin/src/gcode/control/M993_M994.cpp b/Marlin/src/gcode/control/M993_M994.cpp
new file mode 100644
index 0000000..ff9ff85
--- /dev/null
+++ b/Marlin/src/gcode/control/M993_M994.cpp
@@ -0,0 +1,88 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "../../inc/MarlinConfig.h"
+
+#if ALL(HAS_SPI_FLASH, SDSUPPORT, MARLIN_DEV_MODE)
+
+#include "../gcode.h"
+#include "../../sd/cardreader.h"
+#include "../../libs/W25Qxx.h"
+
+/**
+ * M993: Backup SPI Flash to SD
+ */
+void GcodeSuite::M993() {
+ if (!card.isMounted()) card.mount();
+
+ char fname[] = "spiflash.bin";
+ card.openFileWrite(fname);
+ if (!card.isFileOpen()) {
+ SERIAL_ECHOLNPAIR("Failed to open ", fname, " to write.");
+ return;
+ }
+
+ uint8_t buf[1024];
+ uint32_t addr = 0;
+ W25QXX.init(SPI_QUARTER_SPEED);
+ SERIAL_ECHOPGM("Save SPI Flash");
+ while (addr < SPI_FLASH_SIZE) {
+ W25QXX.SPI_FLASH_BufferRead(buf, addr, COUNT(buf));
+ addr += COUNT(buf);
+ card.write(buf, COUNT(buf));
+ if (addr % (COUNT(buf) * 10) == 0) SERIAL_CHAR('.');
+ }
+ SERIAL_ECHOLNPGM(" done");
+
+ card.closefile();
+}
+
+/**
+ * M994: Load a backup from SD to SPI Flash
+ */
+void GcodeSuite::M994() {
+ if (!card.isMounted()) card.mount();
+
+ char fname[] = "spiflash.bin";
+ card.openFileRead(fname);
+ if (!card.isFileOpen()) {
+ SERIAL_ECHOLNPAIR("Failed to open ", fname, " to read.");
+ return;
+ }
+
+ uint8_t buf[1024];
+ uint32_t addr = 0;
+ W25QXX.init(SPI_QUARTER_SPEED);
+ W25QXX.SPI_FLASH_BulkErase();
+ SERIAL_ECHOPGM("Load SPI Flash");
+ while (addr < SPI_FLASH_SIZE) {
+ card.read(buf, COUNT(buf));
+ W25QXX.SPI_FLASH_BufferWrite(buf, addr, COUNT(buf));
+ addr += COUNT(buf);
+ if (addr % (COUNT(buf) * 10) == 0) SERIAL_CHAR('.');
+ }
+ SERIAL_ECHOLNPGM(" done");
+
+ card.closefile();
+}
+
+#endif // HAS_SPI_FLASH && SDSUPPORT && MARLIN_DEV_MODE
diff --git a/Marlin/src/gcode/control/M997.cpp b/Marlin/src/gcode/control/M997.cpp
new file mode 100644
index 0000000..cdff96f
--- /dev/null
+++ b/Marlin/src/gcode/control/M997.cpp
@@ -0,0 +1,36 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "../gcode.h"
+
+#if ENABLED(PLATFORM_M997_SUPPORT)
+
+/**
+ * M997: Perform in-application firmware update
+ */
+void GcodeSuite::M997() {
+
+ flashFirmware(parser.intval('S'));
+
+}
+
+#endif
diff --git a/Marlin/src/gcode/control/M999.cpp b/Marlin/src/gcode/control/M999.cpp
new file mode 100644
index 0000000..7487b4c
--- /dev/null
+++ b/Marlin/src/gcode/control/M999.cpp
@@ -0,0 +1,45 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "../gcode.h"
+
+#include "../../lcd/marlinui.h" // for lcd_reset_alert_level
+#include "../../MarlinCore.h" // for marlin_state
+#include "../queue.h" // for flush_and_request_resend
+
+/**
+ * M999: Restart after being stopped
+ *
+ * Default behavior is to flush the serial buffer and request
+ * a resend to the host starting on the last N line received.
+ *
+ * Sending "M999 S1" will resume printing without flushing the
+ * existing command buffer.
+ */
+void GcodeSuite::M999() {
+ marlin_state = MF_RUNNING;
+ ui.reset_alert_level();
+
+ if (parser.boolval('S')) return;
+
+ queue.flush_and_request_resend();
+}
diff --git a/Marlin/src/gcode/control/T.cpp b/Marlin/src/gcode/control/T.cpp
new file mode 100644
index 0000000..3ce284f
--- /dev/null
+++ b/Marlin/src/gcode/control/T.cpp
@@ -0,0 +1,70 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "../gcode.h"
+#include "../../module/tool_change.h"
+
+#if EITHER(HAS_MULTI_EXTRUDER, DEBUG_LEVELING_FEATURE)
+ #include "../../module/motion.h"
+#endif
+
+#if HAS_PRUSA_MMU2
+ #include "../../feature/mmu/mmu2.h"
+#endif
+
+#define DEBUG_OUT ENABLED(DEBUG_LEVELING_FEATURE)
+#include "../../core/debug_out.h"
+
+/**
+ * T0-T<n>: Switch tool, usually switching extruders
+ *
+ * F[units/min] Set the movement feedrate
+ * S1 Don't move the tool in XY after change
+ *
+ * For PRUSA_MMU2(S) and SMUFF_EMU_MMU2(S)
+ * T[n] Gcode to extrude at least 38.10 mm at feedrate 19.02 mm/s must follow immediately to load to extruder wheels.
+ * T? Gcode to extrude shouldn't have to follow. Load to extruder wheels is done automatically.
+ * Tx Same as T?, but nozzle doesn't have to be preheated. Tc requires a preheated nozzle to finish filament load.
+ * Tc Load to nozzle after filament was prepared by Tc and nozzle is already heated.
+ */
+void GcodeSuite::T(const int8_t tool_index) {
+
+ DEBUG_SECTION(log_T, "T", DEBUGGING(LEVELING));
+ if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("...(", tool_index, ")");
+
+ // Count this command as movement / activity
+ reset_stepper_timeout();
+
+ #if HAS_PRUSA_MMU2
+ if (parser.string_arg) {
+ mmu2.tool_change(parser.string_arg); // Special commands T?/Tx/Tc
+ return;
+ }
+ #endif
+
+ tool_change(tool_index
+ #if HAS_MULTI_EXTRUDER
+ , TERN(PARKING_EXTRUDER, false, tool_index == active_extruder) // For PARKING_EXTRUDER motion is decided in tool_change()
+ || parser.boolval('S')
+ #endif
+ );
+}