Browse Source

resolving conflicts with upstream

PavelSindler 7 years ago
parent
commit
15ef4175b7

+ 8 - 2
Firmware/Configuration.h

@@ -5,7 +5,7 @@
 #include "Configuration_prusa.h"
 
 // Firmware version
-#define FW_version "3.0.12-3"
+#define FW_version "3.0.12-7"
 
 #define FW_PRUSA3D_MAGIC "PRUSA3DFW"
 #define FW_PRUSA3D_MAGIC_LEN 10
@@ -463,7 +463,13 @@ const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of
 // please keep turned on if you can.
 //#define EEPROM_CHITCHAT
 
-
+// Host Keepalive
+//
+// When enabled Marlin will send a busy status message to the host
+// every couple of seconds when it can't accept commands.
+//
+#define HOST_KEEPALIVE_FEATURE    // Disable this if your host doesn't like keepalive messages
+#define HOST_KEEPALIVE_INTERVAL 2 // Number of seconds between "busy" messages. Set with M113.
 
 //LCD and SD support
 #define ULTRA_LCD  //general LCD support, also 16x2

+ 2 - 2
Firmware/Configuration_adv.h

@@ -261,7 +261,7 @@
   #define SD_SORT_ALPHA 1
   #define SD_SORT_NONE 2
 
-  #define SDSORT_LIMIT       40    // Maximum number of sorted items (10-256).
+  #define SDSORT_LIMIT       20    // Maximum number of sorted items (10-256).
   #define FOLDER_SORTING     -1     // -1=above  0=none  1=below
   #define SDSORT_GCODE       false  // Allow turning sorting on/off with LCD and M34 g-code.
   #define SDSORT_USES_RAM    true  // Pre-allocate a static array for faster pre-sorting.
@@ -323,7 +323,7 @@
  * K=0 means advance disabled.
  * See Marlin documentation for calibration instructions.
  */
-//#define LIN_ADVANCE
+#define LIN_ADVANCE
 
 #ifdef LIN_ADVANCE
   #define LIN_ADVANCE_K 0 //Try around 45 for PLA, around 25 for ABS.

+ 28 - 3
Firmware/Marlin.h

@@ -109,6 +109,8 @@ FORCE_INLINE void serialprintPGM(const char *str)
   }
 }
 
+#define NOMORE(v,n) do{ if (v > n) v = n; }while(0)
+
 bool is_buffer_empty();
 void get_command();
 void process_commands();
@@ -281,6 +283,10 @@ extern float retract_length, retract_length_swap, retract_feedrate, retract_zlif
 extern float retract_recover_length, retract_recover_length_swap, retract_recover_feedrate;
 #endif
 
+#ifdef HOST_KEEPALIVE_FEATURE
+extern uint8_t host_keepalive_interval;
+#endif
+
 extern unsigned long starttime;
 extern unsigned long stoptime;
 extern int bowden_length[4];
@@ -316,8 +322,6 @@ extern void digipot_i2c_set_current( int channel, float current );
 extern void digipot_i2c_init();
 #endif
 
-#endif
-
 //Long pause
 extern int saved_feedmultiply;
 extern float HotendTempBckp;
@@ -350,10 +354,31 @@ float d_ReadData();
 void bed_analysis(float x_dimension, float y_dimension, int x_points_num, int y_points_num, float shift_x, float shift_y);
 
 #endif
+
 float temp_comp_interpolation(float temperature);
 void temp_compensation_apply();
 void temp_compensation_start();
 void wait_for_heater(long codenum);
 void serialecho_temperatures();
 void proc_commands();
-bool check_commands();
+bool check_commands();
+
+#ifdef HOST_KEEPALIVE_FEATURE
+
+// States for managing Marlin and host communication
+// Marlin sends messages if blocked or busy
+enum MarlinBusyState {
+	NOT_BUSY,           // Not in a handler
+	IN_HANDLER,         // Processing a GCode
+	IN_PROCESS,         // Known to be blocking command input (as in G29)
+	PAUSED_FOR_USER,    // Blocking pending any input
+	PAUSED_FOR_INPUT    // Blocking pending text input (concept)
+};
+
+#define KEEPALIVE_STATE(n) do { busy_state = n;} while (0)
+extern void host_keepalive();
+extern MarlinBusyState busy_state;
+
+#endif //HOST_KEEPALIVE_FEATURE
+
+#endif //ifndef marlin.h

+ 8 - 4
Firmware/MarlinSerial.cpp

@@ -64,7 +64,7 @@ FORCE_INLINE void store_char(unsigned char c)
           store_char(c);
       }
   }
-  
+#ifndef SNMM
   SIGNAL(USART2_RX_vect)
   {
       if (selectedSerialPort == 1) {
@@ -82,6 +82,7 @@ FORCE_INLINE void store_char(unsigned char c)
       }
   }
 #endif
+#endif
 
 // Constructors ////////////////////////////////////////////////////////////////
 
@@ -122,7 +123,7 @@ void MarlinSerial::begin(long baud)
   sbi(M_UCSRxB, M_TXENx);
   sbi(M_UCSRxB, M_RXCIEx);
   
-  
+#ifndef SNMM
 // set up the second serial port
   if (useU2X) {
         UCSR2A = 1 << U2X2;
@@ -139,6 +140,7 @@ void MarlinSerial::begin(long baud)
     sbi(UCSR2B, RXEN2);
     sbi(UCSR2B, TXEN2);
     sbi(UCSR2B, RXCIE2);
+#endif
 }
 
 void MarlinSerial::end()
@@ -146,10 +148,12 @@ void MarlinSerial::end()
   cbi(M_UCSRxB, M_RXENx);
   cbi(M_UCSRxB, M_TXENx);
   cbi(M_UCSRxB, M_RXCIEx);
-  
+
+#ifndef SNMM
   cbi(UCSR2B, RXEN2);
   cbi(UCSR2B, TXEN2);
-  cbi(UCSR2B, RXCIE2); 
+  cbi(UCSR2B, RXCIE2);
+#endif
 }
 
 

+ 46 - 7
Firmware/MarlinSerial.h

@@ -101,18 +101,56 @@ class MarlinSerial //: public Stream
     {
       return (unsigned int)(RX_BUFFER_SIZE + rx_buffer.head - rx_buffer.tail) % RX_BUFFER_SIZE;
     }
-    
-    FORCE_INLINE void write(uint8_t c)
-    {
-      while (!((M_UCSRxA) & (1 << M_UDREx)))
-        ;
 
-      M_UDRx = c;
-    }
+	void write(uint8_t c)
+	{
+#ifdef SNMM // don't do the second serial port when multimaterialing
+        while (!((M_UCSRxA) & (1 << M_UDREx)))
+				;
+
+        M_UDRx = c;
+#else
+		if (selectedSerialPort == 0) {
+			while (!((M_UCSRxA) & (1 << M_UDREx)))
+				;
+
+			M_UDRx = c;
+		}
+		else if (selectedSerialPort == 1) {
+			while (!((UCSR2A) & (1 << UDRE2)))
+				;
+
+			UDR2 = c;
+		}
+#endif
+	}
     
     
     void checkRx(void)
     {
+        
+#ifdef SNMM
+        if((M_UCSRxA & (1<<M_RXCx)) != 0) {
+                // Test for a framing error.
+                if (M_UCSRxA & (1<<M_FEx)) {
+                    // Characters received with the framing errors will be ignored.
+                    // The temporary variable "c" was made volatile, so the compiler does not optimize this out.
+                    volatile unsigned char c = M_UDRx;
+                } else {
+                    unsigned char c  =  M_UDRx;
+                    int i = (unsigned int)(rx_buffer.head + 1) % RX_BUFFER_SIZE;
+                    // if we should be storing the received character into the location
+                    // just before the tail (meaning that the head would advance to the
+                    // current location of the tail), we're about to overflow the buffer
+                    // and so we don't write the character or advance the head.
+                    if (i != rx_buffer.tail) {
+                        rx_buffer.buffer[rx_buffer.head] = c;
+                        rx_buffer.head = i;
+                    }
+                    selectedSerialPort = 0;
+                }
+            }
+#else
         if (selectedSerialPort == 0) {
             if((M_UCSRxA & (1<<M_RXCx)) != 0) {
                 // Test for a framing error.
@@ -156,6 +194,7 @@ class MarlinSerial //: public Stream
                 }
             }
         }
+#endif
     }
     
     

+ 117 - 34
Firmware/Marlin_main.cpp

@@ -150,6 +150,7 @@
 //        Rxxx Wait for extruder current temp to reach target temp. Waits when heating and cooling
 //        IF AUTOTEMP is enabled, S<mintemp> B<maxtemp> F<factor>. Exit autotemp by any M109 without F
 // M112 - Emergency stop
+// M113 - Get or set the timeout interval for Host Keepalive "busy" messages
 // M114 - Output current position to serial port
 // M115 - Capabilities string
 // M117 - display message
@@ -372,6 +373,16 @@ int fanSpeed=0;
 
 bool cancel_heatup = false ;
 
+#ifdef HOST_KEEPALIVE_FEATURE
+  
+  MarlinBusyState busy_state = NOT_BUSY;
+  static long prev_busy_signal_ms = -1;
+  uint8_t host_keepalive_interval = HOST_KEEPALIVE_INTERVAL;
+#else
+  #define host_keepalive();
+  #define KEEPALIVE_STATE(n);
+#endif
+
 #ifdef FILAMENT_SENSOR
   //Variables for Filament Sensor input 
   float filament_width_nominal=DEFAULT_NOMINAL_FILAMENT_DIA;  //Set nominal filament width, can be changed with M404 
@@ -761,10 +772,12 @@ void enquecommand(const char *cmd, bool from_progmem)
             strcpy_P(cmdbuffer + bufindw + 1, cmd);
         else
             strcpy(cmdbuffer + bufindw + 1, cmd);
-        SERIAL_ECHO_START;
-        SERIAL_ECHORPGM(MSG_Enqueing);
-        SERIAL_ECHO(cmdbuffer + bufindw + 1);
-        SERIAL_ECHOLNPGM("\"");
+		if (!farm_mode) {
+			SERIAL_ECHO_START;
+			SERIAL_ECHORPGM(MSG_Enqueing);
+			SERIAL_ECHO(cmdbuffer + bufindw + 1);
+			SERIAL_ECHOLNPGM("\"");
+		}
         bufindw += len + 2;
         if (bufindw == sizeof(cmdbuffer))
             bufindw = 0;
@@ -797,10 +810,12 @@ void enquecommand_front(const char *cmd, bool from_progmem)
         else
             strcpy(cmdbuffer + bufindr + 1, cmd);
         ++ buflen;
-        SERIAL_ECHO_START;
-        SERIAL_ECHOPGM("Enqueing to the front: \"");
-        SERIAL_ECHO(cmdbuffer + bufindr + 1);
-        SERIAL_ECHOLNPGM("\"");
+		if (!farm_mode) {
+			SERIAL_ECHO_START;
+			SERIAL_ECHOPGM("Enqueing to the front: \"");
+			SERIAL_ECHO(cmdbuffer + bufindr + 1);
+			SERIAL_ECHOLNPGM("\"");
+		}
 #ifdef CMDBUFFER_DEBUG
         cmdqueue_dump_to_serial();
 #endif /* CMDBUFFER_DEBUG */
@@ -948,7 +963,7 @@ void factory_reset(char level, bool quiet)
             // Force the "Follow calibration flow" message at the next boot up.
             calibration_status_store(CALIBRATION_STATUS_Z_CALIBRATION);
             farm_no = 0;
-			farm_mode == false;
+			farm_mode = false;
 			eeprom_update_byte((uint8_t*)EEPROM_FARM_MODE, farm_mode);
             EEPROM_save_B(EEPROM_FARM_NUMBER, &farm_no);
                        
@@ -1011,7 +1026,7 @@ void setup()
 	setup_powerhold();
     farm_mode = eeprom_read_byte((uint8_t*)EEPROM_FARM_MODE);
 	EEPROM_read_B(EEPROM_FARM_NUMBER, &farm_no);
-	//if ((farm_mode == 0xFF && farm_no == 0) || (farm_no == 0xFFFF)) farm_mode = false; //if farm_mode has not been stored to eeprom yet and farm number is set to zero or EEPROM is fresh, deactivate farm mode 
+	if ((farm_mode == 0xFF && farm_no == 0) || (farm_no == 0xFFFF)) farm_mode = false; //if farm_mode has not been stored to eeprom yet and farm number is set to zero or EEPROM is fresh, deactivate farm mode 
 	if (farm_no == 0xFFFF) farm_no = 0;
 	if (farm_mode)
 	{
@@ -1026,6 +1041,7 @@ void setup()
 	SERIAL_PROTOCOLLNPGM("start");
 	SERIAL_ECHO_START;
 
+
 #if 0
 	SERIAL_ECHOLN("Reading eeprom from 0 to 100: start");
 	for (int i = 0; i < 4096; ++i) {
@@ -1086,6 +1102,7 @@ void setup()
 	world2machine_reset();
 
 	lcd_init();
+	KEEPALIVE_STATE(PAUSED_FOR_USER);
 	if (!READ(BTN_ENC))
 	{
 		_delay_ms(1000);
@@ -1107,7 +1124,7 @@ void setup()
 
 
 			_delay_ms(2000);
-
+			
 			char level = reset_menu();
 			factory_reset(level, false);
 
@@ -1168,17 +1185,7 @@ void setup()
 #if defined(Z_AXIS_ALWAYS_ON)
 	enable_z();
 #endif
-	farm_mode = eeprom_read_byte((uint8_t*)EEPROM_FARM_MODE);
-	EEPROM_read_B(EEPROM_FARM_NUMBER, &farm_no);
-	if ((farm_mode == 0xFF && farm_no == 0) || (farm_no == 0xFFFF)) farm_mode = false; //if farm_mode has not been stored to eeprom yet and farm number is set to zero or EEPROM is fresh, deactivate farm mode 
-	if (farm_no == 0xFFFF) farm_no = 0;
-	if (farm_mode)
-	{
-		prusa_statistics(8);
-		no_response = true; //we need confirmation by recieving PRUSA thx
-		important_status = 8;
-	}
-
+	
 	// Enable Toshiba FlashAir SD card / WiFi enahanced card.
 	card.ToshibaFlashAir_enable(eeprom_read_byte((unsigned char*)EEPROM_TOSHIBA_FLASH_AIR_COMPATIBLITY) == 1);
 	// Force SD card update. Otherwise the SD card update is done from loop() on card.checkautostart(false), 
@@ -1255,6 +1262,7 @@ void setup()
   // Store the currently running firmware into an eeprom,
   // so the next time the firmware gets updated, it will know from which version it has been updated.
   update_current_firmware_version_to_eeprom();
+  KEEPALIVE_STATE(NOT_BUSY);
 }
 
 void trace();
@@ -1331,6 +1339,36 @@ int serial_read_stream() {
     }
 }
 
+#ifdef HOST_KEEPALIVE_FEATURE
+/**
+* Output a "busy" message at regular intervals
+* while the machine is not accepting commands.
+*/
+void host_keepalive() {
+  if (farm_mode) return;
+  long ms = millis();
+  if (host_keepalive_interval && busy_state != NOT_BUSY) {
+    if (ms - prev_busy_signal_ms < 1000UL * host_keepalive_interval) return;
+	switch (busy_state) {
+      case IN_HANDLER:
+      case IN_PROCESS:
+        SERIAL_ECHO_START;
+        SERIAL_ECHOLNPGM("busy: processing");
+        break;
+      case PAUSED_FOR_USER:
+        SERIAL_ECHO_START;
+        SERIAL_ECHOLNPGM("busy: paused for user");
+        break;
+      case PAUSED_FOR_INPUT:
+        SERIAL_ECHO_START;
+        SERIAL_ECHOLNPGM("busy: paused for input");
+        break;
+    }
+  }
+  prev_busy_signal_ms = ms;
+}
+#endif
+
 // The loop() function is called in an endless loop by the Arduino framework from the default main() routine.
 // Before loop(), the setup() function is called by the main() routine.
 void loop()
@@ -1386,6 +1424,7 @@ void loop()
       if (! cmdbuffer_front_already_processed)
           cmdqueue_pop_front();
       cmdbuffer_front_already_processed = false;
+	  host_keepalive();
   }
 }
   //check heater every n milliseconds
@@ -2118,6 +2157,8 @@ void process_commands()
   float tmp_motor_loud[3] = DEFAULT_PWM_MOTOR_CURRENT_LOUD;
   int8_t SilentMode;
 #endif
+  KEEPALIVE_STATE(IN_HANDLER);
+
   if (code_seen("M117")) { //moved to highest priority place to be able to to print strings which includes "G", "PRUSA" and "^"
 	  starpos = (strchr(strchr_pointer + 5, '*'));
 	  if (starpos != NULL)
@@ -2451,7 +2492,7 @@ void process_commands()
         prepare_arc_move(false);
       }
       break;
-    case 4: // G4 dwell      
+    case 4: // G4 dwell   
       codenum = 0;
       if(code_seen('P')) codenum = code_value(); // milliseconds to wait
       if(code_seen('S')) codenum = code_value() * 1000; // seconds to wait
@@ -2484,8 +2525,7 @@ void process_commands()
       #endif //FWRETRACT
     case 28: //G28 Home all Axis one at a time
 		homing_flag = true;
-
-#ifdef ENABLE_AUTO_BED_LEVELING
+		#ifdef ENABLE_AUTO_BED_LEVELING
       plan_bed_level_matrix.set_to_identity();  //Reset the plane ("erase" all leveling data)
 #endif //ENABLE_AUTO_BED_LEVELING
             
@@ -2932,6 +2972,7 @@ void process_commands()
 			enquecommand_front_P((PSTR("G28 W0")));
 			break;
 		}
+		KEEPALIVE_STATE(NOT_BUSY); //no need to print busy messages as we print current temperatures periodicaly
 		SERIAL_ECHOLNPGM("PINDA probe calibration start");
 		custom_message = true;
 		custom_message_type = 4;
@@ -3332,6 +3373,7 @@ void process_commands()
 			current_position[E_AXIS] += DEFAULT_RETRACTION;
 			plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 400, active_extruder);
 		}
+		KEEPALIVE_STATE(NOT_BUSY);
 		// Restore custom message state
 		custom_message = custom_message_old;
 		custom_message_type = custom_message_type_old;
@@ -3476,7 +3518,9 @@ void process_commands()
 	case 98: //activate farm mode
 		farm_mode = 1;
 		PingTime = millis();
+		EEPROM_save_B(EEPROM_FARM_NUMBER, &farm_no);
 		eeprom_update_byte((unsigned char *)EEPROM_FARM_MODE, farm_mode);
+		
 		break;
 
 	case 99: //deactivate farm mode
@@ -3529,29 +3573,33 @@ void process_commands()
       while (*src == ' ') ++src;
       if (!hasP && !hasS && *src != '\0') {
         lcd_setstatus(src);
-      } else {
-        LCD_MESSAGERPGM(MSG_USERWAIT);
-      }
+	  } else {
+		  LCD_MESSAGERPGM(MSG_USERWAIT);
+	  }
 
       lcd_ignore_click();				//call lcd_ignore_click aslo for else ???
       st_synchronize();
       previous_millis_cmd = millis();
       if (codenum > 0){
         codenum += millis();  // keep track of when we started waiting
+		KEEPALIVE_STATE(PAUSED_FOR_USER);
         while(millis() < codenum && !lcd_clicked()){
           manage_heater();
           manage_inactivity(true);
           lcd_update();
         }
+		KEEPALIVE_STATE(IN_HANDLER);
         lcd_ignore_click(false);
       }else{
           if (!lcd_detected())
             break;
+		  KEEPALIVE_STATE(PAUSED_FOR_USER);
         while(!lcd_clicked()){
           manage_heater();
           manage_inactivity(true);
           lcd_update();
         }
+		KEEPALIVE_STATE(IN_HANDLER);
       }
       if (IS_SD_PRINTING)
         LCD_MESSAGERPGM(MSG_RESUMING);
@@ -3739,7 +3787,6 @@ void process_commands()
     {
 		// Only Z calibration?
 		bool onlyZ = code_seen('Z');
-
 		if (!onlyZ) {
 			setTargetBed(0);
 			setTargetHotend(0, 0);
@@ -3762,7 +3809,9 @@ void process_commands()
         memset(axis_known_position, 0, sizeof(axis_known_position));
                 
         // Let the user move the Z axes up to the end stoppers.
+		KEEPALIVE_STATE(PAUSED_FOR_USER);
         if (lcd_calibrate_z_end_stop_manual( onlyZ )) {
+			KEEPALIVE_STATE(IN_HANDLER);
             refresh_cmd_timeout();
 			if (((degHotend(0) > MAX_HOTEND_TEMP_CALIBRATION) || (degBed() > MAX_BED_TEMP_CALIBRATION)) && (!onlyZ)) {
 				lcd_wait_for_cool_down();
@@ -3842,6 +3891,7 @@ void process_commands()
             }
         } else {
             // Timeouted.
+			KEEPALIVE_STATE(IN_HANDLER);
         }
         lcd_update_enable(true);
         break;
@@ -3872,8 +3922,10 @@ void process_commands()
 
     case 47:
         // M47: Prusa3D: Show end stops dialog on the display.
+		KEEPALIVE_STATE(PAUSED_FOR_USER);
         lcd_diag_show_end_stops();
-        break;
+		KEEPALIVE_STATE(IN_HANDLER);
+		break;
 
 #if 0
     case 48: // M48: scan the bed induction sensor points, print the sensor trigger coordinates to the serial line for visualization on the PC.
@@ -4256,6 +4308,7 @@ Sigma_Exit:
           }}
         #endif
 		SERIAL_PROTOCOLLN("");
+		KEEPALIVE_STATE(NOT_BUSY);
       return;
       break;
     case 109:
@@ -4293,11 +4346,14 @@ Sigma_Exit:
       /* See if we are heating up or cooling down */
       target_direction = isHeatingHotend(tmp_extruder); // true if heating, false if cooling
 
+	  KEEPALIVE_STATE(NOT_BUSY);
+
       cancel_heatup = false;
 
 	  wait_for_heater(codenum); //loops until target temperature is reached
 
         LCD_MESSAGERPGM(MSG_HEATING_COMPLETE);
+		KEEPALIVE_STATE(IN_HANDLER);
 		heating_status = 2;
 		if (farm_mode) { prusa_statistics(2); };
         
@@ -4325,6 +4381,7 @@ Sigma_Exit:
         cancel_heatup = false;
         target_direction = isHeatingBed(); // true if heating, false if cooling
 
+		KEEPALIVE_STATE(NOT_BUSY);
         while ( (target_direction)&&(!cancel_heatup) ? (isHeatingBed()) : (isCoolingBed()&&(CooldownNoWait==false)) )
         {
           if(( millis() - codenum) > 1000 ) //Print Temp Reading every 1 second while heating up.
@@ -4347,6 +4404,7 @@ Sigma_Exit:
           lcd_update();
         }
         LCD_MESSAGERPGM(MSG_BED_DONE);
+		KEEPALIVE_STATE(IN_HANDLER);
 		heating_status = 4;
 
         previous_millis_cmd = millis();
@@ -4490,6 +4548,18 @@ Sigma_Exit:
 		else
 			gcode_LastN = 0;
 		break;
+#ifdef HOST_KEEPALIVE_FEATURE
+	case 113: // M113 - Get or set Host Keepalive interval
+      if (code_seen('S')) {
+		host_keepalive_interval = (uint8_t)code_value_short();
+		NOMORE(host_keepalive_interval, 60);
+      } else {
+        SERIAL_ECHO_START;
+        SERIAL_ECHOPAIR("M113 S", (unsigned long)host_keepalive_interval);
+		SERIAL_PROTOCOLLN("");
+      }
+	break;
+#endif
     case 115: // M115
       if (code_seen('V')) {
           // Report the Prusa version number.
@@ -5037,7 +5107,8 @@ Sigma_Exit:
           temp=70;
       if (code_seen('S')) temp=code_value();
       if (code_seen('C')) c=code_value();
-      PID_autotune(temp, e, c);
+	  
+	  PID_autotune(temp, e, c);
     }
     break;
     case 400: // M400 finish all moves
@@ -5314,6 +5385,7 @@ case 404:  //M404 Enter the nominal filament width (3mm, 1.75mm ) N<3.0> or disp
         int counterBeep = 0;
         lcd_wait_interact();
 		load_filament_time = millis();
+		KEEPALIVE_STATE(PAUSED_FOR_USER);
         while(!lcd_clicked()){
 
 		  cnt++;
@@ -5350,14 +5422,17 @@ case 404:  //M404 Enter the nominal filament width (3mm, 1.75mm ) N<3.0> or disp
           }
 
         }
+		KEEPALIVE_STATE(IN_HANDLER);
 		WRITE(BEEPER, LOW);
 #ifdef SNMM
 		display_loading();
+		KEEPALIVE_STATE(PAUSED_FOR_USER);
 		do {
 			target[E_AXIS] += 0.002;
 			plan_buffer_line(target[X_AXIS], target[Y_AXIS], target[Z_AXIS], target[E_AXIS], 500, active_extruder);
 			delay_keep_alive(2);
-		} while (!lcd_clicked());		
+		} while (!lcd_clicked());
+		KEEPALIVE_STATE(IN_HANDLER);
 		/*if (millis() - load_filament_time > 2) {
 			load_filament_time = millis();
 			target[E_AXIS] += 0.001;
@@ -5397,7 +5472,9 @@ case 404:  //M404 Enter the nominal filament width (3mm, 1.75mm ) N<3.0> or disp
         lcd_loading_filament();
         while ((lcd_change_fil_state == 0)||(lcd_change_fil_state != 1)){
           lcd_change_fil_state = 0;
+		  KEEPALIVE_STATE(PAUSED_FOR_USER);
           lcd_alright();
+		  KEEPALIVE_STATE(IN_HANDLER);
           switch(lcd_change_fil_state){
             
              // Filament failed to load so load it again
@@ -5570,6 +5647,9 @@ case 404:  //M404 Enter the nominal filament width (3mm, 1.75mm ) N<3.0> or disp
     break;
 	case 701: //M701: load filament
 	{
+#ifdef SNMM
+		extr_adj(snmm_extruder);//loads current extruder
+#else
 		enable_z();
 		custom_message = true;
 		custom_message_type = 2;
@@ -5601,6 +5681,7 @@ case 404:  //M404 Enter the nominal filament width (3mm, 1.75mm ) N<3.0> or disp
 		loading_flag = false;
 		custom_message = false;
 		custom_message_type = 0;
+#endif
 	}
 	break;
 	case 702:
@@ -5809,6 +5890,8 @@ case 404:  //M404 Enter the nominal filament width (3mm, 1.75mm ) N<3.0> or disp
     SERIAL_ECHOLNPGM("\"");
   }
 
+  KEEPALIVE_STATE(NOT_BUSY);
+
   ClearToSend();
 }
 
@@ -6052,7 +6135,7 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) //default argument s
 	static int killCount = 0;   // make the inactivity button a bit less responsive
    const int KILL_DELAY = 10000;
 #endif
-	
+
     if(buflen < (BUFSIZE-1)){
         get_command();
     }
@@ -6328,7 +6411,7 @@ void calculate_volumetric_multipliers() {
 
 void delay_keep_alive(unsigned int ms)
 {
-    for (;;) {
+	for (;;) {
         manage_heater();
         // Manage inactivity, but don't disable steppers on timeout.
         manage_inactivity(true);

+ 8 - 7
Firmware/temperature.cpp

@@ -220,7 +220,7 @@ unsigned long watchmillis[EXTRUDERS] = ARRAY_BY_EXTRUDERS(0,0,0);
 		  pid_cycle = 0;
           return;
         }
-	
+
   SERIAL_ECHOLN("PID Autotune start");
   
   disable_heater(); // switch off all heaters.
@@ -336,13 +336,13 @@ unsigned long watchmillis[EXTRUDERS] = ARRAY_BY_EXTRUDERS(0,0,0);
         p=soft_pwm_bed;       
         SERIAL_PROTOCOLPGM("ok B:");
       }else{
-        p=soft_pwm[extruder];       
-        SERIAL_PROTOCOLPGM("ok T:");
+        p=soft_pwm[extruder]; 		
+		SERIAL_PROTOCOLPGM("ok T:");
       }
-			
-      SERIAL_PROTOCOL(input);   
-      SERIAL_PROTOCOLPGM(" @:");
-      SERIAL_PROTOCOLLN(p);       
+	  
+		SERIAL_PROTOCOL(input);   
+		SERIAL_PROTOCOLPGM(" @:");
+		SERIAL_PROTOCOLLN(p);       
 
       temp_millis = millis();
     }
@@ -686,6 +686,7 @@ void manage_heater()
 		    	 volumetric_multiplier[FILAMENT_SENSOR_EXTRUDER_NUM]=0.01;
 	}
 #endif
+  host_keepalive();
 }
 
 #define PGM_RD_W(x)   (short)pgm_read_word(&x)

+ 44 - 30
Firmware/ultralcd.cpp

@@ -105,7 +105,7 @@ int lcd_commands_step=0;
 bool isPrintPaused = false;
 uint8_t farm_mode = 0;
 int farm_no = 0;
-int farm_timer = 30;
+int farm_timer = 8;
 int farm_status = 0;
 unsigned long allert_timer = millis();
 bool printer_connected = true;
@@ -408,15 +408,15 @@ static void lcd_status_screen()
 		farm_timer--;
 		if (farm_timer < 1)
 		{
-			farm_timer = 180;
+			farm_timer = 10;
 			prusa_statistics(0);
 		}
 		switch (farm_timer)
 		{
-		case 45:
+		case 8:
 			prusa_statistics(21);
 			break;
-		case 10:
+		case 5:
 			if (IS_SD_PRINTING)
 			{
 				prusa_statistics(20);
@@ -1283,13 +1283,14 @@ void lcd_menu_statistics()
 		lcd.print(itostr3(_days));
 
 
-
+		KEEPALIVE_STATE(PAUSED_FOR_USER);
 		while (!lcd_clicked())
 		{
 			manage_heater();
 			manage_inactivity(true);
 			delay(100);
 		}
+		KEEPALIVE_STATE(NOT_BUSY);
 
 		lcd_quick_feedback();
 		lcd_return_to_status();
@@ -1367,6 +1368,7 @@ void lcd_service_mode_show_result() {
 		} else lcd_print_at_PGM(11, i + 1, PSTR("N/A"));
 	}
 	delay_keep_alive(500);
+	KEEPALIVE_STATE(PAUSED_FOR_USER);
 	while (!lcd_clicked()) {
 		delay_keep_alive(100);
 	}
@@ -1393,6 +1395,7 @@ void lcd_service_mode_show_result() {
 	while (!lcd_clicked()) {
 		delay_keep_alive(100);
 	}
+	KEEPALIVE_STATE(NOT_BUSY);
 	delay_keep_alive(500);
 	lcd_set_custom_characters_arrows();
 	lcd_return_to_status();
@@ -1865,6 +1868,7 @@ void lcd_show_fullscreen_message_and_wait_P(const char *msg)
     const char *msg_next = lcd_display_message_fullscreen_P(msg);
     bool multi_screen = msg_next != NULL;
 
+	KEEPALIVE_STATE(PAUSED_FOR_USER);
     // Until confirmed by a button click.
     for (;;) {
         // Wait for 5 seconds before displaying the next text.
@@ -1874,6 +1878,7 @@ void lcd_show_fullscreen_message_and_wait_P(const char *msg)
                 while (lcd_clicked()) ;
                 delay(10);
                 while (lcd_clicked()) ;
+				KEEPALIVE_STATE(IN_HANDLER);
                 return;
             }
         }
@@ -1887,6 +1892,7 @@ void lcd_show_fullscreen_message_and_wait_P(const char *msg)
 
 void lcd_wait_for_click()
 {
+	KEEPALIVE_STATE(PAUSED_FOR_USER);
     for (;;) {
         manage_heater();
         manage_inactivity(true);
@@ -1894,6 +1900,7 @@ void lcd_wait_for_click()
             while (lcd_clicked()) ;
             delay(10);
             while (lcd_clicked()) ;
+			KEEPALIVE_STATE(IN_HANDLER);
             return;
         }
     }
@@ -1901,7 +1908,6 @@ void lcd_wait_for_click()
 
 int8_t lcd_show_fullscreen_message_yes_no_and_wait_P(const char *msg, bool allow_timeouting, bool default_yes)
 {
-
 	lcd_display_message_fullscreen_P(msg);
 	
 	if (default_yes) {
@@ -1923,6 +1929,7 @@ int8_t lcd_show_fullscreen_message_yes_no_and_wait_P(const char *msg, bool allow
 	// Wait for user confirmation or a timeout.
 	unsigned long previous_millis_cmd = millis();
 	int8_t        enc_dif = encoderDiff;
+	KEEPALIVE_STATE(PAUSED_FOR_USER);
 	for (;;) {
 		if (allow_timeouting && millis() - previous_millis_cmd > LCD_TIMEOUT_TO_STATUS)
 			return -1;
@@ -1948,6 +1955,7 @@ int8_t lcd_show_fullscreen_message_yes_no_and_wait_P(const char *msg, bool allow
 			while (lcd_clicked());
 			delay(10);
 			while (lcd_clicked());
+			KEEPALIVE_STATE(IN_HANDLER);
 			return yes;
 		}
 	}
@@ -2158,7 +2166,7 @@ void prusa_statistics(int _message, uint8_t _fil_nr) {
 		prusa_stat_printerstatus(status_number);
 		prusa_stat_farm_number();
 		SERIAL_ECHOLN("}");
-		farm_timer = 5;
+		farm_timer = 4;
 		break;
 	case 21: // temperatures
 		SERIAL_ECHO("{");
@@ -2185,7 +2193,7 @@ void prusa_statistics(int _message, uint8_t _fil_nr) {
 		SERIAL_ECHOLN("}");
 		break;
 	case 92: // Error - Min temp
-		SERIAL_ECHOLN("{[ERR:3]");
+		SERIAL_ECHO("{[ERR:3]");
 		prusa_stat_farm_number();
 		SERIAL_ECHOLN("}");
 		break;
@@ -3001,7 +3009,7 @@ static char snmm_stop_print_menu() { //menu for choosing which filaments will be
 	lcd_print_at_PGM(1,3,MSG_CURRENT);
 	char cursor_pos = 1;
 	int enc_dif = 0;
-
+	KEEPALIVE_STATE(PAUSED_FOR_USER);
 	while (1) {
 		manage_heater();
 		manage_inactivity(true);
@@ -3029,10 +3037,10 @@ static char snmm_stop_print_menu() { //menu for choosing which filaments will be
 			while (lcd_clicked());
 			delay(10);
 			while (lcd_clicked());
+			KEEPALIVE_STATE(IN_HANDLER);
 			return(cursor_pos - 1);
 		}
-	}
-	
+	}	
 }
 
 char choose_extruder_menu() {
@@ -3051,7 +3059,7 @@ char choose_extruder_menu() {
 	for (int i = 0; i < 3; i++) {
 		lcd_print_at_PGM(1, i + 1, MSG_EXTRUDER);
 	}
-
+	KEEPALIVE_STATE(PAUSED_FOR_USER);
 	while (1) {
 
 		for (int i = 0; i < 3; i++) {
@@ -3115,6 +3123,7 @@ char choose_extruder_menu() {
 			while (lcd_clicked());
 			delay(10);
 			while (lcd_clicked());
+			KEEPALIVE_STATE(IN_HANDLER);
 			return(cursor_pos + first - 1);
 			
 		}
@@ -3304,7 +3313,7 @@ void display_loading() {
 	}
 }
 
-static void extr_adj(int extruder) //loading filament for SNMM
+void extr_adj(int extruder) //loading filament for SNMM
 {
 	bool correct;
 	max_feedrate[E_AXIS] =80;
@@ -3318,13 +3327,13 @@ static void extr_adj(int extruder) //loading filament for SNMM
 	case 3: lcd_display_message_fullscreen_P(MSG_FILAMENT_LOADING_T3); break;
 	default: lcd_display_message_fullscreen_P(MSG_FILAMENT_LOADING_T0); break;   
 	}
-			
+	KEEPALIVE_STATE(PAUSED_FOR_USER);
 	do{
 		extr_mov(0.001,1000);
 		delay_keep_alive(2);
 	} while (!lcd_clicked());
 	//delay_keep_alive(500);
-
+	KEEPALIVE_STATE(IN_HANDLER);
 	st_synchronize();
 	//correct = lcd_show_fullscreen_message_yes_no_and_wait_P(MSG_FIL_LOADED_CHECK, false);
 	//if (!correct) goto	START;
@@ -3640,8 +3649,8 @@ unsigned char lcd_choose_color() {
 	//-----------------------------------------------------
 	unsigned char items_no = 2;
 	const char *item[items_no];
-	item[0] = "Black";
-	item[1] = "Orange";
+	item[0] = "Orange";
+	item[1] = "Black";
 	//-----------------------------------------------------
 	unsigned char active_rows;
 	static int first = 0;
@@ -3663,10 +3672,9 @@ unsigned char lcd_choose_color() {
 
 		manage_heater();
 		manage_inactivity(true);
-
-		if (abs((enc_dif - encoderDiff)) > 4) {
-
-			if ((abs(enc_dif - encoderDiff)) > 1) {
+		proc_commands();
+		if (abs((enc_dif - encoderDiff)) > 12) {
+					
 				if (enc_dif > encoderDiff) {
 					cursor_pos--;
 				}
@@ -3674,7 +3682,7 @@ unsigned char lcd_choose_color() {
 				if (enc_dif < encoderDiff) {
 					cursor_pos++;
 				}
-
+				
 				if (cursor_pos > active_rows) {
 					cursor_pos = active_rows;
 					if (first < items_no - active_rows) {
@@ -3700,7 +3708,6 @@ unsigned char lcd_choose_color() {
 				lcd.print(">");
 				enc_dif = encoderDiff;
 				delay(100);
-			}
 
 		}
 
@@ -3708,7 +3715,11 @@ unsigned char lcd_choose_color() {
 			while (lcd_clicked());
 			delay(10);
 			while (lcd_clicked());
-			return(cursor_pos + first - 1);
+			switch(cursor_pos + first - 1) {
+			case 0: return 1; break;
+			case 1: return 0; break;
+			default: return 99; break;
+			}
 		}
 
 	}
@@ -3723,7 +3734,7 @@ void lcd_confirm_print()
 	int _ret = 0;
 	int _t = 0;
 
-
+	enc_dif = encoderDiff;
 	lcd_implementation_clear();
 
 	lcd.setCursor(0, 0);
@@ -3731,8 +3742,7 @@ void lcd_confirm_print()
 
 	do
 	{
-
-		if (abs((enc_dif - encoderDiff)) > 2) {
+		if (abs(enc_dif - encoderDiff) > 12) {
 			if (enc_dif > encoderDiff) {
 				cursor_pos--;
 			}
@@ -3740,6 +3750,7 @@ void lcd_confirm_print()
 			if (enc_dif < encoderDiff) {
 				cursor_pos++;
 			}
+			enc_dif = encoderDiff;
 		}
 
 		if (cursor_pos > 2) { cursor_pos = 2; }
@@ -3784,9 +3795,10 @@ void lcd_confirm_print()
 				NcTime = millis();
 			}
 		}
-
+		
 		manage_heater();
 		manage_inactivity();
+		proc_commands();
 
 	} while (_ret == 0);
 
@@ -4186,7 +4198,8 @@ void lcd_sdcard_menu()
   {
     if (_menuItemNr == _lineNr)
     {
-		const uint16_t nr = (sdSort == SD_SORT_NONE) ? (fileCnt - 1 - i) : i;
+		const uint16_t nr = ((sdSort == SD_SORT_NONE) || farm_mode) ? (fileCnt - 1 - i) : i;
+
 		 /* #ifdef SDCARD_RATHERRECENTFIRST
 			#ifndef SDCARD_SORT_ALPHA
 				fileCnt - 1 -
@@ -4805,6 +4818,7 @@ static bool lcd_selftest_fan_dialog(int _fan)
 	lcd.setCursor(1, 3); lcd_printPGM(MSG_SELFTEST_FAN_NO);
 
 	int8_t enc_dif = 0;
+	KEEPALIVE_STATE(PAUSED_FOR_USER);
 	do
 	{
 		switch (_fan)
@@ -4845,7 +4859,7 @@ static bool lcd_selftest_fan_dialog(int _fan)
 		delay(100);
 
 	} while (!lcd_clicked());
-
+	KEEPALIVE_STATE(IN_HANDLER);
 	SET_OUTPUT(EXTRUDER_0_AUTO_FAN_PIN);
 	WRITE(EXTRUDER_0_AUTO_FAN_PIN, 0);
 	SET_OUTPUT(FAN_PIN);

+ 1 - 1
Firmware/ultralcd.h

@@ -211,7 +211,7 @@ extern void lcd_implementation_print_at(uint8_t x, uint8_t y, const char *str);
 void change_extr(int extr);
 static void lcd_colorprint_change();
 static int get_ext_nr();
-static void extr_adj(int extruder);
+void extr_adj(int extruder);
 static void extr_adj_0();
 static void extr_adj_1();
 static void extr_adj_2();

+ 10 - 14
Firmware/ultralcd_implementation_hitachi_HD44780.h

@@ -830,21 +830,20 @@ static void lcd_implementation_status_screen()
     // If heating in progress, set flag
 	if (heating_status != 0) { custom_message = true; }
 
+	if (IS_SD_PRINTING) {
+		if (strcmp(longFilenameOLD, card.longFilename) != 0)
+		{
+			memset(longFilenameOLD, '\0', strlen(longFilenameOLD));
+			sprintf_P(longFilenameOLD, PSTR("%s"), card.longFilename);
+			scrollstuff = 0;
+		}
+	}
+
     // If printing from SD, show what we are printing
-	if (IS_SD_PRINTING)
+	if (IS_SD_PRINTING && !custom_message)
 	{
-
-      if(strcmp(longFilenameOLD, card.longFilename) != 0)
-	  {
-        memset(longFilenameOLD,'\0',strlen(longFilenameOLD));
-        sprintf_P(longFilenameOLD, PSTR("%s"), card.longFilename);
-        scrollstuff = 0;
-      }
-	  if (!custom_message) {
-
 		  if (strlen(card.longFilename) > LCD_WIDTH)
 		  {
-
 			  int inters = 0;
 			  int gh = scrollstuff;
 			  while (((gh - scrollstuff) < LCD_WIDTH) && (inters == 0))
@@ -873,9 +872,6 @@ static void lcd_implementation_status_screen()
 		  {
 			  lcd.print(longFilenameOLD);
 		  }
-	  }
-
-
     }
     // If not, check for other special events
 	else