From 70abca195abfbb1a8ecf7eba8e27f61ba7eee759 Mon Sep 17 00:00:00 2001
From: Bernhard Kubicek <kubicek@gmx.at>
Date: Sat, 19 Nov 2011 13:13:34 +0100
Subject: [PATCH 1/5] overworked cardreader for folder support; not finished
 yet.

---
 Marlin/Marlin.pde     |   5 +-
 Marlin/SdFat.cpp      | 329 ------------------------------------------
 Marlin/SdFat.h        |  76 ----------
 Marlin/cardreader.h   |  25 ++--
 Marlin/cardreader.pde | 193 +++++++++++++++++--------
 5 files changed, 154 insertions(+), 474 deletions(-)
 delete mode 100644 Marlin/SdFat.cpp
 delete mode 100644 Marlin/SdFat.h

diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde
index 8dc8d0822e..34d50e3c46 100644
--- a/Marlin/Marlin.pde
+++ b/Marlin/Marlin.pde
@@ -176,6 +176,7 @@ static unsigned long stoptime=0;
 //=============================ROUTINES=============================
 //===========================================================================
 
+void get_arc_coordinates();
 
 extern "C"{
   extern unsigned int __bss_end;
@@ -588,7 +589,7 @@ inline void process_commands()
       starpos = (strchr(strchr_pointer + 4,'*'));
       if(starpos!=NULL)
         *(starpos-1)='\0';
-      card.selectFile(strchr_pointer + 4);
+      card.openFile(strchr_pointer + 4,true);
       break;
     case 24: //M24 - Start SD print
       card.startFileprint();
@@ -613,7 +614,7 @@ inline void process_commands()
         strchr_pointer = strchr(npos,' ') + 1;
         *(starpos-1) = '\0';
       }
-      card.startFilewrite(strchr_pointer+4);
+      card.openFile(strchr_pointer+4,false);
       
       break;
     case 29: //M29 - Stop SD write
diff --git a/Marlin/SdFat.cpp b/Marlin/SdFat.cpp
deleted file mode 100644
index 494fd48225..0000000000
--- a/Marlin/SdFat.cpp
+++ /dev/null
@@ -1,329 +0,0 @@
-/* Arduino SdFat Library
- * Copyright (C) 2009 by William Greiman
- *
- * This file is part of the Arduino SdFat Library
- *
- * This Library 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.
- *
- * This Library 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 the Arduino SdFat Library.  If not, see
- * <http://www.gnu.org/licenses/>.
- */
-#include "SdFat.h"
-#include "SdFatUtil.h"
-//------------------------------------------------------------------------------
-/** Change a volume's working directory to root
- *
- * Changes the volume's working directory to the SD's root directory.
- * Optionally set the current working directory to the volume's
- * working directory.
- *
- * \param[in] set_cwd Set the current working directory to this volume's
- *  working directory if true.
- *
- * \return The value one, true, is returned for success and
- * the value zero, false, is returned for failure.
- */
-bool SdFat::chdir(bool set_cwd) {
-  if (set_cwd) SdBaseFile::cwd_ = &vwd_;
-  vwd_.close();
-  return vwd_.openRoot(&vol_);
-}
-//------------------------------------------------------------------------------
-/** Change a volume's working directory
- *
- * Changes the volume working directory to the \a path subdirectory.
- * Optionally set the current working directory to the volume's
- * working directory.
- *
- * Example: If the volume's working directory is "/DIR", chdir("SUB")
- * will change the volume's working directory from "/DIR" to "/DIR/SUB".
- *
- * If path is "/", the volume's working directory will be changed to the
- * root directory
- *
- * \param[in] path The name of the subdirectory.
- *
- * \param[in] set_cwd Set the current working directory to this volume's
- *  working directory if true.
- *
- * \return The value one, true, is returned for success and
- * the value zero, false, is returned for failure.
- */
-bool SdFat::chdir(const char *path, bool set_cwd) {
-  SdBaseFile dir;
-  if (path[0] == '/' && path[1] == '\0') return chdir(set_cwd);
-  if (!dir.open(&vwd_, path, O_READ)) goto fail;
-  if (!dir.isDir()) goto fail;
-  vwd_ = dir;
-  if (set_cwd) SdBaseFile::cwd_ = &vwd_;
-  return true;
-
- fail:
-  return false;
-}
-//------------------------------------------------------------------------------
-/** Set the current working directory to a volume's working directory.
- *
- * This is useful with multiple SD cards.
- *
- * The current working directory is changed to this volume's working directory.
- *
- * This is like the Windows/DOS \<drive letter>: command.
- */
-void SdFat::chvol() {
-  SdBaseFile::cwd_ = &vwd_;
-}
-//------------------------------------------------------------------------------
-/** %Print any SD error code and halt. */
-void SdFat::errorHalt() {
-  errorPrint();
-  while (1);
-}
-//------------------------------------------------------------------------------
-/** %Print msg, any SD error code, and halt.
- *
- * \param[in] msg Message to print.
- */
-void SdFat::errorHalt(char const* msg) {
-  errorPrint(msg);
-  while (1);
-}
-//------------------------------------------------------------------------------
-/** %Print msg, any SD error code, and halt.
- *
- * \param[in] msg Message in program space (flash memory) to print.
- */
-void SdFat::errorHalt_P(PGM_P msg) {
-  errorPrint_P(msg);
-  while (1);
-}
-//------------------------------------------------------------------------------
-/** %Print any SD error code. */
-void SdFat::errorPrint() {
-  if (!card_.errorCode()) return;
-  PgmPrint("SD errorCode: 0X");
-  Serial.println(card_.errorCode(), HEX);
-}
-//------------------------------------------------------------------------------
-/** %Print msg, any SD error code.
- *
- * \param[in] msg Message to print.
- */
-void SdFat::errorPrint(char const* msg) {
-  PgmPrint("error: ");
-  Serial.println(msg);
-  errorPrint();
-}
-//------------------------------------------------------------------------------
-/** %Print msg, any SD error code.
- *
- * \param[in] msg Message in program space (flash memory) to print.
- */
-void SdFat::errorPrint_P(PGM_P msg) {
-  PgmPrint("error: ");
-  SerialPrintln_P(msg);
-  errorPrint();
-}
-//------------------------------------------------------------------------------
-/**
- * Test for the existence of a file.
- *
- * \param[in] name Name of the file to be tested for.
- *
- * \return true if the file exists else false.
- */
-bool SdFat::exists(const char* name) {
-  return vwd_.exists(name);
-}
-//------------------------------------------------------------------------------
-/**
- * Initialize an SdFat object.
- *
- * Initializes the SD card, SD volume, and root directory.
- *
- * \param[in] sckRateID value for SPI SCK rate. See Sd2Card::init().
- * \param[in] chipSelectPin SD chip select pin. See Sd2Card::init().
- *
- * \return The value one, true, is returned for success and
- * the value zero, false, is returned for failure.
- */
-bool SdFat::init(uint8_t sckRateID, uint8_t chipSelectPin) {
-  return card_.init(sckRateID, chipSelectPin) && vol_.init(&card_) && chdir(1);
-}
-//------------------------------------------------------------------------------
-/** %Print error details and halt after SdFat::init() fails. */
-void SdFat::initErrorHalt() {
-  initErrorPrint();
-  while (1);
-}
-//------------------------------------------------------------------------------
-/**Print message, error details, and halt after SdFat::init() fails.
- *
- * \param[in] msg Message to print.
- */
-void SdFat::initErrorHalt(char const *msg) {
-  Serial.println(msg);
-  initErrorHalt();
-}
-//------------------------------------------------------------------------------
-/**Print message, error details, and halt after SdFat::init() fails.
- *
- * \param[in] msg Message in program space (flash memory) to print.
- */
-void SdFat::initErrorHalt_P(PGM_P msg) {
-  SerialPrintln_P(msg);
-  initErrorHalt();
-}
-//------------------------------------------------------------------------------
-/** Print error details after SdFat::init() fails. */
-void SdFat::initErrorPrint() {
-  if (card_.errorCode()) {
-    PgmPrintln("Can't access SD card. Do not reformat.");
-    if (card_.errorCode() == SD_CARD_ERROR_CMD0) {
-      PgmPrintln("No card, wrong chip select pin, or SPI problem?");
-    }
-    errorPrint();
-  } else if (vol_.fatType() == 0) {
-    PgmPrintln("Invalid format, reformat SD.");
-  } else if (!vwd_.isOpen()) {
-    PgmPrintln("Can't open root directory.");
-  } else {
-    PgmPrintln("No error found.");
-  }
-}
-//------------------------------------------------------------------------------
-/**Print message and error details and halt after SdFat::init() fails.
- *
- * \param[in] msg Message to print.
- */
-void SdFat::initErrorPrint(char const *msg) {
-  Serial.println(msg);
-  initErrorPrint();
-}
-//------------------------------------------------------------------------------
-/**Print message and error details after SdFat::init() fails.
- *
- * \param[in] msg Message in program space (flash memory) to print.
- */
-void SdFat::initErrorPrint_P(PGM_P msg) {
-  SerialPrintln_P(msg);
-  initErrorHalt();
-}
-//------------------------------------------------------------------------------
-/** List the directory contents of the volume working directory to Serial.
- *
- * \param[in] flags The inclusive OR of
- *
- * LS_DATE - %Print file modification date
- *
- * LS_SIZE - %Print file size.
- *
- * LS_R - Recursive list of subdirectories.
- */
-void SdFat::ls(uint8_t flags) {
-  vwd_.ls(&Serial, flags);
-}
-//------------------------------------------------------------------------------
-/** List the directory contents of the volume working directory to Serial.
- *
- * \param[in] pr Print stream for list.
- *
- * \param[in] flags The inclusive OR of
- *
- * LS_DATE - %Print file modification date
- *
- * LS_SIZE - %Print file size.
- *
- * LS_R - Recursive list of subdirectories.
- */
-void SdFat::ls(Print* pr, uint8_t flags) {
-  vwd_.ls(pr, flags);
-}
-//------------------------------------------------------------------------------
-/** Make a subdirectory in the volume working directory.
- *
- * \param[in] path A path with a valid 8.3 DOS name for the subdirectory.
- *
- * \param[in] pFlag Create missing parent directories if true.
- *
- * \return The value one, true, is returned for success and
- * the value zero, false, is returned for failure.
- */
-bool SdFat::mkdir(const char* path, bool pFlag) {
-  SdBaseFile sub;
-  return sub.mkdir(&vwd_, path, pFlag);
-}
-//------------------------------------------------------------------------------
-/** Remove a file from the volume working directory.
-*
-* \param[in] path A path with a valid 8.3 DOS name for the file.
-*
-* \return The value one, true, is returned for success and
-* the value zero, false, is returned for failure.
-*/
-bool SdFat::remove(const char* path) {
-  return SdBaseFile::remove(&vwd_, path);
-}
-//------------------------------------------------------------------------------
-/** Rename a file or subdirectory.
- *
- * \param[in] oldPath Path name to the file or subdirectory to be renamed.
- *
- * \param[in] newPath New path name of the file or subdirectory.
- *
- * The \a newPath object must not exist before the rename call.
- *
- * The file to be renamed must not be open.  The directory entry may be
- * moved and file system corruption could occur if the file is accessed by
- * a file object that was opened before the rename() call.
- *
- * \return The value one, true, is returned for success and
- * the value zero, false, is returned for failure.
- */
-bool SdFat::rename(const char *oldPath, const char *newPath) {
-  SdBaseFile file;
-  if (!file.open(oldPath, O_READ)) return false;
-  return file.rename(&vwd_, newPath);
-}
-//------------------------------------------------------------------------------
-/** Remove a subdirectory from the volume's working directory.
- *
- * \param[in] path A path with a valid 8.3 DOS name for the subdirectory.
- *
- * The subdirectory file will be removed only if it is empty.
- *
- * \return The value one, true, is returned for success and
- * the value zero, false, is returned for failure.
- */
-bool SdFat::rmdir(const char* path) {
-  SdBaseFile sub;
-  if (!sub.open(path, O_READ)) return false;
-  return sub.rmdir();
-}
-//------------------------------------------------------------------------------
-/** Truncate a file to a specified length.  The current file position
- * will be maintained if it is less than or equal to \a length otherwise
- * it will be set to end of file.
- *
- * \param[in] path A path with a valid 8.3 DOS name for the file.
- * \param[in] length The desired length for the file.
- *
- * \return The value one, true, is returned for success and
- * the value zero, false, is returned for failure.
- * Reasons for failure include file is read only, file is a directory,
- * \a length is greater than the current file size or an I/O error occurs.
- */
-bool SdFat::truncate(const char* path, uint32_t length) {
-  SdBaseFile file;
-  if (!file.open(path, O_WRITE)) return false;
-  return file.truncate(length);
-}
diff --git a/Marlin/SdFat.h b/Marlin/SdFat.h
deleted file mode 100644
index 1a184d0843..0000000000
--- a/Marlin/SdFat.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/* Arduino SdFat Library
- * Copyright (C) 2009 by William Greiman
- *
- * This file is part of the Arduino SdFat Library
- *
- * This Library 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.
- *
- * This Library 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 the Arduino SdFat Library.  If not, see
- * <http://www.gnu.org/licenses/>.
- */
-#ifndef SdFat_h
-#define SdFat_h
-/**
- * \file
- * \brief SdFat class
- */
-#include "SdFile.h"
-//#include <SdStream.h>
-//#include <ArduinoStream.h>
-//------------------------------------------------------------------------------
-/** SdFat version YYYYMMDD */
-#define SD_FAT_VERSION 20110902
-//------------------------------------------------------------------------------
-/**
- * \class SdFat
- * \brief Integration class for the %SdFat library.
- */
-class SdFat {
- public:
-  SdFat() {}
-  /** \return a pointer to the Sd2Card object. */
-  Sd2Card* card() {return &card_;}
-  bool chdir(bool set_cwd = false);
-  bool chdir(const char* path, bool set_cwd = false);
-  void chvol();
-  void errorHalt();
-  void errorHalt_P(PGM_P msg);
-  void errorHalt(char const *msg);
-  void errorPrint();
-  void errorPrint_P(PGM_P msg);
-  void errorPrint(char const *msg);
-  bool exists(const char* name);
-  bool init(uint8_t sckRateID = SPI_FULL_SPEED,
-    uint8_t chipSelectPin = SD_CHIP_SELECT_PIN);
-  void initErrorHalt();
-  void initErrorHalt(char const *msg);
-  void initErrorHalt_P(PGM_P msg);
-  void initErrorPrint();
-  void initErrorPrint(char const *msg);
-  void initErrorPrint_P(PGM_P msg);
-  void ls(uint8_t flags = 0);
-  void ls(Print* pr, uint8_t flags = 0);
-  bool mkdir(const char* path, bool pFlag = true);
-  bool remove(const char* path);
-  bool rename(const char *oldPath, const char *newPath);
-  bool rmdir(const char* path);
-  bool truncate(const char* path, uint32_t length);
-  /** \return a pointer to the SdVolume object. */
-  SdVolume* vol() {return &vol_;}
-  /** \return a pointer to the volume working directory. */
-  SdBaseFile* vwd() {return &vwd_;}
- private:
-  Sd2Card card_;
-  SdVolume vol_;
-  SdBaseFile vwd_;
-};
-#endif  // SdFat_h
diff --git a/Marlin/cardreader.h b/Marlin/cardreader.h
index 04076bfda0..d96715807f 100644
--- a/Marlin/cardreader.h
+++ b/Marlin/cardreader.h
@@ -3,9 +3,8 @@
 
 #ifdef SDSUPPORT
  
-
-#include "SdFat.h"
-
+#include "SdFile.h"
+enum LsAction {LS_SerialPrint,LS_Count,LS_GetFilename};
 class CardReader
 {
 public:
@@ -17,20 +16,22 @@ public:
   //this is to delay autostart and hence the initialisaiton of the sd card to some seconds after the normal init, so the device is available quick after a reset
 
   void checkautostart(bool x); 
-  
+  void openFile(char* name,bool read);
   void closefile();
   void release();
   void startFileprint();
-  void startFilewrite(char *name);
+  //void startFilewrite(char *name);
   void pauseSDPrint();
   void getStatus();
-  
-  void selectFile(char* name);
+  void cd(char * absolutPath);
+  //void selectFile(char* name);
   void getfilename(const uint8_t nr);
-  uint8_t getnrfilenames();
+  uint16_t getnrfilenames();
   
 
-  inline void ls() {root.ls();};
+  void ls();
+  void lsDive(char *prepend,SdFile parent);
+
   inline bool eof() { return sdpos>=filesize ;};
   inline int16_t get() {  sdpos = file.curPosition();return (int16_t)file.read();};
   inline void setIndex(long index) {sdpos = index;file.seekSet(index);};
@@ -42,7 +43,7 @@ public:
   bool cardOK ;
   char filename[11];
 private:
-  SdFile root;
+  SdFile root,*curDir;
   Sd2Card card;
   SdVolume volume;
   SdFile file;
@@ -52,6 +53,10 @@ private:
   uint32_t sdpos ;
 
   bool autostart_stilltocheck; //the sd start is delayed, because otherwise the serial cannot answer fast enought to make contact with the hostsoftware.
+  
+  LsAction lsAction; //stored for recursion.
+  int16_t nrFiles; //counter for the files in the current directory and recycled as position counter for getting the nrFiles'th name in the directory.
+  char* diveDirName;
 };
   
 
diff --git a/Marlin/cardreader.pde b/Marlin/cardreader.pde
index 605af11bf5..77a8f692bf 100644
--- a/Marlin/cardreader.pde
+++ b/Marlin/cardreader.pde
@@ -20,6 +20,106 @@ CardReader::CardReader()
   autostart_atmillis=millis()+5000;
 }
 
+char *createFilename(char *buffer,const dir_t &p) //buffer>12characters
+{
+  char *pos=buffer;
+  for (uint8_t i = 0; i < 11; i++) 
+  {
+    if (p.name[i] == ' ')continue;
+    if (i == 8) 
+    {
+      *pos++='.';
+    }
+    *pos++=p.name[i];
+  }
+  *pos++=0;
+  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;
+ uint8_t cnt=0;
+ 
+  while (parent.readDir(p) > 0)
+  {
+    if( DIR_IS_SUBDIR(&p) && lsAction!=LS_Count && lsAction!=LS_GetFilename)
+    {
+
+      char path[13*2];
+      char lfilename[13];
+      createFilename(lfilename,p);
+      
+      path[0]=0;
+      if(strlen(prepend)==0) //avoid leading / if already in prepend
+      {
+       strcat(path,"/");
+      }
+      strcat(path,prepend);
+      strcat(path,lfilename);
+      strcat(path,"/");
+      
+      Serial.print(path);
+      
+      SdFile dir;
+      if(!dir.open(parent,lfilename, O_READ))
+      {
+        if(lsAction==LS_SerialPrint)
+        {
+          SERIAL_ECHO_START;
+          SERIAL_ECHOLN("Cannot open subdir");
+          SERIAL_ECHOLN(lfilename);
+        }
+      }
+      lsDive(path,dir);
+      //close done automatically by destructor of SdFile
+
+      
+    }
+    if (p.name[0] == DIR_NAME_FREE) break;
+    if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.'|| p.name[0] == '_') continue;
+    if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue;
+    
+    
+    if(p.name[8]!='G') continue;
+    if(p.name[9]=='~') continue;
+    //if(cnt++!=nr) continue;
+    createFilename(filename,p);
+    if(lsAction==LS_SerialPrint)
+    {
+      SERIAL_PROTOCOL(prepend);
+      SERIAL_PROTOCOLLN(filename);
+    }
+    else if(lsAction==LS_Count)
+    {
+      nrFiles++;
+    } 
+    else if(lsAction==LS_GetFilename)
+    {
+      if(cnt==nrFiles)
+        return;
+      cnt++;
+      
+    }
+  }
+}
+
+void CardReader::ls() 
+{
+  lsAction=LS_SerialPrint;
+  if(lsAction==LS_Count)
+  nrFiles=0;
+
+  root.rewind();
+  lsDive("",root);
+}
+
+
 void CardReader::initsd()
 {
   cardOK = false;
@@ -48,6 +148,7 @@ void CardReader::initsd()
       SERIAL_ECHO_START;
       SERIAL_ECHOLNPGM("SD card ok");
     }
+    curDir=&root;
   #endif //SDSS
 }
 void CardReader::release()
@@ -73,13 +174,20 @@ void CardReader::pauseSDPrint()
   }
 }
 
-void CardReader::selectFile(char* name)
+
+
+void CardReader::openFile(char* name,bool read)
 {
-  if(cardOK){
-    sdprinting = false;
-    file.close();
-   
-    if (file.open(&root, name, O_READ)) {
+  if(!cardOK)
+    return;
+  
+    
+  file.close();
+  sdprinting = false;
+  if(read)
+  {
+    if (file.open(&root, name, O_READ)) 
+    {
       filesize = file.fileSize();
       SERIAL_PROTOCOLPGM("File opened:");
       SERIAL_PROTOCOL(name);
@@ -89,32 +197,27 @@ void CardReader::selectFile(char* name)
       
       SERIAL_PROTOCOLLNPGM("File selected");
     }
-    else{
+    else
+    {
       SERIAL_PROTOCOLLNPGM("file.open failed");
     }
   }
-}
-
-void CardReader::startFilewrite(char *name)
-{
-  if(cardOK)
-  {
-    
-    file.close();
-    sdprinting = false;
-    
+  else 
+  { //write
     if (!file.open(&root, name, O_CREAT | O_APPEND | O_WRITE | O_TRUNC))
     {
       SERIAL_PROTOCOLPGM("open failed, File: ");
       SERIAL_PROTOCOL(name);
       SERIAL_PROTOCOLLNPGM(".");
     }
-    else{
+    else
+    {
       saving = true;
       SERIAL_PROTOCOLPGM("Writing to file: ");
       SERIAL_PROTOCOLLN(name);
     }
   }
+  
 }
 
 void CardReader::getStatus()
@@ -212,49 +315,25 @@ void CardReader::closefile()
 
 void CardReader::getfilename(const uint8_t nr)
 {
-
-  dir_t p;
-  root.rewind();
-  uint8_t cnt=0;
-  filename[0]='\0';
-  while (root.readDir(p) > 0)
-  {
-    if (p.name[0] == DIR_NAME_FREE) break;
-    if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.'|| p.name[0] == '_') continue;
-    if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue;
-    if(p.name[8]!='G') continue;
-    if(p.name[9]=='~') continue;
-    if(cnt++!=nr) continue;
-    //Serial.println((char*)p.name);
-    uint8_t writepos=0;
-    for (int8_t i = 0; i < 11; i++) 
-    {
-      if (p.name[i] == ' ') continue;
-      if (i == 8) {
-        filename[writepos++]='.';
-      }
-      filename[writepos++]=p.name[i];
-    }
-    filename[writepos++]=0;
-  }
+  lsAction=LS_GetFilename;
+  nrFiles=nr;
+  curDir->rewind();
+  lsDive("",*curDir);
+  
 }
 
-uint8_t CardReader::getnrfilenames()
+uint16_t CardReader::getnrfilenames()
 {
-  dir_t p;
-  root.rewind();
-  uint8_t cnt=0;
-  while (root.readDir(p) > 0)
-  {
-    if (p.name[0] == DIR_NAME_FREE) break;
-    if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.'|| p.name[0] == '_') continue;
-    if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue;
-    if(p.name[8]!='G') continue;
-    if(p.name[9]=='~') continue;
-    cnt++;
-  }
-  return cnt;
+  lsAction=LS_Count;
+  nrFiles=0;
+  curDir->rewind();
+  lsDive("",*curDir);
+  return nrFiles;
 }
 
+void CardReader::cd(char * absolutPath)
+{
+  
+}
 
 #endif //SDSUPPORT
\ No newline at end of file

From 869cee74e6cdca8caccd281daf2f45cc8e1944b7 Mon Sep 17 00:00:00 2001
From: Bernhard Kubicek <kubicek@gmx.at>
Date: Sat, 19 Nov 2011 14:34:27 +0100
Subject: [PATCH 2/5] host-based sd card printing seems now to work with
 folders

---
 Marlin/cardreader.pde | 101 ++++++++++++++++++++++++++++++------------
 1 file changed, 72 insertions(+), 29 deletions(-)

diff --git a/Marlin/cardreader.pde b/Marlin/cardreader.pde
index 77a8f692bf..4c869e4276 100644
--- a/Marlin/cardreader.pde
+++ b/Marlin/cardreader.pde
@@ -64,7 +64,7 @@ void  CardReader::lsDive(char *prepend,SdFile parent)
       strcat(path,lfilename);
       strcat(path,"/");
       
-      Serial.print(path);
+      //Serial.print(path);
       
       SdFile dir;
       if(!dir.open(parent,lfilename, O_READ))
@@ -81,30 +81,33 @@ 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 (!DIR_IS_FILE_OR_SUBDIR(&p)) continue;
-    
-    
-    if(p.name[8]!='G') continue;
-    if(p.name[9]=='~') continue;
-    //if(cnt++!=nr) continue;
-    createFilename(filename,p);
-    if(lsAction==LS_SerialPrint)
+    else
     {
-      SERIAL_PROTOCOL(prepend);
-      SERIAL_PROTOCOLLN(filename);
-    }
-    else if(lsAction==LS_Count)
-    {
-      nrFiles++;
-    } 
-    else if(lsAction==LS_GetFilename)
-    {
-      if(cnt==nrFiles)
-        return;
-      cnt++;
+      if (p.name[0] == DIR_NAME_FREE) break;
+      if (p.name[0] == DIR_NAME_DELETED || p.name[0] == '.'|| p.name[0] == '_') continue;
+      if (!DIR_IS_FILE_OR_SUBDIR(&p)) continue;
       
+      
+      if(p.name[8]!='G') continue;
+      if(p.name[9]=='~') continue;
+      //if(cnt++!=nr) continue;
+      createFilename(filename,p);
+      if(lsAction==LS_SerialPrint)
+      {
+        SERIAL_PROTOCOL(prepend);
+        SERIAL_PROTOCOLLN(filename);
+      }
+      else if(lsAction==LS_Count)
+      {
+        nrFiles++;
+      } 
+      else if(lsAction==LS_GetFilename)
+      {
+        if(cnt==nrFiles)
+          return;
+        cnt++;
+        
+      }
     }
   }
 }
@@ -180,17 +183,57 @@ void CardReader::openFile(char* name,bool read)
 {
   if(!cardOK)
     return;
-  
-    
   file.close();
   sdprinting = false;
+  
+  
+  SdFile myDir;
+  curDir=&root;
+  char *fname=name;
+  
+  char *dirname_start,*dirname_end;
+  dirname_start=strchr(name,'/')+1;
+  while(dirname_start!=NULL)
+  {
+    dirname_end=strchr(dirname_start,'/');
+    //SERIAL_ECHO("start:");SERIAL_ECHOLN((int)(dirname_start-name));
+    //SERIAL_ECHO("end  :");SERIAL_ECHOLN((int)(dirname_end-name));
+    if(dirname_end!=NULL && dirname_end>dirname_start)
+    {
+      char subdirname[13];
+      strncpy(subdirname, dirname_start, dirname_end-dirname_start);
+      subdirname[dirname_end-dirname_start]=0;
+      SERIAL_ECHOLN(subdirname);
+      if(!myDir.open(curDir,subdirname,O_READ))
+      {
+        SERIAL_PROTOCOLPGM("open failed, File: ");
+        SERIAL_PROTOCOL(subdirname);
+        SERIAL_PROTOCOLLNPGM(".");
+        return;
+      }
+      else
+        SERIAL_ECHOLN("dive ok");
+        
+      curDir=&myDir; 
+      dirname_start=dirname_end+1;
+    }
+    else // the reminder after all /fsa/fdsa/ is the filename
+    {
+      fname=dirname_start;
+      //SERIAL_ECHOLN("remaider");
+      //SERIAL_ECHOLN(fname);
+      break;
+    }
+    
+  }
+ 
   if(read)
   {
-    if (file.open(&root, name, O_READ)) 
+    if (file.open(curDir, fname, O_READ)) 
     {
       filesize = file.fileSize();
       SERIAL_PROTOCOLPGM("File opened:");
-      SERIAL_PROTOCOL(name);
+      SERIAL_PROTOCOL(fname);
       SERIAL_PROTOCOLPGM(" Size:");
       SERIAL_PROTOCOLLN(filesize);
       sdpos = 0;
@@ -204,10 +247,10 @@ void CardReader::openFile(char* name,bool read)
   }
   else 
   { //write
-    if (!file.open(&root, name, O_CREAT | O_APPEND | O_WRITE | O_TRUNC))
+    if (!file.open(curDir, fname, O_CREAT | O_APPEND | O_WRITE | O_TRUNC))
     {
       SERIAL_PROTOCOLPGM("open failed, File: ");
-      SERIAL_PROTOCOL(name);
+      SERIAL_PROTOCOL(fname);
       SERIAL_PROTOCOLLNPGM(".");
     }
     else

From 70650c331da1fca53eafc5616dabdb4e9c4a6693 Mon Sep 17 00:00:00 2001
From: Bernhard Kubicek <kubicek@gmx.at>
Date: Sat, 19 Nov 2011 14:50:31 +0100
Subject: [PATCH 3/5] corrected the ultimaker default values, the previous had
 a calculation error: see:
 http://groups.google.com/group/ultimaker/browse_thread/thread/91906788639703cf

---
 Marlin/Configuration.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h
index 9bcddc8723..800bb9b32f 100644
--- a/Marlin/Configuration.h
+++ b/Marlin/Configuration.h
@@ -204,7 +204,7 @@ const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the
 
 // default settings 
 
-#define DEFAULT_AXIS_STEPS_PER_UNIT   {79.87220447,79.87220447,200*8/3,760*1.1}                    // default steps per unit for ultimaker 
+#define DEFAULT_AXIS_STEPS_PER_UNIT   {78.7402,78.7402,200*8/3,760*1.1}                    // default steps per unit for ultimaker 
 //#define DEFAULT_AXIS_STEPS_PER_UNIT   {40, 40, 3333.92, 67} 
 #define DEFAULT_MAX_FEEDRATE          {500, 500, 5, 200000}    // (mm/sec)    
 #define DEFAULT_MAX_ACCELERATION      {9000,9000,100,10000}    // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot.
@@ -274,7 +274,7 @@ const bool ENDSTOPS_INVERTING = true; // set to true to invert the logic of the
 
 #define ULTIPANEL
 #ifdef ULTIPANEL
-//  #define NEWPANEL  //enable this if you have a click-encoder panel
+  //#define NEWPANEL  //enable this if you have a click-encoder panel
   #define SDSUPPORT
   #define ULTRA_LCD
   #define LCD_WIDTH 20

From f0154de5b3d1fea9d9ca62265c739e039576249c Mon Sep 17 00:00:00 2001
From: Bernhard Kubicek <kubicek@gmx.at>
Date: Sat, 19 Nov 2011 15:36:49 +0100
Subject: [PATCH 4/5] found bug that disabled printing from root.

---
 Marlin/cardreader.pde | 64 +++++++++++++++++++++++--------------------
 1 file changed, 34 insertions(+), 30 deletions(-)

diff --git a/Marlin/cardreader.pde b/Marlin/cardreader.pde
index 4c869e4276..2771668a46 100644
--- a/Marlin/cardreader.pde
+++ b/Marlin/cardreader.pde
@@ -192,41 +192,43 @@ void CardReader::openFile(char* name,bool read)
   char *fname=name;
   
   char *dirname_start,*dirname_end;
-  dirname_start=strchr(name,'/')+1;
-  while(dirname_start!=NULL)
+  if(name[0]=='/')
   {
-    dirname_end=strchr(dirname_start,'/');
-    //SERIAL_ECHO("start:");SERIAL_ECHOLN((int)(dirname_start-name));
-    //SERIAL_ECHO("end  :");SERIAL_ECHOLN((int)(dirname_end-name));
-    if(dirname_end!=NULL && dirname_end>dirname_start)
+    dirname_start=strchr(name,'/')+1;
+    while(dirname_start>0)
     {
-      char subdirname[13];
-      strncpy(subdirname, dirname_start, dirname_end-dirname_start);
-      subdirname[dirname_end-dirname_start]=0;
-      SERIAL_ECHOLN(subdirname);
-      if(!myDir.open(curDir,subdirname,O_READ))
+      dirname_end=strchr(dirname_start,'/');
+      //SERIAL_ECHO("start:");SERIAL_ECHOLN((int)(dirname_start-name));
+      //SERIAL_ECHO("end  :");SERIAL_ECHOLN((int)(dirname_end-name));
+      if(dirname_end>0 && dirname_end>dirname_start)
       {
-        SERIAL_PROTOCOLPGM("open failed, File: ");
-        SERIAL_PROTOCOL(subdirname);
-        SERIAL_PROTOCOLLNPGM(".");
-        return;
+        char subdirname[13];
+        strncpy(subdirname, dirname_start, dirname_end-dirname_start);
+        subdirname[dirname_end-dirname_start]=0;
+        SERIAL_ECHOLN(subdirname);
+        if(!myDir.open(curDir,subdirname,O_READ))
+        {
+          SERIAL_PROTOCOLPGM("open failed, File: ");
+          SERIAL_PROTOCOL(subdirname);
+          SERIAL_PROTOCOLLNPGM(".");
+          return;
+        }
+        else
+          ;//SERIAL_ECHOLN("dive ok");
+          
+        curDir=&myDir; 
+        dirname_start=dirname_end+1;
       }
-      else
-        SERIAL_ECHOLN("dive ok");
-        
-      curDir=&myDir; 
-      dirname_start=dirname_end+1;
+      else // the reminder after all /fsa/fdsa/ is the filename
+      {
+        fname=dirname_start;
+        //SERIAL_ECHOLN("remaider");
+        //SERIAL_ECHOLN(fname);
+        break;
+      }
+      
     }
-    else // the reminder after all /fsa/fdsa/ is the filename
-    {
-      fname=dirname_start;
-      //SERIAL_ECHOLN("remaider");
-      //SERIAL_ECHOLN(fname);
-      break;
-    }
-    
   }
- 
   if(read)
   {
     if (file.open(curDir, fname, O_READ)) 
@@ -242,7 +244,9 @@ void CardReader::openFile(char* name,bool read)
     }
     else
     {
-      SERIAL_PROTOCOLLNPGM("file.open failed");
+     SERIAL_PROTOCOLPGM("open failed, File: ");
+      SERIAL_PROTOCOL(fname);
+      SERIAL_PROTOCOLLNPGM(".");
     }
   }
   else 

From 8a08b8e07e0bd84c1778eca7f3f32fafff5c3af5 Mon Sep 17 00:00:00 2001
From: Bernhard Kubicek <kubicek@gmx.at>
Date: Sat, 19 Nov 2011 15:37:10 +0100
Subject: [PATCH 5/5] trying to get autotemp to work.

---
 Marlin/Marlin.pde  | 10 ++++++++++
 Marlin/planner.cpp | 20 +++++++++++++-------
 Marlin/planner.h   |  8 +++++++-
 3 files changed, 30 insertions(+), 8 deletions(-)

diff --git a/Marlin/Marlin.pde b/Marlin/Marlin.pde
index 34d50e3c46..c0fc8675c1 100644
--- a/Marlin/Marlin.pde
+++ b/Marlin/Marlin.pde
@@ -695,7 +695,17 @@ inline void process_commands()
     case 109: 
     {// M109 - Wait for extruder heater to reach target.
         LCD_MESSAGEPGM("Heating...");
+        autotemp_enabled=false;
         if (code_seen('S')) setTargetHotend0(code_value());
+        #ifdef AUTOTEMP
+          if (code_seen('S')) autotemp_min=code_value();
+          if (code_seen('T')) autotemp_max=code_value();
+          if (code_seen('F')) 
+          {
+            autotemp_factor=code_value();
+            autotemp_enabled=true;
+          }
+        #endif
         
         setWatch();
         codenum = millis(); 
diff --git a/Marlin/planner.cpp b/Marlin/planner.cpp
index c27d586017..0a226c66f7 100644
--- a/Marlin/planner.cpp
+++ b/Marlin/planner.cpp
@@ -87,7 +87,10 @@ static float previous_speed[4]; // Speed of previous path line segment
 static float previous_nominal_speed; // Nominal speed of previous path line segment
 
 #ifdef AUTOTEMP
-float high_e_speed=0;
+    float autotemp_max=250;
+    float autotemp_min=210;
+    float autotemp_factor=1;
+    bool autotemp_enabled=false;
 #endif
 
 
@@ -379,26 +382,29 @@ block_t *plan_get_current_block() {
 #ifdef AUTOTEMP
 void getHighESpeed()
 {
-  if(degTargetHotend0()+2<AUTOTEMP_MIN)  //probably temperature set to zero.
+  if(!autotemp_enabled)
+    return;
+  if(degTargetHotend0()+2<autotemp_min)  //probably temperature set to zero.
     return; //do nothing
+  
   float high=0;
   char block_index = block_buffer_tail;
   
   while(block_index != block_buffer_head) {
-    float se=block_buffer[block_index].speed_e;
+    float se=block_buffer[block_index].steps_e/float(block_buffer[block_index].step_event_count)*block_buffer[block_index].nominal_rate;
+    //se; units steps/sec;
     if(se>high)
     {
       high=se;
     }
     block_index = (block_index+1) & (BLOCK_BUFFER_SIZE - 1);
   }
-  high_e_speed=high*axis_steps_per_unit[E_AXIS]/(1000000.0);  //so it is independent of the esteps/mm. before 
    
-  float g=AUTOTEMP_MIN+high_e_speed*AUTOTEMP_FACTOR;
-  float t=constrain(AUTOTEMP_MIN,g,AUTOTEMP_MAX);
+  float g=autotemp_min+high*autotemp_factor;
+  float t=constrain(autotemp_min,g,autotemp_max);
   setTargetHotend0(t);
   SERIAL_ECHO_START;
-  SERIAL_ECHOPAIR("highe",high_e_speed);
+  SERIAL_ECHOPAIR("highe",high);
   SERIAL_ECHOPAIR(" t",t);
   SERIAL_ECHOLN("");
 }
diff --git a/Marlin/planner.h b/Marlin/planner.h
index be1587d6b8..ec497d5064 100644
--- a/Marlin/planner.h
+++ b/Marlin/planner.h
@@ -92,7 +92,13 @@ extern float max_xy_jerk; //speed than can be stopped at once, if i understand c
 extern float max_z_jerk;
 extern float mintravelfeedrate;
 extern unsigned long axis_steps_per_sqr_second[NUM_AXIS];
+
+
 #ifdef AUTOTEMP
-extern float high_e_speed;
+    extern bool autotemp_enabled;
+    extern float autotemp_max;
+    extern float autotemp_min;
+    extern float autotemp_factor;
 #endif
+
 #endif