Fri, 17 Nov 2017 10:13:31 +0100
proper configuration, homing and planner optimization
0 | 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 | #include "Marlin.h" | |
21 | #ifdef SDSUPPORT | |
22 | #ifndef SdVolume_h | |
23 | #define SdVolume_h | |
24 | /** | |
25 | * \file | |
26 | * \brief SdVolume class | |
27 | */ | |
28 | #include "SdFatConfig.h" | |
29 | #include "Sd2Card.h" | |
30 | #include "SdFatStructs.h" | |
31 | ||
32 | //============================================================================== | |
33 | // SdVolume class | |
34 | /** | |
35 | * \brief Cache for an SD data block | |
36 | */ | |
37 | union cache_t { | |
38 | /** Used to access cached file data blocks. */ | |
39 | uint8_t data[512]; | |
40 | /** Used to access cached FAT16 entries. */ | |
41 | uint16_t fat16[256]; | |
42 | /** Used to access cached FAT32 entries. */ | |
43 | uint32_t fat32[128]; | |
44 | /** Used to access cached directory entries. */ | |
45 | dir_t dir[16]; | |
46 | /** Used to access a cached Master Boot Record. */ | |
47 | mbr_t mbr; | |
48 | /** Used to access to a cached FAT boot sector. */ | |
49 | fat_boot_t fbs; | |
50 | /** Used to access to a cached FAT32 boot sector. */ | |
51 | fat32_boot_t fbs32; | |
52 | /** Used to access to a cached FAT32 FSINFO sector. */ | |
53 | fat32_fsinfo_t fsinfo; | |
54 | }; | |
55 | //------------------------------------------------------------------------------ | |
56 | /** | |
57 | * \class SdVolume | |
58 | * \brief Access FAT16 and FAT32 volumes on SD and SDHC cards. | |
59 | */ | |
60 | class SdVolume { | |
61 | public: | |
62 | /** Create an instance of SdVolume */ | |
63 | SdVolume() : fatType_(0) {} | |
64 | /** Clear the cache and returns a pointer to the cache. Used by the WaveRP | |
65 | * recorder to do raw write to the SD card. Not for normal apps. | |
66 | * \return A pointer to the cache buffer or zero if an error occurs. | |
67 | */ | |
68 | cache_t* cacheClear() { | |
69 | if (!cacheFlush()) return 0; | |
70 | cacheBlockNumber_ = 0XFFFFFFFF; | |
71 | return &cacheBuffer_; | |
72 | } | |
73 | /** Initialize a FAT volume. Try partition one first then try super | |
74 | * floppy format. | |
75 | * | |
76 | * \param[in] dev The Sd2Card where the volume is located. | |
77 | * | |
78 | * \return The value one, true, is returned for success and | |
79 | * the value zero, false, is returned for failure. Reasons for | |
80 | * failure include not finding a valid partition, not finding a valid | |
81 | * FAT file system or an I/O error. | |
82 | */ | |
83 | bool init(Sd2Card* dev) { return init(dev, 1) ? true : init(dev, 0);} | |
84 | bool init(Sd2Card* dev, uint8_t part); | |
85 | ||
86 | // inline functions that return volume info | |
87 | /** \return The volume's cluster size in blocks. */ | |
88 | uint8_t blocksPerCluster() const {return blocksPerCluster_;} | |
89 | /** \return The number of blocks in one FAT. */ | |
90 | uint32_t blocksPerFat() const {return blocksPerFat_;} | |
91 | /** \return The total number of clusters in the volume. */ | |
92 | uint32_t clusterCount() const {return clusterCount_;} | |
93 | /** \return The shift count required to multiply by blocksPerCluster. */ | |
94 | uint8_t clusterSizeShift() const {return clusterSizeShift_;} | |
95 | /** \return The logical block number for the start of file data. */ | |
96 | uint32_t dataStartBlock() const {return dataStartBlock_;} | |
97 | /** \return The number of FAT structures on the volume. */ | |
98 | uint8_t fatCount() const {return fatCount_;} | |
99 | /** \return The logical block number for the start of the first FAT. */ | |
100 | uint32_t fatStartBlock() const {return fatStartBlock_;} | |
101 | /** \return The FAT type of the volume. Values are 12, 16 or 32. */ | |
102 | uint8_t fatType() const {return fatType_;} | |
103 | int32_t freeClusterCount(); | |
104 | /** \return The number of entries in the root directory for FAT16 volumes. */ | |
105 | uint32_t rootDirEntryCount() const {return rootDirEntryCount_;} | |
106 | /** \return The logical block number for the start of the root directory | |
107 | on FAT16 volumes or the first cluster number on FAT32 volumes. */ | |
108 | uint32_t rootDirStart() const {return rootDirStart_;} | |
109 | /** Sd2Card object for this volume | |
110 | * \return pointer to Sd2Card object. | |
111 | */ | |
112 | Sd2Card* sdCard() {return sdCard_;} | |
113 | /** Debug access to FAT table | |
114 | * | |
115 | * \param[in] n cluster number. | |
116 | * \param[out] v value of entry | |
117 | * \return true for success or false for failure | |
118 | */ | |
119 | bool dbgFat(uint32_t n, uint32_t* v) {return fatGet(n, v);} | |
120 | //------------------------------------------------------------------------------ | |
121 | private: | |
122 | // Allow SdBaseFile access to SdVolume private data. | |
123 | friend class SdBaseFile; | |
124 | ||
125 | // value for dirty argument in cacheRawBlock to indicate read from cache | |
126 | static bool const CACHE_FOR_READ = false; | |
127 | // value for dirty argument in cacheRawBlock to indicate write to cache | |
128 | static bool const CACHE_FOR_WRITE = true; | |
129 | ||
130 | #if USE_MULTIPLE_CARDS | |
131 | cache_t cacheBuffer_; // 512 byte cache for device blocks | |
132 | uint32_t cacheBlockNumber_; // Logical number of block in the cache | |
133 | Sd2Card* sdCard_; // Sd2Card object for cache | |
134 | bool cacheDirty_; // cacheFlush() will write block if true | |
135 | uint32_t cacheMirrorBlock_; // block number for mirror FAT | |
136 | #else // USE_MULTIPLE_CARDS | |
137 | static cache_t cacheBuffer_; // 512 byte cache for device blocks | |
138 | static uint32_t cacheBlockNumber_; // Logical number of block in the cache | |
139 | static Sd2Card* sdCard_; // Sd2Card object for cache | |
140 | static bool cacheDirty_; // cacheFlush() will write block if true | |
141 | static uint32_t cacheMirrorBlock_; // block number for mirror FAT | |
142 | #endif // USE_MULTIPLE_CARDS | |
143 | uint32_t allocSearchStart_; // start cluster for alloc search | |
144 | uint8_t blocksPerCluster_; // cluster size in blocks | |
145 | uint32_t blocksPerFat_; // FAT size in blocks | |
146 | uint32_t clusterCount_; // clusters in one FAT | |
147 | uint8_t clusterSizeShift_; // shift to convert cluster count to block count | |
148 | uint32_t dataStartBlock_; // first data block number | |
149 | uint8_t fatCount_; // number of FATs on volume | |
150 | uint32_t fatStartBlock_; // start block for first FAT | |
151 | uint8_t fatType_; // volume type (12, 16, OR 32) | |
152 | uint16_t rootDirEntryCount_; // number of entries in FAT16 root dir | |
153 | uint32_t rootDirStart_; // root start block for FAT16, cluster for FAT32 | |
154 | //---------------------------------------------------------------------------- | |
155 | bool allocContiguous(uint32_t count, uint32_t* curCluster); | |
156 | uint8_t blockOfCluster(uint32_t position) const { | |
157 | return (position >> 9) & (blocksPerCluster_ - 1);} | |
158 | uint32_t clusterStartBlock(uint32_t cluster) const { | |
159 | return dataStartBlock_ + ((cluster - 2) << clusterSizeShift_);} | |
160 | uint32_t blockNumber(uint32_t cluster, uint32_t position) const { | |
161 | return clusterStartBlock(cluster) + blockOfCluster(position);} | |
162 | cache_t *cache() {return &cacheBuffer_;} | |
163 | uint32_t cacheBlockNumber() {return cacheBlockNumber_;} | |
164 | #if USE_MULTIPLE_CARDS | |
165 | bool cacheFlush(); | |
166 | bool cacheRawBlock(uint32_t blockNumber, bool dirty); | |
167 | #else // USE_MULTIPLE_CARDS | |
168 | static bool cacheFlush(); | |
169 | static bool cacheRawBlock(uint32_t blockNumber, bool dirty); | |
170 | #endif // USE_MULTIPLE_CARDS | |
171 | // used by SdBaseFile write to assign cache to SD location | |
172 | void cacheSetBlockNumber(uint32_t blockNumber, bool dirty) { | |
173 | cacheDirty_ = dirty; | |
174 | cacheBlockNumber_ = blockNumber; | |
175 | } | |
176 | void cacheSetDirty() {cacheDirty_ |= CACHE_FOR_WRITE;} | |
177 | bool chainSize(uint32_t beginCluster, uint32_t* size); | |
178 | bool fatGet(uint32_t cluster, uint32_t* value); | |
179 | bool fatPut(uint32_t cluster, uint32_t value); | |
180 | bool fatPutEOC(uint32_t cluster) { | |
181 | return fatPut(cluster, 0x0FFFFFFF); | |
182 | } | |
183 | bool freeChain(uint32_t cluster); | |
184 | bool isEOC(uint32_t cluster) const { | |
185 | if (FAT12_SUPPORT && fatType_ == 12) return cluster >= FAT12EOC_MIN; | |
186 | if (fatType_ == 16) return cluster >= FAT16EOC_MIN; | |
187 | return cluster >= FAT32EOC_MIN; | |
188 | } | |
189 | bool readBlock(uint32_t block, uint8_t* dst) { | |
190 | return sdCard_->readBlock(block, dst);} | |
191 | bool writeBlock(uint32_t block, const uint8_t* dst) { | |
192 | return sdCard_->writeBlock(block, dst); | |
193 | } | |
194 | //------------------------------------------------------------------------------ | |
195 | // Deprecated functions - suppress cpplint warnings with NOLINT comment | |
196 | #if ALLOW_DEPRECATED_FUNCTIONS && !defined(DOXYGEN) | |
197 | public: | |
198 | /** \deprecated Use: bool SdVolume::init(Sd2Card* dev); | |
199 | * \param[in] dev The SD card where the volume is located. | |
200 | * \return true for success or false for failure. | |
201 | */ | |
202 | bool init(Sd2Card& dev) {return init(&dev);} // NOLINT | |
203 | /** \deprecated Use: bool SdVolume::init(Sd2Card* dev, uint8_t vol); | |
204 | * \param[in] dev The SD card where the volume is located. | |
205 | * \param[in] part The partition to be used. | |
206 | * \return true for success or false for failure. | |
207 | */ | |
208 | bool init(Sd2Card& dev, uint8_t part) { // NOLINT | |
209 | return init(&dev, part); | |
210 | } | |
211 | #endif // ALLOW_DEPRECATED_FUNCTIONS | |
212 | }; | |
213 | #endif // SdVolume | |
214 | #endif |