Browse Source

Merge remote-tracking branch 'prusa3d/MK3' into MK3_dev

Marek Bel 5 years ago
parent
commit
ac62117d6b

+ 2 - 2
Firmware/Configuration.h

@@ -7,8 +7,8 @@
 #define STR(x) STR_HELPER(x)
 
 // Firmware version
-#define FW_VERSION "3.3.1"
-#define FW_COMMIT_NR   845
+#define FW_VERSION "3.4.0-RC1"
+#define FW_COMMIT_NR   1170
 // FW_VERSION_UNKNOWN means this is an unofficial build.
 // The firmware should only be checked into github with this symbol.
 #define FW_DEV_VERSION FW_VERSION_UNKNOWN

+ 5 - 9
Firmware/Marlin.h

@@ -360,11 +360,11 @@ extern bool mmu_print_saved;
 
 //estimated time to end of the print
 extern uint8_t print_percent_done_normal;
-extern uint16_t print_time_remaining_normal;
+extern uint32_t print_time_remaining_normal;
 extern uint8_t print_percent_done_silent;
-extern uint16_t print_time_remaining_silent;
-#define PRINT_TIME_REMAINING_INIT 65535
-#define PRINT_PERCENT_DONE_INIT 255
+extern uint32_t print_time_remaining_silent;
+#define PRINT_TIME_REMAINING_INIT 0xffffffff
+#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)
 
 extern void calculate_extruder_multipliers();
@@ -468,12 +468,8 @@ void gcode_M701();
 
 void proc_commands();
 
-void manage_response(bool move_axes, bool turn_off_nozzle);
-bool mmu_get_response(bool timeout);
-void mmu_not_responding();
-void mmu_load_to_nozzle();
+
 void M600_load_filament();
-void mmu_M600_load_filament(bool automatic);
 void M600_load_filament_movements();
 void M600_wait_for_user();
 void M600_check_state();

+ 23 - 219
Firmware/Marlin_main.cpp

@@ -337,8 +337,8 @@ float pause_lastpos[4];
 unsigned long pause_time = 0;
 unsigned long start_pause_print = millis();
 unsigned long t_fan_rising_edge = millis();
-static LongTimer safetyTimer;
-static LongTimer crashDetTimer;
+LongTimer safetyTimer;
+LongTimer crashDetTimer;
 
 //unsigned long load_filament_time;
 
@@ -476,9 +476,9 @@ bool mmu_print_saved = false;
 
 // storing estimated time to end of print counted by slicer
 uint8_t print_percent_done_normal = PRINT_PERCENT_DONE_INIT;
-uint16_t print_time_remaining_normal = PRINT_TIME_REMAINING_INIT; //estimated remaining print time in minutes
+uint32_t print_time_remaining_normal = PRINT_TIME_REMAINING_INIT; //estimated remaining print time in minutes
 uint8_t print_percent_done_silent = PRINT_PERCENT_DONE_INIT;
-uint16_t print_time_remaining_silent = PRINT_TIME_REMAINING_INIT; //estimated remaining print time in minutes
+uint32_t print_time_remaining_silent = PRINT_TIME_REMAINING_INIT; //estimated remaining print time in minutes
 
 //===========================================================================
 //=============================Private Variables=============================
@@ -509,7 +509,6 @@ unsigned long starttime=0;
 unsigned long stoptime=0;
 unsigned long _usb_timer = 0;
 
-static uint8_t tmp_extruder;
 
 bool extruder_under_pressure = true;
 
@@ -973,42 +972,9 @@ if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
 			case 2: _delay_ms(0); break;
 			case 3: _delay_ms(0); break;
 			}
-			// _delay_ms(100);
-			/*
-			#ifdef MESH_BED_LEVELING
-			_delay_ms(2000);
-
-			if (!READ(BTN_ENC))
-			{
-			WRITE(BEEPER, HIGH);
-			_delay_ms(100);
-			WRITE(BEEPER, LOW);
-			_delay_ms(200);
-			WRITE(BEEPER, HIGH);
-			_delay_ms(100);
-			WRITE(BEEPER, LOW);
-
-			int _z = 0;
-			calibration_status_store(CALIBRATION_STATUS_CALIBRATED);
-			EEPROM_save_B(EEPROM_BABYSTEP_X, &_z);
-			EEPROM_save_B(EEPROM_BABYSTEP_Y, &_z);
-			EEPROM_save_B(EEPROM_BABYSTEP_Z, &_z);
-			}
-			else
-			{
-
-			WRITE(BEEPER, HIGH);
-			_delay_ms(100);
-			WRITE(BEEPER, LOW);
-			}
-			#endif // mesh */
 
 		}
 	}
-	else
-	{
-		//_delay_ms(1000);  // wait 1sec to display the splash screen // what's this and why do we need it?? - andre
-	}
 	KEEPALIVE_STATE(IN_HANDLER);
 }
 
@@ -1158,7 +1124,9 @@ void list_sec_lang_from_external_flash()
 // are initialized by the main() routine provided by the Arduino framework.
 void setup()
 {
-    ultralcd_init();
+	mmu_init();
+	
+	ultralcd_init();
 
 	spi_init();
 
@@ -1778,11 +1746,6 @@ void setup()
   wdt_enable(WDTO_4S);
 #endif //WATCHDOG
 
-	  puts_P(_N("Checking MMU unit..."));
-	  if (mmu_init())
-		  printf_P(_N("MMU ENABLED, finda=%hhd, version=%d\n"), mmu_finda, mmu_version);
-	  else
-		  puts_P(_N("MMU DISABLED"));
 }
 
 
@@ -2016,7 +1979,7 @@ void loop()
 		}
 	}
 #endif //TMC2130
-
+	mmu_loop();
 }
 
 #define DEFINE_PGM_READ_ANY(type, reader)       \
@@ -3476,14 +3439,6 @@ void process_commands()
 		{
 			mmu_reset();
 		}
-		else if (code_seen("MMUFIN"))
-		{
-			mmu_read_finda();
-		}
-		else if (code_seen("MMUVER"))
-		{
-			mmu_read_version();
-		}
 		else if (code_seen("RESET")) {
             // careful!
             if (farm_mode) {
@@ -6333,21 +6288,14 @@ if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
 		//currently three different materials are needed (default, flex and PVA) 
 		//add storing this information for different load/unload profiles etc. in the future
 		//firmware does not wait for "ok" from mmu
-
-		uint8_t extruder = 255;
-		uint8_t filament = FILAMENT_UNDEFINED;
-
-		if(code_seen('E')) extruder = code_value();
-		if(code_seen('F')) filament = code_value();
-
-		printf_P(PSTR("Extruder: %d; "), extruder);
-		switch (filament) {
-			case FILAMENT_FLEX: printf_P(PSTR("Flex\n")); break;
-			case FILAMENT_PVA: printf_P(PSTR("PVA\n")); break;
-			default: printf_P(PSTR("Default\n")); break;
+		if (mmu_enabled)
+		{
+			uint8_t extruder = 255;
+			uint8_t filament = FILAMENT_UNDEFINED;
+			if(code_seen('E')) extruder = code_value();
+			if(code_seen('F')) filament = code_value();
+			mmu_set_filament_type(extruder, filament);
 		}
-		printf_P(PSTR("F%d%d\n"), extruder, filament);
-		mmu_printf_P(PSTR("F%d%d\n"), extruder, filament);
 	}
 	break;
 
@@ -7748,7 +7696,8 @@ void wait_for_heater(long codenum) {
 	}
 }
 
-void check_babystep() {
+void check_babystep()
+{
 	int babystep_z;
 	EEPROM_read_B(EEPROM_BABYSTEP_Z, &babystep_z);
 	if ((babystep_z < Z_BABYSTEP_MIN) || (babystep_z > Z_BABYSTEP_MAX)) {
@@ -8869,7 +8818,8 @@ uint16_t print_time_remaining() {
 	return print_t;
 }
 
-uint8_t print_percent_done() {
+uint8_t print_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;
 	if (SilentModeMenu == SILENT_MODE_OFF && print_percent_done_normal <= 100) {
@@ -8884,131 +8834,16 @@ uint8_t print_percent_done() {
 	return percent_done;
 }
 
-static void print_time_remaining_init() {
+static void print_time_remaining_init()
+{
 	print_time_remaining_normal = PRINT_TIME_REMAINING_INIT;
 	print_time_remaining_silent = PRINT_TIME_REMAINING_INIT;
 	print_percent_done_normal = PRINT_PERCENT_DONE_INIT;
 	print_percent_done_silent = PRINT_PERCENT_DONE_INIT;
 }
 
-bool mmu_get_response(bool timeout) {
-	//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
-	bool response = true;
-	LongTimer mmu_get_reponse_timeout;
-	KEEPALIVE_STATE(IN_PROCESS);
-	mmu_get_reponse_timeout.start();
-	while (mmu_rx_ok() <= 0)
-    {
-      delay_keep_alive(100);
-	  if (timeout && mmu_get_reponse_timeout.expired(5 * 60 * 1000ul)) { //5 minutes timeout
-			response = false;
-			break;
-	  }
-    }
-	return response;
-}
-
-
-void manage_response(bool move_axes, bool turn_off_nozzle) {
-	
-	bool response = false;
-	mmu_print_saved = false;
-	bool lcd_update_was_enabled = false;
-	float hotend_temp_bckp = degTargetHotend(active_extruder);
-	float z_position_bckp = current_position[Z_AXIS];
-	float x_position_bckp = current_position[X_AXIS];
-	float y_position_bckp = current_position[Y_AXIS];	
-	while(!response) {
-		  response = mmu_get_response(true); //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) {
-					  lcd_update_was_enabled = true;
-					  lcd_update_enable(false);
-				  }
-				  st_synchronize();
-				  mmu_print_saved = true;
-				  
-				  hotend_temp_bckp = degTargetHotend(active_extruder);
-				  if (move_axes) {
-					  z_position_bckp = current_position[Z_AXIS];
-					  x_position_bckp = current_position[X_AXIS];
-					  y_position_bckp = current_position[Y_AXIS];
-				  
-					  //lift z
-					  current_position[Z_AXIS] += Z_PAUSE_LIFT;
-					  if (current_position[Z_AXIS] > Z_MAX_POS) current_position[Z_AXIS] = Z_MAX_POS;
-					  plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 15, active_extruder);
-					  st_synchronize();
-					  					  
-					  //Move XY to side
-					  current_position[X_AXIS] = X_PAUSE_POS;
-					  current_position[Y_AXIS] = Y_PAUSE_POS;
-					  plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 50, active_extruder);
-					  st_synchronize();
-				  }
-				  if (turn_off_nozzle) {
-					  //set nozzle target temperature to 0
-					  setAllTargetHotends(0);
-					  printf_P(PSTR("MMU not responding\n"));
-					  lcd_show_fullscreen_message_and_wait_P(_i("MMU needs user attention. Please press knob to resume nozzle target temperature."));
-					  setTargetHotend(hotend_temp_bckp, active_extruder);
-					  while ((degTargetHotend(active_extruder) - degHotend(active_extruder)) > 5) {
-						  delay_keep_alive(1000);
-						  lcd_wait_for_heater();
-					  }
-				  }
-			  }
-			  lcd_display_message_fullscreen_P(_i("Check MMU. Fix the issue and then press button on MMU unit."));
-		  }
-		  else if (mmu_print_saved) {
-			  printf_P(PSTR("MMU start responding\n"));
-			  lcd_clear();
-			  lcd_display_message_fullscreen_P(_i("MMU OK. Resuming..."));
-			  if (move_axes) {
-				  current_position[X_AXIS] = x_position_bckp;
-				  current_position[Y_AXIS] = y_position_bckp;
-				  plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 50, active_extruder);
-				  st_synchronize();
-				  current_position[Z_AXIS] = z_position_bckp;
-				  plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 15, active_extruder);
-				  st_synchronize();
-			  }
-			  else {
-				  delay_keep_alive(1000); //delay just for showing MMU OK message for a while in case that there are no xyz movements
-			  }
-		  }
-	}
-	if (lcd_update_was_enabled) lcd_update_enable(true);
-}
-
-void mmu_load_to_nozzle() {
-	st_synchronize();
-	
-	bool saved_e_relative_mode = axis_relative_modes[E_AXIS];
-	if (!saved_e_relative_mode) axis_relative_modes[E_AXIS] = true;
-	current_position[E_AXIS] += 7.2f;
-    float feedrate = 562;
-	plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], feedrate / 60, active_extruder);
-    st_synchronize();
-	current_position[E_AXIS] += 14.4f;
-	feedrate = 871;
-	plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], feedrate / 60, active_extruder);
-    st_synchronize();
-	current_position[E_AXIS] += 36.0f;
-	feedrate = 1393;
-	plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], feedrate / 60, active_extruder);
-    st_synchronize();
-	current_position[E_AXIS] += 14.4f;
-	feedrate = 871;
-	plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], feedrate / 60, active_extruder);
-    st_synchronize();
-	if (!saved_e_relative_mode) axis_relative_modes[E_AXIS] = false;
-}
-
-void M600_check_state() {
+void M600_check_state()
+{
 		//Wait for user to check the state
 		lcd_change_fil_state = 0;
 		
@@ -9120,37 +8955,6 @@ void M600_wait_for_user() {
 		WRITE(BEEPER, LOW);
 }
 
-void mmu_M600_load_filament(bool automatic)
-{ 
-	//load filament for mmu v2
-	bool yes = false;
-	if (!automatic)
-	{
-		yes = lcd_show_fullscreen_message_yes_no_and_wait_P(_i("Do you want to switch extruder?"), false);
-		if (yes) tmp_extruder = choose_extruder_menu();
-		else tmp_extruder = mmu_extruder;
-	}
-	else
-	{
-		tmp_extruder = (tmp_extruder+1)%5;
-	}
-	lcd_update_enable(false);
-	lcd_clear();
-	lcd_set_cursor(0, 1); lcd_puts_P(_T(MSG_LOADING_FILAMENT));
-	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);
-	manage_response(false, true);
-    mmu_extruder = tmp_extruder; //filament change is finished
-	mmu_load_to_nozzle();
-
-	st_synchronize();
-	current_position[E_AXIS]+= FILAMENTCHANGE_FINALFEED ;
-	plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 2, active_extruder);
-}
-
 void M600_load_filament_movements()
 {
 #ifdef SNMM

+ 1 - 1
Firmware/Timer.cpp

@@ -10,7 +10,7 @@
  * @brief construct Timer
  *
  * It is guaranteed, that construction is equivalent with zeroing all members.
- * This property can be exploited in MenuData union.
+ * This property can be exploited in menu_data.
  */
 template<typename T>
 Timer<T>::Timer() : m_isRunning(false), m_started()

+ 2 - 0
Firmware/lcd.cpp

@@ -754,6 +754,7 @@ void lcd_update_enable(uint8_t enabled)
 	}
 }
 
+extern LongTimer safetyTimer;
 void lcd_buttons_update(void)
 {
 	static bool _lock = false;
@@ -769,6 +770,7 @@ void lcd_buttons_update(void)
 			lcd_timeoutToStatus.start();
 			if (!buttonBlanking.running() || buttonBlanking.expired(BUTTON_BLANKING_TIME)) {
 				buttonBlanking.start();
+		        safetyTimer.start();
 				if ((lcd_button_pressed == 0) && (lcd_long_press_active == 0))
 				{
 					longPressTimer.start();

+ 23 - 10
Firmware/menu.cpp

@@ -116,7 +116,7 @@ uint8_t menu_item_ret(void)
 }
 
 /*
-int menu_item_printf_P(char type_char, const char* format, ...)
+int menu_draw_item_printf_P(char type_char, const char* format, ...)
 {
 	va_list args;
 	va_start(args, format);
@@ -134,12 +134,14 @@ int menu_item_printf_P(char type_char, const char* format, ...)
 	return ret;
 }
 */
+
 int menu_draw_item_puts_P(char type_char, const char* str)
 {
     lcd_set_cursor(0, menu_row);
 	int cnt = lcd_printf_P(PSTR("%c%-18S%c"), (lcd_encoder == menu_item)?'>':' ', str, type_char);
 	return cnt;
 }
+
 /*
 int menu_draw_item_puts_P_int16(char type_char, const char* str, int16_t val, )
 {
@@ -148,6 +150,7 @@ int menu_draw_item_puts_P_int16(char type_char, const char* str, int16_t val, )
 	return cnt;
 }
 */
+
 void menu_item_dummy(void)
 {
 	menu_item++;
@@ -270,25 +273,35 @@ void menu_draw_float13(char chr, const char* str, float val)
 	lcd_printf_P(menu_fmt_float13, chr, str, spaces, val);
 }
 
-#define _menu_data menuData.edit_menu
+typedef struct
+{
+    //Variables used when editing values.
+    const char* editLabel;
+    void* editValue;
+    int32_t minEditValue;
+	int32_t maxEditValue;
+} menu_data_edit_t;
+
 void _menu_edit_int3(void)
 {
+	menu_data_edit_t* _md = (menu_data_edit_t*)&(menu_data[0]);
 	if (lcd_draw_update)
 	{
-		if (lcd_encoder < _menu_data.minEditValue) lcd_encoder = _menu_data.minEditValue;
-		if (lcd_encoder > _menu_data.maxEditValue) lcd_encoder = _menu_data.maxEditValue;
+		if (lcd_encoder < _md->minEditValue) lcd_encoder = _md->minEditValue;
+		if (lcd_encoder > _md->maxEditValue) lcd_encoder = _md->maxEditValue;
 		lcd_set_cursor(0, 1);
-		menu_draw_int3(' ', _menu_data.editLabel, (int)lcd_encoder);
+		menu_draw_int3(' ', _md->editLabel, (int)lcd_encoder);
 	}
 	if (LCD_CLICKED)
 	{
-		*((int*)(_menu_data.editValue)) = (int)lcd_encoder;
+		*((int*)(_md->editValue)) = (int)lcd_encoder;
 		menu_back();
 	}
 }
 
 uint8_t menu_item_edit_int3(const char* str, int16_t* pval, int16_t min_val, int16_t max_val)
 {
+	menu_data_edit_t* _md = (menu_data_edit_t*)&(menu_data[0]);
 	if (menu_item == menu_line)
 	{
 		if (lcd_draw_update) 
@@ -299,10 +312,10 @@ 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_data.editLabel = str;
-			_menu_data.editValue = pval;
-			_menu_data.minEditValue = min_val;
-			_menu_data.maxEditValue = max_val;
+			_md->editLabel = str;
+			_md->editValue = pval;
+			_md->minEditValue = min_val;
+			_md->maxEditValue = max_val;
 			lcd_encoder = *pval;
 			return menu_item_ret();
 		}

+ 1 - 10
Firmware/menu.h

@@ -16,15 +16,6 @@ typedef struct
     uint8_t position;
 } menu_record_t;
 
-typedef struct
-{
-    //Variables used when editing values.
-    const char* editLabel;
-    void* editValue;
-    int32_t minEditValue;
-	int32_t maxEditValue;
-} menu_data_edit_t;
-
 extern menu_record_t menu_stack[MENU_DEPTH_MAX];
 
 extern uint8_t menu_data[MENU_DATA_SIZE];
@@ -63,7 +54,7 @@ extern void menu_submenu(menu_func_t submenu);
 
 extern uint8_t menu_item_ret(void);
 
-//int menu_item_printf_P(char type_char, const char* format, ...);
+//extern int menu_draw_item_printf_P(char type_char, const char* format, ...);
 
 extern int menu_draw_item_puts_P(char type_char, const char* str);
 

+ 4 - 3
Firmware/mesh_bed_calibration.cpp

@@ -2995,13 +2995,14 @@ static int babystepLoadZ = 0;
 
 void babystep_load()
 {
+	babystepLoadZ = 0;
     // Apply Z height correction aka baby stepping before mesh bed leveling gets activated.
-    if(calibration_status() < CALIBRATION_STATUS_LIVE_ADJUST)
+    if (calibration_status() < CALIBRATION_STATUS_LIVE_ADJUST)
     {
         check_babystep(); //checking if babystep is in allowed range, otherwise setting babystep to 0
         
         // End of G80: Apply the baby stepping value.
-        EEPROM_read_B(EEPROM_BABYSTEP_Z,&babystepLoadZ);
+        EEPROM_read_B(EEPROM_BABYSTEP_Z, &babystepLoadZ);
                             
     #if 0
         SERIAL_ECHO("Z baby step: ");
@@ -3037,7 +3038,7 @@ void babystep_undo()
 
 void babystep_reset()
 {
-      babystepLoadZ = 0;    
+	babystepLoadZ = 0;    
 }
 
 void count_xyz_details(float (&distanceMin)[2]) {

+ 1 - 0
Firmware/mesh_bed_calibration.h

@@ -176,6 +176,7 @@ extern void babystep_undo();
 // Reset the current babystep counter without moving the axes.
 extern void babystep_reset();
 
+
 extern void count_xyz_details(float (&distanceMin)[2]);
 extern bool sample_z();
 

+ 243 - 31
Firmware/mmu.cpp

@@ -10,18 +10,34 @@
 
 
 extern const char* lcd_display_message_fullscreen_P(const char *msg);
+extern void lcd_show_fullscreen_message_and_wait_P(const char *msg);
+extern int8_t lcd_show_fullscreen_message_yes_no_and_wait_P(const char *msg, bool allow_timeouting = true, bool default_yes = false);
 extern void lcd_return_to_status();
+extern void lcd_wait_for_heater();
+extern char choose_extruder_menu();
+
+
+#define MMU_TODELAY 100
+#define MMU_TIMEOUT 10
+
+#define MMU_HWRESET
+#define MMU_RST_PIN 76
 
-#define MMU_TIMEOUT 100
 
 bool mmu_enabled = false;
 
+int8_t mmu_state = 0;
+
 uint8_t mmu_extruder = 0;
 
+uint8_t tmp_extruder = 0;
+
 int8_t mmu_finda = -1;
 
 int16_t mmu_version = -1;
 
+int16_t mmu_buildnr = -1;
+
 
 //clear rx buffer
 void mmu_clr_rx_buf(void)
@@ -59,53 +75,249 @@ int8_t mmu_rx_start(void)
 	return uart2_rx_str_P(PSTR("start\n"));
 }
 
-//initialize mmu_unit
-bool mmu_init(void)
+//initialize mmu2 unit - first part - should be done at begining of startup process
+void mmu_init(void)
 {
+	digitalWrite(MMU_RST_PIN, HIGH);
+	pinMode(MMU_RST_PIN, OUTPUT);              //setup reset pin
 	uart2_init();                              //init uart2
 	_delay_ms(10);                             //wait 10ms for sure
-	if (mmu_reset())                           //reset mmu
+	mmu_reset();                               //reset mmu (HW or SW), do not wait for response
+	mmu_state = -1;
+}
+
+//mmu main loop - state machine processing
+void mmu_loop(void)
+{
+//	printf_P(PSTR("MMU loop, state=%d\n"), mmu_state);
+	switch (mmu_state)
 	{
-		mmu_read_finda();
-		mmu_read_version();
-		return true;
+	case 0:
+		return;
+	case -1:
+		if (mmu_rx_start() > 0)
+		{
+			puts_P(PSTR("MMU => 'start'"));
+			puts_P(PSTR("MMU <= 'S1'"));
+		    mmu_puts_P(PSTR("S1\n")); //send 'read version' request
+			mmu_state = -2;
+		}
+		else if (millis() > 30000) //30sec after reset disable mmu
+		{
+			puts_P(PSTR("MMU not responding - DISABLED"));
+			mmu_state = 0;
+		}
+		return;
+	case -2:
+		if (mmu_rx_ok() > 0)
+		{
+			fscanf_P(uart2io, PSTR("%u"), &mmu_version); //scan version from buffer
+			printf_P(PSTR("MMU => '%dok'\n"), mmu_version);
+			puts_P(PSTR("MMU <= 'S2'"));
+		    mmu_puts_P(PSTR("S2\n")); //send 'read buildnr' request
+			mmu_state = -3;
+		}
+		return;
+	case -3:
+		if (mmu_rx_ok() > 0)
+		{
+			fscanf_P(uart2io, PSTR("%u"), &mmu_buildnr); //scan buildnr from buffer
+			printf_P(PSTR("MMU => '%dok'\n"), mmu_buildnr);
+			puts_P(PSTR("MMU <= 'P0'"));
+		    mmu_puts_P(PSTR("P0\n")); //send 'read finda' request
+			mmu_state = -4;
+		}
+		return;
+	case -4:
+		if (mmu_rx_ok() > 0)
+		{
+			fscanf_P(uart2io, PSTR("%hhu"), &mmu_finda); //scan finda from buffer
+			printf_P(PSTR("MMU => '%dok'\n"), mmu_finda);
+			puts_P(PSTR("MMU - ENABLED"));
+			mmu_enabled = true;
+			mmu_state = 1;
+		}
+		return;
 	}
-	return false;
 }
 
-bool mmu_reset(void)
+void mmu_reset(void)
 {
-    mmu_puts_P(PSTR("X0\n"));                  //send command
-	unsigned char timeout = 10;                //timeout = 10x100ms
-	while ((mmu_rx_start() <= 0) && (--timeout))
-		delay_keep_alive(MMU_TIMEOUT);
-	mmu_enabled = timeout?true:false;
-	return mmu_enabled;
+#ifdef MMU_HWRESET                             //HW - pulse reset pin
+	digitalWrite(MMU_RST_PIN, LOW);
+	_delay_us(100);
+	digitalWrite(MMU_RST_PIN, HIGH);
+#else                                          //SW - send X0 command
+    mmu_puts_P(PSTR("X0\n"));
+#endif
 }
 
-int8_t mmu_read_finda(void)
+int8_t mmu_set_filament_type(uint8_t extruder, uint8_t filament)
 {
-    mmu_puts_P(PSTR("P0\n"));
-	unsigned char timeout = 10;                //10x100ms
+	printf_P(PSTR("MMU <= 'F%d %d'\n"), extruder, filament);
+	mmu_printf_P(PSTR("F%d %d\n"), extruder, filament);
+	unsigned char timeout = MMU_TIMEOUT;       //10x100ms
 	while ((mmu_rx_ok() <= 0) && (--timeout))
-		delay_keep_alive(MMU_TIMEOUT);
-	mmu_finda = -1;
-	if (timeout)
-		fscanf_P(uart2io, PSTR("%hhu"), &mmu_finda);
-	return mmu_finda;
+		delay_keep_alive(MMU_TODELAY);
+	return timeout?1:0;
 }
 
-int16_t mmu_read_version(void)
+bool mmu_get_response(bool timeout)
 {
-    mmu_puts_P(PSTR("S1\n"));
-	unsigned char timeout = 10;                //10x100ms
-	while ((mmu_rx_ok() <= 0) && (--timeout))
-		delay_keep_alive(MMU_TIMEOUT);
-	if (timeout)
-		fscanf_P(uart2io, PSTR("%u"), &mmu_version);
-	return mmu_version;
+	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
+	bool response = true;
+	LongTimer mmu_get_reponse_timeout;
+	KEEPALIVE_STATE(IN_PROCESS);
+	mmu_get_reponse_timeout.start();
+	while (mmu_rx_ok() <= 0)
+	{
+		delay_keep_alive(100);
+		if (timeout && mmu_get_reponse_timeout.expired(5 * 60 * 1000ul))
+		{ //5 minutes timeout
+			response = false;
+			break;
+		}
+	}
+	printf_P(PSTR("mmu_get_response - end %d\n"), response?1:0);
+	return response;
+}
+
+
+void manage_response(bool move_axes, bool turn_off_nozzle)
+{
+	bool response = false;
+	mmu_print_saved = false;
+	bool lcd_update_was_enabled = false;
+	float hotend_temp_bckp = degTargetHotend(active_extruder);
+	float z_position_bckp = current_position[Z_AXIS];
+	float x_position_bckp = current_position[X_AXIS];
+	float y_position_bckp = current_position[Y_AXIS];	
+	while(!response)
+	{
+		  response = mmu_get_response(true); //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) {
+					  lcd_update_was_enabled = true;
+					  lcd_update_enable(false);
+				  }
+				  st_synchronize();
+				  mmu_print_saved = true;
+				  
+				  hotend_temp_bckp = degTargetHotend(active_extruder);
+				  if (move_axes) {
+					  z_position_bckp = current_position[Z_AXIS];
+					  x_position_bckp = current_position[X_AXIS];
+					  y_position_bckp = current_position[Y_AXIS];
+				  
+					  //lift z
+					  current_position[Z_AXIS] += Z_PAUSE_LIFT;
+					  if (current_position[Z_AXIS] > Z_MAX_POS) current_position[Z_AXIS] = Z_MAX_POS;
+					  plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 15, active_extruder);
+					  st_synchronize();
+					  					  
+					  //Move XY to side
+					  current_position[X_AXIS] = X_PAUSE_POS;
+					  current_position[Y_AXIS] = Y_PAUSE_POS;
+					  plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 50, active_extruder);
+					  st_synchronize();
+				  }
+				  if (turn_off_nozzle) {
+					  //set nozzle target temperature to 0
+					  setAllTargetHotends(0);
+					  printf_P(PSTR("MMU not responding\n"));
+					  lcd_show_fullscreen_message_and_wait_P(_i("MMU needs user attention. Please press knob to resume nozzle target temperature."));
+					  setTargetHotend(hotend_temp_bckp, active_extruder);
+					  while ((degTargetHotend(active_extruder) - degHotend(active_extruder)) > 5) {
+						  delay_keep_alive(1000);
+						  lcd_wait_for_heater();
+					  }
+				  }
+			  }
+			  lcd_display_message_fullscreen_P(_i("Check MMU. Fix the issue and then press button on MMU unit."));
+		  }
+		  else if (mmu_print_saved) {
+			  printf_P(PSTR("MMU start responding\n"));
+			  lcd_clear();
+			  lcd_display_message_fullscreen_P(_i("MMU OK. Resuming..."));
+			  if (move_axes) {
+				  current_position[X_AXIS] = x_position_bckp;
+				  current_position[Y_AXIS] = y_position_bckp;
+				  plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 50, active_extruder);
+				  st_synchronize();
+				  current_position[Z_AXIS] = z_position_bckp;
+				  plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 15, active_extruder);
+				  st_synchronize();
+			  }
+			  else {
+				  delay_keep_alive(1000); //delay just for showing MMU OK message for a while in case that there are no xyz movements
+			  }
+		  }
+	}
+	if (lcd_update_was_enabled) lcd_update_enable(true);
 }
 
+void mmu_load_to_nozzle()
+{
+	st_synchronize();
+	
+	bool saved_e_relative_mode = axis_relative_modes[E_AXIS];
+	if (!saved_e_relative_mode) axis_relative_modes[E_AXIS] = true;
+	current_position[E_AXIS] += 7.2f;
+    float feedrate = 562;
+	plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], feedrate / 60, active_extruder);
+    st_synchronize();
+	current_position[E_AXIS] += 14.4f;
+	feedrate = 871;
+	plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], feedrate / 60, active_extruder);
+    st_synchronize();
+	current_position[E_AXIS] += 36.0f;
+	feedrate = 1393;
+	plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], feedrate / 60, active_extruder);
+    st_synchronize();
+	current_position[E_AXIS] += 14.4f;
+	feedrate = 871;
+	plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], feedrate / 60, active_extruder);
+    st_synchronize();
+	if (!saved_e_relative_mode) axis_relative_modes[E_AXIS] = false;
+}
+
+void mmu_M600_load_filament(bool automatic)
+{ 
+	//load filament for mmu v2
+		  bool yes = false;
+		  if (!automatic) {
+			  yes = lcd_show_fullscreen_message_yes_no_and_wait_P(_i("Do you want to switch extruder?"), false);
+			  if(yes) tmp_extruder = choose_extruder_menu();
+			  else tmp_extruder = mmu_extruder;
+
+		  }
+		  else {
+			  tmp_extruder = (tmp_extruder+1)%5;
+		  }
+		  lcd_update_enable(false);
+		  lcd_clear();
+		  lcd_set_cursor(0, 1); lcd_puts_P(_T(MSG_LOADING_FILAMENT));
+		  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);
+
+		  manage_response(false, true);
+    	  mmu_extruder = tmp_extruder; //filament change is finished
+
+		  mmu_load_to_nozzle();
+
+		  st_synchronize();
+		  current_position[E_AXIS]+= FILAMENTCHANGE_FINALFEED ;
+		  plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 2, active_extruder);
+}
+
+
 void extr_mov(float shift, float feed_rate)
 { //move extruder no matter what the current heater temperature is
 	set_extrude_min_temp(.0);

+ 19 - 4
Firmware/mmu.h

@@ -5,11 +5,16 @@
 
 extern bool mmu_enabled;
 
+extern int8_t mmu_state;
+
 extern uint8_t mmu_extruder;
 
+extern uint8_t tmp_extruder;
+
 extern int8_t mmu_finda;
 
 extern int16_t mmu_version;
+extern int16_t mmu_buildnr;
 
 
 extern int mmu_puts_P(const char* str);
@@ -19,13 +24,23 @@ extern int mmu_printf_P(const char* format, ...);
 extern int8_t mmu_rx_ok(void);
 
 
-extern bool mmu_init(void);
+extern void mmu_init(void);
+
+extern void mmu_loop(void);
+
+
+extern void mmu_reset(void);
+
+extern int8_t mmu_set_filament_type(uint8_t extruder, uint8_t filament);
+
+
+extern bool mmu_get_response(bool timeout);
 
-extern bool mmu_reset(void);
+extern void manage_response(bool move_axes, bool turn_off_nozzle);
 
-extern int8_t mmu_read_finda(void);
+extern void mmu_load_to_nozzle();
 
-extern int16_t mmu_read_version(void);
+extern void mmu_M600_load_filament(bool automatic);
 
 
 extern void extr_mov(float shift, float feed_rate);

+ 17 - 16
Firmware/tmc2130.cpp

@@ -77,7 +77,8 @@ bool tmc2130_sg_change = false;
 
 bool skip_debug_msg = false;
 
-#define DBG(args...) printf_P(args)
+#define DBG(args...)
+//printf_P(args)
 #ifndef _n
 #define _n PSTR
 #endif //_n
@@ -150,7 +151,7 @@ uint16_t __tcoolthrs(uint8_t axis)
 
 void tmc2130_init()
 {
-	DBG(_n("tmc2130_init(), mode=%S\n"), tmc2130_mode?_n("STEALTH"):_n("NORMAL"));
+//	DBG(_n("tmc2130_init(), mode=%S\n"), tmc2130_mode?_n("STEALTH"):_n("NORMAL"));
 	WRITE(X_TMC2130_CS, HIGH);
 	WRITE(Y_TMC2130_CS, HIGH);
 	WRITE(Z_TMC2130_CS, HIGH);
@@ -442,8 +443,8 @@ void tmc2130_setup_chopper(uint8_t axis, uint8_t mres, uint8_t current_h, uint8_
 //		toff = TMC2130_TOFF_E; // toff = 3-5
 //		rndtf = 1;
 	}
-	DBG(_n("tmc2130_setup_chopper(axis=%hhd, mres=%hhd, curh=%hhd, curr=%hhd\n"), axis, mres, current_h, current_r);
-	DBG(_n(" toff=%hhd, hstr=%hhd, hend=%hhd, tbl=%hhd\n"), toff, hstrt, hend, tbl);
+//	DBG(_n("tmc2130_setup_chopper(axis=%hhd, mres=%hhd, curh=%hhd, curr=%hhd\n"), axis, mres, current_h, current_r);
+//	DBG(_n(" toff=%hhd, hstr=%hhd, hend=%hhd, tbl=%hhd\n"), toff, hstrt, hend, tbl);
 	if (current_r <= 31)
 	{
 		tmc2130_wr_CHOPCONF(axis, toff, hstrt, hend, fd3, 0, rndtf, chm, tbl, 1, 0, 0, 0, mres, intpol, 0, 0);
@@ -458,31 +459,31 @@ void tmc2130_setup_chopper(uint8_t axis, uint8_t mres, uint8_t current_h, uint8_
 
 void tmc2130_set_current_h(uint8_t axis, uint8_t current)
 {
-	DBG(_n("tmc2130_set_current_h(axis=%d, current=%d\n"), axis, current);
+//	DBG(_n("tmc2130_set_current_h(axis=%d, current=%d\n"), axis, current);
 	tmc2130_current_h[axis] = current;
 	tmc2130_setup_chopper(axis, tmc2130_mres[axis], tmc2130_current_h[axis], tmc2130_current_r[axis]);
 }
 
 void tmc2130_set_current_r(uint8_t axis, uint8_t current)
 {
-	DBG(_n("tmc2130_set_current_r(axis=%d, current=%d\n"), axis, current);
+//	DBG(_n("tmc2130_set_current_r(axis=%d, current=%d\n"), axis, current);
 	tmc2130_current_r[axis] = current;
 	tmc2130_setup_chopper(axis, tmc2130_mres[axis], tmc2130_current_h[axis], tmc2130_current_r[axis]);
 }
 
 void tmc2130_print_currents()
 {
-	DBG(_n("tmc2130_print_currents()\n\tH\tR\nX\t%d\t%d\nY\t%d\t%d\nZ\t%d\t%d\nE\t%d\t%d\n"),
-		tmc2130_current_h[0], tmc2130_current_r[0],
-		tmc2130_current_h[1], tmc2130_current_r[1],
-		tmc2130_current_h[2], tmc2130_current_r[2],
-		tmc2130_current_h[3], tmc2130_current_r[3]
-	);
+//	DBG(_n("tmc2130_print_currents()\n\tH\tR\nX\t%d\t%d\nY\t%d\t%d\nZ\t%d\t%d\nE\t%d\t%d\n"),
+//		tmc2130_current_h[0], tmc2130_current_r[0],
+//		tmc2130_current_h[1], tmc2130_current_r[1],
+//		tmc2130_current_h[2], tmc2130_current_r[2],
+//		tmc2130_current_h[3], tmc2130_current_r[3]
+//	);
 }
 
 void tmc2130_set_pwm_ampl(uint8_t axis, uint8_t pwm_ampl)
 {
-	DBG(_n("tmc2130_set_pwm_ampl(axis=%hhd, pwm_ampl=%hhd\n"), axis, pwm_ampl);
+//	DBG(_n("tmc2130_set_pwm_ampl(axis=%hhd, pwm_ampl=%hhd\n"), axis, pwm_ampl);
 	tmc2130_pwm_ampl[axis] = pwm_ampl;
 	if (((axis == 0) || (axis == 1)) && (tmc2130_mode == TMC2130_MODE_SILENT))
 		tmc2130_wr_PWMCONF(axis, tmc2130_pwm_ampl[axis], tmc2130_pwm_grad[axis], tmc2130_pwm_freq[axis], tmc2130_pwm_auto[axis], 0, 0);
@@ -490,7 +491,7 @@ void tmc2130_set_pwm_ampl(uint8_t axis, uint8_t pwm_ampl)
 
 void tmc2130_set_pwm_grad(uint8_t axis, uint8_t pwm_grad)
 {
-	DBG(_n("tmc2130_set_pwm_grad(axis=%hhd, pwm_grad=%hhd\n"), axis, pwm_grad);
+//	DBG(_n("tmc2130_set_pwm_grad(axis=%hhd, pwm_grad=%hhd\n"), axis, pwm_grad);
 	tmc2130_pwm_grad[axis] = pwm_grad;
 	if (((axis == 0) || (axis == 1)) && (tmc2130_mode == TMC2130_MODE_SILENT))
 		tmc2130_wr_PWMCONF(axis, tmc2130_pwm_ampl[axis], tmc2130_pwm_grad[axis], tmc2130_pwm_freq[axis], tmc2130_pwm_auto[axis], 0, 0);
@@ -853,12 +854,12 @@ void tmc2130_set_wave(uint8_t axis, uint8_t amp, uint8_t fac1000)
 {
 // TMC2130 wave compression algorithm
 // optimized for minimal memory requirements
-	printf_P(PSTR("tmc2130_set_wave %hhd %hhd\n"), axis, fac1000);
+//	printf_P(PSTR("tmc2130_set_wave %hhd %hhd\n"), axis, fac1000);
 	if (fac1000 < TMC2130_WAVE_FAC1000_MIN) fac1000 = 0;
 	if (fac1000 > TMC2130_WAVE_FAC1000_MAX) fac1000 = TMC2130_WAVE_FAC1000_MAX;
 	float fac = 0;
 	if (fac1000) fac = ((float)((uint16_t)fac1000 + 1000) / 1000); //correction factor
-	printf_P(PSTR(" factor: %s\n"), ftostr43(fac));
+//	printf_P(PSTR(" factor: %s\n"), ftostr43(fac));
 	uint8_t vA = 0;                //value of currentA
 	uint8_t va = 0;                //previous vA
 	int8_t d0 = 0;                //delta0

+ 2 - 0
Firmware/uart2.c

@@ -34,6 +34,8 @@ int uart2_getchar(FILE *stream __attribute__((unused)))
 //uart init (io + FILE stream)
 void uart2_init(void)
 {
+	DDRH &=	~0x01;
+	PORTH |= 0x01;
 	rbuf_ini(uart2_ibuf, sizeof(uart2_ibuf) - 4);
 	UCSR2A |= (1 << U2X2); // baudrate multiplier
 	UBRR2L = UART_BAUD_SELECT(UART2_BAUD, F_CPU); // select baudrate

+ 196 - 99
Firmware/ultralcd.cpp

@@ -44,12 +44,6 @@ char longFilenameOLD[LONG_FILENAME_LENGTH];
 
 static void lcd_sd_updir();
 
-
-// State of the currently active menu.
-// C Union manages sharing of the static memory by all the menus.
-union MenuData menuData;
-
-
 int8_t ReInitLCD = 0;
 
 
@@ -116,11 +110,14 @@ static void lcd_tune_menu();
 //static void lcd_move_menu();
 static void lcd_settings_menu();
 static void lcd_calibration_menu();
-static void lcd_control_temperature_menu();
 #ifdef LINEARITY_CORRECTION
 static void lcd_settings_menu_back();
 #endif //LINEARITY_CORRECTION
-
+static void lcd_control_temperature_menu();
+static void lcd_control_temperature_preheat_pla_settings_menu();
+static void lcd_control_temperature_preheat_abs_settings_menu();
+static void lcd_control_motion_menu();
+static void lcd_control_volumetric_menu();
 static void prusa_stat_printerstatus(int _status);
 static void prusa_stat_farm_number();
 static void prusa_stat_temperatures();
@@ -225,9 +222,7 @@ bool wait_for_unclick;
 
 
 
-
-
-
+const char STR_SEPARATOR[] PROGMEM = "------------";
 
 
 
@@ -608,12 +603,13 @@ static void lcd_implementation_status_screen()
     //Print Feedrate
     lcd_set_cursor(LCD_WIDTH - 8-2, 1);
     lcd_puts_P(PSTR("  "));
+/*
 	if (maxlimit_status)
 	{
 		maxlimit_status = 0;
 		lcd_print('!');
 	}
-	else
+	else*/
 		lcd_print(LCD_STR_FEEDRATE[0]);
     lcd_print(itostr3(feedmultiply));
     lcd_puts_P(PSTR("%     "));
@@ -1958,6 +1954,9 @@ static void lcd_menu_extruder_info()
 	// Display Nozzle fan RPM
 	fan_speed_RPM[0] = 60*fan_speed[0];
 	fan_speed_RPM[1] = 60*fan_speed[1];
+
+	lcd_timeoutToStatus.stop(); //infinite timeout
+
 	lcd_printf_P(_N(
 	  ESC_H(0,0)
 	  "Nozzle FAN: %4d RPM\n"
@@ -2005,6 +2004,7 @@ static void lcd_menu_fails_stats_total()
 // Filam. runouts  000
 // Crash  X 000  Y 000
 //////////////////////
+	lcd_timeoutToStatus.stop(); //infinite timeout
     uint16_t power = eeprom_read_word((uint16_t*)EEPROM_POWER_COUNT_TOT);
     uint16_t filam = eeprom_read_word((uint16_t*)EEPROM_FERROR_COUNT_TOT);
     uint16_t crashX = eeprom_read_word((uint16_t*)EEPROM_CRASH_COUNT_X_TOT);
@@ -2021,6 +2021,7 @@ static void lcd_menu_fails_stats_print()
 // Filam. runouts  000
 // Crash  X 000  Y 000
 //////////////////////
+	lcd_timeoutToStatus.stop(); //infinite timeout
     uint8_t power = eeprom_read_byte((uint8_t*)EEPROM_POWER_COUNT);
     uint8_t filam = eeprom_read_byte((uint8_t*)EEPROM_FERROR_COUNT);
     uint8_t crashX = eeprom_read_byte((uint8_t*)EEPROM_CRASH_COUNT_X);
@@ -2061,6 +2062,7 @@ static void lcd_menu_fails_stats()
  */
 static void lcd_menu_fails_stats()
 {
+	lcd_timeoutToStatus.stop(); //infinite timeout
     uint8_t filamentLast = eeprom_read_byte((uint8_t*)EEPROM_FERROR_COUNT);
     uint16_t filamentTotal = eeprom_read_word((uint16_t*)EEPROM_FERROR_COUNT_TOT);
     lcd_printf_P(PSTR(ESC_H(0,0) "Last print failures" ESC_H(1,1) "Filam. runouts  %-3d" ESC_H(0,2) "Total failures" ESC_H(1,3) "Filam. runouts  %-3d"), filamentLast, filamentTotal);
@@ -2069,6 +2071,7 @@ static void lcd_menu_fails_stats()
 #else
 static void lcd_menu_fails_stats()
 {
+	lcd_timeoutToStatus.stop(); //infinite timeout
 	MENU_BEGIN();
 	MENU_ITEM_BACK_P(_T(MSG_MAIN));
 	MENU_END();
@@ -2095,6 +2098,8 @@ static void lcd_menu_debug()
 
 static void lcd_menu_temperatures()
 {
+	lcd_timeoutToStatus.stop(); //infinite timeout
+
 	lcd_printf_P(PSTR(ESC_H(1,0) "Nozzle:   %d%c" ESC_H(1,1) "Bed:      %d%c"), (int)current_temperature[0], '\x01', (int)current_temperature_bed, '\x01');
 #ifdef AMBIENT_THERMISTOR
 	lcd_printf_P(PSTR(ESC_H(1,2) "Ambient:  %d%c" ESC_H(1,3) "PINDA:    %d%c"), (int)current_temperature_ambient, '\x01', (int)current_temperature_pinda, '\x01');
@@ -2112,6 +2117,7 @@ static void lcd_menu_temperatures()
 #define VOLT_DIV_REF 5
 static void lcd_menu_voltages()
 {
+	lcd_timeoutToStatus.stop(); //infinite timeout
 	float volt_pwr = VOLT_DIV_REF * ((float)current_voltage_raw_pwr / (1023 * OVERSAMPLENR)) / VOLT_DIV_FAC;
 //	float volt_bed = VOLT_DIV_REF * ((float)current_voltage_raw_bed / (1023 * OVERSAMPLENR)) / VOLT_DIV_FAC;
 //	lcd_printf_P(PSTR(ESC_H(1,1)"PWR:      %d.%01dV" ESC_H(1,2)"BED:      %d.%01dV"), (int)volt_pwr, (int)(10*fabs(volt_pwr - (int)volt_pwr)), (int)volt_bed, (int)(10*fabs(volt_bed - (int)volt_bed)));
@@ -2170,21 +2176,34 @@ static void lcd_preheat_menu()
 
 static void lcd_support_menu()
 {
-    if (menuData.supportMenu.status == 0 || lcd_draw_update == 2) {
+	typedef struct
+	{	// 22bytes total
+		int8_t status;                 // 1byte
+		bool is_flash_air;             // 1byte
+		uint8_t ip[4];                 // 4bytes
+		char ip_str[3*4+3+1];          // 16bytes
+	} _menu_data_t;
+#if (22 > MENU_DATA_SIZE)
+#error "check MENU_DATA_SIZE definition!"
+#endif
+	_menu_data_t* _md = (_menu_data_t*)&(menu_data[0]);
+    if (_md->status == 0 || lcd_draw_update == 2)
+	{
         // Menu was entered or SD card status has changed (plugged in or removed).
         // Initialize its status.
-        menuData.supportMenu.status = 1;
-        menuData.supportMenu.is_flash_air = card.ToshibaFlashAir_isEnabled() && card.ToshibaFlashAir_GetIP(menuData.supportMenu.ip);
-        if (menuData.supportMenu.is_flash_air)
-            sprintf_P(menuData.supportMenu.ip_str, PSTR("%d.%d.%d.%d"), 
-                menuData.supportMenu.ip[0], menuData.supportMenu.ip[1], 
-                menuData.supportMenu.ip[2], menuData.supportMenu.ip[3]);
-    } else if (menuData.supportMenu.is_flash_air && 
-        menuData.supportMenu.ip[0] == 0 && menuData.supportMenu.ip[1] == 0 && 
-        menuData.supportMenu.ip[2] == 0 && menuData.supportMenu.ip[3] == 0 &&
-        ++ menuData.supportMenu.status == 16) {
+        _md->status = 1;
+        _md->is_flash_air = card.ToshibaFlashAir_isEnabled() && card.ToshibaFlashAir_GetIP(_md->ip);
+        if (_md->is_flash_air)
+            sprintf_P(_md->ip_str, PSTR("%d.%d.%d.%d"), 
+                _md->ip[0], _md->ip[1], 
+                _md->ip[2], _md->ip[3]);
+    } else if (_md->is_flash_air && 
+        _md->ip[0] == 0 && _md->ip[1] == 0 && 
+        _md->ip[2] == 0 && _md->ip[3] == 0 &&
+        ++ _md->status == 16)
+	{
         // Waiting for the FlashAir card to get an IP address from a router. Force an update.
-        menuData.supportMenu.status = 0;
+        _md->status = 0;
     }
 
   MENU_BEGIN();
@@ -2207,22 +2226,41 @@ static void lcd_support_menu()
   MENU_ITEM_BACK_P(_i("prusa3d.com"));////MSG_PRUSA3D c=0 r=0
   MENU_ITEM_BACK_P(_i("forum.prusa3d.com"));////MSG_PRUSA3D_FORUM c=0 r=0
   MENU_ITEM_BACK_P(_i("howto.prusa3d.com"));////MSG_PRUSA3D_HOWTO c=0 r=0
-  MENU_ITEM_BACK_P(PSTR("------------"));
+  MENU_ITEM_BACK_P(STR_SEPARATOR);
   MENU_ITEM_BACK_P(PSTR(FILAMENT_SIZE));
   MENU_ITEM_BACK_P(PSTR(ELECTRONICS));
   MENU_ITEM_BACK_P(PSTR(NOZZLE_TYPE));
-  MENU_ITEM_BACK_P(PSTR("------------"));
+  MENU_ITEM_BACK_P(STR_SEPARATOR);
   MENU_ITEM_BACK_P(_i("Date:"));////MSG_DATE c=17 r=1
   MENU_ITEM_BACK_P(PSTR(__DATE__));
 
+	MENU_ITEM_BACK_P(STR_SEPARATOR);
+	if (mmu_enabled)
+	{
+		MENU_ITEM_BACK_P(PSTR("MMU2 connected"));
+		MENU_ITEM_BACK_P(PSTR(" FW:"));
+		if (((menu_item - 1) == menu_line) && lcd_draw_update)
+		{
+		    lcd_set_cursor(6, menu_row);
+			if ((mmu_version > 0) && (mmu_buildnr > 0))
+				lcd_printf_P(PSTR("%d.%d.%d-%d"), mmu_version/100, mmu_version%100/10, mmu_version%10, mmu_buildnr);
+			else
+				lcd_puts_P(PSTR("unknown")); 
+		}
+	}
+	else
+		MENU_ITEM_BACK_P(PSTR("MMU2       N/A"));
+
+
   // Show the FlashAir IP address, if the card is available.
-  if (menuData.supportMenu.is_flash_air) {
-      MENU_ITEM_BACK_P(PSTR("------------"));
+  if (_md->is_flash_air) {
+      MENU_ITEM_BACK_P(STR_SEPARATOR);
       MENU_ITEM_BACK_P(PSTR("FlashAir IP Addr:"));
-///!      MENU_ITEM(back_RAM, menuData.supportMenu.ip_str, 0);
+///!      MENU_ITEM(back_RAM, _md->ip_str, 0);
   }
+
   #ifndef MK1BP
-  MENU_ITEM_BACK_P(PSTR("------------"));
+  MENU_ITEM_BACK_P(STR_SEPARATOR);
   MENU_ITEM_SUBMENU_P(_i("XYZ cal. details"), lcd_menu_xyz_y_min);////MSG_XYZ_DETAILS c=19 r=1
   MENU_ITEM_SUBMENU_P(_i("Extruder info"), lcd_menu_extruder_info);////MSG_INFO_EXTRUDER c=15 r=1
 
@@ -2476,7 +2514,7 @@ static void lcd_menu_AutoLoadFilament()
     }
     else
     {
-		ShortTimer* ptimer = (ShortTimer*)&(menuData.autoLoadFilamentMenu.dummy);
+		ShortTimer* ptimer = (ShortTimer*)&(menu_data[0]);
         if (!ptimer->running()) ptimer->start();
         lcd_set_cursor(0, 0);
         lcd_puts_P(_T(MSG_ERROR));
@@ -2586,10 +2624,19 @@ void lcd_menu_statistics()
 
 static void _lcd_move(const char *name, int axis, int min, int max)
 {
-	if (!menuData._lcd_moveMenu.initialized)
+	typedef struct
+	{	// 2bytes total
+		bool initialized;              // 1byte
+		bool endstopsEnabledPrevious;  // 1byte
+	} _menu_data_t;
+#if (2 > MENU_DATA_SIZE)
+#error "check MENU_DATA_SIZE definition!"
+#endif
+	_menu_data_t* _md = (_menu_data_t*)&(menu_data[0]);
+	if (!_md->initialized)
 	{
-		menuData._lcd_moveMenu.endstopsEnabledPrevious = enable_endstops(false);
-		menuData._lcd_moveMenu.initialized = true;
+		_md->endstopsEnabledPrevious = enable_endstops(false);
+		_md->initialized = true;
 	}
 	if (lcd_encoder != 0)
 	{
@@ -2610,7 +2657,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(menuData._lcd_moveMenu.endstopsEnabledPrevious);
+	if (menuExiting || LCD_CLICKED) (void)enable_endstops(_md->endstopsEnabledPrevious);
 	if (LCD_CLICKED) menu_back();
 }
 
@@ -2782,23 +2829,37 @@ static void lcd_move_z() {
  */
 static void _lcd_babystep(int axis, const char *msg) 
 {
-	if (menuData.babyStep.status == 0)
+	typedef struct
+	{	// 19bytes total
+		int8_t status;                 // 1byte
+		int babystepMem[3];            // 6bytes
+		float babystepMemMM[3];        // 12bytes
+	} _menu_data_t;
+#if (19 > MENU_DATA_SIZE)
+#error "check MENU_DATA_SIZE definition!"
+#endif
+	_menu_data_t* _md = (_menu_data_t*)&(menu_data[0]);
+	if (_md->status == 0)
 	{
 		// Menu was entered.
 		// Initialize its status.
-		menuData.babyStep.status = 1;
+		_md->status = 1;
 		check_babystep();
 
-		EEPROM_read_B(EEPROM_BABYSTEP_X, &menuData.babyStep.babystepMem[0]);
-		EEPROM_read_B(EEPROM_BABYSTEP_Y, &menuData.babyStep.babystepMem[1]);
-		EEPROM_read_B(EEPROM_BABYSTEP_Z, &menuData.babyStep.babystepMem[2]);
+		EEPROM_read_B(EEPROM_BABYSTEP_X, &_md->babystepMem[0]);
+		EEPROM_read_B(EEPROM_BABYSTEP_Y, &_md->babystepMem[1]);
+		EEPROM_read_B(EEPROM_BABYSTEP_Z, &_md->babystepMem[2]);
+
+		// same logic as in babystep_load
+	    if (calibration_status() >= CALIBRATION_STATUS_LIVE_ADJUST)
+			_md->babystepMem[2] = 0;
 
-		menuData.babyStep.babystepMemMM[0] = menuData.babyStep.babystepMem[0]/axis_steps_per_unit[X_AXIS];
-		menuData.babyStep.babystepMemMM[1] = menuData.babyStep.babystepMem[1]/axis_steps_per_unit[Y_AXIS];
-		menuData.babyStep.babystepMemMM[2] = menuData.babyStep.babystepMem[2]/axis_steps_per_unit[Z_AXIS];
+		_md->babystepMemMM[0] = _md->babystepMem[0]/axis_steps_per_unit[X_AXIS];
+		_md->babystepMemMM[1] = _md->babystepMem[1]/axis_steps_per_unit[Y_AXIS];
+		_md->babystepMemMM[2] = _md->babystepMem[2]/axis_steps_per_unit[Z_AXIS];
 		lcd_draw_update = 1;
 		//SERIAL_ECHO("Z baby step: ");
-		//SERIAL_ECHO(menuData.babyStep.babystepMem[2]);
+		//SERIAL_ECHO(_md->babystepMem[2]);
 		// Wait 90 seconds before closing the live adjust dialog.
 		lcd_timeoutToStatus.start();
 	}
@@ -2806,11 +2867,11 @@ static void _lcd_babystep(int axis, const char *msg)
 	if (lcd_encoder != 0) 
 	{
 		if (homing_flag) lcd_encoder = 0;
-		menuData.babyStep.babystepMem[axis] += (int)lcd_encoder;
+		_md->babystepMem[axis] += (int)lcd_encoder;
 		if (axis == 2)
 		{
-			if (menuData.babyStep.babystepMem[axis] < Z_BABYSTEP_MIN) menuData.babyStep.babystepMem[axis] = Z_BABYSTEP_MIN; //-3999 -> -9.99 mm
-			else if (menuData.babyStep.babystepMem[axis] > Z_BABYSTEP_MAX) menuData.babyStep.babystepMem[axis] = Z_BABYSTEP_MAX; //0
+			if (_md->babystepMem[axis] < Z_BABYSTEP_MIN) _md->babystepMem[axis] = Z_BABYSTEP_MIN; //-3999 -> -9.99 mm
+			else if (_md->babystepMem[axis] > Z_BABYSTEP_MAX) _md->babystepMem[axis] = Z_BABYSTEP_MAX; //0
 			else
 			{
 				CRITICAL_SECTION_START
@@ -2818,7 +2879,7 @@ static void _lcd_babystep(int axis, const char *msg)
 				CRITICAL_SECTION_END		
 			}
 		}
-		menuData.babyStep.babystepMemMM[axis] = menuData.babyStep.babystepMem[axis]/axis_steps_per_unit[axis]; 
+		_md->babystepMemMM[axis] = _md->babystepMem[axis]/axis_steps_per_unit[axis]; 
 		delay(50);
 		lcd_encoder = 0;
 		lcd_draw_update = 1;
@@ -2826,14 +2887,14 @@ static void _lcd_babystep(int axis, const char *msg)
 	if (lcd_draw_update)
 	{
 	    lcd_set_cursor(0, 1);
-		menu_draw_float13(' ', msg, menuData.babyStep.babystepMemMM[axis]);
+		menu_draw_float13(' ', msg, _md->babystepMemMM[axis]);
 	}
 	if (LCD_CLICKED || menuExiting)
 	{
 		// Only update the EEPROM when leaving the menu.
 		EEPROM_save_B(
 		(axis == X_AXIS) ? EEPROM_BABYSTEP_X : ((axis == Y_AXIS) ? EEPROM_BABYSTEP_Y : EEPROM_BABYSTEP_Z),
-		&menuData.babyStep.babystepMem[axis]);
+		&_md->babystepMem[axis]);
 		if(Z_AXIS == axis) calibration_status_store(CALIBRATION_STATUS_CALIBRATED);
 	}
 	if (LCD_CLICKED) menu_back();
@@ -2845,72 +2906,94 @@ static void lcd_babystep_z() {
 
 static void lcd_adjust_bed();
 
+typedef struct
+{	// 13bytes total
+	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
+} _menu_data_adjust_bed_t;
+#if (13 > MENU_DATA_SIZE)
+#error "check MENU_DATA_SIZE definition!"
+#endif
+
 static void lcd_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);
-    menuData.adjustBed.status = 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);
+	_menu_data_adjust_bed_t* _md = (_menu_data_adjust_bed_t*)&(menu_data[0]);
+	_md->status = 0;
 }
 
-void adjust_bed_reset() {
+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);
-	menuData.adjustBed.left = menuData.adjustBed.left2 = 0;
-	menuData.adjustBed.right = menuData.adjustBed.right2 = 0;
-	menuData.adjustBed.front = menuData.adjustBed.front2 = 0;
-	menuData.adjustBed.rear = menuData.adjustBed.rear2 = 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()
 {
-    if (menuData.adjustBed.status == 0) {
+	_menu_data_adjust_bed_t* _md = (_menu_data_adjust_bed_t*)&(menu_data[0]);
+    if (_md->status == 0)
+	{
         // Menu was entered.
         // Initialize its status.
-        menuData.adjustBed.status = 1;
+        _md->status = 1;
         bool valid = false;
-        menuData.adjustBed.left  = menuData.adjustBed.left2  = eeprom_read_int8((unsigned char*)EEPROM_BED_CORRECTION_LEFT);
-        menuData.adjustBed.right = menuData.adjustBed.right2 = eeprom_read_int8((unsigned char*)EEPROM_BED_CORRECTION_RIGHT);
-        menuData.adjustBed.front = menuData.adjustBed.front2 = eeprom_read_int8((unsigned char*)EEPROM_BED_CORRECTION_FRONT);
-        menuData.adjustBed.rear  = menuData.adjustBed.rear2  = eeprom_read_int8((unsigned char*)EEPROM_BED_CORRECTION_REAR);
+        _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 && 
-            menuData.adjustBed.left  >= -BED_ADJUSTMENT_UM_MAX && menuData.adjustBed.left  <= BED_ADJUSTMENT_UM_MAX &&
-            menuData.adjustBed.right >= -BED_ADJUSTMENT_UM_MAX && menuData.adjustBed.right <= BED_ADJUSTMENT_UM_MAX &&
-            menuData.adjustBed.front >= -BED_ADJUSTMENT_UM_MAX && menuData.adjustBed.front <= BED_ADJUSTMENT_UM_MAX &&
-            menuData.adjustBed.rear  >= -BED_ADJUSTMENT_UM_MAX && menuData.adjustBed.rear  <= BED_ADJUSTMENT_UM_MAX)
+            _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.
-            menuData.adjustBed.left2  = 0;
-            menuData.adjustBed.right2 = 0;
-            menuData.adjustBed.front2 = 0;
-            menuData.adjustBed.rear2  = 0;
+            _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 (menuData.adjustBed.left  != menuData.adjustBed.left2)
-        eeprom_update_int8((unsigned char*)EEPROM_BED_CORRECTION_LEFT,  menuData.adjustBed.left  = menuData.adjustBed.left2);
-    if (menuData.adjustBed.right != menuData.adjustBed.right2)
-        eeprom_update_int8((unsigned char*)EEPROM_BED_CORRECTION_RIGHT, menuData.adjustBed.right = menuData.adjustBed.right2);
-    if (menuData.adjustBed.front != menuData.adjustBed.front2)
-        eeprom_update_int8((unsigned char*)EEPROM_BED_CORRECTION_FRONT, menuData.adjustBed.front = menuData.adjustBed.front2);
-    if (menuData.adjustBed.rear  != menuData.adjustBed.rear2)
-        eeprom_update_int8((unsigned char*)EEPROM_BED_CORRECTION_REAR,  menuData.adjustBed.rear  = menuData.adjustBed.rear2);
+    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]"),  &menuData.adjustBed.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]"), &menuData.adjustBed.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]"), &menuData.adjustBed.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]"),  &menuData.adjustBed.rear2,  -BED_ADJUSTMENT_UM_MAX, BED_ADJUSTMENT_UM_MAX);////MSG_BED_CORRECTION_REAR c=14 r=1
+    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
     MENU_ITEM_FUNCTION_P(_i("Reset"), lcd_adjust_bed_reset);////MSG_BED_CORRECTION_RESET c=0 r=0
     MENU_END();
 }
@@ -2933,7 +3016,7 @@ void pid_extruder() {
 	}
 
 }
-
+/*
 void lcd_adjust_z() {
   int enc_dif = 0;
   int cursor_pos = 1;
@@ -3016,7 +3099,7 @@ void lcd_adjust_z() {
   lcd_clear();
   lcd_return_to_status();
 
-}
+}*/
 
 bool lcd_wait_for_pinda(float temp) {
 	lcd_set_custom_characters_degree();
@@ -4717,7 +4800,6 @@ static void lcd_settings_menu_back()
 }
 #endif //LINEARITY_CORRECTION
 
-
 static void lcd_calibration_menu()
 {
   MENU_BEGIN();
@@ -5672,15 +5754,30 @@ static void lcd_colorprint_change() {
 
 static void lcd_tune_menu()
 {
-  if (menuData.tuneMenu.status == 0) {
-    // Menu was entered. Mark the menu as entered and save the current extrudemultiply value.
-    menuData.tuneMenu.status = 1;
-    menuData.tuneMenu.extrudemultiply = extrudemultiply;
-  } else if (menuData.tuneMenu.extrudemultiply != extrudemultiply) {
-    // extrudemultiply has been changed from the child menu. Apply the new value.
-    menuData.tuneMenu.extrudemultiply = extrudemultiply;
-    calculate_extruder_multipliers();
-  }
+	typedef struct
+	{	// 3bytes total
+		// To recognize, whether the menu has been just initialized.
+		int8_t  status;                                 // 1byte
+		// Backup of extrudemultiply, to recognize, that the value has been changed and
+		// it needs to be applied.
+		int16_t extrudemultiply;                        // 2byte
+	} _menu_data_t;
+#if (3 > MENU_DATA_SIZE)
+#error "check MENU_DATA_SIZE definition!"
+#endif
+	_menu_data_t* _md = (_menu_data_t*)&(menu_data[0]);
+	if (_md->status == 0)
+	{
+		// Menu was entered. Mark the menu as entered and save the current extrudemultiply value.
+		_md->status = 1;
+		_md->extrudemultiply = extrudemultiply;
+	}
+	else if (_md->extrudemultiply != extrudemultiply)
+	{
+		// extrudemultiply has been changed from the child menu. Apply the new value.
+		_md->extrudemultiply = extrudemultiply;
+		calculate_extruder_multipliers();
+	}
 
   EEPROM_read(EEPROM_SILENT, (uint8_t*)&SilentModeMenu, sizeof(SilentModeMenu));
 

+ 0 - 88
Firmware/ultralcd.h

@@ -14,92 +14,6 @@ extern void menu_lcd_longpress_func(void);
 extern void menu_lcd_charsetup_func(void);
 extern void menu_lcd_lcdupdate_func(void);
 
-struct EditMenuParentState
-{
-    //prevMenu and prevEncoderPosition are used to store the previous menu location when editing settings.
-    menu_func_t prevMenu;
-    uint16_t prevEncoderPosition;
-    //Variables used when editing values.
-    const char* editLabel;
-    void* editValue;
-    int32_t minEditValue, maxEditValue;
-    // menu_func_t callbackFunc;
-};
-
-union MenuData
-{
-    struct BabyStep
-    {
-        // 29B total
-        int8_t status;
-        int babystepMem[3];
-        float babystepMemMM[3];
-    } babyStep;
-
-    struct SupportMenu
-    {
-        // 6B+16B=22B total
-        int8_t status;
-        bool is_flash_air;
-        uint8_t ip[4];
-        char ip_str[3*4+3+1];
-    } supportMenu;
-
-    struct AdjustBed
-    {
-        // 6+13+16=35B
-        // editMenuParentState is used when an edit menu is entered, so it knows
-        // the return menu and encoder state.
-        struct EditMenuParentState editMenuParentState;
-        int8_t status;
-        int8_t left;
-        int8_t right;
-        int8_t front;
-        int8_t rear;
-        int    left2;
-        int    right2;
-        int    front2;
-        int    rear2;
-    } adjustBed;
-
-    struct TuneMenu
-    {
-        // editMenuParentState is used when an edit menu is entered, so it knows
-        // the return menu and encoder state.
-        struct EditMenuParentState editMenuParentState;
-        // To recognize, whether the menu has been just initialized.
-        int8_t  status;
-        // Backup of extrudemultiply, to recognize, that the value has been changed and
-        // it needs to be applied.
-        int16_t extrudemultiply;
-    } tuneMenu;
-
-    // editMenuParentState is used when an edit menu is entered, so it knows
-    // the return menu and encoder state.
-    struct EditMenuParentState editMenuParentState;
-
-    struct AutoLoadFilamentMenu
-    {
-        //ShortTimer timer;
-        char dummy;
-    } autoLoadFilamentMenu;
-    struct _Lcd_moveMenu
-    {
-        bool initialized;
-        bool endstopsEnabledPrevious;
-    } _lcd_moveMenu;
-    struct sdcard_menu_t
-    {
-        uint8_t viewState;
-    } sdcard_menu;
-    menu_data_edit_t edit_menu;
-};
-
-// State of the currently active menu.
-// C Union manages sharing of the static memory by all the menus.
-extern union MenuData menuData;
-
-
   // 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);
@@ -226,8 +140,6 @@ void lcd_temp_cal_show_result(bool result);
 bool lcd_wait_for_pinda(float temp);
 
 
-union MenuData;
-
 void bowden_menu();
 char reset_menu();
 char choose_extruder_menu();

+ 8 - 8
Firmware/xyzcal.cpp

@@ -686,17 +686,17 @@ uint8_t xyzcal_xycoords2point(int16_t x, int16_t y)
 
 //MK3
 #if ((MOTHERBOARD == BOARD_EINSY_1_0a))
-const int16_t PROGMEM xyzcal_point_xcoords[4] = {1200, 22000, 22000, 1200};
-const int16_t PROGMEM xyzcal_point_ycoords[4] = {600, 600, 19800, 19800};
+const int16_t xyzcal_point_xcoords[4] PROGMEM = {1200, 22000, 22000, 1200};
+const int16_t xyzcal_point_ycoords[4] PROGMEM = {600, 600, 19800, 19800};
 #endif //((MOTHERBOARD == BOARD_EINSY_1_0a))
 
 //MK2.5
 #if ((MOTHERBOARD == BOARD_RAMBO_MINI_1_0) || (MOTHERBOARD == BOARD_RAMBO_MINI_1_3))
-const int16_t PROGMEM xyzcal_point_xcoords[4] = {1200, 22000, 22000, 1200};
-const int16_t PROGMEM xyzcal_point_ycoords[4] = {700, 700, 19800, 19800};
+const int16_t xyzcal_point_xcoords[4] PROGMEM = {1200, 22000, 22000, 1200};
+const int16_t xyzcal_point_ycoords[4] PROGMEM = {700, 700, 19800, 19800};
 #endif //((MOTHERBOARD == BOARD_RAMBO_MINI_1_0) || (MOTHERBOARD == BOARD_RAMBO_MINI_1_3))
 
-const uint16_t PROGMEM xyzcal_point_pattern[12] = {0x000, 0x0f0, 0x1f8, 0x3fc, 0x7fe, 0x7fe, 0x7fe, 0x7fe, 0x3fc, 0x1f8, 0x0f0, 0x000};
+const uint16_t xyzcal_point_pattern[12] PROGMEM = {0x000, 0x0f0, 0x1f8, 0x3fc, 0x7fe, 0x7fe, 0x7fe, 0x7fe, 0x3fc, 0x1f8, 0x0f0, 0x000};
 
 bool xyzcal_searchZ(void)
 {
@@ -747,7 +747,7 @@ bool xyzcal_scan_and_process(void)
 	uint16_t* pattern = (uint16_t*)(histo + 2*16);
 	for (uint8_t i = 0; i < 12; i++)
 	{
-		pattern[i] = pgm_read_word_far((uint16_t*)(xyzcal_point_pattern + i));
+		pattern[i] = pgm_read_word((uint16_t*)(xyzcal_point_pattern + i));
 //		DBG(_n(" pattern[%d]=%d\n"), i, pattern[i]);
 	}
 	uint8_t c = 0;
@@ -777,8 +777,8 @@ bool xyzcal_find_bed_induction_sensor_point_xy(void)
 	int16_t y = _Y;
 	int16_t z = _Z;
 	uint8_t point = xyzcal_xycoords2point(x, y);
-	x = pgm_read_word_far((uint16_t*)(xyzcal_point_xcoords + point));
-	y = pgm_read_word_far((uint16_t*)(xyzcal_point_ycoords + point));
+	x = pgm_read_word((uint16_t*)(xyzcal_point_xcoords + point));
+	y = pgm_read_word((uint16_t*)(xyzcal_point_ycoords + point));
 	DBG(_n("point=%d x=%d y=%d z=%d\n"), point, x, y, z);
 	xyzcal_meassure_enter();
 	xyzcal_lineXYZ_to(x, y, z, 200, 0);