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.

212 lines
5.0KB

  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. File::File()
  31. {
  32. type = FILE_INVALID;
  33. namestr[0] = 0;
  34. }
  35. File::~File(void)
  36. {
  37. close();
  38. }
  39. size_t File::write(uint8_t b)
  40. {
  41. return write(&b, 1);
  42. }
  43. size_t File::write(const uint8_t *buf, size_t size)
  44. {
  45. if (type != FILE_WRITE) {
  46. setWriteError();
  47. return 0;
  48. }
  49. // TODO: a lot of work....
  50. return 0;
  51. }
  52. int File::read()
  53. {
  54. uint8_t b;
  55. int ret = read(&b, 1);
  56. if (ret != 1) return -1;
  57. return b;
  58. }
  59. int File::peek()
  60. {
  61. uint32_t save_offset = offset;
  62. uint32_t save_cluster = current_cluster;
  63. uint8_t b;
  64. int ret = read(&b, 1);
  65. if (ret != 1) return -1;
  66. offset = save_offset;
  67. current_cluster = save_cluster;
  68. return b;
  69. }
  70. int File::available()
  71. {
  72. if (type > FILE_WRITE) return 0;
  73. uint32_t maxsize = length - offset;
  74. if (maxsize > 0x7FFFFFFF) maxsize = 0x7FFFFFFF;
  75. return maxsize;
  76. }
  77. void File::flush()
  78. {
  79. }
  80. int File::read(void *buf, uint32_t size)
  81. {
  82. if (type > FILE_WRITE) return 0;
  83. uint32_t maxsize = length - offset;
  84. if (size > maxsize) size = maxsize;
  85. if (size == 0) return 0;
  86. uint32_t count = 0;
  87. uint8_t *dest = (uint8_t *)buf;
  88. uint32_t lba = custer_to_sector(current_cluster);
  89. uint32_t sindex = cluster_offset(offset);
  90. //Serial.printf(" read %u at %u (%X)\n", size, offset, offset);
  91. lba += sindex >> 9;
  92. sindex &= 511;
  93. if (sindex) {
  94. // first read starts in the middle of a sector
  95. do {
  96. SDCache cache;
  97. sector_t *sector = cache.read(lba);
  98. if (!sector) {
  99. //Serial.println(" read err1, unable to read");
  100. return 0;
  101. }
  102. uint32_t n = 512 - sindex;
  103. if (size < n) {
  104. // read does not consume all of the sector
  105. memcpy(dest, sector->u8 + sindex, size);
  106. offset += size;
  107. //cache.priority(+1);
  108. return size;
  109. } else {
  110. // read fully consumes this sector
  111. memcpy(dest, sector->u8 + sindex, n);
  112. dest += n;
  113. count = n;
  114. offset += n;
  115. //cache.priority(-1);
  116. }
  117. } while (0);
  118. if (is_new_cluster(++lba)) {
  119. if (!next_cluster()) {
  120. //Serial.print(" read err1, next cluster");
  121. return count;
  122. }
  123. }
  124. if (count >= size) return count;
  125. }
  126. while (1) {
  127. // every read starts from the beginning of a sector
  128. do {
  129. SDCache cache;
  130. uint32_t n = size - count;
  131. if (n < 512) {
  132. // only part of a sector is needed
  133. sector_t *sector = cache.read(lba);
  134. if (!sector) {
  135. //Serial.println(" read err2, unable to read");
  136. return count;
  137. }
  138. memcpy(dest, sector->u8, n);
  139. offset += n;
  140. count += n;
  141. //cache.priority(+1);
  142. return count;
  143. } else {
  144. // a full sector is required
  145. if (!cache.read(lba, dest)) return count;
  146. dest += 512;
  147. offset += 512;
  148. count += 512;
  149. }
  150. } while (0);
  151. if (is_new_cluster(++lba)) {
  152. if (!next_cluster()) {
  153. //Serial.print(" read err2, next cluster");
  154. return count;
  155. }
  156. }
  157. if (count >= size) return count;
  158. }
  159. }
  160. bool File::seek(uint32_t pos)
  161. {
  162. if (type > FILE_WRITE) return false;
  163. if (pos > length) return false;
  164. //Serial.printf(" seek to %u\n", pos);
  165. uint32_t save_cluster = current_cluster;
  166. uint32_t count;
  167. // TODO: if moving to a new lba, lower cache priority
  168. signed int diff = (int)cluster_number(pos) - (int)cluster_number(offset);
  169. if (diff >= 0) {
  170. // seek fowards, 0 or more clusters from current position
  171. count = diff;
  172. } else {
  173. // seek backwards, need to start from beginning of file
  174. current_cluster = start_cluster;
  175. count = cluster_number(pos);
  176. }
  177. while (count > 0) {
  178. if (!next_cluster()) {
  179. current_cluster = save_cluster;
  180. return false;
  181. }
  182. count--;
  183. }
  184. offset = pos;
  185. return true;
  186. }
  187. void File::close()
  188. {
  189. type = FILE_INVALID;
  190. namestr[0] = 0;
  191. }
  192. #endif
  193. #endif