cmdqueue.cpp 27 KB

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