From b21d5193f25e3e388ddc3787aba7f0086a1abad7 Mon Sep 17 00:00:00 2001
From: Bernhard Kubicek <kubicek@gmx.at>
Date: Sun, 20 Nov 2011 14:43:47 +0100
Subject: [PATCH] made ultralcd compatible with folders.

---
 Marlin/cardreader.h   |   6 +-
 Marlin/cardreader.pde | 115 +++++++----
 Marlin/ultralcd.h     |   6 +-
 Marlin/ultralcd.pde   | 461 +++++++++++++++++++++++++-----------------
 4 files changed, 366 insertions(+), 222 deletions(-)

diff --git a/Marlin/cardreader.h b/Marlin/cardreader.h
index 653f59452e..44ebf0e2c1 100644
--- a/Marlin/cardreader.h
+++ b/Marlin/cardreader.h
@@ -28,7 +28,8 @@ public:
   
 
   void ls();
-  
+  void chdir(const char * relpath);
+  void updir();
 
   inline bool eof() { return sdpos>=filesize ;};
   inline int16_t get() {  sdpos = file.curPosition();return (int16_t)file.read();};
@@ -40,8 +41,9 @@ public:
   bool sdprinting ;  
   bool cardOK ;
   char filename[11];
+  bool filenameIsDir;
 private:
-  SdFile root,*curDir;
+  SdFile root,*curDir,workDir,workDirParent,workDirParentParent;
   Sd2Card card;
   SdVolume volume;
   SdFile file;
diff --git a/Marlin/cardreader.pde b/Marlin/cardreader.pde
index bab87834ec..c0dbc58e47 100644
--- a/Marlin/cardreader.pde
+++ b/Marlin/cardreader.pde
@@ -1,4 +1,5 @@
 #include "cardreader.h"
+//#include <unistd.h>
 #ifdef SDSUPPORT
 
 CardReader::CardReader()
@@ -36,11 +37,7 @@ char *createFilename(char *buffer,const dir_t &p) //buffer>12characters
   return buffer;
 }
 
-// bool SdFat::chdir(bool set_cwd) {
-//   if (set_cwd) SdBaseFile::cwd_ = &vwd_;
-//   vwd_.close();
-//   return vwd_.openRoot(&vol_);
-// }
+
 void  CardReader::lsDive(char *prepend,SdFile parent)
 {
   dir_t p;
@@ -85,11 +82,19 @@ void  CardReader::lsDive(char *prepend,SdFile parent)
     {
       if (p.name[0] == DIR_NAME_FREE) break;
       if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.'|| p.name[0] == '_') continue;
+      if ( p.name[0] == '.')
+      {
+        if ( p.name[1] != '.')
+        continue;
+      }
       if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue;
+      filenameIsDir=DIR_IS_SUBDIR(&p);
       
-      
-      if(p.name[8]!='G') continue;
-      if(p.name[9]=='~') continue;
+      if(!filenameIsDir)
+      {
+        if(p.name[8]!='G') continue;
+        if(p.name[9]=='~') continue;
+      }
       //if(cnt++!=nr) continue;
       createFilename(filename,p);
       if(lsAction==LS_SerialPrint)
@@ -126,33 +131,35 @@ void CardReader::ls()
 void CardReader::initsd()
 {
   cardOK = false;
-  #if SDSS >- 1
-    if(root.isOpen())
-      root.close();
-    if (!card.init(SPI_FULL_SPEED,SDSS))
-    {
-      //if (!card.init(SPI_HALF_SPEED,SDSS))
-      SERIAL_ECHO_START;
-      SERIAL_ECHOLNPGM("SD init fail");
-    }
-    else if (!volume.init(&card))
-    {
-      SERIAL_ERROR_START;
-      SERIAL_ERRORLNPGM("volume.init failed");
-    }
-    else if (!root.openRoot(&volume)) 
-    {
-      SERIAL_ERROR_START;
-      SERIAL_ERRORLNPGM("openRoot failed");
-    }
-    else 
-    {
-      cardOK = true;
-      SERIAL_ECHO_START;
-      SERIAL_ECHOLNPGM("SD card ok");
-    }
-    curDir=&root;
-  #endif //SDSS
+  if(root.isOpen())
+    root.close();
+  if (!card.init(SPI_FULL_SPEED,SDSS))
+  {
+    //if (!card.init(SPI_HALF_SPEED,SDSS))
+    SERIAL_ECHO_START;
+    SERIAL_ECHOLNPGM("SD init fail");
+  }
+  else if (!volume.init(&card))
+  {
+    SERIAL_ERROR_START;
+    SERIAL_ERRORLNPGM("volume.init failed");
+  }
+  else if (!root.openRoot(&volume)) 
+  {
+    SERIAL_ERROR_START;
+    SERIAL_ERRORLNPGM("openRoot failed");
+  }
+  else 
+  {
+    cardOK = true;
+    SERIAL_ECHO_START;
+    SERIAL_ECHOLNPGM("SD card ok");
+  }
+  curDir=&root;
+  if(!workDir.openRoot(&volume))
+  {
+    SERIAL_ECHOLNPGM("workDir open failed");
+  }
 }
 void CardReader::release()
 {
@@ -229,6 +236,10 @@ void CardReader::openFile(char* name,bool read)
       
     }
   }
+  else //relative path
+  {
+    curDir=&workDir;
+  }
   if(read)
   {
     if (file.open(curDir, fname, O_READ)) 
@@ -362,6 +373,7 @@ void CardReader::closefile()
 
 void CardReader::getfilename(const uint8_t nr)
 {
+  curDir=&workDir;
   lsAction=LS_GetFilename;
   nrFiles=nr;
   curDir->rewind();
@@ -371,12 +383,45 @@ void CardReader::getfilename(const uint8_t nr)
 
 uint16_t CardReader::getnrfilenames()
 {
+  curDir=&workDir;
   lsAction=LS_Count;
   nrFiles=0;
   curDir->rewind();
   lsDive("",*curDir);
+  //SERIAL_ECHOLN(nrFiles);
   return nrFiles;
 }
 
+void CardReader::chdir(const char * relpath)
+{
+  SdFile newfile;
+  SdFile *parent=&root;
+  
+  if(workDir.isOpen())
+    parent=&workDir;
+  
+  if(!newfile.open(*parent,relpath, O_READ))
+  {
+   SERIAL_ECHO_START;
+   SERIAL_ECHOPGM("Cannot enter subdir:");
+   SERIAL_ECHOLN(relpath);
+  }
+  else
+  {
+    workDirParentParent=workDirParent;
+    workDirParent=*parent;
+    
+    workDir=newfile;
+  }
+}
+
+void CardReader::updir()
+{
+  if(!workDir.isRoot())
+  {
+    workDir=workDirParent;
+    workDirParent=workDirParentParent;
+  }
+}
 
 #endif //SDSUPPORT
\ No newline at end of file
diff --git a/Marlin/ultralcd.h b/Marlin/ultralcd.h
index d3496bec98..6222c70c25 100644
--- a/Marlin/ultralcd.h
+++ b/Marlin/ultralcd.h
@@ -51,13 +51,13 @@
   #define blocktime 500
   #define lcdslow 5
     
-  enum MainStatus{Main_Status, Main_Menu, Main_Prepare, Main_Control, Main_SD};
+  enum MainStatus{Main_Status, Main_Menu, Main_Prepare, Main_Control, Main_SD,Sub_TempControl,Sub_MotionControl};
 
   class MainMenu{
   public:
     MainMenu();
     void update();
-    uint8_t activeline;
+    int8_t activeline;
     MainStatus status;
     uint8_t displayStartingRow;
     
@@ -65,6 +65,8 @@
     void showMainMenu();
     void showPrepare();
     void showControl();
+    void showControlMotion();
+    void showControlTemp();
     void showSD();
     bool force_lcd_update;
     int lastencoderpos;
diff --git a/Marlin/ultralcd.pde b/Marlin/ultralcd.pde
index aa30a3dd0e..57f63c1061 100644
--- a/Marlin/ultralcd.pde
+++ b/Marlin/ultralcd.pde
@@ -114,11 +114,13 @@ void lcd_init()
   };
   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.");
 }
 
@@ -224,6 +226,7 @@ void buttons_check()
     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);
@@ -311,22 +314,22 @@ void MainMenu::showStatus()
     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));
-    olddegHotEnd0=tBed;
-  }
-  int targetBed=intround(degTargetBed());
-  if((targetBed!=oldtargetBed)||force_lcd_update)
-  {
-    lcd.setCursor(5,0);
-    lcd.print(ftostr3(targetBed));
-    oldtargetBed=targetBed;
-  }
+    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;
@@ -421,6 +424,7 @@ void MainMenu::showStatus()
   }
 
 #endif
+  force_lcd_update=false;
 }
 
 enum {ItemP_exit, ItemP_home, ItemP_origin, ItemP_preheat, ItemP_extrude, ItemP_disstep};
@@ -466,16 +470,7 @@ void MainMenu::showPrepare()
  }
  updateActiveLines(ItemP_disstep,encoderpos);
 }
-enum {
-  ItemC_exit, ItemC_nozzle, 
-  ItemC_PID_P,ItemC_PID_I,ItemC_PID_D,ItemC_PID_C,
-  ItemC_fan, 
-  ItemC_acc, ItemC_xyjerk, 
-  ItemC_vmaxx, ItemC_vmaxy, ItemC_vmaxz, ItemC_vmaxe, 
-  ItemC_vtravmin,ItemC_vmin,  
-  ItemC_amaxx, ItemC_amaxy, ItemC_amaxz, ItemC_amaxe, 
-  ItemC_aret,ItemC_esteps, ItemC_store, ItemC_load,ItemC_failsafe
-};
+
 
 //does not work
 // #define MENUCHANGEITEM(repaint_action,  enter_action, accept_action,  change_action) \
@@ -494,19 +489,23 @@ enum {
 //   }
 //   
 
-  
-void MainMenu::showControl()
+enum {
+  ItemCT_exit, ItemCT_nozzle, ItemCT_fan,
+  ItemCT_PID_P,ItemCT_PID_I,ItemCT_PID_D,ItemCT_PID_C
+};
+
+void MainMenu::showControlTemp()
 {
- uint8_t line=0;
+  uint8_t line=0;
  clearIfNecessary();
  for(int8_t i=lineoffset;i<lineoffset+LCD_HEIGHT;i++)
  {
   switch(i)
   {
-    case ItemC_exit:
-      MENUITEM(  lcdprintPGM(" Control")  ,  BLOCK;status=Main_Menu;beepshort(); ) ;
+    case ItemCT_exit:
+      MENUITEM(  lcdprintPGM(" Temperature")  ,  BLOCK;status=Main_Control;beepshort(); ) ;
       break;
-    case ItemC_nozzle:
+    case ItemCT_nozzle:
       {
         if(force_lcd_update)
         {
@@ -540,7 +539,7 @@ void MainMenu::showControl()
         }
       }break;
       
-      case ItemC_fan:
+      case ItemCT_fan:
       {
         if(force_lcd_update)
         {
@@ -577,74 +576,7 @@ void MainMenu::showControl()
           }
         }
       }break;
-    case ItemC_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) )
-        {
-          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 ItemC_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) )
-        {
-          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 ItemC_PID_P: 
+      case ItemCT_PID_P: 
       {
       if(force_lcd_update)
         {
@@ -678,7 +610,7 @@ void MainMenu::showControl()
           }
         }
       }break;
-    case ItemC_PID_I: 
+    case ItemCT_PID_I: 
       {
       if(force_lcd_update)
         {
@@ -712,7 +644,7 @@ void MainMenu::showControl()
           }
         }
       }break;
-      case ItemC_PID_D: 
+      case ItemCT_PID_D: 
       {
       if(force_lcd_update)
         {
@@ -745,11 +677,9 @@ void MainMenu::showControl()
             lcd.setCursor(13,line);lcd.print(itostr4(encoderpos*5));
           }
         }
-      }break;
-    
-    
-      
-    case ItemC_PID_C: 
+      }break;   
+    case ItemCT_PID_C: 
+      #ifdef PID_ADD_EXTRUSION_RATE
       {
       if(force_lcd_update)
         {
@@ -782,20 +712,50 @@ void MainMenu::showControl()
             lcd.setCursor(13,line);lcd.print(itostr3(encoderpos));
           }
         }
-      }break;
-    case ItemC_vmaxx:
-    case ItemC_vmaxy:
-    case ItemC_vmaxz:
-    case ItemC_vmaxe:
-      {
+      }
+      #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(" Motion")  ,  BLOCK;status=Main_Control;beepshort(); ) ;
+      break;
+    case ItemCM_acc:
+    {
       if(force_lcd_update)
         {
-          lcd.setCursor(0,line);lcdprintPGM(" Vmax ");
-          if(i==ItemC_vmaxx)lcdprintPGM("x:");
-          if(i==ItemC_vmaxy)lcdprintPGM("y:");
-          if(i==ItemC_vmaxz)lcdprintPGM("z:");
-          if(i==ItemC_vmaxe)lcdprintPGM("e:");
-          lcd.setCursor(13,line);lcd.print(itostr3(max_feedrate[i-ItemC_vmaxx]));
+          lcd.setCursor(0,line);lcdprintPGM(" Acc:");
+          lcd.setCursor(13,line);lcd.print(itostr3(acceleration/100));lcdprintPGM("00");
         }
         
         if((activeline==line) )
@@ -805,11 +765,86 @@ void MainMenu::showControl()
             linechanging=!linechanging;
             if(linechanging)
             {
-               encoderpos=(int)max_feedrate[i-ItemC_vmaxx];
+               encoderpos=(int)acceleration/100;
             }
             else
             {
-              max_feedrate[i-ItemC_vmaxx]= encoderpos;
+              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) )
+        {
+          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) )
+        {
+          if(CLICKED)
+          {
+            linechanging=!linechanging;
+            if(linechanging)
+            {
+               encoderpos=(int)max_feedrate[i-ItemCM_vmaxx];
+            }
+            else
+            {
+              max_feedrate[i-ItemCM_vmaxx]= encoderpos;
               encoderpos=activeline*lcdslow;
                 
             }
@@ -825,7 +860,7 @@ void MainMenu::showControl()
         }
       }break;
     
-    case ItemC_vmin:
+    case ItemCM_vmin:
     {
       if(force_lcd_update)
         {
@@ -859,7 +894,7 @@ void MainMenu::showControl()
           }
         }
       }break;
-    case ItemC_vtravmin:
+    case ItemCM_vtravmin:
     {
       if(force_lcd_update)
         {
@@ -894,19 +929,19 @@ void MainMenu::showControl()
         }
       }break;
     
-    case ItemC_amaxx:      
-    case ItemC_amaxy:
-    case ItemC_amaxz:
-    case ItemC_amaxe:
+    case ItemCM_amaxx:      
+    case ItemCM_amaxy:
+    case ItemCM_amaxz:
+    case ItemCM_amaxe:
     {
       if(force_lcd_update)
         {
           lcd.setCursor(0,line);lcdprintPGM(" Amax ");
-          if(i==ItemC_amaxx)lcdprintPGM("x:");
-          if(i==ItemC_amaxy)lcdprintPGM("y:");
-          if(i==ItemC_amaxz)lcdprintPGM("z:");
-          if(i==ItemC_amaxe)lcdprintPGM("e:");
-          lcd.setCursor(13,line);lcd.print(itostr3(max_acceleration_units_per_sq_second[i-ItemC_amaxx]/100));lcdprintPGM("00");
+          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) )
@@ -916,11 +951,11 @@ void MainMenu::showControl()
             linechanging=!linechanging;
             if(linechanging)
             {
-               encoderpos=(int)max_acceleration_units_per_sq_second[i-ItemC_amaxx]/100;
+               encoderpos=(int)max_acceleration_units_per_sq_second[i-ItemCM_amaxx]/100;
             }
             else
             {
-              max_acceleration_units_per_sq_second[i-ItemC_amaxx]= encoderpos*100;
+              max_acceleration_units_per_sq_second[i-ItemCM_amaxx]= encoderpos*100;
               encoderpos=activeline*lcdslow;
             }
             BLOCK;
@@ -934,7 +969,7 @@ void MainMenu::showControl()
           }
         }
       }break;
-    case ItemC_aret://float retract_acceleration = 7000;
+    case ItemCM_aret://float retract_acceleration = 7000;
     {
         if(force_lcd_update)
         {
@@ -968,7 +1003,7 @@ void MainMenu::showControl()
           }
         }
       }break;
-    case ItemC_esteps://axis_steps_per_unit[i] = code_value();
+    case ItemCM_esteps://axis_steps_per_unit[i] = code_value();
          {
       if(force_lcd_update)
         {
@@ -1005,6 +1040,37 @@ void MainMenu::showControl()
           }
         }
       }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(" Control     \x7E")  ,  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)
@@ -1059,7 +1125,6 @@ void MainMenu::showControl()
 
 
 
-
 void MainMenu::showSD()
 {
 #ifdef SDSUPPORT
@@ -1069,7 +1134,6 @@ void MainMenu::showSD()
  static uint8_t nrfiles=0;
  if(force_lcd_update)
  {
-  clear();
   if(card.cardOK)
   {
     nrfiles=card.getnrfilenames();
@@ -1080,7 +1144,7 @@ void MainMenu::showSD()
     lineoffset=0;
   }
  }
- 
+ bool enforceupdate=false;
  for(int8_t i=lineoffset;i<lineoffset+LCD_HEIGHT;i++)
  {
   switch(i)
@@ -1088,58 +1152,76 @@ void MainMenu::showSD()
     case 0:
       MENUITEM(  lcdprintPGM(" File")  ,  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:
-      {
-        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;
+      MENUITEM(  lcdprintPGM(" ..")  ,  BLOCK;card.updir();enforceupdate=true;lineoffset=0;beepshort(); ) ;
+      
+      break;
     default:
     {
-      if(i-2<nrfiles)
+      #define FIRSTITEM 2
+      if(i-FIRSTITEM<nrfiles)
       {
         if(force_lcd_update)
         {
-          card.getfilename(i-2);
+          card.getfilename(i-FIRSTITEM);
           //Serial.print("Filenr:");Serial.println(i-2);
-          lcd.setCursor(0,line);lcdprintPGM(" ");lcd.print(card.filename);
+          lcd.setCursor(0,line);lcdprintPGM(" ");
+          if(card.filenameIsDir) lcd.print("\005");
+          lcd.print(card.filename);
         }
         if((activeline==line) && CLICKED)
         {
           BLOCK
-          card.getfilename(i-2);
-          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);
+          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);
+          }
         }
       }
       
@@ -1148,7 +1230,12 @@ void MainMenu::showSD()
   }
   line++;
  }
- updateActiveLines(1+nrfiles,encoderpos);
+ updateActiveLines(FIRSTITEM+nrfiles-1,encoderpos);
+ if(enforceupdate)
+ {
+   force_lcd_update=true;
+   enforceupdate=false;
+ }
 #endif
 }
 
@@ -1282,6 +1369,14 @@ void MainMenu::update()
       {
         showControl(); 
       }break;
+      case Sub_MotionControl:
+      {
+        showControlMotion(); 
+      }break;
+      case Sub_TempControl:
+      {
+        showControlTemp(); 
+      }break;
       case Main_SD: 
       {
         showSD();
@@ -1290,7 +1385,7 @@ void MainMenu::update()
   
   if(timeoutToStatus<millis())
     status=Main_Status;
-  force_lcd_update=false;
+  //force_lcd_update=false;
   lastencoderpos=encoderpos;
 }