|  |  | @ -1416,6 +1416,7 @@ static void set_home_offset(AxisEnum axis, float v) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  * current_position to home, because neither X nor Y is at home until |  |  |  |  * current_position to home, because neither X nor Y is at home until | 
			
		
	
		
		
			
				
					
					|  |  |  |  * both are at home. Z can however be homed individually. |  |  |  |  * both are at home. Z can however be homed individually. | 
			
		
	
		
		
			
				
					
					|  |  |  |  * |  |  |  |  * | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  * Callers must sync the planner position after calling this! | 
			
		
	
		
		
			
				
					
					|  |  |  |  */ |  |  |  |  */ | 
			
		
	
		
		
			
				
					
					|  |  |  | static void set_axis_is_at_home(AxisEnum axis) { |  |  |  | static void set_axis_is_at_home(AxisEnum axis) { | 
			
		
	
		
		
			
				
					
					|  |  |  |   #if ENABLED(DEBUG_LEVELING_FEATURE) |  |  |  |   #if ENABLED(DEBUG_LEVELING_FEATURE) | 
			
		
	
	
		
		
			
				
					|  |  | @ -3246,10 +3247,12 @@ inline void gcode_G4() { | 
			
		
	
		
		
			
				
					
					|  |  |  |           #endif |  |  |  |           #endif | 
			
		
	
		
		
			
				
					
					|  |  |  |         ) |  |  |  |         ) | 
			
		
	
		
		
			
				
					
					|  |  |  |     ) { |  |  |  |     ) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |       #if HOMING_Z_WITH_PROBE |  |  |  |       #if HOMING_Z_WITH_PROBE | 
			
		
	
		
		
			
				
					
					|  |  |  |         destination[X_AXIS] -= X_PROBE_OFFSET_FROM_EXTRUDER; |  |  |  |         destination[X_AXIS] -= X_PROBE_OFFSET_FROM_EXTRUDER; | 
			
		
	
		
		
			
				
					
					|  |  |  |         destination[Y_AXIS] -= Y_PROBE_OFFSET_FROM_EXTRUDER; |  |  |  |         destination[Y_AXIS] -= Y_PROBE_OFFSET_FROM_EXTRUDER; | 
			
		
	
		
		
			
				
					
					|  |  |  |       #endif |  |  |  |       #endif | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |       #if ENABLED(DEBUG_LEVELING_FEATURE) |  |  |  |       #if ENABLED(DEBUG_LEVELING_FEATURE) | 
			
		
	
		
		
			
				
					
					|  |  |  |         if (DEBUGGING(LEVELING)) DEBUG_POS("Z_SAFE_HOMING", destination); |  |  |  |         if (DEBUGGING(LEVELING)) DEBUG_POS("Z_SAFE_HOMING", destination); | 
			
		
	
		
		
			
				
					
					|  |  |  |       #endif |  |  |  |       #endif | 
			
		
	
	
		
		
			
				
					|  |  | @ -3407,20 +3410,31 @@ inline void gcode_G28() { | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     // Home X
 |  |  |  |     // Home X
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (home_all_axis || homeX) { |  |  |  |     if (home_all_axis || homeX) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |       #if ENABLED(DUAL_X_CARRIAGE) |  |  |  |       #if ENABLED(DUAL_X_CARRIAGE) | 
			
		
	
		
		
			
				
					
					|  |  |  |         int tmp_extruder = active_extruder; |  |  |  | 
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         active_extruder = !active_extruder; |  |  |  |         // Always home the 2nd (right) extruder first
 | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         active_extruder = 1; | 
			
		
	
		
		
			
				
					
					|  |  |  |         HOMEAXIS(X); |  |  |  |         HOMEAXIS(X); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         // Remember this extruder's position for later tool change
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         inactive_extruder_x_pos = RAW_X_POSITION(current_position[X_AXIS]); |  |  |  |         inactive_extruder_x_pos = RAW_X_POSITION(current_position[X_AXIS]); | 
			
		
	
		
		
			
				
					
					|  |  |  |         active_extruder = tmp_extruder; |  |  |  | 
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         // Home the 1st (left) extruder
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         active_extruder = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |         HOMEAXIS(X); |  |  |  |         HOMEAXIS(X); | 
			
		
	
		
		
			
				
					
					|  |  |  |         // reset state used by the different modes
 |  |  |  | 
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |         // Consider the active extruder to be parked
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         memcpy(raised_parked_position, current_position, sizeof(raised_parked_position)); |  |  |  |         memcpy(raised_parked_position, current_position, sizeof(raised_parked_position)); | 
			
		
	
		
		
			
				
					
					|  |  |  |         delayed_move_time = 0; |  |  |  |         delayed_move_time = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |         active_extruder_parked = true; |  |  |  |         active_extruder_parked = true; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |       #else |  |  |  |       #else | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |         HOMEAXIS(X); |  |  |  |         HOMEAXIS(X); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |       #endif |  |  |  |       #endif | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |       #if ENABLED(DEBUG_LEVELING_FEATURE) |  |  |  |       #if ENABLED(DEBUG_LEVELING_FEATURE) | 
			
		
	
		
		
			
				
					
					|  |  |  |         if (DEBUGGING(LEVELING)) DEBUG_POS("> homeX", current_position); |  |  |  |         if (DEBUGGING(LEVELING)) DEBUG_POS("> homeX", current_position); | 
			
		
	
		
		
			
				
					
					|  |  |  |       #endif |  |  |  |       #endif | 
			
		
	
	
		
		
			
				
					|  |  | @ -7446,10 +7460,8 @@ inline void invalid_extruder_error(const uint8_t &e) { | 
			
		
	
		
		
			
				
					
					|  |  |  | void tool_change(const uint8_t tmp_extruder, const float fr_mm_s/*=0.0*/, bool no_move/*=false*/) { |  |  |  | void tool_change(const uint8_t tmp_extruder, const float fr_mm_s/*=0.0*/, bool no_move/*=false*/) { | 
			
		
	
		
		
			
				
					
					|  |  |  |   #if ENABLED(MIXING_EXTRUDER) && MIXING_VIRTUAL_TOOLS > 1 |  |  |  |   #if ENABLED(MIXING_EXTRUDER) && MIXING_VIRTUAL_TOOLS > 1 | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     if (tmp_extruder >= MIXING_VIRTUAL_TOOLS) { |  |  |  |     if (tmp_extruder >= MIXING_VIRTUAL_TOOLS) | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       invalid_extruder_error(tmp_extruder); |  |  |  |       return invalid_extruder_error(tmp_extruder); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |       return; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     } |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     // T0-Tnnn: Switch virtual tool by changing the mix
 |  |  |  |     // T0-Tnnn: Switch virtual tool by changing the mix
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     for (uint8_t j = 0; j < MIXING_STEPPERS; j++) |  |  |  |     for (uint8_t j = 0; j < MIXING_STEPPERS; j++) | 
			
		
	
	
		
		
			
				
					|  |  | @ -7459,10 +7471,8 @@ void tool_change(const uint8_t tmp_extruder, const float fr_mm_s/*=0.0*/, bool n | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |     #if HOTENDS > 1 |  |  |  |     #if HOTENDS > 1 | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |       if (tmp_extruder >= EXTRUDERS) { |  |  |  |       if (tmp_extruder >= EXTRUDERS) | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         invalid_extruder_error(tmp_extruder); |  |  |  |         return invalid_extruder_error(tmp_extruder); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |         return; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |       } |  |  |  |  | 
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |       float old_feedrate_mm_s = feedrate_mm_s; |  |  |  |       float old_feedrate_mm_s = feedrate_mm_s; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -7490,22 +7500,28 @@ void tool_change(const uint8_t tmp_extruder, const float fr_mm_s/*=0.0*/, bool n | 
			
		
	
		
		
			
				
					
					|  |  |  |             } |  |  |  |             } | 
			
		
	
		
		
			
				
					
					|  |  |  |           #endif |  |  |  |           #endif | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |           if (dual_x_carriage_mode == DXC_AUTO_PARK_MODE && IsRunning() && |  |  |  |           const float xhome = x_home_pos(active_extruder); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |               (delayed_move_time || current_position[X_AXIS] != x_home_pos(active_extruder)) |  |  |  |           if (dual_x_carriage_mode == DXC_AUTO_PARK_MODE | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |               && IsRunning() | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |               && (delayed_move_time || current_position[X_AXIS] != xhome) | 
			
		
	
		
		
			
				
					
					|  |  |  |           ) { |  |  |  |           ) { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             float raised_z = current_position[Z_AXIS] + TOOLCHANGE_PARK_ZLIFT; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             #if ENABLED(max_software_endstops) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |               NOMORE(raised_z, soft_endstop_max[Z_AXIS]); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             #endif | 
			
		
	
		
		
			
				
					
					|  |  |  |             #if ENABLED(DEBUG_LEVELING_FEATURE) |  |  |  |             #if ENABLED(DEBUG_LEVELING_FEATURE) | 
			
		
	
		
		
			
				
					
					|  |  |  |               if (DEBUGGING(LEVELING)) { |  |  |  |               if (DEBUGGING(LEVELING)) { | 
			
		
	
		
		
			
				
					
					|  |  |  |                 SERIAL_ECHOPAIR("Raise to ", current_position[Z_AXIS] + TOOLCHANGE_PARK_ZLIFT); SERIAL_EOL; |  |  |  |                 SERIAL_ECHOLNPAIR("Raise to ", raised_z); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                 SERIAL_ECHOPAIR("MoveX to ", x_home_pos(active_extruder)); SERIAL_EOL; |  |  |  |                 SERIAL_ECHOLNPAIR("MoveX to ", xhome); | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                 SERIAL_ECHOPAIR("Lower to ", current_position[Z_AXIS]); SERIAL_EOL; |  |  |  |                 SERIAL_ECHOLNPAIR("Lower to ", current_position[Z_AXIS]); | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |               } |  |  |  |               } | 
			
		
	
		
		
			
				
					
					|  |  |  |             #endif |  |  |  |             #endif | 
			
		
	
		
		
			
				
					
					|  |  |  |             // Park old head: 1) raise 2) move to park position 3) lower
 |  |  |  |             // Park old head: 1) raise 2) move to park position 3) lower
 | 
			
		
	
		
		
			
				
					
					|  |  |  |             for (uint8_t i = 0; i < 3; i++) |  |  |  |             for (uint8_t i = 0; i < 3; i++) | 
			
		
	
		
		
			
				
					
					|  |  |  |               planner.buffer_line( |  |  |  |               planner.buffer_line( | 
			
		
	
		
		
			
				
					
					|  |  |  |                 i == 0 ? current_position[X_AXIS] : x_home_pos(active_extruder), |  |  |  |                 i == 0 ? current_position[X_AXIS] : xhome, | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |                 current_position[Y_AXIS], |  |  |  |                 current_position[Y_AXIS], | 
			
		
	
		
		
			
				
					
					|  |  |  |                 current_position[Z_AXIS] + (i == 2 ? 0 : TOOLCHANGE_PARK_ZLIFT), |  |  |  |                 i == 2 ? current_position[Z_AXIS] : raised_z, | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |                 current_position[E_AXIS], |  |  |  |                 current_position[E_AXIS], | 
			
		
	
		
		
			
				
					
					|  |  |  |                 planner.max_feedrate_mm_s[i == 1 ? X_AXIS : Z_AXIS], |  |  |  |                 planner.max_feedrate_mm_s[i == 1 ? X_AXIS : Z_AXIS], | 
			
		
	
		
		
			
				
					
					|  |  |  |                 active_extruder |  |  |  |                 active_extruder | 
			
		
	
	
		
		
			
				
					|  |  | @ -7513,9 +7529,11 @@ void tool_change(const uint8_t tmp_extruder, const float fr_mm_s/*=0.0*/, bool n | 
			
		
	
		
		
			
				
					
					|  |  |  |             stepper.synchronize(); |  |  |  |             stepper.synchronize(); | 
			
		
	
		
		
			
				
					
					|  |  |  |           } |  |  |  |           } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |           // apply Y & Z extruder offset (x offset is already used in determining home pos)
 |  |  |  |           // Apply Y & Z extruder offset (X offset is used as home pos with Dual X)
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |           current_position[Y_AXIS] -= hotend_offset[Y_AXIS][active_extruder] - hotend_offset[Y_AXIS][tmp_extruder]; |  |  |  |           current_position[Y_AXIS] -= hotend_offset[Y_AXIS][active_extruder] - hotend_offset[Y_AXIS][tmp_extruder]; | 
			
		
	
		
		
			
				
					
					|  |  |  |           current_position[Z_AXIS] -= hotend_offset[Z_AXIS][active_extruder] - hotend_offset[Z_AXIS][tmp_extruder]; |  |  |  |           current_position[Z_AXIS] -= hotend_offset[Z_AXIS][active_extruder] - hotend_offset[Z_AXIS][tmp_extruder]; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |           // Activate the new extruder
 | 
			
		
	
		
		
			
				
					
					|  |  |  |           active_extruder = tmp_extruder; |  |  |  |           active_extruder = tmp_extruder; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |           // This function resets the max/min values - the current position may be overwritten below.
 |  |  |  |           // This function resets the max/min values - the current position may be overwritten below.
 | 
			
		
	
	
		
		
			
				
					|  |  | @ -7530,7 +7548,9 @@ void tool_change(const uint8_t tmp_extruder, const float fr_mm_s/*=0.0*/, bool n | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |           switch (dual_x_carriage_mode) { |  |  |  |           switch (dual_x_carriage_mode) { | 
			
		
	
		
		
			
				
					
					|  |  |  |             case DXC_FULL_CONTROL_MODE: |  |  |  |             case DXC_FULL_CONTROL_MODE: | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |               // New current position is the position of the activated extruder
 | 
			
		
	
		
		
			
				
					
					|  |  |  |               current_position[X_AXIS] = LOGICAL_X_POSITION(inactive_extruder_x_pos); |  |  |  |               current_position[X_AXIS] = LOGICAL_X_POSITION(inactive_extruder_x_pos); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |               // Save the inactive extruder's position (from the old current_position)
 | 
			
		
	
		
		
			
				
					
					|  |  |  |               inactive_extruder_x_pos = RAW_X_POSITION(destination[X_AXIS]); |  |  |  |               inactive_extruder_x_pos = RAW_X_POSITION(destination[X_AXIS]); | 
			
		
	
		
		
			
				
					
					|  |  |  |               break; |  |  |  |               break; | 
			
		
	
		
		
			
				
					
					|  |  |  |             case DXC_AUTO_PARK_MODE: |  |  |  |             case DXC_AUTO_PARK_MODE: | 
			
		
	
	
		
		
			
				
					|  |  | @ -7544,7 +7564,10 @@ void tool_change(const uint8_t tmp_extruder, const float fr_mm_s/*=0.0*/, bool n | 
			
		
	
		
		
			
				
					
					|  |  |  |               delayed_move_time = 0; |  |  |  |               delayed_move_time = 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |               break; |  |  |  |               break; | 
			
		
	
		
		
			
				
					
					|  |  |  |             case DXC_DUPLICATION_MODE: |  |  |  |             case DXC_DUPLICATION_MODE: | 
			
		
	
		
		
			
				
					
					|  |  |  |               active_extruder_parked = (active_extruder == 0); // this triggers the second extruder to move into the duplication position
 |  |  |  |               // If the new extruder is the left one, set it "parked"
 | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |               // This triggers the second extruder to move into the duplication position
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |               active_extruder_parked = (active_extruder == 0); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |               if (active_extruder_parked) |  |  |  |               if (active_extruder_parked) | 
			
		
	
		
		
			
				
					
					|  |  |  |                 current_position[X_AXIS] = LOGICAL_X_POSITION(inactive_extruder_x_pos); |  |  |  |                 current_position[X_AXIS] = LOGICAL_X_POSITION(inactive_extruder_x_pos); | 
			
		
	
		
		
			
				
					
					|  |  |  |               else |  |  |  |               else | 
			
		
	
	
		
		
			
				
					|  |  | @ -7569,9 +7592,7 @@ void tool_change(const uint8_t tmp_extruder, const float fr_mm_s/*=0.0*/, bool n | 
			
		
	
		
		
			
				
					
					|  |  |  |             float z_diff = hotend_offset[Z_AXIS][active_extruder] - hotend_offset[Z_AXIS][tmp_extruder], |  |  |  |             float z_diff = hotend_offset[Z_AXIS][active_extruder] - hotend_offset[Z_AXIS][tmp_extruder], | 
			
		
	
		
		
			
				
					
					|  |  |  |                   z_raise = 0.3 + (z_diff > 0.0 ? z_diff : 0.0); |  |  |  |                   z_raise = 0.3 + (z_diff > 0.0 ? z_diff : 0.0); | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |             set_destination_to_current(); |  |  |  |             // Always raise by some amount (destination copied from current_position earlier)
 | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |             // Always raise by some amount
 |  |  |  |  | 
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  |             destination[Z_AXIS] += z_raise; |  |  |  |             destination[Z_AXIS] += z_raise; | 
			
		
	
		
		
			
				
					
					|  |  |  |             planner.buffer_line_kinematic(destination, planner.max_feedrate_mm_s[Z_AXIS], active_extruder); |  |  |  |             planner.buffer_line_kinematic(destination, planner.max_feedrate_mm_s[Z_AXIS], active_extruder); | 
			
		
	
		
		
			
				
					
					|  |  |  |             stepper.synchronize(); |  |  |  |             stepper.synchronize(); | 
			
		
	
	
		
		
			
				
					|  |  | @ -9260,8 +9281,11 @@ void set_current_from_steppers_for_axis(const AxisEnum axis) { | 
			
		
	
		
		
			
				
					
					|  |  |  |               current_position[Z_AXIS], |  |  |  |               current_position[Z_AXIS], | 
			
		
	
		
		
			
				
					
					|  |  |  |               current_position[E_AXIS] |  |  |  |               current_position[E_AXIS] | 
			
		
	
		
		
			
				
					
					|  |  |  |             ); |  |  |  |             ); | 
			
		
	
		
		
			
				
					
					|  |  |  |             planner.buffer_line(current_position[X_AXIS] + duplicate_extruder_x_offset, |  |  |  |             planner.buffer_line( | 
			
				
				
			
		
	
		
		
			
				
					
					|  |  |  |                              current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], planner.max_feedrate_mm_s[X_AXIS], 1); |  |  |  |               current_position[X_AXIS] + duplicate_extruder_x_offset, | 
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |               current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |               planner.max_feedrate_mm_s[X_AXIS], 1 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |             ); | 
			
		
	
		
		
			
				
					
					|  |  |  |             SYNC_PLAN_POSITION_KINEMATIC(); |  |  |  |             SYNC_PLAN_POSITION_KINEMATIC(); | 
			
		
	
		
		
			
				
					
					|  |  |  |             stepper.synchronize(); |  |  |  |             stepper.synchronize(); | 
			
		
	
		
		
			
				
					
					|  |  |  |             extruder_duplication_enabled = true; |  |  |  |             extruder_duplication_enabled = true; | 
			
		
	
	
		
		
			
				
					|  |  | 
 |