Переглянути джерело

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

Fix merge issues with G90 and G91
3d-gussner 4 роки тому
батько
коміт
f3668cab92

+ 31 - 0
.github/ISSUE_TEMPLATE/bug_report.md

@@ -0,0 +1,31 @@
+---
+name: Bug report
+about: Create a report to help us improve
+title: "[BUG]<Enter comprehensive title>"
+labels: bug
+assignees: ''
+
+---
+
+Please, before you create a new bug report, please make sure you searched in open and closed issues and couldn't find anything that matches.
+
+**Printer type** - [e.g. MK3S, MK3, MK2.5S, MK2.5, MK2S, MK2]
+**Printer firmware version**-  [e.g. 3.8.1, 3.8.1-RC1, ...]
+
+**MMU Upgrade** - [e.g. MMU2S, MMU2, MMU1]
+**MMU upgrade firmware version [e.g. 1.0.6, 1.0.6-RC2, ...]
+
+**Describe the bug**
+  A clear and concise description of what the bug is.
+  
+**To Reproduce**
+  Please describe steps to reproduce the behavior.
+  
+**Expected behavior**
+  A clear and concise description of what you expected to happen.
+  
+**G-code**
+  Please attach a G-code. This will make it easier for us to replicate the error.
+
+**Video**
+  Please attach a video. It usually helps to solve the problem.

+ 20 - 0
.github/ISSUE_TEMPLATE/enhancement.md

@@ -0,0 +1,20 @@
+---
+name: Enhancement
+about: Suggest an idea for this project
+title: "  [ENHANCEMENT]<Enter comprehensive title>"
+labels: enhancement
+assignees: ''
+
+---
+
+Please, before you create a new feature request, please make sure you searched in open and closed issues and couldn't find anything that matches.
+
+Enter what type of printer or upgrade the enhancement applies to.
+**Printer type** - [e.g. MK3S, MK3, MK2.5S, MK2.5, MK2S, MK2]
+**MMU Upgrade** - [e.g. MMU2S, MMU2, MMU1]
+
+**Is your enhancement related to a problem? Please describe.**
+  A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+  
+**Describe the solution you'd like**
+  A clear and concise description of what you want to happen.

+ 20 - 0
.github/ISSUE_TEMPLATE/feature_request.md

@@ -0,0 +1,20 @@
+---
+name: Feature request
+about: Suggest an idea for this project
+title: "[FEATURE REQUEST]<Enter comprehensive title>"
+labels: feature request
+assignees: ''
+
+---
+
+Please, before you create a new feature request, please make sure you searched in open and closed issues and couldn't find anything that matches.
+
+If it makes sense, enter what type of printer or upgrade the feature request applies to.
+**Printer type** - [e.g. MK3S, MK3, MK2.5S, MK2.5, MK2S, MK2]
+**MMU Upgrade** - [e.g. MMU2S, MMU2, MMU1]
+
+**Is your feature request related to a problem? Please describe.**
+  A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+  
+**Describe the solution you'd like**
+  A clear and concise description of what you want to happen.

+ 12 - 0
.github/ISSUE_TEMPLATE/question.md

@@ -0,0 +1,12 @@
+---
+name: Question
+about: What do you want to know?
+title: "[QUESTION]<Enter comprehensive title>"
+labels: question
+assignees: ''
+
+---
+
+Please, before you create a new question, please make sure you searched in open and closed issues and couldn't find anything that matches.
+
+**What is your question?**

+ 1 - 0
Firmware/Marlin.h

@@ -455,6 +455,7 @@ extern void print_mesh_bed_leveling_table();
 
 extern void stop_and_save_print_to_ram(float z_move, float e_move);
 extern void restore_print_from_ram_and_continue(float e_move);
+extern void cancel_saved_printing();
 
 
 //estimated time to end of the print

+ 68 - 32
Firmware/Marlin_main.cpp

@@ -63,6 +63,7 @@
 
 #include "menu.h"
 #include "ultralcd.h"
+#include "backlight.h"
 
 #include "planner.h"
 #include "stepper.h"
@@ -341,10 +342,6 @@ static float next_feedrate;
 // Original feedrate saved during homing moves
 static float saved_feedrate;
 
-// Determines Absolute or Relative Coordinates.
-// Also there is bool axis_relative_modes[] per axis flag.
-static bool relative_mode = false;  
-
 const int sensitive_pins[] = SENSITIVE_PINS; // Sensitive pin list for M42
 
 //static float tt = 0;
@@ -999,10 +996,6 @@ void setup()
 
 	ultralcd_init();
 
-#if (LCD_BL_PIN != -1) && defined (LCD_BL_PIN)
-	analogWrite(LCD_BL_PIN, 255); //set full brightnes
-#endif //(LCD_BL_PIN != -1) && defined (LCD_BL_PIN)
-
 	spi_init();
 
 	lcd_splash();
@@ -2128,9 +2121,15 @@ void raise_z_above(float target, bool plan)
     // Z needs raising
     current_position[Z_AXIS] = target;
 
-    if (axis_known_position[Z_AXIS])
+#if defined(Z_MIN_PIN) && (Z_MIN_PIN > -1) && !defined(DEBUG_DISABLE_ZMINLIMIT)
+    bool z_min_endstop = (READ(Z_MIN_PIN) != Z_MIN_ENDSTOP_INVERTING);
+#else
+    bool z_min_endstop = false;
+#endif
+
+    if (axis_known_position[Z_AXIS] || z_min_endstop)
     {
-        // current position is known, it's safe to raise Z
+        // current position is known or very low, it's safe to raise Z
         if(plan) plan_buffer_line_curposXYZE(max_feedrate[Z_AXIS], active_extruder);
         return;
     }
@@ -2824,7 +2823,10 @@ bool gcode_M45(bool onlyZ, int8_t verbosity_level)
 	#ifdef TMC2130
 	FORCE_HIGH_POWER_START;
 	#endif // TMC2130
-	// Only Z calibration?
+    
+    FORCE_BL_ON_START;
+	
+    // Only Z calibration?
 	if (!onlyZ)
 	{
 		setTargetBed(0);
@@ -3012,6 +3014,9 @@ bool gcode_M45(bool onlyZ, int8_t verbosity_level)
 #ifdef TMC2130
 	FORCE_HIGH_POWER_END;
 #endif // TMC2130
+    
+    FORCE_BL_ON_END;
+    
 	return final_result;
 }
 
@@ -5344,6 +5349,7 @@ if(eSoundMode!=e_SOUND_MODE_SILENT)
 
 #endif  // ENABLE_MESH_BED_LEVELING
             
+
     /*!
 	### G90 - Switch off relative mode <a href="https://reprap.org/wiki/G-code#G90:_Set_to_Absolute_Positioning">G90: Set to Absolute Positioning</a>
 	#### Usage
@@ -5352,20 +5358,25 @@ if(eSoundMode!=e_SOUND_MODE_SILENT)
 	
 	All coordinates from now on are absolute relative to the origin of the machine.
     */
-    case 90:
-      relative_mode = false;
-      break;
+    case 90: {
+        for(uint8_t i = 0; i != NUM_AXIS; ++i)
+            axis_relative_modes[i] = false;
+    }
+    break;
 
-    /*! ### G91 - Switch on relative mode <a href="https://reprap.org/wiki/G-code#G91:_Set_to_Relative_Positioning">G91: Set to Relative Positioning</a>
+    /*!
+	### G91 - Switch on relative mode <a href="https://reprap.org/wiki/G-code#G91:_Set_to_Relative_Positioning">G91: Set to Relative Positioning</a>
 	#### Usage
 	
 	      G91
 	
     All coordinates from now on are relative to the last position. 
 	*/
-    case 91:
-      relative_mode = true;
-      break;
+    case 91: {
+        for(uint8_t i = 0; i != NUM_AXIS; ++i)
+            axis_relative_modes[i] = true;
+    }
+    break;
 
     /*!
 	### G92 - Set position <a href="https://reprap.org/wiki/G-code#G92:_Set_Position">G92: Set Position</a>
@@ -6167,7 +6178,7 @@ Sigma_Exit:
 	### M112 - Emergency stop <a href="https://reprap.org/wiki/G-code#M112:_Full_.28Emergency.29_Stop">M112: Full (Emergency) Stop</a>
     */
     case 112: 
-      kill(_n(""), 3);
+      kill(MSG_M112_KILL, 3);
       break;
 
     /*!
@@ -6455,7 +6466,6 @@ Sigma_Exit:
           LCD_MESSAGERPGM(_T(WELCOME_MSG));
           lcd_update(0);
         break;
-      #endif
 
       /*!
 	  ### M81 - Turn off Power Supply <a href="https://reprap.org/wiki/G-code#M81:_ATX_Power_Off">M81: ATX Power Off</a>
@@ -6480,13 +6490,14 @@ Sigma_Exit:
         LCD_MESSAGERPGM(CAT4(CUSTOM_MENDEL_NAME,PSTR(" "),MSG_OFF,PSTR(".")));
         lcd_update(0);
 	  break;
+    #endif
 
     /*!
 	### M82 - Set E axis to absolute mode <a href="https://reprap.org/wiki/G-code#M82:_Set_extruder_to_absolute_mode">M82: Set extruder to absolute mode</a>
 	Makes the extruder interpret extrusion as absolute positions.
     */
     case 82:
-      axis_relative_modes[3] = false;
+      axis_relative_modes[E_AXIS] = false;
       break;
 
     /*!
@@ -6494,7 +6505,7 @@ Sigma_Exit:
 	Makes the extruder interpret extrusion values as relative positions.
     */
     case 83:
-      axis_relative_modes[3] = true;
+      axis_relative_modes[E_AXIS] = true;
       break;
 
     /*!
@@ -7772,7 +7783,7 @@ Sigma_Exit:
     ### M603 - Stop print <a href="https://reprap.org/wiki/G-code#M603:_Stop_print">M603: Stop print</a>
     */
 	case 603: {
-		Stop();
+		lcd_print_stop();
 	}
 	break;
 
@@ -9029,7 +9040,7 @@ void get_coordinates()
   for(int8_t i=0; i < NUM_AXIS; i++) {
     if(code_seen(axis_codes[i]))
     {
-      bool relative = axis_relative_modes[i] || relative_mode;
+      bool relative = axis_relative_modes[i];
       destination[i] = (float)code_value();
       if (i == E_AXIS) {
         float emult = extruder_multiplier[active_extruder];
@@ -9168,8 +9179,6 @@ void prepare_move()
      plan_buffer_line(destination[X_AXIS], destination[Y_AXIS], destination[Z_AXIS], destination[E_AXIS], feedrate*feedmultiply*(1./(60.f*100.f)), active_extruder);
 #endif
   }
-  if (waiting_inside_plan_buffer_line_print_aborted)
-      return;
 
   set_current_to_destination();
 }
@@ -9379,7 +9388,7 @@ if(0)
 
   if( (_millis() - previous_millis_cmd) >  max_inactive_time )
     if(max_inactive_time)
-      kill(_n(""), 4);
+      kill(_n("Inactivity Shutdown"), 4);
   if(stepper_inactive_time)  {
     if( (_millis() - previous_millis_cmd) >  stepper_inactive_time )
     {
@@ -9420,7 +9429,7 @@ if(0)
     // ----------------------------------------------------------------
     if ( killCount >= KILL_DELAY)
     {
-       kill("", 5);
+       kill(NULL, 5);
     }
   #endif
     
@@ -9498,6 +9507,16 @@ void kill(const char *full_screen_message, unsigned char id)
   } // Wait for reset
 }
 
+// Stop: Emergency stop used by overtemp functions which allows recovery
+//
+//   In addition to stopping the print, this prevents subsequent G[0-3] commands to be
+//   processed via USB (using "Stopped") until the print is resumed via M999 or
+//   manually started from scratch with the LCD.
+//
+//   Note that the current instruction is completely discarded, so resuming from Stop()
+//   will introduce either over/under extrusion on the current segment, and will not
+//   survive a power panic. Switching Stop() to use the pause machinery instead (with
+//   the addition of disabling the headers) could allow true recovery in the future.
 void Stop()
 {
   disable_heater();
@@ -10308,9 +10327,11 @@ float temp_compensation_pinda_thermistor_offset(float temperature_pinda)
 void long_pause() //long pause print
 {
 	st_synchronize();
-	
 	start_pause_print = _millis();
 
+    // Stop heaters
+    setAllTargetHotends(0);
+
 	//retract
 	current_position[E_AXIS] -= default_retraction;
 	plan_buffer_line_curposXYZE(400, active_extruder);
@@ -10325,8 +10346,7 @@ void long_pause() //long pause print
 	current_position[Y_AXIS] = Y_PAUSE_POS;
 	plan_buffer_line_curposXYZE(50, active_extruder);
 
-	// Turn off the hotends and print fan
-    setAllTargetHotends(0);
+	// Turn off the print fan
 	fanSpeed = 0;
 }
 
@@ -10348,6 +10368,11 @@ void uvlo_()
 	unsigned long time_start = _millis();
 	bool sd_print = card.sdprinting;
     // Conserve power as soon as possible.
+#ifdef LCD_BL_PIN
+    backlightMode = BACKLIGHT_MODE_DIM;
+    backlightLevel_LOW = 0;
+    backlight_update();
+#endif //LCD_BL_PIN
     disable_x();
     disable_y();
     
@@ -10973,7 +10998,9 @@ void stop_and_save_print_to_ram(float z_move, float e_move)
 	sei();
 	if ((z_move != 0) || (e_move != 0)) { // extruder or z move
 #if 1
-    // Rather than calling plan_buffer_line directly, push the move into the command queue, 
+    // Rather than calling plan_buffer_line directly, push the move into the command queue so that
+    // the caller can continue processing. This is used during powerpanic to save the state as we
+    // move away from the print.
     char buf[48];
 
 	// First unretract (relative extrusion)
@@ -11002,6 +11029,7 @@ void stop_and_save_print_to_ram(float z_move, float e_move)
     memcpy(current_position, saved_pos, sizeof(saved_pos));
     memcpy(destination, current_position, sizeof(destination));
 #endif
+    waiting_inside_plan_buffer_line_print_aborted = true; //unroll the stack
   }
 }
 
@@ -11084,6 +11112,14 @@ void restore_print_from_ram_and_continue(float e_move)
     waiting_inside_plan_buffer_line_print_aborted = true; //unroll the stack
 }
 
+// Cancel the state related to a currently saved print
+void cancel_saved_printing()
+{
+    saved_target[0] = SAVED_TARGET_UNSET;
+    saved_printing_type = PRINTING_TYPE_NONE;
+    saved_printing = false;
+}
+
 void print_world_coordinates()
 {
 	printf_P(_N("world coordinates: (%.3f, %.3f, %.3f)\n"), current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS]);

+ 16 - 0
Firmware/Sd2Card.cpp

@@ -319,6 +319,22 @@ bool Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) {
       goto fail;
     }
   }
+
+  // send 0xFF until 0xFF received to give card some clock cycles
+  t0 = (uint16_t)_millis();
+  SERIAL_ECHOLNRPGM(PSTR("Sending 0xFF"));
+  spiSend(0XFF);
+  while ((status_ = spiRec()) != 0xFF)
+  {
+    spiSend(0XFF);
+    if (((uint16_t)_millis() - t0) > SD_CARD_ERROR_FF_TIMEOUT)
+    {
+      error(SD_CARD_ERROR_CMD8);
+      SERIAL_ECHOLNRPGM(PSTR("No 0xFF received"));
+      goto fail;
+    }
+  }
+
   // check SD version
   if ((cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND)) {
     type(SD_CARD_TYPE_SD1);

+ 2 - 0
Firmware/Sd2Card.h

@@ -105,6 +105,8 @@ uint8_t const SD_CARD_ERROR_SCK_RATE = 0X18;
 uint8_t const SD_CARD_ERROR_INIT_NOT_CALLED = 0X19;
 /** crc check error */
 uint8_t const SD_CARD_ERROR_CRC = 0X20;
+/** no response to sent 0xFF */
+uint8_t const SD_CARD_ERROR_FF_TIMEOUT = 0X21;
 
 /** Toshiba FlashAir: iSDIO */
 uint8_t const SD_CARD_ERROR_CMD48 = 0x80;

+ 120 - 0
Firmware/backlight.cpp

@@ -0,0 +1,120 @@
+//backlight.cpp
+
+#include "backlight.h"
+#include <avr/eeprom.h>
+#include <Arduino.h>
+#include "eeprom.h"
+#include "Marlin.h"
+#include "pins.h"
+#include "fastio.h"
+#include "Timer.h"
+
+#ifdef LCD_BL_PIN
+
+#define BL_FLASH_DELAY_MS 25
+
+bool backlightSupport = 0; //only if it's true will any of the settings be visible to the user
+int16_t backlightLevel_HIGH = 0;
+int16_t backlightLevel_LOW = 0;
+uint8_t backlightMode = BACKLIGHT_MODE_BRIGHT;
+int16_t backlightTimer_period = 10;
+LongTimer backlightTimer;
+
+static void backlightTimer_reset() //used for resetting the timer and waking the display. Triggered on user interactions.
+{
+    if (!backlightSupport) return;
+    backlightTimer.start();
+    backlight_update();
+}
+
+void force_bl_on(bool section_start)
+{
+    if (section_start)
+    {
+        backlightMode = BACKLIGHT_MODE_BRIGHT;
+        if (backlightLevel_HIGH < 30) backlightLevel_HIGH = 30;
+    }
+    else
+    {
+        backlightMode = eeprom_read_byte((uint8_t *)EEPROM_BACKLIGHT_MODE);
+        backlightLevel_HIGH = eeprom_read_byte((uint8_t *)EEPROM_BACKLIGHT_LEVEL_HIGH);
+    }
+    backlight_update();
+}
+
+void backlight_wake(const uint8_t flashNo)
+{
+    if (!backlightSupport) return;
+    
+    if (flashNo)
+    {
+        uint8_t backlightMode_bck = backlightMode;
+        for (uint8_t i = 0; i < (((backlightMode_bck == BACKLIGHT_MODE_AUTO) && !backlightTimer.running()) + (flashNo * 2)); i++)
+        {
+            backlightMode = !backlightMode; //toggles between BACKLIGHT_MODE_BRIGHT and BACKLIGHT_MODE_DIM
+            backlight_update();
+            _delay(BL_FLASH_DELAY_MS);
+        }
+        backlightMode = backlightMode_bck;
+    }
+    backlightTimer_reset();
+}
+
+void backlight_save() //saves all backlight data to eeprom.
+{
+    eeprom_update_byte((uint8_t *)EEPROM_BACKLIGHT_LEVEL_HIGH, (uint8_t)backlightLevel_HIGH);
+    eeprom_update_byte((uint8_t *)EEPROM_BACKLIGHT_LEVEL_LOW, (uint8_t)backlightLevel_LOW);
+    eeprom_update_byte((uint8_t *)EEPROM_BACKLIGHT_MODE, backlightMode);
+    eeprom_update_word((uint16_t *)EEPROM_BACKLIGHT_TIMEOUT, backlightTimer_period);
+}
+
+void backlight_update()
+{
+    if (!backlightSupport) return;
+    
+    if (backlightMode == BACKLIGHT_MODE_AUTO)
+    {
+        if (backlightTimer.expired((uint32_t)backlightTimer_period * 1000ul)) analogWrite(LCD_BL_PIN, backlightLevel_LOW);
+        else if (backlightTimer.running()) analogWrite(LCD_BL_PIN, backlightLevel_HIGH);
+        else {/*do nothing*/;} //display is dimmed.
+    }
+    else if (backlightMode == BACKLIGHT_MODE_DIM) analogWrite(LCD_BL_PIN, backlightLevel_LOW);
+    else analogWrite(LCD_BL_PIN, backlightLevel_HIGH);
+}
+
+void backlight_init()
+{
+//check for backlight support on lcd
+    SET_INPUT(LCD_BL_PIN);
+    WRITE(LCD_BL_PIN,HIGH);
+    _delay(10);
+    backlightSupport = !READ(LCD_BL_PIN);
+    if (!backlightSupport) return;
+
+//initialize backlight
+    backlightMode = eeprom_read_byte((uint8_t *)EEPROM_BACKLIGHT_MODE);
+    if (backlightMode == 0xFF) //set default values
+    {
+        backlightMode = BACKLIGHT_MODE_AUTO;
+        backlightLevel_HIGH = 130;
+        backlightLevel_LOW = 50;
+        backlightTimer_period = 10; //in seconds
+        backlight_save();
+    }
+    backlightLevel_HIGH = eeprom_read_byte((uint8_t *)EEPROM_BACKLIGHT_LEVEL_HIGH);
+    backlightLevel_LOW = eeprom_read_byte((uint8_t *)EEPROM_BACKLIGHT_LEVEL_LOW);
+    backlightTimer_period = eeprom_read_word((uint16_t *)EEPROM_BACKLIGHT_TIMEOUT);
+    
+    SET_OUTPUT(LCD_BL_PIN);
+    backlightTimer_reset();
+}
+
+#else //LCD_BL_PIN
+
+void force_bl_on(__attribute__((unused)) bool section_start) {}
+void backlight_update() {}
+void backlight_init() {}
+void backlight_save() {}
+void backlight_wake(__attribute__((unused)) const uint8_t flashNo) {}
+
+#endif //LCD_BL_PIN

+ 32 - 0
Firmware/backlight.h

@@ -0,0 +1,32 @@
+//backlight.h
+#ifndef _BACKLIGHT_H
+#define _BACKLIGHT_H
+
+#include <inttypes.h>
+#include "Marlin.h"
+#include "pins.h"
+
+enum Backlight_Mode
+{
+	BACKLIGHT_MODE_DIM     = 0,
+	BACKLIGHT_MODE_BRIGHT  = 1,
+	BACKLIGHT_MODE_AUTO    = 2,
+};
+
+extern int16_t backlightLevel_HIGH;
+extern int16_t backlightLevel_LOW;
+extern uint8_t backlightMode;
+extern bool backlightSupport;
+extern int16_t backlightTimer_period;
+
+#define FORCE_BL_ON_START force_bl_on(true)
+#define FORCE_BL_ON_END force_bl_on(false)
+
+extern void force_bl_on(bool section_start);
+extern void backlight_update();
+extern void backlight_init();
+extern void backlight_save();
+extern void backlight_wake(const uint8_t flashNo = 0);
+
+
+#endif //_BACKLIGHT_H

+ 4 - 4
Firmware/cardreader.cpp

@@ -359,10 +359,10 @@ void CardReader::openFile(const char* name,bool read, bool replace_current/*=tru
     {
      if((int)file_subcall_ctr>(int)SD_PROCEDURE_DEPTH-1)
      {
-       SERIAL_ERROR_START;
-       SERIAL_ERRORPGM("trying to call sub-gcode files with too many levels. MAX level is:");
-       SERIAL_ERRORLN(SD_PROCEDURE_DEPTH);
-       kill("", 1);
+       // SERIAL_ERROR_START;
+       // SERIAL_ERRORPGM("trying to call sub-gcode files with too many levels. MAX level is:");
+       // SERIAL_ERRORLN(SD_PROCEDURE_DEPTH);
+       kill(_n("trying to call sub-gcode files with too many levels."), 1);
        return;
      }
      

+ 1 - 1
Firmware/cmdqueue.cpp

@@ -500,7 +500,7 @@ void get_command()
 
         //If command was e-stop process now
         if(strcmp(cmdbuffer+bufindw+CMDHDRSIZE, "M112") == 0)
-          kill("", 2);
+          kill(MSG_M112_KILL, 2);
         
         // Store the current line into buffer, move to the next line.
 		// Store type of entry

+ 7 - 1
Firmware/eeprom.h

@@ -207,8 +207,14 @@ static Sheets * const EEPROM_Sheets_base = (Sheets*)(EEPROM_SHEETS_BASE);
 #define EEPROM_UVLO_SAVED_TARGET (EEPROM_FSENSOR_ACTION_NA - 4*4) // 4 x float for saved target for all axes
 #define EEPROM_UVLO_FEEDMULTIPLY (EEPROM_UVLO_SAVED_TARGET - 2) // uint16_t for feedmultiply
 
+#define EEPROM_BACKLIGHT_LEVEL_HIGH (EEPROM_UVLO_FEEDMULTIPLY-1) // uint8
+#define EEPROM_BACKLIGHT_LEVEL_LOW (EEPROM_BACKLIGHT_LEVEL_HIGH-1) // uint8
+#define EEPROM_BACKLIGHT_MODE (EEPROM_BACKLIGHT_LEVEL_LOW-1) // uint8
+#define EEPROM_BACKLIGHT_TIMEOUT (EEPROM_BACKLIGHT_MODE-2) // uint16
+
+
 //This is supposed to point to last item to allow EEPROM overrun check. Please update when adding new items.
-#define EEPROM_LAST_ITEM EEPROM_UVLO_FEEDMULTIPLY
+#define EEPROM_LAST_ITEM EEPROM_BACKLIGHT_TIMEOUT
 // !!!!!
 // !!!!! this is end of EEPROM section ... all updates MUST BE inserted before this mark !!!!!
 // !!!!!

+ 3 - 3
Firmware/language.c

@@ -17,10 +17,10 @@ uint8_t lang_selected = 0;
 
 #if (LANG_MODE == 0) //primary language only
 
-uint8_t lang_select(uint8_t lang) { return 0; }
+uint8_t lang_select(__attribute__((unused)) uint8_t lang) { return 0; }
 uint8_t lang_get_count() { return 1; }
-uint16_t lang_get_code(uint8_t lang) { return LANG_CODE_EN; }
-const char* lang_get_name_by_code(uint16_t code) { return _n("English"); }
+uint16_t lang_get_code(__attribute__((unused)) uint8_t lang) { return LANG_CODE_EN; }
+const char* lang_get_name_by_code(__attribute__((unused)) uint16_t code) { return _n("English"); }
 void lang_reset(void) { }
 uint8_t lang_is_selected(void) { return 1; }
 

+ 8 - 0
Firmware/messages.c

@@ -131,6 +131,13 @@ const char MSG_MAGNETS_COMP[] PROGMEM_I1 = ISTR("Magnets comp."); ////
 const char MSG_FS_ACTION[] PROGMEM_I1 = ISTR("FS Action"); ////
 const char MSG_FS_CONTINUE[] PROGMEM_I1 = ISTR("Cont."); ////
 const char MSG_FS_PAUSE[] PROGMEM_I1 = ISTR("Pause"); ////
+const char MSG_BRIGHTNESS[] PROGMEM_I1 = ISTR("Brightness"); ////
+const char MSG_BL_HIGH[] PROGMEM_I1 = ISTR("Level Bright"); ////
+const char MSG_BL_LOW[] PROGMEM_I1 = ISTR("Level Dimmed"); ////
+const char MSG_TIMEOUT[] PROGMEM_I1 = ISTR("Timeout"); ////
+const char MSG_BRIGHT[] PROGMEM_I1 = ISTR("Bright"); ////
+const char MSG_DIM[] PROGMEM_I1 = ISTR("Dim"); ////
+const char MSG_AUTO[] PROGMEM_I1 = ISTR("Auto"); ////
 
 //not internationalized messages
 const char MSG_SD_WORKDIR_FAIL[] PROGMEM_N1 = "workDir open failed"; ////
@@ -160,3 +167,4 @@ const char MSG_OCTOPRINT_RESUMED[] PROGMEM_N1 = "// action:resumed"; ////
 const char MSG_OCTOPRINT_CANCEL[] PROGMEM_N1 = "// action:cancel"; ////
 const char MSG_FANCHECK_EXTRUDER[] PROGMEM_N1 = "Err: EXTR. FAN ERROR"; ////c=20
 const char MSG_FANCHECK_PRINT[] PROGMEM_N1 = "Err: PRINT FAN ERROR"; ////c=20
+const char MSG_M112_KILL[] PROGMEM_N1 = "M112 called. Emergency Stop."; ////c=20

+ 8 - 0
Firmware/messages.h

@@ -131,6 +131,13 @@ extern const char MSG_MAGNETS_COMP[];
 extern const char MSG_FS_ACTION[];
 extern const char MSG_FS_CONTINUE[];
 extern const char MSG_FS_PAUSE[];
+extern const char MSG_BRIGHTNESS[];
+extern const char MSG_BL_HIGH[];
+extern const char MSG_BL_LOW[];
+extern const char MSG_TIMEOUT[];
+extern const char MSG_BRIGHT[];
+extern const char MSG_DIM[];
+extern const char MSG_AUTO[];
 
 //not internationalized messages
 extern const char MSG_BROWNOUT_RESET[];
@@ -161,6 +168,7 @@ extern const char MSG_OCTOPRINT_RESUMED[];
 extern const char MSG_OCTOPRINT_CANCEL[];
 extern const char MSG_FANCHECK_EXTRUDER[];
 extern const char MSG_FANCHECK_PRINT[];
+extern const char MSG_M112_KILL[];
 
 #if defined(__cplusplus)
 }

+ 1 - 12
Firmware/mmu.cpp

@@ -1578,18 +1578,7 @@ void mmu_continue_loading(bool blocking)
             break;
         case Ls::Unload:
             stop_and_save_print_to_ram(0, 0);
-
-            //lift z
-            current_position[Z_AXIS] += Z_PAUSE_LIFT;
-            if (current_position[Z_AXIS] > Z_MAX_POS) current_position[Z_AXIS] = Z_MAX_POS;
-            plan_buffer_line_curposXYZE(15, active_extruder);
-            st_synchronize();
-
-            //Move XY to side
-            current_position[X_AXIS] = X_PAUSE_POS;
-            current_position[Y_AXIS] = Y_PAUSE_POS;
-            plan_buffer_line_curposXYZE(50, active_extruder);
-            st_synchronize();
+            long_pause();
 
             mmu_command(MmuCmd::U0);
             manage_response(false, true, MMU_UNLOAD_MOVE);

+ 2 - 2
Firmware/optiboot_w25x20cl.cpp

@@ -258,11 +258,11 @@ void optiboot_w25x20cl_enter()
         uint32_t addr = (((uint32_t)rampz) << 16) | address;
         // During a single bootloader run, only erase a 64kB block once.
         // An 8bit bitmask 'pages_erased' covers 512kB of FLASH memory.
-        if (address == 0 && (pages_erased & (1 << addr)) == 0) {
+        if ((address == 0) && (pages_erased & (1 << (addr >> 16))) == 0) {
           w25x20cl_wait_busy();
           w25x20cl_enable_wr();
           w25x20cl_block64_erase(addr);
-          pages_erased |= (1 << addr);
+          pages_erased |= (1 << (addr >> 16));
         }
         w25x20cl_wait_busy();
         w25x20cl_enable_wr();

+ 1 - 1
Firmware/pins_Einsy_1_0.h

@@ -100,7 +100,7 @@
 
 //#define KILL_PIN            32
 
-//#define LCD_BL_PIN          5   //backlight control pin
+#define LCD_BL_PIN          5   //backlight control pin
 #define BEEPER              84  // Beeper on AUX-4
 #define LCD_PINS_RS         82
 #define LCD_PINS_ENABLE     61 // !!! changed from 18 (EINY03)

+ 7 - 0
Firmware/sound.cpp

@@ -5,6 +5,7 @@
 //#include <inttypes.h>
 //#include <avr/eeprom.h>
 //#include "eeprom.h"
+#include "backlight.h"
 
 
 //eSOUND_MODE eSoundMode=e_SOUND_MODE_LOUD;
@@ -63,6 +64,7 @@ Sound_SaveMode();
 
 //if critical is true then silend and once mode is ignored
 void Sound_MakeCustom(uint16_t ms,uint16_t tone_,bool critical){
+    backlight_wake();
      if (!critical){
           if (eSoundMode != e_SOUND_MODE_SILENT){
                if(!tone_){
@@ -135,6 +137,7 @@ switch(eSoundMode)
 
 static void Sound_DoSound_Blind_Alert(void)
 {
+    backlight_wake(1);
      uint8_t nI;
 
      for(nI=0; nI<20; nI++)
@@ -148,6 +151,7 @@ static void Sound_DoSound_Blind_Alert(void)
 
  static void Sound_DoSound_Encoder_Move(void)
 {
+    backlight_wake();
 uint8_t nI;
 
  for(nI=0;nI<5;nI++)
@@ -161,6 +165,7 @@ uint8_t nI;
 
 static void Sound_DoSound_Echo(void)
 {
+    backlight_wake();
 uint8_t nI;
 
 for(nI=0;nI<10;nI++)
@@ -174,6 +179,7 @@ for(nI=0;nI<10;nI++)
 
 static void Sound_DoSound_Prompt(void)
 {
+    backlight_wake(2);
 WRITE(BEEPER,HIGH);
 _delay_ms(500);
 WRITE(BEEPER,LOW);
@@ -181,6 +187,7 @@ WRITE(BEEPER,LOW);
 
 static void Sound_DoSound_Alert(bool bOnce)
 {
+    backlight_wake();
 uint8_t nI,nMax;
 
 nMax=bOnce?1:3;

+ 1 - 1
Firmware/temperature.cpp

@@ -879,7 +879,7 @@ static float analog2temp(int raw, uint8_t e) {
       SERIAL_ERROR_START;
       SERIAL_ERROR((int)e);
       SERIAL_ERRORLNPGM(" - Invalid extruder number !");
-      kill(PSTR(""), 6);
+      kill(NULL, 6);
       return 0.0;
   } 
   #ifdef HEATER_0_USES_MAX6675

+ 4 - 4
Firmware/tmc2130.cpp

@@ -807,15 +807,15 @@ void tmc2130_goto_step(uint8_t axis, uint8_t step, uint8_t dir, uint16_t delay_u
 	{
 		dir = tmc2130_get_inv(axis)?0:1;
 		int steps = (int)step - (int)(mscnt >> shift);
-		if (steps < 0)
+		if (steps > static_cast<int>(cnt / 2))
 		{
 			dir ^= 1;
-			steps = -steps;
+			steps = cnt - steps; // This can create a negative step value
 		}
-		if (steps > static_cast<int>(cnt / 2))
+        if (steps < 0)
 		{
 			dir ^= 1;
-			steps = cnt - steps;
+			steps = -steps;
 		}
 		cnt = steps;
 	}

+ 116 - 42
Firmware/ultralcd.cpp

@@ -19,6 +19,8 @@
 #include "lcd.h"
 #include "menu.h"
 
+#include "backlight.h"
+
 #include "util.h"
 #include "mesh_bed_leveling.h"
 #include "mesh_bed_calibration.h"
@@ -56,6 +58,7 @@ char longFilenameOLD[LONG_FILENAME_LENGTH];
 
 static void lcd_sd_updir();
 static void lcd_mesh_bed_leveling_settings();
+static void lcd_backlight_menu();
 
 int8_t ReInitLCD = 0;
 
@@ -112,7 +115,9 @@ static const char* lcd_display_message_fullscreen_nonBlocking_P(const char *msg,
 
 /* Different menus */
 static void lcd_status_screen();
+#if (LANG_MODE != 0)
 static void lcd_language_menu();
+#endif
 static void lcd_main_menu();
 static void lcd_tune_menu();
 //static void lcd_move_menu();
@@ -581,7 +586,7 @@ void lcdui_print_Z_coord(void)
     if (custom_message_type == CustomMsg::MeshBedLeveling)
         lcd_puts_P(_N("Z   --- "));
     else
-		lcd_printf_P(_N("Z%6.2f "), current_position[Z_AXIS]);
+		lcd_printf_P(_N("Z%6.2f%c"), current_position[Z_AXIS], axis_known_position[Z_AXIS]?' ':'?');
 }
 
 #ifdef PLANNER_DIAGNOSTICS
@@ -617,21 +622,24 @@ void lcdui_print_feedrate(void)
 // Print percent done in form "USB---%", " SD---%", "   ---%" (7 chars total)
 void lcdui_print_percent_done(void)
 {
-	char sheet[8];
 	const char* src = is_usb_printing?_N("USB"):(IS_SD_PRINTING?_N(" SD"):_N("   "));
 	char per[4];
 	bool num = IS_SD_PRINTING || (PRINTER_ACTIVE && (print_percent_done_normal != PRINT_PERCENT_DONE_INIT));
 	if (!num || heating_status) // either not printing or heating
 	{
-		eeprom_read_block(sheet, EEPROM_Sheets_base->s[eeprom_read_byte(&(EEPROM_Sheets_base->active_sheet))].name, 7);
-		sheet[7] = '\0';
-		lcd_printf_P(PSTR("%s"),sheet);
-	}
-	else
-	{
-		sprintf_P(per, num?_N("%3hhd"):_N("---"), calc_percent_done());
-		lcd_printf_P(_N("%3S%3s%%"), src, per);
+		const int8_t sheetNR = eeprom_read_byte(&(EEPROM_Sheets_base->active_sheet));
+		const int8_t nextSheet = eeprom_next_initialized_sheet(sheetNR);
+		if ((nextSheet >= 0) && (sheetNR != nextSheet))
+		{
+			char sheet[8];
+			eeprom_read_block(sheet, EEPROM_Sheets_base->s[sheetNR].name, 7);
+			sheet[7] = '\0';
+			lcd_printf_P(PSTR("%-7s"),sheet);
+			return; //do not also print the percentage
+		}
 	}
+	sprintf_P(per, num?_N("%3hhd"):_N("---"), calc_percent_done());
+	lcd_printf_P(_N("%3S%3s%%"), src, per);
 }
 
 // Print extruder status (5 chars total)
@@ -1100,6 +1108,7 @@ void lcd_commands()
 			lcd_setstatuspgm(_i("Print paused"));////MSG_PRINT_PAUSED c=20 r=1
             lcd_commands_type = LcdCommands::Idle;
             lcd_commands_step = 0;
+            long_pause();
 		}
 	}
 
@@ -1656,9 +1665,8 @@ void lcd_return_to_status()
 //! @brief Pause print, disable nozzle heater, move to park position
 void lcd_pause_print()
 {
-    lcd_return_to_status();
     stop_and_save_print_to_ram(0.0,0.0);
-    long_pause();
+    lcd_return_to_status();
     isPrintPaused = true;
     if (LcdCommands::Idle == lcd_commands_type)
     {
@@ -2282,6 +2290,9 @@ static void lcd_support_menu()
 void lcd_set_fan_check() {
 	fans_check_enabled = !fans_check_enabled;
 	eeprom_update_byte((unsigned char *)EEPROM_FAN_CHECK_ENABLED, fans_check_enabled);
+#ifdef FANCHECK
+	if (fans_check_enabled == false) fan_check_error = EFCE_OK; //reset error if fanCheck is disabled during error. Allows resuming print.
+#endif //FANCHECK
 }
 
 #ifdef MMU_HAS_CUTTER
@@ -4926,6 +4937,7 @@ void lcd_wizard() {
 	}
 }
 
+#if (LANG_MODE != 0)
 void lcd_language()
 {
 	lcd_update_enable(true);
@@ -4945,6 +4957,7 @@ void lcd_language()
 	else
 		lang_select(LANG_ID_PRI);
 }
+#endif
 
 static void wait_preheat()
 {
@@ -5053,8 +5066,10 @@ void lcd_wizard(WizState state)
 	// Make sure EEPROM_WIZARD_ACTIVE is true if entering using different entry point
 	// other than WizState::Run - it is useful for debugging wizard.
 	if (state != S::Run) eeprom_update_byte((uint8_t*)EEPROM_WIZARD_ACTIVE, 1);
-
-	while (!end) {
+    
+    FORCE_BL_ON_START;
+	
+    while (!end) {
 		printf_P(PSTR("Wizard state: %d\n"), state);
 		switch (state) {
 		case S::Run: //Run wizard?
@@ -5190,7 +5205,9 @@ void lcd_wizard(WizState state)
 		default: break;
 		}
 	}
-
+    
+    FORCE_BL_ON_END;
+    
 	printf_P(_N("Wizard end state: %d\n"), state);
 	switch (state) { //final message
 	case S::Restore: //printer was already calibrated
@@ -5827,6 +5844,13 @@ static void lcd_settings_menu()
 	SETTINGS_SD;
 	SETTINGS_SOUND;
 
+#ifdef LCD_BL_PIN
+    if (backlightSupport)
+    {
+        MENU_ITEM_SUBMENU_P(_T(MSG_BRIGHTNESS), lcd_backlight_menu);
+    }
+#endif //LCD_BL_PIN
+
 	if (farm_mode)
 	{
 		MENU_ITEM_SUBMENU_P(PSTR("Farm number"), lcd_farm_no);
@@ -6702,6 +6726,7 @@ static void lcd_test_menu()
 static bool fan_error_selftest()
 {
 #ifdef FANCHECK
+    if (!fans_check_enabled) return 0;
 
     fanSpeed = 255;
 #ifdef FAN_SOFT_PWM
@@ -6732,9 +6757,8 @@ static bool fan_error_selftest()
         return 1;
     }
 #endif
+#endif //FANCHECK
     return 0;
-
-#endif //FANCHECK   
 }
 
 //! @brief Resume paused print
@@ -6749,10 +6773,10 @@ void lcd_resume_print()
 
     if (fan_error_selftest()) return; //abort if error persists
 
+    isPrintPaused = false;
     restore_print_from_ram_and_continue(0.0);
     pause_time += (_millis() - start_pause_print); //accumulate time when print is paused for correct statistics calculation
     refresh_cmd_timeout();
-    isPrintPaused = false;
     SERIAL_PROTOCOLLNRPGM(MSG_OCTOPRINT_RESUMED); //resume octoprint
 }
 
@@ -6904,7 +6928,7 @@ static void lcd_main_menu()
 			{
 				MENU_ITEM_FUNCTION_P(_i("Pause print"), lcd_pause_print);////MSG_PAUSE_PRINT
 			}
-			else
+			else if(isPrintPaused)
 			{
 				#ifdef FANCHECK
 					if((fan_check_error == EFCE_FIXED) || (fan_check_error == EFCE_OK))
@@ -7156,6 +7180,12 @@ static void lcd_tune_menu()
 #endif //TMC2130
 	SETTINGS_MMU_MODE;
     SETTINGS_SOUND;
+#ifdef LCD_BL_PIN
+    if (backlightSupport)
+    {
+        MENU_ITEM_SUBMENU_P(_T(MSG_BRIGHTNESS), lcd_backlight_menu);
+    }
+#endif //LCD_BL_PIN
 	MENU_END();
 }
 
@@ -7205,6 +7235,36 @@ static void lcd_mesh_bed_leveling_settings()
 	//SETTINGS_MBL_MODE;
 }
 
+#ifdef LCD_BL_PIN
+static void backlight_mode_toggle()
+{
+    switch (backlightMode)
+    {
+        case BACKLIGHT_MODE_BRIGHT: backlightMode = BACKLIGHT_MODE_DIM; break;
+        case BACKLIGHT_MODE_DIM: backlightMode = BACKLIGHT_MODE_AUTO; break;
+        case BACKLIGHT_MODE_AUTO: backlightMode = BACKLIGHT_MODE_BRIGHT; break;
+        default: backlightMode = BACKLIGHT_MODE_BRIGHT; break;
+    }
+    backlight_save();
+}
+
+static void lcd_backlight_menu()
+{
+    MENU_BEGIN();
+    ON_MENU_LEAVE(
+        backlight_save();
+    );
+    
+    MENU_ITEM_BACK_P(_T(MSG_BACK));
+    MENU_ITEM_EDIT_int3_P(_T(MSG_BL_HIGH), &backlightLevel_HIGH, backlightLevel_LOW, 255);
+    MENU_ITEM_EDIT_int3_P(_T(MSG_BL_LOW), &backlightLevel_LOW, 0, backlightLevel_HIGH);
+	MENU_ITEM_TOGGLE_P(_T(MSG_MODE), ((backlightMode==BACKLIGHT_MODE_BRIGHT) ? _T(MSG_BRIGHT) : ((backlightMode==BACKLIGHT_MODE_DIM) ? _T(MSG_DIM) : _T(MSG_AUTO))), backlight_mode_toggle);
+    MENU_ITEM_EDIT_int3_P(_T(MSG_TIMEOUT), &backlightTimer_period, 1, 999);
+    
+    MENU_END();
+}
+#endif //LCD_BL_PIN
+
 static void lcd_control_temperature_menu()
 {
 #ifdef PIDTEMP
@@ -7255,30 +7315,26 @@ static void lcd_sd_updir()
 
 void lcd_print_stop()
 {
-//-//
-     if(!card.sdprinting)
-          {
-          SERIAL_ECHOLNRPGM(MSG_OCTOPRINT_CANCEL);   // for Octoprint
-          }
-	saved_printing = false;
-    saved_printing_type = PRINTING_TYPE_NONE;
+    if (!card.sdprinting) {
+        SERIAL_ECHOLNRPGM(MSG_OCTOPRINT_CANCEL);   // for Octoprint
+    }
+
+    CRITICAL_SECTION_START;
+
+    // Clear any saved printing state
+    cancel_saved_printing();
 	cancel_heatup = true;
-#ifdef MESH_BED_LEVELING
-	mbl.active = false;
-#endif
-	// Stop the stoppers, update the position from the stoppers.
-	if (mesh_bed_leveling_flag == false && homing_flag == false)
-	{
-		planner_abort_hard();
-		// Because the planner_abort_hard() initialized current_position[Z] from the stepper,
-		// Z baystep is no more applied. Reset it.
-		babystep_reset();
-	}
-	// Clean the input command queue.
+
+    // Abort the planner/queue/sd
+    planner_abort_hard();
 	cmdqueue_reset();
-	lcd_setstatuspgm(_T(MSG_PRINT_ABORTED));
 	card.sdprinting = false;
 	card.closefile();
+    st_reset_timer();
+
+    CRITICAL_SECTION_END;
+
+	lcd_setstatuspgm(_T(MSG_PRINT_ABORTED));
 	stoptime = _millis();
 	unsigned long t = (stoptime - starttime - pause_time) / 1000; //time in s
 	pause_time = 0;
@@ -7492,6 +7548,10 @@ bool lcd_selftest()
 #if !IR_SENSOR_ANALOG
      _delay(2000);
 #endif //!IR_SENSOR_ANALOG
+    
+    FORCE_BL_ON_START;
+    
+	_delay(2000);
 	KEEPALIVE_STATE(IN_HANDLER);
 #if IR_SENSOR_ANALOG
      bool bAction;
@@ -7724,7 +7784,10 @@ bool lcd_selftest()
 	#ifdef TMC2130
 	  FORCE_HIGH_POWER_END;
 	#endif // TMC2130
-	KEEPALIVE_STATE(NOT_BUSY);
+    
+    FORCE_BL_ON_END;
+	
+    KEEPALIVE_STATE(NOT_BUSY);
 	return(_result);
 }
 
@@ -8133,7 +8196,9 @@ static bool lcd_selfcheck_check_heater(bool _isbed)
 static void lcd_selftest_error(TestError testError, const char *_error_1, const char *_error_2)
 {
 	lcd_beeper_quick_feedback();
-
+    
+    FORCE_BL_ON_END;
+    
 	target_temperature[0] = 0;
 	target_temperature_bed = 0;
 	manage_heater();
@@ -8732,6 +8797,7 @@ void ultralcd_init()
         else lcd_autoDeplete = autoDepleteRaw;
 
     }
+    backlight_init();
 	lcd_init();
 	lcd_refresh();
 	lcd_longpress_func = menu_lcd_longpress_func;
@@ -8880,6 +8946,7 @@ uint8_t get_message_level()
 
 void menu_lcd_longpress_func(void)
 {
+	backlight_wake();
     if (homing_flag || mesh_bed_leveling_flag || menu_menu == lcd_babystep_z || menu_menu == lcd_move_z)
     {
         // disable longpress during re-entry, while homing or calibration
@@ -8961,6 +9028,7 @@ void menu_lcd_lcdupdate_func(void)
 		lcd_draw_update = 2;
 		lcd_oldcardstatus = IS_SD_INSERTED;
 		lcd_refresh(); // to maybe revive the LCD if static electricity killed it.
+        backlight_wake();
 		if (lcd_oldcardstatus)
 		{
 			card.initsd();
@@ -8978,6 +9046,7 @@ void menu_lcd_lcdupdate_func(void)
 		}
 	}
 #endif//CARDINSERTED
+    backlight_update();
 	if (lcd_next_update_millis < _millis())
 	{
 		if (abs(lcd_encoder_diff) >= ENCODER_PULSES_PER_STEP)
@@ -8988,9 +9057,14 @@ void menu_lcd_lcdupdate_func(void)
 			Sound_MakeSound(e_SOUND_TYPE_EncoderMove);
 			lcd_encoder_diff = 0;
 			lcd_timeoutToStatus.start();
+			backlight_wake();
 		}
 
-		if (LCD_CLICKED) lcd_timeoutToStatus.start();
+		if (LCD_CLICKED)
+		{
+			lcd_timeoutToStatus.start();
+			backlight_wake();
+		}
 
 		(*menu_menu)();
 

+ 3 - 0
Firmware/ultralcd.h

@@ -6,6 +6,7 @@
 #include "conv2str.h"
 #include "menu.h"
 #include "mesh_bed_calibration.h"
+#include "config.h"
 
 #include "config.h"
 
@@ -220,7 +221,9 @@ void lcd_set_degree();
 void lcd_set_progress();
 #endif
 
+#if (LANG_MODE != 0)
 void lcd_language();
+#endif
 
 void lcd_wizard();
 bool lcd_autoDepleteEnabled();

+ 1 - 0
README.md

@@ -178,6 +178,7 @@ Example:
 
 # 4. Documentation
 run [doxygen](http://www.doxygen.nl/) in Firmware folder
+or visit https://prusa3d.github.io/Prusa-Firmware-Doc for doxygen generated output
 
 # 5. FAQ
 Q:I built firmware using Arduino and I see "?" instead of numbers in printer user interface.

+ 1 - 1
lang/lang_en_cz.txt

@@ -1188,7 +1188,7 @@
 
 #
 "The printer will start printing a zig-zag line. Rotate the knob until you reach the optimal height. Check the pictures in the handbook (Calibration chapter)."
-"\x00"
+"Tiskarna zacne tisknout lomenou caru. Otacenim tlacitka nastavte optimalni vysku. Postupujte podle obrazku v handbooku (kapitola Kalibrace)."
 
 #
 "Y-correct:"

+ 1 - 1
lang/lang_en_de.txt

@@ -1188,7 +1188,7 @@
 
 #
 "The printer will start printing a zig-zag line. Rotate the knob until you reach the optimal height. Check the pictures in the handbook (Calibration chapter)."
-"\x00"
+"Der Drucker beginnt mit dem Drucken einer Zickzacklinie. Drehen Sie den Knopf, bis Sie die optimale Hoehe erreicht haben. Ueberpruefen Sie die Bilder im Handbuch (Kapitel Kalibrierung)."
 
 #
 "Y-correct:"

+ 1 - 1
lang/lang_en_es.txt

@@ -1188,7 +1188,7 @@
 
 #
 "The printer will start printing a zig-zag line. Rotate the knob until you reach the optimal height. Check the pictures in the handbook (Calibration chapter)."
-"\x00"
+"La impresora comenzara a imprimir una linea en zig-zag. Gira el dial hasta que la linea alcance la altura optima. Mira las fotos del manual (Capitulo de calibracion)."
 
 #
 "Y-correct:"

+ 1 - 1
lang/lang_en_fr.txt

@@ -1185,7 +1185,7 @@
 
 #
 "The printer will start printing a zig-zag line. Rotate the knob until you reach the optimal height. Check the pictures in the handbook (Calibration chapter)."
-"\x00"
+"L'imprimante commencera a  imprimer une ligne en zig-zag. Tournez le bouton jusqu'a atteindre la hauteur optimale. Consultez les photos dans le manuel (chapitre Calibration)."
 
 #
 "Y-correct:"

+ 1 - 1
lang/lang_en_it.txt

@@ -1187,7 +1187,7 @@
 
 #
 "The printer will start printing a zig-zag line. Rotate the knob until you reach the optimal height. Check the pictures in the handbook (Calibration chapter)."
-"\x00"
+"La stampante iniziera a stampare una linea a zig-zag. Gira la manopola fino a che non hai raggiungo l'altezza ottimale. Verifica con le immagini nel manuale (capitolo sulla calibrazione):"
 
 #
 "Y-correct:"

+ 1 - 1
lang/lang_en_pl.txt

@@ -1187,7 +1187,7 @@
 
 #
 "The printer will start printing a zig-zag line. Rotate the knob until you reach the optimal height. Check the pictures in the handbook (Calibration chapter)."
-"\x00"
+"Drukarka zacznie drukowanie linii w ksztalcie zygzaka. Ustaw optymalna wysokosc obracajac pokretlo. Porownaj z ilustracjami w Podreczniku (rozdzial Kalibracja)."
 
 #
 "Y-correct:"