You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

232 lines
6.2KB

  1. /* SD library compatibility wrapper for use of SdFat on Teensy
  2. * Copyright (c) 2020, Paul Stoffregen, paul@pjrc.com
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a copy
  5. * of this software and associated documentation files (the "Software"), to deal
  6. * in the Software without restriction, including without limitation the rights
  7. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. * copies of the Software, and to permit persons to whom the Software is
  9. * furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice, development funding notice, and this permission
  12. * notice shall be included in all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. * THE SOFTWARE.
  21. */
  22. #ifndef __SD_H__
  23. #define __SD_H__
  24. #include <core/Arduino.h>
  25. #include <sdfat/SdFat.h>
  26. // Use FILE_READ & FILE_WRITE as defined by FS.h
  27. #if defined(FILE_READ) && !defined(FS_H)
  28. #undef FILE_READ
  29. #endif
  30. #if defined(FILE_WRITE) && !defined(FS_H)
  31. #undef FILE_WRITE
  32. #endif
  33. #include <core/FS.h>
  34. #if defined(__MK64FX512__) || defined(__MK66FX1M0__) || defined(__IMXRT1062__)
  35. #define BUILTIN_SDCARD 254
  36. #endif
  37. #if defined(__arm__)
  38. // Support everything on 32 bit boards with enough memory
  39. #define SDFAT_FILE FsFile
  40. #define SDFAT_BASE SdFs
  41. #define MAX_FILENAME_LEN 256
  42. #elif defined(__AVR__)
  43. // Limit to 32GB cards on 8 bit Teensy with only limited memory
  44. #define SDFAT_FILE File32
  45. #define SDFAT_BASE SdFat32
  46. #define MAX_FILENAME_LEN 64
  47. #endif
  48. class SDFile : public File
  49. {
  50. private:
  51. // Classes derived from File are never meant to be constructed
  52. // anywhere other than open() in the parent FS class and
  53. // openNextFile() while traversing a directory.
  54. // Only the abstract File class which references these derived
  55. // classes is meant to have a public constructor!
  56. SDFile(const SDFAT_FILE &file) : sdfatfile(file), filename(nullptr) { }
  57. friend class SDClass;
  58. public:
  59. virtual ~SDFile(void) {
  60. if (sdfatfile) sdfatfile.close();
  61. if (filename) free(filename);
  62. }
  63. #ifdef FILE_WHOAMI
  64. virtual void whoami() {
  65. Serial.printf(" SDFile this=%x, refcount=%u\n",
  66. (int)this, getRefcount());
  67. }
  68. #endif
  69. virtual size_t write(const void *buf, size_t size) {
  70. return sdfatfile.write(buf, size);
  71. }
  72. virtual int peek() {
  73. return sdfatfile.peek();
  74. }
  75. virtual int available() {
  76. return sdfatfile.available();
  77. }
  78. virtual void flush() {
  79. sdfatfile.flush();
  80. }
  81. virtual size_t read(void *buf, size_t nbyte) {
  82. return sdfatfile.read(buf, nbyte);
  83. }
  84. virtual bool truncate(uint64_t size=0) {
  85. return sdfatfile.truncate(size);
  86. }
  87. virtual bool seek(uint64_t pos, int mode = SeekSet) {
  88. if (mode == SeekSet) return sdfatfile.seekSet(pos);
  89. if (mode == SeekCur) return sdfatfile.seekCur(pos);
  90. if (mode == SeekEnd) return sdfatfile.seekEnd(pos);
  91. return false;
  92. }
  93. virtual uint64_t position() {
  94. return sdfatfile.curPosition();
  95. }
  96. virtual uint64_t size() {
  97. return sdfatfile.size();
  98. }
  99. virtual void close() {
  100. if (filename) {
  101. free(filename);
  102. filename = nullptr;
  103. }
  104. sdfatfile.close();
  105. }
  106. virtual operator bool() {
  107. return sdfatfile.isOpen();
  108. }
  109. virtual const char * name() {
  110. if (!filename) {
  111. filename = (char *)malloc(MAX_FILENAME_LEN);
  112. if (filename) {
  113. sdfatfile.getName(filename, MAX_FILENAME_LEN);
  114. } else {
  115. static char zeroterm = 0;
  116. filename = &zeroterm;
  117. }
  118. }
  119. return filename;
  120. }
  121. virtual boolean isDirectory(void) {
  122. return sdfatfile.isDirectory();
  123. }
  124. virtual File openNextFile(uint8_t mode=0) {
  125. SDFAT_FILE file = sdfatfile.openNextFile();
  126. if (file) return File(new SDFile(file));
  127. return File();
  128. }
  129. virtual void rewindDirectory(void) {
  130. sdfatfile.rewindDirectory();
  131. }
  132. using Print::write;
  133. private:
  134. SDFAT_FILE sdfatfile;
  135. char *filename;
  136. };
  137. class SDClass : public FS
  138. {
  139. public:
  140. SDClass() { }
  141. bool begin(uint8_t csPin = 10) {
  142. #ifdef BUILTIN_SDCARD
  143. if (csPin == BUILTIN_SDCARD) {
  144. return sdfs.begin(SdioConfig(FIFO_SDIO));
  145. //return sdfs.begin(SdioConfig(DMA_SDIO));
  146. }
  147. #endif
  148. return sdfs.begin(SdSpiConfig(csPin, SHARED_SPI, SD_SCK_MHZ(16)));
  149. //return sdfs.begin(csPin, SD_SCK_MHZ(24));
  150. }
  151. File open(const char *filepath, uint8_t mode = FILE_READ) {
  152. oflag_t flags = O_READ;
  153. if (mode == FILE_WRITE) flags = O_RDWR | O_CREAT | O_AT_END;
  154. else if (mode == FILE_WRITE_BEGIN) flags = O_RDWR | O_CREAT;
  155. SDFAT_FILE file = sdfs.open(filepath, flags);
  156. if (file) return File(new SDFile(file));
  157. return File();
  158. }
  159. bool exists(const char *filepath) {
  160. return sdfs.exists(filepath);
  161. }
  162. bool mkdir(const char *filepath) {
  163. return sdfs.mkdir(filepath);
  164. }
  165. bool rename(const char *oldfilepath, const char *newfilepath) {
  166. return sdfs.rename(oldfilepath, newfilepath);
  167. }
  168. bool remove(const char *filepath) {
  169. return sdfs.remove(filepath);
  170. }
  171. bool rmdir(const char *filepath) {
  172. return sdfs.rmdir(filepath);
  173. }
  174. uint64_t usedSize() {
  175. return (uint64_t)(sdfs.clusterCount() - sdfs.freeClusterCount())
  176. * (uint64_t)sdfs.bytesPerCluster();
  177. }
  178. uint64_t totalSize() {
  179. return (uint64_t)sdfs.clusterCount() * (uint64_t)sdfs.bytesPerCluster();
  180. }
  181. public: // allow access, so users can mix SD & SdFat APIs
  182. SDFAT_BASE sdfs;
  183. };
  184. extern SDClass SD;
  185. // do not expose these defines in Arduino sketches or other libraries
  186. #undef SDFAT_FILE
  187. #undef SDFAT_BASE
  188. #undef MAX_FILENAME_LEN
  189. #define SD_CARD_TYPE_SD1 0
  190. #define SD_CARD_TYPE_SD2 1
  191. #define SD_CARD_TYPE_SDHC 3
  192. class Sd2Card
  193. {
  194. public:
  195. bool init(uint32_t speed, uint8_t csPin) {
  196. return SD.begin(csPin);
  197. }
  198. uint8_t type() {
  199. return SD.sdfs.card()->type();
  200. }
  201. };
  202. class SdVolume
  203. {
  204. public:
  205. bool init(Sd2Card &card) {
  206. return SD.sdfs.vol() != nullptr;
  207. }
  208. uint8_t fatType() {
  209. return SD.sdfs.vol()->fatType();
  210. }
  211. uint32_t blocksPerCluster() {
  212. return SD.sdfs.vol()->sectorsPerCluster();
  213. }
  214. uint32_t clusterCount() {
  215. return SD.sdfs.vol()->clusterCount();
  216. }
  217. };
  218. #endif