cmdqueue.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  1. #include "cmdqueue.h"
  2. #include "cardreader.h"
  3. #include "ultralcd.h"
  4. extern bool Stopped;
  5. // Reserve BUFSIZE lines of length MAX_CMD_SIZE plus CMDBUFFER_RESERVE_FRONT.
  6. char cmdbuffer[BUFSIZE * (MAX_CMD_SIZE + 1) + CMDBUFFER_RESERVE_FRONT];
  7. // Head of the circular buffer, where to read.
  8. int bufindr = 0;
  9. // Tail of the buffer, where to write.
  10. int bufindw = 0;
  11. // Number of lines in cmdbuffer.
  12. int buflen = 0;
  13. // Flag for processing the current command inside the main Arduino loop().
  14. // If a new command was pushed to the front of a command buffer while
  15. // processing another command, this replaces the command on the top.
  16. // Therefore don't remove the command from the queue in the loop() function.
  17. bool cmdbuffer_front_already_processed = false;
  18. int serial_count = 0; //index of character read from serial line
  19. boolean comment_mode = false;
  20. char *strchr_pointer; // just a pointer to find chars in the command string like X, Y, Z, E, etc
  21. unsigned long TimeSent = millis();
  22. unsigned long TimeNow = millis();
  23. long gcode_N = 0;
  24. long gcode_LastN = 0;
  25. long Stopped_gcode_LastN = 0;
  26. uint32_t sdpos_atomic = 0;
  27. // Pop the currently processed command from the queue.
  28. // It is expected, that there is at least one command in the queue.
  29. bool cmdqueue_pop_front()
  30. {
  31. if (buflen > 0) {
  32. #ifdef CMDBUFFER_DEBUG
  33. SERIAL_ECHOPGM("Dequeing ");
  34. SERIAL_ECHO(cmdbuffer+bufindr+CMDHDRSIZE);
  35. SERIAL_ECHOLNPGM("");
  36. SERIAL_ECHOPGM("Old indices: buflen ");
  37. SERIAL_ECHO(buflen);
  38. SERIAL_ECHOPGM(", bufindr ");
  39. SERIAL_ECHO(bufindr);
  40. SERIAL_ECHOPGM(", bufindw ");
  41. SERIAL_ECHO(bufindw);
  42. SERIAL_ECHOPGM(", serial_count ");
  43. SERIAL_ECHO(serial_count);
  44. SERIAL_ECHOPGM(", bufsize ");
  45. SERIAL_ECHO(sizeof(cmdbuffer));
  46. SERIAL_ECHOLNPGM("");
  47. #endif /* CMDBUFFER_DEBUG */
  48. if (-- buflen == 0) {
  49. // Empty buffer.
  50. if (serial_count == 0)
  51. // No serial communication is pending. Reset both pointers to zero.
  52. bufindw = 0;
  53. bufindr = bufindw;
  54. } else {
  55. // There is at least one ready line in the buffer.
  56. // First skip the current command ID and iterate up to the end of the string.
  57. // for (++ bufindr; cmdbuffer[bufindr] != 0; ++ bufindr) ;
  58. for (bufindr += CMDHDRSIZE; cmdbuffer[bufindr] != 0; ++ bufindr) ;
  59. // Second, skip the end of string null character and iterate until a nonzero command ID is found.
  60. for (++ bufindr; bufindr < sizeof(cmdbuffer) && cmdbuffer[bufindr] == 0; ++ bufindr) ;
  61. // If the end of the buffer was empty,
  62. if (bufindr == sizeof(cmdbuffer)) {
  63. // skip to the start and find the nonzero command.
  64. for (bufindr = 0; cmdbuffer[bufindr] == 0; ++ bufindr) ;
  65. }
  66. #ifdef CMDBUFFER_DEBUG
  67. SERIAL_ECHOPGM("New indices: buflen ");
  68. SERIAL_ECHO(buflen);
  69. SERIAL_ECHOPGM(", bufindr ");
  70. SERIAL_ECHO(bufindr);
  71. SERIAL_ECHOPGM(", bufindw ");
  72. SERIAL_ECHO(bufindw);
  73. SERIAL_ECHOPGM(", serial_count ");
  74. SERIAL_ECHO(serial_count);
  75. SERIAL_ECHOPGM(" new command on the top: ");
  76. SERIAL_ECHO(cmdbuffer+bufindr+CMDHDRSIZE);
  77. SERIAL_ECHOLNPGM("");
  78. #endif /* CMDBUFFER_DEBUG */
  79. }
  80. return true;
  81. }
  82. return false;
  83. }
  84. void cmdqueue_reset()
  85. {
  86. while (cmdqueue_pop_front()) ;
  87. }
  88. // How long a string could be pushed to the front of the command queue?
  89. // If yes, adjust bufindr to the new position, where the new command could be enqued.
  90. // len_asked does not contain the zero terminator size.
  91. bool cmdqueue_could_enqueue_front(int len_asked)
  92. {
  93. // MAX_CMD_SIZE has to accommodate the zero terminator.
  94. if (len_asked >= MAX_CMD_SIZE)
  95. return false;
  96. // Remove the currently processed command from the queue.
  97. if (! cmdbuffer_front_already_processed) {
  98. cmdqueue_pop_front();
  99. cmdbuffer_front_already_processed = true;
  100. }
  101. if (bufindr == bufindw && buflen > 0)
  102. // Full buffer.
  103. return false;
  104. // Adjust the end of the write buffer based on whether a partial line is in the receive buffer.
  105. int endw = (serial_count > 0) ? (bufindw + MAX_CMD_SIZE + 1) : bufindw;
  106. if (bufindw < bufindr) {
  107. int bufindr_new = bufindr - len_asked - (1 + CMDHDRSIZE);
  108. // Simple case. There is a contiguous space between the write buffer and the read buffer.
  109. if (endw <= bufindr_new) {
  110. bufindr = bufindr_new;
  111. return true;
  112. }
  113. } else {
  114. // Otherwise the free space is split between the start and end.
  115. if (len_asked + (1 + CMDHDRSIZE) <= bufindr) {
  116. // Could fit at the start.
  117. bufindr -= len_asked + (1 + CMDHDRSIZE);
  118. return true;
  119. }
  120. int bufindr_new = sizeof(cmdbuffer) - len_asked - (1 + CMDHDRSIZE);
  121. if (endw <= bufindr_new) {
  122. memset(cmdbuffer, 0, bufindr);
  123. bufindr = bufindr_new;
  124. return true;
  125. }
  126. }
  127. return false;
  128. }
  129. // Could one enqueue a command of lenthg len_asked into the buffer,
  130. // while leaving CMDBUFFER_RESERVE_FRONT at the start?
  131. // If yes, adjust bufindw to the new position, where the new command could be enqued.
  132. // len_asked does not contain the zero terminator size.
  133. bool cmdqueue_could_enqueue_back(int len_asked)
  134. {
  135. // MAX_CMD_SIZE has to accommodate the zero terminator.
  136. if (len_asked >= MAX_CMD_SIZE)
  137. return false;
  138. if (bufindr == bufindw && buflen > 0)
  139. // Full buffer.
  140. return false;
  141. if (serial_count > 0) {
  142. // If there is some data stored starting at bufindw, len_asked is certainly smaller than
  143. // the allocated data buffer. Try to reserve a new buffer and to move the already received
  144. // serial data.
  145. // How much memory to reserve for the commands pushed to the front?
  146. // End of the queue, when pushing to the end.
  147. int endw = bufindw + len_asked + (1 + CMDHDRSIZE);
  148. if (bufindw < bufindr)
  149. // Simple case. There is a contiguous space between the write buffer and the read buffer.
  150. return endw + CMDBUFFER_RESERVE_FRONT <= bufindr;
  151. // Otherwise the free space is split between the start and end.
  152. if (// Could one fit to the end, including the reserve?
  153. endw + CMDBUFFER_RESERVE_FRONT <= sizeof(cmdbuffer) ||
  154. // Could one fit to the end, and the reserve to the start?
  155. (endw <= sizeof(cmdbuffer) && CMDBUFFER_RESERVE_FRONT <= bufindr))
  156. return true;
  157. // Could one fit both to the start?
  158. if (len_asked + (1 + CMDHDRSIZE) + CMDBUFFER_RESERVE_FRONT <= bufindr) {
  159. // Mark the rest of the buffer as used.
  160. memset(cmdbuffer+bufindw, 0, sizeof(cmdbuffer)-bufindw);
  161. // and point to the start.
  162. bufindw = 0;
  163. return true;
  164. }
  165. } else {
  166. // How much memory to reserve for the commands pushed to the front?
  167. // End of the queue, when pushing to the end.
  168. int endw = bufindw + len_asked + (1 + CMDHDRSIZE);
  169. if (bufindw < bufindr)
  170. // Simple case. There is a contiguous space between the write buffer and the read buffer.
  171. return endw + CMDBUFFER_RESERVE_FRONT <= bufindr;
  172. // Otherwise the free space is split between the start and end.
  173. if (// Could one fit to the end, including the reserve?
  174. endw + CMDBUFFER_RESERVE_FRONT <= sizeof(cmdbuffer) ||
  175. // Could one fit to the end, and the reserve to the start?
  176. (endw <= sizeof(cmdbuffer) && CMDBUFFER_RESERVE_FRONT <= bufindr))
  177. return true;
  178. // Could one fit both to the start?
  179. if (len_asked + (1 + CMDHDRSIZE) + CMDBUFFER_RESERVE_FRONT <= bufindr) {
  180. // Mark the rest of the buffer as used.
  181. memset(cmdbuffer+bufindw, 0, sizeof(cmdbuffer)-bufindw);
  182. // and point to the start.
  183. bufindw = 0;
  184. return true;
  185. }
  186. }
  187. return false;
  188. }
  189. #ifdef CMDBUFFER_DEBUG
  190. void cmdqueue_dump_to_serial_single_line(int nr, const char *p)
  191. {
  192. SERIAL_ECHOPGM("Entry nr: ");
  193. SERIAL_ECHO(nr);
  194. SERIAL_ECHOPGM(", type: ");
  195. SERIAL_ECHO(int(*p));
  196. SERIAL_ECHOPGM(", cmd: ");
  197. SERIAL_ECHO(p+1);
  198. SERIAL_ECHOLNPGM("");
  199. }
  200. void cmdqueue_dump_to_serial()
  201. {
  202. if (buflen == 0) {
  203. SERIAL_ECHOLNPGM("The command buffer is empty.");
  204. } else {
  205. SERIAL_ECHOPGM("Content of the buffer: entries ");
  206. SERIAL_ECHO(buflen);
  207. SERIAL_ECHOPGM(", indr ");
  208. SERIAL_ECHO(bufindr);
  209. SERIAL_ECHOPGM(", indw ");
  210. SERIAL_ECHO(bufindw);
  211. SERIAL_ECHOLNPGM("");
  212. int nr = 0;
  213. if (bufindr < bufindw) {
  214. for (const char *p = cmdbuffer + bufindr; p < cmdbuffer + bufindw; ++ nr) {
  215. cmdqueue_dump_to_serial_single_line(nr, p);
  216. // Skip the command.
  217. for (++p; *p != 0; ++ p);
  218. // Skip the gaps.
  219. for (++p; p < cmdbuffer + bufindw && *p == 0; ++ p);
  220. }
  221. } else {
  222. for (const char *p = cmdbuffer + bufindr; p < cmdbuffer + sizeof(cmdbuffer); ++ nr) {
  223. cmdqueue_dump_to_serial_single_line(nr, p);
  224. // Skip the command.
  225. for (++p; *p != 0; ++ p);
  226. // Skip the gaps.
  227. for (++p; p < cmdbuffer + sizeof(cmdbuffer) && *p == 0; ++ p);
  228. }
  229. for (const char *p = cmdbuffer; p < cmdbuffer + bufindw; ++ nr) {
  230. cmdqueue_dump_to_serial_single_line(nr, p);
  231. // Skip the command.
  232. for (++p; *p != 0; ++ p);
  233. // Skip the gaps.
  234. for (++p; p < cmdbuffer + bufindw && *p == 0; ++ p);
  235. }
  236. }
  237. SERIAL_ECHOLNPGM("End of the buffer.");
  238. }
  239. }
  240. #endif /* CMDBUFFER_DEBUG */
  241. //adds an command to the main command buffer
  242. //thats really done in a non-safe way.
  243. //needs overworking someday
  244. // Currently the maximum length of a command piped through this function is around 20 characters
  245. void enquecommand(const char *cmd, bool from_progmem)
  246. {
  247. int len = from_progmem ? strlen_P(cmd) : strlen(cmd);
  248. // Does cmd fit the queue while leaving sufficient space at the front for the chained commands?
  249. // If it fits, it may move bufindw, so it points to a contiguous buffer, which fits cmd.
  250. if (cmdqueue_could_enqueue_back(len)) {
  251. // This is dangerous if a mixing of serial and this happens
  252. // This may easily be tested: If serial_count > 0, we have a problem.
  253. cmdbuffer[bufindw] = CMDBUFFER_CURRENT_TYPE_UI;
  254. if (from_progmem)
  255. strcpy_P(cmdbuffer + bufindw + CMDHDRSIZE, cmd);
  256. else
  257. strcpy(cmdbuffer + bufindw + CMDHDRSIZE, cmd);
  258. SERIAL_ECHO_START;
  259. SERIAL_ECHORPGM(MSG_Enqueing);
  260. SERIAL_ECHO(cmdbuffer + bufindw + CMDHDRSIZE);
  261. SERIAL_ECHOLNPGM("\"");
  262. bufindw += len + (CMDHDRSIZE + 1);
  263. if (bufindw == sizeof(cmdbuffer))
  264. bufindw = 0;
  265. ++ buflen;
  266. #ifdef CMDBUFFER_DEBUG
  267. cmdqueue_dump_to_serial();
  268. #endif /* CMDBUFFER_DEBUG */
  269. } else {
  270. SERIAL_ERROR_START;
  271. SERIAL_ECHORPGM(MSG_Enqueing);
  272. if (from_progmem)
  273. SERIAL_PROTOCOLRPGM(cmd);
  274. else
  275. SERIAL_ECHO(cmd);
  276. SERIAL_ECHOLNPGM("\" failed: Buffer full!");
  277. #ifdef CMDBUFFER_DEBUG
  278. cmdqueue_dump_to_serial();
  279. #endif /* CMDBUFFER_DEBUG */
  280. }
  281. }
  282. void enquecommand_front(const char *cmd, bool from_progmem)
  283. {
  284. int len = from_progmem ? strlen_P(cmd) : strlen(cmd);
  285. // Does cmd fit the queue? This call shall move bufindr, so the command may be copied.
  286. if (cmdqueue_could_enqueue_front(len)) {
  287. cmdbuffer[bufindr] = CMDBUFFER_CURRENT_TYPE_UI;
  288. if (from_progmem)
  289. strcpy_P(cmdbuffer + bufindr + CMDHDRSIZE, cmd);
  290. else
  291. strcpy(cmdbuffer + bufindr + CMDHDRSIZE, cmd);
  292. ++ buflen;
  293. SERIAL_ECHO_START;
  294. SERIAL_ECHOPGM("Enqueing to the front: \"");
  295. SERIAL_ECHO(cmdbuffer + bufindr + CMDHDRSIZE);
  296. SERIAL_ECHOLNPGM("\"");
  297. #ifdef CMDBUFFER_DEBUG
  298. cmdqueue_dump_to_serial();
  299. #endif /* CMDBUFFER_DEBUG */
  300. } else {
  301. SERIAL_ERROR_START;
  302. SERIAL_ECHOPGM("Enqueing to the front: \"");
  303. if (from_progmem)
  304. SERIAL_PROTOCOLRPGM(cmd);
  305. else
  306. SERIAL_ECHO(cmd);
  307. SERIAL_ECHOLNPGM("\" failed: Buffer full!");
  308. #ifdef CMDBUFFER_DEBUG
  309. cmdqueue_dump_to_serial();
  310. #endif /* CMDBUFFER_DEBUG */
  311. }
  312. }
  313. // Mark the command at the top of the command queue as new.
  314. // Therefore it will not be removed from the queue.
  315. void repeatcommand_front()
  316. {
  317. cmdbuffer_front_already_processed = true;
  318. }
  319. bool is_buffer_empty()
  320. {
  321. if (buflen == 0) return true;
  322. else return false;
  323. }
  324. void get_command()
  325. {
  326. // Test and reserve space for the new command string.
  327. if (!cmdqueue_could_enqueue_back(MAX_CMD_SIZE - 1))
  328. return;
  329. bool rx_buffer_full = false; //flag that serial rx buffer is full
  330. while (MYSERIAL.available() > 0) {
  331. if (MYSERIAL.available() == RX_BUFFER_SIZE - 1) { //compare number of chars buffered in rx buffer with rx buffer size
  332. SERIAL_ECHOLNPGM("Full RX Buffer"); //if buffer was full, there is danger that reading of last gcode will not be completed
  333. rx_buffer_full = true; //sets flag that buffer was full
  334. }
  335. char serial_char = MYSERIAL.read();
  336. if (selectedSerialPort == 1)
  337. {
  338. selectedSerialPort = 0;
  339. MYSERIAL.write(serial_char); // for debuging serial line 2 in farm_mode
  340. selectedSerialPort = 1;
  341. }
  342. TimeSent = millis();
  343. TimeNow = millis();
  344. if (serial_char < 0)
  345. // Ignore extended ASCII characters. These characters have no meaning in the G-code apart from the file names
  346. // and Marlin does not support such file names anyway.
  347. // Serial characters with a highest bit set to 1 are generated when the USB cable is unplugged, leading
  348. // to a hang-up of the print process from an SD card.
  349. continue;
  350. if(serial_char == '\n' ||
  351. serial_char == '\r' ||
  352. (serial_char == ':' && comment_mode == false) ||
  353. serial_count >= (MAX_CMD_SIZE - 1) )
  354. {
  355. if(!serial_count) { //if empty line
  356. comment_mode = false; //for new command
  357. return;
  358. }
  359. cmdbuffer[bufindw+serial_count+CMDHDRSIZE] = 0; //terminate string
  360. if(!comment_mode){
  361. comment_mode = false; //for new command
  362. if ((strchr_pointer = strstr(cmdbuffer+bufindw+CMDHDRSIZE, "PRUSA")) == NULL && (strchr_pointer = strchr(cmdbuffer+bufindw+CMDHDRSIZE, 'N')) != NULL) {
  363. if ((strchr_pointer = strchr(cmdbuffer+bufindw+CMDHDRSIZE, 'N')) != NULL)
  364. {
  365. // Line number met. When sending a G-code over a serial line, each line may be stamped with its index,
  366. // and Marlin tests, whether the successive lines are stamped with an increasing line number ID.
  367. gcode_N = (strtol(strchr_pointer+1, NULL, 10));
  368. if(gcode_N != gcode_LastN+1 && (strstr_P(cmdbuffer+bufindw+CMDHDRSIZE, PSTR("M110")) == NULL) ) {
  369. // M110 - set current line number.
  370. // Line numbers not sent in succession.
  371. SERIAL_ERROR_START;
  372. SERIAL_ERRORRPGM(MSG_ERR_LINE_NO);
  373. SERIAL_ERRORLN(gcode_LastN);
  374. //Serial.println(gcode_N);
  375. FlushSerialRequestResend();
  376. serial_count = 0;
  377. return;
  378. }
  379. if((strchr_pointer = strchr(cmdbuffer+bufindw+CMDHDRSIZE, '*')) != NULL)
  380. {
  381. byte checksum = 0;
  382. char *p = cmdbuffer+bufindw+CMDHDRSIZE;
  383. while (p != strchr_pointer)
  384. checksum = checksum^(*p++);
  385. if (int(strtol(strchr_pointer+1, NULL, 10)) != int(checksum)) {
  386. SERIAL_ERROR_START;
  387. SERIAL_ERRORRPGM(MSG_ERR_CHECKSUM_MISMATCH);
  388. SERIAL_ERRORLN(gcode_LastN);
  389. FlushSerialRequestResend();
  390. serial_count = 0;
  391. return;
  392. }
  393. // If no errors, remove the checksum and continue parsing.
  394. *strchr_pointer = 0;
  395. }
  396. else
  397. {
  398. SERIAL_ERROR_START;
  399. SERIAL_ERRORRPGM(MSG_ERR_NO_CHECKSUM);
  400. SERIAL_ERRORLN(gcode_LastN);
  401. FlushSerialRequestResend();
  402. serial_count = 0;
  403. return;
  404. }
  405. gcode_LastN = gcode_N;
  406. //if no errors, continue parsing
  407. } // end of 'N' command
  408. }
  409. else // if we don't receive 'N' but still see '*'
  410. {
  411. if((strchr(cmdbuffer+bufindw+CMDHDRSIZE, '*') != NULL))
  412. {
  413. SERIAL_ERROR_START;
  414. SERIAL_ERRORRPGM(MSG_ERR_NO_LINENUMBER_WITH_CHECKSUM);
  415. SERIAL_ERRORLN(gcode_LastN);
  416. serial_count = 0;
  417. return;
  418. }
  419. } // end of '*' command
  420. if ((strchr_pointer = strchr(cmdbuffer+bufindw+CMDHDRSIZE, 'G')) != NULL) {
  421. if (! IS_SD_PRINTING) {
  422. usb_printing_counter = 10;
  423. is_usb_printing = true;
  424. }
  425. if (Stopped == true) {
  426. int gcode = strtol(strchr_pointer+1, NULL, 10);
  427. if (gcode >= 0 && gcode <= 3) {
  428. SERIAL_ERRORLNRPGM(MSG_ERR_STOPPED);
  429. LCD_MESSAGERPGM(MSG_STOPPED);
  430. }
  431. }
  432. } // end of 'G' command
  433. //If command was e-stop process now
  434. if(strcmp(cmdbuffer+bufindw+CMDHDRSIZE, "M112") == 0)
  435. kill("", 2);
  436. // Store the current line into buffer, move to the next line.
  437. cmdbuffer[bufindw] = CMDBUFFER_CURRENT_TYPE_USB;
  438. #ifdef CMDBUFFER_DEBUG
  439. SERIAL_ECHO_START;
  440. SERIAL_ECHOPGM("Storing a command line to buffer: ");
  441. SERIAL_ECHO(cmdbuffer+bufindw+CMDHDRSIZE);
  442. SERIAL_ECHOLNPGM("");
  443. #endif /* CMDBUFFER_DEBUG */
  444. bufindw += strlen(cmdbuffer+bufindw+CMDHDRSIZE) + (1 + CMDHDRSIZE);
  445. if (bufindw == sizeof(cmdbuffer))
  446. bufindw = 0;
  447. ++ buflen;
  448. #ifdef CMDBUFFER_DEBUG
  449. SERIAL_ECHOPGM("Number of commands in the buffer: ");
  450. SERIAL_ECHO(buflen);
  451. SERIAL_ECHOLNPGM("");
  452. #endif /* CMDBUFFER_DEBUG */
  453. } // end of 'not comment mode'
  454. serial_count = 0; //clear buffer
  455. // Don't call cmdqueue_could_enqueue_back if there are no characters waiting
  456. // in the queue, as this function will reserve the memory.
  457. if (MYSERIAL.available() == 0 || ! cmdqueue_could_enqueue_back(MAX_CMD_SIZE-1))
  458. return;
  459. } // end of "end of line" processing
  460. else {
  461. // Not an "end of line" symbol. Store the new character into a buffer.
  462. if(serial_char == ';') comment_mode = true;
  463. if(!comment_mode) cmdbuffer[bufindw+CMDHDRSIZE+serial_count++] = serial_char;
  464. }
  465. } // end of serial line processing loop
  466. if(farm_mode){
  467. TimeNow = millis();
  468. if ( ((TimeNow - TimeSent) > 800) && (serial_count > 0) ) {
  469. cmdbuffer[bufindw+serial_count+CMDHDRSIZE] = 0;
  470. bufindw += strlen(cmdbuffer+bufindw+CMDHDRSIZE) + (1 + CMDHDRSIZE);
  471. if (bufindw == sizeof(cmdbuffer))
  472. bufindw = 0;
  473. ++ buflen;
  474. serial_count = 0;
  475. SERIAL_ECHOPGM("TIMEOUT:");
  476. //memset(cmdbuffer, 0 , sizeof(cmdbuffer));
  477. return;
  478. }
  479. }
  480. //add comment
  481. if (rx_buffer_full == true && serial_count > 0) { //if rx buffer was full and string was not properly terminated
  482. rx_buffer_full = false;
  483. bufindw = bufindw - serial_count; //adjust tail of the buffer to prepare buffer for writing new command
  484. serial_count = 0;
  485. }
  486. #ifdef SDSUPPORT
  487. if(!card.sdprinting || serial_count!=0){
  488. // If there is a half filled buffer from serial line, wait until return before
  489. // continuing with the serial line.
  490. return;
  491. }
  492. //'#' stops reading from SD to the buffer prematurely, so procedural macro calls are possible
  493. // if it occurs, stop_buffering is triggered and the buffer is ran dry.
  494. // this character _can_ occur in serial com, due to checksums. however, no checksums are used in SD printing
  495. static bool stop_buffering=false;
  496. if(buflen==0) stop_buffering=false;
  497. unsigned char sd_count = 0;
  498. // Reads whole lines from the SD card. Never leaves a half-filled line in the cmdbuffer.
  499. while( !card.eof() && !stop_buffering) {
  500. int16_t n=card.get();
  501. sd_count++;
  502. char serial_char = (char)n;
  503. if(serial_char == '\n' ||
  504. serial_char == '\r' ||
  505. (serial_char == '#' && comment_mode == false) ||
  506. (serial_char == ':' && comment_mode == false) ||
  507. serial_count >= (MAX_CMD_SIZE - 1)||n==-1)
  508. {
  509. if(card.eof()){
  510. SERIAL_PROTOCOLLNRPGM(MSG_FILE_PRINTED);
  511. stoptime=millis();
  512. char time[30];
  513. unsigned long t=(stoptime-starttime-pause_time)/1000;
  514. pause_time = 0;
  515. int hours, minutes;
  516. minutes=(t/60)%60;
  517. hours=t/60/60;
  518. save_statistics(total_filament_used, t);
  519. sprintf_P(time, PSTR("%i hours %i minutes"),hours, minutes);
  520. SERIAL_ECHO_START;
  521. SERIAL_ECHOLN(time);
  522. lcd_setstatus(time);
  523. card.printingHasFinished();
  524. card.checkautostart(true);
  525. if (farm_mode)
  526. {
  527. prusa_statistics(6);
  528. lcd_commands_type = LCD_COMMAND_FARM_MODE_CONFIRM;
  529. }
  530. }
  531. if(serial_char=='#')
  532. stop_buffering=true;
  533. if(!serial_count)
  534. {
  535. comment_mode = false; //for new command
  536. return; //if empty line
  537. }
  538. cmdbuffer[bufindw+serial_count+CMDHDRSIZE] = 0; //terminate string
  539. uint8_t len = strlen(cmdbuffer+bufindw+CMDHDRSIZE) + (1 + CMDHDRSIZE);
  540. cli();
  541. cmdbuffer[bufindw] = CMDBUFFER_CURRENT_TYPE_SDCARD;
  542. cmdbuffer[bufindw+1] = sd_count;
  543. /* SERIAL_ECHOPGM("SD cmd(");
  544. MYSERIAL.print(sd_count, DEC);
  545. SERIAL_ECHOPGM(") ");
  546. SERIAL_ECHOLN(cmdbuffer+bufindw+CMDHDRSIZE);*/
  547. // SERIAL_ECHOPGM("cmdbuffer:");
  548. // MYSERIAL.print(cmdbuffer);
  549. ++ buflen;
  550. // SERIAL_ECHOPGM("buflen:");
  551. // MYSERIAL.print(buflen);
  552. bufindw += len;
  553. sdpos_atomic = card.get_sdpos();
  554. if (bufindw == sizeof(cmdbuffer))
  555. bufindw = 0;
  556. sei();
  557. comment_mode = false; //for new command
  558. serial_count = 0; //clear buffer
  559. // The following line will reserve buffer space if available.
  560. if (! cmdqueue_could_enqueue_back(MAX_CMD_SIZE-1))
  561. return;
  562. }
  563. else
  564. {
  565. if(serial_char == ';') comment_mode = true;
  566. if(!comment_mode) cmdbuffer[bufindw+CMDHDRSIZE+serial_count++] = serial_char;
  567. }
  568. }
  569. #endif //SDSUPPORT
  570. }
  571. uint16_t cmdqueue_calc_sd_length()
  572. {
  573. int _buflen = buflen;
  574. int _bufindr = bufindr;
  575. uint16_t sdlen = 0;
  576. while (_buflen--)
  577. {
  578. if (cmdbuffer[_bufindr] == CMDBUFFER_CURRENT_TYPE_SDCARD)
  579. sdlen += cmdbuffer[_bufindr + 1];
  580. //skip header, skip command
  581. for (_bufindr += CMDHDRSIZE; cmdbuffer[_bufindr] != 0; ++ _bufindr) ;
  582. //skip zeros
  583. for (++ _bufindr; _bufindr < sizeof(cmdbuffer) && cmdbuffer[_bufindr] == 0; ++ _bufindr) ;
  584. }
  585. return sdlen;
  586. }