Explorar o código

Merge branch 'MK3' into MK3_dev

Marek Bel %!s(int64=5) %!d(string=hai) anos
pai
achega
3b3d6ab472
Modificáronse 11 ficheiros con 689 adicións e 691 borrados
  1. 2 5
      Firmware/Marlin.h
  2. 29 31
      Firmware/Marlin_main.cpp
  3. 4 1
      Firmware/lcd.cpp
  4. 1 0
      Firmware/lcd.h
  5. 26 3
      Firmware/menu.cpp
  6. 11 3
      Firmware/menu.h
  7. 86 9
      Firmware/mmu.cpp
  8. 9 1
      Firmware/mmu.h
  9. 3 3
      Firmware/stepper.cpp
  10. 428 552
      Firmware/ultralcd.cpp
  11. 90 83
      Firmware/ultralcd.h

+ 2 - 5
Firmware/Marlin.h

@@ -316,9 +316,6 @@ void save_statistics(unsigned long _total_filament_used, unsigned long _total_pr
 extern unsigned int heating_status;
 extern unsigned int status_number;
 extern unsigned int heating_status_counter;
-extern bool custom_message;
-extern unsigned int custom_message_type;
-extern unsigned int custom_message_state;
 extern char snmm_filaments_used;
 extern unsigned long PingTime;
 extern unsigned long NcTime;
@@ -365,7 +362,7 @@ extern uint8_t print_percent_done_silent;
 extern uint32_t print_time_remaining_silent;
 #define PRINT_TIME_REMAINING_INIT 0xffff
 #define PRINT_PERCENT_DONE_INIT   0xff
-#define PRINTER_ACTIVE (IS_SD_PRINTING || is_usb_printing || isPrintPaused || (custom_message_type == 4) || saved_printing || (lcd_commands_type == LCD_COMMAND_V2_CAL) || card.paused || mmu_print_saved)
+#define PRINTER_ACTIVE (IS_SD_PRINTING || is_usb_printing || isPrintPaused || (custom_message_type == CUSTOM_MSG_TYPE_TEMCAL) || saved_printing || (lcd_commands_type == LCD_COMMAND_V2_CAL) || card.paused || mmu_print_saved)
 
 extern void calculate_extruder_multipliers();
 
@@ -420,7 +417,7 @@ extern void print_mesh_bed_leveling_table();
 
 //estimated time to end of the print
 extern uint16_t print_time_remaining();
-extern uint8_t print_percent_done();
+extern uint8_t calc_percent_done();
 
 #ifdef HOST_KEEPALIVE_FEATURE
 

+ 29 - 31
Firmware/Marlin_main.cpp

@@ -354,12 +354,13 @@ unsigned int status_number = 0;
 unsigned long total_filament_used;
 unsigned int heating_status;
 unsigned int heating_status_counter;
-bool custom_message;
 bool loading_flag = false;
-unsigned int custom_message_type;
-unsigned int custom_message_state;
+
+
+
 char snmm_filaments_used = 0;
 
+
 bool fan_state[2];
 int fan_edge_counter[2];
 int fan_speed[2];
@@ -2843,6 +2844,14 @@ void gcode_G28(bool home_x_axis, long home_x_value, bool home_y_axis, long home_
 #endif
 }
 
+void adjust_bed_reset()
+{
+	eeprom_update_byte((unsigned char*)EEPROM_BED_CORRECTION_VALID, 1);
+	eeprom_update_byte((unsigned char*)EEPROM_BED_CORRECTION_LEFT, 0);
+	eeprom_update_byte((unsigned char*)EEPROM_BED_CORRECTION_RIGHT, 0);
+	eeprom_update_byte((unsigned char*)EEPROM_BED_CORRECTION_FRONT, 0);
+	eeprom_update_byte((unsigned char*)EEPROM_BED_CORRECTION_REAR, 0);
+}
 
 bool gcode_M45(bool onlyZ, int8_t verbosity_level)
 {
@@ -3147,8 +3156,7 @@ static void gcode_M600(bool automatic, float x_position, float y_position, float
     enquecommand(cmd);
 
     lcd_setstatuspgm(_T(WELCOME_MSG));
-    custom_message = false;
-    custom_message_type = 0;
+    custom_message_type = CUSTOM_MSG_TYPE_STATUS;
 }
 
 
@@ -3161,8 +3169,7 @@ void gcode_M701()
 	else
 	{
 		enable_z();
-		custom_message = true;
-		custom_message_type = 2;
+		custom_message_type = CUSTOM_MSG_TYPE_F_LOAD;
 
 #ifdef FILAMENT_SENSOR
 		fsensor_oq_meassure_start(40);
@@ -3204,8 +3211,7 @@ void gcode_M701()
 		lcd_setstatuspgm(_T(WELCOME_MSG));
 		disable_z();
 		loading_flag = false;
-		custom_message = false;
-		custom_message_type = 0;
+		custom_message_type = CUSTOM_MSG_TYPE_STATUS;
 
 #ifdef FILAMENT_SENSOR
 		fsensor_oq_meassure_stop();
@@ -4040,10 +4046,9 @@ if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
 //			setTargetHotend(200, 0);
 			setTargetBed(70 + (start_temp - 30));
 
-			custom_message = true;
-			custom_message_type = 4;
+			custom_message_type = CUSTOM_MSG_TYPE_TEMCAL;
 			custom_message_state = 1;
-			custom_message = _T(MSG_TEMP_CALIBRATION);
+			lcd_setstatuspgm(_T(MSG_TEMP_CALIBRATION));
 			current_position[Z_AXIS] = MESH_HOME_Z_SEARCH;
 			plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 3000 / 60, active_extruder);
 			current_position[X_AXIS] = PINDA_PREHEAT_X;
@@ -4143,10 +4148,9 @@ if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
 			break;
 		}
 		puts_P(_N("PINDA probe calibration start"));
-		custom_message = true;
-		custom_message_type = 4;
+		custom_message_type = CUSTOM_MSG_TYPE_TEMCAL;
 		custom_message_state = 1;
-		custom_message = _T(MSG_TEMP_CALIBRATION);
+		lcd_setstatuspgm(_T(MSG_TEMP_CALIBRATION));
 		current_position[X_AXIS] = PINDA_PREHEAT_X;
 		current_position[Y_AXIS] = PINDA_PREHEAT_Y;
 		current_position[Z_AXIS] = PINDA_PREHEAT_Z;
@@ -4212,8 +4216,7 @@ if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
 			
 		
 		}
-		custom_message_type = 0;
-		custom_message = false;
+		custom_message_type = CUSTOM_MSG_TYPE_STATUS;
 
 		eeprom_update_byte((uint8_t*)EEPROM_CALIBRATION_STATUS_PINDA, 1);
 		puts_P(_N("Temperature calibration done."));
@@ -4347,11 +4350,9 @@ if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
 			break;
 		}
 		// Save custom message state, set a new custom message state to display: Calibrating point 9.
-		bool custom_message_old = custom_message;
 		unsigned int custom_message_type_old = custom_message_type;
 		unsigned int custom_message_state_old = custom_message_state;
-		custom_message = true;
-		custom_message_type = 1;
+		custom_message_type = CUSTOM_MSG_TYPE_MESHBL;
 		custom_message_state = (MESH_MEAS_NUM_X_POINTS * MESH_MEAS_NUM_Y_POINTS) + 10;
 		lcd_update(1);
 
@@ -4583,7 +4584,6 @@ if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
 		KEEPALIVE_STATE(NOT_BUSY);
 		// Restore custom message state
 		lcd_setstatuspgm(_T(WELCOME_MSG));
-		custom_message = custom_message_old;
 		custom_message_type = custom_message_type_old;
 		custom_message_state = custom_message_state_old;
 		mesh_bed_leveling_flag = false;
@@ -6800,8 +6800,9 @@ if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
 
 if (mmu_enabled)
 {
-		  printf_P(PSTR("T code: %d \n"), tmp_extruder);
-		  mmu_printf_P(PSTR("T%d\n"), tmp_extruder);
+		  //printf_P(PSTR("T code: %d \n"), tmp_extruder);
+		  //mmu_printf_P(PSTR("T%d\n"), tmp_extruder);
+		  mmu_command(MMU_CMD_T0 + tmp_extruder);
 
 		  manage_response(true, true);
 
@@ -7424,6 +7425,7 @@ if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
       handle_status_leds();
   #endif
   check_axes_activity();
+//  mmu_loop();
 }
 
 void kill(const char *full_screen_message, unsigned char id)
@@ -7793,11 +7795,9 @@ void bed_analysis(float x_dimension, float y_dimension, int x_points_num, int y_
 		enquecommand_front_P((PSTR("G1 Z5")));
 		return;
 	}
-	bool custom_message_old = custom_message;
 	unsigned int custom_message_type_old = custom_message_type;
 	unsigned int custom_message_state_old = custom_message_state;
-	custom_message = true;
-	custom_message_type = 1;
+	custom_message_type = CUSTOM_MSG_TYPE_MESHBL;
 	custom_message_state = (x_points_num * y_points_num) + 10;
 	lcd_update(1);
 
@@ -7947,8 +7947,7 @@ void bed_analysis(float x_dimension, float y_dimension, int x_points_num, int y_
 
 void temp_compensation_start() {
 	
-	custom_message = true;
-	custom_message_type = 5;
+	custom_message_type = CUSTOM_MSG_TYPE_TEMPRE;
 	custom_message_state = PINDA_HEAT_T + 1;
 	lcd_update(2);
 	if (degHotend(active_extruder) > EXTRUDE_MINTEMP) {
@@ -7969,9 +7968,8 @@ void temp_compensation_start() {
 		if (custom_message_state == 99 || custom_message_state == 9) lcd_update(2); //force whole display redraw if number of digits changed
 		else lcd_update(1);
 	}	
-	custom_message_type = 0;
+	custom_message_type = CUSTOM_MSG_TYPE_STATUS;
 	custom_message_state = 0;
-	custom_message = false;
 }
 
 void temp_compensation_apply() {
@@ -8818,7 +8816,7 @@ uint16_t print_time_remaining() {
 	return print_t;
 }
 
-uint8_t print_percent_done()
+uint8_t calc_percent_done()
 {
 	//in case that we have information from M73 gcode return percentage counted by slicer, else return percentage counted as byte_printed/filesize
 	uint8_t percent_done = 0;

+ 4 - 1
Firmware/lcd.cpp

@@ -537,7 +537,10 @@ int lcd_printf_P(const char* format, ...)
 	return ret;
 }
 
-
+void lcd_space(uint8_t n)
+{
+	while (n--) lcd_putc(' ');
+}
 
 
 void lcd_print(const char* s)

+ 1 - 0
Firmware/lcd.h

@@ -50,6 +50,7 @@ extern int lcd_putc(int c);
 extern int lcd_puts_P(const char* str);
 extern int lcd_puts_at_P(uint8_t c, uint8_t r, const char* str);
 extern int lcd_printf_P(const char* format, ...);
+extern void lcd_space(uint8_t n);
 
 extern void lcd_printNumber(unsigned long n, uint8_t base);
 extern void lcd_printFloat(double number, uint8_t digits);

+ 26 - 3
Firmware/menu.cpp

@@ -28,6 +28,9 @@ uint8_t menu_top = 0;
 
 uint8_t menu_clicked = 0;
 
+uint8_t menu_entering = 0;
+uint8_t menu_leaving = 0;
+
 menu_func_t menu_menu = 0;
 
 
@@ -76,12 +79,22 @@ void menu_end(void)
 
 void menu_back(void)
 {
-	if (menu_depth > 0) {
+	if (menu_depth > 0)
+	{
 		menu_depth--;		
 		menu_goto(menu_stack[menu_depth].menu, menu_stack[menu_depth].position, true, true);
 	}
 }
 
+void menu_back_no_reset(void)
+{
+	if (menu_depth > 0)
+	{
+		menu_depth--;		
+		menu_goto(menu_stack[menu_depth].menu, menu_stack[menu_depth].position, true, false);
+	}
+}
+
 void menu_back_if_clicked(void)
 {
 	if (lcd_clicked())
@@ -107,6 +120,16 @@ void menu_submenu(menu_func_t submenu)
 	}
 }
 
+void menu_submenu_no_reset(menu_func_t submenu)
+{
+	if (menu_depth <= MENU_DEPTH_MAX)
+	{
+		menu_stack[menu_depth].menu = menu_menu;
+		menu_stack[menu_depth++].position = lcd_encoder;
+		menu_goto(submenu, 0, true, false);
+	}
+}
+
 uint8_t menu_item_ret(void)
 {
 	lcd_beeper_quick_feedback();
@@ -295,7 +318,7 @@ void _menu_edit_int3(void)
 	if (LCD_CLICKED)
 	{
 		*((int*)(_md->editValue)) = (int)lcd_encoder;
-		menu_back();
+		menu_back_no_reset();
 	}
 }
 
@@ -311,7 +334,7 @@ uint8_t menu_item_edit_int3(const char* str, int16_t* pval, int16_t min_val, int
 		}
 		if (menu_clicked && (lcd_encoder == menu_item))
 		{
-			menu_submenu(_menu_edit_int3);
+			menu_submenu_no_reset(_menu_edit_int3);
 			_md->editLabel = str;
 			_md->editValue = pval;
 			_md->minEditValue = min_val;

+ 11 - 3
Firmware/menu.h

@@ -4,8 +4,9 @@
 
 #include <inttypes.h>
 
-#define MENU_DEPTH_MAX 4
-#define MENU_DATA_SIZE 32
+#define MENU_DEPTH_MAX       4
+#define MENU_DATA_SIZE      32
+#define MENU_DATA_EDIT_SIZE 12
 
 //Function pointer to menu functions.
 typedef void (*menu_func_t)(void);
@@ -25,12 +26,15 @@ extern uint8_t menu_depth;
 extern uint8_t menu_line;
 extern uint8_t menu_item;
 extern uint8_t menu_row;
-;
+
 //scroll offset in the current menu
 extern uint8_t menu_top;
 
 extern uint8_t menu_clicked;
 
+extern uint8_t menu_entering;
+extern uint8_t menu_leaving;
+
 //function pointer to the currently active menu
 extern menu_func_t menu_menu;
 
@@ -46,12 +50,16 @@ extern void menu_end(void);
 
 extern void menu_back(void);
 
+extern void menu_back_no_reset(void);
+
 extern void menu_back_if_clicked(void);
 
 extern void menu_back_if_clicked_fb(void);
 
 extern void menu_submenu(menu_func_t submenu);
 
+extern void menu_submenu_no_reset(menu_func_t submenu);
+
 extern uint8_t menu_item_ret(void);
 
 //extern int menu_draw_item_printf_P(char type_char, const char* format, ...);

+ 86 - 9
Firmware/mmu.cpp

@@ -26,8 +26,12 @@ extern char choose_extruder_menu();
 
 bool mmu_enabled = false;
 
+bool mmu_ready = false;
+
 int8_t mmu_state = 0;
 
+uint8_t mmu_cmd = 0;
+
 uint8_t mmu_extruder = 0;
 
 uint8_t tmp_extruder = 0;
@@ -38,6 +42,9 @@ int16_t mmu_version = -1;
 
 int16_t mmu_buildnr = -1;
 
+uint32_t mmu_last_request = 0;
+uint32_t mmu_last_response = 0;
+
 
 //clear rx buffer
 void mmu_clr_rx_buf(void)
@@ -49,7 +56,9 @@ void mmu_clr_rx_buf(void)
 int mmu_puts_P(const char* str)
 {
 	mmu_clr_rx_buf();                          //clear rx buffer
-    return fputs_P(str, uart2io);              //send command
+    int r = fputs_P(str, uart2io);             //send command
+	mmu_last_request = millis();
+	return r;
 }
 
 //send command - printf
@@ -60,19 +69,24 @@ int mmu_printf_P(const char* format, ...)
 	mmu_clr_rx_buf();                          //clear rx buffer
 	int r = vfprintf_P(uart2io, format, args); //send command
 	va_end(args);
+	mmu_last_request = millis();
 	return r;
 }
 
 //check 'ok' response
 int8_t mmu_rx_ok(void)
 {
-	return uart2_rx_str_P(PSTR("ok\n"));
+	int8_t res = uart2_rx_str_P(PSTR("ok\n"));
+	if (res == 1) mmu_last_response = millis();
+	return res;
 }
 
 //check 'start' response
 int8_t mmu_rx_start(void)
 {
-	return uart2_rx_str_P(PSTR("start\n"));
+	int8_t res = uart2_rx_str_P(PSTR("start\n"));
+	if (res == 1) mmu_last_response = millis();
+	return res;
 }
 
 //initialize mmu2 unit - first part - should be done at begining of startup process
@@ -138,6 +152,50 @@ void mmu_loop(void)
 			mmu_state = 1;
 		}
 		return;
+	case 1:
+		if (mmu_cmd) //command request ?
+		{
+			if ((mmu_cmd >= MMU_CMD_T0) && (mmu_cmd <= MMU_CMD_T4))
+			{
+				int extruder = mmu_cmd - MMU_CMD_T0;
+				printf_P(PSTR("MMU <= 'T%d'\n"), extruder);
+				mmu_printf_P(PSTR("T%d\n"), extruder);
+				mmu_state = 3; // wait for response
+			}
+			mmu_cmd = 0;
+		}
+		else if ((mmu_last_response + 1000) < millis()) //request every 1s
+		{
+			puts_P(PSTR("MMU <= 'P0'"));
+		    mmu_puts_P(PSTR("P0\n")); //send 'read finda' request
+			mmu_state = 2;
+		}
+		return;
+	case 2: //response to command P0
+		if (mmu_rx_ok() > 0)
+		{
+			fscanf_P(uart2io, PSTR("%hhu"), &mmu_finda); //scan finda from buffer
+			printf_P(PSTR("MMU => '%dok'\n"), mmu_finda);
+			mmu_state = 1;
+			mmu_ready = true;
+		}
+		else if ((mmu_last_request + 30000) < millis())
+		{ //resend request after timeout (30s)
+			mmu_state = 1;
+		}
+		return;
+	case 3: //response to commands T0-T4
+		if (mmu_rx_ok() > 0)
+		{
+			printf_P(PSTR("MMU => 'ok'\n"), mmu_finda);
+			mmu_ready = true;
+			mmu_state = 1;
+		}
+		else if ((mmu_last_request + 30000) < millis())
+		{ //resend request after timeout (30s)
+			mmu_state = 1;
+		}
+		return;
 	}
 }
 
@@ -162,9 +220,26 @@ int8_t mmu_set_filament_type(uint8_t extruder, uint8_t filament)
 	return timeout?1:0;
 }
 
-bool mmu_get_response(bool timeout)
+void mmu_command(uint8_t cmd)
 {
-	printf_P(PSTR("mmu_get_response - begin\n"));
+	mmu_cmd = cmd;
+	mmu_ready = false;
+}
+
+bool mmu_get_response(void)
+{
+	KEEPALIVE_STATE(IN_PROCESS);
+	while (!mmu_ready)
+	{
+		mmu_loop();
+		if (mmu_state != 3)
+			break;
+	}
+	bool ret = mmu_ready;
+	mmu_ready = false;
+	return ret;
+
+/*	printf_P(PSTR("mmu_get_response - begin\n"));
 	//waits for "ok" from mmu
 	//function returns true if "ok" was received
 	//if timeout is set to true function return false if there is no "ok" received before timeout
@@ -182,7 +257,7 @@ bool mmu_get_response(bool timeout)
 		}
 	}
 	printf_P(PSTR("mmu_get_response - end %d\n"), response?1:0);
-	return response;
+	return response;*/
 }
 
 
@@ -197,7 +272,7 @@ void manage_response(bool move_axes, bool turn_off_nozzle)
 	float y_position_bckp = current_position[Y_AXIS];	
 	while(!response)
 	{
-		  response = mmu_get_response(true); //wait for "ok" from mmu
+		  response = mmu_get_response(); //wait for "ok" from mmu
 		  if (!response) { //no "ok" was received in reserved time frame, user will fix the issue on mmu unit
 			  if (!mmu_print_saved) { //first occurence, we are saving current position, park print head in certain position and disable nozzle heater
 				  if (lcd_update_enabled) {
@@ -304,8 +379,10 @@ void mmu_M600_load_filament(bool automatic)
 		  lcd_print(" ");
 		  lcd_print(tmp_extruder + 1);
 		  snmm_filaments_used |= (1 << tmp_extruder); //for stop print
-		  printf_P(PSTR("T code: %d \n"), tmp_extruder);
-		  mmu_printf_P(PSTR("T%d\n"), tmp_extruder);
+
+//		  printf_P(PSTR("T code: %d \n"), tmp_extruder);
+//		  mmu_printf_P(PSTR("T%d\n"), tmp_extruder);
+		  mmu_command(MMU_CMD_T0 + tmp_extruder);
 
 		  manage_response(false, true);
     	  mmu_extruder = tmp_extruder; //filament change is finished

+ 9 - 1
Firmware/mmu.h

@@ -17,6 +17,13 @@ extern int16_t mmu_version;
 extern int16_t mmu_buildnr;
 
 
+#define MMU_CMD_NONE 0
+#define MMU_CMD_T0   0x10
+#define MMU_CMD_T1   0x11
+#define MMU_CMD_T2   0x12
+#define MMU_CMD_T3   0x13
+#define MMU_CMD_T4   0x14
+
 extern int mmu_puts_P(const char* str);
 
 extern int mmu_printf_P(const char* format, ...);
@@ -33,8 +40,9 @@ extern void mmu_reset(void);
 
 extern int8_t mmu_set_filament_type(uint8_t extruder, uint8_t filament);
 
+extern void mmu_command(uint8_t cmd);
 
-extern bool mmu_get_response(bool timeout);
+extern bool mmu_get_response(void);
 
 extern void manage_response(bool move_axes, bool turn_off_nozzle);
 

+ 3 - 3
Firmware/stepper.cpp

@@ -228,15 +228,15 @@ void checkHitEndstops()
    SERIAL_ECHORPGM(_T(MSG_ENDSTOPS_HIT));
    if(endstop_x_hit) {
      SERIAL_ECHOPAIR(" X:",(float)endstops_trigsteps[X_AXIS]/axis_steps_per_unit[X_AXIS]);
-     LCD_MESSAGERPGM(CAT2(_T(MSG_ENDSTOPS_HIT), PSTR("X")));
+//     LCD_MESSAGERPGM(CAT2(_T(MSG_ENDSTOPS_HIT), PSTR("X")));
    }
    if(endstop_y_hit) {
      SERIAL_ECHOPAIR(" Y:",(float)endstops_trigsteps[Y_AXIS]/axis_steps_per_unit[Y_AXIS]);
-     LCD_MESSAGERPGM(CAT2(_T(MSG_ENDSTOPS_HIT), PSTR("Y")));
+//     LCD_MESSAGERPGM(CAT2(_T(MSG_ENDSTOPS_HIT), PSTR("Y")));
    }
    if(endstop_z_hit) {
      SERIAL_ECHOPAIR(" Z:",(float)endstops_trigsteps[Z_AXIS]/axis_steps_per_unit[Z_AXIS]);
-     LCD_MESSAGERPGM(CAT2(_T(MSG_ENDSTOPS_HIT),PSTR("Z")));
+//     LCD_MESSAGERPGM(CAT2(_T(MSG_ENDSTOPS_HIT),PSTR("Z")));
    }
    SERIAL_ECHOLN("");
    endstop_x_hit=false;

+ 428 - 552
Firmware/ultralcd.cpp

@@ -63,13 +63,17 @@ extern void crashdet_disable();
 #endif //TMC2130
 
 
-
 #ifdef SDCARD_SORT_ALPHA
- bool presort_flag = false;
+bool presort_flag = false;
 #endif
 
-int lcd_commands_type=LCD_COMMAND_IDLE;
-int lcd_commands_step=0;
+int lcd_commands_type = LCD_COMMAND_IDLE;
+int lcd_commands_step = 0;
+
+unsigned int custom_message_type = CUSTOM_MSG_TYPE_STATUS;
+unsigned int custom_message_state = 0;
+
+
 bool isPrintPaused = false;
 uint8_t farm_mode = 0;
 int farm_no = 0;
@@ -81,7 +85,6 @@ unsigned long display_time; //just timer for showing pid finished message on lcd
 float pid_temp = DEFAULT_PID_TEMP;
 
 static bool forceMenuExpire = false;
-bool menuExiting = false;
 
 
 static float manual_feedrate[] = MANUAL_FEEDRATE;
@@ -225,62 +228,6 @@ bool wait_for_unclick;
 const char STR_SEPARATOR[] PROGMEM = "------------";
 
 
-
-
-static inline void lcd_print_percent_done() {
-	if (is_usb_printing)
-	{
-		lcd_puts_P(PSTR("USB"));
-	}
-	else if(IS_SD_PRINTING)
-	{
-		lcd_puts_P(PSTR("SD"));
-	}
-	else
-	{
-		lcd_puts_P(PSTR("  "));
-	}
-	if (IS_SD_PRINTING || (PRINTER_ACTIVE && (print_percent_done_normal != PRINT_PERCENT_DONE_INIT)))
-	{
-		lcd_print(itostr3(print_percent_done()));
-	}
-	else
-	{
-		lcd_puts_P(PSTR("---"));
-	}
-	lcd_puts_P(PSTR("% "));
-}
-
-static inline void lcd_print_time() {
-	//if remaining print time estimation is available print it else print elapsed time
-	//uses 8 characters
-	uint16_t print_t = 0;
-	if (print_time_remaining_normal != PRINT_TIME_REMAINING_INIT){
-		print_t = print_time_remaining();
-	}
-	else if(starttime != 0){
-		print_t = millis() / 60000 - starttime / 60000;	
-	}
-	lcd_print(LCD_STR_CLOCK[0]);
-	if((PRINTER_ACTIVE) && ((print_time_remaining_normal != PRINT_TIME_REMAINING_INIT)||(starttime != 0)))
-	{
-		lcd_print(itostr2(print_t/60));
-        lcd_print(':');
-        lcd_print(itostr2(print_t%60));	
-		if (print_time_remaining_normal != PRINT_TIME_REMAINING_INIT)
-		{
-			lcd_print('R');
-			(feedmultiply == 100) ? lcd_print(' ') : lcd_print('?');
-		}
-		else {
-			lcd_puts_P(PSTR("  "));
-		}
-    }else{
-        lcd_puts_P(PSTR("--:--  "));
-    }
-}
-
-
 static void lcd_implementation_drawmenu_sdfile_selected(uint8_t row, char* longFilename)
 {
     char c;
@@ -523,121 +470,78 @@ static uint8_t menu_item_sdfile(const char*
 #endif //NEW_SD_MENU
 }
 
-
-
-
-
-
-
-
-
-/*
-
-20x4   |01234567890123456789|
-       |T 000/000D  Z000.0  |
-       |B 000/000D  F100%   |
-       |SD100%      T--:--  |
-       |Status line.........|
-*/
-static void lcd_implementation_status_screen()
+// Print temperature (nozzle/bed) (9 chars total)
+void lcdui_print_temp(char type, int val_current, int val_target)
 {
-   
-    int tHotend=int(degHotend(0) + 0.5);
-    int tTarget=int(degTargetHotend(0) + 0.5);
-
-    //Print the hotend temperature
-    lcd_set_cursor(0, 0);
-    lcd_print(LCD_STR_THERMOMETER[0]);
-    lcd_print(itostr3(tHotend));
-    lcd_print('/');
-    lcd_print(itostr3left(tTarget));
-    lcd_puts_P(PSTR(LCD_STR_DEGREE " "));
-    lcd_puts_P(PSTR("  "));
-
-    //Print the Z coordinates
-    lcd_set_cursor(LCD_WIDTH - 8-2, 0);
-#if 1
-    lcd_puts_P(PSTR("  Z"));
-    if (custom_message_type == 1) {
-        // In a bed calibration mode.
-        lcd_puts_P(PSTR("   --- "));
-    } else {
-        lcd_print(ftostr32sp(current_position[Z_AXIS] + 0.00001));
-        lcd_print(' ');
-    }
-#else
-    lcd_puts_P(PSTR(" Queue:"));
-    lcd_print(int(moves_planned()));
-    lcd_print(' ');
-#endif
+	int chars = lcd_printf_P(_N("%c%3d/%d%c"), type, val_current, val_target, LCD_STR_DEGREE[0]);
+	lcd_space(9 - chars);
+}
 
-    //Print the Bedtemperature
-    lcd_set_cursor(0, 1);
-    tHotend=int(degBed() + 0.5);
-    tTarget=int(degTargetBed() + 0.5);
-    lcd_print(LCD_STR_BEDTEMP[0]);
-    lcd_print(itostr3(tHotend));
-    lcd_print('/');
-    lcd_print(itostr3left(tTarget));
-    lcd_puts_P(PSTR(LCD_STR_DEGREE " "));
-    lcd_puts_P(PSTR("  "));
+// Print Z-coordinate (8 chars total)
+void lcdui_print_Z_coord(void)
+{
+	int chars = 8;
+    if (custom_message_type == CUSTOM_MSG_TYPE_MESHBL)
+        lcd_puts_P(_N("Z   --- "));
+    else
+		chars = lcd_printf_P(_N("Z%6.2f "), current_position[Z_AXIS]);
+//	lcd_space(8 - chars);
+}
 
 #ifdef PLANNER_DIAGNOSTICS
-    //Print Feedrate
-    lcd_set_cursor(LCD_WIDTH - 8-2, 1);
-    lcd_print(LCD_STR_FEEDRATE[0]);
-    lcd_print(itostr3(feedmultiply));
-    lcd_puts_P(PSTR("%  Q"));
-    {
-      uint8_t queue = planner_queue_min();
-      if (queue < (BLOCK_BUFFER_SIZE >> 1)) {
-        lcd_putc('!');
-      } else {
-        lcd_putc((char)(queue / 10) + '0');
-        queue %= 10;
-      }
-      lcd_putc((char)queue + '0');
-      planner_queue_min_reset();
-    }
-#else /* PLANNER_DIAGNOSTICS */
-    //Print Feedrate
-    lcd_set_cursor(LCD_WIDTH - 8-2, 1);
-    lcd_puts_P(PSTR("  "));
-/*
-	if (maxlimit_status)
-	{
-		maxlimit_status = 0;
-		lcd_print('!');
-	}
-	else*/
-		lcd_print(LCD_STR_FEEDRATE[0]);
-    lcd_print(itostr3(feedmultiply));
-    lcd_puts_P(PSTR("%     "));
-#endif /* PLANNER_DIAGNOSTICS */
-
-	bool print_sd_status = true;
-	
-#ifdef PINDA_THERMISTOR
-//	if (farm_mode && (custom_message_type == 4))
-	if (false)
+// Print planner diagnostics (8 chars total)
+void lcdui_print_planner_diag(void)
+{
+	lcd_set_cursor(LCD_WIDTH - 8-2, 1);
+	lcd_print(LCD_STR_FEEDRATE[0]);
+	lcd_print(itostr3(feedmultiply));
+	lcd_puts_P(PSTR("%  Q"));
 	{
-		lcd_set_cursor(0, 2);
-		lcd_puts_P(PSTR("P"));
-		lcd_print(ftostr3(current_temperature_pinda));
-		lcd_puts_P(PSTR(LCD_STR_DEGREE " "));
-		print_sd_status = false;
+		uint8_t queue = planner_queue_min();
+		if (queue < (BLOCK_BUFFER_SIZE >> 1))
+		lcd_putc('!');
+		else
+		{
+			lcd_putc((char)(queue / 10) + '0');
+			queue %= 10;
+		}
+		lcd_putc((char)queue + '0');
+		planner_queue_min_reset();
 	}
-#endif //PINDA_THERMISTOR
+}
+#endif // PLANNER_DIAGNOSTICS
 
+// Print feedrate (8 chars total)
+void lcdui_print_feedrate(void)
+{
+	int chars = lcd_printf_P(_N("%c%3d%%"), LCD_STR_FEEDRATE[0], feedmultiply);
+	lcd_space(8 - chars);
+}
 
-if (print_sd_status)
+// Print percent done in form "USB---%", " SD---%", "   ---%" (7 chars total)
+void lcdui_print_percent_done(void)
 {
-    //Print SD status
-    lcd_set_cursor(0, 2);
-	lcd_print_percent_done();
+	const char* src = is_usb_printing?_N("USB"):(IS_SD_PRINTING?_N(" SD"):_N("   "));
+	char per[4];
+	bool num = IS_SD_PRINTING || (PRINTER_ACTIVE && (print_percent_done_normal != PRINT_PERCENT_DONE_INIT));
+	sprintf_P(per, num?_N("%3hhd"):_N("---"), calc_percent_done());
+	int chars = lcd_printf_P(_N("%3S%3s%%"), src, per);
+//	lcd_space(7 - chars);
+}
 
+// Print extruder status (5 chars total)
+void lcdui_print_extruder(void)
+{
+	int chars = lcd_printf_P(_N(" T%u"), mmu_extruder);
+	lcd_space(5 - chars);
 }
 
+// Print farm number (5 chars total)
+void lcdui_print_farm(void)
+{
+	int chars = lcd_printf_P(_N(" F0  "));
+//	lcd_space(5 - chars);
+/*
 	// Farm number display
 	if (farm_mode)
 	{
@@ -667,29 +571,45 @@ if (print_sd_status)
 		lcd_puts_P(PSTR(" "));
 #endif
 	}
+*/
+}
 
 #ifdef CMD_DIAGNOSTICS
+// Print CMD queue diagnostic (8 chars total)
+void lcdui_print_cmd_diag(void)
+{
 	lcd_set_cursor(LCD_WIDTH - 8 -1, 2);
 	lcd_puts_P(PSTR("      C"));
 	lcd_print(buflen);	// number of commands in cmd buffer
 	if (buflen < 9) lcd_puts_P(" ");
-#else
-    //Print time
-	lcd_set_cursor(LCD_WIDTH - 8, 2);
-	lcd_print_time();
+}
 #endif //CMD_DIAGNOSTICS
 
-#ifdef DEBUG_DISABLE_LCD_STATUS_LINE
-	return;
-#endif //DEBUG_DISABLE_LCD_STATUS_LINE
-
-    //Print status line
-    lcd_set_cursor(0, 3);
-
-    // If heating in progress, set flag
-	if (heating_status != 0) { custom_message = true; }
+// Print time (8 chars total)
+void lcdui_print_time(void)
+{
+	//if remaining print time estimation is available print it else print elapsed time
+	uint16_t print_t = 0;
+	if (print_time_remaining_normal != PRINT_TIME_REMAINING_INIT)
+		print_t = print_time_remaining();
+	else if(starttime != 0)
+		print_t = millis() / 60000 - starttime / 60000;
+	int chars = 0;
+	if ((PRINTER_ACTIVE) && ((print_time_remaining_normal != PRINT_TIME_REMAINING_INIT) || (starttime != 0)))
+	{
+		char suff = (print_time_remaining_normal == PRINT_TIME_REMAINING_INIT)?' ':'R';
+		chars = lcd_printf_P(_N("%c%02u:%02u%c"), LCD_STR_CLOCK[0], print_t / 60, print_t % 60, suff);
+	}
+	else
+		chars = lcd_printf_P(_N("%c--:--  "), LCD_STR_CLOCK[0]);
+	lcd_space(8 - chars);
+}
 
-	if (IS_SD_PRINTING) {
+//Print status line on status screen
+void lcdui_print_status_line(void)
+{
+	if (IS_SD_PRINTING)
+	{
 		if (strcmp(longFilenameOLD, card.longFilename) != 0)
 		{
 			memset(longFilenameOLD, '\0', strlen(longFilenameOLD));
@@ -698,150 +618,127 @@ if (print_sd_status)
 		}
 	}
 
-    // If printing from SD, show what we are printing
-	if ((IS_SD_PRINTING) && !custom_message
-#ifdef DEBUG_BUILD
-    && lcd_status_message[0] == 0
-#endif /* DEBUG_BUILD */
-    )
+	if (heating_status)
+	{ // If heating flag, show progress of heating
+		heating_status_counter++;
+		if (heating_status_counter > 13)
+		{
+			heating_status_counter = 0;
+		}
+		lcd_set_cursor(7, 3);
+		lcd_puts_P(PSTR("             "));
 
-	{
-      if(strlen(card.longFilename) > LCD_WIDTH)
-      {
-
-			  int inters = 0;
-			  int gh = scrollstuff;
-			  while (((gh - scrollstuff) < LCD_WIDTH) && (inters == 0))
-			  {
-
-				  if (card.longFilename[gh] == '\0')
-				  {
-					  lcd_set_cursor(gh - scrollstuff, 3);
-					  lcd_print(card.longFilename[gh - 1]);
-					  scrollstuff = 0;
-					  gh = scrollstuff;
-					  inters = 1;
-				  }
-				  else
-				  {
-					  lcd_set_cursor(gh - scrollstuff, 3);
-					  lcd_print(card.longFilename[gh - 1]);
-					  gh++;
-				  }
-
-
-			  }
-			  scrollstuff++;
-      }
-      else
-      {
-			  lcd_print(longFilenameOLD);
-      }
+		for (unsigned int dots = 0; dots < heating_status_counter; dots++)
+		{
+			lcd_set_cursor(7 + dots, 3);
+			lcd_print('.');
+		}
+		switch (heating_status)
+		{
+		case 1:
+			lcd_set_cursor(0, 3);
+			lcd_puts_P(_T(MSG_HEATING));
+			break;
+		case 2:
+			lcd_set_cursor(0, 3);
+			lcd_puts_P(_T(MSG_HEATING_COMPLETE));
+			heating_status = 0;
+			heating_status_counter = 0;
+			break;
+		case 3:
+			lcd_set_cursor(0, 3);
+			lcd_puts_P(_T(MSG_BED_HEATING));
+			break;
+		case 4:
+			lcd_set_cursor(0, 3);
+			lcd_puts_P(_T(MSG_BED_DONE));
+			heating_status = 0;
+			heating_status_counter = 0;
+			break;
+		default:
+			break;
+		}
 	}
-	    
-    // If not, check for other special events
-	else
-	{
-        
-		if (custom_message)
+	else if ((IS_SD_PRINTING) && (custom_message_type == CUSTOM_MSG_TYPE_STATUS))
+	{ // If printing from SD, show what we are printing
+		if(strlen(card.longFilename) > LCD_WIDTH)
 		{
-            // If heating flag, show progress of heating.
-			if (heating_status != 0)
+			int inters = 0;
+			int gh = scrollstuff;
+			while (((gh - scrollstuff) < LCD_WIDTH) && (inters == 0))
 			{
-				heating_status_counter++;
-				if (heating_status_counter > 13)
+				if (card.longFilename[gh] == '\0')
 				{
-					heating_status_counter = 0;
+					lcd_set_cursor(gh - scrollstuff, 3);
+					lcd_print(card.longFilename[gh - 1]);
+					scrollstuff = 0;
+					gh = scrollstuff;
+					inters = 1;
 				}
-				lcd_set_cursor(7, 3);
-				lcd_puts_P(PSTR("             "));
-
-				for (unsigned int dots = 0; dots < heating_status_counter; dots++)
-				{
-					lcd_set_cursor(7 + dots, 3);
-					lcd_print('.');
-				}
-
-				switch (heating_status)
+				else
 				{
-				case 1:
-					lcd_set_cursor(0, 3);
-					lcd_puts_P(_T(MSG_HEATING));
-					break;
-				case 2:
-					lcd_set_cursor(0, 3);
-					lcd_puts_P(_T(MSG_HEATING_COMPLETE));
-					heating_status = 0;
-					heating_status_counter = 0;
-					custom_message = false;
-					break;
-				case 3:
-					lcd_set_cursor(0, 3);
-					lcd_puts_P(_T(MSG_BED_HEATING));
-					break;
-				case 4:
-					lcd_set_cursor(0, 3);
-					lcd_puts_P(_T(MSG_BED_DONE));
-					heating_status = 0;
-					heating_status_counter = 0;
-					custom_message = false;
-					break;
-				default:
-					break;
+					lcd_set_cursor(gh - scrollstuff, 3);
+					lcd_print(card.longFilename[gh - 1]);
+					gh++;
 				}
 			}
-            
-            // If mesh bed leveling in progress, show the status
-            
-			if (custom_message_type == 1)
+			scrollstuff++;
+		}
+		else
+		{
+			lcd_print(longFilenameOLD);
+		}
+	}
+	else
+	{ // Otherwise check for other special events
+   		switch (custom_message_type)
+		{
+		case CUSTOM_MSG_TYPE_STATUS: // Nothing special, print status message normally
+			lcd_print(lcd_status_message);
+			break;
+		case CUSTOM_MSG_TYPE_MESHBL: // If mesh bed leveling in progress, show the status
+			if (custom_message_state > 10)
+			{
+				lcd_set_cursor(0, 3);
+				lcd_puts_P(PSTR("                    "));
+				lcd_set_cursor(0, 3);
+				lcd_puts_P(_T(MSG_CALIBRATE_Z_AUTO));
+				lcd_puts_P(PSTR(" : "));
+				lcd_print(custom_message_state-10);
+			}
+			else
 			{
-				if (custom_message_state > 10)
+				if (custom_message_state == 3)
 				{
-					lcd_set_cursor(0, 3);
-					lcd_puts_P(PSTR("                    "));
-					lcd_set_cursor(0, 3);
-					lcd_puts_P(_T(MSG_CALIBRATE_Z_AUTO));
-					lcd_puts_P(PSTR(" : "));
-					lcd_print(custom_message_state-10);
+					lcd_puts_P(_T(WELCOME_MSG));
+					lcd_setstatuspgm(_T(WELCOME_MSG));
+					custom_message_type = CUSTOM_MSG_TYPE_STATUS;
 				}
-				else
+				if (custom_message_state > 3 && custom_message_state <= 10 )
 				{
-					if (custom_message_state == 3)
-					{
-						lcd_puts_P(_T(WELCOME_MSG));
-						lcd_setstatuspgm(_T(WELCOME_MSG));
-						custom_message = false;
-						custom_message_type = 0;
-					}
-					if (custom_message_state > 3 && custom_message_state <= 10 )
-					{
-						lcd_set_cursor(0, 3);
-						lcd_puts_P(PSTR("                   "));
-						lcd_set_cursor(0, 3);
-						lcd_puts_P(_i("Calibration done"));////MSG_HOMEYZ_DONE c=0 r=0
-						custom_message_state--;
-					}
+					lcd_set_cursor(0, 3);
+					lcd_puts_P(PSTR("                   "));
+					lcd_set_cursor(0, 3);
+					lcd_puts_P(_i("Calibration done"));////MSG_HOMEYZ_DONE c=0 r=0
+					custom_message_state--;
 				}
-
 			}
-            // If loading filament, print status
-			if (custom_message_type == 2)
+			break;
+		case CUSTOM_MSG_TYPE_F_LOAD: // If loading filament, print status
+			lcd_print(lcd_status_message);
+			break;
+		case CUSTOM_MSG_TYPE_PIDCAL: // PID tuning in progress
+			lcd_print(lcd_status_message);
+			if (pid_cycle <= pid_number_of_cycles && custom_message_state > 0)
 			{
-				lcd_print(lcd_status_message);
-			}
-			// PID tuning in progress
-			if (custom_message_type == 3) {
-				lcd_print(lcd_status_message);
-				if (pid_cycle <= pid_number_of_cycles && custom_message_state > 0) {
-					lcd_set_cursor(10, 3);
-					lcd_print(itostr3(pid_cycle));
-					
-					lcd_print('/');
-					lcd_print(itostr3left(pid_number_of_cycles));
-				}
+				lcd_set_cursor(10, 3);
+				lcd_print(itostr3(pid_cycle));
+				lcd_print('/');
+				lcd_print(itostr3left(pid_number_of_cycles));
 			}
-			// PINDA temp calibration in progress
-			if (custom_message_type == 4) {
+			break;
+		case CUSTOM_MSG_TYPE_TEMCAL: // PINDA temp calibration in progress
+			{
 				char progress[4];
 				lcd_set_cursor(0, 3);
 				lcd_puts_P(_T(MSG_TEMP_CALIBRATION));
@@ -849,199 +746,214 @@ if (print_sd_status)
 				sprintf(progress, "%d/6", custom_message_state);
 				lcd_print(progress);
 			}
-			// temp compensation preheat
-			if (custom_message_type == 5) {
-				lcd_set_cursor(0, 3);
-				lcd_puts_P(_i("PINDA Heating"));////MSG_PINDA_PREHEAT c=20 r=1
-				if (custom_message_state <= PINDA_HEAT_T) {
-					lcd_puts_P(PSTR(": "));
-					lcd_print(custom_message_state); //seconds
-					lcd_print(' ');
-					
-				}
+			break;
+		case CUSTOM_MSG_TYPE_TEMPRE: // temp compensation preheat
+			lcd_set_cursor(0, 3);
+			lcd_puts_P(_i("PINDA Heating"));////MSG_PINDA_PREHEAT c=20 r=1
+			if (custom_message_state <= PINDA_HEAT_T)
+			{
+				lcd_puts_P(PSTR(": "));
+				lcd_print(custom_message_state); //seconds
+				lcd_print(' ');
 			}
-
-
-		}
-	else
-		{
-            // Nothing special, print status message normally
-			lcd_print(lcd_status_message);
+			break;
 		}
 	}
     
     // Fill the rest of line to have nice and clean output
-    for(int fillspace = 0; fillspace<20;fillspace++)
-	{
-      if((lcd_status_message[fillspace] > 31 ))
-	  {
-      }
-	  else
-	  {
-        lcd_print(' ');
-      }
-    }
-	
+	for(int fillspace = 0; fillspace < 20; fillspace++)
+		if ((lcd_status_message[fillspace] <= 31 ))
+			lcd_print(' ');
 }
 
+void lcdui_print_status_screen(void)
+{
+//|01234567890123456789|
+//|N 000/000D  Z000.0  |
+//|B 000/000D  F100%   |
+//|USB100% T0  t--:--  |
+//|Status line.........|
+//----------------------
+//N - nozzle temp symbol LCD_STR_THERMOMETER
+//B - bed temp symbol LCD_STR_BEDTEMP
+//F - feedrate symbol LCD_STR_FEEDRATE
+//t - clock symbol LCD_STR_THERMOMETER
 
-/* Main status screen. It's up to the implementation specific part to show what is needed. As this is very display dependent */
+    lcd_set_cursor(0, 0); //line 0
 
-static void lcd_status_screen()
-{
-  if (firstrun == 1) 
-  {
-    firstrun = 0;
-     
-      if(lcd_status_message_level == 0){
-          strncpy_P(lcd_status_message, _T(WELCOME_MSG), LCD_WIDTH);
-		lcd_finishstatus();
-      }
-	if (eeprom_read_byte((uint8_t *)EEPROM_TOTALTIME) == 255 && eeprom_read_byte((uint8_t *)EEPROM_TOTALTIME + 1) == 255 && eeprom_read_byte((uint8_t *)EEPROM_TOTALTIME + 2) == 255 && eeprom_read_byte((uint8_t *)EEPROM_TOTALTIME + 3) == 255)
-	{
-		eeprom_update_dword((uint32_t *)EEPROM_TOTALTIME, 0);
-		eeprom_update_dword((uint32_t *)EEPROM_FILAMENTUSED, 0);
-	}
-	
-  }
+    //Print the hotend temperature (9 chars total)
+	lcdui_print_temp(LCD_STR_THERMOMETER[0], (int)(degHotend(0) + 0.5), (int)(degTargetHotend(0) + 0.5));
 
-  
-  if (lcd_status_update_delay)
-    lcd_status_update_delay--;
-  else
-    lcd_draw_update = 1;
-  if (lcd_draw_update)
-  {
-    ReInitLCD++;
+	lcd_space(3); //3 spaces
 
+    //Print Z-coordinate (8 chars total)
+	lcdui_print_Z_coord();
 
-    if (ReInitLCD == 30)
-	{
-      lcd_refresh(); // to maybe revive the LCD if static electricity killed it.
-      ReInitLCD = 0 ;
-    }
+    lcd_set_cursor(0, 1); //line 1
+
+	//Print the Bed temperature (9 chars total)
+	lcdui_print_temp(LCD_STR_BEDTEMP[0], (int)(degBed() + 0.5), (int)(degTargetBed() + 0.5));
+
+	lcd_space(3); //3 spaces
+
+#ifdef PLANNER_DIAGNOSTICS
+	//Print planner diagnostics (8 chars)
+	lcdui_print_planner_diag();
+#else // PLANNER_DIAGNOSTICS
+    //Print Feedrate (8 chars)
+	lcdui_print_feedrate();
+#endif // PLANNER_DIAGNOSTICS
+
+	lcd_set_cursor(0, 2); //line 2
+
+	//Print SD status (7 chars)
+	lcdui_print_percent_done();
+
+	if (mmu_enabled)
+		//Print extruder status (5 chars)
+		lcdui_print_extruder();
+	else if (farm_mode)
+		//Print farm number (5 chars)
+		lcdui_print_farm();
 	else
-	{
+		lcd_space(5); //5 spaces
 
-      if ((ReInitLCD % 10) == 0)
-	  {
-        lcd_refresh_noclear(); //to maybe revive the LCD if static electricity killed it.
-      }
+#ifdef CMD_DIAGNOSTICS
+    //Print cmd queue diagnostics (8chars)
+	lcdui_print_cmd_diag();
+#else
+    //Print time (8chars)
+	lcdui_print_time();
+#endif //CMD_DIAGNOSTICS
 
-    }
+    lcd_set_cursor(0, 3); //line 3
 
+#ifndef DEBUG_DISABLE_LCD_STATUS_LINE
+	lcdui_print_status_line();
+#endif //DEBUG_DISABLE_LCD_STATUS_LINE
 
-    lcd_implementation_status_screen();
-    //lcd_clear();
+}
 
-	if (farm_mode)
+// Main status screen. It's up to the implementation specific part to show what is needed. As this is very display dependent
+static void lcd_status_screen()
+{
+	if (firstrun == 1) 
 	{
-		farm_timer--;
-		if (farm_timer < 1)
+		firstrun = 0;
+		if(lcd_status_message_level == 0)
 		{
-			farm_timer = 10;
-			prusa_statistics(0);
+			strncpy_P(lcd_status_message, _T(WELCOME_MSG), LCD_WIDTH);
+			lcd_finishstatus();
 		}
-		switch (farm_timer)
+		if (eeprom_read_byte((uint8_t *)EEPROM_TOTALTIME) == 255 && eeprom_read_byte((uint8_t *)EEPROM_TOTALTIME + 1) == 255 && eeprom_read_byte((uint8_t *)EEPROM_TOTALTIME + 2) == 255 && eeprom_read_byte((uint8_t *)EEPROM_TOTALTIME + 3) == 255)
 		{
-		case 8:
-			prusa_statistics(21);
-			break;
-		case 5:
-			if (IS_SD_PRINTING)
-			{
-				prusa_statistics(20);
-			}
-			break;
+			eeprom_update_dword((uint32_t *)EEPROM_TOTALTIME, 0);
+			eeprom_update_dword((uint32_t *)EEPROM_FILAMENTUSED, 0);
 		}
-	} // end of farm_mode
+	}
 
+	if (lcd_status_update_delay)
+		lcd_status_update_delay--;
+	else
+		lcd_draw_update = 1;
 
 
+	if (lcd_draw_update)
+	{
+		ReInitLCD++;
+		if (ReInitLCD == 30)
+		{
+			lcd_refresh(); // to maybe revive the LCD if static electricity killed it.
+			ReInitLCD = 0 ;
+		}
+		else
+		{
+			if ((ReInitLCD % 10) == 0)
+				lcd_refresh_noclear(); //to maybe revive the LCD if static electricity killed it.
+		}
 
+		lcdui_print_status_screen();
 
-    lcd_status_update_delay = 10;   /* redraw the main screen every second. This is easier then trying keep track of all things that change on the screen */
-	if (lcd_commands_type != LCD_COMMAND_IDLE)
-	{
-		lcd_commands();
-	}
-	
+		if (farm_mode)
+		{
+			farm_timer--;
+			if (farm_timer < 1)
+			{
+				farm_timer = 10;
+				prusa_statistics(0);
+			}
+			switch (farm_timer)
+			{
+			case 8:
+				prusa_statistics(21);
+				break;
+			case 5:
+				if (IS_SD_PRINTING)
+					prusa_statistics(20);
+				break;
+			}
+		} // end of farm_mode
 
-  } // end of lcd_draw_update
+		lcd_status_update_delay = 10;   /* redraw the main screen every second. This is easier then trying keep track of all things that change on the screen */
+		if (lcd_commands_type != LCD_COMMAND_IDLE)
+			lcd_commands();
+	} // end of lcd_draw_update
 
-  bool current_click = LCD_CLICKED;
+	bool current_click = LCD_CLICKED;
 
-  if (ignore_click) {
-    if (wait_for_unclick) {
-      if (!current_click) {
-        ignore_click = wait_for_unclick = false;
-      }
-      else {
-        current_click = false;
-      }
-    }
-    else if (current_click) {
-      lcd_quick_feedback();
-      wait_for_unclick = true;
-      current_click = false;
-    }
-  }
+	if (ignore_click)
+	{
+		if (wait_for_unclick)
+		{
+			if (!current_click)
+				ignore_click = wait_for_unclick = false;
+			else
+				current_click = false;
+		}
+		else if (current_click)
+		{
+			lcd_quick_feedback();
+			wait_for_unclick = true;
+			current_click = false;
+		}
+	}
 
-  if (current_click && (lcd_commands_type != LCD_COMMAND_STOP_PRINT)) //click is aborted unless stop print finishes
-  {
-	menu_depth = 0; //redundant, as already done in lcd_return_to_status(), just to be sure
-    menu_submenu(lcd_main_menu);
-    lcd_refresh(); // to maybe revive the LCD if static electricity killed it.
-  }
+	if (current_click && (lcd_commands_type != LCD_COMMAND_STOP_PRINT)) //click is aborted unless stop print finishes
+	{
+		menu_depth = 0; //redundant, as already done in lcd_return_to_status(), just to be sure
+		menu_submenu(lcd_main_menu);
+		lcd_refresh(); // to maybe revive the LCD if static electricity killed it.
+	}
 
 #ifdef ULTIPANEL_FEEDMULTIPLY
-  // Dead zone at 100% feedrate
-  if ((feedmultiply < 100 && (feedmultiply + int(lcd_encoder)) > 100) ||
-      (feedmultiply > 100 && (feedmultiply + int(lcd_encoder)) < 100))
-  {
-    lcd_encoder = 0;
-    feedmultiply = 100;
-  }
-
-  if (feedmultiply == 100 && int(lcd_encoder) > ENCODER_FEEDRATE_DEADZONE)
-  {
-    feedmultiply += int(lcd_encoder) - ENCODER_FEEDRATE_DEADZONE;
-    lcd_encoder = 0;
-  }
-  else if (feedmultiply == 100 && int(lcd_encoder) < -ENCODER_FEEDRATE_DEADZONE)
-  {
-    feedmultiply += int(lcd_encoder) + ENCODER_FEEDRATE_DEADZONE;
-    lcd_encoder = 0;
-  }
-  else if (feedmultiply != 100)
-  {
-    feedmultiply += int(lcd_encoder);
-    lcd_encoder = 0;
-  }
+	// Dead zone at 100% feedrate
+	if ((feedmultiply < 100 && (feedmultiply + int(lcd_encoder)) > 100) ||
+		(feedmultiply > 100 && (feedmultiply + int(lcd_encoder)) < 100))
+	{
+		lcd_encoder = 0;
+		feedmultiply = 100;
+	}
+	if (feedmultiply == 100 && int(lcd_encoder) > ENCODER_FEEDRATE_DEADZONE)
+	{
+		feedmultiply += int(lcd_encoder) - ENCODER_FEEDRATE_DEADZONE;
+		lcd_encoder = 0;
+	}
+	else if (feedmultiply == 100 && int(lcd_encoder) < -ENCODER_FEEDRATE_DEADZONE)
+	{
+		feedmultiply += int(lcd_encoder) + ENCODER_FEEDRATE_DEADZONE;
+		lcd_encoder = 0;
+	}
+	else if (feedmultiply != 100)
+	{
+		feedmultiply += int(lcd_encoder);
+		lcd_encoder = 0;
+	}
 #endif //ULTIPANEL_FEEDMULTIPLY
 
-  if (feedmultiply < 10)
-    feedmultiply = 10;
-  else if (feedmultiply > 999)
-    feedmultiply = 999;
-
-  /*if (farm_mode && !printer_connected) {
-	  lcd_set_cursor(0, 3);
-	  lcd_puts_P(_i("Printer disconnected"));////MSG_PRINTER_DISCONNECTED c=20 r=1
-  }*/
-
-
-//#define FSENS_FACTOR (2580.8/50) //filament sensor factor [steps / encoder counts]
-//#define FSENS_FACTOR (2580.8/45.3) //filament sensor factor [steps / encoder counts]
-  //lcd_set_cursor(0, 3);
-  //lcd_print("                    ");
-  //lcd_set_cursor(0, 3);
-  //lcd_print(pat9125_x);
-  //lcd_set_cursor(6, 3);
-  //lcd_print(pat9125_y);
-  //lcd_set_cursor(12, 3);
-  //lcd_print(pat9125_b);
-
+	if (feedmultiply < 10)
+		feedmultiply = 10;
+	else if (feedmultiply > 999)
+		feedmultiply = 999;
 }
 
 
@@ -1642,7 +1554,6 @@ void lcd_commands()
 		if (lcd_commands_step == 0) 
 		{ 
 			lcd_commands_step = 6; 
-			custom_message = true;	
 		}
 
 		if (lcd_commands_step == 1 && !blocks_queued())
@@ -1650,8 +1561,7 @@ void lcd_commands()
 			lcd_commands_step = 0;
 			lcd_commands_type = 0;
 			lcd_setstatuspgm(_T(WELCOME_MSG));
-			custom_message_type = 0;
-			custom_message = false;
+			custom_message_type = CUSTOM_MSG_TYPE_STATUS;
 			isPrintPaused = false;
 		}
 		if (lcd_commands_step == 2 && !blocks_queued())
@@ -1707,8 +1617,7 @@ void lcd_commands()
 			if (mmu_enabled)
 				setAllTargetHotends(0);
 			manage_heater();
-			custom_message = true;
-			custom_message_type = 2;
+			custom_message_type = CUSTOM_MSG_TYPE_F_LOAD;
 			lcd_commands_step = 5;
 		}
 		if (lcd_commands_step == 7 && !blocks_queued())
@@ -1738,7 +1647,7 @@ void lcd_commands()
 	if (lcd_commands_type == LCD_COMMAND_FARM_MODE_CONFIRM)   /// farm mode confirm
 	{
 
-		if (lcd_commands_step == 0) { lcd_commands_step = 6; custom_message = true; }
+		if (lcd_commands_step == 0) { lcd_commands_step = 6; }
 
 		if (lcd_commands_step == 1 && !blocks_queued())
 		{
@@ -1781,9 +1690,8 @@ void lcd_commands()
 		char cmd1[30];
 		
 		if (lcd_commands_step == 0) {
-			custom_message_type = 3;
+			custom_message_type = CUSTOM_MSG_TYPE_PIDCAL;
 			custom_message_state = 1;
-			custom_message = true;
 			lcd_draw_update = 3;
 			lcd_commands_step = 3;
 		}
@@ -1816,8 +1724,7 @@ void lcd_commands()
 		}
 		if ((lcd_commands_step == 1) && ((millis()- display_time)>2000)) { //calibration finished message
 			lcd_setstatuspgm(_T(WELCOME_MSG));
-			custom_message_type = 0;
-			custom_message = false;
+			custom_message_type = CUSTOM_MSG_TYPE_STATUS;
 			pid_temp = DEFAULT_PID_TEMP;
 			lcd_commands_step = 0;
 			lcd_commands_type = 0;
@@ -2530,7 +2437,7 @@ static void lcd_LoadFilament()
 {
   if (degHotend0() > EXTRUDE_MINTEMP)
   {
-      custom_message = true;
+      custom_message_type = CUSTOM_MSG_TYPE_F_LOAD;
       loading_flag = true;
       enquecommand_P(PSTR("M701")); //load filament
       SERIAL_ECHOLN("Loading filament");
@@ -2657,7 +2564,7 @@ static void _lcd_move(const char *name, int axis, int min, int max)
 	    lcd_set_cursor(0, 1);
 		menu_draw_float31(' ', name, current_position[axis]);
 	}
-	if (menuExiting || LCD_CLICKED) (void)enable_endstops(_md->endstopsEnabledPrevious);
+	if (menu_leaving || LCD_CLICKED) (void)enable_endstops(_md->endstopsEnabledPrevious);
 	if (LCD_CLICKED) menu_back();
 }
 
@@ -2889,7 +2796,7 @@ static void _lcd_babystep(int axis, const char *msg)
 	    lcd_set_cursor(0, 1);
 		menu_draw_float13(' ', msg, _md->babystepMemMM[axis]);
 	}
-	if (LCD_CLICKED || menuExiting)
+	if (LCD_CLICKED || menu_leaving)
 	{
 		// Only update the EEPROM when leaving the menu.
 		EEPROM_save_B(
@@ -2900,29 +2807,27 @@ static void _lcd_babystep(int axis, const char *msg)
 	if (LCD_CLICKED) menu_back();
 }
 
-static void lcd_babystep_z() {
+
+static void lcd_babystep_z()
+{
 	_lcd_babystep(Z_AXIS, (_i("Adjusting Z")));////MSG_BABYSTEPPING_Z c=20 r=0
 }
 
-static void lcd_adjust_bed();
 
 typedef struct
-{	// 13bytes total
+{	// 12bytes + 9bytes = 21bytes total
+	uint8_t reserved[MENU_DATA_EDIT_SIZE]; //12 bytes reserved for number editing functions
 	int8_t status;                   // 1byte
-	int8_t left;                     // 1byte
-	int8_t right;                    // 1byte
-	int8_t front;                    // 1byte
-	int8_t rear;                     // 1byte
-	int    left2;                    // 2byte
-	int    right2;                   // 2byte
-	int    front2;                   // 2byte
-	int    rear2;                    // 2byte
+	int16_t left;                    // 2byte
+	int16_t right;                   // 2byte
+	int16_t front;                   // 2byte
+	int16_t rear;                    // 2byte
 } _menu_data_adjust_bed_t;
-#if (13 > MENU_DATA_SIZE)
+#if (21 > MENU_DATA_SIZE)
 #error "check MENU_DATA_SIZE definition!"
 #endif
 
-static void lcd_adjust_bed_reset()
+void lcd_adjust_bed_reset(void)
 {
 	eeprom_update_byte((unsigned char*)EEPROM_BED_CORRECTION_VALID, 1);
 	eeprom_update_byte((unsigned char*)EEPROM_BED_CORRECTION_LEFT , 0);
@@ -2933,73 +2838,48 @@ static void lcd_adjust_bed_reset()
 	_md->status = 0;
 }
 
-void adjust_bed_reset()
-{
-	_menu_data_adjust_bed_t* _md = (_menu_data_adjust_bed_t*)&(menu_data[0]);
-	eeprom_update_byte((unsigned char*)EEPROM_BED_CORRECTION_VALID, 1);
-	eeprom_update_byte((unsigned char*)EEPROM_BED_CORRECTION_LEFT, 0);
-	eeprom_update_byte((unsigned char*)EEPROM_BED_CORRECTION_RIGHT, 0);
-	eeprom_update_byte((unsigned char*)EEPROM_BED_CORRECTION_FRONT, 0);
-	eeprom_update_byte((unsigned char*)EEPROM_BED_CORRECTION_REAR, 0);
-	_md->left = _md->left2 = 0;
-	_md->right = _md->right2 = 0;
-	_md->front = _md->front2 = 0;
-	_md->rear = _md->rear2 = 0;
-}
-
 #define BED_ADJUSTMENT_UM_MAX 50
 
-static void lcd_adjust_bed()
+void lcd_adjust_bed(void)
 {
 	_menu_data_adjust_bed_t* _md = (_menu_data_adjust_bed_t*)&(menu_data[0]);
     if (_md->status == 0)
 	{
         // Menu was entered.
-        // Initialize its status.
+		_md->left  = 0;
+		_md->right = 0;
+		_md->front = 0;
+		_md->rear  = 0;
+        if (eeprom_read_byte((unsigned char*)EEPROM_BED_CORRECTION_VALID) == 1)
+		{
+			_md->left  = eeprom_read_int8((unsigned char*)EEPROM_BED_CORRECTION_LEFT);
+			_md->right = eeprom_read_int8((unsigned char*)EEPROM_BED_CORRECTION_RIGHT);
+			_md->front = eeprom_read_int8((unsigned char*)EEPROM_BED_CORRECTION_FRONT);
+			_md->rear  = eeprom_read_int8((unsigned char*)EEPROM_BED_CORRECTION_REAR);
+		}
         _md->status = 1;
-        bool valid = false;
-        _md->left  = _md->left2  = eeprom_read_int8((unsigned char*)EEPROM_BED_CORRECTION_LEFT);
-        _md->right = _md->right2 = eeprom_read_int8((unsigned char*)EEPROM_BED_CORRECTION_RIGHT);
-        _md->front = _md->front2 = eeprom_read_int8((unsigned char*)EEPROM_BED_CORRECTION_FRONT);
-        _md->rear  = _md->rear2  = eeprom_read_int8((unsigned char*)EEPROM_BED_CORRECTION_REAR);
-        if (eeprom_read_byte((unsigned char*)EEPROM_BED_CORRECTION_VALID) == 1 && 
-            _md->left  >= -BED_ADJUSTMENT_UM_MAX && _md->left  <= BED_ADJUSTMENT_UM_MAX &&
-            _md->right >= -BED_ADJUSTMENT_UM_MAX && _md->right <= BED_ADJUSTMENT_UM_MAX &&
-            _md->front >= -BED_ADJUSTMENT_UM_MAX && _md->front <= BED_ADJUSTMENT_UM_MAX &&
-            _md->rear  >= -BED_ADJUSTMENT_UM_MAX && _md->rear  <= BED_ADJUSTMENT_UM_MAX)
-            valid = true;
-        if (! valid) {
-            // Reset the values: simulate an edit.
-            _md->left2  = 0;
-            _md->right2 = 0;
-            _md->front2 = 0;
-            _md->rear2  = 0;
-        }
-        lcd_draw_update = 1;
-        eeprom_update_byte((unsigned char*)EEPROM_BED_CORRECTION_VALID, 1);
     }
-
-    if (_md->left  != _md->left2)
-        eeprom_update_int8((unsigned char*)EEPROM_BED_CORRECTION_LEFT,  _md->left  = _md->left2);
-    if (_md->right != _md->right2)
-        eeprom_update_int8((unsigned char*)EEPROM_BED_CORRECTION_RIGHT, _md->right = _md->right2);
-    if (_md->front != _md->front2)
-        eeprom_update_int8((unsigned char*)EEPROM_BED_CORRECTION_FRONT, _md->front = _md->front2);
-    if (_md->rear  != _md->rear2)
-        eeprom_update_int8((unsigned char*)EEPROM_BED_CORRECTION_REAR,  _md->rear  = _md->rear2);
-
     MENU_BEGIN();
-    MENU_ITEM_BACK_P(_T(MSG_SETTINGS));
-    MENU_ITEM_EDIT_int3_P(_i("Left side [um]"),  &_md->left2,  -BED_ADJUSTMENT_UM_MAX, BED_ADJUSTMENT_UM_MAX);////MSG_BED_CORRECTION_LEFT c=14 r=1
-    MENU_ITEM_EDIT_int3_P(_i("Right side[um]"), &_md->right2, -BED_ADJUSTMENT_UM_MAX, BED_ADJUSTMENT_UM_MAX);////MSG_BED_CORRECTION_RIGHT c=14 r=1
-    MENU_ITEM_EDIT_int3_P(_i("Front side[um]"), &_md->front2, -BED_ADJUSTMENT_UM_MAX, BED_ADJUSTMENT_UM_MAX);////MSG_BED_CORRECTION_FRONT c=14 r=1
-    MENU_ITEM_EDIT_int3_P(_i("Rear side [um]"),  &_md->rear2,  -BED_ADJUSTMENT_UM_MAX, BED_ADJUSTMENT_UM_MAX);////MSG_BED_CORRECTION_REAR c=14 r=1
+	// leaving menu - this condition must be immediately before MENU_ITEM_BACK_P
+	if (((menu_item == menu_line) && menu_clicked && (lcd_encoder == menu_item)) || menu_leaving)
+	{
+        eeprom_update_int8((unsigned char*)EEPROM_BED_CORRECTION_LEFT,  _md->left);
+        eeprom_update_int8((unsigned char*)EEPROM_BED_CORRECTION_RIGHT, _md->right);
+        eeprom_update_int8((unsigned char*)EEPROM_BED_CORRECTION_FRONT, _md->front);
+        eeprom_update_int8((unsigned char*)EEPROM_BED_CORRECTION_REAR,  _md->rear);
+        eeprom_update_byte((unsigned char*)EEPROM_BED_CORRECTION_VALID, 1);
+	}
+	MENU_ITEM_BACK_P(_T(MSG_SETTINGS));
+	MENU_ITEM_EDIT_int3_P(_i("Left side [um]"),  &_md->left,  -BED_ADJUSTMENT_UM_MAX, BED_ADJUSTMENT_UM_MAX);////MSG_BED_CORRECTION_LEFT c=14 r=1
+    MENU_ITEM_EDIT_int3_P(_i("Right side[um]"), &_md->right, -BED_ADJUSTMENT_UM_MAX, BED_ADJUSTMENT_UM_MAX);////MSG_BED_CORRECTION_RIGHT c=14 r=1
+    MENU_ITEM_EDIT_int3_P(_i("Front side[um]"), &_md->front, -BED_ADJUSTMENT_UM_MAX, BED_ADJUSTMENT_UM_MAX);////MSG_BED_CORRECTION_FRONT c=14 r=1
+    MENU_ITEM_EDIT_int3_P(_i("Rear side [um]"),  &_md->rear,  -BED_ADJUSTMENT_UM_MAX, BED_ADJUSTMENT_UM_MAX);////MSG_BED_CORRECTION_REAR c=14 r=1
     MENU_ITEM_FUNCTION_P(_i("Reset"), lcd_adjust_bed_reset);////MSG_BED_CORRECTION_RESET c=0 r=0
     MENU_END();
 }
 
-void pid_extruder() {
-
+void pid_extruder()
+{
 	lcd_clear();
 	lcd_set_cursor(1, 0);
 	lcd_puts_P(_i("Set temperature:"));////MSG_SET_TEMPERATURE c=19 r=1
@@ -3604,8 +3484,7 @@ void lcd_bed_calibration_show_result(BedSkewOffsetDetectionResultType result, ui
 
 void lcd_temp_cal_show_result(bool result) {
 	
-	custom_message_type = 0;
-	custom_message = false;
+	custom_message_type = CUSTOM_MSG_TYPE_STATUS;
 	disable_x();
 	disable_y();
 	disable_z();
@@ -5262,8 +5141,7 @@ static void change_extr_menu(){
 //unload filament for single material printer (used in M702 gcode)
 void unload_filament()
 {
-	custom_message = true;
-	custom_message_type = 2;
+	custom_message_type = CUSTOM_MSG_TYPE_F_LOAD;
 	lcd_setstatuspgm(_T(MSG_UNLOADING_FILAMENT));
 
 	//		extr_unload2();
@@ -5298,8 +5176,7 @@ void unload_filament()
 	lcd_update_enable(true);
 
 	lcd_setstatuspgm(_T(WELCOME_MSG));
-	custom_message = false;
-	custom_message_type = 0;
+	custom_message_type = CUSTOM_MSG_TYPE_STATUS;
 
 }
 
@@ -5760,8 +5637,7 @@ static void lcd_colorprint_change() {
 	
 	enquecommand_P(PSTR("M600"));
 	
-	custom_message = true;
-	custom_message_type = 2; //just print status message
+	custom_message_type = CUSTOM_MSG_TYPE_F_LOAD; //just print status message
 	lcd_setstatuspgm(_T(MSG_FINISHING_MOVEMENTS));
 	lcd_return_to_status();
 	lcd_draw_update = 3;
@@ -7302,14 +7178,14 @@ void menu_lcd_lcdupdate_func(void)
 
 		if (z_menu_expired() || other_menu_expired() || forced_menu_expire())
 		{
-		// Exiting a menu. Let's call the menu function the last time with menuExiting flag set to true
+		// Exiting a menu. Let's call the menu function the last time with menu_leaving flag set to true
 		// to give it a chance to save its state.
 		// This is useful for example, when the babystep value has to be written into EEPROM.
 			if (menu_menu != NULL)
 			{
-				menuExiting = true;
+				menu_leaving = 1;
 				(*menu_menu)();
-				menuExiting = false;
+				menu_leaving = 0;
 			}
 			lcd_clear();
 			lcd_return_to_status();

+ 90 - 83
Firmware/ultralcd.h

@@ -14,100 +14,108 @@ extern void menu_lcd_longpress_func(void);
 extern void menu_lcd_charsetup_func(void);
 extern void menu_lcd_lcdupdate_func(void);
 
-  // Call with a false parameter to suppress the LCD update from various places like the planner or the temp control.
-  void ultralcd_init();
-  void lcd_setstatus(const char* message);
-  void lcd_setstatuspgm(const char* message);
-  void lcd_setalertstatuspgm(const char* message);
-  void lcd_reset_alert_level();
-  uint8_t get_message_level();
-  void lcd_adjust_z();
-  void lcd_pick_babystep();
-  void lcd_alright();
-  void EEPROM_save_B(int pos, int* value);
-  void EEPROM_read_B(int pos, int* value);
-  void lcd_wait_interact();
-  void lcd_change_filament();
-  void lcd_loading_filament();
-  void lcd_change_success();
-  void lcd_loading_color();
-  void lcd_sdcard_stop();
-  void lcd_sdcard_pause();
-  void lcd_print_stop();
-  void prusa_statistics(int _message, uint8_t _col_nr = 0);
-  void lcd_confirm_print();
-  unsigned char lcd_choose_color();
+// Call with a false parameter to suppress the LCD update from various places like the planner or the temp control.
+void ultralcd_init();
+void lcd_setstatus(const char* message);
+void lcd_setstatuspgm(const char* message);
+void lcd_setalertstatuspgm(const char* message);
+void lcd_reset_alert_level();
+uint8_t get_message_level();
+void lcd_adjust_z();
+void lcd_pick_babystep();
+void lcd_alright();
+void EEPROM_save_B(int pos, int* value);
+void EEPROM_read_B(int pos, int* value);
+void lcd_wait_interact();
+void lcd_change_filament();
+void lcd_loading_filament();
+void lcd_change_success();
+void lcd_loading_color();
+void lcd_sdcard_stop();
+void lcd_sdcard_pause();
+void lcd_print_stop();
+void prusa_statistics(int _message, uint8_t _col_nr = 0);
+void lcd_confirm_print();
+unsigned char lcd_choose_color();
 //void lcd_mylang();
 
-  extern bool lcd_selftest();
+extern bool lcd_selftest();
 
-  void lcd_menu_statistics(); 
+void lcd_menu_statistics(); 
 
 extern const char* lcd_display_message_fullscreen_P(const char *msg, uint8_t &nlines);
 extern const char* lcd_display_message_fullscreen_P(const char *msg);
 
-  extern void lcd_wait_for_click();
-  extern void lcd_show_fullscreen_message_and_wait_P(const char *msg);
-  // 0: no, 1: yes, -1: timeouted
-  extern int8_t lcd_show_fullscreen_message_yes_no_and_wait_P(const char *msg, bool allow_timeouting = true, bool default_yes = false);
-  extern int8_t lcd_show_multiscreen_message_yes_no_and_wait_P(const char *msg, bool allow_timeouting = true, bool default_yes = false);
-  // Ask the user to move the Z axis up to the end stoppers and let
-  // the user confirm that it has been done.
-  #ifndef TMC2130
-  extern bool lcd_calibrate_z_end_stop_manual(bool only_z);
-  #endif
-
-  // Show the result of the calibration process on the LCD screen.
-  extern void lcd_bed_calibration_show_result(BedSkewOffsetDetectionResultType result, uint8_t point_too_far_mask);
-
-  extern void lcd_diag_show_end_stops();
-
-
-
-  #define LCD_MESSAGEPGM(x) lcd_setstatuspgm(PSTR(x))
-  #define LCD_ALERTMESSAGEPGM(x) lcd_setalertstatuspgm(PSTR(x))
-  #define LCD_MESSAGERPGM(x) lcd_setstatuspgm((x))
-  #define LCD_ALERTMESSAGERPGM(x) lcd_setalertstatuspgm((x))
+extern void lcd_wait_for_click();
+extern void lcd_show_fullscreen_message_and_wait_P(const char *msg);
+// 0: no, 1: yes, -1: timeouted
+extern int8_t lcd_show_fullscreen_message_yes_no_and_wait_P(const char *msg, bool allow_timeouting = true, bool default_yes = false);
+extern int8_t lcd_show_multiscreen_message_yes_no_and_wait_P(const char *msg, bool allow_timeouting = true, bool default_yes = false);
+// Ask the user to move the Z axis up to the end stoppers and let
+// the user confirm that it has been done.
 
+#ifndef TMC2130
+extern bool lcd_calibrate_z_end_stop_manual(bool only_z);
+#endif
 
+// Show the result of the calibration process on the LCD screen.
+  extern void lcd_bed_calibration_show_result(BedSkewOffsetDetectionResultType result, uint8_t point_too_far_mask);
 
+extern void lcd_diag_show_end_stops();
+
+
+#define LCD_MESSAGEPGM(x) lcd_setstatuspgm(PSTR(x))
+#define LCD_ALERTMESSAGEPGM(x) lcd_setalertstatuspgm(PSTR(x))
+#define LCD_MESSAGERPGM(x) lcd_setstatuspgm((x))
+#define LCD_ALERTMESSAGERPGM(x) lcd_setalertstatuspgm((x))
+
+
+// To be used in lcd_commands_type.
+#define LCD_COMMAND_IDLE 0
+#define LCD_COMMAND_LOAD_FILAMENT 1
+#define LCD_COMMAND_STOP_PRINT 2
+#define LCD_COMMAND_FARM_MODE_CONFIRM 4
+#define LCD_COMMAND_LONG_PAUSE 5
+#define LCD_COMMAND_LONG_PAUSE_RESUME 6
+#define LCD_COMMAND_PID_EXTRUDER 7 
+#define LCD_COMMAND_V2_CAL 8
+
+extern int lcd_commands_type;
+
+#define CUSTOM_MSG_TYPE_STATUS 0 // status message from lcd_status_message variable
+#define CUSTOM_MSG_TYPE_MESHBL 1 // Mesh bed leveling in progress
+#define CUSTOM_MSG_TYPE_F_LOAD 2 // Loading filament in progress
+#define CUSTOM_MSG_TYPE_PIDCAL 3 // PID tuning in progress
+#define CUSTOM_MSG_TYPE_TEMCAL 4 // PINDA temp calibration
+#define CUSTOM_MSG_TYPE_TEMPRE 5 // Temp compensation preheat
+
+extern unsigned int custom_message_type;
+extern unsigned int custom_message_state;
+
+extern uint8_t farm_mode;
+extern int farm_no;
+extern int farm_timer;
+extern int farm_status;
+
+#ifdef TMC2130
+#define SILENT_MODE_NORMAL 0
+#define SILENT_MODE_STEALTH 1
+#define SILENT_MODE_OFF SILENT_MODE_NORMAL
+#else
+#define SILENT_MODE_POWER 0
+#define SILENT_MODE_SILENT 1
+#define SILENT_MODE_AUTO 2
+#define SILENT_MODE_OFF SILENT_MODE_POWER
+#endif
 
-  // To be used in lcd_commands_type.
-  #define LCD_COMMAND_IDLE 0
-  #define LCD_COMMAND_LOAD_FILAMENT 1
-  #define LCD_COMMAND_STOP_PRINT 2
-  #define LCD_COMMAND_FARM_MODE_CONFIRM 4
-  #define LCD_COMMAND_LONG_PAUSE 5
-  #define LCD_COMMAND_LONG_PAUSE_RESUME 6
-  #define LCD_COMMAND_PID_EXTRUDER 7 
-  #define LCD_COMMAND_V2_CAL 8
+extern int8_t SilentModeMenu;
 
-  extern int lcd_commands_type;
-  
-  extern uint8_t farm_mode;
-  extern int farm_no;
-  extern int farm_timer;
-  extern int farm_status;
-  #ifdef TMC2130
-    #define SILENT_MODE_NORMAL 0
-    #define SILENT_MODE_STEALTH 1
-    #define SILENT_MODE_OFF SILENT_MODE_NORMAL
-  #else
-    #define SILENT_MODE_POWER 0
-    #define SILENT_MODE_SILENT 1
-    #define SILENT_MODE_AUTO 2
-    #define SILENT_MODE_OFF SILENT_MODE_POWER
-  #endif
-  extern int8_t SilentModeMenu;
+extern bool cancel_heatup;
+extern bool isPrintPaused;
 
-  
-  extern bool cancel_heatup;
-  extern bool isPrintPaused;
-      
 
-  void lcd_ignore_click(bool b=true);
-  void lcd_commands();
-  
+void lcd_ignore_click(bool b=true);
+void lcd_commands();
 
 
 void change_extr(int extr);
@@ -133,7 +141,6 @@ void lcd_farm_sdcard_menu_w();
 
 void lcd_wait_for_heater();
 void lcd_wait_for_cool_down();
-void adjust_bed_reset();
 void lcd_extr_cal_reset();
 
 void lcd_temp_cal_show_result(bool result);
@@ -151,8 +158,8 @@ void lcd_temp_calibration_set();
 void display_loading();
 
 #if !SDSORT_USES_RAM
- void lcd_set_degree();
- void lcd_set_progress();
+void lcd_set_degree();
+void lcd_set_progress();
 #endif
 
 void lcd_language();