Browse Source

Merge branch 'MK3' into PFW-1186

DRracer 3 years ago
parent
commit
defbaa6ff8

+ 3 - 3
Firmware/Configuration.h

@@ -16,8 +16,8 @@ extern uint16_t nPrinterType;
 extern PGM_P sPrinterName;
 
 // Firmware version
-#define FW_VERSION "3.9.3-RC1"
-#define FW_COMMIT_NR 3555
+#define FW_VERSION "3.9.3"
+#define FW_COMMIT_NR 3556
 // FW_VERSION_UNKNOWN means this is an unofficial build.
 // The firmware should only be checked into github with this symbol.
 #define FW_DEV_VERSION FW_VERSION_UNKNOWN
@@ -552,7 +552,7 @@ enum CalibrationStatus
 // Try to maintain a minimum distance from the bed even when Z is
 // unknown when doing the following operations
 #define MIN_Z_FOR_LOAD    50
-#define MIN_Z_FOR_UNLOAD  20
+#define MIN_Z_FOR_UNLOAD  50
 #define MIN_Z_FOR_PREHEAT 10
 
 #include "Configuration_adv.h"

+ 10 - 0
Firmware/Configuration_adv.h

@@ -62,6 +62,11 @@
 // before setting a PWM value. (Does not work with software PWM for fan on Sanguinololu)
 #define FAN_KICKSTART_TIME 800
 
+/**
+ * Auto-report temperatures with M155 S<seconds>
+ */
+#define AUTO_REPORT_TEMPERATURES
+
 
 
 
@@ -376,6 +381,11 @@ const unsigned int dropsegments=5; //everything with less than this number of st
   #endif
 #endif
 
+/**
+ * Include capabilities in M115 output
+ */
+#define EXTENDED_CAPABILITIES_REPORT
+
 //===========================================================================
 //=============================  Define Defines  ============================
 //===========================================================================

+ 1 - 18
Firmware/Marlin.h

@@ -4,7 +4,7 @@
 #ifndef MARLIN_H
 #define MARLIN_H
 
-#define  FORCE_INLINE __attribute__((always_inline)) inline
+#include "macros.h"
 
 #include <math.h>
 #include <stdio.h>
@@ -116,7 +116,6 @@ void serial_echopair_P(const char *s_P, unsigned long v);
 void serialprintPGM(const char *str);
 
 bool is_buffer_empty();
-void get_command();
 void process_commands();
 void ramming();
 
@@ -241,23 +240,12 @@ void Stop();
 bool IsStopped();
 void finishAndDisableSteppers();
 
-//put an ASCII command at the end of the current buffer.
-void enquecommand(const char *cmd, bool from_progmem = false);
-
 //put an ASCII command at the end of the current buffer, read from flash
 #define enquecommand_P(cmd) enquecommand(cmd, true)
 
-//put an ASCII command at the begin of the current buffer
-void enquecommand_front(const char *cmd, bool from_progmem = false);
-
 //put an ASCII command at the begin of the current buffer, read from flash
 #define enquecommand_front_P(cmd) enquecommand_front(cmd, true)
 
-void repeatcommand_front();
-
-// Remove all lines from the command queue.
-void cmdqueue_reset();
-
 void prepare_arc_move(char isclockwise);
 void clamp_to_software_endstops(float target[3]);
 void refresh_cmd_timeout(void);
@@ -287,11 +275,6 @@ FORCE_INLINE unsigned long millis_nc() {
 void setPwmFrequency(uint8_t pin, int val);
 #endif
 
-#ifndef CRITICAL_SECTION_START
-  #define CRITICAL_SECTION_START  unsigned char _sreg = SREG; cli();
-  #define CRITICAL_SECTION_END    SREG = _sreg;
-#endif //CRITICAL_SECTION_START
-
 extern bool fans_check_enabled;
 extern float homing_feedrate[];
 extern uint8_t axis_relative_modes;

+ 248 - 176
Firmware/Marlin_main.cpp

@@ -47,7 +47,9 @@
 #include "Configuration.h"
 #include "Marlin.h"
 #include "config.h"
-  
+
+#include "macros.h"
+
 #ifdef ENABLE_AUTO_BED_LEVELING
 #include "vector_3.h"
   #ifdef AUTO_BED_LEVELING_GRID
@@ -137,12 +139,6 @@
 #include "sound.h"
 
 #include "cmdqueue.h"
-#include "io_atmega2560.h"
-
-// Macros for bit masks
-#define BIT(b) (1<<(b))
-#define TEST(n,b) (((n)&BIT(b))!=0)
-#define SET_BIT(n,b,value) (n) ^= ((-value)^(n)) & (BIT(b))
 
 //Macro for print fan speed
 #define FAN_PULSE_WIDTH_LIMIT ((fanSpeed > 100) ? 3 : 4) //time in ms
@@ -393,6 +389,11 @@ static int saved_fanSpeed = 0; //!< Print fan speed
 
 static int saved_feedmultiply_mm = 100;
 
+#ifdef AUTO_REPORT_TEMPERATURES
+static LongTimer auto_report_temp_timer;
+static uint8_t auto_report_temp_period = 0;
+#endif //AUTO_REPORT_TEMPERATURES
+
 //===========================================================================
 //=============================Routines======================================
 //===========================================================================
@@ -402,6 +403,7 @@ static bool setTargetedHotend(int code, uint8_t &extruder);
 static void print_time_remaining_init();
 static void wait_for_heater(long codenum, uint8_t extruder);
 static void gcode_G28(bool home_x_axis, bool home_y_axis, bool home_z_axis);
+static void gcode_M105(uint8_t extruder);
 static void temp_compensation_start();
 static void temp_compensation_apply();
 
@@ -629,7 +631,7 @@ void crashdet_cancel()
 		lcd_print_stop();
 	}else if(saved_printing_type == PRINTING_TYPE_USB){
 		SERIAL_ECHOLNRPGM(MSG_OCTOPRINT_CANCEL); //for Octoprint: works the same as clicking "Abort" button in Octoprint GUI
-		SERIAL_PROTOCOLLNRPGM(MSG_OK);
+		cmdqueue_reset();
 	}
 }
 
@@ -879,7 +881,7 @@ static void check_if_fw_is_on_right_printer(){
 
     #ifdef PAT9125
       //will return 1 only if IR can detect filament in bondtech extruder so this may fail even when we have IR sensor
-      const uint8_t ir_detected = !(PIN_GET(IR_SENSOR_PIN));
+      const uint8_t ir_detected = !READ(IR_SENSOR_PIN);
       if (ir_detected){
         lcd_show_fullscreen_message_and_wait_P(_i("MK3 firmware detected on MK3S printer"));}////c=20 r=3
     #endif //PAT9125
@@ -1727,6 +1729,18 @@ void host_keepalive() {
 #endif //HOST_KEEPALIVE_FEATURE
   if (farm_mode) return;
   long ms = _millis();
+
+#ifdef AUTO_REPORT_TEMPERATURES
+  if (auto_report_temp_timer.running())
+  {
+    if (auto_report_temp_timer.expired(auto_report_temp_period * 1000ul))
+    {
+      gcode_M105(active_extruder);
+      auto_report_temp_timer.start();
+    }
+  }
+#endif //AUTO_REPORT_TEMPERATURES
+
   if (host_keepalive_interval && busy_state != NOT_BUSY) {
     if ((ms - prev_busy_signal_ms) < (long)(1000L * host_keepalive_interval)) return;
      switch (busy_state) {
@@ -2530,6 +2544,95 @@ void force_high_power_mode(bool start_high_power_section) {
 }
 #endif //TMC2130
 
+void gcode_M105(uint8_t extruder)
+{
+#if defined(TEMP_0_PIN) && TEMP_0_PIN > -1
+    SERIAL_PROTOCOLPGM("T:");
+    SERIAL_PROTOCOL_F(degHotend(extruder),1);
+    SERIAL_PROTOCOLPGM(" /");
+    SERIAL_PROTOCOL_F(degTargetHotend(extruder),1);
+#if defined(TEMP_BED_PIN) && TEMP_BED_PIN > -1
+    SERIAL_PROTOCOLPGM(" B:");
+    SERIAL_PROTOCOL_F(degBed(),1);
+    SERIAL_PROTOCOLPGM(" /");
+    SERIAL_PROTOCOL_F(degTargetBed(),1);
+#endif //TEMP_BED_PIN
+    for (int8_t cur_extruder = 0; cur_extruder < EXTRUDERS; ++cur_extruder) {
+        SERIAL_PROTOCOLPGM(" T");
+        SERIAL_PROTOCOL(cur_extruder);
+        SERIAL_PROTOCOL(':');
+        SERIAL_PROTOCOL_F(degHotend(cur_extruder),1);
+        SERIAL_PROTOCOLPGM(" /");
+        SERIAL_PROTOCOL_F(degTargetHotend(cur_extruder),1);
+    }
+#else
+    SERIAL_ERROR_START;
+    SERIAL_ERRORLNRPGM(_i("No thermistors - no temperature"));////MSG_ERR_NO_THERMISTORS
+#endif
+
+    SERIAL_PROTOCOLPGM(" @:");
+#ifdef EXTRUDER_WATTS
+    SERIAL_PROTOCOL((EXTRUDER_WATTS * getHeaterPower(tmp_extruder))/127);
+    SERIAL_PROTOCOLPGM("W");
+#else
+    SERIAL_PROTOCOL(getHeaterPower(extruder));
+#endif
+
+    SERIAL_PROTOCOLPGM(" B@:");
+#ifdef BED_WATTS
+    SERIAL_PROTOCOL((BED_WATTS * getHeaterPower(-1))/127);
+    SERIAL_PROTOCOLPGM("W");
+#else
+    SERIAL_PROTOCOL(getHeaterPower(-1));
+#endif
+
+#ifdef PINDA_THERMISTOR
+    SERIAL_PROTOCOLPGM(" P:");
+    SERIAL_PROTOCOL_F(current_temperature_pinda,1);
+#endif //PINDA_THERMISTOR
+
+#ifdef AMBIENT_THERMISTOR
+    SERIAL_PROTOCOLPGM(" A:");
+    SERIAL_PROTOCOL_F(current_temperature_ambient,1);
+#endif //AMBIENT_THERMISTOR
+
+
+#ifdef SHOW_TEMP_ADC_VALUES
+    {
+        float raw = 0.0;
+#if defined(TEMP_BED_PIN) && TEMP_BED_PIN > -1
+        SERIAL_PROTOCOLPGM("    ADC B:");
+        SERIAL_PROTOCOL_F(degBed(),1);
+        SERIAL_PROTOCOLPGM("C->");
+        raw = rawBedTemp();
+        SERIAL_PROTOCOL_F(raw/OVERSAMPLENR,5);
+        SERIAL_PROTOCOLPGM(" Rb->");
+        SERIAL_PROTOCOL_F(100 * (1 + (PtA * (raw/OVERSAMPLENR)) + (PtB * sq((raw/OVERSAMPLENR)))), 5);
+        SERIAL_PROTOCOLPGM(" Rxb->");
+        SERIAL_PROTOCOL_F(raw, 5);
+#endif
+        for (int8_t cur_extruder = 0; cur_extruder < EXTRUDERS; ++cur_extruder) {
+            SERIAL_PROTOCOLPGM("  T");
+            SERIAL_PROTOCOL(cur_extruder);
+            SERIAL_PROTOCOLPGM(":");
+            SERIAL_PROTOCOL_F(degHotend(cur_extruder),1);
+            SERIAL_PROTOCOLPGM("C->");
+            raw = rawHotendTemp(cur_extruder);
+            SERIAL_PROTOCOL_F(raw/OVERSAMPLENR,5);
+            SERIAL_PROTOCOLPGM(" Rt");
+            SERIAL_PROTOCOL(cur_extruder);
+            SERIAL_PROTOCOLPGM("->");
+            SERIAL_PROTOCOL_F(100 * (1 + (PtA * (raw/OVERSAMPLENR)) + (PtB * sq((raw/OVERSAMPLENR)))), 5);
+            SERIAL_PROTOCOLPGM(" Rx");
+            SERIAL_PROTOCOL(cur_extruder);
+            SERIAL_PROTOCOLPGM("->");
+            SERIAL_PROTOCOL_F(raw, 5);
+        }
+    }
+#endif
+    SERIAL_PROTOCOLLN("");
+}
+
 #ifdef TMC2130
 static void gcode_G28(bool home_x_axis, long home_x_value, bool home_y_axis, long home_y_value, bool home_z_axis, long home_z_value, bool calib, bool without_mbl)
 #else
@@ -3293,37 +3396,24 @@ void gcode_M701()
  */
 static void gcode_PRUSA_SN()
 {
-    if (farm_mode) {
-        selectedSerialPort = 0;
-        putchar(';');
-        putchar('S');
-        int numbersRead = 0;
-        ShortTimer timeout;
-        timeout.start();
-
-        while (numbersRead < 19) {
-            while (MSerial.available() > 0) {
-                uint8_t serial_char = MSerial.read();
-                selectedSerialPort = 1;
-                putchar(serial_char);
-                numbersRead++;
-                selectedSerialPort = 0;
-            }
-            if (timeout.expired(100u)) break;
+    uint8_t selectedSerialPort_bak = selectedSerialPort;
+    char SN[20];
+    selectedSerialPort = 0;
+    SERIAL_ECHOLNRPGM(PSTR(";S"));
+    uint8_t numbersRead = 0;
+    ShortTimer timeout;
+    timeout.start();
+
+    while (numbersRead < (sizeof(SN) - 1)) {
+        if (MSerial.available() > 0) {
+            SN[numbersRead] = MSerial.read();
+            numbersRead++;
         }
-        selectedSerialPort = 1;
-        putchar('\n');
-#if 0
-        for (int b = 0; b < 3; b++) {
-            _tone(BEEPER, 110);
-            _delay(50);
-            _noTone(BEEPER);
-            _delay(50);
-        }
-#endif
-    } else {
-        puts_P(_N("Not in farm mode."));
+        if (timeout.expired(100u)) break;
     }
+    SN[numbersRead] = 0;
+    selectedSerialPort = selectedSerialPort_bak;
+    SERIAL_ECHOLN(SN);
 }
 //! Detection of faulty RAMBo 1.1b boards equipped with bigger capacitors
 //! at the TACH_1 pin, which causes bad detection of print fan speed.
@@ -3417,6 +3507,18 @@ static void gcode_G92()
     }
 }
 
+#ifdef EXTENDED_CAPABILITIES_REPORT
+
+static void cap_line(const char* name, bool ena = false) {
+    printf_P(PSTR("Cap:%S:%c\n"), name, (char)ena + '0');
+}
+
+static void extended_capabilities_report()
+{
+    cap_line(PSTR("AUTOREPORT_TEMP"), ENABLED(AUTO_REPORT_TEMPERATURES));
+    //@todo
+}
+#endif //EXTENDED_CAPABILITIES_REPORT
 
 #ifdef BACKLASH_X
 extern uint8_t st_backlash_x;
@@ -3510,6 +3612,7 @@ extern uint8_t st_backlash_y;
 //!@n M129 - EtoP Closed (BariCUDA EtoP = electricity to air pressure transducer by jmil)
 //!@n M140 - Set bed target temp
 //!@n M150 - Set BlinkM Color Output R: Red<0-255> U(!): Green<0-255> B: Blue<0-255> over i2c, G for green does not work.
+//!@n M155 - Automatically send temperatures
 //!@n M190 - Sxxx Wait for bed current temp to reach target temp. Waits only when heating
 //!          Rxxx Wait for bed current temp to reach target temp. Waits when heating and cooling
 //!@n M200 D<millimeters>- set filament diameter and set E axis units to cubic millimeters (use S0 to set back to millimeters).
@@ -3575,14 +3678,12 @@ There are reasons why some G Codes aren't in numerical order.
 void process_commands()
 {
 #ifdef FANCHECK
-    if(fan_check_error){
-        if(fan_check_error == EFCE_DETECTED){
-            fan_check_error = EFCE_REPORTED;
-            // SERIAL_PROTOCOLLNRPGM(MSG_OCTOPRINT_PAUSED);
-            lcd_pause_print();
-        } // otherwise it has already been reported, so just ignore further processing
-        return; //ignore usb stream. It is reenabled by selecting resume from the lcd.
-    }
+	if(fan_check_error == EFCE_DETECTED){
+		fan_check_error = EFCE_REPORTED;
+		// SERIAL_PROTOCOLLNRPGM(MSG_OCTOPRINT_PAUSED);
+		lcd_pause_print();
+		cmdqueue_serial_disabled = true;
+	}
 #endif
 
 	if (!buflen) return; //empty command
@@ -4288,6 +4389,14 @@ if(eSoundMode!=e_SOUND_MODE_SILENT)
       #endif //FWRETRACT
     
 
+    /*!
+	### G21 - Sets Units to Millimters <a href="https://reprap.org/wiki/G-code#G21:_Set_Units_to_Millimeters">G21: Set Units to Millimeters</a>
+	Units are in millimeters. Prusa doesn't support inches.
+    */
+    case 21: 
+      break; //Doing nothing. This is just to prevent serial UNKOWN warnings.
+    
+
     /*!
     ### G28 - Home all Axes one at a time <a href="https://reprap.org/wiki/G-code#G28:_Move_to_Origin_.28Home.29">G28: Move to Origin (Home)</a>
     Using `G28` without any parameters will perfom homing of all axes AND mesh bed leveling, while `G28 W` will just home all axes (no mesh bed leveling).
@@ -5865,28 +5974,30 @@ if(eSoundMode!=e_SOUND_MODE_SILENT)
     /*!
 	### M46 - Show the assigned IP address <a href="https://reprap.org/wiki/G-code#M46:_Show_the_assigned_IP_address">M46: Show the assigned IP address.</a>
     */
-    /*
-     case 46:
+    case 46:
     {
         // M46: Prusa3D: Show the assigned IP address.
-        uint8_t ip[4];
-        bool hasIP = card.ToshibaFlashAir_GetIP(ip);
-        if (hasIP) {
-            SERIAL_ECHOPGM("Toshiba FlashAir current IP: ");
-            SERIAL_ECHO(int(ip[0]));
-            SERIAL_ECHOPGM(".");
-            SERIAL_ECHO(int(ip[1]));
-            SERIAL_ECHOPGM(".");
-            SERIAL_ECHO(int(ip[2]));
-            SERIAL_ECHOPGM(".");
-            SERIAL_ECHO(int(ip[3]));
-            SERIAL_ECHOLNPGM("");
+        if (card.ToshibaFlashAir_isEnabled()) {
+            uint8_t ip[4];
+            bool hasIP = card.ToshibaFlashAir_GetIP(ip);
+            if (hasIP) {
+                // SERIAL_PROTOCOLPGM("Toshiba FlashAir current IP: ");
+                SERIAL_PROTOCOL(int(ip[0]));
+                SERIAL_PROTOCOLPGM(".");
+                SERIAL_PROTOCOL(int(ip[1]));
+                SERIAL_PROTOCOLPGM(".");
+                SERIAL_PROTOCOL(int(ip[2]));
+                SERIAL_PROTOCOLPGM(".");
+                SERIAL_PROTOCOL(int(ip[3]));
+                SERIAL_PROTOCOLPGM("\n");
+            } else {
+                SERIAL_PROTOCOLPGM("?Toshiba FlashAir GetIP failed\n");          
+            }
         } else {
-            SERIAL_ECHOLNPGM("Toshiba FlashAir GetIP failed");          
+            SERIAL_PROTOCOLPGM("n/a\n");          
         }
         break;
     }
-    */
 
     /*!
 	### M47 - Show end stops dialog on the display <a href="https://reprap.org/wiki/G-code#M47:_Show_end_stops_dialog_on_the_display">M47: Show end stops dialog on the display</a>
@@ -6285,96 +6396,42 @@ Sigma_Exit:
       uint8_t extruder;
       if(setTargetedHotend(105, extruder)){
         break;
-        }
-      #if defined(TEMP_0_PIN) && TEMP_0_PIN > -1
-        SERIAL_PROTOCOLPGM("ok T:");
-        SERIAL_PROTOCOL_F(degHotend(extruder),1);
-        SERIAL_PROTOCOLPGM(" /");
-        SERIAL_PROTOCOL_F(degTargetHotend(extruder),1);
-        #if defined(TEMP_BED_PIN) && TEMP_BED_PIN > -1
-          SERIAL_PROTOCOLPGM(" B:");
-          SERIAL_PROTOCOL_F(degBed(),1);
-          SERIAL_PROTOCOLPGM(" /");
-          SERIAL_PROTOCOL_F(degTargetBed(),1);
-        #endif //TEMP_BED_PIN
-        for (int8_t cur_extruder = 0; cur_extruder < EXTRUDERS; ++cur_extruder) {
-          SERIAL_PROTOCOLPGM(" T");
-          SERIAL_PROTOCOL(cur_extruder);
-          SERIAL_PROTOCOL(':');
-          SERIAL_PROTOCOL_F(degHotend(cur_extruder),1);
-          SERIAL_PROTOCOLPGM(" /");
-          SERIAL_PROTOCOL_F(degTargetHotend(cur_extruder),1);
-        }
-      #else
-        SERIAL_ERROR_START;
-        SERIAL_ERRORLNRPGM(_i("No thermistors - no temperature"));////MSG_ERR_NO_THERMISTORS
-      #endif
-
-        SERIAL_PROTOCOLPGM(" @:");
-      #ifdef EXTRUDER_WATTS
-        SERIAL_PROTOCOL((EXTRUDER_WATTS * getHeaterPower(tmp_extruder))/127);
-        SERIAL_PROTOCOLPGM("W");
-      #else
-        SERIAL_PROTOCOL(getHeaterPower(extruder));
-      #endif
-
-        SERIAL_PROTOCOLPGM(" B@:");
-      #ifdef BED_WATTS
-        SERIAL_PROTOCOL((BED_WATTS * getHeaterPower(-1))/127);
-        SERIAL_PROTOCOLPGM("W");
-      #else
-        SERIAL_PROTOCOL(getHeaterPower(-1));
-      #endif
-
-#ifdef PINDA_THERMISTOR
-		SERIAL_PROTOCOLPGM(" P:");
-		SERIAL_PROTOCOL_F(current_temperature_pinda,1);
-#endif //PINDA_THERMISTOR
-
-#ifdef AMBIENT_THERMISTOR
-		SERIAL_PROTOCOLPGM(" A:");
-		SERIAL_PROTOCOL_F(current_temperature_ambient,1);
-#endif //AMBIENT_THERMISTOR
-
-
-        #ifdef SHOW_TEMP_ADC_VALUES
-          {float raw = 0.0;
-
-          #if defined(TEMP_BED_PIN) && TEMP_BED_PIN > -1
-            SERIAL_PROTOCOLPGM("    ADC B:");
-            SERIAL_PROTOCOL_F(degBed(),1);
-            SERIAL_PROTOCOLPGM("C->");
-            raw = rawBedTemp();
-            SERIAL_PROTOCOL_F(raw/OVERSAMPLENR,5);
-            SERIAL_PROTOCOLPGM(" Rb->");
-            SERIAL_PROTOCOL_F(100 * (1 + (PtA * (raw/OVERSAMPLENR)) + (PtB * sq((raw/OVERSAMPLENR)))), 5);
-            SERIAL_PROTOCOLPGM(" Rxb->");
-            SERIAL_PROTOCOL_F(raw, 5);
-          #endif
-          for (int8_t cur_extruder = 0; cur_extruder < EXTRUDERS; ++cur_extruder) {
-            SERIAL_PROTOCOLPGM("  T");
-            SERIAL_PROTOCOL(cur_extruder);
-            SERIAL_PROTOCOLPGM(":");
-            SERIAL_PROTOCOL_F(degHotend(cur_extruder),1);
-            SERIAL_PROTOCOLPGM("C->");
-            raw = rawHotendTemp(cur_extruder);
-            SERIAL_PROTOCOL_F(raw/OVERSAMPLENR,5);
-            SERIAL_PROTOCOLPGM(" Rt");
-            SERIAL_PROTOCOL(cur_extruder);
-            SERIAL_PROTOCOLPGM("->");
-            SERIAL_PROTOCOL_F(100 * (1 + (PtA * (raw/OVERSAMPLENR)) + (PtB * sq((raw/OVERSAMPLENR)))), 5);
-            SERIAL_PROTOCOLPGM(" Rx");
-            SERIAL_PROTOCOL(cur_extruder);
-            SERIAL_PROTOCOLPGM("->");
-            SERIAL_PROTOCOL_F(raw, 5);
-          }}
-        #endif
-		SERIAL_PROTOCOLLN("");
-		KEEPALIVE_STATE(NOT_BUSY);
-      return;
+      }
+      
+      SERIAL_PROTOCOLPGM("ok ");
+      gcode_M105(extruder);
+      
+      cmdqueue_pop_front(); //prevent an ok after the command since this command uses an ok at the beginning.
+      
       break;
     }
 
+#ifdef AUTO_REPORT_TEMPERATURES
+    /*!
+	### M155 - Automatically send temperatures <a href="https://reprap.org/wiki/G-code#M155:_Automatically_send_temperatures">M155: Automatically send temperatures</a>
+	#### Usage
+	
+		M155 [ S ]
+	
+	#### Parameters
+	
+	- `S` - Set temperature autoreporting interval in seconds. 0 to disable. Maximum: 255
+	
+    */
+    case 155:
+    {
+        if (code_seen('S'))
+        {
+            auto_report_temp_period = code_value_uint8();
+            if (auto_report_temp_period != 0)
+                auto_report_temp_timer.start();
+            else
+                auto_report_temp_timer.stop();
+        }
+    }
+    break;
+#endif //AUTO_REPORT_TEMPERATURES
+
     /*!
 	### M109 - Wait for extruder temperature <a href="https://reprap.org/wiki/G-code#M109:_Set_Extruder_Temperature_and_Wait">M109: Set Extruder Temperature and Wait</a>
     #### Usage
@@ -6807,6 +6864,9 @@ Sigma_Exit:
           SERIAL_ECHOPGM(STRINGIFY(EXTRUDERS)); 
           SERIAL_ECHOPGM(" UUID:"); 
           SERIAL_ECHOLNPGM(MACHINE_UUID);
+#ifdef EXTENDED_CAPABILITIES_REPORT
+          extended_capabilities_report();
+#endif //EXTENDED_CAPABILITIES_REPORT
       }
       break;
 
@@ -7305,17 +7365,26 @@ Sigma_Exit:
     */
     case 220: // M220 S<factor in percent>- set speed factor override percentage
     {
-      if (code_seen('B')) //backup current speed factor
-      {
-        saved_feedmultiply_mm = feedmultiply;
-      }
-      if(code_seen('S'))
-      {		
-        feedmultiply = code_value() ;
-      }
-      if (code_seen('R')) { //restore previous feedmultiply
-        feedmultiply = saved_feedmultiply_mm;
-      }
+        bool codesWereSeen = false;
+        if (code_seen('B')) //backup current speed factor
+        {
+            saved_feedmultiply_mm = feedmultiply;
+            codesWereSeen = true;
+        }
+        if (code_seen('S'))
+        {
+            feedmultiply = code_value();
+            codesWereSeen = true;
+        }
+        if (code_seen('R')) //restore previous feedmultiply
+        {
+            feedmultiply = saved_feedmultiply_mm;
+            codesWereSeen = true;
+        }
+        if (!codesWereSeen)
+        {
+            printf_P(PSTR("%i%%\n"), feedmultiply);
+        }
     }
     break;
 
@@ -7331,23 +7400,26 @@ Sigma_Exit:
     */
     case 221: // M221 S<factor in percent>- set extrude factor override percentage
     {
-      if(code_seen('S'))
-      {
-        int tmp_code = code_value();
-        if (code_seen('T'))
+        if (code_seen('S'))
         {
-          uint8_t extruder;
-          if(setTargetedHotend(221, extruder)){
-            break;
-          }
-          extruder_multiply[extruder] = tmp_code;
+            int tmp_code = code_value();
+            if (code_seen('T'))
+            {
+                uint8_t extruder;
+                if (setTargetedHotend(221, extruder))
+                    break;
+                extruder_multiply[extruder] = tmp_code;
+            }
+            else
+            {
+                extrudemultiply = tmp_code ;
+            }
         }
         else
         {
-          extrudemultiply = tmp_code ;
+            printf_P(PSTR("%i%%\n"), extrudemultiply);
         }
-      }
-      calculate_extruder_multipliers();
+        calculate_extruder_multipliers();
     }
     break;
 
@@ -7921,6 +7993,7 @@ Sigma_Exit:
         if (!isPrintPaused)
         {
             st_synchronize();
+            ClearToSend(); //send OK even before the command finishes executing because we want to make sure it is not skipped because of cmdqueue_pop_front();
             cmdqueue_pop_front(); //trick because we want skip this command (M601) after restore
             lcd_pause_print();
         }
@@ -9135,8 +9208,8 @@ void FlushSerialRequestResend()
 // Execution of a command from a SD card will not be confirmed.
 void ClearToSend()
 {
-    previous_millis_cmd = _millis();
-	if ((CMDBUFFER_CURRENT_TYPE == CMDBUFFER_CURRENT_TYPE_USB) || (CMDBUFFER_CURRENT_TYPE == CMDBUFFER_CURRENT_TYPE_USB_WITH_LINENR)) 
+	previous_millis_cmd = _millis();
+	if (buflen && ((CMDBUFFER_CURRENT_TYPE == CMDBUFFER_CURRENT_TYPE_USB) || (CMDBUFFER_CURRENT_TYPE == CMDBUFFER_CURRENT_TYPE_USB_WITH_LINENR)))
 		SERIAL_PROTOCOLLNRPGM(MSG_OK);
 }
 
@@ -9501,7 +9574,7 @@ static uint16_t nFSCheckCount=0;
 		bInhibitFlag=bInhibitFlag||bMenuFSDetect; // Settings::HWsetup::FSdetect menu active
 #endif // IR_SENSOR_ANALOG
 #endif // IR_SENSOR
-		if ((mcode_in_progress != 600) && (eFilamentAction != FilamentAction::AutoLoad) && (!bInhibitFlag)) //M600 not in progress, preHeat @ autoLoad menu not active, Support::ExtruderInfo/SensorInfo menu not active
+		if ((mcode_in_progress != 600) && (eFilamentAction != FilamentAction::AutoLoad) && (!bInhibitFlag) && (menu_menu != lcd_move_e)) //M600 not in progress, preHeat @ autoLoad menu not active, Support::ExtruderInfo/SensorInfo menu not active
 		{
 			if (!moves_planned() && !IS_SD_PRINTING && !is_usb_printing && (lcd_commands_type != LcdCommands::Layer1Cal) && ! eeprom_read_byte((uint8_t*)EEPROM_WIZARD_ACTIVE))
 			{
@@ -11387,7 +11460,6 @@ void restore_print_from_ram_and_continue(float e_move)
 		//not sd printing nor usb printing
 	}
 
-	SERIAL_PROTOCOLLNRPGM(MSG_OK); //dummy response because of octoprint is waiting for this
 	lcd_setstatuspgm(_T(WELCOME_MSG));
     saved_printing_type = PRINTING_TYPE_NONE;
 	saved_printing = false;

+ 4 - 1
Firmware/Sd2Card.cpp

@@ -767,6 +767,9 @@ uint8_t Sd2Card::waitStartBlock(void) {
 
 // Toshiba FlashAir support, copied from 
 // https://flashair-developers.com/en/documents/tutorials/arduino/
+// However, the official website was closed in September 2019.
+// There is an archived website (written in Japanese).
+// https://flashair-developers.github.io/website/docs/tutorials/arduino/2.html
 
 //------------------------------------------------------------------------------
 /** Perform Extention Read. */
@@ -774,7 +777,7 @@ uint8_t Sd2Card::readExt(uint32_t arg, uint8_t* dst, uint16_t count) {
   uint16_t i;
 
   // send command and argument.
-  if (cardCommand(CMD48, arg)) {
+  if (cardCommand(CMD48, arg) && cardCommand(CMD17, arg)) { // CMD48 for W-03, CMD17 for W-04
     error(SD_CARD_ERROR_CMD48);
     goto fail;
   }

+ 4 - 4
Firmware/backlight.cpp

@@ -1,10 +1,10 @@
 //backlight.cpp
 
 #include "backlight.h"
+#include "macros.h"
 #include <avr/eeprom.h>
 #include <Arduino.h>
 #include "eeprom.h"
-#include "Marlin.h"
 #include "pins.h"
 #include "fastio.h"
 #include "Timer.h"
@@ -111,10 +111,10 @@ void backlight_init()
 
 #else //LCD_BL_PIN
 
-void force_bl_on(__attribute__((unused)) bool section_start) {}
+void force_bl_on(bool) {}
 void backlight_update() {}
 void backlight_init() {}
 void backlight_save() {}
-void backlight_wake(__attribute__((unused)) const uint8_t flashNo) {}
+void backlight_wake(const uint8_t) {}
 
-#endif //LCD_BL_PIN
+#endif //LCD_BL_PIN

+ 4 - 1
Firmware/cardreader.cpp

@@ -1,4 +1,5 @@
 #include "Marlin.h"
+#include "cmdqueue.h"
 #include "cardreader.h"
 #include "ultralcd.h"
 #include "stepper.h"
@@ -243,6 +244,8 @@ void CardReader::release()
 {
   sdprinting = false;
   cardOK = false;
+  SERIAL_ECHO_START;
+  SERIAL_ECHOLNRPGM(_n("SD card released"));////MSG_SD_CARD_RELEASED
 }
 
 void CardReader::startFileprint()
@@ -496,7 +499,7 @@ void CardReader::getStatus()
           SERIAL_PROTOCOLLNPGM("Print saved");
       }
       else {
-          SERIAL_PROTOCOLLN(longFilename);
+          SERIAL_PROTOCOLLN(LONGEST_FILENAME);
           SERIAL_PROTOCOLRPGM(_N("SD printing byte "));////MSG_SD_PRINTING_BYTE
           SERIAL_PROTOCOL(sdpos);
           SERIAL_PROTOCOL('/');

+ 17 - 7
Firmware/cmdqueue.cpp

@@ -18,6 +18,10 @@ int buflen = 0;
 // Therefore don't remove the command from the queue in the loop() function.
 bool cmdbuffer_front_already_processed = false;
 
+// Used for temporarely preventing accidental adding of Serial commands to the queue.
+// For now only check_file and the fancheck pause use this.
+bool cmdqueue_serial_disabled = false;
+
 int serial_count = 0;  //index of character read from serial line
 boolean comment_mode = false;
 char *strchr_pointer; // just a pointer to find chars in the command string like X, Y, Z, E, etc
@@ -91,14 +95,19 @@ bool cmdqueue_pop_front()
 
 void cmdqueue_reset()
 {
-    bufindr = 0;
-    bufindw = 0;
-    buflen = 0;
+	while (buflen)
+	{
+		// printf_P(PSTR("dumping: \"%s\" of type %hu\n"), cmdbuffer+bufindr+CMDHDRSIZE, CMDBUFFER_CURRENT_TYPE);
+		ClearToSend();
+		cmdqueue_pop_front();
+	}
+	bufindr = 0;
+	bufindw = 0;
 
 	//commands are removed from command queue after process_command() function is finished
 	//reseting command queue and enqueing new commands during some (usually long running) command processing would cause that new commands are immediately removed from queue (or damaged)
 	//this will ensure that all new commands which are enqueued after cmdqueue reset, will be always executed
-    cmdbuffer_front_already_processed = true; 
+	cmdbuffer_front_already_processed = true; 
 }
 
 // How long a string could be pushed to the front of the command queue?
@@ -390,7 +399,7 @@ void get_command()
 	}
 
   // start of serial line processing loop
-  while ((MYSERIAL.available() > 0 && !saved_printing) || (MYSERIAL.available() > 0 && isPrintPaused)) {  //is print is saved (crash detection or filament detection), dont process data from serial line
+  while (((MYSERIAL.available() > 0 && !saved_printing) || (MYSERIAL.available() > 0 && isPrintPaused)) && !cmdqueue_serial_disabled) {  //is print is saved (crash detection or filament detection), dont process data from serial line
 	
     char serial_char = MYSERIAL.read();
 /*    if (selectedSerialPort == 1)
@@ -582,8 +591,6 @@ void get_command()
        ((serial_char == '#' || serial_char == ':') && comment_mode == false) ||
        serial_count >= (MAX_CMD_SIZE - 1) || n==-1)
     {
-      if(card.eof()) break;
-
       if(serial_char=='#')
         stop_buffering=true;
 
@@ -631,6 +638,9 @@ void get_command()
 
       comment_mode = false; //for new command
       serial_count = 0; //clear buffer
+    
+      if(card.eof()) break;
+    
       // The following line will reserve buffer space if available.
       if (! cmdqueue_could_enqueue_back(MAX_CMD_SIZE-1, true))
           return;

+ 3 - 2
Firmware/cmdqueue.h

@@ -35,6 +35,7 @@ extern char cmdbuffer[BUFSIZE * (MAX_CMD_SIZE + 1) + CMDBUFFER_RESERVE_FRONT];
 extern size_t bufindr;
 extern int buflen;
 extern bool cmdbuffer_front_already_processed;
+extern bool cmdqueue_serial_disabled;
 
 // Type of a command, which is to be executed right now.
 #define CMDBUFFER_CURRENT_TYPE   (cmdbuffer[bufindr])
@@ -65,8 +66,8 @@ extern void cmdqueue_dump_to_serial_single_line(int nr, const char *p);
 extern void cmdqueue_dump_to_serial();
 #endif /* CMDBUFFER_DEBUG */
 extern bool cmd_buffer_empty();
-extern void enquecommand(const char *cmd, bool from_progmem);
-extern void enquecommand_front(const char *cmd, bool from_progmem);
+extern void enquecommand(const char *cmd, bool from_progmem = false);
+extern void enquecommand_front(const char *cmd, bool from_progmem = false);
 extern void repeatcommand_front();
 extern bool is_buffer_empty();
 extern void get_command();

+ 2 - 54
Firmware/eeprom.h

@@ -98,19 +98,9 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP
 | 0x0FF1h 4081		| uint32	| EEPROM_FILAMENTUSED					| ???			| 00 00 00 00h 0 __S/P__| Filament used in meters							| ??? 			| D3 Ax0ff1 C4
 | 0x0FEDh 4077		| uint32	| EEPROM_TOTALTIME						| ???			| 00 00 00 00h 0 __S/P__| Total print time									| ??? 			| D3 Ax0fed C4
 | 0x0FE5h 4069		| float		| EEPROM_BED_CALIBRATION_CENTER			| ???			| ff ff ff ffh			| ???											 	| ??? 			| D3 Ax0fe5 C8
-| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
 | 0x0FDDh 4061		| float		| EEPROM_BED_CALIBRATION_VEC_X			| ???			| ff ff ff ffh			| ???											 	| ??? 			| D3 Ax0fdd C8
-| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^	
 | 0x0FD5h 4053		| float		| EEPROM_BED_CALIBRATION_VEC_Y			| ???			| ff ff ff ffh			| ???											 	| ??? 			| D3 Ax0fd5 C8
-| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
 | 0x0FC5h 4037		| int16		| EEPROM_BED_CALIBRATION_Z_JITTER		| ???			| ff ffh 65535			| ???											 	| ??? 			| D3 Ax0fc5 C16
-| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^	
-| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
-| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
-| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
-| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
-| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
-| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
 | 0x0FC4h 4036		| bool		| EEPROM_FARM_MODE						| 00h 0			| ffh 255 		__P__	| Prusa farm mode: __off__							| G99 			| D3 Ax0fc4 C1
 | ^					| ^			| ^										| 01h 1			| ^						| Prusa farm mode: __on__							| G98			| ^
 | 0x0FC3h 4035		| free		| _EEPROM_FREE_NR1_						| ???			| ffh 255				| _Free EEPROM space_								| _free space_	| D3 Ax0fc3 C1
@@ -129,10 +119,6 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP
 | ^					| ^			| ^										| 01h 1			| ^						| Toshiba Air: __on__								| ^ 			| ^	
 | 0x0FBAh 4026		| uchar		| EEPROM_PRINT_FLAG						| ???			| ???					| _unsued_											| ??? 			| D3 Ax0fba C1
 | 0x0FB0h 4016		| int16		| EEPROM_PROBE_TEMP_SHIFT				| ???			| ???					| ???												| ??? 			| D3 Ax0fb0 C10
-| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
-| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
-| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
-| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
 | 0x0FAFh 4015		| bool		| EEPROM_TEMP_CAL_ACTIVE				| 00h 0			| 00h 0					| PINDA Temp cal.: __inactive__						| LCD menu		| D3 Ax0faf C1
 | ^					| ^			| ^										| ffh 255		| ^						| PINDA Temp cal.: __active__						| ^ 			| ^
 | 0x0FA7h 4007		| uint32	| EEPROM_BOWDEN_LENGTH					| ???			| ff 00 00 00h			| Bowden length										| ??? 			| D3 Ax0fae C8
@@ -143,16 +129,8 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP
 | ^					| ^			| ^										| 01h 1			| ^						| Power Panic flag: __active__						| ^ 			| ^
 | ^					| ^			| ^										| 02h 2			| ^						| Power Panic flag: __???__							| ^ 			| ^
 | 0x0F9Dh 3997		| float		| EEPROM_UVLO_CURRENT_POSITION			| ???			| ffh 255				| Power Panic position 								| ??? 			| D3 Ax0f9d C8
-| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
 | 0x0F95h 3989		| char		| EEPROM_FILENAME						| ???			| ffh 255				| Power Panic Filename 								| ??? 			| D3 Ax0f95 C8
-| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
-| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
-| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
-| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
-| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
-| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
-| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
-| 0x0F91h 39851		| uint32	| EEPROM_FILE_POSITION					| ???			| ff ff ff ffh			| Power Panic File Position							| ??? 			| D3 Ax0f91 C4
+| 0x0F91h 3985		| uint32	| EEPROM_FILE_POSITION					| ???			| ff ff ff ffh			| Power Panic File Position							| ??? 			| D3 Ax0f91 C4
 | 0x0F8Dh 3981		| float		| EEPROM_UVLO_CURRENT_POSITION_Z		| ???			| ff ff ff ffh			| Power Panic Z Position	 						| ^ 			| D3 Ax0f8d C4
 | 0x0F8Ch 3980		| ???		| EEPROM_UVLO_UNUSED_001				| ??? 			| ffh 255				| Power Panic _unused_								| ^ 			| D3 Ax0f8c C1
 | 0x0F8Bh 3979		| uint8		| EEPROM_UVLO_TARGET_BED				| ???			| ffh 255				| Power Panic Bed temperature						| ^ 			| D3 Ax0f8b C1
@@ -161,14 +139,6 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP
 | 0x0F87h 3975		| uint8		| EEPROM_FAN_CHECK_ENABLED				| 00h 0			| ???					| Fan Check __disabled__							| LCD menu		| D3 Ax0f87 C1
 | ^					| ^			| ^										| 01h 1			| ffh 255				| Fan Check __enabled__ 							| ^ 			| ^
 | 0x0F75h 3957		| uint16	| EEPROM_UVLO_MESH_BED_LEVELING			| ???			| ff ffh 65535			| Power Panic Mesh Bed Leveling						| ???			| D3 Ax0f75 C18 
-| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
-| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
-| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
-| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
-| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
-| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
-| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
-| ^					| ^			| ^										| ^				| ^						| ^													| ^ 			| ^
 | 0x0F73h 3955		| uint16	| EEPROM_UVLO_Z_MICROSTEPS				| ???			| ff ffh 65535			| Power Panic Z microsteps							| ???			| D3 Ax0f73 C2 
 | 0x0F72h 3954		| uint8		| EEPROM_UVLO_E_ABS						| ???			| ffh 255				| Power Panic ??? position							| ???			| D3 Ax0f72 C1
 | 0x0F6Eh 3950		| foat		| EEPROM_UVLO_CURRENT_POSITION_E		| ???			| ff ff ff ffh			| Power Panic E position							| ???			| D3 Ax0f6e C4
@@ -203,7 +173,7 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP
 | 0x0F01h 3841		| uint16	| EEPROM_FERROR_COUNT_TOT				| 0000-fffe		| ff ffh		__S/P__	| Total filament sensor errors 						| ???			| D3 Ax0f01 C2
 | 0x0EFFh 3839		| uint16	| EEPROM_POWER_COUNT_TOT				| 0000-fffe		| ff ffh		__S/P__	| Total power failures		  						| ???			| D3 Ax0eff C2
 | 0x0EFEh 3838		| uint8		| EEPROM_TMC2130_HOME_X_ORIGIN			| ???			| ffh 255				| ???						  						| ???			| D3 Ax0efe C1
-| 0x0EFDh 3837		| uint8		| EEPROM	MC2130_HOME_X_BSTEPS			| ???			| ffh 255			| ???						  						| ???			| D3 Ax0efd C1
+| 0x0EFDh 3837		| uint8		| EEPROM	MC2130_HOME_X_BSTEPS		| ???			| ffh 255		    	| ???						  						| ???			| D3 Ax0efd C1
 | 0x0EFCh 3836		| uint8		| EEPROM_TMC2130_HOME_X_FSTEPS			| ???			| ffh 255				| ???						  						| ???			| D3 Ax0efc C1
 | 0x0EFBh 3835		| uint8		| EEPROM_TMC2130_HOME_Y_ORIGIN			| ???			| ffh 255				| ???						  						| ???			| D3 Ax0efb C1
 | 0x0EFAh 3834		| uint8		| EEPROM_TMC2130_HOME_Y_BSTEPS			| ???			| ffh 255				| ???						  						| ???			| D3 Ax0efa C1
@@ -257,28 +227,6 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP
 | ^					| ^			| ^										| 01h 1			| ^						| MMU2/s cutter: __enabled__						| ^				| ^
 | ^					| ^			| ^										| 02h 2			| ^						| MMU2/s cutter: __always__							| ^				| ^
 | 0x0DAE 3502		| uint16	| EEPROM_UVLO_MESH_BED_LEVELING_FULL	| ???			| ff ffh 65535			| Power panic Mesh bed leveling points 				| ???			| D3 Ax0dae C288
-| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
-| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
-| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
-| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
-| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
-| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
-| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
-| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
-| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
-| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
-| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
-| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
-| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
-| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
-| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
-| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
-| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
-| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
-| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
-| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
-| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
-| ^					| ^			| ^										| ???			| ^						| ^													| ^				| ^
 | 0x0DAD 3501		| uint8		| EEPROM_MBL_TYPE						| ???			| ffh 255				| Mesh bed leveling precision 		_unused atm_	| ???			| D3 Ax0dad C1
 | 0x0DAC 3500		| bool		| EEPROM_MBL_MAGNET_ELIMINATION			| 01h 1			| ffh 255				| Mesh bed leveling does: __ignores__ magnets		| LCD menu		| D3 Ax0dac C1
 | ^					| ^			| ^										| 00h 0			| ^						| Mesh bed leveling does: __NOT ignores__ magnets	| ^				| ^

+ 11 - 19
Firmware/fastio.h

@@ -7,15 +7,7 @@
 #define	_FASTIO_ARDUINO_H
 
 #include <avr/io.h>
-
-/*
-  utility functions
-*/
-
-#ifndef MASK
-/// MASKING- returns \f$2^PIN\f$
-#define MASK(PIN)  (1 << PIN)
-#endif
+#include "macros.h"
 
 /*
   magic I/O routines
@@ -23,20 +15,20 @@
 */
 
 /// Read a pin
-#define _READ(IO) ((bool)(DIO ## IO ## _RPORT & MASK(DIO ## IO ## _PIN)))
+#define _READ(IO) ((bool)(DIO ## IO ## _RPORT & _BV(DIO ## IO ## _PIN)))
 /// write to a pin
 // On some boards pins > 0x100 are used. These are not converted to atomic actions. An critical section is needed.
 
-#define _WRITE_NC(IO, v)  do { if (v) {DIO ##  IO ## _WPORT |= MASK(DIO ## IO ## _PIN); } else {DIO ##  IO ## _WPORT &= ~MASK(DIO ## IO ## _PIN); }; } while (0)
+#define _WRITE_NC(IO, v)  do { if (v) {DIO ##  IO ## _WPORT |= _BV(DIO ## IO ## _PIN); } else {DIO ##  IO ## _WPORT &= ~_BV(DIO ## IO ## _PIN); }; } while (0)
 
 #define _WRITE_C(IO, v)   do { if (v) { \
                                          CRITICAL_SECTION_START; \
-                                         {DIO ##  IO ## _WPORT |= MASK(DIO ## IO ## _PIN); }\
+                                         {DIO ##  IO ## _WPORT |= _BV(DIO ## IO ## _PIN); }\
                                          CRITICAL_SECTION_END; \
                                        }\
                                        else {\
                                          CRITICAL_SECTION_START; \
-                                         {DIO ##  IO ## _WPORT &= ~MASK(DIO ## IO ## _PIN); }\
+                                         {DIO ##  IO ## _WPORT &= ~_BV(DIO ## IO ## _PIN); }\
                                          CRITICAL_SECTION_END; \
                                        }\
                                      }\
@@ -45,20 +37,20 @@
 #define _WRITE(IO, v)  do {  if (&(DIO ##  IO ## _RPORT) >= (uint8_t *)0x100) {_WRITE_C(IO, v); } else {_WRITE_NC(IO, v); }; } while (0)
 
 /// toggle a pin
-#define _TOGGLE(IO)  do {DIO ##  IO ## _RPORT = MASK(DIO ## IO ## _PIN); } while (0)
+#define _TOGGLE(IO)  do {DIO ##  IO ## _RPORT = _BV(DIO ## IO ## _PIN); } while (0)
 
 /// set pin as input
-#define	_SET_INPUT(IO) do {DIO ##  IO ## _DDR &= ~MASK(DIO ## IO ## _PIN); } while (0)
+#define	_SET_INPUT(IO) do {DIO ##  IO ## _DDR &= ~_BV(DIO ## IO ## _PIN); } while (0)
 /// set pin as output
-#define	_SET_OUTPUT(IO) do {DIO ##  IO ## _DDR |=  MASK(DIO ## IO ## _PIN); } while (0)
+#define	_SET_OUTPUT(IO) do {DIO ##  IO ## _DDR |=  _BV(DIO ## IO ## _PIN); } while (0)
 
 /// check if pin is an input
-#define	_GET_INPUT(IO)  ((DIO ## IO ## _DDR & MASK(DIO ## IO ## _PIN)) == 0)
+#define	_GET_INPUT(IO)  ((DIO ## IO ## _DDR & _BV(DIO ## IO ## _PIN)) == 0)
 /// check if pin is an output
-#define	_GET_OUTPUT(IO)  ((DIO ## IO ## _DDR & MASK(DIO ## IO ## _PIN)) != 0)
+#define	_GET_OUTPUT(IO)  ((DIO ## IO ## _DDR & _BV(DIO ## IO ## _PIN)) != 0)
 
 /// check if pin is an timer
-#define	_GET_TIMER(IO)  ((DIO ## IO ## _PWM)
+#define	_GET_TIMER(IO)  (DIO ## IO ## _PWM)
 
 //  why double up on these macros? see http://gcc.gnu.org/onlinedocs/cpp/Stringification.html
 

+ 1 - 0
Firmware/first_lay_cal.cpp

@@ -7,6 +7,7 @@
 #include "Configuration_prusa.h"
 #include "language.h"
 #include "Marlin.h"
+#include "cmdqueue.h"
 #include "mmu.h"
 #include <avr/pgmspace.h>
 

+ 4 - 6
Firmware/fsensor.cpp

@@ -6,7 +6,6 @@
 #include <avr/pgmspace.h>
 #include "pat9125.h"
 #include "stepper.h"
-#include "io_atmega2560.h"
 #include "cmdqueue.h"
 #include "ultralcd.h"
 #include "mmu.h"
@@ -317,7 +316,7 @@ void fsensor_autoload_check_start(void)
 		printf_P(ERRMSG_PAT9125_NOT_RESP, 3);
 		return;
 	}
-	puts_P(_N("fsensor_autoload_check_start - autoload ENABLED\n"));
+	puts_P(_N("fsensor_autoload_check_start - autoload ENABLED"));
 	fsensor_autoload_y = pat9125_y; //save current y value
 	fsensor_autoload_c = 0; //reset number of changes counter
 	fsensor_autoload_sum = 0;
@@ -335,7 +334,7 @@ void fsensor_autoload_check_stop(void)
 	if (!fsensor_autoload_enabled) return;
 //	puts_P(_N("fsensor_autoload_check_stop 2\n"));
 	if (!fsensor_watch_autoload) return;
-	puts_P(_N("fsensor_autoload_check_stop - autoload DISABLED\n"));
+	puts_P(_N("fsensor_autoload_check_stop - autoload DISABLED"));
 	fsensor_autoload_sum = 0;
 	fsensor_watch_autoload = false;
 	fsensor_watch_runout = true;
@@ -608,9 +607,8 @@ void fsensor_st_block_chunk(int cnt)
 	if (!fsensor_enabled) return;
 	fsensor_st_cnt += cnt;
 
-    // !!! bit toggling (PINxn <- 1) (for PinChangeInterrupt) does not work for some MCU pins
-    if (PIN_GET(FSENSOR_INT_PIN)) {PIN_VAL(FSENSOR_INT_PIN, LOW);}
-    else {PIN_VAL(FSENSOR_INT_PIN, HIGH);}
+	// !!! bit toggling (PINxn <- 1) (for PinChangeInterrupt) does not work for some MCU pins
+	WRITE(FSENSOR_INT_PIN, !READ(FSENSOR_INT_PIN));
 }
 #endif //PAT9125
 

+ 0 - 1
Firmware/heatbed_pwm.cpp

@@ -1,6 +1,5 @@
 #include <avr/io.h>
 #include <avr/interrupt.h>
-#include "io_atmega2560.h"
 
 // All this is about silencing the heat bed, as it behaves like a loudspeaker.
 // Basically, we want the PWM heating switched at 30Hz (or so) which is a well ballanced

+ 0 - 374
Firmware/io_atmega2560.h

@@ -1,374 +0,0 @@
-//io_atmega2560.h
-#ifndef _IO_ATMEGA2560
-#define _IO_ATMEGA2560
-
-
-#define __PIN_P0  PINE
-#define __PIN_P1  PINE
-#define __PIN_P2  PINE
-#define __PIN_P3  PINE
-#define __PIN_P4  PING
-#define __PIN_P5  PINE
-#define __PIN_P6  PINH
-#define __PIN_P7  PINH
-#define __PIN_P8  PINH
-#define __PIN_P9  PINH
-#define __PIN_P10 PINB
-#define __PIN_P11 PINB
-#define __PIN_P12 PINB
-#define __PIN_P13 PINB
-#define __PIN_P14 PINJ
-#define __PIN_P15 PINJ
-#define __PIN_P16 PINH
-#define __PIN_P17 PINH
-#define __PIN_P18 PIND
-#define __PIN_P19 PIND
-#define __PIN_P20 PIND
-#define __PIN_P21 PIND
-#define __PIN_P22 PINA
-#define __PIN_P23 PINA
-#define __PIN_P24 PINA
-#define __PIN_P25 PINA
-#define __PIN_P26 PINA
-#define __PIN_P27 PINA
-#define __PIN_P28 PINA
-#define __PIN_P29 PINA
-#define __PIN_P30 PINC
-#define __PIN_P31 PINC
-#define __PIN_P32 PINC
-#define __PIN_P33 PINC
-#define __PIN_P34 PINC
-#define __PIN_P35 PINC
-#define __PIN_P36 PINC
-#define __PIN_P37 PINC
-#define __PIN_P38 PIND
-#define __PIN_P39 PING
-#define __PIN_P40 PING
-#define __PIN_P41 PING
-#define __PIN_P42 PINL
-#define __PIN_P43 PINL
-#define __PIN_P44 PINL
-#define __PIN_P45 PINL
-#define __PIN_P46 PINL
-#define __PIN_P47 PINL
-#define __PIN_P48 PINL
-#define __PIN_P49 PINL
-#define __PIN_P50 PINB
-#define __PIN_P51 PINB
-#define __PIN_P52 PINB
-#define __PIN_P53 PINB
-#define __PIN_P54 PINF
-#define __PIN_P55 PINF
-#define __PIN_P56 PINF
-#define __PIN_P57 PINF
-#define __PIN_P58 PINF
-#define __PIN_P59 PINF
-#define __PIN_P60 PINF
-#define __PIN_P61 PINF
-#define __PIN_P62 PINK
-#define __PIN_P63 PINK
-#define __PIN_P64 PINK
-#define __PIN_P65 PINK
-#define __PIN_P66 PINK
-#define __PIN_P67 PINK
-#define __PIN_P68 PINK
-#define __PIN_P69 PINK
-#define __PIN_P70 PING
-#define __PIN_P71 PING
-#define __PIN_P72 PINJ
-#define __PIN_P73 PINJ
-#define __PIN_P74 PINJ
-#define __PIN_P75 PINJ
-#define __PIN_P76 PINJ
-#define __PIN_P77 PINJ
-#define __PIN_P78 PINE
-#define __PIN_P79 PINE
-#define __PIN_P80 PINE
-#define __PIN_P81 PIND
-#define __PIN_P82 PIND
-#define __PIN_P83 PIND
-#define __PIN_P84 PINH
-#define __PIN_P85 PINH
-
-#define __PORT_P0  PORTE
-#define __PORT_P1  PORTE
-#define __PORT_P2  PORTE
-#define __PORT_P3  PORTE
-#define __PORT_P4  PORTG
-#define __PORT_P5  PORTE
-#define __PORT_P6  PORTH
-#define __PORT_P7  PORTH
-#define __PORT_P8  PORTH
-#define __PORT_P9  PORTH
-#define __PORT_P10 PORTB
-#define __PORT_P11 PORTB
-#define __PORT_P12 PORTB
-#define __PORT_P13 PORTB
-#define __PORT_P14 PORTJ
-#define __PORT_P15 PORTJ
-#define __PORT_P16 PORTH
-#define __PORT_P17 PORTH
-#define __PORT_P18 PORTD
-#define __PORT_P19 PORTD
-#define __PORT_P20 PORTD
-#define __PORT_P21 PORTD
-#define __PORT_P22 PORTA
-#define __PORT_P23 PORTA
-#define __PORT_P24 PORTA
-#define __PORT_P25 PORTA
-#define __PORT_P26 PORTA
-#define __PORT_P27 PORTA
-#define __PORT_P28 PORTA
-#define __PORT_P29 PORTA
-#define __PORT_P30 PORTC
-#define __PORT_P31 PORTC
-#define __PORT_P32 PORTC
-#define __PORT_P33 PORTC
-#define __PORT_P34 PORTC
-#define __PORT_P35 PORTC
-#define __PORT_P36 PORTC
-#define __PORT_P37 PORTC
-#define __PORT_P38 PORTD
-#define __PORT_P39 PORTG
-#define __PORT_P40 PORTG
-#define __PORT_P41 PORTG
-#define __PORT_P42 PORTL
-#define __PORT_P43 PORTL
-#define __PORT_P44 PORTL
-#define __PORT_P45 PORTL
-#define __PORT_P46 PORTL
-#define __PORT_P47 PORTL
-#define __PORT_P48 PORTL
-#define __PORT_P49 PORTL
-#define __PORT_P50 PORTB
-#define __PORT_P51 PORTB
-#define __PORT_P52 PORTB
-#define __PORT_P53 PORTB
-#define __PORT_P54 PORTF
-#define __PORT_P55 PORTF
-#define __PORT_P56 PORTF
-#define __PORT_P57 PORTF
-#define __PORT_P58 PORTF
-#define __PORT_P59 PORTF
-#define __PORT_P60 PORTF
-#define __PORT_P61 PORTF
-#define __PORT_P62 PORTK
-#define __PORT_P63 PORTK
-#define __PORT_P64 PORTK
-#define __PORT_P65 PORTK
-#define __PORT_P66 PORTK
-#define __PORT_P67 PORTK
-#define __PORT_P68 PORTK
-#define __PORT_P69 PORTK
-#define __PORT_P70 PORTG
-#define __PORT_P71 PORTG
-#define __PORT_P72 PORTJ
-#define __PORT_P73 PORTJ
-#define __PORT_P74 PORTJ
-#define __PORT_P75 PORTJ
-#define __PORT_P76 PORTJ
-#define __PORT_P77 PORTJ
-#define __PORT_P78 PORTE
-#define __PORT_P79 PORTE
-#define __PORT_P80 PORTE
-#define __PORT_P81 PORTD
-#define __PORT_P82 PORTD
-#define __PORT_P83 PORTD
-#define __PORT_P84 PORTH
-#define __PORT_P85 PORTH
-
-#define __DDR_P0  DDRE
-#define __DDR_P1  DDRE
-#define __DDR_P2  DDRE
-#define __DDR_P3  DDRE
-#define __DDR_P4  DDRG
-#define __DDR_P5  DDRE
-#define __DDR_P6  DDRH
-#define __DDR_P7  DDRH
-#define __DDR_P8  DDRH
-#define __DDR_P9  DDRH
-#define __DDR_P10 DDRB
-#define __DDR_P11 DDRB
-#define __DDR_P12 DDRB
-#define __DDR_P13 DDRB
-#define __DDR_P14 DDRJ
-#define __DDR_P15 DDRJ
-#define __DDR_P16 DDRH
-#define __DDR_P17 DDRH
-#define __DDR_P18 DDRD
-#define __DDR_P19 DDRD
-#define __DDR_P20 DDRD
-#define __DDR_P21 DDRD
-#define __DDR_P22 DDRA
-#define __DDR_P23 DDRA
-#define __DDR_P24 DDRA
-#define __DDR_P25 DDRA
-#define __DDR_P26 DDRA
-#define __DDR_P27 DDRA
-#define __DDR_P28 DDRA
-#define __DDR_P29 DDRA
-#define __DDR_P30 DDRC
-#define __DDR_P31 DDRC
-#define __DDR_P32 DDRC
-#define __DDR_P33 DDRC
-#define __DDR_P34 DDRC
-#define __DDR_P35 DDRC
-#define __DDR_P36 DDRC
-#define __DDR_P37 DDRC
-#define __DDR_P38 DDRD
-#define __DDR_P39 DDRG
-#define __DDR_P40 DDRG
-#define __DDR_P41 DDRG
-#define __DDR_P42 DDRL
-#define __DDR_P43 DDRL
-#define __DDR_P44 DDRL
-#define __DDR_P45 DDRL
-#define __DDR_P46 DDRL
-#define __DDR_P47 DDRL
-#define __DDR_P48 DDRL
-#define __DDR_P49 DDRL
-#define __DDR_P50 DDRB
-#define __DDR_P51 DDRB
-#define __DDR_P52 DDRB
-#define __DDR_P53 DDRB
-#define __DDR_P54 DDRF
-#define __DDR_P55 DDRF
-#define __DDR_P56 DDRF
-#define __DDR_P57 DDRF
-#define __DDR_P58 DDRF
-#define __DDR_P59 DDRF
-#define __DDR_P60 DDRF
-#define __DDR_P61 DDRF
-#define __DDR_P62 DDRK
-#define __DDR_P63 DDRK
-#define __DDR_P64 DDRK
-#define __DDR_P65 DDRK
-#define __DDR_P66 DDRK
-#define __DDR_P67 DDRK
-#define __DDR_P68 DDRK
-#define __DDR_P69 DDRK
-#define __DDR_P70 DDRG
-#define __DDR_P71 DDRG
-#define __DDR_P72 DDRJ
-#define __DDR_P73 DDRJ
-#define __DDR_P74 DDRJ
-#define __DDR_P75 DDRJ
-#define __DDR_P76 DDRJ
-#define __DDR_P77 DDRJ
-#define __DDR_P78 DDRE
-#define __DDR_P79 DDRE
-#define __DDR_P80 DDRE
-#define __DDR_P81 DDRD
-#define __DDR_P82 DDRD
-#define __DDR_P83 DDRD
-#define __DDR_P84 DDRH
-#define __DDR_P85 DDRH
-
-#define __BIT_P0  0
-#define __BIT_P1  1
-#define __BIT_P2  4
-#define __BIT_P3  5
-#define __BIT_P4  5
-#define __BIT_P5  3
-#define __BIT_P6  3
-#define __BIT_P7  4
-#define __BIT_P8  5
-#define __BIT_P9  6
-#define __BIT_P10 4
-#define __BIT_P11 5
-#define __BIT_P12 6
-#define __BIT_P13 7
-#define __BIT_P14 1
-#define __BIT_P15 0
-#define __BIT_P16 0
-#define __BIT_P17 1
-#define __BIT_P18 3
-#define __BIT_P19 2
-#define __BIT_P20 1
-#define __BIT_P21 0
-#define __BIT_P22 0
-#define __BIT_P23 1
-#define __BIT_P24 2
-#define __BIT_P25 3
-#define __BIT_P26 4
-#define __BIT_P27 5
-#define __BIT_P28 6
-#define __BIT_P29 7
-#define __BIT_P30 7
-#define __BIT_P31 6
-#define __BIT_P32 5
-#define __BIT_P33 4
-#define __BIT_P34 3
-#define __BIT_P35 2
-#define __BIT_P36 1
-#define __BIT_P37 0
-#define __BIT_P38 7
-#define __BIT_P39 2
-#define __BIT_P40 1
-#define __BIT_P41 0
-#define __BIT_P42 7
-#define __BIT_P43 6
-#define __BIT_P44 5
-#define __BIT_P45 4
-#define __BIT_P46 3
-#define __BIT_P47 2
-#define __BIT_P48 1
-#define __BIT_P49 0
-#define __BIT_P50 3
-#define __BIT_P51 2
-#define __BIT_P52 1
-#define __BIT_P53 0
-#define __BIT_P54 0
-#define __BIT_P55 1
-#define __BIT_P56 2
-#define __BIT_P57 3
-#define __BIT_P58 4
-#define __BIT_P59 5
-#define __BIT_P60 6
-#define __BIT_P61 7
-#define __BIT_P62 0
-#define __BIT_P63 1
-#define __BIT_P64 2
-#define __BIT_P65 3
-#define __BIT_P66 4
-#define __BIT_P67 5
-#define __BIT_P68 6
-#define __BIT_P69 7
-#define __BIT_P70 4
-#define __BIT_P71 3
-#define __BIT_P72 2
-#define __BIT_P73 3
-#define __BIT_P74 7
-#define __BIT_P75 4
-#define __BIT_P76 5
-#define __BIT_P77 6
-#define __BIT_P78 2
-#define __BIT_P79 6
-#define __BIT_P80 7
-#define __BIT_P81 4
-#define __BIT_P82 5
-#define __BIT_P83 6
-#define __BIT_P84 2
-#define __BIT_P85 7
-
-#define __BIT(pin) __BIT_P##pin
-#define __MSK(pin) (1 << __BIT(pin))
-
-#define __PIN(pin) __PIN_P##pin
-#define __PORT(pin) __PORT_P##pin
-#define __DDR(pin) __DDR_P##pin
-
-#define PIN(pin) __PIN(pin)
-#define PORT(pin) __PORT(pin)
-#define DDR(pin) __DDR(pin)
-
-#define PIN_INP(pin) DDR(pin) &= ~__MSK(pin)
-#define PIN_OUT(pin) DDR(pin) |= __MSK(pin)
-#define PIN_CLR(pin) PORT(pin) &= ~__MSK(pin)
-#define PIN_SET(pin) PORT(pin) |= __MSK(pin)
-#define PIN_VAL(pin, val) if (val) PIN_SET(pin); else PIN_CLR(pin);
-#define PIN_GET(pin) (PIN(pin) & __MSK(pin))
-#define PIN_INQ(pin) (PORT(pin) & __MSK(pin))
-
-
-#endif //_IO_ATMEGA2560

+ 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(__attribute__((unused)) uint8_t lang) { return 0; }
+uint8_t lang_select(_UNUSED uint8_t lang) { return 0; }
 uint8_t lang_get_count() { return 1; }
-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"); }
+uint16_t lang_get_code(_UNUSED uint8_t lang) { return LANG_CODE_EN; }
+const char* lang_get_name_by_code(_UNUSED uint16_t code) { return _n("English"); }
 void lang_reset(void) { }
 uint8_t lang_is_selected(void) { return 1; }
 

+ 1 - 3
Firmware/language.h

@@ -5,6 +5,7 @@
 
 
 #include "config.h"
+#include "macros.h"
 #include <inttypes.h>
 #ifdef DEBUG_SEC_LANG
     #include <stdio.h>
@@ -22,9 +23,6 @@
 
 #define MSG_FW_VERSION                   "Firmware"
 
-#define STRINGIFY_(n) #n
-#define STRINGIFY(n) STRINGIFY_(n)
-
 #if (LANG_MODE == 0) //primary language only
 #define PROGMEM_I2 __attribute__((section(".progmem0")))
 #define PROGMEM_I1 __attribute__((section(".progmem1")))

+ 90 - 0
Firmware/macros.h

@@ -0,0 +1,90 @@
+#ifndef MACROS_H
+#define MACROS_H
+
+#include <avr/interrupt.h> //for cli() and sei()
+
+#define  FORCE_INLINE __attribute__((always_inline)) inline
+#define _UNUSED __attribute__((unused))
+
+#ifndef CRITICAL_SECTION_START
+  #define CRITICAL_SECTION_START  unsigned char _sreg = SREG; cli();
+  #define CRITICAL_SECTION_END    SREG = _sreg;
+#endif //CRITICAL_SECTION_START
+
+// Macros to make a string from a macro
+#define STRINGIFY_(M) #M
+#define STRINGIFY(M) STRINGIFY_(M)
+
+// Macros for bit masks
+#undef _BV
+#define _BV(n) (1<<(n))
+#define TEST(n,b) (!!((n)&_BV(b)))
+#define SET_BIT_TO(N,B,TF) do{ if (TF) SBI(N,B); else CBI(N,B); }while(0)
+
+#ifndef SBI
+  #define SBI(A,B) (A |= (1 << (B)))
+#endif
+
+#ifndef CBI
+  #define CBI(A,B) (A &= ~(1 << (B)))
+#endif
+
+#define TBI(N,B) (N ^= _BV(B))
+
+
+// Macros to chain up to 12 conditions
+#define _DO_1(W,C,A)       (_##W##_1(A))
+#define _DO_2(W,C,A,B)     (_##W##_1(A) C _##W##_1(B))
+#define _DO_3(W,C,A,V...)  (_##W##_1(A) C _DO_2(W,C,V))
+#define _DO_4(W,C,A,V...)  (_##W##_1(A) C _DO_3(W,C,V))
+#define _DO_5(W,C,A,V...)  (_##W##_1(A) C _DO_4(W,C,V))
+#define _DO_6(W,C,A,V...)  (_##W##_1(A) C _DO_5(W,C,V))
+#define _DO_7(W,C,A,V...)  (_##W##_1(A) C _DO_6(W,C,V))
+#define _DO_8(W,C,A,V...)  (_##W##_1(A) C _DO_7(W,C,V))
+#define _DO_9(W,C,A,V...)  (_##W##_1(A) C _DO_8(W,C,V))
+#define _DO_10(W,C,A,V...) (_##W##_1(A) C _DO_9(W,C,V))
+#define _DO_11(W,C,A,V...) (_##W##_1(A) C _DO_10(W,C,V))
+#define _DO_12(W,C,A,V...) (_##W##_1(A) C _DO_11(W,C,V))
+#define __DO_N(W,C,N,V...) _DO_##N(W,C,V)
+#define _DO_N(W,C,N,V...)  __DO_N(W,C,N,V)
+#define DO(W,C,V...)       _DO_N(W,C,NUM_ARGS(V),V)
+
+// Macros to support option testing
+#define _CAT(a,V...) a##V
+#define CAT(a,V...) _CAT(a,V)
+
+#define _ISENA_     ~,1
+#define _ISENA_1    ~,1
+#define _ISENA_0x1  ~,1
+#define _ISENA_true ~,1
+#define _ISENA(V...)        IS_PROBE(V)
+
+#define _ENA_1(O)           _ISENA(CAT(_IS,CAT(ENA_, O)))
+#define _DIS_1(O)           NOT(_ENA_1(O))
+#define ENABLED(V...)       DO(ENA,&&,V)
+#define DISABLED(V...)      DO(DIS,&&,V)
+
+#define TERN(O,A,B)         _TERN(_ENA_1(O),B,A)    // OPTION converted to '0' or '1'
+#define TERN0(O,A)          _TERN(_ENA_1(O),0,A)    // OPTION converted to A or '0'
+#define TERN1(O,A)          _TERN(_ENA_1(O),1,A)    // OPTION converted to A or '1'
+#define TERN_(O,A)          _TERN(_ENA_1(O),,A)     // OPTION converted to A or '<nul>'
+#define _TERN(E,V...)       __TERN(_CAT(T_,E),V)    // Prepend 'T_' to get 'T_0' or 'T_1'
+#define __TERN(T,V...)      ___TERN(_CAT(_NO,T),V)  // Prepend '_NO' to get '_NOT_0' or '_NOT_1'
+#define ___TERN(P,V...)     THIRD(P,V)              // If first argument has a comma, A. Else B.
+
+
+// Use NUM_ARGS(__VA_ARGS__) to get the number of variadic arguments
+#define _NUM_ARGS(_,Z,Y,X,W,V,U,T,S,R,Q,P,O,N,M,L,K,J,I,H,G,F,E,D,C,B,A,OUT,...) OUT
+#define NUM_ARGS(V...) _NUM_ARGS(0,V,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)
+
+//
+// Primitives supporting precompiler REPEAT
+//
+#define FIRST(a,...)     a
+#define SECOND(a,b,...)  b
+#define THIRD(a,b,c,...) c
+
+#define IS_PROBE(V...) SECOND(V, 0)     // Get the second item passed, or 0
+#define NOT(x) IS_PROBE(_CAT(_NOT_, x)) // NOT('0') gets '1'. Anything else gets '0'.
+
+#endif //MACROS_H

+ 2 - 0
Firmware/menu.cpp

@@ -8,6 +8,7 @@
 #include "lcd.h"
 #include "Configuration.h"
 #include "Marlin.h"
+#include "cmdqueue.h"
 #include "ultralcd.h"
 #include "language.h"
 #include "static_assert.h"
@@ -48,6 +49,7 @@ void menu_goto(menu_func_t menu, const uint32_t encoder, const bool feedback, bo
 	{
 		menu_menu = menu;
 		lcd_encoder = encoder;
+		menu_top = 0; //reset menu view. Needed if menu_back() is called from deep inside a menu, such as Support
 		asm("sei");
 		if (reset_menu_state)
 		{

+ 18 - 9
Firmware/mesh_bed_calibration.cpp

@@ -12,6 +12,8 @@
 #include "tmc2130.h"
 #endif //TMC2130
 
+#define DBG(args...) printf_P(args)
+
 uint8_t world2machine_correction_mode;
 float   world2machine_rotation_and_skew[2][2];
 float   world2machine_rotation_and_skew_inv[2][2];
@@ -369,7 +371,9 @@ BedSkewOffsetDetectionResultType calculate_machine_skew_and_offset_LS(
     BedSkewOffsetDetectionResultType result = BED_SKEW_OFFSET_DETECTION_PERFECT;
     {
         angleDiff = fabs(a2 - a1);
-		eeprom_update_float((float*)(EEPROM_XYZ_CAL_SKEW), angleDiff); //storing xyz cal. skew to be able to show in support menu later 
+        /// XY skew and Y-bed skew
+        DBG(_n("Measured skews: %f %f\n"), degrees(a2 - a1), degrees(a2));
+        eeprom_update_float((float *)(EEPROM_XYZ_CAL_SKEW), angleDiff); //storing xyz cal. skew to be able to show in support menu later
         if (angleDiff > bed_skew_angle_mild)
             result = (angleDiff > bed_skew_angle_extreme) ?
                 BED_SKEW_OFFSET_DETECTION_SKEW_EXTREME :
@@ -1380,7 +1384,7 @@ inline bool find_bed_induction_sensor_point_xy(int verbosity_level)
 
 		//        go_xyz(current_position[X_AXIS], current_position[Y_AXIS], MESH_HOME_Z_SEARCH, homing_feedrate[Z_AXIS]/60);
 		go_xyz(x0, y0, current_position[Z_AXIS], feedrate);
-		// Continously lower the Z axis.
+		// Continuously lower the Z axis.
 		endstops_hit_on_purpose();
 		enable_z_endstop(true);
 		while (current_position[Z_AXIS] > -10.f) {
@@ -2375,8 +2379,9 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
 				delay_keep_alive(3000);
 			}
 			#endif // SUPPORT_VERBOSITY
-		}
-		delay_keep_alive(0); //manage_heater, reset watchdog, manage inactivity
+        }
+        DBG(_n("All 4 calibration points found.\n"));
+        delay_keep_alive(0); //manage_heater, reset watchdog, manage inactivity
 		
 		#ifdef SUPPORT_VERBOSITY
 		if (verbosity_level >= 20) {
@@ -2386,7 +2391,7 @@ 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();
 				// Go to the measurement point.
-				// Use the coorrected coordinate, which is a result of find_bed_offset_and_skew().
+				// Use the corrected coordinate, which is a result of find_bed_offset_and_skew().
 				current_position[X_AXIS] = pts[mesh_point * 2];
 				current_position[Y_AXIS] = pts[mesh_point * 2 + 1];
 				go_to_current(homing_feedrate[X_AXIS] / 60);
@@ -2406,6 +2411,7 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
 		delay_keep_alive(0); //manage_heater, reset watchdog, manage inactivity
 		
 		if (result >= 0) {
+            DBG(_n("Calibration success.\n"));
 			world2machine_update(vec_x, vec_y, cntr);
 #if 1
 			// Fearlessly store the calibration values into the eeprom.
@@ -2450,7 +2456,7 @@ 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();
 					// Go to the measurement point.
-					// Use the coorrected coordinate, which is a result of find_bed_offset_and_skew().
+					// Use the corrected coordinate, which is a result of find_bed_offset_and_skew().
 					uint8_t ix = mesh_point % MESH_MEAS_NUM_X_POINTS; // from 0 to MESH_NUM_X_POINTS - 1
 					uint8_t iy = mesh_point / MESH_MEAS_NUM_X_POINTS;
 					if (iy & 1) ix = (MESH_MEAS_NUM_X_POINTS - 1) - ix;
@@ -2462,9 +2468,12 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
 			}
 			#endif // SUPPORT_VERBOSITY
 			return result;
-		}		
-		if (result == BED_SKEW_OFFSET_DETECTION_FITTING_FAILED && too_far_mask == 2) return result; //if fitting failed and front center point is out of reach, terminate calibration and inform user
-		iteration++;
+		}
+        if (result == BED_SKEW_OFFSET_DETECTION_FITTING_FAILED && too_far_mask == 2){
+            DBG(_n("Fitting failed => calibration failed.\n"));
+            return result; //if fitting failed and front center point is out of reach, terminate calibration and inform user
+        }
+        iteration++;
 	}
 	return result;    
 }

+ 1 - 1
Firmware/messages.c

@@ -176,4 +176,4 @@ 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
 const char MSG_ADVANCE_K[] PROGMEM_N1 = "Advance K:"; ////c=13
 const char MSG_POWERPANIC_DETECTED[] PROGMEM_N1 = "POWER PANIC DETECTED"; ////c=20
-
+const char MSG_LCD_STATUS_CHANGED[] PROGMEM_N1 = "LCD status changed";

+ 1 - 0
Firmware/messages.h

@@ -176,6 +176,7 @@ extern const char MSG_FANCHECK_PRINT[];
 extern const char MSG_M112_KILL[];
 extern const char MSG_ADVANCE_K[];
 extern const char MSG_POWERPANIC_DETECTED[];
+extern const char MSG_LCD_STATUS_CHANGED[];
 
 #if defined(__cplusplus)
 }

+ 13 - 14
Firmware/mmu.cpp

@@ -9,12 +9,14 @@
 #include "Configuration_prusa.h"
 #include "fsensor.h"
 #include "cardreader.h"
+#include "cmdqueue.h"
 #include "ultralcd.h"
 #include "sound.h"
 #include "printers.h"
 #include <avr/pgmspace.h>
-#include "io_atmega2560.h"
 #include "AutoDeplete.h"
+#include "fastio.h"
+#include "pins.h"
 //-//
 #include "util.h"
 
@@ -28,9 +30,6 @@
 #define MMU_P0_TIMEOUT 3000ul //timeout for P0 command: 3seconds
 #define MMU_MAX_RESEND_ATTEMPTS 2
 
-#ifdef MMU_HWRESET
-#define MMU_RST_PIN 76
-#endif //MMU_HWRESET
 
 namespace
 {
@@ -156,8 +155,8 @@ void mmu_init(void)
 	_delay_ms(10);                             //wait 10ms for sure
 	mmu_reset();                               //reset mmu (HW or SW), do not wait for response
 	mmu_state = S::Init;
-	PIN_INP(IR_SENSOR_PIN); //input mode
-	PIN_SET(IR_SENSOR_PIN); //pullup
+	SET_INPUT(IR_SENSOR_PIN); //input mode
+	WRITE(IR_SENSOR_PIN, 1); //pullup
 }
 
 //if IR_SENSOR defined, always returns true
@@ -170,7 +169,7 @@ bool check_for_ir_sensor()
 
 	bool detected = false;
 	//if IR_SENSOR_PIN input is low and pat9125sensor is not present we detected idler sensor
-	if ((PIN_GET(IR_SENSOR_PIN) == 0) 
+	if ((READ(IR_SENSOR_PIN) == 0) 
 #ifdef PAT9125
 		&& fsensor_not_responding
 #endif //PAT9125
@@ -363,7 +362,7 @@ void mmu_loop(void)
 	case S::GetFinda: //response to command P0
         if (mmu_idl_sens)
         {
-            if (PIN_GET(IR_SENSOR_PIN) == 0 && mmu_loading_flag)
+            if (READ(IR_SENSOR_PIN) == 0 && mmu_loading_flag)
             {
 #ifdef MMU_DEBUG
                 printf_P(PSTR("MMU <= 'A'\n"));
@@ -406,7 +405,7 @@ void mmu_loop(void)
 	case S::WaitCmd: //response to mmu commands
         if (mmu_idl_sens)
         {
-            if (PIN_GET(IR_SENSOR_PIN) == 0 && mmu_loading_flag)
+            if (READ(IR_SENSOR_PIN) == 0 && mmu_loading_flag)
             {
                 DEBUG_PRINTF_P(PSTR("MMU <= 'A'\n"));
                 mmu_puts_P(PSTR("A\n")); //send 'abort' request
@@ -596,10 +595,10 @@ bool mmu_get_response(uint8_t move)
 			    mmu_loading_flag = true;
 				if (can_extrude()) mmu_load_step();
 				//don't rely on "ok" signal from mmu unit; if filament detected by idler sensor during loading stop loading movements to prevent infinite loading
-				if (PIN_GET(IR_SENSOR_PIN) == 0) move = MMU_NO_MOVE;
+				if (READ(IR_SENSOR_PIN) == 0) move = MMU_NO_MOVE;
 				break;
 			case MMU_UNLOAD_MOVE:
-				if (PIN_GET(IR_SENSOR_PIN) == 0) //filament is still detected by idler sensor, printer helps with unlading 
+				if (READ(IR_SENSOR_PIN) == 0) //filament is still detected by idler sensor, printer helps with unlading 
 				{
 				    if (can_extrude())
 				    {
@@ -617,7 +616,7 @@ bool mmu_get_response(uint8_t move)
 				}
 				break;
 			case MMU_TCODE_MOVE: //first do unload and then continue with infinite loading movements
-				if (PIN_GET(IR_SENSOR_PIN) == 0) //filament detected by idler sensor, we must unload first 
+				if (READ(IR_SENSOR_PIN) == 0) //filament detected by idler sensor, we must unload first 
 				{
                     if (can_extrude())
                     {
@@ -1460,7 +1459,7 @@ static bool can_load()
         current_position[E_AXIS] -= e_increment;
         plan_buffer_line_curposXYZE(MMU_LOAD_FEEDRATE);
         st_synchronize();
-        if(0 == PIN_GET(IR_SENSOR_PIN))
+        if(0 == READ(IR_SENSOR_PIN))
         {
             ++filament_detected_count;
             DEBUG_PUTCHAR('O');
@@ -1491,7 +1490,7 @@ static bool load_more()
 {
     for (uint8_t i = 0; i < MMU_IDLER_SENSOR_ATTEMPTS_NR; i++)
     {
-        if (PIN_GET(IR_SENSOR_PIN) == 0) return true;
+        if (READ(IR_SENSOR_PIN) == 0) return true;
         DEBUG_PRINTF_P(PSTR("Additional load attempt nr. %d\n"), i);
         mmu_command(MmuCmd::C0);
         manage_response(true, true, MMU_LOAD_MOVE);

+ 2 - 0
Firmware/pins_Einsy_1_0.h

@@ -121,6 +121,8 @@
 
 #define IR_SENSOR_PIN 62 //idler sensor @PK0 (digital pin 62/A8)
 
+#define MMU_RST_PIN 76
+
 // Support for an 8 bit logic analyzer, for example the Saleae.
 // Channels 0-2 are fast, they could generate 2.667Mhz waveform with a software loop.
 #define LOGIC_ANALYZER_CH0		X_MIN_PIN		// PB6

+ 1 - 1
Firmware/sm4.c

@@ -173,7 +173,7 @@ uint16_t sm4_line_xyze_ui(uint16_t dx, uint16_t dy, uint16_t dz, uint16_t de)
 		}
 		if (ce <= de)
 		{
-			sm |= 4;
+			sm |= 8;
 			ce += dd;
 			e++;
 		}

+ 29 - 29
Firmware/swi2c.c

@@ -3,9 +3,10 @@
 #include <avr/io.h>
 #include <util/delay.h>
 #include <avr/pgmspace.h>
+#include "stdbool.h"
 #include "Configuration_prusa.h"
 #include "pins.h"
-#include "io_atmega2560.h"
+#include "fastio.h"
 
 
 #define SWI2C_RMSK   0x01 //read mask (bit0 = 1)
@@ -21,75 +22,75 @@ void __delay(void)
 
 void swi2c_init(void)
 {
-	PIN_OUT(SWI2C_SDA);
-	PIN_OUT(SWI2C_SCL);
-	PIN_SET(SWI2C_SDA);
-	PIN_SET(SWI2C_SCL);
+	WRITE(SWI2C_SDA, 1);
+	WRITE(SWI2C_SCL, 1);
+	SET_OUTPUT(SWI2C_SDA);
+	SET_OUTPUT(SWI2C_SCL);
 	uint8_t i; for (i = 0; i < 100; i++)
 		__delay();
 }
 
 void swi2c_start(void)
 {
-	PIN_CLR(SWI2C_SDA);
+	WRITE(SWI2C_SDA, 0);
 	__delay();
-	PIN_CLR(SWI2C_SCL);
+	WRITE(SWI2C_SCL, 0);
 	__delay();
 }
 
 void swi2c_stop(void)
 {
-	PIN_SET(SWI2C_SCL);
+	WRITE(SWI2C_SCL, 1);
 	__delay();
-	PIN_SET(SWI2C_SDA);
+	WRITE(SWI2C_SDA, 1);
 	__delay();
 }
 
 void swi2c_ack(void)
 {
-	PIN_CLR(SWI2C_SDA);
+	WRITE(SWI2C_SDA, 0);
 	__delay();
-	PIN_SET(SWI2C_SCL);
+	WRITE(SWI2C_SCL, 1);
 	__delay();
-	PIN_CLR(SWI2C_SCL);
+	WRITE(SWI2C_SCL, 0);
 	__delay();
 }
 
 uint8_t swi2c_wait_ack()
 {
-	PIN_INP(SWI2C_SDA);
+	SET_INPUT(SWI2C_SDA);
 	__delay();
-//	PIN_SET(SWI2C_SDA);
+//	WRITE(SWI2C_SDA, 1);
 	__delay();
-	PIN_SET(SWI2C_SCL);
+	WRITE(SWI2C_SCL, 1);
 //	__delay();
 	uint8_t ack = 0;
 	uint16_t ackto = SWI2C_TMO;
-	while (!(ack = (PIN_GET(SWI2C_SDA)?0:1)) && ackto--) __delay();
-	PIN_CLR(SWI2C_SCL);
+	while (!(ack = (!READ(SWI2C_SDA))) && ackto--) __delay();
+	WRITE(SWI2C_SCL, 0);
 	__delay();
-	PIN_OUT(SWI2C_SDA);
+	SET_OUTPUT(SWI2C_SDA);
 	__delay();
-	PIN_CLR(SWI2C_SDA);
+	WRITE(SWI2C_SDA, 0);
 	__delay();
 	return ack;
 }
 
 uint8_t swi2c_read(void)
 {
-	PIN_SET(SWI2C_SDA);
+	WRITE(SWI2C_SDA, 1);
 	__delay();
-	PIN_INP(SWI2C_SDA);
+	SET_INPUT(SWI2C_SDA);
 	uint8_t data = 0;
 	int8_t bit; for (bit = 7; bit >= 0; bit--)
 	{
-		PIN_SET(SWI2C_SCL);
+		WRITE(SWI2C_SCL, 1);
 		__delay();
-		data |= (PIN_GET(SWI2C_SDA)?1:0) << bit;
-		PIN_CLR(SWI2C_SCL);
+		data |= (READ(SWI2C_SDA)) << bit;
+		WRITE(SWI2C_SCL, 0);
 		__delay();
 	}
-	PIN_OUT(SWI2C_SDA);
+	SET_OUTPUT(SWI2C_SDA);
 	return data;
 }
 
@@ -97,12 +98,11 @@ void swi2c_write(uint8_t data)
 {
 	int8_t bit; for (bit = 7; bit >= 0; bit--)
 	{
-		if (data & (1 << bit)) PIN_SET(SWI2C_SDA);
-		else PIN_CLR(SWI2C_SDA);
+		WRITE(SWI2C_SDA, data & _BV(bit));
 		__delay();
-		PIN_SET(SWI2C_SCL);
+		WRITE(SWI2C_SCL, 1);
 		__delay();
-		PIN_CLR(SWI2C_SCL);
+		WRITE(SWI2C_SCL, 0);
 		__delay();
 	}
 }

+ 1 - 1
Firmware/temperature.cpp

@@ -30,6 +30,7 @@
 
 
 #include "Marlin.h"
+#include "cmdqueue.h"
 #include "ultralcd.h"
 #include "sound.h"
 #include "temperature.h"
@@ -632,7 +633,6 @@ void fanSpeedError(unsigned char _fan) {
 		fanSpeedErrorBeep(PSTR("Print fan speed is lower than expected"), MSG_FANCHECK_PRINT);
 		break;
 	}
-    // SERIAL_PROTOCOLLNRPGM(MSG_OK); //This ok messes things up with octoprint.
 }
 #endif //(defined(TACH_0) && TACH_0 >-1) || (defined(TACH_1) && TACH_1 > -1)
 

+ 0 - 3
Firmware/timer02.c

@@ -9,9 +9,6 @@
 
 #include <avr/io.h>
 #include <avr/interrupt.h>
-#include "io_atmega2560.h"
-
-#define BEEPER              84
 
 void timer0_init(void)
 {

+ 3 - 9
Firmware/tone04.c

@@ -10,14 +10,8 @@
 #include <avr/io.h>
 #include <avr/interrupt.h>
 #include "pins.h"
-
-#ifndef CRITICAL_SECTION_START
-	#define CRITICAL_SECTION_START  unsigned char _sreg = SREG; cli();
-	#define CRITICAL_SECTION_END    SREG = _sreg;
-#endif //CRITICAL_SECTION_START
-
-
 #include "fastio.h"
+#include "macros.h"
 
 void timer4_init(void)
 {
@@ -79,7 +73,7 @@ ISR(TIMER4_OVF_vect)
 	WRITE(BEEPER, 0);
 }
 
-void tone4(__attribute__((unused)) uint8_t _pin, uint16_t frequency)
+void tone4(_UNUSED uint8_t _pin, uint16_t frequency)
 {
 	//this ocr and prescalarbits calculation is taken from the Arduino core and simplified for one type of timer only
 	uint8_t prescalarbits = 0b001;
@@ -105,7 +99,7 @@ void tone4(__attribute__((unused)) uint8_t _pin, uint16_t frequency)
 	CRITICAL_SECTION_END;
 }
 
-void noTone4(__attribute__((unused)) uint8_t _pin)
+void noTone4(_UNUSED uint8_t _pin)
 {
 	CRITICAL_SECTION_START;
 	// Revert prescaler to CLK/1024

+ 3 - 2
Firmware/uart2.c

@@ -4,6 +4,7 @@
 #include <avr/interrupt.h>
 #include <avr/pgmspace.h>
 #include "rbuf.h"
+#include "macros.h"
 
 #define UART2_BAUD 115200
 #define UART_BAUD_SELECT(baudRate,xtalCpu) (((float)(xtalCpu))/(((float)(baudRate))*8.0)-1.0+0.5)
@@ -16,7 +17,7 @@ uint8_t uart2_ibuf[14] = {0, 0};
 FILE _uart2io = {0};
 
 
-int uart2_putchar(char c, FILE *stream __attribute__((unused)))
+int uart2_putchar(char c, _UNUSED FILE *stream)
 {
 	while (!uart2_txready);
 	UDR2 = c; // transmit byte
@@ -25,7 +26,7 @@ int uart2_putchar(char c, FILE *stream __attribute__((unused)))
 	return 0;
 }
 
-int uart2_getchar(FILE *stream __attribute__((unused)))
+int uart2_getchar(_UNUSED FILE *stream)
 {
 	if (rbuf_empty(uart2_ibuf)) return -1;
 	return rbuf_get(uart2_ibuf);

+ 108 - 73
Firmware/ultralcd.cpp

@@ -44,7 +44,6 @@
 #include "mmu.h"
 
 #include "static_assert.h"
-#include "io_atmega2560.h"
 #include "first_lay_cal.h"
 
 #include "fsensor.h"
@@ -1001,6 +1000,36 @@ void lcd_status_screen()                          // NOT static due to using ins
 		}
 	}
 
+#ifdef ULTIPANEL_FEEDMULTIPLY
+	// Dead zone at 100% feedrate
+	if ((feedmultiply < 100 && (feedmultiply + int(lcd_encoder)) > 100) ||
+		(feedmultiply > 100 && (feedmultiply + int(lcd_encoder)) < 100))
+	{
+		lcd_encoder = 0;
+		feedmultiply = 100;
+	}
+	if (feedmultiply == 100 && int(lcd_encoder) > ENCODER_FEEDRATE_DEADZONE)
+	{
+		feedmultiply += int(lcd_encoder) - ENCODER_FEEDRATE_DEADZONE;
+		lcd_encoder = 0;
+	}
+	else if (feedmultiply == 100 && int(lcd_encoder) < -ENCODER_FEEDRATE_DEADZONE)
+	{
+		feedmultiply += int(lcd_encoder) + ENCODER_FEEDRATE_DEADZONE;
+		lcd_encoder = 0;
+	}
+	else if (feedmultiply != 100)
+	{
+		feedmultiply += int(lcd_encoder);
+		lcd_encoder = 0;
+	}
+#endif //ULTIPANEL_FEEDMULTIPLY
+
+	if (feedmultiply < 10)
+		feedmultiply = 10;
+	else if (feedmultiply > 999)
+		feedmultiply = 999;
+
 	if (lcd_status_update_delay)
 		lcd_status_update_delay--;
 	else
@@ -1077,36 +1106,6 @@ void lcd_status_screen()                          // NOT static due to using ins
 		menu_submenu(lcd_main_menu);
 		lcd_refresh(); // to maybe revive the LCD if static electricity killed it.
 	}
-
-#ifdef ULTIPANEL_FEEDMULTIPLY
-	// Dead zone at 100% feedrate
-	if ((feedmultiply < 100 && (feedmultiply + int(lcd_encoder)) > 100) ||
-		(feedmultiply > 100 && (feedmultiply + int(lcd_encoder)) < 100))
-	{
-		lcd_encoder = 0;
-		feedmultiply = 100;
-	}
-	if (feedmultiply == 100 && int(lcd_encoder) > ENCODER_FEEDRATE_DEADZONE)
-	{
-		feedmultiply += int(lcd_encoder) - ENCODER_FEEDRATE_DEADZONE;
-		lcd_encoder = 0;
-	}
-	else if (feedmultiply == 100 && int(lcd_encoder) < -ENCODER_FEEDRATE_DEADZONE)
-	{
-		feedmultiply += int(lcd_encoder) + ENCODER_FEEDRATE_DEADZONE;
-		lcd_encoder = 0;
-	}
-	else if (feedmultiply != 100)
-	{
-		feedmultiply += int(lcd_encoder);
-		lcd_encoder = 0;
-	}
-#endif //ULTIPANEL_FEEDMULTIPLY
-
-	if (feedmultiply < 10)
-		feedmultiply = 10;
-	else if (feedmultiply > 999)
-		feedmultiply = 999;
 }
 
 void lcd_commands()
@@ -1583,6 +1582,7 @@ void lcd_return_to_status()
 //! @brief Pause print, disable nozzle heater, move to park position
 void lcd_pause_print()
 {
+    SERIAL_PROTOCOLLNRPGM(MSG_OCTOPRINT_PAUSED); //pause for octoprint
     stop_and_save_print_to_ram(0.0, -default_retraction);
     lcd_return_to_status();
     isPrintPaused = true;
@@ -1590,7 +1590,6 @@ void lcd_pause_print()
     {
         lcd_commands_type = LcdCommands::LongPause;
     }
-	SERIAL_PROTOCOLLNRPGM(MSG_OCTOPRINT_PAUSED); //pause for octoprint
 }
 
 
@@ -2121,12 +2120,14 @@ static void lcd_support_menu()
         // Menu was entered or SD card status has changed (plugged in or removed).
         // Initialize its status.
         _md->status = 1;
-        _md->is_flash_air = card.ToshibaFlashAir_isEnabled() && card.ToshibaFlashAir_GetIP(_md->ip);
-        if (_md->is_flash_air)
+        _md->is_flash_air = card.ToshibaFlashAir_isEnabled();
+        if (_md->is_flash_air) {
+            card.ToshibaFlashAir_GetIP(_md->ip); // ip[4] filled with 0 if it failed
+            // Prepare IP string from ip[4]
             sprintf_P(_md->ip_str, PSTR("%d.%d.%d.%d"), 
                 _md->ip[0], _md->ip[1], 
                 _md->ip[2], _md->ip[3]);
-        
+        }
     } else if (_md->is_flash_air && 
         _md->ip[0] == 0 && _md->ip[1] == 0 && 
         _md->ip[2] == 0 && _md->ip[3] == 0 &&
@@ -2192,7 +2193,11 @@ static void lcd_support_menu()
   if (_md->is_flash_air) {
       MENU_ITEM_BACK_P(STR_SEPARATOR);
       MENU_ITEM_BACK_P(PSTR("FlashAir IP Addr:"));  //c=18 r=1
-///!      MENU_ITEM(back_RAM, _md->ip_str, 0);
+      MENU_ITEM_BACK_P(PSTR(" "));
+      if (((menu_item - 1) == menu_line) && lcd_draw_update) {
+          lcd_set_cursor(2, menu_row);
+          lcd_printf_P(PSTR("%s"), _md->ip_str);
+      }
   }
 
   #ifndef MK1BP
@@ -2413,7 +2418,7 @@ void mFilamentItem(uint16_t nTemp, uint16_t nTempBed)
         case FilamentAction::None:
         case FilamentAction::Preheat:
         case FilamentAction::Lay1Cal:
-
+            // handled earlier
             break;
         }
         if (bFilamentWaitingFlag) Sound_MakeSound(e_SOUND_TYPE_StandardPrompt);
@@ -2421,34 +2426,45 @@ void mFilamentItem(uint16_t nTemp, uint16_t nTempBed)
     }
     else
     {
-        bFilamentWaitingFlag = true;
         lcd_set_cursor(0, 0);
         lcdui_print_temp(LCD_STR_THERMOMETER[0], (int) degHotend(0), (int) degTargetHotend(0));
-        lcd_set_cursor(0, 1);
-        switch (eFilamentAction)
+
+        if (!bFilamentWaitingFlag)
         {
-        case FilamentAction::Load:
-        case FilamentAction::AutoLoad:
-        case FilamentAction::MmuLoad:
-            lcd_puts_P(_i("Preheating to load")); ////MSG_ c=20
-            break;
-        case FilamentAction::UnLoad:
-        case FilamentAction::MmuUnLoad:
-            lcd_puts_P(_i("Preheating to unload")); ////MSG_ c=20
-            break;
-        case FilamentAction::MmuEject:
-            lcd_puts_P(_i("Preheating to eject")); ////MSG_ c=20
-            break;
-        case FilamentAction::MmuCut:
-            lcd_puts_P(_i("Preheating to cut")); ////MSG_ c=20
-            break;
-        case FilamentAction::None:
-        case FilamentAction::Preheat:
-        case FilamentAction::Lay1Cal:
-            break;
+            // First run after the filament preheat selection:
+            // setup the fixed LCD parts and raise Z as we wait
+            bFilamentWaitingFlag = true;
+
+            lcd_set_cursor(0, 1);
+            switch (eFilamentAction)
+            {
+            case FilamentAction::Load:
+            case FilamentAction::AutoLoad:
+            case FilamentAction::MmuLoad:
+                lcd_puts_P(_i("Preheating to load")); ////MSG_ c=20
+                raise_z_above(MIN_Z_FOR_LOAD);
+                break;
+            case FilamentAction::UnLoad:
+            case FilamentAction::MmuUnLoad:
+                lcd_puts_P(_i("Preheating to unload")); ////MSG_ c=20
+                raise_z_above(MIN_Z_FOR_UNLOAD);
+                break;
+            case FilamentAction::MmuEject:
+                lcd_puts_P(_i("Preheating to eject")); ////MSG_ c=20
+                break;
+            case FilamentAction::MmuCut:
+                lcd_puts_P(_i("Preheating to cut")); ////MSG_ c=20
+                break;
+            case FilamentAction::None:
+            case FilamentAction::Preheat:
+            case FilamentAction::Lay1Cal:
+                // handled earlier
+                break;
+            }
+            lcd_set_cursor(0, 3);
+            lcd_puts_P(_i(">Cancel"));                   ////MSG_ c=20 r=1
         }
-        lcd_set_cursor(0, 3);
-        lcd_puts_P(_i(">Cancel"));                   ////MSG_ c=20 r=1
+
         if (lcd_clicked())
         {
             bFilamentWaitingFlag = false;
@@ -2931,7 +2947,7 @@ static void _lcd_move(const char *name, int axis, int min, int max)
 }
 
 
-static void lcd_move_e()
+void lcd_move_e()
 {
 	if (degHotend0() > EXTRUDE_MINTEMP)
 	{
@@ -3999,7 +4015,7 @@ static void lcd_show_sensors_state()
 		finda_state = mmu_finda;
 	}
 	if (ir_sensor_detected) {
-		idler_state = !PIN_GET(IR_SENSOR_PIN);
+		idler_state = !READ(IR_SENSOR_PIN);
 	}
 	lcd_puts_at_P(0, 0, _i("Sensor state"));
 	lcd_puts_at_P(1, 1, _i("PINDA:"));
@@ -6750,6 +6766,7 @@ void lcd_resume_print()
     lcd_return_to_status();
     lcd_reset_alert_level(); //for fan speed error
     if (fan_error_selftest()) return; //abort if error persists
+    cmdqueue_serial_disabled = false;
 
     lcd_setstatuspgm(_T(MSG_FINISHING_MOVEMENTS));
     st_synchronize();
@@ -7362,6 +7379,7 @@ void lcd_print_stop()
     if (!card.sdprinting) {
         SERIAL_ECHOLNRPGM(MSG_OCTOPRINT_CANCEL);   // for Octoprint
     }
+    cmdqueue_serial_disabled = false; //for when canceling a print with a fancheck
 
     CRITICAL_SECTION_START;
 
@@ -8484,7 +8502,7 @@ static bool selftest_irsensor()
         mmu_load_step(false);
         while (blocks_queued())
         {
-            if (PIN_GET(IR_SENSOR_PIN) == 0)
+            if (READ(IR_SENSOR_PIN) == 0)
             {
                 lcd_selftest_error(TestError::TriggeringFsensor, "", "");
                 return false;
@@ -8791,26 +8809,42 @@ static void lcd_selftest_screen_step(int _row, int _col, int _state, const char
 
 static bool check_file(const char* filename) {
 	if (farm_mode) return true;
-	bool result = false;
-	uint32_t filesize;
 	card.openFile((char*)filename, true);
-	filesize = card.getFileSize();
+	bool result = false;
+	const uint32_t filesize = card.getFileSize();
+	uint32_t startPos = 0;
+	const uint16_t bytesToCheck = min(END_FILE_SECTION, filesize);
+	uint8_t blocksPrinted = 0;
 	if (filesize > END_FILE_SECTION) {
-		card.setIndex(filesize - END_FILE_SECTION);
-		
+		startPos = filesize - END_FILE_SECTION;
+		card.setIndex(startPos);
 	}
-	
-		while (!card.eof() && !result) {
+	cmdqueue_reset();
+	cmdqueue_serial_disabled = true;
+
+	lcd_clear();
+	lcd_puts_at_P(0, 1, _i("Checking file"));////c=20 r=1
+	lcd_set_cursor(0, 2);
+	while (!card.eof() && !result) {
+		for (; blocksPrinted < (((card.get_sdpos() - startPos) * LCD_WIDTH) / bytesToCheck); blocksPrinted++)
+			lcd_print('\xFF'); //simple progress bar
+
 		card.sdprinting = true;
 		get_command();
 		result = check_commands();
-		
 	}
+
+	for (; blocksPrinted < LCD_WIDTH; blocksPrinted++)
+		lcd_print('\xFF'); //simple progress bar
+	_delay(100); //for the user to see the end of the progress bar.
+
+	
+	cmdqueue_serial_disabled = false;
 	card.printingHasFinished();
+
 	strncpy_P(lcd_status_message, _T(WELCOME_MSG), LCD_WIDTH);
 	lcd_finishstatus();
 	return result;
-	
 }
 
 static void menu_action_sdfile(const char* filename)
@@ -8978,6 +9012,7 @@ void lcd_ignore_click(bool b)
 }
 
 void lcd_finishstatus() {
+  SERIAL_PROTOCOLLNRPGM(MSG_LCD_STATUS_CHANGED);
   int len = strlen(lcd_status_message);
   if (len > 0) {
     while (len < LCD_WIDTH) {

+ 1 - 0
Firmware/ultralcd.h

@@ -207,6 +207,7 @@ void lcd_farm_sdcard_menu_w();
 
 void lcd_wait_for_heater();
 void lcd_wait_for_cool_down();
+void lcd_move_e(); // NOT static due to usage in Marlin_main
 void lcd_extr_cal_reset();
 
 void lcd_temp_cal_show_result(bool result);

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

@@ -266,7 +266,6 @@
 #define TMC2130_CURRENTS_H {16, 20, 35, 30}  // default holding currents for all axes
 #define TMC2130_CURRENTS_R {16, 20, 35, 30}  // default running currents for all axes
 #define TMC2130_CURRENTS_R_HOME {8, 10, 20, 18}  // homing running currents for all axes
-// #define TMC2130_UNLOAD_CURRENT_R 12			 // lower current for M600 to protect filament sensor - Unused
 
 #define TMC2130_STEALTH_Z
 

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

@@ -268,7 +268,6 @@
 #define TMC2130_CURRENTS_H {16, 20, 35, 30}  // default holding currents for all axes
 #define TMC2130_CURRENTS_R {16, 20, 35, 30}  // default running currents for all axes
 #define TMC2130_CURRENTS_R_HOME {8, 10, 20, 18}  // homing running currents for all axes
-// #define TMC2130_UNLOAD_CURRENT_R 12			 // lower current for M600 to protect filament sensor - Unused
 
 #define TMC2130_STEALTH_Z
 

+ 4 - 4
Firmware/w25x20cl.c

@@ -3,8 +3,8 @@
 #include "w25x20cl.h"
 #include <avr/io.h>
 #include <avr/pgmspace.h>
-#include "io_atmega2560.h"
 #include "spi.h"
+#include "fastio.h"
 
 #define _MFRID             0xEF
 #define _DEVID             0x11
@@ -31,8 +31,8 @@
 #define _CMD_JEDEC_ID      0x9f
 #define _CMD_RD_UID        0x4b
 
-#define _CS_LOW()  PORT(W25X20CL_PIN_CS) &= ~__MSK(W25X20CL_PIN_CS)
-#define _CS_HIGH() PORT(W25X20CL_PIN_CS) |= __MSK(W25X20CL_PIN_CS)
+#define _CS_LOW() WRITE(W25X20CL_PIN_CS, 0)
+#define _CS_HIGH() WRITE(W25X20CL_PIN_CS, 1)
 
 //#define _SPI_TX swspi_tx
 //#define _SPI_RX swspi_rx
@@ -45,8 +45,8 @@ int w25x20cl_mfrid_devid(void);
 
 int8_t w25x20cl_init(void)
 {
-	PIN_OUT(W25X20CL_PIN_CS);
 	_CS_HIGH();
+	SET_OUTPUT(W25X20CL_PIN_CS);
 	W25X20CL_SPI_ENTER();
 	if (!w25x20cl_mfrid_devid()) return 0;
 	return 1;

+ 18 - 16
Firmware/xyzcal.cpp

@@ -293,7 +293,7 @@ bool xyzcal_spiral2(int16_t cx, int16_t cy, int16_t z0, int16_t dz, int16_t radi
 			dad = dad_max - ((719 - ad) / k);
 			r = (float)(((uint32_t)(719 - ad)) * (-radius)) / 720;
 		}
-		ar = (ad + rotation)* (float)M_PI / 180;
+		ar = radians(ad + rotation);
 		int x = (int)(cx + (cos(ar) * r));
 		int y = (int)(cy + (sin(ar) * r));
 		int z = (int)(z0 - ((float)((int32_t)dz * ad) / 720));
@@ -682,7 +682,7 @@ uint8_t xyzcal_find_pattern_12x12_in_32x32(uint8_t* pixels, uint16_t* pattern, u
 		}
 		// DBG(_n("\n"));
 	}
-	DBG(_n("max_c=%d max_r=%d max_match=%d pixel\n"), max_c, max_r, max_match);
+	DBG(_n("Pattern center [%f %f], match %f%%\n"), max_c + 5.5f, max_r + 5.5f, max_match / 1.32f);
 
 	*pc = max_c;
 	*pr = max_r;
@@ -812,16 +812,15 @@ float median(float *points, const uint8_t num_points){
 void dynamic_circle(uint8_t *matrix_32x32, float &x, float &y, float &r, uint8_t iterations){
 	/// circle of 10.5 diameter has 33 in circumference, don't go much above
 	const constexpr uint8_t num_points = 33;
-	float pi_2_div_num_points = 2 * M_PI / num_points;
+	const float pi_2_div_num_points = 2 * M_PI / num_points;
 	const constexpr uint8_t target_z = 32; ///< target z height of the circle
-	float angle;
 	float max_change = 0.5f; ///< avoids too fast changes (avoid oscillation)
 	const uint8_t blocks = num_points;
 	float shifts_x[blocks];
 	float shifts_y[blocks];	
 	float shifts_r[blocks];	
 
-	DBG(_n(" [%f, %f][%f] start circle\n"), x, y, r);
+	// DBG(_n(" [%f, %f][%f] start circle\n"), x, y, r);
 
 	for (int8_t i = iterations; i > 0; --i){
 	
@@ -829,7 +828,7 @@ void dynamic_circle(uint8_t *matrix_32x32, float &x, float &y, float &r, uint8_t
 
 		/// read points on the circle
 		for (uint8_t p = 0; p < num_points; ++p){
-			angle = p * pi_2_div_num_points;
+			const float angle = p * pi_2_div_num_points;
 			const float height = get_value(matrix_32x32, r * cos(angle) + x, r * sin(angle) + y) - target_z;
 			// DBG(_n("%f "), point);
 
@@ -839,7 +838,8 @@ void dynamic_circle(uint8_t *matrix_32x32, float &x, float &y, float &r, uint8_t
 		}
 		// DBG(_n(" points\n"));
 
-		const float norm = 1.f / 32.f;
+		const float reducer = 32.f; ///< reduces speed of convergency to avoid oscillation
+		const float norm = 1.f / reducer;
 		x += CLAMP(median(shifts_x, blocks) * norm, -max_change, max_change);
 		y += CLAMP(median(shifts_y, blocks) * norm, -max_change, max_change);
 		r += CLAMP(median(shifts_r, blocks) * norm * .5f, -max_change, max_change);
@@ -893,32 +893,31 @@ bool xyzcal_scan_and_process(void){
 	bool ret = false;
 	int16_t x = _X;
 	int16_t y = _Y;
-	int16_t z = _Z;
+	const int16_t z = _Z;
 
 	uint8_t *matrix32 = (uint8_t *)block_buffer;
 	uint16_t *pattern08 = (uint16_t *)(matrix32 + 32 * 32);
 	uint16_t *pattern10 = (uint16_t *)(pattern08 + 12);
 
-	xyzcal_scan_pixels_32x32_Zhop(x, y, z - 72, 2400, 200, matrix32);
-	print_image(matrix32);
-
 	for (uint8_t i = 0; i < 12; i++){
 		pattern08[i] = pgm_read_word((uint16_t*)(xyzcal_point_pattern_08 + i));
 		pattern10[i] = pgm_read_word((uint16_t*)(xyzcal_point_pattern_10 + i));
 	}
-	
+
+	xyzcal_scan_pixels_32x32_Zhop(x, y, z, 2400, 200, matrix32);
+	print_image(matrix32);
+
 	/// SEARCH FOR BINARY CIRCLE
 	uint8_t uc = 0;
 	uint8_t ur = 0;
-	
-	
+
 	/// max match = 132, 1/2 good = 66, 2/3 good = 88
 	if (find_patterns(matrix32, pattern08, pattern10, uc, ur) >= 88){
 		/// find precise circle
 		/// move to the center of the pattern (+5.5)
 		float xf = uc + 5.5f;
 		float yf = ur + 5.5f;
-		float radius = 5; ///< default radius
+		float radius = 4.5f; ///< default radius
 		const uint8_t iterations = 20;
 		dynamic_circle(matrix32, xf, yf, radius, iterations);
 		if (fabs(xf - (uc + 5.5f)) > 3 || fabs(yf - (ur + 5.5f)) > 3 || fabs(radius - 5) > 3){
@@ -951,10 +950,13 @@ bool xyzcal_find_bed_induction_sensor_point_xy(void){
 	st_synchronize();
 	pos_i16_t x = _X;
 	pos_i16_t y = _Y;
+	const pos_i16_t z = _Z;
+	///< magic constant, lowers min_z after searchZ to obtain more dense data in scan
+	const pos_i16_t lower_z = 72; 
 
 	xyzcal_meassure_enter();
 	if (xyzcal_searchZ()){
-		xyzcal_lineXYZ_to(x, y, _Z, 200, 0);
+		xyzcal_lineXYZ_to(_X, _Y, _Z - lower_z, 200, 0);
 		ret = xyzcal_scan_and_process();
 	}
 	xyzcal_meassure_leave();

+ 227 - 60
PF-build.sh

@@ -15,7 +15,7 @@
 # 3. Install zip with 'apt-get install zip'
 # 4. Install python3 with 'apt-get install python3'
 # 5. Add command 'ln -sf /usr/bin/python3.5 /usr/bin/python' to link python3 to python.
-#    Donnot istall 'python' as python 2.x has end of life see https://pythonclock.org/
+#    Do not install 'python' as python 2.x has end of life see https://pythonclock.org/
 # 6. Add at top of ~/.bashrc following lines by using 'sudo nano ~/.bashrc'
 #
 #    export OS="Linux"
@@ -37,7 +37,7 @@
 # 2. Another great tool to compare your custom mod and stock firmware is WinMerge http://winmerge.org/downloads/?lang=en
 # 
 # Example for MK3: open git bash and change to your Firmware directory 
-# <username>@<machinename> MINGW64 /<drive>/path
+# <username>@<machine name> MINGW64 /<drive>/path
 # bash build.sh 1_75mm_MK3-EINSy10a-E3Dv6full
 #
 # Example for MK25: open git bash and change to your directory 
@@ -56,15 +56,15 @@
 #   Some may argue that this is only used by a script, BUT as soon someone accidentally or on purpose starts Arduino IDE
 #   it will use the default Arduino IDE folders and so can corrupt the build environment.
 #
-# Version: 1.0.6-Build_18
+# Version: 1.0.6-Build_33
 # Change log:
 # 12 Jan 2019, 3d-gussner, Fixed "compiler.c.elf.flags=-w -Os -Wl,-u,vfprintf -lprintf_flt -lm -Wl,--gc-sections" in 'platform.txt'
 # 16 Jan 2019, 3d-gussner, Build_2, Added development check to modify 'Configuration.h' to prevent unwanted LCD messages that Firmware is unknown
 # 17 Jan 2019, 3d-gussner, Build_3, Check for OS Windows or Linux and use the right build environment
 # 10 Feb 2019, ropaha, Pull Request, Select variant from list while using build.sh
 # 10 Feb 2019, ropaha, change FW_DEV_VERSION automatically depending on FW_VERSION RC/BETA/ALPHA
-# 10 Feb 2019, 3d-gussner, 1st tests with english only 
-# 10 Feb 2019, ropaha, added compiling of all variants and english only
+# 10 Feb 2019, 3d-gussner, 1st tests with English only 
+# 10 Feb 2019, ropaha, added compiling of all variants and English only
 # 10 Feb 2019, 3d-gussner, Set OUTPUT_FOLDER for hex files
 # 11 Feb 2019, 3d-gussner/ropaha, Minor changes and fixes
 # 11 Feb 2019, 3d-gussner, Ready for RC
@@ -80,50 +80,62 @@
 #                                              Configuration_prusa.h
 #                                              language build files
 #                                              multi language firmware files exist and clean them up
-# 15 Feb 2019, 3d-gussner, Fixed selction GOLD/UNKNOWN DEV_STATUS for ALL variants builds, so you have to choose only once
+# 15 Feb 2019, 3d-gussner, Fixed selection GOLD/UNKNOWN DEV_STATUS for ALL variants builds, so you have to choose only once
 # 15 Feb 2019, 3d-gussner, Added some colored output
 # 15 Feb 2019, 3d-gussner, troubleshooting and minor fixes
 # 16 Feb 2019, 3d-gussner, Script can be run using arguments
 #                          $1 = variant, example "1_75mm_MK3-EINSy10a-E3Dv6full.h" at this moment it is not possible to use ALL
-#                          $2 = multi language OR english only [ALL/EN_ONLY]
+#                          $2 = multi language OR English only [ALL/EN_ONLY]
 #                          $3 = development status [GOLD/RC/BETA/ALPHA/DEVEL/DEBUG]
 #                          If one argument is wrong a list of valid one will be shown
-# 13 Mar 2019, 3d-gussner, MKbel updated the linux build environment to version 1.0.2 with an Fix maximum firmware flash size.
+# 13 Mar 2019, 3d-gussner, MKbel updated the Linux build environment to version 1.0.2 with an Fix maximum firmware flash size.
 #                          So did I
 # 11 Jul 2019, deliopoulos,Updated to v1.0.6 as Prusa needs a new board definition for Firmware 3.8.x86_64
-#						   - Splitted the Download of Windows Arduino IDE 1.8.5 and Prusa specific part
+#						   - Split the Download of Windows Arduino IDE 1.8.5 and Prusa specific part
 #                            --> less download volume needed and saves some time
 #
-# 13 Jul 2019, deliopoulos,Splitting of Ardunio IDE and Prusa parts also for Linux64
+# 13 Jul 2019, deliopoulos,Splitting of Arduino IDE and Prusa parts also for Linux64
 # 13 Jul 2019, 3d-gussner, Added Linux 32-bit version (untested yet)
 #                          MacOS could be added in future if needs
 # 14 Jul 2019, 3d-gussner, Update preferences and make it really portable
-# 15 Jul 2019, 3d-gussner, New PF-build-env gihub branch
-# 16 Jul 2019, 3d-gussner, New Arduino_boards github fork
+# 15 Jul 2019, 3d-gussner, New PF-build-env GitHub branch
+# 16 Jul 2019, 3d-gussner, New Arduino_boards GitHub fork
 # 17 Jul 2019, 3d-gussner, Final tests under Windows 10 and Linux Subsystem for Windows   
 # 18 Jul 2019, 3d-gussner, Added python check
 # 18 Jul 2019, deliopoulos, No need more for changing 'platform.txt' file as it comes with the Arduino Boards.
 # 18 Jul 2019, deliopoulos, Modified 'PF_BUILD_FILE_URL' to use 'BUILD_ENV' variable
-# 22 Jul 2019, 3d-gussner, Modiffied checks to check folder and/or installation output exists.
+# 22 Jul 2019, 3d-gussner, Modified checks to check folder and/or installation output exists.
 # 22 Jul 2019, 3d-gussner, Added check if Arduino IDE 1.8.5 boards have been updated
 # 22 Jul 2019, 3d-gussner, Changed exit numbers 1-13 for prepare build env 21-28 for prepare compiling 31-36 compiling
-# 22 Jul 2019, 3d-gussner, Changed BOARD_URL to DRracers respository after he pulled my PR https://github.com/DRracer/Arduino_Boards/pull/1
+# 22 Jul 2019, 3d-gussner, Changed BOARD_URL to DRracers repository after he pulled my PR https://github.com/DRracer/Arduino_Boards/pull/1
 # 23 Jul 2019, 3d-gussner, Changed Build-env path to "PF-build-dl" as requested in PR https://github.com/prusa3d/Prusa-Firmware/pull/2028
 #                          Changed Hex-files folder to PF-build-hex as requested in PR
 # 23 Jul 2019, 3d-gussner, Added Finding OS version routine so supporting new OS should get easier
 # 26 Jul 2019, 3d-gussner, Change JSON repository to prusa3d after PR https://github.com/prusa3d/Arduino_Boards/pull/1 was merged
-# 23 Sep 2019, 3d-gussner, Prepare PF-build.sh for comming Prusa3d/Arduino_Boards version 1.0.2 Pull Request
-# 17 Oct 2019, 3d-gussner, Changed folder and check file names to have seperated build enviroments depening on Arduino IDE version and
+# 23 Sep 2019, 3d-gussner, Prepare PF-build.sh for coming Prusa3d/Arduino_Boards version 1.0.2 Pull Request
+# 17 Oct 2019, 3d-gussner, Changed folder and check file names to have separated build environments depending on Arduino IDE version and
 #                          board-versions.
 # 15 Dec 2019, 3d-gussner, Prepare for switch to Prusa3d/PF-build-env repository
-# 15 Dec 2019, 3d-gussner, Fix Audrino user preferences for the chosen board.
+# 15 Dec 2019, 3d-gussner, Fix Arduino user preferences for the chosen board.
 # 17 Dec 2019, 3d-gussner, Fix "timer0_fract = 0" warning by using Arduino_boards v1.0.3
 # 28 Apr 2020, 3d-gussner, Added RC3 detection
 # 03 May 2020, deliopoulos, Accept all RCx as RC versions
 # 05 May 2020, 3d-gussner, Make a copy of `not_tran.txt`and `not_used.txt` as `not_tran_$VARIANT.txt`and `not_used_$VARIANT.txt`
-#                          After compiling All multilanguage vairants it makes it easier to find missing or unused transltions.
+#                          After compiling All multi-language variants it makes it easier to find missing or unused translations.
 # 12 May 2020, DRracer   , Cleanup double MK2/s MK25/s `not_tran` and `not_used` files
 # 13 May 2020, leptun    , If cleanup files do not exist don't try to.
+# 01 Oct 2020, 3d-gussner, Bug fix if using argument EN_ONLY. Thank to @leptun for pointing out.
+#                          Change Build number to script commits 'git rev-list --count HEAD PF-build.sh'
+# 02 Oct 2020, 3d-gussner, Add UNKNOWN as argument option
+# 05 Oct 2020, 3d-gussner, Disable pause and warnings using command line with all needed arguments
+#                          Install needed apps under linux if needed.
+#                          Clean PF-Firmware build when changing git branch
+# 02 Nov 2020, 3d-gussner, Check for "gawk" on Linux
+#                          Add argument to change build number automatically to current commit or define own number
+#                          Update exit numbers 1-13 for prepare build env 21-29 for prepare compiling 30-36 compiling
+# 08 Jan 2021, 3d-gussner, Comment out 'sudo' auto installation
+#                          Add '-?' '-h' help option
+
 #### Start check if OSTYPE is supported
 OS_FOUND=$( command -v uname)
 
@@ -198,13 +210,14 @@ if ! type zip > /dev/null; then
 	elif [ $TARGET_OS == "linux" ]; then
 		echo "$(tput setaf 1)Missing 'zip' which is important to run this script"
 		echo "install it with the command $(tput setaf 2)'sudo apt-get install zip'$(tput sgr0)"
+		#sudo apt-get update && apt-get install zip
 		exit 3
 	fi
 fi
 # Check python ... needed during language build
 if ! type python > /dev/null; then
 	if [ $TARGET_OS == "windows" ]; then
-		echo "$(tput setaf 1)Missing 'python' which is important to run this script"
+		echo "$(tput setaf 1)Missing 'python3' which is important to run this script"
 		exit 4
 	elif [ $TARGET_OS == "linux" ]; then
 		echo "$(tput setaf 1)Missing 'python' which is important to run this script"
@@ -212,6 +225,17 @@ if ! type python > /dev/null; then
 		echo "install it with the command $(tput setaf 2)'sudo apt-get install python3'."
 		echo "Check which version of Python3 has been installed using 'ls /usr/bin/python3*'"
 		echo "Use 'sudo ln -sf /usr/bin/python3.x /usr/bin/python' (where 'x' is your version number) to make it default.$(tput sgr0)"
+		#sudo apt-get update && apt-get install python3 && ln -sf /usr/bin/python3 /usr/bin/python
+		exit 4
+	fi
+fi
+
+# Check gawk ... needed during language build
+if ! type gawk > /dev/null; then
+	if [ $TARGET_OS == "linux" ]; then
+		echo "$(tput setaf 1)Missing 'gawk' which is important to run this script"
+		echo "install it with the command $(tput setaf 2)'sudo apt-get install gawk'."
+		#sudo apt-get update && apt-get install gawk
 		exit 4
 	fi
 fi
@@ -241,7 +265,7 @@ echo "Script path :" $SCRIPT_PATH
 echo "OS          :" $OS
 echo "OS type     :" $TARGET_OS
 echo ""
-echo "Ardunio IDE :" $ARDUINO_ENV
+echo "Arduino IDE :" $ARDUINO_ENV
 echo "Build env   :" $BUILD_ENV
 echo "Board       :" $BOARD
 echo "Package name:" $BOARD_PACKAGE_NAME
@@ -422,8 +446,63 @@ fi
 #### Start 
 cd $SCRIPT_PATH
 
-# First argument defines which variant of the Prusa Firmware will be compiled 
-if [ -z "$1" ] ; then
+# Check if git is available
+if type git > /dev/null; then
+	git_available="1"
+fi
+
+while getopts v:l:d:b:o:?h flag
+	do
+	    case "${flag}" in
+	        v) variant_flag=${OPTARG};;
+	        l) language_flag=${OPTARG};;
+	        d) devel_flag=${OPTARG};;
+			b) build_flag=${OPTARG};;
+			o) output_flag=${OPTARG};;
+			?) help_flag=1;;
+			h) help_flag=1;;
+	    esac
+	done
+#echo "variant_flag: $variant_flag";
+#echo "language_flag: $language_flag";
+#echo "devel_flag: $devel_flag";
+#echo "build_flag: $build_flag";
+#echo "output_flag: $output_flag";
+#echo "help_flag: $help_flag"
+
+#
+# '?' 'h' argument usage and help
+if [ "$help_flag" == "1" ] ; then
+echo "***************************************"
+echo "* PF-build.sh Version: 1.0.6-Build_33 *"
+echo "***************************************"
+echo "Arguments:"
+echo "$(tput setaf 2)-v$(tput sgr0) Variant '$(tput setaf 2)All$(tput sgr0)' or variant file name"
+echo "$(tput setaf 2)-l$(tput sgr0) Languages '$(tput setaf 2)ALL$(tput sgr0)' for multi language or '$(tput setaf 2)EN_ONLY$(tput sgr0)' for English only"
+echo "$(tput setaf 2)-d$(tput sgr0) Devel build '$(tput setaf 2)GOLD$(tput sgr0)', '$(tput setaf 2)RC$(tput sgr0)', '$(tput setaf 2)BETA$(tput sgr0)', '$(tput setaf 2)ALPHA$(tput sgr0)', '$(tput setaf 2)DEBUG$(tput sgr0)', '$(tput setaf 2)DEVEL$(tput sgr0)' and '$(tput setaf 2)UNKNOWN$(tput sgr0)'"
+echo "$(tput setaf 2)-b$(tput sgr0) Build/commit number '$(tput setaf 2)Auto$(tput sgr0)' needs git or a number"
+echo "$(tput setaf 2)-o$(tput sgr0) Output '$(tput setaf 2)1$(tput sgr0)' force or '$(tput setaf 2)0$(tput sgr0)' block output and delays"
+echo "$(tput setaf 2)-?$(tput sgr0) Help"
+echo "$(tput setaf 2)-h$(tput sgr0) Help"
+echo 
+echo "Brief USAGE:"
+echo "  $(tput setaf 2)./PF-build.sh$(tput sgr0)  [-v] [-l] [-d] [-b] [-o]"
+echo
+echo "Example:"
+echo "  $(tput setaf 2)./PF-build.sh -v All -l ALL -d GOLD$(tput sgr0)"
+echo "  Will build all variants as multi language and final GOLD version"
+echo
+echo "  $(tput setaf 2) ./PF-build.sh -v 1_75mm_MK3S-EINSy10a-E3Dv6full.h -b Auto -l ALL -d GOLD -o 1$(tput sgr0)"
+echo "  Will build MK3S multi language final GOLD firmware "
+echo "  with current commit count number and output extra information"
+echo
+exit 
+
+fi
+
+#
+# '-v' argument defines which variant of the Prusa Firmware will be compiled 
+if [ -z "$variant_flag" ] ; then
 	# Select which variant of the Prusa Firmware will be compiled, like
 	PS3="Select a variant: "
 	while IFS= read -r -d $'\0' f; do
@@ -443,7 +522,7 @@ if [ -z "$1" ] ; then
 				;;
 			"Quit")
 				echo "You chose to stop"
-					exit
+					exit 20
 					;;
 			*)
 				echo "$(tput setaf 1)This is not a valid variant$(tput sgr0)"
@@ -451,21 +530,28 @@ if [ -z "$1" ] ; then
 		esac
 	done
 else
-	if [ -f "$SCRIPT_PATH/Firmware/variants/$1" ] ; then 
-		VARIANTS=$1
+	if [ -f "$SCRIPT_PATH/Firmware/variants/$variant_flag" ] ; then 
+		VARIANTS=$variant_flag
+	elif [ "$variant_flag" == "All" ] ; then
+		while IFS= read -r -d $'\0' f; do
+			options[i++]="$f"
+		done < <(find Firmware/variants/ -maxdepth 1 -type f -name "*.h" -print0 )
+		VARIANT="All"
+		VARIANTS=${options[*]}
 	else
-		echo "$(tput setaf 1)$1 could not be found in Firmware/variants please choose a valid one$(tput setaf 2)"
+		echo "$(tput setaf 1)Argument $variant_flag could not be found in Firmware/variants please choose a valid one.$(tput sgr0)"
+		echo "Only $(tput setaf 2)'All'$(tput sgr0) and file names below are allowed as variant '-v' argument.$(tput setaf 2)"
 		ls -1 $SCRIPT_PATH/Firmware/variants/*.h | xargs -n1 basename
 		echo "$(tput sgr0)"
 		exit 21
 	fi
 fi
 
-#Second argument defines if it is an english only version. Known values EN_ONLY / ALL
+#'-l' argument defines if it is an English only version. Known values EN_ONLY / ALL
 #Check default language mode
 MULTI_LANGUAGE_CHECK=$(grep --max-count=1 "^#define LANG_MODE *" $SCRIPT_PATH/Firmware/config.h|sed -e's/  */ /g'|cut -d ' ' -f3)
 
-if [ -z "$2" ] ; then
+if [ -z "$language_flag" ] ; then
 	PS3="Select a language: "
 	echo
 	echo "Which lang-build do you want?"
@@ -473,12 +559,10 @@ if [ -z "$2" ] ; then
 		case $yn in
 			"Multi languages")
 				LANGUAGES="ALL"
-				sed -i -- "s/^#define LANG_MODE *0/#define LANG_MODE              1/g" $SCRIPT_PATH/Firmware/config.h
 				break
 				;;
 			"English only") 
 				LANGUAGES="EN_ONLY"
-				sed -i -- "s/^#define LANG_MODE *1/#define LANG_MODE              0/g" $SCRIPT_PATH/Firmware/config.h
 				break
 				;;
 			*)
@@ -487,47 +571,106 @@ if [ -z "$2" ] ; then
 		esac
 	done
 else
-	if [[ "$2" == "ALL" || "$2" == "EN_ONLY" ]] ; then
-		LANGUAGES=$2
+	if [[ "$language_flag" == "ALL" || "$language_flag" == "EN_ONLY" ]] ; then
+		LANGUAGES=$language_flag
 	else
 		echo "$(tput setaf 1)Language argument is wrong!$(tput sgr0)"
-		echo "Only $(tput setaf 2)'ALL'$(tput sgr0) or $(tput setaf 2)'EN_ONLY'$(tput sgr0) are allowed as 2nd argument!"
+		echo "Only $(tput setaf 2)'ALL'$(tput sgr0) or $(tput setaf 2)'EN_ONLY'$(tput sgr0) are allowed as language '-l' argument!"
 		exit 22
 	fi
 fi
-#Check if DEV_STATUS is selected via argument 3
-if [ ! -z "$3" ] ; then
-	if [[ "$3" == "GOLD" || "$3" == "RC" || "$3" == "BETA" || "$3" == "ALPHA" || "$3" == "DEVEL" || "$3" == "DEBUG" ]] ; then
-		DEV_STATUS_SELECTED=$3
+#Check if DEV_STATUS is selected via argument '-d'
+if [ ! -z "$devel_flag" ] ; then
+	if [[ "$devel_flag" == "GOLD" || "$devel_flag" == "RC" || "$devel_flag" == "BETA" || "$devel_flag" == "ALPHA" || "$devel_flag" == "DEVEL" || "$devel_flag" == "DEBUG" || "$devel_flag" == "UNKNOWN" ]] ; then
+		DEV_STATUS_SELECTED=$devel_flag
 	else
 		echo "$(tput setaf 1)Development argument is wrong!$(tput sgr0)"
-		echo "Only $(tput setaf 2)'GOLD', 'RC', 'BETA', 'ALPHA', 'DEVEL' or 'DEBUG'$(tput sgr0) are allowed as 3rd argument!$(tput sgr0)"
+		echo "Only $(tput setaf 2)'GOLD', 'RC', 'BETA', 'ALPHA', 'DEVEL', 'DEBUG' or 'UNKNOWN' $(tput sgr0) are allowed as devel '-d' argument!$(tput sgr0)"
 		exit 23
 	fi
 fi
 
+#Check if Build is selected via argument '-b'
+if [ ! -z "$build_flag" ] ; then
+	if [[ "$build_flag" == "Auto" && "$git_available" == "1" ]] ; then
+		echo "Build changed to $build_flag"
+		BUILD=$(git rev-list --count HEAD)
+	elif [[ $build_flag =~ ^[0-9]+$ ]] ; then
+		BUILD=$build_flag
+	else
+		echo "$(tput setaf 1)Build number argument is wrong!$(tput sgr0)"
+		echo "Only $(tput setaf 2)'Auto' (git needed) or numbers $(tput sgr0) are allowed as build '-b' argument!$(tput sgr0)"
+		exit 24
+
+	fi
+	echo "New Build number is: $BUILD"
+fi
+
+# check if script has been started with arguments 
+if [[ "$#" -eq  "0" || "$output_flag" == 1 ]] ; then
+	OUTPUT=1
+else
+	OUTPUT=0
+fi
+#echo "Output is:" $OUTPUT
+
+#Check git branch has changed
+if [ ! -z "git_available" ]; then
+	BRANCH=""
+	CLEAN_PF_FW_BUILD=0
+else
+	BRANCH=$(git branch --show-current)
+	echo "Current branch is:" $BRANCH
+	if [ ! -f "$SCRIPT_PATH/../PF-build.branch" ]; then
+		echo "$BRANCH" >| $SCRIPT_PATH/../PF-build.branch
+		echo "created PF-build.branch file"
+	else
+		PRE_BRANCH=$(cat "$SCRIPT_PATH/../PF-build.branch")
+		echo "Previous branch was:" $PRE_BRANCH
+		if [ ! "$BRANCH" == "$PRE_BRANCH" ] ; then
+			CLEAN_PF_FW_BUILD=1
+			echo "$BRANCH" >| $SCRIPT_PATH/../PF-build.branch
+		fi
+	fi
+fi
+
 #Set BUILD_ENV_PATH
-cd ../PF-build-env-$BUILD_ENV/$ARDUINO_ENV-$BOARD_VERSION-$TARGET_OS-$Processor || exit 24
+cd ../PF-build-env-$BUILD_ENV/$ARDUINO_ENV-$BOARD_VERSION-$TARGET_OS-$Processor || exit 25
 BUILD_ENV_PATH="$( pwd -P )"
 
 cd ../..
 
 #Checkif BUILD_PATH exists and if not creates it
 if [ ! -d "Prusa-Firmware-build" ]; then
-    mkdir Prusa-Firmware-build  || exit 25
+    mkdir Prusa-Firmware-build  || exit 26
 fi
 
 #Set the BUILD_PATH for Arduino IDE
-cd Prusa-Firmware-build || exit 26
+cd Prusa-Firmware-build || exit 27
 BUILD_PATH="$( pwd -P )"
 
+#Check git branch has changed
+if [ "$CLEAN_PF_FW_BUILD" == "1" ]; then
+	read -t 10 -p "Branch changed, cleaning Prusa-Firmware-build folder"
+	rm -r *
+else
+	echo "Nothing to clean up"
+fi
+
 for v in ${VARIANTS[*]}
 do
 	VARIANT=$(basename "$v" ".h")
 	# Find firmware version in Configuration.h file and use it to generate the hex filename
 	FW=$(grep --max-count=1 "\bFW_VERSION\b" $SCRIPT_PATH/Firmware/Configuration.h | sed -e's/  */ /g'|cut -d '"' -f2|sed 's/\.//g')
-	# Find build version in Configuration.h file and use it to generate the hex filename
-	BUILD=$(grep --max-count=1 "\bFW_COMMIT_NR\b" $SCRIPT_PATH/Firmware/Configuration.h | sed -e's/  */ /g'|cut -d ' ' -f3)
+	if [ -z "$BUILD" ] ; then	
+		# Find build version in Configuration.h file and use it to generate the hex filename
+		BUILD=$(grep --max-count=1 "\bFW_COMMIT_NR\b" $SCRIPT_PATH/Firmware/Configuration.h | sed -e's/  */ /g'|cut -d ' ' -f3)
+	else
+		# Find and replace build version in Configuration.h file
+		BUILD_ORG=$(grep --max-count=1 "\bFW_COMMIT_NR\b" $SCRIPT_PATH/Firmware/Configuration.h | sed -e's/  */ /g'|cut -d ' ' -f3)
+		echo "Original build number: $BUILD_ORG"
+		sed -i -- "s/^#define FW_COMMIT_NR.*/#define FW_COMMIT_NR $BUILD/g" $SCRIPT_PATH/Firmware/Configuration.h
+	fi
 	# Check if the motherboard is an EINSY and if so only one hex file will generated
 	MOTHERBOARD=$(grep --max-count=1 "\bMOTHERBOARD\b" $SCRIPT_PATH/Firmware/variants/$VARIANT.h | sed -e's/  */ /g' |cut -d ' ' -f3)
 	# Check development status
@@ -571,7 +714,7 @@ do
 	fi
 	#Prepare hex files folders
 	if [ ! -d "$SCRIPT_PATH/../PF-build-hex/FW$FW-Build$BUILD/$MOTHERBOARD" ]; then
-		mkdir -p $SCRIPT_PATH/../PF-build-hex/FW$FW-Build$BUILD/$MOTHERBOARD || exit 27
+		mkdir -p $SCRIPT_PATH/../PF-build-hex/FW$FW-Build$BUILD/$MOTHERBOARD || exit 28
 	fi
 	OUTPUT_FOLDER="PF-build-hex/FW$FW-Build$BUILD/$MOTHERBOARD"
 	
@@ -580,18 +723,24 @@ do
 		echo ""
 		ls -1 $SCRIPT_PATH/../$OUTPUT_FOLDER/FW$FW-Build$BUILD-$VARIANT.hex | xargs -n1 basename
 		echo "$(tput setaf 6)This hex file to be compiled already exists! To cancel this process press CRTL+C and rename existing hex file.$(tput sgr 0)"
-		read -t 10 -p "Press Enter to continue..."
+		if [ $OUTPUT == "1" ] ; then
+			read -t 10 -p "Press Enter to continue..."
+		fi
 	elif [[ -f "$SCRIPT_PATH/../$OUTPUT_FOLDER/FW$FW-Build$BUILD-$VARIANT-EN_ONLY.hex"  &&  "$LANGUAGES" == "EN_ONLY" ]]; then
 		echo ""
 		ls -1 $SCRIPT_PATH/../$OUTPUT_FOLDER/FW$FW-Build$BUILD-$VARIANT-EN_ONLY.hex | xargs -n1 basename
 		echo "$(tput setaf 6)This hex file to be compiled already exists! To cancel this process press CRTL+C and rename existing hex file.$(tput sgr 0)"
-		read -t 10 -p "Press Enter to continue..."
+		if [ $OUTPUT == "1" ] ; then
+			read -t 10 -p "Press Enter to continue..."
+		fi
 	fi
 	if [[ -f "$SCRIPT_PATH/../$OUTPUT_FOLDER/FW$FW-Build$BUILD-$VARIANT.zip"  &&  "$LANGUAGES" == "ALL" ]]; then
 		echo ""
 		ls -1 $SCRIPT_PATH/../$OUTPUT_FOLDER/FW$FW-Build$BUILD-$VARIANT.zip | xargs -n1 basename
 		echo "$(tput setaf 6)This zip file to be compiled already exists! To cancel this process press CRTL+C and rename existing hex file.$(tput sgr 0)"
-		read -t 10 -p "Press Enter to continue..."
+		if [ $OUTPUT == "1" ] ; then
+			read -t 10 -p "Press Enter to continue..."
+		fi
 	fi
 	
 	#List some useful data
@@ -608,11 +757,13 @@ do
 
 	#Prepare Firmware to be compiled by copying variant as Configuration_prusa.h
 	if [ ! -f "$SCRIPT_PATH/Firmware/Configuration_prusa.h" ]; then
-		cp -f $SCRIPT_PATH/Firmware/variants/$VARIANT.h $SCRIPT_PATH/Firmware/Configuration_prusa.h || exit 28
+		cp -f $SCRIPT_PATH/Firmware/variants/$VARIANT.h $SCRIPT_PATH/Firmware/Configuration_prusa.h || exit 29
 	else
 		echo "$(tput setaf 6)Configuration_prusa.h already exist it will be overwritten in 10 seconds by the chosen variant.$(tput sgr 0)"
-		read -t 10 -p "Press Enter to continue..."
-		cp -f $SCRIPT_PATH/Firmware/variants/$VARIANT.h $SCRIPT_PATH/Firmware/Configuration_prusa.h || exit 28
+		if [ $OUTPUT == "1" ] ; then
+			read -t 10 -p "Press Enter to continue..."
+		fi
+		cp -f $SCRIPT_PATH/Firmware/variants/$VARIANT.h $SCRIPT_PATH/Firmware/Configuration_prusa.h || exit 29
 	fi
 
 	#Prepare Configuration.h to use the correct FW_DEV_VERSION to prevent LCD messages when connecting with OctoPrint
@@ -621,14 +772,16 @@ do
 	# set FW_REPOSITORY
 	sed -i -- 's/#define FW_REPOSITORY "Unknown"/#define FW_REPOSITORY "Prusa3d"/g' $SCRIPT_PATH/Firmware/Configuration.h
 
-	#Prepare english only or multilanguage version to be build
-	if [ $LANGUAGES == "ALL" ]; then
+	#Prepare English only or multi-language version to be build
+	if [ $LANGUAGES == "EN_ONLY" ]; then
 		echo " "
-		echo "Multi-language firmware will be built"
+		echo "English only language firmware will be built"
+		sed -i -- "s/^#define LANG_MODE *1/#define LANG_MODE              0/g" $SCRIPT_PATH/Firmware/config.h
 		echo " "
 	else
 		echo " "
-		echo "English only language firmware will be built"
+		echo "Multi-language firmware will be built"
+		sed -i -- "s/^#define LANG_MODE *0/#define LANG_MODE              1/g" $SCRIPT_PATH/Firmware/config.h
 		echo " "
 	fi
 		
@@ -651,9 +804,11 @@ do
 
 	echo "Start to build Prusa Firmware ..."
 	echo "Using variant $VARIANT$(tput setaf 3)"
-	sleep 2
+	if [ $OUTPUT == "1" ] ; then
+		sleep 2
+	fi
 	#$BUILD_ENV_PATH/arduino-builder -dump-prefs -debug-level 10 -compile -hardware $ARDUINO/hardware -hardware $ARDUINO/portable/packages -tools $ARDUINO/tools-builder -tools $ARDUINO/hardware/tools/avr -tools $ARDUINO/portable/packages -built-in-libraries $ARDUINO/libraries -libraries $ARDUINO/portable/sketchbook/libraries -fqbn=$BOARD_PACKAGE_NAME:avr:$BOARD -build-path=$BUILD_PATH -warnings=all $SCRIPT_PATH/Firmware/Firmware.ino || exit 14
-	$BUILD_ENV_PATH/arduino-builder -compile -hardware $ARDUINO/hardware -hardware $ARDUINO/portable/packages -tools $ARDUINO/tools-builder -tools $ARDUINO/hardware/tools/avr -tools $ARDUINO/portable/packages -built-in-libraries $ARDUINO/libraries -libraries $ARDUINO/portable/sketchbook/libraries -fqbn=$BOARD_PACKAGE_NAME:avr:$BOARD -build-path=$BUILD_PATH -warnings=all $SCRIPT_PATH/Firmware/Firmware.ino || exit 14
+	$BUILD_ENV_PATH/arduino-builder -compile -hardware $ARDUINO/hardware -hardware $ARDUINO/portable/packages -tools $ARDUINO/tools-builder -tools $ARDUINO/hardware/tools/avr -tools $ARDUINO/portable/packages -built-in-libraries $ARDUINO/libraries -libraries $ARDUINO/portable/sketchbook/libraries -fqbn=$BOARD_PACKAGE_NAME:avr:$BOARD -build-path=$BUILD_PATH -warnings=all $SCRIPT_PATH/Firmware/Firmware.ino || exit 30
 	echo "$(tput sgr 0)"
 
 	if [ $LANGUAGES ==  "ALL" ]; then
@@ -661,7 +816,9 @@ do
 
 		echo "Building multi language firmware" $MULTI_LANGUAGE_CHECK
 		echo "$(tput sgr 0)"
-		sleep 2
+		if [ $OUTPUT == "1" ] ; then
+			sleep 2
+		fi
 		cd $SCRIPT_PATH/lang
 		echo "$(tput setaf 3)"
 		./config.sh || exit 31
@@ -670,7 +827,9 @@ do
 		if [ -f "lang_en.tmp" ]; then
 			echo ""
 			echo "$(tput setaf 6)Previous lang build files already exist these will be cleaned up in 10 seconds.$(tput sgr 0)"
-			read -t 10 -p "Press Enter to continue..."
+			if [ $OUTPUT == "1" ] ; then
+				read -t 10 -p "Press Enter to continue..."
+			fi
 			echo "$(tput setaf 3)"
 			./lang-clean.sh
 			echo "$(tput sgr 0)"
@@ -678,7 +837,9 @@ do
 		if [ -f "progmem.out" ]; then
 			echo ""
 			echo "$(tput setaf 6)Previous firmware build files already exist these will be cleaned up in 10 seconds.$(tput sgr 0)"
-			read -t 10 -p "Press Enter to continue..."
+			if [ $OUTPUT == "1" ] ; then
+				read -t 10 -p "Press Enter to continue..."
+			fi
 			echo "$(tput setaf 3)"
 			./fw-clean.sh
 			echo "$(tput sgr 0)"
@@ -740,13 +901,19 @@ do
 	then
 		rm $SCRIPT_PATH/lang/not_used.txt
 	fi
+	# Restore files to previous state
 	sed -i -- "s/^#define FW_DEV_VERSION FW_VERSION_$DEV_STATUS/#define FW_DEV_VERSION FW_VERSION_UNKNOWN/g" $SCRIPT_PATH/Firmware/Configuration.h
 	sed -i -- 's/^#define FW_REPOSITORY "Prusa3d"/#define FW_REPOSITORY "Unknown"/g' $SCRIPT_PATH/Firmware/Configuration.h
+	if [ ! -z "$BUILD_ORG" ] ; then
+		sed -i -- "s/^#define FW_COMMIT_NR.*/#define FW_COMMIT_NR $BUILD_ORG/g" $SCRIPT_PATH/Firmware/Configuration.h
+	fi
 	echo $MULTI_LANGUAGE_CHECK
 	#sed -i -- "s/^#define LANG_MODE * /#define LANG_MODE              $MULTI_LANGUAGE_CHECK/g" $SCRIPT_PATH/Firmware/config.h
 	sed -i -- "s/^#define LANG_MODE *1/#define LANG_MODE              ${MULTI_LANGUAGE_CHECK}/g" $SCRIPT_PATH/Firmware/config.h
 	sed -i -- "s/^#define LANG_MODE *0/#define LANG_MODE              ${MULTI_LANGUAGE_CHECK}/g" $SCRIPT_PATH/Firmware/config.h
-	sleep 5
+	if [ $OUTPUT == "1" ] ; then
+		sleep 5
+	fi
 done
 
 # Switch to hex path and list build files

+ 14 - 11
README.md

@@ -73,7 +73,7 @@ _Note: Multi language build is not supported._
 
 **c.** Modify compiler flags in `platform.txt` file
      
-* The platform.txt file can be found in Arduino instalation directory, or after Arduino has been updated at: `"C:\Users\(user)\AppData\Local\Arduino15\packages\arduino\hardware\avr\(version)"` If you can locate the file in both places, file from user profile is probably used.
+* The platform.txt file can be found in Arduino installation directory, or after Arduino has been updated at: `"C:\Users\(user)\AppData\Local\Arduino15\packages\arduino\hardware\avr\(version)"` If you can locate the file in both places, file from user profile is probably used.
        
 * Add `"-Wl,-u,vfprintf -lprintf_flt -lm"` to `"compiler.c.elf.flags="` before existing flag "-Wl,--gc-sections"  
 
@@ -111,10 +111,13 @@ _notes: Script and instructions contributed by 3d-gussner. Use at your own risk.
 - follow the Microsoft guide https://docs.microsoft.com/en-us/windows/wsl/install-win10
   You can also use the 'prepare_winbuild.ps1' powershell script with Administrator rights
 - Tested versions are at this moment
-  - Ubuntu other may different
+  - Ubuntu and Debian, other may different
   - After the installation and reboot please open your Ubuntu bash and do following steps
-  - run command `apt-get update`
-  - to install zip run `apt-get install zip`
+  - run command `sudo apt-get update`
+  - run command `sudo apt-get upgrade`
+  - to install zip run `sudo apt-get install zip`
+  - to install dos2unix run `sudo apt-get install dos2unix`
+  - run `dos2unix PF-build.sh` to convert the windows line endings to unix line endings
   - add few lines at the top of `~/.bashrc` by running `sudo nano ~/.bashrc`
 	
 	export OS="Linux"
@@ -122,11 +125,11 @@ _notes: Script and instructions contributed by 3d-gussner. Use at your own risk.
 	export GPG_TTY=$(tty)
 	
 	use `CRTL-X` to close nano and confirm to write the new entries
-  - restart Ubuntu bash
-Now your Ubuntu subsystem is ready to use the automatic `PF-build.sh` script and compile your firmware correctly
+  - restart Ubuntu/Debian bash
+  - Now your Ubuntu/Debian subsystem is ready to use the automatic `PF-build.sh` script and compile your firmware correctly
 
-#### Some Tips for Ubuntu
-- Linux is case sensetive so please don't forget to use capital letters where needed, like changing to a directory
+#### Some Tips for Ubuntu and Debian
+- Linux is case sensitive so please don't forget to use capital letters where needed, like changing to a directory
 - To change the path to your Prusa-Firmware location you downloaded and unzipped
   - Example: You files are under `C:\Users\<your-username>\Downloads\Prusa-Firmware-MK3`
   - use under Ubuntu the following command `cd /mnt/c/Users/<your-username>/Downloads/Prusa-Firmware-MK3`
@@ -137,7 +140,7 @@ Now your Ubuntu subsystem is ready to use the automatic `PF-build.sh` script and
 - If your Windows isn't in English the Paths may look different
   Example in other languages
   - English `/mnt/c/Users/<your-username>/Downloads/Prusa-Firmware-MK3` will be on a German Windows`/mnt/c/Anwender/<your-username>/Downloads/Prusa-Firmware-MK3`
-#### Compile Prusa-firmware with Ubuntu Linux subsystem installed
+#### Compile Prusa-firmware with Ubuntu/Debian Linux subsystem installed
 - open Ubuntu bash
 - change to your source code folder (case sensitive)
 - run `./PF-build.sh`
@@ -206,7 +209,7 @@ or visit https://prusa3d.github.io/Prusa-Firmware-Doc for doxygen generated outp
 # 5. FAQ
 Q:I built firmware using Arduino and I see "?" instead of numbers in printer user interface.
 
-A:Step 1.c was ommited or you updated Arduino and now platform.txt located somewhere in your user profile is used.
+A:Step 1.c was omitted or you updated Arduino and now platform.txt located somewhere in your user profile is used.
 
 Q:I built firmware using Arduino and printer now speaks Klingon (nonsense characters and symbols are displayed @^#$&*°;~ÿ)
 
@@ -218,4 +221,4 @@ A:Our production builds are 99.9% equivalent to https://github.com/prusa3d/Prusa
 
 Q:Why are build instructions for Arduino mess.
 
-Y:We are too lazy to ship proper board definition for Arduino. We plan to swich to cmake + ninja to be inherently multiplatform, easily integrate build tools, suport more IDEs, get 10 times shorter build times and be able to update compiler whenewer we want.
+Y:We are too lazy to ship proper board definition for Arduino. We plan to switch to cmake + ninja to be inherently multiplatform, easily integrate build tools, suport more IDEs, get 10 times shorter build times and be able to update compiler whenever we want.