浏览代码

Reset live adjust on XYZ calibration.
Disable timeouts in the XYZ/Z calibration.
Don't modify feed rate multiplier during the XYZ/Z calibration.
Support multi screen messages in the XYZ/Z calibration - "move the Z carriages up" step.
Support up to three lines in the XYZ/Z calibration messages.
Added a new message "Measuring reference height of calibration point xx of 9".
Changed the "move the Z carriages up" message to suggest rotating the knob.
Changed the "live adjust not set" message to reference the manual chapter and section.
Remove debugging serial line output on Z calibration.
Removed the non-working pressure advance feature.
Improved accuracy of diagonal moves by oversampling the path discretization.
Accelerated the planner by rewriting time critical routines from floating
point to fixed point arithmetics.

bubnikv 8 年之前
父节点
当前提交
e0bb76032c

+ 1 - 1
Firmware/Configuration.h

@@ -5,7 +5,7 @@
 #include "Configuration_prusa.h"
 
 // Firmware version
-#define FW_version "3.0.7"
+#define FW_version "3.0.8"
 
 #define FW_PRUSA3D_MAGIC "PRUSA3DFW"
 #define FW_PRUSA3D_MAGIC_LEN 10

+ 8 - 19
Firmware/Marlin_main.cpp

@@ -1021,6 +1021,9 @@ void setup()
 
   // Enable Toshiba FlashAir SD card / WiFi enahanced card.
   card.ToshibaFlashAir_enable(eeprom_read_byte((unsigned char*)EEPROM_TOSHIBA_FLASH_AIR_COMPATIBLITY) == 1);
+  // Force SD card update. Otherwise the SD card update is done from loop() on card.checkautostart(false), 
+  // but this times out if a blocking dialog is shown in setup().
+  card.initsd();
 
   if (eeprom_read_dword((uint32_t*)(EEPROM_TOP-4)) == 0x0ffffffff && 
       eeprom_read_dword((uint32_t*)(EEPROM_TOP-8)) == 0x0ffffffff &&
@@ -1038,22 +1041,15 @@ void setup()
   // is being written into the EEPROM, so the update procedure will be triggered only once.
     lang_selected = eeprom_read_byte((uint8_t*)EEPROM_LANG);
     if (lang_selected >= LANG_NUM){
-    lcd_mylang();
+      lcd_mylang();
     }
     
   if (eeprom_read_byte((uint8_t*)EEPROM_BABYSTEP_Z_SET) == 0x0ff) {
       // Reset the babystepping values, so the printer will not move the Z axis up when the babystepping is enabled.
-      // eeprom_update_byte((uint8_t*)EEPROM_BABYSTEP_X, 0x0ff);
-      // eeprom_update_byte((uint8_t*)EEPROM_BABYSTEP_Y, 0x0ff);
-      eeprom_update_byte((uint8_t*)EEPROM_BABYSTEP_Z, 0x0ff);
-      // Get the selected laugnage index before display update.
-      lang_selected = eeprom_read_byte((uint8_t*)EEPROM_LANG);
-      if (lang_selected >= LANG_NUM)
-          lang_selected = LANG_ID_DEFAULT; // Czech language
+      eeprom_update_word((uint16_t*)EEPROM_BABYSTEP_Z, 0);
       // Show the message.
       lcd_show_fullscreen_message_and_wait_P(MSG_BABYSTEP_Z_NOT_SET);
       lcd_update_enable(true);
-      lcd_implementation_clear();
   }
 
   // Store the currently running firmware into an eeprom,
@@ -2961,6 +2957,9 @@ void process_commands()
                 bool result = sample_mesh_and_store_reference();
                 // if (result) babystep_apply();
             } else {
+                // Reset the baby step value and the baby step applied flag.
+                eeprom_write_byte((unsigned char*)EEPROM_BABYSTEP_Z_SET, 0xFF);
+                eeprom_update_word((uint16_t*)EEPROM_BABYSTEP_Z, 0);
                 // Complete XYZ calibration.
                 BedSkewOffsetDetectionResultType result = find_bed_offset_and_skew(verbosity_level);
                 uint8_t point_too_far_mask = 0;
@@ -2991,9 +2990,6 @@ void process_commands()
             // Timeouted.
         }
         lcd_update_enable(true);
-        lcd_implementation_clear();
-        // lcd_return_to_status();
-        lcd_update();
         break;
     }
 
@@ -3057,9 +3053,6 @@ void process_commands()
         plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS],current_position[Z_AXIS] , current_position[E_AXIS], homing_feedrate[Z_AXIS]/40, active_extruder);
         st_synchronize();
         lcd_update_enable(true);
-        lcd_implementation_clear();
-        // lcd_return_to_status();
-        lcd_update();
         break;
     }
 #endif
@@ -4824,11 +4817,7 @@ void prepare_move()
 
   // Do not use feedmultiply for E or Z only moves
   if( (current_position[X_AXIS] == destination [X_AXIS]) && (current_position[Y_AXIS] == destination [Y_AXIS])) {
-#ifdef MESH_BED_LEVELING
-      mesh_plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder);
-#else
       plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate/60, active_extruder);
-#endif
   }
   else {
 #ifdef MESH_BED_LEVELING

+ 64 - 64
Firmware/language_all.cpp

@@ -87,11 +87,11 @@ const char * const MSG_BABYSTEP_Z_LANG_TABLE[LANG_NUM] PROGMEM = {
 	MSG_BABYSTEP_Z_PL
 };
 
-const char MSG_BABYSTEP_Z_NOT_SET_EN[] PROGMEM = "Printer has not been calibrated yet. Run calibration G-code to adjust Z height.";
-const char MSG_BABYSTEP_Z_NOT_SET_CZ[] PROGMEM = "Tiskarna nebyla jeste zkalibrovana. Spustte kalibracni G-kod a doladte Z.";
-const char MSG_BABYSTEP_Z_NOT_SET_IT[] PROGMEM = "Stampante non ancora calibrata. Eseguire il G-code di calibrazione per regolare l'altezza Z.";
-const char MSG_BABYSTEP_Z_NOT_SET_ES[] PROGMEM = "Impresora aun no calibrada. Ejecutar el G-code de calibracion para ajustar la altura de Z.";
-const char MSG_BABYSTEP_Z_NOT_SET_PL[] PROGMEM = "Drukarka nie byla kalibrowana. Wlaczyc kalibracyjny G-kod i dostroic Z.";
+const char MSG_BABYSTEP_Z_NOT_SET_EN[] PROGMEM = "Printer has not been calibrated yet. Please follow the manual, chapter First steps, section Calibration flow.";
+const char MSG_BABYSTEP_Z_NOT_SET_CZ[] PROGMEM = "Tiskarna nebyla jeste zkalibrovana. Postupujte prosim podle manualu, kapitola Zaciname, odstavec Postup kalibrace.";
+const char MSG_BABYSTEP_Z_NOT_SET_IT[] PROGMEM = "Stampante ancora non calibrata. Si prega di seguire il manuale, capitolo PRIMI PASSI, sezione della calibrazione.";
+const char MSG_BABYSTEP_Z_NOT_SET_ES[] PROGMEM = "Impresora no esta calibrada todavia. Por favor usar el manual, el capitulo First steps, seleccion Calibration flow.";
+const char MSG_BABYSTEP_Z_NOT_SET_PL[] PROGMEM = "Drukarka nie zostala jeszcze skalibrowana. Prosze kierowac sie instrukcja, rozdzial Zaczynamy, podrozdzial Selftest.";
 const char * const MSG_BABYSTEP_Z_NOT_SET_LANG_TABLE[LANG_NUM] PROGMEM = {
 	MSG_BABYSTEP_Z_NOT_SET_EN,
 	MSG_BABYSTEP_Z_NOT_SET_CZ,
@@ -652,7 +652,7 @@ const char * const MSG_FACTOR_LANG_TABLE[1] PROGMEM = {
 
 const char MSG_FAN_SPEED_EN[] PROGMEM = "Fan speed";
 const char MSG_FAN_SPEED_CZ[] PROGMEM = "Rychlost vent.";
-const char MSG_FAN_SPEED_IT[] PROGMEM = "Velocità ventola";
+const char MSG_FAN_SPEED_IT[] PROGMEM = "Velocita ventola";
 const char MSG_FAN_SPEED_ES[] PROGMEM = "Ventilador";
 const char MSG_FAN_SPEED_PL[] PROGMEM = "Predkosc went.";
 const char * const MSG_FAN_SPEED_LANG_TABLE[LANG_NUM] PROGMEM = {
@@ -686,11 +686,11 @@ const char * const MSG_FILE_SAVED_LANG_TABLE[1] PROGMEM = {
 	MSG_FILE_SAVED_EN
 };
 
-const char MSG_FIND_BED_OFFSET_AND_SKEW_LINE1_EN[] PROGMEM = "Searching bed";
-const char MSG_FIND_BED_OFFSET_AND_SKEW_LINE1_CZ[] PROGMEM = "Hledam kalibracni";
-const char MSG_FIND_BED_OFFSET_AND_SKEW_LINE1_IT[] PROGMEM = "Ricerca del letto";
-const char MSG_FIND_BED_OFFSET_AND_SKEW_LINE1_ES[] PROGMEM = "Buscando cama";
-const char MSG_FIND_BED_OFFSET_AND_SKEW_LINE1_PL[] PROGMEM = "Szukam kalibracyj.";
+const char MSG_FIND_BED_OFFSET_AND_SKEW_LINE1_EN[] PROGMEM = "Searching bed calibration point";
+const char MSG_FIND_BED_OFFSET_AND_SKEW_LINE1_CZ[] PROGMEM = "Hledam kalibracni bod podlozky";
+const char MSG_FIND_BED_OFFSET_AND_SKEW_LINE1_IT[] PROGMEM = "Ricerca del letto punto di calibraz.";
+const char MSG_FIND_BED_OFFSET_AND_SKEW_LINE1_ES[] PROGMEM = "Buscando cama punto de calibracion";
+const char MSG_FIND_BED_OFFSET_AND_SKEW_LINE1_PL[] PROGMEM = "Szukam punktu kalibracyjnego podkladki";
 const char * const MSG_FIND_BED_OFFSET_AND_SKEW_LINE1_LANG_TABLE[LANG_NUM] PROGMEM = {
 	MSG_FIND_BED_OFFSET_AND_SKEW_LINE1_EN,
 	MSG_FIND_BED_OFFSET_AND_SKEW_LINE1_CZ,
@@ -699,11 +699,11 @@ const char * const MSG_FIND_BED_OFFSET_AND_SKEW_LINE1_LANG_TABLE[LANG_NUM] PROGM
 	MSG_FIND_BED_OFFSET_AND_SKEW_LINE1_PL
 };
 
-const char MSG_FIND_BED_OFFSET_AND_SKEW_LINE2_EN[] PROGMEM = "calibration point";
-const char MSG_FIND_BED_OFFSET_AND_SKEW_LINE2_CZ[] PROGMEM = "bod podlozky";
-const char MSG_FIND_BED_OFFSET_AND_SKEW_LINE2_IT[] PROGMEM = "punto di calibraz.";
-const char MSG_FIND_BED_OFFSET_AND_SKEW_LINE2_ES[] PROGMEM = "punto de calibracion";
-const char MSG_FIND_BED_OFFSET_AND_SKEW_LINE2_PL[] PROGMEM = "punktu podkladki";
+const char MSG_FIND_BED_OFFSET_AND_SKEW_LINE2_EN[] PROGMEM = " of 4";
+const char MSG_FIND_BED_OFFSET_AND_SKEW_LINE2_CZ[] PROGMEM = " z 4";
+const char MSG_FIND_BED_OFFSET_AND_SKEW_LINE2_IT[] PROGMEM = " su 4";
+const char MSG_FIND_BED_OFFSET_AND_SKEW_LINE2_ES[] PROGMEM = " de 4";
+const char MSG_FIND_BED_OFFSET_AND_SKEW_LINE2_PL[] PROGMEM = " z 4";
 const char * const MSG_FIND_BED_OFFSET_AND_SKEW_LINE2_LANG_TABLE[LANG_NUM] PROGMEM = {
 	MSG_FIND_BED_OFFSET_AND_SKEW_LINE2_EN,
 	MSG_FIND_BED_OFFSET_AND_SKEW_LINE2_CZ,
@@ -712,19 +712,6 @@ const char * const MSG_FIND_BED_OFFSET_AND_SKEW_LINE2_LANG_TABLE[LANG_NUM] PROGM
 	MSG_FIND_BED_OFFSET_AND_SKEW_LINE2_PL
 };
 
-const char MSG_FIND_BED_OFFSET_AND_SKEW_LINE3_EN[] PROGMEM = " of 4";
-const char MSG_FIND_BED_OFFSET_AND_SKEW_LINE3_CZ[] PROGMEM = " z 4";
-const char MSG_FIND_BED_OFFSET_AND_SKEW_LINE3_IT[] PROGMEM = " su 4";
-const char MSG_FIND_BED_OFFSET_AND_SKEW_LINE3_ES[] PROGMEM = " de 4";
-const char MSG_FIND_BED_OFFSET_AND_SKEW_LINE3_PL[] PROGMEM = " z 4";
-const char * const MSG_FIND_BED_OFFSET_AND_SKEW_LINE3_LANG_TABLE[LANG_NUM] PROGMEM = {
-	MSG_FIND_BED_OFFSET_AND_SKEW_LINE3_EN,
-	MSG_FIND_BED_OFFSET_AND_SKEW_LINE3_CZ,
-	MSG_FIND_BED_OFFSET_AND_SKEW_LINE3_IT,
-	MSG_FIND_BED_OFFSET_AND_SKEW_LINE3_ES,
-	MSG_FIND_BED_OFFSET_AND_SKEW_LINE3_PL
-};
-
 const char MSG_FLOW_EN[] PROGMEM = "Flow";
 const char MSG_FLOW_CZ[] PROGMEM = "Prutok";
 const char MSG_FLOW_IT[] PROGMEM = "Flusso";
@@ -828,11 +815,11 @@ const char * const MSG_HOTEND_OFFSET_LANG_TABLE[1] PROGMEM = {
 	MSG_HOTEND_OFFSET_EN
 };
 
-const char MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1_EN[] PROGMEM = "Improving bed";
-const char MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1_CZ[] PROGMEM = "Zlepsuji presnost";
-const char MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1_IT[] PROGMEM = "Perfezion. il letto";
-const char MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1_ES[] PROGMEM = "Mejorando cama";
-const char MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1_PL[] PROGMEM = "Ulepszam dokladnosc";
+const char MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1_EN[] PROGMEM = "Improving bed calibration point";
+const char MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1_CZ[] PROGMEM = "Zlepsuji presnost kalibracniho bodu";
+const char MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1_IT[] PROGMEM = "Perfezion. il letto punto di calibraz.";
+const char MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1_ES[] PROGMEM = "Mejorando cama punto de calibracion";
+const char MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1_PL[] PROGMEM = "Poprawiam precyzyjnosc punktu kalibracyjnego";
 const char * const MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1_LANG_TABLE[LANG_NUM] PROGMEM = {
 	MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1_EN,
 	MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1_CZ,
@@ -841,11 +828,11 @@ const char * const MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1_LANG_TABLE[LANG_NUM] PR
 	MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1_PL
 };
 
-const char MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2_EN[] PROGMEM = "calibration point";
-const char MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2_CZ[] PROGMEM = "kalibracniho bodu";
-const char MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2_IT[] PROGMEM = "punto di calibraz.";
-const char MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2_ES[] PROGMEM = "punto de calibracion";
-const char MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2_PL[] PROGMEM = "punktu kalibracyj.";
+const char MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2_EN[] PROGMEM = " of 9";
+const char MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2_CZ[] PROGMEM = " z 9";
+const char MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2_IT[] PROGMEM = " su 9";
+const char MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2_ES[] PROGMEM = " de 9";
+const char MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2_PL[] PROGMEM = " z 9";
 const char * const MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2_LANG_TABLE[LANG_NUM] PROGMEM = {
 	MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2_EN,
 	MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2_CZ,
@@ -854,19 +841,6 @@ const char * const MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2_LANG_TABLE[LANG_NUM] PR
 	MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2_PL
 };
 
-const char MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE3_EN[] PROGMEM = " of 9";
-const char MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE3_CZ[] PROGMEM = " z 9";
-const char MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE3_IT[] PROGMEM = " su 9";
-const char MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE3_ES[] PROGMEM = " de 9";
-const char MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE3_PL[] PROGMEM = " z 9";
-const char * const MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE3_LANG_TABLE[LANG_NUM] PROGMEM = {
-	MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE3_EN,
-	MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE3_CZ,
-	MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE3_IT,
-	MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE3_ES,
-	MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE3_PL
-};
-
 const char MSG_INIT_SDCARD_EN[] PROGMEM = "Init. SD card";
 const char * const MSG_INIT_SDCARD_LANG_TABLE[1] PROGMEM = {
 	MSG_INIT_SDCARD_EN
@@ -1029,6 +1003,32 @@ const char * const MSG_MAX_LANG_TABLE[1] PROGMEM = {
 	MSG_MAX_EN
 };
 
+const char MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE1_EN[] PROGMEM = "Measuring reference height of calibration point";
+const char MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE1_CZ[] PROGMEM = "Merim referencni vysku kalibracniho bodu";
+const char MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE1_IT[] PROGMEM = "Misurare l'altezza di riferimento del punto di calibrazione";
+const char MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE1_ES[] PROGMEM = "Medir la altura del punto de la calibracion";
+const char MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE1_PL[] PROGMEM = "Okreslam wysokosc odniesienia punktu kalibracyjnego";
+const char * const MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE1_LANG_TABLE[LANG_NUM] PROGMEM = {
+	MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE1_EN,
+	MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE1_CZ,
+	MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE1_IT,
+	MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE1_ES,
+	MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE1_PL
+};
+
+const char MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2_EN[] PROGMEM = " of 9";
+const char MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2_CZ[] PROGMEM = " z 9";
+const char MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2_IT[] PROGMEM = " su 9";
+const char MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2_ES[] PROGMEM = " de 9";
+const char MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2_PL[] PROGMEM = " z 9";
+const char * const MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2_LANG_TABLE[LANG_NUM] PROGMEM = {
+	MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2_EN,
+	MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2_CZ,
+	MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2_IT,
+	MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2_ES,
+	MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2_PL
+};
+
 const char MSG_MENU_CALIBRATION_EN[] PROGMEM = "Calibration";
 const char MSG_MENU_CALIBRATION_CZ[] PROGMEM = "Kalibrace";
 const char MSG_MENU_CALIBRATION_IT[] PROGMEM = "Calibrazione";
@@ -1090,11 +1090,11 @@ const char * const MSG_MOVE_AXIS_LANG_TABLE[LANG_NUM] PROGMEM = {
 	MSG_MOVE_AXIS_PL
 };
 
-const char MSG_MOVE_CARRIAGE_TO_THE_TOP_EN[] PROGMEM = "Calibrating XYZ. Move Z carriage up to the end stoppers. Click when done.";
-const char MSG_MOVE_CARRIAGE_TO_THE_TOP_CZ[] PROGMEM = "Kalibrace XYZ. Posunte prosim Z osu az k~hornimu dorazu. Potvrdte tlacitkem.";
-const char MSG_MOVE_CARRIAGE_TO_THE_TOP_IT[] PROGMEM = "Calibrando XYZ. Muovere Z fino altezza max, poi fare clik.";
-const char MSG_MOVE_CARRIAGE_TO_THE_TOP_ES[] PROGMEM = "Calibrando XYZ. Subir carro Z hasta maximo. Click cuando acabes.";
-const char MSG_MOVE_CARRIAGE_TO_THE_TOP_PL[] PROGMEM = "Kalibracja XYZ. Prosze przesunac os Z do gornej ramy. Potw. guzikiem.";
+const char MSG_MOVE_CARRIAGE_TO_THE_TOP_EN[] PROGMEM = "Calibrating XYZ. Rotate the knob to move the Z carriage up to the end stoppers. Click when done.";
+const char MSG_MOVE_CARRIAGE_TO_THE_TOP_CZ[] PROGMEM = "Kalibrace XYZ. Otacenim tlacitka posunte Z osu az k~hornimu dorazu. Potvrdte tlacitkem.";
+const char MSG_MOVE_CARRIAGE_TO_THE_TOP_IT[] PROGMEM = "Calibrazione XYZ. Ruotare la manopola per alzare il carrello Z fino all'altezza massima. Click per terminare.";
+const char MSG_MOVE_CARRIAGE_TO_THE_TOP_ES[] PROGMEM = "Calibrando XYZ. Gira el boton para subir el carro Z hasta golpe piezas superioras. Despues haz clic.";
+const char MSG_MOVE_CARRIAGE_TO_THE_TOP_PL[] PROGMEM = "Kalibracja XYZ. Przekrec galke, aby przesunac os Z do gornych krancowek. Nacisnij, by potwierdzic.";
 const char * const MSG_MOVE_CARRIAGE_TO_THE_TOP_LANG_TABLE[LANG_NUM] PROGMEM = {
 	MSG_MOVE_CARRIAGE_TO_THE_TOP_EN,
 	MSG_MOVE_CARRIAGE_TO_THE_TOP_CZ,
@@ -1103,11 +1103,11 @@ const char * const MSG_MOVE_CARRIAGE_TO_THE_TOP_LANG_TABLE[LANG_NUM] PROGMEM = {
 	MSG_MOVE_CARRIAGE_TO_THE_TOP_PL
 };
 
-const char MSG_MOVE_CARRIAGE_TO_THE_TOP_Z_EN[] PROGMEM = "Calibrating Z. Move Z carriage up to the end stoppers. Click when done.";
-const char MSG_MOVE_CARRIAGE_TO_THE_TOP_Z_CZ[] PROGMEM = "Kalibrace Z. Posunte prosim Z osu az k~hornimu dorazu. Potvrdte tlacitkem.";
-const char MSG_MOVE_CARRIAGE_TO_THE_TOP_Z_IT[] PROGMEM = "Calibrando Z. Muovere Z fino altezza max, poi fare clik.";
-const char MSG_MOVE_CARRIAGE_TO_THE_TOP_Z_ES[] PROGMEM = "Calibrando Z. Subir carro Z hasta maximo. Click cuando acabes.";
-const char MSG_MOVE_CARRIAGE_TO_THE_TOP_Z_PL[] PROGMEM = "Kalibracja Z. Prosze przesunac os Z do gornej ramy. Potw. guzikiem.";
+const char MSG_MOVE_CARRIAGE_TO_THE_TOP_Z_EN[] PROGMEM = "Calibrating Z. Rotate the knob to move the Z carriage up to the end stoppers. Click when done.";
+const char MSG_MOVE_CARRIAGE_TO_THE_TOP_Z_CZ[] PROGMEM = "Kalibrace Z. Otacenim tlacitka posunte Z osu az k~hornimu dorazu. Potvrdte tlacitkem.";
+const char MSG_MOVE_CARRIAGE_TO_THE_TOP_Z_IT[] PROGMEM = "Calibrazione Z. Ruotare la manopola per alzare il carrello Z fino all'altezza massima. Click per terminare.";
+const char MSG_MOVE_CARRIAGE_TO_THE_TOP_Z_ES[] PROGMEM = "Calibrando Z. Gira el boton para subir el carro Z hasta golpe piezas superioras. Despues haz clic.";
+const char MSG_MOVE_CARRIAGE_TO_THE_TOP_Z_PL[] PROGMEM = "Kalibracja Z. Przekrec galke, aby przesunac os Z do gornych krancowek. Nacisnij, by potwierdzic.";
 const char * const MSG_MOVE_CARRIAGE_TO_THE_TOP_Z_LANG_TABLE[LANG_NUM] PROGMEM = {
 	MSG_MOVE_CARRIAGE_TO_THE_TOP_Z_EN,
 	MSG_MOVE_CARRIAGE_TO_THE_TOP_Z_CZ,
@@ -1830,7 +1830,7 @@ const char * const MSG_SELFTEST_START_LANG_TABLE[LANG_NUM] PROGMEM = {
 const char MSG_SELFTEST_WIRINGERROR_EN[] PROGMEM = "Wiring error";
 const char MSG_SELFTEST_WIRINGERROR_CZ[] PROGMEM = "Chyba zapojeni";
 const char MSG_SELFTEST_WIRINGERROR_IT[] PROGMEM = "Errore cablaggio";
-const char MSG_SELFTEST_WIRINGERROR_ES[] PROGMEM = "Error de conexión";
+const char MSG_SELFTEST_WIRINGERROR_ES[] PROGMEM = "Error de conexion";
 const char MSG_SELFTEST_WIRINGERROR_PL[] PROGMEM = "Blad polaczenia";
 const char * const MSG_SELFTEST_WIRINGERROR_LANG_TABLE[LANG_NUM] PROGMEM = {
 	MSG_SELFTEST_WIRINGERROR_EN,
@@ -1914,7 +1914,7 @@ const char * const MSG_SOFTWARE_RESET_LANG_TABLE[1] PROGMEM = {
 
 const char MSG_SPEED_EN[] PROGMEM = "Speed";
 const char MSG_SPEED_CZ[] PROGMEM = "Rychlost";
-const char MSG_SPEED_IT[] PROGMEM = "Velocità";
+const char MSG_SPEED_IT[] PROGMEM = "Velocita";
 const char MSG_SPEED_ES[] PROGMEM = "Velocidad";
 const char MSG_SPEED_PL[] PROGMEM = "Predkosc";
 const char * const MSG_SPEED_LANG_TABLE[LANG_NUM] PROGMEM = {

+ 4 - 4
Firmware/language_all.h

@@ -176,8 +176,6 @@ extern const char* const MSG_FIND_BED_OFFSET_AND_SKEW_LINE1_LANG_TABLE[LANG_NUM]
 #define MSG_FIND_BED_OFFSET_AND_SKEW_LINE1 LANG_TABLE_SELECT(MSG_FIND_BED_OFFSET_AND_SKEW_LINE1_LANG_TABLE)
 extern const char* const MSG_FIND_BED_OFFSET_AND_SKEW_LINE2_LANG_TABLE[LANG_NUM];
 #define MSG_FIND_BED_OFFSET_AND_SKEW_LINE2 LANG_TABLE_SELECT(MSG_FIND_BED_OFFSET_AND_SKEW_LINE2_LANG_TABLE)
-extern const char* const MSG_FIND_BED_OFFSET_AND_SKEW_LINE3_LANG_TABLE[LANG_NUM];
-#define MSG_FIND_BED_OFFSET_AND_SKEW_LINE3 LANG_TABLE_SELECT(MSG_FIND_BED_OFFSET_AND_SKEW_LINE3_LANG_TABLE)
 extern const char* const MSG_FLOW_LANG_TABLE[LANG_NUM];
 #define MSG_FLOW LANG_TABLE_SELECT(MSG_FLOW_LANG_TABLE)
 extern const char* const MSG_FLOW0_LANG_TABLE[1];
@@ -204,8 +202,6 @@ extern const char* const MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1_LANG_TABLE[LANG_N
 #define MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1 LANG_TABLE_SELECT(MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1_LANG_TABLE)
 extern const char* const MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2_LANG_TABLE[LANG_NUM];
 #define MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2 LANG_TABLE_SELECT(MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2_LANG_TABLE)
-extern const char* const MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE3_LANG_TABLE[LANG_NUM];
-#define MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE3 LANG_TABLE_SELECT(MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE3_LANG_TABLE)
 extern const char* const MSG_INIT_SDCARD_LANG_TABLE[1];
 #define MSG_INIT_SDCARD LANG_TABLE_SELECT_EXPLICIT(MSG_INIT_SDCARD_LANG_TABLE, 0)
 extern const char* const MSG_INSERT_FILAMENT_LANG_TABLE[LANG_NUM];
@@ -248,6 +244,10 @@ extern const char* const MSG_MAIN_LANG_TABLE[LANG_NUM];
 #define MSG_MAIN LANG_TABLE_SELECT(MSG_MAIN_LANG_TABLE)
 extern const char* const MSG_MAX_LANG_TABLE[1];
 #define MSG_MAX LANG_TABLE_SELECT_EXPLICIT(MSG_MAX_LANG_TABLE, 0)
+extern const char* const MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE1_LANG_TABLE[LANG_NUM];
+#define MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE1 LANG_TABLE_SELECT(MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE1_LANG_TABLE)
+extern const char* const MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2_LANG_TABLE[LANG_NUM];
+#define MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2 LANG_TABLE_SELECT(MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2_LANG_TABLE)
 extern const char* const MSG_MENU_CALIBRATION_LANG_TABLE[LANG_NUM];
 #define MSG_MENU_CALIBRATION LANG_TABLE_SELECT(MSG_MENU_CALIBRATION_LANG_TABLE)
 extern const char* const MSG_MESH_BED_LEVELING_LANG_TABLE[LANG_NUM];

+ 9 - 9
Firmware/language_cz.h

@@ -194,18 +194,18 @@
 #define MSG_CALIBRATE_BED					"Kalibrace XYZ"
 #define MSG_CALIBRATE_BED_RESET				"Reset XYZ kalibr."
 
-#define MSG_MOVE_CARRIAGE_TO_THE_TOP		"Kalibrace XYZ. Posunte prosim Z osu az k~hornimu dorazu. Potvrdte tlacitkem."
-#define MSG_MOVE_CARRIAGE_TO_THE_TOP_Z		"Kalibrace Z. Posunte prosim Z osu az k~hornimu dorazu. Potvrdte tlacitkem."
+#define MSG_MOVE_CARRIAGE_TO_THE_TOP		"Kalibrace XYZ. Otacenim tlacitka posunte Z osu az k~hornimu dorazu. Potvrdte tlacitkem."
+#define MSG_MOVE_CARRIAGE_TO_THE_TOP_Z		"Kalibrace Z. Otacenim tlacitka posunte Z osu az k~hornimu dorazu. Potvrdte tlacitkem."
 
 #define MSG_CONFIRM_NOZZLE_CLEAN			"Pro uspesnou kalibraci ocistete prosim tiskovou trysku. Potvrdte tlacitkem."
 #define MSG_CONFIRM_CARRIAGE_AT_THE_TOP		"Dojely oba Z voziky k~hornimu dorazu?"
 
-#define MSG_FIND_BED_OFFSET_AND_SKEW_LINE1	"Hledam kalibracni"
-#define MSG_FIND_BED_OFFSET_AND_SKEW_LINE2	"bod podlozky"
-#define MSG_FIND_BED_OFFSET_AND_SKEW_LINE3	" z 4"
-#define MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1	"Zlepsuji presnost"
-#define MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2	"kalibracniho bodu"
-#define MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE3	" z 9"
+#define MSG_FIND_BED_OFFSET_AND_SKEW_LINE1	"Hledam kalibracni bod podlozky"
+#define MSG_FIND_BED_OFFSET_AND_SKEW_LINE2	" z 4"
+#define MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1	"Zlepsuji presnost kalibracniho bodu"
+#define MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2	" z 9"
+#define MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE1	"Merim referencni vysku kalibracniho bodu"
+#define MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2	" z 9"
 
 #define MSG_BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND			"Kalibrace XYZ selhala. Kalibracni bod podlozky nenalezen."
 #define MSG_BED_SKEW_OFFSET_DETECTION_FITTING_FAILED			"Kalibrace XYZ selhala. Nahlednete do manualu."
@@ -225,7 +225,7 @@
 
 #define MSG_NEW_FIRMWARE_AVAILABLE								"Vysla nova verze firmware:"
 #define MSG_NEW_FIRMWARE_PLEASE_UPGRADE							"Prosim aktualizujte."
-#define MSG_BABYSTEP_Z_NOT_SET                          		"Tiskarna nebyla jeste zkalibrovana. Spustte kalibracni G-kod a doladte Z."
+#define MSG_BABYSTEP_Z_NOT_SET                          		"Tiskarna nebyla jeste zkalibrovana. Postupujte prosim podle manualu, kapitola Zaciname, odstavec Postup kalibrace."
 
 #define MSG_BED_CORRECTION_MENU									"Korekce podlozky"
 #define MSG_BED_CORRECTION_LEFT									"Vlevo  [um]"

+ 10 - 10
Firmware/language_en.h

@@ -188,18 +188,18 @@
 #define MSG_CALIBRATE_BED					"Calibrate XYZ"
 #define MSG_CALIBRATE_BED_RESET				"Reset XYZ calibr."
 
-#define(length=20,lines=4) MSG_MOVE_CARRIAGE_TO_THE_TOP 	"Calibrating XYZ. Move Z carriage up to the end stoppers. Click when done."
-#define(length=20,lines=4) MSG_MOVE_CARRIAGE_TO_THE_TOP_Z 	"Calibrating Z. Move Z carriage up to the end stoppers. Click when done."
+#define(length=20,lines=8) MSG_MOVE_CARRIAGE_TO_THE_TOP 	"Calibrating XYZ. Rotate the knob to move the Z carriage up to the end stoppers. Click when done."
+#define(length=20,lines=8) MSG_MOVE_CARRIAGE_TO_THE_TOP_Z 	"Calibrating Z. Rotate the knob to move the Z carriage up to the end stoppers. Click when done."
 
 #define(length=20,lines=8) MSG_CONFIRM_NOZZLE_CLEAN			"Please clean the nozzle for calibration. Click when done."
 #define(length=20,lines=2) MSG_CONFIRM_CARRIAGE_AT_THE_TOP	"Are left and right Z~carriages all up?"
 
-#define(length=20) MSG_FIND_BED_OFFSET_AND_SKEW_LINE1	"Searching bed"
-#define(length=20) MSG_FIND_BED_OFFSET_AND_SKEW_LINE2	"calibration point"
-#define(length=14) MSG_FIND_BED_OFFSET_AND_SKEW_LINE3	" of 4"
-#define(length=20) MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1	"Improving bed"
-#define(length=20) MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2	"calibration point"
-#define(length=14) MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE3	" of 9"
+#define(length=60) MSG_FIND_BED_OFFSET_AND_SKEW_LINE1		"Searching bed calibration point"
+#define(length=14) MSG_FIND_BED_OFFSET_AND_SKEW_LINE2		" of 4"
+#define(length=60) MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1	"Improving bed calibration point"
+#define(length=14) MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2	" of 9"
+#define(length=60) MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE1	"Measuring reference height of calibration point"
+#define(length=14) MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2	" of 9"
 
 #define(length=20,lines=8) MSG_BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND			"XYZ calibration failed. Bed calibration point was not found."
 #define(length=20,lines=8) MSG_BED_SKEW_OFFSET_DETECTION_FITTING_FAILED				"XYZ calibration failed. Please consult the manual."
@@ -218,9 +218,9 @@
 #define(length=20,lines=4) MSG_BED_LEVELING_FAILED_PROBE_DISCONNECTED				"Bed leveling failed. Sensor disconnected or cable broken. Waiting for reset."
 
 #define(length=20,lines=2) MSG_NEW_FIRMWARE_AVAILABLE								"New firmware version available:"
-#define(length=20) MSG_NEW_FIRMWARE_PLEASE_UPGRADE												"Please upgrade."
+#define(length=20) MSG_NEW_FIRMWARE_PLEASE_UPGRADE									"Please upgrade."
 
-#define(length=20,lines=8) MSG_BABYSTEP_Z_NOT_SET									"Printer has not been calibrated yet. Run calibration G-code to adjust Z height."
+#define(length=20,lines=8) MSG_BABYSTEP_Z_NOT_SET									"Printer has not been calibrated yet. Please follow the manual, chapter First steps, section Calibration flow."
 
 #define MSG_BED_CORRECTION_MENU									"Bed level correct"
 #define MSG_BED_CORRECTION_LEFT									"Left side  um"

+ 11 - 10
Firmware/language_es.h

@@ -159,7 +159,7 @@
 #define MSG_SELFTEST_NOTCONNECTED           "No hay conexion  "
 #define MSG_SELFTEST_HEATERTHERMISTOR       "Calent./Termistor"
 #define MSG_SELFTEST_BEDHEATER              "Cama/Calentador"
-#define MSG_SELFTEST_WIRINGERROR            "Error de conexión"
+#define MSG_SELFTEST_WIRINGERROR            "Error de conexion"
 #define MSG_SELFTEST_ENDSTOPS               "Topes final"
 #define MSG_SELFTEST_MOTOR                  "Motor"
 #define MSG_SELFTEST_ENDSTOP                "Tope final"
@@ -188,17 +188,18 @@
 #define MSG_SHOW_END_STOPS                  "Ensena tope final"
 #define MSG_CALIBRATE_BED                   "Calibra XYZ"
 #define MSG_CALIBRATE_BED_RESET             "Reset XYZ calibr."
-#define MSG_MOVE_CARRIAGE_TO_THE_TOP        "Calibrando XYZ. Subir carro Z hasta maximo. Click cuando acabes."
-#define MSG_MOVE_CARRIAGE_TO_THE_TOP_Z        "Calibrando Z. Subir carro Z hasta maximo. Click cuando acabes."
+#define MSG_MOVE_CARRIAGE_TO_THE_TOP        "Calibrando XYZ. Gira el boton para subir el carro Z hasta golpe piezas superioras. Despues haz clic."
+#define MSG_MOVE_CARRIAGE_TO_THE_TOP_Z       "Calibrando Z. Gira el boton para subir el carro Z hasta golpe piezas superioras. Despues haz clic."
 
 #define MSG_CONFIRM_NOZZLE_CLEAN            "Limpiar boquilla para calibracion. Click cuando acabes."
 #define MSG_CONFIRM_CARRIAGE_AT_THE_TOP     "Carros Z izq./der. estan arriba maximo?"
-#define MSG_FIND_BED_OFFSET_AND_SKEW_LINE1  "Buscando cama"
-#define MSG_FIND_BED_OFFSET_AND_SKEW_LINE2  "punto de calibracion"
-#define MSG_FIND_BED_OFFSET_AND_SKEW_LINE3  " de 4"
-#define MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1   "Mejorando cama"
-#define MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2   "punto de calibracion"
-#define MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE3   " de 9"
+#define MSG_FIND_BED_OFFSET_AND_SKEW_LINE1  "Buscando cama punto de calibracion"
+#define MSG_FIND_BED_OFFSET_AND_SKEW_LINE2  " de 4"
+#define MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1   "Mejorando cama punto de calibracion"
+#define MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2   " de 9"
+#define MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE1	"Medir la altura del punto de la calibracion"
+#define MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2	" de 9"
+
 #define MSG_BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND           "Calibracion XYZ fallada. Puntos de calibracion en la cama no encontrados."
 #define MSG_BED_SKEW_OFFSET_DETECTION_FITTING_FAILED            "Calibracion XYZ fallada. Consultar el manual por favor."
 #define MSG_BED_SKEW_OFFSET_DETECTION_PERFECT               "Calibracion XYZ ok. Ejes X/Y perpendiculares."
@@ -215,7 +216,7 @@
 #define MSG_BED_LEVELING_FAILED_PROBE_DISCONNECTED      			"Nivelacion fallada. Sensor desconectado o cables danados. Esperando reset."
 #define MSG_NEW_FIRMWARE_AVAILABLE                  				"Nuevo firmware disponible:"
 #define MSG_NEW_FIRMWARE_PLEASE_UPGRADE                 			"Actualizar por favor"
-#define MSG_BABYSTEP_Z_NOT_SET                      			"Impresora aun no calibrada. Ejecutar el G-code de calibracion para ajustar la altura de Z."
+#define MSG_BABYSTEP_Z_NOT_SET                      			"Impresora no esta calibrada todavia. Por favor usar el manual, el capitulo First steps, seleccion Calibration flow."
 #define MSG_BED_CORRECTION_MENU                                 "Corr. de la cama"
 #define MSG_BED_CORRECTION_LEFT                                 "Izquierda [um]"
 #define MSG_BED_CORRECTION_RIGHT                                "Derecha   [um]"

+ 12 - 12
Firmware/language_it.h

@@ -17,17 +17,17 @@
 #define MSG_MOVE_01MM                       "Move 0.1mm"
 #define MSG_MOVE_1MM                        "Move 1mm"
 #define MSG_MOVE_10MM                       "Move 10mm"
-#define MSG_SPEED                           "Velocità"
+#define MSG_SPEED                           "Velocita"
 #define MSG_NOZZLE                          "Ugello"
 #define MSG_NOZZLE1                         "Nozzle2"
 #define MSG_NOZZLE2                         "Nozzle3"
 #define MSG_BED                             "Letto"
-#define MSG_FAN_SPEED                       "Velocità ventola"
+#define MSG_FAN_SPEED                       "Velocita ventola"
 #define MSG_FLOW                            "Flusso"
 #define MSG_TEMPERATURE                     "Temperatura"
 #define MSG_MOTION                          "Motion"
 #define MSG_VOLUMETRIC                      "Filament"
-#define MSG_VOLUMETRIC_ENABLED		    "E in mm3"
+#define MSG_VOLUMETRIC_ENABLED		    	"E in mm3"
 #define MSG_STORE_EPROM                     "Store memory"
 #define MSG_LOAD_EPROM                      "Load memory"
 #define MSG_RESTORE_FAILSAFE                "Restore failsafe"
@@ -177,18 +177,18 @@
 #define MSG_CALIBRATE_BED					"Calibra XYZ"
 #define MSG_CALIBRATE_BED_RESET					"Reset XYZ calibr."
 
-#define MSG_MOVE_CARRIAGE_TO_THE_TOP 				"Calibrando XYZ. Muovere Z fino altezza max, poi fare clik."
-#define MSG_MOVE_CARRIAGE_TO_THE_TOP_Z 				"Calibrando Z. Muovere Z fino altezza max, poi fare clik."
+#define MSG_MOVE_CARRIAGE_TO_THE_TOP 				"Calibrazione XYZ. Ruotare la manopola per alzare il carrello Z fino all'altezza massima. Click per terminare."
+#define MSG_MOVE_CARRIAGE_TO_THE_TOP_Z 				"Calibrazione Z. Ruotare la manopola per alzare il carrello Z fino all'altezza massima. Click per terminare."
 
 #define MSG_CONFIRM_NOZZLE_CLEAN					"Pulire l'ugello per la calibrazione, poi fare click."
 #define MSG_CONFIRM_CARRIAGE_AT_THE_TOP				"I carrelli Z sin/des sono altezza max?"
 
-#define MSG_FIND_BED_OFFSET_AND_SKEW_LINE1			"Ricerca del letto"
-#define MSG_FIND_BED_OFFSET_AND_SKEW_LINE2			"punto di calibraz."
-#define MSG_FIND_BED_OFFSET_AND_SKEW_LINE3			" su 4"
-#define MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1		"Perfezion. il letto"
-#define MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2		"punto di calibraz."
-#define MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE3		" su 9"
+#define MSG_FIND_BED_OFFSET_AND_SKEW_LINE1			"Ricerca del letto punto di calibraz."
+#define MSG_FIND_BED_OFFSET_AND_SKEW_LINE2			" su 4"
+#define MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1		"Perfezion. il letto punto di calibraz."
+#define MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2		" su 9"
+#define MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE1		"Misurare l'altezza di riferimento del punto di calibrazione"
+#define MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2		" su 9"
 
 #define MSG_BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND		"Calibrazione XYZ fallita. Il punto di calibrazione sul letto non e' stato trovato."
 #define MSG_BED_SKEW_OFFSET_DETECTION_FITTING_FAILED		"Calibrazione XYZ fallita. Si prega di consultare il manuale."
@@ -209,7 +209,7 @@
 #define MSG_NEW_FIRMWARE_AVAILABLE						"Nuova versione del firmware disponibile"
 #define MSG_NEW_FIRMWARE_PLEASE_UPGRADE					"Prega aggiorna."
 
-#define MSG_BABYSTEP_Z_NOT_SET							"Stampante non ancora calibrata. Eseguire il G-code di calibrazione per regolare l'altezza Z."
+#define MSG_BABYSTEP_Z_NOT_SET							"Stampante ancora non calibrata. Si prega di seguire il manuale, capitolo PRIMI PASSI, sezione della calibrazione."
 
 #define MSG_BED_CORRECTION_MENU							"Correz. liv.letto"
 #define MSG_BED_CORRECTION_LEFT							"Lato sinistro um"

+ 13 - 12
Firmware/language_pl.h

@@ -194,17 +194,18 @@
 #define MSG_SHOW_END_STOPS                  "Pokaz krancowki"
 #define MSG_CALIBRATE_BED                   "Kalibracja XYZ"
 #define MSG_CALIBRATE_BED_RESET             "Reset kalibr. XYZ"
-#define MSG_MOVE_CARRIAGE_TO_THE_TOP        "Kalibracja XYZ. Prosze przesunac os Z do gornej ramy. Potw. guzikiem."
-#define MSG_MOVE_CARRIAGE_TO_THE_TOP_Z        "Kalibracja Z. Prosze przesunac os Z do gornej ramy. Potw. guzikiem."
-
-#define MSG_CONFIRM_NOZZLE_CLEAN            "Dla prawidl. kalibracji prosze oczyscic dysze. Potw. guzikiem."
-#define MSG_CONFIRM_CARRIAGE_AT_THE_TOP     "Oba wozki dojechaly do gornej ramy?"
-#define MSG_FIND_BED_OFFSET_AND_SKEW_LINE1  "Szukam kalibracyj."
-#define MSG_FIND_BED_OFFSET_AND_SKEW_LINE2  "punktu podkladki"
-#define MSG_FIND_BED_OFFSET_AND_SKEW_LINE3  " z 4"
-#define MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1   "Ulepszam dokladnosc"
-#define MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2   "punktu kalibracyj."
-#define MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE3   " z 9"
+#define MSG_MOVE_CARRIAGE_TO_THE_TOP        "Kalibracja XYZ. Przekrec galke, aby przesunac os Z do gornych krancowek. Nacisnij, by potwierdzic."
+#define MSG_MOVE_CARRIAGE_TO_THE_TOP_Z      "Kalibracja Z. Przekrec galke, aby przesunac os Z do gornych krancowek. Nacisnij, by potwierdzic."
+
+#define MSG_CONFIRM_NOZZLE_CLEAN            		"Dla prawidl. kalibracji prosze oczyscic dysze. Potw. guzikiem."
+#define MSG_CONFIRM_CARRIAGE_AT_THE_TOP     		"Oba wozki dojechaly do gornej ramy?"
+#define MSG_FIND_BED_OFFSET_AND_SKEW_LINE1  		"Szukam punktu kalibracyjnego podkladki"
+#define MSG_FIND_BED_OFFSET_AND_SKEW_LINE2  		" z 4"
+#define MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1   	"Poprawiam precyzyjnosc punktu kalibracyjnego"
+#define MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2   	" z 9"
+#define MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE1		"Okreslam wysokosc odniesienia punktu kalibracyjnego"
+#define MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2		" z 9"
+
 #define MSG_BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND           "Kalibr. XYZ nieudana. Kalibracyjny punkt podkladki nieznaleziony."
 #define MSG_BED_SKEW_OFFSET_DETECTION_FITTING_FAILED            "Kalibracja XYZ niepowiedziona. Sprawdzic w instrukcji."
 #define MSG_BED_SKEW_OFFSET_DETECTION_PERFECT                   "Kalibracja XYZ ok. Osie X/Y sa prostopadle."
@@ -221,7 +222,7 @@
 #define MSG_BED_LEVELING_FAILED_PROBE_DISCONNECTED              "Kalibracja nieudana. Sensor odlaczony lub uszkodz. kabel. Czekam na reset."
 #define MSG_NEW_FIRMWARE_AVAILABLE                              "Wyszla nowa wersja firmware:"
 #define MSG_NEW_FIRMWARE_PLEASE_UPGRADE                         "Prosze zaktualizowac"
-#define MSG_BABYSTEP_Z_NOT_SET                                  "Drukarka nie byla kalibrowana. Wlaczyc kalibracyjny G-kod i dostroic Z."
+#define MSG_BABYSTEP_Z_NOT_SET                                  "Drukarka nie zostala jeszcze skalibrowana. Prosze kierowac sie instrukcja, rozdzial Zaczynamy, podrozdzial Selftest."
 #define MSG_BED_CORRECTION_MENU                                 "Korekta podkladki"
 #define MSG_BED_CORRECTION_LEFT                                 "W lewo  [um]"
 #define MSG_BED_CORRECTION_RIGHT                                "W prawo [um]"

+ 32 - 10
Firmware/mesh_bed_calibration.cpp

@@ -1547,8 +1547,10 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
 //    SERIAL_ECHOPGM("");
 
 #ifdef MESH_BED_CALIBRATION_SHOW_LCD
-    lcd_implementation_clear();
-    lcd_print_at_PGM(0, 0, MSG_FIND_BED_OFFSET_AND_SKEW_LINE1);
+    uint8_t next_line;
+    lcd_display_message_fullscreen_P(MSG_FIND_BED_OFFSET_AND_SKEW_LINE1, next_line);
+    if (next_line > 3)
+        next_line = 3;
 #endif /* MESH_BED_CALIBRATION_SHOW_LCD */
 
     // Collect the rear 2x3 points.
@@ -1557,9 +1559,8 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
         // Don't let the manage_inactivity() function remove power from the motors.
         refresh_cmd_timeout();
 #ifdef MESH_BED_CALIBRATION_SHOW_LCD
-        lcd_print_at_PGM(0, 1, MSG_FIND_BED_OFFSET_AND_SKEW_LINE2);
-        lcd_implementation_print_at(0, 2, k+1);
-        lcd_printPGM(MSG_FIND_BED_OFFSET_AND_SKEW_LINE3);
+        lcd_implementation_print_at(0, next_line, k+1);
+        lcd_printPGM(MSG_FIND_BED_OFFSET_AND_SKEW_LINE2);
 #endif /* MESH_BED_CALIBRATION_SHOW_LCD */
         float *pt = pts + k * 2;
         // Go up to z_initial.
@@ -1705,8 +1706,10 @@ BedSkewOffsetDetectionResultType improve_bed_offset_and_skew(int8_t method, int8
     bool endstop_z_enabled = enable_z_endstop(false);
 
 #ifdef MESH_BED_CALIBRATION_SHOW_LCD
-    lcd_implementation_clear();
-    lcd_print_at_PGM(0, 0, MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1);
+    uint8_t next_line;
+    lcd_display_message_fullscreen_P(MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1, next_line);
+    if (next_line > 3)
+        next_line = 3;
 #endif /* MESH_BED_CALIBRATION_SHOW_LCD */
 
     // Collect a matrix of 9x9 points.
@@ -1716,9 +1719,8 @@ BedSkewOffsetDetectionResultType improve_bed_offset_and_skew(int8_t method, int8
         refresh_cmd_timeout();
         // Print the decrasing ID of the measurement point.
 #ifdef MESH_BED_CALIBRATION_SHOW_LCD
-        lcd_print_at_PGM(0, 1, MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2);
-        lcd_implementation_print_at(0, 2, mesh_point+1);
-        lcd_printPGM(MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE3);
+        lcd_implementation_print_at(0, next_line, mesh_point+1);
+        lcd_printPGM(MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2);
 #endif /* MESH_BED_CALIBRATION_SHOW_LCD */
 
         // Move up.
@@ -1963,6 +1965,16 @@ bool sample_mesh_and_store_reference()
     // Don't let the manage_inactivity() function remove power from the motors.
     refresh_cmd_timeout();
 
+#ifdef MESH_BED_CALIBRATION_SHOW_LCD
+    uint8_t next_line;
+    lcd_display_message_fullscreen_P(MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE1, next_line);
+    if (next_line > 3)
+        next_line = 3;
+    // display "point xx of yy"
+    lcd_implementation_print_at(0, next_line, 1);
+    lcd_printPGM(MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2);
+#endif /* MESH_BED_CALIBRATION_SHOW_LCD */
+
     // Sample Z heights for the mesh bed leveling.
     // In addition, store the results into an eeprom, to be used later for verification of the bed leveling process.
     {
@@ -1981,12 +1993,20 @@ bool sample_mesh_and_store_reference()
         mbl.set_z(0, 0, current_position[Z_AXIS]);
     }
     for (int8_t mesh_point = 1; mesh_point != MESH_MEAS_NUM_X_POINTS * MESH_MEAS_NUM_Y_POINTS; ++ mesh_point) {
+        // Don't let the manage_inactivity() function remove power from the motors.
+        refresh_cmd_timeout();
+        // Print the decrasing ID of the measurement point.
         current_position[Z_AXIS] = MESH_HOME_Z_SEARCH;
         go_to_current(homing_feedrate[Z_AXIS]/60);
         current_position[X_AXIS] = pgm_read_float(bed_ref_points+2*mesh_point);
         current_position[Y_AXIS] = pgm_read_float(bed_ref_points+2*mesh_point+1);
         world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]);
         go_to_current(homing_feedrate[X_AXIS]/60);
+#ifdef MESH_BED_CALIBRATION_SHOW_LCD
+        // display "point xx of yy"
+        lcd_implementation_print_at(0, next_line, mesh_point+1);
+        lcd_printPGM(MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2);
+#endif /* MESH_BED_CALIBRATION_SHOW_LCD */
         find_bed_induction_sensor_point_z();
         // Get cords of measuring point
         int8_t ix = mesh_point % MESH_MEAS_NUM_X_POINTS;
@@ -2023,6 +2043,7 @@ bool sample_mesh_and_store_reference()
                 float dif = mbl.z_values[j][i] - mbl.z_values[0][0];
                 int16_t dif_quantized = int16_t(floor(dif * 100.f + 0.5f));
                 eeprom_update_word((uint16_t*)addr, *reinterpret_cast<uint16_t*>(&dif_quantized));
+                #if 0
                 {
                     uint16_t z_offset_u = eeprom_read_word((uint16_t*)addr);
                     float dif2 = *reinterpret_cast<int16_t*>(&z_offset_u) * 0.01;
@@ -2037,6 +2058,7 @@ bool sample_mesh_and_store_reference()
                     MYSERIAL.print(dif2, 5);
                     SERIAL_ECHOLNPGM("");
                 }
+                #endif
                 addr += 2;
             }
     }

+ 164 - 109
Firmware/planner.cpp

@@ -110,6 +110,11 @@ block_t block_buffer[BLOCK_BUFFER_SIZE];            // A ring buffer for motion
 volatile unsigned char block_buffer_head;           // Index of the next block to be pushed
 volatile unsigned char block_buffer_tail;           // Index of the block to process now
 
+#ifdef PLANNER_DIAGNOSTICS
+// Diagnostic function: Minimum number of planned moves since the last 
+static uint8_t g_cntr_planner_queue_min = 0;
+#endif /* PLANNER_DIAGNOSTICS */
+
 //===========================================================================
 //=============================private variables ============================
 //===========================================================================
@@ -171,59 +176,92 @@ FORCE_INLINE float intersection_distance(float initial_rate, float final_rate, f
   }
 }
 
-// Calculates trapezoid parameters so that the entry- and exit-speed is compensated by the provided factors.
+#define MINIMAL_STEP_RATE 120
 
-void calculate_trapezoid_for_block(block_t *block, float entry_factor, float exit_factor) {
-  unsigned long initial_rate = ceil(block->nominal_rate*entry_factor); // (step/min)
-  unsigned long final_rate = ceil(block->nominal_rate*exit_factor); // (step/min)
+// Calculates trapezoid parameters so that the entry- and exit-speed is compensated by the provided factors.
+void calculate_trapezoid_for_block(block_t *block, float entry_speed, float exit_speed) 
+{
+  // These two lines are the only floating point calculations performed in this routine.
+  uint32_t initial_rate = ceil(entry_speed * block->speed_factor); // (step/min)
+  uint32_t final_rate   = ceil(exit_speed  * block->speed_factor); // (step/min)
 
   // Limit minimal step rate (Otherwise the timer will overflow.)
-  if(initial_rate <120) {
-    initial_rate=120; 
-  }
-  if(final_rate < 120) {
-    final_rate=120;  
-  }
-
-  long acceleration = block->acceleration_st;
-  int32_t accelerate_steps =
-    ceil(estimate_acceleration_distance(initial_rate, block->nominal_rate, acceleration));
-  int32_t decelerate_steps =
-    floor(estimate_acceleration_distance(block->nominal_rate, final_rate, -acceleration));
-
-  // Calculate the size of Plateau of Nominal Rate.
-  int32_t plateau_steps = block->step_event_count-accelerate_steps-decelerate_steps;
+  if (initial_rate < MINIMAL_STEP_RATE)
+      initial_rate = MINIMAL_STEP_RATE;
+  if (initial_rate > block->nominal_rate)
+      initial_rate = block->nominal_rate;
+  if (final_rate < MINIMAL_STEP_RATE)
+      final_rate = MINIMAL_STEP_RATE;
+  if (final_rate > block->nominal_rate)
+      final_rate = block->nominal_rate;
+
+  uint32_t acceleration      = block->acceleration_st;
+  if (acceleration == 0)
+      // Don't allow zero acceleration.
+      acceleration = 1;
+  // estimate_acceleration_distance(float initial_rate, float target_rate, float acceleration)
+  // (target_rate*target_rate-initial_rate*initial_rate)/(2.0*acceleration));
+  uint32_t initial_rate_sqr  = initial_rate*initial_rate;
+  //FIXME assert that this result fits a 64bit unsigned int.
+  uint32_t nominal_rate_sqr  = block->nominal_rate*block->nominal_rate;
+  uint32_t final_rate_sqr    = final_rate*final_rate;
+  uint32_t acceleration_x2   = acceleration << 1;
+  // ceil(estimate_acceleration_distance(initial_rate, block->nominal_rate, acceleration));
+  uint32_t accelerate_steps  = (nominal_rate_sqr - initial_rate_sqr + acceleration_x2 - 1) / acceleration_x2;
+  // floor(estimate_acceleration_distance(block->nominal_rate, final_rate, -acceleration));
+  uint32_t decelerate_steps  = (nominal_rate_sqr - final_rate_sqr) / acceleration_x2;
+  uint32_t accel_decel_steps = accelerate_steps + decelerate_steps;
+  // Size of Plateau of Nominal Rate.
+  uint32_t plateau_steps     = 0;
 
   // Is the Plateau of Nominal Rate smaller than nothing? That means no cruising, and we will
   // have to use intersection_distance() to calculate when to abort acceleration and start braking
   // in order to reach the final_rate exactly at the end of this block.
-  if (plateau_steps < 0) {
-    accelerate_steps = ceil(intersection_distance(initial_rate, final_rate, acceleration, block->step_event_count));
-    accelerate_steps = max(accelerate_steps,0); // Check limits due to numerical round-off
-    accelerate_steps = min((uint32_t)accelerate_steps,block->step_event_count);//(We can cast here to unsigned, because the above line ensures that we are above zero)
-    plateau_steps = 0;
+  if (accel_decel_steps < block->step_event_count) {
+    plateau_steps = block->step_event_count - accel_decel_steps;
+  } else {
+    uint32_t acceleration_x4  = acceleration << 2;
+    // Avoid negative numbers
+    if (final_rate_sqr >= initial_rate_sqr) {
+        // accelerate_steps = ceil(intersection_distance(initial_rate, final_rate, acceleration, block->step_event_count));
+        // intersection_distance(float initial_rate, float final_rate, float acceleration, float distance) 
+        // (2.0*acceleration*distance-initial_rate*initial_rate+final_rate*final_rate)/(4.0*acceleration);
+#if 0
+        accelerate_steps = (block->step_event_count >> 1) + (final_rate_sqr - initial_rate_sqr + acceleration_x4 - 1 + (block->step_event_count & 1) * acceleration_x2) / acceleration_x4;
+#else
+        accelerate_steps = final_rate_sqr - initial_rate_sqr + acceleration_x4 - 1;
+        if (block->step_event_count & 1)
+            accelerate_steps += acceleration_x2;
+        accelerate_steps /= acceleration_x4;
+        accelerate_steps += (block->step_event_count >> 1);
+#endif
+        if (accelerate_steps > block->step_event_count)
+            accelerate_steps = block->step_event_count;
+    } else {
+#if 0
+        decelerate_steps = (block->step_event_count >> 1) + (initial_rate_sqr - final_rate_sqr + (block->step_event_count & 1) * acceleration_x2) / acceleration_x4;
+#else
+        decelerate_steps = initial_rate_sqr - final_rate_sqr;
+        if (block->step_event_count & 1)
+            decelerate_steps += acceleration_x2;
+        decelerate_steps /= acceleration_x4;
+        decelerate_steps += (block->step_event_count >> 1);
+#endif
+        if (decelerate_steps > block->step_event_count)
+            decelerate_steps = block->step_event_count;
+        accelerate_steps = block->step_event_count - decelerate_steps;
+    }
   }
 
-#ifdef ADVANCE
-  volatile long initial_advance = block->advance*entry_factor*entry_factor; 
-  volatile long final_advance = block->advance*exit_factor*exit_factor;
-#endif // ADVANCE
-
-  // block->accelerate_until = accelerate_steps;
-  // block->decelerate_after = accelerate_steps+plateau_steps;
   CRITICAL_SECTION_START;  // Fill variables used by the stepper in a critical section
   if (! block->busy) { // Don't update variables if block is busy.
     block->accelerate_until = accelerate_steps;
     block->decelerate_after = accelerate_steps+plateau_steps;
     block->initial_rate = initial_rate;
     block->final_rate = final_rate;
-#ifdef ADVANCE
-    block->initial_advance = initial_advance;
-    block->final_advance = final_advance;
-#endif //ADVANCE
   }
   CRITICAL_SECTION_END;
-}                    
+}
 
 // Calculates the maximum allowable entry speed, when you must be able to reach target_velocity using the 
 // decceleration within the allotted distance.
@@ -249,6 +287,27 @@ FORCE_INLINE float max_allowable_entry_speed(float decceleration, float target_v
 // the set limit. Finally it will:
 //
 //   3. Recalculate trapezoids for all blocks.
+//
+//FIXME This routine is called 15x every time a new line is added to the planner,
+// therefore it is a bottle neck and it shall be rewritten into a Fixed Point arithmetics,
+// if the CPU is found lacking computational power.
+//
+// Following sources may be used to optimize the 8-bit AVR code:
+// http://www.mikrocontroller.net/articles/AVR_Arithmetik
+// http://darcy.rsgc.on.ca/ACES/ICE4M/FixedPoint/avrfix.pdf
+// 
+// https://github.com/gcc-mirror/gcc/blob/master/libgcc/config/avr/lib1funcs-fixed.S
+// https://gcc.gnu.org/onlinedocs/gcc/Fixed-Point.html
+// https://gcc.gnu.org/onlinedocs/gccint/Fixed-point-fractional-library-routines.html
+// 
+// https://ucexperiment.wordpress.com/2015/04/04/arduino-s15-16-fixed-point-math-routines/
+// https://mekonik.wordpress.com/2009/03/18/arduino-avr-gcc-multiplication/
+// https://github.com/rekka/avrmultiplication
+// 
+// https://people.ece.cornell.edu/land/courses/ece4760/Math/Floating_point/
+// https://courses.cit.cornell.edu/ee476/Math/
+// https://courses.cit.cornell.edu/ee476/Math/GCC644/fixedPt/multASM.S
+//
 void planner_recalculate(const float &safe_final_speed) 
 {
     // Reverse pass
@@ -291,8 +350,12 @@ void planner_recalculate(const float &safe_final_speed)
                 // segment and the maximum acceleration allowed for this segment.
                 // If nominal length true, max junction speed is guaranteed to be reached even if decelerating to a jerk-from-zero velocity.
                 // Only compute for max allowable speed if block is decelerating and nominal length is false.
+                // entry_speed is uint16_t, 24 bits would be sufficient for block->acceleration and block->millimiteres, if scaled to um.
+                // therefore an optimized assembly 24bit x 24bit -> 32bit multiply would be more than sufficient
+                // together with an assembly 32bit->16bit sqrt function.
                 current->entry_speed = ((current->flag & BLOCK_FLAG_NOMINAL_LENGTH) || current->max_entry_speed <= next->entry_speed) ?
                     current->max_entry_speed :
+                    // min(current->max_entry_speed, sqrt(next->entry_speed*next->entry_speed+2*current->acceleration*current->millimeters));
                     min(current->max_entry_speed, max_allowable_entry_speed(-current->acceleration,next->entry_speed,current->millimeters));
                 current->flag |= BLOCK_FLAG_RECALCULATE;
             }
@@ -325,7 +388,7 @@ void planner_recalculate(const float &safe_final_speed)
             // Recalculate if current block entry or exit junction speed has changed.
             if ((prev->flag | current->flag) & BLOCK_FLAG_RECALCULATE) {
                 // NOTE: Entry and exit factors always > 0 by all previous logic operations.
-                calculate_trapezoid_for_block(prev, prev->entry_speed/prev->nominal_speed, current->entry_speed/prev->nominal_speed);
+                calculate_trapezoid_for_block(prev, prev->entry_speed, current->entry_speed);
                 // Reset current only to ensure next trapezoid is computed.
                 prev->flag &= ~BLOCK_FLAG_RECALCULATE;
             }
@@ -338,7 +401,7 @@ void planner_recalculate(const float &safe_final_speed)
 
     // Last/newest block in buffer. Exit speed is set with safe_final_speed. Always recalculated.
     current = block_buffer + prev_block_index(block_buffer_head);
-    calculate_trapezoid_for_block(current, current->entry_speed/current->nominal_speed, safe_final_speed/current->nominal_speed);
+    calculate_trapezoid_for_block(current, current->entry_speed, safe_final_speed);
     current->flag &= ~BLOCK_FLAG_RECALCULATE;
 
 //    SERIAL_ECHOLNPGM("planner_recalculate - 4");
@@ -471,6 +534,15 @@ void planner_abort_soft()
 }
 */
 
+#ifdef PLANNER_DIAGNOSTICS
+static inline void planner_update_queue_min_counter()
+{
+  uint8_t new_counter = moves_planned();
+  if (new_counter < g_cntr_planner_queue_min)
+    g_cntr_planner_queue_min = new_counter;
+}
+#endif /* PLANNER_DIAGNOSTICS */
+
 void planner_abort_hard()
 {
     // Abort the stepper routine and flush the planner queue.
@@ -527,11 +599,18 @@ void plan_buffer_line(float x, float y, float z, const float &e, float feed_rate
           manage_inactivity(false); 
           lcd_update();
       } while (block_buffer_tail == next_buffer_head);
-      if (waiting_inside_plan_buffer_line_print_aborted)
+      if (waiting_inside_plan_buffer_line_print_aborted) {
           // Inside the lcd_update() routine the print has been aborted.
           // Cancel the print, do not plan the current line this routine is waiting on.
+#ifdef PLANNER_DIAGNOSTICS
+          planner_update_queue_min_counter();
+#endif /* PLANNER_DIAGNOSTICS */
           return;
+      }
   }
+#ifdef PLANNER_DIAGNOSTICS
+  planner_update_queue_min_counter();
+#endif /* PLANNER_DIAGNOSTICS */
 
 #ifdef ENABLE_AUTO_BED_LEVELING
   apply_rotation_xyz(plan_bed_level_matrix, x, y, z);
@@ -637,14 +716,20 @@ block->steps_y = labs((target[X_AXIS]-position[X_AXIS]) - (target[Y_AXIS]-positi
 #endif
   block->steps_z = labs(target[Z_AXIS]-position[Z_AXIS]);
   block->steps_e = labs(target[E_AXIS]-position[E_AXIS]);
-  block->steps_e *= volumetric_multiplier[active_extruder];
-  block->steps_e *= extrudemultiply;
-  block->steps_e /= 100;
+  if (volumetric_multiplier[active_extruder] != 1.f)
+    block->steps_e *= volumetric_multiplier[active_extruder];
+  if (extrudemultiply != 100) {
+    block->steps_e *= extrudemultiply;
+    block->steps_e /= 100;
+  }
   block->step_event_count = max(block->steps_x, max(block->steps_y, max(block->steps_z, block->steps_e)));
 
   // Bail if this is a zero-length block
   if (block->step_event_count <= dropsegments)
   { 
+#ifdef PLANNER_DIAGNOSTICS
+    planner_update_queue_min_counter();
+#endif /* PLANNER_DIAGNOSTICS */
     return; 
   }
 
@@ -869,6 +954,8 @@ Having the real displacement of the head, we can calculate the total movement le
   }
 
   // Compute and limit the acceleration rate for the trapezoid generator.  
+  // block->step_event_count ... event count of the fastest axis
+  // block->millimeters ... Euclidian length of the XYZ movement or the E length, if no XYZ movement.
   float steps_per_mm = block->step_event_count/block->millimeters;
   if(block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0)
   {
@@ -888,49 +975,27 @@ Having the real displacement of the head, we can calculate the total movement le
     if(((float)block->acceleration_st * (float)block->steps_z / (float)block->step_event_count ) > axis_steps_per_sqr_second[Z_AXIS])
       block->acceleration_st = axis_steps_per_sqr_second[Z_AXIS];
   }
+  // Acceleration of the segment, in mm/sec^2
   block->acceleration = block->acceleration_st / steps_per_mm;
-  block->acceleration_rate = (long)((float)block->acceleration_st * (16777216.0 / (F_CPU / 8.0)));
 
-#if 0  // Use old jerk for now
-  // Compute path unit vector
-  double unit_vec[3];
-
-  unit_vec[X_AXIS] = delta_mm[X_AXIS]*inverse_millimeters;
-  unit_vec[Y_AXIS] = delta_mm[Y_AXIS]*inverse_millimeters;
-  unit_vec[Z_AXIS] = delta_mm[Z_AXIS]*inverse_millimeters;
-
-  // Compute maximum allowable entry speed at junction by centripetal acceleration approximation.
-  // Let a circle be tangent to both previous and current path line segments, where the junction
-  // deviation is defined as the distance from the junction to the closest edge of the circle,
-  // colinear with the circle center. The circular segment joining the two paths represents the
-  // path of centripetal acceleration. Solve for max velocity based on max acceleration about the
-  // radius of the circle, defined indirectly by junction deviation. This may be also viewed as
-  // path width or max_jerk in the previous grbl version. This approach does not actually deviate
-  // from path, but used as a robust way to compute cornering speeds, as it takes into account the
-  // nonlinearities of both the junction angle and junction velocity.
-  double vmax_junction = MINIMUM_PLANNER_SPEED; // Set default max junction speed
-
-  // Skip first block or when previous_nominal_speed is used as a flag for homing and offset cycles.
-  if ((block_buffer_head != block_buffer_tail) && (previous_nominal_speed > 0.0)) {
-    // Compute cosine of angle between previous and current path. (prev_unit_vec is negative)
-    // NOTE: Max junction velocity is computed without sin() or acos() by trig half angle identity.
-    double cos_theta = - previous_unit_vec[X_AXIS] * unit_vec[X_AXIS]
-      - previous_unit_vec[Y_AXIS] * unit_vec[Y_AXIS]
-      - previous_unit_vec[Z_AXIS] * unit_vec[Z_AXIS] ;
-
-    // Skip and use default max junction speed for 0 degree acute junction.
-    if (cos_theta < 0.95) {
-      vmax_junction = min(previous_nominal_speed,block->nominal_speed);
-      // Skip and avoid divide by zero for straight junctions at 180 degrees. Limit to min() of nominal speeds.
-      if (cos_theta > -0.95) {
-        // Compute maximum junction velocity based on maximum acceleration and junction deviation
-        double sin_theta_d2 = sqrt(0.5*(1.0-cos_theta)); // Trig half angle identity. Always positive.
-        vmax_junction = min(vmax_junction,
-        sqrt(block->acceleration * junction_deviation * sin_theta_d2/(1.0-sin_theta_d2)) );
-      }
-    }
+#if 1
+  // Oversample diagonal movements by a power of 2 up to 8x
+  // to achieve more accurate diagonal movements.
+  uint8_t bresenham_oversample = 1;
+  for (uint8_t i = 0; i < 3; ++ i) {
+    if (block->nominal_rate >= 5000) // 5kHz
+      break;
+    block->nominal_rate << 1;
+    bresenham_oversample << 1;
+    block->step_event_count << 1;
   }
+  if (bresenham_oversample > 1)
+    // Lower the acceleration steps/sec^2 to account for the oversampling.
+    block->acceleration_st = (block->acceleration_st + (bresenham_oversample >> 1)) / bresenham_oversample;
 #endif
+
+  block->acceleration_rate = (long)((float)block->acceleration_st * (16777216.0 / (F_CPU / 8.0)));
+
   // Start with a safe speed.
   // Safe speed is the speed, from which the machine may halt to stop immediately.
   float safe_speed = block->nominal_speed;
@@ -1047,34 +1112,9 @@ Having the real displacement of the head, we can calculate the total movement le
   previous_nominal_speed = block->nominal_speed;
   previous_safe_speed = safe_speed;
 
-#ifdef ADVANCE
-  // Calculate advance rate
-  if((block->steps_e == 0) || (block->steps_x == 0 && block->steps_y == 0 && block->steps_z == 0)) {
-    block->advance_rate = 0;
-    block->advance = 0;
-  }
-  else {
-    long acc_dist = estimate_acceleration_distance(0, block->nominal_rate, block->acceleration_st);
-    float advance = (STEPS_PER_CUBIC_MM_E * EXTRUDER_ADVANCE_K) * 
-      (current_speed[E_AXIS] * current_speed[E_AXIS] * EXTRUSION_AREA * EXTRUSION_AREA)*256;
-    block->advance = advance;
-    if(acc_dist == 0) {
-      block->advance_rate = 0;
-    } 
-    else {
-      block->advance_rate = advance / (float)acc_dist;
-    }
-  }
-  /*
-    SERIAL_ECHO_START;
-   SERIAL_ECHOPGM("advance :");
-   SERIAL_ECHO(block->advance/256.0);
-   SERIAL_ECHOPGM("advance rate :");
-   SERIAL_ECHOLN(block->advance_rate/256.0);
-   */
-#endif // ADVANCE
-
-  calculate_trapezoid_for_block(block, block->entry_speed/block->nominal_speed, safe_speed/block->nominal_speed);
+  // Precalculate the division, so when all the trapezoids in the planner queue get recalculated, the division is not repeated.
+  block->speed_factor = block->nominal_rate / block->nominal_speed;
+  calculate_trapezoid_for_block(block, block->entry_speed, safe_speed);
 
   // Move the buffer head. From now the block may be picked up by the stepper interrupt controller.
   block_buffer_head = next_buffer_head;
@@ -1092,6 +1132,9 @@ Having the real displacement of the head, we can calculate the total movement le
 //  SERIAL_ECHO(int(moves_planned()));
 //  SERIAL_ECHOLNPGM("");
 
+#ifdef PLANNER_DIAGNOSTICS
+  planner_update_queue_min_counter();
+#endif /* PLANNER_DIAGNOSTIC */
   st_wake_up();
 }
 
@@ -1172,3 +1215,15 @@ void reset_acceleration_rates()
         axis_steps_per_sqr_second[i] = max_acceleration_units_per_sq_second[i] * axis_steps_per_unit[i];
         }
 }
+
+#ifdef PLANNER_DIAGNOSTICS
+uint8_t planner_queue_min()
+{
+  return g_cntr_planner_queue_min;
+}
+
+void planner_queue_min_reset()
+{
+  g_cntr_planner_queue_min = moves_planned();
+}
+#endif /* PLANNER_DIAGNOSTICS */

+ 14 - 6
Firmware/planner.h

@@ -55,12 +55,6 @@ typedef struct {
   // accelerate_until and decelerate_after are set by calculate_trapezoid_for_block() and they need to be synchronized with the stepper interrupt controller.
   long accelerate_until;                    // The index of the step event on which to stop acceleration
   long decelerate_after;                    // The index of the step event on which to start decelerating
-  #ifdef ADVANCE
-    long advance_rate;
-    volatile long initial_advance;
-    volatile long final_advance;
-    float advance;
-  #endif
 
   // Fields used by the motion planner to manage acceleration
 //  float speed_x, speed_y, speed_z, speed_e;        // Nominal mm/sec for each axis
@@ -82,12 +76,18 @@ typedef struct {
 
   // Settings for the trapezoid generator (runs inside an interrupt handler).
   // Changing the following values in the planner needs to be synchronized with the interrupt handler by disabling the interrupts.
+  //FIXME nominal_rate, initial_rate and final_rate are limited to uint16_t by MultiU24X24toH16 in the stepper interrupt anyway!
   unsigned long nominal_rate;                        // The nominal step rate for this block in step_events/sec 
   unsigned long initial_rate;                        // The jerk-adjusted step rate at start of block  
   unsigned long final_rate;                          // The minimal rate at exit
   unsigned long acceleration_st;                     // acceleration steps/sec^2
+  //FIXME does it have to be unsigned long? Probably uint8_t would be just fine.
   unsigned long fan_speed;
   volatile char busy;
+
+
+  // Pre-calculated division for the calculate_trapezoid_for_block() routine to run faster.
+  float speed_factor;
 } block_t;
 
 #ifdef ENABLE_AUTO_BED_LEVELING
@@ -196,3 +196,11 @@ void set_extrude_min_temp(float temp);
 
 void reset_acceleration_rates();
 #endif
+
+// #define PLANNER_DIAGNOSTICS
+#ifdef PLANNER_DIAGNOSTICS
+// Diagnostic functions to display planner buffer underflow on the display.
+extern uint8_t planner_queue_min();
+// Diagnostic function: Reset the minimum planner segments.
+extern void planner_queue_min_reset();
+#endif /* PLANNER_DIAGNOSTICS */

+ 20 - 142
Firmware/stepper.cpp

@@ -47,22 +47,17 @@ block_t *current_block;  // A pointer to the block currently being traced
 
 // Variables used by The Stepper Driver Interrupt
 static unsigned char out_bits;        // The next stepping-bits to be output
-static long counter_x,       // Counter variables for the bresenham line tracer
-            counter_y,
-            counter_z,
-            counter_e;
-volatile static unsigned long step_events_completed; // The number of step events executed in the current block
-#ifdef ADVANCE
-  static long advance_rate, advance, final_advance = 0;
-  static long old_advance = 0;
-  static long e_steps[3];
-#endif
-static long acceleration_time, deceleration_time;
+static int32_t counter_x,       // Counter variables for the bresenham line tracer
+               counter_y,
+               counter_z,
+               counter_e;
+volatile static uint32_t step_events_completed; // The number of step events executed in the current block
+static int32_t  acceleration_time, deceleration_time;
 //static unsigned long accelerate_until, decelerate_after, acceleration_rate, initial_rate, final_rate, nominal_rate;
-static unsigned short acc_step_rate; // needed for deccelaration start point
-static char step_loops;
-static unsigned short OCR1A_nominal;
-static unsigned short step_loops_nominal;
+static uint16_t acc_step_rate; // needed for deccelaration start point
+static uint8_t  step_loops;
+static uint16_t OCR1A_nominal;
+static uint8_t  step_loops_nominal;
 
 volatile long endstops_trigsteps[3]={0,0,0};
 volatile long endstops_stepsTotal,endstops_stepsDone;
@@ -306,13 +301,6 @@ FORCE_INLINE unsigned short calc_timer(unsigned short step_rate) {
 // Initializes the trapezoid generator from the current block. Called whenever a new
 // block begins.
 FORCE_INLINE void trapezoid_generator_reset() {
-  #ifdef ADVANCE
-    advance = current_block->initial_advance;
-    final_advance = current_block->final_advance;
-    // Do E steps + advance steps
-    e_steps[current_block->active_extruder] += ((advance >>8) - old_advance);
-    old_advance = advance >>8;
-  #endif
   deceleration_time = 0;
   // step_rate to timer interval
   OCR1A_nominal = calc_timer(current_block->nominal_rate);
@@ -359,10 +347,6 @@ ISR(TIMER1_COMPA_vect)
           return;
         }
       #endif
-
-//      #ifdef ADVANCE
-//      e_steps[current_block->active_extruder] = 0;
-//      #endif
     }
     else {
         OCR1A=2000; // 1kHz.
@@ -531,37 +515,20 @@ ISR(TIMER1_COMPA_vect)
     }
     #endif
 
-    #ifndef ADVANCE
-      if ((out_bits & (1<<E_AXIS)) != 0) {  // -direction
-        REV_E_DIR();
-        count_direction[E_AXIS]=-1;
-      }
-      else { // +direction
-        NORM_E_DIR();
-        count_direction[E_AXIS]=1;
-      }
-    #endif //!ADVANCE
-
-
+    if ((out_bits & (1<<E_AXIS)) != 0) {  // -direction
+      REV_E_DIR();
+      count_direction[E_AXIS]=-1;
+    }
+    else { // +direction
+      NORM_E_DIR();
+      count_direction[E_AXIS]=1;
+    }
 
-    for(int8_t i=0; i < step_loops; i++) { // Take multiple steps per interrupt (For high speed moves)
+    for(uint8_t i=0; i < step_loops; i++) { // Take multiple steps per interrupt (For high speed moves)
       #ifndef AT90USB
       MSerial.checkRx(); // Check for serial chars.
       #endif
 
-      #ifdef ADVANCE
-      counter_e += current_block->steps_e;
-      if (counter_e > 0) {
-        counter_e -= current_block->step_event_count;
-        if ((out_bits & (1<<E_AXIS)) != 0) { // - direction
-          e_steps[current_block->active_extruder]--;
-        }
-        else {
-          e_steps[current_block->active_extruder]++;
-        }
-      }
-      #endif //ADVANCE
-
         counter_x += current_block->steps_x;
         if (counter_x > 0) {
           WRITE(X_STEP_PIN, !INVERT_X_STEP_PIN);
@@ -604,7 +571,6 @@ ISR(TIMER1_COMPA_vect)
         #endif
       }
 
-      #ifndef ADVANCE
         counter_e += current_block->steps_e;
         if (counter_e > 0) {
           WRITE_E_STEP(!INVERT_E_STEP_PIN);
@@ -612,7 +578,6 @@ ISR(TIMER1_COMPA_vect)
           count_position[E_AXIS]+=count_direction[E_AXIS];
           WRITE_E_STEP(INVERT_E_STEP_PIN);
         }
-      #endif //!ADVANCE
       step_events_completed += 1;
       if(step_events_completed >= current_block->step_event_count) break;
     }
@@ -620,7 +585,7 @@ ISR(TIMER1_COMPA_vect)
     unsigned short timer;
     unsigned short step_rate;
     if (step_events_completed <= (unsigned long int)current_block->accelerate_until) {
-
+      // v = t * a   ->   acc_step_rate = acceleration_time * current_block->acceleration_rate
       MultiU24X24toH16(acc_step_rate, acceleration_time, current_block->acceleration_rate);
       acc_step_rate += current_block->initial_rate;
 
@@ -632,16 +597,6 @@ ISR(TIMER1_COMPA_vect)
       timer = calc_timer(acc_step_rate);
       OCR1A = timer;
       acceleration_time += timer;
-      #ifdef ADVANCE
-        for(int8_t i=0; i < step_loops; i++) {
-          advance += advance_rate;
-        }
-        //if(advance > current_block->advance) advance = current_block->advance;
-        // Do E steps + advance steps
-        e_steps[current_block->active_extruder] += ((advance >>8) - old_advance);
-        old_advance = advance >>8;
-
-      #endif // ADVANCE
     }
     else if (step_events_completed > (unsigned long int)current_block->decelerate_after) {
       MultiU24X24toH16(step_rate, deceleration_time, current_block->acceleration_rate);
@@ -661,15 +616,6 @@ ISR(TIMER1_COMPA_vect)
       timer = calc_timer(step_rate);
       OCR1A = timer;
       deceleration_time += timer;
-      #ifdef ADVANCE
-        for(int8_t i=0; i < step_loops; i++) {
-          advance -= advance_rate;
-        }
-        if(advance < final_advance) advance = final_advance;
-        // Do E steps + advance steps
-        e_steps[current_block->active_extruder] += ((advance >>8) - old_advance);
-        old_advance = advance >>8;
-      #endif //ADVANCE
     }
     else {
       OCR1A = OCR1A_nominal;
@@ -685,63 +631,6 @@ ISR(TIMER1_COMPA_vect)
   }
 }
 
-#ifdef ADVANCE
-  unsigned char old_OCR0A;
-  // Timer interrupt for E. e_steps is set in the main routine;
-  // Timer 0 is shared with millies
-  ISR(TIMER0_COMPA_vect)
-  {
-    old_OCR0A += 52; // ~10kHz interrupt (250000 / 26 = 9615kHz)
-    OCR0A = old_OCR0A;
-    // Set E direction (Depends on E direction + advance)
-    for(unsigned char i=0; i<4;i++) {
-      if (e_steps[0] != 0) {
-        WRITE(E0_STEP_PIN, INVERT_E_STEP_PIN);
-        if (e_steps[0] < 0) {
-          WRITE(E0_DIR_PIN, INVERT_E0_DIR);
-          e_steps[0]++;
-          WRITE(E0_STEP_PIN, !INVERT_E_STEP_PIN);
-        }
-        else if (e_steps[0] > 0) {
-          WRITE(E0_DIR_PIN, !INVERT_E0_DIR);
-          e_steps[0]--;
-          WRITE(E0_STEP_PIN, !INVERT_E_STEP_PIN);
-        }
-      }
- #if EXTRUDERS > 1
-      if (e_steps[1] != 0) {
-        WRITE(E1_STEP_PIN, INVERT_E_STEP_PIN);
-        if (e_steps[1] < 0) {
-          WRITE(E1_DIR_PIN, INVERT_E1_DIR);
-          e_steps[1]++;
-          WRITE(E1_STEP_PIN, !INVERT_E_STEP_PIN);
-        }
-        else if (e_steps[1] > 0) {
-          WRITE(E1_DIR_PIN, !INVERT_E1_DIR);
-          e_steps[1]--;
-          WRITE(E1_STEP_PIN, !INVERT_E_STEP_PIN);
-        }
-      }
- #endif
- #if EXTRUDERS > 2
-      if (e_steps[2] != 0) {
-        WRITE(E2_STEP_PIN, INVERT_E_STEP_PIN);
-        if (e_steps[2] < 0) {
-          WRITE(E2_DIR_PIN, INVERT_E2_DIR);
-          e_steps[2]++;
-          WRITE(E2_STEP_PIN, !INVERT_E_STEP_PIN);
-        }
-        else if (e_steps[2] > 0) {
-          WRITE(E2_DIR_PIN, !INVERT_E2_DIR);
-          e_steps[2]--;
-          WRITE(E2_STEP_PIN, !INVERT_E_STEP_PIN);
-        }
-      }
- #endif
-    }
-  }
-#endif // ADVANCE
-
 void st_init()
 {
   digipot_init(); //Initialize Digipot Motor Current
@@ -930,17 +819,6 @@ void st_init()
   TCNT1 = 0;
   ENABLE_STEPPER_DRIVER_INTERRUPT();
 
-  #ifdef ADVANCE
-  #if defined(TCCR0A) && defined(WGM01)
-    TCCR0A &= ~(1<<WGM01);
-    TCCR0A &= ~(1<<WGM00);
-  #endif
-    e_steps[0] = 0;
-    e_steps[1] = 0;
-    e_steps[2] = 0;
-    TIMSK0 |= (1<<OCIE0A);
-  #endif //ADVANCE
-
   enable_endstops(true); // Start with endstops active. After homing they can be disabled
   sei();
 }

+ 1 - 0
Firmware/temperature.cpp

@@ -1211,6 +1211,7 @@ void max_temp_error(uint8_t e) {
     WRITE(FAN_PIN, 1);
     WRITE(EXTRUDER_0_AUTO_FAN_PIN, 1);
     WRITE(BEEPER, 1);
+    // fanSpeed will consumed by the check_axes_activity() routine.
     fanSpeed=255;
 }
 

+ 72 - 24
Firmware/ultralcd.cpp

@@ -327,7 +327,6 @@ void set_language_from_EEPROM() {
   }
 }
 
-void lcd_mylang();
 static void lcd_status_screen()
 {
 	
@@ -1441,17 +1440,16 @@ bool lcd_calibrate_z_end_stop_manual(bool only_z)
     // Until confirmed by the confirmation dialog.
     for (;;) {
         unsigned long previous_millis_cmd = millis();
-        if (only_z) {
-            lcd_display_message_fullscreen_P(MSG_MOVE_CARRIAGE_TO_THE_TOP_Z);
-        }else{
-            lcd_display_message_fullscreen_P(MSG_MOVE_CARRIAGE_TO_THE_TOP);
-        }
+        const char   *msg                 = only_z ? MSG_MOVE_CARRIAGE_TO_THE_TOP_Z : MSG_MOVE_CARRIAGE_TO_THE_TOP;
+        const char   *msg_next            = lcd_display_message_fullscreen_P(msg);
+        const bool    multi_screen        = msg_next != NULL;
+        unsigned long previous_millis_msg = millis();
         // Until the user finishes the z up movement.
         encoderDiff = 0;
         encoderPosition = 0;
         for (;;) {
-            if (millis() - previous_millis_cmd > LCD_TIMEOUT_TO_STATUS)
-                goto canceled;
+//          if (millis() - previous_millis_cmd > LCD_TIMEOUT_TO_STATUS)
+//             goto canceled;
             manage_heater();
             manage_inactivity(true);
             if (abs(encoderDiff) >= ENCODER_PULSES_PER_STEP) {
@@ -1474,6 +1472,12 @@ bool lcd_calibrate_z_end_stop_manual(bool only_z)
                 while (lcd_clicked()) ;
                 break;
             }
+            if (multi_screen && millis() - previous_millis_msg > 5000) {
+                if (msg_next == NULL)
+                    msg_next = msg;
+                msg_next = lcd_display_message_fullscreen_P(msg_next);
+                previous_millis_msg = millis();
+            }
         }
 
         if (! clean_nozzle_asked) {
@@ -1482,7 +1486,7 @@ bool lcd_calibrate_z_end_stop_manual(bool only_z)
         }
 
         // Let the user confirm, that the Z carriage is at the top end stoppers.
-        int8_t result = lcd_show_fullscreen_message_yes_no_and_wait_P(MSG_CONFIRM_CARRIAGE_AT_THE_TOP);
+        int8_t result = lcd_show_fullscreen_message_yes_no_and_wait_P(MSG_CONFIRM_CARRIAGE_AT_THE_TOP, false);
         if (result == -1)
             goto canceled;
         else if (result == 1)
@@ -1513,24 +1517,36 @@ static inline bool pgm_is_interpunction(const char *c_addr)
     return c == '.' || c == ',' || c == ':'|| c == ';' || c == '?' || c == '!' || c == '/';
 }
 
-const char* lcd_display_message_fullscreen_P(const char *msg)
+const char* lcd_display_message_fullscreen_P(const char *msg, uint8_t &nlines)
 {
     // Disable update of the screen by the usual lcd_update() routine. 
     lcd_update_enable(false);
     lcd_implementation_clear();
     lcd.setCursor(0, 0);
     const char *msgend = msg;
-    for (int8_t row = 0; row < 4; ++ row) {
+    uint8_t row = 0;
+    bool multi_screen = false;
+    for (; row < 4; ++ row) {
         while (pgm_is_whitespace(msg))
             ++ msg;
         if (pgm_read_byte(msg) == 0)
             // End of the message.
             break;
         lcd.setCursor(0, row);
-        const char *msgend2 = msg + min(strlen_P(msg), 20);
+        uint8_t linelen = min(strlen_P(msg), 20);
+        const char *msgend2 = msg + linelen;
         msgend = msgend2;
+        if (row == 3 && linelen == 20) {
+            // Last line of the display, full line shall be displayed.
+            // Find out, whether this message will be split into multiple screens.
+            while (pgm_is_whitespace(msgend))
+                ++ msgend;
+            multi_screen = pgm_read_byte(msgend) != 0;
+            if (multi_screen)
+                msgend = (msgend2 -= 2);
+        }
         if (pgm_read_byte(msgend) != 0 && ! pgm_is_whitespace(msgend) && ! pgm_is_interpunction(msgend)) {
-              // Splitting a word. Find the start of the current word.
+            // Splitting a word. Find the start of the current word.
             while (msgend > msg && ! pgm_is_whitespace(msgend - 1))
                  -- msgend;
             if (msgend == msg)
@@ -1545,7 +1561,17 @@ const char* lcd_display_message_fullscreen_P(const char *msg)
         }
     }
 
-    return (pgm_read_byte(msgend) == 0) ? NULL : msgend;
+    if (multi_screen) {
+        // Display the "next screen" indicator character.
+        // lcd_set_custom_characters_arrows();
+        lcd_set_custom_characters_nextpage();
+        lcd.setCursor(19, 3);
+        // Display the down arrow.
+        lcd.print(char(1));
+    }
+
+    nlines = row;
+    return multi_screen ? msgend : NULL;
 }
 
 void lcd_show_fullscreen_message_and_wait_P(const char *msg)
@@ -2244,9 +2270,6 @@ void lcd_mylang_drawmenu(int cursor) {
   }  
 }
  
-void lcd_set_custom_characters_arrows();
-void lcd_set_custom_characters_degree();
-
 void lcd_mylang_drawcursor(int cursor) {
   
   if (cursor==1) lcd.setCursor(0, 1);
@@ -3290,10 +3313,36 @@ void lcd_init()
 //#include <avr/pgmspace.h>
 
 static volatile bool lcd_update_enabled = true;
+static unsigned long lcd_timeoutToStatus = 0;
 
 void lcd_update_enable(bool enabled)
 {
-    lcd_update_enabled = enabled;
+    if (lcd_update_enabled != enabled) {
+        lcd_update_enabled = enabled;
+        if (enabled) {
+            // Reset encoder position. This is equivalent to re-entering a menu.
+            encoderPosition = 0;
+            encoderDiff = 0;
+            // Enabling the normal LCD update procedure.
+            // Reset the timeout interval.
+            lcd_timeoutToStatus = millis() + LCD_TIMEOUT_TO_STATUS;
+            // Force the keypad update now.
+            lcd_next_update_millis = millis() - 1;
+            // Full update.
+            lcd_implementation_clear();
+      #if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)
+            lcd_set_custom_characters(currentMenu == lcd_status_screen);
+      #else
+            if (currentMenu == lcd_status_screen)
+                lcd_set_custom_characters_degree();
+            else
+                lcd_set_custom_characters_arrows();
+      #endif
+            lcd_update(2);
+        } else {
+            // Clear the LCD always, or let it to the caller?
+        }
+    }
 }
 
 void lcd_update(uint8_t lcdDrawUpdateOverride)
@@ -3301,8 +3350,6 @@ void lcd_update(uint8_t lcdDrawUpdateOverride)
   if (lcdDrawUpdate < lcdDrawUpdateOverride)
     lcdDrawUpdate = lcdDrawUpdateOverride;
 
-	static unsigned long timeoutToStatus = 0;
-
   if (! lcd_update_enabled)
       return;
 
@@ -3364,13 +3411,14 @@ void lcd_update(uint8_t lcdDrawUpdateOverride)
 #endif
 	  if (abs(encoderDiff) >= ENCODER_PULSES_PER_STEP)
 	  {
-		  lcdDrawUpdate = 1;
+      if (lcdDrawUpdate == 0)
+		    lcdDrawUpdate = 1;
 		  encoderPosition += encoderDiff / ENCODER_PULSES_PER_STEP;
 		  encoderDiff = 0;
-		  timeoutToStatus = millis() + LCD_TIMEOUT_TO_STATUS;
+		  lcd_timeoutToStatus = millis() + LCD_TIMEOUT_TO_STATUS;
 	  }
 	  if (LCD_CLICKED)
-		  timeoutToStatus = millis() + LCD_TIMEOUT_TO_STATUS;
+		  lcd_timeoutToStatus = millis() + LCD_TIMEOUT_TO_STATUS;
 #endif//ULTIPANEL
 
 #ifdef DOGLCD        // Changes due to different driver architecture of the DOGM display
@@ -3395,7 +3443,7 @@ void lcd_update(uint8_t lcdDrawUpdateOverride)
 #endif
 
 #ifdef ULTIPANEL
-	  if (timeoutToStatus < millis() && currentMenu != lcd_status_screen)
+	  if (lcd_timeoutToStatus < millis() && currentMenu != lcd_status_screen)
 	  {
       // Exiting a menu. Let's call the menu function the last time with menuExiting flag set to true
       // to give it a chance to save its state.

+ 4 - 1
Firmware/ultralcd.h

@@ -40,7 +40,10 @@ void lcd_mylang();
   static void lcd_selftest_error(int _error_no, const char *_error_1, const char *_error_2);
   static void lcd_menu_statistics();
 
-  extern const char* lcd_display_message_fullscreen_P(const char *msg);
+  extern const char* lcd_display_message_fullscreen_P(const char *msg, uint8_t &nlines);
+  inline const char* lcd_display_message_fullscreen_P(const char *msg) 
+    { uint8_t nlines; return lcd_display_message_fullscreen_P(msg, nlines); }
+
   extern void lcd_wait_for_click();
   extern void lcd_show_fullscreen_message_and_wait_P(const char *msg);
   // 0: no, 1: yes, -1: timeouted

+ 44 - 4
Firmware/ultralcd_implementation_hitachi_HD44780.h

@@ -461,6 +461,24 @@ void lcd_set_custom_characters_arrows()
 
     lcd.createChar(1, arrdown);
 }
+
+void lcd_set_custom_characters_nextpage()
+ {
+
+  byte arrdown[8] = {
+    B00000,
+    B00000,
+    B10001,
+    B01010,
+    B00100,
+    B10001,
+    B01010,
+    B00100
+  }; 
+
+    lcd.createChar(1, arrdown);
+}
+
 void lcd_set_custom_characters_degree()
  {
   byte degree[8] = {
@@ -659,6 +677,7 @@ static void lcd_implementation_status_screen()
 
     //Print the Z coordinates
     lcd.setCursor(LCD_WIDTH - 8-2, 0);
+#if 1
     lcd_printPGM(PSTR("  Z"));
     if (custom_message_type == 1) {
         // In a bed calibration mode.
@@ -667,6 +686,11 @@ static void lcd_implementation_status_screen()
         lcd.print(ftostr32sp(current_position[Z_AXIS] + 0.00001));
         lcd.print(' ');
     }
+#else
+    lcd_printPGM(PSTR(" Queue:"));
+    lcd.print(int(moves_planned()));
+    lcd.print(' ');
+#endif
 
     //Print the Bedtemperature
     lcd.setCursor(0, 1);
@@ -679,15 +703,31 @@ static void lcd_implementation_status_screen()
     lcd_printPGM(PSTR(LCD_STR_DEGREE " "));
     lcd_printPGM(PSTR("  "));
 
+#if 1
     //Print Feedrate
     lcd.setCursor(LCD_WIDTH - 8-2, 1);
     lcd_printPGM(PSTR("  "));
     lcd.print(LCD_STR_FEEDRATE[0]);
     lcd.print(itostr3(feedmultiply));
-    lcd.print('%');
-    lcd_printPGM(PSTR("     "));
-
-
+    lcd_printPGM(PSTR("%     "));
+#else
+    //Print Feedrate
+    lcd.setCursor(LCD_WIDTH - 8-2, 1);
+    lcd.print(LCD_STR_FEEDRATE[0]);
+    lcd.print(itostr3(feedmultiply));
+    lcd_printPGM(PSTR("%  Q"));
+    {
+      uint8_t queue = planner_queue_min();
+      if (queue < (BLOCK_BUFFER_SIZE >> 1)) {
+        lcd.print('!');
+      } else {
+        lcd.print((char)(queue / 10) + '0');
+        queue %= 10;
+      }
+      lcd.print((char)queue + '0');
+      planner_queue_min_reset();
+    }
+#endif
 	
     //Print SD status
     lcd.setCursor(0, 2);