diff --git a/.travis.yml b/.travis.yml
index a7c220d067dfb27faa8062b52d81acf9ddbde85c..a2e58f2289013d4f3d5a17d8de661c41516a0627 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,12 +1,13 @@
 ---
 language: c
-
+  #
 before_install:
   # Travis runs a detached head. We need to find the current branch
   - git checkout `git branch --contains HEAD | grep -v '*'`
   # Also tags for the root(s) of the minor version(s)
   - git fetch origin --tags
   - mkdir ~/bin
+  #
 install:
   # Install arduino 1.6.4
   - wget http://downloads-02.arduino.cc/arduino-1.6.4-linux64.tar.xz
@@ -26,144 +27,215 @@ install:
   - mv LiquidCrystal_I2C/LiquidCrystal_I2C /usr/local/share/arduino/libraries/LiquidCrystal_I2C
   - git clone https://github.com/lincomatic/LiquidTWI2.git
   - mv LiquidTWI2 /usr/local/share/arduino/libraries/LiquidTWI2
+  #
 before_script:
   # arduino requires an X server even with command line
   # https://github.com/arduino/Arduino/issues/1981
   - Xvfb :1 -screen 0 1024x768x16 &> xvfb.log &
   # change back to home directory for compiling
   - cd $TRAVIS_BUILD_DIR
+  #
 script:
-  # build default config
-  - build_marlin
+  #
   # Backup Configuration.h, Configuration_adv.h, and pins_RAMPS_14.h
+  #
   - cp Marlin/Configuration.h Marlin/Configuration.h.backup
   - cp Marlin/Configuration_adv.h Marlin/Configuration_adv.h.backup
   - cp Marlin/pins_RAMPS_14.h Marlin/pins_RAMPS_14.h.backup
-  # add sensor for bed
+  #
+  # Build with the default configurations
+  #
+  - build_marlin
+  #
+  # Test heated bed temperature sensor
+  #
   - opt_set TEMP_SENSOR_BED 1
   - build_marlin
-  # change extruder numbers from 1 to 2
+  #
+  # Test 2 extruders on basic RAMPS 1.4
+  #
   - opt_set MOTHERBOARD BOARD_RAMPS_14_EEB
   - opt_set EXTRUDERS 2
   - opt_set TEMP_SENSOR_1 1
-  #- cat Marlin/Configuration.h
   - build_marlin
-  # change extruder numbers from 2 to 3, needs to be a board with 3 extruders defined in pins.h 
+  #
+  # Test 3 extruders on RUMBA (can use any board with >=3 extruders defined)
+  #
   - opt_set MOTHERBOARD BOARD_RUMBA
   - opt_set EXTRUDERS 3
   - opt_set TEMP_SENSOR_2 1
   - build_marlin
-  # enable PIDTEMPBED 
+  #
+  # Test PIDTEMPBED
+  #
   - restore_configs
   - opt_enable PIDTEMPBED
   - build_marlin
-  # enable AUTO_BED_LEVELING
+  #
+  # Test AUTO_BED_LEVELING & DEBUG_LEVELING_FEATURE
+  #
   - restore_configs
-  - opt_enable ENABLE_AUTO_BED_LEVELING
+  - opt_enable ENABLE_AUTO_BED_LEVELING DEBUG_LEVELING_FEATURE
   - build_marlin
-  # enable AUTO_BED_LEVELING with servos
-  - restore_configs
-  - opt_enable ENABLE_AUTO_BED_LEVELING NUM_SERVOS Z_ENDSTOP_SERVO_NR SERVO_ENDSTOP_ANGLES DEACTIVATE_SERVOS_AFTER_MOVE
+  #
+  # Test AUTO_BED_LEVELING & DEBUG_LEVELING_FEATURE with Servos
+  #
+  - opt_enable NUM_SERVOS Z_ENDSTOP_SERVO_NR SERVO_ENDSTOP_ANGLES DEACTIVATE_SERVOS_AFTER_MOVE
   - build_marlin
-  # enable EEPROM_SETTINGS & EEPROM_CHITCHAT
+  #
+  # Test EEPROM_SETTINGS & EEPROM_CHITCHAT
+  #
   - restore_configs
   - opt_enable EEPROM_SETTINGS EEPROM_CHITCHAT
   - build_marlin
+  #
   ### LCDS ###
+  #
+  #
   # ULTIMAKERCONTROLLER
+  #
   - restore_configs
   - opt_enable ULTIMAKERCONTROLLER
   - build_marlin
+  #
   # MAKRPANEL
-  # Needs to use melzi and sanguino hardware
+  # Needs to use Melzi and Sanguino hardware
+  #
   #- restore_configs
   #- opt_enable MAKRPANEL
   #- build_marlin
+  #
   # REPRAP_DISCOUNT_SMART_CONTROLLER
+  #
   - restore_configs
   - opt_enable REPRAP_DISCOUNT_SMART_CONTROLLER SDSUPPORT
   - build_marlin
+  #
   # G3D_PANEL
+  #
   - restore_configs
   - opt_enable G3D_PANEL SDSUPPORT
   - build_marlin
+  #
   # REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER
+  #
   - restore_configs
-  - opt_enable REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER
+  - opt_enable REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER SDSUPPORT
   - build_marlin
+  #
   # REPRAPWORLD_KEYPAD
+  #
   # Cant find configuration details to get it to compile
   #- restore_configs
   #- opt_enable ULTRA_LCD REPRAPWORLD_KEYPAD REPRAPWORLD_KEYPAD_MOVE_STEP
   #- build_marlin
+  #
   # RA_CONTROL_PANEL
+  #
   - restore_configs
   - opt_enable RA_CONTROL_PANEL
   - build_marlin
+  #
   ### I2C PANELS ###
+  #
   # LCD_I2C_SAINSMART_YWROBOT
   # Failing at the moment needs different library 
   #- restore_configs
   #- opt_enable LCD_I2C_SAINSMART_YWROBOT
   #- build_marlin
+  #
   # LCD_I2C_PANELOLU2
+  #
   - restore_configs
   - opt_enable LCD_I2C_PANELOLU2
   - build_marlin
+  #
   # LCD_I2C_VIKI
+  #
   - restore_configs
   - opt_enable LCD_I2C_VIKI
   - build_marlin
+  #
   # LCM1602
+  #
   - restore_configs
   - opt_enable LCM1602
   - build_marlin
+  #
   # Enable FILAMENTCHANGEENABLE
+  #
   - restore_configs
-  - opt_enable FILAMENTCHANGEENABLE
+  - opt_enable FILAMENTCHANGEENABLE ULTIMAKERCONTROLLER
   - build_marlin
+  #
   # Enable filament sensor
+  #
   - restore_configs
   - opt_enable FILAMENT_WIDTH_SENSOR
   - build_marlin
+  #
   # Enable filament sensor with LCD display
-  - restore_configs
-  - opt_enable ULTIMAKERCONTROLLER FILAMENT_WIDTH_SENSOR FILAMENT_LCD_DISPLAY
+  #
+  - opt_enable ULTIMAKERCONTROLLER FILAMENT_LCD_DISPLAY
   - build_marlin
+  #
   # Enable COREXY
+  #
   - restore_configs
   - opt_enable COREXY
   - build_marlin
+  #
   # Enable COREXZ
+  #
   - restore_configs
   - opt_enable COREXZ
   - build_marlin
+  #
   # Enable Z_DUAL_STEPPER_DRIVERS, Z_DUAL_ENDSTOPS
+  #
   - restore_configs
   - opt_enable_adv Z_DUAL_STEPPER_DRIVERS Z_DUAL_ENDSTOPS
   - pins_set RAMPS_14 X_MAX_PIN -1
   - opt_set_adv Z2_MAX_PIN 2
   - build_marlin
-  - restore_configs
+  #
+  #
   ######## Example Configurations ##############
+  #
   # Delta Config (generic)
+  - restore_configs
   - use_example_configs delta/generic
   - build_marlin
+  #
   # Delta Config (generic) + ABL + ALLEN_KEY
+  #
   - use_example_configs delta/generic
   - opt_disable DISABLE_MIN_ENDSTOPS
   - opt_enable AUTO_BED_LEVELING_FEATURE Z_PROBE_ALLEN_KEY
   - build_marlin
+  #
   # Delta Config (Mini Kossel)
+  #
   - use_example_configs delta/kossel_mini
   - build_marlin
+  #
   # Makibox Config  need to check board type for Teensy++ 2.0
+  #
   #- use_example_configs makibox
   #- build_marlin
+  #
   # SCARA Config
+  #
   - use_example_configs SCARA
   - build_marlin
+  #
   # tvrrug Config need to check board type for sanguino atmega644p
+  #
   #- use_example_configs tvrrug/Round2
   #- build_marlin
+  #
+  #
   ######## Board Types #############
+  #
+  # To be added in nightly test branch
+  #
diff --git a/Marlin/Conditionals.h b/Marlin/Conditionals.h
index 91760045d741acbf94cb6cbc4be4b68fc226fb8e..b9809793b76d602748056acc3295c8e47499263b 100644
--- a/Marlin/Conditionals.h
+++ b/Marlin/Conditionals.h
@@ -275,20 +275,28 @@
   #include "Arduino.h"
 
   /**
-   * ENDSTOPPULLUPS
+   * Set ENDSTOPPULLUPS for unused endstop switches
    */
   #if ENABLED(ENDSTOPPULLUPS)
-    #if DISABLED(DISABLE_MAX_ENDSTOPS)
+    #if ENABLED(USE_XMAX_PLUG)
       #define ENDSTOPPULLUP_XMAX
+    #endif
+    #if ENABLED(USE_YMAX_PLUG)
       #define ENDSTOPPULLUP_YMAX
+    #endif
+    #if ENABLED(USE_ZMAX_PLUG)
       #define ENDSTOPPULLUP_ZMAX
     #endif
-    #if DISABLED(DISABLE_MIN_ENDSTOPS)
+    #if ENABLED(USE_XMIN_PLUG)
       #define ENDSTOPPULLUP_XMIN
+    #endif
+    #if ENABLED(USE_YMIN_PLUG)
       #define ENDSTOPPULLUP_YMIN
+    #endif
+    #if ENABLED(USE_ZMIN_PLUG)
       #define ENDSTOPPULLUP_ZMIN
     #endif
-    #if DISABLED(DISABLE_Z_MIN_PROBE_ENDSTOP)
+    #if ENABLED(DISABLE_Z_MIN_PROBE_ENDSTOP)
       #define ENDSTOPPULLUP_ZMIN_PROBE
     #endif
   #endif
@@ -440,7 +448,9 @@
     #define HEATER_0_USES_THERMISTOR
   #endif
 
-  #if TEMP_SENSOR_1 == -1
+  #if TEMP_SENSOR_1 <= -2
+    #error MAX6675 / MAX31855 Thermocouples not supported for TEMP_SENSOR_1
+  #elif TEMP_SENSOR_1 == -1
     #define HEATER_1_USES_AD595
   #elif TEMP_SENSOR_1 == 0
     #undef HEATER_1_MINTEMP
@@ -450,7 +460,9 @@
     #define HEATER_1_USES_THERMISTOR
   #endif
 
-  #if TEMP_SENSOR_2 == -1
+  #if TEMP_SENSOR_2 <= -2
+    #error MAX6675 / MAX31855 Thermocouples not supported for TEMP_SENSOR_2
+  #elif TEMP_SENSOR_2 == -1
     #define HEATER_2_USES_AD595
   #elif TEMP_SENSOR_2 == 0
     #undef HEATER_2_MINTEMP
@@ -460,7 +472,9 @@
     #define HEATER_2_USES_THERMISTOR
   #endif
 
-  #if TEMP_SENSOR_3 == -1
+  #if TEMP_SENSOR_3 <= -2
+    #error MAX6675 / MAX31855 Thermocouples not supported for TEMP_SENSOR_3
+  #elif TEMP_SENSOR_3 == -1
     #define HEATER_3_USES_AD595
   #elif TEMP_SENSOR_3 == 0
     #undef HEATER_3_MINTEMP
@@ -470,7 +484,9 @@
     #define HEATER_3_USES_THERMISTOR
   #endif
 
-  #if TEMP_SENSOR_BED == -1
+  #if TEMP_SENSOR_BED <= -2
+    #error MAX6675 / MAX31855 Thermocouples not supported for TEMP_SENSOR_BED
+  #elif TEMP_SENSOR_BED == -1
     #define BED_USES_AD595
   #elif TEMP_SENSOR_BED == 0
     #undef BED_MINTEMP
@@ -495,14 +511,55 @@
 
   #define ARRAY_BY_EXTRUDERS1(v1) ARRAY_BY_EXTRUDERS(v1, v1, v1, v1)
 
+  /**
+   * Z_DUAL_ENDSTOPS endstop reassignment
+   */
+  #if ENABLED(Z_DUAL_ENDSTOPS)
+    #define _XMIN_ 100
+    #define _YMIN_ 200
+    #define _ZMIN_ 300
+    #define _XMAX_ 101
+    #define _YMAX_ 201
+    #define _ZMAX_ 301
+    const bool Z2_MAX_ENDSTOP_INVERTING =
+      #if Z2_USE_ENDSTOP == _XMAX_
+        X_MAX_ENDSTOP_INVERTING
+        #define Z2_MAX_PIN X_MAX_PIN
+        #undef USE_XMAX_PLUG
+      #elif Z2_USE_ENDSTOP == _YMAX_
+        Y_MAX_ENDSTOP_INVERTING
+        #define Z2_MAX_PIN Y_MAX_PIN
+        #undef USE_YMAX_PLUG
+      #elif Z2_USE_ENDSTOP == _ZMAX_
+        Z_MAX_ENDSTOP_INVERTING
+        #define Z2_MAX_PIN Z_MAX_PIN
+        #undef USE_ZMAX_PLUG
+      #elif Z2_USE_ENDSTOP == _XMIN_
+        X_MIN_ENDSTOP_INVERTING
+        #define Z2_MAX_PIN X_MIN_PIN
+        #undef USE_XMIN_PLUG
+      #elif Z2_USE_ENDSTOP == _YMIN_
+        Y_MIN_ENDSTOP_INVERTING
+        #define Z2_MAX_PIN Y_MIN_PIN
+        #undef USE_YMIN_PLUG
+      #elif Z2_USE_ENDSTOP == _ZMIN_
+        Z_MIN_ENDSTOP_INVERTING
+        #define Z2_MAX_PIN Z_MIN_PIN
+        #undef USE_ZMIN_PLUG
+      #else
+        0
+      #endif
+    ;
+  #endif
+
   /**
    * Shorthand for pin tests, used wherever needed
    */
-  #define HAS_TEMP_0 (PIN_EXISTS(TEMP_0) && TEMP_SENSOR_0 != 0 && TEMP_SENSOR_0 != -2)
-  #define HAS_TEMP_1 (PIN_EXISTS(TEMP_1) && TEMP_SENSOR_1 != 0)
-  #define HAS_TEMP_2 (PIN_EXISTS(TEMP_2) && TEMP_SENSOR_2 != 0)
-  #define HAS_TEMP_3 (PIN_EXISTS(TEMP_3) && TEMP_SENSOR_3 != 0)
-  #define HAS_TEMP_BED (PIN_EXISTS(TEMP_BED) && TEMP_SENSOR_BED != 0)
+  #define HAS_TEMP_0 (PIN_EXISTS(TEMP_0) && TEMP_SENSOR_0 != 0 && TEMP_SENSOR_0 > -2)
+  #define HAS_TEMP_1 (PIN_EXISTS(TEMP_1) && TEMP_SENSOR_1 != 0 && TEMP_SENSOR_1 > -2)
+  #define HAS_TEMP_2 (PIN_EXISTS(TEMP_2) && TEMP_SENSOR_2 != 0 && TEMP_SENSOR_2 > -2)
+  #define HAS_TEMP_3 (PIN_EXISTS(TEMP_3) && TEMP_SENSOR_3 != 0 && TEMP_SENSOR_3 > -2)
+  #define HAS_TEMP_BED (PIN_EXISTS(TEMP_BED) && TEMP_SENSOR_BED != 0 && TEMP_SENSOR_BED > -2)
   #define HAS_HEATER_0 (PIN_EXISTS(HEATER_0))
   #define HAS_HEATER_1 (PIN_EXISTS(HEATER_1))
   #define HAS_HEATER_2 (PIN_EXISTS(HEATER_2))
@@ -581,6 +638,8 @@
 
   #define HAS_MOTOR_CURRENT_PWM (PIN_EXISTS(MOTOR_CURRENT_PWM_XY) || PIN_EXISTS(MOTOR_CURRENT_PWM_Z) || PIN_EXISTS(MOTOR_CURRENT_PWM_E))
 
+  #define HAS_TEMP_HOTEND (HAS_TEMP_0 || ENABLED(HEATER_0_USES_MAX6675))
+
   /**
    * Helper Macros for heaters and extruder fan
    */
diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h
index 8debc70bd77b44b1b077240c901b1e4ab7443542..d0a49aade3c4d5091e845e8200e2adeb631100c4 100644
--- a/Marlin/Configuration.h
+++ b/Marlin/Configuration.h
@@ -346,8 +346,22 @@
 // Enable this option for Toshiba steppers
 //#define CONFIG_STEPPERS_TOSHIBA
 
+//===========================================================================
+//============================== Endstop Settings ===========================
+//===========================================================================
+
 // @section homing
 
+// Specify here all the endstop connectors that are connected to any endstop or probe.
+// Almost all printers will be using one per axis. Probes will use one or more of the
+// extra connectors. Leave undefined any used for non-endstop and non-probe purposes.
+#define USE_XMIN_PLUG
+#define USE_YMIN_PLUG
+#define USE_ZMIN_PLUG
+//#define USE_XMAX_PLUG
+//#define USE_YMAX_PLUG
+//#define USE_ZMAX_PLUG
+
 // coarse Endstop Settings
 #define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors
 
@@ -370,8 +384,6 @@ const bool X_MAX_ENDSTOP_INVERTING = false; // set to true to invert the logic o
 const bool Y_MAX_ENDSTOP_INVERTING = false; // set to true to invert the logic of the endstop.
 const bool Z_MAX_ENDSTOP_INVERTING = false; // set to true to invert the logic of the endstop.
 const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the logic of the endstop.
-//#define DISABLE_MAX_ENDSTOPS
-//#define DISABLE_MIN_ENDSTOPS
 
 //===========================================================================
 //============================= Z Probe Options =============================
@@ -709,9 +721,12 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l
 // Host Keepalive
 //
 // By default Marlin will send a busy status message to the host
-// every 10 seconds when it can't accept commands.
+// every couple of seconds when it can't accept commands.
 //
 //#define DISABLE_HOST_KEEPALIVE // Enable this option if your host doesn't like keepalive messages.
+#if DISABLED(DISABLE_HOST_KEEPALIVE)
+  #define DEFAULT_KEEPALIVE_INTERVAL 2 // Number of seconds between "busy" messages. Set with M113.
+#endif
 
 //
 // M100 Free Memory Watcher
diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h
index 84f001fb81bcc06381b530794cec694d48476491..3b262373869448523dd36bc02d36ab4fc065ff1c 100644
--- a/Marlin/Configuration_adv.h
+++ b/Marlin/Configuration_adv.h
@@ -201,9 +201,7 @@
   //#define Z_DUAL_ENDSTOPS
 
   #if ENABLED(Z_DUAL_ENDSTOPS)
-    #define Z2_MAX_PIN 36                     //Endstop used for Z2 axis. In this case I'm using XMAX in a Rumba Board (pin 36)
-    const bool Z2_MAX_ENDSTOP_INVERTING = false;
-    #define DISABLE_XMAX_ENDSTOP              //Better to disable the XMAX to avoid conflict. Just rename "XMAX_ENDSTOP" by the endstop you are using for Z2 axis.
+    #define Z2_USE_ENDSTOP _XMAX_
   #endif
 
 #endif // Z_DUAL_STEPPER_DRIVERS
@@ -655,6 +653,38 @@ const unsigned int dropsegments = 5; //everything with less than this number of
 
 #endif
 
+/**
+ * TWI/I2C BUS
+ *
+ * This feature is an EXPERIMENTAL feature so it shall not be used on production
+ * machines. Enabling this will allow you to send and receive I2C data from slave
+ * devices on the bus.
+ *
+ * ; Example #1
+ * ; This macro send the string "Marlin" to the slave device with address 0x63
+ * ; It uses multiple M155 commands with one B<base 10> arg
+ * M155 A63  ; Target slave address
+ * M155 B77  ; M
+ * M155 B97  ; a
+ * M155 B114 ; r
+ * M155 B108 ; l
+ * M155 B105 ; i
+ * M155 B110 ; n
+ * M155 S1   ; Send the current buffer
+ *
+ * ; Example #2
+ * ; Request 6 bytes from slave device with address 0x63
+ * M156 A63 B5
+ *
+ * ; Example #3
+ * ; Example serial output of a M156 request
+ * echo:i2c-reply: from:63 bytes:5 data:hello
+ */
+
+// @section i2cbus
+
+//#define EXPERIMENTAL_I2CBUS
+
 #include "Conditionals.h"
 #include "SanityCheck.h"
 
diff --git a/Marlin/M100_Free_Mem_Chk.cpp b/Marlin/M100_Free_Mem_Chk.cpp
index f7900a0f35486f033ee4c130327ab29d21e9d0b4..276df98eb1f6c9b6dc96b06869371184db77328a 100644
--- a/Marlin/M100_Free_Mem_Chk.cpp
+++ b/Marlin/M100_Free_Mem_Chk.cpp
@@ -137,8 +137,10 @@ void gcode_M100() {
   // other vital statistics that define the memory pool.
   //
   if (code_seen('F')) {
-    int max_addr = (int) __brkval;
-    int max_cnt = 0;
+    #if 0
+      int max_addr = (int) __brkval;
+      int max_cnt = 0;
+    #endif
     int block_cnt = 0;
     ptr = (unsigned char*) __brkval;
     sp = top_of_stack();
@@ -155,10 +157,12 @@ void gcode_M100() {
           i += j;
           block_cnt++;
         }
-        if (j > max_cnt) {      // We don't do anything with this information yet
-          max_cnt  = j;     // but we do know where the biggest free memory block is.
-          max_addr = (int) ptr + i;
-        }
+        #if 0
+          if (j > max_cnt) {      // We don't do anything with this information yet
+            max_cnt  = j;     // but we do know where the biggest free memory block is.
+            max_addr = (int) ptr + i;
+          }
+        #endif
       }
     }
     if (block_cnt > 1)
@@ -176,10 +180,10 @@ void gcode_M100() {
     x = code_value();
     SERIAL_ECHOLNPGM("Corrupting free memory block.\n");
     ptr = (unsigned char*) __brkval;
-    SERIAL_ECHOPAIR("\n__brkval : ", (long) ptr);
+    SERIAL_ECHOPAIR("\n__brkval : ", ptr);
     ptr += 8;
     sp = top_of_stack();
-    SERIAL_ECHOPAIR("\nStack Pointer : ", (long) sp);
+    SERIAL_ECHOPAIR("\nStack Pointer : ", sp);
     SERIAL_ECHOLNPGM("\n");
     n = sp - ptr - 64;    // -64 just to keep us from finding interrupt activity that
     // has altered the stack.
@@ -200,10 +204,10 @@ void gcode_M100() {
   if (m100_not_initialized || code_seen('I')) {       // If no sub-command is specified, the first time
     SERIAL_ECHOLNPGM("Initializing free memory block.\n");    // this happens, it will Initialize.
     ptr = (unsigned char*) __brkval;        // Repeated M100 with no sub-command will not destroy the
-    SERIAL_ECHOPAIR("\n__brkval : ", (long) ptr);     // state of the initialized free memory pool.
+    SERIAL_ECHOPAIR("\n__brkval : ", ptr);     // state of the initialized free memory pool.
     ptr += 8;
     sp = top_of_stack();
-    SERIAL_ECHOPAIR("\nStack Pointer : ", (long) sp);
+    SERIAL_ECHOPAIR("\nStack Pointer : ", sp);
     SERIAL_ECHOLNPGM("\n");
     n = sp - ptr - 64;    // -64 just to keep us from finding interrupt activity that
     // has altered the stack.
@@ -213,7 +217,7 @@ void gcode_M100() {
       *(ptr + i) = (unsigned char) 0xe5;
     for (i = 0; i < n; i++) {
       if (*(ptr + i) != (unsigned char) 0xe5) {
-        SERIAL_ECHOPAIR("? address : ", (unsigned long) ptr + i);
+        SERIAL_ECHOPAIR("? address : ", ptr + i);
         SERIAL_ECHOPAIR("=", *(ptr + i));
         SERIAL_ECHOLNPGM("\n");
       }
diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h
index c425a3b04941820db409c1c333cd68a3f99941e7..aa3d54de772d55c169d5de178740447f734e73fc 100644
--- a/Marlin/Marlin.h
+++ b/Marlin/Marlin.h
@@ -65,6 +65,8 @@ typedef unsigned long millis_t;
 
 #include "WString.h"
 
+#include "stopwatch.h"
+
 #ifdef USBCON
   #if ENABLED(BLUETOOTH)
     #define MYSERIAL bluetoothSerial
@@ -101,13 +103,15 @@ extern const char echomagic[] PROGMEM;
 #define SERIAL_ECHOLN(x) SERIAL_PROTOCOLLN(x)
 #define SERIAL_ECHOLNPGM(x) SERIAL_PROTOCOLLNPGM(x)
 
-#define SERIAL_ECHOPAIR(name,value) do{ serial_echopair_P(PSTR(name),(value)); }while(0)
+#define SERIAL_ECHOPAIR(name,value) (serial_echopair_P(PSTR(name),(value)))
 
 void serial_echopair_P(const char* s_P, int v);
 void serial_echopair_P(const char* s_P, long v);
 void serial_echopair_P(const char* s_P, float v);
 void serial_echopair_P(const char* s_P, double v);
 void serial_echopair_P(const char* s_P, unsigned long v);
+FORCE_INLINE void serial_echopair_P(const char* s_P, bool v) { serial_echopair_P(s_P, (int)v); }
+FORCE_INLINE void serial_echopair_P(const char* s_P, void *v) { serial_echopair_P(s_P, (unsigned long)v); }
 
 // Things to write to serial from Program memory. Saves 400 to 2k of RAM.
 FORCE_INLINE void serialprintPGM(const char* str) {
@@ -323,6 +327,10 @@ extern bool axis_homed[3]; // axis[n].is_homed
   extern float zprobe_zoffset;
 #endif
 
+#if ENABLED(HOST_KEEPALIVE_FEATURE)
+  extern uint8_t host_keepalive_interval;
+#endif
+
 #if ENABLED(PREVENT_DANGEROUS_EXTRUDE)
   extern float extrude_min_temp;
 #endif
@@ -341,8 +349,7 @@ extern bool axis_homed[3]; // axis[n].is_homed
   extern bool filament_sensor;  //indicates that filament sensor readings should control extrusion
   extern float filament_width_meas; //holds the filament diameter as accurately measured
   extern int8_t measurement_delay[];  //ring buffer to delay measurement
-  extern int delay_index1, delay_index2;  //ring buffer index. used by planner, temperature, and main code
-  extern float delay_dist; //delay distance counter
+  extern int filwidth_delay_index1, filwidth_delay_index2;  //ring buffer index. used by planner, temperature, and main code
   extern int meas_delay_cm; //delay distance
 #endif
 
@@ -357,8 +364,8 @@ extern bool axis_homed[3]; // axis[n].is_homed
   extern float retract_recover_length, retract_recover_length_swap, retract_recover_feedrate;
 #endif
 
-extern millis_t print_job_start_ms;
-extern millis_t print_job_stop_ms;
+// Print job timer
+extern Stopwatch print_job_timer;
 
 // Handling multiple extruders pins
 extern uint8_t active_extruder;
@@ -368,15 +375,10 @@ extern uint8_t active_extruder;
   extern void digipot_i2c_init();
 #endif
 
-#if HAS_TEMP_0 || HAS_TEMP_BED || ENABLED(HEATER_0_USES_MAX6675)
+#if HAS_TEMP_HOTEND || HAS_TEMP_BED
   void print_heaterstates();
 #endif
 
 extern void calculate_volumetric_multipliers();
 
-// Print job timer related functions
-millis_t print_job_timer();
-bool print_job_start(millis_t t = 0);
-bool print_job_stop(bool force = false);
-
 #endif //MARLIN_H
diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp
index 968555ca4aa2087869107c1559635bf30df69a63..3759a07b708cd816ec0aabb14f183a3e470190af 100644
--- a/Marlin/Marlin_main.cpp
+++ b/Marlin/Marlin_main.cpp
@@ -77,6 +77,10 @@
   #include "stepper_dac.h"
 #endif
 
+#if ENABLED(EXPERIMENTAL_I2CBUS)
+  #include "twibus.h"
+#endif
+
 /**
  * Look here for descriptions of G-codes:
  *  - http://linuxcnc.org/handbook/gcode/g-code.html
@@ -151,6 +155,7 @@
  * M110 - Set the current line number
  * M111 - Set debug flags with S<mask>. See flag bits defined in Marlin.h.
  * M112 - Emergency stop
+ * M113 - Get or set the timeout interval for Host Keepalive "busy" messages
  * M114 - Output current position to serial port
  * M115 - Capabilities string
  * M117 - Display a message on the controller screen
@@ -248,6 +253,10 @@
   CardReader card;
 #endif
 
+#if ENABLED(EXPERIMENTAL_I2CBUS)
+  TWIBus i2c;
+#endif
+
 bool Running = true;
 
 uint8_t marlin_debug_flags = DEBUG_NONE;
@@ -298,8 +307,7 @@ const int sensitive_pins[] = SENSITIVE_PINS; ///< Sensitive pin list for M42
 millis_t previous_cmd_ms = 0;
 static millis_t max_inactive_time = 0;
 static millis_t stepper_inactive_time = (DEFAULT_STEPPER_DEACTIVE_TIME) * 1000L;
-millis_t print_job_start_ms = 0; ///< Print job start time
-millis_t print_job_stop_ms = 0;  ///< Print job stop time
+Stopwatch print_job_timer = Stopwatch();
 static uint8_t target_extruder;
 
 #if ENABLED(AUTO_BED_LEVELING_FEATURE)
@@ -411,9 +419,8 @@ static uint8_t target_extruder;
   bool filament_sensor = false;  //M405 turns on filament_sensor control, M406 turns it off
   float filament_width_meas = DEFAULT_MEASURED_FILAMENT_DIA; //Stores the measured filament diameter
   int8_t measurement_delay[MAX_MEASUREMENT_DELAY + 1]; //ring buffer to delay measurement  store extruder factor after subtracting 100
-  int delay_index1 = 0;  //index into ring buffer
-  int delay_index2 = -1;  //index into ring buffer - set to -1 on startup to indicate ring buffer needs to be initialized
-  float delay_dist = 0; //delay distance counter
+  int filwidth_delay_index1 = 0;  //index into ring buffer
+  int filwidth_delay_index2 = -1;  //index into ring buffer - set to -1 on startup to indicate ring buffer needs to be initialized
   int meas_delay_cm = MEASUREMENT_DELAY_CM;  //distance delay setting
 #endif
 
@@ -449,7 +456,8 @@ static bool send_ok[BUFSIZE];
   };
 
   static MarlinBusyState busy_state = NOT_BUSY;
-  static millis_t next_busy_signal_ms = -1;
+  static millis_t prev_busy_signal_ms = -1;
+  uint8_t host_keepalive_interval = DEFAULT_KEEPALIVE_INTERVAL;
   #define KEEPALIVE_STATE(n) do{ busy_state = n; }while(0)
 #else
   #define host_keepalive() ;
@@ -1012,9 +1020,9 @@ inline void get_serial_commands() {
       ) {
         if (card_eof) {
           SERIAL_PROTOCOLLNPGM(MSG_FILE_PRINTED);
-          print_job_stop(true);
+          print_job_timer.stop();
           char time[30];
-          millis_t t = print_job_timer();
+          millis_t t = print_job_timer.duration();
           int hours = t / 60 / 60, minutes = (t / 60) % 60;
           sprintf_P(time, PSTR("%i " MSG_END_HOUR " %i " MSG_END_MINUTE), hours, minutes);
           SERIAL_ECHO_START;
@@ -1164,9 +1172,16 @@ XYZ_CONSTS_FROM_CONFIG(signed char, home_dir, HOME_DIR);
   void print_xyz(const char* prefix, const float xyz[]) {
     print_xyz(prefix, xyz[X_AXIS], xyz[Y_AXIS], xyz[Z_AXIS]);
   }
+  #define DEBUG_POS(PREFIX,VAR) do{ SERIAL_ECHOPGM(PREFIX); print_xyz(" > " STRINGIFY(VAR), VAR); }while(0)
 #endif
 
 static void set_axis_is_at_home(AxisEnum axis) {
+  #if ENABLED(DEBUG_LEVELING_FEATURE)
+    if (DEBUGGING(LEVELING)) {
+      SERIAL_ECHOPAIR("set_axis_is_at_home(", axis);
+      SERIAL_ECHOLNPGM(") >>>");
+    }
+  #endif
 
   #if ENABLED(DUAL_X_CARRIAGE)
     if (axis == X_AXIS) {
@@ -1234,17 +1249,30 @@ static void set_axis_is_at_home(AxisEnum axis) {
     max_pos[axis] = base_max_pos(axis) + home_offset[axis];
 
     #if ENABLED(AUTO_BED_LEVELING_FEATURE) && Z_HOME_DIR < 0
-      if (axis == Z_AXIS) current_position[Z_AXIS] -= zprobe_zoffset;
+      if (axis == Z_AXIS) {
+        current_position[Z_AXIS] -= zprobe_zoffset;
+        #if ENABLED(DEBUG_LEVELING_FEATURE)
+          if (DEBUGGING(LEVELING)) {
+            SERIAL_ECHOPAIR("> zprobe_zoffset==", zprobe_zoffset);
+            SERIAL_EOL;
+          }
+        #endif
+      }
     #endif
 
     #if ENABLED(DEBUG_LEVELING_FEATURE)
       if (DEBUGGING(LEVELING)) {
-        SERIAL_ECHOPAIR("set_axis_is_at_home ", (unsigned long)axis);
-        SERIAL_ECHOPAIR(" > (home_offset[axis]==", home_offset[axis]);
-        print_xyz(") > current_position", current_position);
+        SERIAL_ECHOPAIR("> home_offset[axis]==", home_offset[axis]);
+        DEBUG_POS("", current_position);
       }
     #endif
   }
+  #if ENABLED(DEBUG_LEVELING_FEATURE)
+    if (DEBUGGING(LEVELING)) {
+      SERIAL_ECHOPAIR("<<< set_axis_is_at_home(", axis);
+      SERIAL_ECHOLNPGM(")");
+    }
+  #endif
 }
 
 /**
@@ -1273,10 +1301,16 @@ inline void line_to_destination() {
   line_to_destination(feedrate);
 }
 inline void sync_plan_position() {
+  #if ENABLED(DEBUG_LEVELING_FEATURE)
+    if (DEBUGGING(LEVELING)) DEBUG_POS("sync_plan_position", current_position);
+  #endif
   plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
 }
 #if ENABLED(DELTA) || ENABLED(SCARA)
   inline void sync_plan_position_delta() {
+    #if ENABLED(DEBUG_LEVELING_FEATURE)
+      if (DEBUGGING(LEVELING)) DEBUG_POS("sync_plan_position_delta", current_position);
+    #endif
     calculate_delta(current_position);
     plan_set_position(delta[X_AXIS], delta[Y_AXIS], delta[Z_AXIS], current_position[E_AXIS]);
   }
@@ -1290,9 +1324,7 @@ static void setup_for_endstop_move() {
   feedrate_multiplier = 100;
   refresh_cmd_timeout();
   #if ENABLED(DEBUG_LEVELING_FEATURE)
-    if (DEBUGGING(LEVELING)) {
-      SERIAL_ECHOLNPGM("setup_for_endstop_move > enable_endstops(true)");
-    }
+    if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("setup_for_endstop_move > enable_endstops(true)");
   #endif
   enable_endstops(true);
 }
@@ -1305,9 +1337,7 @@ static void setup_for_endstop_move() {
      */
     void prepare_move_raw() {
       #if ENABLED(DEBUG_LEVELING_FEATURE)
-        if (DEBUGGING(LEVELING)) {
-          print_xyz("prepare_move_raw > destination", destination);
-        }
+        if (DEBUGGING(LEVELING)) DEBUG_POS("prepare_move_raw", destination);
       #endif
       refresh_cmd_timeout();
       calculate_delta(destination);
@@ -1321,13 +1351,17 @@ static void setup_for_endstop_move() {
     #if DISABLED(DELTA)
 
       static void set_bed_level_equation_lsq(double* plane_equation_coefficients) {
+        #if ENABLED(DEBUG_LEVELING_FEATURE)
+          if (DEBUGGING(LEVELING)) DEBUG_POS("BEFORE set_bed_level_equation_lsq", current_position);
+        #endif
+
         vector_3 planeNormal = vector_3(-plane_equation_coefficients[0], -plane_equation_coefficients[1], 1);
-        planeNormal.debug("planeNormal");
+        // planeNormal.debug("planeNormal");
         plan_bed_level_matrix = matrix_3x3::create_look_at(planeNormal);
         //bedLevel.debug("bedLevel");
 
         //plan_bed_level_matrix.debug("bed level before");
-        //vector_3 uncorrected_position = plan_get_position_mm();
+        //vector_3 uncorrected_position = plan_get_position();
         //uncorrected_position.debug("position before");
 
         vector_3 corrected_position = plan_get_position();
@@ -1337,9 +1371,7 @@ static void setup_for_endstop_move() {
         current_position[Z_AXIS] = corrected_position.z;
 
         #if ENABLED(DEBUG_LEVELING_FEATURE)
-          if (DEBUGGING(LEVELING)) {
-            print_xyz("set_bed_level_equation_lsq > current_position", current_position);
-          }
+          if (DEBUGGING(LEVELING)) DEBUG_POS("AFTER set_bed_level_equation_lsq", current_position);
         #endif
 
         sync_plan_position();
@@ -1372,9 +1404,7 @@ static void setup_for_endstop_move() {
       current_position[Z_AXIS] = corrected_position.z;
 
       #if ENABLED(DEBUG_LEVELING_FEATURE)
-        if (DEBUGGING(LEVELING)) {
-          print_xyz("set_bed_level_equation_3pts > current_position", current_position);
-        }
+        if (DEBUGGING(LEVELING)) DEBUG_POS("set_bed_level_equation_3pts", current_position);
       #endif
 
       sync_plan_position();
@@ -1396,9 +1426,7 @@ static void setup_for_endstop_move() {
       long start_steps = st_get_position(Z_AXIS);
 
       #if ENABLED(DEBUG_LEVELING_FEATURE)
-        if (DEBUGGING(LEVELING)) {
-          SERIAL_ECHOLNPGM("run_z_probe (DELTA) 1");
-        }
+        if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("run_z_probe (DELTA) 1");
       #endif
 
       // move down slowly until you find the bed
@@ -1417,9 +1445,7 @@ static void setup_for_endstop_move() {
       current_position[Z_AXIS] = mm;
 
       #if ENABLED(DEBUG_LEVELING_FEATURE)
-        if (DEBUGGING(LEVELING)) {
-          print_xyz("run_z_probe (DELTA) 2 > current_position", current_position);
-        }
+        if (DEBUGGING(LEVELING)) DEBUG_POS("run_z_probe (DELTA) 2", current_position);
       #endif
 
       sync_plan_position_delta();
@@ -1460,9 +1486,7 @@ static void setup_for_endstop_move() {
       sync_plan_position();
 
       #if ENABLED(DEBUG_LEVELING_FEATURE)
-        if (DEBUGGING(LEVELING)) {
-          print_xyz("run_z_probe > current_position", current_position);
-        }
+        if (DEBUGGING(LEVELING)) DEBUG_POS("run_z_probe", current_position);
       #endif
 
     #endif // !DELTA
@@ -1476,9 +1500,7 @@ static void setup_for_endstop_move() {
     float oldFeedRate = feedrate;
 
     #if ENABLED(DEBUG_LEVELING_FEATURE)
-      if (DEBUGGING(LEVELING)) {
-        print_xyz("do_blocking_move_to", x, y, z);
-      }
+      if (DEBUGGING(LEVELING)) print_xyz("do_blocking_move_to", x, y, z);
     #endif
 
     #if ENABLED(DELTA)
@@ -1529,9 +1551,7 @@ static void setup_for_endstop_move() {
 
   static void clean_up_after_endstop_move() {
     #if ENABLED(DEBUG_LEVELING_FEATURE)
-      if (DEBUGGING(LEVELING)) {
-        SERIAL_ECHOLNPGM("clean_up_after_endstop_move > ENDSTOPS_ONLY_FOR_HOMING > endstops_not_homing()");
-      }
+      if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("clean_up_after_endstop_move > ENDSTOPS_ONLY_FOR_HOMING > endstops_not_homing()");
     #endif
     endstops_not_homing();
     feedrate = saved_feedrate;
@@ -1544,9 +1564,7 @@ static void setup_for_endstop_move() {
   static void deploy_z_probe() {
 
     #if ENABLED(DEBUG_LEVELING_FEATURE)
-      if (DEBUGGING(LEVELING)) {
-        print_xyz("deploy_z_probe > current_position", current_position);
-      }
+      if (DEBUGGING(LEVELING)) DEBUG_POS("deploy_z_probe", current_position);
     #endif
 
     if (z_probe_is_active) return;
@@ -1638,10 +1656,11 @@ static void setup_for_endstop_move() {
   }
 
   static void stow_z_probe(bool doRaise = true) {
+    #if !(HAS_SERVO_ENDSTOPS && (Z_RAISE_AFTER_PROBING > 0))
+      UNUSED(doRaise);
+    #endif
     #if ENABLED(DEBUG_LEVELING_FEATURE)
-      if (DEBUGGING(LEVELING)) {
-        print_xyz("stow_z_probe > current_position", current_position);
-      }
+      if (DEBUGGING(LEVELING)) DEBUG_POS("stow_z_probe", current_position);
     #endif
 
     if (!z_probe_is_active) return;
@@ -1655,7 +1674,7 @@ static void setup_for_endstop_move() {
           if (doRaise) {
             #if ENABLED(DEBUG_LEVELING_FEATURE)
               if (DEBUGGING(LEVELING)) {
-                SERIAL_ECHOPAIR("Raise Z (after) by ", (float)Z_RAISE_AFTER_PROBING);
+                SERIAL_ECHOPAIR("Raise Z (after) by ", Z_RAISE_AFTER_PROBING);
                 SERIAL_EOL;
                 SERIAL_ECHO("> SERVO_ENDSTOPS > raise_z_after_probing()");
                 SERIAL_EOL;
@@ -1751,9 +1770,9 @@ static void setup_for_endstop_move() {
     #if ENABLED(DEBUG_LEVELING_FEATURE)
       if (DEBUGGING(LEVELING)) {
         SERIAL_ECHOLNPGM("probe_pt >>>");
-        SERIAL_ECHOPAIR("> ProbeAction:", (unsigned long)probe_action);
+        SERIAL_ECHOPAIR("> ProbeAction:", probe_action);
         SERIAL_EOL;
-        print_xyz("> current_position", current_position);
+        DEBUG_POS("", current_position);
       }
     #endif
 
@@ -1783,9 +1802,7 @@ static void setup_for_endstop_move() {
     #if DISABLED(Z_PROBE_SLED) && DISABLED(Z_PROBE_ALLEN_KEY)
       if (probe_action & ProbeDeploy) {
         #if ENABLED(DEBUG_LEVELING_FEATURE)
-          if (DEBUGGING(LEVELING)) {
-            SERIAL_ECHOLNPGM("> ProbeDeploy");
-          }
+          if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("> ProbeDeploy");
         #endif
         deploy_z_probe();
       }
@@ -1797,9 +1814,7 @@ static void setup_for_endstop_move() {
     #if DISABLED(Z_PROBE_SLED) && DISABLED(Z_PROBE_ALLEN_KEY)
       if (probe_action & ProbeStow) {
         #if ENABLED(DEBUG_LEVELING_FEATURE)
-          if (DEBUGGING(LEVELING)) {
-            SERIAL_ECHOLNPGM("> ProbeStow (stow_z_probe will do Z Raise)");
-          }
+          if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("> ProbeStow (stow_z_probe will do Z Raise)");
         #endif
         stow_z_probe();
       }
@@ -1816,9 +1831,7 @@ static void setup_for_endstop_move() {
     }
 
     #if ENABLED(DEBUG_LEVELING_FEATURE)
-      if (DEBUGGING(LEVELING)) {
-        SERIAL_ECHOLNPGM("<<< probe_pt");
-      }
+      if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("<<< probe_pt");
     #endif
 
     return measured_z;
@@ -1883,9 +1896,7 @@ static void setup_for_endstop_move() {
      */
     void reset_bed_level() {
       #if ENABLED(DEBUG_LEVELING_FEATURE)
-        if (DEBUGGING(LEVELING)) {
-          SERIAL_ECHOLNPGM("reset_bed_level");
-        }
+        if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("reset_bed_level");
       #endif
       for (int y = 0; y < AUTO_BED_LEVELING_GRID_POINTS; y++) {
         for (int x = 0; x < AUTO_BED_LEVELING_GRID_POINTS; x++) {
@@ -1912,11 +1923,13 @@ static void setup_for_endstop_move() {
 
 #endif // AUTO_BED_LEVELING_FEATURE
 
-static void axis_unhomed_error() {
-  LCD_MESSAGEPGM(MSG_YX_UNHOMED);
-  SERIAL_ECHO_START;
-  SERIAL_ECHOLNPGM(MSG_YX_UNHOMED);
-}
+#if ENABLED(Z_PROBE_SLED) || ENABLED(Z_SAFE_HOMING) || ENABLED(AUTO_BED_LEVELING_FEATURE)
+  static void axis_unhomed_error() {
+    LCD_MESSAGEPGM(MSG_YX_UNHOMED);
+    SERIAL_ECHO_START;
+    SERIAL_ECHOLNPGM(MSG_YX_UNHOMED);
+  }
+#endif
 
 #if ENABLED(Z_PROBE_SLED)
 
@@ -1933,8 +1946,8 @@ static void axis_unhomed_error() {
   static void dock_sled(bool dock, int offset = 0) {
     #if ENABLED(DEBUG_LEVELING_FEATURE)
       if (DEBUGGING(LEVELING)) {
-        SERIAL_ECHOPAIR("dock_sled", dock);
-        SERIAL_EOL;
+        SERIAL_ECHOPAIR("dock_sled(", dock);
+        SERIAL_ECHOLNPGM(")");
       }
     #endif
 
@@ -1978,9 +1991,8 @@ static void axis_unhomed_error() {
 static void homeaxis(AxisEnum axis) {
   #if ENABLED(DEBUG_LEVELING_FEATURE)
     if (DEBUGGING(LEVELING)) {
-      SERIAL_ECHOPAIR(">>> homeaxis(", (unsigned long)axis);
-      SERIAL_CHAR(')');
-      SERIAL_EOL;
+      SERIAL_ECHOPAIR(">>> homeaxis(", axis);
+      SERIAL_ECHOLNPGM(")");
     }
   #endif
   #define HOMEAXIS_DO(LETTER) \
@@ -2045,9 +2057,7 @@ static void homeaxis(AxisEnum axis) {
     sync_plan_position();
 
     #if ENABLED(DEBUG_LEVELING_FEATURE)
-      if (DEBUGGING(LEVELING)) {
-        SERIAL_ECHOLNPGM("> enable_endstops(false)");
-      }
+      if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("> enable_endstops(false)");
     #endif
     enable_endstops(false); // Disable endstops while moving away
 
@@ -2057,9 +2067,7 @@ static void homeaxis(AxisEnum axis) {
     st_synchronize();
 
     #if ENABLED(DEBUG_LEVELING_FEATURE)
-      if (DEBUGGING(LEVELING)) {
-        SERIAL_ECHOLNPGM("> enable_endstops(true)");
-      }
+      if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("> enable_endstops(true)");
     #endif
     enable_endstops(true); // Enable endstops for next homing move
 
@@ -2072,9 +2080,7 @@ static void homeaxis(AxisEnum axis) {
     st_synchronize();
 
     #if ENABLED(DEBUG_LEVELING_FEATURE)
-      if (DEBUGGING(LEVELING)) {
-        print_xyz("> TRIGGER ENDSTOP > current_position", current_position);
-      }
+      if (DEBUGGING(LEVELING)) DEBUG_POS("> TRIGGER ENDSTOP", current_position);
     #endif
 
     #if ENABLED(Z_DUAL_ENDSTOPS)
@@ -2106,9 +2112,7 @@ static void homeaxis(AxisEnum axis) {
       // retrace by the amount specified in endstop_adj
       if (endstop_adj[axis] * axis_home_dir < 0) {
         #if ENABLED(DEBUG_LEVELING_FEATURE)
-          if (DEBUGGING(LEVELING)) {
-            SERIAL_ECHOLNPGM("> enable_endstops(false)");
-          }
+          if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("> enable_endstops(false)");
         #endif
         enable_endstops(false); // Disable endstops while moving away
         sync_plan_position();
@@ -2116,15 +2120,13 @@ static void homeaxis(AxisEnum axis) {
         #if ENABLED(DEBUG_LEVELING_FEATURE)
           if (DEBUGGING(LEVELING)) {
             SERIAL_ECHOPAIR("> endstop_adj = ", endstop_adj[axis]);
-            print_xyz(" > destination", destination);
+            DEBUG_POS("", destination);
           }
         #endif
         line_to_destination();
         st_synchronize();
         #if ENABLED(DEBUG_LEVELING_FEATURE)
-          if (DEBUGGING(LEVELING)) {
-            SERIAL_ECHOLNPGM("> enable_endstops(true)");
-          }
+          if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("> enable_endstops(true)");
         #endif
         enable_endstops(true); // Enable endstops for next homing move
       }
@@ -2143,9 +2145,7 @@ static void homeaxis(AxisEnum axis) {
     sync_plan_position();
 
     #if ENABLED(DEBUG_LEVELING_FEATURE)
-      if (DEBUGGING(LEVELING)) {
-        print_xyz("> AFTER set_axis_is_at_home > current_position", current_position);
-      }
+      if (DEBUGGING(LEVELING)) DEBUG_POS("> AFTER set_axis_is_at_home", current_position);
     #endif
 
     destination[axis] = current_position[axis];
@@ -2158,9 +2158,7 @@ static void homeaxis(AxisEnum axis) {
     #if ENABLED(Z_PROBE_SLED) || SERVO_LEVELING || ENABLED(FIX_MOUNTED_PROBE)
       if (axis == Z_AXIS && axis_home_dir < 0) {
         #if ENABLED(DEBUG_LEVELING_FEATURE)
-          if (DEBUGGING(LEVELING)) {
-            SERIAL_ECHOLNPGM("> SERVO_LEVELING > " STRINGIFY(_Z_STOW));
-          }
+          if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("> SERVO_LEVELING > " STRINGIFY(_Z_STOW));
         #endif
         _Z_STOW;
       }
@@ -2170,9 +2168,7 @@ static void homeaxis(AxisEnum axis) {
     #if HAS_SERVO_ENDSTOPS
       if (_Z_SERVO_TEST && servo_endstop_id[axis] >= 0) {
         #if ENABLED(DEBUG_LEVELING_FEATURE)
-          if (DEBUGGING(LEVELING)) {
-            SERIAL_ECHOLNPGM("> SERVO_ENDSTOPS > Stow with servo.move()");
-          }
+          if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("> SERVO_ENDSTOPS > Stow with servo.move()");
         #endif
         servo[servo_endstop_id[axis]].move(servo_endstop_angle[axis][1]);
         if (_Z_PROBE_SUBTEST) z_probe_is_active = false;
@@ -2183,9 +2179,8 @@ static void homeaxis(AxisEnum axis) {
 
   #if ENABLED(DEBUG_LEVELING_FEATURE)
     if (DEBUGGING(LEVELING)) {
-      SERIAL_ECHOPAIR("<<< homeaxis(", (unsigned long)axis);
-      SERIAL_CHAR(')');
-      SERIAL_EOL;
+      SERIAL_ECHOPAIR("<<< homeaxis(", axis);
+      SERIAL_ECHOLNPGM(")");
     }
   #endif
 }
@@ -2284,8 +2279,8 @@ void unknown_command_error() {
    */
   void host_keepalive() {
     millis_t ms = millis();
-    if (busy_state != NOT_BUSY) {
-      if (ms < next_busy_signal_ms) return;
+    if (host_keepalive_interval && busy_state != NOT_BUSY) {
+      if (ms - prev_busy_signal_ms < 1000UL * host_keepalive_interval) return;
       switch (busy_state) {
         case IN_HANDLER:
         case IN_PROCESS:
@@ -2300,9 +2295,11 @@ void unknown_command_error() {
           SERIAL_ECHO_START;
           SERIAL_ECHOLNPGM(MSG_BUSY_PAUSED_FOR_INPUT);
           break;
+        default:
+          break;
       }
     }
-    next_busy_signal_ms = ms + 10000UL; // "busy: ..." message every 10s
+    prev_busy_signal_ms = ms;
   }
 
 #endif //HOST_KEEPALIVE_FEATURE
@@ -2421,9 +2418,7 @@ inline void gcode_G4() {
 inline void gcode_G28() {
 
   #if ENABLED(DEBUG_LEVELING_FEATURE)
-    if (DEBUGGING(LEVELING)) {
-      SERIAL_ECHOLNPGM("gcode_G28 >>>");
-    }
+    if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("gcode_G28 >>>");
   #endif
 
   // Wait for planner moves to finish!
@@ -2484,9 +2479,7 @@ inline void gcode_G28() {
     sync_plan_position_delta();
 
     #if ENABLED(DEBUG_LEVELING_FEATURE)
-      if (DEBUGGING(LEVELING)) {
-        print_xyz("(DELTA) > current_position", current_position);
-      }
+      if (DEBUGGING(LEVELING)) DEBUG_POS("(DELTA)", current_position);
     #endif
 
   #else // NOT DELTA
@@ -2502,9 +2495,7 @@ inline void gcode_G28() {
       if (home_all_axis || homeZ) {
         HOMEAXIS(Z);
         #if ENABLED(DEBUG_LEVELING_FEATURE)
-          if (DEBUGGING(LEVELING)) {
-            print_xyz("> HOMEAXIS(Z) > current_position", current_position);
-          }
+          if (DEBUGGING(LEVELING)) DEBUG_POS("> HOMEAXIS(Z)", current_position);
         #endif
       }
 
@@ -2516,10 +2507,10 @@ inline void gcode_G28() {
         feedrate = max_feedrate[Z_AXIS] * 60;  // feedrate (mm/m) = max_feedrate (mm/s)
         #if ENABLED(DEBUG_LEVELING_FEATURE)
           if (DEBUGGING(LEVELING)) {
-            SERIAL_ECHOPAIR("Raise Z (before homing) to ", (float)(MIN_Z_HEIGHT_FOR_HOMING));
+            SERIAL_ECHOPAIR("Raise Z (before homing) to ", (MIN_Z_HEIGHT_FOR_HOMING));
             SERIAL_EOL;
-            print_xyz("> (home_all_axis || homeZ) > current_position", current_position);
-            print_xyz("> (home_all_axis || homeZ) > destination", destination);
+            DEBUG_POS("> (home_all_axis || homeZ)", current_position);
+            DEBUG_POS("> (home_all_axis || homeZ)", destination);
           }
         #endif
         line_to_destination();
@@ -2563,9 +2554,7 @@ inline void gcode_G28() {
         sync_plan_position();
 
         #if ENABLED(DEBUG_LEVELING_FEATURE)
-          if (DEBUGGING(LEVELING)) {
-            print_xyz("> QUICK_HOME > current_position 1", current_position);
-          }
+          if (DEBUGGING(LEVELING)) DEBUG_POS("> QUICK_HOME 1", current_position);
         #endif
 
         destination[X_AXIS] = current_position[X_AXIS];
@@ -2582,9 +2571,7 @@ inline void gcode_G28() {
         #endif
 
         #if ENABLED(DEBUG_LEVELING_FEATURE)
-          if (DEBUGGING(LEVELING)) {
-            print_xyz("> QUICK_HOME > current_position 2", current_position);
-          }
+          if (DEBUGGING(LEVELING)) DEBUG_POS("> QUICK_HOME 2", current_position);
         #endif
       }
 
@@ -2613,9 +2600,7 @@ inline void gcode_G28() {
         HOMEAXIS(X);
       #endif
       #if ENABLED(DEBUG_LEVELING_FEATURE)
-        if (DEBUGGING(LEVELING)) {
-          print_xyz("> homeX", current_position);
-        }
+        if (DEBUGGING(LEVELING)) DEBUG_POS("> homeX", current_position);
       #endif
     }
 
@@ -2624,9 +2609,7 @@ inline void gcode_G28() {
       if (home_all_axis || homeY) {
         HOMEAXIS(Y);
         #if ENABLED(DEBUG_LEVELING_FEATURE)
-          if (DEBUGGING(LEVELING)) {
-            print_xyz("> homeY", current_position);
-          }
+          if (DEBUGGING(LEVELING)) DEBUG_POS("> homeY", current_position);
         #endif
       }
     #endif
@@ -2665,8 +2648,8 @@ inline void gcode_G28() {
 
             #if ENABLED(DEBUG_LEVELING_FEATURE)
               if (DEBUGGING(LEVELING)) {
-                print_xyz("> Z_SAFE_HOMING > home_all_axis > current_position", current_position);
-                print_xyz("> Z_SAFE_HOMING > home_all_axis > destination", destination);
+                DEBUG_POS("> Z_SAFE_HOMING > home_all_axis", current_position);
+                DEBUG_POS("> Z_SAFE_HOMING > home_all_axis", destination);
               }
             #endif
 
@@ -2729,9 +2712,7 @@ inline void gcode_G28() {
         #endif // !Z_SAFE_HOMING
 
         #if ENABLED(DEBUG_LEVELING_FEATURE)
-          if (DEBUGGING(LEVELING)) {
-            print_xyz("> (home_all_axis || homeZ) > final", current_position);
-          }
+          if (DEBUGGING(LEVELING)) DEBUG_POS("> (home_all_axis || homeZ) > final", current_position);
         #endif
 
       } // home_all_axis || homeZ
@@ -2747,12 +2728,12 @@ inline void gcode_G28() {
   #endif
 
   #if ENABLED(ENDSTOPS_ONLY_FOR_HOMING)
+    enable_endstops(false);
     #if ENABLED(DEBUG_LEVELING_FEATURE)
       if (DEBUGGING(LEVELING)) {
         SERIAL_ECHOLNPGM("ENDSTOPS_ONLY_FOR_HOMING enable_endstops(false)");
       }
     #endif
-    enable_endstops(false);
   #endif
 
   // For mesh leveling move back to Z=0
@@ -2767,9 +2748,7 @@ inline void gcode_G28() {
       line_to_destination();
       st_synchronize();
       #if ENABLED(DEBUG_LEVELING_FEATURE)
-        if (DEBUGGING(LEVELING)) {
-          print_xyz("mbl_was_active > current_position", current_position);
-        }
+        if (DEBUGGING(LEVELING)) DEBUG_POS("mbl_was_active", current_position);
       #endif
     }
   #endif
@@ -2992,6 +2971,7 @@ inline void gcode_G28() {
     #if ENABLED(DEBUG_LEVELING_FEATURE)
       if (DEBUGGING(LEVELING)) {
         SERIAL_ECHOLNPGM("gcode_G29 >>>");
+        DEBUG_POS("", current_position);
       }
     #endif
 
@@ -3069,22 +3049,20 @@ inline void gcode_G28() {
 
     #endif // AUTO_BED_LEVELING_GRID
 
-    #if ENABLED(Z_PROBE_SLED)
-      dock_sled(false); // engage (un-dock) the Z probe
-    #elif ENABLED(Z_PROBE_ALLEN_KEY) || (ENABLED(DELTA) && SERVO_LEVELING)
-      deploy_z_probe();
-    #endif
-
-    st_synchronize();
-
     if (!dryrun) {
+
       // make sure the bed_level_rotation_matrix is identity or the planner will get it wrong
       plan_bed_level_matrix.set_to_identity();
 
       #if ENABLED(DELTA)
         reset_bed_level();
       #else //!DELTA
-        //vector_3 corrected_position = plan_get_position_mm();
+
+        #if ENABLED(DEBUG_LEVELING_FEATURE)
+          if (DEBUGGING(LEVELING)) DEBUG_POS("BEFORE matrix.set_to_identity", current_position);
+        #endif
+
+        //vector_3 corrected_position = plan_get_position();
         //corrected_position.debug("position before G29");
         vector_3 uncorrected_position = plan_get_position();
         //uncorrected_position.debug("position during G29");
@@ -3092,9 +3070,22 @@ inline void gcode_G28() {
         current_position[Y_AXIS] = uncorrected_position.y;
         current_position[Z_AXIS] = uncorrected_position.z;
         sync_plan_position();
+
+        #if ENABLED(DEBUG_LEVELING_FEATURE)
+          if (DEBUGGING(LEVELING)) DEBUG_POS("AFTER matrix.set_to_identity", current_position);
+        #endif
+
       #endif // !DELTA
     }
 
+    #if ENABLED(Z_PROBE_SLED)
+      dock_sled(false); // engage (un-dock) the Z probe
+    #elif ENABLED(Z_PROBE_ALLEN_KEY) || (ENABLED(DELTA) && SERVO_LEVELING)
+      deploy_z_probe();
+    #endif
+
+    st_synchronize();
+
     setup_for_endstop_move();
 
     feedrate = homing_feedrate[Z_AXIS];
@@ -3158,7 +3149,7 @@ inline void gcode_G28() {
           if (probePointCounter) {
             #if ENABLED(DEBUG_LEVELING_FEATURE)
               if (DEBUGGING(LEVELING)) {
-                SERIAL_ECHOPAIR("z_before = (between) ", (float)(Z_RAISE_BETWEEN_PROBINGS + current_position[Z_AXIS]));
+                SERIAL_ECHOPAIR("z_before = (between) ", (Z_RAISE_BETWEEN_PROBINGS + current_position[Z_AXIS]));
                 SERIAL_EOL;
               }
             #endif
@@ -3166,7 +3157,7 @@ inline void gcode_G28() {
           else {
             #if ENABLED(DEBUG_LEVELING_FEATURE)
               if (DEBUGGING(LEVELING)) {
-                SERIAL_ECHOPAIR("z_before = (before) ", (float)Z_RAISE_BEFORE_PROBING);
+                SERIAL_ECHOPAIR("z_before = (before) ", Z_RAISE_BEFORE_PROBING);
                 SERIAL_EOL;
               }
             #endif
@@ -3210,9 +3201,7 @@ inline void gcode_G28() {
       } //yProbe
 
       #if ENABLED(DEBUG_LEVELING_FEATURE)
-        if (DEBUGGING(LEVELING)) {
-          print_xyz("> probing complete > current_position", current_position);
-        }
+        if (DEBUGGING(LEVELING)) DEBUG_POS("> probing complete", current_position);
       #endif
 
       clean_up_after_endstop_move();
@@ -3409,9 +3398,7 @@ inline void gcode_G28() {
         sync_plan_position();
 
         #if ENABLED(DEBUG_LEVELING_FEATURE)
-          if (DEBUGGING(LEVELING)) {
-            print_xyz("> corrected Z in G29", current_position);
-          }
+          if (DEBUGGING(LEVELING)) DEBUG_POS("> corrected Z in G29", current_position);
         #endif
       }
 
@@ -3472,9 +3459,9 @@ inline void gcode_G28() {
 
       run_z_probe();
       SERIAL_PROTOCOLPGM("Bed X: ");
-      SERIAL_PROTOCOL(current_position[X_AXIS] + 0.0001);
+      SERIAL_PROTOCOL(current_position[X_AXIS] + X_PROBE_OFFSET_FROM_EXTRUDER + 0.0001);
       SERIAL_PROTOCOLPGM(" Y: ");
-      SERIAL_PROTOCOL(current_position[Y_AXIS] + 0.0001);
+      SERIAL_PROTOCOL(current_position[Y_AXIS] + Y_PROBE_OFFSET_FROM_EXTRUDER + 0.0001);
       SERIAL_PROTOCOLPGM(" Z: ");
       SERIAL_PROTOCOL(current_position[Z_AXIS] + 0.0001);
       SERIAL_EOL;
@@ -3528,6 +3515,9 @@ inline void gcode_G92() {
   inline void gcode_M0_M1() {
     char* args = current_command_args;
 
+    uint8_t test_value = 12;
+    SERIAL_ECHOPAIR("TEST", test_value);
+
     millis_t codenum = 0;
     bool hasP = false, hasS = false;
     if (code_seen('P')) {
@@ -3617,7 +3607,7 @@ inline void gcode_M17() {
    */
   inline void gcode_M24() {
     card.startFileprint();
-    print_job_start();
+    print_job_timer.start();
   }
 
   /**
@@ -3673,7 +3663,7 @@ inline void gcode_M17() {
  * M31: Get the time since the start of SD Print (or last M109)
  */
 inline void gcode_M31() {
-  millis_t t = print_job_timer();
+  millis_t t = print_job_timer.duration();
   int min = t / 60, sec = t % 60;
   char time[30];
   sprintf_P(time, PSTR("%i min, %i sec"), min, sec);
@@ -3709,7 +3699,7 @@ inline void gcode_M31() {
       card.startFileprint();
 
       // Procedure calls count as normal print time.
-      if (!call_procedure) print_job_start();
+      if (!call_procedure) print_job_timer.start();
     }
   }
 
@@ -3820,7 +3810,7 @@ inline void gcode_M42() {
     }
 
     double sum = 0.0, mean = 0.0, sigma = 0.0, sample_set[50];
-    uint8_t verbose_level = 1, n_samples = 10, n_legs = 0, schizoid_flag = 0;
+    int8_t verbose_level = 1, n_samples = 10, n_legs = 0, schizoid_flag = 0;
 
     if (code_seen('V')) {
       verbose_level = code_value_short();
@@ -4076,6 +4066,27 @@ inline void gcode_M42() {
 
 #endif // AUTO_BED_LEVELING_FEATURE && Z_MIN_PROBE_REPEATABILITY_TEST
 
+/**
+ * M75: Start print timer
+ */
+inline void gcode_M75() {
+  print_job_timer.start();
+}
+
+/**
+ * M76: Pause print timer
+ */
+inline void gcode_M76() {
+  print_job_timer.pause();
+}
+
+/**
+ * M77: Stop print timer
+ */
+inline void gcode_M77() {
+  print_job_timer.stop();
+}
+
 /**
  * M104: Set hot end temperature
  */
@@ -4083,9 +4094,6 @@ inline void gcode_M104() {
   if (setTargetedHotend(104)) return;
   if (DEBUGGING(DRYRUN)) return;
 
-  // Start hook must happen before setTargetHotend()
-  print_job_start();
-
   if (code_seen('S')) {
     float temp = code_value();
     setTargetHotend(temp, target_extruder);
@@ -4094,16 +4102,30 @@ inline void gcode_M104() {
         setTargetHotend1(temp == 0.0 ? 0.0 : temp + duplicate_extruder_temp_offset);
     #endif
 
+    /**
+     * We use half EXTRUDE_MINTEMP here to allow nozzles to be put into hot
+     * stand by mode, for instance in a dual extruder setup, without affecting
+     * the running print timer.
+     */
+    if (temp <= (EXTRUDE_MINTEMP)/2) {
+      print_job_timer.stop();
+      LCD_MESSAGEPGM(WELCOME_MSG);
+    }
+    /**
+     * We do not check if the timer is already running because this check will
+     * be done for us inside the Stopwatch::start() method thus a running timer
+     * will not restart.
+     */
+    else print_job_timer.start();
+
     if (temp > degHotend(target_extruder)) LCD_MESSAGEPGM(MSG_HEATING);
   }
-
-  if (print_job_stop()) LCD_MESSAGEPGM(WELCOME_MSG);
 }
 
-#if HAS_TEMP_0 || HAS_TEMP_BED || ENABLED(HEATER_0_USES_MAX6675)
+#if HAS_TEMP_HOTEND || HAS_TEMP_BED
 
   void print_heaterstates() {
-    #if HAS_TEMP_0 || ENABLED(HEATER_0_USES_MAX6675)
+    #if HAS_TEMP_HOTEND
       SERIAL_PROTOCOLPGM(" T:");
       SERIAL_PROTOCOL_F(degHotend(target_extruder), 1);
       SERIAL_PROTOCOLPGM(" /");
@@ -4179,10 +4201,10 @@ inline void gcode_M104() {
 inline void gcode_M105() {
   if (setTargetedHotend(105)) return;
 
-  #if HAS_TEMP_0 || HAS_TEMP_BED || ENABLED(HEATER_0_USES_MAX6675)
+  #if HAS_TEMP_HOTEND || HAS_TEMP_BED
     SERIAL_PROTOCOLPGM(MSG_OK);
     print_heaterstates();
-  #else // !HAS_TEMP_0 && !HAS_TEMP_BED
+  #else // !HAS_TEMP_HOTEND && !HAS_TEMP_BED
     SERIAL_ERROR_START;
     SERIAL_ERRORLNPGM(MSG_ERR_NO_THERMISTORS);
   #endif
@@ -4225,9 +4247,6 @@ inline void gcode_M109() {
   if (setTargetedHotend(109)) return;
   if (DEBUGGING(DRYRUN)) return;
 
-  // Start hook must happen before setTargetHotend()
-  print_job_start();
-
   no_wait_for_cooling = code_seen('S');
   if (no_wait_for_cooling || code_seen('R')) {
     float temp = code_value();
@@ -4237,11 +4256,25 @@ inline void gcode_M109() {
         setTargetHotend1(temp == 0.0 ? 0.0 : temp + duplicate_extruder_temp_offset);
     #endif
 
+    /**
+     * We use half EXTRUDE_MINTEMP here to allow nozzles to be put into hot
+     * stand by mode, for instance in a dual extruder setup, without affecting
+     * the running print timer.
+     */
+    if (temp <= (EXTRUDE_MINTEMP)/2) {
+      print_job_timer.stop();
+      LCD_MESSAGEPGM(WELCOME_MSG);
+    }
+    /**
+     * We do not check if the timer is already running because this check will
+     * be done for us inside the Stopwatch::start() method thus a running timer
+     * will not restart.
+     */
+    else print_job_timer.start();
+
     if (temp > degHotend(target_extruder)) LCD_MESSAGEPGM(MSG_HEATING);
   }
 
-  if (print_job_stop()) LCD_MESSAGEPGM(WELCOME_MSG);
-
   #if ENABLED(AUTOTEMP)
     autotemp_enabled = code_seen('F');
     if (autotemp_enabled) autotemp_factor = code_value();
@@ -4254,12 +4287,12 @@ inline void gcode_M109() {
 
   // Prevents a wait-forever situation if R is misused i.e. M109 R0
   // Try to calculate a ballpark safe margin by halving EXTRUDE_MINTEMP
-  if (degTargetHotend(target_extruder) < (EXTRUDE_MINTEMP/2)) return;
+  if (degTargetHotend(target_extruder) < (EXTRUDE_MINTEMP)/2) return;
 
   #ifdef TEMP_RESIDENCY_TIME
     long residency_start_ms = -1;
     // Loop until the temperature has stabilized
-    #define TEMP_CONDITIONS (residency_start_ms < 0 || now < residency_start_ms + (TEMP_RESIDENCY_TIME) * 1000UL)
+    #define TEMP_CONDITIONS (residency_start_ms == -1 || now < residency_start_ms + (TEMP_RESIDENCY_TIME) * 1000UL)
   #else
     // Loop until the temperature is very close target
     #define TEMP_CONDITIONS (isHeatingHotend(target_extruder))
@@ -4271,12 +4304,12 @@ inline void gcode_M109() {
     now = millis();
     if (now > next_temp_ms) { //Print temp & remaining time every 1s while waiting
       next_temp_ms = now + 1000UL;
-      #if HAS_TEMP_0 || HAS_TEMP_BED || ENABLED(HEATER_0_USES_MAX6675)
+      #if HAS_TEMP_HOTEND || HAS_TEMP_BED
         print_heaterstates();
       #endif
       #ifdef TEMP_RESIDENCY_TIME
         SERIAL_PROTOCOLPGM(" W:");
-        if (residency_start_ms >= 0) {
+        if (residency_start_ms != -1) {
           long rem = (((TEMP_RESIDENCY_TIME) * 1000UL) - (now - residency_start_ms)) / 1000UL;
           SERIAL_PROTOCOLLN(rem);
         }
@@ -4292,10 +4325,18 @@ inline void gcode_M109() {
     refresh_cmd_timeout(); // to prevent stepper_inactive_time from running out
 
     #ifdef TEMP_RESIDENCY_TIME
-      // Start the TEMP_RESIDENCY_TIME timer when we reach target temp for the first time.
-      // Restart the timer whenever the temperature falls outside the hysteresis.
-      if (labs(degHotend(target_extruder) - degTargetHotend(target_extruder)) > ((residency_start_ms < 0) ? TEMP_WINDOW : TEMP_HYSTERESIS))
+
+      float temp_diff = labs(degHotend(target_extruder) - degTargetHotend(target_extruder));
+
+      if (residency_start_ms == -1) {
+        // Start the TEMP_RESIDENCY_TIME timer when we reach target temp for the first time.
+        if (temp_diff < TEMP_WINDOW) residency_start_ms = millis();
+      }
+      else if (temp_diff > TEMP_HYSTERESIS) {
+        // Restart the timer whenever the temperature falls outside the hysteresis.
         residency_start_ms = millis();
+      }
+
     #endif //TEMP_RESIDENCY_TIME
 
   } // while(!cancel_heatup && TEMP_CONDITIONS)
@@ -4350,16 +4391,16 @@ inline void gcode_M110() {
 inline void gcode_M111() {
   marlin_debug_flags = code_seen('S') ? code_value_short() : DEBUG_NONE;
 
-  const char str_debug_1[] PROGMEM = MSG_DEBUG_ECHO;
-  const char str_debug_2[] PROGMEM = MSG_DEBUG_INFO;
-  const char str_debug_4[] PROGMEM = MSG_DEBUG_ERRORS;
-  const char str_debug_8[] PROGMEM = MSG_DEBUG_DRYRUN;
-  const char str_debug_16[] PROGMEM = MSG_DEBUG_COMMUNICATION;
+  const static char str_debug_1[] PROGMEM = MSG_DEBUG_ECHO;
+  const static char str_debug_2[] PROGMEM = MSG_DEBUG_INFO;
+  const static char str_debug_4[] PROGMEM = MSG_DEBUG_ERRORS;
+  const static char str_debug_8[] PROGMEM = MSG_DEBUG_DRYRUN;
+  const static char str_debug_16[] PROGMEM = MSG_DEBUG_COMMUNICATION;
   #if ENABLED(DEBUG_LEVELING_FEATURE)
-    const char str_debug_32[] PROGMEM = MSG_DEBUG_LEVELING;
+    const static char str_debug_32[] PROGMEM = MSG_DEBUG_LEVELING;
   #endif
 
-  const char* const debug_strings[] PROGMEM = {
+  const static char* const debug_strings[] PROGMEM = {
     str_debug_1, str_debug_2, str_debug_4, str_debug_8, str_debug_16,
     #if ENABLED(DEBUG_LEVELING_FEATURE)
       str_debug_32
@@ -4372,8 +4413,8 @@ inline void gcode_M111() {
     uint8_t comma = 0;
     for (uint8_t i = 0; i < COUNT(debug_strings); i++) {
       if (TEST(marlin_debug_flags, i)) {
-        if (comma++) SERIAL_CHAR('|');
-        serialprintPGM(debug_strings[i]);
+        if (comma++) SERIAL_CHAR(',');
+        serialprintPGM((char*)pgm_read_word(&(debug_strings[i])));
       }
     }
   }
@@ -4388,6 +4429,27 @@ inline void gcode_M111() {
  */
 inline void gcode_M112() { kill(PSTR(MSG_KILLED)); }
 
+#if ENABLED(HOST_KEEPALIVE_FEATURE)
+
+  /**
+   * M113: Get or set Host Keepalive interval (0 to disable)
+   *
+   *   S<seconds> Optional. Set the keepalive interval.
+   */
+  inline void gcode_M113() {
+    if (code_seen('S')) {
+      host_keepalive_interval = (uint8_t)code_value_short();
+      NOMORE(host_keepalive_interval, 60);
+    }
+    else {
+      SERIAL_ECHO_START;
+      SERIAL_ECHOPAIR("M113 S", (unsigned long)host_keepalive_interval);
+      SERIAL_EOL;
+    }
+  }
+
+#endif
+
 #if ENABLED(BARICUDA)
 
   #if HAS_HEATER_1
@@ -4748,6 +4810,57 @@ inline void gcode_M121() { enable_endstops_globally(false); }
 
 #endif // BLINKM
 
+#if ENABLED(EXPERIMENTAL_I2CBUS)
+
+  /**
+   * M155: Send data to a I2C slave device
+   *
+   * This is a PoC, the formating and arguments for the GCODE will
+   * change to be more compatible, the current proposal is:
+   *
+   *  M155 A<slave device address base 10> ; Sets the I2C slave address the data will be sent to
+   *
+   *  M155 B<byte-1 value in base 10>
+   *  M155 B<byte-2 value in base 10>
+   *  M155 B<byte-3 value in base 10>
+   *
+   *  M155 S1 ; Send the buffered data and reset the buffer
+   *  M155 R1 ; Reset the buffer without sending data
+   *
+   */
+  inline void gcode_M155() {
+    // Set the target address
+    if (code_seen('A'))
+      i2c.address((uint8_t) code_value_short());
+
+    // Add a new byte to the buffer
+    else if (code_seen('B'))
+      i2c.addbyte((int) code_value_short());
+
+    // Flush the buffer to the bus
+    else if (code_seen('S')) i2c.send();
+
+    // Reset and rewind the buffer
+    else if (code_seen('R')) i2c.reset();
+  }
+
+  /**
+   * M156: Request X bytes from I2C slave device
+   *
+   * Usage: M156 A<slave device address base 10> B<number of bytes>
+   */
+  inline void gcode_M156() {
+    uint8_t addr = code_seen('A') ? code_value_short() : 0;
+    int bytes    = code_seen('B') ? code_value_short() : 0;
+
+    if (addr && bytes) {
+      i2c.address(addr);
+      i2c.reqbytes(bytes);
+    }
+  }
+
+#endif //EXPERIMENTAL_I2CBUS
+
 /**
  * M200: Set filament diameter and set E axis units to cubic millimeters
  *
@@ -5473,13 +5586,13 @@ inline void gcode_M400() { st_synchronize(); }
     if (code_seen('D')) meas_delay_cm = code_value();
     NOMORE(meas_delay_cm, MAX_MEASUREMENT_DELAY);
 
-    if (delay_index2 == -1) { //initialize the ring buffer if it has not been done since startup
+    if (filwidth_delay_index2 == -1) { // Initialize the ring buffer if not done since startup
       int temp_ratio = widthFil_to_size_ratio();
 
-      for (delay_index1 = 0; delay_index1 < COUNT(measurement_delay); ++delay_index1)
-        measurement_delay[delay_index1] = temp_ratio - 100;  //subtract 100 to scale within a signed byte
+      for (uint8_t i = 0; i < COUNT(measurement_delay); ++i)
+        measurement_delay[i] = temp_ratio - 100;  // Subtract 100 to scale within a signed byte
 
-      delay_index1 = delay_index2 = 0;
+      filwidth_delay_index1 = filwidth_delay_index2 = 0;
     }
 
     filament_sensor = true;
@@ -5525,7 +5638,7 @@ inline void gcode_M410() { quickStop(); }
    * M421: Set a single Mesh Bed Leveling Z coordinate
    */
   inline void gcode_M421() {
-    float x, y, z;
+    float x = 0, y = 0, z = 0;
     bool err = false, hasX, hasY, hasZ;
     if ((hasX = code_seen('X'))) x = code_value();
     if ((hasY = code_seen('Y'))) y = code_value();
@@ -5688,7 +5801,10 @@ inline void gcode_M503() {
       return;
     }
 
-    float lastpos[NUM_AXIS], fr60 = feedrate / 60;
+    float lastpos[NUM_AXIS];
+    #if ENABLED(DELTA)
+      float fr60 = feedrate / 60;
+    #endif
 
     for (int i = 0; i < NUM_AXIS; i++)
       lastpos[i] = destination[i] = current_position[i];
@@ -5745,7 +5861,9 @@ inline void gcode_M503() {
     disable_e3();
     delay(100);
     LCD_ALERTMESSAGEPGM(MSG_FILAMENTCHANGE);
-    millis_t next_tick = 0;
+    #if DISABLED(AUTO_FILAMENT_CHANGE)
+      millis_t next_tick = 0;
+    #endif
     KEEPALIVE_STATE(PAUSED_FOR_USER);
     while (!lcd_clicked()) {
       #if DISABLED(AUTO_FILAMENT_CHANGE)
@@ -6264,6 +6382,18 @@ void process_next_command() {
           break;
       #endif // AUTO_BED_LEVELING_FEATURE && Z_MIN_PROBE_REPEATABILITY_TEST
 
+      case 75: // Start print timer
+        gcode_M75();
+        break;
+
+      case 76: // Pause print timer
+        gcode_M76();
+        break;
+
+      case 77: // Stop print timer
+        gcode_M77();
+        break;
+
       #if ENABLED(M100_FREE_MEMORY_WATCHER)
         case 100:
           gcode_M100();
@@ -6399,6 +6529,18 @@ void process_next_command() {
 
       #endif //BLINKM
 
+      #if ENABLED(EXPERIMENTAL_I2CBUS)
+
+        case 155:
+          gcode_M155();
+          break;
+
+        case 156:
+          gcode_M156();
+          break;
+
+      #endif //EXPERIMENTAL_I2CBUS
+
       case 200: // M200 D<millimeters> set filament diameter and set E axis units to cubic millimeters (use S0 to set back to millimeters).
         gcode_M200();
         break;
@@ -7680,50 +7822,3 @@ void calculate_volumetric_multipliers() {
   for (int i = 0; i < EXTRUDERS; i++)
     volumetric_multiplier[i] = calculate_volumetric_multiplier(filament_size[i]);
 }
-
-/**
- * Start the print job timer
- *
- * The print job is only started if all extruders have their target temp at zero
- * otherwise the print job timew would be reset everytime a M109 is received.
- *
- * @param t start timer timestamp
- *
- * @return true if the timer was started at function call
- */
-bool print_job_start(millis_t t /* = 0 */) {
-  for (int i = 0; i < EXTRUDERS; i++) if (degTargetHotend(i) > 0) return false;
-  print_job_start_ms = (t) ? t : millis();
-  print_job_stop_ms = 0;
-  return true;
-}
-
-/**
- * Check if the running print job has finished and stop the timer
- *
- * When the target temperature for all extruders is zero then we assume that the
- * print job has finished printing. There are some special conditions under which
- * this assumption may not be valid: If during a print job for some reason the
- * user decides to bring a nozzle temp down and only then heat the other afterwards.
- *
- * @param force stops the timer ignoring all pre-checks
- *
- * @return boolean true if the print job has finished printing
- */
-bool print_job_stop(bool force /* = false */) {
-  if (!print_job_start_ms) return false;
-  if (!force) for (int i = 0; i < EXTRUDERS; i++) if (degTargetHotend(i) > 0) return false;
-  print_job_stop_ms = millis();
-  return true;
-}
-
-/**
- * Output the print job timer in seconds
- *
- * @return the number of seconds
- */
-millis_t print_job_timer() {
-  if (!print_job_start_ms) return 0;
-  return (((print_job_stop_ms > print_job_start_ms)
-    ? print_job_stop_ms : millis()) - print_job_start_ms) / 1000;
-}
diff --git a/Marlin/SanityCheck.h b/Marlin/SanityCheck.h
index fb45e77b9f6b0e5162e9eee915a7528043c02f70..b1a9c7b77743a2eeaf13ac145778ee8a01e8bbbb 100644
--- a/Marlin/SanityCheck.h
+++ b/Marlin/SanityCheck.h
@@ -368,27 +368,29 @@
  * Test Heater, Temp Sensor, and Extruder Pins; Sensor Type must also be set.
  */
 #if EXTRUDERS > 3
-  #if !HAS_HEATER_3
+  #if TEMP_SENSOR_3 == 0
+    #error TEMP_SENSOR_3 is required with 4 EXTRUDERS.
+  #elif !HAS_HEATER_3
     #error HEATER_3_PIN not defined for this board.
   #elif !PIN_EXISTS(TEMP_3)
     #error TEMP_3_PIN not defined for this board.
   #elif !PIN_EXISTS(E3_STEP) || !PIN_EXISTS(E3_DIR) || !PIN_EXISTS(E3_ENABLE)
     #error E3_STEP_PIN, E3_DIR_PIN, or E3_ENABLE_PIN not defined for this board.
-  #elif TEMP_SENSOR_3 == 0
-    #error TEMP_SENSOR_3 is required with 4 EXTRUDERS.
   #endif
 #elif EXTRUDERS > 2
-  #if !HAS_HEATER_2
+  #if TEMP_SENSOR_2 == 0
+    #error TEMP_SENSOR_2 is required with 3 or more EXTRUDERS.
+  #elif !HAS_HEATER_2
     #error HEATER_2_PIN not defined for this board.
   #elif !PIN_EXISTS(TEMP_2)
     #error TEMP_2_PIN not defined for this board.
   #elif !PIN_EXISTS(E2_STEP) || !PIN_EXISTS(E2_DIR) || !PIN_EXISTS(E2_ENABLE)
     #error E2_STEP_PIN, E2_DIR_PIN, or E2_ENABLE_PIN not defined for this board.
-  #elif TEMP_SENSOR_2 == 0
-    #error TEMP_SENSOR_2 is required with 3 or more EXTRUDERS.
   #endif
 #elif EXTRUDERS > 1
-  #if !PIN_EXISTS(TEMP_1)
+  #if TEMP_SENSOR_1 == 0
+    #error TEMP_SENSOR_1 is required with 2 or more EXTRUDERS.
+  #elif !PIN_EXISTS(TEMP_1)
     #error TEMP_1_PIN not defined for this board.
   #elif !PIN_EXISTS(E1_STEP) || !PIN_EXISTS(E1_DIR) || !PIN_EXISTS(E1_ENABLE)
     #error E1_STEP_PIN, E1_DIR_PIN, or E1_ENABLE_PIN not defined for this board.
@@ -401,12 +403,8 @@
   #endif
 #endif
 
-#if TEMP_SENSOR_1 == 0
-  #if EXTRUDERS > 1
-    #error TEMP_SENSOR_1 is required with 2 or more EXTRUDERS.
-  #elif ENABLED(TEMP_SENSOR_1_AS_REDUNDANT)
-    #error TEMP_SENSOR_1 is required with TEMP_SENSOR_1_AS_REDUNDANT.
-  #endif
+#if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT) && TEMP_SENSOR_1 == 0
+  #error TEMP_SENSOR_1 is required with TEMP_SENSOR_1_AS_REDUNDANT.
 #endif
 
 #if !HAS_HEATER_0
@@ -419,6 +417,19 @@
   #error TEMP_SENSOR_0 is required.
 #endif
 
+/**
+ * Endstops
+ */
+#if DISABLED(USE_XMIN_PLUG) && DISABLED(USE_XMAX_PLUG) && !(ENABLED(Z_DUAL_ENDSTOPS) && Z2_USE_ENDSTOP >= _XMAX_ && Z2_USE_ENDSTOP <= _XMIN_)
+ #error You must enable USE_XMIN_PLUG or USE_XMAX_PLUG
+#elif DISABLED(USE_YMIN_PLUG) && DISABLED(USE_YMAX_PLUG) && !(ENABLED(Z_DUAL_ENDSTOPS) && Z2_USE_ENDSTOP >= _YMAX_ && Z2_USE_ENDSTOP <= _YMIN_)
+ #error You must enable USE_YMIN_PLUG or USE_YMAX_PLUG
+#elif DISABLED(USE_ZMIN_PLUG) && DISABLED(USE_ZMAX_PLUG) && !(ENABLED(Z_DUAL_ENDSTOPS) && Z2_USE_ENDSTOP >= _ZMAX_ && Z2_USE_ENDSTOP <= _ZMIN_)
+ #error You must enable USE_ZMIN_PLUG or USE_ZMAX_PLUG
+#elif ENABLED(Z_DUAL_ENDSTOPS) && !Z2_USE_ENDSTOP
+ #error You must set Z2_USE_ENDSTOP with Z_DUAL_ENDSTOPS
+#endif
+
 /**
  * Warnings for old configurations
  */
@@ -445,17 +456,21 @@
 #elif defined(CUSTOM_MENDEL_NAME)
   #error CUSTOM_MENDEL_NAME is now CUSTOM_MACHINE_NAME. Please update your configuration.
 #elif defined(HAS_AUTOMATIC_VERSIONING)
-  #error HAS_AUTOMATIC_VERSIONING deprecated - use USE_AUTOMATIC_VERSIONING instead
+  #error HAS_AUTOMATIC_VERSIONING is now USE_AUTOMATIC_VERSIONING. Please update your configuration.
 #elif defined(ENABLE_AUTO_BED_LEVELING)
-  #error ENABLE_AUTO_BED_LEVELING deprecated - use AUTO_BED_LEVELING_FEATURE instead
+  #error ENABLE_AUTO_BED_LEVELING is now AUTO_BED_LEVELING_FEATURE. Please update your configuration.
 #elif defined(SDSLOW)
-  #error SDSLOW deprecated - set SPI_SPEED to SPI_HALF_SPEED instead
+  #error SDSLOW deprecated. Set SPI_SPEED to SPI_HALF_SPEED instead.
 #elif defined(SDEXTRASLOW)
-  #error SDEXTRASLOW deprecated - set SPI_SPEED to SPI_QUARTER_SPEED instead
+  #error SDEXTRASLOW deprecated. Set SPI_SPEED to SPI_QUARTER_SPEED instead.
 #elif defined(Z_RAISE_BEFORE_HOMING)
   #error Z_RAISE_BEFORE_HOMING is deprecated. Use MIN_Z_HEIGHT_FOR_HOMING instead.
 #elif defined(FILAMENT_SENSOR)
   #error FILAMENT_SENSOR is deprecated. Use FILAMENT_WIDTH_SENSOR instead.
+#elif defined(DISABLE_MAX_ENDSTOPS) || defined(DISABLE_MIN_ENDSTOPS)
+  #error DISABLE_MAX_ENDSTOPS and DISABLE_MIN_ENDSTOPS deprecated. Use individual USE_*_PLUG options instead.
+#elif ENABLED(Z_DUAL_ENDSTOPS) && !defined(Z2_USE_ENDSTOP)
+  #error Z_DUAL_ENDSTOPS settings are simplified. Just set Z2_USE_ENDSTOP to the endstop you want to repurpose for Z2
 #endif
 
 #endif //SANITYCHECK_H
diff --git a/Marlin/Sd2Card.cpp b/Marlin/Sd2Card.cpp
index 53935feb109bf9daa8348f88ea34498d9e98c7a7..62416b068486b61ed0b0fb3f4fedadd3991b0d4f 100644
--- a/Marlin/Sd2Card.cpp
+++ b/Marlin/Sd2Card.cpp
@@ -365,6 +365,7 @@ bool Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) {
   #if DISABLED(SOFTWARE_SPI)
     return setSckRate(sckRateID);
   #else  // SOFTWARE_SPI
+    UNUSED(sckRateID);
     return true;
   #endif  // SOFTWARE_SPI
 
diff --git a/Marlin/cardreader.cpp b/Marlin/cardreader.cpp
index c122a45ceef5f2bfb4f241b407b37e488c8fc8fc..eabf7b08b91ebb4cdaf853414f228098a88e1cc6 100644
--- a/Marlin/cardreader.cpp
+++ b/Marlin/cardreader.cpp
@@ -348,11 +348,11 @@ void CardReader::openFile(char* name, bool read, bool push_current/*=false*/) {
   char *dirname_start, *dirname_end;
   if (name[0] == '/') {
     dirname_start = &name[1];
-    while (dirname_start > 0) {
+    while (dirname_start != NULL) {
       dirname_end = strchr(dirname_start, '/');
       //SERIAL_ECHO("start:");SERIAL_ECHOLN((int)(dirname_start - name));
       //SERIAL_ECHO("end  :");SERIAL_ECHOLN((int)(dirname_end - name));
-      if (dirname_end > 0 && dirname_end > dirname_start) {
+      if (dirname_end != NULL && dirname_end > dirname_start) {
         char subdirname[FILENAME_LENGTH];
         strncpy(subdirname, dirname_start, dirname_end - dirname_start);
         subdirname[dirname_end - dirname_start] = 0;
@@ -429,11 +429,11 @@ void CardReader::removeFile(char* name) {
   char *dirname_start, *dirname_end;
   if (name[0] == '/') {
     dirname_start = strchr(name, '/') + 1;
-    while (dirname_start > 0) {
+    while (dirname_start != NULL) {
       dirname_end = strchr(dirname_start, '/');
       //SERIAL_ECHO("start:");SERIAL_ECHOLN((int)(dirname_start - name));
       //SERIAL_ECHO("end  :");SERIAL_ECHOLN((int)(dirname_end - name));
-      if (dirname_end > 0 && dirname_end > dirname_start) {
+      if (dirname_end != NULL && dirname_end > dirname_start) {
         char subdirname[FILENAME_LENGTH];
         strncpy(subdirname, dirname_start, dirname_end - dirname_start);
         subdirname[dirname_end - dirname_start] = 0;
diff --git a/Marlin/configuration_store.cpp b/Marlin/configuration_store.cpp
index 83bd8450bd9299a127b9c7b781deead30b3f10c3..3f22b2f8c61179256b82b2fcb44e65e703d4688e 100644
--- a/Marlin/configuration_store.cpp
+++ b/Marlin/configuration_store.cpp
@@ -328,7 +328,7 @@ void Config_StoreSettings()  {
 
   // Report storage size
   SERIAL_ECHO_START;
-  SERIAL_ECHOPAIR("Settings Stored (", (unsigned long)i);
+  SERIAL_ECHOPAIR("Settings Stored (", i);
   SERIAL_ECHOLNPGM(" bytes)");
 }
 
@@ -507,7 +507,7 @@ void Config_RetrieveSettings() {
     // Report settings retrieved and length
     SERIAL_ECHO_START;
     SERIAL_ECHO(ver);
-    SERIAL_ECHOPAIR(" stored settings retrieved (", (unsigned long)i);
+    SERIAL_ECHOPAIR(" stored settings retrieved (", i);
     SERIAL_ECHOLNPGM(" bytes)");
   }
 
@@ -730,9 +730,9 @@ void Config_PrintSettings(bool forReplay) {
       SERIAL_ECHOLNPGM("Mesh bed leveling:");
       CONFIG_ECHO_START;
     }
-    SERIAL_ECHOPAIR("  M420 S", (unsigned long)mbl.active);
-    SERIAL_ECHOPAIR(" X", (unsigned long)MESH_NUM_X_POINTS);
-    SERIAL_ECHOPAIR(" Y", (unsigned long)MESH_NUM_Y_POINTS);
+    SERIAL_ECHOPAIR("  M420 S", mbl.active);
+    SERIAL_ECHOPAIR(" X", MESH_NUM_X_POINTS);
+    SERIAL_ECHOPAIR(" Y", MESH_NUM_Y_POINTS);
     SERIAL_EOL;
     for (uint8_t y = 0; y < MESH_NUM_Y_POINTS; y++) {
       for (uint8_t x = 0; x < MESH_NUM_X_POINTS; x++) {
@@ -783,14 +783,14 @@ void Config_PrintSettings(bool forReplay) {
       SERIAL_ECHOLNPGM("Material heatup parameters:");
       CONFIG_ECHO_START;
     }
-    SERIAL_ECHOPAIR("  M145 S0 H", (unsigned long)plaPreheatHotendTemp);
-    SERIAL_ECHOPAIR(" B", (unsigned long)plaPreheatHPBTemp);
-    SERIAL_ECHOPAIR(" F", (unsigned long)plaPreheatFanSpeed);
+    SERIAL_ECHOPAIR("  M145 S0 H", plaPreheatHotendTemp);
+    SERIAL_ECHOPAIR(" B", plaPreheatHPBTemp);
+    SERIAL_ECHOPAIR(" F", plaPreheatFanSpeed);
     SERIAL_EOL;
     CONFIG_ECHO_START;
-    SERIAL_ECHOPAIR("  M145 S1 H", (unsigned long)absPreheatHotendTemp);
-    SERIAL_ECHOPAIR(" B", (unsigned long)absPreheatHPBTemp);
-    SERIAL_ECHOPAIR(" F", (unsigned long)absPreheatFanSpeed);
+    SERIAL_ECHOPAIR("  M145 S1 H", absPreheatHotendTemp);
+    SERIAL_ECHOPAIR(" B", absPreheatHPBTemp);
+    SERIAL_ECHOPAIR(" F", absPreheatFanSpeed);
     SERIAL_EOL;
   #endif // ULTIPANEL
 
@@ -805,7 +805,7 @@ void Config_PrintSettings(bool forReplay) {
         if (forReplay) {
           for (uint8_t i = 0; i < EXTRUDERS; i++) {
             CONFIG_ECHO_START;
-            SERIAL_ECHOPAIR("  M301 E", (unsigned long)i);
+            SERIAL_ECHOPAIR("  M301 E", 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)));
@@ -848,7 +848,7 @@ void Config_PrintSettings(bool forReplay) {
       SERIAL_ECHOLNPGM("LCD Contrast:");
       CONFIG_ECHO_START;
     }
-    SERIAL_ECHOPAIR("  M250 C", (unsigned long)lcd_contrast);
+    SERIAL_ECHOPAIR("  M250 C", lcd_contrast);
     SERIAL_EOL;
   #endif
 
@@ -882,7 +882,7 @@ void Config_PrintSettings(bool forReplay) {
       SERIAL_ECHOLNPGM("Auto-Retract: S=0 to disable, 1 to interpret extrude-only moves as retracts or recoveries");
       CONFIG_ECHO_START;
     }
-    SERIAL_ECHOPAIR("  M209 S", (unsigned long)(autoretract_enabled ? 1 : 0));
+    SERIAL_ECHOPAIR("  M209 S", (autoretract_enabled ? 1 : 0));
     SERIAL_EOL;
 
   #endif // FWRETRACT
diff --git a/Marlin/dogm_lcd_implementation.h b/Marlin/dogm_lcd_implementation.h
index 669fd431e694ca1192516b0f663576572d761304..4da13cd297bee5b2be4eab25a0ffe8fe8b0f55e7 100644
--- a/Marlin/dogm_lcd_implementation.h
+++ b/Marlin/dogm_lcd_implementation.h
@@ -334,9 +334,8 @@ static void lcd_implementation_status_screen() {
     }
 
     u8g.setPrintPos(80,48);
-    if (print_job_start_ms != 0) {
-      uint16_t time = (((print_job_stop_ms > print_job_start_ms)
-                       ? print_job_stop_ms : millis()) - print_job_start_ms) / 60000;
+    uint16_t time = print_job_timer.duration() / 60;
+    if (time != 0) {
       lcd_print(itostr2(time/60));
       lcd_print(':');
       lcd_print(itostr2(time%60));
@@ -599,7 +598,7 @@ void lcd_implementation_drawedit(const char* pstr, const char* value) {
 
 #endif //SDSUPPORT
 
-#define lcd_implementation_drawmenu_back(sel, row, pstr, data) lcd_implementation_drawmenu_generic(sel, row, pstr, LCD_STR_UPLEVEL[0], LCD_STR_UPLEVEL[0])
+#define lcd_implementation_drawmenu_back(sel, row, pstr) lcd_implementation_drawmenu_generic(sel, row, pstr, LCD_STR_UPLEVEL[0], LCD_STR_UPLEVEL[0])
 #define lcd_implementation_drawmenu_submenu(sel, row, pstr, data) lcd_implementation_drawmenu_generic(sel, row, pstr, '>', LCD_STR_ARROW_RIGHT[0])
 #define lcd_implementation_drawmenu_gcode(sel, row, pstr, gcode) lcd_implementation_drawmenu_generic(sel, row, pstr, '>', ' ')
 #define lcd_implementation_drawmenu_function(sel, row, pstr, data) lcd_implementation_drawmenu_generic(sel, row, pstr, '>', ' ')
diff --git a/Marlin/example_configurations/Felix/Configuration.h b/Marlin/example_configurations/Felix/Configuration.h
index 3fd1646da82e7890b428a51eb3c97860ff602d23..2da7f04f6d83a82a2473825fc8d25410430d554d 100644
--- a/Marlin/example_configurations/Felix/Configuration.h
+++ b/Marlin/example_configurations/Felix/Configuration.h
@@ -328,8 +328,22 @@
 // Enable this option for Toshiba steppers
 //#define CONFIG_STEPPERS_TOSHIBA
 
+//===========================================================================
+//============================== Endstop Settings ===========================
+//===========================================================================
+
 // @section homing
 
+// Specify here all the endstop connectors that are connected to any endstop or probe.
+// Almost all printers will be using one per axis. Probes will use one or more of the
+// extra connectors. Leave undefined any used for non-endstop and non-probe purposes.
+#define USE_XMIN_PLUG
+#define USE_YMIN_PLUG
+#define USE_ZMIN_PLUG
+//#define USE_XMAX_PLUG
+//#define USE_YMAX_PLUG
+//#define USE_ZMAX_PLUG
+
 // coarse Endstop Settings
 #define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors
 
@@ -352,8 +366,6 @@ const bool X_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of
 const bool Y_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of the endstop.
 const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of the endstop.
 const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the logic of the endstop.
-#define DISABLE_MAX_ENDSTOPS
-//#define DISABLE_MIN_ENDSTOPS
 
 //===========================================================================
 //============================= Z Probe Options =============================
@@ -692,9 +704,12 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l
 // Host Keepalive
 //
 // By default Marlin will send a busy status message to the host
-// every 10 seconds when it can't accept commands.
+// every couple of seconds when it can't accept commands.
 //
 //#define DISABLE_HOST_KEEPALIVE // Enable this option if your host doesn't like keepalive messages.
+#if DISABLED(DISABLE_HOST_KEEPALIVE)
+  #define DEFAULT_KEEPALIVE_INTERVAL 2 // Number of seconds between "busy" messages. Set with M113.
+#endif
 
 //
 // M100 Free Memory Watcher
diff --git a/Marlin/example_configurations/Felix/Configuration_DUAL.h b/Marlin/example_configurations/Felix/Configuration_DUAL.h
index 553c2dc60e29288fd2c9eefb843ad5892caadaa3..60697ed0e8cde303cdbb3e82d82413e36d9c92e6 100644
--- a/Marlin/example_configurations/Felix/Configuration_DUAL.h
+++ b/Marlin/example_configurations/Felix/Configuration_DUAL.h
@@ -325,8 +325,22 @@
 // Enable this option for Toshiba steppers
 //#define CONFIG_STEPPERS_TOSHIBA
 
+//===========================================================================
+//============================== Endstop Settings ===========================
+//===========================================================================
+
 // @section homing
 
+// Specify here all the endstop connectors that are connected to any endstop or probe.
+// Almost all printers will be using one per axis. Probes will use one or more of the
+// extra connectors. Leave undefined any used for non-endstop and non-probe purposes.
+#define USE_XMIN_PLUG
+#define USE_YMIN_PLUG
+#define USE_ZMIN_PLUG
+//#define USE_XMAX_PLUG
+//#define USE_YMAX_PLUG
+//#define USE_ZMAX_PLUG
+
 // coarse Endstop Settings
 #define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors
 
@@ -349,8 +363,6 @@ const bool X_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of
 const bool Y_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of the endstop.
 const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of the endstop.
 const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the logic of the endstop.
-#define DISABLE_MAX_ENDSTOPS
-//#define DISABLE_MIN_ENDSTOPS
 
 //===========================================================================
 //============================= Z Probe Options =============================
@@ -689,9 +701,12 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l
 // Host Keepalive
 //
 // By default Marlin will send a busy status message to the host
-// every 10 seconds when it can't accept commands.
+// every couple of seconds when it can't accept commands.
 //
 //#define DISABLE_HOST_KEEPALIVE // Enable this option if your host doesn't like keepalive messages.
+#if DISABLED(DISABLE_HOST_KEEPALIVE)
+  #define DEFAULT_KEEPALIVE_INTERVAL 2 // Number of seconds between "busy" messages. Set with M113.
+#endif
 
 //
 // M100 Free Memory Watcher
diff --git a/Marlin/example_configurations/Felix/Configuration_adv.h b/Marlin/example_configurations/Felix/Configuration_adv.h
index 5608d4b3936a2f0e4d4f313a6139b2f66fa17202..e8e2c1876c01ab88335982b87f5e1c7188a7c542 100644
--- a/Marlin/example_configurations/Felix/Configuration_adv.h
+++ b/Marlin/example_configurations/Felix/Configuration_adv.h
@@ -201,9 +201,7 @@
   //#define Z_DUAL_ENDSTOPS
 
   #if ENABLED(Z_DUAL_ENDSTOPS)
-    #define Z2_MAX_PIN 36                     //Endstop used for Z2 axis. In this case I'm using XMAX in a Rumba Board (pin 36)
-    const bool Z2_MAX_ENDSTOP_INVERTING = false;
-    #define DISABLE_XMAX_ENDSTOP              //Better to disable the XMAX to avoid conflict. Just rename "XMAX_ENDSTOP" by the endstop you are using for Z2 axis.
+    #define Z2_USE_ENDSTOP _XMAX_
   #endif
 
 #endif // Z_DUAL_STEPPER_DRIVERS
@@ -655,6 +653,38 @@ const unsigned int dropsegments = 5; //everything with less than this number of
 
 #endif
 
+/**
+ * TWI/I2C BUS
+ *
+ * This feature is an EXPERIMENTAL feature so it shall not be used on production
+ * machines. Enabling this will allow you to send and receive I2C data from slave
+ * devices on the bus.
+ *
+ * ; Example #1
+ * ; This macro send the string "Marlin" to the slave device with address 0x63
+ * ; It uses multiple M155 commands with one B<base 10> arg
+ * M155 A63  ; Target slave address
+ * M155 B77  ; M
+ * M155 B97  ; a
+ * M155 B114 ; r
+ * M155 B108 ; l
+ * M155 B105 ; i
+ * M155 B110 ; n
+ * M155 S1   ; Send the current buffer
+ *
+ * ; Example #2
+ * ; Request 6 bytes from slave device with address 0x63
+ * M156 A63 B5
+ *
+ * ; Example #3
+ * ; Example serial output of a M156 request
+ * echo:i2c-reply: from:63 bytes:5 data:hello
+ */
+
+// @section i2cbus
+
+//#define EXPERIMENTAL_I2CBUS
+
 #include "Conditionals.h"
 #include "SanityCheck.h"
 
diff --git a/Marlin/example_configurations/Hephestos/Configuration.h b/Marlin/example_configurations/Hephestos/Configuration.h
index 1d6faab46d82fb00f95cb47d8018b68310e8deb1..9e0af0a329037a67fbaf4272b0706c2e757e4d5c 100644
--- a/Marlin/example_configurations/Hephestos/Configuration.h
+++ b/Marlin/example_configurations/Hephestos/Configuration.h
@@ -338,8 +338,22 @@
 // Enable this option for Toshiba steppers
 //#define CONFIG_STEPPERS_TOSHIBA
 
+//===========================================================================
+//============================== Endstop Settings ===========================
+//===========================================================================
+
 // @section homing
 
+// Specify here all the endstop connectors that are connected to any endstop or probe.
+// Almost all printers will be using one per axis. Probes will use one or more of the
+// extra connectors. Leave undefined any used for non-endstop and non-probe purposes.
+#define USE_XMIN_PLUG
+#define USE_YMIN_PLUG
+#define USE_ZMIN_PLUG
+//#define USE_XMAX_PLUG
+//#define USE_YMAX_PLUG
+//#define USE_ZMAX_PLUG
+
 // coarse Endstop Settings
 #define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors
 
@@ -362,8 +376,6 @@ const bool X_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of
 const bool Y_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of the endstop.
 const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of the endstop.
 const bool Z_MIN_PROBE_ENDSTOP_INVERTING = true; // set to true to invert the logic of the endstop.
-#define DISABLE_MAX_ENDSTOPS
-//#define DISABLE_MIN_ENDSTOPS
 
 //===========================================================================
 //============================= Z Probe Options =============================
@@ -701,9 +713,12 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = true; // set to true to invert the lo
 // Host Keepalive
 //
 // By default Marlin will send a busy status message to the host
-// every 10 seconds when it can't accept commands.
+// every couple of seconds when it can't accept commands.
 //
 //#define DISABLE_HOST_KEEPALIVE // Enable this option if your host doesn't like keepalive messages.
+#if DISABLED(DISABLE_HOST_KEEPALIVE)
+  #define DEFAULT_KEEPALIVE_INTERVAL 2 // Number of seconds between "busy" messages. Set with M113.
+#endif
 
 //
 // M100 Free Memory Watcher
diff --git a/Marlin/example_configurations/Hephestos/Configuration_adv.h b/Marlin/example_configurations/Hephestos/Configuration_adv.h
index fcdee236a9f96a1a2e331824433e30150d1894be..ab8000a88bc25a7d55fbe83dd84c74427f5022d4 100644
--- a/Marlin/example_configurations/Hephestos/Configuration_adv.h
+++ b/Marlin/example_configurations/Hephestos/Configuration_adv.h
@@ -201,9 +201,7 @@
   //#define Z_DUAL_ENDSTOPS
 
   #if ENABLED(Z_DUAL_ENDSTOPS)
-    #define Z2_MAX_PIN 36                     //Endstop used for Z2 axis. In this case I'm using XMAX in a Rumba Board (pin 36)
-    const bool Z2_MAX_ENDSTOP_INVERTING = false;
-    #define DISABLE_XMAX_ENDSTOP              //Better to disable the XMAX to avoid conflict. Just rename "XMAX_ENDSTOP" by the endstop you are using for Z2 axis.
+    #define Z2_USE_ENDSTOP _XMAX_
   #endif
 
 #endif // Z_DUAL_STEPPER_DRIVERS
@@ -655,6 +653,38 @@ const unsigned int dropsegments = 5; //everything with less than this number of
 
 #endif
 
+/**
+ * TWI/I2C BUS
+ *
+ * This feature is an EXPERIMENTAL feature so it shall not be used on production
+ * machines. Enabling this will allow you to send and receive I2C data from slave
+ * devices on the bus.
+ *
+ * ; Example #1
+ * ; This macro send the string "Marlin" to the slave device with address 0x63
+ * ; It uses multiple M155 commands with one B<base 10> arg
+ * M155 A63  ; Target slave address
+ * M155 B77  ; M
+ * M155 B97  ; a
+ * M155 B114 ; r
+ * M155 B108 ; l
+ * M155 B105 ; i
+ * M155 B110 ; n
+ * M155 S1   ; Send the current buffer
+ *
+ * ; Example #2
+ * ; Request 6 bytes from slave device with address 0x63
+ * M156 A63 B5
+ *
+ * ; Example #3
+ * ; Example serial output of a M156 request
+ * echo:i2c-reply: from:63 bytes:5 data:hello
+ */
+
+// @section i2cbus
+
+//#define EXPERIMENTAL_I2CBUS
+
 #include "Conditionals.h"
 #include "SanityCheck.h"
 
diff --git a/Marlin/example_configurations/Hephestos_2/Configuration.h b/Marlin/example_configurations/Hephestos_2/Configuration.h
index e348a6ecb7b0762a3fb38f9529eb6544b208280f..a1a89e37150c72d2a2b98ccd7526928157dfb263 100644
--- a/Marlin/example_configurations/Hephestos_2/Configuration.h
+++ b/Marlin/example_configurations/Hephestos_2/Configuration.h
@@ -340,8 +340,22 @@
 // Enable this option for Toshiba steppers
 //#define CONFIG_STEPPERS_TOSHIBA
 
+//===========================================================================
+//============================== Endstop Settings ===========================
+//===========================================================================
+
 // @section homing
 
+// Specify here all the endstop connectors that are connected to any endstop or probe.
+// Almost all printers will be using one per axis. Probes will use one or more of the
+// extra connectors. Leave undefined any used for non-endstop and non-probe purposes.
+#define USE_XMIN_PLUG
+#define USE_YMIN_PLUG
+#define USE_ZMIN_PLUG
+//#define USE_XMAX_PLUG
+//#define USE_YMAX_PLUG
+//#define USE_ZMAX_PLUG
+
 // coarse Endstop Settings
 #define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors
 
@@ -364,8 +378,6 @@ const bool X_MAX_ENDSTOP_INVERTING = true;  // set to true to invert the logic o
 const bool Y_MAX_ENDSTOP_INVERTING = true;  // set to true to invert the logic of the endstop.
 const bool Z_MAX_ENDSTOP_INVERTING = true;  // set to true to invert the logic of the endstop.
 const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the logic of the endstop.
-#define DISABLE_MAX_ENDSTOPS
-//#define DISABLE_MIN_ENDSTOPS
 
 //===========================================================================
 //============================= Z Probe Options =============================
@@ -703,9 +715,12 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l
 // Host Keepalive
 //
 // By default Marlin will send a busy status message to the host
-// every 10 seconds when it can't accept commands.
+// every couple of seconds when it can't accept commands.
 //
 //#define DISABLE_HOST_KEEPALIVE // Enable this option if your host doesn't like keepalive messages.
+#if DISABLED(DISABLE_HOST_KEEPALIVE)
+  #define DEFAULT_KEEPALIVE_INTERVAL 2 // Number of seconds between "busy" messages. Set with M113.
+#endif
 
 //
 // M100 Free Memory Watcher
diff --git a/Marlin/example_configurations/Hephestos_2/Configuration_adv.h b/Marlin/example_configurations/Hephestos_2/Configuration_adv.h
index 3131e10b248e5c854ff490dd2b8f5943dbabc3d0..be87d38ff4c5b3158fe2a2a53076e409c3189c13 100644
--- a/Marlin/example_configurations/Hephestos_2/Configuration_adv.h
+++ b/Marlin/example_configurations/Hephestos_2/Configuration_adv.h
@@ -201,9 +201,7 @@
   //#define Z_DUAL_ENDSTOPS
 
   #if ENABLED(Z_DUAL_ENDSTOPS)
-    #define Z2_MAX_PIN 36                     //Endstop used for Z2 axis. In this case I'm using XMAX in a Rumba Board (pin 36)
-    const bool Z2_MAX_ENDSTOP_INVERTING = false;
-    #define DISABLE_XMAX_ENDSTOP              //Better to disable the XMAX to avoid conflict. Just rename "XMAX_ENDSTOP" by the endstop you are using for Z2 axis.
+    #define Z2_USE_ENDSTOP _XMAX_
   #endif
 
 #endif // Z_DUAL_STEPPER_DRIVERS
@@ -655,6 +653,38 @@ const unsigned int dropsegments = 5; //everything with less than this number of
 
 #endif
 
+/**
+ * TWI/I2C BUS
+ *
+ * This feature is an EXPERIMENTAL feature so it shall not be used on production
+ * machines. Enabling this will allow you to send and receive I2C data from slave
+ * devices on the bus.
+ *
+ * ; Example #1
+ * ; This macro send the string "Marlin" to the slave device with address 0x63
+ * ; It uses multiple M155 commands with one B<base 10> arg
+ * M155 A63  ; Target slave address
+ * M155 B77  ; M
+ * M155 B97  ; a
+ * M155 B114 ; r
+ * M155 B108 ; l
+ * M155 B105 ; i
+ * M155 B110 ; n
+ * M155 S1   ; Send the current buffer
+ *
+ * ; Example #2
+ * ; Request 6 bytes from slave device with address 0x63
+ * M156 A63 B5
+ *
+ * ; Example #3
+ * ; Example serial output of a M156 request
+ * echo:i2c-reply: from:63 bytes:5 data:hello
+ */
+
+// @section i2cbus
+
+//#define EXPERIMENTAL_I2CBUS
+
 #include "Conditionals.h"
 #include "SanityCheck.h"
 
diff --git a/Marlin/example_configurations/K8200/Configuration.h b/Marlin/example_configurations/K8200/Configuration.h
index e803d3e2b01f953fb804587accb03e88dc2ef663..74c5531772c0248132d27de18603e146fbfc2475 100644
--- a/Marlin/example_configurations/K8200/Configuration.h
+++ b/Marlin/example_configurations/K8200/Configuration.h
@@ -363,8 +363,22 @@
 // Enable this option for Toshiba steppers
 //#define CONFIG_STEPPERS_TOSHIBA
 
+//===========================================================================
+//============================== Endstop Settings ===========================
+//===========================================================================
+
 // @section homing
 
+// Specify here all the endstop connectors that are connected to any endstop or probe.
+// Almost all printers will be using one per axis. Probes will use one or more of the
+// extra connectors. Leave undefined any used for non-endstop and non-probe purposes.
+#define USE_XMIN_PLUG
+#define USE_YMIN_PLUG
+#define USE_ZMIN_PLUG
+//#define USE_XMAX_PLUG
+//#define USE_YMAX_PLUG
+//#define USE_ZMAX_PLUG
+
 // coarse Endstop Settings
 #define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors
 
@@ -387,8 +401,6 @@ const bool X_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of
 const bool Y_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of the endstop.
 const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of the endstop.
 const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the logic of the endstop.
-#define DISABLE_MAX_ENDSTOPS
-//#define DISABLE_MIN_ENDSTOPS
 
 //===========================================================================
 //============================= Z Probe Options =============================
@@ -726,9 +738,12 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l
 // Host Keepalive
 //
 // By default Marlin will send a busy status message to the host
-// every 10 seconds when it can't accept commands.
+// every couple of seconds when it can't accept commands.
 //
 //#define DISABLE_HOST_KEEPALIVE // Enable this option if your host doesn't like keepalive messages.
+#if DISABLED(DISABLE_HOST_KEEPALIVE)
+  #define DEFAULT_KEEPALIVE_INTERVAL 2 // Number of seconds between "busy" messages. Set with M113.
+#endif
 
 //
 // M100 Free Memory Watcher
diff --git a/Marlin/example_configurations/K8200/Configuration_adv.h b/Marlin/example_configurations/K8200/Configuration_adv.h
index f5b6e70ea682d687eeff090610f54c22b1297e6f..429a1ad7b5bc7a6cbb102e05d652a111a02d84c8 100644
--- a/Marlin/example_configurations/K8200/Configuration_adv.h
+++ b/Marlin/example_configurations/K8200/Configuration_adv.h
@@ -207,9 +207,7 @@
   //#define Z_DUAL_ENDSTOPS
 
   #if ENABLED(Z_DUAL_ENDSTOPS)
-    #define Z2_MAX_PIN 36                     //Endstop used for Z2 axis. In this case I'm using XMAX in a Rumba Board (pin 36)
-    const bool Z2_MAX_ENDSTOP_INVERTING = false;
-    #define DISABLE_XMAX_ENDSTOP              //Better to disable the XMAX to avoid conflict. Just rename "XMAX_ENDSTOP" by the endstop you are using for Z2 axis.
+    #define Z2_USE_ENDSTOP _XMAX_
   #endif
 
 #endif // Z_DUAL_STEPPER_DRIVERS
@@ -661,6 +659,38 @@ const unsigned int dropsegments = 2; //everything with less than this number of
 
 #endif
 
+/**
+ * TWI/I2C BUS
+ *
+ * This feature is an EXPERIMENTAL feature so it shall not be used on production
+ * machines. Enabling this will allow you to send and receive I2C data from slave
+ * devices on the bus.
+ *
+ * ; Example #1
+ * ; This macro send the string "Marlin" to the slave device with address 0x63
+ * ; It uses multiple M155 commands with one B<base 10> arg
+ * M155 A63  ; Target slave address
+ * M155 B77  ; M
+ * M155 B97  ; a
+ * M155 B114 ; r
+ * M155 B108 ; l
+ * M155 B105 ; i
+ * M155 B110 ; n
+ * M155 S1   ; Send the current buffer
+ *
+ * ; Example #2
+ * ; Request 6 bytes from slave device with address 0x63
+ * M156 A63 B5
+ *
+ * ; Example #3
+ * ; Example serial output of a M156 request
+ * echo:i2c-reply: from:63 bytes:5 data:hello
+ */
+
+// @section i2cbus
+
+//#define EXPERIMENTAL_I2CBUS
+
 #include "Conditionals.h"
 #include "SanityCheck.h"
 
diff --git a/Marlin/example_configurations/RepRapWorld/Megatronics/Configuration.h b/Marlin/example_configurations/RepRapWorld/Megatronics/Configuration.h
index 80e9d351903c74cb6425b87cdb0bc8900f4c51c8..553c07afa5a50e04270d84b4b7667c963c4727d4 100644
--- a/Marlin/example_configurations/RepRapWorld/Megatronics/Configuration.h
+++ b/Marlin/example_configurations/RepRapWorld/Megatronics/Configuration.h
@@ -346,8 +346,22 @@
 // Enable this option for Toshiba steppers
 //#define CONFIG_STEPPERS_TOSHIBA
 
+//===========================================================================
+//============================== Endstop Settings ===========================
+//===========================================================================
+
 // @section homing
 
+// Specify here all the endstop connectors that are connected to any endstop or probe.
+// Almost all printers will be using one per axis. Probes will use one or more of the
+// extra connectors. Leave undefined any used for non-endstop and non-probe purposes.
+#define USE_XMIN_PLUG
+#define USE_YMIN_PLUG
+#define USE_ZMIN_PLUG
+//#define USE_XMAX_PLUG
+//#define USE_YMAX_PLUG
+//#define USE_ZMAX_PLUG
+
 // coarse Endstop Settings
 #define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors
 
@@ -370,8 +384,6 @@ const bool X_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of
 const bool Y_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of the endstop.
 const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of the endstop.
 const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the logic of the endstop.
-//#define DISABLE_MAX_ENDSTOPS
-//#define DISABLE_MIN_ENDSTOPS
 
 //===========================================================================
 //============================= Z Probe Options =============================
@@ -709,9 +721,12 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l
 // Host Keepalive
 //
 // By default Marlin will send a busy status message to the host
-// every 10 seconds when it can't accept commands.
+// every couple of seconds when it can't accept commands.
 //
 //#define DISABLE_HOST_KEEPALIVE // Enable this option if your host doesn't like keepalive messages.
+#if DISABLED(DISABLE_HOST_KEEPALIVE)
+  #define DEFAULT_KEEPALIVE_INTERVAL 2 // Number of seconds between "busy" messages. Set with M113.
+#endif
 
 //
 // M100 Free Memory Watcher
diff --git a/Marlin/example_configurations/RigidBot/Configuration.h b/Marlin/example_configurations/RigidBot/Configuration.h
index 3147bb0e0c566580610e3f98f6ad2f6493d497ab..733b377cd43e5bf0afa2286ab896200ee0de062e 100644
--- a/Marlin/example_configurations/RigidBot/Configuration.h
+++ b/Marlin/example_configurations/RigidBot/Configuration.h
@@ -340,8 +340,22 @@
 // Enable this option for Toshiba steppers
 //#define CONFIG_STEPPERS_TOSHIBA
 
+//===========================================================================
+//============================== Endstop Settings ===========================
+//===========================================================================
+
 // @section homing
 
+// Specify here all the endstop connectors that are connected to any endstop or probe.
+// Almost all printers will be using one per axis. Probes will use one or more of the
+// extra connectors. Leave undefined any used for non-endstop and non-probe purposes.
+#define USE_XMIN_PLUG
+#define USE_YMIN_PLUG
+#define USE_ZMIN_PLUG
+//#define USE_XMAX_PLUG
+//#define USE_YMAX_PLUG
+//#define USE_ZMAX_PLUG
+
 // coarse Endstop Settings
 #define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors
 
@@ -364,8 +378,6 @@ const bool X_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of
 const bool Y_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of the endstop.
 const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of the endstop.
 const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the logic of the endstop.
-//#define DISABLE_MAX_ENDSTOPS
-//#define DISABLE_MIN_ENDSTOPS
 
 //===========================================================================
 //============================= Z Probe Options =============================
@@ -704,9 +716,12 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l
 // Host Keepalive
 //
 // By default Marlin will send a busy status message to the host
-// every 10 seconds when it can't accept commands.
+// every couple of seconds when it can't accept commands.
 //
 //#define DISABLE_HOST_KEEPALIVE // Enable this option if your host doesn't like keepalive messages.
+#if DISABLED(DISABLE_HOST_KEEPALIVE)
+  #define DEFAULT_KEEPALIVE_INTERVAL 2 // Number of seconds between "busy" messages. Set with M113.
+#endif
 
 //
 // M100 Free Memory Watcher
diff --git a/Marlin/example_configurations/RigidBot/Configuration_adv.h b/Marlin/example_configurations/RigidBot/Configuration_adv.h
index c93dde28148ec5c3dd133349f6e75b8731dfbb39..6985ddbe4f2be3d2373db02f6db10554f6a03a11 100644
--- a/Marlin/example_configurations/RigidBot/Configuration_adv.h
+++ b/Marlin/example_configurations/RigidBot/Configuration_adv.h
@@ -201,9 +201,7 @@
   //#define Z_DUAL_ENDSTOPS
 
   #if ENABLED(Z_DUAL_ENDSTOPS)
-    #define Z2_MAX_PIN 36                     //Endstop used for Z2 axis. In this case I'm using XMAX in a Rumba Board (pin 36)
-    const bool Z2_MAX_ENDSTOP_INVERTING = false;
-    #define DISABLE_XMAX_ENDSTOP              //Better to disable the XMAX to avoid conflict. Just rename "XMAX_ENDSTOP" by the endstop you are using for Z2 axis.
+    #define Z2_USE_ENDSTOP _XMAX_
   #endif
 
 #endif // Z_DUAL_STEPPER_DRIVERS
@@ -655,6 +653,38 @@ const unsigned int dropsegments = 5; //everything with less than this number of
 
 #endif
 
+/**
+ * TWI/I2C BUS
+ *
+ * This feature is an EXPERIMENTAL feature so it shall not be used on production
+ * machines. Enabling this will allow you to send and receive I2C data from slave
+ * devices on the bus.
+ *
+ * ; Example #1
+ * ; This macro send the string "Marlin" to the slave device with address 0x63
+ * ; It uses multiple M155 commands with one B<base 10> arg
+ * M155 A63  ; Target slave address
+ * M155 B77  ; M
+ * M155 B97  ; a
+ * M155 B114 ; r
+ * M155 B108 ; l
+ * M155 B105 ; i
+ * M155 B110 ; n
+ * M155 S1   ; Send the current buffer
+ *
+ * ; Example #2
+ * ; Request 6 bytes from slave device with address 0x63
+ * M156 A63 B5
+ *
+ * ; Example #3
+ * ; Example serial output of a M156 request
+ * echo:i2c-reply: from:63 bytes:5 data:hello
+ */
+
+// @section i2cbus
+
+//#define EXPERIMENTAL_I2CBUS
+
 #include "Conditionals.h"
 #include "SanityCheck.h"
 
diff --git a/Marlin/example_configurations/SCARA/Configuration.h b/Marlin/example_configurations/SCARA/Configuration.h
index 2320abc067208a4cdef1ea8a22b945c0c2572d9f..436bf2290975c3250964bcb438be7692fb53af53 100644
--- a/Marlin/example_configurations/SCARA/Configuration.h
+++ b/Marlin/example_configurations/SCARA/Configuration.h
@@ -354,8 +354,22 @@
 // Enable this option for Toshiba steppers
 //#define CONFIG_STEPPERS_TOSHIBA
 
+//===========================================================================
+//============================== Endstop Settings ===========================
+//===========================================================================
+
 // @section homing
 
+// Specify here all the endstop connectors that are connected to any endstop or probe.
+// Almost all printers will be using one per axis. Probes will use one or more of the
+// extra connectors. Leave undefined any used for non-endstop and non-probe purposes.
+#define USE_XMIN_PLUG
+#define USE_YMIN_PLUG
+//#define USE_ZMIN_PLUG
+//#define USE_XMAX_PLUG
+//#define USE_YMAX_PLUG
+#define USE_ZMAX_PLUG
+
 // coarse Endstop Settings
 //#define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors
 
@@ -378,8 +392,6 @@ const bool X_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of
 const bool Y_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of the endstop.
 const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of the endstop.
 const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the logic of the endstop.
-//#define DISABLE_MAX_ENDSTOPS
-//#define DISABLE_MIN_ENDSTOPS
 
 //===========================================================================
 //============================= Z Probe Options =============================
@@ -717,9 +729,12 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l
 // Host Keepalive
 //
 // By default Marlin will send a busy status message to the host
-// every 10 seconds when it can't accept commands.
+// every couple of seconds when it can't accept commands.
 //
 //#define DISABLE_HOST_KEEPALIVE // Enable this option if your host doesn't like keepalive messages.
+#if DISABLED(DISABLE_HOST_KEEPALIVE)
+  #define DEFAULT_KEEPALIVE_INTERVAL 2 // Number of seconds between "busy" messages. Set with M113.
+#endif
 
 //
 // M100 Free Memory Watcher
diff --git a/Marlin/example_configurations/SCARA/Configuration_adv.h b/Marlin/example_configurations/SCARA/Configuration_adv.h
index 627067d775bd1265330e9f95a794ee5af705bfbb..7af011099146824c7b936eef4b7f02110fa0201e 100644
--- a/Marlin/example_configurations/SCARA/Configuration_adv.h
+++ b/Marlin/example_configurations/SCARA/Configuration_adv.h
@@ -201,9 +201,7 @@
   //#define Z_DUAL_ENDSTOPS
 
   #if ENABLED(Z_DUAL_ENDSTOPS)
-    #define Z2_MAX_PIN 36                     //Endstop used for Z2 axis. In this case I'm using XMAX in a Rumba Board (pin 36)
-    const bool Z2_MAX_ENDSTOP_INVERTING = false;
-    #define DISABLE_XMAX_ENDSTOP              //Better to disable the XMAX to avoid conflict. Just rename "XMAX_ENDSTOP" by the endstop you are using for Z2 axis.
+    #define Z2_USE_ENDSTOP _XMAX_
   #endif
 
 #endif // Z_DUAL_STEPPER_DRIVERS
@@ -655,6 +653,38 @@ const unsigned int dropsegments = 5; //everything with less than this number of
 
 #endif
 
+/**
+ * TWI/I2C BUS
+ *
+ * This feature is an EXPERIMENTAL feature so it shall not be used on production
+ * machines. Enabling this will allow you to send and receive I2C data from slave
+ * devices on the bus.
+ *
+ * ; Example #1
+ * ; This macro send the string "Marlin" to the slave device with address 0x63
+ * ; It uses multiple M155 commands with one B<base 10> arg
+ * M155 A63  ; Target slave address
+ * M155 B77  ; M
+ * M155 B97  ; a
+ * M155 B114 ; r
+ * M155 B108 ; l
+ * M155 B105 ; i
+ * M155 B110 ; n
+ * M155 S1   ; Send the current buffer
+ *
+ * ; Example #2
+ * ; Request 6 bytes from slave device with address 0x63
+ * M156 A63 B5
+ *
+ * ; Example #3
+ * ; Example serial output of a M156 request
+ * echo:i2c-reply: from:63 bytes:5 data:hello
+ */
+
+// @section i2cbus
+
+//#define EXPERIMENTAL_I2CBUS
+
 #include "Conditionals.h"
 #include "SanityCheck.h"
 
diff --git a/Marlin/example_configurations/TAZ4/Configuration.h b/Marlin/example_configurations/TAZ4/Configuration.h
index 8c7fb0388c4f7741cb54e9c526207538bcdc505e..38e7e20cf2c89a08f02314d7a5b18dec23f926d0 100644
--- a/Marlin/example_configurations/TAZ4/Configuration.h
+++ b/Marlin/example_configurations/TAZ4/Configuration.h
@@ -367,8 +367,22 @@
 // Enable this option for Toshiba steppers
 //#define CONFIG_STEPPERS_TOSHIBA
 
+//===========================================================================
+//============================== Endstop Settings ===========================
+//===========================================================================
+
 // @section homing
 
+// Specify here all the endstop connectors that are connected to any endstop or probe.
+// Almost all printers will be using one per axis. Probes will use one or more of the
+// extra connectors. Leave undefined any used for non-endstop and non-probe purposes.
+#define USE_XMIN_PLUG
+#define USE_YMIN_PLUG
+#define USE_ZMIN_PLUG
+//#define USE_XMAX_PLUG
+//#define USE_YMAX_PLUG
+//#define USE_ZMAX_PLUG
+
 // coarse Endstop Settings
 #define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors
 
@@ -391,8 +405,6 @@ const bool X_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of
 const bool Y_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of the endstop.
 const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of the endstop.
 const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the logic of the endstop.
-#define DISABLE_MAX_ENDSTOPS
-//#define DISABLE_MIN_ENDSTOPS
 
 //===========================================================================
 //============================= Z Probe Options =============================
@@ -730,9 +742,12 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l
 // Host Keepalive
 //
 // By default Marlin will send a busy status message to the host
-// every 10 seconds when it can't accept commands.
+// every couple of seconds when it can't accept commands.
 //
 //#define DISABLE_HOST_KEEPALIVE // Enable this option if your host doesn't like keepalive messages.
+#if DISABLED(DISABLE_HOST_KEEPALIVE)
+  #define DEFAULT_KEEPALIVE_INTERVAL 2 // Number of seconds between "busy" messages. Set with M113.
+#endif
 
 //
 // M100 Free Memory Watcher
diff --git a/Marlin/example_configurations/TAZ4/Configuration_adv.h b/Marlin/example_configurations/TAZ4/Configuration_adv.h
index c052253a10ef46c3ff2d2eefbd1e4cf4b7502a0c..f96f20236bff0c4badc4f75d4f419d91356d3020 100644
--- a/Marlin/example_configurations/TAZ4/Configuration_adv.h
+++ b/Marlin/example_configurations/TAZ4/Configuration_adv.h
@@ -209,9 +209,7 @@
   //#define Z_DUAL_ENDSTOPS
 
   #if ENABLED(Z_DUAL_ENDSTOPS)
-    #define Z2_MAX_PIN 36                     //Endstop used for Z2 axis. In this case I'm using XMAX in a Rumba Board (pin 36)
-    const bool Z2_MAX_ENDSTOP_INVERTING = false;
-    #define DISABLE_XMAX_ENDSTOP              //Better to disable the XMAX to avoid conflict. Just rename "XMAX_ENDSTOP" by the endstop you are using for Z2 axis.
+    #define Z2_USE_ENDSTOP _XMAX_
   #endif
 
 #endif // Z_DUAL_STEPPER_DRIVERS
@@ -663,6 +661,38 @@ const unsigned int dropsegments = 5; //everything with less than this number of
 
 #endif
 
+/**
+ * TWI/I2C BUS
+ *
+ * This feature is an EXPERIMENTAL feature so it shall not be used on production
+ * machines. Enabling this will allow you to send and receive I2C data from slave
+ * devices on the bus.
+ *
+ * ; Example #1
+ * ; This macro send the string "Marlin" to the slave device with address 0x63
+ * ; It uses multiple M155 commands with one B<base 10> arg
+ * M155 A63  ; Target slave address
+ * M155 B77  ; M
+ * M155 B97  ; a
+ * M155 B114 ; r
+ * M155 B108 ; l
+ * M155 B105 ; i
+ * M155 B110 ; n
+ * M155 S1   ; Send the current buffer
+ *
+ * ; Example #2
+ * ; Request 6 bytes from slave device with address 0x63
+ * M156 A63 B5
+ *
+ * ; Example #3
+ * ; Example serial output of a M156 request
+ * echo:i2c-reply: from:63 bytes:5 data:hello
+ */
+
+// @section i2cbus
+
+//#define EXPERIMENTAL_I2CBUS
+
 #include "Conditionals.h"
 #include "SanityCheck.h"
 
diff --git a/Marlin/example_configurations/WITBOX/Configuration.h b/Marlin/example_configurations/WITBOX/Configuration.h
index 9d6c5b7f2dd9b3cae063782d2c148ed82c1dd2e8..fd3fa38d09724833f6cd235793d78f87ab4b6942 100644
--- a/Marlin/example_configurations/WITBOX/Configuration.h
+++ b/Marlin/example_configurations/WITBOX/Configuration.h
@@ -338,8 +338,22 @@
 // Enable this option for Toshiba steppers
 //#define CONFIG_STEPPERS_TOSHIBA
 
+//===========================================================================
+//============================== Endstop Settings ===========================
+//===========================================================================
+
 // @section homing
 
+// Specify here all the endstop connectors that are connected to any endstop or probe.
+// Almost all printers will be using one per axis. Probes will use one or more of the
+// extra connectors. Leave undefined any used for non-endstop and non-probe purposes.
+#define USE_XMIN_PLUG
+#define USE_YMIN_PLUG
+#define USE_ZMIN_PLUG
+//#define USE_XMAX_PLUG
+//#define USE_YMAX_PLUG
+//#define USE_ZMAX_PLUG
+
 // coarse Endstop Settings
 #define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors
 
@@ -362,8 +376,6 @@ const bool X_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of
 const bool Y_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of the endstop.
 const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of the endstop.
 const bool Z_MIN_PROBE_ENDSTOP_INVERTING = true; // set to true to invert the logic of the endstop.
-//#define DISABLE_MAX_ENDSTOPS
-//#define DISABLE_MIN_ENDSTOPS
 
 //===========================================================================
 //============================= Z Probe Options =============================
@@ -701,9 +713,12 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = true; // set to true to invert the lo
 // Host Keepalive
 //
 // By default Marlin will send a busy status message to the host
-// every 10 seconds when it can't accept commands.
+// every couple of seconds when it can't accept commands.
 //
 //#define DISABLE_HOST_KEEPALIVE // Enable this option if your host doesn't like keepalive messages.
+#if DISABLED(DISABLE_HOST_KEEPALIVE)
+  #define DEFAULT_KEEPALIVE_INTERVAL 2 // Number of seconds between "busy" messages. Set with M113.
+#endif
 
 //
 // M100 Free Memory Watcher
diff --git a/Marlin/example_configurations/WITBOX/Configuration_adv.h b/Marlin/example_configurations/WITBOX/Configuration_adv.h
index fcdee236a9f96a1a2e331824433e30150d1894be..ab8000a88bc25a7d55fbe83dd84c74427f5022d4 100644
--- a/Marlin/example_configurations/WITBOX/Configuration_adv.h
+++ b/Marlin/example_configurations/WITBOX/Configuration_adv.h
@@ -201,9 +201,7 @@
   //#define Z_DUAL_ENDSTOPS
 
   #if ENABLED(Z_DUAL_ENDSTOPS)
-    #define Z2_MAX_PIN 36                     //Endstop used for Z2 axis. In this case I'm using XMAX in a Rumba Board (pin 36)
-    const bool Z2_MAX_ENDSTOP_INVERTING = false;
-    #define DISABLE_XMAX_ENDSTOP              //Better to disable the XMAX to avoid conflict. Just rename "XMAX_ENDSTOP" by the endstop you are using for Z2 axis.
+    #define Z2_USE_ENDSTOP _XMAX_
   #endif
 
 #endif // Z_DUAL_STEPPER_DRIVERS
@@ -655,6 +653,38 @@ const unsigned int dropsegments = 5; //everything with less than this number of
 
 #endif
 
+/**
+ * TWI/I2C BUS
+ *
+ * This feature is an EXPERIMENTAL feature so it shall not be used on production
+ * machines. Enabling this will allow you to send and receive I2C data from slave
+ * devices on the bus.
+ *
+ * ; Example #1
+ * ; This macro send the string "Marlin" to the slave device with address 0x63
+ * ; It uses multiple M155 commands with one B<base 10> arg
+ * M155 A63  ; Target slave address
+ * M155 B77  ; M
+ * M155 B97  ; a
+ * M155 B114 ; r
+ * M155 B108 ; l
+ * M155 B105 ; i
+ * M155 B110 ; n
+ * M155 S1   ; Send the current buffer
+ *
+ * ; Example #2
+ * ; Request 6 bytes from slave device with address 0x63
+ * M156 A63 B5
+ *
+ * ; Example #3
+ * ; Example serial output of a M156 request
+ * echo:i2c-reply: from:63 bytes:5 data:hello
+ */
+
+// @section i2cbus
+
+//#define EXPERIMENTAL_I2CBUS
+
 #include "Conditionals.h"
 #include "SanityCheck.h"
 
diff --git a/Marlin/example_configurations/adafruit/ST7565/Configuration.h b/Marlin/example_configurations/adafruit/ST7565/Configuration.h
index 8effe9d8917ebc9e84ad7f37055f11c34cbba794..052008aa58ba207965d93c59b6cc54d63351d9fb 100644
--- a/Marlin/example_configurations/adafruit/ST7565/Configuration.h
+++ b/Marlin/example_configurations/adafruit/ST7565/Configuration.h
@@ -346,8 +346,22 @@
 // Enable this option for Toshiba steppers
 //#define CONFIG_STEPPERS_TOSHIBA
 
+//===========================================================================
+//============================== Endstop Settings ===========================
+//===========================================================================
+
 // @section homing
 
+// Specify here all the endstop connectors that are connected to any endstop or probe.
+// Almost all printers will be using one per axis. Probes will use one or more of the
+// extra connectors. Leave undefined any used for non-endstop and non-probe purposes.
+#define USE_XMIN_PLUG
+#define USE_YMIN_PLUG
+#define USE_ZMIN_PLUG
+//#define USE_XMAX_PLUG
+//#define USE_YMAX_PLUG
+//#define USE_ZMAX_PLUG
+
 // coarse Endstop Settings
 #define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors
 
@@ -370,8 +384,6 @@ const bool X_MAX_ENDSTOP_INVERTING = false; // set to true to invert the logic o
 const bool Y_MAX_ENDSTOP_INVERTING = false; // set to true to invert the logic of the endstop.
 const bool Z_MAX_ENDSTOP_INVERTING = false; // set to true to invert the logic of the endstop.
 const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the logic of the endstop.
-//#define DISABLE_MAX_ENDSTOPS
-//#define DISABLE_MIN_ENDSTOPS
 
 //===========================================================================
 //============================= Z Probe Options =============================
@@ -709,9 +721,12 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l
 // Host Keepalive
 //
 // By default Marlin will send a busy status message to the host
-// every 10 seconds when it can't accept commands.
+// every couple of seconds when it can't accept commands.
 //
 //#define DISABLE_HOST_KEEPALIVE // Enable this option if your host doesn't like keepalive messages.
+#if DISABLED(DISABLE_HOST_KEEPALIVE)
+  #define DEFAULT_KEEPALIVE_INTERVAL 2 // Number of seconds between "busy" messages. Set with M113.
+#endif
 
 //
 // M100 Free Memory Watcher
diff --git a/Marlin/example_configurations/delta/biv2.5/Configuration.h b/Marlin/example_configurations/delta/biv2.5/Configuration.h
index feff6f4b743ffdf764f52870632c817cc8fa7ecf..ce1bbf5cc3bd657e9dc9f7f70d0935bde93af68e 100644
--- a/Marlin/example_configurations/delta/biv2.5/Configuration.h
+++ b/Marlin/example_configurations/delta/biv2.5/Configuration.h
@@ -381,8 +381,22 @@
 // Enable this option for Toshiba steppers
 //#define CONFIG_STEPPERS_TOSHIBA
 
+//===========================================================================
+//============================== Endstop Settings ===========================
+//===========================================================================
+
 // @section homing
 
+// Specify here all the endstop connectors that are connected to any endstop or probe.
+// Almost all printers will be using one per axis. Probes will use one or more of the
+// extra connectors. Leave undefined any used for non-endstop and non-probe purposes.
+//#define USE_XMIN_PLUG
+//#define USE_YMIN_PLUG
+//#define USE_ZMIN_PLUG
+#define USE_XMAX_PLUG
+#define USE_YMAX_PLUG
+#define USE_ZMAX_PLUG
+
 // coarse Endstop Settings
 #define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors
 
@@ -405,8 +419,6 @@ const bool X_MAX_ENDSTOP_INVERTING = false; // set to true to invert the logic o
 const bool Y_MAX_ENDSTOP_INVERTING = false; // set to true to invert the logic of the endstop.
 const bool Z_MAX_ENDSTOP_INVERTING = false; // set to true to invert the logic of the endstop.
 const bool Z_MIN_PROBE_ENDSTOP_INVERTING = true; // set to true to invert the logic of the endstop.
-//#define DISABLE_MAX_ENDSTOPS
-#define DISABLE_MIN_ENDSTOPS // Deltas only use min endstops for probing.
 
 //===========================================================================
 //============================= Z Probe Options =============================
@@ -831,9 +843,12 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = true; // set to true to invert the lo
 // Host Keepalive
 //
 // By default Marlin will send a busy status message to the host
-// every 10 seconds when it can't accept commands.
+// every couple of seconds when it can't accept commands.
 //
 //#define DISABLE_HOST_KEEPALIVE // Enable this option if your host doesn't like keepalive messages.
+#if DISABLED(DISABLE_HOST_KEEPALIVE)
+  #define DEFAULT_KEEPALIVE_INTERVAL 2 // Number of seconds between "busy" messages. Set with M113.
+#endif
 
 //
 // M100 Free Memory Watcher
diff --git a/Marlin/example_configurations/delta/biv2.5/Configuration_adv.h b/Marlin/example_configurations/delta/biv2.5/Configuration_adv.h
index 85734dc416fd03b69acef8de7d916eadef3c29c7..da192eb81a9abd1c37d01563c8595d2d8ef3d9a1 100644
--- a/Marlin/example_configurations/delta/biv2.5/Configuration_adv.h
+++ b/Marlin/example_configurations/delta/biv2.5/Configuration_adv.h
@@ -201,9 +201,7 @@
   //#define Z_DUAL_ENDSTOPS
 
   #if ENABLED(Z_DUAL_ENDSTOPS)
-    #define Z2_MAX_PIN 36                     //Endstop used for Z2 axis. In this case I'm using XMAX in a Rumba Board (pin 36)
-    const bool Z2_MAX_ENDSTOP_INVERTING = false;
-    #define DISABLE_XMAX_ENDSTOP              //Better to disable the XMAX to avoid conflict. Just rename "XMAX_ENDSTOP" by the endstop you are using for Z2 axis.
+    #define Z2_USE_ENDSTOP _XMAX_
   #endif
 
 #endif // Z_DUAL_STEPPER_DRIVERS
@@ -657,6 +655,38 @@ const unsigned int dropsegments = 5; //everything with less than this number of
 
 #endif
 
+/**
+ * TWI/I2C BUS
+ *
+ * This feature is an EXPERIMENTAL feature so it shall not be used on production
+ * machines. Enabling this will allow you to send and receive I2C data from slave
+ * devices on the bus.
+ *
+ * ; Example #1
+ * ; This macro send the string "Marlin" to the slave device with address 0x63
+ * ; It uses multiple M155 commands with one B<base 10> arg
+ * M155 A63  ; Target slave address
+ * M155 B77  ; M
+ * M155 B97  ; a
+ * M155 B114 ; r
+ * M155 B108 ; l
+ * M155 B105 ; i
+ * M155 B110 ; n
+ * M155 S1   ; Send the current buffer
+ *
+ * ; Example #2
+ * ; Request 6 bytes from slave device with address 0x63
+ * M156 A63 B5
+ *
+ * ; Example #3
+ * ; Example serial output of a M156 request
+ * echo:i2c-reply: from:63 bytes:5 data:hello
+ */
+
+// @section i2cbus
+
+//#define EXPERIMENTAL_I2CBUS
+
 #include "Conditionals.h"
 #include "SanityCheck.h"
 
diff --git a/Marlin/example_configurations/delta/generic/Configuration.h b/Marlin/example_configurations/delta/generic/Configuration.h
index 93d7f8ad7d8b4fb971ed866964ab7c2d306912fb..bc323fd5a56c7f418a18c60c0744d08e08debde8 100644
--- a/Marlin/example_configurations/delta/generic/Configuration.h
+++ b/Marlin/example_configurations/delta/generic/Configuration.h
@@ -381,8 +381,22 @@
 // Enable this option for Toshiba steppers
 //#define CONFIG_STEPPERS_TOSHIBA
 
+//===========================================================================
+//============================== Endstop Settings ===========================
+//===========================================================================
+
 // @section homing
 
+// Specify here all the endstop connectors that are connected to any endstop or probe.
+// Almost all printers will be using one per axis. Probes will use one or more of the
+// extra connectors. Leave undefined any used for non-endstop and non-probe purposes.
+//#define USE_XMIN_PLUG
+//#define USE_YMIN_PLUG
+#define USE_ZMIN_PLUG // a Z probe
+#define USE_XMAX_PLUG
+#define USE_YMAX_PLUG
+#define USE_ZMAX_PLUG
+
 // coarse Endstop Settings
 #define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors
 
@@ -405,8 +419,6 @@ const bool X_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of
 const bool Y_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of the endstop.
 const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of the endstop.
 const bool Z_MIN_PROBE_ENDSTOP_INVERTING = true; // set to true to invert the logic of the endstop.
-//#define DISABLE_MAX_ENDSTOPS
-#define DISABLE_MIN_ENDSTOPS // Deltas only use min endstops for probing.
 
 //===========================================================================
 //============================= Z Probe Options =============================
@@ -831,9 +843,12 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = true; // set to true to invert the lo
 // Host Keepalive
 //
 // By default Marlin will send a busy status message to the host
-// every 10 seconds when it can't accept commands.
+// every couple of seconds when it can't accept commands.
 //
 //#define DISABLE_HOST_KEEPALIVE // Enable this option if your host doesn't like keepalive messages.
+#if DISABLED(DISABLE_HOST_KEEPALIVE)
+  #define DEFAULT_KEEPALIVE_INTERVAL 2 // Number of seconds between "busy" messages. Set with M113.
+#endif
 
 //
 // M100 Free Memory Watcher
diff --git a/Marlin/example_configurations/delta/generic/Configuration_adv.h b/Marlin/example_configurations/delta/generic/Configuration_adv.h
index 006502e7a52c01327f1578b0eb12a9e98074556a..b2bf328571d6d9ba20968e3a3c93baa9a6941a86 100644
--- a/Marlin/example_configurations/delta/generic/Configuration_adv.h
+++ b/Marlin/example_configurations/delta/generic/Configuration_adv.h
@@ -201,9 +201,7 @@
   //#define Z_DUAL_ENDSTOPS
 
   #if ENABLED(Z_DUAL_ENDSTOPS)
-    #define Z2_MAX_PIN 36                     //Endstop used for Z2 axis. In this case I'm using XMAX in a Rumba Board (pin 36)
-    const bool Z2_MAX_ENDSTOP_INVERTING = false;
-    #define DISABLE_XMAX_ENDSTOP              //Better to disable the XMAX to avoid conflict. Just rename "XMAX_ENDSTOP" by the endstop you are using for Z2 axis.
+    #define Z2_USE_ENDSTOP _XMAX_
   #endif
 
 #endif // Z_DUAL_STEPPER_DRIVERS
@@ -657,6 +655,38 @@ const unsigned int dropsegments = 5; //everything with less than this number of
 
 #endif
 
+/**
+ * TWI/I2C BUS
+ *
+ * This feature is an EXPERIMENTAL feature so it shall not be used on production
+ * machines. Enabling this will allow you to send and receive I2C data from slave
+ * devices on the bus.
+ *
+ * ; Example #1
+ * ; This macro send the string "Marlin" to the slave device with address 0x63
+ * ; It uses multiple M155 commands with one B<base 10> arg
+ * M155 A63  ; Target slave address
+ * M155 B77  ; M
+ * M155 B97  ; a
+ * M155 B114 ; r
+ * M155 B108 ; l
+ * M155 B105 ; i
+ * M155 B110 ; n
+ * M155 S1   ; Send the current buffer
+ *
+ * ; Example #2
+ * ; Request 6 bytes from slave device with address 0x63
+ * M156 A63 B5
+ *
+ * ; Example #3
+ * ; Example serial output of a M156 request
+ * echo:i2c-reply: from:63 bytes:5 data:hello
+ */
+
+// @section i2cbus
+
+//#define EXPERIMENTAL_I2CBUS
+
 #include "Conditionals.h"
 #include "SanityCheck.h"
 
diff --git a/Marlin/example_configurations/delta/kossel_mini/Configuration.h b/Marlin/example_configurations/delta/kossel_mini/Configuration.h
index cde4707f301d47bbf31579896ca6a263941034c9..fbaa538e96659eca10e38290044b22ad27b6cd96 100644
--- a/Marlin/example_configurations/delta/kossel_mini/Configuration.h
+++ b/Marlin/example_configurations/delta/kossel_mini/Configuration.h
@@ -381,8 +381,22 @@
 // Enable this option for Toshiba steppers
 //#define CONFIG_STEPPERS_TOSHIBA
 
+//===========================================================================
+//============================== Endstop Settings ===========================
+//===========================================================================
+
 // @section homing
 
+// Specify here all the endstop connectors that are connected to any endstop or probe.
+// Almost all printers will be using one per axis. Probes will use one or more of the
+// extra connectors. Leave undefined any used for non-endstop and non-probe purposes.
+//#define USE_XMIN_PLUG
+//#define USE_YMIN_PLUG
+//#define USE_ZMIN_PLUG
+#define USE_XMAX_PLUG
+#define USE_YMAX_PLUG
+#define USE_ZMAX_PLUG
+
 // coarse Endstop Settings
 #define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors
 
@@ -405,8 +419,6 @@ const bool X_MAX_ENDSTOP_INVERTING = false; // set to true to invert the logic o
 const bool Y_MAX_ENDSTOP_INVERTING = false; // set to true to invert the logic of the endstop.
 const bool Z_MAX_ENDSTOP_INVERTING = false; // set to true to invert the logic of the endstop.
 const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the logic of the endstop.
-//#define DISABLE_MAX_ENDSTOPS
-//#define DISABLE_MIN_ENDSTOPS // Deltas only use min endstops for probing.
 
 //===========================================================================
 //============================= Z Probe Options =============================
@@ -835,9 +847,12 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l
 // Host Keepalive
 //
 // By default Marlin will send a busy status message to the host
-// every 10 seconds when it can't accept commands.
+// every couple of seconds when it can't accept commands.
 //
 //#define DISABLE_HOST_KEEPALIVE // Enable this option if your host doesn't like keepalive messages.
+#if DISABLED(DISABLE_HOST_KEEPALIVE)
+  #define DEFAULT_KEEPALIVE_INTERVAL 2 // Number of seconds between "busy" messages. Set with M113.
+#endif
 
 //
 // M100 Free Memory Watcher
diff --git a/Marlin/example_configurations/delta/kossel_mini/Configuration_adv.h b/Marlin/example_configurations/delta/kossel_mini/Configuration_adv.h
index 4b93e46474cf0a9f4e1977165a590a35e8987c74..fa0da7cdd3972b0f5322d2d5b8b1c9634c10c3f2 100644
--- a/Marlin/example_configurations/delta/kossel_mini/Configuration_adv.h
+++ b/Marlin/example_configurations/delta/kossel_mini/Configuration_adv.h
@@ -201,9 +201,7 @@
   //#define Z_DUAL_ENDSTOPS
 
   #if ENABLED(Z_DUAL_ENDSTOPS)
-    #define Z2_MAX_PIN 36                     //Endstop used for Z2 axis. In this case I'm using XMAX in a Rumba Board (pin 36)
-    const bool Z2_MAX_ENDSTOP_INVERTING = false;
-    #define DISABLE_XMAX_ENDSTOP              //Better to disable the XMAX to avoid conflict. Just rename "XMAX_ENDSTOP" by the endstop you are using for Z2 axis.
+    #define Z2_USE_ENDSTOP _XMAX_
   #endif
 
 #endif // Z_DUAL_STEPPER_DRIVERS
@@ -656,6 +654,38 @@ const unsigned int dropsegments = 5; //everything with less than this number of
 
 #endif
 
+/**
+ * TWI/I2C BUS
+ *
+ * This feature is an EXPERIMENTAL feature so it shall not be used on production
+ * machines. Enabling this will allow you to send and receive I2C data from slave
+ * devices on the bus.
+ *
+ * ; Example #1
+ * ; This macro send the string "Marlin" to the slave device with address 0x63
+ * ; It uses multiple M155 commands with one B<base 10> arg
+ * M155 A63  ; Target slave address
+ * M155 B77  ; M
+ * M155 B97  ; a
+ * M155 B114 ; r
+ * M155 B108 ; l
+ * M155 B105 ; i
+ * M155 B110 ; n
+ * M155 S1   ; Send the current buffer
+ *
+ * ; Example #2
+ * ; Request 6 bytes from slave device with address 0x63
+ * M156 A63 B5
+ *
+ * ; Example #3
+ * ; Example serial output of a M156 request
+ * echo:i2c-reply: from:63 bytes:5 data:hello
+ */
+
+// @section i2cbus
+
+//#define EXPERIMENTAL_I2CBUS
+
 #include "Conditionals.h"
 #include "SanityCheck.h"
 
diff --git a/Marlin/example_configurations/delta/kossel_pro/Configuration.h b/Marlin/example_configurations/delta/kossel_pro/Configuration.h
index 5255b7accc5ae5bf342066a5c92c4c3e5bd82e90..aedcf72af2e3c878e33c826900ec8f30973849f4 100644
--- a/Marlin/example_configurations/delta/kossel_pro/Configuration.h
+++ b/Marlin/example_configurations/delta/kossel_pro/Configuration.h
@@ -370,8 +370,22 @@
 // Enable this option for Toshiba steppers
 //#define CONFIG_STEPPERS_TOSHIBA
 
+//===========================================================================
+//============================== Endstop Settings ===========================
+//===========================================================================
+
 // @section homing
 
+// Specify here all the endstop connectors that are connected to any endstop or probe.
+// Almost all printers will be using one per axis. Probes will use one or more of the
+// extra connectors. Leave undefined any used for non-endstop and non-probe purposes.
+//#define USE_XMIN_PLUG
+//#define USE_YMIN_PLUG
+#define USE_ZMIN_PLUG // a Z probe
+#define USE_XMAX_PLUG
+#define USE_YMAX_PLUG
+#define USE_ZMAX_PLUG
+
 // coarse Endstop Settings
 #define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors
 
@@ -394,8 +408,6 @@ const bool X_MAX_ENDSTOP_INVERTING = false; // set to true to invert the logic o
 const bool Y_MAX_ENDSTOP_INVERTING = false; // set to true to invert the logic of the endstop.
 const bool Z_MAX_ENDSTOP_INVERTING = false; // set to true to invert the logic of the endstop.
 const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the logic of the endstop.
-//#define DISABLE_MAX_ENDSTOPS
-//#define DISABLE_MIN_ENDSTOPS // Deltas only use min endstops for probing.
 
 //===========================================================================
 //============================= Z Probe Options =============================
@@ -828,9 +840,12 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l
 // Host Keepalive
 //
 // By default Marlin will send a busy status message to the host
-// every 10 seconds when it can't accept commands.
+// every couple of seconds when it can't accept commands.
 //
 //#define DISABLE_HOST_KEEPALIVE // Enable this option if your host doesn't like keepalive messages.
+#if DISABLED(DISABLE_HOST_KEEPALIVE)
+  #define DEFAULT_KEEPALIVE_INTERVAL 2 // Number of seconds between "busy" messages. Set with M113.
+#endif
 
 //
 // M100 Free Memory Watcher
diff --git a/Marlin/example_configurations/delta/kossel_pro/Configuration_adv.h b/Marlin/example_configurations/delta/kossel_pro/Configuration_adv.h
index b3fec75c5ac0a7556069fa37faec8958420903cd..6ace77f421658246204932623f1c6024edc724a5 100644
--- a/Marlin/example_configurations/delta/kossel_pro/Configuration_adv.h
+++ b/Marlin/example_configurations/delta/kossel_pro/Configuration_adv.h
@@ -206,9 +206,7 @@
   //#define Z_DUAL_ENDSTOPS
 
   #if ENABLED(Z_DUAL_ENDSTOPS)
-    #define Z2_MAX_PIN 36                     //Endstop used for Z2 axis. In this case I'm using XMAX in a Rumba Board (pin 36)
-    const bool Z2_MAX_ENDSTOP_INVERTING = false;
-    #define DISABLE_XMAX_ENDSTOP              //Better to disable the XMAX to avoid conflict. Just rename "XMAX_ENDSTOP" by the endstop you are using for Z2 axis.
+    #define Z2_USE_ENDSTOP _XMAX_
   #endif
 
 #endif // Z_DUAL_STEPPER_DRIVERS
@@ -661,6 +659,38 @@ const unsigned int dropsegments = 5; //everything with less than this number of
 
 #endif
 
+/**
+ * TWI/I2C BUS
+ *
+ * This feature is an EXPERIMENTAL feature so it shall not be used on production
+ * machines. Enabling this will allow you to send and receive I2C data from slave
+ * devices on the bus.
+ *
+ * ; Example #1
+ * ; This macro send the string "Marlin" to the slave device with address 0x63
+ * ; It uses multiple M155 commands with one B<base 10> arg
+ * M155 A63  ; Target slave address
+ * M155 B77  ; M
+ * M155 B97  ; a
+ * M155 B114 ; r
+ * M155 B108 ; l
+ * M155 B105 ; i
+ * M155 B110 ; n
+ * M155 S1   ; Send the current buffer
+ *
+ * ; Example #2
+ * ; Request 6 bytes from slave device with address 0x63
+ * M156 A63 B5
+ *
+ * ; Example #3
+ * ; Example serial output of a M156 request
+ * echo:i2c-reply: from:63 bytes:5 data:hello
+ */
+
+// @section i2cbus
+
+//#define EXPERIMENTAL_I2CBUS
+
 #include "Conditionals.h"
 #include "SanityCheck.h"
 
diff --git a/Marlin/example_configurations/delta/kossel_xl/Configuration.h b/Marlin/example_configurations/delta/kossel_xl/Configuration.h
index f7ee5404ccaa511ed83815eae74b97d201e806f1..cba52bf4afda03e4e4c208d502ac4ad651575b1e 100644
--- a/Marlin/example_configurations/delta/kossel_xl/Configuration.h
+++ b/Marlin/example_configurations/delta/kossel_xl/Configuration.h
@@ -374,8 +374,22 @@
 // Enable this option for Toshiba steppers
 //#define CONFIG_STEPPERS_TOSHIBA
 
+//===========================================================================
+//============================== Endstop Settings ===========================
+//===========================================================================
+
 // @section homing
 
+// Specify here all the endstop connectors that are connected to any endstop or probe.
+// Almost all printers will be using one per axis. Probes will use one or more of the
+// extra connectors. Leave undefined any used for non-endstop and non-probe purposes.
+//#define USE_XMIN_PLUG
+//#define USE_YMIN_PLUG
+#define USE_ZMIN_PLUG // a Z probe
+#define USE_XMAX_PLUG
+#define USE_YMAX_PLUG
+#define USE_ZMAX_PLUG
+
 // coarse Endstop Settings
 //#define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors
 
@@ -398,8 +412,6 @@ const bool X_MAX_ENDSTOP_INVERTING = false; // set to true to invert the logic o
 const bool Y_MAX_ENDSTOP_INVERTING = false; // set to true to invert the logic of the endstop.
 const bool Z_MAX_ENDSTOP_INVERTING = false; // set to true to invert the logic of the endstop.
 const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the logic of the endstop.
-//#define DISABLE_MAX_ENDSTOPS
-//#define DISABLE_MIN_ENDSTOPS
 
 //===========================================================================
 //============================= Z Probe Options =============================
@@ -745,9 +757,12 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l
 // Host Keepalive
 //
 // By default Marlin will send a busy status message to the host
-// every 10 seconds when it can't accept commands.
+// every couple of seconds when it can't accept commands.
 //
 //#define DISABLE_HOST_KEEPALIVE // Enable this option if your host doesn't like keepalive messages.
+#if DISABLED(DISABLE_HOST_KEEPALIVE)
+  #define DEFAULT_KEEPALIVE_INTERVAL 2 // Number of seconds between "busy" messages. Set with M113.
+#endif
 
 //
 // M100 Free Memory Watcher
diff --git a/Marlin/example_configurations/delta/kossel_xl/Configuration_adv.h b/Marlin/example_configurations/delta/kossel_xl/Configuration_adv.h
index 44e7942eb2108840188306fbcc033310d0041de4..f42f8770147c48577c05c4d8def079d59beb6024 100644
--- a/Marlin/example_configurations/delta/kossel_xl/Configuration_adv.h
+++ b/Marlin/example_configurations/delta/kossel_xl/Configuration_adv.h
@@ -201,9 +201,7 @@
   //#define Z_DUAL_ENDSTOPS
 
   #if ENABLED(Z_DUAL_ENDSTOPS)
-    #define Z2_MAX_PIN 36                     //Endstop used for Z2 axis. In this case I'm using XMAX in a Rumba Board (pin 36)
-    const bool Z2_MAX_ENDSTOP_INVERTING = false;
-    #define DISABLE_XMAX_ENDSTOP              //Better to disable the XMAX to avoid conflict. Just rename "XMAX_ENDSTOP" by the endstop you are using for Z2 axis.
+    #define Z2_USE_ENDSTOP _XMAX_
   #endif
 
 #endif // Z_DUAL_STEPPER_DRIVERS
@@ -655,6 +653,38 @@ const unsigned int dropsegments = 5; //everything with less than this number of
 
 #endif
 
+/**
+ * TWI/I2C BUS
+ *
+ * This feature is an EXPERIMENTAL feature so it shall not be used on production
+ * machines. Enabling this will allow you to send and receive I2C data from slave
+ * devices on the bus.
+ *
+ * ; Example #1
+ * ; This macro send the string "Marlin" to the slave device with address 0x63
+ * ; It uses multiple M155 commands with one B<base 10> arg
+ * M155 A63  ; Target slave address
+ * M155 B77  ; M
+ * M155 B97  ; a
+ * M155 B114 ; r
+ * M155 B108 ; l
+ * M155 B105 ; i
+ * M155 B110 ; n
+ * M155 S1   ; Send the current buffer
+ *
+ * ; Example #2
+ * ; Request 6 bytes from slave device with address 0x63
+ * M156 A63 B5
+ *
+ * ; Example #3
+ * ; Example serial output of a M156 request
+ * echo:i2c-reply: from:63 bytes:5 data:hello
+ */
+
+// @section i2cbus
+
+//#define EXPERIMENTAL_I2CBUS
+
 #include "Conditionals.h"
 #include "SanityCheck.h"
 
diff --git a/Marlin/example_configurations/makibox/Configuration.h b/Marlin/example_configurations/makibox/Configuration.h
index bd550066c7fbc9e0a701e2a7ffa17802bde63e52..301c7d9b6fe939bb60f82b89190ec820ea69cf37 100644
--- a/Marlin/example_configurations/makibox/Configuration.h
+++ b/Marlin/example_configurations/makibox/Configuration.h
@@ -349,8 +349,22 @@
 // Enable this option for Toshiba steppers
 //#define CONFIG_STEPPERS_TOSHIBA
 
+//===========================================================================
+//============================== Endstop Settings ===========================
+//===========================================================================
+
 // @section homing
 
+// Specify here all the endstop connectors that are connected to any endstop or probe.
+// Almost all printers will be using one per axis. Probes will use one or more of the
+// extra connectors. Leave undefined any used for non-endstop and non-probe purposes.
+#define USE_XMIN_PLUG
+#define USE_YMIN_PLUG
+#define USE_ZMIN_PLUG
+//#define USE_XMAX_PLUG
+//#define USE_YMAX_PLUG
+//#define USE_ZMAX_PLUG
+
 // coarse Endstop Settings
 #define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors
 
@@ -373,8 +387,6 @@ const bool X_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of
 const bool Y_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of the endstop.
 const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of the endstop.
 const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the logic of the endstop.
-//#define DISABLE_MAX_ENDSTOPS
-//#define DISABLE_MIN_ENDSTOPS
 
 //===========================================================================
 //============================= Z Probe Options =============================
@@ -712,9 +724,12 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = false; // set to true to invert the l
 // Host Keepalive
 //
 // By default Marlin will send a busy status message to the host
-// every 10 seconds when it can't accept commands.
+// every couple of seconds when it can't accept commands.
 //
 //#define DISABLE_HOST_KEEPALIVE // Enable this option if your host doesn't like keepalive messages.
+#if DISABLED(DISABLE_HOST_KEEPALIVE)
+  #define DEFAULT_KEEPALIVE_INTERVAL 2 // Number of seconds between "busy" messages. Set with M113.
+#endif
 
 //
 // M100 Free Memory Watcher
diff --git a/Marlin/example_configurations/makibox/Configuration_adv.h b/Marlin/example_configurations/makibox/Configuration_adv.h
index 9b131b329882307b9bf55424a5620b895e72c587..16f00bbf9b2230b0a4660ebac0705b786ee11717 100644
--- a/Marlin/example_configurations/makibox/Configuration_adv.h
+++ b/Marlin/example_configurations/makibox/Configuration_adv.h
@@ -201,9 +201,7 @@
   //#define Z_DUAL_ENDSTOPS
 
   #if ENABLED(Z_DUAL_ENDSTOPS)
-    #define Z2_MAX_PIN 36                     //Endstop used for Z2 axis. In this case I'm using XMAX in a Rumba Board (pin 36)
-    const bool Z2_MAX_ENDSTOP_INVERTING = false;
-    #define DISABLE_XMAX_ENDSTOP              //Better to disable the XMAX to avoid conflict. Just rename "XMAX_ENDSTOP" by the endstop you are using for Z2 axis.
+    #define Z2_USE_ENDSTOP _XMAX_
   #endif
 
 #endif // Z_DUAL_STEPPER_DRIVERS
@@ -655,6 +653,38 @@ const unsigned int dropsegments = 5; //everything with less than this number of
 
 #endif
 
+/**
+ * TWI/I2C BUS
+ *
+ * This feature is an EXPERIMENTAL feature so it shall not be used on production
+ * machines. Enabling this will allow you to send and receive I2C data from slave
+ * devices on the bus.
+ *
+ * ; Example #1
+ * ; This macro send the string "Marlin" to the slave device with address 0x63
+ * ; It uses multiple M155 commands with one B<base 10> arg
+ * M155 A63  ; Target slave address
+ * M155 B77  ; M
+ * M155 B97  ; a
+ * M155 B114 ; r
+ * M155 B108 ; l
+ * M155 B105 ; i
+ * M155 B110 ; n
+ * M155 S1   ; Send the current buffer
+ *
+ * ; Example #2
+ * ; Request 6 bytes from slave device with address 0x63
+ * M156 A63 B5
+ *
+ * ; Example #3
+ * ; Example serial output of a M156 request
+ * echo:i2c-reply: from:63 bytes:5 data:hello
+ */
+
+// @section i2cbus
+
+//#define EXPERIMENTAL_I2CBUS
+
 #include "Conditionals.h"
 #include "SanityCheck.h"
 
diff --git a/Marlin/example_configurations/tvrrug/Round2/Configuration.h b/Marlin/example_configurations/tvrrug/Round2/Configuration.h
index b7431e9d251afedf1c84fd3864d36ab16f08c285..f162ff7b600bf90fae2a2fcad860727cd48d3bc4 100644
--- a/Marlin/example_configurations/tvrrug/Round2/Configuration.h
+++ b/Marlin/example_configurations/tvrrug/Round2/Configuration.h
@@ -336,8 +336,22 @@
 // Enable this option for Toshiba steppers
 #define CONFIG_STEPPERS_TOSHIBA
 
+//===========================================================================
+//============================== Endstop Settings ===========================
+//===========================================================================
+
 // @section homing
 
+// Specify here all the endstop connectors that are connected to any endstop or probe.
+// Almost all printers will be using one per axis. Probes will use one or more of the
+// extra connectors. Leave undefined any used for non-endstop and non-probe purposes.
+#define USE_XMIN_PLUG
+#define USE_YMIN_PLUG
+#define USE_ZMIN_PLUG
+//#define USE_XMAX_PLUG
+//#define USE_YMAX_PLUG
+//#define USE_ZMAX_PLUG
+
 // coarse Endstop Settings
 #define ENDSTOPPULLUPS // Comment this out (using // at the start of the line) to disable the endstop pullup resistors
 
@@ -360,8 +374,6 @@ const bool X_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of
 const bool Y_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of the endstop.
 const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of the endstop.
 const bool Z_MIN_PROBE_ENDSTOP_INVERTING = true; // set to true to invert the logic of the endstop.
-//#define DISABLE_MAX_ENDSTOPS
-//#define DISABLE_MIN_ENDSTOPS
 
 //===========================================================================
 //============================= Z Probe Options =============================
@@ -703,9 +715,12 @@ const bool Z_MIN_PROBE_ENDSTOP_INVERTING = true; // set to true to invert the lo
 // Host Keepalive
 //
 // By default Marlin will send a busy status message to the host
-// every 10 seconds when it can't accept commands.
+// every couple of seconds when it can't accept commands.
 //
 //#define DISABLE_HOST_KEEPALIVE // Enable this option if your host doesn't like keepalive messages.
+#if DISABLED(DISABLE_HOST_KEEPALIVE)
+  #define DEFAULT_KEEPALIVE_INTERVAL 2 // Number of seconds between "busy" messages. Set with M113.
+#endif
 
 //
 // M100 Free Memory Watcher
diff --git a/Marlin/example_configurations/tvrrug/Round2/Configuration_adv.h b/Marlin/example_configurations/tvrrug/Round2/Configuration_adv.h
index 37d3bd81e236df46278f28674f6147bbfde39ab4..c8ddbd603c25865ddcbb1f5e3179e8c91906f94a 100644
--- a/Marlin/example_configurations/tvrrug/Round2/Configuration_adv.h
+++ b/Marlin/example_configurations/tvrrug/Round2/Configuration_adv.h
@@ -201,9 +201,7 @@
   //#define Z_DUAL_ENDSTOPS
 
   #if ENABLED(Z_DUAL_ENDSTOPS)
-    #define Z2_MAX_PIN 36                     //Endstop used for Z2 axis. In this case I'm using XMAX in a Rumba Board (pin 36)
-    const bool Z2_MAX_ENDSTOP_INVERTING = false;
-    #define DISABLE_XMAX_ENDSTOP              //Better to disable the XMAX to avoid conflict. Just rename "XMAX_ENDSTOP" by the endstop you are using for Z2 axis.
+    #define Z2_USE_ENDSTOP _XMAX_
   #endif
 
 #endif // Z_DUAL_STEPPER_DRIVERS
@@ -655,6 +653,38 @@ const unsigned int dropsegments = 5; //everything with less than this number of
 
 #endif
 
+/**
+ * TWI/I2C BUS
+ *
+ * This feature is an EXPERIMENTAL feature so it shall not be used on production
+ * machines. Enabling this will allow you to send and receive I2C data from slave
+ * devices on the bus.
+ *
+ * ; Example #1
+ * ; This macro send the string "Marlin" to the slave device with address 0x63
+ * ; It uses multiple M155 commands with one B<base 10> arg
+ * M155 A63  ; Target slave address
+ * M155 B77  ; M
+ * M155 B97  ; a
+ * M155 B114 ; r
+ * M155 B108 ; l
+ * M155 B105 ; i
+ * M155 B110 ; n
+ * M155 S1   ; Send the current buffer
+ *
+ * ; Example #2
+ * ; Request 6 bytes from slave device with address 0x63
+ * M156 A63 B5
+ *
+ * ; Example #3
+ * ; Example serial output of a M156 request
+ * echo:i2c-reply: from:63 bytes:5 data:hello
+ */
+
+// @section i2cbus
+
+//#define EXPERIMENTAL_I2CBUS
+
 #include "Conditionals.h"
 #include "SanityCheck.h"
 
diff --git a/Marlin/fonts/README.fonts b/Marlin/fonts/README.fonts
index 1d1cda4ce4b411fd54f8473a394f97dd8613587f..971275d1876c1e1913c3dcd2bb4bbb2617939933 100644
--- a/Marlin/fonts/README.fonts
+++ b/Marlin/fonts/README.fonts
@@ -21,6 +21,3 @@ For the second half of the font we now support up to 11x11 pixel.
     #else // fall-back
  * Add your font to the list of permitted fonts in 'language_en.h'
     ... || ENABLED(DISPLAY_CHARSET_YOUR_NEW_FONT) ... )
-
-
-Especially the Kana font should be revised by someone who knows what he/she does. I am only a west-European with very little knowledge about this script.
diff --git a/Marlin/language.h b/Marlin/language.h
index 5d8033e363501c8c68675a98757eae5a073471ca..9085a6a85f29fb0c8405566adf9cd2a6b44c19ab 100644
--- a/Marlin/language.h
+++ b/Marlin/language.h
@@ -82,6 +82,12 @@
 #endif
 
 #ifndef DEFAULT_SOURCE_URL
+  /**
+   * The SOURCE_CODE_URL is the location where users will find the Marlin Source
+   * Code which is installed on the device. In most cases —unless the manufacturer
+   * has a distinct Github fork— the Source Code URL should just be the main
+   * Marlin repository.
+   */
   #define DEFAULT_SOURCE_URL "https://github.com/MarlinFirmware/Marlin"
 #endif
 
@@ -225,7 +231,7 @@
 #define MSG_T_MINTEMP                       "MINTEMP triggered"
 
 // Debug
-#define MSG_DEBUG_PREFIX                    "DEBUG: "
+#define MSG_DEBUG_PREFIX                    "DEBUG:"
 #define MSG_DEBUG_OFF                       "off"
 #define MSG_DEBUG_ECHO                      "ECHO"
 #define MSG_DEBUG_INFO                      "INFO"
diff --git a/Marlin/language_an.h b/Marlin/language_an.h
index 8170698dbe07bb77d0798eb22386dd66d014ab9b..17e32ef8daf96ead18bea92e2bb2cf3b6ea41b92 100644
--- a/Marlin/language_an.h
+++ b/Marlin/language_an.h
@@ -45,6 +45,7 @@
 #define MSG_LEVEL_BED_HOMING                "Homing XYZ"
 #define MSG_LEVEL_BED_WAITING               "Click to Begin"
 #define MSG_LEVEL_BED_DONE                  "Leveling Done!"
+#define MSG_LEVEL_BED_CANCEL                "Cancel"
 #define MSG_SET_HOME_OFFSETS                "Set home offsets"
 #define MSG_HOME_OFFSETS_APPLIED            "Offsets applied"
 #define MSG_SET_ORIGIN                      "Establir zero"
diff --git a/Marlin/language_bg.h b/Marlin/language_bg.h
index 784dbd0b07766106893a2b3ec7ff2f8341b8d70e..062deb0dea75f4312a2a7e2f56137e065f590722 100644
--- a/Marlin/language_bg.h
+++ b/Marlin/language_bg.h
@@ -45,6 +45,7 @@
 #define MSG_LEVEL_BED_HOMING                "Homing XYZ"
 #define MSG_LEVEL_BED_WAITING               "Click to Begin"
 #define MSG_LEVEL_BED_DONE                  "Leveling Done!"
+#define MSG_LEVEL_BED_CANCEL                "Cancel"
 #define MSG_SET_HOME_OFFSETS                "Задай Начало"
 #define MSG_HOME_OFFSETS_APPLIED            "Offsets applied"
 #define MSG_SET_ORIGIN                      "Изходна точка"
diff --git a/Marlin/language_ca.h b/Marlin/language_ca.h
index b79c8e2fcaef9be140a67f659d67e6139f915daa..77fab60d8abbd5bad6a68198596c1f5463e36a57 100644
--- a/Marlin/language_ca.h
+++ b/Marlin/language_ca.h
@@ -46,6 +46,7 @@
 #define MSG_LEVEL_BED_HOMING                "Homing XYZ"
 #define MSG_LEVEL_BED_WAITING               "Click to Begin"
 #define MSG_LEVEL_BED_DONE                  "Leveling Done!"
+#define MSG_LEVEL_BED_CANCEL                "Cancel"
 #define MSG_SET_HOME_OFFSETS                "Set home offsets"
 #define MSG_HOME_OFFSETS_APPLIED            "Offsets applied"
 #define MSG_SET_ORIGIN                      "Establir origen"
diff --git a/Marlin/language_cn.h b/Marlin/language_cn.h
index 8e0bf08245e66cb6f91ae07dd6515421fb3a748e..3473d73ab0cefdf3b152f705ae638dc98f868df5 100644
--- a/Marlin/language_cn.h
+++ b/Marlin/language_cn.h
@@ -43,6 +43,7 @@
 #define MSG_LEVEL_BED_HOMING                "Homing XYZ"
 #define MSG_LEVEL_BED_WAITING               "Click to Begin"
 #define MSG_LEVEL_BED_DONE                  "Leveling Done!"
+#define MSG_LEVEL_BED_CANCEL                "Cancel"
 #define MSG_SET_HOME_OFFSETS                "\xbe\xbf\xbb\xbc\xbd\xc0\xc1"
 #define MSG_HOME_OFFSETS_APPLIED            "Offsets applied"
 #define MSG_SET_ORIGIN                      "\xbe\xbf\xbc\xbd"
diff --git a/Marlin/language_cz.h b/Marlin/language_cz.h
index 2e71d1f011e2ada249d50d20557164ce589e9f75..2cc2d2549f3285f03c3a334ba4ef94ac60d9f9bb 100644
--- a/Marlin/language_cz.h
+++ b/Marlin/language_cz.h
@@ -47,10 +47,11 @@
 #define MSG_DISABLE_STEPPERS                "Uvolnit motory"
 #define MSG_AUTO_HOME                       "Domovska pozice"
 #define MSG_LEVEL_BED_HOMING                "Mereni podlozky"
-#define MSG_LEVEL_BED_WAITING               "Click to Begin"
-#define MSG_LEVEL_BED_DONE                  "Leveling Done!"
+#define MSG_LEVEL_BED_WAITING               "Kliknutim spustte"
+#define MSG_LEVEL_BED_DONE                  "Mereni hotovo!"
+#define MSG_LEVEL_BED_CANCEL                "Storno"
 #define MSG_SET_HOME_OFFSETS                "Nastavit ofsety"
-#define MSG_HOME_OFFSETS_APPLIED            "Offsets applied"
+#define MSG_HOME_OFFSETS_APPLIED            "Ofsety nastaveny"
 #define MSG_SET_ORIGIN                      "Nastavit pocatek"
 #define MSG_PREHEAT_PLA                     "Zahrat PLA"
 #define MSG_PREHEAT_PLA_N                   MSG_PREHEAT_PLA " "
@@ -77,6 +78,7 @@
 #define MSG_MOVE_1MM                        "Posunout o 1mm"
 #define MSG_MOVE_10MM                       "Posunout o 10mm"
 #define MSG_SPEED                           "Rychlost"
+#define MSG_BED_Z                           "Vyska podl."
 #define MSG_NOZZLE                          "Tryska"
 #define MSG_BED                             "Podlozka"
 #define MSG_FAN_SPEED                       "Rychlost vent."
diff --git a/Marlin/language_da.h b/Marlin/language_da.h
index b7e4025911adce35584ade4c23950c0214026087..2031d4e588d7d00f03c7ee89779664a0b338e594 100644
--- a/Marlin/language_da.h
+++ b/Marlin/language_da.h
@@ -44,10 +44,11 @@
 #define MSG_COOLDOWN                        "Afkøl"
 #define MSG_DISABLE_STEPPERS                "Slå stepper fra"
 #define MSG_LEVEL_BED_HOMING                "Homing XYZ"
-#define MSG_LEVEL_BED_WAITING               "Click to Begin"
-#define MSG_LEVEL_BED_DONE                  "Leveling Done!"
-#define MSG_SET_HOME_OFFSETS                "Sæt home offsets"
-#define MSG_HOME_OFFSETS_APPLIED            "Offsets applied"
+#define MSG_LEVEL_BED_WAITING               "Tryk for at starte"
+#define MSG_LEVEL_BED_DONE                  "Justering er færdig!"
+#define MSG_LEVEL_BED_CANCEL                "Annuller"
+#define MSG_SET_HOME_OFFSETS                "Sæt forskyding til udgangsposition"
+#define MSG_HOME_OFFSETS_APPLIED            "Forskydninger er tilføjet"
 #define MSG_SET_ORIGIN                      "Sæt origin"
 #define MSG_SWITCH_PS_ON                    "Slå strøm til"
 #define MSG_SWITCH_PS_OFF                   "Slå strøm fra"
@@ -83,8 +84,8 @@
 #define MSG_MAX                             " \002 Max"
 #define MSG_FACTOR                          " \002 Fact"
 #define MSG_AUTOTEMP                        "Autotemp"
-#define MSG_ON                              "On "
-#define MSG_OFF                             "Off"
+#define MSG_ON                              "Til "
+#define MSG_OFF                             "Fra"
 #define MSG_PID_P                           "PID-P"
 #define MSG_PID_I                           "PID-I"
 #define MSG_PID_D                           "PID-D"
@@ -127,10 +128,10 @@
 #define MSG_DWELL                           "Dvale..."
 #define MSG_USERWAIT                        "Venter på bruger..."
 #define MSG_RESUMING                        "Forsætter printet"
-#define MSG_PRINT_ABORTED                   "Print annuleret"
-#define MSG_NO_MOVE                         "No move."
-#define MSG_KILLED                          "KILLED. "
-#define MSG_STOPPED                         "STOPPED. "
+#define MSG_PRINT_ABORTED                   "Print annulleret"
+#define MSG_NO_MOVE                         "Ingen bevægelse."
+#define MSG_KILLED                          "DRÆBT. "
+#define MSG_STOPPED                         "STOPPET. "
 #define MSG_CONTROL_RETRACT                 "Tilbagetraek mm"
 #define MSG_CONTROL_RETRACT_SWAP            "Skift Re.mm"
 #define MSG_CONTROL_RETRACTF                "Tilbagetræk V"
diff --git a/Marlin/language_de.h b/Marlin/language_de.h
index 2274928e9091f03fff3a24417ba8eb13449d9457..ccdec82f4288c1c8a4e66dfed803669609229d2c 100644
--- a/Marlin/language_de.h
+++ b/Marlin/language_de.h
@@ -43,10 +43,11 @@
 #define MSG_DISABLE_STEPPERS                "Motoren Aus" // M84
 #define MSG_AUTO_HOME                       "Home" // G28
 #define MSG_LEVEL_BED_HOMING                "Homing XYZ"
-#define MSG_LEVEL_BED_WAITING               "Click to Begin"
-#define MSG_LEVEL_BED_DONE                  "Leveling Done!"
+#define MSG_LEVEL_BED_WAITING               "Klick für Start"
+#define MSG_LEVEL_BED_DONE                  "Fertig"
+#define MSG_LEVEL_BED_CANCEL                "Abbruch"
 #define MSG_SET_HOME_OFFSETS                "Setze Home hier"
-#define MSG_HOME_OFFSETS_APPLIED            "Offsets applied"
+#define MSG_HOME_OFFSETS_APPLIED            "Offsets aktiv"
 #define MSG_SET_ORIGIN                      "Setze Null hier" //"G92 X0 Y0 Z0" commented out in ultralcd.cpp
 #define MSG_PREHEAT_PLA                     "Vorwärmen PLA"
 #define MSG_PREHEAT_PLA_N                   "Vorwärmen PLA "
@@ -61,8 +62,10 @@
 #define MSG_COOLDOWN                        "Abkühlen"
 #define MSG_SWITCH_PS_ON                    "Netzteil Ein"
 #define MSG_SWITCH_PS_OFF                   "Netzteil Aus"
+#define MSG_EXTRUDE                         "Extrude"
 #define MSG_RETRACT                         "Retract"
 #define MSG_MOVE_AXIS                       "Bewegen"
+#define MSG_LEVEL_BED                       "Bett Korrektur"
 #define MSG_MOVE_X                          "X"
 #define MSG_MOVE_Y                          "Y"
 #define MSG_MOVE_Z                          "Z"
@@ -71,6 +74,7 @@
 #define MSG_MOVE_1MM                        " 1.0 mm"
 #define MSG_MOVE_10MM                       "10.0 mm"
 #define MSG_SPEED                           "Geschw."
+#define MSG_BED_Z                           "Bett Z"
 #define MSG_NOZZLE                          "Düse"
 #define MSG_BED                             "Bett"
 #define MSG_FAN_SPEED                       "Lüftergeschw."
@@ -99,6 +103,7 @@
 #define MSG_VTRAV_MIN                       "VTrav min"
 #define MSG_AMAX                            "A max " // space by purpose
 #define MSG_A_RETRACT                       "A Retract"
+#define MSG_A_TRAVEL                        "A Travel"
 #define MSG_XSTEPS                          "X steps/mm"
 #define MSG_YSTEPS                          "Y steps/mm"
 #define MSG_ZSTEPS                          "Z steps/mm"
@@ -146,6 +151,13 @@
 #define MSG_BABYSTEP_Y                      "Babystep Y"
 #define MSG_BABYSTEP_Z                      "Babystep Z"
 #define MSG_ENDSTOP_ABORT                   "Endstop Abbr. Ein"
+#define MSG_HEATING_FAILED_LCD              "Err: Heizt langsam"
+#define MSG_ERR_REDUNDANT_TEMP              "Err: Temp. Redundanz"
+#define MSG_THERMAL_RUNAWAY                 "Err: Temp. Messung"
+#define MSG_ERR_MAXTEMP                     "Err: Max-Temp."
+#define MSG_ERR_MINTEMP                     "Err: Min-Temp."
+#define MSG_ERR_MAXTEMP_BED                 "Err: Max-Temp. Bett"
+#define MSG_ERR_MINTEMP_BED                 "Err: Min-Temp. Bett"
 #define MSG_END_HOUR                        "Stunden"
 #define MSG_END_MINUTE                      "Minuten"
 #define MSG_HEATING                         "Aufheizen..."
@@ -163,12 +175,10 @@
 #define MSG_ERR_MAXTEMP_BED                 "Temp. Bett ueberschr."
 #define MSG_ERR_MAXTEMP_BED                 "Temp. Bett unterschr."
 
-#if ENABLED(DELTA_CALIBRATION_MENU)
-  #define MSG_DELTA_CALIBRATE               "Delta kalibrieren"
-  #define MSG_DELTA_CALIBRATE_X             "Kalibriere X"
-  #define MSG_DELTA_CALIBRATE_Y             "Kalibriere Y"
-  #define MSG_DELTA_CALIBRATE_Z             "Kalibriere Z"
-  #define MSG_DELTA_CALIBRATE_CENTER        "Kalibriere Mitte"
-#endif // DELTA_CALIBRATION_MENU
+#define MSG_DELTA_CALIBRATE                 "Delta kalibrieren"
+#define MSG_DELTA_CALIBRATE_X               "Kalibriere X"
+#define MSG_DELTA_CALIBRATE_Y               "Kalibriere Y"
+#define MSG_DELTA_CALIBRATE_Z               "Kalibriere Z"
+#define MSG_DELTA_CALIBRATE_CENTER          "Kalibriere Mitte"
 
 #endif // LANGUAGE_DE_H
diff --git a/Marlin/language_en.h b/Marlin/language_en.h
index de47f11cd85d87ad962cefe99b7727909afb6a04..dae6ea21b8d2117d17fc9d40c5fd05962eaf4372 100644
--- a/Marlin/language_en.h
+++ b/Marlin/language_en.h
@@ -70,6 +70,9 @@
 #ifndef MSG_LEVEL_BED_DONE
   #define MSG_LEVEL_BED_DONE                  "Leveling Done!"
 #endif
+#ifndef MSG_LEVEL_BED_CANCEL
+  #define MSG_LEVEL_BED_CANCEL                "Cancel"
+#endif
 #ifndef MSG_SET_HOME_OFFSETS
   #define MSG_SET_HOME_OFFSETS                "Set home offsets"
 #endif
diff --git a/Marlin/language_es.h b/Marlin/language_es.h
index c3167c3d9fc89aadb591b4609bd65309127c7a26..e91418c3fa06eb97ece6e8dd5960556a2ac80bae 100644
--- a/Marlin/language_es.h
+++ b/Marlin/language_es.h
@@ -39,32 +39,33 @@
 #define MSG_SD_INSERTED                     "Tarjeta colocada"
 #define MSG_SD_REMOVED                      "Tarjeta retirada"
 #define MSG_MAIN                            "Menu principal"
-#define MSG_AUTOSTART                       "Autostart"
+#define MSG_AUTOSTART                       "Inicio automatico"
 #define MSG_DISABLE_STEPPERS                "Apagar motores"
 #define MSG_AUTO_HOME                       "Llevar al origen"
-#define MSG_LEVEL_BED_HOMING                "Homing XYZ"
+#define MSG_LEVEL_BED_HOMING                "Origen XYZ"
 #define MSG_LEVEL_BED_WAITING               "Click to Begin"
 #define MSG_LEVEL_BED_DONE                  "Leveling Done!"
-#define MSG_SET_HOME_OFFSETS                "Ajustar offsets"
+#define MSG_LEVEL_BED_CANCEL                "Cancel"
+#define MSG_SET_HOME_OFFSETS                "Ajustar desfases"
 #define MSG_HOME_OFFSETS_APPLIED            "Offsets applied"
-#define MSG_SET_ORIGIN                      "Establecer cero"
+#define MSG_SET_ORIGIN                      "Establecer origen"
 #define MSG_PREHEAT_PLA                     "Precalentar PLA"
-#define MSG_PREHEAT_PLA_N                   "Precalentar PLA "
-#define MSG_PREHEAT_PLA_ALL                 "Precal. PLA Todo"
-#define MSG_PREHEAT_PLA_BEDONLY             "Precal. PLA Base"
-#define MSG_PREHEAT_PLA_SETTINGS            "Ajustar temp. PLA"
+#define MSG_PREHEAT_PLA_N                   MSG_PREHEAT_PLA " "
+#define MSG_PREHEAT_PLA_ALL                 MSG_PREHEAT_PLA "Todo"
+#define MSG_PREHEAT_PLA_BEDONLY             MSG_PREHEAT_PLA"Plataforma"
+#define MSG_PREHEAT_PLA_SETTINGS            MSG_PREHEAT_PLA "Config"
 #define MSG_PREHEAT_ABS                     "Precalentar ABS"
-#define MSG_PREHEAT_ABS_N                   "Precalentar ABS "
-#define MSG_PREHEAT_ABS_ALL                 "Precal. ABS Todo"
-#define MSG_PREHEAT_ABS_BEDONLY             "Precal. ABS Base"
-#define MSG_PREHEAT_ABS_SETTINGS            "Ajustar temp. ABS"
+#define MSG_PREHEAT_ABS_N                   MSG_PREHEAT_ABS " "
+#define MSG_PREHEAT_ABS_ALL                 MSG_PREHEAT_ABS "Todo"
+#define MSG_PREHEAT_ABS_BEDONLY             MSG_PREHEAT_ABS "Plataforma"
+#define MSG_PREHEAT_ABS_SETTINGS            MSG_PREHEAT_ABS "Config"
 #define MSG_COOLDOWN                        "Enfriar"
 #define MSG_SWITCH_PS_ON                    "Encender"
 #define MSG_SWITCH_PS_OFF                   "Apagar"
 #define MSG_EXTRUDE                         "Extruir"
 #define MSG_RETRACT                         "Retraer"
 #define MSG_MOVE_AXIS                       "Mover ejes"
-#define MSG_LEVEL_BED                       "Nivelar cama"
+#define MSG_LEVEL_BED                       "Nivelar plataforma"
 #define MSG_MOVE_X                          "Mover X"
 #define MSG_MOVE_Y                          "Mover Y"
 #define MSG_MOVE_Z                          "Mover Z"
@@ -73,22 +74,22 @@
 #define MSG_MOVE_1MM                        "Mover 1mm"
 #define MSG_MOVE_10MM                       "Mover 10mm"
 #define MSG_SPEED                           "Velocidad"
-#define MSG_NOZZLE                          "Fusor"
-#define MSG_BED                             "Base"
+#define MSG_NOZZLE                          "Boquilla"
+#define MSG_BED                             "Plataforma"
 #define MSG_FAN_SPEED                       "Ventilador"
 #define MSG_FLOW                            "Flujo"
 #define MSG_CONTROL                         "Control"
 #define MSG_MIN                             LCD_STR_THERMOMETER " Min"
 #define MSG_MAX                             LCD_STR_THERMOMETER " Max"
 #define MSG_FACTOR                          LCD_STR_THERMOMETER " Fact"
-#define MSG_AUTOTEMP                        "Autotemp"
-#define MSG_ON                              "On"
-#define MSG_OFF                             "Off"
+#define MSG_AUTOTEMP                        "Temperatura Automatica"
+#define MSG_ON                              "Encender"
+#define MSG_OFF                             "Apagar"
 #define MSG_PID_P                           "PID-P"
 #define MSG_PID_I                           "PID-I"
 #define MSG_PID_D                           "PID-D"
 #define MSG_PID_C                           "PID-C"
-#define MSG_ACC                             "Acel"
+#define MSG_ACC                             "Aceleracion"
 #define MSG_VXY_JERK                        "Vxy-jerk"
 #define MSG_VZ_JERK                         "Vz-jerk"
 #define MSG_VE_JERK                         "Ve-jerk"
@@ -98,9 +99,9 @@
 #define MSG_Z                               "z"
 #define MSG_E                               "e"
 #define MSG_VMIN                            "Vmin"
-#define MSG_VTRAV_MIN                       "Vvacio min"
-#define MSG_AMAX                            "Amax"
-#define MSG_A_RETRACT                       "A-retrac."
+#define MSG_VTRAV_MIN                       "Vel. viaje min"
+#define MSG_AMAX                            "Acel. max"
+#define MSG_A_RETRACT                       "Acel. retrac."
 #define MSG_XSTEPS                          "X pasos/mm"
 #define MSG_YSTEPS                          "Y pasos/mm"
 #define MSG_ZSTEPS                          "Z pasos/mm"
@@ -113,23 +114,23 @@
 #define MSG_CONTRAST                        "Contraste"
 #define MSG_STORE_EPROM                     "Guardar memoria"
 #define MSG_LOAD_EPROM                      "Cargar memoria"
-#define MSG_RESTORE_FAILSAFE                "Rest. de emergen."
+#define MSG_RESTORE_FAILSAFE                "Restaurar memoria."
 #define MSG_REFRESH                         "Volver a cargar"
 #define MSG_WATCH                           "Monitorizar"
 #define MSG_PREPARE                         "Preparar"
 #define MSG_TUNE                            "Ajustar"
 #define MSG_PAUSE_PRINT                     "Pausar impresion"
-#define MSG_RESUME_PRINT                    "Reanudar impres."
+#define MSG_RESUME_PRINT                    "Reanudar impresion"
 #define MSG_STOP_PRINT                      "Detener impresion"
 #define MSG_CARD_MENU                       "Menu de SD"
 #define MSG_NO_CARD                         "No hay tarjeta SD"
 #define MSG_DWELL                           "Reposo..."
 #define MSG_USERWAIT                        "Esperando ordenes"
 #define MSG_RESUMING                        "Resumiendo impre."
-#define MSG_PRINT_ABORTED                   "Print aborted"
+#define MSG_PRINT_ABORTED                   "Impresion cancelada"
 #define MSG_NO_MOVE                         "Sin movimiento"
-#define MSG_KILLED                          "PARADA DE EMERG."
-#define MSG_STOPPED                         "PARADA"
+#define MSG_KILLED                          "Parada de emergencia."
+#define MSG_STOPPED                         "Detenida"
 #define MSG_CONTROL_RETRACT                 "Retraer mm"
 #define MSG_CONTROL_RETRACT_SWAP            "Interc. Retraer mm"
 #define MSG_CONTROL_RETRACTF                "Retraer  V"
@@ -137,19 +138,32 @@
 #define MSG_CONTROL_RETRACT_RECOVER         "DesRet +mm"
 #define MSG_CONTROL_RETRACT_RECOVER_SWAP    "Interc. DesRet +mm"
 #define MSG_CONTROL_RETRACT_RECOVERF        "DesRet V"
-#define MSG_AUTORETRACT                     "AutoRetr."
+#define MSG_AUTORETRACT                     "Retraccion Auto."
 #define MSG_FILAMENTCHANGE                  "Cambiar filamento"
 #define MSG_INIT_SDCARD                     "Iniciando tarjeta"
 #define MSG_CNG_SDCARD                      "Cambiar tarjeta"
 #define MSG_ZPROBE_OUT                      "Sonda Z fuera"
 #define MSG_YX_UNHOMED                      "Reiniciar X/Y y Z"
-#define MSG_ZPROBE_ZOFFSET                  "Offset Z"
+#define MSG_ZPROBE_ZOFFSET                  "Desfase Z"
 #define MSG_BABYSTEP_X                      "Micropaso X"
 #define MSG_BABYSTEP_Y                      "Micropaso Y"
 #define MSG_BABYSTEP_Z                      "Micropaso Z"
 #define MSG_ENDSTOP_ABORT                   "Endstop abort"
 #define MSG_END_HOUR                        "horas"
 #define MSG_END_MINUTE                      "minutos"
+#define MSG_BED_Z                           "Plataforma Z"
+#define MSG_A_TRAVEL                        "Acel. Viaje"
+#define MSG_HEATING_FAILED_LCD              "Error: al calentar"
+#define MSG_ERR_REDUNDANT_TEMP              "Error: temperatura redundante"
+#define MSG_THERMAL_RUNAWAY                 "Error de temperatura"
+#define MSG_ERR_MAXTEMP                     "Error: Temp Maxima"
+#define MSG_ERR_MINTEMP                     "Error: Temp Minima"
+#define MSG_ERR_MAXTEMP_BED                 "Error: Temp Max Plataforma"
+#define MSG_ERR_MINTEMP_BED                 "Error: Temp Min Plataforma"
+#define MSG_HEATING                         "Calentando..."
+#define MSG_HEATING_COMPLETE                "Calentamiento Completo"
+#define MSG_BED_HEATING                     "Calentando plataforma ..."
+#define MSG_BED_DONE                        "Plataforma Caliente"
 
 #if ENABLED(DELTA_CALIBRATION_MENU)
   #define MSG_DELTA_CALIBRATE               "Calibracion Delta"
diff --git a/Marlin/language_eu.h b/Marlin/language_eu.h
index 8806ca19dafd4c74d0757e4d28d2fe801f1c596a..bc775ec105fdb792b436fed5ccf8fb7ae09fa3c5 100644
--- a/Marlin/language_eu.h
+++ b/Marlin/language_eu.h
@@ -45,6 +45,7 @@
 #define MSG_LEVEL_BED_HOMING                "Homing XYZ"
 #define MSG_LEVEL_BED_WAITING               "Click to Begin"
 #define MSG_LEVEL_BED_DONE                  "Leveling Done!"
+#define MSG_LEVEL_BED_CANCEL                "Cancel"
 #define MSG_SET_HOME_OFFSETS                "Set home offsets"
 #define MSG_HOME_OFFSETS_APPLIED            "Offsets applied"
 #define MSG_SET_ORIGIN                      "Hasiera ipini"
diff --git a/Marlin/language_fi.h b/Marlin/language_fi.h
index 3b673562c16ce0ad7f918a7a83062afd060755e9..9d550c498ef356cad300a1233bff2f7e849e35a2 100644
--- a/Marlin/language_fi.h
+++ b/Marlin/language_fi.h
@@ -45,6 +45,7 @@
 #define MSG_LEVEL_BED_HOMING                "Homing XYZ"
 #define MSG_LEVEL_BED_WAITING               "Click to Begin"
 #define MSG_LEVEL_BED_DONE                  "Leveling Done!"
+#define MSG_LEVEL_BED_CANCEL                "Cancel"
 #define MSG_SET_HOME_OFFSETS                "Set home offsets"
 #define MSG_HOME_OFFSETS_APPLIED            "Offsets applied"
 #define MSG_SET_ORIGIN                      "Aseta origo"
diff --git a/Marlin/language_fr.h b/Marlin/language_fr.h
index b4bc6545c6f58d89d95e72f8c1c897cef82749d1..3145f78a6f6129949798c04c65d8ae52ba4800c7 100644
--- a/Marlin/language_fr.h
+++ b/Marlin/language_fr.h
@@ -42,12 +42,13 @@
 #define MSG_MAIN                            "Menu principal"
 #define MSG_AUTOSTART                       "Demarrage auto"
 #define MSG_DISABLE_STEPPERS                "Arreter moteurs"
-#define MSG_AUTO_HOME                       "Home auto."
-#define MSG_LEVEL_BED_HOMING                "Homing XYZ"
-#define MSG_LEVEL_BED_WAITING               "Click to Begin"
-#define MSG_LEVEL_BED_DONE                  "Leveling Done!"
-#define MSG_SET_HOME_OFFSETS                "Set home offsets"
-#define MSG_HOME_OFFSETS_APPLIED            "Offsets applied"
+#define MSG_AUTO_HOME                       "Origine auto."
+#define MSG_LEVEL_BED_HOMING                "Origine XYZ"
+#define MSG_LEVEL_BED_WAITING               "Cliquer pour commencer"
+#define MSG_LEVEL_BED_DONE                  "Mise a niveau OK!"
+#define MSG_LEVEL_BED_CANCEL                "Annuler"
+#define MSG_SET_HOME_OFFSETS                "Regler decal. origine"
+#define MSG_HOME_OFFSETS_APPLIED            "Decalages appliques"
 #define MSG_SET_ORIGIN                      "Regler origine"
 #define MSG_PREHEAT_PLA                     "Prechauffage PLA"
 #define MSG_PREHEAT_PLA_N                   "Prechauff. PLA "
@@ -109,8 +110,8 @@
 #define MSG_TEMPERATURE                     "Temperature"
 #define MSG_MOTION                          "Mouvement"
 #define MSG_VOLUMETRIC                      "Filament"
-#define MSG_VOLUMETRIC_ENABLED              "E in mm3"
-#define MSG_FILAMENT_DIAM                   "Fil. Dia."
+#define MSG_VOLUMETRIC_ENABLED              "E en mm3"
+#define MSG_FILAMENT_DIAM                   "Diam. Fil."
 #define MSG_CONTRAST                        "Contraste LCD"
 #define MSG_STORE_EPROM                     "Sauver config"
 #define MSG_LOAD_EPROM                      "Lire config"
@@ -144,20 +145,34 @@
 #define MSG_CNG_SDCARD                      "Changer de carte"
 #define MSG_ZPROBE_OUT                      "Z sonde exte. lit"
 #define MSG_YX_UNHOMED                      "Rev. dans XY av.Z"
-#define MSG_ZPROBE_ZOFFSET                  "Offset Z"
+#define MSG_ZPROBE_ZOFFSET                  "Decalage Z"
 #define MSG_BABYSTEP_X                      "Babystep X"
 #define MSG_BABYSTEP_Y                      "Babystep Y"
 #define MSG_BABYSTEP_Z                      "Babystep Z"
 #define MSG_ENDSTOP_ABORT                   "Butee abandon"
 #define MSG_END_HOUR                        "heures"
 #define MSG_END_MINUTE                      "minutes"
+#define MSG_BED_Z                           "Plateau Z"
+#define MSG_A_TRAVEL                        "A-Depl."
+#define MSG_HEATING_FAILED_LCD              "Erreur de chauffe"
+#define MSG_ERR_REDUNDANT_TEMP              "Err: ERREUR TEMP. REDONDANTE"
+#define MSG_THERMAL_RUNAWAY                 "EMBALLEMENT THERMIQUE"
+#define MSG_ERR_MAXTEMP                     "Err: TEMP. MAX"
+#define MSG_ERR_MINTEMP                     "Err: TEMP. MIN"
+#define MSG_ERR_MAXTEMP_BED                 "Err: TEMP. MAX PLATEAU"
+#define MSG_ERR_MINTEMP_BED                 "Err: TEMP. MIN PLATEAU"
+#define MSG_HEATING                         "En chauffe..."
+#define MSG_HEATING_COMPLETE                "Chauffe terminee"
+#define MSG_BED_HEATING                     "Plateau en chauffe..."
+#define MSG_BED_DONE                        "Chauffe plateau terminee"
+
 
 #if ENABLED(DELTA_CALIBRATION_MENU)
-  #define MSG_DELTA_CALIBRATE               "Delta Calibration"
-  #define MSG_DELTA_CALIBRATE_X             "Calibrate X"
-  #define MSG_DELTA_CALIBRATE_Y             "Calibrate Y"
-  #define MSG_DELTA_CALIBRATE_Z             "Calibrate Z"
-  #define MSG_DELTA_CALIBRATE_CENTER        "Calibrate Center"
+  #define MSG_DELTA_CALIBRATE               "Calibration Delta"
+  #define MSG_DELTA_CALIBRATE_X             "Calibrer X"
+  #define MSG_DELTA_CALIBRATE_Y             "Calibrer Y"
+  #define MSG_DELTA_CALIBRATE_Z             "Calibrer Z"
+  #define MSG_DELTA_CALIBRATE_CENTER        "Calibrer centre"
 #endif // DELTA_CALIBRATION_MENU
 
 #endif // LANGUAGE_FR_H
diff --git a/Marlin/language_it.h b/Marlin/language_it.h
index f88a68be668c257f0286b206736997ad398076dc..0c849d0db9b8fdb4628a0743abe0caee76f928fa 100644
--- a/Marlin/language_it.h
+++ b/Marlin/language_it.h
@@ -42,29 +42,30 @@
 #define MSG_AUTOSTART                       "Autostart"
 #define MSG_DISABLE_STEPPERS                "Disabilita Motori"
 #define MSG_AUTO_HOME                       "Auto Home"
-#define MSG_LEVEL_BED_HOMING                "Homing XYZ"
-#define MSG_LEVEL_BED_WAITING               "Click to Begin"
-#define MSG_LEVEL_BED_DONE                  "Leveling Done!"
-#define MSG_SET_HOME_OFFSETS                "Setta offset home"
-#define MSG_HOME_OFFSETS_APPLIED            "Offsets applied"
+#define MSG_LEVEL_BED_HOMING                "Home assi XYZ"
+#define MSG_LEVEL_BED_WAITING               "Premi per Iniziare"
+#define MSG_LEVEL_BED_DONE                  "Livel. terminato!"
+#define MSG_LEVEL_BED_CANCEL                "Annulla"
+#define MSG_SET_HOME_OFFSETS                "Imp. offset home"
+#define MSG_HOME_OFFSETS_APPLIED            "Offset applicato"
 #define MSG_SET_ORIGIN                      "Imposta Origine"
 #define MSG_PREHEAT_PLA                     "Preriscalda PLA"
-#define MSG_PREHEAT_PLA_N                   "Preriscalda PLA "
-#define MSG_PREHEAT_PLA_ALL                 "Prer. PLA Tutto"
-#define MSG_PREHEAT_PLA_BEDONLY             "Prer. PLA Piatto"
-#define MSG_PREHEAT_PLA_SETTINGS            "Config. prer. PLA"
+#define MSG_PREHEAT_PLA_N                   MSG_PREHEAT_PLA " "
+#define MSG_PREHEAT_PLA_ALL                 MSG_PREHEAT_PLA " Tutto"
+#define MSG_PREHEAT_PLA_BEDONLY             MSG_PREHEAT_PLA " Piatto"
+#define MSG_PREHEAT_PLA_SETTINGS            MSG_PREHEAT_PLA " conf"
 #define MSG_PREHEAT_ABS                     "Preriscalda ABS"
-#define MSG_PREHEAT_ABS_N                   "Preriscalda ABS "
-#define MSG_PREHEAT_ABS_ALL                 "Prer. ABS Tutto"
-#define MSG_PREHEAT_ABS_BEDONLY             "Prer. ABS Piatto"
-#define MSG_PREHEAT_ABS_SETTINGS            "Config. prer. ABS"
+#define MSG_PREHEAT_ABS_N                   MSG_PREHEAT_ABS " "
+#define MSG_PREHEAT_ABS_ALL                 MSG_PREHEAT_ABS " Tutto"
+#define MSG_PREHEAT_ABS_BEDONLY             MSG_PREHEAT_ABS " Piatto"
+#define MSG_PREHEAT_ABS_SETTINGS            MSG_PREHEAT_ABS " conf"
 #define MSG_COOLDOWN                        "Raffredda"
 #define MSG_SWITCH_PS_ON                    "Accendi aliment."
 #define MSG_SWITCH_PS_OFF                   "Spegni aliment."
 #define MSG_EXTRUDE                         "Estrudi"
 #define MSG_RETRACT                         "Ritrai"
 #define MSG_MOVE_AXIS                       "Muovi Asse"
-#define MSG_LEVEL_BED                       "Livellamento piano"
+#define MSG_LEVEL_BED                       "Livella piano"
 #define MSG_MOVE_X                          "Muovi X"
 #define MSG_MOVE_Y                          "Muovi Y"
 #define MSG_MOVE_Z                          "Muovi Z"
@@ -72,34 +73,34 @@
 #define MSG_MOVE_01MM                       "Muovi di 0.1mm"
 #define MSG_MOVE_1MM                        "Muovi di   1mm"
 #define MSG_MOVE_10MM                       "Muovi di  10mm"
-#define MSG_SPEED                           "Velcità"
+#define MSG_SPEED                           "Velocità"
 #define MSG_NOZZLE                          "Ugello"
 #define MSG_BED                             "Piatto"
-#define MSG_FAN_SPEED                       "Ventola"
+#define MSG_FAN_SPEED                       "Velocità ventola"
 #define MSG_FLOW                            "Flusso"
 #define MSG_CONTROL                         "Controllo"
 #define MSG_MIN                             LCD_STR_THERMOMETER " Min"
 #define MSG_MAX                             LCD_STR_THERMOMETER " Max"
 #define MSG_FACTOR                          LCD_STR_THERMOMETER " Fact"
 #define MSG_AUTOTEMP                        "Autotemp"
-#define MSG_ON                              "ON "
-#define MSG_OFF                             "OFF"
+#define MSG_ON                              "On "
+#define MSG_OFF                             "Off"
 #define MSG_PID_P                           "PID-P"
 #define MSG_PID_I                           "PID-I"
 #define MSG_PID_D                           "PID-D"
 #define MSG_PID_C                           "PID-C"
-#define MSG_ACC                             "Accel."
+#define MSG_ACC                             "Accel"
 #define MSG_VXY_JERK                        "Vxy-jerk"
 #define MSG_VZ_JERK                         "Vz-jerk"
 #define MSG_VE_JERK                         "Ve-jerk"
-#define MSG_VMAX                            "Vmax"
+#define MSG_VMAX                            "Vmax "
 #define MSG_X                               "x"
 #define MSG_Y                               "y"
 #define MSG_Z                               "z"
 #define MSG_E                               "e"
 #define MSG_VMIN                            "Vmin"
 #define MSG_VTRAV_MIN                       "VTrav min"
-#define MSG_AMAX                            "Amax"
+#define MSG_AMAX                            "Amax "
 #define MSG_A_RETRACT                       "A-retract"
 #define MSG_XSTEPS                          "Xpassi/mm"
 #define MSG_YSTEPS                          "Ypassi/mm"
@@ -107,42 +108,42 @@
 #define MSG_ESTEPS                          "Epassi/mm"
 #define MSG_TEMPERATURE                     "Temperatura"
 #define MSG_MOTION                          "Movimento"
-#define MSG_VOLUMETRIC                      "Filament"
-#define MSG_VOLUMETRIC_ENABLED              "E in mm³"
+#define MSG_VOLUMETRIC                      "Filamento"
+#define MSG_VOLUMETRIC_ENABLED              "E in mm3"
 #define MSG_FILAMENT_DIAM                   "Diam. filo"
 #define MSG_CONTRAST                        "Contrasto LCD"
-#define MSG_STORE_EPROM                     "Salva in EEPROM"
-#define MSG_LOAD_EPROM                      "Carica da EEPROM"
-#define MSG_RESTORE_FAILSAFE                "Impostaz. default"
+#define MSG_STORE_EPROM                     "Salva in memoria"
+#define MSG_LOAD_EPROM                      "Carica da memoria"
+#define MSG_RESTORE_FAILSAFE                "Ripristina imp."
 #define MSG_REFRESH                         "Aggiorna"
 #define MSG_WATCH                           "Guarda"
 #define MSG_PREPARE                         "Prepara"
-#define MSG_TUNE                            "Adatta"
+#define MSG_TUNE                            "Regola"
 #define MSG_PAUSE_PRINT                     "Pausa"
 #define MSG_RESUME_PRINT                    "Riprendi stampa"
 #define MSG_STOP_PRINT                      "Arresta stampa"
-#define MSG_CARD_MENU                       "SD Card Menu"
-#define MSG_NO_CARD                         "No SD Card"
+#define MSG_CARD_MENU                       "Stampa da SD"
+#define MSG_NO_CARD                         "SD non presente"
 #define MSG_DWELL                           "Sospensione..."
-#define MSG_USERWAIT                        "Attendi Utente..."
+#define MSG_USERWAIT                        "Attendi Utente.."
 #define MSG_RESUMING                        "Riprendi Stampa"
-#define MSG_PRINT_ABORTED                   "Stampa abortita"
+#define MSG_PRINT_ABORTED                   "Stampa annullata"
 #define MSG_NO_MOVE                         "Nessun Movimento"
-#define MSG_KILLED                          "UCCISO "
-#define MSG_STOPPED                         "ARRESTATO "
+#define MSG_KILLED                          "UCCISO. "
+#define MSG_STOPPED                         "ARRESTATO. "
 #define MSG_CONTROL_RETRACT                 "Ritrai mm"
 #define MSG_CONTROL_RETRACT_SWAP            "Scamb. Ritrai mm"
 #define MSG_CONTROL_RETRACTF                "Ritrai  V"
 #define MSG_CONTROL_RETRACT_ZLIFT           "Salta mm"
 #define MSG_CONTROL_RETRACT_RECOVER         "UnRet +mm"
-#define MSG_CONTROL_RETRACT_RECOVER_SWAP    "Scamb. UnRet +mm"
+#define MSG_CONTROL_RETRACT_RECOVER_SWAP    "Scamb. UnRet+mm"
 #define MSG_CONTROL_RETRACT_RECOVERF        "UnRet  V"
-#define MSG_AUTORETRACT                     "AutoArretramento"
+#define MSG_AUTORETRACT                     "AutoRitrai"
 #define MSG_FILAMENTCHANGE                  "Cambia filamento"
 #define MSG_INIT_SDCARD                     "Iniz. SD-Card"
 #define MSG_CNG_SDCARD                      "Cambia SD-Card"
 #define MSG_ZPROBE_OUT                      "Z probe out. bed"
-#define MSG_YX_UNHOMED                      "Home X/Y before Z"
+#define MSG_YX_UNHOMED                      "Home X/Y prima di Z"
 #define MSG_ZPROBE_ZOFFSET                  "Z Offset"
 #define MSG_BABYSTEP_X                      "Babystep X"
 #define MSG_BABYSTEP_Y                      "Babystep Y"
@@ -150,6 +151,20 @@
 #define MSG_ENDSTOP_ABORT                   "Finecorsa abort"
 #define MSG_END_HOUR                        "ore"
 #define MSG_END_MINUTE                      "minuti"
+#define MSG_BED_Z                           "piatto Z"
+#define MSG_A_TRAVEL                        "A-Spostamento"
+#define MSG_HEATING_FAILED_LCD              "Riscald. Fallito"
+#define MSG_ERR_REDUNDANT_TEMP              "Err: TEMP RIDONDANTI"
+#define MSG_THERMAL_RUNAWAY                 "TEMP FUORI CONTROLLO"
+#define MSG_ERR_MAXTEMP                     "Err: TEMP MASSIMA"
+#define MSG_ERR_MINTEMP                     "Err: TEMP MINIMA"
+#define MSG_ERR_MAXTEMP_BED                 "Err: TEMP MASSIMA PIATTO"
+#define MSG_ERR_MINTEMP_BED                 "Err: TEMP MINIMA PIATTO"
+#define MSG_HEATING                         "Riscaldamento.."
+#define MSG_HEATING_COMPLETE                "Risc. completato"
+#define MSG_BED_HEATING                     "Risc. Piatto.."
+#define MSG_BED_DONE                        "Piatto Pronto"
+
 
 #if ENABLED(DELTA_CALIBRATION_MENU)
   #define MSG_DELTA_CALIBRATE               "Calibraz. Delta"
diff --git a/Marlin/language_kana.h b/Marlin/language_kana.h
index 78668642656f7364d2f1c630b9dbd189dd14556c..6c810195adc1bd10a9cc4e70733e2563c435e28a 100644
--- a/Marlin/language_kana.h
+++ b/Marlin/language_kana.h
@@ -45,10 +45,11 @@
 #define MSG_DISABLE_STEPPERS                "\xd3\xb0\xc0\xb0\xc3\xde\xdd\xb9\xde\xdd\x20\xb5\xcc"         // "Disable steppers"
 #define MSG_AUTO_HOME                       "\xb9\xde\xdd\xc3\xdd\xc6\xb2\xc4\xde\xb3"                     // "Auto home"
 #define MSG_LEVEL_BED_HOMING                "\xb9\xde\xdd\xc3\xdd\xc6\xb2\xc4\xde\xb3"                     // "Homing XYZ"
-#define MSG_LEVEL_BED_WAITING               "Click to Begin"
-#define MSG_LEVEL_BED_DONE                  "Leveling Done!"
+#define MSG_LEVEL_BED_WAITING               "\xda\xcd\xde\xd8\xdd\xb8\xde\xb6\xb2\xbc"                     //"Click to Begin"
+#define MSG_LEVEL_BED_DONE                  "\xda\xcd\xde\xd8\xdd\xb8\xde\xb6\xdd\xd8\xae\xb3"             //"Leveling Done!"
+#define MSG_LEVEL_BED_CANCEL                "\xc4\xd8\xd4\xd2"                                             //"Cancel"
 #define MSG_SET_HOME_OFFSETS                "\xb7\xbc\xde\xad\xdd\xb5\xcc\xbe\xaf\xc4\xbe\xaf\xc3\xb2"     // "Set home offsets"
-#define MSG_HOME_OFFSETS_APPLIED            "Offsets applied"
+#define MSG_HOME_OFFSETS_APPLIED            "\xb5\xcc\xbe\xaf\xc4\x20\xc3\xb7\xd6\xb3\xbb\xda\xcf\xbc\xc0" //"Offsets applied"
 #define MSG_SET_ORIGIN                      "\xb7\xbc\xde\xad\xdd\xbe\xaf\xc4"                             // "Set origin"
 #define MSG_PREHEAT_PLA                     "PLA \xd6\xc8\xc2"                                             // "Preheat PLA"
 #define MSG_PREHEAT_PLA_N                   MSG_PREHEAT_PLA " "
diff --git a/Marlin/language_kana_utf8.h b/Marlin/language_kana_utf8.h
index 59347a87354529cfad622d2e929491a45a45e53d..da420a5bdb0c3dd00c45aab73cc4d4912d9b2bbe 100644
--- a/Marlin/language_kana_utf8.h
+++ b/Marlin/language_kana_utf8.h
@@ -49,10 +49,11 @@
 #define MSG_DISABLE_STEPPERS                "モーターデンゲン オフ"            // "Disable steppers"
 #define MSG_AUTO_HOME                       "ゲンテンニイドウ"                // "Auto home"
 #define MSG_LEVEL_BED_HOMING                "ゲンテンニイドウ"                // "Homing XYZ"
-#define MSG_LEVEL_BED_WAITING               "Click to Begin"
-#define MSG_LEVEL_BED_DONE                  "Leveling Done!"
+#define MSG_LEVEL_BED_WAITING               "レベリングカイシ"                //"Click to Begin"
+#define MSG_LEVEL_BED_DONE                  "レベリングカンリョウ"              //"Leveling Done!"
+#define MSG_LEVEL_BED_CANCEL                "トリヤメ"                      //"Cancel"
 #define MSG_SET_HOME_OFFSETS                "キジュンオフセットセッテイ"         // "Set home offsets"
-#define MSG_HOME_OFFSETS_APPLIED            "Offsets applied"
+#define MSG_HOME_OFFSETS_APPLIED            "オフセット テキヨウサレマシタ"       //"Offsets applied"
 #define MSG_SET_ORIGIN                      "キジュンセット"                 // "Set origin"
 #define MSG_PREHEAT_PLA                     "PLA ヨネツ"                   // "Preheat PLA"
 #define MSG_PREHEAT_PLA_N                   MSG_PREHEAT_PLA " "
diff --git a/Marlin/language_nl.h b/Marlin/language_nl.h
index a0c20aaef250861fb1dcde0fb4a04f591a813ad3..4ccc7f094f62ff3b96eac344750ebca8e74c9fac 100644
--- a/Marlin/language_nl.h
+++ b/Marlin/language_nl.h
@@ -38,14 +38,15 @@
 #define WELCOME_MSG                         MACHINE_NAME " gereed."
 #define MSG_SD_INSERTED                     "Kaart ingestoken"
 #define MSG_SD_REMOVED                      "Kaart verwijderd"
-#define MSG_MAIN                            "Main"
+#define MSG_MAIN                            "Hoofdmenu"
 #define MSG_AUTOSTART                       "Autostart"
 #define MSG_DISABLE_STEPPERS                "Motoren uit"
 #define MSG_AUTO_HOME                       "Auto home"
 #define MSG_LEVEL_BED_HOMING                "Homing XYZ"
 #define MSG_LEVEL_BED_WAITING               "Click to Begin"
 #define MSG_LEVEL_BED_DONE                  "Leveling Done!"
-#define MSG_SET_HOME_OFFSETS                "Set home offsets"
+#define MSG_LEVEL_BED_CANCEL                "Cancel"
+#define MSG_SET_HOME_OFFSETS                "Zet home offsets"
 #define MSG_HOME_OFFSETS_APPLIED            "Offsets applied"
 #define MSG_SET_ORIGIN                      "Nulpunt instellen"
 #define MSG_PREHEAT_PLA                     "PLA voorverwarmen"
@@ -127,8 +128,8 @@
 #define MSG_RESUMING                        "Print hervatten"
 #define MSG_PRINT_ABORTED                   "Print afgebroken"
 #define MSG_NO_MOVE                         "Geen beweging."
-#define MSG_KILLED                          "AFGEBROKEN. "
-#define MSG_STOPPED                         "GESTOPT. "
+#define MSG_KILLED                          "Afgebroken. "
+#define MSG_STOPPED                         "Gestopt. "
 #define MSG_CONTROL_RETRACT                 "Retract mm"
 #define MSG_CONTROL_RETRACT_SWAP            "Ruil Retract mm"
 #define MSG_CONTROL_RETRACTF                "Retract  F"
@@ -139,7 +140,7 @@
 #define MSG_AUTORETRACT                     "AutoRetr."
 #define MSG_FILAMENTCHANGE                  "Verv. Filament"
 #define MSG_INIT_SDCARD                     "Init. SD kaart"
-#define MSG_CNG_SDCARD                      "Verv. SD card"
+#define MSG_CNG_SDCARD                      "Verv. SD Kaart"
 #define MSG_ZPROBE_OUT                      "Z probe uit. bed"
 #define MSG_YX_UNHOMED                      "Home X/Y voor Z"
 #define MSG_ZPROBE_ZOFFSET                  "Z Offset"
@@ -149,6 +150,24 @@
 #define MSG_ENDSTOP_ABORT                   "Endstop afbr."
 #define MSG_END_HOUR                        "uur"
 #define MSG_END_MINUTE                      "minuten"
+#define MSG_BED_Z                           "Bed Z"
+#define MSG_A_TRAVEL                        "A-travel"
+#define MSG_HEATING_FAILED_LCD              "voorverw. fout"
+#define MSG_ERR_REDUNDANT_TEMP              "Redun. temp fout"
+#define MSG_THERMAL_RUNAWAY                 "Therm. wegloop"
+#define MSG_ERR_MAXTEMP                     "Err: Max. temp"
+#define MSG_ERR_MINTEMP                     "Err: Min. temp"
+#define MSG_ERR_MAXTEMP_BED                 "Err: Max.tmp bed"
+#define MSG_ERR_MINTEMP_BED                 "Err: Min.tmp bed"
+#define MSG_HEATING                         "Voorwarmen..."
+#define MSG_HEATING_COMPLETE                "Voorverw. kompl."
+#define MSG_BED_HEATING                     "Bed voorverw."
+#define MSG_BED_DONE                        "Bed is voorverw."
+#define MSG_LEVEL_BED_HOMING                "Homing XYZ"
+#define MSG_LEVEL_BED_WAITING               "Klik voor begin"
+#define MSG_LEVEL_BED_DONE                  "Bed level kompl."
+#define MSG_LEVEL_BED_CANCEL                "Bed level afbr."
+#define MSG_HOME_OFFSETS_APPLIED            "H offset toegep."
 
 #if ENABLED(DELTA_CALIBRATION_MENU)
   #define MSG_DELTA_CALIBRATE               "Delta Calibratie"
diff --git a/Marlin/language_pl.h b/Marlin/language_pl.h
index 720e1b28030ad26bc80d62d0ed50dd7f3c4186bc..541774850842a70dea19a49919ccf43e7c33f1b9 100644
--- a/Marlin/language_pl.h
+++ b/Marlin/language_pl.h
@@ -45,6 +45,7 @@
 #define MSG_LEVEL_BED_HOMING                "Homing XYZ"
 #define MSG_LEVEL_BED_WAITING               "Click to Begin"
 #define MSG_LEVEL_BED_DONE                  "Leveling Done!"
+#define MSG_LEVEL_BED_CANCEL                "Cancel"
 #define MSG_SET_HOME_OFFSETS                "Set home offsets"
 #define MSG_HOME_OFFSETS_APPLIED            "Offsets applied"
 #define MSG_SET_ORIGIN                      "Ustaw punkt zero"
diff --git a/Marlin/language_pt-br.h b/Marlin/language_pt-br.h
index b8c24baaf75cc1973b996e4f501cbeaf08cdc9c0..38f23d0da6bb298eeabd74eb1a68ac0a69ecd596 100644
--- a/Marlin/language_pt-br.h
+++ b/Marlin/language_pt-br.h
@@ -45,6 +45,7 @@
 #define MSG_LEVEL_BED_HOMING                "Homing XYZ"
 #define MSG_LEVEL_BED_WAITING               "Click to Begin"
 #define MSG_LEVEL_BED_DONE                  "Leveling Done!"
+#define MSG_LEVEL_BED_CANCEL                "Cancel"
 #define MSG_SET_HOME_OFFSETS                "Ajustar Jogo"
 #define MSG_HOME_OFFSETS_APPLIED            "Offsets applied"
 #define MSG_SET_ORIGIN                      "Ajustar orig."
diff --git a/Marlin/language_pt-br_utf8.h b/Marlin/language_pt-br_utf8.h
index b104b76408c0d753491b487eeb951ce77f7556b9..ea92ab15a9a67f47ae17ceb2d9c53859aaa885ed 100644
--- a/Marlin/language_pt-br_utf8.h
+++ b/Marlin/language_pt-br_utf8.h
@@ -45,6 +45,7 @@
 #define MSG_LEVEL_BED_HOMING                "Indo para origem"
 #define MSG_LEVEL_BED_WAITING               "Click to Begin"
 #define MSG_LEVEL_BED_DONE                  "Leveling Done!"
+#define MSG_LEVEL_BED_CANCEL                "Cancel"
 #define MSG_SET_HOME_OFFSETS                "Ajustar Jogo"
 #define MSG_HOME_OFFSETS_APPLIED            "Offsets applied"
 #define MSG_SET_ORIGIN                      "Ajustar orig."
diff --git a/Marlin/language_pt.h b/Marlin/language_pt.h
index 367d0b764755a165c7f1e584020384f72c864d28..07bbd9dbb8b70569c5648a3ccd8ce48fc8957e98 100644
--- a/Marlin/language_pt.h
+++ b/Marlin/language_pt.h
@@ -45,6 +45,7 @@
 #define MSG_LEVEL_BED_HOMING                "Indo para origem"
 #define MSG_LEVEL_BED_WAITING               "Click to Begin"
 #define MSG_LEVEL_BED_DONE                  "Leveling Done!"
+#define MSG_LEVEL_BED_CANCEL                "Cancel"
 #define MSG_SET_HOME_OFFSETS                "Definir desvio"
 #define MSG_HOME_OFFSETS_APPLIED            "Offsets applied"
 #define MSG_SET_ORIGIN                      "Definir origem"
@@ -72,6 +73,7 @@
 #define MSG_MOVE_1MM                        "Mover 1mm"
 #define MSG_MOVE_10MM                       "Mover 10mm"
 #define MSG_SPEED                           "Velocidade"
+#define MSG_BED_Z                           "Base Z"
 #define MSG_NOZZLE                          LCD_STR_THERMOMETER " Bico"
 #define MSG_BED                             LCD_STR_THERMOMETER " Base"
 #define MSG_FAN_SPEED                       "Vel. ventoinha"
@@ -103,7 +105,8 @@
 #define MSG_VMIN                            "Vmin"
 #define MSG_VTRAV_MIN                       "VTrav min"
 #define MSG_AMAX                            "Amax "
-#define MSG_A_RETRACT                       "A-retract"
+#define MSG_A_RETRACT                       "A-retraccao"
+#define MSG_A_TRAVEL                        "A-movimento"
 #define MSG_XSTEPS                          "X passo/mm"
 #define MSG_YSTEPS                          "Y passo/mm"
 #define MSG_ZSTEPS                          "Z passo/mm"
@@ -151,8 +154,19 @@
 #define MSG_BABYSTEP_Y                      "Babystep Y"
 #define MSG_BABYSTEP_Z                      "Babystep Z"
 #define MSG_ENDSTOP_ABORT                   "Fim de curso"
+#define MSG_HEATING_FAILED_LCD              "Aquecimento falhou"
+#define MSG_ERR_REDUNDANT_TEMP              "Err: REDUNDANT TEMP ERROR"
+#define MSG_THERMAL_RUNAWAY                 "THERMAL RUNAWAY"
+#define MSG_ERR_MAXTEMP                     "Err: T Maxima"
+#define MSG_ERR_MINTEMP                     "Err: T Minima"
+#define MSG_ERR_MAXTEMP_BED                 "Err: T Base Maxima"
+#define MSG_ERR_MINTEMP_BED                 "Err: T Base Minima"
 #define MSG_END_HOUR                        "horas"
 #define MSG_END_MINUTE                      "minutos"
+#define MSG_HEATING                         "Aquecendo..."
+#define MSG_HEATING_COMPLETE                "Aquecida."
+#define MSG_BED_HEATING                     "Aquecendo base.."
+#define MSG_BED_DONE                        "Base aquecida."
 
 #if ENABLED(DELTA_CALIBRATION_MENU)
   #define MSG_DELTA_CALIBRATE             "Calibracao Delta"
diff --git a/Marlin/language_pt_utf8.h b/Marlin/language_pt_utf8.h
index 0df5744147411b0c7c174541c8d3ecc4e9304a9a..c20069cf39f7e25286d82f5b35aa351e41bf5734 100644
--- a/Marlin/language_pt_utf8.h
+++ b/Marlin/language_pt_utf8.h
@@ -45,6 +45,7 @@
 #define MSG_LEVEL_BED_HOMING                "Indo para origem"
 #define MSG_LEVEL_BED_WAITING               "Click to Begin"
 #define MSG_LEVEL_BED_DONE                  "Leveling Done!"
+#define MSG_LEVEL_BED_CANCEL                "Cancel"
 #define MSG_SET_HOME_OFFSETS                "Definir desvio"
 #define MSG_HOME_OFFSETS_APPLIED            "Offsets applied"
 #define MSG_SET_ORIGIN                      "Definir origem"
@@ -72,6 +73,7 @@
 #define MSG_MOVE_1MM                        "Mover 1mm"
 #define MSG_MOVE_10MM                       "Mover 10mm"
 #define MSG_SPEED                           "Velocidade"
+#define MSG_BED_Z                           "Base Z"
 #define MSG_NOZZLE                          LCD_STR_THERMOMETER " Bico"
 #define MSG_BED                             LCD_STR_THERMOMETER " Base"
 #define MSG_FAN_SPEED                       "Vel. ventoinha"
@@ -103,7 +105,8 @@
 #define MSG_VMIN                            "Vmin"
 #define MSG_VTRAV_MIN                       "VTrav min"
 #define MSG_AMAX                            "Amax "
-#define MSG_A_RETRACT                       "A-retract"
+#define MSG_A_RETRACT                       "A-retracção"
+#define MSG_A_TRAVEL                        "A-movimento"
 #define MSG_XSTEPS                          "X passo/mm"
 #define MSG_YSTEPS                          "Y passo/mm"
 #define MSG_ZSTEPS                          "Z passo/mm"
@@ -127,7 +130,7 @@
 #define MSG_CARD_MENU                       "Imprimir do SD"
 #define MSG_NO_CARD                         "Sem cartão SD"
 #define MSG_DWELL                           "Em espera..."
-#define MSG_USERWAIT                        "A espera de ordem"
+#define MSG_USERWAIT                        "Á espera de ordem"
 #define MSG_RESUMING                        "Retomando impressão"
 #define MSG_PRINT_ABORTED                   "Impressão cancelada"
 #define MSG_NO_MOVE                         "Sem movimento"
@@ -151,8 +154,19 @@
 #define MSG_BABYSTEP_Y                      "Babystep Y"
 #define MSG_BABYSTEP_Z                      "Babystep Z"
 #define MSG_ENDSTOP_ABORT                   "Fim de curso"
+#define MSG_HEATING_FAILED_LCD              "Aquecimento falhou"
+#define MSG_ERR_REDUNDANT_TEMP              "Err: REDUNDANT TEMP ERROR"
+#define MSG_THERMAL_RUNAWAY                 "THERMAL RUNAWAY"
+#define MSG_ERR_MAXTEMP                     "Err: T Máxima"
+#define MSG_ERR_MINTEMP                     "Err: T Mínima"
+#define MSG_ERR_MAXTEMP_BED                 "Err: T Base Máxima"
+#define MSG_ERR_MINTEMP_BED                 "Err: T Base Mínima"
 #define MSG_END_HOUR                        "horas"
 #define MSG_END_MINUTE                      "minutos"
+#define MSG_HEATING                         "Aquecendo..."
+#define MSG_HEATING_COMPLETE                "Aquecida."
+#define MSG_BED_HEATING                     "Aquecendo base.."
+#define MSG_BED_DONE                        "Base aquecida."
 
 #if ENABLED(DELTA_CALIBRATION_MENU)
   #define MSG_DELTA_CALIBRATE             "Calibração Delta"
diff --git a/Marlin/language_ru.h b/Marlin/language_ru.h
index b5f004908ec53f2893e541c643928c253e0f6706..c23de9b82cc2ef9ef902407928b67840c328c87d 100644
--- a/Marlin/language_ru.h
+++ b/Marlin/language_ru.h
@@ -45,6 +45,7 @@
 #define MSG_LEVEL_BED_HOMING                "Homing XYZ"
 #define MSG_LEVEL_BED_WAITING               "Click to Begin"
 #define MSG_LEVEL_BED_DONE                  "Leveling Done!"
+#define MSG_LEVEL_BED_CANCEL                "Cancel"
 #define MSG_SET_HOME_OFFSETS                "Запомнить парковку"
 #define MSG_HOME_OFFSETS_APPLIED            "Offsets applied"
 #define MSG_SET_ORIGIN                      "Запомнить ноль"
diff --git a/Marlin/macros.h b/Marlin/macros.h
index 4fce8eb539a55130fb9565501ef7b4cc34686e7f..be5e8cf2cfd6721edcef48ae66fd95a61b0309b7 100644
--- a/Marlin/macros.h
+++ b/Marlin/macros.h
@@ -24,8 +24,8 @@
 #define MACROS_H
 
 // Macros to make a string from a macro
-#define STRINGIFY_(n) #n
-#define STRINGIFY(n) STRINGIFY_(n)
+#define STRINGIFY_(M) #M
+#define STRINGIFY(M) STRINGIFY_(M)
 
 // Macros for bit masks
 #define TEST(n,b) (((n)&_BV(b))!=0)
diff --git a/Marlin/pins.h b/Marlin/pins.h
index 4afa2b6160c4ce581fa04536c7e0960e1d753df5..eb37f87af92b0d93d61c495abf0eb62ad02c63ec 100644
--- a/Marlin/pins.h
+++ b/Marlin/pins.h
@@ -209,55 +209,37 @@
   #endif
 #endif
 
-#if ENABLED(DISABLE_MAX_ENDSTOPS)
-  #undef X_MAX_PIN
-  #undef Y_MAX_PIN
-  #undef Z_MAX_PIN
-  #define X_MAX_PIN          -1
-  #define Y_MAX_PIN          -1
-  #define Z_MAX_PIN          -1
-#endif
-
-#if ENABLED(DISABLE_MIN_ENDSTOPS)
-  #undef X_MIN_PIN
-  #undef Y_MIN_PIN
-  #undef Z_MIN_PIN
-  #define X_MIN_PIN          -1
-  #define Y_MIN_PIN          -1
-  #define Z_MIN_PIN          -1
-#endif
-
 #if ENABLED(DISABLE_Z_MIN_PROBE_ENDSTOP) || DISABLED(Z_MIN_PROBE_ENDSTOP) // Allow code to compile regardless of Z_MIN_PROBE_ENDSTOP setting.
   #undef Z_MIN_PROBE_PIN
   #define Z_MIN_PROBE_PIN    -1
 #endif
 
-#if ENABLED(DISABLE_XMAX_ENDSTOP)
+#if DISABLED(USE_XMAX_PLUG)
   #undef X_MAX_PIN
   #define X_MAX_PIN          -1
 #endif
 
-#if ENABLED(DISABLE_XMIN_ENDSTOP)
-  #undef X_MIN_PIN
-  #define X_MIN_PIN          -1
-#endif
-
-#if ENABLED(DISABLE_YMAX_ENDSTOP)
+#if DISABLED(USE_YMAX_PLUG)
   #undef Y_MAX_PIN
   #define Y_MAX_PIN          -1
 #endif
 
-#if ENABLED(DISABLE_YMIN_ENDSTOP)
-  #undef Y_MIN_PIN
-  #define Y_MIN_PIN          -1
-#endif
-
-#if ENABLED(DISABLE_ZMAX_ENDSTOP)
+#if DISABLED(USE_ZMAX_PLUG)
   #undef Z_MAX_PIN
   #define Z_MAX_PIN          -1
 #endif
 
-#if ENABLED(DISABLE_ZMIN_ENDSTOP)
+#if DISABLED(USE_XMIN_PLUG)
+  #undef X_MIN_PIN
+  #define X_MIN_PIN          -1
+#endif
+
+#if DISABLED(USE_YMIN_PLUG)
+  #undef Y_MIN_PIN
+  #define Y_MIN_PIN          -1
+#endif
+
+#if DISABLED(USE_ZMIN_PLUG)
   #undef Z_MIN_PIN
   #define Z_MIN_PIN          -1
 #endif
diff --git a/Marlin/pins_FELIX2.h b/Marlin/pins_FELIX2.h
index 79d8332ada16a1ac78ffd0fa3800820e19925ed7..e5aa87922bb20d07acfa89e32f44b4ef41572b2a 100644
--- a/Marlin/pins_FELIX2.h
+++ b/Marlin/pins_FELIX2.h
@@ -29,8 +29,6 @@
 #undef HEATER_1_PIN
 #define HEATER_1_PIN        7 // EXTRUDER 2
 
-#define DISABLE_MAX_ENDSTOPS
-
 #undef SDPOWER
 #define SDPOWER             1
 
diff --git a/Marlin/pins_MEGATRONICS_3.h b/Marlin/pins_MEGATRONICS_3.h
index c60f3c6339e9e522bf99f7e05c1c2a2854fb9ebd..46f98807b29e27d6d20b614eef64798ab7d63832 100644
--- a/Marlin/pins_MEGATRONICS_3.h
+++ b/Marlin/pins_MEGATRONICS_3.h
@@ -39,7 +39,7 @@
 #define SERVO0_PIN         46 //AUX3-6
 #define SERVO1_PIN         47 //AUX3-5
 #define SERVO2_PIN         48 //AUX3-4
-#define SERVO2_PIN         49 //AUX3-3
+#define SERVO3_PIN         49 //AUX3-3
 
 #define X_STEP_PIN         58
 #define X_DIR_PIN          57
diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp
index ed3aa78a9379a68f317c79c047e54ec389a238da..318b5bdb2833c3bc70789bdd5ffb49aaa06c17fb 100644
--- a/Marlin/planner.cpp
+++ b/Marlin/planner.cpp
@@ -852,25 +852,34 @@ float junction_deviation = 0.1;
   block->nominal_rate = ceil(block->step_event_count * inverse_second); // (step/sec) Always > 0
 
   #if ENABLED(FILAMENT_WIDTH_SENSOR)
+    static float filwidth_e_count = 0, filwidth_delay_dist = 0;
+
     //FMM update ring buffer used for delay with filament measurements
-    if (extruder == FILAMENT_SENSOR_EXTRUDER_NUM && delay_index2 > -1) {  //only for extruder with filament sensor and if ring buffer is initialized
+    if (extruder == FILAMENT_SENSOR_EXTRUDER_NUM && filwidth_delay_index2 >= 0) {  //only for extruder with filament sensor and if ring buffer is initialized
+
+      const int MMD_CM = MAX_MEASUREMENT_DELAY + 1, MMD_MM = MMD_CM * 10;
+
+      // increment counters with next move in e axis
+      filwidth_e_count += delta_mm[E_AXIS];
+      filwidth_delay_dist += delta_mm[E_AXIS];
 
-      const int MMD = MAX_MEASUREMENT_DELAY + 1, MMD10 = MMD * 10;
+      // Only get new measurements on forward E movement
+      if (filwidth_e_count > 0.0001) {
 
-      delay_dist += delta_mm[E_AXIS];  // increment counter with next move in e axis
-      while (delay_dist >= MMD10) delay_dist -= MMD10; // loop around the buffer
-      while (delay_dist < 0) delay_dist += MMD10;
+        // Loop the delay distance counter (modulus by the mm length)
+        while (filwidth_delay_dist >= MMD_MM) filwidth_delay_dist -= MMD_MM;
 
-      delay_index1 = delay_dist / 10.0;  // calculate index
-      delay_index1 = constrain(delay_index1, 0, MAX_MEASUREMENT_DELAY); // (already constrained above)
+        // Convert into an index into the measurement array
+        filwidth_delay_index1 = (int)(filwidth_delay_dist / 10.0 + 0.0001);
 
-      if (delay_index1 != delay_index2) { // moved index
-        int8_t meas_sample = widthFil_to_size_ratio() - 100;  // Subtract 100 to reduce magnitude - to store in a signed char
-        while (delay_index1 != delay_index2) {
-          // Increment and loop around buffer
-          if (++delay_index2 >= MMD) delay_index2 -= MMD;
-          delay_index2 = constrain(delay_index2, 0, MAX_MEASUREMENT_DELAY);
-          measurement_delay[delay_index2] = meas_sample;
+        // If the index has changed (must have gone forward)...
+        if (filwidth_delay_index1 != filwidth_delay_index2) {
+          filwidth_e_count = 0; // Reset the E movement counter
+          int8_t meas_sample = widthFil_to_size_ratio() - 100; // Subtract 100 to reduce magnitude - to store in a signed char
+          do {
+            filwidth_delay_index2 = (filwidth_delay_index2 + 1) % MMD_CM; // The next unused slot
+            measurement_delay[filwidth_delay_index2] = meas_sample;       // Store the measurement
+          } while (filwidth_delay_index1 != filwidth_delay_index2);       // More slots to fill?
         }
       }
     }
diff --git a/Marlin/scripts/findMissingTranslations.sh b/Marlin/scripts/findMissingTranslations.sh
new file mode 100644
index 0000000000000000000000000000000000000000..b31c09d1dff7c8fbbcdc19fc52816fda1cbee176
--- /dev/null
+++ b/Marlin/scripts/findMissingTranslations.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+IGNORE_DEFINES="LANGUAGE_EN_H MAPPER_NON SIMULATE_ROMFONT DISPLAY_CHARSET_ISO10646_1 MSG_H1 MSG_H2 MSG_H3 MSG_H4 MSG_MOVE_E1 MSG_MOVE_E2 MSG_MOVE_E3 MSG_MOVE_E4 MSG_N1 MSG_N2 MSG_N3 MSG_N4 MSG_DIAM_E1 MSG_DIAM_E2 MSG_DIAM_E3 MSG_DIAM_E4 MSG_E1 MSG_E2 MSG_E3 MSG_E4"
+
+for i in `awk '/#define/{print $2}' language_en.h`; do
+  for j in `ls language_*.h | grep -v language_en.h`; do
+    t=$(grep -c "${i}" ${j})
+    if [ "$t" -eq 0 ]; then
+      for k in ${IGNORE_DEFINES}; do
+        [ "${k}" == "${i}" ] && continue 2;
+      done
+      echo "${j},${i}"
+    fi
+  done
+done
diff --git a/Marlin/stepper.cpp b/Marlin/stepper.cpp
index 5d2761f1fd03874ffe3037e3db1660792d1e52ab..a371361c28bee953e8ddf9729c954898ef1f3a7e 100644
--- a/Marlin/stepper.cpp
+++ b/Marlin/stepper.cpp
@@ -294,20 +294,20 @@ void checkHitEndstops() {
     SERIAL_ECHO_START;
     SERIAL_ECHOPGM(MSG_ENDSTOPS_HIT);
     if (TEST(endstop_hit_bits, X_MIN)) {
-      SERIAL_ECHOPAIR(" X:", (float)endstops_trigsteps[X_AXIS] / axis_steps_per_unit[X_AXIS]);
+      SERIAL_ECHOPAIR(" X:", endstops_trigsteps[X_AXIS] / axis_steps_per_unit[X_AXIS]);
       LCD_MESSAGEPGM(MSG_ENDSTOPS_HIT "X");
     }
     if (TEST(endstop_hit_bits, Y_MIN)) {
-      SERIAL_ECHOPAIR(" Y:", (float)endstops_trigsteps[Y_AXIS] / axis_steps_per_unit[Y_AXIS]);
+      SERIAL_ECHOPAIR(" Y:", endstops_trigsteps[Y_AXIS] / axis_steps_per_unit[Y_AXIS]);
       LCD_MESSAGEPGM(MSG_ENDSTOPS_HIT "Y");
     }
     if (TEST(endstop_hit_bits, Z_MIN)) {
-      SERIAL_ECHOPAIR(" Z:", (float)endstops_trigsteps[Z_AXIS] / axis_steps_per_unit[Z_AXIS]);
+      SERIAL_ECHOPAIR(" Z:", endstops_trigsteps[Z_AXIS] / axis_steps_per_unit[Z_AXIS]);
       LCD_MESSAGEPGM(MSG_ENDSTOPS_HIT "Z");
     }
     #if ENABLED(Z_MIN_PROBE_ENDSTOP)
       if (TEST(endstop_hit_bits, Z_MIN_PROBE)) {
-        SERIAL_ECHOPAIR(" Z_MIN_PROBE:", (float)endstops_trigsteps[Z_AXIS] / axis_steps_per_unit[Z_AXIS]);
+        SERIAL_ECHOPAIR(" Z_MIN_PROBE:", endstops_trigsteps[Z_AXIS] / axis_steps_per_unit[Z_AXIS]);
         LCD_MESSAGEPGM(MSG_ENDSTOPS_HIT "ZP");
       }
     #endif
diff --git a/Marlin/stopwatch.cpp b/Marlin/stopwatch.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5bc0a280fd3cfa9db126547f68287c758e66b2bf
--- /dev/null
+++ b/Marlin/stopwatch.cpp
@@ -0,0 +1,77 @@
+/*
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "Marlin.h"
+#include "stopwatch.h"
+
+Stopwatch::Stopwatch() {
+   this->reset();
+ }
+
+void Stopwatch::stop() {
+  if (DEBUGGING(INFO)) SERIAL_ECHOLNPGM("Stopwatch::stop()");
+  if (!this->isRunning()) return;
+
+  this->status = STPWTCH_STOPPED;
+  this->stopTimestamp = millis();
+}
+
+void Stopwatch::pause() {
+  if (DEBUGGING(INFO)) SERIAL_ECHOLNPGM("Stopwatch::pause()");
+  if (!this->isRunning()) return;
+
+  this->status = STPWTCH_PAUSED;
+  this->stopTimestamp = millis();
+}
+
+void Stopwatch::start() {
+  if (DEBUGGING(INFO)) SERIAL_ECHOLNPGM("Stopwatch::start()");
+  if (this->isRunning()) return;
+
+  if (this->isPaused()) this->accumulator = this->duration();
+  else this->reset();
+
+  this->status = STPWTCH_RUNNING;
+  this->startTimestamp = millis();
+}
+
+void Stopwatch::reset() {
+  if (DEBUGGING(INFO)) SERIAL_ECHOLNPGM("Stopwatch::reset()");
+
+  this->status = STPWTCH_STOPPED;
+  this->startTimestamp = 0;
+  this->stopTimestamp = 0;
+  this->accumulator = 0;
+}
+
+bool Stopwatch::isRunning() {
+  return (this->status == STPWTCH_RUNNING) ? true : false;
+}
+
+bool Stopwatch::isPaused() {
+  return (this->status == STPWTCH_PAUSED) ? true : false;
+}
+
+uint16_t Stopwatch::duration() {
+  return (((this->isRunning()) ? millis() : this->stopTimestamp)
+          - this->startTimestamp) / 1000 + this->accumulator;
+}
diff --git a/Marlin/stopwatch.h b/Marlin/stopwatch.h
new file mode 100644
index 0000000000000000000000000000000000000000..d6ef8a74442ab58e7563eae5f76e7ee25806870e
--- /dev/null
+++ b/Marlin/stopwatch.h
@@ -0,0 +1,99 @@
+/*
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef STOPWATCH_H
+#define STOPWATCH_H
+
+enum StopwatchStatus {
+  STPWTCH_STOPPED = 0x0,
+  STPWTCH_RUNNING = 0x1,
+  STPWTCH_PAUSED  = 0x2
+};
+
+/**
+ * @brief Stopwatch class
+ * @details This class acts as a timer proving stopwatch functionality including
+ * the ability to pause the running time counter.
+ */
+class Stopwatch {
+  private:
+    StopwatchStatus status;
+    uint16_t accumulator;
+    uint32_t startTimestamp;
+    uint32_t stopTimestamp;
+
+  public:
+    /**
+     * @brief Class constructor
+     */
+    Stopwatch();
+
+    /**
+     * @brief Stops the stopwatch
+     * @details Stops the running timer, it will silently ignore the request if
+     * no timer is currently running.
+     */
+    void stop();
+
+    /**
+     * @brief Pauses the stopwatch
+     * @details Pauses the running timer, it will silently ignore the request if
+     * no timer is currently running.
+     */
+    void pause();
+
+    /**
+     * @brief Starts the stopwatch
+     * @details Starts the timer, it will silently ignore the request if the
+     * timer is already running.
+     */
+    void start();
+
+    /**
+     * @brief Resets the stopwatch
+     * @details Resets all settings to their default values.
+     */
+    void reset();
+
+    /**
+     * @brief Checks if the timer is running
+     * @details Returns true if the timer is currently running, false otherwise.
+     * @return bool
+     */
+    bool isRunning();
+
+    /**
+     * @brief Checks if the timer is paused
+     * @details Returns true if the timer is currently paused, false otherwise.
+     * @return bool
+     */
+    bool isPaused();
+
+    /**
+     * @brief Gets the running time
+     * @details Returns the total number of seconds the timer has been running.
+     * @return uint16_t
+     */
+    uint16_t duration();
+};
+
+#endif //STOPWATCH_H
diff --git a/Marlin/temperature.cpp b/Marlin/temperature.cpp
index d20b6e7054bb4bbc18042a108ce75af960ba0533..d9a5895f447a0f2edfc5c0aeeb450a540d4815eb 100644
--- a/Marlin/temperature.cpp
+++ b/Marlin/temperature.cpp
@@ -350,7 +350,7 @@ void PID_autotune(float temp, int extruder, int ncycles, bool set_result/*=false
     }
     // Every 2 seconds...
     if (ms > temp_ms + 2000) {
-      #if HAS_TEMP_0 || HAS_TEMP_BED || ENABLED(HEATER_0_USES_MAX6675)
+      #if HAS_TEMP_HOTEND || HAS_TEMP_BED
         print_heaterstates();
         SERIAL_EOL;
       #endif
@@ -705,7 +705,7 @@ void manage_heater() {
   // Control the extruder rate based on the width sensor
   #if ENABLED(FILAMENT_WIDTH_SENSOR)
     if (filament_sensor) {
-      meas_shift_index = delay_index1 - meas_delay_cm;
+      meas_shift_index = filwidth_delay_index1 - meas_delay_cm;
       if (meas_shift_index < 0) meas_shift_index += MAX_MEASUREMENT_DELAY + 1;  //loop around buffer if needed
 
       // Get the delayed info and add 100 to reconstitute to a percent of
@@ -1175,7 +1175,7 @@ void disable_all_heaters() {
   setTargetBed(0);
 
   // If all heaters go down then for sure our print job has stopped
-  print_job_stop(true);
+  print_job_timer.stop();
 
   #define DISABLE_HEATER(NR) { \
     setTargetHotend(NR, 0); \
@@ -1183,7 +1183,7 @@ void disable_all_heaters() {
     WRITE_HEATER_ ## NR (LOW); \
   }
 
-  #if HAS_TEMP_0 || ENABLED(HEATER_0_USES_MAX6675)
+  #if HAS_TEMP_HOTEND
     setTargetHotend(0, 0);
     soft_pwm[0] = 0;
     WRITE_HEATER_0P(LOW); // Should HEATERS_PARALLEL apply here? Then change to DISABLE_HEATER(0)
diff --git a/Marlin/temperature.h b/Marlin/temperature.h
index d6674b5a7c9affd2bf314cbf08082c60fde78f15..edccdfc5d0afab3ea80b66fe25d45135f7e4b7ce 100644
--- a/Marlin/temperature.h
+++ b/Marlin/temperature.h
@@ -83,7 +83,7 @@ extern float current_temperature_bed;
 
   #if ENABLED(PID_PARAMS_PER_EXTRUDER)
     extern float Kp[EXTRUDERS], Ki[EXTRUDERS], Kd[EXTRUDERS], Kc[EXTRUDERS]; // one param per extruder
-    #define PID_PARAM(param,e) param[e] // use macro to point to array value
+    #define PID_PARAM(param, e) param[e] // use macro to point to array value
   #else
     extern float Kp, Ki, Kd, Kc; // one param per extruder - saves 20 or 36 bytes of ram (inc array pointer)
     #define PID_PARAM(param, e) param // use macro to point directly to value
diff --git a/Marlin/twibus.cpp b/Marlin/twibus.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..313106084803ce85fe336cb29b316364003d78c5
--- /dev/null
+++ b/Marlin/twibus.cpp
@@ -0,0 +1,104 @@
+/*
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "Marlin.h"
+
+#if ENABLED(EXPERIMENTAL_I2CBUS)
+
+#include "twibus.h"
+
+#include <Wire.h>
+
+TWIBus::twibus() {
+  Wire.begin(); // We use no address so we will join the BUS as the master
+  this->reset();
+}
+
+void TWIBus::reset() {
+  this->addr = 0;
+  this->buffer_s = 0;
+  this->buffer[0] = 0x00;
+}
+
+void TWIBus::address(uint8_t addr) {
+  this->addr = addr;
+
+  if (DEBUGGING(INFO)) {
+    SERIAL_ECHOPAIR("TWIBus::sendto: ", this->addr);
+    SERIAL_EOL;
+  }
+}
+
+void TWIBus::addbyte(char c) {
+  if (buffer_s >= sizeof(this->buffer)) return;
+  this->buffer[this->buffer_s++] = c;
+
+  if (DEBUGGING(INFO)) {
+    SERIAL_ECHOPAIR("TWIBus::addbyte: ", this->buffer[this->buffer_s -1]);
+    SERIAL_EOL;
+  }
+}
+
+void TWIBus::send() {
+  if (!this->addr) return;
+  if (DEBUGGING(INFO)) SERIAL_ECHOLNPGM("TWIBus::send()");
+
+  Wire.beginTransmission(this->addr);
+  Wire.write(this->buffer, this->buffer_s);
+  Wire.endTransmission();
+
+    // Reset the buffer after sending the data
+  this->reset();
+}
+
+void TWIBus::reqbytes(uint8_t bytes) {
+  if (!this->addr) return;
+  if (DEBUGGING(INFO)) {
+    SERIAL_ECHOPAIR("TWIBus::reqbytes(): ", bytes);
+    SERIAL_EOL;
+  }
+
+  millis_t t = millis();
+  Wire.requestFrom(this->addr, bytes);
+
+    // requestFrom() is a blocking function
+  while (Wire.available() < bytes) {
+    if (millis() - t >= this->timeout) break;
+    else continue;
+  }
+
+  SERIAL_ECHO_START;
+  SERIAL_ECHOPAIR("i2c-reply: from:", this->addr);
+  SERIAL_ECHOPAIR(" bytes:", Wire.available());
+  SERIAL_ECHOPGM (" data:");
+
+    // Protect against buffer overflows if the number of received bytes
+    // is less than the number of requested bytes
+  uint8_t wba = Wire.available();
+  for (int i = 0; i < wba; i++) SERIAL_CHAR(Wire.read());
+  SERIAL_EOL;
+
+  // Reset the buffer after sending the data
+  this->reset();
+}
+
+#endif //EXPERIMENTAL_I2CBUS
diff --git a/Marlin/twibus.h b/Marlin/twibus.h
new file mode 100644
index 0000000000000000000000000000000000000000..5ab725777b523f1ef5cb16e2b2461935604af3b1
--- /dev/null
+++ b/Marlin/twibus.h
@@ -0,0 +1,122 @@
+/*
+ * Marlin 3D Printer Firmware
+ * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef TWIBUS_H
+#define TWIBUS_H
+
+/**
+ * TWIBUS class
+ *
+ * This class implements a wrapper around the two wire (I2C) bus, it allows
+ * Marlin to send and request data from any slave device on the bus. This is
+ * an experimental feature and it's inner workings as well as public facing
+ * interface are prune to change in the future.
+ *
+ * The two main consumers of this class are M155 and M156, where M155 allows
+ * Marlin to send a I2C packet to a device (please be aware that no repeated
+ * starts are possible), this can be done in caching method by calling multiple
+ * times M155 B<byte-1 value in base 10> or a one liner M155, have a look at
+ * the gcode_M155() function for more information. M156 allows Marlin to
+ * request data from a device, the received data is then relayed into the serial
+ * line for host interpretation.
+ *
+ */
+class TWIBus {
+  private:
+    /**
+     * @brief Timeout value in milliseconds
+     * @details For blocking operations this constant value will set the max
+     * amount of time Marlin will keep waiting for a reply. Useful is something
+     * goes wrong on the bus and the SDA/SCL lines are held up by another device.
+     */
+    const int timeout = 5;
+
+    /**
+     * @brief Target device address
+     * @description This stores, until the buffer is flushed, the target device
+     * address, take not we do follow Arduino 7bit addressing.
+     */
+    uint8_t addr = 0;
+
+    /**
+     * @brief Number of bytes on buffer
+     * @description This var holds the total number of bytes on our buffer
+     * waiting to be flushed to the bus.
+     */
+    uint8_t buffer_s = 0;
+
+    /**
+     * @brief Internal buffer
+     * @details This is a fixed buffer, TWI command cannot be longer than this
+     */
+    char buffer[30];
+
+
+  public:
+    /**
+     * @brief Class constructor
+     * @details Initialized the TWI bus and clears the buffer
+     */
+    TWIBus();
+
+    /**
+     * @brief Reset the buffer
+     * @details Brings the internal buffer to a known-empty state
+     */
+    void reset();
+
+    /**
+     * @brief Send the buffer data to the bus
+     * @details Flushed the buffer into the bus targeting the cached slave device
+     * address.
+     */
+    void send();
+
+    /**
+     * @brief Add one byte to the buffer
+     * @details Adds the byte to the buffer in a sequential way, if buffer is full
+     * the request is silently ignored.
+     *
+     * @param c a data byte
+     */
+    void addbyte(char c);
+
+    /**
+     * @brief Sets the target slave address
+     * @details The target slave address is stored so it can be later used when
+     * the complete packet needs to be sent over the bus.
+     *
+     * @param addr 7-bit integer address
+     */
+    void address(uint8_t addr);
+
+    /**
+     * @brief Request data from slave device
+     * @details Requests data from a slave device, when the data is received it will
+     * be relayed to the serial line using a parser-friendly formatting.
+     *
+     * @param bytes the number of bytes to request
+     */
+    void reqbytes(uint8_t bytes);
+};
+
+#endif //TWIBUS_H
diff --git a/Marlin/ultralcd.cpp b/Marlin/ultralcd.cpp
index 28ce54194d66c34f0b416c45f9e53facb7462235..4169311d1c800b714012e24441ea136c5f164b21 100644
--- a/Marlin/ultralcd.cpp
+++ b/Marlin/ultralcd.cpp
@@ -111,13 +111,10 @@ static void lcd_status_screen();
 
   #if ENABLED(MANUAL_BED_LEVELING)
     #include "mesh_bed_leveling.h"
-    static void _lcd_level_bed();
-    static void _lcd_level_bed_homing();
-    static void lcd_level_bed();
   #endif
 
   /* Different types of actions that can be used in menu items. */
-  static void menu_action_back(menuFunc_t data);
+  static void menu_action_back();
   static void menu_action_submenu(menuFunc_t data);
   static void menu_action_gcode(const char* pgcode);
   static void menu_action_function(menuFunc_t data);
@@ -188,9 +185,9 @@ static void lcd_status_screen();
    *   menu_action_[type](arg3...)
    *
    * Examples:
-   *   MENU_ITEM(back, MSG_WATCH, lcd_status_screen)
-   *     lcd_implementation_drawmenu_back(sel, row, PSTR(MSG_WATCH), lcd_status_screen)
-   *     menu_action_back(lcd_status_screen)
+   *   MENU_ITEM(back, MSG_WATCH)
+   *     lcd_implementation_drawmenu_back(sel, row, PSTR(MSG_WATCH))
+   *     menu_action_back()
    *
    *   MENU_ITEM(function, MSG_PAUSE_PRINT, lcd_sdcard_pause)
    *     lcd_implementation_drawmenu_function(sel, row, PSTR(MSG_PAUSE_PRINT), lcd_sdcard_pause)
@@ -267,14 +264,25 @@ static void lcd_status_screen();
   uint8_t currentMenuViewOffset;              /* scroll offset in the current menu */
   millis_t next_button_update_ms;
   uint8_t lastEncoderBits;
-  uint32_t encoderPosition, prevEncoderPosition;
+  uint32_t encoderPosition;
   #if PIN_EXISTS(SD_DETECT)
     uint8_t lcd_sd_status;
   #endif
 
 #endif // ULTIPANEL
 
-menuFunc_t currentMenu = lcd_status_screen; /* function pointer to the currently active menu */
+typedef struct {
+  menuFunc_t menu_function;
+  #if ENABLED(ULTIPANEL)
+    uint32_t encoder_position;
+  #endif
+} menuPosition;
+
+menuFunc_t currentMenu = lcd_status_screen; // pointer to the currently active menu handler
+
+menuPosition menu_history[10];
+uint8_t menu_history_depth = 0;
+
 millis_t next_lcd_update_ms;
 uint8_t lcd_status_update_delay;
 bool ignore_click = false;
@@ -285,7 +293,7 @@ enum LCDHandlerAction {
   LCD_DRAW_UPDATE_NONE,
   LCD_DRAW_UPDATE_CALL_REDRAW,
   LCD_DRAW_UPDATE_CLEAR_CALL_REDRAW,
-  LCD_DRAW_UPDATE_CALL_NO_REDRAW,
+  LCD_DRAW_UPDATE_CALL_NO_REDRAW
 };
 
 uint8_t lcdDrawUpdate = LCD_DRAW_UPDATE_CLEAR_CALL_REDRAW; // Set 1 or 2 when the LCD needs to draw, decrements after every draw. Set to 2 in LCD routines so the LCD gets at least 1 full redraw (first redraw is partial)
@@ -294,7 +302,6 @@ uint8_t lcdDrawUpdate = LCD_DRAW_UPDATE_CLEAR_CALL_REDRAW; // Set 1 or 2 when th
 const char* editLabel;
 void* editValue;
 int32_t minEditValue, maxEditValue;
-menuFunc_t prevMenu = NULL;           // return here after editing (also prevEncoderPosition)
 menuFunc_t callbackFunc;              // call this after editing
 
 // place-holders for Ki and Kd edits
@@ -302,6 +309,7 @@ float raw_Ki, raw_Kd;
 
 /**
  * General function to go directly to a menu
+ * Remembers the previous position
  */
 static void lcd_goto_menu(menuFunc_t menu, const bool feedback = false, const uint32_t encoder = 0) {
   if (currentMenu != menu) {
@@ -311,26 +319,40 @@ static void lcd_goto_menu(menuFunc_t menu, const bool feedback = false, const ui
       encoderPosition = encoder;
       if (feedback) lcd_quick_feedback();
     #endif
-    // For LCD_PROGRESS_BAR re-initialize the custom characters
+    if (menu == lcd_status_screen) {
+      defer_return_to_status = false;
+      menu_history_depth = 0;
+    }
     #if ENABLED(LCD_PROGRESS_BAR)
+      // For LCD_PROGRESS_BAR re-initialize custom characters
       lcd_set_custom_characters(menu == lcd_status_screen);
     #endif
   }
 }
 
-inline void lcd_save_previous_menu() {
-  prevMenu = currentMenu;
-  #if ENABLED(ULTIPANEL)
-    prevEncoderPosition = encoderPosition;
-  #endif
-}
+static void lcd_return_to_status() { lcd_goto_menu(lcd_status_screen); }
 
-static void lcd_goto_previous_menu() {
-  lcd_goto_menu(prevMenu, true
+inline void lcd_save_previous_menu() {
+  if (menu_history_depth < COUNT(menu_history)) {
+    menu_history[menu_history_depth].menu_function = currentMenu;
     #if ENABLED(ULTIPANEL)
-      , prevEncoderPosition
+      menu_history[menu_history_depth].encoder_position = encoderPosition;
     #endif
-  );
+    ++menu_history_depth;
+  }
+}
+
+static void lcd_goto_previous_menu(bool feedback=false) {
+  if (menu_history_depth > 0) {
+    --menu_history_depth;
+    lcd_goto_menu(menu_history[menu_history_depth].menu_function, feedback
+      #if ENABLED(ULTIPANEL)
+        , menu_history[menu_history_depth].encoder_position
+      #endif
+    );
+  }
+  else
+    lcd_return_to_status();
 }
 
 /**
@@ -410,13 +432,13 @@ static void lcd_status_screen() {
     }
 
     #if ENABLED(ULTIPANEL_FEEDMULTIPLY)
+      int new_frm = feedrate_multiplier + int(encoderPosition);
       // Dead zone at 100% feedrate
-      if ((feedrate_multiplier < 100 && (feedrate_multiplier + int(encoderPosition)) > 100) ||
-          (feedrate_multiplier > 100 && (feedrate_multiplier + int(encoderPosition)) < 100)) {
-        encoderPosition = 0;
+      if ((feedrate_multiplier < 100 && new_frm > 100) || (feedrate_multiplier > 100 && new_frm < 100)) {
         feedrate_multiplier = 100;
+        encoderPosition = 0;
       }
-      if (feedrate_multiplier == 100) {
+      else if (feedrate_multiplier == 100) {
         if (int(encoderPosition) > ENCODER_FEEDRATE_DEADZONE) {
           feedrate_multiplier += int(encoderPosition) - (ENCODER_FEEDRATE_DEADZONE);
           encoderPosition = 0;
@@ -427,7 +449,7 @@ static void lcd_status_screen() {
         }
       }
       else {
-        feedrate_multiplier += int(encoderPosition);
+        feedrate_multiplier = new_frm;
         encoderPosition = 0;
       }
     #endif // ULTIPANEL_FEEDMULTIPLY
@@ -439,9 +461,13 @@ static void lcd_status_screen() {
 
 #if ENABLED(ULTIPANEL)
 
-static void lcd_return_to_status() {
-  defer_return_to_status = false;
-  lcd_goto_menu(lcd_status_screen);
+inline void line_to_current(AxisEnum axis) {
+  #if ENABLED(DELTA)
+    calculate_delta(current_position);
+    plan_buffer_line(delta[X_AXIS], delta[Y_AXIS], delta[Z_AXIS], current_position[E_AXIS], manual_feedrate[axis]/60, active_extruder);
+  #else
+    plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], manual_feedrate[axis]/60, active_extruder);
+  #endif
 }
 
 #if ENABLED(SDSUPPORT)
@@ -469,7 +495,7 @@ static void lcd_return_to_status() {
 
 static void lcd_main_menu() {
   START_MENU();
-  MENU_ITEM(back, MSG_WATCH, lcd_status_screen);
+  MENU_ITEM(back, MSG_WATCH);
   if (movesplanned() || IS_SD_PRINTING) {
     MENU_ITEM(submenu, MSG_TUNE, lcd_tune_menu);
   }
@@ -508,13 +534,11 @@ static void lcd_main_menu() {
   END_MENU();
 }
 
-#if ENABLED(SDSUPPORT) && ENABLED(MENU_ADDAUTOSTART)
-  static void lcd_autostart_sd() {
-    card.autostart_index = 0;
-    card.setroot();
-    card.checkautostart(true);
-  }
-#endif
+/**
+ *
+ * "Tune" submenu items
+ *
+ */
 
 /**
  * Set the home offset based on the current_position
@@ -529,7 +553,7 @@ void lcd_set_home_offsets() {
 
   static void _lcd_babystep(const int axis, const char* msg) {
     ENCODER_DIRECTION_NORMAL();
-    if (encoderPosition != 0) {
+    if (encoderPosition) {
       int distance =  (int)encoderPosition * BABYSTEP_MULTIPLICATOR;
       encoderPosition = 0;
       lcdDrawUpdate = LCD_DRAW_UPDATE_CALL_REDRAW;
@@ -559,7 +583,7 @@ void lcd_set_home_offsets() {
       #endif
     }
     if (lcdDrawUpdate) lcd_implementation_drawedit(msg, NULL);
-    if (LCD_CLICKED) lcd_goto_previous_menu();
+    if (LCD_CLICKED) lcd_goto_previous_menu(true);
   }
 
   #if ENABLED(BABYSTEP_XY)
@@ -612,7 +636,7 @@ static void lcd_tune_menu() {
   //
   // ^ Main
   //
-  MENU_ITEM(back, MSG_MAIN, lcd_main_menu);
+  MENU_ITEM(back, MSG_MAIN);
 
   //
   // Speed:
@@ -722,10 +746,17 @@ static void lcd_tune_menu() {
   END_MENU();
 }
 
+/**
+ *
+ * "Prepare" submenu items
+ *
+ */
 void _lcd_preheat(int endnum, const float temph, const float tempb, const int fan) {
   if (temph > 0) setTargetHotend(temph, endnum);
   #if TEMP_SENSOR_BED != 0
     setTargetBed(tempb);
+  #else
+    UNUSED(tempb);
   #endif
   #if FAN_COUNT > 0
     #if FAN_COUNT > 1
@@ -733,6 +764,8 @@ void _lcd_preheat(int endnum, const float temph, const float tempb, const int fa
     #else
       fanSpeeds[0] = fan;
     #endif
+  #else
+    UNUSED(fan);
   #endif
   lcd_return_to_status();
 }
@@ -778,7 +811,7 @@ void _lcd_preheat(int endnum, const float temph, const float tempb, const int fa
 
   static void lcd_preheat_pla_menu() {
     START_MENU();
-    MENU_ITEM(back, MSG_PREPARE, lcd_prepare_menu);
+    MENU_ITEM(back, MSG_PREPARE);
     #if EXTRUDERS == 1
       MENU_ITEM(function, MSG_PREHEAT_PLA, lcd_preheat_pla0);
     #else
@@ -800,7 +833,7 @@ void _lcd_preheat(int endnum, const float temph, const float tempb, const int fa
 
   static void lcd_preheat_abs_menu() {
     START_MENU();
-    MENU_ITEM(back, MSG_PREPARE, lcd_prepare_menu);
+    MENU_ITEM(back, MSG_PREPARE);
     #if EXTRUDERS == 1
       MENU_ITEM(function, MSG_PREHEAT_ABS, lcd_preheat_abs0);
     #else
@@ -830,6 +863,158 @@ void lcd_cooldown() {
   lcd_return_to_status();
 }
 
+#if ENABLED(SDSUPPORT) && ENABLED(MENU_ADDAUTOSTART)
+
+  static void lcd_autostart_sd() {
+    card.autostart_index = 0;
+    card.setroot();
+    card.checkautostart(true);
+  }
+
+#endif
+
+#if ENABLED(MANUAL_BED_LEVELING)
+
+  /**
+   *
+   * "Prepare" > "Bed Leveling" handlers
+   *
+   */
+
+  static int _lcd_level_bed_position;
+
+  /**
+   * MBL Wait for controller movement and clicks:
+   *   - Movement adjusts the Z axis
+   *   - Click saves the Z and goes to the next mesh point
+   */
+  static void _lcd_level_bed_procedure() {
+    static bool mbl_wait_for_move = false;
+    // Menu handlers may be called in a re-entrant fashion
+    // if they call st_synchronize or plan_buffer_line. So
+    // while waiting for a move we just ignore new input.
+    if (mbl_wait_for_move) {
+      lcdDrawUpdate = LCD_DRAW_UPDATE_CALL_NO_REDRAW;
+      return;
+    }
+
+    ENCODER_DIRECTION_NORMAL();
+
+    // Encoder wheel adjusts the Z position
+    if (encoderPosition && movesplanned() <= 3) {
+      refresh_cmd_timeout();
+      current_position[Z_AXIS] += float((int)encoderPosition) * (MBL_Z_STEP);
+      if (min_software_endstops) NOLESS(current_position[Z_AXIS], Z_MIN_POS);
+      if (max_software_endstops) NOMORE(current_position[Z_AXIS], Z_MAX_POS);
+      encoderPosition = 0;
+      line_to_current(Z_AXIS);
+      lcdDrawUpdate = LCD_DRAW_UPDATE_CALL_NO_REDRAW;
+    }
+
+    // Update on first display, then only on updates to Z position
+    if (lcdDrawUpdate) {
+      float v = current_position[Z_AXIS] - MESH_HOME_SEARCH_Z;
+      lcd_implementation_drawedit(PSTR(MSG_MOVE_Z), ftostr43(v + (v < 0 ? -0.0001 : 0.0001), '+'));
+    }
+
+    // We want subsequent calls, but don't force redraw
+    // Set here so it can be overridden by lcd_return_to_status below
+    lcdDrawUpdate = LCD_DRAW_UPDATE_CALL_NO_REDRAW;
+
+    // Click sets the current Z and moves to the next position
+    static bool debounce_click = false;
+    if (LCD_CLICKED) {
+      if (!debounce_click) {
+        debounce_click = true; // ignore multiple "clicks" in a row
+        int ix = _lcd_level_bed_position % (MESH_NUM_X_POINTS),
+            iy = _lcd_level_bed_position / (MESH_NUM_X_POINTS);
+        if (iy & 1) ix = (MESH_NUM_X_POINTS - 1) - ix; // Zig zag
+        mbl.set_z(ix, iy, current_position[Z_AXIS]);
+        _lcd_level_bed_position++;
+        if (_lcd_level_bed_position == (MESH_NUM_X_POINTS) * (MESH_NUM_Y_POINTS)) {
+          lcd_return_to_status();
+          LCD_ALERTMESSAGEPGM(MSG_LEVEL_BED_DONE);
+          #if HAS_BUZZER
+            buzz(200, 659);
+            buzz(200, 698);
+          #endif
+          current_position[Z_AXIS] = MESH_HOME_SEARCH_Z;
+          line_to_current(Z_AXIS);
+          st_synchronize();
+          mbl.active = 1;
+          enqueue_and_echo_commands_P(PSTR("G28"));
+        }
+        else {
+          #if ENABLED(NEWPANEL)
+            lcd_quick_feedback();
+          #endif
+          mbl_wait_for_move = true;
+          current_position[Z_AXIS] = MESH_HOME_SEARCH_Z;
+          line_to_current(Z_AXIS);
+          ix = _lcd_level_bed_position % (MESH_NUM_X_POINTS);
+          iy = _lcd_level_bed_position / (MESH_NUM_X_POINTS);
+          if (iy & 1) ix = (MESH_NUM_X_POINTS - 1) - ix; // Zig zag
+          current_position[X_AXIS] = mbl.get_x(ix);
+          current_position[Y_AXIS] = mbl.get_y(iy);
+          line_to_current(manual_feedrate[X_AXIS] <= manual_feedrate[Y_AXIS] ? X_AXIS : Y_AXIS);
+          st_synchronize();
+          mbl_wait_for_move = false;
+          encoderPosition = 0;
+        }
+      }
+    }
+    else {
+      debounce_click = false;
+    }
+  }
+
+  static void _lcd_level_bed_homing_done() {
+    if (lcdDrawUpdate) lcd_implementation_drawedit(PSTR(MSG_LEVEL_BED_WAITING), NULL);
+    lcdDrawUpdate = LCD_DRAW_UPDATE_CALL_NO_REDRAW;
+    if (LCD_CLICKED) {
+      current_position[Z_AXIS] = MESH_HOME_SEARCH_Z;
+      plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
+      current_position[X_AXIS] = MESH_MIN_X;
+      current_position[Y_AXIS] = MESH_MIN_Y;
+      line_to_current(manual_feedrate[X_AXIS] <= manual_feedrate[Y_AXIS] ? X_AXIS : Y_AXIS);
+      _lcd_level_bed_position = 0;
+      lcd_goto_menu(_lcd_level_bed_procedure, true);
+    }
+  }
+
+  /**
+   * MBL Move to mesh starting point
+   */
+  static void _lcd_level_bed_homing() {
+    if (lcdDrawUpdate) lcd_implementation_drawedit(PSTR(MSG_LEVEL_BED_HOMING), NULL);
+    lcdDrawUpdate = LCD_DRAW_UPDATE_CALL_NO_REDRAW;
+    if (axis_known_position[X_AXIS] && axis_known_position[Y_AXIS] && axis_known_position[Z_AXIS])
+      lcd_goto_menu(_lcd_level_bed_homing_done);
+  }
+
+  /**
+   * MBL Continue Bed Leveling...
+   */
+  static void _lcd_level_bed_continue() {
+    defer_return_to_status = true;
+    axis_known_position[X_AXIS] = axis_known_position[Y_AXIS] = axis_known_position[Z_AXIS] = false;
+    mbl.reset();
+    enqueue_and_echo_commands_P(PSTR("G28"));
+    lcd_goto_menu(_lcd_level_bed_homing);
+  }
+
+  /**
+   * MBL entry-point
+   */
+  static void lcd_level_bed() {
+    START_MENU();
+    MENU_ITEM(back, MSG_LEVEL_BED_CANCEL);
+    MENU_ITEM(submenu, MSG_LEVEL_BED, _lcd_level_bed_continue);
+    END_MENU();
+  }
+
+#endif  // MANUAL_BED_LEVELING
+
 /**
  *
  * "Prepare" submenu
@@ -842,7 +1027,7 @@ static void lcd_prepare_menu() {
   //
   // ^ Main
   //
-  MENU_ITEM(back, MSG_MAIN, lcd_main_menu);
+  MENU_ITEM(back, MSG_MAIN);
 
   //
   // Auto Home
@@ -918,7 +1103,7 @@ static void lcd_prepare_menu() {
 
   static void lcd_delta_calibrate_menu() {
     START_MENU();
-    MENU_ITEM(back, MSG_MAIN, lcd_main_menu);
+    MENU_ITEM(back, MSG_MAIN);
     MENU_ITEM(gcode, MSG_AUTO_HOME, PSTR("G28"));
     MENU_ITEM(gcode, MSG_DELTA_CALIBRATE_X, PSTR("G0 F8000 X-77.94 Y-45 Z0"));
     MENU_ITEM(gcode, MSG_DELTA_CALIBRATE_Y, PSTR("G0 F8000 X77.94 Y-45 Z0"));
@@ -929,15 +1114,6 @@ static void lcd_prepare_menu() {
 
 #endif // DELTA_CALIBRATION_MENU
 
-inline void line_to_current(AxisEnum axis) {
-  #if ENABLED(DELTA)
-    calculate_delta(current_position);
-    plan_buffer_line(delta[X_AXIS], delta[Y_AXIS], delta[Z_AXIS], current_position[E_AXIS], manual_feedrate[axis]/60, active_extruder);
-  #else
-    plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], manual_feedrate[axis]/60, active_extruder);
-  #endif
-}
-
 /**
  *
  * "Prepare" > "Move Axis" submenu
@@ -945,11 +1121,10 @@ inline void line_to_current(AxisEnum axis) {
  */
 
 float move_menu_scale;
-static void lcd_move_menu_axis();
 
-static void _lcd_move(const char* name, AxisEnum axis, int min, int max) {
+static void _lcd_move(const char* name, AxisEnum axis, float min, float max) {
   ENCODER_DIRECTION_NORMAL();
-  if ((encoderPosition != 0) && (movesplanned() <= 3)) {
+  if (encoderPosition && movesplanned() <= 3) {
     refresh_cmd_timeout();
     current_position[axis] += float((int)encoderPosition) * move_menu_scale;
     if (min_software_endstops) NOLESS(current_position[axis], min);
@@ -959,18 +1134,18 @@ static void _lcd_move(const char* name, AxisEnum axis, int min, int max) {
     lcdDrawUpdate = LCD_DRAW_UPDATE_CALL_REDRAW;
   }
   if (lcdDrawUpdate) lcd_implementation_drawedit(name, ftostr31(current_position[axis]));
-  if (LCD_CLICKED) lcd_goto_previous_menu();
+  if (LCD_CLICKED) lcd_goto_previous_menu(true);
 }
 #if ENABLED(DELTA)
   static float delta_clip_radius_2 =  (DELTA_PRINTABLE_RADIUS) * (DELTA_PRINTABLE_RADIUS);
   static int delta_clip( float a ) { return sqrt(delta_clip_radius_2 - a*a); }
-  static void lcd_move_x() { int clip = delta_clip(current_position[Y_AXIS]); _lcd_move(PSTR(MSG_MOVE_X), X_AXIS, max(X_MIN_POS, -clip), min(X_MAX_POS, clip)); }
-  static void lcd_move_y() { int clip = delta_clip(current_position[X_AXIS]); _lcd_move(PSTR(MSG_MOVE_Y), Y_AXIS, max(Y_MIN_POS, -clip), min(Y_MAX_POS, clip)); }
+  static void lcd_move_x() { int clip = delta_clip(current_position[Y_AXIS]); _lcd_move(PSTR(MSG_MOVE_X), X_AXIS, max(min_pos[X_AXIS], -clip), min(max_pos[X_AXIS], clip)); }
+  static void lcd_move_y() { int clip = delta_clip(current_position[X_AXIS]); _lcd_move(PSTR(MSG_MOVE_Y), Y_AXIS, max(min_pos[Y_AXIS], -clip), min(max_pos[Y_AXIS], clip)); }
 #else
-  static void lcd_move_x() { _lcd_move(PSTR(MSG_MOVE_X), X_AXIS, X_MIN_POS, X_MAX_POS); }
-  static void lcd_move_y() { _lcd_move(PSTR(MSG_MOVE_Y), Y_AXIS, Y_MIN_POS, Y_MAX_POS); }
+  static void lcd_move_x() { _lcd_move(PSTR(MSG_MOVE_X), X_AXIS, min_pos[X_AXIS], max_pos[X_AXIS]); }
+  static void lcd_move_y() { _lcd_move(PSTR(MSG_MOVE_Y), Y_AXIS, min_pos[Y_AXIS], max_pos[Y_AXIS]); }
 #endif
-static void lcd_move_z() { _lcd_move(PSTR(MSG_MOVE_Z), Z_AXIS, Z_MIN_POS, Z_MAX_POS); }
+static void lcd_move_z() { _lcd_move(PSTR(MSG_MOVE_Z), Z_AXIS, min_pos[Z_AXIS], max_pos[Z_AXIS]); }
 static void lcd_move_e(
   #if EXTRUDERS > 1
     uint8_t e
@@ -981,7 +1156,7 @@ static void lcd_move_e(
     unsigned short original_active_extruder = active_extruder;
     active_extruder = e;
   #endif
-  if ((encoderPosition != 0) && (movesplanned() <= 3)) {
+  if (encoderPosition && movesplanned() <= 3) {
     current_position[E_AXIS] += float((int)encoderPosition) * move_menu_scale;
     encoderPosition = 0;
     line_to_current(E_AXIS);
@@ -1005,7 +1180,7 @@ static void lcd_move_e(
     #endif //EXTRUDERS > 1
     lcd_implementation_drawedit(pos_label, ftostr31(current_position[E_AXIS]));
   }
-  if (LCD_CLICKED) lcd_goto_previous_menu();
+  if (LCD_CLICKED) lcd_goto_previous_menu(true);
   #if EXTRUDERS > 1
     active_extruder = original_active_extruder;
   #endif
@@ -1028,13 +1203,22 @@ static void lcd_move_e(
  *
  */
 
-static void lcd_move_menu_axis() {
+#if ENABLED(DELTA) || ENABLED(SCARA)
+  #define _MOVE_XYZ_ALLOWED (axis_homed[X_AXIS] && axis_homed[Y_AXIS] && axis_homed[Z_AXIS])
+#else
+  #define _MOVE_XYZ_ALLOWED true
+#endif
+
+static void _lcd_move_menu_axis() {
   START_MENU();
-  MENU_ITEM(back, MSG_MOVE_AXIS, lcd_move_menu);
-  MENU_ITEM(submenu, MSG_MOVE_X, lcd_move_x);
-  MENU_ITEM(submenu, MSG_MOVE_Y, lcd_move_y);
+  MENU_ITEM(back, MSG_MOVE_AXIS);
+
+  if (_MOVE_XYZ_ALLOWED) {
+    MENU_ITEM(submenu, MSG_MOVE_X, lcd_move_x);
+    MENU_ITEM(submenu, MSG_MOVE_Y, lcd_move_y);
+  }
   if (move_menu_scale < 10.0) {
-    MENU_ITEM(submenu, MSG_MOVE_Z, lcd_move_z);
+    if (_MOVE_XYZ_ALLOWED) MENU_ITEM(submenu, MSG_MOVE_Z, lcd_move_z);
     #if EXTRUDERS == 1
       MENU_ITEM(submenu, MSG_MOVE_E, lcd_move_e);
     #else
@@ -1053,15 +1237,15 @@ static void lcd_move_menu_axis() {
 
 static void lcd_move_menu_10mm() {
   move_menu_scale = 10.0;
-  lcd_move_menu_axis();
+  _lcd_move_menu_axis();
 }
 static void lcd_move_menu_1mm() {
   move_menu_scale = 1.0;
-  lcd_move_menu_axis();
+  _lcd_move_menu_axis();
 }
 static void lcd_move_menu_01mm() {
   move_menu_scale = 0.1;
-  lcd_move_menu_axis();
+  _lcd_move_menu_axis();
 }
 
 /**
@@ -1072,8 +1256,11 @@ static void lcd_move_menu_01mm() {
 
 static void lcd_move_menu() {
   START_MENU();
-  MENU_ITEM(back, MSG_PREPARE, lcd_prepare_menu);
-  MENU_ITEM(submenu, MSG_MOVE_10MM, lcd_move_menu_10mm);
+  MENU_ITEM(back, MSG_PREPARE);
+
+  if (_MOVE_XYZ_ALLOWED)
+    MENU_ITEM(submenu, MSG_MOVE_10MM, lcd_move_menu_10mm);
+
   MENU_ITEM(submenu, MSG_MOVE_1MM, lcd_move_menu_1mm);
   MENU_ITEM(submenu, MSG_MOVE_01MM, lcd_move_menu_01mm);
   //TODO:X,Y,Z,E
@@ -1088,7 +1275,7 @@ static void lcd_move_menu() {
 
 static void lcd_control_menu() {
   START_MENU();
-  MENU_ITEM(back, MSG_MAIN, lcd_main_menu);
+  MENU_ITEM(back, MSG_MAIN);
   MENU_ITEM(submenu, MSG_TEMPERATURE, lcd_control_temperature_menu);
   MENU_ITEM(submenu, MSG_MOTION, lcd_control_motion_menu);
   MENU_ITEM(submenu, MSG_VOLUMETRIC, lcd_control_volumetric_menu);
@@ -1146,10 +1333,16 @@ static void lcd_control_menu() {
   // Helpers for editing PID Ki & Kd values
   // grab the PID value out of the temp variable; scale it; then update the PID driver
   void copy_and_scalePID_i(int e) {
+    #if DISABLED(PID_PARAMS_PER_EXTRUDER)
+      UNUSED(e);
+    #endif
     PID_PARAM(Ki, e) = scalePID_i(raw_Ki);
     updatePID();
   }
   void copy_and_scalePID_d(int e) {
+    #if DISABLED(PID_PARAMS_PER_EXTRUDER)
+      UNUSED(e);
+    #endif
     PID_PARAM(Kd, e) = scalePID_d(raw_Kd);
     updatePID();
   }
@@ -1191,7 +1384,7 @@ static void lcd_control_temperature_menu() {
   //
   // ^ Control
   //
-  MENU_ITEM(back, MSG_CONTROL, lcd_control_menu);
+  MENU_ITEM(back, MSG_CONTROL);
 
   //
   // Nozzle:
@@ -1323,7 +1516,7 @@ static void lcd_control_temperature_menu() {
  */
 static void lcd_control_temperature_preheat_pla_settings_menu() {
   START_MENU();
-  MENU_ITEM(back, MSG_TEMPERATURE, lcd_control_temperature_menu);
+  MENU_ITEM(back, MSG_TEMPERATURE);
   MENU_ITEM_EDIT(int3, MSG_FAN_SPEED, &plaPreheatFanSpeed, 0, 255);
   #if TEMP_SENSOR_0 != 0
     MENU_ITEM_EDIT(int3, MSG_NOZZLE, &plaPreheatHotendTemp, HEATER_0_MINTEMP, HEATER_0_MAXTEMP - 15);
@@ -1344,7 +1537,7 @@ static void lcd_control_temperature_preheat_pla_settings_menu() {
  */
 static void lcd_control_temperature_preheat_abs_settings_menu() {
   START_MENU();
-  MENU_ITEM(back, MSG_TEMPERATURE, lcd_control_temperature_menu);
+  MENU_ITEM(back, MSG_TEMPERATURE);
   MENU_ITEM_EDIT(int3, MSG_FAN_SPEED, &absPreheatFanSpeed, 0, 255);
   #if TEMP_SENSOR_0 != 0
     MENU_ITEM_EDIT(int3, MSG_NOZZLE, &absPreheatHotendTemp, HEATER_0_MINTEMP, HEATER_0_MAXTEMP - 15);
@@ -1365,7 +1558,7 @@ static void lcd_control_temperature_preheat_abs_settings_menu() {
  */
 static void lcd_control_motion_menu() {
   START_MENU();
-  MENU_ITEM(back, MSG_CONTROL, lcd_control_menu);
+  MENU_ITEM(back, MSG_CONTROL);
   #if ENABLED(AUTO_BED_LEVELING_FEATURE)
     MENU_ITEM_EDIT(float32, MSG_ZPROBE_ZOFFSET, &zprobe_zoffset, Z_PROBE_OFFSET_RANGE_MIN, Z_PROBE_OFFSET_RANGE_MAX);
   #endif
@@ -1418,7 +1611,7 @@ static void lcd_control_motion_menu() {
  */
 static void lcd_control_volumetric_menu() {
   START_MENU();
-  MENU_ITEM(back, MSG_CONTROL, lcd_control_menu);
+  MENU_ITEM(back, MSG_CONTROL);
 
   MENU_ITEM_EDIT_CALLBACK(bool, MSG_VOLUMETRIC_ENABLED, &volumetric_enabled, calculate_volumetric_multipliers);
 
@@ -1448,7 +1641,7 @@ static void lcd_control_volumetric_menu() {
 #if ENABLED(HAS_LCD_CONTRAST)
   static void lcd_set_contrast() {
     ENCODER_DIRECTION_NORMAL();
-    if (encoderPosition != 0) {
+    if (encoderPosition) {
       #if ENABLED(U8GLIB_LM6059_AF)
         lcd_contrast += encoderPosition;
         lcd_contrast &= 0xFF;
@@ -1467,7 +1660,7 @@ static void lcd_control_volumetric_menu() {
         lcd_implementation_drawedit(PSTR(MSG_CONTRAST), itostr2(lcd_contrast));
       #endif
     }
-    if (LCD_CLICKED) lcd_goto_previous_menu();
+    if (LCD_CLICKED) lcd_goto_previous_menu(true);
   }
 #endif // HAS_LCD_CONTRAST
 
@@ -1479,7 +1672,7 @@ static void lcd_control_volumetric_menu() {
 #if ENABLED(FWRETRACT)
   static void lcd_control_retract_menu() {
     START_MENU();
-    MENU_ITEM(back, MSG_CONTROL, lcd_control_menu);
+    MENU_ITEM(back, MSG_CONTROL);
     MENU_ITEM_EDIT(bool, MSG_AUTORETRACT, &autoretract_enabled);
     MENU_ITEM_EDIT(float52, MSG_CONTROL_RETRACT, &retract_length, 0, 100);
     #if EXTRUDERS > 1
@@ -1520,7 +1713,7 @@ static void lcd_control_volumetric_menu() {
     if (lcdDrawUpdate == 0 && LCD_CLICKED == 0) return; // nothing to do (so don't thrash the SD card)
     uint16_t fileCnt = card.getnrfilenames();
     START_MENU();
-    MENU_ITEM(back, MSG_MAIN, lcd_main_menu);
+    MENU_ITEM(back, MSG_MAIN);
     card.getWorkDirName();
     if (card.filename[0] == '/') {
       #if !PIN_EXISTS(SD_DETECT)
@@ -1589,7 +1782,7 @@ static void lcd_control_volumetric_menu() {
       lcd_implementation_drawedit(editLabel, _strFunc(((_type)((int32_t)encoderPosition + minEditValue)) / scale)); \
     if (isClicked) { \
       *((_type*)editValue) = ((_type)((int32_t)encoderPosition + minEditValue)) / scale; \
-      lcd_goto_previous_menu(); \
+      lcd_goto_previous_menu(true); \
     } \
     return isClicked; \
   } \
@@ -1599,7 +1792,6 @@ static void lcd_control_volumetric_menu() {
     lcd_save_previous_menu(); \
     \
     lcdDrawUpdate = LCD_DRAW_UPDATE_CLEAR_CALL_REDRAW; \
-    currentMenu = menu_edit_ ## _name; \
     \
     editLabel = pstr; \
     editValue = ptr; \
@@ -1616,14 +1808,14 @@ static void lcd_control_volumetric_menu() {
     currentMenu = menu_edit_callback_ ## _name; \
     callbackFunc = callback; \
   }
-menu_edit_type(int, int3, itostr3, 1)
-menu_edit_type(float, float3, ftostr3, 1)
-menu_edit_type(float, float32, ftostr32, 100)
-menu_edit_type(float, float43, ftostr43, 1000)
-menu_edit_type(float, float5, ftostr5, 0.01)
-menu_edit_type(float, float51, ftostr51, 10)
-menu_edit_type(float, float52, ftostr52, 100)
-menu_edit_type(unsigned long, long5, ftostr5, 0.01)
+menu_edit_type(int, int3, itostr3, 1);
+menu_edit_type(float, float3, ftostr3, 1);
+menu_edit_type(float, float32, ftostr32, 100);
+menu_edit_type(float, float43, ftostr43, 1000);
+menu_edit_type(float, float5, ftostr5, 0.01);
+menu_edit_type(float, float51, ftostr51, 10);
+menu_edit_type(float, float52, ftostr52, 100);
+menu_edit_type(unsigned long, long5, ftostr5, 0.01);
 
 /**
  *
@@ -1662,7 +1854,7 @@ menu_edit_type(unsigned long, long5, ftostr5, 0.01)
     lcd_move_y();
   }
   static void reprapworld_keypad_move_home() {
-    enqueue_and_echo_commands_P((PSTR("G28"))); // move all axis home
+    enqueue_and_echo_commands_P(PSTR("G28")); // move all axes home
   }
 #endif // REPRAPWORLD_KEYPAD
 
@@ -1712,7 +1904,7 @@ void lcd_quick_feedback() {
  * Menu actions
  *
  */
-static void menu_action_back(menuFunc_t func) { lcd_goto_menu(func); }
+static void menu_action_back() { lcd_goto_previous_menu(); }
 static void menu_action_submenu(menuFunc_t func) { lcd_save_previous_menu(); lcd_goto_menu(func); }
 static void menu_action_gcode(const char* pgcode) { enqueue_and_echo_commands_P(pgcode); }
 static void menu_action_function(menuFunc_t func) { (*func)(); }
@@ -1720,18 +1912,20 @@ static void menu_action_function(menuFunc_t func) { (*func)(); }
 #if ENABLED(SDSUPPORT)
 
   static void menu_action_sdfile(const char* filename, char* longFilename) {
+    UNUSED(longFilename);
     card.openAndPrintFile(filename);
     lcd_return_to_status();
   }
 
   static void menu_action_sddirectory(const char* filename, char* longFilename) {
+    UNUSED(longFilename);
     card.chdir(filename);
     encoderPosition = 0;
   }
 
 #endif //SDSUPPORT
 
-static void menu_action_setting_edit_bool(const char* pstr, bool* ptr) { *ptr = !(*ptr); }
+static void menu_action_setting_edit_bool(const char* pstr, bool* ptr) {UNUSED(pstr); *ptr = !(*ptr); }
 static void menu_action_setting_edit_callback_bool(const char* pstr, bool* ptr, menuFunc_t callback) {
   menu_action_setting_edit_bool(pstr, ptr);
   (*callback)();
@@ -1909,13 +2103,22 @@ void lcd_update() {
     #if ENABLED(ULTIPANEL)
 
       #if ENABLED(REPRAPWORLD_KEYPAD)
-        if (REPRAPWORLD_KEYPAD_MOVE_Z_UP)     reprapworld_keypad_move_z_up();
-        if (REPRAPWORLD_KEYPAD_MOVE_Z_DOWN)   reprapworld_keypad_move_z_down();
-        if (REPRAPWORLD_KEYPAD_MOVE_X_LEFT)   reprapworld_keypad_move_x_left();
-        if (REPRAPWORLD_KEYPAD_MOVE_X_RIGHT)  reprapworld_keypad_move_x_right();
-        if (REPRAPWORLD_KEYPAD_MOVE_Y_DOWN)   reprapworld_keypad_move_y_down();
-        if (REPRAPWORLD_KEYPAD_MOVE_Y_UP)     reprapworld_keypad_move_y_up();
-        if (REPRAPWORLD_KEYPAD_MOVE_HOME)     reprapworld_keypad_move_home();
+
+        #if ENABLED(DELTA) || ENABLED(SCARA)
+          #define _KEYPAD_MOVE_ALLOWED (axis_homed[X_AXIS] && axis_homed[Y_AXIS] && axis_homed[Z_AXIS])
+        #else
+          #define _KEYPAD_MOVE_ALLOWED true
+        #endif
+
+        if (REPRAPWORLD_KEYPAD_MOVE_HOME)       reprapworld_keypad_move_home();
+        if (_KEYPAD_MOVE_ALLOWED) {
+          if (REPRAPWORLD_KEYPAD_MOVE_Z_UP)     reprapworld_keypad_move_z_up();
+          if (REPRAPWORLD_KEYPAD_MOVE_Z_DOWN)   reprapworld_keypad_move_z_down();
+          if (REPRAPWORLD_KEYPAD_MOVE_X_LEFT)   reprapworld_keypad_move_x_left();
+          if (REPRAPWORLD_KEYPAD_MOVE_X_RIGHT)  reprapworld_keypad_move_x_right();
+          if (REPRAPWORLD_KEYPAD_MOVE_Y_DOWN)   reprapworld_keypad_move_y_down();
+          if (REPRAPWORLD_KEYPAD_MOVE_Y_UP)     reprapworld_keypad_move_y_up();
+        }
       #endif
 
       bool encoderPastThreshold = (abs(encoderDiff) >= ENCODER_PULSES_PER_STEP);
@@ -2000,7 +2203,7 @@ void lcd_update() {
       // Return to Status Screen after a timeout
       if (defer_return_to_status)
         return_to_status_ms = ms + LCD_TIMEOUT_TO_STATUS;
-      else if (currentMenu != lcd_status_screen && millis() > return_to_status_ms) {
+      else if (currentMenu != lcd_status_screen && ms > return_to_status_ms) {
         lcd_return_to_status();
       }
 
@@ -2031,6 +2234,10 @@ void lcd_ignore_click(bool b) {
 }
 
 void lcd_finishstatus(bool persist=false) {
+  #if !(ENABLED(LCD_PROGRESS_BAR) && (PROGRESS_MSG_EXPIRE > 0))
+    UNUSED(persist);
+  #endif
+
   #if ENABLED(LCD_PROGRESS_BAR)
     progress_bar_ms = millis();
     #if PROGRESS_MSG_EXPIRE > 0
@@ -2473,138 +2680,4 @@ char* ftostr52(const float& x) {
   return conv;
 }
 
-#if ENABLED(MANUAL_BED_LEVELING)
-
-  static int _lcd_level_bed_position;
-
-  /**
-   * MBL Wait for controller movement and clicks:
-   *   - Movement adjusts the Z axis
-   *   - Click saves the Z and goes to the next mesh point
-   */
-  static void _lcd_level_bed_procedure() {
-    static bool mbl_wait_for_move = false;
-    // Menu handlers may be called in a re-entrant fashion
-    // if they call st_synchronize or plan_buffer_line. So
-    // while waiting for a move we just ignore new input.
-    if (mbl_wait_for_move) {
-      lcdDrawUpdate = LCD_DRAW_UPDATE_CALL_NO_REDRAW;
-      return;
-    }
-
-    ENCODER_DIRECTION_NORMAL();
-
-    // Encoder wheel adjusts the Z position
-    if (encoderPosition != 0 && movesplanned() <= 3) {
-      refresh_cmd_timeout();
-      current_position[Z_AXIS] += float((int)encoderPosition) * (MBL_Z_STEP);
-      if (min_software_endstops) NOLESS(current_position[Z_AXIS], Z_MIN_POS);
-      if (max_software_endstops) NOMORE(current_position[Z_AXIS], Z_MAX_POS);
-      encoderPosition = 0;
-      line_to_current(Z_AXIS);
-      lcdDrawUpdate = LCD_DRAW_UPDATE_CALL_NO_REDRAW;
-    }
-
-    // Update on first display, then only on updates to Z position
-    if (lcdDrawUpdate) {
-      float v = current_position[Z_AXIS] - MESH_HOME_SEARCH_Z;
-      lcd_implementation_drawedit(PSTR(MSG_MOVE_Z), ftostr43(v + (v < 0 ? -0.0001 : 0.0001), '+'));
-    }
-
-    // We want subsequent calls, but don't force redraw
-    // Set here so it can be overridden by lcd_return_to_status below
-    lcdDrawUpdate = LCD_DRAW_UPDATE_CALL_NO_REDRAW;
-
-    // Click sets the current Z and moves to the next position
-    static bool debounce_click = false;
-    if (LCD_CLICKED) {
-      if (!debounce_click) {
-        debounce_click = true; // ignore multiple "clicks" in a row
-        int ix = _lcd_level_bed_position % (MESH_NUM_X_POINTS),
-            iy = _lcd_level_bed_position / (MESH_NUM_X_POINTS);
-        if (iy & 1) ix = (MESH_NUM_X_POINTS - 1) - ix; // Zig zag
-        mbl.set_z(ix, iy, current_position[Z_AXIS]);
-        _lcd_level_bed_position++;
-        if (_lcd_level_bed_position == (MESH_NUM_X_POINTS) * (MESH_NUM_Y_POINTS)) {
-          current_position[Z_AXIS] = MESH_HOME_SEARCH_Z;
-          mbl_wait_for_move = true;
-          line_to_current(Z_AXIS);
-          st_synchronize();
-          mbl.active = 1;
-          enqueue_and_echo_commands_P(PSTR("G28"));
-          mbl_wait_for_move = false;
-          lcd_return_to_status();
-          #if ENABLED(NEWPANEL)
-            lcd_quick_feedback();
-          #endif
-          LCD_ALERTMESSAGEPGM(MSG_LEVEL_BED_DONE);
-          #if HAS_BUZZER
-            buzz(200, 659);
-            buzz(200, 698);
-          #endif
-        }
-        else {
-          current_position[Z_AXIS] = MESH_HOME_SEARCH_Z;
-          line_to_current(Z_AXIS);
-          ix = _lcd_level_bed_position % (MESH_NUM_X_POINTS);
-          iy = _lcd_level_bed_position / (MESH_NUM_X_POINTS);
-          if (iy & 1) ix = (MESH_NUM_X_POINTS - 1) - ix; // Zig zag
-          current_position[X_AXIS] = mbl.get_x(ix);
-          current_position[Y_AXIS] = mbl.get_y(iy);
-          line_to_current(manual_feedrate[X_AXIS] <= manual_feedrate[Y_AXIS] ? X_AXIS : Y_AXIS);
-        }
-      }
-    }
-    else {
-      debounce_click = false;
-    }
-  }
-
-  static void _lcd_level_bed_homing_done() {
-    if (lcdDrawUpdate) lcd_implementation_drawedit(PSTR(MSG_LEVEL_BED_WAITING), NULL);
-    lcdDrawUpdate = LCD_DRAW_UPDATE_CALL_NO_REDRAW;
-    if (LCD_CLICKED) {
-      current_position[Z_AXIS] = MESH_HOME_SEARCH_Z;
-      plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
-      current_position[X_AXIS] = MESH_MIN_X;
-      current_position[Y_AXIS] = MESH_MIN_Y;
-      line_to_current(manual_feedrate[X_AXIS] <= manual_feedrate[Y_AXIS] ? X_AXIS : Y_AXIS);
-      _lcd_level_bed_position = 0;
-      lcd_goto_menu(_lcd_level_bed_procedure, true);
-    }
-  }
-
-  /**
-   * MBL Move to mesh starting point
-   */
-  static void _lcd_level_bed_homing() {
-    if (lcdDrawUpdate) lcd_implementation_drawedit(PSTR(MSG_LEVEL_BED_HOMING), NULL);
-    lcdDrawUpdate = LCD_DRAW_UPDATE_CALL_NO_REDRAW;
-    if (axis_known_position[X_AXIS] && axis_known_position[Y_AXIS] && axis_known_position[Z_AXIS])
-      lcd_goto_menu(_lcd_level_bed_homing_done);
-  }
-
-  /**
-   * MBL Continue Bed Leveling...
-   */
-  static void _lcd_level_bed_continue() {
-    defer_return_to_status = true;
-    axis_known_position[X_AXIS] = axis_known_position[Y_AXIS] = axis_known_position[Z_AXIS] = false;
-    mbl.reset();
-    enqueue_and_echo_commands_P(PSTR("G28"));
-    lcd_goto_menu(_lcd_level_bed_homing, true);
-  }
-
-  /**
-   * MBL entry-point
-   */
-  static void lcd_level_bed() {
-    START_MENU();
-    MENU_ITEM(back, "Cancel", lcd_prepare_menu);
-    MENU_ITEM(submenu, MSG_LEVEL_BED, _lcd_level_bed_continue);
-    END_MENU();
-  }
-
-#endif  // MANUAL_BED_LEVELING
-
 #endif // ULTRA_LCD
diff --git a/Marlin/ultralcd.h b/Marlin/ultralcd.h
index cbc5e05c46e063d37a555c2783aa6cf87e43b214..61abf9cedeff3661c9bc6b3ce79743872bef3382 100644
--- a/Marlin/ultralcd.h
+++ b/Marlin/ultralcd.h
@@ -65,9 +65,6 @@
   #if ENABLED(ULTIPANEL)
     void lcd_buttons_update();
     extern volatile uint8_t buttons;  //the last checked buttons in a bit array.
-    #if ENABLED(REPRAPWORLD_KEYPAD)
-      extern volatile uint8_t buttons_reprapworld_keypad; // to store the keypad shift register values
-    #endif
   #else
     FORCE_INLINE void lcd_buttons_update() {}
   #endif
@@ -89,33 +86,52 @@
   void lcd_ignore_click(bool b=true);
   bool lcd_blink();
 
+  #if ENABLED(ULTIPANEL) && ENABLED(REPRAPWORLD_KEYPAD)
+
+    #define REPRAPWORLD_BTN_OFFSET 0 // bit offset into buttons for shift register values
+
+    #define BLEN_REPRAPWORLD_KEYPAD_F3     0
+    #define BLEN_REPRAPWORLD_KEYPAD_F2     1
+    #define BLEN_REPRAPWORLD_KEYPAD_F1     2
+    #define BLEN_REPRAPWORLD_KEYPAD_DOWN   3
+    #define BLEN_REPRAPWORLD_KEYPAD_RIGHT  4
+    #define BLEN_REPRAPWORLD_KEYPAD_MIDDLE 5
+    #define BLEN_REPRAPWORLD_KEYPAD_UP     6
+    #define BLEN_REPRAPWORLD_KEYPAD_LEFT   7
+
+    #define EN_REPRAPWORLD_KEYPAD_F3      (_BV(REPRAPWORLD_BTN_OFFSET + BLEN_REPRAPWORLD_KEYPAD_F3))
+    #define EN_REPRAPWORLD_KEYPAD_F2      (_BV(REPRAPWORLD_BTN_OFFSET + BLEN_REPRAPWORLD_KEYPAD_F2))
+    #define EN_REPRAPWORLD_KEYPAD_F1      (_BV(REPRAPWORLD_BTN_OFFSET + BLEN_REPRAPWORLD_KEYPAD_F1))
+    #define EN_REPRAPWORLD_KEYPAD_DOWN    (_BV(REPRAPWORLD_BTN_OFFSET + BLEN_REPRAPWORLD_KEYPAD_DOWN))
+    #define EN_REPRAPWORLD_KEYPAD_RIGHT   (_BV(REPRAPWORLD_BTN_OFFSET + BLEN_REPRAPWORLD_KEYPAD_RIGHT))
+    #define EN_REPRAPWORLD_KEYPAD_MIDDLE  (_BV(REPRAPWORLD_BTN_OFFSET + BLEN_REPRAPWORLD_KEYPAD_MIDDLE))
+    #define EN_REPRAPWORLD_KEYPAD_UP      (_BV(REPRAPWORLD_BTN_OFFSET + BLEN_REPRAPWORLD_KEYPAD_UP))
+    #define EN_REPRAPWORLD_KEYPAD_LEFT    (_BV(REPRAPWORLD_BTN_OFFSET + BLEN_REPRAPWORLD_KEYPAD_LEFT))
+
+    #define REPRAPWORLD_KEYPAD_MOVE_Z_DOWN  (buttons_reprapworld_keypad & EN_REPRAPWORLD_KEYPAD_F3)
+    #define REPRAPWORLD_KEYPAD_MOVE_Z_UP    (buttons_reprapworld_keypad & EN_REPRAPWORLD_KEYPAD_F2)
+    #define REPRAPWORLD_KEYPAD_MOVE_Y_DOWN  (buttons_reprapworld_keypad & EN_REPRAPWORLD_KEYPAD_DOWN)
+    #define REPRAPWORLD_KEYPAD_MOVE_X_RIGHT (buttons_reprapworld_keypad & EN_REPRAPWORLD_KEYPAD_RIGHT)
+    #define REPRAPWORLD_KEYPAD_MOVE_HOME    (buttons_reprapworld_keypad & EN_REPRAPWORLD_KEYPAD_MIDDLE)
+    #define REPRAPWORLD_KEYPAD_MOVE_Y_UP    (buttons_reprapworld_keypad & EN_REPRAPWORLD_KEYPAD_UP)
+    #define REPRAPWORLD_KEYPAD_MOVE_X_LEFT  (buttons_reprapworld_keypad & EN_REPRAPWORLD_KEYPAD_LEFT)
+
+  #endif //ULTIPANEL && REPRAPWORLD_KEYPAD
+
   #if ENABLED(NEWPANEL)
+
     #define EN_C (_BV(BLEN_C))
     #define EN_B (_BV(BLEN_B))
     #define EN_A (_BV(BLEN_A))
 
     #if ENABLED(REPRAPWORLD_KEYPAD)
-      #define EN_REPRAPWORLD_KEYPAD_F3 (_BV(BLEN_REPRAPWORLD_KEYPAD_F3))
-      #define EN_REPRAPWORLD_KEYPAD_F2 (_BV(BLEN_REPRAPWORLD_KEYPAD_F2))
-      #define EN_REPRAPWORLD_KEYPAD_F1 (_BV(BLEN_REPRAPWORLD_KEYPAD_F1))
-      #define EN_REPRAPWORLD_KEYPAD_UP (_BV(BLEN_REPRAPWORLD_KEYPAD_UP))
-      #define EN_REPRAPWORLD_KEYPAD_RIGHT (_BV(BLEN_REPRAPWORLD_KEYPAD_RIGHT))
-      #define EN_REPRAPWORLD_KEYPAD_MIDDLE (_BV(BLEN_REPRAPWORLD_KEYPAD_MIDDLE))
-      #define EN_REPRAPWORLD_KEYPAD_DOWN (_BV(BLEN_REPRAPWORLD_KEYPAD_DOWN))
-      #define EN_REPRAPWORLD_KEYPAD_LEFT (_BV(BLEN_REPRAPWORLD_KEYPAD_LEFT))
-
       #define LCD_CLICKED ((buttons&EN_C) || (buttons_reprapworld_keypad&EN_REPRAPWORLD_KEYPAD_F1))
-      #define REPRAPWORLD_KEYPAD_MOVE_Z_UP (buttons_reprapworld_keypad&EN_REPRAPWORLD_KEYPAD_F2)
-      #define REPRAPWORLD_KEYPAD_MOVE_Z_DOWN (buttons_reprapworld_keypad&EN_REPRAPWORLD_KEYPAD_F3)
-      #define REPRAPWORLD_KEYPAD_MOVE_X_LEFT (buttons_reprapworld_keypad&EN_REPRAPWORLD_KEYPAD_LEFT)
-      #define REPRAPWORLD_KEYPAD_MOVE_X_RIGHT (buttons_reprapworld_keypad&EN_REPRAPWORLD_KEYPAD_RIGHT)
-      #define REPRAPWORLD_KEYPAD_MOVE_Y_DOWN (buttons_reprapworld_keypad&EN_REPRAPWORLD_KEYPAD_DOWN)
-      #define REPRAPWORLD_KEYPAD_MOVE_Y_UP (buttons_reprapworld_keypad&EN_REPRAPWORLD_KEYPAD_UP)
-      #define REPRAPWORLD_KEYPAD_MOVE_HOME (buttons_reprapworld_keypad&EN_REPRAPWORLD_KEYPAD_MIDDLE)
     #else
       #define LCD_CLICKED (buttons&EN_C)
-    #endif //REPRAPWORLD_KEYPAD
-  #else
+    #endif
+
+  #else //!NEWPANEL
+
     //atomic, do not change
     #define B_LE (_BV(BL_LE))
     #define B_UP (_BV(BL_UP))
@@ -127,7 +143,8 @@
     #define EN_A (_BV(BLEN_A))
 
     #define LCD_CLICKED ((buttons&B_MI)||(buttons&B_ST))
-  #endif//NEWPANEL
+
+  #endif //!NEWPANEL
 
 #else //no LCD
   FORCE_INLINE void lcd_update() {}
diff --git a/Marlin/ultralcd_implementation_hitachi_HD44780.h b/Marlin/ultralcd_implementation_hitachi_HD44780.h
index 9d10bce995f490eb091f0f709d778188afc36a9e..26399fbad4aa16932e61d7c0c81502ac833c86b1 100644
--- a/Marlin/ultralcd_implementation_hitachi_HD44780.h
+++ b/Marlin/ultralcd_implementation_hitachi_HD44780.h
@@ -98,31 +98,8 @@ extern volatile uint8_t buttons;  //an extended version of the last checked butt
     #endif
 
   #elif ENABLED(REPRAPWORLD_KEYPAD)
-    // define register bit values, don't change it
-    #define BLEN_REPRAPWORLD_KEYPAD_F3 0
-    #define BLEN_REPRAPWORLD_KEYPAD_F2 1
-    #define BLEN_REPRAPWORLD_KEYPAD_F1 2
-    #define BLEN_REPRAPWORLD_KEYPAD_UP 6
-    #define BLEN_REPRAPWORLD_KEYPAD_RIGHT 4
-    #define BLEN_REPRAPWORLD_KEYPAD_MIDDLE 5
-    #define BLEN_REPRAPWORLD_KEYPAD_DOWN 3
-    #define BLEN_REPRAPWORLD_KEYPAD_LEFT 7
-
-    #define REPRAPWORLD_BTN_OFFSET 0 // bit offset into buttons for shift register values
-
-    #define EN_REPRAPWORLD_KEYPAD_F3 (_BV(BLEN_REPRAPWORLD_KEYPAD_F3+REPRAPWORLD_BTN_OFFSET))
-    #define EN_REPRAPWORLD_KEYPAD_F2 (_BV(BLEN_REPRAPWORLD_KEYPAD_F2+REPRAPWORLD_BTN_OFFSET))
-    #define EN_REPRAPWORLD_KEYPAD_F1 (_BV(BLEN_REPRAPWORLD_KEYPAD_F1+REPRAPWORLD_BTN_OFFSET))
-    #define EN_REPRAPWORLD_KEYPAD_UP (_BV(BLEN_REPRAPWORLD_KEYPAD_UP+REPRAPWORLD_BTN_OFFSET))
-    #define EN_REPRAPWORLD_KEYPAD_RIGHT (_BV(BLEN_REPRAPWORLD_KEYPAD_RIGHT+REPRAPWORLD_BTN_OFFSET))
-    #define EN_REPRAPWORLD_KEYPAD_MIDDLE (_BV(BLEN_REPRAPWORLD_KEYPAD_MIDDLE+REPRAPWORLD_BTN_OFFSET))
-    #define EN_REPRAPWORLD_KEYPAD_DOWN (_BV(BLEN_REPRAPWORLD_KEYPAD_DOWN+REPRAPWORLD_BTN_OFFSET))
-    #define EN_REPRAPWORLD_KEYPAD_LEFT (_BV(BLEN_REPRAPWORLD_KEYPAD_LEFT+REPRAPWORLD_BTN_OFFSET))
-
-    //#define LCD_CLICKED ((buttons&EN_C) || (buttons&EN_REPRAPWORLD_KEYPAD_F1))
-    //#define REPRAPWORLD_KEYPAD_MOVE_Y_DOWN (buttons&EN_REPRAPWORLD_KEYPAD_DOWN)
-    //#define REPRAPWORLD_KEYPAD_MOVE_Y_UP (buttons&EN_REPRAPWORLD_KEYPAD_UP)
-    //#define REPRAPWORLD_KEYPAD_MOVE_HOME (buttons&EN_REPRAPWORLD_KEYPAD_MIDDLE)
+
+    // REPRAPWORLD_KEYPAD defined in ultralcd.h
 
   #elif ENABLED(NEWPANEL)
     #define LCD_CLICKED (buttons&EN_C)
@@ -739,9 +716,9 @@ static void lcd_implementation_status_screen() {
 
     lcd.setCursor(LCD_WIDTH - 6, 2);
     lcd.print(LCD_STR_CLOCK[0]);
-    if (print_job_start_ms != 0) {
-      uint16_t time = (((print_job_stop_ms > print_job_start_ms)
-                       ? print_job_stop_ms : millis()) - print_job_start_ms) / 60000;
+
+    uint16_t time = print_job_timer.duration() / 60;
+    if (time != 0) {
       lcd.print(itostr2(time / 60));
       lcd.print(':');
       lcd.print(itostr2(time % 60));
@@ -873,6 +850,7 @@ void lcd_implementation_drawedit(const char* pstr, const char* value) {
 #if ENABLED(SDSUPPORT)
 
   static void lcd_implementation_drawmenu_sd(bool sel, uint8_t row, const char* pstr, const char* filename, char* longFilename, uint8_t concat, char post_char) {
+    UNUSED(pstr);
     char c;
     uint8_t n = LCD_WIDTH - concat;
     lcd.setCursor(0, row);
@@ -899,7 +877,7 @@ void lcd_implementation_drawedit(const char* pstr, const char* value) {
 
 #endif //SDSUPPORT
 
-#define lcd_implementation_drawmenu_back(sel, row, pstr, data) lcd_implementation_drawmenu_generic(sel, row, pstr, LCD_STR_UPLEVEL[0], LCD_STR_UPLEVEL[0])
+#define lcd_implementation_drawmenu_back(sel, row, pstr) lcd_implementation_drawmenu_generic(sel, row, pstr, LCD_STR_UPLEVEL[0], LCD_STR_UPLEVEL[0])
 #define lcd_implementation_drawmenu_submenu(sel, row, pstr, data) lcd_implementation_drawmenu_generic(sel, row, pstr, '>', LCD_STR_ARROW_RIGHT[0])
 #define lcd_implementation_drawmenu_gcode(sel, row, pstr, gcode) lcd_implementation_drawmenu_generic(sel, row, pstr, '>', ' ')
 #define lcd_implementation_drawmenu_function(sel, row, pstr, data) lcd_implementation_drawmenu_generic(sel, row, pstr, '>', ' ')