Repetier-Firmware 0.2
Repetier/SdFat.h
Go to the documentation of this file.
00001 /* Arduino SdFat Library
00002  * Copyright (C) 2009 by William Greiman
00003  *
00004  * This file is part of the Arduino SdFat Library
00005  *
00006  * This Library is free software: you can redistribute it and/or modify
00007  * it under the terms of the GNU General Public License as published by
00008  * the Free Software Foundation, either version 3 of the License, or
00009  * (at your option) any later version.
00010  *
00011  * This Library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with the Arduino SdFat Library.  If not, see
00018  * <http://www.gnu.org/licenses/>.
00019  */
00020 #ifndef SdFat_h
00021 #define SdFat_h
00022 
00026 #include <avr/pgmspace.h>
00027 #include "Sd2Card.h"
00028 #include "FatStructs.h"
00029 #include "Print.h"
00030 //------------------------------------------------------------------------------
00034 #define ALLOW_DEPRECATED_FUNCTIONS 1
00035 //------------------------------------------------------------------------------
00036 // forward declaration since SdVolume is used in SdFile
00037 class SdVolume;
00038 //==============================================================================
00039 // SdFile class
00040 
00041 // flags for ls()
00043 uint8_t const LS_DATE = 1;
00045 uint8_t const LS_SIZE = 2;
00047 uint8_t const LS_R = 4;
00048 
00049 // use the gnu style oflag in open()
00051 uint8_t const O_READ = 0X01;
00053 uint8_t const O_RDONLY = O_READ;
00055 uint8_t const O_WRITE = 0X02;
00057 uint8_t const O_WRONLY = O_WRITE;
00059 uint8_t const O_RDWR = (O_READ | O_WRITE);
00061 uint8_t const O_ACCMODE = (O_READ | O_WRITE);
00063 uint8_t const O_APPEND = 0X04;
00065 uint8_t const O_SYNC = 0X08;
00067 uint8_t const O_CREAT = 0X10;
00069 uint8_t const O_EXCL = 0X20;
00071 uint8_t const O_TRUNC = 0X40;
00072 
00073 // flags for timestamp
00075 uint8_t const T_ACCESS = 1;
00077 uint8_t const T_CREATE = 2;
00079 uint8_t const T_WRITE = 4;
00080 // values for type_
00082 uint8_t const FAT_FILE_TYPE_CLOSED = 0;
00084 uint8_t const FAT_FILE_TYPE_NORMAL = 1;
00086 uint8_t const FAT_FILE_TYPE_ROOT16 = 2;
00088 uint8_t const FAT_FILE_TYPE_ROOT32 = 3;
00090 uint8_t const FAT_FILE_TYPE_SUBDIR = 4;
00092 uint8_t const FAT_FILE_TYPE_MIN_DIR = FAT_FILE_TYPE_ROOT16;
00093 
00095 static inline uint16_t FAT_DATE(uint16_t year, uint8_t month, uint8_t day) {
00096   return (year - 1980) << 9 | month << 5 | day;
00097 }
00099 static inline uint16_t FAT_YEAR(uint16_t fatDate) {
00100   return 1980 + (fatDate >> 9);
00101 }
00103 static inline uint8_t FAT_MONTH(uint16_t fatDate) {
00104   return (fatDate >> 5) & 0XF;
00105 }
00107 static inline uint8_t FAT_DAY(uint16_t fatDate) {
00108   return fatDate & 0X1F;
00109 }
00111 static inline uint16_t FAT_TIME(uint8_t hour, uint8_t minute, uint8_t second) {
00112   return hour << 11 | minute << 5 | second >> 1;
00113 }
00115 static inline uint8_t FAT_HOUR(uint16_t fatTime) {
00116   return fatTime >> 11;
00117 }
00119 static inline uint8_t FAT_MINUTE(uint16_t fatTime) {
00120   return(fatTime >> 5) & 0X3F;
00121 }
00123 static inline uint8_t FAT_SECOND(uint16_t fatTime) {
00124   return 2*(fatTime & 0X1F);
00125 }
00127 uint16_t const FAT_DEFAULT_DATE = ((2000 - 1980) << 9) | (1 << 5) | 1;
00129 uint16_t const FAT_DEFAULT_TIME = (1 << 11);
00130 //------------------------------------------------------------------------------
00135 class SdFile : public Print {
00136  public:
00138   SdFile(void) : type_(FAT_FILE_TYPE_CLOSED) {}
00144   bool writeError;
00149   void clearUnbufferedRead(void) {
00150     flags_ &= ~F_FILE_UNBUFFERED_READ;
00151   }
00152   uint8_t close(void);
00153   uint8_t contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock);
00154   uint8_t createContiguous(SdFile* dirFile,
00155           const char* fileName, uint32_t size);
00157   uint32_t curCluster(void) const {return curCluster_;}
00159   uint32_t curPosition(void) const {return curPosition_;}
00188   static void dateTimeCallback(
00189     void (*dateTime)(uint16_t* date, uint16_t* time)) {
00190     dateTime_ = dateTime;
00191   }
00195   static void dateTimeCallbackCancel(void) {
00196     // use explicit zero since NULL is not defined for Sanguino
00197     dateTime_ = 0;
00198   }
00200   uint32_t dirBlock(void) const {return dirBlock_;}
00201   uint8_t dirEntry(dir_t* dir);
00203   uint8_t dirIndex(void) const {return dirIndex_;}
00204   static void dirName(const dir_t& dir, char* name);
00206   uint32_t fileSize(void) const {return fileSize_;}
00208   uint32_t firstCluster(void) const {return firstCluster_;}
00210   uint8_t isDir(void) const {return type_ >= FAT_FILE_TYPE_MIN_DIR;}
00212   uint8_t isFile(void) const {return type_ == FAT_FILE_TYPE_NORMAL;}
00214   uint8_t isOpen(void) const {return type_ != FAT_FILE_TYPE_CLOSED;}
00216   uint8_t isSubDir(void) const {return type_ == FAT_FILE_TYPE_SUBDIR;}
00218   uint8_t isRoot(void) const {
00219     return type_ == FAT_FILE_TYPE_ROOT16 || type_ == FAT_FILE_TYPE_ROOT32;
00220   }
00221   void ls(uint8_t flags = 0, uint8_t indent = 0);
00222   uint8_t makeDir(SdFile* dir, const char* dirName);
00223   uint8_t open(SdFile* dirFile, uint16_t index, uint8_t oflag);
00224   uint8_t open(SdFile* dirFile, const char* fileName, uint8_t oflag);
00225 
00226   uint8_t openRoot(SdVolume* vol);
00227   static void printDirName(const dir_t& dir, uint8_t width);
00228   static void printFatDate(uint16_t fatDate);
00229   static void printFatTime(uint16_t fatTime);
00230   static void printTwoDigits(uint8_t v);
00237   int16_t read(void) {
00238     uint8_t b;
00239     return read(&b, 1) == 1 ? b : -1;
00240   }
00241   int16_t read(void* buf, uint16_t nbyte);
00242   int8_t readDir(dir_t* dir);
00243   static uint8_t remove(SdFile* dirFile, const char* fileName);
00244   uint8_t remove(void);
00246   void rewind(void) {
00247     curPosition_ = curCluster_ = 0;
00248   }
00249   uint8_t rmDir(void);
00250   uint8_t rmRfStar(void);
00252   uint8_t seekCur(uint32_t pos) {
00253     return seekSet(curPosition_ + pos);
00254   }
00259   uint8_t seekEnd(void) {return seekSet(fileSize_);}
00260   uint8_t seekSet(uint32_t pos);
00267   void setUnbufferedRead(void) {
00268     if (isFile()) flags_ |= F_FILE_UNBUFFERED_READ;
00269   }
00270   uint8_t timestamp(uint8_t flag, uint16_t year, uint8_t month, uint8_t day,
00271           uint8_t hour, uint8_t minute, uint8_t second);
00272   uint8_t sync(void);
00278   uint8_t type(void) const {return type_;}
00279   uint8_t truncate(uint32_t size);
00281   uint8_t unbufferedRead(void) const {
00282     return flags_ & F_FILE_UNBUFFERED_READ;
00283   }
00285   SdVolume* volume(void) const {return vol_;}
00286   void write(uint8_t b);
00287   int16_t write(const void* buf, uint16_t nbyte);
00288   void write(const char* str);
00289   void write_P(PGM_P str);
00290   void writeln_P(PGM_P str);
00291 //------------------------------------------------------------------------------
00292 #if ALLOW_DEPRECATED_FUNCTIONS
00293 // Deprecated functions  - suppress cpplint warnings with NOLINT comment
00297   uint8_t contiguousRange(uint32_t& bgnBlock, uint32_t& endBlock) {  // NOLINT
00298     return contiguousRange(&bgnBlock, &endBlock);
00299   }
00304   uint8_t createContiguous(SdFile& dirFile,  // NOLINT
00305     const char* fileName, uint32_t size) {
00306     return createContiguous(&dirFile, fileName, size);
00307   }
00308 
00314   static void dateTimeCallback(
00315     void (*dateTime)(uint16_t& date, uint16_t& time)) {  // NOLINT
00316     oldDateTime_ = dateTime;
00317     dateTime_ = dateTime ? oldToNew : 0;
00318   }
00320   uint8_t dirEntry(dir_t& dir) {return dirEntry(&dir);}  // NOLINT
00324   uint8_t makeDir(SdFile& dir, const char* dirName) {  // NOLINT
00325     return makeDir(&dir, dirName);
00326   }
00330   uint8_t open(SdFile& dirFile, // NOLINT
00331     const char* fileName, uint8_t oflag) {
00332     return open(&dirFile, fileName, oflag);
00333   }
00335   uint8_t open(SdFile& dirFile, const char* fileName) {  // NOLINT
00336     return open(dirFile, fileName, O_RDWR);
00337   }
00341   uint8_t open(SdFile& dirFile, uint16_t index, uint8_t oflag) {  // NOLINT
00342     return open(&dirFile, index, oflag);
00343   }
00345   uint8_t openRoot(SdVolume& vol) {return openRoot(&vol);}  // NOLINT
00346 
00348   int8_t readDir(dir_t& dir) {return readDir(&dir);}  // NOLINT
00352   static uint8_t remove(SdFile& dirFile, const char* fileName) {  // NOLINT
00353     return remove(&dirFile, fileName);
00354   }
00355 //------------------------------------------------------------------------------
00356 // rest are private
00357  private:
00358   static void (*oldDateTime_)(uint16_t& date, uint16_t& time);  // NOLINT
00359   static void oldToNew(uint16_t* date, uint16_t* time) {
00360     uint16_t d;
00361     uint16_t t;
00362     oldDateTime_(d, t);
00363     *date = d;
00364     *time = t;
00365   }
00366 #endif  // ALLOW_DEPRECATED_FUNCTIONS
00367  private:
00368   // bits defined in flags_
00369   // should be 0XF
00370   static uint8_t const F_OFLAG = (O_ACCMODE | O_APPEND | O_SYNC);
00371   // available bits
00372   static uint8_t const F_UNUSED = 0X30;
00373   // use unbuffered SD read
00374   static uint8_t const F_FILE_UNBUFFERED_READ = 0X40;
00375   // sync of directory entry required
00376   static uint8_t const F_FILE_DIR_DIRTY = 0X80;
00377 
00378 // make sure F_OFLAG is ok
00379 #if ((F_UNUSED | F_FILE_UNBUFFERED_READ | F_FILE_DIR_DIRTY) & F_OFLAG)
00380 #error flags_ bits conflict
00381 #endif  // flags_ bits
00382 
00383   // private data
00384   uint8_t   flags_;         // See above for definition of flags_ bits
00385   uint8_t   type_;          // type of file see above for values
00386   uint32_t  curCluster_;    // cluster for current file position
00387   uint32_t  curPosition_;   // current file position in bytes from beginning
00388   uint32_t  dirBlock_;      // SD block that contains directory entry for file
00389   uint8_t   dirIndex_;      // index of entry in dirBlock 0 <= dirIndex_ <= 0XF
00390   uint32_t  fileSize_;      // file size in bytes
00391   uint32_t  firstCluster_;  // first cluster of file
00392   SdVolume* vol_;           // volume where file is located
00393 
00394   // private functions
00395   uint8_t addCluster(void);
00396   uint8_t addDirCluster(void);
00397   dir_t* cacheDirEntry(uint8_t action);
00398   static void (*dateTime_)(uint16_t* date, uint16_t* time);
00399   static uint8_t make83Name(const char* str, uint8_t* name);
00400   uint8_t openCachedEntry(uint8_t cacheIndex, uint8_t oflags);
00401   dir_t* readDirCache(void);
00402 };
00403 //==============================================================================
00404 // SdVolume class
00408 union cache_t {
00410   uint8_t  data[512];
00412   uint16_t fat16[256];
00414   uint32_t fat32[128];
00416   dir_t    dir[16];
00418   mbr_t    mbr;
00420   fbs_t    fbs;
00421 };
00422 //------------------------------------------------------------------------------
00427 class SdVolume {
00428  public:
00430   SdVolume(void) :allocSearchStart_(2), fatType_(0) {}
00434   static uint8_t* cacheClear(void) {
00435     cacheFlush();
00436     cacheBlockNumber_ = 0XFFFFFFFF;
00437     return cacheBuffer_.data;
00438   }
00450   uint8_t init(Sd2Card* dev) { return init(dev, 1) ? true : init(dev, 0);}
00451   uint8_t init(Sd2Card* dev, uint8_t part);
00452 
00453   // inline functions that return volume info
00455   uint8_t blocksPerCluster(void) const {return blocksPerCluster_;}
00457   uint32_t blocksPerFat(void)  const {return blocksPerFat_;}
00459   uint32_t clusterCount(void) const {return clusterCount_;}
00461   uint8_t clusterSizeShift(void) const {return clusterSizeShift_;}
00463   uint32_t dataStartBlock(void) const {return dataStartBlock_;}
00465   uint8_t fatCount(void) const {return fatCount_;}
00467   uint32_t fatStartBlock(void) const {return fatStartBlock_;}
00469   uint8_t fatType(void) const {return fatType_;}
00471   uint32_t rootDirEntryCount(void) const {return rootDirEntryCount_;}
00474   uint32_t rootDirStart(void) const {return rootDirStart_;}
00476   static Sd2Card* sdCard(void) {return sdCard_;}
00477 //------------------------------------------------------------------------------
00478 #if ALLOW_DEPRECATED_FUNCTIONS
00479   // Deprecated functions  - suppress cpplint warnings with NOLINT comment
00481   uint8_t init(Sd2Card& dev) {return init(&dev);}  // NOLINT
00482 
00484   uint8_t init(Sd2Card& dev, uint8_t part) {  // NOLINT
00485     return init(&dev, part);
00486   }
00487 #endif  // ALLOW_DEPRECATED_FUNCTIONS
00488 //------------------------------------------------------------------------------
00489   private:
00490   // Allow SdFile access to SdVolume private data.
00491   friend class SdFile;
00492 
00493   // value for action argument in cacheRawBlock to indicate read from cache
00494   static uint8_t const CACHE_FOR_READ = 0;
00495   // value for action argument in cacheRawBlock to indicate cache dirty
00496   static uint8_t const CACHE_FOR_WRITE = 1;
00497 
00498   static cache_t cacheBuffer_;        // 512 byte cache for device blocks
00499   static uint32_t cacheBlockNumber_;  // Logical number of block in the cache
00500   static Sd2Card* sdCard_;            // Sd2Card object for cache
00501   static uint8_t cacheDirty_;         // cacheFlush() will write block if true
00502   static uint32_t cacheMirrorBlock_;  // block number for mirror FAT
00503 //
00504   uint32_t allocSearchStart_;   // start cluster for alloc search
00505   uint8_t blocksPerCluster_;    // cluster size in blocks
00506   uint32_t blocksPerFat_;       // FAT size in blocks
00507   uint32_t clusterCount_;       // clusters in one FAT
00508   uint8_t clusterSizeShift_;    // shift to convert cluster count to block count
00509   uint32_t dataStartBlock_;     // first data block number
00510   uint8_t fatCount_;            // number of FATs on volume
00511   uint32_t fatStartBlock_;      // start block for first FAT
00512   uint8_t fatType_;             // volume type (12, 16, OR 32)
00513   uint16_t rootDirEntryCount_;  // number of entries in FAT16 root dir
00514   uint32_t rootDirStart_;       // root start block for FAT16, cluster for FAT32
00515   //----------------------------------------------------------------------------
00516   uint8_t allocContiguous(uint32_t count, uint32_t* curCluster);
00517   uint8_t blockOfCluster(uint32_t position) const {
00518           return (position >> 9) & (blocksPerCluster_ - 1);}
00519   uint32_t clusterStartBlock(uint32_t cluster) const {
00520            return dataStartBlock_ + ((cluster - 2) << clusterSizeShift_);}
00521   uint32_t blockNumber(uint32_t cluster, uint32_t position) const {
00522            return clusterStartBlock(cluster) + blockOfCluster(position);}
00523   static uint8_t cacheFlush(void);
00524   static uint8_t cacheRawBlock(uint32_t blockNumber, uint8_t action);
00525   static void cacheSetDirty(void) {cacheDirty_ |= CACHE_FOR_WRITE;}
00526   static uint8_t cacheZeroBlock(uint32_t blockNumber);
00527   uint8_t chainSize(uint32_t beginCluster, uint32_t* size) const;
00528   uint8_t fatGet(uint32_t cluster, uint32_t* value) const;
00529   uint8_t fatPut(uint32_t cluster, uint32_t value);
00530   uint8_t fatPutEOC(uint32_t cluster) {
00531     return fatPut(cluster, 0x0FFFFFFF);
00532   }
00533   uint8_t freeChain(uint32_t cluster);
00534   uint8_t isEOC(uint32_t cluster) const {
00535     return  cluster >= (fatType_ == 16 ? FAT16EOC_MIN : FAT32EOC_MIN);
00536   }
00537   uint8_t readBlock(uint32_t block, uint8_t* dst) {
00538     return sdCard_->readBlock(block, dst);}
00539   uint8_t readData(uint32_t block, uint16_t offset,
00540     uint16_t count, uint8_t* dst) {
00541       return sdCard_->readData(block, offset, count, dst);
00542   }
00543   uint8_t writeBlock(uint32_t block, const uint8_t* dst) {
00544     return sdCard_->writeBlock(block, dst);
00545   }
00546 };
00547 #endif  // SdFat_h
 All Data Structures Files Functions Variables Typedefs Friends Defines