Bladeren bron

Merge remote-tracking branch 'upstream/MK3' into crash_movements

PavelSindler 6 jaren geleden
bovenliggende
commit
209209459d

+ 42 - 13
Firmware/Marlin_main.cpp

@@ -99,6 +99,7 @@
 
 #ifdef W25X20CL
 #include "w25x20cl.h"
+#include "optiboot_w25x20cl.h"
 #endif //W25X20CL
 
 #ifdef BLINKM
@@ -194,6 +195,7 @@
 // M84  - Disable steppers until next move,
 //        or use S<seconds> to specify an inactivity timeout, after which the steppers will be disabled.  S0 to disable the timeout.
 // M85  - Set inactivity shutdown timer with parameter S<seconds>. To disable set zero (default)
+// M86  - Set safety timer expiration time with parameter S<seconds>; M86 S0 will disable safety timer
 // M92  - Set axis_steps_per_unit - same syntax as G92
 // M104 - Set extruder target temp
 // M105 - Read current temp
@@ -492,6 +494,7 @@ const int sensitive_pins[] = SENSITIVE_PINS; // Sensitive pin list for M42
 static unsigned long previous_millis_cmd = 0;
 unsigned long max_inactive_time = 0;
 static unsigned long stepper_inactive_time = DEFAULT_STEPPER_DEACTIVE_TIME*1000l;
+static unsigned long safetytimer_inactive_time = DEFAULT_SAFETYTIMER_TIME_MINS*60*1000ul;
 
 unsigned long starttime=0;
 unsigned long stoptime=0;
@@ -1111,7 +1114,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;
@@ -1139,6 +1142,10 @@ void list_sec_lang_from_external_flash()
 // are initialized by the main() routine provided by the Arduino framework.
 void setup()
 {
+#ifdef W25X20CL
+  // Enter an STK500 compatible Optiboot boot loader waiting for flashing the languages to an external flash memory.
+  optiboot_w25x20cl_enter();
+#endif
     lcd_init();
 	fdev_setup_stream(lcdout, lcd_putchar, NULL, _FDEV_SETUP_WRITE); //setup lcdout stream
 
@@ -1184,7 +1191,7 @@ void setup()
 #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
@@ -1201,7 +1208,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(
@@ -1219,7 +1226,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");
@@ -1246,7 +1253,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
 
@@ -1259,7 +1266,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);
@@ -1267,10 +1289,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");
@@ -5435,6 +5453,15 @@ Sigma_Exit:
         max_inactive_time = code_value() * 1000;
       }
       break;
+#ifdef SAFETYTIMER
+	case 86: // M86 - set safety timer expiration time in seconds; M86 S0 will disable safety timer
+	  //when safety timer expires heatbed and nozzle target temperatures are set to zero
+	  if (code_seen('S')) {
+	    safetytimer_inactive_time = code_value() * 1000;
+		safetyTimer.start();
+	  }
+	  break;
+#endif
     case 92: // M92
       for(int8_t i=0; i < NUM_AXIS; i++)
       {
@@ -7418,18 +7445,20 @@ void handle_status_leds(void) {
 
 #ifdef SAFETYTIMER
 /**
- * @brief Turn off heating after 30 minutes of inactivity
+ * @brief Turn off heating after safetytimer_inactive_time milliseconds of inactivity
  *
  * Full screen blocking notification message is shown after heater turning off.
  * Paused print is not considered inactivity, as nozzle is cooled anyway and bed cooling would
  * damage print.
+ *
+ * If safetytimer_inactive_time is zero, feature is disabled (heating is never turned off because of inactivity)
  */
 static void handleSafetyTimer()
 {
 #if (EXTRUDERS > 1)
 #error Implemented only for one extruder.
 #endif //(EXTRUDERS > 1)
-    if ((PRINTER_ACTIVE) || (!degTargetBed() && !degTargetHotend(0)))
+    if ((PRINTER_ACTIVE) || (!degTargetBed() && !degTargetHotend(0)) || (!safetytimer_inactive_time))
     {
         safetyTimer.stop();
     }
@@ -7437,7 +7466,7 @@ static void handleSafetyTimer()
     {
         safetyTimer.start();
     }
-    else if (safetyTimer.expired(1800000ul)) //30 min
+    else if (safetyTimer.expired(safetytimer_inactive_time))
     {
         setTargetBed(0);
         setTargetHotend(0, 0);

+ 1 - 1
Firmware/config.h

@@ -29,7 +29,7 @@
 //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_SIZE_RESERVED 0x2400 // reserved space for secondary language (~10kb)
 //#define LANG_SIZE_RESERVED 0x1ef8 // reserved space for secondary language (~10kb)
 
 

+ 22 - 3
Firmware/language.c

@@ -28,6 +28,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,8 +59,12 @@ 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
@@ -70,6 +77,18 @@ 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()
 {
 #ifdef W25X20CL
@@ -98,7 +117,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

+ 4 - 1
Firmware/language.h

@@ -52,7 +52,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 +98,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

+ 310 - 0
Firmware/optiboot_w25x20cl.cpp

@@ -0,0 +1,310 @@
+// Based on the OptiBoot project
+// https://github.com/Optiboot/optiboot
+// Licence GLP 2 or later.
+
+#include "Marlin.h"
+#include "w25x20cl.h"
+#include "stk500.h"
+#include "bootapp.h"
+
+#define OPTIBOOT_MAJVER 6
+#define OPTIBOOT_CUSTOMVER 0
+#define OPTIBOOT_MINVER 2
+static unsigned const int __attribute__((section(".version"))) 
+  optiboot_version = 256*(OPTIBOOT_MAJVER + OPTIBOOT_CUSTOMVER) + OPTIBOOT_MINVER;
+
+/* Watchdog settings */
+#define WATCHDOG_OFF    (0)
+#define WATCHDOG_16MS   (_BV(WDE))
+#define WATCHDOG_32MS   (_BV(WDP0) | _BV(WDE))
+#define WATCHDOG_64MS   (_BV(WDP1) | _BV(WDE))
+#define WATCHDOG_125MS  (_BV(WDP1) | _BV(WDP0) | _BV(WDE))
+#define WATCHDOG_250MS  (_BV(WDP2) | _BV(WDE))
+#define WATCHDOG_500MS  (_BV(WDP2) | _BV(WDP0) | _BV(WDE))
+#define WATCHDOG_1S     (_BV(WDP2) | _BV(WDP1) | _BV(WDE))
+#define WATCHDOG_2S     (_BV(WDP2) | _BV(WDP1) | _BV(WDP0) | _BV(WDE))
+#define WATCHDOG_4S     (_BV(WDP3) | _BV(WDE))
+#define WATCHDOG_8S     (_BV(WDP3) | _BV(WDP0) | _BV(WDE))
+
+#if 0
+#define W25X20CL_SIGNATURE_0 9
+#define W25X20CL_SIGNATURE_1 8
+#define W25X20CL_SIGNATURE_2 7
+#else
+//FIXME this is a signature of ATmega2560!
+#define W25X20CL_SIGNATURE_0 0x1E
+#define W25X20CL_SIGNATURE_1 0x98
+#define W25X20CL_SIGNATURE_2 0x01
+#endif
+
+static void watchdogConfig(uint8_t x) {
+  WDTCSR = _BV(WDCE) | _BV(WDE);
+  WDTCSR = x;
+}
+
+static void watchdogReset() {
+  __asm__ __volatile__ (
+    "wdr\n"
+  );
+}
+
+#define RECV_READY ((UCSR0A & _BV(RXC0)) != 0)
+
+static uint8_t getch(void) {
+  uint8_t ch;
+  while(! RECV_READY) ;
+  if (!(UCSR0A & _BV(FE0))) {
+      /*
+       * A Framing Error indicates (probably) that something is talking
+       * to us at the wrong bit rate.  Assume that this is because it
+       * expects to be talking to the application, and DON'T reset the
+       * watchdog.  This should cause the bootloader to abort and run
+       * the application "soon", if it keeps happening.  (Note that we
+       * don't care that an invalid char is returned...)
+       */
+    watchdogReset();
+  }
+  ch = UDR0;
+  return ch;
+}
+
+static void putch(char ch) {
+  while (!(UCSR0A & _BV(UDRE0)));
+  UDR0 = ch;
+}
+
+static void verifySpace() {
+  if (getch() != CRC_EOP) {
+    putch(STK_FAILED);
+    watchdogConfig(WATCHDOG_16MS);    // shorten WD timeout
+    while (1)           // and busy-loop so that WD causes
+      ;             //  a reset and app start.
+  }
+  putch(STK_INSYNC);
+}
+
+static void getNch(uint8_t count) {
+  do getch(); while (--count);
+  verifySpace();
+}
+
+typedef uint16_t pagelen_t;
+
+static const char entry_magic_send   [] PROGMEM = "start\n";
+static const char entry_magic_receive[] PROGMEM = "w25x20cl_enter\n";
+static const char entry_magic_cfm    [] PROGMEM = "w25x20cl_cfm\n";
+
+struct block_t;
+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;
+  register pagelen_t length;
+  // Use the planner's queue for the receive / transmit buffers.
+//  uint8_t *buff = (uint8_t*)block_buffer;
+  uint8_t buff[260];
+  // bitmap of pages to be written. Bit is set to 1 if the page has already been erased.
+  uint8_t pages_erased = 0;
+
+  // Handshake sequence: Initialize the serial line, flush serial line, send magic, receive magic.
+  // If the magic is not received on time, or it is not received correctly, continue to the application.
+  {
+    watchdogReset();
+    unsigned long  boot_timeout = 2000000;
+    unsigned long  boot_timer = 0;
+    const char    *ptr = entry_magic_send;
+    const char    *end = strlen_P(entry_magic_send) + ptr;
+    // Initialize the serial line.
+    UCSR0A |= (1 << U2X0);
+    UBRR0L = (((float)(F_CPU))/(((float)(115200))*8.0)-1.0+0.5);
+    UCSR0B = (1 << RXEN0) | (1 << TXEN0);
+    // Flush the serial line.
+    while (RECV_READY) {
+      watchdogReset();
+      // Dummy register read (discard)
+      (void)(*(char *)UDR0);
+    }
+    // Send the initial magic string.
+    while (ptr != end)
+      putch(pgm_read_byte_far(ptr ++));
+    watchdogReset();
+    // Wait for one second until a magic string (constant entry_magic) is received
+    // from the serial line.
+    ptr = entry_magic_receive;
+    end = strlen_P(entry_magic_receive) + ptr;
+    while (ptr != end) {
+      while (! RECV_READY) {
+        watchdogReset();
+        delayMicroseconds(1);
+        if (++ boot_timer > boot_timeout)
+          // Timeout expired, continue with the application.
+          return;
+      }
+      ch = UDR0;
+      if (pgm_read_byte_far(ptr ++) != ch)
+          // Magic was not received correctly, continue with the application
+          return;
+      watchdogReset();
+    }
+    // Send the cfm magic string.
+    ptr = entry_magic_cfm;
+    while (ptr != end)
+      putch(pgm_read_byte_far(ptr ++));
+  }
+
+  spi_init();
+  w25x20cl_init();
+  watchdogConfig(WATCHDOG_OFF);
+
+  /* Forever loop: exits by causing WDT reset */
+  for (;;) {
+    /* get character from UART */
+    ch = getch();
+
+    if(ch == STK_GET_PARAMETER) {
+      unsigned char which = getch();
+      verifySpace();
+      /*
+       * Send optiboot version as "SW version"
+       * Note that the references to memory are optimized away.
+       */
+      if (which == STK_SW_MINOR) {
+        putch(optiboot_version & 0xFF);
+      } else if (which == STK_SW_MAJOR) {
+        putch(optiboot_version >> 8);
+      } else {
+        /*
+         * GET PARAMETER returns a generic 0x03 reply for
+               * other parameters - enough to keep Avrdude happy
+         */
+        putch(0x03);
+      }
+    }
+    else if(ch == STK_SET_DEVICE) {
+      // SET DEVICE is ignored
+      getNch(20);
+    }
+    else if(ch == STK_SET_DEVICE_EXT) {
+      // SET DEVICE EXT is ignored
+      getNch(5);
+    }
+    else if(ch == STK_LOAD_ADDRESS) {
+      // LOAD ADDRESS
+      uint16_t newAddress;
+      // Workaround for the infamous ';' bug in the Prusa3D usb to serial converter.
+      // Send the binary data by nibbles to avoid transmitting the ';' character.
+      newAddress  = getch();
+      newAddress |= getch();
+      newAddress |= (((uint16_t)getch()) << 8);
+      newAddress |= (((uint16_t)getch()) << 8);
+      // Transfer top bit to LSB in rampz
+      if (newAddress & 0x8000)
+        rampz |= 0x01;
+      else
+        rampz &= 0xFE;
+      newAddress += newAddress; // Convert from word address to byte address
+      address = newAddress;
+      verifySpace();
+    }
+    else if(ch == STK_UNIVERSAL) {
+      // LOAD_EXTENDED_ADDRESS is needed in STK_UNIVERSAL for addressing more than 128kB
+      if ( AVR_OP_LOAD_EXT_ADDR == getch() ) {
+        // get address
+        getch();  // get '0'
+        rampz = (rampz & 0x01) | ((getch() << 1) & 0xff);  // get address and put it in rampz
+        getNch(1); // get last '0'
+        // response
+        putch(0x00);
+      }
+      else {
+        // everything else is ignored
+        getNch(3);
+        putch(0x00);
+      }
+    }
+    /* Write memory, length is big endian and is in bytes */
+    else if(ch == STK_PROG_PAGE) {
+      // PROGRAM PAGE - we support flash programming only, not EEPROM
+      uint8_t desttype;
+      uint8_t *bufPtr;
+      pagelen_t savelength;
+      // Read the page length, with the length transferred each nibble separately to work around
+      // the Prusa's USB to serial infamous semicolon issue.
+      length  = ((pagelen_t)getch()) << 8;
+      length |= ((pagelen_t)getch()) << 8;
+      length |= getch();
+      length |= getch();
+
+      savelength = length;
+      // Read the destination type. It should always be 'F' as flash.
+      desttype = getch();
+
+      // read a page worth of contents
+      bufPtr = buff;
+      do *bufPtr++ = getch();
+      while (--length);
+
+      // Read command terminator, start reply
+      verifySpace();
+      if (desttype == 'E') {
+        while (1) ; // Error: wait for WDT
+      } else {
+        uint32_t addr = (((uint32_t)rampz) << 16) | address;
+        // During a single bootloader run, only erase a 64kB block once.
+        // An 8bit bitmask 'pages_erased' covers 512kB of FLASH memory.
+        if (address == 0 && (pages_erased & (1 << addr)) == 0) {
+          w25x20cl_wait_busy();
+          w25x20cl_enable_wr();
+          w25x20cl_block64_erase(addr);
+          pages_erased |= (1 << addr);
+        }
+        w25x20cl_wait_busy();
+        w25x20cl_enable_wr();
+        w25x20cl_page_program(addr, buff, savelength);
+        w25x20cl_wait_busy();
+        w25x20cl_disable_wr();
+      }
+    }
+    /* Read memory block mode, length is big endian.  */
+    else if(ch == STK_READ_PAGE) {
+      uint32_t addr = (((uint32_t)rampz) << 16) | address;
+      uint8_t desttype;
+      register pagelen_t i;
+      // Read the page length, with the length transferred each nibble separately to work around
+      // the Prusa's USB to serial infamous semicolon issue.
+      length  = ((pagelen_t)getch()) << 8;
+      length |= ((pagelen_t)getch()) << 8;
+      length |= getch();
+      length |= getch();
+      // Read the destination type. It should always be 'F' as flash.
+      desttype = getch();
+      verifySpace();
+      w25x20cl_wait_busy();
+      w25x20cl_rd_data(addr, buff, length);
+      for (i = 0; i < length; ++ i)
+        putch(buff[i]);
+    }
+    /* Get device signature bytes  */
+    else if(ch == STK_READ_SIGN) {
+      // READ SIGN - return what Avrdude wants to hear
+      verifySpace();
+      putch(W25X20CL_SIGNATURE_0);
+      putch(W25X20CL_SIGNATURE_1);
+      putch(W25X20CL_SIGNATURE_2);
+    }
+    else if (ch == STK_LEAVE_PROGMODE) { /* 'Q' */
+      // Adaboot no-wait mod
+      watchdogConfig(WATCHDOG_16MS);
+      verifySpace();
+    }
+    else {
+      // This covers the response to commands like STK_ENTER_PROGMODE
+      verifySpace();
+    }
+    putch(STK_OK);
+  }
+}

+ 6 - 0
Firmware/optiboot_w25x20cl.h

@@ -0,0 +1,6 @@
+#ifndef OPTIBOOT_W25X20CL_H
+#define OPTIBOOT_W25X20CL_H
+
+extern void optiboot_w25x20cl_enter();
+
+#endif /* OPTIBOOT_W25X20CL_H */

+ 49 - 0
Firmware/stk500.h

@@ -0,0 +1,49 @@
+/* STK500 constants list, from AVRDUDE
+ *
+ * Trivial set of constants derived from Atmel App Note AVR061
+ * Not copyrighted.  Released to the public domain.
+ */
+
+#define STK_OK              0x10
+#define STK_FAILED          0x11  // Not used
+#define STK_UNKNOWN         0x12  // Not used
+#define STK_NODEVICE        0x13  // Not used
+#define STK_INSYNC          0x14  // ' '
+#define STK_NOSYNC          0x15  // Not used
+#define ADC_CHANNEL_ERROR   0x16  // Not used
+#define ADC_MEASURE_OK      0x17  // Not used
+#define PWM_CHANNEL_ERROR   0x18  // Not used
+#define PWM_ADJUST_OK       0x19  // Not used
+#define CRC_EOP             0x20  // 'SPACE'
+#define STK_GET_SYNC        0x30  // '0'
+#define STK_GET_SIGN_ON     0x31  // '1'
+#define STK_SET_PARAMETER   0x40  // '@'
+#define STK_GET_PARAMETER   0x41  // 'A'
+#define STK_SET_DEVICE      0x42  // 'B'
+#define STK_SET_DEVICE_EXT  0x45  // 'E'
+#define STK_ENTER_PROGMODE  0x50  // 'P'
+#define STK_LEAVE_PROGMODE  0x51  // 'Q'
+#define STK_CHIP_ERASE      0x52  // 'R'
+#define STK_CHECK_AUTOINC   0x53  // 'S'
+#define STK_LOAD_ADDRESS    0x55  // 'U'
+#define STK_UNIVERSAL       0x56  // 'V'
+#define STK_PROG_FLASH      0x60  // '`'
+#define STK_PROG_DATA       0x61  // 'a'
+#define STK_PROG_FUSE       0x62  // 'b'
+#define STK_PROG_LOCK       0x63  // 'c'
+#define STK_PROG_PAGE       0x64  // 'd'
+#define STK_PROG_FUSE_EXT   0x65  // 'e'
+#define STK_READ_FLASH      0x70  // 'p'
+#define STK_READ_DATA       0x71  // 'q'
+#define STK_READ_FUSE       0x72  // 'r'
+#define STK_READ_LOCK       0x73  // 's'
+#define STK_READ_PAGE       0x74  // 't'
+#define STK_READ_SIGN       0x75  // 'u'
+#define STK_READ_OSCCAL     0x76  // 'v'
+#define STK_READ_FUSE_EXT   0x77  // 'w'
+#define STK_READ_OSCCAL_EXT 0x78  // 'x'
+#define STK_SW_MAJOR        0x81  // ' '
+#define STK_SW_MINOR        0x82  // ' '
+
+/* AVR raw commands sent via STK_UNIVERSAL */
+#define AVR_OP_LOAD_EXT_ADDR  0x4d

+ 63 - 28
Firmware/ultralcd.cpp

@@ -27,23 +27,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;
@@ -315,7 +298,6 @@ static void menu_action_setting_edit_callback_long5(const char* pstr, unsigned l
 #endif
 #endif
 
-
 /* Helper macros for menus */
 #define START_MENU() do { \
     if (encoderPosition > 0x8000) encoderPosition = 0; \
@@ -427,6 +409,48 @@ static void lcd_goto_menu(menuFunc_t menu, const uint32_t encoder = 0, const boo
 /* Main status screen. It's up to the implementation specific part to show what is needed. As this is very display dependent */
 
 
+#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;
+}
+
+#ifdef DEBUG_MENU_PRINTF_TEST
+int menu_item_printf_P(uint8_t& item, uint8_t line, const char* format, ...)
+{
+	va_list args;
+	va_start(args, format);
+	int ret = 0;
+	if (item == line)
+	{
+		if (lcdDrawUpdate)
+		{
+			//ret = 
+		    lcd.setCursor(0, line);
+			lcd.print(' ');
+			int cnt = vfprintf_P(lcdout, format, args);
+			for (int i = cnt; i < 19; i++)
+				lcd.print(' ');
+			lcd.print('>');
+		}
+	}
+	item++;
+	va_end(args);
+	return ret;
+}
+#endif //DEBUG_MENU_PRINTF_TEST
+
+
 static void lcd_status_screen()
 {
   if (firstrun == 1) 
@@ -3682,11 +3706,18 @@ void lcd_set_progress() {
 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);
+	if (lang_is_selected()) MENU_ITEM(back, _T(MSG_SETTINGS), 0); //
+	MENU_ITEM(setlang, lang_get_name_by_code(lang_get_code(0)), 0); //primary language
+	uint8_t cnt = lang_get_count();
+#ifdef W25X20CL
+	if (cnt == 2) //display secondary language in case of clear xflash 
+		MENU_ITEM(setlang, lang_get_name_by_code(lang_get_code(1)), 1);
+	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
+			MENU_ITEM(setlang, lang_get_name_by_code(lang_get_code(i)), i);
 	END_MENU();
 }
 #endif //(LANG_MODE != 0)
@@ -4149,11 +4180,11 @@ static void lcd_settings_menu()
   }
 
 #ifdef TMC2130_LINEARITY_CORRECTION_XYZ
-//  MENU_ITEM_EDIT(wfac, _i("X-corr"),  &tmc2130_wave_fac[X_AXIS],  TMC2130_WAVE_FAC1000_MIN-TMC2130_WAVE_FAC1000_STP, TMC2130_WAVE_FAC1000_MAX);////MSG_EXTRUDER_CORRECTION c=9 r=0
-//  MENU_ITEM_EDIT(wfac, _i("Y-corr"),  &tmc2130_wave_fac[Y_AXIS],  TMC2130_WAVE_FAC1000_MIN-TMC2130_WAVE_FAC1000_STP, TMC2130_WAVE_FAC1000_MAX);////MSG_EXTRUDER_CORRECTION c=9 r=0
-//  MENU_ITEM_EDIT(wfac, _i("Z-corr"),  &tmc2130_wave_fac[Z_AXIS],  TMC2130_WAVE_FAC1000_MIN-TMC2130_WAVE_FAC1000_STP, TMC2130_WAVE_FAC1000_MAX);////MSG_EXTRUDER_CORRECTION c=9 r=0
+  MENU_ITEM_EDIT(wfac, _i("X-correct"),  &tmc2130_wave_fac[X_AXIS],  TMC2130_WAVE_FAC1000_MIN-TMC2130_WAVE_FAC1000_STP, TMC2130_WAVE_FAC1000_MAX);////MSG_EXTRUDER_CORRECTION c=9 r=0
+  MENU_ITEM_EDIT(wfac, _i("Y-correct"),  &tmc2130_wave_fac[Y_AXIS],  TMC2130_WAVE_FAC1000_MIN-TMC2130_WAVE_FAC1000_STP, TMC2130_WAVE_FAC1000_MAX);////MSG_EXTRUDER_CORRECTION c=9 r=0
+  MENU_ITEM_EDIT(wfac, _i("Z-correct"),  &tmc2130_wave_fac[Z_AXIS],  TMC2130_WAVE_FAC1000_MIN-TMC2130_WAVE_FAC1000_STP, TMC2130_WAVE_FAC1000_MAX);////MSG_EXTRUDER_CORRECTION c=9 r=0
 #endif //TMC2130_LINEARITY_CORRECTION_XYZ
-//  MENU_ITEM_EDIT(wfac, _i("E-corr"),  &tmc2130_wave_fac[E_AXIS],  TMC2130_WAVE_FAC1000_MIN-TMC2130_WAVE_FAC1000_STP, TMC2130_WAVE_FAC1000_MAX);////MSG_EXTRUDER_CORRECTION c=9 r=0
+  MENU_ITEM_EDIT(wfac, _i("E-correct"),  &tmc2130_wave_fac[E_AXIS],  TMC2130_WAVE_FAC1000_MIN-TMC2130_WAVE_FAC1000_STP, TMC2130_WAVE_FAC1000_MAX);////MSG_EXTRUDER_CORRECTION c=9 r=0
 #endif //TMC2130
 
   if (temp_cal_active == false) {
@@ -5582,6 +5613,10 @@ static void lcd_main_menu()
   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
 
+#ifdef DEBUG_MENU_PRINTF_TEST
+	menu_item_printf_P(_menuItemNr, _lineNr, _N("Test %d %d %d"), 0, 1, 2);
+#endif //DEBUG_MENU_PRINTF_TEST
+
   END_MENU();
 
 }
@@ -6059,7 +6094,7 @@ char *wfac_to_str5(const uint8_t &x)
 	    conv[0] = '[';
 	    ftostr43(((float)((uint16_t)x + 1000) / 1000), 1);
 	    }
-	else strcpy_P(conv, _i("  [off"));////MSG_EXTRUDER_CORRECTION_OFF c=6 r=0
+	else strncpy_P(conv, _i("  [off"), 6);////MSG_EXTRUDER_CORRECTION_OFF c=6 r=0
 	conv[6] = ']';
 	conv[7] = ' ';
 	conv[8] = 0;

+ 4 - 0
Firmware/variants/1_75mm_MK2-RAMBo10a-E3Dv6full.h

@@ -422,6 +422,10 @@ THERMISTORS SETTINGS
 
 #define END_FILE_SECTION 10000 //number of bytes from end of file used for checking if file is complete
 
+// Safety timer
+#define SAFETYTIMER
+#define DEFAULT_SAFETYTIMER_TIME_MINS 30
+
 #define M600_TIMEOUT 600  //seconds
 
 #ifndef SNMM

+ 4 - 0
Firmware/variants/1_75mm_MK2-RAMBo13a-E3Dv6full.h

@@ -422,6 +422,10 @@ THERMISTORS SETTINGS
 
 #define END_FILE_SECTION 10000 //number of bytes from end of file used for checking if file is complete
 
+// Safety timer
+#define SAFETYTIMER
+#define DEFAULT_SAFETYTIMER_TIME_MINS 30
+
 #define M600_TIMEOUT 600  //seconds
 
 #ifndef SNMM

+ 1 - 0
Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h

@@ -106,6 +106,7 @@
 
 // Safety timer
 #define SAFETYTIMER
+#define DEFAULT_SAFETYTIMER_TIME_MINS 30
 
 // Filament sensor
 #define PAT9125

+ 1 - 0
Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h

@@ -106,6 +106,7 @@
 
 // Safety timer
 #define SAFETYTIMER
+#define DEFAULT_SAFETYTIMER_TIME_MINS 30
 
 // Filament sensor
 #define PAT9125

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

@@ -130,6 +130,7 @@
 
 // Safety timer
 #define SAFETYTIMER
+#define DEFAULT_SAFETYTIMER_TIME_MINS 30
 
 // Filament sensor
 #define PAT9125
@@ -148,6 +149,7 @@
 //#define DEBUG_BUILD
 //#define DEBUG_SEC_LANG   //secondary language debug output at startup
 //#define DEBUG_W25X20CL   //debug external spi flash
+//#define DEBUG_MENU_PRINTF_TEST
 #ifdef DEBUG_BUILD
 //#define _NO_ASM
 #define DEBUG_DCODES //D codes

+ 6 - 1
Firmware/w25x20cl.c

@@ -122,7 +122,7 @@ void w25x20cl_page_program_P(uint32_t addr, uint8_t* data, uint16_t cnt)
 void w25x20cl_erase(uint8_t cmd, uint32_t addr)
 {
 	_CS_LOW();
-	_SPI_TX(_CMD_SECTOR_ERASE);          // send command 0x20
+	_SPI_TX(cmd);          			     // send command 0x20
 	_SPI_TX(((uint8_t*)&addr)[2]);       // send addr bits 16..23
 	_SPI_TX(((uint8_t*)&addr)[1]);       // send addr bits 8..15
 	_SPI_TX(((uint8_t*)&addr)[0]);       // send addr bits 0..7
@@ -177,3 +177,8 @@ int w25x20cl_mfrid_devid(void)
 	_CS_HIGH();
 	return ((w25x20cl_mfrid == _MFRID) && (w25x20cl_devid == _DEVID));
 }
+
+void w25x20cl_wait_busy(void)
+{
+	while (w25x20cl_rd_status_reg() & W25X20CL_STATUS_BUSY) ;
+}

+ 2 - 1
Firmware/w25x20cl.h

@@ -34,8 +34,9 @@ extern void w25x20cl_sector_erase(uint32_t addr);
 extern void w25x20cl_block32_erase(uint32_t addr);
 extern void w25x20cl_block64_erase(uint32_t addr);
 extern void w25x20cl_chip_erase(void);
+extern void w25x20cl_page_program(uint32_t addr, uint8_t* data, uint16_t cnt);
 extern void w25x20cl_rd_uid(uint8_t* uid);
-
+extern void w25x20cl_wait_busy(void);
 
 #if defined(__cplusplus)
 }

+ 14 - 14
lang/lang_en_es.txt

@@ -1,6 +1,6 @@
 #MSG_EXTRUDER_CORRECTION_OFF c=6 r=0
 "  [off"
-"[inactivo"
+"  [ina"
 
 #MSG_PLANNER_BUFFER_BYTES c=0 r=0
 "  PlannerBufferBytes: "
@@ -196,7 +196,7 @@
 
 #MSG_CRASHDETECT_OFF c=0 r=0
 "Crash det.  [off]"
-"Det. choque [inactivo]"
+"Det. choque [ina]"
 
 #MSG_CRASH_DETECTED c=20 r=1
 "Crash detected."
@@ -588,19 +588,19 @@
 
 #MSG_STEALTH_MODE_OFF c=0 r=0
 "Mode     [Normal]"
-"Modo [Normal]"
+"Modo     [Normal]"
 
 #MSG_SILENT_MODE_ON c=0 r=0
 "Mode     [silent]"
-"Modo [silencio]"
+"Modo   [silencio]"
 
 #MSG_STEALTH_MODE_ON c=0 r=0
 "Mode    [Stealth]"
-"Modo [Silencio]"
+"Modo   [Silencio]"
 
 #MSG_AUTO_MODE_ON c=0 r=0
 "Mode [auto power]"
-"Modo [fuerza auto]"
+"Modo[fuerza auto]"
 
 #MSG_SILENT_MODE_OFF c=0 r=0
 "Mode [high power]"
@@ -864,7 +864,7 @@
 
 #MSG_TOSHIBA_FLASH_AIR_COMPATIBILITY_ON c=19 r=1
 "SD card [FlshAir]"
-"Tarj. SD [FlshAir]"
+"Tarj.SD [FlshAir]"
 
 #MSG_SD_CARD_OK c=0 r=0
 "SD card ok"
@@ -892,11 +892,11 @@
 
 #MSG_SELFTEST_START c=20 r=0
 "Self test start  "
-"Iniciar Selftest"
+"Iniciar Selftest "
 
 #MSG_SELFTEST c=0 r=0
 "Selftest         "
-"Selftest"
+"Selftest         "
 
 #MSG_SELFTEST_ERROR c=0 r=0
 "Selftest error !"
@@ -904,7 +904,7 @@
 
 #MSG_SELFTEST_FAILED c=20 r=0
 "Selftest failed  "
-"Fallo Selftest"
+"Fallo Selftest   "
 
 #MSG_FORCE_SELFTEST c=20 r=8
 "Selftest will be run to calibrate accurate sensorless rehoming."
@@ -936,11 +936,11 @@
 
 #MSG_SORT_TIME c=17 r=1
 "Sort:      [Time]"
-"Orden: [Fecha]"
+"Orden:    [Fecha]"
 
 #MSG_SORT_ALPHA c=17 r=1
 "Sort:  [Alphabet]"
-"Orden: [Alfabético]"
+"Orden:[Alfabétic]"
 
 #MSG_SORTING c=20 r=1
 "Sorting files"
@@ -988,11 +988,11 @@
 
 #MSG_TEMP_CALIBRATION_ON c=20 r=1
 "Temp. cal.   [on]"
-"Cal. temp. [ON]"
+"Cal. temp.   [ON]"
 
 #MSG_TEMP_CALIBRATION_OFF c=20 r=1
 "Temp. cal.  [off]"
-"Cal. temp. [OFF]"
+"Cal. temp.  [OFF]"
 
 #MSG_CALIBRATION_PINDA_MENU c=17 r=1
 "Temp. calibration"

+ 148 - 148
lang/lang_en_it.txt

@@ -12,11 +12,11 @@
 
 #MSG_FREE_MEMORY c=0 r=0
 " Free Memory: "
-"\x00"
+"Memoria Libera: "
 
 #MSG_CONFIGURATION_VER c=0 r=0
 " Last Updated: "
-"\x00"
+"Ultimo aggiornamento: "
 
 #MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2 c=14 r=0
 " of 4"
@@ -24,11 +24,11 @@
 
 #MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2 c=14 r=0
 " of 9"
-" su 9"
+"su 9"
 
 #MSG_MEASURED_OFFSET c=0 r=0
 "[0;0] point offset"
-"\x00"
+"[0;0] punto offset"
 
 #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"
@@ -52,7 +52,7 @@
 
 #MSG_WIZARD_DONE c=20 r=8
 "All is done. Happy printing!"
-"Ben fatto. Buona stampa!"
+"Tutto fatto. Buona stampa!"
 
 #MSG_PRESS c=20 r=0
 "and press the knob"
@@ -72,23 +72,23 @@
 
 #MSG_AUTOLOAD_FILAMENT c=17 r=0
 "AutoLoad filament"
-"\x00"
+"Autocaricamento filamento"
 
 #MSG_AUTOLOADING_ONLY_IF_FSENS_ON c=20 r=4
 "Autoloading filament available only when filament sensor is turned on..."
-"\x00"
+"Il caricamento automatico del filamento è disponibile solo quando il sensore è acceso..."
 
 #MSG_AUTOLOADING_ENABLED c=20 r=4
 "Autoloading filament is active, just press the knob and insert filament..."
-"\x00"
+"Il caricamento automatico è attivo, premete la manopola e inserite il filamento..."
 
 #MSG_SELFTEST_AXIS_LENGTH c=0 r=0
 "Axis length"
-"\x00"
+"Lunghezza dell'asse"
 
 #MSG_SELFTEST_AXIS c=0 r=0
 "Axis"
-"\x00"
+"Assi"
 
 #MSG_SELFTEST_BEDHEATER c=0 r=0
 "Bed / Heater"
@@ -96,7 +96,7 @@
 
 #MSG_BED_DONE c=0 r=0
 "Bed done"
-"Piatto fatto."
+"Piano fatto."
 
 #MSG_BED_HEATING c=0 r=0
 "Bed Heating"
@@ -108,15 +108,15 @@
 
 #MSG_BED_LEVELING_FAILED_POINT_LOW c=20 r=4
 "Bed leveling failed. Sensor didnt trigger. Debris on nozzle? Waiting for reset."
-"Livellamento letto fallito.NoRispSensor Residui su ugello? In attesa di reset."
+"Livellamento letto fallito.NoRispSensore.Residui su ugello? In attesa di reset."
 
 #MSG_BED_LEVELING_FAILED_PROBE_DISCONNECTED c=20 r=4
 "Bed leveling failed. Sensor disconnected or cable broken. Waiting for reset."
-"Livellamento letto fallito. Sensore discon. o Cavo Dann. In attesa di reset."
+"Livellamento piano fallito. Sensore disconnesso o Cavo Danneggiato. In attesa di reset."
 
 #MSG_BED_LEVELING_FAILED_POINT_HIGH c=20 r=4
 "Bed leveling failed. Sensor triggered too high. Waiting for reset."
-"Livellamento letto fallito.Risp sensore troppo prestoIn attesa di reset."
+"Livellamento piano fallito. Risposta sensore troppo presto. In attesa di reset."
 
 #MSG_BED c=0 r=0
 "Bed"
@@ -124,15 +124,15 @@
 
 #MSG_BEGIN_FILE_LIST c=0 r=0
 "Begin file list"
-"\x00"
+"Inizio lista file"
 
 #MSG_MENU_BELT_STATUS c=15 r=1
 "Belt status"
-"\x00"
+"Stato delle cinghie"
 
 #MSG_RECOVER_PRINT c=20 r=2
 "Blackout occurred. Recover print?"
-"\x00"
+"C'è stato un Blackout. Recuperare la stampa?"
 
 #MSG_CALIBRATE_BED c=0 r=0
 "Calibrate XYZ"
@@ -144,7 +144,7 @@
 
 #MSG_CALIBRATE_PINDA c=17 r=1
 "Calibrate"
-"Calibrare"
+"Calibra"
 
 #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."
@@ -160,7 +160,7 @@
 
 #MSG_HOMEYZ_DONE c=0 r=0
 "Calibration done"
-"Calibrazione OK"
+"Calibrazione completa"
 
 #MSG_MENU_CALIBRATION c=0 r=0
 "Calibration"
@@ -168,7 +168,7 @@
 
 #MSG_SD_CANT_ENTER_SUBDIR c=0 r=0
 "Cannot enter subdir: "
-"\x00"
+"Impossibile accedere alla sottocartella: "
 
 #MSG_SD_INSERTED c=0 r=0
 "Card inserted"
@@ -188,19 +188,19 @@
 
 #MSG_CRASHDETECT_ON c=0 r=0
 "Crash det.   [on]"
-"\x00"
+"Rilevamento imp. [on]"
 
 #MSG_CRASHDETECT_NA c=0 r=0
 "Crash det.  [N/A]"
-"\x00"
+"Rilevamento imp. [N/A]"
 
 #MSG_CRASHDETECT_OFF c=0 r=0
 "Crash det.  [off]"
-"\x00"
+"Rilevamento imp. [off]"
 
 #MSG_CRASH_DETECTED c=20 r=1
 "Crash detected."
-"\x00"
+"Rilevato impatto."
 
 #MSG_CURRENT c=19 r=1
 "Current"
@@ -208,15 +208,15 @@
 
 #MSG_DATE c=17 r=1
 "Date:"
-"Data"
+"Data:"
 
 #MSG_DISABLE_STEPPERS c=0 r=0
 "Disable steppers"
-"Disabilit motori"
+"Disabilita motori"
 
 #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."
-"Distanza tra la punta dell'ugello e la superficie del letto non ancora imposta. Si prega di seguire il manuale, capitolo First steps, sezione First layer calibration."
+"Distanza tra la punta dell'ugello e la superficie del letto non ancora imposta. Si prega di seguire il manuale, capitolo Primi Passi, sezione Calibrazione primo layer."
 
 #MSG_WIZARD_REPEAT_V2_CAL c=20 r=7
 "Do you want to repeat last step to readjust distance between nozzle and heatbed?"
@@ -224,11 +224,11 @@
 
 #MSG_EXTRUDER_CORRECTION c=9 r=0
 "E-correct"
-"\x00"
+"Correzione-E"
 
 #MSG_END_FILE_LIST c=0 r=0
 "End file list"
-"\x00"
+"Fine lista file"
 
 #MSG_SELFTEST_ENDSTOP_NOTHIT c=20 r=1
 "Endstop not hit"
@@ -240,11 +240,11 @@
 
 #MSG_ENDSTOPS_HIT c=0 r=0
 "endstops hit: "
-"\x00"
+"finecorsa colpito: "
 
 #MSG_SELFTEST_ENDSTOPS c=0 r=0
 "Endstops"
-"Finecorsa (2)"
+"Finecorsa"
 
 #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"
+"Errore - la memoria statica è stata sovrascritta"
 
 #MSG_SD_ERR_WRITE_TO_FILE c=0 r=0
 "error writing to file"
-"\x00"
+"errore scrittura sul file"
 
 #MSG_FSENS_NOT_RESPONDING c=20 r=4
 "ERROR: Filament sensor is not responding, please check connection."
-"\x00"
+"ERRORE: il sensore del filamento non risponde, per favore controllate la connessione"
 
 #MSG_ERROR c=0 r=0
 "ERROR:"
@@ -268,59 +268,59 @@
 
 #MSG_SELFTEST_EXTRUDER_FAN_SPEED c=18 r=0
 "Extruder fan:"
-"\x00"
+"Ventola estrusore:"
 
 #MSG_INFO_EXTRUDER c=15 r=1
 "Extruder info"
-"\x00"
+"Info estrusore"
 
 #MSG_MOVE_E c=0 r=0
 "Extruder"
-"Muovi Estrusore"
+"Estrusore"
 
 #MSG_FSENS_AUTOLOAD_ON c=17 r=1
 "F. autoload  [on]"
-"\x00"
+"Autocaricamento f. [on]"
 
 #MSG_FSENS_AUTOLOAD_NA c=17 r=1
 "F. autoload [N/A]"
-"\x00"
+"Autocaricamento f. [N/A]"
 
 #MSG_FSENS_AUTOLOAD_OFF c=17 r=1
 "F. autoload [off]"
-"\x00"
+"Autocaricamento f. [off]"
 
 #MSG_FAN_SPEED c=14 r=0
 "Fan speed"
-"Velocita vent."
+"Velocità ventola"
 
 #MSG_SELFTEST_FAN c=20 r=0
 "Fan test"
-"Prova del ventilator"
+"Test ventola"
 
 #MSG_FANS_CHECK_ON c=17 r=1
 "Fans check   [on]"
-"\x00"
+"Controllo ventole [on]"
 
 #MSG_FANS_CHECK_OFF c=17 r=1
 "Fans check  [off]"
-"\x00"
+"Controllo ventole [off]"
 
 #MSG_FSENSOR_ON c=0 r=0
 "Fil. sensor  [on]"
-"\x00"
+"Sensore filamenti [On]"
 
 #MSG_FSENSOR_NA c=0 r=0
 "Fil. sensor [N/A]"
-"\x00"
+"Sensore fil. [N/A]"
 
 #MSG_FSENSOR_OFF c=0 r=0
 "Fil. sensor [off]"
-"\x00"
+"Sensore filamenti [off]"
 
 #MSG_FILAMENT_CLEAN c=20 r=2
 "Filament extruding & with correct color?"
-"Il colore e' nitido?"
+"Filamento estruso & con il giusto colore?"
 
 #MSG_NOT_LOADED c=19 r=0
 "Filament not loaded"
@@ -328,35 +328,35 @@
 
 #MSG_FILAMENT_SENSOR c=20 r=0
 "Filament sensor"
-"\x00"
+"Sensore filamento "
 
 #MSG_SELFTEST_FILAMENT_SENSOR c=18 r=0
 "Filament sensor:"
-"\x00"
+"Sensore del filamento:"
 
 #MSG_FILE_INCOMPLETE c=20 r=2
 "File incomplete. Continue anyway?"
-"\x00"
+"File incompleto. Continuare comunque?"
 
 #MSG_SD_FILE_OPENED c=0 r=0
 "File opened: "
-"\x00"
+"File aperto: "
 
 #MSG_SD_FILE_SELECTED c=0 r=0
 "File selected"
-"\x00"
+"File selezionato"
 
 #MSG_FINISHING_MOVEMENTS c=20 r=1
 "Finishing movements"
-"Arresto in corso"
+"Finalizzando gli spostamenti"
 
 #MSG_V2_CALIBRATION c=17 r=1
 "First layer cal."
-"Cal. primo layer."
+"Calibrazione primo layer."
 
 #MSG_WIZARD_SELFTEST c=20 r=8
 "First, I will run the selftest to check most common assembly problems."
-"Anzitutto avviero il Self Test per controllare gli errori di assemblaggio piu comuni."
+"Per primo avvierò l'autotest per controllare gli errori di assemblaggio più comuni."
 
 #MSG_FLOW c=0 r=0
 "Flow"
@@ -368,7 +368,7 @@
 
 #MSG_SELFTEST_COOLING_FAN c=20 r=0
 "Front print fan?"
-"Vent di stampa ant.?"
+"Ventola di stampa frontale?"
 
 #MSG_BED_CORRECTION_FRONT c=14 r=1
 "Front side[um]"
@@ -376,7 +376,7 @@
 
 #MSG_SELFTEST_FANS c=0 r=0
 "Front/left fans"
-"\x00"
+"Ventola frontale/sinistra"
 
 #MSG_SELFTEST_HEATERTHERMISTOR c=0 r=0
 "Heater/Thermistor"
@@ -384,7 +384,7 @@
 
 #MSG_BED_HEATING_SAFETY_DISABLED c=0 r=0
 "Heating disabled by safety timer."
-"\x00"
+"Riscaldamento fermato dal timer di sicurezza."
 
 #MSG_HEATING_COMPLETE c=20 r=0
 "Heating done."
@@ -396,7 +396,7 @@
 
 #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?"
-"Ciao, sono la tua stampante Original Prusa i3. Gradiresti aiuto attraverso il processo di configurazione?"
+"Ciao, sono la tua stampante Original Prusa i3. Gradiresti un aiuto nel processo di configurazione?"
 
 #MSG_PRUSA3D_HOWTO c=0 r=0
 "howto.prusa3d.com"
@@ -404,7 +404,7 @@
 
 #MSG_FILAMENTCHANGE c=0 r=0
 "Change filament"
-"Camb. filamento"
+"Cambia filamento"
 
 #MSG_CHANGE_SUCCESS c=0 r=0
 "Change success!"
@@ -412,7 +412,7 @@
 
 #MSG_CORRECTLY c=20 r=0
 "Changed correctly?"
-"Cambiato corr.?"
+"Cambiato correttamente?"
 
 #MSG_CHANGING_FILAMENT c=20 r=0
 "Changing filament!"
@@ -420,7 +420,7 @@
 
 #MSG_SELFTEST_CHECK_BED c=20 r=0
 "Checking bed     "
-"Verifica letto"
+"Verifica piano"
 
 #MSG_SELFTEST_CHECK_ENDSTOPS c=20 r=0
 "Checking endstops"
@@ -432,7 +432,7 @@
 
 #MSG_SELFTEST_CHECK_FSENSOR c=20 r=0
 "Checking sensors "
-"\x00"
+"Controllo sensori"
 
 #MSG_SELFTEST_CHECK_X c=20 r=0
 "Checking X axis  "
@@ -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. Puo durare circa 12 min."
+"Adesso avviero una Calibrazione XYZ. Può durare circa 12 min."
 
 #MSG_WIZARD_Z_CAL c=20 r=8
 "I will run z calibration now."
-"Adesso avviero una Calibrazione Z."
+"Adesso avvierò 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."
@@ -480,7 +480,7 @@
 
 #MSG_FILAMENT_LOADING_T1 c=20 r=4
 "Insert filament into extruder 2. Click when done."
-"Inserire filamento nell'estrusore 2. Click per continuare."
+"Inserire filamento nell'estrusore 2. Clicca per continuare."
 
 #MSG_FILAMENT_LOADING_T2 c=20 r=4
 "Insert filament into extruder 3. Click when done."
@@ -488,7 +488,7 @@
 
 #MSG_FILAMENT_LOADING_T3 c=20 r=4
 "Insert filament into extruder 4. Click when done."
-"Inserire filamento nell'estrusore 4. Click per continuare."
+"Inserire filamento nell'estrusore 4. Clicca per continuare."
 
 #MSG_INSERT_FILAMENT c=20 r=0
 "Insert filament"
@@ -500,19 +500,19 @@
 
 #MSG_WIZARD_PLA_FILAMENT c=20 r=2
 "Is it PLA filament?"
-"E questo un filamento di PLA?"
+"E' un filamento di PLA?"
 
 #MSG_PLA_FILAMENT_LOADED c=20 r=2
 "Is PLA filament loaded?"
-"Il PLA e stato caricato?"
+"E' stato caricato il filamento di PLA?"
 
 #MSG_STEEL_SHEET_CHECK c=20 r=2
 "Is steel sheet on heatbed?"
-"\x00"
+"La piastra d'acciaio si trova sul piano riscaldato?"
 
 #MSG_FIND_BED_OFFSET_AND_SKEW_ITERATION c=20 r=0
 "Iteration "
-"Reiterazione "
+"Iterazione"
 
 #MSG_KILLED c=0 r=0
 "KILLED. "
@@ -520,11 +520,11 @@
 
 #MSG_SELFTEST_EXTRUDER_FAN c=20 r=0
 "Left hotend fan?"
-"Vent SX sull'ugello?"
+"Vent SX hotend?"
 
 #MSG_BED_CORRECTION_LEFT c=14 r=1
 "Left side [um]"
-"Sinistra [um]"
+"Lato sinistro [um]"
 
 #MSG_BABYSTEP_Z c=0 r=0
 "Live adjust Z"
@@ -540,7 +540,7 @@
 
 #MSG_LOADING_FILAMENT c=20 r=0
 "Loading filament"
-"Caricando filam."
+"Caricando filamento"
 
 #MSG_LOOSE_PULLEY c=20 r=1
 "Loose pulley"
@@ -548,19 +548,19 @@
 
 #MSG_M104_INVALID_EXTRUDER c=0 r=0
 "M104 Invalid extruder "
-"\x00"
+"M104 Estrusore non valido"
 
 #MSG_M105_INVALID_EXTRUDER c=0 r=0
 "M105 Invalid extruder "
-"\x00"
+"M105 Estrusore non valido"
 
 #MSG_M109_INVALID_EXTRUDER c=0 r=0
 "M109 Invalid extruder "
-"\x00"
+"M109 Estrusore non valido"
 
 #MSG_M117_V2_CALIBRATION c=25 r=1
 "M117 First layer cal."
-"M117 Cal. primo layer."
+"M117 Calibrazione primo layer."
 
 #MSG_M200_INVALID_EXTRUDER c=0 r=0
 "M200 Invalid extruder "
@@ -568,11 +568,11 @@
 
 #MSG_M218_INVALID_EXTRUDER c=0 r=0
 "M218 Invalid extruder "
-"\x00"
+"M218 Estrusore non valido"
 
 #MSG_M221_INVALID_EXTRUDER c=0 r=0
 "M221 Invalid extruder "
-"\x00"
+"M221 Estrusore non valido"
 
 #MSG_MAIN c=0 r=0
 "Main"
@@ -580,7 +580,7 @@
 
 #MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE1 c=60 r=0
 "Measuring reference height of calibration point"
-"Misurare l'altezza di riferimento del punto di calibrazione"
+"Misurando altezza di riferimento del punto di calibrazione"
 
 #MSG_MESH_BED_LEVELING c=0 r=0
 "Mesh Bed Leveling"
@@ -588,7 +588,7 @@
 
 #MSG_STEALTH_MODE_OFF c=0 r=0
 "Mode     [Normal]"
-"\x00"
+"Modo [normale]"
 
 #MSG_SILENT_MODE_ON c=0 r=0
 "Mode     [silent]"
@@ -596,11 +596,11 @@
 
 #MSG_STEALTH_MODE_ON c=0 r=0
 "Mode    [Stealth]"
-"\x00"
+"Modo [Silenziosa]"
 
 #MSG_AUTO_MODE_ON c=0 r=0
 "Mode [auto power]"
-"\x00"
+"Modo [auto]"
 
 #MSG_SILENT_MODE_OFF c=0 r=0
 "Mode [high power]"
@@ -652,11 +652,11 @@
 
 #MSG_WIZARD_V2_CAL c=20 r=8
 "Now I will calibrate distance between tip of the nozzle and heatbed surface."
-"Adesso tarero lo stacco fra ugello e superfice del piatto."
+"Adesso calibro la distanza fra ugello e superfice del piatto."
 
 #MSG_WIZARD_WILL_PREHEAT c=20 r=4
 "Now I will preheat nozzle for PLA."
-"Adesso preriscaldero l'ugello per PLA."
+"Adesso preriscalderò l'ugello per PLA."
 
 #MSG_NOZZLE c=0 r=0
 "Nozzle"
@@ -668,15 +668,15 @@
 
 #MSG_DEFAULT_SETTINGS_LOADED c=20 r=4
 "Old settings found. Default PID, Esteps etc. will be set."
-"\x00"
+"Sono state trovate impostazioni vecchie. I valori di default di PID, Esteps etc. saranno impostati"
 
 #MSG_SD_OPEN_FILE_FAIL c=0 r=0
 "open failed, File: "
-"\x00"
+"apertura fallita, File: "
 
 #MSG_ENDSTOP_OPEN c=0 r=0
 "open"
-"\x00"
+"apri"
 
 #MSG_SD_OPENROOT_FAIL c=0 r=0
 "openRoot failed"
@@ -688,11 +688,11 @@
 
 #MSG_PID_RUNNING c=20 r=1
 "PID cal.           "
-"Cal. PID"
+"Calibrazione PID"
 
 #MSG_PID_FINISHED c=20 r=1
 "PID cal. finished"
-"Cal. PID completa"
+"Calib. PID completa"
 
 #MSG_PID_EXTRUDER c=17 r=1
 "PID calibration"
@@ -700,7 +700,7 @@
 
 #MSG_PINDA_PREHEAT c=20 r=1
 "PINDA Heating"
-"Riscald. PINDA"
+"Riscaldamento 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."
@@ -716,7 +716,7 @@
 
 #MSG_SELFTEST_PLEASECHECK c=0 r=0
 "Please check :"
-"Verificare:"
+"Verifica:"
 
 #MSG_WIZARD_CALIBRATION_FAILED c=20 r=8
 "Please check our handbook and fix the problem. Then resume the Wizard by rebooting the printer."
@@ -732,35 +732,35 @@
 
 #MSG_PLEASE_LOAD_PLA c=20 r=4
 "Please load PLA filament first."
-"Per favore prima caricare filamento di PLA."
+"Per favore prima carica il filamento di PLA."
 
 #MSG_CHECK_IDLER c=20 r=4
 "Please open idler and remove filament manually."
-"\x00"
+"aprite l'assemblaggio estrusore e rimuovete il filamento manualmente."
 
 #MSG_PLACE_STEEL_SHEET c=20 r=4
 "Please place steel sheet on heatbed."
-"\x00"
+"Per favore posizionate la piastra d'acciaio sul piano riscaldato."
 
 #MSG_PRESS_TO_UNLOAD c=20 r=4
 "Please press the knob to unload filament"
-"\x00"
+"Premete la manopola per scaricare il filamento "
 
 #MSG_PULL_OUT_FILAMENT c=20 r=4
 "Please pull out filament immediately"
-"\x00"
+"Tirate fuori il filamento immediatamente"
 
 #MSG_REMOVE_STEEL_SHEET c=20 r=4
 "Please remove steel sheet from heatbed."
-"\x00"
+"Rimuovete la piastra di acciaio dal piano riscaldato"
 
 #MSG_PLEASE_WAIT c=20 r=0
 "Please wait"
-"Aspetta"
+"Attendere"
 
 #MSG_POWERUP c=0 r=0
 "PowerUp"
-"\x00"
+"Accendi"
 
 #MSG_PREHEAT_NOZZLE c=20 r=0
 "Preheat the nozzle!"
@@ -772,19 +772,19 @@
 
 #MSG_WIZARD_HEATING c=20 r=3
 "Preheating nozzle. Please wait."
-"Sto preriscaldando l'ugello. Per favore attendi."
+"Preriscaldando l'ugello. Attendere prego."
 
 #MSG_PRESS_TO_PREHEAT c=20 r=4
 "Press knob to preheat nozzle and continue."
-"\x00"
+"Premete la manopola per preriscaldare l'ugello e continuare."
 
 #MSG_PRINT_ABORTED c=20 r=0
 "Print aborted"
-"Stampa abortita"
+"Stampa interrotta"
 
 #MSG_SELFTEST_PRINT_FAN_SPEED c=18 r=0
 "Print fan:"
-"\x00"
+"Ventola di stampa:"
 
 #MSG_CARD_MENU c=0 r=0
 "Print from SD"
@@ -800,11 +800,11 @@
 
 #MSG_FOLLOW_CALIBRATION_FLOW c=20 r=8
 "Printer has not been calibrated yet. Please follow the manual, chapter First steps, section Calibration flow."
-"Stampante ancora non calibrata. Si prega di seguire il manuale, capitolo PRIMI PASSI, sezione della calibrazione."
+"Stampante non ancora calibrata. Si prega di seguire il manuale, capitolo Primi Passi, sezione Sequenza di Calibrazione."
 
 #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"
+"La stampante si è 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."
@@ -820,7 +820,7 @@
 
 #MSG_RECOVERING_PRINT c=20 r=1
 "Recovering print    "
-"\x00"
+"Recupero stampa"
 
 #MSG_M119_REPORT c=0 r=0
 "Reporting endstop status"
@@ -848,11 +848,11 @@
 
 #MSG_SECOND_SERIAL_ON c=17 r=1
 "RPi port     [on]"
-"\x00"
+"Porta RPi [on]"
 
 #MSG_SECOND_SERIAL_OFF c=17 r=1
 "RPi port    [off]"
-"\x00"
+"Porta RPi [off]"
 
 #MSG_WIZARD_RERUN c=20 r=7
 "Running Wizard will delete current calibration results and start from the beginning. Continue?"
@@ -860,11 +860,11 @@
 
 #MSG_TOSHIBA_FLASH_AIR_COMPATIBILITY_OFF c=19 r=1
 "SD card  [normal]"
-"SD card [normal]"
+"Memoria SD [normale]"
 
 #MSG_TOSHIBA_FLASH_AIR_COMPATIBILITY_ON c=19 r=1
 "SD card [FlshAir]"
-"\x00"
+"Memoria SD [FlshAir]"
 
 #MSG_SD_CARD_OK c=0 r=0
 "SD card ok"
@@ -872,7 +872,7 @@
 
 #MSG_SD_INIT_FAIL c=0 r=0
 "SD init fail"
-"\x00"
+"Inizializzazione Memoria SD Fallita"
 
 #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"
-"Ricerca del letto punto di calibraz."
+"Ricerca dei punti di calibrazione del piano"
 
 #MSG_LANGUAGE_SELECT c=0 r=0
 "Select language"
@@ -900,7 +900,7 @@
 
 #MSG_SELFTEST_ERROR c=0 r=0
 "Selftest error !"
-"Autotest negativo"
+"Errore Autotest !"
 
 #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"
+"Verrà effettuato un self test per calibrare l'homing senza sensori"
 
 #MSG_SET_TEMPERATURE c=19 r=1
 "Set temperature:"
-"Imposta temperatura"
+"Imposta temperatura:"
 
 #MSG_SETTINGS c=0 r=0
 "Settings"
@@ -928,27 +928,27 @@
 
 #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"
+"Alcuni file non saranno ordinati. Il numero massimo di file in una cartella è 100 perché siano ordinati."
 
 #MSG_SORT_NONE c=17 r=1
 "Sort:      [None]"
-"\x00"
+"Ordine: [Nessuno]"
 
 #MSG_SORT_TIME c=17 r=1
 "Sort:      [Time]"
-"\x00"
+"Ordine: [Tempo]"
 
 #MSG_SORT_ALPHA c=17 r=1
 "Sort:  [Alphabet]"
-"\x00"
+"Ordine: [Alfabetico]"
 
 #MSG_SORTING c=20 r=1
 "Sorting files"
-"\x00"
+"Ordinando i file"
 
 #MSG_SPEED c=0 r=0
 "Speed"
-"Velocita"
+"Velocità"
 
 #MSG_SELFTEST_FAN_YES c=19 r=0
 "Spinning"
@@ -956,7 +956,7 @@
 
 #MSG_TEMP_CAL_WARNING c=20 r=4
 "Stable ambient temperature 21-26C is needed a rigid stand is required."
-"\x00"
+"Sono necessari una temperatura ambiente di 21-26C e una superficie rigida "
 
 #MSG_STATISTICS c=0 r=0
 "Statistics  "
@@ -964,7 +964,7 @@
 
 #MSG_STEPPER_TOO_HIGH c=0 r=0
 "Steprate too high: "
-"\x00"
+"Velocità passo troppo alta: "
 
 #MSG_STOP_PRINT c=0 r=0
 "Stop print"
@@ -976,47 +976,47 @@
 
 #MSG_SUPPORT c=0 r=0
 "Support"
-"\x00"
+"Supporto"
 
 #MSG_SELFTEST_SWAPPED c=0 r=0
 "Swapped"
-"\x00"
+"Scambiato"
 
 #MSG_TEMP_CALIBRATION c=20 r=1
 "Temp. cal.          "
-"Cal. temp. "
+"Calib. temp. "
 
 #MSG_TEMP_CALIBRATION_ON c=20 r=1
 "Temp. cal.   [on]"
-"Cal. temp. [ON]"
+"Calib. temp. [ON]"
 
 #MSG_TEMP_CALIBRATION_OFF c=20 r=1
 "Temp. cal.  [off]"
-"Cal. temp. [OFF]"
+"Calib. temp. [OFF]"
 
 #MSG_CALIBRATION_PINDA_MENU c=17 r=1
 "Temp. calibration"
-"Taratura temp."
+"Calib. Temp."
 
 #MSG_TEMP_CAL_FAILED c=20 r=8
 "Temperature calibration failed"
-"\x00"
+"Calibrazione temperatura fallita"
 
 #MSG_TEMP_CALIBRATION_DONE c=20 r=12
 "Temperature calibration is finished and active. Temp. calibration can be disabled in menu Settings->Temp. cal."
-"Taratura temperatura terminata. Fare click per continuare."
+"Calibrazione temperatura completata e attiva. Può essere disattivata dal menù Impostazioni ->Cal. Temp."
 
 #MSG_TEMPERATURE c=0 r=0
 "Temperature"
-"Temperatura"
+"\x00"
 
 #MSG_MENU_TEMPERATURES c=15 r=1
 "Temperatures"
-"\x00"
+"Temperature"
 
 #MSG_ENDSTOP_HIT c=0 r=0
 "TRIGGERED"
-"\x00"
+"ATTIVATO"
 
 #MSG_TUNE c=0 r=0
 "Tune"
@@ -1028,7 +1028,7 @@
 
 #MSG_UNLOADING_FILAMENT c=20 r=1
 "Unloading filament"
-"Rilasc. filamento"
+"Scaricando filamento"
 
 #MSG_USED c=19 r=1
 "Used during print"
@@ -1036,7 +1036,7 @@
 
 #MSG_MENU_VOLTAGES c=15 r=1
 "Voltages"
-"\x00"
+"Voltaggi"
 
 #MSG_SD_VOL_INIT_FAIL c=0 r=0
 "volume.init failed"
@@ -1044,31 +1044,31 @@
 
 #MSG_USERWAIT c=0 r=0
 "Wait for user..."
-"Attendendo utente"
+"Attendendo utente..."
 
 #MSG_WAITING_TEMP c=20 r=3
 "Waiting for nozzle and bed cooling"
-"In attesa del raffreddamento della testina e del piatto"
+"In attesa del raffreddamento dell'ugello e del piano"
 
 #MSG_WAITING_TEMP_PINDA c=20 r=3
 "Waiting for PINDA probe cooling"
-"\x00"
+"In attesa del raffreddamento della sonda PINDA"
 
 #MSG_CHANGED_BOTH c=20 r=4
 "Warning: both printer type and motherboard type changed."
-"\x00"
+"Attenzione: tipo di stampante e di scheda madre cambiati."
 
 #MSG_CHANGED_MOTHERBOARD c=20 r=4
 "Warning: motherboard type changed."
-"\x00"
+"Avviso: tipo di scheda madre cambiato"
 
 #MSG_CHANGED_PRINTER c=20 r=4
 "Warning: printer type changed."
-"\x00"
+"Avviso: tipo di stampante cambiato."
 
 #MSG_UNLOAD_SUCCESSFUL c=20 r=2
 "Was filament unload successful?"
-"\x00"
+"Filamento scaricato con successo?"
 
 #MSG_SELFTEST_WIRINGERROR c=0 r=0
 "Wiring error"
@@ -1084,7 +1084,7 @@
 
 #MSG_SD_WRITE_TO_FILE c=0 r=0
 "Writing to file: "
-"\x00"
+"Scrittura su file: "
 
 #MSG_XYZ_DETAILS c=19 r=1
 "XYZ cal. details"
@@ -1100,5 +1100,5 @@
 
 #MSG_WIZARD_QUIT c=20 r=8
 "You can always resume the Wizard from Calibration -> Wizard."
-"E possibile proseguire la guide Wizard in qualsiasi momento attraverso Calibrazione -> Wizard."
+"E possibile riprendere il Wizard in qualsiasi momento attraverso Calibrazione -> Wizard."
 

+ 47 - 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,42 @@ 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
 
+#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
  make_lang cz
  make_lang de
  make_lang es
@@ -154,7 +159,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

+ 4 - 4
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
@@ -99,8 +99,8 @@ 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

+ 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