SdFat.h 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552
  1. /* Arduino SdFat Library
  2. * Copyright (C) 2009 by William Greiman
  3. *
  4. * This file is part of the Arduino SdFat Library
  5. *
  6. * This Library is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This Library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with the Arduino SdFat Library. If not, see
  18. * <http://www.gnu.org/licenses/>.
  19. */
  20. #ifndef SdFat_h
  21. #define SdFat_h
  22. /**
  23. * \file
  24. * SdFile and SdVolume classes
  25. */
  26. #include <avr/pgmspace.h>
  27. #include "Sd2Card.h"
  28. #include "FatStructs.h"
  29. #include "Print.h"
  30. //------------------------------------------------------------------------------
  31. /**
  32. * Allow use of deprecated functions if non-zero
  33. */
  34. #define ALLOW_DEPRECATED_FUNCTIONS 1
  35. //------------------------------------------------------------------------------
  36. // forward declaration since SdVolume is used in SdFile
  37. class SdVolume;
  38. //==============================================================================
  39. // SdFile class
  40. // flags for ls()
  41. /** ls() flag to print modify date */
  42. uint8_t const LS_DATE = 1;
  43. /** ls() flag to print file size */
  44. uint8_t const LS_SIZE = 2;
  45. /** ls() flag for recursive list of subdirectories */
  46. uint8_t const LS_R = 4;
  47. // use the gnu style oflag in open()
  48. /** open() oflag for reading */
  49. uint8_t const O_READ = 0X01;
  50. /** open() oflag - same as O_READ */
  51. uint8_t const O_RDONLY = O_READ;
  52. /** open() oflag for write */
  53. uint8_t const O_WRITE = 0X02;
  54. /** open() oflag - same as O_WRITE */
  55. uint8_t const O_WRONLY = O_WRITE;
  56. /** open() oflag for reading and writing */
  57. uint8_t const O_RDWR = (O_READ | O_WRITE);
  58. /** open() oflag mask for access modes */
  59. uint8_t const O_ACCMODE = (O_READ | O_WRITE);
  60. /** The file offset shall be set to the end of the file prior to each write. */
  61. uint8_t const O_APPEND = 0X04;
  62. /** synchronous writes - call sync() after each write */
  63. uint8_t const O_SYNC = 0X08;
  64. /** create the file if nonexistent */
  65. uint8_t const O_CREAT = 0X10;
  66. /** If O_CREAT and O_EXCL are set, open() shall fail if the file exists */
  67. uint8_t const O_EXCL = 0X20;
  68. /** truncate the file to zero length */
  69. uint8_t const O_TRUNC = 0X40;
  70. // flags for timestamp
  71. /** set the file's last access date */
  72. uint8_t const T_ACCESS = 1;
  73. /** set the file's creation date and time */
  74. uint8_t const T_CREATE = 2;
  75. /** Set the file's write date and time */
  76. uint8_t const T_WRITE = 4;
  77. // values for type_
  78. /** This SdFile has not been opened. */
  79. uint8_t const FAT_FILE_TYPE_CLOSED = 0;
  80. /** SdFile for a file */
  81. uint8_t const FAT_FILE_TYPE_NORMAL = 1;
  82. /** SdFile for a FAT16 root directory */
  83. uint8_t const FAT_FILE_TYPE_ROOT16 = 2;
  84. /** SdFile for a FAT32 root directory */
  85. uint8_t const FAT_FILE_TYPE_ROOT32 = 3;
  86. /** SdFile for a subdirectory */
  87. uint8_t const FAT_FILE_TYPE_SUBDIR = 4;
  88. /** Test value for directory type */
  89. uint8_t const FAT_FILE_TYPE_MIN_DIR = FAT_FILE_TYPE_ROOT16;
  90. /** date field for FAT directory entry */
  91. static inline uint16_t FAT_DATE(uint16_t year, uint8_t month, uint8_t day) {
  92. return (year - 1980) << 9 | month << 5 | day;
  93. }
  94. /** year part of FAT directory date field */
  95. static inline uint16_t FAT_YEAR(uint16_t fatDate) {
  96. return 1980 + (fatDate >> 9);
  97. }
  98. /** month part of FAT directory date field */
  99. static inline uint8_t FAT_MONTH(uint16_t fatDate) {
  100. return (fatDate >> 5) & 0XF;
  101. }
  102. /** day part of FAT directory date field */
  103. static inline uint8_t FAT_DAY(uint16_t fatDate) {
  104. return fatDate & 0X1F;
  105. }
  106. /** time field for FAT directory entry */
  107. static inline uint16_t FAT_TIME(uint8_t hour, uint8_t minute, uint8_t second) {
  108. return hour << 11 | minute << 5 | second >> 1;
  109. }
  110. /** hour part of FAT directory time field */
  111. static inline uint8_t FAT_HOUR(uint16_t fatTime) {
  112. return fatTime >> 11;
  113. }
  114. /** minute part of FAT directory time field */
  115. static inline uint8_t FAT_MINUTE(uint16_t fatTime) {
  116. return(fatTime >> 5) & 0X3F;
  117. }
  118. /** second part of FAT directory time field */
  119. static inline uint8_t FAT_SECOND(uint16_t fatTime) {
  120. return 2*(fatTime & 0X1F);
  121. }
  122. /** Default date for file timestamps is 1 Jan 2000 */
  123. uint16_t const FAT_DEFAULT_DATE = ((2000 - 1980) << 9) | (1 << 5) | 1;
  124. /** Default time for file timestamp is 1 am */
  125. uint16_t const FAT_DEFAULT_TIME = (1 << 11);
  126. //------------------------------------------------------------------------------
  127. /**
  128. * \class SdFile
  129. * \brief Access FAT16 and FAT32 files on SD and SDHC cards.
  130. */
  131. class SdFile : public Print {
  132. public:
  133. /** Create an instance of SdFile. */
  134. SdFile(void) : type_(FAT_FILE_TYPE_CLOSED) {}
  135. /**
  136. * writeError is set to true if an error occurs during a write().
  137. * Set writeError to false before calling print() and/or write() and check
  138. * for true after calls to print() and/or write().
  139. */
  140. bool writeError;
  141. /**
  142. * Cancel unbuffered reads for this file.
  143. * See setUnbufferedRead()
  144. */
  145. void clearUnbufferedRead(void) {
  146. flags_ &= ~F_FILE_UNBUFFERED_READ;
  147. }
  148. uint8_t close(void);
  149. uint8_t contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock);
  150. uint8_t createContiguous(SdFile* dirFile,
  151. const char* fileName, uint32_t size);
  152. /** \return The current cluster number for a file or directory. */
  153. uint32_t curCluster(void) const {return curCluster_;}
  154. /** \return The current position for a file or directory. */
  155. uint32_t curPosition(void) const {return curPosition_;}
  156. /**
  157. * Set the date/time callback function
  158. *
  159. * \param[in] dateTime The user's call back function. The callback
  160. * function is of the form:
  161. *
  162. * \code
  163. * void dateTime(uint16_t* date, uint16_t* time) {
  164. * uint16_t year;
  165. * uint8_t month, day, hour, minute, second;
  166. *
  167. * // User gets date and time from GPS or real-time clock here
  168. *
  169. * // return date using FAT_DATE macro to format fields
  170. * *date = FAT_DATE(year, month, day);
  171. *
  172. * // return time using FAT_TIME macro to format fields
  173. * *time = FAT_TIME(hour, minute, second);
  174. * }
  175. * \endcode
  176. *
  177. * Sets the function that is called when a file is created or when
  178. * a file's directory entry is modified by sync(). All timestamps,
  179. * access, creation, and modify, are set when a file is created.
  180. * sync() maintains the last access date and last modify date/time.
  181. *
  182. * See the timestamp() function.
  183. */
  184. static void dateTimeCallback(
  185. void (*dateTime)(uint16_t* date, uint16_t* time)) {
  186. dateTime_ = dateTime;
  187. }
  188. /**
  189. * Cancel the date/time callback function.
  190. */
  191. static void dateTimeCallbackCancel(void) {
  192. // use explicit zero since NULL is not defined for Sanguino
  193. dateTime_ = 0;
  194. }
  195. /** \return Address of the block that contains this file's directory. */
  196. uint32_t dirBlock(void) const {return dirBlock_;}
  197. uint8_t dirEntry(dir_t* dir);
  198. /** \return Index of this file's directory in the block dirBlock. */
  199. uint8_t dirIndex(void) const {return dirIndex_;}
  200. static void dirName(const dir_t& dir, char* name);
  201. /** \return The total number of bytes in a file or directory. */
  202. uint32_t fileSize(void) const {return fileSize_;}
  203. /** \return The first cluster number for a file or directory. */
  204. uint32_t firstCluster(void) const {return firstCluster_;}
  205. /** \return True if this is a SdFile for a directory else false. */
  206. uint8_t isDir(void) const {return type_ >= FAT_FILE_TYPE_MIN_DIR;}
  207. /** \return True if this is a SdFile for a file else false. */
  208. uint8_t isFile(void) const {return type_ == FAT_FILE_TYPE_NORMAL;}
  209. /** \return True if this is a SdFile for an open file/directory else false. */
  210. uint8_t isOpen(void) const {return type_ != FAT_FILE_TYPE_CLOSED;}
  211. /** \return True if this is a SdFile for a subdirectory else false. */
  212. uint8_t isSubDir(void) const {return type_ == FAT_FILE_TYPE_SUBDIR;}
  213. /** \return True if this is a SdFile for the root directory. */
  214. uint8_t isRoot(void) const {
  215. return type_ == FAT_FILE_TYPE_ROOT16 || type_ == FAT_FILE_TYPE_ROOT32;
  216. }
  217. void ls(uint8_t flags = 0, uint8_t indent = 0);
  218. uint8_t makeDir(SdFile* dir, const char* dirName);
  219. uint8_t open(SdFile* dirFile, uint16_t index, uint8_t oflag);
  220. uint8_t open(SdFile* dirFile, const char* fileName, uint8_t oflag);
  221. uint8_t openRoot(SdVolume* vol);
  222. static void printDirName(const dir_t& dir, uint8_t width);
  223. static void printFatDate(uint16_t fatDate);
  224. static void printFatTime(uint16_t fatTime);
  225. static void printTwoDigits(uint8_t v);
  226. /**
  227. * Read the next byte from a file.
  228. *
  229. * \return For success read returns the next byte in the file as an int.
  230. * If an error occurs or end of file is reached -1 is returned.
  231. */
  232. int16_t read(void) {
  233. uint8_t b;
  234. return read(&b, 1) == 1 ? b : -1;
  235. }
  236. int16_t read(void* buf, uint16_t nbyte);
  237. int8_t readDir(dir_t* dir);
  238. static uint8_t remove(SdFile* dirFile, const char* fileName);
  239. uint8_t remove(void);
  240. /** Set the file's current position to zero. */
  241. void rewind(void) {
  242. curPosition_ = curCluster_ = 0;
  243. }
  244. uint8_t rmDir(void);
  245. uint8_t rmRfStar(void);
  246. /** Set the files position to current position + \a pos. See seekSet(). */
  247. uint8_t seekCur(uint32_t pos) {
  248. return seekSet(curPosition_ + pos);
  249. }
  250. /**
  251. * Set the files current position to end of file. Useful to position
  252. * a file for append. See seekSet().
  253. */
  254. uint8_t seekEnd(void) {return seekSet(fileSize_);}
  255. uint8_t seekSet(uint32_t pos);
  256. /**
  257. * Use unbuffered reads to access this file. Used with Wave
  258. * Shield ISR. Used with Sd2Card::partialBlockRead() in WaveRP.
  259. *
  260. * Not recommended for normal applications.
  261. */
  262. void setUnbufferedRead(void) {
  263. if (isFile()) flags_ |= F_FILE_UNBUFFERED_READ;
  264. }
  265. uint8_t timestamp(uint8_t flag, uint16_t year, uint8_t month, uint8_t day,
  266. uint8_t hour, uint8_t minute, uint8_t second);
  267. uint8_t sync(void);
  268. /** Type of this SdFile. You should use isFile() or isDir() instead of type()
  269. * if possible.
  270. *
  271. * \return The file or directory type.
  272. */
  273. uint8_t type(void) const {return type_;}
  274. uint8_t truncate(uint32_t size);
  275. /** \return Unbuffered read flag. */
  276. uint8_t unbufferedRead(void) const {
  277. return flags_ & F_FILE_UNBUFFERED_READ;
  278. }
  279. /** \return SdVolume that contains this file. */
  280. SdVolume* volume(void) const {return vol_;}
  281. #if ARDUINO >= 100
  282. size_t write(uint8_t b);
  283. #else
  284. void write(uint8_t b);
  285. #endif
  286. int16_t write(const void* buf, uint16_t nbyte);
  287. void write(const char* str);
  288. void write_P(PGM_P str);
  289. void writeln_P(PGM_P str);
  290. //------------------------------------------------------------------------------
  291. #if ALLOW_DEPRECATED_FUNCTIONS
  292. // Deprecated functions - suppress cpplint warnings with NOLINT comment
  293. /** \deprecated Use:
  294. * uint8_t SdFile::contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock);
  295. */
  296. uint8_t contiguousRange(uint32_t& bgnBlock, uint32_t& endBlock) { // NOLINT
  297. return contiguousRange(&bgnBlock, &endBlock);
  298. }
  299. /** \deprecated Use:
  300. * uint8_t SdFile::createContiguous(SdFile* dirFile,
  301. * const char* fileName, uint32_t size)
  302. */
  303. uint8_t createContiguous(SdFile& dirFile, // NOLINT
  304. const char* fileName, uint32_t size) {
  305. return createContiguous(&dirFile, fileName, size);
  306. }
  307. /**
  308. * \deprecated Use:
  309. * static void SdFile::dateTimeCallback(
  310. * void (*dateTime)(uint16_t* date, uint16_t* time));
  311. */
  312. static void dateTimeCallback(
  313. void (*dateTime)(uint16_t& date, uint16_t& time)) { // NOLINT
  314. oldDateTime_ = dateTime;
  315. dateTime_ = dateTime ? oldToNew : 0;
  316. }
  317. /** \deprecated Use: uint8_t SdFile::dirEntry(dir_t* dir); */
  318. uint8_t dirEntry(dir_t& dir) {return dirEntry(&dir);} // NOLINT
  319. /** \deprecated Use:
  320. * uint8_t SdFile::makeDir(SdFile* dir, const char* dirName);
  321. */
  322. uint8_t makeDir(SdFile& dir, const char* dirName) { // NOLINT
  323. return makeDir(&dir, dirName);
  324. }
  325. /** \deprecated Use:
  326. * uint8_t SdFile::open(SdFile* dirFile, const char* fileName, uint8_t oflag);
  327. */
  328. uint8_t open(SdFile& dirFile, // NOLINT
  329. const char* fileName, uint8_t oflag) {
  330. return open(&dirFile, fileName, oflag);
  331. }
  332. /** \deprecated Do not use in new apps */
  333. uint8_t open(SdFile& dirFile, const char* fileName) { // NOLINT
  334. return open(dirFile, fileName, O_RDWR);
  335. }
  336. /** \deprecated Use:
  337. * uint8_t SdFile::open(SdFile* dirFile, uint16_t index, uint8_t oflag);
  338. */
  339. uint8_t open(SdFile& dirFile, uint16_t index, uint8_t oflag) { // NOLINT
  340. return open(&dirFile, index, oflag);
  341. }
  342. /** \deprecated Use: uint8_t SdFile::openRoot(SdVolume* vol); */
  343. uint8_t openRoot(SdVolume& vol) {return openRoot(&vol);} // NOLINT
  344. /** \deprecated Use: int8_t SdFile::readDir(dir_t* dir); */
  345. int8_t readDir(dir_t& dir) {return readDir(&dir);} // NOLINT
  346. /** \deprecated Use:
  347. * static uint8_t SdFile::remove(SdFile* dirFile, const char* fileName);
  348. */
  349. static uint8_t remove(SdFile& dirFile, const char* fileName) { // NOLINT
  350. return remove(&dirFile, fileName);
  351. }
  352. //------------------------------------------------------------------------------
  353. // rest are private
  354. private:
  355. static void (*oldDateTime_)(uint16_t& date, uint16_t& time); // NOLINT
  356. static void oldToNew(uint16_t* date, uint16_t* time) {
  357. uint16_t d;
  358. uint16_t t;
  359. oldDateTime_(d, t);
  360. *date = d;
  361. *time = t;
  362. }
  363. #endif // ALLOW_DEPRECATED_FUNCTIONS
  364. private:
  365. // bits defined in flags_
  366. // should be 0XF
  367. static uint8_t const F_OFLAG = (O_ACCMODE | O_APPEND | O_SYNC);
  368. // available bits
  369. static uint8_t const F_UNUSED = 0X30;
  370. // use unbuffered SD read
  371. static uint8_t const F_FILE_UNBUFFERED_READ = 0X40;
  372. // sync of directory entry required
  373. static uint8_t const F_FILE_DIR_DIRTY = 0X80;
  374. // make sure F_OFLAG is ok
  375. #if ((F_UNUSED | F_FILE_UNBUFFERED_READ | F_FILE_DIR_DIRTY) & F_OFLAG)
  376. #error flags_ bits conflict
  377. #endif // flags_ bits
  378. // private data
  379. uint8_t flags_; // See above for definition of flags_ bits
  380. uint8_t type_; // type of file see above for values
  381. uint32_t curCluster_; // cluster for current file position
  382. uint32_t curPosition_; // current file position in bytes from beginning
  383. uint32_t dirBlock_; // SD block that contains directory entry for file
  384. uint8_t dirIndex_; // index of entry in dirBlock 0 <= dirIndex_ <= 0XF
  385. uint32_t fileSize_; // file size in bytes
  386. uint32_t firstCluster_; // first cluster of file
  387. SdVolume* vol_; // volume where file is located
  388. // private functions
  389. uint8_t addCluster(void);
  390. uint8_t addDirCluster(void);
  391. dir_t* cacheDirEntry(uint8_t action);
  392. static void (*dateTime_)(uint16_t* date, uint16_t* time);
  393. static uint8_t make83Name(const char* str, uint8_t* name);
  394. uint8_t openCachedEntry(uint8_t cacheIndex, uint8_t oflags);
  395. dir_t* readDirCache(void);
  396. };
  397. //==============================================================================
  398. // SdVolume class
  399. /**
  400. * \brief Cache for an SD data block
  401. */
  402. union cache_t {
  403. /** Used to access cached file data blocks. */
  404. uint8_t data[512];
  405. /** Used to access cached FAT16 entries. */
  406. uint16_t fat16[256];
  407. /** Used to access cached FAT32 entries. */
  408. uint32_t fat32[128];
  409. /** Used to access cached directory entries. */
  410. dir_t dir[16];
  411. /** Used to access a cached MasterBoot Record. */
  412. mbr_t mbr;
  413. /** Used to access to a cached FAT boot sector. */
  414. fbs_t fbs;
  415. };
  416. //------------------------------------------------------------------------------
  417. /**
  418. * \class SdVolume
  419. * \brief Access FAT16 and FAT32 volumes on SD and SDHC cards.
  420. */
  421. class SdVolume {
  422. public:
  423. /** Create an instance of SdVolume */
  424. SdVolume(void) :allocSearchStart_(2), fatType_(0) {}
  425. /** Clear the cache and returns a pointer to the cache. Used by the WaveRP
  426. * recorder to do raw write to the SD card. Not for normal apps.
  427. */
  428. static uint8_t* cacheClear(void) {
  429. cacheFlush();
  430. cacheBlockNumber_ = 0XFFFFFFFF;
  431. return cacheBuffer_.data;
  432. }
  433. /**
  434. * Initialize a FAT volume. Try partition one first then try super
  435. * floppy format.
  436. *
  437. * \param[in] dev The Sd2Card where the volume is located.
  438. *
  439. * \return The value one, true, is returned for success and
  440. * the value zero, false, is returned for failure. Reasons for
  441. * failure include not finding a valid partition, not finding a valid
  442. * FAT file system or an I/O error.
  443. */
  444. uint8_t init(Sd2Card* dev) { return init(dev, 1) ? true : init(dev, 0);}
  445. uint8_t init(Sd2Card* dev, uint8_t part);
  446. // inline functions that return volume info
  447. /** \return The volume's cluster size in blocks. */
  448. uint8_t blocksPerCluster(void) const {return blocksPerCluster_;}
  449. /** \return The number of blocks in one FAT. */
  450. uint32_t blocksPerFat(void) const {return blocksPerFat_;}
  451. /** \return The total number of clusters in the volume. */
  452. uint32_t clusterCount(void) const {return clusterCount_;}
  453. /** \return The shift count required to multiply by blocksPerCluster. */
  454. uint8_t clusterSizeShift(void) const {return clusterSizeShift_;}
  455. /** \return The logical block number for the start of file data. */
  456. uint32_t dataStartBlock(void) const {return dataStartBlock_;}
  457. /** \return The number of FAT structures on the volume. */
  458. uint8_t fatCount(void) const {return fatCount_;}
  459. /** \return The logical block number for the start of the first FAT. */
  460. uint32_t fatStartBlock(void) const {return fatStartBlock_;}
  461. /** \return The FAT type of the volume. Values are 12, 16 or 32. */
  462. uint8_t fatType(void) const {return fatType_;}
  463. /** \return The number of entries in the root directory for FAT16 volumes. */
  464. uint32_t rootDirEntryCount(void) const {return rootDirEntryCount_;}
  465. /** \return The logical block number for the start of the root directory
  466. on FAT16 volumes or the first cluster number on FAT32 volumes. */
  467. uint32_t rootDirStart(void) const {return rootDirStart_;}
  468. /** return a pointer to the Sd2Card object for this volume */
  469. static Sd2Card* sdCard(void) {return sdCard_;}
  470. //------------------------------------------------------------------------------
  471. #if ALLOW_DEPRECATED_FUNCTIONS
  472. // Deprecated functions - suppress cpplint warnings with NOLINT comment
  473. /** \deprecated Use: uint8_t SdVolume::init(Sd2Card* dev); */
  474. uint8_t init(Sd2Card& dev) {return init(&dev);} // NOLINT
  475. /** \deprecated Use: uint8_t SdVolume::init(Sd2Card* dev, uint8_t vol); */
  476. uint8_t init(Sd2Card& dev, uint8_t part) { // NOLINT
  477. return init(&dev, part);
  478. }
  479. #endif // ALLOW_DEPRECATED_FUNCTIONS
  480. //------------------------------------------------------------------------------
  481. private:
  482. // Allow SdFile access to SdVolume private data.
  483. friend class SdFile;
  484. // value for action argument in cacheRawBlock to indicate read from cache
  485. static uint8_t const CACHE_FOR_READ = 0;
  486. // value for action argument in cacheRawBlock to indicate cache dirty
  487. static uint8_t const CACHE_FOR_WRITE = 1;
  488. static cache_t cacheBuffer_; // 512 byte cache for device blocks
  489. static uint32_t cacheBlockNumber_; // Logical number of block in the cache
  490. static Sd2Card* sdCard_; // Sd2Card object for cache
  491. static uint8_t cacheDirty_; // cacheFlush() will write block if true
  492. static uint32_t cacheMirrorBlock_; // block number for mirror FAT
  493. //
  494. uint32_t allocSearchStart_; // start cluster for alloc search
  495. uint8_t blocksPerCluster_; // cluster size in blocks
  496. uint32_t blocksPerFat_; // FAT size in blocks
  497. uint32_t clusterCount_; // clusters in one FAT
  498. uint8_t clusterSizeShift_; // shift to convert cluster count to block count
  499. uint32_t dataStartBlock_; // first data block number
  500. uint8_t fatCount_; // number of FATs on volume
  501. uint32_t fatStartBlock_; // start block for first FAT
  502. uint8_t fatType_; // volume type (12, 16, OR 32)
  503. uint16_t rootDirEntryCount_; // number of entries in FAT16 root dir
  504. uint32_t rootDirStart_; // root start block for FAT16, cluster for FAT32
  505. //----------------------------------------------------------------------------
  506. uint8_t allocContiguous(uint32_t count, uint32_t* curCluster);
  507. uint8_t blockOfCluster(uint32_t position) const {
  508. return (position >> 9) & (blocksPerCluster_ - 1);}
  509. uint32_t clusterStartBlock(uint32_t cluster) const {
  510. return dataStartBlock_ + ((cluster - 2) << clusterSizeShift_);}
  511. uint32_t blockNumber(uint32_t cluster, uint32_t position) const {
  512. return clusterStartBlock(cluster) + blockOfCluster(position);}
  513. static uint8_t cacheFlush(void);
  514. static uint8_t cacheRawBlock(uint32_t blockNumber, uint8_t action);
  515. static void cacheSetDirty(void) {cacheDirty_ |= CACHE_FOR_WRITE;}
  516. static uint8_t cacheZeroBlock(uint32_t blockNumber);
  517. uint8_t chainSize(uint32_t beginCluster, uint32_t* size) const;
  518. uint8_t fatGet(uint32_t cluster, uint32_t* value) const;
  519. uint8_t fatPut(uint32_t cluster, uint32_t value);
  520. uint8_t fatPutEOC(uint32_t cluster) {
  521. return fatPut(cluster, 0x0FFFFFFF);
  522. }
  523. uint8_t freeChain(uint32_t cluster);
  524. uint8_t isEOC(uint32_t cluster) const {
  525. return cluster >= (fatType_ == 16 ? FAT16EOC_MIN : FAT32EOC_MIN);
  526. }
  527. uint8_t readBlock(uint32_t block, uint8_t* dst) {
  528. return sdCard_->readBlock(block, dst);}
  529. uint8_t readData(uint32_t block, uint16_t offset,
  530. uint16_t count, uint8_t* dst) {
  531. return sdCard_->readData(block, offset, count, dst);
  532. }
  533. uint8_t writeBlock(uint32_t block, const uint8_t* dst) {
  534. return sdCard_->writeBlock(block, dst);
  535. }
  536. };
  537. #endif // SdFat_h