No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

237 líneas
6.3KB

  1. /* Optimized SD Library for Teensy 3.X
  2. * Copyright (c) 2015, Paul Stoffregen, paul@pjrc.com
  3. *
  4. * Development of this SD library was funded by PJRC.COM, LLC by sales of
  5. * Teensy and Audio Adaptor boards. Please support PJRC's efforts to develop
  6. * open source software by purchasing genuine Teensy or other PJRC products.
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining a copy
  9. * of this software and associated documentation files (the "Software"), to deal
  10. * in the Software without restriction, including without limitation the rights
  11. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. * copies of the Software, and to permit persons to whom the Software is
  13. * furnished to do so, subject to the following conditions:
  14. *
  15. * The above copyright notice, development funding notice, and this permission
  16. * notice shall be included in all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  21. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24. * THE SOFTWARE.
  25. */
  26. #if defined(__arm__)
  27. #include "SD_t3.h"
  28. #ifdef USE_TEENSY3_OPTIMIZED_CODE
  29. #define sector_t SDClass::sector_t
  30. #define fatdir_t SDClass::fatdir_t
  31. File SDClass::open(const char *path, uint8_t mode)
  32. {
  33. File root = rootDir;
  34. File f;
  35. if (mode > FILE_READ) return f; // TODO: writing not yet supported
  36. if (strcmp(path, "/") == 0) {
  37. f = rootDir;
  38. return f;
  39. }
  40. // TODO: this needs the path traversal feature
  41. //Serial.println("SDClass::open");
  42. //Serial.printf("rootDir.start_cluster = %d\n", rootDir.start_cluster);
  43. //Serial.printf("root.start_cluster = %d\n", root.start_cluster);
  44. root.find(path, &f);
  45. return f;
  46. }
  47. bool SDClass::exists(const char *path)
  48. {
  49. File f = open(path);
  50. return (bool)f;
  51. }
  52. File File::openNextFile(uint8_t mode)
  53. {
  54. File f;
  55. uint32_t lba, sector_offset, sector_index, sector_count;
  56. //Serial.print("File::openNextFile, offset=");
  57. //Serial.println(offset);
  58. if (mode > FILE_READ) return f; // TODO: writing not yet supported
  59. if (type == FILE_DIR_ROOT16) {
  60. //Serial.print(" fat16 dir");
  61. sector_offset = offset >> 9;
  62. lba = start_cluster + sector_offset;
  63. sector_count = length >> 9;
  64. } else if (type == FILE_DIR) {
  65. //Serial.print(" subdir");
  66. sector_offset = cluster_offset(offset) >> 9;
  67. lba = custer_to_sector(current_cluster) + sector_offset;
  68. sector_count = (1 << SDClass::sector2cluster);
  69. } else {
  70. return f;
  71. }
  72. //Serial.print(" sector_offset=");
  73. //Serial.println(sector_offset);
  74. //Serial.print(" lba=");
  75. //Serial.println(lba);
  76. //Serial.print(" sector_count=");
  77. //Serial.println(sector_count);
  78. sector_index = (offset >> 5) & 15;
  79. //Serial.print(" sector_index=");
  80. //Serial.println(sector_index);
  81. while (1) {
  82. SDCache sector;
  83. sector_t *s = sector.read(lba);
  84. if (!s) return f;
  85. fatdir_t *dirent = s->dir + sector_index;
  86. while (sector_index < 16) {
  87. //Serial.print(" sector_index=");
  88. //Serial.println(sector_index);
  89. if (dirent->attrib != ATTR_LONG_NAME) {
  90. uint8_t b0 = dirent->name[0];
  91. //Serial.print(" b0=");
  92. //Serial.println(b0);
  93. if (b0 == 0) return f;
  94. if (b0 != 0xE5 && memcmp(dirent->name, ". ", 11) != 0
  95. && memcmp(dirent->name, ".. ", 11) != 0) {
  96. f.init(dirent);
  97. sector.release();
  98. offset += 32;
  99. if (cluster_offset(offset) == 0) {
  100. next_cluster(); // TODO: handle error
  101. }
  102. return f;
  103. }
  104. }
  105. offset += 32;
  106. dirent++;
  107. sector_index++;
  108. }
  109. sector.release();
  110. sector_index = 0;
  111. if (++sector_offset >= sector_count) {
  112. if (type == FILE_DIR_ROOT16) {
  113. break;
  114. } else {
  115. if (!next_cluster()) break;
  116. lba = custer_to_sector(current_cluster);
  117. sector_offset = 0;
  118. }
  119. }
  120. }
  121. return f;
  122. }
  123. bool File::find(const char *filename, File *found)
  124. {
  125. bool find_unused = true;
  126. char name83[11];
  127. uint32_t lba, sector_count;
  128. //Serial.println("File::open");
  129. const char *f = filename;
  130. char *p = name83;
  131. while (p < name83 + 11) {
  132. char c = *f++;
  133. if (c == 0) {
  134. while (p < name83 + 11) *p++ = ' ';
  135. break;
  136. }
  137. if (c == '.') {
  138. while (p < name83 + 8) *p++ = ' ';
  139. continue;
  140. }
  141. if (c > 126) continue;
  142. if (c >= 'a' && c <= 'z') c -= 32;
  143. *p++ = c;
  144. }
  145. //Serial.print("name83 = ");
  146. //for (uint32_t i=0; i < 11; i++) {
  147. //Serial.printf(" %02X", name83[i]);
  148. //}
  149. //Serial.println();
  150. if (type == FILE_DIR_ROOT16) {
  151. lba = start_cluster;
  152. sector_count = length >> 9;
  153. } else if (type == FILE_DIR) {
  154. current_cluster = start_cluster;
  155. lba = custer_to_sector(start_cluster);
  156. sector_count = (1 << SDClass::sector2cluster);
  157. } else {
  158. return false; // not a directory
  159. }
  160. while (1) {
  161. for (uint32_t i=0; i < sector_count; i++) {
  162. SDCache sector;
  163. sector_t *s = sector.read(lba);
  164. if (!s) return false;
  165. fatdir_t *dirent = s->dir;
  166. for (uint32_t j=0; j < 16; j++) {
  167. if (dirent->attrib == ATTR_LONG_NAME) {
  168. // TODO: how to match long names?
  169. }
  170. if (memcmp(dirent->name, name83, 11) == 0) {
  171. //Serial.printf("found 8.3, j=%d\n", j);
  172. found->init(dirent);
  173. return true;
  174. }
  175. uint8_t b0 = dirent->name[0];
  176. if (find_unused && (b0 == 0 || b0 == 0xE5)) {
  177. found->dirent_lba = lba;
  178. found->dirent_index = j;
  179. find_unused = false;
  180. }
  181. if (b0 == 0) return false;
  182. offset += 32;
  183. dirent++;
  184. }
  185. lba++;
  186. }
  187. if (type == FILE_DIR_ROOT16) break;
  188. if (!next_cluster()) break;
  189. lba = custer_to_sector(current_cluster);
  190. //Serial.printf(" next lba = %d\n", lba);
  191. }
  192. return false;
  193. }
  194. void File::init(fatdir_t *dirent)
  195. {
  196. offset = 0;
  197. length = dirent->size;
  198. start_cluster = (dirent->cluster_high << 16) | dirent->cluster_low;
  199. current_cluster = start_cluster;
  200. type = (dirent->attrib & ATTR_DIRECTORY) ? FILE_DIR : FILE_READ;
  201. char *p = namestr;
  202. const char *s = dirent->name;
  203. for (int i=0; i < 8; i++) {
  204. if (*s == ' ') break;
  205. *p++ = *s++;
  206. }
  207. s = dirent->name + 8;
  208. if (*s != ' ') {
  209. *p++ = '.';
  210. *p++ = *s++;
  211. if (*s != ' ') *p++ = *s++;
  212. if (*s != ' ') *p++ = *s++;
  213. }
  214. *p = 0;
  215. //Serial.printf("File::init, cluster = %d, length = %d\n", start_cluster, length);
  216. }
  217. #endif
  218. #endif