Procházet zdrojové kódy

Merge branch 'MK3' into use_Timer

Marek Bel před 6 roky
rodič
revize
fc657bc31e

+ 2 - 2
Firmware/Configuration.h

@@ -7,8 +7,8 @@
 #define STR(x) STR_HELPER(x)
 
 // Firmware version
-#define FW_VERSION "3.2.1"
-#define FW_COMMIT_NR   576
+#define FW_VERSION "3.3.0"
+#define FW_COMMIT_NR   830
 // 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

+ 7 - 2
Firmware/Marlin.h

@@ -229,13 +229,18 @@ bool IsStopped();
 
 //put an ASCII command at the end of the current buffer.
 void enquecommand(const char *cmd, bool from_progmem = false);
+
 //put an ASCII command at the end of the current buffer, read from flash
 #define enquecommand_P(cmd) enquecommand(cmd, true)
+
+//put an ASCII command at the begin of the current buffer
 void enquecommand_front(const char *cmd, bool from_progmem = false);
-//put an ASCII command at the end of the current buffer, read from flash
-#define enquecommand_P(cmd) enquecommand(cmd, true)
+
+//put an ASCII command at the begin of the current buffer, read from flash
 #define enquecommand_front_P(cmd) enquecommand_front(cmd, true)
+
 void repeatcommand_front();
+
 // Remove all lines from the command queue.
 void cmdqueue_reset();
 

+ 175 - 29
Firmware/Marlin_main.cpp

@@ -71,6 +71,7 @@
 #include "math.h"
 #include "util.h"
 #include "Timer.h"
+#include "uart2.h"
 
 #include <avr/wdt.h>
 #include <avr/pgmspace.h>
@@ -528,6 +529,7 @@ static float saved_pos[4] = { 0, 0, 0, 0 };
 static float saved_feedrate2 = 0;
 static uint8_t saved_active_extruder = 0;
 static bool saved_extruder_under_pressure = false;
+static bool saved_extruder_relative_mode = false;
 
 //===========================================================================
 //=============================Routines======================================
@@ -663,12 +665,12 @@ void crashdet_disable()
 
 void crashdet_stop_and_save_print()
 {
-	stop_and_save_print_to_ram(10, -2); //XY - no change, Z 10mm up, E -2mm retract
+	stop_and_save_print_to_ram(10, -DEFAULT_RETRACTION); //XY - no change, Z 10mm up, E -1mm retract
 }
 
 void crashdet_restore_print_and_continue()
 {
-	restore_print_from_ram_and_continue(2); //XYZ = orig, E +2mm unretract
+	restore_print_from_ram_and_continue(DEFAULT_RETRACTION); //XYZ = orig, E +1mm unretract
 //	babystep_apply();
 }
 
@@ -847,6 +849,15 @@ void factory_reset(char level, bool quiet)
 			farm_mode = false;
 			eeprom_update_byte((uint8_t*)EEPROM_FARM_MODE, farm_mode);
             EEPROM_save_B(EEPROM_FARM_NUMBER, &farm_no);
+
+            eeprom_update_dword((uint32_t *)EEPROM_TOTALTIME, 0);
+            eeprom_update_dword((uint32_t *)EEPROM_FILAMENTUSED, 0);
+            eeprom_update_word((uint16_t *)EEPROM_CRASH_COUNT_X_TOT, 0);
+            eeprom_update_word((uint16_t *)EEPROM_CRASH_COUNT_Y_TOT, 0);
+            eeprom_update_word((uint16_t *)EEPROM_FERROR_COUNT_TOT, 0);
+            eeprom_update_word((uint16_t *)EEPROM_POWER_COUNT_TOT, 0);
+
+            fsensor_enable();
                        
             WRITE(BEEPER, HIGH);
             _delay_ms(100);
@@ -1113,7 +1124,7 @@ uint8_t lang_xflash_enum_codes(uint16_t* codes)
 		printf_P(_n(" _lt_count        = 0x%04x (%d)\n"), header.count, header.count);
 		printf_P(_n(" _lt_chsum        = 0x%04x\n"), header.checksum);
 		printf_P(_n(" _lt_code         = 0x%04x (%c%c)\n"), header.code, header.code >> 8, header.code & 0xff);
-		printf_P(_n(" _lt_resv1        = 0x%08lx\n"), header.reserved1);
+		printf_P(_n(" _lt_sign         = 0x%08lx\n"), header.signature);
 
 		addr += header.size;
 		codes[count] = header.code;
@@ -1173,11 +1184,19 @@ void setup()
 	selectedSerialPort = eeprom_read_byte((uint8_t*)EEPROM_SECOND_SERIAL_ACTIVE);
 	if (selectedSerialPort == 0xFF) selectedSerialPort = 0;
 	if (farm_mode)
-	{ 
+	{
 		no_response = true; //we need confirmation by recieving PRUSA thx
 		important_status = 8;
 		prusa_statistics(8);
 		selectedSerialPort = 1;
+#ifdef TMC2130
+		//increased extruder current (PFW363)
+		tmc2130_current_h[E_AXIS] = 36;
+		tmc2130_current_r[E_AXIS] = 36;
+#endif //TMC2130
+		//disabled filament autoload (PFW360)
+		filament_autoload_enabled = false;
+		eeprom_update_byte((uint8_t*)EEPROM_FSENS_AUTOLOAD_ENABLED, 0);
 	}
 	MYSERIAL.begin(BAUDRATE);
 	fdev_setup_stream(uartout, uart_putchar, NULL, _FDEV_SETUP_WRITE); //setup uart out stream
@@ -1186,11 +1205,13 @@ void setup()
 	SERIAL_ECHO_START;
 	printf_P(PSTR(" " FW_VERSION_FULL "\n"));
 
+	uart2_init();
+
 
 #ifdef DEBUG_SEC_LANG
 	lang_table_header_t header;
 	uint32_t src_addr = 0x00000;
-	if (lang_get_header(3, &header, &src_addr))
+	if (lang_get_header(1, &header, &src_addr))
 	{
 //this is comparsion of some printing-methods regarding to flash space usage and code size/readability
 #define LT_PRINT_TEST 2
@@ -1207,7 +1228,7 @@ void setup()
 		printf_P(_n(" _lt_count = 0x%04x (%d)\n"), header.count, header.count);
 		printf_P(_n(" _lt_chsum = 0x%04x\n"), header.checksum);
 		printf_P(_n(" _lt_code  = 0x%04x (%c%c)\n"), header.code, header.code >> 8, header.code & 0xff);
-		printf_P(_n(" _lt_resv1 = 0x%08lx\n"), header.reserved1);
+		printf_P(_n(" _lt_sign = 0x%08lx\n"), header.signature);
 #elif (LT_PRINT_TEST==2) //optimized printf
 		printf_P(
 		 _n(
@@ -1225,7 +1246,7 @@ void setup()
 		 header.count, header.count,
 		 header.checksum,
 		 header.code, header.code >> 8, header.code & 0xff,
-		 header.reserved1
+		 header.signature
 		);
 #elif (LT_PRINT_TEST==3) //arduino print/println (leading zeros not solved)
 		MYSERIAL.print(" _src_addr = 0x");
@@ -1252,7 +1273,7 @@ void setup()
 		MYSERIAL.print((char)(header.code & 0xff), 0);
 		MYSERIAL.println(")");
 		MYSERIAL.print(" _lt_resv1 = 0x");
-		MYSERIAL.println(header.reserved1, 16);
+		MYSERIAL.println(header.signature, 16);
 #endif //(LT_PRINT_TEST==)
 #undef LT_PRINT_TEST
 
@@ -1265,7 +1286,22 @@ void setup()
 			if ((i % 16) == 15) putchar('\n');
 		}
 #endif
-#if 1
+		uint16_t sum = 0;
+		for (uint16_t i = 0; i < header.size; i++)
+			sum += (uint16_t)pgm_read_byte((uint8_t*)(_SEC_LANG_TABLE + i)) << ((i & 1)?0:8);
+		printf_P(_n("_SEC_LANG_TABLE checksum = %04x\n"), sum);
+		sum -= header.checksum; //subtract checksum
+		printf_P(_n("_SEC_LANG_TABLE checksum = %04x\n"), sum);
+		sum = (sum >> 8) | ((sum & 0xff) << 8); //swap bytes
+		if (sum == header.checksum)
+			printf_P(_n("Checksum OK\n"), sum);
+		else
+			printf_P(_n("Checksum NG\n"), sum);
+	}
+	else
+		printf_P(_n("lang_get_header failed!\n"));
+
+#if 0
 		for (uint16_t i = 0; i < 1024*10; i++)
 		{
 			if ((i % 16) == 0) printf_P(_n("%04x:"), _SEC_LANG_TABLE+i);
@@ -1273,10 +1309,6 @@ void setup()
 			if ((i % 16) == 15) putchar('\n');
 		}
 #endif
-	}
-	else
-		printf_P(_n("lang_get_header failed!\n"));
-
 
 #if 0
 	SERIAL_ECHOLN("Reading eeprom from 0 to 100: start");
@@ -3222,16 +3254,59 @@ void process_commands()
 	}
 	else if (strncmp_P(CMDBUFFER_CURRENT_STRING, PSTR("TMC_"), 4) == 0)
 	{
-		if (strncmp_P(CMDBUFFER_CURRENT_STRING + 4, PSTR("SET_WAVE_E"), 10) == 0)
+		if (strncmp_P(CMDBUFFER_CURRENT_STRING + 4, PSTR("SET_WAVE_"), 9) == 0)
+		{
+			uint8_t axis = *(CMDBUFFER_CURRENT_STRING + 13);
+			axis = (axis == 'E')?3:(axis - 'X');
+			if (axis < 4)
+			{
+				uint8_t fac = (uint8_t)strtol(CMDBUFFER_CURRENT_STRING + 14, NULL, 10);
+				tmc2130_set_wave(axis, 247, fac);
+			}
+		}
+		else if (strncmp_P(CMDBUFFER_CURRENT_STRING + 4, PSTR("SET_STEP_"), 9) == 0)
 		{
-			uint8_t fac = (uint8_t)strtol(CMDBUFFER_CURRENT_STRING + 14, NULL, 10);
-			tmc2130_set_wave(E_AXIS, 247, fac);
+			uint8_t axis = *(CMDBUFFER_CURRENT_STRING + 13);
+			axis = (axis == 'E')?3:(axis - 'X');
+			if (axis < 4)
+			{
+				uint8_t step = (uint8_t)strtol(CMDBUFFER_CURRENT_STRING + 14, NULL, 10);
+				uint16_t res = tmc2130_get_res(axis);
+				tmc2130_goto_step(axis, step & (4*res - 1), 2, 1000, res);
+			}
 		}
-		else if (strncmp_P(CMDBUFFER_CURRENT_STRING + 4, PSTR("SET_STEP_E"), 10) == 0)
+		else if (strncmp_P(CMDBUFFER_CURRENT_STRING + 4, PSTR("SET_CHOP_"), 9) == 0)
 		{
-			uint8_t step = (uint8_t)strtol(CMDBUFFER_CURRENT_STRING + 14, NULL, 10);
-			uint16_t res = tmc2130_get_res(E_AXIS);
-			tmc2130_goto_step(E_AXIS, step & (4*res - 1), 2, 1000, res);
+			uint8_t axis = *(CMDBUFFER_CURRENT_STRING + 13);
+			axis = (axis == 'E')?3:(axis - 'X');
+			if (axis < 4)
+			{
+				uint8_t chop0 = tmc2130_chopper_config[axis].toff;
+				uint8_t chop1 = tmc2130_chopper_config[axis].hstr;
+				uint8_t chop2 = tmc2130_chopper_config[axis].hend;
+				uint8_t chop3 = tmc2130_chopper_config[axis].tbl;
+				char* str_end = 0;
+				if (CMDBUFFER_CURRENT_STRING[14])
+				{
+					chop0 = (uint8_t)strtol(CMDBUFFER_CURRENT_STRING + 14, &str_end, 10) & 15;
+					if (str_end && *str_end)
+					{
+						chop1 = (uint8_t)strtol(str_end, &str_end, 10) & 7;
+						if (str_end && *str_end)
+						{
+							chop2 = (uint8_t)strtol(str_end, &str_end, 10) & 15;
+							if (str_end && *str_end)
+								chop3 = (uint8_t)strtol(str_end, &str_end, 10) & 3;
+						}
+					}
+				}
+				tmc2130_chopper_config[axis].toff = chop0;
+				tmc2130_chopper_config[axis].hstr = chop1 & 7;
+				tmc2130_chopper_config[axis].hend = chop2 & 15;
+				tmc2130_chopper_config[axis].tbl = chop3 & 3;
+				tmc2130_setup_chopper(axis, tmc2130_mres[axis], tmc2130_current_h[axis], tmc2130_current_r[axis]);
+				//printf_P(_N("TMC_SET_CHOP_%c %hhd %hhd %hhd %hhd\n"), "xyze"[axis], chop0, chop1, chop2, chop3);
+			}
 		}
 	}
 #endif //TMC2130
@@ -3259,6 +3334,20 @@ void process_commands()
 		}
 		else if (code_seen("thx")) {
 			no_response = false;
+        } else if (code_seen("RESET")) {
+            // careful!
+            if (farm_mode) {
+#ifdef WATCHDOG
+				wdt_enable(WDTO_15MS);
+				cli();
+				while(1);
+#else //WATCHDOG
+                asm volatile("jmp 0x3E000");
+#endif //WATCHDOG
+            }
+            else {
+                MYSERIAL.println("Not in farm mode.");
+            }
 		}else if (code_seen("fv")) {
         // get file version
         #ifdef SDSUPPORT
@@ -4377,6 +4466,7 @@ void process_commands()
 		}
 		KEEPALIVE_STATE(NOT_BUSY);
 		// Restore custom message state
+		lcd_setstatuspgm(_T(WELCOME_MSG));
 		custom_message = custom_message_old;
 		custom_message_type = custom_message_type_old;
 		custom_message_state = custom_message_state_old;
@@ -6986,6 +7076,45 @@ Sigma_Exit:
 			  tmp_extruder = code_value();
 		  }
 		  snmm_filaments_used |= (1 << tmp_extruder); //for stop print
+
+#ifdef SNMM_V2
+		  printf_P(PSTR("T code: %d \n"), tmp_extruder);
+          switch (tmp_extruder) 
+          {
+          case 1:
+              
+              fprintf_P(uart2io, PSTR("T1\n"));
+              break;
+          case 2:
+              
+              fprintf_P(uart2io, PSTR("T2\n"));
+              break;
+          case 3:
+              
+              fprintf_P(uart2io, PSTR("T3\n"));
+              break;
+          case 4:
+              
+              fprintf_P(uart2io, PSTR("T4\n"));
+              break;
+          default:
+              
+              fprintf_P(uart2io, PSTR("T0\n"));
+              break;
+          }
+
+          
+
+          
+              // get response
+            uart2_rx_clr();
+              while (!uart2_rx_ok())
+              {
+                  //printf_P(PSTR("waiting..\n"));
+                  delay_keep_alive(100);
+              }
+#endif
+
 #ifdef SNMM
           
     #ifdef LIN_ADVANCE
@@ -7148,8 +7277,8 @@ void FlushSerialRequestResend()
 void ClearToSend()
 {
     previous_millis_cmd = millis();
-    if ((CMDBUFFER_CURRENT_TYPE == CMDBUFFER_CURRENT_TYPE_USB) || (CMDBUFFER_CURRENT_TYPE == CMDBUFFER_CURRENT_TYPE_USB_WITH_LINENR))
-        SERIAL_PROTOCOLLNRPGM(_T(MSG_OK));
+	if ((CMDBUFFER_CURRENT_TYPE == CMDBUFFER_CURRENT_TYPE_USB) || (CMDBUFFER_CURRENT_TYPE == CMDBUFFER_CURRENT_TYPE_USB_WITH_LINENR)) 
+		SERIAL_PROTOCOLLNRPGM(_T(MSG_OK));
 }
 
 #if MOTHERBOARD == BOARD_RAMBO_MINI_1_0 || MOTHERBOARD == BOARD_RAMBO_MINI_1_3
@@ -7297,6 +7426,7 @@ void clamp_to_software_endstops(float target[3])
             float de = e - current_position[E_AXIS];
             for (int i = 1; i < n_segments; ++ i) {
                 float t = float(i) / float(n_segments);
+                if (saved_printing || (mbl.active == false)) return;
                 plan_buffer_line(
                                  current_position[X_AXIS] + t * dx,
                                  current_position[Y_AXIS] + t * dy,
@@ -8792,11 +8922,11 @@ void stop_and_save_print_to_ram(float z_move, float e_move)
         uint16_t value;
     } sdlen_single;
     int _bufindr = bufindr;
-    for (int _buflen  = buflen; _buflen > 0; ++ iline) {
+	for (int _buflen  = buflen; _buflen > 0; ++ iline) {
         if (cmdbuffer[_bufindr] == CMDBUFFER_CURRENT_TYPE_SDCARD) {
             sdlen_single.lohi.lo = cmdbuffer[_bufindr + 1];
             sdlen_single.lohi.hi = cmdbuffer[_bufindr + 2];
-        }
+        }		 
         SERIAL_ECHOPGM("Buffer line (from buffer): ");
         MYSERIAL.print(int(iline), DEC);
         SERIAL_ECHOPGM(", type: ");
@@ -8807,7 +8937,6 @@ void stop_and_save_print_to_ram(float z_move, float e_move)
         MYSERIAL.println(cmdbuffer + _bufindr + CMDHDRSIZE);
 
         SERIAL_ECHOPGM("Buffer line (from file): ");
-        MYSERIAL.print(int(iline), DEC);
         MYSERIAL.println(int(iline), DEC);
         for (; sdlen_single.value > 0; -- sdlen_single.value)
           MYSERIAL.print(char(card.get()));
@@ -8840,7 +8969,7 @@ void stop_and_save_print_to_ram(float z_move, float e_move)
 	saved_active_extruder = active_extruder; //save active_extruder
 
 	saved_extruder_under_pressure = extruder_under_pressure; //extruder under pressure flag - currently unused
-
+	saved_extruder_relative_mode = axis_relative_modes[E_AXIS];
 	cmdqueue_reset(); //empty cmdqueue
 	card.sdprinting = false;
 //	card.closefile();
@@ -8854,10 +8983,16 @@ void stop_and_save_print_to_ram(float z_move, float e_move)
     char buf[48];
 
 	// First unretract (relative extrusion)
+	if(!saved_extruder_relative_mode){
+	  strcpy_P(buf, PSTR("M83"));
+	  enquecommand(buf, false);
+	}
+	
+	//retract 45mm/s
 	strcpy_P(buf, PSTR("G1 E"));
 	dtostrf(e_move, 6, 3, buf + strlen(buf));
 	strcat_P(buf, PSTR(" F"));
-	dtostrf(retract_feedrate*60, 8, 3, buf + strlen(buf));
+	dtostrf(2700, 8, 3, buf + strlen(buf));
 	enquecommand(buf, false);
 
 	// Then lift Z axis
@@ -8886,26 +9021,37 @@ void restore_print_from_ram_and_continue(float e_move)
 //	    current_position[axis] = st_get_position_mm(axis);
 	active_extruder = saved_active_extruder; //restore active_extruder
 	feedrate = saved_feedrate2; //restore feedrate
+	axis_relative_modes[E_AXIS] = saved_extruder_relative_mode;
 	float e = saved_pos[E_AXIS] - e_move;
 	plan_set_e_position(e);
-	plan_buffer_line(saved_pos[X_AXIS], saved_pos[Y_AXIS], saved_pos[Z_AXIS], saved_pos[E_AXIS], homing_feedrate[Z_AXIS]/13, active_extruder);
+	//first move print head in XY to the saved position:
+	plan_buffer_line(saved_pos[X_AXIS], saved_pos[Y_AXIS], current_position[Z_AXIS], saved_pos[E_AXIS] - e_move, homing_feedrate[Z_AXIS]/13, active_extruder);
+	st_synchronize();
+	//then move Z
+	plan_buffer_line(saved_pos[X_AXIS], saved_pos[Y_AXIS], saved_pos[Z_AXIS], saved_pos[E_AXIS] - e_move, homing_feedrate[Z_AXIS]/13, active_extruder);
 	st_synchronize();
+	//and finaly unretract (35mm/s)
+	plan_buffer_line(saved_pos[X_AXIS], saved_pos[Y_AXIS], saved_pos[Z_AXIS], saved_pos[E_AXIS], 35, active_extruder);
+	st_synchronize();
+
 	memcpy(current_position, saved_pos, sizeof(saved_pos));
 	memcpy(destination, current_position, sizeof(destination));
 	if (saved_printing_type == PRINTING_TYPE_SD) { //was sd printing
 		card.setIndex(saved_sdpos);
 		sdpos_atomic = saved_sdpos;
 		card.sdprinting = true;
+		printf_P(PSTR("ok\n")); //dummy response because of octoprint is waiting for this
 	}
 	else if (saved_printing_type == PRINTING_TYPE_USB) { //was usb printing
 		gcode_LastN = saved_sdpos; //saved_sdpos was reused for storing line number when usb printing
+		serial_count = 0; 
 		FlushSerialRequestResend();
 	}
 	else {
 		//not sd printing nor usb printing
 	}
+	lcd_setstatuspgm(_T(WELCOME_MSG));
 	saved_printing = false;
-	
 }
 
 void print_world_coordinates()

+ 2 - 1
Firmware/cmdqueue.cpp

@@ -385,7 +385,8 @@ void get_command()
 		rx_buffer_full = true;                //sets flag that buffer was full    
 	}
 
-  while (MYSERIAL.available() > 0) {
+  // start of serial line processing loop
+  while (MYSERIAL.available() > 0 && !saved_printing) {  //is print is saved (crash detection or filament detection), dont process data from serial line
 	
     char serial_char = MYSERIAL.read();
 /*    if (selectedSerialPort == 1)

+ 3 - 3
Firmware/config.h

@@ -27,9 +27,9 @@
 #define W25X20CL_SPSR          SPI_SPSR(W25X20CL_SPI_RATE)
 
 //LANG - Multi-language support
-//#define LANG_MODE               0 // primary language only
-#define LANG_MODE               1 // sec. language support
-#define LANG_SIZE_RESERVED 0x2700 // reserved space for secondary language (~10kb)
+//#define LANG_MODE                      0 // primary language only
+#define LANG_MODE                        1 // sec. language support
+#define LANG_SIZE_RESERVED          0x2400 // reserved space for secondary language (~12kb)
 //#define LANG_SIZE_RESERVED 0x1ef8 // reserved space for secondary language (~10kb)
 
 

+ 62 - 12
Firmware/language.c

@@ -5,6 +5,7 @@
 #include "bootapp.h"
 
 #include "Configuration.h"
+#include "pins.h"
 
 #ifdef W25X20CL
 #include "w25x20cl.h"
@@ -28,6 +29,9 @@ uint8_t lang_is_selected(void) { return 1; }
 //reserved xx kbytes for secondary language table
 const char _SEC_LANG[LANG_SIZE_RESERVED] PROGMEM_I2 = "_SEC_LANG";
 
+//primary language signature
+const uint32_t _PRI_LANG_SIGNATURE[1] __attribute__((section(".progmem0"))) = {0xffffffff};
+
 //lang_table pointer
 lang_table_t* lang_table = 0;
 
@@ -56,11 +60,28 @@ uint8_t lang_select(uint8_t lang)
 	{
 		if (pgm_read_dword(((uint32_t*)_SEC_LANG_TABLE)) == LANG_MAGIC) //magic valid
 		{
-			lang_table = _SEC_LANG_TABLE; // set table pointer
-			lang_selected = lang; // set language id
+			if (lang_check(_SEC_LANG_TABLE))
+				if (pgm_read_dword(((uint32_t*)(_SEC_LANG_TABLE + 12))) == pgm_read_dword(((uint32_t*)(_PRI_LANG_SIGNATURE)))) //signature valid
+				{
+					lang_table = _SEC_LANG_TABLE; // set table pointer
+					lang_selected = lang; // set language id
+				}
 		}
 	}
 #else //W25X20CL
+	if (lang == LANG_ID_SEC)
+	{
+		uint16_t table = _SEC_LANG_TABLE;
+		if (pgm_read_dword(((uint32_t*)table)) == LANG_MAGIC) //magic valid
+		{
+			if (lang_check(table))
+				if (pgm_read_dword(((uint32_t*)(table + 12))) == pgm_read_dword(((uint32_t*)(_PRI_LANG_SIGNATURE)))) //signature valid
+				{
+					lang_table = table; // set table pointer
+					lang_selected = lang; // set language id
+				}
+		}
+	}
 #endif //W25X20CL
 	if (lang_selected == lang)
 	{
@@ -70,8 +91,22 @@ uint8_t lang_select(uint8_t lang)
 	return 0;
 }
 
+uint8_t lang_check(uint16_t addr)
+{
+	uint16_t sum = 0;
+	uint16_t size = pgm_read_word((uint16_t*)(addr + 4));
+	uint16_t lt_sum = pgm_read_word((uint16_t*)(addr + 8));
+	uint16_t i; for (i = 0; i < size; i++)
+		sum += (uint16_t)pgm_read_byte((uint8_t*)(addr + i)) << ((i & 1)?0:8);
+	sum -= lt_sum; //subtract checksum
+	sum = (sum >> 8) | ((sum & 0xff) << 8); //swap bytes
+	return (sum == lt_sum);
+}
+
 uint8_t lang_get_count()
 {
+	if (pgm_read_dword(((uint32_t*)(_PRI_LANG_SIGNATURE))) == 0xffffffff)
+		return 1; //signature not set - only primary language will be available
 #ifdef W25X20CL
 	W25X20CL_SPI_ENTER();
 	uint8_t count = 2; //count = 1+n (primary + secondary + all in xflash)
@@ -84,9 +119,16 @@ uint8_t lang_get_count()
 		addr += header.size; //calc address of next table
 		count++; //inc counter
 	}
-	return count;
 #else //W25X20CL
+	uint16_t table = _SEC_LANG_TABLE;
+	uint8_t count = 1; //count = 1 (primary)
+	while (pgm_read_dword(((uint32_t*)table)) == LANG_MAGIC) //magic valid
+	{
+		table += pgm_read_word((uint16_t*)(table + 4));
+		count++;
+	}
 #endif //W25X20CL
+	return count;
 }
 
 uint8_t lang_get_header(uint8_t lang, lang_table_header_t* header, uint32_t* offset)
@@ -98,7 +140,7 @@ uint8_t lang_get_header(uint8_t lang, lang_table_header_t* header, uint32_t* off
 		uint16_t ui = _SEC_LANG_TABLE; //table pointer
 		memcpy_P(header, ui, sizeof(lang_table_header_t)); //read table header from progmem
 		if (offset) *offset = ui;
-		return (header == LANG_MAGIC)?1:0; //return 1 if magic valid
+		return (header->magic == LANG_MAGIC)?1:0; //return 1 if magic valid
 	}
 	W25X20CL_SPI_ENTER();
 	uint32_t addr = 0x00000; //start of xflash
@@ -111,9 +153,16 @@ uint8_t lang_get_header(uint8_t lang, lang_table_header_t* header, uint32_t* off
 		if (--lang == 0) return 1;
 		addr += header->size; //calc address of next table
 	}
-	return 0;
 #else //W25X20CL
+	if (lang == LANG_ID_SEC)
+	{
+		uint16_t ui = _SEC_LANG_TABLE; //table pointer
+		memcpy_P(header, ui, sizeof(lang_table_header_t)); //read table header from progmem
+		if (offset) *offset = ui;
+		return (header->magic == LANG_MAGIC)?1:0; //return 1 if magic valid
+	}
 #endif //W25X20CL
+	return 0;
 }
 
 uint16_t lang_get_code(uint8_t lang)
@@ -138,14 +187,15 @@ uint16_t lang_get_code(uint8_t lang)
 		addr += header.size; //calc address of next table
 	}
 #else //W25X20CL
+	uint16_t table = _SEC_LANG_TABLE;
+	uint8_t count = 1; //count = 1 (primary)
+	while (pgm_read_dword((uint32_t*)table) == LANG_MAGIC) //magic valid
+	{
+		if (count == lang) return pgm_read_word(((uint16_t*)(table + 10))); //read language code
+		table += pgm_read_word((uint16_t*)(table + 4));
+		count++;
+	}
 #endif //W25X20CL
-
-//	if (lang == LANG_ID_SEC)
-//	{
-//		uint16_t ui = _SEC_LANG_TABLE; //table pointer
-//		if (pgm_read_dword(((uint32_t*)(ui + 0))) == LANG_MAGIC) //magic num is OK
-//			return pgm_read_word(((uint16_t*)(ui + 10))); //read language code
-//	}
 	return LANG_CODE_XX;
 }
 

+ 4 - 2
Firmware/language.h

@@ -2,7 +2,6 @@
 #ifndef LANGUAGE_H
 #define LANGUAGE_H
 
-#define W25X20CL
 
 #include "config.h"
 #include <inttypes.h>
@@ -52,7 +51,7 @@ typedef struct
 	uint16_t count;      //+6
 	uint16_t checksum;   //+8
 	uint16_t code;       //+10
-	uint32_t reserved1;  //+12
+	uint32_t signature;  //+12
 } lang_table_header_t;
 
 //lang_table_t structure - (size= 16byte + 2*count)
@@ -98,10 +97,13 @@ extern uint8_t lang_selected;
 extern const char _SEC_LANG[LANG_SIZE_RESERVED];
 extern const char* lang_get_translation(const char* s);
 #define _SEC_LANG_TABLE ((((uint16_t)&_SEC_LANG) + 0x00ff) & 0xff00)
+//extern const uint32_t _PRI_LANG_SIGNATURE;
 #endif //(LANG_MODE != 0)
 
 //selects language, eeprom is updated in case of success
 extern uint8_t lang_select(uint8_t lang);
+//performs checksum test of secondary language data
+extern uint8_t lang_check(uint16_t addr);
 //returns total number of languages (primary + all in xflash)
 extern uint8_t lang_get_count(void);
 //reads lang table header and offset in xflash or progmem

+ 2 - 2
Firmware/mesh_bed_calibration.cpp

@@ -2845,11 +2845,11 @@ bool sample_mesh_and_store_reference()
     {
         // Verify the span of the Z values.
         float zmin = mbl.z_values[0][0];
-        float zmax = zmax;
+        float zmax = zmin;
         for (int8_t j = 0; j < 3; ++ j)
            for (int8_t i = 0; i < 3; ++ i) {
                 zmin = min(zmin, mbl.z_values[j][i]);
-                zmax = min(zmax, mbl.z_values[j][i]);
+                zmax = max(zmax, mbl.z_values[j][i]);
            }
         if (zmax - zmin > 3.f) {
             // The span of the Z offsets is extreme. Give up.

+ 2 - 0
Firmware/optiboot_w25x20cl.cpp

@@ -5,6 +5,7 @@
 #include "Marlin.h"
 #include "w25x20cl.h"
 #include "stk500.h"
+#include "bootapp.h"
 
 #define OPTIBOOT_MAJVER 6
 #define OPTIBOOT_CUSTOMVER 0
@@ -98,6 +99,7 @@ extern struct block_t *block_buffer;
 
 void optiboot_w25x20cl_enter()
 {
+  if (boot_app_flags & BOOT_APP_FLG_USER0) return;
   uint8_t ch;
   uint8_t rampz = 0;
   register uint16_t address = 0;

+ 1 - 1
Firmware/pins_Rambo_1_0.h

@@ -16,7 +16,7 @@
 
 #define PAT9125_SWI2C
 #define PAT9125_SWI2C_SDA      20 //SDA on P3
-#define PAT9125_SWI2C_SCL      21 //SCL on P3
+#define PAT9125_SWI2C_SCL      84 //PH2 on P3, sensor cable must be rewired
 #define PAT9125_SWI2C_CFG    0xb1 //2us clock delay, 2048 cycles timeout
 
 //#define PAT9125_HWI2C

+ 65 - 0
Firmware/rbuf.c

@@ -0,0 +1,65 @@
+//rbuf.c
+#include "rbuf.h"
+//#include <avr/interrupt.h>
+
+
+void rbuf_ini(uint8_t* ptr, uint8_t l)
+{
+	ptr[0] = l;
+	ptr[1] = 0;
+	ptr[2] = 0;
+}
+
+//lock/unlock macros
+//#define _lock() uint8_t _sreg = SREG; cli();
+//#define _unlock() SREG = _sreg;
+#define _lock()
+#define _unlock()
+
+//put single byte to buffer
+int rbuf_put(uint8_t* ptr, uint8_t b)
+{
+//#ifdef _NO_ASM
+	_lock();                         //lock
+	uint8_t buf_w = ptr[1];          //get write index
+	uint8_t buf_r = ptr[2];          //get read index
+	_unlock();                       //unlock
+	ptr[4 + buf_w] = b;              //store byte to buffer
+	buf_w++;                         //incerment write index
+	uint8_t buf_l = ptr[0];          //get length
+	if (buf_w >= buf_l) buf_w = 0;   //rotate write index
+	if (buf_w == buf_r) return -1;   //return -1 to signal buffer full
+	ptr[1] = buf_w;                  //store write index
+	return 0;                        //return 0 to signal success
+//#else //_NO_ASM
+// TODO - optimized assembler version
+//	asm("movw r26, r24");
+//	asm("ld r18, X+");
+//	asm("cli");
+//	asm("ld r19, X+");
+//	asm("ld r20, X");
+//	asm("cp r19, r18");
+//	asm("brne .-6");*/
+//#endif //_NO_ASM
+}
+
+//get single byte from buffer
+int rbuf_get(uint8_t* ptr)
+{
+//#ifdef _NO_ASM
+	_lock();                         //lock
+	uint8_t buf_w = ptr[1];          //get write index
+	uint8_t buf_r = ptr[2];          //get read index
+	_unlock();                       //unlock
+	if (buf_r == buf_w) return -1;   //return -1 to signal buffer empty
+	int ret = ptr[4 + buf_r];        //get byte from buffer
+	buf_r++;                         //increment read index
+	uint8_t buf_l = ptr[0];          //get length
+	if (buf_r >= buf_l) buf_r = 0;   //rotate read index
+	ptr[2] = buf_r;                  //store read index
+	return ret;                      //return byte (0-255)
+//	return 0;                        //return 0 to signal success
+//#else //_NO_ASM
+// TODO - optimized assembler version
+//#endif //_NO_ASM
+}

+ 27 - 0
Firmware/rbuf.h

@@ -0,0 +1,27 @@
+//rbuf.h
+#ifndef _RBUF_H
+#define _RBUF_H
+
+#include <inttypes.h>
+
+
+#define rbuf_l(ptr) (ptr[0])
+#define rbuf_w(ptr) (ptr[1])
+#define rbuf_r(ptr) (ptr[2])
+#define rbuf_empty(ptr) (ptr[1] == ptr[2])
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif //defined(__cplusplus)
+
+
+extern void rbuf_ini(uint8_t* ptr, uint8_t len);
+extern int rbuf_put(uint8_t* ptr, uint8_t val);
+extern int rbuf_get(uint8_t* ptr);
+
+
+#if defined(__cplusplus)
+}
+#endif //defined(__cplusplus)
+#endif //_RBUF_H

+ 16 - 13
Firmware/tmc2130.cpp

@@ -62,6 +62,13 @@ uint8_t tmc2130_home_fsteps[2] = {48, 48};
 
 uint8_t tmc2130_wave_fac[4] = {0, 0, 0, 0};
 
+tmc2130_chopper_config_t tmc2130_chopper_config[4] = {
+	{TMC2130_TOFF_XYZ, 5, 1, 2, 0},
+	{TMC2130_TOFF_XYZ, 5, 1, 2, 0},
+	{TMC2130_TOFF_XYZ, 5, 1, 2, 0},
+	{TMC2130_TOFF_E, 5, 1, 2, 0}
+};
+
 bool tmc2130_sg_stop_on_crash = true;
 uint8_t tmc2130_sg_diag_mask = 0x00;
 uint8_t tmc2130_sg_crash = 0;
@@ -418,13 +425,13 @@ void tmc2130_check_overtemp()
 void tmc2130_setup_chopper(uint8_t axis, uint8_t mres, uint8_t current_h, uint8_t current_r)
 {
 	uint8_t intpol = 1;
-	uint8_t toff = TMC2130_TOFF_XYZ; // toff = 3 (fchop = 27.778kHz)
-	uint8_t hstrt = 5; //initial 4, modified to 5
-	uint8_t hend = 1;
+	uint8_t toff = tmc2130_chopper_config[axis].toff; // toff = 3 (fchop = 27.778kHz)
+	uint8_t hstrt = tmc2130_chopper_config[axis].hstr; //initial 4, modified to 5
+	uint8_t hend = tmc2130_chopper_config[axis].hend; //original value = 1
 	uint8_t fd3 = 0;
 	uint8_t rndtf = 0; //random off time
 	uint8_t chm = 0; //spreadCycle
-	uint8_t tbl = 2; //blanking time
+	uint8_t tbl = tmc2130_chopper_config[axis].tbl; //blanking time, original value = 2
 	if (axis == E_AXIS)
 	{
 #ifdef TMC2130_CNSTOFF_E
@@ -434,9 +441,11 @@ void tmc2130_setup_chopper(uint8_t axis, uint8_t mres, uint8_t current_h, uint8_
 		hend = 0; //sine wave offset
 		chm = 1; // constant off time mod
 #endif //TMC2130_CNSTOFF_E
-		toff = TMC2130_TOFF_E; // toff = 3-5
+//		toff = TMC2130_TOFF_E; // toff = 3-5
 //		rndtf = 1;
 	}
+	DBG(_n("tmc2130_setup_chopper(axis=%hhd, mres=%hhd, curh=%hhd, curr=%hhd\n"), axis, mres, current_h, current_r);
+	DBG(_n(" toff=%hhd, hstr=%hhd, hend=%hhd, tbl=%hhd\n"), toff, hstrt, hend, tbl);
 	if (current_r <= 31)
 	{
 		tmc2130_wr_CHOPCONF(axis, toff, hstrt, hend, fd3, 0, rndtf, chm, tbl, 1, 0, 0, 0, mres, intpol, 0, 0);
@@ -475,10 +484,7 @@ void tmc2130_print_currents()
 
 void tmc2130_set_pwm_ampl(uint8_t axis, uint8_t pwm_ampl)
 {
-	MYSERIAL.print("tmc2130_set_pwm_ampl ");
-	MYSERIAL.print((int)axis);
-	MYSERIAL.print(" ");
-	MYSERIAL.println((int)pwm_ampl);
+	DBG(_n("tmc2130_set_pwm_ampl(axis=%hhd, pwm_ampl=%hhd\n"), axis, pwm_ampl);
 	tmc2130_pwm_ampl[axis] = pwm_ampl;
 	if (((axis == 0) || (axis == 1)) && (tmc2130_mode == TMC2130_MODE_SILENT))
 		tmc2130_wr_PWMCONF(axis, tmc2130_pwm_ampl[axis], tmc2130_pwm_grad[axis], tmc2130_pwm_freq[axis], tmc2130_pwm_auto[axis], 0, 0);
@@ -486,10 +492,7 @@ void tmc2130_set_pwm_ampl(uint8_t axis, uint8_t pwm_ampl)
 
 void tmc2130_set_pwm_grad(uint8_t axis, uint8_t pwm_grad)
 {
-	MYSERIAL.print("tmc2130_set_pwm_grad ");
-	MYSERIAL.print((int)axis);
-	MYSERIAL.print(" ");
-	MYSERIAL.println((int)pwm_grad);
+	DBG(_n("tmc2130_set_pwm_grad(axis=%hhd, pwm_grad=%hhd\n"), axis, pwm_grad);
 	tmc2130_pwm_grad[axis] = pwm_grad;
 	if (((axis == 0) || (axis == 1)) && (tmc2130_mode == TMC2130_MODE_SILENT))
 		tmc2130_wr_PWMCONF(axis, tmc2130_pwm_ampl[axis], tmc2130_pwm_grad[axis], tmc2130_pwm_freq[axis], tmc2130_pwm_auto[axis], 0, 0);

+ 15 - 0
Firmware/tmc2130.h

@@ -36,6 +36,19 @@ extern uint8_t tmc2130_home_fsteps[2];
 
 extern uint8_t tmc2130_wave_fac[4];
 
+#pragma pack(push)
+#pragma pack(1)
+typedef struct
+{
+	uint8_t toff:4;
+	uint8_t hstr:3;
+	uint8_t hend:4;
+	uint8_t tbl:2;
+	uint8_t res:3;
+} tmc2130_chopper_config_t;
+#pragma pack(pop)
+
+extern tmc2130_chopper_config_t tmc2130_chopper_config[4];
 
 //initialize tmc2130
 extern void tmc2130_init();
@@ -55,6 +68,7 @@ extern void tmc2130_sg_meassure_start(uint8_t axis);
 //stop current stallguard meassuring and report result
 extern uint16_t tmc2130_sg_meassure_stop();
 
+extern void tmc2130_setup_chopper(uint8_t axis, uint8_t mres, uint8_t current_h, uint8_t current_r);
 
 //set holding current for any axis (M911)
 extern void tmc2130_set_current_h(uint8_t axis, uint8_t current);
@@ -80,6 +94,7 @@ extern bool tmc2130_wait_standstill_xy(int timeout);
 extern void tmc2130_eeprom_load_config();
 extern void tmc2130_eeprom_save_config();
 
+
 #pragma pack(push)
 #pragma pack(1)
 struct

+ 79 - 0
Firmware/uart2.c

@@ -0,0 +1,79 @@
+//uart2.c
+#include "uart2.h"
+#include <avr/io.h>
+#include <avr/interrupt.h>
+#include <avr/pgmspace.h>
+#include "rbuf.h"
+
+#define UART2_BAUD 115200
+#define UART_BAUD_SELECT(baudRate,xtalCpu) (((float)(xtalCpu))/(((float)(baudRate))*8.0)-1.0+0.5)
+#define uart2_rxcomplete (UCSR2A & (1 << RXC2))
+#define uart2_txcomplete (UCSR2A & (1 << TXC2))
+#define uart2_txready    (UCSR2A & (1 << UDRE2))
+
+uint8_t uart2_ibuf[10] = {0, 0};
+
+FILE _uart2io = {0};
+
+
+int uart2_putchar(char c, FILE *stream)
+{
+	while (!uart2_txready);
+	UDR2 = c; // transmit byte
+//	while (!uart2_txcomplete); // wait until byte sent
+//	UCSR2A |= (1 << TXC2); // delete TXCflag
+	return 0;
+}
+
+int uart2_getchar(FILE *stream)
+{
+	if (rbuf_empty(uart2_ibuf)) return -1;
+	return rbuf_get(uart2_ibuf);
+}
+
+void uart2_init(void)
+{
+	rbuf_ini(uart2_ibuf, 6);
+	UCSR2A |= (1 << U2X2); // baudrate multiplier
+	UBRR2L = UART_BAUD_SELECT(UART2_BAUD, F_CPU); // select baudrate
+	UCSR2B = (1 << RXEN2) | (1 << TXEN2); // enable receiver and transmitter
+	UCSR2B |= (1 << RXCIE2); // enable rx interrupt
+	fdev_setup_stream(uart2io, uart2_putchar, uart2_getchar, _FDEV_SETUP_WRITE | _FDEV_SETUP_READ); //setup uart2 i/o stream
+}
+
+uint8_t uart2_rx_clr(void)
+{
+	rbuf_w(uart2_ibuf) = 0;
+	rbuf_r(uart2_ibuf) = 0;
+}
+
+uint8_t uart2_rx_ok(void)
+{
+	//printf_P(PSTR("uart2_rx_ok %hhu %hhu %hhu %hhu %hhu %hhu %hhu %hhu %hhu %hhu\n"), uart2_ibuf[0], uart2_ibuf[1], uart2_ibuf[2], uart2_ibuf[3], uart2_ibuf[4], uart2_ibuf[5], uart2_ibuf[6], uart2_ibuf[7], uart2_ibuf[8], uart2_ibuf[9]);
+//	return 0;
+//	_lock();                                   //lock
+	uint8_t i = rbuf_w(uart2_ibuf);            //get write index
+//	_unlock();                                 //unlock
+	uint8_t e = rbuf_l(uart2_ibuf) - 1;        //get end index
+//	printf_P(PSTR("%d %d \n"), i, e);
+//	return 0;
+	if ((i--) == 255) i = e;                   //decrement index
+	if ((uart2_ibuf[4 + i] != '\n') &&
+		(uart2_ibuf[4 + i] != '\r')) return 0; //no match - exit
+	if ((i--) == 255) i = e;                   //decrement index
+	if (uart2_ibuf[4 + i] != 'k') return 0;    //no match - exit
+	if ((i--) == 255) i = e;                   //decrement index
+	if (uart2_ibuf[4 + i] != 'o') return 0;    //no match - exit
+	uart2_ibuf[4 + i] = 0;                     //discard char
+	return 1;                                  //match "ok\n"
+}
+
+ISR(USART2_RX_vect)
+{
+	//printf_P(PSTR("USART2_RX_vect \n") );
+	if (rbuf_put(uart2_ibuf, UDR2) < 0) // put received byte to buffer
+	{
+		//rx buffer full
+	}
+}
+

+ 29 - 0
Firmware/uart2.h

@@ -0,0 +1,29 @@
+//uart2.h
+#ifndef _UART2_H
+#define _UART2_H
+
+#include <inttypes.h>
+#include <stdio.h>
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif //defined(__cplusplus)
+
+
+extern FILE _uart2io;
+#define uart2io (&_uart2io)
+
+//extern uint8_t uart2_ibuf[10];
+
+extern void uart2_init(void);
+
+extern uint8_t uart2_rx_clr(void);
+
+extern uint8_t uart2_rx_ok(void);
+
+
+#if defined(__cplusplus)
+}
+#endif //defined(__cplusplus)
+#endif //_UART2_H

+ 613 - 400
Firmware/ultralcd.cpp

@@ -26,23 +26,6 @@
 #endif //TMC2130
 
 
-#include <stdarg.h>
-
-int lcd_puts_P(const char* str)
-{
-	return fputs_P(str, lcdout);
-}
-
-int lcd_printf_P(const char* format, ...)
-{
-	va_list args;
-	va_start(args, format);
-	int ret = vfprintf_P(lcdout, format, args);
-	va_end(args);
-	return ret;
-}
-
-
 int8_t encoderDiff; /* encoderDiff is updated from interrupt context and added to encoderPosition every LCD update */
 
 extern int lcd_change_fil_state;
@@ -133,6 +116,10 @@ union MenuData
         bool initialized;
         bool endstopsEnabledPrevious;
     } _lcd_moveMenu;
+	struct sdcard_menu_t
+	{
+		uint8_t viewState;
+	} sdcard_menu;
 };
 
 // State of the currently active menu.
@@ -264,12 +251,6 @@ static void lcd_delta_calibrate_menu();
 static void lcd_quick_feedback();//Cause an LCD refresh, and give the user visual or audible feedback that something has happened
 
 /* Different types of actions that can be used in menu items. */
-static void menu_action_back(menuFunc_t data = 0);
-#define menu_action_back_RAM menu_action_back
-static void menu_action_submenu(menuFunc_t data);
-static void menu_action_gcode(const char* pgcode);
-static void menu_action_function(menuFunc_t data);
-static void menu_action_setlang(unsigned char lang);
 static void menu_action_sdfile(const char* filename, char* longFilename);
 static void menu_action_sddirectory(const char* filename, char* longFilename);
 static void menu_action_setting_edit_bool(const char* pstr, bool* ptr);
@@ -315,15 +296,11 @@ static void menu_action_setting_edit_callback_long5(const char* pstr, unsigned l
 #endif
 #endif
 
+uint8_t _lineNr = 0;
+uint8_t _menuItemNr = 0;
+uint8_t _drawLineNr = 0;
 
-/* Helper macros for menus */
-#define START_MENU() do { \
-    if (encoderPosition > 0x8000) encoderPosition = 0; \
-    if (encoderPosition / ENCODER_STEPS_PER_MENU_ITEM < currentMenuViewOffset) currentMenuViewOffset = encoderPosition / ENCODER_STEPS_PER_MENU_ITEM;\
-    uint8_t _lineNr = currentMenuViewOffset, _menuItemNr; \
-    bool wasClicked = LCD_CLICKED;\
-    for(uint8_t _drawLineNr = 0; _drawLineNr < LCD_HEIGHT; _drawLineNr++, _lineNr++) { \
-      _menuItemNr = 0;
+bool wasClicked = false;
 
 #define MENU_ITEM(type, label, args...) do { \
     if (_menuItemNr == _lineNr) { \
@@ -344,13 +321,9 @@ static void menu_action_setting_edit_callback_long5(const char* pstr, unsigned l
     _menuItemNr++;\
   } while(0)
 
-#define MENU_ITEM_DUMMY() do { _menuItemNr++; } while(0)
+//#define MENU_ITEM_DUMMY() do { _menuItemNr++; } while(0)
 #define MENU_ITEM_EDIT(type, label, args...) MENU_ITEM(setting_edit_ ## type, label, (label) , ## args )
 #define MENU_ITEM_EDIT_CALLBACK(type, label, args...) MENU_ITEM(setting_edit_callback_ ## type, label, (label) , ## args )
-#define END_MENU() \
-  if (encoderPosition / ENCODER_STEPS_PER_MENU_ITEM >= _menuItemNr) encoderPosition = _menuItemNr * ENCODER_STEPS_PER_MENU_ITEM - 1; \
-  if ((uint8_t)(encoderPosition / ENCODER_STEPS_PER_MENU_ITEM) >= currentMenuViewOffset + LCD_HEIGHT) { currentMenuViewOffset = (encoderPosition / ENCODER_STEPS_PER_MENU_ITEM) - LCD_HEIGHT + 1; lcdDrawUpdate = 1; _lineNr = currentMenuViewOffset - 1; _drawLineNr = -1; } \
-  } } while(0)
 
 /** Used variables to keep track of the menu */
 #ifndef REPRAPWORLD_KEYPAD
@@ -385,8 +358,8 @@ uint8_t lcdDrawUpdate = 2;                  /* Set to none-zero when the LCD nee
 /**
  * @brief Go to menu
  *
- * In MENU_ITEM(submenu,... ) use MENU_ITEM(back,...) or
- * menu_action_back() and menu_action_submenu() instead, otherwise menuStack will be broken.
+ * In MENU_ITEM_SUBMENU_P(str, func) use MENU_ITEM_BACK_P(str) or
+ * menu_back() and menu_submenu() instead, otherwise menuStack will be broken.
  *
  * It is acceptable to call lcd_goto_menu(menu) directly from MENU_ITEM(function,...), if destination menu
  * is the same, from which function was called.
@@ -424,8 +397,282 @@ static void lcd_goto_menu(menuFunc_t menu, const uint32_t encoder = 0, const boo
 		asm("sei");
 }
 
-/* Main status screen. It's up to the implementation specific part to show what is needed. As this is very display dependent */
 
+////////////////////////////////////////////////////////////////////////////////
+// New Menu implementation
+
+#include <stdarg.h>
+
+int lcd_puts_P(const char* str)
+{
+	return fputs_P(str, lcdout);
+}
+
+int lcd_putc(int c)
+{
+	return fputc(c, lcdout);
+}
+
+int lcd_printf_P(const char* format, ...)
+{
+	va_list args;
+	va_start(args, format);
+	int ret = vfprintf_P(lcdout, format, args);
+	va_end(args);
+	return ret;
+}
+
+#define MENU_BEGIN() menu_start(); for(_drawLineNr = 0; _drawLineNr < LCD_HEIGHT; _drawLineNr++, _lineNr++) { _menuItemNr = 0;
+void menu_start(void)
+{
+    if (encoderPosition > 0x8000) encoderPosition = 0;
+    if (encoderPosition / ENCODER_STEPS_PER_MENU_ITEM < currentMenuViewOffset)
+		currentMenuViewOffset = encoderPosition / ENCODER_STEPS_PER_MENU_ITEM;
+    _lineNr = currentMenuViewOffset;
+    wasClicked = LCD_CLICKED;
+}
+
+#define MENU_END() menu_end(); }
+void menu_end(void)
+{
+	if (encoderPosition / ENCODER_STEPS_PER_MENU_ITEM >= _menuItemNr)
+		encoderPosition = _menuItemNr * ENCODER_STEPS_PER_MENU_ITEM - 1;
+	if ((uint8_t)(encoderPosition / ENCODER_STEPS_PER_MENU_ITEM) >= currentMenuViewOffset + LCD_HEIGHT)
+	{
+		currentMenuViewOffset = (encoderPosition / ENCODER_STEPS_PER_MENU_ITEM) - LCD_HEIGHT + 1;
+		lcdDrawUpdate = 1;
+		_lineNr = currentMenuViewOffset - 1;
+		_drawLineNr = -1;
+	}
+}
+
+void menu_back(void)
+{
+	MenuStack::Record record = menuStack.pop();
+	lcd_goto_menu(record.menu);
+	encoderPosition = record.position;
+}
+
+void menu_back_if_clicked(void)
+{
+	if (lcd_clicked())
+		menu_back();
+}
+
+void menu_back_if_clicked_fb(void)
+{
+	if (lcd_clicked())
+	{
+        lcd_quick_feedback();
+		menu_back();
+	}
+}
+
+void menu_submenu(menuFunc_t submenu)
+{
+	menuStack.push(currentMenu, encoderPosition);
+	lcd_goto_menu(submenu);
+}
+
+uint8_t menu_item_ret(void)
+{
+	lcd_implementation_quick_feedback();
+	lcdDrawUpdate = 2;
+	button_pressed = false;
+	return 1;
+}
+
+uint8_t menu_enc_is_at_item(void)
+{
+	return ((encoderPosition / ENCODER_STEPS_PER_MENU_ITEM) == _menuItemNr);
+}
+
+/*
+int menu_item_printf_P(char type_char, const char* format, ...)
+{
+	va_list args;
+	va_start(args, format);
+	int ret = 0;
+    lcd.setCursor(0, _drawLineNr);
+	if ((encoderPosition / ENCODER_STEPS_PER_MENU_ITEM) == _menuItemNr)
+		lcd.print('>');
+	else
+		lcd.print(' ');
+	int cnt = vfprintf_P(lcdout, format, args);
+	for (int i = cnt; i < 18; i++)
+		lcd.print(' ');
+	lcd.print(type_char);
+	va_end(args);
+	return ret;
+}
+*/
+int menu_draw_item_puts_P(char type_char, const char* str)
+{
+    lcd.setCursor(0, _drawLineNr);
+	int cnt = lcd_printf_P(_N("%c%-18S%c"), menu_enc_is_at_item()?'>':' ', str, type_char);
+	return cnt;
+}
+
+#define MENU_ITEM_DUMMY() menu_item_dummy()
+inline void menu_item_dummy(void)
+{
+	_menuItemNr++;
+}
+
+#define MENU_ITEM_TEXT_P(str) do { if (menu_item_text_P(str)) return; } while (0)
+uint8_t menu_item_text_P(const char* str)
+{
+	if (_menuItemNr == _lineNr)
+	{
+		if (lcdDrawUpdate) menu_draw_item_puts_P(' ', str);
+		if (wasClicked && menu_enc_is_at_item())
+			return menu_item_ret();
+	}
+	_menuItemNr++;
+	return 0;
+}
+
+#define MENU_ITEM_SUBMENU_P(str, submenu) do { if (menu_item_submenu_P(str, submenu)) return; } while (0)
+uint8_t menu_item_submenu_P(const char* str, menuFunc_t submenu)
+{
+	if (_menuItemNr == _lineNr)
+	{
+		if (lcdDrawUpdate) menu_draw_item_puts_P(LCD_STR_ARROW_RIGHT[0], str);
+		if (wasClicked && menu_enc_is_at_item())
+		{
+			menuStack.push(currentMenu, encoderPosition);
+			lcd_goto_menu(submenu, 0, false, true);
+			return menu_item_ret();
+		}
+	}
+	_menuItemNr++;
+	return 0;
+}
+
+#define MENU_ITEM_BACK_P(str) do { if (menu_item_back_P(str)) return; } while (0)
+uint8_t menu_item_back_P(const char* str)
+{
+	if (_menuItemNr == _lineNr)
+	{
+		if (lcdDrawUpdate) menu_draw_item_puts_P(LCD_STR_UPLEVEL[0], str);
+		if (wasClicked && menu_enc_is_at_item())
+		{
+			MenuStack::Record record = menuStack.pop();
+			lcd_goto_menu(record.menu, false, true);
+			encoderPosition = record.position;
+			return menu_item_ret();
+		}
+	}
+	_menuItemNr++;
+	return 0;
+}
+
+#define MENU_ITEM_FUNCTION_P(str, func) do { if (menu_item_function_P(str, func)) return; } while (0)
+uint8_t menu_item_function_P(const char* str, menuFunc_t func)
+{
+	if (_menuItemNr == _lineNr)
+	{
+		if (lcdDrawUpdate) menu_draw_item_puts_P(' ', str);
+		if (wasClicked && menu_enc_is_at_item())
+		{
+			if (func) func();
+			return menu_item_ret();
+		}
+	}
+	_menuItemNr++;
+	return 0;
+}
+
+#define MENU_ITEM_GCODE_P(str, str_gcode) do { if (menu_item_gcode_P(str, str_gcode)) return; } while (0)
+uint8_t menu_item_gcode_P(const char* str, const char* str_gcode)
+{
+	if (_menuItemNr == _lineNr)
+	{
+		if (lcdDrawUpdate) menu_draw_item_puts_P(' ', str);
+		if (wasClicked && menu_enc_is_at_item())
+		{
+			if (str_gcode) enquecommand_P(str_gcode);
+			return menu_item_ret();
+		}
+	}
+	_menuItemNr++;
+	return 0;
+}
+
+//#define MENU_ITEM_SDDIR(str, str_fn, str_fnl) do { if (menu_item_sddir(str, str_fn, str_fnl)) return; } while (0)
+#define MENU_ITEM_SDDIR(str, str_fn, str_fnl) MENU_ITEM(sddirectory, str, str_fn, str_fnl)
+uint8_t menu_item_sddir(const char* str, const char* str_fn, char* str_fnl)
+{
+//	str_fnl[18] = 0;
+//	printf_P(_N("menu dir %d '%s' '%s'\n"), _drawLineNr, str_fn, str_fnl);
+	if (_menuItemNr == _lineNr)
+	{
+		if (lcdDrawUpdate)
+		{
+			lcd.setCursor(0, _drawLineNr);
+			int cnt = lcd_printf_P(_N("%c%c%-18s"), menu_enc_is_at_item()?'>':' ', LCD_STR_FOLDER[0], str_fnl[0]?str_fnl:str_fn);
+//			int cnt = lcd_printf_P(_N("%c%c%-18s"), menu_enc_is_at_item()?'>':' ', LCD_STR_FOLDER[0], str_fn);
+		}
+		if (wasClicked && menu_enc_is_at_item())
+		{
+			uint8_t depth = (uint8_t)card.getWorkDirDepth();
+			strcpy(dir_names[depth], str_fn);
+//			printf_P(PSTR("%s\n"), dir_names[depth]);
+			card.chdir(str_fn);
+			encoderPosition = 0;
+			return menu_item_ret();
+		}
+	}
+	_menuItemNr++;
+	return 0;
+}
+
+//#define MENU_ITEM_SDFILE(str, str_fn, str_fnl) do { if (menu_item_sdfile(str, str_fn, str_fnl)) return; } while (0)
+#define MENU_ITEM_SDFILE(str, str_fn, str_fnl) MENU_ITEM(sdfile, str, str_fn, str_fnl)
+uint8_t menu_item_sdfile(const char* str, const char* str_fn, char* str_fnl)
+{
+//	printf_P(_N("menu sdfile\n"));
+//	str_fnl[19] = 0;
+//	printf_P(_N("menu file %d '%s' '%s'\n"), _drawLineNr, str_fn, str_fnl);
+	if (_menuItemNr == _lineNr)
+	{
+		if (lcdDrawUpdate)
+		{
+//			printf_P(_N("menu file %d %d '%s'\n"), _drawLineNr, menuData.sdcard_menu.viewState, str_fnl[0]?str_fnl:str_fn);
+			lcd.setCursor(0, _drawLineNr);
+/*			if (menu_enc_is_at_item())
+			{
+				lcd_printf_P(_N("%c%-19s"), menu_enc_is_at_item()?'>':' ', (str_fnl[0]?str_fnl:str_fn) + 1);
+				if (menuData.sdcard_menu.viewState == 0)
+				{
+					menuData.sdcard_menu.viewState++;
+					lcd_printf_P(_N("%c%-19s"), menu_enc_is_at_item()?'>':' ', (str_fnl[0]?str_fnl:str_fn) + 1);
+				}
+				else if (menuData.sdcard_menu.viewState == 1)
+				{
+					lcd_printf_P(_N("%c%-19s"), menu_enc_is_at_item()?'>':' ', (str_fnl[0]?str_fnl:str_fn) + 2);
+				}
+			}
+			else*/
+			{
+				str_fnl[19] = 0;
+				lcd_printf_P(_N("%c%-19s"), menu_enc_is_at_item()?'>':' ', str_fnl[0]?str_fnl:str_fn);
+			}
+
+//			int cnt = lcd_printf_P(_N("%c%-19s"), menu_enc_is_at_item()?'>':' ', str_fnl);
+//			int cnt = lcd_printf_P(_N("%cTESTIK.gcode"), menu_enc_is_at_item()?'>':' ');
+		}
+		if (wasClicked && menu_enc_is_at_item())
+		{
+			return menu_item_ret();
+		}
+	}
+	_menuItemNr++;
+	return 0;
+}
+
+
+/* Main status screen. It's up to the implementation specific part to show what is needed. As this is very display dependent */
 
 static void lcd_status_screen()
 {
@@ -538,7 +785,7 @@ static void lcd_status_screen()
   if (current_click && (lcd_commands_type != LCD_COMMAND_STOP_PRINT)) //click is aborted unless stop print finishes
   {
     menuStack.reset(); //redundant, as already done in lcd_return_to_status(), just to be sure
-    menu_action_submenu(lcd_main_menu);
+    menu_submenu(lcd_main_menu);
     lcd_implementation_init( // to maybe revive the LCD if static electricity killed it.
 #if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)
       currentMenu == lcd_status_screen
@@ -982,7 +1229,7 @@ void lcd_commands()
 
 			lcd_implementation_clear();
 			menuStack.reset();
-			menu_action_submenu(lcd_babystep_z);
+			menu_submenu(lcd_babystep_z);
 			enquecommand_P(PSTR("G1 X60.0 E9.0 F1000.0")); //intro line
 			enquecommand_P(PSTR("G1 X100.0 E12.5 F1000.0")); //intro line			
 			enquecommand_P(PSTR("G92 E0.0"));
@@ -1545,10 +1792,7 @@ static void lcd_menu_extruder_info()
 	);
 #endif //PAT9125
     
-    if (lcd_clicked())
-    {
-        menu_action_back();
-    }
+    menu_back_if_clicked();
 }
 
 #if defined(TMC2130) && defined(PAT9125)
@@ -1565,11 +1809,7 @@ static void lcd_menu_fails_stats_total()
     uint16_t crashX = eeprom_read_word((uint16_t*)EEPROM_CRASH_COUNT_X_TOT);
     uint16_t crashY = eeprom_read_word((uint16_t*)EEPROM_CRASH_COUNT_Y_TOT);
 	lcd_printf_P(PSTR(ESC_H(0,0) "Total failures" ESC_H(1,1) "Power failures  %-3d" ESC_H(1,2) "Filam. runouts  %-3d" ESC_H(1,3) "Crash  X %-3d  Y %-3d"), power, filam, crashX, crashY);
-	if (lcd_clicked())
-    {
-        lcd_quick_feedback();
-        menu_action_back();
-    }
+	menu_back_if_clicked_fb();
 }
 
 static void lcd_menu_fails_stats_print()
@@ -1585,11 +1825,7 @@ static void lcd_menu_fails_stats_print()
     uint8_t crashX = eeprom_read_byte((uint8_t*)EEPROM_CRASH_COUNT_X);
     uint8_t crashY = eeprom_read_byte((uint8_t*)EEPROM_CRASH_COUNT_Y);
 	lcd_printf_P(PSTR(ESC_H(0,0) "Last print failures" ESC_H(1,1) "Power failures  %-3d" ESC_H(1,2) "Filam. runouts  %-3d" ESC_H(1,3) "Crash  X %-3d  Y %-3d"), power, filam, crashX, crashY);
-	if (lcd_clicked())
-    {
-        lcd_quick_feedback();
-		menu_action_back();
-    }    
+	menu_back_if_clicked_fb();
 }
 /**
  * @brief Open fail statistics menu
@@ -1600,11 +1836,11 @@ static void lcd_menu_fails_stats_print()
  */
 static void lcd_menu_fails_stats()
 {
-	START_MENU();
-	MENU_ITEM(back, _T(MSG_MAIN), 0);
-	MENU_ITEM(submenu, PSTR("Last print"), lcd_menu_fails_stats_print);
-	MENU_ITEM(submenu, PSTR("Total"), lcd_menu_fails_stats_total);
-	END_MENU();
+	MENU_BEGIN();
+	MENU_ITEM_BACK_P(_T(MSG_MAIN));
+	MENU_ITEM_SUBMENU_P(PSTR("Last print"), lcd_menu_fails_stats_print);
+	MENU_ITEM_SUBMENU_P(PSTR("Total"), lcd_menu_fails_stats_total);
+	MENU_END();
 }
 #elif defined(PAT9125)
 /**
@@ -1627,10 +1863,7 @@ static void lcd_menu_fails_stats()
     uint8_t filamentLast = eeprom_read_byte((uint8_t*)EEPROM_FERROR_COUNT);
     uint16_t filamentTotal = eeprom_read_word((uint16_t*)EEPROM_FERROR_COUNT_TOT);
     lcd_printf_P(PSTR(ESC_H(0,0) "Last print failures" ESC_H(1,1) "Filam. runouts  %-3d" ESC_H(0,2) "Total failures" ESC_H(1,3) "Filam. runouts  %-3d"), filamentLast, filamentTotal);
-    if (lcd_clicked())
-    {
-        menu_action_back();
-    }
+    menu_back_if_clicked();
 }
 #endif //TMC2130
 
@@ -1648,11 +1881,7 @@ static void lcd_menu_debug()
 	lcd_printf_P(PSTR(ESC_H(1,1) "RAM statistics" ESC_H(5,1) "SP_min: 0x%04x" ESC_H(1,2) "heap_start: 0x%04x" ESC_H(3,3) "heap_end: 0x%04x"), SP_min, __malloc_heap_start, __malloc_heap_end);
 #endif //DEBUG_STACK_MONITOR
 
-	if (lcd_clicked())
-    {
-        lcd_quick_feedback();
-        menu_action_back();
-    }
+	menu_back_if_clicked_fb();
 }
 #endif /* DEBUG_BUILD */
 
@@ -1665,10 +1894,7 @@ static void lcd_menu_temperatures()
 	lcd_printf_P(PSTR(ESC_H(1,2) "PINDA:    %d%c"), (int)current_temperature_pinda, '\x01');
 #endif //AMBIENT_THERMISTOR
 
-	if (lcd_clicked())
-    {
-        menu_action_back();
-    }
+    menu_back_if_clicked();
 }
 
 #if defined (VOLT_BED_PIN) || defined (VOLT_PWR_PIN)
@@ -1682,10 +1908,7 @@ static void lcd_menu_voltages()
 //	float volt_bed = VOLT_DIV_REF * ((float)current_voltage_raw_bed / (1023 * OVERSAMPLENR)) / VOLT_DIV_FAC;
 //	lcd_printf_P(PSTR(ESC_H(1,1)"PWR:      %d.%01dV" ESC_H(1,2)"BED:      %d.%01dV"), (int)volt_pwr, (int)(10*fabs(volt_pwr - (int)volt_pwr)), (int)volt_bed, (int)(10*fabs(volt_bed - (int)volt_bed)));
     lcd_printf_P(PSTR( ESC_H(1,1)"PWR:      %d.%01dV"), (int)volt_pwr, (int)(10*fabs(volt_pwr - (int)volt_pwr))) ;
-    if (lcd_clicked())
-    {
-        menu_action_back();
-    }
+    menu_back_if_clicked();
 }
 #endif //defined VOLT_BED_PIN || defined VOLT_PWR_PIN
 
@@ -1693,10 +1916,7 @@ static void lcd_menu_voltages()
 static void lcd_menu_belt_status()
 {
     lcd_printf_P(PSTR(ESC_H(1,0) "Belt status" ESC_H(2,1) "X %d" ESC_H(2,2) "Y %d" ), eeprom_read_word((uint16_t*)(EEPROM_BELTSTATUS_X)), eeprom_read_word((uint16_t*)(EEPROM_BELTSTATUS_Y)));
-    if (lcd_clicked())
-    {
-        menu_action_back();
-    }
+    menu_back_if_clicked();
 }
 #endif //TMC2130
 
@@ -1715,27 +1935,27 @@ static void lcd_menu_test_restore()
 
 static void lcd_preheat_menu()
 {
-  START_MENU();
+  MENU_BEGIN();
 
-  MENU_ITEM(back, _T(MSG_MAIN), 0);
+  MENU_ITEM_BACK_P(_T(MSG_MAIN));
 
   if (farm_mode) {
-	  MENU_ITEM(function, PSTR("farm   -  " STRINGIFY(FARM_PREHEAT_HOTEND_TEMP) "/" STRINGIFY(FARM_PREHEAT_HPB_TEMP)), lcd_preheat_farm);
-	  MENU_ITEM(function, PSTR("nozzle -  " STRINGIFY(FARM_PREHEAT_HOTEND_TEMP) "/0"), lcd_preheat_farm_nozzle);
-	  MENU_ITEM(function, _T(MSG_COOLDOWN), lcd_cooldown);
-	  MENU_ITEM(function, PSTR("ABS    -  " STRINGIFY(ABS_PREHEAT_HOTEND_TEMP) "/" STRINGIFY(ABS_PREHEAT_HPB_TEMP)), lcd_preheat_abs);
+	  MENU_ITEM_FUNCTION_P(PSTR("farm   -  " STRINGIFY(FARM_PREHEAT_HOTEND_TEMP) "/" STRINGIFY(FARM_PREHEAT_HPB_TEMP)), lcd_preheat_farm);
+	  MENU_ITEM_FUNCTION_P(PSTR("nozzle -  " STRINGIFY(FARM_PREHEAT_HOTEND_TEMP) "/0"), lcd_preheat_farm_nozzle);
+	  MENU_ITEM_FUNCTION_P(_T(MSG_COOLDOWN), lcd_cooldown);
+	  MENU_ITEM_FUNCTION_P(PSTR("ABS    -  " STRINGIFY(ABS_PREHEAT_HOTEND_TEMP) "/" STRINGIFY(ABS_PREHEAT_HPB_TEMP)), lcd_preheat_abs);
   } else {
-	  MENU_ITEM(function, PSTR("PLA  -  " STRINGIFY(PLA_PREHEAT_HOTEND_TEMP) "/" STRINGIFY(PLA_PREHEAT_HPB_TEMP)), lcd_preheat_pla);
-	  MENU_ITEM(function, PSTR("PET  -  " STRINGIFY(PET_PREHEAT_HOTEND_TEMP) "/" STRINGIFY(PET_PREHEAT_HPB_TEMP)), lcd_preheat_pet);
-	  MENU_ITEM(function, PSTR("ABS  -  " STRINGIFY(ABS_PREHEAT_HOTEND_TEMP) "/" STRINGIFY(ABS_PREHEAT_HPB_TEMP)), lcd_preheat_abs);
-	  MENU_ITEM(function, PSTR("HIPS -  " STRINGIFY(HIPS_PREHEAT_HOTEND_TEMP) "/" STRINGIFY(HIPS_PREHEAT_HPB_TEMP)), lcd_preheat_hips);
-	  MENU_ITEM(function, PSTR("PP   -  " STRINGIFY(PP_PREHEAT_HOTEND_TEMP) "/" STRINGIFY(PP_PREHEAT_HPB_TEMP)), lcd_preheat_pp);
-	  MENU_ITEM(function, PSTR("FLEX -  " STRINGIFY(FLEX_PREHEAT_HOTEND_TEMP) "/" STRINGIFY(FLEX_PREHEAT_HPB_TEMP)), lcd_preheat_flex);
-	  MENU_ITEM(function, _T(MSG_COOLDOWN), lcd_cooldown);
+	  MENU_ITEM_FUNCTION_P(PSTR("PLA  -  " STRINGIFY(PLA_PREHEAT_HOTEND_TEMP) "/" STRINGIFY(PLA_PREHEAT_HPB_TEMP)), lcd_preheat_pla);
+	  MENU_ITEM_FUNCTION_P(PSTR("PET  -  " STRINGIFY(PET_PREHEAT_HOTEND_TEMP) "/" STRINGIFY(PET_PREHEAT_HPB_TEMP)), lcd_preheat_pet);
+	  MENU_ITEM_FUNCTION_P(PSTR("ABS  -  " STRINGIFY(ABS_PREHEAT_HOTEND_TEMP) "/" STRINGIFY(ABS_PREHEAT_HPB_TEMP)), lcd_preheat_abs);
+	  MENU_ITEM_FUNCTION_P(PSTR("HIPS -  " STRINGIFY(HIPS_PREHEAT_HOTEND_TEMP) "/" STRINGIFY(HIPS_PREHEAT_HPB_TEMP)), lcd_preheat_hips);
+	  MENU_ITEM_FUNCTION_P(PSTR("PP   -  " STRINGIFY(PP_PREHEAT_HOTEND_TEMP) "/" STRINGIFY(PP_PREHEAT_HPB_TEMP)), lcd_preheat_pp);
+	  MENU_ITEM_FUNCTION_P(PSTR("FLEX -  " STRINGIFY(FLEX_PREHEAT_HOTEND_TEMP) "/" STRINGIFY(FLEX_PREHEAT_HPB_TEMP)), lcd_preheat_flex);
+	  MENU_ITEM_FUNCTION_P(_T(MSG_COOLDOWN), lcd_cooldown);
   }
   
 
-  END_MENU();
+  MENU_END();
 }
 
 static void lcd_support_menu()
@@ -1757,61 +1977,62 @@ static void lcd_support_menu()
         menuData.supportMenu.status = 0;
     }
 
-  START_MENU();
+  MENU_BEGIN();
 
-  MENU_ITEM(back, _T(MSG_MAIN), 0);
+  MENU_ITEM_BACK_P(_T(MSG_MAIN));
 
-  MENU_ITEM(back, PSTR("Firmware:"), 0);
-  MENU_ITEM(back, PSTR(" " FW_VERSION_FULL), 0);
+  MENU_ITEM_BACK_P(PSTR("Firmware:"));
+  MENU_ITEM_BACK_P(PSTR(" " FW_VERSION_FULL));
 #if (FW_DEV_VERSION != FW_VERSION_GOLD) && (FW_DEV_VERSION != FW_VERSION_RC)
-  MENU_ITEM(back, PSTR(" repo " FW_REPOSITORY), 0);
+  MENU_ITEM_BACK_P(PSTR(" repo " FW_REPOSITORY));
 #endif
   // Ideally this block would be optimized out by the compiler.
 /*  const uint8_t fw_string_len = strlen_P(FW_VERSION_STR_P());
   if (fw_string_len < 6) {
-      MENU_ITEM(back, PSTR(MSG_FW_VERSION " - " FW_version), 0);
+      MENU_ITEM_BACK_P(PSTR(MSG_FW_VERSION " - " FW_version));
   } else {
-      MENU_ITEM(back, PSTR("FW - " FW_version), 0);
+      MENU_ITEM_BACK_P(PSTR("FW - " FW_version));
   }*/
       
-  MENU_ITEM(back, _i("prusa3d.com"), 0);////MSG_PRUSA3D c=0 r=0
-  MENU_ITEM(back, _i("forum.prusa3d.com"), 0);////MSG_PRUSA3D_FORUM c=0 r=0
-  MENU_ITEM(back, _i("howto.prusa3d.com"), 0);////MSG_PRUSA3D_HOWTO c=0 r=0
-  MENU_ITEM(back, PSTR("------------"), 0);
-  MENU_ITEM(back, PSTR(FILAMENT_SIZE), 0);
-  MENU_ITEM(back, PSTR(ELECTRONICS),0);
-  MENU_ITEM(back, PSTR(NOZZLE_TYPE),0);
-  MENU_ITEM(back, PSTR("------------"), 0);
-  MENU_ITEM(back, _i("Date:"), 0);////MSG_DATE c=17 r=1
-  MENU_ITEM(back, PSTR(__DATE__), 0);
+  MENU_ITEM_BACK_P(_i("prusa3d.com"));////MSG_PRUSA3D c=0 r=0
+  MENU_ITEM_BACK_P(_i("forum.prusa3d.com"));////MSG_PRUSA3D_FORUM c=0 r=0
+  MENU_ITEM_BACK_P(_i("howto.prusa3d.com"));////MSG_PRUSA3D_HOWTO c=0 r=0
+  MENU_ITEM_BACK_P(PSTR("------------"));
+  MENU_ITEM_BACK_P(PSTR(FILAMENT_SIZE));
+  MENU_ITEM_BACK_P(PSTR(ELECTRONICS));
+  MENU_ITEM_BACK_P(PSTR(NOZZLE_TYPE));
+  MENU_ITEM_BACK_P(PSTR("------------"));
+  MENU_ITEM_BACK_P(_i("Date:"));////MSG_DATE c=17 r=1
+  MENU_ITEM_BACK_P(PSTR(__DATE__));
 
   // Show the FlashAir IP address, if the card is available.
   if (menuData.supportMenu.is_flash_air) {
-      MENU_ITEM(back, PSTR("------------"), 0);
-      MENU_ITEM(back, PSTR("FlashAir IP Addr:"), 0);
-      MENU_ITEM(back_RAM, menuData.supportMenu.ip_str, 0);
+      MENU_ITEM_BACK_P(PSTR("------------"));
+      MENU_ITEM_BACK_P(PSTR("FlashAir IP Addr:"));
+///!      MENU_ITEM(back_RAM, menuData.supportMenu.ip_str, 0);
   }
   #ifndef MK1BP
-  MENU_ITEM(back, PSTR("------------"), 0);
-  MENU_ITEM(submenu, _i("XYZ cal. details"), lcd_menu_xyz_y_min);////MSG_XYZ_DETAILS c=19 r=1
-  MENU_ITEM(submenu, _i("Extruder info"), lcd_menu_extruder_info);////MSG_INFO_EXTRUDER c=15 r=1
+  MENU_ITEM_BACK_P(PSTR("------------"));
+  MENU_ITEM_SUBMENU_P(_i("XYZ cal. details"), lcd_menu_xyz_y_min);////MSG_XYZ_DETAILS c=19 r=1
+  MENU_ITEM_SUBMENU_P(_i("Extruder info"), lcd_menu_extruder_info);////MSG_INFO_EXTRUDER c=15 r=1
 
 #ifdef TMC2130
-  MENU_ITEM(submenu, _i("Belt status"), lcd_menu_belt_status);////MSG_MENU_BELT_STATUS c=15 r=1
+  MENU_ITEM_SUBMENU_P(_i("Belt status"), lcd_menu_belt_status);////MSG_MENU_BELT_STATUS c=15 r=1
 #endif //TMC2130
     
-  MENU_ITEM(submenu, _i("Temperatures"), lcd_menu_temperatures);////MSG_MENU_TEMPERATURES c=15 r=1
+  MENU_ITEM_SUBMENU_P(_i("Temperatures"), lcd_menu_temperatures);////MSG_MENU_TEMPERATURES c=15 r=1
 
 #if defined (VOLT_BED_PIN) || defined (VOLT_PWR_PIN)
-  MENU_ITEM(submenu, _i("Voltages"), lcd_menu_voltages);////MSG_MENU_VOLTAGES c=15 r=1
+  MENU_ITEM_SUBMENU_P(_i("Voltages"), lcd_menu_voltages);////MSG_MENU_VOLTAGES c=15 r=1
 #endif //defined VOLT_BED_PIN || defined VOLT_PWR_PIN
 
 #ifdef DEBUG_BUILD
-  MENU_ITEM(submenu, PSTR("Debug"), lcd_menu_debug);
+  MENU_ITEM_SUBMENU_P(PSTR("Debug"), lcd_menu_debug);
 #endif /* DEBUG_BUILD */
 
   #endif //MK1BP
-  END_MENU();
+
+  MENU_END();
 }
 
 void lcd_set_fan_check() {
@@ -1844,7 +2065,7 @@ void lcd_unLoadFilament()
     lcd_implementation_clear();
   }
 
-  menu_action_back();
+  menu_back();
 }
 
 void lcd_change_filament() {
@@ -2053,9 +2274,9 @@ static void lcd_menu_AutoLoadFilament()
         lcd_printPGM(_T(MSG_ERROR));
         lcd.setCursor(0, 2);
         lcd_printPGM(_T(MSG_PREHEAT_NOZZLE));
-        if (ptimer->expired(2000ul)) menu_action_back();
+        if (ptimer->expired(2000ul)) menu_back();
     }
-    if (lcd_clicked()) menu_action_back();
+    menu_back_if_clicked();
 }
 #endif //PAT9125
 
@@ -2110,11 +2331,7 @@ void lcd_menu_statistics()
 		 _i("Print time"),
 		 _h, _m, _s
 		);
-		if (lcd_clicked())
-		{
-			lcd_quick_feedback();
-			menu_action_back();
-		}
+		menu_back_if_clicked_fb();
 	}
 	else
 	{
@@ -2155,7 +2372,7 @@ void lcd_menu_statistics()
 		}
 		KEEPALIVE_STATE(NOT_BUSY);
 		lcd_quick_feedback();
-		menu_action_back();
+		menu_back();
 	}
 }
 
@@ -2181,7 +2398,7 @@ static void _lcd_move(const char *name, int axis, int min, int max) {
   }
   if (lcdDrawUpdate) lcd_implementation_drawedit(name, ftostr31(current_position[axis]));
   if (menuExiting || LCD_CLICKED) (void)enable_endstops(menuData._lcd_moveMenu.endstopsEnabledPrevious);
-  if (LCD_CLICKED) menu_action_back();
+  if (LCD_CLICKED) menu_back();
 }
 
 
@@ -2202,7 +2419,7 @@ static void lcd_move_e()
   {
     lcd_implementation_drawedit(PSTR("Extruder"), ftostr31(current_position[E_AXIS]));
   }
-  if (LCD_CLICKED) menu_action_back();
+  if (LCD_CLICKED) menu_back();
 }
 	else {
 		lcd_implementation_clear();
@@ -2250,9 +2467,7 @@ static void lcd_menu_xyz_y_min()
 		else lcd_printf_P(_N("%6.2fmm"), distanceMin[i]);
 	}
     if (lcd_clicked())
-    {
         lcd_goto_menu(lcd_menu_xyz_skew);
-    }
 }
 /**
  * @brief Show measured axis skewness
@@ -2267,13 +2482,13 @@ static void lcd_menu_xyz_skew()
 //|01234567890123456789|
 //|Measured skew:  N/A |
 //|--------------------|
-//|Slight skew:   0.12°|
-//|Severe skew:   0.25°|
+//|Slight skew:   0.12�|
+//|Severe skew:   0.25�|
 //----------------------
     float angleDiff = eeprom_read_float((float*)(EEPROM_XYZ_CAL_SKEW));
 	lcd_printf_P(_N(
 	  ESC_H(0,0)
-	  "%S:  N/A\n"
+	  "%S:\n"
 	  "%S\n"
 	  "%S:  %5.2f\x01\n"
 	  "%S:  %5.2f\x01"
@@ -2283,11 +2498,12 @@ static void lcd_menu_xyz_skew()
 	 _i("Slight skew"), _deg(bed_skew_angle_mild),
 	 _i("Severe skew"), _deg(bed_skew_angle_extreme)
 	);
-	if (angleDiff < 100) lcd_printf_P(_N(ESC_H(15,0)"%4.2f\x01"), _deg(angleDiff));
+	if (angleDiff < 100)
+		lcd_printf_P(_N(ESC_H(15,0)"%4.2f\x01"), _deg(angleDiff));
+	else
+		lcd_puts_P(_N(ESC_H(15,0)"N/A"));
     if (lcd_clicked())
-    {
         lcd_goto_menu(lcd_menu_xyz_offset);
-    }
 }
 /**
  * @brief Show measured bed offset from expected position
@@ -2311,10 +2527,7 @@ static void lcd_menu_xyz_offset()
         lcd.print(cntr[i]);
         lcd_print_at_PGM((cntr[i] < 0) ? 17 : 16, i + 2, PSTR("mm"));
     }
-    if (lcd_clicked())
-    {
-        menu_action_back();
-    }
+    menu_back_if_clicked();
 }
 
 // Save a single axis babystep value.
@@ -2410,7 +2623,7 @@ static void _lcd_babystep(int axis, const char *msg)
 
     if(Z_AXIS == axis) calibration_status_store(CALIBRATION_STATUS_CALIBRATED);
   }
-  if (LCD_CLICKED) menu_action_back();
+  if (LCD_CLICKED) menu_back();
 }
 
 static void lcd_babystep_x() {
@@ -2494,14 +2707,14 @@ static void lcd_adjust_bed()
     if (menuData.adjustBed.rear  != menuData.adjustBed.rear2)
         eeprom_update_int8((unsigned char*)EEPROM_BED_CORRECTION_REAR,  menuData.adjustBed.rear  = menuData.adjustBed.rear2);
 
-    START_MENU();
-    MENU_ITEM(back, _T(MSG_SETTINGS), 0);
+    MENU_BEGIN();
+    MENU_ITEM_BACK_P(_T(MSG_SETTINGS));
     MENU_ITEM_EDIT(int3, _i("Left side [um]"),  &menuData.adjustBed.left2,  -BED_ADJUSTMENT_UM_MAX, BED_ADJUSTMENT_UM_MAX);////MSG_BED_CORRECTION_LEFT c=14 r=1
     MENU_ITEM_EDIT(int3, _i("Right side[um]"), &menuData.adjustBed.right2, -BED_ADJUSTMENT_UM_MAX, BED_ADJUSTMENT_UM_MAX);////MSG_BED_CORRECTION_RIGHT c=14 r=1
     MENU_ITEM_EDIT(int3, _i("Front side[um]"), &menuData.adjustBed.front2, -BED_ADJUSTMENT_UM_MAX, BED_ADJUSTMENT_UM_MAX);////MSG_BED_CORRECTION_FRONT c=14 r=1
     MENU_ITEM_EDIT(int3, _i("Rear side [um]"),  &menuData.adjustBed.rear2,  -BED_ADJUSTMENT_UM_MAX, BED_ADJUSTMENT_UM_MAX);////MSG_BED_CORRECTION_REAR c=14 r=1
-    MENU_ITEM(function, _i("Reset"), lcd_adjust_bed_reset);////MSG_BED_CORRECTION_RESET c=0 r=0
-    END_MENU();
+    MENU_ITEM_FUNCTION_P(_i("Reset"), lcd_adjust_bed_reset);////MSG_BED_CORRECTION_RESET c=0 r=0
+    MENU_END();
 }
 
 void pid_extruder() {
@@ -3143,7 +3356,7 @@ static void lcd_show_end_stops() {
 
 static void menu_show_end_stops() {
     lcd_show_end_stops();
-    if (LCD_CLICKED) menu_action_back();
+    if (LCD_CLICKED) menu_back();
 }
 
 // Lets the user move the Z carriage up to the end stoppers.
@@ -3488,13 +3701,13 @@ void lcd_pick_babystep(){
 */
 void lcd_move_menu_axis()
 {
-	START_MENU();
-	MENU_ITEM(back, _T(MSG_SETTINGS), 0);
-	MENU_ITEM(submenu, _i("Move X"), lcd_move_x);////MSG_MOVE_X c=0 r=0
-	MENU_ITEM(submenu, _i("Move Y"), lcd_move_y);////MSG_MOVE_Y c=0 r=0
-	MENU_ITEM(submenu, _i("Move Z"), lcd_move_z);////MSG_MOVE_Z c=0 r=0
-	MENU_ITEM(submenu, _i("Extruder"), lcd_move_e);////MSG_MOVE_E c=0 r=0
-	END_MENU();
+	MENU_BEGIN();
+	MENU_ITEM_BACK_P(_T(MSG_SETTINGS));
+	MENU_ITEM_SUBMENU_P(_i("Move X"), lcd_move_x);////MSG_MOVE_X c=0 r=0
+	MENU_ITEM_SUBMENU_P(_i("Move Y"), lcd_move_y);////MSG_MOVE_Y c=0 r=0
+	MENU_ITEM_SUBMENU_P(_i("Move Z"), lcd_move_z);////MSG_MOVE_Z c=0 r=0
+	MENU_ITEM_SUBMENU_P(_i("Extruder"), lcd_move_e);////MSG_MOVE_E c=0 r=0
+	MENU_END();
 }
 
 static void lcd_move_menu_1mm()
@@ -3549,8 +3762,7 @@ static void lcd_crash_mode_info()
 		fputs_P(_i("\x1b[2JCrash detection can\x1b[1;0Hbe turned on only in\x1b[2;0HNormal mode"), lcdout);////MSG_CRASH_DET_ONLY_IN_NORMAL c=20 r=4
 		tim = millis();
 	}
-	if (lcd_clicked())
-          menu_action_back();
+    menu_back_if_clicked();
 }
 
 static void lcd_crash_mode_info2()
@@ -3562,8 +3774,7 @@ static void lcd_crash_mode_info2()
 		fputs_P(_i("\x1b[2JWARNING:\x1b[1;0HCrash detection\x1b[2;0Hdisabled in\x1b[3;0HStealth mode"), lcdout);////MSG_CRASH_DET_STEALTH_FORCE_OFF c=20 r=4
 		tim = millis();
 	}
-	if (lcd_clicked())
-          menu_action_back();
+    menu_back_if_clicked();
 }
 #endif //TMC2130
 
@@ -3578,8 +3789,7 @@ uint8_t nlines;
           lcd_display_message_fullscreen_nonBlocking_P(_i("Autoloading filament available only when filament sensor is turned on..."), nlines); ////MSG_AUTOLOADING_ONLY_IF_FSENS_ON c=20 r=4
 		tim = millis();
 	}
-	if (lcd_clicked())
-          menu_action_back();
+    menu_back_if_clicked();
 }
 
 static void lcd_fsensor_fail()
@@ -3592,8 +3802,7 @@ uint8_t nlines;
           lcd_display_message_fullscreen_nonBlocking_P(_i("ERROR: Filament sensor is not responding, please check connection."), nlines);////MSG_FSENS_NOT_RESPONDING c=20 r=4
 		tim = millis();
 	}
-	if (lcd_clicked())
-          menu_action_back();
+    menu_back_if_clicked();
 }
 #endif //PAT9125
 
@@ -3631,7 +3840,7 @@ static void lcd_silent_mode_set() {
   st_current_init();
 #ifdef TMC2130
   if (CrashDetectMenu && (SilentModeMenu != SILENT_MODE_NORMAL))
-	  menu_action_submenu(lcd_crash_mode_info2);
+	  menu_submenu(lcd_crash_mode_info2);
 #endif //TMC2130
 }
 
@@ -3658,11 +3867,11 @@ static void lcd_fsensor_state_set()
     if (!FSensorStateMenu) {
         fsensor_disable();
         if (filament_autoload_enabled)
-            menu_action_submenu(lcd_filament_autoload_info);
+            menu_submenu(lcd_filament_autoload_info);
     }else{
         fsensor_enable();
         if (fsensor_not_responding)
-            menu_action_submenu(lcd_fsensor_fail);
+            menu_submenu(lcd_fsensor_fail);
     }
 }
 #endif //PAT9125
@@ -3679,15 +3888,51 @@ void lcd_set_progress() {
 #endif
 
 #if (LANG_MODE != 0)
+
+void menu_setlang(unsigned char lang)
+{
+	if (!lang_select(lang))
+	{
+		if (lcd_show_fullscreen_message_yes_no_and_wait_P(_i("Copy selected language from XFLASH?"), false, true))
+			lang_boot_update_start(lang);
+		lcd_update_enable(true);
+		lcd_implementation_clear();
+		lcd_goto_menu(lcd_language_menu);
+		lcd_timeoutToStatus.stop(); //infinite timeout
+		lcdDrawUpdate = 2;
+	}
+}
+
 static void lcd_language_menu()
 {
-	START_MENU();
-	if (lang_is_selected()) MENU_ITEM(back, _T(MSG_SETTINGS), 0);
-	MENU_ITEM(setlang, lang_get_name_by_code(lang_get_code(0)), 0);
-//	MENU_ITEM(setlang, lang_get_name_by_code(lang_get_code(1)), 1);
-	for (int i = 2; i < lang_get_count(); i++) //skip seconday language - solved in lang_select
-		MENU_ITEM(setlang, lang_get_name_by_code(lang_get_code(i)), i);
-	END_MENU();
+	MENU_BEGIN();
+	if (lang_is_selected()) MENU_ITEM_BACK_P(_T(MSG_SETTINGS)); //
+	if (menu_item_text_P(lang_get_name_by_code(lang_get_code(0)))) //primary language
+	{
+		menu_setlang(0);
+		return;
+	}
+	uint8_t cnt = lang_get_count();
+#ifdef W25X20CL
+	if (cnt == 2) //display secondary language in case of clear xflash 
+	{
+		if (menu_item_text_P(lang_get_name_by_code(lang_get_code(1))))
+		{
+			menu_setlang(1);
+			return;
+		}
+	}
+	else
+		for (int i = 2; i < cnt; i++) //skip seconday language - solved in lang_select (MK3)
+#else //W25X20CL
+		for (int i = 1; i < cnt; i++) //all seconday languages (MK2/25)
+#endif //W25X20CL
+			if (menu_item_text_P(lang_get_name_by_code(lang_get_code(i))))
+			{
+				menu_setlang(i);
+				return;
+			}
+	MENU_END();
 }
 #endif //(LANG_MODE != 0)
 
@@ -3713,10 +3958,10 @@ void lcd_mesh_calibration_z()
 
 void lcd_pinda_calibration_menu()
 {
-	START_MENU();
-		MENU_ITEM(back, _T(MSG_MENU_CALIBRATION), 0);
-		MENU_ITEM(submenu, _i("Calibrate"), lcd_calibrate_pinda);////MSG_CALIBRATE_PINDA c=17 r=1
-	END_MENU();
+	MENU_BEGIN();
+		MENU_ITEM_BACK_P(_T(MSG_MENU_CALIBRATION));
+		MENU_ITEM_SUBMENU_P(_i("Calibrate"), lcd_calibrate_pinda);////MSG_CALIBRATE_PINDA c=17 r=1
+	MENU_END();
 }
 
 void lcd_temp_calibration_set() {
@@ -4075,26 +4320,30 @@ void lcd_wizard(int state) {
 static void lcd_settings_menu()
 {
   EEPROM_read(EEPROM_SILENT, (uint8_t*)&SilentModeMenu, sizeof(SilentModeMenu));
-  START_MENU();
+  MENU_BEGIN();
 
-  MENU_ITEM(back, _T(MSG_MAIN), lcd_settings_menu_back);
+  if (menu_item_back_P(_T(MSG_MAIN)))
+  {
+	  lcd_settings_menu_back();
+	  return;
+  }
 
-  MENU_ITEM(submenu, _i("Temperature"), lcd_control_temperature_menu);////MSG_TEMPERATURE c=0 r=0
+  MENU_ITEM_SUBMENU_P(_i("Temperature"), lcd_control_temperature_menu);////MSG_TEMPERATURE c=0 r=0
   if (!homing_flag)
   {
-	  MENU_ITEM(submenu, _i("Move axis"), lcd_move_menu_1mm);////MSG_MOVE_AXIS c=0 r=0
+	  MENU_ITEM_SUBMENU_P(_i("Move axis"), lcd_move_menu_1mm);////MSG_MOVE_AXIS c=0 r=0
   }
   if (!isPrintPaused)
   {
-	  MENU_ITEM(gcode, _i("Disable steppers"), PSTR("M84"));////MSG_DISABLE_STEPPERS c=0 r=0
+	  MENU_ITEM_GCODE_P(_i("Disable steppers"), PSTR("M84"));////MSG_DISABLE_STEPPERS c=0 r=0
   }
 #ifndef TMC2130
   if (!farm_mode) { //dont show in menu if we are in farm mode
 	  switch (SilentModeMenu) {
-	  case SILENT_MODE_POWER: MENU_ITEM(function, _T(MSG_SILENT_MODE_OFF), lcd_silent_mode_set); break;
-	  case SILENT_MODE_SILENT: MENU_ITEM(function, _T(MSG_SILENT_MODE_ON), lcd_silent_mode_set); break;
-	  case SILENT_MODE_AUTO: MENU_ITEM(function, _T(MSG_AUTO_MODE_ON), lcd_silent_mode_set); break;
-	  default: MENU_ITEM(function, _T(MSG_SILENT_MODE_OFF), lcd_silent_mode_set); break; // (probably) not needed
+	  case SILENT_MODE_POWER: MENU_ITEM_FUNCTION_P(_T(MSG_SILENT_MODE_OFF), lcd_silent_mode_set); break;
+	  case SILENT_MODE_SILENT: MENU_ITEM_FUNCTION_P(_T(MSG_SILENT_MODE_ON), lcd_silent_mode_set); break;
+	  case SILENT_MODE_AUTO: MENU_ITEM_FUNCTION_P(_T(MSG_AUTO_MODE_ON), lcd_silent_mode_set); break;
+	  default: MENU_ITEM_FUNCTION_P(_T(MSG_SILENT_MODE_OFF), lcd_silent_mode_set); break; // (probably) not needed
 	  }
   }
 #endif //TMC2130
@@ -4104,24 +4353,24 @@ static void lcd_settings_menu()
   if (FSensorStateMenu == 0) {
       if (fsensor_not_responding){
           // Filament sensor not working
-          MENU_ITEM(function, _i("Fil. sensor [N/A]"), lcd_fsensor_state_set);////MSG_FSENSOR_NA c=0 r=0
-          MENU_ITEM(submenu, _T(MSG_FSENS_AUTOLOAD_NA), lcd_fsensor_fail);
+          MENU_ITEM_FUNCTION_P(_i("Fil. sensor [N/A]"), lcd_fsensor_state_set);////MSG_FSENSOR_NA c=0 r=0
+          MENU_ITEM_SUBMENU_P(_T(MSG_FSENS_AUTOLOAD_NA), lcd_fsensor_fail);
       }
       else{
           // Filament sensor turned off, working, no problems
-          MENU_ITEM(function, _T(MSG_FSENSOR_OFF), lcd_fsensor_state_set);
-          MENU_ITEM(submenu,_T(MSG_FSENS_AUTOLOAD_NA), lcd_filament_autoload_info);
+          MENU_ITEM_FUNCTION_P(_T(MSG_FSENSOR_OFF), lcd_fsensor_state_set);
+          MENU_ITEM_SUBMENU_P(_T(MSG_FSENS_AUTOLOAD_NA), lcd_filament_autoload_info);
       }
   } else {
       // Filament sensor turned on, working, no problems
-      MENU_ITEM(function, _T(MSG_FSENSOR_ON), lcd_fsensor_state_set);
+      MENU_ITEM_FUNCTION_P(_T(MSG_FSENSOR_ON), lcd_fsensor_state_set);
      
 
       if (filament_autoload_enabled) {
-          MENU_ITEM(function, _i("F. autoload  [on]"), lcd_set_filament_autoload);////MSG_FSENS_AUTOLOAD_ON c=17 r=1
+          MENU_ITEM_FUNCTION_P(_i("F. autoload  [on]"), lcd_set_filament_autoload);////MSG_FSENS_AUTOLOAD_ON c=17 r=1
       }
       else {
-          MENU_ITEM(function, _i("F. autoload [off]"), lcd_set_filament_autoload);////MSG_FSENS_AUTOLOAD_OFF c=17 r=1
+          MENU_ITEM_FUNCTION_P(_i("F. autoload [off]"), lcd_set_filament_autoload);////MSG_FSENS_AUTOLOAD_OFF c=17 r=1
       }
       
   }
@@ -4129,23 +4378,23 @@ static void lcd_settings_menu()
 #endif //PAT9125
 
   if (fans_check_enabled == true) {
-	  MENU_ITEM(function, _i("Fans check   [on]"), lcd_set_fan_check);////MSG_FANS_CHECK_ON c=17 r=1
+	  MENU_ITEM_FUNCTION_P(_i("Fans check   [on]"), lcd_set_fan_check);////MSG_FANS_CHECK_ON c=17 r=1
   }
   else {
-	  MENU_ITEM(function, _i("Fans check  [off]"), lcd_set_fan_check);////MSG_FANS_CHECK_OFF c=17 r=1
+	  MENU_ITEM_FUNCTION_P(_i("Fans check  [off]"), lcd_set_fan_check);////MSG_FANS_CHECK_OFF c=17 r=1
   }
 
 #ifdef TMC2130
   if(!farm_mode)
   {
-    if (SilentModeMenu == SILENT_MODE_NORMAL) MENU_ITEM(function, _T(MSG_STEALTH_MODE_OFF), lcd_silent_mode_set);
-    else MENU_ITEM(function, _T(MSG_STEALTH_MODE_ON), lcd_silent_mode_set);
+	if (SilentModeMenu == SILENT_MODE_NORMAL) { MENU_ITEM_FUNCTION_P(_T(MSG_STEALTH_MODE_OFF), lcd_silent_mode_set); }
+    else MENU_ITEM_FUNCTION_P(_T(MSG_STEALTH_MODE_ON), lcd_silent_mode_set);
     if (SilentModeMenu == SILENT_MODE_NORMAL)
     {
-      if (CrashDetectMenu == 0) MENU_ITEM(function, _T(MSG_CRASHDETECT_OFF), lcd_crash_mode_set);
-      else MENU_ITEM(function, _T(MSG_CRASHDETECT_ON), lcd_crash_mode_set);
+	  if (CrashDetectMenu == 0) { MENU_ITEM_FUNCTION_P(_T(MSG_CRASHDETECT_OFF), lcd_crash_mode_set); }
+      else MENU_ITEM_FUNCTION_P(_T(MSG_CRASHDETECT_ON), lcd_crash_mode_set);
     }
-    else MENU_ITEM(submenu, _T(MSG_CRASHDETECT_NA), lcd_crash_mode_info);
+    else MENU_ITEM_SUBMENU_P(_T(MSG_CRASHDETECT_NA), lcd_crash_mode_info);
   }
 
 #ifdef TMC2130_LINEARITY_CORRECTION_XYZ
@@ -4157,33 +4406,33 @@ static void lcd_settings_menu()
 #endif //TMC2130
 
   if (temp_cal_active == false) {
-	  MENU_ITEM(function, _i("Temp. cal.  [off]"), lcd_temp_calibration_set);////MSG_TEMP_CALIBRATION_OFF c=20 r=1
+	  MENU_ITEM_FUNCTION_P(_i("Temp. cal.  [off]"), lcd_temp_calibration_set);////MSG_TEMP_CALIBRATION_OFF c=20 r=1
   }
   else {
-	  MENU_ITEM(function, _i("Temp. cal.   [on]"), lcd_temp_calibration_set);////MSG_TEMP_CALIBRATION_ON c=20 r=1
+	  MENU_ITEM_FUNCTION_P(_i("Temp. cal.   [on]"), lcd_temp_calibration_set);////MSG_TEMP_CALIBRATION_ON c=20 r=1
   }
 #ifdef HAS_SECOND_SERIAL_PORT
   if (selectedSerialPort == 0) {
-	  MENU_ITEM(function, _i("RPi port    [off]"), lcd_second_serial_set);////MSG_SECOND_SERIAL_OFF c=17 r=1
+	  MENU_ITEM_FUNCTION_P(_i("RPi port    [off]"), lcd_second_serial_set);////MSG_SECOND_SERIAL_OFF c=17 r=1
   }
   else {
-	  MENU_ITEM(function, _i("RPi port     [on]"), lcd_second_serial_set);////MSG_SECOND_SERIAL_ON c=17 r=1
+	  MENU_ITEM_FUNCTION_P(_i("RPi port     [on]"), lcd_second_serial_set);////MSG_SECOND_SERIAL_ON c=17 r=1
   }
 #endif //HAS_SECOND_SERIAL
 
   if (!isPrintPaused && !homing_flag)
 	{
-		MENU_ITEM(submenu, _T(MSG_BABYSTEP_Z), lcd_babystep_z);
+		MENU_ITEM_SUBMENU_P(_T(MSG_BABYSTEP_Z), lcd_babystep_z);
 	}
 
 #if (LANG_MODE != 0)
-	MENU_ITEM(submenu, _i("Select language"), lcd_language_menu);////MSG_LANGUAGE_SELECT c=0 r=0
+	MENU_ITEM_SUBMENU_P(_i("Select language"), lcd_language_menu);////MSG_LANGUAGE_SELECT c=0 r=0
 #endif //(LANG_MODE != 0)
 
   if (card.ToshibaFlashAir_isEnabled()) {
-    MENU_ITEM(function, _i("SD card [FlshAir]"), lcd_toshiba_flash_air_compatibility_toggle);////MSG_TOSHIBA_FLASH_AIR_COMPATIBILITY_ON c=19 r=1
+    MENU_ITEM_FUNCTION_P(_i("SD card [FlshAir]"), lcd_toshiba_flash_air_compatibility_toggle);////MSG_TOSHIBA_FLASH_AIR_COMPATIBILITY_ON c=19 r=1
   } else {
-    MENU_ITEM(function, _i("SD card  [normal]"), lcd_toshiba_flash_air_compatibility_toggle);////MSG_TOSHIBA_FLASH_AIR_COMPATIBILITY_OFF c=19 r=1
+    MENU_ITEM_FUNCTION_P(_i("SD card  [normal]"), lcd_toshiba_flash_air_compatibility_toggle);////MSG_TOSHIBA_FLASH_AIR_COMPATIBILITY_OFF c=19 r=1
   }
 
   #ifdef SDCARD_SORT_ALPHA
@@ -4191,20 +4440,20 @@ static void lcd_settings_menu()
 	  uint8_t sdSort;
 	  EEPROM_read(EEPROM_SD_SORT, (uint8_t*)&sdSort, sizeof(sdSort));
 	  switch (sdSort) {
-		  case SD_SORT_TIME: MENU_ITEM(function, _i("Sort:      [Time]"), lcd_sort_type_set); break;////MSG_SORT_TIME c=17 r=1
-		  case SD_SORT_ALPHA: MENU_ITEM(function, _i("Sort:  [Alphabet]"), lcd_sort_type_set); break;////MSG_SORT_ALPHA c=17 r=1
-		  default: MENU_ITEM(function, _i("Sort:      [None]"), lcd_sort_type_set);////MSG_SORT_NONE c=17 r=1
+		  case SD_SORT_TIME: MENU_ITEM_FUNCTION_P(_i("Sort:      [Time]"), lcd_sort_type_set); break;////MSG_SORT_TIME c=17 r=1
+		  case SD_SORT_ALPHA: MENU_ITEM_FUNCTION_P(_i("Sort:  [Alphabet]"), lcd_sort_type_set); break;////MSG_SORT_ALPHA c=17 r=1
+		  default: MENU_ITEM_FUNCTION_P(_i("Sort:      [None]"), lcd_sort_type_set);////MSG_SORT_NONE c=17 r=1
 	  }
   }
   #endif // SDCARD_SORT_ALPHA
     
     if (farm_mode)
     {
-        MENU_ITEM(submenu, PSTR("Farm number"), lcd_farm_no);
-		MENU_ITEM(function, PSTR("Disable farm mode"), lcd_disable_farm_mode);
+        MENU_ITEM_SUBMENU_P(PSTR("Farm number"), lcd_farm_no);
+		MENU_ITEM_FUNCTION_P(PSTR("Disable farm mode"), lcd_disable_farm_mode);
     }
 
-	END_MENU();
+	MENU_END();
 }
 
 static void lcd_selftest_()
@@ -4238,7 +4487,7 @@ static void lcd_settings_menu_back()
     if (changed) tmc2130_init();
 #endif //TMC2130
     currentMenu = lcd_main_menu;
-    lcd_main_menu();
+//    lcd_main_menu();
 }
 #ifdef EXPERIMENTAL_FEATURES
 
@@ -4279,27 +4528,27 @@ static void lcd_homing_accuracy_menu_advanced_back()
 static void lcd_homing_accuracy_menu_advanced()
 {
 	lcd_timeoutToStatus.start();
-	START_MENU();
-	MENU_ITEM(back, PSTR("Homing accuracy"), lcd_homing_accuracy_menu_advanced_back);
-	MENU_ITEM(function, PSTR("Reset def. steps"), lcd_homing_accuracy_menu_advanced_reset);
+	MENU_BEGIN();
+///!	MENU_ITEM_BACK_P(PSTR("Homing accuracy"), lcd_homing_accuracy_menu_advanced_back);
+	MENU_ITEM_FUNCTION_P(PSTR("Reset def. steps"), lcd_homing_accuracy_menu_advanced_reset);
 	MENU_ITEM_EDIT(byte3, PSTR("X-origin"),  &tmc2130_home_origin[X_AXIS],  0, 63);
 	MENU_ITEM_EDIT(byte3, PSTR("Y-origin"),  &tmc2130_home_origin[Y_AXIS],  0, 63);
 	MENU_ITEM_EDIT(byte3, PSTR("X-bsteps"),  &tmc2130_home_bsteps[X_AXIS],  0, 128);
 	MENU_ITEM_EDIT(byte3, PSTR("Y-bsteps"),  &tmc2130_home_bsteps[Y_AXIS],  0, 128);
 	MENU_ITEM_EDIT(byte3, PSTR("X-fsteps"),  &tmc2130_home_fsteps[X_AXIS],  0, 128);
 	MENU_ITEM_EDIT(byte3, PSTR("Y-fsteps"),  &tmc2130_home_fsteps[Y_AXIS],  0, 128);
-	END_MENU();
+	MENU_END();
 }
 
 static void lcd_homing_accuracy_menu()
 {
-	START_MENU();
-	MENU_ITEM(back, PSTR("Experimental"), 0);
-	MENU_ITEM(function, tmc2130_home_enabled?PSTR("Accur. homing  On"):PSTR("Accur. homing Off"), lcd_accurate_home_set);
-    MENU_ITEM(gcode, PSTR("Calibrate X"), PSTR("G28XC"));
-    MENU_ITEM(gcode, PSTR("Calibrate Y"), PSTR("G28YC"));
-	MENU_ITEM(submenu, PSTR("Advanced"), lcd_homing_accuracy_menu_advanced);
-	END_MENU();
+	MENU_BEGIN();
+	MENU_ITEM_BACK_P(PSTR("Experimental"));
+	MENU_ITEM_FUNCTION_P(tmc2130_home_enabled?PSTR("Accur. homing  On"):PSTR("Accur. homing Off"), lcd_accurate_home_set);
+    MENU_ITEM_GCODE_P(PSTR("Calibrate X"), PSTR("G28XC"));
+    MENU_ITEM_GCODE_P(PSTR("Calibrate Y"), PSTR("G28YC"));
+	MENU_ITEM_SUBMENU_P(PSTR("Advanced"), lcd_homing_accuracy_menu_advanced);
+	MENU_END();
 }
 
 static void lcd_ustep_resolution_menu_save()
@@ -4360,14 +4609,14 @@ static void lcd_ustep_resolution_reset_def_xyze()
 static void lcd_ustep_resolution_menu()
 {
 	lcd_timeoutToStatus.start();
-	START_MENU();
-	MENU_ITEM(back, PSTR("Experimental"), lcd_ustep_resolution_menu_back);
-	MENU_ITEM(function, PSTR("Reset defaults"),  lcd_ustep_resolution_reset_def_xyze);
+	MENU_BEGIN();
+///!	MENU_ITEM_BACK_P(PSTR("Experimental"), lcd_ustep_resolution_menu_back);
+	MENU_ITEM_FUNCTION_P(PSTR("Reset defaults"),  lcd_ustep_resolution_reset_def_xyze);
 	MENU_ITEM_EDIT(mres, PSTR("X-resolution"),  &tmc2130_mres[X_AXIS],  4, 4);
 	MENU_ITEM_EDIT(mres, PSTR("Y-resolution"),  &tmc2130_mres[Y_AXIS],  4, 4);
 	MENU_ITEM_EDIT(mres, PSTR("Z-resolution"),  &tmc2130_mres[Z_AXIS],  4, 4);
 	MENU_ITEM_EDIT(mres, PSTR("E-resolution"),  &tmc2130_mres[E_AXIS],  2, 5);
-	END_MENU();
+	MENU_END();
 }
 
 
@@ -4408,15 +4657,15 @@ static void lcd_ustep_linearity_menu_reset()
 static void lcd_ustep_linearity_menu()
 {
 	lcd_timeoutToStatus.start();
-	START_MENU();
-	MENU_ITEM(back, PSTR("Experimental"), lcd_ustep_linearity_menu_back);
-	MENU_ITEM(function, PSTR("Reset correction"), lcd_ustep_linearity_menu_reset);
-	MENU_ITEM(function, PSTR("Recomended config"), lcd_ustep_linearity_menu_recomended);
+	MENU_BEGIN();
+///!	MENU_ITEM_BACK_P(PSTR("Experimental"), lcd_ustep_linearity_menu_back);
+	MENU_ITEM_FUNCTION_P(PSTR("Reset correction"), lcd_ustep_linearity_menu_reset);
+	MENU_ITEM_FUNCTION_P(PSTR("Recomended config"), lcd_ustep_linearity_menu_recomended);
 	MENU_ITEM_EDIT(wfac, PSTR("X-correction"),  &tmc2130_wave_fac[X_AXIS],  TMC2130_WAVE_FAC1000_MIN-TMC2130_WAVE_FAC1000_STP, TMC2130_WAVE_FAC1000_MAX);
 	MENU_ITEM_EDIT(wfac, PSTR("Y-correction"),  &tmc2130_wave_fac[Y_AXIS],  TMC2130_WAVE_FAC1000_MIN-TMC2130_WAVE_FAC1000_STP, TMC2130_WAVE_FAC1000_MAX);
 	MENU_ITEM_EDIT(wfac, PSTR("Z-correction"),  &tmc2130_wave_fac[Z_AXIS],  TMC2130_WAVE_FAC1000_MIN-TMC2130_WAVE_FAC1000_STP, TMC2130_WAVE_FAC1000_MAX);
 	MENU_ITEM_EDIT(wfac, PSTR("E-correction"),  &tmc2130_wave_fac[E_AXIS],  TMC2130_WAVE_FAC1000_MIN-TMC2130_WAVE_FAC1000_STP, TMC2130_WAVE_FAC1000_MAX);
-	END_MENU();
+	MENU_END();
 }
 
 static void lcd_experimantal_menu_save_all()
@@ -4438,61 +4687,61 @@ static void lcd_experimantal_menu_disable_all()
 
 static void lcd_experimantal_menu()
 {
-	START_MENU();
-	MENU_ITEM(back, _T(MSG_MAIN), 0);
-	MENU_ITEM(function, PSTR("All Xfeatures off"), lcd_experimantal_menu_disable_all);
-	MENU_ITEM(submenu, PSTR("Homing accuracy"), lcd_homing_accuracy_menu);
-	MENU_ITEM(submenu, PSTR("uStep resolution"), lcd_ustep_resolution_menu);
-	MENU_ITEM(submenu, PSTR("uStep linearity"), lcd_ustep_linearity_menu);
-	END_MENU();
+	MENU_BEGIN();
+	MENU_ITEM_BACK_P(_T(MSG_MAIN));
+	MENU_ITEM_FUNCTION_P(PSTR("All Xfeatures off"), lcd_experimantal_menu_disable_all);
+	MENU_ITEM_SUBMENU_P(PSTR("Homing accuracy"), lcd_homing_accuracy_menu);
+	MENU_ITEM_SUBMENU_P(PSTR("uStep resolution"), lcd_ustep_resolution_menu);
+	MENU_ITEM_SUBMENU_P(PSTR("uStep linearity"), lcd_ustep_linearity_menu);
+	MENU_END();
 }
 #endif //EXPERIMENTAL_FEATURES
 
 
 static void lcd_calibration_menu()
 {
-  START_MENU();
-  MENU_ITEM(back, _T(MSG_MAIN), 0);
+  MENU_BEGIN();
+  MENU_ITEM_BACK_P(_T(MSG_MAIN));
   if (!isPrintPaused)
   {
-	MENU_ITEM(function, _i("Wizard"), lcd_wizard);////MSG_WIZARD c=17 r=1
-	MENU_ITEM(submenu, _i("First layer cal."), lcd_v2_calibration);////MSG_V2_CALIBRATION c=17 r=1
-	MENU_ITEM(gcode, _T(MSG_AUTO_HOME), PSTR("G28 W"));
-	MENU_ITEM(function, _i("Selftest         "), lcd_selftest_v);////MSG_SELFTEST c=0 r=0
+	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_GCODE_P(_T(MSG_AUTO_HOME), PSTR("G28 W"));
+	MENU_ITEM_FUNCTION_P(_i("Selftest         "), lcd_selftest_v);////MSG_SELFTEST c=0 r=0
 #ifdef MK1BP
     // MK1
     // "Calibrate Z"
-    MENU_ITEM(gcode, _T(MSG_HOMEYZ), PSTR("G28 Z"));
+    MENU_ITEM_GCODE_P(_T(MSG_HOMEYZ), PSTR("G28 Z"));
 #else //MK1BP
     // MK2
-    MENU_ITEM(function, _i("Calibrate XYZ"), lcd_mesh_calibration);////MSG_CALIBRATE_BED c=0 r=0
+    MENU_ITEM_FUNCTION_P(_i("Calibrate XYZ"), lcd_mesh_calibration);////MSG_CALIBRATE_BED c=0 r=0
     // "Calibrate Z" with storing the reference values to EEPROM.
-    MENU_ITEM(submenu, _T(MSG_HOMEYZ), lcd_mesh_calibration_z);
+    MENU_ITEM_SUBMENU_P(_T(MSG_HOMEYZ), lcd_mesh_calibration_z);
 #ifndef SNMM
-	//MENU_ITEM(function, _i("Calibrate E"), lcd_calibrate_extruder);////MSG_CALIBRATE_E c=20 r=1
+	//MENU_ITEM_FUNCTION_P(_i("Calibrate E"), lcd_calibrate_extruder);////MSG_CALIBRATE_E c=20 r=1
 #endif
     // "Mesh Bed Leveling"
-    MENU_ITEM(submenu, _i("Mesh Bed Leveling"), lcd_mesh_bedleveling);////MSG_MESH_BED_LEVELING c=0 r=0
+    MENU_ITEM_SUBMENU_P(_i("Mesh Bed Leveling"), lcd_mesh_bedleveling);////MSG_MESH_BED_LEVELING c=0 r=0
 	
 #endif //MK1BP
 
-    MENU_ITEM(submenu, _i("Bed level correct"), lcd_adjust_bed);////MSG_BED_CORRECTION_MENU c=0 r=0
-	MENU_ITEM(submenu, _i("PID calibration"), pid_extruder);////MSG_PID_EXTRUDER c=17 r=1
+    MENU_ITEM_SUBMENU_P(_i("Bed level correct"), lcd_adjust_bed);////MSG_BED_CORRECTION_MENU c=0 r=0
+	MENU_ITEM_SUBMENU_P(_i("PID calibration"), pid_extruder);////MSG_PID_EXTRUDER c=17 r=1
 #ifndef TMC2130
-    MENU_ITEM(submenu, _i("Show end stops"), menu_show_end_stops);////MSG_SHOW_END_STOPS c=17 r=1
+    MENU_ITEM_SUBMENU_P(_i("Show end stops"), menu_show_end_stops);////MSG_SHOW_END_STOPS c=17 r=1
 #endif
 #ifndef MK1BP
-    MENU_ITEM(gcode, _i("Reset XYZ calibr."), PSTR("M44"));////MSG_CALIBRATE_BED_RESET c=0 r=0
+    MENU_ITEM_GCODE_P(_i("Reset XYZ calibr."), PSTR("M44"));////MSG_CALIBRATE_BED_RESET c=0 r=0
 #endif //MK1BP
 #ifndef SNMM
-	//MENU_ITEM(function, MSG_RESET_CALIBRATE_E, lcd_extr_cal_reset);
+	//MENU_ITEM_FUNCTION_P(MSG_RESET_CALIBRATE_E, lcd_extr_cal_reset);
 #endif
 #ifndef MK1BP
-	MENU_ITEM(submenu, _i("Temp. calibration"), lcd_pinda_calibration_menu);////MSG_CALIBRATION_PINDA_MENU c=17 r=1
+	MENU_ITEM_SUBMENU_P(_i("Temp. calibration"), lcd_pinda_calibration_menu);////MSG_CALIBRATION_PINDA_MENU c=17 r=1
 #endif //MK1BP
   }
   
-  END_MENU();
+  MENU_END();
 }
 
 void bowden_menu() {
@@ -5135,39 +5384,39 @@ static void extr_unload_3() {
 
 static void fil_load_menu()
 {
-	START_MENU();
-	MENU_ITEM(back, _T(MSG_MAIN), 0);
-	MENU_ITEM(function, _i("Load all"), load_all);////MSG_LOAD_ALL c=0 r=0
-	MENU_ITEM(function, _i("Load filament 1"), extr_adj_0);////MSG_LOAD_FILAMENT_1 c=17 r=0
-	MENU_ITEM(function, _i("Load filament 2"), extr_adj_1);////MSG_LOAD_FILAMENT_2 c=17 r=0
-	MENU_ITEM(function, _i("Load filament 3"), extr_adj_2);////MSG_LOAD_FILAMENT_3 c=17 r=0
-	MENU_ITEM(function, _i("Load filament 4"), extr_adj_3);////MSG_LOAD_FILAMENT_4 c=17 r=0
+	MENU_BEGIN();
+	MENU_ITEM_BACK_P(_T(MSG_MAIN));
+	MENU_ITEM_FUNCTION_P(_i("Load all"), load_all);////MSG_LOAD_ALL c=0 r=0
+	MENU_ITEM_FUNCTION_P(_i("Load filament 1"), extr_adj_0);////MSG_LOAD_FILAMENT_1 c=17 r=0
+	MENU_ITEM_FUNCTION_P(_i("Load filament 2"), extr_adj_1);////MSG_LOAD_FILAMENT_2 c=17 r=0
+	MENU_ITEM_FUNCTION_P(_i("Load filament 3"), extr_adj_2);////MSG_LOAD_FILAMENT_3 c=17 r=0
+	MENU_ITEM_FUNCTION_P(_i("Load filament 4"), extr_adj_3);////MSG_LOAD_FILAMENT_4 c=17 r=0
 	
-	END_MENU();
+	MENU_END();
 }
 
 static void fil_unload_menu()
 {
-	START_MENU();
-	MENU_ITEM(back, _T(MSG_MAIN), 0);
-	MENU_ITEM(function, _i("Unload all"), extr_unload_all);////MSG_UNLOAD_ALL c=0 r=0
-	MENU_ITEM(function, _i("Unload filament 1"), extr_unload_0);////MSG_UNLOAD_FILAMENT_1 c=17 r=0
-	MENU_ITEM(function, _i("Unload filament 2"), extr_unload_1);////MSG_UNLOAD_FILAMENT_2 c=17 r=0
-	MENU_ITEM(function, _i("Unload filament 3"), extr_unload_2);////MSG_UNLOAD_FILAMENT_3 c=17 r=0
-	MENU_ITEM(function, _i("Unload filament 4"), extr_unload_3);////MSG_UNLOAD_FILAMENT_4 c=17 r=0
+	MENU_BEGIN();
+	MENU_ITEM_BACK_P(_T(MSG_MAIN));
+	MENU_ITEM_FUNCTION_P(_i("Unload all"), extr_unload_all);////MSG_UNLOAD_ALL c=0 r=0
+	MENU_ITEM_FUNCTION_P(_i("Unload filament 1"), extr_unload_0);////MSG_UNLOAD_FILAMENT_1 c=17 r=0
+	MENU_ITEM_FUNCTION_P(_i("Unload filament 2"), extr_unload_1);////MSG_UNLOAD_FILAMENT_2 c=17 r=0
+	MENU_ITEM_FUNCTION_P(_i("Unload filament 3"), extr_unload_2);////MSG_UNLOAD_FILAMENT_3 c=17 r=0
+	MENU_ITEM_FUNCTION_P(_i("Unload filament 4"), extr_unload_3);////MSG_UNLOAD_FILAMENT_4 c=17 r=0
 
-	END_MENU();
+	MENU_END();
 }
 
 static void change_extr_menu(){
-	START_MENU();
-	MENU_ITEM(back, _T(MSG_MAIN), 0);
-	MENU_ITEM(function, _i("Extruder 1"), extr_change_0);////MSG_EXTRUDER_1 c=17 r=1
-	MENU_ITEM(function, _i("Extruder 2"), extr_change_1);////MSG_EXTRUDER_2 c=17 r=1
-	MENU_ITEM(function, _i("Extruder 3"), extr_change_2);////MSG_EXTRUDER_3 c=17 r=1
-	MENU_ITEM(function, _i("Extruder 4"), extr_change_3);////MSG_EXTRUDER_4 c=17 r=1
+	MENU_BEGIN();
+	MENU_ITEM_BACK_P(_T(MSG_MAIN));
+	MENU_ITEM_FUNCTION_P(_i("Extruder 1"), extr_change_0);////MSG_EXTRUDER_1 c=17 r=1
+	MENU_ITEM_FUNCTION_P(_i("Extruder 2"), extr_change_1);////MSG_EXTRUDER_2 c=17 r=1
+	MENU_ITEM_FUNCTION_P(_i("Extruder 3"), extr_change_2);////MSG_EXTRUDER_3 c=17 r=1
+	MENU_ITEM_FUNCTION_P(_i("Extruder 4"), extr_change_3);////MSG_EXTRUDER_4 c=17 r=1
 
-	END_MENU();
+	MENU_END();
 }
 
 #endif
@@ -5415,23 +5664,23 @@ static void lcd_main_menu()
 {
 
   SDscrool = 0;
-  START_MENU();
+  MENU_BEGIN();
 
   // Majkl superawesome menu
 
 
- MENU_ITEM(back, _T(MSG_WATCH), 0);
+ MENU_ITEM_BACK_P(_T(MSG_WATCH));
 
 #ifdef RESUME_DEBUG 
  if (!saved_printing) 
-  MENU_ITEM(function, PSTR("tst - Save"), lcd_menu_test_save);
+  MENU_ITEM_FUNCTION_P(PSTR("tst - Save"), lcd_menu_test_save);
  else
-  MENU_ITEM(function, PSTR("tst - Restore"), lcd_menu_test_restore);
+  MENU_ITEM_FUNCTION_P(PSTR("tst - Restore"), lcd_menu_test_restore);
 #endif //RESUME_DEBUG 
 
 #ifdef TMC2130_DEBUG
- MENU_ITEM(function, PSTR("recover print"), recover_print);
- MENU_ITEM(function, PSTR("power panic"), uvlo_);
+ 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 )
@@ -5447,10 +5696,10 @@ static void lcd_main_menu()
         if (card.filename[0] == '/')
         {
 #if SDCARDDETECT == -1
-            MENU_ITEM(function, _T(MSG_REFRESH), lcd_sd_refresh);
+            MENU_ITEM_FUNCTION_P(_T(MSG_REFRESH), lcd_sd_refresh);
 #endif
         } else {
-            MENU_ITEM(function, PSTR(LCD_STR_FOLDER ".."), lcd_sd_updir);
+            MENU_ITEM_FUNCTION_P(PSTR(LCD_STR_FOLDER ".."), lcd_sd_updir);
         }
         
         for (uint16_t i = 0; i < fileCnt; i++)
@@ -5464,10 +5713,10 @@ static void lcd_main_menu()
 #endif
                 if (card.filenameIsDir)
                 {
-                    MENU_ITEM(sddirectory, _T(MSG_CARD_MENU), card.filename, card.longFilename);
+                    MENU_ITEM_SDDIR(_T(MSG_CARD_MENU), card.filename, card.longFilename);
                 } else {
                     
-                    MENU_ITEM(sdfile, _T(MSG_CARD_MENU), card.filename, card.longFilename);
+                    MENU_ITEM_SDFILE(_T(MSG_CARD_MENU), card.filename, card.longFilename);
                     
                     
                     
@@ -5478,23 +5727,23 @@ static void lcd_main_menu()
             }
         }
         
-        MENU_ITEM(back, PSTR("- - - - - - - - -"), 0);
+        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)
   {
-	MENU_ITEM(submenu, _T(MSG_BABYSTEP_Z), lcd_babystep_z);//8
+	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))
   {
-    MENU_ITEM(submenu, _i("Tune"), lcd_tune_menu);////MSG_TUNE c=0 r=0
+    MENU_ITEM_SUBMENU_P(_i("Tune"), lcd_tune_menu);////MSG_TUNE c=0 r=0
   } else 
   {
-    MENU_ITEM(submenu, _i("Preheat"), lcd_preheat_menu);////MSG_PREHEAT c=0 r=0
+    MENU_ITEM_SUBMENU_P(_i("Preheat"), lcd_preheat_menu);////MSG_PREHEAT c=0 r=0
   }
 
 #ifdef SDSUPPORT
@@ -5505,35 +5754,35 @@ static void lcd_main_menu()
 		if (mesh_bed_leveling_flag == false && homing_flag == false) {
 			if (card.sdprinting)
 			{
-				MENU_ITEM(function, _i("Pause print"), lcd_sdcard_pause);////MSG_PAUSE_PRINT c=0 r=0
+				MENU_ITEM_FUNCTION_P(_i("Pause print"), lcd_sdcard_pause);////MSG_PAUSE_PRINT c=0 r=0
 			}
 			else
 			{
-				MENU_ITEM(function, _i("Resume print"), lcd_sdcard_resume);////MSG_RESUME_PRINT c=0 r=0
+				MENU_ITEM_FUNCTION_P(_i("Resume print"), lcd_sdcard_resume);////MSG_RESUME_PRINT c=0 r=0
 			}
-			MENU_ITEM(submenu, _T(MSG_STOP_PRINT), lcd_sdcard_stop);
+			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) {
-		//MENU_ITEM(submenu, _T(MSG_STOP_PRINT), lcd_sdcard_stop);
+		//MENU_ITEM_SUBMENU_P(_T(MSG_STOP_PRINT), lcd_sdcard_stop);
 	}
 	else
 	{
 		if (!is_usb_printing && (lcd_commands_type != LCD_COMMAND_V2_CAL))
 		{
-			//if (farm_mode) MENU_ITEM(submenu, MSG_FARM_CARD_MENU, lcd_farm_sdcard_menu);
-			/*else*/ MENU_ITEM(submenu, _T(MSG_CARD_MENU), lcd_sdcard_menu);
+			//if (farm_mode) MENU_ITEM_SUBMENU_P(MSG_FARM_CARD_MENU, lcd_farm_sdcard_menu);
+			/*else*/ MENU_ITEM_SUBMENU_P(_T(MSG_CARD_MENU), lcd_sdcard_menu);
 		}
 #if SDCARDDETECT < 1
-      MENU_ITEM(gcode, _i("Change SD card"), PSTR("M21"));  // SD-card changed by user////MSG_CNG_SDCARD c=0 r=0
+      MENU_ITEM_GCODE_P(_i("Change SD card"), PSTR("M21"));  // SD-card changed by user////MSG_CNG_SDCARD c=0 r=0
 #endif
     }
 	
   } else 
   {
-    MENU_ITEM(submenu, _i("No SD card"), lcd_sdcard_menu);////MSG_NO_CARD c=0 r=0
+    MENU_ITEM_SUBMENU_P(_i("No SD card"), lcd_sdcard_menu);////MSG_NO_CARD c=0 r=0
 #if SDCARDDETECT < 1
-    MENU_ITEM(gcode, _i("Init. SD card"), PSTR("M21")); // Manually initialize the SD-card via user interface////MSG_INIT_SDCARD c=0 r=0
+    MENU_ITEM_GCODE_P(_i("Init. SD card"), PSTR("M21")); // Manually initialize the SD-card via user interface////MSG_INIT_SDCARD c=0 r=0
 #endif
   }
 #endif
@@ -5543,7 +5792,7 @@ static void lcd_main_menu()
   {
 	  if (farm_mode)
 	  {
-		  MENU_ITEM(submenu, PSTR("Farm number"), lcd_farm_no);
+		  MENU_ITEM_SUBMENU_P(PSTR("Farm number"), lcd_farm_no);
 	  }
   } 
   else 
@@ -5551,38 +5800,39 @@ static void lcd_main_menu()
 	#ifndef SNMM
 #ifdef PAT9125
 	if ( ((filament_autoload_enabled == true) && (fsensor_enabled == true)))
-        MENU_ITEM(submenu, _i("AutoLoad filament"), lcd_menu_AutoLoadFilament);////MSG_AUTOLOAD_FILAMENT c=17 r=0
+        MENU_ITEM_SUBMENU_P(_i("AutoLoad filament"), lcd_menu_AutoLoadFilament);////MSG_AUTOLOAD_FILAMENT c=17 r=0
 	else
 #endif //PAT9125
-		MENU_ITEM(function, _T(MSG_LOAD_FILAMENT), lcd_LoadFilament);
-	MENU_ITEM(submenu, _T(MSG_UNLOAD_FILAMENT), lcd_unLoadFilament);
+		MENU_ITEM_FUNCTION_P(_T(MSG_LOAD_FILAMENT), lcd_LoadFilament);
+	MENU_ITEM_SUBMENU_P(_T(MSG_UNLOAD_FILAMENT), lcd_unLoadFilament);
 	#endif
 	#ifdef SNMM
-	MENU_ITEM(submenu, _T(MSG_LOAD_FILAMENT), fil_load_menu);
-	MENU_ITEM(submenu, _T(MSG_UNLOAD_FILAMENT), fil_unload_menu);
-	MENU_ITEM(submenu, _i("Change extruder"), change_extr_menu);////MSG_CHANGE_EXTR c=20 r=1
+	MENU_ITEM_SUBMENU_P(_T(MSG_LOAD_FILAMENT), fil_load_menu);
+	MENU_ITEM_SUBMENU_P(_T(MSG_UNLOAD_FILAMENT), fil_unload_menu);
+	MENU_ITEM_SUBMENU_P(_i("Change extruder"), change_extr_menu);////MSG_CHANGE_EXTR c=20 r=1
 	#endif
-	MENU_ITEM(submenu, _T(MSG_SETTINGS), lcd_settings_menu);
-    if(!isPrintPaused) MENU_ITEM(submenu, _T(MSG_MENU_CALIBRATION), lcd_calibration_menu);
+	MENU_ITEM_SUBMENU_P(_T(MSG_SETTINGS), lcd_settings_menu);
+    if(!isPrintPaused) MENU_ITEM_SUBMENU_P(_T(MSG_MENU_CALIBRATION), lcd_calibration_menu);
 
 #ifdef EXPERIMENTAL_FEATURES
-	MENU_ITEM(submenu, PSTR("Experimantal"), lcd_experimantal_menu);
+	MENU_ITEM_SUBMENU_P(PSTR("Experimantal"), lcd_experimantal_menu);
 #endif //EXPERIMENTAL_FEATURES
   }
 
   if (!is_usb_printing && (lcd_commands_type != LCD_COMMAND_V2_CAL))
   {
-	  MENU_ITEM(submenu, _i("Statistics  "), lcd_menu_statistics);////MSG_STATISTICS c=0 r=0
+	  MENU_ITEM_SUBMENU_P(_i("Statistics  "), lcd_menu_statistics);////MSG_STATISTICS c=0 r=0
   }
     
 #if defined(TMC2130) || defined(PAT9125)
-  MENU_ITEM(submenu, PSTR("Fail stats"), lcd_menu_fails_stats);
+  MENU_ITEM_SUBMENU_P(PSTR("Fail stats"), lcd_menu_fails_stats);
 #endif
 
-  MENU_ITEM(submenu, _i("Support"), lcd_support_menu);////MSG_SUPPORT c=0 r=0
-  MENU_ITEM(submenu, _i("W25x20XL init"), lcd_test_menu);////MSG_SUPPORT c=0 r=0
+  MENU_ITEM_SUBMENU_P(_i("Support"), lcd_support_menu);////MSG_SUPPORT c=0 r=0
 
-  END_MENU();
+  MENU_ITEM_SUBMENU_P(_i("W25x20CL init"), lcd_test_menu);////MSG_SUPPORT c=0 r=0
+
+  MENU_END();
 
 }
 
@@ -5642,7 +5892,7 @@ static void lcd_silent_mode_set_tune() {
   }
   eeprom_update_byte((unsigned char *)EEPROM_SILENT, SilentModeMenu);
   st_current_init();
-  menu_action_back();
+  menu_back();
 }
 
 static void lcd_colorprint_change() {
@@ -5672,8 +5922,8 @@ static void lcd_tune_menu()
 
 
 
-	START_MENU();
-	MENU_ITEM(back, _T(MSG_MAIN), 0); //1
+	MENU_BEGIN();
+	MENU_ITEM_BACK_P(_T(MSG_MAIN)); //1
 	MENU_ITEM_EDIT(int3, _i("Speed"), &feedmultiply, 10, 999);//2////MSG_SPEED c=0 r=0
 
 	MENU_ITEM_EDIT(int3, _T(MSG_NOZZLE), &target_temperature[0], 0, HEATER_0_MAXTEMP - 10);//3
@@ -5682,16 +5932,16 @@ static void lcd_tune_menu()
 	MENU_ITEM_EDIT(int3, _T(MSG_FAN_SPEED), &fanSpeed, 0, 255);//5
 	MENU_ITEM_EDIT(int3, _i("Flow"), &extrudemultiply, 10, 999);//6////MSG_FLOW c=0 r=0
 #ifdef FILAMENTCHANGEENABLE
-	MENU_ITEM(function, _T(MSG_FILAMENTCHANGE), lcd_colorprint_change);//7
+	MENU_ITEM_FUNCTION_P(_T(MSG_FILAMENTCHANGE), lcd_colorprint_change);//7
 #endif
 
 #ifndef DEBUG_DISABLE_FSENSORCHECK
 #ifdef PAT9125
 	if (FSensorStateMenu == 0) {
-		MENU_ITEM(function, _T(MSG_FSENSOR_OFF), lcd_fsensor_state_set);
+		MENU_ITEM_FUNCTION_P(_T(MSG_FSENSOR_OFF), lcd_fsensor_state_set);
 	}
 	else {
-		MENU_ITEM(function, _T(MSG_FSENSOR_ON), lcd_fsensor_state_set);
+		MENU_ITEM_FUNCTION_P(_T(MSG_FSENSOR_ON), lcd_fsensor_state_set);
 	}
 #endif //PAT9125
 #endif //DEBUG_DISABLE_FSENSORCHECK
@@ -5699,27 +5949,27 @@ static void lcd_tune_menu()
 #ifdef TMC2130
      if(!farm_mode)
      {
-          if (SilentModeMenu == SILENT_MODE_NORMAL) MENU_ITEM(function, _T(MSG_STEALTH_MODE_OFF), lcd_silent_mode_set);
-          else MENU_ITEM(function, _T(MSG_STEALTH_MODE_ON), lcd_silent_mode_set);
+          if (SilentModeMenu == SILENT_MODE_NORMAL) MENU_ITEM_FUNCTION_P(_T(MSG_STEALTH_MODE_OFF), lcd_silent_mode_set);
+          else MENU_ITEM_FUNCTION_P(_T(MSG_STEALTH_MODE_ON), lcd_silent_mode_set);
 
           if (SilentModeMenu == SILENT_MODE_NORMAL)
           {
-               if (CrashDetectMenu == 0) MENU_ITEM(function, _T(MSG_CRASHDETECT_OFF), lcd_crash_mode_set);
-               else MENU_ITEM(function, _T(MSG_CRASHDETECT_ON), lcd_crash_mode_set);
+               if (CrashDetectMenu == 0) MENU_ITEM_FUNCTION_P(_T(MSG_CRASHDETECT_OFF), lcd_crash_mode_set);
+               else MENU_ITEM_FUNCTION_P(_T(MSG_CRASHDETECT_ON), lcd_crash_mode_set);
           }
-          else MENU_ITEM(submenu, _T(MSG_CRASHDETECT_NA), lcd_crash_mode_info);
+          else MENU_ITEM_SUBMENU_P(_T(MSG_CRASHDETECT_NA), lcd_crash_mode_info);
      }
 #else //TMC2130
 	if (!farm_mode) { //dont show in menu if we are in farm mode
 		switch (SilentModeMenu) {
-		case SILENT_MODE_POWER: MENU_ITEM(function, _T(MSG_SILENT_MODE_OFF), lcd_silent_mode_set); break;
-		case SILENT_MODE_SILENT: MENU_ITEM(function, _T(MSG_SILENT_MODE_ON), lcd_silent_mode_set); break;
-		case SILENT_MODE_AUTO: MENU_ITEM(function, _T(MSG_AUTO_MODE_ON), lcd_silent_mode_set); break;
-		default: MENU_ITEM(function, _T(MSG_SILENT_MODE_OFF), lcd_silent_mode_set); break; // (probably) not needed
+		case SILENT_MODE_POWER: MENU_ITEM_FUNCTION_P(_T(MSG_SILENT_MODE_OFF), lcd_silent_mode_set); break;
+		case SILENT_MODE_SILENT: MENU_ITEM_FUNCTION_P(_T(MSG_SILENT_MODE_ON), lcd_silent_mode_set); break;
+		case SILENT_MODE_AUTO: MENU_ITEM_FUNCTION_P(_T(MSG_AUTO_MODE_ON), lcd_silent_mode_set); break;
+		default: MENU_ITEM_FUNCTION_P(_T(MSG_SILENT_MODE_OFF), lcd_silent_mode_set); break; // (probably) not needed
 		}
 	}
 #endif //TMC2130
-	END_MENU();
+	MENU_END();
 }
 
 static void lcd_move_menu_01mm()
@@ -5736,8 +5986,8 @@ static void lcd_control_temperature_menu()
 //  raw_Kd = unscalePID_d(Kd);
 #endif
 
-  START_MENU();
-  MENU_ITEM(back, _T(MSG_SETTINGS), 0);
+  MENU_BEGIN();
+  MENU_ITEM_BACK_P(_T(MSG_SETTINGS));
 #if TEMP_SENSOR_0 != 0
   MENU_ITEM_EDIT(int3, _T(MSG_NOZZLE), &target_temperature[0], 0, HEATER_0_MAXTEMP - 10);
 #endif
@@ -5758,7 +6008,7 @@ static void lcd_control_temperature_menu()
   MENU_ITEM_EDIT(float32, _i(" \002 Fact"), &autotemp_factor, 0.0, 1.0);////MSG_FACTOR c=0 r=0
 #endif
 
-  END_MENU();
+  MENU_END();
 }
 
 
@@ -5874,6 +6124,7 @@ void getFileDescription(char *name, char *description) {
 
 void lcd_sdcard_menu()
 {
+  printf_P(_N("menu sd\n"));
   uint8_t sdSort = eeprom_read_byte((uint8_t*)EEPROM_SD_SORT);
   int tempScrool = 0;
   if (presort_flag == true) {
@@ -5885,16 +6136,17 @@ void lcd_sdcard_menu()
     return; // nothing to do (so don't thrash the SD card)
   uint16_t fileCnt = card.getnrfilenames();
 
-  START_MENU();
-  MENU_ITEM(back, _T(MSG_MAIN), 0);
+
+  MENU_BEGIN();
+  MENU_ITEM_BACK_P(_T(MSG_MAIN));
   card.getWorkDirName();
   if (card.filename[0] == '/')
   {
 #if SDCARDDETECT == -1
-    MENU_ITEM(function, _T(MSG_REFRESH), lcd_sd_refresh);
+    MENU_ITEM_FUNCTION_P(_T(MSG_REFRESH), lcd_sd_refresh);
 #endif
   } else {
-    MENU_ITEM(function, PSTR(LCD_STR_FOLDER ".."), lcd_sd_updir);
+    MENU_ITEM_FUNCTION_P(PSTR(LCD_STR_FOLDER ".."), lcd_sd_updir);
   }
 
   for (uint16_t i = 0; i < fileCnt; i++)
@@ -5916,14 +6168,14 @@ void lcd_sdcard_menu()
 		#endif
 			
 		if (card.filenameIsDir)
-			MENU_ITEM(sddirectory, _T(MSG_CARD_MENU), card.filename, card.longFilename);
+			MENU_ITEM_SDDIR(_T(MSG_CARD_MENU), card.filename, card.longFilename);
 		else
-			MENU_ITEM(sdfile, _T(MSG_CARD_MENU), card.filename, card.longFilename);
+			MENU_ITEM_SDFILE(_T(MSG_CARD_MENU), card.filename, card.longFilename);
     } else {
       MENU_ITEM_DUMMY();
     }
   }
-  END_MENU();
+  MENU_END();
 }
 
 //char description [10] [31];
@@ -5952,17 +6204,17 @@ void lcd_sdcard_menu()
 			return; // nothing to do (so don't thrash the SD card)
 		uint16_t fileCnt = card.getnrfilenames();
 
-		START_MENU();
-		MENU_ITEM(back, _T(MSG_MAIN), 0);
+		MENU_BEGIN();
+		MENU_ITEM_BACK_P(_T(MSG_MAIN));
 		card.getWorkDirName();
 		if (card.filename[0] == '/')
 		{
 #if SDCARDDETECT == -1
-			MENU_ITEM(function, _T(MSG_REFRESH), lcd_sd_refresh);
+			MENU_ITEM_FUNCTION_P(_T(MSG_REFRESH), lcd_sd_refresh);
 #endif
 		}
 		else {
-			MENU_ITEM(function, PSTR(LCD_STR_FOLDER ".."), lcd_sd_updir);
+			MENU_ITEM_FUNCTION_P(PSTR(LCD_STR_FOLDER ".."), lcd_sd_updir);
 		}
 
 
@@ -5978,18 +6230,18 @@ void lcd_sdcard_menu()
 #endif
 				if (card.filenameIsDir)
 				{
-					MENU_ITEM(sddirectory, _T(MSG_CARD_MENU), card.filename, card.longFilename);
+					MENU_ITEM_SDDIR(_T(MSG_CARD_MENU), card.filename, card.longFilename);
 				}
 				else {
 					
-					MENU_ITEM(sdfile, _T(MSG_CARD_MENU), card.filename, description[i]);
+					MENU_ITEM_SDFILE(_T(MSG_CARD_MENU), card.filename, description[i]);
 				}
 			}
 			else {
 				MENU_ITEM_DUMMY();
 			}
 		}
-		END_MENU();
+		MENU_END();
 
 }*/
 
@@ -7063,47 +7315,6 @@ static void lcd_quick_feedback()
 
 /** Menu action functions **/
 
-/**
- * @brief Go up in menu structure
- * @param data one time action to be done before leaving menu e.g. saving data or 0
- */
-static void menu_action_back(menuFunc_t data)
-{
-    if (data) data();
-    MenuStack::Record record = menuStack.pop();
-    lcd_goto_menu(record.menu);
-    encoderPosition = record.position;
-}
-/**
- * @brief Go deeper into menu structure
- * @param data nested menu
- */
-static void menu_action_submenu(menuFunc_t data) {
-  menuStack.push(currentMenu, encoderPosition);
-  lcd_goto_menu(data);
-}
-static void menu_action_gcode(const char* pgcode) {
-  enquecommand_P(pgcode);
-}
-
-static void menu_action_setlang(unsigned char lang)
-{
-	if (!lang_select(lang))
-	{
-		if (lcd_show_fullscreen_message_yes_no_and_wait_P(_i("Copy selected language from XFLASH?"), false, true))
-			lang_boot_update_start(lang);
-		lcd_update_enable(true);
-		lcd_implementation_clear();
-		lcd_goto_menu(lcd_language_menu);
-		lcd_timeoutToStatus.stop(); //infinite timeout
-		lcdDrawUpdate = 2;
-	}
-}
-
-static void menu_action_function(menuFunc_t data) {
-  (*data)();
-}
-
 static bool check_file(const char* filename) {
 	if (farm_mode) return true;
 	bool result = false;
@@ -7434,7 +7645,9 @@ static void lcd_send_status() {
 		//send important status messages periodicaly
 		prusa_statistics(important_status, saved_filament_type);
 		NcTime = millis();
+#ifdef FARM_CONNECT_MESSAGE
 		lcd_connect_printer();
+#endif //FARM_CONNECT_MESSAGE
 	}
 }
 
@@ -7576,7 +7789,7 @@ void lcd_buttons_update()
 				  if (longPressTimer.expired(LONG_PRESS_TIME)) {
 					  long_press_active = true;
 					  move_menu_scale = 1.0;
-					  menu_action_submenu(lcd_move_z);
+					  menu_submenu(lcd_move_z);
 				  }
 			  }
 		  }

+ 11 - 16
Firmware/ultralcd_implementation_hitachi_HD44780.h

@@ -699,7 +699,7 @@ static inline void lcd_print_percent_done() {
 	{
 		lcd_printPGM(PSTR("---"));
 	}
-	lcd.print('%');
+	lcd_printPGM(PSTR("% "));
 }
 
 static inline void lcd_print_time() {
@@ -718,8 +718,14 @@ static inline void lcd_print_time() {
 		lcd.print(itostr2(print_t/60));
         lcd.print(':');
         lcd.print(itostr2(print_t%60));	
-		(print_time_remaining_normal != PRINT_TIME_REMAINING_INIT) ? lcd.print('R') : lcd.print(' ');
-		(feedmultiply == 100) ? lcd.print(' ') : lcd.print('?');
+		if (print_time_remaining_normal != PRINT_TIME_REMAINING_INIT)
+		{
+			lcd.print('R');
+			(feedmultiply == 100) ? lcd.print(' ') : lcd.print('?');
+		}
+		else {
+			lcd_printPGM(PSTR("  "));
+		}
     }else{
         lcd_printPGM(PSTR("--:--  "));
     }
@@ -828,7 +834,7 @@ if (print_sd_status)
 	// Farm number display
 	if (farm_mode)
 	{
-		lcd.setCursor(0, 6);
+		lcd.setCursor(6, 2);
 		lcd_printPGM(PSTR(" F"));
 		lcd.print(farm_no);
 		lcd_printPGM(PSTR("  "));
@@ -1352,18 +1358,7 @@ static void lcd_implementation_drawmenu_sddirectory(uint8_t row, const char* pst
     while(n--)
         lcd.print(' ');
 }
-#define lcd_implementation_drawmenu_back_selected(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, LCD_STR_UPLEVEL[0], LCD_STR_UPLEVEL[0])
-#define lcd_implementation_drawmenu_back(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, ' ', LCD_STR_UPLEVEL[0])
-#define lcd_implementation_drawmenu_back_RAM_selected(row, str, data) lcd_implementation_drawmenu_generic_RAM(row, str, LCD_STR_UPLEVEL[0], LCD_STR_UPLEVEL[0])
-#define lcd_implementation_drawmenu_back_RAM(row, str, data) lcd_implementation_drawmenu_generic_RAM(row, str, ' ', LCD_STR_UPLEVEL[0])
-#define lcd_implementation_drawmenu_submenu_selected(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, '>', LCD_STR_ARROW_RIGHT[0])
-#define lcd_implementation_drawmenu_submenu(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, ' ', LCD_STR_ARROW_RIGHT[0])
-#define lcd_implementation_drawmenu_gcode_selected(row, pstr, gcode) lcd_implementation_drawmenu_generic(row, pstr, '>', ' ')
-#define lcd_implementation_drawmenu_gcode(row, pstr, gcode) lcd_implementation_drawmenu_generic(row, pstr, ' ', ' ')
-#define lcd_implementation_drawmenu_function_selected(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, '>', ' ')
-#define lcd_implementation_drawmenu_function(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, ' ', ' ')
-#define lcd_implementation_drawmenu_setlang_selected(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, '>', ' ')
-#define lcd_implementation_drawmenu_setlang(row, pstr, data) lcd_implementation_drawmenu_generic(row, pstr, ' ', ' ')
+
 
 static void lcd_implementation_quick_feedback()
 {

+ 3 - 1
Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h

@@ -467,6 +467,8 @@
 // FIND YOUR OWN: "M303 E-1 C8 S90" to run autotune on the bed at 90 degreesC for 8 cycles.
 #endif // PIDTEMPBED
 
+//connect message when communication with monitoring broken
+//#define FARM_CONNECT_MESSAGE
 
 /*-----------------------------------
  PREHEAT SETTINGS
@@ -598,7 +600,7 @@
 
 #define MIN_PRINT_FAN_SPEED 75
 
-#ifdef SNMM
+#if defined (SNMM) || defined (SNMM_V2)
 #define DEFAULT_RETRACTION 4 //used for PINDA temp calibration and pause print
 #else
 #define DEFAULT_RETRACTION 1 //used for PINDA temp calibration and pause print

+ 627 - 0
Firmware/variants/1_75mm_MK3-MMU-EINSy10a-E3Dv6full.h

@@ -0,0 +1,627 @@
+#ifndef CONFIGURATION_PRUSA_H
+#define CONFIGURATION_PRUSA_H
+
+/*------------------------------------
+ GENERAL SETTINGS
+ *------------------------------------*/
+
+// Printer revision
+#define PRINTER_TYPE PRINTER_MK3
+#define FILAMENT_SIZE "1_75mm_MK3"
+#define NOZZLE_TYPE "E3Dv6full"
+
+// Developer flag
+#define DEVELOPER
+
+// Printer name
+#define CUSTOM_MENDEL_NAME "Prusa i3 MK3"
+
+// Electronics
+#define MOTHERBOARD BOARD_EINSY_1_0a
+
+#define STEEL_SHEET
+#define HAS_SECOND_SERIAL_PORT
+#define SNMM_V2
+
+// Uncomment the below for the E3D PT100 temperature sensor (with or without PT100 Amplifier)
+//#define E3D_PT100_EXTRUDER_WITH_AMP
+//#define E3D_PT100_EXTRUDER_NO_AMP
+//#define E3D_PT100_BED_WITH_AMP
+//#define E3D_PT100_BED_NO_AMP
+
+
+/*------------------------------------
+ AXIS SETTINGS
+ *------------------------------------*/
+
+// Steps per unit {X,Y,Z,E}
+//#define DEFAULT_AXIS_STEPS_PER_UNIT   {100,100,3200/8,140}
+#define DEFAULT_AXIS_STEPS_PER_UNIT   {100,100,3200/8,280}
+//#define DEFAULT_AXIS_STEPS_PER_UNIT   {100,100,3200/8,560}
+
+// Endstop inverting
+#define X_MIN_ENDSTOP_INVERTING 0 // set to 1 to invert the logic of the endstop.
+#define Y_MIN_ENDSTOP_INVERTING 0 // set to 1 to invert the logic of the endstop.
+#define Z_MIN_ENDSTOP_INVERTING 0 // set to 1 to invert the logic of the endstop.
+
+// Direction inverting
+#define INVERT_X_DIR 1    // for Mendel set to 0, for Orca set to 1
+#define INVERT_Y_DIR 0    // for Mendel set to 1, for Orca set to 0
+#define INVERT_Z_DIR 1     // for Mendel set to 0, for Orca set to 1
+#define INVERT_E0_DIR 0   // for direct drive extruder v9 set to 1, for geared extruder set to 0
+#define INVERT_E1_DIR 0    // for direct drive extruder v9 set to 1, for geared extruder set to 0
+#define INVERT_E2_DIR 0   // for direct drive extruder v9 set to 1, for geared extruder set to 0
+
+// Home position
+#define MANUAL_X_HOME_POS 0
+#define MANUAL_Y_HOME_POS -2.2
+#define MANUAL_Z_HOME_POS 0.2
+
+// Travel limits after homing
+#define X_MAX_POS 255
+#define X_MIN_POS 0
+#define Y_MAX_POS 212.5
+#define Y_MIN_POS -4 //orig -4
+#define Z_MAX_POS 210
+#define Z_MIN_POS 0.15
+
+// Canceled home position
+#define X_CANCEL_POS 50
+#define Y_CANCEL_POS 190
+
+//Pause print position
+#define X_PAUSE_POS 50
+#define Y_PAUSE_POS 190
+#define Z_PAUSE_LIFT 20
+
+#define NUM_AXIS 4 // The axis order in all axis related arrays is X, Y, Z, E
+#define HOMING_FEEDRATE {3000, 3000, 800, 0}  // set the homing speeds (mm/min) // 3000 is also valid for stallGuard homing. Valid range: 2200 - 3000
+
+//#define DEFAULT_Y_OFFSET    4.f // Default distance of Y_MIN_POS point from endstop, when the printer is not calibrated.
+/**
+ * [0,0] steel sheet print area point X coordinate in bed print area coordinates
+ */
+#define SHEET_PRINT_ZERO_REF_X 0.f
+/**
+ * [0,0] steel sheet print area point Y coordinate in bed print area coordinates
+ */
+#define SHEET_PRINT_ZERO_REF_Y -2.f
+
+#define DEFAULT_MAX_FEEDRATE          {200, 200, 12, 120}      // (mm/sec)   max feedrate (M203)
+#define DEFAULT_MAX_ACCELERATION      {1000, 1000, 200, 5000}  // (mm/sec^2) max acceleration (M201)
+
+
+#define DEFAULT_ACCELERATION          1250   // X, Y, Z and E max acceleration in mm/s^2 for printing moves (M204S)
+#define DEFAULT_RETRACT_ACCELERATION  1250   // X, Y, Z and E max acceleration in mm/s^2 for retracts (M204T)
+
+#define MANUAL_FEEDRATE {2700, 2700, 1000, 100}   // set the speeds for manual moves (mm/min)
+
+//Silent mode limits
+#define SILENT_MAX_ACCEL  960 // max axxeleration in silent mode in mm/s^2
+#define SILENT_MAX_ACCEL_ST (100*SILENT_MAX_ACCEL) // max accel in steps/s^2
+#define SILENT_MAX_FEEDRATE 172  //max feedrate in mm/s, because mode switched to normal for homming , this value limits also homing, it should be greater (172mm/s=9600mm/min>2700mm/min)
+
+//Normal mode limits
+#define NORMAL_MAX_ACCEL 2500 // Y-axis max axxeleration in normal mode in mm/s^2
+#define NORMAL_MAX_ACCEL_ST (100*NORMAL_MAX_ACCEL) // max accel in steps/s^2
+#define NORMAL_MAX_FEEDRATE 200  //max feedrate in mm/s, because mode switched to normal for homming , this value limits also homing, it should be greater (172mm/s=9600mm/min>2700mm/min)
+
+//#define SIMPLE_ACCEL_LIMIT          //new limitation method for normal/silent
+
+//number of bytes from end of the file to start check
+#define END_FILE_SECTION 10000
+
+#define Z_AXIS_ALWAYS_ON 1
+
+//Crash detection
+#define CRASHDET_TIMER 45 //seconds
+#define CRASHDET_COUNTER_MAX 3 
+
+// New XYZ calibration
+#define NEW_XYZCAL
+
+// Watchdog support
+#define WATCHDOG
+
+// Power panic
+#define UVLO_SUPPORT
+
+// Fan check
+#define FANCHECK
+
+// Safety timer
+#define SAFETYTIMER
+#define DEFAULT_SAFETYTIMER_TIME_MINS 30
+
+// Filament sensor
+#define PAT9125
+
+
+// Disable some commands
+#define _DISABLE_M42_M226
+
+// Minimum ambient temperature limit to start triggering MINTEMP errors [C]
+// this value is litlebit higher that real limit, because ambient termistor is on the board and is temperated from it,
+// temperature inside the case is around 31C for ambient temperature 25C, when the printer is powered on long time and idle
+// the real limit is 15C (same as MINTEMP limit), this is because 15C is end of scale for both used thermistors (bed, heater)
+#define MINTEMP_MINAMBIENT      25
+#define MINTEMP_MINAMBIENT_RAW  978
+
+//#define DEBUG_BUILD
+//#define DEBUG_SEC_LANG   //secondary language debug output at startup
+//#define DEBUG_W25X20CL   //debug external spi flash
+#ifdef DEBUG_BUILD
+//#define _NO_ASM
+#define DEBUG_DCODES //D codes
+#define DEBUG_STACK_MONITOR        //Stack monitor in stepper ISR
+//#define DEBUG_FSENSOR_LOG          //Reports fsensor status to serial
+//#define DEBUG_CRASHDET_COUNTERS  //Display crash-detection counters on LCD
+//#define DEBUG_RESUME_PRINT       //Resume/save print debug enable 
+//#define DEBUG_UVLO_AUTOMATIC_RECOVER // Power panic automatic recovery debug output 
+//#define DEBUG_DISABLE_XMINLIMIT  //x min limit ignored
+//#define DEBUG_DISABLE_XMAXLIMIT  //x max limit ignored
+//#define DEBUG_DISABLE_YMINLIMIT  //y min limit ignored
+//#define DEBUG_DISABLE_YMAXLIMIT  //y max limit ignored
+//#define DEBUG_DISABLE_ZMINLIMIT  //z min limit ignored
+//#define DEBUG_DISABLE_ZMAXLIMIT  //z max limit ignored
+#define DEBUG_DISABLE_STARTMSGS //no startup messages 
+//#define DEBUG_DISABLE_MINTEMP   //mintemp error ignored
+//#define DEBUG_DISABLE_SWLIMITS  //sw limits ignored
+//#define DEBUG_DISABLE_LCD_STATUS_LINE  //empty four lcd line
+//#define DEBUG_DISABLE_PREVENT_EXTRUDER //cold extrusion and long extrusion allowed
+//#define DEBUG_DISABLE_PRUSA_STATISTICS //disable prusa_statistics() mesages
+//#define DEBUG_DISABLE_FORCE_SELFTEST //disable force selftest
+//#define DEBUG_XSTEP_DUP_PIN 21   //duplicate x-step output to pin 21 (SCL on P3)
+//#define DEBUG_YSTEP_DUP_PIN 21   //duplicate y-step output to pin 21 (SCL on P3)
+//#define DEBUG_BLINK_ACTIVE
+//#define DEBUG_DISABLE_FANCHECK     //disable fan check (no ISR INT7, check disabled)
+//#define DEBUG_DISABLE_FSENSORCHECK //disable fsensor check (no ISR INT7, check disabled)
+#define DEBUG_DUMP_TO_2ND_SERIAL   //dump received characters to 2nd serial line
+#define DEBUG_STEPPER_TIMER_MISSED // Stop on stepper timer overflow, beep and display a message.
+#define PLANNER_DIAGNOSTICS // Show the planner queue status on printer display.
+#define CMD_DIAGNOSTICS //Show cmd queue length on printer display
+#endif /* DEBUG_BUILD */
+
+//#define EXPERIMENTAL_FEATURES
+#define TMC2130_LINEARITY_CORRECTION
+#define TMC2130_LINEARITY_CORRECTION_XYZ
+//#define TMC2130_VARIABLE_RESOLUTION
+
+
+
+/*------------------------------------
+ TMC2130 default settings
+ *------------------------------------*/
+
+#define TMC2130_FCLK 12000000       // fclk = 12MHz
+
+#define TMC2130_USTEPS_XY   16        // microstep resolution for XY axes
+#define TMC2130_USTEPS_Z    16        // microstep resolution for Z axis
+#define TMC2130_USTEPS_E    32        // microstep resolution for E axis
+#define TMC2130_INTPOL_XY   1         // extrapolate 256 for XY axes
+#define TMC2130_INTPOL_Z    1         // extrapolate 256 for Z axis
+#define TMC2130_INTPOL_E    1         // extrapolate 256 for E axis
+
+#define TMC2130_PWM_GRAD_X  2         // PWMCONF
+#define TMC2130_PWM_AMPL_X  230       // PWMCONF
+#define TMC2130_PWM_AUTO_X  1         // PWMCONF
+#define TMC2130_PWM_FREQ_X  2         // PWMCONF
+
+#define TMC2130_PWM_GRAD_Y  2         // PWMCONF
+#define TMC2130_PWM_AMPL_Y  235       // PWMCONF
+#define TMC2130_PWM_AUTO_Y  1         // PWMCONF
+#define TMC2130_PWM_FREQ_Y  2         // PWMCONF
+
+#define TMC2130_PWM_GRAD_Z  4         // PWMCONF
+#define TMC2130_PWM_AMPL_Z  200       // PWMCONF
+#define TMC2130_PWM_AUTO_Z  1         // PWMCONF
+#define TMC2130_PWM_FREQ_Z  2         // PWMCONF
+
+#define TMC2130_PWM_GRAD_E  4         // PWMCONF
+#define TMC2130_PWM_AMPL_E  240       // PWMCONF
+#define TMC2130_PWM_AUTO_E  1         // PWMCONF
+#define TMC2130_PWM_FREQ_E  2         // PWMCONF
+
+#define TMC2130_TOFF_XYZ    3         // CHOPCONF // fchop = 27.778kHz
+#define TMC2130_TOFF_E      3         // CHOPCONF // fchop = 27.778kHz
+//#define TMC2130_TOFF_E      4         // CHOPCONF // fchop = 21.429kHz
+//#define TMC2130_TOFF_E      5         // CHOPCONF // fchop = 17.442kHz
+
+//#define TMC2130_STEALTH_E // Extruder stealthChop mode
+//#define TMC2130_CNSTOFF_E // Extruder constant-off-time mode (similar to MK2)
+
+//#define TMC2130_PWM_DIV   683         // PWM frequency divider (1024, 683, 512, 410)
+#define TMC2130_PWM_DIV   512         // PWM frequency divider (1024, 683, 512, 410)
+#define TMC2130_PWM_CLK   (2 * TMC2130_FCLK / TMC2130_PWM_DIV) // PWM frequency (23.4kHz, 35.1kHz, 46.9kHz, 58.5kHz for 12MHz fclk)
+
+#define TMC2130_TPWMTHRS  0         // TPWMTHRS - Sets the switching speed threshold based on TSTEP from stealthChop to spreadCycle mode
+#define TMC2130_THIGH     0         // THIGH - unused
+
+//#define TMC2130_TCOOLTHRS_X 450       // TCOOLTHRS - coolstep treshold
+//#define TMC2130_TCOOLTHRS_Y 450       // TCOOLTHRS - coolstep treshold
+#define TMC2130_TCOOLTHRS_X 430       // TCOOLTHRS - coolstep treshold
+#define TMC2130_TCOOLTHRS_Y 430       // TCOOLTHRS - coolstep treshold
+#define TMC2130_TCOOLTHRS_Z 500       // TCOOLTHRS - coolstep treshold
+#define TMC2130_TCOOLTHRS_E 500       // TCOOLTHRS - coolstep treshold
+
+#define TMC2130_SG_HOMING       1     // stallguard homing
+#define TMC2130_SG_THRS_X       3     // stallguard sensitivity for X axis
+#define TMC2130_SG_THRS_Y       3     // stallguard sensitivity for Y axis
+#define TMC2130_SG_THRS_Z       4     // stallguard sensitivity for Z axis
+#define TMC2130_SG_THRS_E       3     // stallguard sensitivity for E axis
+
+//new settings is possible for vsense = 1, running current value > 31 set vsense to zero and shift both currents by 1 bit right (Z axis only)
+#define TMC2130_CURRENTS_H {16, 20, 35, 30}  // default holding currents for all axes
+#define TMC2130_CURRENTS_R {16, 20, 35, 30}  // default running currents for all axes
+#define TMC2130_UNLOAD_CURRENT_R 12			 // lowe current for M600 to protect filament sensor 
+
+#define TMC2130_STEALTH_Z
+
+//#define TMC2130_DEBUG
+//#define TMC2130_DEBUG_WR
+//#define TMC2130_DEBUG_RD
+
+
+/*------------------------------------
+ EXTRUDER SETTINGS
+ *------------------------------------*/
+
+// Mintemps
+#define HEATER_0_MINTEMP 15
+#define HEATER_1_MINTEMP 5
+#define HEATER_2_MINTEMP 5
+#define BED_MINTEMP 15
+
+// Maxtemps
+#if defined(E3D_PT100_EXTRUDER_WITH_AMP) || defined(E3D_PT100_EXTRUDER_NO_AMP)
+#define HEATER_0_MAXTEMP 410
+#else
+#define HEATER_0_MAXTEMP 305
+#endif
+#define HEATER_1_MAXTEMP 305
+#define HEATER_2_MAXTEMP 305
+#define BED_MAXTEMP 125
+
+#if defined(E3D_PT100_EXTRUDER_WITH_AMP) || defined(E3D_PT100_EXTRUDER_NO_AMP)
+// Define PID constants for extruder with PT100
+#define  DEFAULT_Kp 21.70
+#define  DEFAULT_Ki 1.60
+#define  DEFAULT_Kd 73.76
+#else
+// Define PID constants for extruder
+//#define  DEFAULT_Kp 40.925
+//#define  DEFAULT_Ki 4.875
+//#define  DEFAULT_Kd 86.085
+#define  DEFAULT_Kp 16.13
+#define  DEFAULT_Ki 1.1625
+#define  DEFAULT_Kd 56.23
+#endif
+
+// Extrude mintemp
+#define EXTRUDE_MINTEMP 190
+
+// Extruder cooling fans
+#define EXTRUDER_0_AUTO_FAN_PIN   8
+#define EXTRUDER_1_AUTO_FAN_PIN   -1
+#define EXTRUDER_2_AUTO_FAN_PIN   -1
+#define EXTRUDER_AUTO_FAN_TEMPERATURE 50
+#define EXTRUDER_AUTO_FAN_SPEED   255  // == full speed
+
+
+
+/*------------------------------------
+ LOAD/UNLOAD FILAMENT SETTINGS
+ *------------------------------------*/
+
+// Load filament commands
+#define LOAD_FILAMENT_0 "M83"
+#define LOAD_FILAMENT_1 "G1 E70 F400"
+#define LOAD_FILAMENT_2 "G1 E40 F100"
+
+// Unload filament commands
+#define UNLOAD_FILAMENT_0 "M83"
+#define UNLOAD_FILAMENT_1 "G1 E-80 F7000"
+
+/*------------------------------------
+ CHANGE FILAMENT SETTINGS
+ *------------------------------------*/
+
+// Filament change configuration
+#define FILAMENTCHANGEENABLE
+#ifdef FILAMENTCHANGEENABLE
+#define FILAMENTCHANGE_XPOS 211
+#define FILAMENTCHANGE_YPOS 0
+#define FILAMENTCHANGE_ZADD 2
+#define FILAMENTCHANGE_FIRSTRETRACT -2
+#define FILAMENTCHANGE_FINALRETRACT -80
+
+#define FILAMENTCHANGE_FIRSTFEED 70
+#define FILAMENTCHANGE_FINALFEED 50
+#define FILAMENTCHANGE_RECFEED 5
+
+#define FILAMENTCHANGE_XYFEED 50
+#define FILAMENTCHANGE_EFEED 20
+//#define FILAMENTCHANGE_RFEED 400
+#define FILAMENTCHANGE_RFEED 7000 / 60
+#define FILAMENTCHANGE_EXFEED 2
+#define FILAMENTCHANGE_ZFEED 15
+
+#endif
+
+/*------------------------------------
+ ADDITIONAL FEATURES SETTINGS
+ *------------------------------------*/
+
+// Define Prusa filament runout sensor
+//#define FILAMENT_RUNOUT_SUPPORT
+
+#ifdef FILAMENT_RUNOUT_SUPPORT
+#define FILAMENT_RUNOUT_SENSOR 1
+#endif
+
+// temperature runaway
+#define TEMP_RUNAWAY_BED_HYSTERESIS 5
+#define TEMP_RUNAWAY_BED_TIMEOUT 360
+
+#define TEMP_RUNAWAY_EXTRUDER_HYSTERESIS 15
+#define TEMP_RUNAWAY_EXTRUDER_TIMEOUT 45
+
+/*------------------------------------
+ MOTOR CURRENT SETTINGS
+ *------------------------------------*/
+
+// Motor Current setting for BIG RAMBo
+#define DIGIPOT_MOTOR_CURRENT {135,135,135,135,135} // Values 0-255 (RAMBO 135 = ~0.75A, 185 = ~1A)
+#define DIGIPOT_MOTOR_CURRENT_LOUD {135,135,135,135,135}
+
+// Motor Current settings for RAMBo mini PWM value = MotorCurrentSetting * 255 / range
+#if MOTHERBOARD == BOARD_RAMBO_MINI_1_0 || MOTHERBOARD == BOARD_RAMBO_MINI_1_3
+#define MOTOR_CURRENT_PWM_RANGE 2000
+#define DEFAULT_PWM_MOTOR_CURRENT  {400, 750, 750} // {XY,Z,E}
+#define DEFAULT_PWM_MOTOR_CURRENT_LOUD  {400, 750, 750} // {XY,Z,E}
+#endif
+
+/*------------------------------------
+ PAT9125 SETTINGS
+ *------------------------------------*/
+
+#define PAT9125_XRES			0
+#define PAT9125_YRES			255
+
+/*------------------------------------
+ BED SETTINGS
+ *------------------------------------*/
+
+// Define Mesh Bed Leveling system to enable it
+#define MESH_BED_LEVELING
+#ifdef MESH_BED_LEVELING
+
+#define MBL_Z_STEP 0.01
+
+// Mesh definitions
+#define MESH_MIN_X 35
+#define MESH_MAX_X 238
+#define MESH_MIN_Y 6
+#define MESH_MAX_Y 202
+
+// Mesh upsample definition
+#define MESH_NUM_X_POINTS 7
+#define MESH_NUM_Y_POINTS 7
+// Mesh measure definition
+#define MESH_MEAS_NUM_X_POINTS 3
+#define MESH_MEAS_NUM_Y_POINTS 3
+
+#define MESH_HOME_Z_CALIB 0.2
+#define MESH_HOME_Z_SEARCH 5 //Z lift for homing, mesh bed leveling etc.
+
+#define X_PROBE_OFFSET_FROM_EXTRUDER 23     // Z probe to nozzle X offset: -left  +right
+#define Y_PROBE_OFFSET_FROM_EXTRUDER 5     // Z probe to nozzle Y offset: -front +behind
+#define Z_PROBE_OFFSET_FROM_EXTRUDER -0.4  // Z probe to nozzle Z offset: -below (always!)
+#endif
+
+// Bed Temperature Control
+// Select PID or bang-bang with PIDTEMPBED. If bang-bang, BED_LIMIT_SWITCHING will enable hysteresis
+//
+// Uncomment this to enable PID on the bed. It uses the same frequency PWM as the extruder.
+// If your PID_dT above is the default, and correct for your hardware/configuration, that means 7.689Hz,
+// which is fine for driving a square wave into a resistive load and does not significantly impact you FET heating.
+// This also works fine on a Fotek SSR-10DA Solid State Relay into a 250W heater.
+// If your configuration is significantly different than this and you don't understand the issues involved, you probably
+// shouldn't use bed PID until someone else verifies your hardware works.
+// If this is enabled, find your own PID constants below.
+#define PIDTEMPBED
+//
+//#define BED_LIMIT_SWITCHING
+
+// This sets the max power delivered to the bed, and replaces the HEATER_BED_DUTY_CYCLE_DIVIDER option.
+// all forms of bed control obey this (PID, bang-bang, bang-bang with hysteresis)
+// setting this to anything other than 255 enables a form of PWM to the bed just like HEATER_BED_DUTY_CYCLE_DIVIDER did,
+// so you shouldn't use it unless you are OK with PWM on your bed.  (see the comment on enabling PIDTEMPBED)
+#define MAX_BED_POWER 255 // limits duty cycle to bed; 255=full current
+
+// Bed temperature compensation settings
+#define BED_OFFSET 10
+#define BED_OFFSET_START 40
+#define BED_OFFSET_CENTER 50
+
+
+#ifdef PIDTEMPBED
+//120v 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)
+//from FOPDT model - kp=.39 Tp=405 Tdead=66, Tc set to 79.2, aggressive factor of .15 (vs .1, 1, 10)
+#if defined(E3D_PT100_BED_WITH_AMP) || defined(E3D_PT100_BED_NO_AMP)
+// Define PID constants for extruder with PT100
+#define  DEFAULT_bedKp 21.70
+#define  DEFAULT_bedKi 1.60
+#define  DEFAULT_bedKd 73.76
+#else
+#define  DEFAULT_bedKp 126.13
+#define  DEFAULT_bedKi 4.30
+#define  DEFAULT_bedKd 924.76
+#endif
+
+//120v 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)
+//from pidautotune
+//    #define  DEFAULT_bedKp 97.1
+//    #define  DEFAULT_bedKi 1.41
+//    #define  DEFAULT_bedKd 1675.16
+
+// FIND YOUR OWN: "M303 E-1 C8 S90" to run autotune on the bed at 90 degreesC for 8 cycles.
+#endif // PIDTEMPBED
+
+//connect message when communication with monitoring broken
+//#define FARM_CONNECT_MESSAGE
+
+/*-----------------------------------
+ PREHEAT SETTINGS
+ *------------------------------------*/
+
+#define FARM_PREHEAT_HOTEND_TEMP 250
+#define FARM_PREHEAT_HPB_TEMP 60
+#define FARM_PREHEAT_FAN_SPEED 0
+
+#define PLA_PREHEAT_HOTEND_TEMP 215
+#define PLA_PREHEAT_HPB_TEMP 60
+#define PLA_PREHEAT_FAN_SPEED 0
+
+#define ABS_PREHEAT_HOTEND_TEMP 255
+#define ABS_PREHEAT_HPB_TEMP 100
+#define ABS_PREHEAT_FAN_SPEED 0
+
+#define HIPS_PREHEAT_HOTEND_TEMP 220
+#define HIPS_PREHEAT_HPB_TEMP 100
+#define HIPS_PREHEAT_FAN_SPEED 0
+
+#define PP_PREHEAT_HOTEND_TEMP 254
+#define PP_PREHEAT_HPB_TEMP 100
+#define PP_PREHEAT_FAN_SPEED 0
+
+#define PET_PREHEAT_HOTEND_TEMP 230
+#define PET_PREHEAT_HPB_TEMP 85
+#define PET_PREHEAT_FAN_SPEED 0
+
+#define FLEX_PREHEAT_HOTEND_TEMP 240
+#define FLEX_PREHEAT_HPB_TEMP 50
+#define FLEX_PREHEAT_FAN_SPEED 0
+
+/*------------------------------------
+ THERMISTORS SETTINGS
+ *------------------------------------*/
+
+//
+//--NORMAL IS 4.7kohm PULLUP!-- 1kohm pullup can be used on hotend sensor, using correct resistor and table
+//
+//// Temperature sensor settings:
+// -2 is thermocouple with MAX6675 (only for sensor 0)
+// -1 is thermocouple with AD595
+// 0 is not used
+// 1 is 100k thermistor - best choice for EPCOS 100k (4.7k pullup)
+// 2 is 200k thermistor - ATC Semitec 204GT-2 (4.7k pullup)
+// 3 is Mendel-parts thermistor (4.7k pullup)
+// 4 is 10k thermistor !! do not use it for a hotend. It gives bad resolution at high temp. !!
+// 5 is 100K thermistor - ATC Semitec 104GT-2 (Used in ParCan & J-Head) (4.7k pullup)
+// 6 is 100k EPCOS - Not as accurate as table 1 (created using a fluke thermocouple) (4.7k pullup)
+// 7 is 100k Honeywell thermistor 135-104LAG-J01 (4.7k pullup)
+// 71 is 100k Honeywell thermistor 135-104LAF-J01 (4.7k pullup)
+// 8 is 100k 0603 SMD Vishay NTCS0603E3104FXT (4.7k pullup)
+// 9 is 100k GE Sensing AL03006-58.2K-97-G1 (4.7k pullup)
+// 10 is 100k RS thermistor 198-961 (4.7k pullup)
+// 11 is 100k beta 3950 1% thermistor (4.7k pullup)
+// 12 is 100k 0603 SMD Vishay NTCS0603E3104FXT (4.7k pullup) (calibrated for Makibox hot bed)
+// 13 is 100k Hisens 3950  1% up to 300°C for hotend "Simple ONE " & "Hotend "All In ONE"
+// 20 is the PT100 circuit found in the Ultimainboard V2.x
+// 60 is 100k Maker's Tool Works Kapton Bed Thermistor beta=3950
+//
+//    1k ohm pullup tables - This is not normal, you would have to have changed out your 4.7k for 1k
+//                          (but gives greater accuracy and more stable PID)
+// 51 is 100k thermistor - EPCOS (1k pullup)
+// 52 is 200k thermistor - ATC Semitec 204GT-2 (1k pullup)
+// 55 is 100k thermistor - ATC Semitec 104GT-2 (Used in ParCan & J-Head) (1k pullup)
+//
+// 1047 is Pt1000 with 4k7 pullup
+// 1010 is Pt1000 with 1k pullup (non standard)
+// 147 is Pt100 with 4k7 pullup
+// 148 is E3D Pt100 with 4k7 pullup and no PT100 Amplifier on a MiniRambo 1.3a
+// 247 is Pt100 with 4k7 pullup and PT100 Amplifier
+// 110 is Pt100 with 1k pullup (non standard)
+
+#if defined(E3D_PT100_EXTRUDER_WITH_AMP)
+#define TEMP_SENSOR_0 247
+#elif defined(E3D_PT100_EXTRUDER_NO_AMP)
+#define TEMP_SENSOR_0 148
+#else
+#define TEMP_SENSOR_0 5
+#endif
+#define TEMP_SENSOR_1 0
+#define TEMP_SENSOR_2 0
+#if defined(E3D_PT100_BED_WITH_AMP)
+#define TEMP_SENSOR_BED 247
+#elif defined(E3D_PT100_BED_NO_AMP)
+#define TEMP_SENSOR_BED 148
+#else
+#define TEMP_SENSOR_BED 1
+#endif
+#define TEMP_SENSOR_PINDA 1
+#define TEMP_SENSOR_AMBIENT 2000
+
+#define STACK_GUARD_TEST_VALUE 0xA2A2
+
+#define MAX_BED_TEMP_CALIBRATION 50
+#define MAX_HOTEND_TEMP_CALIBRATION 50
+
+#define MAX_E_STEPS_PER_UNIT 250
+#define MIN_E_STEPS_PER_UNIT 100
+
+#define Z_BABYSTEP_MIN -3999
+#define Z_BABYSTEP_MAX 0
+
+#define PINDA_PREHEAT_X 20
+#define PINDA_PREHEAT_Y 60
+#define PINDA_PREHEAT_Z 0.15
+/*
+#define PINDA_PREHEAT_X 70
+#define PINDA_PREHEAT_Y -3
+#define PINDA_PREHEAT_Z 1*/
+#define PINDA_HEAT_T 120 //time in s
+
+#define PINDA_MIN_T 50
+#define PINDA_STEP_T 10
+#define PINDA_MAX_T 100
+
+#define PING_TIME 60 //time in s
+#define PING_TIME_LONG 600 //10 min; used when length of commands buffer > 0 to avoid 0 triggering when dealing with long gcodes
+#define PING_ALLERT_PERIOD 60 //time in s
+
+#define NC_TIME 10 //time in s for periodic important status messages sending which needs reponse from monitoring
+#define NC_BUTTON_LONG_PRESS 15 //time in s
+
+#define LONG_PRESS_TIME 1000 //time in ms for button long press
+#define BUTTON_BLANKING_TIME 200 //time in ms for blanking after button release
+
+#define DEFAULT_PID_TEMP 210
+
+#define MIN_PRINT_FAN_SPEED 75
+
+#if defined (SNMM) || defined (SNMM_V2)
+#define DEFAULT_RETRACTION 4 //used for PINDA temp calibration and pause print
+#else
+#define DEFAULT_RETRACTION 1 //used for PINDA temp calibration and pause print
+#endif
+
+// How much shall the print head be lifted on power panic?
+// Ideally the Z axis will reach a zero phase of the stepper driver on power outage. To simplify this,
+// UVLO_Z_AXIS_SHIFT shall be an integer multiply of the stepper driver cycle, that is 4x full step.
+// For example, the Prusa i3 MK2 with 16 microsteps per full step has Z stepping of 400 microsteps per mm.
+// At 400 microsteps per mm, a full step lifts the Z axis by 0.04mm, and a stepper driver cycle is 0.16mm.
+// The following example, 12 * (4 * 16 / 400) = 12 * 0.16mm = 1.92mm.
+//#define UVLO_Z_AXIS_SHIFT 1.92
+#define UVLO_Z_AXIS_SHIFT 0.64
+// If power panic occured, and the current temperature is higher then target temperature before interrupt minus this offset, print will be recovered automatically. 
+#define AUTOMATIC_UVLO_BED_TEMP_OFFSET 5 
+
+#define HEATBED_V2
+
+#define M600_TIMEOUT 600  //seconds
+
+//#define SUPPORT_VERBOSITY
+
+#endif //__CONFIGURATION_PRUSA_H

+ 61 - 0
lang/fw-clean.sh

@@ -0,0 +1,61 @@
+#!/bin/sh
+#
+# fw-clean.sh - multi-language support script
+#  Remove all firmware output files from lang folder.
+#
+
+result=0
+
+rm_if_exists()
+{
+ if [ -e $1 ]; then
+  echo -n " removing '$1'..." >&2
+  if rm $1; then
+   echo "OK" >&2
+  else
+   echo "NG!" >&2
+   result=1
+  fi
+ fi
+}
+
+echo "fw-clean.sh started" >&2
+
+rm_if_exists text.sym
+rm_if_exists progmem1.sym
+rm_if_exists progmem1.lss
+rm_if_exists progmem1.hex
+rm_if_exists progmem1.chr
+rm_if_exists progmem1.var
+rm_if_exists progmem1.txt
+rm_if_exists textaddr.txt
+rm_if_exists firmware.bin
+rm_if_exists firmware.hex
+rm_if_exists firmware_cz.hex
+rm_if_exists firmware_de.hex
+rm_if_exists firmware_es.hex
+rm_if_exists firmware_it.hex
+rm_if_exists firmware_pl.hex
+rm_if_exists progmem.out
+rm_if_exists textaddr.out
+rm_if_exists update_lang.out
+rm_if_exists update_lang_cz.out
+rm_if_exists update_lang_de.out
+rm_if_exists update_lang_es.out
+rm_if_exists update_lang_it.out
+rm_if_exists update_lang_pl.out
+rm_if_exists lang.bin
+rm_if_exists lang.hex
+
+echo -n "fw-clean.sh finished" >&2
+if [ $result -eq 0 ]; then
+ echo " with success" >&2
+else
+ echo " with errors!" >&2
+fi
+
+case "$-" in
+ *i*) echo "press enter key"; read ;;
+esac
+
+exit $result

+ 10 - 0
lang/iso639-1.txt

@@ -0,0 +1,10 @@
+#language codes ISO639-1
+# iso english  localized
+#-----------------------
+# en  English  English
+# de  German   Deutsch
+# cs  Czech    Cestina
+# es  Spanish  Espanol
+# fr  
+# it  Italian  Italiano
+# pl  Polish   Polski

+ 139 - 0
lang/lang-build.sh

@@ -0,0 +1,139 @@
+#!/bin/sh
+#
+# lang-build.sh - multi-language support script
+#  generate lang_xx.bin (language binary file)
+#
+# Input files:
+#  lang_en.txt or lang_en_xx.txt
+#  
+# Output files:
+#  lang_xx.bin
+#
+# Temporary files:
+#  lang_xx.tmp
+#  lang_xx.dat
+#
+
+#awk code to format ui16 variables for dd
+awk_ui16='{ h=int($1/256); printf("\\x%02x\\x%02x\n", int($1-256*h), h); }'
+
+#startup message
+echo "lang-build.sh started" >&2
+
+#exiting function
+finish()
+{
+ if [ $1 -eq 0 ]; then
+  echo "lang-build.sh finished with success" >&2
+ else
+  echo "lang-build.sh finished with errors!" >&2
+ fi
+ exit $1
+}
+
+#returns hexadecial data for lang code
+lang_code_hex_data()
+# $1 - language code ('en', 'cz'...)
+{
+ case "$1" in
+  *en*) echo '\x6e\x65' ;;
+  *cz*) echo '\x73\x63' ;;
+  *de*) echo '\x65\x64' ;;
+  *es*) echo '\x73\x65' ;;
+  *fr*) echo '\x72\x66' ;;
+  *it*) echo '\x74\x69' ;;
+  *pl*) echo '\x6c\x70' ;;
+ esac
+ echo '??'
+}
+
+write_header()
+# $1 - lang
+# $2 - size
+# $3 - count
+# $4 - checksum
+# $5 - signature
+{
+ /bin/echo -n -e "\xa5\x5a\xb4\x4b" |\
+  dd of=lang_$1.bin bs=1 count=4 seek=0 conv=notrunc 2>/dev/null
+ /bin/echo -n -e $(echo -n "$(($2))" | awk "$awk_ui16") |\
+  dd of=lang_$1.bin bs=1 count=2 seek=4 conv=notrunc 2>/dev/null
+ /bin/echo -n -e $(echo -n "$(($3))" | awk "$awk_ui16") |\
+  dd of=lang_$1.bin bs=1 count=2 seek=6 conv=notrunc 2>/dev/null
+ /bin/echo -n -e $(echo -n "$(($4))" | awk "$awk_ui16") |\
+  dd of=lang_$1.bin bs=1 count=2 seek=8 conv=notrunc 2>/dev/null
+ /bin/echo -n -e "$(lang_code_hex_data $1)" |\
+  dd of=lang_$1.bin bs=1 count=2 seek=10 conv=notrunc 2>/dev/null
+ sig_h=$(($5 / 65536))
+ /bin/echo -n -e $(echo -n "$sig_h" | awk "$awk_ui16") |\
+  dd of=lang_$1.bin bs=1 count=2 seek=14 conv=notrunc 2>/dev/null
+ sig_l=$(($5 - $sig_h * 65536))
+ /bin/echo -n -e $(echo -n "$sig_l" | awk "$awk_ui16") |\
+  dd of=lang_$1.bin bs=1 count=2 seek=12 conv=notrunc 2>/dev/null
+}
+
+generate_binary()
+# $1 - language code ('en', 'cz'...)
+{
+ echo "lang="$1 >&2
+ #remove output and temporary files
+ rm -f lang_$1.bin
+ rm -f lang_$1.tmp
+ rm -f lang_$1.dat
+ LNG=$1
+ #create lang_xx.tmp - different processing for 'en' language
+ if [ "$1" = "en" ]; then
+  #remove comments and empty lines
+  cat lang_en.txt | sed '/^$/d;/^#/d'
+ else
+  #remove comments and empty lines, print lines with translated text only
+  cat lang_en_$1.txt | sed '/^$/d;/^#/d' | sed -n 'n;p'
+ fi | sed 's/^\"\\x00\"$/\"\"/' > lang_$1.tmp
+ #create lang_xx.dat (binary text data file)
+# cat lang_$1.tmp | sed 's/^\"/\/bin\/echo -e \"/;s/"$/\\x00\"/' > lang_$1.shx
+ cat lang_$1.tmp | sed 's/^\"/\/bin\/echo -e -n \"/;s/"$/\\x00\"/' | sh >lang_$1.dat
+ #calculate number of strings
+ count=$(grep -c '^"' lang_$1.tmp)
+ echo "count="$count >&2
+ #calculate text data offset
+ offs=$((16 + 2 * $count))
+ echo "offs="$offs >&2
+ #calculate text data size
+ size=$(($offs + $(wc -c lang_$1.dat | cut -f1 -d' ')))
+ echo "size="$size >&2
+ #write header with empty signature and checksum
+ write_header $1 $size $count 0x0000 0x00000000
+ #write offset table
+ offs_hex=$(cat lang_$1.tmp | sed 's/^\"//;s/\"$//' |\
+  sed 's/\\x[0-9a-f][0-9a-f]/\./g;s/\\[0-7][0-7][0-7]/\./g;s/\ /\./g' |\
+  awk 'BEGIN { o='$offs';} { h=int(o/256); printf("\\x%02x\\x%02x",int(o-256*h), h); o+=(length($0)+1); }')
+ /bin/echo -n -e "$offs_hex" | dd of=./lang_$1.bin bs=1 seek=16 conv=notrunc 2>/dev/null
+ #write binary text data
+ dd if=./lang_$1.dat of=./lang_$1.bin bs=1 seek=$offs conv=notrunc 2>/dev/null
+ #write signature
+ if [ "$1" != "en" ]; then
+  dd if=lang_en.bin of=lang_$1.bin bs=1 count=4 skip=6 seek=12 conv=notrunc 2>/dev/null
+ fi
+ #calculate and update checksum
+ chsum=$(cat lang_$1.bin | xxd | cut -c11-49 | tr ' ' "\n" | sed '/^$/d' | awk 'BEGIN { sum = 0; } { sum += strtonum("0x"$1); if (sum > 0xffff) sum -= 0x10000; } END { printf("%x\n", sum); }')
+ /bin/echo -n -e $(echo -n $((0x$chsum)) | awk "$awk_ui16") |\
+  dd of=lang_$1.bin bs=1 count=2 seek=8 conv=notrunc 2>/dev/null
+ #remove temporary files
+# rm -f lang_$1.tmp
+# rm -f lang_$1.dat
+}
+
+if [ -z "$1" ]; then set 'all'; fi
+
+if [ "$1" = "all" ]; then
+ generate_binary 'en'
+ generate_binary 'cz'
+ generate_binary 'de'
+ generate_binary 'es'
+ generate_binary 'it'
+ generate_binary 'pl'
+else
+ generate_binary $1
+fi
+
+finish 0

+ 75 - 0
lang/lang-check.sh

@@ -0,0 +1,75 @@
+#!/bin/sh
+#
+# lang_check.sh - multi-language support script
+#  check lang_xx.bin (language binary file)
+#
+# Input files:
+#  lang_$1.bin
+#  lang_en.txt or lang_en_$1.txt
+#  
+#
+
+#set 'cz'
+
+#dictionary txt file
+fn_t=lang_en_$1.txt
+if [ "$1" = "en" ]; then fn_t=lang_en.txt; fi
+#binary file to check
+fn_b=lang_$1.bin
+
+#check txt dictionary file
+echo -n "dictionary file: $fn_t"
+if [ -e $fn_t ]; then echo " - OK"; else echo " - Not found!"; exit 1; fi
+
+#create lang_xx.tmp - different processing for 'en' language
+if [ "$1" = "en" ]; then
+ #remove comments and empty lines
+ cat lang_en.txt | sed '/^$/d;/^#/d'
+else
+ #remove comments and empty lines, print lines with translated text only
+ cat lang_en_$1.txt | sed '/^$/d;/^#/d' | sed -n 'n;p'
+fi | sed 's/^\"\\x00\"$/\"\"/' > lang_$1.tmp
+
+count_txt=$(grep -c '^"' lang_$1.tmp)
+
+echo -n "language bin file: $fn_b"
+if [ -e $fn_b ]; then echo " - OK"; else echo " - Not found!"; exit 1; fi
+
+#read header and convert to hex
+header=$(dd if=$fn_b bs=1 count=16 2>/dev/null | xxd | cut -c11-49 | sed 's/\([0-9a-f][0-9a-f]\)[\ ]*/\1 /g')
+echo "header='$header'"
+magic=0x$(echo $header | tr -d ' ' | cut -c1-8)
+echo "magic='$magic'"
+size=$(echo $header | tr -d ' ' | cut -c9-12)
+size=0x${size:2:2}${size:0:2}
+echo "size='$size' ($(($size)))"
+count=$(echo $header | tr -d ' ' | cut -c13-16)
+count=0x${count:2:2}${count:0:2}
+echo "count='$count' ($(($count)))"
+o=0
+l=0
+#create lang_xx_1.tmp (temporary text file from binary data)
+(dd if=$fn_b bs=1 count=$((2*$count)) skip=16 2>/dev/null | xxd | cut -c11-49 | tr ' ' "\n" |\
+ sed 's/\([0-9a-f][0-9a-f]\)\([0-9a-f][0-9a-f]\)/\2\1 /g;/^$/d'; printf "%04x\n" $(($size)) ) |\
+ while read offs; do
+  if [ $o -ne 0 ]; then
+   l=$((0x$offs - $o))
+   echo -n '"'
+   dd if=$fn_b bs=1 count=$((l-1)) skip=$o 2>/dev/null
+   echo '"'
+  fi
+  o=$((0x$offs))
+ done > lang_$1_1.tmp
+#create lang_xx_2.tmp (temporary text file from dictionary)
+cat lang_$1.tmp | sed 's/^\"/printf \"\\x22/;s/"$/\\x22\\x0a\"/' | sh >lang_$1_2.tmp
+#compare temporary files
+diff -a lang_$1_1.tmp lang_$1_2.tmp >lang_$1_check.dif
+dif=$(cat lang_$1_check.dif)
+if [ -z "$dif" ]; then
+ echo 'binary data OK'
+else
+ echo 'binary data NG!'
+fi
+
+read
+exit

+ 57 - 0
lang/lang-clean.sh

@@ -0,0 +1,57 @@
+#!/bin/sh
+#
+# clean.sh - multi-language support script
+#  Remove all language output files from lang folder.
+#
+
+result=0
+
+rm_if_exists()
+{
+ if [ -e $1 ]; then
+  echo -n " removing '$1'..." >&2
+  if rm $1; then
+   echo "OK" >&2
+  else
+   echo "NG!" >&2
+   result=1
+  fi
+ fi
+}
+
+clean_lang()
+{
+ if [ "$1" = "en" ]; then
+  rm_if_exists lang_$1.tmp
+ else
+  rm_if_exists lang_en_$1.tmp
+  rm_if_exists lang_en_$1.dif
+  rm_if_exists lang_$1.ofs
+  rm_if_exists lang_$1.txt
+ fi
+ rm_if_exists lang_$1.bin
+ rm_if_exists lang_$1.dat
+}
+
+echo "lang-clean.sh started" >&2
+
+clean_lang en
+clean_lang cz
+clean_lang de
+clean_lang es
+clean_lang fr
+clean_lang it
+clean_lang pl
+
+echo -n "lang-clean.sh finished" >&2
+if [ $result -eq 0 ]; then
+ echo " with success" >&2
+else
+ echo " with errors!" >&2
+fi
+
+case "$-" in
+ *i*) echo "press enter key" >&2; read ;;
+esac
+
+exit $result

+ 13 - 13
lang/lang_en_es.txt

@@ -76,7 +76,7 @@
 
 #MSG_AUTOLOADING_ONLY_IF_FSENS_ON c=20 r=4
 "Autoloading filament available only when filament sensor is turned on..."
-"La carga automatica de filamento solo funciona si el sensor de filamento está activado..."
+"La carga automatica de filamento solo funciona si el sensor de filamento esta activado..."
 
 #MSG_AUTOLOADING_ENABLED c=20 r=4
 "Autoloading filament is active, just press the knob and insert filament..."
@@ -132,7 +132,7 @@
 
 #MSG_RECOVER_PRINT c=20 r=2
 "Blackout occurred. Recover print?"
-"Se fue la luz. ¿Reanudar la impresion?"
+"Se fue la luz. Reanudar la impresion?"
 
 #MSG_CALIBRATE_BED c=0 r=0
 "Calibrate XYZ"
@@ -252,7 +252,7 @@
 
 #MSG_STACK_ERROR c=20 r=4
 "Error - static memory has been overwritten"
-"Error - se ha sobre-escrito la memoria estática"
+"Error - se ha sobre-escrito la memoria estatica"
 
 #MSG_SD_ERR_WRITE_TO_FILE c=0 r=0
 "error writing to file"
@@ -260,7 +260,7 @@
 
 #MSG_FSENS_NOT_RESPONDING c=20 r=4
 "ERROR: Filament sensor is not responding, please check connection."
-"ERROR: El sensor de filamento no responde, por favor comprueba la conexión."
+"ERROR: El sensor de filamento no responde, por favor comprueba la conexion."
 
 #MSG_ERROR c=0 r=0
 "ERROR:"
@@ -336,7 +336,7 @@
 
 #MSG_FILE_INCOMPLETE c=20 r=2
 "File incomplete. Continue anyway?"
-"Archivo incompleto. ¿Continuar de todos modos?"
+"Archivo incompleto. Continuar de todos modos?"
 
 #MSG_SD_FILE_OPENED c=0 r=0
 "File opened: "
@@ -508,7 +508,7 @@
 
 #MSG_STEEL_SHEET_CHECK c=20 r=2
 "Is steel sheet on heatbed?"
-"¿Esta colocada la lamina de acero sobre la base?"
+"Esta colocada la lamina de acero sobre la base?"
 
 #MSG_FIND_BED_OFFSET_AND_SKEW_ITERATION c=20 r=0
 "Iteration "
@@ -584,7 +584,7 @@
 
 #MSG_MESH_BED_LEVELING c=0 r=0
 "Mesh Bed Leveling"
-"Nivelación Mesh Level"
+"Nivelacion Mesh Level"
 
 #MSG_STEALTH_MODE_OFF c=0 r=0
 "Mode     [Normal]"
@@ -668,7 +668,7 @@
 
 #MSG_DEFAULT_SETTINGS_LOADED c=20 r=4
 "Old settings found. Default PID, Esteps etc. will be set."
-"Se han encontrado ajustes anteriores. Se ajustará el PID, los pasos del extrusor, etc"
+"Se han encontrado ajustes anteriores. Se ajustara el PID, los pasos del extrusor, etc"
 
 #MSG_SD_OPEN_FILE_FAIL c=0 r=0
 "open failed, File: "
@@ -820,7 +820,7 @@
 
 #MSG_RECOVERING_PRINT c=20 r=1
 "Recovering print    "
-"Recuperando impresión"
+"Recuperando impresion"
 
 #MSG_M119_REPORT c=0 r=0
 "Reporting endstop status"
@@ -908,7 +908,7 @@
 
 #MSG_FORCE_SELFTEST c=20 r=8
 "Selftest will be run to calibrate accurate sensorless rehoming."
-"Se realizará el auto-test para calibrar con precisión la vuelta a la posición inicial sin sensores."
+"Se realizara el auto-test para calibrar con precision la vuelta a la posicion inicial sin sensores."
 
 #MSG_SET_TEMPERATURE c=19 r=1
 "Set temperature:"
@@ -940,7 +940,7 @@
 
 #MSG_SORT_ALPHA c=17 r=1
 "Sort:  [Alphabet]"
-"Orden:[Alfabétic]"
+"Orden:[Alfabetic]"
 
 #MSG_SORTING c=20 r=1
 "Sorting files"
@@ -1052,7 +1052,7 @@
 
 #MSG_WAITING_TEMP_PINDA c=20 r=3
 "Waiting for PINDA probe cooling"
-"Esperando a que se enfríe la sonda PINDA"
+"Esperando a que se enfrie la sonda PINDA"
 
 #MSG_CHANGED_BOTH c=20 r=4
 "Warning: both printer type and motherboard type changed."
@@ -1068,7 +1068,7 @@
 
 #MSG_UNLOAD_SUCCESSFUL c=20 r=2
 "Was filament unload successful?"
-"¿Se cargocon exito el filamento?"
+"Se cargocon exito el filamento?"
 
 #MSG_SELFTEST_WIRINGERROR c=0 r=0
 "Wiring error"

+ 15 - 15
lang/lang_en_it.txt

@@ -76,11 +76,11 @@
 
 #MSG_AUTOLOADING_ONLY_IF_FSENS_ON c=20 r=4
 "Autoloading filament available only when filament sensor is turned on..."
-"Il caricamento automatico del filamento è disponibile solo quando il sensore è acceso..."
+"Il caricamento automatico del filamento e disponibile solo quando il sensore e acceso..."
 
 #MSG_AUTOLOADING_ENABLED c=20 r=4
 "Autoloading filament is active, just press the knob and insert filament..."
-"Il caricamento automatico è attivo, premete la manopola e inserite il filamento..."
+"Il caricamento automatico e attivo, premete la manopola e inserite il filamento..."
 
 #MSG_SELFTEST_AXIS_LENGTH c=0 r=0
 "Axis length"
@@ -132,7 +132,7 @@
 
 #MSG_RECOVER_PRINT c=20 r=2
 "Blackout occurred. Recover print?"
-"C'è stato un Blackout. Recuperare la stampa?"
+"C'e stato un Blackout. Recuperare la stampa?"
 
 #MSG_CALIBRATE_BED c=0 r=0
 "Calibrate XYZ"
@@ -252,7 +252,7 @@
 
 #MSG_STACK_ERROR c=20 r=4
 "Error - static memory has been overwritten"
-"Errore - la memoria statica è stata sovrascritta"
+"Errore - la memoria statica e stata sovrascritta"
 
 #MSG_SD_ERR_WRITE_TO_FILE c=0 r=0
 "error writing to file"
@@ -292,7 +292,7 @@
 
 #MSG_FAN_SPEED c=14 r=0
 "Fan speed"
-"Velocità ventola"
+"Velocita ventola"
 
 #MSG_SELFTEST_FAN c=20 r=0
 "Fan test"
@@ -356,7 +356,7 @@
 
 #MSG_WIZARD_SELFTEST c=20 r=8
 "First, I will run the selftest to check most common assembly problems."
-"Per primo avvierò l'autotest per controllare gli errori di assemblaggio più comuni."
+"Per primo avviero l'autotest per controllare gli errori di assemblaggio piu comuni."
 
 #MSG_FLOW c=0 r=0
 "Flow"
@@ -456,11 +456,11 @@
 
 #MSG_WIZARD_XYZ_CAL c=20 r=8
 "I will run xyz calibration now. It will take approx. 12 mins."
-"Adesso avviero una Calibrazione XYZ. Può durare circa 12 min."
+"Adesso avviero una Calibrazione XYZ. Puo durare circa 12 min."
 
 #MSG_WIZARD_Z_CAL c=20 r=8
 "I will run z calibration now."
-"Adesso avvierò la Calibrazione Z."
+"Adesso avviero la Calibrazione Z."
 
 #MSG_WIZARD_V2_CAL_2 c=20 r=12
 "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."
@@ -656,7 +656,7 @@
 
 #MSG_WIZARD_WILL_PREHEAT c=20 r=4
 "Now I will preheat nozzle for PLA."
-"Adesso preriscalderò l'ugello per PLA."
+"Adesso preriscaldero l'ugello per PLA."
 
 #MSG_NOZZLE c=0 r=0
 "Nozzle"
@@ -804,7 +804,7 @@
 
 #MSG_ERR_STOPPED c=0 r=0
 "Printer stopped due to errors. Fix the error and use M999 to restart. (Temperature is reset. Set it after restarting)"
-"La stampante si è fermata a causa di errori. Correggete l'errore e usate M999 per riavviare. (La temperatura viene resettate. Impostatela dopo il riavvio)"
+"La stampante si e fermata a causa di errori. Correggete l'errore e usate M999 per riavviare. (La temperatura viene resettate. Impostatela dopo il riavvio)"
 
 #WELCOME_MSG c=20 r=0
 "Prusa i3 MK3 ready."
@@ -908,7 +908,7 @@
 
 #MSG_FORCE_SELFTEST c=20 r=8
 "Selftest will be run to calibrate accurate sensorless rehoming."
-"Verrà effettuato un self test per calibrare l'homing senza sensori"
+"Verra effettuato un self test per calibrare l'homing senza sensori"
 
 #MSG_SET_TEMPERATURE c=19 r=1
 "Set temperature:"
@@ -928,7 +928,7 @@
 
 #MSG_FILE_CNT c=20 r=4
 "Some files will not be sorted. Max. No. of files in 1 folder for sorting is 100."
-"Alcuni file non saranno ordinati. Il numero massimo di file in una cartella è 100 perché siano ordinati."
+"Alcuni file non saranno ordinati. Il numero massimo di file in una cartella e 100 perche siano ordinati."
 
 #MSG_SORT_NONE c=17 r=1
 "Sort:      [None]"
@@ -948,7 +948,7 @@
 
 #MSG_SPEED c=0 r=0
 "Speed"
-"Velocità"
+"Velocita"
 
 #MSG_SELFTEST_FAN_YES c=19 r=0
 "Spinning"
@@ -964,7 +964,7 @@
 
 #MSG_STEPPER_TOO_HIGH c=0 r=0
 "Steprate too high: "
-"Velocità passo troppo alta: "
+"Velocita passo troppo alta: "
 
 #MSG_STOP_PRINT c=0 r=0
 "Stop print"
@@ -1004,7 +1004,7 @@
 
 #MSG_TEMP_CALIBRATION_DONE c=20 r=12
 "Temperature calibration is finished and active. Temp. calibration can be disabled in menu Settings->Temp. cal."
-"Calibrazione temperatura completata e attiva. Può essere disattivata dal menù Impostazioni ->Cal. Temp."
+"Calibrazione temperatura completata e attiva. Puo essere disattivata dal menu Impostazioni ->Cal. Temp."
 
 #MSG_TEMPERATURE c=0 r=0
 "Temperature"

+ 208 - 208
lang/lang_en_pl.txt

@@ -1,6 +1,6 @@
 #MSG_EXTRUDER_CORRECTION_OFF c=6 r=0
 "  [off"
-"\x00"
+"[wyl"
 
 #MSG_PLANNER_BUFFER_BYTES c=0 r=0
 "  PlannerBufferBytes: "
@@ -8,15 +8,15 @@
 
 #MSG_ERR_COLD_EXTRUDE_STOP c=0 r=0
 " cold extrusion prevented"
-"\x00"
+" nie dopuszczono do zimnej ekstruzji"
 
 #MSG_FREE_MEMORY c=0 r=0
 " Free Memory: "
-"\x00"
+" Wolna pamiec:"
 
 #MSG_CONFIGURATION_VER c=0 r=0
 " Last Updated: "
-"\x00"
+" Ostatnia aktualizacja: "
 
 #MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2 c=14 r=0
 " of 4"
@@ -28,7 +28,7 @@
 
 #MSG_MEASURED_OFFSET c=0 r=0
 "[0;0] point offset"
-"\x00"
+"[0;0] przesuniecie punktu"
 
 #MSG_CRASH_DET_ONLY_IN_NORMAL c=20 r=4
 "\x1b[2JCrash detection can\x1b[1;0Hbe turned on only in\x1b[2;0HNormal mode"
@@ -40,11 +40,11 @@
 
 #MSG_REFRESH c=0 r=0
 "\xf8Refresh"
-"\xf8Obnovit"
+"\x00"
 
 #MSG_BABYSTEPPING_Z c=20 r=0
 "Adjusting Z"
-"Dostrojenie Z"
+"Dostrajanie Z"
 
 #MSG_SELFTEST_CHECK_ALLCORRECT c=20 r=0
 "All correct      "
@@ -52,15 +52,15 @@
 
 #MSG_WIZARD_DONE c=20 r=8
 "All is done. Happy printing!"
-"Gotowe. Udanego druku!"
+"Gotowe. Udanego drukowania!"
 
 #MSG_PRESS c=20 r=0
 "and press the knob"
-"Nacisnij przycisk"
+"i nacisnij pokretlo"
 
 #MSG_CONFIRM_CARRIAGE_AT_THE_TOP c=20 r=2
 "Are left and right Z~carriages all up?"
-"Oba wozki dojechaly do gornej ramy?"
+"Obydwa konce osi dojechaly do gornych ogranicznikow?"
 
 #MSG_ADJUSTZ c=0 r=0
 "Auto adjust Z?"
@@ -68,71 +68,71 @@
 
 #MSG_AUTO_HOME c=0 r=0
 "Auto home"
-"\x00"
+"Auto zerowanie"
 
 #MSG_AUTOLOAD_FILAMENT c=17 r=0
 "AutoLoad filament"
-"\x00"
+"AutoLadowanie filamentu"
 
 #MSG_AUTOLOADING_ONLY_IF_FSENS_ON c=20 r=4
 "Autoloading filament available only when filament sensor is turned on..."
-"\x00"
+"Autoladowanie filamentu dostepne tylko gdy czujnik filamentu jest wlaczony..."
 
 #MSG_AUTOLOADING_ENABLED c=20 r=4
 "Autoloading filament is active, just press the knob and insert filament..."
-"\x00"
+"Autoladowanie filamentu wlaczone, nacisnij pokretlo i wsun filament..."
 
 #MSG_SELFTEST_AXIS_LENGTH c=0 r=0
 "Axis length"
-"\x00"
+"Dlugosc osi"
 
 #MSG_SELFTEST_AXIS c=0 r=0
 "Axis"
-"\x00"
+"Os"
 
 #MSG_SELFTEST_BEDHEATER c=0 r=0
 "Bed / Heater"
-"\x00"
+"Stol / Grzanie"
 
 #MSG_BED_DONE c=0 r=0
 "Bed done"
-"Stolik OK."
+"Stol OK"
 
 #MSG_BED_HEATING c=0 r=0
 "Bed Heating"
-"Grzanie stolika.."
+"Grzanie stolu.."
 
 #MSG_BED_CORRECTION_MENU c=0 r=0
 "Bed level correct"
-"Korekta podkladki"
+"Korekta poziomowania stolu"
 
 #MSG_BED_LEVELING_FAILED_POINT_LOW c=20 r=4
 "Bed leveling failed. Sensor didnt trigger. Debris on nozzle? Waiting for reset."
-"Kalibracja nieudana. Sensor nie dotknal. Zanieczysz. dysza? Czekam na reset."
+"Kalibracja nieudana. Sensor nie aktywowal sie. Zanieczysz. dysza? Czekam na reset."
 
 #MSG_BED_LEVELING_FAILED_PROBE_DISCONNECTED c=20 r=4
 "Bed leveling failed. Sensor disconnected or cable broken. Waiting for reset."
-"Kalibracja nieudana. Sensor odlaczony lub uszkodz. kabel. Czekam na reset."
+"Poziomowanie stolu nieudane. Sensor odlacz. lub uszkodz. przewod. Czekam na reset."
 
 #MSG_BED_LEVELING_FAILED_POINT_HIGH c=20 r=4
 "Bed leveling failed. Sensor triggered too high. Waiting for reset."
-"Kalibracja Z nieudana. Sensor dotk. za wysoko. Czekam na reset."
+"Kalibracja Z nieudana. Sensor aktywowal za wysoko. Czekam na reset."
 
 #MSG_BED c=0 r=0
 "Bed"
-"Stolik"
+"Stol"
 
 #MSG_BEGIN_FILE_LIST c=0 r=0
 "Begin file list"
-"\x00"
+"Poczatek listy plikowogranicznikow"
 
 #MSG_MENU_BELT_STATUS c=15 r=1
 "Belt status"
-"\x00"
+"Stan paskow"
 
 #MSG_RECOVER_PRINT c=20 r=2
 "Blackout occurred. Recover print?"
-"\x00"
+"Wykryto zanik napiecia. Kontynowac?"
 
 #MSG_CALIBRATE_BED c=0 r=0
 "Calibrate XYZ"
@@ -144,11 +144,11 @@
 
 #MSG_CALIBRATE_PINDA c=17 r=1
 "Calibrate"
-"Skalibrowac"
+"Kalibruj"
 
 #MSG_MOVE_CARRIAGE_TO_THE_TOP c=20 r=8
 "Calibrating XYZ. Rotate the knob to move the Z carriage up to the end stoppers. Click when done."
-"Kalibracja XYZ. Przekrec galke, aby przesunac os Z do gornych krancowek. Nacisnij, by potwierdzic."
+"Kalibracja XYZ. Przekrec pokretlo, aby przesunac os Z do gornych ogranicznikow. Nacisnij, by potwierdzic."
 
 #MSG_CALIBRATE_Z_AUTO c=20 r=2
 "Calibrating Z"
@@ -156,7 +156,7 @@
 
 #MSG_MOVE_CARRIAGE_TO_THE_TOP_Z c=20 r=8
 "Calibrating Z. Rotate the knob to move the Z carriage up to the end stoppers. Click when done."
-"Kalibracja Z. Przekrec galke, aby przesunac os Z do gornych krancowek. Nacisnij, by potwierdzic."
+"Kalibracja XYZ. Przekrec pokretlo, aby przesunac os Z do gornych ogranicznikow. Nacisnij, by potwierdzic."
 
 #MSG_HOMEYZ_DONE c=0 r=0
 "Calibration done"
@@ -168,7 +168,7 @@
 
 #MSG_SD_CANT_ENTER_SUBDIR c=0 r=0
 "Cannot enter subdir: "
-"\x00"
+"Brak dostepu do subdir: "
 
 #MSG_SD_INSERTED c=0 r=0
 "Card inserted"
@@ -184,27 +184,27 @@
 
 #MSG_COOLDOWN c=0 r=0
 "Cooldown"
-"Wychlodzic"
+"Chlodzenie"
 
 #MSG_CRASHDETECT_ON c=0 r=0
 "Crash det.   [on]"
-"\x00"
+"Wykr. zderzen [wl]"
 
 #MSG_CRASHDETECT_NA c=0 r=0
 "Crash det.  [N/A]"
-"\x00"
+"Wykr. zderzen [n/d]"
 
 #MSG_CRASHDETECT_OFF c=0 r=0
 "Crash det.  [off]"
-"\x00"
+"Wykr. zderzen [wyl]"
 
 #MSG_CRASH_DETECTED c=20 r=1
 "Crash detected."
-"\x00"
+"Zderzenie wykryte"
 
 #MSG_CURRENT c=19 r=1
 "Current"
-"Tylko aktualne"
+"Aktualne"
 
 #MSG_DATE c=17 r=1
 "Date:"
@@ -212,39 +212,39 @@
 
 #MSG_DISABLE_STEPPERS c=0 r=0
 "Disable steppers"
-"Wylaczyc silniki"
+"Wylaczenie silnikow"
 
 #MSG_BABYSTEP_Z_NOT_SET c=20 r=12
 "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."
-"Odleglosc dyszy od podkladki nie jest skalibrowana. Postepuj zgodnie z instrukcja rozdzial Zaczynamy, podrozdzial Kalibracja pierwszej warstwy."
+"Odleglosc dyszy od powierzchni druku nie jest skalibrowana. Postepuj zgodnie z instrukcja: rozdzial Wprowadzenie - Kalibracja pierwszej warstwy."
 
 #MSG_WIZARD_REPEAT_V2_CAL c=20 r=7
 "Do you want to repeat last step to readjust distance between nozzle and heatbed?"
-"Chcesz powtorzyc ostatni krok i przestawic odleglosc miedzy dysza a stolikiem?"
+"Chcesz powtorzyc ostatni krok i ponownie ustawic odleglosc miedzy dysza a stolikiem?"
 
 #MSG_EXTRUDER_CORRECTION c=9 r=0
 "E-correct"
-"\x00"
+"Korekcja E"
 
 #MSG_END_FILE_LIST c=0 r=0
 "End file list"
-"\x00"
+"Koniec listy plikow"
 
 #MSG_SELFTEST_ENDSTOP_NOTHIT c=20 r=1
 "Endstop not hit"
-"\x00"
+"Krancowka nie aktyw."
 
 #MSG_SELFTEST_ENDSTOP c=0 r=0
 "Endstop"
-"\x00"
+"Krancowka"
 
 #MSG_ENDSTOPS_HIT c=0 r=0
 "endstops hit: "
-"\x00"
+"krancowki aktywowane:"
 
 #MSG_SELFTEST_ENDSTOPS c=0 r=0
 "Endstops"
-"\x00"
+"Krancowki"
 
 #MSG_Enqueing c=0 r=0
 "enqueing \x22"
@@ -252,15 +252,15 @@
 
 #MSG_STACK_ERROR c=20 r=4
 "Error - static memory has been overwritten"
-"\x00"
+"Blad - pamiec statyczna zostala nadpisana"
 
 #MSG_SD_ERR_WRITE_TO_FILE c=0 r=0
 "error writing to file"
-"\x00"
+"blad zapisywania pliku"
 
 #MSG_FSENS_NOT_RESPONDING c=20 r=4
 "ERROR: Filament sensor is not responding, please check connection."
-"\x00"
+"BLAD: Czujnik filamentu nie odpowiada, sprawdz polaczenie."
 
 #MSG_ERROR c=0 r=0
 "ERROR:"
@@ -268,27 +268,27 @@
 
 #MSG_SELFTEST_EXTRUDER_FAN_SPEED c=18 r=0
 "Extruder fan:"
-"\x00"
+"Went. ekstrudera:"
 
 #MSG_INFO_EXTRUDER c=15 r=1
 "Extruder info"
-"\x00"
+"Informacje o ekstruderze"
 
 #MSG_MOVE_E c=0 r=0
 "Extruder"
-"\x00"
+"Ekstruder"
 
 #MSG_FSENS_AUTOLOAD_ON c=17 r=1
 "F. autoload  [on]"
-"\x00"
+"Autoladowanie fil. [wl]"
 
 #MSG_FSENS_AUTOLOAD_NA c=17 r=1
 "F. autoload [N/A]"
-"\x00"
+"Autoladowanie fil. [N/D]"
 
 #MSG_FSENS_AUTOLOAD_OFF c=17 r=1
 "F. autoload [off]"
-"\x00"
+"Autoladowanie [wyl]"
 
 #MSG_FAN_SPEED c=14 r=0
 "Fan speed"
@@ -300,51 +300,51 @@
 
 #MSG_FANS_CHECK_ON c=17 r=1
 "Fans check   [on]"
-"\x00"
+"Sprawdzanie wentylatorow [wl]"
 
 #MSG_FANS_CHECK_OFF c=17 r=1
 "Fans check  [off]"
-"\x00"
+"Sprawdzanie wentylatorow [wyl]"
 
 #MSG_FSENSOR_ON c=0 r=0
 "Fil. sensor  [on]"
-"\x00"
+"Czuj. filamentu. [wl]"
 
 #MSG_FSENSOR_NA c=0 r=0
 "Fil. sensor [N/A]"
-"\x00"
+"Czuj. filamentu [N/D]"
 
 #MSG_FSENSOR_OFF c=0 r=0
 "Fil. sensor [off]"
-"\x00"
+"Czuj. fil. [wyl]"
 
 #MSG_FILAMENT_CLEAN c=20 r=2
 "Filament extruding & with correct color?"
-"Czy kolor jest czysty?"
+"Filament wychodzi z dyszy a kolor jest czysty?"
 
 #MSG_NOT_LOADED c=19 r=0
 "Filament not loaded"
-"Brak filamentu"
+"Filament nie zaladowany"
 
 #MSG_FILAMENT_SENSOR c=20 r=0
 "Filament sensor"
-"\x00"
+"Czujnik filamentu"
 
 #MSG_SELFTEST_FILAMENT_SENSOR c=18 r=0
 "Filament sensor:"
-"\x00"
+"Czujnik filamentu:"
 
 #MSG_FILE_INCOMPLETE c=20 r=2
 "File incomplete. Continue anyway?"
-"\x00"
+"Plik niekompletny. Kontynowac?"
 
 #MSG_SD_FILE_OPENED c=0 r=0
 "File opened: "
-"\x00"
+"Otwarty plik:"
 
 #MSG_SD_FILE_SELECTED c=0 r=0
 "File selected"
-"\x00"
+"Wybrano plik"
 
 #MSG_FINISHING_MOVEMENTS c=20 r=1
 "Finishing movements"
@@ -356,7 +356,7 @@
 
 #MSG_WIZARD_SELFTEST c=20 r=8
 "First, I will run the selftest to check most common assembly problems."
-"Najpierw wlacze autotest w celu kontrolli najczestszych problemow z montazem."
+"Najpierw wlacze selftest w celu sprawdzenia najczestszych problemow podczas montazu."
 
 #MSG_FLOW c=0 r=0
 "Flow"
@@ -364,7 +364,7 @@
 
 #MSG_PRUSA3D_FORUM c=0 r=0
 "forum.prusa3d.com"
-"forum.prusa3d.cz"
+"\x00"
 
 #MSG_SELFTEST_COOLING_FAN c=20 r=0
 "Front print fan?"
@@ -372,23 +372,23 @@
 
 #MSG_BED_CORRECTION_FRONT c=14 r=1
 "Front side[um]"
-"Do przodu [um]"
+"Przod [um]"
 
 #MSG_SELFTEST_FANS c=0 r=0
 "Front/left fans"
-"\x00"
+"Przedni/lewy wentylator"
 
 #MSG_SELFTEST_HEATERTHERMISTOR c=0 r=0
 "Heater/Thermistor"
-"\x00"
+"Grzalka/Termistor"
 
 #MSG_BED_HEATING_SAFETY_DISABLED c=0 r=0
 "Heating disabled by safety timer."
-"\x00"
+"Grzanie wylaczone przez wyl. czasowy"
 
 #MSG_HEATING_COMPLETE c=20 r=0
 "Heating done."
-"Grzanie OK."
+"Grzanie zakonczone"
 
 #MSG_HEATING c=0 r=0
 "Heating"
@@ -396,15 +396,15 @@
 
 #MSG_WIZARD_WELCOME c=20 r=7
 "Hi, I am your Original Prusa i3 printer. Would you like me to guide you through the setup process?"
-"Czesc, jestem Twoja drukarka Original Prusa i3. Czy potrzebujesz pomocy z instalacja?"
+"Czesc, jestem Twoja drukarka Original Prusa i3. Czy potrzebujesz pomocy z ustawieniem?"
 
 #MSG_PRUSA3D_HOWTO c=0 r=0
 "howto.prusa3d.com"
-"howto.prusa3d.cz"
+"\x00"
 
 #MSG_FILAMENTCHANGE c=0 r=0
 "Change filament"
-"Wymienic filament"
+"Wymiana filamentu"
 
 #MSG_CHANGE_SUCCESS c=0 r=0
 "Change success!"
@@ -416,79 +416,79 @@
 
 #MSG_CHANGING_FILAMENT c=20 r=0
 "Changing filament!"
-"Wymiana filamentu"
+"Wymiana filamentu!"
 
 #MSG_SELFTEST_CHECK_BED c=20 r=0
 "Checking bed     "
-"Kontrola bed "
+"Kontrola stolu"
 
 #MSG_SELFTEST_CHECK_ENDSTOPS c=20 r=0
 "Checking endstops"
-"Kontrola endstops"
+"Kontrola krancowek"
 
 #MSG_SELFTEST_CHECK_HOTEND c=20 r=0
 "Checking hotend  "
-"Kontrola hotend "
+"Kontrola hotendu"
 
 #MSG_SELFTEST_CHECK_FSENSOR c=20 r=0
 "Checking sensors "
-"\x00"
+"Sprawdzanie czujnikow"
 
 #MSG_SELFTEST_CHECK_X c=20 r=0
 "Checking X axis  "
-"Kontrola X axis "
+"Kontrola osi X"
 
 #MSG_SELFTEST_CHECK_Y c=20 r=0
 "Checking Y axis  "
-"Kontrola Y axis "
+"Kontrola osi Y"
 
 #MSG_SELFTEST_CHECK_Z c=20 r=0
 "Checking Z axis  "
-"Kontrola Z axis "
+"Kontrola osi Z"
 
 #MSG_ERR_CHECKSUM_MISMATCH c=0 r=0
 "checksum mismatch, Last Line: "
-"\x00"
+"suma kontrolna niezgodna, ostatnia linia:"
 
 #MSG_CHOOSE_EXTRUDER c=20 r=1
 "Choose extruder:"
-"Wybierz ekstruder"
+"Wybierz ekstruder:"
 
 #MSG_WIZARD_XYZ_CAL c=20 r=8
 "I will run xyz calibration now. It will take approx. 12 mins."
-"Wlaczam kalibracje xyz. Zajmie to ok. 12 min."
+"Przeprowadze teraz kalibracje XYZ. Zajmie ok. 12 min."
 
 #MSG_WIZARD_Z_CAL c=20 r=8
 "I will run z calibration now."
-"Wlaczam kalibracje z."
+"Przeprowadze kalibracje Z."
 
 #MSG_WIZARD_V2_CAL_2 c=20 r=12
 "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."
-"Zaczne drukowac linie. Stopniowo opuszczaj dysze przekrecajac guzik, poki nie uzyskasz optymalnej wysokosci. Sprawdz obrazki w naszym poradniku w rozdz. Kalibracja"
+"Zaczne drukowac linie. Stopniowo opuszczaj dysze przekrecajac pokretlo, poki nie uzyskasz optymalnej wysokosci. Sprawdz obrazki w naszym Podreczniku w rozdz. Kalibracja"
 
 #MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1 c=60 r=0
 "Improving bed calibration point"
-"Poprawiam precyzyjnosc punktu kalibracyjnego"
+"Poprawiam precyzje punktu kalibracyjnego"
 
 #MSG_WATCH c=0 r=0
 "Info screen"
-"Informacje"
+"Ekran informacyjny"
 
 #MSG_FILAMENT_LOADING_T0 c=20 r=4
 "Insert filament into extruder 1. Click when done."
-"Wloz filament do ekstrudera 1. Potwierdz przyciskiem."
+"Wloz filament do ekstrudera 1. Potwierdz naciskajac pokretlo."
 
 #MSG_FILAMENT_LOADING_T1 c=20 r=4
 "Insert filament into extruder 2. Click when done."
-"Wloz filament do ekstrudera 2. Potwierdz przyciskiem."
+"Wloz filament do ekstrudera 2. Potwierdz naciskajac pokretlo."
 
 #MSG_FILAMENT_LOADING_T2 c=20 r=4
 "Insert filament into extruder 3. Click when done."
-"Wloz filament do ekstrudera 3. Potwierdz przyciskiem."
+"Wloz filament do ekstrudera 3. Potwierdz naciskajac pokretlo."
 
 #MSG_FILAMENT_LOADING_T3 c=20 r=4
 "Insert filament into extruder 4. Click when done."
-"Wloz filament do ekstrudera 4. Potwierdz przyciskiem."
+"Wloz filament do ekstrudera 4. Potwierdz naciskajac pokretlo."
 
 #MSG_INSERT_FILAMENT c=20 r=0
 "Insert filament"
@@ -508,7 +508,7 @@
 
 #MSG_STEEL_SHEET_CHECK c=20 r=2
 "Is steel sheet on heatbed?"
-"\x00"
+"Czy plyta stal. jest na podgrzew. stole?"
 
 #MSG_FIND_BED_OFFSET_AND_SKEW_ITERATION c=20 r=0
 "Iteration "
@@ -516,23 +516,23 @@
 
 #MSG_KILLED c=0 r=0
 "KILLED. "
-"\x00"
+"PRZERWANE."
 
 #MSG_SELFTEST_EXTRUDER_FAN c=20 r=0
 "Left hotend fan?"
-"Lewy went na dysze?"
+"Lewy went hotendu?"
 
 #MSG_BED_CORRECTION_LEFT c=14 r=1
 "Left side [um]"
-"W lewo [um]"
+"Lewo [um]"
 
 #MSG_BABYSTEP_Z c=0 r=0
 "Live adjust Z"
-"Dostrojenie osy Z"
+"Dostrajanie osi Z"
 
 #MSG_LOAD_FILAMENT c=17 r=0
 "Load filament"
-"Wprowadz filament"
+"Ladowanie filamentu"
 
 #MSG_LOADING_COLOR c=0 r=0
 "Loading color"
@@ -540,23 +540,23 @@
 
 #MSG_LOADING_FILAMENT c=20 r=0
 "Loading filament"
-"Wprow. filamentu"
+"Ladowanie filamentu"
 
 #MSG_LOOSE_PULLEY c=20 r=1
 "Loose pulley"
-"Kolo pasowe"
+"Luzne kolo pasowe"
 
 #MSG_M104_INVALID_EXTRUDER c=0 r=0
 "M104 Invalid extruder "
-"\x00"
+"M104 Nieprawidlowy ekstruder"
 
 #MSG_M105_INVALID_EXTRUDER c=0 r=0
 "M105 Invalid extruder "
-"\x00"
+"M105 Nieprawidlowy ekstruder"
 
 #MSG_M109_INVALID_EXTRUDER c=0 r=0
 "M109 Invalid extruder "
-"\x00"
+"M109 Nieprawidlowy ekstruder"
 
 #MSG_M117_V2_CALIBRATION c=25 r=1
 "M117 First layer cal."
@@ -564,15 +564,15 @@
 
 #MSG_M200_INVALID_EXTRUDER c=0 r=0
 "M200 Invalid extruder "
-"\x00"
+"M200 Nieprawidlowy ekstruder"
 
 #MSG_M218_INVALID_EXTRUDER c=0 r=0
 "M218 Invalid extruder "
-"\x00"
+"M218 Nieprawidlowy ekstruder"
 
 #MSG_M221_INVALID_EXTRUDER c=0 r=0
 "M221 Invalid extruder "
-"\x00"
+"M221 Nieprawidlowy ekstruder"
 
 #MSG_MAIN c=0 r=0
 "Main"
@@ -584,11 +584,11 @@
 
 #MSG_MESH_BED_LEVELING c=0 r=0
 "Mesh Bed Leveling"
-"\x00"
+"Poziomowanie stolu wg siatki"
 
 #MSG_STEALTH_MODE_OFF c=0 r=0
 "Mode     [Normal]"
-"\x00"
+"Tryb [normalny]"
 
 #MSG_SILENT_MODE_ON c=0 r=0
 "Mode     [silent]"
@@ -596,15 +596,15 @@
 
 #MSG_STEALTH_MODE_ON c=0 r=0
 "Mode    [Stealth]"
-"\x00"
+"Tryb [Stealth]"
 
 #MSG_AUTO_MODE_ON c=0 r=0
 "Mode [auto power]"
-"\x00"
+"Tryb [automatyczny]"
 
 #MSG_SILENT_MODE_OFF c=0 r=0
 "Mode [high power]"
-"Tryb[w wydajnosc]"
+"Tryb [wysoka wydajnosc]"
 
 #MSG_SELFTEST_MOTOR c=0 r=0
 "Motor"
@@ -616,23 +616,23 @@
 
 #MSG_MOVE_X c=0 r=0
 "Move X"
-"Przesunac X"
+"Ruch osi X"
 
 #MSG_MOVE_Y c=0 r=0
 "Move Y"
-"Przesunac Y"
+"Ruch osi Y"
 
 #MSG_MOVE_Z c=0 r=0
 "Move Z"
-"Przesunac Z"
+"Ruch osi Z"
 
 #MSG_ERR_NO_CHECKSUM c=0 r=0
 "No Checksum with line number, Last Line: "
-"\x00"
+"Brak sumy kontrolnej z numerem linii, ostatnia linia:"
 
 #MSG_NO_MOVE c=0 r=0
 "No move."
-"\x00"
+"Brak ruchu."
 
 #MSG_NO_CARD c=0 r=0
 "No SD card"
@@ -652,7 +652,7 @@
 
 #MSG_WIZARD_V2_CAL c=20 r=8
 "Now I will calibrate distance between tip of the nozzle and heatbed surface."
-"Kalibruje odleglosc miedzy koncowka dyszy a stolikiem."
+"Kalibruje odleglosc miedzy koncowka dyszy a powierzchnia druku."
 
 #MSG_WIZARD_WILL_PREHEAT c=20 r=4
 "Now I will preheat nozzle for PLA."
@@ -668,27 +668,27 @@
 
 #MSG_DEFAULT_SETTINGS_LOADED c=20 r=4
 "Old settings found. Default PID, Esteps etc. will be set."
-"\x00"
+"Znaleziono stare ustawienia. Zostana przywrocone domyslne ust. PID, Esteps, itp."
 
 #MSG_SD_OPEN_FILE_FAIL c=0 r=0
 "open failed, File: "
-"\x00"
+"niepowodzenie otwarcia, Plik:"
 
 #MSG_ENDSTOP_OPEN c=0 r=0
 "open"
-"\x00"
+"otworz"
 
 #MSG_SD_OPENROOT_FAIL c=0 r=0
 "openRoot failed"
-"\x00"
+"niepowodzenie openRoot "
 
 #MSG_PAUSE_PRINT c=0 r=0
 "Pause print"
-"Przerwac druk"
+"Wstrzymanie wydruku"
 
 #MSG_PID_RUNNING c=20 r=1
 "PID cal.           "
-"Kal. PID"
+"Kalibracja PID"
 
 #MSG_PID_FINISHED c=20 r=1
 "PID cal. finished"
@@ -700,59 +700,59 @@
 
 #MSG_PINDA_PREHEAT c=20 r=1
 "PINDA Heating"
-"Grzanie PINDA"
+"Grzanie sondy PINDA"
 
 #MSG_PAPER c=20 r=8
 "Place a sheet of paper under the nozzle during the calibration of first 4 points. If the nozzle catches the paper, power off the printer immediately."
-"Umiesc kartke papieru na podkladce i trzymaj pod dysza podczas pomiaru pierwszych 4 punktow. Jesli dysza zahaczy o papier, wylacz drukarke."
+"Umiesc kartke papieru na stole roboczym i podczas pomiaru pierwszych 4 punktow. Jesli dysza zahaczy o papier, natychmiast wylacz drukarke."
 
 #MSG_WIZARD_CLEAN_HEATBED c=20 r=8
 "Please clean heatbed and then press the knob."
-"Prosze oczysc stolik i nacisnij guzik."
+"Oczysc powierzchnie druku i nacisnij pokretlo."
 
 #MSG_CONFIRM_NOZZLE_CLEAN c=20 r=8
 "Please clean the nozzle for calibration. Click when done."
-"Dla prawidl. kalibracji prosze oczyscic dysze. Potw. guzikiem."
+"Dla prawidl. kalibracji nalezy oczyscic dysze. Potw. guzikiem."
 
 #MSG_SELFTEST_PLEASECHECK c=0 r=0
 "Please check :"
-"Skontroluj :"
+"Sprawdz :"
 
 #MSG_WIZARD_CALIBRATION_FAILED c=20 r=8
 "Please check our handbook and fix the problem. Then resume the Wizard by rebooting the printer."
-"Prosze sprawdz nasz poradnik i napraw problem. Potem przywroc Wizard restartujac drukarke."
+"Przeczytaj nasz Podrecznik druku 3D aby naprawic problem. Potem wznow Asystenta przez restart drukarki."
 
 #MSG_WIZARD_LOAD_FILAMENT c=20 r=8
 "Please insert PLA filament to the extruder, then press knob to load it."
-"Prosze umiesc filament PLA w ekstruderze i nacisnij przycisk by zaladowac."
+"Umiesc filament PLA w ekstruderze i nacisnij pokretlo, aby zaladowac."
 
 #MSG_WIZARD_INSERT_CORRECT_FILAMENT c=20 r=8
 "Please load PLA filament and then resume Wizard by rebooting the printer."
-"Prosze zaladuj filament PLA i przywroc Wizard przez restart drukarki."
+"Zaladuj filament PLA i przywroc Asystenta przez restart drukarki."
 
 #MSG_PLEASE_LOAD_PLA c=20 r=4
 "Please load PLA filament first."
-"Prosze, najpierw zaladuj filament PLA."
+"Najpierw zaladuj filament PLA."
 
 #MSG_CHECK_IDLER c=20 r=4
 "Please open idler and remove filament manually."
-"\x00"
+"Prosze odciagnac dzwignie dociskowa ekstrudera i recznie usunac filament."
 
 #MSG_PLACE_STEEL_SHEET c=20 r=4
 "Please place steel sheet on heatbed."
-"\x00"
+"Prosze umiescic plyte stalowa na stole podgrzewanym."
 
 #MSG_PRESS_TO_UNLOAD c=20 r=4
 "Please press the knob to unload filament"
-"\x00"
+"Nacisnij pokretlo aby rozladowac filament"
 
 #MSG_PULL_OUT_FILAMENT c=20 r=4
 "Please pull out filament immediately"
-"\x00"
+"Wyciagnij filament teraz"
 
 #MSG_REMOVE_STEEL_SHEET c=20 r=4
 "Please remove steel sheet from heatbed."
-"\x00"
+"Prosze zdjac plyte stalowa z podgrzewanego stolu."
 
 #MSG_PLEASE_WAIT c=20 r=0
 "Please wait"
@@ -760,7 +760,7 @@
 
 #MSG_POWERUP c=0 r=0
 "PowerUp"
-"\x00"
+"Uruchamianie"
 
 #MSG_PREHEAT_NOZZLE c=20 r=0
 "Preheat the nozzle!"
@@ -776,7 +776,7 @@
 
 #MSG_PRESS_TO_PREHEAT c=20 r=4
 "Press knob to preheat nozzle and continue."
-"\x00"
+"Wcisnij pokretlo aby rozgrzac dysze i kontynuowac."
 
 #MSG_PRINT_ABORTED c=20 r=0
 "Print aborted"
@@ -784,27 +784,27 @@
 
 #MSG_SELFTEST_PRINT_FAN_SPEED c=18 r=0
 "Print fan:"
-"\x00"
+"Went. wydruku:"
 
 #MSG_CARD_MENU c=0 r=0
 "Print from SD"
-"Druk z SD"
+"Druk z karty SD"
 
 #MSG_PRINT_PAUSED c=20 r=1
 "Print paused"
-"Druk zatrzymany"
+"Druk wstrzymany"
 
 #MSG_ERR_KILLED c=0 r=0
 "Printer halted. kill() called!"
-"\x00"
+"Drukarka zatrzymana. Wywolano komende kill()!"
 
 #MSG_FOLLOW_CALIBRATION_FLOW c=20 r=8
 "Printer has not been calibrated yet. Please follow the manual, chapter First steps, section Calibration flow."
-"Drukarka nie zostala jeszcze skalibrowana. Prosze kierowac sie instrukcja, rozdzial Zaczynamy, podrozdzial Selftest."
+"Drukarka nie zostala jeszcze skalibrowana. Kieruj sie Samouczkiem: rozdzial Pierwsze Kroki, sekcja Konfiguracja przed drukowaniem."
 
 #MSG_ERR_STOPPED c=0 r=0
 "Printer stopped due to errors. Fix the error and use M999 to restart. (Temperature is reset. Set it after restarting)"
-"\x00"
+"Drukarka zatrzymana z powodu bledow. Usun problem i uzyj M999 aby zrestartowac. (Temperatura jest zresetowana, ustaw ja po restarcie)"
 
 #WELCOME_MSG c=20 r=0
 "Prusa i3 MK3 ready."
@@ -812,19 +812,19 @@
 
 #MSG_PRUSA3D c=0 r=0
 "prusa3d.com"
-"prusa3d.cz"
+"\x00"
 
 #MSG_BED_CORRECTION_REAR c=14 r=1
 "Rear side [um]"
-"Do tylu [um]"
+"Tyl [um]"
 
 #MSG_RECOVERING_PRINT c=20 r=1
 "Recovering print    "
-"\x00"
+"Wznawianie wydruku"
 
 #MSG_M119_REPORT c=0 r=0
 "Reporting endstop status"
-"\x00"
+"Raportowanie statusu krancowek"
 
 #MSG_CALIBRATE_BED_RESET c=0 r=0
 "Reset XYZ calibr."
@@ -836,43 +836,43 @@
 
 #MSG_RESUME_PRINT c=0 r=0
 "Resume print"
-"Kontynuowac"
+"Wznowic wydruk"
 
 #MSG_RESUMING_PRINT c=20 r=1
 "Resuming print"
-"Wznowienie druku"
+"Wznawianie druku"
 
 #MSG_BED_CORRECTION_RIGHT c=14 r=1
 "Right side[um]"
-"W prawo [um]"
+"Prawo [um]"
 
 #MSG_SECOND_SERIAL_ON c=17 r=1
 "RPi port     [on]"
-"\x00"
+"Port RPi [wl]"
 
 #MSG_SECOND_SERIAL_OFF c=17 r=1
 "RPi port    [off]"
-"\x00"
+"Port RPi [wyl]"
 
 #MSG_WIZARD_RERUN c=20 r=7
 "Running Wizard will delete current calibration results and start from the beginning. Continue?"
-"Wlaczenie Wizard usunie obecne dane kalibracyjne i zacznie od nowa. Kontynuowac?"
+"Wlaczenie Asystenta usunie obecne dane kalibracyjne i zacznie od poczatku. Kontynuowac?"
 
 #MSG_TOSHIBA_FLASH_AIR_COMPATIBILITY_OFF c=19 r=1
 "SD card  [normal]"
-"karta SD [normal]"
+"Karta SD [normalna]"
 
 #MSG_TOSHIBA_FLASH_AIR_COMPATIBILITY_ON c=19 r=1
 "SD card [FlshAir]"
-"karta SD[FlshAir]"
+"Karta SD [FlashAir]"
 
 #MSG_SD_CARD_OK c=0 r=0
 "SD card ok"
-"\x00"
+"Karta SD OK"
 
 #MSG_SD_INIT_FAIL c=0 r=0
 "SD init fail"
-"\x00"
+"Inicjalizacja karty SD nieudana"
 
 #MSG_SD_PRINTING_BYTE c=0 r=0
 "SD printing byte "
@@ -880,7 +880,7 @@
 
 #MSG_FIND_BED_OFFSET_AND_SKEW_LINE1 c=60 r=0
 "Searching bed calibration point"
-"Szukam punktu kalibracyjnego podkladki"
+"Szukam punktu kalibracyjnego na stole"
 
 #MSG_LANGUAGE_SELECT c=0 r=0
 "Select language"
@@ -888,11 +888,11 @@
 
 #MSG_SELFTEST_OK c=0 r=0
 "Self test OK"
-"\x00"
+"Selftest OK"
 
 #MSG_SELFTEST_START c=20 r=0
 "Self test start  "
-"Self test start "
+"Rozpoczynanie Selftestu"
 
 #MSG_SELFTEST c=0 r=0
 "Selftest         "
@@ -900,7 +900,7 @@
 
 #MSG_SELFTEST_ERROR c=0 r=0
 "Selftest error !"
-"\x00"
+"Blad selftest !"
 
 #MSG_SELFTEST_FAILED c=20 r=0
 "Selftest failed  "
@@ -908,11 +908,11 @@
 
 #MSG_FORCE_SELFTEST c=20 r=8
 "Selftest will be run to calibrate accurate sensorless rehoming."
-"\x00"
+"Zostanie uruchomiony Selftest aby dokladnie skalibrowac punkt bazowy bez krancowek"
 
 #MSG_SET_TEMPERATURE c=19 r=1
 "Set temperature:"
-"Ustawic temperature"
+"Ustaw. temperatury:"
 
 #MSG_SETTINGS c=0 r=0
 "Settings"
@@ -924,27 +924,27 @@
 
 #MSG_DWELL c=0 r=0
 "Sleep..."
-"\x00"
+"Czuwanie..."
 
 #MSG_FILE_CNT c=20 r=4
 "Some files will not be sorted. Max. No. of files in 1 folder for sorting is 100."
-"\x00"
+"Niektore pliki nie zostana posortowane. Max. liczba plikow w 1 folderze = 100."
 
 #MSG_SORT_NONE c=17 r=1
 "Sort:      [None]"
-"\x00"
+"Sortowanie:[brak]"
 
 #MSG_SORT_TIME c=17 r=1
 "Sort:      [Time]"
-"\x00"
+"Sortowanie:[czas]"
 
 #MSG_SORT_ALPHA c=17 r=1
 "Sort:  [Alphabet]"
-"\x00"
+"Sort.:[alfabet]"
 
 #MSG_SORTING c=20 r=1
 "Sorting files"
-"\x00"
+"Sortowanie plikow"
 
 #MSG_SPEED c=0 r=0
 "Speed"
@@ -956,15 +956,15 @@
 
 #MSG_TEMP_CAL_WARNING c=20 r=4
 "Stable ambient temperature 21-26C is needed a rigid stand is required."
-"\x00"
+"Potrzebna jest stabilna temperatura otoczenia 21-26C i stabilne podloze."
 
 #MSG_STATISTICS c=0 r=0
 "Statistics  "
-"Statystyka "
+"Statystyki"
 
 #MSG_STEPPER_TOO_HIGH c=0 r=0
 "Steprate too high: "
-"\x00"
+"Liczba krokow zbyt wysoka:"
 
 #MSG_STOP_PRINT c=0 r=0
 "Stop print"
@@ -972,39 +972,39 @@
 
 #MSG_STOPPED c=0 r=0
 "STOPPED. "
-"\x00"
+"ZATRZYMANO."
 
 #MSG_SUPPORT c=0 r=0
 "Support"
-"Pomoc"
+"Wsparcie"
 
 #MSG_SELFTEST_SWAPPED c=0 r=0
 "Swapped"
-"\x00"
+"Zamieniono"
 
 #MSG_TEMP_CALIBRATION c=20 r=1
 "Temp. cal.          "
-"Ciepl. kal. "
+"Kalibracja temp."
 
 #MSG_TEMP_CALIBRATION_ON c=20 r=1
 "Temp. cal.   [on]"
-"Ciepl. kal. [ON]"
+"Kalibr. temp. [wl]"
 
 #MSG_TEMP_CALIBRATION_OFF c=20 r=1
 "Temp. cal.  [off]"
-"Ciepl. kal. [OFF]"
+"Kalibr. temp. [wyl]"
 
 #MSG_CALIBRATION_PINDA_MENU c=17 r=1
 "Temp. calibration"
-"Cieplna kalibr."
+"Kalibracja temp."
 
 #MSG_TEMP_CAL_FAILED c=20 r=8
 "Temperature calibration failed"
-"\x00"
+"Kalibracja temperaturowa nieudana"
 
 #MSG_TEMP_CALIBRATION_DONE c=20 r=12
 "Temperature calibration is finished and active. Temp. calibration can be disabled in menu Settings->Temp. cal."
-"Cieplna kalibracja zakonczona. Kontynuuj przyciskiem"
+"Kalibracja temperaturowa zakonczona i wlaczona. Moze byc wylaczona z menu Ustawienia -> Kalibracja temp."
 
 #MSG_TEMPERATURE c=0 r=0
 "Temperature"
@@ -1012,63 +1012,63 @@
 
 #MSG_MENU_TEMPERATURES c=15 r=1
 "Temperatures"
-"\x00"
+"Temperatury"
 
 #MSG_ENDSTOP_HIT c=0 r=0
 "TRIGGERED"
-"\x00"
+"AKTYWOWANO"
 
 #MSG_TUNE c=0 r=0
 "Tune"
-"Nastroic"
+"Strojenie"
 
 #MSG_UNLOAD_FILAMENT c=17 r=0
 "Unload filament"
-"Wyjac filament"
+"Wyladowanie filamentu"
 
 #MSG_UNLOADING_FILAMENT c=20 r=1
 "Unloading filament"
-"Wysuwam filament"
+"Rozladowuje filament"
 
 #MSG_USED c=19 r=1
 "Used during print"
-"Uzyte przy druku"
+"Uzyte podczas druku"
 
 #MSG_MENU_VOLTAGES c=15 r=1
 "Voltages"
-"\x00"
+"Napiecia"
 
 #MSG_SD_VOL_INIT_FAIL c=0 r=0
 "volume.init failed"
-"\x00"
+"niepowodzenie volume.init "
 
 #MSG_USERWAIT c=0 r=0
 "Wait for user..."
-"\x00"
+"Czekam na uzytkownika..."
 
 #MSG_WAITING_TEMP c=20 r=3
 "Waiting for nozzle and bed cooling"
-"Oczekiwanie na wychlodzenie dyszy i podkladki."
+"Oczekiwanie na wychlodzenie dyszy i stolu"
 
 #MSG_WAITING_TEMP_PINDA c=20 r=3
 "Waiting for PINDA probe cooling"
-"\x00"
+"Czekam az spadnie temp. sondy PINDA"
 
 #MSG_CHANGED_BOTH c=20 r=4
 "Warning: both printer type and motherboard type changed."
-"\x00"
+"Ostrzezenie: typ drukarki i plyta glowna ulegly zmianie."
 
 #MSG_CHANGED_MOTHERBOARD c=20 r=4
 "Warning: motherboard type changed."
-"\x00"
+"Ostrzezenie: plyta glowna ulegla zmianie."
 
 #MSG_CHANGED_PRINTER c=20 r=4
 "Warning: printer type changed."
-"\x00"
+"Ostrzezenie: rodzaj drukarki ulegl zmianie"
 
 #MSG_UNLOAD_SUCCESSFUL c=20 r=2
 "Was filament unload successful?"
-"\x00"
+"Wyladowanie fil. ok?"
 
 #MSG_SELFTEST_WIRINGERROR c=0 r=0
 "Wiring error"
@@ -1076,23 +1076,23 @@
 
 #MSG_WIZARD c=17 r=1
 "Wizard"
-"\x00"
+"Asystent"
 
 #MSG_SD_WORKDIR_FAIL c=0 r=0
 "workDir open failed"
-"\x00"
+"blad otwierania workDir"
 
 #MSG_SD_WRITE_TO_FILE c=0 r=0
 "Writing to file: "
-"\x00"
+"Zapis do pliku:"
 
 #MSG_XYZ_DETAILS c=19 r=1
 "XYZ cal. details"
-"Szczegoly kal.XYZ"
+"Szczegoly kal. XYZ"
 
 #MSG_BED_SKEW_OFFSET_DETECTION_FITTING_FAILED c=20 r=8
 "XYZ calibration failed. Please consult the manual."
-"Kalibracja XYZ niepowiedziona. Sprawdzic w instrukcji."
+"Kalibracja XYZ nieudana. Sprawdz przyczyny i rozwiazania w instrukcji."
 
 #MSG_YES c=0 r=0
 "Yes"
@@ -1100,5 +1100,5 @@
 
 #MSG_WIZARD_QUIT c=20 r=8
 "You can always resume the Wizard from Calibration -> Wizard."
-"Zawsze mozesz przywrocic Wizard przez Kalibracja -> Wizard."
+"Zawsze mozesz uruchomic Asystenta ponownie przez Kalibracja -> Asystent."
 

+ 53 - 42
lang/make_lang.sh

@@ -5,18 +5,18 @@
 #
 # Input files:
 #  lang_en.txt
-#  lang_en_$LANG.txt
+#  lang_en_xx.txt
 #
 # Output files:
 #  lang_en.tmp (temporary, will be removed when finished)
-#  lang_en_$LANG.tmp ==||==
-#  lang_en_$LANG.dif ==||==
-#  lang_$LANG.txt
+#  lang_en_xx.tmp ==||==
+#  lang_en_xx.dif ==||==
+#  lang_xx.txt
 #
 #
 # Selected language:
-LANG=$1
-if [ -z "$LANG" ]; then LANG='cz'; fi
+LNG=$1
+if [ -z "$LNG" ]; then LNG='cz'; fi
 #
 #
 
@@ -24,8 +24,8 @@ finish()
 {
  if [ $1 -eq 0 ]; then
   if [ -e lang_en.tmp ]; then rm lang_en.tmp; fi
-  if [ -e lang_en_$LANG.tmp ]; then rm lang_en_$LANG.tmp; fi
-  if [ -e lang_en_$LANG.dif ]; then rm lang_en_$LANG.dif; fi
+  if [ -e lang_en_$LNG.tmp ]; then rm lang_en_$LNG.tmp; fi
+  if [ -e lang_en_$LNG.dif ]; then rm lang_en_$LNG.dif; fi
  fi
 # echo >&2
  if [ $1 -eq 0 ]; then
@@ -38,59 +38,59 @@ finish()
 
 make_lang()
 {
-LANG=$1
+LNG=$1
 
 echo "make_lang.sh started" >&2
-echo "selected language=$LANG" >&2
+echo "selected language=$LNG" >&2
 
 #check if input files exists
 echo -n " checking input files..." >&2
 if [ ! -e lang_en.txt ]; then echo "NG!  file lang_en.txt not found!" >&2; exit 1; fi
-if [ ! -e lang_en_$LANG.txt ]; then echo "NG!  file lang_en_$LANG.txt not found!" >&2; exit 1; fi
+if [ ! -e lang_en_$LNG.txt ]; then echo "NG!  file lang_en_$LNG.txt not found!" >&2; exit 1; fi
 echo "OK" >&2
 
 #filter comment and empty lines from key and dictionary files, create temporary files
 echo -n " creating tmp files..." >&2
 cat lang_en.txt | sed "/^$/d;/^#/d" > lang_en.tmp
-cat lang_en_$LANG.txt | sed "/^$/d;/^#/d" > lang_en_$LANG.tmp
+cat lang_en_$LNG.txt | sed "/^$/d;/^#/d" > lang_en_$LNG.tmp
 echo "OK" >&2
-#cat lang_en_$LANG.tmp | sed 'n;d' >test1.txt
+#cat lang_en_$LNG.tmp | sed 'n;d' >test1.txt
 
 #compare files using diff and check for differences
 echo -n " comparing tmp files..." >&2
-if ! cat lang_en_$LANG.tmp | sed 'n;d' | diff lang_en.tmp - > lang_en_$LANG.dif; then
+if ! cat lang_en_$LNG.tmp | sed 'n;d' | diff lang_en.tmp - > lang_en_$LNG.dif; then
  echo "NG!" >&2
- echo "Entries in lang_en_$LANG.txt are different from lang_en.txt!" >&2
- echo "please check lang_en_$LANG.dif" >&2
+ echo "Entries in lang_en_$LNG.txt are different from lang_en.txt!" >&2
+ echo "please check lang_en_$LNG.dif" >&2
  finish 1
 fi
 echo "OK" >&2
 
 #generate lang_xx.txt (secondary language text data sorted by ids)
-echo -n " generating lang_$LANG.txt..." >&2
-cat lang_en_$LANG.tmp | sed '1~2d' | sed "s/^\"\\\\x00/\"/" > lang_$LANG.txt
+echo -n " generating lang_$LNG.txt..." >&2
+cat lang_en_$LNG.tmp | sed '1~2d' | sed "s/^\"\\\\x00/\"/" > lang_$LNG.txt
 echo "OK" >&2
 
 #generate lang_xx.dat (secondary language text data in binary form)
-echo -n " generating lang_$LANG.dat..." >&2
-cat lang_$LANG.txt | sed "s/\\\\/\\\\\\\\/g" | while read s; do
+echo -n " generating lang_$LNG.dat..." >&2
+cat lang_$LNG.txt | sed "s/\\\\/\\\\\\\\/g" | while read s; do
  s=${s#\"}
  s=${s%\"}
  /bin/echo -e -n "$s\x00"
-done >lang_$LANG.dat
+done >lang_$LNG.dat
 echo "OK" >&2
 
 #calculate variables
 lt_magic='\xa5\x5a\xb4\x4b'
-lt_count=$(grep -c '^' lang_$LANG.txt)
-lt_data_size=$(wc -c lang_$LANG.dat | cut -f1 -d' ')
+lt_count=$(grep -c '^' lang_$LNG.txt)
+lt_data_size=$(wc -c lang_$LNG.dat | cut -f1 -d' ')
 lt_offs_size=$((2 * $lt_count))
 lt_size=$((16 + $lt_offs_size + $lt_data_size))
-lt_chsum=1
+lt_chsum=0
 lt_code='\xff\xff'
 lt_resv1='\xff\xff\xff\xff'
 
-case "$LANG" in
+case "$LNG" in
  *en*) lt_code='\x6e\x65' ;;
  *cz*) lt_code='\x73\x63' ;;
  *de*) lt_code='\x65\x64' ;;
@@ -100,15 +100,15 @@ case "$LANG" in
 esac
 
 #generate lang_xx.ofs (secondary language text data offset table)
-echo -n " generating lang_$LANG.ofs..." >&2
-cat lang_$LANG.txt | sed "s/\\\\x[0-9a-f][0-9a-f]/\./g;s/\\\\[0-7][0-7][0-7]/\./g" |\
- awk 'BEGIN { o='$((16 + $lt_offs_size))';} { printf("%d\n",o); o+=(length($0)-1); }' > lang_$LANG.ofs
+echo -n " generating lang_$LNG.ofs..." >&2
+cat lang_$LNG.txt | sed "s/\\\\x[0-9a-f][0-9a-f]/\./g;s/\\\\[0-7][0-7][0-7]/\./g" |\
+ awk 'BEGIN { o='$((16 + $lt_offs_size))';} { printf("%d\n",o); o+=(length($0)-1); }' > lang_$LNG.ofs
 echo "OK" >&2
 
 #generate lang_xx.bin (secondary language result binary file)
-echo " generating lang_$LANG.bin:" >&2
+echo " generating lang_$LNG.bin:" >&2
 #create empty file
-dd if=/dev/zero of=lang_$LANG.bin bs=1 count=$lt_size 2>/dev/null
+dd if=/dev/zero of=lang_$LNG.bin bs=1 count=$lt_size 2>/dev/null
 #awk code to format ui16 variables for dd
 awk_ui16='{ h=int($1/256); printf("\\x%02x\\x%02x\n", int($1-256*h), h); }'
 
@@ -116,37 +116,48 @@ awk_ui16='{ h=int($1/256); printf("\\x%02x\\x%02x\n", int($1-256*h), h); }'
 
 echo -n "  writing header (16 bytes)..." >&2
 /bin/echo -n -e "$lt_magic" |\
- dd of=lang_$LANG.bin bs=1 count=4 seek=0 conv=notrunc 2>/dev/null
+ dd of=lang_$LNG.bin bs=1 count=4 seek=0 conv=notrunc 2>/dev/null
 /bin/echo -n -e $(echo -n "$lt_size" | awk "$awk_ui16") |\
- dd of=lang_$LANG.bin bs=1 count=2 seek=4 conv=notrunc 2>/dev/null
+ dd of=lang_$LNG.bin bs=1 count=2 seek=4 conv=notrunc 2>/dev/null
 /bin/echo -n -e $(echo -n "$lt_count" | awk "$awk_ui16") |\
- dd of=lang_$LANG.bin bs=1 count=2 seek=6 conv=notrunc 2>/dev/null
+ dd of=lang_$LNG.bin bs=1 count=2 seek=6 conv=notrunc 2>/dev/null
 /bin/echo -n -e $(echo -n "$lt_chsum" | awk "$awk_ui16") |\
- dd of=lang_$LANG.bin bs=1 count=2 seek=8 conv=notrunc 2>/dev/null
+ dd of=lang_$LNG.bin bs=1 count=2 seek=8 conv=notrunc 2>/dev/null
 /bin/echo -n -e "$lt_code" |\
- dd of=lang_$LANG.bin bs=1 count=2 seek=10 conv=notrunc 2>/dev/null
+ dd of=lang_$LNG.bin bs=1 count=2 seek=10 conv=notrunc 2>/dev/null
 /bin/echo -n -e "$lt_resv1" |\
- dd of=lang_$LANG.bin bs=1 count=4 seek=12 conv=notrunc 2>/dev/null
+ dd of=lang_$LNG.bin bs=1 count=4 seek=12 conv=notrunc 2>/dev/null
 echo "OK" >&2
 
 echo -n "  writing offset table ($lt_offs_size bytes)..." >&2
-/bin/echo -n -e $(cat lang_$LANG.ofs | awk "$awk_ui16" | tr -d '\n'; echo) |\
- dd of=./lang_$LANG.bin bs=1 count=$lt_offs_size seek=16 conv=notrunc 2>/dev/null
+/bin/echo -n -e $(cat lang_$LNG.ofs | awk "$awk_ui16" | tr -d '\n'; echo) |\
+ dd of=./lang_$LNG.bin bs=1 count=$lt_offs_size seek=16 conv=notrunc 2>/dev/null
 echo "OK" >&2
 
 echo -n "  writing text data ($lt_data_size bytes)..." >&2
-dd if=./lang_$LANG.dat of=./lang_$LANG.bin bs=1 count=$lt_data_size seek=$((16 + $lt_offs_size)) conv=notrunc 2>/dev/null
+dd if=./lang_$LNG.dat of=./lang_$LNG.bin bs=1 count=$lt_data_size seek=$((16 + $lt_offs_size)) conv=notrunc 2>/dev/null
 echo "OK" >&2
 
+#update signature
+echo -n "  updating signature..." >&2
+dd if=lang_en.bin of=lang_$LNG.bin bs=1 count=4 skip=6 seek=12 conv=notrunc 2>/dev/null
+echo "OK" >&2
+
+#calculate and update checksum
+lt_chsum=$(cat lang_$LNG.bin | xxd | cut -c11-49 | tr ' ' "\n" | sed '/^$/d' | awk 'BEGIN { sum = 0; } { sum += strtonum("0x"$1); if (sum > 0xffff) sum -= 0x10000; } END { printf("%x\n", sum); }')
+/bin/echo -n -e $(echo -n $((0x$lt_chsum)) | awk "$awk_ui16") |\
+ dd of=lang_$LNG.bin bs=1 count=2 seek=8 conv=notrunc 2>/dev/null
+
 echo " lang_table details:" >&2
 echo "  lt_count = $lt_count" >&2
 echo "  lt_size  = $lt_size" >&2
 echo "  lt_chsum = $lt_chsum" >&2
 }
 
-echo $LANG
+echo $LNG
 
-if [ "$LANG" = "all" ]; then
+if [ "$LNG" = "all" ]; then
+ ./lang-build.sh en
  make_lang cz
  make_lang de
  make_lang es
@@ -154,7 +165,7 @@ if [ "$LANG" = "all" ]; then
  make_lang pl
  exit 0
 else
- make_lang $LANG
+ make_lang $LNG
 fi
 
 finish 0

+ 29 - 29
lang/po/make_po.sh

@@ -5,11 +5,11 @@
 #
 SRCDIR="../../Firmware"
 #
-LANG=$1
-if [ -z "$LANG" ]; then LANG=cz; fi
+LNG=$1
+if [ -z "$LNG" ]; then LNG=cz; fi
 #
 
-if [ "$LANG" == "all" ]; then
+if [ "$LNG" == "all" ]; then
  ./make_po.sh cz
  ./make_po.sh de
  ./make_po.sh es
@@ -19,13 +19,13 @@ if [ "$LANG" == "all" ]; then
 fi
 
 echo "make_po.sh started" >&2
-echo " selected language=$LANG" >&2
+echo " selected language=$LNG" >&2
 
 #remove output file if exists
-if [ -e lang_$LANG.po ]; then rm lang_$LANG.po; fi
+if [ -e lang_$LNG.po ]; then rm lang_$LNG.po; fi
 
 lang_name=$(\
- case "$LANG" in
+ case "$LNG" in
   *en*) echo "English" ;;
   *cz*) echo "Czech" ;;
   *de*) echo "German" ;;
@@ -35,7 +35,7 @@ lang_name=$(\
  esac)
 
 lang_short=$(\
- case "$LANG" in
+ case "$LNG" in
   *en*) echo "en" ;;
   *cz*) echo "cs" ;;
   *de*) echo "de" ;;
@@ -47,29 +47,29 @@ lang_short=$(\
 po_date=$(date)
 
 #write po header
-echo "# Translation of Prusa-Firmware into $lang_name." > lang_$LANG.po
-echo "#" >> lang_$LANG.po
-echo 'msgid ""' >> lang_$LANG.po
-echo 'msgstr ""' >> lang_$LANG.po
-echo '"MIME-Version: 1.0\n"' >> lang_$LANG.po
-echo '"Content-Type: text/plain; charset=UTF-8\n"' >> lang_$LANG.po
-echo '"Content-Transfer-Encoding: 8bit\n"' >> lang_$LANG.po
-echo '"Language: '$lang_short'\n"' >> lang_$LANG.po
-echo '"Project-Id-Version: Prusa-Firmware\n"' >> lang_$LANG.po
-echo '"POT-Creation-Date: '$po_date'\n"' >> lang_$LANG.po
-echo '"PO-Revision-Date: '$po_date'\n"' >> lang_$LANG.po
-echo '"Language-Team: \n"' >> lang_$LANG.po
-echo '"X-Generator: Poedit 2.0.7\n"' >> lang_$LANG.po
-echo '"X-Poedit-SourceCharset: UTF-8\n"' >> lang_$LANG.po
-echo '"Last-Translator: \n"' >> lang_$LANG.po
-echo '"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"' >> lang_$LANG.po
-echo >> lang_$LANG.po
+echo "# Translation of Prusa-Firmware into $lang_name." > lang_$LNG.po
+echo "#" >> lang_$LNG.po
+echo 'msgid ""' >> lang_$LNG.po
+echo 'msgstr ""' >> lang_$LNG.po
+echo '"MIME-Version: 1.0\n"' >> lang_$LNG.po
+echo '"Content-Type: text/plain; charset=UTF-8\n"' >> lang_$LNG.po
+echo '"Content-Transfer-Encoding: 8bit\n"' >> lang_$LNG.po
+echo '"Language: '$lang_short'\n"' >> lang_$LNG.po
+echo '"Project-Id-Version: Prusa-Firmware\n"' >> lang_$LNG.po
+echo '"POT-Creation-Date: '$po_date'\n"' >> lang_$LNG.po
+echo '"PO-Revision-Date: '$po_date'\n"' >> lang_$LNG.po
+echo '"Language-Team: \n"' >> lang_$LNG.po
+echo '"X-Generator: Poedit 2.0.7\n"' >> lang_$LNG.po
+echo '"X-Poedit-SourceCharset: UTF-8\n"' >> lang_$LNG.po
+echo '"Last-Translator: \n"' >> lang_$LNG.po
+echo '"Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"' >> lang_$LNG.po
+echo >> lang_$LNG.po
 
 #list .cpp, .c and .h files
 files=$(ls "$SRCDIR"/*.cpp "$SRCDIR"/*.c "$SRCDIR"/*.h)
 
-num_texts=$(grep '^#' -c ../lang_en_$LANG.txt)
-num_texts_nt=$(grep '^\"\\x00\"' -c ../lang_en_$LANG.txt)
+num_texts=$(grep '^#' -c ../lang_en_$LNG.txt)
+num_texts_nt=$(grep '^\"\\x00\"' -c ../lang_en_$LNG.txt)
 echo " $num_texts texts, $num_texts_nt not translated" >&2
 
 #loop over all messages
@@ -77,7 +77,7 @@ s0=''
 s1=''
 s2=''
 num=1
-cat ../lang_en_$LANG.txt | sed "s/\\\\/\\\\\\\\/g" | while read -r s; do
+cat ../lang_en_$LNG.txt | sed "s/\\\\/\\\\\\\\/g" | while read -r s; do
  if [ "$s" == "" ]; then
   echo "  processing $num of $num_texts" >&2
   if [ "$s0" == "\"\\\\x00\"" ]; then
@@ -103,11 +103,11 @@ cat ../lang_en_$LANG.txt | sed "s/\\\\/\\\\\\\\/g" | while read -r s; do
  s2=$s1
  s1=$s0
  s0=$s
-done >> lang_$LANG.po
+done >> lang_$LNG.po
 
 #replace LF with CRLF
 sync
-sed -i 's/$/\r/' lang_$LANG.po
+sed -i 's/$/\r/' lang_$LNG.po
 
 echo "make_po.sh finished" >&2
 #read

+ 6 - 6
lang/po_new/merge_lang.sh

@@ -2,14 +2,14 @@
 #
 #
 
-LANG=$1
-if [ -z "$LANG" ]; then exit -1; fi
+LNG=$1
+if [ -z "$LNG" ]; then exit -1; fi
 
 #convert '\\e' sequencies to 'x1b' and '\\' to '\'
-cat $LANG.po | sed 's/\\\\e/\\x1b/g;s/\\\\/\\/g' > $LANG'_filtered.po'
+cat $LNG.po | sed 's/\\\\e/\\x1b/g;s/\\\\/\\/g' > $LNG'_filtered.po'
 
 #join lines with multi-line string constants
-cat $LANG'_filtered.po' | sed ':a;N;$!ba;s/\x22\n\x22//g' > $LANG'_new.po'
+cat $LNG'_filtered.po' | sed ':a;N;$!ba;s/\x22\n\x22//g' > $LNG'_new.po'
 
 #generate dictionary
 cat ../lang_en.txt | sed 's/\\/\\\\/g' | while read -r s; do
@@ -17,7 +17,7 @@ cat ../lang_en.txt | sed 's/\\/\\\\/g' | while read -r s; do
  if [ "${s:0:1}" = "\"" ]; then
 #  /bin/echo -e "$s"
   s=$(/bin/echo -e "$s")
-  s2=$(grep -F -A1 -B0  "$s" "$LANG"_new.po | tail -n1 | sed 's/^msgstr //')
+  s2=$(grep -F -A1 -B0  "$s" "$LNG"_new.po | tail -n1 | sed 's/^msgstr //')
   if [ -z "$s2" ]; then
    echo '"\x00"'
   else
@@ -25,4 +25,4 @@ cat ../lang_en.txt | sed 's/\\/\\\\/g' | while read -r s; do
   fi
 #  echo
  fi
-done > lang_en_$LANG.txt
+done > lang_en_$LNG.txt

+ 45 - 9
lang/postbuild.sh

@@ -23,8 +23,8 @@ if [ -z "$CONFIG_OK" ]; then eval "$(cat config.sh)"; fi
 if [ -z "$CONFIG_OK" ] | [ $CONFIG_OK -eq 0 ]; then echo 'Config NG!' >&2; exit 1; fi
 #
 # Selected language:
-LANG=$1
-#if [ -z "$LANG" ]; then LANG='cz'; fi
+LNG=$1
+#if [ -z "$LNG" ]; then LNG='cz'; fi
 #
 # Params:
 IGNORE_MISSING_TEXT=1
@@ -80,7 +80,7 @@ else
  echo "OK" >&2
 fi
 
-#update progmem1 id entries in binary file
+#extract binary file
 echo -n " extracting binary..." >&2
 $OBJCOPY -I ihex -O binary $INOHEX ./firmware.bin
 echo "OK" >&2
@@ -97,10 +97,35 @@ cat textaddr.txt | grep "^ADDR OK" | cut -f3- -d' ' | sed "s/^0000/0x/" |\
  done
 echo "OK" >&2
 
+#update primary language signature in binary file
+echo -n "  primary language signature..." >&2
+if [ -e lang_en.bin ]; then
+ #find symbol _PRI_LANG_SIGNATURE in section '.text'
+ pri_lang=$(cat text.sym | grep -E "\b_PRI_LANG_SIGNATURE\b")
+ if [ -z "$pri_lang" ]; then echo "NG!\n  symbol _PRI_LANG_SIGNATURE not found!" >&2; finish 1; fi
+ #get pri_lang address
+ pri_lang_addr='0x'$(echo $pri_lang | cut -f1 -d' ')
+ #read header from primary language binary file
+ header=$(dd if=lang_en.bin bs=1 count=16 2>/dev/null | xxd | cut -c11-49 | sed 's/\([0-9a-f][0-9a-f]\)[\ ]*/\1 /g')
+ #read checksum and count data as 4 byte signature
+ chscnt=$(echo $header | cut -c18-29 | sed "s/ /\\\\x/g")
+ /bin/echo -e -n "$chscnt" |\
+  dd of=firmware.bin bs=1 count=4 seek=$(($pri_lang_addr)) conv=notrunc 2>/dev/null
+ echo "OK" >&2
+else
+ echo "NG! - file lang_en.bin not found!" >&2;
+ finish 1
+fi
+
+#convert bin to hex
+echo -n " converting to hex..." >&2
+$OBJCOPY -I binary -O ihex ./firmware.bin ./firmware.hex
+echo "OK" >&2
+
 #update _SEC_LANG in binary file if language is selected
 echo -n "  secondary language data..." >&2
-if [ ! -z "$LANG" ]; then
- ./update_lang.sh $LANG 2>./update_lang.out
+if [ ! -z "$LNG" ]; then
+ ./update_lang.sh $LNG 2>./update_lang.out
  if [ $? -ne 0 ]; then echo "NG! - check update_lang.out file" >&2; finish 1; fi
  echo "OK" >&2
  finish 0
@@ -134,9 +159,20 @@ else
 # echo "skipped" >&2
 fi
 
-#convert bin to hex
-#echo -n " converting to hex..." >&2
-#$OBJCOPY -I binary -O ihex ./firmware.bin ./firmware.hex
-#echo "OK" >&2
+#create binary file with all languages
+rm -f lang.bin
+if [ -e lang_cz.bin ]; then cat lang_cz.bin >> lang.bin; fi
+if [ -e lang_de.bin ]; then cat lang_de.bin >> lang.bin; fi
+if [ -e lang_es.bin ]; then cat lang_es.bin >> lang.bin; fi
+if [ -e lang_it.bin ]; then cat lang_it.bin >> lang.bin; fi
+if [ -e lang_pl.bin ]; then cat lang_pl.bin >> lang.bin; fi
+
+#convert lang.bin to lang.hex
+echo -n " converting to hex..." >&2
+$OBJCOPY -I binary -O ihex ./lang.bin ./lang.hex
+echo "OK" >&2
+
+#append languages to hex file
+cat ./lang.hex >> firmware.hex
 
 finish 0

+ 14 - 7
lang/update_lang.sh

@@ -9,8 +9,8 @@ if [ -z "$OBJCOPY" ]; then echo 'variable OBJCOPY not set!' >&2; exit 1; fi
 if [ -z "$CONFIG_OK" ] | [ $CONFIG_OK -eq 0 ]; then echo 'Config NG!' >&2; exit 1; fi
 #
 # Selected language:
-LANG=$1
-if [ -z "$LANG" ]; then LANG='cz'; fi
+LNG=$1
+if [ -z "$LNG" ]; then LNG='cz'; fi
 #
 
 finish()
@@ -28,11 +28,11 @@ finish()
 }
 
 echo "update_lang.sh started" >&2
-echo " selected language=$LANG" >&2
+echo " selected language=$LNG" >&2
 
 echo -n " checking files..." >&2
 if [ ! -e text.sym ]; then echo "NG!  file text.sym not found!" >&2; finish 1; fi
-if [ ! -e lang_$LANG.bin ]; then echo "NG!  file lang_$LANG.bin not found!" >&2; finish 1; fi
+if [ ! -e lang_$LNG.bin ]; then echo "NG!  file lang_$LNG.bin not found!" >&2; finish 1; fi
 if [ ! -e firmware.bin ]; then echo "NG!  file firmware.bin not found!" >&2; finish 1; fi
 echo "OK" >&2
 
@@ -40,9 +40,15 @@ echo -n " checking symbols..." >&2
 #find symbol _SEC_LANG in section '.text'
 sec_lang=$(cat text.sym | grep -E "\b_SEC_LANG\b")
 if [ -z "$sec_lang" ]; then echo "NG!\n  symbol _SEC_LANG not found!" >&2; finish 1; fi
+#find symbol _PRI_LANG_SIGNATURE in section '.text'
+pri_lang=$(cat text.sym | grep -E "\b_PRI_LANG_SIGNATURE\b")
+if [ -z "$pri_lang" ]; then echo "NG!\n  symbol _PRI_LANG_SIGNATURE not found!" >&2; finish 1; fi
 echo "OK" >&2
 
 echo " calculating vars:" >&2
+#get pri_lang addres
+pri_lang_addr='0x'$(echo $pri_lang | cut -f1 -d' ')
+echo "  pri_lang_addr   =$pri_lang_addr" >&2
 #get addres and size
 sec_lang_addr='0x'$(echo $sec_lang | cut -f1 -d' ')
 sec_lang_size='0x'$(echo $sec_lang | cut -f2 -d' ')
@@ -56,16 +62,17 @@ lang_table_size=$((256*$((($sec_lang_size - ($lang_table_addr - $sec_lang_addr))
 printf "  lang_table_size =0x%04x (=%d bytes)\n" $lang_table_size $lang_table_size >&2
 
 #get lang_xx.bin file size
-lang_file_size=$(wc -c lang_$LANG.bin | cut -f1 -d' ')
+lang_file_size=$(wc -c lang_$LNG.bin | cut -f1 -d' ')
 printf "  lang_file_size  =0x%04x (=%d bytes)\n" $lang_file_size $lang_file_size >&2
 
 if [ $lang_file_size -gt $lang_table_size ]; then echo "Lanaguage binary file size too big!" >&2; finish 1; fi
 
 echo "updating 'firmware.bin'..." >&2
-dd if=lang_$LANG.bin of=firmware.bin bs=1 seek=$lang_table_addr conv=notrunc 2>/dev/null
+
+dd if=lang_$LNG.bin of=firmware.bin bs=1 seek=$lang_table_addr conv=notrunc 2>/dev/null
 
 #convert bin to hex
 echo "converting to hex..." >&2
-$OBJCOPY -I binary -O ihex ./firmware.bin ./firmware_$LANG.hex
+$OBJCOPY -I binary -O ihex ./firmware.bin ./firmware_$LNG.hex
 
 finish 0