1
0
mirror of https://github.com/bdring/Grbl_Esp32.git synced 2025-08-18 04:11:53 +02:00

Most #defines are gone (#595)

* Many more #defines bite the dust

* Fixed botch in rt accessory logic

* Update Probe.cpp

* Update System.cpp

* Typo
This commit is contained in:
Mitch Bradley
2020-10-07 18:43:31 -10:00
committed by GitHub
parent 8c10709f21
commit 994de40724
23 changed files with 592 additions and 717 deletions

View File

@@ -247,23 +247,17 @@ void atari_next_pen() {
void user_defined_macro(uint8_t index) {
char gcode_line[20];
switch (index) {
#ifdef MACRO_BUTTON_0_PIN
case CONTROL_PIN_INDEX_MACRO_0:
case 0:
grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Pen switch");
WebUI::inputBuffer.push("$H\r");
break;
#endif
#ifdef MACRO_BUTTON_1_PIN
case CONTROL_PIN_INDEX_MACRO_1:
case 1:
grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Color switch");
atari_next_pen();
sprintf(gcode_line, "G90G0X%3.2f\r", ATARI_PAPER_WIDTH); // alway return to right side to reduce home travel stalls
WebUI::inputBuffer.push(gcode_line);
break;
#endif
#ifdef MACRO_BUTTON_2_PIN
case CONTROL_PIN_INDEX_MACRO_2:
// feed out some paper and reset the Y 0
case 2:
grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Paper switch");
WebUI::inputBuffer.push("G0Y-25\r");
WebUI::inputBuffer.push("G4P0.1\r"); // sync...forces wait for planner to clear
@@ -271,9 +265,7 @@ void user_defined_macro(uint8_t index) {
gc_sync_position();
plan_sync_position();
break;
#endif
default:
grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Unknown Switch %d", index);
break;
}
}

View File

@@ -223,25 +223,15 @@ float abs_angle(float ang) {
// Polar coaster has macro buttons, this handles those button pushes.
void user_defined_macro(uint8_t index) {
switch (index) {
#ifdef MACRO_BUTTON_0_PIN
case CONTROL_PIN_INDEX_MACRO_0:
case 0:
WebUI::inputBuffer.push("$H\r"); // home machine
break;
#endif
#ifdef MACRO_BUTTON_1_PIN
case CONTROL_PIN_INDEX_MACRO_1:
case 1:
WebUI::inputBuffer.push("[ESP220]/1.nc\r"); // run SD card file 1.nc
break;
#endif
#ifdef MACRO_BUTTON_2_PIN
case CONTROL_PIN_INDEX_MACRO_2:
case 2:
WebUI::inputBuffer.push("[ESP220]/2.nc\r"); // run SD card file 2.nc
break;
#endif
#ifdef MACRO_BUTTON_3_PIN
case CONTROL_PIN_INDEX_MACRO_3:
break;
#endif
default:
break;
}

View File

@@ -167,40 +167,37 @@ const int DEFAULT_RADIO_MODE = ESP_RADIO_OFF;
// GCode programs, maybe selected for interface programs.
// NOTE: If changed, manually update help message in report.c.
const uint8_t CMD_RESET = 0x18; // ctrl-x.
const uint8_t CMD_STATUS_REPORT = '?';
const uint8_t CMD_CYCLE_START = '~';
const uint8_t CMD_FEED_HOLD = '!';
// NOTE: All override realtime commands must be in the extended ASCII character set, starting
// at character value 128 (0x80) and up to 255 (0xFF). If the normal set of realtime commands,
// such as status reports, feed hold, reset, and cycle start, are moved to the extended set
// space, serial.c's RX ISR will need to be modified to accommodate the change.
// const uint8_t CMD_RESET = 0x80;
// const uint8_t CMD_STATUS_REPORT = 0x81;
// const uint8_t CMD_CYCLE_START = 0x82;
// const uint8_t CMD_FEED_HOLD = 0x83;
const uint8_t CMD_SAFETY_DOOR = 0x84;
const uint8_t CMD_JOG_CANCEL = 0x85;
const uint8_t CMD_DEBUG_REPORT = 0x86; // Only when DEBUG enabled, sends debug report in '{}' braces.
const uint8_t CMD_FEED_OVR_RESET = 0x90; // Restores feed override value to 100%.
const uint8_t CMD_FEED_OVR_COARSE_PLUS = 0x91;
const uint8_t CMD_FEED_OVR_COARSE_MINUS = 0x92;
const uint8_t CMD_FEED_OVR_FINE_PLUS = 0x93;
const uint8_t CMD_FEED_OVR_FINE_MINUS = 0x94;
const uint8_t CMD_RAPID_OVR_RESET = 0x95; // Restores rapid override value to 100%.
const uint8_t CMD_RAPID_OVR_MEDIUM = 0x96;
const uint8_t CMD_RAPID_OVR_LOW = 0x97;
// const uint8_t CMD_RAPID_OVR_EXTRA_LOW = 0x98; // *NOT SUPPORTED*
const uint8_t CMD_SPINDLE_OVR_RESET = 0x99; // Restores spindle override value to 100%.
const uint8_t CMD_SPINDLE_OVR_COARSE_PLUS = 0x9A; // 154
const uint8_t CMD_SPINDLE_OVR_COARSE_MINUS = 0x9B;
const uint8_t CMD_SPINDLE_OVR_FINE_PLUS = 0x9C;
const uint8_t CMD_SPINDLE_OVR_FINE_MINUS = 0x9D;
const uint8_t CMD_SPINDLE_OVR_STOP = 0x9E;
const uint8_t CMD_COOLANT_FLOOD_OVR_TOGGLE = 0xA0;
const uint8_t CMD_COOLANT_MIST_OVR_TOGGLE = 0xA1;
enum class Cmd : uint8_t {
Reset = 0x18, // Ctrl-X
StatusReport = '?',
CycleStart = '~',
FeedHold = '!',
SafetyDoor = 0x84,
JogCancel = 0x85,
DebugReport = 0x86, // Only when DEBUG enabled, sends debug report in '{}' braces.
FeedOvrReset = 0x90, // Restores feed override value to 100%.
FeedOvrCoarsePlus = 0x91,
FeedOvrCoarseMinus = 0x92,
FeedOvrFinePlus = 0x93,
FeedOvrFineMinus = 0x94,
RapidOvrReset = 0x95, // Restores rapid override value to 100%.
RapidOvrMedium = 0x96,
RapidOvrLow = 0x97,
RapidOvrExtraLow = 0x98, // *NOT SUPPORTED*
SpindleOvrReset = 0x99, // Restores spindle override value to 100%.
SpindleOvrCoarsePlus = 0x9A, // 154
SpindleOvrCoarseMinus = 0x9B,
SpindleOvrFinePlus = 0x9C,
SpindleOvrFineMinus = 0x9D,
SpindleOvrStop = 0x9E,
CoolantFloodOvrToggle = 0xA0,
CoolantMistOvrToggle = 0xA1,
};
// If homing is enabled, homing init lock sets Grbl into an alarm state upon power up. This forces
// the user to perform the homing cycle (or override the locks) before doing anything else. This is
@@ -309,22 +306,27 @@ const double SAFETY_DOOR_COOLANT_DELAY = 1.0; // Float (seconds)
// Configure rapid, feed, and spindle override settings. These values define the max and min
// allowable override values and the coarse and fine increments per command received. Please
// note the allowable values in the descriptions following each define.
const int DEFAULT_FEED_OVERRIDE = 100; // 100%. Don't change this value.
const int MAX_FEED_RATE_OVERRIDE = 200; // Percent of programmed feed rate (100-255). Usually 120% or 200%
const int MIN_FEED_RATE_OVERRIDE = 10; // Percent of programmed feed rate (1-100). Usually 50% or 1%
const int FEED_OVERRIDE_COARSE_INCREMENT = 10; // (1-99). Usually 10%.
const int FEED_OVERRIDE_FINE_INCREMENT = 1; // (1-99). Usually 1%.
namespace FeedOverride {
const int Default = 100; // 100%. Don't change this value.
const int Max = 200; // Percent of programmed feed rate (100-255). Usually 120% or 200%
const int Min = 10; // Percent of programmed feed rate (1-100). Usually 50% or 1%
const int CoarseIncrement = 10; // (1-99). Usually 10%.
const int FineIncrement = 1; // (1-99). Usually 1%.
};
namespace RapidOverride {
const int Default = 100; // 100%. Don't change this value.
const int Medium = 50; // Percent of rapid (1-99). Usually 50%.
const int Low = 25; // Percent of rapid (1-99). Usually 25%.
const int ExtraLow = 5; // Percent of rapid (1-99). Usually 5%. Not Supported
};
const int DEFAULT_RAPID_OVERRIDE = 100; // 100%. Don't change this value.
const int RAPID_OVERRIDE_MEDIUM = 50; // Percent of rapid (1-99). Usually 50%.
const int RAPID_OVERRIDE_LOW = 25; // Percent of rapid (1-99). Usually 25%.
// const int RAPID_OVERRIDE_EXTRA_LOW = 5; // *NOT SUPPORTED* Percent of rapid (1-99). Usually 5%.
const int DEFAULT_SPINDLE_SPEED_OVERRIDE = 100; // 100%. Don't change this value.
const int MAX_SPINDLE_SPEED_OVERRIDE = 200; // Percent of programmed spindle speed (100-255). Usually 200%.
const int MIN_SPINDLE_SPEED_OVERRIDE = 10; // Percent of programmed spindle speed (1-100). Usually 10%.
const int SPINDLE_OVERRIDE_COARSE_INCREMENT = 10; // (1-99). Usually 10%.
const int SPINDLE_OVERRIDE_FINE_INCREMENT = 1; // (1-99). Usually 1%.
namespace SpindleSpeedOverride {
const int Default = 100; // 100%. Don't change this value.
const int Max = 200; // Percent of programmed spindle speed (100-255). Usually 200%.
const int Min = 10; // Percent of programmed spindle speed (1-100). Usually 10%.
const int CoarseIncrement = 10; // (1-99). Usually 10%.
const int FineIncrement = 1; // (1-99). Usually 1%.
}
// When a M2 or M30 program end command is executed, most GCode states are restored to their defaults.
// This compile-time option includes the restoring of the feed, rapid, and spindle speed override values

View File

@@ -1565,7 +1565,7 @@ Error gc_execute_line(char* line, uint8_t client) {
case ProgramFlow::Paused:
protocol_buffer_synchronize(); // Sync and finish all remaining buffered motions before moving on.
if (sys.state != State::CheckMode) {
system_set_exec_state_flag(EXEC_FEED_HOLD); // Use feed hold for program pause.
sys_rt_exec_state.bit.feedHold = true; // Use feed hold for program pause.
protocol_execute_realtime(); // Execute suspend.
}
break;
@@ -1594,9 +1594,9 @@ Error gc_execute_line(char* line, uint8_t client) {
#endif
// gc_state.modal.override = OVERRIDE_DISABLE; // Not supported.
#ifdef RESTORE_OVERRIDES_AFTER_PROGRAM_END
sys.f_override = DEFAULT_FEED_OVERRIDE;
sys.r_override = DEFAULT_RAPID_OVERRIDE;
sys.spindle_speed_ovr = DEFAULT_SPINDLE_SPEED_OVERRIDE;
sys.f_override = FeedOverride::Default;
sys.r_override = RapidOverride::Default;
sys.spindle_speed_ovr = SpindleSpeedOverride::Default;
#endif
// Execute coordinate change and spindle/coolant stop.
if (sys.state != State::CheckMode) {

View File

@@ -163,15 +163,6 @@ struct CoolantState {
// Modal Group M8: Coolant control
// Modal Group M9: Override control
enum class Override : uint8_t {
#ifdef DEACTIVATE_PARKING_UPON_INIT
Disabled = 0, // (Default: Must be zero)
ParkingMotion = 1, // M56
#else
ParkingMotion = 0, // M56 (Default: Must be zero)
Disabled = 1, // Parking disabled.
#endif
};
// Modal Group M10: User I/O control
enum class IoControl : uint8_t {

View File

@@ -80,16 +80,20 @@ static void reset_variables() {
State prior_state = sys.state;
memset(&sys, 0, sizeof(system_t)); // Clear system struct variable.
sys.state = prior_state;
sys.f_override = DEFAULT_FEED_OVERRIDE; // Set to 100%
sys.r_override = DEFAULT_RAPID_OVERRIDE; // Set to 100%
sys.spindle_speed_ovr = DEFAULT_SPINDLE_SPEED_OVERRIDE; // Set to 100%
sys.f_override = FeedOverride::Default; // Set to 100%
sys.r_override = RapidOverride::Default; // Set to 100%
sys.spindle_speed_ovr = SpindleSpeedOverride::Default; // Set to 100%
memset(sys_probe_position, 0, sizeof(sys_probe_position)); // Clear probe position.
sys_probe_state = 0;
sys_rt_exec_state = 0;
sys_probe_state = Probe::Off;
sys_rt_exec_state.value = 0;
sys_rt_exec_accessory_override.value = 0;
sys_rt_exec_alarm = ExecAlarm::None;
cycle_stop = false;
sys_rt_exec_motion_override = 0;
sys_rt_exec_accessory_override = 0;
system_clear_exec_alarm();
sys_rt_f_override = FeedOverride::Default;
sys_rt_r_override = RapidOverride::Default;
sys_rt_s_override = SpindleSpeedOverride::Default;
// Reset Grbl primary systems.
serial_reset_read_buffer(CLIENT_ALL); // Clear serial read buffer
gc_init(); // Set g-code parser to default state

View File

@@ -44,6 +44,7 @@ const char* const GRBL_VERSION_BUILD = "20201004";
#include "Eeprom.h"
#include "WebUI/Authentication.h"
#include "WebUI/Commands.h"
#include "Probe.h"
#include "System.h"
#include "GCode.h"
@@ -51,7 +52,6 @@ const char* const GRBL_VERSION_BUILD = "20201004";
#include "CoolantControl.h"
#include "Limits.h"
#include "MotionControl.h"
#include "Probe.h"
#include "Protocol.h"
#include "Report.h"
#include "Serial.h"

View File

@@ -56,11 +56,11 @@ void IRAM_ATTR isr_limit_switches() {
// Check limit pin state.
if (limits_get_state()) {
mc_reset(); // Initiate system kill.
system_set_exec_alarm(ExecAlarm::HardLimit); // Indicate hard limit critical event
sys_rt_exec_alarm = ExecAlarm::HardLimit; // Indicate hard limit critical event
}
# else
mc_reset(); // Initiate system kill.
system_set_exec_alarm(ExecAlarm::HardLimit); // Indicate hard limit critical event
sys_rt_exec_alarm = ExecAlarm::HardLimit; // Indicate hard limit critical event
# endif
#endif
}
@@ -127,7 +127,8 @@ void limits_go_home(uint8_t cycle_mask) {
// Set search mode with approach at seek rate to quickly engage the specified cycle_mask limit switches.
bool approach = true;
float homing_rate = homing_seek_rate->get();
uint8_t limit_state, axislock, n_active_axis;
uint8_t n_active_axis;
AxisMask limit_state, axislock;
do {
system_convert_array_steps_to_mpos(target, sys_position);
// Initialize and declare variables needed for homing routine.
@@ -176,7 +177,8 @@ void limits_go_home(uint8_t cycle_mask) {
// Perform homing cycle. Planner buffer should be empty, as required to initiate the homing cycle.
pl_data->feed_rate = homing_rate; // Set current homing rate.
plan_buffer_line(target, pl_data); // Bypass mc_line(). Directly plan homing motion.
sys.step_control = STEP_CONTROL_EXECUTE_SYS_MOTION; // Set to execute homing motion and clear existing flags.
sys.step_control = {};
sys.step_control.executeSysMotion = true; // Set to execute homing motion and clear existing flags.
st_prep_buffer(); // Prep and fill segment buffer from newly planned block.
st_wake_up(); // Initiate motion
do {
@@ -202,23 +204,24 @@ void limits_go_home(uint8_t cycle_mask) {
}
st_prep_buffer(); // Check and prep segment buffer. NOTE: Should take no longer than 200us.
// Exit routines: No time to run protocol_execute_realtime() in this loop.
if ((sys_rt_exec_state & (EXEC_SAFETY_DOOR | EXEC_RESET)) || cycle_stop) {
uint8_t rt_exec = sys_rt_exec_state;
if (sys_rt_exec_state.bit.safetyDoor || sys_rt_exec_state.bit.reset || cycle_stop) {
ExecState rt_exec_state;
rt_exec_state.value = sys_rt_exec_state.value;
// Homing failure condition: Reset issued during cycle.
if (rt_exec & EXEC_RESET) {
system_set_exec_alarm(ExecAlarm::HomingFailReset);
if (rt_exec_state.bit.reset) {
sys_rt_exec_alarm = ExecAlarm::HomingFailReset;
}
// Homing failure condition: Safety door was opened.
if (rt_exec & EXEC_SAFETY_DOOR) {
system_set_exec_alarm(ExecAlarm::HomingFailDoor);
if (rt_exec_state.bit.safetyDoor) {
sys_rt_exec_alarm = ExecAlarm::HomingFailDoor;
}
// Homing failure condition: Limit switch still engaged after pull-off motion
if (!approach && (limits_get_state() & cycle_mask)) {
system_set_exec_alarm(ExecAlarm::HomingFailPulloff);
sys_rt_exec_alarm = ExecAlarm::HomingFailPulloff;
}
// Homing failure condition: Limit switch not found during approach.
if (approach && cycle_stop) {
system_set_exec_alarm(ExecAlarm::HomingFailApproach);
sys_rt_exec_alarm = ExecAlarm::HomingFailApproach;
}
if (sys_rt_exec_alarm != ExecAlarm::None) {
@@ -303,7 +306,7 @@ void limits_go_home(uint8_t cycle_mask) {
#endif
}
}
sys.step_control = STEP_CONTROL_NORMAL_OP; // Return step control to normal operation.
sys.step_control = {}; // Return step control to normal operation.
motors_set_homing_mode(cycle_mask, false); // tell motors homing is done
}
@@ -371,8 +374,8 @@ void limits_disable() {
// Returns limit state as a bit-wise uint8 variable. Each bit indicates an axis limit, where
// triggered is 1 and not triggered is 0. Invert mask is applied. Axes are defined by their
// number in bit position, i.e. Z_AXIS is bit(2), and Y_AXIS is bit(1).
uint8_t limits_get_state() {
uint8_t pinMask = 0;
AxisMask limits_get_state() {
AxisMask pinMask = 0;
auto n_axis = number_axis->get();
for (int axis = 0; axis < n_axis; axis++) {
for (int gang_index = 0; gang_index < 2; gang_index++) {
@@ -402,7 +405,7 @@ void limits_soft_check(float* target) {
// workspace volume so just come to a controlled stop so position is not lost. When complete
// enter alarm mode.
if (sys.state == State::Cycle) {
system_set_exec_state_flag(EXEC_FEED_HOLD);
sys_rt_exec_state.bit.feedHold = true;
do {
protocol_execute_realtime();
if (sys.abort) {
@@ -411,7 +414,7 @@ void limits_soft_check(float* target) {
} while (sys.state != State::Idle);
}
mc_reset(); // Issue system reset and ensure spindle and coolant are shutdown.
system_set_exec_alarm(ExecAlarm::SoftLimit); // Indicate soft limit critical event
sys_rt_exec_alarm = ExecAlarm::SoftLimit; // Indicate soft limit critical event
protocol_execute_realtime(); // Execute to enter critical event loop and system abort
return;
}
@@ -423,12 +426,12 @@ void limitCheckTask(void* pvParameters) {
int evt;
xQueueReceive(limit_sw_queue, &evt, portMAX_DELAY); // block until receive queue
vTaskDelay(DEBOUNCE_PERIOD / portTICK_PERIOD_MS); // delay a while
uint8_t switch_state;
AxisMask switch_state;
switch_state = limits_get_state();
if (switch_state) {
//grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Limit Switch State %08d", switch_state);
mc_reset(); // Initiate system kill.
system_set_exec_alarm(ExecAlarm::HardLimit); // Indicate hard limit critical event
sys_rt_exec_alarm = ExecAlarm::HardLimit; // Indicate hard limit critical event
}
}
}

View File

@@ -36,7 +36,7 @@ void limits_init();
void limits_disable();
// Returns limit state as a bit-wise uint8 variable.
uint8_t limits_get_state();
AxisMask limits_get_state();
// Perform one portion of the homing cycle based on the input settings.
void limits_go_home(uint8_t cycle_mask);

View File

@@ -283,7 +283,7 @@ void mc_homing_cycle(uint8_t cycle_mask) {
#ifdef LIMITS_TWO_SWITCHES_ON_AXES
if (limits_get_state()) {
mc_reset(); // Issue system reset and ensure spindle and coolant are shutdown.
system_set_exec_alarm(ExecAlarm::HardLimit);
sys_rt_exec_alarm = ExecAlarm::HardLimit;
return;
}
#endif
@@ -379,16 +379,16 @@ GCUpdatePos mc_probe_cycle(float* target, plan_line_data_t* pl_data, uint8_t par
// After syncing, check if probe is already triggered. If so, halt and issue alarm.
// NOTE: This probe initialization error applies to all probing cycles.
if (probe_get_state() ^ is_probe_away) { // Check probe pin state.
system_set_exec_alarm(ExecAlarm::ProbeFailInitial);
sys_rt_exec_alarm = ExecAlarm::ProbeFailInitial;
protocol_execute_realtime();
return GCUpdatePos::None; // Nothing else to do but bail.
}
// Setup and queue probing motion. Auto cycle-start should not start the cycle.
mc_line(target, pl_data);
// Activate the probing state monitor in the stepper module.
sys_probe_state = PROBE_ACTIVE;
sys_probe_state = Probe::Active;
// Perform probing cycle. Wait here until probe is triggered or motion completes.
system_set_exec_state_flag(EXEC_CYCLE_START);
sys_rt_exec_state.bit.cycleStart = true;
do {
protocol_execute_realtime();
if (sys.abort) {
@@ -397,16 +397,16 @@ GCUpdatePos mc_probe_cycle(float* target, plan_line_data_t* pl_data, uint8_t par
} while (sys.state != State::Idle);
// Probing cycle complete!
// Set state variables and error out, if the probe failed and cycle with error is enabled.
if (sys_probe_state == PROBE_ACTIVE) {
if (sys_probe_state == Probe::Active) {
if (is_no_error) {
memcpy(sys_probe_position, sys_position, sizeof(sys_position));
} else {
system_set_exec_alarm(ExecAlarm::ProbeFailContact);
sys_rt_exec_alarm = ExecAlarm::ProbeFailContact;
}
} else {
sys.probe_succeeded = true; // Indicate to system the probing cycle completed successfully.
}
sys_probe_state = PROBE_OFF; // Ensure probe state monitor is disabled.
sys_probe_state = Probe::Off; // Ensure probe state monitor is disabled.
protocol_execute_realtime(); // Check and execute run-time commands
// Reset the stepper and planner buffers to remove the remainder of the probe motion.
st_reset(); // Reset step segment buffer.
@@ -431,8 +431,8 @@ void mc_parking_motion(float* parking_target, plan_line_data_t* pl_data) {
}
uint8_t plan_status = plan_buffer_line(parking_target, pl_data);
if (plan_status) {
bit_true(sys.step_control, STEP_CONTROL_EXECUTE_SYS_MOTION);
bit_false(sys.step_control, STEP_CONTROL_END_MOTION); // Allow parking motion to execute, if feed hold is active.
sys.step_control.executeSysMotion = true;
sys.step_control.endMotion = false; // Allow parking motion to execute, if feed hold is active.
st_parking_setup_buffer(); // Setup step segment buffer for special parking motion case
st_prep_buffer();
st_wake_up();
@@ -441,10 +441,10 @@ void mc_parking_motion(float* parking_target, plan_line_data_t* pl_data) {
if (sys.abort) {
return;
}
} while (sys.step_control & STEP_CONTROL_EXECUTE_SYS_MOTION);
} while (sys.step_control.executeSysMotion);
st_parking_restore_buffer(); // Restore step segment buffer to normal run state.
} else {
bit_false(sys.step_control, STEP_CONTROL_EXECUTE_SYS_MOTION);
sys.step_control.executeSysMotion = false;
protocol_exec_rt_system();
}
}
@@ -467,8 +467,8 @@ void mc_override_ctrl_update(uint8_t override_state) {
// realtime abort command and hard limits. So, keep to a minimum.
void mc_reset() {
// Only this function can set the system reset. Helps prevent multiple kill calls.
if (bit_isfalse(sys_rt_exec_state, EXEC_RESET)) {
system_set_exec_state_flag(EXEC_RESET);
if (!sys_rt_exec_state.bit.reset) {
sys_rt_exec_state.bit.reset = true;
// Kill spindle and coolant.
spindle->stop();
coolant_stop();
@@ -489,13 +489,13 @@ void mc_reset() {
// the steppers enabled by avoiding the go_idle call altogether, unless the motion state is
// violated, by which, all bets are off.
if ((sys.state == State::Cycle || sys.state == State::Homing || sys.state == State::Jog) ||
(sys.step_control & (STEP_CONTROL_EXECUTE_HOLD | STEP_CONTROL_EXECUTE_SYS_MOTION))) {
(sys.step_control.executeHold || sys.step_control.executeSysMotion)) {
if (sys.state == State::Homing) {
if (sys_rt_exec_alarm == ExecAlarm::None) {
system_set_exec_alarm(ExecAlarm::HomingFailReset);
sys_rt_exec_alarm = ExecAlarm::HomingFailReset;
}
} else {
system_set_exec_alarm(ExecAlarm::AbortCycle);
sys_rt_exec_alarm = ExecAlarm::AbortCycle;
}
st_go_idle(); // Force kill steppers. Position has likely been lost.
}

View File

@@ -123,7 +123,7 @@ void delay_sec(float seconds, uint8_t mode) {
} else { // DELAY_MODE_SYS_SUSPEND
// Execute rt_system() only to avoid nesting suspend loops.
protocol_exec_rt_system();
if (sys.suspend & SUSPEND_RESTART_RETRACT) {
if (sys.suspend.bit.restartRetract) {
return; // Bail, if safety door reopens.
}
}

View File

@@ -58,8 +58,8 @@ bool probe_get_state() {
// NOTE: This function must be extremely efficient as to not bog down the stepper ISR.
void probe_state_monitor() {
if (probe_get_state() ^ is_probe_away) {
sys_probe_state = PROBE_OFF;
sys_probe_state = Probe::Off;
memcpy(sys_probe_position, sys_position, sizeof(sys_position));
bit_true(sys_rt_exec_state, EXEC_MOTION_CANCEL);
sys_rt_exec_state.bit.motionCancel = true;
}
}

View File

@@ -24,8 +24,10 @@
*/
// Values that define the probing state machine.
const int PROBE_OFF = 0; // Probing disabled or not in use. (Must be zero.)
const int PROBE_ACTIVE = 1; // Actively watching the input pin.
enum class Probe : uint8_t {
Off = 0, // Probing disabled or not in use. (Must be zero.)
Active = 1, // Actively watching the input pin.
};
// Probe pin initialization routine.
void probe_init();

View File

@@ -267,7 +267,7 @@ Error home_c(const char* value, WebUI::AuthenticationLevel auth_level, WebUI::ES
return home(bit(C_AXIS));
}
Error sleep_grbl(const char* value, WebUI::AuthenticationLevel auth_level, WebUI::ESPResponseStream* out) {
system_set_exec_state_flag(EXEC_SLEEP);
sys_rt_exec_state.bit.sleep = true;
return Error::Ok;
}
Error get_report_build_info(const char* value, WebUI::AuthenticationLevel auth_level, WebUI::ESPResponseStream* out) {

View File

@@ -94,7 +94,7 @@ Error execute_line(char* line, uint8_t client, WebUI::AuthenticationLevel auth_l
bool can_park() {
return
#ifdef ENABLE_PARKING_OVERRIDE_CONTROL
sys.override_ctrl == OVERRIDE_PARKING_MOTION &&
sys.override_ctrl == Override::ParkingMotion &&
#endif
homing_enable->get() && !laser_mode->get();
}
@@ -125,7 +125,7 @@ void protocol_main_loop() {
// Check if the safety door is open.
sys.state = State::Idle;
if (system_check_safety_door_ajar()) {
bit_true(sys_rt_exec_state, EXEC_SAFETY_DOOR);
sys_rt_exec_state.bit.safetyDoor = true;
protocol_execute_realtime(); // Enter safety door mode. Should return as IDLE state.
}
// All systems go!
@@ -223,7 +223,7 @@ void protocol_buffer_synchronize() {
// execute calls a buffer sync, or the planner buffer is full and ready to go.
void protocol_auto_cycle_start() {
if (plan_get_current_block() != NULL) { // Check if there are any blocks in the buffer.
system_set_exec_state_flag(EXEC_CYCLE_START); // If so, execute them!
sys_rt_exec_state.bit.cycleStart = true; // If so, execute them!
}
}
@@ -236,11 +236,11 @@ void protocol_auto_cycle_start() {
// handles them, removing the need to define more computationally-expensive volatile variables. This
// also provides a controlled way to execute certain tasks without having two or more instances of
// the same task, such as the planner recalculating the buffer upon a feedhold or overrides.
// NOTE: The sys_rt_exec_state variable flags are set by any process, step or serial interrupts, pinouts,
// NOTE: The sys_rt_exec_state.bit variable flags are set by any process, step or serial interrupts, pinouts,
// limit switches, or the main program.
void protocol_execute_realtime() {
protocol_exec_rt_system();
if (sys.suspend) {
if (sys.suspend.value) {
protocol_exec_rt_suspend();
}
}
@@ -259,145 +259,156 @@ void protocol_exec_rt_system() {
// Halt everything upon a critical event flag. Currently hard and soft limits flag this.
if ((alarm == ExecAlarm::HardLimit) || (alarm == ExecAlarm::SoftLimit)) {
report_feedback_message(Message::CriticalEvent);
system_clear_exec_state_flag(EXEC_RESET); // Disable any existing reset
sys_rt_exec_state.bit.reset = false; // Disable any existing reset
do {
// Block everything, except reset and status reports, until user issues reset or power
// cycles. Hard limits typically occur while unattended or not paying attention. Gives
// the user and a GUI time to do what is needed before resetting, like killing the
// incoming stream. The same could be said about soft limits. While the position is not
// lost, continued streaming could cause a serious crash if by chance it gets executed.
} while (bit_isfalse(sys_rt_exec_state, EXEC_RESET));
} while (!sys_rt_exec_state.bit.reset);
}
system_clear_exec_alarm(); // Clear alarm
sys_rt_exec_alarm = ExecAlarm::None;
}
uint8_t rt_exec = sys_rt_exec_state; // Copy volatile sys_rt_exec_state.
if (rt_exec || cycle_stop) {
ExecState rt_exec_state;
rt_exec_state.value = sys_rt_exec_state.value; // Copy volatile sys_rt_exec_state.
if (rt_exec_state.value != 0 || cycle_stop) { // Test if any bits are on
// Execute system abort.
if (rt_exec & EXEC_RESET) {
if (rt_exec_state.bit.reset) {
sys.abort = true; // Only place this is set true.
return; // Nothing else to do but exit.
}
// Execute and serial print status
if (rt_exec & EXEC_STATUS_REPORT) {
if (rt_exec_state.bit.statusReport) {
report_realtime_status(CLIENT_ALL);
system_clear_exec_state_flag(EXEC_STATUS_REPORT);
sys_rt_exec_state.bit.statusReport = false;
}
// NOTE: Once hold is initiated, the system immediately enters a suspend state to block all
// main program processes until either reset or resumed. This ensures a hold completes safely.
if (rt_exec & (EXEC_MOTION_CANCEL | EXEC_FEED_HOLD | EXEC_SAFETY_DOOR | EXEC_SLEEP)) {
if (rt_exec_state.bit.motionCancel || rt_exec_state.bit.feedHold || rt_exec_state.bit.safetyDoor || rt_exec_state.bit.sleep) {
// State check for allowable states for hold methods.
if (!(sys.state == State::Alarm || sys.state == State::CheckMode)) {
// If in CYCLE or JOG states, immediately initiate a motion HOLD.
if (sys.state == State::Cycle || sys.state == State::Jog) {
if (!(sys.suspend & (SUSPEND_MOTION_CANCEL | SUSPEND_JOG_CANCEL))) { // Block, if already holding.
if (!(sys.suspend.bit.motionCancel || sys.suspend.bit.jogCancel)) { // Block, if already holding.
st_update_plan_block_parameters(); // Notify stepper module to recompute for hold deceleration.
sys.step_control = STEP_CONTROL_EXECUTE_HOLD; // Initiate suspend state with active flag.
sys.step_control = {};
sys.step_control.executeHold = true; // Initiate suspend state with active flag.
if (sys.state == State::Jog) { // Jog cancelled upon any hold event, except for sleeping.
if (!(rt_exec & EXEC_SLEEP)) {
sys.suspend |= SUSPEND_JOG_CANCEL;
if (!rt_exec_state.bit.sleep) {
sys.suspend.bit.jogCancel = true;
}
}
}
}
// If IDLE, Grbl is not in motion. Simply indicate suspend state and hold is complete.
if (sys.state == State::Idle) {
sys.suspend = SUSPEND_HOLD_COMPLETE;
sys.suspend.value = 0;
sys.suspend.bit.holdComplete = true;
}
// Execute and flag a motion cancel with deceleration and return to idle. Used primarily by probing cycle
// to halt and cancel the remainder of the motion.
if (rt_exec & EXEC_MOTION_CANCEL) {
if (rt_exec_state.bit.motionCancel) {
// MOTION_CANCEL only occurs during a CYCLE, but a HOLD and SAFETY_DOOR may been initiated beforehand
// to hold the CYCLE. Motion cancel is valid for a single planner block motion only, while jog cancel
// will handle and clear multiple planner block motions.
if (sys.state != State::Jog) {
sys.suspend |= SUSPEND_MOTION_CANCEL; // NOTE: State is State::Cycle.
sys.suspend.bit.motionCancel = true; // NOTE: State is State::Cycle.
}
sys_rt_exec_state.bit.motionCancel = false;
}
// Execute a feed hold with deceleration, if required. Then, suspend system.
if (rt_exec & EXEC_FEED_HOLD) {
if (rt_exec_state.bit.feedHold) {
// Block SAFETY_DOOR, JOG, and SLEEP states from changing to HOLD state.
if (!(sys.state == State::SafetyDoor || sys.state == State::Jog || sys.state == State::Sleep)) {
sys.state = State::Hold;
}
sys_rt_exec_state.bit.feedHold = false;
}
// Execute a safety door stop with a feed hold and disable spindle/coolant.
// NOTE: Safety door differs from feed holds by stopping everything no matter state, disables powered
// devices (spindle/coolant), and blocks resuming until switch is re-engaged.
if (rt_exec & EXEC_SAFETY_DOOR) {
if (rt_exec_state.bit.safetyDoor) {
report_feedback_message(Message::SafetyDoorAjar);
// If jogging, block safety door methods until jog cancel is complete. Just flag that it happened.
if (!(sys.suspend & SUSPEND_JOG_CANCEL)) {
if (!(sys.suspend.bit.jogCancel)) {
// Check if the safety re-opened during a restore parking motion only. Ignore if
// already retracting, parked or in sleep state.
if (sys.state == State::SafetyDoor) {
if (sys.suspend & SUSPEND_INITIATE_RESTORE) { // Actively restoring
if (sys.suspend.bit.initiateRestore) { // Actively restoring
#ifdef PARKING_ENABLE
// Set hold and reset appropriate control flags to restart parking sequence.
if (sys.step_control & STEP_CONTROL_EXECUTE_SYS_MOTION) {
if (sys.step_control.executeSysMotion) {
st_update_plan_block_parameters(); // Notify stepper module to recompute for hold deceleration.
sys.step_control = (STEP_CONTROL_EXECUTE_HOLD | STEP_CONTROL_EXECUTE_SYS_MOTION);
sys.suspend &= ~(SUSPEND_HOLD_COMPLETE);
sys.step_control = {};
sys.step_control.executeHold = true;
sys.step_control.executeSysMotion = true;
sys.suspend.bit.holdComplete = false;
} // else NO_MOTION is active.
#endif
sys.suspend &= ~(SUSPEND_RETRACT_COMPLETE | SUSPEND_INITIATE_RESTORE | SUSPEND_RESTORE_COMPLETE);
sys.suspend |= SUSPEND_RESTART_RETRACT;
sys.suspend.bit.retractComplete = false;
sys.suspend.bit.initiateRestore = false;
sys.suspend.bit.restoreComplete = false;
sys.suspend.bit.restartRetract = true;
}
}
if (sys.state != State::Sleep) {
sys.state = State::SafetyDoor;
}
sys_rt_exec_state.bit.safetyDoor = false;
}
// NOTE: This flag doesn't change when the door closes, unlike sys.state. Ensures any parking motions
// are executed if the door switch closes and the state returns to HOLD.
sys.suspend |= SUSPEND_SAFETY_DOOR_AJAR;
sys.suspend.bit.safetyDoorAjar = true;
}
}
if (rt_exec & EXEC_SLEEP) {
if (rt_exec_state.bit.sleep) {
if (sys.state == State::Alarm) {
sys.suspend |= (SUSPEND_RETRACT_COMPLETE | SUSPEND_HOLD_COMPLETE);
sys.suspend.bit.retractComplete = true;
sys.suspend.bit.holdComplete = true;
}
sys.state = State::Sleep;
sys_rt_exec_state.bit.sleep = false;
}
system_clear_exec_state_flag((EXEC_MOTION_CANCEL | EXEC_FEED_HOLD | EXEC_SAFETY_DOOR | EXEC_SLEEP));
}
// Execute a cycle start by starting the stepper interrupt to begin executing the blocks in queue.
if (rt_exec & EXEC_CYCLE_START) {
if (rt_exec_state.bit.cycleStart) {
// Block if called at same time as the hold commands: feed hold, motion cancel, and safety door.
// Ensures auto-cycle-start doesn't resume a hold without an explicit user-input.
if (!(rt_exec & (EXEC_FEED_HOLD | EXEC_MOTION_CANCEL | EXEC_SAFETY_DOOR))) {
if (!(rt_exec_state.bit.feedHold || rt_exec_state.bit.motionCancel || rt_exec_state.bit.safetyDoor)) {
// Resume door state when parking motion has retracted and door has been closed.
if ((sys.state == State::SafetyDoor) && !(sys.suspend & SUSPEND_SAFETY_DOOR_AJAR)) {
if (sys.suspend & SUSPEND_RESTORE_COMPLETE) {
if (sys.state == State::SafetyDoor && !(sys.suspend.bit.safetyDoorAjar)) {
if (sys.suspend.bit.restoreComplete) {
sys.state = State::Idle; // Set to IDLE to immediately resume the cycle.
} else if (sys.suspend & SUSPEND_RETRACT_COMPLETE) {
} else if (sys.suspend.bit.retractComplete) {
// Flag to re-energize powered components and restore original position, if disabled by SAFETY_DOOR.
// NOTE: For a safety door to resume, the switch must be closed, as indicated by HOLD state, and
// the retraction execution is complete, which implies the initial feed hold is not active. To
// restore normal operation, the restore procedures must be initiated by the following flag. Once,
// they are complete, it will call CYCLE_START automatically to resume and exit the suspend.
sys.suspend |= SUSPEND_INITIATE_RESTORE;
sys.suspend.bit.initiateRestore = true;
}
}
// Cycle start only when IDLE or when a hold is complete and ready to resume.
if ((sys.state == State::Idle) || ((sys.state == State::Hold) && (sys.suspend & SUSPEND_HOLD_COMPLETE))) {
if (sys.state == State::Hold && sys.spindle_stop_ovr) {
sys.spindle_stop_ovr |= SPINDLE_STOP_OVR_RESTORE_CYCLE; // Set to restore in suspend routine and cycle start after.
if (sys.state == State::Idle || (sys.state == State::Hold && sys.suspend.bit.holdComplete)) {
if (sys.state == State::Hold && sys.spindle_stop_ovr.value) {
sys.spindle_stop_ovr.bit.restoreCycle = true; // Set to restore in suspend routine and cycle start after.
} else {
// Start cycle only if queued motions exist in planner buffer and the motion is not canceled.
sys.step_control = STEP_CONTROL_NORMAL_OP; // Restore step control to normal operation
if (plan_get_current_block() && bit_isfalse(sys.suspend, SUSPEND_MOTION_CANCEL)) {
sys.suspend = SUSPEND_DISABLE; // Break suspend state.
sys.step_control = {}; // Restore step control to normal operation
if (plan_get_current_block() && !sys.suspend.bit.motionCancel) {
sys.suspend.value = 0; // Break suspend state.
sys.state = State::Cycle;
st_prep_buffer(); // Initialize step segment buffer before beginning cycle.
st_wake_up();
} else { // Otherwise, do nothing. Set and resume IDLE state.
sys.suspend = SUSPEND_DISABLE; // Break suspend state.
sys.suspend.value = 0; // Break suspend state.
sys.state = State::Idle;
}
}
}
}
system_clear_exec_state_flag(EXEC_CYCLE_START);
sys_rt_exec_state.bit.cycleStart = false;
}
if (cycle_stop) {
// Reinitializes the cycle plan and stepper system after a feed hold for a resume. Called by
@@ -406,30 +417,31 @@ void protocol_exec_rt_system() {
// cycle reinitializations. The stepper path should continue exactly as if nothing has happened.
// NOTE: cycle_stop is set by the stepper subsystem when a cycle or feed hold completes.
if ((sys.state == State::Hold || sys.state == State::SafetyDoor || sys.state == State::Sleep) && !(sys.soft_limit) &&
!(sys.suspend & SUSPEND_JOG_CANCEL)) {
!(sys.suspend.bit.jogCancel)) {
// Hold complete. Set to indicate ready to resume. Remain in HOLD or DOOR states until user
// has issued a resume command or reset.
plan_cycle_reinitialize();
if (sys.step_control & STEP_CONTROL_EXECUTE_HOLD) {
sys.suspend |= SUSPEND_HOLD_COMPLETE;
if (sys.step_control.executeHold) {
sys.suspend.bit.holdComplete = true;
}
bit_false(sys.step_control, (STEP_CONTROL_EXECUTE_HOLD | STEP_CONTROL_EXECUTE_SYS_MOTION));
sys.step_control.executeHold = false;
sys.step_control.executeSysMotion = false;
} else {
// Motion complete. Includes CYCLE/JOG/HOMING states and jog cancel/motion cancel/soft limit events.
// NOTE: Motion and jog cancel both immediately return to idle after the hold completes.
if (sys.suspend & SUSPEND_JOG_CANCEL) { // For jog cancel, flush buffers and sync positions.
sys.step_control = STEP_CONTROL_NORMAL_OP;
if (sys.suspend.bit.jogCancel) { // For jog cancel, flush buffers and sync positions.
sys.step_control = {};
plan_reset();
st_reset();
gc_sync_position();
plan_sync_position();
}
if (sys.suspend & SUSPEND_SAFETY_DOOR_AJAR) { // Only occurs when safety door opens during jog.
sys.suspend &= ~(SUSPEND_JOG_CANCEL);
sys.suspend |= SUSPEND_HOLD_COMPLETE;
if (sys.suspend.bit.safetyDoorAjar) { // Only occurs when safety door opens during jog.
sys.suspend.bit.jogCancel = false;
sys.suspend.bit.holdComplete = true;
sys.state = State::SafetyDoor;
} else {
sys.suspend = SUSPEND_DISABLE;
sys.suspend.value = 0;
sys.state = State::Idle;
}
}
@@ -437,119 +449,63 @@ void protocol_exec_rt_system() {
}
}
// Execute overrides.
rt_exec = sys_rt_exec_motion_override; // Copy volatile sys_rt_exec_motion_override
if (rt_exec) {
system_clear_exec_motion_overrides(); // Clear all motion override flags.
uint8_t new_f_override = sys.f_override;
if (rt_exec & EXEC_FEED_OVR_RESET) {
new_f_override = DEFAULT_FEED_OVERRIDE;
}
if (rt_exec & EXEC_FEED_OVR_COARSE_PLUS) {
new_f_override += FEED_OVERRIDE_COARSE_INCREMENT;
}
if (rt_exec & EXEC_FEED_OVR_COARSE_MINUS) {
new_f_override -= FEED_OVERRIDE_COARSE_INCREMENT;
}
if (rt_exec & EXEC_FEED_OVR_FINE_PLUS) {
new_f_override += FEED_OVERRIDE_FINE_INCREMENT;
}
if (rt_exec & EXEC_FEED_OVR_FINE_MINUS) {
new_f_override -= FEED_OVERRIDE_FINE_INCREMENT;
}
new_f_override = MIN(new_f_override, MAX_FEED_RATE_OVERRIDE);
new_f_override = MAX(new_f_override, MIN_FEED_RATE_OVERRIDE);
uint8_t new_r_override = sys.r_override;
if (rt_exec & EXEC_RAPID_OVR_RESET) {
new_r_override = DEFAULT_RAPID_OVERRIDE;
}
if (rt_exec & EXEC_RAPID_OVR_MEDIUM) {
new_r_override = RAPID_OVERRIDE_MEDIUM;
}
if (rt_exec & EXEC_RAPID_OVR_LOW) {
new_r_override = RAPID_OVERRIDE_LOW;
}
if ((new_f_override != sys.f_override) || (new_r_override != sys.r_override)) {
sys.f_override = new_f_override;
sys.r_override = new_r_override;
if ((sys_rt_f_override != sys.f_override) || (sys_rt_r_override != sys.r_override)) {
sys.f_override = sys_rt_f_override;
sys.r_override = sys_rt_r_override;
sys.report_ovr_counter = 0; // Set to report change immediately
plan_update_velocity_profile_parameters();
plan_cycle_reinitialize();
}
}
rt_exec = sys_rt_exec_accessory_override;
if (rt_exec) {
system_clear_exec_accessory_overrides(); // Clear all accessory override flags.
// NOTE: Unlike motion overrides, spindle overrides do not require a planner reinitialization.
uint8_t last_s_override = sys.spindle_speed_ovr;
if (rt_exec & EXEC_SPINDLE_OVR_RESET) {
last_s_override = DEFAULT_SPINDLE_SPEED_OVERRIDE;
}
if (rt_exec & EXEC_SPINDLE_OVR_COARSE_PLUS) {
last_s_override += SPINDLE_OVERRIDE_COARSE_INCREMENT;
}
if (rt_exec & EXEC_SPINDLE_OVR_COARSE_MINUS) {
last_s_override -= SPINDLE_OVERRIDE_COARSE_INCREMENT;
}
if (rt_exec & EXEC_SPINDLE_OVR_FINE_PLUS) {
last_s_override += SPINDLE_OVERRIDE_FINE_INCREMENT;
}
if (rt_exec & EXEC_SPINDLE_OVR_FINE_MINUS) {
last_s_override -= SPINDLE_OVERRIDE_FINE_INCREMENT;
}
last_s_override = MIN(last_s_override, MAX_SPINDLE_SPEED_OVERRIDE);
last_s_override = MAX(last_s_override, MIN_SPINDLE_SPEED_OVERRIDE);
if (last_s_override != sys.spindle_speed_ovr) {
bit_true(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM);
sys.spindle_speed_ovr = last_s_override;
if (sys_rt_s_override != sys.spindle_speed_ovr) {
sys.step_control.updateSpindleRpm = true;
sys.spindle_speed_ovr = sys_rt_s_override;
sys.report_ovr_counter = 0; // Set to report change immediately
// If spinlde is on, tell it the rpm has been overridden
if (gc_state.modal.spindle != SpindleState::Disable) {
spindle->set_rpm(gc_state.spindle_speed);
}
}
if (rt_exec & EXEC_SPINDLE_OVR_STOP) {
if (sys_rt_exec_accessory_override.bit.spindleOvrStop) {
sys_rt_exec_accessory_override.bit.spindleOvrStop = false;
// Spindle stop override allowed only while in HOLD state.
// NOTE: Report counters are set in spindle_set_state() when spindle stop is executed.
if (sys.state == State::Hold) {
if (!(sys.spindle_stop_ovr)) {
sys.spindle_stop_ovr = SPINDLE_STOP_OVR_INITIATE;
} else if (sys.spindle_stop_ovr & SPINDLE_STOP_OVR_ENABLED) {
sys.spindle_stop_ovr |= SPINDLE_STOP_OVR_RESTORE;
if (sys.spindle_stop_ovr.value == 0) {
sys.spindle_stop_ovr.bit.initiate = true;
} else if (sys.spindle_stop_ovr.bit.enabled) {
sys.spindle_stop_ovr.bit.restore = true;
}
}
}
// NOTE: Since coolant state always performs a planner sync whenever it changes, the current
// run state can be determined by checking the parser state.
if (rt_exec & (EXEC_COOLANT_FLOOD_OVR_TOGGLE | EXEC_COOLANT_MIST_OVR_TOGGLE)) {
if (sys.state == State::Idle || sys.state == State::Cycle || sys.state == State::Hold) {
CoolantState coolant_state = gc_state.modal.coolant;
if (sys_rt_exec_accessory_override.bit.coolantFloodOvrToggle) {
sys_rt_exec_accessory_override.bit.coolantFloodOvrToggle = false;
#ifdef COOLANT_FLOOD_PIN
if (rt_exec & EXEC_COOLANT_FLOOD_OVR_TOGGLE) {
if (coolant_state.Flood) {
coolant_state.Flood = 0;
} else {
coolant_state.Flood = 1;
}
if (sys.state == State::Idle || sys.state == State::Cycle || sys.state == State::Hold) {
gc_state.modal.coolant.Flood = !gc_state.modal.coolant.Flood;
coolant_set_state(gc_state.modal.coolant); // Report counter set in coolant_set_state().
}
#endif
}
if (sys_rt_exec_accessory_override.bit.coolantMistOvrToggle) {
sys_rt_exec_accessory_override.bit.coolantMistOvrToggle = false;
#ifdef COOLANT_MIST_PIN
if (rt_exec & EXEC_COOLANT_MIST_OVR_TOGGLE) {
if (coolant_state.Mist) {
coolant_state.Mist = 0;
} else {
coolant_state.Mist = 1;
}
if (sys.state == State::Idle || sys.state == State::Cycle || sys.state == State::Hold) {
gc_state.modal.coolant.Mist = !gc_state.modal.coolant.Mist;
coolant_set_state(gc_state.modal.coolant); // Report counter set in coolant_set_state().
}
#endif
coolant_set_state(coolant_state); // Report counter set in coolant_set_state().
gc_state.modal.coolant = coolant_state;
}
}
}
#ifdef DEBUG
if (sys_rt_exec_debug) {
report_realtime_debug();
sys_rt_exec_debug = 0;
sys_rt_exec_debug = false;
}
#endif
// Reload step segment buffer
@@ -603,30 +559,30 @@ static void protocol_exec_rt_suspend() {
}
#ifdef DISABLE_LASER_DURING_HOLD
if (laser_mode->get()) {
system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_STOP);
sys_rt_exec_accessory_override.bit.spindleOvrStop = true;
}
#endif
while (sys.suspend) {
while (sys.suspend.value) {
if (sys.abort) {
return;
}
// Block until initial hold is complete and the machine has stopped motion.
if (sys.suspend & SUSPEND_HOLD_COMPLETE) {
if (sys.suspend.bit.holdComplete) {
// Parking manager. Handles de/re-energizing, switch state checks, and parking motions for
// the safety door and sleep states.
if (sys.state == State::SafetyDoor || sys.state == State::Sleep) {
// Handles retraction motions and de-energizing.
if (bit_isfalse(sys.suspend, SUSPEND_RETRACT_COMPLETE)) {
if (!sys.suspend.bit.retractComplete) {
// Ensure any prior spindle stop override is disabled at start of safety door routine.
sys.spindle_stop_ovr = SPINDLE_STOP_OVR_DISABLED;
sys.spindle_stop_ovr.value = 0; // Disable override
#ifndef PARKING_ENABLE
spindle->set_state(SpindleState::Disable, 0); // De-energize
coolant_off();
#else
// Get current position and store restore location and spindle retract waypoint.
system_convert_array_steps_to_mpos(parking_target, sys_position);
if (bit_isfalse(sys.suspend, SUSPEND_RESTART_RETRACT)) {
if (!sys.suspend.bit.restartRetract) {
memcpy(restore_target, parking_target, sizeof(parking_target));
retract_waypoint += restore_target[PARKING_AXIS];
retract_waypoint = MIN(retract_waypoint, PARKING_TARGET);
@@ -667,8 +623,8 @@ static void protocol_exec_rt_suspend() {
coolant_off();
}
#endif
sys.suspend &= ~(SUSPEND_RESTART_RETRACT);
sys.suspend |= SUSPEND_RETRACT_COMPLETE;
sys.suspend.bit.restartRetract = false;
sys.suspend.bit.retractComplete = true;
} else {
if (sys.state == State::Sleep) {
report_feedback_message(Message::SleepMode);
@@ -684,11 +640,11 @@ static void protocol_exec_rt_suspend() {
// Allows resuming from parking/safety door. Actively checks if safety door is closed and ready to resume.
if (sys.state == State::SafetyDoor) {
if (!(system_check_safety_door_ajar())) {
sys.suspend &= ~(SUSPEND_SAFETY_DOOR_AJAR); // Reset door ajar flag to denote ready to resume.
sys.suspend.bit.safetyDoorAjar = false; // Reset door ajar flag to denote ready to resume.
}
}
// Handles parking restore and safety door resume.
if (sys.suspend & SUSPEND_INITIATE_RESTORE) {
if (sys.suspend.bit.initiateRestore) {
#ifdef PARKING_ENABLE
// Execute fast restore motion to the pull-out position. Parking requires homing enabled.
// NOTE: State is will remain DOOR, until the de-energizing and retract is complete.
@@ -704,10 +660,10 @@ static void protocol_exec_rt_suspend() {
// Delayed Tasks: Restart spindle and coolant, delay to power-up, then resume cycle.
if (gc_state.modal.spindle != SpindleState::Disable) {
// Block if safety door re-opened during prior restore actions.
if (bit_isfalse(sys.suspend, SUSPEND_RESTART_RETRACT)) {
if (!sys.suspend.bit.restartRetract) {
if (laser_mode->get()) {
// When in laser mode, ignore spindle spin-up delay. Set to turn on laser when cycle starts.
bit_true(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM);
sys.step_control.updateSpindleRpm = true;
} else {
spindle->set_state(restore_spindle, (uint32_t)restore_spindle_speed);
delay_sec(SAFETY_DOOR_SPINDLE_DELAY, DELAY_MODE_SYS_SUSPEND);
@@ -716,7 +672,7 @@ static void protocol_exec_rt_suspend() {
}
if (gc_state.modal.coolant.Flood || gc_state.modal.coolant.Mist) {
// Block if safety door re-opened during prior restore actions.
if (bit_isfalse(sys.suspend, SUSPEND_RESTART_RETRACT)) {
if (!sys.suspend.bit.restartRetract) {
// NOTE: Laser mode will honor this delay. An exhaust system is often controlled by this pin.
coolant_set_state(restore_coolant);
delay_sec(SAFETY_DOOR_COOLANT_DELAY, DELAY_MODE_SYS_SUSPEND);
@@ -726,7 +682,7 @@ static void protocol_exec_rt_suspend() {
// Execute slow plunge motion from pull-out position to resume position.
if (can_park()) {
// Block if safety door re-opened during prior restore actions.
if (bit_isfalse(sys.suspend, SUSPEND_RESTART_RETRACT)) {
if (!sys.suspend.bit.restartRetract) {
// Regardless if the retract parking motion was a valid/safe motion or not, the
// restore parking motion should logically be valid, either by returning to the
// original position through valid machine space or by not moving at all.
@@ -738,46 +694,47 @@ static void protocol_exec_rt_suspend() {
}
}
#endif
if (bit_isfalse(sys.suspend, SUSPEND_RESTART_RETRACT)) {
sys.suspend |= SUSPEND_RESTORE_COMPLETE;
system_set_exec_state_flag(EXEC_CYCLE_START); // Set to resume program.
if (!sys.suspend.bit.restartRetract) {
sys.suspend.bit.restoreComplete = true;
sys_rt_exec_state.bit.cycleStart = true; // Set to resume program.
}
}
}
} else {
// Feed hold manager. Controls spindle stop override states.
// NOTE: Hold ensured as completed by condition check at the beginning of suspend routine.
if (sys.spindle_stop_ovr) {
if (sys.spindle_stop_ovr.value) {
// Handles beginning of spindle stop
if (sys.spindle_stop_ovr & SPINDLE_STOP_OVR_INITIATE) {
if (sys.spindle_stop_ovr.bit.initiate) {
if (gc_state.modal.spindle != SpindleState::Disable) {
spindle->set_state(SpindleState::Disable, 0); // De-energize
sys.spindle_stop_ovr = SPINDLE_STOP_OVR_ENABLED; // Set stop override state to enabled, if de-energized.
sys.spindle_stop_ovr.value = 0;
sys.spindle_stop_ovr.bit.enabled = true; // Set stop override state to enabled, if de-energized.
} else {
sys.spindle_stop_ovr = SPINDLE_STOP_OVR_DISABLED; // Clear stop override state
sys.spindle_stop_ovr.value = 0; // Clear stop override state
}
// Handles restoring of spindle state
} else if (sys.spindle_stop_ovr & (SPINDLE_STOP_OVR_RESTORE | SPINDLE_STOP_OVR_RESTORE_CYCLE)) {
} else if (sys.spindle_stop_ovr.bit.restore || sys.spindle_stop_ovr.bit.restoreCycle) {
if (gc_state.modal.spindle != SpindleState::Disable) {
report_feedback_message(Message::SpindleRestore);
if (laser_mode->get()) {
// When in laser mode, ignore spindle spin-up delay. Set to turn on laser when cycle starts.
bit_true(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM);
sys.step_control.updateSpindleRpm = true;
} else {
spindle->set_state(restore_spindle, (uint32_t)restore_spindle_speed);
}
}
if (sys.spindle_stop_ovr & SPINDLE_STOP_OVR_RESTORE_CYCLE) {
system_set_exec_state_flag(EXEC_CYCLE_START); // Set to resume program.
if (sys.spindle_stop_ovr.bit.restoreCycle) {
sys_rt_exec_state.bit.cycleStart = true; // Set to resume program.
}
sys.spindle_stop_ovr = SPINDLE_STOP_OVR_DISABLED; // Clear stop override state
sys.spindle_stop_ovr.value = 0; // Clear stop override state
}
} else {
// Handles spindle state during hold. NOTE: Spindle speed overrides may be altered during hold state.
// NOTE: STEP_CONTROL_UPDATE_SPINDLE_RPM is automatically reset upon resume in step generator.
if (bit_istrue(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM)) {
// NOTE: sys.step_control.updateSpindleRpm is automatically reset upon resume in step generator.
if (sys.step_control.updateSpindleRpm) {
spindle->set_state(restore_spindle, (uint32_t)restore_spindle_speed);
bit_false(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM);
sys.step_control.updateSpindleRpm = false;
}
}
}

View File

@@ -487,7 +487,7 @@ void report_gcode_modes(uint8_t client) {
}
#ifdef ENABLE_PARKING_OVERRIDE_CONTROL
if (sys.override_ctrl == OVERRIDE_PARKING_MOTION) {
if (sys.override_ctrl == Override::ParkingMotion) {
strcat(modes_rpt, " M56");
}
#endif
@@ -601,13 +601,9 @@ void report_realtime_status(uint8_t client) {
strcat(status, "Run");
break;
case State::Hold:
if (!(sys.suspend & SUSPEND_JOG_CANCEL)) {
if (!(sys.suspend.bit.jogCancel)) {
strcat(status, "Hold:");
if (sys.suspend & SUSPEND_HOLD_COMPLETE) {
strcat(status, "0"); // Ready to resume
} else {
strcat(status, "1"); // Actively holding
}
strcat(status, sys.suspend.bit.holdComplete ? "0" : "1"); // Ready to resume
break;
} // Continues to print jog state during jog cancel.
case State::Jog:
@@ -624,15 +620,11 @@ void report_realtime_status(uint8_t client) {
break;
case State::SafetyDoor:
strcat(status, "Door:");
if (sys.suspend & SUSPEND_INITIATE_RESTORE) {
if (sys.suspend.bit.initiateRestore) {
strcat(status, "3"); // Restoring
} else {
if (sys.suspend & SUSPEND_RETRACT_COMPLETE) {
if (sys.suspend & SUSPEND_SAFETY_DOOR_AJAR) {
strcat(status, "1"); // Door ajar
} else {
strcat(status, "0");
}
if (sys.suspend.bit.retractComplete) {
strcat(status, sys.suspend.bit.safetyDoorAjar ? "1" : "0"); // Door ajar
// Door closed and ready to resume
} else {
strcat(status, "2"); // Retracting
@@ -713,10 +705,10 @@ void report_realtime_status(uint8_t client) {
strcat(status, temp);
#endif
#ifdef REPORT_FIELD_PIN_STATE
uint8_t lim_pin_state = limits_get_state();
uint8_t ctrl_pin_state = system_control_get_state();
uint8_t prb_pin_state = probe_get_state();
if (lim_pin_state | ctrl_pin_state | prb_pin_state) {
AxisMask lim_pin_state = limits_get_state();
ControlPins ctrl_pin_state = system_control_get_state();
bool prb_pin_state = probe_get_state();
if (lim_pin_state || ctrl_pin_state.value || prb_pin_state) {
strcat(status, "|Pn:");
if (prb_pin_state) {
strcat(status, "P");
@@ -742,21 +734,31 @@ void report_realtime_status(uint8_t client) {
strcat(status, "C");
}
}
if (ctrl_pin_state) {
# ifdef ENABLE_SAFETY_DOOR_INPUT_PIN
if (bit_istrue(ctrl_pin_state, CONTROL_PIN_INDEX_SAFETY_DOOR)) {
if (ctrl_pin_state.value) {
if (ctrl_pin_state.bit.safetyDoor) {
strcat(status, "D");
}
# endif
if (bit_istrue(ctrl_pin_state, CONTROL_PIN_INDEX_RESET)) {
if (ctrl_pin_state.bit.reset) {
strcat(status, "R");
}
if (bit_istrue(ctrl_pin_state, CONTROL_PIN_INDEX_FEED_HOLD)) {
if (ctrl_pin_state.bit.feedHold) {
strcat(status, "H");
}
if (bit_istrue(ctrl_pin_state, CONTROL_PIN_INDEX_CYCLE_START)) {
if (ctrl_pin_state.bit.cycleStart) {
strcat(status, "S");
}
if (ctrl_pin_state.bit.macro0) {
strcat(status, "M0");
}
if (ctrl_pin_state.bit.macro1) {
strcat(status, "M1");
}
if (ctrl_pin_state.bit.macro2) {
strcat(status, "M2");
}
if (ctrl_pin_state.bit.macro3) {
strcat(status, "M3");
}
}
}
#endif

View File

@@ -131,7 +131,7 @@ void serialCheckTask(void* pvParameters) {
// Pick off realtime command characters directly from the serial stream. These characters are
// not passed into the main buffer, but these set system state flag bits for realtime execution.
if (is_realtime_command(data)) {
execute_realtime_command(data, client);
execute_realtime_command(static_cast<Cmd>(data), client);
} else {
vTaskEnterCritical(&myMutex);
client_buffer[client].write(data);
@@ -196,91 +196,115 @@ bool any_client_has_data() {
// checks to see if a character is a realtime character
bool is_realtime_command(uint8_t data) {
return data == CMD_RESET || data == CMD_STATUS_REPORT || data == CMD_CYCLE_START || data == CMD_FEED_HOLD || data > 0x7F;
if (data >= 0x80) {
return true;
}
auto cmd = static_cast<Cmd>(data);
return cmd == Cmd::Reset || cmd == Cmd::StatusReport || cmd == Cmd::CycleStart || cmd == Cmd::FeedHold;
}
// Act upon a realtime character
void execute_realtime_command(uint8_t command, uint8_t client) {
void execute_realtime_command(Cmd command, uint8_t client) {
switch (command) {
case CMD_RESET:
case Cmd::Reset:
mc_reset(); // Call motion control reset routine.
break;
case CMD_STATUS_REPORT:
case Cmd::StatusReport:
report_realtime_status(client); // direct call instead of setting flag
break;
case CMD_CYCLE_START:
system_set_exec_state_flag(EXEC_CYCLE_START); // Set as true
case Cmd::CycleStart:
sys_rt_exec_state.bit.cycleStart = true;
break;
case CMD_FEED_HOLD:
system_set_exec_state_flag(EXEC_FEED_HOLD); // Set as true
case Cmd::FeedHold:
sys_rt_exec_state.bit.feedHold = true;
break;
case CMD_SAFETY_DOOR:
system_set_exec_state_flag(EXEC_SAFETY_DOOR);
break; // Set as true
case CMD_JOG_CANCEL:
case Cmd::SafetyDoor:
sys_rt_exec_state.bit.safetyDoor = true;
break;
case Cmd::JogCancel:
if (sys.state == State::Jog) { // Block all other states from invoking motion cancel.
system_set_exec_state_flag(EXEC_MOTION_CANCEL);
sys_rt_exec_state.bit.motionCancel = true;
}
break;
case Cmd::DebugReport:
#ifdef DEBUG
case CMD_DEBUG_REPORT: {
uint8_t sreg = SREG;
cli();
bit_true(sys_rt_exec_debug, EXEC_DEBUG_REPORT);
SREG = sreg;
} break;
sys_rt_exec_debug = true;
#endif
case CMD_FEED_OVR_RESET:
system_set_exec_motion_override_flag(EXEC_FEED_OVR_RESET);
break;
case CMD_FEED_OVR_COARSE_PLUS:
system_set_exec_motion_override_flag(EXEC_FEED_OVR_COARSE_PLUS);
case Cmd::SpindleOvrStop:
sys_rt_exec_accessory_override.bit.spindleOvrStop = 1;
break;
case CMD_FEED_OVR_COARSE_MINUS:
system_set_exec_motion_override_flag(EXEC_FEED_OVR_COARSE_MINUS);
case Cmd::FeedOvrReset:
sys_rt_f_override = FeedOverride::Default;
break;
case CMD_FEED_OVR_FINE_PLUS:
system_set_exec_motion_override_flag(EXEC_FEED_OVR_FINE_PLUS);
case Cmd::FeedOvrCoarsePlus:
sys_rt_f_override += FeedOverride::CoarseIncrement;
if (sys_rt_f_override > FeedOverride::Max) {
sys_rt_f_override = FeedOverride::Max;
}
break;
case CMD_FEED_OVR_FINE_MINUS:
system_set_exec_motion_override_flag(EXEC_FEED_OVR_FINE_MINUS);
case Cmd::FeedOvrCoarseMinus:
sys_rt_f_override -= FeedOverride::CoarseIncrement;
if (sys_rt_f_override < FeedOverride::Min) {
sys_rt_f_override = FeedOverride::Min;
}
break;
case CMD_RAPID_OVR_RESET:
system_set_exec_motion_override_flag(EXEC_RAPID_OVR_RESET);
case Cmd::FeedOvrFinePlus:
sys_rt_f_override += FeedOverride::FineIncrement;
if (sys_rt_f_override > FeedOverride::Max) {
sys_rt_f_override = FeedOverride::Max;
}
break;
case CMD_RAPID_OVR_MEDIUM:
system_set_exec_motion_override_flag(EXEC_RAPID_OVR_MEDIUM);
case Cmd::FeedOvrFineMinus:
sys_rt_f_override -= FeedOverride::FineIncrement;
if (sys_rt_f_override < FeedOverride::Min) {
sys_rt_f_override = FeedOverride::Min;
}
break;
case CMD_RAPID_OVR_LOW:
system_set_exec_motion_override_flag(EXEC_RAPID_OVR_LOW);
case Cmd::RapidOvrReset:
sys_rt_r_override = RapidOverride::Default;
break;
case CMD_SPINDLE_OVR_RESET:
system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_RESET);
case Cmd::RapidOvrMedium:
sys_rt_r_override = RapidOverride::Medium;
break;
case CMD_SPINDLE_OVR_COARSE_PLUS:
system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_COARSE_PLUS);
case Cmd::RapidOvrLow:
sys_rt_r_override = RapidOverride::Low;
break;
case CMD_SPINDLE_OVR_COARSE_MINUS:
system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_COARSE_MINUS);
case Cmd::RapidOvrExtraLow:
sys_rt_r_override = RapidOverride::ExtraLow;
break;
case CMD_SPINDLE_OVR_FINE_PLUS:
system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_FINE_PLUS);
case Cmd::SpindleOvrReset:
sys_rt_s_override = SpindleSpeedOverride::Default;
break;
case CMD_SPINDLE_OVR_FINE_MINUS:
system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_FINE_MINUS);
case Cmd::SpindleOvrCoarsePlus:
sys_rt_s_override += SpindleSpeedOverride::CoarseIncrement;
if (sys_rt_s_override > SpindleSpeedOverride::Max) {
sys_rt_s_override = SpindleSpeedOverride::Max;
}
break;
case CMD_SPINDLE_OVR_STOP:
system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_STOP);
case Cmd::SpindleOvrCoarseMinus:
sys_rt_s_override -= SpindleSpeedOverride::CoarseIncrement;
if (sys_rt_s_override < SpindleSpeedOverride::Min) {
sys_rt_s_override = SpindleSpeedOverride::Min;
}
break;
#ifdef COOLANT_FLOOD_PIN
case CMD_COOLANT_FLOOD_OVR_TOGGLE:
system_set_exec_accessory_override_flag(EXEC_COOLANT_FLOOD_OVR_TOGGLE);
case Cmd::SpindleOvrFinePlus:
sys_rt_s_override += SpindleSpeedOverride::FineIncrement;
if (sys_rt_s_override > SpindleSpeedOverride::Max) {
sys_rt_s_override = SpindleSpeedOverride::Max;
}
break;
#endif
#ifdef COOLANT_MIST_PIN
case CMD_COOLANT_MIST_OVR_TOGGLE:
system_set_exec_accessory_override_flag(EXEC_COOLANT_MIST_OVR_TOGGLE);
case Cmd::SpindleOvrFineMinus:
sys_rt_s_override -= SpindleSpeedOverride::FineIncrement;
if (sys_rt_s_override < SpindleSpeedOverride::Min) {
sys_rt_s_override = SpindleSpeedOverride::Min;
}
break;
case Cmd::CoolantFloodOvrToggle:
sys_rt_exec_accessory_override.bit.coolantFloodOvrToggle = 1;
break;
case Cmd::CoolantMistOvrToggle:
sys_rt_exec_accessory_override.bit.coolantMistOvrToggle = 1;
break;
#endif
}
}

View File

@@ -51,6 +51,6 @@ void serial_reset_read_buffer(uint8_t client);
// Returns the number of bytes available in the RX serial buffer.
uint8_t serial_get_rx_buffer_available(uint8_t client);
void execute_realtime_command(uint8_t command, uint8_t client);
void execute_realtime_command(Cmd command, uint8_t client);
bool any_client_has_data();
bool is_realtime_command(uint8_t data);

View File

@@ -193,7 +193,7 @@ namespace Spindles {
grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Spindle RS485 Unresponsive %d", next_cmd.rx_length);
if (next_cmd.critical) {
grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Critical Spindle RS485 Unresponsive");
system_set_exec_alarm(ExecAlarm::SpindleControl);
sys_rt_exec_alarm = ExecAlarm::SpindleControl;
}
unresponsive = true;
}

View File

@@ -301,7 +301,7 @@ static void stepper_pulse_func() {
}
}
// Check probing state.
if (sys_probe_state == PROBE_ACTIVE) {
if (sys_probe_state == Probe::Active) {
probe_state_monitor();
}
// Reset step out bits.
@@ -796,7 +796,7 @@ static uint8_t st_next_block_index(uint8_t block_index) {
*/
void st_prep_buffer() {
// Block step prep buffer, while in a suspend state and there is no suspend motion to execute.
if (bit_istrue(sys.step_control, STEP_CONTROL_END_MOTION)) {
if (sys.step_control.endMotion) {
return;
}
@@ -804,7 +804,7 @@ void st_prep_buffer() {
// Determine if we need to load a new planner block or if the block needs to be recomputed.
if (pl_block == NULL) {
// Query planner for a queued block
if (sys.step_control & STEP_CONTROL_EXECUTE_SYS_MOTION) {
if (sys.step_control.executeSysMotion) {
pl_block = plan_get_system_motion_block();
} else {
pl_block = plan_get_current_block();
@@ -854,7 +854,7 @@ void st_prep_buffer() {
prep.step_per_mm = prep.steps_remaining / pl_block->millimeters;
prep.req_mm_increment = REQ_MM_INCREMENT_SCALAR / prep.step_per_mm;
prep.dt_remainder = 0.0; // Reset for new segment block
if ((sys.step_control & STEP_CONTROL_EXECUTE_HOLD) || prep.recalculate_flag.decelOverride) {
if ((sys.step_control.executeHold) || prep.recalculate_flag.decelOverride) {
// New block loaded mid-hold. Override planner block entry speed to enforce deceleration.
prep.current_speed = prep.exit_speed;
pl_block->entry_speed_sqr = prep.exit_speed * prep.exit_speed;
@@ -879,7 +879,7 @@ void st_prep_buffer() {
*/
prep.mm_complete = 0.0; // Default velocity profile complete at 0.0mm from end of block.
float inv_2_accel = 0.5 / pl_block->acceleration;
if (sys.step_control & STEP_CONTROL_EXECUTE_HOLD) { // [Forced Deceleration to Zero Velocity]
if (sys.step_control.executeHold) { // [Forced Deceleration to Zero Velocity]
// Compute velocity profile parameters for a feed hold in-progress. This profile overrides
// the planner block profile, enforcing a deceleration to zero speed.
prep.ramp_type = RAMP_DECEL;
@@ -898,7 +898,7 @@ void st_prep_buffer() {
prep.accelerate_until = pl_block->millimeters;
float exit_speed_sqr;
float nominal_speed;
if (sys.step_control & STEP_CONTROL_EXECUTE_SYS_MOTION) {
if (sys.step_control.executeSysMotion) {
prep.exit_speed = exit_speed_sqr = 0.0; // Enforce stop at end of system motion.
} else {
exit_speed_sqr = plan_get_exec_block_exit_speed_sqr();
@@ -956,7 +956,7 @@ void st_prep_buffer() {
}
}
bit_true(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM); // Force update whenever updating block.
sys.step_control.updateSpindleRpm = true; // Force update whenever updating block.
}
// Initialize new segment
@@ -1075,7 +1075,7 @@ void st_prep_buffer() {
/* -----------------------------------------------------------------------------------
Compute spindle speed PWM output for step segment
*/
if (st_prep_block->is_pwm_rate_adjusted || (sys.step_control & STEP_CONTROL_UPDATE_SPINDLE_RPM)) {
if (st_prep_block->is_pwm_rate_adjusted || sys.step_control.updateSpindleRpm) {
if (pl_block->spindle != SpindleState::Disable) {
float rpm = pl_block->spindle_speed;
// NOTE: Feed and rapid overrides are independent of PWM value and do not alter laser power/rate.
@@ -1092,7 +1092,7 @@ void st_prep_buffer() {
sys.spindle_speed = 0.0;
prep.current_spindle_rpm = 0.0;
}
bit_false(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM);
sys.step_control.updateSpindleRpm = false;
}
prep_segment->spindle_rpm = prep.current_spindle_rpm; // Reload segment PWM value
@@ -1113,10 +1113,10 @@ void st_prep_buffer() {
// Bail if we are at the end of a feed hold and don't have a step to execute.
if (prep_segment->n_step == 0) {
if (sys.step_control & STEP_CONTROL_EXECUTE_HOLD) {
if (sys.step_control.executeHold) {
// Less than one step to decelerate to zero speed, but already very close. AMASS
// requires full steps to execute. So, just bail.
bit_true(sys.step_control, STEP_CONTROL_END_MOTION);
sys.step_control.endMotion = true;
#ifdef PARKING_ENABLE
if (!(prep.recalculate_flag.parking)) {
prep.recalculate_flag.holdPartialBlock = 1;
@@ -1195,7 +1195,7 @@ void st_prep_buffer() {
// Reset prep parameters for resuming and then bail. Allow the stepper ISR to complete
// the segment queue, where realtime protocol will set new state upon receiving the
// cycle stop flag from the ISR. Prep_segment is blocked until then.
bit_true(sys.step_control, STEP_CONTROL_END_MOTION);
sys.step_control.endMotion = true;
#ifdef PARKING_ENABLE
if (!(prep.recalculate_flag.parking)) {
prep.recalculate_flag.holdPartialBlock = 1;
@@ -1204,8 +1204,8 @@ void st_prep_buffer() {
return; // Bail!
} else { // End of planner block
// The planner block is complete. All steps are set to be executed in the segment buffer.
if (sys.step_control & STEP_CONTROL_EXECUTE_SYS_MOTION) {
bit_true(sys.step_control, STEP_CONTROL_END_MOTION);
if (sys.step_control.executeSysMotion) {
sys.step_control.endMotion = true;
return;
}
pl_block = NULL; // Set pointer to indicate check and load next planner block.

View File

@@ -25,15 +25,17 @@
system_t sys;
int32_t sys_position[MAX_N_AXIS]; // Real-time machine (aka home) position vector in steps.
int32_t sys_probe_position[MAX_N_AXIS]; // Last probe position in machine coordinates and steps.
volatile uint8_t sys_probe_state; // Probing state value. Used to coordinate the probing cycle with stepper ISR.
volatile uint8_t sys_rt_exec_state; // Global realtime executor bitflag variable for state management. See EXEC bitmasks.
volatile Probe sys_probe_state; // Probing state value. Used to coordinate the probing cycle with stepper ISR.
volatile ExecState sys_rt_exec_state; // Global realtime executor bitflag variable for state management. See EXEC bitmasks.
volatile ExecAlarm sys_rt_exec_alarm; // Global realtime executor bitflag variable for setting various alarms.
volatile uint8_t sys_rt_exec_motion_override; // Global realtime executor bitflag variable for motion-based overrides.
volatile uint8_t sys_rt_exec_accessory_override; // Global realtime executor bitflag variable for spindle/coolant overrides.
volatile ExecAccessory sys_rt_exec_accessory_override; // Global realtime executor bitflag variable for spindle/coolant overrides.
volatile bool cycle_stop; // For state transitions, instead of bitflag
#ifdef DEBUG
volatile uint8_t sys_rt_exec_debug;
volatile bool sys_rt_exec_debug;
#endif
volatile Percent sys_rt_f_override; // Global realtime executor feedrate override percentage
volatile Percent sys_rt_r_override; // Global realtime executor rapid override percentage
volatile Percent sys_rt_s_override; // Global realtime executor spindle override percentage
UserOutput::AnalogOutput* myAnalogOutputs[MaxUserDigitalPin];
UserOutput::DigitalOutput* myDigitalOutputs[MaxUserDigitalPin];
@@ -116,9 +118,9 @@ void controlCheckTask(void* pvParameters) {
int evt;
xQueueReceive(control_sw_queue, &evt, portMAX_DELAY); // block until receive queue
vTaskDelay(CONTROL_SW_DEBOUNCE_PERIOD); // delay a while
uint8_t pin = system_control_get_state();
if (pin) {
system_exec_control_pin(pin);
ControlPins pins = system_control_get_state();
if (pins.value) {
system_exec_control_pin(pins);
}
debouncing = false;
}
@@ -134,77 +136,20 @@ void IRAM_ATTR isr_control_inputs() {
xQueueSendFromISR(control_sw_queue, &evt, NULL);
}
#else
uint8_t pin = system_control_get_state();
system_exec_control_pin(pin);
ControlPins pins = system_control_get_state();
system_exec_control_pin(pins);
#endif
}
// Returns if safety door is ajar(T) or closed(F), based on pin state.
uint8_t system_check_safety_door_ajar() {
#ifdef ENABLE_SAFETY_DOOR_INPUT_PIN
return system_control_get_state() & CONTROL_PIN_INDEX_SAFETY_DOOR;
return system_control_get_state().bit.safetyDoor;
#else
return false; // Input pin not enabled, so just return that it's closed.
#endif
}
// Special handlers for setting and clearing Grbl's real-time execution flags.
void system_set_exec_state_flag(uint8_t mask) {
// TODO uint8_t sreg = SREG;
// TODO cli();
sys_rt_exec_state |= (mask);
// TODO SREG = sreg;
}
void system_clear_exec_state_flag(uint8_t mask) {
//uint8_t sreg = SREG;
//cli();
sys_rt_exec_state &= ~(mask);
//SREG = sreg;
}
void system_set_exec_alarm(ExecAlarm code) {
//uint8_t sreg = SREG;
//cli();
sys_rt_exec_alarm = code;
//SREG = sreg;
}
void system_clear_exec_alarm() {
//uint8_t sreg = SREG;
//cli();
sys_rt_exec_alarm = ExecAlarm::None;
//SREG = sreg;
}
void system_set_exec_motion_override_flag(uint8_t mask) {
//uint8_t sreg = SREG;
//cli();
sys_rt_exec_motion_override |= (mask);
//SREG = sreg;
}
void system_set_exec_accessory_override_flag(uint8_t mask) {
//uint8_t sreg = SREG;
//cli();
sys_rt_exec_accessory_override |= (mask);
//SREG = sreg;
}
void system_clear_exec_motion_overrides() {
//uint8_t sreg = SREG;
//cli();
sys_rt_exec_motion_override = 0;
//SREG = sreg;
}
void system_clear_exec_accessory_overrides() {
//uint8_t sreg = SREG;
//cli();
sys_rt_exec_accessory_override = 0;
//SREG = sreg;
}
void system_flag_wco_change() {
#ifdef FORCE_BUFFER_SYNC_DURING_WCO_CHANGE
protocol_buffer_synchronize();
@@ -267,98 +212,88 @@ uint8_t system_check_travel_limits(float* target) {
// Returns control pin state as a uint8 bitfield. Each bit indicates the input pin state, where
// triggered is 1 and not triggered is 0. Invert mask is applied. Bitfield organization is
// defined by the CONTROL_PIN_INDEX in the header file.
uint8_t system_control_get_state() {
uint8_t defined_pin_mask = 0; // a mask of defined pins
uint8_t control_state = 0;
// defined by the ControlPin in System.h.
ControlPins system_control_get_state() {
ControlPins defined_pins;
defined_pins.value = 0;
ControlPins pin_states;
pin_states.value = 0;
#ifdef CONTROL_SAFETY_DOOR_PIN
defined_pin_mask |= CONTROL_PIN_INDEX_SAFETY_DOOR;
defined_pins.bit.safetyDoor = true;
if (digitalRead(CONTROL_SAFETY_DOOR_PIN)) {
control_state |= CONTROL_PIN_INDEX_SAFETY_DOOR;
pin_states.bit.safetyDoor = true;
}
#endif
#ifdef CONTROL_RESET_PIN
defined_pin_mask |= CONTROL_PIN_INDEX_RESET;
defined_pins.bit.reset = true;
if (digitalRead(CONTROL_RESET_PIN)) {
control_state |= CONTROL_PIN_INDEX_RESET;
pin_states.bit.reset = true;
}
#endif
#ifdef CONTROL_FEED_HOLD_PIN
defined_pin_mask |= CONTROL_PIN_INDEX_FEED_HOLD;
defined_pins.bit.feedHold = true;
if (digitalRead(CONTROL_FEED_HOLD_PIN)) {
control_state |= CONTROL_PIN_INDEX_FEED_HOLD;
pin_states.bit.feedHold = true;
}
#endif
#ifdef CONTROL_CYCLE_START_PIN
defined_pin_mask |= CONTROL_PIN_INDEX_CYCLE_START;
defined_pins.bit.cycleStart = true;
if (digitalRead(CONTROL_CYCLE_START_PIN)) {
control_state |= CONTROL_PIN_INDEX_CYCLE_START;
pin_states.bit.cycleStart = true;
}
#endif
#ifdef MACRO_BUTTON_0_PIN
defined_pin_mask |= CONTROL_PIN_INDEX_MACRO_0;
defined_pins.bit.macro0 = true;
if (digitalRead(MACRO_BUTTON_0_PIN)) {
control_state |= CONTROL_PIN_INDEX_MACRO_0;
pin_states.bit.macro0 = true;
}
#endif
#ifdef MACRO_BUTTON_1_PIN
defined_pin_mask |= CONTROL_PIN_INDEX_MACRO_1;
defined_pins.bit.macro1 = true;
if (digitalRead(MACRO_BUTTON_1_PIN)) {
control_state |= CONTROL_PIN_INDEX_MACRO_1;
pin_states.bit.macro1 = true;
}
#endif
#ifdef MACRO_BUTTON_2_PIN
defined_pin_mask |= CONTROL_PIN_INDEX_MACRO_2;
defined_pins.bit.macro2 = true;
if (digitalRead(MACRO_BUTTON_2_PIN)) {
control_state |= CONTROL_PIN_INDEX_MACRO_2;
pin_states.bit.macro2 = true;
}
#endif
#ifdef MACRO_BUTTON_3_PIN
defined_pin_mask |= CONTROL_PIN_INDEX_MACRO_3;
defined_pins.bit.macro3 = true;
if (digitalRead(MACRO_BUTTON_3_PIN)) {
control_state |= CONTROL_PIN_INDEX_MACRO_3;
pin_states.bit.macro3 = true;
}
#endif
#ifdef INVERT_CONTROL_PIN_MASK
control_state ^= (INVERT_CONTROL_PIN_MASK & defined_pin_mask);
pin_states.value ^= (INVERT_CONTROL_PIN_MASK & defined_pins.value);
#endif
return control_state;
return pin_states;
}
// execute the function of the control pin
void system_exec_control_pin(uint8_t pin) {
if (bit_istrue(pin, CONTROL_PIN_INDEX_RESET)) {
void system_exec_control_pin(ControlPins pins) {
if (pins.bit.reset) {
grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Reset via control pin");
mc_reset();
} else if (bit_istrue(pin, CONTROL_PIN_INDEX_CYCLE_START)) {
bit_true(sys_rt_exec_state, EXEC_CYCLE_START);
} else if (bit_istrue(pin, CONTROL_PIN_INDEX_FEED_HOLD)) {
bit_true(sys_rt_exec_state, EXEC_FEED_HOLD);
} else if (bit_istrue(pin, CONTROL_PIN_INDEX_SAFETY_DOOR)) {
bit_true(sys_rt_exec_state, EXEC_SAFETY_DOOR);
} else if (pins.bit.cycleStart) {
sys_rt_exec_state.bit.cycleStart = true;
} else if (pins.bit.feedHold) {
sys_rt_exec_state.bit.feedHold = true;
} else if (pins.bit.safetyDoor) {
sys_rt_exec_state.bit.safetyDoor = true;
} else if (pins.bit.macro0) {
user_defined_macro(0); // function must be implemented by user
} else if (pins.bit.macro1) {
user_defined_macro(1); // function must be implemented by user
} else if (pins.bit.macro2) {
user_defined_macro(2); // function must be implemented by user
} else if (pins.bit.macro3) {
user_defined_macro(3); // function must be implemented by user
}
#ifdef MACRO_BUTTON_0_PIN
else if (bit_istrue(pin, CONTROL_PIN_INDEX_MACRO_0)) {
user_defined_macro(CONTROL_PIN_INDEX_MACRO_0); // function must be implemented by user
}
#endif
#ifdef MACRO_BUTTON_1_PIN
else if (bit_istrue(pin, CONTROL_PIN_INDEX_MACRO_1)) {
user_defined_macro(CONTROL_PIN_INDEX_MACRO_1); // function must be implemented by user
}
#endif
#ifdef MACRO_BUTTON_2_PIN
else if (bit_istrue(pin, CONTROL_PIN_INDEX_MACRO_2)) {
user_defined_macro(CONTROL_PIN_INDEX_MACRO_2); // function must be implemented by user
}
#endif
#ifdef MACRO_BUTTON_3_PIN
else if (bit_istrue(pin, CONTROL_PIN_INDEX_MACRO_3)) {
user_defined_macro(CONTROL_PIN_INDEX_MACRO_3); // function must be implemented by user
}
#endif
}
// CoreXY calculation only. Returns x or y-axis "steps" based on CoreXY motor steps.
@@ -449,3 +384,4 @@ uint8_t sys_calc_pwm_precision(uint32_t freq) {
return precision - 1;
}
void __attribute__((weak)) user_defined_macro(uint8_t index);

View File

@@ -37,43 +37,98 @@ enum class State : uint8_t {
Sleep, // Sleep state.
};
// Define global system variables
// Step segment generator state flags.
struct StepControl {
uint8_t endMotion : 1;
uint8_t executeHold : 1;
uint8_t executeSysMotion : 1;
uint8_t updateSpindleRpm : 1;
};
// System suspend flags. Used in various ways to manage suspend states and procedures.
struct SuspendBits {
uint8_t holdComplete : 1; // Indicates initial feed hold is complete.
uint8_t restartRetract : 1; // Flag to indicate a retract from a restore parking motion.
uint8_t retractComplete : 1; // (Safety door only) Indicates retraction and de-energizing is complete.
uint8_t initiateRestore : 1; // (Safety door only) Flag to initiate resume procedures from a cycle start.
uint8_t restoreComplete : 1; // (Safety door only) Indicates ready to resume normal operation.
uint8_t safetyDoorAjar : 1; // Tracks safety door state for resuming.
uint8_t motionCancel : 1; // Indicates a canceled resume motion. Currently used by probing routine.
uint8_t jogCancel : 1; // Indicates a jog cancel in process and to reset buffers when complete.
};
union Suspend {
uint8_t value;
SuspendBits bit;
};
typedef uint8_t AxisMask; // Bits indexed by axis number
typedef uint8_t Percent; // Integer percent
typedef uint8_t Counter; // Report interval
enum class Override : uint8_t {
#ifdef DEACTIVATE_PARKING_UPON_INIT
Disabled = 0, // (Default: Must be zero)
ParkingMotion = 1, // M56
#else
ParkingMotion = 0, // M56 (Default: Must be zero)
Disabled = 1, // Parking disabled.
#endif
};
// Spindle stop override control states.
struct SpindleStopBits {
uint8_t enabled : 1;
uint8_t initiate : 1;
uint8_t restore : 1;
uint8_t restoreCycle : 1;
};
union SpindleStop {
uint8_t value;
SpindleStopBits bit;
};
// Global system variables
typedef struct {
volatile State state; // Tracks the current system state of Grbl.
uint8_t abort; // System abort flag. Forces exit back to main loop for reset.
uint8_t suspend; // System suspend bitflag variable that manages holds, cancels, and safety door.
uint8_t soft_limit; // Tracks soft limit errors for the state machine. (boolean)
uint8_t step_control; // Governs the step segment generator depending on system state.
uint8_t probe_succeeded; // Tracks if last probing cycle was successful.
uint8_t homing_axis_lock; // Locks axes when limits engage. Used as an axis motion mask in the stepper ISR.
uint8_t f_override; // Feed rate override value in percent
uint8_t r_override; // Rapids override value in percent
uint8_t spindle_speed_ovr; // Spindle speed value in percent
uint8_t spindle_stop_ovr; // Tracks spindle stop override states
uint8_t report_ovr_counter; // Tracks when to add override data to status reports.
uint8_t report_wco_counter; // Tracks when to add work coordinate offset data to status reports.
bool abort; // System abort flag. Forces exit back to main loop for reset.
Suspend suspend; // System suspend bitflag variable that manages holds, cancels, and safety door.
bool soft_limit; // Tracks soft limit errors for the state machine. (boolean)
StepControl step_control; // Governs the step segment generator depending on system state.
bool probe_succeeded; // Tracks if last probing cycle was successful.
AxisMask homing_axis_lock; // Locks axes when limits engage. Used as an axis motion mask in the stepper ISR.
Percent f_override; // Feed rate override value in percent
Percent r_override; // Rapids override value in percent
Percent spindle_speed_ovr; // Spindle speed value in percent
SpindleStop spindle_stop_ovr; // Tracks spindle stop override states
Counter report_ovr_counter; // Tracks when to add override data to status reports.
Counter report_wco_counter; // Tracks when to add work coordinate offset data to status reports.
#ifdef ENABLE_PARKING_OVERRIDE_CONTROL
uint8_t override_ctrl; // Tracks override control states.
Override override_ctrl; // Tracks override control states.
#endif
uint32_t spindle_speed;
} system_t;
extern system_t sys;
// Define system executor bit map. Used internally by realtime protocol as realtime command flags,
// System executor bit map. Used internally by realtime protocol as realtime command flags,
// which notifies the main program to execute the specified realtime command asynchronously.
// NOTE: The system executor uses an unsigned 8-bit volatile variable (8 flag limit.) The default
// flags are always false, so the realtime protocol only needs to check for a non-zero value to
// know when there is a realtime command to execute.
#define EXEC_STATUS_REPORT bit(0) // bitmask 00000001
#define EXEC_CYCLE_START bit(1) // bitmask 00000010
// #define EXEC_CYCLE_STOP bit(2) // bitmask 00000100 moved to cycle_stop
#define EXEC_FEED_HOLD bit(3) // bitmask 00001000
#define EXEC_RESET bit(4) // bitmask 00010000
#define EXEC_SAFETY_DOOR bit(5) // bitmask 00100000
#define EXEC_MOTION_CANCEL bit(6) // bitmask 01000000
#define EXEC_SLEEP bit(7) // bitmask 10000000
struct ExecStateBits {
uint8_t statusReport : 1;
uint8_t cycleStart : 1;
uint8_t cycleStop : 1; // Unused, per cycle_stop variable
uint8_t feedHold : 1;
uint8_t reset : 1;
uint8_t safetyDoor : 1;
uint8_t motionCancel : 1;
uint8_t sleep : 1;
};
union ExecState {
uint8_t value;
ExecStateBits bit;
};
// Alarm executor codes. Valid values (1-255). Zero is reserved.
enum class ExecAlarm : uint8_t {
@@ -92,104 +147,60 @@ enum class ExecAlarm : uint8_t {
// Override bit maps. Realtime bitflags to control feed, rapid, spindle, and coolant overrides.
// Spindle/coolant and feed/rapids are separated into two controlling flag variables.
#define EXEC_FEED_OVR_RESET bit(0)
#define EXEC_FEED_OVR_COARSE_PLUS bit(1)
#define EXEC_FEED_OVR_COARSE_MINUS bit(2)
#define EXEC_FEED_OVR_FINE_PLUS bit(3)
#define EXEC_FEED_OVR_FINE_MINUS bit(4)
#define EXEC_RAPID_OVR_RESET bit(5)
#define EXEC_RAPID_OVR_MEDIUM bit(6)
#define EXEC_RAPID_OVR_LOW bit(7)
// #define EXEC_RAPID_OVR_EXTRA_LOW bit(*) // *NOT SUPPORTED*
#define EXEC_SPINDLE_OVR_RESET bit(0)
#define EXEC_SPINDLE_OVR_COARSE_PLUS bit(1)
#define EXEC_SPINDLE_OVR_COARSE_MINUS bit(2)
#define EXEC_SPINDLE_OVR_FINE_PLUS bit(3)
#define EXEC_SPINDLE_OVR_FINE_MINUS bit(4)
#define EXEC_SPINDLE_OVR_STOP bit(5)
#define EXEC_COOLANT_FLOOD_OVR_TOGGLE bit(6)
#define EXEC_COOLANT_MIST_OVR_TOGGLE bit(7)
struct ExecAccessoryBits {
uint8_t spindleOvrStop : 1;
uint8_t coolantFloodOvrToggle : 1;
uint8_t coolantMistOvrToggle : 1;
};
// Define system suspend flags. Used in various ways to manage suspend states and procedures.
#define SUSPEND_DISABLE 0 // Must be zero.
#define SUSPEND_HOLD_COMPLETE bit(0) // Indicates initial feed hold is complete.
#define SUSPEND_RESTART_RETRACT bit(1) // Flag to indicate a retract from a restore parking motion.
#define SUSPEND_RETRACT_COMPLETE bit(2) // (Safety door only) Indicates retraction and de-energizing is complete.
#define SUSPEND_INITIATE_RESTORE bit(3) // (Safety door only) Flag to initiate resume procedures from a cycle start.
#define SUSPEND_RESTORE_COMPLETE bit(4) // (Safety door only) Indicates ready to resume normal operation.
#define SUSPEND_SAFETY_DOOR_AJAR bit(5) // Tracks safety door state for resuming.
#define SUSPEND_MOTION_CANCEL bit(6) // Indicates a canceled resume motion. Currently used by probing routine.
#define SUSPEND_JOG_CANCEL bit(7) // Indicates a jog cancel in process and to reset buffers when complete.
union ExecAccessory {
uint8_t value;
ExecAccessoryBits bit;
};
// Define step segment generator state flags.
#define STEP_CONTROL_NORMAL_OP 0 // Must be zero.
#define STEP_CONTROL_END_MOTION bit(0)
#define STEP_CONTROL_EXECUTE_HOLD bit(1)
#define STEP_CONTROL_EXECUTE_SYS_MOTION bit(2)
#define STEP_CONTROL_UPDATE_SPINDLE_RPM bit(3)
// Define control pin index for Grbl internal use. Pin maps may change, but these values don't.
//#ifdef ENABLE_SAFETY_DOOR_INPUT_PIN
#define N_CONTROL_PIN 4
#define CONTROL_PIN_INDEX_SAFETY_DOOR bit(0)
#define CONTROL_PIN_INDEX_RESET bit(1)
#define CONTROL_PIN_INDEX_FEED_HOLD bit(2)
#define CONTROL_PIN_INDEX_CYCLE_START bit(3)
#define CONTROL_PIN_INDEX_MACRO_0 bit(4)
#define CONTROL_PIN_INDEX_MACRO_1 bit(5)
#define CONTROL_PIN_INDEX_MACRO_2 bit(6)
#define CONTROL_PIN_INDEX_MACRO_3 bit(7)
//#else
//#define N_CONTROL_PIN 3
//#define CONTROL_PIN_INDEX_RESET bit(0)
//#define CONTROL_PIN_INDEX_FEED_HOLD bit(1)
//#define CONTROL_PIN_INDEX_CYCLE_START bit(2)
//#endif
// Define spindle stop override control states.
#define SPINDLE_STOP_OVR_DISABLED 0 // Must be zero.
#define SPINDLE_STOP_OVR_ENABLED bit(0)
#define SPINDLE_STOP_OVR_INITIATE bit(1)
#define SPINDLE_STOP_OVR_RESTORE bit(2)
#define SPINDLE_STOP_OVR_RESTORE_CYCLE bit(3)
// Control pin states
struct ControlPinBits {
uint8_t safetyDoor : 1;
uint8_t reset : 1;
uint8_t feedHold : 1;
uint8_t cycleStart : 1;
uint8_t macro0 : 1;
uint8_t macro1 : 1;
uint8_t macro2 : 1;
uint8_t macro3 : 1;
};
union ControlPins {
uint8_t value;
ControlPinBits bit;
};
// NOTE: These position variables may need to be declared as volatiles, if problems arise.
extern int32_t sys_position[MAX_N_AXIS]; // Real-time machine (aka home) position vector in steps.
extern int32_t sys_probe_position[MAX_N_AXIS]; // Last probe position in machine coordinates and steps.
extern volatile uint8_t sys_probe_state; // Probing state value. Used to coordinate the probing cycle with stepper ISR.
extern volatile uint8_t sys_rt_exec_state; // Global realtime executor bitflag variable for state management. See EXEC bitmasks.
extern volatile Probe sys_probe_state; // Probing state value. Used to coordinate the probing cycle with stepper ISR.
extern volatile ExecState sys_rt_exec_state; // Global realtime executor bitflag variable for state management. See EXEC bitmasks.
extern volatile ExecAlarm sys_rt_exec_alarm; // Global realtime executor bitflag variable for setting various alarms.
extern volatile uint8_t sys_rt_exec_motion_override; // Global realtime executor bitflag variable for motion-based overrides.
extern volatile uint8_t sys_rt_exec_accessory_override; // Global realtime executor bitflag variable for spindle/coolant overrides.
extern volatile ExecAccessory sys_rt_exec_accessory_override; // Global realtime executor bitflag variable for spindle/coolant overrides.
extern volatile Percent sys_rt_f_override; // Feed override value in percent
extern volatile Percent sys_rt_r_override; // Rapid feed override value in percent
extern volatile Percent sys_rt_s_override; // Spindle override value in percent
extern volatile bool cycle_stop;
#ifdef DEBUG
# define EXEC_DEBUG_REPORT bit(0)
extern volatile uint8_t sys_rt_exec_debug;
extern volatile bool sys_rt_exec_debug;
#endif
void system_ini(); // Renamed from system_init() due to conflict with esp32 files
// Returns bitfield of control pin states, organized by CONTROL_PIN_INDEX. (1=triggered, 0=not triggered).
uint8_t system_control_get_state();
ControlPins system_control_get_state();
// Returns if safety door is ajar(T) or closed(F), based on pin state.
uint8_t system_check_safety_door_ajar();
void isr_control_inputs();
// Special handlers for setting and clearing Grbl's real-time execution flags.
void system_set_exec_state_flag(uint8_t mask);
void system_clear_exec_state_flag(uint8_t mask);
void system_set_exec_alarm(ExecAlarm code);
void system_clear_exec_alarm();
void system_set_exec_motion_override_flag(uint8_t mask);
void system_set_exec_accessory_override_flag(uint8_t mask);
void system_clear_exec_motion_overrides();
void system_clear_exec_accessory_overrides();
// Execute the startup script lines stored in non-volatile storage upon initialization
void system_execute_startup(char* line);
Error execute_line(char* line, uint8_t client, WebUI::AuthenticationLevel auth_level);
@@ -207,27 +218,16 @@ void system_convert_array_steps_to_mpos(float* position, int32_t* steps);
// Checks and reports if target array exceeds machine travel limits.
uint8_t system_check_travel_limits(float* target);
// Special handlers for setting and clearing Grbl's real-time execution flags.
void system_set_exec_state_flag(uint8_t mask);
void system_clear_exec_state_flag(uint8_t mask);
void system_set_exec_alarm(ExecAlarm code);
void system_clear_exec_alarm();
void system_set_exec_motion_override_flag(uint8_t mask);
void system_set_exec_accessory_override_flag(uint8_t mask);
void system_clear_exec_motion_overrides();
void system_clear_exec_accessory_overrides();
int32_t system_convert_corexy_to_x_axis_steps(int32_t* steps);
int32_t system_convert_corexy_to_y_axis_steps(int32_t* steps);
// A task that runs after a control switch interrupt for debouncing.
void controlCheckTask(void* pvParameters);
void system_exec_control_pin(uint8_t pin);
void system_exec_control_pin(ControlPins pins);
bool sys_io_control(uint8_t io_num_mask, bool turnOn, bool synchronized);
bool sys_pwm_control(uint8_t io_num_mask, float duty, bool synchronized);
int8_t sys_get_next_RMT_chan_num();
int8_t sys_get_next_PWM_chan_num();
uint8_t sys_calc_pwm_precision(uint32_t freq);

View File

@@ -430,35 +430,7 @@ namespace WebUI {
}
# endif
bool Web_Server::is_realtime_cmd(char c) {
switch (c) {
case CMD_STATUS_REPORT:
case CMD_CYCLE_START:
case CMD_RESET:
case CMD_FEED_HOLD:
case CMD_SAFETY_DOOR:
case CMD_JOG_CANCEL:
case CMD_DEBUG_REPORT:
case CMD_FEED_OVR_RESET:
case CMD_FEED_OVR_COARSE_PLUS:
case CMD_FEED_OVR_COARSE_MINUS:
case CMD_FEED_OVR_FINE_PLUS:
case CMD_FEED_OVR_FINE_MINUS:
case CMD_RAPID_OVR_RESET:
case CMD_RAPID_OVR_MEDIUM:
case CMD_RAPID_OVR_LOW:
case CMD_SPINDLE_OVR_COARSE_PLUS:
case CMD_SPINDLE_OVR_COARSE_MINUS:
case CMD_SPINDLE_OVR_FINE_PLUS:
case CMD_SPINDLE_OVR_FINE_MINUS:
case CMD_SPINDLE_OVR_STOP:
case CMD_COOLANT_FLOOD_OVR_TOGGLE:
case CMD_COOLANT_MIST_OVR_TOGGLE:
return true;
default:
return false;
}
}
bool Web_Server::is_realtime_cmd(char c) { return is_realtime_cmd(c); }
void Web_Server::_handle_web_command(bool silent) {
//to save time if already disconnected