Procházet zdrojové kódy

Ensure proper SD print completion (#16967)

Scott Lahteine před 4 roky
rodič
revize
5071fe82ab
No account linked to committer's email address

+ 72
- 8
Marlin/src/MarlinCore.cpp Zobrazit soubor

@@ -390,8 +390,8 @@ void startOrResumeJob() {
390 390
 
391 391
 #if ENABLED(SDSUPPORT)
392 392
 
393
-  void abortSDPrinting() {
394
-    card.stopSDPrint(
393
+  inline void abortSDPrinting() {
394
+    card.endFilePrint(
395 395
       #if SD_RESORT
396 396
         true
397 397
       #endif
@@ -412,10 +412,68 @@ void startOrResumeJob() {
412 412
     #endif
413 413
   }
414 414
 
415
-#endif
415
+  #if ENABLED(PRINTER_EVENT_LEDS)
416
+    #include "feature/leds/printer_event_leds.h"
417
+  #endif
418
+
419
+  inline void finishSDPrinting() {
420
+    bool did_state = true;
421
+    switch (card.sdprinting_done_state) {
422
+
423
+      #if ENABLED(PRINTER_EVENT_LEDS)
424
+        case 1:
425
+          printerEventLEDs.onPrintCompleted();  // Change LED color for Print Completed
426
+          break;
427
+      #endif
428
+
429
+      #if HAS_RESUME_CONTINUE                   // Display "Click to Continue..."
430
+        case 2:
431
+          did_state = queue.enqueue_P(PSTR("M0 S"
432
+            #if HAS_LCD_MENU
433
+              "1800"                            // ...for 30 minutes with LCD
434
+            #else
435
+              "60"                              // ...for 1 minute with no LCD
436
+            #endif
437
+          ));
438
+          break;
439
+      #endif
440
+
441
+      case 3: print_job_timer.stop(); break;
442
+
443
+      case 4:
444
+        did_state = print_job_timer.duration() < 60 || queue.enqueue_P(PSTR("M31"));
445
+        break;
446
+
447
+      case 5:
448
+        #if ENABLED(POWER_LOSS_RECOVERY)
449
+          recovery.purge();
450
+        #endif
451
+
452
+        #if ENABLED(SD_FINISHED_STEPPERRELEASE) && defined(SD_FINISHED_RELEASECOMMAND)
453
+          planner.finish_and_disable();
454
+        #endif
455
+
456
+        #if ENABLED(LCD_SET_PROGRESS_MANUALLY)
457
+          ui.set_progress_done();
458
+        #endif
459
+
460
+        #if ENABLED(SD_REPRINT_LAST_SELECTED_FILE)
461
+          ui.reselect_last_file();
462
+        #endif
463
+
464
+        SERIAL_ECHOLNPGM(MSG_FILE_PRINTED);
465
+
466
+      default:
467
+        did_state = false;
468
+        card.sdprinting_done_state = 0;
469
+    }
470
+    if (did_state) ++card.sdprinting_done_state;
471
+  }
472
+
473
+#endif // SDSUPPORT
416 474
 
417 475
 /**
418
- * Manage several activities:
476
+ * Minimal management of Marlin's core activities:
419 477
  *  - Check for Filament Runout
420 478
  *  - Keep the command buffer full
421 479
  *  - Check for maximum inactive time between commands
@@ -1122,10 +1180,15 @@ void setup() {
1122 1180
 /**
1123 1181
  * The main Marlin program loop
1124 1182
  *
1125
- *  - Save or log commands to SD
1126
- *  - Process available commands (if not saving)
1127
- *  - Call endstop manager
1128
- *  - Call inactivity manager
1183
+ *  - Call idle() to handle all tasks between G-code commands
1184
+ *      Note that no G-codes from the queue can be executed during idle()
1185
+ *      but many G-codes can be called directly anytime like macros.
1186
+ *  - Check whether SD card auto-start is needed now.
1187
+ *  - Check whether SD print finishing is needed now.
1188
+ *  - Run one G-code command from the immediate or main command queue
1189
+ *    and open up one space. Commands in the main queue may come from sd
1190
+ *    card, host, or by direct injection. The queue will continue to fill
1191
+ *    as long as idle() or manage_inactivity() are being called.
1129 1192
  */
1130 1193
 void loop() {
1131 1194
   do {
@@ -1135,6 +1198,7 @@ void loop() {
1135 1198
     #if ENABLED(SDSUPPORT)
1136 1199
       card.checkautostart();
1137 1200
       if (card.flag.abort_sd_printing) abortSDPrinting();
1201
+      if (card.sdprinting_done_state) finishSDPrinting();
1138 1202
     #endif
1139 1203
 
1140 1204
     queue.advance();

+ 13
- 30
Marlin/src/gcode/queue.cpp Zobrazit soubor

@@ -512,9 +512,10 @@ void GCodeQueue::get_serial_commands() {
512 512
 #if ENABLED(SDSUPPORT)
513 513
 
514 514
   /**
515
-   * Get commands from the SD Card until the command buffer is full
516
-   * or until the end of the file is reached. The special character '#'
517
-   * can also interrupt buffering.
515
+   * Get lines from the SD Card until the command buffer is full
516
+   * or until the end of the file is reached. Because this method
517
+   * always receives complete command-lines, they can go directly
518
+   * into the main command queue.
518 519
    */
519 520
   inline void GCodeQueue::get_sdcard_commands() {
520 521
     static uint8_t sd_input_state = PS_NORMAL;
@@ -527,37 +528,21 @@ void GCodeQueue::get_serial_commands() {
527 528
       const int16_t n = card.get();
528 529
       card_eof = card.eof();
529 530
       if (n < 0 && !card_eof) { SERIAL_ERROR_MSG(MSG_SD_ERR_READ); continue; }
531
+
530 532
       const char sd_char = (char)n;
531
-      if (sd_char == '\n' || sd_char == '\r' || card_eof) {
533
+      const bool is_eol = sd_char == '\n' || sd_char == '\r';
534
+      if (is_eol || card_eof) {
532 535
 
533 536
         // Reset stream state, terminate the buffer, and commit a non-empty command
537
+        if (!is_eol && sd_count) ++sd_count;          // End of file with no newline
534 538
         if (!process_line_done(sd_input_state, command_buffer[index_w], sd_count)) {
535
-          _commit_command(false);                     // Can handle last line missing a newline terminator
539
+          _commit_command(false);
536 540
           #if ENABLED(POWER_LOSS_RECOVERY)
537
-            recovery.cmd_sdpos = card.getIndex();     // Prime for the next _commit_command
541
+            recovery.cmd_sdpos = card.getIndex();     // Prime for the NEXT _commit_command
538 542
           #endif
539 543
         }
540 544
 
541
-        if (card_eof) {
542
-
543
-          card.fileHasFinished();                     // Handle end of file reached
544
-
545
-          if (!IS_SD_PRINTING()) {                    // Was it the main job file?
546
-            SERIAL_ECHOLNPGM(MSG_FILE_PRINTED);       // Tell the host the file is printed.
547
-            #if ENABLED(PRINTER_EVENT_LEDS)
548
-              printerEventLEDs.onPrintCompleted();    // Change LED color for Print Completed
549
-              #if HAS_RESUME_CONTINUE
550
-                enqueue_now_P(PSTR("M0 S"             // Display "Click to Continue..."
551
-                  #if HAS_LCD_MENU
552
-                    "1800"                            // ...for 30 minutes with LCD
553
-                  #else
554
-                    "60"                              // ...for 1 minute with no LCD
555
-                  #endif
556
-                ));
557
-              #endif
558
-            #endif
559
-          }
560
-        }
545
+        if (card_eof) card.fileHasFinished();         // Handle end of file reached
561 546
       }
562 547
       else
563 548
         process_stream_char(sd_char, sd_input_state, command_buffer[index_w], sd_count);
@@ -633,9 +618,7 @@ void GCodeQueue::advance() {
633 618
   #endif // SDSUPPORT
634 619
 
635 620
   // The queue may be reset by a command handler or by code invoked by idle() within a handler
636
-  if (length) {
637
-    --length;
638
-    if (++index_r >= BUFSIZE) index_r = 0;
639
-  }
621
+  --length;
622
+  if (++index_r >= BUFSIZE) index_r = 0;
640 623
 
641 624
 }

+ 6
- 0
Marlin/src/gcode/queue.h Zobrazit soubor

@@ -117,6 +117,12 @@ public:
117 117
    */
118 118
   static void flush_and_request_resend();
119 119
 
120
+  /**
121
+   * Attempt to enqueue a single G-code command
122
+   * and return 'true' if successful.
123
+   */
124
+  FORCE_INLINE static bool enqueue_P(const char* cmd) { return _enqueue(cmd); }
125
+
120 126
 private:
121 127
 
122 128
   static uint8_t index_w;  // Ring buffer write position

+ 1
- 1
Marlin/src/lcd/menu/menu.cpp Zobrazit soubor

@@ -324,9 +324,9 @@ void MarlinUI::_synchronize() {
324 324
   if (should_draw()) MenuItem_static::draw(LCD_HEIGHT >= 4, sync_message);
325 325
   if (no_reentry) return;
326 326
   // Make this the current handler till all moves are done
327
-  no_reentry = true;
328 327
   const screenFunc_t old_screen = currentScreen;
329 328
   goto_screen(_synchronize);
329
+  no_reentry = true;
330 330
   planner.synchronize(); // idle() is called until moves complete
331 331
   no_reentry = false;
332 332
   goto_screen(old_screen);

+ 1
- 1
Marlin/src/module/endstops.cpp Zobrazit soubor

@@ -403,7 +403,7 @@ void Endstops::event_handler() {
403 403
 
404 404
     #if BOTH(SD_ABORT_ON_ENDSTOP_HIT, SDSUPPORT)
405 405
       if (planner.abort_on_endstop_hit) {
406
-        card.stopSDPrint();
406
+        card.endFilePrint();
407 407
         quickstop_stepper();
408 408
         thermalManager.disable_all_heaters();
409 409
         print_job_timer.stop();

+ 10
- 26
Marlin/src/sd/cardreader.cpp Zobrazit soubor

@@ -28,7 +28,7 @@
28 28
 
29 29
 #include "../MarlinCore.h"
30 30
 #include "../lcd/ultralcd.h"
31
-#include "../module/planner.h"
31
+#include "../module/planner.h"        // for synchronize
32 32
 #include "../module/printcounter.h"
33 33
 #include "../core/language.h"
34 34
 #include "../gcode/queue.h"
@@ -49,6 +49,7 @@
49 49
 // public:
50 50
 
51 51
 card_flags_t CardReader::flag;
52
+uint8_t CardReader::sdprinting_done_state;
52 53
 char CardReader::filename[FILENAME_LENGTH], CardReader::longFilename[LONG_FILENAME_LENGTH];
53 54
 int8_t CardReader::autostart_index;
54 55
 
@@ -379,7 +380,7 @@ void CardReader::mount() {
379 380
 }
380 381
 
381 382
 void CardReader::release() {
382
-  stopSDPrint();
383
+  endFilePrint();
383 384
   flag.mounted = false;
384 385
 }
385 386
 
@@ -401,7 +402,7 @@ void CardReader::startFileprint() {
401 402
   }
402 403
 }
403 404
 
404
-void CardReader::stopSDPrint(
405
+void CardReader::endFilePrint(
405 406
   #if SD_RESORT
406 407
     const bool re_sort/*=false*/
407 408
   #endif
@@ -501,7 +502,7 @@ void CardReader::openFileRead(char * const path, const uint8_t subcall_type/*=0*
501 502
       break;
502 503
   }
503 504
 
504
-  stopSDPrint();
505
+  endFilePrint();
505 506
 
506 507
   SdFile *curDir;
507 508
   const char * const fname = diveToFile(true, curDir, path);
@@ -529,7 +530,7 @@ void CardReader::openFileWrite(char * const path) {
529 530
   announceOpen(2, path);
530 531
   file_subcall_ctr = 0;
531 532
 
532
-  stopSDPrint();
533
+  endFilePrint();
533 534
 
534 535
   SdFile *curDir;
535 536
   const char * const fname = diveToFile(false, curDir, path);
@@ -554,7 +555,7 @@ void CardReader::openFileWrite(char * const path) {
554 555
 void CardReader::removeFile(const char * const name) {
555 556
   if (!isMounted()) return;
556 557
 
557
-  //stopSDPrint();
558
+  //endFilePrint();
558 559
 
559 560
   SdFile *curDir;
560 561
   const char * const fname = diveToFile(false, curDir, name);
@@ -937,7 +938,7 @@ void CardReader::cdroot() {
937 938
           bool didSwap = false;
938 939
           uint8_t o1 = sort_order[0];
939 940
           #if DISABLED(SDSORT_USES_RAM)
940
-            selectFileByIndex(o1);                // Pre-fetch the first entry and save it
941
+            selectFileByIndex(o1);              // Pre-fetch the first entry and save it
941 942
             strcpy(name1, longest_filename());  // so the loop only needs one fetch
942 943
             #if HAS_FOLDER_SORTING
943 944
               bool dir1 = flag.filenameIsDir;
@@ -1073,30 +1074,13 @@ void CardReader::fileHasFinished() {
1073 1074
     startFileprint();
1074 1075
   }
1075 1076
   else {
1076
-    stopSDPrint();
1077
-
1078
-    #if ENABLED(POWER_LOSS_RECOVERY)
1079
-      recovery.purge();
1080
-    #endif
1081
-
1082
-    #if ENABLED(SD_FINISHED_STEPPERRELEASE) && defined(SD_FINISHED_RELEASECOMMAND)
1083
-      planner.finish_and_disable();
1084
-    #endif
1085
-
1086
-    print_job_timer.stop();
1087
-    queue.enqueue_now_P(print_job_timer.duration() > 60 ? PSTR("M31") : PSTR("M117"));
1077
+    endFilePrint();
1088 1078
 
1089 1079
     #if ENABLED(SDCARD_SORT_ALPHA)
1090 1080
       presort();
1091 1081
     #endif
1092 1082
 
1093
-    #if ENABLED(LCD_SET_PROGRESS_MANUALLY)
1094
-      ui.set_progress_done();
1095
-    #endif
1096
-
1097
-    #if ENABLED(SD_REPRINT_LAST_SELECTED_FILE)
1098
-      ui.reselect_last_file();
1099
-    #endif
1083
+    sdprinting_done_state = 1;
1100 1084
   }
1101 1085
 }
1102 1086
 

+ 3
- 2
Marlin/src/sd/cardreader.h Zobrazit soubor

@@ -49,6 +49,7 @@ typedef struct {
49 49
 
50 50
 class CardReader {
51 51
 public:
52
+  static uint8_t sdprinting_done_state;
52 53
   static card_flags_t flag;                         // Flags (above)
53 54
   static char filename[FILENAME_LENGTH],            // DOS 8.3 filename of the selected item
54 55
               longFilename[LONG_FILENAME_LENGTH];   // Long name of the selected item
@@ -108,9 +109,9 @@ public:
108 109
   static void openAndPrintFile(const char *name);   // (working directory)
109 110
   static void fileHasFinished();
110 111
   static void getAbsFilename(char *dst);
111
-  static void startFileprint();
112 112
   static void printFilename();
113
-  static void stopSDPrint(
113
+  static void startFileprint();
114
+  static void endFilePrint(
114 115
     #if SD_RESORT
115 116
       const bool re_sort=false
116 117
     #endif

Loading…
Zrušit
Uložit