chiark / gitweb /
merging
authorErik van der Zalm <erik@vdzalm.eu>
Mon, 12 Dec 2011 19:35:46 +0000 (20:35 +0100)
committerErik van der Zalm <erik@vdzalm.eu>
Mon, 12 Dec 2011 19:35:46 +0000 (20:35 +0100)
1  2 
Marlin/Configuration.h
Marlin/Marlin.h
Marlin/Marlin.pde
Marlin/cardreader.pde
Marlin/planner.cpp
Marlin/planner.h
Marlin/stepper.cpp
Marlin/stepper.h
Marlin/temperature.cpp
Marlin/temperature.h
Marlin/ultralcd.pde

index d4e23bd1628904ab544234b429ef1b19aed8821e,dc8c799f5bd589814f6d33ad1235052f61953ab1..58f5bcaeaf8d61b8e1b22697b7bb99aab6560973
  
  #define BED_CHECK_INTERVAL 5000 //ms
  
- //// Experimental watchdog and minimal temp
- // The watchdog waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature
- // If the temperature has not increased at the end of that period, the target temperature is set to zero. It can be reset with another M104/M109
- /// CURRENTLY NOT IMPLEMENTED AND UNUSEABLE
- //#define WATCHPERIOD 5000 //5 seconds
+ //// Heating sanity check:
+ // This waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature
+ // If the temperature has not increased at the end of that period, the target temperature is set to zero. 
+ // It can be reset with another M104/M109
+ //#define WATCHPERIOD 20000 //20 seconds
  
  // Actual temperature must be close to target for this long before M109 returns success
 -//#define TEMP_RESIDENCY_TIME 20  // (seconds)
 -//#define TEMP_HYSTERESIS 5       // (C°) range of +/- temperatures considered "close" to the target one
 +#define TEMP_RESIDENCY_TIME 30  // (seconds)
 +#define TEMP_HYSTERESIS 3       // (C°) range of +/- temperatures considered "close" to the target one
  
  //// The minimal temperature defines the temperature below which the heater will not be enabled
  #define HEATER_0_MINTEMP 5
@@@ -303,8 -302,9 +313,9 @@@ const bool Z_ENDSTOPS_INVERTING = true
  //#define ULTRA_LCD  //general lcd support, also 16x2
  //#define SDSUPPORT // Enable SD Card Support in Hardware Console
  #define SD_FINISHED_STEPPERRELEASE true  //if sd support and the file is finished: disable steppers?
+ #define SD_FINISHED_RELEASECOMMAND "M84 X Y E" // no z because of layer shift.
  
 -//#define ULTIPANEL
 +#define ULTIPANEL
  #ifdef ULTIPANEL
    //#define NEWPANEL  //enable this if you have a click-encoder panel
    #define SDSUPPORT
diff --cc Marlin/Marlin.h
index d4654a38627fe018e037c2575ae64157f7a6c34e,8f98244089d86589e58f6c01a8f954669f5c99d4..f8ded924e10589df9d5c2eb96dc6f3895c71370b
@@@ -147,8 -131,6 +148,9 @@@ extern float homing_feedrate[]
  extern bool axis_relative_modes[];
  extern float current_position[NUM_AXIS] ;
  extern float add_homeing[3];
+ extern bool stop_heating_wait;
  
 +// Handling multiple extruders pins
 +extern uint8_t active_extruder;
 +
  #endif
index 183002fe256e9cc45377d3c8016cc5431845a287,4d031ea7883229012ece475a77dd2edbc1b0e2e3..79707e8c34e030dfabf98a9a35b54d0f4c2f5460
@@@ -132,11 -136,9 +135,11 @@@ bool axis_relative_modes[] = AXIS_RELAT
  volatile int feedmultiply=100; //100->1 200->2
  int saved_feedmultiply;
  volatile bool feedmultiplychanged=false;
 -float current_position[NUM_AXIS] = {  0.0, 0.0, 0.0, 0.0};
 +float current_position[NUM_AXIS] = { 0.0, 0.0, 0.0, 0.0 };
  float add_homeing[3]={0,0,0};
 +uint8_t active_extruder = 0;
+ bool stop_heating_wait=false;
 +
  //===========================================================================
  //=============================private variables=============================
  //===========================================================================
@@@ -540,16 -542,24 +543,25 @@@ FORCE_INLINE void process_commands(
        #ifdef QUICK_HOME
        if( code_seen(axis_codes[0]) && code_seen(axis_codes[1]) )  //first diagonal move
        {
-         current_position[X_AXIS] = 0; current_position[Y_AXIS] = 0;
+         current_position[X_AXIS] = 0;current_position[Y_AXIS] = 0;  
 +
          plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]); 
-         destination[X_AXIS] = 1.5 * X_MAX_LENGTH * X_HOME_DIR;
-         destination[Y_AXIS] = 1.5 * Y_MAX_LENGTH * Y_HOME_DIR; 
-         feedrate =homing_feedrate[X_AXIS]; 
+         destination[X_AXIS] = 1.5 * X_MAX_LENGTH * X_HOME_DIR;destination[Y_AXIS] = 1.5 * Y_MAX_LENGTH * Y_HOME_DIR;  
+         feedrate = homing_feedrate[X_AXIS]; 
          if(homing_feedrate[Y_AXIS]<feedrate)
            feedrate =homing_feedrate[Y_AXIS]; 
-         prepare_move();
-         current_position[X_AXIS] = 0; current_position[Y_AXIS] = 0;
+         prepare_move(); 
+     
+         current_position[X_AXIS] = (X_HOME_DIR == -1) ? 0 : X_MAX_LENGTH;
+         current_position[Y_AXIS] = (Y_HOME_DIR == -1) ? 0 : Y_MAX_LENGTH;
+         plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
+         destination[X_AXIS] = current_position[X_AXIS];
+         destination[Y_AXIS] = current_position[Y_AXIS];
+         feedrate = 0.0;
+         st_synchronize();
+         plan_set_position(0, 0, current_position[Z_AXIS], current_position[E_AXIS]);
+         current_position[X_AXIS] = 0;current_position[Y_AXIS] = 0;
+         endstops_hit_on_purpose();
        }
        #endif
        
        #else
          while ( target_direction ? (isHeatingHotend(tmp_extruder)) : (isCoolingHotend(tmp_extruder)&&(CooldownNoWait==false)) ) {
        #endif //TEMP_RESIDENCY_TIME
 -        if( (millis() - codenum) > 1000 ) 
 -        { //Print Temp Reading every 1 second while heating up/cooling down
 -          SERIAL_PROTOCOLPGM("T:");
 -          SERIAL_PROTOCOLLN( degHotend(tmp_extruder) ); 
 -          codenum = millis();
 -        }
 -        manage_heater();
 -        LCD_STATUS;
 +          if( (millis() - codenum) > 1000 ) 
 +          { //Print Temp Reading and remaining time every 1 second while heating up/cooling down
 +            SERIAL_PROTOCOLPGM("T:");
 +            SERIAL_PROTOCOL( degHotend(tmp_extruder) ); 
 +            SERIAL_PROTOCOLPGM(" E:");
 +            SERIAL_PROTOCOLLN( (int)tmp_extruder ); 
 +            #ifdef TEMP_RESIDENCY_TIME
 +              SERIAL_PROTOCOLPGM(" W:");
 +              if(residencyStart > -1)
 +              {
 +                 codenum = TEMP_RESIDENCY_TIME - ((millis() - residencyStart) / 1000);
 +                 SERIAL_PROTOCOLLN( codenum );
 +              }
 +              else 
 +              {
 +                 SERIAL_PROTOCOLLN( "?" );
 +              }
 +            #endif
 +            codenum = millis();
 +          }
 +          manage_heater();
 +          LCD_STATUS;
+         if(stop_heating_wait) break;
          #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 */
          }
          LCD_MESSAGEPGM("Heating done.");
          starttime=millis();
+         previous_millis_cmd = millis();
        }
        break;
 -    case 190: // M190 - Wait bed for heater to reach target.
 -    #if TEMP_1_PIN > -1
 +    case 190: // M190 - Wait for bed heater to reach target.
 +    #if TEMP_BED_PIN > -1
          LCD_MESSAGEPGM("Bed Heating.");
          if (code_seen('S')) setTargetBed(code_value());
          codenum = millis(); 
        }
        else
        { 
-         #if ((E_ENABLE_PIN != X_ENABLE_PIN) && (E_ENABLE_PIN != Y_ENABLE_PIN)) // Only enable on boards that have seperate ENABLE_PINS
-         if(code_seen('E')) {
-           st_synchronize();
-           LCD_MESSAGEPGM("Free Move");
+         bool all_axis = !((code_seen(axis_codes[0])) || (code_seen(axis_codes[1])) || (code_seen(axis_codes[2]))|| (code_seen(axis_codes[3])));
+         if(all_axis)
+         {
 +          disable_e0();
 +          disable_e1();
 +          disable_e2();
-         }
-         else {
            finishAndDisableSteppers();
          }
-         #else
-           finishAndDisableSteppers();
-         #endif
+         else
+         {
+           st_synchronize();
+           if(code_seen('X')) disable_x();
+           if(code_seen('Y')) disable_y();
+           if(code_seen('Z')) disable_z();
+           #if ((E_ENABLE_PIN != X_ENABLE_PIN) && (E_ENABLE_PIN != Y_ENABLE_PIN)) // Only enable on boards that have seperate ENABLE_PINS
+             if(code_seen('E')) disable_e();
+           #endif 
+           LCD_MESSAGEPGM("Partial Release");
+         }
        }
        break;
      case 85: // M85
Simple merge
index afe2f3e83e0bbefcd62a11279dfa53cedc5af125,df255443dce02e8cfb68a31e0c0a9bc2f733656a..1d66dad03f2a8acfae721ddcd9e27d7509953e40
@@@ -778,3 -804,9 +796,9 @@@ uint8_t movesplanned(
   return (block_buffer_head-block_buffer_tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1);
  }
  
 -}
+ void allow_cold_extrudes(bool allow)
+ {
+   #ifdef PREVENT_DANGEROUS_EXTRUDE
+     allow_cold_extrude=allow;
+   #endif
++}
Simple merge
index 586ea7c95adf72ff0065d1ec8acdec39df1f1ae1,51a9fe0719b6231ec22e3d0d3c9efffabf504203..cffa25f2ac1ac3b005346908f49cc7ad9a224c99
@@@ -800,7 -750,14 +801,16 @@@ void finishAndDisableSteppers(
    disable_x(); 
    disable_y(); 
    disable_z(); 
 -  disable_e(); 
 +  disable_e0(); 
 +  disable_e1(); 
 +  disable_e2(); 
  }
+ void quickStop()
+ {
+   DISABLE_STEPPER_DRIVER_INTERRUPT();
+   while(blocks_queued())
+     plan_discard_current_block();
+   ENABLE_STEPPER_DRIVER_INTERRUPT();
+ }
Simple merge
index 761e136a32f497cac844f023e4f843cd5c9df6b8,785da6c92648a4fec9d12ab0afb0aad444ce35b7..ba116c7aa3ca07f1cbab496158f8a6de63a1cdfa
@@@ -68,23 -72,23 +68,24 @@@ static unsigned long  previous_millis_b
  
  #ifdef PIDTEMP
    //static cannot be external:
 -  static float temp_iState = 0;
 -  static float temp_dState = 0;
 -  static float pTerm;
 -  static float iTerm;
 -  static float dTerm;
 +  static float temp_iState[EXTRUDERS] = { 0 };
 +  static float temp_dState[EXTRUDERS] = { 0 };
 +  static float pTerm[EXTRUDERS];
 +  static float iTerm[EXTRUDERS];
 +  static float dTerm[EXTRUDERS];
    //int output;
 -  static float pid_error;
 -  static float temp_iState_min;
 -  static float temp_iState_max;
 - // static float pid_input; 
 - // static float pid_output;
 -  static bool pid_reset;
 - 
 +  static float pid_error[EXTRUDERS];
 +  static float temp_iState_min[EXTRUDERS];
 +  static float temp_iState_max[EXTRUDERS];
 +  // static float pid_input[EXTRUDERS];
 +  // static float pid_output[EXTRUDERS];
 +  static bool pid_reset[EXTRUDERS];
  #endif //PIDTEMP
 +  static unsigned char soft_pwm[EXTRUDERS];
    
  #ifdef WATCHPERIOD
 +  static int watch_raw[EXTRUDERS] = { -1000 }; // the first value used for all
+   static int watch_oldtemp[3] = {0,0,0};
    static unsigned long watchmillis = 0;
  #endif //WATCHPERIOD
  
@@@ -193,27 -160,46 +194,40 @@@ void manage_heater(
          }
      #endif //PID_OPENLOOP
      #ifdef PID_DEBUG
 -     //SERIAL_ECHOLN(" PIDDEBUG Input "<<pid_input<<" Output "<<pid_output" pTerm "<<pTerm<<" iTerm "<<iTerm<<" dTerm "<<dTerm);  
 +    SERIAL_ECHOLN(" PIDDEBUG "<<e<<": Input "<<pid_input<<" Output "<<pid_output" pTerm "<<pTerm[e]<<" iTerm "<<iTerm[e]<<" dTerm "<<dTerm[e]);  
      #endif //PID_DEBUG
 -    HeaterPower=pid_output;
 -    // Check if temperature is within the correct range
 -    if((current_raw[TEMPSENSOR_HOTEND_0] > minttemp_0) && (current_raw[TEMPSENSOR_HOTEND_0] < maxttemp_0)) {
 -      analogWrite(HEATER_0_PIN, pid_output);
 +  #else /* PID off */
 +    pid_output = 0;
 +    if(current_raw[e] < target_raw[e]) {
 +      pid_output = PID_MAX;
      }
 -    else {
 -      analogWrite(HEATER_0_PIN, 0);
 -    }
 -  #endif //PIDTEMP
 +  #endif
  
 -  #ifndef PIDTEMP
      // Check if temperature is within the correct range
 -    if((current_raw[TEMPSENSOR_HOTEND_0] > minttemp_0) && (current_raw[TEMPSENSOR_HOTEND_0] < maxttemp_0)) {
 -      if(current_raw[TEMPSENSOR_HOTEND_0] >= target_raw[TEMPSENSOR_HOTEND_0]) {
 -        WRITE(HEATER_0_PIN,LOW);
 -      }
 -      else {
 -        WRITE(HEATER_0_PIN,HIGH);
 -      }
 +    if((current_raw[e] > minttemp[e]) && (current_raw[e] < maxttemp[e])) 
 +    {
 +      //analogWrite(heater_pin_map[e], pid_output);
 +      soft_pwm[e] = (int)pid_output >> 1;
      }
      else {
 -      WRITE(HEATER_0_PIN,LOW);
 -    }    
 -  #endif
 +      //analogWrite(heater_pin_map[e], 0);
 +      soft_pwm[e] = 0;
 +    }
 +  } // End extruder for loop
-     
+   
+   #ifdef WATCHPERIOD
+     if(watchmillis && millis() - watchmillis > WATCHPERIOD){
+         if(watch_oldtemp[TEMPSENSOR_HOTEND_0] >= degHotend(active_extruder)){
+             setTargetHotend(0,active_extruder);
+             LCD_MESSAGEPGM("Heating failed");
+             SERIAL_ECHO_START;
+             SERIAL_ECHOLN("Heating failed");
+         }else{
+             watchmillis = 0;
+         }
+     }
+   #endif
+   
    if(millis() - previous_millis_bed_heater < BED_CHECK_INTERVAL)
      return;
    previous_millis_bed_heater = millis();
@@@ -489,16 -436,15 +503,17 @@@ void tp_init(
  void setWatch() 
  {  
  #ifdef WATCHPERIOD
 -  if(isHeatingHotend0())
 +  int t = 0;
 +  for (int e = 0; e < EXTRUDERS; e++)
    {
 -    watchmillis = max(1,millis());
 +    if(isHeatingHotend(e))
+     watch_oldtemp[TEMPSENSOR_HOTEND_0] = degHotend(0);
 +    {
 +      t = max(t,millis());
 +      watch_raw[e] = current_raw[e];
 +    } 
    }
 -  else
 -  {
 -    watchmillis = 0;
 -  } 
 +  watchmillis = t;
  #endif 
  }
  
index aa0d6c4f591c08ee6d1af7a90cd1211266e7a433,2580947e7ecc85e374195804077a82e4de9d1d5c..f8b09649f572e7dfed9993f55e7d65dcf06ea7d7
- /*
-   temperature.h - temperature controller
-   Part of Marlin
-   Copyright (c) 2011 Erik van der Zalm
-   Grbl is free software: you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation, either version 3 of the License, or
-   (at your option) any later version.
-   Grbl is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-   You should have received a copy of the GNU General Public License
-   along with Grbl.  If not, see <http://www.gnu.org/licenses/>.
- */
- #ifndef temperature_h
- #define temperature_h 
- #include "Marlin.h"
- #include "fastio.h"
- #ifdef PID_ADD_EXTRUSION_RATE
-   #include "stepper.h"
- #endif
- // public functions
- void tp_init();  //initialise the heating
- void manage_heater(); //it is critical that this is called periodically.
- //low leven conversion routines
- // do not use this routines and variables outsie of temperature.cpp
- int temp2analog(int celsius, uint8_t e);
- int temp2analogBed(int celsius);
- float analog2temp(int raw, uint8_t e);
- float analog2tempBed(int raw);
- extern int target_raw[EXTRUDERS];  
- extern int heatingtarget_raw[EXTRUDERS];  
- extern int current_raw[EXTRUDERS];
- extern int target_raw_bed;
- extern int current_raw_bed;
- extern float Kp,Ki,Kd,Kc;
- #ifdef PIDTEMP
-   extern float pid_setpoint[EXTRUDERS];
- #endif
-   
- #ifdef WATCHPERIOD
-   extern int watch_raw[EXTRUDERS] ;
-   extern unsigned long watchmillis;
- #endif
- //high level conversion routines, for use outside of temperature.cpp
- //inline so that there is no performance decrease.
- //deg=degreeCelsius
- FORCE_INLINE float degHotend(uint8_t extruder) {  
-   return analog2temp(current_raw[extruder], extruder);
- };
- FORCE_INLINE float degBed() {
-   return analog2tempBed(current_raw_bed);
- };
- FORCE_INLINE float degTargetHotend(uint8_t extruder) {  
-   return analog2temp(target_raw[extruder], extruder);
- };
- FORCE_INLINE float degTargetBed() {   
-   return analog2tempBed(target_raw_bed);
- };
- FORCE_INLINE void setTargetHotend(const float &celsius, uint8_t extruder) {  
-   target_raw[extruder] = temp2analog(celsius, extruder);
- #ifdef PIDTEMP
-   pid_setpoint[extruder] = celsius;
- #endif //PIDTEMP
- };
- FORCE_INLINE void setTargetBed(const float &celsius) {  
-   target_raw_bed = temp2analogBed(celsius);
- };
- FORCE_INLINE bool isHeatingHotend(uint8_t extruder){  
-   return target_raw[extruder] > current_raw[extruder];
- };
- FORCE_INLINE bool isHeatingBed() {
-   return target_raw_bed > current_raw_bed;
- };
- FORCE_INLINE bool isCoolingHotend(uint8_t extruder) {  
-   return target_raw[extruder] < current_raw[extruder];
- };
- FORCE_INLINE bool isCoolingBed() {
-   return target_raw_bed < current_raw_bed;
- };
- #define degHotend0() degHotend(0)
- #define degTargetHotend0() degTargetHotend(0)
- #define setTargetHotend0(_celsius) setTargetHotend((_celsius), 0)
- #define isHeatingHotend0() isHeatingHotend(0)
- #define isCoolingHotend0() isCoolingHotend(0)
- #if EXTRUDERS > 1
- #define degHotend1() degHotend(1)
- #define degTargetHotend1() degTargetHotend(1)
- #define setTargetHotend1(_celsius) setTargetHotend((_celsius), 1)
- #define isHeatingHotend1() isHeatingHotend(1)
- #define isCoolingHotend1() isCoolingHotend(1)
- #endif
- #if EXTRUDERS > 2
- #define degHotend2() degHotend(2)
- #define degTargetHotend2() degTargetHotend(2)
- #define setTargetHotend2(_celsius) setTargetHotend((_celsius), 2)
- #define isHeatingHotend2() isHeatingHotend(2)
- #define isCoolingHotend2() isCoolingHotend(2)
- #endif
- #if EXTRUDERS > 3
- #error Invalid number of extruders
- #endif
- FORCE_INLINE void autotempShutdown(){
-  #ifdef AUTOTEMP
-  if(autotemp_enabled)
-  {
-   autotemp_enabled=false;
-   if(degTargetHotend(ACTIVE_EXTRUDER)>autotemp_min)
-     setTargetHotend(0,ACTIVE_EXTRUDER);
-  }
-  #endif
- }
- int getHeaterPower(int heater);
- void disable_heater();
- void setWatch();
- void updatePID();
- #endif
+ /*\r
+   temperature.h - temperature controller\r
+   Part of Marlin\r
\r
+   Copyright (c) 2011 Erik van der Zalm\r
\r
+   Grbl is free software: you can redistribute it and/or modify\r
+   it under the terms of the GNU General Public License as published by\r
+   the Free Software Foundation, either version 3 of the License, or\r
+   (at your option) any later version.\r
\r
+   Grbl is distributed in the hope that it will be useful,\r
+   but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+   GNU General Public License for more details.\r
\r
+   You should have received a copy of the GNU General Public License\r
+   along with Grbl.  If not, see <http://www.gnu.org/licenses/>.\r
+ */\r
\r
+ #ifndef temperature_h\r
+ #define temperature_h \r
\r
+ #include "Marlin.h"\r
+ #include "fastio.h"\r
+ #include "planner.h"\r
+ #ifdef PID_ADD_EXTRUSION_RATE\r
+   #include "stepper.h"\r
+ #endif\r
\r
+ // public functions\r
+ void tp_init();  //initialise the heating\r
+ void manage_heater(); //it is critical that this is called periodically.\r
\r
 -\r
 -enum TempSensor {TEMPSENSOR_HOTEND_0=0,TEMPSENSOR_BED=1, TEMPSENSOR_HOTEND_1=2};\r
 -\r
+ //low leven conversion routines\r
+ // do not use this routines and variables outsie of temperature.cpp\r
 -int temp2analog(int celsius);\r
++int temp2analog(int celsius, uint8_t e);\r
+ int temp2analogBed(int celsius);\r
 -float analog2temp(int raw);\r
++float analog2temp(int raw, uint8_t e);\r
+ float analog2tempBed(int raw);\r
 -extern int target_raw[3];  \r
 -extern int heatingtarget_raw[3];\r
 -extern int current_raw[3];\r
++extern int target_raw[EXTRUDERS];  \r
++extern int heatingtarget_raw[EXTRUDERS];  \r
++extern int current_raw[EXTRUDERS];\r
++extern int target_raw_bed;\r
++extern int current_raw_bed;\r
+ extern float Kp,Ki,Kd,Kc;\r
\r
+ #ifdef PIDTEMP\r
 -  extern float pid_setpoint ;\r
++  extern float pid_setpoint[EXTRUDERS];\r
+ #endif\r
+   \r
+ // #ifdef WATCHPERIOD\r
 -//   extern int watch_raw[3] ;\r
++  extern int watch_raw[EXTRUDERS] ;\r
+ //   extern unsigned long watchmillis;\r
+ // #endif\r
\r
\r
 -\r
+ //high level conversion routines, for use outside of temperature.cpp\r
+ //inline so that there is no performance decrease.\r
+ //deg=degreeCelsius\r
\r
 -FORCE_INLINE float degHotend0(){  return analog2temp(current_raw[TEMPSENSOR_HOTEND_0]);};\r
 -FORCE_INLINE float degHotend1(){  return analog2temp(current_raw[TEMPSENSOR_HOTEND_1]);};\r
 -FORCE_INLINE float degBed() {  return analog2tempBed(current_raw[TEMPSENSOR_BED]);};\r
 -FORCE_INLINE float degHotend(uint8_t extruder){  \r
 -  if(extruder == 0) return analog2temp(current_raw[TEMPSENSOR_HOTEND_0]);\r
 -  if(extruder == 1) return analog2temp(current_raw[TEMPSENSOR_HOTEND_1]);\r
++FORCE_INLINE float degHotend(uint8_t extruder) {  \r
++  return analog2temp(current_raw[extruder], extruder);\r
+ };\r
\r
 -FORCE_INLINE float degTargetHotend0() {  return analog2temp(target_raw[TEMPSENSOR_HOTEND_0]);};\r
 -FORCE_INLINE float degTargetHotend1() {  return analog2temp(target_raw[TEMPSENSOR_HOTEND_1]);};\r
 -FORCE_INLINE float degTargetHotend(uint8_t extruder){  \r
 -  if(extruder == 0) return analog2temp(target_raw[TEMPSENSOR_HOTEND_0]);\r
 -  if(extruder == 1) return analog2temp(target_raw[TEMPSENSOR_HOTEND_1]);\r
++FORCE_INLINE float degBed() {\r
++  return analog2tempBed(current_raw_bed);\r
+ };\r
\r
 -FORCE_INLINE float degTargetBed() {   return analog2tempBed(target_raw[TEMPSENSOR_BED]);};\r
++FORCE_INLINE float degTargetHotend(uint8_t extruder) {  \r
++  return analog2temp(target_raw[extruder], extruder);\r
++};\r
\r
 -FORCE_INLINE void setTargetHotend0(const float &celsius) \r
 -{  \r
 -  target_raw[TEMPSENSOR_HOTEND_0]=temp2analog(celsius);\r
 -  heatingtarget_raw[TEMPSENSOR_HOTEND_0]=temp2analog(celsius-HEATING_EARLY_FINISH_DEG_OFFSET);\r
 -  #ifdef PIDTEMP\r
 -    pid_setpoint = celsius;\r
 -  #endif //PIDTEMP\r
++FORCE_INLINE float degTargetBed() {   \r
++  return analog2tempBed(target_raw_bed);\r
+ };\r
 -FORCE_INLINE void setTargetHotend1(const float &celsius) {  target_raw[TEMPSENSOR_HOTEND_1]=temp2analog(celsius);};\r
 -FORCE_INLINE void setTargetHotend(const float &celcius, uint8_t extruder){  \r
 -  if(extruder == 0) setTargetHotend0(celcius);\r
 -  if(extruder == 1) setTargetHotend1(celcius);\r
++\r
++FORCE_INLINE void setTargetHotend(const float &celsius, uint8_t extruder) {  \r
++  target_raw[extruder] = temp2analog(celsius, extruder);\r
++#ifdef PIDTEMP\r
++  pid_setpoint[extruder] = celsius;\r
++#endif //PIDTEMP\r
++};\r
++\r
++FORCE_INLINE void setTargetBed(const float &celsius) {  \r
++  target_raw_bed = temp2analogBed(celsius);\r
+ };\r
 -FORCE_INLINE void setTargetBed(const float &celsius)     {  target_raw[TEMPSENSOR_BED     ]=temp2analogBed(celsius);};\r
\r
 -FORCE_INLINE bool isHeatingHotend0() {return heatingtarget_raw[TEMPSENSOR_HOTEND_0] > current_raw[TEMPSENSOR_HOTEND_0];};\r
 -FORCE_INLINE bool isHeatingHotend1() {return target_raw[TEMPSENSOR_HOTEND_1] > current_raw[TEMPSENSOR_HOTEND_1];};\r
+ FORCE_INLINE bool isHeatingHotend(uint8_t extruder){  \r
 -  if(extruder == 0) return heatingtarget_raw[TEMPSENSOR_HOTEND_0] > current_raw[TEMPSENSOR_HOTEND_0];\r
 -  if(extruder == 1) return target_raw[TEMPSENSOR_HOTEND_1] > current_raw[TEMPSENSOR_HOTEND_1];\r
 -  return false; \r
++  return target_raw[extruder] > current_raw[extruder];\r
++};\r
++\r
++FORCE_INLINE bool isHeatingBed() {\r
++  return target_raw_bed > current_raw_bed;\r
+ };\r
 -FORCE_INLINE bool isHeatingBed() {return target_raw[TEMPSENSOR_BED] > current_raw[TEMPSENSOR_BED];};\r
 -\r
 -FORCE_INLINE bool isCoolingHotend0() {return target_raw[TEMPSENSOR_HOTEND_0] < current_raw[TEMPSENSOR_HOTEND_0];};\r
 -FORCE_INLINE bool isCoolingHotend1() {return target_raw[TEMPSENSOR_HOTEND_1] < current_raw[TEMPSENSOR_HOTEND_1];};\r
 -FORCE_INLINE bool isCoolingHotend(uint8_t extruder){  \r
 -  if(extruder == 0) return target_raw[TEMPSENSOR_HOTEND_0] < current_raw[TEMPSENSOR_HOTEND_0];\r
 -  if(extruder == 1) return target_raw[TEMPSENSOR_HOTEND_1] < current_raw[TEMPSENSOR_HOTEND_1];\r
 -  return false; \r
++\r
++FORCE_INLINE bool isCoolingHotend(uint8_t extruder) {  \r
++  return target_raw[extruder] < current_raw[extruder];\r
+ };\r
 -FORCE_INLINE bool isCoolingBed() {return target_raw[TEMPSENSOR_BED] < current_raw[TEMPSENSOR_BED];};\r
++\r
++FORCE_INLINE bool isCoolingBed() {\r
++  return target_raw_bed < current_raw_bed;\r
++};\r
++\r
++#define degHotend0() degHotend(0)\r
++#define degTargetHotend0() degTargetHotend(0)\r
++#define setTargetHotend0(_celsius) setTargetHotend((_celsius), 0)\r
++#define isHeatingHotend0() isHeatingHotend(0)\r
++#define isCoolingHotend0() isCoolingHotend(0)\r
++#if EXTRUDERS > 1\r
++#define degHotend1() degHotend(1)\r
++#define degTargetHotend1() degTargetHotend(1)\r
++#define setTargetHotend1(_celsius) setTargetHotend((_celsius), 1)\r
++#define isHeatingHotend1() isHeatingHotend(1)\r
++#define isCoolingHotend1() isCoolingHotend(1)\r
++#endif\r
++#if EXTRUDERS > 2\r
++#define degHotend2() degHotend(2)\r
++#define degTargetHotend2() degTargetHotend(2)\r
++#define setTargetHotend2(_celsius) setTargetHotend((_celsius), 2)\r
++#define isHeatingHotend2() isHeatingHotend(2)\r
++#define isCoolingHotend2() isCoolingHotend(2)\r
++#endif\r
++#if EXTRUDERS > 3\r
++#error Invalid number of extruders\r
++#endif\r
\r
+ FORCE_INLINE void autotempShutdown(){\r
+  #ifdef AUTOTEMP\r
+  if(autotemp_enabled)\r
+  {\r
+   autotemp_enabled=false;\r
 -  if(degTargetHotend0()>autotemp_min)\r
 -    setTargetHotend0(0);\r
++  if(degTargetHotend(ACTIVE_EXTRUDER)>autotemp_min)\r
++    setTargetHotend(0,ACTIVE_EXTRUDER);\r
+  }\r
+  #endif\r
+ }\r
++\r
++int getHeaterPower(int heater);\r
+ void disable_heater();\r
+ void setWatch();\r
+ void updatePID();\r
\r
+ #endif\r
  \r
index d5772750d235ebe4aa8cab6ce2f8c423f29c6212,e89474ed281e11091ebc6a5901a3f1ba96ba7143..3b7663beb9674345623310b1588f09013d30eb4c
 -#include "ultralcd.h"\r
 -#ifdef ULTRA_LCD\r
 -\r
 -//===========================================================================\r
 -//=============================imported variables============================\r
 -//===========================================================================\r
 -\r
 -extern volatile int feedmultiply;\r
 -extern volatile bool feedmultiplychanged;\r
 -\r
 -extern long position[4];   \r
 -extern CardReader card;\r
 -\r
 -//===========================================================================\r
 -//=============================public variables============================\r
 -//===========================================================================\r
 -volatile char buttons=0;  //the last checked buttons in a bit array.\r
 -int encoderpos=0;\r
 -short lastenc=0;\r
 -\r
 -\r
 -//===========================================================================\r
 -//=============================private  variables============================\r
 -//===========================================================================\r
 -static char messagetext[LCD_WIDTH]="";\r
 -\r
 -//return for string conversion routines\r
 -static char conv[8];\r
 -\r
 -#include <LiquidCrystal.h>\r
 -LiquidCrystal 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 \r
 -\r
 -static unsigned long previous_millis_lcd=0;\r
 -static long previous_millis_buttons=0;\r
 -\r
 -\r
 -#ifdef NEWPANEL\r
 - static long blocking=0;\r
 -#else\r
 - static long blocking[8]={0,0,0,0,0,0,0,0};\r
 -#endif\r
 - \r
 -static MainMenu menu;\r
 -\r
 -#include <avr/pgmspace.h>\r
 -\r
 -void lcdProgMemprint(const char *str)\r
 -{\r
 -  char ch=pgm_read_byte(str);\r
 -  while(ch)\r
 -  {\r
 -    lcd.print(ch);\r
 -    ch=pgm_read_byte(++str);\r
 -  }\r
 -}\r
 -#define lcdprintPGM(x) lcdProgMemprint(MYPGM(x))\r
 -\r
 -\r
 -//===========================================================================\r
 -//=============================functions         ============================\r
 -//===========================================================================\r
 -\r
 -FORCE_INLINE int intround(const float &x){return int(0.5+x);}\r
 -\r
 -void lcd_status(const char* message)\r
 -{\r
 -  strncpy(messagetext,message,LCD_WIDTH);\r
 -  messagetext[strlen(message)]=0;\r
 -}\r
 -\r
 -void lcd_statuspgm(const char* message)\r
 -{\r
 -  char ch=pgm_read_byte(message);\r
 -  char *target=messagetext;\r
 -  uint8_t cnt=0;\r
 -  while(ch &&cnt<LCD_WIDTH)\r
 -  {\r
 -    *target=ch;\r
 -    target++;\r
 -    cnt++;\r
 -    ch=pgm_read_byte(++message);\r
 -  }\r
 -  *target=0;\r
 -}\r
 -\r
 -FORCE_INLINE void clear()\r
 -{\r
 -  lcd.clear();\r
 -}\r
 -\r
 -\r
 -void lcd_init()\r
 -{\r
 -  //beep();\r
 -  byte Degree[8] =\r
 -  {\r
 -    B01100,\r
 -    B10010,\r
 -    B10010,\r
 -    B01100,\r
 -    B00000,\r
 -    B00000,\r
 -    B00000,\r
 -    B00000\r
 -  };\r
 -  byte Thermometer[8] =\r
 -  {\r
 -    B00100,\r
 -    B01010,\r
 -    B01010,\r
 -    B01010,\r
 -    B01010,\r
 -    B10001,\r
 -    B10001,\r
 -    B01110\r
 -  };\r
 -  byte uplevel[8]={0x04, 0x0e, 0x1f, 0x04, 0x1c, 0x00, 0x00, 0x00};//thanks joris\r
 -  byte refresh[8]={0x00, 0x06, 0x19, 0x18, 0x03, 0x13, 0x0c, 0x00}; //thanks joris\r
 -  byte folder [8]={0x00, 0x1c, 0x1f, 0x11, 0x11, 0x1f, 0x00, 0x00}; //thanks joris\r
 -  lcd.begin(LCD_WIDTH, LCD_HEIGHT);\r
 -  lcd.createChar(1,Degree);\r
 -  lcd.createChar(2,Thermometer);\r
 -  lcd.createChar(3,uplevel);\r
 -  lcd.createChar(4,refresh);\r
 -  lcd.createChar(5,folder);\r
 -  LCD_MESSAGEPGM("UltiMarlin ready.");\r
 -}\r
 -\r
 -\r
 -void beep()\r
 -{\r
 -  //return;\r
 -  #ifdef ULTIPANEL\r
 -    pinMode(BEEPER,OUTPUT);\r
 -    for(int8_t i=0;i<20;i++){\r
 -      WRITE(BEEPER,HIGH);\r
 -      delay(5);\r
 -      WRITE(BEEPER,LOW);\r
 -      delay(5);\r
 -    }\r
 -  #endif\r
 -}\r
 -\r
 -void beepshort()\r
 -{\r
 -  //return;\r
 -  #ifdef ULTIPANEL\r
 -    pinMode(BEEPER,OUTPUT);\r
 -    for(int8_t i=0;i<10;i++){\r
 -      WRITE(BEEPER,HIGH);\r
 -      delay(3);\r
 -      WRITE(BEEPER,LOW);\r
 -      delay(3);\r
 -    }\r
 -  #endif  \r
 -}\r
 -\r
 -void lcd_status()\r
 -{\r
 -  #ifdef ULTIPANEL\r
 -    static uint8_t oldbuttons=0;\r
 -    //static long previous_millis_buttons=0;\r
 -    //static long previous_lcdinit=0;\r
 -  //  buttons_check(); // Done in temperature interrupt\r
 -    //previous_millis_buttons=millis();\r
 -    \r
 -    if((buttons==oldbuttons) &&  ((millis() - previous_millis_lcd) < LCD_UPDATE_INTERVAL)   )\r
 -      return;\r
 -    oldbuttons=buttons;\r
 -  #else\r
 -  \r
 -    if(((millis() - previous_millis_lcd) < LCD_UPDATE_INTERVAL)   )\r
 -      return;\r
 -  #endif\r
 -    \r
 -  previous_millis_lcd=millis();\r
 -  menu.update();\r
 -}\r
 -#ifdef ULTIPANEL  \r
 -\r
 -\r
 -void buttons_init()\r
 -{\r
 -  #ifdef NEWPANEL\r
 -    pinMode(BTN_EN1,INPUT);\r
 -    pinMode(BTN_EN2,INPUT); \r
 -    pinMode(BTN_ENC,INPUT); \r
 -    pinMode(SDCARDDETECT,INPUT);\r
 -    WRITE(BTN_EN1,HIGH);\r
 -    WRITE(BTN_EN2,HIGH);\r
 -    WRITE(BTN_ENC,HIGH);\r
 -    WRITE(SDCARDDETECT,HIGH);\r
 -  #else\r
 -    pinMode(SHIFT_CLK,OUTPUT);\r
 -    pinMode(SHIFT_LD,OUTPUT);\r
 -    pinMode(SHIFT_EN,OUTPUT);\r
 -    pinMode(SHIFT_OUT,INPUT);\r
 -    WRITE(SHIFT_OUT,HIGH);\r
 -    WRITE(SHIFT_LD,HIGH); \r
 -    WRITE(SHIFT_EN,LOW); \r
 -  #endif\r
 -}\r
 -\r
 -\r
 -void buttons_check()\r
 -{\r
 -  \r
 -  #ifdef NEWPANEL\r
 -    uint8_t newbutton=0;\r
 -    if(READ(BTN_EN1)==0)  newbutton|=EN_A;\r
 -    if(READ(BTN_EN2)==0)  newbutton|=EN_B;\r
 -    if((blocking<millis()) &&(READ(BTN_ENC)==0))\r
 -      newbutton|=EN_C;\r
 -    buttons=newbutton;\r
 -  #else   //read it from the shift register\r
 -    uint8_t newbutton=0;\r
 -    WRITE(SHIFT_LD,LOW);\r
 -    WRITE(SHIFT_LD,HIGH);\r
 -    unsigned char tmp_buttons=0;\r
 -    for(int8_t i=0;i<8;i++)\r
 -    { \r
 -      newbutton = newbutton>>1;\r
 -      if(READ(SHIFT_OUT))\r
 -        newbutton|=(1<<7);\r
 -      WRITE(SHIFT_CLK,HIGH);\r
 -      WRITE(SHIFT_CLK,LOW);\r
 -    }\r
 -    buttons=~newbutton; //invert it, because a pressed switch produces a logical 0\r
 -  #endif\r
 -  \r
 -  //manage encoder rotation\r
 -  char enc=0;\r
 -  if(buttons&EN_A)\r
 -    enc|=(1<<0);\r
 -  if(buttons&EN_B)\r
 -    enc|=(1<<1);\r
 -  if(enc!=lastenc)\r
 -      {\r
 -    switch(enc)\r
 -    {\r
 -    case encrot0:\r
 -      if(lastenc==encrot3)\r
 -        encoderpos++;\r
 -      else if(lastenc==encrot1)\r
 -        encoderpos--;\r
 -      break;\r
 -    case encrot1:\r
 -      if(lastenc==encrot0)\r
 -        encoderpos++;\r
 -      else if(lastenc==encrot2)\r
 -        encoderpos--;\r
 -      break;\r
 -    case encrot2:\r
 -      if(lastenc==encrot1)\r
 -        encoderpos++;\r
 -      else if(lastenc==encrot3)\r
 -        encoderpos--;\r
 -      break;\r
 -    case encrot3:\r
 -      if(lastenc==encrot2)\r
 -        encoderpos++;\r
 -      else if(lastenc==encrot0)\r
 -        encoderpos--;\r
 -      break;\r
 -    default:\r
 -      ;\r
 -    }\r
 -  }\r
 -  lastenc=enc;\r
 -}\r
 -\r
 -#endif\r
 -\r
 -MainMenu::MainMenu()\r
 -{\r
 -  status=Main_Status;\r
 -  displayStartingRow=0;\r
 -  activeline=0;\r
 -  force_lcd_update=true;\r
 -  #ifdef ULTIPANEL\r
 -    buttons_init();\r
 -  #endif\r
 -  lcd_init();\r
 -  linechanging=false;\r
 -  tune=false;\r
 -}\r
 -\r
 -void MainMenu::showStatus()\r
 -{ \r
 -#if LCD_HEIGHT==4\r
 -  static int olddegHotEnd0=-1;\r
 -  static int oldtargetHotEnd0=-1;\r
 -  //force_lcd_update=true;\r
 -  if(force_lcd_update||feedmultiplychanged)  //initial display of content\r
 -  {\r
 -    feedmultiplychanged=false;\r
 -    encoderpos=feedmultiply;\r
 -    clear();\r
 -    lcd.setCursor(0,0);lcdprintPGM("\002123/567\001 ");\r
 -    #if defined BED_USES_THERMISTOR || defined BED_USES_AD595 \r
 -      lcd.setCursor(10,0);lcdprintPGM("B123/567\001 ");\r
 -    #endif\r
 -  }\r
 -    \r
 -  int tHotEnd0=intround(degHotend0());\r
 -  if((abs(tHotEnd0-olddegHotEnd0)>1)||force_lcd_update) //>1 because otherwise the lcd is refreshed to often.\r
 -  {\r
 -    lcd.setCursor(1,0);\r
 -    lcd.print(ftostr3(tHotEnd0));\r
 -    olddegHotEnd0=tHotEnd0;\r
 -  }\r
 -  int ttHotEnd0=intround(degTargetHotend0());\r
 -  if((ttHotEnd0!=oldtargetHotEnd0)||force_lcd_update)\r
 -  {\r
 -    lcd.setCursor(5,0);\r
 -    lcd.print(ftostr3(ttHotEnd0));\r
 -    oldtargetHotEnd0=ttHotEnd0;\r
 -  }\r
 -  #if defined BED_USES_THERMISTOR || defined BED_USES_AD595 \r
 -    static int oldtBed=-1;\r
 -    static int oldtargetBed=-1; \r
 -    int tBed=intround(degBed());\r
 -    if((tBed!=oldtBed)||force_lcd_update)\r
 -    {\r
 -      lcd.setCursor(1,0);\r
 -      lcd.print(ftostr3(tBed));\r
 -      oldtBed=tBed;\r
 -    }\r
 -    int targetBed=intround(degTargetBed());\r
 -    if((targetBed!=oldtargetBed)||force_lcd_update)\r
 -    {\r
 -      lcd.setCursor(5,0);\r
 -      lcd.print(ftostr3(targetBed));\r
 -      oldtargetBed=targetBed;\r
 -    }\r
 -  #endif\r
 -  //starttime=2;\r
 -  static uint16_t oldtime=0;\r
 -  if(starttime!=0)\r
 -  {\r
 -    lcd.setCursor(0,1);\r
 -    uint16_t time=millis()/60000-starttime/60000;\r
 -    \r
 -    if(starttime!=oldtime)\r
 -    {\r
 -      lcd.print(itostr2(time/60));lcdprintPGM("h ");lcd.print(itostr2(time%60));lcdprintPGM("m");\r
 -      oldtime=time;\r
 -    }\r
 -  }\r
 -  static int oldzpos=0;\r
 -  int currentz=current_position[2]*10;\r
 -  if((currentz!=oldzpos)||force_lcd_update)\r
 -  {\r
 -    lcd.setCursor(10,1);\r
 -    lcdprintPGM("Z:");lcd.print(itostr31(currentz));\r
 -    oldzpos=currentz;\r
 -  }\r
 -  static int oldfeedmultiply=0;\r
 -  int curfeedmultiply=feedmultiply;\r
 -  if(encoderpos!=curfeedmultiply||force_lcd_update)\r
 -  {\r
 -   curfeedmultiply=encoderpos;\r
 -   if(curfeedmultiply<10)\r
 -     curfeedmultiply=10;\r
 -   if(curfeedmultiply>999)\r
 -     curfeedmultiply=999;\r
 -   feedmultiply=curfeedmultiply;\r
 -   encoderpos=curfeedmultiply;\r
 -  }\r
 -  if((curfeedmultiply!=oldfeedmultiply)||force_lcd_update)\r
 -  {\r
 -   oldfeedmultiply=curfeedmultiply;\r
 -   lcd.setCursor(0,2);\r
 -   lcd.print(itostr3(curfeedmultiply));lcdprintPGM("% ");\r
 -  }\r
 -  if(messagetext[0]!='\0')\r
 -  {\r
 -    lcd.setCursor(0,LCD_HEIGHT-1);\r
 -    lcd.print(messagetext);\r
 -    uint8_t n=strlen(messagetext);\r
 -    for(int8_t i=0;i<LCD_WIDTH-n;i++)\r
 -      lcd.print(" ");\r
 -    \r
 -    messagetext[0]='\0';\r
 -  }\r
 -  \r
 -  static uint8_t oldpercent=101;\r
 -  uint8_t percent=card.percentDone();\r
 -  if(oldpercent!=percent ||force_lcd_update)\r
 -  {\r
 -     lcd.setCursor(7,2);\r
 -    lcd.print(itostr3((int)percent));\r
 -    lcdprintPGM("%SD");\r
 -    \r
 -  }\r
 -  \r
 -#else //smaller LCDS----------------------------------\r
 -  static int olddegHotEnd0=-1;\r
 -  static int oldtargetHotEnd0=-1;\r
 -  if(force_lcd_update)  //initial display of content\r
 -  {\r
 -    encoderpos=feedmultiply;\r
 -    lcd.setCursor(0,0);lcdprintPGM("\002123/567\001 ");\r
 -    #if defined BED_USES_THERMISTOR || defined BED_USES_AD595 \r
 -    lcd.setCursor(10,0);lcdprintPGM("B123/567\001 ");\r
 -    #endif\r
 -  }\r
 -    \r
 -  int tHotEnd0=intround(degHotend0());\r
 -  int ttHotEnd0=intround(degTargetHotend0());\r
 -\r
 -\r
 -  if((abs(tHotEnd0-olddegHotEnd0)>1)||force_lcd_update)\r
 -  {\r
 -    lcd.setCursor(1,0);\r
 -    lcd.print(ftostr3(tHotEnd0));\r
 -    olddegHotEnd0=tHotEnd0;\r
 -  }\r
 -  if((ttHotEnd0!=oldtargetHotEnd0)||force_lcd_update)\r
 -  {\r
 -    lcd.setCursor(5,0);\r
 -    lcd.print(ftostr3(ttHotEnd0));\r
 -    oldtargetHotEnd0=ttHotEnd0;\r
 -  }\r
 -\r
 -  if(messagetext[0]!='\0')\r
 -  {\r
 -    lcd.setCursor(0,LCD_HEIGHT-1);\r
 -    lcd.print(messagetext);\r
 -    uint8_t n=strlen(messagetext);\r
 -    for(int8_t i=0;i<LCD_WIDTH-n;i++)\r
 -      lcd.print(" ");\r
 -    messagetext[0]='\0';\r
 -  }\r
 -\r
 -#endif\r
 -  force_lcd_update=false;\r
 -}\r
 -\r
 -enum {ItemP_exit, ItemP_autostart,ItemP_disstep,ItemP_home, ItemP_origin, ItemP_preheat, ItemP_extrude};\r
 -\r
 -//any action must not contain a ',' character anywhere, or this breaks:\r
 -#define MENUITEM(repaint_action, click_action) \\r
 -  {\\r
 -    if(force_lcd_update)  { lcd.setCursor(0,line);  repaint_action; } \\r
 -    if((activeline==line) && CLICKED) {click_action} \\r
 -  }\r
 -  \r
 -void MainMenu::showPrepare()\r
 -{\r
 - uint8_t line=0;\r
 - clearIfNecessary();\r
 - for(int8_t i=lineoffset;i<lineoffset+LCD_HEIGHT;i++)\r
 - {\r
 -   //Serial.println((int)(line-lineoffset));\r
 -  switch(i)\r
 -  {\r
 -    case ItemP_exit:\r
 -      MENUITEM(  lcdprintPGM(" Main \003")  ,  BLOCK;status=Main_Menu;beepshort(); ) ;\r
 -      break;\r
 -    case ItemP_autostart:\r
 -      MENUITEM(  lcdprintPGM(" Autostart")  ,  BLOCK;card.lastnr=0;card.checkautostart(true);beepshort(); ) ;\r
 -      break;\r
 -    case ItemP_disstep:\r
 -      MENUITEM(  lcdprintPGM(" Disable Steppers")  ,  BLOCK;enquecommand("M84");beepshort(); ) ;\r
 -      break;\r
 -    case ItemP_home:\r
 -      MENUITEM(  lcdprintPGM(" Auto Home")  ,  BLOCK;enquecommand("G28 X-105 Y-105 Z0");beepshort(); ) ;\r
 -      break;\r
 -    case ItemP_origin:\r
 -      MENUITEM(  lcdprintPGM(" Set Origin")  ,  BLOCK;enquecommand("G92 X0 Y0 Z0");beepshort(); ) ;\r
 -      break;\r
 -    case ItemP_preheat:\r
 -      MENUITEM(  lcdprintPGM(" Preheat")  ,  BLOCK;setTargetHotend0(170);beepshort(); ) ;\r
 -      break;\r
 -    case ItemP_extrude:\r
 -      MENUITEM(  lcdprintPGM(" Extrude")  ,  BLOCK;enquecommand("G92 E0");enquecommand("G1 F700 E50");beepshort(); ) ;\r
 -      break;\r
 -    \r
 -    \r
 -    default:   \r
 -      break;\r
 -  }\r
 -  line++;\r
 - }\r
 - updateActiveLines(ItemP_extrude,encoderpos);\r
 -}\r
 -\r
 -enum {ItemT_exit,ItemT_speed,ItemT_flow,ItemT_nozzle,ItemT_fan};\r
 -\r
 -void MainMenu::showTune()\r
 -{ \r
 -  uint8_t line=0;\r
 -  clearIfNecessary();\r
 - for(int8_t i=lineoffset;i<lineoffset+LCD_HEIGHT;i++)\r
 - {\r
 -   //Serial.println((int)(line-lineoffset));\r
 -  switch(i)\r
 -  {\r
 -  case ItemT_exit:\r
 -      MENUITEM(  lcdprintPGM(" Main \003")  ,  BLOCK;status=Main_Menu;beepshort(); ) ;\r
 -      break;\r
 -  case ItemT_speed:\r
 -    {\r
 -      if(force_lcd_update)\r
 -      {\r
 -        lcd.setCursor(0,line);lcdprintPGM(" Speed:");\r
 -        lcd.setCursor(13,line);lcd.print(ftostr3(feedmultiply));\r
 -      }\r
 -      \r
 -      if((activeline!=line) )\r
 -        break;\r
 -      \r
 -      if(CLICKED) //nalogWrite(FAN_PIN,  fanpwm);\r
 -      {\r
 -        linechanging=!linechanging;\r
 -        if(linechanging)\r
 -        {\r
 -            encoderpos=feedmultiply;\r
 -        }\r
 -        else\r
 -        {\r
 -          encoderpos=activeline*lcdslow;\r
 -          beepshort();\r
 -        }\r
 -        BLOCK;\r
 -      }\r
 -      if(linechanging)\r
 -      {\r
 -        if(encoderpos<1) encoderpos=1;\r
 -        if(encoderpos>400) encoderpos=400;\r
 -        feedmultiply = encoderpos;\r
 -        feedmultiplychanged=true;\r
 -        lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));\r
 -      }\r
 -      \r
 -    }break;\r
 -    case ItemT_nozzle:\r
 -      {\r
 -        if(force_lcd_update)\r
 -        {\r
 -          lcd.setCursor(0,line);lcdprintPGM(" \002Nozzle:");\r
 -          lcd.setCursor(13,line);lcd.print(ftostr3(intround(degTargetHotend0())));\r
 -        }\r
 -        \r
 -        if((activeline!=line) )\r
 -          break;\r
 -        \r
 -        if(CLICKED)\r
 -        {\r
 -          linechanging=!linechanging;\r
 -          if(linechanging)\r
 -          {\r
 -              encoderpos=intround(degTargetHotend0());\r
 -          }\r
 -          else\r
 -          {\r
 -            setTargetHotend0(encoderpos);\r
 -            encoderpos=activeline*lcdslow;\r
 -            beepshort();\r
 -          }\r
 -          BLOCK;\r
 -        }\r
 -        if(linechanging)\r
 -        {\r
 -          if(encoderpos<0) encoderpos=0;\r
 -          if(encoderpos>260) encoderpos=260;\r
 -          lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));\r
 -        }\r
 -      }break;\r
 -      \r
 -      case ItemT_fan:\r
 -      {\r
 -        if(force_lcd_update)\r
 -        {\r
 -          lcd.setCursor(0,line);lcdprintPGM(" Fan speed:");\r
 -          lcd.setCursor(13,line);lcd.print(ftostr3(fanpwm));\r
 -        }\r
 -        \r
 -        if((activeline!=line) )\r
 -          break;\r
 -        \r
 -        if(CLICKED) //nalogWrite(FAN_PIN,  fanpwm);\r
 -        {\r
 -          linechanging=!linechanging;\r
 -          if(linechanging)\r
 -          {\r
 -              encoderpos=fanpwm;\r
 -          }\r
 -          else\r
 -          {\r
 -            encoderpos=activeline*lcdslow;\r
 -            beepshort();\r
 -          }\r
 -          BLOCK;\r
 -        }\r
 -        if(linechanging)\r
 -        {\r
 -          if(encoderpos<0) encoderpos=0;\r
 -          if(encoderpos>255) encoderpos=255;\r
 -          fanpwm=encoderpos;\r
 -            analogWrite(FAN_PIN,  fanpwm);\r
 -          lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));\r
 -        }\r
 -        \r
 -      }break;\r
 -      case ItemT_flow://axis_steps_per_unit[i] = code_value();\r
 -         {\r
 -      if(force_lcd_update)\r
 -        {\r
 -          lcd.setCursor(0,line);lcdprintPGM(" Flow:");\r
 -          lcd.setCursor(13,line);lcd.print(itostr4(axis_steps_per_unit[3]));\r
 -        }\r
 -        \r
 -        if((activeline!=line) )\r
 -          break;\r
 -        \r
 -        if(CLICKED)\r
 -        {\r
 -          linechanging=!linechanging;\r
 -          if(linechanging)\r
 -          {\r
 -              encoderpos=(int)axis_steps_per_unit[3];\r
 -          }\r
 -          else\r
 -          {\r
 -            float factor=float(encoderpos)/float(axis_steps_per_unit[3]);\r
 -            position[E_AXIS]=lround(position[E_AXIS]*factor);\r
 -            //current_position[3]*=factor;\r
 -            axis_steps_per_unit[E_AXIS]= encoderpos;\r
 -            encoderpos=activeline*lcdslow;\r
 -              \r
 -          }\r
 -          BLOCK;\r
 -          beepshort();\r
 -        }\r
 -        if(linechanging)\r
 -        {\r
 -          if(encoderpos<5) encoderpos=5;\r
 -          if(encoderpos>9999) encoderpos=9999;\r
 -          lcd.setCursor(13,line);lcd.print(itostr4(encoderpos));\r
 -        }\r
 -        \r
 -      }break; \r
 -    default:   \r
 -      break;\r
 -  }\r
 -  line++;\r
 - }\r
 - updateActiveLines(ItemT_fan,encoderpos);\r
 -}\r
 -\r
 -//does not work\r
 -// #define MENUCHANGEITEM(repaint_action,  enter_action, accept_action,  change_action) \\r
 -//   {\\r
 -//     if(force_lcd_update)  { lcd.setCursor(0,line);  repaint_action; } \\r
 -//     if(activeline==line)  \\r
 -//     { \\r
 -//       if(CLICKED) \\r
 -//       { \\r
 -//         linechanging=!linechanging; \\r
 -//         if(linechanging)  {enter_action;} \\r
 -//         else {accept_action;} \\r
 -//       }  \\r
 -//       else \\r
 -//       if(linechanging) {change_action};}\\r
 -//   }\r
 -//   \r
 -\r
 -enum {\r
 -  ItemCT_exit,ItemCT_nozzle,\r
 -#ifdef AUTOTEMP\r
 -  ItemCT_autotempactive,\r
 -  ItemCT_autotempmin,ItemCT_autotempmax,ItemCT_autotempfact,\r
 -#endif\r
 -  ItemCT_fan,\r
 -  ItemCT_PID_P,ItemCT_PID_I,ItemCT_PID_D,ItemCT_PID_C\r
 -};\r
 -\r
 -void MainMenu::showControlTemp()\r
 -{\r
 -  uint8_t line=0;\r
 - clearIfNecessary();\r
 - for(int8_t i=lineoffset;i<lineoffset+LCD_HEIGHT;i++)\r
 - {\r
 -  switch(i)\r
 -  {\r
 -    case ItemCT_exit:\r
 -      MENUITEM(  lcdprintPGM(" Control \003")  ,  BLOCK;status=Main_Control;beepshort(); ) ;\r
 -      break;\r
 -    case ItemCT_nozzle:\r
 -      {\r
 -        if(force_lcd_update)\r
 -        {\r
 -          lcd.setCursor(0,line);lcdprintPGM(" \002Nozzle:");\r
 -          lcd.setCursor(13,line);lcd.print(ftostr3(intround(degTargetHotend0())));\r
 -        }\r
 -        \r
 -        if((activeline!=line) )\r
 -          break;\r
 -        \r
 -        if(CLICKED)\r
 -        {\r
 -          linechanging=!linechanging;\r
 -          if(linechanging)\r
 -          {\r
 -              encoderpos=intround(degTargetHotend0());\r
 -          }\r
 -          else\r
 -          {\r
 -            setTargetHotend0(encoderpos);\r
 -            encoderpos=activeline*lcdslow;\r
 -            beepshort();\r
 -          }\r
 -          BLOCK;\r
 -        }\r
 -        if(linechanging)\r
 -        {\r
 -          if(encoderpos<0) encoderpos=0;\r
 -          if(encoderpos>260) encoderpos=260;\r
 -          lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));\r
 -        }\r
 -        \r
 -      }break;\r
 -      #ifdef AUTOTEMP\r
 -      case ItemCT_autotempmin:\r
 -      {\r
 -        if(force_lcd_update)\r
 -        {\r
 -          lcd.setCursor(0,line);lcdprintPGM(" \002 Min:");\r
 -          lcd.setCursor(13,line);lcd.print(ftostr3(autotemp_min));\r
 -        }\r
 -        \r
 -        if((activeline!=line) )\r
 -          break;\r
 -        \r
 -        if(CLICKED)\r
 -        {\r
 -          linechanging=!linechanging;\r
 -          if(linechanging)\r
 -          {\r
 -              encoderpos=intround(autotemp_min);\r
 -          }\r
 -          else\r
 -          {\r
 -            autotemp_min=encoderpos;\r
 -            encoderpos=activeline*lcdslow;\r
 -            beepshort();\r
 -          }\r
 -          BLOCK;\r
 -        }\r
 -        if(linechanging)\r
 -        {\r
 -          if(encoderpos<0) encoderpos=0;\r
 -          if(encoderpos>260) encoderpos=260;\r
 -          lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));\r
 -        }\r
 -        \r
 -      }break;  \r
 -      case ItemCT_autotempmax:\r
 -      {\r
 -        if(force_lcd_update)\r
 -        {\r
 -          lcd.setCursor(0,line);lcdprintPGM(" \002 Max:");\r
 -          lcd.setCursor(13,line);lcd.print(ftostr3(autotemp_max));\r
 -        }\r
 -        \r
 -        if((activeline!=line) )\r
 -          break;\r
 -        \r
 -        if(CLICKED)\r
 -        {\r
 -          linechanging=!linechanging;\r
 -          if(linechanging)\r
 -          {\r
 -              encoderpos=intround(autotemp_max);\r
 -          }\r
 -          else\r
 -          {\r
 -            autotemp_max=encoderpos;\r
 -            encoderpos=activeline*lcdslow;\r
 -            beepshort();\r
 -          }\r
 -          BLOCK;\r
 -        }\r
 -        if(linechanging)\r
 -        {\r
 -          if(encoderpos<0) encoderpos=0;\r
 -          if(encoderpos>260) encoderpos=260;\r
 -          lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));\r
 -        }\r
 -        \r
 -      }break;  \r
 -      case ItemCT_autotempfact:\r
 -      {\r
 -        if(force_lcd_update)\r
 -        {\r
 -          lcd.setCursor(0,line);lcdprintPGM(" \002 Fact:");\r
 -          lcd.setCursor(13,line);lcd.print(ftostr32(autotemp_factor));\r
 -        }\r
 -        \r
 -        if((activeline!=line) )\r
 -          break;\r
 -        \r
 -        if(CLICKED)\r
 -        {\r
 -          linechanging=!linechanging;\r
 -          if(linechanging)\r
 -          {\r
 -              encoderpos=intround(autotemp_factor*100);\r
 -          }\r
 -          else\r
 -          {\r
 -            autotemp_max=encoderpos;\r
 -            encoderpos=activeline*lcdslow;\r
 -            beepshort();\r
 -          }\r
 -          BLOCK;\r
 -        }\r
 -        if(linechanging)\r
 -        {\r
 -          if(encoderpos<0) encoderpos=0;\r
 -          if(encoderpos>99) encoderpos=99;\r
 -          lcd.setCursor(13,line);lcd.print(ftostr32(encoderpos/100.));\r
 -        }\r
 -        \r
 -      }break;\r
 -      case ItemCT_autotempactive:\r
 -      {\r
 -        if(force_lcd_update)\r
 -        {\r
 -          lcd.setCursor(0,line);lcdprintPGM(" Autotemp:");\r
 -          lcd.setCursor(13,line);\r
 -          if(autotemp_enabled)\r
 -            lcdprintPGM("On");\r
 -          else\r
 -            lcdprintPGM("Off");\r
 -        }\r
 -        \r
 -        if((activeline!=line) )\r
 -          break;\r
 -        \r
 -        if(CLICKED)\r
 -        {\r
 -          autotemp_enabled=!autotemp_enabled;\r
 -          lcd.setCursor(13,line);\r
 -          if(autotemp_enabled)\r
 -            lcdprintPGM("On ");\r
 -          else\r
 -            lcdprintPGM("Off");\r
 -          BLOCK;\r
 -        }\r
 -        \r
 -      }break;  \r
 -      #endif //autotemp\r
 -      case ItemCT_fan:\r
 -      {\r
 -        if(force_lcd_update)\r
 -        {\r
 -          lcd.setCursor(0,line);lcdprintPGM(" Fan speed:");\r
 -          lcd.setCursor(13,line);lcd.print(ftostr3(fanpwm));\r
 -        }\r
 -        \r
 -        if((activeline!=line) )\r
 -          break;\r
 -        \r
 -        if(CLICKED) //nalogWrite(FAN_PIN,  fanpwm);\r
 -        {\r
 -          linechanging=!linechanging;\r
 -          if(linechanging)\r
 -          {\r
 -              encoderpos=fanpwm;\r
 -          }\r
 -          else\r
 -          {\r
 -            encoderpos=activeline*lcdslow;\r
 -            beepshort();\r
 -          }\r
 -          BLOCK;\r
 -        }\r
 -        if(linechanging)\r
 -        {\r
 -          if(encoderpos<0) encoderpos=0;\r
 -          if(encoderpos>255) encoderpos=255;\r
 -          fanpwm=encoderpos;\r
 -            analogWrite(FAN_PIN,  fanpwm);\r
 -          lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));\r
 -        }\r
 -        \r
 -      }break;\r
 -      case ItemCT_PID_P: \r
 -      {\r
 -      if(force_lcd_update)\r
 -        {\r
 -          lcd.setCursor(0,line);lcdprintPGM(" PID-P: ");\r
 -          lcd.setCursor(13,line);lcd.print(itostr4(Kp));\r
 -        }\r
 -        \r
 -        if((activeline!=line) )\r
 -          break;\r
 -        \r
 -        if(CLICKED)\r
 -        {\r
 -          linechanging=!linechanging;\r
 -          if(linechanging)\r
 -          {\r
 -              encoderpos=(int)Kp;\r
 -          }\r
 -          else\r
 -          {\r
 -            Kp= encoderpos;\r
 -            encoderpos=activeline*lcdslow;\r
 -              \r
 -          }\r
 -          BLOCK;\r
 -          beepshort();\r
 -        }\r
 -        if(linechanging)\r
 -        {\r
 -          if(encoderpos<1) encoderpos=1;\r
 -          if(encoderpos>9990) encoderpos=9990;\r
 -          lcd.setCursor(13,line);lcd.print(itostr4(encoderpos));\r
 -        }\r
 -        \r
 -      }break;\r
 -    case ItemCT_PID_I: \r
 -      {\r
 -      if(force_lcd_update)\r
 -        {\r
 -          lcd.setCursor(0,line);lcdprintPGM(" PID-I: ");\r
 -          lcd.setCursor(13,line);lcd.print(ftostr51(Ki/PID_dT));\r
 -        }\r
 -        \r
 -        if((activeline!=line) )\r
 -          break;\r
 -        \r
 -        if(CLICKED)\r
 -        {\r
 -          linechanging=!linechanging;\r
 -          if(linechanging)\r
 -          {\r
 -              encoderpos=(int)(Ki*10/PID_dT);\r
 -          }\r
 -          else\r
 -          {\r
 -            Ki= encoderpos/10.*PID_dT;\r
 -            encoderpos=activeline*lcdslow;\r
 -              \r
 -          }\r
 -          BLOCK;\r
 -          beepshort();\r
 -        }\r
 -        if(linechanging)\r
 -        {\r
 -          if(encoderpos<0) encoderpos=0;\r
 -          if(encoderpos>9990) encoderpos=9990;\r
 -          lcd.setCursor(13,line);lcd.print(ftostr51(encoderpos/10.));\r
 -        }\r
 -        \r
 -      }break;\r
 -      case ItemCT_PID_D: \r
 -      {\r
 -      if(force_lcd_update)\r
 -        {\r
 -          lcd.setCursor(0,line);lcdprintPGM(" PID-D: ");\r
 -          lcd.setCursor(13,line);lcd.print(itostr4(Kd*PID_dT));\r
 -        }\r
 -        \r
 -        if((activeline!=line) )\r
 -          break;\r
 -        \r
 -        \r
 -        if(CLICKED)\r
 -        {\r
 -          linechanging=!linechanging;\r
 -          if(linechanging)\r
 -          {\r
 -              encoderpos=(int)(Kd/5./PID_dT);\r
 -          }\r
 -          else\r
 -          {\r
 -            Kd= encoderpos;\r
 -            encoderpos=activeline*lcdslow;\r
 -              \r
 -          }\r
 -          BLOCK;\r
 -          beepshort();\r
 -        }\r
 -        if(linechanging)\r
 -        {\r
 -          if(encoderpos<0) encoderpos=0;\r
 -          if(encoderpos>9990) encoderpos=9990;\r
 -          lcd.setCursor(13,line);lcd.print(itostr4(encoderpos));\r
 -        }\r
 -       \r
 -      }break;   \r
 -    case ItemCT_PID_C: \r
 -      #ifdef PID_ADD_EXTRUSION_RATE\r
 -      {\r
 -      if(force_lcd_update)\r
 -        {\r
 -          lcd.setCursor(0,line);lcdprintPGM(" PID-C: ");\r
 -          lcd.setCursor(13,line);lcd.print(itostr3(Kc));\r
 -        }\r
 -        \r
 -        if((activeline!=line) )\r
 -          break;\r
 -        \r
 -        if(CLICKED)\r
 -        {\r
 -          linechanging=!linechanging;\r
 -          if(linechanging)\r
 -          {\r
 -              encoderpos=(int)Kc;\r
 -          }\r
 -          else\r
 -          {\r
 -            Kc= encoderpos;\r
 -            encoderpos=activeline*lcdslow;\r
 -              \r
 -          }\r
 -          BLOCK;\r
 -          beepshort();\r
 -        }\r
 -        if(linechanging)\r
 -        {\r
 -          if(encoderpos<0) encoderpos=0;\r
 -          if(encoderpos>990) encoderpos=990;\r
 -          lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));\r
 -        }\r
 -        \r
 -      }\r
 -      #endif\r
 -      break;\r
 -    default:   \r
 -      break;\r
 -  }\r
 -  line++;\r
 - }\r
 - #ifdef PID_ADD_EXTRUSION_RATE\r
 -  updateActiveLines(ItemCT_PID_C,encoderpos);\r
 - #else\r
 -  updateActiveLines(ItemCT_PID_D,encoderpos);\r
 - #endif\r
 -}\r
 -\r
 -\r
 -enum {\r
 -  ItemCM_exit, \r
 -  ItemCM_acc, ItemCM_xyjerk, \r
 -  ItemCM_vmaxx, ItemCM_vmaxy, ItemCM_vmaxz, ItemCM_vmaxe, \r
 -  ItemCM_vtravmin,ItemCM_vmin,  \r
 -  ItemCM_amaxx, ItemCM_amaxy, ItemCM_amaxz, ItemCM_amaxe, \r
 -  ItemCM_aret,ItemCM_esteps\r
 -};\r
 -\r
 -\r
 -\r
 -void MainMenu::showControlMotion()\r
 -{\r
 - uint8_t line=0;\r
 - clearIfNecessary();\r
 - for(int8_t i=lineoffset;i<lineoffset+LCD_HEIGHT;i++)\r
 - {\r
 -  switch(i)\r
 -  {\r
 -    case ItemCM_exit:\r
 -      MENUITEM(  lcdprintPGM(" Control \003")  ,  BLOCK;status=Main_Control;beepshort(); ) ;\r
 -      break;\r
 -    case ItemCM_acc:\r
 -    {\r
 -      if(force_lcd_update)\r
 -        {\r
 -          lcd.setCursor(0,line);lcdprintPGM(" Acc:");\r
 -          lcd.setCursor(13,line);lcd.print(itostr3(acceleration/100));lcdprintPGM("00");\r
 -        }\r
 -        \r
 -        if((activeline!=line) )\r
 -          break;\r
 -        \r
 -        if(CLICKED)\r
 -        {\r
 -          linechanging=!linechanging;\r
 -          if(linechanging)\r
 -          {\r
 -              encoderpos=(int)acceleration/100;\r
 -          }\r
 -          else\r
 -          {\r
 -            acceleration= encoderpos*100;\r
 -            encoderpos=activeline*lcdslow;\r
 -          }\r
 -          BLOCK;\r
 -          beepshort();\r
 -        }\r
 -        if(linechanging)\r
 -        {\r
 -          if(encoderpos<5) encoderpos=5;\r
 -          if(encoderpos>990) encoderpos=990;\r
 -          lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcdprintPGM("00");\r
 -        }\r
 -        \r
 -      }break;\r
 -    case ItemCM_xyjerk: //max_xy_jerk\r
 -      {\r
 -      if(force_lcd_update)\r
 -        {\r
 -          lcd.setCursor(0,line);lcdprintPGM(" Vxy-jerk: ");\r
 -          lcd.setCursor(13,line);lcd.print(itostr3(max_xy_jerk));\r
 -        }\r
 -        \r
 -        if((activeline!=line) )\r
 -          break;\r
 -        \r
 -        if(CLICKED)\r
 -        {\r
 -          linechanging=!linechanging;\r
 -          if(linechanging)\r
 -          {\r
 -              encoderpos=(int)max_xy_jerk;\r
 -          }\r
 -          else\r
 -          {\r
 -            max_xy_jerk= encoderpos;\r
 -            encoderpos=activeline*lcdslow;\r
 -              \r
 -          }\r
 -          BLOCK;\r
 -          beepshort();\r
 -        }\r
 -        if(linechanging)\r
 -        {\r
 -          if(encoderpos<1) encoderpos=1;\r
 -          if(encoderpos>990) encoderpos=990;\r
 -          lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));\r
 -        }\r
 -        \r
 -      }break;\r
 -      \r
 -    case ItemCM_vmaxx:\r
 -    case ItemCM_vmaxy:\r
 -    case ItemCM_vmaxz:\r
 -    case ItemCM_vmaxe:\r
 -      {\r
 -      if(force_lcd_update)\r
 -        {\r
 -          lcd.setCursor(0,line);lcdprintPGM(" Vmax ");\r
 -          if(i==ItemCM_vmaxx)lcdprintPGM("x:");\r
 -          if(i==ItemCM_vmaxy)lcdprintPGM("y:");\r
 -          if(i==ItemCM_vmaxz)lcdprintPGM("z:");\r
 -          if(i==ItemCM_vmaxe)lcdprintPGM("e:");\r
 -          lcd.setCursor(13,line);lcd.print(itostr3(max_feedrate[i-ItemCM_vmaxx]));\r
 -        }\r
 -        \r
 -        if((activeline!=line) )\r
 -          break;\r
 -        \r
 -        if(CLICKED)\r
 -        {\r
 -          linechanging=!linechanging;\r
 -          if(linechanging)\r
 -          {\r
 -              encoderpos=(int)max_feedrate[i-ItemCM_vmaxx];\r
 -          }\r
 -          else\r
 -          {\r
 -            max_feedrate[i-ItemCM_vmaxx]= encoderpos;\r
 -            encoderpos=activeline*lcdslow;\r
 -              \r
 -          }\r
 -          BLOCK;\r
 -          beepshort();\r
 -        }\r
 -        if(linechanging)\r
 -        {\r
 -          if(encoderpos<1) encoderpos=1;\r
 -          if(encoderpos>990) encoderpos=990;\r
 -          lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));\r
 -        }\r
 -        \r
 -      }break;\r
 -    \r
 -    case ItemCM_vmin:\r
 -    {\r
 -      if(force_lcd_update)\r
 -        {\r
 -          lcd.setCursor(0,line);lcdprintPGM(" Vmin:");\r
 -          lcd.setCursor(13,line);lcd.print(itostr3(minimumfeedrate));\r
 -        }\r
 -        \r
 -        if((activeline!=line) )\r
 -          break;\r
 -        \r
 -        if(CLICKED)\r
 -        {\r
 -          linechanging=!linechanging;\r
 -          if(linechanging)\r
 -          {\r
 -              encoderpos=(int)(minimumfeedrate);\r
 -          }\r
 -          else\r
 -          {\r
 -            minimumfeedrate= encoderpos;\r
 -            encoderpos=activeline*lcdslow;\r
 -              \r
 -          }\r
 -          BLOCK;\r
 -          beepshort();\r
 -        }\r
 -        if(linechanging)\r
 -        {\r
 -          if(encoderpos<0) encoderpos=0;\r
 -          if(encoderpos>990) encoderpos=990;\r
 -          lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));\r
 -        }\r
 -        \r
 -      }break;\r
 -    case ItemCM_vtravmin:\r
 -    {\r
 -      if(force_lcd_update)\r
 -        {\r
 -          lcd.setCursor(0,line);lcdprintPGM(" VTrav min:");\r
 -          lcd.setCursor(13,line);lcd.print(itostr3(mintravelfeedrate));\r
 -        }\r
 -        \r
 -        if((activeline!=line) )\r
 -          break;\r
 -        \r
 -        if(CLICKED)\r
 -        {\r
 -          linechanging=!linechanging;\r
 -          if(linechanging)\r
 -          {\r
 -              encoderpos=(int)mintravelfeedrate;\r
 -          }\r
 -          else\r
 -          {\r
 -            mintravelfeedrate= encoderpos;\r
 -            encoderpos=activeline*lcdslow;\r
 -              \r
 -          }\r
 -          BLOCK;\r
 -          beepshort();\r
 -        }\r
 -        if(linechanging)\r
 -        {\r
 -          if(encoderpos<0) encoderpos=0;\r
 -          if(encoderpos>990) encoderpos=990;\r
 -          lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));\r
 -        }\r
 -        \r
 -      }break;\r
 -    \r
 -    case ItemCM_amaxx:      \r
 -    case ItemCM_amaxy:\r
 -    case ItemCM_amaxz:\r
 -    case ItemCM_amaxe:\r
 -    {\r
 -      if(force_lcd_update)\r
 -        {\r
 -          lcd.setCursor(0,line);lcdprintPGM(" Amax ");\r
 -          if(i==ItemCM_amaxx)lcdprintPGM("x:");\r
 -          if(i==ItemCM_amaxy)lcdprintPGM("y:");\r
 -          if(i==ItemCM_amaxz)lcdprintPGM("z:");\r
 -          if(i==ItemCM_amaxe)lcdprintPGM("e:");\r
 -          lcd.setCursor(13,line);lcd.print(itostr3(max_acceleration_units_per_sq_second[i-ItemCM_amaxx]/100));lcdprintPGM("00");\r
 -        }\r
 -        \r
 -        if((activeline!=line) )\r
 -          break;\r
 -        \r
 -        if(CLICKED)\r
 -        {\r
 -          linechanging=!linechanging;\r
 -          if(linechanging)\r
 -          {\r
 -              encoderpos=(int)max_acceleration_units_per_sq_second[i-ItemCM_amaxx]/100;\r
 -          }\r
 -          else\r
 -          {\r
 -            max_acceleration_units_per_sq_second[i-ItemCM_amaxx]= encoderpos*100;\r
 -            encoderpos=activeline*lcdslow;\r
 -          }\r
 -          BLOCK;\r
 -          beepshort();\r
 -        }\r
 -        if(linechanging)\r
 -        {\r
 -          if(encoderpos<1) encoderpos=1;\r
 -          if(encoderpos>990) encoderpos=990;\r
 -          lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcdprintPGM("00");\r
 -        }\r
 -        \r
 -      }break;\r
 -    case ItemCM_aret://float retract_acceleration = 7000;\r
 -    {\r
 -        if(force_lcd_update)\r
 -        {\r
 -          lcd.setCursor(0,line);lcdprintPGM(" A-retract:");\r
 -          lcd.setCursor(13,line);lcd.print(ftostr3(retract_acceleration/100));lcdprintPGM("00");\r
 -        }\r
 -        \r
 -        if((activeline!=line) )\r
 -          break;\r
 -        \r
 -        if(CLICKED)\r
 -        {\r
 -          linechanging=!linechanging;\r
 -          if(linechanging)\r
 -          {\r
 -              encoderpos=(int)retract_acceleration/100;\r
 -          }\r
 -          else\r
 -          {\r
 -            retract_acceleration= encoderpos*100;\r
 -            encoderpos=activeline*lcdslow;\r
 -              \r
 -          }\r
 -          BLOCK;\r
 -          beepshort();\r
 -        }\r
 -        if(linechanging)\r
 -        {\r
 -          if(encoderpos<10) encoderpos=10;\r
 -          if(encoderpos>990) encoderpos=990;\r
 -          lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcdprintPGM("00");\r
 -        }\r
 -        \r
 -      }break;\r
 -    case ItemCM_esteps://axis_steps_per_unit[i] = code_value();\r
 -         {\r
 -      if(force_lcd_update)\r
 -        {\r
 -          lcd.setCursor(0,line);lcdprintPGM(" Esteps/mm:");\r
 -          lcd.setCursor(13,line);lcd.print(itostr4(axis_steps_per_unit[3]));\r
 -        }\r
 -        \r
 -        if((activeline!=line) )\r
 -          break;\r
 -        \r
 -        if(CLICKED)\r
 -        {\r
 -          linechanging=!linechanging;\r
 -          if(linechanging)\r
 -          {\r
 -              encoderpos=(int)axis_steps_per_unit[3];\r
 -          }\r
 -          else\r
 -          {\r
 -            float factor=float(encoderpos)/float(axis_steps_per_unit[3]);\r
 -            position[E_AXIS]=lround(position[E_AXIS]*factor);\r
 -            //current_position[3]*=factor;\r
 -            axis_steps_per_unit[E_AXIS]= encoderpos;\r
 -            encoderpos=activeline*lcdslow;\r
 -              \r
 -          }\r
 -          BLOCK;\r
 -          beepshort();\r
 -        }\r
 -        if(linechanging)\r
 -        {\r
 -          if(encoderpos<5) encoderpos=5;\r
 -          if(encoderpos>9999) encoderpos=9999;\r
 -          lcd.setCursor(13,line);lcd.print(itostr4(encoderpos));\r
 -        }\r
 -        \r
 -      }break; \r
 -    default:   \r
 -      break;\r
 -  }\r
 -  line++;\r
 - }\r
 - updateActiveLines(ItemCM_esteps,encoderpos);\r
 -}\r
 -\r
 -\r
 -enum {\r
 -  ItemC_exit,ItemC_temp,ItemC_move,\r
 -  ItemC_store, ItemC_load,ItemC_failsafe\r
 -};\r
 -\r
 -void MainMenu::showControl()\r
 -{\r
 - uint8_t line=0;\r
 - clearIfNecessary();\r
 - for(int8_t i=lineoffset;i<lineoffset+LCD_HEIGHT;i++)\r
 - {\r
 -  switch(i)\r
 -  {\r
 -    case ItemC_exit:\r
 -      MENUITEM(  lcdprintPGM(" Main        \003")  ,  BLOCK;status=Main_Menu;beepshort(); ) ;\r
 -      break;\r
 -    case ItemC_temp:\r
 -      MENUITEM(  lcdprintPGM(" Temperature \x7E")  ,  BLOCK;status=Sub_TempControl;beepshort(); ) ;\r
 -      break;\r
 -   case ItemC_move:\r
 -      MENUITEM(  lcdprintPGM(" Motion      \x7E")  ,  BLOCK;status=Sub_MotionControl;beepshort(); ) ;\r
 -      break;\r
 -    case ItemC_store:\r
 -    {\r
 -      if(force_lcd_update)\r
 -      {\r
 -        lcd.setCursor(0,line);lcdprintPGM(" Store EPROM");\r
 -      }\r
 -      if((activeline==line) && CLICKED)\r
 -      {\r
 -        //enquecommand("M84");\r
 -        beepshort();\r
 -        BLOCK;\r
 -        EEPROM_StoreSettings();\r
 -      }\r
 -    }break;\r
 -    case ItemC_load:\r
 -    {\r
 -      if(force_lcd_update)\r
 -      {\r
 -        lcd.setCursor(0,line);lcdprintPGM(" Load EPROM");\r
 -      }\r
 -      if((activeline==line) && CLICKED)\r
 -      {\r
 -        //enquecommand("M84");\r
 -        beepshort();\r
 -        BLOCK;\r
 -        EEPROM_RetrieveSettings();\r
 -      }\r
 -    }break;\r
 -    case ItemC_failsafe:\r
 -    {\r
 -      if(force_lcd_update)\r
 -      {\r
 -        lcd.setCursor(0,line);lcdprintPGM(" Restore Failsafe");\r
 -      }\r
 -      if((activeline==line) && CLICKED)\r
 -      {\r
 -        //enquecommand("M84");\r
 -        beepshort();\r
 -        BLOCK;\r
 -        EEPROM_RetrieveSettings(true);\r
 -      }\r
 -    }break;\r
 -    default:   \r
 -      break;\r
 -  }\r
 -  line++;\r
 - }\r
 - updateActiveLines(ItemC_failsafe,encoderpos);\r
 -}\r
 -\r
 -\r
 -\r
 -\r
 -\r
 -void MainMenu::showSD()\r
 -{\r
 -#ifdef SDSUPPORT\r
 - uint8_t line=0;\r
 -\r
 - clearIfNecessary();\r
 - static uint8_t nrfiles=0;\r
 - if(force_lcd_update)\r
 - {\r
 -  if(card.cardOK)\r
 -  {\r
 -    nrfiles=card.getnrfilenames();\r
 -  }\r
 -  else\r
 -  {\r
 -    nrfiles=0;\r
 -    lineoffset=0;\r
 -  }\r
 - }\r
 - bool enforceupdate=false;\r
 - for(int8_t i=lineoffset;i<lineoffset+LCD_HEIGHT;i++)\r
 - {\r
 -  switch(i)\r
 -  {\r
 -    case 0:\r
 -      MENUITEM(  lcdprintPGM(" Main \003")  ,  BLOCK;status=Main_Menu;beepshort(); ) ;\r
 -      break;\r
 -//     case 1:\r
 -//       {\r
 -//         if(force_lcd_update)\r
 -//         {\r
 -//           lcd.setCursor(0,line);\r
 -//            #ifdef CARDINSERTED\r
 -//           if(CARDINSERTED)\r
 -//           #else\r
 -//           if(true)\r
 -//           #endif\r
 -//           {\r
 -//             lcdprintPGM(" \004Refresh");\r
 -//           }\r
 -//           else\r
 -//           {\r
 -//             lcdprintPGM(" \004Insert Card");\r
 -//           }\r
 -//           \r
 -//         }\r
 -//         if((activeline==line) && CLICKED)\r
 -//         {\r
 -//           BLOCK;\r
 -//           beepshort();\r
 -//           card.initsd();\r
 -//           force_lcd_update=true;\r
 -//            nrfiles=card.getnrfilenames();\r
 -//         }\r
 -//       }break;\r
 -    case 1:\r
 -      MENUITEM(  lcd.print(" ");card.getWorkDirName();if(card.filename[0]=='/') lcdprintPGM("\004Refresh");else {lcd.print("\005");lcd.print(card.filename);lcd.print("/..");}  ,  BLOCK;card.updir();enforceupdate=true;lineoffset=0;beepshort(); ) ;\r
 -      \r
 -      break;\r
 -    default:\r
 -    {\r
 -      #define FIRSTITEM 2\r
 -      if(i-FIRSTITEM<nrfiles)\r
 -      {\r
 -        if(force_lcd_update)\r
 -        {\r
 -          card.getfilename(i-FIRSTITEM);\r
 -          //Serial.print("Filenr:");Serial.println(i-2);\r
 -          lcd.setCursor(0,line);lcdprintPGM(" ");\r
 -          if(card.filenameIsDir) lcd.print("\005");\r
 -          lcd.print(card.filename);\r
 -        }\r
 -        if((activeline==line) && CLICKED)\r
 -        {\r
 -          BLOCK\r
 -          card.getfilename(i-FIRSTITEM);\r
 -          if(card.filenameIsDir)\r
 -          {\r
 -            for(int8_t i=0;i<strlen(card.filename);i++)\r
 -              card.filename[i]=tolower(card.filename[i]);\r
 -            card.chdir(card.filename);\r
 -            lineoffset=0;\r
 -            enforceupdate=true;\r
 -          }\r
 -          else\r
 -          {\r
 -            char cmd[30];\r
 -            for(int8_t i=0;i<strlen(card.filename);i++)\r
 -              card.filename[i]=tolower(card.filename[i]);\r
 -            sprintf(cmd,"M23 %s",card.filename);\r
 -            //sprintf(cmd,"M115");\r
 -            enquecommand(cmd);\r
 -            enquecommand("M24");\r
 -            beep(); \r
 -            status=Main_Status;\r
 -            lcd_status(card.filename);\r
 -          }\r
 -        }\r
 -      }\r
 -      \r
 -    }\r
 -      break;\r
 -  }\r
 -  line++;\r
 - }\r
 - updateActiveLines(FIRSTITEM+nrfiles-1,encoderpos);\r
 - if(enforceupdate)\r
 - {\r
 -   force_lcd_update=true;\r
 -   enforceupdate=false;\r
 - }\r
 -#endif\r
 -}\r
 -\r
 -enum {ItemM_watch, ItemM_prepare, ItemM_control, ItemM_file };\r
 -void MainMenu::showMainMenu()\r
 -{\r
 -\r
 -  #ifndef ULTIPANEL\r
 -    force_lcd_update=false;\r
 -  #endif\r
 -  if(tune)\r
 -  {\r
 -    if(!(movesplanned() ||card.sdprinting))\r
 -    {\r
 -      force_lcd_update=true;\r
 -      tune=false;\r
 -    }\r
 -  }\r
 -  else \r
 -  {\r
 -    if(movesplanned() ||card.sdprinting)\r
 -    {\r
 -      force_lcd_update=true;\r
 -      tune=true;\r
 -    }\r
 -  } \r
 -  clearIfNecessary();\r
 -  for(int8_t line=0;line<LCD_HEIGHT;line++)\r
 -  {\r
 -    switch(line)\r
 -    { \r
 -      case ItemM_watch:\r
 -        MENUITEM(  lcdprintPGM(" Watch   \003")  ,  BLOCK;status=Main_Status;beepshort(); ) ;\r
 -       break;\r
 -      case ItemM_prepare:\r
 -        MENUITEM(  if(!tune) lcdprintPGM(" Prepare \x7E");else  lcdprintPGM(" Tune    \x7E"); ,  BLOCK;status=Main_Prepare;beepshort(); ) ;\r
 -      break;\r
 -       \r
 -      case ItemM_control:\r
 -        MENUITEM(  lcdprintPGM(" Control \x7E")  ,  BLOCK;status=Main_Control;beepshort(); ) ;\r
 -      break;\r
 -      #ifdef SDSUPPORT\r
 -      case ItemM_file:    \r
 -      {\r
 -        if(force_lcd_update) \r
 -        {\r
 -          lcd.setCursor(0,line);\r
 -          #ifdef CARDINSERTED\r
 -            if(CARDINSERTED)\r
 -          #else\r
 -            if(true)\r
 -          #endif\r
 -          {\r
 -            if(card.sdprinting)\r
 -              lcdprintPGM(" Stop Print   \x7E");\r
 -            else\r
 -              lcdprintPGM(" Card Menu    \x7E");\r
 -          }\r
 -          else\r
 -          {\r
 -           lcdprintPGM(" No Card"); \r
 -          }\r
 -        }\r
 -        #ifdef CARDINSERTED\r
 -          if(CARDINSERTED)\r
 -        #endif\r
 -        if((activeline==line)&&CLICKED)\r
 -        {\r
 -          card.printingHasFinished();\r
 -          BLOCK;\r
 -          status=Main_SD;\r
 -          beepshort();\r
 -        }\r
 -      }break;\r
 -      #else\r
 -      case ItemM_file:\r
 -        break;\r
 -      #endif\r
 -      default: \r
 -        SERIAL_ERROR_START;\r
 -        SERIAL_ERRORLNPGM("Something is wrong in the MenuStructure.");\r
 -      break;\r
 -    }\r
 -  }\r
 -  updateActiveLines(3,encoderpos);\r
 -}\r
 -\r
 -void MainMenu::update()\r
 -{\r
 -  static MainStatus oldstatus=Main_Menu;  //init automatically causes foce_lcd_update=true\r
 -  static long timeoutToStatus=0;\r
 -  static bool oldcardstatus=false;\r
 -  #ifdef CARDINSERTED\r
 -    if((CARDINSERTED != oldcardstatus))\r
 -    {\r
 -      force_lcd_update=true;\r
 -      oldcardstatus=CARDINSERTED;\r
 -      //Serial.println("echo: SD CHANGE");\r
 -      if(CARDINSERTED)\r
 -      {\r
 -        card.initsd();\r
 -        LCD_MESSAGEPGM("Card inserted");\r
 -      }\r
 -      else\r
 -      {\r
 -        card.release();\r
 -        LCD_MESSAGEPGM("Card removed");\r
 -      }\r
 -    }\r
 -  #endif\r
 - \r
 -  if(status!=oldstatus)\r
 -  {\r
 -    force_lcd_update=true;\r
 -    encoderpos=0;\r
 -    lineoffset=0;\r
 -    \r
 -    oldstatus=status;\r
 -  }\r
 -  if( (encoderpos!=lastencoderpos) || CLICKED)\r
 -    timeoutToStatus=millis()+STATUSTIMEOUT;\r
 -\r
 -  switch(status)\r
 -  { \r
 -      case Main_Status: \r
 -      {  \r
 -        showStatus();\r
 -        if(CLICKED)\r
 -        {\r
 -           linechanging=false;\r
 -           BLOCK\r
 -           status=Main_Menu;\r
 -           timeoutToStatus=millis()+STATUSTIMEOUT;\r
 -        }\r
 -      }break;\r
 -      case Main_Menu: \r
 -      {\r
 -        showMainMenu();\r
 -        linechanging=false;\r
 -      }break;\r
 -      case Main_Prepare: \r
 -      {\r
 -        if(tune)\r
 -        {\r
 -          showTune();\r
 -        }\r
 -        else\r
 -        {\r
 -          showPrepare(); \r
 -        }\r
 -      }break;\r
 -      case Main_Control:\r
 -      {\r
 -        showControl(); \r
 -      }break;\r
 -      case Sub_MotionControl:\r
 -      {\r
 -        showControlMotion(); \r
 -      }break;\r
 -      case Sub_TempControl:\r
 -      {\r
 -        showControlTemp(); \r
 -      }break;\r
 -      case Main_SD: \r
 -      {\r
 -        showSD();\r
 -      }break;\r
 -  }\r
 -  \r
 -  if(timeoutToStatus<millis())\r
 -    status=Main_Status;\r
 -  //force_lcd_update=false;\r
 -  lastencoderpos=encoderpos;\r
 -}\r
 -\r
 -\r
 -\r
 -\r
 -\r
 -\r
 -//  convert float to string with +123.4 format\r
 -char *ftostr3(const float &x)\r
 -{\r
 -  //sprintf(conv,"%5.1f",x);\r
 -  int xx=x;\r
 -  conv[0]=(xx/100)%10+'0';\r
 -  conv[1]=(xx/10)%10+'0';\r
 -  conv[2]=(xx)%10+'0';\r
 -  conv[3]=0;\r
 -  return conv;\r
 -}\r
 -\r
 -char *itostr2(const uint8_t &x)\r
 -{\r
 -  //sprintf(conv,"%5.1f",x);\r
 -  int xx=x;\r
 -  conv[0]=(xx/10)%10+'0';\r
 -  conv[1]=(xx)%10+'0';\r
 -  conv[2]=0;\r
 -  return conv;\r
 -}\r
 -\r
 -//  convert float to string with +123.4 format\r
 -char *ftostr31(const float &x)\r
 -{\r
 -  int xx=x*10;\r
 -  conv[0]=(xx>=0)?'+':'-';\r
 -  xx=abs(xx);\r
 -  conv[1]=(xx/1000)%10+'0';\r
 -  conv[2]=(xx/100)%10+'0';\r
 -  conv[3]=(xx/10)%10+'0';\r
 -  conv[4]='.';\r
 -  conv[5]=(xx)%10+'0';\r
 -  conv[6]=0;\r
 -  return conv;\r
 -}\r
 -\r
 -char *ftostr32(const float &x)\r
 -{\r
 -  int xx=x*100;\r
 -  conv[0]=(xx>=0)?'+':'-';\r
 -  xx=abs(xx);\r
 -  conv[1]=(xx/100)%10+'0';\r
 -  conv[2]='.';\r
 -  conv[3]=(xx/10)%10+'0';\r
 -  conv[4]=(xx)%10+'0';\r
 -  conv[6]=0;\r
 -  return conv;\r
 -}\r
 -\r
 -char *itostr31(const int &xx)\r
 -{\r
 -  conv[0]=(xx>=0)?'+':'-';\r
 -  conv[1]=(xx/1000)%10+'0';\r
 -  conv[2]=(xx/100)%10+'0';\r
 -  conv[3]=(xx/10)%10+'0';\r
 -  conv[4]='.';\r
 -  conv[5]=(xx)%10+'0';\r
 -  conv[6]=0;\r
 -  return conv;\r
 -}\r
 -\r
 -char *itostr3(const int &xx)\r
 -{\r
 -  conv[0]=(xx/100)%10+'0';\r
 -  conv[1]=(xx/10)%10+'0';\r
 -  conv[2]=(xx)%10+'0';\r
 -  conv[3]=0;\r
 -  return conv;\r
 -}\r
 -\r
 -char *itostr4(const int &xx)\r
 -{\r
 -  conv[0]=(xx/1000)%10+'0';\r
 -  conv[1]=(xx/100)%10+'0';\r
 -  conv[2]=(xx/10)%10+'0';\r
 -  conv[3]=(xx)%10+'0';\r
 -  conv[4]=0;\r
 -  return conv;\r
 -}\r
 -\r
 -//  convert float to string with +1234.5 format\r
 -char *ftostr51(const float &x)\r
 -{\r
 -  int xx=x*10;\r
 -  conv[0]=(xx>=0)?'+':'-';\r
 -  xx=abs(xx);\r
 -  conv[1]=(xx/10000)%10+'0';\r
 -  conv[2]=(xx/1000)%10+'0';\r
 -  conv[3]=(xx/100)%10+'0';\r
 -  conv[4]=(xx/10)%10+'0';\r
 -  conv[5]='.';\r
 -  conv[6]=(xx)%10+'0';\r
 -  conv[7]=0;\r
 -  return conv;\r
 -}\r
 -\r
 -\r
 -#endif //ULTRA_LCD\r
 -\r
 -\r
 +#include "ultralcd.h"
 +#ifdef ULTRA_LCD
 +
 +//===========================================================================
 +//=============================imported variables============================
 +//===========================================================================
 +
 +extern volatile int feedmultiply;
 +extern volatile bool feedmultiplychanged;
 +
 +extern long position[4];   
 +extern CardReader card;
 +
 +//===========================================================================
 +//=============================public variables============================
 +//===========================================================================
 +volatile char buttons=0;  //the last checked buttons in a bit array.
 +int encoderpos=0;
 +short lastenc=0;
 +
 +
 +//===========================================================================
 +//=============================private  variables============================
 +//===========================================================================
 +static char messagetext[LCD_WIDTH]="";
 +
 +//return for string conversion routines
 +static char conv[8];
 +
 +#include <LiquidCrystal.h>
 +LiquidCrystal 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 
 +
 +static unsigned long previous_millis_lcd=0;
 +static long previous_millis_buttons=0;
 +
 +
 +#ifdef NEWPANEL
 + static long blocking=0;
 +#else
 + static long blocking[8]={0,0,0,0,0,0,0,0};
 +#endif
 + 
 +static MainMenu menu;
 +
 +#include <avr/pgmspace.h>
 +
 +void lcdProgMemprint(const char *str)
 +{
 +  char ch=pgm_read_byte(str);
 +  while(ch)
 +  {
 +    lcd.print(ch);
 +    ch=pgm_read_byte(++str);
 +  }
 +}
 +#define lcdprintPGM(x) lcdProgMemprint(MYPGM(x))
 +
 +
 +//===========================================================================
 +//=============================functions         ============================
 +//===========================================================================
 +
 +FORCE_INLINE int intround(const float &x){return int(0.5+x);}
 +
 +void lcd_status(const char* message)
 +{
 +  strncpy(messagetext,message,LCD_WIDTH);
 +  messagetext[strlen(message)]=0;
 +}
 +
 +void lcd_statuspgm(const char* message)
 +{
 +  char ch=pgm_read_byte(message);
 +  char *target=messagetext;
 +  uint8_t cnt=0;
 +  while(ch &&cnt<LCD_WIDTH)
 +  {
 +    *target=ch;
 +    target++;
 +    cnt++;
 +    ch=pgm_read_byte(++message);
 +  }
 +  *target=0;
 +}
 +
 +FORCE_INLINE void clear()
 +{
 +  lcd.clear();
 +}
 +
 +
 +void lcd_init()
 +{
 +  //beep();
 +  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]={0x04, 0x0e, 0x1f, 0x04, 0x1c, 0x00, 0x00, 0x00};//thanks joris
 +  byte refresh[8]={0x00, 0x06, 0x19, 0x18, 0x03, 0x13, 0x0c, 0x00}; //thanks joris
 +  byte folder [8]={0x00, 0x1c, 0x1f, 0x11, 0x11, 0x1f, 0x00, 0x00}; //thanks joris
 +  lcd.begin(LCD_WIDTH, LCD_HEIGHT);
 +  lcd.createChar(1,Degree);
 +  lcd.createChar(2,Thermometer);
 +  lcd.createChar(3,uplevel);
 +  lcd.createChar(4,refresh);
 +  lcd.createChar(5,folder);
 +  LCD_MESSAGEPGM("UltiMarlin ready.");
 +}
 +
 +
 +void beep()
 +{
 +  //return;
 +  #ifdef ULTIPANEL
 +    pinMode(BEEPER,OUTPUT);
 +    for(int8_t i=0;i<20;i++){
 +      WRITE(BEEPER,HIGH);
 +      delay(5);
 +      WRITE(BEEPER,LOW);
 +      delay(5);
 +    }
 +  #endif
 +}
 +
 +void beepshort()
 +{
 +  //return;
 +  #ifdef ULTIPANEL
 +    pinMode(BEEPER,OUTPUT);
 +    for(int8_t i=0;i<10;i++){
 +      WRITE(BEEPER,HIGH);
 +      delay(3);
 +      WRITE(BEEPER,LOW);
 +      delay(3);
 +    }
 +  #endif  
 +}
 +
 +void lcd_status()
 +{
 +  #ifdef ULTIPANEL
 +    static uint8_t oldbuttons=0;
 +    //static long previous_millis_buttons=0;
 +    //static long previous_lcdinit=0;
 +  //  buttons_check(); // Done in temperature interrupt
 +    //previous_millis_buttons=millis();
 +    long ms=millis();
 +    for(int8_t i=0; i<8; i++) {
 +      if((blocking[i]>ms))
 +        buttons &= ~(1<<i);
 +    }
 +    if((buttons==oldbuttons) &&  ((millis() - previous_millis_lcd) < LCD_UPDATE_INTERVAL)   )
 +      return;
 +    oldbuttons=buttons;
 +  #else
 +  
 +    if(((millis() - previous_millis_lcd) < LCD_UPDATE_INTERVAL)   )
 +      return;
 +  #endif
 +    
 +  previous_millis_lcd=millis();
 +  menu.update();
 +}
 +#ifdef ULTIPANEL  
 +
 +
 +void buttons_init()
 +{
 +  #ifdef NEWPANEL
 +    pinMode(BTN_EN1,INPUT);
 +    pinMode(BTN_EN2,INPUT); 
 +    pinMode(BTN_ENC,INPUT); 
 +    pinMode(SDCARDDETECT,INPUT);
 +    WRITE(BTN_EN1,HIGH);
 +    WRITE(BTN_EN2,HIGH);
 +    WRITE(BTN_ENC,HIGH);
 +    WRITE(SDCARDDETECT,HIGH);
 +  #else
 +    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); 
 +  #endif
 +}
 +
 +
 +void buttons_check()
 +{
 +  
 +  #ifdef NEWPANEL
 +    uint8_t newbutton=0;
 +    if(READ(BTN_EN1)==0)  newbutton|=EN_A;
 +    if(READ(BTN_EN2)==0)  newbutton|=EN_B;
 +    if((blocking<millis()) &&(READ(BTN_ENC)==0))
 +      newbutton|=EN_C;
 +    buttons=newbutton;
 +  #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
 +  
 +  //manage encoder rotation
 +  char enc=0;
 +  if(buttons&EN_A)
 +    enc|=(1<<0);
 +  if(buttons&EN_B)
 +    enc|=(1<<1);
 +  if(enc!=lastenc)
 +      {
 +    switch(enc)
 +    {
 +    case encrot0:
 +      if(lastenc==encrot3)
 +        encoderpos++;
 +      else if(lastenc==encrot1)
 +        encoderpos--;
 +      break;
 +    case encrot1:
 +      if(lastenc==encrot0)
 +        encoderpos++;
 +      else if(lastenc==encrot2)
 +        encoderpos--;
 +      break;
 +    case encrot2:
 +      if(lastenc==encrot1)
 +        encoderpos++;
 +      else if(lastenc==encrot3)
 +        encoderpos--;
 +      break;
 +    case encrot3:
 +      if(lastenc==encrot2)
 +        encoderpos++;
 +      else if(lastenc==encrot0)
 +        encoderpos--;
 +      break;
 +    default:
 +      ;
 +    }
 +  }
 +  lastenc=enc;
 +}
 +
 +#endif
 +
 +MainMenu::MainMenu()
 +{
 +  status=Main_Status;
 +  displayStartingRow=0;
 +  activeline=0;
 +  force_lcd_update=true;
 +  #ifdef ULTIPANEL
 +    buttons_init();
 +  #endif
 +  lcd_init();
 +  linechanging=false;
 +  tune=false;
 +}
 +
 +void MainMenu::showStatus()
 +{ 
 +#if LCD_HEIGHT==4
 +  static int olddegHotEnd0=-1;
 +  static int oldtargetHotEnd0=-1;
 +  //force_lcd_update=true;
 +  if(force_lcd_update||feedmultiplychanged)  //initial display of content
 +  {
 +    feedmultiplychanged=false;
 +    encoderpos=feedmultiply;
 +    clear();
 +    lcd.setCursor(0,0);lcdprintPGM("\002123/567\001 ");
 +    #if defined BED_USES_THERMISTOR || defined BED_USES_AD595 
 +      lcd.setCursor(10,0);lcdprintPGM("B123/567\001 ");
 +    #endif
 +  }
 +    
 +  int tHotEnd0=intround(degHotend0());
 +  if((abs(tHotEnd0-olddegHotEnd0)>1)||force_lcd_update) //>1 because otherwise the lcd is refreshed to often.
 +  {
 +    lcd.setCursor(1,0);
 +    lcd.print(ftostr3(tHotEnd0));
 +    olddegHotEnd0=tHotEnd0;
 +  }
 +  int ttHotEnd0=intround(degTargetHotend0());
 +  if((ttHotEnd0!=oldtargetHotEnd0)||force_lcd_update)
 +  {
 +    lcd.setCursor(5,0);
 +    lcd.print(ftostr3(ttHotEnd0));
 +    oldtargetHotEnd0=ttHotEnd0;
 +  }
 +  #if defined BED_USES_THERMISTOR || defined BED_USES_AD595 
 +    static int oldtBed=-1;
 +    static int oldtargetBed=-1; 
 +    int tBed=intround(degBed());
 +    if((tBed!=oldtBed)||force_lcd_update)
 +    {
 +      lcd.setCursor(1,0);
 +      lcd.print(ftostr3(tBed));
 +      oldtBed=tBed;
 +    }
 +    int targetBed=intround(degTargetBed());
 +    if((targetBed!=oldtargetBed)||force_lcd_update)
 +    {
 +      lcd.setCursor(5,0);
 +      lcd.print(ftostr3(targetBed));
 +      oldtargetBed=targetBed;
 +    }
 +  #endif
 +  //starttime=2;
 +  static uint16_t oldtime=0;
 +  if(starttime!=0)
 +  {
 +    lcd.setCursor(0,1);
 +    uint16_t time=millis()/60000-starttime/60000;
 +    
 +    if(starttime!=oldtime)
 +    {
 +      lcd.print(itostr2(time/60));lcdprintPGM("h ");lcd.print(itostr2(time%60));lcdprintPGM("m");
 +      oldtime=time;
 +    }
 +  }
 +  static int oldzpos=0;
 +  int currentz=current_position[2]*10;
 +  if((currentz!=oldzpos)||force_lcd_update)
 +  {
 +    lcd.setCursor(10,1);
 +    lcdprintPGM("Z:");lcd.print(itostr31(currentz));
 +    oldzpos=currentz;
 +  }
 +  static int oldfeedmultiply=0;
 +  int curfeedmultiply=feedmultiply;
 +  if(encoderpos!=curfeedmultiply||force_lcd_update)
 +  {
 +   curfeedmultiply=encoderpos;
 +   if(curfeedmultiply<10)
 +     curfeedmultiply=10;
 +   if(curfeedmultiply>999)
 +     curfeedmultiply=999;
 +   feedmultiply=curfeedmultiply;
 +   encoderpos=curfeedmultiply;
 +  }
 +  if((curfeedmultiply!=oldfeedmultiply)||force_lcd_update)
 +  {
 +   oldfeedmultiply=curfeedmultiply;
 +   lcd.setCursor(0,2);
 +   lcd.print(itostr3(curfeedmultiply));lcdprintPGM("% ");
 +  }
 +  if(messagetext[0]!='\0')
 +  {
 +    lcd.setCursor(0,LCD_HEIGHT-1);
 +    lcd.print(messagetext);
 +    uint8_t n=strlen(messagetext);
 +    for(int8_t i=0;i<LCD_WIDTH-n;i++)
 +      lcd.print(" ");
 +    
 +    messagetext[0]='\0';
 +  }
 +  
 +  static uint8_t oldpercent=101;
 +  uint8_t percent=card.percentDone();
 +  if(oldpercent!=percent ||force_lcd_update)
 +  {
 +     lcd.setCursor(7,2);
 +    lcd.print(itostr3((int)percent));
 +    lcdprintPGM("%SD");
 +    
 +  }
 +  
 +#else //smaller LCDS----------------------------------
 +  static int olddegHotEnd0=-1;
 +  static int oldtargetHotEnd0=-1;
 +  if(force_lcd_update)  //initial display of content
 +  {
 +    encoderpos=feedmultiply;
 +    lcd.setCursor(0,0);lcdprintPGM("\002123/567\001 ");
 +    #if defined BED_USES_THERMISTOR || defined BED_USES_AD595 
 +    lcd.setCursor(10,0);lcdprintPGM("B123/567\001 ");
 +    #endif
 +  }
 +    
 +  int tHotEnd0=intround(degHotend0());
 +  int ttHotEnd0=intround(degTargetHotend0());
 +
 +
 +  if((abs(tHotEnd0-olddegHotEnd0)>1)||force_lcd_update)
 +  {
 +    lcd.setCursor(1,0);
 +    lcd.print(ftostr3(tHotEnd0));
 +    olddegHotEnd0=tHotEnd0;
 +  }
 +  if((ttHotEnd0!=oldtargetHotEnd0)||force_lcd_update)
 +  {
 +    lcd.setCursor(5,0);
 +    lcd.print(ftostr3(ttHotEnd0));
 +    oldtargetHotEnd0=ttHotEnd0;
 +  }
 +
 +  if(messagetext[0]!='\0')
 +  {
 +    lcd.setCursor(0,LCD_HEIGHT-1);
 +    lcd.print(messagetext);
 +    uint8_t n=strlen(messagetext);
 +    for(int8_t i=0;i<LCD_WIDTH-n;i++)
 +      lcd.print(" ");
 +    messagetext[0]='\0';
 +  }
 +
 +#endif
 +  force_lcd_update=false;
 +}
 +
- enum {ItemP_exit, ItemP_home, ItemP_origin, ItemP_preheat, ItemP_extrude, ItemP_disstep};
++enum {ItemP_exit, ItemP_autostart,ItemP_disstep,ItemP_home, ItemP_origin, ItemP_preheat, ItemP_extrude};
 +
 +//any action must not contain a ',' character anywhere, or this breaks:
 +#define MENUITEM(repaint_action, click_action) \
 +  {\
 +    if(force_lcd_update)  { lcd.setCursor(0,line);  repaint_action; } \
 +    if((activeline==line) && CLICKED) {click_action} \
 +  }
 +  
 +void MainMenu::showPrepare()
 +{
 + uint8_t line=0;
 + clearIfNecessary();
 + for(int8_t i=lineoffset;i<lineoffset+LCD_HEIGHT;i++)
 + {
 +   //Serial.println((int)(line-lineoffset));
 +  switch(i)
 +  {
 +    case ItemP_exit:
 +      MENUITEM(  lcdprintPGM(" Main \003")  ,  BLOCK;status=Main_Menu;beepshort(); ) ;
 +      break;
++    case ItemP_autostart:
++      MENUITEM(  lcdprintPGM(" Autostart")  ,  BLOCK;card.lastnr=0;card.checkautostart(true);beepshort(); ) ;
++      break;
++    case ItemP_disstep:
++      MENUITEM(  lcdprintPGM(" Disable Steppers")  ,  BLOCK;enquecommand("M84");beepshort(); ) ;
++      break;
 +    case ItemP_home:
 +      MENUITEM(  lcdprintPGM(" Auto Home")  ,  BLOCK;enquecommand("G28 X-105 Y-105 Z0");beepshort(); ) ;
 +      break;
 +    case ItemP_origin:
 +      MENUITEM(  lcdprintPGM(" Set Origin")  ,  BLOCK;enquecommand("G92 X0 Y0 Z0");beepshort(); ) ;
 +      break;
 +    case ItemP_preheat:
 +      MENUITEM(  lcdprintPGM(" Preheat")  ,  BLOCK;setTargetHotend0(170);beepshort(); ) ;
 +      break;
 +    case ItemP_extrude:
 +      MENUITEM(  lcdprintPGM(" Extrude")  ,  BLOCK;enquecommand("G92 E0");enquecommand("G1 F700 E50");beepshort(); ) ;
 +      break;
-     case ItemP_disstep:
-       MENUITEM(  lcdprintPGM(" Disable Steppers")  ,  BLOCK;enquecommand("M84");beepshort(); ) ;
-       break;
++    
++    
 +    default:   
 +      break;
 +  }
 +  line++;
 + }
-  updateActiveLines(ItemP_disstep,encoderpos);
++ updateActiveLines(ItemP_extrude,encoderpos);
 +}
 +
 +enum {ItemT_exit,ItemT_speed,ItemT_flow,ItemT_nozzle,ItemT_fan};
 +
 +void MainMenu::showTune()
 +{ 
 +  uint8_t line=0;
 +  clearIfNecessary();
 + for(int8_t i=lineoffset;i<lineoffset+LCD_HEIGHT;i++)
 + {
 +   //Serial.println((int)(line-lineoffset));
 +  switch(i)
 +  {
 +  case ItemT_exit:
 +      MENUITEM(  lcdprintPGM(" Main \003")  ,  BLOCK;status=Main_Menu;beepshort(); ) ;
 +      break;
 +  case ItemT_speed:
 +    {
 +      if(force_lcd_update)
 +      {
 +        lcd.setCursor(0,line);lcdprintPGM(" Speed:");
 +        lcd.setCursor(13,line);lcd.print(ftostr3(feedmultiply));
 +      }
 +      
 +      if((activeline!=line) )
 +        break;
 +      
 +      if(CLICKED) //nalogWrite(FAN_PIN,  fanpwm);
 +      {
 +        linechanging=!linechanging;
 +        if(linechanging)
 +        {
 +            encoderpos=feedmultiply;
 +        }
 +        else
 +        {
 +          encoderpos=activeline*lcdslow;
 +          beepshort();
 +        }
 +        BLOCK;
 +      }
 +      if(linechanging)
 +      {
 +        if(encoderpos<1) encoderpos=1;
 +        if(encoderpos>400) encoderpos=400;
 +        feedmultiply = encoderpos;
 +        feedmultiplychanged=true;
 +        lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));
 +      }
 +      
 +    }break;
 +    case ItemT_nozzle:
 +      {
 +        if(force_lcd_update)
 +        {
 +          lcd.setCursor(0,line);lcdprintPGM(" \002Nozzle:");
 +          lcd.setCursor(13,line);lcd.print(ftostr3(intround(degTargetHotend0())));
 +        }
 +        
 +        if((activeline!=line) )
 +          break;
 +        
 +        if(CLICKED)
 +        {
 +          linechanging=!linechanging;
 +          if(linechanging)
 +          {
 +              encoderpos=intround(degTargetHotend0());
 +          }
 +          else
 +          {
 +            setTargetHotend0(encoderpos);
 +            encoderpos=activeline*lcdslow;
 +            beepshort();
 +          }
 +          BLOCK;
 +        }
 +        if(linechanging)
 +        {
 +          if(encoderpos<0) encoderpos=0;
 +          if(encoderpos>260) encoderpos=260;
 +          lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));
 +        }
 +      }break;
 +      
 +      case ItemT_fan:
 +      {
 +        if(force_lcd_update)
 +        {
 +          lcd.setCursor(0,line);lcdprintPGM(" Fan speed:");
 +          lcd.setCursor(13,line);lcd.print(ftostr3(fanpwm));
 +        }
 +        
 +        if((activeline!=line) )
 +          break;
 +        
 +        if(CLICKED) //nalogWrite(FAN_PIN,  fanpwm);
 +        {
 +          linechanging=!linechanging;
 +          if(linechanging)
 +          {
 +              encoderpos=fanpwm;
 +          }
 +          else
 +          {
 +            encoderpos=activeline*lcdslow;
 +            beepshort();
 +          }
 +          BLOCK;
 +        }
 +        if(linechanging)
 +        {
 +          if(encoderpos<0) encoderpos=0;
 +          if(encoderpos>255) encoderpos=255;
 +          fanpwm=encoderpos;
 +            analogWrite(FAN_PIN,  fanpwm);
 +          lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));
 +        }
 +        
 +      }break;
 +      case ItemT_flow://axis_steps_per_unit[i] = code_value();
 +         {
 +      if(force_lcd_update)
 +        {
 +          lcd.setCursor(0,line);lcdprintPGM(" Flow:");
 +          lcd.setCursor(13,line);lcd.print(itostr4(axis_steps_per_unit[3]));
 +        }
 +        
 +        if((activeline!=line) )
 +          break;
 +        
 +        if(CLICKED)
 +        {
 +          linechanging=!linechanging;
 +          if(linechanging)
 +          {
 +              encoderpos=(int)axis_steps_per_unit[3];
 +          }
 +          else
 +          {
 +            float factor=float(encoderpos)/float(axis_steps_per_unit[3]);
 +            position[E_AXIS]=lround(position[E_AXIS]*factor);
 +            //current_position[3]*=factor;
 +            axis_steps_per_unit[E_AXIS]= encoderpos;
 +            encoderpos=activeline*lcdslow;
 +              
 +          }
 +          BLOCK;
 +          beepshort();
 +        }
 +        if(linechanging)
 +        {
 +          if(encoderpos<5) encoderpos=5;
 +          if(encoderpos>9999) encoderpos=9999;
 +          lcd.setCursor(13,line);lcd.print(itostr4(encoderpos));
 +        }
 +        
 +      }break; 
 +    default:   
 +      break;
 +  }
 +  line++;
 + }
 + updateActiveLines(ItemT_fan,encoderpos);
 +}
 +
 +//does not work
 +// #define MENUCHANGEITEM(repaint_action,  enter_action, accept_action,  change_action) \
 +//   {\
 +//     if(force_lcd_update)  { lcd.setCursor(0,line);  repaint_action; } \
 +//     if(activeline==line)  \
 +//     { \
 +//       if(CLICKED) \
 +//       { \
 +//         linechanging=!linechanging; \
 +//         if(linechanging)  {enter_action;} \
 +//         else {accept_action;} \
 +//       }  \
 +//       else \
 +//       if(linechanging) {change_action};}\
 +//   }
 +//   
 +
 +enum {
 +  ItemCT_exit,ItemCT_nozzle,
 +#ifdef AUTOTEMP
 +  ItemCT_autotempactive,
 +  ItemCT_autotempmin,ItemCT_autotempmax,ItemCT_autotempfact,
 +#endif
 +  ItemCT_fan,
 +  ItemCT_PID_P,ItemCT_PID_I,ItemCT_PID_D,ItemCT_PID_C
 +};
 +
 +void MainMenu::showControlTemp()
 +{
 +  uint8_t line=0;
 + clearIfNecessary();
 + for(int8_t i=lineoffset;i<lineoffset+LCD_HEIGHT;i++)
 + {
 +  switch(i)
 +  {
 +    case ItemCT_exit:
 +      MENUITEM(  lcdprintPGM(" Control \003")  ,  BLOCK;status=Main_Control;beepshort(); ) ;
 +      break;
 +    case ItemCT_nozzle:
 +      {
 +        if(force_lcd_update)
 +        {
 +          lcd.setCursor(0,line);lcdprintPGM(" \002Nozzle:");
 +          lcd.setCursor(13,line);lcd.print(ftostr3(intround(degTargetHotend0())));
 +        }
 +        
 +        if((activeline!=line) )
 +          break;
 +        
 +        if(CLICKED)
 +        {
 +          linechanging=!linechanging;
 +          if(linechanging)
 +          {
 +              encoderpos=intround(degTargetHotend0());
 +          }
 +          else
 +          {
 +            setTargetHotend0(encoderpos);
 +            encoderpos=activeline*lcdslow;
 +            beepshort();
 +          }
 +          BLOCK;
 +        }
 +        if(linechanging)
 +        {
 +          if(encoderpos<0) encoderpos=0;
 +          if(encoderpos>260) encoderpos=260;
 +          lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));
 +        }
 +        
 +      }break;
 +      #ifdef AUTOTEMP
 +      case ItemCT_autotempmin:
 +      {
 +        if(force_lcd_update)
 +        {
 +          lcd.setCursor(0,line);lcdprintPGM(" \002 Min:");
 +          lcd.setCursor(13,line);lcd.print(ftostr3(autotemp_min));
 +        }
 +        
 +        if((activeline!=line) )
 +          break;
 +        
 +        if(CLICKED)
 +        {
 +          linechanging=!linechanging;
 +          if(linechanging)
 +          {
 +              encoderpos=intround(autotemp_min);
 +          }
 +          else
 +          {
 +            autotemp_min=encoderpos;
 +            encoderpos=activeline*lcdslow;
 +            beepshort();
 +          }
 +          BLOCK;
 +        }
 +        if(linechanging)
 +        {
 +          if(encoderpos<0) encoderpos=0;
 +          if(encoderpos>260) encoderpos=260;
 +          lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));
 +        }
 +        
 +      }break;  
 +      case ItemCT_autotempmax:
 +      {
 +        if(force_lcd_update)
 +        {
 +          lcd.setCursor(0,line);lcdprintPGM(" \002 Max:");
 +          lcd.setCursor(13,line);lcd.print(ftostr3(autotemp_max));
 +        }
 +        
 +        if((activeline!=line) )
 +          break;
 +        
 +        if(CLICKED)
 +        {
 +          linechanging=!linechanging;
 +          if(linechanging)
 +          {
 +              encoderpos=intround(autotemp_max);
 +          }
 +          else
 +          {
 +            autotemp_max=encoderpos;
 +            encoderpos=activeline*lcdslow;
 +            beepshort();
 +          }
 +          BLOCK;
 +        }
 +        if(linechanging)
 +        {
 +          if(encoderpos<0) encoderpos=0;
 +          if(encoderpos>260) encoderpos=260;
 +          lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));
 +        }
 +        
 +      }break;  
 +      case ItemCT_autotempfact:
 +      {
 +        if(force_lcd_update)
 +        {
 +          lcd.setCursor(0,line);lcdprintPGM(" \002 Fact:");
 +          lcd.setCursor(13,line);lcd.print(ftostr32(autotemp_factor));
 +        }
 +        
 +        if((activeline!=line) )
 +          break;
 +        
 +        if(CLICKED)
 +        {
 +          linechanging=!linechanging;
 +          if(linechanging)
 +          {
 +              encoderpos=intround(autotemp_factor*100);
 +          }
 +          else
 +          {
 +            autotemp_max=encoderpos;
 +            encoderpos=activeline*lcdslow;
 +            beepshort();
 +          }
 +          BLOCK;
 +        }
 +        if(linechanging)
 +        {
 +          if(encoderpos<0) encoderpos=0;
 +          if(encoderpos>99) encoderpos=99;
 +          lcd.setCursor(13,line);lcd.print(ftostr32(encoderpos/100.));
 +        }
 +        
 +      }break;
 +      case ItemCT_autotempactive:
 +      {
 +        if(force_lcd_update)
 +        {
 +          lcd.setCursor(0,line);lcdprintPGM(" Autotemp:");
 +          lcd.setCursor(13,line);
 +          if(autotemp_enabled)
 +            lcdprintPGM("On");
 +          else
 +            lcdprintPGM("Off");
 +        }
 +        
 +        if((activeline!=line) )
 +          break;
 +        
 +        if(CLICKED)
 +        {
 +          autotemp_enabled=!autotemp_enabled;
 +          lcd.setCursor(13,line);
 +          if(autotemp_enabled)
 +            lcdprintPGM("On ");
 +          else
 +            lcdprintPGM("Off");
 +          BLOCK;
 +        }
 +        
 +      }break;  
 +      #endif //autotemp
 +      case ItemCT_fan:
 +      {
 +        if(force_lcd_update)
 +        {
 +          lcd.setCursor(0,line);lcdprintPGM(" Fan speed:");
 +          lcd.setCursor(13,line);lcd.print(ftostr3(fanpwm));
 +        }
 +        
 +        if((activeline!=line) )
 +          break;
 +        
 +        if(CLICKED) //nalogWrite(FAN_PIN,  fanpwm);
 +        {
 +          linechanging=!linechanging;
 +          if(linechanging)
 +          {
 +              encoderpos=fanpwm;
 +          }
 +          else
 +          {
 +            encoderpos=activeline*lcdslow;
 +            beepshort();
 +          }
 +          BLOCK;
 +        }
 +        if(linechanging)
 +        {
 +          if(encoderpos<0) encoderpos=0;
 +          if(encoderpos>255) encoderpos=255;
 +          fanpwm=encoderpos;
 +            analogWrite(FAN_PIN,  fanpwm);
 +          lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));
 +        }
 +        
 +      }break;
 +      case ItemCT_PID_P: 
 +      {
 +      if(force_lcd_update)
 +        {
 +          lcd.setCursor(0,line);lcdprintPGM(" PID-P: ");
 +          lcd.setCursor(13,line);lcd.print(itostr4(Kp));
 +        }
 +        
 +        if((activeline!=line) )
 +          break;
 +        
 +        if(CLICKED)
 +        {
 +          linechanging=!linechanging;
 +          if(linechanging)
 +          {
 +              encoderpos=(int)Kp;
 +          }
 +          else
 +          {
 +            Kp= encoderpos;
 +            encoderpos=activeline*lcdslow;
 +              
 +          }
 +          BLOCK;
 +          beepshort();
 +        }
 +        if(linechanging)
 +        {
 +          if(encoderpos<1) encoderpos=1;
 +          if(encoderpos>9990) encoderpos=9990;
 +          lcd.setCursor(13,line);lcd.print(itostr4(encoderpos));
 +        }
 +        
 +      }break;
 +    case ItemCT_PID_I: 
 +      {
 +      if(force_lcd_update)
 +        {
 +          lcd.setCursor(0,line);lcdprintPGM(" PID-I: ");
 +          lcd.setCursor(13,line);lcd.print(ftostr51(Ki/PID_dT));
 +        }
 +        
 +        if((activeline!=line) )
 +          break;
 +        
 +        if(CLICKED)
 +        {
 +          linechanging=!linechanging;
 +          if(linechanging)
 +          {
 +              encoderpos=(int)(Ki*10/PID_dT);
 +          }
 +          else
 +          {
 +            Ki= encoderpos/10.*PID_dT;
 +            encoderpos=activeline*lcdslow;
 +              
 +          }
 +          BLOCK;
 +          beepshort();
 +        }
 +        if(linechanging)
 +        {
 +          if(encoderpos<0) encoderpos=0;
 +          if(encoderpos>9990) encoderpos=9990;
 +          lcd.setCursor(13,line);lcd.print(ftostr51(encoderpos/10.));
 +        }
 +        
 +      }break;
 +      case ItemCT_PID_D: 
 +      {
 +      if(force_lcd_update)
 +        {
 +          lcd.setCursor(0,line);lcdprintPGM(" PID-D: ");
 +          lcd.setCursor(13,line);lcd.print(itostr4(Kd*PID_dT));
 +        }
 +        
 +        if((activeline!=line) )
 +          break;
 +        
 +        
 +        if(CLICKED)
 +        {
 +          linechanging=!linechanging;
 +          if(linechanging)
 +          {
 +              encoderpos=(int)(Kd/5./PID_dT);
 +          }
 +          else
 +          {
 +            Kd= encoderpos;
 +            encoderpos=activeline*lcdslow;
 +              
 +          }
 +          BLOCK;
 +          beepshort();
 +        }
 +        if(linechanging)
 +        {
 +          if(encoderpos<0) encoderpos=0;
 +          if(encoderpos>9990) encoderpos=9990;
 +          lcd.setCursor(13,line);lcd.print(itostr4(encoderpos));
 +        }
 +       
 +      }break;   
 +    case ItemCT_PID_C: 
 +      #ifdef PID_ADD_EXTRUSION_RATE
 +      {
 +      if(force_lcd_update)
 +        {
 +          lcd.setCursor(0,line);lcdprintPGM(" PID-C: ");
 +          lcd.setCursor(13,line);lcd.print(itostr3(Kc));
 +        }
 +        
 +        if((activeline!=line) )
 +          break;
 +        
 +        if(CLICKED)
 +        {
 +          linechanging=!linechanging;
 +          if(linechanging)
 +          {
 +              encoderpos=(int)Kc;
 +          }
 +          else
 +          {
 +            Kc= encoderpos;
 +            encoderpos=activeline*lcdslow;
 +              
 +          }
 +          BLOCK;
 +          beepshort();
 +        }
 +        if(linechanging)
 +        {
 +          if(encoderpos<0) encoderpos=0;
 +          if(encoderpos>990) encoderpos=990;
 +          lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));
 +        }
 +        
 +      }
 +      #endif
 +      break;
 +    default:   
 +      break;
 +  }
 +  line++;
 + }
 + #ifdef PID_ADD_EXTRUSION_RATE
 +  updateActiveLines(ItemCT_PID_C,encoderpos);
 + #else
 +  updateActiveLines(ItemCT_PID_D,encoderpos);
 + #endif
 +}
 +
 +
 +enum {
 +  ItemCM_exit, 
 +  ItemCM_acc, ItemCM_xyjerk, 
 +  ItemCM_vmaxx, ItemCM_vmaxy, ItemCM_vmaxz, ItemCM_vmaxe, 
 +  ItemCM_vtravmin,ItemCM_vmin,  
 +  ItemCM_amaxx, ItemCM_amaxy, ItemCM_amaxz, ItemCM_amaxe, 
 +  ItemCM_aret,ItemCM_esteps
 +};
 +
 +
 +
 +void MainMenu::showControlMotion()
 +{
 + uint8_t line=0;
 + clearIfNecessary();
 + for(int8_t i=lineoffset;i<lineoffset+LCD_HEIGHT;i++)
 + {
 +  switch(i)
 +  {
 +    case ItemCM_exit:
 +      MENUITEM(  lcdprintPGM(" Control \003")  ,  BLOCK;status=Main_Control;beepshort(); ) ;
 +      break;
 +    case ItemCM_acc:
 +    {
 +      if(force_lcd_update)
 +        {
 +          lcd.setCursor(0,line);lcdprintPGM(" Acc:");
 +          lcd.setCursor(13,line);lcd.print(itostr3(acceleration/100));lcdprintPGM("00");
 +        }
 +        
 +        if((activeline!=line) )
 +          break;
 +        
 +        if(CLICKED)
 +        {
 +          linechanging=!linechanging;
 +          if(linechanging)
 +          {
 +              encoderpos=(int)acceleration/100;
 +          }
 +          else
 +          {
 +            acceleration= encoderpos*100;
 +            encoderpos=activeline*lcdslow;
 +          }
 +          BLOCK;
 +          beepshort();
 +        }
 +        if(linechanging)
 +        {
 +          if(encoderpos<5) encoderpos=5;
 +          if(encoderpos>990) encoderpos=990;
 +          lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcdprintPGM("00");
 +        }
 +        
 +      }break;
 +    case ItemCM_xyjerk: //max_xy_jerk
 +      {
 +      if(force_lcd_update)
 +        {
 +          lcd.setCursor(0,line);lcdprintPGM(" Vxy-jerk: ");
 +          lcd.setCursor(13,line);lcd.print(itostr3(max_xy_jerk));
 +        }
 +        
 +        if((activeline!=line) )
 +          break;
 +        
 +        if(CLICKED)
 +        {
 +          linechanging=!linechanging;
 +          if(linechanging)
 +          {
 +              encoderpos=(int)max_xy_jerk;
 +          }
 +          else
 +          {
 +            max_xy_jerk= encoderpos;
 +            encoderpos=activeline*lcdslow;
 +              
 +          }
 +          BLOCK;
 +          beepshort();
 +        }
 +        if(linechanging)
 +        {
 +          if(encoderpos<1) encoderpos=1;
 +          if(encoderpos>990) encoderpos=990;
 +          lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));
 +        }
 +        
 +      }break;
 +      
 +    case ItemCM_vmaxx:
 +    case ItemCM_vmaxy:
 +    case ItemCM_vmaxz:
 +    case ItemCM_vmaxe:
 +      {
 +      if(force_lcd_update)
 +        {
 +          lcd.setCursor(0,line);lcdprintPGM(" Vmax ");
 +          if(i==ItemCM_vmaxx)lcdprintPGM("x:");
 +          if(i==ItemCM_vmaxy)lcdprintPGM("y:");
 +          if(i==ItemCM_vmaxz)lcdprintPGM("z:");
 +          if(i==ItemCM_vmaxe)lcdprintPGM("e:");
 +          lcd.setCursor(13,line);lcd.print(itostr3(max_feedrate[i-ItemCM_vmaxx]));
 +        }
 +        
 +        if((activeline!=line) )
 +          break;
 +        
 +        if(CLICKED)
 +        {
 +          linechanging=!linechanging;
 +          if(linechanging)
 +          {
 +              encoderpos=(int)max_feedrate[i-ItemCM_vmaxx];
 +          }
 +          else
 +          {
 +            max_feedrate[i-ItemCM_vmaxx]= encoderpos;
 +            encoderpos=activeline*lcdslow;
 +              
 +          }
 +          BLOCK;
 +          beepshort();
 +        }
 +        if(linechanging)
 +        {
 +          if(encoderpos<1) encoderpos=1;
 +          if(encoderpos>990) encoderpos=990;
 +          lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));
 +        }
 +        
 +      }break;
 +    
 +    case ItemCM_vmin:
 +    {
 +      if(force_lcd_update)
 +        {
 +          lcd.setCursor(0,line);lcdprintPGM(" Vmin:");
 +          lcd.setCursor(13,line);lcd.print(itostr3(minimumfeedrate));
 +        }
 +        
 +        if((activeline!=line) )
 +          break;
 +        
 +        if(CLICKED)
 +        {
 +          linechanging=!linechanging;
 +          if(linechanging)
 +          {
 +              encoderpos=(int)(minimumfeedrate);
 +          }
 +          else
 +          {
 +            minimumfeedrate= encoderpos;
 +            encoderpos=activeline*lcdslow;
 +              
 +          }
 +          BLOCK;
 +          beepshort();
 +        }
 +        if(linechanging)
 +        {
 +          if(encoderpos<0) encoderpos=0;
 +          if(encoderpos>990) encoderpos=990;
 +          lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));
 +        }
 +        
 +      }break;
 +    case ItemCM_vtravmin:
 +    {
 +      if(force_lcd_update)
 +        {
 +          lcd.setCursor(0,line);lcdprintPGM(" VTrav min:");
 +          lcd.setCursor(13,line);lcd.print(itostr3(mintravelfeedrate));
 +        }
 +        
 +        if((activeline!=line) )
 +          break;
 +        
 +        if(CLICKED)
 +        {
 +          linechanging=!linechanging;
 +          if(linechanging)
 +          {
 +              encoderpos=(int)mintravelfeedrate;
 +          }
 +          else
 +          {
 +            mintravelfeedrate= encoderpos;
 +            encoderpos=activeline*lcdslow;
 +              
 +          }
 +          BLOCK;
 +          beepshort();
 +        }
 +        if(linechanging)
 +        {
 +          if(encoderpos<0) encoderpos=0;
 +          if(encoderpos>990) encoderpos=990;
 +          lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));
 +        }
 +        
 +      }break;
 +    
 +    case ItemCM_amaxx:      
 +    case ItemCM_amaxy:
 +    case ItemCM_amaxz:
 +    case ItemCM_amaxe:
 +    {
 +      if(force_lcd_update)
 +        {
 +          lcd.setCursor(0,line);lcdprintPGM(" Amax ");
 +          if(i==ItemCM_amaxx)lcdprintPGM("x:");
 +          if(i==ItemCM_amaxy)lcdprintPGM("y:");
 +          if(i==ItemCM_amaxz)lcdprintPGM("z:");
 +          if(i==ItemCM_amaxe)lcdprintPGM("e:");
 +          lcd.setCursor(13,line);lcd.print(itostr3(max_acceleration_units_per_sq_second[i-ItemCM_amaxx]/100));lcdprintPGM("00");
 +        }
 +        
 +        if((activeline!=line) )
 +          break;
 +        
 +        if(CLICKED)
 +        {
 +          linechanging=!linechanging;
 +          if(linechanging)
 +          {
 +              encoderpos=(int)max_acceleration_units_per_sq_second[i-ItemCM_amaxx]/100;
 +          }
 +          else
 +          {
 +            max_acceleration_units_per_sq_second[i-ItemCM_amaxx]= encoderpos*100;
 +            encoderpos=activeline*lcdslow;
 +          }
 +          BLOCK;
 +          beepshort();
 +        }
 +        if(linechanging)
 +        {
 +          if(encoderpos<1) encoderpos=1;
 +          if(encoderpos>990) encoderpos=990;
 +          lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcdprintPGM("00");
 +        }
 +        
 +      }break;
 +    case ItemCM_aret://float retract_acceleration = 7000;
 +    {
 +        if(force_lcd_update)
 +        {
 +          lcd.setCursor(0,line);lcdprintPGM(" A-retract:");
 +          lcd.setCursor(13,line);lcd.print(ftostr3(retract_acceleration/100));lcdprintPGM("00");
 +        }
 +        
 +        if((activeline!=line) )
 +          break;
 +        
 +        if(CLICKED)
 +        {
 +          linechanging=!linechanging;
 +          if(linechanging)
 +          {
 +              encoderpos=(int)retract_acceleration/100;
 +          }
 +          else
 +          {
 +            retract_acceleration= encoderpos*100;
 +            encoderpos=activeline*lcdslow;
 +              
 +          }
 +          BLOCK;
 +          beepshort();
 +        }
 +        if(linechanging)
 +        {
 +          if(encoderpos<10) encoderpos=10;
 +          if(encoderpos>990) encoderpos=990;
 +          lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));lcdprintPGM("00");
 +        }
 +        
 +      }break;
 +    case ItemCM_esteps://axis_steps_per_unit[i] = code_value();
 +         {
 +      if(force_lcd_update)
 +        {
 +          lcd.setCursor(0,line);lcdprintPGM(" Esteps/mm:");
 +          lcd.setCursor(13,line);lcd.print(itostr4(axis_steps_per_unit[3]));
 +        }
 +        
 +        if((activeline!=line) )
 +          break;
 +        
 +        if(CLICKED)
 +        {
 +          linechanging=!linechanging;
 +          if(linechanging)
 +          {
 +              encoderpos=(int)axis_steps_per_unit[3];
 +          }
 +          else
 +          {
 +            float factor=float(encoderpos)/float(axis_steps_per_unit[3]);
 +            position[E_AXIS]=lround(position[E_AXIS]*factor);
 +            //current_position[3]*=factor;
 +            axis_steps_per_unit[E_AXIS]= encoderpos;
 +            encoderpos=activeline*lcdslow;
 +              
 +          }
 +          BLOCK;
 +          beepshort();
 +        }
 +        if(linechanging)
 +        {
 +          if(encoderpos<5) encoderpos=5;
 +          if(encoderpos>9999) encoderpos=9999;
 +          lcd.setCursor(13,line);lcd.print(itostr4(encoderpos));
 +        }
 +        
 +      }break; 
 +    default:   
 +      break;
 +  }
 +  line++;
 + }
 + updateActiveLines(ItemCM_esteps,encoderpos);
 +}
 +
 +
 +enum {
 +  ItemC_exit,ItemC_temp,ItemC_move,
 +  ItemC_store, ItemC_load,ItemC_failsafe
 +};
 +
 +void MainMenu::showControl()
 +{
 + uint8_t line=0;
 + clearIfNecessary();
 + for(int8_t i=lineoffset;i<lineoffset+LCD_HEIGHT;i++)
 + {
 +  switch(i)
 +  {
 +    case ItemC_exit:
 +      MENUITEM(  lcdprintPGM(" Main        \003")  ,  BLOCK;status=Main_Menu;beepshort(); ) ;
 +      break;
 +    case ItemC_temp:
 +      MENUITEM(  lcdprintPGM(" Temperature \x7E")  ,  BLOCK;status=Sub_TempControl;beepshort(); ) ;
 +      break;
 +   case ItemC_move:
 +      MENUITEM(  lcdprintPGM(" Motion      \x7E")  ,  BLOCK;status=Sub_MotionControl;beepshort(); ) ;
 +      break;
 +    case ItemC_store:
 +    {
 +      if(force_lcd_update)
 +      {
 +        lcd.setCursor(0,line);lcdprintPGM(" Store EPROM");
 +      }
 +      if((activeline==line) && CLICKED)
 +      {
 +        //enquecommand("M84");
 +        beepshort();
 +        BLOCK;
 +        EEPROM_StoreSettings();
 +      }
 +    }break;
 +    case ItemC_load:
 +    {
 +      if(force_lcd_update)
 +      {
 +        lcd.setCursor(0,line);lcdprintPGM(" Load EPROM");
 +      }
 +      if((activeline==line) && CLICKED)
 +      {
 +        //enquecommand("M84");
 +        beepshort();
 +        BLOCK;
 +        EEPROM_RetrieveSettings();
 +      }
 +    }break;
 +    case ItemC_failsafe:
 +    {
 +      if(force_lcd_update)
 +      {
 +        lcd.setCursor(0,line);lcdprintPGM(" Restore Failsafe");
 +      }
 +      if((activeline==line) && CLICKED)
 +      {
 +        //enquecommand("M84");
 +        beepshort();
 +        BLOCK;
 +        EEPROM_RetrieveSettings(true);
 +      }
 +    }break;
 +    default:   
 +      break;
 +  }
 +  line++;
 + }
 + updateActiveLines(ItemC_failsafe,encoderpos);
 +}
 +
 +
 +
 +
 +
 +void MainMenu::showSD()
 +{
 +#ifdef SDSUPPORT
 + uint8_t line=0;
 +
 + clearIfNecessary();
 + static uint8_t nrfiles=0;
 + if(force_lcd_update)
 + {
 +  if(card.cardOK)
 +  {
 +    nrfiles=card.getnrfilenames();
 +  }
 +  else
 +  {
 +    nrfiles=0;
 +    lineoffset=0;
 +  }
 + }
 + bool enforceupdate=false;
 + for(int8_t i=lineoffset;i<lineoffset+LCD_HEIGHT;i++)
 + {
 +  switch(i)
 +  {
 +    case 0:
 +      MENUITEM(  lcdprintPGM(" Main \003")  ,  BLOCK;status=Main_Menu;beepshort(); ) ;
 +      break;
 +//     case 1:
 +//       {
 +//         if(force_lcd_update)
 +//         {
 +//           lcd.setCursor(0,line);
 +//            #ifdef CARDINSERTED
 +//           if(CARDINSERTED)
 +//           #else
 +//           if(true)
 +//           #endif
 +//           {
 +//             lcdprintPGM(" \004Refresh");
 +//           }
 +//           else
 +//           {
 +//             lcdprintPGM(" \004Insert Card");
 +//           }
 +//           
 +//         }
 +//         if((activeline==line) && CLICKED)
 +//         {
 +//           BLOCK;
 +//           beepshort();
 +//           card.initsd();
 +//           force_lcd_update=true;
 +//            nrfiles=card.getnrfilenames();
 +//         }
 +//       }break;
 +    case 1:
 +      MENUITEM(  lcd.print(" ");card.getWorkDirName();if(card.filename[0]=='/') lcdprintPGM("\004Refresh");else {lcd.print("\005");lcd.print(card.filename);lcd.print("/..");}  ,  BLOCK;card.updir();enforceupdate=true;lineoffset=0;beepshort(); ) ;
 +      
 +      break;
 +    default:
 +    {
 +      #define FIRSTITEM 2
 +      if(i-FIRSTITEM<nrfiles)
 +      {
 +        if(force_lcd_update)
 +        {
 +          card.getfilename(i-FIRSTITEM);
 +          //Serial.print("Filenr:");Serial.println(i-2);
 +          lcd.setCursor(0,line);lcdprintPGM(" ");
 +          if(card.filenameIsDir) lcd.print("\005");
 +          lcd.print(card.filename);
 +        }
 +        if((activeline==line) && CLICKED)
 +        {
 +          BLOCK
 +          card.getfilename(i-FIRSTITEM);
 +          if(card.filenameIsDir)
 +          {
 +            for(int8_t i=0;i<strlen(card.filename);i++)
 +              card.filename[i]=tolower(card.filename[i]);
 +            card.chdir(card.filename);
 +            lineoffset=0;
 +            enforceupdate=true;
 +          }
 +          else
 +          {
 +            char cmd[30];
 +            for(int8_t i=0;i<strlen(card.filename);i++)
 +              card.filename[i]=tolower(card.filename[i]);
 +            sprintf(cmd,"M23 %s",card.filename);
 +            //sprintf(cmd,"M115");
 +            enquecommand(cmd);
 +            enquecommand("M24");
 +            beep(); 
 +            status=Main_Status;
 +            lcd_status(card.filename);
 +          }
 +        }
 +      }
 +      
 +    }
 +      break;
 +  }
 +  line++;
 + }
 + updateActiveLines(FIRSTITEM+nrfiles-1,encoderpos);
 + if(enforceupdate)
 + {
 +   force_lcd_update=true;
 +   enforceupdate=false;
 + }
 +#endif
 +}
 +
 +enum {ItemM_watch, ItemM_prepare, ItemM_control, ItemM_file };
 +void MainMenu::showMainMenu()
 +{
 +
 +  #ifndef ULTIPANEL
 +    force_lcd_update=false;
 +  #endif
 +  if(tune)
 +  {
 +    if(!(movesplanned() ||card.sdprinting))
 +    {
 +      force_lcd_update=true;
 +      tune=false;
 +    }
 +  }
 +  else 
 +  {
 +    if(movesplanned() ||card.sdprinting)
 +    {
 +      force_lcd_update=true;
 +      tune=true;
 +    }
 +  } 
 +  clearIfNecessary();
 +  for(int8_t line=0;line<LCD_HEIGHT;line++)
 +  {
 +    switch(line)
 +    { 
 +      case ItemM_watch:
 +        MENUITEM(  lcdprintPGM(" Watch   \003")  ,  BLOCK;status=Main_Status;beepshort(); ) ;
 +       break;
 +      case ItemM_prepare:
 +        MENUITEM(  if(!tune) lcdprintPGM(" Prepare \x7E");else  lcdprintPGM(" Tune    \x7E"); ,  BLOCK;status=Main_Prepare;beepshort(); ) ;
 +      break;
 +       
 +      case ItemM_control:
 +        MENUITEM(  lcdprintPGM(" Control \x7E")  ,  BLOCK;status=Main_Control;beepshort(); ) ;
 +      break;
 +      #ifdef SDSUPPORT
 +      case ItemM_file:    
 +      {
 +        if(force_lcd_update) 
 +        {
 +          lcd.setCursor(0,line);
 +          #ifdef CARDINSERTED
 +            if(CARDINSERTED)
 +          #else
 +            if(true)
 +          #endif
 +          {
 +            if(card.sdprinting)
 +              lcdprintPGM(" Stop Print   \x7E");
 +            else
 +              lcdprintPGM(" Card Menu    \x7E");
 +          }
 +          else
 +          {
 +           lcdprintPGM(" No Card"); 
 +          }
 +        }
 +        #ifdef CARDINSERTED
 +          if(CARDINSERTED)
 +        #endif
 +        if((activeline==line)&&CLICKED)
 +        {
 +          card.printingHasFinished();
 +          BLOCK;
 +          status=Main_SD;
 +          beepshort();
 +        }
 +      }break;
 +      #else
 +      case ItemM_file:
 +        break;
 +      #endif
 +      default: 
 +        SERIAL_ERROR_START;
 +        SERIAL_ERRORLNPGM("Something is wrong in the MenuStructure.");
 +      break;
 +    }
 +  }
 +  updateActiveLines(3,encoderpos);
 +}
 +
 +void MainMenu::update()
 +{
 +  static MainStatus oldstatus=Main_Menu;  //init automatically causes foce_lcd_update=true
 +  static long timeoutToStatus=0;
 +  static bool oldcardstatus=false;
 +  #ifdef CARDINSERTED
 +    if((CARDINSERTED != oldcardstatus))
 +    {
 +      force_lcd_update=true;
 +      oldcardstatus=CARDINSERTED;
 +      //Serial.println("echo: SD CHANGE");
 +      if(CARDINSERTED)
 +      {
 +        card.initsd();
 +        LCD_MESSAGEPGM("Card inserted");
 +      }
 +      else
 +      {
 +        card.release();
 +        LCD_MESSAGEPGM("Card removed");
 +      }
 +    }
 +  #endif
 + 
 +  if(status!=oldstatus)
 +  {
 +    force_lcd_update=true;
 +    encoderpos=0;
 +    lineoffset=0;
 +    
 +    oldstatus=status;
 +  }
 +  if( (encoderpos!=lastencoderpos) || CLICKED)
 +    timeoutToStatus=millis()+STATUSTIMEOUT;
 +
 +  switch(status)
 +  { 
 +      case Main_Status: 
 +      {  
 +        showStatus();
 +        if(CLICKED)
 +        {
 +           linechanging=false;
 +           BLOCK
 +           status=Main_Menu;
 +           timeoutToStatus=millis()+STATUSTIMEOUT;
 +        }
 +      }break;
 +      case Main_Menu: 
 +      {
 +        showMainMenu();
 +        linechanging=false;
 +      }break;
 +      case Main_Prepare: 
 +      {
 +        if(tune)
 +        {
 +          showTune();
 +        }
 +        else
 +        {
 +          showPrepare(); 
 +        }
 +      }break;
 +      case Main_Control:
 +      {
 +        showControl(); 
 +      }break;
 +      case Sub_MotionControl:
 +      {
 +        showControlMotion(); 
 +      }break;
 +      case Sub_TempControl:
 +      {
 +        showControlTemp(); 
 +      }break;
 +      case Main_SD: 
 +      {
 +        showSD();
 +      }break;
 +  }
 +  
 +  if(timeoutToStatus<millis())
 +    status=Main_Status;
 +  //force_lcd_update=false;
 +  lastencoderpos=encoderpos;
 +}
 +
 +
 +
 +
 +
 +
 +//  convert float to string with +123.4 format
 +char *ftostr3(const float &x)
 +{
 +  //sprintf(conv,"%5.1f",x);
 +  int xx=x;
 +  conv[0]=(xx/100)%10+'0';
 +  conv[1]=(xx/10)%10+'0';
 +  conv[2]=(xx)%10+'0';
 +  conv[3]=0;
 +  return conv;
 +}
 +
 +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
 +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;
 +}
 +
 +char *ftostr32(const float &x)
 +{
 +  int xx=x*100;
 +  conv[0]=(xx>=0)?'+':'-';
 +  xx=abs(xx);
 +  conv[1]=(xx/100)%10+'0';
 +  conv[2]='.';
 +  conv[3]=(xx/10)%10+'0';
 +  conv[4]=(xx)%10+'0';
 +  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;
 +}
 +
 +char *itostr3(const int &xx)
 +{
 +  conv[0]=(xx/100)%10+'0';
 +  conv[1]=(xx/10)%10+'0';
 +  conv[2]=(xx)%10+'0';
 +  conv[3]=0;
 +  return conv;
 +}
 +
 +char *itostr4(const int &xx)
 +{
 +  conv[0]=(xx/1000)%10+'0';
 +  conv[1]=(xx/100)%10+'0';
 +  conv[2]=(xx/10)%10+'0';
 +  conv[3]=(xx)%10+'0';
 +  conv[4]=0;
 +  return conv;
 +}
 +
 +//  convert float to string with +1234.5 format
 +char *ftostr51(const float &x)
 +{
 +  int 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;
 +}
 +
 +
 +#endif //ULTRA_LCD
 +
\r
++