Sfoglia il codice sorgente

Merge branch 'MK3' into MK3_Enable_fan_waiting_cooldown

leptun 4 anni fa
parent
commit
b8b167d1ca

+ 1 - 0
.gitignore

@@ -51,3 +51,4 @@ Firmware/Doc
 /build-env/
 /Firmware/Firmware.vcxproj
 /Firmware/Configuration_prusa_bckp.h
+/Firmware/variants/printers.h

+ 7 - 0
.travis.yml

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

+ 10 - 0
Firmware/Configuration.cpp

@@ -0,0 +1,10 @@
+#include "Configuration.h"
+#include "Configuration_prusa.h"
+
+const uint16_t _nPrinterType PROGMEM=PRINTER_TYPE;
+const char _sPrinterName[] PROGMEM=PRINTER_NAME;
+const uint16_t _nPrinterMmuType PROGMEM=PRINTER_MMU_TYPE;
+const char _sPrinterMmuName[] PROGMEM=PRINTER_MMU_NAME;
+
+uint16_t nPrinterType;
+PGM_P sPrinterName;

+ 12 - 0
Firmware/Configuration.h

@@ -6,6 +6,15 @@
 #define STR_HELPER(x) #x
 #define STR(x) STR_HELPER(x)
 
+//-//
+#include <avr/pgmspace.h>
+extern const uint16_t _nPrinterType;
+extern const char _sPrinterName[] PROGMEM;
+extern const uint16_t _nPrinterMmuType;
+extern const char _sPrinterMmuName[] PROGMEM;
+extern uint16_t nPrinterType;
+extern PGM_P sPrinterName;
+
 // Firmware version
 #define FW_VERSION "3.7.2-RC1"
 #define FW_COMMIT_NR   2359
@@ -15,6 +24,9 @@
 #define FW_REPOSITORY "Unknown"
 #define FW_VERSION_FULL FW_VERSION "-" STR(FW_COMMIT_NR)
 
+// G-code language level
+#define GCODE_LEVEL 1
+
 // Debug version has debugging enabled (the symbol DEBUG_BUILD is set).
 // The debug build may be a bit slower than the non-debug build, therefore the debug build should
 // not be shipped to a customer.

+ 0 - 1
Firmware/Marlin.h

@@ -323,7 +323,6 @@ extern float retract_recover_length_swap;
 
 extern uint8_t host_keepalive_interval;
 
-
 extern unsigned long starttime;
 extern unsigned long stoptime;
 extern int bowden_length[4];

+ 128 - 72
Firmware/Marlin_main.cpp

@@ -43,8 +43,10 @@
  *
  */
 
+//-//
+#include "Configuration.h"
 #include "Marlin.h"
-
+  
 #ifdef ENABLE_AUTO_BED_LEVELING
 #include "vector_3.h"
   #ifdef AUTO_BED_LEVELING_GRID
@@ -354,7 +356,6 @@ unsigned long starttime=0;
 unsigned long stoptime=0;
 unsigned long _usb_timer = 0;
 
-
 bool extruder_under_pressure = true;
 
 
@@ -657,19 +658,13 @@ static void factory_reset(char level)
                    
         // Level 0: Language reset
         case 0:
-if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
-            WRITE(BEEPER, HIGH);
-            _delay_ms(100);
-            WRITE(BEEPER, LOW);
+      Sound_MakeCustom(100,0,false);
 			lang_reset();
             break;
          
 		//Level 1: Reset statistics
 		case 1:
-if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
-			WRITE(BEEPER, HIGH);
-			_delay_ms(100);
-			WRITE(BEEPER, LOW);
+      Sound_MakeCustom(100,0,false);
 			eeprom_update_dword((uint32_t *)EEPROM_TOTALTIME, 0);
 			eeprom_update_dword((uint32_t *)EEPROM_FILAMENTUSED, 0);
 
@@ -724,11 +719,7 @@ if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
 			fsensor_enable();
             fsensor_autoload_set(true);
 #endif //FILAMENT_SENSOR
-                       
-if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
-            WRITE(BEEPER, HIGH);
-            _delay_ms(100);
-            WRITE(BEEPER, LOW);
+      Sound_MakeCustom(100,0,false);   
 			//_delay_ms(2000);
             break;
 
@@ -738,11 +729,7 @@ if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
 			lcd_puts_P(PSTR("Factory RESET"));
 			lcd_puts_at_P(1, 2, PSTR("ERASING all data"));
 
-if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
-			WRITE(BEEPER, HIGH);
-			_delay_ms(100);
-			WRITE(BEEPER, LOW);
-
+      Sound_MakeCustom(100,0,false);
 			er_progress = 0;
 			lcd_puts_at_P(3, 3, PSTR("      "));
 			lcd_set_cursor(3, 3);
@@ -812,7 +799,7 @@ void factory_reset()
 
 
 			SET_OUTPUT(BEEPER);
-if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
+  if(eSoundMode!=e_SOUND_MODE_SILENT)
 			WRITE(BEEPER, HIGH);
 
 			while (!READ(BTN_ENC));
@@ -1076,6 +1063,7 @@ void setup()
 	SERIAL_ECHO_START;
 	printf_P(PSTR(" " FW_VERSION_FULL "\n"));
 
+	//SERIAL_ECHOPAIR("Active sheet before:", static_cast<unsigned long int>(eeprom_read_byte(&(EEPROM_Sheets_base->active_sheet))));
 
 #ifdef DEBUG_SEC_LANG
 	lang_table_header_t header;
@@ -1424,20 +1412,7 @@ void setup()
 		printf_P(PSTR("Card NG!\n"));
 #endif //DEBUG_SD_SPEED_TEST
 
-	if (eeprom_read_byte((uint8_t*)EEPROM_POWER_COUNT) == 0xff) eeprom_write_byte((uint8_t*)EEPROM_POWER_COUNT, 0);
-	if (eeprom_read_byte((uint8_t*)EEPROM_CRASH_COUNT_X) == 0xff) eeprom_write_byte((uint8_t*)EEPROM_CRASH_COUNT_X, 0);
-	if (eeprom_read_byte((uint8_t*)EEPROM_CRASH_COUNT_Y) == 0xff) eeprom_write_byte((uint8_t*)EEPROM_CRASH_COUNT_Y, 0);
-	if (eeprom_read_byte((uint8_t*)EEPROM_FERROR_COUNT) == 0xff) eeprom_write_byte((uint8_t*)EEPROM_FERROR_COUNT, 0);
-	if (eeprom_read_word((uint16_t*)EEPROM_POWER_COUNT_TOT) == 0xffff) eeprom_write_word((uint16_t*)EEPROM_POWER_COUNT_TOT, 0);
-	if (eeprom_read_word((uint16_t*)EEPROM_CRASH_COUNT_X_TOT) == 0xffff) eeprom_write_word((uint16_t*)EEPROM_CRASH_COUNT_X_TOT, 0);
-	if (eeprom_read_word((uint16_t*)EEPROM_CRASH_COUNT_Y_TOT) == 0xffff) eeprom_write_word((uint16_t*)EEPROM_CRASH_COUNT_Y_TOT, 0);
-	if (eeprom_read_word((uint16_t*)EEPROM_FERROR_COUNT_TOT) == 0xffff) eeprom_write_word((uint16_t*)EEPROM_FERROR_COUNT_TOT, 0);
-
-	if (eeprom_read_word((uint16_t*)EEPROM_MMU_FAIL_TOT) == 0xffff) eeprom_update_word((uint16_t *)EEPROM_MMU_FAIL_TOT, 0);
-	if (eeprom_read_word((uint16_t*)EEPROM_MMU_LOAD_FAIL_TOT) == 0xffff) eeprom_update_word((uint16_t *)EEPROM_MMU_LOAD_FAIL_TOT, 0);
-	if (eeprom_read_byte((uint8_t*)EEPROM_MMU_FAIL) == 0xff) eeprom_update_byte((uint8_t *)EEPROM_MMU_FAIL, 0);
-	if (eeprom_read_byte((uint8_t*)EEPROM_MMU_LOAD_FAIL) == 0xff) eeprom_update_byte((uint8_t *)EEPROM_MMU_LOAD_FAIL, 0);
-
+    eeprom_init();
 #ifdef SNMM
 	if (eeprom_read_dword((uint32_t*)EEPROM_BOWDEN_LENGTH) == 0x0ffffffff) { //bowden length used for SNMM
 	  int _z = BOWDEN_LENGTH;
@@ -1504,7 +1479,6 @@ void setup()
 		SilentModeMenu_MMU = 1;
 		eeprom_write_byte((uint8_t*)EEPROM_MMU_STEALTH, SilentModeMenu_MMU);
 	}
-	check_babystep(); //checking if Z babystep is in allowed range
 
 #if !defined(DEBUG_DISABLE_FANCHECK) && defined(FANCHECK) && defined(TACH_1) && TACH_1 >-1
 	setup_fan_interrupt();
@@ -1646,11 +1620,11 @@ void setup()
   }
 #endif //UVLO_SUPPORT
   fCheckModeInit();
+  fSetMmuMode(mmu_enabled);
   KEEPALIVE_STATE(NOT_BUSY);
 #ifdef WATCHDOG
   wdt_enable(WDTO_4S);
 #endif //WATCHDOG
-
 }
 
 
@@ -2359,11 +2333,7 @@ void refresh_cmd_timeout(void)
 #endif //FWRETRACT
 
 void trace() {
-//if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
-    _tone(BEEPER, 440);
-    _delay(25);
-    _noTone(BEEPER);
-    _delay(20);
+    Sound_MakeCustom(25,440,true);
 }
 /*
 void ramming() {
@@ -3175,6 +3145,11 @@ void gcode_M701()
 {
 	printf_P(PSTR("gcode_M701 begin\n"));
 
+	if (farm_mode)
+	{
+		prusa_statistics(22);
+	}
+
 	if (mmu_enabled) 
 	{
 		extr_adj(tmp_extruder);//loads current extruder
@@ -3201,9 +3176,7 @@ void gcode_M701()
 		load_filament_final_feed(); //slow sequence
 		st_synchronize();
 
-		if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE)) _tone(BEEPER, 500);
-		delay_keep_alive(50);
-		_noTone(BEEPER);
+    Sound_MakeCustom(50,500,false);
 
 		if (!farm_mode && loading_flag) {
 			lcd_load_filament_color_check();
@@ -3654,7 +3627,7 @@ void process_commands()
 
 //-//
 /*
-    } else if(code_seen("qqq")) {
+    } else if(code_seen("rrr")) {
 MYSERIAL.println("=== checking ===");
 MYSERIAL.println(eeprom_read_byte((uint8_t*)EEPROM_CHECK_MODE),DEC);
 MYSERIAL.println(eeprom_read_byte((uint8_t*)EEPROM_NOZZLE_DIAMETER),DEC);
@@ -3676,13 +3649,47 @@ eeprom_update_word((uint16_t*)EEPROM_NOZZLE_DIAMETER_uM,0xFFFF);
                }
           else if(code_seen("set") && farm_mode)
                {
+               strchr_pointer++;                  // skip 1st char (~ 's')
                strchr_pointer++;                  // skip 2nd char (~ 'e')
-               strchr_pointer++;                  // skip 3rd char (~ 't')
                nDiameter=(uint16_t)(code_value()*1000.0+0.5); // [,um]
-               eeprom_update_byte((uint8_t*)EEPROM_NOZZLE_DIAMETER,(uint8_t)e_NOZZLE_DIAMETER_NULL); // for correct synchronization after farm-mode exiting
+               eeprom_update_byte((uint8_t*)EEPROM_NOZZLE_DIAMETER,(uint8_t)ClNozzleDiameter::_Diameter_Undef); // for correct synchronization after farm-mode exiting
                eeprom_update_word((uint16_t*)EEPROM_NOZZLE_DIAMETER_uM,nDiameter);
                }
           else SERIAL_PROTOCOLLN((float)eeprom_read_word((uint16_t*)EEPROM_NOZZLE_DIAMETER_uM)/1000.0);
+
+//-// !!! SupportMenu
+/*
+// musi byt PRED "PRUSA model"
+    } else if (code_seen("smodel")) { //! PRUSA smodel
+          size_t nOffset;
+// ! -> "l"
+          strchr_pointer+=5*sizeof(*strchr_pointer); // skip 1st - 5th char (~ 'smode')
+          nOffset=strspn(strchr_pointer+1," \t\n\r\v\f");
+          if(*(strchr_pointer+1+nOffset))
+               printer_smodel_check(strchr_pointer);
+          else SERIAL_PROTOCOLLN(PRINTER_NAME);
+    } else if (code_seen("model")) { //! PRUSA model
+          uint16_t nPrinterModel;
+          strchr_pointer+=4*sizeof(*strchr_pointer); // skip 1st - 4th char (~ 'mode')
+          nPrinterModel=(uint16_t)code_value_long();
+          if(nPrinterModel!=0)
+               printer_model_check(nPrinterModel);
+          else SERIAL_PROTOCOLLN(PRINTER_TYPE);
+    } else if (code_seen("version")) { //! PRUSA version
+          strchr_pointer+=7*sizeof(*strchr_pointer); // skip 1st - 7th char (~ 'version')
+          while(*strchr_pointer==' ')             // skip leading spaces
+               strchr_pointer++;
+          if(*strchr_pointer!=0)
+               fw_version_check(strchr_pointer);
+          else SERIAL_PROTOCOLLN(FW_VERSION);
+    } else if (code_seen("gcode")) { //! PRUSA gcode
+          uint16_t nGcodeLevel;
+          strchr_pointer+=4*sizeof(*strchr_pointer); // skip 1st - 4th char (~ 'gcod')
+          nGcodeLevel=(uint16_t)code_value_long();
+          if(nGcodeLevel!=0)
+               gcode_level_check(nGcodeLevel);
+          else SERIAL_PROTOCOLLN(GCODE_LEVEL);
+*/
 	}	
     //else if (code_seen('Cal')) {
 		//  lcd_calibration();
@@ -3768,7 +3775,7 @@ eeprom_update_word((uint16_t*)EEPROM_NOZZLE_DIAMETER_uM,0xFFFF);
                             
                             SET_OUTPUT(BEEPER);
                             if (counterBeep== 0){
-if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
+if(eSoundMode!=e_SOUND_MODE_SILENT)
                               WRITE(BEEPER,HIGH);
                             }
                             
@@ -5964,7 +5971,7 @@ Sigma_Exit:
           SERIAL_PROTOCOLLNRPGM(FW_VERSION_STR_P());
       } else if (code_seen('U')) {
           // Check the firmware version provided. If the firmware version provided by the U code is higher than the currently running firmware,
-          // pause the print and ask the user to upgrade the firmware.
+          // pause the print for 30s and ask the user to upgrade the firmware.
           show_upgrade_dialog_if_version_newer(++ strchr_pointer);
       } else {
           SERIAL_ECHOPGM("FIRMWARE_NAME:Prusa-Firmware ");
@@ -6436,10 +6443,7 @@ Sigma_Exit:
       if (beepS > 0)
       {
         #if BEEPER > 0
-if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
-          _tone(BEEPER, beepS);
-          _delay(beepP);
-          _noTone(BEEPER);
+          Sound_MakeCustom(beepP,beepS,false);
         #endif
       }
       else
@@ -6847,6 +6851,65 @@ if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
 
 #endif //PINDA_THERMISTOR
 
+    case 862: // M862: print checking
+          float nDummy;
+          uint8_t nCommand;
+          nCommand=(uint8_t)(modff(code_value_float(),&nDummy)*10.0+0.5);
+          switch((ClPrintChecking)nCommand)
+               {
+               case ClPrintChecking::_Nozzle:     // ~ .1
+                    uint16_t nDiameter;
+                    if(code_seen('P'))
+                         {
+                         nDiameter=(uint16_t)(code_value()*1000.0+0.5); // [,um]
+                         nozzle_diameter_check(nDiameter);
+                         }
+/*
+                    else if(code_seen('S')&&farm_mode)
+                         {
+                         nDiameter=(uint16_t)(code_value()*1000.0+0.5); // [,um]
+                         eeprom_update_byte((uint8_t*)EEPROM_NOZZLE_DIAMETER,(uint8_t)ClNozzleDiameter::_Diameter_Undef); // for correct synchronization after farm-mode exiting
+                         eeprom_update_word((uint16_t*)EEPROM_NOZZLE_DIAMETER_uM,nDiameter);
+                         }
+*/
+                    else if(code_seen('Q'))
+                         SERIAL_PROTOCOLLN((float)eeprom_read_word((uint16_t*)EEPROM_NOZZLE_DIAMETER_uM)/1000.0);
+                    break;
+               case ClPrintChecking::_Model:      // ~ .2
+                    if(code_seen('P'))
+                         {
+                         uint16_t nPrinterModel;
+                         nPrinterModel=(uint16_t)code_value_long();
+                         printer_model_check(nPrinterModel);
+                         }
+                    else if(code_seen('Q'))
+                         SERIAL_PROTOCOLLN(nPrinterType);
+                    break;
+               case ClPrintChecking::_Smodel:     // ~ .3
+                    if(code_seen('P'))
+                         printer_smodel_check(strchr_pointer);
+                    else if(code_seen('Q'))
+                         SERIAL_PROTOCOLLNRPGM(sPrinterName);
+                    break;
+               case ClPrintChecking::_Version:    // ~ .4
+                    if(code_seen('P'))
+                         fw_version_check(++strchr_pointer);
+                    else if(code_seen('Q'))
+                         SERIAL_PROTOCOLLN(FW_VERSION);
+                    break;
+               case ClPrintChecking::_Gcode:      // ~ .5
+                    if(code_seen('P'))
+                         {
+                         uint16_t nGcodeLevel;
+                         nGcodeLevel=(uint16_t)code_value_long();
+                         gcode_level_check(nGcodeLevel);
+                         }
+                    else if(code_seen('Q'))
+                         SERIAL_PROTOCOLLN(GCODE_LEVEL);
+                    break;
+               }
+    break;
+
 #ifdef LIN_ADVANCE
     case 900: // M900: Set LIN_ADVANCE options.
         gcode_M900();
@@ -7741,10 +7804,7 @@ bool bInhibitFlag;
 //-//					if (degHotend0() > EXTRUDE_MINTEMP)
 if(0)
 					{
-						if ((eSoundMode == e_SOUND_MODE_LOUD) || (eSoundMode == e_SOUND_MODE_ONCE))
-							_tone(BEEPER, 1000);
-						delay_keep_alive(50);
-						_noTone(BEEPER);
+            Sound_MakeCustom(50,1000,false);
 						loading_flag = true;
 						enquecommand_front_P((PSTR("M701")));
 					}
@@ -8154,12 +8214,15 @@ static void wait_for_heater(long codenum, uint8_t extruder) {
 
 void check_babystep()
 {
-	int babystep_z;
-	EEPROM_read_B(EEPROM_BABYSTEP_Z, &babystep_z);
+	int babystep_z = eeprom_read_word(reinterpret_cast<uint16_t *>(&(EEPROM_Sheets_base->
+            s[(eeprom_read_byte(&(EEPROM_Sheets_base->active_sheet)))].z_offset)));
+
 	if ((babystep_z < Z_BABYSTEP_MIN) || (babystep_z > Z_BABYSTEP_MAX)) {
 		babystep_z = 0; //if babystep value is out of min max range, set it to 0
 		SERIAL_ECHOLNPGM("Z live adjust out of range. Setting to 0");
-		EEPROM_save_B(EEPROM_BABYSTEP_Z, &babystep_z);
+		eeprom_write_word(reinterpret_cast<uint16_t *>(&(EEPROM_Sheets_base->
+            s[(eeprom_read_byte(&(EEPROM_Sheets_base->active_sheet)))].z_offset)),
+                    babystep_z);
 		lcd_show_fullscreen_message_and_wait_P(PSTR("Z live adjust out of range. Setting to 0. Click to continue."));
 		lcd_update_enable(true);		
 	}	
@@ -9004,8 +9067,7 @@ ISR(INT4_vect) {
 	EIMSK &= ~(1 << 4); //disable INT4 interrupt to make sure that this code will be executed just once 
 	SERIAL_ECHOLNPGM("INT4");
     //fire normal uvlo only in case where EEPROM_UVLO is 0 or if IS_SD_PRINTING is 1. 
-    //Don't change || to && because in some case the printer can be moving although IS_SD_PRINTING is zero
-     if((IS_SD_PRINTING ) || (!(eeprom_read_byte((uint8_t*)EEPROM_UVLO)))) uvlo_();
+     if(PRINTER_ACTIVE && (!(eeprom_read_byte((uint8_t*)EEPROM_UVLO)))) uvlo_();
      if(eeprom_read_byte((uint8_t*)EEPROM_UVLO)) uvlo_tiny();
 }
 
@@ -9585,7 +9647,7 @@ void M600_wait_for_user(float HotendTempBckp) {
 			}
 			SET_OUTPUT(BEEPER);
 			if (counterBeep == 0) {
-				if((eSoundMode==e_SOUND_MODE_LOUD)||((eSoundMode==e_SOUND_MODE_ONCE)&&bFirst))
+				if((eSoundMode==e_SOUND_MODE_BLIND)|| (eSoundMode==e_SOUND_MODE_LOUD)||((eSoundMode==e_SOUND_MODE_ONCE)&&bFirst))
 				{
 					bFirst=false;
 					WRITE(BEEPER, HIGH);
@@ -9688,10 +9750,7 @@ void M600_load_filament() {
 #ifdef FILAMENT_SENSOR
 		if (fsensor_check_autoload())
 		{
-if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
-			_tone(BEEPER, 1000);
-			delay_keep_alive(50);
-			_noTone(BEEPER);
+      Sound_MakeCustom(50,1000,false);
 			break;
 		}
 #endif //FILAMENT_SENSOR
@@ -9707,10 +9766,7 @@ if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
 
 	M600_load_filament_movements();
 
-if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
-	_tone(BEEPER, 500);
-	delay_keep_alive(50);
-	_noTone(BEEPER);
+      Sound_MakeCustom(50,1000,false);
 
 #ifdef FSENSOR_QUALITY
 	fsensor_oq_meassure_stop();

+ 83 - 0
Firmware/eeprom.cpp

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

+ 44 - 22
Firmware/eeprom.h

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

+ 109 - 0
Firmware/heatbed_pwm.cpp

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

+ 1 - 4
Firmware/lcd.cpp

@@ -704,15 +704,12 @@ uint8_t lcd_clicked(void)
 
 void lcd_beeper_quick_feedback(void)
 {
-	SET_OUTPUT(BEEPER);
 //-//
 Sound_MakeSound(e_SOUND_TYPE_ButtonEcho);
 /*
 	for(int8_t i = 0; i < 10; i++)
 	{
-		WRITE(BEEPER,HIGH);
-		delayMicroseconds(100);
-		WRITE(BEEPER,LOW);
+		Sound_MakeCustom(100,0,false);
 		delayMicroseconds(100);
 	}
 */

+ 51 - 6
Firmware/menu.cpp

@@ -11,8 +11,7 @@
 #include "ultralcd.h"
 #include "language.h"
 #include "static_assert.h"
-
-
+#include "sound.h"
 
 extern int32_t lcd_encoder;
 
@@ -65,7 +64,11 @@ void menu_goto(menu_func_t menu, const uint32_t encoder, const bool feedback, bo
 void menu_start(void)
 {
     if (lcd_encoder > 0x8000) lcd_encoder = 0;
-    if (lcd_encoder < 0) lcd_encoder = 0;
+    if (lcd_encoder < 0)
+    {
+        lcd_encoder = 0;
+		Sound_MakeSound(e_SOUND_TYPE_BlindAlert);
+    }
     if (lcd_encoder < menu_top)
 		menu_top = lcd_encoder;
     menu_line = menu_top;
@@ -75,7 +78,10 @@ void menu_start(void)
 void menu_end(void)
 {
 	if (lcd_encoder >= menu_item)
+	{
 		lcd_encoder = menu_item - 1;
+		Sound_MakeSound(e_SOUND_TYPE_BlindAlert);
+	}
 	if (((uint8_t)lcd_encoder) >= menu_top + LCD_HEIGHT)
 	{
 		menu_top = lcd_encoder - LCD_HEIGHT + 1;
@@ -168,16 +174,40 @@ int menu_draw_item_printf_P(char type_char, const char* format, ...)
 }
 */
 
+static char menu_selection_mark(){
+	return (lcd_encoder == menu_item)?'>':' ';
+}
+
 static void menu_draw_item_puts_P(char type_char, const char* str)
 {
     lcd_set_cursor(0, menu_row);
-    lcd_printf_P(PSTR("%c%-18.18S%c"), (lcd_encoder == menu_item)?'>':' ', str, type_char);
+    lcd_printf_P(PSTR("%c%-18.18S%c"), menu_selection_mark(), str, type_char);
+}
+
+//! @brief Format sheet name
+//!
+//! @param[in] sheet_E Sheet in EEPROM
+//! @param[out] buffer for formatted output
+void menu_format_sheet_E(const Sheet &sheet_E, SheetFormatBuffer &buffer)
+{
+    uint_least8_t index = sprintf_P(buffer.c, PSTR("%.10S "), _T(MSG_SHEET));
+    eeprom_read_block(&(buffer.c[index]), sheet_E.name, 7);
+    //index += 7;
+    buffer.c[index + 7] = '\0';
+}
+
+static void menu_draw_item_puts_E(char type_char, const Sheet &sheet)
+{
+    lcd_set_cursor(0, menu_row);
+    SheetFormatBuffer buffer;
+    menu_format_sheet_E(sheet, buffer);
+    lcd_printf_P(PSTR("%c%-18.18s%c"), menu_selection_mark(), buffer.c, type_char);
 }
 
 static void menu_draw_item_puts_P(char type_char, const char* str, char num)
 {
     lcd_set_cursor(0, menu_row);
-    lcd_printf_P(PSTR("%c%-.16S "), (lcd_encoder == menu_item)?'>':' ', str);
+    lcd_printf_P(PSTR("%c%-.16S "), menu_selection_mark(), str);
     lcd_putc(num);
     lcd_set_cursor(19, menu_row);
     lcd_putc(type_char);
@@ -224,6 +254,21 @@ uint8_t menu_item_submenu_P(const char* str, menu_func_t submenu)
 	return 0;
 }
 
+uint8_t menu_item_submenu_E(const Sheet &sheet, menu_func_t submenu)
+{
+    if (menu_item == menu_line)
+    {
+        if (lcd_draw_update) menu_draw_item_puts_E(LCD_STR_ARROW_RIGHT[0], sheet);
+        if (menu_clicked && (lcd_encoder == menu_item))
+        {
+            menu_submenu(submenu);
+            return menu_item_ret();
+        }
+    }
+    menu_item++;
+    return 0;
+}
+
 uint8_t menu_item_back_P(const char* str)
 {
 	if (menu_item == menu_line)
@@ -399,7 +444,7 @@ uint8_t menu_item_edit_P(const char* str, T pval, int16_t min_val, int16_t max_v
 		if (lcd_draw_update) 
 		{
 			lcd_set_cursor(0, menu_row);
-			menu_draw_P<T>((lcd_encoder == menu_item)?'>':' ', str, *pval);
+			menu_draw_P<T>(menu_selection_mark(), str, *pval);
 		}
 		if (menu_clicked && (lcd_encoder == menu_item))
 		{

+ 12 - 0
Firmware/menu.h

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

+ 3 - 2
Firmware/mesh_bed_calibration.cpp

@@ -3031,7 +3031,8 @@ void babystep_load()
         check_babystep(); //checking if babystep is in allowed range, otherwise setting babystep to 0
         
         // End of G80: Apply the baby stepping value.
-        EEPROM_read_B(EEPROM_BABYSTEP_Z, &babystepLoadZ);
+        babystepLoadZ = eeprom_read_word(reinterpret_cast<uint16_t *>(&(EEPROM_Sheets_base->
+                    s[(eeprom_read_byte(&(EEPROM_Sheets_base->active_sheet)))].z_offset)));
                             
     #if 0
         SERIAL_ECHO("Z baby step: ");
@@ -3186,4 +3187,4 @@ void mbl_interpolation(uint8_t meas_points) {
 			}
 		}
 	}
-}
+}

+ 3 - 1
Firmware/messages.c

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

+ 2 - 0
Firmware/messages.h

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

+ 71 - 15
Firmware/mmu.cpp

@@ -15,6 +15,8 @@
 #include <avr/pgmspace.h>
 #include "io_atmega2560.h"
 #include "AutoDeplete.h"
+//-//
+#include "util.h"
 
 #ifdef TMC2130
 #include "tmc2130.h"
@@ -81,9 +83,11 @@ uint16_t mmu_power_failures = 0;
 
 
 #ifdef MMU_DEBUG
+static const auto DEBUG_PUTCHAR = putchar;
 static const auto DEBUG_PUTS_P = puts_P;
 static const auto DEBUG_PRINTF_P = printf_P;
 #else //MMU_DEBUG
+#define DEBUG_PUTCHAR(c)
 #define DEBUG_PUTS_P(str)
 #define DEBUG_PRINTF_P( __fmt, ... )
 #endif //MMU_DEBUG
@@ -263,6 +267,9 @@ void mmu_loop(void)
 			FDEBUG_PRINTF_P(PSTR("MMU => '%dok'\n"), mmu_finda);
 			puts_P(PSTR("MMU - ENABLED"));
 			mmu_enabled = true;
+            //-//
+            // ... PrinterType/Name
+            fSetMmuMode(true);
 			mmu_state = S::Idle;
 		}
 		return;
@@ -831,7 +838,7 @@ void mmu_M600_wait_and_beep() {
 			}
 			SET_OUTPUT(BEEPER);
 			if (counterBeep == 0) {
-				if((eSoundMode==e_SOUND_MODE_LOUD)||((eSoundMode==e_SOUND_MODE_ONCE)&&bFirst))
+				if((eSoundMode==e_SOUND_MODE_BLIND)|| (eSoundMode==e_SOUND_MODE_LOUD)||((eSoundMode==e_SOUND_MODE_ONCE)&&bFirst))
 				{
 					bFirst=false;
 					WRITE(BEEPER, HIGH);
@@ -1447,26 +1454,69 @@ bFilamentAction=false;                            // NOT in "mmu_fil_eject_menu(
 	}
 }
 
+//! @brief Fits filament tip into heatbreak?
+//!
+//! If PTFE tube is jammed, this causes filament to be unloaded and no longer
+//! being detected by the pulley IR sensor.
+//! @retval true Fits
+//! @retval false Doesn't fit
+static bool can_load()
+{
+    current_position[E_AXIS] += 60;
+    plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS],
+            current_position[E_AXIS], MMU_LOAD_FEEDRATE, active_extruder);
+    current_position[E_AXIS] -= 52;
+    plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS],
+            current_position[E_AXIS], MMU_LOAD_FEEDRATE, active_extruder);
+    st_synchronize();
+
+    uint_least8_t filament_detected_count = 0;
+    const float e_increment = 0.2;
+    const uint_least8_t steps = 6.0 / e_increment;
+    DEBUG_PUTS_P(PSTR("MMU can_load:"));
+    for(uint_least8_t i = 0; i < steps; ++i)
+    {
+        current_position[E_AXIS] -= e_increment;
+        plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS],
+                current_position[E_AXIS], MMU_LOAD_FEEDRATE, active_extruder);
+        st_synchronize();
+        if(0 == PIN_GET(IR_SENSOR_PIN))
+        {
+            ++filament_detected_count;
+            DEBUG_PUTCHAR('O');
+        }
+        else
+        {
+            DEBUG_PUTCHAR('o');
+        }
+    }
+    if (filament_detected_count > steps - 4)
+    {
+        DEBUG_PUTS_P(PSTR(" succeeded."));
+        return true;
+    }
+    else
+    {
+        DEBUG_PUTS_P(PSTR(" failed."));
+        return false;
+    }
+}
+
 //! @brief load more
 //!
 //! Try to feed more filament from MMU if it is not detected by filament sensor.
-//! Move filament back and forth to nozzle in order to detect jam.
-//! If PTFE tube is jammed, this cause filament to be unloaded and no longer
-//! detected by pulley IR sensor in next step.
-static void load_more()
+//! @retval true Success, filament detected by IR sensor
+//! @retval false Failed, filament not detected by IR sensor after maximum number of attempts
+static bool load_more()
 {
     for (uint8_t i = 0; i < MMU_IDLER_SENSOR_ATTEMPTS_NR; i++)
     {
-        if (PIN_GET(IR_SENSOR_PIN) == 0) break;
+        if (PIN_GET(IR_SENSOR_PIN) == 0) return true;
         DEBUG_PRINTF_P(PSTR("Additional load attempt nr. %d\n"), i);
         mmu_command(MmuCmd::C0);
         manage_response(true, true, MMU_LOAD_MOVE);
     }
-    current_position[E_AXIS] += 60;
-    plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], MMU_LOAD_FEEDRATE, active_extruder);
-    current_position[E_AXIS] -= 58;
-    plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], MMU_LOAD_FEEDRATE, active_extruder);
-    st_synchronize();
+    return false;
 }
 
 static void increment_load_fail()
@@ -1507,7 +1557,8 @@ void mmu_continue_loading(bool blocking)
 	    return;
 	}
 
-    load_more();
+    bool success = load_more();
+    if (success) success = can_load();
 
     enum class Ls : uint_least8_t
     {
@@ -1517,7 +1568,10 @@ void mmu_continue_loading(bool blocking)
     };
     Ls state = Ls::Enter;
 
-    while (PIN_GET(IR_SENSOR_PIN) != 0)
+    const uint_least8_t max_retry = 2;
+    uint_least8_t retry = 0;
+
+    while (!success)
     {
         switch (state)
         {
@@ -1534,8 +1588,10 @@ void mmu_continue_loading(bool blocking)
 #endif //MMU_HAS_CUTTER
             mmu_command(MmuCmd::T0 + tmp_extruder);
             manage_response(true, true, MMU_TCODE_MOVE);
-            load_more();
-            state = Ls::Unload;
+            success = load_more();
+            if (success) success = can_load();
+            ++retry; // overflow not handled, as it is not dangerous.
+            if (retry >= max_retry) state = Ls::Unload;
             break;
         case Ls::Unload:
             stop_and_save_print_to_ram(0, 0);

+ 33 - 9
Firmware/printers.h

@@ -3,14 +3,38 @@
 
 #define PRINTER_UNKNOWN 0
 
-#define PRINTER_MK1         100
-#define PRINTER_MK2         200
-#define PRINTER_MK2_SNMM    201
-#define PRINTER_MK25        250
-#define PRINTER_MK25_SNMM   251
-#define PRINTER_MK25S		252
-#define PRINTER_MK3         300
-#define PRINTER_MK3_SNMM    301
-#define PRINTER_MK3S		302
+// *** MK1
+#define PRINTER_MK1	               100
+#define PRINTER_MK1_NAME           "MK1"
+// *** MK2
+#define PRINTER_MK2	               200
+#define PRINTER_MK2_NAME           "MK2"
+#define PRINTER_MK2_SNMM           201            // better is "10200"
+#define PRINTER_MK2_SNMM_NAME      "MK2MM"        // better is "MK2MMU1"
+// *** MK2S ??? is same as "MK2" ???
+#define PRINTER_MK2S	          202
+#define PRINTER_MK2S_NAME          "MK2S"
+#define PRINTER_MK2S_SNMM          203            // better is "10202"
+#define PRINTER_MK2S_SNMM_NAME     "MK2SMM"       // better is "MK2SMMU1"
+// *** MK2.5
+#define PRINTER_MK25	          250
+#define PRINTER_MK25_NAME          "MK2.5"
+#define PRINTER_MK25_MMU2          20250
+#define PRINTER_MK25_MMU2_NAME     "MK2.5MMU2"
+// *** MK2.5S
+#define PRINTER_MK25S	     	252
+#define PRINTER_MK25S_NAME         "MK2.5S"
+#define PRINTER_MK25S_MMU2         20252
+#define PRINTER_MK25S_MMU2_NAME    "MK2.5SMMU2S"
+// *** MK3
+#define PRINTER_MK3                300
+#define PRINTER_MK3_NAME           "MK3"
+#define PRINTER_MK3_MMU2           20300
+#define PRINTER_MK3_MMU2_NAME      "MK3MMU2"
+// *** MK3S
+#define PRINTER_MK3S     		302
+#define PRINTER_MK3S_NAME          "MK3S"
+#define PRINTER_MK3S_MMU2          20302
+#define PRINTER_MK3S_MMU2_NAME     "MK3SMMU2S"
 
 #endif //PRINTERS_H

+ 70 - 9
Firmware/sound.cpp

@@ -17,7 +17,8 @@ static void Sound_SaveMode(void);
 static void Sound_DoSound_Echo(void);
 static void Sound_DoSound_Prompt(void);
 static void Sound_DoSound_Alert(bool bOnce);
-
+static void Sound_DoSound_Encoder_Move(void);
+static void Sound_DoSound_Blind_Alert(void);
 
 void Sound_Init(void)
 {
@@ -49,9 +50,9 @@ switch(eSoundMode)
           eSoundMode=e_SOUND_MODE_SILENT;
           break;
      case e_SOUND_MODE_SILENT:
-          eSoundMode=e_SOUND_MODE_MUTE;
+          eSoundMode=e_SOUND_MODE_BLIND;
           break;
-     case e_SOUND_MODE_MUTE:
+     case e_SOUND_MODE_BLIND:
           eSoundMode=e_SOUND_MODE_LOUD;
           break;
      default:
@@ -60,6 +61,36 @@ switch(eSoundMode)
 Sound_SaveMode();
 }
 
+void Sound_MakeCustom(uint16_t ms,uint16_t tone_,bool critical){
+     if (!critical){
+          if (eSoundMode != e_SOUND_MODE_SILENT){
+               if(!tone_){
+                    WRITE(BEEPER, HIGH);
+                    delayMicroseconds(ms);
+                    WRITE(BEEPER, LOW);
+               }
+               else{
+                    _tone(BEEPER, tone_);
+                    delayMicroseconds(ms);
+                    _noTone(BEEPER);
+               }
+          }
+     }
+     else{
+          if(!tone_){
+               WRITE(BEEPER, HIGH);
+               delayMicroseconds(ms);
+               WRITE(BEEPER, LOW);
+               delayMicroseconds(100);
+          }
+          else{
+               _tone(BEEPER, tone_);
+               delayMicroseconds(ms);
+               _noTone(BEEPER);
+          }
+     }
+}
+
 void Sound_MakeSound(eSOUND_TYPE eSoundType)
 {
 switch(eSoundMode)
@@ -84,13 +115,43 @@ switch(eSoundMode)
           if(eSoundType==e_SOUND_TYPE_StandardAlert)
                Sound_DoSound_Alert(true);
           break;
-     case e_SOUND_MODE_MUTE:
-          break;
+     case e_SOUND_MODE_BLIND:
+          if(eSoundType==e_SOUND_TYPE_ButtonEcho)
+               Sound_DoSound_Echo();
+          if(eSoundType==e_SOUND_TYPE_StandardPrompt)
+               Sound_DoSound_Prompt();
+          if(eSoundType==e_SOUND_TYPE_StandardAlert)
+               Sound_DoSound_Alert(false);
+          if(eSoundType==e_SOUND_TYPE_EncoderMove)
+               Sound_DoSound_Encoder_Move();
+          if(eSoundType==e_SOUND_TYPE_BlindAlert)
+               Sound_DoSound_Blind_Alert();
+               break;
      default:
-          ;
+          break;
      }
 }
 
+static void Sound_DoSound_Blind_Alert(void)
+{
+     _tone(BEEPER,100);
+     delayMicroseconds(50);
+     _noTone(BEEPER);
+     delayMicroseconds(200);
+}
+
+ static void Sound_DoSound_Encoder_Move(void)
+{
+uint8_t nI;
+
+ for(nI=0;nI<5;nI++)
+     {
+     WRITE(BEEPER,HIGH);
+     delayMicroseconds(75);
+     WRITE(BEEPER,LOW);
+     delayMicroseconds(75);
+     }
+}
 
 static void Sound_DoSound_Echo(void)
 {
@@ -108,7 +169,7 @@ for(nI=0;nI<10;nI++)
 static void Sound_DoSound_Prompt(void)
 {
 WRITE(BEEPER,HIGH);
-delay_keep_alive(500);
+delayMicroseconds(500);
 WRITE(BEEPER,LOW);
 }
 
@@ -120,8 +181,8 @@ nMax=bOnce?1:3;
 for(nI=0;nI<nMax;nI++)
      {
      WRITE(BEEPER,HIGH);
-     delay_keep_alive(200);
+     delayMicroseconds(200);
      WRITE(BEEPER,LOW);
-     delay_keep_alive(500);
+     delayMicroseconds(500);
      }
 }

+ 5 - 3
Firmware/sound.h

@@ -1,3 +1,4 @@
+#include <stdint.h>
 #ifndef SOUND_H
 #define SOUND_H
 
@@ -5,16 +6,16 @@
 #define MSG_SOUND_MODE_LOUD "Sound      [loud]"
 #define MSG_SOUND_MODE_ONCE "Sound      [once]"
 #define MSG_SOUND_MODE_SILENT "Sound    [silent]"
-#define MSG_SOUND_MODE_MUTE "Sound      [mute]"
+#define MSG_SOUND_MODE_BLIND "Sound      [blind]" 
 
 
 #define e_SOUND_MODE_NULL 0xFF
 typedef enum
-     {e_SOUND_MODE_LOUD,e_SOUND_MODE_ONCE,e_SOUND_MODE_SILENT,e_SOUND_MODE_MUTE} eSOUND_MODE;
+     {e_SOUND_MODE_LOUD,e_SOUND_MODE_ONCE,e_SOUND_MODE_SILENT,e_SOUND_MODE_BLIND} eSOUND_MODE;
 #define e_SOUND_MODE_DEFAULT e_SOUND_MODE_LOUD
 
 typedef enum
-     {e_SOUND_TYPE_ButtonEcho,e_SOUND_TYPE_EncoderEcho,e_SOUND_TYPE_StandardPrompt,e_SOUND_TYPE_StandardConfirm,e_SOUND_TYPE_StandardWarning,e_SOUND_TYPE_StandardAlert} eSOUND_TYPE;
+     {e_SOUND_TYPE_ButtonEcho,e_SOUND_TYPE_EncoderEcho,e_SOUND_TYPE_StandardPrompt,e_SOUND_TYPE_StandardConfirm,e_SOUND_TYPE_StandardWarning,e_SOUND_TYPE_StandardAlert,e_SOUND_TYPE_EncoderMove,e_SOUND_TYPE_BlindAlert} eSOUND_TYPE;
 typedef enum
      {e_SOUND_CLASS_Echo,e_SOUND_CLASS_Prompt,e_SOUND_CLASS_Confirm,e_SOUND_CLASS_Warning,e_SOUND_CLASS_Alert} eSOUND_CLASS;
 
@@ -27,6 +28,7 @@ extern void Sound_Default(void);
 extern void Sound_Save(void);
 extern void Sound_CycleState(void);
 extern void Sound_MakeSound(eSOUND_TYPE eSoundType);
+extern void Sound_MakeCustom(uint16_t ms,uint16_t tone_ ,bool critical);
 
 //static void Sound_DoSound_Echo(void);
 //static void Sound_DoSound_Prompt(void);

+ 6 - 3
Firmware/system_timer.h

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

+ 33 - 38
Firmware/temperature.cpp

@@ -44,8 +44,6 @@
 #include "Timer.h"
 #include "Configuration_prusa.h"
 
-
-
 //===========================================================================
 //=============================public variables============================
 //===========================================================================
@@ -535,12 +533,7 @@ void checkFanSpeed()
 static void fanSpeedErrorBeep(const char *serialMsg, const char *lcdMsg){
 	SERIAL_ECHOLNRPGM(serialMsg);
 	if (get_message_level() == 0) {
-		if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE)||(eSoundMode==e_SOUND_MODE_SILENT)){
-			WRITE(BEEPER, HIGH);
-			delayMicroseconds(200);
-			WRITE(BEEPER, LOW);
-			delayMicroseconds(100); // what is this wait for?
-		}
+		Sound_MakeCustom(200,0,true);
 		LCD_ALERTMESSAGERPGM(lcdMsg);
 	}
 }
@@ -1130,18 +1123,9 @@ void tp_init()
 
   adc_init();
 
-#ifdef SYSTEM_TIMER_2
-  timer02_init();
+  timer0_init();
   OCR2B = 128;
   TIMSK2 |= (1<<OCIE2B);  
-#else //SYSTEM_TIMER_2
-  // Use timer0 for temperature measurement
-  // Interleave temperature interrupt with millies interrupt
-  OCR0B = 128;
-  TIMSK0 |= (1<<OCIE0B);  
-#endif //SYSTEM_TIMER_2
-
-
   
   // Wait for temperature measurement to settle
   _delay(250);
@@ -1406,13 +1390,9 @@ void temp_runaway_stop(bool isPreheat, bool isBed)
 	disable_e2();
 	manage_heater();
 	lcd_update(0);
-if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE)||(eSoundMode==e_SOUND_MODE_SILENT))
-	WRITE(BEEPER, HIGH);
-	delayMicroseconds(500);
-	WRITE(BEEPER, LOW);
-	delayMicroseconds(100);
-
-	if (isPreheat)
+  Sound_MakeCustom(200,0,true);
+	
+  if (isPreheat)
 	{
 		Stop();
 		isBed ? LCD_ALERTMESSAGEPGM("BED PREHEAT ERROR") : LCD_ALERTMESSAGEPGM("PREHEAT ERROR");
@@ -1472,8 +1452,8 @@ void disable_heater()
     target_temperature_bed=0;
     soft_pwm_bed=0;
 	timer02_set_pwm0(soft_pwm_bed << 1);
-    #if defined(HEATER_BED_PIN) && HEATER_BED_PIN > -1  
-      WRITE(HEATER_BED_PIN,LOW);
+    #if defined(HEATER_BED_PIN) && HEATER_BED_PIN > -1
+      //WRITE(HEATER_BED_PIN,LOW);
     #endif
   #endif 
 }
@@ -1506,7 +1486,6 @@ void max_temp_error(uint8_t e) {
     SET_OUTPUT(BEEPER);
     WRITE(FAN_PIN, 1);
     WRITE(EXTRUDER_0_AUTO_FAN_PIN, 1);
-if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE)||(eSoundMode==e_SOUND_MODE_SILENT))
     WRITE(BEEPER, 1);
     // fanSpeed will consumed by the check_axes_activity() routine.
     fanSpeed=255;
@@ -1544,7 +1523,7 @@ void min_temp_error(uint8_t e) {
 
 void bed_max_temp_error(void) {
 #if HEATER_BED_PIN > -1
-  WRITE(HEATER_BED_PIN, 0);
+  //WRITE(HEATER_BED_PIN, 0);
 #endif
   if(IsStopped() == false) {
     SERIAL_ERROR_START;
@@ -1563,7 +1542,7 @@ void bed_min_temp_error(void) {
 #endif
 //if (current_temperature_ambient < MINTEMP_MINAMBIENT) return;
 #if HEATER_BED_PIN > -1
-    WRITE(HEATER_BED_PIN, 0);
+    //WRITE(HEATER_BED_PIN, 0);
 #endif
 	static const char err[] PROGMEM = "Err: MINTEMP BED";
     if(IsStopped() == false) {
@@ -1660,7 +1639,6 @@ void adc_ready(void) //callback from adc when sampling finished
 
 } // extern "C"
 
-
 // Timer2 (originaly timer0) is shared with millies
 #ifdef SYSTEM_TIMER_2
 ISR(TIMER2_COMPB_vect)
@@ -1676,8 +1654,8 @@ ISR(TIMER0_COMPB_vect)
 	if (!temp_meas_ready) adc_cycle();
 	lcd_buttons_update();
 
-  static unsigned char pwm_count = (1 << SOFT_PWM_SCALE);
-  static unsigned char soft_pwm_0;
+  static uint8_t pwm_count = (1 << SOFT_PWM_SCALE);
+  static uint8_t soft_pwm_0;
 #ifdef SLOW_PWM_HEATERS
   static unsigned char slow_pwm_count = 0;
   static unsigned char state_heater_0 = 0;
@@ -1698,7 +1676,7 @@ ISR(TIMER0_COMPB_vect)
 #endif 
 #endif
 #if HEATER_BED_PIN > -1
-  static unsigned char soft_pwm_b;
+  // @@DR static unsigned char soft_pwm_b;
 #ifdef SLOW_PWM_HEATERS
   static unsigned char state_heater_b = 0;
   static unsigned char state_timer_heater_b = 0;
@@ -1733,14 +1711,25 @@ ISR(TIMER0_COMPB_vect)
 #endif
   }
 #if defined(HEATER_BED_PIN) && HEATER_BED_PIN > -1
+  
+#if 0  // @@DR vypnuto pro hw pwm bedu
+  // tuhle prasarnu bude potreba poustet ve stanovenych intervalech, jinak nemam moc sanci zareagovat
+  // teoreticky by se tato cast uz vubec nemusela poustet
   if ((pwm_count & ((1 << HEATER_BED_SOFT_PWM_BITS) - 1)) == 0)
   {
     soft_pwm_b = soft_pwm_bed >> (7 - HEATER_BED_SOFT_PWM_BITS);
-#ifndef SYSTEM_TIMER_2
-	if(soft_pwm_b > 0) WRITE(HEATER_BED_PIN,1); else WRITE(HEATER_BED_PIN,0);
-#endif //SYSTEM_TIMER_2
+#  ifndef SYSTEM_TIMER_2
+	// tady budu krokovat pomalou frekvenci na automatu - tohle je rizeni spinani a rozepinani
+	// jako ridici frekvenci mam 2khz, jako vystupni frekvenci mam 30hz
+	// 2kHz jsou ovsem ve slysitelnem pasmu, mozna bude potreba jit s frekvenci nahoru (a tomu taky prizpusobit ostatni veci)
+	// Teoreticky bych mohl stahnout OCR0B citac na 6, cimz bych se dostal nekam ke 40khz a tady potom honit PWM rychleji nebo i pomaleji
+	// to nicemu nevadi. Soft PWM scale by se 20x zvetsilo (no dobre, 16x), cimz by se to posunulo k puvodnimu 30Hz PWM
+	//if(soft_pwm_b > 0) WRITE(HEATER_BED_PIN,1); else WRITE(HEATER_BED_PIN,0);
+#  endif //SYSTEM_TIMER_2
   }
 #endif
+#endif
+  
 #ifdef FAN_SOFT_PWM
   if ((pwm_count & ((1 << FAN_SOFT_PWM_BITS) - 1)) == 0)
   {
@@ -1762,8 +1751,14 @@ ISR(TIMER0_COMPB_vect)
 #if EXTRUDERS > 2
   if(soft_pwm_2 < pwm_count) WRITE(HEATER_2_PIN,0);
 #endif
+
+#if 0 // @@DR  
 #if defined(HEATER_BED_PIN) && HEATER_BED_PIN > -1
-  if (soft_pwm_b < (pwm_count & ((1 << HEATER_BED_SOFT_PWM_BITS) - 1))) WRITE(HEATER_BED_PIN,0);
+  if (soft_pwm_b < (pwm_count & ((1 << HEATER_BED_SOFT_PWM_BITS) - 1))){
+	  //WRITE(HEATER_BED_PIN,0);
+  }
+  //WRITE(HEATER_BED_PIN, pwm_count & 1 );
+#endif
 #endif
 #ifdef FAN_SOFT_PWM
   if (soft_pwm_fan < (pwm_count & ((1 << FAN_SOFT_PWM_BITS) - 1))) WRITE(FAN_PIN,0);

+ 15 - 41
Firmware/timer02.c

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

+ 8 - 7
Firmware/timer02.h

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

+ 353 - 144
Firmware/ultralcd.cpp

@@ -307,6 +307,7 @@ bool wait_for_unclick;
 #endif
 
 bool bMain;                                       // flag (i.e. 'fake parameter') for 'lcd_sdcard_menu()' function
+bool bSettings;                                   // flag (i.e. 'fake parameter') for 'lcd_checkink_menu()' function
 
 
 
@@ -988,6 +989,8 @@ static void lcd_status_screen()
 			{
 			case 8:
 				prusa_statistics(21);
+				if(loading_flag)
+					prusa_statistics(22);
 				break;
 			case 5:
 				if (IS_SD_PRINTING)
@@ -2683,10 +2686,12 @@ void lcd_alright() {
 
         if (cursor_pos > 3) {
           cursor_pos = 3;
+					Sound_MakeSound(e_SOUND_TYPE_BlindAlert);
         }
 
         if (cursor_pos < 1) {
           cursor_pos = 1;
+					Sound_MakeSound(e_SOUND_TYPE_BlindAlert);
         }
         lcd_set_cursor(0, 1);
         lcd_print(" ");
@@ -2697,6 +2702,7 @@ void lcd_alright() {
         lcd_set_cursor(0, cursor_pos);
         lcd_print(">");
         enc_dif = lcd_encoder_diff;
+				Sound_MakeSound(e_SOUND_TYPE_EncoderMove);
         _delay(100);
       }
 
@@ -2704,7 +2710,7 @@ void lcd_alright() {
 
 
     if (lcd_clicked()) {
-
+			Sound_MakeSound(e_SOUND_TYPE_ButtonEcho);
       lcd_change_fil_state = cursor_pos;
       _delay(500);
 
@@ -3066,13 +3072,13 @@ static void lcd_move_z() {
  * other value leads to storing Z_AXIS
  * @param msg text to be displayed
  */
-static void _lcd_babystep(int axis, const char *msg) 
+static void lcd_babystep_z()
 {
 	typedef struct
-	{	// 19bytes total
-		int8_t status;                 // 1byte
-		int babystepMem[3];            // 6bytes
-		float babystepMemMM[3];        // 12bytes
+	{
+		int8_t status;
+		int16_t babystepMemZ;
+		float babystepMemMMZ;
 	} _menu_data_t;
 	static_assert(sizeof(menu_data)>= sizeof(_menu_data_t),"_menu_data_t doesn't fit into menu_data");
 	_menu_data_t* _md = (_menu_data_t*)&(menu_data[0]);
@@ -3082,18 +3088,20 @@ static void _lcd_babystep(int axis, const char *msg)
 		// Initialize its status.
 		_md->status = 1;
 		check_babystep();
-
-		EEPROM_read_B(EEPROM_BABYSTEP_X, &_md->babystepMem[0]);
-		EEPROM_read_B(EEPROM_BABYSTEP_Y, &_md->babystepMem[1]);
-		EEPROM_read_B(EEPROM_BABYSTEP_Z, &_md->babystepMem[2]);
+		
+		if(!is_sheet_initialized()){
+			_md->babystepMemZ = 0;
+		}
+		else{
+			_md->babystepMemZ = eeprom_read_word(reinterpret_cast<uint16_t *>(&(EEPROM_Sheets_base->
+					s[(eeprom_read_byte(&(EEPROM_Sheets_base->active_sheet)))].z_offset)));
+		}
 
 		// same logic as in babystep_load
 	    if (calibration_status() >= CALIBRATION_STATUS_LIVE_ADJUST)
-			_md->babystepMem[2] = 0;
+			_md->babystepMemZ = 0;
 
-		_md->babystepMemMM[0] = _md->babystepMem[0]/cs.axis_steps_per_unit[X_AXIS];
-		_md->babystepMemMM[1] = _md->babystepMem[1]/cs.axis_steps_per_unit[Y_AXIS];
-		_md->babystepMemMM[2] = _md->babystepMem[2]/cs.axis_steps_per_unit[Z_AXIS];
+		_md->babystepMemMMZ = _md->babystepMemZ/cs.axis_steps_per_unit[Z_AXIS];
 		lcd_draw_update = 1;
 		//SERIAL_ECHO("Z baby step: ");
 		//SERIAL_ECHO(_md->babystepMem[2]);
@@ -3104,46 +3112,49 @@ static void _lcd_babystep(int axis, const char *msg)
 	if (lcd_encoder != 0) 
 	{
 		if (homing_flag) lcd_encoder = 0;
-		_md->babystepMem[axis] += (int)lcd_encoder;
-		if (axis == 2)
-		{
-			if (_md->babystepMem[axis] < Z_BABYSTEP_MIN) _md->babystepMem[axis] = Z_BABYSTEP_MIN; //-3999 -> -9.99 mm
-			else if (_md->babystepMem[axis] > Z_BABYSTEP_MAX) _md->babystepMem[axis] = Z_BABYSTEP_MAX; //0
-			else
-			{
-				CRITICAL_SECTION_START
-				babystepsTodo[axis] += (int)lcd_encoder;
-				CRITICAL_SECTION_END		
-			}
-		}
-		_md->babystepMemMM[axis] = _md->babystepMem[axis]/cs.axis_steps_per_unit[axis]; 
+		_md->babystepMemZ += (int)lcd_encoder;
+
+        if (_md->babystepMemZ < Z_BABYSTEP_MIN) _md->babystepMemZ = Z_BABYSTEP_MIN; //-3999 -> -9.99 mm
+        else if (_md->babystepMemZ > Z_BABYSTEP_MAX) _md->babystepMemZ = Z_BABYSTEP_MAX; //0
+        else
+        {
+            CRITICAL_SECTION_START
+            babystepsTodo[Z_AXIS] += (int)lcd_encoder;
+            CRITICAL_SECTION_END
+        }
+
+		_md->babystepMemMMZ = _md->babystepMemZ/cs.axis_steps_per_unit[Z_AXIS];
 		_delay(50);
 		lcd_encoder = 0;
 		lcd_draw_update = 1;
 	}
 	if (lcd_draw_update)
 	{
+	    SheetFormatBuffer buffer;
+	    menu_format_sheet_E(EEPROM_Sheets_base->s[(eeprom_read_byte(&(EEPROM_Sheets_base->active_sheet)))], buffer);
+	    lcd_set_cursor(0, 0);
+	    lcd_print(buffer.c);
 	    lcd_set_cursor(0, 1);
-		menu_draw_float13(msg, _md->babystepMemMM[axis]);
+		menu_draw_float13(_i("Adjusting Z:"), _md->babystepMemMMZ); ////MSG_BABYSTEPPING_Z c=15 Beware: must include the ':' as its last character
 	}
 	if (LCD_CLICKED || menu_leaving)
 	{
 		// Only update the EEPROM when leaving the menu.
-		EEPROM_save_B(
-		(axis == X_AXIS) ? EEPROM_BABYSTEP_X : ((axis == Y_AXIS) ? EEPROM_BABYSTEP_Y : EEPROM_BABYSTEP_Z),
-		&_md->babystepMem[axis]);
-		if(Z_AXIS == axis) calibration_status_store(CALIBRATION_STATUS_CALIBRATED);
+		eeprom_update_word(reinterpret_cast<uint16_t *>(&(EEPROM_Sheets_base->
+                s[(eeprom_read_byte(&(EEPROM_Sheets_base->active_sheet)))].z_offset)),
+		        _md->babystepMemZ);
+		eeprom_update_byte(&(EEPROM_Sheets_base->s[(eeprom_read_byte(
+		        &(EEPROM_Sheets_base->active_sheet)))].bed_temp),
+		        target_temperature_bed);
+		eeprom_update_byte(&(EEPROM_Sheets_base->s[(eeprom_read_byte(
+		        &(EEPROM_Sheets_base->active_sheet)))].pinda_temp),
+		        current_temperature_pinda);
+		calibration_status_store(CALIBRATION_STATUS_CALIBRATED);
 	}
 	if (LCD_CLICKED) menu_back();
 }
 
 
-static void lcd_babystep_z()
-{
-	_lcd_babystep(Z_AXIS, (_i("Adjusting Z:")));////MSG_BABYSTEPPING_Z c=15 Beware: must include the ':' as its last character
-}
-
-
 typedef struct
 {	// 12bytes + 9bytes = 21bytes total
     menu_data_edit_t reserved; //12 bytes reserved for number editing functions
@@ -3664,20 +3675,24 @@ int8_t lcd_show_multiscreen_message_two_choices_and_wait_P(const char *msg, bool
 						lcd_set_cursor(7, 3);
 						lcd_puts_P((PSTR(">")));
 						yes = false;
+						Sound_MakeSound(e_SOUND_TYPE_EncoderMove);
 					}
 					else if (enc_dif > lcd_encoder_diff && !yes) {
 						lcd_puts_P((PSTR(">")));
 						lcd_set_cursor(7, 3);
 						lcd_puts_P((PSTR(" ")));
 						yes = true;
+						Sound_MakeSound(e_SOUND_TYPE_EncoderMove);
 					}
 					enc_dif = lcd_encoder_diff;
 				}
 				else {
+					Sound_MakeSound(e_SOUND_TYPE_BlindAlert);
 					break; //turning knob skips waiting loop
 				}
 			}
 			if (lcd_clicked()) {
+				Sound_MakeSound(e_SOUND_TYPE_ButtonEcho);
 				if (msg_next == NULL) {
 					//KEEPALIVE_STATE(IN_HANDLER);
 					lcd_set_custom_characters();
@@ -3750,16 +3765,20 @@ int8_t lcd_show_fullscreen_message_yes_no_and_wait_P(const char *msg, bool allow
 					lcd_set_cursor(0, 3);
 					lcd_puts_P((PSTR(">")));
 					yes = false;
+					Sound_MakeSound(e_SOUND_TYPE_EncoderMove);
+
 				}
 				else if (enc_dif > lcd_encoder_diff && !yes) {
 					lcd_puts_P((PSTR(">")));
 					lcd_set_cursor(0, 3);
 					lcd_puts_P((PSTR(" ")));
 					yes = true;
+					Sound_MakeSound(e_SOUND_TYPE_EncoderMove);
 				}
 				enc_dif = lcd_encoder_diff;
 		}
 		if (lcd_clicked()) {
+			Sound_MakeSound(e_SOUND_TYPE_ButtonEcho);
 			KEEPALIVE_STATE(IN_HANDLER);
 			return yes;
 		}
@@ -3964,7 +3983,7 @@ void prusa_statistics(int _message, uint8_t _fil_nr) {
 			SERIAL_ECHOLN("}");
 			status_number = 14;
 		}
-		else if (IS_SD_PRINTING)
+		else if (IS_SD_PRINTING || loading_flag)
 		{
 			SERIAL_ECHO("{");
 			prusa_stat_printerstatus(4);
@@ -4003,7 +4022,7 @@ void prusa_statistics(int _message, uint8_t _fil_nr) {
 		status_number = 3;
 		farm_timer = 1;
 
-		if (IS_SD_PRINTING)
+		if (IS_SD_PRINTING || loading_flag)
 		{
 			farm_status = 4;
 			SERIAL_ECHO("{");
@@ -5274,8 +5293,8 @@ do\
          case e_SOUND_MODE_SILENT:\
               MENU_ITEM_FUNCTION_P(_i(MSG_SOUND_MODE_SILENT),lcd_sound_state_set);\
               break;\
-         case e_SOUND_MODE_MUTE:\
-              MENU_ITEM_FUNCTION_P(_i(MSG_SOUND_MODE_MUTE),lcd_sound_state_set);\
+         case e_SOUND_MODE_BLIND:\
+              MENU_ITEM_FUNCTION_P(_i(MSG_SOUND_MODE_BLIND),lcd_sound_state_set);\
               break;\
          default:\
               MENU_ITEM_FUNCTION_P(_i(MSG_SOUND_MODE_LOUD),lcd_sound_state_set);\
@@ -5286,95 +5305,218 @@ while (0)
 //-//
 static void lcd_check_mode_set(void)
 {
-switch(eCheckMode)
+switch(oCheckMode)
      {
-     case e_CHECK_MODE_none:
-          eCheckMode=e_CHECK_MODE_warn;
+     case ClCheckMode::_None:
+          oCheckMode=ClCheckMode::_Warn;
           break;
-     case e_CHECK_MODE_warn:
-          eCheckMode=e_CHECK_MODE_strict;
+     case ClCheckMode::_Warn:
+          oCheckMode=ClCheckMode::_Strict;
           break;
-     case e_CHECK_MODE_strict:
-          eCheckMode=e_CHECK_MODE_none;
+     case ClCheckMode::_Strict:
+          oCheckMode=ClCheckMode::_None;
           break;
      default:
-          eCheckMode=e_CHECK_MODE_none;
+          oCheckMode=ClCheckMode::_None;
      }
-eeprom_update_byte((uint8_t*)EEPROM_CHECK_MODE,(uint8_t)eCheckMode);
+eeprom_update_byte((uint8_t*)EEPROM_CHECK_MODE,(uint8_t)oCheckMode);
 }
 
+#define SETTINGS_MODE \
+do\
+{\
+    switch(oCheckMode)\
+         {\
+         case ClCheckMode::_None:\
+              MENU_ITEM_FUNCTION_P(_i("Nozzle     [none]"),lcd_check_mode_set);\
+              break;\
+         case ClCheckMode::_Warn:\
+              MENU_ITEM_FUNCTION_P(_i("Nozzle     [warn]"),lcd_check_mode_set);\
+              break;\
+         case ClCheckMode::_Strict:\
+              MENU_ITEM_FUNCTION_P(_i("Nozzle   [strict]"),lcd_check_mode_set);\
+              break;\
+         default:\
+              MENU_ITEM_FUNCTION_P(_i("Nozzle     [none]"),lcd_check_mode_set);\
+         }\
+}\
+while (0)
+
 static void lcd_nozzle_diameter_set(void)
 {
 uint16_t nDiameter;
 
-switch(eNozzleDiameter)
+switch(oNozzleDiameter)
      {
-     case e_NOZZLE_DIAMETER_250:
-          eNozzleDiameter=e_NOZZLE_DIAMETER_400;
+     case ClNozzleDiameter::_Diameter_250:
+          oNozzleDiameter=ClNozzleDiameter::_Diameter_400;
           nDiameter=400;
           break;
-     case e_NOZZLE_DIAMETER_400:
-          eNozzleDiameter=e_NOZZLE_DIAMETER_600;
+     case ClNozzleDiameter::_Diameter_400:
+          oNozzleDiameter=ClNozzleDiameter::_Diameter_600;
           nDiameter=600;
           break;
-     case e_NOZZLE_DIAMETER_600:
-          eNozzleDiameter=e_NOZZLE_DIAMETER_250;
+     case ClNozzleDiameter::_Diameter_600:
+          oNozzleDiameter=ClNozzleDiameter::_Diameter_250;
           nDiameter=250;
           break;
      default:
-          eNozzleDiameter=e_NOZZLE_DIAMETER_400;
+          oNozzleDiameter=ClNozzleDiameter::_Diameter_400;
           nDiameter=400;
      }
-eeprom_update_byte((uint8_t*)EEPROM_NOZZLE_DIAMETER,(uint8_t)eNozzleDiameter);
+eeprom_update_byte((uint8_t*)EEPROM_NOZZLE_DIAMETER,(uint8_t)oNozzleDiameter);
 eeprom_update_word((uint16_t*)EEPROM_NOZZLE_DIAMETER_uM,nDiameter);
 }
 
-#define SETTINGS_MODE \
+#define SETTINGS_NOZZLE \
 do\
 {\
-    switch(eCheckMode)\
+    switch(oNozzleDiameter)\
          {\
-         case e_CHECK_MODE_none:\
-              MENU_ITEM_FUNCTION_P(_i("Action     [none]"),lcd_check_mode_set);\
+         case ClNozzleDiameter::_Diameter_250:\
+              MENU_ITEM_FUNCTION_P(_i("Nozzle d.  [0.25]"),lcd_nozzle_diameter_set);\
               break;\
-         case e_CHECK_MODE_warn:\
-              MENU_ITEM_FUNCTION_P(_i("Action     [warn]"),lcd_check_mode_set);\
+         case ClNozzleDiameter::_Diameter_400:\
+              MENU_ITEM_FUNCTION_P(_i("Nozzle d.  [0.40]"),lcd_nozzle_diameter_set);\
               break;\
-         case e_CHECK_MODE_strict:\
-              MENU_ITEM_FUNCTION_P(_i("Action   [strict]"),lcd_check_mode_set);\
+         case ClNozzleDiameter::_Diameter_600:\
+              MENU_ITEM_FUNCTION_P(_i("Nozzle d.  [0.60]"),lcd_nozzle_diameter_set);\
               break;\
          default:\
-              MENU_ITEM_FUNCTION_P(_i("Action     [none]"),lcd_check_mode_set);\
+              MENU_ITEM_FUNCTION_P(_i("Nozzle d.  [0.40]"),lcd_nozzle_diameter_set);\
          }\
 }\
 while (0)
 
-#define SETTINGS_NOZZLE \
+static void lcd_check_model_set(void)
+{
+switch(oCheckModel)
+     {
+     case ClCheckModel::_None:
+          oCheckModel=ClCheckModel::_Warn;
+          break;
+     case ClCheckModel::_Warn:
+          oCheckModel=ClCheckModel::_Strict;
+          break;
+     case ClCheckModel::_Strict:
+          oCheckModel=ClCheckModel::_None;
+          break;
+     default:
+          oCheckModel=ClCheckModel::_None;
+     }
+eeprom_update_byte((uint8_t*)EEPROM_CHECK_MODEL,(uint8_t)oCheckModel);
+}
+
+#define SETTINGS_MODEL \
+do\
+{\
+    switch(oCheckModel)\
+         {\
+         case ClCheckModel::_None:\
+              MENU_ITEM_FUNCTION_P(_i("Model      [none]"),lcd_check_model_set);\
+              break;\
+         case ClCheckModel::_Warn:\
+              MENU_ITEM_FUNCTION_P(_i("Model      [warn]"),lcd_check_model_set);\
+              break;\
+         case ClCheckModel::_Strict:\
+              MENU_ITEM_FUNCTION_P(_i("Model    [strict]"),lcd_check_model_set);\
+              break;\
+         default:\
+              MENU_ITEM_FUNCTION_P(_i("Model      [none]"),lcd_check_model_set);\
+         }\
+}\
+while (0)
+
+static void lcd_check_version_set(void)
+{
+switch(oCheckVersion)
+     {
+     case ClCheckVersion::_None:
+          oCheckVersion=ClCheckVersion::_Warn;
+          break;
+     case ClCheckVersion::_Warn:
+          oCheckVersion=ClCheckVersion::_Strict;
+          break;
+     case ClCheckVersion::_Strict:
+          oCheckVersion=ClCheckVersion::_None;
+          break;
+     default:
+          oCheckVersion=ClCheckVersion::_None;
+     }
+eeprom_update_byte((uint8_t*)EEPROM_CHECK_VERSION,(uint8_t)oCheckVersion);
+}
+
+#define SETTINGS_VERSION \
+do\
+{\
+    switch(oCheckVersion)\
+         {\
+         case ClCheckVersion::_None:\
+              MENU_ITEM_FUNCTION_P(_i("Firmware   [none]"),lcd_check_version_set);\
+              break;\
+         case ClCheckVersion::_Warn:\
+              MENU_ITEM_FUNCTION_P(_i("Firmware   [warn]"),lcd_check_version_set);\
+              break;\
+         case ClCheckVersion::_Strict:\
+              MENU_ITEM_FUNCTION_P(_i("Firmware [strict]"),lcd_check_version_set);\
+              break;\
+         default:\
+              MENU_ITEM_FUNCTION_P(_i("Firmware   [none]"),lcd_check_version_set);\
+         }\
+}\
+while (0)
+
+static void lcd_check_gcode_set(void)
+{
+switch(oCheckGcode)
+     {
+     case ClCheckGcode::_None:
+          oCheckGcode=ClCheckGcode::_Warn;
+          break;
+     case ClCheckGcode::_Warn:
+          oCheckGcode=ClCheckGcode::_Strict;
+          break;
+     case ClCheckGcode::_Strict:
+          oCheckGcode=ClCheckGcode::_None;
+          break;
+     default:
+          oCheckGcode=ClCheckGcode::_None;
+     }
+eeprom_update_byte((uint8_t*)EEPROM_CHECK_GCODE,(uint8_t)oCheckGcode);
+}
+
+#define SETTINGS_GCODE \
 do\
 {\
-    switch(eNozzleDiameter)\
+    switch(oCheckGcode)\
          {\
-         case e_NOZZLE_DIAMETER_250:\
-              MENU_ITEM_FUNCTION_P(_i("Nozzle     [0.25]"),lcd_nozzle_diameter_set);\
+         case ClCheckGcode::_None:\
+              MENU_ITEM_FUNCTION_P(_i("Gcode      [none]"),lcd_check_gcode_set);\
               break;\
-         case e_NOZZLE_DIAMETER_400:\
-              MENU_ITEM_FUNCTION_P(_i("Nozzle     [0.40]"),lcd_nozzle_diameter_set);\
+         case ClCheckGcode::_Warn:\
+              MENU_ITEM_FUNCTION_P(_i("Gcode      [warn]"),lcd_check_gcode_set);\
               break;\
-         case e_NOZZLE_DIAMETER_600:\
-              MENU_ITEM_FUNCTION_P(_i("Nozzle     [0.60]"),lcd_nozzle_diameter_set);\
+         case ClCheckGcode::_Strict:\
+              MENU_ITEM_FUNCTION_P(_i("Gcode    [strict]"),lcd_check_gcode_set);\
               break;\
          default:\
-              MENU_ITEM_FUNCTION_P(_i("Nozzle     [0.40]"),lcd_nozzle_diameter_set);\
+              MENU_ITEM_FUNCTION_P(_i("Gcode      [none]"),lcd_check_gcode_set);\
          }\
 }\
 while (0)
 
-static void lcd_checking_menu()
+//-//static void lcd_checking_menu()
+void lcd_checking_menu()
 {
 MENU_BEGIN();
-MENU_ITEM_BACK_P(_T(MSG_SETTINGS));
-SETTINGS_MODE;
+MENU_ITEM_BACK_P(_T(bSettings?MSG_SETTINGS:MSG_BACK)); // i.e. default menu-item / menu-item after checking mismatch
 SETTINGS_NOZZLE;
+MENU_ITEM_TEXT_P(STR_SEPARATOR);
+MENU_ITEM_TEXT_P(_i("Checks:"));
+SETTINGS_MODE;
+SETTINGS_MODEL;
+SETTINGS_VERSION;
+SETTINGS_GCODE;
 MENU_END();
 }
 
@@ -5430,7 +5572,10 @@ static void lcd_settings_menu()
 #endif //(LANG_MODE != 0)
 
 	if (!farm_mode)
+          {
+          bSettings=true;                         // flag ('fake parameter') for 'lcd_checking_menu()' function
           MENU_ITEM_SUBMENU_P(_i("Print checking"), lcd_checking_menu);
+          }
 
 	SETTINGS_SD;
 	SETTINGS_SOUND;
@@ -5478,7 +5623,7 @@ static void lcd_calibration_menu()
   if (!isPrintPaused)
   {
 	MENU_ITEM_FUNCTION_P(_i("Wizard"), lcd_wizard);////MSG_WIZARD c=17 r=1
-	MENU_ITEM_SUBMENU_P(_i("First layer cal."), lcd_v2_calibration);////MSG_V2_CALIBRATION c=17 r=1
+	MENU_ITEM_SUBMENU_P(_T(MSG_V2_CALIBRATION), lcd_v2_calibration);
 	MENU_ITEM_GCODE_P(_T(MSG_AUTO_HOME), PSTR("G28 W"));
 	MENU_ITEM_FUNCTION_P(_i("Selftest         "), lcd_selftest_v);////MSG_SELFTEST
 #ifdef MK1BP
@@ -5551,10 +5696,12 @@ void bowden_menu() {
 
 				if (cursor_pos > 3) {
 					cursor_pos = 3;
+					Sound_MakeSound(e_SOUND_TYPE_BlindAlert);
 				}
 
 				if (cursor_pos < 0) {
 					cursor_pos = 0;
+					Sound_MakeSound(e_SOUND_TYPE_BlindAlert);
 				}
 
 				lcd_set_cursor(0, 0);
@@ -5567,13 +5714,13 @@ void bowden_menu() {
 				lcd_print(" ");
 				lcd_set_cursor(0, cursor_pos);
 				lcd_print(">");
-
+				Sound_MakeSound(e_SOUND_TYPE_EncoderMove);
 				enc_dif = lcd_encoder_diff;
 				_delay(100);
 		}
 
 		if (lcd_clicked()) {
-
+			Sound_MakeSound(e_SOUND_TYPE_ButtonEcho);
 			lcd_clear();
 			while (1) {
 
@@ -5604,6 +5751,7 @@ void bowden_menu() {
 				}
 				_delay(100);
 				if (lcd_clicked()) {
+					Sound_MakeSound(e_SOUND_TYPE_ButtonEcho);
 					EEPROM_save_B(EEPROM_BOWDEN_LENGTH + cursor_pos * 2, &bowden_length[cursor_pos]);
 					if (lcd_show_fullscreen_message_yes_no_and_wait_P(PSTR("Continue with another bowden?"))) {
 						lcd_update_enable(true);
@@ -5649,8 +5797,14 @@ static char snmm_stop_print_menu() { //menu for choosing which filaments will be
 			if ((abs(enc_dif - lcd_encoder_diff)) > 1) {
 				if (enc_dif > lcd_encoder_diff) cursor_pos--;
 				if (enc_dif < lcd_encoder_diff) cursor_pos++;
-				if (cursor_pos > 3) cursor_pos = 3;
-				if (cursor_pos < 1) cursor_pos = 1;
+				if (cursor_pos > 3) {
+					cursor_pos = 3;
+					Sound_MakeSound(e_SOUND_TYPE_BlindAlert);
+				}
+				if (cursor_pos < 1){
+					cursor_pos = 1;
+					Sound_MakeSound(e_SOUND_TYPE_BlindAlert);
+				}	
 
 				lcd_set_cursor(0, 1);
 				lcd_print(" ");
@@ -5661,10 +5815,12 @@ static char snmm_stop_print_menu() { //menu for choosing which filaments will be
 				lcd_set_cursor(0, cursor_pos);
 				lcd_print(">");
 				enc_dif = lcd_encoder_diff;
+				Sound_MakeSound(e_SOUND_TYPE_EncoderMove);
 				_delay(100);
 			}
 		}
 		if (lcd_clicked()) {
+			Sound_MakeSound(e_SOUND_TYPE_ButtonEcho);
 			KEEPALIVE_STATE(IN_HANDLER);
 			return(cursor_pos - 1);
 		}
@@ -5716,7 +5872,8 @@ uint8_t choose_menu_P(const char *header, const char *item, const char *last_ite
 		}
 
 		if (cursor_pos > 3)
-		{
+		{		
+			Sound_MakeSound(e_SOUND_TYPE_BlindAlert);
             cursor_pos = 3;
             if (first < items_no - 3)
             {
@@ -5727,6 +5884,7 @@ uint8_t choose_menu_P(const char *header, const char *item, const char *last_ite
 
         if (cursor_pos < 1)
         {
+					Sound_MakeSound(e_SOUND_TYPE_BlindAlert);
             cursor_pos = 1;
             if (first > 0)
             {
@@ -5761,11 +5919,12 @@ uint8_t choose_menu_P(const char *header, const char *item, const char *last_ite
         lcd_print(" ");
         lcd_set_cursor(0, cursor_pos);
         lcd_print(">");
-
+				Sound_MakeSound(e_SOUND_TYPE_EncoderMove);
         _delay(100);
 
 		if (lcd_clicked())
 		{
+			Sound_MakeSound(e_SOUND_TYPE_ButtonEcho);
 		    KEEPALIVE_STATE(IN_HANDLER);
 			lcd_encoder_diff = 0;
 			return(cursor_pos + first - 1);
@@ -5820,6 +5979,7 @@ char reset_menu() {
 
 				if (cursor_pos > 3) {
 					cursor_pos = 3;
+					Sound_MakeSound(e_SOUND_TYPE_BlindAlert);
 					if (first < items_no - 4) {
 						first++;
 						lcd_clear();
@@ -5828,6 +5988,7 @@ char reset_menu() {
 
 				if (cursor_pos < 0) {
 					cursor_pos = 0;
+					Sound_MakeSound(e_SOUND_TYPE_BlindAlert);
 					if (first > 0) {
 						first--;
 						lcd_clear();
@@ -5843,6 +6004,7 @@ char reset_menu() {
 				lcd_print(" ");
 				lcd_set_cursor(0, cursor_pos);
 				lcd_print(">");
+				Sound_MakeSound(e_SOUND_TYPE_EncoderMove);
 				enc_dif = lcd_encoder_diff;
 				_delay(100);
 			}
@@ -5850,6 +6012,7 @@ char reset_menu() {
 		}
 
 		if (lcd_clicked()) {
+			Sound_MakeSound(e_SOUND_TYPE_ButtonEcho);
 			return(cursor_pos + first);
 		}
 
@@ -6158,6 +6321,7 @@ unsigned char lcd_choose_color() {
 				
 				if (cursor_pos > active_rows) {
 					cursor_pos = active_rows;
+					Sound_MakeSound(e_SOUND_TYPE_BlindAlert);
 					if (first < items_no - active_rows) {
 						first++;
 						lcd_clear();
@@ -6166,6 +6330,7 @@ unsigned char lcd_choose_color() {
 
 				if (cursor_pos < 1) {
 					cursor_pos = 1;
+					Sound_MakeSound(e_SOUND_TYPE_BlindAlert);
 					if (first > 0) {
 						first--;
 						lcd_clear();
@@ -6179,12 +6344,14 @@ unsigned char lcd_choose_color() {
 				lcd_print(" ");
 				lcd_set_cursor(0, cursor_pos);
 				lcd_print(">");
+				Sound_MakeSound(e_SOUND_TYPE_EncoderMove);
 				enc_dif = lcd_encoder_diff;
 				_delay(100);
 
 		}
 
 		if (lcd_clicked()) {
+			Sound_MakeSound(e_SOUND_TYPE_ButtonEcho);
 			switch(cursor_pos + first - 1) {
 			case 0: return 1; break;
 			case 1: return 0; break;
@@ -6301,6 +6468,95 @@ void lcd_resume_print()
     isPrintPaused = false;
 }
 
+static void change_sheet(uint8_t sheet_num)
+{
+	eeprom_update_byte(&(EEPROM_Sheets_base->active_sheet), sheet_num);
+	if(is_sheet_initialized())
+		calibration_status_store(CALIBRATION_STATUS_CALIBRATED);
+	else
+		calibration_status_store(CALIBRATION_STATUS_LIVE_ADJUST);
+
+    menu_back(3);
+}
+
+static void lcd_select_sheet_0_menu()
+{
+	change_sheet(0);
+}
+static void lcd_select_sheet_1_menu()
+{
+	change_sheet(1);
+}
+static void lcd_select_sheet_2_menu()
+{
+	change_sheet(2);
+}
+
+static void lcd_select_sheet_menu()
+{
+    MENU_BEGIN();
+    MENU_ITEM_BACK_P(_T(MSG_BACK));
+    MENU_ITEM_SUBMENU_E(EEPROM_Sheets_base->s[0], lcd_select_sheet_0_menu);
+    MENU_ITEM_SUBMENU_E(EEPROM_Sheets_base->s[1], lcd_select_sheet_1_menu);
+    MENU_ITEM_SUBMENU_E(EEPROM_Sheets_base->s[2], lcd_select_sheet_2_menu);
+    MENU_END();
+}
+
+static void lcd_rename_sheet_menu()
+{
+    struct MenuData
+    {
+        bool initialized;
+        uint8_t selected;
+        char name[sizeof(Sheet::name)];
+    };
+    static_assert(sizeof(menu_data)>= sizeof(MenuData),"MenuData doesn't fit into menu_data");
+    MenuData* menuData = (MenuData*)&(menu_data[0]);
+
+    if (!menuData->initialized)
+    {
+        eeprom_read_block(menuData->name, EEPROM_Sheets_base->s[(eeprom_read_byte(&(EEPROM_Sheets_base->active_sheet)))].name, sizeof(Sheet::name));
+        lcd_encoder = menuData->name[0];
+        menuData->initialized = true;
+    }
+    if (lcd_encoder < '\x20') lcd_encoder = '\x20';
+    if (lcd_encoder > '\x7F') lcd_encoder = '\x7F';
+
+    menuData->name[menuData->selected] = lcd_encoder;
+    lcd_set_cursor(0,0);
+    for (uint_least8_t i = 0; i < sizeof(Sheet::name); ++i)
+    {
+        lcd_putc(menuData->name[i]);
+    }
+    lcd_set_cursor(menuData->selected, 1);
+    lcd_putc('^');
+    if (lcd_clicked())
+    {
+        if ((menuData->selected + 1u) < sizeof(Sheet::name))
+        {
+            lcd_encoder = menuData->name[++(menuData->selected)];
+        }
+        else
+        {
+            eeprom_update_block(menuData->name,
+                EEPROM_Sheets_base->s[(eeprom_read_byte(&(EEPROM_Sheets_base->active_sheet)))].name,
+                sizeof(Sheet::name));
+            menu_back();
+        }
+    }
+}
+
+static void lcd_sheet_menu()
+{
+    MENU_BEGIN();
+    MENU_ITEM_BACK_P(_T(MSG_MAIN));
+    MENU_ITEM_SUBMENU_P(_i("Select"), lcd_select_sheet_menu); //// c=18
+    MENU_ITEM_SUBMENU_P(_i("Rename"), lcd_rename_sheet_menu); //// c=18
+    MENU_ITEM_SUBMENU_P(_T(MSG_V2_CALIBRATION), lcd_v2_calibration);
+
+    MENU_END();
+}
+
 static void lcd_main_menu()
 {
 
@@ -6322,55 +6578,6 @@ static void lcd_main_menu()
  MENU_ITEM_FUNCTION_P(PSTR("recover print"), recover_print);
  MENU_ITEM_FUNCTION_P(PSTR("power panic"), uvlo_);
 #endif //TMC2130_DEBUG
-
- /* if (farm_mode && !IS_SD_PRINTING )
-    {
-    
-        int tempScrool = 0;
-        if (lcd_draw_update == 0 && LCD_CLICKED == 0)
-            //_delay(100);
-            return; // nothing to do (so don't thrash the SD card)
-        uint16_t fileCnt = card.getnrfilenames();
-        
-        card.getWorkDirName();
-        if (card.filename[0] == '/')
-        {
-#if SDCARDDETECT == -1
-            MENU_ITEM_FUNCTION_P(_T(MSG_REFRESH), lcd_sd_refresh);
-#endif
-        } else {
-            MENU_ITEM_FUNCTION_P(PSTR(LCD_STR_FOLDER ".."), lcd_sd_updir);
-        }
-        
-        for (uint16_t i = 0; i < fileCnt; i++)
-        {
-            if (menu_item == menu_line)
-            {
-#ifndef SDCARD_RATHERRECENTFIRST
-                card.getfilename(i);
-#else
-                card.getfilename(fileCnt - 1 - i);
-#endif
-                if (card.filenameIsDir)
-                {
-                    MENU_ITEM_SDDIR(_T(MSG_CARD_MENU), card.filename, card.longFilename);
-                } else {
-                    
-                    MENU_ITEM_SDFILE(_T(MSG_CARD_MENU), card.filename, card.longFilename);
-                    
-                    
-                    
-                    
-                }
-            } else {
-                MENU_ITEM_DUMMY();
-            }
-        }
-        
-        MENU_ITEM_BACK_P(PSTR("- - - - - - - - -"));
-    
-        
-    }*/
  
   if ( ( IS_SD_PRINTING || is_usb_printing || (lcd_commands_type == LcdCommands::Layer1Cal)) && (current_position[Z_AXIS] < Z_HEIGHT_HIDE_LIVE_ADJUST_MENU) && !homing_flag && !mesh_bed_leveling_flag)
   {
@@ -6386,6 +6593,8 @@ static void lcd_main_menu()
     MENU_ITEM_SUBMENU_P(_i("Preheat"), lcd_preheat_menu);////MSG_PREHEAT
   }
 
+
+
 #ifdef SDSUPPORT
   if (card.cardOK || lcd_commands_type == LcdCommands::Layer1Cal)
   {
@@ -6476,6 +6685,8 @@ static void lcd_main_menu()
 
   }
 
+  if(!isPrintPaused)MENU_ITEM_SUBMENU_E(EEPROM_Sheets_base->s[(eeprom_read_byte(&(EEPROM_Sheets_base->active_sheet)))], lcd_sheet_menu);
+  
   if (!is_usb_printing && (lcd_commands_type != LcdCommands::Layer1Cal))
   {
 	  MENU_ITEM_SUBMENU_P(_i("Statistics  "), lcd_menu_statistics);////MSG_STATISTICS
@@ -6497,11 +6708,7 @@ static void lcd_main_menu()
 }
 
 void stack_error() {
-	SET_OUTPUT(BEEPER);
-if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE)||(eSoundMode==e_SOUND_MODE_SILENT))
-	WRITE(BEEPER, HIGH);
-	_delay(1000);
-	WRITE(BEEPER, LOW);
+	Sound_MakeCustom(1000,0,true);
 	lcd_display_message_fullscreen_P(_i("Error - static memory has been overwritten"));////MSG_STACK_ERROR c=20 r=4
 	//err_triggered = 1;
 	 while (1) delay_keep_alive(1000);
@@ -6636,8 +6843,8 @@ static void lcd_tune_menu()
           case e_SOUND_MODE_SILENT:
                MENU_ITEM_FUNCTION_P(_i(MSG_SOUND_MODE_SILENT),lcd_sound_state_set);
                break;
-          case e_SOUND_MODE_MUTE:
-               MENU_ITEM_FUNCTION_P(_i(MSG_SOUND_MODE_MUTE),lcd_sound_state_set);
+          case e_SOUND_MODE_BLIND:
+               MENU_ITEM_FUNCTION_P(_i(MSG_SOUND_MODE_BLIND),lcd_sound_state_set);
                break;
           default:
                MENU_ITEM_FUNCTION_P(_i(MSG_SOUND_MODE_LOUD),lcd_sound_state_set);
@@ -6802,6 +7009,7 @@ void lcd_sdcard_stop()
 
 	if (lcd_clicked())
 	{
+		Sound_MakeSound(e_SOUND_TYPE_ButtonEcho);
 		if ((int32_t)lcd_encoder == 1)
 		{
 			lcd_return_to_status();
@@ -8318,6 +8526,7 @@ void menu_lcd_lcdupdate_func(void)
 			if (lcd_draw_update == 0)
 			lcd_draw_update = 1;
 			lcd_encoder += lcd_encoder_diff / ENCODER_PULSES_PER_STEP;
+			Sound_MakeSound(e_SOUND_TYPE_EncoderMove);
 			lcd_encoder_diff = 0;
 			lcd_timeoutToStatus.start();
 		}

+ 3 - 0
Firmware/ultralcd.h

@@ -143,6 +143,9 @@ void lcd_ignore_click(bool b=true);
 void lcd_commands();
 
 
+extern bool bSettings;                            // flag (i.e. 'fake parameter') for 'lcd_checkink_menu()' function
+
+
 void change_extr(int extr);
 
 #ifdef SNMM

+ 215 - 23
Firmware/util.cpp

@@ -295,16 +295,10 @@ bool show_upgrade_dialog_if_version_newer(const char *version_string)
         for (const char *c = version_string; ! is_whitespace_or_nl_or_eol(*c); ++ c)
             lcd_putc(*c);
         lcd_puts_at_P(0, 3, _i("Please upgrade."));////MSG_NEW_FIRMWARE_PLEASE_UPGRADE c=20
-if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
-        _tone(BEEPER, 1000);
-        delay_keep_alive(50);
-        _noTone(BEEPER);
+        Sound_MakeCustom(50,1000,false);
         delay_keep_alive(500);
-if((eSoundMode==e_SOUND_MODE_LOUD)||(eSoundMode==e_SOUND_MODE_ONCE))
-        _tone(BEEPER, 1000);
-        delay_keep_alive(50);
-        _noTone(BEEPER);
-        lcd_wait_for_click();
+        Sound_MakeCustom(50,1000,false);
+        lcd_wait_for_click_delay(30);
         lcd_update_enable(true);
         lcd_clear();
         lcd_update(0);
@@ -330,43 +324,241 @@ void update_current_firmware_version_to_eeprom()
 
 
 //-//
-eNOZZLE_DIAMETER eNozzleDiameter=e_NOZZLE_DIAMETER_400;
-eCHECK_MODE eCheckMode=e_CHECK_MODE_none;
+void lcd_checking_menu(void);
+
+ClNozzleDiameter oNozzleDiameter=ClNozzleDiameter::_Diameter_400;
+ClCheckMode oCheckMode=ClCheckMode::_None;
+ClCheckModel oCheckModel=ClCheckModel::_None;
+ClCheckVersion oCheckVersion=ClCheckVersion::_None;
+ClCheckGcode oCheckGcode=ClCheckGcode::_None;
 
 void fCheckModeInit()
 {
-eCheckMode=(eCHECK_MODE)eeprom_read_byte((uint8_t*)EEPROM_CHECK_MODE);
-if(eCheckMode==e_CHECK_MODE_NULL)
+oCheckMode=(ClCheckMode)eeprom_read_byte((uint8_t*)EEPROM_CHECK_MODE);
+if(oCheckMode==ClCheckMode::_Undef)
      {
-     eCheckMode=e_CHECK_MODE_warn;
-     eeprom_update_byte((uint8_t*)EEPROM_CHECK_MODE,(uint8_t)eCheckMode);
+     oCheckMode=ClCheckMode::_Warn;
+     eeprom_update_byte((uint8_t*)EEPROM_CHECK_MODE,(uint8_t)oCheckMode);
      }
 if(farm_mode)
-     eCheckMode=e_CHECK_MODE_strict;
-eNozzleDiameter=(eNOZZLE_DIAMETER)eeprom_read_byte((uint8_t*)EEPROM_NOZZLE_DIAMETER);
-if((eNozzleDiameter==e_NOZZLE_DIAMETER_NULL)&& !farm_mode)
+     oCheckMode=ClCheckMode::_Strict;
+oNozzleDiameter=(ClNozzleDiameter)eeprom_read_byte((uint8_t*)EEPROM_NOZZLE_DIAMETER);
+if((oNozzleDiameter==ClNozzleDiameter::_Diameter_Undef)&& !farm_mode)
      {
-     eNozzleDiameter=e_NOZZLE_DIAMETER_400;
-     eeprom_update_byte((uint8_t*)EEPROM_NOZZLE_DIAMETER,(uint8_t)eNozzleDiameter);
+     oNozzleDiameter=ClNozzleDiameter::_Diameter_400;
+     eeprom_update_byte((uint8_t*)EEPROM_NOZZLE_DIAMETER,(uint8_t)oNozzleDiameter);
      eeprom_update_word((uint16_t*)EEPROM_NOZZLE_DIAMETER_uM,400);
      }
+oCheckModel=(ClCheckModel)eeprom_read_byte((uint8_t*)EEPROM_CHECK_MODEL);
+if(oCheckModel==ClCheckModel::_Undef)
+     {
+     oCheckModel=ClCheckModel::_Warn;
+     eeprom_update_byte((uint8_t*)EEPROM_CHECK_MODEL,(uint8_t)oCheckModel);
+     }
+oCheckVersion=(ClCheckVersion)eeprom_read_byte((uint8_t*)EEPROM_CHECK_VERSION);
+if(oCheckVersion==ClCheckVersion::_Undef)
+     {
+     oCheckVersion=ClCheckVersion::_Warn;
+     eeprom_update_byte((uint8_t*)EEPROM_CHECK_VERSION,(uint8_t)oCheckVersion);
+     }
+oCheckGcode=(ClCheckGcode)eeprom_read_byte((uint8_t*)EEPROM_CHECK_GCODE);
+if(oCheckGcode==ClCheckGcode::_Undef)
+     {
+     oCheckGcode=ClCheckGcode::_Warn;
+     eeprom_update_byte((uint8_t*)EEPROM_CHECK_GCODE,(uint8_t)oCheckGcode);
+     }
 }
 
 void nozzle_diameter_check(uint16_t nDiameter)
 {
 uint16_t nDiameter_um;
 
+if(oCheckMode==ClCheckMode::_None)
+     return;
 nDiameter_um=eeprom_read_word((uint16_t*)EEPROM_NOZZLE_DIAMETER_uM);
 if(nDiameter==nDiameter_um)
      return;
-switch(eCheckMode)
+//SERIAL_ECHO_START;
+//SERIAL_ECHOLNPGM("Nozzle diameter doesn't match ...");
+//SERIAL_ECHOPGM("actual  : ");
+//SERIAL_ECHOLN((float)(nDiameter_um/1000.0));
+//SERIAL_ECHOPGM("expected: ");
+//SERIAL_ECHOLN((float)(nDiameter/1000.0));
+switch(oCheckMode)
      {
-     case e_CHECK_MODE_warn:
+     case ClCheckMode::_Warn:
           lcd_show_fullscreen_message_and_wait_P(_i("Nozzle diameter doesn't match! Press the knob to continue."));
           break;
-     case e_CHECK_MODE_strict:
+     case ClCheckMode::_Strict:
           lcd_show_fullscreen_message_and_wait_P(_i("Nozzle diameter doesn't match! Print is aborted, press the knob."));
           lcd_print_stop();
           break;
      }
+bSettings=false;                                  // flag ('fake parameter') for 'lcd_checking_menu()' function
+menu_submenu(lcd_checking_menu);
+}
+
+void printer_model_check(uint16_t nPrinterModel)
+{
+if(oCheckModel==ClCheckModel::_None)
+     return;
+if(nPrinterModel==nPrinterType)
+     return;
+//SERIAL_ECHO_START;
+//SERIAL_ECHOLNPGM("Printer model doesn't match ...");
+//SERIAL_ECHOPGM("actual  : ");
+//SERIAL_ECHOLN(nPrinterType);
+//SERIAL_ECHOPGM("expected: ");
+//SERIAL_ECHOLN(nPrinterModel);
+switch(oCheckModel)
+     {
+     case ClCheckModel::_Warn:
+          lcd_show_fullscreen_message_and_wait_P(_i("Printer model doesn't match! Press the knob to continue."));
+          break;
+     case ClCheckModel::_Strict:
+          lcd_show_fullscreen_message_and_wait_P(_i("Printer model doesn't match! Print is aborted, press the knob."));
+          lcd_print_stop();
+          break;
+     }
+}
+
+uint8_t mCompareValue(uint16_t nX,uint16_t nY)
+{
+if(nX>nY)
+     return((uint8_t)ClCompareValue::_Greater);
+if(nX<nY)
+     return((uint8_t)ClCompareValue::_Less);
+return((uint8_t)ClCompareValue::_Equal);
+}
+
+void fw_version_check(const char *pVersion)
+{
+uint16_t aVersion[4];
+uint8_t nCompareValueResult;
+
+if(oCheckVersion==ClCheckVersion::_None)
+     return;
+parse_version(pVersion,aVersion);
+nCompareValueResult=mCompareValue(aVersion[0],eeprom_read_word((uint16_t*)EEPROM_FIRMWARE_VERSION_MAJOR))<<6;
+nCompareValueResult+=mCompareValue(aVersion[1],eeprom_read_word((uint16_t*)EEPROM_FIRMWARE_VERSION_MINOR))<<4;
+nCompareValueResult+=mCompareValue(aVersion[2],eeprom_read_word((uint16_t*)EEPROM_FIRMWARE_VERSION_REVISION))<<2;
+nCompareValueResult+=mCompareValue(aVersion[3],eeprom_read_word((uint16_t*)EEPROM_FIRMWARE_VERSION_FLAVOR));
+if(nCompareValueResult==COMPARE_VALUE_EQUAL)
+     return;
+if((nCompareValueResult<COMPARE_VALUE_EQUAL)&&oCheckVersion==ClCheckVersion::_Warn)
+     return;
+//SERIAL_ECHO_START;
+//SERIAL_ECHOLNPGM("FW version doesn't match ...");
+//SERIAL_ECHOPGM("actual  : ");
+//SERIAL_ECHOLN(FW_VERSION);
+//SERIAL_ECHOPGM("expected: ");
+//SERIAL_ECHOLN(pVersion);
+switch(oCheckVersion)
+     {
+     case ClCheckVersion::_Warn:
+          lcd_show_fullscreen_message_and_wait_P(_i("FW version doesn't match! Press the knob to continue."));
+          break;
+     case ClCheckVersion::_Strict:
+          lcd_show_fullscreen_message_and_wait_P(_i("FW version doesn't match! Print is aborted, press the knob."));
+          lcd_print_stop();
+          break;
+     }
+}
+
+void gcode_level_check(uint16_t nGcodeLevel)
+{
+if(oCheckGcode==ClCheckGcode::_None)
+     return;
+if(nGcodeLevel==(uint16_t)GCODE_LEVEL)
+     return;
+if((nGcodeLevel<(uint16_t)GCODE_LEVEL)&&(oCheckGcode==ClCheckGcode::_Warn))
+     return;
+//SERIAL_ECHO_START;
+//SERIAL_ECHOLNPGM("G-code level doesn't match ...");
+//SERIAL_ECHOPGM("actual  : ");
+//SERIAL_ECHOLN(GCODE_LEVEL);
+//SERIAL_ECHOPGM("expected: ");
+//SERIAL_ECHOLN(nGcodeLevel);
+switch(oCheckGcode)
+     {
+     case ClCheckGcode::_Warn:
+          lcd_show_fullscreen_message_and_wait_P(_i("G-code level doesn't match! Press the knob to continue."));
+          break;
+     case ClCheckGcode::_Strict:
+          lcd_show_fullscreen_message_and_wait_P(_i("G-code level doesn't match! Print is aborted, press the knob."));
+          lcd_print_stop();
+          break;
+     }
+}
+
+//-// -> cmdqueue ???
+#define PRINTER_NAME_LENGTH ((sizeof(PRINTER_MMU_NAME)>sizeof(PRINTER_NAME))?(sizeof(PRINTER_MMU_NAME)-1):(sizeof(PRINTER_NAME)-1))
+#define GCODE_DELIMITER '"'
+#define ELLIPSIS "..."
+
+char* code_string(char* pStr,size_t* nLength)
+{
+char* pStrBegin;
+char* pStrEnd;
+
+pStrBegin=strchr(pStr,GCODE_DELIMITER);
+if(!pStrBegin)
+     return(NULL);
+pStrBegin++;
+pStrEnd=strchr(pStrBegin,GCODE_DELIMITER);
+if(!pStrEnd)
+     return(NULL);
+*nLength=pStrEnd-pStrBegin;
+return(pStrBegin);
+}
+
+void printer_smodel_check(char* pStrPos)
+{
+char* pResult;
+size_t nLength,nPrinterNameLength;
+bool bCheckOK;
+char sPrinterName[PRINTER_NAME_LENGTH+sizeof(ELLIPSIS)-1+1]="";
+
+nPrinterNameLength=strlen_P(::sPrinterName);
+pResult=code_string(pStrPos,&nLength);
+if(pResult!=NULL)
+     {
+     strlcpy(sPrinterName,pResult,min(nPrinterNameLength,nLength)+1);
+     if(nLength>nPrinterNameLength)
+          strcat(sPrinterName,ELLIPSIS);
+     bCheckOK=(nLength==nPrinterNameLength);
+     if(bCheckOK&&(!strncasecmp_P(pResult,::sPrinterName,nLength))) // i.e. string compare execute only if lengths are same
+          return;
+     }
+//SERIAL_ECHO_START;
+//SERIAL_ECHOLNPGM("Printer model doesn't match ...");
+//SERIAL_ECHOPGM("actual  : \"");
+//serialprintPGM(::sPrinterName);
+//SERIAL_ECHOLNPGM("\"");
+//SERIAL_ECHOPGM("expected: \"");
+////SERIAL_ECHO(sPrinterName);
+//SERIAL_ECHOLNPGM("\"");
+switch(oCheckModel)
+     {
+     case ClCheckModel::_Warn:
+          lcd_show_fullscreen_message_and_wait_P(_i("Printer model doesn't match! Press the knob to continue."));
+          break;
+     case ClCheckModel::_Strict:
+          lcd_show_fullscreen_message_and_wait_P(_i("Printer model doesn't match! Print is aborted, press the knob."));
+          lcd_print_stop();
+          break;
+     }
+}
+
+void fSetMmuMode(bool bMMu)
+{
+if(bMMu)
+     {
+     nPrinterType=pgm_read_word(&_nPrinterMmuType);
+     sPrinterName=_sPrinterMmuName;
+     }
+else {
+     nPrinterType=pgm_read_word(&_nPrinterType);
+     sPrinterName=_sPrinterName;
+     }
 }

+ 63 - 14
Firmware/util.h

@@ -35,27 +35,76 @@ inline void eeprom_update_int8(unsigned char* addr, int8_t v) {
 
 
 //-//
-#define e_CHECK_MODE_NULL 0xFF
-#define e_NOZZLE_DIAMETER_NULL 0xFF
+enum class ClPrintChecking:uint_least8_t
+{
+    _Nozzle=1,
+    _Model=2,
+    _Smodel=3,
+    _Version=4,
+    _Gcode=5
+};
 
-typedef enum
+enum class ClNozzleDiameter:uint_least8_t
 {
-    e_NOZZLE_DIAMETER_250,
-    e_NOZZLE_DIAMETER_400,
-    e_NOZZLE_DIAMETER_600
-} eNOZZLE_DIAMETER;
+    _Diameter_250=25,
+    _Diameter_400=40,
+    _Diameter_600=60,
+    _Diameter_Undef=EEPROM_EMPTY_VALUE
+};
 
-typedef enum
+enum class ClCheckMode:uint_least8_t
 {
-    e_CHECK_MODE_none,
-    e_CHECK_MODE_warn,
-    e_CHECK_MODE_strict
-} eCHECK_MODE;
+    _None,
+    _Warn,
+    _Strict,
+    _Undef=EEPROM_EMPTY_VALUE
+};
 
-extern eNOZZLE_DIAMETER eNozzleDiameter;
-extern eCHECK_MODE eCheckMode;
+enum class ClCheckModel:uint_least8_t
+{
+    _None,
+    _Warn,
+    _Strict,
+    _Undef=EEPROM_EMPTY_VALUE
+};
+
+enum class ClCheckVersion:uint_least8_t
+{
+    _None,
+    _Warn,
+    _Strict,
+    _Undef=EEPROM_EMPTY_VALUE
+};
+
+enum class ClCheckGcode:uint_least8_t
+{
+    _None,
+    _Warn,
+    _Strict,
+    _Undef=EEPROM_EMPTY_VALUE
+};
+
+#define COMPARE_VALUE_EQUAL (((uint8_t)ClCompareValue::_Equal<<6)+((uint8_t)ClCompareValue::_Equal<<4)+((uint8_t)ClCompareValue::_Equal<<2)+((uint8_t)ClCompareValue::_Equal))
+enum class ClCompareValue:uint_least8_t
+{
+    _Less=0,
+    _Equal=1,
+    _Greater=2
+};
+
+extern ClNozzleDiameter oNozzleDiameter;
+extern ClCheckMode oCheckMode;
+extern ClCheckModel oCheckModel;
+extern ClCheckVersion oCheckVersion;
+extern ClCheckGcode oCheckGcode;
 
 void fCheckModeInit();
 void nozzle_diameter_check(uint16_t nDiameter);
+void printer_model_check(uint16_t nPrinterModel);
+void printer_smodel_check(char* pStrPos);
+void fw_version_check(const char *pVersion);
+void gcode_level_check(uint16_t nGcodeLevel);
+
+void fSetMmuMode(bool bMMu);
 
 #endif /* UTIL_H */

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

@@ -2,12 +2,16 @@
 #define CONFIGURATION_PRUSA_H
 
 #include <limits.h>
+#include "printers.h"
 /*------------------------------------
 GENERAL SETTINGS
 *------------------------------------*/
 
 // Printer revision
 #define PRINTER_TYPE PRINTER_MK2
+#define PRINTER_NAME PRINTER_MK2_NAME
+#define PRINTER_MMU_TYPE PRINTER_MK2              // dummy item (due to successfully compilation / building only)
+#define PRINTER_MMU_NAME PRINTER_MK2_NAME         // dummy item (due to successfully compilation / building only)
 #define FILAMENT_SIZE "1_75mm_MK2"
 #define NOZZLE_TYPE "E3Dv6full"
 

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

@@ -2,12 +2,16 @@
 #define CONFIGURATION_PRUSA_H
 
 #include <limits.h>
+#include "printers.h"
 /*------------------------------------
 GENERAL SETTINGS
 *------------------------------------*/
 
 // Printer revision
 #define PRINTER_TYPE PRINTER_MK2
+#define PRINTER_NAME PRINTER_MK2_NAME
+#define PRINTER_MMU_TYPE PRINTER_MK2              // dummy item (due to successfully compilation / building only)
+#define PRINTER_MMU_NAME PRINTER_MK2_NAME         // dummy item (due to successfully compilation / building only)
 #define FILAMENT_SIZE "1_75mm_MK2"
 #define NOZZLE_TYPE "E3Dv6full"
 

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

@@ -2,12 +2,16 @@
 #define CONFIGURATION_PRUSA_H
 
 #include <limits.h>
+#include "printers.h"
 /*------------------------------------
  GENERAL SETTINGS
  *------------------------------------*/
 
 // Printer revision
 #define PRINTER_TYPE PRINTER_MK25
+#define PRINTER_NAME PRINTER_MK25_NAME
+#define PRINTER_MMU_TYPE PRINTER_MK25_MMU2
+#define PRINTER_MMU_NAME PRINTER_MK25_MMU2_NAME
 #define FILAMENT_SIZE "1_75mm_MK25"
 #define NOZZLE_TYPE "E3Dv6full"
 

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

@@ -2,12 +2,16 @@
 #define CONFIGURATION_PRUSA_H
 
 #include <limits.h>
+#include "printers.h"
 /*------------------------------------
  GENERAL SETTINGS
  *------------------------------------*/
 
 // Printer revision
 #define PRINTER_TYPE PRINTER_MK25
+#define PRINTER_NAME PRINTER_MK25_NAME
+#define PRINTER_MMU_TYPE PRINTER_MK25_MMU2
+#define PRINTER_MMU_NAME PRINTER_MK25_MMU2_NAME
 #define FILAMENT_SIZE "1_75mm_MK25"
 #define NOZZLE_TYPE "E3Dv6full"
 

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

@@ -2,12 +2,16 @@
 #define CONFIGURATION_PRUSA_H
 
 #include <limits.h>
+#include "printers.h"
 /*------------------------------------
  GENERAL SETTINGS
  *------------------------------------*/
 
 // Printer revision
 #define PRINTER_TYPE PRINTER_MK25S
+#define PRINTER_NAME PRINTER_MK25S_NAME
+#define PRINTER_MMU_TYPE PRINTER_MK25S_MMU2
+#define PRINTER_MMU_NAME PRINTER_MK25S_MMU2_NAME
 #define FILAMENT_SIZE "1_75mm_MK25S"
 #define NOZZLE_TYPE "E3Dv6full"
 

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

@@ -2,12 +2,16 @@
 #define CONFIGURATION_PRUSA_H
 
 #include <limits.h>
+#include "printers.h"
 /*------------------------------------
  GENERAL SETTINGS
  *------------------------------------*/
 
 // Printer revision
 #define PRINTER_TYPE PRINTER_MK25S
+#define PRINTER_NAME PRINTER_MK25S_NAME
+#define PRINTER_MMU_TYPE PRINTER_MK25S_MMU2
+#define PRINTER_MMU_NAME PRINTER_MK25S_MMU2_NAME
 #define FILAMENT_SIZE "1_75mm_MK25"
 #define NOZZLE_TYPE "E3Dv6full"
 

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

@@ -2,12 +2,17 @@
 #define CONFIGURATION_PRUSA_H
 
 #include <limits.h>
+//-//
+#include "printers.h"
 /*------------------------------------
  GENERAL SETTINGS
  *------------------------------------*/
 
 // Printer revision
 #define PRINTER_TYPE PRINTER_MK3
+#define PRINTER_NAME PRINTER_MK3_NAME
+#define PRINTER_MMU_TYPE PRINTER_MK3_MMU2
+#define PRINTER_MMU_NAME PRINTER_MK3_MMU2_NAME
 #define FILAMENT_SIZE "1_75mm_MK3"
 #define NOZZLE_TYPE "E3Dv6full"
 
@@ -188,9 +193,9 @@
 //#define FSENSOR_QUALITY
 
 
-#define LINEARITY_CORRECTION
-#define TMC2130_LINEARITY_CORRECTION
-#define TMC2130_LINEARITY_CORRECTION_XYZ
+//#define LINEARITY_CORRECTION
+//#define TMC2130_LINEARITY_CORRECTION
+//#define TMC2130_LINEARITY_CORRECTION_XYZ
 #define TMC2130_VARIABLE_RESOLUTION
 
 

+ 4 - 0
Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h

@@ -2,12 +2,16 @@
 #define CONFIGURATION_PRUSA_H
 
 #include <limits.h>
+#include "printers.h"
 /*------------------------------------
  GENERAL SETTINGS
  *------------------------------------*/
 
 // Printer revision
 #define PRINTER_TYPE PRINTER_MK3S
+#define PRINTER_NAME PRINTER_MK3S_NAME
+#define PRINTER_MMU_TYPE PRINTER_MK3S_MMU2
+#define PRINTER_MMU_NAME PRINTER_MK3S_MMU2_NAME
 #define FILAMENT_SIZE "1_75mm_MK3"
 #define NOZZLE_TYPE "E3Dv6full"
 

+ 2 - 2
PF-build.sh

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

+ 7 - 7
README.md

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

+ 2 - 2
build.sh

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

+ 1 - 1
lang/lang-build.sh

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