Commit 9c6f57b2 authored by MagoKimbra's avatar MagoKimbra

Merge remote-tracking branch 'refs/remotes/origin/master' into dev

parents 1e3fc326 744b1137
...@@ -52,9 +52,14 @@ ...@@ -52,9 +52,14 @@
//#define FIRMWARE_TEST //#define FIRMWARE_TEST
// Some particular clients re-start sending commands only after receiving a 'wait' when there is a bad serial-connection. // Some particular clients re-start sending commands only after receiving a 'wait' when there is a bad serial-connection.
//#define NO_TIMEOUTS //#define NO_TIMEOUTS 1000 // Milliseconds
// Uncomment to include more info in ok command // Uncomment to include more info in ok command
//#define ADVANCED_OK //#define ADVANCED_OK
// By default MarlinKimbra will send a busy status message to the host
// every couple of seconds when it can't accept commands.
// Enable this option if your host doesn't like keepalive messages.
//#define DISABLE_HOST_KEEPALIVE
/***********************************************************************/ /***********************************************************************/
...@@ -192,11 +197,16 @@ ...@@ -192,11 +197,16 @@
/*********************************************************************** /***********************************************************************
************************* Temperature limits *************************** ************************* Temperature limits ***************************
***********************************************************************/ ***********************************************************************/
// Actual temperature must be close to target for this long before M109 returns success // Hotend temperature must be close to target for this long before M109 returns success
#define TEMP_RESIDENCY_TIME 10 // (seconds) #define TEMP_RESIDENCY_TIME 10 // (seconds)
#define TEMP_HYSTERESIS 3 // (degC) range of +/- temperatures considered "close" to the target one #define TEMP_HYSTERESIS 3 // (degC) range of +/- temperatures considered "close" to the target one
#define TEMP_WINDOW 1 // (degC) Window around target to start the residency timer x degC early. #define TEMP_WINDOW 1 // (degC) Window around target to start the residency timer x degC early.
// Bed temperature must be close to target for this long before M190 returns success
#define TEMP_BED_RESIDENCY_TIME 0 // (seconds)
#define TEMP_BED_HYSTERESIS 3 // (degC) range of +/- temperatures considered "close" to the target one
#define TEMP_BED_WINDOW 1 // (degC) Window around target to start the residency timer x degC early.
// When temperature exceeds max temp, your heater will be switched off. // When temperature exceeds max temp, your heater will be switched off.
// This feature exists to protect your hotend from overheating accidentally, but *NOT* from thermistor short/failure! // This feature exists to protect your hotend from overheating accidentally, but *NOT* from thermistor short/failure!
// You should use MINTEMP for thermistor short/failure protection. // You should use MINTEMP for thermistor short/failure protection.
......
...@@ -57,7 +57,7 @@ ...@@ -57,7 +57,7 @@
// //
// C, Y-axis // C, Y-axis
// | // |
// DELTA_ALPHA_CA=120° | DELTA_ALPHA_CB=120° // DELTA_ALPHA_CA=120° | DELTA_ALPHA_CB=120°
// | // |
// |______ X-axis // |______ X-axis
// / \ // / \
......
/** /**
* MK Firmware * MK 3D Printer Firmware
* *
* Based on Marlin, Sprinter and grbl * Based on Marlin, Sprinter and grbl
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
......
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
#include "Configuration_Store.h" #include "Configuration_Store.h"
#include "module/language/language.h" #include "module/language/language.h"
#include "module/stopwatch/stopwatch.h"
#include "module/MK_Main.h" #include "module/MK_Main.h"
#include "module/motion/planner.h" #include "module/motion/planner.h"
#include "module/motion/stepper_indirection.h" #include "module/motion/stepper_indirection.h"
......
/** /**
* MK Firmware * MK 3D Printer Firmware
* *
* Based on Marlin, Sprinter and grbl * Based on Marlin, Sprinter and grbl
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm * Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
bool Running = true; bool Running = true;
bool Printing = false; bool Printing = false;
uint8_t debugLevel = DEBUG_ERRORS; uint8_t mk_debug_flags = DEBUG_NONE;
static float feedrate = 1500.0, saved_feedrate; static float feedrate = 1500.0, saved_feedrate;
float current_position[NUM_AXIS] = { 0.0 }; float current_position[NUM_AXIS] = { 0.0 };
...@@ -83,24 +83,34 @@ uint8_t previous_extruder = 0; ...@@ -83,24 +83,34 @@ uint8_t previous_extruder = 0;
uint8_t active_driver = 0; uint8_t active_driver = 0;
int fanSpeed = 0; int fanSpeed = 0;
bool cancel_heatup = false;
const char axis_codes[NUM_AXIS] = {'X', 'Y', 'Z', 'E'}; const char axis_codes[NUM_AXIS] = {'X', 'Y', 'Z', 'E'};
static bool relative_mode = false; //Determines Absolute or Relative Coordinates // Relative Mode. Enable with G91, disable with G90.
static char serial_char; static bool relative_mode = false;
bool cancel_heatup = false;
static int serial_count = 0; static int serial_count = 0;
static boolean comment_mode = false;
static char* seen_pointer; // < A pointer to find chars in the command string (X, Y, Z, E, etc.) // GCode parameter pointer used by code_seen(), code_value(), etc.
const char* queued_commands_P = NULL; /* pointer to the current line in the active sequence of commands, or NULL when none */ static char* seen_pointer;
// Next Immediate GCode Command pointer. NULL if none.
const char* queued_commands_P = NULL;
const int sensitive_pins[] = SENSITIVE_PINS; ///< Sensitive pin list for M42 const int sensitive_pins[] = SENSITIVE_PINS; ///< Sensitive pin list for M42
// Inactivity shutdown // Inactivity shutdown
millis_t previous_cmd_ms = 0; millis_t previous_cmd_ms = 0;
static millis_t max_inactive_time = 0; static millis_t max_inactive_time = 0;
static millis_t stepper_inactive_time = (DEFAULT_STEPPER_DEACTIVE_TIME) * 1000UL; static millis_t stepper_inactive_time = (DEFAULT_STEPPER_DEACTIVE_TIME) * 1000UL;
millis_t print_job_start_ms = 0; ///< Print job start time
millis_t print_job_stop_ms = 0; ///< Print job stop time // Print Job Timer
Stopwatch print_job_timer = Stopwatch();
static uint8_t target_extruder; static uint8_t target_extruder;
bool no_wait_for_cooling = true; bool no_wait_for_cooling = true;
bool software_endstops = true; bool software_endstops = true;
...@@ -142,8 +152,8 @@ double printer_usage_filament; ...@@ -142,8 +152,8 @@ double printer_usage_filament;
#endif #endif
#if ENABLED(BARICUDA) #if ENABLED(BARICUDA)
int ValvePressure = 0; int baricuda_valve_pressure = 0;
int EtoPPressure = 0; int baricuda_e_to_p_pressure = 0;
#endif #endif
#if ENABLED(FWRETRACT) #if ENABLED(FWRETRACT)
...@@ -298,6 +308,8 @@ double printer_usage_filament; ...@@ -298,6 +308,8 @@ double printer_usage_filament;
bool allow_lengthy_extrude_once; // for load/unload bool allow_lengthy_extrude_once; // for load/unload
#endif #endif
static bool send_ok[BUFSIZE];
#if HAS(CHDK) #if HAS(CHDK)
unsigned long chdkHigh = 0; unsigned long chdkHigh = 0;
boolean chdkActive = false; boolean chdkActive = false;
...@@ -307,9 +319,37 @@ double printer_usage_filament; ...@@ -307,9 +319,37 @@ double printer_usage_filament;
int lpq_len = 20; int lpq_len = 20;
#endif #endif
//=========================================================================== #if ENABLED(HOST_KEEPALIVE_FEATURE)
//================================ Functions ================================ // States for managing MK and host communication
//=========================================================================== // MK sends messages if blocked or busy
enum MKBusyState {
NOT_BUSY, // Not in a handler
IN_HANDLER, // Processing a GCode
IN_PROCESS, // Known to be blocking command input (as in G29)
PAUSED_FOR_USER, // Blocking pending any input
PAUSED_FOR_INPUT // Blocking pending text input (concept)
};
static MKBusyState busy_state = NOT_BUSY;
static millis_t next_busy_signal_ms = 0;
uint8_t host_keepalive_interval = DEFAULT_KEEPALIVE_INTERVAL;
#define KEEPALIVE_STATE(n) do{ busy_state = n; }while(0)
#else
#define host_keepalive() ;
#define KEEPALIVE_STATE(n) ;
#endif // HOST_KEEPALIVE_FEATURE
/**
* ***************************************************************************
* ******************************** FUNCTIONS ********************************
* ***************************************************************************
*/
void stop();
void get_available_commands();
void process_next_command();
inline void refresh_cmd_timeout() { previous_cmd_ms = millis(); } inline void refresh_cmd_timeout() { previous_cmd_ms = millis(); }
void delay_ms(millis_t ms) { void delay_ms(millis_t ms) {
...@@ -317,8 +357,6 @@ void delay_ms(millis_t ms) { ...@@ -317,8 +357,6 @@ void delay_ms(millis_t ms) {
while (millis() < ms) idle(); while (millis() < ms) idle();
} }
void process_next_command();
void plan_arc(float target[NUM_AXIS], float* offset, uint8_t clockwise); void plan_arc(float target[NUM_AXIS], float* offset, uint8_t clockwise);
#if ENABLED(PREVENT_DANGEROUS_EXTRUDE) #if ENABLED(PREVENT_DANGEROUS_EXTRUDE)
...@@ -375,25 +413,21 @@ void plan_arc(float target[NUM_AXIS], float* offset, uint8_t clockwise); ...@@ -375,25 +413,21 @@ void plan_arc(float target[NUM_AXIS], float* offset, uint8_t clockwise);
* Return false only if no command was pending * Return false only if no command was pending
*/ */
static bool drain_queued_commands_P() { static bool drain_queued_commands_P() {
if (!queued_commands_P) return false; if (queued_commands_P != NULL) {
size_t i = 0;
// Get the next 30 chars from the sequence of gcodes to run char c, cmd[30];
char cmd[30];
strncpy_P(cmd, queued_commands_P, sizeof(cmd) - 1); strncpy_P(cmd, queued_commands_P, sizeof(cmd) - 1);
cmd[sizeof(cmd) - 1] = '\0'; cmd[sizeof(cmd) - 1] = '\0';
while ((c = cmd[i]) && c != '\n') i++; // find the end of this gcode command
// Look for the end of line, or the end of sequence
size_t i = 0;
char c;
while((c = cmd[i]) && c != '\n') i++; // find the end of this gcode command
cmd[i] = '\0'; cmd[i] = '\0';
if (enqueuecommand(cmd)) { // buffer was not full (else we will retry later) if (enqueue_and_echo_command(cmd)) { // success?
if (c) if (c) // newline char?
queued_commands_P += i + 1; // move to next command queued_commands_P += i + 1; // advance to the next command
else else
queued_commands_P = NULL; // will have no more commands in the sequence queued_commands_P = NULL; // nul char? no more commands
} }
return true; }
return (queued_commands_P != NULL); // return whether any more remain
} }
/** /**
...@@ -401,29 +435,46 @@ static bool drain_queued_commands_P() { ...@@ -401,29 +435,46 @@ static bool drain_queued_commands_P() {
* Aborts the current queue, if any. * Aborts the current queue, if any.
* Note: drain_queued_commands_P() must be called repeatedly to drain the commands afterwards * Note: drain_queued_commands_P() must be called repeatedly to drain the commands afterwards
*/ */
void enqueuecommands_P(const char* pgcode) { void enqueue_and_echo_commands_P(const char* pgcode) {
queued_commands_P = pgcode; queued_commands_P = pgcode;
drain_queued_commands_P(); // first command executed asap (when possible) drain_queued_commands_P(); // first command executed asap (when possible)
} }
/** /**
* Copy a command directly into the main command buffer, from RAM. * Once a new command is in the ring buffer, call this to commit it
*
* This is done in a non-safe way and needs a rework someday.
* Returns false if it doesn't add any command
*/ */
bool enqueuecommand(const char* cmd) { inline void _commit_command(bool say_ok) {
send_ok[cmd_queue_index_w] = say_ok;
cmd_queue_index_w = (cmd_queue_index_w + 1) % BUFSIZE;
commands_in_queue++;
}
/**
* Copy a command directly into the main command buffer, from RAM.
* Returns true if successfully adds the command
*/
inline bool _enqueuecommand(const char* cmd, bool say_ok = false) {
if (*cmd == ';' || commands_in_queue >= BUFSIZE) return false; if (*cmd == ';' || commands_in_queue >= BUFSIZE) return false;
strcpy(command_queue[cmd_queue_index_w], cmd);
_commit_command(say_ok);
return true;
}
// This is dangerous if a mixing of serial and this happens void enqueue_and_echo_command_now(const char* cmd) {
char* command = command_queue[cmd_queue_index_w]; while (!enqueue_and_echo_command(cmd)) idle();
strcpy(command, cmd); }
ECHO_SMT(DB, SERIAL_ENQUEUEING, command);
/**
* Enqueue with Serial Echo
*/
bool enqueue_and_echo_command(const char* cmd, bool say_ok/*=false*/) {
if (_enqueuecommand(cmd, say_ok)) {
ECHO_SM(DB, SERIAL_ENQUEUEING);
ECHO_T(cmd);
ECHO_EM("\""); ECHO_EM("\"");
cmd_queue_index_w = (cmd_queue_index_w + 1) % BUFSIZE;
commands_in_queue++;
return true; return true;
}
return false;
} }
#if MB(ALLIGATOR) #if MB(ALLIGATOR)
...@@ -708,7 +759,7 @@ void setup() { ...@@ -708,7 +759,7 @@ void setup() {
* - Call LCD update * - Call LCD update
*/ */
void loop() { void loop() {
if (commands_in_queue < BUFSIZE - 1) get_command(); if (commands_in_queue < BUFSIZE - 1) get_available_commands();
#if ENABLED(SDSUPPORT) #if ENABLED(SDSUPPORT)
card.checkautostart(false); card.checkautostart(false);
...@@ -754,85 +805,82 @@ void gcode_line_error(const char* err, bool doFlush = true) { ...@@ -754,85 +805,82 @@ void gcode_line_error(const char* err, bool doFlush = true) {
serial_count = 0; serial_count = 0;
} }
/** inline void get_serial_commands() {
* Add to the circular command queue the next command from: static char serial_line_buffer[MAX_CMD_SIZE];
* - The command-injection queue (queued_commands_P) static boolean serial_comment_mode = false;
* - The active serial input (usually USB)
* - The SD card file being actively printed
*/
void get_command() {
if (drain_queued_commands_P()) return; // priority is given to non-serial commands
#if ENABLED(NO_TIMEOUTS) // If the command buffer is empty for too long,
// send "wait" to indicate Marlin is still waiting.
#if defined(NO_TIMEOUTS) && NO_TIMEOUTS > 0
static millis_t last_command_time = 0; static millis_t last_command_time = 0;
millis_t ms = millis(); millis_t ms = millis();
if (!MKSERIAL.available() && commands_in_queue == 0 && ELAPSED(ms, last_command_time + NO_TIMEOUTS)) {
if (!MKSERIAL.available() && commands_in_queue == 0 && ms - last_command_time > 1000UL) {
ECHO_L(WT); ECHO_L(WT);
last_command_time = ms; last_command_time = ms;
} }
#endif #endif
// /**
// Loop while serial characters are incoming and the queue is not full * Loop while serial characters are incoming and the queue is not full
// */
while (MKSERIAL.available() > 0 && commands_in_queue < BUFSIZE) { while (MKSERIAL.available() > 0 && commands_in_queue < BUFSIZE) {
#if ENABLED(NO_TIMEOUTS) char serial_char = MKSERIAL.read();
last_command_time = ms;
#endif
serial_char = MKSERIAL.read();
// /**
// If the character ends the line, or the line is full... * If the character ends the line
// */
if (serial_char == '\n' || serial_char == '\r' || serial_count >= MAX_CMD_SIZE - 1) { if (serial_char == '\n' || serial_char == '\r') {
// end of line == end of comment serial_comment_mode = false; // end of line == end of comment
comment_mode = false;
if (!serial_count) return; // empty lines just exit if (!serial_count) return; // skip empty lines
char* command = command_queue[cmd_queue_index_w]; serial_line_buffer[serial_count] = 0; // terminate string
command[serial_count] = 0; // terminate string serial_count = 0; //reset buffer
// this item in the queue is not from sd char* command = serial_line_buffer;
#if ENABLED(SDSUPPORT)
fromsd[cmd_queue_index_w] = false;
#endif
while (*command == ' ') command++; // skip any leading spaces while (*command == ' ') command++; // skip any leading spaces
char* npos = (*command == 'N') ? command : NULL; // Require the N parameter to start the line char* npos = (*command == 'N') ? command : NULL; // Require the N parameter to start the line
char* apos = strchr(command, '*'); char* apos = strchr(command, '*');
if (npos) { if (npos) {
boolean M110 = strstr_P(command, PSTR("M110")) != NULL; boolean M110 = strstr_P(command, PSTR("M110")) != NULL;
if (M110) { if (M110) {
char* n2pos = strchr(command + 4, 'N'); char* n2pos = strchr(command + 4, 'N');
if (n2pos) npos = n2pos; if (n2pos) npos = n2pos;
} }
gcode_N = strtol(npos + 1, NULL, 10); gcode_N = strtol(npos + 1, NULL, 10);
if (gcode_N != gcode_LastN + 1 && !M110) { if (gcode_N != gcode_LastN + 1 && !M110) {
gcode_line_error(PSTR(SERIAL_ERR_LINE_NO)); gcode_line_error(PSTR(SERIAL_ERR_LINE_NO));
return; return;
} }
if (apos) { if (apos) {
byte checksum = 0, count = 0; byte checksum = 0, count = 0;
while (command[count] != '*') checksum ^= command[count++]; while (command[count] != '*') checksum ^= command[count++];
if (strtol(apos + 1, NULL, 10) != checksum) { if (strtol(apos + 1, NULL, 10) != checksum) {
gcode_line_error(PSTR(SERIAL_ERR_CHECKSUM_MISMATCH)); gcode_line_error(PSTR(SERIAL_ERR_CHECKSUM_MISMATCH));
return; return;
} }
// if no errors, continue parsing // if no errors, continue parsing
} else if (npos == command) { }
else {
gcode_line_error(PSTR(SERIAL_ERR_NO_CHECKSUM)); gcode_line_error(PSTR(SERIAL_ERR_NO_CHECKSUM));
return; return;
} }
gcode_LastN = gcode_N; gcode_LastN = gcode_N;
// if no errors, continue parsing // if no errors, continue parsing
} else if (apos) { // No '*' without 'N'
}
else if (apos) { // No '*' without 'N'
gcode_line_error(PSTR(SERIAL_ERR_NO_LINENUMBER_WITH_CHECKSUM), false); gcode_line_error(PSTR(SERIAL_ERR_NO_LINENUMBER_WITH_CHECKSUM), false);
return; return;
} }
...@@ -857,48 +905,63 @@ void get_command() { ...@@ -857,48 +905,63 @@ void get_command() {
// If command was e-stop process now // If command was e-stop process now
if (strcmp(command, "M112") == 0) kill(PSTR(MSG_KILLED)); if (strcmp(command, "M112") == 0) kill(PSTR(MSG_KILLED));
cmd_queue_index_w = (cmd_queue_index_w + 1) % BUFSIZE; #if defined(NO_TIMEOUTS) && NO_TIMEOUTS > 0
commands_in_queue += 1; last_command_time = ms;
#endif
serial_count = 0; //clear buffer // Add the command to the queue
_enqueuecommand(serial_line_buffer, true);
}
else if (serial_count >= MAX_CMD_SIZE - 1) {
// Keep fetching, but ignore normal characters beyond the max length
// The command will be injected when EOL is reached
} }
else if (serial_char == '\\') { // Handle escapes else if (serial_char == '\\') { // Handle escapes
if (MKSERIAL.available() > 0 && commands_in_queue < BUFSIZE) { if (MKSERIAL.available() > 0) {
// if we have one more character, copy it over // if we have one more character, copy it over
serial_char = MKSERIAL.read(); serial_char = MKSERIAL.read();
command_queue[cmd_queue_index_w][serial_count++] = serial_char; if (!serial_comment_mode) serial_line_buffer[serial_count++] = serial_char;
} }
// otherwise do nothing // otherwise do nothing
} }
else { // its not a newline, carriage return or escape char else { // its not a newline, carriage return or escape char
if (serial_char == ';') comment_mode = true; if (serial_char == ';') serial_comment_mode = true;
if (!comment_mode) command_queue[cmd_queue_index_w][serial_count++] = serial_char; if (!serial_comment_mode) serial_line_buffer[serial_count++] = serial_char;
}
} }
} // queue has space, serial has data
}
#if ENABLED(SDSUPPORT) #if ENABLED(SDSUPPORT)
if (!card.sdprinting || serial_count) return; inline void get_sdcard_commands() {
static bool stop_buffering = false,
sd_comment_mode = false;
if (!card.sdprinting) return;
// '#' stops reading from SD to the buffer prematurely, so procedural macro calls are possible /**
// if it occurs, stop_buffering is triggered and the buffer is ran dry. * '#' stops reading from SD to the buffer prematurely, so procedural
// this character _can_ occur in serial com, due to checksums. however, no checksums are used in SD printing * macro calls are possible. If it occurs, stop_buffering is triggered
* and the buffer is run dry; this character _can_ occur in serial com
* due to checksums, however, no checksums are used in SD printing.
*/
static bool stop_buffering = false;
if (commands_in_queue == 0) stop_buffering = false; if (commands_in_queue == 0) stop_buffering = false;
while (!card.eof() && commands_in_queue < BUFSIZE && !stop_buffering) { uint16_t sd_count = 0;
bool card_eof = card.eof();
while (commands_in_queue < BUFSIZE && !card_eof && !stop_buffering) {
int16_t n = card.get(); int16_t n = card.get();
card.sdpos++; char sd_char = (char)n;
serial_char = (char)n; card_eof = card.eof();
if (serial_char == '\n' || serial_char == '\r' || if (card_eof || n == -1
((serial_char == '#' || serial_char == ':') && !comment_mode) || || sd_char == '\n' || sd_char == '\r'
serial_count >= (MAX_CMD_SIZE - 1) || n == -1 || ((sd_char == '#' || sd_char == ':') && !sd_comment_mode)
) { ) {
if (card.eof()) { if (card_eof) {
ECHO_EM(SERIAL_FILE_PRINTED); ECHO_EM(SERIAL_FILE_PRINTED);
print_job_stop_ms = millis(); print_job_timer.stop();
char time[30]; char time[30];
millis_t t = (print_job_stop_ms - print_job_start_ms) / 1000; millis_t t = print_job_timer.duration();
int hours = t / 60 / 60, minutes = (t / 60) % 60; int hours = t / 60 / 60, minutes = (t / 60) % 60;
sprintf_P(time, PSTR("%i " MSG_END_HOUR " %i " MSG_END_MINUTE), hours, minutes); sprintf_P(time, PSTR("%i " MSG_END_HOUR " %i " MSG_END_MINUTE), hours, minutes);
ECHO_LT(DB, time); ECHO_LT(DB, time);
...@@ -906,27 +969,47 @@ void get_command() { ...@@ -906,27 +969,47 @@ void get_command() {
card.printingHasFinished(); card.printingHasFinished();
card.checkautostart(true); card.checkautostart(true);
} }
if (serial_char == '#') stop_buffering = true; if (sd_char == '#') stop_buffering = true;
sd_comment_mode = false; // for new command
if (!sd_count) continue; // skip empty lines
command_queue[cmd_queue_index_w][sd_count] = '\0'; // terminate string
sd_count = 0; // clear buffer
if (!serial_count) { _commit_command(false);
comment_mode = false; //for new command
return; //if empty line
} }
command_queue[cmd_queue_index_w][serial_count] = 0; //terminate string else if (sd_count >= MAX_CMD_SIZE - 1) {
// if (!comment_mode) { /**
fromsd[cmd_queue_index_w] = true; * Keep fetching, but ignore normal characters beyond the max length
commands_in_queue += 1; * The command will be injected when EOL is reached
cmd_queue_index_w = (cmd_queue_index_w + 1) % BUFSIZE; */
// }
comment_mode = false; //for new command
serial_count = 0; //clear buffer
} }
else { else {
if (serial_char == ';') comment_mode = true; if (sd_char == ';') sd_comment_mode = true;
if (!comment_mode) command_queue[cmd_queue_index_w][serial_count++] = serial_char; if (!sd_comment_mode) command_queue[cmd_queue_index_w][sd_count++] = sd_char;
} }
} }
#endif // SDSUPPORT }
#endif // SDSUPPORT
/**
* Add to the circular command queue the next command from:
* - The command-injection queue (queued_commands_P)
* - The active serial input (usually USB)
* - The SD card file being actively printed
*/
void get_available_commands() {
// if any immediate commands remain, don't get other commands yet
if (drain_queued_commands_P()) return;
get_serial_commands();
#if ENABLED(SDSUPPORT)
get_sdcard_commands();
#endif
} }
bool code_has_value() { bool code_has_value() {
...@@ -935,7 +1018,7 @@ bool code_has_value() { ...@@ -935,7 +1018,7 @@ bool code_has_value() {
while (c == ' ') c = seen_pointer[++i]; while (c == ' ') c = seen_pointer[++i];
if (c == '-' || c == '+') c = seen_pointer[++i]; if (c == '-' || c == '+') c = seen_pointer[++i];
if (c == '.') c = seen_pointer[++i]; if (c == '.') c = seen_pointer[++i];
return (c >= '0' && c <= '9'); return NUMERIC(c);
} }
float code_value() { float code_value() {
...@@ -945,7 +1028,8 @@ float code_value() { ...@@ -945,7 +1028,8 @@ float code_value() {
*e = 0; *e = 0;
ret = strtod(seen_pointer + 1, NULL); ret = strtod(seen_pointer + 1, NULL);
*e = 'E'; *e = 'E';
} else }
else
ret = strtod(seen_pointer + 1, NULL); ret = strtod(seen_pointer + 1, NULL);
return ret; return ret;
} }
...@@ -959,6 +1043,48 @@ bool code_seen(char code) { ...@@ -959,6 +1043,48 @@ bool code_seen(char code) {
return (seen_pointer != NULL); // Return TRUE if the code-letter was found return (seen_pointer != NULL); // Return TRUE if the code-letter was found
} }
/**
* Set target_extruder from the T parameter or the active_extruder
*
* Returns TRUE if the target is invalid
*/
bool setTargetedExtruder(int code) {
if (code_seen('T')) {
short t = code_value_short();
if (t >= EXTRUDERS) {
ECHO_SMV(ER, "M", code);
ECHO_EMV(" " SERIAL_INVALID_EXTRUDER, t);
return true;
}
target_extruder = t;
}
else
target_extruder = active_extruder;
return false;
}
/**
* Set target_Hotend from the T parameter or the active_extruder
*
* Returns TRUE if the target is invalid
*/
bool setTargetedHotend(int code) {
if (code_seen('H')) {
short h = code_value_short();
if (h >= HOTENDS) {
ECHO_SMV(ER, "M", code);
ECHO_EMV(" " SERIAL_INVALID_HOTEND, h);
return true;
}
target_extruder = h;
}
else
target_extruder = active_extruder;
return false;
}
#define DEFINE_PGM_READ_ANY(type, reader) \ #define DEFINE_PGM_READ_ANY(type, reader) \
static inline type pgm_read_any(const type *p) \ static inline type pgm_read_any(const type *p) \
{ return pgm_read_##reader##_near(p); } { return pgm_read_##reader##_near(p); }
...@@ -1088,7 +1214,7 @@ static void set_axis_is_at_home(AxisEnum axis) { ...@@ -1088,7 +1214,7 @@ static void set_axis_is_at_home(AxisEnum axis) {
if (axis == Z_AXIS) current_position[Z_AXIS] -= zprobe_zoffset; if (axis == Z_AXIS) current_position[Z_AXIS] -= zprobe_zoffset;
#endif #endif
if (debugLevel & DEBUG_INFO) { if (DEBUGGING(INFO)) {
ECHO_SMV(INFO, "set_axis_is_at_home ", (unsigned long)axis); ECHO_SMV(INFO, "set_axis_is_at_home ", (unsigned long)axis);
ECHO_MV(" > (home_offset[axis]==", home_offset[axis]); ECHO_MV(" > (home_offset[axis]==", home_offset[axis]);
print_xyz(") > current_position", current_position); print_xyz(") > current_position", current_position);
...@@ -1159,7 +1285,7 @@ static void clean_up_after_endstop_move() { ...@@ -1159,7 +1285,7 @@ static void clean_up_after_endstop_move() {
float oldFeedRate = feedrate; float oldFeedRate = feedrate;
feedrate = homing_feedrate[Z_AXIS]; feedrate = homing_feedrate[Z_AXIS];
if (debugLevel & DEBUG_INFO) { if (DEBUGGING(INFO)) {
ECHO_S(INFO); ECHO_S(INFO);
print_xyz("do_blocking_move_to", x, y, z); print_xyz("do_blocking_move_to", x, y, z);
} }
...@@ -1201,7 +1327,7 @@ static void clean_up_after_endstop_move() { ...@@ -1201,7 +1327,7 @@ static void clean_up_after_endstop_move() {
current_position[Y_AXIS] = corrected_position.y; current_position[Y_AXIS] = corrected_position.y;
current_position[Z_AXIS] = corrected_position.z; current_position[Z_AXIS] = corrected_position.z;
if (debugLevel & DEBUG_INFO) { if (DEBUGGING(INFO)) {
ECHO_S(INFO); ECHO_S(INFO);
print_xyz("set_bed_level_equation_lsq > current_position", current_position); print_xyz("set_bed_level_equation_lsq > current_position", current_position);
} }
...@@ -1231,7 +1357,7 @@ static void clean_up_after_endstop_move() { ...@@ -1231,7 +1357,7 @@ static void clean_up_after_endstop_move() {
current_position[Y_AXIS] = corrected_position.y; current_position[Y_AXIS] = corrected_position.y;
current_position[Z_AXIS] = corrected_position.z; current_position[Z_AXIS] = corrected_position.z;
if (debugLevel & DEBUG_INFO) { if (DEBUGGING(INFO)) {
ECHO_S(INFO); ECHO_S(INFO);
print_xyz("set_bed_level_equation_3pts > current_position", current_position); print_xyz("set_bed_level_equation_3pts > current_position", current_position);
} }
...@@ -1273,14 +1399,14 @@ static void clean_up_after_endstop_move() { ...@@ -1273,14 +1399,14 @@ static void clean_up_after_endstop_move() {
current_position[Z_AXIS] = st_get_axis_position_mm(Z_AXIS); current_position[Z_AXIS] = st_get_axis_position_mm(Z_AXIS);
sync_plan_position(); sync_plan_position();
if (debugLevel & DEBUG_INFO) { if (DEBUGGING(INFO)) {
ECHO_S(INFO); ECHO_S(INFO);
print_xyz("run_z_probe > current_position", current_position); print_xyz("run_z_probe > current_position", current_position);
} }
} }
static void deploy_z_probe() { static void deploy_z_probe() {
if (debugLevel & DEBUG_INFO) { if (DEBUGGING(INFO)) {
ECHO_S(INFO); ECHO_S(INFO);
print_xyz("deploy_z_probe > current_position", current_position); print_xyz("deploy_z_probe > current_position", current_position);
} }
...@@ -1291,7 +1417,7 @@ static void clean_up_after_endstop_move() { ...@@ -1291,7 +1417,7 @@ static void clean_up_after_endstop_move() {
} }
static void stow_z_probe(bool doRaise = true) { static void stow_z_probe(bool doRaise = true) {
if (debugLevel & DEBUG_INFO) { if (DEBUGGING(INFO)) {
ECHO_S(INFO); ECHO_S(INFO);
print_xyz("stow_z_probe > current_position", current_position); print_xyz("stow_z_probe > current_position", current_position);
} }
...@@ -1301,7 +1427,7 @@ static void clean_up_after_endstop_move() { ...@@ -1301,7 +1427,7 @@ static void clean_up_after_endstop_move() {
#if Z_RAISE_AFTER_PROBING > 0 #if Z_RAISE_AFTER_PROBING > 0
if (doRaise) { if (doRaise) {
if (debugLevel & DEBUG_INFO) { if (DEBUGGING(INFO)) {
ECHO_LMV(INFO, "Raise Z (after) by ", (float)Z_RAISE_AFTER_PROBING); ECHO_LMV(INFO, "Raise Z (after) by ", (float)Z_RAISE_AFTER_PROBING);
ECHO_LMV(INFO, "> SERVO_ENDSTOPS > do_blocking_move_to_z ", current_position[Z_AXIS] + Z_RAISE_AFTER_PROBING); ECHO_LMV(INFO, "> SERVO_ENDSTOPS > do_blocking_move_to_z ", current_position[Z_AXIS] + Z_RAISE_AFTER_PROBING);
} }
...@@ -1325,7 +1451,7 @@ static void clean_up_after_endstop_move() { ...@@ -1325,7 +1451,7 @@ static void clean_up_after_endstop_move() {
// Probe bed height at position (x,y), returns the measured z value // Probe bed height at position (x,y), returns the measured z value
static float probe_pt(float x, float y, float z_before, ProbeAction probe_action = ProbeDeployAndStow, int verbose_level = 1) { static float probe_pt(float x, float y, float z_before, ProbeAction probe_action = ProbeDeployAndStow, int verbose_level = 1) {
if (debugLevel & DEBUG_INFO) { if (DEBUGGING(INFO)) {
ECHO_LM(INFO, "probe_pt >>>"); ECHO_LM(INFO, "probe_pt >>>");
ECHO_SMV(INFO, "> ProbeAction:", (unsigned long)probe_action); ECHO_SMV(INFO, "> ProbeAction:", (unsigned long)probe_action);
print_xyz(" > current_position", current_position); print_xyz(" > current_position", current_position);
...@@ -1336,7 +1462,7 @@ static void clean_up_after_endstop_move() { ...@@ -1336,7 +1462,7 @@ static void clean_up_after_endstop_move() {
// Move Z up to the z_before height, then move the probe to the given XY // Move Z up to the z_before height, then move the probe to the given XY
do_blocking_move_to_z(z_before); // this also updates current_position do_blocking_move_to_z(z_before); // this also updates current_position
if (debugLevel & DEBUG_INFO) { if (DEBUGGING(INFO)) {
ECHO_SMV(INFO, "> do_blocking_move_to_xy ", x - (X_PROBE_OFFSET_FROM_EXTRUDER)); ECHO_SMV(INFO, "> do_blocking_move_to_xy ", x - (X_PROBE_OFFSET_FROM_EXTRUDER));
ECHO_EMV(", ", y - Y_PROBE_OFFSET_FROM_EXTRUDER); ECHO_EMV(", ", y - Y_PROBE_OFFSET_FROM_EXTRUDER);
} }
...@@ -1345,7 +1471,7 @@ static void clean_up_after_endstop_move() { ...@@ -1345,7 +1471,7 @@ static void clean_up_after_endstop_move() {
#if HASNT(Z_PROBE_SLED) #if HASNT(Z_PROBE_SLED)
if (probe_action & ProbeDeploy) { if (probe_action & ProbeDeploy) {
if (debugLevel & DEBUG_INFO) ECHO_LM(INFO, "> ProbeDeploy"); if (DEBUGGING(INFO)) ECHO_LM(INFO, "> ProbeDeploy");
deploy_z_probe(); deploy_z_probe();
} }
#endif #endif
...@@ -1355,7 +1481,7 @@ static void clean_up_after_endstop_move() { ...@@ -1355,7 +1481,7 @@ static void clean_up_after_endstop_move() {
#if HASNT(Z_PROBE_SLED) #if HASNT(Z_PROBE_SLED)
if (probe_action & ProbeStow) { if (probe_action & ProbeStow) {
if (debugLevel & DEBUG_INFO) ECHO_LM(INFO, "> ProbeStow (stow_z_probe will do Z Raise)"); if (DEBUGGING(INFO)) ECHO_LM(INFO, "> ProbeStow (stow_z_probe will do Z Raise)");
stow_z_probe(); stow_z_probe();
} }
#endif #endif
...@@ -1367,7 +1493,7 @@ static void clean_up_after_endstop_move() { ...@@ -1367,7 +1493,7 @@ static void clean_up_after_endstop_move() {
ECHO_EMV(SERIAL_BED_LEVELLING_Z, measured_z, 3); ECHO_EMV(SERIAL_BED_LEVELLING_Z, measured_z, 3);
} }
if (debugLevel & DEBUG_INFO) ECHO_LM(INFO, "<<< probe_pt"); if (DEBUGGING(INFO)) ECHO_LM(INFO, "<<< probe_pt");
return measured_z; return measured_z;
} }
...@@ -1386,7 +1512,7 @@ static void clean_up_after_endstop_move() { ...@@ -1386,7 +1512,7 @@ static void clean_up_after_endstop_move() {
#define HOMEAXIS_DO(LETTER) \ #define HOMEAXIS_DO(LETTER) \
((LETTER##_MIN_PIN > -1 && LETTER##_HOME_DIR==-1) || (LETTER##_MAX_PIN > -1 && LETTER##_HOME_DIR==1)) ((LETTER##_MIN_PIN > -1 && LETTER##_HOME_DIR==-1) || (LETTER##_MAX_PIN > -1 && LETTER##_HOME_DIR==1))
if (debugLevel & DEBUG_INFO) { if (DEBUGGING(INFO)) {
ECHO_SMV(INFO, ">>> homeaxis(", (unsigned long)axis); ECHO_SMV(INFO, ">>> homeaxis(", (unsigned long)axis);
ECHO_EM(")"); ECHO_EM(")");
} }
...@@ -1455,7 +1581,7 @@ static void clean_up_after_endstop_move() { ...@@ -1455,7 +1581,7 @@ static void clean_up_after_endstop_move() {
line_to_destination(); line_to_destination();
st_synchronize(); st_synchronize();
if (debugLevel & DEBUG_INFO) { if (DEBUGGING(INFO)) {
ECHO_S(INFO); ECHO_S(INFO);
print_xyz("> TRIGGER ENDSTOP > current_position", current_position); print_xyz("> TRIGGER ENDSTOP > current_position", current_position);
} }
...@@ -1489,7 +1615,7 @@ static void clean_up_after_endstop_move() { ...@@ -1489,7 +1615,7 @@ static void clean_up_after_endstop_move() {
set_axis_is_at_home(axis); set_axis_is_at_home(axis);
sync_plan_position(); sync_plan_position();
if (debugLevel & DEBUG_INFO) { if (DEBUGGING(INFO)) {
ECHO_S(INFO); ECHO_S(INFO);
print_xyz("> AFTER set_axis_is_at_home > current_position", current_position); print_xyz("> AFTER set_axis_is_at_home > current_position", current_position);
} }
...@@ -1511,7 +1637,7 @@ static void clean_up_after_endstop_move() { ...@@ -1511,7 +1637,7 @@ static void clean_up_after_endstop_move() {
// Deploy a probe if there is one, and homing towards the bed // Deploy a probe if there is one, and homing towards the bed
if (axis == Z_AXIS) { if (axis == Z_AXIS) {
if (axis_home_dir < 0) { if (axis_home_dir < 0) {
if (debugLevel & DEBUG_INFO) ECHO_LM(INFO, "> SERVO_LEVELING > stow_z_probe"); if (DEBUGGING(INFO)) ECHO_LM(INFO, "> SERVO_LEVELING > stow_z_probe");
stow_z_probe(); stow_z_probe();
} }
} }
...@@ -1521,13 +1647,13 @@ static void clean_up_after_endstop_move() { ...@@ -1521,13 +1647,13 @@ static void clean_up_after_endstop_move() {
#if HAS(SERVO_ENDSTOPS) #if HAS(SERVO_ENDSTOPS)
// Retract Servo endstop if enabled // Retract Servo endstop if enabled
if (servo_endstop_id[axis] >= 0) { if (servo_endstop_id[axis] >= 0) {
if (debugLevel & DEBUG_INFO) ECHO_LM(INFO, "> SERVO_ENDSTOPS > Stow with servo.move()"); if (DEBUGGING(INFO)) ECHO_LM(INFO, "> SERVO_ENDSTOPS > Stow with servo.move()");
servo[servo_endstop_id[axis]].move(servo_endstop_angle[axis][1]); servo[servo_endstop_id[axis]].move(servo_endstop_angle[axis][1]);
} }
#endif #endif
} }
} }
if (debugLevel & DEBUG_INFO) { if (DEBUGGING(INFO)) {
ECHO_SMV(INFO, "<<< homeaxis(", (unsigned long)axis); ECHO_SMV(INFO, "<<< homeaxis(", (unsigned long)axis);
ECHO_EM(")"); ECHO_EM(")");
} }
...@@ -1581,7 +1707,7 @@ static void clean_up_after_endstop_move() { ...@@ -1581,7 +1707,7 @@ static void clean_up_after_endstop_move() {
enable_endstops(false); // Disable endstops while moving away enable_endstops(false); // Disable endstops while moving away
sync_plan_position(); sync_plan_position();
destination[axis] = endstop_adj[axis]; destination[axis] = endstop_adj[axis];
if (debugLevel & DEBUG_INFO) { if (DEBUGGING(INFO)) {
ECHO_SMV(INFO, "> endstop_adj = ", endstop_adj[axis]); ECHO_SMV(INFO, "> endstop_adj = ", endstop_adj[axis]);
print_xyz(" > destination", destination); print_xyz(" > destination", destination);
} }
...@@ -1590,13 +1716,13 @@ static void clean_up_after_endstop_move() { ...@@ -1590,13 +1716,13 @@ static void clean_up_after_endstop_move() {
enable_endstops(true); // Enable endstops for next homing move enable_endstops(true); // Enable endstops for next homing move
} }
if (debugLevel & DEBUG_INFO) ECHO_LMV(INFO, "> endstop_adj * axis_home_dir = ", endstop_adj[axis] * axis_home_dir); if (DEBUGGING(INFO)) ECHO_LMV(INFO, "> endstop_adj * axis_home_dir = ", endstop_adj[axis] * axis_home_dir);
// Set the axis position to its home position (plus home offsets) // Set the axis position to its home position (plus home offsets)
set_axis_is_at_home(axis); set_axis_is_at_home(axis);
sync_plan_position(); sync_plan_position();
if (debugLevel & DEBUG_INFO) { if (DEBUGGING(INFO)) {
ECHO_S(INFO); ECHO_S(INFO);
print_xyz("> AFTER set_axis_is_at_home > current_position", current_position); print_xyz("> AFTER set_axis_is_at_home > current_position", current_position);
} }
...@@ -1679,7 +1805,7 @@ static void clean_up_after_endstop_move() { ...@@ -1679,7 +1805,7 @@ static void clean_up_after_endstop_move() {
// Reset calibration results to zero. // Reset calibration results to zero.
void reset_bed_level() { void reset_bed_level() {
if (debugLevel & DEBUG_INFO) ECHO_LM(INFO, "reset_bed_level"); if (DEBUGGING(INFO)) ECHO_LM(INFO, "reset_bed_level");
for (int y = 0; y < AUTO_BED_LEVELING_GRID_POINTS; y++) { for (int y = 0; y < AUTO_BED_LEVELING_GRID_POINTS; y++) {
for (int x = 0; x < AUTO_BED_LEVELING_GRID_POINTS; x++) { for (int x = 0; x < AUTO_BED_LEVELING_GRID_POINTS; x++) {
bed_level[x][y] = 0.0; bed_level[x][y] = 0.0;
...@@ -1807,7 +1933,7 @@ static void clean_up_after_endstop_move() { ...@@ -1807,7 +1933,7 @@ static void clean_up_after_endstop_move() {
float high_endstop = max(max(endstop_adj[0], endstop_adj[1]), endstop_adj[2]); float high_endstop = max(max(endstop_adj[0], endstop_adj[1]), endstop_adj[2]);
if (debugLevel & DEBUG_INFO) { if (DEBUGGING(INFO)) {
ECHO_LMV(INFO, "High endstop: ", high_endstop, 4); ECHO_LMV(INFO, "High endstop: ", high_endstop, 4);
} }
...@@ -2328,7 +2454,7 @@ static void clean_up_after_endstop_move() { ...@@ -2328,7 +2454,7 @@ static void clean_up_after_endstop_move() {
probe_z = probe_bed_mean / probe_count; probe_z = probe_bed_mean / probe_count;
if (debugLevel & DEBUG_INFO) { if (DEBUGGING(INFO)) {
ECHO_SM(INFO, "Bed probe heights: "); ECHO_SM(INFO, "Bed probe heights: ");
for(int i = 0; i < probe_count; i++) { for(int i = 0; i < probe_count; i++) {
if (probe_bed_array[i] >= 0) ECHO_M(" "); if (probe_bed_array[i] >= 0) ECHO_M(" ");
...@@ -2465,7 +2591,7 @@ static void clean_up_after_endstop_move() { ...@@ -2465,7 +2591,7 @@ static void clean_up_after_endstop_move() {
} }
void prepare_move_raw() { void prepare_move_raw() {
if (debugLevel & DEBUG_DEBUG) { if (DEBUGGING(DEBUG)) {
ECHO_S(DEB); ECHO_S(DEB);
print_xyz("prepare_move_raw > destination", destination); print_xyz("prepare_move_raw > destination", destination);
} }
...@@ -2512,7 +2638,7 @@ static void clean_up_after_endstop_move() { ...@@ -2512,7 +2638,7 @@ static void clean_up_after_endstop_move() {
delta[TOWER_2] += offset; delta[TOWER_2] += offset;
delta[TOWER_3] += offset; delta[TOWER_3] += offset;
if (debugLevel & DEBUG_DEBUG) { if (DEBUGGING(DEBUG)) {
ECHO_SMV(DEB, "grid_x=", grid_x); ECHO_SMV(DEB, "grid_x=", grid_x);
ECHO_MV(" grid_y=", grid_y); ECHO_MV(" grid_y=", grid_y);
ECHO_MV(" floor_x=", floor_x); ECHO_MV(" floor_x=", floor_x);
...@@ -2651,7 +2777,7 @@ static void clean_up_after_endstop_move() { ...@@ -2651,7 +2777,7 @@ static void clean_up_after_endstop_move() {
* offset[in] The additional distance to move to adjust docking location * offset[in] The additional distance to move to adjust docking location
*/ */
static void dock_sled(bool dock, int offset=0) { static void dock_sled(bool dock, int offset=0) {
if (debugLevel & DEBUG_INFO) ECHO_LMV(INFO, "dock_sled", dock); if (DEBUGGING(INFO)) ECHO_LMV(INFO, "dock_sled", dock);
if (axis_known_position & (_BV(X_AXIS)|_BV(Y_AXIS)) != (_BV(X_AXIS)|_BV(Y_AXIS))) { if (axis_known_position & (_BV(X_AXIS)|_BV(Y_AXIS)) != (_BV(X_AXIS)|_BV(Y_AXIS))) {
LCD_MESSAGEPGM(MSG_POSITION_UNKNOWN); LCD_MESSAGEPGM(MSG_POSITION_UNKNOWN);
...@@ -2736,30 +2862,36 @@ static void clean_up_after_endstop_move() { ...@@ -2736,30 +2862,36 @@ static void clean_up_after_endstop_move() {
#endif #endif
inline void wait_heater() { inline void wait_heater() {
// Exit if the temperature is above target and not waiting for cooling bool wants_to_cool = isCoolingHotend(target_extruder);
if (no_wait_for_cooling && !isHeatingHotend(target_extruder)) return;
// Exit if S<lower>, continue if S<higher>, R<lower>, or R<higher>
if (no_wait_for_cooling && wants_to_cool) return;
// Prevents a wait-forever situation if R is misused i.e. M109 R0
// Try to calculate a ballpark safe margin by halving EXTRUDE_MINTEMP
if (wants_to_cool && degTargetHotend(target_extruder) < (EXTRUDE_MINTEMP)/2) return;
#if ENABLED(TEMP_RESIDENCY_TIME) #if ENABLED(TEMP_RESIDENCY_TIME)
long residency_start_ms = -1; long residency_start_ms = -1;
// Loop until the temperature has stabilized // Loop until the temperature has stabilized
#define TEMP_CONDITIONS (residency_start_ms < 0 || now < residency_start_ms + (TEMP_RESIDENCY_TIME) * 1000UL) #define TEMP_CONDITIONS (!residency_start_ms || PENDING(now, residency_start_ms + (TEMP_RESIDENCY_TIME) * 1000UL))
#else #else
// Loop until the temperature is exactly on target // Loop until the temperature is exactly on target
#define TEMP_CONDITIONS (degHotend(target_extruder) != degTargetHotend(target_extruder)) #define TEMP_CONDITIONS (wants_to_cool ? isCoolingHotend(target_extruder) : isHeatingHotend(target_extruder))
#endif // TEMP_RESIDENCY_TIME #endif // TEMP_RESIDENCY_TIME
cancel_heatup = false; cancel_heatup = false;
millis_t now = millis(), next_temp_ms = now + 1000UL; millis_t now, next_temp_ms = 0;
while (!cancel_heatup && TEMP_CONDITIONS) { do {
now = millis(); now = millis();
if (now > next_temp_ms) { // Print temp & remaining time every 1s while waiting if (ELAPSED(now, next_temp_ms)) { //Print temp & remaining time every 1s while waiting
next_temp_ms = now + 1000UL; next_temp_ms = now + 1000UL;
#if HAS(TEMP_0) || HAS(TEMP_BED) || ENABLED(HEATER_0_USES_MAX6675) #if HAS(TEMP_0) || HAS(TEMP_BED) || ENABLED(HEATER_0_USES_MAX6675)
print_heaterstates(); print_heaterstates();
#endif #endif
#if ENABLED(TEMP_RESIDENCY_TIME) #if TEMP_RESIDENCY_TIME > 0
ECHO_M(" " SERIAL_W); ECHO_M(" " SERIAL_W);
if (residency_start_ms >= 0) { if (residency_start_ms) {
long rem = ((TEMP_RESIDENCY_TIME * 1000UL) - (now - residency_start_ms)) / 1000UL; long rem = ((TEMP_RESIDENCY_TIME * 1000UL) - (now - residency_start_ms)) / 1000UL;
ECHO_EV(rem); ECHO_EV(rem);
} }
...@@ -2772,39 +2904,85 @@ inline void wait_heater() { ...@@ -2772,39 +2904,85 @@ inline void wait_heater() {
} }
idle(); idle();
refresh_cmd_timeout(); // to prevent stepper_inactive_time from running out
#if ENABLED(TEMP_RESIDENCY_TIME) #if TEMP_RESIDENCY_TIME > 0
float temp_diff = fabs(degTargetHotend(target_extruder) - degHotend(target_extruder));
if (!residency_start_ms) {
// Start the TEMP_RESIDENCY_TIME timer when we reach target temp for the first time. // Start the TEMP_RESIDENCY_TIME timer when we reach target temp for the first time.
if (temp_diff < TEMP_WINDOW) residency_start_ms = millis();
}
else if (temp_diff > TEMP_HYSTERESIS) {
// Restart the timer whenever the temperature falls outside the hysteresis. // Restart the timer whenever the temperature falls outside the hysteresis.
if (labs(degHotend(target_extruder) - degTargetHotend(target_extruder)) > ((residency_start_ms < 0) ? TEMP_WINDOW : TEMP_HYSTERESIS))
residency_start_ms = millis(); residency_start_ms = millis();
#endif // TEMP_RESIDENCY_TIME }
} // while(!cancel_heatup && TEMP_CONDITIONS) #endif //TEMP_RESIDENCY_TIME > 0
} while(!cancel_heatup && TEMP_CONDITIONS);
LCD_MESSAGEPGM(MSG_HEATING_COMPLETE); LCD_MESSAGEPGM(MSG_HEATING_COMPLETE);
refresh_cmd_timeout();
print_job_start_ms = previous_cmd_ms;
} }
inline void wait_bed() { inline void wait_bed() {
bool wants_to_cool = isCoolingBed();
// Exit if the temperature is above target and not waiting for cooling // Exit if the temperature is above target and not waiting for cooling
if (no_wait_for_cooling && !isHeatingBed()) return; if (no_wait_for_cooling && wants_to_cool) return;
#if TEMP_BED_RESIDENCY_TIME > 0
millis_t residency_start_ms = 0;
// Loop until the temperature has stabilized
#define TEMP_BED_CONDITIONS (!residency_start_ms || PENDING(now, residency_start_ms + (TEMP_BED_RESIDENCY_TIME) * 1000UL))
#else
// Loop until the temperature is very close target
#define TEMP_BED_CONDITIONS (wants_to_cool ? isCoolingBed() : isHeatingBed())
#endif // TEMP_BED_RESIDENCY_TIME > 0
cancel_heatup = false; cancel_heatup = false;
millis_t now = millis(), next_temp_ms = now + 1000UL; millis_t now, next_temp_ms = 0;
while (!cancel_heatup && degTargetBed() != degBed()) {
millis_t now = millis(); // Wait for temperature to come close enough
if (now > next_temp_ms) { // Print Temp Reading every 1 second while heating up. do {
now = millis();
if (ELAPSED(now, next_temp_ms)) { //Print Temp Reading every 1 second while heating up.
next_temp_ms = now + 1000UL; next_temp_ms = now + 1000UL;
print_heaterstates(); print_heaterstates();
#if TEMP_BED_RESIDENCY_TIME > 0
ECHO_M(" " SERIAL_W);
if (residency_start_ms) {
long rem = (((TEMP_BED_RESIDENCY_TIME) * 1000UL) - (now - residency_start_ms)) / 1000UL;
ECHO_EV(rem);
}
else {
ECHO_EM("?");
}
#else
ECHO_E; ECHO_E;
#endif
} }
idle(); idle();
refresh_cmd_timeout(); // to prevent stepper_inactive_time from running out
#if TEMP_BED_RESIDENCY_TIME > 0
float temp_diff = fabs(degBed() - degTargetBed());
if (!residency_start_ms) {
// Start the TEMP_BED_RESIDENCY_TIME timer when we reach target temp for the first time.
if (temp_diff < TEMP_BED_WINDOW) residency_start_ms = millis();
} }
else if (temp_diff > TEMP_BED_HYSTERESIS) {
// Restart the timer whenever the temperature falls outside the hysteresis.
residency_start_ms = millis();
}
#endif //TEMP_BED_RESIDENCY_TIME > 0
} while (!cancel_heatup && TEMP_BED_CONDITIONS);
LCD_MESSAGEPGM(MSG_BED_DONE); LCD_MESSAGEPGM(MSG_BED_DONE);
refresh_cmd_timeout();
} }
/****************************************************************************** /******************************************************************************
***************************** G-Code Functions ******************************** ***************************** G-Code Functions ********************************
*******************************************************************************/ *******************************************************************************/
...@@ -2867,6 +3045,35 @@ void unknown_command_error() { ...@@ -2867,6 +3045,35 @@ void unknown_command_error() {
ECHO_LMV(ER, SERIAL_UNKNOWN_COMMAND, current_command); ECHO_LMV(ER, SERIAL_UNKNOWN_COMMAND, current_command);
} }
#if ENABLED(HOST_KEEPALIVE_FEATURE)
/**
* Output a "busy" message at regular intervals
* while the machine is not accepting commands.
*/
void host_keepalive() {
millis_t ms = millis();
if (host_keepalive_interval && busy_state != NOT_BUSY) {
if (PENDING(ms, next_busy_signal_ms)) return;
switch (busy_state) {
case IN_HANDLER:
case IN_PROCESS:
ECHO_LM(BUSY, SERIAL_BUSY_PROCESSING);
break;
case PAUSED_FOR_USER:
ECHO_LM(BUSY, SERIAL_BUSY_PAUSED_FOR_USER);
break;
case PAUSED_FOR_INPUT:
ECHO_LM(BUSY, SERIAL_BUSY_PAUSED_FOR_INPUT);
break;
default:
break;
}
}
next_busy_signal_ms = ms + host_keepalive_interval * 1000UL;
}
#endif //HOST_KEEPALIVE_FEATURE
/** /**
* G0, G1: Coordinated movement of X Y Z E axes * G0, G1: Coordinated movement of X Y Z E axes
*/ */
...@@ -2977,7 +3184,7 @@ inline void gcode_G4() { ...@@ -2977,7 +3184,7 @@ inline void gcode_G4() {
* *
*/ */
inline void gcode_G28() { inline void gcode_G28() {
if (debugLevel & DEBUG_INFO) ECHO_LM(INFO, "gcode_G28 >>>"); if (DEBUGGING(INFO)) ECHO_LM(INFO, "gcode_G28 >>>");
// Wait for planner moves to finish! // Wait for planner moves to finish!
st_synchronize(); st_synchronize();
...@@ -3045,7 +3252,7 @@ inline void gcode_G28() { ...@@ -3045,7 +3252,7 @@ inline void gcode_G28() {
sync_plan_position_delta(); sync_plan_position_delta();
if (debugLevel & DEBUG_INFO) { if (DEBUGGING(INFO)) {
ECHO_S(INFO); ECHO_S(INFO);
print_xyz("(DELTA) > current_position", current_position); print_xyz("(DELTA) > current_position", current_position);
} }
...@@ -3057,7 +3264,7 @@ inline void gcode_G28() { ...@@ -3057,7 +3264,7 @@ inline void gcode_G28() {
#if Z_HOME_DIR > 0 // If homing away from BED do Z first #if Z_HOME_DIR > 0 // If homing away from BED do Z first
HOMEAXIS(Z); HOMEAXIS(Z);
if (debugLevel & DEBUG_INFO) { if (DEBUGGING(INFO)) {
ECHO_S(INFO); ECHO_S(INFO);
print_xyz("> HOMEAXIS(Z) > current_position", current_position); print_xyz("> HOMEAXIS(Z) > current_position", current_position);
} }
...@@ -3066,7 +3273,7 @@ inline void gcode_G28() { ...@@ -3066,7 +3273,7 @@ inline void gcode_G28() {
// Raise Z before homing any other axes // Raise Z before homing any other axes
destination[Z_AXIS] = -(Z_RAISE_BEFORE_HOMING) * home_dir(Z_AXIS); // Set destination away from bed destination[Z_AXIS] = -(Z_RAISE_BEFORE_HOMING) * home_dir(Z_AXIS); // Set destination away from bed
if (debugLevel & DEBUG_INFO) { if (DEBUGGING(INFO)) {
ECHO_SMV(INFO, "Raise Z (before homing) by ", (float)Z_RAISE_BEFORE_HOMING); ECHO_SMV(INFO, "Raise Z (before homing) by ", (float)Z_RAISE_BEFORE_HOMING);
print_xyz(" > (home_all_axis || homeZ) > destination", destination); print_xyz(" > (home_all_axis || homeZ) > destination", destination);
} }
...@@ -3106,7 +3313,7 @@ inline void gcode_G28() { ...@@ -3106,7 +3313,7 @@ inline void gcode_G28() {
set_axis_is_at_home(Y_AXIS); set_axis_is_at_home(Y_AXIS);
sync_plan_position(); sync_plan_position();
if (debugLevel & DEBUG_INFO) { if (DEBUGGING(INFO)) {
ECHO_S(INFO); ECHO_S(INFO);
print_xyz("> QUICK_HOME > current_position 1", current_position); print_xyz("> QUICK_HOME > current_position 1", current_position);
} }
...@@ -3124,7 +3331,7 @@ inline void gcode_G28() { ...@@ -3124,7 +3331,7 @@ inline void gcode_G28() {
current_position[Z_AXIS] = destination[Z_AXIS]; current_position[Z_AXIS] = destination[Z_AXIS];
#endif #endif
if (debugLevel & DEBUG_INFO) { if (DEBUGGING(INFO)) {
ECHO_S(INFO); ECHO_S(INFO);
print_xyz("> QUICK_HOME > current_position 2", current_position); print_xyz("> QUICK_HOME > current_position 2", current_position);
} }
...@@ -3153,7 +3360,7 @@ inline void gcode_G28() { ...@@ -3153,7 +3360,7 @@ inline void gcode_G28() {
#else #else
HOMEAXIS(X); HOMEAXIS(X);
#endif #endif
if (debugLevel & DEBUG_INFO) { if (DEBUGGING(INFO)) {
ECHO_S(INFO); ECHO_S(INFO);
print_xyz("> homeX", current_position); print_xyz("> homeX", current_position);
} }
...@@ -3163,7 +3370,7 @@ inline void gcode_G28() { ...@@ -3163,7 +3370,7 @@ inline void gcode_G28() {
// Home Y // Home Y
if (home_all_axis || homeY) { if (home_all_axis || homeY) {
HOMEAXIS(Y); HOMEAXIS(Y);
if (debugLevel & DEBUG_INFO) { if (DEBUGGING(INFO)) {
ECHO_S(INFO); ECHO_S(INFO);
print_xyz("> homeY", current_position); print_xyz("> homeY", current_position);
} }
...@@ -3176,9 +3383,9 @@ inline void gcode_G28() { ...@@ -3176,9 +3383,9 @@ inline void gcode_G28() {
if (code_seen('M') && !(homeX || homeY)) { if (code_seen('M') && !(homeX || homeY)) {
// Manual G28 bed level // Manual G28 bed level
#if ENABLED(ULTIPANEL) #if ENABLED(ULTIPANEL)
ECHO_LM(DB, " --LEVEL PLATE SCRIPT--"); ECHO_LM(DB, "--LEVEL PLATE SCRIPT--");
while(!lcd_clicked()) { while(!lcd_clicked()) {
idle(true); idle();
} }
saved_feedrate = feedrate; saved_feedrate = feedrate;
saved_feedrate_multiplier = feedrate_multiplier; saved_feedrate_multiplier = feedrate_multiplier;
...@@ -3218,7 +3425,7 @@ inline void gcode_G28() { ...@@ -3218,7 +3425,7 @@ inline void gcode_G28() {
do_blocking_move_to(LEFT_PROBE_BED_POSITION, FRONT_PROBE_BED_POSITION, current_position[Z_AXIS]); do_blocking_move_to(LEFT_PROBE_BED_POSITION, FRONT_PROBE_BED_POSITION, current_position[Z_AXIS]);
do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], Z_MIN_POS); do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], Z_MIN_POS);
while(!lcd_clicked()) { while(!lcd_clicked()) {
idle(true); idle();
} }
// PROBE SECOND POINT // PROBE SECOND POINT
...@@ -3227,7 +3434,7 @@ inline void gcode_G28() { ...@@ -3227,7 +3434,7 @@ inline void gcode_G28() {
do_blocking_move_to(RIGHT_PROBE_BED_POSITION, FRONT_PROBE_BED_POSITION, current_position[Z_AXIS]); do_blocking_move_to(RIGHT_PROBE_BED_POSITION, FRONT_PROBE_BED_POSITION, current_position[Z_AXIS]);
do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], Z_MIN_POS); do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], Z_MIN_POS);
while(!lcd_clicked()) { while(!lcd_clicked()) {
idle(true); idle();
} }
// PROBE THIRD POINT // PROBE THIRD POINT
...@@ -3236,7 +3443,7 @@ inline void gcode_G28() { ...@@ -3236,7 +3443,7 @@ inline void gcode_G28() {
do_blocking_move_to(RIGHT_PROBE_BED_POSITION, BACK_PROBE_BED_POSITION, current_position[Z_AXIS]); do_blocking_move_to(RIGHT_PROBE_BED_POSITION, BACK_PROBE_BED_POSITION, current_position[Z_AXIS]);
do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], Z_MIN_POS); do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], Z_MIN_POS);
while(!lcd_clicked()) { while(!lcd_clicked()) {
idle(true); idle();
} }
// PROBE FOURTH POINT // PROBE FOURTH POINT
...@@ -3245,7 +3452,7 @@ inline void gcode_G28() { ...@@ -3245,7 +3452,7 @@ inline void gcode_G28() {
do_blocking_move_to(LEFT_PROBE_BED_POSITION, BACK_PROBE_BED_POSITION, current_position[Z_AXIS]); do_blocking_move_to(LEFT_PROBE_BED_POSITION, BACK_PROBE_BED_POSITION, current_position[Z_AXIS]);
do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], Z_MIN_POS); do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], Z_MIN_POS);
while(!lcd_clicked()) { while(!lcd_clicked()) {
idle(true); idle();
} }
// PROBE CENTER // PROBE CENTER
...@@ -3254,25 +3461,25 @@ inline void gcode_G28() { ...@@ -3254,25 +3461,25 @@ inline void gcode_G28() {
do_blocking_move_to(((X_MAX_POS) - (X_MIN_POS)) / 2, ((Y_MAX_POS) - (Y_MIN_POS)) / 2, current_position[Z_AXIS]); do_blocking_move_to(((X_MAX_POS) - (X_MIN_POS)) / 2, ((Y_MAX_POS) - (Y_MIN_POS)) / 2, current_position[Z_AXIS]);
do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], Z_MIN_POS); do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], Z_MIN_POS);
while(!lcd_clicked()) { while(!lcd_clicked()) {
idle(true); idle();
} }
// FINISH MANUAL BED LEVEL // FINISH MANUAL BED LEVEL
set_pageShowInfo(6); set_pageShowInfo(6);
do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], (Z_MIN_POS) + 5); do_blocking_move_to(current_position[X_AXIS], current_position[Y_AXIS], (Z_MIN_POS) + 5);
enqueuecommands_P(PSTR("G28")); enqueue_and_echo_commands_P(PSTR("G28"));
#endif // ULTIPANEL #endif // ULTIPANEL
} }
else if (home_all_axis || homeZ) { else if (home_all_axis || homeZ) {
HOMEAXIS(Z); HOMEAXIS(Z);
if (debugLevel & DEBUG_INFO) { if (DEBUGGING(INFO)) {
ECHO_S(INFO); ECHO_S(INFO);
print_xyz("> (home_all_axis || homeZ) > final", current_position); print_xyz("> (home_all_axis || homeZ) > final", current_position);
} }
} }
#elif ENABLED(Z_SAFE_HOMING) && ENABLED(AUTO_BED_LEVELING_FEATURE)// Z Safe mode activated. #elif ENABLED(Z_SAFE_HOMING) && ENABLED(AUTO_BED_LEVELING_FEATURE)// Z Safe mode activated.
if (debugLevel & DEBUG_INFO) ECHO_LM(INFO, "> Z_SAFE_HOMING >>>"); if (DEBUGGING(INFO)) ECHO_LM(INFO, "> Z_SAFE_HOMING >>>");
if (home_all_axis) { if (home_all_axis) {
...@@ -3289,7 +3496,7 @@ inline void gcode_G28() { ...@@ -3289,7 +3496,7 @@ inline void gcode_G28() {
destination[Z_AXIS] = -(Z_RAISE_BEFORE_HOMING) * home_dir(Z_AXIS); // Set destination away from bed destination[Z_AXIS] = -(Z_RAISE_BEFORE_HOMING) * home_dir(Z_AXIS); // Set destination away from bed
feedrate = xy_travel_speed; feedrate = xy_travel_speed;
if (debugLevel & DEBUG_INFO) { if (DEBUGGING(INFO)) {
ECHO_SMV(INFO, "Raise Z (before homing) by ", (float)Z_RAISE_BEFORE_HOMING); ECHO_SMV(INFO, "Raise Z (before homing) by ", (float)Z_RAISE_BEFORE_HOMING);
print_xyz(" > home_all_axis > current_position", current_position, false); print_xyz(" > home_all_axis > current_position", current_position, false);
print_xyz(" > home_all_axis > destination", destination); print_xyz(" > home_all_axis > destination", destination);
...@@ -3325,7 +3532,7 @@ inline void gcode_G28() { ...@@ -3325,7 +3532,7 @@ inline void gcode_G28() {
destination[Z_AXIS] = -(Z_RAISE_BEFORE_HOMING) * home_dir(Z_AXIS); // Set destination away from bed destination[Z_AXIS] = -(Z_RAISE_BEFORE_HOMING) * home_dir(Z_AXIS); // Set destination away from bed
feedrate = max_feedrate[Z_AXIS] * 60; feedrate = max_feedrate[Z_AXIS] * 60;
if (debugLevel & DEBUG_INFO) { if (DEBUGGING(INFO)) {
ECHO_SMV(INFO, "Raise Z (before homing) by ", (float)Z_RAISE_BEFORE_HOMING); ECHO_SMV(INFO, "Raise Z (before homing) by ", (float)Z_RAISE_BEFORE_HOMING);
print_xyz(" > homeZ > current_position", current_position, false); print_xyz(" > homeZ > current_position", current_position, false);
print_xyz(" > homeZ > destination", destination); print_xyz(" > homeZ > destination", destination);
...@@ -3347,7 +3554,7 @@ inline void gcode_G28() { ...@@ -3347,7 +3554,7 @@ inline void gcode_G28() {
ECHO_LM(DB, MSG_POSITION_UNKNOWN); ECHO_LM(DB, MSG_POSITION_UNKNOWN);
} }
} }
if (debugLevel & DEBUG_INFO) ECHO_LM(INFO, "<<< Z_SAFE_HOMING"); if (DEBUGGING(INFO)) ECHO_LM(INFO, "<<< Z_SAFE_HOMING");
#elif ENABLED(Z_SAFE_HOMING) #elif ENABLED(Z_SAFE_HOMING)
if (home_all_axis || homeZ) { if (home_all_axis || homeZ) {
...@@ -3361,7 +3568,7 @@ inline void gcode_G28() { ...@@ -3361,7 +3568,7 @@ inline void gcode_G28() {
destination[Z_AXIS] = current_position[Z_AXIS] = 0; destination[Z_AXIS] = current_position[Z_AXIS] = 0;
feedrate = xy_travel_speed; feedrate = xy_travel_speed;
if (debugLevel & DEBUG_INFO) { if (DEBUGGING(INFO)) {
ECHO_SMV(INFO, "Raise Z (before homing) by ", (float)Z_RAISE_BEFORE_HOMING); ECHO_SMV(INFO, "Raise Z (before homing) by ", (float)Z_RAISE_BEFORE_HOMING);
print_xyz(" > home_all_axis > current_position", current_position, false); print_xyz(" > home_all_axis > current_position", current_position, false);
print_xyz(" > home_all_axis > destination", destination); print_xyz(" > home_all_axis > destination", destination);
...@@ -3381,7 +3588,7 @@ inline void gcode_G28() { ...@@ -3381,7 +3588,7 @@ inline void gcode_G28() {
ECHO_LM(ER, MSG_POSITION_UNKNOWN); ECHO_LM(ER, MSG_POSITION_UNKNOWN);
} }
} }
if (debugLevel & DEBUG_INFO) ECHO_LM(INFO, "<<< Z_SAFE_HOMING"); if (DEBUGGING(INFO)) ECHO_LM(INFO, "<<< Z_SAFE_HOMING");
#endif // Z_SAFE_HOMING #endif // Z_SAFE_HOMING
#endif // Z_HOME_DIR < 0 #endif // Z_HOME_DIR < 0
...@@ -3431,7 +3638,7 @@ inline void gcode_G28() { ...@@ -3431,7 +3638,7 @@ inline void gcode_G28() {
#endif #endif
#endif #endif
if (debugLevel & DEBUG_INFO) ECHO_LM(INFO, "<<< gcode_G28"); if (DEBUGGING(INFO)) ECHO_LM(INFO, "<<< gcode_G28");
} }
#if ENABLED(AUTO_BED_LEVELING_FEATURE) #if ENABLED(AUTO_BED_LEVELING_FEATURE)
...@@ -3479,7 +3686,7 @@ inline void gcode_G28() { ...@@ -3479,7 +3686,7 @@ inline void gcode_G28() {
* *
*/ */
inline void gcode_G29() { inline void gcode_G29() {
if (debugLevel & DEBUG_INFO) ECHO_LM(INFO, "gcode_G29 >>>"); if (DEBUGGING(INFO)) ECHO_LM(INFO, "gcode_G29 >>>");
// Don't allow auto-leveling without homing first // Don't allow auto-leveling without homing first
if (axis_known_position & (_BV(X_AXIS)|_BV(Y_AXIS)) != (_BV(X_AXIS)|_BV(Y_AXIS))) { if (axis_known_position & (_BV(X_AXIS)|_BV(Y_AXIS)) != (_BV(X_AXIS)|_BV(Y_AXIS))) {
...@@ -3619,7 +3826,7 @@ inline void gcode_G28() { ...@@ -3619,7 +3826,7 @@ inline void gcode_G28() {
float measured_z, float measured_z,
z_before = probePointCounter ? Z_RAISE_BETWEEN_PROBINGS + current_position[Z_AXIS] : Z_RAISE_BEFORE_PROBING + current_position[Z_AXIS]; z_before = probePointCounter ? Z_RAISE_BETWEEN_PROBINGS + current_position[Z_AXIS] : Z_RAISE_BEFORE_PROBING + current_position[Z_AXIS];
if (debugLevel & DEBUG_INFO) { if (DEBUGGING(INFO)) {
if (probePointCounter) if (probePointCounter)
ECHO_LMV(INFO, "z_before = (between) ", (float)(Z_RAISE_BETWEEN_PROBINGS + current_position[Z_AXIS])); ECHO_LMV(INFO, "z_before = (between) ", (float)(Z_RAISE_BETWEEN_PROBINGS + current_position[Z_AXIS]));
else else
...@@ -3651,7 +3858,7 @@ inline void gcode_G28() { ...@@ -3651,7 +3858,7 @@ inline void gcode_G28() {
} // xProbe } // xProbe
} // yProbe } // yProbe
if (debugLevel & DEBUG_INFO) { if (DEBUGGING(INFO)) {
ECHO_S(INFO); ECHO_S(INFO);
print_xyz("> probing complete > current_position", current_position); print_xyz("> probing complete > current_position", current_position);
} }
...@@ -3676,12 +3883,17 @@ inline void gcode_G28() { ...@@ -3676,12 +3883,17 @@ inline void gcode_G28() {
// Show the Topography map if enabled // Show the Topography map if enabled
if (do_topography_map) { if (do_topography_map) {
ECHO_LM(DB, "Bed Height Topography:"); ECHO_EM(" Bed Height Topography:");
ECHO_LM(DB, "+-----------+"); ECHO_EM(" +--- BACK --+");
ECHO_LM(DB, "|...Back....|"); ECHO_EM(" | |");
ECHO_LM(DB, "|Left..Right|"); ECHO_EM(" L | (+) | R");
ECHO_LM(DB, "|...Front...|"); ECHO_EM(" E | | I");
ECHO_LM(DB, "+-----------+"); ECHO_EM(" F | (-) N (+) | G");
ECHO_EM(" T | | H");
ECHO_EM(" | (-) | T");
ECHO_EM(" | |");
ECHO_EM(" O-- FRONT --+");
ECHO_EM(" (0,0)");
float min_diff = 999; float min_diff = 999;
...@@ -3736,7 +3948,7 @@ inline void gcode_G28() { ...@@ -3736,7 +3948,7 @@ inline void gcode_G28() {
#else // !AUTO_BED_LEVELING_GRID #else // !AUTO_BED_LEVELING_GRID
if (debugLevel & DEBUG_INFO) ECHO_LM(INFO, "> 3-point Leveling"); if (DEBUGGING(INFO)) ECHO_LM(INFO, "> 3-point Leveling");
// Actions for each probe // Actions for each probe
ProbeAction p1, p2, p3; ProbeAction p1, p2, p3;
...@@ -3766,7 +3978,7 @@ inline void gcode_G28() { ...@@ -3766,7 +3978,7 @@ inline void gcode_G28() {
z_tmp = current_position[Z_AXIS], z_tmp = current_position[Z_AXIS],
real_z = st_get_axis_position_mm(Z_AXIS); //get the real Z (since plan_get_position is now correcting the plane) real_z = st_get_axis_position_mm(Z_AXIS); //get the real Z (since plan_get_position is now correcting the plane)
if (debugLevel & DEBUG_INFO) { if (DEBUGGING(INFO)) {
ECHO_LMV(INFO, "> BEFORE apply_rotation_xyz > z_tmp = ", z_tmp); ECHO_LMV(INFO, "> BEFORE apply_rotation_xyz > z_tmp = ", z_tmp);
ECHO_LMV(INFO, "> BEFORE apply_rotation_xyz > real_z = ", real_z); ECHO_LMV(INFO, "> BEFORE apply_rotation_xyz > real_z = ", real_z);
} }
...@@ -3789,7 +4001,7 @@ inline void gcode_G28() { ...@@ -3789,7 +4001,7 @@ inline void gcode_G28() {
// adjust for inaccurate endstops, not for reasonably accurate probes. If it were // adjust for inaccurate endstops, not for reasonably accurate probes. If it were
// added here, it could be seen as a compensating factor for the Z probe. // added here, it could be seen as a compensating factor for the Z probe.
// //
if (debugLevel & DEBUG_INFO) if (DEBUGGING(INFO))
ECHO_LMV(INFO, "> AFTER apply_rotation_xyz > z_tmp = ", z_tmp); ECHO_LMV(INFO, "> AFTER apply_rotation_xyz > z_tmp = ", z_tmp);
current_position[Z_AXIS] = -zprobe_zoffset + (z_tmp - real_z) current_position[Z_AXIS] = -zprobe_zoffset + (z_tmp - real_z)
...@@ -3800,7 +4012,7 @@ inline void gcode_G28() { ...@@ -3800,7 +4012,7 @@ inline void gcode_G28() {
// current_position[Z_AXIS] += home_offset[Z_AXIS]; // The Z probe determines Z=0, not "Z home" // current_position[Z_AXIS] += home_offset[Z_AXIS]; // The Z probe determines Z=0, not "Z home"
sync_plan_position(); sync_plan_position();
if (debugLevel & DEBUG_INFO) if (DEBUGGING(INFO))
print_xyz("> corrected Z in G29", current_position); print_xyz("> corrected Z in G29", current_position);
} }
...@@ -3813,15 +4025,17 @@ inline void gcode_G28() { ...@@ -3813,15 +4025,17 @@ inline void gcode_G28() {
#endif #endif
#if ENABLED(Z_PROBE_END_SCRIPT) #if ENABLED(Z_PROBE_END_SCRIPT)
if (debugLevel & DEBUG_INFO) { if (DEBUGGING(INFO)) {
ECHO_SM(INFO, "Z Probe End Script: "); ECHO_SM(INFO, "Z Probe End Script: ");
ECHO_EM(Z_PROBE_END_SCRIPT); ECHO_EM(Z_PROBE_END_SCRIPT);
} }
enqueuecommands_P(PSTR(Z_PROBE_END_SCRIPT)); enqueue_and_echo_commands_P(PSTR(Z_PROBE_END_SCRIPT));
st_synchronize(); st_synchronize();
#endif #endif
if (debugLevel & DEBUG_INFO) ECHO_LM(INFO, "<<< gcode_G29"); KEEPALIVE_STATE(IN_HANDLER);
if (DEBUGGING(INFO)) ECHO_LM(INFO, "<<< gcode_G29");
} }
#if HASNT(Z_PROBE_SLED) #if HASNT(Z_PROBE_SLED)
...@@ -3829,7 +4043,7 @@ inline void gcode_G28() { ...@@ -3829,7 +4043,7 @@ inline void gcode_G28() {
* G30: Do a single Z probe at the current XY * G30: Do a single Z probe at the current XY
*/ */
inline void gcode_G30() { inline void gcode_G30() {
if (debugLevel & DEBUG_INFO) ECHO_LM(INFO, "gcode_G30 >>>"); if (DEBUGGING(INFO)) ECHO_LM(INFO, "gcode_G30 >>>");
#if HAS(SERVO_ENDSTOPS) #if HAS(SERVO_ENDSTOPS)
raise_z_for_servo(); raise_z_for_servo();
...@@ -3857,7 +4071,7 @@ inline void gcode_G28() { ...@@ -3857,7 +4071,7 @@ inline void gcode_G28() {
stow_z_probe(); // Retract Z Servo endstop if available stow_z_probe(); // Retract Z Servo endstop if available
if (debugLevel & DEBUG_INFO) ECHO_LM(INFO, "<<< gcode_G30"); if (DEBUGGING(INFO)) ECHO_LM(INFO, "<<< gcode_G30");
} }
#endif // !Z_PROBE_SLED #endif // !Z_PROBE_SLED
#endif // AUTO_BED_LEVELING_FEATURE #endif // AUTO_BED_LEVELING_FEATURE
...@@ -3869,7 +4083,7 @@ inline void gcode_G28() { ...@@ -3869,7 +4083,7 @@ inline void gcode_G28() {
*/ */
inline void gcode_G29() { inline void gcode_G29() {
if (debugLevel & DEBUG_INFO) ECHO_LM(INFO, "gcode_G29 >>>"); if (DEBUGGING(INFO)) ECHO_LM(INFO, "gcode_G29 >>>");
if (code_seen('D')) { if (code_seen('D')) {
print_bed_level(); print_bed_level();
...@@ -3886,7 +4100,9 @@ inline void gcode_G28() { ...@@ -3886,7 +4100,9 @@ inline void gcode_G28() {
retract_z_probe(); retract_z_probe();
clean_up_after_endstop_move(); clean_up_after_endstop_move();
if (debugLevel & DEBUG_INFO) ECHO_LM(INFO, "<<< gcode_G29"); KEEPALIVE_STATE(IN_HANDLER);
if (DEBUGGING(INFO)) ECHO_LM(INFO, "<<< gcode_G29");
} }
/* G30: Delta AutoCalibration /* G30: Delta AutoCalibration
...@@ -3896,7 +4112,7 @@ inline void gcode_G28() { ...@@ -3896,7 +4112,7 @@ inline void gcode_G28() {
* *
*/ */
inline void gcode_G30() { inline void gcode_G30() {
if (debugLevel & DEBUG_INFO) ECHO_LM(INFO, "gcode_G30 >>>"); if (DEBUGGING(INFO)) ECHO_LM(INFO, "gcode_G30 >>>");
// Zero the bed level array // Zero the bed level array
reset_bed_level(); reset_bed_level();
...@@ -3925,7 +4141,7 @@ inline void gcode_G28() { ...@@ -3925,7 +4141,7 @@ inline void gcode_G28() {
ECHO_MV(" Y:", y); ECHO_MV(" Y:", y);
ECHO_EMV(" = ", probe_value, 4); ECHO_EMV(" = ", probe_value, 4);
if (debugLevel & DEBUG_INFO) { if (DEBUGGING(INFO)) {
ECHO_SMV(INFO, "Carriage Positions: [", saved_position[X_AXIS]); ECHO_SMV(INFO, "Carriage Positions: [", saved_position[X_AXIS]);
ECHO_MV(", ", saved_position[Y_AXIS]); ECHO_MV(", ", saved_position[Y_AXIS]);
ECHO_MV(", ", saved_position[Z_AXIS]); ECHO_MV(", ", saved_position[Z_AXIS]);
...@@ -4036,7 +4252,7 @@ inline void gcode_G28() { ...@@ -4036,7 +4252,7 @@ inline void gcode_G28() {
else else
dr_adjusted = false; dr_adjusted = false;
if (debugLevel & DEBUG_DEBUG) { if (DEBUGGING(DEBUG)) {
ECHO_LMV(DEB, "bed_level_c=", bed_level_c, 4); ECHO_LMV(DEB, "bed_level_c=", bed_level_c, 4);
ECHO_LMV(DEB, "bed_level_x=", bed_level_x, 4); ECHO_LMV(DEB, "bed_level_x=", bed_level_x, 4);
ECHO_LMV(DEB, "bed_level_y=", bed_level_y, 4); ECHO_LMV(DEB, "bed_level_y=", bed_level_y, 4);
...@@ -4074,7 +4290,7 @@ inline void gcode_G28() { ...@@ -4074,7 +4290,7 @@ inline void gcode_G28() {
calibration_report(); calibration_report();
} }
if (debugLevel & DEBUG_DEBUG) { if (DEBUGGING(DEBUG)) {
ECHO_LMV(DEB, "bed_level_c=", bed_level_c, 4); ECHO_LMV(DEB, "bed_level_c=", bed_level_c, 4);
ECHO_LMV(DEB, "bed_level_x=", bed_level_x, 4); ECHO_LMV(DEB, "bed_level_x=", bed_level_x, 4);
ECHO_LMV(DEB, "bed_level_y=", bed_level_y, 4); ECHO_LMV(DEB, "bed_level_y=", bed_level_y, 4);
...@@ -4101,7 +4317,9 @@ inline void gcode_G28() { ...@@ -4101,7 +4317,9 @@ inline void gcode_G28() {
clean_up_after_endstop_move(); clean_up_after_endstop_move();
if (debugLevel & DEBUG_INFO) ECHO_LM(INFO, "<<< gcode_G30"); KEEPALIVE_STATE(IN_HANDLER);
if (DEBUGGING(INFO)) ECHO_LM(INFO, "<<< gcode_G30");
} }
#endif // DELTA && Z_PROBE_ENDSTOP #endif // DELTA && Z_PROBE_ENDSTOP
...@@ -4230,13 +4448,17 @@ inline void gcode_G92() { ...@@ -4230,13 +4448,17 @@ inline void gcode_G92() {
st_synchronize(); st_synchronize();
refresh_cmd_timeout(); refresh_cmd_timeout();
if (codenum > 0) { if (codenum > 0) {
codenum += previous_cmd_ms; // keep track of when we started waiting codenum += previous_cmd_ms; // wait until this time for a click
while(millis() < codenum && !lcd_clicked()) idle(); KEEPALIVE_STATE(PAUSED_FOR_USER);
while (PENDING(millis(), codenum) && !lcd_clicked()) idle();
KEEPALIVE_STATE(IN_HANDLER);
lcd_ignore_click(false); lcd_ignore_click(false);
} }
else { else {
if (!lcd_detected()) return; if (!lcd_detected()) return;
KEEPALIVE_STATE(PAUSED_FOR_USER);
while (!lcd_clicked()) idle(); while (!lcd_clicked()) idle();
KEEPALIVE_STATE(IN_HANDLER);
} }
if (IS_SD_PRINTING) if (IS_SD_PRINTING)
LCD_MESSAGEPGM(MSG_RESUMING); LCD_MESSAGEPGM(MSG_RESUMING);
...@@ -4283,7 +4505,7 @@ inline void gcode_M11() { ...@@ -4283,7 +4505,7 @@ inline void gcode_M11() {
Printing = false; Printing = false;
ECHO_LM(DB, "Stop Printing"); ECHO_LM(DB, "Stop Printing");
#if ENABLED(STOP_GCODE) #if ENABLED(STOP_GCODE)
enqueuecommands_P(PSTR(STOP_PRINTING_SCRIPT)); enqueue_and_echo_commands_P(PSTR(STOP_PRINTING_SCRIPT));
#endif #endif
#if HAS(FILRUNOUT) #if HAS(FILRUNOUT)
filrunoutEnqueued = false; filrunoutEnqueued = false;
...@@ -4294,7 +4516,7 @@ inline void gcode_M11() { ...@@ -4294,7 +4516,7 @@ inline void gcode_M11() {
Printing = true; Printing = true;
ECHO_LM(DB, "Start Printing"); ECHO_LM(DB, "Start Printing");
#if ENABLED(START_GCODE) #if ENABLED(START_GCODE)
enqueuecommands_P(PSTR(START_PRINTING_SCRIPT)); enqueue_and_echo_commands_P(PSTR(START_PRINTING_SCRIPT));
#endif #endif
#if HAS(FILRUNOUT) #if HAS(FILRUNOUT)
filrunoutEnqueued = false; filrunoutEnqueued = false;
...@@ -4353,7 +4575,7 @@ inline void gcode_M17() { ...@@ -4353,7 +4575,7 @@ inline void gcode_M17() {
*/ */
inline void gcode_M24() { inline void gcode_M24() {
card.startPrint(); card.startPrint();
print_job_start_ms = millis(); print_job_timer.start();
#if HAS(POWER_CONSUMPTION_SENSOR) #if HAS(POWER_CONSUMPTION_SENSOR)
startpower = power_consumption_hour; startpower = power_consumption_hour;
#endif #endif
...@@ -4410,8 +4632,7 @@ inline void gcode_M17() { ...@@ -4410,8 +4632,7 @@ inline void gcode_M17() {
* M31: Get the time since the start of SD Print (or last M109) * M31: Get the time since the start of SD Print (or last M109)
*/ */
inline void gcode_M31() { inline void gcode_M31() {
print_job_stop_ms = millis(); millis_t t = print_job_timer.duration();
millis_t t = (print_job_stop_ms - print_job_start_ms) / 1000;
int min = t / 60, sec = t % 60; int min = t / 60, sec = t % 60;
char time[30]; char time[30];
sprintf_P(time, PSTR("%i min, %i sec"), min, sec); sprintf_P(time, PSTR("%i min, %i sec"), min, sec);
...@@ -4489,7 +4710,7 @@ inline void gcode_M42() { ...@@ -4489,7 +4710,7 @@ inline void gcode_M42() {
* regenerated. * regenerated.
*/ */
inline void gcode_M48() { inline void gcode_M48() {
if (debugLevel & DEBUG_INFO) ECHO_LM(INFO, "gcode_M48 >>>"); if (DEBUGGING(INFO)) ECHO_LM(INFO, "gcode_M48 >>>");
double sum = 0.0, mean = 0.0, sigma = 0.0, sample_set[50]; double sum = 0.0, mean = 0.0, sigma = 0.0, sample_set[50];
uint8_t verbose_level = 1, n_samples = 10, n_legs = 0; uint8_t verbose_level = 1, n_samples = 10, n_legs = 0;
...@@ -4687,13 +4908,12 @@ inline void gcode_M42() { ...@@ -4687,13 +4908,12 @@ inline void gcode_M42() {
if (verbose_level > 0) ECHO_EMV("Mean: ", mean, 6); if (verbose_level > 0) ECHO_EMV("Mean: ", mean, 6);
ECHO_EMV("Standard Deviation: ", sigma, 6); ECHO_EMV("Standard Deviation: ", sigma, 6);
if (debugLevel & DEBUG_INFO) ECHO_LM(INFO, "<<< gcode_M28"); if (DEBUGGING(INFO)) ECHO_LM(INFO, "<<< gcode_M28");
} }
#endif // AUTO_BED_LEVELING_FEATURE && Z_PROBE_REPEATABILITY_TEST #endif // AUTO_BED_LEVELING_FEATURE && Z_PROBE_REPEATABILITY_TEST
#if HAS(POWER_CONSUMPTION_SENSOR) #if HAS(POWER_CONSUMPTION_SENSOR)
/** /**
* M70 - Power consumption sensor calibration * M70 - Power consumption sensor calibration
* *
...@@ -4720,6 +4940,27 @@ inline void gcode_M42() { ...@@ -4720,6 +4940,27 @@ inline void gcode_M42() {
} }
#endif #endif
/**
* M75: Start print timer
*/
inline void gcode_M75() {
print_job_timer.start();
}
/**
* M76: Pause print timer
*/
inline void gcode_M76() {
print_job_timer.pause();
}
/**
* M77: Stop print timer
*/
inline void gcode_M77() {
print_job_timer.stop();
}
#if HAS(POWER_SWITCH) #if HAS(POWER_SWITCH)
/** /**
* M80: Turn on Power Supply * M80: Turn on Power Supply
...@@ -5062,7 +5303,7 @@ inline void gcode_M92() { ...@@ -5062,7 +5303,7 @@ inline void gcode_M92() {
*/ */
inline void gcode_M104() { inline void gcode_M104() {
if (setTargetedExtruder(104)) return; if (setTargetedExtruder(104)) return;
if (debugLevel & DEBUG_DRYRUN) return; if (DEBUGGING(DRYRUN)) return;
#if HOTENDS == 1 #if HOTENDS == 1
if (target_extruder != active_extruder) return; if (target_extruder != active_extruder) return;
...@@ -5113,7 +5354,7 @@ inline void gcode_M105() { ...@@ -5113,7 +5354,7 @@ inline void gcode_M105() {
*/ */
inline void gcode_M109() { inline void gcode_M109() {
if (setTargetedExtruder(109)) return; if (setTargetedExtruder(109)) return;
if (debugLevel & DEBUG_DRYRUN) return; if (DEBUGGING(DRYRUN)) return;
#if HOTENDS == 1 #if HOTENDS == 1
if (target_extruder != active_extruder) return; if (target_extruder != active_extruder) return;
...@@ -5129,6 +5370,24 @@ inline void gcode_M109() { ...@@ -5129,6 +5370,24 @@ inline void gcode_M109() {
if (dual_x_carriage_mode == DXC_DUPLICATION_MODE && target_extruder == 0) if (dual_x_carriage_mode == DXC_DUPLICATION_MODE && target_extruder == 0)
setTargetHotend1(temp == 0.0 ? 0.0 : temp + duplicate_extruder_temp_offset); setTargetHotend1(temp == 0.0 ? 0.0 : temp + duplicate_extruder_temp_offset);
#endif #endif
/**
* We use half EXTRUDE_MINTEMP here to allow nozzles to be put into hot
* stand by mode, for instance in a dual extruder setup, without affecting
* the running print timer.
*/
if (temp <= (EXTRUDE_MINTEMP)/2) {
print_job_timer.stop();
LCD_MESSAGEPGM(WELCOME_MSG);
}
/**
* We do not check if the timer is already running because this check will
* be done for us inside the Stopwatch::start() method thus a running timer
* will not restart.
*/
else print_job_timer.start();
if (temp > degHotend(target_extruder)) LCD_MESSAGEPGM(MSG_HEATING);
} }
#if ENABLED(AUTOTEMP) #if ENABLED(AUTOTEMP)
...@@ -5145,16 +5404,16 @@ inline void gcode_M109() { ...@@ -5145,16 +5404,16 @@ inline void gcode_M109() {
* M111: Debug mode Repetier Host compatibile * M111: Debug mode Repetier Host compatibile
*/ */
inline void gcode_M111() { inline void gcode_M111() {
debugLevel = code_seen('S') ? code_value_short() : DEBUG_INFO|DEBUG_COMMUNICATION; mk_debug_flags = code_seen('S') ? code_value_short() : DEBUG_INFO|DEBUG_COMMUNICATION;
if (debugLevel & DEBUG_ECHO) ECHO_LM(DB, SERIAL_DEBUG_ECHO); if (DEBUGGING(ECHO)) ECHO_LM(DB, SERIAL_DEBUG_ECHO);
if (debugLevel & DEBUG_INFO) ECHO_LM(DB, SERIAL_DEBUG_INFO); if (DEBUGGING(INFO)) ECHO_LM(DB, SERIAL_DEBUG_INFO);
//if (debugLevel & DEBUG_ERRORS) ECHO_LM(DB, SERIAL_DEBUG_ERRORS); //if (mk_debug_flags & DEBUG_ERRORS) ECHO_LM(DB, SERIAL_DEBUG_ERRORS);
if (debugLevel & DEBUG_DRYRUN) { if (DEBUGGING(DRYRUN)) {
ECHO_LM(DB, SERIAL_DEBUG_DRYRUN); ECHO_LM(DB, SERIAL_DEBUG_DRYRUN);
disable_all_heaters(); disable_all_heaters();
} }
if (debugLevel & DEBUG_DEBUG) ECHO_LM(DB, SERIAL_DEBUG); if (DEBUGGING(DEBUG)) ECHO_LM(DB, SERIAL_DEBUG);
} }
/** /**
...@@ -5162,6 +5421,23 @@ inline void gcode_M111() { ...@@ -5162,6 +5421,23 @@ inline void gcode_M111() {
*/ */
inline void gcode_M112() { kill(PSTR(MSG_KILLED)); } inline void gcode_M112() { kill(PSTR(MSG_KILLED)); }
#if ENABLED(HOST_KEEPALIVE_FEATURE)
/**
* M113: Get or set Host Keepalive interval (0 to disable)
*
* S<seconds> Optional. Set the keepalive interval.
*/
inline void gcode_M113() {
if (code_seen('S')) {
host_keepalive_interval = (uint8_t)code_value_short();
NOMORE(host_keepalive_interval, 60);
}
else {
ECHO_LMV(DB, "M113 S", (unsigned long)host_keepalive_interval);
}
}
#endif
/** /**
* M114: Output current position to serial port * M114: Output current position to serial port
*/ */
...@@ -5304,22 +5580,22 @@ inline void gcode_M122() { ...@@ -5304,22 +5580,22 @@ inline void gcode_M122() {
/** /**
* M126: Heater 1 valve open * M126: Heater 1 valve open
*/ */
inline void gcode_M126() { ValvePressure = code_seen('S') ? constrain(code_value(), 0, 255) : 255; } inline void gcode_M126() { baricuda_valve_pressure = code_seen('S') ? constrain(code_value(), 0, 255) : 255; }
/** /**
* M127: Heater 1 valve close * M127: Heater 1 valve close
*/ */
inline void gcode_M127() { ValvePressure = 0; } inline void gcode_M127() { baricuda_valve_pressure = 0; }
#endif #endif
#if HAS(HEATER_2) #if HAS(HEATER_2)
/** /**
* M128: Heater 2 valve open * M128: Heater 2 valve open
*/ */
inline void gcode_M128() { EtoPPressure = code_seen('S') ? constrain(code_value(), 0, 255) : 255; } inline void gcode_M128() { baricuda_e_to_p_pressure = code_seen('S') ? constrain(code_value(), 0, 255) : 255; }
/** /**
* M129: Heater 2 valve close * M129: Heater 2 valve close
*/ */
inline void gcode_M129() { EtoPPressure = 0; } inline void gcode_M129() { baricuda_e_to_p_pressure = 0; }
#endif #endif
#endif //BARICUDA #endif //BARICUDA
...@@ -5327,7 +5603,7 @@ inline void gcode_M122() { ...@@ -5327,7 +5603,7 @@ inline void gcode_M122() {
* M140: Set bed temperature * M140: Set bed temperature
*/ */
inline void gcode_M140() { inline void gcode_M140() {
if (debugLevel & DEBUG_DRYRUN) return; if (DEBUGGING(DRYRUN)) return;
if (code_seen('S')) setTargetBed(code_value()); if (code_seen('S')) setTargetBed(code_value());
} }
...@@ -5481,12 +5757,11 @@ inline void gcode_M140() { ...@@ -5481,12 +5757,11 @@ inline void gcode_M140() {
* Rxxx Wait for bed current temp to reach target temp. Waits when heating and cooling * Rxxx Wait for bed current temp to reach target temp. Waits when heating and cooling
*/ */
inline void gcode_M190() { inline void gcode_M190() {
if (debugLevel & DEBUG_DRYRUN) return; if (DEBUGGING(DRYRUN)) return;
LCD_MESSAGEPGM(MSG_BED_HEATING); LCD_MESSAGEPGM(MSG_BED_HEATING);
no_wait_for_cooling = code_seen('S'); no_wait_for_cooling = code_seen('S');
if (no_wait_for_cooling || code_seen('R')) if (no_wait_for_cooling || code_seen('R')) setTargetBed(code_value());
setTargetBed(code_value());
wait_bed(); wait_bed();
} }
...@@ -5919,7 +6194,7 @@ inline void gcode_M226() { ...@@ -5919,7 +6194,7 @@ inline void gcode_M226() {
#endif #endif
updatePID(); updatePID();
ECHO_SMV(OK, "H:", h); ECHO_SMV(DB, "H:", h);
ECHO_MV(" p:", PID_PARAM(Kp, h)); ECHO_MV(" p:", PID_PARAM(Kp, h));
ECHO_MV(" i:", unscalePID_i(PID_PARAM(Ki, h))); ECHO_MV(" i:", unscalePID_i(PID_PARAM(Ki, h)));
ECHO_MV(" d:", unscalePID_d(PID_PARAM(Kd, h))); ECHO_MV(" d:", unscalePID_d(PID_PARAM(Kd, h)));
...@@ -5957,7 +6232,12 @@ inline void gcode_M226() { ...@@ -5957,7 +6232,12 @@ inline void gcode_M226() {
int c = code_seen('C') ? code_value_short() : 5; int c = code_seen('C') ? code_value_short() : 5;
float temp = code_seen('S') ? code_value() : (h < 0 ? 70.0 : 150.0); float temp = code_seen('S') ? code_value() : (h < 0 ? 70.0 : 150.0);
if (h >= 0 && h < HOTENDS) target_extruder = h; if (h >= 0 && h < HOTENDS) target_extruder = h;
KEEPALIVE_STATE(NOT_BUSY); // don't send "busy: processing" messages during autotune output
PID_autotune(temp, h, c); PID_autotune(temp, h, c);
KEEPALIVE_STATE(IN_HANDLER);
} }
#endif #endif
...@@ -5969,7 +6249,7 @@ inline void gcode_M226() { ...@@ -5969,7 +6249,7 @@ inline void gcode_M226() {
if (code_seen('D')) bedKd = scalePID_d(code_value()); if (code_seen('D')) bedKd = scalePID_d(code_value());
updatePID(); updatePID();
ECHO_SMV(OK, "p:", bedKp); ECHO_SMV(DB, "p:", bedKp);
ECHO_MV(" i:", unscalePID_i(bedKi)); ECHO_MV(" i:", unscalePID_i(bedKi));
ECHO_EMV(" d:", unscalePID_d(bedKd)); ECHO_EMV(" d:", unscalePID_d(bedKd));
} }
...@@ -6025,7 +6305,7 @@ inline void gcode_M226() { ...@@ -6025,7 +6305,7 @@ inline void gcode_M226() {
* M360: SCARA calibration: Move to cal-position ThetaA (0 deg calibration) * M360: SCARA calibration: Move to cal-position ThetaA (0 deg calibration)
*/ */
inline bool gcode_M360() { inline bool gcode_M360() {
ECHO_LM(DB, " Cal: Theta 0 "); ECHO_LM(DB, "Cal: Theta 0 ");
return SCARA_move_to_cal(0, 120); return SCARA_move_to_cal(0, 120);
} }
...@@ -6033,7 +6313,7 @@ inline void gcode_M226() { ...@@ -6033,7 +6313,7 @@ inline void gcode_M226() {
* M361: SCARA calibration: Move to cal-position ThetaB (90 deg calibration - steps per degree) * M361: SCARA calibration: Move to cal-position ThetaB (90 deg calibration - steps per degree)
*/ */
inline bool gcode_M361() { inline bool gcode_M361() {
ECHO_LM(DB, " Cal: Theta 90 "); ECHO_LM(DB, "Cal: Theta 90 ");
return SCARA_move_to_cal(90, 130); return SCARA_move_to_cal(90, 130);
} }
...@@ -6041,7 +6321,7 @@ inline void gcode_M226() { ...@@ -6041,7 +6321,7 @@ inline void gcode_M226() {
* M362: SCARA calibration: Move to cal-position PsiA (0 deg calibration) * M362: SCARA calibration: Move to cal-position PsiA (0 deg calibration)
*/ */
inline bool gcode_M362() { inline bool gcode_M362() {
ECHO_LM(DB, " Cal: Psi 0 "); ECHO_LM(DB, "Cal: Psi 0 ");
return SCARA_move_to_cal(60, 180); return SCARA_move_to_cal(60, 180);
} }
...@@ -6049,7 +6329,7 @@ inline void gcode_M226() { ...@@ -6049,7 +6329,7 @@ inline void gcode_M226() {
* M363: SCARA calibration: Move to cal-position PsiB (90 deg calibration - steps per degree) * M363: SCARA calibration: Move to cal-position PsiB (90 deg calibration - steps per degree)
*/ */
inline bool gcode_M363() { inline bool gcode_M363() {
ECHO_LM(DB," Cal: Psi 90 "); ECHO_LM(DB,"Cal: Psi 90 ");
return SCARA_move_to_cal(50, 90); return SCARA_move_to_cal(50, 90);
} }
...@@ -6057,7 +6337,7 @@ inline void gcode_M226() { ...@@ -6057,7 +6337,7 @@ inline void gcode_M226() {
* M364: SCARA calibration: Move to cal-position PSIC (90 deg to Theta calibration position) * M364: SCARA calibration: Move to cal-position PSIC (90 deg to Theta calibration position)
*/ */
inline bool gcode_M364() { inline bool gcode_M364() {
ECHO_LM(DB, " Cal: Theta-Psi 90 "); ECHO_LM(DB, "Cal: Theta-Psi 90 ");
return SCARA_move_to_cal(45, 135); return SCARA_move_to_cal(45, 135);
} }
...@@ -6496,7 +6776,7 @@ inline void gcode_M428() { ...@@ -6496,7 +6776,7 @@ inline void gcode_M428() {
ECHO_LM(ER, SERIAL_ERR_M428_TOO_FAR); ECHO_LM(ER, SERIAL_ERR_M428_TOO_FAR);
LCD_ALERTMESSAGEPGM("Err: Too far!"); LCD_ALERTMESSAGEPGM("Err: Too far!");
#if HAS(BUZZER) #if HAS(BUZZER)
enqueuecommands_P(PSTR("M300 S40 P200")); enqueue_and_echo_commands_P(PSTR("M300 S40 P200"));
#endif #endif
err = true; err = true;
break; break;
...@@ -6515,7 +6795,7 @@ inline void gcode_M428() { ...@@ -6515,7 +6795,7 @@ inline void gcode_M428() {
ECHO_LM(DB, "Offset applied."); ECHO_LM(DB, "Offset applied.");
LCD_MESSAGEPGM("Offset applied."); LCD_MESSAGEPGM("Offset applied.");
#if HAS(BUZZER) #if HAS(BUZZER)
enqueuecommands_P(PSTR("M300 S659 P200\nM300 S698 P200")); enqueue_and_echo_commands_P(PSTR("M300 S659 P200\nM300 S698 P200"));
#endif #endif
} }
} }
...@@ -6695,9 +6975,10 @@ inline void gcode_M503() { ...@@ -6695,9 +6975,10 @@ inline void gcode_M503() {
millis_t last_set = millis(); millis_t last_set = millis();
PRESSBUTTON: PRESSBUTTON:
KEEPALIVE_STATE(PAUSED_FOR_USER);
LCD_ALERTMESSAGEPGM(MSG_FILAMENTCHANGE); LCD_ALERTMESSAGEPGM(MSG_FILAMENTCHANGE);
while (!lcd_clicked()) { while (!lcd_clicked()) {
idle(true); idle();
if ((millis() - last_set > 60000) && cnt <= FILAMENTCHANGE_PRINTEROFF) beep = true; if ((millis() - last_set > 60000) && cnt <= FILAMENTCHANGE_PRINTEROFF) beep = true;
if (cnt >= FILAMENTCHANGE_PRINTEROFF && !sleep) { if (cnt >= FILAMENTCHANGE_PRINTEROFF && !sleep) {
disable_all_heaters(); disable_all_heaters();
...@@ -6715,7 +6996,7 @@ inline void gcode_M503() { ...@@ -6715,7 +6996,7 @@ inline void gcode_M503() {
++cnt; ++cnt;
} }
} // while(!lcd_clicked) } // while(!lcd_clicked)
KEEPALIVE_STATE(IN_HANDLER);
lcd_quick_feedback(); // click sound feedback lcd_quick_feedback(); // click sound feedback
lcd_reset_alert_level(); //reset LCD alert message lcd_reset_alert_level(); //reset LCD alert message
...@@ -7303,7 +7584,7 @@ inline void gcode_T(uint8_t tmp_extruder) { ...@@ -7303,7 +7584,7 @@ inline void gcode_T(uint8_t tmp_extruder) {
void process_next_command() { void process_next_command() {
current_command = command_queue[cmd_queue_index_r]; current_command = command_queue[cmd_queue_index_r];
if ((debugLevel & DEBUG_ECHO)) { if (DEBUGGING(ECHO)) {
ECHO_LT(DB, current_command); ECHO_LT(DB, current_command);
} }
...@@ -7312,38 +7593,45 @@ void process_next_command() { ...@@ -7312,38 +7593,45 @@ void process_next_command() {
// - Bypass N[-0-9][0-9]*[ ]* // - Bypass N[-0-9][0-9]*[ ]*
// - Overwrite * with nul to mark the end // - Overwrite * with nul to mark the end
while (*current_command == ' ') ++current_command; while (*current_command == ' ') ++current_command;
if ((*current_command == 'N' || *current_command == 'n') && ((current_command[1] >= '0' && current_command[1] <= '9') || current_command[1] == '-')) { if (*current_command == 'N' && NUMERIC_SIGNED(current_command[1])) {
current_command += 2; // skip N[-0-9] current_command += 2; // skip N[-0-9]
while (*current_command >= '0' && *current_command <= '9') ++current_command; // skip [0-9]* while (NUMERIC(*current_command)) ++current_command; // skip [0-9]*
while (*current_command == ' ') ++current_command; // skip [ ]* while (*current_command == ' ') ++current_command; // skip [ ]*
} }
char* starpos = strchr(current_command, '*'); // * should always be the last parameter char* starpos = strchr(current_command, '*'); // * should always be the last parameter
if (starpos) while (*starpos == ' ' || *starpos == '*') *starpos-- = '\0'; // nullify '*' and ' ' if (starpos) while (*starpos == ' ' || *starpos == '*') *starpos-- = '\0'; // nullify '*' and ' '
char *cmd_ptr = current_command;
// Get the command code, which must be G, M, or T // Get the command code, which must be G, M, or T
char command_code = *current_command; char command_code = *cmd_ptr++;
// The code must have a numeric value // Skip spaces to get the numeric part
bool code_is_good = (current_command[1] >= '0' && current_command[1] <= '9'); while (*cmd_ptr == ' ') cmd_ptr++;
int codenum; // define ahead of goto uint16_t codenum = 0; // define ahead of goto
// Bail early if there's no code // Bail early if there's no code
bool code_is_good = NUMERIC(*cmd_ptr);
if (!code_is_good) goto ExitUnknownCommand; if (!code_is_good) goto ExitUnknownCommand;
// Args pointer optimizes code_seen, especially those taking XYZEF // Get and skip the code number
// This wastes a little cpu on commands that expect no arguments. do {
current_command_args = current_command; codenum = (codenum * 10) + (*cmd_ptr - '0');
while (*current_command_args && *current_command_args != ' ') ++current_command_args; cmd_ptr++;
while (*current_command_args == ' ') ++current_command_args; } while (NUMERIC(*cmd_ptr));
// Skip all spaces to get to the first argument, or nul
while (*cmd_ptr == ' ') cmd_ptr++;
// The command's arguments (if any) start here, for sure!
current_command_args = cmd_ptr;
// Interpret the code int KEEPALIVE_STATE(IN_HANDLER);
seen_pointer = current_command;
codenum = code_value_short();
// Handle a known G, M, or T // Handle a known G, M, or T
switch(command_code) { switch(command_code) {
case 'G': case 'g': switch (codenum) { case 'G': switch (codenum) {
// G0 -> G1 // G0 -> G1
case 0: case 0:
...@@ -7403,7 +7691,7 @@ void process_next_command() { ...@@ -7403,7 +7691,7 @@ void process_next_command() {
} }
break; break;
case 'M': case 'm': switch (codenum) { case 'M': switch (codenum) {
#if ENABLED(ULTIPANEL) #if ENABLED(ULTIPANEL)
case 0: // M0 - Unconditional stop - Wait for user button press on LCD case 0: // M0 - Unconditional stop - Wait for user button press on LCD
...@@ -7471,6 +7759,15 @@ void process_next_command() { ...@@ -7471,6 +7759,15 @@ void process_next_command() {
gcode_M70(); break; gcode_M70(); break;
#endif #endif
case 75: // Start print timer
gcode_M75(); break;
case 76: // Pause print timer
gcode_M76(); break;
case 77: // Stop print timer
gcode_M77(); break;
#if HAS(POWER_SWITCH) #if HAS(POWER_SWITCH)
case 80: // M80 - Turn on Power Supply case 80: // M80 - Turn on Power Supply
gcode_M80(); break; gcode_M80(); break;
...@@ -7511,8 +7808,11 @@ void process_next_command() { ...@@ -7511,8 +7808,11 @@ void process_next_command() {
case 104: // M104 case 104: // M104
gcode_M104(); break; gcode_M104(); break;
case 105: // M105 Read current temperature case 105: // M105 Read current temperature
gcode_M105(); return; // "ok" already printed gcode_M105();
KEEPALIVE_STATE(NOT_BUSY);
return; // "ok" already printed
#if HAS(FAN) #if HAS(FAN)
case 106: //M106 Fan On case 106: //M106 Fan On
...@@ -7523,13 +7823,23 @@ void process_next_command() { ...@@ -7523,13 +7823,23 @@ void process_next_command() {
case 109: // M109 Wait for temperature case 109: // M109 Wait for temperature
gcode_M109(); break; gcode_M109(); break;
case 110: break; // M110: Set line number - don't show "unknown command" case 110: break; // M110: Set line number - don't show "unknown command"
case 111: // M111 Set debug level case 111: // M111 Set debug level
gcode_M111(); break; gcode_M111(); break;
case 112: // M112 Emergency Stop case 112: // M112 Emergency Stop
gcode_M112(); break; gcode_M112(); break;
case 114: // M114 Report current position case 114: // M114 Report current position
gcode_M114(); break; gcode_M114(); break;
#if ENABLED(HOST_KEEPALIVE_FEATURE)
case 113: // M113: Set Host Keepalive interval
gcode_M113(); break;
#endif
case 115: // M115 Report capabilities case 115: // M115 Report capabilities
gcode_M115(); break; gcode_M115(); break;
...@@ -7783,13 +8093,15 @@ void process_next_command() { ...@@ -7783,13 +8093,15 @@ void process_next_command() {
} }
break; break;
case 'T': case 't': case 'T':
gcode_T(codenum); gcode_T(codenum);
break; break;
default: code_is_good = false; default: code_is_good = false;
} }
KEEPALIVE_STATE(NOT_BUSY);
ExitUnknownCommand: ExitUnknownCommand:
// Still unknown command? Throw an error // Still unknown command? Throw an error
...@@ -7802,18 +8114,22 @@ void FlushSerialRequestResend() { ...@@ -7802,18 +8114,22 @@ void FlushSerialRequestResend() {
//char command_queue[cmd_queue_index_r][100]="Resend:"; //char command_queue[cmd_queue_index_r][100]="Resend:";
MKSERIAL.flush(); MKSERIAL.flush();
ECHO_LV(RESEND, (long)(gcode_LastN + 1)); ECHO_LV(RESEND, (long)(gcode_LastN + 1));
ECHO_S(OK); ok_to_send();
} }
void ok_to_send() { void ok_to_send() {
refresh_cmd_timeout(); refresh_cmd_timeout();
#if ENABLED(SDSUPPORT) if (!send_ok[cmd_queue_index_r]) return;
if (fromsd[cmd_queue_index_r]) return;
#endif
ECHO_S(OK); ECHO_S(OK);
#if ENABLED(ADVANCED_OK) #if ENABLED(ADVANCED_OK)
ECHO_MV("N", gcode_LastN); char* p = command_queue[cmd_queue_index_r];
ECHO_MV(" P", (int(BLOCK_BUFFER_SIZE - movesplanned() - 1))); if (*p == 'N') {
ECHO_C(' ');
ECHO_C(*p++);
while (NUMERIC_SIGNED(*p))
ECHO_C(*p++);
}
ECHO_MV(" P", (int)(BLOCK_BUFFER_SIZE - movesplanned() - 1));
ECHO_MV(" B", BUFSIZE - commands_in_queue); ECHO_MV(" B", BUFSIZE - commands_in_queue);
#endif #endif
ECHO_E; ECHO_E;
...@@ -7843,7 +8159,7 @@ void clamp_to_software_endstops(float target[3]) { ...@@ -7843,7 +8159,7 @@ void clamp_to_software_endstops(float target[3]) {
FORCE_INLINE void prevent_dangerous_extrude(float &curr_e, float &dest_e) { FORCE_INLINE void prevent_dangerous_extrude(float &curr_e, float &dest_e) {
float de = dest_e - curr_e; float de = dest_e - curr_e;
if (debugLevel & DEBUG_DRYRUN) return; if (DEBUGGING(DRYRUN)) return;
if (de) { if (de) {
if (degHotend(active_extruder) < extrude_min_temp) { if (degHotend(active_extruder) < extrude_min_temp) {
curr_e = dest_e; // Behave as if the move really took place, but ignore E part curr_e = dest_e; // Behave as if the move really took place, but ignore E part
...@@ -7878,7 +8194,7 @@ void clamp_to_software_endstops(float target[3]) { ...@@ -7878,7 +8194,7 @@ void clamp_to_software_endstops(float target[3]) {
float seconds = 6000 * cartesian_mm / feedrate / feedrate_multiplier; float seconds = 6000 * cartesian_mm / feedrate / feedrate_multiplier;
int steps = max(1, int(DELTA_SEGMENTS_PER_SECOND * seconds)); int steps = max(1, int(DELTA_SEGMENTS_PER_SECOND * seconds));
if (debugLevel & DEBUG_DEBUG) { if (DEBUGGING(DEBUG)) {
ECHO_SMV(DEB, "mm=", cartesian_mm); ECHO_SMV(DEB, "mm=", cartesian_mm);
ECHO_MV(" seconds=", seconds); ECHO_MV(" seconds=", seconds);
ECHO_EMV(" steps=", steps); ECHO_EMV(" steps=", steps);
...@@ -7918,7 +8234,7 @@ void clamp_to_software_endstops(float target[3]) { ...@@ -7918,7 +8234,7 @@ void clamp_to_software_endstops(float target[3]) {
calculate_delta(target); calculate_delta(target);
adjust_delta(target); adjust_delta(target);
if (debugLevel & DEBUG_DEBUG) { if (DEBUGGING(DEBUG)) {
ECHO_LMV(DEB, "target[X_AXIS]=", target[X_AXIS]); ECHO_LMV(DEB, "target[X_AXIS]=", target[X_AXIS]);
ECHO_LMV(DEB, "target[Y_AXIS]=", target[Y_AXIS]); ECHO_LMV(DEB, "target[Y_AXIS]=", target[Y_AXIS]);
ECHO_LMV(DEB, "target[Z_AXIS]=", target[Z_AXIS]); ECHO_LMV(DEB, "target[Z_AXIS]=", target[Z_AXIS]);
...@@ -8309,9 +8625,18 @@ void plan_arc( ...@@ -8309,9 +8625,18 @@ void plan_arc(
/** /**
* Standard idle routine keeps the machine alive * Standard idle routine keeps the machine alive
*/ */
void idle(bool ignore_stepper_queue/*=false*/) { void idle(
#if ENABLED(FILAMENTCHANGEENABLE)
bool no_stepper_sleep/*=false*/
#endif
) {
manage_heater(); manage_heater();
manage_inactivity(ignore_stepper_queue); manage_inactivity(
#if ENABLED(FILAMENTCHANGEENABLE)
no_stepper_sleep
#endif
);
host_keepalive();
lcd_update(); lcd_update();
} }
...@@ -8336,13 +8661,14 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) { ...@@ -8336,13 +8661,14 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) {
filrunout(); filrunout();
#endif #endif
if (commands_in_queue < BUFSIZE - 1) get_command(); if (commands_in_queue < BUFSIZE - 1) get_available_commands();
millis_t ms = millis(); millis_t ms = millis();
if (max_inactive_time && ms > previous_cmd_ms + max_inactive_time) kill(PSTR(MSG_KILLED)); if (max_inactive_time && ELAPSED(ms, previous_cmd_ms + max_inactive_time)) kill(PSTR(MSG_KILLED));
if (stepper_inactive_time && ms > previous_cmd_ms + stepper_inactive_time && !ignore_stepper_queue && !blocks_queued()) { if (stepper_inactive_time && ELAPSED(ms, previous_cmd_ms + stepper_inactive_time)
&& !ignore_stepper_queue && !blocks_queued()) {
#if DISABLE_X == true #if DISABLE_X == true
disable_x(); disable_x();
#endif #endif
...@@ -8358,7 +8684,7 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) { ...@@ -8358,7 +8684,7 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) {
} }
#if HAS(CHDK) // Check if pin should be set to LOW after M240 set it to HIGH #if HAS(CHDK) // Check if pin should be set to LOW after M240 set it to HIGH
if (chdkActive && ms > chdkHigh + CHDK_DELAY) { if (chdkActive && PENDING(ms, chdkHigh + CHDK_DELAY)) {
chdkActive = false; chdkActive = false;
WRITE(CHDK_PIN, LOW); WRITE(CHDK_PIN, LOW);
} }
...@@ -8389,7 +8715,7 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) { ...@@ -8389,7 +8715,7 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) {
const int HOME_DEBOUNCE_DELAY = 750; const int HOME_DEBOUNCE_DELAY = 750;
if (!READ(HOME_PIN)) { if (!READ(HOME_PIN)) {
if (!homeDebounceCount) { if (!homeDebounceCount) {
enqueuecommands_P(PSTR("G28")); enqueue_and_echo_commands_P(PSTR("G28"));
LCD_MESSAGEPGM(MSG_AUTO_HOME); LCD_MESSAGEPGM(MSG_AUTO_HOME);
} }
if (homeDebounceCount < HOME_DEBOUNCE_DELAY) if (homeDebounceCount < HOME_DEBOUNCE_DELAY)
...@@ -8404,7 +8730,7 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) { ...@@ -8404,7 +8730,7 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) {
#endif #endif
#if ENABLED(EXTRUDER_RUNOUT_PREVENT) #if ENABLED(EXTRUDER_RUNOUT_PREVENT)
if (ms > previous_cmd_ms + (EXTRUDER_RUNOUT_SECONDS) * 1000) { if (ELAPSED(ms, previous_cmd_ms + (EXTRUDER_RUNOUT_SECONDS) * 1000UL))
if (degHotend(active_extruder) > EXTRUDER_RUNOUT_MINTEMP) { if (degHotend(active_extruder) > EXTRUDER_RUNOUT_MINTEMP) {
bool oldstatus; bool oldstatus;
switch(active_extruder) { switch(active_extruder) {
...@@ -8476,7 +8802,7 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) { ...@@ -8476,7 +8802,7 @@ void manage_inactivity(bool ignore_stepper_queue/*=false*/) {
#if ENABLED(IDLE_OOZING_PREVENT) #if ENABLED(IDLE_OOZING_PREVENT)
if (blocks_queued()) axis_last_activity = millis(); if (blocks_queued()) axis_last_activity = millis();
if (degHotend(active_extruder) > IDLE_OOZING_MINTEMP && !(debugLevel & DEBUG_DRYRUN) && IDLE_OOZING_enabled) { if (degHotend(active_extruder) > IDLE_OOZING_MINTEMP && !(DEBUGGING(DRYRUN)) && IDLE_OOZING_enabled) {
#if ENABLED(FILAMENTCHANGEENABLE) #if ENABLED(FILAMENTCHANGEENABLE)
if (!filament_changing) if (!filament_changing)
#endif #endif
...@@ -8579,7 +8905,7 @@ void kill(const char* lcd_msg) { ...@@ -8579,7 +8905,7 @@ void kill(const char* lcd_msg) {
void filrunout() { void filrunout() {
if (!filrunoutEnqueued) { if (!filrunoutEnqueued) {
filrunoutEnqueued = true; filrunoutEnqueued = true;
enqueuecommands_P(PSTR(FILAMENT_RUNOUT_SCRIPT)); enqueue_and_echo_commands_P(PSTR(FILAMENT_RUNOUT_SCRIPT));
st_synchronize(); st_synchronize();
} }
} }
...@@ -8653,7 +8979,7 @@ void kill(const char* lcd_msg) { ...@@ -8653,7 +8979,7 @@ void kill(const char* lcd_msg) {
} }
#endif // FAST_PWM_FAN #endif // FAST_PWM_FAN
void Stop() { void stop() {
disable_all_heaters(); disable_all_heaters();
if (IsRunning()) { if (IsRunning()) {
Running = false; Running = false;
...@@ -8664,32 +8990,6 @@ void Stop() { ...@@ -8664,32 +8990,6 @@ void Stop() {
} }
} }
bool setTargetedExtruder(int code) {
target_extruder = active_extruder;
if (code_seen('T')) {
target_extruder = code_value_short();
if (target_extruder >= EXTRUDERS) {
ECHO_SMV(ER, "M", code);
ECHO_EMV(" " SERIAL_INVALID_EXTRUDER, target_extruder);
return true;
}
}
return false;
}
bool setTargetedHotend(int code) {
target_extruder = active_extruder;
if (code_seen('H')) {
target_extruder = code_value_short();
if (target_extruder >= HOTENDS) {
ECHO_SMV(ER, "M", code);
ECHO_EMV(" " SERIAL_INVALID_HOTEND, target_extruder);
return true;
}
}
return false;
}
float calculate_volumetric_multiplier(float diameter) { float calculate_volumetric_multiplier(float diameter) {
if (!volumetric_enabled || diameter == 0) return 1.0; if (!volumetric_enabled || diameter == 0) return 1.0;
float d2 = diameter * 0.5; float d2 = diameter * 0.5;
......
...@@ -9,16 +9,17 @@ ...@@ -9,16 +9,17 @@
void get_command(); void get_command();
void idle(bool ignore_stepper_queue = false); void idle(
#if ENABLED(FILAMENTCHANGEENABLE)
bool no_stepper_sleep=false // pass true to keep steppers from disabling on timeout
#endif
);
void manage_inactivity(bool ignore_stepper_queue = false); void manage_inactivity(bool ignore_stepper_queue = false);
void FlushSerialRequestResend(); void FlushSerialRequestResend();
void ok_to_send(); void ok_to_send();
bool setTargetedExtruder(int code);
bool setTargetedHotend(int code);
#if MECH(DELTA) #if MECH(DELTA)
float probe_bed(float x, float y); float probe_bed(float x, float y);
void set_delta_constants(); void set_delta_constants();
...@@ -63,25 +64,27 @@ void Stop(); ...@@ -63,25 +64,27 @@ void Stop();
* Debug flags - with repetier * Debug flags - with repetier
*/ */
enum DebugFlags { enum DebugFlags {
DEBUG_ECHO = _BV(0), DEBUG_NONE = 0,
DEBUG_INFO = _BV(1), DEBUG_ECHO = _BV(0), ///< Echo commands in order as they are processed
DEBUG_ERRORS = _BV(2), DEBUG_INFO = _BV(1), ///< Print messages for code that has debug output
DEBUG_DRYRUN = _BV(3), DEBUG_ERRORS = _BV(2), ///< Not implemented
DEBUG_COMMUNICATION = _BV(4), DEBUG_DRYRUN = _BV(3), ///< Ignore temperature setting
DEBUG_DEBUG = _BV(5) DEBUG_COMMUNICATION = _BV(4), ///< Not implemented
DEBUG_DEBUG = _BV(5) ///< Print Debug
}; };
extern uint8_t mk_debug_flags;
#define DEBUGGING(F) (mk_debug_flags & (DEBUG_## F))
void clamp_to_software_endstops(float target[3]); void clamp_to_software_endstops(float target[3]);
extern uint8_t debugLevel;
extern bool Running; extern bool Running;
inline bool IsRunning() { return Running; } inline bool IsRunning() { return Running; }
inline bool IsStopped() { return !Running; } inline bool IsStopped() { return !Running; }
extern bool Printing; extern bool Printing;
bool enqueuecommand(const char *cmd); //put a single ASCII command at the end of the current buffer or return false when it is full bool enqueue_and_echo_command(const char* cmd, bool say_ok = false); // put a single ASCII command at the end of the current buffer or return false when it is full
void enqueuecommands_P(const char *cmd); //put one or many ASCII commands at the end of the current buffer, read from flash void enqueue_and_echo_command_now(const char* cmd); // enqueue now, only return when the command has been enqueued
void enqueue_and_echo_commands_P(const char* cmd); // put one or many ASCII commands at the end of the current buffer, read from flash
void prepare_arc_move(char isclockwise); void prepare_arc_move(char isclockwise);
void clamp_to_software_endstops(float target[3]); void clamp_to_software_endstops(float target[3]);
...@@ -139,11 +142,15 @@ extern double printer_usage_filament; ...@@ -139,11 +142,15 @@ extern double printer_usage_filament;
extern float extrude_min_temp; extern float extrude_min_temp;
#endif #endif
#if ENABLED(HOST_KEEPALIVE_FEATURE)
extern uint8_t host_keepalive_interval;
#endif
extern int fanSpeed; extern int fanSpeed;
#if ENABLED(BARICUDA) #if ENABLED(BARICUDA)
extern int ValvePressure; extern int baricuda_valve_pressure;
extern int EtoPPressure; extern int baricuda_e_to_p_pressure;
#endif #endif
#if ENABLED(FAN_SOFT_PWM) #if ENABLED(FAN_SOFT_PWM)
...@@ -202,8 +209,8 @@ extern int fanSpeed; ...@@ -202,8 +209,8 @@ extern int fanSpeed;
extern bool config_readed; extern bool config_readed;
#endif #endif
extern millis_t print_job_start_ms; // Print job timer
extern millis_t print_job_stop_ms; extern Stopwatch print_job_timer;
// Handling multiple extruders pins // Handling multiple extruders pins
extern uint8_t active_extruder; extern uint8_t active_extruder;
......
...@@ -2,15 +2,16 @@ ...@@ -2,15 +2,16 @@
#define COMMUNICATION_H #define COMMUNICATION_H
#define START "start" // start for host #define START "start" // start for host
#define OK "ok " // ok answer for host #define OK "ok" // ok answer for host
#define ER "Error: " // error for host #define ER "Error:" // error for host
#define WT "Wait" // wait for host #define WT "wait" // wait for host
#define DB "Echo: " // message for user #define DB "Echo:" // message for user
#define DEB "Debug: " // message for debug #define DEB "Debug:" // message for debug
#define CFG "Config: " // config for host #define CFG "Config:" // config for host
#define INFO "Info: " // info for host #define INFO "Info:" // info for host
#define RESEND "Resend: " // resend for host #define BUSY "busy:" // buys for host
#define WARNING "Warning: " // warning for host #define RESEND "Resend:" // resend for host
#define WARNING "Warning:" // warning for host
#define TNAN "NAN" // NAN for host #define TNAN "NAN" // NAN for host
#define TINF "INF" // INF for host #define TINF "INF" // INF for host
#define PAUSE "//action:pause" // command for host that support action #define PAUSE "//action:pause" // command for host that support action
......
/**
* MK 3D Printer Firmware
*
* Based on Marlin, Sprinter and grbl
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
* Copyright (C) 2013 - 2016 Alberto Cotronei @MagoKimbra
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/** /**
* Conditionals.h * Conditionals.h
* Defines that depend on configuration but are not editable. * Defines that depend on configuration but are not editable.
*/ */
#ifndef CONDITIONALS_H #ifndef CONDITIONALS_H
#define CONDITIONALS_H #define CONDITIONALS_H
#if ENABLED(MAKRPANEL) #if ENABLED(MAKRPANEL)
#define DOGLCD #define DOGLCD
#define DEFAULT_LCD_CONTRAST 17 #define DEFAULT_LCD_CONTRAST 17
#define ULTIPANEL #define ULTIPANEL
#define NEWPANEL #define NEWPANEL
#endif #endif
#if ENABLED(miniVIKI) || ENABLED(VIKI2) || ENABLED(ELB_FULL_GRAPHIC_CONTROLLER) #if ENABLED(miniVIKI) || ENABLED(VIKI2) || ENABLED(ELB_FULL_GRAPHIC_CONTROLLER)
#define ULTRA_LCD //general LCD support, also 16x2 #define ULTRA_LCD //general LCD support, also 16x2
#define DOGLCD // Support for SPI LCD 128x64 (Controller ST7565R graphic Display Family) #define DOGLCD // Support for SPI LCD 128x64 (Controller ST7565R graphic Display Family)
#define ULTIMAKERCONTROLLER //as available from the Ultimaker online store. #define ULTIMAKERCONTROLLER //as available from the Ultimaker online store.
...@@ -28,85 +51,85 @@ ...@@ -28,85 +51,85 @@
#define ENCODER_PULSES_PER_STEP 4 #define ENCODER_PULSES_PER_STEP 4
#define ENCODER_STEPS_PER_MENU_ITEM 1 #define ENCODER_STEPS_PER_MENU_ITEM 1
#endif #endif
// Generic support for SSD1306 OLED based LCDs. // Generic support for SSD1306 OLED based LCDs.
#if ENABLED(U8GLIB_SSD1306) #if ENABLED(U8GLIB_SSD1306)
#define ULTRA_LCD //general LCD support, also 16x2 #define ULTRA_LCD //general LCD support, also 16x2
#define DOGLCD // Support for I2C LCD 128x64 (Controller SSD1306 graphic Display Family) #define DOGLCD // Support for I2C LCD 128x64 (Controller SSD1306 graphic Display Family)
#endif #endif
#if ENABLED(PANEL_ONE) #if ENABLED(PANEL_ONE)
#define ULTIMAKERCONTROLLER #define ULTIMAKERCONTROLLER
#endif #endif
#if ENABLED(REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER) #if ENABLED(REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER)
#define DOGLCD #define DOGLCD
#define U8GLIB_ST7920 #define U8GLIB_ST7920
#define REPRAP_DISCOUNT_SMART_CONTROLLER #define REPRAP_DISCOUNT_SMART_CONTROLLER
#endif #endif
#if ENABLED(SPARK_FULL_GRAPHICS) #if ENABLED(SPARK_FULL_GRAPHICS)
#define ENCODER_PULSES_PER_STEP 2 #define ENCODER_PULSES_PER_STEP 2
#define ENCODER_STEPS_PER_MENU_ITEM 1 #define ENCODER_STEPS_PER_MENU_ITEM 1
#define DOGLCD #define DOGLCD
#define U8GLIB_ST7920 #define U8GLIB_ST7920
#define REPRAP_DISCOUNT_SMART_CONTROLLER #define REPRAP_DISCOUNT_SMART_CONTROLLER
#endif #endif
#if ENABLED(REPRAP_DISCOUNT_SMART_CONTROLLER) #if ENABLED(REPRAP_DISCOUNT_SMART_CONTROLLER)
#if DISABLED(SDSUPPORT) #if DISABLED(SDSUPPORT)
#define SDSUPPORT #define SDSUPPORT
#endif #endif
#endif #endif
#if ENABLED(ULTIMAKERCONTROLLER) || ENABLED(REPRAP_DISCOUNT_SMART_CONTROLLER) || ENABLED(G3D_PANEL) || ENABLED(RIGIDBOT_PANEL) #if ENABLED(ULTIMAKERCONTROLLER) || ENABLED(REPRAP_DISCOUNT_SMART_CONTROLLER) || ENABLED(G3D_PANEL) || ENABLED(RIGIDBOT_PANEL)
#define ULTIPANEL #define ULTIPANEL
#define NEWPANEL #define NEWPANEL
#endif #endif
#if ENABLED(RADDS_DISPLAY) #if ENABLED(RADDS_DISPLAY)
#define ENCODER_PULSES_PER_STEP 2 #define ENCODER_PULSES_PER_STEP 2
#define ENCODER_STEPS_PER_MENU_ITEM 1 #define ENCODER_STEPS_PER_MENU_ITEM 1
#define ULTIPANEL #define ULTIPANEL
#define NEWPANEL #define NEWPANEL
#endif #endif
#if ENABLED(REPRAPWORLD_KEYPAD) #if ENABLED(REPRAPWORLD_KEYPAD)
#define ULTIPANEL #define ULTIPANEL
#define NEWPANEL #define NEWPANEL
#endif #endif
#if ENABLED(RA_CONTROL_PANEL) #if ENABLED(RA_CONTROL_PANEL)
#define LCD_I2C_TYPE_PCA8574 #define LCD_I2C_TYPE_PCA8574
#define LCD_I2C_ADDRESS 0x27 // I2C Address of the port expander #define LCD_I2C_ADDRESS 0x27 // I2C Address of the port expander
#define ULTIPANEL #define ULTIPANEL
#define NEWPANEL #define NEWPANEL
#endif #endif
#if ENABLED(MINIPANEL) #if ENABLED(MINIPANEL)
#define DOGLCD #define DOGLCD
#define ULTIPANEL #define ULTIPANEL
#define NEWPANEL #define NEWPANEL
#define DEFAULT_LCD_CONTRAST 17 #define DEFAULT_LCD_CONTRAST 17
#endif #endif
/** /**
* I2C PANELS * I2C PANELS
*/ */
#if ENABLED(LCD_I2C_SAINSMART_YWROBOT) #if ENABLED(LCD_I2C_SAINSMART_YWROBOT)
// This uses the LiquidCrystal_I2C library ( https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/Home ) // This uses the LiquidCrystal_I2C library ( https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/Home )
// Make sure it is placed in the Arduino libraries directory. // Make sure it is placed in the Arduino libraries directory.
#define LCD_I2C_TYPE_PCF8575 #define LCD_I2C_TYPE_PCF8575
#define LCD_I2C_ADDRESS 0x27 // I2C Address of the port expander #define LCD_I2C_ADDRESS 0x27 // I2C Address of the port expander
#define ULTIPANEL #define ULTIPANEL
#define NEWPANEL #define NEWPANEL
#endif #endif
// PANELOLU2 LCD with status LEDs, separate encoder and click inputs // PANELOLU2 LCD with status LEDs, separate encoder and click inputs
#if ENABLED(LCD_I2C_PANELOLU2) #if ENABLED(LCD_I2C_PANELOLU2)
#define LCD_I2C_TYPE_MCP23017 #define LCD_I2C_TYPE_MCP23017
#define LCD_I2C_ADDRESS 0x20 // I2C Address of the port expander #define LCD_I2C_ADDRESS 0x20 // I2C Address of the port expander
#define LCD_USE_I2C_BUZZER //comment out to disable buzzer on LCD #define LCD_USE_I2C_BUZZER //comment out to disable buzzer on LCD
...@@ -126,10 +149,10 @@ ...@@ -126,10 +149,10 @@
#define ULTIPANEL #define ULTIPANEL
#define NEWPANEL #define NEWPANEL
#endif #endif
// Panucatt VIKI LCD with status LEDs, integrated click & L/R/U/P buttons, separate encoder inputs // Panucatt VIKI LCD with status LEDs, integrated click & L/R/U/P buttons, separate encoder inputs
#if ENABLED(LCD_I2C_VIKI) #if ENABLED(LCD_I2C_VIKI)
// This uses the LiquidTWI2 library v1.2.3 or later ( https://github.com/lincomatic/LiquidTWI2 ) // This uses the LiquidTWI2 library v1.2.3 or later ( https://github.com/lincomatic/LiquidTWI2 )
// Make sure the LiquidTWI2 directory is placed in the Arduino or Sketchbook libraries subdirectory. // Make sure the LiquidTWI2 directory is placed in the Arduino or Sketchbook libraries subdirectory.
// Note: The pause/stop/resume LCD button pin should be connected to the Arduino // Note: The pause/stop/resume LCD button pin should be connected to the Arduino
...@@ -139,29 +162,29 @@ ...@@ -139,29 +162,29 @@
#define LCD_USE_I2C_BUZZER //comment out to disable buzzer on LCD (requires LiquidTWI2 v1.2.3 or later) #define LCD_USE_I2C_BUZZER //comment out to disable buzzer on LCD (requires LiquidTWI2 v1.2.3 or later)
#define ULTIPANEL #define ULTIPANEL
#define NEWPANEL #define NEWPANEL
#endif #endif
// Shift register panels // Shift register panels
// --------------------- // ---------------------
// 2 wire Non-latching LCD SR from: // 2 wire Non-latching LCD SR from:
// https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/schematics#!shiftregister-connection // https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/schematics#!shiftregister-connection
#if ENABLED(SAV_3DLCD) #if ENABLED(SAV_3DLCD)
#define SR_LCD_2W_NL // Non latching 2 wire shiftregister #define SR_LCD_2W_NL // Non latching 2 wire shiftregister
#define ULTIPANEL #define ULTIPANEL
#define NEWPANEL #define NEWPANEL
#endif #endif
#if ENABLED(DOGLCD) // Change number of lines to match the DOG graphic display #if ENABLED(DOGLCD) // Change number of lines to match the DOG graphic display
#if DISABLED(LCD_WIDTH) #if DISABLED(LCD_WIDTH)
#define LCD_WIDTH 22 #define LCD_WIDTH 22
#endif #endif
#if DISABLED(LCD_HEIGHT) #if DISABLED(LCD_HEIGHT)
#define LCD_HEIGHT 5 #define LCD_HEIGHT 5
#endif #endif
#endif #endif
#if ENABLED(ULTIPANEL) #if ENABLED(ULTIPANEL)
#define NEWPANEL //enable this if you have a click-encoder panel #define NEWPANEL //enable this if you have a click-encoder panel
#define ULTRA_LCD #define ULTRA_LCD
#if DISABLED(LCD_WIDTH) #if DISABLED(LCD_WIDTH)
...@@ -170,7 +193,7 @@ ...@@ -170,7 +193,7 @@
#if DISABLED(LCD_HEIGHT) #if DISABLED(LCD_HEIGHT)
#define LCD_HEIGHT 4 #define LCD_HEIGHT 4
#endif #endif
#else //no panel but just LCD #else //no panel but just LCD
#if ENABLED(ULTRA_LCD) #if ENABLED(ULTRA_LCD)
#if DISABLED(LCD_WIDTH) #if DISABLED(LCD_WIDTH)
#define LCD_WIDTH 16 #define LCD_WIDTH 16
...@@ -179,9 +202,9 @@ ...@@ -179,9 +202,9 @@
#define LCD_HEIGHT 2 #define LCD_HEIGHT 2
#endif #endif
#endif #endif
#endif #endif
#if ENABLED(DOGLCD) #if ENABLED(DOGLCD)
/* Custom characters defined in font font_6x10_marlin_symbols */ /* Custom characters defined in font font_6x10_marlin_symbols */
// \x00 intentionally skipped to avoid problems in strings // \x00 intentionally skipped to avoid problems in strings
#define LCD_STR_REFRESH "\x01" #define LCD_STR_REFRESH "\x01"
...@@ -197,7 +220,7 @@ ...@@ -197,7 +220,7 @@
#define LCD_STR_SPECIAL_MAX '\x09' #define LCD_STR_SPECIAL_MAX '\x09'
// Maximum here is 0x1f because 0x20 is ' ' (space) and the normal charsets begin. // Maximum here is 0x1f because 0x20 is ' ' (space) and the normal charsets begin.
// Better stay below 0x10 because DISPLAY_CHARSET_HD44780_WESTERN begins here. // Better stay below 0x10 because DISPLAY_CHARSET_HD44780_WESTERN begins here.
#else #else
/* Custom characters defined in the first 8 characters of the LCD */ /* Custom characters defined in the first 8 characters of the LCD */
#define LCD_STR_BEDTEMP "\x00" // this will have 'unexpected' results when used in a string! #define LCD_STR_BEDTEMP "\x00" // this will have 'unexpected' results when used in a string!
#define LCD_STR_DEGREE "\x01" #define LCD_STR_DEGREE "\x01"
...@@ -208,16 +231,16 @@ ...@@ -208,16 +231,16 @@
#define LCD_STR_FEEDRATE "\x06" #define LCD_STR_FEEDRATE "\x06"
#define LCD_STR_CLOCK "\x07" #define LCD_STR_CLOCK "\x07"
#define LCD_STR_ARROW_RIGHT ">" /* from the default character set */ #define LCD_STR_ARROW_RIGHT ">" /* from the default character set */
#endif #endif
/** /**
* Default LCD contrast for dogm-like LCD displays * Default LCD contrast for dogm-like LCD displays
*/ */
#if ENABLED(DOGLCD) && DISABLED(DEFAULT_LCD_CONTRAST) #if ENABLED(DOGLCD) && DISABLED(DEFAULT_LCD_CONTRAST)
#define DEFAULT_LCD_CONTRAST 32 #define DEFAULT_LCD_CONTRAST 32
#endif #endif
#if ENABLED(DOGLCD) #if ENABLED(DOGLCD)
#define HAS_LCD_CONTRAST #define HAS_LCD_CONTRAST
#if ENABLED(U8GLIB_ST7920) #if ENABLED(U8GLIB_ST7920)
#undef HAS_LCD_CONTRAST #undef HAS_LCD_CONTRAST
...@@ -225,62 +248,62 @@ ...@@ -225,62 +248,62 @@
#if ENABLED(U8GLIB_SSD1306) #if ENABLED(U8GLIB_SSD1306)
#undef HAS_LCD_CONTRAST #undef HAS_LCD_CONTRAST
#endif #endif
#endif #endif
#include "pins.h" #include "pins.h"
/** /**
* SAM3X8E * SAM3X8E
*/ */
#ifdef __SAM3X8E__ #ifdef __SAM3X8E__
#ifdef FAST_PWM_FAN #ifdef FAST_PWM_FAN
#undef FAST_PWM_FAN #undef FAST_PWM_FAN
#endif #endif
#ifdef M100_FREE_MEMORY_WATCHER #ifdef M100_FREE_MEMORY_WATCHER
#undef M100_FREE_MEMORY_WATCHER #undef M100_FREE_MEMORY_WATCHER
#endif #endif
#endif #endif
/** /**
* DONDOLO * DONDOLO
*/ */
#if ENABLED(DONDOLO) #if ENABLED(DONDOLO)
#undef SINGLENOZZLE #undef SINGLENOZZLE
#undef ADVANCE #undef ADVANCE
#undef DRIVER_EXTRUDERS #undef DRIVER_EXTRUDERS
#define DRIVER_EXTRUDERS 1 #define DRIVER_EXTRUDERS 1
#endif #endif
/** /**
* SINGLENOZZLE * SINGLENOZZLE
*/ */
#if ENABLED(SINGLENOZZLE) #if ENABLED(SINGLENOZZLE)
#undef HOTENDS #undef HOTENDS
#define HOTENDS 1 #define HOTENDS 1
#undef TEMP_SENSOR_1_AS_REDUNDANT #undef TEMP_SENSOR_1_AS_REDUNDANT
#else #else
#undef HOTENDS #undef HOTENDS
#define HOTENDS EXTRUDERS #define HOTENDS EXTRUDERS
#endif #endif
/** /**
* DRIVER_EXTRUDERS * DRIVER_EXTRUDERS
*/ */
#if DISABLED(MKR4) && DISABLED(NPR2) && DISABLED(DONDOLO) && DISABLED(COLOR_MIXING_EXTRUDER) #if DISABLED(MKR4) && DISABLED(NPR2) && DISABLED(DONDOLO) && DISABLED(COLOR_MIXING_EXTRUDER)
#undef DRIVER_EXTRUDERS #undef DRIVER_EXTRUDERS
#define DRIVER_EXTRUDERS EXTRUDERS // This defines the number of Driver extruder #define DRIVER_EXTRUDERS EXTRUDERS // This defines the number of Driver extruder
#endif #endif
#ifndef __SAM3X8E__ #ifndef __SAM3X8E__
#ifndef USBCON #ifndef USBCON
#define HardwareSerial_h // trick to disable the standard HWserial #define HardwareSerial_h // trick to disable the standard HWserial
#endif #endif
#endif #endif
/** /**
* ENDSTOPPULLUPS * ENDSTOPPULLUPS
*/ */
#if ENABLED(ENDSTOPPULLUPS) #if ENABLED(ENDSTOPPULLUPS)
#define ENDSTOPPULLUP_XMIN #define ENDSTOPPULLUP_XMIN
#define ENDSTOPPULLUP_YMIN #define ENDSTOPPULLUP_YMIN
#define ENDSTOPPULLUP_ZMIN #define ENDSTOPPULLUP_ZMIN
...@@ -291,12 +314,12 @@ ...@@ -291,12 +314,12 @@
#define ENDSTOPPULLUP_Z2MAX #define ENDSTOPPULLUP_Z2MAX
#define ENDSTOPPULLUP_ZPROBE #define ENDSTOPPULLUP_ZPROBE
#define ENDSTOPPULLUP_EMIN #define ENDSTOPPULLUP_EMIN
#endif #endif
/** /**
* ENDSTOP LOGICAL * ENDSTOP LOGICAL
*/ */
#if MB(ALLIGATOR) #if MB(ALLIGATOR)
#define X_MIN_ENDSTOP_INVERTING !X_MIN_ENDSTOP_LOGIC #define X_MIN_ENDSTOP_INVERTING !X_MIN_ENDSTOP_LOGIC
#define Y_MIN_ENDSTOP_INVERTING !Y_MIN_ENDSTOP_LOGIC #define Y_MIN_ENDSTOP_INVERTING !Y_MIN_ENDSTOP_LOGIC
#define Z_MIN_ENDSTOP_INVERTING !Z_MIN_ENDSTOP_LOGIC #define Z_MIN_ENDSTOP_INVERTING !Z_MIN_ENDSTOP_LOGIC
...@@ -317,7 +340,7 @@ ...@@ -317,7 +340,7 @@
#undef ENDSTOPPULLUP_Z2MAX #undef ENDSTOPPULLUP_Z2MAX
#undef ENDSTOPPULLUP_ZPROBE #undef ENDSTOPPULLUP_ZPROBE
#undef ENDSTOPPULLUP_EMIN #undef ENDSTOPPULLUP_EMIN
#else #else
#define X_MIN_ENDSTOP_INVERTING X_MIN_ENDSTOP_LOGIC #define X_MIN_ENDSTOP_INVERTING X_MIN_ENDSTOP_LOGIC
#define Y_MIN_ENDSTOP_INVERTING Y_MIN_ENDSTOP_LOGIC #define Y_MIN_ENDSTOP_INVERTING Y_MIN_ENDSTOP_LOGIC
#define Z_MIN_ENDSTOP_INVERTING Z_MIN_ENDSTOP_LOGIC #define Z_MIN_ENDSTOP_INVERTING Z_MIN_ENDSTOP_LOGIC
...@@ -328,35 +351,35 @@ ...@@ -328,35 +351,35 @@
#define Z_MAX_ENDSTOP_INVERTING Z_MAX_ENDSTOP_LOGIC #define Z_MAX_ENDSTOP_INVERTING Z_MAX_ENDSTOP_LOGIC
#define Z2_MAX_ENDSTOP_INVERTING Z2_MAX_ENDSTOP_LOGIC #define Z2_MAX_ENDSTOP_INVERTING Z2_MAX_ENDSTOP_LOGIC
#define Z_PROBE_ENDSTOP_INVERTING Z_PROBE_ENDSTOP_LOGIC #define Z_PROBE_ENDSTOP_INVERTING Z_PROBE_ENDSTOP_LOGIC
#endif #endif
/** /**
* Firmware Test * Firmware Test
*/ */
#if ENABLED(FIRMWARE_TEST) #if ENABLED(FIRMWARE_TEST)
#undef BAUDRATE #undef BAUDRATE
#define BAUDRATE 115200 // Baudrate setting to 115200 because serial monitor arduino function at max 115200 baudrate. #define BAUDRATE 115200 // Baudrate setting to 115200 because serial monitor arduino function at max 115200 baudrate.
#endif #endif
/** /**
* Axis lengths * Axis lengths
*/ */
#define X_MAX_LENGTH (X_MAX_POS - (X_MIN_POS)) #define X_MAX_LENGTH (X_MAX_POS - (X_MIN_POS))
#define Y_MAX_LENGTH (Y_MAX_POS - (Y_MIN_POS)) #define Y_MAX_LENGTH (Y_MAX_POS - (Y_MIN_POS))
#define Z_MAX_LENGTH (Z_MAX_POS - (Z_MIN_POS)) #define Z_MAX_LENGTH (Z_MAX_POS - (Z_MIN_POS))
/** /**
* SCARA * SCARA
*/ */
#if MECH(SCARA) #if MECH(SCARA)
#undef SLOWDOWN #undef SLOWDOWN
#define QUICK_HOME //SCARA needs Quickhome #define QUICK_HOME //SCARA needs Quickhome
#endif #endif
/** /**
* DELTA * DELTA
*/ */
#if MECH(DELTA) #if MECH(DELTA)
#undef SLOWDOWN //DELTA not needs SLOWDOWN #undef SLOWDOWN //DELTA not needs SLOWDOWN
#define AUTOLEVEL_GRID_MULTI 1/AUTOLEVEL_GRID #define AUTOLEVEL_GRID_MULTI 1/AUTOLEVEL_GRID
// DELTA must have same valour for 3 axis endstop hits // DELTA must have same valour for 3 axis endstop hits
...@@ -374,16 +397,16 @@ ...@@ -374,16 +397,16 @@
// Radius for probe // Radius for probe
#define DELTA_PROBABLE_RADIUS DELTA_PRINTABLE_RADIUS - 5 #define DELTA_PROBABLE_RADIUS DELTA_PRINTABLE_RADIUS - 5
#endif #endif
/** /**
* AUTOSET LOCATIONS OF LIMIT SWITCHES * AUTOSET LOCATIONS OF LIMIT SWITCHES
*/ */
#if ENABLED(MANUAL_HOME_POSITIONS) // Use manual limit switch locations #if ENABLED(MANUAL_HOME_POSITIONS) // Use manual limit switch locations
#define X_HOME_POS MANUAL_X_HOME_POS #define X_HOME_POS MANUAL_X_HOME_POS
#define Y_HOME_POS MANUAL_Y_HOME_POS #define Y_HOME_POS MANUAL_Y_HOME_POS
#define Z_HOME_POS MANUAL_Z_HOME_POS #define Z_HOME_POS MANUAL_Z_HOME_POS
#else //!MANUAL_HOME_POSITIONS – Use home switch positions based on homing direction and travel limits #else //!MANUAL_HOME_POSITIONS – Use home switch positions based on homing direction and travel limits
#if ENABLED(BED_CENTER_AT_0_0) #if ENABLED(BED_CENTER_AT_0_0)
#define X_HOME_POS (X_MAX_LENGTH) * (X_HOME_DIR) * 0.5 #define X_HOME_POS (X_MAX_LENGTH) * (X_HOME_DIR) * 0.5
#define Y_HOME_POS (Y_MAX_LENGTH) * (Y_HOME_DIR) * 0.5 #define Y_HOME_POS (Y_MAX_LENGTH) * (Y_HOME_DIR) * 0.5
...@@ -392,12 +415,12 @@ ...@@ -392,12 +415,12 @@
#define Y_HOME_POS (Y_HOME_DIR < 0 ? Y_MIN_POS : Y_MAX_POS) #define Y_HOME_POS (Y_HOME_DIR < 0 ? Y_MIN_POS : Y_MAX_POS)
#endif #endif
#define Z_HOME_POS (Z_HOME_DIR < 0 ? Z_MIN_POS : Z_MAX_POS) #define Z_HOME_POS (Z_HOME_DIR < 0 ? Z_MIN_POS : Z_MAX_POS)
#endif //!MANUAL_HOME_POSITIONS #endif //!MANUAL_HOME_POSITIONS
/** /**
* Auto Bed Leveling * Auto Bed Leveling
*/ */
#if ENABLED(AUTO_BED_LEVELING_FEATURE) #if ENABLED(AUTO_BED_LEVELING_FEATURE)
// Boundaries for probing based on set limits // Boundaries for probing based on set limits
#define MIN_PROBE_X (max(X_MIN_POS, X_MIN_POS + X_PROBE_OFFSET_FROM_EXTRUDER)) #define MIN_PROBE_X (max(X_MIN_POS, X_MIN_POS + X_PROBE_OFFSET_FROM_EXTRUDER))
#define MAX_PROBE_X (min(X_MAX_POS, X_MAX_POS + X_PROBE_OFFSET_FROM_EXTRUDER)) #define MAX_PROBE_X (min(X_MAX_POS, X_MAX_POS + X_PROBE_OFFSET_FROM_EXTRUDER))
...@@ -427,19 +450,27 @@ ...@@ -427,19 +450,27 @@
#undef Z_RAISE_AFTER_PROBING #undef Z_RAISE_AFTER_PROBING
#define Z_RAISE_AFTER_PROBING 0 #define Z_RAISE_AFTER_PROBING 0
#endif #endif
#endif #endif
/** /**
* Sled Options * Sled Options
*/ */
#if ENABLED(Z_PROBE_SLED) #if ENABLED(Z_PROBE_SLED)
#define Z_SAFE_HOMING #define Z_SAFE_HOMING
#endif #endif
/** /**
* Avoid double-negatives for enabling features
*/
#if DISABLED(DISABLE_HOST_KEEPALIVE)
#define HOST_KEEPALIVE_FEATURE
#define DEFAULT_KEEPALIVE_INTERVAL 2
#endif
/**
* MAX_STEP_FREQUENCY differs for TOSHIBA OR ARDUINO DUE OR ARDUINO MEGA * MAX_STEP_FREQUENCY differs for TOSHIBA OR ARDUINO DUE OR ARDUINO MEGA
*/ */
#ifdef __SAM3X8E__ #ifdef __SAM3X8E__
#if ENABLED(CONFIG_STEPPERS_TOSHIBA) #if ENABLED(CONFIG_STEPPERS_TOSHIBA)
#define MAX_STEP_FREQUENCY 150000 // Max step frequency for Toshiba Stepper Controllers #define MAX_STEP_FREQUENCY 150000 // Max step frequency for Toshiba Stepper Controllers
#define DOUBLE_STEP_FREQUENCY MAX_STEP_FREQUENCY #define DOUBLE_STEP_FREQUENCY MAX_STEP_FREQUENCY
...@@ -447,7 +478,7 @@ ...@@ -447,7 +478,7 @@
#define MAX_STEP_FREQUENCY 320000 // Max step frequency for the Due is approx. 330kHz #define MAX_STEP_FREQUENCY 320000 // Max step frequency for the Due is approx. 330kHz
#define DOUBLE_STEP_FREQUENCY 90000 // 96kHz is close to maximum for an Arduino Due #define DOUBLE_STEP_FREQUENCY 90000 // 96kHz is close to maximum for an Arduino Due
#endif #endif
#else #else
#if ENABLED(CONFIG_STEPPERS_TOSHIBA) #if ENABLED(CONFIG_STEPPERS_TOSHIBA)
#define MAX_STEP_FREQUENCY 10000 // Max step frequency for Toshiba Stepper Controllers #define MAX_STEP_FREQUENCY 10000 // Max step frequency for Toshiba Stepper Controllers
#define DOUBLE_STEP_FREQUENCY MAX_STEP_FREQUENCY #define DOUBLE_STEP_FREQUENCY MAX_STEP_FREQUENCY
...@@ -455,270 +486,270 @@ ...@@ -455,270 +486,270 @@
#define MAX_STEP_FREQUENCY 40000 // Max step frequency for Arduino mega #define MAX_STEP_FREQUENCY 40000 // Max step frequency for Arduino mega
#define DOUBLE_STEP_FREQUENCY 10000 #define DOUBLE_STEP_FREQUENCY 10000
#endif #endif
#endif #endif
// MS1 MS2 Stepper Driver Microstepping mode table // MS1 MS2 Stepper Driver Microstepping mode table
#define MICROSTEP1 LOW,LOW #define MICROSTEP1 LOW,LOW
#define MICROSTEP2 HIGH,LOW #define MICROSTEP2 HIGH,LOW
#define MICROSTEP4 LOW,HIGH #define MICROSTEP4 LOW,HIGH
#define MICROSTEP8 HIGH,HIGH #define MICROSTEP8 HIGH,HIGH
#if MB(ALLIGATOR) #if MB(ALLIGATOR)
#define MICROSTEP16 LOW,LOW #define MICROSTEP16 LOW,LOW
#define MICROSTEP32 HIGH,HIGH #define MICROSTEP32 HIGH,HIGH
#else #else
#define MICROSTEP16 HIGH,HIGH #define MICROSTEP16 HIGH,HIGH
#endif #endif
/** /**
* Advance calculated values * Advance calculated values
*/ */
#if ENABLED(ADVANCE) #if ENABLED(ADVANCE)
#define EXTRUSION_AREA (0.25 * (D_FILAMENT) * (D_FILAMENT) * M_PI) #define EXTRUSION_AREA (0.25 * (D_FILAMENT) * (D_FILAMENT) * M_PI)
#define STEPS_PER_CUBIC_MM_E (axis_steps_per_unit[E_AXIS + active_extruder] / EXTRUSION_AREA) #define STEPS_PER_CUBIC_MM_E (axis_steps_per_unit[E_AXIS + active_extruder] / EXTRUSION_AREA)
#endif #endif
/** /**
* SD DETECT * SD DETECT
* *
*/ */
#if ENABLED(SD_DISABLED_DETECT) #if ENABLED(SD_DISABLED_DETECT)
#undef SD_DETECT_PIN #undef SD_DETECT_PIN
#define SD_DETECT_PIN -1 #define SD_DETECT_PIN -1
#endif #endif
#if ENABLED(ULTIPANEL) && DISABLED(ELB_FULL_GRAPHIC_CONTROLLER) #if ENABLED(ULTIPANEL) && DISABLED(ELB_FULL_GRAPHIC_CONTROLLER)
#undef SD_DETECT_INVERTED #undef SD_DETECT_INVERTED
#endif #endif
/** /**
* Power Signal Control Definitions * Power Signal Control Definitions
* By default use Normal definition * By default use Normal definition
*/ */
#if DISABLED(POWER_SUPPLY) #if DISABLED(POWER_SUPPLY)
#define POWER_SUPPLY 0 #define POWER_SUPPLY 0
#endif #endif
#if (POWER_SUPPLY == 1) // 1 = ATX #if (POWER_SUPPLY == 1) // 1 = ATX
#define PS_ON_AWAKE LOW #define PS_ON_AWAKE LOW
#define PS_ON_ASLEEP HIGH #define PS_ON_ASLEEP HIGH
#elif (POWER_SUPPLY == 2) // 2 = X-Box 360 203W #elif (POWER_SUPPLY == 2) // 2 = X-Box 360 203W
#define PS_ON_AWAKE HIGH #define PS_ON_AWAKE HIGH
#define PS_ON_ASLEEP LOW #define PS_ON_ASLEEP LOW
#endif #endif
#define HAS_POWER_SWITCH (POWER_SUPPLY > 0 && PIN_EXISTS(PS_ON)) #define HAS_POWER_SWITCH (POWER_SUPPLY > 0 && PIN_EXISTS(PS_ON))
/** /**
* Temp Sensor defines * Temp Sensor defines
*/ */
#if TEMP_SENSOR_0 == -2 #if TEMP_SENSOR_0 == -2
#define HEATER_0_USES_MAX6675 #define HEATER_0_USES_MAX6675
#elif TEMP_SENSOR_0 == -1 #elif TEMP_SENSOR_0 == -1
#define HEATER_0_USES_AD595 #define HEATER_0_USES_AD595
#elif TEMP_SENSOR_0 == 0 #elif TEMP_SENSOR_0 == 0
#undef HEATER_0_MINTEMP #undef HEATER_0_MINTEMP
#undef HEATER_0_MAXTEMP #undef HEATER_0_MAXTEMP
#elif TEMP_SENSOR_0 > 0 #elif TEMP_SENSOR_0 > 0
#define THERMISTORHEATER_0 TEMP_SENSOR_0 #define THERMISTORHEATER_0 TEMP_SENSOR_0
#define HEATER_0_USES_THERMISTOR #define HEATER_0_USES_THERMISTOR
#endif #endif
#if TEMP_SENSOR_1 == -1 #if TEMP_SENSOR_1 == -1
#define HEATER_1_USES_AD595 #define HEATER_1_USES_AD595
#elif TEMP_SENSOR_1 == 0 #elif TEMP_SENSOR_1 == 0
#undef HEATER_1_MINTEMP #undef HEATER_1_MINTEMP
#undef HEATER_1_MAXTEMP #undef HEATER_1_MAXTEMP
#elif TEMP_SENSOR_1 > 0 #elif TEMP_SENSOR_1 > 0
#define THERMISTORHEATER_1 TEMP_SENSOR_1 #define THERMISTORHEATER_1 TEMP_SENSOR_1
#define HEATER_1_USES_THERMISTOR #define HEATER_1_USES_THERMISTOR
#endif #endif
#if TEMP_SENSOR_2 == -1 #if TEMP_SENSOR_2 == -1
#define HEATER_2_USES_AD595 #define HEATER_2_USES_AD595
#elif TEMP_SENSOR_2 == 0 #elif TEMP_SENSOR_2 == 0
#undef HEATER_2_MINTEMP #undef HEATER_2_MINTEMP
#undef HEATER_2_MAXTEMP #undef HEATER_2_MAXTEMP
#elif TEMP_SENSOR_2 > 0 #elif TEMP_SENSOR_2 > 0
#define THERMISTORHEATER_2 TEMP_SENSOR_2 #define THERMISTORHEATER_2 TEMP_SENSOR_2
#define HEATER_2_USES_THERMISTOR #define HEATER_2_USES_THERMISTOR
#endif #endif
#if TEMP_SENSOR_3 == -1 #if TEMP_SENSOR_3 == -1
#define HEATER_3_USES_AD595 #define HEATER_3_USES_AD595
#elif TEMP_SENSOR_3 == 0 #elif TEMP_SENSOR_3 == 0
#undef HEATER_3_MINTEMP #undef HEATER_3_MINTEMP
#undef HEATER_3_MAXTEMP #undef HEATER_3_MAXTEMP
#elif TEMP_SENSOR_3 > 0 #elif TEMP_SENSOR_3 > 0
#define THERMISTORHEATER_3 TEMP_SENSOR_3 #define THERMISTORHEATER_3 TEMP_SENSOR_3
#define HEATER_3_USES_THERMISTOR #define HEATER_3_USES_THERMISTOR
#endif #endif
#if TEMP_SENSOR_BED == -1 #if TEMP_SENSOR_BED == -1
#define BED_USES_AD595 #define BED_USES_AD595
#elif TEMP_SENSOR_BED == 0 #elif TEMP_SENSOR_BED == 0
#undef BED_MINTEMP #undef BED_MINTEMP
#undef BED_MAXTEMP #undef BED_MAXTEMP
#elif TEMP_SENSOR_BED > 0 #elif TEMP_SENSOR_BED > 0
#define THERMISTORBED TEMP_SENSOR_BED #define THERMISTORBED TEMP_SENSOR_BED
#define BED_USES_THERMISTOR #define BED_USES_THERMISTOR
#endif #endif
#define HEATER_USES_AD595 (ENABLED(HEATER_0_USES_AD595) || ENABLED(HEATER_1_USES_AD595) || ENABLED(HEATER_2_USES_AD595) || ENABLED(HEATER_3_USES_AD595)) #define HEATER_USES_AD595 (ENABLED(HEATER_0_USES_AD595) || ENABLED(HEATER_1_USES_AD595) || ENABLED(HEATER_2_USES_AD595) || ENABLED(HEATER_3_USES_AD595))
/** /**
* ARRAY_BY_EXTRUDERS based on EXTRUDERS * ARRAY_BY_EXTRUDERS based on EXTRUDERS
*/ */
#if EXTRUDERS > 9 #if EXTRUDERS > 9
#define ARRAY_BY_EXTRUDERS(v1) { v1, v1, v1, v1, v1, v1, v1, v1, v1, v1 } #define ARRAY_BY_EXTRUDERS(v1) { v1, v1, v1, v1, v1, v1, v1, v1, v1, v1 }
#elif EXTRUDERS > 8 #elif EXTRUDERS > 8
#define ARRAY_BY_EXTRUDERS(v1) { v1, v1, v1, v1, v1, v1, v1, v1, v1 } #define ARRAY_BY_EXTRUDERS(v1) { v1, v1, v1, v1, v1, v1, v1, v1, v1 }
#elif EXTRUDERS > 7 #elif EXTRUDERS > 7
#define ARRAY_BY_EXTRUDERS(v1) { v1, v1, v1, v1, v1, v1, v1, v1 } #define ARRAY_BY_EXTRUDERS(v1) { v1, v1, v1, v1, v1, v1, v1, v1 }
#elif EXTRUDERS > 6 #elif EXTRUDERS > 6
#define ARRAY_BY_EXTRUDERS(v1) { v1, v1, v1, v1, v1, v1, v1 } #define ARRAY_BY_EXTRUDERS(v1) { v1, v1, v1, v1, v1, v1, v1 }
#elif EXTRUDERS > 5 #elif EXTRUDERS > 5
#define ARRAY_BY_EXTRUDERS(v1) { v1, v1, v1, v1, v1, v1 } #define ARRAY_BY_EXTRUDERS(v1) { v1, v1, v1, v1, v1, v1 }
#elif EXTRUDERS > 4 #elif EXTRUDERS > 4
#define ARRAY_BY_EXTRUDERS(v1) { v1, v1, v1, v1, v1 } #define ARRAY_BY_EXTRUDERS(v1) { v1, v1, v1, v1, v1 }
#elif EXTRUDERS > 3 #elif EXTRUDERS > 3
#define ARRAY_BY_EXTRUDERS(v1) { v1, v1, v1, v1 } #define ARRAY_BY_EXTRUDERS(v1) { v1, v1, v1, v1 }
#elif EXTRUDERS > 2 #elif EXTRUDERS > 2
#define ARRAY_BY_EXTRUDERS(v1) { v1, v1, v1 } #define ARRAY_BY_EXTRUDERS(v1) { v1, v1, v1 }
#elif EXTRUDERS > 1 #elif EXTRUDERS > 1
#define ARRAY_BY_EXTRUDERS(v1) { v1, v1 } #define ARRAY_BY_EXTRUDERS(v1) { v1, v1 }
#else #else
#define ARRAY_BY_EXTRUDERS(v1) { v1 } #define ARRAY_BY_EXTRUDERS(v1) { v1 }
#endif #endif
/** /**
* ARRAY_BY_HOTENDS based on HOTENDS * ARRAY_BY_HOTENDS based on HOTENDS
*/ */
#if HOTENDS > 3 #if HOTENDS > 3
#define ARRAY_BY_HOTENDS(v1, v2, v3, v4) { v1, v2, v3, v4 } #define ARRAY_BY_HOTENDS(v1, v2, v3, v4) { v1, v2, v3, v4 }
#elif HOTENDS > 2 #elif HOTENDS > 2
#define ARRAY_BY_HOTENDS(v1, v2, v3, v4) { v1, v2, v3 } #define ARRAY_BY_HOTENDS(v1, v2, v3, v4) { v1, v2, v3 }
#elif HOTENDS > 1 #elif HOTENDS > 1
#define ARRAY_BY_HOTENDS(v1, v2, v3, v4) { v1, v2 } #define ARRAY_BY_HOTENDS(v1, v2, v3, v4) { v1, v2 }
#else #else
#define ARRAY_BY_HOTENDS(v1, v2, v3, v4) { v1 } #define ARRAY_BY_HOTENDS(v1, v2, v3, v4) { v1 }
#endif #endif
#define ARRAY_BY_HOTENDS1(v1) ARRAY_BY_HOTENDS(v1, v1, v1, v1) #define ARRAY_BY_HOTENDS1(v1) ARRAY_BY_HOTENDS(v1, v1, v1, v1)
/** /**
* Shorthand for pin tests, used wherever needed * Shorthand for pin tests, used wherever needed
*/ */
#define HAS_TEMP_0 (PIN_EXISTS(TEMP_0) && TEMP_SENSOR_0 != 0 && TEMP_SENSOR_0 != -2) #define HAS_TEMP_0 (PIN_EXISTS(TEMP_0) && TEMP_SENSOR_0 != 0 && TEMP_SENSOR_0 != -2)
#define HAS_TEMP_1 (PIN_EXISTS(TEMP_1) && TEMP_SENSOR_1 != 0) #define HAS_TEMP_1 (PIN_EXISTS(TEMP_1) && TEMP_SENSOR_1 != 0)
#define HAS_TEMP_2 (PIN_EXISTS(TEMP_2) && TEMP_SENSOR_2 != 0) #define HAS_TEMP_2 (PIN_EXISTS(TEMP_2) && TEMP_SENSOR_2 != 0)
#define HAS_TEMP_3 (PIN_EXISTS(TEMP_3) && TEMP_SENSOR_3 != 0) #define HAS_TEMP_3 (PIN_EXISTS(TEMP_3) && TEMP_SENSOR_3 != 0)
#define HAS_TEMP_BED (PIN_EXISTS(TEMP_BED) && TEMP_SENSOR_BED != 0) #define HAS_TEMP_BED (PIN_EXISTS(TEMP_BED) && TEMP_SENSOR_BED != 0)
#define HAS_HEATER_0 (PIN_EXISTS(HEATER_0)) #define HAS_HEATER_0 (PIN_EXISTS(HEATER_0))
#define HAS_HEATER_1 (PIN_EXISTS(HEATER_1)) #define HAS_HEATER_1 (PIN_EXISTS(HEATER_1))
#define HAS_HEATER_2 (PIN_EXISTS(HEATER_2)) #define HAS_HEATER_2 (PIN_EXISTS(HEATER_2))
#define HAS_HEATER_3 (PIN_EXISTS(HEATER_3)) #define HAS_HEATER_3 (PIN_EXISTS(HEATER_3))
#define HAS_HEATER_BED (PIN_EXISTS(HEATER_BED)) #define HAS_HEATER_BED (PIN_EXISTS(HEATER_BED))
#define HAS_AUTO_FAN_0 (ENABLED(EXTRUDER_AUTO_FAN) && PIN_EXISTS(EXTRUDER_0_AUTO_FAN)) #define HAS_AUTO_FAN_0 (ENABLED(EXTRUDER_AUTO_FAN) && PIN_EXISTS(EXTRUDER_0_AUTO_FAN))
#define HAS_AUTO_FAN_1 (ENABLED(EXTRUDER_AUTO_FAN) && PIN_EXISTS(EXTRUDER_1_AUTO_FAN)) #define HAS_AUTO_FAN_1 (ENABLED(EXTRUDER_AUTO_FAN) && PIN_EXISTS(EXTRUDER_1_AUTO_FAN))
#define HAS_AUTO_FAN_2 (ENABLED(EXTRUDER_AUTO_FAN) && PIN_EXISTS(EXTRUDER_2_AUTO_FAN)) #define HAS_AUTO_FAN_2 (ENABLED(EXTRUDER_AUTO_FAN) && PIN_EXISTS(EXTRUDER_2_AUTO_FAN))
#define HAS_AUTO_FAN_3 (ENABLED(EXTRUDER_AUTO_FAN) && PIN_EXISTS(EXTRUDER_3_AUTO_FAN)) #define HAS_AUTO_FAN_3 (ENABLED(EXTRUDER_AUTO_FAN) && PIN_EXISTS(EXTRUDER_3_AUTO_FAN))
#define HAS_AUTO_FAN (HAS_AUTO_FAN_0 || HAS_AUTO_FAN_1 || HAS_AUTO_FAN_2 || HAS_AUTO_FAN_3) #define HAS_AUTO_FAN (HAS_AUTO_FAN_0 || HAS_AUTO_FAN_1 || HAS_AUTO_FAN_2 || HAS_AUTO_FAN_3)
#define HAS_FAN (PIN_EXISTS(FAN)) #define HAS_FAN (PIN_EXISTS(FAN))
#define HAS_CONTROLLERFAN (ENABLED(CONTROLLERFAN) && PIN_EXISTS(CONTROLLERFAN)) #define HAS_CONTROLLERFAN (ENABLED(CONTROLLERFAN) && PIN_EXISTS(CONTROLLERFAN))
#define HAS_SERVO_0 (PIN_EXISTS(SERVO0)) #define HAS_SERVO_0 (PIN_EXISTS(SERVO0))
#define HAS_SERVO_1 (PIN_EXISTS(SERVO1)) #define HAS_SERVO_1 (PIN_EXISTS(SERVO1))
#define HAS_SERVO_2 (PIN_EXISTS(SERVO2)) #define HAS_SERVO_2 (PIN_EXISTS(SERVO2))
#define HAS_SERVO_3 (PIN_EXISTS(SERVO3)) #define HAS_SERVO_3 (PIN_EXISTS(SERVO3))
#define HAS_SERVOS ((ENABLED(ENABLE_SERVOS) && NUM_SERVOS > 0) && (HAS_SERVO_0 || HAS_SERVO_1 || HAS_SERVO_2 || HAS_SERVO_3)) #define HAS_SERVOS ((ENABLED(ENABLE_SERVOS) && NUM_SERVOS > 0) && (HAS_SERVO_0 || HAS_SERVO_1 || HAS_SERVO_2 || HAS_SERVO_3))
#define HAS_FILAMENT_SENSOR (ENABLED(FILAMENT_SENSOR) && PIN_EXISTS(FILWIDTH)) #define HAS_FILAMENT_SENSOR (ENABLED(FILAMENT_SENSOR) && PIN_EXISTS(FILWIDTH))
#define HAS_POWER_CONSUMPTION_SENSOR (ENABLED(POWER_CONSUMPTION) && PIN_EXISTS(POWER_CONSUMPTION)) #define HAS_POWER_CONSUMPTION_SENSOR (ENABLED(POWER_CONSUMPTION) && PIN_EXISTS(POWER_CONSUMPTION))
#define HAS_Z_PROBE_SLED (ENABLED(Z_PROBE_SLED) && PIN_EXISTS(SLED_PIN)) #define HAS_Z_PROBE_SLED (ENABLED(Z_PROBE_SLED) && PIN_EXISTS(SLED_PIN))
#define HAS_FILRUNOUT (ENABLED(FILAMENT_RUNOUT_SENSOR) && PIN_EXISTS(FILRUNOUT)) #define HAS_FILRUNOUT (ENABLED(FILAMENT_RUNOUT_SENSOR) && PIN_EXISTS(FILRUNOUT))
#define HAS_HOME (PIN_EXISTS(HOME)) #define HAS_HOME (PIN_EXISTS(HOME))
#define HAS_KILL (PIN_EXISTS(KILL)) #define HAS_KILL (PIN_EXISTS(KILL))
#define HAS_SUICIDE (PIN_EXISTS(SUICIDE)) #define HAS_SUICIDE (PIN_EXISTS(SUICIDE))
#define HAS_CHDK (ENABLED(CHDK) && PIN_EXISTS(CHDK)) #define HAS_CHDK (ENABLED(CHDK) && PIN_EXISTS(CHDK))
#define HAS_PHOTOGRAPH (ENABLED(PHOTOGRAPH) && PIN_EXISTS(PHOTOGRAPH)) #define HAS_PHOTOGRAPH (ENABLED(PHOTOGRAPH) && PIN_EXISTS(PHOTOGRAPH))
#define HAS_X_MIN (PIN_EXISTS(X_MIN)) #define HAS_X_MIN (PIN_EXISTS(X_MIN))
#define HAS_X_MAX (PIN_EXISTS(X_MAX)) #define HAS_X_MAX (PIN_EXISTS(X_MAX))
#define HAS_Y_MIN (PIN_EXISTS(Y_MIN)) #define HAS_Y_MIN (PIN_EXISTS(Y_MIN))
#define HAS_Y_MAX (PIN_EXISTS(Y_MAX)) #define HAS_Y_MAX (PIN_EXISTS(Y_MAX))
#define HAS_Z_MIN (PIN_EXISTS(Z_MIN)) #define HAS_Z_MIN (PIN_EXISTS(Z_MIN))
#define HAS_Z_MAX (PIN_EXISTS(Z_MAX)) #define HAS_Z_MAX (PIN_EXISTS(Z_MAX))
#define HAS_Z2_MIN (PIN_EXISTS(Z2_MIN)) #define HAS_Z2_MIN (PIN_EXISTS(Z2_MIN))
#define HAS_Z2_MAX (PIN_EXISTS(Z2_MAX)) #define HAS_Z2_MAX (PIN_EXISTS(Z2_MAX))
#define HAS_Z_PROBE (ENABLED(Z_PROBE_ENDSTOP) && PIN_EXISTS(Z_PROBE)) #define HAS_Z_PROBE (ENABLED(Z_PROBE_ENDSTOP) && PIN_EXISTS(Z_PROBE))
#define HAS_E_MIN (PIN_EXISTS(E_MIN)) #define HAS_E_MIN (PIN_EXISTS(E_MIN))
#define HAS_SOLENOID_1 (PIN_EXISTS(SOL1)) #define HAS_SOLENOID_1 (PIN_EXISTS(SOL1))
#define HAS_SOLENOID_2 (PIN_EXISTS(SOL2)) #define HAS_SOLENOID_2 (PIN_EXISTS(SOL2))
#define HAS_SOLENOID_3 (PIN_EXISTS(SOL3)) #define HAS_SOLENOID_3 (PIN_EXISTS(SOL3))
#define HAS_MICROSTEPS (ENABLED(USE_MICROSTEPS) && PIN_EXISTS(X_MS1)) #define HAS_MICROSTEPS (ENABLED(USE_MICROSTEPS) && PIN_EXISTS(X_MS1))
#define HAS_MICROSTEPS_E0 (ENABLED(USE_MICROSTEPS) && PIN_EXISTS(E0_MS1)) #define HAS_MICROSTEPS_E0 (ENABLED(USE_MICROSTEPS) && PIN_EXISTS(E0_MS1))
#define HAS_MICROSTEPS_E1 (ENABLED(USE_MICROSTEPS) && PIN_EXISTS(E1_MS1)) #define HAS_MICROSTEPS_E1 (ENABLED(USE_MICROSTEPS) && PIN_EXISTS(E1_MS1))
#define HAS_MICROSTEPS_E2 (ENABLED(USE_MICROSTEPS) && PIN_EXISTS(E2_MS1)) #define HAS_MICROSTEPS_E2 (ENABLED(USE_MICROSTEPS) && PIN_EXISTS(E2_MS1))
#define HAS_STEPPER_RESET (PIN_EXISTS(STEPPER_RESET)) #define HAS_STEPPER_RESET (PIN_EXISTS(STEPPER_RESET))
#define HAS_X_ENABLE (PIN_EXISTS(X_ENABLE)) #define HAS_X_ENABLE (PIN_EXISTS(X_ENABLE))
#define HAS_X2_ENABLE (PIN_EXISTS(X2_ENABLE)) #define HAS_X2_ENABLE (PIN_EXISTS(X2_ENABLE))
#define HAS_Y_ENABLE (PIN_EXISTS(Y_ENABLE)) #define HAS_Y_ENABLE (PIN_EXISTS(Y_ENABLE))
#define HAS_Y2_ENABLE (PIN_EXISTS(Y2_ENABLE)) #define HAS_Y2_ENABLE (PIN_EXISTS(Y2_ENABLE))
#define HAS_Z_ENABLE (PIN_EXISTS(Z_ENABLE)) #define HAS_Z_ENABLE (PIN_EXISTS(Z_ENABLE))
#define HAS_Z2_ENABLE (PIN_EXISTS(Z2_ENABLE)) #define HAS_Z2_ENABLE (PIN_EXISTS(Z2_ENABLE))
#define HAS_E0_ENABLE (PIN_EXISTS(E0_ENABLE)) #define HAS_E0_ENABLE (PIN_EXISTS(E0_ENABLE))
#define HAS_E1_ENABLE (PIN_EXISTS(E1_ENABLE)) #define HAS_E1_ENABLE (PIN_EXISTS(E1_ENABLE))
#define HAS_E2_ENABLE (PIN_EXISTS(E2_ENABLE)) #define HAS_E2_ENABLE (PIN_EXISTS(E2_ENABLE))
#define HAS_E3_ENABLE (PIN_EXISTS(E3_ENABLE)) #define HAS_E3_ENABLE (PIN_EXISTS(E3_ENABLE))
#define HAS_E4_ENABLE (PIN_EXISTS(E4_ENABLE)) #define HAS_E4_ENABLE (PIN_EXISTS(E4_ENABLE))
#define HAS_E5_ENABLE (PIN_EXISTS(E5_ENABLE)) #define HAS_E5_ENABLE (PIN_EXISTS(E5_ENABLE))
#define HAS_X_DIR (PIN_EXISTS(X_DIR)) #define HAS_X_DIR (PIN_EXISTS(X_DIR))
#define HAS_X2_DIR (PIN_EXISTS(X2_DIR)) #define HAS_X2_DIR (PIN_EXISTS(X2_DIR))
#define HAS_Y_DIR (PIN_EXISTS(Y_DIR)) #define HAS_Y_DIR (PIN_EXISTS(Y_DIR))
#define HAS_Y2_DIR (PIN_EXISTS(Y2_DIR)) #define HAS_Y2_DIR (PIN_EXISTS(Y2_DIR))
#define HAS_Z_DIR (PIN_EXISTS(Z_DIR)) #define HAS_Z_DIR (PIN_EXISTS(Z_DIR))
#define HAS_Z2_DIR (PIN_EXISTS(Z2_DIR)) #define HAS_Z2_DIR (PIN_EXISTS(Z2_DIR))
#define HAS_E0_DIR (PIN_EXISTS(E0_DIR)) #define HAS_E0_DIR (PIN_EXISTS(E0_DIR))
#define HAS_E1_DIR (PIN_EXISTS(E1_DIR)) #define HAS_E1_DIR (PIN_EXISTS(E1_DIR))
#define HAS_E2_DIR (PIN_EXISTS(E2_DIR)) #define HAS_E2_DIR (PIN_EXISTS(E2_DIR))
#define HAS_E3_DIR (PIN_EXISTS(E3_DIR)) #define HAS_E3_DIR (PIN_EXISTS(E3_DIR))
#define HAS_E4_DIR (PIN_EXISTS(E4_DIR)) #define HAS_E4_DIR (PIN_EXISTS(E4_DIR))
#define HAS_E5_DIR (PIN_EXISTS(E5_DIR)) #define HAS_E5_DIR (PIN_EXISTS(E5_DIR))
#define HAS_X_STEP (PIN_EXISTS(X_STEP)) #define HAS_X_STEP (PIN_EXISTS(X_STEP))
#define HAS_X2_STEP (PIN_EXISTS(X2_STEP)) #define HAS_X2_STEP (PIN_EXISTS(X2_STEP))
#define HAS_Y_STEP (PIN_EXISTS(Y_STEP)) #define HAS_Y_STEP (PIN_EXISTS(Y_STEP))
#define HAS_Y2_STEP (PIN_EXISTS(Y2_STEP)) #define HAS_Y2_STEP (PIN_EXISTS(Y2_STEP))
#define HAS_Z_STEP (PIN_EXISTS(Z_STEP)) #define HAS_Z_STEP (PIN_EXISTS(Z_STEP))
#define HAS_Z2_STEP (PIN_EXISTS(Z2_STEP)) #define HAS_Z2_STEP (PIN_EXISTS(Z2_STEP))
#define HAS_E0_STEP (PIN_EXISTS(E0_STEP)) #define HAS_E0_STEP (PIN_EXISTS(E0_STEP))
#define HAS_E1_STEP (PIN_EXISTS(E1_STEP)) #define HAS_E1_STEP (PIN_EXISTS(E1_STEP))
#define HAS_E2_STEP (PIN_EXISTS(E2_STEP)) #define HAS_E2_STEP (PIN_EXISTS(E2_STEP))
#define HAS_E3_STEP (PIN_EXISTS(E3_STEP)) #define HAS_E3_STEP (PIN_EXISTS(E3_STEP))
#define HAS_E4_STEP (PIN_EXISTS(E4_STEP)) #define HAS_E4_STEP (PIN_EXISTS(E4_STEP))
#define HAS_E5_STEP (PIN_EXISTS(E5_STEP)) #define HAS_E5_STEP (PIN_EXISTS(E5_STEP))
#define HAS_E0E1 (PIN_EXISTS(E0E1_CHOICE)) #define HAS_E0E1 (PIN_EXISTS(E0E1_CHOICE))
#define HAS_E0E2 (PIN_EXISTS(E0E2_CHOICE)) #define HAS_E0E2 (PIN_EXISTS(E0E2_CHOICE))
#define HAS_E0E3 (PIN_EXISTS(E0E3_CHOICE)) #define HAS_E0E3 (PIN_EXISTS(E0E3_CHOICE))
#define HAS_E0E4 (PIN_EXISTS(E0E4_CHOICE)) #define HAS_E0E4 (PIN_EXISTS(E0E4_CHOICE))
#define HAS_E0E5 (PIN_EXISTS(E0E5_CHOICE)) #define HAS_E0E5 (PIN_EXISTS(E0E5_CHOICE))
#define HAS_E1E3 (PIN_EXISTS(E1E3_CHOICE)) #define HAS_E1E3 (PIN_EXISTS(E1E3_CHOICE))
#define HAS_BTN_BACK (PIN_EXISTS(BTN_BACK)) #define HAS_BTN_BACK (PIN_EXISTS(BTN_BACK))
#define HAS_POWER_SWITCH (POWER_SUPPLY > 0 && PIN_EXISTS(PS_ON)) #define HAS_POWER_SWITCH (POWER_SUPPLY > 0 && PIN_EXISTS(PS_ON))
#define HAS_MOTOR_CURRENT_PWM_XY (PIN_EXISTS(MOTOR_CURRENT_PWM_XY)) #define HAS_MOTOR_CURRENT_PWM_XY (PIN_EXISTS(MOTOR_CURRENT_PWM_XY))
#define HAS_SDSUPPORT (ENABLED(SDSUPPORT)) #define HAS_SDSUPPORT (ENABLED(SDSUPPORT))
#define HAS_DIGIPOTSS (PIN_EXISTS(DIGIPOTSS)) #define HAS_DIGIPOTSS (PIN_EXISTS(DIGIPOTSS))
/** /**
* Shorthand for filament sensor and power sensor for ultralcd.cpp, dogm_lcd_implementation.h, ultralcd_implementation_hitachi_HD44780.h * Shorthand for filament sensor and power sensor for ultralcd.cpp, dogm_lcd_implementation.h, ultralcd_implementation_hitachi_HD44780.h
*/ */
#define HAS_LCD_FILAMENT_SENSOR (HAS_FILAMENT_SENSOR && ENABLED(FILAMENT_LCD_DISPLAY)) #define HAS_LCD_FILAMENT_SENSOR (HAS_FILAMENT_SENSOR && ENABLED(FILAMENT_LCD_DISPLAY))
#define HAS_LCD_POWER_SENSOR (HAS_POWER_CONSUMPTION_SENSOR && ENABLED(POWER_CONSUMPTION_LCD_DISPLAY)) #define HAS_LCD_POWER_SENSOR (HAS_POWER_CONSUMPTION_SENSOR && ENABLED(POWER_CONSUMPTION_LCD_DISPLAY))
/** /**
* Helper Macros for heaters and extruder fan and rele * Helper Macros for heaters and extruder fan and rele
*/ */
#if ENABLED(INVERTED_HEATER_PINS) #if ENABLED(INVERTED_HEATER_PINS)
#define WRITE_HEATER(pin, value) WRITE(pin, !value) #define WRITE_HEATER(pin, value) WRITE(pin, !value)
#else #else
#define WRITE_HEATER(pin, value) WRITE(pin, value) #define WRITE_HEATER(pin, value) WRITE(pin, value)
#endif #endif
#define WRITE_HEATER_0P(v) WRITE_HEATER(HEATER_0_PIN, v) #define WRITE_HEATER_0P(v) WRITE_HEATER(HEATER_0_PIN, v)
#if HOTENDS > 1 || ENABLED(HEATERS_PARALLEL) #if HOTENDS > 1 || ENABLED(HEATERS_PARALLEL)
#define WRITE_HEATER_1(v) WRITE_HEATER(HEATER_1_PIN, v) #define WRITE_HEATER_1(v) WRITE_HEATER(HEATER_1_PIN, v)
#if HOTENDS > 2 #if HOTENDS > 2
#define WRITE_HEATER_2(v) WRITE_HEATER(HEATER_2_PIN, v) #define WRITE_HEATER_2(v) WRITE_HEATER(HEATER_2_PIN, v)
...@@ -726,27 +757,27 @@ ...@@ -726,27 +757,27 @@
#define WRITE_HEATER_3(v) WRITE_HEATER(HEATER_3_PIN, v) #define WRITE_HEATER_3(v) WRITE_HEATER(HEATER_3_PIN, v)
#endif #endif
#endif #endif
#endif #endif
#if ENABLED(HEATERS_PARALLEL) #if ENABLED(HEATERS_PARALLEL)
#define WRITE_HEATER_0(v) { WRITE_HEATER_0P(v); WRITE_HEATER_1(v); } #define WRITE_HEATER_0(v) { WRITE_HEATER_0P(v); WRITE_HEATER_1(v); }
#else #else
#define WRITE_HEATER_0(v) WRITE_HEATER_0P(v) #define WRITE_HEATER_0(v) WRITE_HEATER_0P(v)
#endif #endif
#if HAS(HEATER_BED) #if HAS(HEATER_BED)
#if ENABLED(INVERTED_BED_PINS) #if ENABLED(INVERTED_BED_PINS)
#define WRITE_HEATER_BED(v) WRITE(HEATER_BED_PIN,!v) #define WRITE_HEATER_BED(v) WRITE(HEATER_BED_PIN,!v)
#else #else
#define WRITE_HEATER_BED(v) WRITE(HEATER_BED_PIN,v) #define WRITE_HEATER_BED(v) WRITE(HEATER_BED_PIN,v)
#endif #endif
#endif #endif
#if HAS(FAN) #if HAS(FAN)
#if ENABLED(INVERTED_HEATER_PINS) #if ENABLED(INVERTED_HEATER_PINS)
#define WRITE_FAN(v) WRITE(FAN_PIN, !v) #define WRITE_FAN(v) WRITE(FAN_PIN, !v)
#else #else
#define WRITE_FAN(v) WRITE(FAN_PIN, v) #define WRITE_FAN(v) WRITE(FAN_PIN, v)
#endif #endif
#endif #endif
#if ENABLED(MKR4) #if ENABLED(MKR4)
#if ENABLED(INVERTED_RELE_PINS) #if ENABLED(INVERTED_RELE_PINS)
#define WRITE_RELE(pin, value) WRITE(pin, !value) #define WRITE_RELE(pin, value) WRITE(pin, !value)
#define OUT_WRITE_RELE(pin, value) OUT_WRITE(pin, !value) #define OUT_WRITE_RELE(pin, value) OUT_WRITE(pin, !value)
...@@ -754,17 +785,17 @@ ...@@ -754,17 +785,17 @@
#define WRITE_RELE(pin, value) WRITE(pin, value) #define WRITE_RELE(pin, value) WRITE(pin, value)
#define OUT_WRITE_RELE(pin, value) OUT_WRITE(pin, value) #define OUT_WRITE_RELE(pin, value) OUT_WRITE(pin, value)
#endif #endif
#endif #endif
/** /**
* Buzzer * Buzzer
*/ */
#define HAS_BUZZER (PIN_EXISTS(BEEPER) || ENABLED(LCD_USE_I2C_BUZZER)) #define HAS_BUZZER (PIN_EXISTS(BEEPER) || ENABLED(LCD_USE_I2C_BUZZER))
/** /**
* Servos * Servos
*/ */
#if HAS(SERVOS) #if HAS(SERVOS)
#ifndef X_ENDSTOP_SERVO_NR #ifndef X_ENDSTOP_SERVO_NR
#define X_ENDSTOP_SERVO_NR -1 #define X_ENDSTOP_SERVO_NR -1
#endif #endif
...@@ -781,12 +812,11 @@ ...@@ -781,12 +812,11 @@
#define HAS_SERVO_ENDSTOPS true #define HAS_SERVO_ENDSTOPS true
#define SERVO_ENDSTOP_IDS { X_ENDSTOP_SERVO_NR, Y_ENDSTOP_SERVO_NR, Z_ENDSTOP_SERVO_NR } #define SERVO_ENDSTOP_IDS { X_ENDSTOP_SERVO_NR, Y_ENDSTOP_SERVO_NR, Z_ENDSTOP_SERVO_NR }
#endif #endif
#endif #endif
/** /**
* The axis order in all axis related arrays is X, Y, Z, E * The axis order in all axis related arrays is X, Y, Z, E
*/ */
#define NUM_AXIS 4 #define NUM_AXIS 4
#endif //CONDITIONALS_H #endif //CONDITIONALS_H
...@@ -101,6 +101,9 @@ ...@@ -101,6 +101,9 @@
#define SERIAL_COUNT_X " Count X: " #define SERIAL_COUNT_X " Count X: "
#define SERIAL_ERR_KILLED "Printer halted. kill() called!" #define SERIAL_ERR_KILLED "Printer halted. kill() called!"
#define SERIAL_ERR_STOPPED "Printer stopped due to errors. Fix the error and use M999 to restart. (Temperature is reset. Set it after restarting)" #define SERIAL_ERR_STOPPED "Printer stopped due to errors. Fix the error and use M999 to restart. (Temperature is reset. Set it after restarting)"
#define SERIAL_BUSY_PROCESSING "processing"
#define SERIAL_BUSY_PAUSED_FOR_USER "paused for user"
#define SERIAL_BUSY_PAUSED_FOR_INPUT "paused for input"
#define SERIAL_UNKNOWN_COMMAND "Unknown command: \"" #define SERIAL_UNKNOWN_COMMAND "Unknown command: \""
#define SERIAL_ACTIVE_DRIVER "Active Driver: " #define SERIAL_ACTIVE_DRIVER "Active Driver: "
#define SERIAL_ACTIVE_EXTRUDER "Active Extruder: " #define SERIAL_ACTIVE_EXTRUDER "Active Extruder: "
......
/**
* MK 3D Printer Firmware
*
* Based on Marlin, Sprinter and grbl
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
* Copyright (C) 2013 - 2016 Alberto Cotronei @MagoKimbra
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/** /**
* dogm_lcd_implementation.h * dogm_lcd_implementation.h
* *
...@@ -7,7 +29,7 @@ ...@@ -7,7 +29,7 @@
* *
* With the use of: * With the use of:
* u8glib by Oliver Kraus * u8glib by Oliver Kraus
* http://code.google.com/p/u8glib/ * https://github.com/olikraus/U8glib_Arduino
* License: http://opensource.org/licenses/BSD-3-Clause * License: http://opensource.org/licenses/BSD-3-Clause
*/ */
...@@ -173,7 +195,7 @@ char lcd_print(char c) { ...@@ -173,7 +195,7 @@ char lcd_print(char c) {
return charset_mapper(c); return charset_mapper(c);
} }
char lcd_print(char* str) { char lcd_print(const char* str) {
char c; char c;
int i = 0; int i = 0;
char n = 0; char n = 0;
...@@ -228,14 +250,14 @@ static void lcd_implementation_init() { ...@@ -228,14 +250,14 @@ static void lcd_implementation_init() {
#endif #endif
#if ENABLED(SHOW_BOOTSCREEN) #if ENABLED(SHOW_BOOTSCREEN)
int offx = (u8g.getWidth() - START_BMPWIDTH) / 2; int offx = (u8g.getWidth() - (START_BMPWIDTH)) / 2;
#if ENABLED(START_BMPHIGH) #if ENABLED(START_BMPHIGH)
int offy = 0; int offy = 0;
#else #else
int offy = DOG_CHAR_HEIGHT; int offy = DOG_CHAR_HEIGHT;
#endif #endif
int txt1X = (u8g.getWidth() - (sizeof(STRING_SPLASH_LINE1) - 1) * DOG_CHAR_WIDTH) / 2; int txt1X = (u8g.getWidth() - (sizeof(STRING_SPLASH_LINE1) - 1) * (DOG_CHAR_WIDTH)) / 2;
u8g.firstPage(); u8g.firstPage();
do { do {
...@@ -243,11 +265,11 @@ static void lcd_implementation_init() { ...@@ -243,11 +265,11 @@ static void lcd_implementation_init() {
u8g.drawBitmapP(offx, offy, START_BMPBYTEWIDTH, START_BMPHEIGHT, start_bmp); u8g.drawBitmapP(offx, offy, START_BMPBYTEWIDTH, START_BMPHEIGHT, start_bmp);
lcd_setFont(FONT_MENU); lcd_setFont(FONT_MENU);
#if DISABLED(STRING_SPLASH_LINE2) #if DISABLED(STRING_SPLASH_LINE2)
u8g.drawStr(txt1X, u8g.getHeight() - DOG_CHAR_HEIGHT, STRING_SPLASH_LINE1); u8g.drawStr(txt1X, u8g.getHeight() - (DOG_CHAR_HEIGHT), STRING_SPLASH_LINE1);
#else #else
int txt2X = (u8g.getWidth() - (sizeof(STRING_SPLASH_LINE2) - 1) * DOG_CHAR_WIDTH) / 2; int txt2X = (u8g.getWidth() - (sizeof(STRING_SPLASH_LINE2) - 1) * (DOG_CHAR_WIDTH)) / 2;
u8g.drawStr(txt1X, u8g.getHeight() - DOG_CHAR_HEIGHT * 3 / 2, STRING_SPLASH_LINE1); u8g.drawStr(txt1X, u8g.getHeight() - (DOG_CHAR_HEIGHT) * 3 / 2, STRING_SPLASH_LINE1);
u8g.drawStr(txt2X, u8g.getHeight() - DOG_CHAR_HEIGHT * 1 / 2, STRING_SPLASH_LINE2); u8g.drawStr(txt2X, u8g.getHeight() - (DOG_CHAR_HEIGHT) * 1 / 2, STRING_SPLASH_LINE2);
#endif #endif
} }
} while (u8g.nextPage()); } while (u8g.nextPage());
...@@ -261,6 +283,13 @@ static void lcd_implementation_init() { ...@@ -261,6 +283,13 @@ static void lcd_implementation_init() {
static void lcd_implementation_clear() { } // Automatically cleared by Picture Loop static void lcd_implementation_clear() { } // Automatically cleared by Picture Loop
FORCE_INLINE void _draw_centered_temp(int temp, int x, int y) {
int degsize = 6 * (temp >= 100 ? 3 : temp >= 10 ? 2 : 1); // number's pixel width
u8g.setPrintPos(x - (18 - degsize) / 2, y); // move left if shorter
lcd_print(itostr3(temp));
lcd_printPGM(PSTR(LCD_STR_DEGREE " "));
}
static void _draw_heater_status(int x, int heater) { static void _draw_heater_status(int x, int heater) {
bool isBed = heater < 0; bool isBed = heater < 0;
int y = 17 + (isBed ? 1 : 0); int y = 17 + (isBed ? 1 : 0);
...@@ -321,29 +350,30 @@ static void lcd_implementation_status_screen() { ...@@ -321,29 +350,30 @@ static void lcd_implementation_status_screen() {
// Symbols menu graphics, animated fan // Symbols menu graphics, animated fan
u8g.drawBitmapP(9, 1, STATUS_SCREENBYTEWIDTH, STATUS_SCREENHEIGHT, (blink % 2) && fanSpeed ? status_screen0_bmp : status_screen1_bmp); u8g.drawBitmapP(9, 1, STATUS_SCREENBYTEWIDTH, STATUS_SCREENHEIGHT, (blink % 2) && fanSpeed ? status_screen0_bmp : status_screen1_bmp);
// Status Menu Font for SD info, Heater status, Fan, XYZ
lcd_setFont(FONT_STATUSMENU);
#if ENABLED(SDSUPPORT) #if ENABLED(SDSUPPORT)
// SD Card Symbol // SD Card Symbol
u8g.drawBox(42, 42 - TALL_FONT_CORRECTION, 8, 7); u8g.drawBox(42, 42 - (TALL_FONT_CORRECTION), 8, 7);
u8g.drawBox(50, 44 - TALL_FONT_CORRECTION, 2, 5); u8g.drawBox(50, 44 - (TALL_FONT_CORRECTION), 2, 5);
u8g.drawFrame(42, 49 - TALL_FONT_CORRECTION, 10, 4); u8g.drawFrame(42, 49 - (TALL_FONT_CORRECTION), 10, 4);
u8g.drawPixel(50, 43 - TALL_FONT_CORRECTION); u8g.drawPixel(50, 43 - (TALL_FONT_CORRECTION));
// Progress bar frame // Progress bar frame
u8g.drawFrame(54, 49, 73, 4 - TALL_FONT_CORRECTION); u8g.drawFrame(54, 49, 73, 4 - (TALL_FONT_CORRECTION));
// SD Card Progress bar and clock // SD Card Progress bar and clock
lcd_setFont(FONT_STATUSMENU);
if (IS_SD_PRINTING) { if (IS_SD_PRINTING) {
// Progress bar solid part // Progress bar solid part
u8g.drawBox(55, 50, (unsigned int)(71.f * card.percentDone() / 100.f), 2 - TALL_FONT_CORRECTION); u8g.drawBox(55, 50, (unsigned int)(71.f * card.percentDone() / 100.f), 2 - (TALL_FONT_CORRECTION));
} }
u8g.setPrintPos(53, 47); u8g.setPrintPos(53, 47);
if (print_job_start_ms != 0) { uint16_t time = print_job_timer.duration() / 60;
if (time != 0) {
#if HAS(LCD_POWER_SENSOR) #if HAS(LCD_POWER_SENSOR)
if (millis() < print_millis + 1000) { if (millis() < print_millis + 1000) {
uint16_t time = (millis() - print_job_start_ms) / 60000;
uint16_t end_time = (time * (100 - card.percentDone())) / card.percentDone(); uint16_t end_time = (time * (100 - card.percentDone())) / card.percentDone();
lcd_print('S'); lcd_print('S');
lcd_print(itostr2(time/60)); lcd_print(itostr2(time/60));
...@@ -356,9 +386,9 @@ static void lcd_implementation_status_screen() { ...@@ -356,9 +386,9 @@ static void lcd_implementation_status_screen() {
u8g.print('E--:--'); u8g.print('E--:--');
else if (end_time > 0) { else if (end_time > 0) {
u8g.print('E'); u8g.print('E');
u8g.print(itostr2(end_time / 60)); u8g.print(itostr2(end_time/60));
u8g.print(':'); u8g.print(':');
u8g.print(itostr2(end_time %60)); u8g.print(itostr2(end_time%60));
} }
} }
else { else {
...@@ -366,12 +396,11 @@ static void lcd_implementation_status_screen() { ...@@ -366,12 +396,11 @@ static void lcd_implementation_status_screen() {
lcd_print((char*)"Wh"); lcd_print((char*)"Wh");
} }
#else #else
uint16_t time = (millis() - print_job_start_ms) / 60000;
uint16_t end_time = (time * (100 - card.percentDone())) / card.percentDone(); uint16_t end_time = (time * (100 - card.percentDone())) / card.percentDone();
lcd_print('S'); lcd_print('S');
lcd_print(itostr2(time / 60)); lcd_print(itostr2(time/60));
lcd_print(':'); lcd_print(':');
lcd_print(itostr2(time %60)); lcd_print(itostr2(time%60));
u8g.setPrintPos(90, 47); u8g.setPrintPos(90, 47);
...@@ -379,9 +408,9 @@ static void lcd_implementation_status_screen() { ...@@ -379,9 +408,9 @@ static void lcd_implementation_status_screen() {
u8g.print('E--:--'); u8g.print('E--:--');
else if (end_time > 0) { else if (end_time > 0) {
u8g.print('E'); u8g.print('E');
u8g.print(itostr2(end_time / 60)); u8g.print(itostr2(end_time/60));
u8g.print(':'); u8g.print(':');
u8g.print(itostr2(end_time %60)); u8g.print(itostr2(end_time%60));
} }
#endif #endif
} }
...@@ -395,11 +424,12 @@ static void lcd_implementation_status_screen() { ...@@ -395,11 +424,12 @@ static void lcd_implementation_status_screen() {
// Hotends // Hotends
for (int i = 0; i < HOTENDS; i++) _draw_heater_status(6 + i * 25, i); for (int i = 0; i < HOTENDS; i++) _draw_heater_status(6 + i * 25, i);
// Heatbed // Heated bed
if (HOTENDS < 4) _draw_heater_status(81, -1); #if HOTENDS < 4 && HAS(TEMP_BED)
_draw_heater_status(81, -1);
#endif
// Fan // Fan
lcd_setFont(FONT_STATUSMENU);
u8g.setPrintPos(104, 27); u8g.setPrintPos(104, 27);
#if HAS(FAN) #if HAS(FAN)
int per = ((fanSpeed + 1) * 100) / 256; int per = ((fanSpeed + 1) * 100) / 256;
...@@ -407,17 +437,13 @@ static void lcd_implementation_status_screen() { ...@@ -407,17 +437,13 @@ static void lcd_implementation_status_screen() {
lcd_print(itostr3(per)); lcd_print(itostr3(per));
lcd_print('%'); lcd_print('%');
} }
else
#endif #endif
{
lcd_printPGM(PSTR("---"));
}
// Print XYZ Coordinates // X, Y, Z-Coordinates
// If the axis was not homed, show "---" // Before homing the axis letters are blinking 'X' <-> '?'.
// If the position is untrusted, show "?" // When axis is homed but axis_known_position is false the axis letters are blinking 'X' <-> ' '.
// When everything is ok you see a constant 'X'.
#define XYZ_BASELINE 38 #define XYZ_BASELINE 38
lcd_setFont(FONT_STATUSMENU);
#if ENABLED(USE_SMALL_INFOFONT) #if ENABLED(USE_SMALL_INFOFONT)
u8g.drawBox(0, 30, LCD_PIXEL_WIDTH, 10); u8g.drawBox(0, 30, LCD_PIXEL_WIDTH, 10);
...@@ -461,20 +487,20 @@ static void lcd_implementation_status_screen() { ...@@ -461,20 +487,20 @@ static void lcd_implementation_status_screen() {
lcd_setFont(FONT_MENU); lcd_setFont(FONT_MENU);
u8g.setPrintPos(3, 49); u8g.setPrintPos(3, 49);
lcd_print(LCD_STR_FEEDRATE[0]); lcd_print(LCD_STR_FEEDRATE[0]);
lcd_setFont(FONT_STATUSMENU); lcd_setFont(FONT_STATUSMENU);
u8g.setPrintPos(12, 49); u8g.setPrintPos(12, 49);
lcd_print(itostr3(feedrate_multiplier)); lcd_print(itostr3(feedrate_multiplier));
lcd_print('%'); lcd_print('%');
// Status line // Status line
lcd_setFont(FONT_STATUSMENU);
#if ENABLED(USE_SMALL_INFOFONT) #if ENABLED(USE_SMALL_INFOFONT)
u8g.setPrintPos(0, 62); u8g.setPrintPos(0, 62);
#else #else
u8g.setPrintPos(0, 63); u8g.setPrintPos(0, 63);
#endif #endif
#if HAS(LCD_FILAMENT_SENSOR) || HAS(LCD_POWER_SENSOR) #if HAS(LCD_FILAMENT_SENSOR) || HAS(LCD_POWER_SENSOR)
if (millis() < previous_lcd_status_ms + 5000) //Display both Status message line and Filament display on the last line if (PENDING(millis(), previous_lcd_status_ms + 5000UL)) { //Display both Status message line and Filament display on the last line
lcd_print(lcd_status_message); lcd_print(lcd_status_message);
#if HAS(LCD_POWER_SENSOR) #if HAS(LCD_POWER_SENSOR)
#if HAS(LCD_FILAMENT_SENSOR) #if HAS(LCD_FILAMENT_SENSOR)
...@@ -507,13 +533,13 @@ static void lcd_implementation_status_screen() { ...@@ -507,13 +533,13 @@ static void lcd_implementation_status_screen() {
static void lcd_implementation_mark_as_selected(uint8_t row, bool isSelected) { static void lcd_implementation_mark_as_selected(uint8_t row, bool isSelected) {
if (isSelected) { if (isSelected) {
u8g.setColorIndex(1); // black on white u8g.setColorIndex(1); // black on white
u8g.drawBox(0, row * DOG_CHAR_HEIGHT + 3 - TALL_FONT_CORRECTION, LCD_PIXEL_WIDTH, DOG_CHAR_HEIGHT); u8g.drawBox(0, row * (DOG_CHAR_HEIGHT) + 3 - (TALL_FONT_CORRECTION), LCD_PIXEL_WIDTH, DOG_CHAR_HEIGHT);
u8g.setColorIndex(0); // following text must be white on black u8g.setColorIndex(0); // following text must be white on black
} }
else { else {
u8g.setColorIndex(1); // unmarked text is black on white u8g.setColorIndex(1); // unmarked text is black on white
} }
u8g.setPrintPos(START_ROW * DOG_CHAR_WIDTH, (row + 1) * DOG_CHAR_HEIGHT); u8g.setPrintPos((START_ROW) * (DOG_CHAR_WIDTH), (row + 1) * (DOG_CHAR_HEIGHT));
} }
static void lcd_implementation_drawmenu_generic(bool isSelected, uint8_t row, const char* pstr, char pre_char, char post_char) { static void lcd_implementation_drawmenu_generic(bool isSelected, uint8_t row, const char* pstr, char pre_char, char post_char) {
...@@ -527,7 +553,7 @@ static void lcd_implementation_drawmenu_generic(bool isSelected, uint8_t row, co ...@@ -527,7 +553,7 @@ static void lcd_implementation_drawmenu_generic(bool isSelected, uint8_t row, co
pstr++; pstr++;
} }
while (n--) lcd_print(' '); while (n--) lcd_print(' ');
u8g.setPrintPos(LCD_PIXEL_WIDTH - DOG_CHAR_WIDTH, (row + 1) * DOG_CHAR_HEIGHT); u8g.setPrintPos(LCD_PIXEL_WIDTH - (DOG_CHAR_WIDTH), (row + 1) * (DOG_CHAR_HEIGHT));
lcd_print(post_char); lcd_print(post_char);
lcd_print(' '); lcd_print(' ');
} }
...@@ -545,7 +571,7 @@ static void _drawmenu_setting_edit_generic(bool isSelected, uint8_t row, const c ...@@ -545,7 +571,7 @@ static void _drawmenu_setting_edit_generic(bool isSelected, uint8_t row, const c
} }
lcd_print(':'); lcd_print(':');
while (n--) lcd_print(' '); while (n--) lcd_print(' ');
u8g.setPrintPos(LCD_PIXEL_WIDTH - DOG_CHAR_WIDTH * vallen, (row + 1) * DOG_CHAR_HEIGHT); u8g.setPrintPos(LCD_PIXEL_WIDTH - (DOG_CHAR_WIDTH) * vallen, (row + 1) * (DOG_CHAR_HEIGHT));
if (pgm) lcd_printPGM(data); else lcd_print((char*)data); if (pgm) lcd_printPGM(data); else lcd_print((char*)data);
} }
...@@ -592,14 +618,16 @@ void lcd_implementation_drawedit(const char* pstr, char* value) { ...@@ -592,14 +618,16 @@ void lcd_implementation_drawedit(const char* pstr, char* value) {
if (lcd_strlen_P(pstr) > LCD_WIDTH - 2 - vallen) rows = 2; if (lcd_strlen_P(pstr) > LCD_WIDTH - 2 - vallen) rows = 2;
const float kHalfChar = DOG_CHAR_HEIGHT_EDIT / 2; const float kHalfChar = (DOG_CHAR_HEIGHT_EDIT) / 2;
float rowHeight = u8g.getHeight() / (rows + 1); // 1/(rows+1) = 1/2 or 1/3 float rowHeight = u8g.getHeight() / (rows + 1); // 1/(rows+1) = 1/2 or 1/3
u8g.setPrintPos(0, rowHeight + kHalfChar); u8g.setPrintPos(0, rowHeight + kHalfChar);
lcd_printPGM(pstr); lcd_printPGM(pstr);
if (value != NULL) {
lcd_print(':'); lcd_print(':');
u8g.setPrintPos((lcd_width - 1 - vallen) * char_width, rows * rowHeight + kHalfChar); u8g.setPrintPos((lcd_width - 1 - vallen) * char_width, rows * rowHeight + kHalfChar);
lcd_print(value); lcd_print(value);
}
} }
#if ENABLED(SDSUPPORT) #if ENABLED(SDSUPPORT)
......
...@@ -490,7 +490,7 @@ static void lcd_main_menu() { ...@@ -490,7 +490,7 @@ static void lcd_main_menu() {
*/ */
void lcd_set_home_offsets() { void lcd_set_home_offsets() {
// M428 Command // M428 Command
enqueuecommands_P(PSTR("M428")); enqueue_and_echo_commands_P(PSTR("M428"));
lcd_return_to_status(); lcd_return_to_status();
} }
...@@ -513,9 +513,9 @@ void lcd_set_home_offsets() { ...@@ -513,9 +513,9 @@ void lcd_set_home_offsets() {
static void lcd_tune_fixstep() { static void lcd_tune_fixstep() {
#if MECH(DELTA) #if MECH(DELTA)
enqueuecommands_P(PSTR("G28 B")); enqueue_and_echo_commands_P(PSTR("G28 B"));
#else #else
enqueuecommands_P(PSTR("G28 X Y B")); enqueue_and_echo_commands_P(PSTR("G28 X Y B"));
#endif #endif
} }
...@@ -1654,7 +1654,7 @@ menu_edit_type(unsigned long, long5, ftostr5, 0.01) ...@@ -1654,7 +1654,7 @@ menu_edit_type(unsigned long, long5, ftostr5, 0.01)
lcd_move_y(); lcd_move_y();
} }
static void reprapworld_keypad_move_home() { static void reprapworld_keypad_move_home() {
enqueuecommands_P((PSTR("G28"))); // move all axis home enqueue_and_echo_commands_P((PSTR("G28"))); // move all axis home
} }
#endif // REPRAPWORLD_KEYPAD #endif // REPRAPWORLD_KEYPAD
...@@ -1706,7 +1706,7 @@ void lcd_quick_feedback() { ...@@ -1706,7 +1706,7 @@ void lcd_quick_feedback() {
*/ */
static void menu_action_back(menuFunc_t func) { lcd_goto_menu(func); } static void menu_action_back(menuFunc_t func) { lcd_goto_menu(func); }
static void menu_action_submenu(menuFunc_t func) { lcd_goto_menu(func); } static void menu_action_submenu(menuFunc_t func) { lcd_goto_menu(func); }
static void menu_action_gcode(const char* pgcode) { enqueuecommands_P(pgcode); } static void menu_action_gcode(const char* pgcode) { enqueue_and_echo_commands_P(pgcode); }
static void menu_action_function(menuFunc_t func) { (*func)(); } static void menu_action_function(menuFunc_t func) { (*func)(); }
#if ENABLED(SDSUPPORT) #if ENABLED(SDSUPPORT)
...@@ -1716,8 +1716,8 @@ static void menu_action_function(menuFunc_t func) { (*func)(); } ...@@ -1716,8 +1716,8 @@ static void menu_action_function(menuFunc_t func) { (*func)(); }
char* c; char* c;
sprintf_P(cmd, PSTR("M23 %s"), longFilename); sprintf_P(cmd, PSTR("M23 %s"), longFilename);
for (c = &cmd[4]; *c; c++) *c = tolower(*c); for (c = &cmd[4]; *c; c++) *c = tolower(*c);
enqueuecommand(cmd); enqueue_and_echo_command(cmd);
enqueuecommands_P(PSTR("M24")); enqueue_and_echo_commands_P(PSTR("M24"));
lcd_return_to_status(); lcd_return_to_status();
} }
...@@ -2482,7 +2482,7 @@ char* ftostr52(const float& x) { ...@@ -2482,7 +2482,7 @@ char* ftostr52(const float& x) {
LCD_Printpos(0, 0); lcd_printPGM(PSTR(MSG_MBL_6)); LCD_Printpos(0, 0); lcd_printPGM(PSTR(MSG_MBL_6));
LCD_Printpos(0, 1); lcd_printPGM(PSTR(" ")); LCD_Printpos(0, 1); lcd_printPGM(PSTR(" "));
HAL::delayMilliseconds(5000); HAL::delayMilliseconds(5000);
enqueuecommands_P(PSTR("G28")); enqueue_and_echo_commands_P(PSTR("G28"));
lcd_goto_menu(lcd_prepare_menu); lcd_goto_menu(lcd_prepare_menu);
} }
break; break;
...@@ -2491,7 +2491,7 @@ char* ftostr52(const float& x) { ...@@ -2491,7 +2491,7 @@ char* ftostr52(const float& x) {
static void config_lcd_level_bed() { static void config_lcd_level_bed() {
ECHO_EM(MSG_MBL_SETTING); ECHO_EM(MSG_MBL_SETTING);
enqueuecommands_P(PSTR("G28 M")); enqueue_and_echo_commands_P(PSTR("G28 M"));
pageShowInfo = 0; pageShowInfo = 0;
lcd_goto_menu(lcd_level_bed); lcd_goto_menu(lcd_level_bed);
} }
......
...@@ -726,11 +726,11 @@ static void lcd_implementation_status_screen() { ...@@ -726,11 +726,11 @@ static void lcd_implementation_status_screen() {
#endif // LCD_WIDTH > 19 && SDSUPPORT #endif // LCD_WIDTH > 19 && SDSUPPORT
lcd.setCursor(LCD_WIDTH - 6, 2); lcd.setCursor(LCD_WIDTH - 6, 2);
if(print_job_start_ms != 0) { uint16_t time = print_job_timer.duration() / 60;
if(time != 0) {
#if HAS(LCD_POWER_SENSOR) #if HAS(LCD_POWER_SENSOR)
if (millis() < print_millis + 1000) { if (millis() < print_millis + 1000) {
lcd.print(LCD_STR_CLOCK[0]); lcd.print(LCD_STR_CLOCK[0]);
uint16_t time = millis()/60000 - print_job_start_ms/60000;
lcd.print(itostr2(time/60)); lcd.print(itostr2(time/60));
lcd.print(':'); lcd.print(':');
lcd.print(itostr2(time%60)); lcd.print(itostr2(time%60));
...@@ -741,7 +741,6 @@ static void lcd_implementation_status_screen() { ...@@ -741,7 +741,6 @@ static void lcd_implementation_status_screen() {
} }
#else #else
lcd.print(LCD_STR_CLOCK[0]); lcd.print(LCD_STR_CLOCK[0]);
uint16_t time = millis()/60000 - print_job_start_ms/60000;
lcd.print(itostr2(time/60)); lcd.print(itostr2(time/60));
lcd.print(':'); lcd.print(':');
lcd.print(itostr2(time%60)); lcd.print(itostr2(time%60));
......
...@@ -25,11 +25,18 @@ ...@@ -25,11 +25,18 @@
// Macros to support option testing // Macros to support option testing
#define ENABLED defined #define ENABLED defined
#define DISABLED !defined #define DISABLED !defined
#define PIN_EXISTS(PN) (defined(PN##_PIN) && PN##_PIN >= 0) #define PIN_EXISTS(PN) (defined(PN##_PIN) && PN##_PIN >= 0)
#define HAS(FE) (HAS_##FE) #define HAS(FE) (HAS_##FE)
#define HASNT(FE) (!(HAS_##FE)) #define HASNT(FE) (!(HAS_##FE))
#define PENDING(NOW,SOON) ((long)(NOW-(SOON))<0)
#define ELAPSED(NOW,SOON) (!PENDING(NOW,SOON))
// Macros to contrain values // Macros to contrain values
#define NUMERIC(a) ((a) >= '0' && '9' >= (a))
#define NUMERIC_SIGNED(a) (NUMERIC(a) || (a) == '-')
#define NOLESS(v,n) do{ if (v < n) v = n; }while(0) #define NOLESS(v,n) do{ if (v < n) v = n; }while(0)
#define NOMORE(v,n) do{ if (v > n) v = n; }while(0) #define NOMORE(v,n) do{ if (v > n) v = n; }while(0)
#define COUNT(a) (sizeof(a)/sizeof(*a)) #define COUNT(a) (sizeof(a)/sizeof(*a))
......
...@@ -242,7 +242,7 @@ ...@@ -242,7 +242,7 @@
//=========================================================================== //===========================================================================
void ZWobble::setSample(float zRod, float zActual) { void ZWobble::setSample(float zRod, float zActual) {
if (debugLevel & DEBUG_DEBUG) { if (DEBUGGING(DEBUG)) {
ECHO_SMV(DB, "New sample Rod: ", zRod); ECHO_SMV(DB, "New sample Rod: ", zRod);
ECHO_EMV(" Act: ", zActual); ECHO_EMV(" Act: ", zActual);
} }
...@@ -446,7 +446,7 @@ ...@@ -446,7 +446,7 @@
if (originZ < ZWOBBLE_MIN_Z || targetZ < ZWOBBLE_MIN_Z) return; if (originZ < ZWOBBLE_MIN_Z || targetZ < ZWOBBLE_MIN_Z) return;
if (debugLevel & DEBUG_DEBUG) { if (DEBUGGING(DEBUG)) {
ECHO_SMV(DB, "Origin: ", originZ); ECHO_SMV(DB, "Origin: ", originZ);
ECHO_MV(" Target: ", targetZ); ECHO_MV(" Target: ", targetZ);
} }
...@@ -461,18 +461,18 @@ ...@@ -461,18 +461,18 @@
else else
originZRod = findZRod(originZ); originZRod = findZRod(originZ);
if (debugLevel & DEBUG_DEBUG) if (DEBUGGING(DEBUG))
ECHO_MV(" Origin rod: ", originZRod); ECHO_MV(" Origin rod: ", originZRod);
float targetZRod = findZRod(targetZ); float targetZRod = findZRod(targetZ);
if (debugLevel & DEBUG_DEBUG) if (DEBUGGING(DEBUG))
ECHO_MV(" Target Rod: ", targetZRod); ECHO_MV(" Target Rod: ", targetZRod);
// difference in steps between the correct movement (originZRod->targetZRod) and the planned movement // difference in steps between the correct movement (originZRod->targetZRod) and the planned movement
long stepDiff = lround((targetZRod - originZRod) * axis_steps_per_unit[Z_AXIS]) - (lround(targetZ * axis_steps_per_unit[Z_AXIS]) - position[Z_AXIS]); long stepDiff = lround((targetZRod - originZRod) * axis_steps_per_unit[Z_AXIS]) - (lround(targetZ * axis_steps_per_unit[Z_AXIS]) - position[Z_AXIS]);
if (debugLevel & DEBUG_DEBUG) if (DEBUGGING(DEBUG))
ECHO_EMV(" stepDiff: ", stepDiff); ECHO_EMV(" stepDiff: ", stepDiff);
lastZ = targetZ; lastZ = targetZ;
......
...@@ -552,7 +552,7 @@ float junction_deviation = 0.1; ...@@ -552,7 +552,7 @@ float junction_deviation = 0.1;
if (extruder != 1) if (extruder != 1)
#endif #endif
{ {
if (degHotend(extruder) < extrude_min_temp && !(debugLevel & DEBUG_DRYRUN)) { if (degHotend(extruder) < extrude_min_temp && !(DEBUGGING(DRYRUN))) {
position[E_AXIS] = target[E_AXIS]; //behave as if the move really took place, but ignore E part position[E_AXIS] = target[E_AXIS]; //behave as if the move really took place, but ignore E part
de = 0; // no difference de = 0; // no difference
ECHO_LM(ER, SERIAL_ERR_COLD_EXTRUDE_STOP); ECHO_LM(ER, SERIAL_ERR_COLD_EXTRUDE_STOP);
......
...@@ -636,7 +636,7 @@ ISR(TIMER1_COMPA_vect) { ...@@ -636,7 +636,7 @@ ISR(TIMER1_COMPA_vect) {
current_block = NULL; current_block = NULL;
plan_discard_current_block(); plan_discard_current_block();
#if ENABLED(SD_FINISHED_RELEASECOMMAND) #if ENABLED(SD_FINISHED_RELEASECOMMAND)
if ((cleaning_buffer_counter == 1) && (SD_FINISHED_STEPPERRELEASE)) enqueuecommands_P(PSTR(SD_FINISHED_RELEASECOMMAND)); if ((cleaning_buffer_counter == 1) && (SD_FINISHED_STEPPERRELEASE)) enqueue_and_echo_commands_P(PSTR(SD_FINISHED_RELEASECOMMAND));
#endif #endif
cleaning_buffer_counter--; cleaning_buffer_counter--;
OCR1A = 200; OCR1A = 200;
......
...@@ -276,8 +276,8 @@ ...@@ -276,8 +276,8 @@
char* c; char* c;
sprintf_P(cmd, PSTR("M23 %s"), filename); sprintf_P(cmd, PSTR("M23 %s"), filename);
for(c = &cmd[4]; *c; c++) *c = tolower(*c); for(c = &cmd[4]; *c; c++) *c = tolower(*c);
enqueuecommand(cmd); enqueue_and_echo_command(cmd);
enqueuecommands_P(PSTR("M24")); enqueue_and_echo_commands_P(PSTR("M24"));
setpageInfo(); setpageInfo();
} }
...@@ -428,14 +428,14 @@ ...@@ -428,14 +428,14 @@
void sethotPopCallback(void *ptr) { void sethotPopCallback(void *ptr) {
memset(buffer, 0, sizeof(buffer)); memset(buffer, 0, sizeof(buffer));
set1.getText(buffer, sizeof(buffer)); set1.getText(buffer, sizeof(buffer));
enqueuecommands_P(buffer); enqueue_and_echo_commands_P(buffer);
setpageInfo(); setpageInfo();
} }
void setgcodePopCallback(void *ptr) { void setgcodePopCallback(void *ptr) {
memset(buffer, 0, sizeof(buffer)); memset(buffer, 0, sizeof(buffer));
Tgcode.getText(buffer, sizeof(buffer)); Tgcode.getText(buffer, sizeof(buffer));
enqueuecommands_P(buffer); enqueue_and_echo_commands_P(buffer);
Pmenu.show(); Pmenu.show();
} }
...@@ -453,9 +453,9 @@ ...@@ -453,9 +453,9 @@
void setmovePopCallback(void *ptr) { void setmovePopCallback(void *ptr) {
memset(buffer, 0, sizeof(buffer)); memset(buffer, 0, sizeof(buffer));
movecmd.getText(buffer, sizeof(buffer)); movecmd.getText(buffer, sizeof(buffer));
enqueuecommands_P(PSTR("G91")); enqueue_and_echo_commands_P(PSTR("G91"));
enqueuecommands_P(buffer); enqueue_and_echo_commands_P(buffer);
enqueuecommands_P(PSTR("G90")); enqueue_and_echo_commands_P(PSTR("G90"));
} }
#if ENABLED(SDSUPPORT) #if ENABLED(SDSUPPORT)
...@@ -647,7 +647,7 @@ ...@@ -647,7 +647,7 @@
NPlay.setPic(17); NPlay.setPic(17);
// Estimate End Time // Estimate End Time
uint16_t time = (millis() - print_job_start_ms) / 60000; uint16_t time = print_job_timer.duration() / 60;
uint16_t end_time = (time * (100 - card.percentDone())) / card.percentDone(); uint16_t end_time = (time * (100 - card.percentDone())) / card.percentDone();
if (end_time > (60 * 23)) { if (end_time > (60 * 23)) {
lcd_setstatus("End --:--"); lcd_setstatus("End --:--");
......
...@@ -320,7 +320,7 @@ void CardReader::printingHasFinished() { ...@@ -320,7 +320,7 @@ void CardReader::printingHasFinished() {
sdprinting = false; sdprinting = false;
if (SD_FINISHED_STEPPERRELEASE) { if (SD_FINISHED_STEPPERRELEASE) {
//finishAndDisableSteppers(); //finishAndDisableSteppers();
enqueuecommands_P(PSTR(SD_FINISHED_RELEASECOMMAND)); enqueue_and_echo_commands_P(PSTR(SD_FINISHED_RELEASECOMMAND));
} }
autotempShutdown(); autotempShutdown();
} }
......
/**
* MK 3D Printer Firmware
*
* Based on Marlin, Sprinter and grbl
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
* Copyright (C) 2013 - 2016 Alberto Cotronei @MagoKimbra
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "../../base.h"
#include "stopwatch.h"
Stopwatch::Stopwatch() {
this->reset();
}
void Stopwatch::stop() {
#if ENABLED(DEBUG_STOPWATCH)
debug(PSTR("stop"));
#endif
if (!this->isRunning()) return;
this->status = STPWTCH_STOPPED;
this->stopTimestamp = millis();
}
void Stopwatch::pause() {
#if ENABLED(DEBUG_STOPWATCH)
debug(PSTR("pause"));
#endif
if (!this->isRunning()) return;
this->status = STPWTCH_PAUSED;
this->stopTimestamp = millis();
}
void Stopwatch::start() {
#if ENABLED(DEBUG_STOPWATCH)
debug(PSTR("start"));
#endif
if (this->isRunning()) return;
if (this->isPaused()) this->accumulator = this->duration();
else this->reset();
this->status = STPWTCH_RUNNING;
this->startTimestamp = millis();
}
void Stopwatch::reset() {
#if ENABLED(DEBUG_STOPWATCH)
debug(PSTR("reset"));
#endif
this->status = STPWTCH_STOPPED;
this->startTimestamp = 0;
this->stopTimestamp = 0;
this->accumulator = 0;
}
bool Stopwatch::isRunning() {
return (this->status == STPWTCH_RUNNING) ? true : false;
}
bool Stopwatch::isPaused() {
return (this->status == STPWTCH_PAUSED) ? true : false;
}
uint16_t Stopwatch::duration() {
return (((this->isRunning()) ? millis() : this->stopTimestamp)
- this->startTimestamp) / 1000 + this->accumulator;
}
#if ENABLED(DEBUG_STOPWATCH)
void Stopwatch::debug(const char func[]) {
if (DEBUGGING(INFO)) {
ECHO_MT("Stopwatch::", func);
ECHO_EM("()");
}
}
#endif
/**
* MK 3D Printer Firmware
*
* Based on Marlin, Sprinter and grbl
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
* Copyright (C) 2013 - 2016 Alberto Cotronei @MagoKimbra
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef STOPWATCH_H
#define STOPWATCH_H
// Print debug messages with M111 S2 (Uses 156 bytes of PROGMEM)
//#define DEBUG_STOPWATCH
enum StopwatchStatus {
STPWTCH_STOPPED,
STPWTCH_RUNNING,
STPWTCH_PAUSED
};
/**
* @brief Stopwatch class
* @details This class acts as a timer proving stopwatch functionality including
* the ability to pause the running time counter.
*/
class Stopwatch {
private:
StopwatchStatus status;
uint16_t accumulator;
uint32_t startTimestamp;
uint32_t stopTimestamp;
public:
/**
* @brief Class constructor
*/
Stopwatch();
/**
* @brief Stops the stopwatch
* @details Stops the running timer, it will silently ignore the request if
* no timer is currently running.
*/
void stop();
/**
* @brief Pauses the stopwatch
* @details Pauses the running timer, it will silently ignore the request if
* no timer is currently running.
*/
void pause();
/**
* @brief Starts the stopwatch
* @details Starts the timer, it will silently ignore the request if the
* timer is already running.
*/
void start();
/**
* @brief Resets the stopwatch
* @details Resets all settings to their default values.
*/
void reset();
/**
* @brief Checks if the timer is running
* @details Returns true if the timer is currently running, false otherwise.
* @return bool
*/
bool isRunning();
/**
* @brief Checks if the timer is paused
* @details Returns true if the timer is currently paused, false otherwise.
* @return bool
*/
bool isPaused();
/**
* @brief Gets the running time
* @details Returns the total number of seconds the timer has been running.
* @return uint16_t
*/
uint16_t duration();
#if ENABLED(DEBUG_STOPWATCH)
/**
* @brief Prints a debug message
* @details Prints a simple debug message "Stopwatch::function"
*/
static void debug(const char func[]);
#endif
};
#endif //STOPWATCH_H
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment