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