Ensure proper SD print completion (#16967)

This commit is contained in:
Scott Lahteine 2020-02-25 22:18:14 -06:00 committed by GitHub
parent 91cff02596
commit 5071fe82ab
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 106 additions and 68 deletions

View file

@ -390,8 +390,8 @@ void startOrResumeJob() {
#if ENABLED(SDSUPPORT)
void abortSDPrinting() {
card.stopSDPrint(
inline void abortSDPrinting() {
card.endFilePrint(
#if SD_RESORT
true
#endif
@ -412,10 +412,68 @@ void startOrResumeJob() {
#endif
}
#endif
#if ENABLED(PRINTER_EVENT_LEDS)
#include "feature/leds/printer_event_leds.h"
#endif
inline void finishSDPrinting() {
bool did_state = true;
switch (card.sdprinting_done_state) {
#if ENABLED(PRINTER_EVENT_LEDS)
case 1:
printerEventLEDs.onPrintCompleted(); // Change LED color for Print Completed
break;
#endif
#if HAS_RESUME_CONTINUE // Display "Click to Continue..."
case 2:
did_state = queue.enqueue_P(PSTR("M0 S"
#if HAS_LCD_MENU
"1800" // ...for 30 minutes with LCD
#else
"60" // ...for 1 minute with no LCD
#endif
));
break;
#endif
case 3: print_job_timer.stop(); break;
case 4:
did_state = print_job_timer.duration() < 60 || queue.enqueue_P(PSTR("M31"));
break;
case 5:
#if ENABLED(POWER_LOSS_RECOVERY)
recovery.purge();
#endif
#if ENABLED(SD_FINISHED_STEPPERRELEASE) && defined(SD_FINISHED_RELEASECOMMAND)
planner.finish_and_disable();
#endif
#if ENABLED(LCD_SET_PROGRESS_MANUALLY)
ui.set_progress_done();
#endif
#if ENABLED(SD_REPRINT_LAST_SELECTED_FILE)
ui.reselect_last_file();
#endif
SERIAL_ECHOLNPGM(MSG_FILE_PRINTED);
default:
did_state = false;
card.sdprinting_done_state = 0;
}
if (did_state) ++card.sdprinting_done_state;
}
#endif // SDSUPPORT
/**
* Manage several activities:
* Minimal management of Marlin's core activities:
* - Check for Filament Runout
* - Keep the command buffer full
* - Check for maximum inactive time between commands
@ -1122,10 +1180,15 @@ void setup() {
/**
* The main Marlin program loop
*
* - Save or log commands to SD
* - Process available commands (if not saving)
* - Call endstop manager
* - Call inactivity manager
* - Call idle() to handle all tasks between G-code commands
* Note that no G-codes from the queue can be executed during idle()
* but many G-codes can be called directly anytime like macros.
* - Check whether SD card auto-start is needed now.
* - Check whether SD print finishing is needed now.
* - Run one G-code command from the immediate or main command queue
* and open up one space. Commands in the main queue may come from sd
* card, host, or by direct injection. The queue will continue to fill
* as long as idle() or manage_inactivity() are being called.
*/
void loop() {
do {
@ -1135,6 +1198,7 @@ void loop() {
#if ENABLED(SDSUPPORT)
card.checkautostart();
if (card.flag.abort_sd_printing) abortSDPrinting();
if (card.sdprinting_done_state) finishSDPrinting();
#endif
queue.advance();

View file

@ -512,9 +512,10 @@ void GCodeQueue::get_serial_commands() {
#if ENABLED(SDSUPPORT)
/**
* Get commands from the SD Card until the command buffer is full
* or until the end of the file is reached. The special character '#'
* can also interrupt buffering.
* Get lines from the SD Card until the command buffer is full
* or until the end of the file is reached. Because this method
* always receives complete command-lines, they can go directly
* into the main command queue.
*/
inline void GCodeQueue::get_sdcard_commands() {
static uint8_t sd_input_state = PS_NORMAL;
@ -527,37 +528,21 @@ void GCodeQueue::get_serial_commands() {
const int16_t n = card.get();
card_eof = card.eof();
if (n < 0 && !card_eof) { SERIAL_ERROR_MSG(MSG_SD_ERR_READ); continue; }
const char sd_char = (char)n;
if (sd_char == '\n' || sd_char == '\r' || card_eof) {
const bool is_eol = sd_char == '\n' || sd_char == '\r';
if (is_eol || card_eof) {
// Reset stream state, terminate the buffer, and commit a non-empty command
if (!is_eol && sd_count) ++sd_count; // End of file with no newline
if (!process_line_done(sd_input_state, command_buffer[index_w], sd_count)) {
_commit_command(false); // Can handle last line missing a newline terminator
_commit_command(false);
#if ENABLED(POWER_LOSS_RECOVERY)
recovery.cmd_sdpos = card.getIndex(); // Prime for the next _commit_command
recovery.cmd_sdpos = card.getIndex(); // Prime for the NEXT _commit_command
#endif
}
if (card_eof) {
card.fileHasFinished(); // Handle end of file reached
if (!IS_SD_PRINTING()) { // Was it the main job file?
SERIAL_ECHOLNPGM(MSG_FILE_PRINTED); // Tell the host the file is printed.
#if ENABLED(PRINTER_EVENT_LEDS)
printerEventLEDs.onPrintCompleted(); // Change LED color for Print Completed
#if HAS_RESUME_CONTINUE
enqueue_now_P(PSTR("M0 S" // Display "Click to Continue..."
#if HAS_LCD_MENU
"1800" // ...for 30 minutes with LCD
#else
"60" // ...for 1 minute with no LCD
#endif
));
#endif
#endif
}
}
if (card_eof) card.fileHasFinished(); // Handle end of file reached
}
else
process_stream_char(sd_char, sd_input_state, command_buffer[index_w], sd_count);
@ -633,9 +618,7 @@ void GCodeQueue::advance() {
#endif // SDSUPPORT
// The queue may be reset by a command handler or by code invoked by idle() within a handler
if (length) {
--length;
if (++index_r >= BUFSIZE) index_r = 0;
}
--length;
if (++index_r >= BUFSIZE) index_r = 0;
}

View file

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

View file

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

View file

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

View file

@ -28,7 +28,7 @@
#include "../MarlinCore.h"
#include "../lcd/ultralcd.h"
#include "../module/planner.h"
#include "../module/planner.h" // for synchronize
#include "../module/printcounter.h"
#include "../core/language.h"
#include "../gcode/queue.h"
@ -49,6 +49,7 @@
// public:
card_flags_t CardReader::flag;
uint8_t CardReader::sdprinting_done_state;
char CardReader::filename[FILENAME_LENGTH], CardReader::longFilename[LONG_FILENAME_LENGTH];
int8_t CardReader::autostart_index;
@ -379,7 +380,7 @@ void CardReader::mount() {
}
void CardReader::release() {
stopSDPrint();
endFilePrint();
flag.mounted = false;
}
@ -401,7 +402,7 @@ void CardReader::startFileprint() {
}
}
void CardReader::stopSDPrint(
void CardReader::endFilePrint(
#if SD_RESORT
const bool re_sort/*=false*/
#endif
@ -501,7 +502,7 @@ void CardReader::openFileRead(char * const path, const uint8_t subcall_type/*=0*
break;
}
stopSDPrint();
endFilePrint();
SdFile *curDir;
const char * const fname = diveToFile(true, curDir, path);
@ -529,7 +530,7 @@ void CardReader::openFileWrite(char * const path) {
announceOpen(2, path);
file_subcall_ctr = 0;
stopSDPrint();
endFilePrint();
SdFile *curDir;
const char * const fname = diveToFile(false, curDir, path);
@ -554,7 +555,7 @@ void CardReader::openFileWrite(char * const path) {
void CardReader::removeFile(const char * const name) {
if (!isMounted()) return;
//stopSDPrint();
//endFilePrint();
SdFile *curDir;
const char * const fname = diveToFile(false, curDir, name);
@ -937,7 +938,7 @@ void CardReader::cdroot() {
bool didSwap = false;
uint8_t o1 = sort_order[0];
#if DISABLED(SDSORT_USES_RAM)
selectFileByIndex(o1); // Pre-fetch the first entry and save it
selectFileByIndex(o1); // Pre-fetch the first entry and save it
strcpy(name1, longest_filename()); // so the loop only needs one fetch
#if HAS_FOLDER_SORTING
bool dir1 = flag.filenameIsDir;
@ -1073,30 +1074,13 @@ void CardReader::fileHasFinished() {
startFileprint();
}
else {
stopSDPrint();
#if ENABLED(POWER_LOSS_RECOVERY)
recovery.purge();
#endif
#if ENABLED(SD_FINISHED_STEPPERRELEASE) && defined(SD_FINISHED_RELEASECOMMAND)
planner.finish_and_disable();
#endif
print_job_timer.stop();
queue.enqueue_now_P(print_job_timer.duration() > 60 ? PSTR("M31") : PSTR("M117"));
endFilePrint();
#if ENABLED(SDCARD_SORT_ALPHA)
presort();
#endif
#if ENABLED(LCD_SET_PROGRESS_MANUALLY)
ui.set_progress_done();
#endif
#if ENABLED(SD_REPRINT_LAST_SELECTED_FILE)
ui.reselect_last_file();
#endif
sdprinting_done_state = 1;
}
}

View file

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