|  |  | @ -4086,6 +4086,9 @@ inline void gcode_M104() { | 
			
		
	
		
		
			
				
					
					|  |  |  |   if (setTargetedHotend(104)) return; |  |  |  |   if (setTargetedHotend(104)) return; | 
			
		
	
		
		
			
				
					
					|  |  |  |   if (DEBUGGING(DRYRUN)) return; |  |  |  |   if (DEBUGGING(DRYRUN)) return; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   // Start hook must happen before setTargetHotend()
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   print_job_start(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   if (code_seen('S')) { |  |  |  |   if (code_seen('S')) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     float temp = code_value(); |  |  |  |     float temp = code_value(); | 
			
		
	
		
		
			
				
					
					|  |  |  |     setTargetHotend(temp, target_extruder); |  |  |  |     setTargetHotend(temp, target_extruder); | 
			
		
	
	
		
		
			
				
					|  |  | @ -4093,9 +4096,11 @@ inline void gcode_M104() { | 
			
		
	
		
		
			
				
					
					|  |  |  |       if (dual_x_carriage_mode == DXC_DUPLICATION_MODE && target_extruder == 0) |  |  |  |       if (dual_x_carriage_mode == DXC_DUPLICATION_MODE && target_extruder == 0) | 
			
		
	
		
		
			
				
					
					|  |  |  |         setTargetHotend1(temp == 0.0 ? 0.0 : temp + duplicate_extruder_temp_offset); |  |  |  |         setTargetHotend1(temp == 0.0 ? 0.0 : temp + duplicate_extruder_temp_offset); | 
			
		
	
		
		
			
				
					
					|  |  |  |     #endif |  |  |  |     #endif | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     if (temp > degHotend(target_extruder)) LCD_MESSAGEPGM(MSG_HEATING); | 
			
		
	
		
		
			
				
					
					|  |  |  |   } |  |  |  |   } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   print_job_stop(); |  |  |  |   if (print_job_stop()) LCD_MESSAGEPGM(WELCOME_MSG); | 
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | #if HAS_TEMP_0 || HAS_TEMP_BED || ENABLED(HEATER_0_USES_MAX6675) |  |  |  | #if HAS_TEMP_0 || HAS_TEMP_BED || ENABLED(HEATER_0_USES_MAX6675) | 
			
		
	
	
		
		
			
				
					|  |  | @ -4220,12 +4225,12 @@ inline void gcode_M105() { | 
			
		
	
		
		
			
				
					
					|  |  |  | inline void gcode_M109() { |  |  |  | inline void gcode_M109() { | 
			
		
	
		
		
			
				
					
					|  |  |  |   bool no_wait_for_cooling = true; |  |  |  |   bool no_wait_for_cooling = true; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   // Start hook must happen before setTargetHotend()
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   print_job_start(); |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   if (setTargetedHotend(109)) return; |  |  |  |   if (setTargetedHotend(109)) return; | 
			
		
	
		
		
			
				
					
					|  |  |  |   if (DEBUGGING(DRYRUN)) return; |  |  |  |   if (DEBUGGING(DRYRUN)) return; | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   // Start hook must happen before setTargetHotend()
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   print_job_start(); | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |   no_wait_for_cooling = code_seen('S'); |  |  |  |   no_wait_for_cooling = code_seen('S'); | 
			
		
	
		
		
			
				
					
					|  |  |  |   if (no_wait_for_cooling || code_seen('R')) { |  |  |  |   if (no_wait_for_cooling || code_seen('R')) { | 
			
		
	
		
		
			
				
					
					|  |  |  |     float temp = code_value(); |  |  |  |     float temp = code_value(); | 
			
		
	
	
		
		
			
				
					|  |  | @ -7698,17 +7703,6 @@ bool print_job_start(millis_t t /* = 0 */) { | 
			
		
	
		
		
			
				
					
					|  |  |  |   return true; |  |  |  |   return true; | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  | /**
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |  * Output the print job timer in seconds |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |  * |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |  * @return the number of seconds |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |  */ |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | millis_t print_job_timer() { |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   if (!print_job_start_ms) return 0; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |   return (((print_job_stop_ms > print_job_start_ms) |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  |     ? print_job_stop_ms : millis()) - print_job_start_ms) / 1000; |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | 
 |  |  |  |  | 
			
		
	
		
		
			
				
					
					|  |  |  | /**
 |  |  |  | /**
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  * Check if the running print job has finished and stop the timer |  |  |  |  * Check if the running print job has finished and stop the timer | 
			
		
	
		
		
			
				
					
					|  |  |  |  * |  |  |  |  * | 
			
		
	
	
		
		
			
				
					|  |  | @ -7727,3 +7721,14 @@ bool print_job_stop(bool force /* = false */) { | 
			
		
	
		
		
			
				
					
					|  |  |  |   print_job_stop_ms = millis(); |  |  |  |   print_job_stop_ms = millis(); | 
			
		
	
		
		
			
				
					
					|  |  |  |   return true; |  |  |  |   return true; | 
			
		
	
		
		
			
				
					
					|  |  |  | } |  |  |  | } | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | 
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | /**
 | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  * Output the print job timer in seconds | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  * | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  * @return the number of seconds | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |  */ | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | millis_t print_job_timer() { | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   if (!print_job_start_ms) return 0; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |   return (((print_job_stop_ms > print_job_start_ms) | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  |     ? print_job_stop_ms : millis()) - print_job_start_ms) / 1000; | 
			
		
	
		
		
			
				
					
					|  |  |  |  |  |  |  | } | 
			
		
	
	
		
		
			
				
					|  |  | 
 |