aboutsummaryrefslogtreecommitdiff
path: root/Marlin/src/gcode/config
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/config
downloadkp3s-lgvl-e8701195e66f2d27ffe17fb514eae8173795aaf7.tar.xz
kp3s-lgvl-e8701195e66f2d27ffe17fb514eae8173795aaf7.zip
Initial commit
Diffstat (limited to 'Marlin/src/gcode/config')
-rw-r--r--Marlin/src/gcode/config/M200-M205.cpp191
-rw-r--r--Marlin/src/gcode/config/M217.cpp171
-rw-r--r--Marlin/src/gcode/config/M218.cpp71
-rw-r--r--Marlin/src/gcode/config/M220.cpp51
-rw-r--r--Marlin/src/gcode/config/M221.cpp47
-rw-r--r--Marlin/src/gcode/config/M281.cpp68
-rw-r--r--Marlin/src/gcode/config/M301.cpp91
-rw-r--r--Marlin/src/gcode/config/M302.cpp63
-rw-r--r--Marlin/src/gcode/config/M304.cpp48
-rw-r--r--Marlin/src/gcode/config/M305.cpp81
-rw-r--r--Marlin/src/gcode/config/M43.cpp386
-rw-r--r--Marlin/src/gcode/config/M540.cpp40
-rw-r--r--Marlin/src/gcode/config/M575.cpp75
-rw-r--r--Marlin/src/gcode/config/M672.cpp98
-rw-r--r--Marlin/src/gcode/config/M92.cpp114
15 files changed, 1595 insertions, 0 deletions
diff --git a/Marlin/src/gcode/config/M200-M205.cpp b/Marlin/src/gcode/config/M200-M205.cpp
new file mode 100644
index 0000000..cb17fc4
--- /dev/null
+++ b/Marlin/src/gcode/config/M200-M205.cpp
@@ -0,0 +1,191 @@
+/**
+ * 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"
+#include "../../module/planner.h"
+
+#if DISABLED(NO_VOLUMETRICS)
+
+ /**
+ * M200: Set filament diameter and set E axis units to cubic units
+ *
+ * T<extruder> - Optional extruder number. Current extruder if omitted.
+ * D<linear> - Set filament diameter and enable. D0 disables volumetric.
+ * S<bool> - Turn volumetric ON or OFF.
+ * L<float> - Volumetric extruder limit (in mm^3/sec). L0 disables the limit.
+ */
+ void GcodeSuite::M200() {
+
+ const int8_t target_extruder = get_target_extruder_from_command();
+ if (target_extruder < 0) return;
+
+ bool vol_enable = parser.volumetric_enabled,
+ can_enable = true;
+
+ if (parser.seenval('D')) {
+ const float dval = parser.value_linear_units();
+ if (dval) { // Set filament size for volumetric calculation
+ planner.set_filament_size(target_extruder, dval);
+ vol_enable = true; // Dn = enable for compatibility
+ }
+ else
+ can_enable = false; // D0 = disable for compatibility
+ }
+
+ // Enable or disable with S1 / S0
+ parser.volumetric_enabled = can_enable && parser.boolval('S', vol_enable);
+
+ #if ENABLED(VOLUMETRIC_EXTRUDER_LIMIT)
+ if (parser.seenval('L')) {
+ // Set volumetric limit (in mm^3/sec)
+ const float lval = parser.value_float();
+ if (WITHIN(lval, 0, 20))
+ planner.set_volumetric_extruder_limit(target_extruder, lval);
+ else
+ SERIAL_ECHOLNPGM("?L value out of range (0-20).");
+ }
+ #endif
+
+ planner.calculate_volumetric_multipliers();
+ }
+
+#endif // !NO_VOLUMETRICS
+
+/**
+ * M201: Set max acceleration in units/s^2 for print moves (M201 X1000 Y1000)
+ *
+ * With multiple extruders use T to specify which one.
+ */
+void GcodeSuite::M201() {
+
+ const int8_t target_extruder = get_target_extruder_from_command();
+ if (target_extruder < 0) return;
+
+ #ifdef XY_FREQUENCY_LIMIT
+ if (parser.seenval('F')) planner.set_frequency_limit(parser.value_byte());
+ if (parser.seenval('G')) planner.xy_freq_min_speed_factor = constrain(parser.value_float(), 1, 100) / 100;
+ #endif
+
+ LOOP_XYZE(i) {
+ if (parser.seen(axis_codes[i])) {
+ const uint8_t a = (i == E_AXIS ? uint8_t(E_AXIS_N(target_extruder)) : i);
+ planner.set_max_acceleration(a, parser.value_axis_units((AxisEnum)a));
+ }
+ }
+}
+
+/**
+ * M203: Set maximum feedrate that your machine can sustain (M203 X200 Y200 Z300 E10000) in units/sec
+ *
+ * With multiple extruders use T to specify which one.
+ */
+void GcodeSuite::M203() {
+
+ const int8_t target_extruder = get_target_extruder_from_command();
+ if (target_extruder < 0) return;
+
+ LOOP_XYZE(i)
+ if (parser.seen(axis_codes[i])) {
+ const uint8_t a = (i == E_AXIS ? uint8_t(E_AXIS_N(target_extruder)) : i);
+ planner.set_max_feedrate(a, parser.value_axis_units((AxisEnum)a));
+ }
+}
+
+/**
+ * M204: Set Accelerations in units/sec^2 (M204 P1200 R3000 T3000)
+ *
+ * P = Printing moves
+ * R = Retract only (no X, Y, Z) moves
+ * T = Travel (non printing) moves
+ */
+void GcodeSuite::M204() {
+ if (!parser.seen("PRST")) {
+ SERIAL_ECHOPAIR("Acceleration: P", planner.settings.acceleration);
+ SERIAL_ECHOPAIR(" R", planner.settings.retract_acceleration);
+ SERIAL_ECHOLNPAIR_P(SP_T_STR, planner.settings.travel_acceleration);
+ }
+ else {
+ //planner.synchronize();
+ // 'S' for legacy compatibility. Should NOT BE USED for new development
+ if (parser.seenval('S')) planner.settings.travel_acceleration = planner.settings.acceleration = parser.value_linear_units();
+ if (parser.seenval('P')) planner.settings.acceleration = parser.value_linear_units();
+ if (parser.seenval('R')) planner.settings.retract_acceleration = parser.value_linear_units();
+ if (parser.seenval('T')) planner.settings.travel_acceleration = parser.value_linear_units();
+ }
+}
+
+/**
+ * M205: Set Advanced Settings
+ *
+ * B = Min Segment Time (µs)
+ * S = Min Feed Rate (units/s)
+ * T = Min Travel Feed Rate (units/s)
+ * X = Max X Jerk (units/sec^2)
+ * Y = Max Y Jerk (units/sec^2)
+ * Z = Max Z Jerk (units/sec^2)
+ * E = Max E Jerk (units/sec^2)
+ * J = Junction Deviation (mm) (If not using CLASSIC_JERK)
+ */
+void GcodeSuite::M205() {
+ #if HAS_JUNCTION_DEVIATION
+ #define J_PARAM "J"
+ #else
+ #define J_PARAM
+ #endif
+ #if HAS_CLASSIC_JERK
+ #define XYZE_PARAM "XYZE"
+ #else
+ #define XYZE_PARAM
+ #endif
+ if (!parser.seen("BST" J_PARAM XYZE_PARAM)) return;
+
+ //planner.synchronize();
+ if (parser.seen('B')) planner.settings.min_segment_time_us = parser.value_ulong();
+ if (parser.seen('S')) planner.settings.min_feedrate_mm_s = parser.value_linear_units();
+ if (parser.seen('T')) planner.settings.min_travel_feedrate_mm_s = parser.value_linear_units();
+ #if HAS_JUNCTION_DEVIATION
+ if (parser.seen('J')) {
+ const float junc_dev = parser.value_linear_units();
+ if (WITHIN(junc_dev, 0.01f, 0.3f)) {
+ planner.junction_deviation_mm = junc_dev;
+ TERN_(LIN_ADVANCE, planner.recalculate_max_e_jerk());
+ }
+ else
+ SERIAL_ERROR_MSG("?J out of range (0.01 to 0.3)");
+ }
+ #endif
+ #if HAS_CLASSIC_JERK
+ if (parser.seen('X')) planner.set_max_jerk(X_AXIS, parser.value_linear_units());
+ if (parser.seen('Y')) planner.set_max_jerk(Y_AXIS, parser.value_linear_units());
+ if (parser.seen('Z')) {
+ planner.set_max_jerk(Z_AXIS, parser.value_linear_units());
+ #if HAS_MESH && DISABLED(LIMITED_JERK_EDITING)
+ if (planner.max_jerk.z <= 0.1f)
+ SERIAL_ECHOLNPGM("WARNING! Low Z Jerk may lead to unwanted pauses.");
+ #endif
+ }
+ #if HAS_CLASSIC_E_JERK
+ if (parser.seen('E')) planner.set_max_jerk(E_AXIS, parser.value_linear_units());
+ #endif
+ #endif
+}
diff --git a/Marlin/src/gcode/config/M217.cpp b/Marlin/src/gcode/config/M217.cpp
new file mode 100644
index 0000000..f2fefb5
--- /dev/null
+++ b/Marlin/src/gcode/config/M217.cpp
@@ -0,0 +1,171 @@
+/**
+ * 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_MULTI_EXTRUDER
+
+#include "../gcode.h"
+#include "../../module/tool_change.h"
+
+#if ENABLED(TOOLCHANGE_MIGRATION_FEATURE)
+ #include "../../module/motion.h"
+#endif
+
+#include "../../MarlinCore.h" // for SP_X_STR, etc.
+
+void M217_report(const bool eeprom=false) {
+
+ #if ENABLED(TOOLCHANGE_FILAMENT_SWAP)
+ serialprintPGM(eeprom ? PSTR(" M217") : PSTR("Toolchange:"));
+ SERIAL_ECHOPAIR(" S", LINEAR_UNIT(toolchange_settings.swap_length));
+ SERIAL_ECHOPAIR_P(SP_B_STR, LINEAR_UNIT(toolchange_settings.extra_resume),
+ SP_E_STR, LINEAR_UNIT(toolchange_settings.extra_prime),
+ SP_P_STR, LINEAR_UNIT(toolchange_settings.prime_speed));
+ SERIAL_ECHOPAIR(" R", LINEAR_UNIT(toolchange_settings.retract_speed),
+ " U", LINEAR_UNIT(toolchange_settings.unretract_speed),
+ " F", toolchange_settings.fan_speed,
+ " G", toolchange_settings.fan_time);
+
+ #if ENABLED(TOOLCHANGE_MIGRATION_FEATURE)
+ SERIAL_ECHOPAIR(" A", int(migration.automode));
+ SERIAL_ECHOPAIR(" L", LINEAR_UNIT(migration.last));
+ #endif
+
+ #if ENABLED(TOOLCHANGE_PARK)
+ SERIAL_ECHOPAIR(" W", LINEAR_UNIT(toolchange_settings.enable_park));
+ SERIAL_ECHOPAIR_P(SP_X_STR, LINEAR_UNIT(toolchange_settings.change_point.x));
+ SERIAL_ECHOPAIR_P(SP_Y_STR, LINEAR_UNIT(toolchange_settings.change_point.y));
+ #endif
+
+ #if ENABLED(TOOLCHANGE_FS_PRIME_FIRST_USED)
+ SERIAL_ECHOPAIR(" V", LINEAR_UNIT(enable_first_prime));
+ #endif
+
+ #else
+
+ UNUSED(eeprom);
+
+ #endif
+
+ SERIAL_ECHOPAIR_P(SP_Z_STR, LINEAR_UNIT(toolchange_settings.z_raise));
+ SERIAL_EOL();
+}
+
+/**
+ * M217 - Set SINGLENOZZLE toolchange parameters
+ *
+ * // Tool change command
+ * Q Prime active tool and exit
+ *
+ * // Tool change settings
+ * S[linear] Swap length
+ * B[linear] Extra Swap length
+ * E[linear] Prime length
+ * P[linear/m] Prime speed
+ * R[linear/m] Retract speed
+ * U[linear/m] UnRetract speed
+ * V[linear] 0/1 Enable auto prime first extruder used
+ * W[linear] 0/1 Enable park & Z Raise
+ * X[linear] Park X (Requires TOOLCHANGE_PARK)
+ * Y[linear] Park Y (Requires TOOLCHANGE_PARK)
+ * Z[linear] Z Raise
+ * F[linear] Fan Speed 0-255
+ * G[linear/s] Fan time
+ *
+ * Tool migration settings
+ * A[0|1] Enable auto-migration on runout
+ * L[index] Last extruder to use for auto-migration
+ *
+ * Tool migration command
+ * T[index] Migrate to next extruder or the given extruder
+ */
+void GcodeSuite::M217() {
+
+ #if ENABLED(TOOLCHANGE_FILAMENT_SWAP)
+
+ static constexpr float max_extrude = TERN(PREVENT_LENGTHY_EXTRUDE, EXTRUDE_MAXLENGTH, 500);
+
+ if (parser.seen('Q')) { tool_change_prime(); return; }
+
+ if (parser.seenval('S')) { const float v = parser.value_linear_units(); toolchange_settings.swap_length = constrain(v, 0, max_extrude); }
+ if (parser.seenval('B')) { const float v = parser.value_linear_units(); toolchange_settings.extra_resume = constrain(v, -10, 10); }
+ if (parser.seenval('E')) { const float v = parser.value_linear_units(); toolchange_settings.extra_prime = constrain(v, 0, max_extrude); }
+ if (parser.seenval('P')) { const int16_t v = parser.value_linear_units(); toolchange_settings.prime_speed = constrain(v, 10, 5400); }
+ if (parser.seenval('R')) { const int16_t v = parser.value_linear_units(); toolchange_settings.retract_speed = constrain(v, 10, 5400); }
+ if (parser.seenval('U')) { const int16_t v = parser.value_linear_units(); toolchange_settings.unretract_speed = constrain(v, 10, 5400); }
+ #if TOOLCHANGE_FS_FAN >= 0 && HAS_FAN
+ if (parser.seenval('F')) { const int16_t v = parser.value_linear_units(); toolchange_settings.fan_speed = constrain(v, 0, 255); }
+ if (parser.seenval('G')) { const int16_t v = parser.value_linear_units(); toolchange_settings.fan_time = constrain(v, 1, 30); }
+ #endif
+ #endif
+
+ #if ENABLED(TOOLCHANGE_FS_PRIME_FIRST_USED)
+ if (parser.seenval('V')) { enable_first_prime = parser.value_linear_units(); }
+ #endif
+
+ #if ENABLED(TOOLCHANGE_PARK)
+ if (parser.seenval('W')) { toolchange_settings.enable_park = parser.value_linear_units(); }
+ if (parser.seenval('X')) { const int16_t v = parser.value_linear_units(); toolchange_settings.change_point.x = constrain(v, X_MIN_POS, X_MAX_POS); }
+ if (parser.seenval('Y')) { const int16_t v = parser.value_linear_units(); toolchange_settings.change_point.y = constrain(v, Y_MIN_POS, Y_MAX_POS); }
+ #endif
+
+ if (parser.seenval('Z')) { toolchange_settings.z_raise = parser.value_linear_units(); }
+
+ #if ENABLED(TOOLCHANGE_MIGRATION_FEATURE)
+ migration.target = 0; // 0 = disabled
+
+ if (parser.seenval('L')) { // Last
+ const int16_t lval = parser.value_int();
+ if (WITHIN(lval, 0, EXTRUDERS - 1)) {
+ migration.last = lval;
+ migration.automode = (active_extruder < migration.last);
+ }
+ }
+
+ if (parser.seen('A')) // Auto on/off
+ migration.automode = parser.value_bool();
+
+ if (parser.seen('T')) { // Migrate now
+ if (parser.has_value()) {
+ const int16_t tval = parser.value_int();
+ if (WITHIN(tval, 0, EXTRUDERS - 1) && tval != active_extruder) {
+ migration.target = tval + 1;
+ extruder_migration();
+ migration.target = 0; // disable
+ return;
+ }
+ else
+ migration.target = 0; // disable
+ }
+ else {
+ extruder_migration();
+ return;
+ }
+ }
+
+ #endif
+
+ M217_report();
+}
+
+#endif // HAS_MULTI_EXTRUDER
diff --git a/Marlin/src/gcode/config/M218.cpp b/Marlin/src/gcode/config/M218.cpp
new file mode 100644
index 0000000..7701320
--- /dev/null
+++ b/Marlin/src/gcode/config/M218.cpp
@@ -0,0 +1,71 @@
+/**
+ * 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_HOTEND_OFFSET
+
+#include "../gcode.h"
+#include "../../module/motion.h"
+
+#if ENABLED(DELTA)
+ #include "../../module/planner.h"
+#endif
+
+/**
+ * M218 - set hotend offset (in linear units)
+ *
+ * T<tool>
+ * X<xoffset>
+ * Y<yoffset>
+ * Z<zoffset>
+ */
+void GcodeSuite::M218() {
+
+ const int8_t target_extruder = get_target_extruder_from_command();
+ if (target_extruder < 0) return;
+
+ if (parser.seenval('X')) hotend_offset[target_extruder].x = parser.value_linear_units();
+ if (parser.seenval('Y')) hotend_offset[target_extruder].y = parser.value_linear_units();
+ if (parser.seenval('Z')) hotend_offset[target_extruder].z = parser.value_linear_units();
+
+ if (!parser.seen("XYZ")) {
+ SERIAL_ECHO_START();
+ SERIAL_ECHOPGM(STR_HOTEND_OFFSET);
+ HOTEND_LOOP() {
+ SERIAL_CHAR(' ');
+ SERIAL_ECHO(hotend_offset[e].x);
+ SERIAL_CHAR(',');
+ SERIAL_ECHO(hotend_offset[e].y);
+ SERIAL_CHAR(',');
+ SERIAL_ECHO_F(hotend_offset[e].z, 3);
+ }
+ SERIAL_EOL();
+ }
+
+ #if ENABLED(DELTA)
+ if (target_extruder == active_extruder)
+ do_blocking_move_to_xy(current_position, planner.settings.max_feedrate_mm_s[X_AXIS]);
+ #endif
+}
+
+#endif // HAS_HOTEND_OFFSET
diff --git a/Marlin/src/gcode/config/M220.cpp b/Marlin/src/gcode/config/M220.cpp
new file mode 100644
index 0000000..75339f1
--- /dev/null
+++ b/Marlin/src/gcode/config/M220.cpp
@@ -0,0 +1,51 @@
+/**
+ * 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/motion.h"
+
+/**
+ * M220: Set speed percentage factor, aka "Feed Rate"
+ *
+ * Parameters
+ * S<percent> : Set the feed rate percentage factor
+ *
+ * Report the current speed percentage factor if no parameter is specified
+ *
+ * For MMU2 and MMU2S devices...
+ * B : Flag to back up the current factor
+ * R : Flag to restore the last-saved factor
+ */
+void GcodeSuite::M220() {
+
+ static int16_t backup_feedrate_percentage = 100;
+ if (parser.seen('B')) backup_feedrate_percentage = feedrate_percentage;
+ if (parser.seen('R')) feedrate_percentage = backup_feedrate_percentage;
+
+ if (parser.seenval('S')) feedrate_percentage = parser.value_int();
+
+ if (!parser.seen_any()) {
+ SERIAL_ECHOPAIR("FR:", feedrate_percentage);
+ SERIAL_CHAR('%');
+ SERIAL_EOL();
+ }
+}
diff --git a/Marlin/src/gcode/config/M221.cpp b/Marlin/src/gcode/config/M221.cpp
new file mode 100644
index 0000000..7ba22d1
--- /dev/null
+++ b/Marlin/src/gcode/config/M221.cpp
@@ -0,0 +1,47 @@
+/**
+ * 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/planner.h"
+
+#if EXTRUDERS
+
+/**
+ * M221: Set extrusion percentage (M221 T0 S95)
+ */
+void GcodeSuite::M221() {
+
+ const int8_t target_extruder = get_target_extruder_from_command();
+ if (target_extruder < 0) return;
+
+ if (parser.seenval('S'))
+ planner.set_flow(target_extruder, parser.value_int());
+ else {
+ SERIAL_ECHO_START();
+ SERIAL_CHAR('E', '0' + target_extruder);
+ SERIAL_ECHOPAIR(" Flow: ", planner.flow_percentage[target_extruder]);
+ SERIAL_CHAR('%');
+ SERIAL_EOL();
+ }
+}
+
+#endif // EXTRUDERS
diff --git a/Marlin/src/gcode/config/M281.cpp b/Marlin/src/gcode/config/M281.cpp
new file mode 100644
index 0000000..018ca1c
--- /dev/null
+++ b/Marlin/src/gcode/config/M281.cpp
@@ -0,0 +1,68 @@
+/**
+ * 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(EDITABLE_SERVO_ANGLES)
+
+#include "../gcode.h"
+#include "../../module/servo.h"
+
+/**
+ * M281 - Edit / Report Servo Angles
+ *
+ * P<index> - Servo to update
+ * L<angle> - Deploy Angle
+ * U<angle> - Stowed Angle
+ */
+void GcodeSuite::M281() {
+ if (!parser.seenval('P')) return;
+ const int servo_index = parser.value_int();
+ if (WITHIN(servo_index, 0, NUM_SERVOS - 1)) {
+ #if ENABLED(BLTOUCH)
+ if (servo_index == Z_PROBE_SERVO_NR) {
+ SERIAL_ERROR_MSG("BLTouch angles can't be changed.");
+ return;
+ }
+ #endif
+ bool angle_change = false;
+ if (parser.seen('L')) {
+ servo_angles[servo_index][0] = parser.value_int();
+ angle_change = true;
+ }
+ if (parser.seen('U')) {
+ servo_angles[servo_index][1] = parser.value_int();
+ angle_change = true;
+ }
+ if (!angle_change) {
+ SERIAL_ECHO_START();
+ SERIAL_ECHOLNPAIR(" Servo ", servo_index,
+ " L", servo_angles[servo_index][0],
+ " U", servo_angles[servo_index][1]);
+ }
+ }
+ else {
+ SERIAL_ERROR_START();
+ SERIAL_ECHOLNPAIR("Servo ", servo_index, " out of range");
+ }
+}
+
+#endif // EDITABLE_SERVO_ANGLES
diff --git a/Marlin/src/gcode/config/M301.cpp b/Marlin/src/gcode/config/M301.cpp
new file mode 100644
index 0000000..7b3f576
--- /dev/null
+++ b/Marlin/src/gcode/config/M301.cpp
@@ -0,0 +1,91 @@
+/**
+ * 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(PIDTEMP)
+
+#include "../gcode.h"
+#include "../../module/temperature.h"
+
+/**
+ * M301: Set PID parameters P I D (and optionally C, L)
+ *
+ * E[extruder] Default: 0
+ *
+ * P[float] Kp term
+ * I[float] Ki term (unscaled)
+ * D[float] Kd term (unscaled)
+ *
+ * With PID_EXTRUSION_SCALING:
+ *
+ * C[float] Kc term
+ * L[int] LPQ length
+ *
+ * With PID_FAN_SCALING:
+ *
+ * F[float] Kf term
+ */
+void GcodeSuite::M301() {
+
+ // multi-extruder PID patch: M301 updates or prints a single extruder's PID values
+ // default behavior (omitting E parameter) is to update for extruder 0 only
+ const uint8_t e = parser.byteval('E'); // extruder being updated
+
+ if (e < HOTENDS) { // catch bad input value
+ if (parser.seen('P')) PID_PARAM(Kp, e) = parser.value_float();
+ if (parser.seen('I')) PID_PARAM(Ki, e) = scalePID_i(parser.value_float());
+ if (parser.seen('D')) PID_PARAM(Kd, e) = scalePID_d(parser.value_float());
+ #if ENABLED(PID_EXTRUSION_SCALING)
+ if (parser.seen('C')) PID_PARAM(Kc, e) = parser.value_float();
+ if (parser.seenval('L')) thermalManager.lpq_len = parser.value_int();
+ NOMORE(thermalManager.lpq_len, LPQ_MAX_LEN);
+ NOLESS(thermalManager.lpq_len, 0);
+ #endif
+
+ #if ENABLED(PID_FAN_SCALING)
+ if (parser.seen('F')) PID_PARAM(Kf, e) = parser.value_float();
+ #endif
+
+ thermalManager.updatePID();
+
+ SERIAL_ECHO_START();
+ #if ENABLED(PID_PARAMS_PER_HOTEND)
+ SERIAL_ECHOPAIR(" e:", e); // specify extruder in serial output
+ #endif
+ SERIAL_ECHOPAIR(" p:", PID_PARAM(Kp, e),
+ " i:", unscalePID_i(PID_PARAM(Ki, e)),
+ " d:", unscalePID_d(PID_PARAM(Kd, e)));
+ #if ENABLED(PID_EXTRUSION_SCALING)
+ SERIAL_ECHOPAIR(" c:", PID_PARAM(Kc, e));
+ #endif
+ #if ENABLED(PID_FAN_SCALING)
+ SERIAL_ECHOPAIR(" f:", PID_PARAM(Kf, e));
+ #endif
+
+ SERIAL_EOL();
+ }
+ else
+ SERIAL_ERROR_MSG(STR_INVALID_EXTRUDER);
+}
+
+#endif // PIDTEMP
diff --git a/Marlin/src/gcode/config/M302.cpp b/Marlin/src/gcode/config/M302.cpp
new file mode 100644
index 0000000..afdc6c9
--- /dev/null
+++ b/Marlin/src/gcode/config/M302.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(PREVENT_COLD_EXTRUSION)
+
+#include "../gcode.h"
+#include "../../module/temperature.h"
+
+/**
+ * M302: Allow cold extrudes, or set the minimum extrude temperature
+ *
+ * S<temperature> sets the minimum extrude temperature
+ * P<bool> enables (1) or disables (0) cold extrusion
+ *
+ * Examples:
+ *
+ * M302 ; report current cold extrusion state
+ * M302 P0 ; enable cold extrusion checking
+ * M302 P1 ; disable cold extrusion checking
+ * M302 S0 ; always allow extrusion (disables checking)
+ * M302 S170 ; only allow extrusion above 170
+ * M302 S170 P1 ; set min extrude temp to 170 but leave disabled
+ */
+void GcodeSuite::M302() {
+ const bool seen_S = parser.seen('S');
+ if (seen_S) {
+ thermalManager.extrude_min_temp = parser.value_celsius();
+ thermalManager.allow_cold_extrude = (thermalManager.extrude_min_temp == 0);
+ }
+
+ if (parser.seen('P'))
+ thermalManager.allow_cold_extrude = (thermalManager.extrude_min_temp == 0) || parser.value_bool();
+ else if (!seen_S) {
+ // Report current state
+ SERIAL_ECHO_START();
+ SERIAL_ECHOPGM("Cold extrudes are ");
+ serialprintPGM(thermalManager.allow_cold_extrude ? PSTR("en") : PSTR("dis"));
+ SERIAL_ECHOLNPAIR("abled (min temp ", thermalManager.extrude_min_temp, "C)");
+ }
+}
+
+#endif // PREVENT_COLD_EXTRUSION
diff --git a/Marlin/src/gcode/config/M304.cpp b/Marlin/src/gcode/config/M304.cpp
new file mode 100644
index 0000000..10739be
--- /dev/null
+++ b/Marlin/src/gcode/config/M304.cpp
@@ -0,0 +1,48 @@
+/**
+ * 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(PIDTEMPBED)
+
+#include "../gcode.h"
+#include "../../module/temperature.h"
+
+/**
+ * M304 - Set and/or Report the current Bed PID values
+ *
+ * P<pval> - Set the P value
+ * I<ival> - Set the I value
+ * D<dval> - Set the D value
+ */
+void GcodeSuite::M304() {
+ if (parser.seen('P')) thermalManager.temp_bed.pid.Kp = parser.value_float();
+ if (parser.seen('I')) thermalManager.temp_bed.pid.Ki = scalePID_i(parser.value_float());
+ if (parser.seen('D')) thermalManager.temp_bed.pid.Kd = scalePID_d(parser.value_float());
+
+ SERIAL_ECHO_START();
+ SERIAL_ECHOLNPAIR(" p:", thermalManager.temp_bed.pid.Kp,
+ " i:", unscalePID_i(thermalManager.temp_bed.pid.Ki),
+ " d:", unscalePID_d(thermalManager.temp_bed.pid.Kd));
+}
+
+#endif // PIDTEMPBED
diff --git a/Marlin/src/gcode/config/M305.cpp b/Marlin/src/gcode/config/M305.cpp
new file mode 100644
index 0000000..3e7206a
--- /dev/null
+++ b/Marlin/src/gcode/config/M305.cpp
@@ -0,0 +1,81 @@
+/**
+ * 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_USER_THERMISTORS
+
+#include "../gcode.h"
+#include "../../module/temperature.h"
+
+/**
+ * M305: Set (or report) custom thermistor parameters
+ *
+ * P[index] Thermistor table index
+ * R[ohms] Pullup resistor value
+ * T[ohms] Resistance at 25C
+ * B[beta] Thermistor "beta" value
+ * C[coeff] Steinhart-Hart Coefficient 'C'
+ *
+ * Format: M305 P[tbl_index] R[pullup_resistor_val] T[therm_25C_resistance] B[therm_beta] C[Steinhart_Hart_C_coeff]
+ *
+ * Examples: M305 P0 R4700 T100000 B3950 C0.0
+ * M305 P0 R4700
+ * M305 P0 T100000
+ * M305 P0 B3950
+ * M305 P0 C0.0
+ */
+void GcodeSuite::M305() {
+ const int8_t t_index = parser.intval('P', -1);
+ const bool do_set = parser.seen("BCRT");
+
+ // A valid P index is required
+ if (t_index >= (USER_THERMISTORS) || (do_set && t_index < 0)) {
+ SERIAL_ECHO_START();
+ SERIAL_ECHOLNPAIR("!Invalid index. (0 <= P <= ", int(USER_THERMISTORS - 1), ")");
+ }
+ else if (do_set) {
+ if (parser.seen('R')) // Pullup resistor value
+ if (!thermalManager.set_pull_up_res(t_index, parser.value_float()))
+ SERIAL_ECHO_MSG("!Invalid series resistance. (0 < R < 1000000)");
+
+ if (parser.seen('T')) // Resistance at 25C
+ if (!thermalManager.set_res25(t_index, parser.value_float()))
+ SERIAL_ECHO_MSG("!Invalid 25C resistance. (0 < T < 10000000)");
+
+ if (parser.seen('B')) // Beta value
+ if (!thermalManager.set_beta(t_index, parser.value_float()))
+ SERIAL_ECHO_MSG("!Invalid beta. (0 < B < 1000000)");
+
+ if (parser.seen('C')) // Steinhart-Hart C coefficient
+ if (!thermalManager.set_sh_coeff(t_index, parser.value_float()))
+ SERIAL_ECHO_MSG("!Invalid Steinhart-Hart C coeff. (-0.01 < C < +0.01)");
+ } // If not setting then report parameters
+ else if (t_index < 0) { // ...all user thermistors
+ LOOP_L_N(i, USER_THERMISTORS)
+ thermalManager.log_user_thermistor(i);
+ }
+ else // ...one user thermistor
+ thermalManager.log_user_thermistor(t_index);
+}
+
+#endif // HAS_USER_THERMISTORS
diff --git a/Marlin/src/gcode/config/M43.cpp b/Marlin/src/gcode/config/M43.cpp
new file mode 100644
index 0000000..005fdf0
--- /dev/null
+++ b/Marlin/src/gcode/config/M43.cpp
@@ -0,0 +1,386 @@
+/**
+ * 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(PINS_DEBUGGING)
+
+#include "../gcode.h"
+#include "../../MarlinCore.h" // for pin_is_protected
+#include "../../pins/pinsDebug.h"
+#include "../../module/endstops.h"
+
+#if HAS_Z_SERVO_PROBE
+ #include "../../module/probe.h"
+ #include "../../module/servo.h"
+#endif
+
+#if ENABLED(BLTOUCH)
+ #include "../../feature/bltouch.h"
+#endif
+
+#if ENABLED(HOST_PROMPT_SUPPORT)
+ #include "../../feature/host_actions.h"
+#endif
+
+#if ENABLED(EXTENSIBLE_UI)
+ #include "../../lcd/extui/ui_api.h"
+#endif
+
+#if HAS_RESUME_CONTINUE
+ #include "../../lcd/marlinui.h"
+#endif
+
+#ifndef GET_PIN_MAP_PIN_M43
+ #define GET_PIN_MAP_PIN_M43(Q) GET_PIN_MAP_PIN(Q)
+#endif
+
+inline void toggle_pins() {
+ const bool ignore_protection = parser.boolval('I');
+ const int repeat = parser.intval('R', 1),
+ start = PARSED_PIN_INDEX('S', 0),
+ end = PARSED_PIN_INDEX('L', NUM_DIGITAL_PINS - 1),
+ wait = parser.intval('W', 500);
+
+ LOOP_S_LE_N(i, start, end) {
+ pin_t pin = GET_PIN_MAP_PIN_M43(i);
+ if (!VALID_PIN(pin)) continue;
+ if (M43_NEVER_TOUCH(i) || (!ignore_protection && pin_is_protected(pin))) {
+ report_pin_state_extended(pin, ignore_protection, true, PSTR("Untouched "));
+ SERIAL_EOL();
+ }
+ else {
+ watchdog_refresh();
+ report_pin_state_extended(pin, ignore_protection, true, PSTR("Pulsing "));
+ #ifdef __STM32F1__
+ const auto prior_mode = _GET_MODE(i);
+ #else
+ const bool prior_mode = GET_PINMODE(pin);
+ #endif
+ #if AVR_AT90USB1286_FAMILY // Teensy IDEs don't know about these pins so must use FASTIO
+ if (pin == TEENSY_E2) {
+ SET_OUTPUT(TEENSY_E2);
+ for (int16_t j = 0; j < repeat; j++) {
+ WRITE(TEENSY_E2, LOW); safe_delay(wait);
+ WRITE(TEENSY_E2, HIGH); safe_delay(wait);
+ WRITE(TEENSY_E2, LOW); safe_delay(wait);
+ }
+ }
+ else if (pin == TEENSY_E3) {
+ SET_OUTPUT(TEENSY_E3);
+ for (int16_t j = 0; j < repeat; j++) {
+ WRITE(TEENSY_E3, LOW); safe_delay(wait);
+ WRITE(TEENSY_E3, HIGH); safe_delay(wait);
+ WRITE(TEENSY_E3, LOW); safe_delay(wait);
+ }
+ }
+ else
+ #endif
+ {
+ pinMode(pin, OUTPUT);
+ for (int16_t j = 0; j < repeat; j++) {
+ watchdog_refresh(); extDigitalWrite(pin, 0); safe_delay(wait);
+ watchdog_refresh(); extDigitalWrite(pin, 1); safe_delay(wait);
+ watchdog_refresh(); extDigitalWrite(pin, 0); safe_delay(wait);
+ watchdog_refresh();
+ }
+ }
+ #ifdef __STM32F1__
+ _SET_MODE(i, prior_mode);
+ #else
+ pinMode(pin, prior_mode);
+ #endif
+ }
+ SERIAL_EOL();
+ }
+ SERIAL_ECHOLNPGM("Done.");
+
+} // toggle_pins
+
+inline void servo_probe_test() {
+
+ #if !(NUM_SERVOS > 0 && HAS_SERVO_0)
+
+ SERIAL_ERROR_MSG("SERVO not set up.");
+
+ #elif !HAS_Z_SERVO_PROBE
+
+ SERIAL_ERROR_MSG("Z_PROBE_SERVO_NR not set up.");
+
+ #else // HAS_Z_SERVO_PROBE
+
+ const uint8_t probe_index = parser.byteval('P', Z_PROBE_SERVO_NR);
+
+ SERIAL_ECHOLNPAIR("Servo probe test\n"
+ ". using index: ", int(probe_index),
+ ", deploy angle: ", servo_angles[probe_index][0],
+ ", stow angle: ", servo_angles[probe_index][1]
+ );
+
+ bool deploy_state = false, stow_state;
+
+ #if ENABLED(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN)
+
+ #define PROBE_TEST_PIN Z_MIN_PIN
+ constexpr bool probe_inverting = Z_MIN_ENDSTOP_INVERTING;
+
+ SERIAL_ECHOLNPAIR(". Probe Z_MIN_PIN: ", int(PROBE_TEST_PIN));
+ SERIAL_ECHOPGM(". Z_MIN_ENDSTOP_INVERTING: ");
+
+ #else
+
+ #define PROBE_TEST_PIN Z_MIN_PROBE_PIN
+ constexpr bool probe_inverting = Z_MIN_PROBE_ENDSTOP_INVERTING;
+
+ SERIAL_ECHOLNPAIR(". Probe Z_MIN_PROBE_PIN: ", int(PROBE_TEST_PIN));
+ SERIAL_ECHOPGM( ". Z_MIN_PROBE_ENDSTOP_INVERTING: ");
+
+ #endif
+
+ serialprint_truefalse(probe_inverting);
+ SERIAL_EOL();
+
+ SET_INPUT_PULLUP(PROBE_TEST_PIN);
+
+ // First, check for a probe that recognizes an advanced BLTouch sequence.
+ // In addition to STOW and DEPLOY, it uses SW MODE (and RESET in the beginning)
+ // to see if this is one of the following: BLTOUCH Classic 1.2, 1.3, or
+ // BLTouch Smart 1.0, 2.0, 2.2, 3.0, 3.1. But only if the user has actually
+ // configured a BLTouch as being present. If the user has not configured this,
+ // the BLTouch will be detected in the last phase of these tests (see further on).
+ bool blt = false;
+ // This code will try to detect a BLTouch probe or clone
+ #if ENABLED(BLTOUCH)
+ SERIAL_ECHOLNPGM(". Check for BLTOUCH");
+ bltouch._reset();
+ bltouch._stow();
+ if (probe_inverting == READ(PROBE_TEST_PIN)) {
+ bltouch._set_SW_mode();
+ if (probe_inverting != READ(PROBE_TEST_PIN)) {
+ bltouch._deploy();
+ if (probe_inverting == READ(PROBE_TEST_PIN)) {
+ bltouch._stow();
+ SERIAL_ECHOLNPGM("= BLTouch Classic 1.2, 1.3, Smart 1.0, 2.0, 2.2, 3.0, 3.1 detected.");
+ // Check for a 3.1 by letting the user trigger it, later
+ blt = true;
+ }
+ }
+ }
+ #endif
+
+ // The following code is common to all kinds of servo probes.
+ // Since it could be a real servo or a BLTouch (any kind) or a clone,
+ // use only "common" functions - i.e. SERVO_MOVE. No bltouch.xxxx stuff.
+
+ // If it is already recognised as a being a BLTouch, no need for this test
+ if (!blt) {
+ // DEPLOY and STOW 4 times and see if the signal follows
+ // Then it is a mechanical switch
+ uint8_t i = 0;
+ SERIAL_ECHOLNPGM(". Deploy & stow 4 times");
+ do {
+ MOVE_SERVO(probe_index, servo_angles[Z_PROBE_SERVO_NR][0]); // Deploy
+ safe_delay(500);
+ deploy_state = READ(PROBE_TEST_PIN);
+ MOVE_SERVO(probe_index, servo_angles[Z_PROBE_SERVO_NR][1]); // Stow
+ safe_delay(500);
+ stow_state = READ(PROBE_TEST_PIN);
+ } while (++i < 4);
+
+ if (probe_inverting != deploy_state) SERIAL_ECHOLNPGM("WARNING: INVERTING setting probably backwards.");
+
+ if (deploy_state != stow_state) {
+ SERIAL_ECHOLNPGM("= Mechanical Switch detected");
+ if (deploy_state) {
+ SERIAL_ECHOLNPAIR(" DEPLOYED state: HIGH (logic 1)",
+ " STOWED (triggered) state: LOW (logic 0)");
+ }
+ else {
+ SERIAL_ECHOLNPAIR(" DEPLOYED state: LOW (logic 0)",
+ " STOWED (triggered) state: HIGH (logic 1)");
+ }
+ #if ENABLED(BLTOUCH)
+ SERIAL_ECHOLNPGM("FAIL: BLTOUCH enabled - Set up this device as a Servo Probe with INVERTING set to 'true'.");
+ #endif
+ return;
+ }
+ }
+
+ // Ask the user for a trigger event and measure the pulse width.
+ MOVE_SERVO(probe_index, servo_angles[Z_PROBE_SERVO_NR][0]); // Deploy
+ safe_delay(500);
+ SERIAL_ECHOLNPGM("** Please trigger probe within 30 sec **");
+ uint16_t probe_counter = 0;
+
+ // Wait 30 seconds for user to trigger probe
+ for (uint16_t j = 0; j < 500 * 30 && probe_counter == 0 ; j++) {
+ safe_delay(2);
+
+ if (0 == j % (500 * 1)) gcode.reset_stepper_timeout(); // Keep steppers powered
+
+ if (deploy_state != READ(PROBE_TEST_PIN)) { // probe triggered
+ for (probe_counter = 0; probe_counter < 15 && deploy_state != READ(PROBE_TEST_PIN); ++probe_counter) safe_delay(2);
+
+ SERIAL_ECHOPGM(". Pulse width");
+ if (probe_counter == 15)
+ SERIAL_ECHOLNPGM(": 30ms or more");
+ else
+ SERIAL_ECHOLNPAIR(" (+/- 4ms): ", probe_counter * 2);
+
+ if (probe_counter >= 4) {
+ if (probe_counter == 15) {
+ if (blt) SERIAL_ECHOPGM("= BLTouch V3.1");
+ else SERIAL_ECHOPGM("= Z Servo Probe");
+ }
+ else SERIAL_ECHOPGM("= BLTouch pre V3.1 (or compatible)");
+ SERIAL_ECHOLNPGM(" detected.");
+ }
+ else SERIAL_ECHOLNPGM("FAIL: Noise detected - please re-run test");
+
+ MOVE_SERVO(probe_index, servo_angles[Z_PROBE_SERVO_NR][1]); // Stow
+ return;
+ }
+ }
+
+ if (!probe_counter) SERIAL_ECHOLNPGM("FAIL: No trigger detected");
+
+ #endif // HAS_Z_SERVO_PROBE
+
+} // servo_probe_test
+
+/**
+ * M43: Pin debug - report pin state, watch pins, toggle pins and servo probe test/report
+ *
+ * M43 - report name and state of pin(s)
+ * P<pin> Pin to read or watch. If omitted, reads all pins.
+ * I Flag to ignore Marlin's pin protection.
+ *
+ * M43 W - Watch pins -reporting changes- until reset, click, or M108.
+ * P<pin> Pin to read or watch. If omitted, read/watch all pins.
+ * I Flag to ignore Marlin's pin protection.
+ *
+ * M43 E<bool> - Enable / disable background endstop monitoring
+ * - Machine continues to operate
+ * - Reports changes to endstops
+ * - Toggles LED_PIN when an endstop changes
+ * - Cannot reliably catch the 5mS pulse from BLTouch type probes
+ *
+ * M43 T - Toggle pin(s) and report which pin is being toggled
+ * S<pin> - Start Pin number. If not given, will default to 0
+ * L<pin> - End Pin number. If not given, will default to last pin defined for this board
+ * I<bool> - Flag to ignore Marlin's pin protection. Use with caution!!!!
+ * R - Repeat pulses on each pin this number of times before continueing to next pin
+ * W - Wait time (in miliseconds) between pulses. If not given will default to 500
+ *
+ * M43 S - Servo probe test
+ * P<index> - Probe index (optional - defaults to 0
+ */
+void GcodeSuite::M43() {
+
+ // 'T' must be first. It uses 'S' and 'E' differently.
+ if (parser.seen('T')) return toggle_pins();
+
+ // 'E' Enable or disable endstop monitoring and return
+ if (parser.seen('E')) {
+ endstops.monitor_flag = parser.value_bool();
+ SERIAL_ECHOPGM("endstop monitor ");
+ serialprintPGM(endstops.monitor_flag ? PSTR("en") : PSTR("dis"));
+ SERIAL_ECHOLNPGM("abled");
+ return;
+ }
+
+ // 'S' Run servo probe test and return
+ if (parser.seen('S')) return servo_probe_test();
+
+ // 'P' Get the range of pins to test or watch
+ uint8_t first_pin = PARSED_PIN_INDEX('P', 0),
+ last_pin = parser.seenval('P') ? first_pin : NUMBER_PINS_TOTAL - 1;
+
+ if (first_pin > last_pin) return;
+
+ // 'I' to ignore protected pins
+ const bool ignore_protection = parser.boolval('I');
+
+ // 'W' Watch until click, M108, or reset
+ if (parser.boolval('W')) {
+ SERIAL_ECHOLNPGM("Watching pins");
+ #ifdef ARDUINO_ARCH_SAM
+ NOLESS(first_pin, 2); // Don't hijack the UART pins
+ #endif
+ uint8_t pin_state[last_pin - first_pin + 1];
+ LOOP_S_LE_N(i, first_pin, last_pin) {
+ pin_t pin = GET_PIN_MAP_PIN_M43(i);
+ if (!VALID_PIN(pin)) continue;
+ if (M43_NEVER_TOUCH(i) || (!ignore_protection && pin_is_protected(pin))) continue;
+ pinMode(pin, INPUT_PULLUP);
+ delay(1);
+ /*
+ if (IS_ANALOG(pin))
+ pin_state[pin - first_pin] = analogRead(DIGITAL_PIN_TO_ANALOG_PIN(pin)); // int16_t pin_state[...]
+ else
+ //*/
+ pin_state[i - first_pin] = extDigitalRead(pin);
+ }
+
+ #if HAS_RESUME_CONTINUE
+ KEEPALIVE_STATE(PAUSED_FOR_USER);
+ wait_for_user = true;
+ TERN_(HOST_PROMPT_SUPPORT, host_prompt_do(PROMPT_USER_CONTINUE, PSTR("M43 Wait Called"), CONTINUE_STR));
+ TERN_(EXTENSIBLE_UI, ExtUI::onUserConfirmRequired_P(PSTR("M43 Wait Called")));
+ #endif
+
+ for (;;) {
+ LOOP_S_LE_N(i, first_pin, last_pin) {
+ pin_t pin = GET_PIN_MAP_PIN_M43(i);
+ if (!VALID_PIN(pin)) continue;
+ if (M43_NEVER_TOUCH(i) || (!ignore_protection && pin_is_protected(pin))) continue;
+ const byte val =
+ /*
+ IS_ANALOG(pin)
+ ? analogRead(DIGITAL_PIN_TO_ANALOG_PIN(pin)) : // int16_t val
+ :
+ //*/
+ extDigitalRead(pin);
+ if (val != pin_state[i - first_pin]) {
+ report_pin_state_extended(pin, ignore_protection, false);
+ pin_state[i - first_pin] = val;
+ }
+ }
+
+ #if HAS_RESUME_CONTINUE
+ ui.update();
+ if (!wait_for_user) break;
+ #endif
+
+ safe_delay(200);
+ }
+ }
+ else {
+ // Report current state of selected pin(s)
+ LOOP_S_LE_N(i, first_pin, last_pin) {
+ pin_t pin = GET_PIN_MAP_PIN_M43(i);
+ if (VALID_PIN(pin)) report_pin_state_extended(pin, ignore_protection, true);
+ }
+ }
+}
+
+#endif // PINS_DEBUGGING
diff --git a/Marlin/src/gcode/config/M540.cpp b/Marlin/src/gcode/config/M540.cpp
new file mode 100644
index 0000000..54d52f3
--- /dev/null
+++ b/Marlin/src/gcode/config/M540.cpp
@@ -0,0 +1,40 @@
+/**
+ * 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(SD_ABORT_ON_ENDSTOP_HIT)
+
+#include "../gcode.h"
+#include "../../module/stepper.h"
+
+/**
+ * M540: Set whether SD card print should abort on endstop hit (M540 S<0|1>)
+ */
+void GcodeSuite::M540() {
+
+ if (parser.seen('S'))
+ planner.abort_on_endstop_hit = parser.value_bool();
+
+}
+
+#endif // SD_ABORT_ON_ENDSTOP_HIT
diff --git a/Marlin/src/gcode/config/M575.cpp b/Marlin/src/gcode/config/M575.cpp
new file mode 100644
index 0000000..44723b7
--- /dev/null
+++ b/Marlin/src/gcode/config/M575.cpp
@@ -0,0 +1,75 @@
+/**
+ * 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(BAUD_RATE_GCODE)
+
+#include "../gcode.h"
+
+/**
+ * M575 - Change serial baud rate
+ *
+ * P<index> - Serial port index. Omit for all.
+ * B<baudrate> - Baud rate (bits per second)
+ */
+void GcodeSuite::M575() {
+ int32_t baud = parser.ulongval('B');
+ switch (baud) {
+ case 24:
+ case 96:
+ case 192:
+ case 384:
+ case 576:
+ case 1152: baud *= 100; break;
+ case 250:
+ case 500: baud *= 1000; break;
+ case 19: baud = 19200; break;
+ case 38: baud = 38400; break;
+ case 57: baud = 57600; break;
+ case 115: baud = 115200; break;
+ }
+ switch (baud) {
+ case 2400: case 9600: case 19200: case 38400: case 57600:
+ case 115200: case 250000: case 500000: case 1000000: {
+ const int8_t port = parser.intval('P', -99);
+ const bool set0 = (port == -99 || port == 0);
+ if (set0) SERIAL_ECHO_MSG(" Serial ", '0', " baud rate set to ", baud);
+ #if HAS_MULTI_SERIAL
+ const bool set1 = (port == -99 || port == 1);
+ if (set1) SERIAL_ECHO_MSG(" Serial ", '1', " baud rate set to ", baud);
+ #endif
+
+ SERIAL_FLUSH();
+
+ if (set0) { MYSERIAL0.end(); MYSERIAL0.begin(baud); }
+
+ #if HAS_MULTI_SERIAL
+ if (set1) { MYSERIAL1.end(); MYSERIAL1.begin(baud); }
+ #endif
+
+ } break;
+ default: SERIAL_ECHO_MSG("?(B)aud rate implausible.");
+ }
+}
+
+#endif // BAUD_RATE_GCODE
diff --git a/Marlin/src/gcode/config/M672.cpp b/Marlin/src/gcode/config/M672.cpp
new file mode 100644
index 0000000..af74230
--- /dev/null
+++ b/Marlin/src/gcode/config/M672.cpp
@@ -0,0 +1,98 @@
+/**
+ * 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(DUET_SMART_EFFECTOR) && PIN_EXISTS(SMART_EFFECTOR_MOD)
+
+#include "../gcode.h"
+#include "../../HAL/shared/Delay.h"
+#include "../parser.h"
+
+/**
+ * The Marlin format for the M672 command is different than shown in the Duet Smart Effector
+ * documentation https://duet3d.dozuki.com/Wiki/Smart_effector_and_carriage_adapters_for_delta_printer
+ *
+ * To set custom sensitivity:
+ * Duet: M672 S105:aaa:bbb
+ * Marlin: M672 Saaa
+ *
+ * (where aaa is the desired sensitivity and bbb is 255 - aaa).
+ *
+ * Revert sensitivity to factory settings:
+ * Duet: M672 S105:131:131
+ * Marlin: M672 R
+ */
+
+#define M672_PROGBYTE 105 // magic byte to start programming custom sensitivity
+#define M672_ERASEBYTE 131 // magic byte to clear custom sensitivity
+
+//
+// Smart Effector byte send protocol:
+//
+// 0 0 1 0 ... always 0010
+// b7 b6 b5 b4 ~b4 ... hi bits, NOT last bit
+// b3 b2 b1 b0 ~b0 ... lo bits, NOT last bit
+//
+void M672_send(uint8_t b) { // bit rate requirement: 1KHz +/- 30%
+ LOOP_L_N(bits, 14) {
+ switch (bits) {
+ default: { OUT_WRITE(SMART_EFFECTOR_MOD_PIN, !!(b & 0x80)); b <<= 1; break; } // send bit, shift next into place
+ case 7:
+ case 12: { OUT_WRITE(SMART_EFFECTOR_MOD_PIN, !!(b & 0x80)); break; } // send bit. no shift
+ case 8:
+ case 13: { OUT_WRITE(SMART_EFFECTOR_MOD_PIN, !(b & 0x80)); b <<= 1; break; } // send inverted previous bit
+ case 0: case 1: // 00
+ case 3: { OUT_WRITE(SMART_EFFECTOR_MOD_PIN, LOW); break; } // 0010
+ case 2: { OUT_WRITE(SMART_EFFECTOR_MOD_PIN, HIGH); break; } // 001
+ }
+ DELAY_US(1000);
+ }
+}
+
+/**
+ * M672 - Set/reset Duet Smart Effector sensitivity
+ *
+ * One of these is required:
+ * S<sensitivity> - 0-255
+ * R - Flag to reset sensitivity to default
+ */
+void GcodeSuite::M672() {
+ if (parser.seen('R')) {
+ M672_send(M672_ERASEBYTE);
+ M672_send(M672_ERASEBYTE);
+ }
+ else if (parser.seenval('S')) {
+ const int8_t M672_sensitivity = parser.value_byte();
+ M672_send(M672_PROGBYTE);
+ M672_send(M672_sensitivity);
+ M672_send(255 - M672_sensitivity);
+ }
+ else {
+ SERIAL_ECHO_MSG("!'S' or 'R' parameter required.");
+ return;
+ }
+
+ OUT_WRITE(SMART_EFFECTOR_MOD_PIN, LOW); // Keep Smart Effector in NORMAL mode
+}
+
+#endif // DUET_SMART_EFFECTOR && SMART_EFFECTOR_MOD_PIN
diff --git a/Marlin/src/gcode/config/M92.cpp b/Marlin/src/gcode/config/M92.cpp
new file mode 100644
index 0000000..0a7d52b
--- /dev/null
+++ b/Marlin/src/gcode/config/M92.cpp
@@ -0,0 +1,114 @@
+/**
+ * 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/planner.h"
+
+void report_M92(const bool echo=true, const int8_t e=-1) {
+ if (echo) SERIAL_ECHO_START(); else SERIAL_CHAR(' ');
+ SERIAL_ECHOPAIR_P(PSTR(" M92 X"), LINEAR_UNIT(planner.settings.axis_steps_per_mm[X_AXIS]),
+ SP_Y_STR, LINEAR_UNIT(planner.settings.axis_steps_per_mm[Y_AXIS]),
+ SP_Z_STR, LINEAR_UNIT(planner.settings.axis_steps_per_mm[Z_AXIS]));
+ #if DISABLED(DISTINCT_E_FACTORS)
+ SERIAL_ECHOPAIR_P(SP_E_STR, VOLUMETRIC_UNIT(planner.settings.axis_steps_per_mm[E_AXIS]));
+ #endif
+ SERIAL_EOL();
+
+ #if ENABLED(DISTINCT_E_FACTORS)
+ LOOP_L_N(i, E_STEPPERS) {
+ if (e >= 0 && i != e) continue;
+ if (echo) SERIAL_ECHO_START(); else SERIAL_CHAR(' ');
+ SERIAL_ECHOLNPAIR_P(PSTR(" M92 T"), (int)i,
+ SP_E_STR, VOLUMETRIC_UNIT(planner.settings.axis_steps_per_mm[E_AXIS_N(i)]));
+ }
+ #endif
+
+ UNUSED_E(e);
+}
+
+/**
+ * M92: Set axis steps-per-unit for one or more axes, X, Y, Z, and E.
+ * (Follows the same syntax as G92)
+ *
+ * With multiple extruders use T to specify which one.
+ *
+ * If no argument is given print the current values.
+ *
+ * With MAGIC_NUMBERS_GCODE:
+ * Use 'H' and/or 'L' to get ideal layer-height information.
+ * 'H' specifies micro-steps to use. We guess if it's not supplied.
+ * 'L' specifies a desired layer height. Nearest good heights are shown.
+ */
+void GcodeSuite::M92() {
+
+ const int8_t target_extruder = get_target_extruder_from_command();
+ if (target_extruder < 0) return;
+
+ // No arguments? Show M92 report.
+ if (!parser.seen("XYZE"
+ #if ENABLED(MAGIC_NUMBERS_GCODE)
+ "HL"
+ #endif
+ )) return report_M92(true, target_extruder);
+
+ LOOP_XYZE(i) {
+ if (parser.seenval(axis_codes[i])) {
+ if (i == E_AXIS) {
+ const float value = parser.value_per_axis_units((AxisEnum)(E_AXIS_N(target_extruder)));
+ if (value < 20) {
+ float factor = planner.settings.axis_steps_per_mm[E_AXIS_N(target_extruder)] / value; // increase e constants if M92 E14 is given for netfab.
+ #if HAS_CLASSIC_JERK && HAS_CLASSIC_E_JERK
+ planner.max_jerk.e *= factor;
+ #endif
+ planner.settings.max_feedrate_mm_s[E_AXIS_N(target_extruder)] *= factor;
+ planner.max_acceleration_steps_per_s2[E_AXIS_N(target_extruder)] *= factor;
+ }
+ planner.settings.axis_steps_per_mm[E_AXIS_N(target_extruder)] = value;
+ }
+ else {
+ planner.settings.axis_steps_per_mm[i] = parser.value_per_axis_units((AxisEnum)i);
+ }
+ }
+ }
+ planner.refresh_positioning();
+
+ #if ENABLED(MAGIC_NUMBERS_GCODE)
+ #ifndef Z_MICROSTEPS
+ #define Z_MICROSTEPS 16
+ #endif
+ const float wanted = parser.floatval('L');
+ if (parser.seen('H') || wanted) {
+ const uint16_t argH = parser.ushortval('H'),
+ micro_steps = argH ?: Z_MICROSTEPS;
+ const float z_full_step_mm = micro_steps * planner.steps_to_mm[Z_AXIS];
+ SERIAL_ECHO_START();
+ SERIAL_ECHOPAIR("{ micro_steps:", micro_steps, ", z_full_step_mm:", z_full_step_mm);
+ if (wanted) {
+ const float best = uint16_t(wanted / z_full_step_mm) * z_full_step_mm;
+ SERIAL_ECHOPAIR(", best:[", best);
+ if (best != wanted) { SERIAL_CHAR(','); SERIAL_DECIMAL(best + z_full_step_mm); }
+ SERIAL_CHAR(']');
+ }
+ SERIAL_ECHOLNPGM(" }");
+ }
+ #endif
+}