Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  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 ret, parent = rootDir;
  34. //Serial.print("SD.open: ");
  35. //Serial.println(path);
  36. while (1) {
  37. while (*path == '/') path++;
  38. if (*path == 0) {
  39. // end of pathname is "/", use last subdir
  40. ret = parent;
  41. break;
  42. }
  43. File next;
  44. bool found = parent.find(path, &next);
  45. const char *p = path;
  46. do p++; while (*p != '/' && *p != 0);
  47. if (found) {
  48. //Serial.println(" open: found");
  49. if (*p == 0) {
  50. // found the file
  51. ret = next;
  52. break;
  53. }
  54. // found next subdir
  55. parent = next;
  56. path = p;
  57. } else {
  58. //Serial.print(" open: not found ");
  59. //Serial.println(path);
  60. if (*p == '/') break; // subdir doesn't exist
  61. // file doesn't exist
  62. if (mode == FILE_READ) break;
  63. // TODO: for writing, create the file
  64. break;
  65. }
  66. }
  67. return ret;
  68. }
  69. bool SDClass::exists(const char *path)
  70. {
  71. File f = open(path);
  72. return (bool)f;
  73. }
  74. File File::openNextFile(uint8_t mode)
  75. {
  76. File f;
  77. uint32_t lba, sector_offset, sector_index, sector_count;
  78. //Serial.print("File::openNextFile, offset=");
  79. //Serial.println(offset);
  80. if (mode > FILE_READ) return f; // TODO: writing not yet supported
  81. if (type == FILE_DIR_ROOT16) {
  82. //Serial.print(" fat16 dir");
  83. sector_offset = offset >> 9;
  84. lba = start_cluster + sector_offset;
  85. sector_count = length >> 9;
  86. } else if (type == FILE_DIR) {
  87. //Serial.print(" subdir");
  88. sector_offset = cluster_offset(offset) >> 9;
  89. lba = custer_to_sector(current_cluster) + sector_offset;
  90. sector_count = (1 << SDClass::sector2cluster);
  91. } else {
  92. return f;
  93. }
  94. //Serial.print(" sector_offset=");
  95. //Serial.println(sector_offset);
  96. //Serial.print(" lba=");
  97. //Serial.println(lba);
  98. //Serial.print(" sector_count=");
  99. //Serial.println(sector_count);
  100. sector_index = (offset >> 5) & 15;
  101. //Serial.print(" sector_index=");
  102. //Serial.println(sector_index);
  103. while (1) {
  104. SDCache sector;
  105. sector_t *s = sector.read(lba);
  106. if (!s) return f;
  107. fatdir_t *dirent = s->dir + sector_index;
  108. while (sector_index < 16) {
  109. //Serial.print(" sector_index=");
  110. //Serial.println(sector_index);
  111. if (dirent->attrib != ATTR_LONG_NAME) {
  112. uint8_t b0 = dirent->name[0];
  113. //Serial.print(" b0=");
  114. //Serial.println(b0);
  115. if (b0 == 0) return f;
  116. if (b0 != 0xE5 && memcmp(dirent->name, ". ", 11) != 0
  117. && memcmp(dirent->name, ".. ", 11) != 0) {
  118. f.init(dirent);
  119. sector.release();
  120. offset += 32;
  121. if (cluster_offset(offset) == 0) {
  122. next_cluster(); // TODO: handle error
  123. }
  124. return f;
  125. }
  126. }
  127. offset += 32;
  128. dirent++;
  129. sector_index++;
  130. }
  131. sector.release();
  132. sector_index = 0;
  133. if (++sector_offset >= sector_count) {
  134. if (type == FILE_DIR_ROOT16) {
  135. break;
  136. } else {
  137. if (!next_cluster()) break;
  138. lba = custer_to_sector(current_cluster);
  139. sector_offset = 0;
  140. }
  141. }
  142. }
  143. return f;
  144. }
  145. bool File::find(const char *filename, File *found)
  146. {
  147. bool find_unused = true;
  148. char name83[11];
  149. uint32_t lba, sector_count;
  150. //Serial.println("File::open");
  151. const char *f = filename;
  152. if (*f == 0) return false;
  153. char *p = name83;
  154. while (p < name83 + 11) {
  155. char c = *f++;
  156. if (c == 0 || c == '/') {
  157. while (p < name83 + 11) *p++ = ' ';
  158. break;
  159. }
  160. if (c == '.') {
  161. while (p < name83 + 8) *p++ = ' ';
  162. continue;
  163. }
  164. if (c > 126) continue;
  165. if (c >= 'a' && c <= 'z') c -= 32;
  166. *p++ = c;
  167. }
  168. //Serial.print("name83 = ");
  169. //for (uint32_t i=0; i < 11; i++) {
  170. //Serial.printf(" %02X", name83[i]);
  171. //}
  172. //Serial.println();
  173. if (type == FILE_DIR_ROOT16) {
  174. lba = start_cluster;
  175. sector_count = length >> 9;
  176. } else if (type == FILE_DIR) {
  177. current_cluster = start_cluster;
  178. lba = custer_to_sector(start_cluster);
  179. sector_count = (1 << SDClass::sector2cluster);
  180. } else {
  181. return false; // not a directory
  182. }
  183. while (1) {
  184. for (uint32_t i=0; i < sector_count; i++) {
  185. SDCache sector;
  186. sector_t *s = sector.read(lba);
  187. if (!s) return false;
  188. fatdir_t *dirent = s->dir;
  189. for (uint32_t j=0; j < 16; j++) {
  190. if (dirent->attrib == ATTR_LONG_NAME) {
  191. // TODO: how to match long names?
  192. }
  193. if (memcmp(dirent->name, name83, 11) == 0) {
  194. //Serial.printf("found 8.3, j=%d\n", j);
  195. found->init(dirent);
  196. return true;
  197. }
  198. uint8_t b0 = dirent->name[0];
  199. if (find_unused && (b0 == 0 || b0 == 0xE5)) {
  200. found->dirent_lba = lba;
  201. found->dirent_index = j;
  202. find_unused = false;
  203. }
  204. if (b0 == 0) return false;
  205. offset += 32;
  206. dirent++;
  207. }
  208. lba++;
  209. }
  210. if (type == FILE_DIR_ROOT16) break;
  211. if (!next_cluster()) break;
  212. lba = custer_to_sector(current_cluster);
  213. //Serial.printf(" next lba = %d\n", lba);
  214. }
  215. return false;
  216. }
  217. void File::init(fatdir_t *dirent)
  218. {
  219. offset = 0;
  220. length = dirent->size;
  221. start_cluster = (dirent->cluster_high << 16) | dirent->cluster_low;
  222. current_cluster = start_cluster;
  223. type = (dirent->attrib & ATTR_DIRECTORY) ? FILE_DIR : FILE_READ;
  224. char *p = namestr;
  225. const char *s = dirent->name;
  226. for (int i=0; i < 8; i++) {
  227. if (*s == ' ') break;
  228. *p++ = *s++;
  229. }
  230. s = dirent->name + 8;
  231. if (*s != ' ') {
  232. *p++ = '.';
  233. *p++ = *s++;
  234. if (*s != ' ') *p++ = *s++;
  235. if (*s != ' ') *p++ = *s++;
  236. }
  237. *p = 0;
  238. //Serial.printf("File::init, cluster = %d, length = %d\n", start_cluster, length);
  239. }
  240. #endif
  241. #endif