Browse Source

Merge branch 'MK3' into PFW-873

MRprusa3d 4 years ago
parent
commit
98bae7af9f

+ 7 - 0
.travis.yml

@@ -1,6 +1,13 @@
 dist: trusty
 before_install:
   - sudo apt-get install -y ninja-build
+  # Arduino IDE adds a lot of noise caused by network traffic, trying to firewall it off
+  - sudo iptables -P INPUT DROP
+  - sudo iptables -P FORWARD DROP
+  - sudo iptables -P OUTPUT ACCEPT
+  - sudo iptables -A INPUT -i lo -j ACCEPT
+  - sudo iptables -A OUTPUT -o lo -j ACCEPT
+  - sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
 script:
   - bash -x test.sh
   - cp Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h Firmware/Configuration_prusa.h

+ 2 - 2
Firmware/Configuration.h

@@ -16,8 +16,8 @@ extern uint16_t nPrinterType;
 extern PGM_P sPrinterName;
 
 // Firmware version
-#define FW_VERSION "3.7.1"
-#define FW_COMMIT_NR   2266
+#define FW_VERSION "3.7.2-RC1"
+#define FW_COMMIT_NR   2359
 // 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

+ 1 - 2
Firmware/Marlin.h

@@ -323,7 +323,6 @@ extern float retract_recover_length_swap;
 
 extern uint8_t host_keepalive_interval;
 
-
 extern unsigned long starttime;
 extern unsigned long stoptime;
 extern int bowden_length[4];
@@ -392,7 +391,7 @@ extern bool wizard_active; //autoload temporarily disabled during wizard
 extern LongTimer safetyTimer;
 
 #define PRINT_PERCENT_DONE_INIT   0xff
-#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)
+#define PRINTER_ACTIVE (IS_SD_PRINTING || is_usb_printing || isPrintPaused || (custom_message_type == CustomMsg::TempCal) || saved_printing || (lcd_commands_type == LcdCommands::Layer1Cal) || card.paused || mmu_print_saved)
 //! Beware - mcode_in_progress is set as soon as the command gets really processed,
 //! which is not the same as posting the M600 command into the command queue
 //! There can be a considerable lag between posting M600 and its real processing which might result

+ 36 - 43
Firmware/Marlin_main.cpp

@@ -356,7 +356,6 @@ unsigned long starttime=0;
 unsigned long stoptime=0;
 unsigned long _usb_timer = 0;
 
-
 bool extruder_under_pressure = true;
 
 
@@ -1078,6 +1077,7 @@ void setup()
 	SERIAL_ECHO_START;
 	printf_P(PSTR(" " FW_VERSION_FULL "\n"));
 
+	//SERIAL_ECHOPAIR("Active sheet before:", static_cast<unsigned long int>(eeprom_read_byte(&(EEPROM_Sheets_base->active_sheet))));
 
 #ifdef DEBUG_SEC_LANG
 	lang_table_header_t header;
@@ -1426,20 +1426,7 @@ void setup()
 		printf_P(PSTR("Card NG!\n"));
 #endif //DEBUG_SD_SPEED_TEST
 
-	if (eeprom_read_byte((uint8_t*)EEPROM_POWER_COUNT) == 0xff) eeprom_write_byte((uint8_t*)EEPROM_POWER_COUNT, 0);
-	if (eeprom_read_byte((uint8_t*)EEPROM_CRASH_COUNT_X) == 0xff) eeprom_write_byte((uint8_t*)EEPROM_CRASH_COUNT_X, 0);
-	if (eeprom_read_byte((uint8_t*)EEPROM_CRASH_COUNT_Y) == 0xff) eeprom_write_byte((uint8_t*)EEPROM_CRASH_COUNT_Y, 0);
-	if (eeprom_read_byte((uint8_t*)EEPROM_FERROR_COUNT) == 0xff) eeprom_write_byte((uint8_t*)EEPROM_FERROR_COUNT, 0);
-	if (eeprom_read_word((uint16_t*)EEPROM_POWER_COUNT_TOT) == 0xffff) eeprom_write_word((uint16_t*)EEPROM_POWER_COUNT_TOT, 0);
-	if (eeprom_read_word((uint16_t*)EEPROM_CRASH_COUNT_X_TOT) == 0xffff) eeprom_write_word((uint16_t*)EEPROM_CRASH_COUNT_X_TOT, 0);
-	if (eeprom_read_word((uint16_t*)EEPROM_CRASH_COUNT_Y_TOT) == 0xffff) eeprom_write_word((uint16_t*)EEPROM_CRASH_COUNT_Y_TOT, 0);
-	if (eeprom_read_word((uint16_t*)EEPROM_FERROR_COUNT_TOT) == 0xffff) eeprom_write_word((uint16_t*)EEPROM_FERROR_COUNT_TOT, 0);
-
-	if (eeprom_read_word((uint16_t*)EEPROM_MMU_FAIL_TOT) == 0xffff) eeprom_update_word((uint16_t *)EEPROM_MMU_FAIL_TOT, 0);
-	if (eeprom_read_word((uint16_t*)EEPROM_MMU_LOAD_FAIL_TOT) == 0xffff) eeprom_update_word((uint16_t *)EEPROM_MMU_LOAD_FAIL_TOT, 0);
-	if (eeprom_read_byte((uint8_t*)EEPROM_MMU_FAIL) == 0xff) eeprom_update_byte((uint8_t *)EEPROM_MMU_FAIL, 0);
-	if (eeprom_read_byte((uint8_t*)EEPROM_MMU_LOAD_FAIL) == 0xff) eeprom_update_byte((uint8_t *)EEPROM_MMU_LOAD_FAIL, 0);
-
+    eeprom_init();
 #ifdef SNMM
 	if (eeprom_read_dword((uint32_t*)EEPROM_BOWDEN_LENGTH) == 0x0ffffffff) { //bowden length used for SNMM
 	  int _z = BOWDEN_LENGTH;
@@ -1506,7 +1493,6 @@ void setup()
 		SilentModeMenu_MMU = 1;
 		eeprom_write_byte((uint8_t*)EEPROM_MMU_STEALTH, SilentModeMenu_MMU);
 	}
-	check_babystep(); //checking if Z babystep is in allowed range
 
 #if !defined(DEBUG_DISABLE_FANCHECK) && defined(FANCHECK) && defined(TACH_1) && TACH_1 >-1
 	setup_fan_interrupt();
@@ -3161,7 +3147,7 @@ static void gcode_M600(bool automatic, float x_position, float y_position, float
 #endif //IR_SENSOR
 
     lcd_setstatuspgm(_T(WELCOME_MSG));
-    custom_message_type = CUSTOM_MSG_TYPE_STATUS;
+    custom_message_type = CustomMsg::Status;
 }
 
 //! @brief Rise Z if too low to avoid blob/jam before filament loading
@@ -3177,6 +3163,11 @@ void gcode_M701()
 {
 	printf_P(PSTR("gcode_M701 begin\n"));
 
+	if (farm_mode)
+	{
+		prusa_statistics(22);
+	}
+
 	if (mmu_enabled) 
 	{
 		extr_adj(tmp_extruder);//loads current extruder
@@ -3185,7 +3176,7 @@ void gcode_M701()
 	else
 	{
 		enable_z();
-		custom_message_type = CUSTOM_MSG_TYPE_F_LOAD;
+		custom_message_type = CustomMsg::FilamentLoading;
 
 #ifdef FSENSOR_QUALITY
 		fsensor_oq_meassure_start(40);
@@ -3215,7 +3206,7 @@ void gcode_M701()
 		lcd_setstatuspgm(_T(WELCOME_MSG));
 		disable_z();
 		loading_flag = false;
-		custom_message_type = CUSTOM_MSG_TYPE_STATUS;
+		custom_message_type = CustomMsg::Status;
 
 #ifdef FSENSOR_QUALITY
         fsensor_oq_meassure_stop();
@@ -4264,7 +4255,7 @@ if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
 //			setTargetHotend(200, 0);
 			setTargetBed(70 + (start_temp - 30));
 
-			custom_message_type = CUSTOM_MSG_TYPE_TEMCAL;
+			custom_message_type = CustomMsg::TempCal;
 			custom_message_state = 1;
 			lcd_setstatuspgm(_T(MSG_TEMP_CALIBRATION));
 			current_position[Z_AXIS] = MESH_HOME_Z_SEARCH;
@@ -4366,7 +4357,7 @@ if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
 			break;
 		}
 		puts_P(_N("PINDA probe calibration start"));
-		custom_message_type = CUSTOM_MSG_TYPE_TEMCAL;
+		custom_message_type = CustomMsg::TempCal;
 		custom_message_state = 1;
 		lcd_setstatuspgm(_T(MSG_TEMP_CALIBRATION));
 		current_position[X_AXIS] = PINDA_PREHEAT_X;
@@ -4434,7 +4425,7 @@ if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
 			
 		
 		}
-		custom_message_type = CUSTOM_MSG_TYPE_STATUS;
+		custom_message_type = CustomMsg::Status;
 
 		eeprom_update_byte((uint8_t*)EEPROM_CALIBRATION_STATUS_PINDA, 1);
 		puts_P(_N("Temperature calibration done."));
@@ -4494,7 +4485,7 @@ if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
 			// We don't know where we are! HOME!
 			// Push the commands to the front of the message queue in the reverse order!
 			// There shall be always enough space reserved for these commands.
-			if (lcd_commands_type != LCD_COMMAND_STOP_PRINT) {
+			if (lcd_commands_type != LcdCommands::StopPrint) {
 				repeatcommand_front(); // repeat G80 with all its parameters
 				enquecommand_front_P((PSTR("G28 W0")));
 			}
@@ -4534,7 +4525,7 @@ if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
 
 		if (temp_comp_start)
 		if (run == false && temp_cal_active == true && calibration_status_pinda() == true && target_temperature_bed >= 50) {
-			if (lcd_commands_type != LCD_COMMAND_STOP_PRINT) {
+			if (lcd_commands_type != LcdCommands::StopPrint) {
 				temp_compensation_start();
 				run = true;
 				repeatcommand_front(); // repeat G80 with all its parameters
@@ -4546,14 +4537,14 @@ if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
 			break;
 		}
 		run = false;
-		if (lcd_commands_type == LCD_COMMAND_STOP_PRINT) {
+		if (lcd_commands_type == LcdCommands::StopPrint) {
 			mesh_bed_leveling_flag = false;
 			break;
 		}
 		// Save custom message state, set a new custom message state to display: Calibrating point 9.
-		unsigned int custom_message_type_old = custom_message_type;
+		CustomMsg custom_message_type_old = custom_message_type;
 		unsigned int custom_message_state_old = custom_message_state;
-		custom_message_type = CUSTOM_MSG_TYPE_MESHBL;
+		custom_message_type = CustomMsg::MeshBedLeveling;
 		custom_message_state = (nMeasPoints * nMeasPoints) + 10;
 		lcd_update(1);
 
@@ -4753,7 +4744,7 @@ if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
                     enable_z_endstop(bState);
                     } while (st_get_position_mm(Z_AXIS) > MESH_HOME_Z_SEARCH); // i.e. Z-leveling not o.k.
 //               plan_set_z_position(MESH_HOME_Z_SEARCH); // is not necessary ('do-while' loop always ends at the expected Z-position)
-               custom_message_type=CUSTOM_MSG_TYPE_STATUS; // display / status-line recovery
+               custom_message_type=CustomMsg::Status; // display / status-line recovery
                lcd_update_enable(true);           // display / status-line recovery
                gcode_G28(true, true, true);       // X & Y & Z-homing (must be after individual Z-homing (problem with spool-holder)!)
                repeatcommand_front();             // re-run (i.e. of "G80")
@@ -6000,7 +5991,7 @@ Sigma_Exit:
           SERIAL_PROTOCOLLNRPGM(FW_VERSION_STR_P());
       } else if (code_seen('U')) {
           // Check the firmware version provided. If the firmware version provided by the U code is higher than the currently running firmware,
-          // pause the print and ask the user to upgrade the firmware.
+          // pause the print for 30s and ask the user to upgrade the firmware.
           show_upgrade_dialog_if_version_newer(++ strchr_pointer);
       } else {
           SERIAL_ECHOPGM("FIRMWARE_NAME:Prusa-Firmware ");
@@ -7824,9 +7815,9 @@ bool bInhibitFlag;
 #ifdef IR_SENSOR
           bInhibitFlag=(menu_menu==lcd_menu_show_sensors_state); // Support::SensorInfo menu active
 #endif // IR_SENSOR
-          if ((mcode_in_progress != 600) && (eFilamentAction != e_FILAMENT_ACTION_autoLoad) && (!bInhibitFlag)) //M600 not in progress, preHeat @ autoLoad menu not active, Support::ExtruderInfo/SensorInfo menu not active
+          if ((mcode_in_progress != 600) && (eFilamentAction != FilamentAction::AutoLoad) && (!bInhibitFlag)) //M600 not in progress, preHeat @ autoLoad menu not active, Support::ExtruderInfo/SensorInfo menu not active
 		{
-			if (!moves_planned() && !IS_SD_PRINTING && !is_usb_printing && (lcd_commands_type != LCD_COMMAND_V2_CAL) && !wizard_active)
+			if (!moves_planned() && !IS_SD_PRINTING && !is_usb_printing && (lcd_commands_type != LcdCommands::Layer1Cal) && !wizard_active)
 			{
 				if (fsensor_check_autoload())
 				{
@@ -7850,7 +7841,7 @@ if(0)
 						show_preheat_nozzle_warning();
 						lcd_update_enable(true);
 */
-                              eFilamentAction=e_FILAMENT_ACTION_autoLoad;
+                              eFilamentAction=FilamentAction::AutoLoad;
                               bFilamentFirstRun=false;
                               if(target_temperature[0]>=EXTRUDE_MINTEMP)
                               {
@@ -8249,12 +8240,15 @@ static void wait_for_heater(long codenum, uint8_t extruder) {
 
 void check_babystep()
 {
-	int babystep_z;
-	EEPROM_read_B(EEPROM_BABYSTEP_Z, &babystep_z);
+	int babystep_z = eeprom_read_word(reinterpret_cast<uint16_t *>(&(EEPROM_Sheets_base->
+            s[(eeprom_read_byte(&(EEPROM_Sheets_base->active_sheet)))].z_offset)));
+
 	if ((babystep_z < Z_BABYSTEP_MIN) || (babystep_z > Z_BABYSTEP_MAX)) {
 		babystep_z = 0; //if babystep value is out of min max range, set it to 0
 		SERIAL_ECHOLNPGM("Z live adjust out of range. Setting to 0");
-		EEPROM_save_B(EEPROM_BABYSTEP_Z, &babystep_z);
+		eeprom_write_word(reinterpret_cast<uint16_t *>(&(EEPROM_Sheets_base->
+            s[(eeprom_read_byte(&(EEPROM_Sheets_base->active_sheet)))].z_offset)),
+                    babystep_z);
 		lcd_show_fullscreen_message_and_wait_P(PSTR("Z live adjust out of range. Setting to 0. Click to continue."));
 		lcd_update_enable(true);		
 	}	
@@ -8324,7 +8318,7 @@ void bed_check(float x_dimension, float y_dimension, int x_points_num, int y_poi
 	float bed_zero_ref_y = (-0.6f + Y_PROBE_OFFSET_FROM_EXTRUDER);
 
 	float mesh_home_z_search = 4;
-	float measure_z_heigth = 0.2f;
+	float measure_z_height = 0.2f;
 	float row[x_points_num];
 	int ix = 0;
 	int iy = 0;
@@ -8341,7 +8335,7 @@ void bed_check(float x_dimension, float y_dimension, int x_points_num, int y_poi
 
 	unsigned int custom_message_type_old = custom_message_type;
 	unsigned int custom_message_state_old = custom_message_state;
-	custom_message_type = CUSTOM_MSG_TYPE_MESHBL;
+	custom_message_type = CustomMsg::MeshBedLeveling;
 	custom_message_state = (x_points_num * y_points_num) + 10;
 	lcd_update(1);
 
@@ -8359,7 +8353,7 @@ void bed_check(float x_dimension, float y_dimension, int x_points_num, int y_poi
 	}
 	st_synchronize();
 	*/
-		destination[Z_AXIS] = measure_z_heigth;
+		destination[Z_AXIS] = measure_z_height;
 		plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], Z_LIFT_FEEDRATE, active_extruder);
 		for(int8_t i=0; i < NUM_AXIS; i++) {
 			current_position[i] = destination[i];
@@ -8539,7 +8533,7 @@ void bed_analysis(float x_dimension, float y_dimension, int x_points_num, int y_
 	}
 	unsigned int custom_message_type_old = custom_message_type;
 	unsigned int custom_message_state_old = custom_message_state;
-	custom_message_type = CUSTOM_MSG_TYPE_MESHBL;
+	custom_message_type = CustomMsg::MeshBedLeveling;
 	custom_message_state = (x_points_num * y_points_num) + 10;
 	lcd_update(1);
 
@@ -8689,7 +8683,7 @@ void bed_analysis(float x_dimension, float y_dimension, int x_points_num, int y_
 
 void temp_compensation_start() {
 	
-	custom_message_type = CUSTOM_MSG_TYPE_TEMPRE;
+	custom_message_type = CustomMsg::TempCompPreheat;
 	custom_message_state = PINDA_HEAT_T + 1;
 	lcd_update(2);
 	if (degHotend(active_extruder) > EXTRUDE_MINTEMP) {
@@ -8710,7 +8704,7 @@ 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 = CUSTOM_MSG_TYPE_STATUS;
+	custom_message_type = CustomMsg::Status;
 	custom_message_state = 0;
 }
 
@@ -9099,8 +9093,7 @@ ISR(INT4_vect) {
 	EIMSK &= ~(1 << 4); //disable INT4 interrupt to make sure that this code will be executed just once 
 	SERIAL_ECHOLNPGM("INT4");
     //fire normal uvlo only in case where EEPROM_UVLO is 0 or if IS_SD_PRINTING is 1. 
-    //Don't change || to && because in some case the printer can be moving although IS_SD_PRINTING is zero
-     if((IS_SD_PRINTING ) || (!(eeprom_read_byte((uint8_t*)EEPROM_UVLO)))) uvlo_();
+     if(PRINTER_ACTIVE && (!(eeprom_read_byte((uint8_t*)EEPROM_UVLO)))) uvlo_();
      if(eeprom_read_byte((uint8_t*)EEPROM_UVLO)) uvlo_tiny();
 }
 

+ 1 - 1
Firmware/cmdqueue.cpp

@@ -598,7 +598,7 @@ void get_command()
         if (farm_mode)
         {
             prusa_statistics(6);
-            lcd_commands_type = LCD_COMMAND_FARM_MODE_CONFIRM;
+            lcd_commands_type = LcdCommands::FarmModeConfirm;
         }
 
       }

+ 83 - 0
Firmware/eeprom.cpp

@@ -0,0 +1,83 @@
+//! @file
+//! @date Jun 20, 2019
+//! @author Marek Běl
+
+#include "eeprom.h"
+#include "Marlin.h"
+
+#include <avr/eeprom.h>
+#include <stdint.h>
+
+
+#include "language.h"
+
+#if 0
+template <typename T>
+static T eeprom_read(T *address);
+
+template<>
+char eeprom_read<char>(char *address)
+{
+    return eeprom_read_byte(reinterpret_cast<uint8_t*>(address));
+}
+#endif
+
+template <typename T>
+static void eeprom_write(T *address, T value);
+
+template<>
+void eeprom_write<char>(char *addres, char value)
+{
+    eeprom_write_byte(reinterpret_cast<uint8_t*>(addres), static_cast<uint8_t>(value));
+}
+
+
+template <typename T>
+static bool eeprom_is_uninitialized(T *address);
+
+template <>
+bool eeprom_is_uninitialized<char>(char *address)
+{
+    return (0xff == eeprom_read_byte(reinterpret_cast<uint8_t*>(address)));
+}
+
+bool is_sheet_initialized(){
+  return (0xffff != eeprom_read_word(reinterpret_cast<uint16_t*>(&(EEPROM_Sheets_base->
+  s[eeprom_read_byte(&(EEPROM_Sheets_base->active_sheet))].z_offset))));
+}
+
+void eeprom_init()
+{
+    if (eeprom_read_byte((uint8_t*)EEPROM_POWER_COUNT) == 0xff) eeprom_write_byte((uint8_t*)EEPROM_POWER_COUNT, 0);
+    if (eeprom_read_byte((uint8_t*)EEPROM_CRASH_COUNT_X) == 0xff) eeprom_write_byte((uint8_t*)EEPROM_CRASH_COUNT_X, 0);
+    if (eeprom_read_byte((uint8_t*)EEPROM_CRASH_COUNT_Y) == 0xff) eeprom_write_byte((uint8_t*)EEPROM_CRASH_COUNT_Y, 0);
+    if (eeprom_read_byte((uint8_t*)EEPROM_FERROR_COUNT) == 0xff) eeprom_write_byte((uint8_t*)EEPROM_FERROR_COUNT, 0);
+    if (eeprom_read_word((uint16_t*)EEPROM_POWER_COUNT_TOT) == 0xffff) eeprom_write_word((uint16_t*)EEPROM_POWER_COUNT_TOT, 0);
+    if (eeprom_read_word((uint16_t*)EEPROM_CRASH_COUNT_X_TOT) == 0xffff) eeprom_write_word((uint16_t*)EEPROM_CRASH_COUNT_X_TOT, 0);
+    if (eeprom_read_word((uint16_t*)EEPROM_CRASH_COUNT_Y_TOT) == 0xffff) eeprom_write_word((uint16_t*)EEPROM_CRASH_COUNT_Y_TOT, 0);
+    if (eeprom_read_word((uint16_t*)EEPROM_FERROR_COUNT_TOT) == 0xffff) eeprom_write_word((uint16_t*)EEPROM_FERROR_COUNT_TOT, 0);
+
+    if (eeprom_read_word((uint16_t*)EEPROM_MMU_FAIL_TOT) == 0xffff) eeprom_update_word((uint16_t *)EEPROM_MMU_FAIL_TOT, 0);
+    if (eeprom_read_word((uint16_t*)EEPROM_MMU_LOAD_FAIL_TOT) == 0xffff) eeprom_update_word((uint16_t *)EEPROM_MMU_LOAD_FAIL_TOT, 0);
+    if (eeprom_read_byte((uint8_t*)EEPROM_MMU_FAIL) == 0xff) eeprom_update_byte((uint8_t *)EEPROM_MMU_FAIL, 0);
+    if (eeprom_read_byte((uint8_t*)EEPROM_MMU_LOAD_FAIL) == 0xff) eeprom_update_byte((uint8_t *)EEPROM_MMU_LOAD_FAIL, 0);
+    if (eeprom_read_byte(&(EEPROM_Sheets_base->active_sheet)) == 0xff) eeprom_update_byte(&(EEPROM_Sheets_base->active_sheet), 0);
+    for (uint_least8_t i = 0; i < (sizeof(Sheets::s)/sizeof(Sheets::s[0])); ++i)
+    {
+        bool is_uninitialized = true;
+        for (uint_least8_t j = 0; j < (sizeof(Sheet::name)/sizeof(Sheet::name[0])); ++j)
+        {
+            if (!eeprom_is_uninitialized(&(EEPROM_Sheets_base->s[i].name[j]))) is_uninitialized = false;
+        }
+        if(is_uninitialized)
+        {
+            eeprom_write(&(EEPROM_Sheets_base->s[i].name[0]), static_cast<char>(i + '1'));
+            eeprom_write(&(EEPROM_Sheets_base->s[i].name[1]), '\0');
+        }
+    }
+    check_babystep();
+}
+
+
+
+

+ 40 - 22
Firmware/eeprom.h

@@ -1,6 +1,35 @@
 #ifndef EEPROM_H
 #define EEPROM_H
 
+#include <stdint.h>
+
+#ifdef __cplusplus
+void eeprom_init();
+extern bool is_sheet_initialized();
+#endif
+
+
+typedef struct
+{
+    char name[7];     //!< Can be null terminated, doesn't need to be null terminated
+    int16_t z_offset; //!< Z_BABYSTEP_MIN .. Z_BABYSTEP_MAX = Z_BABYSTEP_MIN*2/1000 [mm] .. Z_BABYSTEP_MAX*2/1000 [mm]
+    uint8_t bed_temp; //!< 0 .. 254 [°C]
+    uint8_t pinda_temp; //!< 0 .. 254 [°C]
+} Sheet;
+
+typedef struct
+{
+    Sheet s[3];
+    uint8_t active_sheet;
+} Sheets;
+// sizeof(Sheets). Do not change it unless EEPROM_Sheets_base is last item in EEPROM.
+// Otherwise it would move following items.
+#define EEPROM_SHEETS_SIZEOF 34
+
+#ifdef __cplusplus
+static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEPROM_SHEETS_SIZEOF.");
+#endif
+
 #define EEPROM_EMPTY_VALUE 0xFF
 // The total size of the EEPROM is
 // 4096 for the Atmega2560
@@ -171,31 +200,16 @@
 #define EEPROM_CHECK_VERSION (EEPROM_CHECK_MODEL-1) // uint8
 #define EEPROM_CHECK_GCODE (EEPROM_CHECK_VERSION-1) // uint8
 
+#define EEPROM_SHEETS_BASE (EEPROM_NOZZLE_DIAMETER_uM - EEPROM_SHEETS_SIZEOF) // Sheets
+static Sheets * const EEPROM_Sheets_base = (Sheets*)(EEPROM_SHEETS_BASE);
+
+//This is supposed to point to last item to allow EEPROM overrun check. Please update when adding new items.
+#define EEPROM_LAST_ITEM EEPROM_SHEETS_BASE
 // !!!!!
 // !!!!! this is end of EEPROM section ... all updates MUST BE inserted before this mark !!!!!
 // !!!!!
 
-//TMC2130 configuration
-#define EEPROM_TMC_AXIS_SIZE  //axis configuration block size
-#define EEPROM_TMC_X (EEPROM_TMC + 0 * EEPROM_TMC_AXIS_SIZE) //X axis configuration blok
-#define EEPROM_TMC_Y (EEPROM_TMC + 1 * EEPROM_TMC_AXIS_SIZE) //Y axis
-#define EEPROM_TMC_Z (EEPROM_TMC + 2 * EEPROM_TMC_AXIS_SIZE) //Z axis
-#define EEPROM_TMC_E (EEPROM_TMC + 3 * EEPROM_TMC_AXIS_SIZE) //E axis
-//TMC2130 - X axis
-#define EEPROM_TMC_X_USTEPS_INTPOL   (EEPROM_TMC_X +  0) // 1byte, bit 0..4 USTEPS, bit 7 INTPOL
-#define EEPROM_TMC_X_PWM_AMPL        (EEPROM_TMC_X +  1) // 1byte (0..255)
-#define EEPROM_TMC_X_PWM_GRAD_FREQ   (EEPROM_TMC_X +  2) // 1byte, bit 0..3 GRAD, bit 4..5 FREQ
-#define EEPROM_TMC_X_TCOOLTHRS       (EEPROM_TMC_X +  3) // 2bytes (0..)
-#define EEPROM_TMC_X_SG_THRS         (EEPROM_TMC_X +  5) // 1byte, (-64..+63)
-#define EEPROM_TMC_X_CURRENT_H       (EEPROM_TMC_X +  6) // 1byte, (0..63)
-#define EEPROM_TMC_X_CURRENT_R       (EEPROM_TMC_X +  7) // 1byte, (0..63)
-#define EEPROM_TMC_X_HOME_SG_THRS    (EEPROM_TMC_X +  8) // 1byte, (-64..+63)
-#define EEPROM_TMC_X_HOME_CURRENT_R  (EEPROM_TMC_X +  9) // 1byte, (-64..+63)
-#define EEPROM_TMC_X_HOME_DTCOOLTHRS (EEPROM_TMC_X + 10) // 1byte (-128..+127)
-#define EEPROM_TMC_X_DTCOOLTHRS_LOW  (EEPROM_TMC_X + 11) // 1byte (-128..+127)
-#define EEPROM_TMC_X_DTCOOLTHRS_HIGH (EEPROM_TMC_X + 12) // 1byte (-128..+127)
-#define EEPROM_TMC_X_SG_THRS_LOW     (EEPROM_TMC_X + 13) // 1byte, (-64..+63)
-#define EEPROM_TMC_X_SG_THRS_HIGH    (EEPROM_TMC_X + 14) // 1byte, (-64..+63)
+
 
 // Currently running firmware, each digit stored as uint16_t.
 // The flavor differentiates a dev, alpha, beta, release candidate or a release version.
@@ -209,9 +223,13 @@
 
 #ifdef __cplusplus
 #include "ConfigurationStore.h"
-static M500_conf * const EEPROM_M500_base = reinterpret_cast<M500_conf*>(20); //offset for storing settings using M500
+static_assert(EEPROM_FIRMWARE_VERSION_END < 20, "Firmware version EEPROM address conflicts with EEPROM_M500_base");
+static constexpr M500_conf * const EEPROM_M500_base = reinterpret_cast<M500_conf*>(20); //offset for storing settings using M500
+static_assert(((sizeof(M500_conf) + 20) < EEPROM_LAST_ITEM), "M500_conf address space conflicts with previous items.");
 #endif
 
+#undef EEPROM_SHEETS_BASE
+
 enum
 {
     EEPROM_MMU_CUTTER_ENABLED_enabled = 1,

+ 6 - 6
Firmware/first_lay_cal.cpp

@@ -128,19 +128,19 @@ void lay1cal_before_meander()
 
 //! @brief Count extrude length
 //!
-//! @param layer_heigth layer heigth in mm
+//! @param layer_height layer height in mm
 //! @param extrusion_width extrusion width in mm
 //! @param extrusion_length extrusion length in mm
 //! @return filament length in mm which needs to be extruded to form line
-static constexpr float count_e(float layer_heigth, float extrusion_width, float extrusion_length)
+static constexpr float count_e(float layer_height, float extrusion_width, float extrusion_length)
 {
-    return (extrusion_length * layer_heigth * extrusion_width / (M_PI * pow(1.75, 2) / 4));
+    return (extrusion_length * layer_height * extrusion_width / (M_PI * pow(1.75, 2) / 4));
 }
 
 static const float width = 0.4; //!< line width
 static const float length = 20 - width; //!< line length
-static const float heigth = 0.2; //!< layer height TODO This is wrong, as current Z height is 0.15 mm
-static const float extr = count_e(heigth, width, length); //!< E axis movement needed to print line
+static const float height = 0.2; //!< layer height TODO This is wrong, as current Z height is 0.15 mm
+static const float extr = count_e(height, width, length); //!< E axis movement needed to print line
 
 //! @brief Print meander
 //! @param cmd_buffer character buffer needed to format gcodes
@@ -199,7 +199,7 @@ void lay1cal_meander(char *cmd_buffer)
 //! @param i iteration
 void lay1cal_square(char *cmd_buffer, uint8_t i)
 {
-    const float extr_short_segment = count_e(heigth, width, width);
+    const float extr_short_segment = count_e(height, width, width);
 
     static const char fmt1[] PROGMEM = "G1 X%d Y%-.2f E%-.3f";
     static const char fmt2[] PROGMEM = "G1 Y%-.2f E%-.3f";

+ 109 - 0
Firmware/heatbed_pwm.cpp

@@ -0,0 +1,109 @@
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include "io_atmega2560.h"
+
+// All this is about silencing the heat bed, as it behaves like a loudspeaker.
+// Basically, we want the PWM heating switched at 30Hz (or so) which is a well ballanced
+// frequency for both power supply units (i.e. both PSUs are reasonably silent).
+// The only trouble is the rising or falling edge of bed heating - that creates an audible click.
+// This audible click may be suppressed by making the rising or falling edge NOT sharp.
+// Of course, making non-sharp edges in digital technology is not easy, but there is a solution.
+// It is possible to do a fast PWM sequence with duty starting from 0 to 255.
+// Doing this at higher frequency than the bed "loudspeaker" can handle makes the click barely audible.
+// Technically:
+// timer0 is set to fast PWM mode at 62.5kHz (timer0 is linked to the bed heating pin) (zero prescaler)
+// To keep the bed switching at 30Hz - we don't want the PWM running at 62kHz all the time 
+// since it would burn the heatbed's MOSFET:
+// 16MHz/256 levels of PWM duty gives us 62.5kHz
+// 62.5kHz/256 gives ~244Hz, that is still too fast - 244/8 gives ~30Hz, that's what we need
+// So the automaton runs atop of inner 8 (or 16) cycles.
+// The finite automaton is running in the ISR(TIMER0_OVF_vect)
+
+///! Definition off finite automaton states
+enum class States : uint8_t {
+  ZERO = 0,
+  RISE = 1,
+  ONE = 2,
+  FALL = 3
+};
+
+///! State table for the inner part of the finite automaton
+///! Basically it specifies what shall happen if the outer automaton is requesting setting the heat pin to 0 (OFF) or 1 (ON)
+///! ZERO: steady 0 (OFF), no change for the whole period
+///! RISE: 8 (16) fast PWM cycles with increasing duty up to steady ON
+///! ONE:  steady 1 (ON), no change for the whole period 
+///! FALL: 8 (16) fast PWM cycles with decreasing duty down to steady OFF
+///! @@TODO move it into progmem
+static States stateTable[4*2] = {
+// off             on
+States::ZERO,      States::RISE, // ZERO
+States::FALL,      States::ONE,  // RISE
+States::FALL,      States::ONE,  // ONE
+States::ZERO,      States::RISE  // FALL
+};
+
+///! Inner states of the finite automaton
+static States state = States::ZERO;
+
+///! Inner and outer PWM counters
+static uint8_t outer = 0;
+static uint8_t inner = 0;
+static uint8_t pwm = 0;
+
+///! the slow PWM duty for the next 30Hz cycle
+///! Set in the whole firmware at various places
+extern unsigned char soft_pwm_bed;
+
+/// Fine tuning of automaton cycles
+#if 1
+static const uint8_t innerMax = 16;
+static const uint8_t innerShift = 4;
+#else
+static const uint8_t innerMax = 8;
+static const uint8_t innerShift = 5;
+#endif
+
+ISR(TIMER0_OVF_vect)          // timer compare interrupt service routine
+{
+  if( inner ){
+    switch(state){
+    case States::ZERO:
+      OCR0B = 255;
+	  // Commenting the following code saves 6B, but it is left here for reference
+	  // It is not necessary to set it all over again, because we can only get into the ZERO state from the FALL state (which sets this register)
+//       TCCR0A |= (1 << COM0B1) | (1 << COM0B0);
+      break;
+    case States::RISE:
+      OCR0B = (innerMax - inner) << innerShift;
+//       TCCR0A |= (1 << COM0B1); // this bit is always 1
+      TCCR0A &= ~(1 << COM0B0);
+      break;  
+    case States::ONE:
+      OCR0B = 255;
+	  // again - may be skipped, because we get into the ONE state only from RISE (which sets this register)
+//       TCCR0A |= (1 << COM0B1);
+       TCCR0A &= ~(1 << COM0B0);
+      break;
+    case States::FALL:
+      OCR0B = (innerMax - inner) << innerShift; // this is the same as in RISE, because now we are setting the zero part of duty due to inverting mode
+      // must switch to inverting mode already here, because it takes a whole PWM cycle and it would make a "1" at the end of this pwm cycle
+	  TCCR0A |= /*(1 << COM0B1) |*/ (1 << COM0B0); 
+      break;
+    }
+    --inner;
+  } else {
+    if( ! outer ){ // at the end of 30Hz PWM period
+      // synchro is not needed (almost), soft_pwm_bed is just 1 byte, 1-byte write instruction is atomic
+      pwm = soft_pwm_bed << 1;
+    }
+	if( pwm > outer || pwm >= 254 ){
+      // soft_pwm_bed has a range of 0-127, that why a <<1 is done here. That also means that we may get only up to 254 which we want to be full-time 1 (ON)
+      state = stateTable[ uint8_t(state) * 2 + 1 ];
+    } else {
+      // switch OFF
+      state = stateTable[ uint8_t(state) * 2 + 0 ];
+    }
+    ++outer;
+    inner = innerMax;
+  }
+}

+ 42 - 3
Firmware/menu.cpp

@@ -168,16 +168,40 @@ int menu_draw_item_printf_P(char type_char, const char* format, ...)
 }
 */
 
+static char menu_selection_mark(){
+	return (lcd_encoder == menu_item)?'>':' ';
+}
+
 static void menu_draw_item_puts_P(char type_char, const char* str)
 {
     lcd_set_cursor(0, menu_row);
-    lcd_printf_P(PSTR("%c%-18.18S%c"), (lcd_encoder == menu_item)?'>':' ', str, type_char);
+    lcd_printf_P(PSTR("%c%-18.18S%c"), menu_selection_mark(), str, type_char);
+}
+
+//! @brief Format sheet name
+//!
+//! @param[in] sheet_E Sheet in EEPROM
+//! @param[out] buffer for formatted output
+void menu_format_sheet_E(const Sheet &sheet_E, SheetFormatBuffer &buffer)
+{
+    uint_least8_t index = sprintf_P(buffer.c, PSTR("%.10S "), _T(MSG_SHEET));
+    eeprom_read_block(&(buffer.c[index]), sheet_E.name, 7);
+    //index += 7;
+    buffer.c[index + 7] = '\0';
+}
+
+static void menu_draw_item_puts_E(char type_char, const Sheet &sheet)
+{
+    lcd_set_cursor(0, menu_row);
+    SheetFormatBuffer buffer;
+    menu_format_sheet_E(sheet, buffer);
+    lcd_printf_P(PSTR("%c%-18.18s%c"), menu_selection_mark(), buffer.c, type_char);
 }
 
 static void menu_draw_item_puts_P(char type_char, const char* str, char num)
 {
     lcd_set_cursor(0, menu_row);
-    lcd_printf_P(PSTR("%c%-.16S "), (lcd_encoder == menu_item)?'>':' ', str);
+    lcd_printf_P(PSTR("%c%-.16S "), menu_selection_mark(), str);
     lcd_putc(num);
     lcd_set_cursor(19, menu_row);
     lcd_putc(type_char);
@@ -224,6 +248,21 @@ uint8_t menu_item_submenu_P(const char* str, menu_func_t submenu)
 	return 0;
 }
 
+uint8_t menu_item_submenu_E(const Sheet &sheet, menu_func_t submenu)
+{
+    if (menu_item == menu_line)
+    {
+        if (lcd_draw_update) menu_draw_item_puts_E(LCD_STR_ARROW_RIGHT[0], sheet);
+        if (menu_clicked && (lcd_encoder == menu_item))
+        {
+            menu_submenu(submenu);
+            return menu_item_ret();
+        }
+    }
+    menu_item++;
+    return 0;
+}
+
 uint8_t menu_item_back_P(const char* str)
 {
 	if (menu_item == menu_line)
@@ -399,7 +438,7 @@ uint8_t menu_item_edit_P(const char* str, T pval, int16_t min_val, int16_t max_v
 		if (lcd_draw_update) 
 		{
 			lcd_set_cursor(0, menu_row);
-			menu_draw_P<T>((lcd_encoder == menu_item)?'>':' ', str, *pval);
+			menu_draw_P<T>(menu_selection_mark(), str, *pval);
 		}
 		if (menu_clicked && (lcd_encoder == menu_item))
 		{

+ 12 - 0
Firmware/menu.h

@@ -3,6 +3,7 @@
 #define _MENU_H
 
 #include <inttypes.h>
+#include "eeprom.h"
 
 #define MENU_DATA_SIZE      32
 
@@ -99,6 +100,10 @@ extern uint8_t menu_item_text_P(const char* str);
 #define MENU_ITEM_SUBMENU_P(str, submenu) do { if (menu_item_submenu_P(str, submenu)) return; } while (0)
 extern uint8_t menu_item_submenu_P(const char* str, menu_func_t submenu);
 
+#define MENU_ITEM_SUBMENU_E(sheet, submenu) do { if (menu_item_submenu_E(sheet, submenu)) return; } while (0)
+extern uint8_t menu_item_submenu_E(const Sheet &sheet, menu_func_t submenu);
+
+
 #define MENU_ITEM_BACK_P(str) do { if (menu_item_back_P(str)) return; } while (0)
 extern uint8_t menu_item_back_P(const char* str);
 
@@ -125,6 +130,13 @@ extern void menu_draw_float31(const char* str, float val);
 
 extern void menu_draw_float13(const char* str, float val);
 
+struct SheetFormatBuffer
+{
+    char c[19];
+};
+
+extern void menu_format_sheet_E(const Sheet &sheet_E, SheetFormatBuffer &buffer);
+
 
 #define MENU_ITEM_EDIT_int3_P(str, pval, minval, maxval) do { if (menu_item_edit_P(str, pval, minval, maxval)) return; } while (0)
 //#define MENU_ITEM_EDIT_int3_P(str, pval, minval, maxval) MENU_ITEM_EDIT(int3, str, pval, minval, maxval)

+ 3 - 2
Firmware/mesh_bed_calibration.cpp

@@ -3031,7 +3031,8 @@ void babystep_load()
         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);
+        babystepLoadZ = eeprom_read_word(reinterpret_cast<uint16_t *>(&(EEPROM_Sheets_base->
+                    s[(eeprom_read_byte(&(EEPROM_Sheets_base->active_sheet)))].z_offset)));
                             
     #if 0
         SERIAL_ECHO("Z baby step: ");
@@ -3186,4 +3187,4 @@ void mbl_interpolation(uint8_t meas_points) {
 			}
 		}
 	}
-}
+}

+ 3 - 1
Firmware/messages.c

@@ -10,7 +10,7 @@
 //internationalized messages
 const char MSG_AUTO_HOME[] PROGMEM_I1 = ISTR("Auto home"); ////
 const char MSG_AUTO_MODE_ON[] PROGMEM_I1 = ISTR("Mode [auto power]"); ////
-const char MSG_BABYSTEP_Z[] PROGMEM_I1 = ISTR("Live adjust Z"); ////
+const char MSG_BABYSTEP_Z[] PROGMEM_I1 = ISTR("Live adjust Z"); //// c=18
 const char MSG_BABYSTEP_Z_NOT_SET[] PROGMEM_I1 = ISTR("Distance between tip of the nozzle and the bed surface has not been set yet. Please follow the manual, chapter First steps, section First layer calibration."); ////c=20 r=12
 const char MSG_BED[] PROGMEM_I1 = ISTR("Bed"); ////
 const char MSG_BED_DONE[] PROGMEM_I1 = ISTR("Bed done"); ////
@@ -55,6 +55,7 @@ const char MSG_CUT_FILAMENT[] PROGMEM_I1 = ISTR("Cut filament"); //// Number 1 t
 const char MSG_M117_V2_CALIBRATION[] PROGMEM_I1 = ISTR("M117 First layer cal."); ////c=25 r=1
 const char MSG_MAIN[] PROGMEM_I1 = ISTR("Main"); ////
 const char MSG_BACK[] PROGMEM_I1 = ISTR("Back"); ////
+const char MSG_SHEET[] PROGMEM_I1 = ISTR("Sheet"); ////c=10
 const char MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE1[] PROGMEM_I1 = ISTR("Measuring reference height of calibration point"); ////c=60
 const char MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2[] PROGMEM_I1 = ISTR(" of 9"); ////c=14
 const char MSG_MENU_CALIBRATION[] PROGMEM_I1 = ISTR("Calibration"); ////
@@ -100,6 +101,7 @@ const char MSG_WIZARD_DONE[] PROGMEM_I1 = ISTR("All is done. Happy printing!");
 const char MSG_WIZARD_HEATING[] PROGMEM_I1 = ISTR("Preheating nozzle. Please wait."); ////c=20 r=3
 const char MSG_WIZARD_QUIT[] PROGMEM_I1 = ISTR("You can always resume the Wizard from Calibration -> Wizard."); ////c=20 r=8
 const char MSG_YES[] PROGMEM_I1 = ISTR("Yes"); ////
+const char MSG_V2_CALIBRATION[] PROGMEM_I1 = ISTR("First layer cal."); ////c=17 r=1
 const char WELCOME_MSG[] PROGMEM_I1 = ISTR(CUSTOM_MENDEL_NAME " OK."); ////c=20
 //not internationalized messages
 const char MSG_SD_WORKDIR_FAIL[] PROGMEM_N1 = "workDir open failed"; ////

+ 2 - 0
Firmware/messages.h

@@ -54,6 +54,7 @@ extern const char MSG_LOADING_FILAMENT[];
 extern const char MSG_M117_V2_CALIBRATION[];
 extern const char MSG_MAIN[];
 extern const char MSG_BACK[];
+extern const char MSG_SHEET[];
 extern const char MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE1[];
 extern const char MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2[];
 extern const char MSG_MENU_CALIBRATION[];
@@ -100,6 +101,7 @@ extern const char MSG_WIZARD_DONE[];
 extern const char MSG_WIZARD_HEATING[];
 extern const char MSG_WIZARD_QUIT[];
 extern const char MSG_YES[];
+extern const char MSG_V2_CALIBRATION[];
 extern const char WELCOME_MSG[];
 //not internationalized messages
 extern const char MSG_BROWNOUT_RESET[];

+ 76 - 25
Firmware/mmu.cpp

@@ -83,9 +83,11 @@ uint16_t mmu_power_failures = 0;
 
 
 #ifdef MMU_DEBUG
+static const auto DEBUG_PUTCHAR = putchar;
 static const auto DEBUG_PUTS_P = puts_P;
 static const auto DEBUG_PRINTF_P = printf_P;
 #else //MMU_DEBUG
+#define DEBUG_PUTCHAR(c)
 #define DEBUG_PUTS_P(str)
 #define DEBUG_PRINTF_P( __fmt, ... )
 #endif //MMU_DEBUG
@@ -1081,7 +1083,7 @@ if(0)
      extr_unload();
      }
 else	{
-     eFilamentAction=e_FILAMENT_ACTION_mmuUnLoad;
+     eFilamentAction=FilamentAction::MmuUnLoad;
      bFilamentFirstRun=false;
      if(target_temperature[0]>=EXTRUDE_MINTEMP)
           {
@@ -1377,13 +1379,13 @@ void lcd_mmu_load_to_nozzle(uint8_t filament_nr)
         mmu_load_to_nozzle();
         load_filament_final_feed();
         st_synchronize();
-        custom_message_type = CUSTOM_MSG_TYPE_F_LOAD;
+        custom_message_type = CustomMsg::FilamentLoading;
         lcd_setstatuspgm(_T(MSG_LOADING_FILAMENT));
         lcd_return_to_status();
         lcd_update_enable(true);
         lcd_load_filament_color_check();
         lcd_setstatuspgm(_T(WELCOME_MSG));
-        custom_message_type = CUSTOM_MSG_TYPE_STATUS;
+        custom_message_type = CustomMsg::Status;
     }
     else
     {
@@ -1452,26 +1454,69 @@ bFilamentAction=false;                            // NOT in "mmu_fil_eject_menu(
 	}
 }
 
+//! @brief Fits filament tip into heatbreak?
+//!
+//! If PTFE tube is jammed, this causes filament to be unloaded and no longer
+//! being detected by the pulley IR sensor.
+//! @retval true Fits
+//! @retval false Doesn't fit
+static bool can_load()
+{
+    current_position[E_AXIS] += 60;
+    plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS],
+            current_position[E_AXIS], MMU_LOAD_FEEDRATE, active_extruder);
+    current_position[E_AXIS] -= 52;
+    plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS],
+            current_position[E_AXIS], MMU_LOAD_FEEDRATE, active_extruder);
+    st_synchronize();
+
+    uint_least8_t filament_detected_count = 0;
+    const float e_increment = 0.2;
+    const uint_least8_t steps = 6.0 / e_increment;
+    DEBUG_PUTS_P(PSTR("MMU can_load:"));
+    for(uint_least8_t i = 0; i < steps; ++i)
+    {
+        current_position[E_AXIS] -= e_increment;
+        plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS],
+                current_position[E_AXIS], MMU_LOAD_FEEDRATE, active_extruder);
+        st_synchronize();
+        if(0 == PIN_GET(IR_SENSOR_PIN))
+        {
+            ++filament_detected_count;
+            DEBUG_PUTCHAR('O');
+        }
+        else
+        {
+            DEBUG_PUTCHAR('o');
+        }
+    }
+    if (filament_detected_count > steps - 4)
+    {
+        DEBUG_PUTS_P(PSTR(" succeeded."));
+        return true;
+    }
+    else
+    {
+        DEBUG_PUTS_P(PSTR(" failed."));
+        return false;
+    }
+}
+
 //! @brief load more
 //!
 //! Try to feed more filament from MMU if it is not detected by filament sensor.
-//! Move filament back and forth to nozzle in order to detect jam.
-//! If PTFE tube is jammed, this cause filament to be unloaded and no longer
-//! detected by pulley IR sensor in next step.
-static void load_more()
+//! @retval true Success, filament detected by IR sensor
+//! @retval false Failed, filament not detected by IR sensor after maximum number of attempts
+static bool load_more()
 {
     for (uint8_t i = 0; i < MMU_IDLER_SENSOR_ATTEMPTS_NR; i++)
     {
-        if (PIN_GET(IR_SENSOR_PIN) == 0) break;
+        if (PIN_GET(IR_SENSOR_PIN) == 0) return true;
         DEBUG_PRINTF_P(PSTR("Additional load attempt nr. %d\n"), i);
         mmu_command(MmuCmd::C0);
         manage_response(true, true, MMU_LOAD_MOVE);
     }
-    current_position[E_AXIS] += 60;
-    plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], MMU_LOAD_FEEDRATE, active_extruder);
-    current_position[E_AXIS] -= 58;
-    plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], MMU_LOAD_FEEDRATE, active_extruder);
-    st_synchronize();
+    return false;
 }
 
 static void increment_load_fail()
@@ -1512,24 +1557,28 @@ void mmu_continue_loading(bool blocking)
 	    return;
 	}
 
-    load_more();
+    bool success = load_more();
+    if (success) success = can_load();
 
     enum class Ls : uint_least8_t
     {
-        enter,
-        retry,
-        unload,
+        Enter,
+        Retry,
+        Unload,
     };
-    Ls state = Ls::enter;
+    Ls state = Ls::Enter;
+
+    const uint_least8_t max_retry = 2;
+    uint_least8_t retry = 0;
 
-    while (PIN_GET(IR_SENSOR_PIN) != 0)
+    while (!success)
     {
         switch (state)
         {
-        case Ls::enter:
+        case Ls::Enter:
             increment_load_fail();
             // no break
-        case Ls::retry:
+        case Ls::Retry:
 #ifdef MMU_HAS_CUTTER
             if (1 == eeprom_read_byte((uint8_t*)EEPROM_MMU_CUTTER_ENABLED))
             {
@@ -1539,10 +1588,12 @@ void mmu_continue_loading(bool blocking)
 #endif //MMU_HAS_CUTTER
             mmu_command(MmuCmd::T0 + tmp_extruder);
             manage_response(true, true, MMU_TCODE_MOVE);
-            load_more();
-            state = Ls::unload;
+            success = load_more();
+            if (success) success = can_load();
+            ++retry; // overflow not handled, as it is not dangerous.
+            if (retry >= max_retry) state = Ls::Unload;
             break;
-        case Ls::unload:
+        case Ls::Unload:
             stop_and_save_print_to_ram(0, 0);
 
             //lift z
@@ -1567,7 +1618,7 @@ void mmu_continue_loading(bool blocking)
             {
                 marlin_wait_for_click();
                 restore_print_from_ram_and_continue(0);
-                state = Ls::retry;
+                state = Ls::Retry;
             }
             else
             {

+ 6 - 3
Firmware/system_timer.h

@@ -4,7 +4,7 @@
 #define FIRMWARE_SYSTEM_TIMER_H_
 
 #include "Arduino.h"
-//#define SYSTEM_TIMER_2
+#define SYSTEM_TIMER_2
 
 #ifdef SYSTEM_TIMER_2
 #include "timer02.h"
@@ -13,12 +13,15 @@
 #define _delay delay2
 #define _tone tone2
 #define _noTone noTone2
+
+#define timer02_set_pwm0(pwm0)
+
 #else //SYSTEM_TIMER_2
 #define _millis millis
 #define _micros micros
 #define _delay delay
-#define _tone tone
-#define _noTone noTone
+#define _tone(x, y) /*tone*/
+#define _noTone(x) /*noTone*/
 #define timer02_set_pwm0(pwm0)
 #endif //SYSTEM_TIMER_2
 

+ 39 - 34
Firmware/temperature.cpp

@@ -44,8 +44,6 @@
 #include "Timer.h"
 #include "Configuration_prusa.h"
 
-
-
 //===========================================================================
 //=============================public variables============================
 //===========================================================================
@@ -1130,18 +1128,9 @@ void tp_init()
 
   adc_init();
 
-#ifdef SYSTEM_TIMER_2
-  timer02_init();
+  timer0_init();
   OCR2B = 128;
   TIMSK2 |= (1<<OCIE2B);  
-#else //SYSTEM_TIMER_2
-  // Use timer0 for temperature measurement
-  // Interleave temperature interrupt with millies interrupt
-  OCR0B = 128;
-  TIMSK0 |= (1<<OCIE0B);  
-#endif //SYSTEM_TIMER_2
-
-
   
   // Wait for temperature measurement to settle
   _delay(250);
@@ -1472,8 +1461,8 @@ void disable_heater()
     target_temperature_bed=0;
     soft_pwm_bed=0;
 	timer02_set_pwm0(soft_pwm_bed << 1);
-    #if defined(HEATER_BED_PIN) && HEATER_BED_PIN > -1  
-      WRITE(HEATER_BED_PIN,LOW);
+    #if defined(HEATER_BED_PIN) && HEATER_BED_PIN > -1
+      //WRITE(HEATER_BED_PIN,LOW);
     #endif
   #endif 
 }
@@ -1544,7 +1533,7 @@ void min_temp_error(uint8_t e) {
 
 void bed_max_temp_error(void) {
 #if HEATER_BED_PIN > -1
-  WRITE(HEATER_BED_PIN, 0);
+  //WRITE(HEATER_BED_PIN, 0);
 #endif
   if(IsStopped() == false) {
     SERIAL_ERROR_START;
@@ -1563,7 +1552,7 @@ void bed_min_temp_error(void) {
 #endif
 //if (current_temperature_ambient < MINTEMP_MINAMBIENT) return;
 #if HEATER_BED_PIN > -1
-    WRITE(HEATER_BED_PIN, 0);
+    //WRITE(HEATER_BED_PIN, 0);
 #endif
 	static const char err[] PROGMEM = "Err: MINTEMP BED";
     if(IsStopped() == false) {
@@ -1660,7 +1649,6 @@ void adc_ready(void) //callback from adc when sampling finished
 
 } // extern "C"
 
-
 // Timer2 (originaly timer0) is shared with millies
 #ifdef SYSTEM_TIMER_2
 ISR(TIMER2_COMPB_vect)
@@ -1676,8 +1664,8 @@ ISR(TIMER0_COMPB_vect)
 	if (!temp_meas_ready) adc_cycle();
 	lcd_buttons_update();
 
-  static unsigned char pwm_count = (1 << SOFT_PWM_SCALE);
-  static unsigned char soft_pwm_0;
+  static uint8_t pwm_count = (1 << SOFT_PWM_SCALE);
+  static uint8_t soft_pwm_0;
 #ifdef SLOW_PWM_HEATERS
   static unsigned char slow_pwm_count = 0;
   static unsigned char state_heater_0 = 0;
@@ -1698,7 +1686,7 @@ ISR(TIMER0_COMPB_vect)
 #endif 
 #endif
 #if HEATER_BED_PIN > -1
-  static unsigned char soft_pwm_b;
+  // @@DR static unsigned char soft_pwm_b;
 #ifdef SLOW_PWM_HEATERS
   static unsigned char state_heater_b = 0;
   static unsigned char state_timer_heater_b = 0;
@@ -1733,14 +1721,25 @@ ISR(TIMER0_COMPB_vect)
 #endif
   }
 #if defined(HEATER_BED_PIN) && HEATER_BED_PIN > -1
+  
+#if 0  // @@DR vypnuto pro hw pwm bedu
+  // tuhle prasarnu bude potreba poustet ve stanovenych intervalech, jinak nemam moc sanci zareagovat
+  // teoreticky by se tato cast uz vubec nemusela poustet
   if ((pwm_count & ((1 << HEATER_BED_SOFT_PWM_BITS) - 1)) == 0)
   {
     soft_pwm_b = soft_pwm_bed >> (7 - HEATER_BED_SOFT_PWM_BITS);
-#ifndef SYSTEM_TIMER_2
-	if(soft_pwm_b > 0) WRITE(HEATER_BED_PIN,1); else WRITE(HEATER_BED_PIN,0);
-#endif //SYSTEM_TIMER_2
+#  ifndef SYSTEM_TIMER_2
+	// tady budu krokovat pomalou frekvenci na automatu - tohle je rizeni spinani a rozepinani
+	// jako ridici frekvenci mam 2khz, jako vystupni frekvenci mam 30hz
+	// 2kHz jsou ovsem ve slysitelnem pasmu, mozna bude potreba jit s frekvenci nahoru (a tomu taky prizpusobit ostatni veci)
+	// Teoreticky bych mohl stahnout OCR0B citac na 6, cimz bych se dostal nekam ke 40khz a tady potom honit PWM rychleji nebo i pomaleji
+	// to nicemu nevadi. Soft PWM scale by se 20x zvetsilo (no dobre, 16x), cimz by se to posunulo k puvodnimu 30Hz PWM
+	//if(soft_pwm_b > 0) WRITE(HEATER_BED_PIN,1); else WRITE(HEATER_BED_PIN,0);
+#  endif //SYSTEM_TIMER_2
   }
 #endif
+#endif
+  
 #ifdef FAN_SOFT_PWM
   if ((pwm_count & ((1 << FAN_SOFT_PWM_BITS) - 1)) == 0)
   {
@@ -1762,8 +1761,14 @@ ISR(TIMER0_COMPB_vect)
 #if EXTRUDERS > 2
   if(soft_pwm_2 < pwm_count) WRITE(HEATER_2_PIN,0);
 #endif
+
+#if 0 // @@DR  
 #if defined(HEATER_BED_PIN) && HEATER_BED_PIN > -1
-  if (soft_pwm_b < (pwm_count & ((1 << HEATER_BED_SOFT_PWM_BITS) - 1))) WRITE(HEATER_BED_PIN,0);
+  if (soft_pwm_b < (pwm_count & ((1 << HEATER_BED_SOFT_PWM_BITS) - 1))){
+	  //WRITE(HEATER_BED_PIN,0);
+  }
+  //WRITE(HEATER_BED_PIN, pwm_count & 1 );
+#endif
 #endif
 #ifdef FAN_SOFT_PWM
   if (soft_pwm_fan < (pwm_count & ((1 << FAN_SOFT_PWM_BITS) - 1))) WRITE(FAN_PIN,0);
@@ -2053,8 +2058,8 @@ void check_max_temp()
 struct alert_automaton_mintemp {
 private:
 	enum { ALERT_AUTOMATON_SPEED_DIV = 5 };
-	enum class States : uint8_t { INIT = 0, TEMP_ABOVE_MINTEMP, SHOW_PLEASE_RESTART, SHOW_MINTEMP };
-	States state = States::INIT;
+	enum class States : uint8_t { Init = 0, TempAboveMintemp, ShowPleaseRestart, ShowMintemp };
+	States state = States::Init;
 	uint8_t repeat = ALERT_AUTOMATON_SPEED_DIV;
 
 	void substep(States next_state){
@@ -2073,26 +2078,26 @@ public:
 		static const char m2[] PROGMEM = "MINTEMP fixed";
 		static const char m1[] PROGMEM = "Please restart";
 		switch(state){
-		case States::INIT: // initial state - check hysteresis
+		case States::Init: // initial state - check hysteresis
 			if( current_temp > mintemp ){
-				state = States::TEMP_ABOVE_MINTEMP;
+				state = States::TempAboveMintemp;
 			}
 			// otherwise keep the Err MINTEMP alert message on the display,
 			// i.e. do not transfer to state 1
 			break;
-		case States::TEMP_ABOVE_MINTEMP: // the temperature has risen above the hysteresis check
+		case States::TempAboveMintemp: // the temperature has risen above the hysteresis check
 			lcd_setalertstatuspgm(m2);
-			substep(States::SHOW_MINTEMP);
+			substep(States::ShowMintemp);
 			last_alert_sent_to_lcd = LCDALERT_MINTEMPFIXED;
 			break;
-		case States::SHOW_PLEASE_RESTART: // displaying "Please restart"
+		case States::ShowPleaseRestart: // displaying "Please restart"
 			lcd_updatestatuspgm(m1);
-			substep(States::SHOW_MINTEMP);
+			substep(States::ShowMintemp);
 			last_alert_sent_to_lcd = LCDALERT_PLEASERESTART;
 			break;
-		case States::SHOW_MINTEMP: // displaying "MINTEMP fixed"
+		case States::ShowMintemp: // displaying "MINTEMP fixed"
 			lcd_updatestatuspgm(m2);
-			substep(States::SHOW_PLEASE_RESTART);
+			substep(States::ShowPleaseRestart);
 			last_alert_sent_to_lcd = LCDALERT_MINTEMPFIXED;
 			break;
 		}

+ 15 - 41
Firmware/timer02.c

@@ -9,48 +9,27 @@
 
 #include <avr/io.h>
 #include <avr/interrupt.h>
-#include "Arduino.h"
 #include "io_atmega2560.h"
 
 #define BEEPER              84
 
-uint8_t timer02_pwm0 = 0;
-
-void timer02_set_pwm0(uint8_t pwm0)
-{
-	if (timer02_pwm0 == pwm0) return;
-	if (pwm0)
-	{
-		TCCR0A |= (2 << COM0B0);
-		OCR0B = pwm0 - 1;
-	}
-	else
-	{
-		TCCR0A &= ~(2 << COM0B0);
-		OCR0B = 0;
-	}
-	timer02_pwm0 = pwm0;
-}
-
-void timer02_init(void)
+void timer0_init(void)
 {
 	//save sreg
 	uint8_t _sreg = SREG;
 	//disable interrupts for sure
 	cli();
-	//mask timer0 interrupts - disable all
-	TIMSK0 &= ~(1<<TOIE0);
-	TIMSK0 &= ~(1<<OCIE0A);
-	TIMSK0 &= ~(1<<OCIE0B);
-	//setup timer0
-	TCCR0A = 0x00; //COM_A-B=00, WGM_0-1=00
-	TCCR0B = (1 << CS00); //WGM_2=0, CS_0-2=011
-	//switch timer0 to fast pwm mode
-	TCCR0A |= (3 << WGM00); //WGM_0-1=11
-	//set OCR0B register to zero
-	OCR0B = 0;
-	//disable OCR0B output (will be enabled in timer02_set_pwm0)
-	TCCR0A &= ~(2 << COM0B0);
+
+	TCNT0  = 0;
+	// Fast PWM duty (0-255). 
+	// Due to invert mode (following rows) the duty is set to 255, which means zero all the time (bed not heating)
+	OCR0B = 255;
+	// Set fast PWM mode and inverting mode.
+	TCCR0A = (1 << WGM01) | (1 << WGM00) | (1 << COM0B1) | (1 << COM0B0);  
+	TCCR0B = (1 << CS00);    // no clock prescaling
+	TIMSK0 |= (1 << TOIE0);  // enable timer overflow interrupt
+	
+	// Everything, that used to be on timer0 was moved to timer2 (delay, beeping, millis etc.)
 	//setup timer2
 	TCCR2A = 0x00; //COM_A-B=00, WGM_0-1=00
 	TCCR2B = (4 << CS20); //WGM_2=0, CS_0-2=011
@@ -66,11 +45,9 @@ void timer02_init(void)
 }
 
 
-//following code is OVF handler for timer 2
-//it is copy-paste from wiring.c and modified for timer2
-//variables timer0_overflow_count and timer0_millis are declared in wiring.c
-
-
+// The following code is OVF handler for timer 2
+// it was copy-pasted from wiring.c and modified for timer2
+// variables timer0_overflow_count and timer0_millis are declared in wiring.c
 
 // the prescaler is set so that timer0 ticks every 64 clock cycles, and the
 // the overflow handler is called every 256 ticks.
@@ -85,9 +62,6 @@ void timer02_init(void)
 #define FRACT_INC ((MICROSECONDS_PER_TIMER0_OVERFLOW % 1000) >> 3)
 #define FRACT_MAX (1000 >> 3)
 
-//extern volatile unsigned long timer0_overflow_count;
-//extern volatile unsigned long timer0_millis;
-//unsigned char timer0_fract = 0;
 volatile unsigned long timer2_overflow_count;
 volatile unsigned long timer2_millis;
 unsigned char timer2_fract = 0;

+ 8 - 7
Firmware/timer02.h

@@ -11,24 +11,25 @@
 extern "C" {
 #endif //defined(__cplusplus)
 
+///! Initializes TIMER0 for fast PWM mode-driven bed heating
+extern void timer0_init(void);
 
-extern uint8_t timer02_pwm0;
-
-extern void timer02_set_pwm0(uint8_t pwm0);
-
-extern void timer02_init(void);
-
+///! Reimplemented original millis() using timer2
 extern unsigned long millis2(void);
 
+///! Reimplemented original micros() using timer2
 extern unsigned long micros2(void);
 
+///! Reimplemented original delay() using timer2
 extern void delay2(unsigned long ms);
 
+///! Reimplemented original tone() using timer2
+///! Does not perform any PWM tone generation, it just sets the beeper pin to 1
 extern void tone2(uint8_t _pin, unsigned int frequency/*, unsigned long duration*/);
 
+///! Turn off beeping - set beeper pin to 0
 extern void noTone2(uint8_t _pin);
 
-
 #if defined(__cplusplus)
 }
 #endif //defined(__cplusplus)

+ 380 - 334
Firmware/ultralcd.cpp

@@ -74,10 +74,10 @@ extern void crashdet_disable();
 bool presort_flag = false;
 #endif
 
-uint8_t lcd_commands_type = LCD_COMMAND_IDLE;
+LcdCommands lcd_commands_type = LcdCommands::Idle;
 static uint8_t lcd_commands_step = 0;
 
-unsigned int custom_message_type = CUSTOM_MSG_TYPE_STATUS;
+CustomMsg custom_message_type = CustomMsg::Status;
 unsigned int custom_message_state = 0;
 
 
@@ -85,7 +85,7 @@ bool isPrintPaused = false;
 uint8_t farm_mode = 0;
 int farm_no = 0;
 int farm_timer = 8;
-int farm_status = 0;
+uint8_t farm_status = 0;
 bool printer_connected = true;
 
 unsigned long display_time; //just timer for showing pid finished message on lcd;
@@ -167,42 +167,42 @@ static bool lcd_selfcheck_pulleys(int axis);
 #endif //TMC2130
 
 static bool lcd_selfcheck_check_heater(bool _isbed);
-enum class testScreen : uint_least8_t
-{
-    extruderFan,
-    printFan,
-    fansOk,
-    endStops,
-    axisX,
-    axisY,
-    axisZ,
-    bed,
-    hotend,
-    hotendOk,
-    fsensor,
-    fsensorOk,
-    allCorrect,
-    failed,
-    home,
+enum class TestScreen : uint_least8_t
+{
+    ExtruderFan,
+    PrintFan,
+    FansOk,
+    EndStops,
+    AxisX,
+    AxisY,
+    AxisZ,
+    Bed,
+    Hotend,
+    HotendOk,
+    Fsensor,
+    FsensorOk,
+    AllCorrect,
+    Failed,
+    Home,
 };
 
 enum class TestError : uint_least8_t
 {
-    heater,
-    bed,
-    endstops,
-    motor,
-    endstop,
-    printFan,
-    extruderFan,
-    pulley,
-    axis,
-    swappedFan,
-    wiringFsensor,
-    triggeringFsensor,
+    Heater,
+    Bed,
+    Endstops,
+    Motor,
+    Endstop,
+    PrintFan,
+    ExtruderFan,
+    Pulley,
+    Axis,
+    SwappedFan,
+    WiringFsensor,
+    TriggeringFsensor,
 };
 
-static int  lcd_selftest_screen(testScreen screen, int _progress, int _progress_scale, bool _clear, int _delay);
+static int  lcd_selftest_screen(TestScreen screen, int _progress, int _progress_scale, bool _clear, int _delay);
 static void lcd_selftest_screen_step(int _row, int _col, int _state, const char *_name, const char *_indicator);
 static bool lcd_selftest_manual_fan_check(int _fan, bool check_opposite,
 	bool _default=false);
@@ -211,10 +211,10 @@ static bool lcd_selftest_manual_fan_check(int _fan, bool check_opposite,
 /** Enumerate for lcd_selftest_fan_auto function.
  */
 enum class FanCheck : uint_least8_t {
-    success,
-    printFan = TestError::printFan,
-    extruderFan = TestError::extruderFan,
-    swappedFan = TestError::swappedFan,
+    Success,
+    PrintFan,
+    ExtruderFan,
+    SwappedFan,
 };
 
 /**
@@ -567,7 +567,7 @@ void lcdui_print_temp(char type, int val_current, int val_target)
 // Print Z-coordinate (8 chars total)
 void lcdui_print_Z_coord(void)
 {
-    if (custom_message_type == CUSTOM_MSG_TYPE_MESHBL)
+    if (custom_message_type == CustomMsg::MeshBedLeveling)
         lcd_puts_P(_N("Z   --- "));
     else
 		lcd_printf_P(_N("Z%6.2f "), current_position[Z_AXIS]);
@@ -762,7 +762,7 @@ void lcdui_print_status_line(void)
 			break;
 		}
 	}
-	else if ((IS_SD_PRINTING) && (custom_message_type == CUSTOM_MSG_TYPE_STATUS))
+	else if ((IS_SD_PRINTING) && (custom_message_type == CustomMsg::Status))
 	{ // If printing from SD, show what we are printing
 		if(strlen(card.longFilename) > LCD_WIDTH)
 		{
@@ -796,10 +796,10 @@ void lcdui_print_status_line(void)
 	{ // Otherwise check for other special events
    		switch (custom_message_type)
 		{
-		case CUSTOM_MSG_TYPE_STATUS: // Nothing special, print status message normally
+		case CustomMsg::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
+		case CustomMsg::MeshBedLeveling: // If mesh bed leveling in progress, show the status
 			if (custom_message_state > 10)
 			{
 				lcd_set_cursor(0, 3);
@@ -815,7 +815,7 @@ void lcdui_print_status_line(void)
 				{
 					lcd_puts_P(_T(WELCOME_MSG));
 					lcd_setstatuspgm(_T(WELCOME_MSG));
-					custom_message_type = CUSTOM_MSG_TYPE_STATUS;
+					custom_message_type = CustomMsg::Status;
 				}
 				if (custom_message_state > 3 && custom_message_state <= 10 )
 				{
@@ -827,10 +827,10 @@ void lcdui_print_status_line(void)
 				}
 			}
 			break;
-		case CUSTOM_MSG_TYPE_F_LOAD: // If loading filament, print status
+		case CustomMsg::FilamentLoading: // If loading filament, print status
 			lcd_print(lcd_status_message);
 			break;
-		case CUSTOM_MSG_TYPE_PIDCAL: // PID tuning in progress
+		case CustomMsg::PidCal: // PID tuning in progress
 			lcd_print(lcd_status_message);
 			if (pid_cycle <= pid_number_of_cycles && custom_message_state > 0)
 			{
@@ -840,7 +840,7 @@ void lcdui_print_status_line(void)
 				lcd_print(itostr3left(pid_number_of_cycles));
 			}
 			break;
-		case CUSTOM_MSG_TYPE_TEMCAL: // PINDA temp calibration in progress
+		case CustomMsg::TempCal: // PINDA temp calibration in progress
 			{
 				char progress[4];
 				lcd_set_cursor(0, 3);
@@ -850,7 +850,7 @@ void lcdui_print_status_line(void)
 				lcd_print(progress);
 			}
 			break;
-		case CUSTOM_MSG_TYPE_TEMPRE: // temp compensation preheat
+		case CustomMsg::TempCompPreheat: // 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)
@@ -989,6 +989,8 @@ static void lcd_status_screen()
 			{
 			case 8:
 				prusa_statistics(21);
+				if(loading_flag)
+					prusa_statistics(22);
 				break;
 			case 5:
 				if (IS_SD_PRINTING)
@@ -998,7 +1000,7 @@ static void lcd_status_screen()
 		} // end of farm_mode
 
 		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)
+		if (lcd_commands_type != LcdCommands::Idle)
 			lcd_commands();
 	} // end of lcd_draw_update
 
@@ -1022,7 +1024,7 @@ static void lcd_status_screen()
 	}
 
 	if (current_click
-		&& (lcd_commands_type != LCD_COMMAND_STOP_PRINT) //click is aborted unless stop print finishes
+		&& (lcd_commands_type != LcdCommands::StopPrint) //click is aborted unless stop print finishes
 		&& ( menu_block_entering_on_serious_errors == SERIOUS_ERR_NONE ) // or a serious error blocks entering the menu
 	)
 	{
@@ -1064,15 +1066,15 @@ static void lcd_status_screen()
 
 void lcd_commands()
 {	
-	if (lcd_commands_type == LCD_COMMAND_LONG_PAUSE)
+	if (lcd_commands_type == LcdCommands::LongPause)
 	{
 		if (!blocks_queued() && !homing_flag)
 		{
 			lcd_setstatuspgm(_i("Print paused"));////MSG_PRINT_PAUSED c=20 r=1
 			long_pause();
-               if (lcd_commands_type == LCD_COMMAND_LONG_PAUSE) // !!! because "lcd_commands_type" can be changed during/inside "long_pause()"
+               if (lcd_commands_type == LcdCommands::LongPause) // !!! because "lcd_commands_type" can be changed during/inside "long_pause()"
                {
-                    lcd_commands_type = 0;
+                    lcd_commands_type = LcdCommands::Idle;
                     lcd_commands_step = 0;
                }
 		}
@@ -1080,7 +1082,7 @@ void lcd_commands()
 
 
 #ifdef SNMM
-	if (lcd_commands_type == LCD_COMMAND_V2_CAL)
+	if (lcd_commands_type == LcdCommands::Layer1Cal)
 	{
 		char cmd1[30];
 		float width = 0.4;
@@ -1345,7 +1347,7 @@ void lcd_commands()
 
 #else //if not SNMM
 
-	if (lcd_commands_type == LCD_COMMAND_V2_CAL)
+	if (lcd_commands_type == LcdCommands::Layer1Cal)
 	{
 		char cmd1[30];
 		static uint8_t filament = 0;
@@ -1441,7 +1443,7 @@ void lcd_commands()
             case 1:
                 lcd_setstatuspgm(_T(WELCOME_MSG));
                 lcd_commands_step = 0;
-                lcd_commands_type = 0;
+                lcd_commands_type = LcdCommands::Idle;
                 if (eeprom_read_byte((uint8_t*)EEPROM_WIZARD_ACTIVE) == 1)
                 {
                     lcd_wizard(WizState::RepeatLay1Cal);
@@ -1453,7 +1455,7 @@ void lcd_commands()
 
 #endif // not SNMM
 
-	if (lcd_commands_type == LCD_COMMAND_STOP_PRINT)   /// stop print
+	if (lcd_commands_type == LcdCommands::StopPrint)   /// stop print
 	{
 		
 
@@ -1465,9 +1467,9 @@ void lcd_commands()
 		if (lcd_commands_step == 1 && !blocks_queued())
 		{
 			lcd_commands_step = 0;
-			lcd_commands_type = 0;
+			lcd_commands_type = LcdCommands::Idle;
 			lcd_setstatuspgm(_T(WELCOME_MSG));
-			custom_message_type = CUSTOM_MSG_TYPE_STATUS;
+			custom_message_type = CustomMsg::Status;
 			isPrintPaused = false;
 		}
 		if (lcd_commands_step == 2 && !blocks_queued())
@@ -1523,7 +1525,7 @@ void lcd_commands()
 			if (mmu_enabled)
 				setAllTargetHotends(0);
 			manage_heater();
-			custom_message_type = CUSTOM_MSG_TYPE_F_LOAD;
+			custom_message_type = CustomMsg::FilamentLoading;
 			lcd_commands_step = 5;
 		}
 		if (lcd_commands_step == 7 && !blocks_queued())
@@ -1545,12 +1547,7 @@ void lcd_commands()
 		}
 	}
 
-	if (lcd_commands_type == 3)
-	{
-		lcd_commands_type = 0;
-	}
-
-	if (lcd_commands_type == LCD_COMMAND_FARM_MODE_CONFIRM)   /// farm mode confirm
+	if (lcd_commands_type == LcdCommands::FarmModeConfirm)   /// farm mode confirm
 	{
 
 		if (lcd_commands_step == 0) { lcd_commands_step = 6; }
@@ -1559,7 +1556,7 @@ void lcd_commands()
 		{
 			lcd_confirm_print();
 			lcd_commands_step = 0;
-			lcd_commands_type = 0;
+			lcd_commands_type = LcdCommands::Idle;
 		}
 		if (lcd_commands_step == 2 && !blocks_queued())
 		{
@@ -1592,11 +1589,11 @@ void lcd_commands()
 		}
 
 	}
-	if (lcd_commands_type == LCD_COMMAND_PID_EXTRUDER) {
+	if (lcd_commands_type == LcdCommands::PidExtruder) {
 		char cmd1[30];
 		
 		if (lcd_commands_step == 0) {
-			custom_message_type = CUSTOM_MSG_TYPE_PIDCAL;
+			custom_message_type = CustomMsg::PidCal;
 			custom_message_state = 1;
 			lcd_draw_update = 3;
 			lcd_commands_step = 3;
@@ -1632,10 +1629,10 @@ void lcd_commands()
 		}
 		if ((lcd_commands_step == 1) && ((_millis()- display_time)>2000)) { //calibration finished message
 			lcd_setstatuspgm(_T(WELCOME_MSG));
-			custom_message_type = CUSTOM_MSG_TYPE_STATUS;
+			custom_message_type = CustomMsg::Status;
 			pid_temp = DEFAULT_PID_TEMP;
 			lcd_commands_step = 0;
-			lcd_commands_type = 0;
+			lcd_commands_type = LcdCommands::Idle;
 		}
 	}
 
@@ -1647,7 +1644,7 @@ void lcd_return_to_status()
 	lcd_refresh(); // to maybe revive the LCD if static electricity killed it.
 	menu_goto(lcd_status_screen, 0, false, true);
 	menu_depth = 0;
-     eFilamentAction=e_FILAMENT_ACTION_none; // i.e. non-autoLoad
+     eFilamentAction=FilamentAction::None; // i.e. non-autoLoad
 }
 
 //! @brief Pause print, disable nozzle heater, move to park position
@@ -1657,9 +1654,9 @@ void lcd_pause_print()
     stop_and_save_print_to_ram(0.0,0.0);
     setAllTargetHotends(0);
     isPrintPaused = true;
-    if (LCD_COMMAND_IDLE == lcd_commands_type)
+    if (LcdCommands::Idle == lcd_commands_type)
     {
-        lcd_commands_type = LCD_COMMAND_LONG_PAUSE;
+        lcd_commands_type = LcdCommands::LongPause;
     }
 }
 
@@ -1800,7 +1797,7 @@ void lcd_menu_extruder_info()                     // NOT static due to using ins
 			lcd_puts_P(_N("Filament sensor\n" "is disabled."));
 		else
 		{
-			if (!moves_planned() && !IS_SD_PRINTING && !is_usb_printing && (lcd_commands_type != LCD_COMMAND_V2_CAL))
+			if (!moves_planned() && !IS_SD_PRINTING && !is_usb_printing && (lcd_commands_type != LcdCommands::Layer1Cal))
 				pat9125_update();
 			lcd_printf_P(_N(
 				"Fil. Xd:%3d Yd:%3d\n"
@@ -2185,7 +2182,7 @@ void lcd_set_filament_oq_meass()
 }
 
 
-eFILAMENT_ACTION eFilamentAction=e_FILAMENT_ACTION_none; // must be initialized as 'non-autoLoad'
+FilamentAction eFilamentAction=FilamentAction::None; // must be initialized as 'non-autoLoad'
 bool bFilamentFirstRun;
 bool bFilamentPreheatState;
 bool bFilamentAction=false;
@@ -2202,18 +2199,18 @@ lcd_puts_P(_i("Press the knob"));                 ////MSG_ c=20 r=1
 lcd_set_cursor(0,3);
 switch(eFilamentAction)
      {
-     case e_FILAMENT_ACTION_Load:
-     case e_FILAMENT_ACTION_autoLoad:
-     case e_FILAMENT_ACTION_mmuLoad:
+     case FilamentAction::Load:
+     case FilamentAction::AutoLoad:
+     case FilamentAction::MmuLoad:
           lcd_puts_P(_i("to load filament"));     ////MSG_ c=20 r=1
           break;
-     case e_FILAMENT_ACTION_unLoad:
-     case e_FILAMENT_ACTION_mmuUnLoad:
+     case FilamentAction::UnLoad:
+     case FilamentAction::MmuUnLoad:
           lcd_puts_P(_i("to unload filament"));   ////MSG_ c=20 r=1
           break;
-     case e_FILAMENT_ACTION_mmuEject:
-     case e_FILAMENT_ACTION_mmuCut:
-     case e_FILAMENT_ACTION_none:
+     case FilamentAction::MmuEject:
+     case FilamentAction::MmuCut:
+     case FilamentAction::None:
           break;
      }
 if(lcd_clicked())
@@ -2227,21 +2224,21 @@ if(lcd_clicked())
      menu_back(nLevel);
      switch(eFilamentAction)
           {
-          case e_FILAMENT_ACTION_autoLoad:
-               eFilamentAction=e_FILAMENT_ACTION_none; // i.e. non-autoLoad
+          case FilamentAction::AutoLoad:
+               eFilamentAction=FilamentAction::None; // i.e. non-autoLoad
                // no break
-          case e_FILAMENT_ACTION_Load:
+          case FilamentAction::Load:
                loading_flag=true;
                enquecommand_P(PSTR("M701"));      // load filament
                break;
-          case e_FILAMENT_ACTION_unLoad:
+          case FilamentAction::UnLoad:
                enquecommand_P(PSTR("M702"));      // unload filament
                break;
-          case e_FILAMENT_ACTION_mmuLoad:
-          case e_FILAMENT_ACTION_mmuUnLoad:
-          case e_FILAMENT_ACTION_mmuEject:
-          case e_FILAMENT_ACTION_mmuCut:
-          case e_FILAMENT_ACTION_none:
+          case FilamentAction::MmuLoad:
+          case FilamentAction::MmuUnLoad:
+          case FilamentAction::MmuEject:
+          case FilamentAction::MmuCut:
+          case FilamentAction::None:
                break;
           }
      }
@@ -2265,19 +2262,19 @@ lcdui_print_temp(LCD_STR_THERMOMETER[0],(int)degHotend(0),(int)degTargetHotend(0
 lcd_set_cursor(0,1);
 switch(eFilamentAction)
      {
-     case e_FILAMENT_ACTION_Load:
-     case e_FILAMENT_ACTION_autoLoad:
-     case e_FILAMENT_ACTION_mmuLoad:
+     case eFILAMENT_ACTION::load:
+     case eFILAMENT_ACTION::autoLoad:
+     case eFILAMENT_ACTION::mmuLoad:
           lcd_puts_P(_i("Preheating to load"));   ////MSG_ c=20 r=1
           break;
-     case e_FILAMENT_ACTION_unLoad:
-     case e_FILAMENT_ACTION_mmuUnLoad:
+     case eFILAMENT_ACTION::unLoad:
+     case eFILAMENT_ACTION::mmuUnLoad:
           lcd_puts_P(_i("Preheating to unload")); ////MSG_ c=20 r=1
           break;
-     case e_FILAMENT_ACTION_mmuEject:
+     case eFILAMENT_ACTION::mmuEject:
           lcd_puts_P(_i("Preheating to eject"));  ////MSG_ c=20 r=1
           break;
-     case e_FILAMENT_ACTION_mmuCut:
+     case eFILAMENT_ACTION::mmuCut:
           lcd_puts_P(_i("Preheating to cut"));  ////MSG_ c=20 r=1
           break;
      }
@@ -2296,20 +2293,20 @@ if(lcd_clicked())
           setTargetBed((float)nTargetBedOld);
           }
      menu_back();
-     if(eFilamentAction==e_FILAMENT_ACTION_autoLoad)
-          eFilamentAction=e_FILAMENT_ACTION_none; // i.e. non-autoLoad
+     if(eFilamentAction==eFILAMENT_ACTION::autoLoad)
+          eFilamentAction=eFILAMENT_ACTION::none; // i.e. non-autoLoad
      }
 else {
      if(current_temperature[0]>(target_temperature[0]*0.95))
           {
           switch(eFilamentAction)
                {
-               case e_FILAMENT_ACTION_Load:
-               case e_FILAMENT_ACTION_autoLoad:
-               case e_FILAMENT_ACTION_unLoad:
+               case eFILAMENT_ACTION::load:
+               case eFILAMENT_ACTION::autoLoad:
+               case eFILAMENT_ACTION::unLoad:
                     menu_submenu(mFilamentPrompt);
                     break;
-               case e_FILAMENT_ACTION_mmuLoad:
+               case eFILAMENT_ACTION::mmuLoad:
                     nLevel=1;
                     if(!bFilamentPreheatState)
                          nLevel++;
@@ -2317,7 +2314,7 @@ else {
                     menu_back(nLevel);
                     menu_submenu(mmu_load_to_nozzle_menu);
                     break;
-               case e_FILAMENT_ACTION_mmuUnLoad:
+               case eFILAMENT_ACTION::mmuUnLoad:
                     nLevel=1;
                     if(!bFilamentPreheatState)
                          nLevel++;
@@ -2325,7 +2322,7 @@ else {
                     menu_back(nLevel);
                     extr_unload();
                     break;
-               case e_FILAMENT_ACTION_mmuEject:
+               case eFILAMENT_ACTION::mmuEject:
                     nLevel=1;
                     if(!bFilamentPreheatState)
                          nLevel++;
@@ -2333,7 +2330,7 @@ else {
                     menu_back(nLevel);
                     menu_submenu(mmu_fil_eject_menu);
                     break;
-               case e_FILAMENT_ACTION_mmuCut:
+               case eFILAMENT_ACTION::mmuCut:
                     nLevel=1;
                     if(!bFilamentPreheatState)
                          nLevel++;
@@ -2366,44 +2363,44 @@ if(current_temperature[0]>(target_temperature[0]*0.95))
      {
      switch(eFilamentAction)
           {
-          case e_FILAMENT_ACTION_Load:
-          case e_FILAMENT_ACTION_autoLoad:
-          case e_FILAMENT_ACTION_unLoad:
+          case FilamentAction::Load:
+          case FilamentAction::AutoLoad:
+          case FilamentAction::UnLoad:
                if(bFilamentWaitingFlag)
                     menu_submenu(mFilamentPrompt);
                else {
                     nLevel=bFilamentPreheatState?1:2;
                     menu_back(nLevel);
-                    if((eFilamentAction==e_FILAMENT_ACTION_Load)||(eFilamentAction==e_FILAMENT_ACTION_autoLoad))
+                    if((eFilamentAction==FilamentAction::Load)||(eFilamentAction==FilamentAction::AutoLoad))
                          {
                          loading_flag=true;
                          enquecommand_P(PSTR("M701")); // load filament
-                         if(eFilamentAction==e_FILAMENT_ACTION_autoLoad)
-                              eFilamentAction=e_FILAMENT_ACTION_none; // i.e. non-autoLoad
+                         if(eFilamentAction==FilamentAction::AutoLoad)
+                              eFilamentAction=FilamentAction::None; // i.e. non-autoLoad
                          }
-                    if(eFilamentAction==e_FILAMENT_ACTION_unLoad)
+                    if(eFilamentAction==FilamentAction::UnLoad)
                          enquecommand_P(PSTR("M702")); // unload filament
                     }
                break;
-          case e_FILAMENT_ACTION_mmuLoad:
+          case FilamentAction::MmuLoad:
                nLevel=bFilamentPreheatState?1:2;
                bFilamentAction=true;
                menu_back(nLevel);
                menu_submenu(mmu_load_to_nozzle_menu);
                break;
-          case e_FILAMENT_ACTION_mmuUnLoad:
+          case FilamentAction::MmuUnLoad:
                nLevel=bFilamentPreheatState?1:2;
                bFilamentAction=true;
                menu_back(nLevel);
                extr_unload();
                break;
-          case e_FILAMENT_ACTION_mmuEject:
+          case FilamentAction::MmuEject:
                nLevel=bFilamentPreheatState?1:2;
                bFilamentAction=true;
                menu_back(nLevel);
                menu_submenu(mmu_fil_eject_menu);
                break;
-          case e_FILAMENT_ACTION_mmuCut:
+          case FilamentAction::MmuCut:
 #ifdef MMU_HAS_CUTTER
                nLevel=bFilamentPreheatState?1:2;
                bFilamentAction=true;
@@ -2411,7 +2408,7 @@ if(current_temperature[0]>(target_temperature[0]*0.95))
                menu_submenu(mmu_cut_filament_menu);
 #endif //MMU_HAS_CUTTER
                break;
-          case e_FILAMENT_ACTION_none:
+          case FilamentAction::None:
                break;
           }
      if(bFilamentWaitingFlag)
@@ -2425,22 +2422,22 @@ else {
      lcd_set_cursor(0,1);
      switch(eFilamentAction)
           {
-          case e_FILAMENT_ACTION_Load:
-          case e_FILAMENT_ACTION_autoLoad:
-          case e_FILAMENT_ACTION_mmuLoad:
+          case FilamentAction::Load:
+          case FilamentAction::AutoLoad:
+          case FilamentAction::MmuLoad:
                lcd_puts_P(_i("Preheating to load")); ////MSG_ c=20 r=1
                break;
-          case e_FILAMENT_ACTION_unLoad:
-          case e_FILAMENT_ACTION_mmuUnLoad:
+          case FilamentAction::UnLoad:
+          case FilamentAction::MmuUnLoad:
                lcd_puts_P(_i("Preheating to unload")); ////MSG_ c=20 r=1
                break;
-          case e_FILAMENT_ACTION_mmuEject:
+          case FilamentAction::MmuEject:
                lcd_puts_P(_i("Preheating to eject")); ////MSG_ c=20 r=1
                break;
-          case e_FILAMENT_ACTION_mmuCut:
+          case FilamentAction::MmuCut:
                lcd_puts_P(_i("Preheating to cut")); ////MSG_ c=20 r=1
                break;
-          case e_FILAMENT_ACTION_none:
+          case FilamentAction::None:
                break;
           }
      lcd_set_cursor(0,3);
@@ -2459,8 +2456,8 @@ else {
                setTargetBed((float)nTargetBedOld);
                }
           menu_back();
-          if(eFilamentAction==e_FILAMENT_ACTION_autoLoad)
-               eFilamentAction=e_FILAMENT_ACTION_none; // i.e. non-autoLoad
+          if(eFilamentAction==FilamentAction::AutoLoad)
+               eFilamentAction=FilamentAction::None; // i.e. non-autoLoad
           }
      }
 }
@@ -2505,8 +2502,8 @@ mFilamentItem(FLEX_PREHEAT_HOTEND_TEMP,FLEX_PREHEAT_HPB_TEMP);
 void mFilamentBack()
 {
 menu_back();
-if(eFilamentAction==e_FILAMENT_ACTION_autoLoad)
-     eFilamentAction=e_FILAMENT_ACTION_none; // i.e. non-autoLoad
+if(eFilamentAction==FilamentAction::AutoLoad)
+     eFilamentAction=FilamentAction::None; // i.e. non-autoLoad
 }
 
 void mFilamentMenu()
@@ -2537,7 +2534,7 @@ if(0)
      enquecommand_P(PSTR("M702"));                // unload filament
      }
 else {
-     eFilamentAction=e_FILAMENT_ACTION_unLoad;
+     eFilamentAction=FilamentAction::UnLoad;
      bFilamentFirstRun=false;
      if(target_temperature[0]>=EXTRUDE_MINTEMP)
           {
@@ -2764,7 +2761,7 @@ static void lcd_LoadFilament()
 if(0)
   {
 //      menu_back();                                // not necessary (see "lcd_return_to_status()" below)
-      custom_message_type = CUSTOM_MSG_TYPE_F_LOAD;
+      custom_message_type = CustomMsg::FilamentLoading;
       loading_flag = true;
       enquecommand_P(PSTR("M701")); //load filament
       SERIAL_ECHOLN("Loading filament");
@@ -2772,7 +2769,7 @@ if(0)
   }
   else
   {
-     eFilamentAction=e_FILAMENT_ACTION_Load;
+     eFilamentAction=FilamentAction::Load;
      bFilamentFirstRun=false;
      if(target_temperature[0]>=EXTRUDE_MINTEMP)
           {
@@ -3072,13 +3069,13 @@ static void lcd_move_z() {
  * other value leads to storing Z_AXIS
  * @param msg text to be displayed
  */
-static void _lcd_babystep(int axis, const char *msg) 
+static void lcd_babystep_z()
 {
 	typedef struct
-	{	// 19bytes total
-		int8_t status;                 // 1byte
-		int babystepMem[3];            // 6bytes
-		float babystepMemMM[3];        // 12bytes
+	{
+		int8_t status;
+		int16_t babystepMemZ;
+		float babystepMemMMZ;
 	} _menu_data_t;
 	static_assert(sizeof(menu_data)>= sizeof(_menu_data_t),"_menu_data_t doesn't fit into menu_data");
 	_menu_data_t* _md = (_menu_data_t*)&(menu_data[0]);
@@ -3088,18 +3085,20 @@ static void _lcd_babystep(int axis, const char *msg)
 		// Initialize its status.
 		_md->status = 1;
 		check_babystep();
-
-		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]);
+		
+		if(!is_sheet_initialized()){
+			_md->babystepMemZ = 0;
+		}
+		else{
+			_md->babystepMemZ = eeprom_read_word(reinterpret_cast<uint16_t *>(&(EEPROM_Sheets_base->
+					s[(eeprom_read_byte(&(EEPROM_Sheets_base->active_sheet)))].z_offset)));
+		}
 
 		// same logic as in babystep_load
 	    if (calibration_status() >= CALIBRATION_STATUS_LIVE_ADJUST)
-			_md->babystepMem[2] = 0;
+			_md->babystepMemZ = 0;
 
-		_md->babystepMemMM[0] = _md->babystepMem[0]/cs.axis_steps_per_unit[X_AXIS];
-		_md->babystepMemMM[1] = _md->babystepMem[1]/cs.axis_steps_per_unit[Y_AXIS];
-		_md->babystepMemMM[2] = _md->babystepMem[2]/cs.axis_steps_per_unit[Z_AXIS];
+		_md->babystepMemMMZ = _md->babystepMemZ/cs.axis_steps_per_unit[Z_AXIS];
 		lcd_draw_update = 1;
 		//SERIAL_ECHO("Z baby step: ");
 		//SERIAL_ECHO(_md->babystepMem[2]);
@@ -3110,46 +3109,49 @@ static void _lcd_babystep(int axis, const char *msg)
 	if (lcd_encoder != 0) 
 	{
 		if (homing_flag) lcd_encoder = 0;
-		_md->babystepMem[axis] += (int)lcd_encoder;
-		if (axis == 2)
-		{
-			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
-				babystepsTodo[axis] += (int)lcd_encoder;
-				CRITICAL_SECTION_END		
-			}
-		}
-		_md->babystepMemMM[axis] = _md->babystepMem[axis]/cs.axis_steps_per_unit[axis]; 
+		_md->babystepMemZ += (int)lcd_encoder;
+
+        if (_md->babystepMemZ < Z_BABYSTEP_MIN) _md->babystepMemZ = Z_BABYSTEP_MIN; //-3999 -> -9.99 mm
+        else if (_md->babystepMemZ > Z_BABYSTEP_MAX) _md->babystepMemZ = Z_BABYSTEP_MAX; //0
+        else
+        {
+            CRITICAL_SECTION_START
+            babystepsTodo[Z_AXIS] += (int)lcd_encoder;
+            CRITICAL_SECTION_END
+        }
+
+		_md->babystepMemMMZ = _md->babystepMemZ/cs.axis_steps_per_unit[Z_AXIS];
 		_delay(50);
 		lcd_encoder = 0;
 		lcd_draw_update = 1;
 	}
 	if (lcd_draw_update)
 	{
+	    SheetFormatBuffer buffer;
+	    menu_format_sheet_E(EEPROM_Sheets_base->s[(eeprom_read_byte(&(EEPROM_Sheets_base->active_sheet)))], buffer);
+	    lcd_set_cursor(0, 0);
+	    lcd_print(buffer.c);
 	    lcd_set_cursor(0, 1);
-		menu_draw_float13(msg, _md->babystepMemMM[axis]);
+		menu_draw_float13(_i("Adjusting Z:"), _md->babystepMemMMZ); ////MSG_BABYSTEPPING_Z c=15 Beware: must include the ':' as its last character
 	}
 	if (LCD_CLICKED || menu_leaving)
 	{
 		// 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),
-		&_md->babystepMem[axis]);
-		if(Z_AXIS == axis) calibration_status_store(CALIBRATION_STATUS_CALIBRATED);
+		eeprom_update_word(reinterpret_cast<uint16_t *>(&(EEPROM_Sheets_base->
+                s[(eeprom_read_byte(&(EEPROM_Sheets_base->active_sheet)))].z_offset)),
+		        _md->babystepMemZ);
+		eeprom_update_byte(&(EEPROM_Sheets_base->s[(eeprom_read_byte(
+		        &(EEPROM_Sheets_base->active_sheet)))].bed_temp),
+		        target_temperature_bed);
+		eeprom_update_byte(&(EEPROM_Sheets_base->s[(eeprom_read_byte(
+		        &(EEPROM_Sheets_base->active_sheet)))].pinda_temp),
+		        current_temperature_pinda);
+		calibration_status_store(CALIBRATION_STATUS_CALIBRATED);
 	}
 	if (LCD_CLICKED) menu_back();
 }
 
 
-static void lcd_babystep_z()
-{
-	_lcd_babystep(Z_AXIS, (_i("Adjusting Z:")));////MSG_BABYSTEPPING_Z c=15 Beware: must include the ':' as its last character
-}
-
-
 typedef struct
 {	// 12bytes + 9bytes = 21bytes total
     menu_data_edit_t reserved; //12 bytes reserved for number editing functions
@@ -3221,7 +3223,7 @@ void pid_extruder()
 	lcd_set_cursor(1, 2);
 	lcd_print(ftostr3(pid_temp));
 	if (lcd_clicked()) {
-		lcd_commands_type = LCD_COMMAND_PID_EXTRUDER;
+		lcd_commands_type = LcdCommands::PidExtruder;
 		lcd_return_to_status();
 		lcd_update(2);
 	}
@@ -3823,7 +3825,7 @@ void lcd_bed_calibration_show_result(BedSkewOffsetDetectionResultType result, ui
 
 void lcd_temp_cal_show_result(bool result) {
 	
-	custom_message_type = CUSTOM_MSG_TYPE_STATUS;
+	custom_message_type = CustomMsg::Status;
 	disable_x();
 	disable_y();
 	disable_z();
@@ -3967,7 +3969,7 @@ void prusa_statistics(int _message, uint8_t _fil_nr) {
 			SERIAL_ECHOLN("}");
 			status_number = 14;
 		}
-		else if (IS_SD_PRINTING)
+		else if (IS_SD_PRINTING || loading_flag)
 		{
 			SERIAL_ECHO("{");
 			prusa_stat_printerstatus(4);
@@ -4006,7 +4008,7 @@ void prusa_statistics(int _message, uint8_t _fil_nr) {
 		status_number = 3;
 		farm_timer = 1;
 
-		if (IS_SD_PRINTING)
+		if (IS_SD_PRINTING || loading_flag)
 		{
 			farm_status = 4;
 			SERIAL_ECHO("{");
@@ -4452,7 +4454,7 @@ static void lcd_crash_mode_set()
     }else{
         crashdet_enable();
     }
-	if (IS_SD_PRINTING || is_usb_printing || (lcd_commands_type == LCD_COMMAND_V2_CAL)) menu_goto(lcd_tune_menu, 9, true, true);
+	if (IS_SD_PRINTING || is_usb_printing || (lcd_commands_type == LcdCommands::Layer1Cal)) menu_goto(lcd_tune_menu, 9, true, true);
 	else menu_goto(lcd_settings_menu, 9, true, true);
     
 }
@@ -4689,14 +4691,14 @@ void lcd_v2_calibration()
 	    if (filament < 5)
 	    {
 	        lcd_commands_step = 20 + filament;
-	        lcd_commands_type = LCD_COMMAND_V2_CAL;
+	        lcd_commands_type = LcdCommands::Layer1Cal;
 	    }
 	}
 	else
 	{
 		bool loaded = lcd_show_fullscreen_message_yes_no_and_wait_P(_i("Is PLA filament loaded?"), false, true);////MSG_PLA_FILAMENT_LOADED c=20 r=2
 		if (loaded) {
-			lcd_commands_type = LCD_COMMAND_V2_CAL;
+			lcd_commands_type = LcdCommands::Layer1Cal;
 		}
 		else {
 			lcd_display_message_fullscreen_P(_i("Please load PLA filament first."));////MSG_PLEASE_LOAD_PLA c=20 r=4
@@ -4956,7 +4958,7 @@ void lcd_wizard(WizState state)
 		case S::Lay1Cal:
 			lcd_show_fullscreen_message_and_wait_P(_i("Now I will calibrate distance between tip of the nozzle and heatbed surface."));////MSG_WIZARD_V2_CAL c=20 r=8
 			lcd_show_fullscreen_message_and_wait_P(_i("I will start to print line and you will gradually lower the nozzle by rotating the knob, until you reach optimal height. Check the pictures in our handbook in chapter Calibration."));////MSG_WIZARD_V2_CAL_2 c=20 r=12
-			lcd_commands_type = LCD_COMMAND_V2_CAL;
+			lcd_commands_type = LcdCommands::Layer1Cal;
 			lcd_return_to_status();
 			end = true;
 			break;
@@ -5607,7 +5609,7 @@ static void lcd_calibration_menu()
   if (!isPrintPaused)
   {
 	MENU_ITEM_FUNCTION_P(_i("Wizard"), lcd_wizard);////MSG_WIZARD c=17 r=1
-	MENU_ITEM_SUBMENU_P(_i("First layer cal."), lcd_v2_calibration);////MSG_V2_CALIBRATION c=17 r=1
+	MENU_ITEM_SUBMENU_P(_T(MSG_V2_CALIBRATION), lcd_v2_calibration);
 	MENU_ITEM_GCODE_P(_T(MSG_AUTO_HOME), PSTR("G28 W"));
 	MENU_ITEM_FUNCTION_P(_i("Selftest         "), lcd_selftest_v);////MSG_SELFTEST
 #ifdef MK1BP
@@ -6033,7 +6035,7 @@ static void mmu_load_to_nozzle_menu()
     }
     else
     {
-        eFilamentAction = e_FILAMENT_ACTION_mmuLoad;
+        eFilamentAction = FilamentAction::MmuLoad;
         bFilamentFirstRun = false;
         if (target_temperature[0] >= EXTRUDE_MINTEMP)
         {
@@ -6065,7 +6067,7 @@ static void mmu_fil_eject_menu()
     }
     else
     {
-        eFilamentAction = e_FILAMENT_ACTION_mmuEject;
+        eFilamentAction = FilamentAction::MmuEject;
         bFilamentFirstRun = false;
         if (target_temperature[0] >= EXTRUDE_MINTEMP)
         {
@@ -6093,7 +6095,7 @@ static void mmu_cut_filament_menu()
     }
     else
     {
-        eFilamentAction=e_FILAMENT_ACTION_mmuCut;
+        eFilamentAction=FilamentAction::MmuCut;
         bFilamentFirstRun=false;
         if(target_temperature[0]>=EXTRUDE_MINTEMP)
         {
@@ -6138,7 +6140,7 @@ static void change_extr_menu(){
 //unload filament for single material printer (used in M702 gcode)
 void unload_filament()
 {
-	custom_message_type = CUSTOM_MSG_TYPE_F_LOAD;
+	custom_message_type = CustomMsg::FilamentLoading;
 	lcd_setstatuspgm(_T(MSG_UNLOADING_FILAMENT));
 
 	//		extr_unload2();
@@ -6173,7 +6175,7 @@ void unload_filament()
 	lcd_update_enable(true);
 
 	lcd_setstatuspgm(_T(WELCOME_MSG));
-	custom_message_type = CUSTOM_MSG_TYPE_STATUS;
+	custom_message_type = CustomMsg::Status;
 
 }
 
@@ -6430,6 +6432,95 @@ void lcd_resume_print()
     isPrintPaused = false;
 }
 
+static void change_sheet(uint8_t sheet_num)
+{
+	eeprom_update_byte(&(EEPROM_Sheets_base->active_sheet), sheet_num);
+	if(is_sheet_initialized())
+		calibration_status_store(CALIBRATION_STATUS_CALIBRATED);
+	else
+		calibration_status_store(CALIBRATION_STATUS_LIVE_ADJUST);
+
+    menu_back(3);
+}
+
+static void lcd_select_sheet_0_menu()
+{
+	change_sheet(0);
+}
+static void lcd_select_sheet_1_menu()
+{
+	change_sheet(1);
+}
+static void lcd_select_sheet_2_menu()
+{
+	change_sheet(2);
+}
+
+static void lcd_select_sheet_menu()
+{
+    MENU_BEGIN();
+    MENU_ITEM_BACK_P(_T(MSG_BACK));
+    MENU_ITEM_SUBMENU_E(EEPROM_Sheets_base->s[0], lcd_select_sheet_0_menu);
+    MENU_ITEM_SUBMENU_E(EEPROM_Sheets_base->s[1], lcd_select_sheet_1_menu);
+    MENU_ITEM_SUBMENU_E(EEPROM_Sheets_base->s[2], lcd_select_sheet_2_menu);
+    MENU_END();
+}
+
+static void lcd_rename_sheet_menu()
+{
+    struct MenuData
+    {
+        bool initialized;
+        uint8_t selected;
+        char name[sizeof(Sheet::name)];
+    };
+    static_assert(sizeof(menu_data)>= sizeof(MenuData),"MenuData doesn't fit into menu_data");
+    MenuData* menuData = (MenuData*)&(menu_data[0]);
+
+    if (!menuData->initialized)
+    {
+        eeprom_read_block(menuData->name, EEPROM_Sheets_base->s[(eeprom_read_byte(&(EEPROM_Sheets_base->active_sheet)))].name, sizeof(Sheet::name));
+        lcd_encoder = menuData->name[0];
+        menuData->initialized = true;
+    }
+    if (lcd_encoder < '\x20') lcd_encoder = '\x20';
+    if (lcd_encoder > '\x7F') lcd_encoder = '\x7F';
+
+    menuData->name[menuData->selected] = lcd_encoder;
+    lcd_set_cursor(0,0);
+    for (uint_least8_t i = 0; i < sizeof(Sheet::name); ++i)
+    {
+        lcd_putc(menuData->name[i]);
+    }
+    lcd_set_cursor(menuData->selected, 1);
+    lcd_putc('^');
+    if (lcd_clicked())
+    {
+        if ((menuData->selected + 1u) < sizeof(Sheet::name))
+        {
+            lcd_encoder = menuData->name[++(menuData->selected)];
+        }
+        else
+        {
+            eeprom_update_block(menuData->name,
+                EEPROM_Sheets_base->s[(eeprom_read_byte(&(EEPROM_Sheets_base->active_sheet)))].name,
+                sizeof(Sheet::name));
+            menu_back();
+        }
+    }
+}
+
+static void lcd_sheet_menu()
+{
+    MENU_BEGIN();
+    MENU_ITEM_BACK_P(_T(MSG_MAIN));
+    MENU_ITEM_SUBMENU_P(_i("Select"), lcd_select_sheet_menu); //// c=18
+    MENU_ITEM_SUBMENU_P(_i("Rename"), lcd_rename_sheet_menu); //// c=18
+    MENU_ITEM_SUBMENU_P(_T(MSG_V2_CALIBRATION), lcd_v2_calibration);
+
+    MENU_END();
+}
+
 static void lcd_main_menu()
 {
 
@@ -6451,63 +6542,14 @@ static void lcd_main_menu()
  MENU_ITEM_FUNCTION_P(PSTR("recover print"), recover_print);
  MENU_ITEM_FUNCTION_P(PSTR("power panic"), uvlo_);
 #endif //TMC2130_DEBUG
-
- /* if (farm_mode && !IS_SD_PRINTING )
-    {
-    
-        int tempScrool = 0;
-        if (lcd_draw_update == 0 && LCD_CLICKED == 0)
-            //_delay(100);
-            return; // nothing to do (so don't thrash the SD card)
-        uint16_t fileCnt = card.getnrfilenames();
-        
-        card.getWorkDirName();
-        if (card.filename[0] == '/')
-        {
-#if SDCARDDETECT == -1
-            MENU_ITEM_FUNCTION_P(_T(MSG_REFRESH), lcd_sd_refresh);
-#endif
-        } else {
-            MENU_ITEM_FUNCTION_P(PSTR(LCD_STR_FOLDER ".."), lcd_sd_updir);
-        }
-        
-        for (uint16_t i = 0; i < fileCnt; i++)
-        {
-            if (menu_item == menu_line)
-            {
-#ifndef SDCARD_RATHERRECENTFIRST
-                card.getfilename(i);
-#else
-                card.getfilename(fileCnt - 1 - i);
-#endif
-                if (card.filenameIsDir)
-                {
-                    MENU_ITEM_SDDIR(_T(MSG_CARD_MENU), card.filename, card.longFilename);
-                } else {
-                    
-                    MENU_ITEM_SDFILE(_T(MSG_CARD_MENU), card.filename, card.longFilename);
-                    
-                    
-                    
-                    
-                }
-            } else {
-                MENU_ITEM_DUMMY();
-            }
-        }
-        
-        MENU_ITEM_BACK_P(PSTR("- - - - - - - - -"));
-    
-        
-    }*/
  
-  if ( ( IS_SD_PRINTING || is_usb_printing || (lcd_commands_type == LCD_COMMAND_V2_CAL)) && (current_position[Z_AXIS] < Z_HEIGHT_HIDE_LIVE_ADJUST_MENU) && !homing_flag && !mesh_bed_leveling_flag)
+  if ( ( IS_SD_PRINTING || is_usb_printing || (lcd_commands_type == LcdCommands::Layer1Cal)) && (current_position[Z_AXIS] < Z_HEIGHT_HIDE_LIVE_ADJUST_MENU) && !homing_flag && !mesh_bed_leveling_flag)
   {
 	MENU_ITEM_SUBMENU_P(_T(MSG_BABYSTEP_Z), lcd_babystep_z);//8
   }
 
 
-  if ( moves_planned() || IS_SD_PRINTING || is_usb_printing || (lcd_commands_type == LCD_COMMAND_V2_CAL))
+  if ( moves_planned() || IS_SD_PRINTING || is_usb_printing || (lcd_commands_type == LcdCommands::Layer1Cal))
   {
     MENU_ITEM_SUBMENU_P(_i("Tune"), lcd_tune_menu);////MSG_TUNE
   } else 
@@ -6515,8 +6557,10 @@ static void lcd_main_menu()
     MENU_ITEM_SUBMENU_P(_i("Preheat"), lcd_preheat_menu);////MSG_PREHEAT
   }
 
+
+
 #ifdef SDSUPPORT
-  if (card.cardOK || lcd_commands_type == LCD_COMMAND_V2_CAL)
+  if (card.cardOK || lcd_commands_type == LcdCommands::Layer1Cal)
   {
     if (card.isFileOpen())
     {
@@ -6532,12 +6576,12 @@ static void lcd_main_menu()
 			MENU_ITEM_SUBMENU_P(_T(MSG_STOP_PRINT), lcd_sdcard_stop);
 		}
 	}
-	else if (lcd_commands_type == LCD_COMMAND_V2_CAL && mesh_bed_leveling_flag == false && homing_flag == false) {
+	else if (lcd_commands_type == LcdCommands::Layer1Cal && mesh_bed_leveling_flag == false && homing_flag == false) {
 		//MENU_ITEM_SUBMENU_P(_T(MSG_STOP_PRINT), lcd_sdcard_stop);
 	}
 	else
 	{
-		if (!is_usb_printing && (lcd_commands_type != LCD_COMMAND_V2_CAL))
+		if (!is_usb_printing && (lcd_commands_type != LcdCommands::Layer1Cal))
 		{
 			//if (farm_mode) MENU_ITEM_SUBMENU_P(MSG_FARM_CARD_MENU, lcd_farm_sdcard_menu);
 			/*else*/ {
@@ -6561,7 +6605,7 @@ static void lcd_main_menu()
 #endif
 
 
-  if (IS_SD_PRINTING || is_usb_printing || (lcd_commands_type == LCD_COMMAND_V2_CAL))
+  if (IS_SD_PRINTING || is_usb_printing || (lcd_commands_type == LcdCommands::Layer1Cal))
   {
 	  if (farm_mode)
 	  {
@@ -6605,7 +6649,9 @@ static void lcd_main_menu()
 
   }
 
-  if (!is_usb_printing && (lcd_commands_type != LCD_COMMAND_V2_CAL))
+  if(!isPrintPaused)MENU_ITEM_SUBMENU_E(EEPROM_Sheets_base->s[(eeprom_read_byte(&(EEPROM_Sheets_base->active_sheet)))], lcd_sheet_menu);
+  
+  if (!is_usb_printing && (lcd_commands_type != LcdCommands::Layer1Cal))
   {
 	  MENU_ITEM_SUBMENU_P(_i("Statistics  "), lcd_menu_statistics);////MSG_STATISTICS
   }
@@ -6661,7 +6707,7 @@ static void lcd_colorprint_change() {
 	
 	enquecommand_P(PSTR("M600"));
 	
-	custom_message_type = CUSTOM_MSG_TYPE_F_LOAD; //just print status message
+	custom_message_type = CustomMsg::FilamentLoading; //just print status message
 	lcd_setstatuspgm(_T(MSG_FINISHING_MOVEMENTS));
 	lcd_return_to_status();
 	lcd_draw_update = 3;
@@ -6904,7 +6950,7 @@ void lcd_print_stop()
 	lcd_return_to_status();
 	lcd_ignore_click(true);
 	lcd_commands_step = 0;
-	lcd_commands_type = LCD_COMMAND_STOP_PRINT;
+	lcd_commands_type = LcdCommands::StopPrint;
 	// Turn off the print fan
 	SET_OUTPUT(FAN_PIN);
 	WRITE(FAN_PIN, 0);
@@ -7017,13 +7063,13 @@ bool lcd_selftest()
 	_delay(2000);
 	KEEPALIVE_STATE(IN_HANDLER);
 
-	_progress = lcd_selftest_screen(testScreen::extruderFan, _progress, 3, true, 2000);
+	_progress = lcd_selftest_screen(TestScreen::ExtruderFan, _progress, 3, true, 2000);
 #if (defined(FANCHECK) && defined(TACH_0))
 	switch (lcd_selftest_fan_auto(0)){		// check extruder Fan
-		case FanCheck::extruderFan:
+		case FanCheck::ExtruderFan:
 			_result = false;
 			break;
-		case FanCheck::swappedFan:
+		case FanCheck::SwappedFan:
 			_swapped_fan = true;
 			// no break
 		default:
@@ -7035,18 +7081,18 @@ bool lcd_selftest()
 #endif //defined(TACH_0)
 	if (!_result)
 	{
-		lcd_selftest_error(TestError::extruderFan, "", "");
+		lcd_selftest_error(TestError::ExtruderFan, "", "");
 	}
 
 	if (_result)
 	{
-		_progress = lcd_selftest_screen(testScreen::printFan, _progress, 3, true, 2000);
+		_progress = lcd_selftest_screen(TestScreen::PrintFan, _progress, 3, true, 2000);
 #if (defined(FANCHECK) && defined(TACH_1))
 	switch (lcd_selftest_fan_auto(1)){		// check print fan
-		case FanCheck::printFan:
+		case FanCheck::PrintFan:
 			_result = false;
 			break;
-		case FanCheck::swappedFan:
+		case FanCheck::SwappedFan:
 			_swapped_fan = true;
 			// no break
 		default:
@@ -7058,7 +7104,7 @@ bool lcd_selftest()
 #endif //defined(TACH_1)
 		if (!_result)
 		{
-			lcd_selftest_error(TestError::printFan, "", ""); //print fan not spinning
+			lcd_selftest_error(TestError::PrintFan, "", ""); //print fan not spinning
 		}
 	}
 
@@ -7069,18 +7115,18 @@ bool lcd_selftest()
 			//print fan is stil turned on; check that it is spinning
 			_result = lcd_selftest_manual_fan_check(1, false, true);
 			if (!_result){
-				lcd_selftest_error(TestError::printFan, "", "");
+				lcd_selftest_error(TestError::PrintFan, "", "");
 			}
 		}
 		else {
 			// fans are swapped
-			lcd_selftest_error(TestError::swappedFan, "", "");
+			lcd_selftest_error(TestError::SwappedFan, "", "");
 		}
 	}
 
 	if (_result)
 	{
-		_progress = lcd_selftest_screen(testScreen::fansOk, _progress, 3, true, 2000);
+		_progress = lcd_selftest_screen(TestScreen::FansOk, _progress, 3, true, 2000);
 #ifndef TMC2130
 		_result = lcd_selfcheck_endstops();
 #else
@@ -7091,7 +7137,7 @@ bool lcd_selftest()
 	if (_result)
 	{
 		//current_position[Z_AXIS] += 15;									//move Z axis higher to avoid false triggering of Z end stop in case that we are very low - just above heatbed
-		_progress = lcd_selftest_screen(testScreen::axisX, _progress, 3, true, 2000);
+		_progress = lcd_selftest_screen(TestScreen::AxisX, _progress, 3, true, 2000);
 #ifdef TMC2130
         _result = lcd_selfcheck_axis_sg(X_AXIS);
 #else
@@ -7104,7 +7150,7 @@ bool lcd_selftest()
 
 	if (_result)
 	{
-		_progress = lcd_selftest_screen(testScreen::axisX, _progress, 3, true, 0);
+		_progress = lcd_selftest_screen(TestScreen::AxisX, _progress, 3, true, 0);
 
 #ifndef TMC2130
 		_result = lcd_selfcheck_pulleys(X_AXIS);
@@ -7114,7 +7160,7 @@ bool lcd_selftest()
 
 	if (_result)
 	{
-		_progress = lcd_selftest_screen(testScreen::axisY, _progress, 3, true, 1500);
+		_progress = lcd_selftest_screen(TestScreen::AxisY, _progress, 3, true, 1500);
 #ifdef TMC2130
 		_result = lcd_selfcheck_axis_sg(Y_AXIS);
 #else
@@ -7124,7 +7170,7 @@ bool lcd_selftest()
 
 	if (_result)
 	{
-		_progress = lcd_selftest_screen(testScreen::axisZ, _progress, 3, true, 0);
+		_progress = lcd_selftest_screen(TestScreen::AxisZ, _progress, 3, true, 0);
 #ifndef TMC2130
 		_result = lcd_selfcheck_pulleys(Y_AXIS);
 #endif // TMC2130
@@ -7145,7 +7191,7 @@ bool lcd_selftest()
 		current_position[Z_AXIS] = current_position[Z_AXIS] + 10;
 		plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[3], manual_feedrate[0] / 60, active_extruder);
 		st_synchronize();
-		_progress = lcd_selftest_screen(testScreen::axisZ, _progress, 3, true, 1500);
+		_progress = lcd_selftest_screen(TestScreen::AxisZ, _progress, 3, true, 1500);
 		_result = lcd_selfcheck_axis(2, Z_MAX_POS);
 		if (eeprom_read_byte((uint8_t*)EEPROM_WIZARD_ACTIVE) != 1) {
 			enquecommand_P(PSTR("G28 W"));
@@ -7159,11 +7205,11 @@ bool lcd_selftest()
 		current_position[Z_AXIS] = current_position[Z_AXIS] + 10;
 		plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[3], manual_feedrate[0] / 60, active_extruder);
 		st_synchronize();
-		_progress = lcd_selftest_screen(testScreen::home, 0, 2, true, 0);
+		_progress = lcd_selftest_screen(TestScreen::Home, 0, 2, true, 0);
 		bool bres = tmc2130_home_calibrate(X_AXIS);
-		_progress = lcd_selftest_screen(testScreen::home, 1, 2, true, 0);
+		_progress = lcd_selftest_screen(TestScreen::Home, 1, 2, true, 0);
 		bres &= tmc2130_home_calibrate(Y_AXIS);
-		_progress = lcd_selftest_screen(testScreen::home, 2, 2, true, 0);
+		_progress = lcd_selftest_screen(TestScreen::Home, 2, 2, true, 0);
 		if (bres)
 			eeprom_update_byte((uint8_t*)EEPROM_TMC2130_HOME_ENABLED, 1);
 		_result = bres;
@@ -7172,18 +7218,18 @@ bool lcd_selftest()
 
 	if (_result)
 	{
-		_progress = lcd_selftest_screen(testScreen::bed, _progress, 3, true, 2000);
+		_progress = lcd_selftest_screen(TestScreen::Bed, _progress, 3, true, 2000);
 		_result = lcd_selfcheck_check_heater(true);
 	}
 
     if (_result)
     {
-        _progress = lcd_selftest_screen(testScreen::hotend, _progress, 3, true, 1000);
+        _progress = lcd_selftest_screen(TestScreen::Hotend, _progress, 3, true, 1000);
         _result = lcd_selfcheck_check_heater(false);
     }
 	if (_result)
 	{
-		_progress = lcd_selftest_screen(testScreen::hotendOk, _progress, 3, true, 2000); //nozzle ok
+		_progress = lcd_selftest_screen(TestScreen::HotendOk, _progress, 3, true, 2000); //nozzle ok
 	}
 #ifdef FILAMENT_SENSOR
     if (_result)
@@ -7191,20 +7237,20 @@ bool lcd_selftest()
 
         if (mmu_enabled)
         {        
-			_progress = lcd_selftest_screen(testScreen::fsensor, _progress, 3, true, 2000); //check filaments sensor
+			_progress = lcd_selftest_screen(TestScreen::Fsensor, _progress, 3, true, 2000); //check filaments sensor
             _result = selftest_irsensor();
 		    if (_result)
 			{
-				_progress = lcd_selftest_screen(testScreen::fsensorOk, _progress, 3, true, 2000); //fil sensor OK
+				_progress = lcd_selftest_screen(TestScreen::FsensorOk, _progress, 3, true, 2000); //fil sensor OK
 			}
         } else
         {
 #ifdef PAT9125
-			_progress = lcd_selftest_screen(testScreen::fsensor, _progress, 3, true, 2000); //check filaments sensor
+			_progress = lcd_selftest_screen(TestScreen::Fsensor, _progress, 3, true, 2000); //check filaments sensor
             _result = lcd_selftest_fsensor();
 			if (_result)
 			{
-				_progress = lcd_selftest_screen(testScreen::fsensorOk, _progress, 3, true, 2000); //fil sensor OK
+				_progress = lcd_selftest_screen(TestScreen::FsensorOk, _progress, 3, true, 2000); //fil sensor OK
 			}
 #endif //PAT9125
         }
@@ -7212,11 +7258,11 @@ bool lcd_selftest()
 #endif //FILAMENT_SENSOR
 	if (_result)
 	{
-		_progress = lcd_selftest_screen(testScreen::allCorrect, _progress, 3, true, 5000); //all correct
+		_progress = lcd_selftest_screen(TestScreen::AllCorrect, _progress, 3, true, 5000); //all correct
 	}
 	else
 	{
-		_progress = lcd_selftest_screen(testScreen::failed, _progress, 3, true, 5000);
+		_progress = lcd_selftest_screen(TestScreen::Failed, _progress, 3, true, 5000);
 	}
 	lcd_reset_alert_level();
 	enquecommand_P(PSTR("M84"));
@@ -7330,7 +7376,7 @@ static bool lcd_selfcheck_axis_sg(unsigned char axis) {
 			if (axis == Y_AXIS) _error_1 = "Y";
 			if (axis == Z_AXIS) _error_1 = "Z";
 
-			lcd_selftest_error(TestError::axis, _error_1, "");
+			lcd_selftest_error(TestError::Axis, _error_1, "");
 			current_position[axis] = 0;
 			plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
 			reset_crash_det(axis);
@@ -7348,7 +7394,7 @@ static bool lcd_selfcheck_axis_sg(unsigned char axis) {
 			if (axis == Y_AXIS) _error_1 = "Y";
 			if (axis == Z_AXIS) _error_1 = "Z";
 
-			lcd_selftest_error(TestError::pulley, _error_1, "");
+			lcd_selftest_error(TestError::Pulley, _error_1, "");
 			current_position[axis] = 0;
 			plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
 			reset_crash_det(axis);
@@ -7423,7 +7469,7 @@ static bool lcd_selfcheck_axis(int _axis, int _travel)
 		}
 		else
 		{
-			_progress = lcd_selftest_screen(static_cast<testScreen>(static_cast<int>(testScreen::axisX) + _axis), _progress, 3, false, 0);
+			_progress = lcd_selftest_screen(static_cast<TestScreen>(static_cast<int>(TestScreen::AxisX) + _axis), _progress, 3, false, 0);
 			_lcd_refresh = 0;
 		}
 
@@ -7455,11 +7501,11 @@ static bool lcd_selfcheck_axis(int _axis, int _travel)
 
 		if (_travel_done >= _travel)
 		{
-			lcd_selftest_error(TestError::endstop, _error_1, _error_2);
+			lcd_selftest_error(TestError::Endstop, _error_1, _error_2);
 		}
 		else
 		{
-			lcd_selftest_error(TestError::motor, _error_1, _error_2);
+			lcd_selftest_error(TestError::Motor, _error_1, _error_2);
 		}
 	}
 
@@ -7499,7 +7545,7 @@ static bool lcd_selfcheck_pulleys(int axis)
 		st_synchronize();
 		if (((READ(X_MIN_PIN) ^ X_MIN_ENDSTOP_INVERTING) == 1) ||
 			((READ(Y_MIN_PIN) ^ Y_MIN_ENDSTOP_INVERTING) == 1)) {
-			lcd_selftest_error(TestError::pulley, (axis == 0) ? "X" : "Y", "");
+			lcd_selftest_error(TestError::Pulley, (axis == 0) ? "X" : "Y", "");
 			return(false);
 		}
 	}
@@ -7517,7 +7563,7 @@ static bool lcd_selfcheck_pulleys(int axis)
 				return(true);
 			}
 			else {
-				lcd_selftest_error(TestError::pulley, (axis == 0) ? "X" : "Y", "");
+				lcd_selftest_error(TestError::Pulley, (axis == 0) ? "X" : "Y", "");
 				return(false);
 			}
 		}
@@ -7526,7 +7572,7 @@ static bool lcd_selfcheck_pulleys(int axis)
 			plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[3], manual_feedrate[0] / 60, active_extruder);
 			st_synchronize();
 			if (_millis() > timeout_counter) {
-				lcd_selftest_error(TestError::pulley, (axis == 0) ? "X" : "Y", "");
+				lcd_selftest_error(TestError::Pulley, (axis == 0) ? "X" : "Y", "");
 				return(false);
 			}
 		}
@@ -7559,7 +7605,7 @@ static bool lcd_selfcheck_endstops()
 		if ((READ(X_MIN_PIN) ^ X_MIN_ENDSTOP_INVERTING) == 1) strcat(_error, "X");
 		if ((READ(Y_MIN_PIN) ^ Y_MIN_ENDSTOP_INVERTING) == 1) strcat(_error, "Y");
 		if ((READ(Z_MIN_PIN) ^ Z_MIN_ENDSTOP_INVERTING) == 1) strcat(_error, "Z");
-		lcd_selftest_error(TestError::endstops, _error, "");
+		lcd_selftest_error(TestError::Endstops, _error, "");
 	}
 	manage_heater();
 	manage_inactivity(true);
@@ -7590,7 +7636,7 @@ static bool lcd_selfcheck_check_heater(bool _isbed)
 
 		manage_heater();
 		manage_inactivity(true);
-		_progress = (_isbed) ? lcd_selftest_screen(testScreen::bed, _progress, 2, false, 400) : lcd_selftest_screen(testScreen::hotend, _progress, 2, false, 400);
+		_progress = (_isbed) ? lcd_selftest_screen(TestScreen::Bed, _progress, 2, false, 400) : lcd_selftest_screen(TestScreen::Hotend, _progress, 2, false, 400);
 		/*if (_isbed) {
 			MYSERIAL.print("Bed temp:");
 			MYSERIAL.println(degBed());
@@ -7625,12 +7671,12 @@ static bool lcd_selfcheck_check_heater(bool _isbed)
 		}
 		else
 		{
-			lcd_selftest_error(TestError::heater, "", "");
+			lcd_selftest_error(TestError::Heater, "", "");
 		}
 	}
 	else
 	{
-		lcd_selftest_error(TestError::bed, "", "");
+		lcd_selftest_error(TestError::Bed, "", "");
 	}
 
 	manage_heater();
@@ -7657,19 +7703,19 @@ static void lcd_selftest_error(TestError testError, const char *_error_1, const
 
 	switch (testError)
 	{
-	case TestError::heater:
+	case TestError::Heater:
 		lcd_set_cursor(0, 2);
 		lcd_puts_P(_i("Heater/Thermistor"));////MSG_SELFTEST_HEATERTHERMISTOR
 		lcd_set_cursor(0, 3);
 		lcd_puts_P(_i("Not connected"));////MSG_SELFTEST_NOTCONNECTED
 		break;
-	case TestError::bed:
+	case TestError::Bed:
 		lcd_set_cursor(0, 2);
 		lcd_puts_P(_i("Bed / Heater"));////MSG_SELFTEST_BEDHEATER
 		lcd_set_cursor(0, 3);
 		lcd_puts_P(_T(MSG_SELFTEST_WIRINGERROR));
 		break;
-	case TestError::endstops:
+	case TestError::Endstops:
 		lcd_set_cursor(0, 2);
 		lcd_puts_P(_i("Endstops"));////MSG_SELFTEST_ENDSTOPS
 		lcd_set_cursor(0, 3);
@@ -7677,7 +7723,7 @@ static void lcd_selftest_error(TestError testError, const char *_error_1, const
 		lcd_set_cursor(17, 3);
 		lcd_print(_error_1);
 		break;
-	case TestError::motor:
+	case TestError::Motor:
 		lcd_set_cursor(0, 2);
 		lcd_puts_P(_T(MSG_SELFTEST_MOTOR));
 		lcd_set_cursor(18, 2);
@@ -7687,7 +7733,7 @@ static void lcd_selftest_error(TestError testError, const char *_error_1, const
 		lcd_set_cursor(18, 3);
 		lcd_print(_error_2);
 		break;
-	case TestError::endstop:
+	case TestError::Endstop:
 		lcd_set_cursor(0, 2);
 		lcd_puts_P(_i("Endstop not hit"));////MSG_SELFTEST_ENDSTOP_NOTHIT c=20 r=1
 		lcd_set_cursor(0, 3);
@@ -7695,7 +7741,7 @@ static void lcd_selftest_error(TestError testError, const char *_error_1, const
 		lcd_set_cursor(18, 3);
 		lcd_print(_error_1);
 		break;
-	case TestError::printFan:
+	case TestError::PrintFan:
 		lcd_set_cursor(0, 2);
 		lcd_puts_P(_T(MSG_SELFTEST_COOLING_FAN));
 		lcd_set_cursor(0, 3);
@@ -7703,7 +7749,7 @@ static void lcd_selftest_error(TestError testError, const char *_error_1, const
 		lcd_set_cursor(18, 3);
 		lcd_print(_error_1);
 		break;
-	case TestError::extruderFan:
+	case TestError::ExtruderFan:
 		lcd_set_cursor(0, 2);
 		lcd_puts_P(_T(MSG_SELFTEST_EXTRUDER_FAN));
 		lcd_set_cursor(0, 3);
@@ -7711,7 +7757,7 @@ static void lcd_selftest_error(TestError testError, const char *_error_1, const
 		lcd_set_cursor(18, 3);
 		lcd_print(_error_1);
 		break;
-	case TestError::pulley:
+	case TestError::Pulley:
 		lcd_set_cursor(0, 2);
 		lcd_puts_P(_i("Loose pulley"));////MSG_LOOSE_PULLEY c=20 r=1
 		lcd_set_cursor(0, 3);
@@ -7719,7 +7765,7 @@ static void lcd_selftest_error(TestError testError, const char *_error_1, const
 		lcd_set_cursor(18, 3);
 		lcd_print(_error_1);
 		break;
-	case TestError::axis:
+	case TestError::Axis:
 		lcd_set_cursor(0, 2);
 		lcd_puts_P(_i("Axis length"));////MSG_SELFTEST_AXIS_LENGTH
 		lcd_set_cursor(0, 3);
@@ -7727,7 +7773,7 @@ static void lcd_selftest_error(TestError testError, const char *_error_1, const
 		lcd_set_cursor(18, 3);
 		lcd_print(_error_1);
 		break;
-	case TestError::swappedFan:
+	case TestError::SwappedFan:
 		lcd_set_cursor(0, 2);
 		lcd_puts_P(_i("Front/left fans"));////MSG_SELFTEST_FANS
 		lcd_set_cursor(0, 3);
@@ -7735,13 +7781,13 @@ static void lcd_selftest_error(TestError testError, const char *_error_1, const
 		lcd_set_cursor(18, 3);
 		lcd_print(_error_1);
 		break;
-	case TestError::wiringFsensor:
+	case TestError::WiringFsensor:
 		lcd_set_cursor(0, 2);
 		lcd_puts_P(_T(MSG_SELFTEST_FILAMENT_SENSOR));
 		lcd_set_cursor(0, 3);
 		lcd_puts_P(_T(MSG_SELFTEST_WIRINGERROR));
 		break;
-	case TestError::triggeringFsensor:
+	case TestError::TriggeringFsensor:
 	    lcd_set_cursor(0, 2);
         lcd_puts_P(_T(MSG_SELFTEST_FILAMENT_SENSOR));
         lcd_set_cursor(0, 3);
@@ -7770,7 +7816,7 @@ static bool lcd_selftest_fsensor(void)
 	fsensor_init();
 	if (fsensor_not_responding)
 	{
-		lcd_selftest_error(TestError::wiringFsensor, "", "");
+		lcd_selftest_error(TestError::WiringFsensor, "", "");
 	}
 	return (!fsensor_not_responding);
 }
@@ -7808,23 +7854,23 @@ static bool selftest_irsensor()
         TempBackup tempBackup;
         setTargetHotend(ABS_PREHEAT_HOTEND_TEMP,active_extruder);
         mmu_wait_for_heater_blocking();
-        progress = lcd_selftest_screen(testScreen::fsensor, 0, 1, true, 0);
+        progress = lcd_selftest_screen(TestScreen::Fsensor, 0, 1, true, 0);
         mmu_filament_ramming();
     }
-    progress = lcd_selftest_screen(testScreen::fsensor, progress, 1, true, 0);
+    progress = lcd_selftest_screen(TestScreen::Fsensor, progress, 1, true, 0);
     mmu_command(MmuCmd::U0);
     manage_response(false, false);
 
     for(uint_least8_t i = 0; i < 200; ++i)
     {
-        if (0 == (i % 32)) progress = lcd_selftest_screen(testScreen::fsensor, progress, 1, true, 0);
+        if (0 == (i % 32)) progress = lcd_selftest_screen(TestScreen::Fsensor, progress, 1, true, 0);
 
         mmu_load_step(false);
         while (blocks_queued())
         {
             if (PIN_GET(IR_SENSOR_PIN) == 0)
             {
-                lcd_selftest_error(TestError::triggeringFsensor, "", "");
+                lcd_selftest_error(TestError::TriggeringFsensor, "", "");
                 return false;
             }
 #ifdef TMC2130
@@ -7969,11 +8015,11 @@ static FanCheck lcd_selftest_fan_auto(int _fan)
 		printf_P(PSTR("Extr fan speed: %d \n"), fan_speed[0]);
 
 		if (!fan_speed[0]) {
-			return FanCheck::extruderFan;
+			return FanCheck::ExtruderFan;
 		}
 #ifdef FAN_SOFT_PWM
 		else if (fan_speed[0] > 50 ) { // printerFan is faster
-			return FanCheck::swappedFan;
+			return FanCheck::SwappedFan;
 		}
 		break;
 #endif
@@ -8008,7 +8054,7 @@ static FanCheck lcd_selftest_fan_auto(int _fan)
 		printf_P(PSTR("Print fan speed: %d \n"), fan_speed[1]);
 		printf_P(PSTR("Extr fan speed: %d \n"), fan_speed[0]);
 		if (!fan_speed[1]) {
-			return FanCheck::printFan;
+			return FanCheck::PrintFan;
 		}
 
 #ifdef FAN_SOFT_PWM
@@ -8027,23 +8073,23 @@ static FanCheck lcd_selftest_fan_auto(int _fan)
 
 		// noctua speed is between 17 and 24, turbine more then 30
 		if (fan_speed[1] < 30) {
-			return FanCheck::swappedFan;
+			return FanCheck::SwappedFan;
 		}
 #else
 		// fan is spinning, but measured RPM are too low for print fan, it must
 		// be left extruder fan
 		else if (fan_speed[1] < 34) {
-			return FanCheck::swappedFan;
+			return FanCheck::SwappedFan;
 		}
 #endif //FAN_SOFT_PWM
 		break;
 	}
-	return FanCheck::success;
+	return FanCheck::Success;
 }
 
 #endif //FANCHECK
 
-static int lcd_selftest_screen(testScreen screen, int _progress, int _progress_scale, bool _clear, int _delay)
+static int lcd_selftest_screen(TestScreen screen, int _progress, int _progress_scale, bool _clear, int _delay)
 {
 
     lcd_update_enable(false);
@@ -8055,58 +8101,58 @@ static int lcd_selftest_screen(testScreen screen, int _progress, int _progress_s
 
 	lcd_set_cursor(0, 0);
 
-	if (screen == testScreen::extruderFan) lcd_puts_P(_T(MSG_SELFTEST_FAN));
-	if (screen == testScreen::printFan) lcd_puts_P(_T(MSG_SELFTEST_FAN));
-	if (screen == testScreen::fansOk) lcd_puts_P(_T(MSG_SELFTEST_FAN));
-	if (screen == testScreen::endStops) lcd_puts_P(_i("Checking endstops"));////MSG_SELFTEST_CHECK_ENDSTOPS c=20
-	if (screen == testScreen::axisX) lcd_puts_P(_i("Checking X axis  "));////MSG_SELFTEST_CHECK_X c=20
-	if (screen == testScreen::axisY) lcd_puts_P(_i("Checking Y axis  "));////MSG_SELFTEST_CHECK_Y c=20
-	if (screen == testScreen::axisZ) lcd_puts_P(_i("Checking Z axis  "));////MSG_SELFTEST_CHECK_Z c=20
-	if (screen == testScreen::bed) lcd_puts_P(_T(MSG_SELFTEST_CHECK_BED));
-	if (screen == testScreen::hotend
-	    || screen == testScreen::hotendOk) lcd_puts_P(_i("Checking hotend  "));////MSG_SELFTEST_CHECK_HOTEND c=20
-	if (screen == testScreen::fsensor) lcd_puts_P(_T(MSG_SELFTEST_CHECK_FSENSOR));
-	if (screen == testScreen::fsensorOk) lcd_puts_P(_T(MSG_SELFTEST_CHECK_FSENSOR));
-	if (screen == testScreen::allCorrect) lcd_puts_P(_i("All correct      "));////MSG_SELFTEST_CHECK_ALLCORRECT c=20
-	if (screen == testScreen::failed) lcd_puts_P(_T(MSG_SELFTEST_FAILED));
-	if (screen == testScreen::home) lcd_puts_P(_i("Calibrating home"));////c=20 r=1
+	if (screen == TestScreen::ExtruderFan) lcd_puts_P(_T(MSG_SELFTEST_FAN));
+	if (screen == TestScreen::PrintFan) lcd_puts_P(_T(MSG_SELFTEST_FAN));
+	if (screen == TestScreen::FansOk) lcd_puts_P(_T(MSG_SELFTEST_FAN));
+	if (screen == TestScreen::EndStops) lcd_puts_P(_i("Checking endstops"));////MSG_SELFTEST_CHECK_ENDSTOPS c=20
+	if (screen == TestScreen::AxisX) lcd_puts_P(_i("Checking X axis  "));////MSG_SELFTEST_CHECK_X c=20
+	if (screen == TestScreen::AxisY) lcd_puts_P(_i("Checking Y axis  "));////MSG_SELFTEST_CHECK_Y c=20
+	if (screen == TestScreen::AxisZ) lcd_puts_P(_i("Checking Z axis  "));////MSG_SELFTEST_CHECK_Z c=20
+	if (screen == TestScreen::Bed) lcd_puts_P(_T(MSG_SELFTEST_CHECK_BED));
+	if (screen == TestScreen::Hotend
+	    || screen == TestScreen::HotendOk) lcd_puts_P(_i("Checking hotend  "));////MSG_SELFTEST_CHECK_HOTEND c=20
+	if (screen == TestScreen::Fsensor) lcd_puts_P(_T(MSG_SELFTEST_CHECK_FSENSOR));
+	if (screen == TestScreen::FsensorOk) lcd_puts_P(_T(MSG_SELFTEST_CHECK_FSENSOR));
+	if (screen == TestScreen::AllCorrect) lcd_puts_P(_i("All correct      "));////MSG_SELFTEST_CHECK_ALLCORRECT c=20
+	if (screen == TestScreen::Failed) lcd_puts_P(_T(MSG_SELFTEST_FAILED));
+	if (screen == TestScreen::Home) lcd_puts_P(_i("Calibrating home"));////c=20 r=1
 
 	lcd_set_cursor(0, 1);
 	lcd_puts_P(separator);
-	if ((screen >= testScreen::extruderFan) && (screen <= testScreen::fansOk))
+	if ((screen >= TestScreen::ExtruderFan) && (screen <= TestScreen::FansOk))
 	{
 		//SERIAL_ECHOLNPGM("Fan test");
 		lcd_puts_at_P(0, 2, _i("Extruder fan:"));////MSG_SELFTEST_EXTRUDER_FAN_SPEED c=18
 		lcd_set_cursor(18, 2);
-		(screen < testScreen::printFan) ? lcd_print(_indicator) : lcd_print("OK");
+		(screen < TestScreen::PrintFan) ? lcd_print(_indicator) : lcd_print("OK");
 		lcd_puts_at_P(0, 3, _i("Print fan:"));////MSG_SELFTEST_PRINT_FAN_SPEED c=18
 		lcd_set_cursor(18, 3);
-		(screen < testScreen::fansOk) ? lcd_print(_indicator) : lcd_print("OK");
+		(screen < TestScreen::FansOk) ? lcd_print(_indicator) : lcd_print("OK");
 	}
-	else if (screen >= testScreen::fsensor && screen <= testScreen::fsensorOk)
+	else if (screen >= TestScreen::Fsensor && screen <= TestScreen::FsensorOk)
 	{
 		lcd_puts_at_P(0, 2, _T(MSG_SELFTEST_FILAMENT_SENSOR));
 		lcd_putc(':');
 		lcd_set_cursor(18, 2);
-		(screen == testScreen::fsensor) ? lcd_print(_indicator) : lcd_print("OK");
+		(screen == TestScreen::Fsensor) ? lcd_print(_indicator) : lcd_print("OK");
 	}
-	else if (screen < testScreen::fsensor)
+	else if (screen < TestScreen::Fsensor)
 	{
 		//SERIAL_ECHOLNPGM("Other tests");
 
-	    testScreen _step_block = testScreen::axisX;
+	    TestScreen _step_block = TestScreen::AxisX;
 		lcd_selftest_screen_step(2, 2, ((screen == _step_block) ? 1 : (screen < _step_block) ? 0 : 2), "X", _indicator);
 
-		_step_block = testScreen::axisY;
+		_step_block = TestScreen::AxisY;
 		lcd_selftest_screen_step(2, 8, ((screen == _step_block) ? 1 : (screen < _step_block) ? 0 : 2), "Y", _indicator);
 
-		_step_block = testScreen::axisZ;
+		_step_block = TestScreen::AxisZ;
 		lcd_selftest_screen_step(2, 14, ((screen == _step_block) ? 1 : (screen < _step_block) ? 0 : 2), "Z", _indicator);
 
-		_step_block = testScreen::bed;
+		_step_block = TestScreen::Bed;
 		lcd_selftest_screen_step(3, 0, ((screen == _step_block) ? 1 : (screen < _step_block) ? 0 : 2), "Bed", _indicator);
 
-        _step_block = testScreen::hotend;
+        _step_block = TestScreen::Hotend;
         lcd_selftest_screen_step(3, 9, ((screen == _step_block) ? 1 : (screen < _step_block) ? 0 : 2), "Hotend", _indicator);
 	}
 
@@ -8477,5 +8523,5 @@ void menu_lcd_lcdupdate_func(void)
 	if (!SdFatUtil::test_stack_integrity()) stack_error();
 	lcd_ping(); //check that we have received ping command if we are in farm mode
 	lcd_send_status();
-	if (lcd_commands_type == LCD_COMMAND_V2_CAL) lcd_commands();
+	if (lcd_commands_type == LcdCommands::Layer1Cal) lcd_commands();
 }

+ 35 - 28
Firmware/ultralcd.h

@@ -89,31 +89,37 @@ extern void lcd_diag_show_end_stops();
 
 
 // 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_PID_EXTRUDER 7 
-#define LCD_COMMAND_V2_CAL 8
-
-extern uint8_t lcd_commands_type;
+enum class LcdCommands : uint_least8_t
+{
+	Idle,
+	LoadFilament,
+	StopPrint,
+	FarmModeConfirm,
+	LongPause,
+	PidExtruder,
+	Layer1Cal,
+};
+
+extern LcdCommands lcd_commands_type;
 extern int8_t FSensorStateMenu;
 
-#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
+enum class CustomMsg : uint_least8_t
+{
+	Status,          //!< status message from lcd_status_message variable
+	MeshBedLeveling, //!< Mesh bed leveling in progress
+	FilamentLoading, //!< Loading filament in progress
+	PidCal,          //!< PID tuning in progress
+	TempCal,         //!< PINDA temperature calibration
+	TempCompPreheat, //!< Temperature compensation preheat
+};
 
-extern unsigned int custom_message_type;
+extern CustomMsg 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;
+extern uint8_t farm_status;
 
 #ifdef TMC2130
 #define SILENT_MODE_NORMAL 0
@@ -148,18 +154,19 @@ void extr_unload_used();
 #endif //SNMM
 void extr_unload();
 
-typedef enum
+enum class FilamentAction : uint_least8_t
 {
-    e_FILAMENT_ACTION_none,                       //!< 'none' state is used as flag for (filament) autoLoad (i.e. opposite for 'autoLoad' state)
-    e_FILAMENT_ACTION_Load,
-    e_FILAMENT_ACTION_autoLoad,
-    e_FILAMENT_ACTION_unLoad,
-    e_FILAMENT_ACTION_mmuLoad,
-    e_FILAMENT_ACTION_mmuUnLoad,
-    e_FILAMENT_ACTION_mmuEject,
-    e_FILAMENT_ACTION_mmuCut
-} eFILAMENT_ACTION;
-extern eFILAMENT_ACTION eFilamentAction;
+    None, //!< 'none' state is used as flag for (filament) autoLoad (i.e. opposite for 'autoLoad' state)
+    Load,
+    AutoLoad,
+    UnLoad,
+    MmuLoad,
+    MmuUnLoad,
+    MmuEject,
+    MmuCut,
+};
+
+extern FilamentAction eFilamentAction;
 extern bool bFilamentFirstRun;
 extern bool bFilamentPreheatState;
 extern bool bFilamentAction;

+ 1 - 1
Firmware/util.cpp

@@ -304,7 +304,7 @@ if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
         _tone(BEEPER, 1000);
         delay_keep_alive(50);
         _noTone(BEEPER);
-        lcd_wait_for_click();
+        lcd_wait_for_click_delay(30);
         lcd_update_enable(true);
         lcd_clear();
         lcd_update(0);

+ 2 - 2
PF-build.sh

@@ -426,14 +426,14 @@ do
 		sleep 2
 		#$BUILDER -dump-prefs -logger=machine -hardware $ARDUINO/hardware -hardware $ARDUINO/portable/packages -tools $ARDUINO/tools-builder -tools $ARDUINO/hardware/tools/avr -tools $ARDUINO/portable/packages -built-in-libraries $ARDUINO/libraries -libraries $ARDUINO/portable/sketchbook/libraries -fqbn=rambo:avr:rambo -ide-version=10805 -build-path=$BUILD_PATH -warnings=none -quiet $SCRIPT_PATH/Firmware/Firmware.ino || exit 12
 		#$BUILDER -compile -logger=machine -hardware $ARDUINO/hardware -hardware $ARDUINO/portable/packages -tools $ARDUINO/tools-builder -tools $ARDUINO/hardware/tools/avr -tools $ARDUINO/portable/packages -built-in-libraries $ARDUINO/libraries -libraries $ARDUINO/portable/sketchbook/libraries -fqbn=rambo:avr:rambo -ide-version=10805 -build-path=$BUILD_PATH -warnings=none -quiet $SCRIPT_PATH/Firmware/Firmware.ino || exit 13
-		$BUILDER -compile -hardware $ARDUINO/hardware -hardware $ARDUINO/portable/packages -tools $ARDUINO/tools-builder -tools $ARDUINO/hardware/tools/avr -tools $ARDUINO/portable/packages -built-in-libraries $ARDUINO/libraries -libraries $ARDUINO/portable/sketchbook/libraries -fqbn=rambo:avr:rambo -ide-version=10805 -build-path=$BUILD_PATH -warnings=default $SCRIPT_PATH/Firmware/Firmware.ino || exit 14
+		$BUILDER -compile -hardware $ARDUINO/hardware -hardware $ARDUINO/portable/packages -tools $ARDUINO/tools-builder -tools $ARDUINO/hardware/tools/avr -tools $ARDUINO/portable/packages -built-in-libraries $ARDUINO/libraries -libraries $ARDUINO/portable/sketchbook/libraries -fqbn=rambo:avr:rambo -ide-version=10805 -build-path=$BUILD_PATH -warnings=all $SCRIPT_PATH/Firmware/Firmware.ino || exit 14
 		echo "$(tput sgr 0)"
 	fi
 	if [ $OSTYPE == "linux-gnu" ] ; then
 		echo "Start to build Prusa Firmware under Linux 64..."
 		echo "Using variant $VARIANT$(tput setaf 3)"
 		sleep 2
-		$BUILD_ENV_PATH/arduino $SCRIPT_PATH/Firmware/Firmware.ino --verify --board rambo:avr:rambo --pref build.path=$BUILD_PATH || exit 14
+		$BUILD_ENV_PATH/arduino $SCRIPT_PATH/Firmware/Firmware.ino --verify --board rambo:avr:rambo --pref build.path=$BUILD_PATH --pref compiler.warning_level=all || exit 14
 		echo "$(tput sgr 0)"
 	fi
 

+ 7 - 7
README.md

@@ -14,8 +14,8 @@
 
 # Build
 ## Linux
-Run shell script build.sh to build for MK3 and flash with Sli3er.  
-If you have different printel model, follow step [2.b](#2b) from Windows build first.  
+Run shell script build.sh to build for MK3 and flash with Slic3er.  
+If you have a different printer model, follow step [2.b](#2b) from Windows build first.  
 If you wish to flash from Arduino, follow step [2.c](#2c) from Windows build first.  
 
 The script downloads Arduino with our modifications and Rambo board support installed, unpacks it into folder PF-build-env-\<version\> on the same level, as your Prusa-Firmware folder is located, builds firmware for MK3 using that Arduino in Prusa-Firmware-build folder on the same level as Prusa-Firmware, runs secondary language support scripts. Firmware with secondary language support is generated in lang subfolder. Use firmware.hex for MK3 variant. Use firmware_\<lang\>.hex for other printers. Don't forget to follow step [2.b](#2b) first for non-MK3 printers.
@@ -40,11 +40,11 @@ type location
 or you can 'manually' modify the item  
 `"boardsmanager.additional.urls=....."`  
 at the file `"preferences.txt"` (this parameter allows you to write a comma-separated list of addresses)  
-_note: you can find location of this file on your disk by following way:  
+_note: you can find location of this file on your disk by doing the following:  
 `File->Preferences->Settings`  (`"More preferences can be edited in file ..."`)_  
-than do it  
+then choose 
 `Tools->Board->BoardsManager`  
-from viewed list select an item `"RAMBo"` (will probably be labeled as `"RepRap Arduino-compatible Mother Board (RAMBo) by UltiMachine"`  
+from viewed list and select the item labeled `"RAMBo"` (will probably be labeled as `"RepRap Arduino-compatible Mother Board (RAMBo) by UltiMachine"`  
 _note: select this item for any variant of board used in printers `'Prusa i3 MKx'`, that is for `RAMBo-mini x.y` and `EINSy x.y` to_  
 'clicking' the item will display the installation button; select choice `"1.0.1"` from the list(last known version as of the date of issue of this document)  
 _(after installation, the item is labeled as `"INSTALLED"` and can then be used for target board selection)_  
@@ -66,7 +66,7 @@ b.<a name="2b"></a> In the subdirectory `"Firmware/variants/"` select the config
 
 c.<a name="2c"></a> In file `"Firmware/config.h"` set LANG_MODE to 0.
 
-run `"Arduino IDE"`; select the file `"Firmware.ino"` from the subdirectory `"Firmware/"` at the location, where you placed the source codes  
+run `"Arduino IDE"`; select the file `"Firmware.ino"` from the subdirectory `"Firmware/"` at the location, where you placed the source code  
 `File->Open`  
 make the desired code customizations; **all changes are on your own risk!**  
 
@@ -146,7 +146,7 @@ cmake
 build system - ninja or gnu make
 
 ## Building
-Create folder where you want to build tests.
+Create a folder where you want to build tests.
 
 Example:
 

+ 2 - 2
build.sh

@@ -1,5 +1,5 @@
 #!/bin/bash 
-BUILD_ENV="1.0.2"
+BUILD_ENV="1.0.6"
 SCRIPT_PATH="$( cd "$(dirname "$0")" ; pwd -P )"
 
 if [ ! -d "build-env" ]; then
@@ -31,7 +31,7 @@ if [ ! -f "$SCRIPT_PATH/Firmware/Configuration_prusa.h" ]; then
     cp $SCRIPT_PATH/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h $SCRIPT_PATH/Firmware/Configuration_prusa.h || exit 8
 fi
 
-$BUILD_ENV_PATH/arduino $SCRIPT_PATH/Firmware/Firmware.ino --verify --board rambo:avr:rambo --pref build.path=$BUILD_PATH --pref compiler.warning_level=all || exit 9
+$BUILD_ENV_PATH/arduino $SCRIPT_PATH/Firmware/Firmware.ino --verify --board PrusaResearchRambo:avr:rambo --pref build.path=$BUILD_PATH --pref compiler.warning_level=all || exit 9
 
 export ARDUINO=$BUILD_ENV_PATH
 

+ 1 - 1
lang/lang-build.sh

@@ -82,7 +82,7 @@ generate_binary()
  rm -f lang_$1.dat
  LNG=$1
  #check lang dictionary
- /usr/bin/env python lang-check.py $1
+ /usr/bin/env python lang-check.py $1 --no-warning
  #create lang_xx.tmp - different processing for 'en' language
  if [ "$1" = "en" ]; then
   #remove comments and empty lines

+ 2 - 2
lang/lang-check.py

@@ -38,7 +38,7 @@ def parse_txt(lang, no_warning):
             if rows is None:
                 rows = 1
 
-            if len(translation) > cols*rows:
+            if len(translation)-2 > cols*rows:
                 stderr.write(
                     "[E]: Text %s is longer then definiton on line %d\n" %
                     (translation, lines))
@@ -56,7 +56,7 @@ def main():
         usage="$(prog)s lang")
     parser.add_argument(
         "lang", nargs='?', default="en", type=str,
-        help="Check lang file (en|cs|de|es|fr|it)")
+        help="Check lang file (en|cs|de|es|fr|it|pl)")
     parser.add_argument(
         "--no-warning", action="store_true",
         help="Disable warnings")