Ensure proper SD print completion (#16967)
This commit is contained in:
parent
91cff02596
commit
5071fe82ab
7 changed files with 106 additions and 68 deletions
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Reference in a new issue