Skip to content
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
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ script:
- opt_enable REPRAP_DISCOUNT_SMART_CONTROLLER SDSUPPORT EEPROM_SETTINGS
- opt_enable BLINKM PCA9632 RGB_LED NEOPIXEL_LED AUTO_POWER_CONTROL NOZZLE_PARK_FEATURE FILAMENT_RUNOUT_SENSOR
- opt_enable AUTO_BED_LEVELING_LINEAR Z_MIN_PROBE_REPEATABILITY_TEST DEBUG_LEVELING_FEATURE SKEW_CORRECTION SKEW_CORRECTION_FOR_Z SKEW_CORRECTION_GCODE
- opt_enable_adv ARC_P_CIRCLES ADVANCED_PAUSE_FEATURE CNC_WORKSPACE_PLANES CNC_COORDINATE_SYSTEMS
- opt_enable_adv ARC_P_CIRCLES ADVANCED_PAUSE_FEATURE CNC_WORKSPACE_PLANES CNC_COORDINATE_SYSTEMS POWER_LOSS_RECOVERY
- opt_enable_adv FWRETRACT MAX7219_DEBUG LED_CONTROL_MENU CASE_LIGHT_ENABLE CASE_LIGHT_USE_NEOPIXEL CODEPENDENT_XY_HOMING
- opt_set GRID_MAX_POINTS_X 16
- opt_set_adv FANMUX0_PIN 53
Expand Down
2 changes: 1 addition & 1 deletion Marlin/Conditionals_post.h
Original file line number Diff line number Diff line change
Expand Up @@ -1225,7 +1225,7 @@
#define GRID_MAX_POINTS ((GRID_MAX_POINTS_X) * (GRID_MAX_POINTS_Y))

// Add commands that need sub-codes to this list
#define USE_GCODE_SUBCODES ENABLED(G38_PROBE_TARGET) || ENABLED(CNC_COORDINATE_SYSTEMS)
#define USE_GCODE_SUBCODES ENABLED(G38_PROBE_TARGET) || ENABLED(CNC_COORDINATE_SYSTEMS) || ENABLED(POWER_LOSS_RECOVERY)

// Parking Extruder
#if ENABLED(PARKING_EXTRUDER)
Expand Down
10 changes: 10 additions & 0 deletions Marlin/Configuration_adv.h
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,16 @@
// Add an option in the menu to run all auto#.g files
//#define MENU_ADDAUTOSTART

/**
* Continue after Power-Loss (Creality3D)
*
* Store the current state to the SD Card at the start of each layer
* during SD printing. If the recovery file is found at boot time, present
* an option on the LCD screen to continue the print from the last-known
* point in the file.
*/
//#define POWER_LOSS_RECOVERY

/**
* Sort SD file listings in alphabetical order.
*
Expand Down
2 changes: 0 additions & 2 deletions Marlin/M100_Free_Mem_Chk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,6 @@

#define TEST_BYTE ((char) 0xE5)

extern char command_queue[BUFSIZE][MAX_CMD_SIZE];

extern char* __brkval;
extern size_t __heap_start, __heap_end, __flp;
extern char __bss_end;
Expand Down
4 changes: 4 additions & 0 deletions Marlin/Marlin.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,10 @@ bool enqueue_and_echo_command(const char* cmd, bool say_ok=false); // Add a sing
void enqueue_and_echo_commands_P(const char * const cmd); // Set one or more commands to be prioritized over the next Serial/SD command.
void clear_command_queue();

#if ENABLED(M100_FREE_MEMORY_WATCHER) || ENABLED(POWER_LOSS_RECOVERY)
extern char command_queue[BUFSIZE][MAX_CMD_SIZE];
#endif

#define HAS_LCD_QUEUE_NOW (ENABLED(MALYAN_LCD) || (ENABLED(ULTIPANEL) && (ENABLED(AUTO_BED_LEVELING_UBL) || ENABLED(PID_AUTOTUNE_MENU) || ENABLED(ADVANCED_PAUSE_FEATURE))))
#define HAS_QUEUE_NOW (ENABLED(SDSUPPORT) || HAS_LCD_QUEUE_NOW)
#if HAS_QUEUE_NOW
Expand Down
68 changes: 53 additions & 15 deletions Marlin/Marlin_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,10 @@
#include "fwretract.h"
#endif

#if ENABLED(POWER_LOSS_RECOVERY)
#include "power_loss_recovery.h"
#endif

#if ENABLED(FILAMENT_RUNOUT_SENSOR)
#include "runout.h"
#endif
Expand Down Expand Up @@ -415,14 +419,11 @@ static long gcode_N, gcode_LastN, Stopped_gcode_LastN = 0;
* the main loop. The process_next_command function parses the next
* command and hands off execution to individual handler functions.
*/
uint8_t commands_in_queue = 0; // Count of commands in the queue
static uint8_t cmd_queue_index_r = 0, // Ring buffer read position
cmd_queue_index_w = 0; // Ring buffer write position
#if ENABLED(M100_FREE_MEMORY_WATCHER)
char command_queue[BUFSIZE][MAX_CMD_SIZE]; // Necessary so M100 Free Memory Dumper can show us the commands and any corruption
#else // This can be collapsed back to the way it was soon.
static char command_queue[BUFSIZE][MAX_CMD_SIZE];
#endif
uint8_t commands_in_queue = 0, // Count of commands in the queue
cmd_queue_index_r = 0, // Ring buffer read (out) position
cmd_queue_index_w = 0; // Ring buffer write (in) position

char command_queue[BUFSIZE][MAX_CMD_SIZE];

/**
* Next Injected Command pointer. NULL if no commands are being injected.
Expand Down Expand Up @@ -1231,21 +1232,43 @@ inline void get_serial_commands() {
}
}

#if ENABLED(POWER_LOSS_RECOVERY)

inline bool drain_job_recovery_commands() {
static uint8_t job_recovery_commands_index = 0; // Resets on reboot
if (job_recovery_commands_count) {
if (_enqueuecommand(job_recovery_commands[job_recovery_commands_index])) {
++job_recovery_commands_index;
if (!--job_recovery_commands_count) job_recovery_phase = JOB_RECOVERY_IDLE;
}
return true;
}
return false;
}

#endif

#endif // SDSUPPORT

/**
* Add to the circular command queue the next command from:
* - The command-injection queue (injected_commands_P)
* - The active serial input (usually USB)
* - Commands left in the queue after power-loss
* - The SD card file being actively printed
*/
void get_available_commands() {

// if any immediate commands remain, don't get other commands yet
// Immediate commands block the other queues
if (drain_injected_commands_P()) return;

get_serial_commands();

#if ENABLED(POWER_LOSS_RECOVERY)
// Commands for power-loss recovery take precedence
if (job_recovery_phase == JOB_RECOVERY_YES && drain_job_recovery_commands()) return;
#endif

#if ENABLED(SDSUPPORT)
get_sdcard_commands();
#endif
Expand Down Expand Up @@ -3994,6 +4017,8 @@ inline void gcode_G4() {
* None Home to all axes with no parameters.
* With QUICK_HOME enabled XY will home together, then Z.
*
* Rn Raise by n mm/inches before homing
*
* Cartesian parameters
*
* X Home to the X endstop
Expand Down Expand Up @@ -4068,11 +4093,12 @@ inline void gcode_G28(const bool always_home_all) {

#endif

#if ENABLED(UNKNOWN_Z_NO_RAISE)
const float z_homing_height = axis_known_position[Z_AXIS] ? Z_HOMING_HEIGHT : 0;
#else
constexpr float z_homing_height = Z_HOMING_HEIGHT;
#endif
const float z_homing_height = (
#if ENABLED(UNKNOWN_Z_NO_RAISE)
!axis_known_position[Z_AXIS] ? 0 :
#endif
(parser.seenval('R') ? parser.value_linear_units() : Z_HOMING_HEIGHT)
);

if (z_homing_height && (home_all || homeX || homeY)) {
// Raise Z before homing any other axes and z is not already high enough (never lower z)
Expand Down Expand Up @@ -7014,6 +7040,10 @@ inline void gcode_M17() {
* M24: Start or Resume SD Print
*/
inline void gcode_M24() {
#if ENABLED(POWER_LOSS_RECOVERY)
card.removeJobRecoveryFile();
#endif

#if ENABLED(PARK_HEAD_ON_PAUSE)
resume_print();
#endif
Expand Down Expand Up @@ -14271,6 +14301,10 @@ void setup() {
#endif
#endif

#if ENABLED(POWER_LOSS_RECOVERY)
do_print_job_recovery();
#endif

#if ENABLED(USE_WATCHDOG)
watchdog_init();
#endif
Expand Down Expand Up @@ -14348,8 +14382,12 @@ void loop() {
ok_to_send();
}
}
else
else {
process_next_command();
#if ENABLED(POWER_LOSS_RECOVERY)
if (card.cardOK && card.sdprinting) save_job_recovery_info();
#endif
}

#else

Expand Down
6 changes: 5 additions & 1 deletion Marlin/SanityCheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -435,7 +435,7 @@ static_assert(X_MAX_LENGTH >= X_BED_SIZE && Y_MAX_LENGTH >= Y_BED_SIZE,
#elif ENABLED(BABYSTEP_ZPROBE_OFFSET) && !HAS_BED_PROBE
#error "BABYSTEP_ZPROBE_OFFSET requires a probe."
#elif ENABLED(BABYSTEP_ZPROBE_GFX_OVERLAY) && !ENABLED(DOGLCD)
#error "BABYSTEP_ZPROBE_GFX_OVERLAY requires a DOGLCD."
#error "BABYSTEP_ZPROBE_GFX_OVERLAY requires a Graphical LCD."
#elif ENABLED(BABYSTEP_ZPROBE_GFX_OVERLAY) && !ENABLED(BABYSTEP_ZPROBE_OFFSET)
#error "BABYSTEP_ZPROBE_GFX_OVERLAY requires a BABYSTEP_ZPROBE_OFFSET."
#endif
Expand Down Expand Up @@ -1743,4 +1743,8 @@ static_assert(COUNT(sanity_arr_3) <= XYZE_N, "DEFAULT_MAX_ACCELERATION has too m
#endif
#endif

#if ENABLED(POWER_LOSS_RECOVERY) && !ENABLED(ULTIPANEL)
#error "POWER_LOSS_RECOVERY currently requires an LCD Controller."
#endif

#endif // _SANITYCHECK_H_
58 changes: 56 additions & 2 deletions Marlin/cardreader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@
#include "language.h"
#include "printcounter.h"

#if ENABLED(POWER_LOSS_RECOVERY)
#include "power_loss_recovery.h"
#endif

#define LONGEST_FILENAME (longFilename[0] ? longFilename : filename)

CardReader::CardReader() {
Expand Down Expand Up @@ -420,8 +424,7 @@ void CardReader::openFile(char* name, const bool read, const bool subcall/*=fals
strncpy(subdirname, dirname_start, dirname_end - dirname_start);
subdirname[dirname_end - dirname_start] = '\0';
if (!myDir.open(curDir, subdirname, O_READ)) {
SERIAL_PROTOCOLPGM(MSG_SD_OPEN_FILE_FAIL);
SERIAL_PROTOCOL(subdirname);
SERIAL_PROTOCOLPAIR(MSG_SD_OPEN_FILE_FAIL, subdirname);
SERIAL_PROTOCOLCHAR('.');
return;
}
Expand Down Expand Up @@ -928,6 +931,15 @@ void CardReader::printingHasFinished() {
}
else {
sdprinting = false;

#if ENABLED(POWER_LOSS_RECOVERY)
openJobRecoveryFile(false);
job_recovery_info.valid_head = job_recovery_info.valid_foot = 0;
(void)saveJobRecoveryInfo();
closeJobRecoveryFile();
job_recovery_commands_count = 0;
#endif

#if ENABLED(SD_FINISHED_STEPPERRELEASE) && defined(SD_FINISHED_RELEASECOMMAND)
stepper.cleaning_buffer_counter = 1; // The command will fire from the Stepper ISR
#endif
Expand Down Expand Up @@ -959,4 +971,46 @@ void CardReader::printingHasFinished() {
}
#endif // AUTO_REPORT_SD_STATUS

#if ENABLED(POWER_LOSS_RECOVERY)

char job_recovery_file_name[4] = "bin";

void CardReader::openJobRecoveryFile(const bool read) {
if (!cardOK) return;
if (jobRecoveryFile.isOpen()) return;
if (!jobRecoveryFile.open(&root, job_recovery_file_name, read ? O_READ : O_CREAT | O_WRITE | O_TRUNC | O_SYNC)) {
SERIAL_PROTOCOLPAIR(MSG_SD_OPEN_FILE_FAIL, job_recovery_file_name);
SERIAL_PROTOCOLCHAR('.');
SERIAL_EOL();
}
else
SERIAL_PROTOCOLLNPAIR(MSG_SD_WRITE_TO_FILE, job_recovery_file_name);
}

void CardReader::closeJobRecoveryFile() { jobRecoveryFile.close(); }

bool CardReader::jobRecoverFileExists() {
return jobRecoveryFile.open(&root, job_recovery_file_name, O_READ);
}

int16_t CardReader::saveJobRecoveryInfo() {
jobRecoveryFile.seekSet(0);
const int16_t ret = jobRecoveryFile.write(&job_recovery_info, sizeof(job_recovery_info));
if (ret == -1) SERIAL_PROTOCOLLNPGM("Power-loss file write failed.");
return ret;
}

int16_t CardReader::loadJobRecoveryInfo() {
return jobRecoveryFile.read(&job_recovery_info, sizeof(job_recovery_info));
}

void CardReader::removeJobRecoveryFile() {
if (jobRecoveryFile.remove(&root, job_recovery_file_name))
SERIAL_PROTOCOLLNPGM("Power-loss file deleted.");
else
SERIAL_PROTOCOLLNPGM("Power-loss file delete failed.");
}

#endif // POWER_LOSS_RECOVERY

#endif // SDSUPPORT
16 changes: 15 additions & 1 deletion Marlin/cardreader.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,21 @@ class CardReader {
#endif
#endif

#if ENABLED(POWER_LOSS_RECOVERY)
void openJobRecoveryFile(const bool read);
void closeJobRecoveryFile();
bool jobRecoverFileExists();
int16_t saveJobRecoveryInfo();
int16_t loadJobRecoveryInfo();
void removeJobRecoveryFile();
#endif

FORCE_INLINE void pauseSDPrint() { sdprinting = false; }
FORCE_INLINE bool isFileOpen() { return file.isOpen(); }
FORCE_INLINE bool eof() { return sdpos >= filesize; }
FORCE_INLINE int16_t get() { sdpos = file.curPosition(); return (int16_t)file.read(); }
FORCE_INLINE void setIndex(long index) { sdpos = index; file.seekSet(index); }
FORCE_INLINE void setIndex(const uint32_t index) { sdpos = index; file.seekSet(index); }
FORCE_INLINE uint32_t getIndex() { return sdpos; }
FORCE_INLINE uint8_t percentDone() { return (isFileOpen() && filesize) ? sdpos / ((filesize + 99) / 100) : 0; }
FORCE_INLINE char* getWorkDirName() { workDir.getFilename(filename); return filename; }

Expand Down Expand Up @@ -168,6 +178,10 @@ class CardReader {
SdVolume volume;
SdFile file;

#if ENABLED(POWER_LOSS_RECOVERY)
SdFile jobRecoveryFile;
#endif

#define SD_PROCEDURE_DEPTH 1
#define MAXPATHNAMELENGTH (FILENAME_LENGTH*MAX_DIR_DEPTH + MAX_DIR_DEPTH + 1)
uint8_t file_subcall_ctr;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,16 @@
// Add an option in the menu to run all auto#.g files
//#define MENU_ADDAUTOSTART

/**
* Continue after Power-Loss (Creality3D)
*
* Store the current state to the SD Card at the start of each layer
* during SD printing. If the recovery file is found at boot time, present
* an option on the LCD screen to continue the print from the last-known
* point in the file.
*/
//#define POWER_LOSS_RECOVERY

/**
* Sort SD file listings in alphabetical order.
*
Expand Down
10 changes: 10 additions & 0 deletions Marlin/example_configurations/Anet/A6/Configuration_adv.h
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,16 @@
// Add an option in the menu to run all auto#.g files
//#define MENU_ADDAUTOSTART

/**
* Continue after Power-Loss (Creality3D)
*
* Store the current state to the SD Card at the start of each layer
* during SD printing. If the recovery file is found at boot time, present
* an option on the LCD screen to continue the print from the last-known
* point in the file.
*/
//#define POWER_LOSS_RECOVERY

/**
* Sort SD file listings in alphabetical order.
*
Expand Down
10 changes: 10 additions & 0 deletions Marlin/example_configurations/Anet/A8/Configuration_adv.h
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,16 @@
// Add an option in the menu to run all auto#.g files
//#define MENU_ADDAUTOSTART

/**
* Continue after Power-Loss (Creality3D)
*
* Store the current state to the SD Card at the start of each layer
* during SD printing. If the recovery file is found at boot time, present
* an option on the LCD screen to continue the print from the last-known
* point in the file.
*/
//#define POWER_LOSS_RECOVERY

/**
* Sort SD file listings in alphabetical order.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,16 @@
// Add an option in the menu to run all auto#.g files
//#define MENU_ADDAUTOSTART

/**
* Continue after Power-Loss (Creality3D)
*
* Store the current state to the SD Card at the start of each layer
* during SD printing. If the recovery file is found at boot time, present
* an option on the LCD screen to continue the print from the last-known
* point in the file.
*/
//#define POWER_LOSS_RECOVERY

/**
* Sort SD file listings in alphabetical order.
*
Expand Down
Loading