Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure proper SD print completion #16967

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 72 additions & 8 deletions Marlin/src/MarlinCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -390,8 +390,8 @@ void startOrResumeJob() {

#if ENABLED(SDSUPPORT)

void abortSDPrinting() {
card.stopSDPrint(
inline void abortSDPrinting() {
card.endFilePrint(
#if SD_RESORT
true
#endif
Expand All @@ -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
Expand Down Expand Up @@ -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 {
Expand All @@ -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();
Expand Down
43 changes: 13 additions & 30 deletions Marlin/src/gcode/queue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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;

}
6 changes: 6 additions & 0 deletions Marlin/src/gcode/queue.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,12 @@ class GCodeQueue {
*/
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
Expand Down
2 changes: 1 addition & 1 deletion Marlin/src/lcd/menu/menu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion Marlin/src/module/endstops.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
36 changes: 10 additions & 26 deletions Marlin/src/sd/cardreader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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;

Expand Down Expand Up @@ -379,7 +380,7 @@ void CardReader::mount() {
}

void CardReader::release() {
stopSDPrint();
endFilePrint();
flag.mounted = false;
}

Expand All @@ -401,7 +402,7 @@ void CardReader::startFileprint() {
}
}

void CardReader::stopSDPrint(
void CardReader::endFilePrint(
#if SD_RESORT
const bool re_sort/*=false*/
#endif
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
}

Expand Down
5 changes: 3 additions & 2 deletions Marlin/src/sd/cardreader.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -108,9 +109,9 @@ class CardReader {
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
Expand Down