From 0fca084ea688aed41b892f9cea7e069510c73c94 Mon Sep 17 00:00:00 2001
From: Scott Lahteine <sourcetree@thinkyhead.com>
Date: Sun, 26 Apr 2015 18:44:01 -0700
Subject: [PATCH] Make EEPROM reproducible in GCode
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

With these changes the output of `M503 S0` is all you need to restore
the EEPROM. Building on this it is straightforward to save and restore
the EEPROM state using the SD card or external GCode file.

- Added `M145` to set “heatup states” for the LCD menu
- Added `M420` to toggle Mesh Bed Leveling
- Added `M421` to set a single Mesh coordinate
- Extended `Config_PrintSettings` with added M codes
- Cleaned up some comments here and there
---
 Marlin/Configuration_adv.h                    |   2 +-
 Marlin/Marlin_main.cpp                        | 153 +++++++-
 Marlin/configuration_store.cpp                | 334 +++++++++++-------
 .../configurator/config/Configuration_adv.h   |   2 +-
 Marlin/configurator/config/language.h         |   5 +-
 .../Felix/Configuration_adv.h                 |   2 +-
 .../Hephestos/Configuration_adv.h             |   2 +-
 .../K8200/Configuration_adv.h                 |   2 +-
 .../SCARA/Configuration_adv.h                 |   2 +-
 .../WITBOX/Configuration_adv.h                |   2 +-
 .../delta/generic/Configuration_adv.h         |   2 +-
 .../delta/kossel_mini/Configuration_adv.h     |   2 +-
 .../makibox/Configuration_adv.h               |   2 +-
 .../tvrrug/Round2/Configuration_adv.h         |   2 +-
 Marlin/language.h                             |   3 +
 Marlin/planner.cpp                            | 139 ++++----
 Marlin/planner.h                              |  14 +-
 Marlin/temperature.cpp                        |   5 +-
 Marlin/ultralcd.cpp                           |   8 +-
 Marlin/watchdog.cpp                           |   6 +-
 20 files changed, 454 insertions(+), 235 deletions(-)

diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h
index 6478eb923e9..059f0c5c162 100644
--- a/Marlin/Configuration_adv.h
+++ b/Marlin/Configuration_adv.h
@@ -355,7 +355,7 @@ const unsigned int dropsegments=5; //everything with less than this number of st
 //#define HEATERS_PARALLEL
 
 //===========================================================================
-//=============================Buffers           ============================
+//================================= Buffers =================================
 //===========================================================================
 
 // @section hidden
diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp
index ac86cb05b7e..cbeb9a09121 100644
--- a/Marlin/Marlin_main.cpp
+++ b/Marlin/Marlin_main.cpp
@@ -151,6 +151,7 @@
  * M128 - EtoP Open (BariCUDA EtoP = electricity to air pressure transducer by jmil)
  * M129 - EtoP Closed (BariCUDA EtoP = electricity to air pressure transducer by jmil)
  * M140 - Set bed target temp
+ * M145 - Set the heatup state H<hotend> B<bed> F<fan speed> for S<material> (0=PLA, 1=ABS)
  * M150 - Set BlinkM Color Output R: Red<0-255> U(!): Green<0-255> B: Blue<0-255> over i2c, G for green does not work.
  * M190 - Sxxx Wait for bed current temp to reach target temp. Waits only when heating
  *        Rxxx Wait for bed current temp to reach target temp. Waits when heating and cooling
@@ -186,6 +187,8 @@
  * M406 - Turn off Filament Sensor extrusion control
  * M407 - Display measured filament diameter
  * M410 - Quickstop. Abort all the planned moves
+ * M420 - Enable/Disable Mesh Leveling (with current values) S1=enable S0=disable
+ * M421 - Set a single Z coordinate in the Mesh Leveling grid. X<index> Y<index> Z<offset in mm>
  * M500 - Store parameters in EEPROM
  * M501 - Read parameters from EEPROM (if you need reset them after you changed them temporarily).
  * M502 - Revert to the default "factory settings". You still need to store them in EEPROM afterwards if you want to.
@@ -3385,6 +3388,62 @@ inline void gcode_M140() {
   if (code_seen('S')) setTargetBed(code_value());
 }
 
+#ifdef ULTIPANEL
+
+  /**
+   * M145: Set the heatup state for a material in the LCD menu
+   *   S<material> (0=PLA, 1=ABS)
+   *   H<hotend temp>
+   *   B<bed temp>
+   *   F<fan speed>
+   */
+  inline void gcode_M145() {
+    uint8_t material = code_seen('S') ? code_value_short() : 0;
+    if (material < 0 || material > 1) {
+      SERIAL_ERROR_START;
+      SERIAL_ERRORLNPGM(MSG_ERR_MATERIAL_INDEX);
+    }
+    else {
+      int v;
+      switch (material) {
+        case 0:
+          if (code_seen('H')) {
+            v = code_value_short();
+            plaPreheatHotendTemp = constrain(v, EXTRUDE_MINTEMP, HEATER_0_MAXTEMP - 15);
+          }
+          if (code_seen('F')) {
+            v = code_value_short();
+            plaPreheatFanSpeed = constrain(v, 0, 255);
+          }
+          #if TEMP_SENSOR_BED != 0
+            if (code_seen('B')) {
+              v = code_value_short();
+              plaPreheatHPBTemp = constrain(v, BED_MINTEMP, BED_MAXTEMP - 15);
+            }
+          #endif
+          break;
+        case 1:
+          if (code_seen('H')) {
+            v = code_value_short();
+            absPreheatHotendTemp = constrain(v, EXTRUDE_MINTEMP, HEATER_0_MAXTEMP - 15);
+          }
+          if (code_seen('F')) {
+            v = code_value_short();
+            absPreheatFanSpeed = constrain(v, 0, 255);
+          }
+          #if TEMP_SENSOR_BED != 0
+            if (code_seen('B')) {
+              v = code_value_short();
+              absPreheatHPBTemp = constrain(v, BED_MINTEMP, BED_MAXTEMP - 15);
+            }
+          #endif
+          break;
+      }
+    }
+  }
+
+#endif
+
 #if HAS_POWER_SWITCH
 
   /**
@@ -3492,7 +3551,8 @@ inline void gcode_M85() {
 }
 
 /**
- * M92: Set inactivity shutdown timer with parameter S<seconds>. To disable set zero (default)
+ * M92: Set axis steps-per-unit for one or more axes, X, Y, Z, and E.
+ *      (Follows the same syntax as G92)
  */
 inline void gcode_M92() {
   for(int8_t i=0; i < NUM_AXIS; i++) {
@@ -3814,20 +3874,35 @@ inline void gcode_M206() {
 #ifdef FWRETRACT
 
   /**
-   * M207: Set retract length S[positive mm] F[feedrate mm/min] Z[additional zlift/hop]
+   * M207: Set firmware retraction values
+   *
+   *   S[+mm]    retract_length
+   *   W[+mm]    retract_length_swap (multi-extruder)
+   *   F[mm/min] retract_feedrate
+   *   Z[mm]     retract_zlift
    */
   inline void gcode_M207() {
     if (code_seen('S')) retract_length = code_value();
     if (code_seen('F')) retract_feedrate = code_value() / 60;
     if (code_seen('Z')) retract_zlift = code_value();
+    #if EXTRUDERS > 1
+      if (code_seen('W')) retract_length_swap = code_value();
+    #endif
   }
 
   /**
-   * M208: Set retract recover length S[positive mm surplus to the M207 S*] F[feedrate mm/min]
+   * M208: Set firmware un-retraction values
+   *
+   *   S[+mm]    retract_recover_length (in addition to M207 S*)
+   *   W[+mm]    retract_recover_length_swap (multi-extruder)
+   *   F[mm/min] retract_recover_feedrate
    */
   inline void gcode_M208() {
     if (code_seen('S')) retract_recover_length = code_value();
     if (code_seen('F')) retract_recover_feedrate = code_value() / 60;
+    #if EXTRUDERS > 1
+      if (code_seen('W')) retract_recover_length_swap = code_value();
+    #endif
   }
 
   /**
@@ -4380,6 +4455,42 @@ inline void gcode_M400() { st_synchronize(); }
  */
 inline void gcode_M410() { quickStop(); }
 
+
+#ifdef MESH_BED_LEVELING
+
+  /**
+   * M420: Enable/Disable Mesh Bed Leveling
+   */
+  inline void gcode_M420() { if (code_seen('S') && code_has_value()) mbl.active = !!code_value_short(); }
+
+  /**
+   * M421: Set a single Mesh Bed Leveling Z coordinate
+   */
+  inline void gcode_M421() {
+    int x, y;
+    float z;
+    bool err = false, hasX, hasY, hasZ;
+    if ((hasX = code_seen('X'))) x = code_value_short();
+    if ((hasY = code_seen('Y'))) y = code_value_short();
+    if ((hasZ = code_seen('Z'))) z = code_value();
+
+    if (!hasX || !hasY || !hasZ) {
+      SERIAL_ERROR_START;
+      SERIAL_ERRORLNPGM(MSG_ERR_XYZ_REQUIRED_FOR_M421);
+      err = true;
+    }
+
+    if (x >= MESH_NUM_X_POINTS || y >= MESH_NUM_Y_POINTS) {
+      SERIAL_ERROR_START;
+      SERIAL_ERRORLNPGM(MSG_ERR_MESH_INDEX_OOB);
+      err = true;
+    }
+
+    if (!err) mbl.z_values[y][x] = z;
+  }
+
+#endif
+
 /**
  * M500: Store settings in EEPROM
  */
@@ -4934,11 +5045,11 @@ void process_commands() {
         gcode_M104();
         break;
 
-      case 111: //  M111: Set debug level
+      case 111: // M111: Set debug level
         gcode_M111();
         break;
 
-      case 112: //  M112: Emergency Stop
+      case 112: // M112: Emergency Stop
         gcode_M112();
         break;
 
@@ -5017,28 +5128,35 @@ void process_commands() {
       case 85: // M85
         gcode_M85();
         break;
-      case 92: // M92
+      case 92: // M92: Set the steps-per-unit for one or more axes
         gcode_M92();
         break;
-      case 115: // M115
+      case 115: // M115: Report capabilities
         gcode_M115();
         break;
-      case 117: // M117 display message
+      case 117: // M117: Set LCD message text
         gcode_M117();
         break;
-      case 114: // M114
+      case 114: // M114: Report current position
         gcode_M114();
         break;
-      case 120: // M120
+      case 120: // M120: Enable endstops
         gcode_M120();
         break;
-      case 121: // M121
+      case 121: // M121: Disable endstops
         gcode_M121();
         break;
-      case 119: // M119
+      case 119: // M119: Report endstop states
         gcode_M119();
         break;
-        //TODO: update for all axis, use for loop
+
+      #ifdef ULTIPANEL
+
+        case 145: // M145: Set material heatup parameters
+          gcode_M145();
+          break;
+
+      #endif
 
       #ifdef BLINKM
 
@@ -5213,6 +5331,15 @@ void process_commands() {
         gcode_M410();
         break;
 
+      #ifdef MESH_BED_LEVELING
+        case 420: // M420 Enable/Disable Mesh Bed Leveling
+          gcode_M420();
+          break;
+        case 421: // M421 Set a Mesh Bed Leveling Z coordinate
+          gcode_M421();
+          break;
+      #endif
+
       case 500: // M500 Store settings in EEPROM
         gcode_M500();
         break;
diff --git a/Marlin/configuration_store.cpp b/Marlin/configuration_store.cpp
index 9f91db09857..318501db623 100644
--- a/Marlin/configuration_store.cpp
+++ b/Marlin/configuration_store.cpp
@@ -20,72 +20,72 @@
  * V19 EEPROM Layout:
  *
  *  ver
- *  axis_steps_per_unit (x4)
- *  max_feedrate (x4)
- *  max_acceleration_units_per_sq_second (x4)
- *  acceleration
- *  retract_acceleration
- *  travel_acceleration
- *  minimumfeedrate
- *  mintravelfeedrate
- *  minsegmenttime
- *  max_xy_jerk
- *  max_z_jerk
- *  max_e_jerk
- *  home_offset (x3)
+ *  M92 XYZE  axis_steps_per_unit (x4)
+ *  M203 XYZE max_feedrate (x4)
+ *  M201 XYZE max_acceleration_units_per_sq_second (x4)
+ *  M204 P    acceleration
+ *  M204 R    retract_acceleration
+ *  M204 T    travel_acceleration
+ *  M205 S    minimumfeedrate
+ *  M205 T    mintravelfeedrate
+ *  M205 B    minsegmenttime
+ *  M205 X    max_xy_jerk
+ *  M205 Z    max_z_jerk
+ *  M205 E    max_e_jerk
+ *  M206 XYZ  home_offset (x3)
  *
  * Mesh bed leveling:
- *  active
- *  mesh_num_x
- *  mesh_num_y
- *  z_values[][]
- *  zprobe_zoffset
+ *  M420 S    active
+ *            mesh_num_x (set in firmware)
+ *            mesh_num_y (set in firmware)
+ *  M421 XYZ  z_values[][]
+ *  M851      zprobe_zoffset
  *
  * DELTA:
- *  endstop_adj (x3)
- *  delta_radius
- *  delta_diagonal_rod
- *  delta_segments_per_second
+ *  M666 XYZ  endstop_adj (x3)
+ *  M665 R    delta_radius
+ *  M665 L    delta_diagonal_rod
+ *  M665 S    delta_segments_per_second
  *
  * ULTIPANEL:
- *  plaPreheatHotendTemp
- *  plaPreheatHPBTemp
- *  plaPreheatFanSpeed
- *  absPreheatHotendTemp
- *  absPreheatHPBTemp
- *  absPreheatFanSpeed
+ *  M145 S0 H plaPreheatHotendTemp
+ *  M145 S0 B plaPreheatHPBTemp
+ *  M145 S0 F plaPreheatFanSpeed
+ *  M145 S1 H absPreheatHotendTemp
+ *  M145 S1 B absPreheatHPBTemp
+ *  M145 S1 F absPreheatFanSpeed
  *
  * PIDTEMP:
- *  Kp[0], Ki[0], Kd[0], Kc[0]
- *  Kp[1], Ki[1], Kd[1], Kc[1]
- *  Kp[2], Ki[2], Kd[2], Kc[2]
- *  Kp[3], Ki[3], Kd[3], Kc[3]
+ *  M301 E0 PIDC  Kp[0], Ki[0], Kd[0], Kc[0]
+ *  M301 E1 PIDC  Kp[1], Ki[1], Kd[1], Kc[1]
+ *  M301 E2 PIDC  Kp[2], Ki[2], Kd[2], Kc[2]
+ *  M301 E3 PIDC  Kp[3], Ki[3], Kd[3], Kc[3]
  *
  * PIDTEMPBED:
- *  bedKp, bedKi, bedKd
+ *  M304 PID  bedKp, bedKi, bedKd
  *
  * DOGLCD:
- *  lcd_contrast
+ *  M250 C    lcd_contrast
  *
  * SCARA:
- *  axis_scaling (x3)
+ *  M365 XYZ  axis_scaling (x3)
  *
  * FWRETRACT:
- *  autoretract_enabled
- *  retract_length
- *  retract_length_swap
- *  retract_feedrate
- *  retract_zlift
- *  retract_recover_length
- *  retract_recover_length_swap
- *  retract_recover_feedrate
+ *  M209 S    autoretract_enabled
+ *  M207 S    retract_length
+ *  M207 W    retract_length_swap
+ *  M207 F    retract_feedrate
+ *  M207 Z    retract_zlift
+ *  M208 S    retract_recover_length
+ *  M208 W    retract_recover_length_swap
+ *  M208 F    retract_recover_feedrate
  *
- *  volumetric_enabled
+ *  M200 D    volumetric_enabled (D>0 makes this enabled)
  *
- *  filament_size (x4)
+ *  M200 T D  filament_size (x4) (T0..3)
  *
- * Z_DUAL_ENDSTOPS
- *  z_endstop_adj
+ * Z_DUAL_ENDSTOPS:
+ *  M666 Z    z_endstop_adj
  *
  */
 #include "Marlin.h"
@@ -122,7 +122,9 @@ void _EEPROM_readData(int &pos, uint8_t* value, uint8_t size) {
 #define EEPROM_WRITE_VAR(pos, value) _EEPROM_writeData(pos, (uint8_t*)&value, sizeof(value))
 #define EEPROM_READ_VAR(pos, value) _EEPROM_readData(pos, (uint8_t*)&value, sizeof(value))
 
-//======================================================================================
+/**
+ * Store Configuration Settings - M500
+ */
 
 #define DUMMY_PID_VALUE 3000.0f
 
@@ -235,7 +237,7 @@ void Config_StoreSettings()  {
   EEPROM_WRITE_VAR(i, bedKi);
   EEPROM_WRITE_VAR(i, bedKd);
 
-  #ifndef DOGLCD
+  #ifndef HAS_LCD_CONTRAST
     int lcd_contrast = 32;
   #endif
   EEPROM_WRITE_VAR(i, lcd_contrast);
@@ -286,6 +288,10 @@ void Config_StoreSettings()  {
   SERIAL_ECHOLNPGM(" bytes)");
 }
 
+/**
+ * Retrieve Configuration Settings - M501
+ */
+
 void Config_RetrieveSettings() {
 
   int i = EEPROM_OFFSET;
@@ -412,7 +418,7 @@ void Config_RetrieveSettings() {
       for (int q=2; q--;) EEPROM_READ_VAR(i, dummy); // bedKi, bedKd
     }
 
-    #ifndef DOGLCD
+    #ifndef HAS_LCD_CONTRAST
       int lcd_contrast;
     #endif
     EEPROM_READ_VAR(i, lcd_contrast);
@@ -467,6 +473,10 @@ void Config_RetrieveSettings() {
 
 #endif // EEPROM_SETTINGS
 
+/**
+ * Reset Configuration Settings - M502
+ */
+
 void Config_ResetDefault() {
   float tmp1[] = DEFAULT_AXIS_STEPS_PER_UNIT;
   float tmp2[] = DEFAULT_MAX_FEEDRATE;
@@ -522,7 +532,7 @@ void Config_ResetDefault() {
     absPreheatFanSpeed = ABS_PREHEAT_FAN_SPEED;
   #endif
 
-  #ifdef DOGLCD
+  #ifdef HAS_LCD_CONTRAST
     lcd_contrast = DEFAULT_LCD_CONTRAST;
   #endif
 
@@ -584,14 +594,20 @@ void Config_ResetDefault() {
 
 #ifndef DISABLE_M503
 
+/**
+ * Print Configuration Settings - M503
+ */
+
+#define CONFIG_ECHO_START do{ if (!forReplay) SERIAL_ECHO_START; }while(0)
+
 void Config_PrintSettings(bool forReplay) {
   // Always have this function, even with EEPROM_SETTINGS disabled, the current values will be shown
 
-  SERIAL_ECHO_START;
+  CONFIG_ECHO_START;
 
   if (!forReplay) {
     SERIAL_ECHOLNPGM("Steps per unit:");
-    SERIAL_ECHO_START;
+    CONFIG_ECHO_START;
   }
   SERIAL_ECHOPAIR("  M92 X", axis_steps_per_unit[X_AXIS]);
   SERIAL_ECHOPAIR(" Y", axis_steps_per_unit[Y_AXIS]);
@@ -599,23 +615,23 @@ void Config_PrintSettings(bool forReplay) {
   SERIAL_ECHOPAIR(" E", axis_steps_per_unit[E_AXIS]);
   SERIAL_EOL;
 
-  SERIAL_ECHO_START;
+  CONFIG_ECHO_START;
 
   #ifdef SCARA
     if (!forReplay) {
       SERIAL_ECHOLNPGM("Scaling factors:");
-      SERIAL_ECHO_START;
+      CONFIG_ECHO_START;
     }
     SERIAL_ECHOPAIR("  M365 X", axis_scaling[X_AXIS]);
     SERIAL_ECHOPAIR(" Y", axis_scaling[Y_AXIS]);
     SERIAL_ECHOPAIR(" Z", axis_scaling[Z_AXIS]);
     SERIAL_EOL;
-    SERIAL_ECHO_START;
+    CONFIG_ECHO_START;
   #endif // SCARA
 
   if (!forReplay) {
     SERIAL_ECHOLNPGM("Maximum feedrates (mm/s):");
-    SERIAL_ECHO_START;
+    CONFIG_ECHO_START;
   }
   SERIAL_ECHOPAIR("  M203 X", max_feedrate[X_AXIS]);
   SERIAL_ECHOPAIR(" Y", max_feedrate[Y_AXIS]);
@@ -623,160 +639,224 @@ void Config_PrintSettings(bool forReplay) {
   SERIAL_ECHOPAIR(" E", max_feedrate[E_AXIS]);
   SERIAL_EOL;
 
-  SERIAL_ECHO_START;
+  CONFIG_ECHO_START;
   if (!forReplay) {
     SERIAL_ECHOLNPGM("Maximum Acceleration (mm/s2):");
-    SERIAL_ECHO_START;
+    CONFIG_ECHO_START;
   }
-  SERIAL_ECHOPAIR("  M201 X", max_acceleration_units_per_sq_second[X_AXIS] );
-  SERIAL_ECHOPAIR(" Y", max_acceleration_units_per_sq_second[Y_AXIS] );
-  SERIAL_ECHOPAIR(" Z", max_acceleration_units_per_sq_second[Z_AXIS] );
+  SERIAL_ECHOPAIR("  M201 X", max_acceleration_units_per_sq_second[X_AXIS]);
+  SERIAL_ECHOPAIR(" Y", max_acceleration_units_per_sq_second[Y_AXIS]);
+  SERIAL_ECHOPAIR(" Z", max_acceleration_units_per_sq_second[Z_AXIS]);
   SERIAL_ECHOPAIR(" E", max_acceleration_units_per_sq_second[E_AXIS]);
   SERIAL_EOL;
-  SERIAL_ECHO_START;
+  CONFIG_ECHO_START;
   if (!forReplay) {
     SERIAL_ECHOLNPGM("Accelerations: P=printing, R=retract and T=travel");
-    SERIAL_ECHO_START;
+    CONFIG_ECHO_START;
   }
-  SERIAL_ECHOPAIR("  M204 P", acceleration );
+  SERIAL_ECHOPAIR("  M204 P", acceleration);
   SERIAL_ECHOPAIR(" R", retract_acceleration);
   SERIAL_ECHOPAIR(" T", travel_acceleration);
   SERIAL_EOL;
 
-  SERIAL_ECHO_START;
+  CONFIG_ECHO_START;
   if (!forReplay) {
     SERIAL_ECHOLNPGM("Advanced variables: S=Min feedrate (mm/s), T=Min travel feedrate (mm/s), B=minimum segment time (ms), X=maximum XY jerk (mm/s),  Z=maximum Z jerk (mm/s),  E=maximum E jerk (mm/s)");
-    SERIAL_ECHO_START;
+    CONFIG_ECHO_START;
   }
-  SERIAL_ECHOPAIR("  M205 S", minimumfeedrate );
-  SERIAL_ECHOPAIR(" T", mintravelfeedrate );
-  SERIAL_ECHOPAIR(" B", minsegmenttime );
-  SERIAL_ECHOPAIR(" X", max_xy_jerk );
+  SERIAL_ECHOPAIR("  M205 S", minimumfeedrate);
+  SERIAL_ECHOPAIR(" T", mintravelfeedrate);
+  SERIAL_ECHOPAIR(" B", minsegmenttime);
+  SERIAL_ECHOPAIR(" X", max_xy_jerk);
   SERIAL_ECHOPAIR(" Z", max_z_jerk);
   SERIAL_ECHOPAIR(" E", max_e_jerk);
   SERIAL_EOL;
 
-  SERIAL_ECHO_START;
+  CONFIG_ECHO_START;
   if (!forReplay) {
     SERIAL_ECHOLNPGM("Home offset (mm):");
-    SERIAL_ECHO_START;
+    CONFIG_ECHO_START;
   }
-  SERIAL_ECHOPAIR("  M206 X", home_offset[X_AXIS] );
-  SERIAL_ECHOPAIR(" Y", home_offset[Y_AXIS] );
-  SERIAL_ECHOPAIR(" Z", home_offset[Z_AXIS] );
+  SERIAL_ECHOPAIR("  M206 X", home_offset[X_AXIS]);
+  SERIAL_ECHOPAIR(" Y", home_offset[Y_AXIS]);
+  SERIAL_ECHOPAIR(" Z", home_offset[Z_AXIS]);
   SERIAL_EOL;
 
+  #ifdef MESH_BED_LEVELING
+    if (!forReplay) {
+      SERIAL_ECHOLNPGM("Mesh bed leveling:");
+      CONFIG_ECHO_START;
+    }
+    SERIAL_ECHOPAIR("  M420 S", (int32_t)mbl.active);
+    SERIAL_ECHOPAIR(" X", MESH_NUM_X_POINTS);
+    SERIAL_ECHOPAIR(" Y", MESH_NUM_Y_POINTS);
+    SERIAL_EOL;
+    for (int y=0; y<MESH_NUM_Y_POINTS; y++) {
+      for (int x=0; x<MESH_NUM_X_POINTS; x++) {
+        CONFIG_ECHO_START;
+        SERIAL_ECHOPAIR("  M421 X", x);
+        SERIAL_ECHOPAIR(" Y", y);
+        SERIAL_ECHOPAIR(" Z", mbl.z_values[y][x]);
+        SERIAL_EOL;
+      }
+    }
+  #endif
+
   #ifdef DELTA
-    SERIAL_ECHO_START;
+    CONFIG_ECHO_START;
     if (!forReplay) {
       SERIAL_ECHOLNPGM("Endstop adjustment (mm):");
-      SERIAL_ECHO_START;
+      CONFIG_ECHO_START;
     }
-    SERIAL_ECHOPAIR("  M666 X", endstop_adj[X_AXIS] );
-    SERIAL_ECHOPAIR(" Y", endstop_adj[Y_AXIS] );
-    SERIAL_ECHOPAIR(" Z", endstop_adj[Z_AXIS] );
+    SERIAL_ECHOPAIR("  M666 X", endstop_adj[X_AXIS]);
+    SERIAL_ECHOPAIR(" Y", endstop_adj[Y_AXIS]);
+    SERIAL_ECHOPAIR(" Z", endstop_adj[Z_AXIS]);
     SERIAL_EOL;
-    SERIAL_ECHO_START;
+    CONFIG_ECHO_START;
     SERIAL_ECHOLNPGM("Delta settings: L=delta_diagonal_rod, R=delta_radius, S=delta_segments_per_second");
-    SERIAL_ECHO_START;
-    SERIAL_ECHOPAIR("  M665 L", delta_diagonal_rod );
-    SERIAL_ECHOPAIR(" R", delta_radius );
-    SERIAL_ECHOPAIR(" S", delta_segments_per_second );
+    CONFIG_ECHO_START;
+    SERIAL_ECHOPAIR("  M665 L", delta_diagonal_rod);
+    SERIAL_ECHOPAIR(" R", delta_radius);
+    SERIAL_ECHOPAIR(" S", delta_segments_per_second);
     SERIAL_EOL;
   #elif defined(Z_DUAL_ENDSTOPS)
-    SERIAL_ECHO_START;
+    CONFIG_ECHO_START;
     if (!forReplay) {
       SERIAL_ECHOLNPGM("Z2 Endstop adjustment (mm):");
-      SERIAL_ECHO_START;
+      CONFIG_ECHO_START;
     }
-    SERIAL_ECHOPAIR("  M666 Z", z_endstop_adj );
+    SERIAL_ECHOPAIR("  M666 Z", z_endstop_adj);
     SERIAL_EOL;  
   #endif // DELTA
 
+  #ifdef ULTIPANEL
+    CONFIG_ECHO_START;
+    if (!forReplay) {
+      SERIAL_ECHOLNPGM("Material heatup parameters:");
+      CONFIG_ECHO_START;
+    }
+    SERIAL_ECHOPAIR("  M145 M0 H", (unsigned long)plaPreheatHotendTemp);
+    SERIAL_ECHOPAIR(" B", (unsigned long)plaPreheatHPBTemp);
+    SERIAL_ECHOPAIR(" F", (unsigned long)plaPreheatFanSpeed);
+    SERIAL_EOL;
+    CONFIG_ECHO_START;
+    SERIAL_ECHOPAIR("  M145 M1 H", (unsigned long)absPreheatHotendTemp);
+    SERIAL_ECHOPAIR(" B", (unsigned long)absPreheatHPBTemp);
+    SERIAL_ECHOPAIR(" F", (unsigned long)absPreheatFanSpeed);
+    SERIAL_EOL;
+  #endif // ULTIPANEL
+
   #if defined(PIDTEMP) || defined(PIDTEMPBED)
-    SERIAL_ECHO_START;
+
+    CONFIG_ECHO_START;
     if (!forReplay) {
       SERIAL_ECHOLNPGM("PID settings:");
-      SERIAL_ECHO_START;
     }
-    #if defined(PIDTEMP) && defined(PIDTEMPBED)
-      SERIAL_EOL;
-    #endif
     #ifdef PIDTEMP
-      SERIAL_ECHOPAIR("  M301 P", PID_PARAM(Kp, 0)); // for compatibility with hosts, only echos values for E0
-      SERIAL_ECHOPAIR(" I", unscalePID_i(PID_PARAM(Ki, 0)));
-      SERIAL_ECHOPAIR(" D", unscalePID_d(PID_PARAM(Kd, 0)));
-      SERIAL_EOL;
-    #endif
+      #if EXTRUDERS > 1
+        if (forReplay) {
+          for (uint8_t i = 0; i < EXTRUDERS; i++) {
+            CONFIG_ECHO_START;
+            SERIAL_ECHOPAIR("  M301 E", (unsigned long)i);
+            SERIAL_ECHOPAIR(" P", PID_PARAM(Kp, i));
+            SERIAL_ECHOPAIR(" I", unscalePID_i(PID_PARAM(Ki, i)));
+            SERIAL_ECHOPAIR(" D", unscalePID_d(PID_PARAM(Kd, i)));
+            #ifdef PID_ADD_EXTRUSION_RATE
+              SERIAL_ECHOPAIR(" C", PID_PARAM(Kc, i));
+            #endif      
+            SERIAL_EOL;
+          }
+        }
+        else
+      #endif // EXTRUDERS > 1
+      // !forReplay || EXTRUDERS == 1
+      {
+        CONFIG_ECHO_START;
+        SERIAL_ECHOPAIR("  M301 P", PID_PARAM(Kp, 0)); // for compatibility with hosts, only echo values for E0
+        SERIAL_ECHOPAIR(" I", unscalePID_i(PID_PARAM(Ki, 0)));
+        SERIAL_ECHOPAIR(" D", unscalePID_d(PID_PARAM(Kd, 0)));
+        #ifdef PID_ADD_EXTRUSION_RATE
+          SERIAL_ECHOPAIR(" C", PID_PARAM(Kc, 0));
+        #endif      
+        SERIAL_EOL;
+      }
+    #endif // PIDTEMP
+
     #ifdef PIDTEMPBED
-      SERIAL_ECHOPAIR("  M304 P", bedKp); // for compatibility with hosts, only echos values for E0
+      CONFIG_ECHO_START;
+      SERIAL_ECHOPAIR("  M304 P", bedKp);
       SERIAL_ECHOPAIR(" I", unscalePID_i(bedKi));
       SERIAL_ECHOPAIR(" D", unscalePID_d(bedKd));
       SERIAL_EOL;
     #endif
+
+  #endif // PIDTEMP || PIDTEMPBED
+
+  #ifdef HAS_LCD_CONTRAST
+    CONFIG_ECHO_START;
+    if (!forReplay) {
+      SERIAL_ECHOLNPGM("LCD Contrast:");
+      CONFIG_ECHO_START;
+    }
+    SERIAL_ECHOPAIR("  M250 C", (unsigned long)lcd_contrast);
+    SERIAL_EOL;
   #endif
 
   #ifdef FWRETRACT
 
-    SERIAL_ECHO_START;
+    CONFIG_ECHO_START;
     if (!forReplay) {
       SERIAL_ECHOLNPGM("Retract: S=Length (mm) F:Speed (mm/m) Z: ZLift (mm)");
-      SERIAL_ECHO_START;
+      CONFIG_ECHO_START;
     }
     SERIAL_ECHOPAIR("  M207 S", retract_length);
+    #if EXTRUDERS > 1
+      SERIAL_ECHOPAIR(" W", retract_length_swap);
+    #endif
     SERIAL_ECHOPAIR(" F", retract_feedrate*60);
     SERIAL_ECHOPAIR(" Z", retract_zlift);
     SERIAL_EOL;
-    SERIAL_ECHO_START;
+    CONFIG_ECHO_START;
     if (!forReplay) {
       SERIAL_ECHOLNPGM("Recover: S=Extra length (mm) F:Speed (mm/m)");
-      SERIAL_ECHO_START;
+      CONFIG_ECHO_START;
     }
     SERIAL_ECHOPAIR("  M208 S", retract_recover_length);
+    #if EXTRUDERS > 1
+      SERIAL_ECHOPAIR(" W", retract_recover_length_swap);
+    #endif
     SERIAL_ECHOPAIR(" F", retract_recover_feedrate*60);
     SERIAL_EOL;
-    SERIAL_ECHO_START;
+    CONFIG_ECHO_START;
     if (!forReplay) {
       SERIAL_ECHOLNPGM("Auto-Retract: S=0 to disable, 1 to interpret extrude-only moves as retracts or recoveries");
-      SERIAL_ECHO_START;
+      CONFIG_ECHO_START;
     }
     SERIAL_ECHOPAIR("  M209 S", (unsigned long)(autoretract_enabled ? 1 : 0));
     SERIAL_EOL;
 
-    #if EXTRUDERS > 1
-      if (!forReplay) {
-        SERIAL_ECHO_START;
-        SERIAL_ECHOLNPGM("Multi-extruder settings:");
-        SERIAL_ECHO_START;
-        SERIAL_ECHOPAIR("   Swap retract length (mm):    ", retract_length_swap);
-        SERIAL_EOL;
-        SERIAL_ECHO_START;
-        SERIAL_ECHOPAIR("   Swap rec. addl. length (mm): ", retract_recover_length_swap);
-        SERIAL_EOL;
-      }
-    #endif // EXTRUDERS > 1
-
   #endif // FWRETRACT
 
-  SERIAL_ECHO_START;
   if (volumetric_enabled) {
     if (!forReplay) {
+      CONFIG_ECHO_START;
       SERIAL_ECHOLNPGM("Filament settings:");
-      SERIAL_ECHO_START;
     }
+
+    CONFIG_ECHO_START;
     SERIAL_ECHOPAIR("  M200 D", filament_size[0]);
     SERIAL_EOL;
 
     #if EXTRUDERS > 1
-      SERIAL_ECHO_START;
+      CONFIG_ECHO_START;
       SERIAL_ECHOPAIR("  M200 T1 D", filament_size[1]);
       SERIAL_EOL;
       #if EXTRUDERS > 2
-        SERIAL_ECHO_START;
+        CONFIG_ECHO_START;
         SERIAL_ECHOPAIR("  M200 T2 D", filament_size[2]);
         SERIAL_EOL;
         #if EXTRUDERS > 3
-          SERIAL_ECHO_START;
+          CONFIG_ECHO_START;
           SERIAL_ECHOPAIR("  M200 T3 D", filament_size[3]);
           SERIAL_EOL;
         #endif
@@ -785,21 +865,23 @@ void Config_PrintSettings(bool forReplay) {
 
   } else {
     if (!forReplay) {
+      CONFIG_ECHO_START;
       SERIAL_ECHOLNPGM("Filament settings: Disabled");
     }
   }
 
   #ifdef ENABLE_AUTO_BED_LEVELING
-    SERIAL_ECHO_START;
     #ifdef CUSTOM_M_CODES
       if (!forReplay) {
+        CONFIG_ECHO_START;
         SERIAL_ECHOLNPGM("Z-Probe Offset (mm):");
-        SERIAL_ECHO_START;
       }
+      CONFIG_ECHO_START;
       SERIAL_ECHOPAIR("  M", (unsigned long)CUSTOM_M_CODE_SET_Z_PROBE_OFFSET);
       SERIAL_ECHOPAIR(" Z", -zprobe_zoffset);
     #else
       if (!forReplay) {
+        CONFIG_ECHO_START;
         SERIAL_ECHOPAIR("Z-Probe Offset (mm):", -zprobe_zoffset);
       }
     #endif
diff --git a/Marlin/configurator/config/Configuration_adv.h b/Marlin/configurator/config/Configuration_adv.h
index 6478eb923e9..059f0c5c162 100644
--- a/Marlin/configurator/config/Configuration_adv.h
+++ b/Marlin/configurator/config/Configuration_adv.h
@@ -355,7 +355,7 @@ const unsigned int dropsegments=5; //everything with less than this number of st
 //#define HEATERS_PARALLEL
 
 //===========================================================================
-//=============================Buffers           ============================
+//================================= Buffers =================================
 //===========================================================================
 
 // @section hidden
diff --git a/Marlin/configurator/config/language.h b/Marlin/configurator/config/language.h
index 2576bec42b6..b6beb474738 100644
--- a/Marlin/configurator/config/language.h
+++ b/Marlin/configurator/config/language.h
@@ -70,7 +70,7 @@
   #endif
 #else
   #ifndef MACHINE_NAME
-    #define MACHINE_NAME "Mendel"
+    #define MACHINE_NAME "3D Printer"
   #endif
 #endif
 
@@ -158,6 +158,9 @@
 #define MSG_Z_MAX                           "z_max: "
 #define MSG_Z2_MAX                          "z2_max: "
 #define MSG_Z_PROBE                         "z_probe: "
+#define MSG_ERR_MATERIAL_INDEX              "M145 S<index> out of range (0-1)"
+#define MSG_ERR_XYZ_REQUIRED_FOR_M421       "M421 requires XYZ parameters"
+#define MSG_ERR_MESH_INDEX_OOB              "Mesh XY index is out of bounds"
 #define MSG_M119_REPORT                     "Reporting endstop status"
 #define MSG_ENDSTOP_HIT                     "TRIGGERED"
 #define MSG_ENDSTOP_OPEN                    "open"
diff --git a/Marlin/example_configurations/Felix/Configuration_adv.h b/Marlin/example_configurations/Felix/Configuration_adv.h
index a80790b9578..bc27cd8dcf3 100644
--- a/Marlin/example_configurations/Felix/Configuration_adv.h
+++ b/Marlin/example_configurations/Felix/Configuration_adv.h
@@ -355,7 +355,7 @@ const unsigned int dropsegments=5; //everything with less than this number of st
 //#define HEATERS_PARALLEL
 
 //===========================================================================
-//=============================Buffers           ============================
+//================================= Buffers =================================
 //===========================================================================
 
 // @section hidden
diff --git a/Marlin/example_configurations/Hephestos/Configuration_adv.h b/Marlin/example_configurations/Hephestos/Configuration_adv.h
index 84536d044e4..39545c378b9 100644
--- a/Marlin/example_configurations/Hephestos/Configuration_adv.h
+++ b/Marlin/example_configurations/Hephestos/Configuration_adv.h
@@ -355,7 +355,7 @@ const unsigned int dropsegments=5; //everything with less than this number of st
 //#define HEATERS_PARALLEL
 
 //===========================================================================
-//=============================Buffers           ============================
+//================================= Buffers =================================
 //===========================================================================
 
 // @section hidden
diff --git a/Marlin/example_configurations/K8200/Configuration_adv.h b/Marlin/example_configurations/K8200/Configuration_adv.h
index a80790b9578..bc27cd8dcf3 100644
--- a/Marlin/example_configurations/K8200/Configuration_adv.h
+++ b/Marlin/example_configurations/K8200/Configuration_adv.h
@@ -355,7 +355,7 @@ const unsigned int dropsegments=5; //everything with less than this number of st
 //#define HEATERS_PARALLEL
 
 //===========================================================================
-//=============================Buffers           ============================
+//================================= Buffers =================================
 //===========================================================================
 
 // @section hidden
diff --git a/Marlin/example_configurations/SCARA/Configuration_adv.h b/Marlin/example_configurations/SCARA/Configuration_adv.h
index edc2445af6e..bdf2eab4b2b 100644
--- a/Marlin/example_configurations/SCARA/Configuration_adv.h
+++ b/Marlin/example_configurations/SCARA/Configuration_adv.h
@@ -355,7 +355,7 @@ const unsigned int dropsegments=5; //everything with less than this number of st
 //#define HEATERS_PARALLEL
 
 //===========================================================================
-//=============================Buffers           ============================
+//================================= Buffers =================================
 //===========================================================================
 
 // @section hidden
diff --git a/Marlin/example_configurations/WITBOX/Configuration_adv.h b/Marlin/example_configurations/WITBOX/Configuration_adv.h
index 15c52328487..e9c0cd0f1ae 100644
--- a/Marlin/example_configurations/WITBOX/Configuration_adv.h
+++ b/Marlin/example_configurations/WITBOX/Configuration_adv.h
@@ -355,7 +355,7 @@ const unsigned int dropsegments=5; //everything with less than this number of st
 //#define HEATERS_PARALLEL
 
 //===========================================================================
-//=============================Buffers           ============================
+//================================= Buffers =================================
 //===========================================================================
 
 // @section hidden
diff --git a/Marlin/example_configurations/delta/generic/Configuration_adv.h b/Marlin/example_configurations/delta/generic/Configuration_adv.h
index 88b76c66e18..aebfa59d5a0 100644
--- a/Marlin/example_configurations/delta/generic/Configuration_adv.h
+++ b/Marlin/example_configurations/delta/generic/Configuration_adv.h
@@ -356,7 +356,7 @@ const unsigned int dropsegments=5; //everything with less than this number of st
 //#define HEATERS_PARALLEL
 
 //===========================================================================
-//=============================Buffers           ============================
+//================================= Buffers =================================
 //===========================================================================
 
 // @section hidden
diff --git a/Marlin/example_configurations/delta/kossel_mini/Configuration_adv.h b/Marlin/example_configurations/delta/kossel_mini/Configuration_adv.h
index 9b52ede7b75..5e8337ce844 100644
--- a/Marlin/example_configurations/delta/kossel_mini/Configuration_adv.h
+++ b/Marlin/example_configurations/delta/kossel_mini/Configuration_adv.h
@@ -355,7 +355,7 @@ const unsigned int dropsegments=5; //everything with less than this number of st
 //#define HEATERS_PARALLEL
 
 //===========================================================================
-//=============================Buffers           ============================
+//================================= Buffers =================================
 //===========================================================================
 
 // @section hidden
diff --git a/Marlin/example_configurations/makibox/Configuration_adv.h b/Marlin/example_configurations/makibox/Configuration_adv.h
index 7b63732a69d..2d97c626bc8 100644
--- a/Marlin/example_configurations/makibox/Configuration_adv.h
+++ b/Marlin/example_configurations/makibox/Configuration_adv.h
@@ -355,7 +355,7 @@ const unsigned int dropsegments=5; //everything with less than this number of st
 //#define HEATERS_PARALLEL
 
 //===========================================================================
-//=============================Buffers           ============================
+//================================= Buffers =================================
 //===========================================================================
 
 // @section hidden
diff --git a/Marlin/example_configurations/tvrrug/Round2/Configuration_adv.h b/Marlin/example_configurations/tvrrug/Round2/Configuration_adv.h
index d221f080b4a..832fb83552a 100644
--- a/Marlin/example_configurations/tvrrug/Round2/Configuration_adv.h
+++ b/Marlin/example_configurations/tvrrug/Round2/Configuration_adv.h
@@ -355,7 +355,7 @@ const unsigned int dropsegments=5; //everything with less than this number of st
 //#define HEATERS_PARALLEL
 
 //===========================================================================
-//=============================Buffers           ============================
+//================================= Buffers =================================
 //===========================================================================
 
 // @section hidden
diff --git a/Marlin/language.h b/Marlin/language.h
index c9ddfeee41c..b6beb474738 100644
--- a/Marlin/language.h
+++ b/Marlin/language.h
@@ -158,6 +158,9 @@
 #define MSG_Z_MAX                           "z_max: "
 #define MSG_Z2_MAX                          "z2_max: "
 #define MSG_Z_PROBE                         "z_probe: "
+#define MSG_ERR_MATERIAL_INDEX              "M145 S<index> out of range (0-1)"
+#define MSG_ERR_XYZ_REQUIRED_FOR_M421       "M421 requires XYZ parameters"
+#define MSG_ERR_MESH_INDEX_OOB              "Mesh XY index is out of bounds"
 #define MSG_M119_REPORT                     "Reporting endstop status"
 #define MSG_ENDSTOP_HIT                     "TRIGGERED"
 #define MSG_ENDSTOP_OPEN                    "open"
diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp
index 060be3007e0..a8558d6c491 100644
--- a/Marlin/planner.cpp
+++ b/Marlin/planner.cpp
@@ -1,54 +1,51 @@
-/*
-  planner.c - buffers movement commands and manages the acceleration profile plan
- Part of Grbl
- 
- Copyright (c) 2009-2011 Simen Svale Skogsrud
- 
- Grbl 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.
- 
- Grbl 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 Grbl.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-/* The ring buffer implementation gleaned from the wiring_serial library by David A. Mellis. */
-
-/*  
- Reasoning behind the mathematics in this module (in the key of 'Mathematica'):
- 
- s == speed, a == acceleration, t == time, d == distance
- 
- Basic definitions:
- 
- Speed[s_, a_, t_] := s + (a*t) 
- Travel[s_, a_, t_] := Integrate[Speed[s, a, t], t]
- 
- Distance to reach a specific speed with a constant acceleration:
- 
- Solve[{Speed[s, a, t] == m, Travel[s, a, t] == d}, d, t]
- d -> (m^2 - s^2)/(2 a) --> estimate_acceleration_distance()
- 
- Speed after a given distance of travel with constant acceleration:
- 
- Solve[{Speed[s, a, t] == m, Travel[s, a, t] == d}, m, t]
- m -> Sqrt[2 a d + s^2]    
- 
- DestinationSpeed[s_, a_, d_] := Sqrt[2 a d + s^2]
- 
- When to start braking (di) to reach a specified destionation speed (s2) after accelerating
- from initial speed s1 without ever stopping at a plateau:
- 
- Solve[{DestinationSpeed[s1, a, di] == DestinationSpeed[s2, a, d - di]}, di]
- di -> (2 a d - s1^2 + s2^2)/(4 a) --> intersection_distance()
- 
- IntersectionDistance[s1_, s2_, a_, d_] := (2 a d - s1^2 + s2^2)/(4 a)
+/**
+ * planner.cpp - Buffer movement commands and manage the acceleration profile plan
+ * Part of Grbl
+ * 
+ * Copyright (c) 2009-2011 Simen Svale Skogsrud
+ *
+ * Grbl 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.
+ *
+ * Grbl 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 Grbl.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ *
+ * The ring buffer implementation gleaned from the wiring_serial library by David A. Mellis.
+ *
+ *
+ * Reasoning behind the mathematics in this module (in the key of 'Mathematica'):
+ *
+ * s == speed, a == acceleration, t == time, d == distance
+ *
+ * Basic definitions:
+ *   Speed[s_, a_, t_] := s + (a*t)
+ *   Travel[s_, a_, t_] := Integrate[Speed[s, a, t], t]
+ *
+ * Distance to reach a specific speed with a constant acceleration:
+ *   Solve[{Speed[s, a, t] == m, Travel[s, a, t] == d}, d, t]
+ *   d -> (m^2 - s^2)/(2 a) --> estimate_acceleration_distance()
+ *
+ * Speed after a given distance of travel with constant acceleration:
+ *   Solve[{Speed[s, a, t] == m, Travel[s, a, t] == d}, m, t]
+ *   m -> Sqrt[2 a d + s^2]
+ *
+ * DestinationSpeed[s_, a_, d_] := Sqrt[2 a d + s^2]
+ *
+ * When to start braking (di) to reach a specified destination speed (s2) after accelerating
+ * from initial speed s1 without ever stopping at a plateau:
+ *   Solve[{DestinationSpeed[s1, a, di] == DestinationSpeed[s2, a, d - di]}, di]
+ *   di -> (2 a d - s1^2 + s2^2)/(4 a) --> intersection_distance()
+ *
+ * IntersectionDistance[s1_, s2_, a_, d_] := (2 a d - s1^2 + s2^2)/(4 a)
+ *
  */
 
 #include "Marlin.h"
@@ -71,17 +68,17 @@ float max_feedrate[NUM_AXIS]; // Max speeds in mm per minute
 float axis_steps_per_unit[NUM_AXIS];
 unsigned long max_acceleration_units_per_sq_second[NUM_AXIS]; // Use M201 to override by software
 float minimumfeedrate;
-float acceleration;         // Normal acceleration mm/s^2  THIS IS THE DEFAULT ACCELERATION for all printing moves. M204 SXXXX
-float retract_acceleration; //  mm/s^2   filament pull-pack and push-forward  while standing still in the other axis M204 TXXXX
-float travel_acceleration;  // Travel acceleration mm/s^2  THIS IS THE DEFAULT ACCELERATION for all NON printing moves. M204 MXXXX
-float max_xy_jerk; //speed than can be stopped at once, if i understand correctly.
+float acceleration;         // Normal acceleration mm/s^2  DEFAULT ACCELERATION for all printing moves. M204 SXXXX
+float retract_acceleration; // Retract acceleration mm/s^2 filament pull-back and push-forward while standing still in the other axes M204 TXXXX
+float travel_acceleration;  // Travel acceleration mm/s^2  DEFAULT ACCELERATION for all NON printing moves. M204 MXXXX
+float max_xy_jerk;          // The largest speed change requiring no acceleration
 float max_z_jerk;
 float max_e_jerk;
 float mintravelfeedrate;
 unsigned long axis_steps_per_sqr_second[NUM_AXIS];
 
 #ifdef ENABLE_AUTO_BED_LEVELING
-  // this holds the required transform to compensate for bed level
+  // Transform required to compensate for bed level
   matrix_3x3 plan_bed_level_matrix = {
     1.0, 0.0, 0.0,
     0.0, 1.0, 0.0,
@@ -89,11 +86,6 @@ unsigned long axis_steps_per_sqr_second[NUM_AXIS];
   };
 #endif // ENABLE_AUTO_BED_LEVELING
 
-// The current position of the tool in absolute steps
-long position[NUM_AXIS];   //rescaled from extern when axis_steps_per_unit are changed by gcode
-static float previous_speed[NUM_AXIS]; // Speed of previous path line segment
-static float previous_nominal_speed; // Nominal speed of previous path line segment
-
 #ifdef AUTOTEMP
   float autotemp_max = 250;
   float autotemp_min = 210;
@@ -101,18 +93,25 @@ static float previous_nominal_speed; // Nominal speed of previous path line segm
   bool autotemp_enabled = false;
 #endif
 
-unsigned char g_uc_extruder_last_move[4] = {0,0,0,0};
+//===========================================================================
+//============ semi-private variables, used in inline functions =============
+//===========================================================================
 
-//===========================================================================
-//=================semi-private variables, used in inline  functions    =====
-//===========================================================================
 block_t block_buffer[BLOCK_BUFFER_SIZE];            // A ring buffer for motion instfructions
 volatile unsigned char block_buffer_head;           // Index of the next block to be pushed
 volatile unsigned char block_buffer_tail;           // Index of the block to process now
 
 //===========================================================================
-//=============================private variables ============================
+//============================ private variables ============================
 //===========================================================================
+
+// The current position of the tool in absolute steps
+long position[NUM_AXIS];               // Rescaled from extern when axis_steps_per_unit are changed by gcode
+static float previous_speed[NUM_AXIS]; // Speed of previous path line segment
+static float previous_nominal_speed;   // Nominal speed of previous path line segment
+
+unsigned char g_uc_extruder_last_move[4] = {0,0,0,0};
+
 #ifdef XY_FREQUENCY_LIMIT
   // Used for the frequency limit
   #define MAX_FREQ_TIME (1000000.0/XY_FREQUENCY_LIMIT)
@@ -126,15 +125,15 @@ volatile unsigned char block_buffer_tail;           // Index of the block to pro
   static char meas_sample; //temporary variable to hold filament measurement sample
 #endif
 
+//===========================================================================
+//================================ functions ================================
+//===========================================================================
+
 // Get the next / previous index of the next block in the ring buffer
 // NOTE: Using & here (not %) because BLOCK_BUFFER_SIZE is always a power of 2
 FORCE_INLINE int8_t next_block_index(int8_t block_index) { return BLOCK_MOD(block_index + 1); }
 FORCE_INLINE int8_t prev_block_index(int8_t block_index) { return BLOCK_MOD(block_index - 1); }
 
-//===========================================================================
-//================================ Functions ================================
-//===========================================================================
-
 // Calculates the distance (not time) it takes to accelerate from initial_rate to target_rate using the 
 // given acceleration:
 FORCE_INLINE float estimate_acceleration_distance(float initial_rate, float target_rate, float acceleration) {
diff --git a/Marlin/planner.h b/Marlin/planner.h
index d96aa8c1120..c54ed4411ae 100644
--- a/Marlin/planner.h
+++ b/Marlin/planner.h
@@ -115,15 +115,19 @@ FORCE_INLINE uint8_t movesplanned() { return BLOCK_MOD(block_buffer_head - block
 
 void plan_set_e_position(const float &e);
 
+//===========================================================================
+//============================= public variables ============================
+//===========================================================================
+
 extern millis_t minsegmenttime;
-extern float max_feedrate[NUM_AXIS]; // set the max speeds
+extern float max_feedrate[NUM_AXIS]; // Max speeds in mm per minute
 extern float axis_steps_per_unit[NUM_AXIS];
 extern unsigned long max_acceleration_units_per_sq_second[NUM_AXIS]; // Use M201 to override by software
 extern float minimumfeedrate;
-extern float acceleration;         // Normal acceleration mm/s^2  THIS IS THE DEFAULT ACCELERATION for all moves. M204 SXXXX
-extern float retract_acceleration; //  mm/s^2   filament pull-pack and push-forward  while standing still in the other axis M204 TXXXX
-extern float travel_acceleration;  // Travel acceleration mm/s^2  THIS IS THE DEFAULT ACCELERATION for all NON printing moves. M204 MXXXX
-extern float max_xy_jerk; //speed than can be stopped at once, if i understand correctly.
+extern float acceleration;         // Normal acceleration mm/s^2  DEFAULT ACCELERATION for all printing moves. M204 SXXXX
+extern float retract_acceleration; // Retract acceleration mm/s^2 filament pull-back and push-forward while standing still in the other axes M204 TXXXX
+extern float travel_acceleration;  // Travel acceleration mm/s^2  DEFAULT ACCELERATION for all NON printing moves. M204 MXXXX
+extern float max_xy_jerk;          // The largest speed change requiring no acceleration
 extern float max_z_jerk;
 extern float max_e_jerk;
 extern float mintravelfeedrate;
diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp
index fa17b6c4c2f..a494e3a9d08 100644
--- a/Marlin/temperature.cpp
+++ b/Marlin/temperature.cpp
@@ -89,8 +89,9 @@ unsigned char soft_pwm_bed;
 #endif
 
 //===========================================================================
-//=============================private variables============================
+//============================ private variables ============================
 //===========================================================================
+
 static volatile bool temp_meas_ready = false;
 
 #ifdef PIDTEMP
@@ -187,7 +188,7 @@ static void updateTemperaturesFromRawValues();
 #endif
 
 //===========================================================================
-//=============================   functions      ============================
+//================================ functions ================================
 //===========================================================================
 
 void PID_autotune(float temp, int extruder, int ncycles)
diff --git a/Marlin/ultralcd.cpp b/Marlin/ultralcd.cpp
index 81844573ea9..3895dc55199 100644
--- a/Marlin/ultralcd.cpp
+++ b/Marlin/ultralcd.cpp
@@ -868,10 +868,10 @@ static void lcd_control_temperature_preheat_pla_settings_menu() {
   MENU_ITEM(back, MSG_TEMPERATURE, lcd_control_temperature_menu);
   MENU_ITEM_EDIT(int3, MSG_FAN_SPEED, &plaPreheatFanSpeed, 0, 255);
   #if TEMP_SENSOR_0 != 0
-    MENU_ITEM_EDIT(int3, MSG_NOZZLE, &plaPreheatHotendTemp, 0, HEATER_0_MAXTEMP - 15);
+    MENU_ITEM_EDIT(int3, MSG_NOZZLE, &plaPreheatHotendTemp, HEATER_0_MINTEMP, HEATER_0_MAXTEMP - 15);
   #endif
   #if TEMP_SENSOR_BED != 0
-    MENU_ITEM_EDIT(int3, MSG_BED, &plaPreheatHPBTemp, 0, BED_MAXTEMP - 15);
+    MENU_ITEM_EDIT(int3, MSG_BED, &plaPreheatHPBTemp, BED_MINTEMP, BED_MAXTEMP - 15);
   #endif
   #ifdef EEPROM_SETTINGS
     MENU_ITEM(function, MSG_STORE_EPROM, Config_StoreSettings);
@@ -884,10 +884,10 @@ static void lcd_control_temperature_preheat_abs_settings_menu() {
   MENU_ITEM(back, MSG_TEMPERATURE, lcd_control_temperature_menu);
   MENU_ITEM_EDIT(int3, MSG_FAN_SPEED, &absPreheatFanSpeed, 0, 255);
   #if TEMP_SENSOR_0 != 0
-    MENU_ITEM_EDIT(int3, MSG_NOZZLE, &absPreheatHotendTemp, 0, HEATER_0_MAXTEMP - 15);
+    MENU_ITEM_EDIT(int3, MSG_NOZZLE, &absPreheatHotendTemp, HEATER_0_MINTEMP, HEATER_0_MAXTEMP - 15);
   #endif
   #if TEMP_SENSOR_BED != 0
-    MENU_ITEM_EDIT(int3, MSG_BED, &absPreheatHPBTemp, 0, BED_MAXTEMP - 15);
+    MENU_ITEM_EDIT(int3, MSG_BED, &absPreheatHPBTemp, BED_MINTEMP, BED_MAXTEMP - 15);
   #endif
   #ifdef EEPROM_SETTINGS
     MENU_ITEM(function, MSG_STORE_EPROM, Config_StoreSettings);
diff --git a/Marlin/watchdog.cpp b/Marlin/watchdog.cpp
index b378ca706ab..8505f7efac2 100644
--- a/Marlin/watchdog.cpp
+++ b/Marlin/watchdog.cpp
@@ -7,11 +7,11 @@
 #include "ultralcd.h"
 
 //===========================================================================
-//=============================private variables  ============================
+//============================ private variables ============================
 //===========================================================================
 
 //===========================================================================
-//=============================functinos         ============================
+//================================ functions ================================
 //===========================================================================
 
 
@@ -36,7 +36,7 @@ void watchdog_reset()
 }
 
 //===========================================================================
-//=============================ISR               ============================
+//=================================== ISR ===================================
 //===========================================================================
 
 //Watchdog timer interrupt, called if main program blocks >1sec and manual reset is enabled.