PavelSindler 5 роки тому
батько
коміт
33f9af65c8
43 змінених файлів з 4245 додано та 5576 видалено
  1. 6 142
      Firmware/Configuration.h
  2. 42 133
      Firmware/ConfigurationStore.cpp
  3. 2 21
      Firmware/Configuration_adv.h
  4. 0 21
      Firmware/Firmware.ino
  5. 0 718
      Firmware/LiquidCrystal_Prusa.cpp
  6. 0 142
      Firmware/LiquidCrystal_Prusa.h
  7. 4 3
      Firmware/Marlin.h
  8. 192 132
      Firmware/Marlin_main.cpp
  9. 0 29
      Firmware/MenuStack.cpp
  10. 0 34
      Firmware/MenuStack.h
  11. 1 0
      Firmware/bootapp.h
  12. 17 10
      Firmware/cardreader.cpp
  13. 1 0
      Firmware/cmdqueue.cpp
  14. 16 0
      Firmware/config.h
  15. 292 0
      Firmware/conv2str.cpp
  16. 28 0
      Firmware/conv2str.h
  17. 6 2
      Firmware/fsensor.cpp
  18. 3 0
      Firmware/fsensor.h
  19. 1083 0
      Firmware/lcd.cpp
  20. 224 0
      Firmware/lcd.h
  21. 274 0
      Firmware/menu.cpp
  22. 98 0
      Firmware/menu.h
  23. 15 12
      Firmware/mesh_bed_calibration.cpp
  24. 88 70
      Firmware/pat9125.cpp
  25. 25 39
      Firmware/pat9125.h
  26. 3 11
      Firmware/pins_Einsy_1_0.h
  27. 2 11
      Firmware/pins_Rambo_1_0.h
  28. 2 11
      Firmware/pins_Rambo_1_3.h
  29. 9 2
      Firmware/planner.cpp
  30. 59 2
      Firmware/stepper.cpp
  31. 189 0
      Firmware/swi2c.c
  32. 0 209
      Firmware/swi2c.cpp
  33. 19 6
      Firmware/swi2c.h
  34. 2 2
      Firmware/temperature.cpp
  35. 21 20
      Firmware/tmc2130.cpp
  36. 15 0
      Firmware/tmc2130.h
  37. 1482 2228
      Firmware/ultralcd.cpp
  38. 9 114
      Firmware/ultralcd.h
  39. 0 1437
      Firmware/ultralcd_implementation_hitachi_HD44780.h
  40. 5 5
      Firmware/util.cpp
  41. 0 1
      Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h
  42. 0 1
      Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h
  43. 11 8
      Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h

+ 6 - 142
Firmware/Configuration.h

@@ -7,8 +7,8 @@
 #define STR(x) STR_HELPER(x)
 
 // Firmware version
-#define FW_VERSION "3.3.0"
-#define FW_COMMIT_NR   830
+#define FW_VERSION "3.3.1"
+#define FW_COMMIT_NR   845
 // 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
@@ -621,154 +621,18 @@ your extruder heater takes 2 minutes to hit the target on heating.
 #define HOST_KEEPALIVE_INTERVAL 2 // Number of seconds between "busy" messages. Set with M113.
 
 //LCD and SD support
-#define ULTRA_LCD  //general LCD support, also 16x2
 #define SDSUPPORT // Enable SD Card Support in Hardware Console
 //#define SDSLOW // Use slower SD transfer mode (not normally needed - uncomment if you're getting volume init error)
 #define SD_CHECK_AND_RETRY // Use CRC checks and retries on the SD communication
 #define ENCODER_PULSES_PER_STEP 4 // Increase if you have a high resolution encoder
-#define ENCODER_STEPS_PER_MENU_ITEM 1 // Set according to ENCODER_PULSES_PER_STEP or your liking
-//#define ULTIMAKERCONTROLLER //as available from the Ultimaker online store.
-//#define ULTIPANEL  //the UltiPanel as on Thingiverse
-//#define LCD_FEEDBACK_FREQUENCY_HZ 1000	// this is the tone frequency the buzzer plays when on UI feedback. ie Screen Click
-//#define LCD_FEEDBACK_FREQUENCY_DURATION_MS 100 // the duration the buzzer plays the UI feedback sound. ie Screen Click
-
-// The MaKr3d Makr-Panel with graphic controller and SD support
-// http://reprap.org/wiki/MaKr3d_MaKrPanel
-//#define MAKRPANEL
+//#define ENCODER_STEPS_PER_MENU_ITEM 1 // Set according to ENCODER_PULSES_PER_STEP or your liking
 
 // The RepRapDiscount Smart Controller (white PCB)
 // http://reprap.org/wiki/RepRapDiscount_Smart_Controller
 #define REPRAP_DISCOUNT_SMART_CONTROLLER
-
-// The GADGETS3D G3D LCD/SD Controller (blue PCB)
-// http://reprap.org/wiki/RAMPS_1.3/1.4_GADGETS3D_Shield_with_Panel
-//#define G3D_PANEL
-
-// The RepRapWorld REPRAPWORLD_KEYPAD v1.1
-// http://reprapworld.com/?products_details&products_id=202&cPath=1591_1626
-//#define REPRAPWORLD_KEYPAD
-//#define REPRAPWORLD_KEYPAD_MOVE_STEP 10.0 // how much should be moved when a key is pressed, eg 10.0 means 10mm per click
-
-// The Elefu RA Board Control Panel
-// http://www.elefu.com/index.php?route=product/product&product_id=53
-// REMEMBER TO INSTALL LiquidCrystal_I2C.h in your ARDUINO library folder: https://github.com/kiyoshigawa/LiquidCrystal_I2C
-//#define RA_CONTROL_PANEL
-
-//automatic expansion
-#if defined (MAKRPANEL)
- #define SDSUPPORT
- #define ULTIPANEL
- #define NEWPANEL
- #define DEFAULT_LCD_CONTRAST 17
-#endif
-
-#if defined(ULTIMAKERCONTROLLER) || defined(REPRAP_DISCOUNT_SMART_CONTROLLER) || defined(G3D_PANEL)
- #define ULTIPANEL
- #define NEWPANEL
-#endif
-
-#if defined(REPRAPWORLD_KEYPAD)
-  #define NEWPANEL
-  #define ULTIPANEL
-#endif
-#if defined(RA_CONTROL_PANEL)
- #define ULTIPANEL
- #define NEWPANEL
- #define LCD_I2C_TYPE_PCA8574
- #define LCD_I2C_ADDRESS 0x27   // I2C Address of the port expander
-#endif
-
-//I2C PANELS
-
-//#define LCD_I2C_SAINSMART_YWROBOT
-#ifdef LCD_I2C_SAINSMART_YWROBOT
-  // This uses the LiquidCrystal_I2C library ( https://bitbucket.org/fmalpartida/new-LiquidCrystal_Prusa/wiki/Home )
-  // Make sure it is placed in the Arduino libraries directory.
-  #define LCD_I2C_TYPE_PCF8575
-  #define LCD_I2C_ADDRESS 0x27   // I2C Address of the port expander
-  #define NEWPANEL
-  #define ULTIPANEL
-#endif
-
-// PANELOLU2 LCD with status LEDs, separate encoder and click inputs
-//#define LCD_I2C_PANELOLU2
-#ifdef LCD_I2C_PANELOLU2
-  // This uses the LiquidTWI2 library v1.2.3 or later ( https://github.com/lincomatic/LiquidTWI2 )
-  // Make sure the LiquidTWI2 directory is placed in the Arduino or Sketchbook libraries subdirectory.
-  // (v1.2.3 no longer requires you to define PANELOLU in the LiquidTWI2.h library header file)
-  // Note: The PANELOLU2 encoder click input can either be directly connected to a pin
-  //       (if BTN_ENC defined to != -1) or read through I2C (when BTN_ENC == -1).
-  #define LCD_I2C_TYPE_MCP23017
-  #define LCD_I2C_ADDRESS 0x20 // I2C Address of the port expander
-  #define LCD_USE_I2C_BUZZER //comment out to disable buzzer on LCD
-  #define NEWPANEL
-  #define ULTIPANEL
-
-  #ifndef ENCODER_PULSES_PER_STEP
-	#define ENCODER_PULSES_PER_STEP 4
-  #endif
-
-  #ifndef ENCODER_STEPS_PER_MENU_ITEM
-	#define ENCODER_STEPS_PER_MENU_ITEM 2
-  #endif
-
-
-  #ifdef LCD_USE_I2C_BUZZER
-	#define LCD_FEEDBACK_FREQUENCY_HZ 1000
-	#define LCD_FEEDBACK_FREQUENCY_DURATION_MS 100
-  #endif
-
-#endif
-
-// Panucatt VIKI LCD with status LEDs, integrated click & L/R/U/P buttons, separate encoder inputs
-//#define LCD_I2C_VIKI
-#ifdef LCD_I2C_VIKI
-  // This uses the LiquidTWI2 library v1.2.3 or later ( https://github.com/lincomatic/LiquidTWI2 )
-  // Make sure the LiquidTWI2 directory is placed in the Arduino or Sketchbook libraries subdirectory.
-  // Note: The pause/stop/resume LCD button pin should be connected to the Arduino
-  //       BTN_ENC pin (or set BTN_ENC to -1 if not used)
-  #define LCD_I2C_TYPE_MCP23017
-  #define LCD_I2C_ADDRESS 0x20 // I2C Address of the port expander
-  #define LCD_USE_I2C_BUZZER //comment out to disable buzzer on LCD (requires LiquidTWI2 v1.2.3 or later)
-  #define NEWPANEL
-  #define ULTIPANEL
-#endif
-
-// Shift register panels
-// ---------------------
-// 2 wire Non-latching LCD SR from:
-// https://bitbucket.org/fmalpartida/new-LiquidCrystal_Prusa/wiki/schematics#!shiftregister-connection 
-
-//#define SAV_3DLCD
-#ifdef SAV_3DLCD
-   #define SR_LCD_2W_NL    // Non latching 2 wire shiftregister
-   #define NEWPANEL
-   #define ULTIPANEL
-#endif
-
-
-#ifdef ULTIPANEL
-//  #define NEWPANEL  //enable this if you have a click-encoder panel
-  #define SDSUPPORT
-  #define ULTRA_LCD
-  #ifdef DOGLCD // Change number of lines to match the DOG graphic display
-    #define LCD_WIDTH 20
-    #define LCD_HEIGHT 5
-  #else
-    #define LCD_WIDTH 20
-    #define LCD_HEIGHT 4
-  #endif
-#else //no panel but just LCD
-  #ifdef ULTRA_LCD
-  #ifdef DOGLCD // Change number of lines to match the 128x64 graphics display
-    #define LCD_WIDTH 20
-    #define LCD_HEIGHT 5
-  #else
-    #define LCD_WIDTH 16
-    #define LCD_HEIGHT 2
-  #endif
-  #endif
-#endif
+#define SDSUPPORT
+#define LCD_WIDTH 20
+#define LCD_HEIGHT 4
 
 
 // Increase the FAN pwm frequency. Removes the PWM noise but increases heating in the FET/Arduino

+ 42 - 133
Firmware/ConfigurationStore.cpp

@@ -68,13 +68,6 @@ void Config_StoreSettings(uint16_t offset, uint8_t level)
   EEPROM_WRITE_VAR(i,max_jerk[Z_AXIS]);
   EEPROM_WRITE_VAR(i,max_jerk[E_AXIS]);
   EEPROM_WRITE_VAR(i,add_homing);
-  #ifndef ULTIPANEL
-  int plaPreheatHotendTemp = PLA_PREHEAT_HOTEND_TEMP, plaPreheatHPBTemp = PLA_PREHEAT_HPB_TEMP, plaPreheatFanSpeed = PLA_PREHEAT_FAN_SPEED;
-  int absPreheatHotendTemp = ABS_PREHEAT_HOTEND_TEMP, absPreheatHPBTemp = ABS_PREHEAT_HPB_TEMP, absPreheatFanSpeed = ABS_PREHEAT_FAN_SPEED;
-  
-
-  
-  #endif
 /*  EEPROM_WRITE_VAR(i,plaPreheatHotendTemp);
   EEPROM_WRITE_VAR(i,plaPreheatHPBTemp);
   EEPROM_WRITE_VAR(i,plaPreheatFanSpeed);
@@ -100,10 +93,7 @@ void Config_StoreSettings(uint16_t offset, uint8_t level)
 	EEPROM_WRITE_VAR(i, bedKi);
 	EEPROM_WRITE_VAR(i, bedKd);
   #endif
-  #ifndef DOGLCD
-    int lcd_contrast = 32;
-  #endif
-  EEPROM_WRITE_VAR(i,lcd_contrast);
+//  EEPROM_WRITE_VAR(i,lcd_contrast);
   #ifdef FWRETRACT
   EEPROM_WRITE_VAR(i,autoretract_enabled);
   EEPROM_WRITE_VAR(i,retract_length);
@@ -154,132 +144,62 @@ void Config_StoreSettings(uint16_t offset, uint8_t level)
 #ifndef DISABLE_M503
 void Config_PrintSettings(uint8_t level)
 {  // Always have this function, even with EEPROM_SETTINGS disabled, the current values will be shown
-	
-	SERIAL_ECHO_START;
-    SERIAL_ECHOLNPGM("Steps per unit:");
-    SERIAL_ECHO_START;
-    SERIAL_ECHOPAIR("  M92 X",axis_steps_per_unit[X_AXIS]);
-    SERIAL_ECHOPAIR(" Y",axis_steps_per_unit[Y_AXIS]);
-    SERIAL_ECHOPAIR(" Z",axis_steps_per_unit[Z_AXIS]);
-    SERIAL_ECHOPAIR(" E",axis_steps_per_unit[E_AXIS]);
-    SERIAL_ECHOLN("");
-      
-    SERIAL_ECHO_START;
-    SERIAL_ECHOLNPGM("Maximum feedrates (mm/s):");
-    SERIAL_ECHO_START;
-    SERIAL_ECHOPAIR("  M203 X", max_feedrate[X_AXIS]);
-    SERIAL_ECHOPAIR(" Y", max_feedrate[Y_AXIS]); 
-    SERIAL_ECHOPAIR(" Z", max_feedrate[Z_AXIS]); 
-    SERIAL_ECHOPAIR(" E", max_feedrate[E_AXIS]);
-    SERIAL_ECHOLN("");
-
-    SERIAL_ECHO_START;
-    SERIAL_ECHOLNPGM("Maximum Acceleration (mm/s2):");
-    SERIAL_ECHO_START;
-    SERIAL_ECHOPAIR("  M201 X" ,max_acceleration_units_per_sq_second[X_AXIS] ); 
-    SERIAL_ECHOPAIR(" Y" , max_acceleration_units_per_sq_second[Y_AXIS] ); 
-    SERIAL_ECHOPAIR(" Z" ,max_acceleration_units_per_sq_second[Z_AXIS] );
-    SERIAL_ECHOPAIR(" E" ,max_acceleration_units_per_sq_second[E_AXIS]);
-    SERIAL_ECHOLN("");
-    SERIAL_ECHO_START;
-    SERIAL_ECHOLNPGM("Acceleration: S=acceleration, T=retract acceleration");
-    SERIAL_ECHO_START;
-    SERIAL_ECHOPAIR("  M204 S",acceleration ); 
-    SERIAL_ECHOPAIR(" T" ,retract_acceleration);
-    SERIAL_ECHOLN("");
-
-    SERIAL_ECHO_START;
-    SERIAL_ECHOLNPGM("Advanced variables: S=Min feedrate (mm/s), T=Min travel feedrate (mm/s), B=minimum segment time (ms), X=maximum XY jerk (mm/s),  Z=maximum Z jerk (mm/s),  E=maximum E jerk (mm/s)");
-    SERIAL_ECHO_START;
-    SERIAL_ECHOPAIR("  M205 S",minimumfeedrate ); 
-    SERIAL_ECHOPAIR(" T" ,mintravelfeedrate ); 
-    SERIAL_ECHOPAIR(" B" ,minsegmenttime ); 
-    SERIAL_ECHOPAIR(" X" ,max_jerk[X_AXIS] ); 
-    SERIAL_ECHOPAIR(" Y" ,max_jerk[Y_AXIS] ); 
-    SERIAL_ECHOPAIR(" Z" ,max_jerk[Z_AXIS] ); 
-    SERIAL_ECHOPAIR(" E" ,max_jerk[E_AXIS] ); 
-    SERIAL_ECHOLN(""); 
-
-    SERIAL_ECHO_START;
-    SERIAL_ECHOLNPGM("Home offset (mm):");
-    SERIAL_ECHO_START;
-    SERIAL_ECHOPAIR("  M206 X",add_homing[X_AXIS] );
-    SERIAL_ECHOPAIR(" Y" ,add_homing[Y_AXIS] );
-    SERIAL_ECHOPAIR(" Z" ,add_homing[Z_AXIS] );
-    SERIAL_ECHOLN("");
+	printf_P(PSTR(
+		"%SSteps per unit:\n%S  M92 X%.2f Y%.2f Z%.2f E%.2f\n"
+		"%SMaximum feedrates (mm/s):\n%S  M203 X%.2f Y%.2f Z%.2f E%.2f\n"
+		"%SMaximum Acceleration (mm/s2):\n%S  M201 X%.2f Y%.2f Z%.2f E%.2f\n"
+		"%SAcceleration: S=acceleration, T=retract acceleration\n%S  M204 S%.2f T%.2f\n"
+		"%SAdvanced variables: S=Min feedrate (mm/s), T=Min travel feedrate (mm/s), B=minimum segment time (ms), X=maximum XY jerk (mm/s),  Z=maximum Z jerk (mm/s),  E=maximum E jerk (mm/s)\n%S  M205 S%.2f T%.2f B%.2f X%.2f Y%.2f Z%.2f E%.2f\n"
+		"%SHome offset (mm):\n%S  M206 X%.2f Y%.2f Z%.2f\n"
+		),
+		echomagic, echomagic, axis_steps_per_unit[X_AXIS], axis_steps_per_unit[Y_AXIS], axis_steps_per_unit[Z_AXIS], axis_steps_per_unit[E_AXIS],
+		echomagic, echomagic, max_feedrate[X_AXIS], max_feedrate[Y_AXIS], max_feedrate[Z_AXIS], max_feedrate[E_AXIS],
+		echomagic, echomagic, max_acceleration_units_per_sq_second[X_AXIS], max_acceleration_units_per_sq_second[Y_AXIS], max_acceleration_units_per_sq_second[Z_AXIS], max_acceleration_units_per_sq_second[E_AXIS],
+		echomagic, echomagic, acceleration, retract_acceleration,
+		echomagic, echomagic, minimumfeedrate, mintravelfeedrate, minsegmenttime, max_jerk[X_AXIS], max_jerk[Y_AXIS], max_jerk[Z_AXIS], max_jerk[E_AXIS],
+		echomagic, echomagic, add_homing[X_AXIS], add_homing[Y_AXIS], add_homing[Z_AXIS]
+	);
 #ifdef PIDTEMP
-    SERIAL_ECHO_START;
-    SERIAL_ECHOLNPGM("PID settings:");
-    SERIAL_ECHO_START;
-    SERIAL_ECHOPAIR("   M301 P",Kp); 
-    SERIAL_ECHOPAIR(" I" ,unscalePID_i(Ki)); 
-    SERIAL_ECHOPAIR(" D" ,unscalePID_d(Kd));
-    SERIAL_ECHOLN(""); 
+	printf_P(PSTR("%SPID settings:\n%S   M301 P%.2f I%.2f D%.2f\n"),
+		echomagic, echomagic, Kp, unscalePID_i(Ki), unscalePID_d(Kd));
 #endif
 #ifdef PIDTEMPBED
-	SERIAL_ECHO_START;
-	SERIAL_ECHOLNPGM("PID heatbed settings:");
-	SERIAL_ECHO_START;
-	SERIAL_ECHOPAIR("   M304 P", bedKp);
-	SERIAL_ECHOPAIR(" I", unscalePID_i(bedKi));
-	SERIAL_ECHOPAIR(" D", unscalePID_d(bedKd));
-	SERIAL_ECHOLN("");
+	printf_P(PSTR("%SPID heatbed settings:\n%S   M304 P%.2f I%.2f D%.2f\n"),
+		echomagic, echomagic, bedKp, unscalePID_i(bedKi), unscalePID_d(bedKd));
 #endif
 #ifdef FWRETRACT
-    SERIAL_ECHO_START;
-    SERIAL_ECHOLNPGM("Retract: S=Length (mm) F:Speed (mm/m) Z: ZLift (mm)");
-    SERIAL_ECHO_START;
-    SERIAL_ECHOPAIR("   M207 S",retract_length); 
-    SERIAL_ECHOPAIR(" F" ,retract_feedrate*60); 
-    SERIAL_ECHOPAIR(" Z" ,retract_zlift);
-    SERIAL_ECHOLN(""); 
-    SERIAL_ECHO_START;
-    SERIAL_ECHOLNPGM("Recover: S=Extra length (mm) F:Speed (mm/m)");
-    SERIAL_ECHO_START;
-    SERIAL_ECHOPAIR("   M208 S",retract_recover_length);
-    SERIAL_ECHOPAIR(" F", retract_recover_feedrate*60);
-	SERIAL_ECHOLN("");
-    SERIAL_ECHO_START;
-    SERIAL_ECHOLNPGM("Auto-Retract: S=0 to disable, 1 to interpret extrude-only moves as retracts or recoveries");
-    SERIAL_ECHO_START;
-    SERIAL_ECHOPAIR("   M209 S", (unsigned long)(autoretract_enabled ? 1 : 0));
-    SERIAL_ECHOLN("");
+	printf_P(PSTR(
+		"%SRetract: S=Length (mm) F:Speed (mm/m) Z: ZLift (mm)\n%S   M207 S%.2f F%.2f Z%.2f\n"
+		"%SRecover: S=Extra length (mm) F:Speed (mm/m)\n%S   M208 S%.2f F%.2f\n"
+		"%SAuto-Retract: S=0 to disable, 1 to interpret extrude-only moves as retracts or recoveries\n%S   M209 S%.2f\n"
+		),
+		echomagic, echomagic, retract_length, retract_feedrate*60, retract_zlift,
+		echomagic, echomagic, retract_recover_length, retract_recover_feedrate*60,
+		echomagic, echomagic, (unsigned long)(autoretract_enabled ? 1 : 0)
+	);
 #if EXTRUDERS > 1
-    SERIAL_ECHO_START;
-    SERIAL_ECHOLNPGM("Multi-extruder settings:");
-    SERIAL_ECHO_START;
-    SERIAL_ECHOPAIR("   Swap retract length (mm):    ", retract_length_swap);
-    SERIAL_ECHOLN("");
-    SERIAL_ECHO_START;
-    SERIAL_ECHOPAIR("   Swap rec. addl. length (mm): ", retract_recover_length_swap);
-    SERIAL_ECHOLN("");
+	printf_P(PSTR("%SMulti-extruder settings:\n%S   Swap retract length (mm):    %.2f\n%S   Swap rec. addl. length (mm): %.2f\n"),
+		echomagic, echomagic, retract_length_swap, echomagic, retract_recover_length_swap);
 #endif
-    SERIAL_ECHO_START;
-    if (volumetric_enabled) {
-        SERIAL_ECHOLNPGM("Filament settings:");
-        SERIAL_ECHO_START;
-        SERIAL_ECHOPAIR("   M200 D", filament_size[0]);
-        SERIAL_ECHOLN(""); 
+	if (volumetric_enabled) {
+		printf_P(PSTR("%SFilament settings:\n%S   M200 D%.2f\n"),
+			echomagic, echomagic, filament_size[0]);
 #if EXTRUDERS > 1
-		SERIAL_ECHO_START;
-        SERIAL_ECHOPAIR("   M200 T1 D", filament_size[1]);
-        SERIAL_ECHOLN(""); 
+		printf_P(PSTR("%S   M200 T1 D%.2f\n"),
+			echomagic, echomagic, filament_size[1]);
 #if EXTRUDERS > 2
-		SERIAL_ECHO_START;
-        SERIAL_ECHOPAIR("   M200 T2 D", filament_size[2]);
-		SERIAL_ECHOLN("");
+		printf_P(PSTR("%S   M200 T1 D%.2f\n"),
+			echomagic, echomagic, filament_size[2]);
 #endif
 #endif
     } else {
-        SERIAL_ECHOLNPGM("Filament settings: Disabled");
+        printf_P(PSTR("%SFilament settings: Disabled\n"), echomagic);
     }
 #endif
 	if (level >= 10) {
 #ifdef LIN_ADVANCE
-		SERIAL_ECHO_START;
-		SERIAL_ECHOLNPGM("Linear advance settings:");
-		SERIAL_ECHOPAIR("   M900 K", extruder_advance_k);
-		SERIAL_ECHOPAIR("   E/D = ", advance_ed_ratio);
+		printf_P(PSTR("%SLinear advance settings:\n   M900 K%.2f   E/D = %.2f\n"),
+			echomagic, extruder_advance_k, advance_ed_ratio);
 #endif //LIN_ADVANCE
 	}
 }
@@ -317,11 +237,6 @@ bool Config_RetrieveSettings(uint16_t offset, uint8_t level)
 		if (max_jerk[X_AXIS] > DEFAULT_XJERK) max_jerk[X_AXIS] = DEFAULT_XJERK;
 		if (max_jerk[Y_AXIS] > DEFAULT_YJERK) max_jerk[Y_AXIS] = DEFAULT_YJERK;
         EEPROM_READ_VAR(i,add_homing);
-        #ifndef ULTIPANEL
-        int plaPreheatHotendTemp, plaPreheatHPBTemp, plaPreheatFanSpeed;
-        int absPreheatHotendTemp, absPreheatHPBTemp, absPreheatFanSpeed;
-
-        #endif
 	/*
         EEPROM_READ_VAR(i,plaPreheatHotendTemp);
         EEPROM_READ_VAR(i,plaPreheatHPBTemp);
@@ -345,10 +260,7 @@ bool Config_RetrieveSettings(uint16_t offset, uint8_t level)
 		EEPROM_READ_VAR(i, bedKi);
 		EEPROM_READ_VAR(i, bedKd);
 		#endif
-		#ifndef DOGLCD
-        int lcd_contrast;
-        #endif
-        EEPROM_READ_VAR(i,lcd_contrast);
+//        EEPROM_READ_VAR(i,lcd_contrast);
 
 		#ifdef FWRETRACT
 		EEPROM_READ_VAR(i,autoretract_enabled);
@@ -433,9 +345,6 @@ void Config_ResetDefault()
 #ifdef ENABLE_AUTO_BED_LEVELING
     zprobe_zoffset = -Z_PROBE_OFFSET_FROM_EXTRUDER;
 #endif
-#ifdef DOGLCD
-    lcd_contrast = DEFAULT_LCD_CONTRAST;
-#endif
 #ifdef PIDTEMP
     Kp = DEFAULT_Kp;
     Ki = scalePID_i(DEFAULT_Ki);

+ 2 - 21
Firmware/Configuration_adv.h

@@ -178,9 +178,7 @@
 
 
 //Comment to disable setting feedrate multiplier via encoder
-#ifdef ULTIPANEL
-    #define ULTIPANEL_FEEDMULTIPLY
-#endif
+#define ULTIPANEL_FEEDMULTIPLY
 
 // minimum time in microseconds that a movement needs to take if the buffer is emptied.
 #define DEFAULT_MINSEGMENTTIME        20000
@@ -260,20 +258,6 @@
 	  #define HAS_FOLDER_SORTING (FOLDER_SORTING || SDSORT_GCODE)
 	#endif
 
-// Show a progress bar on the LCD when printing from SD?
-//#define LCD_PROGRESS_BAR
-
-#ifdef LCD_PROGRESS_BAR
-  // Amount of time (ms) to show the bar
-  #define PROGRESS_BAR_BAR_TIME 2000
-  // Amount of time (ms) to show the status message
-  #define PROGRESS_BAR_MSG_TIME 3000
-  // Amount of time (ms) to retain the status message (0=forever)
-  #define PROGRESS_MSG_EXPIRE   0
-  // Enable this to show messages for MSG_TIME then hide them
-  //#define PROGRESS_MSG_ONCE
-#endif
-
 // Enable the option to stop SD printing when hitting and endstops, needs to be enabled from the LCD menu when this option is enabled.
 //#define ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED
 
@@ -342,10 +326,7 @@ const unsigned int dropsegments=5; //everything with less than this number of st
 // in the pins.h file.  When using a push button pulling the pin to ground this will need inverted.  This setting should
 // be commented out otherwise
 #define SDCARDDETECTINVERTED
-
-#ifdef ULTIPANEL
- #undef SDCARDDETECTINVERTED
-#endif
+#undef SDCARDDETECTINVERTED
 
 // Power Signal Control Definitions
 // By default use ATX definition

+ 0 - 21
Firmware/Firmware.ino

@@ -33,24 +33,3 @@
 #include "Configuration.h"
 #include "pins.h"
 
-#ifdef ULTRA_LCD
-  #if defined(LCD_I2C_TYPE_PCF8575)
-    #include <Wire.h>
-    #include <LiquidCrystal_I2C.h>
-  #elif defined(LCD_I2C_TYPE_MCP23017) || defined(LCD_I2C_TYPE_MCP23008)
-    #include <Wire.h>
-    #include <LiquidTWI2.h>
-  #elif defined(DOGLCD)
-    #include <U8glib.h> // library for graphics LCD by Oli Kraus (https://code.google.com/p/u8glib/)
-  #else
-    #include "LiquidCrystal_Prusa.h" // library for character LCD
-  #endif
-#endif
-
-#if defined(DIGIPOTSS_PIN) && DIGIPOTSS_PIN > -1
-#include <SPI.h>
-#endif
-
-#if defined(DIGIPOT_I2C)
-  #include <Wire.h>
-#endif

+ 0 - 718
Firmware/LiquidCrystal_Prusa.cpp

@@ -1,718 +0,0 @@
-#include "LiquidCrystal_Prusa.h"
-
-#include <stdio.h>
-#include <string.h>
-#include <inttypes.h>
-#include "Arduino.h"
-
-// When the display powers up, it is configured as follows:
-//
-// 1. Display clear
-// 2. Function set: 
-//    DL = 1; 8-bit interface data 
-//    N = 0; 1-line display 
-//    F = 0; 5x8 dot character font 
-// 3. Display on/off control: 
-//    D = 0; Display off 
-//    C = 0; Cursor off 
-//    B = 0; Blinking off 
-// 4. Entry mode set: 
-//    I/D = 1; Increment by 1 
-//    S = 0; No shift 
-//
-// Note, however, that resetting the Arduino doesn't reset the LCD, so we
-// can't assume that it's in that state when a sketch starts (and the
-// LiquidCrystal_Prusa constructor is called).
-
-LiquidCrystal_Prusa::LiquidCrystal_Prusa(uint8_t rs, uint8_t rw, uint8_t enable,
-			     uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
-			     uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7)
-{
-  init(0, rs, rw, enable, d0, d1, d2, d3, d4, d5, d6, d7);
-}
-
-LiquidCrystal_Prusa::LiquidCrystal_Prusa(uint8_t rs, uint8_t enable,
-			     uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
-			     uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7)
-{
-  init(0, rs, 255, enable, d0, d1, d2, d3, d4, d5, d6, d7);
-}
-
-LiquidCrystal_Prusa::LiquidCrystal_Prusa(uint8_t rs, uint8_t rw, uint8_t enable,
-			     uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3)
-{
-  init(1, rs, rw, enable, d0, d1, d2, d3, 0, 0, 0, 0);
-}
-
-LiquidCrystal_Prusa::LiquidCrystal_Prusa(uint8_t rs,  uint8_t enable,
-			     uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3)
-{
-  init(1, rs, 255, enable, d0, d1, d2, d3, 0, 0, 0, 0);
-}
-
-void LiquidCrystal_Prusa::init(uint8_t fourbitmode, uint8_t rs, uint8_t rw, uint8_t enable,
-			 uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
-			 uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7)
-{
-  _rs_pin = rs;
-  _rw_pin = rw;
-  _enable_pin = enable;
-  
-  _data_pins[0] = d0;
-  _data_pins[1] = d1;
-  _data_pins[2] = d2;
-  _data_pins[3] = d3; 
-  _data_pins[4] = d4;
-  _data_pins[5] = d5;
-  _data_pins[6] = d6;
-  _data_pins[7] = d7; 
-
-  pinMode(_rs_pin, OUTPUT);
-  // we can save 1 pin by not using RW. Indicate by passing 255 instead of pin#
-  if (_rw_pin != 255) { 
-    pinMode(_rw_pin, OUTPUT);
-  }
-  pinMode(_enable_pin, OUTPUT);
-  
-  if (fourbitmode)
-    _displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS;
-  else 
-    _displayfunction = LCD_8BITMODE | LCD_1LINE | LCD_5x8DOTS;
-  
-  begin(16, 1);  
-}
-
-void LiquidCrystal_Prusa::begin(uint8_t cols, uint8_t lines, uint8_t dotsize) {
-  if (lines > 1) {
-    _displayfunction |= LCD_2LINE;
-  }
-  _numlines = lines;
-  _currline = 0;
-
-  // for some 1 line displays you can select a 10 pixel high font
-  if ((dotsize != 0) && (lines == 1)) {
-    _displayfunction |= LCD_5x10DOTS;
-  }
-
-  // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION!
-  // according to datasheet, we need at least 40ms after power rises above 2.7V
-  // before sending commands. Arduino can turn on way befer 4.5V so we'll wait 50
-  delayMicroseconds(50000); 
-  // Now we pull both RS and R/W low to begin commands
-  digitalWrite(_rs_pin, LOW);
-  digitalWrite(_enable_pin, LOW);
-  if (_rw_pin != 255) { 
-    digitalWrite(_rw_pin, LOW);
-  }
-  
-  //put the LCD into 4 bit or 8 bit mode
-  if (! (_displayfunction & LCD_8BITMODE)) {
-    // this is according to the hitachi HD44780 datasheet
-    // figure 24, pg 46
-
-    // we start in 8bit mode, try to set 4 bit mode
-    write4bits(0x03);
-    delayMicroseconds(4500); // wait min 4.1ms
-
-    // second try
-    write4bits(0x03);
-    delayMicroseconds(4500); // wait min 4.1ms
-    
-    // third go!
-    write4bits(0x03); 
-    delayMicroseconds(150);
-
-    // finally, set to 4-bit interface
-    write4bits(0x02); 
-  } else {
-    // this is according to the hitachi HD44780 datasheet
-    // page 45 figure 23
-
-    // Send function set command sequence
-    command(LCD_FUNCTIONSET | _displayfunction);
-    delayMicroseconds(4500);  // wait more than 4.1ms
-
-    // second try
-    command(LCD_FUNCTIONSET | _displayfunction);
-    delayMicroseconds(150);
-
-    // third go
-    command(LCD_FUNCTIONSET | _displayfunction);
-  }
-
-  // finally, set # lines, font size, etc.
-  command(LCD_FUNCTIONSET | _displayfunction);  
-  delayMicroseconds(60);
-  // turn the display on with no cursor or blinking default
-  _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;  
-  display();
-  delayMicroseconds(60);
-  // clear it off
-  clear();
-  delayMicroseconds(3000);
-  // Initialize to default text direction (for romance languages)
-  _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
-  // set the entry mode
-  command(LCD_ENTRYMODESET | _displaymode);
-  delayMicroseconds(60);
-
-  _escape[0] = 0;
-
-}
-
-
-
-void LiquidCrystal_Prusa::begin_noclear(uint8_t cols, uint8_t lines, uint8_t dotsize) {
-  if (lines > 1) {
-    _displayfunction |= LCD_2LINE;
-  }
-  _numlines = lines;
-  _currline = 0;
-
-  // for some 1 line displays you can select a 10 pixel high font
-  if ((dotsize != 0) && (lines == 1)) {
-    _displayfunction |= LCD_5x10DOTS;
-  }
-
-  // SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION!
-  // according to datasheet, we need at least 40ms after power rises above 2.7V
-  // before sending commands. Arduino can turn on way befer 4.5V so we'll wait 50
-  delayMicroseconds(50000); 
-  // Now we pull both RS and R/W low to begin commands
-  digitalWrite(_rs_pin, LOW);
-  digitalWrite(_enable_pin, LOW);
-  if (_rw_pin != 255) { 
-    digitalWrite(_rw_pin, LOW);
-  }
-  
-  //put the LCD into 4 bit or 8 bit mode
-  if (! (_displayfunction & LCD_8BITMODE)) {
-    // this is according to the hitachi HD44780 datasheet
-    // figure 24, pg 46
-
-    // we start in 8bit mode, try to set 4 bit mode
-    write4bits(0x03);
-    delayMicroseconds(4500); // wait min 4.1ms
-
-    // second try
-    write4bits(0x03);
-    delayMicroseconds(4500); // wait min 4.1ms
-    
-    // third go!
-    write4bits(0x03); 
-    delayMicroseconds(150);
-
-    // finally, set to 4-bit interface
-    write4bits(0x02); 
-  } else {
-    // this is according to the hitachi HD44780 datasheet
-    // page 45 figure 23
-
-    // Send function set command sequence
-    command(LCD_FUNCTIONSET | _displayfunction);
-    delayMicroseconds(4500);  // wait more than 4.1ms
-
-    // second try
-    command(LCD_FUNCTIONSET | _displayfunction);
-    delayMicroseconds(150);
-
-    // third go
-    command(LCD_FUNCTIONSET | _displayfunction);
-  }
-
-  // finally, set # lines, font size, etc.
-  command(LCD_FUNCTIONSET | _displayfunction);  
-  delayMicroseconds(60);
-
-  // turn the display on with no cursor or blinking default
-  _displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;  
-  display();
-  delayMicroseconds(60);
-  // clear it off
-  //clear();
-
-  home();
-  delayMicroseconds(1600);
-  // Initialize to default text direction (for romance languages)
-  _displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
-  // set the entry mode
-  command(LCD_ENTRYMODESET | _displaymode);
-  delayMicroseconds(60);
-
-  setCursor(8,0);
-  print("    ");
-  setCursor(8,1);
-  print("    ");
-  setCursor(6,2);
-  print("      ");
-
-
-}
-
-
-
-
-/********** high level commands, for the user! */
-void LiquidCrystal_Prusa::clear()
-{
-  command(LCD_CLEARDISPLAY);  // clear display, set cursor position to zero
-  delayMicroseconds(1600);  // this command takes a long time
-  
-}
-
-void LiquidCrystal_Prusa::home()
-{
-  command(LCD_RETURNHOME);  // set cursor position to zero
-  delayMicroseconds(1600);  // this command takes a long time!
-  
-}
-
-void LiquidCrystal_Prusa::setCursor(uint8_t col, uint8_t row)
-{
-  int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
-  if ( row >= _numlines ) {
-    row = _numlines-1;    // we count rows starting w/0
-  }
-  _currline = row;  
-  command(LCD_SETDDRAMADDR | (col + row_offsets[row]));
-}
-
-// Turn the display on/off (quickly)
-void LiquidCrystal_Prusa::noDisplay() {
-  _displaycontrol &= ~LCD_DISPLAYON;
-  command(LCD_DISPLAYCONTROL | _displaycontrol);
-}
-void LiquidCrystal_Prusa::display() {
-  _displaycontrol |= LCD_DISPLAYON;
-  command(LCD_DISPLAYCONTROL | _displaycontrol);
-}
-
-// Turns the underline cursor on/off
-void LiquidCrystal_Prusa::noCursor() {
-  _displaycontrol &= ~LCD_CURSORON;
-  command(LCD_DISPLAYCONTROL | _displaycontrol);
-}
-void LiquidCrystal_Prusa::cursor() {
-  _displaycontrol |= LCD_CURSORON;
-  command(LCD_DISPLAYCONTROL | _displaycontrol);
-}
-
-// Turn on and off the blinking cursor
-void LiquidCrystal_Prusa::noBlink() {
-  _displaycontrol &= ~LCD_BLINKON;
-  command(LCD_DISPLAYCONTROL | _displaycontrol);
-}
-void LiquidCrystal_Prusa::blink() {
-  _displaycontrol |= LCD_BLINKON;
-  command(LCD_DISPLAYCONTROL | _displaycontrol);
-}
-
-// These commands scroll the display without changing the RAM
-void LiquidCrystal_Prusa::scrollDisplayLeft(void) {
-  command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT);
-}
-void LiquidCrystal_Prusa::scrollDisplayRight(void) {
-  command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT);
-}
-
-// This is for text that flows Left to Right
-void LiquidCrystal_Prusa::leftToRight(void) {
-  _displaymode |= LCD_ENTRYLEFT;
-  command(LCD_ENTRYMODESET | _displaymode);
-}
-
-// This is for text that flows Right to Left
-void LiquidCrystal_Prusa::rightToLeft(void) {
-  _displaymode &= ~LCD_ENTRYLEFT;
-  command(LCD_ENTRYMODESET | _displaymode);
-}
-
-// This will 'right justify' text from the cursor
-void LiquidCrystal_Prusa::autoscroll(void) {
-  _displaymode |= LCD_ENTRYSHIFTINCREMENT;
-  command(LCD_ENTRYMODESET | _displaymode);
-}
-
-// This will 'left justify' text from the cursor
-void LiquidCrystal_Prusa::noAutoscroll(void) {
-  _displaymode &= ~LCD_ENTRYSHIFTINCREMENT;
-  command(LCD_ENTRYMODESET | _displaymode);
-}
-
-// Allows us to fill the first 8 CGRAM locations
-// with custom characters
-void LiquidCrystal_Prusa::createChar(uint8_t location, uint8_t charmap[]) {
-  location &= 0x7; // we only have 8 locations 0-7
-  command(LCD_SETCGRAMADDR | (location << 3));
-  for (int i=0; i<8; i++)
-    send(charmap[i], HIGH);
-}
-
-/*********** mid level commands, for sending data/cmds */
-
-inline void LiquidCrystal_Prusa::command(uint8_t value) {
-  send(value, LOW);
-}
-
-inline size_t LiquidCrystal_Prusa::write(uint8_t value) {
-  if (value == '\n')
-  {
-    if (_currline > 3) _currline = -1;
-	setCursor(0, _currline + 1); // LF
-	return 1;
-  }
-  if (_escape[0] || (value == 0x1b))
-    return escape_write(value);
-  send(value, HIGH);
-  return 1; // assume sucess
-}
-
-//Supported VT100 escape codes:
-//EraseScreen  "\x1b[2J"
-//CursorHome   "\x1b[%d;%dH"
-//CursorShow   "\x1b[?25h"
-//CursorHide   "\x1b[?25l"
-
-inline size_t LiquidCrystal_Prusa::escape_write(uint8_t chr)
-{
-#define escape_cnt (_escape[0])        //escape character counter
-#define is_num_msk (_escape[1])        //numeric character bit mask
-#define chr_is_num (is_num_msk & 0x01) //current character is numeric
-#define e_2_is_num (is_num_msk & 0x04) //escape char 2 is numeric
-#define e_3_is_num (is_num_msk & 0x08) //...
-#define e_4_is_num (is_num_msk & 0x10)
-#define e_5_is_num (is_num_msk & 0x20)
-#define e_6_is_num (is_num_msk & 0x40)
-#define e_7_is_num (is_num_msk & 0x80)
-#define e2_num (_escape[2] - '0')      //number from character 2
-#define e3_num (_escape[3] - '0')      //number from character 3
-#define e23_num (10*e2_num+e3_num)     //number from characters 2 and 3
-#define e4_num (_escape[4] - '0')      //number from character 4
-#define e5_num (_escape[5] - '0')      //number from character 5
-#define e45_num (10*e4_num+e5_num)     //number from characters 4 and 5
-#define e6_num (_escape[6] - '0')      //number from character 6
-#define e56_num (10*e5_num+e6_num)     //number from characters 5 and 6
-	if (escape_cnt > 1) // escape length > 1 = "\x1b["
-	{
-		_escape[escape_cnt] = chr; // store current char
-		if ((chr >= '0') && (chr <= '9')) // char is numeric
-			is_num_msk |= (1 | (1 << escape_cnt)); //set mask
-		else
-			is_num_msk &= ~1; //clear mask
-	}
-	switch (escape_cnt++)
-	{
-	case 0:
-		if (chr == 0x1b) return 1;  // escape = "\x1b"
-		break;
-	case 1:
-		is_num_msk = 0x00; // reset 'is number' bit mask
-		if (chr == '[') return 1; // escape = "\x1b["
-		break;
-	case 2:
-		switch (chr)
-		{
-		case '2': return 1; // escape = "\x1b[2"
-		case '?': return 1; // escape = "\x1b[?"
-		default:
-			if (chr_is_num) return 1; // escape = "\x1b[%1d"
-		}
-		break;
-	case 3:
-		switch (_escape[2])
-		{
-		case '?': // escape = "\x1b[?"
-			if (chr == '2') return 1; // escape = "\x1b[?2"
-			break;
-		case '2':
-			if (chr == 'J') // escape = "\x1b[2J"
-				{ clear(); _currline = 0; break; } // EraseScreen
-		default:
-			if (e_2_is_num && // escape = "\x1b[%1d"
-				((chr == ';') || // escape = "\x1b[%1d;"
-				chr_is_num)) // escape = "\x1b[%2d"
-				return 1;
-		}
-		break;
-	case 4:
-		switch (_escape[2])
-		{
-		case '?': // "\x1b[?"
-			if ((_escape[3] == '2') && (chr == '5')) return 1; // escape = "\x1b[?25"
-			break;
-		default:
-			if (e_2_is_num) // escape = "\x1b[%1d"
-			{
-				if ((_escape[3] == ';') && chr_is_num) return 1; // escape = "\x1b[%1d;%1d"
-				else if (e_3_is_num && (chr == ';')) return 1; // escape = "\x1b[%2d;"
-			}
-		}
-		break;
-	case 5:
-		switch (_escape[2])
-		{
-		case '?':
-			if ((_escape[3] == '2') && (_escape[4] == '5')) // escape = "\x1b[?25"
-				switch (chr)
-				{
-				case 'h': // escape = "\x1b[?25h"
-  					void cursor(); // CursorShow
-					break;
-				case 'l': // escape = "\x1b[?25l"
-					noCursor(); // CursorHide
-					break;
-				}
-			break;
-		default:
-			if (e_2_is_num) // escape = "\x1b[%1d"
-			{
-				if ((_escape[3] == ';') && e_4_is_num) // escape = "\x1b%1d;%1dH"
-				{
-					if (chr == 'H') // escape = "\x1b%1d;%1dH"
-						setCursor(e4_num, e2_num); // CursorHome
-					else if (chr_is_num)
-						return 1; // escape = "\x1b%1d;%2d"
-				}
-				else if (e_3_is_num && (_escape[4] == ';') && chr_is_num)
-					return 1; // escape = "\x1b%2d;%1d"
-			}
-		}
-		break;
-	case 6:
-		if (e_2_is_num) // escape = "\x1b[%1d"
-		{
-			if ((_escape[3] == ';') && e_4_is_num && e_5_is_num && (chr == 'H')) // escape = "\x1b%1d;%2dH"
-				setCursor(e45_num, e2_num); // CursorHome
-			else if (e_3_is_num && (_escape[4] == ';') && e_5_is_num) // escape = "\x1b%2d;%1d"
-			{
-				if (chr == 'H') // escape = "\x1b%2d;%1dH"
-					setCursor(e5_num, e23_num); // CursorHome
-				else if (chr_is_num) // "\x1b%2d;%2d"
-					return 1;
-			}
-		}
-		break;
-	case 7:
-		if (e_2_is_num && e_3_is_num && (_escape[4] == ';')) // "\x1b[%2d;"
-			if (e_5_is_num && e_6_is_num && (chr == 'H')) // "\x1b[%2d;%2dH"
-				setCursor(e56_num, e23_num); // CursorHome
-		break;
-	}
-	escape_cnt = 0; // reset escape
-end:
-	return 1; // assume sucess
-}
-
-
-/************ low level data pushing commands **********/
-
-// write either command or data, with automatic 4/8-bit selection
-void LiquidCrystal_Prusa::send(uint8_t value, uint8_t mode) {
-  digitalWrite(_rs_pin, mode);
-
-  // if there is a RW pin indicated, set it low to Write
-  if (_rw_pin != 255) { 
-    digitalWrite(_rw_pin, LOW);
-  }
-  
-  if (_displayfunction & LCD_8BITMODE) {
-    write8bits(value); 
-  } else {
-    write4bits(value>>4);
-    write4bits(value);
-  }
-}
-
-void LiquidCrystal_Prusa::pulseEnable(void) {
-  digitalWrite(_enable_pin, LOW);
-  delayMicroseconds(1);    
-  digitalWrite(_enable_pin, HIGH);
-  delayMicroseconds(1);    // enable pulse must be >450ns
-  digitalWrite(_enable_pin, LOW);
-  delayMicroseconds(100);   // commands need > 37us to settle
-}
-
-void LiquidCrystal_Prusa::write4bits(uint8_t value) {
-  for (int i = 0; i < 4; i++) {
-    pinMode(_data_pins[i], OUTPUT);
-    digitalWrite(_data_pins[i], (value >> i) & 0x01);
-  }
-
-  pulseEnable();
-}
-
-void LiquidCrystal_Prusa::write8bits(uint8_t value) {
-  for (int i = 0; i < 8; i++) {
-    pinMode(_data_pins[i], OUTPUT);
-    digitalWrite(_data_pins[i], (value >> i) & 0x01);
-  }
-  
-  pulseEnable();
-}
-
-void LiquidCrystal_Prusa::print(const char* s)
-{
-	while (*s) write(*(s++));
-}
-
-void LiquidCrystal_Prusa::print(char c, int base)
-{
-  print((long) c, base);
-}
-
-void LiquidCrystal_Prusa::print(unsigned char b, int base)
-{
-  print((unsigned long) b, base);
-}
-
-void LiquidCrystal_Prusa::print(int n, int base)
-{
-  print((long) n, base);
-}
-
-void LiquidCrystal_Prusa::print(unsigned int n, int base)
-{
-  print((unsigned long) n, base);
-}
-
-void LiquidCrystal_Prusa::print(long n, int base)
-{
-  if (base == 0) {
-    write(n);
-  } else if (base == 10) {
-    if (n < 0) {
-      print('-');
-      n = -n;
-    }
-    printNumber(n, 10);
-  } else {
-    printNumber(n, base);
-  }
-}
-
-void LiquidCrystal_Prusa::print(unsigned long n, int base)
-{
-  if (base == 0) write(n);
-  else printNumber(n, base);
-}
-
-void LiquidCrystal_Prusa::print(double n, int digits)
-{
-  printFloat(n, digits);
-}
-
-void LiquidCrystal_Prusa::println(void)
-{
-  print('\r');
-  print('\n');  
-}
-
-/*void LiquidCrystal_Prusa::println(const String &s)
-{
-  print(s);
-  println();
-}*/
-
-void LiquidCrystal_Prusa::println(const char c[])
-{
-  print(c);
-  println();
-}
-
-void LiquidCrystal_Prusa::println(char c, int base)
-{
-  print(c, base);
-  println();
-}
-
-void LiquidCrystal_Prusa::println(unsigned char b, int base)
-{
-  print(b, base);
-  println();
-}
-
-void LiquidCrystal_Prusa::println(int n, int base)
-{
-  print(n, base);
-  println();
-}
-
-void LiquidCrystal_Prusa::println(unsigned int n, int base)
-{
-  print(n, base);
-  println();
-}
-
-void LiquidCrystal_Prusa::println(long n, int base)
-{
-  print(n, base);
-  println();
-}
-
-void LiquidCrystal_Prusa::println(unsigned long n, int base)
-{
-  print(n, base);
-  println();
-}
-
-void LiquidCrystal_Prusa::println(double n, int digits)
-{
-  print(n, digits);
-  println();
-}
-
-void LiquidCrystal_Prusa::printNumber(unsigned long n, uint8_t base)
-{
-  unsigned char buf[8 * sizeof(long)]; // Assumes 8-bit chars. 
-  unsigned long i = 0;
-
-  if (n == 0) {
-    print('0');
-    return;
-  } 
-
-  while (n > 0) {
-    buf[i++] = n % base;
-    n /= base;
-  }
-
-  for (; i > 0; i--)
-    print((char) (buf[i - 1] < 10 ?
-      '0' + buf[i - 1] :
-      'A' + buf[i - 1] - 10));
-}
-
-void LiquidCrystal_Prusa::printFloat(double number, uint8_t digits) 
-{ 
-  // Handle negative numbers
-  if (number < 0.0)
-  {
-     print('-');
-     number = -number;
-  }
-
-  // Round correctly so that print(1.999, 2) prints as "2.00"
-  double rounding = 0.5;
-  for (uint8_t i=0; i<digits; ++i)
-    rounding /= 10.0;
-  
-  number += rounding;
-
-  // Extract the integer part of the number and print it
-  unsigned long int_part = (unsigned long)number;
-  double remainder = number - (double)int_part;
-  print(int_part);
-
-  // Print the decimal point, but only if there are digits beyond
-  if (digits > 0)
-    print("."); 
-
-  // Extract digits from the remainder one at a time
-  while (digits-- > 0)
-  {
-    remainder *= 10.0;
-    int toPrint = int(remainder);
-    print(toPrint);
-    remainder -= toPrint; 
-  } 
-}

+ 0 - 142
Firmware/LiquidCrystal_Prusa.h

@@ -1,142 +0,0 @@
-#ifndef LiquidCrystal_Prusa_h
-#define LiquidCrystal_Prusa_h
-
-#include <inttypes.h>
-#include <stddef.h>
-//#include "Print.h"
-
-// commands
-#define LCD_CLEARDISPLAY 0x01
-#define LCD_RETURNHOME 0x02
-#define LCD_ENTRYMODESET 0x04
-#define LCD_DISPLAYCONTROL 0x08
-#define LCD_CURSORSHIFT 0x10
-#define LCD_FUNCTIONSET 0x20
-#define LCD_SETCGRAMADDR 0x40
-#define LCD_SETDDRAMADDR 0x80
-
-// flags for display entry mode
-#define LCD_ENTRYRIGHT 0x00
-#define LCD_ENTRYLEFT 0x02
-#define LCD_ENTRYSHIFTINCREMENT 0x01
-#define LCD_ENTRYSHIFTDECREMENT 0x00
-
-// flags for display on/off control
-#define LCD_DISPLAYON 0x04
-#define LCD_DISPLAYOFF 0x00
-#define LCD_CURSORON 0x02
-#define LCD_CURSOROFF 0x00
-#define LCD_BLINKON 0x01
-#define LCD_BLINKOFF 0x00
-
-// flags for display/cursor shift
-#define LCD_DISPLAYMOVE 0x08
-#define LCD_CURSORMOVE 0x00
-#define LCD_MOVERIGHT 0x04
-#define LCD_MOVELEFT 0x00
-
-// flags for function set
-#define LCD_8BITMODE 0x10
-#define LCD_4BITMODE 0x00
-#define LCD_2LINE 0x08
-#define LCD_1LINE 0x00
-#define LCD_5x10DOTS 0x04
-#define LCD_5x8DOTS 0x00
-
-class LiquidCrystal_Prusa/* : public Print */{
-public:
-  LiquidCrystal_Prusa(uint8_t rs, uint8_t enable,
-		uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
-		uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7);
-  LiquidCrystal_Prusa(uint8_t rs, uint8_t rw, uint8_t enable,
-		uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
-		uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7);
-  LiquidCrystal_Prusa(uint8_t rs, uint8_t rw, uint8_t enable,
-		uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3);
-  LiquidCrystal_Prusa(uint8_t rs, uint8_t enable,
-		uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3);
-
-  void init(uint8_t fourbitmode, uint8_t rs, uint8_t rw, uint8_t enable,
-	    uint8_t d0, uint8_t d1, uint8_t d2, uint8_t d3,
-	    uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7);
-    
-  void begin(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS);
-
-  void begin_noclear(uint8_t cols, uint8_t rows, uint8_t charsize = LCD_5x8DOTS);
-
-  void clear();
-  void home();
-
-  void noDisplay();
-  void display();
-  void noBlink();
-  void blink();
-  void noCursor();
-  void cursor();
-  void scrollDisplayLeft();
-  void scrollDisplayRight();
-  void leftToRight();
-  void rightToLeft();
-  void autoscroll();
-  void noAutoscroll();
-
-  void createChar(uint8_t, uint8_t[]);
-  void setCursor(uint8_t, uint8_t); 
-//  virtual size_t write(uint8_t);
-  size_t write(uint8_t);
-  void command(uint8_t);
-
-    void print(const char*);
-    void print(char, int = 0);
-    void print(unsigned char, int = 0);
-    void print(int, int = 10);
-    void print(unsigned int, int = 10);
-    void print(long, int = 10);
-    void print(unsigned long, int = 10);
-    void print(double, int = 2);
-
-//    void println(const String &s);
-    void println(const char[]);
-    void println(char, int = 0);
-    void println(unsigned char, int = 0);
-    void println(int, int = 10);
-    void println(unsigned int, int = 10);
-    void println(long, int = 10);
-    void println(unsigned long, int = 10);
-    void println(double, int = 2);
-    void println(void);
-
-	void printNumber(unsigned long n, uint8_t base);
-	void printFloat(double number, uint8_t digits);
-
-//  using Print::write;
-private:
-  void send(uint8_t, uint8_t);
-  void write4bits(uint8_t);
-  void write8bits(uint8_t);
-  void pulseEnable();
-
-  uint8_t _rs_pin; // LOW: command.  HIGH: character.
-  uint8_t _rw_pin; // LOW: write to LCD.  HIGH: read from LCD.
-  uint8_t _enable_pin; // activated by a HIGH pulse.
-  uint8_t _data_pins[8];
-
-  uint8_t _displayfunction;
-  uint8_t _displaycontrol;
-  uint8_t _displaymode;
-
-  uint8_t _initialized;
-
-  uint8_t _numlines,_currline;
-
-  uint8_t _escape[8];
-  size_t escape_write(uint8_t value);
-  
-};
-
-#define ESC_2J     "\x1b[2J"
-#define ESC_25h    "\x1b[?25h"
-#define ESC_25l    "\x1b[?25l"
-#define ESC_H(c,r) "\x1b["#r";"#c"H"
-
-#endif

+ 4 - 3
Firmware/Marlin.h

@@ -62,8 +62,7 @@
   #define MYSERIAL MSerial
 #endif
 
-extern FILE _lcdout;
-#define lcdout (&_lcdout)
+#include "lcd.h"
 
 extern FILE _uartout;
 #define uartout (&_uartout)
@@ -456,7 +455,9 @@ void force_high_power_mode(bool start_high_power_section);
 #endif //TMC2130
 
 // G-codes
-void gcode_G28(bool home_x, bool home_y, bool home_z, bool calib);
+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);
+void gcode_G28(bool home_x_axis, bool home_y_axis, bool home_z_axis);
+
 bool gcode_M45(bool onlyZ, int8_t verbosity_level);
 void gcode_M114();
 void gcode_M701();

+ 192 - 132
Firmware/Marlin_main.cpp

@@ -58,8 +58,10 @@
 #endif
 
 #include "printers.h"
+
+#include "menu.h"
 #include "ultralcd.h"
-#include "Configuration_prusa.h"
+
 #include "planner.h"
 #include "stepper.h"
 #include "temperature.h"
@@ -167,7 +169,7 @@
 // G92 - Set current position to coordinates given
 
 // M Codes
-// M0   - Unconditional stop - Wait for user to press a button on the LCD (Only if ULTRA_LCD is enabled)
+// M0   - Unconditional stop - Wait for user to press a button on the LCD
 // M1   - Same as M0
 // M17  - Enable/Power all stepper motors
 // M18  - Disable all stepper motors; same as M84
@@ -431,13 +433,11 @@ int fanSpeed=0;
   float retract_recover_feedrate = RETRACT_RECOVER_FEEDRATE;
 #endif
 
-#ifdef ULTIPANEL
   #ifdef PS_DEFAULT_OFF
     bool powersupply = false;
   #else
 	  bool powersupply = true;
   #endif
-#endif
 
 bool cancel_heatup = false ;
 
@@ -716,7 +716,7 @@ void crashdet_detected(uint8_t mask)
 	}
 
 	lcd_update_enable(true);
-	lcd_implementation_clear();
+	lcd_clear();
 	lcd_update(2);
 
 	if (mask & X_AXIS_MASK)
@@ -735,7 +735,7 @@ void crashdet_detected(uint8_t mask)
 	lcd_update_enable(true);
 	lcd_update(2);
 	lcd_setstatuspgm(_T(MSG_CRASH_DETECTED));
-	gcode_G28(true, true, false, false); //home X and Y
+	gcode_G28(true, true, false); //home X and Y
 	st_synchronize();
 
 	if (automatic_recovery_after_crash) {
@@ -801,7 +801,7 @@ void failstats_reset_print()
 int  er_progress = 0;
 void factory_reset(char level, bool quiet)
 {	
-	lcd_implementation_clear();
+	lcd_clear();
 	int cursor_pos = 0;
     switch (level) {
                    
@@ -837,8 +837,8 @@ void factory_reset(char level, bool quiet)
 
         // Level 2: Prepare for shipping
         case 2:
-			//lcd_printPGM(PSTR("Factory RESET"));
-            //lcd_print_at_PGM(1,2,PSTR("Shipping prep"));
+			//lcd_puts_P(PSTR("Factory RESET"));
+            //lcd_puts_at_P(1,2,PSTR("Shipping prep"));
             
             // Force language selection at the next boot up.
 			lang_reset();
@@ -849,6 +849,16 @@ void factory_reset(char level, bool quiet)
 			farm_mode = false;
 			eeprom_update_byte((uint8_t*)EEPROM_FARM_MODE, farm_mode);
             EEPROM_save_B(EEPROM_FARM_NUMBER, &farm_no);
+
+            eeprom_update_dword((uint32_t *)EEPROM_TOTALTIME, 0);
+            eeprom_update_dword((uint32_t *)EEPROM_FILAMENTUSED, 0);
+            eeprom_update_word((uint16_t *)EEPROM_CRASH_COUNT_X_TOT, 0);
+            eeprom_update_word((uint16_t *)EEPROM_CRASH_COUNT_Y_TOT, 0);
+            eeprom_update_word((uint16_t *)EEPROM_FERROR_COUNT_TOT, 0);
+            eeprom_update_word((uint16_t *)EEPROM_POWER_COUNT_TOT, 0);
+
+            fsensor_enable();
+            fautoload_set(true);
                        
             WRITE(BEEPER, HIGH);
             _delay_ms(100);
@@ -859,16 +869,17 @@ void factory_reset(char level, bool quiet)
 			// Level 3: erase everything, whole EEPROM will be set to 0xFF
 
 		case 3:
-			lcd_printPGM(PSTR("Factory RESET"));
-			lcd_print_at_PGM(1, 2, PSTR("ERASING all data"));
+			lcd_puts_P(PSTR("Factory RESET"));
+			lcd_puts_at_P(1, 2, PSTR("ERASING all data"));
 
 			WRITE(BEEPER, HIGH);
 			_delay_ms(100);
 			WRITE(BEEPER, LOW);
 
 			er_progress = 0;
-			lcd_print_at_PGM(3, 3, PSTR("      "));
-			lcd_implementation_print_at(3, 3, er_progress);
+			lcd_puts_at_P(3, 3, PSTR("      "));
+			lcd_set_cursor(3, 3);
+			lcd_print(er_progress);
 
 			// Erase EEPROM
 			for (int i = 0; i < 4096; i++) {
@@ -876,9 +887,10 @@ void factory_reset(char level, bool quiet)
 
 				if (i % 41 == 0) {
 					er_progress++;
-					lcd_print_at_PGM(3, 3, PSTR("      "));
-					lcd_implementation_print_at(3, 3, er_progress);
-					lcd_printPGM(PSTR("%"));
+					lcd_puts_at_P(3, 3, PSTR("      "));
+					lcd_set_cursor(3, 3);
+					lcd_print(er_progress);
+					lcd_puts_P(PSTR("%"));
 				}
 
 			}
@@ -895,16 +907,7 @@ void factory_reset(char level, bool quiet)
     
 
 }
-#include "LiquidCrystal_Prusa.h"
-extern LiquidCrystal_Prusa lcd;
-
-FILE _lcdout = {0};
 
-int lcd_putchar(char c, FILE *stream)
-{
-	lcd.write(c);
-	return 0;
-}
 
 FILE _uartout = {0};
 
@@ -917,9 +920,9 @@ int uart_putchar(char c, FILE *stream)
 
 void lcd_splash()
 {
-//	lcd_print_at_PGM(0, 1, PSTR("   Original Prusa   "));
-//	lcd_print_at_PGM(0, 2, PSTR("    3D  Printers    "));
-//	lcd.print_P(PSTR("\x1b[1;3HOriginal Prusa\x1b[2;4H3D  Printers"));
+//	lcd_puts_at_P(0, 1, PSTR("   Original Prusa   "));
+//	lcd_puts_at_P(0, 2, PSTR("    3D  Printers    "));
+//	lcd_puts_P(PSTR("\x1b[1;3HOriginal Prusa\x1b[2;4H3D  Printers"));
 //    fputs_P(PSTR(ESC_2J ESC_H(1,1) "Original Prusa i3" ESC_H(3,2) "Prusa Research"), lcdout);
     lcd_puts_P(PSTR(ESC_2J ESC_H(1,1) "Original Prusa i3" ESC_H(3,2) "Prusa Research"));
 //	lcd_printf_P(_N(ESC_2J "x:%.3f\ny:%.3f\nz:%.3f\ne:%.3f"), _x, _y, _z, _e);
@@ -934,10 +937,10 @@ void factory_reset()
 		_delay_ms(1000);
 		if (!READ(BTN_ENC))
 		{
-			lcd_implementation_clear();
+			lcd_clear();
 
 
-			lcd_printPGM(PSTR("Factory RESET"));
+			lcd_puts_P(PSTR("Factory RESET"));
 
 
 			SET_OUTPUT(BEEPER);
@@ -1007,15 +1010,15 @@ void show_fw_version_warnings() {
   case(FW_VERSION_DEVEL):
 	case(FW_VERSION_DEBUG):
     lcd_update_enable(false);
-    lcd_implementation_clear();
+    lcd_clear();
   #if FW_DEV_VERSION == FW_VERSION_DEVEL
-    lcd_print_at_PGM(0, 0, PSTR("Development build !!"));
+    lcd_puts_at_P(0, 0, PSTR("Development build !!"));
   #else
-    lcd_print_at_PGM(0, 0, PSTR("Debbugging build !!!"));
+    lcd_puts_at_P(0, 0, PSTR("Debbugging build !!!"));
   #endif
-    lcd_print_at_PGM(0, 1, PSTR("May destroy printer!"));
-    lcd_print_at_PGM(0, 2, PSTR("ver ")); lcd_printPGM(PSTR(FW_VERSION_FULL));
-    lcd_print_at_PGM(0, 3, PSTR(FW_REPOSITORY));
+    lcd_puts_at_P(0, 1, PSTR("May destroy printer!"));
+    lcd_puts_at_P(0, 2, PSTR("ver ")); lcd_puts_P(PSTR(FW_VERSION_FULL));
+    lcd_puts_at_P(0, 3, PSTR(FW_REPOSITORY));
     lcd_wait_for_click();
     break;
 //	default: lcd_show_fullscreen_message_and_wait_P(_i("WARNING: This is an unofficial, unsupported build. Use at your own risk!")); break;////MSG_FW_VERSION_UNKNOWN c=20 r=8
@@ -1143,17 +1146,17 @@ void list_sec_lang_from_external_flash()
 // are initialized by the main() routine provided by the Arduino framework.
 void setup()
 {
-#ifdef W25X20CL
-  // Enter an STK500 compatible Optiboot boot loader waiting for flashing the languages to an external flash memory.
-  optiboot_w25x20cl_enter();
-#endif
-    lcd_init();
-	fdev_setup_stream(lcdout, lcd_putchar, NULL, _FDEV_SETUP_WRITE); //setup lcdout stream
+    ultralcd_init();
 
 	spi_init();
 
 	lcd_splash();
 
+#ifdef W25X20CL
+  // Enter an STK500 compatible Optiboot boot loader waiting for flashing the languages to an external flash memory.
+ // optiboot_w25x20cl_enter();
+#endif
+
 #if (LANG_MODE != 0) //secondary language support
 #ifdef W25X20CL
 	if (w25x20cl_init())
@@ -1696,7 +1699,7 @@ void setup()
   KEEPALIVE_STATE(IN_PROCESS);
 #endif //DEBUG_DISABLE_STARTMSGS
   lcd_update_enable(true);
-  lcd_implementation_clear();
+  lcd_clear();
   lcd_update(2);
   // Store the currently running firmware into an eeprom,
   // so the next time the firmware gets updated, it will know from which version it has been updated.
@@ -1810,8 +1813,8 @@ int serial_read_stream() {
     setTargetHotend(0, 0);
     setTargetBed(0);
 
-    lcd_implementation_clear();
-    lcd_printPGM(PSTR(" Upload in progress"));
+    lcd_clear();
+    lcd_puts_P(PSTR(" Upload in progress"));
 
     // first wait for how many bytes we will receive
     uint32_t bytesToReceive;
@@ -2011,7 +2014,7 @@ void loop()
   manage_heater();
   isPrintPaused ? manage_inactivity(true) : manage_inactivity(false);
   checkHitEndstops();
-  lcd_update();
+  lcd_update(0);
 #ifdef PAT9125
 	fsensor_update();
 #endif //PAT9125
@@ -2269,8 +2272,8 @@ bool check_commands() {
 bool calibrate_z_auto()
 {
 	//lcd_display_message_fullscreen_P(_T(MSG_CALIBRATE_Z_AUTO));
-	lcd_implementation_clear();
-	lcd_print_at_PGM(0,1, _T(MSG_CALIBRATE_Z_AUTO));
+	lcd_clear();
+	lcd_puts_at_P(0,1, _T(MSG_CALIBRATE_Z_AUTO));
 	bool endstops_enabled  = enable_endstops(true);
 	int axis_up_dir = -home_dir(Z_AXIS);
 	tmc2130_home_enter(Z_AXIS_MASK);
@@ -2606,7 +2609,11 @@ void force_high_power_mode(bool start_high_power_section) {
 }
 #endif //TMC2130
 
-void gcode_G28(bool home_x, bool home_y, bool home_z, bool calib) {
+void gcode_G28(bool home_x_axis, bool home_y_axis, bool home_z_axis) {
+	gcode_G28(home_x_axis, 0, home_y_axis, 0, home_z_axis, 0, false, true);
+}
+
+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) {
 	st_synchronize();
 
 #if 0
@@ -2617,6 +2624,11 @@ void gcode_G28(bool home_x, bool home_y, bool home_z, bool calib) {
 	// Flag for the display update routine and to disable the print cancelation during homing.
 	homing_flag = true;
 
+	// Which axes should be homed?
+	bool home_x = home_x_axis;
+	bool home_y = home_y_axis;
+	bool home_z = home_z_axis;
+
 	// Either all X,Y,Z codes are present, or none of them.
 	bool home_all_axes = home_x == home_y && home_x == home_z;
 	if (home_all_axes)
@@ -2725,11 +2737,11 @@ void gcode_G28(bool home_x, bool home_y, bool home_z, bool calib) {
 #endif //TMC2130
 
 
-      if(code_seen(axis_codes[X_AXIS]) && code_value_long() != 0)
-        current_position[X_AXIS]=code_value()+add_homing[X_AXIS];
+      if(home_x_axis && home_x_value != 0)
+        current_position[X_AXIS]=home_x_value+add_homing[X_AXIS];
 
-      if(code_seen(axis_codes[Y_AXIS]) && code_value_long() != 0)
-		    current_position[Y_AXIS]=code_value()+add_homing[Y_AXIS];
+      if(home_y_axis && home_y_value != 0)
+        current_position[Y_AXIS]=home_y_value+add_homing[Y_AXIS];
 
       #if Z_HOME_DIR < 0                      // If homing towards BED do Z last
         #ifndef Z_SAFE_HOMING
@@ -2824,8 +2836,8 @@ void gcode_G28(bool home_x, bool home_y, bool home_z, bool calib) {
         #endif // Z_SAFE_HOMING
       #endif // Z_HOME_DIR < 0
 
-      if(code_seen(axis_codes[Z_AXIS]) && code_value_long() != 0)
-        current_position[Z_AXIS]=code_value()+add_homing[Z_AXIS];
+      if(home_z_axis && home_z_value != 0)
+        current_position[Z_AXIS]=home_z_value+add_homing[Z_AXIS];
       #ifdef ENABLE_AUTO_BED_LEVELING
         if(home_z)
           current_position[Z_AXIS] += zprobe_zoffset;  //Add Z_Probe offset (the distance is negative)
@@ -2857,7 +2869,7 @@ void gcode_G28(bool home_x, bool home_y, bool home_z, bool calib) {
     world2machine_update_current();
 
 #if (defined(MESH_BED_LEVELING) && !defined(MK1BP))
-	if (code_seen(axis_codes[X_AXIS]) || code_seen(axis_codes[Y_AXIS]) || code_seen('W') || code_seen(axis_codes[Z_AXIS]))
+	if (home_x_axis || home_y_axis || without_mbl || home_z_axis)
 		{
       if (! home_z && mbl_was_active) {
         // Re-enable the mesh bed leveling if only the X and Y axes were re-homed.
@@ -2870,10 +2882,6 @@ void gcode_G28(bool home_x, bool home_y, bool home_z, bool calib) {
 		{
 			st_synchronize();
 			homing_flag = false;
-			// Push the commands to the front of the message queue in the reverse order!
-			// There shall be always enough space reserved for these commands.
-			enquecommand_front_P((PSTR("G80")));
-			//goto case_G80;
 	  }
 #endif
 
@@ -2955,8 +2963,9 @@ bool gcode_M45(bool onlyZ, int8_t verbosity_level)
 		    lcd_show_fullscreen_message_and_wait_P(_T(MSG_PAPER));
 			KEEPALIVE_STATE(IN_HANDLER);
 			lcd_display_message_fullscreen_P(_T(MSG_FIND_BED_OFFSET_AND_SKEW_LINE1));
-			lcd_implementation_print_at(0, 2, 1);
-			lcd_printPGM(_T(MSG_FIND_BED_OFFSET_AND_SKEW_LINE2));
+			lcd_set_cursor(0, 2);
+			lcd_print(1);
+			lcd_puts_P(_T(MSG_FIND_BED_OFFSET_AND_SKEW_LINE2));
 		}
 		// Move the print head close to the bed.
 		current_position[Z_AXIS] = MESH_HOME_Z_SEARCH;
@@ -3106,10 +3115,17 @@ void gcode_M701()
 	custom_message = true;
 	custom_message_type = 2;
 
+	
+
 	lcd_setstatuspgm(_T(MSG_LOADING_FILAMENT));
-	current_position[E_AXIS] += 70;
+	current_position[E_AXIS] += 40;
 	plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 400 / 60, active_extruder); //fast sequence
+	st_synchronize();
 
+	if (current_position[Z_AXIS] < 20) current_position[Z_AXIS] += 30;
+	current_position[E_AXIS] += 30;
+	plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 400 / 60, active_extruder); //fast sequence
+	st_synchronize();
 	current_position[E_AXIS] += 25;
 	plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 100 / 60, active_extruder); //slow sequence
 	st_synchronize();
@@ -3190,6 +3206,13 @@ static void gcode_PRUSA_SN()
     }
 }
 
+#ifdef BACKLASH_X
+extern uint8_t st_backlash_x;
+#endif //BACKLASH_X
+#ifdef BACKLASH_Y
+extern uint8_t st_backlash_y;
+#endif //BACKLASH_Y
+
 void process_commands()
 {
 	if (!buflen) return; //empty command
@@ -3245,18 +3268,77 @@ void process_commands()
 	}
 	else if (strncmp_P(CMDBUFFER_CURRENT_STRING, PSTR("TMC_"), 4) == 0)
 	{
-		if (strncmp_P(CMDBUFFER_CURRENT_STRING + 4, PSTR("SET_WAVE_E"), 10) == 0)
+		if (strncmp_P(CMDBUFFER_CURRENT_STRING + 4, PSTR("SET_WAVE_"), 9) == 0)
 		{
-			uint8_t fac = (uint8_t)strtol(CMDBUFFER_CURRENT_STRING + 14, NULL, 10);
-			tmc2130_set_wave(E_AXIS, 247, fac);
+			uint8_t axis = *(CMDBUFFER_CURRENT_STRING + 13);
+			axis = (axis == 'E')?3:(axis - 'X');
+			if (axis < 4)
+			{
+				uint8_t fac = (uint8_t)strtol(CMDBUFFER_CURRENT_STRING + 14, NULL, 10);
+				tmc2130_set_wave(axis, 247, fac);
+			}
 		}
-		else if (strncmp_P(CMDBUFFER_CURRENT_STRING + 4, PSTR("SET_STEP_E"), 10) == 0)
+		else if (strncmp_P(CMDBUFFER_CURRENT_STRING + 4, PSTR("SET_STEP_"), 9) == 0)
 		{
-			uint8_t step = (uint8_t)strtol(CMDBUFFER_CURRENT_STRING + 14, NULL, 10);
-			uint16_t res = tmc2130_get_res(E_AXIS);
-			tmc2130_goto_step(E_AXIS, step & (4*res - 1), 2, 1000, res);
+			uint8_t axis = *(CMDBUFFER_CURRENT_STRING + 13);
+			axis = (axis == 'E')?3:(axis - 'X');
+			if (axis < 4)
+			{
+				uint8_t step = (uint8_t)strtol(CMDBUFFER_CURRENT_STRING + 14, NULL, 10);
+				uint16_t res = tmc2130_get_res(axis);
+				tmc2130_goto_step(axis, step & (4*res - 1), 2, 1000, res);
+			}
 		}
+		else if (strncmp_P(CMDBUFFER_CURRENT_STRING + 4, PSTR("SET_CHOP_"), 9) == 0)
+		{
+			uint8_t axis = *(CMDBUFFER_CURRENT_STRING + 13);
+			axis = (axis == 'E')?3:(axis - 'X');
+			if (axis < 4)
+			{
+				uint8_t chop0 = tmc2130_chopper_config[axis].toff;
+				uint8_t chop1 = tmc2130_chopper_config[axis].hstr;
+				uint8_t chop2 = tmc2130_chopper_config[axis].hend;
+				uint8_t chop3 = tmc2130_chopper_config[axis].tbl;
+				char* str_end = 0;
+				if (CMDBUFFER_CURRENT_STRING[14])
+				{
+					chop0 = (uint8_t)strtol(CMDBUFFER_CURRENT_STRING + 14, &str_end, 10) & 15;
+					if (str_end && *str_end)
+					{
+						chop1 = (uint8_t)strtol(str_end, &str_end, 10) & 7;
+						if (str_end && *str_end)
+						{
+							chop2 = (uint8_t)strtol(str_end, &str_end, 10) & 15;
+							if (str_end && *str_end)
+								chop3 = (uint8_t)strtol(str_end, &str_end, 10) & 3;
+						}
+					}
+				}
+				tmc2130_chopper_config[axis].toff = chop0;
+				tmc2130_chopper_config[axis].hstr = chop1 & 7;
+				tmc2130_chopper_config[axis].hend = chop2 & 15;
+				tmc2130_chopper_config[axis].tbl = chop3 & 3;
+				tmc2130_setup_chopper(axis, tmc2130_mres[axis], tmc2130_current_h[axis], tmc2130_current_r[axis]);
+				//printf_P(_N("TMC_SET_CHOP_%c %hhd %hhd %hhd %hhd\n"), "xyze"[axis], chop0, chop1, chop2, chop3);
+			}
+		}
+	}
+#ifdef BACKLASH_X
+	else if (strncmp_P(CMDBUFFER_CURRENT_STRING, PSTR("BACKLASH_X"), 10) == 0)
+	{
+		uint8_t bl = (uint8_t)strtol(CMDBUFFER_CURRENT_STRING + 10, NULL, 10);
+		st_backlash_x = bl;
+		printf_P(_N("st_backlash_x = %hhd\n"), st_backlash_x);
 	}
+#endif //BACKLASH_X
+#ifdef BACKLASH_Y
+	else if (strncmp_P(CMDBUFFER_CURRENT_STRING, PSTR("BACKLASH_Y"), 10) == 0)
+	{
+		uint8_t bl = (uint8_t)strtol(CMDBUFFER_CURRENT_STRING + 10, NULL, 10);
+		st_backlash_y = bl;
+		printf_P(_N("st_backlash_y = %hhd\n"), st_backlash_y);
+	}
+#endif //BACKLASH_Y
 #endif //TMC2130
 
   else if(code_seen("PRUSA")){
@@ -3286,6 +3368,8 @@ void process_commands()
             // careful!
             if (farm_mode) {
 #ifdef WATCHDOG
+                boot_app_magic = BOOT_APP_MAGIC;
+                boot_app_flags = BOOT_APP_FLG_RUN;
 				wdt_enable(WDTO_15MS);
 				cli();
 				while(1);
@@ -3410,7 +3494,7 @@ void process_commands()
                           cnt++;
                           manage_heater();
                           manage_inactivity(true);
-                          //lcd_update();
+                          //lcd_update(0);
                           if(cnt==0)
                           {
                           #if BEEPER > 0
@@ -3435,11 +3519,6 @@ void process_commands()
                           
                             counterBeep++;
                           #else
-                      #if !defined(LCD_FEEDBACK_FREQUENCY_HZ) || !defined(LCD_FEEDBACK_FREQUENCY_DURATION_MS)
-                              lcd_buzz(1000/6,100);
-                      #else
-                        lcd_buzz(LCD_FEEDBACK_FREQUENCY_DURATION_MS,LCD_FEEDBACK_FREQUENCY_HZ);
-                      #endif
                           #endif
                           }
                         }
@@ -3576,7 +3655,7 @@ void process_commands()
       while(millis() < codenum) {
         manage_heater();
         manage_inactivity();
-        lcd_update();
+        lcd_update(0);
       }
       break;
       #ifdef FWRETRACT
@@ -3598,16 +3677,26 @@ void process_commands()
       #endif //FWRETRACT
     case 28: //G28 Home all Axis one at a time
     {
+      long home_x_value = 0;
+      long home_y_value = 0;
+      long home_z_value = 0;
       // Which axes should be homed?
       bool home_x = code_seen(axis_codes[X_AXIS]);
+      home_x_value = code_value_long();
       bool home_y = code_seen(axis_codes[Y_AXIS]);
+      home_y_value = code_value_long();
       bool home_z = code_seen(axis_codes[Z_AXIS]);
+      home_z_value = code_value_long();
+      bool without_mbl = code_seen('W');
       // calibrate?
       bool calib = code_seen('C');
-
-	  gcode_G28(home_x, home_y, home_z, calib);
-	  
-	  break;
+      gcode_G28(home_x, home_x_value, home_y, home_y_value, home_z, home_z_value, calib, without_mbl);
+      if ((home_x || home_y || without_mbl || home_z) == false) {
+         // Push the commands to the front of the message queue in the reverse order!
+         // There shall be always enough space reserved for these commands.
+         goto case_G80;
+      }
+      break;
     }
 #ifdef ENABLE_AUTO_BED_LEVELING
     case 29: // G29 Detailed Z-Probe, probes the bed at 3 or more points.
@@ -3847,7 +3936,7 @@ void process_commands()
 				current_position[X_AXIS] = pgm_read_float(bed_ref_points_4);
 				plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 3000 / 60, active_extruder);
 				st_synchronize();
-				gcode_G28(false, false, true, false);
+				gcode_G28(false, false, true);
 
 			}
 			if ((current_temperature_pinda > 35) && (farm_mode == false)) {
@@ -4586,7 +4675,6 @@ void process_commands()
 	  } else
     switch((int)code_value())
     {
-#ifdef ULTIPANEL
 
     case 0: // M0 - Unconditional stop - Wait for user button press on LCD
     case 1: // M1 - Conditional stop - Wait for user button press on LCD
@@ -4622,18 +4710,16 @@ void process_commands()
         while(millis() < codenum && !lcd_clicked()){
           manage_heater();
           manage_inactivity(true);
-          lcd_update();
+          lcd_update(0);
         }
 		KEEPALIVE_STATE(IN_HANDLER);
         lcd_ignore_click(false);
       }else{
-          if (!lcd_detected())
-            break;
 		KEEPALIVE_STATE(PAUSED_FOR_USER);
         while(!lcd_clicked()){
           manage_heater();
           manage_inactivity(true);
-          lcd_update();
+          lcd_update(0);
         }
 		KEEPALIVE_STATE(IN_HANDLER);
       }
@@ -4643,7 +4729,6 @@ void process_commands()
         LCD_MESSAGERPGM(_T(WELCOME_MSG));
     }
     break;
-#endif
     case 17:
         LCD_MESSAGERPGM(_i("No move."));////MSG_NO_MOVE c=0 r=0
         enable_x();
@@ -4656,9 +4741,9 @@ void process_commands()
 
 #ifdef SDSUPPORT
     case 20: // M20 - list SD card
-      SERIAL_PROTOCOLLNRPGM(_i("Begin file list"));////MSG_BEGIN_FILE_LIST c=0 r=0
+      SERIAL_PROTOCOLLNRPGM(_N("Begin file list"));////MSG_BEGIN_FILE_LIST c=0 r=0
       card.ls();
-      SERIAL_PROTOCOLLNRPGM(_i("End file list"));////MSG_END_FILE_LIST c=0 r=0
+      SERIAL_PROTOCOLLNRPGM(_N("End file list"));////MSG_END_FILE_LIST c=0 r=0
       break;
     case 21: // M21 - init SD card
 
@@ -5365,7 +5450,7 @@ Sigma_Exit:
           }
           manage_heater();
           manage_inactivity();
-          lcd_update();
+          lcd_update(0);
         }
         LCD_MESSAGERPGM(_T(MSG_BED_DONE));
 		KEEPALIVE_STATE(IN_HANDLER);
@@ -5402,11 +5487,9 @@ Sigma_Exit:
             WRITE(SUICIDE_PIN, HIGH);
         #endif
 
-        #ifdef ULTIPANEL
           powersupply = true;
           LCD_MESSAGERPGM(_T(WELCOME_MSG));
-          lcd_update();
-        #endif
+          lcd_update(0);
         break;
       #endif
 
@@ -5426,11 +5509,9 @@ Sigma_Exit:
         SET_OUTPUT(PS_ON_PIN);
         WRITE(PS_ON_PIN, PS_ON_ASLEEP);
       #endif
-      #ifdef ULTIPANEL
         powersupply = false;
         LCD_MESSAGERPGM(CAT4(CUSTOM_MENDEL_NAME,PSTR(" "),MSG_OFF,PSTR(".")));
-        lcd_update();
-      #endif
+        lcd_update(0);
 	  break;
 
     case 82:
@@ -5563,7 +5644,7 @@ Sigma_Exit:
       enable_endstops(true) ;
       break;
     case 119: // M119
-    SERIAL_PROTOCOLRPGM(_i("Reporting endstop status"));////MSG_M119_REPORT c=0 r=0
+    SERIAL_PROTOCOLRPGM(_N("Reporting endstop status"));////MSG_M119_REPORT c=0 r=0
     SERIAL_PROTOCOLLN("");
       #if defined(X_MIN_PIN) && X_MIN_PIN > -1
         SERIAL_PROTOCOLRPGM(_n("x_min: "));////MSG_X_MIN c=0 r=0
@@ -5890,7 +5971,7 @@ Sigma_Exit:
             while(digitalRead(pin_number) != target){
               manage_heater();
               manage_inactivity();
-              lcd_update();
+              lcd_update(0);
             }
           }
         }
@@ -5948,10 +6029,6 @@ Sigma_Exit:
           tone(BEEPER, beepS);
           delay(beepP);
           noTone(BEEPER);
-        #elif defined(ULTRALCD)
-		  lcd_buzz(beepS, beepP);
-		#elif defined(LCD_USE_I2C_BUZZER)
-		  lcd_buzz(beepP, beepS);
         #endif
       }
       else
@@ -6040,18 +6117,6 @@ Sigma_Exit:
       #endif //chdk end if
      }
     break;
-#ifdef DOGLCD
-    case 250: // M250  Set LCD contrast value: C<value> (value 0..63)
-     {
-	  if (code_seen('C')) {
-	   lcd_setcontrast( ((int)code_value())&63 );
-          }
-          SERIAL_PROTOCOLPGM("lcd contrast value: ");
-          SERIAL_PROTOCOL(lcd_contrast);
-          SERIAL_PROTOCOLLN("");
-     }
-    break;
-#endif
     #ifdef PREVENT_DANGEROUS_EXTRUDE
     case 302: // allow cold extrudes, or set the minimum extrude temperature
     {
@@ -6278,11 +6343,6 @@ Sigma_Exit:
 				
 				counterBeep++;
 #else
-#if !defined(LCD_FEEDBACK_FREQUENCY_HZ) || !defined(LCD_FEEDBACK_FREQUENCY_DURATION_MS)
-				lcd_buzz(1000 / 6, 100);
-#else
-				lcd_buzz(LCD_FEEDBACK_FREQUENCY_DURATION_MS, LCD_FEEDBACK_FREQUENCY_HZ);
-#endif
 #endif
 			}
 			
@@ -6321,8 +6381,8 @@ Sigma_Exit:
 				}
 				else {
 					counterBeep = 20; //beeper will be inactive during waiting for nozzle preheat
-					lcd.setCursor(1, 4);
-					lcd.print(ftostr3(degHotend(active_extruder)));
+					lcd_set_cursor(1, 4);
+					lcd_print(ftostr3(degHotend(active_extruder)));
 				}
 				break;
 
@@ -6680,7 +6740,7 @@ Sigma_Exit:
 			}
 			manage_heater();
 			manage_inactivity();
-			lcd_update();
+			lcd_update(0);
 		}
 		LCD_MESSAGERPGM(_T(MSG_OK));
 
@@ -7586,13 +7646,13 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) //default argument s
                 else
                 {
                     lcd_update_enable(false);
-                    lcd_implementation_clear();
-                    lcd.setCursor(0, 0);
-                    lcd_printPGM(_T(MSG_ERROR));
-                    lcd.setCursor(0, 2);
-                    lcd_printPGM(_T(MSG_PREHEAT_NOZZLE));
+                    lcd_clear();
+                    lcd_set_cursor(0, 0);
+                    lcd_puts_P(_T(MSG_ERROR));
+                    lcd_set_cursor(0, 2);
+                    lcd_puts_P(_T(MSG_PREHEAT_NOZZLE));
                     delay(2000);
-                    lcd_implementation_clear();
+                    lcd_clear();
                     lcd_update_enable(true);
                 }
                 
@@ -7724,7 +7784,7 @@ void kill(const char *full_screen_message, unsigned char id)
 
   // FMC small patch to update the LCD before ending
   sei();   // enable interrupts
-  for ( int i=5; i--; lcd_update())
+  for ( int i=5; i--; lcd_update(0))
   {
      delay(200);	
   }
@@ -7899,7 +7959,7 @@ void delay_keep_alive(unsigned int ms)
         manage_heater();
         // Manage inactivity, but don't disable steppers on timeout.
         manage_inactivity(true);
-        lcd_update();
+        lcd_update(0);
         if (ms == 0)
             break;
         else if (ms >= 50) {
@@ -7951,7 +8011,7 @@ void wait_for_heater(long codenum) {
 		}
 			manage_heater();
 			manage_inactivity();
-			lcd_update();
+			lcd_update(0);
 #ifdef TEMP_RESIDENCY_TIME
 			/* start/restart the TEMP_RESIDENCY_TIME timer whenever we reach target temp for the first time
 			or when current temp falls outside the hysteresis after target temp was reached */

+ 0 - 29
Firmware/MenuStack.cpp

@@ -1,29 +0,0 @@
-/**
- * @file
- * @author Marek Bel
- */
-
-#include "MenuStack.h"
-/**
- * @brief Push menu on stack
- * @param menu
- * @param position selected position in menu being pushed
- */
-void MenuStack::push(menuFunc_t menu, int8_t position)
-{
-    if (m_index >= max_depth) return;
-    m_stack[m_index].menu = menu;
-    m_stack[m_index].position = position;
-    ++m_index;
-}
-
-/**
- * @brief Pop menu from stack
- * @return Record containing menu function pointer and previously selected line number
- */
-MenuStack::Record MenuStack::pop()
-{
-    if (m_index != 0) m_index--;
-
-    return m_stack[m_index];
-}

+ 0 - 34
Firmware/MenuStack.h

@@ -1,34 +0,0 @@
-/**
- * @file
- * @author Marek Bel
- */
-
-#ifndef MENUSTACK_H
-#define MENUSTACK_H
-
-#include <stdint.h>
-
-/** Pointer to function implementing menu.*/
-typedef void (*menuFunc_t)();
-/**
- * @brief Stack implementation for navigating menu structure
- */
-class MenuStack
-{
-public:
-    struct Record
-    {
-        menuFunc_t menu;
-        int8_t position;
-    };
-    MenuStack():m_stack(),m_index(0) {}
-    void push(menuFunc_t menu, int8_t position);
-    Record pop();
-    void reset(){m_index = 0;}
-private:
-    static const int max_depth = 4;
-    Record m_stack[max_depth];
-    uint8_t m_index;
-};
-
-#endif /* FIRMWARE_MENUSTACK_H_ */

+ 1 - 0
Firmware/bootapp.h

@@ -17,6 +17,7 @@
 #define BOOT_APP_FLG_ERASE 0x01
 #define BOOT_APP_FLG_COPY  0x02
 #define BOOT_APP_FLG_FLASH 0x04
+#define BOOT_APP_FLG_RUN 0x08
 
 #define BOOT_APP_FLG_USER0 0x80
 

+ 17 - 10
Firmware/cardreader.cpp

@@ -392,13 +392,13 @@ void CardReader::openFile(char* name,bool read, bool replace_current/*=true*/)
     if (file.open(curDir, fname, O_READ)) 
     {
       filesize = file.fileSize();
-      SERIAL_PROTOCOLRPGM(_i("File opened: "));////MSG_SD_FILE_OPENED c=0 r=0
+      SERIAL_PROTOCOLRPGM(_N("File opened: "));////MSG_SD_FILE_OPENED c=0 r=0
       SERIAL_PROTOCOL(fname);
       SERIAL_PROTOCOLRPGM(_n(" Size: "));////MSG_SD_SIZE c=0 r=0
       SERIAL_PROTOCOLLN(filesize);
       sdpos = 0;
       
-      SERIAL_PROTOCOLLNRPGM(_i("File selected"));////MSG_SD_FILE_SELECTED c=0 r=0
+      SERIAL_PROTOCOLLNRPGM(_N("File selected"));////MSG_SD_FILE_SELECTED c=0 r=0
       getfilename(0, fname);
       lcd_setstatus(longFilename[0] ? longFilename : fname);
       lcd_setstatus("SD-PRINTING         ");
@@ -421,7 +421,7 @@ void CardReader::openFile(char* name,bool read, bool replace_current/*=true*/)
     else
     {
       saving = true;
-      SERIAL_PROTOCOLRPGM(_i("Writing to file: "));////MSG_SD_WRITE_TO_FILE c=0 r=0
+      SERIAL_PROTOCOLRPGM(_N("Writing to file: "));////MSG_SD_WRITE_TO_FILE c=0 r=0
       SERIAL_PROTOCOLLN(name);
       lcd_setstatus(fname);
     }
@@ -513,7 +513,7 @@ void CardReader::getStatus()
   if(sdprinting){
     SERIAL_PROTOCOL(longFilename);
     SERIAL_PROTOCOLPGM("\n");
-    SERIAL_PROTOCOLRPGM(_i("SD printing byte "));////MSG_SD_PRINTING_BYTE c=0 r=0
+    SERIAL_PROTOCOLRPGM(_N("SD printing byte "));////MSG_SD_PRINTING_BYTE c=0 r=0
     SERIAL_PROTOCOL(sdpos);
     SERIAL_PROTOCOLPGM("/");
     SERIAL_PROTOCOLLN(filesize);
@@ -757,11 +757,11 @@ void CardReader::presort() {
 			lcd_show_fullscreen_message_and_wait_P(_i("Some files will not be sorted. Max. No. of files in 1 folder for sorting is 100."));////MSG_FILE_CNT c=20 r=4
 			fileCnt = SDSORT_LIMIT;
 		}
-		lcd_implementation_clear();
+		lcd_clear();
 		#if !SDSORT_USES_RAM
 			lcd_set_progress();
 		#endif
-		lcd_print_at_PGM(0, 1, _i("Sorting files"));////MSG_SORTING c=20 r=1
+		lcd_puts_at_P(0, 1, _i("Sorting files"));////MSG_SORTING c=20 r=1
 
 		// Sort order is always needed. May be static or dynamic.
 		#if SDSORT_DYNAMIC_RAM
@@ -889,7 +889,11 @@ void CardReader::presort() {
 				#if !SDSORT_USES_RAM //show progresss bar only if slow sorting method is used
 				int8_t percent = (counter * 100) / total;//((counter * 100) / pow((fileCnt-1),2));
 				for (int column = 0; column < 20; column++) {
-					if (column < (percent / 5)) lcd_implementation_print_at(column, 2, "\x01"); //simple progress bar
+					if (column < (percent / 5))
+					{
+						lcd_set_cursor(column, 2);
+						lcd_print('\x01'); //simple progress bar
+					}
 				}
 				counter++;
 				#endif
@@ -964,11 +968,14 @@ void CardReader::presort() {
 		sort_count = fileCnt;
 	}
 #if !SDSORT_USES_RAM //show progresss bar only if slow sorting method is used
-	for (int column = 0; column <= 19; column++)	lcd_implementation_print_at(column, 2, "\x01"); //simple progress bar	
+	for (int column = 0; column <= 19; column++)
+	{
+		lcd_set_cursor(column, 2);
+		lcd_print('\x01'); //simple progress bar
+	}
 	delay(300);
 	lcd_set_degree();
-	lcd_implementation_clear();
-	lcd_update(2);
+	lcd_clear();
 #endif
 	lcd_update(2);
 	KEEPALIVE_STATE(NOT_BUSY);

+ 1 - 0
Firmware/cmdqueue.cpp

@@ -476,6 +476,7 @@ void get_command()
             SERIAL_ERROR_START;
             SERIAL_ERRORRPGM(_n("No Line Number with checksum, Last Line: "));////MSG_ERR_NO_LINENUMBER_WITH_CHECKSUM c=0 r=0
             SERIAL_ERRORLN(gcode_LastN);
+			FlushSerialRequestResend();
             serial_count = 0;
             return;
         }

+ 16 - 0
Firmware/config.h

@@ -8,6 +8,22 @@
 #define ADC_OVRSAMPL      16        //oversampling multiplier
 #define ADC_CALLBACK      adc_ready //callback function ()
 
+//SWI2C configuration
+#define SWI2C
+//#define SWI2C_SDA         20 //SDA on P3
+//#define SWI2C_SCL         21 //SCL on P3
+#define SWI2C_A8
+#define SWI2C_DEL         20 //2us clock delay
+#define SWI2C_TMO         2048 //2048 cycles timeout
+
+//PAT9125 configuration
+#define PAT9125_SWI2C
+#define PAT9125_I2C_ADDR  0x75  //ID=LO
+//#define PAT9125_I2C_ADDR  0x79  //ID=HI
+//#define PAT9125_I2C_ADDR  0x73  //ID=NC
+#define PAT9125_XRES      0
+#define PAT9125_YRES      200
+
 //SM4 configuration
 #define SM4_DEFDELAY      500       //default step delay [us]
 

+ 292 - 0
Firmware/conv2str.cpp

@@ -0,0 +1,292 @@
+//conv2str.cpp - Float conversion utilities
+
+#include "conv2str.h"
+#include <stdlib.h>
+
+
+//  convert float to string with +123.4 format
+char conv[8];
+
+char *ftostr3(const float &x)
+{
+  return itostr3((int)x);
+}
+
+char *itostr2(const uint8_t &x)
+{
+  //sprintf(conv,"%5.1f",x);
+  int xx = x;
+  conv[0] = (xx / 10) % 10 + '0';
+  conv[1] = (xx) % 10 + '0';
+  conv[2] = 0;
+  return conv;
+}
+
+// Convert float to string with 123.4 format, dropping sign
+char *ftostr31(const float &x)
+{
+  int xx = x * 10;
+  conv[0] = (xx >= 0) ? '+' : '-';
+  xx = abs(xx);
+  conv[1] = (xx / 1000) % 10 + '0';
+  conv[2] = (xx / 100) % 10 + '0';
+  conv[3] = (xx / 10) % 10 + '0';
+  conv[4] = '.';
+  conv[5] = (xx) % 10 + '0';
+  conv[6] = 0;
+  return conv;
+}
+
+// Convert float to string with 123.4 format
+char *ftostr31ns(const float &x)
+{
+  int xx = x * 10;
+  //conv[0]=(xx>=0)?'+':'-';
+  xx = abs(xx);
+  conv[0] = (xx / 1000) % 10 + '0';
+  conv[1] = (xx / 100) % 10 + '0';
+  conv[2] = (xx / 10) % 10 + '0';
+  conv[3] = '.';
+  conv[4] = (xx) % 10 + '0';
+  conv[5] = 0;
+  return conv;
+}
+
+char *ftostr32(const float &x)
+{
+  long xx = x * 100;
+  if (xx >= 0)
+    conv[0] = (xx / 10000) % 10 + '0';
+  else
+    conv[0] = '-';
+  xx = abs(xx);
+  conv[1] = (xx / 1000) % 10 + '0';
+  conv[2] = (xx / 100) % 10 + '0';
+  conv[3] = '.';
+  conv[4] = (xx / 10) % 10 + '0';
+  conv[5] = (xx) % 10 + '0';
+  conv[6] = 0;
+  return conv;
+}
+
+//// Convert float to rj string with 123.45 format
+char *ftostr32ns(const float &x) {
+	long xx = abs(x);
+	conv[0] = xx >= 10000 ? (xx / 10000) % 10 + '0' : ' ';
+	conv[1] = xx >= 1000 ? (xx / 1000) % 10 + '0' : ' ';
+	conv[2] = xx >= 100 ? (xx / 100) % 10 + '0' : '0';
+	conv[3] = '.';
+	conv[4] = (xx / 10) % 10 + '0';
+	conv[5] = xx % 10 + '0';
+	return conv;
+}
+
+
+// Convert float to string with 1.234 format
+char *ftostr43(const float &x, uint8_t offset)
+{
+  const size_t maxOffset = sizeof(conv)/sizeof(conv[0]) - 6;
+  if (offset>maxOffset) offset = maxOffset;
+  long xx = x * 1000;
+  if (xx >= 0)
+    conv[offset] = (xx / 1000) % 10 + '0';
+  else
+    conv[offset] = '-';
+  xx = abs(xx);
+  conv[offset + 1] = '.';
+  conv[offset + 2] = (xx / 100) % 10 + '0';
+  conv[offset + 3] = (xx / 10) % 10 + '0';
+  conv[offset + 4] = (xx) % 10 + '0';
+  conv[offset + 5] = 0;
+  return conv;
+}
+
+//Float to string with 1.23 format
+char *ftostr12ns(const float &x)
+{
+  long xx = x * 100;
+
+  xx = abs(xx);
+  conv[0] = (xx / 100) % 10 + '0';
+  conv[1] = '.';
+  conv[2] = (xx / 10) % 10 + '0';
+  conv[3] = (xx) % 10 + '0';
+  conv[4] = 0;
+  return conv;
+}
+
+//Float to string with 1.234 format
+char *ftostr13ns(const float &x)
+{
+    long xx = x * 1000;
+    if (xx >= 0)
+        conv[0] = ' ';
+    else
+        conv[0] = '-';
+    xx = abs(xx);
+    conv[1] = (xx / 1000) % 10 + '0';
+    conv[2] = '.';
+    conv[3] = (xx / 100) % 10 + '0';
+    conv[4] = (xx / 10) % 10 + '0';
+    conv[5] = (xx) % 10 + '0';
+    conv[6] = 0;
+    return conv;
+}
+
+//  convert float to space-padded string with -_23.4_ format
+char *ftostr32sp(const float &x) {
+  long xx = abs(x * 100);
+  uint8_t dig;
+
+  if (x < 0) { // negative val = -_0
+    conv[0] = '-';
+    dig = (xx / 1000) % 10;
+    conv[1] = dig ? '0' + dig : ' ';
+  }
+  else { // positive val = __0
+    dig = (xx / 10000) % 10;
+    if (dig) {
+      conv[0] = '0' + dig;
+      conv[1] = '0' + (xx / 1000) % 10;
+    }
+    else {
+      conv[0] = ' ';
+      dig = (xx / 1000) % 10;
+      conv[1] = dig ? '0' + dig : ' ';
+    }
+  }
+
+  conv[2] = '0' + (xx / 100) % 10; // lsd always
+
+  dig = xx % 10;
+  if (dig) { // 2 decimal places
+    conv[5] = '0' + dig;
+    conv[4] = '0' + (xx / 10) % 10;
+    conv[3] = '.';
+  }
+  else { // 1 or 0 decimal place
+    dig = (xx / 10) % 10;
+    if (dig) {
+      conv[4] = '0' + dig;
+      conv[3] = '.';
+    }
+    else {
+      conv[3] = conv[4] = ' ';
+    }
+    conv[5] = ' ';
+  }
+  conv[6] = '\0';
+  return conv;
+}
+
+char *itostr31(const int &xx)
+{
+  conv[0] = (xx >= 0) ? '+' : '-';
+  conv[1] = (xx / 1000) % 10 + '0';
+  conv[2] = (xx / 100) % 10 + '0';
+  conv[3] = (xx / 10) % 10 + '0';
+  conv[4] = '.';
+  conv[5] = (xx) % 10 + '0';
+  conv[6] = 0;
+  return conv;
+}
+
+// Convert int to rj string with 123 or -12 format
+char *itostr3(const int &x)
+{
+  int xx = x;
+  if (xx < 0) {
+    conv[0] = '-';
+    xx = -xx;
+  } else if (xx >= 100)
+    conv[0] = (xx / 100) % 10 + '0';
+  else
+    conv[0] = ' ';
+  if (xx >= 10)
+    conv[1] = (xx / 10) % 10 + '0';
+  else
+    conv[1] = ' ';
+  conv[2] = (xx) % 10 + '0';
+  conv[3] = 0;
+  return conv;
+}
+
+// Convert int to lj string with 123 format
+char *itostr3left(const int &xx)
+{
+  if (xx >= 100)
+  {
+    conv[0] = (xx / 100) % 10 + '0';
+    conv[1] = (xx / 10) % 10 + '0';
+    conv[2] = (xx) % 10 + '0';
+    conv[3] = 0;
+  }
+  else if (xx >= 10)
+  {
+    conv[0] = (xx / 10) % 10 + '0';
+    conv[1] = (xx) % 10 + '0';
+    conv[2] = 0;
+  }
+  else
+  {
+    conv[0] = (xx) % 10 + '0';
+    conv[1] = 0;
+  }
+  return conv;
+}
+
+// Convert int to rj string with 1234 format
+char *itostr4(const int &xx) {
+  conv[0] = xx >= 1000 ? (xx / 1000) % 10 + '0' : ' ';
+  conv[1] = xx >= 100 ? (xx / 100) % 10 + '0' : ' ';
+  conv[2] = xx >= 10 ? (xx / 10) % 10 + '0' : ' ';
+  conv[3] = xx % 10 + '0';
+  conv[4] = 0;
+  return conv;
+}
+
+// Convert float to rj string with 12345 format
+char *ftostr5(const float &x) {
+  long xx = abs(x);
+  conv[0] = xx >= 10000 ? (xx / 10000) % 10 + '0' : ' ';
+  conv[1] = xx >= 1000 ? (xx / 1000) % 10 + '0' : ' ';
+  conv[2] = xx >= 100 ? (xx / 100) % 10 + '0' : ' ';
+  conv[3] = xx >= 10 ? (xx / 10) % 10 + '0' : ' ';
+  conv[4] = xx % 10 + '0';
+  conv[5] = 0;
+  return conv;
+}
+
+// Convert float to string with +1234.5 format
+char *ftostr51(const float &x)
+{
+  long xx = x * 10;
+  conv[0] = (xx >= 0) ? '+' : '-';
+  xx = abs(xx);
+  conv[1] = (xx / 10000) % 10 + '0';
+  conv[2] = (xx / 1000) % 10 + '0';
+  conv[3] = (xx / 100) % 10 + '0';
+  conv[4] = (xx / 10) % 10 + '0';
+  conv[5] = '.';
+  conv[6] = (xx) % 10 + '0';
+  conv[7] = 0;
+  return conv;
+}
+
+// Convert float to string with +123.45 format
+char *ftostr52(const float &x)
+{
+  long xx = x * 100;
+  conv[0] = (xx >= 0) ? '+' : '-';
+  xx = abs(xx);
+  conv[1] = (xx / 10000) % 10 + '0';
+  conv[2] = (xx / 1000) % 10 + '0';
+  conv[3] = (xx / 100) % 10 + '0';
+  conv[4] = '.';
+  conv[5] = (xx / 10) % 10 + '0';
+  conv[6] = (xx) % 10 + '0';
+  conv[7] = 0;
+  return conv;
+}
+
+

+ 28 - 0
Firmware/conv2str.h

@@ -0,0 +1,28 @@
+//conv2str.h - Float conversion utilities
+#ifndef _CONV2STR_H
+#define _CONV2STR_H
+
+#include <inttypes.h>
+
+
+char *itostr2(const uint8_t &x);
+char *itostr31(const int &xx);
+char *itostr3(const int &xx);
+char *itostr3left(const int &xx);
+char *itostr4(const int &xx);
+
+char *ftostr3(const float &x);
+char *ftostr31ns(const float &x); // float to string without sign character
+char *ftostr31(const float &x);
+char *ftostr32(const float &x);
+char *ftostr32ns(const float &x);
+char *ftostr43(const float &x, uint8_t offset = 0);
+char *ftostr12ns(const float &x);
+char *ftostr13ns(const float &x);
+char *ftostr32sp(const float &x); // remove zero-padding from ftostr32
+char *ftostr5(const float &x);
+char *ftostr51(const float &x);
+char *ftostr52(const float &x);
+
+
+#endif //_CONV2STR_H

+ 6 - 2
Firmware/fsensor.cpp

@@ -9,8 +9,6 @@
 #include "fastio.h"
 #include "cmdqueue.h"
 
-//#include "LiquidCrystal_Prusa.h"
-//extern LiquidCrystal_Prusa lcd;
 
 
 #define FSENSOR_ERR_MAX          5  //filament sensor max error count
@@ -86,6 +84,12 @@ void fsensor_disable()
 	FSensorStateMenu = 0;
 }
 
+void fautoload_set(bool State)
+{
+	filament_autoload_enabled = State;
+	eeprom_update_byte((unsigned char *)EEPROM_FSENS_AUTOLOAD_ENABLED, filament_autoload_enabled);
+}
+
 void pciSetup(byte pin)
 {
 	*digitalPinToPCMSK(pin) |= bit (digitalPinToPCMSKbit(pin)); // enable pin

+ 3 - 0
Firmware/fsensor.h

@@ -15,6 +15,9 @@ extern void fsensor_unblock();
 extern bool fsensor_enable();
 extern void fsensor_disable();
 
+extern bool filament_autoload_enabled;
+extern void fautoload_set(bool State);
+
 //update (perform M600 on filament runout)
 extern void fsensor_update();
 

+ 1083 - 0
Firmware/lcd.cpp

@@ -0,0 +1,1083 @@
+//menu.cpp
+
+#include "lcd.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include <avr/pgmspace.h>
+#include <avr/delay.h>
+#include "Timer.h"
+
+#include "Configuration.h"
+#include "pins.h"
+#include <binary.h>
+//#include <Arduino.h>
+#include "Marlin.h"
+#include "fastio.h"
+
+
+// commands
+#define LCD_CLEARDISPLAY 0x01
+#define LCD_RETURNHOME 0x02
+#define LCD_ENTRYMODESET 0x04
+#define LCD_DISPLAYCONTROL 0x08
+#define LCD_CURSORSHIFT 0x10
+#define LCD_FUNCTIONSET 0x20
+#define LCD_SETCGRAMADDR 0x40
+#define LCD_SETDDRAMADDR 0x80
+
+// flags for display entry mode
+#define LCD_ENTRYRIGHT 0x00
+#define LCD_ENTRYLEFT 0x02
+#define LCD_ENTRYSHIFTINCREMENT 0x01
+#define LCD_ENTRYSHIFTDECREMENT 0x00
+
+// flags for display on/off control
+#define LCD_DISPLAYON 0x04
+#define LCD_DISPLAYOFF 0x00
+#define LCD_CURSORON 0x02
+#define LCD_CURSOROFF 0x00
+#define LCD_BLINKON 0x01
+#define LCD_BLINKOFF 0x00
+
+// flags for display/cursor shift
+#define LCD_DISPLAYMOVE 0x08
+#define LCD_CURSORMOVE 0x00
+#define LCD_MOVERIGHT 0x04
+#define LCD_MOVELEFT 0x00
+
+// flags for function set
+#define LCD_8BITMODE 0x10
+#define LCD_4BITMODE 0x00
+#define LCD_2LINE 0x08
+#define LCD_1LINE 0x00
+#define LCD_5x10DOTS 0x04
+#define LCD_5x8DOTS 0x00
+
+
+FILE _lcdout = {0};
+
+
+uint8_t lcd_rs_pin; // LOW: command.  HIGH: character.
+uint8_t lcd_rw_pin; // LOW: write to LCD.  HIGH: read from LCD.
+uint8_t lcd_enable_pin; // activated by a HIGH pulse.
+uint8_t lcd_data_pins[8];
+
+uint8_t lcd_displayfunction;
+uint8_t lcd_displaycontrol;
+uint8_t lcd_displaymode;
+
+uint8_t lcd_numlines;
+uint8_t lcd_currline;
+
+uint8_t lcd_escape[8];
+
+
+void lcd_pulseEnable(void)
+{
+	digitalWrite(lcd_enable_pin, LOW);
+	delayMicroseconds(1);    
+	digitalWrite(lcd_enable_pin, HIGH);
+	delayMicroseconds(1);    // enable pulse must be >450ns
+	digitalWrite(lcd_enable_pin, LOW);
+	delayMicroseconds(100);   // commands need > 37us to settle
+}
+
+void lcd_write4bits(uint8_t value)
+{
+	for (int i = 0; i < 4; i++)
+	{
+		pinMode(lcd_data_pins[i], OUTPUT);
+		digitalWrite(lcd_data_pins[i], (value >> i) & 0x01);
+	}
+	lcd_pulseEnable();
+}
+
+void lcd_write8bits(uint8_t value)
+{
+	for (int i = 0; i < 8; i++)
+	{
+		pinMode(lcd_data_pins[i], OUTPUT);
+		digitalWrite(lcd_data_pins[i], (value >> i) & 0x01);
+	}
+	lcd_pulseEnable();
+}
+
+// write either command or data, with automatic 4/8-bit selection
+void lcd_send(uint8_t value, uint8_t mode)
+{
+	digitalWrite(lcd_rs_pin, mode);
+	// if there is a RW pin indicated, set it low to Write
+	if (lcd_rw_pin != 255) digitalWrite(lcd_rw_pin, LOW);
+	if (lcd_displayfunction & LCD_8BITMODE)
+		lcd_write8bits(value); 
+	else
+	{
+		lcd_write4bits(value>>4);
+		lcd_write4bits(value);
+	}
+}
+
+void lcd_command(uint8_t value)
+{
+	lcd_send(value, LOW);
+}
+
+void lcd_clear(void);
+void lcd_home(void);
+void lcd_no_display(void);
+void lcd_display(void);
+void lcd_no_cursor(void);
+void lcd_cursor(void);
+void lcd_no_blink(void);
+void lcd_blink(void);
+void lcd_scrollDisplayLeft(void);
+void lcd_scrollDisplayRight(void);
+void lcd_leftToRight(void);
+void lcd_rightToLeft(void);
+void lcd_autoscroll(void);
+void lcd_no_autoscroll(void);
+void lcd_set_cursor(uint8_t col, uint8_t row);
+void lcd_createChar_P(uint8_t location, const uint8_t* charmap);
+
+uint8_t lcd_escape_write(uint8_t chr);
+
+uint8_t lcd_write(uint8_t value)
+{
+	if (value == '\n')
+	{
+		if (lcd_currline > 3) lcd_currline = -1;
+		lcd_set_cursor(0, lcd_currline + 1); // LF
+		return 1;
+	}
+	if (lcd_escape[0] || (value == 0x1b))
+		return lcd_escape_write(value);
+	lcd_send(value, HIGH);
+	return 1; // assume sucess
+}
+
+void lcd_begin(uint8_t cols, uint8_t lines, uint8_t dotsize, uint8_t clear)
+{
+	if (lines > 1) lcd_displayfunction |= LCD_2LINE;
+	lcd_numlines = lines;
+	lcd_currline = 0;
+	// for some 1 line displays you can select a 10 pixel high font
+	if ((dotsize != 0) && (lines == 1)) lcd_displayfunction |= LCD_5x10DOTS;
+	// SEE PAGE 45/46 FOR INITIALIZATION SPECIFICATION!
+	// according to datasheet, we need at least 40ms after power rises above 2.7V
+	// before sending commands. Arduino can turn on way befer 4.5V so we'll wait 50
+	_delay_us(50000); 
+	// Now we pull both RS and R/W low to begin commands
+	digitalWrite(lcd_rs_pin, LOW);
+	digitalWrite(lcd_enable_pin, LOW);
+	if (lcd_rw_pin != 255)
+		digitalWrite(lcd_rw_pin, LOW);
+	//put the LCD into 4 bit or 8 bit mode
+	if (!(lcd_displayfunction & LCD_8BITMODE))
+	{
+		// this is according to the hitachi HD44780 datasheet
+		// figure 24, pg 46
+		// we start in 8bit mode, try to set 4 bit mode
+		lcd_write4bits(0x03);
+		_delay_us(4500); // wait min 4.1ms
+		// second try
+		lcd_write4bits(0x03);
+		_delay_us(4500); // wait min 4.1ms
+		// third go!
+		lcd_write4bits(0x03); 
+		_delay_us(150);
+		// finally, set to 4-bit interface
+		lcd_write4bits(0x02); 
+	}
+	else
+	{
+		// this is according to the hitachi HD44780 datasheet
+		// page 45 figure 23
+		// Send function set command sequence
+		lcd_command(LCD_FUNCTIONSET | lcd_displayfunction);
+		_delay_us(4500);  // wait more than 4.1ms
+		// second try
+		lcd_command(LCD_FUNCTIONSET | lcd_displayfunction);
+		_delay_us(150);
+		// third go
+		lcd_command(LCD_FUNCTIONSET | lcd_displayfunction);
+	}
+	// finally, set # lines, font size, etc.
+	lcd_command(LCD_FUNCTIONSET | lcd_displayfunction);  
+	_delay_us(60);
+	// turn the display on with no cursor or blinking default
+	lcd_displaycontrol = LCD_DISPLAYON | LCD_CURSOROFF | LCD_BLINKOFF;  
+	lcd_display();
+	_delay_us(60);
+	// clear it off
+	if (clear) lcd_clear();
+	_delay_us(3000);
+	// Initialize to default text direction (for romance languages)
+	lcd_displaymode = LCD_ENTRYLEFT | LCD_ENTRYSHIFTDECREMENT;
+	// set the entry mode
+	lcd_command(LCD_ENTRYMODESET | lcd_displaymode);
+	_delay_us(60);
+	lcd_escape[0] = 0;
+}
+
+int lcd_putchar(char c, FILE *stream)
+{
+	lcd_write(c);
+	return 0;
+}
+
+void lcd_init(void)
+{
+	uint8_t fourbitmode = 1;
+	lcd_rs_pin = LCD_PINS_RS;
+	lcd_rw_pin = 255;
+	lcd_enable_pin = LCD_PINS_ENABLE;
+	lcd_data_pins[0] = LCD_PINS_D4;
+	lcd_data_pins[1] = LCD_PINS_D5;
+	lcd_data_pins[2] = LCD_PINS_D6;
+	lcd_data_pins[3] = LCD_PINS_D7; 
+	lcd_data_pins[4] = 0;
+	lcd_data_pins[5] = 0;
+	lcd_data_pins[6] = 0;
+	lcd_data_pins[7] = 0;
+	pinMode(lcd_rs_pin, OUTPUT);
+	// we can save 1 pin by not using RW. Indicate by passing 255 instead of pin#
+	if (lcd_rw_pin != 255) pinMode(lcd_rw_pin, OUTPUT);
+	pinMode(lcd_enable_pin, OUTPUT);
+	if (fourbitmode) lcd_displayfunction = LCD_4BITMODE | LCD_1LINE | LCD_5x8DOTS;
+	else lcd_displayfunction = LCD_8BITMODE | LCD_1LINE | LCD_5x8DOTS;
+	lcd_begin(LCD_WIDTH, LCD_HEIGHT, LCD_5x8DOTS, 1);
+	//lcd_clear();
+	fdev_setup_stream(lcdout, lcd_putchar, NULL, _FDEV_SETUP_WRITE); //setup lcdout stream
+}
+
+void lcd_refresh(void)
+{
+    lcd_begin(LCD_WIDTH, LCD_HEIGHT, LCD_5x8DOTS, 1);
+    lcd_set_custom_characters();
+}
+
+void lcd_refresh_noclear(void)
+{
+    lcd_begin(LCD_WIDTH, LCD_HEIGHT, LCD_5x8DOTS, 0);
+    lcd_set_custom_characters();
+}
+
+
+
+void lcd_clear(void)
+{
+	lcd_command(LCD_CLEARDISPLAY);  // clear display, set cursor position to zero
+	_delay_us(1600);  // this command takes a long time
+}
+
+void lcd_home(void)
+{
+	lcd_command(LCD_RETURNHOME);  // set cursor position to zero
+	_delay_us(1600);  // this command takes a long time!
+}
+
+// Turn the display on/off (quickly)
+void lcd_no_display(void)
+{
+	lcd_displaycontrol &= ~LCD_DISPLAYON;
+	lcd_command(LCD_DISPLAYCONTROL | lcd_displaycontrol);
+}
+
+void lcd_display(void)
+{
+	lcd_displaycontrol |= LCD_DISPLAYON;
+	lcd_command(LCD_DISPLAYCONTROL | lcd_displaycontrol);
+}
+
+// Turns the underline cursor on/off
+void lcd_no_cursor(void)
+{
+	lcd_displaycontrol &= ~LCD_CURSORON;
+	lcd_command(LCD_DISPLAYCONTROL | lcd_displaycontrol);
+}
+
+void lcd_cursor(void)
+{
+	lcd_displaycontrol |= LCD_CURSORON;
+	lcd_command(LCD_DISPLAYCONTROL | lcd_displaycontrol);
+}
+
+// Turn on and off the blinking cursor
+void lcd_no_blink(void)
+{
+	lcd_displaycontrol &= ~LCD_BLINKON;
+	lcd_command(LCD_DISPLAYCONTROL | lcd_displaycontrol);
+}
+
+void lcd_blink(void)
+{
+	lcd_displaycontrol |= LCD_BLINKON;
+	lcd_command(LCD_DISPLAYCONTROL | lcd_displaycontrol);
+}
+
+// These commands scroll the display without changing the RAM
+void lcd_scrollDisplayLeft(void)
+{
+	lcd_command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVELEFT);
+}
+
+void lcd_scrollDisplayRight(void)
+{
+	lcd_command(LCD_CURSORSHIFT | LCD_DISPLAYMOVE | LCD_MOVERIGHT);
+}
+
+// This is for text that flows Left to Right
+void lcd_leftToRight(void)
+{
+	lcd_displaymode |= LCD_ENTRYLEFT;
+	lcd_command(LCD_ENTRYMODESET | lcd_displaymode);
+}
+
+// This is for text that flows Right to Left
+void lcd_rightToLeft(void)
+{
+	lcd_displaymode &= ~LCD_ENTRYLEFT;
+	lcd_command(LCD_ENTRYMODESET | lcd_displaymode);
+}
+
+// This will 'right justify' text from the cursor
+void lcd_autoscroll(void)
+{
+	lcd_displaymode |= LCD_ENTRYSHIFTINCREMENT;
+	lcd_command(LCD_ENTRYMODESET | lcd_displaymode);
+}
+
+// This will 'left justify' text from the cursor
+void lcd_no_autoscroll(void)
+{
+	lcd_displaymode &= ~LCD_ENTRYSHIFTINCREMENT;
+	lcd_command(LCD_ENTRYMODESET | lcd_displaymode);
+}
+
+void lcd_set_cursor(uint8_t col, uint8_t row)
+{
+	int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
+	if ( row >= lcd_numlines )
+		row = lcd_numlines-1;    // we count rows starting w/0
+	lcd_currline = row;  
+	lcd_command(LCD_SETDDRAMADDR | (col + row_offsets[row]));
+}
+
+// Allows us to fill the first 8 CGRAM locations
+// with custom characters
+void lcd_createChar_P(uint8_t location, const uint8_t* charmap)
+{
+  location &= 0x7; // we only have 8 locations 0-7
+  lcd_command(LCD_SETCGRAMADDR | (location << 3));
+  for (int i=0; i<8; i++)
+    lcd_send(pgm_read_byte(&charmap[i]), HIGH);
+}
+
+//Supported VT100 escape codes:
+//EraseScreen  "\x1b[2J"
+//CursorHome   "\x1b[%d;%dH"
+//CursorShow   "\x1b[?25h"
+//CursorHide   "\x1b[?25l"
+uint8_t lcd_escape_write(uint8_t chr)
+{
+#define escape_cnt (lcd_escape[0])        //escape character counter
+#define is_num_msk (lcd_escape[1])        //numeric character bit mask
+#define chr_is_num (is_num_msk & 0x01) //current character is numeric
+#define e_2_is_num (is_num_msk & 0x04) //escape char 2 is numeric
+#define e_3_is_num (is_num_msk & 0x08) //...
+#define e_4_is_num (is_num_msk & 0x10)
+#define e_5_is_num (is_num_msk & 0x20)
+#define e_6_is_num (is_num_msk & 0x40)
+#define e_7_is_num (is_num_msk & 0x80)
+#define e2_num (lcd_escape[2] - '0')      //number from character 2
+#define e3_num (lcd_escape[3] - '0')      //number from character 3
+#define e23_num (10*e2_num+e3_num)     //number from characters 2 and 3
+#define e4_num (lcd_escape[4] - '0')      //number from character 4
+#define e5_num (lcd_escape[5] - '0')      //number from character 5
+#define e45_num (10*e4_num+e5_num)     //number from characters 4 and 5
+#define e6_num (lcd_escape[6] - '0')      //number from character 6
+#define e56_num (10*e5_num+e6_num)     //number from characters 5 and 6
+	if (escape_cnt > 1) // escape length > 1 = "\x1b["
+	{
+		lcd_escape[escape_cnt] = chr; // store current char
+		if ((chr >= '0') && (chr <= '9')) // char is numeric
+			is_num_msk |= (1 | (1 << escape_cnt)); //set mask
+		else
+			is_num_msk &= ~1; //clear mask
+	}
+	switch (escape_cnt++)
+	{
+	case 0:
+		if (chr == 0x1b) return 1;  // escape = "\x1b"
+		break;
+	case 1:
+		is_num_msk = 0x00; // reset 'is number' bit mask
+		if (chr == '[') return 1; // escape = "\x1b["
+		break;
+	case 2:
+		switch (chr)
+		{
+		case '2': return 1; // escape = "\x1b[2"
+		case '?': return 1; // escape = "\x1b[?"
+		default:
+			if (chr_is_num) return 1; // escape = "\x1b[%1d"
+		}
+		break;
+	case 3:
+		switch (lcd_escape[2])
+		{
+		case '?': // escape = "\x1b[?"
+			if (chr == '2') return 1; // escape = "\x1b[?2"
+			break;
+		case '2':
+			if (chr == 'J') // escape = "\x1b[2J"
+				{ lcd_clear(); lcd_currline = 0; break; } // EraseScreen
+		default:
+			if (e_2_is_num && // escape = "\x1b[%1d"
+				((chr == ';') || // escape = "\x1b[%1d;"
+				chr_is_num)) // escape = "\x1b[%2d"
+				return 1;
+		}
+		break;
+	case 4:
+		switch (lcd_escape[2])
+		{
+		case '?': // "\x1b[?"
+			if ((lcd_escape[3] == '2') && (chr == '5')) return 1; // escape = "\x1b[?25"
+			break;
+		default:
+			if (e_2_is_num) // escape = "\x1b[%1d"
+			{
+				if ((lcd_escape[3] == ';') && chr_is_num) return 1; // escape = "\x1b[%1d;%1d"
+				else if (e_3_is_num && (chr == ';')) return 1; // escape = "\x1b[%2d;"
+			}
+		}
+		break;
+	case 5:
+		switch (lcd_escape[2])
+		{
+		case '?':
+			if ((lcd_escape[3] == '2') && (lcd_escape[4] == '5')) // escape = "\x1b[?25"
+				switch (chr)
+				{
+				case 'h': // escape = "\x1b[?25h"
+  					lcd_cursor(); // CursorShow
+					break;
+				case 'l': // escape = "\x1b[?25l"
+					lcd_no_cursor(); // CursorHide
+					break;
+				}
+			break;
+		default:
+			if (e_2_is_num) // escape = "\x1b[%1d"
+			{
+				if ((lcd_escape[3] == ';') && e_4_is_num) // escape = "\x1b%1d;%1dH"
+				{
+					if (chr == 'H') // escape = "\x1b%1d;%1dH"
+						lcd_set_cursor(e4_num, e2_num); // CursorHome
+					else if (chr_is_num)
+						return 1; // escape = "\x1b%1d;%2d"
+				}
+				else if (e_3_is_num && (lcd_escape[4] == ';') && chr_is_num)
+					return 1; // escape = "\x1b%2d;%1d"
+			}
+		}
+		break;
+	case 6:
+		if (e_2_is_num) // escape = "\x1b[%1d"
+		{
+			if ((lcd_escape[3] == ';') && e_4_is_num && e_5_is_num && (chr == 'H')) // escape = "\x1b%1d;%2dH"
+				lcd_set_cursor(e45_num, e2_num); // CursorHome
+			else if (e_3_is_num && (lcd_escape[4] == ';') && e_5_is_num) // escape = "\x1b%2d;%1d"
+			{
+				if (chr == 'H') // escape = "\x1b%2d;%1dH"
+					lcd_set_cursor(e5_num, e23_num); // CursorHome
+				else if (chr_is_num) // "\x1b%2d;%2d"
+					return 1;
+			}
+		}
+		break;
+	case 7:
+		if (e_2_is_num && e_3_is_num && (lcd_escape[4] == ';')) // "\x1b[%2d;"
+			if (e_5_is_num && e_6_is_num && (chr == 'H')) // "\x1b[%2d;%2dH"
+				lcd_set_cursor(e56_num, e23_num); // CursorHome
+		break;
+	}
+	escape_cnt = 0; // reset escape
+end:
+	return 1; // assume sucess
+}
+
+
+
+
+int lcd_putc(int c)
+{
+	return fputc(c, lcdout);
+}
+
+int lcd_puts_P(const char* str)
+{
+	return fputs_P(str, lcdout);
+}
+
+int lcd_puts_at_P(uint8_t c, uint8_t r, const char* str)
+{
+	lcd_set_cursor(c, r);
+	return fputs_P(str, lcdout);
+}
+
+int lcd_printf_P(const char* format, ...)
+{
+	va_list args;
+	va_start(args, format);
+	int ret = vfprintf_P(lcdout, format, args);
+	va_end(args);
+	return ret;
+}
+
+
+
+
+void lcd_print(const char* s)
+{
+	while (*s) lcd_write(*(s++));
+}
+
+void lcd_print(char c, int base)
+{
+	lcd_print((long) c, base);
+}
+
+void lcd_print(unsigned char b, int base)
+{
+	lcd_print((unsigned long) b, base);
+}
+
+void lcd_print(int n, int base)
+{
+	lcd_print((long) n, base);
+}
+
+void lcd_print(unsigned int n, int base)
+{
+	lcd_print((unsigned long) n, base);
+}
+
+void lcd_print(long n, int base)
+{
+	if (base == 0)
+		lcd_write(n);
+	else if (base == 10)
+	{
+		if (n < 0)
+		{
+			lcd_print('-');
+			n = -n;
+		}
+		lcd_printNumber(n, 10);
+	}
+	else
+		lcd_printNumber(n, base);
+}
+
+void lcd_print(unsigned long n, int base)
+{
+	if (base == 0)
+		lcd_write(n);
+	else
+		lcd_printNumber(n, base);
+}
+
+void lcd_print(double n, int digits)
+{
+  lcd_printFloat(n, digits);
+}
+
+
+void lcd_printNumber(unsigned long n, uint8_t base)
+{
+	unsigned char buf[8 * sizeof(long)]; // Assumes 8-bit chars. 
+	unsigned long i = 0;
+	if (n == 0)
+	{
+		lcd_print('0');
+		return;
+	} 
+	while (n > 0)
+	{
+		buf[i++] = n % base;
+		n /= base;
+	}
+	for (; i > 0; i--)
+		lcd_print((char) (buf[i - 1] < 10 ?	'0' + buf[i - 1] : 'A' + buf[i - 1] - 10));
+}
+
+void lcd_printFloat(double number, uint8_t digits) 
+{ 
+	// Handle negative numbers
+	if (number < 0.0)
+	{
+		lcd_print('-');
+		number = -number;
+	}
+	// Round correctly so that print(1.999, 2) prints as "2.00"
+	double rounding = 0.5;
+	for (uint8_t i=0; i<digits; ++i)
+		rounding /= 10.0;
+	number += rounding;
+	// Extract the integer part of the number and print it
+	unsigned long int_part = (unsigned long)number;
+	double remainder = number - (double)int_part;
+	lcd_print(int_part);
+	// Print the decimal point, but only if there are digits beyond
+	if (digits > 0)
+		lcd_print('.'); 
+	// Extract digits from the remainder one at a time
+	while (digits-- > 0)
+	{
+		remainder *= 10.0;
+		int toPrint = int(remainder);
+		lcd_print(toPrint);
+		remainder -= toPrint; 
+	} 
+}
+
+
+
+
+
+
+
+
+
+
+
+
+uint8_t lcd_draw_update = 2;
+int32_t lcd_encoder = 0;
+uint8_t lcd_encoder_bits = 0;
+int8_t lcd_encoder_diff = 0;
+
+uint8_t lcd_buttons = 0;
+uint8_t lcd_button_pressed = 0;
+uint8_t lcd_update_enabled = 1;
+uint32_t lcd_timeoutToStatus = 0;
+
+uint32_t lcd_next_update_millis = 0;
+uint8_t lcd_status_update_delay = 0;
+
+uint8_t lcd_long_press_active = 0;
+
+lcd_longpress_func_t lcd_longpress_func = 0;
+
+lcd_charsetup_func_t lcd_charsetup_func = 0;
+
+lcd_lcdupdate_func_t lcd_lcdupdate_func = 0;
+
+uint32_t lcd_button_blanking_time = millis();
+ShortTimer longPressTimer;
+
+
+uint8_t lcd_clicked(void)
+{
+	bool clicked = LCD_CLICKED;
+	if(clicked) lcd_button_pressed = 1;
+    return clicked;
+}
+
+void lcd_beeper_quick_feedback(void)
+{
+	SET_OUTPUT(BEEPER);
+	for(int8_t i = 0; i < 10; i++)
+	{
+		WRITE(BEEPER,HIGH);
+		delayMicroseconds(100);
+		WRITE(BEEPER,LOW);
+		delayMicroseconds(100);
+	}
+}
+
+void lcd_quick_feedback(void)
+{
+  lcd_draw_update = 2;
+  lcd_button_pressed = false;  
+  lcd_beeper_quick_feedback();
+}
+
+
+
+
+
+
+
+
+
+void lcd_update(uint8_t lcdDrawUpdateOverride)
+{
+	if (lcd_draw_update < lcdDrawUpdateOverride)
+		lcd_draw_update = lcdDrawUpdateOverride;
+	if (!lcd_update_enabled)
+		return;
+	lcd_buttons_update();
+	if (lcd_lcdupdate_func)
+		lcd_lcdupdate_func();
+}
+
+void lcd_update_enable(uint8_t enabled)
+{
+	if (lcd_update_enabled != enabled)
+	{
+		lcd_update_enabled = enabled;
+		if (enabled)
+		{ // Reset encoder position. This is equivalent to re-entering a menu.
+			lcd_encoder = 0;
+			lcd_encoder_diff = 0;
+			// Enabling the normal LCD update procedure.
+			// Reset the timeout interval.
+			lcd_timeoutToStatus = millis() + LCD_TIMEOUT_TO_STATUS;
+			// Force the keypad update now.
+			lcd_next_update_millis = millis() - 1;
+			// Full update.
+			lcd_clear();
+			if (lcd_charsetup_func)
+				lcd_charsetup_func();
+			lcd_update(2);
+		} else
+		{
+			// Clear the LCD always, or let it to the caller?
+		}
+	}
+}
+
+void lcd_buttons_update(void)
+{
+	static bool _lock = false;
+	if (_lock) return;
+	_lock = true;
+	uint8_t newbutton = 0;
+	if (READ(BTN_EN1) == 0)  newbutton |= EN_A;
+	if (READ(BTN_EN2) == 0)  newbutton |= EN_B;
+	if (lcd_update_enabled)
+	{ //if we are in non-modal mode, long press can be used and short press triggers with button release
+		if (READ(BTN_ENC) == 0)
+		{ //button is pressed	  
+			lcd_timeoutToStatus = millis() + LCD_TIMEOUT_TO_STATUS;
+			if (millis() > lcd_button_blanking_time)
+			{
+				lcd_button_blanking_time = millis() + BUTTON_BLANKING_TIME;
+				if ((lcd_button_pressed == 0) && (lcd_long_press_active == 0))
+				{
+					longPressTimer.start();
+					lcd_button_pressed = 1;
+				}
+				else
+				{
+					if (longPressTimer.expired(LONG_PRESS_TIME))
+					{
+						lcd_long_press_active = 1;
+						if (lcd_longpress_func)
+							lcd_longpress_func();
+					}
+				}
+			}
+		}
+		else
+		{ //button not pressed
+			if (lcd_button_pressed)
+			{ //button was released
+				lcd_button_blanking_time = millis() + BUTTON_BLANKING_TIME;
+				if (lcd_long_press_active == 0)
+				{ //button released before long press gets activated
+					newbutton |= EN_C;
+				}
+				//else if (menu_menu == lcd_move_z) lcd_quick_feedback(); 
+				//lcd_button_pressed is set back to false via lcd_quick_feedback function
+			}
+			else
+				lcd_long_press_active = 0;
+		}
+	}
+	else
+	{ //we are in modal mode
+		if (READ(BTN_ENC) == 0)
+			newbutton |= EN_C; 
+	}
+
+	lcd_buttons = newbutton;
+	//manage encoder rotation
+	uint8_t enc = 0;
+	if (lcd_buttons & EN_A) enc |= B01;
+	if (lcd_buttons & EN_B) enc |= B10;
+	if (enc != lcd_encoder_bits)
+	{
+		switch (enc)
+		{
+		case encrot0:
+			if (lcd_encoder_bits == encrot3)
+				lcd_encoder_diff++;
+			else if (lcd_encoder_bits == encrot1)
+				lcd_encoder_diff--;
+			break;
+		case encrot1:
+			if (lcd_encoder_bits == encrot0)
+				lcd_encoder_diff++;
+			else if (lcd_encoder_bits == encrot2)
+				lcd_encoder_diff--;
+			break;
+		case encrot2:
+			if (lcd_encoder_bits == encrot1)
+				lcd_encoder_diff++;
+			else if (lcd_encoder_bits == encrot3)
+				lcd_encoder_diff--;
+			break;
+		case encrot3:
+			if (lcd_encoder_bits == encrot2)
+				lcd_encoder_diff++;
+			else if (lcd_encoder_bits == encrot0)
+				lcd_encoder_diff--;
+			break;
+		}
+	}
+	lcd_encoder_bits = enc;
+	_lock = false;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+void lcd_drawedit(const char* pstr, char* value)
+{
+    lcd_set_cursor(1, 1);
+    lcd_puts_P(pstr);
+    lcd_print(':');
+   #if LCD_WIDTH < 20
+      lcd_set_cursor(LCD_WIDTH - strlen(value), 1);
+    #else
+      lcd_set_cursor(LCD_WIDTH -1 - strlen(value), 1);
+   #endif
+    lcd_print(value);
+}
+
+void lcd_drawedit_2(const char* pstr, char* value)
+{
+    lcd_set_cursor(0, 1);
+    lcd_puts_P(pstr);
+    lcd_print(':');
+
+    lcd_set_cursor((LCD_WIDTH - strlen(value))/2, 3);
+
+    lcd_print(value);
+    lcd_print(" mm");
+}
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// Custom character data
+
+const uint8_t lcd_chardata_bedTemp[8] PROGMEM = {
+	B00000,
+	B11111,
+	B10101,
+	B10001,
+	B10101,
+	B11111,
+	B00000,
+	B00000}; //thanks Sonny Mounicou
+
+const uint8_t lcd_chardata_degree[8] PROGMEM = {
+	B01100,
+	B10010,
+	B10010,
+	B01100,
+	B00000,
+	B00000,
+	B00000,
+	B00000};
+
+const uint8_t lcd_chardata_thermometer[8] PROGMEM = {
+	B00100,
+	B01010,
+	B01010,
+	B01010,
+	B01010,
+	B10001,
+	B10001,
+	B01110};
+
+const uint8_t lcd_chardata_uplevel[8] PROGMEM = {
+	B00100,
+	B01110,
+	B11111,
+	B00100,
+	B11100,
+	B00000,
+	B00000,
+	B00000}; //thanks joris
+
+const uint8_t lcd_chardata_refresh[8] PROGMEM = {
+	B00000,
+	B00110,
+	B11001,
+	B11000,
+	B00011,
+	B10011,
+	B01100,
+	B00000}; //thanks joris
+
+const uint8_t lcd_chardata_folder[8] PROGMEM = {
+	B00000,
+	B11100,
+	B11111,
+	B10001,
+	B10001,
+	B11111,
+	B00000,
+	B00000}; //thanks joris
+
+const uint8_t lcd_chardata_feedrate[8] PROGMEM = {
+	B11100,
+	B10000,
+	B11000,
+	B10111,
+	B00101,
+	B00110,
+	B00101,
+	B00000}; //thanks Sonny Mounicou
+
+/*const uint8_t lcd_chardata_feedrate[8] PROGMEM = {
+	B11100,
+	B10100,
+	B11000,
+	B10100,
+	B00000,
+	B00111,
+	B00010,
+	B00010};*/
+
+/*const uint8_t lcd_chardata_feedrate[8] PROGMEM = {
+	B01100,
+	B10011,
+	B00000,
+	B01100,
+	B10011,
+	B00000,
+	B01100,
+	B10011};*/
+
+/*const uint8_t lcd_chardata_feedrate[8] PROGMEM = {
+	B00000,
+	B00100,
+	B10010,
+	B01001,
+	B10010,
+	B00100,
+	B00000,
+	B00000};*/
+
+const uint8_t lcd_chardata_clock[8] PROGMEM = {
+	B00000,
+	B01110,
+	B10011,
+	B10101,
+	B10001,
+	B01110,
+	B00000,
+	B00000}; //thanks Sonny Mounicou
+
+const uint8_t lcd_chardata_arrup[8] PROGMEM = {
+	B00100,
+	B01110,
+	B11111,
+	B00000,
+	B00000,
+	B00000,
+	B00000,
+	B00000};
+
+const uint8_t lcd_chardata_arrdown[8] PROGMEM = {
+	B00000,
+	B00000,
+	B00000,
+	B00000,
+	B00000,
+	B10001,
+	B01010,
+	B00100};
+
+
+
+void lcd_set_custom_characters(void)
+{
+	lcd_createChar_P(LCD_STR_BEDTEMP[0], lcd_chardata_bedTemp);
+	lcd_createChar_P(LCD_STR_DEGREE[0], lcd_chardata_degree);
+	lcd_createChar_P(LCD_STR_THERMOMETER[0], lcd_chardata_thermometer);
+	lcd_createChar_P(LCD_STR_UPLEVEL[0], lcd_chardata_uplevel);
+	lcd_createChar_P(LCD_STR_REFRESH[0], lcd_chardata_refresh);
+	lcd_createChar_P(LCD_STR_FOLDER[0], lcd_chardata_folder);
+	lcd_createChar_P(LCD_STR_FEEDRATE[0], lcd_chardata_feedrate);
+	lcd_createChar_P(LCD_STR_CLOCK[0], lcd_chardata_clock);
+	//lcd_createChar_P(LCD_STR_ARROW_UP[0], lcd_chardata_arrup);
+	//lcd_createChar_P(LCD_STR_ARROW_DOWN[0], lcd_chardata_arrdown);
+}
+
+void lcd_set_custom_characters_arrows(void)
+{
+	lcd_createChar_P(1, lcd_chardata_arrdown);
+}
+
+const uint8_t lcd_chardata_progress[8] PROGMEM = {
+	B11111,
+	B11111,
+	B11111,
+	B11111,
+	B11111,
+	B11111,
+	B11111,
+	B11111};
+
+void lcd_set_custom_characters_progress(void)
+{
+	lcd_createChar_P(1, lcd_chardata_progress);
+}
+
+const uint8_t lcd_chardata_arr2down[8] PROGMEM = {
+	B00000,
+	B00000,
+	B10001,
+	B01010,
+	B00100,
+	B10001,
+	B01010,
+	B00100};
+
+const uint8_t lcd_chardata_confirm[8] PROGMEM = {
+	B00000,
+	B00001,
+	B00011,
+	B10110,
+	B11100,
+	B01000,
+	B00000};
+
+void lcd_set_custom_characters_nextpage(void)
+{
+	lcd_createChar_P(1, lcd_chardata_arr2down);
+	lcd_createChar_P(2, lcd_chardata_confirm);
+}
+
+void lcd_set_custom_characters_degree(void)
+{
+	lcd_createChar_P(1, lcd_chardata_degree);
+}
+

+ 224 - 0
Firmware/lcd.h

@@ -0,0 +1,224 @@
+//lcd.h
+#ifndef _LCD_H
+#define _LCD_H
+
+#include <inttypes.h>
+#include <stdio.h>
+
+
+
+extern FILE _lcdout;
+
+#define lcdout (&_lcdout)
+extern int lcd_putchar(char c, FILE *stream);
+
+
+extern void lcd_init(void);
+
+extern void lcd_refresh(void);
+
+extern void lcd_refresh_noclear(void);
+
+
+
+extern void lcd_clear(void);
+
+extern void lcd_home(void);
+
+
+/*extern void lcd_no_display(void);
+extern void lcd_display(void);
+extern void lcd_no_blink(void);
+extern void lcd_blink(void);
+extern void lcd_no_cursor(void);
+extern void lcd_cursor(void);
+extern void lcd_scrollDisplayLeft(void);
+extern void lcd_scrollDisplayRight(void);
+extern void lcd_leftToRight(void);
+extern void lcd_rightToLeft(void);
+extern void lcd_autoscroll(void);
+extern void lcd_no_autoscroll(void);*/
+
+extern void lcd_set_cursor(uint8_t col, uint8_t row);
+
+extern void lcd_createChar_P(uint8_t, const uint8_t*);
+
+
+
+extern int lcd_putc(int c);
+extern int lcd_puts_P(const char* str);
+extern int lcd_puts_at_P(uint8_t c, uint8_t r, const char* str);
+extern int lcd_printf_P(const char* format, ...);
+
+extern void lcd_printNumber(unsigned long n, uint8_t base);
+extern void lcd_printFloat(double number, uint8_t digits);
+
+extern void lcd_print(const char*);
+extern void lcd_print(char, int = 0);
+extern void lcd_print(unsigned char, int = 0);
+extern void lcd_print(int, int = 10);
+extern void lcd_print(unsigned int, int = 10);
+extern void lcd_print(long, int = 10);
+extern void lcd_print(unsigned long, int = 10);
+extern void lcd_print(double, int = 2);
+
+#define ESC_2J     "\x1b[2J"
+#define ESC_25h    "\x1b[?25h"
+#define ESC_25l    "\x1b[?25l"
+#define ESC_H(c,r) "\x1b["#r";"#c"H"
+
+
+
+
+
+
+
+
+
+
+
+
+
+#define LCD_UPDATE_INTERVAL    100
+#define LCD_TIMEOUT_TO_STATUS  30000
+
+
+typedef void (*lcd_longpress_func_t)(void);
+
+typedef void (*lcd_charsetup_func_t)(void);
+
+typedef void (*lcd_lcdupdate_func_t)(void);
+
+//Set to none-zero when the LCD needs to draw, decreased after every draw. Set to 2 in LCD routines so the LCD gets at least 1 full redraw (first redraw is partial)
+extern uint8_t lcd_draw_update;
+
+extern int32_t lcd_encoder;
+
+extern uint8_t lcd_encoder_bits;
+
+// lcd_encoder_diff is updated from interrupt context and added to lcd_encoder every LCD update
+extern int8_t lcd_encoder_diff;
+
+//the last checked lcd_buttons in a bit array.
+extern uint8_t lcd_buttons;
+
+extern uint8_t lcd_button_pressed;
+
+extern uint8_t lcd_update_enabled;
+
+extern uint32_t lcd_timeoutToStatus;
+
+extern uint32_t lcd_next_update_millis;
+
+extern uint8_t lcd_status_update_delay;
+
+extern uint8_t lcd_long_press_active;
+
+extern lcd_longpress_func_t lcd_longpress_func;
+
+extern lcd_charsetup_func_t lcd_charsetup_func;
+
+extern lcd_lcdupdate_func_t lcd_lcdupdate_func;
+
+
+
+
+
+
+extern uint8_t lcd_clicked(void);
+
+
+extern void lcd_beeper_quick_feedback(void);
+
+//Cause an LCD refresh, and give the user visual or audible feedback that something has happened
+extern void lcd_quick_feedback(void);
+
+
+
+
+
+
+
+
+extern void lcd_update(uint8_t lcdDrawUpdateOverride);
+
+extern void lcd_update_enable(uint8_t enabled);
+
+extern void lcd_buttons_update(void);
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+/**
+* Implementation of the LCD display routines for a Hitachi HD44780 display. These are common LCD character displays.
+* When selecting the Russian language, a slightly different LCD implementation is used to handle UTF8 characters.
+**/
+
+
+////////////////////////////////////
+// Setup button and encode mappings for each panel (into 'lcd_buttons' variable
+//
+// This is just to map common functions (across different panels) onto the same 
+// macro name. The mapping is independent of whether the button is directly connected or 
+// via a shift/i2c register.
+
+#define BLEN_B 1
+#define BLEN_A 0
+#define EN_B (1<<BLEN_B) // The two encoder pins are connected through BTN_EN1 and BTN_EN2
+#define EN_A (1<<BLEN_A)
+#define BLEN_C 2 
+#define EN_C (1<<BLEN_C) 
+  
+#define LCD_CLICKED (lcd_buttons&EN_C)
+
+////////////////////////
+// Setup Rotary Encoder Bit Values (for two pin encoders to indicate movement)
+// These values are independent of which pins are used for EN_A and EN_B indications
+// The rotary encoder part is also independent to the chipset used for the LCD
+#define encrot0 0
+#define encrot1 2
+#define encrot2 3
+#define encrot3 1
+
+
+
+
+//Custom characters defined in the first 8 characters of the LCD
+#define LCD_STR_BEDTEMP     "\x00"
+#define LCD_STR_DEGREE      "\x01"
+#define LCD_STR_THERMOMETER "\x02"
+#define LCD_STR_UPLEVEL     "\x03"
+#define LCD_STR_REFRESH     "\x04"
+#define LCD_STR_FOLDER      "\x05"
+#define LCD_STR_FEEDRATE    "\x06"
+#define LCD_STR_CLOCK       "\x07"
+#define LCD_STR_ARROW_UP    "\x0B"
+#define LCD_STR_ARROW_DOWN  "\x01"
+#define LCD_STR_ARROW_RIGHT "\x7E" //from the default character set
+
+extern void lcd_set_custom_characters(void);
+extern void lcd_set_custom_characters_arrows(void);
+extern void lcd_set_custom_characters_progress(void);
+extern void lcd_set_custom_characters_nextpage(void);
+extern void lcd_set_custom_characters_degree(void);
+
+extern void lcd_drawedit(const char* pstr, char* value);
+extern void lcd_drawedit_2(const char* pstr, char* value);
+
+
+#endif //_LCD_H

+ 274 - 0
Firmware/menu.cpp

@@ -0,0 +1,274 @@
+//menu.cpp
+
+#include "menu.h"
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <avr/pgmspace.h>
+#include "lcd.h"
+#include "Configuration.h"
+#include "Marlin.h"
+
+
+
+extern int32_t lcd_encoder;
+
+
+menu_record_t menu_stack[MENU_DEPTH_MAX];
+
+uint8_t menu_data[MENU_DATA_SIZE];
+
+uint8_t menu_depth = 0;
+
+uint8_t menu_line = 0;
+uint8_t menu_item = 0;
+uint8_t menu_row = 0;
+uint8_t menu_top = 0;
+
+uint8_t menu_clicked = 0;
+
+menu_func_t menu_menu = 0;
+
+
+void menu_goto(menu_func_t menu, const uint32_t encoder, const bool feedback, bool reset_menu_state)
+{
+	asm("cli");
+	if (menu_menu != menu)
+	{
+		menu_menu = menu;
+		lcd_encoder = encoder;
+		asm("sei");
+		if (reset_menu_state)
+		{
+			// Resets the global shared C union.
+			// This ensures, that the menu entered will find out, that it shall initialize itself.
+			memset(&menu_data, 0, sizeof(menu_data));
+		}
+		if (feedback) lcd_quick_feedback();
+	}
+	else
+		asm("sei");
+}
+
+void menu_start(void)
+{
+    if (lcd_encoder > 0x8000) lcd_encoder = 0;
+    if (lcd_encoder < 0) lcd_encoder = 0;
+    if (lcd_encoder < menu_top)
+		menu_top = lcd_encoder;
+    menu_line = menu_top;
+    menu_clicked = LCD_CLICKED;
+}
+
+void menu_end(void)
+{
+	if (lcd_encoder >= menu_item)
+		lcd_encoder = menu_item - 1;
+	if (((uint8_t)lcd_encoder) >= menu_top + LCD_HEIGHT)
+	{
+		menu_top = lcd_encoder - LCD_HEIGHT + 1;
+		lcd_draw_update = 1;
+		menu_line = menu_top - 1;
+		menu_row = -1;
+	}
+}
+
+void menu_back(void)
+{
+	if (menu_depth > 0) menu_goto(menu_stack[--menu_depth].menu, menu_stack[menu_depth].position, true, true);
+}
+
+void menu_back_if_clicked(void)
+{
+	if (lcd_clicked())
+		menu_back();
+}
+
+void menu_back_if_clicked_fb(void)
+{
+	if (lcd_clicked())
+	{
+        lcd_quick_feedback();
+		menu_back();
+	}
+}
+
+void menu_submenu(menu_func_t submenu)
+{
+	if (menu_depth <= MENU_DEPTH_MAX)
+	{
+		menu_stack[menu_depth].menu = menu_menu;
+		menu_stack[menu_depth++].position = lcd_encoder;
+		menu_goto(submenu, 0, true, true);
+	}
+}
+
+uint8_t menu_item_ret(void)
+{
+	lcd_beeper_quick_feedback();
+	lcd_draw_update = 2;
+	lcd_button_pressed = false;
+	return 1;
+}
+
+/*
+int menu_item_printf_P(char type_char, const char* format, ...)
+{
+	va_list args;
+	va_start(args, format);
+	int ret = 0;
+    lcd_set_cursor(0, menu_row);
+	if (lcd_encoder == menu_item)
+		lcd_print('>');
+	else
+		lcd_print(' ');
+	int cnt = vfprintf_P(lcdout, format, args);
+	for (int i = cnt; i < 18; i++)
+		lcd_print(' ');
+	lcd_print(type_char);
+	va_end(args);
+	return ret;
+}
+*/
+int menu_draw_item_puts_P(char type_char, const char* str)
+{
+    lcd_set_cursor(0, menu_row);
+	int cnt = lcd_printf_P(PSTR("%c%-18S%c"), (lcd_encoder == menu_item)?'>':' ', str, type_char);
+	return cnt;
+}
+/*
+int menu_draw_item_puts_P_int16(char type_char, const char* str, int16_t val, )
+{
+    lcd_set_cursor(0, menu_row);
+	int cnt = lcd_printf_P(PSTR("%c%-18S%c"), (lcd_encoder == menu_item)?'>':' ', str, type_char);
+	return cnt;
+}
+*/
+void menu_item_dummy(void)
+{
+	menu_item++;
+}
+
+uint8_t menu_item_text_P(const char* str)
+{
+	if (menu_item == menu_line)
+	{
+		if (lcd_draw_update) menu_draw_item_puts_P(' ', str);
+		if (menu_clicked && (lcd_encoder == menu_item))
+			return menu_item_ret();
+	}
+	menu_item++;
+	return 0;
+}
+
+uint8_t menu_item_submenu_P(const char* str, menu_func_t submenu)
+{
+	if (menu_item == menu_line)
+	{
+		if (lcd_draw_update) menu_draw_item_puts_P(LCD_STR_ARROW_RIGHT[0], str);
+		if (menu_clicked && (lcd_encoder == menu_item))
+		{
+			menu_submenu(submenu);
+			return menu_item_ret();
+		}
+	}
+	menu_item++;
+	return 0;
+}
+
+uint8_t menu_item_back_P(const char* str)
+{
+	if (menu_item == menu_line)
+	{
+		if (lcd_draw_update) menu_draw_item_puts_P(LCD_STR_UPLEVEL[0], str);
+		if (menu_clicked && (lcd_encoder == menu_item))
+		{
+			menu_back();
+			return menu_item_ret();
+		}
+	}
+	menu_item++;
+	return 0;
+}
+
+uint8_t menu_item_function_P(const char* str, menu_func_t func)
+{
+	if (menu_item == menu_line)
+	{
+		if (lcd_draw_update) menu_draw_item_puts_P(' ', str);
+		if (menu_clicked && (lcd_encoder == menu_item))
+		{
+			menu_clicked = false;
+			lcd_update_enabled = 0;
+			if (func) func();
+			lcd_update_enabled = 1;
+			return menu_item_ret();
+		}
+	}
+	menu_item++;
+	return 0;
+}
+
+uint8_t menu_item_gcode_P(const char* str, const char* str_gcode)
+{
+	if (menu_item == menu_line)
+	{
+		if (lcd_draw_update) menu_draw_item_puts_P(' ', str);
+		if (menu_clicked && (lcd_encoder == menu_item))
+		{
+			if (str_gcode) enquecommand_P(str_gcode);
+			return menu_item_ret();
+		}
+	}
+	menu_item++;
+	return 0;
+}
+
+const char menu_fmt_int3[] PROGMEM = "%c%S:\x1b[%hhu;16H%3d";
+
+#define _menu_data (*((menu_data_edit_t*)menu_data))
+void _menu_edit_int3(void)
+{
+	if (lcd_draw_update)
+	{
+		if (lcd_encoder < _menu_data.minEditValue) lcd_encoder = _menu_data.minEditValue;
+		if (lcd_encoder > _menu_data.maxEditValue) lcd_encoder = _menu_data.maxEditValue;
+		lcd_set_cursor(0, 1);
+		lcd_printf_P(menu_fmt_int3, ' ', _menu_data.editLabel, (uint8_t)1, (int)lcd_encoder);
+	}
+	if (LCD_CLICKED)
+	{
+		*((int*)(_menu_data.editValue)) = (int)lcd_encoder;
+		menu_back();
+	}
+}
+
+uint8_t menu_item_edit_int3(const char* str, int16_t* pval, int16_t min_val, int16_t max_val)
+{
+	if (menu_item == menu_line)
+	{
+		if (lcd_draw_update) 
+		{
+			lcd_set_cursor(0, menu_row);
+			lcd_printf_P(menu_fmt_int3, (lcd_encoder == menu_item)?'>':' ', str, menu_row, *pval);
+		}
+		if (menu_clicked && (lcd_encoder == menu_item))
+		{
+			menu_submenu(_menu_edit_int3);
+			_menu_data.editLabel = str;
+			_menu_data.editValue = pval;
+			_menu_data.minEditValue = min_val;
+			_menu_data.maxEditValue = max_val;
+			lcd_encoder = *pval;
+			return menu_item_ret();
+		}
+	}
+	menu_item++;
+	return 0;
+}
+#undef _menu_data
+
+
+
+
+

+ 98 - 0
Firmware/menu.h

@@ -0,0 +1,98 @@
+//menu.h
+#ifndef _MENU_H
+#define _MENU_H
+
+#include <inttypes.h>
+
+#define MENU_DEPTH_MAX 4
+#define MENU_DATA_SIZE 32
+
+//Function pointer to menu functions.
+typedef void (*menu_func_t)(void);
+
+typedef struct 
+{
+    menu_func_t menu;
+    uint8_t position;
+} menu_record_t;
+
+typedef struct
+{
+    //Variables used when editing values.
+    const char* editLabel;
+    void* editValue;
+    int32_t minEditValue;
+	int32_t maxEditValue;
+} menu_data_edit_t;
+
+extern menu_record_t menu_stack[MENU_DEPTH_MAX];
+
+extern uint8_t menu_data[MENU_DATA_SIZE];
+
+extern uint8_t menu_depth;
+
+extern uint8_t menu_line;
+extern uint8_t menu_item;
+extern uint8_t menu_row;
+;
+//scroll offset in the current menu
+extern uint8_t menu_top;
+
+extern uint8_t menu_clicked;
+
+//function pointer to the currently active menu
+extern menu_func_t menu_menu;
+
+
+
+extern void menu_goto(menu_func_t menu, const uint32_t encoder, const bool feedback, bool reset_menu_state);
+
+#define MENU_BEGIN() menu_start(); for(menu_row = 0; menu_row < LCD_HEIGHT; menu_row++, menu_line++) { menu_item = 0;
+void menu_start(void);
+
+#define MENU_END() menu_end(); }
+extern void menu_end(void);
+
+extern void menu_back(void);
+
+extern void menu_back_if_clicked(void);
+
+extern void menu_back_if_clicked_fb(void);
+
+extern void menu_submenu(menu_func_t submenu);
+
+extern uint8_t menu_item_ret(void);
+
+//int menu_item_printf_P(char type_char, const char* format, ...);
+
+extern int menu_draw_item_puts_P(char type_char, const char* str);
+
+//int menu_draw_item_puts_P_int16(char type_char, const char* str, int16_t val, );
+
+#define MENU_ITEM_DUMMY() menu_item_dummy()
+extern void menu_item_dummy(void);
+
+#define MENU_ITEM_TEXT_P(str) do { if (menu_item_text_P(str)) return; } while (0)
+extern uint8_t menu_item_text_P(const char* str);
+
+#define MENU_ITEM_SUBMENU_P(str, submenu) do { if (menu_item_submenu_P(str, submenu)) return; } while (0)
+extern uint8_t menu_item_submenu_P(const char* str, menu_func_t submenu);
+
+#define MENU_ITEM_BACK_P(str) do { if (menu_item_back_P(str)) return; } while (0)
+extern uint8_t menu_item_back_P(const char* str);
+
+#define MENU_ITEM_FUNCTION_P(str, func) do { if (menu_item_function_P(str, func)) return; } while (0)
+extern uint8_t menu_item_function_P(const char* str, menu_func_t func);
+
+#define MENU_ITEM_GCODE_P(str, str_gcode) do { if (menu_item_gcode_P(str, str_gcode)) return; } while (0)
+extern uint8_t menu_item_gcode_P(const char* str, const char* str_gcode);
+
+
+extern const char menu_fmt_int3[];
+extern void _menu_edit_int3(void);
+#define MENU_ITEM_EDIT_int3_P(str, pval, minval, maxval) do { if (menu_item_edit_int3(str, pval, minval, maxval)) return; } while (0)
+//#define MENU_ITEM_EDIT_int3_P(str, pval, minval, maxval) MENU_ITEM_EDIT(int3, str, pval, minval, maxval)
+extern uint8_t menu_item_edit_int3(const char* str, int16_t* pval, int16_t min_val, int16_t max_val);
+
+
+#endif //_MENU_H

+ 15 - 12
Firmware/mesh_bed_calibration.cpp

@@ -2204,12 +2204,13 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
 		// Don't let the manage_inactivity() function remove power from the motors.
 		refresh_cmd_timeout();
 #ifdef MESH_BED_CALIBRATION_SHOW_LCD
-		lcd_implementation_print_at(0, next_line, k + 1);
-		lcd_printPGM(_T(MSG_FIND_BED_OFFSET_AND_SKEW_LINE2));
+		lcd_set_cursor(0, next_line);
+		lcd_print(k + 1);
+		lcd_puts_P(_T(MSG_FIND_BED_OFFSET_AND_SKEW_LINE2));
 
 		if (iteration > 0) {
-			lcd_print_at_PGM(0, next_line + 1, _i("Iteration "));////MSG_FIND_BED_OFFSET_AND_SKEW_ITERATION c=20 r=0
-			lcd_implementation_print(int(iteration + 1));
+			lcd_puts_at_P(0, next_line + 1, _i("Iteration "));////MSG_FIND_BED_OFFSET_AND_SKEW_ITERATION c=20 r=0
+			lcd_print(int(iteration + 1));
 		}
 #endif /* MESH_BED_CALIBRATION_SHOW_LCD */
 		float *pt = pts + k * 2;
@@ -2478,8 +2479,8 @@ BedSkewOffsetDetectionResultType improve_bed_offset_and_skew(int8_t method, int8
         refresh_cmd_timeout();
         // Print the decrasing ID of the measurement point.
 #ifdef MESH_BED_CALIBRATION_SHOW_LCD
-        lcd_implementation_print_at(0, next_line, mesh_point+1);
-        lcd_printPGM(_T(MSG_FIND_BED_OFFSET_AND_SKEW_LINE2));////MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2 c=14 r=0
+        lcd_print_at(0, next_line, mesh_point+1);
+        lcd_puts_P(_T(MSG_FIND_BED_OFFSET_AND_SKEW_LINE2));////MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2 c=14 r=0
 #endif /* MESH_BED_CALIBRATION_SHOW_LCD */
 
         // Move up.
@@ -2782,8 +2783,9 @@ bool sample_mesh_and_store_reference()
     if (next_line > 3)
         next_line = 3;
     // display "point xx of yy"
-    lcd_implementation_print_at(0, next_line, 1);
-    lcd_printPGM(_T(MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2));
+	lcd_set_cursor(0, next_line);
+    lcd_print(1);
+    lcd_puts_P(_T(MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2));
 #endif /* MESH_BED_CALIBRATION_SHOW_LCD */
 
     // Sample Z heights for the mesh bed leveling.
@@ -2828,8 +2830,9 @@ bool sample_mesh_and_store_reference()
         go_to_current(homing_feedrate[X_AXIS]/60);
 #ifdef MESH_BED_CALIBRATION_SHOW_LCD
         // display "point xx of yy"
-        lcd_implementation_print_at(0, next_line, mesh_point+1);
-        lcd_printPGM(_T(MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2));
+		lcd_set_cursor(0, next_line);
+        lcd_print(mesh_point+1);
+        lcd_puts_P(_T(MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2));
 #endif /* MESH_BED_CALIBRATION_SHOW_LCD */
 		if (!find_bed_induction_sensor_point_z()) //Z crash or deviation > 50um
 		{
@@ -2845,11 +2848,11 @@ bool sample_mesh_and_store_reference()
     {
         // Verify the span of the Z values.
         float zmin = mbl.z_values[0][0];
-        float zmax = zmax;
+        float zmax = zmin;
         for (int8_t j = 0; j < 3; ++ j)
            for (int8_t i = 0; i < 3; ++ i) {
                 zmin = min(zmin, mbl.z_values[j][i]);
-                zmax = min(zmax, mbl.z_values[j][i]);
+                zmax = max(zmax, mbl.z_values[j][i]);
            }
         if (zmax - zmin > 3.f) {
             // The span of the Z offsets is extreme. Give up.

+ 88 - 70
Firmware/pat9125.cpp

@@ -1,8 +1,30 @@
-#include "uni_avr_rpi.h"
+//pat9125.c
+#include "pat9125.h"
+#include <avr/delay.h>
+#include <avr/pgmspace.h>
+#include "config.h"
+#include <stdio.h>
 
-#ifdef PAT9125
 
-#include "pat9125.h"
+//PAT9125 registers
+#define PAT9125_PID1			0x00
+#define PAT9125_PID2			0x01
+#define PAT9125_MOTION			0x02
+#define PAT9125_DELTA_XL		0x03
+#define PAT9125_DELTA_YL		0x04
+#define PAT9125_MODE			0x05
+#define PAT9125_CONFIG			0x06
+#define PAT9125_WP				0x09
+#define PAT9125_SLEEP1			0x0a
+#define PAT9125_SLEEP2			0x0b
+#define PAT9125_RES_X			0x0d
+#define PAT9125_RES_Y			0x0e
+#define PAT9125_DELTA_XYH		0x12
+#define PAT9125_SHUTTER			0x14
+#define PAT9125_FRAME			0x17
+#define PAT9125_ORIENTATION		0x19
+#define PAT9125_BANK_SELECTION	0x7f
+
 
 #ifdef PAT9125_SWSPI
 #include "swspi.h"
@@ -10,20 +32,18 @@
 #ifdef PAT9125_SWI2C
 #include "swi2c.h"
 #endif //PAT9125_SWI2C
-#ifdef PAT9125_HWI2C
-#include <Wire.h>
-#endif //PAT9125_HWI2C
 
 
-unsigned char pat9125_PID1 = 0;
-unsigned char pat9125_PID2 = 0;
-int pat9125_x = 0;
-int pat9125_y = 0;
-unsigned char pat9125_b = 0;
-unsigned char pat9125_s = 0;
+uint8_t pat9125_PID1 = 0;
+uint8_t pat9125_PID2 = 0;
+int16_t pat9125_x = 0;
+int16_t pat9125_y = 0;
+uint8_t pat9125_b = 0;
+uint8_t pat9125_s = 0;
+
 
 // Init sequence, address & value.
-const PROGMEM unsigned char pat9125_init_seq1[] = {
+const PROGMEM uint8_t pat9125_init_seq1[] = {
 	// Disable write protect.
 	PAT9125_WP, 0x5a,
 	// Set the X resolution to zero to let the sensor know that it could safely ignore movement in the X axis.
@@ -43,7 +63,7 @@ const PROGMEM unsigned char pat9125_init_seq1[] = {
 };
 
 // Init sequence, address & value.
-const PROGMEM unsigned char pat9125_init_seq2[] = {
+const PROGMEM uint8_t pat9125_init_seq2[] = {
 	// Magic sequence to enforce full frame rate of the sensor.
 	0x06, 0x028,
 	0x33, 0x0d0,
@@ -74,22 +94,23 @@ const PROGMEM unsigned char pat9125_init_seq2[] = {
     0x0ff
 };
 
-int pat9125_init()
+
+uint8_t pat9125_rd_reg(uint8_t addr);
+void pat9125_wr_reg(uint8_t addr, uint8_t data);
+uint8_t pat9125_wr_reg_verify(uint8_t addr, uint8_t data);
+
+
+uint8_t pat9125_init(void)
 {
 #ifdef PAT9125_SWSPI
 	swspi_init();
 #endif //PAT9125_SWSPI
 #ifdef PAT9125_SWI2C
-	swi2c_init(PAT9125_SWI2C_SDA, PAT9125_SWI2C_SCL, PAT9125_SWI2C_CFG);
+	swi2c_init();
 #endif //PAT9125_SWI2C
-#ifdef PAT9125_HWI2C
-	Wire.begin();
-#endif //PAT9125_HWI2C
 	// Verify that the sensor responds with its correct product ID.
 	pat9125_PID1 = pat9125_rd_reg(PAT9125_PID1);
 	pat9125_PID2 = pat9125_rd_reg(PAT9125_PID2);
-//	pat9125_PID1 = 0x31;
-//	pat9125_PID2 = 0x91;
 	if ((pat9125_PID1 != 0x31) || (pat9125_PID2 != 0x91))
 	{
 		pat9125_PID1 = pat9125_rd_reg(PAT9125_PID1);
@@ -97,6 +118,8 @@ int pat9125_init()
 		if ((pat9125_PID1 != 0x31) || (pat9125_PID2 != 0x91))
 			return 0;
 	}
+
+#ifdef PAT9125_NEW_INIT
 	// Switch to bank0, not allowed to perform OTS_RegWriteRead.
 	pat9125_wr_reg(PAT9125_BANK_SELECTION, 0);
 	// Software reset (i.e. set bit7 to 1). It will reset to 0 automatically.
@@ -104,11 +127,11 @@ int pat9125_init()
 	pat9125_wr_reg(PAT9125_CONFIG, 0x97);
 	// Wait until the sensor reboots.
 	// Delay 1ms.
-	delayMicroseconds(1000);
+	_delay_us(1000);
 	{
-		const unsigned char *ptr = pat9125_init_seq1;
+		const uint8_t *ptr = pat9125_init_seq1;
 		for (;;) {
-			const unsigned char addr = pgm_read_byte_near(ptr ++);
+			const uint8_t addr = pgm_read_byte_near(ptr ++);
 			if (addr == 0x0ff)
 				break;
 			if (! pat9125_wr_reg_verify(addr, pgm_read_byte_near(ptr ++)))
@@ -117,13 +140,13 @@ int pat9125_init()
 		}
 	}
 	// Delay 10ms.
-	delayMicroseconds(10000);
+	_delay_ms(10);
 	// Switch to bank1, not allowed to perform OTS_RegWrite.
 	pat9125_wr_reg(PAT9125_BANK_SELECTION, 0x01);
 	{
-		const unsigned char *ptr = pat9125_init_seq2;
+		const uint8_t *ptr = pat9125_init_seq2;
 		for (;;) {
-			const unsigned char addr = pgm_read_byte_near(ptr ++);
+			const uint8_t addr = pgm_read_byte_near(ptr ++);
 			if (addr == 0x0ff)
 				break;
 			if (! pat9125_wr_reg_verify(addr, pgm_read_byte_near(ptr ++)))
@@ -138,25 +161,28 @@ int pat9125_init()
 
 	pat9125_PID1 = pat9125_rd_reg(PAT9125_PID1);
 	pat9125_PID2 = pat9125_rd_reg(PAT9125_PID2);
+#endif //PAT9125_NEW_INIT
+	pat9125_wr_reg(PAT9125_RES_X, 0);
+	pat9125_wr_reg(PAT9125_RES_Y, 200);
 	return 1;
 }
 
-int pat9125_update()
+uint8_t pat9125_update(void)
 {
 	if ((pat9125_PID1 == 0x31) && (pat9125_PID2 == 0x91))
 	{
-		unsigned char ucMotion = pat9125_rd_reg(PAT9125_MOTION);
+		uint8_t ucMotion = pat9125_rd_reg(PAT9125_MOTION);
 		pat9125_b = pat9125_rd_reg(PAT9125_FRAME);
 		pat9125_s = pat9125_rd_reg(PAT9125_SHUTTER);
 		if (pat9125_PID1 == 0xff) return 0;
 		if (ucMotion & 0x80)
 		{
-			unsigned char ucXL = pat9125_rd_reg(PAT9125_DELTA_XL);
-			unsigned char ucYL = pat9125_rd_reg(PAT9125_DELTA_YL);
-			unsigned char ucXYH = pat9125_rd_reg(PAT9125_DELTA_XYH);
+			uint8_t ucXL = pat9125_rd_reg(PAT9125_DELTA_XL);
+			uint8_t ucYL = pat9125_rd_reg(PAT9125_DELTA_YL);
+			uint8_t ucXYH = pat9125_rd_reg(PAT9125_DELTA_XYH);
 			if (pat9125_PID1 == 0xff) return 0;
-			int iDX = ucXL | ((ucXYH << 4) & 0xf00);
-			int iDY = ucYL | ((ucXYH << 8) & 0xf00);
+			int16_t iDX = ucXL | ((ucXYH << 4) & 0xf00);
+			int16_t iDY = ucYL | ((ucXYH << 8) & 0xf00);
 			if (iDX & 0x800) iDX -= 4096;
 			if (iDY & 0x800) iDY -= 4096;
 			pat9125_x += iDX;
@@ -167,18 +193,18 @@ int pat9125_update()
 	return 0;
 }
 
-int pat9125_update_y()
+uint8_t pat9125_update_y(void)
 {
 	if ((pat9125_PID1 == 0x31) && (pat9125_PID2 == 0x91))
 	{
-		unsigned char ucMotion = pat9125_rd_reg(PAT9125_MOTION);
+		uint8_t ucMotion = pat9125_rd_reg(PAT9125_MOTION);
 		if (pat9125_PID1 == 0xff) return 0;
 		if (ucMotion & 0x80)
 		{
-			unsigned char ucYL = pat9125_rd_reg(PAT9125_DELTA_YL);
-			unsigned char ucXYH = pat9125_rd_reg(PAT9125_DELTA_XYH);
+			uint8_t ucYL = pat9125_rd_reg(PAT9125_DELTA_YL);
+			uint8_t ucXYH = pat9125_rd_reg(PAT9125_DELTA_XYH);
 			if (pat9125_PID1 == 0xff) return 0;
-			int iDY = ucYL | ((ucXYH << 8) & 0xf00);
+			int16_t iDY = ucYL | ((ucXYH << 8) & 0xf00);
 			if (iDY & 0x800) iDY -= 4096;
 			pat9125_y -= iDY; //negative number, because direction switching does not work
 		}
@@ -187,10 +213,26 @@ int pat9125_update_y()
 	return 0;
 }
 
-unsigned char pat9125_rd_reg(unsigned char addr)
+uint8_t pat9125_update_y2(void)
 {
-//    printf_P(PSTR("pat9125_rd_reg 0x%hhx "), addr);
-	unsigned char data = 0;
+	if ((pat9125_PID1 == 0x31) && (pat9125_PID2 == 0x91))
+	{
+		uint8_t ucMotion = pat9125_rd_reg(PAT9125_MOTION);
+		if (pat9125_PID1 == 0xff) return 0; //NOACK error
+		if (ucMotion & 0x80)
+		{
+			int8_t dy = pat9125_rd_reg(PAT9125_DELTA_YL);
+			if (pat9125_PID1 == 0xff) return 0; //NOACK error
+			pat9125_y -= dy; //negative number, because direction switching does not work
+		}
+		return 1;
+	}
+	return 0;
+}
+
+uint8_t pat9125_rd_reg(uint8_t addr)
+{
+	uint8_t data = 0;
 #ifdef PAT9125_SWSPI
 	swspi_start();
 	swspi_tx(addr & 0x7f);
@@ -198,30 +240,18 @@ unsigned char pat9125_rd_reg(unsigned char addr)
 	swspi_stop();
 #endif //PAT9125_SWSPI
 #ifdef PAT9125_SWI2C
-	int iret = swi2c_readByte_A8(PAT9125_I2C_ADDR, addr, &data);
-	if (!iret) //NO ACK error
+	if (!swi2c_readByte_A8(PAT9125_I2C_ADDR, addr, &data)) //NO ACK error
 	{
 		pat9125_PID1 = 0xff;
 		pat9125_PID2 = 0xff;
-//	    printf_P(PSTR("ERR\n"));
 		return 0;
 	}
-//    printf_P(PSTR("0x%hhx OK\n"), data);
 #endif //PAT9125_SWI2C
-#ifdef PAT9125_HWI2C
-	Wire.beginTransmission(PAT9125_I2C_ADDR);
-	Wire.write(addr);
-	Wire.endTransmission();
-	if (Wire.requestFrom(PAT9125_I2C_ADDR, 1) == 1)
-//	if (Wire.available())
-		data = Wire.read();
-#endif //PAT9125_HWI2C
 	return data;
 }
 
-void pat9125_wr_reg(unsigned char addr, unsigned char data)
+void pat9125_wr_reg(uint8_t addr, uint8_t data)
 {
-//    printf_P(PSTR("pat9125_wr_reg 0x%hhx 0x%hhx  "), addr, data);
 #ifdef PAT9125_SWSPI
 	swspi_start();
 	swspi_tx(addr | 0x80);
@@ -229,29 +259,17 @@ void pat9125_wr_reg(unsigned char addr, unsigned char data)
 	swspi_stop();
 #endif //PAT9125_SWSPI
 #ifdef PAT9125_SWI2C
-	int iret = swi2c_writeByte_A8(PAT9125_I2C_ADDR, addr, &data);
-	if (!iret) //NO ACK error
+	if (!swi2c_writeByte_A8(PAT9125_I2C_ADDR, addr, &data)) //NO ACK error
 	{
 		pat9125_PID1 = 0xff;
 		pat9125_PID2 = 0xff;
-//	    printf_P(PSTR("ERR\n"));
 		return;
 	}
-//    printf_P(PSTR("OK\n"));
-
 #endif //PAT9125_SWI2C
-#ifdef PAT9125_HWI2C
-	Wire.beginTransmission(PAT9125_I2C_ADDR);
-	Wire.write(addr);
-	Wire.write(data);
-	Wire.endTransmission();
-#endif //PAT9125_HWI2C
 }
 
-bool pat9125_wr_reg_verify(unsigned char addr, unsigned char data)
+uint8_t pat9125_wr_reg_verify(uint8_t addr, uint8_t data)
 {
 	pat9125_wr_reg(addr, data);
 	return pat9125_rd_reg(addr) == data;
 }
-
-#endif //PAT9125

+ 25 - 39
Firmware/pat9125.h

@@ -1,45 +1,31 @@
+//pat9125.h
 #ifndef PAT9125_H
 #define PAT9125_H
 
-//PAT9125 I2C
-#define PAT9125_I2C_ADDR        0x75  //ID=LO
-//#define PAT9125_I2C_ADDR        0x79  //ID=HI
-//#define PAT9125_I2C_ADDR        0x73  //ID=NC
-
-//PAT9125 registers
-#define PAT9125_PID1			0x00
-#define PAT9125_PID2			0x01
-#define PAT9125_MOTION			0x02
-#define PAT9125_DELTA_XL		0x03
-#define PAT9125_DELTA_YL		0x04
-#define PAT9125_MODE			0x05
-#define PAT9125_CONFIG			0x06
-#define PAT9125_WP				0x09
-#define PAT9125_SLEEP1			0x0a
-#define PAT9125_SLEEP2			0x0b
-#define PAT9125_RES_X			0x0d
-#define PAT9125_RES_Y			0x0e
-#define PAT9125_DELTA_XYH		0x12
-#define PAT9125_SHUTTER			0x14
-#define PAT9125_FRAME			0x17
-#define PAT9125_ORIENTATION		0x19
-#define PAT9125_BANK_SELECTION	0x7f
-
-extern unsigned char pat9125_PID1;
-extern unsigned char pat9125_PID2;
-
-extern int pat9125_x;
-extern int pat9125_y;
-extern unsigned char pat9125_b;
-extern unsigned char pat9125_s;
-
-extern int pat9125_init();
-extern int pat9125_update();
-extern int pat9125_update_y();
-
-extern unsigned char pat9125_rd_reg(unsigned char addr);
-extern void pat9125_wr_reg(unsigned char addr, unsigned char data);
-extern bool pat9125_wr_reg_verify(unsigned char addr, unsigned char data);
+#include <inttypes.h>
 
 
+#if defined(__cplusplus)
+extern "C" {
+#endif //defined(__cplusplus)
+
+
+extern uint8_t pat9125_PID1;
+extern uint8_t pat9125_PID2;
+
+extern int16_t pat9125_x;
+extern int16_t pat9125_y;
+extern uint8_t pat9125_b;
+extern uint8_t pat9125_s;
+
+extern uint8_t pat9125_init(void);
+extern uint8_t pat9125_update(void);
+extern uint8_t pat9125_update_y(void);
+extern uint8_t pat9125_update_y2(void);
+
+
+#if defined(__cplusplus)
+}
+#endif //defined(__cplusplus)
+
 #endif //PAT9125_H

+ 3 - 11
Firmware/pins_Einsy_1_0.h

@@ -17,15 +17,11 @@
 
 #define W25X20CL                 // external 256kB flash
 
-#define SWI2C                    // enable software i2c
-#define SWI2C_A8                 // 8bit address functions
 
-#define PAT9125_SWI2C
-#define PAT9125_SWI2C_SDA      20 //SDA on P3
-#define PAT9125_SWI2C_SCL      21 //SCL on P3
-#define PAT9125_SWI2C_CFG    0xb1 //2us clock delay, 2048 cycles timeout
+#define SWI2C_SDA      20 //SDA on P3
+#define SWI2C_SCL      21 //SCL on P3
+
 
-//#define PAT9125_HWI2C
 
 #define X_TMC2130_CS           41
 #define X_TMC2130_DIAG         64 // !!! changed from 40 (EINY03)
@@ -99,11 +95,9 @@
 #define KILL_PIN            -1  // 80 with Smart Controller LCD
 #define SUICIDE_PIN         -1  // PIN that has to be turned on right after start, to keep power flowing.
 
-#ifdef ULTRA_LCD
 
 //#define KILL_PIN            32
 
-#ifdef NEWPANEL
 
 //#define LCD_PWM_PIN         -1//32  // lcd backlight brightnes pwm control pin
 //#define LCD_PWM_MAX       0x0f  // lcd pwm maximum value (0x07=64Hz, 0x0f=32Hz, 0x1f=16Hz)
@@ -126,8 +120,6 @@
 #define TACH_0                 79 // !!! changed from 81 (EINY03)
 #define TACH_1                 80 
 
-#endif //NEWPANEL
-#endif //ULTRA_LCD
 
 // 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.

+ 2 - 11
Firmware/pins_Rambo_1_0.h

@@ -11,15 +11,10 @@
 
 #define PINDA_THERMISTOR
 
-#define SWI2C                    // enable software i2c
-#define SWI2C_A8                 // 8bit address functions
+#define SWI2C_SDA      20 //SDA on P3
+#define SWI2C_SCL      84 //PH2 on P3, sensor cable must be rewired
 
-#define PAT9125_SWI2C
-#define PAT9125_SWI2C_SDA      20 //SDA on P3
-#define PAT9125_SWI2C_SCL      84 //PH2 on P3, sensor cable must be rewired
-#define PAT9125_SWI2C_CFG    0xb1 //2us clock delay, 2048 cycles timeout
 
-//#define PAT9125_HWI2C
 
 #define X_STEP_PIN             37
 #define X_DIR_PIN              48
@@ -88,11 +83,9 @@
 #define SUICIDE_PIN         -1  // PIN that has to be turned on right after start, to keep power flowing.
 #define TACH_0				30	// noctua extruder fan
 
-#ifdef ULTRA_LCD
 
 //#define KILL_PIN            32
 
-#ifdef NEWPANEL
 
 #define BEEPER              78  // Beeper on AUX-4
 #define LCD_PINS_RS         38
@@ -110,8 +103,6 @@
 #define SDCARDDETECT           72
 
 
-#endif //NEWPANEL
-#endif //ULTRA_LCD
 
 // 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.

+ 2 - 11
Firmware/pins_Rambo_1_3.h

@@ -11,15 +11,10 @@
 
 #define PINDA_THERMISTOR
 
-#define SWI2C                    // enable software i2c
-#define SWI2C_A8                 // 8bit address functions
+#define SWI2C_SDA      20 //SDA on P3
+#define SWI2C_SCL      21 //SCL on P3
 
-#define PAT9125_SWI2C
-#define PAT9125_SWI2C_SDA      20 //SDA on P3
-#define PAT9125_SWI2C_SCL      21 //SCL on P3
-#define PAT9125_SWI2C_CFG    0xb1 //2us clock delay, 2048 cycles timeout
 
-//#define PAT9125_HWI2C
 
 #define X_STEP_PIN             37
 #define X_DIR_PIN              48
@@ -88,11 +83,9 @@
 #define SUICIDE_PIN         -1  // PIN that has to be turned on right after start, to keep power flowing.
 #define TACH_0				30	// noctua extruder fan
 
-#ifdef ULTRA_LCD
 
 //#define KILL_PIN            32
 
-#ifdef NEWPANEL
 
 #define BEEPER              84  // Beeper on AUX-4
 #define LCD_PINS_RS         82
@@ -110,8 +103,6 @@
 #define SDCARDDETECT           15
 
 
-#endif //NEWPANEL
-#endif //ULTRA_LCD
 
 // 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.

+ 9 - 2
Firmware/planner.cpp

@@ -646,10 +646,10 @@ void plan_buffer_line(float x, float y, float z, const float &e, float feed_rate
           manage_heater(); 
           // Vojtech: Don't disable motors inside the planner!
           manage_inactivity(false); 
-          lcd_update();
+          lcd_update(0);
       } while (block_buffer_tail == next_buffer_head);
       if (waiting_inside_plan_buffer_line_print_aborted) {
-          // Inside the lcd_update() routine the print has been aborted.
+          // Inside the lcd_update(0) routine the print has been aborted.
           // Cancel the print, do not plan the current line this routine is waiting on.
 #ifdef PLANNER_DIAGNOSTICS
           planner_update_queue_min_counter();
@@ -954,6 +954,7 @@ Having the real displacement of the head, we can calculate the total movement le
   {
     current_speed[i] = delta_mm[i] * inverse_second;
 #ifdef TMC2130
+#ifdef FEEDRATE_LIMIT
 	float max_fr = max_feedrate[i];
 	if (i < 2) // X, Y
 	{
@@ -970,6 +971,10 @@ Having the real displacement of the head, we can calculate the total movement le
 	}
     if(fabs(current_speed[i]) > max_fr)
       speed_factor = min(speed_factor, max_fr / fabs(current_speed[i]));
+#else //FEEDRATE_LIMIT
+    if(fabs(current_speed[i]) > max_feedrate[i])
+      speed_factor = min(speed_factor, max_feedrate[i] / fabs(current_speed[i]));
+#endif //FEEDRATE_LIMIT
 #else //TMC2130
     if(fabs(current_speed[i]) > max_feedrate[i])
       speed_factor = min(speed_factor, max_feedrate[i] / fabs(current_speed[i]));
@@ -1015,6 +1020,7 @@ Having the real displacement of the head, we can calculate the total movement le
 	if (block->steps_z.wide && (block->acceleration_st > axis_steps_per_sqr_second[Z_AXIS])) block->acceleration_st = axis_steps_per_sqr_second[Z_AXIS];
 	if (block->steps_e.wide && (block->acceleration_st > axis_steps_per_sqr_second[E_AXIS])) block->acceleration_st = axis_steps_per_sqr_second[E_AXIS];
 #else // SIMPLE_ACCEL_LIMIT
+#ifdef ACCEL_LIMIT
 	if (tmc2130_mode == TMC2130_MODE_SILENT)
 	{
 		if ((block->steps_x.wide > block->step_event_count.wide / 2) || (block->steps_y.wide > block->step_event_count.wide / 2))
@@ -1033,6 +1039,7 @@ Having the real displacement of the head, we can calculate the total movement le
       block->acceleration_st = axis_steps_per_sqr_second[Z_AXIS];
     if(((float)block->acceleration_st * (float)block->steps_e.wide / (float)block->step_event_count.wide) > axis_steps_per_sqr_second[E_AXIS])
       block->acceleration_st = axis_steps_per_sqr_second[E_AXIS];
+#endif // ACCEL_LIMIT
 #endif // SIMPLE_ACCEL_LIMIT
 #else //TMC2130
     // Limit acceleration per axis

+ 59 - 2
Firmware/stepper.cpp

@@ -407,12 +407,68 @@ ISR(TIMER1_COMPA_vect) {
   }
 }
 
+uint8_t last_dir_bits = 0;
+
+#ifdef BACKLASH_X
+uint8_t st_backlash_x = 0;
+#endif //BACKLASH_X
+#ifdef BACKLASH_Y
+uint8_t st_backlash_y = 0;
+#endif //BACKLASH_Y
+
 FORCE_INLINE void stepper_next_block()
 {
   // Anything in the buffer?
   //WRITE_NC(LOGIC_ANALYZER_CH2, true);
   current_block = plan_get_current_block();
   if (current_block != NULL) {
+#ifdef BACKLASH_X
+	if (current_block->steps_x.wide)
+	{ //X-axis movement
+		if ((current_block->direction_bits ^ last_dir_bits) & 1)
+		{
+			printf_P(PSTR("BL %d\n"), (current_block->direction_bits & 1)?st_backlash_x:-st_backlash_x);
+			if (current_block->direction_bits & 1)
+				WRITE_NC(X_DIR_PIN, INVERT_X_DIR);
+			else
+				WRITE_NC(X_DIR_PIN, !INVERT_X_DIR);
+			_delay_us(100);
+			for (uint8_t i = 0; i < st_backlash_x; i++)
+			{
+				WRITE_NC(X_STEP_PIN, !INVERT_X_STEP_PIN);
+				_delay_us(100);
+				WRITE_NC(X_STEP_PIN, INVERT_X_STEP_PIN);
+				_delay_us(900);
+			}
+		}
+		last_dir_bits &= ~1;
+		last_dir_bits |= current_block->direction_bits & 1;
+	}
+#endif
+#ifdef BACKLASH_Y
+	if (current_block->steps_y.wide)
+	{ //Y-axis movement
+		if ((current_block->direction_bits ^ last_dir_bits) & 2)
+		{
+			printf_P(PSTR("BL %d\n"), (current_block->direction_bits & 2)?st_backlash_y:-st_backlash_y);
+			if (current_block->direction_bits & 2)
+				WRITE_NC(Y_DIR_PIN, INVERT_Y_DIR);
+			else
+				WRITE_NC(Y_DIR_PIN, !INVERT_Y_DIR);
+			_delay_us(100);
+			for (uint8_t i = 0; i < st_backlash_y; i++)
+			{
+				WRITE_NC(Y_STEP_PIN, !INVERT_Y_STEP_PIN);
+				_delay_us(100);
+				WRITE_NC(Y_STEP_PIN, INVERT_Y_STEP_PIN);
+				_delay_us(900);
+			}
+		}
+		last_dir_bits &= ~2;
+		last_dir_bits |= current_block->direction_bits & 2;
+	}
+#endif
+
 #ifdef PAT9125
     fsensor_counter = 0;
     fsensor_st_block_begin(current_block);
@@ -996,6 +1052,7 @@ FORCE_INLINE void isr() {
       fsensor_st_block_chunk(current_block, fsensor_counter);
 	    fsensor_counter = 0;
 #endif //PAT9125
+
       current_block = NULL;
       plan_discard_current_block();
     }
@@ -1268,13 +1325,13 @@ void st_synchronize()
 		if (!tmc2130_update_sg())
 		{
 			manage_inactivity(true);
-			lcd_update();
+			lcd_update(0);
 		}
 #else //TMC2130
 		manage_heater();
 		// Vojtech: Don't disable motors inside the planner!
 		manage_inactivity(true);
-		lcd_update();
+		lcd_update(0);
 #endif //TMC2130
 	}
 }

+ 189 - 0
Firmware/swi2c.c

@@ -0,0 +1,189 @@
+//swi2c.c
+#include "swi2c.h"
+#include <avr/io.h>
+#include <avr/delay.h>
+#include <avr/pgmspace.h>
+#include "Configuration_prusa.h"
+#include "pins.h"
+#include "io_atmega2560.h"
+
+
+#define SWI2C_RMSK   0x01 //read mask (bit0 = 1)
+#define SWI2C_WMSK   0x00 //write mask (bit0 = 0)
+#define SWI2C_ASHF   0x01 //address shift (<< 1)
+#define SWI2C_DMSK   0x7f //device address mask
+
+
+void __delay(void)
+{
+	_delay_us(1.5);
+}
+
+void swi2c_init(void)
+{
+	PIN_OUT(SWI2C_SDA);
+	PIN_OUT(SWI2C_SCL);
+	PIN_SET(SWI2C_SDA);
+	PIN_SET(SWI2C_SCL);
+	uint8_t i; for (i = 0; i < 100; i++)
+		__delay();
+}
+
+void swi2c_start(void)
+{
+	PIN_CLR(SWI2C_SDA);
+	__delay();
+	PIN_CLR(SWI2C_SCL);
+	__delay();
+}
+
+void swi2c_stop(void)
+{
+	PIN_SET(SWI2C_SCL);
+	__delay();
+	PIN_SET(SWI2C_SDA);
+	__delay();
+}
+
+void swi2c_ack(void)
+{
+	PIN_CLR(SWI2C_SDA);
+	__delay();
+	PIN_SET(SWI2C_SCL);
+	__delay();
+	PIN_CLR(SWI2C_SCL);
+	__delay();
+}
+
+uint8_t swi2c_wait_ack()
+{
+	PIN_INP(SWI2C_SDA);
+	__delay();
+//	PIN_SET(SWI2C_SDA);
+	__delay();
+	PIN_SET(SWI2C_SCL);
+//	__delay();
+	uint8_t ack = 0;
+	uint16_t ackto = SWI2C_TMO;
+	while (!(ack = (PIN_GET(SWI2C_SDA)?0:1)) && ackto--) __delay();
+	PIN_CLR(SWI2C_SCL);
+	__delay();
+	PIN_OUT(SWI2C_SDA);
+	__delay();
+	PIN_CLR(SWI2C_SDA);
+	__delay();
+	return ack;
+}
+
+uint8_t swi2c_read(void)
+{
+	PIN_SET(SWI2C_SDA);
+	__delay();
+	PIN_INP(SWI2C_SDA);
+	uint8_t data = 0;
+	int8_t bit; for (bit = 7; bit >= 0; bit--)
+	{
+		PIN_SET(SWI2C_SCL);
+		__delay();
+		data |= (PIN_GET(SWI2C_SDA)?1:0) << bit;
+		PIN_CLR(SWI2C_SCL);
+		__delay();
+	}
+	PIN_OUT(SWI2C_SDA);
+	return data;
+}
+
+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);
+		__delay();
+		PIN_SET(SWI2C_SCL);
+		__delay();
+		PIN_CLR(SWI2C_SCL);
+		__delay();
+	}
+}
+
+uint8_t swi2c_check(uint8_t dev_addr)
+{
+	swi2c_start();
+	swi2c_write((dev_addr & SWI2C_DMSK) << SWI2C_ASHF);
+	if (!swi2c_wait_ack()) { swi2c_stop(); return 0; }
+	swi2c_stop();
+	return 1;
+}
+
+#ifdef SWI2C_A8 //8bit address
+
+uint8_t swi2c_readByte_A8(uint8_t dev_addr, uint8_t addr, uint8_t* pbyte)
+{
+	swi2c_start();
+	swi2c_write(SWI2C_WMSK | ((dev_addr & SWI2C_DMSK) << SWI2C_ASHF));
+	if (!swi2c_wait_ack()) { swi2c_stop(); return 0; }
+	swi2c_write(addr & 0xff);
+	if (!swi2c_wait_ack()) return 0;
+	swi2c_stop();
+	swi2c_start();
+	swi2c_write(SWI2C_RMSK | ((dev_addr & SWI2C_DMSK) << SWI2C_ASHF));
+	if (!swi2c_wait_ack()) return 0;
+	uint8_t byte = swi2c_read();
+	swi2c_stop();
+	if (pbyte) *pbyte = byte;
+	return 1;
+}
+
+uint8_t swi2c_writeByte_A8(uint8_t dev_addr, uint8_t addr, uint8_t* pbyte)
+{
+	swi2c_start();
+	swi2c_write(SWI2C_WMSK | ((dev_addr & SWI2C_DMSK) << SWI2C_ASHF));
+	if (!swi2c_wait_ack()) { swi2c_stop(); return 0; }
+	swi2c_write(addr & 0xff);
+	if (!swi2c_wait_ack()) return 0;
+	swi2c_write(*pbyte);
+	if (!swi2c_wait_ack()) return 0;
+	swi2c_stop();
+	return 1;
+}
+
+#endif //SWI2C_A8
+
+#ifdef SWI2C_A16 //16bit address
+
+uint8_t swi2c_readByte_A16(uint8_t dev_addr, unsigned short addr, uint8_t* pbyte)
+{
+	swi2c_start();
+	swi2c_write(SWI2C_WMSK | ((dev_addr & SWI2C_DMSK) << SWI2C_ASHF));
+	if (!swi2c_wait_ack()) { swi2c_stop(); return 0; }
+	swi2c_write(addr >> 8);
+	if (!swi2c_wait_ack()) return 0;
+	swi2c_write(addr & 0xff);
+	if (!swi2c_wait_ack()) return 0;
+	swi2c_stop();
+	swi2c_start();
+	swi2c_write(SWI2C_RMSK | ((dev_addr & SWI2C_DMSK) << SWI2C_ASHF));
+	if (!swi2c_wait_ack()) return 0;
+	uint8_t byte = swi2c_read();
+	swi2c_stop();
+	if (pbyte) *pbyte = byte;
+	return 1;
+}
+
+uint8_t swi2c_writeByte_A16(uint8_t dev_addr, unsigned short addr, uint8_t* pbyte)
+{
+	swi2c_start();
+	swi2c_write(SWI2C_WMSK | ((dev_addr & SWI2C_DMSK) << SWI2C_ASHF));
+	if (!swi2c_wait_ack()) { swi2c_stop(); return 0; }
+	swi2c_write(addr >> 8);
+	if (!swi2c_wait_ack()) return 0;
+	swi2c_write(addr & 0xff);
+	if (!swi2c_wait_ack()) return 0;
+	swi2c_write(*pbyte);
+	if (!swi2c_wait_ack()) return 0;
+	swi2c_stop();
+	return 1;
+}
+
+#endif //SWI2C_A16

+ 0 - 209
Firmware/swi2c.cpp

@@ -1,209 +0,0 @@
-#include "uni_avr_rpi.h"
-
-#ifdef SWI2C
-#include "swi2c.h"
-
-#ifdef __AVR
-unsigned char swi2c_sda = 20; // SDA pin
-unsigned char swi2c_scl = 21; // SCL pin
-#endif //__AVR
-
-#ifdef __RPI
-unsigned char swi2c_sda = 2; // SDA pin
-unsigned char swi2c_scl = 3; // SCL pin
-#endif //__RPI
-
-unsigned char swi2c_cfg = 0xb1; // config
-//  bit0..3 = clock delay factor = 1 << 1 = 2 [us]
-//  bit4..7 = ack timeout factor = 1 << 11 = 2048 [cycles]
-
-#define SWI2C_SDA    swi2c_sda
-#define SWI2C_SCL    swi2c_scl
-#define SWI2C_RMSK   0x01 //read mask (bit0 = 1)
-#define SWI2C_WMSK   0x00 //write mask (bit0 = 0)
-#define SWI2C_ASHF   0x01 //address shift (<< 1)
-#define SWI2C_DMSK   0x7f //device address mask
-
-
-void swi2c_init(unsigned char sda, unsigned char scl, unsigned char cfg)
-{
-	swi2c_sda = sda;
-	swi2c_scl = scl;
-	swi2c_cfg = cfg;
-	GPIO_OUT(SWI2C_SDA);
-	GPIO_OUT(SWI2C_SCL);
-	GPIO_SET(SWI2C_SDA);
-	GPIO_SET(SWI2C_SCL);
-	DELAY(1000);
-}
-
-void swi2c_start(int delay)
-{
-	GPIO_CLR(SWI2C_SDA);
-	DELAY(delay);
-	GPIO_CLR(SWI2C_SCL);
-	DELAY(delay);
-}
-
-void swi2c_stop(int delay)
-{
-	GPIO_SET(SWI2C_SCL);
-	DELAY(delay);
-	GPIO_SET(SWI2C_SDA);
-	DELAY(delay);
-}
-
-void swi2c_ack(int delay)
-{
-	GPIO_CLR(SWI2C_SDA);
-	DELAY(delay);
-	GPIO_SET(SWI2C_SCL);
-	DELAY(delay);
-	GPIO_CLR(SWI2C_SCL);
-	DELAY(delay);
-}
-
-int swi2c_wait_ack(int delay, int ackto)
-{
-	GPIO_INP(SWI2C_SDA);
-	DELAY(delay);
-//	GPIO_SET(SWI2C_SDA);
-	DELAY(delay);
-	GPIO_SET(SWI2C_SCL);
-//	DELAY(delay);
-	int ack = 0;
-	while (!(ack = !GPIO_GET(SWI2C_SDA)) && ackto--) DELAY(delay);
-	GPIO_CLR(SWI2C_SCL);
-	DELAY(delay);
-	GPIO_OUT(SWI2C_SDA);
-	DELAY(delay);
-	GPIO_CLR(SWI2C_SDA);
-	DELAY(delay);
-	return ack;
-}
-
-unsigned char swi2c_read(int delay)
-{
-	GPIO_SET(SWI2C_SDA);
-	DELAY(delay);
-	GPIO_INP(SWI2C_SDA);
-	unsigned char data = 0;
-	int bit; for (bit = 7; bit >= 0; bit--)
-	{
-		GPIO_SET(SWI2C_SCL);
-		DELAY(delay);
-		data |= GPIO_GET(SWI2C_SDA) << bit;
-		GPIO_CLR(SWI2C_SCL);
-		DELAY(delay);
-	}
-	GPIO_OUT(SWI2C_SDA);
-	return data;
-}
-
-void swi2c_write(int delay, unsigned char data)
-{
-	int bit; for (bit = 7; bit >= 0; bit--)
-	{
-		if (data & (1 << bit)) GPIO_SET(SWI2C_SDA);
-		else GPIO_CLR(SWI2C_SDA);
-		DELAY(delay);
-		GPIO_SET(SWI2C_SCL);
-		DELAY(delay);
-		GPIO_CLR(SWI2C_SCL);
-		DELAY(delay);
-	}
-}
-
-int swi2c_check(unsigned char dev_addr)
-{
-	int delay = 1 << (swi2c_cfg & 0xf);
-	int tmout = 1 << (swi2c_cfg >> 4);
-	swi2c_start(delay);
-	swi2c_write(delay, (dev_addr & SWI2C_DMSK) << SWI2C_ASHF);
-	if (!swi2c_wait_ack(delay, tmout)) { swi2c_stop(delay); return 0; }
-	swi2c_stop(delay);
-	return 1;
-}
-
-#ifdef SWI2C_A8 //8bit address
-
-int swi2c_readByte_A8(unsigned char dev_addr, unsigned char addr, unsigned char* pbyte)
-{
-	int delay = 1 << (swi2c_cfg & 0xf);
-	int tmout = 1 << (swi2c_cfg >> 4);
-	swi2c_start(delay);
-	swi2c_write(delay, SWI2C_WMSK | ((dev_addr & SWI2C_DMSK) << SWI2C_ASHF));
-	if (!swi2c_wait_ack(delay, tmout)) { swi2c_stop(delay); return 0; }
-	swi2c_write(delay, addr & 0xff);
-	if (!swi2c_wait_ack(delay, tmout)) return 0;
-	swi2c_stop(delay);
-	swi2c_start(delay);
-	swi2c_write(delay, SWI2C_RMSK | ((dev_addr & SWI2C_DMSK) << SWI2C_ASHF));
-	if (!swi2c_wait_ack(delay, tmout)) return 0;
-	unsigned char byte = swi2c_read(delay);
-	swi2c_stop(delay);
-	if (pbyte) *pbyte = byte;
-	return 1;
-}
-
-int swi2c_writeByte_A8(unsigned char dev_addr, unsigned char addr, unsigned char* pbyte)
-{
-	int delay = 1 << (swi2c_cfg & 0xf);
-	int tmout = 1 << (swi2c_cfg >> 4);
-	swi2c_start(delay);
-	swi2c_write(delay, SWI2C_WMSK | ((dev_addr & SWI2C_DMSK) << SWI2C_ASHF));
-	if (!swi2c_wait_ack(delay, tmout)) { swi2c_stop(delay); return 0; }
-	swi2c_write(delay, addr & 0xff);
-	if (!swi2c_wait_ack(delay, tmout)) return 0;
-	swi2c_write(delay, *pbyte);
-	if (!swi2c_wait_ack(delay, tmout)) return 0;
-	swi2c_stop(delay);
-	return 1;
-}
-
-#endif //SWI2C_A8
-
-#ifdef SWI2C_A16 //16bit address
-
-int swi2c_readByte_A16(unsigned char dev_addr, unsigned short addr, unsigned char* pbyte)
-{
-	int delay = 1 << (swi2c_cfg & 0xf);
-	int tmout = 1 << (swi2c_cfg >> 4);
-	swi2c_start(delay);
-	swi2c_write(delay, SWI2C_WMSK | ((dev_addr & SWI2C_DMSK) << SWI2C_ASHF));
-	if (!swi2c_wait_ack(delay, tmout)) { swi2c_stop(delay); return 0; }
-	swi2c_write(delay, addr >> 8);
-	if (!swi2c_wait_ack(delay, tmout)) return 0;
-	swi2c_write(delay, addr & 0xff);
-	if (!swi2c_wait_ack(delay, tmout)) return 0;
-	swi2c_stop(delay);
-	swi2c_start(delay);
-	swi2c_write(delay, SWI2C_RMSK | ((dev_addr & SWI2C_DMSK) << SWI2C_ASHF));
-	if (!swi2c_wait_ack(delay, tmout)) return 0;
-	unsigned char byte = swi2c_read(delay);
-	swi2c_stop(delay);
-	if (pbyte) *pbyte = byte;
-	return 1;
-}
-
-int swi2c_writeByte_A16(unsigned char dev_addr, unsigned short addr, unsigned char* pbyte)
-{
-	int delay = 1 << (swi2c_cfg & 0xf);
-	int tmout = 1 << (swi2c_cfg >> 4);
-	swi2c_start(delay);
-	swi2c_write(delay, SWI2C_WMSK | ((dev_addr & SWI2C_DMSK) << SWI2C_ASHF));
-	if (!swi2c_wait_ack(delay, tmout)) { swi2c_stop(delay); return 0; }
-	swi2c_write(delay, addr >> 8);
-	if (!swi2c_wait_ack(delay, tmout)) return 0;
-	swi2c_write(delay, addr & 0xff);
-	if (!swi2c_wait_ack(delay, tmout)) return 0;
-	swi2c_write(delay, *pbyte);
-	if (!swi2c_wait_ack(delay, tmout)) return 0;
-	swi2c_stop(delay);
-	return 1;
-}
-
-#endif //SWI2C_A16
-
-
-#endif //SWI2C

+ 19 - 6
Firmware/swi2c.h

@@ -1,22 +1,35 @@
+//swi2c.h
 #ifndef SWI2C_H
 #define SWI2C_H
 
+#include <inttypes.h>
+#include "config.h"
+
+
+#if defined(__cplusplus)
+extern "C" {
+#endif //defined(__cplusplus)
+
 //initialize
-extern void swi2c_init(unsigned char sda, unsigned char scl, unsigned char cfg);
+extern void swi2c_init(void);
 
 //check device address acknowledge
-extern int swi2c_check(unsigned char dev_addr);
+extern uint8_t swi2c_check(uint8_t dev_addr);
 
 //read write functions - 8bit address (most i2c chips)
 #ifdef SWI2C_A8
-extern int swi2c_readByte_A8(unsigned char dev_addr, unsigned char addr, unsigned char* pbyte);
-extern int swi2c_writeByte_A8(unsigned char dev_addr, unsigned char addr, unsigned char* pbyte);
+extern uint8_t swi2c_readByte_A8(uint8_t dev_addr, uint8_t addr, uint8_t* pbyte);
+extern uint8_t swi2c_writeByte_A8(uint8_t dev_addr, uint8_t addr, uint8_t* pbyte);
 #endif //SWI2C_A8
 
 //read write functions - 16bit address (e.g. serial eeprom AT24C256)
 #ifdef SWI2C_A16
-extern int swi2c_readByte_A16(unsigned char dev_addr, unsigned short addr, unsigned char* pbyte);
-extern int swi2c_writeByte_A16(unsigned char dev_addr, unsigned short addr, unsigned char* pbyte);
+extern uint8_t swi2c_readByte_A16(uint8_t dev_addr, uint16_t addr, uint8_t* pbyte);
+extern uint8_t swi2c_writeByte_A16(uint8_t dev_addr, uint16_t addr, uint8_t* pbyte);
 #endif //SWI2C_A16
 
+#if defined(__cplusplus)
+}
+#endif //defined(__cplusplus)
+
 #endif //SWI2C_H

+ 2 - 2
Firmware/temperature.cpp

@@ -403,7 +403,7 @@ unsigned long watchmillis[EXTRUDERS] = ARRAY_BY_EXTRUDERS(0,0,0);
 	  pid_cycle = 0;
       return;
     }
-    lcd_update();
+    lcd_update(0);
   }
 }
 
@@ -1332,7 +1332,7 @@ void temp_runaway_stop(bool isPreheat, bool isBed)
 	disable_e1();
 	disable_e2();
 	manage_heater();
-	lcd_update();
+	lcd_update(0);
 	WRITE(BEEPER, HIGH);
 	delayMicroseconds(500);
 	WRITE(BEEPER, LOW);

+ 21 - 20
Firmware/tmc2130.cpp

@@ -3,13 +3,11 @@
 #ifdef TMC2130
 
 #include "tmc2130.h"
-#include "LiquidCrystal_Prusa.h"
 #include "ultralcd.h"
 #include "language.h"
 #include "spi.h"
 
 
-extern LiquidCrystal_Prusa lcd;
 
 #define TMC2130_GCONF_NORMAL 0x00000000 // spreadCycle
 #define TMC2130_GCONF_SGSENS 0x00003180 // spreadCycle with stallguard (stall activates DIAG0 and DIAG1 [pushpull])
@@ -62,6 +60,13 @@ uint8_t tmc2130_home_fsteps[2] = {48, 48};
 
 uint8_t tmc2130_wave_fac[4] = {0, 0, 0, 0};
 
+tmc2130_chopper_config_t tmc2130_chopper_config[4] = {
+	{TMC2130_TOFF_XYZ, 5, 1, 2, 0},
+	{TMC2130_TOFF_XYZ, 5, 1, 2, 0},
+	{TMC2130_TOFF_XYZ, 5, 1, 2, 0},
+	{TMC2130_TOFF_E, 5, 1, 2, 0}
+};
+
 bool tmc2130_sg_stop_on_crash = true;
 uint8_t tmc2130_sg_diag_mask = 0x00;
 uint8_t tmc2130_sg_crash = 0;
@@ -407,9 +412,9 @@ void tmc2130_check_overtemp()
 		for (int i = 0; i < 4; i++)
 		{
 			tmc2130_sg_change = false;
-			lcd.setCursor(0 + i*4, 3);
-			lcd.print(itostr3(tmc2130_sg_cnt[i]));
-			lcd.print(' ');
+			lcd_set_cursor(0 + i*4, 3);
+			lcd_print(itostr3(tmc2130_sg_cnt[i]));
+			lcd_print(' ');
 		}
 	}
 #endif //DEBUG_CRASHDET_COUNTERS
@@ -418,13 +423,13 @@ void tmc2130_check_overtemp()
 void tmc2130_setup_chopper(uint8_t axis, uint8_t mres, uint8_t current_h, uint8_t current_r)
 {
 	uint8_t intpol = 1;
-	uint8_t toff = TMC2130_TOFF_XYZ; // toff = 3 (fchop = 27.778kHz)
-	uint8_t hstrt = 5; //initial 4, modified to 5
-	uint8_t hend = 1;
+	uint8_t toff = tmc2130_chopper_config[axis].toff; // toff = 3 (fchop = 27.778kHz)
+	uint8_t hstrt = tmc2130_chopper_config[axis].hstr; //initial 4, modified to 5
+	uint8_t hend = tmc2130_chopper_config[axis].hend; //original value = 1
 	uint8_t fd3 = 0;
 	uint8_t rndtf = 0; //random off time
 	uint8_t chm = 0; //spreadCycle
-	uint8_t tbl = 2; //blanking time
+	uint8_t tbl = tmc2130_chopper_config[axis].tbl; //blanking time, original value = 2
 	if (axis == E_AXIS)
 	{
 #ifdef TMC2130_CNSTOFF_E
@@ -434,9 +439,11 @@ void tmc2130_setup_chopper(uint8_t axis, uint8_t mres, uint8_t current_h, uint8_
 		hend = 0; //sine wave offset
 		chm = 1; // constant off time mod
 #endif //TMC2130_CNSTOFF_E
-		toff = TMC2130_TOFF_E; // toff = 3-5
+//		toff = TMC2130_TOFF_E; // toff = 3-5
 //		rndtf = 1;
 	}
+	DBG(_n("tmc2130_setup_chopper(axis=%hhd, mres=%hhd, curh=%hhd, curr=%hhd\n"), axis, mres, current_h, current_r);
+	DBG(_n(" toff=%hhd, hstr=%hhd, hend=%hhd, tbl=%hhd\n"), toff, hstrt, hend, tbl);
 	if (current_r <= 31)
 	{
 		tmc2130_wr_CHOPCONF(axis, toff, hstrt, hend, fd3, 0, rndtf, chm, tbl, 1, 0, 0, 0, mres, intpol, 0, 0);
@@ -444,7 +451,7 @@ void tmc2130_setup_chopper(uint8_t axis, uint8_t mres, uint8_t current_h, uint8_
 	}
 	else
 	{
-		tmc2130_wr_CHOPCONF(axis, toff, hstrt, hend, fd3, 0, 0, 0, tbl, 0, 0, 0, 0, mres, intpol, 0, 0);
+		tmc2130_wr_CHOPCONF(axis, toff, hstrt, hend, fd3, 0, rndtf, chm, tbl, 0, 0, 0, 0, mres, intpol, 0, 0);
 		tmc2130_wr(axis, TMC2130_REG_IHOLD_IRUN, 0x000f0000 | (((current_r >> 1) & 0x1f) << 8) | ((current_h >> 1) & 0x1f));
 	}
 }
@@ -475,10 +482,7 @@ void tmc2130_print_currents()
 
 void tmc2130_set_pwm_ampl(uint8_t axis, uint8_t pwm_ampl)
 {
-	MYSERIAL.print("tmc2130_set_pwm_ampl ");
-	MYSERIAL.print((int)axis);
-	MYSERIAL.print(" ");
-	MYSERIAL.println((int)pwm_ampl);
+	DBG(_n("tmc2130_set_pwm_ampl(axis=%hhd, pwm_ampl=%hhd\n"), axis, pwm_ampl);
 	tmc2130_pwm_ampl[axis] = pwm_ampl;
 	if (((axis == 0) || (axis == 1)) && (tmc2130_mode == TMC2130_MODE_SILENT))
 		tmc2130_wr_PWMCONF(axis, tmc2130_pwm_ampl[axis], tmc2130_pwm_grad[axis], tmc2130_pwm_freq[axis], tmc2130_pwm_auto[axis], 0, 0);
@@ -486,10 +490,7 @@ void tmc2130_set_pwm_ampl(uint8_t axis, uint8_t pwm_ampl)
 
 void tmc2130_set_pwm_grad(uint8_t axis, uint8_t pwm_grad)
 {
-	MYSERIAL.print("tmc2130_set_pwm_grad ");
-	MYSERIAL.print((int)axis);
-	MYSERIAL.print(" ");
-	MYSERIAL.println((int)pwm_grad);
+	DBG(_n("tmc2130_set_pwm_grad(axis=%hhd, pwm_grad=%hhd\n"), axis, pwm_grad);
 	tmc2130_pwm_grad[axis] = pwm_grad;
 	if (((axis == 0) || (axis == 1)) && (tmc2130_mode == TMC2130_MODE_SILENT))
 		tmc2130_wr_PWMCONF(axis, tmc2130_pwm_ampl[axis], tmc2130_pwm_grad[axis], tmc2130_pwm_freq[axis], tmc2130_pwm_auto[axis], 0, 0);
@@ -865,7 +866,7 @@ void tmc2130_set_wave(uint8_t axis, uint8_t amp, uint8_t fac1000)
 	if (fac1000 < TMC2130_WAVE_FAC1000_MIN) fac1000 = 0;
 	if (fac1000 > TMC2130_WAVE_FAC1000_MAX) fac1000 = TMC2130_WAVE_FAC1000_MAX;
 	float fac = 0;
-	if (fac1000) fac = (float)((uint16_t)fac1000 + 1000) / 1000; //correction factor
+	if (fac1000) fac = ((float)((uint16_t)fac1000 + 1000) / 1000); //correction factor
 	printf_P(PSTR(" factor: %s\n"), ftostr43(fac));
 	uint8_t vA = 0;                //value of currentA
 	uint8_t va = 0;                //previous vA

+ 15 - 0
Firmware/tmc2130.h

@@ -36,6 +36,19 @@ extern uint8_t tmc2130_home_fsteps[2];
 
 extern uint8_t tmc2130_wave_fac[4];
 
+#pragma pack(push)
+#pragma pack(1)
+typedef struct
+{
+	uint8_t toff:4;
+	uint8_t hstr:3;
+	uint8_t hend:4;
+	uint8_t tbl:2;
+	uint8_t res:3;
+} tmc2130_chopper_config_t;
+#pragma pack(pop)
+
+extern tmc2130_chopper_config_t tmc2130_chopper_config[4];
 
 //initialize tmc2130
 extern void tmc2130_init();
@@ -55,6 +68,7 @@ extern void tmc2130_sg_meassure_start(uint8_t axis);
 //stop current stallguard meassuring and report result
 extern uint16_t tmc2130_sg_meassure_stop();
 
+extern void tmc2130_setup_chopper(uint8_t axis, uint8_t mres, uint8_t current_h, uint8_t current_r);
 
 //set holding current for any axis (M911)
 extern void tmc2130_set_current_h(uint8_t axis, uint8_t current);
@@ -80,6 +94,7 @@ extern bool tmc2130_wait_standstill_xy(int timeout);
 extern void tmc2130_eeprom_load_config();
 extern void tmc2130_eeprom_save_config();
 
+
 #pragma pack(push)
 #pragma pack(1)
 struct

+ 1482 - 2228
Firmware/ultralcd.cpp

@@ -1,7 +1,6 @@
 #include "temperature.h"
 #include "ultralcd.h"
-#ifdef ULTRA_LCD
-#include "MenuStack.h"
+#include "fsensor.h"
 #include "Marlin.h"
 #include "language.h"
 #include "cardreader.h"
@@ -11,8 +10,14 @@
 #include <string.h>
 #include "Timer.h"
 
+
+#include "lcd.h"
+#include "menu.h"
+
 #include "util.h"
 #include "mesh_bed_leveling.h"
+#include "mesh_bed_calibration.h"
+
 //#include "Configuration.h"
 #include "cmdqueue.h"
 
@@ -30,7 +35,6 @@
 #include "uart2.h"
 #endif //SNMM_V2
 
-int8_t encoderDiff; /* encoderDiff is updated from interrupt context and added to encoderPosition every LCD update */
 
 extern int lcd_change_fil_state;
 extern bool fans_check_enabled;
@@ -41,7 +45,8 @@ extern bool fsensor_not_responding;
 extern bool fsensor_enabled;
 #endif //PAT9125
 
-//Function pointer to menu functions.
+int scrollstuff = 0;
+char longFilenameOLD[LONG_FILENAME_LENGTH];
 
 
 static void lcd_sd_updir();
@@ -49,13 +54,13 @@ static void lcd_sd_updir();
 struct EditMenuParentState
 {
     //prevMenu and prevEncoderPosition are used to store the previous menu location when editing settings.
-    menuFunc_t prevMenu;
+    menu_func_t prevMenu;
     uint16_t prevEncoderPosition;
     //Variables used when editing values.
     const char* editLabel;
     void* editValue;
     int32_t minEditValue, maxEditValue;
-    // menuFunc_t callbackFunc;
+    // menu_func_t callbackFunc;
 };
 
 union MenuData
@@ -128,17 +133,12 @@ union MenuData
 
 // State of the currently active menu.
 // C Union manages sharing of the static memory by all the menus.
-union MenuData menuData = { 0 };
+//union MenuData menuData = { 0 };
+#define menuData (*((MenuData*)menu_data))
+
 
-union Data
-{
-  byte b[2];
-  int value;
-};
-static MenuStack menuStack;
 int8_t ReInitLCD = 0;
 
-int8_t SDscrool = 0;
 
 int8_t SilentModeMenu = SILENT_MODE_OFF;
 
@@ -178,20 +178,11 @@ bool printer_connected = true;
 unsigned long display_time; //just timer for showing pid finished message on lcd;
 float pid_temp = DEFAULT_PID_TEMP;
 
-bool long_press_active = false;
-static ShortTimer longPressTimer;
-unsigned long button_blanking_time = millis();
-bool button_pressed = false;
 
 bool menuExiting = false;
 
-#ifdef FILAMENT_LCD_DISPLAY
-unsigned long message_millis = 0;
-#endif
 
-#ifdef ULTIPANEL
 static float manual_feedrate[] = MANUAL_FEEDRATE;
-#endif // ULTIPANEL
 
 /* !Configuration settings */
 
@@ -199,7 +190,6 @@ uint8_t lcd_status_message_level;
 char lcd_status_message[LCD_WIDTH + 1] = ""; //////WELCOME!
 unsigned char firstrun = 1;
 
-#include "ultralcd_implementation_hitachi_HD44780.h"
 
 static const char separator[] PROGMEM = "--------------------";
 
@@ -211,7 +201,6 @@ static const char* lcd_display_message_fullscreen_nonBlocking_P(const char *msg,
 
 /* Different menus */
 static void lcd_status_screen();
-#ifdef ULTIPANEL
 extern bool powersupply;
 static void lcd_main_menu();
 static void lcd_tune_menu();
@@ -241,9 +230,6 @@ static void lcd_menu_fails_stats();
 
 void lcd_finishstatus();
 
-#ifdef DOGLCD
-static void lcd_set_contrast();
-#endif
 static void lcd_control_retract_menu();
 static void lcd_sdcard_menu();
 
@@ -251,106 +237,41 @@ static void lcd_sdcard_menu();
 static void lcd_delta_calibrate_menu();
 #endif // DELTA_CALIBRATION_MENU
 
-static void lcd_quick_feedback();//Cause an LCD refresh, and give the user visual or audible feedback that something has happened
 
 /* Different types of actions that can be used in menu items. */
-static void menu_action_sdfile(const char* filename, char* longFilename);
-static void menu_action_sddirectory(const char* filename, char* longFilename);
-static void menu_action_setting_edit_bool(const char* pstr, bool* ptr);
-static void menu_action_setting_edit_wfac(const char* pstr, uint8_t* ptr, uint8_t minValue, uint8_t maxValue);
-static void menu_action_setting_edit_mres(const char* pstr, uint8_t* ptr, uint8_t minValue, uint8_t maxValue);
-static void menu_action_setting_edit_byte3(const char* pstr, uint8_t* ptr, uint8_t minValue, uint8_t maxValue);
-static void menu_action_setting_edit_int3(const char* pstr, int* ptr, int minValue, int maxValue);
-static void menu_action_setting_edit_float3(const char* pstr, float* ptr, float minValue, float maxValue);
-static void menu_action_setting_edit_float32(const char* pstr, float* ptr, float minValue, float maxValue);
-static void menu_action_setting_edit_float43(const char* pstr, float* ptr, float minValue, float maxValue);
-static void menu_action_setting_edit_float5(const char* pstr, float* ptr, float minValue, float maxValue);
-static void menu_action_setting_edit_float51(const char* pstr, float* ptr, float minValue, float maxValue);
-static void menu_action_setting_edit_float52(const char* pstr, float* ptr, float minValue, float maxValue);
-static void menu_action_setting_edit_long5(const char* pstr, unsigned long* ptr, unsigned long minValue, unsigned long maxValue);
-
-/*
-static void menu_action_setting_edit_callback_bool(const char* pstr, bool* ptr, menuFunc_t callbackFunc);
-static void menu_action_setting_edit_callback_int3(const char* pstr, int* ptr, int minValue, int maxValue, menuFunc_t callbackFunc);
-static void menu_action_setting_edit_callback_float3(const char* pstr, float* ptr, float minValue, float maxValue, menuFunc_t callbackFunc);
-static void menu_action_setting_edit_callback_float32(const char* pstr, float* ptr, float minValue, float maxValue, menuFunc_t callbackFunc);
-static void menu_action_setting_edit_callback_float43(const char* pstr, float* ptr, float minValue, float maxValue, menuFunc_t callbackFunc);
-static void menu_action_setting_edit_callback_float5(const char* pstr, float* ptr, float minValue, float maxValue, menuFunc_t callbackFunc);
-static void menu_action_setting_edit_callback_float51(const char* pstr, float* ptr, float minValue, float maxValue, menuFunc_t callbackFunc);
-static void menu_action_setting_edit_callback_float52(const char* pstr, float* ptr, float minValue, float maxValue, menuFunc_t callbackFunc);
-static void menu_action_setting_edit_callback_long5(const char* pstr, unsigned long* ptr, unsigned long minValue, unsigned long maxValue, menuFunc_t callbackFunc);
-*/
+void menu_action_sdfile(const char* filename, char* longFilename);
+void menu_action_sddirectory(const char* filename, char* longFilename);
 
 #define ENCODER_FEEDRATE_DEADZONE 10
 
-#if !defined(LCD_I2C_VIKI)
-#ifndef ENCODER_STEPS_PER_MENU_ITEM
-#define ENCODER_STEPS_PER_MENU_ITEM 5
-#endif
-#ifndef ENCODER_PULSES_PER_STEP
-#define ENCODER_PULSES_PER_STEP 1
-#endif
-#else
-#ifndef ENCODER_STEPS_PER_MENU_ITEM
-#define ENCODER_STEPS_PER_MENU_ITEM 2 // VIKI LCD rotary encoder uses a different number of steps per rotation
-#endif
-#ifndef ENCODER_PULSES_PER_STEP
-#define ENCODER_PULSES_PER_STEP 1
-#endif
-#endif
-
-uint8_t _lineNr = 0;
-uint8_t _menuItemNr = 0;
-uint8_t _drawLineNr = 0;
-
-bool wasClicked = false;
 
+/*
 #define MENU_ITEM(type, label, args...) do { \
-    if (_menuItemNr == _lineNr) { \
-      if (lcdDrawUpdate) { \
+    if (menu_item == menu_line) { \
+      if (lcd_draw_update) { \
         const char* _label_pstr = (label); \
-        if ((encoderPosition / ENCODER_STEPS_PER_MENU_ITEM) == _menuItemNr) { \
-          lcd_implementation_drawmenu_ ## type ## _selected (_drawLineNr, _label_pstr , ## args ); \
+        if (lcd_encoder == menu_item) { \
+          lcd_implementation_drawmenu_ ## type ## _selected (menu_row, _label_pstr , ## args ); \
         }else{\
-          lcd_implementation_drawmenu_ ## type (_drawLineNr, _label_pstr , ## args ); \
+          lcd_implementation_drawmenu_ ## type (menu_row, _label_pstr , ## args ); \
         }\
       }\
-      if (wasClicked && (encoderPosition / ENCODER_STEPS_PER_MENU_ITEM) == _menuItemNr) {\
+      if (menu_clicked && (lcd_encoder == menu_item)) {\
         lcd_quick_feedback(); \
         menu_action_ ## type ( args ); \
         return;\
       }\
     }\
-    _menuItemNr++;\
+    menu_item++;\
   } while(0)
+*/
 
-//#define MENU_ITEM_DUMMY() do { _menuItemNr++; } while(0)
-#define MENU_ITEM_EDIT(type, label, args...) MENU_ITEM(setting_edit_ ## type, label, (label) , ## args )
-#define MENU_ITEM_EDIT_CALLBACK(type, label, args...) MENU_ITEM(setting_edit_callback_ ## type, label, (label) , ## args )
-
-/** Used variables to keep track of the menu */
-#ifndef REPRAPWORLD_KEYPAD
-volatile uint8_t buttons;//Contains the bits of the currently pressed buttons.
-#else
-volatile uint8_t buttons_reprapworld_keypad; // to store the reprapworld_keypad shift register values
-#endif
-#ifdef LCD_HAS_SLOW_BUTTONS
-volatile uint8_t slow_buttons;//Contains the bits of the currently pressed buttons.
-#endif
-uint8_t currentMenuViewOffset;              /* scroll offset in the current menu */
-uint8_t lastEncoderBits;
-uint32_t encoderPosition;
 #if (SDCARDDETECT > 0)
 bool lcd_oldcardstatus;
 #endif
-#endif //ULTIPANEL
 
-menuFunc_t currentMenu = lcd_status_screen; /* function pointer to the currently active menu */
-uint32_t lcd_next_update_millis;
-uint8_t lcd_status_update_delay;
 bool ignore_click = false;
 bool wait_for_unclick;
-uint8_t lcdDrawUpdate = 2;                  /* Set to none-zero when the LCD needs to draw, decreased after every draw. Set to 2 in LCD routines so the LCD gets at least 1 full redraw (first redraw is partial) */
 
 // place-holders for Ki and Kd edits
 #ifdef PIDTEMP
@@ -358,320 +279,658 @@ uint8_t lcdDrawUpdate = 2;                  /* Set to none-zero when the LCD nee
 #endif
 
 
-/**
- * @brief Go to menu
- *
- * In MENU_ITEM_SUBMENU_P(str, func) use MENU_ITEM_BACK_P(str) or
- * menu_back() and menu_submenu() instead, otherwise menuStack will be broken.
- *
- * It is acceptable to call lcd_goto_menu(menu) directly from MENU_ITEM(function,...), if destination menu
- * is the same, from which function was called.
- *
- * @param menu target menu
- * @param encoder position in target menu
- * @param feedback
- *  * true sound feedback (click)
- *  * false no feedback
- * @param reset_menu_state
- *  * true reset menu state global union
- *  * false do not reset menu state global union
- */
-static void lcd_goto_menu(menuFunc_t menu, const uint32_t encoder = 0, const bool feedback = true, bool reset_menu_state = true)
-{
-	asm("cli");
-	if (currentMenu != menu)
-	{
-		currentMenu = menu;
-		encoderPosition = encoder;
-		asm("sei");
-		if (reset_menu_state)
-		{
-			// Resets the global shared C union.
-			// This ensures, that the menu entered will find out, that it shall initialize itself.
-			memset(&menuData, 0, sizeof(menuData));
-		}
-		if (feedback) lcd_quick_feedback();
-		// For LCD_PROGRESS_BAR re-initialize the custom characters
-#if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)
-		lcd_set_custom_characters(menu == lcd_status_screen);
-#endif
-	}
-	else
-		asm("sei");
-}
 
 
-////////////////////////////////////////////////////////////////////////////////
-// New Menu implementation
 
-#include <stdarg.h>
 
-int lcd_puts_P(const char* str)
-{
-	return fputs_P(str, lcdout);
-}
 
-int lcd_putc(int c)
-{
-	return fputc(c, lcdout);
-}
 
-int lcd_printf_P(const char* format, ...)
-{
-	va_list args;
-	va_start(args, format);
-	int ret = vfprintf_P(lcdout, format, args);
-	va_end(args);
-	return ret;
-}
 
-#define MENU_BEGIN() menu_start(); for(_drawLineNr = 0; _drawLineNr < LCD_HEIGHT; _drawLineNr++, _lineNr++) { _menuItemNr = 0;
-void menu_start(void)
-{
-    if (encoderPosition > 0x8000) encoderPosition = 0;
-    if (encoderPosition / ENCODER_STEPS_PER_MENU_ITEM < currentMenuViewOffset)
-		currentMenuViewOffset = encoderPosition / ENCODER_STEPS_PER_MENU_ITEM;
-    _lineNr = currentMenuViewOffset;
-    wasClicked = LCD_CLICKED;
-}
 
-#define MENU_END() menu_end(); }
-void menu_end(void)
-{
-	if (encoderPosition / ENCODER_STEPS_PER_MENU_ITEM >= _menuItemNr)
-		encoderPosition = _menuItemNr * ENCODER_STEPS_PER_MENU_ITEM - 1;
-	if ((uint8_t)(encoderPosition / ENCODER_STEPS_PER_MENU_ITEM) >= currentMenuViewOffset + LCD_HEIGHT)
+static inline void lcd_print_percent_done() {
+	if (is_usb_printing)
+	{
+		lcd_puts_P(PSTR("USB"));
+	}
+	else if(IS_SD_PRINTING)
 	{
-		currentMenuViewOffset = (encoderPosition / ENCODER_STEPS_PER_MENU_ITEM) - LCD_HEIGHT + 1;
-		lcdDrawUpdate = 1;
-		_lineNr = currentMenuViewOffset - 1;
-		_drawLineNr = -1;
+		lcd_puts_P(PSTR("SD"));
 	}
+	else
+	{
+		lcd_puts_P(PSTR("  "));
+	}
+	if (IS_SD_PRINTING || (PRINTER_ACTIVE && (print_percent_done_normal != PRINT_PERCENT_DONE_INIT)))
+	{
+		lcd_print(itostr3(print_percent_done()));
+	}
+	else
+	{
+		lcd_puts_P(PSTR("---"));
+	}
+	lcd_puts_P(PSTR("% "));
 }
 
-void menu_back(void)
-{
-	MenuStack::Record record = menuStack.pop();
-	lcd_goto_menu(record.menu);
-	encoderPosition = record.position;
+static inline void lcd_print_time() {
+	//if remaining print time estimation is available print it else print elapsed time
+	//uses 8 characters
+	uint16_t print_t = 0;
+	if (print_time_remaining_normal != PRINT_TIME_REMAINING_INIT){
+		print_t = print_time_remaining();
+	}
+	else if(starttime != 0){
+		print_t = millis() / 60000 - starttime / 60000;	
+	}
+	lcd_print(LCD_STR_CLOCK[0]);
+	if((PRINTER_ACTIVE) && ((print_time_remaining_normal != PRINT_TIME_REMAINING_INIT)||(starttime != 0)))
+	{
+		lcd_print(itostr2(print_t/60));
+        lcd_print(':');
+        lcd_print(itostr2(print_t%60));	
+		if (print_time_remaining_normal != PRINT_TIME_REMAINING_INIT)
+		{
+			lcd_print('R');
+			(feedmultiply == 100) ? lcd_print(' ') : lcd_print('?');
+		}
+		else {
+			lcd_puts_P(PSTR("  "));
+		}
+    }else{
+        lcd_puts_P(PSTR("--:--  "));
+    }
 }
 
-void menu_back_if_clicked(void)
-{
-	if (lcd_clicked())
-		menu_back();
-}
 
-void menu_back_if_clicked_fb(void)
+void lcd_implementation_drawmenu_sdfile_selected(uint8_t row, const char* pstr, const char* filename, char* longFilename)
 {
-	if (lcd_clicked())
-	{
-        lcd_quick_feedback();
-		menu_back();
-	}
-}
+    char c;
+    int enc_dif = lcd_encoder_diff;
+    uint8_t n = LCD_WIDTH - 1;
+    for(int g = 0; g<4;g++){
+      lcd_set_cursor(0, g);
+    lcd_print(' ');
+    }
 
-void menu_submenu(menuFunc_t submenu)
-{
-	menuStack.push(currentMenu, encoderPosition);
-	lcd_goto_menu(submenu);
-}
+    lcd_set_cursor(0, row);
+    lcd_print('>');
+    int i = 1;
+    int j = 0;
+    char* longFilenameTMP = longFilename;
 
-uint8_t menu_item_ret(void)
-{
-	lcd_implementation_quick_feedback();
-	lcdDrawUpdate = 2;
-	button_pressed = false;
-	return 1;
-}
+    while((c = *longFilenameTMP) != '\0')
+    {
+        lcd_set_cursor(i, row);
+        lcd_print(c);
+        i++;
+        longFilenameTMP++;
+        if(i==LCD_WIDTH){
+          i=1;
+          j++;
+          longFilenameTMP = longFilename + j;          
+          n = LCD_WIDTH - 1;
+          for(int g = 0; g<300 ;g++){
+			  manage_heater();
+            if(LCD_CLICKED || ( enc_dif != lcd_encoder_diff )){
+				longFilenameTMP = longFilename;
+				*(longFilenameTMP + LCD_WIDTH - 2) = '\0';
+				i = 1;
+				j = 0;
+				break;
+            }else{
+				if (j == 1) delay(3);	//wait around 1.2 s to start scrolling text
+				delay(1);				//then scroll with redrawing every 300 ms 
+            }
 
-uint8_t menu_enc_is_at_item(void)
-{
-	return ((encoderPosition / ENCODER_STEPS_PER_MENU_ITEM) == _menuItemNr);
+          }
+        }
+    }
+    if(c!='\0'){
+      lcd_set_cursor(i, row);
+        lcd_print(c);
+        i++;
+    }
+    n=n-i+1;
+    while(n--)
+        lcd_print(' ');
 }
-
-/*
-int menu_item_printf_P(char type_char, const char* format, ...)
+void lcd_implementation_drawmenu_sdfile(uint8_t row, const char* pstr, const char* filename, char* longFilename)
 {
-	va_list args;
-	va_start(args, format);
-	int ret = 0;
-    lcd.setCursor(0, _drawLineNr);
-	if ((encoderPosition / ENCODER_STEPS_PER_MENU_ITEM) == _menuItemNr)
-		lcd.print('>');
-	else
-		lcd.print(' ');
-	int cnt = vfprintf_P(lcdout, format, args);
-	for (int i = cnt; i < 18; i++)
-		lcd.print(' ');
-	lcd.print(type_char);
-	va_end(args);
-	return ret;
+    char c;
+    uint8_t n = LCD_WIDTH - 1;
+    lcd_set_cursor(0, row);
+    lcd_print(' ');
+    if (longFilename[0] != '\0')
+    {
+        filename = longFilename;
+        longFilename[LCD_WIDTH-1] = '\0';
+    }
+    while( ((c = *filename) != '\0') && (n>0) )
+    {
+        lcd_print(c);
+        filename++;
+        n--;
+    }
+    while(n--)
+        lcd_print(' ');
 }
-*/
-int menu_draw_item_puts_P(char type_char, const char* str)
+void lcd_implementation_drawmenu_sddirectory_selected(uint8_t row, const char* pstr, const char* filename, char* longFilename)
 {
-    lcd.setCursor(0, _drawLineNr);
-	int cnt = lcd_printf_P(_N("%c%-18S%c"), menu_enc_is_at_item()?'>':' ', str, type_char);
-	return cnt;
+    char c;
+    uint8_t n = LCD_WIDTH - 2;
+    lcd_set_cursor(0, row);
+    lcd_print('>');
+    lcd_print(LCD_STR_FOLDER[0]);
+    if (longFilename[0] != '\0')
+    {
+        filename = longFilename;
+        longFilename[LCD_WIDTH-2] = '\0';
+    }
+    while( ((c = *filename) != '\0') && (n>0) )
+    {
+        lcd_print(c);
+        filename++;
+        n--;
+    }
+    while(n--)
+        lcd_print(' ');
 }
-
-#define MENU_ITEM_DUMMY() menu_item_dummy()
-inline void menu_item_dummy(void)
+void lcd_implementation_drawmenu_sddirectory(uint8_t row, const char* pstr, const char* filename, char* longFilename)
 {
-	_menuItemNr++;
+    char c;
+    uint8_t n = LCD_WIDTH - 2;
+    lcd_set_cursor(0, row);
+    lcd_print(' ');
+    lcd_print(LCD_STR_FOLDER[0]);
+    if (longFilename[0] != '\0')
+    {
+        filename = longFilename;
+        longFilename[LCD_WIDTH-2] = '\0';
+    }
+    while( ((c = *filename) != '\0') && (n>0) )
+    {
+        lcd_print(c);
+        filename++;
+        n--;
+    }
+    while(n--)
+        lcd_print(' ');
 }
 
-#define MENU_ITEM_TEXT_P(str) do { if (menu_item_text_P(str)) return; } while (0)
-uint8_t menu_item_text_P(const char* str)
+
+
+#define MENU_ITEM_SDDIR(str, str_fn, str_fnl) do { if (menu_item_sddir(str, str_fn, str_fnl)) return; } while (0)
+//#define MENU_ITEM_SDDIR(str, str_fn, str_fnl) MENU_ITEM(sddirectory, str, str_fn, str_fnl)
+//extern uint8_t menu_item_sddir(const char* str, const char* str_fn, char* str_fnl);
+
+#define MENU_ITEM_SDFILE(str, str_fn, str_fnl) do { if (menu_item_sdfile(str, str_fn, str_fnl)) return; } while (0)
+//#define MENU_ITEM_SDFILE(str, str_fn, str_fnl) MENU_ITEM(sdfile, str, str_fn, str_fnl)
+//extern uint8_t menu_item_sdfile(const char* str, const char* str_fn, char* str_fnl);
+
+
+uint8_t menu_item_sddir(const char* str, const char* str_fn, char* str_fnl)
 {
-	if (_menuItemNr == _lineNr)
+#ifdef NEW_SD_MENU
+//	str_fnl[18] = 0;
+//	printf_P(PSTR("menu dir %d '%s' '%s'\n"), menu_row, str_fn, str_fnl);
+	if (menu_item == menu_line)
 	{
-		if (lcdDrawUpdate) menu_draw_item_puts_P(' ', str);
-		if (wasClicked && menu_enc_is_at_item())
+		if (lcd_draw_update)
+		{
+			lcd_set_cursor(0, menu_row);
+			int cnt = lcd_printf_P(PSTR("%c%c%-18s"), (lcd_encoder == menu_item)?'>':' ', LCD_STR_FOLDER[0], str_fnl[0]?str_fnl:str_fn);
+//			int cnt = lcd_printf_P(PSTR("%c%c%-18s"), (lcd_encoder == menu_item)?'>':' ', LCD_STR_FOLDER[0], str_fn);
+		}
+		if (menu_clicked && (lcd_encoder == menu_item))
+		{
+			uint8_t depth = (uint8_t)card.getWorkDirDepth();
+			strcpy(dir_names[depth], str_fn);
+//			printf_P(PSTR("%s\n"), dir_names[depth]);
+			card.chdir(str_fn);
+			lcd_encoder = 0;
 			return menu_item_ret();
+		}
 	}
-	_menuItemNr++;
+	menu_item++;
 	return 0;
-}
-
-#define MENU_ITEM_SUBMENU_P(str, submenu) do { if (menu_item_submenu_P(str, submenu)) return; } while (0)
-uint8_t menu_item_submenu_P(const char* str, menuFunc_t submenu)
-{
-	if (_menuItemNr == _lineNr)
+#else //NEW_SD_MENU
+	if (menu_item == menu_line)
 	{
-		if (lcdDrawUpdate) menu_draw_item_puts_P(LCD_STR_ARROW_RIGHT[0], str);
-		if (wasClicked && menu_enc_is_at_item())
+		if (lcd_draw_update)
 		{
-			menuStack.push(currentMenu, encoderPosition);
-			lcd_goto_menu(submenu, 0, false, true);
+			if (lcd_encoder == menu_item)
+				lcd_implementation_drawmenu_sddirectory_selected(menu_row, str, str_fn, str_fnl);
+			else
+				lcd_implementation_drawmenu_sddirectory(menu_row, str, str_fn, str_fnl);
+		}
+		if (menu_clicked && (lcd_encoder == menu_item))
+		{
+			menu_clicked = false;
+			lcd_update_enabled = 0;
+			menu_action_sddirectory(str_fn, str_fnl);
+			lcd_update_enabled = 1;
 			return menu_item_ret();
 		}
 	}
-	_menuItemNr++;
+	menu_item++;
 	return 0;
+
+#endif //NEW_SD_MENU
 }
 
-#define MENU_ITEM_BACK_P(str) do { if (menu_item_back_P(str)) return; } while (0)
-uint8_t menu_item_back_P(const char* str)
+uint8_t menu_item_sdfile(const char* str, const char* str_fn, char* str_fnl)
 {
-	if (_menuItemNr == _lineNr)
+#ifdef NEW_SD_MENU
+//	printf_P(PSTR("menu sdfile\n"));
+//	str_fnl[19] = 0;
+//	printf_P(PSTR("menu file %d '%s' '%s'\n"), menu_row, str_fn, str_fnl);
+	if (menu_item == menu_line)
 	{
-		if (lcdDrawUpdate) menu_draw_item_puts_P(LCD_STR_UPLEVEL[0], str);
-		if (wasClicked && menu_enc_is_at_item())
+		if (lcd_draw_update)
+		{
+//			printf_P(PSTR("menu file %d %d '%s'\n"), menu_row, menuData.sdcard_menu.viewState, str_fnl[0]?str_fnl:str_fn);
+			lcd_set_cursor(0, menu_row);
+/*			if (lcd_encoder == menu_item)
+			{
+				lcd_printf_P(PSTR("%c%-19s"), (lcd_encoder == menu_item)?'>':' ', (str_fnl[0]?str_fnl:str_fn) + 1);
+				if (menuData.sdcard_menu.viewState == 0)
+				{
+					menuData.sdcard_menu.viewState++;
+					lcd_printf_P(PSTR("%c%-19s"), (lcd_encoder == menu_item)?'>':' ', (str_fnl[0]?str_fnl:str_fn) + 1);
+				}
+				else if (menuData.sdcard_menu.viewState == 1)
+				{
+					lcd_printf_P(PSTR("%c%-19s"), (lcd_encoder == menu_item)?'>':' ', (str_fnl[0]?str_fnl:str_fn) + 2);
+				}
+			}
+			else*/
+			{
+				str_fnl[19] = 0;
+				lcd_printf_P(PSTR("%c%-19s"), (lcd_encoder == menu_item)?'>':' ', str_fnl[0]?str_fnl:str_fn);
+			}
+
+//			int cnt = lcd_printf_P(PSTR("%c%-19s"), (lcd_encoder == menu_item)?'>':' ', str_fnl);
+//			int cnt = lcd_printf_P(PSTR("%cTESTIK.gcode"), (lcd_encoder == menu_item)?'>':' ');
+		}
+		if (menu_clicked && (lcd_encoder == menu_item))
 		{
-			MenuStack::Record record = menuStack.pop();
-			lcd_goto_menu(record.menu, false, true);
-			encoderPosition = record.position;
 			return menu_item_ret();
 		}
 	}
-	_menuItemNr++;
+	menu_item++;
 	return 0;
-}
-
-#define MENU_ITEM_FUNCTION_P(str, func) do { if (menu_item_function_P(str, func)) return; } while (0)
-uint8_t menu_item_function_P(const char* str, menuFunc_t func)
-{
-	if (_menuItemNr == _lineNr)
+#else //NEW_SD_MENU
+	if (menu_item == menu_line)
 	{
-		if (lcdDrawUpdate) menu_draw_item_puts_P(' ', str);
-		if (wasClicked && menu_enc_is_at_item())
+		if (lcd_draw_update)
 		{
-			if (func) func();
+			if (lcd_encoder == menu_item)
+				lcd_implementation_drawmenu_sdfile_selected(menu_row, str, str_fn, str_fnl);
+			else
+				lcd_implementation_drawmenu_sdfile(menu_row, str, str_fn, str_fnl);
+		}
+		if (menu_clicked && (lcd_encoder == menu_item))
+		{
+			menu_action_sdfile(str_fn, str_fnl);
 			return menu_item_ret();
 		}
 	}
-	_menuItemNr++;
+	menu_item++;
 	return 0;
+#endif //NEW_SD_MENU
 }
 
-#define MENU_ITEM_GCODE_P(str, str_gcode) do { if (menu_item_gcode_P(str, str_gcode)) return; } while (0)
-uint8_t menu_item_gcode_P(const char* str, const char* str_gcode)
+
+
+
+
+
+
+
+
+/*
+
+20x4   |01234567890123456789|
+       |T 000/000D  Z000.0  |
+       |B 000/000D  F100%   |
+       |SD100%      T--:--  |
+       |Status line.........|
+*/
+static void lcd_implementation_status_screen()
 {
-	if (_menuItemNr == _lineNr)
+   
+    int tHotend=int(degHotend(0) + 0.5);
+    int tTarget=int(degTargetHotend(0) + 0.5);
+
+    //Print the hotend temperature
+    lcd_set_cursor(0, 0);
+    lcd_print(LCD_STR_THERMOMETER[0]);
+    lcd_print(itostr3(tHotend));
+    lcd_print('/');
+    lcd_print(itostr3left(tTarget));
+    lcd_puts_P(PSTR(LCD_STR_DEGREE " "));
+    lcd_puts_P(PSTR("  "));
+
+    //Print the Z coordinates
+    lcd_set_cursor(LCD_WIDTH - 8-2, 0);
+#if 1
+    lcd_puts_P(PSTR("  Z"));
+    if (custom_message_type == 1) {
+        // In a bed calibration mode.
+        lcd_puts_P(PSTR("   --- "));
+    } else {
+        lcd_print(ftostr32sp(current_position[Z_AXIS] + 0.00001));
+        lcd_print(' ');
+    }
+#else
+    lcd_puts_P(PSTR(" Queue:"));
+    lcd_print(int(moves_planned()));
+    lcd_print(' ');
+#endif
+
+    //Print the Bedtemperature
+    lcd_set_cursor(0, 1);
+    tHotend=int(degBed() + 0.5);
+    tTarget=int(degTargetBed() + 0.5);
+    lcd_print(LCD_STR_BEDTEMP[0]);
+    lcd_print(itostr3(tHotend));
+    lcd_print('/');
+    lcd_print(itostr3left(tTarget));
+    lcd_puts_P(PSTR(LCD_STR_DEGREE " "));
+    lcd_puts_P(PSTR("  "));
+
+#ifdef PLANNER_DIAGNOSTICS
+    //Print Feedrate
+    lcd_set_cursor(LCD_WIDTH - 8-2, 1);
+    lcd_print(LCD_STR_FEEDRATE[0]);
+    lcd_print(itostr3(feedmultiply));
+    lcd_puts_P(PSTR("%  Q"));
+    {
+      uint8_t queue = planner_queue_min();
+      if (queue < (BLOCK_BUFFER_SIZE >> 1)) {
+        lcd_putc('!');
+      } else {
+        lcd_putc((char)(queue / 10) + '0');
+        queue %= 10;
+      }
+      lcd_putc((char)queue + '0');
+      planner_queue_min_reset();
+    }
+#else /* PLANNER_DIAGNOSTICS */
+    //Print Feedrate
+    lcd_set_cursor(LCD_WIDTH - 8-2, 1);
+    lcd_puts_P(PSTR("  "));
+    lcd_print(LCD_STR_FEEDRATE[0]);
+    lcd_print(itostr3(feedmultiply));
+    lcd_puts_P(PSTR("%     "));
+#endif /* PLANNER_DIAGNOSTICS */
+
+	bool print_sd_status = true;
+	
+#ifdef PINDA_THERMISTOR
+//	if (farm_mode && (custom_message_type == 4))
+	if (false)
 	{
-		if (lcdDrawUpdate) menu_draw_item_puts_P(' ', str);
-		if (wasClicked && menu_enc_is_at_item())
-		{
-			if (str_gcode) enquecommand_P(str_gcode);
-			return menu_item_ret();
-		}
+		lcd_set_cursor(0, 2);
+		lcd_puts_P(PSTR("P"));
+		lcd_print(ftostr3(current_temperature_pinda));
+		lcd_puts_P(PSTR(LCD_STR_DEGREE " "));
+		print_sd_status = false;
 	}
-	_menuItemNr++;
-	return 0;
-}
+#endif //PINDA_THERMISTOR
 
-//#define MENU_ITEM_SDDIR(str, str_fn, str_fnl) do { if (menu_item_sddir(str, str_fn, str_fnl)) return; } while (0)
-#define MENU_ITEM_SDDIR(str, str_fn, str_fnl) MENU_ITEM(sddirectory, str, str_fn, str_fnl)
-uint8_t menu_item_sddir(const char* str, const char* str_fn, char* str_fnl)
+
+if (print_sd_status)
 {
-//	str_fnl[18] = 0;
-//	printf_P(_N("menu dir %d '%s' '%s'\n"), _drawLineNr, str_fn, str_fnl);
-	if (_menuItemNr == _lineNr)
+    //Print SD status
+    lcd_set_cursor(0, 2);
+	lcd_print_percent_done();
+
+}
+
+	// Farm number display
+	if (farm_mode)
 	{
-		if (lcdDrawUpdate)
-		{
-			lcd.setCursor(0, _drawLineNr);
-			int cnt = lcd_printf_P(_N("%c%c%-18s"), menu_enc_is_at_item()?'>':' ', LCD_STR_FOLDER[0], str_fnl[0]?str_fnl:str_fn);
-//			int cnt = lcd_printf_P(_N("%c%c%-18s"), menu_enc_is_at_item()?'>':' ', LCD_STR_FOLDER[0], str_fn);
-		}
-		if (wasClicked && menu_enc_is_at_item())
+		lcd_set_cursor(6, 2);
+		lcd_puts_P(PSTR(" F"));
+		lcd_print(farm_no);
+		lcd_puts_P(PSTR("  "));
+        
+        // Beat display
+        lcd_set_cursor(LCD_WIDTH - 1, 0);
+        if ( (millis() - kicktime) < 60000 ) {
+        
+            lcd_puts_P(PSTR("L"));
+        
+        }else{
+            lcd_puts_P(PSTR(" "));
+        }
+        
+	}
+	else {
+#ifdef SNMM
+		lcd_puts_P(PSTR(" E"));
+		lcd_print(get_ext_nr() + 1);
+
+#else
+		lcd_set_cursor(LCD_WIDTH - 8 - 2, 2);
+		lcd_puts_P(PSTR(" "));
+#endif
+	}
+
+#ifdef CMD_DIAGNOSTICS
+	lcd_set_cursor(LCD_WIDTH - 8 -1, 2);
+	lcd_puts_P(PSTR("      C"));
+	lcd_print(buflen);	// number of commands in cmd buffer
+	if (buflen < 9) lcd_puts_P(" ");
+#else
+    //Print time
+	lcd_set_cursor(LCD_WIDTH - 8, 2);
+	lcd_print_time();
+#endif //CMD_DIAGNOSTICS
+
+#ifdef DEBUG_DISABLE_LCD_STATUS_LINE
+	return;
+#endif //DEBUG_DISABLE_LCD_STATUS_LINE
+
+    //Print status line
+    lcd_set_cursor(0, 3);
+
+    // If heating in progress, set flag
+	if (heating_status != 0) { custom_message = true; }
+
+	if (IS_SD_PRINTING) {
+		if (strcmp(longFilenameOLD, card.longFilename) != 0)
 		{
-			uint8_t depth = (uint8_t)card.getWorkDirDepth();
-			strcpy(dir_names[depth], str_fn);
-//			printf_P(PSTR("%s\n"), dir_names[depth]);
-			card.chdir(str_fn);
-			encoderPosition = 0;
-			return menu_item_ret();
+			memset(longFilenameOLD, '\0', strlen(longFilenameOLD));
+			sprintf_P(longFilenameOLD, PSTR("%s"), card.longFilename);
+			scrollstuff = 0;
 		}
 	}
-	_menuItemNr++;
-	return 0;
-}
 
-//#define MENU_ITEM_SDFILE(str, str_fn, str_fnl) do { if (menu_item_sdfile(str, str_fn, str_fnl)) return; } while (0)
-#define MENU_ITEM_SDFILE(str, str_fn, str_fnl) MENU_ITEM(sdfile, str, str_fn, str_fnl)
-uint8_t menu_item_sdfile(const char* str, const char* str_fn, char* str_fnl)
-{
-//	printf_P(_N("menu sdfile\n"));
-//	str_fnl[19] = 0;
-//	printf_P(_N("menu file %d '%s' '%s'\n"), _drawLineNr, str_fn, str_fnl);
-	if (_menuItemNr == _lineNr)
+    // If printing from SD, show what we are printing
+	if ((IS_SD_PRINTING) && !custom_message
+#ifdef DEBUG_BUILD
+    && lcd_status_message[0] == 0
+#endif /* DEBUG_BUILD */
+    )
+
+	{
+      if(strlen(card.longFilename) > LCD_WIDTH)
+      {
+
+			  int inters = 0;
+			  int gh = scrollstuff;
+			  while (((gh - scrollstuff) < LCD_WIDTH) && (inters == 0))
+			  {
+
+				  if (card.longFilename[gh] == '\0')
+				  {
+					  lcd_set_cursor(gh - scrollstuff, 3);
+					  lcd_print(card.longFilename[gh - 1]);
+					  scrollstuff = 0;
+					  gh = scrollstuff;
+					  inters = 1;
+				  }
+				  else
+				  {
+					  lcd_set_cursor(gh - scrollstuff, 3);
+					  lcd_print(card.longFilename[gh - 1]);
+					  gh++;
+				  }
+
+
+			  }
+			  scrollstuff++;
+      }
+      else
+      {
+			  lcd_print(longFilenameOLD);
+      }
+	}
+	    
+    // If not, check for other special events
+	else
 	{
-		if (lcdDrawUpdate)
+        
+		if (custom_message)
 		{
-//			printf_P(_N("menu file %d %d '%s'\n"), _drawLineNr, menuData.sdcard_menu.viewState, str_fnl[0]?str_fnl:str_fn);
-			lcd.setCursor(0, _drawLineNr);
-/*			if (menu_enc_is_at_item())
+            // If heating flag, show progress of heating.
+			if (heating_status != 0)
 			{
-				lcd_printf_P(_N("%c%-19s"), menu_enc_is_at_item()?'>':' ', (str_fnl[0]?str_fnl:str_fn) + 1);
-				if (menuData.sdcard_menu.viewState == 0)
+				heating_status_counter++;
+				if (heating_status_counter > 13)
 				{
-					menuData.sdcard_menu.viewState++;
-					lcd_printf_P(_N("%c%-19s"), menu_enc_is_at_item()?'>':' ', (str_fnl[0]?str_fnl:str_fn) + 1);
+					heating_status_counter = 0;
 				}
-				else if (menuData.sdcard_menu.viewState == 1)
+				lcd_set_cursor(7, 3);
+				lcd_puts_P(PSTR("             "));
+
+				for (int dots = 0; dots < heating_status_counter; dots++)
 				{
-					lcd_printf_P(_N("%c%-19s"), menu_enc_is_at_item()?'>':' ', (str_fnl[0]?str_fnl:str_fn) + 2);
+					lcd_set_cursor(7 + dots, 3);
+					lcd_print('.');
+				}
+
+				switch (heating_status)
+				{
+				case 1:
+					lcd_set_cursor(0, 3);
+					lcd_puts_P(_T(MSG_HEATING));
+					break;
+				case 2:
+					lcd_set_cursor(0, 3);
+					lcd_puts_P(_T(MSG_HEATING_COMPLETE));
+					heating_status = 0;
+					heating_status_counter = 0;
+					custom_message = false;
+					break;
+				case 3:
+					lcd_set_cursor(0, 3);
+					lcd_puts_P(_T(MSG_BED_HEATING));
+					break;
+				case 4:
+					lcd_set_cursor(0, 3);
+					lcd_puts_P(_T(MSG_BED_DONE));
+					heating_status = 0;
+					heating_status_counter = 0;
+					custom_message = false;
+					break;
+				default:
+					break;
 				}
 			}
-			else*/
+            
+            // If mesh bed leveling in progress, show the status
+            
+			if (custom_message_type == 1)
 			{
-				str_fnl[19] = 0;
-				lcd_printf_P(_N("%c%-19s"), menu_enc_is_at_item()?'>':' ', str_fnl[0]?str_fnl:str_fn);
+				if (custom_message_state > 10)
+				{
+					lcd_set_cursor(0, 3);
+					lcd_puts_P(PSTR("                    "));
+					lcd_set_cursor(0, 3);
+					lcd_puts_P(_T(MSG_CALIBRATE_Z_AUTO));
+					lcd_puts_P(PSTR(" : "));
+					lcd_print(custom_message_state-10);
+				}
+				else
+				{
+					if (custom_message_state == 3)
+					{
+						lcd_puts_P(_T(WELCOME_MSG));
+						lcd_setstatuspgm(_T(WELCOME_MSG));
+						custom_message = false;
+						custom_message_type = 0;
+					}
+					if (custom_message_state > 3 && custom_message_state <= 10 )
+					{
+						lcd_set_cursor(0, 3);
+						lcd_puts_P(PSTR("                   "));
+						lcd_set_cursor(0, 3);
+						lcd_puts_P(_i("Calibration done"));////MSG_HOMEYZ_DONE c=0 r=0
+						custom_message_state--;
+					}
+				}
+
+			}
+            // If loading filament, print status
+			if (custom_message_type == 2)
+			{
+				lcd_print(lcd_status_message);
+			}
+			// PID tuning in progress
+			if (custom_message_type == 3) {
+				lcd_print(lcd_status_message);
+				if (pid_cycle <= pid_number_of_cycles && custom_message_state > 0) {
+					lcd_set_cursor(10, 3);
+					lcd_print(itostr3(pid_cycle));
+					
+					lcd_print('/');
+					lcd_print(itostr3left(pid_number_of_cycles));
+				}
+			}
+			// PINDA temp calibration in progress
+			if (custom_message_type == 4) {
+				char progress[4];
+				lcd_set_cursor(0, 3);
+				lcd_puts_P(_T(MSG_TEMP_CALIBRATION));
+				lcd_set_cursor(12, 3);
+				sprintf(progress, "%d/6", custom_message_state);
+				lcd_print(progress);
+			}
+			// temp compensation preheat
+			if (custom_message_type == 5) {
+				lcd_set_cursor(0, 3);
+				lcd_puts_P(_i("PINDA Heating"));////MSG_PINDA_PREHEAT c=20 r=1
+				if (custom_message_state <= PINDA_HEAT_T) {
+					lcd_puts_P(PSTR(": "));
+					lcd_print(custom_message_state); //seconds
+					lcd_print(' ');
+					
+				}
 			}
 
-//			int cnt = lcd_printf_P(_N("%c%-19s"), menu_enc_is_at_item()?'>':' ', str_fnl);
-//			int cnt = lcd_printf_P(_N("%cTESTIK.gcode"), menu_enc_is_at_item()?'>':' ');
+
 		}
-		if (wasClicked && menu_enc_is_at_item())
+	else
 		{
-			return menu_item_ret();
+            // Nothing special, print status message normally
+			lcd_print(lcd_status_message);
 		}
 	}
-	_menuItemNr++;
-	return 0;
+    
+    // Fill the rest of line to have nice and clean output
+    for(int fillspace = 0; fillspace<20;fillspace++)
+	{
+      if((lcd_status_message[fillspace] > 31 ))
+	  {
+      }
+	  else
+	  {
+        lcd_print(' ');
+      }
+    }
+	
 }
 
 
@@ -699,37 +958,30 @@ static void lcd_status_screen()
   if (lcd_status_update_delay)
     lcd_status_update_delay--;
   else
-    lcdDrawUpdate = 1;
-  if (lcdDrawUpdate)
+    lcd_draw_update = 1;
+  if (lcd_draw_update)
   {
     ReInitLCD++;
 
 
-    if (ReInitLCD == 30) {
-      lcd_implementation_init( // to maybe revive the LCD if static electricity killed it.
-#if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)
-        currentMenu == lcd_status_screen
-#endif
-      );
+    if (ReInitLCD == 30)
+	{
+      lcd_refresh(); // to maybe revive the LCD if static electricity killed it.
       ReInitLCD = 0 ;
-    } else {
-
-      if ((ReInitLCD % 10) == 0) {
-        //lcd_implementation_nodisplay();
-        lcd_implementation_init_noclear( // to maybe revive the LCD if static electricity killed it.
-#if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)
-          currentMenu == lcd_status_screen
-#endif
-        );
+    }
+	else
+	{
 
+      if ((ReInitLCD % 10) == 0)
+	  {
+        lcd_refresh_noclear(); //to maybe revive the LCD if static electricity killed it.
       }
 
     }
 
 
-    //lcd_implementation_display();
     lcd_implementation_status_screen();
-    //lcd_implementation_clear();
+    //lcd_clear();
 
 	if (farm_mode)
 	{
@@ -764,8 +1016,7 @@ static void lcd_status_screen()
 	}
 	
 
-  } // end of lcdDrawUpdate
-#ifdef ULTIPANEL
+  } // end of lcd_draw_update
 
   bool current_click = LCD_CLICKED;
 
@@ -787,41 +1038,34 @@ static void lcd_status_screen()
 
   if (current_click && (lcd_commands_type != LCD_COMMAND_STOP_PRINT)) //click is aborted unless stop print finishes
   {
-    menuStack.reset(); //redundant, as already done in lcd_return_to_status(), just to be sure
+	menu_depth = 0; //redundant, as already done in lcd_return_to_status(), just to be sure
     menu_submenu(lcd_main_menu);
-    lcd_implementation_init( // to maybe revive the LCD if static electricity killed it.
-#if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)
-      currentMenu == lcd_status_screen
-#endif
-    );
-#ifdef FILAMENT_LCD_DISPLAY
-    message_millis = millis();  // get status message to show up for a while
-#endif
+    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(encoderPosition)) > 100) ||
-      (feedmultiply > 100 && (feedmultiply + int(encoderPosition)) < 100))
+  if ((feedmultiply < 100 && (feedmultiply + int(lcd_encoder)) > 100) ||
+      (feedmultiply > 100 && (feedmultiply + int(lcd_encoder)) < 100))
   {
-    encoderPosition = 0;
+    lcd_encoder = 0;
     feedmultiply = 100;
   }
 
-  if (feedmultiply == 100 && int(encoderPosition) > ENCODER_FEEDRATE_DEADZONE)
+  if (feedmultiply == 100 && int(lcd_encoder) > ENCODER_FEEDRATE_DEADZONE)
   {
-    feedmultiply += int(encoderPosition) - ENCODER_FEEDRATE_DEADZONE;
-    encoderPosition = 0;
+    feedmultiply += int(lcd_encoder) - ENCODER_FEEDRATE_DEADZONE;
+    lcd_encoder = 0;
   }
-  else if (feedmultiply == 100 && int(encoderPosition) < -ENCODER_FEEDRATE_DEADZONE)
+  else if (feedmultiply == 100 && int(lcd_encoder) < -ENCODER_FEEDRATE_DEADZONE)
   {
-    feedmultiply += int(encoderPosition) + ENCODER_FEEDRATE_DEADZONE;
-    encoderPosition = 0;
+    feedmultiply += int(lcd_encoder) + ENCODER_FEEDRATE_DEADZONE;
+    lcd_encoder = 0;
   }
   else if (feedmultiply != 100)
   {
-    feedmultiply += int(encoderPosition);
-    encoderPosition = 0;
+    feedmultiply += int(lcd_encoder);
+    lcd_encoder = 0;
   }
 #endif //ULTIPANEL_FEEDMULTIPLY
 
@@ -829,28 +1073,26 @@ static void lcd_status_screen()
     feedmultiply = 10;
   else if (feedmultiply > 999)
     feedmultiply = 999;
-#endif //ULTIPANEL
 
   /*if (farm_mode && !printer_connected) {
-	  lcd.setCursor(0, 3);
-	  lcd_printPGM(_i("Printer disconnected"));////MSG_PRINTER_DISCONNECTED c=20 r=1
+	  lcd_set_cursor(0, 3);
+	  lcd_puts_P(_i("Printer disconnected"));////MSG_PRINTER_DISCONNECTED c=20 r=1
   }*/
 
 
 //#define FSENS_FACTOR (2580.8/50) //filament sensor factor [steps / encoder counts]
 //#define FSENS_FACTOR (2580.8/45.3) //filament sensor factor [steps / encoder counts]
-  //lcd.setCursor(0, 3);
-  //lcd_implementation_print("                    ");
-  //lcd.setCursor(0, 3);
-  //lcd_implementation_print(pat9125_x);
-  //lcd.setCursor(6, 3);
-  //lcd_implementation_print(pat9125_y);
-  //lcd.setCursor(12, 3);
-  //lcd_implementation_print(pat9125_b);
+  //lcd_set_cursor(0, 3);
+  //lcd_print("                    ");
+  //lcd_set_cursor(0, 3);
+  //lcd_print(pat9125_x);
+  //lcd_set_cursor(6, 3);
+  //lcd_print(pat9125_y);
+  //lcd_set_cursor(12, 3);
+  //lcd_print(pat9125_b);
 
 }
 
-#ifdef ULTIPANEL
 
 void lcd_commands()
 {	
@@ -860,7 +1102,7 @@ void lcd_commands()
 			if (card.sdprinting) {
 				card.pauseSDPrint();
 				lcd_setstatuspgm(_T(MSG_FINISHING_MOVEMENTS));
-				lcdDrawUpdate = 3;
+				lcd_draw_update = 3;
 				lcd_commands_step = 1;
 			}
 			else {
@@ -881,7 +1123,7 @@ void lcd_commands()
 		char cmd1[30];
 		if (lcd_commands_step == 0) {
 
-			lcdDrawUpdate = 3;
+			lcd_draw_update = 3;
 			lcd_commands_step = 4;
 		}
 		if (lcd_commands_step == 1 && !blocks_queued() && cmd_buffer_empty()) {	//recover feedmultiply; cmd_buffer_empty() ensures that card.sdprinting is synchronized with buffered commands and thus print cant be paused until resume is finished
@@ -988,8 +1230,8 @@ void lcd_commands()
 			enquecommand_P(PSTR("M204 S1000"));
 			enquecommand_P(PSTR("G1 F4000"));
 
-			lcd_implementation_clear();
-			lcd_goto_menu(lcd_babystep_z, 0, false);
+			lcd_clear();
+			menu_goto(lcd_babystep_z, 0, false, true);
 
 
 			lcd_commands_step = 8;
@@ -1230,8 +1472,8 @@ void lcd_commands()
 		if (lcd_commands_step == 8 && !blocks_queued() && cmd_buffer_empty())
 		{
 
-			lcd_implementation_clear();
-			menuStack.reset();
+			lcd_clear();
+			menu_depth = 0;
 			menu_submenu(lcd_babystep_z);
 			enquecommand_P(PSTR("G1 X60.0 E9.0 F1000.0")); //intro line
 			enquecommand_P(PSTR("G1 X100.0 E12.5 F1000.0")); //intro line			
@@ -1585,7 +1827,7 @@ void lcd_commands()
 			custom_message_type = 3;
 			custom_message_state = 1;
 			custom_message = true;
-			lcdDrawUpdate = 3;
+			lcd_draw_update = 3;
 			lcd_commands_step = 3;
 		}
 		if (lcd_commands_step == 3 && !blocks_queued()) { //PID calibration
@@ -1634,15 +1876,11 @@ static float count_e(float layer_heigth, float extrusion_width, float extrusion_
 	return extr;
 }
 
-static void lcd_return_to_status() {
-  lcd_implementation_init( // to maybe revive the LCD if static electricity killed it.
-#if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)
-    currentMenu == lcd_status_screen
-#endif
-  );
-
-    lcd_goto_menu(lcd_status_screen, 0, false);
-    menuStack.reset();
+static void lcd_return_to_status()
+{
+	lcd_refresh(); // to maybe revive the LCD if static electricity killed it.
+	menu_goto(lcd_status_screen, 0, false, true);
+	menu_depth = 0;
 }
 
 
@@ -1963,7 +2201,7 @@ static void lcd_preheat_menu()
 
 static void lcd_support_menu()
 {
-    if (menuData.supportMenu.status == 0 || lcdDrawUpdate == 2) {
+    if (menuData.supportMenu.status == 0 || lcd_draw_update == 2) {
         // Menu was entered or SD card status has changed (plugged in or removed).
         // Initialize its status.
         menuData.supportMenu.status = 1;
@@ -2041,12 +2279,10 @@ static void lcd_support_menu()
 void lcd_set_fan_check() {
 	fans_check_enabled = !fans_check_enabled;
 	eeprom_update_byte((unsigned char *)EEPROM_FAN_CHECK_ENABLED, fans_check_enabled);
-	lcd_goto_menu(lcd_settings_menu); //doesn't break menuStack
 }
 
 void lcd_set_filament_autoload() {
-	filament_autoload_enabled = !filament_autoload_enabled;
-	eeprom_update_byte((unsigned char *)EEPROM_FSENS_AUTOLOAD_ENABLED, filament_autoload_enabled);
+     fautoload_set(!filament_autoload_enabled);
 }
 
 void lcd_unLoadFilament()
@@ -2058,14 +2294,14 @@ void lcd_unLoadFilament()
 
   } else {
 
-    lcd_implementation_clear();
-    lcd.setCursor(0, 0);
-    lcd_printPGM(_T(MSG_ERROR));
-    lcd.setCursor(0, 2);
-    lcd_printPGM(_T(MSG_PREHEAT_NOZZLE));
+    lcd_clear();
+    lcd_set_cursor(0, 0);
+    lcd_puts_P(_T(MSG_ERROR));
+    lcd_set_cursor(0, 2);
+    lcd_puts_P(_T(MSG_PREHEAT_NOZZLE));
 
     delay(2000);
-    lcd_implementation_clear();
+    lcd_clear();
   }
 
   menu_back();
@@ -2073,11 +2309,11 @@ void lcd_unLoadFilament()
 
 void lcd_change_filament() {
 
-  lcd_implementation_clear();
+  lcd_clear();
 
-  lcd.setCursor(0, 1);
+  lcd_set_cursor(0, 1);
 
-  lcd_printPGM(_i("Changing filament!"));////MSG_CHANGING_FILAMENT c=20 r=0
+  lcd_puts_P(_i("Changing filament!"));////MSG_CHANGING_FILAMENT c=20 r=0
 
 
 }
@@ -2085,27 +2321,27 @@ void lcd_change_filament() {
 
 void lcd_wait_interact() {
 
-  lcd_implementation_clear();
+  lcd_clear();
 
-  lcd.setCursor(0, 1);
+  lcd_set_cursor(0, 1);
 #ifdef SNMM 
-  lcd_printPGM(_i("Prepare new filament"));////MSG_PREPARE_FILAMENT c=20 r=1
+  lcd_puts_P(_i("Prepare new filament"));////MSG_PREPARE_FILAMENT c=20 r=1
 #else
-  lcd_printPGM(_i("Insert filament"));////MSG_INSERT_FILAMENT c=20 r=0
+  lcd_puts_P(_i("Insert filament"));////MSG_INSERT_FILAMENT c=20 r=0
 #endif
-  lcd.setCursor(0, 2);
-  lcd_printPGM(_i("and press the knob"));////MSG_PRESS c=20 r=0
+  lcd_set_cursor(0, 2);
+  lcd_puts_P(_i("and press the knob"));////MSG_PRESS c=20 r=0
 
 }
 
 
 void lcd_change_success() {
 
-  lcd_implementation_clear();
+  lcd_clear();
 
-  lcd.setCursor(0, 2);
+  lcd_set_cursor(0, 2);
 
-  lcd_printPGM(_i("Change success!"));////MSG_CHANGE_SUCCESS c=0 r=0
+  lcd_puts_P(_i("Change success!"));////MSG_CHANGE_SUCCESS c=0 r=0
 
 
 }
@@ -2113,19 +2349,19 @@ void lcd_change_success() {
 
 void lcd_loading_color() {
 
-  lcd_implementation_clear();
+  lcd_clear();
 
-  lcd.setCursor(0, 0);
+  lcd_set_cursor(0, 0);
 
-  lcd_printPGM(_i("Loading color"));////MSG_LOADING_COLOR c=0 r=0
-  lcd.setCursor(0, 2);
-  lcd_printPGM(_T(MSG_PLEASE_WAIT));
+  lcd_puts_P(_i("Loading color"));////MSG_LOADING_COLOR c=0 r=0
+  lcd_set_cursor(0, 2);
+  lcd_puts_P(_T(MSG_PLEASE_WAIT));
 
 
   for (int i = 0; i < 20; i++) {
 
-    lcd.setCursor(i, 3);
-    lcd.print(".");
+    lcd_set_cursor(i, 3);
+    lcd_print(".");
     for (int j = 0; j < 10 ; j++) {
       manage_heater();
       manage_inactivity(true);
@@ -2142,18 +2378,18 @@ void lcd_loading_color() {
 void lcd_loading_filament() {
 
 
-  lcd_implementation_clear();
+  lcd_clear();
 
-  lcd.setCursor(0, 0);
+  lcd_set_cursor(0, 0);
 
-  lcd_printPGM(_T(MSG_LOADING_FILAMENT));
-  lcd.setCursor(0, 2);
-  lcd_printPGM(_T(MSG_PLEASE_WAIT));
+  lcd_puts_P(_T(MSG_LOADING_FILAMENT));
+  lcd_set_cursor(0, 2);
+  lcd_puts_P(_T(MSG_PLEASE_WAIT));
 
   for (int i = 0; i < 20; i++) {
 
-    lcd.setCursor(i, 3);
-    lcd.print(".");
+    lcd_set_cursor(i, 3);
+    lcd_print(".");
     for (int j = 0; j < 10 ; j++) {
       manage_heater();
       manage_inactivity(true);
@@ -2180,45 +2416,45 @@ void lcd_alright() {
 
 
 
-  lcd_implementation_clear();
+  lcd_clear();
 
-  lcd.setCursor(0, 0);
+  lcd_set_cursor(0, 0);
 
-  lcd_printPGM(_i("Changed correctly?"));////MSG_CORRECTLY c=20 r=0
+  lcd_puts_P(_i("Changed correctly?"));////MSG_CORRECTLY c=20 r=0
 
-  lcd.setCursor(1, 1);
+  lcd_set_cursor(1, 1);
 
-  lcd_printPGM(_T(MSG_YES));
+  lcd_puts_P(_T(MSG_YES));
 
-  lcd.setCursor(1, 2);
+  lcd_set_cursor(1, 2);
 
-  lcd_printPGM(_i("Filament not loaded"));////MSG_NOT_LOADED c=19 r=0
+  lcd_puts_P(_i("Filament not loaded"));////MSG_NOT_LOADED c=19 r=0
 
 
-  lcd.setCursor(1, 3);
-  lcd_printPGM(_i("Color not correct"));////MSG_NOT_COLOR c=0 r=0
+  lcd_set_cursor(1, 3);
+  lcd_puts_P(_i("Color not correct"));////MSG_NOT_COLOR c=0 r=0
 
 
-  lcd.setCursor(0, 1);
+  lcd_set_cursor(0, 1);
 
-  lcd.print(">");
+  lcd_print(">");
 
 
-  enc_dif = encoderDiff;
+  enc_dif = lcd_encoder_diff;
 
   while (lcd_change_fil_state == 0) {
 
     manage_heater();
     manage_inactivity(true);
 
-    if ( abs((enc_dif - encoderDiff)) > 4 ) {
+    if ( abs((enc_dif - lcd_encoder_diff)) > 4 ) {
 
-      if ( (abs(enc_dif - encoderDiff)) > 1 ) {
-        if (enc_dif > encoderDiff ) {
+      if ( (abs(enc_dif - lcd_encoder_diff)) > 1 ) {
+        if (enc_dif > lcd_encoder_diff ) {
           cursor_pos --;
         }
 
-        if (enc_dif < encoderDiff  ) {
+        if (enc_dif < lcd_encoder_diff  ) {
           cursor_pos ++;
         }
 
@@ -2229,15 +2465,15 @@ void lcd_alright() {
         if (cursor_pos < 1) {
           cursor_pos = 1;
         }
-        lcd.setCursor(0, 1);
-        lcd.print(" ");
-        lcd.setCursor(0, 2);
-        lcd.print(" ");
-        lcd.setCursor(0, 3);
-        lcd.print(" ");
-        lcd.setCursor(0, cursor_pos);
-        lcd.print(">");
-        enc_dif = encoderDiff;
+        lcd_set_cursor(0, 1);
+        lcd_print(" ");
+        lcd_set_cursor(0, 2);
+        lcd_print(" ");
+        lcd_set_cursor(0, 3);
+        lcd_print(" ");
+        lcd_set_cursor(0, cursor_pos);
+        lcd_print(">");
+        enc_dif = lcd_encoder_diff;
         delay(100);
       }
 
@@ -2256,7 +2492,7 @@ void lcd_alright() {
   };
 
 
-  lcd_implementation_clear();
+  lcd_clear();
   lcd_return_to_status();
 
 }
@@ -2273,10 +2509,10 @@ static void lcd_menu_AutoLoadFilament()
     {
 		ShortTimer* ptimer = (ShortTimer*)&(menuData.autoLoadFilamentMenu.dummy);
         if (!ptimer->running()) ptimer->start();
-        lcd.setCursor(0, 0);
-        lcd_printPGM(_T(MSG_ERROR));
-        lcd.setCursor(0, 2);
-        lcd_printPGM(_T(MSG_PREHEAT_NOZZLE));
+        lcd_set_cursor(0, 0);
+        lcd_puts_P(_T(MSG_ERROR));
+        lcd_set_cursor(0, 2);
+        lcd_puts_P(_T(MSG_PREHEAT_NOZZLE));
         if (ptimer->expired(2000ul)) menu_back();
     }
     menu_back_if_clicked();
@@ -2296,13 +2532,13 @@ static void lcd_LoadFilament()
   else
   {
 
-    lcd_implementation_clear();
-    lcd.setCursor(0, 0);
-    lcd_printPGM(_T(MSG_ERROR));
-    lcd.setCursor(0, 2);
-    lcd_printPGM(_T(MSG_PREHEAT_NOZZLE));
+    lcd_clear();
+    lcd_set_cursor(0, 0);
+    lcd_puts_P(_T(MSG_ERROR));
+    lcd_set_cursor(0, 2);
+    lcd_puts_P(_T(MSG_PREHEAT_NOZZLE));
     delay(2000);
-    lcd_implementation_clear();
+    lcd_clear();
   }
 }
 
@@ -2310,7 +2546,7 @@ void lcd_menu_statistics()
 {
 	if (IS_SD_PRINTING)
 	{
-		int _met = total_filament_used / 100000;
+		float _met = ((float)total_filament_used) / (100000.f);
 		int _cm = (total_filament_used - (_met * 100000)) / 10;
 		int _t = (millis() - starttime) / 1000;
 		int _h = _t / 3600;
@@ -2325,12 +2561,12 @@ void lcd_menu_statistics()
 		lcd_printf_P(_N(
 		  ESC_2J
 		  "%S:"
-		  ESC_H(6,1) "%8.2f m\n"
+		  ESC_H(6,1) "%8.2fm \n"
 		  "%S :"
 		  ESC_H(8,3) "%2dh %02dm %02d"
 		  ),
 		 _i("Filament used"),
-		 _met, _cm,
+		 _met,
 		 _i("Print time"),
 		 _h, _m, _s
 		);
@@ -2387,19 +2623,19 @@ static void _lcd_move(const char *name, int axis, int min, int max) {
         menuData._lcd_moveMenu.initialized = true;
     }
 
-	if (encoderPosition != 0) {
+	if (lcd_encoder != 0) {
     refresh_cmd_timeout();
     if (! planner_queue_full()) {
-      current_position[axis] += float((int)encoderPosition) * move_menu_scale;
+      current_position[axis] += float((int)lcd_encoder) * move_menu_scale;
       if (min_software_endstops && current_position[axis] < min) current_position[axis] = min;
       if (max_software_endstops && current_position[axis] > max) current_position[axis] = max;
-      encoderPosition = 0;
+      lcd_encoder = 0;
       world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]);
       plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], manual_feedrate[axis] / 60, active_extruder);
-      lcdDrawUpdate = 1;
+      lcd_draw_update = 1;
     }
   }
-  if (lcdDrawUpdate) lcd_implementation_drawedit(name, ftostr31(current_position[axis]));
+  if (lcd_draw_update) lcd_drawedit(name, ftostr31(current_position[axis]));
   if (menuExiting || LCD_CLICKED) (void)enable_endstops(menuData._lcd_moveMenu.endstopsEnabledPrevious);
   if (LCD_CLICKED) menu_back();
 }
@@ -2408,28 +2644,28 @@ static void _lcd_move(const char *name, int axis, int min, int max) {
 static void lcd_move_e()
 {
 	if (degHotend0() > EXTRUDE_MINTEMP) {
-  if (encoderPosition != 0)
+  if (lcd_encoder != 0)
   {
     refresh_cmd_timeout();
     if (! planner_queue_full()) {
-      current_position[E_AXIS] += float((int)encoderPosition) * move_menu_scale;
-      encoderPosition = 0;
+      current_position[E_AXIS] += float((int)lcd_encoder) * move_menu_scale;
+      lcd_encoder = 0;
       plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], manual_feedrate[E_AXIS] / 60, active_extruder);
-      lcdDrawUpdate = 1;
+      lcd_draw_update = 1;
     }
   }
-  if (lcdDrawUpdate)
+  if (lcd_draw_update)
   {
-    lcd_implementation_drawedit(PSTR("Extruder"), ftostr31(current_position[E_AXIS]));
+    lcd_drawedit(PSTR("Extruder"), ftostr31(current_position[E_AXIS]));
   }
   if (LCD_CLICKED) menu_back();
 }
 	else {
-		lcd_implementation_clear();
-		lcd.setCursor(0, 0);
-		lcd_printPGM(_T(MSG_ERROR));
-		lcd.setCursor(0, 2);
-		lcd_printPGM(_T(MSG_PREHEAT_NOZZLE));
+		lcd_clear();
+		lcd_set_cursor(0, 0);
+		lcd_puts_P(_T(MSG_ERROR));
+		lcd_set_cursor(0, 2);
+		lcd_puts_P(_T(MSG_PREHEAT_NOZZLE));
 
 		delay(2000);
 		lcd_return_to_status();
@@ -2465,12 +2701,12 @@ static void lcd_menu_xyz_y_min()
 	);
 	for (uint8_t i = 0; i < 2; i++)
 	{
-		lcd.setCursor(11,2+i);
+		lcd_set_cursor(11,2+i);
 		if (distanceMin[i] >= 200) lcd_puts_P(_N("N/A"));
 		else lcd_printf_P(_N("%6.2fmm"), distanceMin[i]);
 	}
     if (lcd_clicked())
-        lcd_goto_menu(lcd_menu_xyz_skew);
+        menu_goto(lcd_menu_xyz_skew, 0, true, true);
 }
 /**
  * @brief Show measured axis skewness
@@ -2506,18 +2742,18 @@ static void lcd_menu_xyz_skew()
 	else
 		lcd_puts_P(_N(ESC_H(15,0)"N/A"));
     if (lcd_clicked())
-        lcd_goto_menu(lcd_menu_xyz_offset);
+        menu_goto(lcd_menu_xyz_offset, 0, true, true);
 }
 /**
  * @brief Show measured bed offset from expected position
  */
 static void lcd_menu_xyz_offset()
 {
-    lcd.setCursor(0,0);
-    lcd_printPGM(_i("[0;0] point offset"));////MSG_MEASURED_OFFSET c=0 r=0
-    lcd_print_at_PGM(0, 1, separator);
-    lcd_print_at_PGM(0, 2, PSTR("X"));
-    lcd_print_at_PGM(0, 3, PSTR("Y"));
+    lcd_set_cursor(0,0);
+    lcd_puts_P(_i("[0;0] point offset"));////MSG_MEASURED_OFFSET c=0 r=0
+    lcd_puts_at_P(0, 1, separator);
+    lcd_puts_at_P(0, 2, PSTR("X"));
+    lcd_puts_at_P(0, 3, PSTR("Y"));
 
     float vec_x[2];
     float vec_y[2];
@@ -2526,9 +2762,9 @@ static void lcd_menu_xyz_offset()
 
     for (int i = 0; i < 2; i++)
     {
-        lcd_print_at_PGM(11, i + 2, PSTR(""));
-        lcd.print(cntr[i]);
-        lcd_print_at_PGM((cntr[i] < 0) ? 17 : 16, i + 2, PSTR("mm"));
+        lcd_puts_at_P(11, i + 2, PSTR(""));
+        lcd_print(cntr[i]);
+        lcd_puts_at_P((cntr[i] < 0) ? 17 : 16, i + 2, PSTR("mm"));
     }
     menu_back_if_clicked();
 }
@@ -2536,20 +2772,14 @@ static void lcd_menu_xyz_offset()
 // Save a single axis babystep value.
 void EEPROM_save_B(int pos, int* value)
 {
-  union Data data;
-  data.value = *value;
-
-  eeprom_update_byte((unsigned char*)pos, data.b[0]);
-  eeprom_update_byte((unsigned char*)pos + 1, data.b[1]);
+  eeprom_update_byte((unsigned char*)pos, (unsigned char)((*value) & 0xff));
+  eeprom_update_byte((unsigned char*)pos + 1, (unsigned char)((*value) >> 8));
 }
 
 // Read a single axis babystep value.
 void EEPROM_read_B(int pos, int* value)
 {
-  union Data data;
-  data.b[0] = eeprom_read_byte((unsigned char*)pos);
-  data.b[1] = eeprom_read_byte((unsigned char*)pos + 1);
-  *value = data.value;
+  *value = (int)eeprom_read_byte((unsigned char*)pos) | (int)(eeprom_read_byte((unsigned char*)pos + 1) << 8);
 }
 
 
@@ -2590,34 +2820,34 @@ static void _lcd_babystep(int axis, const char *msg)
         menuData.babyStep.babystepMemMM[0] = menuData.babyStep.babystepMem[0]/axis_steps_per_unit[X_AXIS];
         menuData.babyStep.babystepMemMM[1] = menuData.babyStep.babystepMem[1]/axis_steps_per_unit[Y_AXIS];
         menuData.babyStep.babystepMemMM[2] = menuData.babyStep.babystepMem[2]/axis_steps_per_unit[Z_AXIS];
-        lcdDrawUpdate = 1;
+        lcd_draw_update = 1;
 		//SERIAL_ECHO("Z baby step: ");
 		//SERIAL_ECHO(menuData.babyStep.babystepMem[2]);
         // Wait 90 seconds before closing the live adjust dialog.
         lcd_timeoutToStatus = millis() + 90000;
     }
 
-  if (encoderPosition != 0) 
+  if (lcd_encoder != 0) 
   {
-	if (homing_flag) encoderPosition = 0;
+	if (homing_flag) lcd_encoder = 0;
 
-    menuData.babyStep.babystepMem[axis] += (int)encoderPosition;
+    menuData.babyStep.babystepMem[axis] += (int)lcd_encoder;
 	if (axis == 2) {
 		if (menuData.babyStep.babystepMem[axis] < Z_BABYSTEP_MIN) menuData.babyStep.babystepMem[axis] = Z_BABYSTEP_MIN; //-3999 -> -9.99 mm
 		else  if (menuData.babyStep.babystepMem[axis] > Z_BABYSTEP_MAX) menuData.babyStep.babystepMem[axis] = Z_BABYSTEP_MAX; //0
 		else {
 			CRITICAL_SECTION_START
-				babystepsTodo[axis] += (int)encoderPosition;
+				babystepsTodo[axis] += (int)lcd_encoder;
 			CRITICAL_SECTION_END		
 		}
 	}
     menuData.babyStep.babystepMemMM[axis] = menuData.babyStep.babystepMem[axis]/axis_steps_per_unit[axis]; 
 	  delay(50);
-	  encoderPosition = 0;
-    lcdDrawUpdate = 1;
+	  lcd_encoder = 0;
+    lcd_draw_update = 1;
   }
-  if (lcdDrawUpdate)
-    lcd_implementation_drawedit_2(msg, ftostr13ns(menuData.babyStep.babystepMemMM[axis]));
+  if (lcd_draw_update)
+    lcd_drawedit_2(msg, ftostr13ns(menuData.babyStep.babystepMemMM[axis]));
   if (LCD_CLICKED || menuExiting) {
     // Only update the EEPROM when leaving the menu.
     EEPROM_save_B(
@@ -2641,14 +2871,6 @@ static void lcd_babystep_z() {
 
 static void lcd_adjust_bed();
 
-/**
- * @brief adjust bed reset menu item function
- *
- * To be used as MENU_ITEM(function,...) inside lcd_adjust_bed submenu. In such case lcd_goto_menu usage
- * is correct and doesn't break menuStack.
- * Because we did not leave the menu, the menuData did not reset.
- * Force refresh of the bed leveling data.
- */
 static void lcd_adjust_bed_reset()
 {
     eeprom_update_byte((unsigned char*)EEPROM_BED_CORRECTION_VALID, 1);
@@ -2656,7 +2878,6 @@ static void lcd_adjust_bed_reset()
     eeprom_update_byte((unsigned char*)EEPROM_BED_CORRECTION_RIGHT, 0);
     eeprom_update_byte((unsigned char*)EEPROM_BED_CORRECTION_FRONT, 0);
     eeprom_update_byte((unsigned char*)EEPROM_BED_CORRECTION_REAR , 0);
-    lcd_goto_menu(lcd_adjust_bed, 0, false); //doesn't break menuStack
     menuData.adjustBed.status = 0;
 }
 
@@ -2697,7 +2918,7 @@ static void lcd_adjust_bed()
             menuData.adjustBed.front2 = 0;
             menuData.adjustBed.rear2  = 0;
         }
-        lcdDrawUpdate = 1;
+        lcd_draw_update = 1;
         eeprom_update_byte((unsigned char*)EEPROM_BED_CORRECTION_VALID, 1);
     }
 
@@ -2712,25 +2933,25 @@ static void lcd_adjust_bed()
 
     MENU_BEGIN();
     MENU_ITEM_BACK_P(_T(MSG_SETTINGS));
-    MENU_ITEM_EDIT(int3, _i("Left side [um]"),  &menuData.adjustBed.left2,  -BED_ADJUSTMENT_UM_MAX, BED_ADJUSTMENT_UM_MAX);////MSG_BED_CORRECTION_LEFT c=14 r=1
-    MENU_ITEM_EDIT(int3, _i("Right side[um]"), &menuData.adjustBed.right2, -BED_ADJUSTMENT_UM_MAX, BED_ADJUSTMENT_UM_MAX);////MSG_BED_CORRECTION_RIGHT c=14 r=1
-    MENU_ITEM_EDIT(int3, _i("Front side[um]"), &menuData.adjustBed.front2, -BED_ADJUSTMENT_UM_MAX, BED_ADJUSTMENT_UM_MAX);////MSG_BED_CORRECTION_FRONT c=14 r=1
-    MENU_ITEM_EDIT(int3, _i("Rear side [um]"),  &menuData.adjustBed.rear2,  -BED_ADJUSTMENT_UM_MAX, BED_ADJUSTMENT_UM_MAX);////MSG_BED_CORRECTION_REAR c=14 r=1
+    MENU_ITEM_EDIT_int3_P(_i("Left side [um]"),  &menuData.adjustBed.left2,  -BED_ADJUSTMENT_UM_MAX, BED_ADJUSTMENT_UM_MAX);////MSG_BED_CORRECTION_LEFT c=14 r=1
+    MENU_ITEM_EDIT_int3_P(_i("Right side[um]"), &menuData.adjustBed.right2, -BED_ADJUSTMENT_UM_MAX, BED_ADJUSTMENT_UM_MAX);////MSG_BED_CORRECTION_RIGHT c=14 r=1
+    MENU_ITEM_EDIT_int3_P(_i("Front side[um]"), &menuData.adjustBed.front2, -BED_ADJUSTMENT_UM_MAX, BED_ADJUSTMENT_UM_MAX);////MSG_BED_CORRECTION_FRONT c=14 r=1
+    MENU_ITEM_EDIT_int3_P(_i("Rear side [um]"),  &menuData.adjustBed.rear2,  -BED_ADJUSTMENT_UM_MAX, BED_ADJUSTMENT_UM_MAX);////MSG_BED_CORRECTION_REAR c=14 r=1
     MENU_ITEM_FUNCTION_P(_i("Reset"), lcd_adjust_bed_reset);////MSG_BED_CORRECTION_RESET c=0 r=0
     MENU_END();
 }
 
 void pid_extruder() {
 
-	lcd_implementation_clear();
-	lcd.setCursor(1, 0);
-	lcd_printPGM(_i("Set temperature:"));////MSG_SET_TEMPERATURE c=19 r=1
-	pid_temp += int(encoderPosition);
+	lcd_clear();
+	lcd_set_cursor(1, 0);
+	lcd_puts_P(_i("Set temperature:"));////MSG_SET_TEMPERATURE c=19 r=1
+	pid_temp += int(lcd_encoder);
 	if (pid_temp > HEATER_0_MAXTEMP) pid_temp = HEATER_0_MAXTEMP;
 	if (pid_temp < HEATER_0_MINTEMP) pid_temp = HEATER_0_MINTEMP;
-	encoderPosition = 0;
-	lcd.setCursor(1, 2);
-	lcd.print(ftostr3(pid_temp));
+	lcd_encoder = 0;
+	lcd_set_cursor(1, 2);
+	lcd_print(ftostr3(pid_temp));
 	if (lcd_clicked()) {
 		lcd_commands_type = LCD_COMMAND_PID_EXTRUDER;
 		lcd_return_to_status();
@@ -2747,36 +2968,36 @@ void lcd_adjust_z() {
 
 
 
-  lcd_implementation_clear();
-  lcd.setCursor(0, 0);
-  lcd_printPGM(_i("Auto adjust Z?"));////MSG_ADJUSTZ c=0 r=0
-  lcd.setCursor(1, 1);
-  lcd_printPGM(_T(MSG_YES));
+  lcd_clear();
+  lcd_set_cursor(0, 0);
+  lcd_puts_P(_i("Auto adjust Z?"));////MSG_ADJUSTZ c=0 r=0
+  lcd_set_cursor(1, 1);
+  lcd_puts_P(_T(MSG_YES));
 
-  lcd.setCursor(1, 2);
+  lcd_set_cursor(1, 2);
 
-  lcd_printPGM(_T(MSG_NO));
+  lcd_puts_P(_T(MSG_NO));
 
-  lcd.setCursor(0, 1);
+  lcd_set_cursor(0, 1);
 
-  lcd.print(">");
+  lcd_print(">");
 
 
-  enc_dif = encoderDiff;
+  enc_dif = lcd_encoder_diff;
 
   while (fsm == 0) {
 
     manage_heater();
     manage_inactivity(true);
 
-    if ( abs((enc_dif - encoderDiff)) > 4 ) {
+    if ( abs((enc_dif - lcd_encoder_diff)) > 4 ) {
 
-      if ( (abs(enc_dif - encoderDiff)) > 1 ) {
-        if (enc_dif > encoderDiff ) {
+      if ( (abs(enc_dif - lcd_encoder_diff)) > 1 ) {
+        if (enc_dif > lcd_encoder_diff ) {
           cursor_pos --;
         }
 
-        if (enc_dif < encoderDiff  ) {
+        if (enc_dif < lcd_encoder_diff  ) {
           cursor_pos ++;
         }
 
@@ -2787,13 +3008,13 @@ void lcd_adjust_z() {
         if (cursor_pos < 1) {
           cursor_pos = 1;
         }
-        lcd.setCursor(0, 1);
-        lcd.print(" ");
-        lcd.setCursor(0, 2);
-        lcd.print(" ");
-        lcd.setCursor(0, cursor_pos);
-        lcd.print(">");
-        enc_dif = encoderDiff;
+        lcd_set_cursor(0, 1);
+        lcd_print(" ");
+        lcd_set_cursor(0, 2);
+        lcd_print(" ");
+        lcd_set_cursor(0, cursor_pos);
+        lcd_print(">");
+        enc_dif = lcd_encoder_diff;
         delay(100);
       }
 
@@ -2818,7 +3039,7 @@ void lcd_adjust_z() {
     }
   };
 
-  lcd_implementation_clear();
+  lcd_clear();
   lcd_return_to_status();
 
 }
@@ -2834,12 +3055,12 @@ bool lcd_wait_for_pinda(float temp) {
 	while (current_temperature_pinda > temp){
 		lcd_display_message_fullscreen_P(_i("Waiting for PINDA probe cooling"));////MSG_WAITING_TEMP_PINDA c=20 r=3
 
-		lcd.setCursor(0, 4);
-		lcd.print(LCD_STR_THERMOMETER[0]);
-		lcd.print(ftostr3(current_temperature_pinda));
-		lcd.print("/");
-		lcd.print(ftostr3(temp));
-		lcd.print(LCD_STR_DEGREE);
+		lcd_set_cursor(0, 4);
+		lcd_print(LCD_STR_THERMOMETER[0]);
+		lcd_print(ftostr3(current_temperature_pinda));
+		lcd_print("/");
+		lcd_print(ftostr3(temp));
+		lcd_print(LCD_STR_DEGREE);
 		delay_keep_alive(1000);
 		serialecho_temperatures();
 		if (pinda_timeout.expired(8 * 60 * 1000ul)) { //PINDA cooling from 60 C to 35 C takes about 7 minutes
@@ -2855,12 +3076,12 @@ bool lcd_wait_for_pinda(float temp) {
 void lcd_wait_for_heater() {
 	lcd_display_message_fullscreen_P(_T(MSG_WIZARD_HEATING));
 
-		lcd.setCursor(0, 4);
-		lcd.print(LCD_STR_THERMOMETER[0]);
-		lcd.print(ftostr3(degHotend(active_extruder)));
-		lcd.print("/");
-		lcd.print(ftostr3(degTargetHotend(active_extruder)));
-		lcd.print(LCD_STR_DEGREE);
+		lcd_set_cursor(0, 4);
+		lcd_print(LCD_STR_THERMOMETER[0]);
+		lcd_print(ftostr3(degHotend(active_extruder)));
+		lcd_print("/");
+		lcd_print(ftostr3(degTargetHotend(active_extruder)));
+		lcd_print(LCD_STR_DEGREE);
 }
 
 void lcd_wait_for_cool_down() {
@@ -2870,17 +3091,17 @@ void lcd_wait_for_cool_down() {
 	while ((degHotend(0)>MAX_HOTEND_TEMP_CALIBRATION) || (degBed() > MAX_BED_TEMP_CALIBRATION)) {
 		lcd_display_message_fullscreen_P(_i("Waiting for nozzle and bed cooling"));////MSG_WAITING_TEMP c=20 r=3
 
-		lcd.setCursor(0, 4);
-		lcd.print(LCD_STR_THERMOMETER[0]);
-		lcd.print(ftostr3(degHotend(0)));
-		lcd.print("/0");		
-		lcd.print(LCD_STR_DEGREE);
-
-		lcd.setCursor(9, 4);
-		lcd.print(LCD_STR_BEDTEMP[0]);
-		lcd.print(ftostr3(degBed()));
-		lcd.print("/0");		
-		lcd.print(LCD_STR_DEGREE);
+		lcd_set_cursor(0, 4);
+		lcd_print(LCD_STR_THERMOMETER[0]);
+		lcd_print(ftostr3(degHotend(0)));
+		lcd_print("/0");		
+		lcd_print(LCD_STR_DEGREE);
+
+		lcd_set_cursor(9, 4);
+		lcd_print(LCD_STR_BEDTEMP[0]);
+		lcd_print(ftostr3(degBed()));
+		lcd_print("/0");		
+		lcd_print(LCD_STR_DEGREE);
 		lcd_set_custom_characters();
 		delay_keep_alive(1000);
 		serialecho_temperatures();
@@ -2910,22 +3131,22 @@ bool lcd_calibrate_z_end_stop_manual(bool only_z)
         const bool    multi_screen        = msg_next != NULL;
         unsigned long previous_millis_msg = millis();
         // Until the user finishes the z up movement.
-        encoderDiff = 0;
-        encoderPosition = 0;
+        lcd_encoder_diff = 0;
+        lcd_encoder = 0;
         for (;;) {
 //          if (millis() - previous_millis_cmd > LCD_TIMEOUT_TO_STATUS)
 //             goto canceled;
             manage_heater();
             manage_inactivity(true);
-            if (abs(encoderDiff) >= ENCODER_PULSES_PER_STEP) {
+            if (abs(lcd_encoder_diff) >= ENCODER_PULSES_PER_STEP) {
                 delay(50);
                 previous_millis_cmd = millis();
-                encoderPosition += abs(encoderDiff / ENCODER_PULSES_PER_STEP);
-                encoderDiff = 0;
+                lcd_encoder += abs(lcd_encoder_diff / ENCODER_PULSES_PER_STEP);
+                lcd_encoder_diff = 0;
                 if (! planner_queue_full()) {
                     // Only move up, whatever direction the user rotates the encoder.
-                    current_position[Z_AXIS] += fabs(encoderPosition);
-                    encoderPosition = 0;
+                    current_position[Z_AXIS] += fabs(lcd_encoder);
+                    lcd_encoder = 0;
                     plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], manual_feedrate[Z_AXIS] / 60, active_extruder);
                 }
             }
@@ -2969,13 +3190,15 @@ calibrated:
     
     if(only_z){
         lcd_display_message_fullscreen_P(_T(MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE1));
-        lcd_implementation_print_at(0, 3, 1);
-        lcd_printPGM(_T(MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2));
+        lcd_set_cursor(0, 3);
+        lcd_print(1);
+        lcd_puts_P(_T(MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2));
     }else{
 		//lcd_show_fullscreen_message_and_wait_P(_T(MSG_PAPER));
         lcd_display_message_fullscreen_P(_T(MSG_FIND_BED_OFFSET_AND_SKEW_LINE1));
-        lcd_implementation_print_at(0, 2, 1);
-        lcd_printPGM(_T(MSG_FIND_BED_OFFSET_AND_SKEW_LINE2));
+        lcd_set_cursor(0, 2);
+        lcd_print(1);
+        lcd_puts_P(_T(MSG_FIND_BED_OFFSET_AND_SKEW_LINE2));
     }
     
     
@@ -3009,7 +3232,7 @@ static inline bool pgm_is_interpunction(const char *c_addr)
  */
 static const char* lcd_display_message_fullscreen_nonBlocking_P(const char *msg, uint8_t &nlines)
 {
-    lcd.setCursor(0, 0);
+    lcd_set_cursor(0, 0);
     const char *msgend = msg;
     uint8_t row = 0;
     bool multi_screen = false;
@@ -3019,7 +3242,7 @@ static const char* lcd_display_message_fullscreen_nonBlocking_P(const char *msg,
         if (pgm_read_byte(msg) == 0)
             // End of the message.
             break;
-        lcd.setCursor(0, row);
+        lcd_set_cursor(0, row);
         uint8_t linelen = min(strlen_P(msg), 20);
         const char *msgend2 = msg + linelen;
         msgend = msgend2;
@@ -3044,7 +3267,7 @@ static const char* lcd_display_message_fullscreen_nonBlocking_P(const char *msg,
             char c = char(pgm_read_byte(msg));
             if (c == '~')
                 c = ' ';
-            lcd.print(c);
+            lcd_print(c);
         }
     }
 
@@ -3052,9 +3275,9 @@ static const char* lcd_display_message_fullscreen_nonBlocking_P(const char *msg,
         // Display the "next screen" indicator character.
         // lcd_set_custom_characters_arrows();
         lcd_set_custom_characters_nextpage();
-        lcd.setCursor(19, 3);
+        lcd_set_cursor(19, 3);
         // Display the down arrow.
-        lcd.print(char(1));
+        lcd_print(char(1));
     }
 
     nlines = row;
@@ -3063,9 +3286,9 @@ static const char* lcd_display_message_fullscreen_nonBlocking_P(const char *msg,
 
 const char* lcd_display_message_fullscreen_P(const char *msg, uint8_t &nlines)
 {
-    // Disable update of the screen by the usual lcd_update() routine.
+    // Disable update of the screen by the usual lcd_update(0) routine.
     lcd_update_enable(false);
-    lcd_implementation_clear();
+    lcd_clear();
     return lcd_display_message_fullscreen_nonBlocking_P(msg, nlines);
 }
 
@@ -3085,9 +3308,9 @@ void lcd_show_fullscreen_message_and_wait_P(const char *msg)
 	// Until confirmed by a button click.
 	for (;;) {
 		if (!multi_screen) {
-			lcd.setCursor(19, 3);
+			lcd_set_cursor(19, 3);
 			// Display the confirm char.
-			lcd.print(char(2));
+			lcd_print(char(2));
 		}
         // Wait for 5 seconds before displaying the next text.
         for (uint8_t i = 0; i < 100; ++ i) {
@@ -3114,9 +3337,9 @@ void lcd_show_fullscreen_message_and_wait_P(const char *msg)
             msg_next = lcd_display_message_fullscreen_P(msg_next);
 			if (msg_next == NULL) {
 
-				lcd.setCursor(19, 3);
+				lcd_set_cursor(19, 3);
 				// Display the confirm char.
-				lcd.print(char(2));
+				lcd_print(char(2));
 			}
         }
     }
@@ -3146,7 +3369,7 @@ int8_t lcd_show_multiscreen_message_yes_no_and_wait_P(const char *msg, bool allo
 
 	// Wait for user confirmation or a timeout.
 	unsigned long previous_millis_cmd = millis();
-	int8_t        enc_dif = encoderDiff;
+	int8_t        enc_dif = lcd_encoder_diff;
 	//KEEPALIVE_STATE(PAUSED_FOR_USER);
 	for (;;) {
 		for (uint8_t i = 0; i < 100; ++i) {
@@ -3156,22 +3379,22 @@ int8_t lcd_show_multiscreen_message_yes_no_and_wait_P(const char *msg, bool allo
 			manage_heater();
 			manage_inactivity(true);
 
-			if (abs(enc_dif - encoderDiff) > 4) {
+			if (abs(enc_dif - lcd_encoder_diff) > 4) {
 				if (msg_next == NULL) {
-					lcd.setCursor(0, 3);
-					if (enc_dif < encoderDiff && yes) {
-						lcd_printPGM((PSTR(" ")));
-						lcd.setCursor(7, 3);
-						lcd_printPGM((PSTR(">")));
+					lcd_set_cursor(0, 3);
+					if (enc_dif < lcd_encoder_diff && yes) {
+						lcd_puts_P((PSTR(" ")));
+						lcd_set_cursor(7, 3);
+						lcd_puts_P((PSTR(">")));
 						yes = false;
 					}
-					else if (enc_dif > encoderDiff && !yes) {
-						lcd_printPGM((PSTR(">")));
-						lcd.setCursor(7, 3);
-						lcd_printPGM((PSTR(" ")));
+					else if (enc_dif > lcd_encoder_diff && !yes) {
+						lcd_puts_P((PSTR(">")));
+						lcd_set_cursor(7, 3);
+						lcd_puts_P((PSTR(" ")));
 						yes = true;
 					}
-					enc_dif = encoderDiff;
+					enc_dif = lcd_encoder_diff;
 				}
 				else {
 					break; //turning knob skips waiting loop
@@ -3196,14 +3419,14 @@ int8_t lcd_show_multiscreen_message_yes_no_and_wait_P(const char *msg, bool allo
 			msg_next = lcd_display_message_fullscreen_P(msg_next);
 		}
 		if (msg_next == NULL) {
-			lcd.setCursor(0, 3);
-			if (yes) lcd_printPGM(PSTR(">"));
-			lcd.setCursor(1, 3);
-			lcd_printPGM(_T(MSG_YES));
-			lcd.setCursor(7, 3);
-			if (!yes) lcd_printPGM(PSTR(">"));
-			lcd.setCursor(8, 3);
-			lcd_printPGM(_T(MSG_NO));
+			lcd_set_cursor(0, 3);
+			if (yes) lcd_puts_P(PSTR(">"));
+			lcd_set_cursor(1, 3);
+			lcd_puts_P(_T(MSG_YES));
+			lcd_set_cursor(7, 3);
+			if (!yes) lcd_puts_P(PSTR(">"));
+			lcd_set_cursor(8, 3);
+			lcd_puts_P(_T(MSG_NO));
 		}
 	}
 }
@@ -3214,45 +3437,45 @@ int8_t lcd_show_fullscreen_message_yes_no_and_wait_P(const char *msg, bool allow
 	lcd_display_message_fullscreen_P(msg);
 	
 	if (default_yes) {
-		lcd.setCursor(0, 2);
-		lcd_printPGM(PSTR(">"));
-		lcd_printPGM(_T(MSG_YES));
-		lcd.setCursor(1, 3);
-		lcd_printPGM(_T(MSG_NO));
+		lcd_set_cursor(0, 2);
+		lcd_puts_P(PSTR(">"));
+		lcd_puts_P(_T(MSG_YES));
+		lcd_set_cursor(1, 3);
+		lcd_puts_P(_T(MSG_NO));
 	}
 	else {
-		lcd.setCursor(1, 2);
-		lcd_printPGM(_T(MSG_YES));
-		lcd.setCursor(0, 3);
-		lcd_printPGM(PSTR(">"));
-		lcd_printPGM(_T(MSG_NO));
+		lcd_set_cursor(1, 2);
+		lcd_puts_P(_T(MSG_YES));
+		lcd_set_cursor(0, 3);
+		lcd_puts_P(PSTR(">"));
+		lcd_puts_P(_T(MSG_NO));
 	}
 	bool yes = default_yes ? true : false;
 
 	// Wait for user confirmation or a timeout.
 	unsigned long previous_millis_cmd = millis();
-	int8_t        enc_dif = encoderDiff;
+	int8_t        enc_dif = lcd_encoder_diff;
 	KEEPALIVE_STATE(PAUSED_FOR_USER);
 	for (;;) {
 		if (allow_timeouting && millis() - previous_millis_cmd > LCD_TIMEOUT_TO_STATUS)
 			return -1;
 		manage_heater();
 		manage_inactivity(true);
-		if (abs(enc_dif - encoderDiff) > 4) {
-			lcd.setCursor(0, 2);
-				if (enc_dif < encoderDiff && yes) {
-					lcd_printPGM((PSTR(" ")));
-					lcd.setCursor(0, 3);
-					lcd_printPGM((PSTR(">")));
+		if (abs(enc_dif - lcd_encoder_diff) > 4) {
+			lcd_set_cursor(0, 2);
+				if (enc_dif < lcd_encoder_diff && yes) {
+					lcd_puts_P((PSTR(" ")));
+					lcd_set_cursor(0, 3);
+					lcd_puts_P((PSTR(">")));
 					yes = false;
 				}
-				else if (enc_dif > encoderDiff && !yes) {
-					lcd_printPGM((PSTR(">")));
-					lcd.setCursor(0, 3);
-					lcd_printPGM((PSTR(" ")));
+				else if (enc_dif > lcd_encoder_diff && !yes) {
+					lcd_puts_P((PSTR(">")));
+					lcd_set_cursor(0, 3);
+					lcd_puts_P((PSTR(" ")));
 					yes = true;
 				}
-				enc_dif = encoderDiff;
+				enc_dif = lcd_encoder_diff;
 		}
 		if (lcd_clicked()) {
 			while (lcd_clicked());
@@ -3264,7 +3487,7 @@ int8_t lcd_show_fullscreen_message_yes_no_and_wait_P(const char *msg, bool allow
 	}
 }
 
-void lcd_bed_calibration_show_result(BedSkewOffsetDetectionResultType result, uint8_t point_too_far_mask)
+void lcd_bed_calibration_show_result(uint8_t result, uint8_t point_too_far_mask)
 {
     const char *msg = NULL;
     if (result == BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND) {
@@ -3347,14 +3570,14 @@ void lcd_temp_cal_show_result(bool result) {
 }
 
 static void lcd_show_end_stops() {
-	lcd.setCursor(0, 0);
-	lcd_printPGM((PSTR("End stops diag")));
-	lcd.setCursor(0, 1);
-	lcd_printPGM((READ(X_MIN_PIN) ^ X_MIN_ENDSTOP_INVERTING == 1) ? (PSTR("X1")) : (PSTR("X0")));
-	lcd.setCursor(0, 2);
-	lcd_printPGM((READ(Y_MIN_PIN) ^ Y_MIN_ENDSTOP_INVERTING == 1) ? (PSTR("Y1")) : (PSTR("Y0")));
-	lcd.setCursor(0, 3);
-	lcd_printPGM((READ(Z_MIN_PIN) ^ Z_MIN_ENDSTOP_INVERTING == 1) ? (PSTR("Z1")) : (PSTR("Z0")));
+	lcd_set_cursor(0, 0);
+	lcd_puts_P((PSTR("End stops diag")));
+	lcd_set_cursor(0, 1);
+	lcd_puts_P((READ(X_MIN_PIN) ^ X_MIN_ENDSTOP_INVERTING == 1) ? (PSTR("X1")) : (PSTR("X0")));
+	lcd_set_cursor(0, 2);
+	lcd_puts_P((READ(Y_MIN_PIN) ^ Y_MIN_ENDSTOP_INVERTING == 1) ? (PSTR("Y1")) : (PSTR("Y0")));
+	lcd_set_cursor(0, 3);
+	lcd_puts_P((READ(Z_MIN_PIN) ^ Z_MIN_ENDSTOP_INVERTING == 1) ? (PSTR("Z1")) : (PSTR("Z0")));
 }
 
 static void menu_show_end_stops() {
@@ -3367,8 +3590,8 @@ static void menu_show_end_stops() {
 // Otherwise the Z calibration is not changed and false is returned.
 void lcd_diag_show_end_stops()
 {
-    int enc_dif = encoderDiff;
-    lcd_implementation_clear();
+    int enc_dif = lcd_encoder_diff;
+    lcd_clear();
     for (;;) {
         manage_heater();
         manage_inactivity(true);
@@ -3380,7 +3603,7 @@ void lcd_diag_show_end_stops()
             break;
         }
     }
-    lcd_implementation_clear();
+    lcd_clear();
     lcd_return_to_status();
 }
 
@@ -3608,49 +3831,49 @@ void lcd_pick_babystep(){
     
     
     
-    lcd_implementation_clear();
+    lcd_clear();
     
-    lcd.setCursor(0, 0);
+    lcd_set_cursor(0, 0);
     
-    lcd_printPGM(_i("Pick print"));////MSG_PICK_Z c=0 r=0
+    lcd_puts_P(_i("Pick print"));////MSG_PICK_Z c=0 r=0
     
     
-    lcd.setCursor(3, 2);
+    lcd_set_cursor(3, 2);
     
-    lcd.print("1");
+    lcd_print("1");
     
-    lcd.setCursor(3, 3);
+    lcd_set_cursor(3, 3);
     
-    lcd.print("2");
+    lcd_print("2");
     
-    lcd.setCursor(12, 2);
+    lcd_set_cursor(12, 2);
     
-    lcd.print("3");
+    lcd_print("3");
     
-    lcd.setCursor(12, 3);
+    lcd_set_cursor(12, 3);
     
-    lcd.print("4");
+    lcd_print("4");
     
-    lcd.setCursor(1, 2);
+    lcd_set_cursor(1, 2);
     
-    lcd.print(">");
+    lcd_print(">");
     
     
-    enc_dif = encoderDiff;
+    enc_dif = lcd_encoder_diff;
     
     while (fsm == 0) {
         
         manage_heater();
         manage_inactivity(true);
         
-        if ( abs((enc_dif - encoderDiff)) > 4 ) {
+        if ( abs((enc_dif - lcd_encoder_diff)) > 4 ) {
             
-            if ( (abs(enc_dif - encoderDiff)) > 1 ) {
-                if (enc_dif > encoderDiff ) {
+            if ( (abs(enc_dif - lcd_encoder_diff)) > 1 ) {
+                if (enc_dif > lcd_encoder_diff ) {
                     cursor_pos --;
                 }
                 
-                if (enc_dif < encoderDiff  ) {
+                if (enc_dif < lcd_encoder_diff  ) {
                     cursor_pos ++;
                 }
                 
@@ -3663,25 +3886,25 @@ void lcd_pick_babystep(){
                 }
 
                 
-                lcd.setCursor(1, 2);
-                lcd.print(" ");
-                lcd.setCursor(1, 3);
-                lcd.print(" ");
-                lcd.setCursor(10, 2);
-                lcd.print(" ");
-                lcd.setCursor(10, 3);
-                lcd.print(" ");
+                lcd_set_cursor(1, 2);
+                lcd_print(" ");
+                lcd_set_cursor(1, 3);
+                lcd_print(" ");
+                lcd_set_cursor(10, 2);
+                lcd_print(" ");
+                lcd_set_cursor(10, 3);
+                lcd_print(" ");
                 
                 if (cursor_pos < 3) {
-                    lcd.setCursor(1, cursor_pos+1);
-                    lcd.print(">");
+                    lcd_set_cursor(1, cursor_pos+1);
+                    lcd_print(">");
                 }else{
-                    lcd.setCursor(10, cursor_pos-1);
-                    lcd.print(">");
+                    lcd_set_cursor(10, cursor_pos-1);
+                    lcd_print(">");
                 }
                 
    
-                enc_dif = encoderDiff;
+                enc_dif = lcd_encoder_diff;
                 delay(100);
             }
             
@@ -3698,7 +3921,7 @@ void lcd_pick_babystep(){
         }
     };
     
-    lcd_implementation_clear();
+    lcd_clear();
     lcd_return_to_status();
 }
 */
@@ -3751,7 +3974,6 @@ static void lcd_sort_type_set() {
 	}
 	eeprom_update_byte((unsigned char *)EEPROM_SD_SORT, sdSort);
 	presort_flag = true;
-	lcd_goto_menu(lcd_settings_menu); //doesn't break menuStack
 }
 #endif //SDCARD_SORT_ALPHA
 
@@ -3856,8 +4078,8 @@ static void lcd_crash_mode_set()
     }else{
         crashdet_enable();
     }
-	if (IS_SD_PRINTING || is_usb_printing || (lcd_commands_type == LCD_COMMAND_V2_CAL)) lcd_goto_menu(lcd_tune_menu, 9);
-	else lcd_goto_menu(lcd_settings_menu, 9);
+	if (IS_SD_PRINTING || is_usb_printing || (lcd_commands_type == LCD_COMMAND_V2_CAL)) menu_goto(lcd_tune_menu, 9, true, true);
+	else menu_goto(lcd_settings_menu, 9, true, true);
     
 }
 #endif //TMC2130
@@ -3899,10 +4121,10 @@ void menu_setlang(unsigned char lang)
 		if (lcd_show_fullscreen_message_yes_no_and_wait_P(_i("Copy selected language from XFLASH?"), false, true))
 			lang_boot_update_start(lang);
 		lcd_update_enable(true);
-		lcd_implementation_clear();
-		lcd_goto_menu(lcd_language_menu);
+		lcd_clear();
+		menu_goto(lcd_language_menu, 0, true, true);
 		lcd_timeoutToStatus = -1; //infinite timeout
-		lcdDrawUpdate = 2;
+		lcd_draw_update = 2;
 	}
 }
 
@@ -3971,7 +4193,6 @@ void lcd_temp_calibration_set() {
 	temp_cal_active = !temp_cal_active;
 	eeprom_update_byte((unsigned char *)EEPROM_TEMP_CAL_ACTIVE, temp_cal_active);
 	st_current_init();
-	lcd_goto_menu(lcd_settings_menu); //doesn't break menuStack
 }
 
 #ifdef HAS_SECOND_SERIAL_PORT
@@ -3980,7 +4201,6 @@ void lcd_second_serial_set() {
 	else selectedSerialPort = 1;
 	eeprom_update_byte((unsigned char *)EEPROM_SECOND_SERIAL_ACTIVE, selectedSerialPort);
 	MYSERIAL.begin(BAUDRATE);
-	lcd_goto_menu(lcd_settings_menu);//doesn't break menuStack
 }
 #endif //HAS_SECOND_SERIAL_PORT
 
@@ -4010,10 +4230,10 @@ void lcd_calibrate_pinda() {
 		unsigned long msg_millis;
 
 		lcd_show_fullscreen_message_and_wait_P(_i("Mark filament 100mm from extruder body. Click when done."));////MSG_MARK_FIL c=20 r=8
-		lcd_implementation_clear();
+		lcd_clear();
 		
 		
-		lcd.setCursor(0, 1); lcd_printPGM(_T(MSG_PLEASE_WAIT));
+		lcd_set_cursor(0, 1); lcd_puts_P(_T(MSG_PLEASE_WAIT));
 		current_position[E_AXIS] += e_shift_calibration;
 		plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], feedrate, active_extruder);
 		st_synchronize();
@@ -4030,14 +4250,14 @@ void lcd_calibrate_pinda() {
 
 			//manage_inactivity(true);
 			manage_heater();
-			if (abs(encoderDiff) >= ENCODER_PULSES_PER_STEP) {						//adjusting mark by knob rotation
+			if (abs(lcd_encoder_diff) >= ENCODER_PULSES_PER_STEP) {						//adjusting mark by knob rotation
 				delay_keep_alive(50);
 				//previous_millis_cmd = millis();
-				encoderPosition += (encoderDiff / ENCODER_PULSES_PER_STEP);
-				encoderDiff = 0;
+				lcd_encoder += (lcd_encoder_diff / ENCODER_PULSES_PER_STEP);
+				lcd_encoder_diff = 0;
 				if (!planner_queue_full()) {
-					current_position[E_AXIS] += float(abs((int)encoderPosition)) * 0.01; //0.05
-					encoderPosition = 0;
+					current_position[E_AXIS] += float(abs((int)lcd_encoder)) * 0.01; //0.05
+					lcd_encoder = 0;
 					plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], feedrate, active_extruder);
 					
 				}
@@ -4046,33 +4266,33 @@ void lcd_calibrate_pinda() {
 		
 		steps_final = current_position[E_AXIS] * axis_steps_per_unit[E_AXIS];
 		//steps_final = st_get_position(E_AXIS);
-		lcdDrawUpdate = 1;
+		lcd_draw_update = 1;
 		e_steps_per_unit = ((float)(steps_final)) / 100.0f;
 		if (e_steps_per_unit < MIN_E_STEPS_PER_UNIT) e_steps_per_unit = MIN_E_STEPS_PER_UNIT;				
 		if (e_steps_per_unit > MAX_E_STEPS_PER_UNIT) e_steps_per_unit = MAX_E_STEPS_PER_UNIT;
 
-		lcd_implementation_clear();
+		lcd_clear();
 
 		axis_steps_per_unit[E_AXIS] = e_steps_per_unit;
 		enquecommand_P(PSTR("M500")); //store settings to eeprom
 	
-		//lcd_implementation_drawedit(PSTR("Result"), ftostr31(axis_steps_per_unit[E_AXIS]));
+		//lcd_drawedit(PSTR("Result"), ftostr31(axis_steps_per_unit[E_AXIS]));
 		//delay_keep_alive(2000);
 		delay_keep_alive(500);
 		lcd_show_fullscreen_message_and_wait_P(_i("E calibration finished. Please clean the nozzle. Click when done."));////MSG_CLEAN_NOZZLE_E c=20 r=8
 		lcd_update_enable(true);
-		lcdDrawUpdate = 2;
+		lcd_draw_update = 2;
 
 	}
 	else
 	{
-		lcd_implementation_clear();
-		lcd.setCursor(0, 0);
-		lcd_printPGM(_T(MSG_ERROR));
-		lcd.setCursor(0, 2);
-		lcd_printPGM(_T(MSG_PREHEAT_NOZZLE));
+		lcd_clear();
+		lcd_set_cursor(0, 0);
+		lcd_puts_P(_T(MSG_ERROR));
+		lcd_set_cursor(0, 2);
+		lcd_puts_P(_T(MSG_PREHEAT_NOZZLE));
 		delay(2000);
-		lcd_implementation_clear();
+		lcd_clear();
 	}
 	lcd_return_to_status();
 }
@@ -4132,14 +4352,14 @@ void lcd_wizard() {
 void lcd_language()
 {
 	lcd_update_enable(true);
-	lcd_implementation_clear();
-	lcd_goto_menu(lcd_language_menu);
+	lcd_clear();
+	menu_goto(lcd_language_menu, 0, true, true);
 	lcd_timeoutToStatus = -1; //infinite timeout
-	lcdDrawUpdate = 2;
-	while ((currentMenu != lcd_status_screen) && (!lang_is_selected()))
+	lcd_draw_update = 2;
+	while ((menu_menu != lcd_status_screen) && (!lang_is_selected()))
 	{
 		delay(50);
-		lcd_update();
+		lcd_update(0);
 		manage_heater();
 		manage_inactivity(true);
 	}
@@ -4219,12 +4439,12 @@ void lcd_wizard(int state) {
 			while (abs(degHotend(0) - PLA_PREHEAT_HOTEND_TEMP) > 3) {
 				lcd_display_message_fullscreen_P(_T(MSG_WIZARD_HEATING));
 
-				lcd.setCursor(0, 4);
-				lcd.print(LCD_STR_THERMOMETER[0]);
-				lcd.print(ftostr3(degHotend(0)));
-				lcd.print("/");
-				lcd.print(PLA_PREHEAT_HOTEND_TEMP);
-				lcd.print(LCD_STR_DEGREE);
+				lcd_set_cursor(0, 4);
+				lcd_print(LCD_STR_THERMOMETER[0]);
+				lcd_print(ftostr3(degHotend(0)));
+				lcd_print("/");
+				lcd_print(PLA_PREHEAT_HOTEND_TEMP);
+				lcd_print(LCD_STR_DEGREE);
 				lcd_set_custom_characters();
 				delay_keep_alive(1000);
 			}
@@ -4237,8 +4457,8 @@ void lcd_wizard(int state) {
 #endif //PAT9125
 			lcd_show_fullscreen_message_and_wait_P(_i("Please insert PLA filament to the extruder, then press knob to load it."));////MSG_WIZARD_LOAD_FILAMENT c=20 r=8
 			lcd_update_enable(false);
-			lcd_implementation_clear();
-			lcd_print_at_PGM(0, 2, _T(MSG_LOADING_FILAMENT));
+			lcd_clear();
+			lcd_puts_at_P(0, 2, _T(MSG_LOADING_FILAMENT));
 #ifdef SNMM
 			change_extr(0);
 #endif
@@ -4317,19 +4537,34 @@ void lcd_wizard(int state) {
 	lcd_return_to_status();
 	lcd_update(2);
 }
+/*
+void lcd_settings_linearity_correction_menu(void)
+{
+	MENU_BEGIN();
+	if (menu_item_back_P(_T(MSG_MAIN)))
+	{
+		lcd_settings_menu_back();
+		return;
+	}
+//	MENU_ITEM_BACK_P(_T(MSG_SETTINGS));
+#ifdef TMC2130_LINEARITY_CORRECTION_XYZ
+	//tmc2130_wave_fac[X_AXIS]
+	int corr[4] = {tmc2130_wave_fac[X_AXIS], tmc2130_wave_fac[Y_AXIS], tmc2130_wave_fac[Z_AXIS], tmc2130_wave_fac[E_AXIS]};
 
-
-
+	MENU_ITEM_EDIT_int3_P(_i("X-correct"),  &corr[X_AXIS],  TMC2130_WAVE_FAC1000_MIN-TMC2130_WAVE_FAC1000_STP, TMC2130_WAVE_FAC1000_MAX);////MSG_EXTRUDER_CORRECTION c=9 r=0
+	MENU_ITEM_EDIT_int3_P(_i("Y-correct"),  &corr[Y_AXIS],  TMC2130_WAVE_FAC1000_MIN-TMC2130_WAVE_FAC1000_STP, TMC2130_WAVE_FAC1000_MAX);////MSG_EXTRUDER_CORRECTION c=9 r=0
+	MENU_ITEM_EDIT_int3_P(_i("Z-correct"),  &corr[Z_AXIS],  TMC2130_WAVE_FAC1000_MIN-TMC2130_WAVE_FAC1000_STP, TMC2130_WAVE_FAC1000_MAX);////MSG_EXTRUDER_CORRECTION c=9 r=0
+#endif //TMC2130_LINEARITY_CORRECTION_XYZ
+	MENU_ITEM_EDIT_int3_P(_i("E-correct"),  &corr[E_AXIS],  TMC2130_WAVE_FAC1000_MIN-TMC2130_WAVE_FAC1000_STP, TMC2130_WAVE_FAC1000_MAX);////MSG_EXTRUDER_CORRECTION c=9 r=0
+	MENU_END();
+}
+*/
 static void lcd_settings_menu()
 {
   EEPROM_read(EEPROM_SILENT, (uint8_t*)&SilentModeMenu, sizeof(SilentModeMenu));
   MENU_BEGIN();
+  MENU_ITEM_BACK_P(_T(MSG_MAIN));
 
-  if (menu_item_back_P(_T(MSG_MAIN)))
-  {
-	  lcd_settings_menu_back();
-	  return;
-  }
 
   MENU_ITEM_SUBMENU_P(_i("Temperature"), lcd_control_temperature_menu);////MSG_TEMPERATURE c=0 r=0
   if (!homing_flag)
@@ -4400,12 +4635,7 @@ static void lcd_settings_menu()
     else MENU_ITEM_SUBMENU_P(_T(MSG_CRASHDETECT_NA), lcd_crash_mode_info);
   }
 
-#ifdef TMC2130_LINEARITY_CORRECTION_XYZ
-  MENU_ITEM_EDIT(wfac, _i("X-correct"),  &tmc2130_wave_fac[X_AXIS],  TMC2130_WAVE_FAC1000_MIN-TMC2130_WAVE_FAC1000_STP, TMC2130_WAVE_FAC1000_MAX);////MSG_EXTRUDER_CORRECTION c=9 r=0
-  MENU_ITEM_EDIT(wfac, _i("Y-correct"),  &tmc2130_wave_fac[Y_AXIS],  TMC2130_WAVE_FAC1000_MIN-TMC2130_WAVE_FAC1000_STP, TMC2130_WAVE_FAC1000_MAX);////MSG_EXTRUDER_CORRECTION c=9 r=0
-  MENU_ITEM_EDIT(wfac, _i("Z-correct"),  &tmc2130_wave_fac[Z_AXIS],  TMC2130_WAVE_FAC1000_MIN-TMC2130_WAVE_FAC1000_STP, TMC2130_WAVE_FAC1000_MAX);////MSG_EXTRUDER_CORRECTION c=9 r=0
-#endif //TMC2130_LINEARITY_CORRECTION_XYZ
-  MENU_ITEM_EDIT(wfac, _i("E-correct"),  &tmc2130_wave_fac[E_AXIS],  TMC2130_WAVE_FAC1000_MIN-TMC2130_WAVE_FAC1000_STP, TMC2130_WAVE_FAC1000_MAX);////MSG_EXTRUDER_CORRECTION c=9 r=0
+//  MENU_ITEM_SUBMENU_P(_i("Lin. correction"), lcd_settings_linearity_correction_menu);
 #endif //TMC2130
 
   if (temp_cal_active == false) {
@@ -4489,216 +4719,9 @@ static void lcd_settings_menu_back()
     lcd_ustep_linearity_menu_save();
     if (changed) tmc2130_init();
 #endif //TMC2130
-    currentMenu = lcd_main_menu;
+    menu_menu = lcd_main_menu;
 //    lcd_main_menu();
 }
-#ifdef EXPERIMENTAL_FEATURES
-
-static void lcd_experimantal_menu();
-static void lcd_homing_accuracy_menu();
-
-static void lcd_accurate_home_set()
-{
-	tmc2130_home_enabled = tmc2130_home_enabled?0:1;
-	eeprom_update_byte((uint8_t*)EEPROM_TMC2130_HOME_ENABLED, tmc2130_home_enabled);
-}
-
-static void lcd_homing_accuracy_menu_advanced_reset()
-{
-	tmc2130_home_bsteps[X_AXIS] = 48;
-	tmc2130_home_fsteps[X_AXIS] = 48;
-	tmc2130_home_bsteps[Y_AXIS] = 48;
-	tmc2130_home_fsteps[Y_AXIS] = 48;
-}
-
-static void lcd_homing_accuracy_menu_advanced_save()
-{
-	eeprom_update_byte((uint8_t*)EEPROM_TMC2130_HOME_X_ORIGIN, tmc2130_home_origin[X_AXIS]);
-	eeprom_update_byte((uint8_t*)EEPROM_TMC2130_HOME_X_BSTEPS, tmc2130_home_bsteps[X_AXIS]);
-	eeprom_update_byte((uint8_t*)EEPROM_TMC2130_HOME_X_FSTEPS, tmc2130_home_fsteps[X_AXIS]);
-	eeprom_update_byte((uint8_t*)EEPROM_TMC2130_HOME_Y_ORIGIN, tmc2130_home_origin[Y_AXIS]);
-	eeprom_update_byte((uint8_t*)EEPROM_TMC2130_HOME_Y_BSTEPS, tmc2130_home_bsteps[Y_AXIS]);
-	eeprom_update_byte((uint8_t*)EEPROM_TMC2130_HOME_Y_FSTEPS, tmc2130_home_fsteps[Y_AXIS]);
-}
-
-static void lcd_homing_accuracy_menu_advanced_back()
-{
-	lcd_homing_accuracy_menu_advanced_save();
-	currentMenu = lcd_homing_accuracy_menu;
-	lcd_homing_accuracy_menu();
-}
-
-static void lcd_homing_accuracy_menu_advanced()
-{
-	lcd_timeoutToStatus = millis() + LCD_TIMEOUT_TO_STATUS;
-	MENU_BEGIN();
-///!	MENU_ITEM_BACK_P(PSTR("Homing accuracy"), lcd_homing_accuracy_menu_advanced_back);
-	MENU_ITEM_FUNCTION_P(PSTR("Reset def. steps"), lcd_homing_accuracy_menu_advanced_reset);
-	MENU_ITEM_EDIT(byte3, PSTR("X-origin"),  &tmc2130_home_origin[X_AXIS],  0, 63);
-	MENU_ITEM_EDIT(byte3, PSTR("Y-origin"),  &tmc2130_home_origin[Y_AXIS],  0, 63);
-	MENU_ITEM_EDIT(byte3, PSTR("X-bsteps"),  &tmc2130_home_bsteps[X_AXIS],  0, 128);
-	MENU_ITEM_EDIT(byte3, PSTR("Y-bsteps"),  &tmc2130_home_bsteps[Y_AXIS],  0, 128);
-	MENU_ITEM_EDIT(byte3, PSTR("X-fsteps"),  &tmc2130_home_fsteps[X_AXIS],  0, 128);
-	MENU_ITEM_EDIT(byte3, PSTR("Y-fsteps"),  &tmc2130_home_fsteps[Y_AXIS],  0, 128);
-	MENU_END();
-}
-
-static void lcd_homing_accuracy_menu()
-{
-	MENU_BEGIN();
-	MENU_ITEM_BACK_P(PSTR("Experimental"));
-	MENU_ITEM_FUNCTION_P(tmc2130_home_enabled?PSTR("Accur. homing  On"):PSTR("Accur. homing Off"), lcd_accurate_home_set);
-    MENU_ITEM_GCODE_P(PSTR("Calibrate X"), PSTR("G28XC"));
-    MENU_ITEM_GCODE_P(PSTR("Calibrate Y"), PSTR("G28YC"));
-	MENU_ITEM_SUBMENU_P(PSTR("Advanced"), lcd_homing_accuracy_menu_advanced);
-	MENU_END();
-}
-
-static void lcd_ustep_resolution_menu_save()
-{
-	eeprom_update_byte((uint8_t*)EEPROM_TMC2130_X_MRES, tmc2130_mres[X_AXIS]);
-	eeprom_update_byte((uint8_t*)EEPROM_TMC2130_Y_MRES, tmc2130_mres[Y_AXIS]);
-	eeprom_update_byte((uint8_t*)EEPROM_TMC2130_Z_MRES, tmc2130_mres[Z_AXIS]);
-	eeprom_update_byte((uint8_t*)EEPROM_TMC2130_E_MRES, tmc2130_mres[E_AXIS]);
-}
-
-static void lcd_ustep_resolution_menu_back()
-{
-	float tmp1[]=DEFAULT_AXIS_STEPS_PER_UNIT;
-	bool changed = false;
-	if (tmc2130_mres[X_AXIS] != eeprom_read_byte((uint8_t*)EEPROM_TMC2130_X_MRES))
-	{
-		axis_steps_per_unit[X_AXIS] = tmp1[X_AXIS] * tmc2130_mres2usteps(tmc2130_mres[X_AXIS]) / TMC2130_USTEPS_XY;
-		changed = true;
-	}
-	if (tmc2130_mres[Y_AXIS] != eeprom_read_byte((uint8_t*)EEPROM_TMC2130_Y_MRES))
-	{
-		axis_steps_per_unit[Y_AXIS] = tmp1[Y_AXIS] * tmc2130_mres2usteps(tmc2130_mres[Y_AXIS]) / TMC2130_USTEPS_XY;
-		changed = true;
-	}
-	if (tmc2130_mres[Z_AXIS] != eeprom_read_byte((uint8_t*)EEPROM_TMC2130_Z_MRES))
-	{
-		axis_steps_per_unit[Z_AXIS] = tmp1[Z_AXIS] * tmc2130_mres2usteps(tmc2130_mres[Z_AXIS]) / TMC2130_USTEPS_Z;
-		changed = true;
-	}
-	if (tmc2130_mres[E_AXIS] != eeprom_read_byte((uint8_t*)EEPROM_TMC2130_E_MRES))
-	{
-		axis_steps_per_unit[E_AXIS] = tmp1[E_AXIS] * tmc2130_mres2usteps(tmc2130_mres[E_AXIS]) / TMC2130_USTEPS_E;
-		changed = true;
-	}
-    if (changed)
-	{
-		lcd_ustep_resolution_menu_save();
-		Config_StoreSettings(EEPROM_OFFSET);
-		tmc2130_init();
-	}
-	currentMenu = lcd_experimantal_menu;
-	lcd_experimantal_menu();
-}
-
-static void lcd_ustep_resolution_reset_def_xyze()
-{
-	tmc2130_mres[X_AXIS] = tmc2130_usteps2mres(TMC2130_USTEPS_XY);
-	tmc2130_mres[Y_AXIS] = tmc2130_usteps2mres(TMC2130_USTEPS_XY);
-	tmc2130_mres[Z_AXIS] = tmc2130_usteps2mres(TMC2130_USTEPS_Z);
-	tmc2130_mres[E_AXIS] = tmc2130_usteps2mres(TMC2130_USTEPS_E);
-	float tmp1[]=DEFAULT_AXIS_STEPS_PER_UNIT;
-	axis_steps_per_unit[X_AXIS] = tmp1[X_AXIS];
-	axis_steps_per_unit[Y_AXIS] = tmp1[Y_AXIS];
-	axis_steps_per_unit[Z_AXIS] = tmp1[Z_AXIS];
-	axis_steps_per_unit[E_AXIS] = tmp1[E_AXIS];
-}
-
-static void lcd_ustep_resolution_menu()
-{
-	lcd_timeoutToStatus = millis() + LCD_TIMEOUT_TO_STATUS;
-	MENU_BEGIN();
-///!	MENU_ITEM_BACK_P(PSTR("Experimental"), lcd_ustep_resolution_menu_back);
-	MENU_ITEM_FUNCTION_P(PSTR("Reset defaults"),  lcd_ustep_resolution_reset_def_xyze);
-	MENU_ITEM_EDIT(mres, PSTR("X-resolution"),  &tmc2130_mres[X_AXIS],  4, 4);
-	MENU_ITEM_EDIT(mres, PSTR("Y-resolution"),  &tmc2130_mres[Y_AXIS],  4, 4);
-	MENU_ITEM_EDIT(mres, PSTR("Z-resolution"),  &tmc2130_mres[Z_AXIS],  4, 4);
-	MENU_ITEM_EDIT(mres, PSTR("E-resolution"),  &tmc2130_mres[E_AXIS],  2, 5);
-	MENU_END();
-}
-
-
-
-static void lcd_ustep_linearity_menu_back()
-{
-	bool changed = false;
-	if (tmc2130_wave_fac[X_AXIS] < TMC2130_WAVE_FAC1000_MIN) tmc2130_wave_fac[X_AXIS] = 0;
-	if (tmc2130_wave_fac[Y_AXIS] < TMC2130_WAVE_FAC1000_MIN) tmc2130_wave_fac[Y_AXIS] = 0;
-	if (tmc2130_wave_fac[Z_AXIS] < TMC2130_WAVE_FAC1000_MIN) tmc2130_wave_fac[Z_AXIS] = 0;
-	if (tmc2130_wave_fac[E_AXIS] < TMC2130_WAVE_FAC1000_MIN) tmc2130_wave_fac[E_AXIS] = 0;
-	changed |= (eeprom_read_byte((uint8_t*)EEPROM_TMC2130_WAVE_X_FAC) != tmc2130_wave_fac[X_AXIS]);
-	changed |= (eeprom_read_byte((uint8_t*)EEPROM_TMC2130_WAVE_Y_FAC) != tmc2130_wave_fac[Y_AXIS]);
-	changed |= (eeprom_read_byte((uint8_t*)EEPROM_TMC2130_WAVE_Z_FAC) != tmc2130_wave_fac[Z_AXIS]);
-	changed |= (eeprom_read_byte((uint8_t*)EEPROM_TMC2130_WAVE_E_FAC) != tmc2130_wave_fac[E_AXIS]);
-	lcd_ustep_linearity_menu_save();
-	if (changed) tmc2130_init();
-	currentMenu = lcd_experimantal_menu;
-	lcd_experimantal_menu();
-}
-
-static void lcd_ustep_linearity_menu_recomended()
-{
-	tmc2130_wave_fac[X_AXIS] = 220;
-	tmc2130_wave_fac[Y_AXIS] = 220;
-	tmc2130_wave_fac[Z_AXIS] = 220;
-	tmc2130_wave_fac[E_AXIS] = 220;
-}
-
-static void lcd_ustep_linearity_menu_reset()
-{
-	tmc2130_wave_fac[X_AXIS] = 0;
-	tmc2130_wave_fac[Y_AXIS] = 0;
-	tmc2130_wave_fac[Z_AXIS] = 0;
-	tmc2130_wave_fac[E_AXIS] = 0;
-}
-
-static void lcd_ustep_linearity_menu()
-{
-	lcd_timeoutToStatus = millis() + LCD_TIMEOUT_TO_STATUS;
-	MENU_BEGIN();
-///!	MENU_ITEM_BACK_P(PSTR("Experimental"), lcd_ustep_linearity_menu_back);
-	MENU_ITEM_FUNCTION_P(PSTR("Reset correction"), lcd_ustep_linearity_menu_reset);
-	MENU_ITEM_FUNCTION_P(PSTR("Recomended config"), lcd_ustep_linearity_menu_recomended);
-	MENU_ITEM_EDIT(wfac, PSTR("X-correction"),  &tmc2130_wave_fac[X_AXIS],  TMC2130_WAVE_FAC1000_MIN-TMC2130_WAVE_FAC1000_STP, TMC2130_WAVE_FAC1000_MAX);
-	MENU_ITEM_EDIT(wfac, PSTR("Y-correction"),  &tmc2130_wave_fac[Y_AXIS],  TMC2130_WAVE_FAC1000_MIN-TMC2130_WAVE_FAC1000_STP, TMC2130_WAVE_FAC1000_MAX);
-	MENU_ITEM_EDIT(wfac, PSTR("Z-correction"),  &tmc2130_wave_fac[Z_AXIS],  TMC2130_WAVE_FAC1000_MIN-TMC2130_WAVE_FAC1000_STP, TMC2130_WAVE_FAC1000_MAX);
-	MENU_ITEM_EDIT(wfac, PSTR("E-correction"),  &tmc2130_wave_fac[E_AXIS],  TMC2130_WAVE_FAC1000_MIN-TMC2130_WAVE_FAC1000_STP, TMC2130_WAVE_FAC1000_MAX);
-	MENU_END();
-}
-
-static void lcd_experimantal_menu_save_all()
-{
-	eeprom_update_byte((uint8_t*)EEPROM_TMC2130_HOME_ENABLED, tmc2130_home_enabled);
-	lcd_ustep_resolution_menu_save();
-	lcd_ustep_linearity_menu_save();
-	Config_StoreSettings(EEPROM_OFFSET);
-}
-
-static void lcd_experimantal_menu_disable_all()
-{
-	tmc2130_home_enabled = 0;
-	lcd_ustep_resolution_reset_def_xyze();
-	lcd_ustep_linearity_menu_reset();
-	lcd_experimantal_menu_save_all();
-	tmc2130_init();
-}
-
-static void lcd_experimantal_menu()
-{
-	MENU_BEGIN();
-	MENU_ITEM_BACK_P(_T(MSG_MAIN));
-	MENU_ITEM_FUNCTION_P(PSTR("All Xfeatures off"), lcd_experimantal_menu_disable_all);
-	MENU_ITEM_SUBMENU_P(PSTR("Homing accuracy"), lcd_homing_accuracy_menu);
-	MENU_ITEM_SUBMENU_P(PSTR("uStep resolution"), lcd_ustep_resolution_menu);
-	MENU_ITEM_SUBMENU_P(PSTR("uStep linearity"), lcd_ustep_linearity_menu);
-	MENU_END();
-}
-#endif //EXPERIMENTAL_FEATURES
 
 
 static void lcd_calibration_menu()
@@ -4748,34 +4771,34 @@ static void lcd_calibration_menu()
 }
 
 void bowden_menu() {
-	int enc_dif = encoderDiff;
+	int enc_dif = lcd_encoder_diff;
 	int cursor_pos = 0;
-	lcd_implementation_clear();
-	lcd.setCursor(0, 0);
-	lcd.print(">");
+	lcd_clear();
+	lcd_set_cursor(0, 0);
+	lcd_print(">");
 	for (int i = 0; i < 4; i++) {
-		lcd.setCursor(1, i);
-		lcd.print("Extruder ");
-		lcd.print(i);
-		lcd.print(": ");
+		lcd_set_cursor(1, i);
+		lcd_print("Extruder ");
+		lcd_print(i);
+		lcd_print(": ");
 		EEPROM_read_B(EEPROM_BOWDEN_LENGTH + i * 2, &bowden_length[i]);
-		lcd.print(bowden_length[i] - 48);
+		lcd_print(bowden_length[i] - 48);
 
 	}
-	enc_dif = encoderDiff;
+	enc_dif = lcd_encoder_diff;
 
 	while (1) {
 
 		manage_heater();
 		manage_inactivity(true);
 
-		if (abs((enc_dif - encoderDiff)) > 2) {
+		if (abs((enc_dif - lcd_encoder_diff)) > 2) {
 
-			if (enc_dif > encoderDiff) {
+			if (enc_dif > lcd_encoder_diff) {
 					cursor_pos--;
 				}
 
-				if (enc_dif < encoderDiff) {
+				if (enc_dif < lcd_encoder_diff) {
 					cursor_pos++;
 				}
 
@@ -4787,18 +4810,18 @@ void bowden_menu() {
 					cursor_pos = 0;
 				}
 
-				lcd.setCursor(0, 0);
-				lcd.print(" ");
-				lcd.setCursor(0, 1);
-				lcd.print(" ");
-				lcd.setCursor(0, 2);
-				lcd.print(" ");
-				lcd.setCursor(0, 3);
-				lcd.print(" ");
-				lcd.setCursor(0, cursor_pos);
-				lcd.print(">");
-
-				enc_dif = encoderDiff;
+				lcd_set_cursor(0, 0);
+				lcd_print(" ");
+				lcd_set_cursor(0, 1);
+				lcd_print(" ");
+				lcd_set_cursor(0, 2);
+				lcd_print(" ");
+				lcd_set_cursor(0, 3);
+				lcd_print(" ");
+				lcd_set_cursor(0, cursor_pos);
+				lcd_print(">");
+
+				enc_dif = lcd_encoder_diff;
 				delay(100);
 		}
 
@@ -4807,32 +4830,32 @@ void bowden_menu() {
 			delay(10);
 			while (lcd_clicked());
 
-			lcd_implementation_clear();
+			lcd_clear();
 			while (1) {
 
 				manage_heater();
 				manage_inactivity(true);
 
-				lcd.setCursor(1, 1);
-				lcd.print("Extruder ");
-				lcd.print(cursor_pos);
-				lcd.print(": ");
-				lcd.setCursor(13, 1);
-				lcd.print(bowden_length[cursor_pos] - 48);
+				lcd_set_cursor(1, 1);
+				lcd_print("Extruder ");
+				lcd_print(cursor_pos);
+				lcd_print(": ");
+				lcd_set_cursor(13, 1);
+				lcd_print(bowden_length[cursor_pos] - 48);
 
-				if (abs((enc_dif - encoderDiff)) > 2) {
-						if (enc_dif > encoderDiff) {
+				if (abs((enc_dif - lcd_encoder_diff)) > 2) {
+						if (enc_dif > lcd_encoder_diff) {
 							bowden_length[cursor_pos]--;
-							lcd.setCursor(13, 1);
-							lcd.print(bowden_length[cursor_pos] - 48);
-							enc_dif = encoderDiff;
+							lcd_set_cursor(13, 1);
+							lcd_print(bowden_length[cursor_pos] - 48);
+							enc_dif = lcd_encoder_diff;
 						}
 
-						if (enc_dif < encoderDiff) {
+						if (enc_dif < lcd_encoder_diff) {
 							bowden_length[cursor_pos]++;
-							lcd.setCursor(13, 1);
-							lcd.print(bowden_length[cursor_pos] - 48);
-							enc_dif = encoderDiff;
+							lcd_set_cursor(13, 1);
+							lcd_print(bowden_length[cursor_pos] - 48);
+							enc_dif = lcd_encoder_diff;
 						}
 				}
 				delay(100);
@@ -4843,17 +4866,17 @@ void bowden_menu() {
 					EEPROM_save_B(EEPROM_BOWDEN_LENGTH + cursor_pos * 2, &bowden_length[cursor_pos]);
 					if (lcd_show_fullscreen_message_yes_no_and_wait_P(PSTR("Continue with another bowden?"))) {
 						lcd_update_enable(true);
-						lcd_implementation_clear();
-						enc_dif = encoderDiff;
-						lcd.setCursor(0, cursor_pos);
-						lcd.print(">");
+						lcd_clear();
+						enc_dif = lcd_encoder_diff;
+						lcd_set_cursor(0, cursor_pos);
+						lcd_print(">");
 						for (int i = 0; i < 4; i++) {
-							lcd.setCursor(1, i);
-							lcd.print("Extruder ");
-							lcd.print(i);
-							lcd.print(": ");
+							lcd_set_cursor(1, i);
+							lcd_print("Extruder ");
+							lcd_print(i);
+							lcd_print(": ");
 							EEPROM_read_B(EEPROM_BOWDEN_LENGTH + i * 2, &bowden_length[i]);
-							lcd.print(bowden_length[i] - 48);
+							lcd_print(bowden_length[i] - 48);
 
 						}
 						break;
@@ -4868,34 +4891,34 @@ void bowden_menu() {
 //#ifdef SNMM
 
 static char snmm_stop_print_menu() { //menu for choosing which filaments will be unloaded in stop print
-	lcd_implementation_clear();
-	lcd_print_at_PGM(0,0,_T(MSG_UNLOAD_FILAMENT)); lcd.print(":");
-	lcd.setCursor(0, 1); lcd.print(">");
-	lcd_print_at_PGM(1,2,_i("Used during print"));////MSG_USED c=19 r=1
-	lcd_print_at_PGM(1,3,_i("Current"));////MSG_CURRENT c=19 r=1
+	lcd_clear();
+	lcd_puts_at_P(0,0,_T(MSG_UNLOAD_FILAMENT)); lcd_print(":");
+	lcd_set_cursor(0, 1); lcd_print(">");
+	lcd_puts_at_P(1,2,_i("Used during print"));////MSG_USED c=19 r=1
+	lcd_puts_at_P(1,3,_i("Current"));////MSG_CURRENT c=19 r=1
 	char cursor_pos = 1;
 	int enc_dif = 0;
 	KEEPALIVE_STATE(PAUSED_FOR_USER);
 	while (1) {
 		manage_heater();
 		manage_inactivity(true);
-		if (abs((enc_dif - encoderDiff)) > 4) {
+		if (abs((enc_dif - lcd_encoder_diff)) > 4) {
 
-			if ((abs(enc_dif - encoderDiff)) > 1) {
-				if (enc_dif > encoderDiff) cursor_pos--;
-				if (enc_dif < encoderDiff) cursor_pos++;
+			if ((abs(enc_dif - lcd_encoder_diff)) > 1) {
+				if (enc_dif > lcd_encoder_diff) cursor_pos--;
+				if (enc_dif < lcd_encoder_diff) cursor_pos++;
 				if (cursor_pos > 3) cursor_pos = 3;
 				if (cursor_pos < 1) cursor_pos = 1;
 
-				lcd.setCursor(0, 1);
-				lcd.print(" ");
-				lcd.setCursor(0, 2);
-				lcd.print(" ");
-				lcd.setCursor(0, 3);
-				lcd.print(" ");
-				lcd.setCursor(0, cursor_pos);
-				lcd.print(">");
-				enc_dif = encoderDiff;
+				lcd_set_cursor(0, 1);
+				lcd_print(" ");
+				lcd_set_cursor(0, 2);
+				lcd_print(" ");
+				lcd_set_cursor(0, 3);
+				lcd_print(" ");
+				lcd_set_cursor(0, cursor_pos);
+				lcd_print(">");
+				enc_dif = lcd_encoder_diff;
 				delay(100);
 			}
 		}
@@ -4921,34 +4944,34 @@ char choose_extruder_menu() {
 	int enc_dif = 0;
 	char cursor_pos = 1;
 	
-	enc_dif = encoderDiff;
-	lcd_implementation_clear();
+	enc_dif = lcd_encoder_diff;
+	lcd_clear();
 	
-	lcd_printPGM(_T(MSG_CHOOSE_EXTRUDER));
-	lcd.setCursor(0, 1);
-	lcd.print(">");
+	lcd_puts_P(_T(MSG_CHOOSE_EXTRUDER));
+	lcd_set_cursor(0, 1);
+	lcd_print(">");
 	for (int i = 0; i < 3; i++) {
-		lcd_print_at_PGM(1, i + 1, _T(MSG_EXTRUDER));
+		lcd_puts_at_P(1, i + 1, _T(MSG_EXTRUDER));
 	}
 	KEEPALIVE_STATE(PAUSED_FOR_USER);
 	while (1) {
 
 		for (int i = 0; i < 3; i++) {
-			lcd.setCursor(2 + strlen_P(_T(MSG_EXTRUDER)), i+1);
-			lcd.print(first + i + 1);
+			lcd_set_cursor(2 + strlen_P(_T(MSG_EXTRUDER)), i+1);
+			lcd_print(first + i + 1);
 		}
 
 		manage_heater();
 		manage_inactivity(true);
 
-		if (abs((enc_dif - encoderDiff)) > 4) {
+		if (abs((enc_dif - lcd_encoder_diff)) > 4) {
 
-			if ((abs(enc_dif - encoderDiff)) > 1) {
-				if (enc_dif > encoderDiff) {
+			if ((abs(enc_dif - lcd_encoder_diff)) > 1) {
+				if (enc_dif > lcd_encoder_diff) {
 					cursor_pos--;
 				}
 
-				if (enc_dif < encoderDiff) {
+				if (enc_dif < lcd_encoder_diff) {
 					cursor_pos++;
 				}
 
@@ -4956,10 +4979,10 @@ char choose_extruder_menu() {
 					cursor_pos = 3;
 					if (first < items_no - 3) {
 						first++;
-						lcd_implementation_clear();
-						lcd_printPGM(_T(MSG_CHOOSE_EXTRUDER));
+						lcd_clear();
+						lcd_puts_P(_T(MSG_CHOOSE_EXTRUDER));
 						for (int i = 0; i < 3; i++) {
-							lcd_print_at_PGM(1, i + 1, _T(MSG_EXTRUDER));
+							lcd_puts_at_P(1, i + 1, _T(MSG_EXTRUDER));
 						}
 					}
 				}
@@ -4968,22 +4991,22 @@ char choose_extruder_menu() {
 					cursor_pos = 1;
 					if (first > 0) {
 						first--;
-						lcd_implementation_clear();
-						lcd_printPGM(_T(MSG_CHOOSE_EXTRUDER));
+						lcd_clear();
+						lcd_puts_P(_T(MSG_CHOOSE_EXTRUDER));
 						for (int i = 0; i < 3; i++) {
-							lcd_print_at_PGM(1, i + 1, _T(MSG_EXTRUDER));
+							lcd_puts_at_P(1, i + 1, _T(MSG_EXTRUDER));
 						}
 					}
 				}
-				lcd.setCursor(0, 1);
-				lcd.print(" ");
-				lcd.setCursor(0, 2);
-				lcd.print(" ");
-				lcd.setCursor(0, 3);
-				lcd.print(" ");
-				lcd.setCursor(0, cursor_pos);
-				lcd.print(">");
-				enc_dif = encoderDiff;
+				lcd_set_cursor(0, 1);
+				lcd_print(" ");
+				lcd_set_cursor(0, 2);
+				lcd_print(" ");
+				lcd_set_cursor(0, 3);
+				lcd_print(" ");
+				lcd_set_cursor(0, cursor_pos);
+				lcd_print(">");
+				enc_dif = lcd_encoder_diff;
 				delay(100);
 			}
 
@@ -5024,29 +5047,29 @@ char reset_menu() {
 	item[4] = "Bowden length";
 #endif // SNMM
 
-	enc_dif = encoderDiff;
-	lcd_implementation_clear();
-	lcd.setCursor(0, 0);
-	lcd.print(">");
+	enc_dif = lcd_encoder_diff;
+	lcd_clear();
+	lcd_set_cursor(0, 0);
+	lcd_print(">");
 
 	while (1) {		
 
 		for (int i = 0; i < 4; i++) {
-			lcd.setCursor(1, i);
-			lcd.print(item[first + i]);
+			lcd_set_cursor(1, i);
+			lcd_print(item[first + i]);
 		}
 
 		manage_heater();
 		manage_inactivity(true);
 
-		if (abs((enc_dif - encoderDiff)) > 4) {
+		if (abs((enc_dif - lcd_encoder_diff)) > 4) {
 
-			if ((abs(enc_dif - encoderDiff)) > 1) {
-				if (enc_dif > encoderDiff) {
+			if ((abs(enc_dif - lcd_encoder_diff)) > 1) {
+				if (enc_dif > lcd_encoder_diff) {
 					cursor_pos--;
 				}
 
-				if (enc_dif < encoderDiff) {
+				if (enc_dif < lcd_encoder_diff) {
 					cursor_pos++;
 				}
 
@@ -5054,7 +5077,7 @@ char reset_menu() {
 					cursor_pos = 3;
 					if (first < items_no - 4) {
 						first++;
-						lcd_implementation_clear();
+						lcd_clear();
 					}
 				}
 
@@ -5062,20 +5085,20 @@ char reset_menu() {
 					cursor_pos = 0;
 					if (first > 0) {
 						first--;
-						lcd_implementation_clear();
+						lcd_clear();
 					}
 				}
-				lcd.setCursor(0, 0);
-				lcd.print(" ");
-				lcd.setCursor(0, 1);
-				lcd.print(" ");
-				lcd.setCursor(0, 2);
-				lcd.print(" ");
-				lcd.setCursor(0, 3);
-				lcd.print(" ");
-				lcd.setCursor(0, cursor_pos);
-				lcd.print(">");
-				enc_dif = encoderDiff;
+				lcd_set_cursor(0, 0);
+				lcd_print(" ");
+				lcd_set_cursor(0, 1);
+				lcd_print(" ");
+				lcd_set_cursor(0, 2);
+				lcd_print(" ");
+				lcd_set_cursor(0, 3);
+				lcd_print(" ");
+				lcd_set_cursor(0, cursor_pos);
+				lcd_print(">");
+				enc_dif = lcd_encoder_diff;
 				delay(100);
 			}
 
@@ -5092,17 +5115,16 @@ char reset_menu() {
 
 }
 
-static void lcd_disable_farm_mode() {
+static void lcd_disable_farm_mode()
+{
 	int8_t disable = lcd_show_fullscreen_message_yes_no_and_wait_P(PSTR("Disable farm mode?"), true, false); //allow timeouting, default no
-	if (disable) {
+	if (disable)
+	{
 		enquecommand_P(PSTR("G99"));
 		lcd_return_to_status();
 	}
-	else {
-		lcd_goto_menu(lcd_settings_menu); //doesn't break menuStack
-	}
 	lcd_update_enable(true);
-	lcdDrawUpdate = 2;
+	lcd_draw_update = 2;
 	
 }
 
@@ -5208,8 +5230,8 @@ void extr_adj(int extruder) //loading filament for SNMM
 	max_feedrate[E_AXIS] =80;
 	//max_feedrate[E_AXIS] = 50;
 	START:
-	lcd_implementation_clear();
-	lcd.setCursor(0, 0); 
+	lcd_clear();
+	lcd_set_cursor(0, 0); 
 	switch (extruder) {
 	case 1: lcd_display_message_fullscreen_P(_T(MSG_FILAMENT_LOADING_T1)); break;
 	case 2: lcd_display_message_fullscreen_P(_T(MSG_FILAMENT_LOADING_T2)); break;
@@ -5229,12 +5251,12 @@ void extr_adj(int extruder) //loading filament for SNMM
 	//extr_mov(BOWDEN_LENGTH/2.f, 500); //dividing by 2 is there because of max. extrusion length limitation (x_max + y_max)
 	//extr_mov(BOWDEN_LENGTH/2.f, 500);
 	extr_mov(bowden_length[extruder], 500);
-	lcd_implementation_clear();
-	lcd.setCursor(0, 0); lcd_printPGM(_T(MSG_LOADING_FILAMENT));
-	if(strlen(_T(MSG_LOADING_FILAMENT))>18) lcd.setCursor(0, 1);
-	else lcd.print(" ");
-	lcd.print(snmm_extruder + 1);
-	lcd.setCursor(0, 2); lcd_printPGM(_T(MSG_PLEASE_WAIT));
+	lcd_clear();
+	lcd_set_cursor(0, 0); lcd_puts_P(_T(MSG_LOADING_FILAMENT));
+	if(strlen(_T(MSG_LOADING_FILAMENT))>18) lcd_set_cursor(0, 1);
+	else lcd_print(" ");
+	lcd_print(snmm_extruder + 1);
+	lcd_set_cursor(0, 2); lcd_puts_P(_T(MSG_PLEASE_WAIT));
 	st_synchronize();
 	max_feedrate[E_AXIS] = 50;
 	lcd_update_enable(true);
@@ -5278,13 +5300,13 @@ void extr_unload() { //unloads filament
 		lcd_update_enable(true);
 		#else //SNMM_V2
 
-		lcd_implementation_clear();
+		lcd_clear();
 		lcd_display_message_fullscreen_P(PSTR(""));
 		max_feedrate[E_AXIS] = 50;
-		lcd.setCursor(0, 0); lcd_printPGM(_T(MSG_UNLOADING_FILAMENT));
-		lcd.print(" ");
-		lcd.print(snmm_extruder + 1);
-		lcd.setCursor(0, 2); lcd_printPGM(_T(MSG_PLEASE_WAIT));
+		lcd_set_cursor(0, 0); lcd_puts_P(_T(MSG_UNLOADING_FILAMENT));
+		lcd_print(" ");
+		lcd_print(snmm_extruder + 1);
+		lcd_set_cursor(0, 2); lcd_puts_P(_T(MSG_PLEASE_WAIT));
 		if (current_position[Z_AXIS] < 15) {
 			current_position[Z_AXIS] += 15; //lifting in Z direction to make space for extrusion
 			plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS], 25, active_extruder);
@@ -5331,14 +5353,14 @@ void extr_unload() { //unloads filament
 	}
 	else {
 
-		lcd_implementation_clear();
-		lcd.setCursor(0, 0);
-		lcd_printPGM(_T(MSG_ERROR));
-		lcd.setCursor(0, 2);
-		lcd_printPGM(_T(MSG_PREHEAT_NOZZLE));
+		lcd_clear();
+		lcd_set_cursor(0, 0);
+		lcd_puts_P(_T(MSG_ERROR));
+		lcd_set_cursor(0, 2);
+		lcd_puts_P(_T(MSG_PREHEAT_NOZZLE));
 
 		delay(2000);
-		lcd_implementation_clear();
+		lcd_clear();
 	}
 	//lcd_return_to_status();
 }
@@ -5431,13 +5453,13 @@ void extr_unload_all() {
 		}
 	}
 	else {
-		lcd_implementation_clear();
-		lcd.setCursor(0, 0);
-		lcd_printPGM(_T(MSG_ERROR));
-		lcd.setCursor(0, 2);
-		lcd_printPGM(_T(MSG_PREHEAT_NOZZLE));
+		lcd_clear();
+		lcd_set_cursor(0, 0);
+		lcd_puts_P(_T(MSG_ERROR));
+		lcd_set_cursor(0, 2);
+		lcd_puts_P(_T(MSG_PREHEAT_NOZZLE));
 		delay(2000);
-		lcd_implementation_clear();
+		lcd_clear();
 		lcd_return_to_status();
 	}
 }
@@ -5455,13 +5477,13 @@ void extr_unload_used() {
 		snmm_filaments_used = 0;
 	}
 	else {
-		lcd_implementation_clear();
-		lcd.setCursor(0, 0);
-		lcd_printPGM(_T(MSG_ERROR));
-		lcd.setCursor(0, 2);
-		lcd_printPGM(_T(MSG_PREHEAT_NOZZLE));
+		lcd_clear();
+		lcd_set_cursor(0, 0);
+		lcd_puts_P(_T(MSG_ERROR));
+		lcd_set_cursor(0, 2);
+		lcd_puts_P(_T(MSG_PREHEAT_NOZZLE));
 		delay(2000);
-		lcd_implementation_clear();
+		lcd_clear();
 		lcd_return_to_status();
 	}
 }
@@ -5543,16 +5565,16 @@ static void lcd_farm_no()
 	int enc_dif = 0;
 	int _farmno = farm_no;
 	int _ret = 0;
-	lcd_implementation_clear();
+	lcd_clear();
 
-	lcd.setCursor(0, 0);
-	lcd.print("Farm no");
+	lcd_set_cursor(0, 0);
+	lcd_print("Farm no");
 
 	do
 	{
 
-		if (abs((enc_dif - encoderDiff)) > 2) {
-			if (enc_dif > encoderDiff) {
+		if (abs((enc_dif - lcd_encoder_diff)) > 2) {
+			if (enc_dif > lcd_encoder_diff) {
 				switch (step) {
 				case(0): if (_farmno >= 100) _farmno -= 100; break;
 				case(1): if (_farmno % 100 >= 10) _farmno -= 10; break;
@@ -5561,7 +5583,7 @@ static void lcd_farm_no()
 				}
 			}
 
-			if (enc_dif < encoderDiff) {
+			if (enc_dif < lcd_encoder_diff) {
 				switch (step) {
 				case(0): if (_farmno < 900) _farmno += 100; break;
 				case(1): if (_farmno % 100 < 90) _farmno += 10; break;
@@ -5570,20 +5592,20 @@ static void lcd_farm_no()
 				}
 			}
 			enc_dif = 0;
-			encoderDiff = 0;
+			lcd_encoder_diff = 0;
 		}
 
-		lcd.setCursor(0, 2);
-		if (_farmno < 100) lcd.print("0");
-		if (_farmno < 10) lcd.print("0");
-		lcd.print(_farmno);
-		lcd.print("  ");
-		lcd.setCursor(0, 3);
-		lcd.print("   ");
+		lcd_set_cursor(0, 2);
+		if (_farmno < 100) lcd_print("0");
+		if (_farmno < 10) lcd_print("0");
+		lcd_print(_farmno);
+		lcd_print("  ");
+		lcd_set_cursor(0, 3);
+		lcd_print("   ");
 
 
-		lcd.setCursor(step, 3);
-		lcd.print("^");
+		lcd_set_cursor(step, 3);
+		lcd_print("^");
 		delay(100);
 
 		if (lcd_clicked())
@@ -5618,30 +5640,30 @@ unsigned char lcd_choose_color() {
 	static int first = 0;
 	int enc_dif = 0;
 	unsigned char cursor_pos = 1;
-	enc_dif = encoderDiff;
-	lcd_implementation_clear();
-	lcd.setCursor(0, 1);
-	lcd.print(">");
+	enc_dif = lcd_encoder_diff;
+	lcd_clear();
+	lcd_set_cursor(0, 1);
+	lcd_print(">");
 
 	active_rows = items_no < 3 ? items_no : 3;
 
 	while (1) {
-		lcd_print_at_PGM(0, 0, PSTR("Choose color:"));
+		lcd_puts_at_P(0, 0, PSTR("Choose color:"));
 		for (int i = 0; i < active_rows; i++) {
-			lcd.setCursor(1, i+1);
-			lcd.print(item[first + i]);
+			lcd_set_cursor(1, i+1);
+			lcd_print(item[first + i]);
 		}
 
 		manage_heater();
 		manage_inactivity(true);
 		proc_commands();
-		if (abs((enc_dif - encoderDiff)) > 12) {
+		if (abs((enc_dif - lcd_encoder_diff)) > 12) {
 					
-				if (enc_dif > encoderDiff) {
+				if (enc_dif > lcd_encoder_diff) {
 					cursor_pos--;
 				}
 
-				if (enc_dif < encoderDiff) {
+				if (enc_dif < lcd_encoder_diff) {
 					cursor_pos++;
 				}
 				
@@ -5649,7 +5671,7 @@ unsigned char lcd_choose_color() {
 					cursor_pos = active_rows;
 					if (first < items_no - active_rows) {
 						first++;
-						lcd_implementation_clear();
+						lcd_clear();
 					}
 				}
 
@@ -5657,18 +5679,18 @@ unsigned char lcd_choose_color() {
 					cursor_pos = 1;
 					if (first > 0) {
 						first--;
-						lcd_implementation_clear();
+						lcd_clear();
 					}
 				}
-				lcd.setCursor(0, 1);
-				lcd.print(" ");
-				lcd.setCursor(0, 2);
-				lcd.print(" ");
-				lcd.setCursor(0, 3);
-				lcd.print(" ");
-				lcd.setCursor(0, cursor_pos);
-				lcd.print(">");
-				enc_dif = encoderDiff;
+				lcd_set_cursor(0, 1);
+				lcd_print(" ");
+				lcd_set_cursor(0, 2);
+				lcd_print(" ");
+				lcd_set_cursor(0, 3);
+				lcd_print(" ");
+				lcd_set_cursor(0, cursor_pos);
+				lcd_print(">");
+				enc_dif = lcd_encoder_diff;
 				delay(100);
 
 		}
@@ -5696,36 +5718,36 @@ void lcd_confirm_print()
 	int _ret = 0;
 	int _t = 0;
 
-	enc_dif = encoderDiff;
-	lcd_implementation_clear();
+	enc_dif = lcd_encoder_diff;
+	lcd_clear();
 
-	lcd.setCursor(0, 0);
-	lcd.print("Print ok ?");
+	lcd_set_cursor(0, 0);
+	lcd_print("Print ok ?");
 
 	do
 	{
-		if (abs(enc_dif - encoderDiff) > 12) {
-			if (enc_dif > encoderDiff) {
+		if (abs(enc_dif - lcd_encoder_diff) > 12) {
+			if (enc_dif > lcd_encoder_diff) {
 				cursor_pos--;
 			}
 
-			if (enc_dif < encoderDiff) {
+			if (enc_dif < lcd_encoder_diff) {
 				cursor_pos++;
 			}
-			enc_dif = encoderDiff;
+			enc_dif = lcd_encoder_diff;
 		}
 
 		if (cursor_pos > 2) { cursor_pos = 2; }
 		if (cursor_pos < 1) { cursor_pos = 1; }
 
-		lcd.setCursor(0, 2); lcd.print("          ");
-		lcd.setCursor(0, 3); lcd.print("          ");
-		lcd.setCursor(2, 2);
-		lcd_printPGM(_T(MSG_YES));
-		lcd.setCursor(2, 3);
-		lcd_printPGM(_T(MSG_NO));
-		lcd.setCursor(0, 1 + cursor_pos);
-		lcd.print(">");
+		lcd_set_cursor(0, 2); lcd_print("          ");
+		lcd_set_cursor(0, 3); lcd_print("          ");
+		lcd_set_cursor(2, 2);
+		lcd_puts_P(_T(MSG_YES));
+		lcd_set_cursor(2, 3);
+		lcd_puts_P(_T(MSG_NO));
+		lcd_set_cursor(0, 1 + cursor_pos);
+		lcd_print(">");
 		delay(100);
 
 		_t = _t + 1;
@@ -5779,7 +5801,6 @@ static void lcd_test_menu()
 static void lcd_main_menu()
 {
 
-  SDscrool = 0;
   MENU_BEGIN();
 
   // Majkl superawesome menu
@@ -5803,7 +5824,7 @@ static void lcd_main_menu()
     {
     
         int tempScrool = 0;
-        if (lcdDrawUpdate == 0 && LCD_CLICKED == 0)
+        if (lcd_draw_update == 0 && LCD_CLICKED == 0)
             //delay(100);
             return; // nothing to do (so don't thrash the SD card)
         uint16_t fileCnt = card.getnrfilenames();
@@ -5820,7 +5841,7 @@ static void lcd_main_menu()
         
         for (uint16_t i = 0; i < fileCnt; i++)
         {
-            if (_menuItemNr == _lineNr)
+            if (menu_item == menu_line)
             {
 #ifndef SDCARD_RATHERRECENTFIRST
                 card.getfilename(i);
@@ -5935,9 +5956,6 @@ static void lcd_main_menu()
 	MENU_ITEM_SUBMENU_P(_T(MSG_SETTINGS), lcd_settings_menu);
     if(!isPrintPaused) MENU_ITEM_SUBMENU_P(_T(MSG_MENU_CALIBRATION), lcd_calibration_menu);
 
-#ifdef EXPERIMENTAL_FEATURES
-	MENU_ITEM_SUBMENU_P(PSTR("Experimantal"), lcd_experimantal_menu);
-#endif //EXPERIMENTAL_FEATURES
   }
 
   if (!is_usb_printing && (lcd_commands_type != LCD_COMMAND_V2_CAL))
@@ -5951,7 +5969,7 @@ static void lcd_main_menu()
 
   MENU_ITEM_SUBMENU_P(_i("Support"), lcd_support_menu);////MSG_SUPPORT c=0 r=0
 
-  MENU_ITEM_SUBMENU_P(_i("W25x20CL init"), lcd_test_menu);////MSG_SUPPORT c=0 r=0
+//  MENU_ITEM_SUBMENU_P(_i("W25x20CL init"), lcd_test_menu);////MSG_SUPPORT c=0 r=0
 
   MENU_END();
 
@@ -6024,7 +6042,7 @@ static void lcd_colorprint_change() {
 	custom_message_type = 2; //just print status message
 	lcd_setstatuspgm(_T(MSG_FINISHING_MOVEMENTS));
 	lcd_return_to_status();
-	lcdDrawUpdate = 3;
+	lcd_draw_update = 3;
 }
 
 static void lcd_tune_menu()
@@ -6045,13 +6063,13 @@ static void lcd_tune_menu()
 
 	MENU_BEGIN();
 	MENU_ITEM_BACK_P(_T(MSG_MAIN)); //1
-	MENU_ITEM_EDIT(int3, _i("Speed"), &feedmultiply, 10, 999);//2////MSG_SPEED c=0 r=0
+	MENU_ITEM_EDIT_int3_P(_i("Speed"), &feedmultiply, 10, 999);//2////MSG_SPEED c=0 r=0
 
-	MENU_ITEM_EDIT(int3, _T(MSG_NOZZLE), &target_temperature[0], 0, HEATER_0_MAXTEMP - 10);//3
-	MENU_ITEM_EDIT(int3, _T(MSG_BED), &target_temperature_bed, 0, BED_MAXTEMP - 10);//4
+	MENU_ITEM_EDIT_int3_P(_T(MSG_NOZZLE), &target_temperature[0], 0, HEATER_0_MAXTEMP - 10);//3
+	MENU_ITEM_EDIT_int3_P(_T(MSG_BED), &target_temperature_bed, 0, BED_MAXTEMP - 10);//4
 
-	MENU_ITEM_EDIT(int3, _T(MSG_FAN_SPEED), &fanSpeed, 0, 255);//5
-	MENU_ITEM_EDIT(int3, _i("Flow"), &extrudemultiply, 10, 999);//6////MSG_FLOW c=0 r=0
+	MENU_ITEM_EDIT_int3_P(_T(MSG_FAN_SPEED), &fanSpeed, 0, 255);//5
+	MENU_ITEM_EDIT_int3_P(_i("Flow"), &extrudemultiply, 10, 999);//6////MSG_FLOW c=0 r=0
 #ifdef FILAMENTCHANGEENABLE
 	MENU_ITEM_FUNCTION_P(_T(MSG_FILAMENTCHANGE), lcd_colorprint_change);//7
 #endif
@@ -6110,19 +6128,20 @@ static void lcd_control_temperature_menu()
   MENU_BEGIN();
   MENU_ITEM_BACK_P(_T(MSG_SETTINGS));
 #if TEMP_SENSOR_0 != 0
-  MENU_ITEM_EDIT(int3, _T(MSG_NOZZLE), &target_temperature[0], 0, HEATER_0_MAXTEMP - 10);
+  MENU_ITEM_EDIT_int3_P(_T(MSG_NOZZLE), &target_temperature[0], 0, HEATER_0_MAXTEMP - 10);
 #endif
 #if TEMP_SENSOR_1 != 0
-  MENU_ITEM_EDIT(int3, _i("Nozzle2"), &target_temperature[1], 0, HEATER_1_MAXTEMP - 10);////MSG_NOZZLE1 c=0 r=0
+  MENU_ITEM_EDIT_int3_P(_i("Nozzle2"), &target_temperature[1], 0, HEATER_1_MAXTEMP - 10);////MSG_NOZZLE1 c=0 r=0
 #endif
 #if TEMP_SENSOR_2 != 0
-  MENU_ITEM_EDIT(int3, _i("Nozzle3"), &target_temperature[2], 0, HEATER_2_MAXTEMP - 10);////MSG_NOZZLE2 c=0 r=0
+  MENU_ITEM_EDIT_int3_P(_i("Nozzle3"), &target_temperature[2], 0, HEATER_2_MAXTEMP - 10);////MSG_NOZZLE2 c=0 r=0
 #endif
 #if TEMP_SENSOR_BED != 0
-  MENU_ITEM_EDIT(int3, _T(MSG_BED), &target_temperature_bed, 0, BED_MAXTEMP - 3);
+  MENU_ITEM_EDIT_int3_P(_T(MSG_BED), &target_temperature_bed, 0, BED_MAXTEMP - 3);
 #endif
-  MENU_ITEM_EDIT(int3, _T(MSG_FAN_SPEED), &fanSpeed, 0, 255);
+  MENU_ITEM_EDIT_int3_P(_T(MSG_FAN_SPEED), &fanSpeed, 0, 255);
 #if defined AUTOTEMP && (TEMP_SENSOR_0 != 0)
+//MENU_ITEM_EDIT removed, following code must be redesigned if AUTOTEMP enabled
   MENU_ITEM_EDIT(bool, MSG_AUTOTEMP, &autotemp_enabled);
   MENU_ITEM_EDIT(float3, _i(" \002 Min"), &autotemp_min, 0, HEATER_0_MAXTEMP - 10);////MSG_MIN c=0 r=0
   MENU_ITEM_EDIT(float3, _i(" \002 Max"), &autotemp_max, 0, HEATER_0_MAXTEMP - 10);////MSG_MAX c=0 r=0
@@ -6137,14 +6156,13 @@ static void lcd_control_temperature_menu()
 static void lcd_sd_refresh()
 {
   card.initsd();
-  currentMenuViewOffset = 0;
+  menu_top = 0;
 }
 #endif
 static void lcd_sd_updir()
 {
-  SDscrool = 0;
   card.updir();
-  currentMenuViewOffset = 0;
+  menu_top = 0;
 }
 
 void lcd_print_stop() {
@@ -6185,74 +6203,44 @@ void lcd_print_stop() {
 void lcd_sdcard_stop()
 {
 	
-	lcd.setCursor(0, 0);
-	lcd_printPGM(_T(MSG_STOP_PRINT));
-	lcd.setCursor(2, 2);
-	lcd_printPGM(_T(MSG_NO));
-	lcd.setCursor(2, 3);
-	lcd_printPGM(_T(MSG_YES));
-	lcd.setCursor(0, 2); lcd.print(" ");
-	lcd.setCursor(0, 3); lcd.print(" ");
-
-	if ((int32_t)encoderPosition > 2) { encoderPosition = 2; }
-	if ((int32_t)encoderPosition < 1) { encoderPosition = 1; }
+	lcd_set_cursor(0, 0);
+	lcd_puts_P(_T(MSG_STOP_PRINT));
+	lcd_set_cursor(2, 2);
+	lcd_puts_P(_T(MSG_NO));
+	lcd_set_cursor(2, 3);
+	lcd_puts_P(_T(MSG_YES));
+	lcd_set_cursor(0, 2); lcd_print(" ");
+	lcd_set_cursor(0, 3); lcd_print(" ");
+
+	if ((int32_t)lcd_encoder > 2) { lcd_encoder = 2; }
+	if ((int32_t)lcd_encoder < 1) { lcd_encoder = 1; }
 	
-	lcd.setCursor(0, 1 + encoderPosition);
-	lcd.print(">");
+	lcd_set_cursor(0, 1 + lcd_encoder);
+	lcd_print(">");
 
 	if (lcd_clicked())
 	{
-		if ((int32_t)encoderPosition == 1)
+		if ((int32_t)lcd_encoder == 1)
 		{
 			lcd_return_to_status();
 		}
-		if ((int32_t)encoderPosition == 2)
+		if ((int32_t)lcd_encoder == 2)
 		{
 			lcd_print_stop();
 		}
 	}
 
 }
-/*
-void getFileDescription(char *name, char *description) {
-	// get file description, ie the REAL filenam, ie the second line
-	card.openFile(name, true);
-	int i = 0;
-	// skip the first line (which is the version line)
-	while (true) {
-		uint16_t readByte = card.get();
-		if (readByte == '\n') {
-			break;
-		}
-	}
-	// read the second line (which is the description line)
-	while (true) {
-		uint16_t readByte = card.get();
-		if (i == 0) {
-			// skip the first '^'
-			readByte = card.get();
-		}
-		description[i] = readByte;
-		i++;
-		if (readByte == '\n') {
-			break;
-		}
-	}
-	card.closefile();
-	description[i-1] = 0;
-}
-*/
 
 void lcd_sdcard_menu()
 {
-  printf_P(_N("menu sd\n"));
   uint8_t sdSort = eeprom_read_byte((uint8_t*)EEPROM_SD_SORT);
   int tempScrool = 0;
   if (presort_flag == true) {
 	  presort_flag = false;
 	  card.presort();
   }
-  if (lcdDrawUpdate == 0 && LCD_CLICKED == 0)
+  if (lcd_draw_update == 0 && LCD_CLICKED == 0)
     //delay(100);
     return; // nothing to do (so don't thrash the SD card)
   uint16_t fileCnt = card.getnrfilenames();
@@ -6265,191 +6253,39 @@ void lcd_sdcard_menu()
   {
 #if SDCARDDETECT == -1
     MENU_ITEM_FUNCTION_P(_T(MSG_REFRESH), lcd_sd_refresh);
-#endif
-  } else {
-    MENU_ITEM_FUNCTION_P(PSTR(LCD_STR_FOLDER ".."), lcd_sd_updir);
-  }
-
-  for (uint16_t i = 0; i < fileCnt; i++)
-  {
-    if (_menuItemNr == _lineNr)
-    {
-		const uint16_t nr = ((sdSort == SD_SORT_NONE) || farm_mode || (sdSort == SD_SORT_TIME)) ? (fileCnt - 1 - i) : i;
-		/*#ifdef SDCARD_RATHERRECENTFIRST
-			#ifndef SDCARD_SORT_ALPHA
-				fileCnt - 1 -
-			#endif
-		#endif
-		i;*/
-		#ifdef SDCARD_SORT_ALPHA
-			if (sdSort == SD_SORT_NONE) card.getfilename(nr);
-			else card.getfilename_sorted(nr);
-		#else
-			 card.getfilename(nr);
-		#endif
-			
-		if (card.filenameIsDir)
-			MENU_ITEM_SDDIR(_T(MSG_CARD_MENU), card.filename, card.longFilename);
-		else
-			MENU_ITEM_SDFILE(_T(MSG_CARD_MENU), card.filename, card.longFilename);
-    } else {
-      MENU_ITEM_DUMMY();
-    }
-  }
-  MENU_END();
-}
-
-//char description [10] [31];
-
-/*void get_description() {
-	uint16_t fileCnt = card.getnrfilenames();
-	for (uint16_t i = 0; i < fileCnt; i++)
-	{
-		card.getfilename(fileCnt - 1 - i);
-		getFileDescription(card.filename, description[i]);
-	}
-}*/
-
-/*void lcd_farm_sdcard_menu() 
-{
-	static int i = 0;
-	if (i == 0) {
-		get_description();
-		i++;
-	}
-		//int j;
-		//char description[31];
-		int tempScrool = 0;
-		if (lcdDrawUpdate == 0 && LCD_CLICKED == 0)
-			//delay(100);
-			return; // nothing to do (so don't thrash the SD card)
-		uint16_t fileCnt = card.getnrfilenames();
-
-		MENU_BEGIN();
-		MENU_ITEM_BACK_P(_T(MSG_MAIN));
-		card.getWorkDirName();
-		if (card.filename[0] == '/')
-		{
-#if SDCARDDETECT == -1
-			MENU_ITEM_FUNCTION_P(_T(MSG_REFRESH), lcd_sd_refresh);
-#endif
-		}
-		else {
-			MENU_ITEM_FUNCTION_P(PSTR(LCD_STR_FOLDER ".."), lcd_sd_updir);
-		}
-
-
-
-		for (uint16_t i = 0; i < fileCnt; i++)
-		{
-			if (_menuItemNr == _lineNr)
-			{
-#ifndef SDCARD_RATHERRECENTFIRST
-				card.getfilename(i);
-#else
-				card.getfilename(fileCnt - 1 - i);
-#endif
-				if (card.filenameIsDir)
-				{
-					MENU_ITEM_SDDIR(_T(MSG_CARD_MENU), card.filename, card.longFilename);
-				}
-				else {
-					
-					MENU_ITEM_SDFILE(_T(MSG_CARD_MENU), card.filename, description[i]);
-				}
-			}
-			else {
-				MENU_ITEM_DUMMY();
-			}
-		}
-		MENU_END();
-
-}*/
-
-#define menu_edit_type(_type, _name, _strFunc, scale) \
-  void menu_edit_ ## _name () \
-  { \
-    if ((int32_t)encoderPosition < 0) encoderPosition = 0; \
-    if ((int32_t)encoderPosition > menuData.editMenuParentState.maxEditValue) encoderPosition = menuData.editMenuParentState.maxEditValue; \
-    if (lcdDrawUpdate) \
-      lcd_implementation_drawedit(menuData.editMenuParentState.editLabel, _strFunc(((_type)((int32_t)encoderPosition + menuData.editMenuParentState.minEditValue)) / scale)); \
-    if (LCD_CLICKED) \
-    { \
-      *((_type*)menuData.editMenuParentState.editValue) = ((_type)((int32_t)encoderPosition + menuData.editMenuParentState.minEditValue)) / scale; \
-      lcd_goto_menu(menuData.editMenuParentState.prevMenu, menuData.editMenuParentState.prevEncoderPosition, true, false); \
-    } \
-  } \
-  static void menu_action_setting_edit_ ## _name (const char* pstr, _type* ptr, _type minValue, _type maxValue) \
-  { \
-    asm("cli"); \
-	menuData.editMenuParentState.prevMenu = currentMenu; \
-    menuData.editMenuParentState.prevEncoderPosition = encoderPosition; \
-    asm("sei"); \
-    \
-    lcdDrawUpdate = 2; \
-    menuData.editMenuParentState.editLabel = pstr; \
-    menuData.editMenuParentState.editValue = ptr; \
-    menuData.editMenuParentState.minEditValue = minValue * scale; \
-    menuData.editMenuParentState.maxEditValue = maxValue * scale - menuData.editMenuParentState.minEditValue; \
-    lcd_goto_menu(menu_edit_ ## _name, (*ptr) * scale - menuData.editMenuParentState.minEditValue, true, false); \
-    \
-  }\
-  /*
-  void menu_edit_callback_ ## _name () { \
-    menu_edit_ ## _name (); \
-    if (LCD_CLICKED) (*callbackFunc)(); \
-  } \
-  static void menu_action_setting_edit_callback_ ## _name (const char* pstr, _type* ptr, _type minValue, _type maxValue, menuFunc_t callback) \
-  { \
-    menuData.editMenuParentState.prevMenu = currentMenu; \
-    menuData.editMenuParentState.prevEncoderPosition = encoderPosition; \
-    \
-    lcdDrawUpdate = 2; \
-    lcd_goto_menu(menu_edit_callback_ ## _name, (*ptr) * scale - menuData.editMenuParentState.minEditValue, true, false); \
-    \
-    menuData.editMenuParentState.editLabel = pstr; \
-    menuData.editMenuParentState.editValue = ptr; \
-    menuData.editMenuParentState.minEditValue = minValue * scale; \
-    menuData.editMenuParentState.maxEditValue = maxValue * scale - menuData.editMenuParentState.minEditValue; \
-    callbackFunc = callback;\
+#endif
+  } else {
+    MENU_ITEM_FUNCTION_P(PSTR(LCD_STR_FOLDER ".."), lcd_sd_updir);
   }
-  */
-
 
-#ifdef TMC2130
-extern char conv[8];
-// Convert tmc2130 mres to string 
-char *mres_to_str3(const uint8_t &x)
-{
-	return itostr3(256 >> x);
+  for (uint16_t i = 0; i < fileCnt; i++)
+  {
+    if (menu_item == menu_line)
+    {
+		const uint16_t nr = ((sdSort == SD_SORT_NONE) || farm_mode || (sdSort == SD_SORT_TIME)) ? (fileCnt - 1 - i) : i;
+		/*#ifdef SDCARD_RATHERRECENTFIRST
+			#ifndef SDCARD_SORT_ALPHA
+				fileCnt - 1 -
+			#endif
+		#endif
+		i;*/
+		#ifdef SDCARD_SORT_ALPHA
+			if (sdSort == SD_SORT_NONE) card.getfilename(nr);
+			else card.getfilename_sorted(nr);
+		#else
+			 card.getfilename(nr);
+		#endif
+			
+		if (card.filenameIsDir)
+			MENU_ITEM_SDDIR(_T(MSG_CARD_MENU), card.filename, card.longFilename);
+		else
+			MENU_ITEM_SDFILE(_T(MSG_CARD_MENU), card.filename, card.longFilename);
+    } else {
+      MENU_ITEM_DUMMY();
+    }
+  }
+  MENU_END();
 }
-menu_edit_type(uint8_t, mres, mres_to_str3, 1)
-// Convert tmc2130 wfac to string 
-char *wfac_to_str5(const uint8_t &x)
-{
-	if (x >= TMC2130_WAVE_FAC1000_MIN)
-	    {
-	    conv[0] = '[';
-	    ftostr43(((float)((uint16_t)x + 1000) / 1000), 1);
-	    }
-	else strncpy_P(conv, _i("  [off"), 6);////MSG_EXTRUDER_CORRECTION_OFF c=6 r=0
-	conv[6] = ']';
-	conv[7] = ' ';
-	conv[8] = 0;
-	return conv;
-}
-menu_edit_type(uint8_t, wfac, wfac_to_str5, 1)
-#endif //TMC2130
-
-menu_edit_type(uint8_t, byte3, itostr3, 1)
-menu_edit_type(int, int3, itostr3, 1)
-menu_edit_type(float, float3, ftostr3, 1)
-menu_edit_type(float, float32, ftostr32, 100)
-menu_edit_type(float, float43, ftostr43, 1000)
-menu_edit_type(float, float5, ftostr5, 0.01)
-menu_edit_type(float, float51, ftostr51, 10)
-menu_edit_type(float, float52, ftostr52, 100)
-menu_edit_type(unsigned long, long5, ftostr5, 0.01)
 
 static void lcd_selftest_v()
 {
@@ -6461,8 +6297,8 @@ bool lcd_selftest()
 	int _progress = 0;
 	bool _result = true;
 	lcd_wait_for_cool_down();
-	lcd_implementation_clear();
-	lcd.setCursor(0, 0); lcd_printPGM(_i("Self test start  "));////MSG_SELFTEST_START c=20 r=0
+	lcd_clear();
+	lcd_set_cursor(0, 0); lcd_puts_P(_i("Self test start  "));////MSG_SELFTEST_START c=20 r=0
 	#ifdef TMC2130
 	  FORCE_HIGH_POWER_START;
 	#endif // TMC2130
@@ -6620,7 +6456,7 @@ bool lcd_selftest()
 	}
 	lcd_reset_alert_level();
 	enquecommand_P(PSTR("M84"));
-	lcd_implementation_clear();
+	lcd_clear();
 	lcd_next_update_millis = millis() + LCD_UPDATE_INTERVAL;
 	
 	if (_result)
@@ -7044,110 +6880,110 @@ static bool lcd_selfcheck_check_heater(bool _isbed)
 }
 static void lcd_selftest_error(int _error_no, const char *_error_1, const char *_error_2)
 {
-	lcd_implementation_quick_feedback();
+	lcd_beeper_quick_feedback();
 
 	target_temperature[0] = 0;
 	target_temperature_bed = 0;
 	manage_heater();
 	manage_inactivity();
 
-	lcd_implementation_clear();
+	lcd_clear();
 
-	lcd.setCursor(0, 0);
-	lcd_printPGM(_i("Selftest error !"));////MSG_SELFTEST_ERROR c=0 r=0
-	lcd.setCursor(0, 1);
-	lcd_printPGM(_i("Please check :"));////MSG_SELFTEST_PLEASECHECK c=0 r=0
+	lcd_set_cursor(0, 0);
+	lcd_puts_P(_i("Selftest error !"));////MSG_SELFTEST_ERROR c=0 r=0
+	lcd_set_cursor(0, 1);
+	lcd_puts_P(_i("Please check :"));////MSG_SELFTEST_PLEASECHECK c=0 r=0
 
 	switch (_error_no)
 	{
 	case 1:
-		lcd.setCursor(0, 2);
-		lcd_printPGM(_i("Heater/Thermistor"));////MSG_SELFTEST_HEATERTHERMISTOR c=0 r=0
-		lcd.setCursor(0, 3);
-		lcd_printPGM(_i("Not connected"));////MSG_SELFTEST_NOTCONNECTED c=0 r=0
+		lcd_set_cursor(0, 2);
+		lcd_puts_P(_i("Heater/Thermistor"));////MSG_SELFTEST_HEATERTHERMISTOR c=0 r=0
+		lcd_set_cursor(0, 3);
+		lcd_puts_P(_i("Not connected"));////MSG_SELFTEST_NOTCONNECTED c=0 r=0
 		break;
 	case 2:
-		lcd.setCursor(0, 2);
-		lcd_printPGM(_i("Bed / Heater"));////MSG_SELFTEST_BEDHEATER c=0 r=0
-		lcd.setCursor(0, 3);
-		lcd_printPGM(_T(MSG_SELFTEST_WIRINGERROR));
+		lcd_set_cursor(0, 2);
+		lcd_puts_P(_i("Bed / Heater"));////MSG_SELFTEST_BEDHEATER c=0 r=0
+		lcd_set_cursor(0, 3);
+		lcd_puts_P(_T(MSG_SELFTEST_WIRINGERROR));
 		break;
 	case 3:
-		lcd.setCursor(0, 2);
-		lcd_printPGM(_i("Endstops"));////MSG_SELFTEST_ENDSTOPS c=0 r=0
-		lcd.setCursor(0, 3);
-		lcd_printPGM(_T(MSG_SELFTEST_WIRINGERROR));
-		lcd.setCursor(17, 3);
-		lcd.print(_error_1);
+		lcd_set_cursor(0, 2);
+		lcd_puts_P(_i("Endstops"));////MSG_SELFTEST_ENDSTOPS c=0 r=0
+		lcd_set_cursor(0, 3);
+		lcd_puts_P(_T(MSG_SELFTEST_WIRINGERROR));
+		lcd_set_cursor(17, 3);
+		lcd_print(_error_1);
 		break;
 	case 4:
-		lcd.setCursor(0, 2);
-		lcd_printPGM(_T(MSG_SELFTEST_MOTOR));
-		lcd.setCursor(18, 2);
-		lcd.print(_error_1);
-		lcd.setCursor(0, 3);
-		lcd_printPGM(_i("Endstop"));////MSG_SELFTEST_ENDSTOP c=0 r=0
-		lcd.setCursor(18, 3);
-		lcd.print(_error_2);
+		lcd_set_cursor(0, 2);
+		lcd_puts_P(_T(MSG_SELFTEST_MOTOR));
+		lcd_set_cursor(18, 2);
+		lcd_print(_error_1);
+		lcd_set_cursor(0, 3);
+		lcd_puts_P(_i("Endstop"));////MSG_SELFTEST_ENDSTOP c=0 r=0
+		lcd_set_cursor(18, 3);
+		lcd_print(_error_2);
 		break;
 	case 5:
-		lcd.setCursor(0, 2);
-		lcd_printPGM(_i("Endstop not hit"));////MSG_SELFTEST_ENDSTOP_NOTHIT c=20 r=1
-		lcd.setCursor(0, 3);
-		lcd_printPGM(_T(MSG_SELFTEST_MOTOR));
-		lcd.setCursor(18, 3);
-		lcd.print(_error_1);
+		lcd_set_cursor(0, 2);
+		lcd_puts_P(_i("Endstop not hit"));////MSG_SELFTEST_ENDSTOP_NOTHIT c=20 r=1
+		lcd_set_cursor(0, 3);
+		lcd_puts_P(_T(MSG_SELFTEST_MOTOR));
+		lcd_set_cursor(18, 3);
+		lcd_print(_error_1);
 		break;
 	case 6:
-		lcd.setCursor(0, 2);
-		lcd_printPGM(_T(MSG_SELFTEST_COOLING_FAN));
-		lcd.setCursor(0, 3);
-		lcd_printPGM(_T(MSG_SELFTEST_WIRINGERROR));
-		lcd.setCursor(18, 3);
-		lcd.print(_error_1);
+		lcd_set_cursor(0, 2);
+		lcd_puts_P(_T(MSG_SELFTEST_COOLING_FAN));
+		lcd_set_cursor(0, 3);
+		lcd_puts_P(_T(MSG_SELFTEST_WIRINGERROR));
+		lcd_set_cursor(18, 3);
+		lcd_print(_error_1);
 		break;
 	case 7:
-		lcd.setCursor(0, 2);
-		lcd_printPGM(_T(MSG_SELFTEST_EXTRUDER_FAN));
-		lcd.setCursor(0, 3);
-		lcd_printPGM(_T(MSG_SELFTEST_WIRINGERROR));
-		lcd.setCursor(18, 3);
-		lcd.print(_error_1);
+		lcd_set_cursor(0, 2);
+		lcd_puts_P(_T(MSG_SELFTEST_EXTRUDER_FAN));
+		lcd_set_cursor(0, 3);
+		lcd_puts_P(_T(MSG_SELFTEST_WIRINGERROR));
+		lcd_set_cursor(18, 3);
+		lcd_print(_error_1);
 		break;
 	case 8:
-		lcd.setCursor(0, 2);
-		lcd_printPGM(_i("Loose pulley"));////MSG_LOOSE_PULLEY c=20 r=1
-		lcd.setCursor(0, 3);
-		lcd_printPGM(_T(MSG_SELFTEST_MOTOR));
-		lcd.setCursor(18, 3);
-		lcd.print(_error_1);
+		lcd_set_cursor(0, 2);
+		lcd_puts_P(_i("Loose pulley"));////MSG_LOOSE_PULLEY c=20 r=1
+		lcd_set_cursor(0, 3);
+		lcd_puts_P(_T(MSG_SELFTEST_MOTOR));
+		lcd_set_cursor(18, 3);
+		lcd_print(_error_1);
 		break;
 	case 9:
-		lcd.setCursor(0, 2);
-		lcd_printPGM(_i("Axis length"));////MSG_SELFTEST_AXIS_LENGTH c=0 r=0
-		lcd.setCursor(0, 3);
-		lcd_printPGM(_i("Axis"));////MSG_SELFTEST_AXIS c=0 r=0
-		lcd.setCursor(18, 3);
-		lcd.print(_error_1);
+		lcd_set_cursor(0, 2);
+		lcd_puts_P(_i("Axis length"));////MSG_SELFTEST_AXIS_LENGTH c=0 r=0
+		lcd_set_cursor(0, 3);
+		lcd_puts_P(_i("Axis"));////MSG_SELFTEST_AXIS c=0 r=0
+		lcd_set_cursor(18, 3);
+		lcd_print(_error_1);
 		break;
 	case 10:
-		lcd.setCursor(0, 2);
-		lcd_printPGM(_i("Front/left fans"));////MSG_SELFTEST_FANS c=0 r=0
-		lcd.setCursor(0, 3);
-		lcd_printPGM(_i("Swapped"));////MSG_SELFTEST_SWAPPED c=0 r=0
-		lcd.setCursor(18, 3);
-		lcd.print(_error_1);
+		lcd_set_cursor(0, 2);
+		lcd_puts_P(_i("Front/left fans"));////MSG_SELFTEST_FANS c=0 r=0
+		lcd_set_cursor(0, 3);
+		lcd_puts_P(_i("Swapped"));////MSG_SELFTEST_SWAPPED c=0 r=0
+		lcd_set_cursor(18, 3);
+		lcd_print(_error_1);
 		break;
 	case 11: 
-		lcd.setCursor(0, 2);
-		lcd_printPGM(_i("Filament sensor"));////MSG_FILAMENT_SENSOR c=20 r=0
-		lcd.setCursor(0, 3);
-		lcd_printPGM(_T(MSG_SELFTEST_WIRINGERROR));
+		lcd_set_cursor(0, 2);
+		lcd_puts_P(_i("Filament sensor"));////MSG_FILAMENT_SENSOR c=20 r=0
+		lcd_set_cursor(0, 3);
+		lcd_puts_P(_T(MSG_SELFTEST_WIRINGERROR));
 		break;
 	}
 
 	delay(1000);
-	lcd_implementation_quick_feedback();
+	lcd_beeper_quick_feedback();
 
 	do {
 		delay(100);
@@ -7176,39 +7012,39 @@ static bool lcd_selftest_manual_fan_check(int _fan, bool check_opposite)
 {
 
 	bool _result = check_opposite;
-	lcd_implementation_clear();
+	lcd_clear();
 
-	lcd.setCursor(0, 0); lcd_printPGM(_T(MSG_SELFTEST_FAN));
+	lcd_set_cursor(0, 0); lcd_puts_P(_T(MSG_SELFTEST_FAN));
 	
 	switch (_fan)
 	{
 	case 0:
 		// extruder cooling fan
-		lcd.setCursor(0, 1); 
-		if(check_opposite == true) lcd_printPGM(_T(MSG_SELFTEST_COOLING_FAN)); 
-		else lcd_printPGM(_T(MSG_SELFTEST_EXTRUDER_FAN));
+		lcd_set_cursor(0, 1); 
+		if(check_opposite == true) lcd_puts_P(_T(MSG_SELFTEST_COOLING_FAN)); 
+		else lcd_puts_P(_T(MSG_SELFTEST_EXTRUDER_FAN));
 		SET_OUTPUT(EXTRUDER_0_AUTO_FAN_PIN);
 		WRITE(EXTRUDER_0_AUTO_FAN_PIN, 1);
 		break;
 	case 1:
 		// object cooling fan
-		lcd.setCursor(0, 1);
-		if (check_opposite == true) lcd_printPGM(_T(MSG_SELFTEST_EXTRUDER_FAN));
-		else lcd_printPGM(_T(MSG_SELFTEST_COOLING_FAN));
+		lcd_set_cursor(0, 1);
+		if (check_opposite == true) lcd_puts_P(_T(MSG_SELFTEST_EXTRUDER_FAN));
+		else lcd_puts_P(_T(MSG_SELFTEST_COOLING_FAN));
 		SET_OUTPUT(FAN_PIN);
 		analogWrite(FAN_PIN, 255);
 		break;
 	}
 	delay(500);
 
-	lcd.setCursor(1, 2); lcd_printPGM(_T(MSG_SELFTEST_FAN_YES));
-	lcd.setCursor(0, 3); lcd.print(">");
-	lcd.setCursor(1, 3); lcd_printPGM(_T(MSG_SELFTEST_FAN_NO));
+	lcd_set_cursor(1, 2); lcd_puts_P(_T(MSG_SELFTEST_FAN_YES));
+	lcd_set_cursor(0, 3); lcd_print(">");
+	lcd_set_cursor(1, 3); lcd_puts_P(_T(MSG_SELFTEST_FAN_NO));
 
 	int8_t enc_dif = 0;
 	KEEPALIVE_STATE(PAUSED_FOR_USER);
 
-	button_pressed = false; 
+	lcd_button_pressed = false; 
 	do
 	{
 		switch (_fan)
@@ -7225,24 +7061,24 @@ static bool lcd_selftest_manual_fan_check(int _fan, bool check_opposite)
 			break;
 		}
 
-		if (abs((enc_dif - encoderDiff)) > 2) {
-			if (enc_dif > encoderDiff) {
+		if (abs((enc_dif - lcd_encoder_diff)) > 2) {
+			if (enc_dif > lcd_encoder_diff) {
 				_result = !check_opposite;
-				lcd.setCursor(0, 2); lcd.print(">");
-				lcd.setCursor(1, 2); lcd_printPGM(_T(MSG_SELFTEST_FAN_YES));
-				lcd.setCursor(0, 3); lcd.print(" ");
-				lcd.setCursor(1, 3); lcd_printPGM(_T(MSG_SELFTEST_FAN_NO));
+				lcd_set_cursor(0, 2); lcd_print(">");
+				lcd_set_cursor(1, 2); lcd_puts_P(_T(MSG_SELFTEST_FAN_YES));
+				lcd_set_cursor(0, 3); lcd_print(" ");
+				lcd_set_cursor(1, 3); lcd_puts_P(_T(MSG_SELFTEST_FAN_NO));
 			}
 
-			if (enc_dif < encoderDiff) {
+			if (enc_dif < lcd_encoder_diff) {
 				_result = check_opposite;
-				lcd.setCursor(0, 2); lcd.print(" ");
-				lcd.setCursor(1, 2); lcd_printPGM(_T(MSG_SELFTEST_FAN_YES));
-				lcd.setCursor(0, 3); lcd.print(">");
-				lcd.setCursor(1, 3); lcd_printPGM(_T(MSG_SELFTEST_FAN_NO));
+				lcd_set_cursor(0, 2); lcd_print(" ");
+				lcd_set_cursor(1, 2); lcd_puts_P(_T(MSG_SELFTEST_FAN_YES));
+				lcd_set_cursor(0, 3); lcd_print(">");
+				lcd_set_cursor(1, 3); lcd_puts_P(_T(MSG_SELFTEST_FAN_NO));
 			}
 			enc_dif = 0;
-			encoderDiff = 0;
+			lcd_encoder_diff = 0;
 		}
 
 
@@ -7288,11 +7124,11 @@ static bool lcd_selftest_fan_dialog(int _fan)
 		fanSpeed = 150;				//print fan
 		for (uint8_t i = 0; i < 5; i++) {
 			delay_keep_alive(1000);
-			lcd.setCursor(18, 3);
-			lcd.print("-");
+			lcd_set_cursor(18, 3);
+			lcd_print("-");
 			delay_keep_alive(1000);
-			lcd.setCursor(18, 3);
-			lcd.print("|");
+			lcd_set_cursor(18, 3);
+			lcd_print("|");
 		}
 		fanSpeed = 0;
 		manage_heater();			//turn off fan
@@ -7335,44 +7171,44 @@ static int lcd_selftest_screen(int _step, int _progress, int _progress_scale, bo
 	int _step_block = 0;
 	const char *_indicator = (_progress > _progress_scale) ? "-" : "|";
 
-	if (_clear) lcd_implementation_clear();
-
-
-	lcd.setCursor(0, 0);
-
-	if (_step == -1) lcd_printPGM(_T(MSG_SELFTEST_FAN));
-	if (_step == 0) lcd_printPGM(_T(MSG_SELFTEST_FAN));
-	if (_step == 1) lcd_printPGM(_T(MSG_SELFTEST_FAN));
-	if (_step == 2) lcd_printPGM(_i("Checking endstops"));////MSG_SELFTEST_CHECK_ENDSTOPS c=20 r=0
-	if (_step == 3) lcd_printPGM(_i("Checking hotend  "));////MSG_SELFTEST_CHECK_HOTEND c=20 r=0
-	if (_step == 4) lcd_printPGM(_i("Checking X axis  "));////MSG_SELFTEST_CHECK_X c=20 r=0
-	if (_step == 5) lcd_printPGM(_i("Checking Y axis  "));////MSG_SELFTEST_CHECK_Y c=20 r=0
-	if (_step == 6) lcd_printPGM(_i("Checking Z axis  "));////MSG_SELFTEST_CHECK_Z c=20 r=0
-	if (_step == 7) lcd_printPGM(_T(MSG_SELFTEST_CHECK_BED));
-	if (_step == 8) lcd_printPGM(_T(MSG_SELFTEST_CHECK_BED));
-	if (_step == 9) lcd_printPGM(_T(MSG_SELFTEST_CHECK_FSENSOR));
-	if (_step == 10) lcd_printPGM(_T(MSG_SELFTEST_CHECK_FSENSOR));
-	if (_step == 11) lcd_printPGM(_i("All correct      "));////MSG_SELFTEST_CHECK_ALLCORRECT c=20 r=0
-	if (_step == 12) lcd_printPGM(_T(MSG_SELFTEST_FAILED));
-	if (_step == 13) lcd_printPGM(PSTR("Calibrating home"));
-
-	lcd.setCursor(0, 1);
-	lcd_printPGM(separator);
+	if (_clear) lcd_clear();
+
+
+	lcd_set_cursor(0, 0);
+
+	if (_step == -1) lcd_puts_P(_T(MSG_SELFTEST_FAN));
+	if (_step == 0) lcd_puts_P(_T(MSG_SELFTEST_FAN));
+	if (_step == 1) lcd_puts_P(_T(MSG_SELFTEST_FAN));
+	if (_step == 2) lcd_puts_P(_i("Checking endstops"));////MSG_SELFTEST_CHECK_ENDSTOPS c=20 r=0
+	if (_step == 3) lcd_puts_P(_i("Checking hotend  "));////MSG_SELFTEST_CHECK_HOTEND c=20 r=0
+	if (_step == 4) lcd_puts_P(_i("Checking X axis  "));////MSG_SELFTEST_CHECK_X c=20 r=0
+	if (_step == 5) lcd_puts_P(_i("Checking Y axis  "));////MSG_SELFTEST_CHECK_Y c=20 r=0
+	if (_step == 6) lcd_puts_P(_i("Checking Z axis  "));////MSG_SELFTEST_CHECK_Z c=20 r=0
+	if (_step == 7) lcd_puts_P(_T(MSG_SELFTEST_CHECK_BED));
+	if (_step == 8) lcd_puts_P(_T(MSG_SELFTEST_CHECK_BED));
+	if (_step == 9) lcd_puts_P(_T(MSG_SELFTEST_CHECK_FSENSOR));
+	if (_step == 10) lcd_puts_P(_T(MSG_SELFTEST_CHECK_FSENSOR));
+	if (_step == 11) lcd_puts_P(_i("All correct      "));////MSG_SELFTEST_CHECK_ALLCORRECT c=20 r=0
+	if (_step == 12) lcd_puts_P(_T(MSG_SELFTEST_FAILED));
+	if (_step == 13) lcd_puts_P(PSTR("Calibrating home"));
+
+	lcd_set_cursor(0, 1);
+	lcd_puts_P(separator);
 	if ((_step >= -1) && (_step <= 1))
 	{
 		//SERIAL_ECHOLNPGM("Fan test");
-		lcd_print_at_PGM(0, 2, _i("Extruder fan:"));////MSG_SELFTEST_EXTRUDER_FAN_SPEED c=18 r=0
-		lcd.setCursor(18, 2);
-		(_step < 0) ? lcd.print(_indicator) : lcd.print("OK");
-		lcd_print_at_PGM(0, 3, _i("Print fan:"));////MSG_SELFTEST_PRINT_FAN_SPEED c=18 r=0
-		lcd.setCursor(18, 3);
-		(_step < 1) ? lcd.print(_indicator) : lcd.print("OK");
+		lcd_puts_at_P(0, 2, _i("Extruder fan:"));////MSG_SELFTEST_EXTRUDER_FAN_SPEED c=18 r=0
+		lcd_set_cursor(18, 2);
+		(_step < 0) ? lcd_print(_indicator) : lcd_print("OK");
+		lcd_puts_at_P(0, 3, _i("Print fan:"));////MSG_SELFTEST_PRINT_FAN_SPEED c=18 r=0
+		lcd_set_cursor(18, 3);
+		(_step < 1) ? lcd_print(_indicator) : lcd_print("OK");
 	}
 	else if (_step >= 9 && _step <= 10)
 	{
-		lcd_print_at_PGM(0, 2, _i("Filament sensor:"));////MSG_SELFTEST_FILAMENT_SENSOR c=18 r=0
-		lcd.setCursor(18, 2);
-		(_step == 9) ? lcd.print(_indicator) : lcd.print("OK");
+		lcd_puts_at_P(0, 2, _i("Filament sensor:"));////MSG_SELFTEST_FILAMENT_SENSOR c=18 r=0
+		lcd_set_cursor(18, 2);
+		(_step == 9) ? lcd_print(_indicator) : lcd_print("OK");
 	}
 	else if (_step < 9)
 	{
@@ -7401,39 +7237,32 @@ static int lcd_selftest_screen(int _step, int _progress, int _progress_scale, bo
 
 static void lcd_selftest_screen_step(int _row, int _col, int _state, const char *_name, const char *_indicator)
 {
-	lcd.setCursor(_col, _row);
+	lcd_set_cursor(_col, _row);
 
 	switch (_state)
 	{
 	case 1:
-		lcd.print(_name);
-		lcd.setCursor(_col + strlen(_name), _row);
-		lcd.print(":");
-		lcd.setCursor(_col + strlen(_name) + 1, _row);
-		lcd.print(_indicator);
+		lcd_print(_name);
+		lcd_set_cursor(_col + strlen(_name), _row);
+		lcd_print(":");
+		lcd_set_cursor(_col + strlen(_name) + 1, _row);
+		lcd_print(_indicator);
 		break;
 	case 2:
-		lcd.print(_name);
-		lcd.setCursor(_col + strlen(_name), _row);
-		lcd.print(":");
-		lcd.setCursor(_col + strlen(_name) + 1, _row);
-		lcd.print("OK");
+		lcd_print(_name);
+		lcd_set_cursor(_col + strlen(_name), _row);
+		lcd_print(":");
+		lcd_set_cursor(_col + strlen(_name) + 1, _row);
+		lcd_print("OK");
 		break;
 	default:
-		lcd.print(_name);
+		lcd_print(_name);
 	}
 }
 
 
 /** End of menus **/
 
-static void lcd_quick_feedback()
-{
-  lcdDrawUpdate = 2;
-  button_pressed = false;  
-  lcd_implementation_quick_feedback();
-}
-
 /** Menu action functions **/
 
 static bool check_file(const char* filename) {
@@ -7460,7 +7289,7 @@ static bool check_file(const char* filename) {
 	
 }
 
-static void menu_action_sdfile(const char* filename, char* longFilename)
+void menu_action_sdfile(const char* filename, char* longFilename)
 {
   loading_flag = false;
   char cmd[30];
@@ -7504,35 +7333,29 @@ static void menu_action_sdfile(const char* filename, char* longFilename)
 
   lcd_return_to_status();
 }
-static void menu_action_sddirectory(const char* filename, char* longFilename)
+
+void menu_action_sddirectory(const char* filename, char* longFilename)
 {
 	uint8_t depth = (uint8_t)card.getWorkDirDepth();
 
 	strcpy(dir_names[depth], filename);
 	MYSERIAL.println(dir_names[depth]);
   card.chdir(filename);
-  encoderPosition = 0;
-}
-static void menu_action_setting_edit_bool(const char* pstr, bool* ptr)
-{
-  *ptr = !(*ptr);
-}
-/*
-static void menu_action_setting_edit_callback_bool(const char* pstr, bool* ptr, menuFunc_t callback)
-{
-  menu_action_setting_edit_bool(pstr, ptr);
-  (*callback)();
+  lcd_encoder = 0;
 }
-*/
-#endif//ULTIPANEL
 
 /** LCD API **/
 
-void lcd_init()
+void ultralcd_init()
 {
-  lcd_implementation_init();
+	lcd_init();
+	lcd_refresh();
+	lcd_longpress_func = menu_lcd_longpress_func;
+	lcd_charsetup_func = menu_lcd_charsetup_func;
+	lcd_lcdupdate_func = menu_lcd_lcdupdate_func;
+	menu_menu = lcd_status_screen;
+	menu_lcd_charsetup_func();
 
-#ifdef NEWPANEL
   SET_INPUT(BTN_EN1);
   SET_INPUT(BTN_EN2);
   WRITE(BTN_EN1, HIGH);
@@ -7541,203 +7364,19 @@ void lcd_init()
   SET_INPUT(BTN_ENC);
   WRITE(BTN_ENC, HIGH);
 #endif
-#ifdef REPRAPWORLD_KEYPAD
-  pinMode(SHIFT_CLK, OUTPUT);
-  pinMode(SHIFT_LD, OUTPUT);
-  pinMode(SHIFT_OUT, INPUT);
-  WRITE(SHIFT_OUT, HIGH);
-  WRITE(SHIFT_LD, HIGH);
-#endif
-#else  // Not NEWPANEL
-#ifdef SR_LCD_2W_NL // Non latching 2 wire shift register
-  pinMode (SR_DATA_PIN, OUTPUT);
-  pinMode (SR_CLK_PIN, OUTPUT);
-#elif defined(SHIFT_CLK)
-  pinMode(SHIFT_CLK, OUTPUT);
-  pinMode(SHIFT_LD, OUTPUT);
-  pinMode(SHIFT_EN, OUTPUT);
-  pinMode(SHIFT_OUT, INPUT);
-  WRITE(SHIFT_OUT, HIGH);
-  WRITE(SHIFT_LD, HIGH);
-  WRITE(SHIFT_EN, LOW);
-#else
-#ifdef ULTIPANEL
-#error ULTIPANEL requires an encoder
-#endif
-#endif // SR_LCD_2W_NL
-#endif//!NEWPANEL
 
 #if defined (SDSUPPORT) && defined(SDCARDDETECT) && (SDCARDDETECT > 0)
   pinMode(SDCARDDETECT, INPUT);
   WRITE(SDCARDDETECT, HIGH);
   lcd_oldcardstatus = IS_SD_INSERTED;
 #endif//(SDCARDDETECT > 0)
-#ifdef LCD_HAS_SLOW_BUTTONS
-  slow_buttons = 0;
-#endif
   lcd_buttons_update();
-#ifdef ULTIPANEL
-  encoderDiff = 0;
-#endif
-}
-
-
-
-
-//#include <avr/pgmspace.h>
-
-static volatile bool lcd_update_enabled = true;
-unsigned long lcd_timeoutToStatus = 0;
-
-void lcd_update_enable(bool enabled)
-{
-    if (lcd_update_enabled != enabled) {
-        lcd_update_enabled = enabled;
-        if (enabled) {
-            // Reset encoder position. This is equivalent to re-entering a menu.
-            encoderPosition = 0;
-            encoderDiff = 0;
-            // Enabling the normal LCD update procedure.
-            // Reset the timeout interval.
-            lcd_timeoutToStatus = millis() + LCD_TIMEOUT_TO_STATUS;
-            // Force the keypad update now.
-            lcd_next_update_millis = millis() - 1;
-            // Full update.
-            lcd_implementation_clear();
-      #if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)
-            lcd_set_custom_characters(currentMenu == lcd_status_screen);
-      #else
-            if (currentMenu == lcd_status_screen)
-                lcd_set_custom_characters_degree();
-            else
-                lcd_set_custom_characters_arrows();
-      #endif
-            lcd_update(2);
-        } else {
-            // Clear the LCD always, or let it to the caller?
-        }
-    }
+  lcd_encoder_diff = 0;
 }
 
-void lcd_update(uint8_t lcdDrawUpdateOverride)
-{
-
-	if (lcdDrawUpdate < lcdDrawUpdateOverride)
-		lcdDrawUpdate = lcdDrawUpdateOverride;
-
-	if (!lcd_update_enabled)
-		return;
-
-#ifdef LCD_HAS_SLOW_BUTTONS
-  slow_buttons = lcd_implementation_read_slow_buttons(); // buttons which take too long to read in interrupt context
-#endif
-  
-  lcd_buttons_update();
-
-#if (SDCARDDETECT > 0)
-  if ((IS_SD_INSERTED != lcd_oldcardstatus && lcd_detected()))
-  {
-	  lcdDrawUpdate = 2;
-	  lcd_oldcardstatus = IS_SD_INSERTED;
-	  lcd_implementation_init( // to maybe revive the LCD if static electricity killed it.
-#if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)
-		  currentMenu == lcd_status_screen
-#endif
-	  );
-
-	  if (lcd_oldcardstatus)
-	  {
-		  card.initsd();
-		  LCD_MESSAGERPGM(_i("Card inserted"));////MSG_SD_INSERTED c=0 r=0
-		  //get_description();
-	  }
-	  else
-	  {
-		  card.release();
-		  LCD_MESSAGERPGM(_i("Card removed"));////MSG_SD_REMOVED c=0 r=0
-	  }
-  }
-#endif//CARDINSERTED
-
-  if (lcd_next_update_millis < millis())
-  {
-#ifdef DEBUG_BLINK_ACTIVE
-	static bool active_led = false;
-	active_led = !active_led;
-	pinMode(LED_PIN, OUTPUT);
-	digitalWrite(LED_PIN, active_led?HIGH:LOW);
-#endif //DEBUG_BLINK_ACTIVE
-
-#ifdef ULTIPANEL
-#ifdef REPRAPWORLD_KEYPAD
-	  if (REPRAPWORLD_KEYPAD_MOVE_Z_UP) {
-		  reprapworld_keypad_move_z_up();
-	  }
-	  if (REPRAPWORLD_KEYPAD_MOVE_Z_DOWN) {
-		  reprapworld_keypad_move_z_down();
-	  }
-	  if (REPRAPWORLD_KEYPAD_MOVE_X_LEFT) {
-		  reprapworld_keypad_move_x_left();
-	  }
-	  if (REPRAPWORLD_KEYPAD_MOVE_X_RIGHT) {
-		  reprapworld_keypad_move_x_right();
-	  }
-	  if (REPRAPWORLD_KEYPAD_MOVE_Y_DOWN) {
-		  reprapworld_keypad_move_y_down();
-	  }
-	  if (REPRAPWORLD_KEYPAD_MOVE_Y_UP) {
-		  reprapworld_keypad_move_y_up();
-	  }
-	  if (REPRAPWORLD_KEYPAD_MOVE_HOME) {
-		  reprapworld_keypad_move_home();
-	  }
-#endif
-	  if (abs(encoderDiff) >= ENCODER_PULSES_PER_STEP)
-	  {
-      if (lcdDrawUpdate == 0)
-		    lcdDrawUpdate = 1;
-		  encoderPosition += encoderDiff / ENCODER_PULSES_PER_STEP;
-		  encoderDiff = 0;
-		  lcd_timeoutToStatus = millis() + LCD_TIMEOUT_TO_STATUS;
-	  }
-
-	  if (LCD_CLICKED) lcd_timeoutToStatus = millis() + LCD_TIMEOUT_TO_STATUS;
-#endif//ULTIPANEL
 
-	  (*currentMenu)();
 
-#ifdef LCD_HAS_STATUS_INDICATORS
-	  lcd_implementation_update_indicators();
-#endif
 
-#ifdef ULTIPANEL
-	  if (lcd_timeoutToStatus < millis() && currentMenu != lcd_status_screen)
-	  {
-      // Exiting a menu. Let's call the menu function the last time with menuExiting flag set to true
-      // to give it a chance to save its state.
-      // This is useful for example, when the babystep value has to be written into EEPROM.
-      if (currentMenu != NULL) {
-        menuExiting = true;
-        (*currentMenu)();
-        menuExiting = false;
-      }
-	      lcd_implementation_clear();
-		  lcd_return_to_status();
-		  lcdDrawUpdate = 2;
-	  }
-#endif//ULTIPANEL
-	  if (lcdDrawUpdate == 2) lcd_implementation_clear();
-	  if (lcdDrawUpdate) lcdDrawUpdate--;
-	  lcd_next_update_millis = millis() + LCD_UPDATE_INTERVAL;
-	  }
-	if (!SdFatUtil::test_stack_integrity()) stack_error();
-#ifdef DEBUG_STEPPER_TIMER_MISSED
-  if (stepper_timer_overflow_state) stepper_timer_overflow();
-#endif /* DEBUG_STEPPER_TIMER_MISSED */
-	lcd_ping(); //check that we have received ping command if we are in farm mode
-	lcd_send_status();
-	if (lcd_commands_type == LCD_COMMAND_V2_CAL) lcd_commands();
-}
 
 void lcd_printer_connected() {
 	printer_connected = true;
@@ -7756,15 +7395,15 @@ static void lcd_send_status() {
 
 static void lcd_connect_printer() {
 	lcd_update_enable(false);
-	lcd_implementation_clear();
+	lcd_clear();
 	
 	bool pressed = false;
 	int i = 0;
 	int t = 0;
 	lcd_set_custom_characters_progress();
-	lcd_implementation_print_at(0, 0, "Connect printer to"); 
-	lcd_implementation_print_at(0, 1, "monitoring or hold");
-	lcd_implementation_print_at(0, 2, "the knob to continue");
+	lcd_puts_at_P(0, 0, _i("Connect printer to")); 
+	lcd_puts_at_P(0, 1, _i("monitoring or hold"));
+	lcd_puts_at_P(0, 2, _i("the knob to continue"));
 	while (no_response) {
 		i++;
 		t++;		
@@ -7776,9 +7415,9 @@ static void lcd_connect_printer() {
 		}
 		if (READ(BTN_ENC)) { //if button is not pressed
 			i = 0; 
-			lcd_implementation_print_at(0, 3, "                    ");
+			lcd_puts_at_P(0, 3, PSTR("                    "));
 		}
-		if (i!=0) lcd_implementation_print_at((i * 20) / (NC_BUTTON_LONG_PRESS * 10), 3, "\x01");
+		if (i!=0) lcd_puts_at_P((i * 20) / (NC_BUTTON_LONG_PRESS * 10), 3, "\x01");
 		if (i == NC_BUTTON_LONG_PRESS * 10) {
 			no_response = false;
 		}
@@ -7815,17 +7454,8 @@ void lcd_finishstatus() {
     }
   }
   lcd_status_message[LCD_WIDTH] = '\0';
-#if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)
-#if PROGRESS_MSG_EXPIRE > 0
-  messageTick =
-#endif
-    progressBarTick = millis();
-#endif
-  lcdDrawUpdate = 2;
+  lcd_draw_update = 2;
 
-#ifdef FILAMENT_LCD_DISPLAY
-  message_millis = millis();  //get status message to show up for a while
-#endif
 }
 void lcd_setstatus(const char* message)
 {
@@ -7846,9 +7476,7 @@ void lcd_setalertstatuspgm(const char* message)
 {
   lcd_setstatuspgm(message);
   lcd_status_message_level = 1;
-#ifdef ULTIPANEL
   lcd_return_to_status();
-#endif//ULTIPANEL
 }
 void lcd_reset_alert_level()
 {
@@ -7859,468 +7487,94 @@ uint8_t get_message_level()
 {
 	return lcd_status_message_level;
 }
-#ifdef DOGLCD
-void lcd_setcontrast(uint8_t value)
-{
-  lcd_contrast = value & 63;
-  u8g.setContrast(lcd_contrast);
-}
-#endif
 
-#ifdef ULTIPANEL
-/* Warning: This function is called from interrupt context */
-void lcd_buttons_update()
-{
-	static bool _lock = false;
-	if (_lock) return;
-	_lock = true;
-#ifdef NEWPANEL
-  uint8_t newbutton = 0;
-  if (READ(BTN_EN1) == 0)  newbutton |= EN_A;
-  if (READ(BTN_EN2) == 0)  newbutton |= EN_B;
-#if BTN_ENC > 0
-  if (lcd_update_enabled == true) { //if we are in non-modal mode, long press can be used and short press triggers with button release
-	  if (READ(BTN_ENC) == 0) { //button is pressed	  
-		  lcd_timeoutToStatus = millis() + LCD_TIMEOUT_TO_STATUS;
-		  if (millis() > button_blanking_time) {
-			  button_blanking_time = millis() + BUTTON_BLANKING_TIME;
-			  if (button_pressed == false && long_press_active == false) {
-			      longPressTimer.start();
-				  button_pressed = true;
-			  }
-			  else {
-				  if (longPressTimer.expired(LONG_PRESS_TIME)) {
-					  long_press_active = true;
-					  move_menu_scale = 1.0;
-					  menu_submenu(lcd_move_z);
-				  }
-			  }
-		  }
-	  }
-	  else { //button not pressed
-		  if (button_pressed) { //button was released
-			  button_blanking_time = millis() + BUTTON_BLANKING_TIME;
 
-			  if (long_press_active == false) { //button released before long press gets activated
-					  newbutton |= EN_C;
-			  }
-			  else if (currentMenu == lcd_move_z) lcd_quick_feedback(); 
-			  //button_pressed is set back to false via lcd_quick_feedback function
-		  }
-		  else {			  
-			  long_press_active = false;
-		  }
-	  }
-  }
-  else { //we are in modal mode
-	  if (READ(BTN_ENC) == 0)
-		  newbutton |= EN_C; 
-  }
-  
-#endif  
-  buttons = newbutton;
-#ifdef LCD_HAS_SLOW_BUTTONS
-  buttons |= slow_buttons;
-#endif
-#ifdef REPRAPWORLD_KEYPAD
-  // for the reprapworld_keypad
-  uint8_t newbutton_reprapworld_keypad = 0;
-  WRITE(SHIFT_LD, LOW);
-  WRITE(SHIFT_LD, HIGH);
-  for (int8_t i = 0; i < 8; i++) {
-    newbutton_reprapworld_keypad = newbutton_reprapworld_keypad >> 1;
-    if (READ(SHIFT_OUT))
-      newbutton_reprapworld_keypad |= (1 << 7);
-    WRITE(SHIFT_CLK, HIGH);
-    WRITE(SHIFT_CLK, LOW);
-  }
-  buttons_reprapworld_keypad = ~newbutton_reprapworld_keypad; //invert it, because a pressed switch produces a logical 0
-#endif
-#else   //read it from the shift register
-  uint8_t newbutton = 0;
-  WRITE(SHIFT_LD, LOW);
-  WRITE(SHIFT_LD, HIGH);
-  unsigned char tmp_buttons = 0;
-  for (int8_t i = 0; i < 8; i++)
-  {
-    newbutton = newbutton >> 1;
-    if (READ(SHIFT_OUT))
-      newbutton |= (1 << 7);
-    WRITE(SHIFT_CLK, HIGH);
-    WRITE(SHIFT_CLK, LOW);
-  }
-  buttons = ~newbutton; //invert it, because a pressed switch produces a logical 0
-#endif//!NEWPANEL
-
-  //manage encoder rotation
-  uint8_t enc = 0;
-  if (buttons & EN_A) enc |= B01;
-  if (buttons & EN_B) enc |= B10;
-  if (enc != lastEncoderBits)
-  {
-    switch (enc)
-    {
-      case encrot0:
-        if (lastEncoderBits == encrot3)
-          encoderDiff++;
-        else if (lastEncoderBits == encrot1)
-          encoderDiff--;
-        break;
-      case encrot1:
-        if (lastEncoderBits == encrot0)
-          encoderDiff++;
-        else if (lastEncoderBits == encrot2)
-          encoderDiff--;
-        break;
-      case encrot2:
-        if (lastEncoderBits == encrot1)
-          encoderDiff++;
-        else if (lastEncoderBits == encrot3)
-          encoderDiff--;
-        break;
-      case encrot3:
-        if (lastEncoderBits == encrot2)
-          encoderDiff++;
-        else if (lastEncoderBits == encrot0)
-          encoderDiff--;
-        break;
-    }
-  }
-  lastEncoderBits = enc;
-  _lock = false;
-}
 
-bool lcd_detected(void)
-{
-#if (defined(LCD_I2C_TYPE_MCP23017) || defined(LCD_I2C_TYPE_MCP23008)) && defined(DETECT_DEVICE)
-  return lcd.LcdDetected() == 1;
-#else
-  return true;
-#endif
-}
 
-void lcd_buzz(long duration, uint16_t freq)
-{
-#ifdef LCD_USE_I2C_BUZZER
-  lcd.buzz(duration, freq);
-#endif
-}
 
-bool lcd_clicked()
-{
-	bool clicked = LCD_CLICKED;
-	if(clicked) button_pressed = false;
-    return clicked;
-}
-#endif//ULTIPANEL
-
-/********************************/
-/** Float conversion utilities **/
-/********************************/
-//  convert float to string with +123.4 format
-char conv[8];
-char *ftostr3(const float &x)
-{
-  return itostr3((int)x);
-}
 
-char *itostr2(const uint8_t &x)
-{
-  //sprintf(conv,"%5.1f",x);
-  int xx = x;
-  conv[0] = (xx / 10) % 10 + '0';
-  conv[1] = (xx) % 10 + '0';
-  conv[2] = 0;
-  return conv;
-}
 
-// Convert float to string with 123.4 format, dropping sign
-char *ftostr31(const float &x)
-{
-  int xx = x * 10;
-  conv[0] = (xx >= 0) ? '+' : '-';
-  xx = abs(xx);
-  conv[1] = (xx / 1000) % 10 + '0';
-  conv[2] = (xx / 100) % 10 + '0';
-  conv[3] = (xx / 10) % 10 + '0';
-  conv[4] = '.';
-  conv[5] = (xx) % 10 + '0';
-  conv[6] = 0;
-  return conv;
-}
-
-// Convert float to string with 123.4 format
-char *ftostr31ns(const float &x)
-{
-  int xx = x * 10;
-  //conv[0]=(xx>=0)?'+':'-';
-  xx = abs(xx);
-  conv[0] = (xx / 1000) % 10 + '0';
-  conv[1] = (xx / 100) % 10 + '0';
-  conv[2] = (xx / 10) % 10 + '0';
-  conv[3] = '.';
-  conv[4] = (xx) % 10 + '0';
-  conv[5] = 0;
-  return conv;
-}
-
-char *ftostr32(const float &x)
-{
-  long xx = x * 100;
-  if (xx >= 0)
-    conv[0] = (xx / 10000) % 10 + '0';
-  else
-    conv[0] = '-';
-  xx = abs(xx);
-  conv[1] = (xx / 1000) % 10 + '0';
-  conv[2] = (xx / 100) % 10 + '0';
-  conv[3] = '.';
-  conv[4] = (xx / 10) % 10 + '0';
-  conv[5] = (xx) % 10 + '0';
-  conv[6] = 0;
-  return conv;
-}
-
-//// Convert float to rj string with 123.45 format
-char *ftostr32ns(const float &x) {
-	long xx = abs(x);
-	conv[0] = xx >= 10000 ? (xx / 10000) % 10 + '0' : ' ';
-	conv[1] = xx >= 1000 ? (xx / 1000) % 10 + '0' : ' ';
-	conv[2] = xx >= 100 ? (xx / 100) % 10 + '0' : '0';
-	conv[3] = '.';
-	conv[4] = (xx / 10) % 10 + '0';
-	conv[5] = xx % 10 + '0';
-	return conv;
-}
-
-
-// Convert float to string with 1.234 format
-char *ftostr43(const float &x, uint8_t offset)
-{
-  const size_t maxOffset = sizeof(conv)/sizeof(conv[0]) - 6;
-  if (offset>maxOffset) offset = maxOffset;
-  long xx = x * 1000;
-  if (xx >= 0)
-    conv[offset] = (xx / 1000) % 10 + '0';
-  else
-    conv[offset] = '-';
-  xx = abs(xx);
-  conv[offset + 1] = '.';
-  conv[offset + 2] = (xx / 100) % 10 + '0';
-  conv[offset + 3] = (xx / 10) % 10 + '0';
-  conv[offset + 4] = (xx) % 10 + '0';
-  conv[offset + 5] = 0;
-  return conv;
-}
-
-//Float to string with 1.23 format
-char *ftostr12ns(const float &x)
-{
-  long xx = x * 100;
 
-  xx = abs(xx);
-  conv[0] = (xx / 100) % 10 + '0';
-  conv[1] = '.';
-  conv[2] = (xx / 10) % 10 + '0';
-  conv[3] = (xx) % 10 + '0';
-  conv[4] = 0;
-  return conv;
-}
 
-//Float to string with 1.234 format
-char *ftostr13ns(const float &x)
-{
-    long xx = x * 1000;
-    if (xx >= 0)
-        conv[0] = ' ';
-    else
-        conv[0] = '-';
-    xx = abs(xx);
-    conv[1] = (xx / 1000) % 10 + '0';
-    conv[2] = '.';
-    conv[3] = (xx / 100) % 10 + '0';
-    conv[4] = (xx / 10) % 10 + '0';
-    conv[5] = (xx) % 10 + '0';
-    conv[6] = 0;
-    return conv;
-}
-
-//  convert float to space-padded string with -_23.4_ format
-char *ftostr32sp(const float &x) {
-  long xx = abs(x * 100);
-  uint8_t dig;
-
-  if (x < 0) { // negative val = -_0
-    conv[0] = '-';
-    dig = (xx / 1000) % 10;
-    conv[1] = dig ? '0' + dig : ' ';
-  }
-  else { // positive val = __0
-    dig = (xx / 10000) % 10;
-    if (dig) {
-      conv[0] = '0' + dig;
-      conv[1] = '0' + (xx / 1000) % 10;
-    }
-    else {
-      conv[0] = ' ';
-      dig = (xx / 1000) % 10;
-      conv[1] = dig ? '0' + dig : ' ';
-    }
-  }
 
-  conv[2] = '0' + (xx / 100) % 10; // lsd always
 
-  dig = xx % 10;
-  if (dig) { // 2 decimal places
-    conv[5] = '0' + dig;
-    conv[4] = '0' + (xx / 10) % 10;
-    conv[3] = '.';
-  }
-  else { // 1 or 0 decimal place
-    dig = (xx / 10) % 10;
-    if (dig) {
-      conv[4] = '0' + dig;
-      conv[3] = '.';
-    }
-    else {
-      conv[3] = conv[4] = ' ';
-    }
-    conv[5] = ' ';
-  }
-  conv[6] = '\0';
-  return conv;
-}
 
-char *itostr31(const int &xx)
+
+
+
+void menu_lcd_longpress_func(void)
 {
-  conv[0] = (xx >= 0) ? '+' : '-';
-  conv[1] = (xx / 1000) % 10 + '0';
-  conv[2] = (xx / 100) % 10 + '0';
-  conv[3] = (xx / 10) % 10 + '0';
-  conv[4] = '.';
-  conv[5] = (xx) % 10 + '0';
-  conv[6] = 0;
-  return conv;
-}
-
-// Convert int to rj string with 123 or -12 format
-char *itostr3(const int &x)
+	menu_submenu(lcd_move_z);
+}
+
+void menu_lcd_charsetup_func(void)
 {
-  int xx = x;
-  if (xx < 0) {
-    conv[0] = '-';
-    xx = -xx;
-  } else if (xx >= 100)
-    conv[0] = (xx / 100) % 10 + '0';
-  else
-    conv[0] = ' ';
-  if (xx >= 10)
-    conv[1] = (xx / 10) % 10 + '0';
-  else
-    conv[1] = ' ';
-  conv[2] = (xx) % 10 + '0';
-  conv[3] = 0;
-  return conv;
+	if (menu_menu == lcd_status_screen)
+		lcd_set_custom_characters_degree();
+	else
+		lcd_set_custom_characters_arrows();
 }
 
-// Convert int to lj string with 123 format
-char *itostr3left(const int &xx)
+void menu_lcd_lcdupdate_func(void)
 {
-  if (xx >= 100)
-  {
-    conv[0] = (xx / 100) % 10 + '0';
-    conv[1] = (xx / 10) % 10 + '0';
-    conv[2] = (xx) % 10 + '0';
-    conv[3] = 0;
-  }
-  else if (xx >= 10)
-  {
-    conv[0] = (xx / 10) % 10 + '0';
-    conv[1] = (xx) % 10 + '0';
-    conv[2] = 0;
-  }
-  else
+#if (SDCARDDETECT > 0)
+  if ((IS_SD_INSERTED != lcd_oldcardstatus))
   {
-    conv[0] = (xx) % 10 + '0';
-    conv[1] = 0;
+	  lcd_draw_update = 2;
+	  lcd_oldcardstatus = IS_SD_INSERTED;
+	  lcd_refresh(); // to maybe revive the LCD if static electricity killed it.
+
+	  if (lcd_oldcardstatus)
+	  {
+		  card.initsd();
+		  LCD_MESSAGERPGM(_i("Card inserted"));////MSG_SD_INSERTED c=0 r=0
+		  //get_description();
+	  }
+	  else
+	  {
+		  card.release();
+		  LCD_MESSAGERPGM(_i("Card removed"));////MSG_SD_REMOVED c=0 r=0
+	  }
   }
-  return conv;
-}
+#endif//CARDINSERTED
 
-// Convert int to rj string with 1234 format
-char *itostr4(const int &xx) {
-  conv[0] = xx >= 1000 ? (xx / 1000) % 10 + '0' : ' ';
-  conv[1] = xx >= 100 ? (xx / 100) % 10 + '0' : ' ';
-  conv[2] = xx >= 10 ? (xx / 10) % 10 + '0' : ' ';
-  conv[3] = xx % 10 + '0';
-  conv[4] = 0;
-  return conv;
-}
+  if (lcd_next_update_millis < millis())
+  {
 
-// Convert float to rj string with 12345 format
-char *ftostr5(const float &x) {
-  long xx = abs(x);
-  conv[0] = xx >= 10000 ? (xx / 10000) % 10 + '0' : ' ';
-  conv[1] = xx >= 1000 ? (xx / 1000) % 10 + '0' : ' ';
-  conv[2] = xx >= 100 ? (xx / 100) % 10 + '0' : ' ';
-  conv[3] = xx >= 10 ? (xx / 10) % 10 + '0' : ' ';
-  conv[4] = xx % 10 + '0';
-  conv[5] = 0;
-  return conv;
-}
+	  if (abs(lcd_encoder_diff) >= ENCODER_PULSES_PER_STEP)
+	  {
+      if (lcd_draw_update == 0)
+		    lcd_draw_update = 1;
+		  lcd_encoder += lcd_encoder_diff / ENCODER_PULSES_PER_STEP;
+		  lcd_encoder_diff = 0;
+		  lcd_timeoutToStatus = millis() + LCD_TIMEOUT_TO_STATUS;
+	  }
 
-// Convert float to string with +1234.5 format
-char *ftostr51(const float &x)
-{
-  long xx = x * 10;
-  conv[0] = (xx >= 0) ? '+' : '-';
-  xx = abs(xx);
-  conv[1] = (xx / 10000) % 10 + '0';
-  conv[2] = (xx / 1000) % 10 + '0';
-  conv[3] = (xx / 100) % 10 + '0';
-  conv[4] = (xx / 10) % 10 + '0';
-  conv[5] = '.';
-  conv[6] = (xx) % 10 + '0';
-  conv[7] = 0;
-  return conv;
-}
-
-// Convert float to string with +123.45 format
-char *ftostr52(const float &x)
-{
-  long xx = x * 100;
-  conv[0] = (xx >= 0) ? '+' : '-';
-  xx = abs(xx);
-  conv[1] = (xx / 10000) % 10 + '0';
-  conv[2] = (xx / 1000) % 10 + '0';
-  conv[3] = (xx / 100) % 10 + '0';
-  conv[4] = '.';
-  conv[5] = (xx / 10) % 10 + '0';
-  conv[6] = (xx) % 10 + '0';
-  conv[7] = 0;
-  return conv;
-}
+	  if (LCD_CLICKED) lcd_timeoutToStatus = millis() + LCD_TIMEOUT_TO_STATUS;
 
-/*
-// Callback for after editing PID i value
-// grab the PID i value out of the temp variable; scale it; then update the PID driver
-void copy_and_scalePID_i()
-{
-#ifdef PIDTEMP
-  Ki = scalePID_i(raw_Ki);
-  updatePID();
-#endif
-}
+	  (*menu_menu)();
 
-// Callback for after editing PID d value
-// grab the PID d value out of the temp variable; scale it; then update the PID driver
-void copy_and_scalePID_d()
-{
-#ifdef PIDTEMP
-  Kd = scalePID_d(raw_Kd);
-  updatePID();
-#endif
+	  if (lcd_timeoutToStatus < millis() && menu_menu != lcd_status_screen)
+	  {
+      // Exiting a menu. Let's call the menu function the last time with menuExiting flag set to true
+      // to give it a chance to save its state.
+      // This is useful for example, when the babystep value has to be written into EEPROM.
+      if (menu_menu != NULL) {
+        menuExiting = true;
+        (*menu_menu)();
+        menuExiting = false;
+      }
+	      lcd_clear();
+		  lcd_return_to_status();
+		  lcd_draw_update = 2;
+	  }
+	  if (lcd_draw_update == 2) lcd_clear();
+	  if (lcd_draw_update) lcd_draw_update--;
+	  lcd_next_update_millis = millis() + LCD_UPDATE_INTERVAL;
+	  }
+	if (!SdFatUtil::test_stack_integrity()) stack_error();
+	lcd_ping(); //check that we have received ping command if we are in farm mode
+	lcd_send_status();
+	if (lcd_commands_type == LCD_COMMAND_V2_CAL) lcd_commands();
 }
-*/
 
-#endif //ULTRA_LCD

+ 9 - 114
Firmware/ultralcd.h

@@ -2,19 +2,20 @@
 #define ULTRALCD_H
 
 #include "Marlin.h"
-#include "mesh_bed_calibration.h"
+#include "lcd.h"
+#include "conv2str.h"
 
 extern int lcd_puts_P(const char* str);
 extern int lcd_printf_P(const char* format, ...);
 
-#ifdef ULTRA_LCD
+extern void menu_lcd_longpress_func(void);
+extern void menu_lcd_charsetup_func(void);
+extern void menu_lcd_lcdupdate_func(void);
 
 	static void lcd_language_menu();
 
-  void lcd_update(uint8_t lcdDrawUpdateOverride = 0);
   // Call with a false parameter to suppress the LCD update from various places like the planner or the temp control.
-  void lcd_update_enable(bool enable);
-  void lcd_init();
+  void ultralcd_init();
   void lcd_setstatus(const char* message);
   void lcd_setstatuspgm(const char* message);
   void lcd_setalertstatuspgm(const char* message);
@@ -37,7 +38,6 @@ extern int lcd_printf_P(const char* format, ...);
   void lcd_confirm_print();
   unsigned char lcd_choose_color();
 //void lcd_mylang();
-  bool lcd_detected(void);
 
   static void lcd_selftest_v();
   extern bool lcd_selftest();
@@ -76,15 +76,12 @@ extern int lcd_printf_P(const char* format, ...);
   #ifndef TMC2130
   extern bool lcd_calibrate_z_end_stop_manual(bool only_z);
   #endif
+
   // Show the result of the calibration process on the LCD screen.
-  extern void lcd_bed_calibration_show_result(BedSkewOffsetDetectionResultType result, uint8_t point_too_far_mask);
+  extern void lcd_bed_calibration_show_result(uint8_t result, uint8_t point_too_far_mask);
 
   extern void lcd_diag_show_end_stops();
 
-#ifdef DOGLCD
-  extern int lcd_contrast;
-  void lcd_setcontrast(uint8_t value);
-#endif
 
   static unsigned char blink = 0;	// Variable for visualization of fan rotation in GLCD
 
@@ -93,18 +90,7 @@ extern int lcd_printf_P(const char* format, ...);
   #define LCD_MESSAGERPGM(x) lcd_setstatuspgm((x))
   #define LCD_ALERTMESSAGERPGM(x) lcd_setalertstatuspgm((x))
 
-  #define LCD_UPDATE_INTERVAL 100
-  #define LCD_TIMEOUT_TO_STATUS 30000
 
-  #ifdef ULTIPANEL
-  void lcd_buttons_update();
-  extern volatile uint8_t buttons;  //the last checked buttons in a bit array.
-  #ifdef REPRAPWORLD_KEYPAD
-    extern volatile uint8_t buttons_reprapworld_keypad; // to store the keypad shift register values
-  #endif
-  #else
-  FORCE_INLINE void lcd_buttons_update() {}
-  #endif
 
 
   // To be used in lcd_commands_type.
@@ -142,102 +128,11 @@ extern int lcd_printf_P(const char* format, ...);
 
   extern bool cancel_heatup;
   extern bool isPrintPaused;
-  
-  #ifdef FILAMENT_LCD_DISPLAY
-        extern unsigned long message_millis;
-  #endif
-    
-  void lcd_buzz(long duration,uint16_t freq);
-  bool lcd_clicked();
+      
 
   void lcd_ignore_click(bool b=true);
   void lcd_commands();
   
-  #ifdef NEWPANEL
-    #define EN_C (1<<BLEN_C)
-    #define EN_B (1<<BLEN_B)
-    #define EN_A (1<<BLEN_A)
-
-    #define LCD_CLICKED (buttons&EN_C)
-    #ifdef REPRAPWORLD_KEYPAD
-  	  #define EN_REPRAPWORLD_KEYPAD_F3 (1<<BLEN_REPRAPWORLD_KEYPAD_F3)
-  	  #define EN_REPRAPWORLD_KEYPAD_F2 (1<<BLEN_REPRAPWORLD_KEYPAD_F2)
-  	  #define EN_REPRAPWORLD_KEYPAD_F1 (1<<BLEN_REPRAPWORLD_KEYPAD_F1)
-  	  #define EN_REPRAPWORLD_KEYPAD_UP (1<<BLEN_REPRAPWORLD_KEYPAD_UP)
-  	  #define EN_REPRAPWORLD_KEYPAD_RIGHT (1<<BLEN_REPRAPWORLD_KEYPAD_RIGHT)
-  	  #define EN_REPRAPWORLD_KEYPAD_MIDDLE (1<<BLEN_REPRAPWORLD_KEYPAD_MIDDLE)
-  	  #define EN_REPRAPWORLD_KEYPAD_DOWN (1<<BLEN_REPRAPWORLD_KEYPAD_DOWN)
-  	  #define EN_REPRAPWORLD_KEYPAD_LEFT (1<<BLEN_REPRAPWORLD_KEYPAD_LEFT)
-
-  	  #define LCD_CLICKED ((buttons&EN_C) || (buttons_reprapworld_keypad&EN_REPRAPWORLD_KEYPAD_F1))
-  	  #define REPRAPWORLD_KEYPAD_MOVE_Z_UP (buttons_reprapworld_keypad&EN_REPRAPWORLD_KEYPAD_F2)
-  	  #define REPRAPWORLD_KEYPAD_MOVE_Z_DOWN (buttons_reprapworld_keypad&EN_REPRAPWORLD_KEYPAD_F3)
-  	  #define REPRAPWORLD_KEYPAD_MOVE_X_LEFT (buttons_reprapworld_keypad&EN_REPRAPWORLD_KEYPAD_LEFT)
-  	  #define REPRAPWORLD_KEYPAD_MOVE_X_RIGHT (buttons_reprapworld_keypad&EN_REPRAPWORLD_KEYPAD_RIGHT)
-  	  #define REPRAPWORLD_KEYPAD_MOVE_Y_DOWN (buttons_reprapworld_keypad&EN_REPRAPWORLD_KEYPAD_DOWN)
-  	  #define REPRAPWORLD_KEYPAD_MOVE_Y_UP (buttons_reprapworld_keypad&EN_REPRAPWORLD_KEYPAD_UP)
-  	  #define REPRAPWORLD_KEYPAD_MOVE_HOME (buttons_reprapworld_keypad&EN_REPRAPWORLD_KEYPAD_MIDDLE)
-    #endif //REPRAPWORLD_KEYPAD
-  #else
-    //atomic, do not change
-    #define B_LE (1<<BL_LE)
-    #define B_UP (1<<BL_UP)
-    #define B_MI (1<<BL_MI)
-    #define B_DW (1<<BL_DW)
-    #define B_RI (1<<BL_RI)
-    #define B_ST (1<<BL_ST)
-    #define EN_B (1<<BLEN_B)
-    #define EN_A (1<<BLEN_A)
-    
-    #define LCD_CLICKED ((buttons&B_MI)||(buttons&B_ST))
-  #endif//NEWPANEL
-
-#else //no LCD
-  FORCE_INLINE void 
-  {}
-  FORCE_INLINE void lcd_init() {}
-  FORCE_INLINE void lcd_setstatus(const char* message) {}
-  FORCE_INLINE void lcd_buttons_update() {}
-  FORCE_INLINE void lcd_reset_alert_level() {}
-  FORCE_INLINE void lcd_buzz(long duration,uint16_t freq) {}
-  FORCE_INLINE bool lcd_detected(void) { return true; }
-
-  #define LCD_MESSAGEPGM(x) 
-  #define LCD_ALERTMESSAGEPGM(x) 
-
-#endif //ULTRA_LCD
-
-char *itostr2(const uint8_t &x);
-char *itostr31(const int &xx);
-char *itostr3(const int &xx);
-char *itostr3left(const int &xx);
-char *itostr4(const int &xx);
-
-char *ftostr3(const float &x);
-char *ftostr31ns(const float &x); // float to string without sign character
-char *ftostr31(const float &x);
-char *ftostr32(const float &x);
-char *ftostr32ns(const float &x);
-char *ftostr43(const float &x, uint8_t offset = 0);
-char *ftostr12ns(const float &x);
-char *ftostr13ns(const float &x);
-char *ftostr32sp(const float &x); // remove zero-padding from ftostr32
-char *ftostr5(const float &x);
-char *ftostr51(const float &x);
-char *ftostr52(const float &x);
-
-
-extern void lcd_implementation_clear();
-extern void lcd_printPGM(const char* str);
-extern void lcd_print_at_PGM(uint8_t x, uint8_t y, const char* str);
-extern void lcd_implementation_write(char c);
-extern void lcd_implementation_print(const char *str);
-extern void lcd_implementation_print(int8_t i);
-extern void lcd_implementation_print_at(uint8_t x, uint8_t y, int8_t i);
-extern void lcd_implementation_print(int i);
-extern void lcd_implementation_print_at(uint8_t x, uint8_t y, int i);
-extern void lcd_implementation_print(float f);
-extern void lcd_implementation_print_at(uint8_t x, uint8_t y, const char *str);
 
 
 void change_extr(int extr);

+ 0 - 1437
Firmware/ultralcd_implementation_hitachi_HD44780.h

@@ -1,1437 +0,0 @@
-#ifndef ULTRA_LCD_IMPLEMENTATION_HITACHI_HD44780_H
-#define ULTRA_LCD_IMPLEMENTATION_HITACHI_HD44780_H
-
-
-int scrollstuff = 0;
-char longFilenameOLD[LONG_FILENAME_LENGTH];
-
-#include "Configuration_prusa.h"
-#include "Marlin.h"
-/**
-* Implementation of the LCD display routines for a Hitachi HD44780 display. These are common LCD character displays.
-* When selecting the Russian language, a slightly different LCD implementation is used to handle UTF8 characters.
-**/
-
-#ifndef REPRAPWORLD_KEYPAD
-extern volatile uint8_t buttons;  //the last checked buttons in a bit array.
-#else
-extern volatile uint16_t buttons;  //an extended version of the last checked buttons in a bit array.
-#endif
-
-////////////////////////////////////
-// Setup button and encode mappings for each panel (into 'buttons' variable
-//
-// This is just to map common functions (across different panels) onto the same 
-// macro name. The mapping is independent of whether the button is directly connected or 
-// via a shift/i2c register.
-
-#ifdef ULTIPANEL
-// All UltiPanels might have an encoder - so this is always be mapped onto first two bits
-#define BLEN_B 1
-#define BLEN_A 0
-
-#define EN_B (1<<BLEN_B) // The two encoder pins are connected through BTN_EN1 and BTN_EN2
-#define EN_A (1<<BLEN_A)
-
-#if defined(BTN_ENC) && BTN_ENC > -1
-  // encoder click is directly connected
-  #define BLEN_C 2 
-  #define EN_C (1<<BLEN_C) 
-#endif 
-  
-//
-// Setup other button mappings of each panel
-//
-#if defined(LCD_I2C_VIKI)
-  #define B_I2C_BTN_OFFSET 3 // (the first three bit positions reserved for EN_A, EN_B, EN_C)
-  
-  // button and encoder bit positions within 'buttons'
-  #define B_LE (BUTTON_LEFT<<B_I2C_BTN_OFFSET)    // The remaining normalized buttons are all read via I2C
-  #define B_UP (BUTTON_UP<<B_I2C_BTN_OFFSET)
-  #define B_MI (BUTTON_SELECT<<B_I2C_BTN_OFFSET)
-  #define B_DW (BUTTON_DOWN<<B_I2C_BTN_OFFSET)
-  #define B_RI (BUTTON_RIGHT<<B_I2C_BTN_OFFSET)
-
-  #if defined(BTN_ENC) && BTN_ENC > -1 
-    // the pause/stop/restart button is connected to BTN_ENC when used
-    #define B_ST (EN_C)                            // Map the pause/stop/resume button into its normalized functional name 
-    #define LCD_CLICKED (buttons&(B_MI|B_RI|B_ST)) // pause/stop button also acts as click until we implement proper pause/stop.
-  #else
-    #define LCD_CLICKED (buttons&(B_MI|B_RI))
-  #endif  
-
-  // I2C buttons take too long to read inside an interrupt context and so we read them during lcd_update
-  #define LCD_HAS_SLOW_BUTTONS
-
-#elif defined(LCD_I2C_PANELOLU2)
-  // encoder click can be read through I2C if not directly connected
-  #if BTN_ENC <= 0 
-    #define B_I2C_BTN_OFFSET 3 // (the first three bit positions reserved for EN_A, EN_B, EN_C)
-  
-    #define B_MI (PANELOLU2_ENCODER_C<<B_I2C_BTN_OFFSET) // requires LiquidTWI2 library v1.2.3 or later
-
-    #define LCD_CLICKED (buttons&B_MI)
-
-    // I2C buttons take too long to read inside an interrupt context and so we read them during lcd_update
-    #define LCD_HAS_SLOW_BUTTONS
-  #else
-    #define LCD_CLICKED (buttons&EN_C)  
-  #endif
-
-#elif defined(REPRAPWORLD_KEYPAD)
-    // define register bit values, don't change it
-    #define BLEN_REPRAPWORLD_KEYPAD_F3 0
-    #define BLEN_REPRAPWORLD_KEYPAD_F2 1
-    #define BLEN_REPRAPWORLD_KEYPAD_F1 2
-    #define BLEN_REPRAPWORLD_KEYPAD_UP 3
-    #define BLEN_REPRAPWORLD_KEYPAD_RIGHT 4
-    #define BLEN_REPRAPWORLD_KEYPAD_MIDDLE 5
-    #define BLEN_REPRAPWORLD_KEYPAD_DOWN 6
-    #define BLEN_REPRAPWORLD_KEYPAD_LEFT 7
-    
-    #define REPRAPWORLD_BTN_OFFSET 3 // bit offset into buttons for shift register values
-
-    #define EN_REPRAPWORLD_KEYPAD_F3 (1<<(BLEN_REPRAPWORLD_KEYPAD_F3+REPRAPWORLD_BTN_OFFSET))
-    #define EN_REPRAPWORLD_KEYPAD_F2 (1<<(BLEN_REPRAPWORLD_KEYPAD_F2+REPRAPWORLD_BTN_OFFSET))
-    #define EN_REPRAPWORLD_KEYPAD_F1 (1<<(BLEN_REPRAPWORLD_KEYPAD_F1+REPRAPWORLD_BTN_OFFSET))
-    #define EN_REPRAPWORLD_KEYPAD_UP (1<<(BLEN_REPRAPWORLD_KEYPAD_UP+REPRAPWORLD_BTN_OFFSET))
-    #define EN_REPRAPWORLD_KEYPAD_RIGHT (1<<(BLEN_REPRAPWORLD_KEYPAD_RIGHT+REPRAPWORLD_BTN_OFFSET))
-    #define EN_REPRAPWORLD_KEYPAD_MIDDLE (1<<(BLEN_REPRAPWORLD_KEYPAD_MIDDLE+REPRAPWORLD_BTN_OFFSET))
-    #define EN_REPRAPWORLD_KEYPAD_DOWN (1<<(BLEN_REPRAPWORLD_KEYPAD_DOWN+REPRAPWORLD_BTN_OFFSET))
-    #define EN_REPRAPWORLD_KEYPAD_LEFT (1<<(BLEN_REPRAPWORLD_KEYPAD_LEFT+REPRAPWORLD_BTN_OFFSET))
-
-    #define LCD_CLICKED ((buttons&EN_C) || (buttons&EN_REPRAPWORLD_KEYPAD_F1))
-    #define REPRAPWORLD_KEYPAD_MOVE_Y_DOWN (buttons&EN_REPRAPWORLD_KEYPAD_DOWN)
-    #define REPRAPWORLD_KEYPAD_MOVE_Y_UP (buttons&EN_REPRAPWORLD_KEYPAD_UP)
-    #define REPRAPWORLD_KEYPAD_MOVE_HOME (buttons&EN_REPRAPWORLD_KEYPAD_MIDDLE)
-
-#elif defined(NEWPANEL)
-  #define LCD_CLICKED (buttons&EN_C)
-  
-#else // old style ULTIPANEL
-  //bits in the shift register that carry the buttons for:
-  // left up center down right red(stop)
-  #define BL_LE 7
-  #define BL_UP 6
-  #define BL_MI 5
-  #define BL_DW 4
-  #define BL_RI 3
-  #define BL_ST 2
-
-  //automatic, do not change
-  #define B_LE (1<<BL_LE)
-  #define B_UP (1<<BL_UP)
-  #define B_MI (1<<BL_MI)
-  #define B_DW (1<<BL_DW)
-  #define B_RI (1<<BL_RI)
-  #define B_ST (1<<BL_ST)
-  
-  #define LCD_CLICKED (buttons&(B_MI|B_ST))
-#endif
-
-////////////////////////
-// Setup Rotary Encoder Bit Values (for two pin encoders to indicate movement)
-// These values are independent of which pins are used for EN_A and EN_B indications
-// The rotary encoder part is also independent to the chipset used for the LCD
-#if defined(EN_A) && defined(EN_B)
-    #define encrot0 0
-    #define encrot1 2
-    #define encrot2 3
-    #define encrot3 1
-#endif 
-
-#endif //ULTIPANEL
-
-////////////////////////////////////
-// Create LCD class instance and chipset-specific information
-#if defined(LCD_I2C_TYPE_PCF8575)
-  // note: these are register mapped pins on the PCF8575 controller not Arduino pins
-  #define LCD_I2C_PIN_BL  3
-  #define LCD_I2C_PIN_EN  2
-  #define LCD_I2C_PIN_RW  1
-  #define LCD_I2C_PIN_RS  0
-  #define LCD_I2C_PIN_D4  4
-  #define LCD_I2C_PIN_D5  5
-  #define LCD_I2C_PIN_D6  6
-  #define LCD_I2C_PIN_D7  7
-
-  #include <Wire.h>
-  #include <LCD.h>
-  #include <LiquidCrystal_I2C.h>
-  #define LCD_CLASS LiquidCrystal_I2C
-  LCD_CLASS lcd(LCD_I2C_ADDRESS,LCD_I2C_PIN_EN,LCD_I2C_PIN_RW,LCD_I2C_PIN_RS,LCD_I2C_PIN_D4,LCD_I2C_PIN_D5,LCD_I2C_PIN_D6,LCD_I2C_PIN_D7);
-  
-#elif defined(LCD_I2C_TYPE_MCP23017)
-  //for the LED indicators (which maybe mapped to different things in lcd_implementation_update_indicators())
-  #define LED_A 0x04 //100
-  #define LED_B 0x02 //010
-  #define LED_C 0x01 //001
-
-  #define LCD_HAS_STATUS_INDICATORS
-
-  #include <Wire.h>
-  #include <LiquidTWI2.h>
-  #define LCD_CLASS LiquidTWI2
-  #if defined(DETECT_DEVICE)
-     LCD_CLASS lcd(LCD_I2C_ADDRESS, 1);
-  #else
-     LCD_CLASS lcd(LCD_I2C_ADDRESS);
-  #endif
-  
-#elif defined(LCD_I2C_TYPE_MCP23008)
-  #include <Wire.h>
-  #include <LiquidTWI2.h>
-  #define LCD_CLASS LiquidTWI2
-  #if defined(DETECT_DEVICE)
-     LCD_CLASS lcd(LCD_I2C_ADDRESS, 1);
-  #else
-     LCD_CLASS lcd(LCD_I2C_ADDRESS);
-  #endif
-
-#elif defined(LCD_I2C_TYPE_PCA8574)
-    #include <LiquidCrystal_I2C.h>
-    #define LCD_CLASS LiquidCrystal_I2C
-    LCD_CLASS lcd(LCD_I2C_ADDRESS, LCD_WIDTH, LCD_HEIGHT);
-    
-// 2 wire Non-latching LCD SR from:
-// https://bitbucket.org/fmalpartida/new-LiquidCrystal/wiki/schematics#!shiftregister-connection 
-#elif defined(SR_LCD_2W_NL)
-
-  extern "C" void __cxa_pure_virtual() { while (1); }
-  #include <LCD.h>
-  #include <LiquidCrystal_SR.h>
-  #define LCD_CLASS LiquidCrystal_SR
-  LCD_CLASS lcd(SR_DATA_PIN, SR_CLK_PIN);
-
-#else
-  // Standard directly connected LCD implementations
-  #ifdef LANGUAGE_RU
-    #include "LiquidCrystal_Rus.h"
-    #define LCD_CLASS LiquidCrystal_Rus
-  #else 
-    #include "LiquidCrystal_Prusa.h"
-    #define LCD_CLASS LiquidCrystal_Prusa
-  #endif  
-  LCD_CLASS lcd(LCD_PINS_RS, LCD_PINS_ENABLE, LCD_PINS_D4, LCD_PINS_D5,LCD_PINS_D6,LCD_PINS_D7);  //RS,Enable,D4,D5,D6,D7
-#endif
-
-#if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)
-  static uint16_t progressBarTick = 0;
-  #if PROGRESS_MSG_EXPIRE > 0
-    static uint16_t messageTick = 0;
-  #endif
-  #define LCD_STR_PROGRESS  "\x03\x04\x05"
-#endif
-
-/* Custom characters defined in the first 8 characters of the LCD */
-#define LCD_STR_BEDTEMP     "\x00"
-#define LCD_STR_DEGREE      "\x01"
-#define LCD_STR_THERMOMETER "\x02"
-#define LCD_STR_UPLEVEL     "\x03"
-#define LCD_STR_REFRESH     "\x04"
-#define LCD_STR_FOLDER      "\x05"
-#define LCD_STR_FEEDRATE    "\x06"
-#define LCD_STR_CLOCK       "\x07"
-#define LCD_STR_ARROW_UP    "\x0B"
-#define LCD_STR_ARROW_DOWN  "\x01"
-#define LCD_STR_ARROW_RIGHT "\x7E"  /* from the default character set */
-
-static void lcd_set_custom_characters(
-  #if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)
-    bool progress_bar_set=true
-  #endif
-) {
-  byte bedTemp[8] = {
-    B00000,
-    B11111,
-    B10101,
-    B10001,
-    B10101,
-    B11111,
-    B00000,
-    B00000
-  }; //thanks Sonny Mounicou
-  byte degree[8] = {
-    B01100,
-    B10010,
-    B10010,
-    B01100,
-    B00000,
-    B00000,
-    B00000,
-    B00000
-  };
-  byte thermometer[8] = {
-    B00100,
-    B01010,
-    B01010,
-    B01010,
-    B01010,
-    B10001,
-    B10001,
-    B01110
-  };
-  byte uplevel[8] = {
-    B00100,
-    B01110,
-    B11111,
-    B00100,
-    B11100,
-    B00000,
-    B00000,
-    B00000
-  }; //thanks joris
-  byte refresh[8] = {
-    B00000,
-    B00110,
-    B11001,
-    B11000,
-    B00011,
-    B10011,
-    B01100,
-    B00000,
-  }; //thanks joris
-  byte folder[8] = {
-    B00000,
-    B11100,
-    B11111,
-    B10001,
-    B10001,
-    B11111,
-    B00000,
-    B00000
-  }; //thanks joris
-  #ifdef LANGUAGE_EN_H
-  byte feedrate[8] = {
-    B11100,
-    B10000,
-    B11000,
-    B10111,
-    B00101,
-    B00110,
-    B00101,
-    B00000
-  }; //thanks Sonny Mounicou
-  #else
- /*
-  byte feedrate[8] = {
-        B11100,
-        B10100,
-        B11000,
-        B10100,
-        B00000,
-        B00111,
-        B00010,
-        B00010
-  };
-  */
-  /*
-  byte feedrate[8] = {
-        B01100,
-        B10011,
-        B00000,
-        B01100,
-        B10011,
-        B00000,
-        B01100,
-        B10011
-  };
-  */
-  byte feedrate[8] = {
-        B00000,
-        B00100,
-        B10010,
-        B01001,
-        B10010,
-        B00100,
-        B00000,
-        B00000
-  };
-  #endif
-
-  byte clock[8] = {
-    B00000,
-    B01110,
-    B10011,
-    B10101,
-    B10001,
-    B01110,
-    B00000,
-    B00000
-  }; //thanks Sonny Mounicou
-
-  byte arrup[8] = {
-    B00100,
-    B01110,
-    B11111,
-    B00000,
-    B00000,
-    B00000,
-    B00000,
-    B00000
-  }; 
-
-  byte arrdown[8] = {
-    B00000,
-    B00000,
-    B00000,
-    B00000,
-    B00000,
-    B10001,
-    B01010,
-    B00100
-  }; 
-
-
-  #if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)
-    static bool char_mode = false;
-    byte progress[3][8] = { {
-      B00000,
-      B10000,
-      B10000,
-      B10000,
-      B10000,
-      B10000,
-      B10000,
-      B00000
-    }, {
-      B00000,
-      B10100,
-      B10100,
-      B10100,
-      B10100,
-      B10100,
-      B10100,
-      B00000
-    }, {
-      B00000,
-      B10101,
-      B10101,
-      B10101,
-      B10101,
-      B10101,
-      B10101,
-      B00000
-    } };
-    if (progress_bar_set != char_mode) {
-      char_mode = progress_bar_set;
-      lcd.createChar(LCD_STR_BEDTEMP[0], bedTemp);
-      lcd.createChar(LCD_STR_DEGREE[0], degree);
-      lcd.createChar(LCD_STR_THERMOMETER[0], thermometer);
-      lcd.createChar(LCD_STR_FEEDRATE[0], feedrate);
-      lcd.createChar(LCD_STR_CLOCK[0], clock);
-      if (progress_bar_set) {
-        // Progress bar characters for info screen
-        for (int i=3; i--;) lcd.createChar(LCD_STR_PROGRESS[i], progress[i]);
-      }
-      else {
-        // Custom characters for submenus
-        lcd.createChar(LCD_STR_UPLEVEL[0], uplevel);
-        lcd.createChar(LCD_STR_REFRESH[0], refresh);
-        lcd.createChar(LCD_STR_FOLDER[0], folder);
-      }
-    }
-  #else
-    lcd.createChar(LCD_STR_BEDTEMP[0], bedTemp);
-    lcd.createChar(LCD_STR_DEGREE[0], degree);
-    lcd.createChar(LCD_STR_THERMOMETER[0], thermometer);
-    lcd.createChar(LCD_STR_UPLEVEL[0], uplevel);
-    lcd.createChar(LCD_STR_REFRESH[0], refresh);
-    lcd.createChar(LCD_STR_FOLDER[0], folder);
-    lcd.createChar(LCD_STR_FEEDRATE[0], feedrate);
-    lcd.createChar(LCD_STR_CLOCK[0], clock);
-    //lcd.createChar(LCD_STR_ARROW_UP[0], arrup);
-    //lcd.createChar(LCD_STR_ARROW_DOWN[0], arrdown);
-  #endif
-}
-
-void lcd_set_custom_characters_arrows()
- {
-
-  byte arrdown[8] = {
-    B00000,
-    B00000,
-    B00000,
-    B00000,
-    B00000,
-    B10001,
-    B01010,
-    B00100
-  }; 
-
-    lcd.createChar(1, arrdown);
-}
-
-void lcd_set_custom_characters_progress()
- {
-  byte progress[8] = {
-	B11111,
-	B11111,
-	B11111,
-	B11111,
-	B11111,
-	B11111,
-	B11111,
-	B11111,
-  };
-  lcd.createChar(1, progress);
- }
-
-void lcd_set_custom_characters_nextpage()
- {
-
-  byte arrdown[8] = {
-    B00000,
-    B00000,
-    B10001,
-    B01010,
-    B00100,
-    B10001,
-    B01010,
-    B00100
-  }; 
-  
-  byte confirm[8] = {
-	  B00000,
-	  B00001,
-	  B00011,
-	  B10110,
-	  B11100,
-	  B01000,
-	  B00000
-  };
-
-    lcd.createChar(1, arrdown);
-	lcd.createChar(2, confirm);
-}
-
-void lcd_set_custom_characters_degree()
- {
-  byte degree[8] = {
-    B01100,
-    B10010,
-    B10010,
-    B01100,
-    B00000,
-    B00000,
-    B00000,
-    B00000
-  };
-
-    lcd.createChar(1, degree);
-}
-
-
-static void lcd_implementation_init(
-  #if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)
-    bool progress_bar_set=true
-  #endif
-) {
-
-#if defined(LCD_I2C_TYPE_PCF8575)
-    lcd.begin(LCD_WIDTH, LCD_HEIGHT);
-  #ifdef LCD_I2C_PIN_BL
-    lcd.setBacklightPin(LCD_I2C_PIN_BL,POSITIVE);
-    lcd.setBacklight(HIGH);
-  #endif
-  
-#elif defined(LCD_I2C_TYPE_MCP23017)
-    lcd.setMCPType(LTI_TYPE_MCP23017);
-    lcd.begin(LCD_WIDTH, LCD_HEIGHT);
-    lcd.setBacklight(0); //set all the LEDs off to begin with
-    
-#elif defined(LCD_I2C_TYPE_MCP23008)
-    lcd.setMCPType(LTI_TYPE_MCP23008);
-    lcd.begin(LCD_WIDTH, LCD_HEIGHT);
-
-#elif defined(LCD_I2C_TYPE_PCA8574)
-      lcd.init();
-      lcd.backlight();
-    
-#else
-    lcd.begin(LCD_WIDTH, LCD_HEIGHT);
-#endif
-
-    lcd_set_custom_characters(
-        #if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)
-            progress_bar_set
-        #endif
-    );
-
-    lcd.clear();
-}
-
-
-static void lcd_implementation_init_noclear(
-  #if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)
-    bool progress_bar_set=true
-  #endif
-) {
-
-#if defined(LCD_I2C_TYPE_PCF8575)
-    lcd.begin_noclear(LCD_WIDTH, LCD_HEIGHT);
-  #ifdef LCD_I2C_PIN_BL
-    lcd.setBacklightPin(LCD_I2C_PIN_BL,POSITIVE);
-    lcd.setBacklight(HIGH);
-  #endif
-  
-#elif defined(LCD_I2C_TYPE_MCP23017)
-    lcd.setMCPType(LTI_TYPE_MCP23017);
-    lcd.begin_noclear(LCD_WIDTH, LCD_HEIGHT);
-    lcd.setBacklight(0); //set all the LEDs off to begin with
-    
-#elif defined(LCD_I2C_TYPE_MCP23008)
-    lcd.setMCPType(LTI_TYPE_MCP23008);
-    lcd.begin_noclear(LCD_WIDTH, LCD_HEIGHT);
-
-#elif defined(LCD_I2C_TYPE_PCA8574)
-      lcd.init();
-      lcd.backlight();
-    
-#else
-    lcd.begin_noclear(LCD_WIDTH, LCD_HEIGHT);
-#endif
-
-    lcd_set_custom_characters(
-        #if defined(LCD_PROGRESS_BAR) && defined(SDSUPPORT)
-            progress_bar_set
-        #endif
-    );
-
-
-}
-
-
-static void lcd_implementation_nodisplay()
-{
-    lcd.noDisplay();
-}
-static void lcd_implementation_display()
-{
-    lcd.display();
-}
-
-void lcd_implementation_clear()
-{
-    lcd.clear();
-}
-/* Arduino < 1.0.0 is missing a function to print PROGMEM strings, so we need to implement our own */
-void lcd_printPGM(const char* str)
-{
-    char c;
-    while((c = pgm_read_byte(str++)) != '\0')
-    {
-        lcd.write(c);
-    }
-}
-
-void lcd_print_at_PGM(uint8_t x, uint8_t y, const char* str)
-{
-    lcd.setCursor(x, y);
-    char c;
-    while((c = pgm_read_byte(str++)) != '\0')
-    {
-        lcd.write(c);
-    }
-}
-
-void lcd_implementation_write(char c)
-{
-    lcd.write(c);
-}
-
-void lcd_implementation_print(int8_t i)
-{
-    lcd.print(i);
-}
-
-void lcd_implementation_print_at(uint8_t x, uint8_t y, int8_t i)
-{
-    lcd.setCursor(x, y);
-    lcd.print(i);
-}
-
-void lcd_implementation_print(int i)
-{
-    lcd.print(i);
-}
-
-void lcd_implementation_print_at(uint8_t x, uint8_t y, int i)
-{
-    lcd.setCursor(x, y);
-    lcd.print(i);
-}
-
-void lcd_implementation_print(float f)
-{
-    lcd.print(f);
-}
-
-void lcd_implementation_print(const char *str)
-{
-    lcd.print(str);
-}
-
-void lcd_implementation_print_at(uint8_t x, uint8_t y, const char *str)
-{
-    lcd.setCursor(x, y);
-    lcd.print(str);
-}
-
-static inline void lcd_print_percent_done() {
-	if (is_usb_printing)
-	{
-		lcd_printPGM(PSTR("USB"));
-	}
-	else if(IS_SD_PRINTING)
-	{
-		lcd_printPGM(PSTR("SD"));
-	}
-	else
-	{
-		lcd_printPGM(PSTR("  "));
-	}
-	if (IS_SD_PRINTING || (PRINTER_ACTIVE && (print_percent_done_normal != PRINT_PERCENT_DONE_INIT)))
-	{
-		lcd.print(itostr3(print_percent_done()));
-	}
-	else
-	{
-		lcd_printPGM(PSTR("---"));
-	}
-	lcd_printPGM(PSTR("% "));
-}
-
-static inline void lcd_print_time() {
-	//if remaining print time estimation is available print it else print elapsed time
-	//uses 8 characters
-	uint16_t print_t = 0;
-	if (print_time_remaining_normal != PRINT_TIME_REMAINING_INIT){
-		print_t = print_time_remaining();
-	}
-	else if(starttime != 0){
-		print_t = millis() / 60000 - starttime / 60000;	
-	}
-	lcd.print(LCD_STR_CLOCK[0]);
-	if((PRINTER_ACTIVE) && ((print_time_remaining_normal != PRINT_TIME_REMAINING_INIT)||(starttime != 0)))
-	{
-		lcd.print(itostr2(print_t/60));
-        lcd.print(':');
-        lcd.print(itostr2(print_t%60));	
-		if (print_time_remaining_normal != PRINT_TIME_REMAINING_INIT)
-		{
-			lcd.print('R');
-			(feedmultiply == 100) ? lcd.print(' ') : lcd.print('?');
-		}
-		else {
-			lcd_printPGM(PSTR("  "));
-		}
-    }else{
-        lcd_printPGM(PSTR("--:--  "));
-    }
-}
-
-/*
-
-20x4   |01234567890123456789|
-       |T 000/000D  Z000.0  |
-       |B 000/000D  F100%   |
-       |SD100%      T--:--  |
-       |Status line.........|
-*/
-static void lcd_implementation_status_screen()
-{
-   
-    int tHotend=int(degHotend(0) + 0.5);
-    int tTarget=int(degTargetHotend(0) + 0.5);
-
-    //Print the hotend temperature
-    lcd.setCursor(0, 0);
-    lcd.print(LCD_STR_THERMOMETER[0]);
-    lcd.print(itostr3(tHotend));
-    lcd.print('/');
-    lcd.print(itostr3left(tTarget));
-    lcd_printPGM(PSTR(LCD_STR_DEGREE " "));
-    lcd_printPGM(PSTR("  "));
-
-    //Print the Z coordinates
-    lcd.setCursor(LCD_WIDTH - 8-2, 0);
-#if 1
-    lcd_printPGM(PSTR("  Z"));
-    if (custom_message_type == 1) {
-        // In a bed calibration mode.
-        lcd_printPGM(PSTR("   --- "));
-    } else {
-        lcd.print(ftostr32sp(current_position[Z_AXIS] + 0.00001));
-        lcd.print(' ');
-    }
-#else
-    lcd_printPGM(PSTR(" Queue:"));
-    lcd.print(int(moves_planned()));
-    lcd.print(' ');
-#endif
-
-    //Print the Bedtemperature
-    lcd.setCursor(0, 1);
-    tHotend=int(degBed() + 0.5);
-    tTarget=int(degTargetBed() + 0.5);
-    lcd.print(LCD_STR_BEDTEMP[0]);
-    lcd.print(itostr3(tHotend));
-    lcd.print('/');
-    lcd.print(itostr3left(tTarget));
-    lcd_printPGM(PSTR(LCD_STR_DEGREE " "));
-    lcd_printPGM(PSTR("  "));
-
-#ifdef PLANNER_DIAGNOSTICS
-    //Print Feedrate
-    lcd.setCursor(LCD_WIDTH - 8-2, 1);
-    lcd.print(LCD_STR_FEEDRATE[0]);
-    lcd.print(itostr3(feedmultiply));
-    lcd_printPGM(PSTR("%  Q"));
-    {
-      uint8_t queue = planner_queue_min();
-      if (queue < (BLOCK_BUFFER_SIZE >> 1)) {
-        lcd.write('!');
-      } else {
-        lcd.write((char)(queue / 10) + '0');
-        queue %= 10;
-      }
-      lcd.write((char)queue + '0');
-      planner_queue_min_reset();
-    }
-#else /* PLANNER_DIAGNOSTICS */
-    //Print Feedrate
-    lcd.setCursor(LCD_WIDTH - 8-2, 1);
-    lcd_printPGM(PSTR("  "));
-    lcd.print(LCD_STR_FEEDRATE[0]);
-    lcd.print(itostr3(feedmultiply));
-    lcd_printPGM(PSTR("%     "));
-#endif /* PLANNER_DIAGNOSTICS */
-
-	bool print_sd_status = true;
-	
-#ifdef PINDA_THERMISTOR
-//	if (farm_mode && (custom_message_type == 4))
-	if (false)
-	{
-		lcd.setCursor(0, 2);
-		lcd_printPGM(PSTR("P"));
-		lcd.print(ftostr3(current_temperature_pinda));
-		lcd_printPGM(PSTR(LCD_STR_DEGREE " "));
-		print_sd_status = false;
-	}
-#endif //PINDA_THERMISTOR
-
-
-if (print_sd_status)
-{
-    //Print SD status
-    lcd.setCursor(0, 2);
-	lcd_print_percent_done();
-
-}
-
-	// Farm number display
-	if (farm_mode)
-	{
-		lcd.setCursor(6, 2);
-		lcd_printPGM(PSTR(" F"));
-		lcd.print(farm_no);
-		lcd_printPGM(PSTR("  "));
-        
-        // Beat display
-        lcd.setCursor(LCD_WIDTH - 1, 0);
-        if ( (millis() - kicktime) < 60000 ) {
-        
-            lcd_printPGM(PSTR("L"));
-        
-        }else{
-            lcd_printPGM(PSTR(" "));
-        }
-        
-	}
-	else {
-#ifdef SNMM 
-		lcd_printPGM(PSTR(" E"));
-		lcd.print(get_ext_nr() + 1);
-
-#else
-		lcd.setCursor(LCD_WIDTH - 8 - 2, 2);
-		lcd_printPGM(PSTR(" "));
-#endif
-	}
-
-#ifdef CMD_DIAGNOSTICS
-	lcd.setCursor(LCD_WIDTH - 8 -1, 2);
-	lcd_printPGM(PSTR("      C"));
-	lcd.print(buflen);	// number of commands in cmd buffer
-	if (buflen < 9) lcd_printPGM(" ");
-#else
-    //Print time
-	lcd.setCursor(LCD_WIDTH - 8, 2);
-	lcd_print_time();
-#endif //CMD_DIAGNOSTICS
-
-#ifdef DEBUG_DISABLE_LCD_STATUS_LINE
-	return;
-#endif //DEBUG_DISABLE_LCD_STATUS_LINE
-
-    //Print status line
-    lcd.setCursor(0, 3);
-
-    // If heating in progress, set flag
-	if (heating_status != 0) { custom_message = true; }
-
-	if (IS_SD_PRINTING) {
-		if (strcmp(longFilenameOLD, card.longFilename) != 0)
-		{
-			memset(longFilenameOLD, '\0', strlen(longFilenameOLD));
-			sprintf_P(longFilenameOLD, PSTR("%s"), card.longFilename);
-			scrollstuff = 0;
-		}
-	}
-
-    // If printing from SD, show what we are printing
-	if ((IS_SD_PRINTING) && !custom_message
-#ifdef DEBUG_BUILD
-    && lcd_status_message[0] == 0
-#endif /* DEBUG_BUILD */
-    )
-
-	{
-      if(strlen(card.longFilename) > LCD_WIDTH)
-      {
-
-			  int inters = 0;
-			  int gh = scrollstuff;
-			  while (((gh - scrollstuff) < LCD_WIDTH) && (inters == 0))
-			  {
-
-				  if (card.longFilename[gh] == '\0')
-				  {
-					  lcd.setCursor(gh - scrollstuff, 3);
-					  lcd.print(card.longFilename[gh - 1]);
-					  scrollstuff = 0;
-					  gh = scrollstuff;
-					  inters = 1;
-				  }
-				  else
-				  {
-					  lcd.setCursor(gh - scrollstuff, 3);
-					  lcd.print(card.longFilename[gh - 1]);
-					  gh++;
-				  }
-
-
-			  }
-			  scrollstuff++;
-      }
-      else
-      {
-			  lcd.print(longFilenameOLD);
-      }
-	}
-	    
-    // If not, check for other special events
-	else
-	{
-        
-		if (custom_message)
-		{
-            // If heating flag, show progress of heating.
-			if (heating_status != 0)
-			{
-				heating_status_counter++;
-				if (heating_status_counter > 13)
-				{
-					heating_status_counter = 0;
-				}
-				lcd.setCursor(7, 3);
-				lcd_printPGM(PSTR("             "));
-
-				for (int dots = 0; dots < heating_status_counter; dots++)
-				{
-					lcd.setCursor(7 + dots, 3);
-					lcd.print('.');
-				}
-
-				switch (heating_status)
-				{
-				case 1:
-					lcd.setCursor(0, 3);
-					lcd_printPGM(_T(MSG_HEATING));
-					break;
-				case 2:
-					lcd.setCursor(0, 3);
-					lcd_printPGM(_T(MSG_HEATING_COMPLETE));
-					heating_status = 0;
-					heating_status_counter = 0;
-					custom_message = false;
-					break;
-				case 3:
-					lcd.setCursor(0, 3);
-					lcd_printPGM(_T(MSG_BED_HEATING));
-					break;
-				case 4:
-					lcd.setCursor(0, 3);
-					lcd_printPGM(_T(MSG_BED_DONE));
-					heating_status = 0;
-					heating_status_counter = 0;
-					custom_message = false;
-					break;
-				default:
-					break;
-				}
-			}
-            
-            // If mesh bed leveling in progress, show the status
-            
-			if (custom_message_type == 1)
-			{
-				if (custom_message_state > 10)
-				{
-					lcd.setCursor(0, 3);
-					lcd_printPGM(PSTR("                    "));
-					lcd.setCursor(0, 3);
-					lcd_printPGM(_T(MSG_CALIBRATE_Z_AUTO));
-					lcd_printPGM(PSTR(" : "));
-					lcd.print(custom_message_state-10);
-				}
-				else
-				{
-					if (custom_message_state == 3)
-					{
-						lcd_printPGM(_T(WELCOME_MSG));
-						lcd_setstatuspgm(_T(WELCOME_MSG));
-						custom_message = false;
-						custom_message_type = 0;
-					}
-					if (custom_message_state > 3 && custom_message_state <= 10 )
-					{
-						lcd.setCursor(0, 3);
-						lcd_printPGM(PSTR("                   "));
-						lcd.setCursor(0, 3);
-						lcd_printPGM(_i("Calibration done"));////MSG_HOMEYZ_DONE c=0 r=0
-						custom_message_state--;
-					}
-				}
-
-			}
-            // If loading filament, print status
-			if (custom_message_type == 2)
-			{
-				lcd.print(lcd_status_message);
-			}
-			// PID tuning in progress
-			if (custom_message_type == 3) {
-				lcd.print(lcd_status_message);
-				if (pid_cycle <= pid_number_of_cycles && custom_message_state > 0) {
-					lcd.setCursor(10, 3);
-					lcd.print(itostr3(pid_cycle));
-					
-					lcd.print('/');
-					lcd.print(itostr3left(pid_number_of_cycles));
-				}
-			}
-			// PINDA temp calibration in progress
-			if (custom_message_type == 4) {
-				char progress[4];
-				lcd.setCursor(0, 3);
-				lcd_printPGM(_T(MSG_TEMP_CALIBRATION));
-				lcd.setCursor(12, 3);
-				sprintf(progress, "%d/6", custom_message_state);
-				lcd.print(progress);
-			}
-			// temp compensation preheat
-			if (custom_message_type == 5) {
-				lcd.setCursor(0, 3);
-				lcd_printPGM(_i("PINDA Heating"));////MSG_PINDA_PREHEAT c=20 r=1
-				if (custom_message_state <= PINDA_HEAT_T) {
-					lcd_printPGM(PSTR(": "));
-					lcd.print(custom_message_state); //seconds
-					lcd.print(' ');
-					
-				}
-			}
-
-
-		}
-	else
-		{
-            // Nothing special, print status message normally
-			lcd.print(lcd_status_message);
-		}
-	}
-    
-    // Fill the rest of line to have nice and clean output
-    for(int fillspace = 0; fillspace<20;fillspace++)
-	{
-      if((lcd_status_message[fillspace] > 31 ))
-	  {
-      }
-	  else
-	  {
-        lcd.print(' ');
-      }
-    }
-	
-}
-
-
-static void lcd_implementation_drawmenu_generic(uint8_t row, const char* pstr, char pre_char, char post_char)
-{
-    char c;
-    //Use all characters in narrow LCDs
-  #if LCD_WIDTH < 20
-      uint8_t n = LCD_WIDTH - 1 - 1;
-    #else
-      uint8_t n = LCD_WIDTH - 1 - 2;
-  #endif
-    lcd.setCursor(0, row);
-    lcd.print(pre_char);
-    while( ((c = pgm_read_byte(pstr)) != '\0') && (n>0) )
-    {
-        lcd.print(c);
-        pstr++;
-        n--;
-    }
-    while(n--)
-        lcd.print(' ');
-    lcd.print(post_char);
-    lcd.print(' ');
-}
-
-static void lcd_implementation_drawmenu_generic_RAM(uint8_t row, const char* str, char pre_char, char post_char)
-{
-    char c;
-    //Use all characters in narrow LCDs
-  #if LCD_WIDTH < 20
-      uint8_t n = LCD_WIDTH - 1 - 1;
-    #else
-      uint8_t n = LCD_WIDTH - 1 - 2;
-  #endif
-    lcd.setCursor(0, row);
-    lcd.print(pre_char);
-    while( ((c = *str) != '\0') && (n>0) )
-    {
-        lcd.print(c);
-        str++;
-        n--;
-    }
-    while(n--)
-        lcd.print(' ');
-    lcd.print(post_char);
-    lcd.print(' ');
-}
-
-static void lcd_implementation_drawmenu_setting_edit_generic(uint8_t row, const char* pstr, char pre_char, char* data)
-{
-    char c;
-    //Use all characters in narrow LCDs
-  #if LCD_WIDTH < 20
-      uint8_t n = LCD_WIDTH - 1 - 1 - strlen(data);
-    #else
-      uint8_t n = LCD_WIDTH - 1 - 2 - strlen(data);
-  #endif
-    lcd.setCursor(0, row);
-    lcd.print(pre_char);
-    while( ((c = pgm_read_byte(pstr)) != '\0') && (n>0) )
-    {
-        lcd.print(c);
-        pstr++;
-        n--;
-    }
-    lcd.print(':');
-    while(n--)
-        lcd.print(' ');
-    lcd.print(data);
-}
-static void lcd_implementation_drawmenu_setting_edit_generic_P(uint8_t row, const char* pstr, char pre_char, const char* data)
-{
-    char c;
-    //Use all characters in narrow LCDs
-  #if LCD_WIDTH < 20
-      uint8_t n = LCD_WIDTH - 1 - 1 - strlen_P(data);
-    #else
-      uint8_t n = LCD_WIDTH - 1 - 2 - strlen_P(data);
-  #endif
-    lcd.setCursor(0, row);
-    lcd.print(pre_char);
-    while( ((c = pgm_read_byte(pstr)) != '\0') && (n>0) )
-    {
-        lcd.print(c);
-        pstr++;
-        n--;
-    }
-    lcd.print(':');
-    while(n--)
-        lcd.print(' ');
-    lcd_printPGM(data);
-}
-
-
-extern char *wfac_to_str5(const uint8_t &x);
-extern char *mres_to_str3(const uint8_t &x);
-
-#define lcd_implementation_drawmenu_setting_edit_wfac_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', wfac_to_str5(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_wfac(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', wfac_to_str5(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_mres_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', mres_to_str3(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_mres(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', mres_to_str3(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_byte3_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', itostr3((uint8_t)*(data)))
-#define lcd_implementation_drawmenu_setting_edit_byte3(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', itostr3((uint8_t)*(data)))
-#define lcd_implementation_drawmenu_setting_edit_int3_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', itostr3(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_int3(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', itostr3(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_float3_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr3(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_float3(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr3(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_float32_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr32(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_float32(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr32(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_float43_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr43(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_float43(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr43(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_float5_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_float5(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_float52_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr52(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_float52(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr52(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_float51_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr51(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_float51(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr51(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_long5_selected(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_long5(row, pstr, pstr2, data, minValue, maxValue) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_bool_selected(row, pstr, pstr2, data) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, '>', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
-#define lcd_implementation_drawmenu_setting_edit_bool(row, pstr, pstr2, data) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, ' ', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
-
-//Add version for callback functions
-#define lcd_implementation_drawmenu_setting_edit_callback_int3_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', itostr3(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_callback_int3(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', itostr3(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_callback_float3_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr3(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_callback_float3(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr3(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_callback_float32_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr32(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_callback_float32(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr32(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_callback_float43_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr43(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_callback_float43(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr43(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_callback_float5_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_callback_float5(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_callback_float52_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr52(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_callback_float52(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr52(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_callback_float51_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr51(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_callback_float51(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr51(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_callback_long5_selected(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, '>', ftostr5(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_callback_long5(row, pstr, pstr2, data, minValue, maxValue, callback) lcd_implementation_drawmenu_setting_edit_generic(row, pstr, ' ', ftostr5(*(data)))
-#define lcd_implementation_drawmenu_setting_edit_callback_bool_selected(row, pstr, pstr2, data, callback) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, '>', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
-#define lcd_implementation_drawmenu_setting_edit_callback_bool(row, pstr, pstr2, data, callback) lcd_implementation_drawmenu_setting_edit_generic_P(row, pstr, ' ', (*(data))?PSTR(MSG_ON):PSTR(MSG_OFF))
-
-
-void lcd_implementation_drawedit(const char* pstr, char* value)
-{
-    lcd.setCursor(1, 1);
-    lcd_printPGM(pstr);
-    lcd.print(':');
-   #if LCD_WIDTH < 20
-      lcd.setCursor(LCD_WIDTH - strlen(value), 1);
-    #else
-      lcd.setCursor(LCD_WIDTH -1 - strlen(value), 1);
-   #endif
-    lcd.print(value);
-}
-
-void lcd_implementation_drawedit_2(const char* pstr, char* value)
-{
-    lcd.setCursor(0, 1);
-    lcd_printPGM(pstr);
-    lcd.print(':');
-
-    lcd.setCursor((LCD_WIDTH - strlen(value))/2, 3);
-
-    lcd.print(value);
-    lcd.print(" mm");
-}
-
-static void lcd_implementation_drawmenu_sdfile_selected(uint8_t row, const char* pstr, const char* filename, char* longFilename)
-{
-    char c;
-    int enc_dif = encoderDiff;
-    uint8_t n = LCD_WIDTH - 1;
-    for(int g = 0; g<4;g++){
-      lcd.setCursor(0, g);
-    lcd.print(' ');
-    }
-
-    lcd.setCursor(0, row);
-    lcd.print('>');
-    int i = 1;
-    int j = 0;
-    char* longFilenameTMP = longFilename;
-
-    while((c = *longFilenameTMP) != '\0')
-    {
-        lcd.setCursor(i, row);
-        lcd.print(c);
-        i++;
-        longFilenameTMP++;
-        if(i==LCD_WIDTH){
-          i=1;
-          j++;
-          longFilenameTMP = longFilename + j;          
-          n = LCD_WIDTH - 1;
-          for(int g = 0; g<300 ;g++){
-			  manage_heater();
-            if(LCD_CLICKED || ( enc_dif != encoderDiff )){
-				longFilenameTMP = longFilename;
-				*(longFilenameTMP + LCD_WIDTH - 2) = '\0';
-				i = 1;
-				j = 0;
-				break;
-            }else{
-				if (j == 1) delay(3);	//wait around 1.2 s to start scrolling text
-				delay(1);				//then scroll with redrawing every 300 ms 
-            }
-
-          }
-        }
-    }
-    if(c!='\0'){
-      lcd.setCursor(i, row);
-        lcd.print(c);
-        i++;
-    }
-    n=n-i+1;
-    while(n--)
-        lcd.print(' ');
-}
-static void lcd_implementation_drawmenu_sdfile(uint8_t row, const char* pstr, const char* filename, char* longFilename)
-{
-    char c;
-    uint8_t n = LCD_WIDTH - 1;
-    lcd.setCursor(0, row);
-    lcd.print(' ');
-    if (longFilename[0] != '\0')
-    {
-        filename = longFilename;
-        longFilename[LCD_WIDTH-1] = '\0';
-    }
-    while( ((c = *filename) != '\0') && (n>0) )
-    {
-        lcd.print(c);
-        filename++;
-        n--;
-    }
-    while(n--)
-        lcd.print(' ');
-}
-static void lcd_implementation_drawmenu_sddirectory_selected(uint8_t row, const char* pstr, const char* filename, char* longFilename)
-{
-    char c;
-    uint8_t n = LCD_WIDTH - 2;
-    lcd.setCursor(0, row);
-    lcd.print('>');
-    lcd.print(LCD_STR_FOLDER[0]);
-    if (longFilename[0] != '\0')
-    {
-        filename = longFilename;
-        longFilename[LCD_WIDTH-2] = '\0';
-    }
-    while( ((c = *filename) != '\0') && (n>0) )
-    {
-        lcd.print(c);
-        filename++;
-        n--;
-    }
-    while(n--)
-        lcd.print(' ');
-}
-static void lcd_implementation_drawmenu_sddirectory(uint8_t row, const char* pstr, const char* filename, char* longFilename)
-{
-    char c;
-    uint8_t n = LCD_WIDTH - 2;
-    lcd.setCursor(0, row);
-    lcd.print(' ');
-    lcd.print(LCD_STR_FOLDER[0]);
-    if (longFilename[0] != '\0')
-    {
-        filename = longFilename;
-        longFilename[LCD_WIDTH-2] = '\0';
-    }
-    while( ((c = *filename) != '\0') && (n>0) )
-    {
-        lcd.print(c);
-        filename++;
-        n--;
-    }
-    while(n--)
-        lcd.print(' ');
-}
-
-
-static void lcd_implementation_quick_feedback()
-{
-#ifdef LCD_USE_I2C_BUZZER
-	#if !defined(LCD_FEEDBACK_FREQUENCY_HZ) || !defined(LCD_FEEDBACK_FREQUENCY_DURATION_MS)
-	  lcd_buzz(1000/6,100);
-	#else
-	  lcd_buzz(LCD_FEEDBACK_FREQUENCY_DURATION_MS,LCD_FEEDBACK_FREQUENCY_HZ);
-	#endif
-#elif defined(BEEPER) && BEEPER > -1
-    SET_OUTPUT(BEEPER);
-	#if !defined(LCD_FEEDBACK_FREQUENCY_HZ) || !defined(LCD_FEEDBACK_FREQUENCY_DURATION_MS)
-    for(int8_t i=0;i<10;i++)
-    {
-      WRITE(BEEPER,HIGH);
-      delayMicroseconds(100);
-      WRITE(BEEPER,LOW);
-      delayMicroseconds(100);
-    }
-    #else
-    for(int8_t i=0;i<(LCD_FEEDBACK_FREQUENCY_DURATION_MS / (1000 / LCD_FEEDBACK_FREQUENCY_HZ));i++)
-    {
-      WRITE(BEEPER,HIGH);
-      delayMicroseconds(1000000 / LCD_FEEDBACK_FREQUENCY_HZ / 2);
-      WRITE(BEEPER,LOW);
-      delayMicroseconds(1000000 / LCD_FEEDBACK_FREQUENCY_HZ / 2);
-    }
-    #endif
-#endif
-}
-
-#ifdef LCD_HAS_STATUS_INDICATORS
-static void lcd_implementation_update_indicators()
-{
-  #if defined(LCD_I2C_PANELOLU2) || defined(LCD_I2C_VIKI)
-    //set the LEDS - referred to as backlights by the LiquidTWI2 library 
-    static uint8_t ledsprev = 0;
-    uint8_t leds = 0;
-    if (target_temperature_bed > 0) leds |= LED_A;
-    if (target_temperature[0] > 0) leds |= LED_B;
-    if (fanSpeed) leds |= LED_C;
-    #if EXTRUDERS > 1  
-      if (target_temperature[1] > 0) leds |= LED_C;
-    #endif
-    if (leds != ledsprev) {
-      lcd.setBacklight(leds);
-      ledsprev = leds;
-    }
-  #endif
-}
-#endif
-
-#ifdef LCD_HAS_SLOW_BUTTONS
-extern uint32_t blocking_enc;
-
-static uint8_t lcd_implementation_read_slow_buttons()
-{
-  #ifdef LCD_I2C_TYPE_MCP23017
-  uint8_t slow_buttons;
-    // Reading these buttons this is likely to be too slow to call inside interrupt context
-    // so they are called during normal lcd_update
-    slow_buttons = lcd.readButtons() << B_I2C_BTN_OFFSET; 
-
-    #if defined(LCD_I2C_VIKI)
-    if(slow_buttons & (B_MI|B_RI)) { //LCD clicked
-       if(blocking_enc > millis()) {
-         slow_buttons &= ~(B_MI|B_RI); // Disable LCD clicked buttons if screen is updated
-       }
-    }
-    #endif
-    return slow_buttons; 
-  #endif
-}
-#endif
-
-#endif//ULTRA_LCD_IMPLEMENTATION_HITACHI_HD44780_H

+ 5 - 5
Firmware/util.cpp

@@ -290,10 +290,10 @@ bool show_upgrade_dialog_if_version_newer(const char *version_string)
 
     if (upgrade) {
         lcd_display_message_fullscreen_P(_i("New firmware version available:"));////MSG_NEW_FIRMWARE_AVAILABLE c=20 r=2
-        lcd_print_at_PGM(0, 2, PSTR(""));
+        lcd_puts_at_P(0, 2, PSTR(""));
         for (const char *c = version_string; ! is_whitespace_or_nl_or_eol(*c); ++ c)
-            lcd_implementation_write(*c);
-        lcd_print_at_PGM(0, 3, _i("Please upgrade."));////MSG_NEW_FIRMWARE_PLEASE_UPGRADE c=20 r=0
+            lcd_putc(*c);
+        lcd_puts_at_P(0, 3, _i("Please upgrade."));////MSG_NEW_FIRMWARE_PLEASE_UPGRADE c=20 r=0
         tone(BEEPER, 1000);
         delay_keep_alive(50);
         noTone(BEEPER);
@@ -303,8 +303,8 @@ bool show_upgrade_dialog_if_version_newer(const char *version_string)
         noTone(BEEPER);
         lcd_wait_for_click();
         lcd_update_enable(true);
-        lcd_implementation_clear();
-        lcd_update();
+        lcd_clear();
+        lcd_update(0);
     }
 
     // Succeeded.

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

@@ -136,7 +136,6 @@
 //#define DEBUG_DISABLE_PRUSA_STATISTICS //disable prusa_statistics() mesages
 //#define DEBUG_XSTEP_DUP_PIN 21   //duplicate x-step output to pin 21 (SCL on P3)
 //#define DEBUG_YSTEP_DUP_PIN 21   //duplicate y-step output to pin 21 (SCL on P3)
-//#define DEBUG_BLINK_ACTIVE
 //#define DEBUG_DISABLE_FANCHECK     //disable fan check (no ISR INT7, check disabled)
 //#define DEBUG_DISABLE_FSENSORCHECK //disable fsensor check (no ISR INT7, check disabled)
 //#define DEBUG_DUMP_TO_2ND_SERIAL   //dump received characters to 2nd serial line

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

@@ -136,7 +136,6 @@
 //#define DEBUG_DISABLE_PRUSA_STATISTICS //disable prusa_statistics() mesages
 //#define DEBUG_XSTEP_DUP_PIN 21   //duplicate x-step output to pin 21 (SCL on P3)
 //#define DEBUG_YSTEP_DUP_PIN 21   //duplicate y-step output to pin 21 (SCL on P3)
-//#define DEBUG_BLINK_ACTIVE
 //#define DEBUG_DISABLE_FANCHECK     //disable fan check (no ISR INT7, check disabled)
 //#define DEBUG_DISABLE_FSENSORCHECK //disable fsensor check (no ISR INT7, check disabled)
 //#define DEBUG_DUMP_TO_2ND_SERIAL   //dump received characters to 2nd serial line

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

@@ -96,15 +96,17 @@
 #define MANUAL_FEEDRATE {2700, 2700, 1000, 100}   // set the speeds for manual moves (mm/min)
 
 //Silent mode limits
-#define SILENT_MAX_ACCEL  960 // max axxeleration in silent mode in mm/s^2
-#define SILENT_MAX_ACCEL_ST (100*SILENT_MAX_ACCEL) // max accel in steps/s^2
-#define SILENT_MAX_FEEDRATE 172  //max feedrate in mm/s, because mode switched to normal for homming , this value limits also homing, it should be greater (172mm/s=9600mm/min>2700mm/min)
+//#define SILENT_MAX_ACCEL  960 // max axxeleration in silent mode in mm/s^2
+//#define SILENT_MAX_ACCEL_ST (100*SILENT_MAX_ACCEL) // max accel in steps/s^2
+//#define SILENT_MAX_FEEDRATE 172  //max feedrate in mm/s, because mode switched to normal for homming , this value limits also homing, it should be greater (172mm/s=9600mm/min>2700mm/min)
 
 //Normal mode limits
-#define NORMAL_MAX_ACCEL 2500 // Y-axis max axxeleration in normal mode in mm/s^2
-#define NORMAL_MAX_ACCEL_ST (100*NORMAL_MAX_ACCEL) // max accel in steps/s^2
-#define NORMAL_MAX_FEEDRATE 200  //max feedrate in mm/s, because mode switched to normal for homming , this value limits also homing, it should be greater (172mm/s=9600mm/min>2700mm/min)
+//#define NORMAL_MAX_ACCEL 2500 // Y-axis max axxeleration in normal mode in mm/s^2
+//#define NORMAL_MAX_ACCEL_ST (100*NORMAL_MAX_ACCEL) // max accel in steps/s^2
+//#define NORMAL_MAX_FEEDRATE 200  //max feedrate in mm/s, because mode switched to normal for homming , this value limits also homing, it should be greater (172mm/s=9600mm/min>2700mm/min)
 
+//#define FEEDRATE_LIMIT                 //limitation method for normal/silent
+//#define ACCEL_LIMIT                 //limitation method for normal/silent
 //#define SIMPLE_ACCEL_LIMIT          //new limitation method for normal/silent
 
 //number of bytes from end of the file to start check
@@ -135,6 +137,9 @@
 // Filament sensor
 #define PAT9125
 
+// Backlash - 
+//#define BACKLASH_X
+//#define BACKLASH_Y
 
 // Disable some commands
 #define _DISABLE_M42_M226
@@ -172,7 +177,6 @@
 //#define DEBUG_DISABLE_FORCE_SELFTEST //disable force selftest
 //#define DEBUG_XSTEP_DUP_PIN 21   //duplicate x-step output to pin 21 (SCL on P3)
 //#define DEBUG_YSTEP_DUP_PIN 21   //duplicate y-step output to pin 21 (SCL on P3)
-//#define DEBUG_BLINK_ACTIVE
 //#define DEBUG_DISABLE_FANCHECK     //disable fan check (no ISR INT7, check disabled)
 //#define DEBUG_DISABLE_FSENSORCHECK //disable fsensor check (no ISR INT7, check disabled)
 #define DEBUG_DUMP_TO_2ND_SERIAL   //dump received characters to 2nd serial line
@@ -181,7 +185,6 @@
 #define CMD_DIAGNOSTICS //Show cmd queue length on printer display
 #endif /* DEBUG_BUILD */
 
-//#define EXPERIMENTAL_FEATURES
 #define TMC2130_LINEARITY_CORRECTION
 #define TMC2130_LINEARITY_CORRECTION_XYZ
 //#define TMC2130_VARIABLE_RESOLUTION