PageRenderTime 60ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/OpenSprinkler Controller/software/arduino-code/libraries/OpenSprinklerGen2/tinyFAT.cpp

https://github.com/sherckuith/opensprinkler
C++ | 952 lines | 829 code | 91 blank | 32 comment | 144 complexity | dbc9e4409990cca8658b9b148807eea0 MD5 | raw file
Possible License(s): GPL-2.0
  1. /*
  2. tinyFAT.cpp - Arduino library support FAT16 on SD cards
  3. Copyright (C)2010-2011 Henning Karlsen. All right reserved
  4. You can find the latest version of the library at
  5. http://www.henningkarlsen.com/electronics
  6. This library has been made to easily use SD card with the Arduino.
  7. If you make any modifications or improvements to the code, I would appreciate
  8. that you share the code with me so that I might include it in the next release.
  9. I can be contacted through http://www.henningkarlsen.com/electronics/contact.php
  10. This library is free software; you can redistribute it and/or
  11. modify it under the terms of the GNU Lesser General Public
  12. License as published by the Free Software Foundation; either
  13. version 2.1 of the License, or (at your option) any later version.
  14. This library is distributed in the hope that it will be useful,
  15. but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. Lesser General Public License for more details.
  18. You should have received a copy of the GNU Lesser General Public
  19. License along with this library; if not, write to the Free Software
  20. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  21. */
  22. #include "tinyFAT.h"
  23. #include <mmc.h>
  24. /* Public */
  25. tinyFAT::tinyFAT()
  26. {
  27. _inited=false;
  28. }
  29. byte tinyFAT::initFAT(byte speed)
  30. {
  31. mmc::initialize(speed);
  32. // Read MBR
  33. if (RES_OK == mmc::readSector(buffer, 0))
  34. {
  35. if ((buffer[0x01FE]==0x55) && (buffer[0x01FF]==0xAA))
  36. {
  37. MBR.part1Type=buffer[450];
  38. MBR.part1Start = uint16_t(buffer[454])+(uint16_t(buffer[455])<<8)+(uint32_t(buffer[456])<<16)+(uint32_t(buffer[457])<<24);
  39. MBR.part1Size = uint16_t(buffer[458])+(uint16_t(buffer[459])<<8)+(uint32_t(buffer[460])<<16)+(uint32_t(buffer[461])<<24);
  40. }
  41. else
  42. {
  43. return ERROR_MBR_SIGNATURE;
  44. }
  45. }
  46. else
  47. return ERROR_MBR_READ_ERROR;
  48. if ((MBR.part1Type!=0x04) && (MBR.part1Type!=0x06) && (MBR.part1Type!=0x86))
  49. {
  50. return ERROR_MBR_INVALID_FS;
  51. }
  52. // Read Boot Sector
  53. if (RES_OK == mmc::readSector(buffer, MBR.part1Start))
  54. {
  55. if ((buffer[0x01FE]==0x55) && (buffer[0x01FF]==0xAA))
  56. {
  57. BS.sectorsPerCluster = buffer[0x0D];
  58. BS.reservedSectors = uint16_t(buffer[0x0E])+(uint16_t(buffer[0x0F])<<8);
  59. BS.fatCopies = buffer[0x10];
  60. BS.rootDirectoryEntries = uint16_t(buffer[0x11])+(uint16_t(buffer[0x12])<<8);
  61. BS.totalFilesystemSectors = uint16_t(buffer[0x13])+(uint16_t(buffer[0x14])<<8);
  62. if (BS.totalFilesystemSectors==0)
  63. BS.totalFilesystemSectors = uint16_t(buffer[0x20])+(uint16_t(buffer[0x21])<<8)+(uint32_t(buffer[0x22])<<16)+(uint32_t(buffer[0x23])<<24);
  64. BS.sectorsPerFAT = uint16_t(buffer[0x16])+(uint16_t(buffer[0x17])<<8);
  65. BS.hiddenSectors = uint16_t(buffer[0x1C])+(uint16_t(buffer[0x1D])<<8)+(uint32_t(buffer[0x1E])<<16)+(uint32_t(buffer[0x1F])<<24);
  66. BS.partitionSerialNum = uint16_t(buffer[0x27])+(uint16_t(buffer[0x28])<<8)+(uint32_t(buffer[0x29])<<16)+(uint32_t(buffer[0x2A])<<24);
  67. firstDirSector = MBR.part1Start + BS.reservedSectors + (BS.fatCopies * BS.sectorsPerFAT);
  68. BS.fat1Start = MBR.part1Start + BS.reservedSectors;
  69. BS.fat2Start = BS.fat1Start + BS.sectorsPerFAT;
  70. BS.partitionSize = float((MBR.part1Size*512)/float(1048576));
  71. }
  72. else
  73. return ERROR_BOOTSEC_SIGNATURE;
  74. }
  75. else
  76. return ERROR_BOOTSEC_READ_ERROR;
  77. _inited=true;
  78. return 0x00;
  79. }
  80. byte tinyFAT::findFirstFile(_directory_entry *tempDE)
  81. {
  82. unsigned long currSec = firstDirSector;
  83. word offset = 0;
  84. DEcnt=0;
  85. mmc::readSector(buffer, currSec);
  86. if (buffer[0]==0x00)
  87. return ERROR_NO_MORE_FILES;
  88. else
  89. {
  90. while ((buffer[offset + 0x0B] & 0x08) || (buffer[offset + 0x0B] & 0x10) || (buffer[offset]==0xE5))
  91. {
  92. offset+=32;
  93. DEcnt++;
  94. if (offset==512)
  95. {
  96. currSec++;
  97. mmc::readSector(buffer, currSec);
  98. offset = 0;
  99. }
  100. if (buffer[offset]==0x00)
  101. return ERROR_NO_MORE_FILES;
  102. }
  103. for (int i=0; i<8; i++)
  104. {
  105. tempDE->filename[i] = buffer[i+offset];
  106. }
  107. for (int i=0; i<3; i++)
  108. {
  109. tempDE->fileext[i] = buffer[i+0x08+offset];
  110. }
  111. tempDE->filename[8] = 0;
  112. tempDE->fileext[3] = 0;
  113. tempDE->attributes = buffer[0x0B + offset];
  114. tempDE->time = uint16_t(buffer[0x0E + offset]) + (uint16_t(buffer[0x0F + offset])<<8);
  115. tempDE->date = uint16_t(buffer[0x10 + offset]) + (uint16_t(buffer[0x11 + offset])<<8);
  116. tempDE->startCluster = uint16_t(buffer[0x1A + offset]) + (uint16_t(buffer[0x1B + offset])<<8);
  117. tempDE->fileSize = uint16_t(buffer[offset + 0x1C]) | (uint16_t(buffer[offset + 0x1D])<<8) | (uint32_t(buffer[offset + 0x1E])<<16) | (uint32_t(buffer[offset + 0x1F])<<24);
  118. DEcnt++;
  119. return NO_ERROR;
  120. }
  121. }
  122. byte tinyFAT::findNextFile(_directory_entry *tempDE)
  123. {
  124. unsigned long currSec = firstDirSector;
  125. word offset = DEcnt*32;
  126. while (offset>=512)
  127. {
  128. currSec++;
  129. offset-=512;
  130. }
  131. mmc::readSector(buffer, currSec);
  132. if (buffer[offset]==0x00)
  133. return ERROR_NO_MORE_FILES;
  134. else
  135. {
  136. while ((buffer[offset + 0x0B] & 0x08) || (buffer[offset + 0x0B] & 0x10) || (buffer[offset]==0xE5))
  137. {
  138. offset+=32;
  139. DEcnt++;
  140. if (offset==512)
  141. {
  142. currSec++;
  143. mmc::readSector(buffer, currSec);
  144. offset = 0;
  145. }
  146. if (buffer[offset]==0x00)
  147. return ERROR_NO_MORE_FILES;
  148. }
  149. for (int i=0; i<8; i++)
  150. {
  151. tempDE->filename[i] = buffer[i+offset];
  152. }
  153. for (int i=0; i<3; i++)
  154. {
  155. tempDE->fileext[i] = buffer[i+0x08+offset];
  156. }
  157. tempDE->filename[8] = 0;
  158. tempDE->fileext[3] = 0;
  159. tempDE->attributes = buffer[0x0B + offset];
  160. tempDE->time = uint16_t(buffer[0x0E + offset]) + (uint16_t(buffer[0x0F + offset])<<8);
  161. tempDE->date = uint16_t(buffer[0x10 + offset]) + (uint16_t(buffer[0x11 + offset])<<8);
  162. tempDE->startCluster = uint16_t(buffer[0x1A + offset]) + (uint16_t(buffer[0x1B + offset])<<8);
  163. tempDE->fileSize = uint16_t(buffer[offset + 0x1C]) | (uint16_t(buffer[offset + 0x1D])<<8) | (uint32_t(buffer[offset + 0x1E])<<16) | (uint32_t(buffer[offset + 0x1F])<<24);
  164. DEcnt++;
  165. return NO_ERROR;
  166. }
  167. }
  168. byte tinyFAT::openFile(char *fn, byte mode)
  169. {
  170. _directory_entry tmpDE;
  171. char tmpFN[13];
  172. byte res;
  173. int i, j;
  174. if (currFile.filename[0]!=0x00)
  175. return ERROR_ANOTHER_FILE_OPEN;
  176. for (i=0; i<strlen(fn); i++)
  177. fn[i]=uCase(fn[i]);
  178. res=findFirstFile(&tmpDE);
  179. if (res==ERROR_NO_MORE_FILES)
  180. return ERROR_FILE_NOT_FOUND;
  181. else
  182. {
  183. i=0;
  184. j=0;
  185. while ((tmpDE.filename[i]!=0x20) and (i<8))
  186. {
  187. tmpFN[i]=tmpDE.filename[i];
  188. i++;
  189. }
  190. tmpFN[i]='.';
  191. i++;
  192. while ((tmpDE.fileext[j]!=0x20) and (j<3))
  193. {
  194. tmpFN[i]=tmpDE.fileext[j];
  195. i++;
  196. j++;
  197. }
  198. tmpFN[i]=0x00;
  199. if (!strcmp(tmpFN,fn))
  200. {
  201. for (i=0; i<13; i++)
  202. currFile.filename[i]=tmpFN[i];
  203. currFile.currentCluster=tmpDE.startCluster;
  204. currFile.fileSize=tmpDE.fileSize;
  205. currFile.currentPos=0;
  206. currFile.fileMode=mode;
  207. return NO_ERROR;
  208. }
  209. while (res==NO_ERROR)
  210. {
  211. res = file.findNextFile(&tmpDE);
  212. if (res==NO_ERROR)
  213. {
  214. i=0;
  215. j=0;
  216. while ((tmpDE.filename[i]!=0x20) and (i<8))
  217. {
  218. tmpFN[i]=tmpDE.filename[i];
  219. i++;
  220. }
  221. tmpFN[i]='.';
  222. i++;
  223. while ((tmpDE.fileext[j]!=0x20) and (j<3))
  224. {
  225. tmpFN[i]=tmpDE.fileext[j];
  226. i++;
  227. j++;
  228. }
  229. tmpFN[i]=0x00;
  230. if (!strcmp(tmpFN,fn))
  231. {
  232. for (i=0; i<13; i++)
  233. currFile.filename[i]=tmpFN[i];
  234. currFile.currentCluster=tmpDE.startCluster;
  235. currFile.fileSize=tmpDE.fileSize;
  236. currFile.currentPos=0;
  237. currFile.fileMode=mode;
  238. return NO_ERROR;
  239. }
  240. }
  241. }
  242. }
  243. return ERROR_FILE_NOT_FOUND;
  244. }
  245. uint16_t tinyFAT::readBinary()
  246. {
  247. uint32_t sec;
  248. uint8_t status_;
  249. if (currFile.fileMode==FILEMODE_BINARY)
  250. {
  251. if ((currFile.currentPos==0) and (currFile.currentCluster==0))
  252. return FILE_IS_EMPTY;
  253. if (((currFile.currentPos % BS.sectorsPerCluster)==0) and (currFile.currentPos>0))
  254. currFile.currentCluster=findNextCluster(currFile.currentCluster);
  255. sec=BS.hiddenSectors + (uint32_t)BS.reservedSectors + ((uint32_t)BS.fatCopies*(uint32_t)BS.sectorsPerFAT)+(((uint32_t)BS.rootDirectoryEntries*32)/512)+((uint32_t)currFile.currentCluster-2)*(uint32_t)BS.sectorsPerCluster+((uint32_t)currFile.currentPos % (uint32_t)BS.sectorsPerCluster);
  256. status_=mmc::readSector(buffer, sec);
  257. if (status_)
  258. {
  259. return status_;
  260. }
  261. currFile.currentPos++;
  262. if ((currFile.currentPos*512)>currFile.fileSize)
  263. {
  264. return (currFile.fileSize-((currFile.currentPos-1)*512));
  265. }
  266. else
  267. {
  268. return 512;
  269. }
  270. }
  271. else
  272. if (currFile.fileMode==0x00)
  273. return ERROR_NO_FILE_OPEN;
  274. else
  275. return ERROR_WRONG_FILEMODE;
  276. }
  277. uint16_t tinyFAT::readLn(char *st, int bufSize)
  278. {
  279. uint32_t sec;
  280. int bufIndex=0;
  281. for (int i=0; i<=bufSize; i++)
  282. st[i]=0;
  283. if (currFile.fileMode==FILEMODE_TEXT_READ)
  284. {
  285. if ((currFile.currentPos==0) and (currFile.currentCluster==0))
  286. return FILE_IS_EMPTY;
  287. sec=((uint32_t)BS.reservedSectors+((uint32_t)BS.fatCopies*(uint32_t)BS.sectorsPerFAT)+(((uint32_t)BS.rootDirectoryEntries*32)/512)+(((uint32_t)currFile.currentCluster-2)*(uint32_t)BS.sectorsPerCluster)+BS.hiddenSectors)+(((uint32_t)currFile.currentPos/512) % (uint32_t)BS.sectorsPerCluster);
  288. mmc::readSector(buffer, sec);
  289. while ((currFile.currentPos<currFile.fileSize) and (buffer[currFile.currentPos % 512]!=10) and (buffer[currFile.currentPos % 512]!=13) and (bufIndex<bufSize))
  290. {
  291. st[bufIndex]=buffer[currFile.currentPos % 512];
  292. bufIndex++;
  293. currFile.currentPos++;
  294. if ((currFile.currentPos % 512) == 0)
  295. {
  296. sec++;
  297. if (((currFile.currentPos/512) % BS.sectorsPerCluster)==0)
  298. {
  299. currFile.currentCluster=findNextCluster(currFile.currentCluster);
  300. sec=((uint32_t)BS.reservedSectors+((uint32_t)BS.fatCopies*(uint32_t)BS.sectorsPerFAT)+(((uint32_t)BS.rootDirectoryEntries*32)/512)+(((uint32_t)currFile.currentCluster-2)*(uint32_t)BS.sectorsPerCluster)+BS.hiddenSectors);
  301. }
  302. mmc::readSector(buffer, sec);
  303. }
  304. }
  305. if (currFile.currentPos>=currFile.fileSize)
  306. return EOF;
  307. else if ((buffer[(currFile.currentPos % 512)]==13) and (buffer[(currFile.currentPos % 512)+1]==10))
  308. {
  309. currFile.currentPos+=2;
  310. return bufIndex;
  311. }
  312. else if ((buffer[(currFile.currentPos % 512)]==13) or (buffer[(currFile.currentPos % 512)]==10))
  313. {
  314. currFile.currentPos++;
  315. return bufIndex;
  316. }
  317. else
  318. return BUFFER_OVERFLOW;
  319. }
  320. else
  321. if (currFile.fileMode==0x00)
  322. return ERROR_NO_FILE_OPEN;
  323. else
  324. return ERROR_WRONG_FILEMODE;
  325. }
  326. uint16_t tinyFAT::writeLn(char *st)
  327. {
  328. unsigned long currSec = firstDirSector;
  329. uint16_t nextCluster = 0;
  330. word offset = -32;
  331. uint32_t sec;
  332. char tmpFN[13];
  333. int i, j;
  334. int bufIndex=0;
  335. boolean done=false;
  336. if (currFile.fileMode==FILEMODE_TEXT_WRITE)
  337. {
  338. if (currFile.currentCluster==0)
  339. {
  340. currFile.currentCluster=findFreeCluster();
  341. mmc::readSector(buffer, currSec);
  342. while (!done)
  343. {
  344. offset+=32;
  345. if (offset==512)
  346. {
  347. currSec++;
  348. mmc::readSector(buffer, currSec);
  349. offset = 0;
  350. }
  351. j=0;
  352. for (int i=0; i<8; i++)
  353. {
  354. if (buffer[i+offset]!=0x20)
  355. {
  356. tmpFN[j]=buffer[i+offset];
  357. j++;
  358. }
  359. }
  360. tmpFN[j]='.';
  361. j++;
  362. for (int i=0; i<3; i++)
  363. {
  364. if (buffer[i+0x08+offset]!=0x20)
  365. {
  366. tmpFN[j]=buffer[i+0x08+offset];
  367. j++;
  368. }
  369. }
  370. tmpFN[j]=0x00;
  371. if (!strcmp(tmpFN, currFile.filename))
  372. {
  373. buffer[offset+0x1A]=currFile.currentCluster & 0xFF;
  374. buffer[offset+0x1B]=currFile.currentCluster>>8;
  375. mmc::writeSector(buffer, currSec);
  376. mmc::readSector(buffer, BS.fat1Start+(currFile.currentCluster>>8));
  377. buffer[(currFile.currentCluster & 0xFF)*2]=0xFF;
  378. buffer[((currFile.currentCluster & 0xFF)*2)+1]=0xFF;
  379. mmc::writeSector(buffer, BS.fat1Start+(currFile.currentCluster>>8));
  380. mmc::readSector(buffer, BS.fat2Start+(currFile.currentCluster>>8));
  381. buffer[(currFile.currentCluster & 0xFF)*2]=0xFF;
  382. buffer[((currFile.currentCluster & 0xFF)*2)+1]=0xFF;
  383. mmc::writeSector(buffer, BS.fat2Start+(currFile.currentCluster>>8));
  384. done=true;
  385. }
  386. }
  387. }
  388. if ((((currFile.fileSize % 512)+strlen(st))<=510) and ((currFile.fileSize % (long(BS.sectorsPerCluster)*512)!=0) or (currFile.fileSize==0)))
  389. {
  390. currSec=(BS.reservedSectors+(BS.fatCopies*BS.sectorsPerFAT)+((BS.rootDirectoryEntries*32)/512)+((currFile.currentCluster-2)*BS.sectorsPerCluster)+BS.hiddenSectors)+((currFile.fileSize/512) % BS.sectorsPerCluster);
  391. mmc::readSector(buffer, currSec);
  392. for (int i=0; i<strlen(st); i++)
  393. buffer[(currFile.fileSize%512)+i]=st[i];
  394. buffer[(currFile.fileSize%512)+strlen(st)]=0x0D;
  395. buffer[(currFile.fileSize%512)+strlen(st)+1]=0x0A;
  396. mmc::writeSector(buffer, currSec);
  397. }
  398. else
  399. {
  400. currSec=(BS.reservedSectors+(BS.fatCopies*BS.sectorsPerFAT)+((BS.rootDirectoryEntries*32)/512)+((currFile.currentCluster-2)*BS.sectorsPerCluster)+BS.hiddenSectors)+((currFile.fileSize/512) % BS.sectorsPerCluster);
  401. if ((currFile.fileSize%512)!=0)
  402. {
  403. mmc::readSector(buffer, currSec);
  404. for (int i=0; i<(512-(currFile.fileSize%512)); i++)
  405. {
  406. buffer[(currFile.fileSize%512)+i]=st[i];
  407. bufIndex++;
  408. }
  409. mmc::writeSector(buffer, currSec);
  410. currSec++;
  411. }
  412. else
  413. bufIndex=0;
  414. if (((currSec-(BS.reservedSectors+(BS.fatCopies*BS.sectorsPerFAT)+((BS.rootDirectoryEntries*32)/512)+BS.hiddenSectors)) % BS.sectorsPerCluster)==0)
  415. {
  416. nextCluster=findFreeCluster();
  417. mmc::readSector(buffer, BS.fat1Start+(currFile.currentCluster>>8));
  418. buffer[(currFile.currentCluster & 0xFF)*2]=nextCluster & 0xFF;
  419. buffer[((currFile.currentCluster & 0xFF)*2)+1]=nextCluster>>8;
  420. if ((nextCluster>>8)==(currFile.currentCluster>>8))
  421. {
  422. buffer[(nextCluster & 0xFF)*2]=0xFF;
  423. buffer[((nextCluster & 0xFF)*2)+1]=0xFF;
  424. mmc::writeSector(buffer, BS.fat1Start+(currFile.currentCluster>>8));
  425. }
  426. else
  427. {
  428. mmc::writeSector(buffer, BS.fat1Start+(currFile.currentCluster>>8));
  429. mmc::readSector(buffer, BS.fat1Start+(nextCluster>>8));
  430. buffer[(nextCluster & 0xFF)*2]=0xFF;
  431. buffer[((nextCluster & 0xFF)*2)+1]=0xFF;
  432. mmc::writeSector(buffer, BS.fat1Start+(nextCluster>>8));
  433. }
  434. mmc::readSector(buffer, BS.fat2Start+(currFile.currentCluster>>8));
  435. buffer[(currFile.currentCluster & 0xFF)*2]=nextCluster & 0xFF;
  436. buffer[((currFile.currentCluster & 0xFF)*2)+1]=nextCluster>>8;
  437. if ((nextCluster>>8)==(currFile.currentCluster>>8))
  438. {
  439. buffer[(nextCluster & 0xFF)*2]=0xFF;
  440. buffer[((nextCluster & 0xFF)*2)+1]=0xFF;
  441. mmc::writeSector(buffer, BS.fat2Start+(currFile.currentCluster>>8));
  442. }
  443. else
  444. {
  445. mmc::writeSector(buffer, BS.fat2Start+(currFile.currentCluster>>8));
  446. mmc::readSector(buffer, BS.fat2Start+(nextCluster>>8));
  447. buffer[(nextCluster & 0xFF)*2]=0xFF;
  448. buffer[((nextCluster & 0xFF)*2)+1]=0xFF;
  449. mmc::writeSector(buffer, BS.fat2Start+(nextCluster>>8));
  450. }
  451. currFile.currentCluster=nextCluster;
  452. currSec=(BS.reservedSectors+(BS.fatCopies*BS.sectorsPerFAT)+((BS.rootDirectoryEntries*32)/512)+((currFile.currentCluster-2)*BS.sectorsPerCluster)+BS.hiddenSectors);
  453. }
  454. mmc::readSector(buffer, currSec);
  455. for (int i=0; i<strlen(st)-bufIndex; i++)
  456. buffer[i]=st[i+bufIndex];
  457. buffer[strlen(st)-bufIndex]=0x0D;
  458. buffer[strlen(st)-bufIndex+1]=0x0A;
  459. mmc::writeSector(buffer, currSec);
  460. }
  461. currFile.fileSize+=(strlen(st)+2);
  462. currSec=firstDirSector;
  463. offset=-32;
  464. done=false;
  465. mmc::readSector(buffer, currSec);
  466. while (!done)
  467. {
  468. offset+=32;
  469. if (offset==512)
  470. {
  471. currSec++;
  472. mmc::readSector(buffer, currSec);
  473. offset = 0;
  474. }
  475. j=0;
  476. for (int i=0; i<8; i++)
  477. {
  478. if (buffer[i+offset]!=0x20)
  479. {
  480. tmpFN[j]=buffer[i+offset];
  481. j++;
  482. }
  483. }
  484. tmpFN[j]='.';
  485. j++;
  486. for (int i=0; i<3; i++)
  487. {
  488. if (buffer[i+0x08+offset]!=0x20)
  489. {
  490. tmpFN[j]=buffer[i+0x08+offset];
  491. j++;
  492. }
  493. }
  494. tmpFN[j]=0x00;
  495. if (!strcmp(tmpFN, currFile.filename))
  496. {
  497. buffer[offset+0x1C]=currFile.fileSize & 0xFF;
  498. buffer[offset+0x1D]=(currFile.fileSize & 0xFF00)>>8;
  499. buffer[offset+0x1E]=(currFile.fileSize & 0xFF0000)>>16;
  500. buffer[offset+0x1F]=currFile.fileSize>>24;
  501. mmc::writeSector(buffer, currSec);
  502. done=true;
  503. }
  504. }
  505. return NO_ERROR;
  506. }
  507. else
  508. if (currFile.fileMode==0x00)
  509. return ERROR_NO_FILE_OPEN;
  510. else
  511. return ERROR_WRONG_FILEMODE;
  512. }
  513. void tinyFAT::closeFile()
  514. {
  515. currFile.filename[0]=0x00;
  516. currFile.fileMode=0x00;
  517. }
  518. boolean tinyFAT::exists(char *fn)
  519. {
  520. _directory_entry tmpDE;
  521. char tmpFN[13];
  522. byte res;
  523. int i, j;
  524. for (i=0; i<strlen(fn); i++)
  525. fn[i]=uCase(fn[i]);
  526. res=findFirstFile(&tmpDE);
  527. if (res==ERROR_NO_MORE_FILES)
  528. return false;
  529. else
  530. {
  531. i=0;
  532. j=0;
  533. while ((tmpDE.filename[i]!=0x20) and (i<8))
  534. {
  535. tmpFN[i]=tmpDE.filename[i];
  536. i++;
  537. }
  538. tmpFN[i]='.';
  539. i++;
  540. while ((tmpDE.fileext[j]!=0x20) and (j<3))
  541. {
  542. tmpFN[i]=tmpDE.fileext[j];
  543. i++;
  544. j++;
  545. }
  546. tmpFN[i]=0x00;
  547. if (!strcmp(tmpFN,fn))
  548. return true;
  549. while (res==NO_ERROR)
  550. {
  551. res = file.findNextFile(&tmpDE);
  552. if (res==NO_ERROR)
  553. {
  554. i=0;
  555. j=0;
  556. while ((tmpDE.filename[i]!=0x20) and (i<8))
  557. {
  558. tmpFN[i]=tmpDE.filename[i];
  559. i++;
  560. }
  561. tmpFN[i]='.';
  562. i++;
  563. while ((tmpDE.fileext[j]!=0x20) and (j<3))
  564. {
  565. tmpFN[i]=tmpDE.fileext[j];
  566. i++;
  567. j++;
  568. }
  569. tmpFN[i]=0x00;
  570. if (!strcmp(tmpFN,fn))
  571. return true;
  572. }
  573. }
  574. }
  575. return false;
  576. }
  577. boolean tinyFAT::rename(char *fn1, char *fn2)
  578. {
  579. unsigned long currSec = firstDirSector;
  580. word offset = -32;
  581. char tmpFN[13];
  582. int i, j;
  583. boolean done=false;
  584. for (i=0; i<strlen(fn1); i++)
  585. fn1[i]=uCase(fn1[i]);
  586. for (i=0; i<strlen(fn2); i++)
  587. {
  588. fn2[i]=uCase(fn2[i]);
  589. if (!validChar(fn2[i]))
  590. return false;
  591. }
  592. if (exists(fn1))
  593. {
  594. mmc::readSector(buffer, currSec);
  595. while (!done)
  596. {
  597. offset+=32;
  598. if (offset==512)
  599. {
  600. currSec++;
  601. mmc::readSector(buffer, currSec);
  602. offset = 0;
  603. }
  604. j=0;
  605. for (int i=0; i<8; i++)
  606. {
  607. if (buffer[i+offset]!=0x20)
  608. {
  609. tmpFN[j]=buffer[i+offset];
  610. j++;
  611. }
  612. }
  613. tmpFN[j]='.';
  614. j++;
  615. for (int i=0; i<3; i++)
  616. {
  617. if (buffer[i+0x08+offset]!=0x20)
  618. {
  619. tmpFN[j]=buffer[i+0x08+offset];
  620. j++;
  621. }
  622. }
  623. tmpFN[j]=0x00;
  624. if (!strcmp(tmpFN, fn1))
  625. {
  626. for (int i=0; i<11; i++)
  627. {
  628. buffer[i+offset]=0x20;
  629. }
  630. j=0;
  631. for (int i=0; i<strlen(fn2); i++)
  632. {
  633. if (fn2[i]=='.')
  634. j=8;
  635. else
  636. {
  637. buffer[j+offset]=fn2[i];
  638. j++;
  639. }
  640. }
  641. mmc::writeSector(buffer, currSec);
  642. done=true;
  643. }
  644. }
  645. return true;
  646. }
  647. else
  648. return false;
  649. }
  650. boolean tinyFAT::delFile(char *fn)
  651. {
  652. unsigned long currSec = firstDirSector;
  653. uint16_t firstCluster, currCluster, nextCluster;
  654. word offset = -32;
  655. char tmpFN[13];
  656. int j;
  657. boolean done=false;
  658. for (int i=0; i<strlen(fn); i++)
  659. fn[i]=uCase(fn[i]);
  660. if (exists(fn))
  661. {
  662. mmc::readSector(buffer, currSec);
  663. while (!done)
  664. {
  665. offset+=32;
  666. if (offset==512)
  667. {
  668. currSec++;
  669. mmc::readSector(buffer, currSec);
  670. offset = 0;
  671. }
  672. j=0;
  673. for (int i=0; i<8; i++)
  674. {
  675. if (buffer[i+offset]!=0x20)
  676. {
  677. tmpFN[j]=buffer[i+offset];
  678. j++;
  679. }
  680. }
  681. tmpFN[j]='.';
  682. j++;
  683. for (int i=0; i<3; i++)
  684. {
  685. if (buffer[i+0x08+offset]!=0x20)
  686. {
  687. tmpFN[j]=buffer[i+0x08+offset];
  688. j++;
  689. }
  690. }
  691. tmpFN[j]=0x00;
  692. if (!strcmp(tmpFN, fn))
  693. {
  694. buffer[offset]=0xE5;
  695. firstCluster = uint16_t(buffer[0x1A + offset]) + (uint16_t(buffer[0x1B + offset])<<8);
  696. mmc::writeSector(buffer, currSec);
  697. if (firstCluster!=0)
  698. {
  699. currSec=firstCluster/256;
  700. mmc::readSector(buffer, BS.fat1Start+currSec);
  701. currCluster=firstCluster;
  702. nextCluster=0;
  703. while (nextCluster!=0xFFFF)
  704. {
  705. nextCluster = buffer[(currCluster % 256)*2] + (buffer[((currCluster % 256)*2)+1]<<8);
  706. buffer[(currCluster % 256)*2]=0;
  707. buffer[((currCluster % 256)*2)+1]=0;
  708. if (((currCluster/256) != (nextCluster/256)) and (nextCluster!=0xFFFF))
  709. {
  710. mmc::writeSector(buffer, BS.fat1Start+currSec);
  711. currSec=nextCluster/256;
  712. mmc::readSector(buffer, BS.fat1Start+currSec);
  713. }
  714. currCluster=nextCluster;
  715. }
  716. mmc::writeSector(buffer, BS.fat1Start+currSec);
  717. currSec=firstCluster/256;
  718. mmc::readSector(buffer, BS.fat2Start+currSec);
  719. currCluster=firstCluster;
  720. nextCluster=0;
  721. while (nextCluster!=0xFFFF)
  722. {
  723. nextCluster = buffer[(currCluster % 256)*2] + (buffer[((currCluster % 256)*2)+1]<<8);
  724. buffer[(currCluster % 256)*2]=0;
  725. buffer[((currCluster % 256)*2)+1]=0;
  726. if (((currCluster/256) != (nextCluster/256)) and (nextCluster!=0xFFFF))
  727. {
  728. mmc::writeSector(buffer, BS.fat2Start+currSec);
  729. currSec=nextCluster/256;
  730. mmc::readSector(buffer, BS.fat2Start+currSec);
  731. }
  732. currCluster=nextCluster;
  733. }
  734. mmc::writeSector(buffer, BS.fat2Start+currSec);
  735. }
  736. done=true;
  737. }
  738. }
  739. return true;
  740. }
  741. else
  742. return false;
  743. }
  744. boolean tinyFAT::create(char *fn)
  745. {
  746. unsigned long currSec;
  747. word offset = 0;
  748. boolean done=false;
  749. int j;
  750. for (int i=0; i<strlen(fn); i++)
  751. {
  752. fn[i]=uCase(fn[i]);
  753. if (!validChar(fn[i]))
  754. return false;
  755. }
  756. if (!exists(fn))
  757. {
  758. currSec = firstDirSector;
  759. mmc::readSector(buffer, currSec);
  760. offset = -32;
  761. while (!done)
  762. {
  763. offset+=32;
  764. if (offset==512)
  765. {
  766. currSec++;
  767. mmc::readSector(buffer, currSec);
  768. offset = 0;
  769. }
  770. if ((buffer[offset]==0x00) or (buffer[offset]==0xE5))
  771. {
  772. for (int i=0; i<11; i++)
  773. {
  774. buffer[i+offset]=0x20;
  775. }
  776. j=0;
  777. for (int i=0; i<strlen(fn); i++)
  778. {
  779. if (fn[i]=='.')
  780. j=8;
  781. else
  782. {
  783. buffer[j+offset]=fn[i];
  784. j++;
  785. }
  786. }
  787. for (int i=0x0b; i<0x20; i++)
  788. buffer[offset+i]=0;
  789. buffer[offset+0x0b]=0x20;
  790. buffer[offset+0x0f]=0x60;
  791. buffer[offset+0x10]=0x21;
  792. buffer[offset+0x11]=0x3E;
  793. buffer[offset+0x12]=0x21;
  794. buffer[offset+0x13]=0x3E;
  795. buffer[offset+0x17]=0x60;
  796. buffer[offset+0x18]=0x21;
  797. buffer[offset+0x19]=0x3E;
  798. mmc::writeSector(buffer, currSec);
  799. done=true;
  800. }
  801. }
  802. return true;
  803. }
  804. else
  805. return false;
  806. }
  807. /* Private */
  808. uint16_t tinyFAT::findNextCluster(uint16_t cc)
  809. {
  810. uint16_t nc;
  811. mmc::readSector(buffer, BS.fat1Start+int(cc/256));
  812. nc = buffer[(cc % 256)*2] + (buffer[((cc % 256)*2)+1]<<8);
  813. return nc;
  814. }
  815. char tinyFAT::uCase(char c)
  816. {
  817. if ((c>='a') && (c<='z'))
  818. return (c-0x20);
  819. else
  820. return c;
  821. }
  822. boolean tinyFAT::validChar(char c)
  823. {
  824. char valid[]= "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!#$&'()-@^_`{}~.";
  825. for (int i=0; i<strlen(valid); i++)
  826. if (c==valid[i])
  827. return true;
  828. return false;
  829. }
  830. uint16_t tinyFAT::findFreeCluster()
  831. {
  832. unsigned long currSec=0;
  833. word firstFreeCluster=0;
  834. word offset=0;
  835. while ((firstFreeCluster==0) and (currSec<=BS.sectorsPerFAT))
  836. {
  837. mmc::readSector(buffer, BS.fat1Start+currSec);
  838. while ((firstFreeCluster==0) and (offset<=512))
  839. {
  840. if ((buffer[offset] + (buffer[offset+1]<<8))==0)
  841. firstFreeCluster=(currSec<<8)+(offset/2);
  842. else
  843. offset+=2;
  844. }
  845. offset=0;
  846. currSec++;
  847. }
  848. }
  849. void tinyFAT::setSSpin(byte pin)
  850. {
  851. if (_inited==false)
  852. mmc::setSSpin(pin);
  853. }
  854. /* Declarations */
  855. tinyFAT file = tinyFAT();