My Marlin configs for Fabrikator Mini and CTC i3 Pro B
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.

cardreader.cpp 30KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064
  1. /**
  2. * Marlin 3D Printer Firmware
  3. * Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
  4. *
  5. * Based on Sprinter and grbl.
  6. * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
  7. *
  8. * This program is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation, either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  20. *
  21. */
  22. #include "../inc/MarlinConfig.h"
  23. #if ENABLED(SDSUPPORT)
  24. #include "cardreader.h"
  25. #include "../Marlin.h"
  26. #include "../lcd/ultralcd.h"
  27. #include "../module/stepper.h"
  28. #include "../module/printcounter.h"
  29. #include "../core/language.h"
  30. #include "../gcode/queue.h"
  31. #if ENABLED(POWER_LOSS_RECOVERY)
  32. #include "../feature/power_loss_recovery.h"
  33. #endif
  34. #if ENABLED(ADVANCED_PAUSE_FEATURE)
  35. #include "../feature/pause.h"
  36. #endif
  37. #include <ctype.h>
  38. #define LONGEST_FILENAME (longFilename[0] ? longFilename : filename)
  39. CardReader::CardReader() {
  40. #if ENABLED(SDCARD_SORT_ALPHA)
  41. sort_count = 0;
  42. #if ENABLED(SDSORT_GCODE)
  43. sort_alpha = true;
  44. sort_folders = FOLDER_SORTING;
  45. //sort_reverse = false;
  46. #endif
  47. #endif
  48. sdprinting = cardOK = saving = logging = false;
  49. filesize = 0;
  50. sdpos = 0;
  51. file_subcall_ctr = 0;
  52. workDirDepth = 0;
  53. ZERO(workDirParents);
  54. autostart_stilltocheck = true; //the SD start is delayed, because otherwise the serial cannot answer fast enough to make contact with the host software.
  55. autostart_index = 0;
  56. //power to SD reader
  57. #if SDPOWER > -1
  58. OUT_WRITE(SDPOWER, HIGH);
  59. #endif // SDPOWER
  60. next_autostart_ms = millis() + 5000;
  61. }
  62. char *createFilename(char *buffer, const dir_t &p) { //buffer > 12characters
  63. char *pos = buffer;
  64. for (uint8_t i = 0; i < 11; i++) {
  65. if (p.name[i] == ' ') continue;
  66. if (i == 8) *pos++ = '.';
  67. *pos++ = p.name[i];
  68. }
  69. *pos++ = 0;
  70. return buffer;
  71. }
  72. /**
  73. * Dive into a folder and recurse depth-first to perform a pre-set operation lsAction:
  74. * LS_Count - Add +1 to nrFiles for every file within the parent
  75. * LS_GetFilename - Get the filename of the file indexed by nrFile_index
  76. * LS_SerialPrint - Print the full path and size of each file to serial output
  77. */
  78. uint16_t nrFile_index;
  79. void CardReader::lsDive(const char *prepend, SdFile parent, const char * const match/*=NULL*/
  80. #if NUM_SERIAL > 1
  81. , const int8_t port/*= -1*/
  82. #endif
  83. ) {
  84. dir_t p;
  85. uint8_t cnt = 0;
  86. // Read the next entry from a directory
  87. while (parent.readDir(p, longFilename) > 0) {
  88. // If the entry is a directory and the action is LS_SerialPrint
  89. if (DIR_IS_SUBDIR(&p) && lsAction != LS_Count && lsAction != LS_GetFilename) {
  90. // Get the short name for the item, which we know is a folder
  91. char lfilename[FILENAME_LENGTH];
  92. createFilename(lfilename, p);
  93. // Allocate enough stack space for the full path to a folder, trailing slash, and nul
  94. bool prepend_is_empty = (prepend[0] == '\0');
  95. int len = (prepend_is_empty ? 1 : strlen(prepend)) + strlen(lfilename) + 1 + 1;
  96. char path[len];
  97. // Append the FOLDERNAME12/ to the passed string.
  98. // It contains the full path to the "parent" argument.
  99. // We now have the full path to the item in this folder.
  100. strcpy(path, prepend_is_empty ? "/" : prepend); // root slash if prepend is empty
  101. strcat(path, lfilename); // FILENAME_LENGTH-1 characters maximum
  102. strcat(path, "/"); // 1 character
  103. // Serial.print(path);
  104. // Get a new directory object using the full path
  105. // and dive recursively into it.
  106. SdFile dir;
  107. if (!dir.open(parent, lfilename, O_READ)) {
  108. if (lsAction == LS_SerialPrint) {
  109. SERIAL_ECHO_START_P(port);
  110. SERIAL_ECHOPGM_P(port, MSG_SD_CANT_OPEN_SUBDIR);
  111. SERIAL_ECHOLN_P(port, lfilename);
  112. }
  113. }
  114. lsDive(path, dir
  115. #if NUM_SERIAL > 1
  116. , NULL, port
  117. #endif
  118. );
  119. // close() is done automatically by destructor of SdFile
  120. }
  121. else {
  122. uint8_t pn0 = p.name[0];
  123. if (pn0 == DIR_NAME_FREE) break;
  124. if (pn0 == DIR_NAME_DELETED || pn0 == '.') continue;
  125. if (longFilename[0] == '.') continue;
  126. if (!DIR_IS_FILE_OR_SUBDIR(&p) || (p.attributes & DIR_ATT_HIDDEN)) continue;
  127. filenameIsDir = DIR_IS_SUBDIR(&p);
  128. if (!filenameIsDir && (p.name[8] != 'G' || p.name[9] == '~')) continue;
  129. switch (lsAction) { // 1 based file count
  130. case LS_Count:
  131. nrFiles++;
  132. break;
  133. case LS_SerialPrint:
  134. createFilename(filename, p);
  135. if (prepend) SERIAL_PROTOCOL_P(port, prepend);
  136. SERIAL_PROTOCOL_P(port, filename);
  137. SERIAL_PROTOCOLCHAR_P(port, ' ');
  138. SERIAL_PROTOCOLLN_P(port, p.fileSize);
  139. break;
  140. case LS_GetFilename:
  141. createFilename(filename, p);
  142. if (match != NULL) {
  143. if (strcasecmp(match, filename) == 0) return;
  144. }
  145. else if (cnt == nrFile_index) return; // 0 based index
  146. cnt++;
  147. break;
  148. }
  149. }
  150. } // while readDir
  151. }
  152. void CardReader::ls(
  153. #if NUM_SERIAL > 1
  154. const int8_t port
  155. #endif
  156. ) {
  157. lsAction = LS_SerialPrint;
  158. root.rewind();
  159. lsDive(NULL, root
  160. #if NUM_SERIAL > 1
  161. , NULL, port
  162. #endif
  163. );
  164. }
  165. #if ENABLED(LONG_FILENAME_HOST_SUPPORT)
  166. /**
  167. * Get a long pretty path based on a DOS 8.3 path
  168. */
  169. void CardReader::printLongPath(char *path
  170. #if NUM_SERIAL > 1
  171. , const int8_t port/*= -1*/
  172. #endif
  173. ) {
  174. lsAction = LS_GetFilename;
  175. int i, pathLen = strlen(path);
  176. // SERIAL_ECHOPGM_P(port, "Full Path: "); SERIAL_ECHOLN_P(port, path);
  177. // Zero out slashes to make segments
  178. for (i = 0; i < pathLen; i++) if (path[i] == '/') path[i] = '\0';
  179. SdFile diveDir = root; // start from the root for segment 1
  180. for (i = 0; i < pathLen;) {
  181. if (path[i] == '\0') i++; // move past a single nul
  182. char *segment = &path[i]; // The segment after most slashes
  183. // If a segment is empty (extra-slash) then exit
  184. if (!*segment) break;
  185. // Go to the next segment
  186. while (path[++i]) { }
  187. // SERIAL_ECHOPGM_P(port, "Looking for segment: "); SERIAL_ECHOLN_P(port, segment);
  188. // Find the item, setting the long filename
  189. diveDir.rewind();
  190. lsDive(NULL, diveDir, segment
  191. #if NUM_SERIAL > 1
  192. , port
  193. #endif
  194. );
  195. // Print /LongNamePart to serial output
  196. SERIAL_PROTOCOLCHAR_P(port, '/');
  197. SERIAL_PROTOCOL_P(port, longFilename[0] ? longFilename : "???");
  198. // If the filename was printed then that's it
  199. if (!filenameIsDir) break;
  200. // SERIAL_ECHOPGM_P(port, "Opening dir: "); SERIAL_ECHOLN_P(port, segment);
  201. // Open the sub-item as the new dive parent
  202. SdFile dir;
  203. if (!dir.open(diveDir, segment, O_READ)) {
  204. SERIAL_EOL_P(port);
  205. SERIAL_ECHO_START_P(port);
  206. SERIAL_ECHOPGM_P(port, MSG_SD_CANT_OPEN_SUBDIR);
  207. SERIAL_ECHO_P(port, segment);
  208. break;
  209. }
  210. diveDir.close();
  211. diveDir = dir;
  212. } // while i<pathLen
  213. SERIAL_EOL_P(port);
  214. }
  215. #endif // LONG_FILENAME_HOST_SUPPORT
  216. /**
  217. * Echo the DOS 8.3 filename (and long filename, if any)
  218. */
  219. void CardReader::printFilename(
  220. #if NUM_SERIAL > 1
  221. const int8_t port/*= -1*/
  222. #endif
  223. ) {
  224. if (file.isOpen()) {
  225. char lfilename[FILENAME_LENGTH];
  226. file.getFilename(lfilename);
  227. SERIAL_ECHO_P(port, lfilename);
  228. #if ENABLED(LONG_FILENAME_HOST_SUPPORT)
  229. getfilename(0, lfilename);
  230. if (longFilename[0]) {
  231. SERIAL_ECHO_P(port, ' ');
  232. SERIAL_ECHO_P(port, longFilename);
  233. }
  234. #endif
  235. }
  236. else
  237. SERIAL_ECHOPGM_P(port, "(no file)");
  238. SERIAL_EOL_P(port);
  239. }
  240. void CardReader::initsd() {
  241. cardOK = false;
  242. if (root.isOpen()) root.close();
  243. #ifndef SPI_SPEED
  244. #define SPI_SPEED SPI_FULL_SPEED
  245. #endif
  246. if (!card.init(SPI_SPEED, SDSS)
  247. #if defined(LCD_SDSS) && (LCD_SDSS != SDSS)
  248. && !card.init(SPI_SPEED, LCD_SDSS)
  249. #endif
  250. ) {
  251. //if (!card.init(SPI_HALF_SPEED,SDSS))
  252. SERIAL_ECHO_START();
  253. SERIAL_ECHOLNPGM(MSG_SD_INIT_FAIL);
  254. }
  255. else if (!volume.init(&card)) {
  256. SERIAL_ERROR_START();
  257. SERIAL_ERRORLNPGM(MSG_SD_VOL_INIT_FAIL);
  258. }
  259. else if (!root.openRoot(&volume)) {
  260. SERIAL_ERROR_START();
  261. SERIAL_ERRORLNPGM(MSG_SD_OPENROOT_FAIL);
  262. }
  263. else {
  264. cardOK = true;
  265. SERIAL_ECHO_START();
  266. SERIAL_ECHOLNPGM(MSG_SD_CARD_OK);
  267. }
  268. setroot();
  269. }
  270. void CardReader::setroot() {
  271. /*if (!workDir.openRoot(&volume)) {
  272. SERIAL_ECHOLNPGM(MSG_SD_WORKDIR_FAIL);
  273. }*/
  274. workDir = root;
  275. curDir = &workDir;
  276. #if ENABLED(SDCARD_SORT_ALPHA)
  277. presort();
  278. #endif
  279. }
  280. void CardReader::release() {
  281. sdprinting = false;
  282. cardOK = false;
  283. }
  284. void CardReader::openAndPrintFile(const char *name) {
  285. char cmd[4 + strlen(name) + 1]; // Room for "M23 ", filename, and null
  286. sprintf_P(cmd, PSTR("M23 %s"), name);
  287. for (char *c = &cmd[4]; *c; c++) *c = tolower(*c);
  288. enqueue_and_echo_command_now(cmd);
  289. enqueue_and_echo_commands_P(PSTR("M24"));
  290. }
  291. void CardReader::startFileprint() {
  292. if (cardOK) {
  293. sdprinting = true;
  294. #if SD_RESORT
  295. flush_presort();
  296. #endif
  297. }
  298. }
  299. void CardReader::stopSDPrint(
  300. #if SD_RESORT
  301. const bool re_sort/*=false*/
  302. #endif
  303. ) {
  304. #if ENABLED(ADVANCED_PAUSE_FEATURE)
  305. did_pause_print = 0;
  306. #endif
  307. sdprinting = false;
  308. if (isFileOpen()) file.close();
  309. #if SD_RESORT
  310. if (re_sort) presort();
  311. #endif
  312. }
  313. void CardReader::openLogFile(char* name) {
  314. logging = true;
  315. openFile(name, false);
  316. }
  317. void appendAtom(SdFile &file, char *& dst, uint8_t &cnt) {
  318. file.getFilename(dst);
  319. while (*dst && cnt < MAXPATHNAMELENGTH) { dst++; cnt++; }
  320. if (cnt < MAXPATHNAMELENGTH) { *dst = '/'; dst++; cnt++; }
  321. }
  322. void CardReader::getAbsFilename(char *t) {
  323. *t++ = '/'; // Root folder
  324. uint8_t cnt = 1;
  325. for (uint8_t i = 0; i < workDirDepth; i++) // Loop to current work dir
  326. appendAtom(workDirParents[i], t, cnt);
  327. if (cnt < MAXPATHNAMELENGTH - (FILENAME_LENGTH)) {
  328. appendAtom(file, t, cnt);
  329. --t;
  330. }
  331. *t = '\0';
  332. }
  333. void CardReader::openFile(char* name, const bool read, const bool subcall/*=false*/) {
  334. if (!cardOK) return;
  335. uint8_t doing = 0;
  336. if (isFileOpen()) { // Replacing current file or doing a subroutine
  337. if (subcall) {
  338. if (file_subcall_ctr > SD_PROCEDURE_DEPTH - 1) {
  339. SERIAL_ERROR_START();
  340. SERIAL_ERRORPGM("trying to call sub-gcode files with too many levels. MAX level is:");
  341. SERIAL_ERRORLN((int)SD_PROCEDURE_DEPTH);
  342. kill(PSTR(MSG_KILLED));
  343. return;
  344. }
  345. // Store current filename (based on workDirParents) and position
  346. getAbsFilename(proc_filenames[file_subcall_ctr]);
  347. filespos[file_subcall_ctr] = sdpos;
  348. SERIAL_ECHO_START();
  349. SERIAL_ECHOPAIR("SUBROUTINE CALL target:\"", name);
  350. SERIAL_ECHOPAIR("\" parent:\"", proc_filenames[file_subcall_ctr]);
  351. SERIAL_ECHOLNPAIR("\" pos", sdpos);
  352. file_subcall_ctr++;
  353. }
  354. else
  355. doing = 1;
  356. }
  357. else if (subcall) { // Returning from a subcall?
  358. SERIAL_ECHO_START();
  359. SERIAL_ECHOLNPGM("END SUBROUTINE");
  360. }
  361. else { // Opening fresh file
  362. doing = 2;
  363. file_subcall_ctr = 0; // Reset procedure depth in case user cancels print while in procedure
  364. }
  365. if (doing) {
  366. SERIAL_ECHO_START();
  367. SERIAL_ECHOPGM("Now ");
  368. serialprintPGM(doing == 1 ? PSTR("doing") : PSTR("fresh"));
  369. SERIAL_ECHOLNPAIR(" file: ", name);
  370. }
  371. stopSDPrint();
  372. SdFile myDir;
  373. curDir = &root;
  374. char *fname = name;
  375. char *dirname_start, *dirname_end;
  376. if (name[0] == '/') {
  377. dirname_start = &name[1];
  378. while (dirname_start != NULL) {
  379. dirname_end = strchr(dirname_start, '/');
  380. //SERIAL_ECHOPGM("start:");SERIAL_ECHOLN((int)(dirname_start - name));
  381. //SERIAL_ECHOPGM("end :");SERIAL_ECHOLN((int)(dirname_end - name));
  382. if (dirname_end != NULL && dirname_end > dirname_start) {
  383. char subdirname[FILENAME_LENGTH];
  384. strncpy(subdirname, dirname_start, dirname_end - dirname_start);
  385. subdirname[dirname_end - dirname_start] = '\0';
  386. if (!myDir.open(curDir, subdirname, O_READ)) {
  387. SERIAL_PROTOCOLPGM(MSG_SD_OPEN_FILE_FAIL);
  388. SERIAL_PROTOCOL(subdirname);
  389. SERIAL_PROTOCOLCHAR('.');
  390. return;
  391. }
  392. else {
  393. //SERIAL_ECHOLNPGM("dive ok");
  394. }
  395. curDir = &myDir;
  396. dirname_start = dirname_end + 1;
  397. }
  398. else { // the remainder after all /fsa/fdsa/ is the filename
  399. fname = dirname_start;
  400. //SERIAL_ECHOLNPGM("remainder");
  401. //SERIAL_ECHOLN(fname);
  402. break;
  403. }
  404. }
  405. }
  406. else
  407. curDir = &workDir; // Relative paths start in current directory
  408. if (read) {
  409. if (file.open(curDir, fname, O_READ)) {
  410. filesize = file.fileSize();
  411. sdpos = 0;
  412. SERIAL_PROTOCOLPAIR(MSG_SD_FILE_OPENED, fname);
  413. SERIAL_PROTOCOLLNPAIR(MSG_SD_SIZE, filesize);
  414. SERIAL_PROTOCOLLNPGM(MSG_SD_FILE_SELECTED);
  415. getfilename(0, fname);
  416. lcd_setstatus(longFilename[0] ? longFilename : fname);
  417. //if (longFilename[0]) {
  418. // SERIAL_PROTOCOLPAIR(MSG_SD_FILE_LONG_NAME, longFilename);
  419. //}
  420. }
  421. else {
  422. SERIAL_PROTOCOLPAIR(MSG_SD_OPEN_FILE_FAIL, fname);
  423. SERIAL_PROTOCOLCHAR('.');
  424. SERIAL_EOL();
  425. }
  426. }
  427. else { //write
  428. if (!file.open(curDir, fname, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)) {
  429. SERIAL_PROTOCOLPAIR(MSG_SD_OPEN_FILE_FAIL, fname);
  430. SERIAL_PROTOCOLCHAR('.');
  431. SERIAL_EOL();
  432. }
  433. else {
  434. saving = true;
  435. SERIAL_PROTOCOLLNPAIR(MSG_SD_WRITE_TO_FILE, name);
  436. lcd_setstatus(fname);
  437. }
  438. }
  439. }
  440. void CardReader::removeFile(const char * const name) {
  441. if (!cardOK) return;
  442. stopSDPrint();
  443. SdFile myDir;
  444. curDir = &root;
  445. const char *fname = name;
  446. char *dirname_start, *dirname_end;
  447. if (name[0] == '/') {
  448. dirname_start = strchr(name, '/') + 1;
  449. while (dirname_start != NULL) {
  450. dirname_end = strchr(dirname_start, '/');
  451. //SERIAL_ECHOPGM("start:");SERIAL_ECHOLN((int)(dirname_start - name));
  452. //SERIAL_ECHOPGM("end :");SERIAL_ECHOLN((int)(dirname_end - name));
  453. if (dirname_end != NULL && dirname_end > dirname_start) {
  454. char subdirname[FILENAME_LENGTH];
  455. strncpy(subdirname, dirname_start, dirname_end - dirname_start);
  456. subdirname[dirname_end - dirname_start] = 0;
  457. SERIAL_ECHOLN(subdirname);
  458. if (!myDir.open(curDir, subdirname, O_READ)) {
  459. SERIAL_PROTOCOLPAIR(MSG_SD_OPEN_FILE_FAIL, subdirname);
  460. SERIAL_PROTOCOLCHAR('.');
  461. SERIAL_EOL();
  462. return;
  463. }
  464. curDir = &myDir;
  465. dirname_start = dirname_end + 1;
  466. }
  467. else {
  468. fname = dirname_start;
  469. break;
  470. }
  471. }
  472. }
  473. else // Relative paths are rooted in the current directory
  474. curDir = &workDir;
  475. if (file.remove(curDir, fname)) {
  476. SERIAL_PROTOCOLPGM("File deleted:");
  477. SERIAL_PROTOCOLLN(fname);
  478. sdpos = 0;
  479. #if ENABLED(SDCARD_SORT_ALPHA)
  480. presort();
  481. #endif
  482. }
  483. else {
  484. SERIAL_PROTOCOLPGM("Deletion failed, File: ");
  485. SERIAL_PROTOCOL(fname);
  486. SERIAL_PROTOCOLCHAR('.');
  487. }
  488. }
  489. void CardReader::getStatus(
  490. #if NUM_SERIAL > 1
  491. const int8_t port/*= -1*/
  492. #endif
  493. ) {
  494. if (cardOK && sdprinting) {
  495. SERIAL_PROTOCOLPGM_P(port, MSG_SD_PRINTING_BYTE);
  496. SERIAL_PROTOCOL_P(port, sdpos);
  497. SERIAL_PROTOCOLCHAR_P(port, '/');
  498. SERIAL_PROTOCOLLN_P(port, filesize);
  499. }
  500. else
  501. SERIAL_PROTOCOLLNPGM_P(port, MSG_SD_NOT_PRINTING);
  502. }
  503. void CardReader::write_command(char *buf) {
  504. char* begin = buf;
  505. char* npos = NULL;
  506. char* end = buf + strlen(buf) - 1;
  507. file.writeError = false;
  508. if ((npos = strchr(buf, 'N')) != NULL) {
  509. begin = strchr(npos, ' ') + 1;
  510. end = strchr(npos, '*') - 1;
  511. }
  512. end[1] = '\r';
  513. end[2] = '\n';
  514. end[3] = '\0';
  515. file.write(begin);
  516. if (file.writeError) {
  517. SERIAL_ERROR_START();
  518. SERIAL_ERRORLNPGM(MSG_SD_ERR_WRITE_TO_FILE);
  519. }
  520. }
  521. void CardReader::checkautostart(bool force) {
  522. if (!force && (!autostart_stilltocheck || PENDING(millis(), next_autostart_ms)))
  523. return;
  524. autostart_stilltocheck = false;
  525. if (!cardOK) {
  526. initsd();
  527. if (!cardOK) return; // fail
  528. }
  529. char autoname[10];
  530. sprintf_P(autoname, PSTR("auto%i.g"), autostart_index);
  531. for (int8_t i = 0; i < (int8_t)strlen(autoname); i++) autoname[i] = tolower(autoname[i]);
  532. dir_t p;
  533. root.rewind();
  534. bool found = false;
  535. while (root.readDir(p, NULL) > 0) {
  536. for (int8_t i = (int8_t)strlen((char*)p.name); i--;) p.name[i] = tolower(p.name[i]);
  537. if (p.name[9] != '~' && strncmp((char*)p.name, autoname, 5) == 0) {
  538. openAndPrintFile(autoname);
  539. found = true;
  540. }
  541. }
  542. if (!found)
  543. autostart_index = -1;
  544. else
  545. autostart_index++;
  546. }
  547. void CardReader::closefile(bool store_location) {
  548. file.sync();
  549. file.close();
  550. saving = logging = false;
  551. if (store_location) {
  552. //future: store printer state, filename and position for continuing a stopped print
  553. // so one can unplug the printer and continue printing the next day.
  554. }
  555. }
  556. /**
  557. * Get the name of a file in the current directory by index
  558. */
  559. void CardReader::getfilename(uint16_t nr, const char * const match/*=NULL*/) {
  560. #if ENABLED(SDSORT_CACHE_NAMES)
  561. if (match != NULL) {
  562. while (nr < sort_count) {
  563. if (strcasecmp(match, sortshort[nr]) == 0) break;
  564. nr++;
  565. }
  566. }
  567. if (nr < sort_count) {
  568. strcpy(filename, sortshort[nr]);
  569. strcpy(longFilename, sortnames[nr]);
  570. filenameIsDir = TEST(isDir[nr>>3], nr & 0x07);
  571. return;
  572. }
  573. #endif // SDSORT_CACHE_NAMES
  574. curDir = &workDir;
  575. lsAction = LS_GetFilename;
  576. nrFile_index = nr;
  577. curDir->rewind();
  578. lsDive(NULL, *curDir, match);
  579. }
  580. uint16_t CardReader::getnrfilenames() {
  581. curDir = &workDir;
  582. lsAction = LS_Count;
  583. nrFiles = 0;
  584. curDir->rewind();
  585. lsDive(NULL, *curDir);
  586. //SERIAL_ECHOLN(nrFiles);
  587. return nrFiles;
  588. }
  589. void CardReader::chdir(const char * relpath) {
  590. SdFile newDir;
  591. SdFile *parent = &root;
  592. if (workDir.isOpen()) parent = &workDir;
  593. if (!newDir.open(*parent, relpath, O_READ)) {
  594. SERIAL_ECHO_START();
  595. SERIAL_ECHOPGM(MSG_SD_CANT_ENTER_SUBDIR);
  596. SERIAL_ECHOLN(relpath);
  597. }
  598. else {
  599. workDir = newDir;
  600. if (workDirDepth < MAX_DIR_DEPTH)
  601. workDirParents[workDirDepth++] = workDir;
  602. #if ENABLED(SDCARD_SORT_ALPHA)
  603. presort();
  604. #endif
  605. }
  606. }
  607. int8_t CardReader::updir() {
  608. if (workDirDepth > 0) { // At least 1 dir has been saved
  609. workDir = --workDirDepth ? workDirParents[workDirDepth - 1] : root; // Use parent, or root if none
  610. #if ENABLED(SDCARD_SORT_ALPHA)
  611. presort();
  612. #endif
  613. }
  614. return workDirDepth;
  615. }
  616. #if ENABLED(SDCARD_SORT_ALPHA)
  617. /**
  618. * Get the name of a file in the current directory by sort-index
  619. */
  620. void CardReader::getfilename_sorted(const uint16_t nr) {
  621. getfilename(
  622. #if ENABLED(SDSORT_GCODE)
  623. sort_alpha &&
  624. #endif
  625. (nr < sort_count) ? sort_order[nr] : nr
  626. );
  627. }
  628. /**
  629. * Read all the files and produce a sort key
  630. *
  631. * We can do this in 3 ways...
  632. * - Minimal RAM: Read two filenames at a time sorting along...
  633. * - Some RAM: Buffer the directory just for this sort
  634. * - Most RAM: Buffer the directory and return filenames from RAM
  635. */
  636. void CardReader::presort() {
  637. // Throw away old sort index
  638. flush_presort();
  639. // Sorting may be turned off
  640. #if ENABLED(SDSORT_GCODE)
  641. if (!sort_alpha) return;
  642. #endif
  643. // If there are files, sort up to the limit
  644. uint16_t fileCnt = getnrfilenames();
  645. if (fileCnt > 0) {
  646. // Never sort more than the max allowed
  647. // If you use folders to organize, 20 may be enough
  648. if (fileCnt > SDSORT_LIMIT) fileCnt = SDSORT_LIMIT;
  649. // Sort order is always needed. May be static or dynamic.
  650. #if ENABLED(SDSORT_DYNAMIC_RAM)
  651. sort_order = new uint8_t[fileCnt];
  652. #endif
  653. // Use RAM to store the entire directory during pre-sort.
  654. // SDSORT_LIMIT should be set to prevent over-allocation.
  655. #if ENABLED(SDSORT_USES_RAM)
  656. // If using dynamic ram for names, allocate on the heap.
  657. #if ENABLED(SDSORT_CACHE_NAMES)
  658. #if ENABLED(SDSORT_DYNAMIC_RAM)
  659. sortshort = new char*[fileCnt];
  660. sortnames = new char*[fileCnt];
  661. #endif
  662. #elif ENABLED(SDSORT_USES_STACK)
  663. char sortnames[fileCnt][SORTED_LONGNAME_MAXLEN];
  664. #endif
  665. // Folder sorting needs 1 bit per entry for flags.
  666. #if HAS_FOLDER_SORTING
  667. #if ENABLED(SDSORT_DYNAMIC_RAM)
  668. isDir = new uint8_t[(fileCnt + 7) >> 3];
  669. #elif ENABLED(SDSORT_USES_STACK)
  670. uint8_t isDir[(fileCnt + 7) >> 3];
  671. #endif
  672. #endif
  673. #else // !SDSORT_USES_RAM
  674. // By default re-read the names from SD for every compare
  675. // retaining only two filenames at a time. This is very
  676. // slow but is safest and uses minimal RAM.
  677. char name1[LONG_FILENAME_LENGTH + 1];
  678. #endif
  679. if (fileCnt > 1) {
  680. // Init sort order.
  681. for (uint16_t i = 0; i < fileCnt; i++) {
  682. sort_order[i] = i;
  683. // If using RAM then read all filenames now.
  684. #if ENABLED(SDSORT_USES_RAM)
  685. getfilename(i);
  686. #if ENABLED(SDSORT_DYNAMIC_RAM)
  687. // Use dynamic method to copy long filename
  688. sortnames[i] = strdup(LONGEST_FILENAME);
  689. #if ENABLED(SDSORT_CACHE_NAMES)
  690. // When caching also store the short name, since
  691. // we're replacing the getfilename() behavior.
  692. sortshort[i] = strdup(filename);
  693. #endif
  694. #else
  695. // Copy filenames into the static array
  696. #if SORTED_LONGNAME_MAXLEN != LONG_FILENAME_LENGTH
  697. strncpy(sortnames[i], LONGEST_FILENAME, SORTED_LONGNAME_MAXLEN);
  698. sortnames[i][SORTED_LONGNAME_MAXLEN - 1] = '\0';
  699. #else
  700. strncpy(sortnames[i], LONGEST_FILENAME, SORTED_LONGNAME_MAXLEN);
  701. #endif
  702. #if ENABLED(SDSORT_CACHE_NAMES)
  703. strcpy(sortshort[i], filename);
  704. #endif
  705. #endif
  706. // char out[30];
  707. // sprintf_P(out, PSTR("---- %i %s %s"), i, filenameIsDir ? "D" : " ", sortnames[i]);
  708. // SERIAL_ECHOLN(out);
  709. #if HAS_FOLDER_SORTING
  710. const uint16_t bit = i & 0x07, ind = i >> 3;
  711. if (bit == 0) isDir[ind] = 0x00;
  712. if (filenameIsDir) isDir[ind] |= _BV(bit);
  713. #endif
  714. #endif
  715. }
  716. // Bubble Sort
  717. for (uint16_t i = fileCnt; --i;) {
  718. bool didSwap = false;
  719. for (uint16_t j = 0; j < i; ++j) {
  720. const uint16_t o1 = sort_order[j], o2 = sort_order[j + 1];
  721. // Compare names from the array or just the two buffered names
  722. #if ENABLED(SDSORT_USES_RAM)
  723. #define _SORT_CMP_NODIR() (strcasecmp(sortnames[o1], sortnames[o2]) > 0)
  724. #else
  725. #define _SORT_CMP_NODIR() (strcasecmp(name1, name2) > 0)
  726. #endif
  727. #if HAS_FOLDER_SORTING
  728. #if ENABLED(SDSORT_USES_RAM)
  729. // Folder sorting needs an index and bit to test for folder-ness.
  730. const uint8_t ind1 = o1 >> 3, bit1 = o1 & 0x07,
  731. ind2 = o2 >> 3, bit2 = o2 & 0x07;
  732. #define _SORT_CMP_DIR(fs) \
  733. (((isDir[ind1] & _BV(bit1)) != 0) == ((isDir[ind2] & _BV(bit2)) != 0) \
  734. ? _SORT_CMP_NODIR() \
  735. : (isDir[fs > 0 ? ind1 : ind2] & (fs > 0 ? _BV(bit1) : _BV(bit2))) != 0)
  736. #else
  737. #define _SORT_CMP_DIR(fs) ((dir1 == filenameIsDir) ? _SORT_CMP_NODIR() : (fs > 0 ? dir1 : !dir1))
  738. #endif
  739. #endif
  740. // The most economical method reads names as-needed
  741. // throughout the loop. Slow if there are many.
  742. #if DISABLED(SDSORT_USES_RAM)
  743. getfilename(o1);
  744. strcpy(name1, LONGEST_FILENAME); // save (or getfilename below will trounce it)
  745. #if HAS_FOLDER_SORTING
  746. bool dir1 = filenameIsDir;
  747. #endif
  748. getfilename(o2);
  749. char *name2 = LONGEST_FILENAME; // use the string in-place
  750. #endif // !SDSORT_USES_RAM
  751. // Sort the current pair according to settings.
  752. if (
  753. #if HAS_FOLDER_SORTING
  754. #if ENABLED(SDSORT_GCODE)
  755. sort_folders ? _SORT_CMP_DIR(sort_folders) : _SORT_CMP_NODIR()
  756. #else
  757. _SORT_CMP_DIR(FOLDER_SORTING)
  758. #endif
  759. #else
  760. _SORT_CMP_NODIR()
  761. #endif
  762. ) {
  763. sort_order[j] = o2;
  764. sort_order[j + 1] = o1;
  765. didSwap = true;
  766. }
  767. }
  768. if (!didSwap) break;
  769. }
  770. // Using RAM but not keeping names around
  771. #if ENABLED(SDSORT_USES_RAM) && DISABLED(SDSORT_CACHE_NAMES)
  772. #if ENABLED(SDSORT_DYNAMIC_RAM)
  773. for (uint16_t i = 0; i < fileCnt; ++i) free(sortnames[i]);
  774. #if HAS_FOLDER_SORTING
  775. free(isDir);
  776. #endif
  777. #endif
  778. #endif
  779. }
  780. else {
  781. sort_order[0] = 0;
  782. #if ENABLED(SDSORT_USES_RAM) && ENABLED(SDSORT_CACHE_NAMES)
  783. getfilename(0);
  784. #if ENABLED(SDSORT_DYNAMIC_RAM)
  785. sortnames = new char*[1];
  786. sortnames[0] = strdup(LONGEST_FILENAME); // malloc
  787. #if ENABLED(SDSORT_CACHE_NAMES)
  788. sortshort = new char*[1];
  789. sortshort[0] = strdup(filename); // malloc
  790. #endif
  791. isDir = new uint8_t[1];
  792. #else
  793. #if SORTED_LONGNAME_MAXLEN != LONG_FILENAME_LENGTH
  794. strncpy(sortnames[0], LONGEST_FILENAME, SORTED_LONGNAME_MAXLEN);
  795. sortnames[0][SORTED_LONGNAME_MAXLEN - 1] = '\0';
  796. #else
  797. strncpy(sortnames[0], LONGEST_FILENAME, SORTED_LONGNAME_MAXLEN);
  798. #endif
  799. #if ENABLED(SDSORT_CACHE_NAMES)
  800. strcpy(sortshort[0], filename);
  801. #endif
  802. #endif
  803. isDir[0] = filenameIsDir ? 0x01 : 0x00;
  804. #endif
  805. }
  806. sort_count = fileCnt;
  807. }
  808. }
  809. void CardReader::flush_presort() {
  810. if (sort_count > 0) {
  811. #if ENABLED(SDSORT_DYNAMIC_RAM)
  812. delete sort_order;
  813. #if ENABLED(SDSORT_CACHE_NAMES)
  814. for (uint8_t i = 0; i < sort_count; ++i) {
  815. free(sortshort[i]); // strdup
  816. free(sortnames[i]); // strdup
  817. }
  818. delete sortshort;
  819. delete sortnames;
  820. #endif
  821. #endif
  822. sort_count = 0;
  823. }
  824. }
  825. #endif // SDCARD_SORT_ALPHA
  826. uint16_t CardReader::get_num_Files() {
  827. return
  828. #if ENABLED(SDCARD_SORT_ALPHA) && SDSORT_USES_RAM && SDSORT_CACHE_NAMES
  829. nrFiles // no need to access the SD card for filenames
  830. #else
  831. getnrfilenames()
  832. #endif
  833. ;
  834. }
  835. void CardReader::printingHasFinished() {
  836. stepper.synchronize();
  837. file.close();
  838. if (file_subcall_ctr > 0) { // Heading up to a parent file that called current as a procedure.
  839. file_subcall_ctr--;
  840. openFile(proc_filenames[file_subcall_ctr], true, true);
  841. setIndex(filespos[file_subcall_ctr]);
  842. startFileprint();
  843. }
  844. else {
  845. sdprinting = false;
  846. #if ENABLED(POWER_LOSS_RECOVERY)
  847. openJobRecoveryFile(false);
  848. job_recovery_info.valid_head = job_recovery_info.valid_foot = 0;
  849. (void)saveJobRecoveryInfo();
  850. closeJobRecoveryFile();
  851. job_recovery_commands_count = 0;
  852. #endif
  853. #if ENABLED(SD_FINISHED_STEPPERRELEASE) && defined(SD_FINISHED_RELEASECOMMAND)
  854. stepper.cleaning_buffer_counter = 1; // The command will fire from the Stepper ISR
  855. #endif
  856. print_job_timer.stop();
  857. if (print_job_timer.duration() > 60)
  858. enqueue_and_echo_commands_P(PSTR("M31"));
  859. #if ENABLED(SDCARD_SORT_ALPHA)
  860. presort();
  861. #endif
  862. #if ENABLED(ULTRA_LCD) && ENABLED(LCD_SET_PROGRESS_MANUALLY)
  863. progress_bar_percent = 0;
  864. #endif
  865. #if ENABLED(SD_REPRINT_LAST_SELECTED_FILE)
  866. lcd_reselect_last_file();
  867. #endif
  868. }
  869. }
  870. #if ENABLED(AUTO_REPORT_SD_STATUS)
  871. uint8_t CardReader::auto_report_sd_interval = 0;
  872. millis_t CardReader::next_sd_report_ms;
  873. #if NUM_SERIAL > 1
  874. int8_t CardReader::serialport;
  875. #endif
  876. void CardReader::auto_report_sd_status() {
  877. millis_t current_ms = millis();
  878. if (auto_report_sd_interval && ELAPSED(current_ms, next_sd_report_ms)) {
  879. next_sd_report_ms = current_ms + 1000UL * auto_report_sd_interval;
  880. getStatus(
  881. #if NUM_SERIAL > 1
  882. serialport
  883. #endif
  884. );
  885. }
  886. }
  887. #endif // AUTO_REPORT_SD_STATUS
  888. #if ENABLED(POWER_LOSS_RECOVERY)
  889. char job_recovery_file_name[4] = "bin";
  890. void CardReader::openJobRecoveryFile(const bool read) {
  891. if (!cardOK) return;
  892. if (jobRecoveryFile.isOpen()) return;
  893. if (!jobRecoveryFile.open(&root, job_recovery_file_name, read ? O_READ : O_CREAT | O_WRITE | O_TRUNC | O_SYNC)) {
  894. SERIAL_PROTOCOLPAIR(MSG_SD_OPEN_FILE_FAIL, job_recovery_file_name);
  895. SERIAL_PROTOCOLCHAR('.');
  896. SERIAL_EOL();
  897. }
  898. else
  899. SERIAL_PROTOCOLLNPAIR(MSG_SD_WRITE_TO_FILE, job_recovery_file_name);
  900. }
  901. void CardReader::closeJobRecoveryFile() { jobRecoveryFile.close(); }
  902. bool CardReader::jobRecoverFileExists() {
  903. return jobRecoveryFile.open(&root, job_recovery_file_name, O_READ);
  904. }
  905. int16_t CardReader::saveJobRecoveryInfo() {
  906. jobRecoveryFile.seekSet(0);
  907. const int16_t ret = jobRecoveryFile.write(&job_recovery_info, sizeof(job_recovery_info));
  908. if (ret == -1) SERIAL_PROTOCOLLNPGM("Power-loss file write failed.");
  909. return ret;
  910. }
  911. int16_t CardReader::loadJobRecoveryInfo() {
  912. return jobRecoveryFile.read(&job_recovery_info, sizeof(job_recovery_info));
  913. }
  914. void CardReader::removeJobRecoveryFile() {
  915. if (jobRecoveryFile.remove(&root, job_recovery_file_name))
  916. SERIAL_PROTOCOLLNPGM("Power-loss file deleted.");
  917. else
  918. SERIAL_PROTOCOLLNPGM("Power-loss file delete failed.");
  919. }
  920. #endif // POWER_LOSS_RECOVERY
  921. #endif // SDSUPPORT