cardreader.cpp 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081
  1. #include "Marlin.h"
  2. #include "cardreader.h"
  3. #include "ultralcd.h"
  4. #include "stepper.h"
  5. #include "temperature.h"
  6. #include "language.h"
  7. #ifdef SDSUPPORT
  8. #define LONGEST_FILENAME (longFilename[0] ? longFilename : filename)
  9. CardReader::CardReader()
  10. {
  11. #ifdef SDCARD_SORT_ALPHA
  12. sort_count = 0;
  13. #if SDSORT_GCODE
  14. sort_alpha = true;
  15. sort_folders = FOLDER_SORTING;
  16. //sort_reverse = false;
  17. #endif
  18. #endif
  19. filesize = 0;
  20. sdpos = 0;
  21. sdprinting = false;
  22. cardOK = false;
  23. saving = false;
  24. logging = false;
  25. autostart_atmillis=0;
  26. workDirDepth = 0;
  27. file_subcall_ctr=0;
  28. memset(workDirParents, 0, sizeof(workDirParents));
  29. autostart_stilltocheck=true; //the SD start is delayed, because otherwise the serial cannot answer fast enough to make contact with the host software.
  30. lastnr=0;
  31. //power to SD reader
  32. #if SDPOWER > -1
  33. SET_OUTPUT(SDPOWER);
  34. WRITE(SDPOWER,HIGH);
  35. #endif //SDPOWER
  36. autostart_atmillis=millis()+5000;
  37. }
  38. char *createFilename(char *buffer,const dir_t &p) //buffer>12characters
  39. {
  40. char *pos=buffer;
  41. for (uint8_t i = 0; i < 11; i++)
  42. {
  43. if (p.name[i] == ' ')continue;
  44. if (i == 8)
  45. {
  46. *pos++='.';
  47. }
  48. *pos++=p.name[i];
  49. }
  50. *pos++=0;
  51. return buffer;
  52. }
  53. void CardReader::lsDive_pointer(const char *prepend, SdFile parent, const char * const match) {
  54. dir_t p;
  55. uint8_t cnt = 0;
  56. //parent.seekSet =
  57. // Read the next entry from a directory
  58. parent.readDir(p, longFilename);
  59. uint8_t pn0 = p.name[0];
  60. filenameIsDir = DIR_IS_SUBDIR(&p);
  61. createFilename(filename, p);
  62. creationDate = p.creationDate;
  63. creationTime = p.creationTime;
  64. }
  65. /**
  66. * Dive into a folder and recurse depth-first to perform a pre-set operation lsAction:
  67. * LS_Count - Add +1 to nrFiles for every file within the parent
  68. * LS_GetFilename - Get the filename of the file indexed by nrFiles
  69. * LS_SerialPrint - Print the full path and size of each file to serial output
  70. */
  71. void CardReader::lsDive(const char *prepend, SdFile parent, const char * const match/*=NULL*/) {
  72. dir_t p;
  73. uint8_t cnt = 0;
  74. /*SERIAL_ECHOPGM("Cur pos. first: ");
  75. uint32_t pom = parent.curPosition();
  76. MYSERIAL.println(pom, 10);*/
  77. // Read the next entry from a directory
  78. while (parent.readDir(p, longFilename) > 0) {
  79. //MYSERIAL.print(int(cnt));
  80. //uint32_t pom = parent.curCluster();
  81. //SERIAL_ECHOPGM(": ");
  82. //MYSERIAL.print(pom, 10);
  83. //SERIAL_ECHOPGM("; ");
  84. /*SERIAL_ECHOPGM("Cur pos.: ");
  85. uint32_t pom = parent.curPosition();
  86. MYSERIAL.println(pom, 10);*/
  87. // If the entry is a directory and the action is LS_SerialPrint
  88. if (DIR_IS_SUBDIR(&p) && lsAction != LS_Count && lsAction != LS_GetFilename) {
  89. // Get the short name for the item, which we know is a folder
  90. char lfilename[FILENAME_LENGTH];
  91. createFilename(lfilename, p);
  92. // Allocate enough stack space for the full path to a folder, trailing slash, and nul
  93. bool prepend_is_empty = (prepend[0] == '\0');
  94. int len = (prepend_is_empty ? 1 : strlen(prepend)) + strlen(lfilename) + 1 + 1;
  95. char path[len];
  96. // Append the FOLDERNAME12/ to the passed string.
  97. // It contains the full path to the "parent" argument.
  98. // We now have the full path to the item in this folder.
  99. strcpy(path, prepend_is_empty ? "/" : prepend); // root slash if prepend is empty
  100. strcat(path, lfilename); // FILENAME_LENGTH-1 characters maximum
  101. strcat(path, "/"); // 1 character
  102. // Serial.print(path);
  103. // Get a new directory object using the full path
  104. // and dive recursively into it.
  105. SdFile dir;
  106. if (!dir.open(parent, lfilename, O_READ)) {
  107. if (lsAction == LS_SerialPrint) {
  108. //SERIAL_ECHO_START();
  109. //SERIAL_ECHOPGM(MSG_SD_CANT_OPEN_SUBDIR);
  110. //SERIAL_ECHOLN(lfilename);
  111. }
  112. }
  113. lsDive(path, dir);
  114. // close() is done automatically by destructor of SdFile
  115. }
  116. else {
  117. uint8_t pn0 = p.name[0];
  118. if (pn0 == DIR_NAME_FREE) break;
  119. if (pn0 == DIR_NAME_DELETED || pn0 == '.') continue;
  120. if (longFilename[0] == '.') continue;
  121. if (!DIR_IS_FILE_OR_SUBDIR(&p) || (p.attributes & DIR_ATT_HIDDEN)) continue;
  122. filenameIsDir = DIR_IS_SUBDIR(&p);
  123. if (!filenameIsDir && (p.name[8] != 'G' || p.name[9] == '~')) continue;
  124. switch (lsAction) {
  125. case LS_Count:
  126. nrFiles++;
  127. break;
  128. case LS_SerialPrint:
  129. createFilename(filename, p);
  130. SERIAL_PROTOCOL(prepend);
  131. SERIAL_PROTOCOL(filename);
  132. //SERIAL_PROTOCOLCHAR(' ');
  133. SERIAL_PROTOCOLLN(p.fileSize);
  134. break;
  135. case LS_GetFilename:
  136. //SERIAL_ECHOPGM("File: ");
  137. createFilename(filename, p);
  138. /*MYSERIAL.println(filename);
  139. SERIAL_ECHOPGM("Write date: ");
  140. writeDate = p.lastWriteDate;
  141. MYSERIAL.println(writeDate);
  142. writeTime = p.lastWriteTime;
  143. SERIAL_ECHOPGM("Creation date: ");
  144. MYSERIAL.println(p.creationDate);
  145. SERIAL_ECHOPGM("Access date: ");
  146. MYSERIAL.println(p.lastAccessDate);
  147. SERIAL_ECHOLNPGM("");*/
  148. cluster = parent.curCluster();
  149. position = parent.curPosition();
  150. creationDate = p.creationDate;
  151. creationTime = p.creationTime;
  152. //writeDate = p.lastAccessDate;
  153. if (match != NULL) {
  154. if (strcasecmp(match, filename) == 0) return;
  155. }
  156. else if (cnt == nrFiles) {
  157. return;
  158. }
  159. cnt++;
  160. break;
  161. }
  162. }
  163. } // while readDir
  164. }
  165. void CardReader::ls()
  166. {
  167. lsAction=LS_SerialPrint;
  168. // if(lsAction==LS_Count)
  169. // nrFiles=0;
  170. root.rewind();
  171. lsDive("",root);
  172. }
  173. void CardReader::initsd()
  174. {
  175. cardOK = false;
  176. if(root.isOpen())
  177. root.close();
  178. #ifdef SDSLOW
  179. if (!card.init(SPI_HALF_SPEED,SDSS)
  180. #if defined(LCD_SDSS) && (LCD_SDSS != SDSS)
  181. && !card.init(SPI_HALF_SPEED,LCD_SDSS)
  182. #endif
  183. )
  184. #else
  185. if (!card.init(SPI_FULL_SPEED,SDSS)
  186. #if defined(LCD_SDSS) && (LCD_SDSS != SDSS)
  187. && !card.init(SPI_FULL_SPEED,LCD_SDSS)
  188. #endif
  189. )
  190. #endif
  191. {
  192. //if (!card.init(SPI_HALF_SPEED,SDSS))
  193. SERIAL_ECHO_START;
  194. SERIAL_ECHOLNRPGM(MSG_SD_INIT_FAIL);
  195. }
  196. else if (!volume.init(&card))
  197. {
  198. SERIAL_ERROR_START;
  199. SERIAL_ERRORLNRPGM(MSG_SD_VOL_INIT_FAIL);
  200. }
  201. else if (!root.openRoot(&volume))
  202. {
  203. SERIAL_ERROR_START;
  204. SERIAL_ERRORLNRPGM(MSG_SD_OPENROOT_FAIL);
  205. }
  206. else
  207. {
  208. cardOK = true;
  209. SERIAL_ECHO_START;
  210. SERIAL_ECHOLNRPGM(MSG_SD_CARD_OK);
  211. }
  212. workDir=root;
  213. curDir=&root;
  214. #ifdef SDCARD_SORT_ALPHA
  215. presort();
  216. #endif
  217. /*
  218. if(!workDir.openRoot(&volume))
  219. {
  220. SERIAL_ECHOLNPGM(MSG_SD_WORKDIR_FAIL);
  221. }
  222. */
  223. }
  224. void CardReader::setroot()
  225. {
  226. /*if(!workDir.openRoot(&volume))
  227. {
  228. SERIAL_ECHOLNPGM(MSG_SD_WORKDIR_FAIL);
  229. }*/
  230. workDir=root;
  231. curDir=&workDir;
  232. #ifdef SDCARD_SORT_ALPHA
  233. presort();
  234. #endif
  235. }
  236. void CardReader::release()
  237. {
  238. sdprinting = false;
  239. cardOK = false;
  240. }
  241. void CardReader::startFileprint()
  242. {
  243. if(cardOK)
  244. {
  245. sdprinting = true;
  246. #ifdef SDCARD_SORT_ALPHA
  247. flush_presort();
  248. #endif
  249. }
  250. }
  251. void CardReader::pauseSDPrint()
  252. {
  253. if(sdprinting)
  254. {
  255. sdprinting = false;
  256. }
  257. }
  258. void CardReader::openLogFile(char* name)
  259. {
  260. logging = true;
  261. openFile(name, false);
  262. }
  263. void CardReader::getAbsFilename(char *t)
  264. {
  265. uint8_t cnt=0;
  266. *t='/';t++;cnt++;
  267. for(uint8_t i=0;i<workDirDepth;i++)
  268. {
  269. workDirParents[i].getFilename(t); //SDBaseFile.getfilename!
  270. while(*t!=0 && cnt< MAXPATHNAMELENGTH)
  271. {t++;cnt++;} //crawl counter forward.
  272. }
  273. if(cnt<MAXPATHNAMELENGTH-13)
  274. file.getFilename(t);
  275. else
  276. t[0]=0;
  277. }
  278. void CardReader::openFile(char* name,bool read, bool replace_current/*=true*/)
  279. {
  280. if(!cardOK)
  281. return;
  282. if(file.isOpen()) //replacing current file by new file, or subfile call
  283. {
  284. if(!replace_current)
  285. {
  286. if((int)file_subcall_ctr>(int)SD_PROCEDURE_DEPTH-1)
  287. {
  288. SERIAL_ERROR_START;
  289. SERIAL_ERRORPGM("trying to call sub-gcode files with too many levels. MAX level is:");
  290. SERIAL_ERRORLN(SD_PROCEDURE_DEPTH);
  291. kill();
  292. return;
  293. }
  294. SERIAL_ECHO_START;
  295. SERIAL_ECHOPGM("SUBROUTINE CALL target:\"");
  296. SERIAL_ECHO(name);
  297. SERIAL_ECHOPGM("\" parent:\"");
  298. //store current filename and position
  299. getAbsFilename(filenames[file_subcall_ctr]);
  300. SERIAL_ECHO(filenames[file_subcall_ctr]);
  301. SERIAL_ECHOPGM("\" pos");
  302. SERIAL_ECHOLN(sdpos);
  303. filespos[file_subcall_ctr]=sdpos;
  304. file_subcall_ctr++;
  305. }
  306. else
  307. {
  308. SERIAL_ECHO_START;
  309. SERIAL_ECHOPGM("Now doing file: ");
  310. SERIAL_ECHOLN(name);
  311. }
  312. file.close();
  313. }
  314. else //opening fresh file
  315. {
  316. file_subcall_ctr=0; //resetting procedure depth in case user cancels print while in procedure
  317. SERIAL_ECHO_START;
  318. SERIAL_ECHOPGM("Now fresh file: ");
  319. SERIAL_ECHOLN(name);
  320. }
  321. sdprinting = false;
  322. SdFile myDir;
  323. curDir=&root;
  324. char *fname=name;
  325. char *dirname_start,*dirname_end;
  326. if(name[0]=='/')
  327. {
  328. dirname_start=strchr(name,'/')+1;
  329. while(dirname_start>0)
  330. {
  331. dirname_end=strchr(dirname_start,'/');
  332. //SERIAL_ECHO("start:");SERIAL_ECHOLN((int)(dirname_start-name));
  333. //SERIAL_ECHO("end :");SERIAL_ECHOLN((int)(dirname_end-name));
  334. if(dirname_end>0 && dirname_end>dirname_start)
  335. {
  336. char subdirname[13];
  337. strncpy(subdirname, dirname_start, dirname_end-dirname_start);
  338. subdirname[dirname_end-dirname_start]=0;
  339. SERIAL_ECHOLN(subdirname);
  340. if(!myDir.open(curDir,subdirname,O_READ))
  341. {
  342. SERIAL_PROTOCOLRPGM(MSG_SD_OPEN_FILE_FAIL);
  343. SERIAL_PROTOCOL(subdirname);
  344. SERIAL_PROTOCOLLNPGM(".");
  345. return;
  346. }
  347. else
  348. {
  349. //SERIAL_ECHOLN("dive ok");
  350. }
  351. curDir=&myDir;
  352. dirname_start=dirname_end+1;
  353. }
  354. else // the reminder after all /fsa/fdsa/ is the filename
  355. {
  356. fname=dirname_start;
  357. //SERIAL_ECHOLN("remaider");
  358. //SERIAL_ECHOLN(fname);
  359. break;
  360. }
  361. }
  362. }
  363. else //relative path
  364. {
  365. curDir=&workDir;
  366. }
  367. if(read)
  368. {
  369. if (file.open(curDir, fname, O_READ))
  370. {
  371. filesize = file.fileSize();
  372. SERIAL_PROTOCOLRPGM(MSG_SD_FILE_OPENED);
  373. SERIAL_PROTOCOL(fname);
  374. SERIAL_PROTOCOLRPGM(MSG_SD_SIZE);
  375. SERIAL_PROTOCOLLN(filesize);
  376. sdpos = 0;
  377. SERIAL_PROTOCOLLNRPGM(MSG_SD_FILE_SELECTED);
  378. getfilename(0, fname);
  379. lcd_setstatus(longFilename[0] ? longFilename : fname);
  380. lcd_setstatus("SD-PRINTING ");
  381. }
  382. else
  383. {
  384. SERIAL_PROTOCOLRPGM(MSG_SD_OPEN_FILE_FAIL);
  385. SERIAL_PROTOCOL(fname);
  386. SERIAL_PROTOCOLLNPGM(".");
  387. }
  388. }
  389. else
  390. { //write
  391. if (!file.open(curDir, fname, O_CREAT | O_APPEND | O_WRITE | O_TRUNC))
  392. {
  393. SERIAL_PROTOCOLRPGM(MSG_SD_OPEN_FILE_FAIL);
  394. SERIAL_PROTOCOL(fname);
  395. SERIAL_PROTOCOLLNPGM(".");
  396. }
  397. else
  398. {
  399. saving = true;
  400. SERIAL_PROTOCOLRPGM(MSG_SD_WRITE_TO_FILE);
  401. SERIAL_PROTOCOLLN(name);
  402. lcd_setstatus(fname);
  403. }
  404. }
  405. }
  406. void CardReader::removeFile(char* name)
  407. {
  408. if(!cardOK)
  409. return;
  410. file.close();
  411. sdprinting = false;
  412. SdFile myDir;
  413. curDir=&root;
  414. char *fname=name;
  415. char *dirname_start,*dirname_end;
  416. if(name[0]=='/')
  417. {
  418. dirname_start=strchr(name,'/')+1;
  419. while(dirname_start>0)
  420. {
  421. dirname_end=strchr(dirname_start,'/');
  422. //SERIAL_ECHO("start:");SERIAL_ECHOLN((int)(dirname_start-name));
  423. //SERIAL_ECHO("end :");SERIAL_ECHOLN((int)(dirname_end-name));
  424. if(dirname_end>0 && dirname_end>dirname_start)
  425. {
  426. char subdirname[13];
  427. strncpy(subdirname, dirname_start, dirname_end-dirname_start);
  428. subdirname[dirname_end-dirname_start]=0;
  429. SERIAL_ECHOLN(subdirname);
  430. if(!myDir.open(curDir,subdirname,O_READ))
  431. {
  432. SERIAL_PROTOCOLRPGM("open failed, File: ");
  433. SERIAL_PROTOCOL(subdirname);
  434. SERIAL_PROTOCOLLNPGM(".");
  435. return;
  436. }
  437. else
  438. {
  439. //SERIAL_ECHOLN("dive ok");
  440. }
  441. curDir=&myDir;
  442. dirname_start=dirname_end+1;
  443. }
  444. else // the reminder after all /fsa/fdsa/ is the filename
  445. {
  446. fname=dirname_start;
  447. //SERIAL_ECHOLN("remaider");
  448. //SERIAL_ECHOLN(fname);
  449. break;
  450. }
  451. }
  452. }
  453. else //relative path
  454. {
  455. curDir=&workDir;
  456. }
  457. if (file.remove(curDir, fname))
  458. {
  459. SERIAL_PROTOCOLPGM("File deleted:");
  460. SERIAL_PROTOCOLLN(fname);
  461. sdpos = 0;
  462. #ifdef SDCARD_SORT_ALPHA
  463. presort();
  464. #endif
  465. }
  466. else
  467. {
  468. SERIAL_PROTOCOLPGM("Deletion failed, File: ");
  469. SERIAL_PROTOCOL(fname);
  470. SERIAL_PROTOCOLLNPGM(".");
  471. }
  472. }
  473. uint32_t CardReader::getFileSize()
  474. {
  475. return filesize;
  476. }
  477. void CardReader::getStatus()
  478. {
  479. if(sdprinting){
  480. SERIAL_PROTOCOL(longFilename);
  481. SERIAL_PROTOCOLPGM("\n");
  482. SERIAL_PROTOCOLRPGM(MSG_SD_PRINTING_BYTE);
  483. SERIAL_PROTOCOL(sdpos);
  484. SERIAL_PROTOCOLPGM("/");
  485. SERIAL_PROTOCOLLN(filesize);
  486. uint16_t time = millis()/60000 - starttime/60000;
  487. SERIAL_PROTOCOL(itostr2(time/60));
  488. SERIAL_PROTOCOL(':');
  489. SERIAL_PROTOCOL(itostr2(time%60));
  490. SERIAL_PROTOCOLPGM("\n");
  491. }
  492. else{
  493. SERIAL_PROTOCOLLNRPGM("Not printing");
  494. }
  495. }
  496. void CardReader::write_command(char *buf)
  497. {
  498. char* begin = buf;
  499. char* npos = 0;
  500. char* end = buf + strlen(buf) - 1;
  501. file.writeError = false;
  502. if((npos = strchr(buf, 'N')) != NULL)
  503. {
  504. begin = strchr(npos, ' ') + 1;
  505. end = strchr(npos, '*') - 1;
  506. }
  507. end[1] = '\r';
  508. end[2] = '\n';
  509. end[3] = '\0';
  510. file.write(begin);
  511. if (file.writeError)
  512. {
  513. SERIAL_ERROR_START;
  514. SERIAL_ERRORLNRPGM(MSG_SD_ERR_WRITE_TO_FILE);
  515. }
  516. }
  517. #define CHUNK_SIZE 64
  518. void CardReader::write_command_no_newline(char *buf)
  519. {
  520. file.write(buf, CHUNK_SIZE);
  521. if (file.writeError)
  522. {
  523. SERIAL_ERROR_START;
  524. SERIAL_ERRORLNRPGM(MSG_SD_ERR_WRITE_TO_FILE);
  525. MYSERIAL.println("An error while writing to the SD Card.");
  526. }
  527. }
  528. void CardReader::checkautostart(bool force)
  529. {
  530. if(!force)
  531. {
  532. if(!autostart_stilltocheck)
  533. return;
  534. if(autostart_atmillis<millis())
  535. return;
  536. }
  537. autostart_stilltocheck=false;
  538. if(!cardOK)
  539. {
  540. initsd();
  541. if(!cardOK) //fail
  542. return;
  543. }
  544. char autoname[30];
  545. sprintf_P(autoname, PSTR("auto%i.g"), lastnr);
  546. for(int8_t i=0;i<(int8_t)strlen(autoname);i++)
  547. autoname[i]=tolower(autoname[i]);
  548. dir_t p;
  549. root.rewind();
  550. bool found=false;
  551. while (root.readDir(p, NULL) > 0)
  552. {
  553. for(int8_t i=0;i<(int8_t)strlen((char*)p.name);i++)
  554. p.name[i]=tolower(p.name[i]);
  555. //Serial.print((char*)p.name);
  556. //Serial.print(" ");
  557. //Serial.println(autoname);
  558. if(p.name[9]!='~') //skip safety copies
  559. if(strncmp((char*)p.name,autoname,5)==0)
  560. {
  561. char cmd[30];
  562. // M23: Select SD file
  563. sprintf_P(cmd, PSTR("M23 %s"), autoname);
  564. enquecommand(cmd);
  565. // M24: Start/resume SD print
  566. enquecommand_P(PSTR("M24"));
  567. found=true;
  568. }
  569. }
  570. if(!found)
  571. lastnr=-1;
  572. else
  573. lastnr++;
  574. }
  575. void CardReader::closefile(bool store_location)
  576. {
  577. file.sync();
  578. file.close();
  579. saving = false;
  580. logging = false;
  581. if(store_location)
  582. {
  583. //future: store printer state, filename and position for continuing a stopped print
  584. // so one can unplug the printer and continue printing the next day.
  585. }
  586. }
  587. /*void CardReader::getfilename_adress(uint16_t nr, const char * const match)
  588. {
  589. curDir = &workDir;
  590. lsAction = LS_GetFilenameAdress;
  591. nrFiles = nr;
  592. curDir->rewind();
  593. lsDive("", *curDir, match);
  594. }*/
  595. void CardReader::getfilename(uint16_t nr, const char * const match/*=NULL*/)
  596. {
  597. curDir=&workDir;
  598. lsAction=LS_GetFilename;
  599. nrFiles=nr;
  600. curDir->rewind();
  601. lsDive("",*curDir,match);
  602. }
  603. void CardReader::getfilename_simple(uint32_t position, const char * const match/*=NULL*/)
  604. {
  605. //SERIAL_ECHOPGM("FILE NR:");
  606. //MYSERIAL.println(position);
  607. curDir = &workDir;
  608. //curDir = curDir + nr * 32 * 8; //32 bytes per entry
  609. lsAction = LS_GetFilename;
  610. //nrFiles = nr;
  611. //curDir->rewind();
  612. curDir->seekSet(position);
  613. //curDir->setpos(32*nr);
  614. lsDive_pointer("", *curDir, match);
  615. /*SERIAL_ECHOPGM("; Position:");
  616. uint32_t pom = curDir->curPosition();
  617. MYSERIAL.print(pom, 10);
  618. SERIAL_ECHOPGM("; Cluster:");
  619. MYSERIAL.println(curDir->curCluster());*/
  620. }
  621. uint16_t CardReader::getnrfilenames()
  622. {
  623. curDir=&workDir;
  624. lsAction=LS_Count;
  625. nrFiles=0;
  626. curDir->rewind();
  627. lsDive("",*curDir);
  628. //SERIAL_ECHOLN(nrFiles);
  629. return nrFiles;
  630. }
  631. void CardReader::chdir(const char * relpath)
  632. {
  633. SdFile newfile;
  634. SdFile *parent=&root;
  635. if(workDir.isOpen())
  636. parent=&workDir;
  637. if(!newfile.open(*parent,relpath, O_READ))
  638. {
  639. SERIAL_ECHO_START;
  640. SERIAL_ECHORPGM(MSG_SD_CANT_ENTER_SUBDIR);
  641. SERIAL_ECHOLN(relpath);
  642. }
  643. else
  644. {
  645. if (workDirDepth < MAX_DIR_DEPTH) {
  646. for (int d = ++workDirDepth; d--;)
  647. workDirParents[d+1] = workDirParents[d];
  648. workDirParents[0]=*parent;
  649. }
  650. workDir=newfile;
  651. }
  652. }
  653. void CardReader::updir()
  654. {
  655. if(workDirDepth > 0)
  656. {
  657. --workDirDepth;
  658. workDir = workDirParents[0];
  659. int d;
  660. for (int d = 0; d < workDirDepth; d++)
  661. workDirParents[d] = workDirParents[d+1];
  662. }
  663. }
  664. #ifdef SDCARD_SORT_ALPHA
  665. /**
  666. * Get the name of a file in the current directory by sort-index
  667. */
  668. void CardReader::getfilename_sorted(const uint16_t nr) {
  669. getfilename(
  670. #if SDSORT_GCODE
  671. sort_alpha &&
  672. #endif
  673. (nr < sort_count) ? sort_order[nr] : nr
  674. );
  675. }
  676. /**
  677. * Read all the files and produce a sort key
  678. *
  679. * We can do this in 3 ways...
  680. * - Minimal RAM: Read two filenames at a time sorting along...
  681. * - Some RAM: Buffer the directory just for this sort
  682. * - Most RAM: Buffer the directory and return filenames from RAM
  683. */
  684. void CardReader::presort() {
  685. unsigned long start_time = millis();
  686. if (farm_mode) return; //sorting is not used in farm mode
  687. uint8_t sdSort = eeprom_read_byte((uint8_t*)EEPROM_SD_SORT);
  688. if (sdSort == SD_SORT_NONE) return; //sd sort is turned off
  689. #if !SDSORT_USES_RAM
  690. lcd_set_progress();
  691. #endif
  692. lcd_implementation_clear();
  693. lcd_print_at_PGM(0, 1, MSG_SORTING);
  694. #if SDSORT_GCODE
  695. if (!sort_alpha) return;
  696. #endif
  697. // Throw away old sort index
  698. flush_presort();
  699. // If there are files, sort up to the limit
  700. uint16_t fileCnt = getnrfilenames();
  701. if (fileCnt > 0) {
  702. // Never sort more than the max allowed
  703. // If you use folders to organize, 20 may be enough
  704. if (fileCnt > SDSORT_LIMIT) fileCnt = SDSORT_LIMIT;
  705. // Sort order is always needed. May be static or dynamic.
  706. #if SDSORT_DYNAMIC_RAM
  707. sort_order = new uint8_t[fileCnt];
  708. #endif
  709. // Use RAM to store the entire directory during pre-sort.
  710. // SDSORT_LIMIT should be set to prevent over-allocation.
  711. #if SDSORT_USES_RAM
  712. // If using dynamic ram for names, allocate on the heap.
  713. #if SDSORT_CACHE_NAMES
  714. #if SDSORT_DYNAMIC_RAM
  715. sortshort = new char*[fileCnt];
  716. sortnames = new char*[fileCnt];
  717. #endif
  718. #elif SDSORT_USES_STACK
  719. char sortnames[fileCnt][LONG_FILENAME_LENGTH];
  720. uint16_t creation_time[SDSORT_LIMIT];
  721. uint16_t creation_date[SDSORT_LIMIT];
  722. //#elif SDSORT_POINTERS
  723. #endif
  724. // Folder sorting needs 1 bit per entry for flags.
  725. #if HAS_FOLDER_SORTING
  726. #if SDSORT_DYNAMIC_RAM
  727. isDir = new uint8_t[(fileCnt + 7) >> 3];
  728. #elif SDSORT_USES_STACK
  729. uint8_t isDir[(fileCnt + 7) >> 3];
  730. #endif
  731. #endif
  732. #else // !SDSORT_USES_RAM
  733. // uint32_t clusters [fileCnt];
  734. uint32_t positions [fileCnt];
  735. // By default re-read the names from SD for every compare
  736. // retaining only two filenames at a time. This is very
  737. // slow but is safest and uses minimal RAM.
  738. char name1[LONG_FILENAME_LENGTH + 1];
  739. uint16_t creation_time_bckp;
  740. uint16_t creation_date_bckp;
  741. #endif
  742. if (fileCnt > 1) {
  743. // Init sort order.
  744. for (uint16_t i = 0; i < fileCnt; i++) {
  745. sort_order[i] = i;
  746. getfilename(i);
  747. //clusters[i] = cluster;
  748. positions[i] = position-96;
  749. //MYSERIAL.println(i);
  750. //MYSERIAL.println(position);
  751. // If using RAM then read all filenames now.
  752. #if SDSORT_USES_RAM
  753. getfilename(i);
  754. #if SDSORT_DYNAMIC_RAM
  755. // Use dynamic method to copy long filename
  756. sortnames[i] = strdup(LONGEST_FILENAME);
  757. #if SDSORT_CACHE_NAMES
  758. // When caching also store the short name, since
  759. // we're replacing the getfilename() behavior.
  760. sortshort[i] = strdup(filename);
  761. #endif
  762. #else
  763. // Copy filenames into the static array
  764. strcpy(sortnames[i], LONGEST_FILENAME);
  765. creation_time[i] = creationTime;
  766. creation_date[i] = creationDate;
  767. #if SDSORT_CACHE_NAMES
  768. strcpy(sortshort[i], filename);
  769. #endif
  770. #endif
  771. // char out[30];
  772. // sprintf_P(out, PSTR("---- %i %s %s"), i, filenameIsDir ? "D" : " ", sortnames[i]);
  773. // SERIAL_ECHOLN(out);
  774. #if HAS_FOLDER_SORTING
  775. const uint16_t bit = i & 0x07, ind = i >> 3;
  776. if (bit == 0) isDir[ind] = 0x00;
  777. if (filenameIsDir) isDir[ind] |= _BV(bit);
  778. #endif
  779. #endif
  780. }
  781. SERIAL_ECHOPGM("Mezicas:");
  782. MYSERIAL.println(millis() - start_time);
  783. // Bubble Sort
  784. uint16_t counter = 0;
  785. for (uint16_t i = fileCnt; --i;) {
  786. bool didSwap = false;
  787. #if !SDSORT_USES_RAM //show progresss bar only if slow sorting method is used
  788. int8_t percent = ((counter * 100) / (fileCnt-1));
  789. for (int column = 0; column < 20; column++) {
  790. if (column < (percent/5)) lcd_implementation_print_at(column, 2, "\x01"); //simple progress bar
  791. }
  792. counter++;
  793. #endif
  794. //MYSERIAL.println(int(i));
  795. for (uint16_t j = 0; j < i; ++j) {
  796. const uint16_t o1 = sort_order[j], o2 = sort_order[j + 1];
  797. // Compare names from the array or just the two buffered names
  798. #if SDSORT_USES_RAM
  799. #define _SORT_CMP_NODIR() (strcasecmp(sortnames[o1], sortnames[o2]) > 0)
  800. #define _SORT_CMP_TIME_NODIR() (((creation_date[o1] == creation_date[o2]) && (creation_time[o1] < creation_time[o2])) || \
  801. (creation_date[o1] < creation_date [o2]))
  802. #else
  803. #define _SORT_CMP_NODIR() (strcasecmp(name1, name2) > 0) //true if lowercase(name1) > lowercase(name2)
  804. #define _SORT_CMP_TIME_NODIR() (((creation_date_bckp == creationDate) && (creation_time_bckp < creationTime)) || \
  805. (creation_date_bckp < creationDate))
  806. #endif
  807. #if HAS_FOLDER_SORTING
  808. #if SDSORT_USES_RAM
  809. // Folder sorting needs an index and bit to test for folder-ness.
  810. const uint8_t ind1 = o1 >> 3, bit1 = o1 & 0x07,
  811. ind2 = o2 >> 3, bit2 = o2 & 0x07;
  812. #define _SORT_CMP_DIR(fs) \
  813. (((isDir[ind1] & _BV(bit1)) != 0) == ((isDir[ind2] & _BV(bit2)) != 0) \
  814. ? _SORT_CMP_NODIR() \
  815. : (isDir[fs > 0 ? ind1 : ind2] & (fs > 0 ? _BV(bit1) : _BV(bit2))) != 0)
  816. #define _SORT_CMP_TIME_DIR(fs) \
  817. (((isDir[ind1] & _BV(bit1)) != 0) == ((isDir[ind2] & _BV(bit2)) != 0) \
  818. ? _SORT_CMP_TIME_NODIR() \
  819. : (isDir[fs > 0 ? ind1 : ind2] & (fs > 0 ? _BV(bit1) : _BV(bit2))) != 0)
  820. #else
  821. #define _SORT_CMP_DIR(fs) ((dir1 == filenameIsDir) ? _SORT_CMP_NODIR() : (fs > 0 ? dir1 : !dir1))
  822. #define _SORT_CMP_TIME_DIR(fs) ((dir1 == filenameIsDir) ? _SORT_CMP_TIME_NODIR() : (fs > 0 ? dir1 : !dir1))
  823. #endif
  824. #endif
  825. // The most economical method reads names as-needed
  826. // throughout the loop. Slow if there are many.
  827. #if !SDSORT_USES_RAM
  828. getfilename_simple(positions[o1]);
  829. //getfilename(o1);
  830. strcpy(name1, LONGEST_FILENAME); // save (or getfilename below will trounce it)
  831. creation_date_bckp = creationDate;
  832. creation_time_bckp = creationTime;
  833. #if HAS_FOLDER_SORTING
  834. bool dir1 = filenameIsDir;
  835. #endif
  836. getfilename_simple(positions[o2]);
  837. // getfilename(o2);
  838. char *name2 = LONGEST_FILENAME; // use the string in-place
  839. //SERIAL_ECHOPGM("NAMES:");
  840. //MYSERIAL.println(name1);
  841. //MYSERIAL.println(name2);
  842. #endif // !SDSORT_USES_RAM
  843. // Sort the current pair according to settings.
  844. if(
  845. #if HAS_FOLDER_SORTING
  846. (sdSort == SD_SORT_TIME && _SORT_CMP_TIME_DIR(FOLDER_SORTING)) || (sdSort == SD_SORT_ALPHA && _SORT_CMP_DIR(FOLDER_SORTING))
  847. #else
  848. (sdSort == SD_SORT_TIME && _SORT_CMP_TIME_NODIR()) || (sdSort == SD_SORT_ALPHA && _SORT_CMP_NODIR())
  849. #endif
  850. )
  851. {
  852. sort_order[j] = o2;
  853. sort_order[j + 1] = o1;
  854. didSwap = true;
  855. //SERIAL_ECHOLNPGM("did swap");
  856. }
  857. //SERIAL_ECHOLNPGM("");
  858. }
  859. if (!didSwap) break;
  860. } //end of bubble sort loop
  861. // Using RAM but not keeping names around
  862. #if (SDSORT_USES_RAM && !SDSORT_CACHE_NAMES)
  863. #if SDSORT_DYNAMIC_RAM
  864. for (uint16_t i = 0; i < fileCnt; ++i) free(sortnames[i]);
  865. #if HAS_FOLDER_SORTING
  866. free(isDir);
  867. #endif
  868. #endif
  869. #endif
  870. }
  871. else {
  872. sort_order[0] = 0;
  873. #if (SDSORT_USES_RAM && SDSORT_CACHE_NAMES)
  874. getfilename(0);
  875. #if SDSORT_DYNAMIC_RAM
  876. sortnames = new char*[1];
  877. sortnames[0] = strdup(LONGEST_FILENAME); // malloc
  878. sortshort = new char*[1];
  879. sortshort[0] = strdup(filename); // malloc
  880. isDir = new uint8_t[1];
  881. #else
  882. strcpy(sortnames[0], LONGEST_FILENAME);
  883. strcpy(sortshort[0], filename);
  884. #endif
  885. isDir[0] = filenameIsDir ? 0x01 : 0x00;
  886. #endif
  887. }
  888. sort_count = fileCnt;
  889. }
  890. #if !SDSORT_USES_RAM //show progresss bar only if slow sorting method is used
  891. for(int column = 0; column <=19; column++ ) lcd_implementation_print_at(column, 2, "\x01"); //simple progress bar
  892. delay(500);
  893. lcd_set_arrows();
  894. lcd_update(2);
  895. #endif
  896. SERIAL_ECHOPGM("Sort time:");
  897. MYSERIAL.println(millis() - start_time);
  898. }
  899. void CardReader::flush_presort() {
  900. if (sort_count > 0) {
  901. #if SDSORT_DYNAMIC_RAM
  902. delete sort_order;
  903. #if SDSORT_CACHE_NAMES
  904. for (uint8_t i = 0; i < sort_count; ++i) {
  905. free(sortshort[i]); // strdup
  906. free(sortnames[i]); // strdup
  907. }
  908. delete sortshort;
  909. delete sortnames;
  910. #endif
  911. #endif
  912. sort_count = 0;
  913. }
  914. }
  915. #endif // SDCARD_SORT_ALPHA
  916. void CardReader::printingHasFinished()
  917. {
  918. st_synchronize();
  919. if(file_subcall_ctr>0) //heading up to a parent file that called current as a procedure.
  920. {
  921. file.close();
  922. file_subcall_ctr--;
  923. openFile(filenames[file_subcall_ctr],true,true);
  924. setIndex(filespos[file_subcall_ctr]);
  925. startFileprint();
  926. }
  927. else
  928. {
  929. quickStop();
  930. file.close();
  931. sdprinting = false;
  932. if(SD_FINISHED_STEPPERRELEASE)
  933. {
  934. finishAndDisableSteppers();
  935. //enquecommand_P(PSTR(SD_FINISHED_RELEASECOMMAND));
  936. }
  937. autotempShutdown();
  938. #ifdef SDCARD_SORT_ALPHA
  939. presort();
  940. #endif
  941. }
  942. }
  943. bool CardReader::ToshibaFlashAir_GetIP(uint8_t *ip)
  944. {
  945. memset(ip, 0, 4);
  946. return card.readExtMemory(1, 1, 0x400+0x150, 4, ip);
  947. }
  948. #endif //SDSUPPORT