From 70abca195abfbb1a8ecf7eba8e27f61ba7eee759 Mon Sep 17 00:00:00 2001 From: Bernhard Kubicek Date: Sat, 19 Nov 2011 13:13:34 +0100 Subject: [PATCH] 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 8dc8d0822..34d50e3c4 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 494fd4822..000000000 --- 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 - * . - */ -#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 \: 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 1a184d084..000000000 --- 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 - * . - */ -#ifndef SdFat_h -#define SdFat_h -/** - * \file - * \brief SdFat class - */ -#include "SdFile.h" -//#include -//#include -//------------------------------------------------------------------------------ -/** 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 04076bfda..d96715807 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 605af11bf..77a8f692b 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