From f2c3b0d47646c5b56804f2474ae96c0884b783c8 Mon Sep 17 00:00:00 2001
From: Scott Lahteine <github@thinkyhead.com>
Date: Mon, 11 Jun 2018 21:29:31 -0500
Subject: [PATCH 1/2] Use bit flags for homed/known

---
 Marlin/src/Marlin.cpp                         |  2 +-
 Marlin/src/Marlin.h                           | 20 ++++++++-----
 Marlin/src/gcode/calibrate/G28.cpp            |  6 ++--
 .../src/gcode/feature/trinamic/M911-M915.cpp  |  2 +-
 Marlin/src/lcd/dogm/status_screen_DOGM.h      |  4 +--
 .../src/lcd/dogm/status_screen_lite_ST7920.h  |  4 +--
 Marlin/src/lcd/ultralcd.cpp                   | 30 +++++++++----------
 Marlin/src/lcd/ultralcd_impl_HD44780.h        |  4 +--
 Marlin/src/module/delta.cpp                   |  2 +-
 Marlin/src/module/motion.cpp                  | 15 +++++-----
 Marlin/src/module/probe.cpp                   |  4 +--
 Marlin/src/module/temperature.h               |  4 +--
 Marlin/src/module/tool_change.cpp             |  2 +-
 13 files changed, 50 insertions(+), 49 deletions(-)

diff --git a/Marlin/src/Marlin.cpp b/Marlin/src/Marlin.cpp
index a13d7f19a9d..c182efc418f 100644
--- a/Marlin/src/Marlin.cpp
+++ b/Marlin/src/Marlin.cpp
@@ -161,7 +161,7 @@ bool Running = true;
  *   Flags that the position is known in each linear axis. Set when homed.
  *   Cleared whenever a stepper powers off, potentially losing its position.
  */
-bool axis_homed[XYZ] = { false }, axis_known_position[XYZ] = { false };
+uint8_t axis_homed, axis_known_position; // = 0
 
 #if ENABLED(TEMPERATURE_UNITS_SUPPORT)
   TempUnit input_temp_units = TEMPUNIT_C;
diff --git a/Marlin/src/Marlin.h b/Marlin/src/Marlin.h
index 6dae6b5d5a5..1259a385c6d 100644
--- a/Marlin/src/Marlin.h
+++ b/Marlin/src/Marlin.h
@@ -44,10 +44,10 @@ void manage_inactivity(const bool ignore_stepper_queue=false);
 
 #if HAS_X2_ENABLE
   #define  enable_X() do{ X_ENABLE_WRITE( X_ENABLE_ON); X2_ENABLE_WRITE( X_ENABLE_ON); }while(0)
-  #define disable_X() do{ X_ENABLE_WRITE(!X_ENABLE_ON); X2_ENABLE_WRITE(!X_ENABLE_ON); axis_known_position[X_AXIS] = false; }while(0)
+  #define disable_X() do{ X_ENABLE_WRITE(!X_ENABLE_ON); X2_ENABLE_WRITE(!X_ENABLE_ON); CBI(axis_known_position, X_AXIS); }while(0)
 #elif HAS_X_ENABLE
   #define  enable_X() X_ENABLE_WRITE( X_ENABLE_ON)
-  #define disable_X() do{ X_ENABLE_WRITE(!X_ENABLE_ON); axis_known_position[X_AXIS] = false; }while(0)
+  #define disable_X() do{ X_ENABLE_WRITE(!X_ENABLE_ON); CBI(axis_known_position, X_AXIS); }while(0)
 #else
   #define  enable_X() NOOP
   #define disable_X() NOOP
@@ -55,10 +55,10 @@ void manage_inactivity(const bool ignore_stepper_queue=false);
 
 #if HAS_Y2_ENABLE
   #define  enable_Y() do{ Y_ENABLE_WRITE( Y_ENABLE_ON); Y2_ENABLE_WRITE(Y_ENABLE_ON); }while(0)
-  #define disable_Y() do{ Y_ENABLE_WRITE(!Y_ENABLE_ON); Y2_ENABLE_WRITE(!Y_ENABLE_ON); axis_known_position[Y_AXIS] = false; }while(0)
+  #define disable_Y() do{ Y_ENABLE_WRITE(!Y_ENABLE_ON); Y2_ENABLE_WRITE(!Y_ENABLE_ON); CBI(axis_known_position, Y_AXIS); }while(0)
 #elif HAS_Y_ENABLE
   #define  enable_Y() Y_ENABLE_WRITE( Y_ENABLE_ON)
-  #define disable_Y() do{ Y_ENABLE_WRITE(!Y_ENABLE_ON); axis_known_position[Y_AXIS] = false; }while(0)
+  #define disable_Y() do{ Y_ENABLE_WRITE(!Y_ENABLE_ON); CBI(axis_known_position, Y_AXIS); }while(0)
 #else
   #define  enable_Y() NOOP
   #define disable_Y() NOOP
@@ -66,10 +66,10 @@ void manage_inactivity(const bool ignore_stepper_queue=false);
 
 #if HAS_Z2_ENABLE
   #define  enable_Z() do{ Z_ENABLE_WRITE( Z_ENABLE_ON); Z2_ENABLE_WRITE(Z_ENABLE_ON); }while(0)
-  #define disable_Z() do{ Z_ENABLE_WRITE(!Z_ENABLE_ON); Z2_ENABLE_WRITE(!Z_ENABLE_ON); axis_known_position[Z_AXIS] = false; }while(0)
+  #define disable_Z() do{ Z_ENABLE_WRITE(!Z_ENABLE_ON); Z2_ENABLE_WRITE(!Z_ENABLE_ON); CBI(axis_known_position, Z_AXIS); }while(0)
 #elif HAS_Z_ENABLE
   #define  enable_Z() Z_ENABLE_WRITE( Z_ENABLE_ON)
-  #define disable_Z() do{ Z_ENABLE_WRITE(!Z_ENABLE_ON); axis_known_position[Z_AXIS] = false; }while(0)
+  #define disable_Z() do{ Z_ENABLE_WRITE(!Z_ENABLE_ON); CBI(axis_known_position, Z_AXIS); }while(0)
 #else
   #define  enable_Z() NOOP
   #define disable_Z() NOOP
@@ -169,8 +169,12 @@ extern bool Running;
 inline bool IsRunning() { return  Running; }
 inline bool IsStopped() { return !Running; }
 
-extern bool axis_known_position[XYZ];
-extern bool axis_homed[XYZ];
+extern uint8_t axis_homed, axis_known_position;
+
+constexpr uint8_t xyz_bits = _BV(X_AXIS) | _BV(Y_AXIS) | _BV(Z_AXIS);
+FORCE_INLINE bool all_axes_homed() { return (axis_homed & xyz_bits) == xyz_bits; }
+FORCE_INLINE bool all_axes_known() { return (axis_known_position & xyz_bits) == xyz_bits; }
+
 extern volatile bool wait_for_heatup;
 
 #if HAS_RESUME_CONTINUE
diff --git a/Marlin/src/gcode/calibrate/G28.cpp b/Marlin/src/gcode/calibrate/G28.cpp
index 45356216882..2a57b52f340 100644
--- a/Marlin/src/gcode/calibrate/G28.cpp
+++ b/Marlin/src/gcode/calibrate/G28.cpp
@@ -88,7 +88,7 @@
   inline void home_z_safely() {
 
     // Disallow Z homing if X or Y are unknown
-    if (!axis_known_position[X_AXIS] || !axis_known_position[Y_AXIS]) {
+    if (!TEST(axis_known_position, X_AXIS) || !TEST(axis_known_position, Y_AXIS)) {
       LCD_MESSAGEPGM(MSG_ERR_Z_HOMING);
       SERIAL_ECHO_START();
       SERIAL_ECHOLNPGM(MSG_ERR_Z_HOMING);
@@ -172,7 +172,7 @@ void GcodeSuite::G28(const bool always_home_all) {
     }
   #endif
 
-  if ((axis_known_position[X_AXIS] && axis_known_position[Y_AXIS] && axis_known_position[Z_AXIS]) && parser.boolval('O')) { // home only if needed
+  if (all_axes_known() && parser.boolval('O')) { // home only if needed
     #if ENABLED(DEBUG_LEVELING_FEATURE)
       if (DEBUGGING(LEVELING)) {
         SERIAL_ECHOLNPGM("> homing not needed, skip");
@@ -246,7 +246,7 @@ void GcodeSuite::G28(const bool always_home_all) {
 
     const float z_homing_height = (
       #if ENABLED(UNKNOWN_Z_NO_RAISE)
-        !axis_known_position[Z_AXIS] ? 0 :
+        !TEST(axis_known_position, Z_AXIS) ? 0 :
       #endif
           (parser.seenval('R') ? parser.value_linear_units() : Z_HOMING_HEIGHT)
     );
diff --git a/Marlin/src/gcode/feature/trinamic/M911-M915.cpp b/Marlin/src/gcode/feature/trinamic/M911-M915.cpp
index b812bd57223..8a59837658a 100644
--- a/Marlin/src/gcode/feature/trinamic/M911-M915.cpp
+++ b/Marlin/src/gcode/feature/trinamic/M911-M915.cpp
@@ -332,7 +332,7 @@ void GcodeSuite::M912() {
     const uint16_t _rms = parser.seenval('S') ? parser.value_int() : CALIBRATION_CURRENT,
                    _z = parser.seenval('Z') ? parser.value_linear_units() : CALIBRATION_EXTRA_HEIGHT;
 
-    if (!axis_known_position[Z_AXIS]) {
+    if (!TEST(axis_known_position, Z_AXIS)) {
       SERIAL_ECHOLNPGM("\nPlease home Z axis first");
       return;
     }
diff --git a/Marlin/src/lcd/dogm/status_screen_DOGM.h b/Marlin/src/lcd/dogm/status_screen_DOGM.h
index 869b470f947..fc8f2324c0c 100644
--- a/Marlin/src/lcd/dogm/status_screen_DOGM.h
+++ b/Marlin/src/lcd/dogm/status_screen_DOGM.h
@@ -108,11 +108,11 @@ FORCE_INLINE void _draw_axis_value(const AxisEnum axis, const char *value, const
   if (blink)
     lcd_put_u8str(value);
   else {
-    if (!axis_homed[axis])
+    if (!TEST(axis_homed, axis))
       while (const char c = *value++) lcd_put_wchar(c <= '.' ? c : '?');
     else {
       #if DISABLED(HOME_AFTER_DEACTIVATE) && DISABLED(DISABLE_REDUCED_ACCURACY_WARNING)
-        if (!axis_known_position[axis])
+        if (!TEST(axis_known_position, axis))
           lcd_put_u8str_P(axis == Z_AXIS ? PSTR("      ") : PSTR("    "));
         else
       #endif
diff --git a/Marlin/src/lcd/dogm/status_screen_lite_ST7920.h b/Marlin/src/lcd/dogm/status_screen_lite_ST7920.h
index 4102cb9ed04..23a7f1a10a6 100644
--- a/Marlin/src/lcd/dogm/status_screen_lite_ST7920.h
+++ b/Marlin/src/lcd/dogm/status_screen_lite_ST7920.h
@@ -868,9 +868,7 @@ void ST7920_Lite_Status_Screen::update_status_or_position(bool forceUpdate) {
         #if ENABLED(DISABLE_REDUCED_ACCURACY_WARNING)
           true
         #else
-          axis_known_position[X_AXIS] &&
-          axis_known_position[Y_AXIS] &&
-          axis_known_position[Z_AXIS]
+          all_axes_known()
         #endif
       );
     }
diff --git a/Marlin/src/lcd/ultralcd.cpp b/Marlin/src/lcd/ultralcd.cpp
index a8297f9aad5..80e0240adcb 100644
--- a/Marlin/src/lcd/ultralcd.cpp
+++ b/Marlin/src/lcd/ultralcd.cpp
@@ -2026,8 +2026,7 @@ void lcd_quick_feedback(const bool clear_buttons) {
     void _lcd_level_bed_homing() {
       if (lcdDrawUpdate) lcd_implementation_drawedit(PSTR(MSG_LEVEL_BED_HOMING), NULL);
       lcdDrawUpdate = LCDVIEW_CALL_NO_REDRAW;
-      if (axis_homed[X_AXIS] && axis_homed[Y_AXIS] && axis_homed[Z_AXIS])
-        lcd_goto_screen(_lcd_level_bed_homing_done);
+      if (all_axes_homed()) lcd_goto_screen(_lcd_level_bed_homing_done);
     }
 
     #if ENABLED(PROBE_MANUALLY)
@@ -2039,7 +2038,7 @@ void lcd_quick_feedback(const bool clear_buttons) {
      */
     void _lcd_level_bed_continue() {
       defer_return_to_status = true;
-      axis_homed[X_AXIS] = axis_homed[Y_AXIS] = axis_homed[Z_AXIS] = false;
+      axis_homed = 0;
       lcd_goto_screen(_lcd_level_bed_homing);
       enqueue_and_echo_commands_P(PSTR("G28"));
     }
@@ -2369,7 +2368,7 @@ void lcd_quick_feedback(const bool clear_buttons) {
       defer_return_to_status = true;
       if (lcdDrawUpdate) lcd_implementation_drawmenu_static(LCD_HEIGHT < 3 ? 0 : (LCD_HEIGHT > 4 ? 2 : 1), PSTR(MSG_LEVEL_BED_HOMING));
       lcdDrawUpdate = LCDVIEW_CALL_NO_REDRAW;
-      if (axis_homed[X_AXIS] && axis_homed[Y_AXIS] && axis_homed[Z_AXIS]) {
+      if (all_axes_homed()) {
         ubl.lcd_map_control = true; // Return to the map screen
         lcd_goto_screen(_lcd_ubl_output_map_lcd);
       }
@@ -2414,7 +2413,7 @@ void lcd_quick_feedback(const bool clear_buttons) {
     void _lcd_ubl_output_map_lcd() {
       static int16_t step_scaler = 0;
 
-      if (!(axis_known_position[X_AXIS] && axis_known_position[Y_AXIS] && axis_known_position[Z_AXIS]))
+      if (!all_axes_known())
         return lcd_goto_screen(_lcd_ubl_map_homing);
 
       if (use_click()) return _lcd_ubl_map_lcd_edit_cmd();
@@ -2463,8 +2462,8 @@ void lcd_quick_feedback(const bool clear_buttons) {
      * UBL Homing before LCD map
      */
     void _lcd_ubl_output_map_lcd_cmd() {
-      if (!(axis_known_position[X_AXIS] && axis_known_position[Y_AXIS] && axis_known_position[Z_AXIS])) {
-        axis_homed[X_AXIS] = axis_homed[Y_AXIS] = axis_homed[Z_AXIS] = false;
+      if (!all_axes_known()) {
+        axis_homed = 0;
         enqueue_and_echo_commands_P(PSTR("G28"));
       }
       lcd_goto_screen(_lcd_ubl_map_homing);
@@ -2592,7 +2591,7 @@ void lcd_quick_feedback(const bool clear_buttons) {
       START_MENU();
       MENU_BACK(MSG_PREPARE);
 
-      const bool is_homed = axis_known_position[X_AXIS] && axis_known_position[Y_AXIS] && axis_known_position[Z_AXIS];
+      const bool is_homed = all_axes_known();
 
       // Auto Home if not using manual probing
       #if DISABLED(PROBE_MANUALLY) && DISABLED(MESH_BED_LEVELING)
@@ -2634,8 +2633,7 @@ void lcd_quick_feedback(const bool clear_buttons) {
 
       #if ENABLED(LEVEL_BED_CORNERS)
         // Move to the next corner for leveling
-        if (axis_homed[X_AXIS] && axis_homed[Y_AXIS] && axis_homed[Z_AXIS])
-          MENU_ITEM(submenu, MSG_LEVEL_CORNERS, _lcd_level_bed_corners);
+        if (all_axes_homed()) MENU_ITEM(submenu, MSG_LEVEL_CORNERS, _lcd_level_bed_corners);
       #endif
 
       #if ENABLED(EEPROM_SETTINGS)
@@ -2665,7 +2663,7 @@ void lcd_quick_feedback(const bool clear_buttons) {
     // Move Axis
     //
     #if ENABLED(DELTA)
-      if (axis_homed[X_AXIS] && axis_homed[Y_AXIS] && axis_homed[Z_AXIS])
+      if (all_axes_homed())
     #endif
         MENU_ITEM(submenu, MSG_MOVE_AXIS, lcd_move_menu);
 
@@ -2709,7 +2707,7 @@ void lcd_quick_feedback(const bool clear_buttons) {
     #endif
 
     #if ENABLED(LEVEL_BED_CORNERS) && DISABLED(LCD_BED_LEVELING)
-      if (axis_homed[X_AXIS] && axis_homed[Y_AXIS] && axis_homed[Z_AXIS])
+      if (all_axes_homed())
         MENU_ITEM(function, MSG_LEVEL_CORNERS, _lcd_level_bed_corners);
     #endif
 
@@ -2839,7 +2837,7 @@ void lcd_quick_feedback(const bool clear_buttons) {
     void _lcd_calibrate_homing() {
       if (lcdDrawUpdate) lcd_implementation_drawmenu_static(LCD_HEIGHT >= 4 ? 1 : 0, PSTR(MSG_LEVEL_BED_HOMING));
       lcdDrawUpdate = LCDVIEW_CALL_REDRAW_NEXT;
-      if (axis_homed[X_AXIS] && axis_homed[Y_AXIS] && axis_homed[Z_AXIS])
+      if (all_axes_homed())
         lcd_goto_previous_menu();
     }
 
@@ -2894,7 +2892,7 @@ void lcd_quick_feedback(const bool clear_buttons) {
       MENU_ITEM(submenu, MSG_DELTA_SETTINGS, lcd_delta_settings);
       #if ENABLED(DELTA_CALIBRATION_MENU)
         MENU_ITEM(submenu, MSG_AUTO_HOME, _lcd_delta_calibrate_home);
-        if (axis_homed[X_AXIS] && axis_homed[Y_AXIS] && axis_homed[Z_AXIS]) {
+        if (all_axes_homed()) {
           MENU_ITEM(submenu, MSG_DELTA_CALIBRATE_X, _goto_tower_x);
           MENU_ITEM(submenu, MSG_DELTA_CALIBRATE_Y, _goto_tower_y);
           MENU_ITEM(submenu, MSG_DELTA_CALIBRATE_Z, _goto_tower_z);
@@ -3190,7 +3188,7 @@ void lcd_quick_feedback(const bool clear_buttons) {
    */
 
   #if IS_KINEMATIC || ENABLED(NO_MOTION_BEFORE_HOMING)
-    #define _MOVE_XYZ_ALLOWED (axis_homed[X_AXIS] && axis_homed[Y_AXIS] && axis_homed[Z_AXIS])
+    #define _MOVE_XYZ_ALLOWED (all_axes_homed())
   #else
     #define _MOVE_XYZ_ALLOWED true
   #endif
@@ -4930,7 +4928,7 @@ void lcd_quick_feedback(const bool clear_buttons) {
           if (REPRAPWORLD_KEYPAD_MOVE_Z_UP)     reprapworld_keypad_move_z_up();
         #endif
 
-        if (axis_homed[X_AXIS] && axis_homed[Y_AXIS] && axis_homed[Z_AXIS]) {
+        if (all_axes_homed()) {
           #if ENABLED(DELTA) || Z_HOME_DIR != -1
             if (REPRAPWORLD_KEYPAD_MOVE_Z_UP)   reprapworld_keypad_move_z_up();
           #endif
diff --git a/Marlin/src/lcd/ultralcd_impl_HD44780.h b/Marlin/src/lcd/ultralcd_impl_HD44780.h
index 66b69aab814..4ea2fdc22bb 100644
--- a/Marlin/src/lcd/ultralcd_impl_HD44780.h
+++ b/Marlin/src/lcd/ultralcd_impl_HD44780.h
@@ -493,11 +493,11 @@ FORCE_INLINE void _draw_axis_value(const AxisEnum axis, const char *value, const
   if (blink)
     lcd_put_u8str(value);
   else {
-    if (!axis_homed[axis])
+    if (!TEST(axis_homed, axis))
       while (const char c = *value++) lcd_put_wchar(c <= '.' ? c : '?');
     else {
       #if DISABLED(HOME_AFTER_DEACTIVATE) && DISABLED(DISABLE_REDUCED_ACCURACY_WARNING)
-        if (!axis_known_position[axis])
+        if (!TEST(axis_known_position, axis))
           lcd_put_u8str_P(axis == Z_AXIS ? PSTR("      ") : PSTR("    "));
         else
       #endif
diff --git a/Marlin/src/module/delta.cpp b/Marlin/src/module/delta.cpp
index ca8109ba2f1..dded33f9fde 100644
--- a/Marlin/src/module/delta.cpp
+++ b/Marlin/src/module/delta.cpp
@@ -73,7 +73,7 @@ void recalc_delta_settings() {
   delta_diagonal_rod_2_tower[B_AXIS] = sq(delta_diagonal_rod + drt[B_AXIS]);
   delta_diagonal_rod_2_tower[C_AXIS] = sq(delta_diagonal_rod + drt[C_AXIS]);
   update_software_endstops(Z_AXIS);
-  axis_homed[X_AXIS] = axis_homed[Y_AXIS] = axis_homed[Z_AXIS] = false;
+  axis_homed = 0;
 }
 
 /**
diff --git a/Marlin/src/module/motion.cpp b/Marlin/src/module/motion.cpp
index 45877049836..e8e3ee5bb76 100644
--- a/Marlin/src/module/motion.cpp
+++ b/Marlin/src/module/motion.cpp
@@ -957,13 +957,13 @@ void prepare_move_to_destination() {
 
   bool axis_unhomed_error(const bool x/*=true*/, const bool y/*=true*/, const bool z/*=true*/) {
     #if ENABLED(HOME_AFTER_DEACTIVATE)
-      const bool xx = x && !axis_known_position[X_AXIS],
-                 yy = y && !axis_known_position[Y_AXIS],
-                 zz = z && !axis_known_position[Z_AXIS];
+      const bool xx = x && !TEST(axis_known_position, X_AXIS),
+                 yy = y && !TEST(axis_known_position, Y_AXIS),
+                 zz = z && !TEST(axis_known_position, Z_AXIS);
     #else
-      const bool xx = x && !axis_homed[X_AXIS],
-                 yy = y && !axis_homed[Y_AXIS],
-                 zz = z && !axis_homed[Z_AXIS];
+      const bool xx = x && !TEST(axis_homed, X_AXIS),
+                 yy = y && !TEST(axis_homed, Y_AXIS),
+                 zz = z && !TEST(axis_homed, Z_AXIS);
     #endif
     if (xx || yy || zz) {
       SERIAL_ECHO_START();
@@ -1173,7 +1173,8 @@ void set_axis_is_at_home(const AxisEnum axis) {
     }
   #endif
 
-  axis_known_position[axis] = axis_homed[axis] = true;
+  SBI(axis_known_position, axis);
+  SBI(axis_homed, axis);
 
   #if HAS_POSITION_SHIFT
     position_shift[axis] = 0;
diff --git a/Marlin/src/module/probe.cpp b/Marlin/src/module/probe.cpp
index 65fbff8822d..f3503cfad13 100644
--- a/Marlin/src/module/probe.cpp
+++ b/Marlin/src/module/probe.cpp
@@ -386,7 +386,7 @@ bool set_probe_deployed(const bool deploy) {
 
   // For beds that fall when Z is powered off only raise for trusted Z
   #if ENABLED(UNKNOWN_Z_NO_RAISE)
-    const bool unknown_condition = axis_known_position[Z_AXIS];
+    const bool unknown_condition = TEST(axis_known_position, Z_AXIS);
   #else
     constexpr float unknown_condition = true;
   #endif
@@ -562,7 +562,7 @@ static float run_z_probe() {
 
   // Stop the probe before it goes too low to prevent damage.
   // If Z isn't known then probe to -10mm.
-  const float z_probe_low_point = axis_known_position[Z_AXIS] ? -zprobe_zoffset + Z_PROBE_LOW_POINT : -10.0;
+  const float z_probe_low_point = TEST(axis_known_position, Z_AXIS) ? -zprobe_zoffset + Z_PROBE_LOW_POINT : -10.0;
 
   // Double-probing does a fast probe followed by a slow probe
   #if MULTIPLE_PROBING == 2
diff --git a/Marlin/src/module/temperature.h b/Marlin/src/module/temperature.h
index 9be142cb822..bc9aa9a7667 100644
--- a/Marlin/src/module/temperature.h
+++ b/Marlin/src/module/temperature.h
@@ -31,7 +31,7 @@
 #include "../inc/MarlinConfig.h"
 
 #if ENABLED(BABYSTEPPING)
-  extern bool axis_known_position[XYZ];
+  extern uint8_t axis_known_position;
 #endif
 
 #if ENABLED(AUTO_POWER_CONTROL)
@@ -504,7 +504,7 @@ class Temperature {
     #if ENABLED(BABYSTEPPING)
 
       static void babystep_axis(const AxisEnum axis, const int16_t distance) {
-        if (axis_known_position[axis]) {
+        if (TEST(axis_known_position, axis)) {
           #if IS_CORE
             #if ENABLED(BABYSTEP_XY)
               switch (axis) {
diff --git a/Marlin/src/module/tool_change.cpp b/Marlin/src/module/tool_change.cpp
index 7cad6d16820..d013c2c7a1f 100644
--- a/Marlin/src/module/tool_change.cpp
+++ b/Marlin/src/module/tool_change.cpp
@@ -80,7 +80,7 @@
     }
   }
 
-#endif // SWITCHING_EXTRUDER
+#endif // DO_SWITCH_EXTRUDER
 
 #if ENABLED(SWITCHING_NOZZLE)
 

From 9d04f47d9809a22f2ed41cb8cc093ce68e5f5753 Mon Sep 17 00:00:00 2001
From: Scott Lahteine <github@thinkyhead.com>
Date: Mon, 11 Jun 2018 18:49:08 -0500
Subject: [PATCH 2/2] Improvements for junction_deviation_mm

- Drop `max_jerk` with `JUNCTION_DEVIATION`
- Add `max_e_jerk_factor` for use by `LIN_ADVANCE`
- Recalculate `max_e_jerk_factor` when `junction_deviation_mm` changes
- Fix LCD editing of `junction_deviation_mm`
---
 Marlin/src/gcode/config/M200-M205.cpp     |  6 ++--
 Marlin/src/gcode/config/M92.cpp           |  4 ++-
 Marlin/src/lcd/ultralcd.cpp               |  4 +--
 Marlin/src/module/configuration_store.cpp | 22 ++++++++-----
 Marlin/src/module/planner.cpp             | 24 +++++++++-----
 Marlin/src/module/planner.h               | 38 +++++++++++++++--------
 6 files changed, 64 insertions(+), 34 deletions(-)

diff --git a/Marlin/src/gcode/config/M200-M205.cpp b/Marlin/src/gcode/config/M200-M205.cpp
index 2feab3c55ee..c73f8da3cce 100644
--- a/Marlin/src/gcode/config/M200-M205.cpp
+++ b/Marlin/src/gcode/config/M200-M205.cpp
@@ -134,8 +134,10 @@ void GcodeSuite::M205() {
   #if ENABLED(JUNCTION_DEVIATION)
     if (parser.seen('J')) {
       const float junc_dev = parser.value_linear_units();
-      if (WITHIN(junc_dev, 0.01, 0.3))
+      if (WITHIN(junc_dev, 0.01, 0.3)) {
         planner.junction_deviation_mm = junc_dev;
+        planner.recalculate_max_e_jerk_factor();
+      }
       else {
         SERIAL_ERROR_START();
         SERIAL_ERRORLNPGM("?J out of range (0.01 to 0.3)");
@@ -151,8 +153,6 @@ void GcodeSuite::M205() {
           SERIAL_ECHOLNPGM("WARNING! Low Z Jerk may lead to unwanted pauses.");
       #endif
     }
-  #endif
-  #if DISABLED(JUNCTION_DEVIATION) || ENABLED(LIN_ADVANCE)
     if (parser.seen('E')) planner.max_jerk[E_AXIS] = parser.value_linear_units();
   #endif
 }
diff --git a/Marlin/src/gcode/config/M92.cpp b/Marlin/src/gcode/config/M92.cpp
index 25c79fe0b82..c1b8ed2eecc 100644
--- a/Marlin/src/gcode/config/M92.cpp
+++ b/Marlin/src/gcode/config/M92.cpp
@@ -39,7 +39,9 @@ void GcodeSuite::M92() {
         const float value = parser.value_per_axis_unit((AxisEnum)(E_AXIS + TARGET_EXTRUDER));
         if (value < 20.0) {
           float factor = planner.axis_steps_per_mm[E_AXIS + TARGET_EXTRUDER] / value; // increase e constants if M92 E14 is given for netfab.
-          planner.max_jerk[E_AXIS] *= factor;
+          #if DISABLED(JUNCTION_DEVIATION)
+            planner.max_jerk[E_AXIS] *= factor;
+          #endif
           planner.max_feedrate_mm_s[E_AXIS + TARGET_EXTRUDER] *= factor;
           planner.max_acceleration_steps_per_s2[E_AXIS + TARGET_EXTRUDER] *= factor;
         }
diff --git a/Marlin/src/lcd/ultralcd.cpp b/Marlin/src/lcd/ultralcd.cpp
index 80e0240adcb..9a7ad5c8151 100644
--- a/Marlin/src/lcd/ultralcd.cpp
+++ b/Marlin/src/lcd/ultralcd.cpp
@@ -3752,7 +3752,7 @@ void lcd_quick_feedback(const bool clear_buttons) {
       MENU_BACK(MSG_MOTION);
 
       #if ENABLED(JUNCTION_DEVIATION)
-        MENU_ITEM_EDIT(float3, MSG_JUNCTION_DEVIATION, &planner.junction_deviation_mm, 0.01, 0.3);
+        MENU_ITEM_EDIT_CALLBACK(float43, MSG_JUNCTION_DEVIATION, &planner.junction_deviation_mm, 0.01, 0.3, planner.recalculate_max_e_jerk_factor);
       #else
         MENU_MULTIPLIER_ITEM_EDIT(float3, MSG_VA_JERK, &planner.max_jerk[A_AXIS], 1, 990);
         MENU_MULTIPLIER_ITEM_EDIT(float3, MSG_VB_JERK, &planner.max_jerk[B_AXIS], 1, 990);
@@ -3761,8 +3761,8 @@ void lcd_quick_feedback(const bool clear_buttons) {
         #else
           MENU_MULTIPLIER_ITEM_EDIT(float52sign, MSG_VC_JERK, &planner.max_jerk[C_AXIS], 0.1, 990);
         #endif
+        MENU_MULTIPLIER_ITEM_EDIT(float3, MSG_VE_JERK, &planner.max_jerk[E_AXIS], 1, 990);
       #endif
-      MENU_MULTIPLIER_ITEM_EDIT(float3, MSG_VE_JERK, &planner.max_jerk[E_AXIS], 1, 990);
 
       END_MENU();
     }
diff --git a/Marlin/src/module/configuration_store.cpp b/Marlin/src/module/configuration_store.cpp
index 3dbf3fa7578..0a6e60b5d30 100644
--- a/Marlin/src/module/configuration_store.cpp
+++ b/Marlin/src/module/configuration_store.cpp
@@ -330,6 +330,10 @@ void MarlinSettings::postprocess() {
     fwretract.refresh_autoretract();
   #endif
 
+  #if ENABLED(JUNCTION_DEVIATION) && ENABLED(LIN_ADVANCE)
+    planner.recalculate_max_e_jerk_factor();
+  #endif
+
   // Refresh steps_to_mm with the reciprocal of axis_steps_per_mm
   // and init stepper.count[], planner.position[] with current_position
   planner.refresh_positioning();
@@ -411,11 +415,13 @@ void MarlinSettings::postprocess() {
     EEPROM_WRITE(planner.travel_acceleration);
     EEPROM_WRITE(planner.min_feedrate_mm_s);
     EEPROM_WRITE(planner.min_travel_feedrate_mm_s);
-    EEPROM_WRITE(planner.max_jerk);
 
     #if ENABLED(JUNCTION_DEVIATION)
+      const float planner_max_jerk[] = { DEFAULT_XJERK, DEFAULT_YJERK, DEFAULT_ZJERK, DEFAULT_EJERK };
+      EEPROM_WRITE(planner_max_jerk);
       EEPROM_WRITE(planner.junction_deviation_mm);
     #else
+      EEPROM_WRITE(planner.max_jerk);
       dummy = 0.02;
       EEPROM_WRITE(dummy);
     #endif
@@ -1008,11 +1014,12 @@ void MarlinSettings::postprocess() {
       EEPROM_READ(planner.travel_acceleration);
       EEPROM_READ(planner.min_feedrate_mm_s);
       EEPROM_READ(planner.min_travel_feedrate_mm_s);
-      EEPROM_READ(planner.max_jerk);
 
       #if ENABLED(JUNCTION_DEVIATION)
+        for (uint8_t q = 4; q--;) EEPROM_READ(dummy);
         EEPROM_READ(planner.junction_deviation_mm);
       #else
+        EEPROM_READ(planner.max_jerk);
         EEPROM_READ(dummy);
       #endif
 
@@ -1724,13 +1731,14 @@ void MarlinSettings::reset(PORTARG_SOLO) {
   planner.travel_acceleration = DEFAULT_TRAVEL_ACCELERATION;
   planner.min_feedrate_mm_s = DEFAULT_MINIMUMFEEDRATE;
   planner.min_travel_feedrate_mm_s = DEFAULT_MINTRAVELFEEDRATE;
-  planner.max_jerk[X_AXIS] = DEFAULT_XJERK;
-  planner.max_jerk[Y_AXIS] = DEFAULT_YJERK;
-  planner.max_jerk[Z_AXIS] = DEFAULT_ZJERK;
-  planner.max_jerk[E_AXIS] = DEFAULT_EJERK;
 
   #if ENABLED(JUNCTION_DEVIATION)
     planner.junction_deviation_mm = JUNCTION_DEVIATION_MM;
+  #else
+    planner.max_jerk[X_AXIS] = DEFAULT_XJERK;
+    planner.max_jerk[Y_AXIS] = DEFAULT_YJERK;
+    planner.max_jerk[Z_AXIS] = DEFAULT_ZJERK;
+    planner.max_jerk[E_AXIS] = DEFAULT_EJERK;
   #endif
 
   #if HAS_HOME_OFFSET
@@ -2135,8 +2143,6 @@ void MarlinSettings::reset(PORTARG_SOLO) {
       SERIAL_ECHOPAIR_P(port, " X", LINEAR_UNIT(planner.max_jerk[X_AXIS]));
       SERIAL_ECHOPAIR_P(port, " Y", LINEAR_UNIT(planner.max_jerk[Y_AXIS]));
       SERIAL_ECHOPAIR_P(port, " Z", LINEAR_UNIT(planner.max_jerk[Z_AXIS]));
-    #endif
-    #if DISABLED(JUNCTION_DEVIATION) || ENABLED(LIN_ADVANCE)
       SERIAL_ECHOPAIR_P(port, " E", LINEAR_UNIT(planner.max_jerk[E_AXIS]));
     #endif
 
diff --git a/Marlin/src/module/planner.cpp b/Marlin/src/module/planner.cpp
index 87a3d1a2ae6..db02c8f4388 100644
--- a/Marlin/src/module/planner.cpp
+++ b/Marlin/src/module/planner.cpp
@@ -121,11 +121,15 @@ float Planner::max_feedrate_mm_s[XYZE_N],     // (mm/s) M203 XYZE - Max speeds
       Planner::acceleration,                  // (mm/s^2) M204 S - Normal acceleration. DEFAULT ACCELERATION for all printing moves.
       Planner::retract_acceleration,          // (mm/s^2) M204 R - Retract acceleration. Filament pull-back and push-forward while standing still in the other axes
       Planner::travel_acceleration,           // (mm/s^2) M204 T - Travel acceleration. DEFAULT ACCELERATION for all NON printing moves.
-      Planner::max_jerk[XYZE],                // (mm/s^2) M205 XYZE - The largest speed change requiring no acceleration.
       Planner::min_travel_feedrate_mm_s;      // (mm/s) M205 T - Minimum travel feedrate
 
 #if ENABLED(JUNCTION_DEVIATION)
   float Planner::junction_deviation_mm;       // (mm) M205 J
+  #if ENABLED(LIN_ADVANCE)
+    float Planner::max_e_jerk_factor;         // Calculated from junction_deviation_mm
+  #endif
+#else
+  float Planner::max_jerk[XYZE];              // (mm/s^2) M205 XYZE - The largest speed change requiring no acceleration.
 #endif
 
 #if ENABLED(ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED)
@@ -134,6 +138,9 @@ float Planner::max_feedrate_mm_s[XYZE_N],     // (mm/s) M203 XYZE - Max speeds
 
 #if ENABLED(DISTINCT_E_FACTORS)
   uint8_t Planner::last_extruder = 0;     // Respond to extruder change
+  #define _EINDEX (E_AXIS + active_extruder)
+#else
+  #define _EINDEX E_AXIS
 #endif
 
 int16_t Planner::flow_percentage[EXTRUDERS] = ARRAY_BY_EXTRUDERS1(100); // Extrusion factor for each extruder
@@ -2021,6 +2028,13 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
     accel = CEIL((esteps ? acceleration : travel_acceleration) * steps_per_mm);
 
     #if ENABLED(LIN_ADVANCE)
+
+      #if ENABLED(JUNCTION_DEVIATION)
+        #define MAX_E_JERK (max_e_jerk_factor * max_acceleration_mm_per_s2[_EINDEX])
+      #else
+        #define MAX_E_JERK max_jerk[E_AXIS]
+      #endif
+
       /**
        *
        * Use LIN_ADVANCE for blocks if all these are true:
@@ -2051,10 +2065,9 @@ bool Planner::_populate_block(block_t * const block, bool split_move,
         if (block->e_D_ratio > 3.0)
           block->use_advance_lead = false;
         else {
-          const uint32_t max_accel_steps_per_s2 = max_jerk[E_AXIS] / (extruder_advance_K * block->e_D_ratio) * steps_per_mm;
+          const uint32_t max_accel_steps_per_s2 = MAX_E_JERK / (extruder_advance_K * block->e_D_ratio) * steps_per_mm;
           #if ENABLED(LA_DEBUG)
-            if (accel > max_accel_steps_per_s2)
-              SERIAL_ECHOLNPGM("Acceleration limited.");
+            if (accel > max_accel_steps_per_s2) SERIAL_ECHOLNPGM("Acceleration limited.");
           #endif
           NOMORE(accel, max_accel_steps_per_s2);
         }
@@ -2459,10 +2472,7 @@ bool Planner::buffer_segment(const float &a, const float &b, const float &c, con
 
 void Planner::_set_position_mm(const float &a, const float &b, const float &c, const float &e) {
   #if ENABLED(DISTINCT_E_FACTORS)
-    #define _EINDEX (E_AXIS + active_extruder)
     last_extruder = active_extruder;
-  #else
-    #define _EINDEX E_AXIS
   #endif
   position[A_AXIS] = LROUND(a * axis_steps_per_mm[A_AXIS]),
   position[B_AXIS] = LROUND(b * axis_steps_per_mm[B_AXIS]),
diff --git a/Marlin/src/module/planner.h b/Marlin/src/module/planner.h
index 2d880c8bd9d..0e313152dd6 100644
--- a/Marlin/src/module/planner.h
+++ b/Marlin/src/module/planner.h
@@ -195,21 +195,25 @@ class Planner {
                                                       // May be auto-adjusted by a filament width sensor
     #endif
 
-    static uint32_t max_acceleration_steps_per_s2[XYZE_N],
-                    max_acceleration_mm_per_s2[XYZE_N], // Use M201 to override
-                    min_segment_time_us; // Use 'M205 B<µs>' to override
-    static float max_feedrate_mm_s[XYZE_N],         // Max speeds in mm per second
-                 axis_steps_per_mm[XYZE_N],
-                 steps_to_mm[XYZE_N],
-                 min_feedrate_mm_s,
-                 acceleration,         // Normal acceleration mm/s^2  DEFAULT ACCELERATION for all printing moves. M204 SXXXX
-                 retract_acceleration, // Retract acceleration mm/s^2 filament pull-back and push-forward while standing still in the other axes M204 TXXXX
-                 travel_acceleration,  // Travel acceleration mm/s^2  DEFAULT ACCELERATION for all NON printing moves. M204 MXXXX
-                 max_jerk[XYZE],       // The largest speed change requiring no acceleration
-                 min_travel_feedrate_mm_s;
+    static uint32_t max_acceleration_mm_per_s2[XYZE_N],    // (mm/s^2) M201 XYZE
+                    max_acceleration_steps_per_s2[XYZE_N], // (steps/s^2) Derived from mm_per_s2
+                    min_segment_time_us;                   // (µs) M205 B
+    static float max_feedrate_mm_s[XYZE_N],     // (mm/s) M203 XYZE - Max speeds
+                 axis_steps_per_mm[XYZE_N],     // (steps) M92 XYZE - Steps per millimeter
+                 steps_to_mm[XYZE_N],           // (mm) Millimeters per step
+                 min_feedrate_mm_s,             // (mm/s) M205 S - Minimum linear feedrate
+                 acceleration,                  // (mm/s^2) M204 S - Normal acceleration. DEFAULT ACCELERATION for all printing moves.
+                 retract_acceleration,          // (mm/s^2) M204 R - Retract acceleration. Filament pull-back and push-forward while standing still in the other axes
+                 travel_acceleration,           // (mm/s^2) M204 T - Travel acceleration. DEFAULT ACCELERATION for all NON printing moves.
+                 min_travel_feedrate_mm_s;      // (mm/s) M205 T - Minimum travel feedrate
 
     #if ENABLED(JUNCTION_DEVIATION)
-      static float junction_deviation_mm; // Initialized by EEPROM
+      static float junction_deviation_mm;       // (mm) M205 J
+      #if ENABLED(LIN_ADVANCE)
+        static float max_e_jerk_factor;         // Calculated from junction_deviation_mm
+      #endif
+    #else
+      static float max_jerk[XYZE];              // (mm/s^2) M205 XYZE - The largest speed change requiring no acceleration.
     #endif
 
     #if HAS_LEVELING
@@ -745,6 +749,14 @@ class Planner {
       static void autotemp_M104_M109();
     #endif
 
+    #if ENABLED(JUNCTION_DEVIATION)
+      FORCE_INLINE static void recalculate_max_e_jerk_factor() {
+        #if ENABLED(LIN_ADVANCE)
+          max_e_jerk_factor = SQRT(SQRT(0.5) * junction_deviation_mm) * RECIPROCAL(1.0 - SQRT(0.5));
+        #endif
+      }
+    #endif
+
   private:
 
     /**