Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

7 лет назад
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544
  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. int32_t read(void* buf, size_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. size_t write(uint8_t b);
  282. size_t write(const void* buf, size_t nbyte);
  283. size_t write(const char* str);
  284. void write_P(PGM_P str);
  285. void writeln_P(PGM_P str);
  286. //------------------------------------------------------------------------------
  287. #if ALLOW_DEPRECATED_FUNCTIONS
  288. // Deprecated functions - suppress cpplint warnings with NOLINT comment
  289. /** \deprecated Use:
  290. * uint8_t SdFile::contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock);
  291. */
  292. uint8_t contiguousRange(uint32_t& bgnBlock, uint32_t& endBlock) { // NOLINT
  293. return contiguousRange(&bgnBlock, &endBlock);
  294. }
  295. /** \deprecated Use:
  296. * uint8_t SdFile::createContiguous(SdFile* dirFile,
  297. * const char* fileName, uint32_t size)
  298. */
  299. uint8_t createContiguous(SdFile& dirFile, // NOLINT
  300. const char* fileName, uint32_t size) {
  301. return createContiguous(&dirFile, fileName, size);
  302. }
  303. /**
  304. * \deprecated Use:
  305. * static void SdFile::dateTimeCallback(
  306. * void (*dateTime)(uint16_t* date, uint16_t* time));
  307. */
  308. static void dateTimeCallback(
  309. void (*dateTime)(uint16_t& date, uint16_t& time)) { // NOLINT
  310. oldDateTime_ = dateTime;
  311. dateTime_ = dateTime ? oldToNew : 0;
  312. }
  313. /** \deprecated Use: uint8_t SdFile::dirEntry(dir_t* dir); */
  314. uint8_t dirEntry(dir_t& dir) {return dirEntry(&dir);} // NOLINT
  315. /** \deprecated Use:
  316. * uint8_t SdFile::makeDir(SdFile* dir, const char* dirName);
  317. */
  318. uint8_t makeDir(SdFile& dir, const char* dirName) { // NOLINT
  319. return makeDir(&dir, dirName);
  320. }
  321. /** \deprecated Use:
  322. * uint8_t SdFile::open(SdFile* dirFile, const char* fileName, uint8_t oflag);
  323. */
  324. uint8_t open(SdFile& dirFile, // NOLINT
  325. const char* fileName, uint8_t oflag) {
  326. return open(&dirFile, fileName, oflag);
  327. }
  328. /** \deprecated Do not use in new apps */
  329. uint8_t open(SdFile& dirFile, const char* fileName) { // NOLINT
  330. return open(dirFile, fileName, O_RDWR);
  331. }
  332. /** \deprecated Use:
  333. * uint8_t SdFile::open(SdFile* dirFile, uint16_t index, uint8_t oflag);
  334. */
  335. uint8_t open(SdFile& dirFile, uint16_t index, uint8_t oflag) { // NOLINT
  336. return open(&dirFile, index, oflag);
  337. }
  338. /** \deprecated Use: uint8_t SdFile::openRoot(SdVolume* vol); */
  339. uint8_t openRoot(SdVolume& vol) {return openRoot(&vol);} // NOLINT
  340. /** \deprecated Use: int8_t SdFile::readDir(dir_t* dir); */
  341. int8_t readDir(dir_t& dir) {return readDir(&dir);} // NOLINT
  342. /** \deprecated Use:
  343. * static uint8_t SdFile::remove(SdFile* dirFile, const char* fileName);
  344. */
  345. static uint8_t remove(SdFile& dirFile, const char* fileName) { // NOLINT
  346. return remove(&dirFile, fileName);
  347. }
  348. //------------------------------------------------------------------------------
  349. // rest are private
  350. private:
  351. static void (*oldDateTime_)(uint16_t& date, uint16_t& time); // NOLINT
  352. static void oldToNew(uint16_t* date, uint16_t* time) {
  353. uint16_t d;
  354. uint16_t t;
  355. oldDateTime_(d, t);
  356. *date = d;
  357. *time = t;
  358. }
  359. #endif // ALLOW_DEPRECATED_FUNCTIONS
  360. private:
  361. // bits defined in flags_
  362. // should be 0XF
  363. static uint8_t const F_OFLAG = (O_ACCMODE | O_APPEND | O_SYNC);
  364. // available bits
  365. static uint8_t const F_UNUSED = 0X30;
  366. // use unbuffered SD read
  367. static uint8_t const F_FILE_UNBUFFERED_READ = 0X40;
  368. // sync of directory entry required
  369. static uint8_t const F_FILE_DIR_DIRTY = 0X80;
  370. // make sure F_OFLAG is ok
  371. #if ((F_UNUSED | F_FILE_UNBUFFERED_READ | F_FILE_DIR_DIRTY) & F_OFLAG)
  372. #error flags_ bits conflict
  373. #endif // flags_ bits
  374. // private data
  375. uint8_t flags_; // See above for definition of flags_ bits
  376. uint8_t type_; // type of file see above for values
  377. uint32_t curCluster_; // cluster for current file position
  378. uint32_t curPosition_; // current file position in bytes from beginning
  379. uint32_t dirBlock_; // SD block that contains directory entry for file
  380. uint8_t dirIndex_; // index of entry in dirBlock 0 <= dirIndex_ <= 0XF
  381. uint32_t fileSize_; // file size in bytes
  382. uint32_t firstCluster_; // first cluster of file
  383. SdVolume* vol_; // volume where file is located
  384. // private functions
  385. uint8_t addCluster(void);
  386. uint8_t addDirCluster(void);
  387. dir_t* cacheDirEntry(uint8_t action);
  388. static void (*dateTime_)(uint16_t* date, uint16_t* time);
  389. static uint8_t make83Name(const char* str, uint8_t* name);
  390. uint8_t openCachedEntry(uint8_t cacheIndex, uint8_t oflags);
  391. dir_t* readDirCache(void);
  392. };
  393. //==============================================================================
  394. // SdVolume class
  395. /**
  396. * \brief Cache for an SD data block
  397. */
  398. union cache_t {
  399. /** Used to access cached file data blocks. */
  400. uint8_t data[512];
  401. /** Used to access cached FAT16 entries. */
  402. uint16_t fat16[256];
  403. /** Used to access cached FAT32 entries. */
  404. uint32_t fat32[128];
  405. /** Used to access cached directory entries. */
  406. dir_t dir[16];
  407. /** Used to access a cached MasterBoot Record. */
  408. mbr_t mbr;
  409. /** Used to access to a cached FAT boot sector. */
  410. fbs_t fbs;
  411. };
  412. //------------------------------------------------------------------------------
  413. /**
  414. * \class SdVolume
  415. * \brief Access FAT16 and FAT32 volumes on SD and SDHC cards.
  416. */
  417. class SdVolume {
  418. public:
  419. /** Create an instance of SdVolume */
  420. SdVolume(void) :allocSearchStart_(2), fatType_(0) {}
  421. /** Clear the cache and returns a pointer to the cache. Used by the WaveRP
  422. * recorder to do raw write to the SD card. Not for normal apps.
  423. */
  424. static uint8_t* cacheClear(void) {
  425. cacheFlush();
  426. cacheBlockNumber_ = 0XFFFFFFFF;
  427. return cacheBuffer_.data;
  428. }
  429. /**
  430. * Initialize a FAT volume. Try partition one first then try super
  431. * floppy format.
  432. *
  433. * \param[in] dev The Sd2Card where the volume is located.
  434. *
  435. * \return The value one, true, is returned for success and
  436. * the value zero, false, is returned for failure. Reasons for
  437. * failure include not finding a valid partition, not finding a valid
  438. * FAT file system or an I/O error.
  439. */
  440. uint8_t init(Sd2Card* dev) { return init(dev, 1) ? true : init(dev, 0);}
  441. uint8_t init(Sd2Card* dev, uint8_t part);
  442. // inline functions that return volume info
  443. /** \return The volume's cluster size in blocks. */
  444. uint8_t blocksPerCluster(void) const {return blocksPerCluster_;}
  445. /** \return The number of blocks in one FAT. */
  446. uint32_t blocksPerFat(void) const {return blocksPerFat_;}
  447. /** \return The total number of clusters in the volume. */
  448. uint32_t clusterCount(void) const {return clusterCount_;}
  449. /** \return The shift count required to multiply by blocksPerCluster. */
  450. uint8_t clusterSizeShift(void) const {return clusterSizeShift_;}
  451. /** \return The logical block number for the start of file data. */
  452. uint32_t dataStartBlock(void) const {return dataStartBlock_;}
  453. /** \return The number of FAT structures on the volume. */
  454. uint8_t fatCount(void) const {return fatCount_;}
  455. /** \return The logical block number for the start of the first FAT. */
  456. uint32_t fatStartBlock(void) const {return fatStartBlock_;}
  457. /** \return The FAT type of the volume. Values are 12, 16 or 32. */
  458. uint8_t fatType(void) const {return fatType_;}
  459. /** \return The number of entries in the root directory for FAT16 volumes. */
  460. uint32_t rootDirEntryCount(void) const {return rootDirEntryCount_;}
  461. /** \return The logical block number for the start of the root directory
  462. on FAT16 volumes or the first cluster number on FAT32 volumes. */
  463. uint32_t rootDirStart(void) const {return rootDirStart_;}
  464. /** return a pointer to the Sd2Card object for this volume */
  465. static Sd2Card* sdCard(void) {return sdCard_;}
  466. //------------------------------------------------------------------------------
  467. #if ALLOW_DEPRECATED_FUNCTIONS
  468. // Deprecated functions - suppress cpplint warnings with NOLINT comment
  469. /** \deprecated Use: uint8_t SdVolume::init(Sd2Card* dev); */
  470. uint8_t init(Sd2Card& dev) {return init(&dev);} // NOLINT
  471. /** \deprecated Use: uint8_t SdVolume::init(Sd2Card* dev, uint8_t vol); */
  472. uint8_t init(Sd2Card& dev, uint8_t part) { // NOLINT
  473. return init(&dev, part);
  474. }
  475. #endif // ALLOW_DEPRECATED_FUNCTIONS
  476. //------------------------------------------------------------------------------
  477. private:
  478. // Allow SdFile access to SdVolume private data.
  479. friend class SdFile;
  480. // value for action argument in cacheRawBlock to indicate read from cache
  481. static uint8_t const CACHE_FOR_READ = 0;
  482. // value for action argument in cacheRawBlock to indicate cache dirty
  483. static uint8_t const CACHE_FOR_WRITE = 1;
  484. static cache_t cacheBuffer_; // 512 byte cache for device blocks
  485. static uint32_t cacheBlockNumber_; // Logical number of block in the cache
  486. static Sd2Card* sdCard_; // Sd2Card object for cache
  487. static uint8_t cacheDirty_; // cacheFlush() will write block if true
  488. static uint32_t cacheMirrorBlock_; // block number for mirror FAT
  489. //
  490. uint32_t allocSearchStart_; // start cluster for alloc search
  491. uint8_t blocksPerCluster_; // cluster size in blocks
  492. uint32_t blocksPerFat_; // FAT size in blocks
  493. uint32_t clusterCount_; // clusters in one FAT
  494. uint8_t clusterSizeShift_; // shift to convert cluster count to block count
  495. uint32_t dataStartBlock_; // first data block number
  496. uint8_t fatCount_; // number of FATs on volume
  497. uint32_t fatStartBlock_; // start block for first FAT
  498. uint8_t fatType_; // volume type (12, 16, OR 32)
  499. uint16_t rootDirEntryCount_; // number of entries in FAT16 root dir
  500. uint32_t rootDirStart_; // root start block for FAT16, cluster for FAT32
  501. //----------------------------------------------------------------------------
  502. uint8_t allocContiguous(uint32_t count, uint32_t* curCluster);
  503. uint8_t blockOfCluster(uint32_t position) const {
  504. return (position >> 9) & (blocksPerCluster_ - 1);}
  505. uint32_t clusterStartBlock(uint32_t cluster) const {
  506. return dataStartBlock_ + ((cluster - 2) << clusterSizeShift_);}
  507. uint32_t blockNumber(uint32_t cluster, uint32_t position) const {
  508. return clusterStartBlock(cluster) + blockOfCluster(position);}
  509. static uint8_t cacheFlush(void);
  510. static uint8_t cacheRawBlock(uint32_t blockNumber, uint8_t action);
  511. static void cacheSetDirty(void) {cacheDirty_ |= CACHE_FOR_WRITE;}
  512. static uint8_t cacheZeroBlock(uint32_t blockNumber);
  513. uint8_t chainSize(uint32_t beginCluster, uint32_t* size) const;
  514. uint8_t fatGet(uint32_t cluster, uint32_t* value) const;
  515. uint8_t fatPut(uint32_t cluster, uint32_t value);
  516. uint8_t fatPutEOC(uint32_t cluster) {
  517. return fatPut(cluster, 0x0FFFFFFF);
  518. }
  519. uint8_t freeChain(uint32_t cluster);
  520. uint8_t isEOC(uint32_t cluster) const {
  521. return cluster >= (fatType_ == 16 ? FAT16EOC_MIN : FAT32EOC_MIN);
  522. }
  523. uint8_t readBlock(uint32_t block, uint8_t* dst) {
  524. return sdCard_->readBlock(block, dst);
  525. }
  526. uint8_t writeBlock(uint32_t block, const uint8_t* dst) {
  527. return sdCard_->writeBlock(block, dst);
  528. }
  529. };
  530. #endif // SdFat_h