LAT Hologramm-Software 2.0
Loading...
Searching...
No Matches
protocol.c
Go to the documentation of this file.
1/*
2 protocol.c - controls Grbl execution protocol and procedures
3 Part of Grbl
4
5 Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC
6 Copyright (c) 2009-2011 Simen Svale Skogsrud
7
8 Grbl is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
12
13 Grbl is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with Grbl. If not, see <http://www.gnu.org/licenses/>.
20*/
21
22#include "grbl.h"
23
24// Define line flags. Includes comment type tracking and line overflow detection.
25#define LINE_FLAG_OVERFLOW bit(0)
26#define LINE_FLAG_COMMENT_PARENTHESES bit(1)
27#define LINE_FLAG_COMMENT_SEMICOLON bit(2)
28
29
30static char line[LINE_BUFFER_SIZE]; // Line to be executed. Zero-terminated.
31
32static void protocol_exec_rt_suspend();
33
34
35/*
36 GRBL PRIMARY LOOP:
37*/
39{
40 // Perform some machine checks to make sure everything is good to go.
41 #ifdef CHECK_LIMITS_AT_INIT
43 if (limits_get_state()) {
44 sys.state = STATE_ALARM; // Ensure alarm state is active.
46 }
47 }
48 #endif
49 // Check for and report alarm state after a reset, error, or an initial power up.
50 // NOTE: Sleep mode disables the stepper drivers and position can't be guaranteed.
51 // Re-initialize the sleep state as an ALARM mode to ensure user homes or acknowledges.
52 if (sys.state & (STATE_ALARM | STATE_SLEEP)) {
54 sys.state = STATE_ALARM; // Ensure alarm state is set.
55 } else {
56 // Check if the safety door is open.
60 protocol_execute_realtime(); // Enter safety door mode. Should return as IDLE state.
61 }
62 // All systems go!
63 system_execute_startup(line); // Execute startup script.
64 }
65
66 // ---------------------------------------------------------------------------------
67 // Primary loop! Upon a system abort, this exits back to main() to reset the system.
68 // This is also where Grbl idles while waiting for something to do.
69 // ---------------------------------------------------------------------------------
70
71 uint8_t line_flags = 0;
72 uint8_t char_counter = 0;
73 uint8_t c;
74 for (;;) {
75
76 // Process one line of incoming serial data, as the data becomes available. Performs an
77 // initial filtering by removing spaces and comments and capitalizing all letters.
78 while((c = serial_read()) != SERIAL_NO_DATA) {
79 if ((c == '\n') || (c == '\r')) { // End of line reached
80
81 protocol_execute_realtime(); // Runtime command check point.
82 if (sys.abort) { return; } // Bail to calling function upon system abort
83
84 line[char_counter] = 0; // Set string termination character.
85 #ifdef REPORT_ECHO_LINE_RECEIVED
87 #endif
88
89 // Direct and execute one line of formatted input, and report status of execution.
90 if (line_flags & LINE_FLAG_OVERFLOW) {
91 // Report line overflow error.
93 } else if (line[0] == 0) {
94 // Empty or comment line. For syncing purposes.
96 } else if (line[0] == '$') {
97 // Grbl '$' system command
99 } else if (sys.state & (STATE_ALARM | STATE_JOG)) {
100 // Everything else is gcode. Block if in alarm or jog mode.
102 } else {
103 // Parse and execute g-code block.
105 }
106
107 // Reset tracking data for next line.
108 line_flags = 0;
109 char_counter = 0;
110
111 } else {
112
113 if (line_flags) {
114 // Throw away all (except EOL) comment characters and overflow characters.
115 if (c == ')') {
116 // End of '()' comment. Resume line allowed.
117 if (line_flags & LINE_FLAG_COMMENT_PARENTHESES) { line_flags &= ~(LINE_FLAG_COMMENT_PARENTHESES); }
118 }
119 } else {
120 if (c <= ' ') {
121 // Throw away whitepace and control characters
122 } else if (c == '/') {
123 // Block delete NOT SUPPORTED. Ignore character.
124 // NOTE: If supported, would simply need to check the system if block delete is enabled.
125 } else if (c == '(') {
126 // Enable comments flag and ignore all characters until ')' or EOL.
127 // NOTE: This doesn't follow the NIST definition exactly, but is good enough for now.
128 // In the future, we could simply remove the items within the comments, but retain the
129 // comment control characters, so that the g-code parser can error-check it.
130 line_flags |= LINE_FLAG_COMMENT_PARENTHESES;
131 } else if (c == ';') {
132 // NOTE: ';' comment to EOL is a LinuxCNC definition. Not NIST.
133 line_flags |= LINE_FLAG_COMMENT_SEMICOLON;
134 // TODO: Install '%' feature
135 // } else if (c == '%') {
136 // Program start-end percent sign NOT SUPPORTED.
137 // NOTE: This maybe installed to tell Grbl when a program is running vs manual input,
138 // where, during a program, the system auto-cycle start will continue to execute
139 // everything until the next '%' sign. This will help fix resuming issues with certain
140 // functions that empty the planner buffer to execute its task on-time.
141 } else if (char_counter >= (LINE_BUFFER_SIZE-1)) {
142 // Detect line buffer overflow and set flag.
143 line_flags |= LINE_FLAG_OVERFLOW;
144 } else if (c >= 'a' && c <= 'z') { // Upcase lowercase
145 line[char_counter++] = c-'a'+'A';
146 } else {
147 line[char_counter++] = c;
148 }
149 }
150
151 }
152 }
153
154 // If there are no more characters in the serial read buffer to be processed and executed,
155 // this indicates that g-code streaming has either filled the planner buffer or has
156 // completed. In either case, auto-cycle start, if enabled, any queued moves.
158
159 protocol_execute_realtime(); // Runtime command check point.
160 if (sys.abort) { return; } // Bail to main() program loop to reset system.
161 }
162
163 return; /* Never reached */
164}
165
166
167// Block until all buffered steps are executed or in a cycle state. Works with feed hold
168// during a synchronize call, if it should happen. Also, waits for clean cycle end.
170{
171 // If system is queued, ensure cycle resumes if the auto start flag is present.
173 do {
174 protocol_execute_realtime(); // Check and execute run-time commands
175 if (sys.abort) { return; } // Check for system abort
176 } while (plan_get_current_block() || (sys.state == STATE_CYCLE));
177}
178
179
180// Auto-cycle start triggers when there is a motion ready to execute and if the main program is not
181// actively parsing commands.
182// NOTE: This function is called from the main loop, buffer sync, and mc_line() only and executes
183// when one of these conditions exist respectively: There are no more blocks sent (i.e. streaming
184// is finished, single commands), a command that needs to wait for the motions in the buffer to
185// execute calls a buffer sync, or the planner buffer is full and ready to go.
187{
188 if (plan_get_current_block() != NULL) { // Check if there are any blocks in the buffer.
189 system_set_exec_state_flag(EXEC_CYCLE_START); // If so, execute them!
190 }
191}
192
193
194// This function is the general interface to Grbl's real-time command execution system. It is called
195// from various check points in the main program, primarily where there may be a while loop waiting
196// for a buffer to clear space or any point where the execution time from the last check point may
197// be more than a fraction of a second. This is a way to execute realtime commands asynchronously
198// (aka multitasking) with grbl's g-code parsing and planning functions. This function also serves
199// as an interface for the interrupts to set the system realtime flags, where only the main program
200// handles them, removing the need to define more computationally-expensive volatile variables. This
201// also provides a controlled way to execute certain tasks without having two or more instances of
202// the same task, such as the planner recalculating the buffer upon a feedhold or overrides.
203// NOTE: The sys_rt_exec_state variable flags are set by any process, step or serial interrupts, pinouts,
204// limit switches, or the main program.
206{
209}
210
211
212// Executes run-time commands, when required. This function primarily operates as Grbl's state
213// machine and controls the various real-time features Grbl has to offer.
214// NOTE: Do not alter this unless you know exactly what you are doing!
216{
217 uint8_t rt_exec; // Temp variable to avoid calling volatile multiple times.
218 rt_exec = sys_rt_exec_alarm; // Copy volatile sys_rt_exec_alarm.
219 if (rt_exec) { // Enter only if any bit flag is true
220 // System alarm. Everything has shutdown by something that has gone severely wrong. Report
221 // the source of the error to the user. If critical, Grbl disables by entering an infinite
222 // loop until system reset/abort.
223 sys.state = STATE_ALARM; // Set system alarm state
224 report_alarm_message(rt_exec);
225 // Halt everything upon a critical event flag. Currently hard and soft limits flag this.
226 if ((rt_exec == EXEC_ALARM_HARD_LIMIT) || (rt_exec == EXEC_ALARM_SOFT_LIMIT)) {
228 system_clear_exec_state_flag(EXEC_RESET); // Disable any existing reset
229 do {
230 // Block everything, except reset and status reports, until user issues reset or power
231 // cycles. Hard limits typically occur while unattended or not paying attention. Gives
232 // the user and a GUI time to do what is needed before resetting, like killing the
233 // incoming stream. The same could be said about soft limits. While the position is not
234 // lost, continued streaming could cause a serious crash if by chance it gets executed.
236 }
237 system_clear_exec_alarm(); // Clear alarm
238 }
239
240 rt_exec = sys_rt_exec_state; // Copy volatile sys_rt_exec_state.
241 if (rt_exec) {
242
243 // Execute system abort.
244 if (rt_exec & EXEC_RESET) {
245 sys.abort = true; // Only place this is set true.
246 return; // Nothing else to do but exit.
247 }
248
249 // Execute and serial print status
250 if (rt_exec & EXEC_STATUS_REPORT) {
253 }
254
255 // NOTE: Once hold is initiated, the system immediately enters a suspend state to block all
256 // main program processes until either reset or resumed. This ensures a hold completes safely.
258
259 // State check for allowable states for hold methods.
260 if (!(sys.state & (STATE_ALARM | STATE_CHECK_MODE))) {
261
262 // If in CYCLE or JOG states, immediately initiate a motion HOLD.
263 if (sys.state & (STATE_CYCLE | STATE_JOG)) {
264 if (!(sys.suspend & (SUSPEND_MOTION_CANCEL | SUSPEND_JOG_CANCEL))) { // Block, if already holding.
265 st_update_plan_block_parameters(); // Notify stepper module to recompute for hold deceleration.
266 sys.step_control = STEP_CONTROL_EXECUTE_HOLD; // Initiate suspend state with active flag.
267 if (sys.state == STATE_JOG) { // Jog cancelled upon any hold event, except for sleeping.
268 if (!(rt_exec & EXEC_SLEEP)) { sys.suspend |= SUSPEND_JOG_CANCEL; }
269 }
270 }
271 }
272 // If IDLE, Grbl is not in motion. Simply indicate suspend state and hold is complete.
274
275 // Execute and flag a motion cancel with deceleration and return to idle. Used primarily by probing cycle
276 // to halt and cancel the remainder of the motion.
277 if (rt_exec & EXEC_MOTION_CANCEL) {
278 // MOTION_CANCEL only occurs during a CYCLE, but a HOLD and SAFETY_DOOR may been initiated beforehand
279 // to hold the CYCLE. Motion cancel is valid for a single planner block motion only, while jog cancel
280 // will handle and clear multiple planner block motions.
281 if (!(sys.state & STATE_JOG)) { sys.suspend |= SUSPEND_MOTION_CANCEL; } // NOTE: State is STATE_CYCLE.
282 }
283
284 // Execute a feed hold with deceleration, if required. Then, suspend system.
285 if (rt_exec & EXEC_FEED_HOLD) {
286 // Block SAFETY_DOOR, JOG, and SLEEP states from changing to HOLD state.
288 }
289
290 // Execute a safety door stop with a feed hold and disable spindle/coolant.
291 // NOTE: Safety door differs from feed holds by stopping everything no matter state, disables powered
292 // devices (spindle/coolant), and blocks resuming until switch is re-engaged.
293 if (rt_exec & EXEC_SAFETY_DOOR) {
295 // If jogging, block safety door methods until jog cancel is complete. Just flag that it happened.
296 if (!(sys.suspend & SUSPEND_JOG_CANCEL)) {
297 // Check if the safety re-opened during a restore parking motion only. Ignore if
298 // already retracting, parked or in sleep state.
299 if (sys.state == STATE_SAFETY_DOOR) {
300 if (sys.suspend & SUSPEND_INITIATE_RESTORE) { // Actively restoring
301 #ifdef PARKING_ENABLE
302 // Set hold and reset appropriate control flags to restart parking sequence.
304 st_update_plan_block_parameters(); // Notify stepper module to recompute for hold deceleration.
307 } // else NO_MOTION is active.
308 #endif
311 }
312 }
314 }
315 // NOTE: This flag doesn't change when the door closes, unlike sys.state. Ensures any parking motions
316 // are executed if the door switch closes and the state returns to HOLD.
318 }
319
320 }
321
322 if (rt_exec & EXEC_SLEEP) {
325 }
326
328 }
329
330 // Execute a cycle start by starting the stepper interrupt to begin executing the blocks in queue.
331 if (rt_exec & EXEC_CYCLE_START) {
332 // Block if called at same time as the hold commands: feed hold, motion cancel, and safety door.
333 // Ensures auto-cycle-start doesn't resume a hold without an explicit user-input.
334 if (!(rt_exec & (EXEC_FEED_HOLD | EXEC_MOTION_CANCEL | EXEC_SAFETY_DOOR))) {
335 // Resume door state when parking motion has retracted and door has been closed.
338 sys.state = STATE_IDLE; // Set to IDLE to immediately resume the cycle.
339 } else if (sys.suspend & SUSPEND_RETRACT_COMPLETE) {
340 // Flag to re-energize powered components and restore original position, if disabled by SAFETY_DOOR.
341 // NOTE: For a safety door to resume, the switch must be closed, as indicated by HOLD state, and
342 // the retraction execution is complete, which implies the initial feed hold is not active. To
343 // restore normal operation, the restore procedures must be initiated by the following flag. Once,
344 // they are complete, it will call CYCLE_START automatically to resume and exit the suspend.
346 }
347 }
348 // Cycle start only when IDLE or when a hold is complete and ready to resume.
351 sys.spindle_stop_ovr |= SPINDLE_STOP_OVR_RESTORE_CYCLE; // Set to restore in suspend routine and cycle start after.
352 } else {
353 // Start cycle only if queued motions exist in planner buffer and the motion is not canceled.
354 sys.step_control = STEP_CONTROL_NORMAL_OP; // Restore step control to normal operation
356 sys.suspend = SUSPEND_DISABLE; // Break suspend state.
358 st_prep_buffer(); // Initialize step segment buffer before beginning cycle.
359 st_wake_up();
360 } else { // Otherwise, do nothing. Set and resume IDLE state.
361 sys.suspend = SUSPEND_DISABLE; // Break suspend state.
363 }
364 }
365 }
366 }
368 }
369
370 if (rt_exec & EXEC_CYCLE_STOP) {
371 // Reinitializes the cycle plan and stepper system after a feed hold for a resume. Called by
372 // realtime command execution in the main program, ensuring that the planner re-plans safely.
373 // NOTE: Bresenham algorithm variables are still maintained through both the planner and stepper
374 // cycle reinitializations. The stepper path should continue exactly as if nothing has happened.
375 // NOTE: EXEC_CYCLE_STOP is set by the stepper subsystem when a cycle or feed hold completes.
377 // Hold complete. Set to indicate ready to resume. Remain in HOLD or DOOR states until user
378 // has issued a resume command or reset.
382 } else {
383 // Motion complete. Includes CYCLE/JOG/HOMING states and jog cancel/motion cancel/soft limit events.
384 // NOTE: Motion and jog cancel both immediately return to idle after the hold completes.
385 if (sys.suspend & SUSPEND_JOG_CANCEL) { // For jog cancel, flush buffers and sync positions.
387 plan_reset();
388 st_reset();
391 }
392 if (sys.suspend & SUSPEND_SAFETY_DOOR_AJAR) { // Only occurs when safety door opens during jog.
396 } else {
399 }
400 }
402 }
403 }
404
405 // Execute overrides.
406 rt_exec = sys_rt_exec_motion_override; // Copy volatile sys_rt_exec_motion_override
407 if (rt_exec) {
408 system_clear_exec_motion_overrides(); // Clear all motion override flags.
409
410 uint8_t new_f_override = sys.f_override;
411 if (rt_exec & EXEC_FEED_OVR_RESET) { new_f_override = DEFAULT_FEED_OVERRIDE; }
412 if (rt_exec & EXEC_FEED_OVR_COARSE_PLUS) { new_f_override += FEED_OVERRIDE_COARSE_INCREMENT; }
413 if (rt_exec & EXEC_FEED_OVR_COARSE_MINUS) { new_f_override -= FEED_OVERRIDE_COARSE_INCREMENT; }
414 if (rt_exec & EXEC_FEED_OVR_FINE_PLUS) { new_f_override += FEED_OVERRIDE_FINE_INCREMENT; }
415 if (rt_exec & EXEC_FEED_OVR_FINE_MINUS) { new_f_override -= FEED_OVERRIDE_FINE_INCREMENT; }
416 new_f_override = min(new_f_override,MAX_FEED_RATE_OVERRIDE);
417 new_f_override = max(new_f_override,MIN_FEED_RATE_OVERRIDE);
418
419 uint8_t new_r_override = sys.r_override;
420 if (rt_exec & EXEC_RAPID_OVR_RESET) { new_r_override = DEFAULT_RAPID_OVERRIDE; }
421 if (rt_exec & EXEC_RAPID_OVR_MEDIUM) { new_r_override = RAPID_OVERRIDE_MEDIUM; }
422 if (rt_exec & EXEC_RAPID_OVR_LOW) { new_r_override = RAPID_OVERRIDE_LOW; }
423
424 if ((new_f_override != sys.f_override) || (new_r_override != sys.r_override)) {
425 sys.f_override = new_f_override;
426 sys.r_override = new_r_override;
427 sys.report_ovr_counter = 0; // Set to report change immediately
430 }
431 }
432
434 if (rt_exec) {
435 system_clear_exec_accessory_overrides(); // Clear all accessory override flags.
436
437 // NOTE: Unlike motion overrides, spindle overrides do not require a planner reinitialization.
438 uint8_t last_s_override = sys.spindle_speed_ovr;
439 if (rt_exec & EXEC_SPINDLE_OVR_RESET) { last_s_override = DEFAULT_SPINDLE_SPEED_OVERRIDE; }
440 if (rt_exec & EXEC_SPINDLE_OVR_COARSE_PLUS) { last_s_override += SPINDLE_OVERRIDE_COARSE_INCREMENT; }
441 if (rt_exec & EXEC_SPINDLE_OVR_COARSE_MINUS) { last_s_override -= SPINDLE_OVERRIDE_COARSE_INCREMENT; }
442 if (rt_exec & EXEC_SPINDLE_OVR_FINE_PLUS) { last_s_override += SPINDLE_OVERRIDE_FINE_INCREMENT; }
443 if (rt_exec & EXEC_SPINDLE_OVR_FINE_MINUS) { last_s_override -= SPINDLE_OVERRIDE_FINE_INCREMENT; }
444 last_s_override = min(last_s_override,MAX_SPINDLE_SPEED_OVERRIDE);
445 last_s_override = max(last_s_override,MIN_SPINDLE_SPEED_OVERRIDE);
446
447 if (last_s_override != sys.spindle_speed_ovr) {
448 sys.spindle_speed_ovr = last_s_override;
449 // NOTE: Spindle speed overrides during HOLD state are taken care of by suspend function.
452 sys.report_ovr_counter = 0; // Set to report change immediately
453 }
454
455 if (rt_exec & EXEC_SPINDLE_OVR_STOP) {
456 // Spindle stop override allowed only while in HOLD state.
457 // NOTE: Report counters are set in spindle_set_state() when spindle stop is executed.
458 if (sys.state == STATE_HOLD) {
461 }
462 }
463
464 // NOTE: Since coolant state always performs a planner sync whenever it changes, the current
465 // run state can be determined by checking the parser state.
466 // NOTE: Coolant overrides only operate during IDLE, CYCLE, HOLD, and JOG states. Ignored otherwise.
469 uint8_t coolant_state = gc_state.modal.coolant;
470 #ifdef ENABLE_M7
471 if (rt_exec & EXEC_COOLANT_MIST_OVR_TOGGLE) {
472 if (coolant_state & COOLANT_MIST_ENABLE) { bit_false(coolant_state,COOLANT_MIST_ENABLE); }
473 else { coolant_state |= COOLANT_MIST_ENABLE; }
474 }
475 if (rt_exec & EXEC_COOLANT_FLOOD_OVR_TOGGLE) {
476 if (coolant_state & COOLANT_FLOOD_ENABLE) { bit_false(coolant_state,COOLANT_FLOOD_ENABLE); }
477 else { coolant_state |= COOLANT_FLOOD_ENABLE; }
478 }
479 #else
480 if (coolant_state & COOLANT_FLOOD_ENABLE) { bit_false(coolant_state,COOLANT_FLOOD_ENABLE); }
481 else { coolant_state |= COOLANT_FLOOD_ENABLE; }
482 #endif
483 coolant_set_state(coolant_state); // Report counter set in coolant_set_state().
484 gc_state.modal.coolant = coolant_state;
485 }
486 }
487 }
488
489 #ifdef DEBUG
490 if (sys_rt_exec_debug) {
491 report_realtime_debug();
492 sys_rt_exec_debug = 0;
493 }
494 #endif
495
496 // Reload step segment buffer
499 }
500
501}
502
503
504// Handles Grbl system suspend procedures, such as feed hold, safety door, and parking motion.
505// The system will enter this loop, create local variables for suspend tasks, and return to
506// whatever function that invoked the suspend, such that Grbl resumes normal operation.
507// This function is written in a way to promote custom parking motions. Simply use this as a
508// template
510{
511 #ifdef PARKING_ENABLE
512 // Declare and initialize parking local variables
513 float restore_target[N_AXIS];
514 float parking_target[N_AXIS];
515 float retract_waypoint = PARKING_PULLOUT_INCREMENT;
516 plan_line_data_t plan_data;
517 plan_line_data_t *pl_data = &plan_data;
518 memset(pl_data,0,sizeof(plan_line_data_t));
520 #ifdef USE_LINE_NUMBERS
521 pl_data->line_number = PARKING_MOTION_LINE_NUMBER;
522 #endif
523 #endif
524
526 uint8_t restore_condition;
527 #ifdef VARIABLE_SPINDLE
528 float restore_spindle_speed;
529 if (block == NULL) {
530 restore_condition = (gc_state.modal.spindle | gc_state.modal.coolant);
531 restore_spindle_speed = gc_state.spindle_speed;
532 } else {
533 restore_condition = (block->condition & PL_COND_SPINDLE_MASK) | coolant_get_state();
534 restore_spindle_speed = block->spindle_speed;
535 }
536 #ifdef DISABLE_LASER_DURING_HOLD
539 }
540 #endif
541 #else
542 if (block == NULL) { restore_condition = (gc_state.modal.spindle | gc_state.modal.coolant); }
543 else { restore_condition = (block->condition & PL_COND_SPINDLE_MASK) | coolant_get_state(); }
544 #endif
545
546 while (sys.suspend) {
547
548 if (sys.abort) { return; }
549
550 // Block until initial hold is complete and the machine has stopped motion.
552
553 // Parking manager. Handles de/re-energizing, switch state checks, and parking motions for
554 // the safety door and sleep states.
556
557 // Handles retraction motions and de-energizing.
559
560 // Ensure any prior spindle stop override is disabled at start of safety door routine.
562
563 #ifndef PARKING_ENABLE
564
565 spindle_set_state(SPINDLE_DISABLE,0.0); // De-energize
566 coolant_set_state(COOLANT_DISABLE); // De-energize
567
568 #else
569
570 // Get current position and store restore location and spindle retract waypoint.
573 memcpy(restore_target,parking_target,sizeof(parking_target));
574 retract_waypoint += restore_target[PARKING_AXIS];
575 retract_waypoint = min(retract_waypoint,PARKING_TARGET);
576 }
577
578 // Execute slow pull-out parking retract motion. Parking requires homing enabled, the
579 // current location not exceeding the parking target location, and laser mode disabled.
580 // NOTE: State is will remain DOOR, until the de-energizing and retract is complete.
581 #ifdef ENABLE_PARKING_OVERRIDE_CONTROL
583 (parking_target[PARKING_AXIS] < PARKING_TARGET) &&
585 (sys.override_ctrl == OVERRIDE_PARKING_MOTION)) {
586 #else
588 (parking_target[PARKING_AXIS] < PARKING_TARGET) &&
590 #endif
591 // Retract spindle by pullout distance. Ensure retraction motion moves away from
592 // the workpiece and waypoint motion doesn't exceed the parking target location.
593 if (parking_target[PARKING_AXIS] < retract_waypoint) {
594 parking_target[PARKING_AXIS] = retract_waypoint;
596 pl_data->condition |= (restore_condition & PL_COND_ACCESSORY_MASK); // Retain accessory state
597 pl_data->spindle_speed = restore_spindle_speed;
598 mc_parking_motion(parking_target, pl_data);
599 }
600
601 // NOTE: Clear accessory state after retract and after an aborted restore motion.
603 pl_data->spindle_speed = 0.0;
604 spindle_set_state(SPINDLE_DISABLE,0.0); // De-energize
605 coolant_set_state(COOLANT_DISABLE); // De-energize
606
607 // Execute fast parking retract motion to parking target location.
608 if (parking_target[PARKING_AXIS] < PARKING_TARGET) {
609 parking_target[PARKING_AXIS] = PARKING_TARGET;
610 pl_data->feed_rate = PARKING_RATE;
611 mc_parking_motion(parking_target, pl_data);
612 }
613
614 } else {
615
616 // Parking motion not possible. Just disable the spindle and coolant.
617 // NOTE: Laser mode does not start a parking motion to ensure the laser stops immediately.
618 spindle_set_state(SPINDLE_DISABLE,0.0); // De-energize
619 coolant_set_state(COOLANT_DISABLE); // De-energize
620
621 }
622
623 #endif
624
627
628 } else {
629
630
631 if (sys.state == STATE_SLEEP) {
633 // Spindle and coolant should already be stopped, but do it again just to be sure.
634 spindle_set_state(SPINDLE_DISABLE,0.0); // De-energize
635 coolant_set_state(COOLANT_DISABLE); // De-energize
636 st_go_idle(); // Disable steppers
637 while (!(sys.abort)) { protocol_exec_rt_system(); } // Do nothing until reset.
638 return; // Abort received. Return to re-initialize.
639 }
640
641 // Allows resuming from parking/safety door. Actively checks if safety door is closed and ready to resume.
642 if (sys.state == STATE_SAFETY_DOOR) {
644 sys.suspend &= ~(SUSPEND_SAFETY_DOOR_AJAR); // Reset door ajar flag to denote ready to resume.
645 }
646 }
647
648 // Handles parking restore and safety door resume.
650
651 #ifdef PARKING_ENABLE
652 // Execute fast restore motion to the pull-out position. Parking requires homing enabled.
653 // NOTE: State is will remain DOOR, until the de-energizing and retract is complete.
654 #ifdef ENABLE_PARKING_OVERRIDE_CONTROL
656 (sys.override_ctrl == OVERRIDE_PARKING_MOTION)) {
657 #else
659 #endif
660 // Check to ensure the motion doesn't move below pull-out position.
661 if (parking_target[PARKING_AXIS] <= PARKING_TARGET) {
662 parking_target[PARKING_AXIS] = retract_waypoint;
663 pl_data->feed_rate = PARKING_RATE;
664 mc_parking_motion(parking_target, pl_data);
665 }
666 }
667 #endif
668
669 // Delayed Tasks: Restart spindle and coolant, delay to power-up, then resume cycle.
671 // Block if safety door re-opened during prior restore actions.
674 // When in laser mode, ignore spindle spin-up delay. Set to turn on laser when cycle starts.
676 } else {
677 spindle_set_state((restore_condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)), restore_spindle_speed);
679 }
680 }
681 }
683 // Block if safety door re-opened during prior restore actions.
685 // NOTE: Laser mode will honor this delay. An exhaust system is often controlled by this pin.
688 }
689 }
690
691 #ifdef PARKING_ENABLE
692 // Execute slow plunge motion from pull-out position to resume position.
693 #ifdef ENABLE_PARKING_OVERRIDE_CONTROL
695 (sys.override_ctrl == OVERRIDE_PARKING_MOTION)) {
696 #else
698 #endif
699 // Block if safety door re-opened during prior restore actions.
701 // Regardless if the retract parking motion was a valid/safe motion or not, the
702 // restore parking motion should logically be valid, either by returning to the
703 // original position through valid machine space or by not moving at all.
705 pl_data->condition |= (restore_condition & PL_COND_ACCESSORY_MASK); // Restore accessory state
706 pl_data->spindle_speed = restore_spindle_speed;
707 mc_parking_motion(restore_target, pl_data);
708 }
709 }
710 #endif
711
714 system_set_exec_state_flag(EXEC_CYCLE_START); // Set to resume program.
715 }
716 }
717
718 }
719
720
721 } else {
722
723 // Feed hold manager. Controls spindle stop override states.
724 // NOTE: Hold ensured as completed by condition check at the beginning of suspend routine.
725 if (sys.spindle_stop_ovr) {
726 // Handles beginning of spindle stop
729 spindle_set_state(SPINDLE_DISABLE,0.0); // De-energize
730 sys.spindle_stop_ovr = SPINDLE_STOP_OVR_ENABLED; // Set stop override state to enabled, if de-energized.
731 } else {
732 sys.spindle_stop_ovr = SPINDLE_STOP_OVR_DISABLED; // Clear stop override state
733 }
734 // Handles restoring of spindle state
739 // When in laser mode, ignore spindle spin-up delay. Set to turn on laser when cycle starts.
741 } else {
742 spindle_set_state((restore_condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)), restore_spindle_speed);
743 }
744 }
746 system_set_exec_state_flag(EXEC_CYCLE_START); // Set to resume program.
747 }
748 sys.spindle_stop_ovr = SPINDLE_STOP_OVR_DISABLED; // Clear stop override state
749 }
750 } else {
751 // Handles spindle state during hold. NOTE: Spindle speed overrides may be altered during hold state.
752 // NOTE: STEP_CONTROL_UPDATE_SPINDLE_PWM is automatically reset upon resume in step generator.
754 spindle_set_state((restore_condition & (PL_COND_FLAG_SPINDLE_CW | PL_COND_FLAG_SPINDLE_CCW)), restore_spindle_speed);
756 }
757 }
758
759 }
760 }
761
763
764 }
765}
#define PARKING_TARGET
Definition: config.h:568
#define SPINDLE_OVERRIDE_COARSE_INCREMENT
Definition: config.h:255
#define DEFAULT_RAPID_OVERRIDE
Definition: config.h:247
#define SAFETY_DOOR_COOLANT_DELAY
Definition: config.h:180
#define PARKING_PULLOUT_INCREMENT
Definition: config.h:571
#define PARKING_AXIS
Definition: config.h:567
#define MAX_SPINDLE_SPEED_OVERRIDE
Definition: config.h:253
#define FEED_OVERRIDE_FINE_INCREMENT
Definition: config.h:245
#define RAPID_OVERRIDE_LOW
Definition: config.h:249
#define PARKING_RATE
Definition: config.h:569
#define PARKING_PULLOUT_RATE
Definition: config.h:570
#define MIN_FEED_RATE_OVERRIDE
Definition: config.h:243
#define MIN_SPINDLE_SPEED_OVERRIDE
Definition: config.h:254
#define RAPID_OVERRIDE_MEDIUM
Definition: config.h:248
#define FEED_OVERRIDE_COARSE_INCREMENT
Definition: config.h:244
#define MAX_FEED_RATE_OVERRIDE
Definition: config.h:242
#define DEFAULT_FEED_OVERRIDE
Definition: config.h:241
#define DEFAULT_SPINDLE_SPEED_OVERRIDE
Definition: config.h:252
#define SPINDLE_OVERRIDE_FINE_INCREMENT
Definition: config.h:256
#define SAFETY_DOOR_SPINDLE_DELAY
Definition: config.h:179
uint8_t coolant_get_state()
void coolant_set_state(uint8_t mode)
parser_state_t gc_state
Definition: gcode.c:36
void gc_sync_position()
Definition: gcode.c:55
uint8_t gc_execute_line(char *line)
Definition: gcode.c:66
#define COOLANT_DISABLE
Definition: gcode.h:118
#define COOLANT_FLOOD_ENABLE
Definition: gcode.h:119
#define SPINDLE_DISABLE
Definition: gcode.h:113
#define OVERRIDE_PARKING_MOTION
Definition: gcode.h:131
#define COOLANT_MIST_ENABLE
Definition: gcode.h:120
uint8_t limits_get_state()
Definition: limits.c:77
int32_t sys_position[N_AXIS]
Definition: main.c:27
volatile uint8_t sys_rt_exec_alarm
Definition: main.c:31
system_t sys
Definition: main.c:26
volatile uint8_t sys_rt_exec_accessory_override
Definition: main.c:33
volatile uint8_t sys_rt_exec_motion_override
Definition: main.c:32
volatile uint8_t sys_rt_exec_state
Definition: main.c:30
void mc_parking_motion(float *parking_target, plan_line_data_t *pl_data)
#define PARKING_MOTION_LINE_NUMBER
void delay_sec(float seconds, uint8_t mode)
Definition: nuts_bolts.c:112
#define DELAY_MODE_SYS_SUSPEND
Definition: nuts_bolts.h:50
#define bit_isfalse(x, mask)
Definition: nuts_bolts.h:65
#define bit_istrue(x, mask)
Definition: nuts_bolts.h:64
#define bit_false(x, mask)
Definition: nuts_bolts.h:63
#define min(a, b)
Definition: nuts_bolts.h:57
#define N_AXIS
Definition: nuts_bolts.h:31
#define bit_true(x, mask)
Definition: nuts_bolts.h:62
#define max(a, b)
Definition: nuts_bolts.h:56
plan_block_t * plan_get_current_block()
Definition: planner.c:234
void plan_sync_position()
Definition: planner.c:476
void plan_cycle_reinitialize()
Definition: planner.c:516
void plan_update_velocity_profile_parameters()
Definition: planner.c:284
void plan_reset()
Definition: planner.c:199
#define PL_COND_FLAG_COOLANT_FLOOD
Definition: planner.h:46
#define PL_COND_SPINDLE_MASK
Definition: planner.h:49
#define PL_COND_FLAG_SPINDLE_CCW
Definition: planner.h:45
#define PL_COND_ACCESSORY_MASK
Definition: planner.h:50
#define PL_COND_FLAG_SYSTEM_MOTION
Definition: planner.h:41
#define PL_COND_FLAG_COOLANT_MIST
Definition: planner.h:47
#define PL_COND_FLAG_NO_FEED_OVERRIDE
Definition: planner.h:42
#define PL_COND_FLAG_SPINDLE_CW
Definition: planner.h:44
void protocol_exec_rt_system()
Definition: protocol.c:215
void protocol_auto_cycle_start()
Definition: protocol.c:186
void protocol_main_loop()
Definition: protocol.c:38
#define LINE_FLAG_COMMENT_SEMICOLON
Definition: protocol.c:27
void protocol_execute_realtime()
Definition: protocol.c:205
void protocol_buffer_synchronize()
Definition: protocol.c:169
#define LINE_FLAG_OVERFLOW
Definition: protocol.c:25
#define LINE_FLAG_COMMENT_PARENTHESES
Definition: protocol.c:26
static char line[LINE_BUFFER_SIZE]
Definition: protocol.c:30
static void protocol_exec_rt_suspend()
Definition: protocol.c:509
#define LINE_BUFFER_SIZE
Definition: protocol.h:32
void report_alarm_message(uint8_t alarm_code)
Definition: report.c:125
void report_echo_line_received(char *line)
Definition: report.c:454
void report_realtime_status()
Definition: report.c:466
void report_feedback_message(uint8_t message_code)
Definition: report.c:138
void report_status_message(uint8_t status_code)
Definition: report.c:112
#define MESSAGE_SAFETY_DOOR_AJAR
Definition: report.h:80
#define MESSAGE_CRITICAL_EVENT
Definition: report.h:75
#define STATUS_OK
Definition: report.h:24
#define MESSAGE_SPINDLE_RESTORE
Definition: report.h:84
#define MESSAGE_SLEEP_MODE
Definition: report.h:85
#define MESSAGE_ALARM_LOCK
Definition: report.h:76
#define STATUS_OVERFLOW
Definition: report.h:35
#define STATUS_SYSTEM_GC_LOCK
Definition: report.h:33
#define MESSAGE_CHECK_LIMITS
Definition: report.h:81
uint8_t serial_read()
Definition: serial.c:126
#define SERIAL_NO_DATA
Definition: serial.h:37
settings_t settings
Definition: settings.c:24
#define BITFLAG_HARD_LIMIT_ENABLE
Definition: settings.h:45
#define BITFLAG_HOMING_ENABLE
Definition: settings.h:46
#define BITFLAG_LASER_MODE
Definition: settings.h:43
#define spindle_set_state(state, rpm)
void st_go_idle()
Definition: stepper.c:250
void st_reset()
Definition: stepper.c:535
void st_update_plan_block_parameters()
Definition: stepper.c:598
void st_prep_buffer()
Definition: stepper.c:668
void st_wake_up()
Definition: stepper.c:224
uint8_t coolant
Definition: gcode.h:194
uint8_t spindle
Definition: gcode.h:195
gc_modal_t modal
Definition: gcode.h:214
float spindle_speed
Definition: gcode.h:216
uint8_t condition
Definition: planner.h:63
float spindle_speed
Definition: planner.h:92
uint8_t condition
Definition: planner.h:93
float feed_rate
Definition: planner.h:91
uint8_t flags
Definition: settings.h:106
uint8_t step_control
Definition: system.h:132
uint8_t suspend
Definition: system.h:130
uint8_t report_ovr_counter
Definition: system.h:142
uint8_t r_override
Definition: system.h:139
uint8_t soft_limit
Definition: system.h:131
uint8_t abort
Definition: system.h:129
uint8_t spindle_speed_ovr
Definition: system.h:140
uint8_t f_override
Definition: system.h:138
uint8_t spindle_stop_ovr
Definition: system.h:141
uint8_t state
Definition: system.h:128
void system_clear_exec_accessory_overrides()
Definition: system.c:405
void system_clear_exec_alarm()
Definition: system.c:377
void system_set_exec_state_flag(uint8_t mask)
Definition: system.c:356
void system_clear_exec_state_flag(uint8_t mask)
Definition: system.c:363
void system_set_exec_accessory_override_flag(uint8_t mask)
Definition: system.c:391
uint8_t system_check_safety_door_ajar()
Definition: system.c:87
void system_execute_startup(char *line)
Definition: system.c:98
uint8_t system_execute_line(char *line)
Definition: system.c:123
void system_convert_array_steps_to_mpos(float *position, int32_t *steps)
Definition: system.c:310
void system_clear_exec_motion_overrides()
Definition: system.c:398
#define STATE_ALARM
Definition: system.h:77
#define EXEC_FEED_OVR_RESET
Definition: system.h:54
#define STEP_CONTROL_EXECUTE_HOLD
Definition: system.h:100
#define SPINDLE_STOP_OVR_RESTORE
Definition: system.h:122
#define EXEC_FEED_OVR_COARSE_MINUS
Definition: system.h:56
#define SUSPEND_HOLD_COMPLETE
Definition: system.h:88
#define EXEC_SPINDLE_OVR_FINE_MINUS
Definition: system.h:68
#define EXEC_SPINDLE_OVR_COARSE_MINUS
Definition: system.h:66
#define SUSPEND_MOTION_CANCEL
Definition: system.h:94
#define EXEC_FEED_OVR_FINE_PLUS
Definition: system.h:57
#define SUSPEND_RETRACT_COMPLETE
Definition: system.h:90
#define STATE_CHECK_MODE
Definition: system.h:78
#define EXEC_RAPID_OVR_LOW
Definition: system.h:61
#define EXEC_FEED_OVR_COARSE_PLUS
Definition: system.h:55
#define SPINDLE_STOP_OVR_RESTORE_CYCLE
Definition: system.h:123
#define SUSPEND_RESTORE_COMPLETE
Definition: system.h:92
#define EXEC_SPINDLE_OVR_COARSE_PLUS
Definition: system.h:65
#define EXEC_STATUS_REPORT
Definition: system.h:31
#define EXEC_COOLANT_FLOOD_OVR_TOGGLE
Definition: system.h:70
#define SPINDLE_STOP_OVR_DISABLED
Definition: system.h:119
#define EXEC_ALARM_HARD_LIMIT
Definition: system.h:41
#define EXEC_SPINDLE_OVR_STOP
Definition: system.h:69
#define STATE_JOG
Definition: system.h:82
#define STEP_CONTROL_EXECUTE_SYS_MOTION
Definition: system.h:101
#define EXEC_ALARM_SOFT_LIMIT
Definition: system.h:42
#define STATE_CYCLE
Definition: system.h:80
#define EXEC_RESET
Definition: system.h:35
#define EXEC_RAPID_OVR_MEDIUM
Definition: system.h:60
#define SUSPEND_JOG_CANCEL
Definition: system.h:95
#define SPINDLE_STOP_OVR_ENABLED
Definition: system.h:120
#define STATE_HOMING
Definition: system.h:79
#define STEP_CONTROL_UPDATE_SPINDLE_PWM
Definition: system.h:102
#define EXEC_FEED_HOLD
Definition: system.h:34
#define STATE_SAFETY_DOOR
Definition: system.h:83
#define STATE_IDLE
Definition: system.h:76
#define EXEC_MOTION_CANCEL
Definition: system.h:37
#define EXEC_COOLANT_MIST_OVR_TOGGLE
Definition: system.h:71
#define SUSPEND_DISABLE
Definition: system.h:87
#define SUSPEND_INITIATE_RESTORE
Definition: system.h:91
#define EXEC_SLEEP
Definition: system.h:38
#define SPINDLE_STOP_OVR_INITIATE
Definition: system.h:121
#define EXEC_SPINDLE_OVR_FINE_PLUS
Definition: system.h:67
#define EXEC_SAFETY_DOOR
Definition: system.h:36
#define EXEC_SPINDLE_OVR_RESET
Definition: system.h:64
#define STATE_HOLD
Definition: system.h:81
#define SUSPEND_SAFETY_DOOR_AJAR
Definition: system.h:93
#define STATE_SLEEP
Definition: system.h:84
#define STEP_CONTROL_NORMAL_OP
Definition: system.h:98
#define SUSPEND_RESTART_RETRACT
Definition: system.h:89
#define EXEC_RAPID_OVR_RESET
Definition: system.h:59
#define EXEC_CYCLE_START
Definition: system.h:32
#define EXEC_CYCLE_STOP
Definition: system.h:33
#define EXEC_FEED_OVR_FINE_MINUS
Definition: system.h:58