20 #include "../../../include/esp3d_config.h"
21 #if defined (ARDUINO_ARCH_ESP8266) && defined(SD_DEVICE)
22 #if (SD_DEVICE == ESP_SD_NATIVE) || (SD_DEVICE == ESP_SDFAT)
24 #include "../esp_sd.h"
25 #include "../../../core/genLinkedList.h"
26 #include "../../../core/settings_esp3d.h"
30 using namespace sdfat;
34 void dateTime (uint16_t* date, uint16_t* dtime)
39 localtime_r (&now, &tmstruct);
40 *date = FAT_DATE ( (tmstruct.tm_year) + 1900, ( tmstruct.tm_mon) + 1, tmstruct.tm_mday);
41 *dtime = FAT_TIME (tmstruct.tm_hour, tmstruct.tm_min, tmstruct.tm_sec);
44 time_t getDateTimeFile(sdfat::File & filehandle)
50 if (filehandle.dirEntry(&d)) {
51 timefile.tm_year = FAT_YEAR(d.lastWriteDate) - 1900;
52 timefile.tm_mon = FAT_MONTH(d.lastWriteDate) - 1;
53 timefile.tm_mday = FAT_DAY(d.lastWriteDate);
54 timefile.tm_hour = FAT_HOUR(d.lastWriteTime);
55 timefile.tm_min = FAT_MINUTE(d.lastWriteTime);
56 timefile.tm_sec = FAT_SECOND(d.lastWriteTime);
57 timefile.tm_isdst = -1;
58 dt = mktime(&timefile);
73 #if defined(ESP_SD_DETECT_PIN) && ESP_SD_DETECT_PIN != -1
79 #endif //ESP_SD_DETECT_PIN
91 if (SD.card()->cardSize() > 0 ) {
104 if (_spi_speed_divider <= 0) {
105 _spi_speed_divider = 1;
107 #ifdef SD_TIMESTAMP_FEATURE
109 SdFile::dateTimeCallback (dateTime);
110 #endif //SD_TIMESTAMP_FEATURE
125 uint64_t volTotal = SD.vol()->clusterCount();
126 uint8_t blocks = SD.vol()->blocksPerCluster();
127 return volTotal * blocks * 512;
132 return totalBytes() - freeBytes();
137 static uint64_t volFree;
139 volFree = SD.vol()->freeClusterCount();
140 _sizechanged =
false;
142 uint8_t blocks = SD.vol()->blocksPerCluster();
143 return volFree * blocks * 512;
148 return SD.rename(oldpath,newpath);
152 #define noName "NO NAME "
153 #define fat16str "FAT16 "
154 #define fat32str "FAT32 "
158 #define ERASE_SIZE 262144L;
162 uint8_t writeCache(uint32_t lbn, Sd2Card & card, cache_t & cache)
164 return card.writeBlock(lbn, cache.data);
169 bool initSizes(uint32_t cardCapacityMB, uint8_t & sectorsPerCluster, uint8_t & numberOfHeads, uint8_t & sectorsPerTrack)
171 if (cardCapacityMB <= 6) {
173 }
else if (cardCapacityMB <= 16) {
174 sectorsPerCluster = 2;
175 }
else if (cardCapacityMB <= 32) {
176 sectorsPerCluster = 4;
177 }
else if (cardCapacityMB <= 64) {
178 sectorsPerCluster = 8;
179 }
else if (cardCapacityMB <= 128) {
180 sectorsPerCluster = 16;
181 }
else if (cardCapacityMB <= 1024) {
182 sectorsPerCluster = 32;
183 }
else if (cardCapacityMB <= 32768) {
184 sectorsPerCluster = 64;
187 sectorsPerCluster = 128;
191 sectorsPerTrack = cardCapacityMB <= 256 ? 32 : 63;
193 if (cardCapacityMB <= 16) {
195 }
else if (cardCapacityMB <= 32) {
197 }
else if (cardCapacityMB <= 128) {
199 }
else if (cardCapacityMB <= 504) {
201 }
else if (cardCapacityMB <= 1008) {
203 }
else if (cardCapacityMB <= 2016) {
205 }
else if (cardCapacityMB <= 4032) {
215 void clearCache(uint8_t addSig, cache_t & cache)
217 memset(&cache, 0,
sizeof(cache));
219 cache.mbr.mbrSig0 = BOOTSIG0;
220 cache.mbr.mbrSig1 = BOOTSIG1;
225 bool clearFatDir(uint32_t bgn, uint32_t count, Sd2Card & card, cache_t & cache,
ESP3DOutput * output)
227 clearCache(
false, cache);
228 if (!card.writeStart(bgn, count)) {
231 for (uint32_t i = 0; i < count; i++) {
232 if ((i & 0XFF) == 0) {
237 if (!card.writeData(cache.data)) {
241 if (!card.writeStop()) {
249 uint16_t lbnToCylinder(uint32_t lbn, uint8_t numberOfHeads, uint8_t sectorsPerTrack)
251 return lbn / (numberOfHeads * sectorsPerTrack);
255 uint8_t lbnToHead(uint32_t lbn, uint8_t numberOfHeads, uint8_t sectorsPerTrack)
257 return (lbn % (numberOfHeads * sectorsPerTrack)) / sectorsPerTrack;
261 uint8_t lbnToSector(uint32_t lbn, uint8_t sectorsPerTrack)
263 return (lbn % sectorsPerTrack) + 1;
268 bool writeMbr(Sd2Card & card, cache_t & cache, uint8_t partType, uint32_t relSector, uint32_t partSize, uint8_t numberOfHeads, uint8_t sectorsPerTrack)
270 clearCache(
true, cache);
271 part_t* p = cache.mbr.part;
273 uint16_t c = lbnToCylinder(relSector, numberOfHeads, sectorsPerTrack);
277 p->beginCylinderHigh = c >> 8;
278 p->beginCylinderLow = c & 0XFF;
279 p->beginHead = lbnToHead(relSector, numberOfHeads, sectorsPerTrack);
280 p->beginSector = lbnToSector(relSector, sectorsPerTrack);
282 uint32_t endLbn = relSector + partSize - 1;
283 c = lbnToCylinder(endLbn,numberOfHeads, sectorsPerTrack);
285 p->endCylinderHigh = c >> 8;
286 p->endCylinderLow = c & 0XFF;
287 p->endHead = lbnToHead(endLbn, numberOfHeads, sectorsPerTrack);
288 p->endSector = lbnToSector(endLbn, sectorsPerTrack);
291 p->endCylinderHigh = 3;
292 p->endCylinderLow = 255;
296 p->firstSector = relSector;
297 p->totalSectors = partSize;
298 if (!writeCache(0, card, cache)) {
306 uint32_t volSerialNumber(uint32_t cardSizeBlocks)
308 return (cardSizeBlocks << 8) + micros();
312 bool makeFat16(uint32_t & dataStart, Sd2Card & card, cache_t & cache, uint8_t numberOfHeads, uint8_t sectorsPerTrack, uint32_t cardSizeBlocks, uint8_t sectorsPerCluster, uint32_t &relSector, uint32_t partSize, uint8_t & partType, uint32_t &fatSize, uint32_t &fatStart, uint16_t reservedSectors,
ESP3DOutput * output)
315 for (dataStart = 2 * BU16;; dataStart += BU16) {
316 nc = (cardSizeBlocks - dataStart)/sectorsPerCluster;
317 fatSize = (nc + 2 + 255)/256;
318 uint32_t r = BU16 + 1 + 2 * fatSize + 32;
322 relSector = dataStart - r + BU16;
326 if (nc < 4085 || nc >= 65525) {
330 fatStart = relSector + reservedSectors;
331 partSize = nc * sectorsPerCluster + 2 * fatSize + reservedSectors + 32;
332 if (partSize < 32680) {
334 }
else if (partSize < 65536) {
340 if (!writeMbr(card, cache, partType, relSector, partSize, numberOfHeads, sectorsPerTrack)) {
343 clearCache(
true, cache);
344 fat_boot_t* pb = &cache.fbs;
348 for (uint8_t i = 0; i <
sizeof(pb->oemId); i++) {
351 pb->bytesPerSector = 512;
352 pb->sectorsPerCluster = sectorsPerCluster;
353 pb->reservedSectorCount = reservedSectors;
355 pb->rootDirEntryCount = 512;
356 pb->mediaType = 0XF8;
357 pb->sectorsPerFat16 = fatSize;
358 pb->sectorsPerTrack = sectorsPerTrack;
359 pb->headCount = numberOfHeads;
360 pb->hidddenSectors = relSector;
361 pb->totalSectors32 = partSize;
362 pb->driveNumber = 0X80;
363 pb->bootSignature = EXTENDED_BOOT_SIG;
364 pb->volumeSerialNumber = volSerialNumber(cardSizeBlocks);
365 memcpy(pb->volumeLabel, noName,
sizeof(pb->volumeLabel));
366 memcpy(pb->fileSystemType, fat16str,
sizeof(pb->fileSystemType));
368 if (!writeCache(relSector, card, cache)) {
372 clearFatDir(fatStart, dataStart - fatStart, card, cache, output);
373 clearCache(
false, cache);
374 cache.fat16[0] = 0XFFF8;
375 cache.fat16[1] = 0XFFFF;
377 if (!writeCache(fatStart, card, cache)
378 || !writeCache(fatStart + fatSize, card, cache)) {
385 bool makeFat32(uint32_t & dataStart, Sd2Card & card, cache_t & cache, uint8_t numberOfHeads, uint8_t sectorsPerTrack, uint32_t cardSizeBlocks, uint8_t sectorsPerCluster, uint32_t &relSector, uint32_t partSize, uint8_t & partType, uint32_t &fatSize, uint32_t &fatStart, uint16_t reservedSectors,
ESP3DOutput * output)
389 for (dataStart = 2 * BU32;; dataStart += BU32) {
390 nc = (cardSizeBlocks - dataStart)/sectorsPerCluster;
391 fatSize = (nc + 2 + 127)/128;
392 uint32_t r = relSector + 9 + 2 * fatSize;
393 if (dataStart >= r) {
401 reservedSectors = dataStart - relSector - 2 * fatSize;
402 fatStart = relSector + reservedSectors;
403 partSize = nc * sectorsPerCluster + dataStart - relSector;
406 if ((relSector + partSize) <= 16450560) {
413 if (!writeMbr(card, cache, partType, relSector, partSize, numberOfHeads, sectorsPerTrack)) {
416 clearCache(
true, cache);
418 fat32_boot_t* pb = &cache.fbs32;
422 for (uint8_t i = 0; i <
sizeof(pb->oemId); i++) {
425 pb->bytesPerSector = 512;
426 pb->sectorsPerCluster = sectorsPerCluster;
427 pb->reservedSectorCount = reservedSectors;
429 pb->mediaType = 0XF8;
430 pb->sectorsPerTrack = sectorsPerTrack;
431 pb->headCount = numberOfHeads;
432 pb->hidddenSectors = relSector;
433 pb->totalSectors32 = partSize;
434 pb->sectorsPerFat32 = fatSize;
435 pb->fat32RootCluster = 2;
437 pb->fat32BackBootBlock = 6;
438 pb->driveNumber = 0X80;
439 pb->bootSignature = EXTENDED_BOOT_SIG;
440 pb->volumeSerialNumber = volSerialNumber(cardSizeBlocks);
441 memcpy(pb->volumeLabel, noName,
sizeof(pb->volumeLabel));
442 memcpy(pb->fileSystemType, fat32str,
sizeof(pb->fileSystemType));
444 if (!writeCache(relSector, card, cache)
445 || !writeCache(relSector + 6, card, cache)) {
448 clearCache(
true, cache);
450 if (!writeCache(relSector + 2, card, cache)
451 || !writeCache(relSector + 8, card, cache)) {
454 fat32_fsinfo_t* pf = &cache.fsinfo;
455 pf->leadSignature = FSINFO_LEAD_SIG;
456 pf->structSignature = FSINFO_STRUCT_SIG;
457 pf->freeCount = 0XFFFFFFFF;
458 pf->nextFree = 0XFFFFFFFF;
460 if (!writeCache(relSector + 1, card, cache)
461 || !writeCache(relSector + 7, card, cache)) {
464 clearFatDir(fatStart, 2 * fatSize + sectorsPerCluster, card, cache, output);
465 clearCache(
false, cache);
466 cache.fat32[0] = 0x0FFFFFF8;
467 cache.fat32[1] = 0x0FFFFFFF;
468 cache.fat32[2] = 0x0FFFFFFF;
470 if (!writeCache(fatStart, card, cache)
471 || !writeCache(fatStart + fatSize, card, cache)) {
477 bool eraseCard(Sd2Card & card, cache_t & cache, uint32_t cardSizeBlocks,
ESP3DOutput * output)
479 uint32_t firstBlock = 0;
483 output->
printMSG(
"Erasing ",
false);
486 lastBlock = firstBlock + ERASE_SIZE - 1;
487 if (lastBlock >= cardSizeBlocks) {
488 lastBlock = cardSizeBlocks - 1;
490 if (!card.erase(firstBlock, lastBlock)) {
496 firstBlock += ERASE_SIZE;
497 }
while (firstBlock < cardSizeBlocks);
499 if (!card.readBlock(0, cache.data)) {
508 bool formatCard(uint32_t & dataStart, Sd2Card & card,
509 cache_t & cache, uint8_t numberOfHeads,
510 uint8_t sectorsPerTrack, uint32_t cardSizeBlocks,
511 uint8_t sectorsPerCluster, uint32_t &relSector,
512 uint32_t partSize, uint8_t & partType,
513 uint32_t &fatSize, uint32_t &fatStart,
514 uint32_t cardCapacityMB, uint16_t reservedSectors,
ESP3DOutput * output)
516 initSizes(cardCapacityMB, sectorsPerCluster, numberOfHeads, sectorsPerTrack);
517 if (card.type() != SD_CARD_TYPE_SDHC) {
519 output->
printMSG(
"Formating FAT16 ");
521 if(!makeFat16(dataStart, card, cache, numberOfHeads, sectorsPerTrack, cardSizeBlocks, sectorsPerCluster, relSector, partSize, partType, fatSize, fatStart, reservedSectors, output)) {
526 output->
printMSG(
"Formating FAT32 ",
false);
528 if(!makeFat32(dataStart, card, cache, numberOfHeads, sectorsPerTrack, cardSizeBlocks, sectorsPerCluster, relSector, partSize, partType, fatSize, fatStart, reservedSectors, output)) {
542 uint32_t cardSizeBlocks;
543 uint32_t cardCapacityMB;
553 uint8_t numberOfHeads;
554 uint8_t sectorsPerTrack;
557 uint16_t reservedSectors;
558 uint8_t sectorsPerCluster;
565 cardSizeBlocks = card.cardSize();
566 if (cardSizeBlocks == 0) {
569 cardCapacityMB = (cardSizeBlocks + 2047)/2048;
571 String s =
"Capacity detected :" + String((1.048576*cardCapacityMB)/1024) +
"GB";
574 if (!eraseCard(card, cache, cardSizeBlocks, output)) {
578 if (!formatCard(dataStart, card, cache, numberOfHeads,
579 sectorsPerTrack, cardSizeBlocks,
580 sectorsPerCluster, relSector, partSize, partType,
581 fatSize, fatStart, cardCapacityMB, reservedSectors,output)) {
597 if (path[0] !=
'/') {
603 p.remove(p.lastIndexOf(
'/') +1);
604 if (!exists(p.c_str())) {
618 if (strcmp(path,
"/") == 0) {
621 res = SD.exists(path);
634 return SD.remove(path);
639 return SD.mkdir(path);
651 while (pathlist.
count() > 0) {
652 sdfat::File
dir = SD.open(pathlist.
getLast().c_str());
653 dir.rewindDirectory();
655 bool candelete =
true;
663 pathlist.
push(newdir);
676 if (pathlist.
getLast() !=
"/") {
677 res = SD.rmdir(pathlist.
getLast().c_str());
704 _iswritemode = iswritemode;
719 if (_name.endsWith(
"/")) {
720 _name.remove( _name.length() - 1,1);
723 if (_name[0] ==
'/') {
726 int pos = _name.lastIndexOf(
'/');
728 _name.remove( 0, pos+1);
730 if (_name.length() == 0) {
752 static char sname[13];
753 sdfat::File ftmp = SD.open(_filename.c_str());
759 return _name.c_str();
770 if (_iswritemode && !_isdir) {
771 sdfat::File ftmp = SD.open(_filename.c_str());
774 _lastwrite = getDateTimeFile(ftmp);
786 if ((_index == -1) || !_isdir) {
793 tmp.getName(tmps,254);
794 log_esp3d(
"tmp name :%s %s", tmps, (tmp.isDir())?
"isDir":
"isFile");
795 String s = _filename ;
800 ESP_SDFile esptmp(&tmp, tmp.isDir(),
false, s.c_str());
812 #endif //SD_DEVICE == ESP_SD_NATIVE
813 #endif //ARCH_ESP32 && SD_DEVICE