@ -249,7 +249,7 @@ int EtoPPressure=0;
 
			
		
	
		
			
				
					float  delta [ 3 ]  =  { 0.0 ,  0.0 ,  0.0 } ;  
			
		
	
		
			
				
					# endif  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					//===========================================================================
  
			
		
	
		
			
				
					//=============================private variables=============================
  
			
		
	
		
			
				
					//===========================================================================
  
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -492,6 +492,10 @@ void setup()
 
			
		
	
		
			
				
					  # if defined(CONTROLLERFAN_PIN) && CONTROLLERFAN_PIN > -1 
 
			
		
	
		
			
				
					    SET_OUTPUT ( CONTROLLERFAN_PIN ) ;  //Set pin used for driver cooling fan
 
 
			
		
	
		
			
				
					  # endif 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					  # ifdef DIGIPOT_I2C 
 
			
		
	
		
			
				
					    digipot_i2c_init ( ) ; 
 
			
		
	
		
			
				
					  # endif 
 
			
		
	
		
			
				
					}  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					
 
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -789,7 +793,7 @@ static unsigned long delayed_move_time = 0; // used in mode 1
 
			
		
	
		
			
				
					static  float  duplicate_extruder_x_offset  =  DEFAULT_DUPLICATION_X_OFFSET ;  // used in mode 2
  
			
		
	
		
			
				
					static  float  duplicate_extruder_temp_offset  =  0 ;  // used in mode 2
  
			
		
	
		
			
				
					bool  extruder_duplication_enabled  =  false ;  // used in mode 2
  
			
		
	
		
			
				
					# endif  //DUAL_X_CARRIAGE      
 
			
		
	
		
			
				
					# endif  //DUAL_X_CARRIAGE 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					static  void  axis_is_at_home ( int  axis )  {  
			
		
	
		
			
				
					# ifdef DUAL_X_CARRIAGE  
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -802,8 +806,8 @@ static void axis_is_at_home(int axis) {
 
			
		
	
		
			
				
					    } 
 
			
		
	
		
			
				
					    else  if  ( dual_x_carriage_mode  = =  DXC_DUPLICATION_MODE  & &  active_extruder  = =  0 )  { 
 
			
		
	
		
			
				
					      current_position [ X_AXIS ]  =  base_home_pos ( X_AXIS )  +  add_homeing [ X_AXIS ] ; 
 
			
		
	
		
			
				
					      min_pos [ X_AXIS ]  =           base_min_pos ( X_AXIS )  +  add_homeing [ X_AXIS ] ;   
 
			
		
	
		
			
				
					      max_pos [ X_AXIS ]  =           min ( base_max_pos ( X_AXIS )  +  add_homeing [ X_AXIS ] ,   
 
			
		
	
		
			
				
					      min_pos [ X_AXIS ]  =           base_min_pos ( X_AXIS )  +  add_homeing [ X_AXIS ] ; 
 
			
		
	
		
			
				
					      max_pos [ X_AXIS ]  =           min ( base_max_pos ( X_AXIS )  +  add_homeing [ X_AXIS ] , 
 
			
		
	
		
			
				
					                                  max ( extruder_offset [ X_AXIS ] [ 1 ] ,  X2_MAX_POS )  -  duplicate_extruder_x_offset ) ; 
 
			
		
	
		
			
				
					      return ; 
 
			
		
	
		
			
				
					    } 
 
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -895,7 +899,7 @@ static void run_z_probe() {
 
			
		
	
		
			
				
					    st_synchronize ( ) ; 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    // move back down slowly to find bed
 
 
			
		
	
		
			
				
					    feedrate  =  homing_feedrate [ Z_AXIS ] / 4 ;   
 
			
		
	
		
			
				
					    feedrate  =  homing_feedrate [ Z_AXIS ] / 4 ; 
 
			
		
	
		
			
				
					    zPosition  - =  home_retract_mm ( Z_AXIS )  *  2 ; 
 
			
		
	
		
			
				
					    plan_buffer_line ( current_position [ X_AXIS ] ,  current_position [ Y_AXIS ] ,  zPosition ,  current_position [ E_AXIS ] ,  feedrate / 60 ,  active_extruder ) ; 
 
			
		
	
		
			
				
					    st_synchronize ( ) ; 
 
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -992,7 +996,7 @@ static void homeaxis(int axis) {
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    current_position [ axis ]  =  0 ; 
 
			
		
	
		
			
				
					    plan_set_position ( current_position [ X_AXIS ] ,  current_position [ Y_AXIS ] ,  current_position [ Z_AXIS ] ,  current_position [ E_AXIS ] ) ; 
 
			
		
	
		
			
				
						  
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    // Engage Servo endstop if enabled
 
 
			
		
	
		
			
				
					    # ifdef SERVO_ENDSTOPS 
 
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -1050,7 +1054,7 @@ static void homeaxis(int axis) {
 
			
		
	
		
			
				
					# if defined (ENABLE_AUTO_BED_LEVELING) && (PROBE_SERVO_DEACTIVATION_DELAY > 0)  
			
		
	
		
			
				
					    if  ( axis = = Z_AXIS )  retract_z_probe ( ) ; 
 
			
		
	
		
			
				
					# endif  
			
		
	
		
			
				
					      
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					  } 
 
			
		
	
		
			
				
					}  
			
		
	
		
			
				
					# define HOMEAXIS(LETTER) homeaxis(LETTER##_AXIS)  
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -1124,7 +1128,7 @@ void process_commands()
 
			
		
	
		
			
				
					        destination [ Y_AXIS ] = current_position [ Y_AXIS ] ; 
 
			
		
	
		
			
				
					        destination [ Z_AXIS ] = current_position [ Z_AXIS ] ; 
 
			
		
	
		
			
				
					        current_position [ Z_AXIS ] + = retract_zlift ; 
 
			
		
	
		
			
				
					        destination [ E_AXIS ] = current_position [ E_AXIS ] + retract_length + retract_recover_length ;   
 
			
		
	
		
			
				
					        destination [ E_AXIS ] = current_position [ E_AXIS ] + retract_length + retract_recover_length ; 
 
			
		
	
		
			
				
					        feedrate = retract_recover_feedrate ; 
 
			
		
	
		
			
				
					        retracted = false ; 
 
			
		
	
		
			
				
					        prepare_move ( ) ; 
 
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -1238,10 +1242,10 @@ void process_commands()
 
			
		
	
		
			
				
					        // reset state used by the different modes
 
 
			
		
	
		
			
				
					        memcpy ( raised_parked_position ,  current_position ,  sizeof ( raised_parked_position ) ) ; 
 
			
		
	
		
			
				
					        delayed_move_time  =  0 ; 
 
			
		
	
		
			
				
					        active_extruder_parked  =  true ;   
 
			
		
	
		
			
				
					      # else        
 
			
		
	
		
			
				
					        active_extruder_parked  =  true ; 
 
			
		
	
		
			
				
					      # else 
 
			
		
	
		
			
				
					        HOMEAXIS ( X ) ; 
 
			
		
	
		
			
				
					      # endif           
 
			
		
	
		
			
				
					      # endif 
 
			
		
	
		
			
				
					      } 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					      if ( ( home_all_axis )  | |  ( code_seen ( axis_codes [ Y_AXIS ] ) ) )  { 
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -1260,7 +1264,7 @@ void process_commands()
 
			
		
	
		
			
				
					          current_position [ Y_AXIS ] = code_value ( ) + add_homeing [ 1 ] ; 
 
			
		
	
		
			
				
					        } 
 
			
		
	
		
			
				
					      } 
 
			
		
	
		
			
				
					        
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					      # if Z_HOME_DIR < 0                       // If homing towards BED do Z last
 
 
			
		
	
		
			
				
					        # ifndef Z_SAFE_HOMING 
 
			
		
	
		
			
				
					          if ( ( home_all_axis )  | |  ( code_seen ( axis_codes [ Z_AXIS ] ) ) )  { 
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -1272,14 +1276,14 @@ void process_commands()
 
			
		
	
		
			
				
					            # endif 
 
			
		
	
		
			
				
					            HOMEAXIS ( Z ) ; 
 
			
		
	
		
			
				
					          } 
 
			
		
	
		
			
				
					        # else                       // Z Safe mode activated.   
 
			
		
	
		
			
				
					        # else                       // Z Safe mode activated. 
 
			
		
	
		
			
				
					          if ( home_all_axis )  { 
 
			
		
	
		
			
				
					            destination [ X_AXIS ]  =  round ( Z_SAFE_HOMING_X_POINT  -  X_PROBE_OFFSET_FROM_EXTRUDER ) ; 
 
			
		
	
		
			
				
					            destination [ Y_AXIS ]  =  round ( Z_SAFE_HOMING_Y_POINT  -  Y_PROBE_OFFSET_FROM_EXTRUDER ) ; 
 
			
		
	
		
			
				
					            destination [ Z_AXIS ]  =  Z_RAISE_BEFORE_HOMING  *  home_dir ( Z_AXIS )  *  ( - 1 ) ;     // Set destination away from bed
 
 
			
		
	
		
			
				
					            feedrate  =  XY_TRAVEL_SPEED ; 
 
			
		
	
		
			
				
					            current_position [ Z_AXIS ]  =  0 ; 
 
			
		
	
		
			
				
								  
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					            plan_set_position ( current_position [ X_AXIS ] ,  current_position [ Y_AXIS ] ,  current_position [ Z_AXIS ] ,  current_position [ E_AXIS ] ) ; 
 
			
		
	
		
			
				
					            plan_buffer_line ( destination [ X_AXIS ] ,  destination [ Y_AXIS ] ,  destination [ Z_AXIS ] ,  destination [ E_AXIS ] ,  feedrate ,  active_extruder ) ; 
 
			
		
	
		
			
				
					            st_synchronize ( ) ; 
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -1297,7 +1301,7 @@ void process_commands()
 
			
		
	
		
			
				
					              & &  ( current_position [ Y_AXIS ] + Y_PROBE_OFFSET_FROM_EXTRUDER  < =  Y_MAX_POS ) )  { 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					              current_position [ Z_AXIS ]  =  0 ; 
 
			
		
	
		
			
				
					              plan_set_position ( current_position [ X_AXIS ] ,  current_position [ Y_AXIS ] ,  current_position [ Z_AXIS ] ,  current_position [ E_AXIS ] ) ; 			   
 
			
		
	
		
			
				
					              plan_set_position ( current_position [ X_AXIS ] ,  current_position [ Y_AXIS ] ,  current_position [ Z_AXIS ] ,  current_position [ E_AXIS ] ) ; 
 
			
		
	
		
			
				
					              destination [ Z_AXIS ]  =  Z_RAISE_BEFORE_HOMING  *  home_dir ( Z_AXIS )  *  ( - 1 ) ;     // Set destination away from bed
 
 
			
		
	
		
			
				
					              feedrate  =  max_feedrate [ Z_AXIS ] ; 
 
			
		
	
		
			
				
					              plan_buffer_line ( destination [ X_AXIS ] ,  destination [ Y_AXIS ] ,  destination [ Z_AXIS ] ,  destination [ E_AXIS ] ,  feedrate ,  active_extruder ) ; 
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -1317,8 +1321,8 @@ void process_commands()
 
			
		
	
		
			
				
					        # endif 
 
			
		
	
		
			
				
					      # endif 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					        
			
		
	
		
			
				
					       
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					      if ( code_seen ( axis_codes [ Z_AXIS ] ) )  { 
 
			
		
	
		
			
				
					        if ( code_value_long ( )  ! =  0 )  { 
 
			
		
	
		
			
				
					          current_position [ Z_AXIS ] = code_value ( ) + add_homeing [ 2 ] ; 
 
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -1364,26 +1368,26 @@ void process_commands()
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					            feedrate  =  homing_feedrate [ Z_AXIS ] ; 
 
			
		
	
		
			
				
					# ifdef ACCURATE_BED_LEVELING  
			
		
	
		
			
				
					              
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					            int  xGridSpacing  =  ( RIGHT_PROBE_BED_POSITION  -  LEFT_PROBE_BED_POSITION )  /  ( ACCURATE_BED_LEVELING_POINTS - 1 ) ; 
 
			
		
	
		
			
				
					            int  yGridSpacing  =  ( BACK_PROBE_BED_POSITION  -  FRONT_PROBE_BED_POSITION )  /  ( ACCURATE_BED_LEVELING_POINTS - 1 ) ; 
 
			
		
	
		
			
				
					              
			
		
	
		
			
				
					              
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					            // solve the plane equation ax + by + d = z
 
 
			
		
	
		
			
				
					            // A is the matrix with rows [x y 1] for all the probed points
 
 
			
		
	
		
			
				
					            // B is the vector of the Z positions
 
 
			
		
	
		
			
				
					            // the normal vector to the plane is formed by the coefficients of the plane equation in the standard form, which is Vx*x+Vy*y+Vz*z+d = 0
 
 
			
		
	
		
			
				
					            // so Vx = -a Vy = -b Vz = 1 (we want the vector facing towards positive Z
 
 
			
		
	
		
			
				
					              
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					            // "A" matrix of the linear system of equations
 
 
			
		
	
		
			
				
					            double  eqnAMatrix [ ACCURATE_BED_LEVELING_POINTS * ACCURATE_BED_LEVELING_POINTS * 3 ] ; 
 
			
		
	
		
			
				
					            // "B" vector of Z points
 
 
			
		
	
		
			
				
					            double  eqnBVector [ ACCURATE_BED_LEVELING_POINTS * ACCURATE_BED_LEVELING_POINTS ] ; 
 
			
		
	
		
			
				
					              
			
		
	
		
			
				
					              
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					            int  probePointCounter  =  0 ; 
 
			
		
	
		
			
				
					            bool  zig  =  true ; 
 
			
		
	
		
			
				
					              
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					            for  ( int  yProbe = FRONT_PROBE_BED_POSITION ;  yProbe  < =  BACK_PROBE_BED_POSITION ;  yProbe  + =  yGridSpacing ) 
 
			
		
	
		
			
				
					            { 
 
			
		
	
		
			
				
					              int  xProbe ,  xInc ; 
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -1400,7 +1404,7 @@ void process_commands()
 
			
		
	
		
			
				
					                xInc  =  - xGridSpacing ; 
 
			
		
	
		
			
				
					                zig  =  true ; 
 
			
		
	
		
			
				
					              } 
 
			
		
	
		
			
				
					                
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					              for  ( int  xCount = 0 ;  xCount  <  ACCURATE_BED_LEVELING_POINTS ;  xCount + + ) 
 
			
		
	
		
			
				
					              { 
 
			
		
	
		
			
				
					                if  ( probePointCounter  = =  0 ) 
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -1408,19 +1412,19 @@ void process_commands()
 
			
		
	
		
			
				
					                  // raise before probing
 
 
			
		
	
		
			
				
					                  do_blocking_move_to ( current_position [ X_AXIS ] ,  current_position [ Y_AXIS ] ,  Z_RAISE_BEFORE_PROBING ) ; 
 
			
		
	
		
			
				
					                }  else 
 
			
		
	
		
			
				
					                {                 
 
			
		
	
		
			
				
					                { 
 
			
		
	
		
			
				
					                  // raise extruder
 
 
			
		
	
		
			
				
					                  do_blocking_move_to ( current_position [ X_AXIS ] ,  current_position [ Y_AXIS ] ,  current_position [ Z_AXIS ]  +  Z_RAISE_BETWEEN_PROBINGS ) ; 
 
			
		
	
		
			
				
					                } 
 
			
		
	
		
			
				
					                  
			
		
	
		
			
				
					                  
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					                do_blocking_move_to ( xProbe  -  X_PROBE_OFFSET_FROM_EXTRUDER ,  yProbe  -  Y_PROBE_OFFSET_FROM_EXTRUDER ,  current_position [ Z_AXIS ] ) ; 
 
			
		
	
		
			
				
					      
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					                engage_z_probe ( ) ;    // Engage Z Servo endstop if available
 
 
			
		
	
		
			
				
					                run_z_probe ( ) ; 
 
			
		
	
		
			
				
					                eqnBVector [ probePointCounter ]  =  current_position [ Z_AXIS ] ; 
 
			
		
	
		
			
				
					                retract_z_probe ( ) ; 
 
			
		
	
		
			
				
					      
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					                SERIAL_PROTOCOLPGM ( " Bed x:  " ) ; 
 
			
		
	
		
			
				
					                SERIAL_PROTOCOL ( xProbe ) ; 
 
			
		
	
		
			
				
					                SERIAL_PROTOCOLPGM ( "  y:  " ) ; 
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -1428,7 +1432,7 @@ void process_commands()
 
			
		
	
		
			
				
					                SERIAL_PROTOCOLPGM ( "  z:  " ) ; 
 
			
		
	
		
			
				
					                SERIAL_PROTOCOL ( current_position [ Z_AXIS ] ) ; 
 
			
		
	
		
			
				
					                SERIAL_PROTOCOLPGM ( " \n " ) ; 
 
			
		
	
		
			
				
					                  
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					                eqnAMatrix [ probePointCounter  +  0 * ACCURATE_BED_LEVELING_POINTS * ACCURATE_BED_LEVELING_POINTS ]  =  xProbe ; 
 
			
		
	
		
			
				
					                eqnAMatrix [ probePointCounter  +  1 * ACCURATE_BED_LEVELING_POINTS * ACCURATE_BED_LEVELING_POINTS ]  =  yProbe ; 
 
			
		
	
		
			
				
					                eqnAMatrix [ probePointCounter  +  2 * ACCURATE_BED_LEVELING_POINTS * ACCURATE_BED_LEVELING_POINTS ]  =  1 ; 
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -1437,25 +1441,25 @@ void process_commands()
 
			
		
	
		
			
				
					              } 
 
			
		
	
		
			
				
					            } 
 
			
		
	
		
			
				
					            clean_up_after_endstop_move ( ) ; 
 
			
		
	
		
			
				
					              
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					            // solve lsq problem
 
 
			
		
	
		
			
				
					            double  * plane_equation_coefficients  =  qr_solve ( ACCURATE_BED_LEVELING_POINTS * ACCURATE_BED_LEVELING_POINTS ,  3 ,  eqnAMatrix ,  eqnBVector ) ; 
 
			
		
	
		
			
				
					              
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					            SERIAL_PROTOCOLPGM ( " Eqn coefficients: a:  " ) ; 
 
			
		
	
		
			
				
					            SERIAL_PROTOCOL ( plane_equation_coefficients [ 0 ] ) ; 
 
			
		
	
		
			
				
					            SERIAL_PROTOCOLPGM ( "  b:  " ) ; 
 
			
		
	
		
			
				
					            SERIAL_PROTOCOL ( plane_equation_coefficients [ 1 ] ) ; 
 
			
		
	
		
			
				
					            SERIAL_PROTOCOLPGM ( "  d:  " ) ; 
 
			
		
	
		
			
				
					            SERIAL_PROTOCOLLN ( plane_equation_coefficients [ 2 ] ) ; 
 
			
		
	
		
			
				
					              
			
		
	
		
			
				
					              
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					            set_bed_level_equation_lsq ( plane_equation_coefficients ) ; 
 
			
		
	
		
			
				
					              
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					            free ( plane_equation_coefficients ) ; 
 
			
		
	
		
			
				
					              
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					# else  // ACCURATE_BED_LEVELING not defined
  
			
		
	
		
			
				
					              
			
		
	
		
			
				
					              
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					            // prob 1
 
 
			
		
	
		
			
				
					            do_blocking_move_to ( current_position [ X_AXIS ] ,  current_position [ Y_AXIS ] ,  Z_RAISE_BEFORE_PROBING ) ; 
 
			
		
	
		
			
				
					            do_blocking_move_to ( LEFT_PROBE_BED_POSITION  -  X_PROBE_OFFSET_FROM_EXTRUDER ,  BACK_PROBE_BED_POSITION  -  Y_PROBE_OFFSET_FROM_EXTRUDER ,  current_position [ Z_AXIS ] ) ; 
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -1481,7 +1485,7 @@ void process_commands()
 
			
		
	
		
			
				
					            run_z_probe ( ) ; 
 
			
		
	
		
			
				
					            float  z_at_xLeft_yFront  =  current_position [ Z_AXIS ] ; 
 
			
		
	
		
			
				
					            retract_z_probe ( ) ; 
 
			
		
	
		
			
				
					              
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					            SERIAL_PROTOCOLPGM ( " Bed x:  " ) ; 
 
			
		
	
		
			
				
					            SERIAL_PROTOCOL ( LEFT_PROBE_BED_POSITION ) ; 
 
			
		
	
		
			
				
					            SERIAL_PROTOCOLPGM ( "  y:  " ) ; 
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -1499,7 +1503,7 @@ void process_commands()
 
			
		
	
		
			
				
					            run_z_probe ( ) ; 
 
			
		
	
		
			
				
					            float  z_at_xRight_yFront  =  current_position [ Z_AXIS ] ; 
 
			
		
	
		
			
				
					            retract_z_probe ( ) ;  // Retract Z Servo endstop if available
 
 
			
		
	
		
			
				
					              
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					            SERIAL_PROTOCOLPGM ( " Bed x:  " ) ; 
 
			
		
	
		
			
				
					            SERIAL_PROTOCOL ( RIGHT_PROBE_BED_POSITION ) ; 
 
			
		
	
		
			
				
					            SERIAL_PROTOCOLPGM ( "  y:  " ) ; 
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -1511,13 +1515,13 @@ void process_commands()
 
			
		
	
		
			
				
					            clean_up_after_endstop_move ( ) ; 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					            set_bed_level_equation ( z_at_xLeft_yFront ,  z_at_xRight_yFront ,  z_at_xLeft_yBack ) ; 
 
			
		
	
		
			
				
					           
			
		
	
		
			
				
					              
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					# endif  // ACCURATE_BED_LEVELING
  
			
		
	
		
			
				
					            st_synchronize ( ) ;              
 
			
		
	
		
			
				
					            st_synchronize ( ) ; 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					            // The following code correct the Z height difference from z-probe position and hotend tip position.
 
 
			
		
	
		
			
				
					            // The Z height on homing is measured by Z-Probe, but the probe is quite far from the hotend.   
 
			
		
	
		
			
				
					            // The Z height on homing is measured by Z-Probe, but the probe is quite far from the hotend. 
 
			
		
	
		
			
				
					            // When the bed is uneven, this height must be corrected.
 
 
			
		
	
		
			
				
					            real_z  =  float ( st_get_position ( Z_AXIS ) ) / axis_steps_per_unit [ Z_AXIS ] ;   //get the real Z (since the auto bed leveling is already correcting the plane)
 
 
			
		
	
		
			
				
					            x_tmp  =  current_position [ X_AXIS ]  +  X_PROBE_OFFSET_FROM_EXTRUDER ; 
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -1529,11 +1533,11 @@ void process_commands()
 
			
		
	
		
			
				
					            plan_set_position ( current_position [ X_AXIS ] ,  current_position [ Y_AXIS ] ,  current_position [ Z_AXIS ] ,  current_position [ E_AXIS ] ) ; 
 
			
		
	
		
			
				
					        } 
 
			
		
	
		
			
				
					        break ; 
 
			
		
	
		
			
				
					          
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					    case  30 :  // G30 Single Z Probe
 
 
			
		
	
		
			
				
					        { 
 
			
		
	
		
			
				
					            engage_z_probe ( ) ;  // Engage Z Servo endstop if available
 
 
			
		
	
		
			
				
					              
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					            st_synchronize ( ) ; 
 
			
		
	
		
			
				
					            // TODO: make sure the bed_level_rotation_matrix is identity or the planner will get set incorectly
 
 
			
		
	
		
			
				
					            setup_for_endstop_move ( ) ; 
 
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -1684,14 +1688,14 @@ void process_commands()
 
			
		
	
		
			
				
					        card . removeFile ( strchr_pointer  +  4 ) ; 
 
			
		
	
		
			
				
					      } 
 
			
		
	
		
			
				
					      break ; 
 
			
		
	
		
			
				
					    case  32 :  //M32 - Select file and start SD print   
 
			
		
	
		
			
				
					    case  32 :  //M32 - Select file and start SD print 
 
			
		
	
		
			
				
					    { 
 
			
		
	
		
			
				
					      if ( card . sdprinting )  { 
 
			
		
	
		
			
				
					        st_synchronize ( ) ; 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					      } 
 
			
		
	
		
			
				
					      starpos  =  ( strchr ( strchr_pointer  +  4 , ' * ' ) ) ;   
 
			
		
	
		
			
				
					        
			
		
	
		
			
				
					      starpos  =  ( strchr ( strchr_pointer  +  4 , ' * ' ) ) ; 
 
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					      char *  namestartpos  =  ( strchr ( strchr_pointer  +  4 , ' ! ' ) ) ;    //find ! to indicate filename string start.
 
 
			
		
	
		
			
				
					      if ( namestartpos = = NULL ) 
 
			
		
	
		
			
				
					      { 
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -1699,16 +1703,16 @@ void process_commands()
 
			
		
	
		
			
				
					      } 
 
			
		
	
		
			
				
					      else 
 
			
		
	
		
			
				
					        namestartpos + + ;  //to skip the '!'
 
 
			
		
	
		
			
				
					          
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					      if ( starpos ! = NULL ) 
 
			
		
	
		
			
				
					        * ( starpos - 1 ) = ' \0 ' ; 
 
			
		
	
		
			
				
					              
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					      bool  call_procedure = ( code_seen ( ' P ' ) ) ; 
 
			
		
	
		
			
				
					        
			
		
	
		
			
				
					      if ( strchr_pointer > namestartpos )   
 
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					      if ( strchr_pointer > namestartpos ) 
 
			
		
	
		
			
				
					        call_procedure = false ;   //false alert, 'P' found within filename
 
 
			
		
	
		
			
				
					        
			
		
	
		
			
				
					      if (  card . cardOK  )   
 
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					      if (  card . cardOK  ) 
 
			
		
	
		
			
				
					      { 
 
			
		
	
		
			
				
					        card . openFile ( namestartpos , true , ! call_procedure ) ; 
 
			
		
	
		
			
				
					        if ( code_seen ( ' S ' ) ) 
 
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -1781,7 +1785,7 @@ void process_commands()
 
			
		
	
		
			
				
					# ifdef DUAL_X_CARRIAGE  
			
		
	
		
			
				
					      if  ( dual_x_carriage_mode  = =  DXC_DUPLICATION_MODE  & &  tmp_extruder  = =  0 ) 
 
			
		
	
		
			
				
					        setTargetHotend1 ( code_value ( )  = =  0.0  ?  0.0  :  code_value ( )  +  duplicate_extruder_temp_offset ) ; 
 
			
		
	
		
			
				
					# endif             
			
		
	
		
			
				
					# endif  
			
		
	
		
			
				
					      setWatch ( ) ; 
 
			
		
	
		
			
				
					      break ; 
 
			
		
	
		
			
				
					    case  140 :  // M140 set bed temp
 
 
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -1847,7 +1851,7 @@ void process_commands()
 
			
		
	
		
			
				
					            SERIAL_PROTOCOL_F ( rawHotendTemp ( cur_extruder ) / OVERSAMPLENR , 0 ) ; 
 
			
		
	
		
			
				
					          } 
 
			
		
	
		
			
				
					        # endif 
 
			
		
	
		
			
				
							  
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					        SERIAL_PROTOCOLLN ( " " ) ; 
 
			
		
	
		
			
				
					      return ; 
 
			
		
	
		
			
				
					      break ; 
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -1865,14 +1869,14 @@ void process_commands()
 
			
		
	
		
			
				
					# ifdef DUAL_X_CARRIAGE  
			
		
	
		
			
				
					        if  ( dual_x_carriage_mode  = =  DXC_DUPLICATION_MODE  & &  tmp_extruder  = =  0 ) 
 
			
		
	
		
			
				
					          setTargetHotend1 ( code_value ( )  = =  0.0  ?  0.0  :  code_value ( )  +  duplicate_extruder_temp_offset ) ; 
 
			
		
	
		
			
				
					# endif             
			
		
	
		
			
				
					# endif  
			
		
	
		
			
				
					        CooldownNoWait  =  true ; 
 
			
		
	
		
			
				
					      }  else  if  ( code_seen ( ' R ' ) )  { 
 
			
		
	
		
			
				
					        setTargetHotend ( code_value ( ) ,  tmp_extruder ) ; 
 
			
		
	
		
			
				
					# ifdef DUAL_X_CARRIAGE  
			
		
	
		
			
				
					        if  ( dual_x_carriage_mode  = =  DXC_DUPLICATION_MODE  & &  tmp_extruder  = =  0 ) 
 
			
		
	
		
			
				
					          setTargetHotend1 ( code_value ( )  = =  0.0  ?  0.0  :  code_value ( )  +  duplicate_extruder_temp_offset ) ; 
 
			
		
	
		
			
				
					# endif             
			
		
	
		
			
				
					# endif  
			
		
	
		
			
				
					        CooldownNoWait  =  false ; 
 
			
		
	
		
			
				
					      } 
 
			
		
	
		
			
				
					      # ifdef AUTOTEMP 
 
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -2036,7 +2040,7 @@ void process_commands()
 
			
		
	
		
			
				
					            SET_OUTPUT ( SUICIDE_PIN ) ; 
 
			
		
	
		
			
				
					            WRITE ( SUICIDE_PIN ,  HIGH ) ; 
 
			
		
	
		
			
				
					        # endif 
 
			
		
	
		
			
				
					          
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					        # ifdef ULTIPANEL 
 
			
		
	
		
			
				
					          powersupply  =  true ; 
 
			
		
	
		
			
				
					          LCD_MESSAGEPGM ( WELCOME_MSG ) ; 
 
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -2193,18 +2197,18 @@ void process_commands()
 
			
		
	
		
			
				
					      # endif 
 
			
		
	
		
			
				
					      break ; 
 
			
		
	
		
			
				
					      //TODO: update for all axis, use for loop
 
 
			
		
	
		
			
				
					    # ifdef BLINKM    
 
			
		
	
		
			
				
					    # ifdef BLINKM 
 
			
		
	
		
			
				
					    case  150 :  // M150
 
 
			
		
	
		
			
				
					      { 
 
			
		
	
		
			
				
					        byte  red ; 
 
			
		
	
		
			
				
					        byte  grn ; 
 
			
		
	
		
			
				
					        byte  blu ; 
 
			
		
	
		
			
				
					          
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					        if ( code_seen ( ' R ' ) )  red  =  code_value ( ) ; 
 
			
		
	
		
			
				
					        if ( code_seen ( ' U ' ) )  grn  =  code_value ( ) ; 
 
			
		
	
		
			
				
					        if ( code_seen ( ' B ' ) )  blu  =  code_value ( ) ; 
 
			
		
	
		
			
				
					          
			
		
	
		
			
				
					        SendColors ( red , grn , blu ) ;          
 
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					        SendColors ( red , grn , blu ) ; 
 
			
		
	
		
			
				
					      } 
 
			
		
	
		
			
				
					      break ; 
 
			
		
	
		
			
				
					    # endif  //BLINKM
 
 
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -2354,7 +2358,7 @@ void process_commands()
 
			
		
	
		
			
				
					      { 
 
			
		
	
		
			
				
					        extruder_offset [ Z_AXIS ] [ tmp_extruder ]  =  code_value ( ) ; 
 
			
		
	
		
			
				
					      } 
 
			
		
	
		
			
				
					      # endif         
 
			
		
	
		
			
				
					      # endif 
 
			
		
	
		
			
				
					      SERIAL_ECHO_START ; 
 
			
		
	
		
			
				
					      SERIAL_ECHOPGM ( MSG_HOTEND_OFFSET ) ; 
 
			
		
	
		
			
				
					      for ( tmp_extruder  =  0 ;  tmp_extruder  <  EXTRUDERS ;  tmp_extruder + + ) 
 
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -2387,17 +2391,17 @@ void process_commands()
 
			
		
	
		
			
				
					      } 
 
			
		
	
		
			
				
					    } 
 
			
		
	
		
			
				
					    break ; 
 
			
		
	
		
			
				
						  
			
		
	
		
			
				
					
  
			
		
	
		
			
				
						case  226 :  // M226 P<pin number> S<pin state>- Wait until the specified pin reaches the state required
 
 
			
		
	
		
			
				
						{ 
 
			
		
	
		
			
				
					      if ( code_seen ( ' P ' ) ) { 
 
			
		
	
		
			
				
					        int  pin_number  =  code_value ( ) ;  // pin number
 
 
			
		
	
		
			
				
					        int  pin_state  =  - 1 ;  // required pin state - default is inverted
 
 
			
		
	
		
			
				
					          
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					        if ( code_seen ( ' S ' ) )  pin_state  =  code_value ( ) ;  // required pin state
 
 
			
		
	
		
			
				
					        
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					        if ( pin_state  > =  - 1  & &  pin_state  < =  1 ) { 
 
			
		
	
		
			
				
					          
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					          for ( int8_t  i  =  0 ;  i  <  ( int8_t ) sizeof ( sensitive_pins ) ;  i + + ) 
 
			
		
	
		
			
				
					          { 
 
			
		
	
		
			
				
					            if  ( sensitive_pins [ i ]  = =  pin_number ) 
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -2406,28 +2410,28 @@ void process_commands()
 
			
		
	
		
			
				
					              break ; 
 
			
		
	
		
			
				
					            } 
 
			
		
	
		
			
				
					          } 
 
			
		
	
		
			
				
					          
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					          if  ( pin_number  >  - 1 ) 
 
			
		
	
		
			
				
					          { 
 
			
		
	
		
			
				
					            st_synchronize ( ) ; 
 
			
		
	
		
			
				
					              
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					            pinMode ( pin_number ,  INPUT ) ; 
 
			
		
	
		
			
				
					              
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					            int  target ; 
 
			
		
	
		
			
				
					            switch ( pin_state ) { 
 
			
		
	
		
			
				
					            case  1 : 
 
			
		
	
		
			
				
					              target  =  HIGH ; 
 
			
		
	
		
			
				
					              break ; 
 
			
		
	
		
			
				
					              
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					            case  0 : 
 
			
		
	
		
			
				
					              target  =  LOW ; 
 
			
		
	
		
			
				
					              break ; 
 
			
		
	
		
			
				
					              
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					            case  - 1 : 
 
			
		
	
		
			
				
					              target  =  ! digitalRead ( pin_number ) ; 
 
			
		
	
		
			
				
					              break ; 
 
			
		
	
		
			
				
					            } 
 
			
		
	
		
			
				
					              
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					            while ( digitalRead ( pin_number )  ! =  target ) { 
 
			
		
	
		
			
				
					              manage_heater ( ) ; 
 
			
		
	
		
			
				
					              manage_inactivity ( ) ; 
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -2437,7 +2441,7 @@ void process_commands()
 
			
		
	
		
			
				
					        } 
 
			
		
	
		
			
				
					      } 
 
			
		
	
		
			
				
					    } 
 
			
		
	
		
			
				
					    break ; 	 
 
			
		
	
		
			
				
					    break ; 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    # if NUM_SERVOS > 0 
 
			
		
	
		
			
				
					    case  280 :  // M280 - set servo position absolute. P: servo index, S: angle or microseconds
 
 
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -2615,13 +2619,13 @@ void process_commands()
 
			
		
	
		
			
				
					        engage_z_probe ( ) ;     // Engage Z Servo endstop if available
 
 
			
		
	
		
			
				
					    } 
 
			
		
	
		
			
				
					    break ; 
 
			
		
	
		
			
				
					      
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					    case  402 : 
 
			
		
	
		
			
				
					    { 
 
			
		
	
		
			
				
					        retract_z_probe ( ) ;     // Retract Z Servo endstop if enabled
 
 
			
		
	
		
			
				
					    } 
 
			
		
	
		
			
				
					    break ; 
 
			
		
	
		
			
				
					# endif       
			
		
	
		
			
				
					# endif  
			
		
	
		
			
				
					    case  500 :  // M500 Store settings in EEPROM
 
 
			
		
	
		
			
				
					    { 
 
			
		
	
		
			
				
					        Config_StoreSettings ( ) ; 
 
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -2783,14 +2787,14 @@ void process_commands()
 
			
		
	
		
			
				
					              //    M605 S0: Full control mode. The slicer has full control over x-carriage movement
 
 
			
		
	
		
			
				
					              //    M605 S1: Auto-park mode. The inactive head will auto park/unpark without slicer involvement
 
 
			
		
	
		
			
				
					              //    M605 S2 [Xnnn] [Rmmm]: Duplication mode. The second extruder will duplicate the first with nnn
 
 
			
		
	
		
			
				
					              //                         millimeters x-offset and an optional differential hotend temperature of   
 
			
		
	
		
			
				
					              //                         millimeters x-offset and an optional differential hotend temperature of 
 
			
		
	
		
			
				
					              //                         mmm degrees. E.g., with "M605 S2 X100 R2" the second extruder will duplicate
 
 
			
		
	
		
			
				
					              //                         the first with a spacing of 100mm in the x direction and 2 degrees hotter.
 
 
			
		
	
		
			
				
					              //
 
 
			
		
	
		
			
				
					              //    Note: the X axis should be homed after changing dual x-carriage mode.
 
 
			
		
	
		
			
				
					    { 
 
			
		
	
		
			
				
					        st_synchronize ( ) ; 
 
			
		
	
		
			
				
					          
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					        if  ( code_seen ( ' S ' ) ) 
 
			
		
	
		
			
				
					          dual_x_carriage_mode  =  code_value ( ) ; 
 
			
		
	
		
			
				
					
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -2801,7 +2805,7 @@ void process_commands()
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					          if  ( code_seen ( ' R ' ) ) 
 
			
		
	
		
			
				
					            duplicate_extruder_temp_offset  =  code_value ( ) ; 
 
			
		
	
		
			
				
					              
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					          SERIAL_ECHO_START ; 
 
			
		
	
		
			
				
					          SERIAL_ECHOPGM ( MSG_HOTEND_OFFSET ) ; 
 
			
		
	
		
			
				
					          SERIAL_ECHO ( "   " ) ; 
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -2817,13 +2821,13 @@ void process_commands()
 
			
		
	
		
			
				
					        { 
 
			
		
	
		
			
				
					          dual_x_carriage_mode  =  DEFAULT_DUAL_X_CARRIAGE_MODE ; 
 
			
		
	
		
			
				
					        } 
 
			
		
	
		
			
				
					          
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					        active_extruder_parked  =  false ; 
 
			
		
	
		
			
				
					        extruder_duplication_enabled  =  false ; 
 
			
		
	
		
			
				
					        delayed_move_time  =  0 ; 
 
			
		
	
		
			
				
					    } 
 
			
		
	
		
			
				
					    break ; 
 
			
		
	
		
			
				
					    # endif  //DUAL_X_CARRIAGE           
 
			
		
	
		
			
				
					    # endif  //DUAL_X_CARRIAGE 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					    case  907 :  // M907 Set digital trimpot motor current using axis codes.
 
 
			
		
	
		
			
				
					    { 
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -2841,6 +2845,12 @@ void process_commands()
 
			
		
	
		
			
				
					      # ifdef MOTOR_CURRENT_PWM_E_PIN 
 
			
		
	
		
			
				
					        if ( code_seen ( ' E ' ) )  digipot_current ( 2 ,  code_value ( ) ) ; 
 
			
		
	
		
			
				
					      # endif 
 
			
		
	
		
			
				
					      # ifdef DIGIPOT_I2C 
 
			
		
	
		
			
				
					        // this one uses actual amps in floating point
 
 
			
		
	
		
			
				
					        for ( int  i = 0 ; i < NUM_AXIS ; i + + )  if ( code_seen ( axis_codes [ i ] ) )  digipot_i2c_set_current ( i ,  code_value ( ) ) ; 
 
			
		
	
		
			
				
					        // for each additional extruder (named B,C,D,E..., channels 4,5,6,7...)
 
 
			
		
	
		
			
				
					        for ( int  i = NUM_AXIS ; i < DIGIPOT_I2C_NUM_CHANNELS ; i + + )  if ( code_seen ( ' B ' + i - NUM_AXIS ) )  digipot_i2c_set_current ( i ,  code_value ( ) ) ; 
 
			
		
	
		
			
				
					      # endif 
 
			
		
	
		
			
				
					    } 
 
			
		
	
		
			
				
					    break ; 
 
			
		
	
		
			
				
					    case  908 :  // M908 Control digital trimpot directly.
 
 
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -2913,19 +2923,19 @@ void process_commands()
 
			
		
	
		
			
				
					        // Save current position to return to after applying extruder offset
 
 
			
		
	
		
			
				
					        memcpy ( destination ,  current_position ,  sizeof ( destination ) ) ; 
 
			
		
	
		
			
				
					      # ifdef DUAL_X_CARRIAGE 
 
			
		
	
		
			
				
					        if  ( dual_x_carriage_mode  = =  DXC_AUTO_PARK_MODE  & &  Stopped  = =  false  & &   
 
			
		
	
		
			
				
					        if  ( dual_x_carriage_mode  = =  DXC_AUTO_PARK_MODE  & &  Stopped  = =  false  & & 
 
			
		
	
		
			
				
					            ( delayed_move_time  ! =  0  | |  current_position [ X_AXIS ]  ! =  x_home_pos ( active_extruder ) ) ) 
 
			
		
	
		
			
				
					        { 
 
			
		
	
		
			
				
					          // Park old head: 1) raise 2) move to park position 3) lower
 
 
			
		
	
		
			
				
					          plan_buffer_line ( current_position [ X_AXIS ] ,  current_position [ Y_AXIS ] ,  current_position [ Z_AXIS ]  +  TOOLCHANGE_PARK_ZLIFT ,   
 
			
		
	
		
			
				
					          plan_buffer_line ( current_position [ X_AXIS ] ,  current_position [ Y_AXIS ] ,  current_position [ Z_AXIS ]  +  TOOLCHANGE_PARK_ZLIFT , 
 
			
		
	
		
			
				
					                current_position [ E_AXIS ] ,  max_feedrate [ Z_AXIS ] ,  active_extruder ) ; 
 
			
		
	
		
			
				
					          plan_buffer_line ( x_home_pos ( active_extruder ) ,  current_position [ Y_AXIS ] ,  current_position [ Z_AXIS ]  +  TOOLCHANGE_PARK_ZLIFT ,   
 
			
		
	
		
			
				
					          plan_buffer_line ( x_home_pos ( active_extruder ) ,  current_position [ Y_AXIS ] ,  current_position [ Z_AXIS ]  +  TOOLCHANGE_PARK_ZLIFT , 
 
			
		
	
		
			
				
					                current_position [ E_AXIS ] ,  max_feedrate [ X_AXIS ] ,  active_extruder ) ; 
 
			
		
	
		
			
				
					          plan_buffer_line ( x_home_pos ( active_extruder ) ,  current_position [ Y_AXIS ] ,  current_position [ Z_AXIS ] ,   
 
			
		
	
		
			
				
					          plan_buffer_line ( x_home_pos ( active_extruder ) ,  current_position [ Y_AXIS ] ,  current_position [ Z_AXIS ] , 
 
			
		
	
		
			
				
					                current_position [ E_AXIS ] ,  max_feedrate [ Z_AXIS ] ,  active_extruder ) ; 
 
			
		
	
		
			
				
					          st_synchronize ( ) ; 
 
			
		
	
		
			
				
					        } 
 
			
		
	
		
			
				
					          
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					        // apply Y & Z extruder offset (x offset is already used in determining home pos)
 
 
			
		
	
		
			
				
					        current_position [ Y_AXIS ]  =  current_position [ Y_AXIS ]  - 
 
			
		
	
		
			
				
					                     extruder_offset [ Y_AXIS ] [ active_extruder ]  + 
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -2933,7 +2943,7 @@ void process_commands()
 
			
		
	
		
			
				
					        current_position [ Z_AXIS ]  =  current_position [ Z_AXIS ]  - 
 
			
		
	
		
			
				
					                     extruder_offset [ Z_AXIS ] [ active_extruder ]  + 
 
			
		
	
		
			
				
					                     extruder_offset [ Z_AXIS ] [ tmp_extruder ] ; 
 
			
		
	
		
			
				
					                       
			
		
	
		
			
				
					
  
			
		
	
		
			
				
					        active_extruder  =  tmp_extruder ; 
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					        // This function resets the max/min values - the current position may be overwritten below.
 
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -2941,18 +2951,18 @@ void process_commands()
 
			
		
	
		
			
				
					
 
			
		
	
		
			
				
					        if  ( dual_x_carriage_mode  = =  DXC_FULL_CONTROL_MODE ) 
 
			
		
	
		
			
				
					        { 
 
			
		
	
		
			
				
					          current_position [ X_AXIS ]  =  inactive_extruder_x_pos ;   
 
			
		
	
		
			
				
					          current_position [ X_AXIS ]  =  inactive_extruder_x_pos ; 
 
			
		
	
		
			
				
					          inactive_extruder_x_pos  =  destination [ X_AXIS ] ; 
 
			
		
	
		
			
				
					        } 
 
			
		
	
		
			
				
					        else  if  ( dual_x_carriage_mode  = =  DXC_DUPLICATION_MODE ) 
 
			
		
	
		
			
				
					        { 
 
			
		
	
		
			
				
					          active_extruder_parked  =  ( active_extruder  = =  0 ) ;  // this triggers the second extruder to move into the duplication position
 
 
			
		
	
		
			
				
					          if  ( active_extruder  = =  0  | |  active_extruder_parked ) 
 
			
		
	
		
			
				
					            current_position [ X_AXIS ]  =  inactive_extruder_x_pos ;   
 
			
		
	
		
			
				
					            current_position [ X_AXIS ]  =  inactive_extruder_x_pos ; 
 
			
		
	
		
			
				
					          else 
 
			
		
	
		
			
				
					            current_position [ X_AXIS ]  =  destination [ X_AXIS ]  +  duplicate_extruder_x_offset ;   
 
			
		
	
		
			
				
					            current_position [ X_AXIS ]  =  destination [ X_AXIS ]  +  duplicate_extruder_x_offset ; 
 
			
		
	
		
			
				
					          inactive_extruder_x_pos  =  destination [ X_AXIS ] ; 
 
			
		
	
		
			
				
					          extruder_duplication_enabled  =  false ;   
 
			
		
	
		
			
				
					          extruder_duplication_enabled  =  false ; 
 
			
		
	
		
			
				
					        } 
 
			
		
	
		
			
				
					        else 
 
			
		
	
		
			
				
					        { 
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -2962,7 +2972,7 @@ void process_commands()
 
			
		
	
		
			
				
					          active_extruder_parked  =  true ; 
 
			
		
	
		
			
				
					          delayed_move_time  =  0 ; 
 
			
		
	
		
			
				
					        } 
 
			
		
	
		
			
				
					      # else      
 
			
		
	
		
			
				
					      # else 
 
			
		
	
		
			
				
					        // Offset extruder (only by XY)
 
 
			
		
	
		
			
				
					        int  i ; 
 
			
		
	
		
			
				
					        for ( i  =  0 ;  i  <  2 ;  i + + )  { 
 
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -3175,13 +3185,13 @@ void prepare_move()
 
			
		
	
		
			
				
					    { 
 
			
		
	
		
			
				
					      // move duplicate extruder into correct duplication position.
 
 
			
		
	
		
			
				
					      plan_set_position ( inactive_extruder_x_pos ,  current_position [ Y_AXIS ] ,  current_position [ Z_AXIS ] ,  current_position [ E_AXIS ] ) ; 
 
			
		
	
		
			
				
					      plan_buffer_line ( current_position [ X_AXIS ]  +  duplicate_extruder_x_offset ,  current_position [ Y_AXIS ] ,  current_position [ Z_AXIS ] ,   
 
			
		
	
		
			
				
					      plan_buffer_line ( current_position [ X_AXIS ]  +  duplicate_extruder_x_offset ,  current_position [ Y_AXIS ] ,  current_position [ Z_AXIS ] , 
 
			
		
	
		
			
				
					          current_position [ E_AXIS ] ,  max_feedrate [ X_AXIS ] ,  1 ) ; 
 
			
		
	
		
			
				
					      plan_set_position ( current_position [ X_AXIS ] ,  current_position [ Y_AXIS ] ,  current_position [ Z_AXIS ] ,  current_position [ E_AXIS ] ) ; 
 
			
		
	
		
			
				
					      st_synchronize ( ) ; 
 
			
		
	
		
			
				
					      extruder_duplication_enabled  =  true ; 
 
			
		
	
		
			
				
					      active_extruder_parked  =  false ; 
 
			
		
	
		
			
				
					    }    
 
			
		
	
		
			
				
					    } 
 
			
		
	
		
			
				
					    else  if  ( dual_x_carriage_mode  = =  DXC_AUTO_PARK_MODE )  // handle unparking of head
 
 
			
		
	
		
			
				
					    { 
 
			
		
	
		
			
				
					      if  ( current_position [ E_AXIS ]  = =  destination [ E_AXIS ] ) 
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -3190,7 +3200,7 @@ void prepare_move()
 
			
		
	
		
			
				
					        // be used as start of first non-travel move)
 
 
			
		
	
		
			
				
					        if  ( delayed_move_time  ! =  0xFFFFFFFFUL ) 
 
			
		
	
		
			
				
					        { 
 
			
		
	
		
			
				
					          memcpy ( current_position ,  destination ,  sizeof ( current_position ) ) ;   
 
			
		
	
		
			
				
					          memcpy ( current_position ,  destination ,  sizeof ( current_position ) ) ; 
 
			
		
	
		
			
				
					          if  ( destination [ Z_AXIS ]  >  raised_parked_position [ Z_AXIS ] ) 
 
			
		
	
		
			
				
					            raised_parked_position [ Z_AXIS ]  =  destination [ Z_AXIS ] ; 
 
			
		
	
		
			
				
					          delayed_move_time  =  millis ( ) ; 
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -3200,9 +3210,9 @@ void prepare_move()
 
			
		
	
		
			
				
					      delayed_move_time  =  0 ; 
 
			
		
	
		
			
				
					      // unpark extruder: 1) raise, 2) move into starting XY position, 3) lower
 
 
			
		
	
		
			
				
					      plan_buffer_line ( raised_parked_position [ X_AXIS ] ,  raised_parked_position [ Y_AXIS ] ,  raised_parked_position [ Z_AXIS ] ,     current_position [ E_AXIS ] ,  max_feedrate [ Z_AXIS ] ,  active_extruder ) ; 
 
			
		
	
		
			
				
					      plan_buffer_line ( current_position [ X_AXIS ] ,  current_position [ Y_AXIS ] ,  raised_parked_position [ Z_AXIS ] ,   
 
			
		
	
		
			
				
					      plan_buffer_line ( current_position [ X_AXIS ] ,  current_position [ Y_AXIS ] ,  raised_parked_position [ Z_AXIS ] , 
 
			
		
	
		
			
				
					          current_position [ E_AXIS ] ,  min ( max_feedrate [ X_AXIS ] , max_feedrate [ Y_AXIS ] ) ,  active_extruder ) ; 
 
			
		
	
		
			
				
					      plan_buffer_line ( current_position [ X_AXIS ] ,  current_position [ Y_AXIS ] ,  current_position [ Z_AXIS ] ,   
 
			
		
	
		
			
				
					      plan_buffer_line ( current_position [ X_AXIS ] ,  current_position [ Y_AXIS ] ,  current_position [ Z_AXIS ] , 
 
			
		
	
		
			
				
					          current_position [ E_AXIS ] ,  max_feedrate [ Z_AXIS ] ,  active_extruder ) ; 
 
			
		
	
		
			
				
					      active_extruder_parked  =  false ; 
 
			
		
	
		
			
				
					    } 
 
			
		
	
	
		
			
				
					
						
							
								 
						
						
							
								 
						
						
					 
				
				@ -3350,8 +3360,8 @@ void manage_inactivity()
 
			
		
	
		
			
				
					     enable_e0 ( ) ; 
 
			
		
	
		
			
				
					     float  oldepos = current_position [ E_AXIS ] ; 
 
			
		
	
		
			
				
					     float  oldedes = destination [ E_AXIS ] ; 
 
			
		
	
		
			
				
					     plan_buffer_line ( destination [ X_AXIS ] ,  destination [ Y_AXIS ] ,  destination [ Z_AXIS ] ,   
 
			
		
	
		
			
				
					                      destination [ E_AXIS ] + EXTRUDER_RUNOUT_EXTRUDE * EXTRUDER_RUNOUT_ESTEPS / axis_steps_per_unit [ E_AXIS ] ,   
 
			
		
	
		
			
				
					     plan_buffer_line ( destination [ X_AXIS ] ,  destination [ Y_AXIS ] ,  destination [ Z_AXIS ] , 
 
			
		
	
		
			
				
					                      destination [ E_AXIS ] + EXTRUDER_RUNOUT_EXTRUDE * EXTRUDER_RUNOUT_ESTEPS / axis_steps_per_unit [ E_AXIS ] , 
 
			
		
	
		
			
				
					                      EXTRUDER_RUNOUT_SPEED / 60. * EXTRUDER_RUNOUT_ESTEPS / axis_steps_per_unit [ E_AXIS ] ,  active_extruder ) ; 
 
			
		
	
		
			
				
					     current_position [ E_AXIS ] = oldepos ; 
 
			
		
	
		
			
				
					     destination [ E_AXIS ] = oldedes ; 
 
			
		
	
	
		
			
				
					
						
						
						
							
								 
						
					 
				
				@ -3368,7 +3378,7 @@ void manage_inactivity()
 
			
		
	
		
			
				
					      // travel moves have been received so enact them
 
 
			
		
	
		
			
				
					      delayed_move_time  =  0xFFFFFFFFUL ;  // force moves to be done
 
 
			
		
	
		
			
				
					      memcpy ( destination , current_position , sizeof ( destination ) ) ; 
 
			
		
	
		
			
				
					      prepare_move ( ) ;   
 
			
		
	
		
			
				
					      prepare_move ( ) ; 
 
			
		
	
		
			
				
					    } 
 
			
		
	
		
			
				
					  # endif 
 
			
		
	
		
			
				
					  # ifdef TEMP_STAT_LEDS