Add gcode.cpp, motion.*, queue.* - Apply to some G-codes.
This commit is contained in:
@ -20,6 +20,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../queue.h"
|
||||
|
||||
#include "../../libs/buzzer.h"
|
||||
#include "../../lcd/ultralcd.h"
|
||||
|
||||
|
@ -20,15 +20,18 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../gcode.h"
|
||||
#include "../../Marlin.h"
|
||||
|
||||
/**
|
||||
* M200: Set filament diameter and set E axis units to cubic units
|
||||
*
|
||||
* T<extruder> - Optional extruder number. Current extruder if omitted.
|
||||
* D<linear> - Diameter of the filament. Use "D0" to switch back to linear units on the E axis.
|
||||
*/
|
||||
void gcode_M200() {
|
||||
void GcodeSuite::M200() {
|
||||
|
||||
if (get_target_extruder_from_command(200)) return;
|
||||
if (get_target_extruder_from_command()) return;
|
||||
|
||||
if (parser.seen('D')) {
|
||||
// setting any extruder filament size disables volumetric on the assumption that
|
@ -27,7 +27,7 @@
|
||||
*/
|
||||
void gcode_M201() {
|
||||
|
||||
GET_TARGET_EXTRUDER(201);
|
||||
GET_TARGET_EXTRUDER();
|
||||
|
||||
LOOP_XYZE(i) {
|
||||
if (parser.seen(axis_codes[i])) {
|
||||
|
@ -27,7 +27,7 @@
|
||||
*/
|
||||
void gcode_M203() {
|
||||
|
||||
GET_TARGET_EXTRUDER(203);
|
||||
GET_TARGET_EXTRUDER();
|
||||
|
||||
LOOP_XYZE(i)
|
||||
if (parser.seen(axis_codes[i])) {
|
||||
|
@ -20,6 +20,13 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#if HOTENDS > 1
|
||||
|
||||
#include "../gcode.h"
|
||||
#include "../../module/motion.h"
|
||||
|
||||
/**
|
||||
* M218 - set hotend offset (in linear units)
|
||||
*
|
||||
@ -28,8 +35,8 @@
|
||||
* Y<yoffset>
|
||||
* Z<zoffset> - Available with DUAL_X_CARRIAGE and SWITCHING_NOZZLE
|
||||
*/
|
||||
void gcode_M218() {
|
||||
if (get_target_extruder_from_command(218) || target_extruder == 0) return;
|
||||
void GcodeSuite::M218() {
|
||||
if (get_target_extruder_from_command() || target_extruder == 0) return;
|
||||
|
||||
if (parser.seenval('X')) hotend_offset[X_AXIS][target_extruder] = parser.value_linear_units();
|
||||
if (parser.seenval('Y')) hotend_offset[Y_AXIS][target_extruder] = parser.value_linear_units();
|
||||
@ -52,3 +59,5 @@ void gcode_M218() {
|
||||
}
|
||||
SERIAL_EOL();
|
||||
}
|
||||
|
||||
#endif // HOTENDS > 1
|
@ -20,11 +20,14 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../gcode.h"
|
||||
#include "../../Marlin.h"
|
||||
|
||||
/**
|
||||
* M221: Set extrusion percentage (M221 T0 S95)
|
||||
*/
|
||||
void gcode_M221() {
|
||||
if (get_target_extruder_from_command(221)) return;
|
||||
void GcodeSuite::M221() {
|
||||
if (get_target_extruder_from_command()) return;
|
||||
if (parser.seenval('S'))
|
||||
flow_percentage[target_extruder] = parser.value_int();
|
||||
}
|
@ -20,6 +20,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../gcode.h"
|
||||
|
||||
#include "../../pins/pinsDebug.h"
|
||||
|
||||
inline void toggle_pins() {
|
||||
@ -141,7 +143,7 @@ inline void servo_probe_test() {
|
||||
}
|
||||
if (probe_inverting != deploy_state) SERIAL_PROTOCOLLNPGM("WARNING - INVERTING setting probably backwards");
|
||||
|
||||
refresh_cmd_timeout();
|
||||
gcode.refresh_cmd_timeout();
|
||||
|
||||
if (deploy_state != stow_state) {
|
||||
SERIAL_PROTOCOLLNPGM("BLTouch clone detected");
|
||||
@ -170,7 +172,7 @@ inline void servo_probe_test() {
|
||||
safe_delay(2);
|
||||
|
||||
if (0 == j % (500 * 1)) // keep cmd_timeout happy
|
||||
refresh_cmd_timeout();
|
||||
gcode.refresh_cmd_timeout();
|
||||
|
||||
if (deploy_state != READ(PROBE_TEST_PIN)) { // probe triggered
|
||||
|
||||
|
@ -28,7 +28,7 @@
|
||||
*/
|
||||
void gcode_M92() {
|
||||
|
||||
GET_TARGET_EXTRUDER(92);
|
||||
GET_TARGET_EXTRUDER();
|
||||
|
||||
LOOP_XYZE(i) {
|
||||
if (parser.seen(axis_codes[i])) {
|
||||
|
@ -20,6 +20,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../queue.h"
|
||||
|
||||
/**
|
||||
* M999: Restart after being stopped
|
||||
*
|
||||
@ -37,5 +39,5 @@ void gcode_M999() {
|
||||
if (parser.boolval('S')) return;
|
||||
|
||||
// gcode_LastN = Stopped_gcode_LastN;
|
||||
FlushSerialRequestResend();
|
||||
flush_and_request_resend();
|
||||
}
|
||||
|
@ -20,11 +20,243 @@
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* gcode.cpp - Temporary container for all gcode handlers
|
||||
* Most will migrate to classes, by feature.
|
||||
*/
|
||||
|
||||
#include "gcode.h"
|
||||
GcodeSuite gcode;
|
||||
|
||||
#include "parser.h"
|
||||
#include "queue.h"
|
||||
#include "../module/motion.h"
|
||||
|
||||
#if ENABLED(PRINTCOUNTER)
|
||||
#include "../module/printcounter.h"
|
||||
#endif
|
||||
|
||||
uint8_t GcodeSuite::target_extruder;
|
||||
millis_t GcodeSuite::previous_cmd_ms;
|
||||
|
||||
bool GcodeSuite::axis_relative_modes[] = AXIS_RELATIVE_MODES;
|
||||
|
||||
/**
|
||||
* Set target_extruder from the T parameter or the active_extruder
|
||||
*
|
||||
* Returns TRUE if the target is invalid
|
||||
*/
|
||||
bool GcodeSuite::get_target_extruder_from_command() {
|
||||
if (parser.seenval('T')) {
|
||||
const int8_t e = parser.value_byte();
|
||||
if (e >= EXTRUDERS) {
|
||||
SERIAL_ECHO_START();
|
||||
SERIAL_CHAR('M');
|
||||
SERIAL_ECHO(parser.codenum);
|
||||
SERIAL_ECHOLNPAIR(" " MSG_INVALID_EXTRUDER " ", e);
|
||||
return true;
|
||||
}
|
||||
target_extruder = e;
|
||||
}
|
||||
else
|
||||
target_extruder = active_extruder;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set XYZE destination and feedrate from the current GCode command
|
||||
*
|
||||
* - Set destination from included axis codes
|
||||
* - Set to current for missing axis codes
|
||||
* - Set the feedrate, if included
|
||||
*/
|
||||
void GcodeSuite::get_destination_from_command() {
|
||||
LOOP_XYZE(i) {
|
||||
if (parser.seen(axis_codes[i]))
|
||||
destination[i] = parser.value_axis_units((AxisEnum)i) + (axis_relative_modes[i] || relative_mode ? current_position[i] : 0);
|
||||
else
|
||||
destination[i] = current_position[i];
|
||||
}
|
||||
|
||||
if (parser.linearval('F') > 0.0)
|
||||
feedrate_mm_s = MMM_TO_MMS(parser.value_feedrate());
|
||||
|
||||
#if ENABLED(PRINTCOUNTER)
|
||||
if (!DEBUGGING(DRYRUN))
|
||||
print_job_timer.incFilamentUsed(destination[E_AXIS] - current_position[E_AXIS]);
|
||||
#endif
|
||||
|
||||
// Get ABCDHI mixing factors
|
||||
#if ENABLED(MIXING_EXTRUDER) && ENABLED(DIRECT_MIXING_IN_G1)
|
||||
gcode_get_mix();
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
// Placeholders for non-migrated codes
|
||||
//
|
||||
extern void gcode_G0_G1(
|
||||
#if IS_SCARA
|
||||
bool fast_move=false
|
||||
#endif
|
||||
);
|
||||
extern void gcode_G2_G3(bool clockwise);
|
||||
extern void gcode_G4();
|
||||
extern void gcode_G5();
|
||||
extern void gcode_G12();
|
||||
extern void gcode_G17();
|
||||
extern void gcode_G18();
|
||||
extern void gcode_G19();
|
||||
extern void gcode_G20();
|
||||
extern void gcode_G21();
|
||||
extern void gcode_G26();
|
||||
extern void gcode_G27();
|
||||
extern void gcode_G28(const bool always_home_all);
|
||||
extern void gcode_G29();
|
||||
extern void gcode_G30();
|
||||
extern void gcode_G31();
|
||||
extern void gcode_G32();
|
||||
extern void gcode_G33();
|
||||
extern void gcode_G38(bool is_38_2);
|
||||
extern void gcode_G42();
|
||||
extern void gcode_G92();
|
||||
extern void gcode_M0_M1();
|
||||
extern void gcode_M3_M4(bool is_M3);
|
||||
extern void gcode_M5();
|
||||
extern void gcode_M17();
|
||||
extern void gcode_M18_M84();
|
||||
extern void gcode_M20();
|
||||
extern void gcode_M21();
|
||||
extern void gcode_M22();
|
||||
extern void gcode_M23();
|
||||
extern void gcode_M24();
|
||||
extern void gcode_M25();
|
||||
extern void gcode_M26();
|
||||
extern void gcode_M27();
|
||||
extern void gcode_M28();
|
||||
extern void gcode_M29();
|
||||
extern void gcode_M30();
|
||||
extern void gcode_M31();
|
||||
extern void gcode_M32();
|
||||
extern void gcode_M33();
|
||||
extern void gcode_M34();
|
||||
extern void gcode_M42();
|
||||
extern void gcode_M43();
|
||||
extern void gcode_M48();
|
||||
extern void gcode_M49();
|
||||
extern void gcode_M75();
|
||||
extern void gcode_M76();
|
||||
extern void gcode_M77();
|
||||
extern void gcode_M78();
|
||||
extern void gcode_M80();
|
||||
extern void gcode_M81();
|
||||
extern void gcode_M82();
|
||||
extern void gcode_M83();
|
||||
extern void gcode_M85();
|
||||
extern void gcode_M92();
|
||||
extern void gcode_M100();
|
||||
extern void gcode_M105();
|
||||
extern void gcode_M106();
|
||||
extern void gcode_M107();
|
||||
extern void gcode_M108();
|
||||
extern void gcode_M110();
|
||||
extern void gcode_M111();
|
||||
extern void gcode_M112();
|
||||
extern void gcode_M113();
|
||||
extern void gcode_M114();
|
||||
extern void gcode_M115();
|
||||
extern void gcode_M117();
|
||||
extern void gcode_M118();
|
||||
extern void gcode_M119();
|
||||
extern void gcode_M120();
|
||||
extern void gcode_M121();
|
||||
extern void gcode_M125();
|
||||
extern void gcode_M126();
|
||||
extern void gcode_M127();
|
||||
extern void gcode_M128();
|
||||
extern void gcode_M129();
|
||||
extern void gcode_M140();
|
||||
extern void gcode_M145();
|
||||
extern void gcode_M149();
|
||||
extern void gcode_M150();
|
||||
extern void gcode_M155();
|
||||
extern void gcode_M163();
|
||||
extern void gcode_M164();
|
||||
extern void gcode_M165();
|
||||
extern void gcode_M190();
|
||||
extern void gcode_M201();
|
||||
extern void gcode_M203();
|
||||
extern void gcode_M204();
|
||||
extern void gcode_M205();
|
||||
extern void gcode_M206();
|
||||
extern void gcode_M211();
|
||||
extern void gcode_M220();
|
||||
extern void gcode_M226();
|
||||
extern void gcode_M240();
|
||||
extern void gcode_M250();
|
||||
extern void gcode_M260();
|
||||
extern void gcode_M261();
|
||||
extern void gcode_M280();
|
||||
extern void gcode_M300();
|
||||
extern void gcode_M301();
|
||||
extern void gcode_M302();
|
||||
extern void gcode_M304();
|
||||
extern void gcode_M350();
|
||||
extern void gcode_M351();
|
||||
extern void gcode_M355();
|
||||
extern bool gcode_M360();
|
||||
extern bool gcode_M361();
|
||||
extern bool gcode_M362();
|
||||
extern bool gcode_M363();
|
||||
extern bool gcode_M364();
|
||||
extern void gcode_M380();
|
||||
extern void gcode_M381();
|
||||
extern void gcode_M400();
|
||||
extern void gcode_M401();
|
||||
extern void gcode_M402();
|
||||
extern void gcode_M404();
|
||||
extern void gcode_M405();
|
||||
extern void gcode_M406();
|
||||
extern void gcode_M407();
|
||||
extern void gcode_M410();
|
||||
extern void gcode_M420();
|
||||
extern void gcode_M421();
|
||||
extern void gcode_M428();
|
||||
extern void gcode_M500();
|
||||
extern void gcode_M501();
|
||||
extern void gcode_M502();
|
||||
extern void gcode_M503();
|
||||
extern void gcode_M540();
|
||||
extern void gcode_M600();
|
||||
extern void gcode_M605();
|
||||
extern void gcode_M665();
|
||||
extern void gcode_M666();
|
||||
extern void gcode_M702();
|
||||
extern void gcode_M851();
|
||||
extern void gcode_M900();
|
||||
extern void gcode_M906();
|
||||
extern void gcode_M911();
|
||||
extern void gcode_M912();
|
||||
extern void gcode_M913();
|
||||
extern void gcode_M914();
|
||||
extern void gcode_M907();
|
||||
extern void gcode_M908();
|
||||
extern void gcode_M909();
|
||||
extern void gcode_M910();
|
||||
extern void gcode_M928();
|
||||
extern void gcode_M999();
|
||||
extern void gcode_T(uint8_t tmp_extruder);
|
||||
|
||||
#if ENABLED(M100_FREE_MEMORY_WATCHER)
|
||||
extern void M100_dump_routine(const char * const title, const char *start, const char *end);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Process a single command and dispatch it to its handler
|
||||
* This is called from the main loop()
|
||||
*/
|
||||
void process_next_command() {
|
||||
void GcodeSuite::process_next_command() {
|
||||
char * const current_command = command_queue[cmd_queue_index_r];
|
||||
|
||||
if (DEBUGGING(ECHO)) {
|
||||
@ -49,9 +281,9 @@ void process_next_command() {
|
||||
case 0:
|
||||
case 1:
|
||||
#if IS_SCARA
|
||||
gcode_G0_G1(parser.codenum == 0);
|
||||
G0_G1(parser.codenum == 0);
|
||||
#else
|
||||
gcode_G0_G1();
|
||||
G0_G1();
|
||||
#endif
|
||||
break;
|
||||
|
||||
@ -76,10 +308,10 @@ void process_next_command() {
|
||||
|
||||
#if ENABLED(FWRETRACT)
|
||||
case 10: // G10: retract
|
||||
gcode_G10();
|
||||
G10();
|
||||
break;
|
||||
case 11: // G11: retract_recover
|
||||
gcode_G11();
|
||||
G11();
|
||||
break;
|
||||
#endif // FWRETRACT
|
||||
|
||||
@ -303,9 +535,8 @@ void process_next_command() {
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 104: // M104: Set hot end temperature
|
||||
gcode_M104();
|
||||
break;
|
||||
case 104: M104(); break; // M104: Set hot end temperature
|
||||
case 109: M109(); break; // M109: Wait for hotend temperature to reach target
|
||||
|
||||
case 110: // M110: Set Current Line Number
|
||||
gcode_M110();
|
||||
@ -353,10 +584,6 @@ void process_next_command() {
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 109: // M109: Wait for hotend temperature to reach target
|
||||
gcode_M109();
|
||||
break;
|
||||
|
||||
#if HAS_TEMP_BED
|
||||
case 190: // M190: Wait for bed temperature to reach target
|
||||
gcode_M190();
|
||||
@ -488,7 +715,7 @@ void process_next_command() {
|
||||
#endif
|
||||
|
||||
case 200: // M200: Set filament diameter, E to cubic units
|
||||
gcode_M200();
|
||||
M200();
|
||||
break;
|
||||
case 201: // M201: Set max acceleration for print moves (units/s^2)
|
||||
gcode_M201();
|
||||
@ -528,13 +755,13 @@ void process_next_command() {
|
||||
|
||||
#if ENABLED(FWRETRACT)
|
||||
case 207: // M207: Set Retract Length, Feedrate, and Z lift
|
||||
gcode_M207();
|
||||
M207();
|
||||
break;
|
||||
case 208: // M208: Set Recover (unretract) Additional Length and Feedrate
|
||||
gcode_M208();
|
||||
M208();
|
||||
break;
|
||||
case 209: // M209: Turn Automatic Retract Detection on/off
|
||||
if (MIN_AUTORETRACT <= MAX_AUTORETRACT) gcode_M209();
|
||||
if (MIN_AUTORETRACT <= MAX_AUTORETRACT) M209();
|
||||
break;
|
||||
#endif // FWRETRACT
|
||||
|
||||
@ -544,7 +771,7 @@ void process_next_command() {
|
||||
|
||||
#if HOTENDS > 1
|
||||
case 218: // M218: Set a tool offset
|
||||
gcode_M218();
|
||||
M218();
|
||||
break;
|
||||
#endif
|
||||
|
||||
@ -553,7 +780,7 @@ void process_next_command() {
|
||||
break;
|
||||
|
||||
case 221: // M221: Set Flow Percentage
|
||||
gcode_M221();
|
||||
M221();
|
||||
break;
|
||||
|
||||
case 226: // M226: Wait until a pin reaches a state
|
||||
@ -615,7 +842,7 @@ void process_next_command() {
|
||||
#endif // PREVENT_COLD_EXTRUSION
|
||||
|
||||
case 303: // M303: PID autotune
|
||||
gcode_M303();
|
||||
M303();
|
||||
break;
|
||||
|
||||
#if ENABLED(MORGAN_SCARA)
|
||||
@ -636,6 +863,15 @@ void process_next_command() {
|
||||
break;
|
||||
#endif // SCARA
|
||||
|
||||
#if ENABLED(EXT_SOLENOID)
|
||||
case 380: // M380: Activate solenoid on active extruder
|
||||
gcode_M380();
|
||||
break;
|
||||
case 381: // M381: Disable all solenoids
|
||||
gcode_M381();
|
||||
break;
|
||||
#endif
|
||||
|
||||
case 400: // M400: Finish all moves
|
||||
gcode_M400();
|
||||
break;
|
||||
@ -809,48 +1045,17 @@ void process_next_command() {
|
||||
#endif
|
||||
|
||||
#if ENABLED(I2C_POSITION_ENCODERS)
|
||||
|
||||
case 860: // M860 Report encoder module position
|
||||
gcode_M860();
|
||||
break;
|
||||
|
||||
case 861: // M861 Report encoder module status
|
||||
gcode_M861();
|
||||
break;
|
||||
|
||||
case 862: // M862 Perform axis test
|
||||
gcode_M862();
|
||||
break;
|
||||
|
||||
case 863: // M863 Calibrate steps/mm
|
||||
gcode_M863();
|
||||
break;
|
||||
|
||||
case 864: // M864 Change module address
|
||||
gcode_M864();
|
||||
break;
|
||||
|
||||
case 865: // M865 Check module firmware version
|
||||
gcode_M865();
|
||||
break;
|
||||
|
||||
case 866: // M866 Report axis error count
|
||||
gcode_M866();
|
||||
break;
|
||||
|
||||
case 867: // M867 Toggle error correction
|
||||
gcode_M867();
|
||||
break;
|
||||
|
||||
case 868: // M868 Set error correction threshold
|
||||
gcode_M868();
|
||||
break;
|
||||
|
||||
case 869: // M869 Report axis error
|
||||
gcode_M869();
|
||||
break;
|
||||
|
||||
#endif // I2C_POSITION_ENCODERS
|
||||
case 860: M860(); break; // M860: Report encoder module position
|
||||
case 861: M861(); break; // M861: Report encoder module status
|
||||
case 862: M862(); break; // M862: Perform axis test
|
||||
case 863: M863(); break; // M863: Calibrate steps/mm
|
||||
case 864: M864(); break; // M864: Change module address
|
||||
case 865: M865(); break; // M865: Check module firmware version
|
||||
case 866: M866(); break; // M866: Report axis error count
|
||||
case 867: M867(); break; // M867: Toggle error correction
|
||||
case 868: M868(); break; // M868: Set error correction threshold
|
||||
case 869: M869(); break; // M869: Report axis error
|
||||
#endif
|
||||
|
||||
case 999: // M999: Restart after being Stopped
|
||||
gcode_M999();
|
||||
@ -868,4 +1073,4 @@ void process_next_command() {
|
||||
KEEPALIVE_STATE(NOT_BUSY);
|
||||
|
||||
ok_to_send();
|
||||
}
|
||||
}
|
@ -237,8 +237,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GCODE_H
|
||||
#define GCODE_H
|
||||
#ifndef _GCODE_H_
|
||||
#define _GCODE_H_
|
||||
|
||||
#include "../inc/MarlinConfig.h"
|
||||
#include "parser.h"
|
||||
@ -252,6 +252,30 @@ public:
|
||||
|
||||
GcodeSuite() {}
|
||||
|
||||
static uint8_t target_extruder;
|
||||
|
||||
static bool axis_relative_modes[];
|
||||
|
||||
static millis_t previous_cmd_ms;
|
||||
FORCE_INLINE static void refresh_cmd_timeout() { previous_cmd_ms = millis(); }
|
||||
|
||||
static bool get_target_extruder_from_command();
|
||||
static void get_destination_from_command();
|
||||
static void process_next_command();
|
||||
|
||||
/**
|
||||
* Multi-stepper support for M92, M201, M203
|
||||
*/
|
||||
#if ENABLED(DISTINCT_E_FACTORS)
|
||||
#define GET_TARGET_EXTRUDER() if (gcode.get_target_extruder_from_command()) return
|
||||
#define TARGET_EXTRUDER gcode.target_extruder
|
||||
#else
|
||||
#define GET_TARGET_EXTRUDER() NOOP
|
||||
#define TARGET_EXTRUDER 0
|
||||
#endif
|
||||
|
||||
static FORCE_INLINE void home_all_axes() { G28(true); }
|
||||
|
||||
private:
|
||||
|
||||
static void G0_G1(
|
||||
@ -375,7 +399,7 @@ private:
|
||||
static void M48();
|
||||
#endif
|
||||
|
||||
#if ENABLED(AUTO_BED_LEVELING_UBL) && ENABLED(UBL_G26_MESH_VALIDATION)
|
||||
#if ENABLED(UBL_G26_MESH_VALIDATION)
|
||||
static void M49();
|
||||
#endif
|
||||
|
||||
@ -679,4 +703,4 @@ private:
|
||||
|
||||
extern GcodeSuite gcode;
|
||||
|
||||
#endif // GCODE_H
|
||||
#endif // _GCODE_H_
|
||||
|
@ -20,6 +20,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../queue.h"
|
||||
|
||||
/**
|
||||
* M110: Set Current Line Number
|
||||
*/
|
||||
|
@ -20,6 +20,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../gcode.h"
|
||||
|
||||
/**
|
||||
* M0: Unconditional stop - Wait for user button press on LCD
|
||||
* M1: Conditional stop - Wait for user button press on LCD
|
||||
@ -62,7 +64,7 @@ void gcode_M0_M1() {
|
||||
wait_for_user = true;
|
||||
|
||||
stepper.synchronize();
|
||||
refresh_cmd_timeout();
|
||||
gcode.refresh_cmd_timeout();
|
||||
|
||||
if (ms > 0) {
|
||||
ms += previous_cmd_ms; // wait until this time for a click
|
||||
|
@ -20,16 +20,25 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../gcode.h"
|
||||
#include "../../module/motion.h"
|
||||
|
||||
#include "../../Marlin.h"
|
||||
|
||||
#include "../../sd/cardreader.h"
|
||||
|
||||
extern float destination[XYZE];
|
||||
|
||||
/**
|
||||
* G0, G1: Coordinated movement of X Y Z E axes
|
||||
*/
|
||||
void gcode_G0_G1(
|
||||
void GcodeSuite::G0_G1(
|
||||
#if IS_SCARA
|
||||
bool fast_move=false
|
||||
bool fast_move/*=false*/
|
||||
#endif
|
||||
) {
|
||||
if (IsRunning()) {
|
||||
gcode_get_destination(); // For X Y Z E F
|
||||
get_destination_from_command(); // For X Y Z E F
|
||||
|
||||
#if ENABLED(FWRETRACT)
|
||||
if (MIN_AUTORETRACT <= MAX_AUTORETRACT) {
|
@ -20,6 +20,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../gcode.h"
|
||||
|
||||
#if N_ARC_CORRECTION < 1
|
||||
#undef N_ARC_CORRECTION
|
||||
#define N_ARC_CORRECTION 1
|
||||
@ -209,7 +211,7 @@ void gcode_G2_G3(bool clockwise) {
|
||||
relative_mode = true;
|
||||
#endif
|
||||
|
||||
gcode_get_destination();
|
||||
gcode.get_destination_from_command();
|
||||
|
||||
#if ENABLED(SF_ARC_FIX)
|
||||
relative_mode = relative_mode_backup;
|
||||
@ -252,7 +254,7 @@ void gcode_G2_G3(bool clockwise) {
|
||||
|
||||
// Send the arc to the planner
|
||||
plan_arc(destination, arc_offset, clockwise);
|
||||
refresh_cmd_timeout();
|
||||
gcode.refresh_cmd_timeout();
|
||||
}
|
||||
else {
|
||||
// Bad arguments
|
||||
|
@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
#include "../../module/planner_bezier.h"
|
||||
#include "../../gcode/gcode.h"
|
||||
|
||||
void plan_cubic_move(const float offset[4]) {
|
||||
cubic_b_spline(current_position, destination, offset, MMS_SCALED(feedrate_mm_s), active_extruder);
|
||||
@ -52,7 +53,7 @@ void gcode_G5() {
|
||||
}
|
||||
#endif
|
||||
|
||||
gcode_get_destination();
|
||||
gcode.get_destination_from_command();
|
||||
|
||||
const float offset[] = {
|
||||
parser.linearval('I'),
|
||||
|
@ -242,7 +242,7 @@ public:
|
||||
FORCE_INLINE static char temp_units_code() {
|
||||
return input_temp_units == TEMPUNIT_K ? 'K' : input_temp_units == TEMPUNIT_F ? 'F' : 'C';
|
||||
}
|
||||
FORCE_INLINE static char* temp_units_name() {
|
||||
FORCE_INLINE static const char* temp_units_name() {
|
||||
return input_temp_units == TEMPUNIT_K ? PSTR("Kelvin") : input_temp_units == TEMPUNIT_F ? PSTR("Fahrenheit") : PSTR("Celsius");
|
||||
}
|
||||
inline static float to_temp_units(const float &f) {
|
||||
|
@ -20,6 +20,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../gcode.h"
|
||||
|
||||
static bool G38_run_probe() {
|
||||
|
||||
bool G38_pass_fail = false;
|
||||
@ -88,7 +90,7 @@ static bool G38_run_probe() {
|
||||
*/
|
||||
void gcode_G38(bool is_38_2) {
|
||||
// Get X Y Z E F
|
||||
gcode_get_destination();
|
||||
gcode.get_destination_from_command();
|
||||
|
||||
setup_for_endstop_or_probe_move();
|
||||
|
||||
|
473
Marlin/src/gcode/queue.cpp
Normal file
473
Marlin/src/gcode/queue.cpp
Normal file
@ -0,0 +1,473 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* queue.cpp - The G-code command queue
|
||||
*/
|
||||
|
||||
#include "queue.h"
|
||||
#include "gcode.h"
|
||||
|
||||
#include "../lcd/ultralcd.h"
|
||||
#include "../sd/cardreader.h"
|
||||
#include "../module/planner.h"
|
||||
#include "../Marlin.h"
|
||||
|
||||
/**
|
||||
* GCode line number handling. Hosts may opt to include line numbers when
|
||||
* sending commands to Marlin, and lines will be checked for sequentiality.
|
||||
* M110 N<int> sets the current line number.
|
||||
*/
|
||||
long gcode_N, gcode_LastN, Stopped_gcode_LastN = 0;
|
||||
|
||||
/**
|
||||
* GCode Command Queue
|
||||
* A simple ring buffer of BUFSIZE command strings.
|
||||
*
|
||||
* Commands are copied into this buffer by the command injectors
|
||||
* (immediate, serial, sd card) and they are processed sequentially by
|
||||
* the main loop. The gcode.process_next_command method parses the next
|
||||
* command and hands off execution to individual handler functions.
|
||||
*/
|
||||
uint8_t commands_in_queue = 0, // Count of commands in the queue
|
||||
cmd_queue_index_r = 0, // Ring buffer read position
|
||||
cmd_queue_index_w = 0; // Ring buffer write position
|
||||
|
||||
char command_queue[BUFSIZE][MAX_CMD_SIZE];
|
||||
|
||||
/**
|
||||
* Serial command injection
|
||||
*/
|
||||
|
||||
// Number of characters read in the current line of serial input
|
||||
static int serial_count = 0;
|
||||
|
||||
bool send_ok[BUFSIZE];
|
||||
|
||||
/**
|
||||
* Next Injected Command pointer. NULL if no commands are being injected.
|
||||
* Used by Marlin internally to ensure that commands initiated from within
|
||||
* are enqueued ahead of any pending serial or sd card commands.
|
||||
*/
|
||||
static const char *injected_commands_P = NULL;
|
||||
|
||||
void queue_setup() {
|
||||
// Send "ok" after commands by default
|
||||
for (uint8_t i = 0; i < COUNT(send_ok); i++) send_ok[i] = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the Marlin command queue
|
||||
*/
|
||||
void clear_command_queue() {
|
||||
cmd_queue_index_r = cmd_queue_index_w;
|
||||
commands_in_queue = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Once a new command is in the ring buffer, call this to commit it
|
||||
*/
|
||||
inline void _commit_command(bool say_ok) {
|
||||
send_ok[cmd_queue_index_w] = say_ok;
|
||||
if (++cmd_queue_index_w >= BUFSIZE) cmd_queue_index_w = 0;
|
||||
commands_in_queue++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy a command from RAM into the main command buffer.
|
||||
* Return true if the command was successfully added.
|
||||
* Return false for a full buffer, or if the 'command' is a comment.
|
||||
*/
|
||||
inline bool _enqueuecommand(const char* cmd, bool say_ok/*=false*/) {
|
||||
if (*cmd == ';' || commands_in_queue >= BUFSIZE) return false;
|
||||
strcpy(command_queue[cmd_queue_index_w], cmd);
|
||||
_commit_command(say_ok);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue with Serial Echo
|
||||
*/
|
||||
bool enqueue_and_echo_command(const char* cmd, bool say_ok/*=false*/) {
|
||||
if (_enqueuecommand(cmd, say_ok)) {
|
||||
SERIAL_ECHO_START();
|
||||
SERIAL_ECHOPAIR(MSG_ENQUEUEING, cmd);
|
||||
SERIAL_CHAR('"');
|
||||
SERIAL_EOL();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inject the next "immediate" command, when possible, onto the front of the queue.
|
||||
* Return true if any immediate commands remain to inject.
|
||||
*/
|
||||
static bool drain_injected_commands_P() {
|
||||
if (injected_commands_P != NULL) {
|
||||
size_t i = 0;
|
||||
char c, cmd[30];
|
||||
strncpy_P(cmd, injected_commands_P, sizeof(cmd) - 1);
|
||||
cmd[sizeof(cmd) - 1] = '\0';
|
||||
while ((c = cmd[i]) && c != '\n') i++; // find the end of this gcode command
|
||||
cmd[i] = '\0';
|
||||
if (enqueue_and_echo_command(cmd)) // success?
|
||||
injected_commands_P = c ? injected_commands_P + i + 1 : NULL; // next command or done
|
||||
}
|
||||
return (injected_commands_P != NULL); // return whether any more remain
|
||||
}
|
||||
|
||||
/**
|
||||
* Record one or many commands to run from program memory.
|
||||
* Aborts the current queue, if any.
|
||||
* Note: drain_injected_commands_P() must be called repeatedly to drain the commands afterwards
|
||||
*/
|
||||
void enqueue_and_echo_commands_P(const char * const pgcode) {
|
||||
injected_commands_P = pgcode;
|
||||
drain_injected_commands_P(); // first command executed asap (when possible)
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an "ok" message to the host, indicating
|
||||
* that a command was successfully processed.
|
||||
*
|
||||
* If ADVANCED_OK is enabled also include:
|
||||
* N<int> Line number of the command, if any
|
||||
* P<int> Planner space remaining
|
||||
* B<int> Block queue space remaining
|
||||
*/
|
||||
void ok_to_send() {
|
||||
gcode.refresh_cmd_timeout();
|
||||
if (!send_ok[cmd_queue_index_r]) return;
|
||||
SERIAL_PROTOCOLPGM(MSG_OK);
|
||||
#if ENABLED(ADVANCED_OK)
|
||||
char* p = command_queue[cmd_queue_index_r];
|
||||
if (*p == 'N') {
|
||||
SERIAL_PROTOCOL(' ');
|
||||
SERIAL_ECHO(*p++);
|
||||
while (NUMERIC_SIGNED(*p))
|
||||
SERIAL_ECHO(*p++);
|
||||
}
|
||||
SERIAL_PROTOCOLPGM(" P"); SERIAL_PROTOCOL(int(BLOCK_BUFFER_SIZE - planner.movesplanned() - 1));
|
||||
SERIAL_PROTOCOLPGM(" B"); SERIAL_PROTOCOL(BUFSIZE - commands_in_queue);
|
||||
#endif
|
||||
SERIAL_EOL();
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a "Resend: nnn" message to the host to
|
||||
* indicate that a command needs to be re-sent.
|
||||
*/
|
||||
void flush_and_request_resend() {
|
||||
//char command_queue[cmd_queue_index_r][100]="Resend:";
|
||||
MYSERIAL.flush();
|
||||
SERIAL_PROTOCOLPGM(MSG_RESEND);
|
||||
SERIAL_PROTOCOLLN(gcode_LastN + 1);
|
||||
ok_to_send();
|
||||
}
|
||||
|
||||
void gcode_line_error(const char* err, bool doFlush = true) {
|
||||
SERIAL_ERROR_START();
|
||||
serialprintPGM(err);
|
||||
SERIAL_ERRORLN(gcode_LastN);
|
||||
//Serial.println(gcode_N);
|
||||
if (doFlush) flush_and_request_resend();
|
||||
serial_count = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all commands waiting on the serial port and queue them.
|
||||
* Exit when the buffer is full or when no more characters are
|
||||
* left on the serial port.
|
||||
*/
|
||||
inline void get_serial_commands() {
|
||||
static char serial_line_buffer[MAX_CMD_SIZE];
|
||||
static bool serial_comment_mode = false;
|
||||
|
||||
// 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;
|
||||
const millis_t ms = millis();
|
||||
if (commands_in_queue == 0 && !MYSERIAL.available() && ELAPSED(ms, last_command_time + NO_TIMEOUTS)) {
|
||||
SERIAL_ECHOLNPGM(MSG_WAIT);
|
||||
last_command_time = ms;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Loop while serial characters are incoming and the queue is not full
|
||||
*/
|
||||
while (commands_in_queue < BUFSIZE && MYSERIAL.available() > 0) {
|
||||
|
||||
char serial_char = MYSERIAL.read();
|
||||
|
||||
/**
|
||||
* If the character ends the line
|
||||
*/
|
||||
if (serial_char == '\n' || serial_char == '\r') {
|
||||
|
||||
serial_comment_mode = false; // end of line == end of comment
|
||||
|
||||
if (!serial_count) continue; // skip empty lines
|
||||
|
||||
serial_line_buffer[serial_count] = 0; // terminate string
|
||||
serial_count = 0; //reset buffer
|
||||
|
||||
char* command = serial_line_buffer;
|
||||
|
||||
while (*command == ' ') command++; // skip any leading spaces
|
||||
char *npos = (*command == 'N') ? command : NULL, // Require the N parameter to start the line
|
||||
*apos = strchr(command, '*');
|
||||
|
||||
if (npos) {
|
||||
|
||||
bool M110 = strstr_P(command, PSTR("M110")) != NULL;
|
||||
|
||||
if (M110) {
|
||||
char* n2pos = strchr(command + 4, 'N');
|
||||
if (n2pos) npos = n2pos;
|
||||
}
|
||||
|
||||
gcode_N = strtol(npos + 1, NULL, 10);
|
||||
|
||||
if (gcode_N != gcode_LastN + 1 && !M110) {
|
||||
gcode_line_error(PSTR(MSG_ERR_LINE_NO));
|
||||
return;
|
||||
}
|
||||
|
||||
if (apos) {
|
||||
byte checksum = 0, count = 0;
|
||||
while (command[count] != '*') checksum ^= command[count++];
|
||||
|
||||
if (strtol(apos + 1, NULL, 10) != checksum) {
|
||||
gcode_line_error(PSTR(MSG_ERR_CHECKSUM_MISMATCH));
|
||||
return;
|
||||
}
|
||||
// if no errors, continue parsing
|
||||
}
|
||||
else {
|
||||
gcode_line_error(PSTR(MSG_ERR_NO_CHECKSUM));
|
||||
return;
|
||||
}
|
||||
|
||||
gcode_LastN = gcode_N;
|
||||
// if no errors, continue parsing
|
||||
}
|
||||
else if (apos) { // No '*' without 'N'
|
||||
gcode_line_error(PSTR(MSG_ERR_NO_LINENUMBER_WITH_CHECKSUM), false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Movement commands alert when stopped
|
||||
if (IsStopped()) {
|
||||
char* gpos = strchr(command, 'G');
|
||||
if (gpos) {
|
||||
const int codenum = strtol(gpos + 1, NULL, 10);
|
||||
switch (codenum) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
SERIAL_ERRORLNPGM(MSG_ERR_STOPPED);
|
||||
LCD_MESSAGEPGM(MSG_STOPPED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if DISABLED(EMERGENCY_PARSER)
|
||||
// If command was e-stop process now
|
||||
if (strcmp(command, "M108") == 0) {
|
||||
wait_for_heatup = false;
|
||||
#if ENABLED(ULTIPANEL)
|
||||
wait_for_user = false;
|
||||
#endif
|
||||
}
|
||||
if (strcmp(command, "M112") == 0) kill(PSTR(MSG_KILLED));
|
||||
if (strcmp(command, "M410") == 0) { quickstop_stepper(); }
|
||||
#endif
|
||||
|
||||
#if defined(NO_TIMEOUTS) && NO_TIMEOUTS > 0
|
||||
last_command_time = ms;
|
||||
#endif
|
||||
|
||||
// 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
|
||||
if (MYSERIAL.available() > 0) {
|
||||
// if we have one more character, copy it over
|
||||
serial_char = MYSERIAL.read();
|
||||
if (!serial_comment_mode) serial_line_buffer[serial_count++] = serial_char;
|
||||
}
|
||||
// otherwise do nothing
|
||||
}
|
||||
else { // it's not a newline, carriage return or escape char
|
||||
if (serial_char == ';') serial_comment_mode = true;
|
||||
if (!serial_comment_mode) serial_line_buffer[serial_count++] = serial_char;
|
||||
}
|
||||
|
||||
} // queue has space, serial has data
|
||||
}
|
||||
|
||||
#if ENABLED(SDSUPPORT)
|
||||
|
||||
/**
|
||||
* Get commands from the SD Card until the command buffer is full
|
||||
* or until the end of the file is reached. The special character '#'
|
||||
* can also interrupt buffering.
|
||||
*/
|
||||
inline void get_sdcard_commands() {
|
||||
static bool stop_buffering = false,
|
||||
sd_comment_mode = false;
|
||||
|
||||
if (!IS_SD_PRINTING) 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 run dry; this character _can_ occur in serial com
|
||||
* due to checksums, however, no checksums are used in SD printing.
|
||||
*/
|
||||
|
||||
if (commands_in_queue == 0) stop_buffering = false;
|
||||
|
||||
uint16_t sd_count = 0;
|
||||
bool card_eof = card.eof();
|
||||
while (commands_in_queue < BUFSIZE && !card_eof && !stop_buffering) {
|
||||
const int16_t n = card.get();
|
||||
char sd_char = (char)n;
|
||||
card_eof = card.eof();
|
||||
if (card_eof || n == -1
|
||||
|| sd_char == '\n' || sd_char == '\r'
|
||||
|| ((sd_char == '#' || sd_char == ':') && !sd_comment_mode)
|
||||
) {
|
||||
if (card_eof) {
|
||||
SERIAL_PROTOCOLLNPGM(MSG_FILE_PRINTED);
|
||||
card.printingHasFinished();
|
||||
#if ENABLED(PRINTER_EVENT_LEDS)
|
||||
LCD_MESSAGEPGM(MSG_INFO_COMPLETED_PRINTS);
|
||||
set_led_color(0, 255, 0); // Green
|
||||
#if HAS_RESUME_CONTINUE
|
||||
enqueue_and_echo_commands_P(PSTR("M0")); // end of the queue!
|
||||
#else
|
||||
safe_delay(1000);
|
||||
#endif
|
||||
set_led_color(0, 0, 0); // OFF
|
||||
#endif
|
||||
card.checkautostart(true);
|
||||
}
|
||||
else if (n == -1) {
|
||||
SERIAL_ERROR_START();
|
||||
SERIAL_ECHOLNPGM(MSG_SD_ERR_READ);
|
||||
}
|
||||
if (sd_char == '#') stop_buffering = true;
|
||||
|
||||
sd_comment_mode = false; // for new command
|
||||
|
||||
if (!sd_count) continue; // skip empty lines (and comment lines)
|
||||
|
||||
command_queue[cmd_queue_index_w][sd_count] = '\0'; // terminate string
|
||||
sd_count = 0; // clear sd line buffer
|
||||
|
||||
_commit_command(false);
|
||||
}
|
||||
else if (sd_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 (sd_char == ';') sd_comment_mode = true;
|
||||
if (!sd_comment_mode) command_queue[cmd_queue_index_w][sd_count++] = sd_char;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SDSUPPORT
|
||||
|
||||
/**
|
||||
* Add to the circular command queue the next command from:
|
||||
* - The command-injection queue (injected_commands_P)
|
||||
* - The active serial input (usually USB)
|
||||
* - The SD card file being actively printed
|
||||
*/
|
||||
void get_available_commands() {
|
||||
|
||||
// if any immediate commands remain, don't get other commands yet
|
||||
if (drain_injected_commands_P()) return;
|
||||
|
||||
get_serial_commands();
|
||||
|
||||
#if ENABLED(SDSUPPORT)
|
||||
get_sdcard_commands();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next command in the queue, optionally log it to SD, then dispatch it
|
||||
*/
|
||||
void advance_command_queue() {
|
||||
|
||||
if (!commands_in_queue) return;
|
||||
|
||||
#if ENABLED(SDSUPPORT)
|
||||
|
||||
if (card.saving) {
|
||||
char* command = command_queue[cmd_queue_index_r];
|
||||
if (strstr_P(command, PSTR("M29"))) {
|
||||
// M29 closes the file
|
||||
card.closefile();
|
||||
SERIAL_PROTOCOLLNPGM(MSG_FILE_SAVED);
|
||||
ok_to_send();
|
||||
}
|
||||
else {
|
||||
// Write the string from the read buffer to SD
|
||||
card.write_command(command);
|
||||
if (card.logging)
|
||||
gcode.process_next_command(); // The card is saving because it's logging
|
||||
else
|
||||
ok_to_send();
|
||||
}
|
||||
}
|
||||
else
|
||||
gcode.process_next_command();
|
||||
|
||||
#else
|
||||
|
||||
gcode.process_next_command();
|
||||
|
||||
#endif // SDSUPPORT
|
||||
|
||||
// The queue may be reset by a command handler or by code invoked by idle() within a handler
|
||||
if (commands_in_queue) {
|
||||
--commands_in_queue;
|
||||
if (++cmd_queue_index_r >= BUFSIZE) cmd_queue_index_r = 0;
|
||||
}
|
||||
|
||||
}
|
106
Marlin/src/gcode/queue.h
Normal file
106
Marlin/src/gcode/queue.h
Normal file
@ -0,0 +1,106 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* queue.h - The G-code command queue, which holds commands before they
|
||||
* go to the parser and dispatcher.
|
||||
*/
|
||||
|
||||
#ifndef GCODE_QUEUE_H
|
||||
#define GCODE_QUEUE_H
|
||||
|
||||
#include "../inc/MarlinConfig.h"
|
||||
|
||||
/**
|
||||
* GCode line number handling. Hosts may include line numbers when sending
|
||||
* commands to Marlin, and lines will be checked for sequentiality.
|
||||
* M110 N<int> sets the current line number.
|
||||
*/
|
||||
extern long gcode_LastN, Stopped_gcode_LastN;
|
||||
|
||||
/**
|
||||
* GCode Command Queue
|
||||
* A simple ring buffer of BUFSIZE command strings.
|
||||
*
|
||||
* Commands are copied into this buffer by the command injectors
|
||||
* (immediate, serial, sd card) and they are processed sequentially by
|
||||
* the main loop. The gcode.process_next_command method parses the next
|
||||
* command and hands off execution to individual handler functions.
|
||||
*/
|
||||
extern uint8_t commands_in_queue, // Count of commands in the queue
|
||||
cmd_queue_index_r; // Ring buffer read position
|
||||
|
||||
extern char command_queue[BUFSIZE][MAX_CMD_SIZE];
|
||||
|
||||
/**
|
||||
* Initialization of queue for setup()
|
||||
*/
|
||||
void queue_setup();
|
||||
|
||||
/**
|
||||
* Clear the Marlin command queue
|
||||
*/
|
||||
void clear_command_queue();
|
||||
|
||||
/**
|
||||
* Clear the serial line and request a resend of
|
||||
* the next expected line number.
|
||||
*/
|
||||
void flush_and_request_resend();
|
||||
|
||||
/**
|
||||
* Send an "ok" message to the host, indicating
|
||||
* that a command was successfully processed.
|
||||
*
|
||||
* If ADVANCED_OK is enabled also include:
|
||||
* N<int> Line number of the command, if any
|
||||
* P<int> Planner space remaining
|
||||
* B<int> Block queue space remaining
|
||||
*/
|
||||
void ok_to_send();
|
||||
|
||||
/**
|
||||
* Record one or many commands to run from program memory.
|
||||
* Aborts the current queue, if any.
|
||||
* Note: drain_injected_commands_P() must be called repeatedly to drain the commands afterwards
|
||||
*/
|
||||
void enqueue_and_echo_commands_P(const char * const pgcode);
|
||||
|
||||
/**
|
||||
* Enqueue with Serial Echo
|
||||
*/
|
||||
bool enqueue_and_echo_command(const char* cmd, bool say_ok=false);
|
||||
|
||||
/**
|
||||
* Add to the circular command queue the next command from:
|
||||
* - The command-injection queue (injected_commands_P)
|
||||
* - The active serial input (usually USB)
|
||||
* - The SD card file being actively printed
|
||||
*/
|
||||
void get_available_commands();
|
||||
|
||||
/**
|
||||
* Get the next command in the queue, optionally log it to SD, then dispatch it
|
||||
*/
|
||||
void advance_command_queue();
|
||||
|
||||
#endif // GCODE_QUEUE_H
|
@ -20,23 +20,35 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../gcode.h"
|
||||
#include "../../module/temperature.h"
|
||||
#include "../../module/motion.h"
|
||||
#include "../../module/planner.h"
|
||||
#include "../../lcd/ultralcd.h"
|
||||
|
||||
#if ENABLED(PRINTJOB_TIMER_AUTOSTART)
|
||||
#include "../../module/printcounter.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* M104: Set hot end temperature
|
||||
*/
|
||||
void gcode_M104() {
|
||||
if (get_target_extruder_from_command(104)) return;
|
||||
void GcodeSuite::M104() {
|
||||
if (get_target_extruder_from_command()) return;
|
||||
if (DEBUGGING(DRYRUN)) return;
|
||||
|
||||
const uint8_t e = target_extruder;
|
||||
|
||||
#if ENABLED(SINGLENOZZLE)
|
||||
if (target_extruder != active_extruder) return;
|
||||
if (e != active_extruder) return;
|
||||
#endif
|
||||
|
||||
if (parser.seenval('S')) {
|
||||
const int16_t temp = parser.value_celsius();
|
||||
thermalManager.setTargetHotend(temp, target_extruder);
|
||||
thermalManager.setTargetHotend(temp, e);
|
||||
|
||||
#if ENABLED(DUAL_X_CARRIAGE)
|
||||
if (dual_x_carriage_mode == DXC_DUPLICATION_MODE && target_extruder == 0)
|
||||
if (dual_x_carriage_mode == DXC_DUPLICATION_MODE && e == 0)
|
||||
thermalManager.setTargetHotend(temp ? temp + duplicate_extruder_temp_offset : 0, 1);
|
||||
#endif
|
||||
|
||||
@ -53,8 +65,8 @@ void gcode_M104() {
|
||||
}
|
||||
#endif
|
||||
|
||||
if (parser.value_celsius() > thermalManager.degHotend(target_extruder))
|
||||
lcd_status_printf_P(0, PSTR("E%i %s"), target_extruder + 1, MSG_HEATING);
|
||||
if (parser.value_celsius() > thermalManager.degHotend(e))
|
||||
lcd_status_printf_P(0, PSTR("E%i %s"), e + 1, MSG_HEATING);
|
||||
}
|
||||
|
||||
#if ENABLED(AUTOTEMP)
|
@ -24,7 +24,7 @@
|
||||
* M105: Read hot end and bed temperature
|
||||
*/
|
||||
void gcode_M105() {
|
||||
if (get_target_extruder_from_command(105)) return;
|
||||
if (gcode.get_target_extruder_from_command()) return;
|
||||
|
||||
#if HAS_TEMP_HOTEND || HAS_TEMP_BED
|
||||
SERIAL_PROTOCOLPGM(MSG_OK);
|
||||
|
@ -20,6 +20,20 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../gcode.h"
|
||||
#include "../../module/temperature.h"
|
||||
#include "../../module/planner.h"
|
||||
#include "../../lcd/ultralcd.h"
|
||||
#include "../../Marlin.h"
|
||||
|
||||
#if ENABLED(PRINTJOB_TIMER_AUTOSTART)
|
||||
#include "../../module/printcounter.h"
|
||||
#endif
|
||||
|
||||
#if ENABLED(DUAL_X_CARRIAGE)
|
||||
#include "../../module/motion.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* M109: Sxxx Wait for extruder(s) to reach temperature. Waits only when heating.
|
||||
* Rxxx Wait for extruder(s) to reach temperature. Waits when heating and cooling.
|
||||
@ -32,9 +46,9 @@
|
||||
#define MIN_COOLING_SLOPE_TIME 60
|
||||
#endif
|
||||
|
||||
void gcode_M109() {
|
||||
void GcodeSuite::M109() {
|
||||
|
||||
if (get_target_extruder_from_command(109)) return;
|
||||
if (get_target_extruder_from_command()) return;
|
||||
if (DEBUGGING(DRYRUN)) return;
|
||||
|
||||
#if ENABLED(SINGLENOZZLE)
|
@ -20,6 +20,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../gcode.h"
|
||||
|
||||
#ifndef MIN_COOLING_SLOPE_DEG_BED
|
||||
#define MIN_COOLING_SLOPE_DEG_BED 1.50
|
||||
#endif
|
||||
@ -63,7 +65,7 @@ void gcode_M190() {
|
||||
KEEPALIVE_STATE(NOT_BUSY);
|
||||
#endif
|
||||
|
||||
target_extruder = active_extruder; // for print_heaterstates
|
||||
gcode.target_extruder = active_extruder; // for print_heaterstates
|
||||
|
||||
#if ENABLED(PRINTER_EVENT_LEDS)
|
||||
const float start_temp = thermalManager.degBed();
|
||||
@ -95,7 +97,7 @@ void gcode_M190() {
|
||||
}
|
||||
|
||||
idle();
|
||||
refresh_cmd_timeout(); // to prevent stepper_inactive_time from running out
|
||||
gcode.refresh_cmd_timeout(); // to prevent stepper_inactive_time from running out
|
||||
|
||||
const float temp = thermalManager.degBed();
|
||||
|
||||
|
@ -20,6 +20,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../gcode.h"
|
||||
#include "../../module/temperature.h"
|
||||
|
||||
/**
|
||||
* M303: PID relay autotune
|
||||
*
|
||||
@ -28,7 +31,7 @@
|
||||
* C<cycles>
|
||||
* U<bool> with a non-zero value will apply the result to current settings
|
||||
*/
|
||||
void gcode_M303() {
|
||||
void GcodeSuite::M303() {
|
||||
#if HAS_PID_HEATING
|
||||
const int e = parser.intval('E'), c = parser.intval('C', 5);
|
||||
const bool u = parser.boolval('U');
|
@ -23,9 +23,9 @@
|
||||
/**
|
||||
* M82: Set E codes absolute (default)
|
||||
*/
|
||||
void gcode_M82() { axis_relative_modes[E_AXIS] = false; }
|
||||
void gcode_M82() { gcode.axis_relative_modes[E_AXIS] = false; }
|
||||
|
||||
/**
|
||||
* M83: Set E codes relative while in Absolute Coordinates (G90) mode
|
||||
*/
|
||||
void gcode_M83() { axis_relative_modes[E_AXIS] = true; }
|
||||
void gcode_M83() { gcode.axis_relative_modes[E_AXIS] = true; }
|
||||
|
Reference in New Issue
Block a user