1
0
mirror of https://github.com/bdring/Grbl_Esp32.git synced 2025-08-19 21:02:02 +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

@@ -179,7 +179,7 @@ void atari_home_task(void* pvParameters) {
void calc_solenoid(float penZ) { void calc_solenoid(float penZ) {
bool isPenUp; bool isPenUp;
static bool previousPenState = false; static bool previousPenState = false;
uint32_t solenoid_pen_pulse_len; // duty cycle of solenoid uint32_t solenoid_pen_pulse_len; // duty cycle of solenoid
isPenUp = ((penZ > 0) || (sys.state == State::Alarm)); // is pen above Z0 or is there an alarm isPenUp = ((penZ > 0) || (sys.state == State::Alarm)); // is pen above Z0 or is there an alarm
// if the state has not change, we only count down to the pull time // if the state has not change, we only count down to the pull time
if (previousPenState == isPenUp) { if (previousPenState == isPenUp) {
@@ -247,23 +247,17 @@ void atari_next_pen() {
void user_defined_macro(uint8_t index) { void user_defined_macro(uint8_t index) {
char gcode_line[20]; char gcode_line[20];
switch (index) { switch (index) {
#ifdef MACRO_BUTTON_0_PIN case 0:
case CONTROL_PIN_INDEX_MACRO_0:
grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Pen switch"); grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Pen switch");
WebUI::inputBuffer.push("$H\r"); WebUI::inputBuffer.push("$H\r");
break; break;
#endif case 1:
#ifdef MACRO_BUTTON_1_PIN
case CONTROL_PIN_INDEX_MACRO_1:
grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Color switch"); grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Color switch");
atari_next_pen(); atari_next_pen();
sprintf(gcode_line, "G90G0X%3.2f\r", ATARI_PAPER_WIDTH); // alway return to right side to reduce home travel stalls 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); WebUI::inputBuffer.push(gcode_line);
break; break;
#endif case 2:
#ifdef MACRO_BUTTON_2_PIN
case CONTROL_PIN_INDEX_MACRO_2:
// feed out some paper and reset the Y 0
grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Paper switch"); grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Paper switch");
WebUI::inputBuffer.push("G0Y-25\r"); WebUI::inputBuffer.push("G0Y-25\r");
WebUI::inputBuffer.push("G4P0.1\r"); // sync...forces wait for planner to clear 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(); gc_sync_position();
plan_sync_position(); plan_sync_position();
break; break;
#endif
default: default:
grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Unknown Switch %d", index);
break; break;
} }
} }

View File

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

View File

@@ -167,40 +167,37 @@ const int DEFAULT_RADIO_MODE = ESP_RADIO_OFF;
// GCode programs, maybe selected for interface programs. // GCode programs, maybe selected for interface programs.
// NOTE: If changed, manually update help message in report.c. // 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 // 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, // 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 // 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. // space, serial.c's RX ISR will need to be modified to accommodate the change.
// const uint8_t CMD_RESET = 0x80; enum class Cmd : uint8_t {
// const uint8_t CMD_STATUS_REPORT = 0x81; Reset = 0x18, // Ctrl-X
// const uint8_t CMD_CYCLE_START = 0x82; StatusReport = '?',
// const uint8_t CMD_FEED_HOLD = 0x83; CycleStart = '~',
const uint8_t CMD_SAFETY_DOOR = 0x84; FeedHold = '!',
const uint8_t CMD_JOG_CANCEL = 0x85; SafetyDoor = 0x84,
const uint8_t CMD_DEBUG_REPORT = 0x86; // Only when DEBUG enabled, sends debug report in '{}' braces. JogCancel = 0x85,
const uint8_t CMD_FEED_OVR_RESET = 0x90; // Restores feed override value to 100%. DebugReport = 0x86, // Only when DEBUG enabled, sends debug report in '{}' braces.
const uint8_t CMD_FEED_OVR_COARSE_PLUS = 0x91; FeedOvrReset = 0x90, // Restores feed override value to 100%.
const uint8_t CMD_FEED_OVR_COARSE_MINUS = 0x92; FeedOvrCoarsePlus = 0x91,
const uint8_t CMD_FEED_OVR_FINE_PLUS = 0x93; FeedOvrCoarseMinus = 0x92,
const uint8_t CMD_FEED_OVR_FINE_MINUS = 0x94; FeedOvrFinePlus = 0x93,
const uint8_t CMD_RAPID_OVR_RESET = 0x95; // Restores rapid override value to 100%. FeedOvrFineMinus = 0x94,
const uint8_t CMD_RAPID_OVR_MEDIUM = 0x96; RapidOvrReset = 0x95, // Restores rapid override value to 100%.
const uint8_t CMD_RAPID_OVR_LOW = 0x97; RapidOvrMedium = 0x96,
// const uint8_t CMD_RAPID_OVR_EXTRA_LOW = 0x98; // *NOT SUPPORTED* RapidOvrLow = 0x97,
const uint8_t CMD_SPINDLE_OVR_RESET = 0x99; // Restores spindle override value to 100%. RapidOvrExtraLow = 0x98, // *NOT SUPPORTED*
const uint8_t CMD_SPINDLE_OVR_COARSE_PLUS = 0x9A; // 154 SpindleOvrReset = 0x99, // Restores spindle override value to 100%.
const uint8_t CMD_SPINDLE_OVR_COARSE_MINUS = 0x9B; SpindleOvrCoarsePlus = 0x9A, // 154
const uint8_t CMD_SPINDLE_OVR_FINE_PLUS = 0x9C; SpindleOvrCoarseMinus = 0x9B,
const uint8_t CMD_SPINDLE_OVR_FINE_MINUS = 0x9D; SpindleOvrFinePlus = 0x9C,
const uint8_t CMD_SPINDLE_OVR_STOP = 0x9E; SpindleOvrFineMinus = 0x9D,
const uint8_t CMD_COOLANT_FLOOD_OVR_TOGGLE = 0xA0; SpindleOvrStop = 0x9E,
const uint8_t CMD_COOLANT_MIST_OVR_TOGGLE = 0xA1; CoolantFloodOvrToggle = 0xA0,
CoolantMistOvrToggle = 0xA1,
};
// If homing is enabled, homing init lock sets Grbl into an alarm state upon power up. This forces // 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 // 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 // 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 // allowable override values and the coarse and fine increments per command received. Please
// note the allowable values in the descriptions following each define. // note the allowable values in the descriptions following each define.
const int DEFAULT_FEED_OVERRIDE = 100; // 100%. Don't change this value. namespace FeedOverride {
const int MAX_FEED_RATE_OVERRIDE = 200; // Percent of programmed feed rate (100-255). Usually 120% or 200% const int Default = 100; // 100%. Don't change this value.
const int MIN_FEED_RATE_OVERRIDE = 10; // Percent of programmed feed rate (1-100). Usually 50% or 1% const int Max = 200; // Percent of programmed feed rate (100-255). Usually 120% or 200%
const int FEED_OVERRIDE_COARSE_INCREMENT = 10; // (1-99). Usually 10%. const int Min = 10; // Percent of programmed feed rate (1-100). Usually 50% or 1%
const int FEED_OVERRIDE_FINE_INCREMENT = 1; // (1-99). Usually 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. namespace SpindleSpeedOverride {
const int RAPID_OVERRIDE_MEDIUM = 50; // Percent of rapid (1-99). Usually 50%. const int Default = 100; // 100%. Don't change this value.
const int RAPID_OVERRIDE_LOW = 25; // Percent of rapid (1-99). Usually 25%. const int Max = 200; // Percent of programmed spindle speed (100-255). Usually 200%.
// const int RAPID_OVERRIDE_EXTRA_LOW = 5; // *NOT SUPPORTED* Percent of rapid (1-99). Usually 5%. const int Min = 10; // Percent of programmed spindle speed (1-100). Usually 10%.
const int CoarseIncrement = 10; // (1-99). Usually 10%.
const int DEFAULT_SPINDLE_SPEED_OVERRIDE = 100; // 100%. Don't change this value. const int FineIncrement = 1; // (1-99). Usually 1%.
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%.
// When a M2 or M30 program end command is executed, most GCode states are restored to their defaults. // 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 // This compile-time option includes the restoring of the feed, rapid, and spindle speed override values

View File

@@ -1565,8 +1565,8 @@ Error gc_execute_line(char* line, uint8_t client) {
case ProgramFlow::Paused: case ProgramFlow::Paused:
protocol_buffer_synchronize(); // Sync and finish all remaining buffered motions before moving on. protocol_buffer_synchronize(); // Sync and finish all remaining buffered motions before moving on.
if (sys.state != State::CheckMode) { 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. protocol_execute_realtime(); // Execute suspend.
} }
break; break;
case ProgramFlow::CompletedM2: case ProgramFlow::CompletedM2:
@@ -1594,9 +1594,9 @@ Error gc_execute_line(char* line, uint8_t client) {
#endif #endif
// gc_state.modal.override = OVERRIDE_DISABLE; // Not supported. // gc_state.modal.override = OVERRIDE_DISABLE; // Not supported.
#ifdef RESTORE_OVERRIDES_AFTER_PROGRAM_END #ifdef RESTORE_OVERRIDES_AFTER_PROGRAM_END
sys.f_override = DEFAULT_FEED_OVERRIDE; sys.f_override = FeedOverride::Default;
sys.r_override = DEFAULT_RAPID_OVERRIDE; sys.r_override = RapidOverride::Default;
sys.spindle_speed_ovr = DEFAULT_SPINDLE_SPEED_OVERRIDE; sys.spindle_speed_ovr = SpindleSpeedOverride::Default;
#endif #endif
// Execute coordinate change and spindle/coolant stop. // Execute coordinate change and spindle/coolant stop.
if (sys.state != State::CheckMode) { if (sys.state != State::CheckMode) {

View File

@@ -163,15 +163,6 @@ struct CoolantState {
// Modal Group M8: Coolant control // Modal Group M8: Coolant control
// Modal Group M9: Override 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 // Modal Group M10: User I/O control
enum class IoControl : uint8_t { enum class IoControl : uint8_t {

View File

@@ -80,16 +80,20 @@ static void reset_variables() {
State prior_state = sys.state; State prior_state = sys.state;
memset(&sys, 0, sizeof(system_t)); // Clear system struct variable. memset(&sys, 0, sizeof(system_t)); // Clear system struct variable.
sys.state = prior_state; sys.state = prior_state;
sys.f_override = DEFAULT_FEED_OVERRIDE; // Set to 100% sys.f_override = FeedOverride::Default; // Set to 100%
sys.r_override = DEFAULT_RAPID_OVERRIDE; // Set to 100% sys.r_override = RapidOverride::Default; // Set to 100%
sys.spindle_speed_ovr = DEFAULT_SPINDLE_SPEED_OVERRIDE; // Set to 100% sys.spindle_speed_ovr = SpindleSpeedOverride::Default; // Set to 100%
memset(sys_probe_position, 0, sizeof(sys_probe_position)); // Clear probe position. 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;
cycle_stop = false; sys_rt_exec_state.value = 0;
sys_rt_exec_motion_override = 0; sys_rt_exec_accessory_override.value = 0;
sys_rt_exec_accessory_override = 0; sys_rt_exec_alarm = ExecAlarm::None;
system_clear_exec_alarm(); cycle_stop = false;
sys_rt_f_override = FeedOverride::Default;
sys_rt_r_override = RapidOverride::Default;
sys_rt_s_override = SpindleSpeedOverride::Default;
// Reset Grbl primary systems. // Reset Grbl primary systems.
serial_reset_read_buffer(CLIENT_ALL); // Clear serial read buffer serial_reset_read_buffer(CLIENT_ALL); // Clear serial read buffer
gc_init(); // Set g-code parser to default state 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 "Eeprom.h"
#include "WebUI/Authentication.h" #include "WebUI/Authentication.h"
#include "WebUI/Commands.h" #include "WebUI/Commands.h"
#include "Probe.h"
#include "System.h" #include "System.h"
#include "GCode.h" #include "GCode.h"
@@ -51,7 +52,6 @@ const char* const GRBL_VERSION_BUILD = "20201004";
#include "CoolantControl.h" #include "CoolantControl.h"
#include "Limits.h" #include "Limits.h"
#include "MotionControl.h" #include "MotionControl.h"
#include "Probe.h"
#include "Protocol.h" #include "Protocol.h"
#include "Report.h" #include "Report.h"
#include "Serial.h" #include "Serial.h"

View File

@@ -55,12 +55,12 @@ void IRAM_ATTR isr_limit_switches() {
# ifdef HARD_LIMIT_FORCE_STATE_CHECK # ifdef HARD_LIMIT_FORCE_STATE_CHECK
// Check limit pin state. // Check limit pin state.
if (limits_get_state()) { if (limits_get_state()) {
mc_reset(); // Initiate system kill. 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 # else
mc_reset(); // Initiate system kill. 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
#endif #endif
} }
@@ -125,9 +125,10 @@ 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. // Set search mode with approach at seek rate to quickly engage the specified cycle_mask limit switches.
bool approach = true; bool approach = true;
float homing_rate = homing_seek_rate->get(); 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 { do {
system_convert_array_steps_to_mpos(target, sys_position); system_convert_array_steps_to_mpos(target, sys_position);
// Initialize and declare variables needed for homing routine. // Initialize and declare variables needed for homing routine.
@@ -174,11 +175,12 @@ void limits_go_home(uint8_t cycle_mask) {
homing_rate *= sqrt(n_active_axis); // [sqrt(number of active axis)] Adjust so individual axes all move at homing rate. homing_rate *= sqrt(n_active_axis); // [sqrt(number of active axis)] Adjust so individual axes all move at homing rate.
sys.homing_axis_lock = axislock; sys.homing_axis_lock = axislock;
// Perform homing cycle. Planner buffer should be empty, as required to initiate the homing cycle. // 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. pl_data->feed_rate = homing_rate; // Set current homing rate.
plan_buffer_line(target, pl_data); // Bypass mc_line(). Directly plan homing motion. 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 = {};
st_prep_buffer(); // Prep and fill segment buffer from newly planned block. sys.step_control.executeSysMotion = true; // Set to execute homing motion and clear existing flags.
st_wake_up(); // Initiate motion st_prep_buffer(); // Prep and fill segment buffer from newly planned block.
st_wake_up(); // Initiate motion
do { do {
if (approach) { if (approach) {
// Check limit state. Lock out cycle axes when they change. // Check limit state. Lock out cycle axes when they change.
@@ -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. 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. // Exit routines: No time to run protocol_execute_realtime() in this loop.
if ((sys_rt_exec_state & (EXEC_SAFETY_DOOR | EXEC_RESET)) || cycle_stop) { if (sys_rt_exec_state.bit.safetyDoor || sys_rt_exec_state.bit.reset || cycle_stop) {
uint8_t rt_exec = sys_rt_exec_state; ExecState rt_exec_state;
rt_exec_state.value = sys_rt_exec_state.value;
// Homing failure condition: Reset issued during cycle. // Homing failure condition: Reset issued during cycle.
if (rt_exec & EXEC_RESET) { if (rt_exec_state.bit.reset) {
system_set_exec_alarm(ExecAlarm::HomingFailReset); sys_rt_exec_alarm = ExecAlarm::HomingFailReset;
} }
// Homing failure condition: Safety door was opened. // Homing failure condition: Safety door was opened.
if (rt_exec & EXEC_SAFETY_DOOR) { if (rt_exec_state.bit.safetyDoor) {
system_set_exec_alarm(ExecAlarm::HomingFailDoor); sys_rt_exec_alarm = ExecAlarm::HomingFailDoor;
} }
// Homing failure condition: Limit switch still engaged after pull-off motion // Homing failure condition: Limit switch still engaged after pull-off motion
if (!approach && (limits_get_state() & cycle_mask)) { 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. // Homing failure condition: Limit switch not found during approach.
if (approach && cycle_stop) { if (approach && cycle_stop) {
system_set_exec_alarm(ExecAlarm::HomingFailApproach); sys_rt_exec_alarm = ExecAlarm::HomingFailApproach;
} }
if (sys_rt_exec_alarm != ExecAlarm::None) { if (sys_rt_exec_alarm != ExecAlarm::None) {
@@ -303,7 +306,7 @@ void limits_go_home(uint8_t cycle_mask) {
#endif #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 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 // 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 // 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). // number in bit position, i.e. Z_AXIS is bit(2), and Y_AXIS is bit(1).
uint8_t limits_get_state() { AxisMask limits_get_state() {
uint8_t pinMask = 0; AxisMask pinMask = 0;
auto n_axis = number_axis->get(); auto n_axis = number_axis->get();
for (int axis = 0; axis < n_axis; axis++) { for (int axis = 0; axis < n_axis; axis++) {
for (int gang_index = 0; gang_index < 2; gang_index++) { 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 // workspace volume so just come to a controlled stop so position is not lost. When complete
// enter alarm mode. // enter alarm mode.
if (sys.state == State::Cycle) { if (sys.state == State::Cycle) {
system_set_exec_state_flag(EXEC_FEED_HOLD); sys_rt_exec_state.bit.feedHold = true;
do { do {
protocol_execute_realtime(); protocol_execute_realtime();
if (sys.abort) { if (sys.abort) {
@@ -410,9 +413,9 @@ void limits_soft_check(float* target) {
} }
} while (sys.state != State::Idle); } while (sys.state != State::Idle);
} }
mc_reset(); // Issue system reset and ensure spindle and coolant are shutdown. 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 protocol_execute_realtime(); // Execute to enter critical event loop and system abort
return; return;
} }
} }
@@ -423,12 +426,12 @@ void limitCheckTask(void* pvParameters) {
int evt; int evt;
xQueueReceive(limit_sw_queue, &evt, portMAX_DELAY); // block until receive queue xQueueReceive(limit_sw_queue, &evt, portMAX_DELAY); // block until receive queue
vTaskDelay(DEBOUNCE_PERIOD / portTICK_PERIOD_MS); // delay a while vTaskDelay(DEBOUNCE_PERIOD / portTICK_PERIOD_MS); // delay a while
uint8_t switch_state; AxisMask switch_state;
switch_state = limits_get_state(); switch_state = limits_get_state();
if (switch_state) { if (switch_state) {
//grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Limit Switch State %08d", switch_state); //grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Limit Switch State %08d", switch_state);
mc_reset(); // Initiate system kill. 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(); void limits_disable();
// Returns limit state as a bit-wise uint8 variable. // 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. // Perform one portion of the homing cycle based on the input settings.
void limits_go_home(uint8_t cycle_mask); 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 #ifdef LIMITS_TWO_SWITCHES_ON_AXES
if (limits_get_state()) { if (limits_get_state()) {
mc_reset(); // Issue system reset and ensure spindle and coolant are shutdown. 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; return;
} }
#endif #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. // After syncing, check if probe is already triggered. If so, halt and issue alarm.
// NOTE: This probe initialization error applies to all probing cycles. // NOTE: This probe initialization error applies to all probing cycles.
if (probe_get_state() ^ is_probe_away) { // Check probe pin state. 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(); protocol_execute_realtime();
return GCUpdatePos::None; // Nothing else to do but bail. return GCUpdatePos::None; // Nothing else to do but bail.
} }
// Setup and queue probing motion. Auto cycle-start should not start the cycle. // Setup and queue probing motion. Auto cycle-start should not start the cycle.
mc_line(target, pl_data); mc_line(target, pl_data);
// Activate the probing state monitor in the stepper module. // 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. // 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 { do {
protocol_execute_realtime(); protocol_execute_realtime();
if (sys.abort) { if (sys.abort) {
@@ -397,17 +397,17 @@ GCUpdatePos mc_probe_cycle(float* target, plan_line_data_t* pl_data, uint8_t par
} while (sys.state != State::Idle); } while (sys.state != State::Idle);
// Probing cycle complete! // Probing cycle complete!
// Set state variables and error out, if the probe failed and cycle with error is enabled. // 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) { if (is_no_error) {
memcpy(sys_probe_position, sys_position, sizeof(sys_position)); memcpy(sys_probe_position, sys_position, sizeof(sys_position));
} else { } else {
system_set_exec_alarm(ExecAlarm::ProbeFailContact); sys_rt_exec_alarm = ExecAlarm::ProbeFailContact;
} }
} else { } else {
sys.probe_succeeded = true; // Indicate to system the probing cycle completed successfully. 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 protocol_execute_realtime(); // Check and execute run-time commands
// Reset the stepper and planner buffers to remove the remainder of the probe motion. // Reset the stepper and planner buffers to remove the remainder of the probe motion.
st_reset(); // Reset step segment buffer. st_reset(); // Reset step segment buffer.
plan_reset(); // Reset planner buffer. Zero planner positions. Ensure probing motion is cleared. plan_reset(); // Reset planner buffer. Zero planner positions. Ensure probing motion is cleared.
@@ -431,9 +431,9 @@ void mc_parking_motion(float* parking_target, plan_line_data_t* pl_data) {
} }
uint8_t plan_status = plan_buffer_line(parking_target, pl_data); uint8_t plan_status = plan_buffer_line(parking_target, pl_data);
if (plan_status) { if (plan_status) {
bit_true(sys.step_control, STEP_CONTROL_EXECUTE_SYS_MOTION); sys.step_control.executeSysMotion = true;
bit_false(sys.step_control, STEP_CONTROL_END_MOTION); // Allow parking motion to execute, if feed hold is active. 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_parking_setup_buffer(); // Setup step segment buffer for special parking motion case
st_prep_buffer(); st_prep_buffer();
st_wake_up(); st_wake_up();
do { do {
@@ -441,10 +441,10 @@ void mc_parking_motion(float* parking_target, plan_line_data_t* pl_data) {
if (sys.abort) { if (sys.abort) {
return; 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. st_parking_restore_buffer(); // Restore step segment buffer to normal run state.
} else { } else {
bit_false(sys.step_control, STEP_CONTROL_EXECUTE_SYS_MOTION); sys.step_control.executeSysMotion = false;
protocol_exec_rt_system(); 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. // realtime abort command and hard limits. So, keep to a minimum.
void mc_reset() { void mc_reset() {
// Only this function can set the system reset. Helps prevent multiple kill calls. // Only this function can set the system reset. Helps prevent multiple kill calls.
if (bit_isfalse(sys_rt_exec_state, EXEC_RESET)) { if (!sys_rt_exec_state.bit.reset) {
system_set_exec_state_flag(EXEC_RESET); sys_rt_exec_state.bit.reset = true;
// Kill spindle and coolant. // Kill spindle and coolant.
spindle->stop(); spindle->stop();
coolant_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 // the steppers enabled by avoiding the go_idle call altogether, unless the motion state is
// violated, by which, all bets are off. // violated, by which, all bets are off.
if ((sys.state == State::Cycle || sys.state == State::Homing || sys.state == State::Jog) || 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.state == State::Homing) {
if (sys_rt_exec_alarm == ExecAlarm::None) { if (sys_rt_exec_alarm == ExecAlarm::None) {
system_set_exec_alarm(ExecAlarm::HomingFailReset); sys_rt_exec_alarm = ExecAlarm::HomingFailReset;
} }
} else { } else {
system_set_exec_alarm(ExecAlarm::AbortCycle); sys_rt_exec_alarm = ExecAlarm::AbortCycle;
} }
st_go_idle(); // Force kill steppers. Position has likely been lost. 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 } else { // DELAY_MODE_SYS_SUSPEND
// Execute rt_system() only to avoid nesting suspend loops. // Execute rt_system() only to avoid nesting suspend loops.
protocol_exec_rt_system(); protocol_exec_rt_system();
if (sys.suspend & SUSPEND_RESTART_RETRACT) { if (sys.suspend.bit.restartRetract) {
return; // Bail, if safety door reopens. 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. // NOTE: This function must be extremely efficient as to not bog down the stepper ISR.
void probe_state_monitor() { void probe_state_monitor() {
if (probe_get_state() ^ is_probe_away) { 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)); 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. // Values that define the probing state machine.
const int PROBE_OFF = 0; // Probing disabled or not in use. (Must be zero.) enum class Probe : uint8_t {
const int PROBE_ACTIVE = 1; // Actively watching the input pin. Off = 0, // Probing disabled or not in use. (Must be zero.)
Active = 1, // Actively watching the input pin.
};
// Probe pin initialization routine. // Probe pin initialization routine.
void probe_init(); 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)); return home(bit(C_AXIS));
} }
Error sleep_grbl(const char* value, WebUI::AuthenticationLevel auth_level, WebUI::ESPResponseStream* out) { 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; return Error::Ok;
} }
Error get_report_build_info(const char* value, WebUI::AuthenticationLevel auth_level, WebUI::ESPResponseStream* out) { 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() { bool can_park() {
return return
#ifdef ENABLE_PARKING_OVERRIDE_CONTROL #ifdef ENABLE_PARKING_OVERRIDE_CONTROL
sys.override_ctrl == OVERRIDE_PARKING_MOTION && sys.override_ctrl == Override::ParkingMotion &&
#endif #endif
homing_enable->get() && !laser_mode->get(); homing_enable->get() && !laser_mode->get();
} }
@@ -125,7 +125,7 @@ void protocol_main_loop() {
// Check if the safety door is open. // Check if the safety door is open.
sys.state = State::Idle; sys.state = State::Idle;
if (system_check_safety_door_ajar()) { 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. protocol_execute_realtime(); // Enter safety door mode. Should return as IDLE state.
} }
// All systems go! // All systems go!
@@ -222,8 +222,8 @@ void protocol_buffer_synchronize() {
// is finished, single commands), a command that needs to wait for the motions in the buffer to // is finished, single commands), a command that needs to wait for the motions in the buffer to
// execute calls a buffer sync, or the planner buffer is full and ready to go. // execute calls a buffer sync, or the planner buffer is full and ready to go.
void protocol_auto_cycle_start() { void protocol_auto_cycle_start() {
if (plan_get_current_block() != NULL) { // Check if there are any blocks in the buffer. 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 // 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 // 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. // 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. // limit switches, or the main program.
void protocol_execute_realtime() { void protocol_execute_realtime() {
protocol_exec_rt_system(); protocol_exec_rt_system();
if (sys.suspend) { if (sys.suspend.value) {
protocol_exec_rt_suspend(); 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. // Halt everything upon a critical event flag. Currently hard and soft limits flag this.
if ((alarm == ExecAlarm::HardLimit) || (alarm == ExecAlarm::SoftLimit)) { if ((alarm == ExecAlarm::HardLimit) || (alarm == ExecAlarm::SoftLimit)) {
report_feedback_message(Message::CriticalEvent); 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 { do {
// Block everything, except reset and status reports, until user issues reset or power // 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 // 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 // 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 // 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. // 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. ExecState rt_exec_state;
if (rt_exec || cycle_stop) { 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. // Execute system abort.
if (rt_exec & EXEC_RESET) { if (rt_exec_state.bit.reset) {
sys.abort = true; // Only place this is set true. sys.abort = true; // Only place this is set true.
return; // Nothing else to do but exit. return; // Nothing else to do but exit.
} }
// Execute and serial print status // Execute and serial print status
if (rt_exec & EXEC_STATUS_REPORT) { if (rt_exec_state.bit.statusReport) {
report_realtime_status(CLIENT_ALL); 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 // 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. // 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. // State check for allowable states for hold methods.
if (!(sys.state == State::Alarm || sys.state == State::CheckMode)) { if (!(sys.state == State::Alarm || sys.state == State::CheckMode)) {
// If in CYCLE or JOG states, immediately initiate a motion HOLD. // If in CYCLE or JOG states, immediately initiate a motion HOLD.
if (sys.state == State::Cycle || sys.state == State::Jog) { 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. 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 = {};
if (sys.state == State::Jog) { // Jog cancelled upon any hold event, except for sleeping. sys.step_control.executeHold = true; // Initiate suspend state with active flag.
if (!(rt_exec & EXEC_SLEEP)) { if (sys.state == State::Jog) { // Jog cancelled upon any hold event, except for sleeping.
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 IDLE, Grbl is not in motion. Simply indicate suspend state and hold is complete.
if (sys.state == State::Idle) { 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 // 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. // 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 // 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 // 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. // will handle and clear multiple planner block motions.
if (sys.state != State::Jog) { 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. // 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. // 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)) { if (!(sys.state == State::SafetyDoor || sys.state == State::Jog || sys.state == State::Sleep)) {
sys.state = State::Hold; sys.state = State::Hold;
} }
sys_rt_exec_state.bit.feedHold = false;
} }
// Execute a safety door stop with a feed hold and disable spindle/coolant. // 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 // 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. // 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); report_feedback_message(Message::SafetyDoorAjar);
// If jogging, block safety door methods until jog cancel is complete. Just flag that it happened. // 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 // Check if the safety re-opened during a restore parking motion only. Ignore if
// already retracting, parked or in sleep state. // already retracting, parked or in sleep state.
if (sys.state == State::SafetyDoor) { if (sys.state == State::SafetyDoor) {
if (sys.suspend & SUSPEND_INITIATE_RESTORE) { // Actively restoring if (sys.suspend.bit.initiateRestore) { // Actively restoring
#ifdef PARKING_ENABLE #ifdef PARKING_ENABLE
// Set hold and reset appropriate control flags to restart parking sequence. // 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. 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.step_control = {};
sys.suspend &= ~(SUSPEND_HOLD_COMPLETE); sys.step_control.executeHold = true;
sys.step_control.executeSysMotion = true;
sys.suspend.bit.holdComplete = false;
} // else NO_MOTION is active. } // else NO_MOTION is active.
#endif #endif
sys.suspend &= ~(SUSPEND_RETRACT_COMPLETE | SUSPEND_INITIATE_RESTORE | SUSPEND_RESTORE_COMPLETE); sys.suspend.bit.retractComplete = false;
sys.suspend |= SUSPEND_RESTART_RETRACT; sys.suspend.bit.initiateRestore = false;
sys.suspend.bit.restoreComplete = false;
sys.suspend.bit.restartRetract = true;
} }
} }
if (sys.state != State::Sleep) { if (sys.state != State::Sleep) {
sys.state = State::SafetyDoor; 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 // 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. // 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) { 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.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. // 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. // 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. // 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. // 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.state == State::SafetyDoor && !(sys.suspend.bit.safetyDoorAjar)) {
if (sys.suspend & SUSPEND_RESTORE_COMPLETE) { if (sys.suspend.bit.restoreComplete) {
sys.state = State::Idle; // Set to IDLE to immediately resume the cycle. 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. // 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 // 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 // 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, // 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. // 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. // 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::Idle || (sys.state == State::Hold && sys.suspend.bit.holdComplete)) {
if (sys.state == State::Hold && sys.spindle_stop_ovr) { if (sys.state == State::Hold && sys.spindle_stop_ovr.value) {
sys.spindle_stop_ovr |= SPINDLE_STOP_OVR_RESTORE_CYCLE; // Set to restore in suspend routine and cycle start after. sys.spindle_stop_ovr.bit.restoreCycle = true; // Set to restore in suspend routine and cycle start after.
} else { } else {
// Start cycle only if queued motions exist in planner buffer and the motion is not canceled. // 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 sys.step_control = {}; // Restore step control to normal operation
if (plan_get_current_block() && bit_isfalse(sys.suspend, SUSPEND_MOTION_CANCEL)) { if (plan_get_current_block() && !sys.suspend.bit.motionCancel) {
sys.suspend = SUSPEND_DISABLE; // Break suspend state. sys.suspend.value = 0; // Break suspend state.
sys.state = State::Cycle; sys.state = State::Cycle;
st_prep_buffer(); // Initialize step segment buffer before beginning cycle. st_prep_buffer(); // Initialize step segment buffer before beginning cycle.
st_wake_up(); st_wake_up();
} else { // Otherwise, do nothing. Set and resume IDLE state. } 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; sys.state = State::Idle;
} }
} }
} }
} }
system_clear_exec_state_flag(EXEC_CYCLE_START); sys_rt_exec_state.bit.cycleStart = false;
} }
if (cycle_stop) { if (cycle_stop) {
// Reinitializes the cycle plan and stepper system after a feed hold for a resume. Called by // Reinitializes the cycle plan and stepper system after a feed hold for a resume. Called by
@@ -406,150 +417,95 @@ void protocol_exec_rt_system() {
// cycle reinitializations. The stepper path should continue exactly as if nothing has happened. // 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. // 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) && 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 // Hold complete. Set to indicate ready to resume. Remain in HOLD or DOOR states until user
// has issued a resume command or reset. // has issued a resume command or reset.
plan_cycle_reinitialize(); plan_cycle_reinitialize();
if (sys.step_control & STEP_CONTROL_EXECUTE_HOLD) { if (sys.step_control.executeHold) {
sys.suspend |= SUSPEND_HOLD_COMPLETE; 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 { } else {
// Motion complete. Includes CYCLE/JOG/HOMING states and jog cancel/motion cancel/soft limit events. // 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. // 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. if (sys.suspend.bit.jogCancel) { // For jog cancel, flush buffers and sync positions.
sys.step_control = STEP_CONTROL_NORMAL_OP; sys.step_control = {};
plan_reset(); plan_reset();
st_reset(); st_reset();
gc_sync_position(); gc_sync_position();
plan_sync_position(); plan_sync_position();
} }
if (sys.suspend & SUSPEND_SAFETY_DOOR_AJAR) { // Only occurs when safety door opens during jog. if (sys.suspend.bit.safetyDoorAjar) { // Only occurs when safety door opens during jog.
sys.suspend &= ~(SUSPEND_JOG_CANCEL); sys.suspend.bit.jogCancel = false;
sys.suspend |= SUSPEND_HOLD_COMPLETE; sys.suspend.bit.holdComplete = true;
sys.state = State::SafetyDoor; sys.state = State::SafetyDoor;
} else { } else {
sys.suspend = SUSPEND_DISABLE; sys.suspend.value = 0;
sys.state = State::Idle; sys.state = State::Idle;
} }
} }
cycle_stop = false; cycle_stop = false;
} }
} }
// Execute overrides. // Execute overrides.
rt_exec = sys_rt_exec_motion_override; // Copy volatile sys_rt_exec_motion_override if ((sys_rt_f_override != sys.f_override) || (sys_rt_r_override != sys.r_override)) {
if (rt_exec) { sys.f_override = sys_rt_f_override;
system_clear_exec_motion_overrides(); // Clear all motion override flags. sys.r_override = sys_rt_r_override;
uint8_t new_f_override = sys.f_override; sys.report_ovr_counter = 0; // Set to report change immediately
if (rt_exec & EXEC_FEED_OVR_RESET) { plan_update_velocity_profile_parameters();
new_f_override = DEFAULT_FEED_OVERRIDE; plan_cycle_reinitialize();
} }
if (rt_exec & EXEC_FEED_OVR_COARSE_PLUS) {
new_f_override += FEED_OVERRIDE_COARSE_INCREMENT; // NOTE: Unlike motion overrides, spindle overrides do not require a planner reinitialization.
} if (sys_rt_s_override != sys.spindle_speed_ovr) {
if (rt_exec & EXEC_FEED_OVR_COARSE_MINUS) { sys.step_control.updateSpindleRpm = true;
new_f_override -= FEED_OVERRIDE_COARSE_INCREMENT; sys.spindle_speed_ovr = sys_rt_s_override;
} sys.report_ovr_counter = 0; // Set to report change immediately
if (rt_exec & EXEC_FEED_OVR_FINE_PLUS) { // If spinlde is on, tell it the rpm has been overridden
new_f_override += FEED_OVERRIDE_FINE_INCREMENT; if (gc_state.modal.spindle != SpindleState::Disable) {
} spindle->set_rpm(gc_state.spindle_speed);
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;
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) { if (sys_rt_exec_accessory_override.bit.spindleOvrStop) {
system_clear_exec_accessory_overrides(); // Clear all accessory override flags. sys_rt_exec_accessory_override.bit.spindleOvrStop = false;
// NOTE: Unlike motion overrides, spindle overrides do not require a planner reinitialization. // Spindle stop override allowed only while in HOLD state.
uint8_t last_s_override = sys.spindle_speed_ovr; // NOTE: Report counters are set in spindle_set_state() when spindle stop is executed.
if (rt_exec & EXEC_SPINDLE_OVR_RESET) { if (sys.state == State::Hold) {
last_s_override = DEFAULT_SPINDLE_SPEED_OVERRIDE; if (sys.spindle_stop_ovr.value == 0) {
} sys.spindle_stop_ovr.bit.initiate = true;
if (rt_exec & EXEC_SPINDLE_OVR_COARSE_PLUS) { } else if (sys.spindle_stop_ovr.bit.enabled) {
last_s_override += SPINDLE_OVERRIDE_COARSE_INCREMENT; sys.spindle_stop_ovr.bit.restore = true;
}
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;
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) { }
// Spindle stop override allowed only while in HOLD state.
// NOTE: Report counters are set in spindle_set_state() when spindle stop is executed. // NOTE: Since coolant state always performs a planner sync whenever it changes, the current
if (sys.state == State::Hold) { // run state can be determined by checking the parser state.
if (!(sys.spindle_stop_ovr)) { if (sys_rt_exec_accessory_override.bit.coolantFloodOvrToggle) {
sys.spindle_stop_ovr = SPINDLE_STOP_OVR_INITIATE; sys_rt_exec_accessory_override.bit.coolantFloodOvrToggle = false;
} else if (sys.spindle_stop_ovr & SPINDLE_STOP_OVR_ENABLED) {
sys.spindle_stop_ovr |= SPINDLE_STOP_OVR_RESTORE;
}
}
}
// 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;
#ifdef COOLANT_FLOOD_PIN #ifdef COOLANT_FLOOD_PIN
if (rt_exec & EXEC_COOLANT_FLOOD_OVR_TOGGLE) { if (sys.state == State::Idle || sys.state == State::Cycle || sys.state == State::Hold) {
if (coolant_state.Flood) { gc_state.modal.coolant.Flood = !gc_state.modal.coolant.Flood;
coolant_state.Flood = 0; coolant_set_state(gc_state.modal.coolant); // Report counter set in coolant_set_state().
} else {
coolant_state.Flood = 1;
}
}
#endif
#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;
}
}
#endif
coolant_set_state(coolant_state); // Report counter set in coolant_set_state().
gc_state.modal.coolant = coolant_state;
}
} }
#endif
} }
if (sys_rt_exec_accessory_override.bit.coolantMistOvrToggle) {
sys_rt_exec_accessory_override.bit.coolantMistOvrToggle = false;
#ifdef COOLANT_MIST_PIN
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
}
#ifdef DEBUG #ifdef DEBUG
if (sys_rt_exec_debug) { if (sys_rt_exec_debug) {
report_realtime_debug(); report_realtime_debug();
sys_rt_exec_debug = 0; sys_rt_exec_debug = false;
} }
#endif #endif
// Reload step segment buffer // Reload step segment buffer
@@ -603,30 +559,30 @@ static void protocol_exec_rt_suspend() {
} }
#ifdef DISABLE_LASER_DURING_HOLD #ifdef DISABLE_LASER_DURING_HOLD
if (laser_mode->get()) { if (laser_mode->get()) {
system_set_exec_accessory_override_flag(EXEC_SPINDLE_OVR_STOP); sys_rt_exec_accessory_override.bit.spindleOvrStop = true;
} }
#endif #endif
while (sys.suspend) { while (sys.suspend.value) {
if (sys.abort) { if (sys.abort) {
return; return;
} }
// Block until initial hold is complete and the machine has stopped motion. // 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 // Parking manager. Handles de/re-energizing, switch state checks, and parking motions for
// the safety door and sleep states. // the safety door and sleep states.
if (sys.state == State::SafetyDoor || sys.state == State::Sleep) { if (sys.state == State::SafetyDoor || sys.state == State::Sleep) {
// Handles retraction motions and de-energizing. // 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. // 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 #ifndef PARKING_ENABLE
spindle->set_state(SpindleState::Disable, 0); // De-energize spindle->set_state(SpindleState::Disable, 0); // De-energize
coolant_off(); coolant_off();
#else #else
// Get current position and store restore location and spindle retract waypoint. // Get current position and store restore location and spindle retract waypoint.
system_convert_array_steps_to_mpos(parking_target, sys_position); 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)); memcpy(restore_target, parking_target, sizeof(parking_target));
retract_waypoint += restore_target[PARKING_AXIS]; retract_waypoint += restore_target[PARKING_AXIS];
retract_waypoint = MIN(retract_waypoint, PARKING_TARGET); retract_waypoint = MIN(retract_waypoint, PARKING_TARGET);
@@ -667,8 +623,8 @@ static void protocol_exec_rt_suspend() {
coolant_off(); coolant_off();
} }
#endif #endif
sys.suspend &= ~(SUSPEND_RESTART_RETRACT); sys.suspend.bit.restartRetract = false;
sys.suspend |= SUSPEND_RETRACT_COMPLETE; sys.suspend.bit.retractComplete = true;
} else { } else {
if (sys.state == State::Sleep) { if (sys.state == State::Sleep) {
report_feedback_message(Message::SleepMode); 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. // Allows resuming from parking/safety door. Actively checks if safety door is closed and ready to resume.
if (sys.state == State::SafetyDoor) { if (sys.state == State::SafetyDoor) {
if (!(system_check_safety_door_ajar())) { 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. // Handles parking restore and safety door resume.
if (sys.suspend & SUSPEND_INITIATE_RESTORE) { if (sys.suspend.bit.initiateRestore) {
#ifdef PARKING_ENABLE #ifdef PARKING_ENABLE
// Execute fast restore motion to the pull-out position. Parking requires homing enabled. // 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. // 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. // Delayed Tasks: Restart spindle and coolant, delay to power-up, then resume cycle.
if (gc_state.modal.spindle != SpindleState::Disable) { if (gc_state.modal.spindle != SpindleState::Disable) {
// Block if safety door re-opened during prior restore actions. // 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()) { if (laser_mode->get()) {
// When in laser mode, ignore spindle spin-up delay. Set to turn on laser when cycle starts. // 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 { } else {
spindle->set_state(restore_spindle, (uint32_t)restore_spindle_speed); spindle->set_state(restore_spindle, (uint32_t)restore_spindle_speed);
delay_sec(SAFETY_DOOR_SPINDLE_DELAY, DELAY_MODE_SYS_SUSPEND); 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) { if (gc_state.modal.coolant.Flood || gc_state.modal.coolant.Mist) {
// Block if safety door re-opened during prior restore actions. // 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. // NOTE: Laser mode will honor this delay. An exhaust system is often controlled by this pin.
coolant_set_state(restore_coolant); coolant_set_state(restore_coolant);
delay_sec(SAFETY_DOOR_COOLANT_DELAY, DELAY_MODE_SYS_SUSPEND); 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. // Execute slow plunge motion from pull-out position to resume position.
if (can_park()) { if (can_park()) {
// Block if safety door re-opened during prior restore actions. // 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 // 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 // restore parking motion should logically be valid, either by returning to the
// original position through valid machine space or by not moving at all. // original position through valid machine space or by not moving at all.
@@ -738,46 +694,47 @@ static void protocol_exec_rt_suspend() {
} }
} }
#endif #endif
if (bit_isfalse(sys.suspend, SUSPEND_RESTART_RETRACT)) { if (!sys.suspend.bit.restartRetract) {
sys.suspend |= SUSPEND_RESTORE_COMPLETE; sys.suspend.bit.restoreComplete = true;
system_set_exec_state_flag(EXEC_CYCLE_START); // Set to resume program. sys_rt_exec_state.bit.cycleStart = true; // Set to resume program.
} }
} }
} }
} else { } else {
// Feed hold manager. Controls spindle stop override states. // Feed hold manager. Controls spindle stop override states.
// NOTE: Hold ensured as completed by condition check at the beginning of suspend routine. // 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 // 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) { if (gc_state.modal.spindle != SpindleState::Disable) {
spindle->set_state(SpindleState::Disable, 0); // De-energize 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 { } 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 // 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) { if (gc_state.modal.spindle != SpindleState::Disable) {
report_feedback_message(Message::SpindleRestore); report_feedback_message(Message::SpindleRestore);
if (laser_mode->get()) { if (laser_mode->get()) {
// When in laser mode, ignore spindle spin-up delay. Set to turn on laser when cycle starts. // 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 { } else {
spindle->set_state(restore_spindle, (uint32_t)restore_spindle_speed); spindle->set_state(restore_spindle, (uint32_t)restore_spindle_speed);
} }
} }
if (sys.spindle_stop_ovr & SPINDLE_STOP_OVR_RESTORE_CYCLE) { if (sys.spindle_stop_ovr.bit.restoreCycle) {
system_set_exec_state_flag(EXEC_CYCLE_START); // Set to resume program. 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 { } else {
// Handles spindle state during hold. NOTE: Spindle speed overrides may be altered during hold state. // 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. // NOTE: sys.step_control.updateSpindleRpm is automatically reset upon resume in step generator.
if (bit_istrue(sys.step_control, STEP_CONTROL_UPDATE_SPINDLE_RPM)) { if (sys.step_control.updateSpindleRpm) {
spindle->set_state(restore_spindle, (uint32_t)restore_spindle_speed); 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 #ifdef ENABLE_PARKING_OVERRIDE_CONTROL
if (sys.override_ctrl == OVERRIDE_PARKING_MOTION) { if (sys.override_ctrl == Override::ParkingMotion) {
strcat(modes_rpt, " M56"); strcat(modes_rpt, " M56");
} }
#endif #endif
@@ -601,13 +601,9 @@ void report_realtime_status(uint8_t client) {
strcat(status, "Run"); strcat(status, "Run");
break; break;
case State::Hold: case State::Hold:
if (!(sys.suspend & SUSPEND_JOG_CANCEL)) { if (!(sys.suspend.bit.jogCancel)) {
strcat(status, "Hold:"); strcat(status, "Hold:");
if (sys.suspend & SUSPEND_HOLD_COMPLETE) { strcat(status, sys.suspend.bit.holdComplete ? "0" : "1"); // Ready to resume
strcat(status, "0"); // Ready to resume
} else {
strcat(status, "1"); // Actively holding
}
break; break;
} // Continues to print jog state during jog cancel. } // Continues to print jog state during jog cancel.
case State::Jog: case State::Jog:
@@ -624,15 +620,11 @@ void report_realtime_status(uint8_t client) {
break; break;
case State::SafetyDoor: case State::SafetyDoor:
strcat(status, "Door:"); strcat(status, "Door:");
if (sys.suspend & SUSPEND_INITIATE_RESTORE) { if (sys.suspend.bit.initiateRestore) {
strcat(status, "3"); // Restoring strcat(status, "3"); // Restoring
} else { } else {
if (sys.suspend & SUSPEND_RETRACT_COMPLETE) { if (sys.suspend.bit.retractComplete) {
if (sys.suspend & SUSPEND_SAFETY_DOOR_AJAR) { strcat(status, sys.suspend.bit.safetyDoorAjar ? "1" : "0"); // Door ajar
strcat(status, "1"); // Door ajar
} else {
strcat(status, "0");
}
// Door closed and ready to resume // Door closed and ready to resume
} else { } else {
strcat(status, "2"); // Retracting strcat(status, "2"); // Retracting
@@ -713,10 +705,10 @@ void report_realtime_status(uint8_t client) {
strcat(status, temp); strcat(status, temp);
#endif #endif
#ifdef REPORT_FIELD_PIN_STATE #ifdef REPORT_FIELD_PIN_STATE
uint8_t lim_pin_state = limits_get_state(); AxisMask lim_pin_state = limits_get_state();
uint8_t ctrl_pin_state = system_control_get_state(); ControlPins ctrl_pin_state = system_control_get_state();
uint8_t prb_pin_state = probe_get_state(); bool prb_pin_state = probe_get_state();
if (lim_pin_state | ctrl_pin_state | prb_pin_state) { if (lim_pin_state || ctrl_pin_state.value || prb_pin_state) {
strcat(status, "|Pn:"); strcat(status, "|Pn:");
if (prb_pin_state) { if (prb_pin_state) {
strcat(status, "P"); strcat(status, "P");
@@ -742,21 +734,31 @@ void report_realtime_status(uint8_t client) {
strcat(status, "C"); strcat(status, "C");
} }
} }
if (ctrl_pin_state) { if (ctrl_pin_state.value) {
# ifdef ENABLE_SAFETY_DOOR_INPUT_PIN if (ctrl_pin_state.bit.safetyDoor) {
if (bit_istrue(ctrl_pin_state, CONTROL_PIN_INDEX_SAFETY_DOOR)) {
strcat(status, "D"); strcat(status, "D");
} }
# endif if (ctrl_pin_state.bit.reset) {
if (bit_istrue(ctrl_pin_state, CONTROL_PIN_INDEX_RESET)) {
strcat(status, "R"); strcat(status, "R");
} }
if (bit_istrue(ctrl_pin_state, CONTROL_PIN_INDEX_FEED_HOLD)) { if (ctrl_pin_state.bit.feedHold) {
strcat(status, "H"); strcat(status, "H");
} }
if (bit_istrue(ctrl_pin_state, CONTROL_PIN_INDEX_CYCLE_START)) { if (ctrl_pin_state.bit.cycleStart) {
strcat(status, "S"); 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 #endif

View File

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

View File

@@ -301,7 +301,7 @@ static void stepper_pulse_func() {
} }
} }
// Check probing state. // Check probing state.
if (sys_probe_state == PROBE_ACTIVE) { if (sys_probe_state == Probe::Active) {
probe_state_monitor(); probe_state_monitor();
} }
// Reset step out bits. // Reset step out bits.
@@ -796,7 +796,7 @@ static uint8_t st_next_block_index(uint8_t block_index) {
*/ */
void st_prep_buffer() { void st_prep_buffer() {
// Block step prep buffer, while in a suspend state and there is no suspend motion to execute. // 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; 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. // Determine if we need to load a new planner block or if the block needs to be recomputed.
if (pl_block == NULL) { if (pl_block == NULL) {
// Query planner for a queued block // 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(); pl_block = plan_get_system_motion_block();
} else { } else {
pl_block = plan_get_current_block(); 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.step_per_mm = prep.steps_remaining / pl_block->millimeters;
prep.req_mm_increment = REQ_MM_INCREMENT_SCALAR / prep.step_per_mm; prep.req_mm_increment = REQ_MM_INCREMENT_SCALAR / prep.step_per_mm;
prep.dt_remainder = 0.0; // Reset for new segment block 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. // New block loaded mid-hold. Override planner block entry speed to enforce deceleration.
prep.current_speed = prep.exit_speed; prep.current_speed = prep.exit_speed;
pl_block->entry_speed_sqr = prep.exit_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. 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; 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 // Compute velocity profile parameters for a feed hold in-progress. This profile overrides
// the planner block profile, enforcing a deceleration to zero speed. // the planner block profile, enforcing a deceleration to zero speed.
prep.ramp_type = RAMP_DECEL; prep.ramp_type = RAMP_DECEL;
@@ -898,7 +898,7 @@ void st_prep_buffer() {
prep.accelerate_until = pl_block->millimeters; prep.accelerate_until = pl_block->millimeters;
float exit_speed_sqr; float exit_speed_sqr;
float nominal_speed; 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. prep.exit_speed = exit_speed_sqr = 0.0; // Enforce stop at end of system motion.
} else { } else {
exit_speed_sqr = plan_get_exec_block_exit_speed_sqr(); 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 // Initialize new segment
@@ -1075,7 +1075,7 @@ void st_prep_buffer() {
/* ----------------------------------------------------------------------------------- /* -----------------------------------------------------------------------------------
Compute spindle speed PWM output for step segment 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) { if (pl_block->spindle != SpindleState::Disable) {
float rpm = pl_block->spindle_speed; float rpm = pl_block->spindle_speed;
// NOTE: Feed and rapid overrides are independent of PWM value and do not alter laser power/rate. // 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; sys.spindle_speed = 0.0;
prep.current_spindle_rpm = 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 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. // 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 (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 // Less than one step to decelerate to zero speed, but already very close. AMASS
// requires full steps to execute. So, just bail. // 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 #ifdef PARKING_ENABLE
if (!(prep.recalculate_flag.parking)) { if (!(prep.recalculate_flag.parking)) {
prep.recalculate_flag.holdPartialBlock = 1; 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 // 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 // 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. // 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 #ifdef PARKING_ENABLE
if (!(prep.recalculate_flag.parking)) { if (!(prep.recalculate_flag.parking)) {
prep.recalculate_flag.holdPartialBlock = 1; prep.recalculate_flag.holdPartialBlock = 1;
@@ -1204,8 +1204,8 @@ void st_prep_buffer() {
return; // Bail! return; // Bail!
} else { // End of planner block } else { // End of planner block
// The planner block is complete. All steps are set to be executed in the segment buffer. // 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) { if (sys.step_control.executeSysMotion) {
bit_true(sys.step_control, STEP_CONTROL_END_MOTION); sys.step_control.endMotion = true;
return; return;
} }
pl_block = NULL; // Set pointer to indicate check and load next planner block. pl_block = NULL; // Set pointer to indicate check and load next planner block.

View File

@@ -22,18 +22,20 @@
#include "Config.h" #include "Config.h"
// Declare system global variable structure // Declare system global variable structure
system_t sys; system_t sys;
int32_t sys_position[MAX_N_AXIS]; // Real-time machine (aka home) position vector in steps. 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. 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 Probe 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 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 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 ExecAccessory sys_rt_exec_accessory_override; // Global realtime executor bitflag variable for spindle/coolant overrides.
volatile uint8_t sys_rt_exec_accessory_override; // Global realtime executor bitflag variable for spindle/coolant overrides. volatile bool cycle_stop; // For state transitions, instead of bitflag
volatile bool cycle_stop; // For state transitions, instead of bitflag
#ifdef DEBUG #ifdef DEBUG
volatile uint8_t sys_rt_exec_debug; volatile bool sys_rt_exec_debug;
#endif #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::AnalogOutput* myAnalogOutputs[MaxUserDigitalPin];
UserOutput::DigitalOutput* myDigitalOutputs[MaxUserDigitalPin]; UserOutput::DigitalOutput* myDigitalOutputs[MaxUserDigitalPin];
@@ -116,9 +118,9 @@ void controlCheckTask(void* pvParameters) {
int evt; int evt;
xQueueReceive(control_sw_queue, &evt, portMAX_DELAY); // block until receive queue xQueueReceive(control_sw_queue, &evt, portMAX_DELAY); // block until receive queue
vTaskDelay(CONTROL_SW_DEBOUNCE_PERIOD); // delay a while vTaskDelay(CONTROL_SW_DEBOUNCE_PERIOD); // delay a while
uint8_t pin = system_control_get_state(); ControlPins pins = system_control_get_state();
if (pin) { if (pins.value) {
system_exec_control_pin(pin); system_exec_control_pin(pins);
} }
debouncing = false; debouncing = false;
} }
@@ -134,77 +136,20 @@ void IRAM_ATTR isr_control_inputs() {
xQueueSendFromISR(control_sw_queue, &evt, NULL); xQueueSendFromISR(control_sw_queue, &evt, NULL);
} }
#else #else
uint8_t pin = system_control_get_state(); ControlPins pins = system_control_get_state();
system_exec_control_pin(pin); system_exec_control_pin(pins);
#endif #endif
} }
// Returns if safety door is ajar(T) or closed(F), based on pin state. // Returns if safety door is ajar(T) or closed(F), based on pin state.
uint8_t system_check_safety_door_ajar() { uint8_t system_check_safety_door_ajar() {
#ifdef ENABLE_SAFETY_DOOR_INPUT_PIN #ifdef ENABLE_SAFETY_DOOR_INPUT_PIN
return system_control_get_state() & CONTROL_PIN_INDEX_SAFETY_DOOR; return system_control_get_state().bit.safetyDoor;
#else #else
return false; // Input pin not enabled, so just return that it's closed. return false; // Input pin not enabled, so just return that it's closed.
#endif #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() { void system_flag_wco_change() {
#ifdef FORCE_BUFFER_SYNC_DURING_WCO_CHANGE #ifdef FORCE_BUFFER_SYNC_DURING_WCO_CHANGE
protocol_buffer_synchronize(); 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 // 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 // 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. // defined by the ControlPin in System.h.
uint8_t system_control_get_state() { ControlPins system_control_get_state() {
uint8_t defined_pin_mask = 0; // a mask of defined pins ControlPins defined_pins;
uint8_t control_state = 0; defined_pins.value = 0;
ControlPins pin_states;
pin_states.value = 0;
#ifdef CONTROL_SAFETY_DOOR_PIN #ifdef CONTROL_SAFETY_DOOR_PIN
defined_pin_mask |= CONTROL_PIN_INDEX_SAFETY_DOOR; defined_pins.bit.safetyDoor = true;
if (digitalRead(CONTROL_SAFETY_DOOR_PIN)) { if (digitalRead(CONTROL_SAFETY_DOOR_PIN)) {
control_state |= CONTROL_PIN_INDEX_SAFETY_DOOR; pin_states.bit.safetyDoor = true;
} }
#endif #endif
#ifdef CONTROL_RESET_PIN #ifdef CONTROL_RESET_PIN
defined_pin_mask |= CONTROL_PIN_INDEX_RESET; defined_pins.bit.reset = true;
if (digitalRead(CONTROL_RESET_PIN)) { if (digitalRead(CONTROL_RESET_PIN)) {
control_state |= CONTROL_PIN_INDEX_RESET; pin_states.bit.reset = true;
} }
#endif #endif
#ifdef CONTROL_FEED_HOLD_PIN #ifdef CONTROL_FEED_HOLD_PIN
defined_pin_mask |= CONTROL_PIN_INDEX_FEED_HOLD; defined_pins.bit.feedHold = true;
if (digitalRead(CONTROL_FEED_HOLD_PIN)) { if (digitalRead(CONTROL_FEED_HOLD_PIN)) {
control_state |= CONTROL_PIN_INDEX_FEED_HOLD; pin_states.bit.feedHold = true;
} }
#endif #endif
#ifdef CONTROL_CYCLE_START_PIN #ifdef CONTROL_CYCLE_START_PIN
defined_pin_mask |= CONTROL_PIN_INDEX_CYCLE_START; defined_pins.bit.cycleStart = true;
if (digitalRead(CONTROL_CYCLE_START_PIN)) { if (digitalRead(CONTROL_CYCLE_START_PIN)) {
control_state |= CONTROL_PIN_INDEX_CYCLE_START; pin_states.bit.cycleStart = true;
} }
#endif #endif
#ifdef MACRO_BUTTON_0_PIN #ifdef MACRO_BUTTON_0_PIN
defined_pin_mask |= CONTROL_PIN_INDEX_MACRO_0; defined_pins.bit.macro0 = true;
if (digitalRead(MACRO_BUTTON_0_PIN)) { if (digitalRead(MACRO_BUTTON_0_PIN)) {
control_state |= CONTROL_PIN_INDEX_MACRO_0; pin_states.bit.macro0 = true;
} }
#endif #endif
#ifdef MACRO_BUTTON_1_PIN #ifdef MACRO_BUTTON_1_PIN
defined_pin_mask |= CONTROL_PIN_INDEX_MACRO_1; defined_pins.bit.macro1 = true;
if (digitalRead(MACRO_BUTTON_1_PIN)) { if (digitalRead(MACRO_BUTTON_1_PIN)) {
control_state |= CONTROL_PIN_INDEX_MACRO_1; pin_states.bit.macro1 = true;
} }
#endif #endif
#ifdef MACRO_BUTTON_2_PIN #ifdef MACRO_BUTTON_2_PIN
defined_pin_mask |= CONTROL_PIN_INDEX_MACRO_2; defined_pins.bit.macro2 = true;
if (digitalRead(MACRO_BUTTON_2_PIN)) { if (digitalRead(MACRO_BUTTON_2_PIN)) {
control_state |= CONTROL_PIN_INDEX_MACRO_2; pin_states.bit.macro2 = true;
} }
#endif #endif
#ifdef MACRO_BUTTON_3_PIN #ifdef MACRO_BUTTON_3_PIN
defined_pin_mask |= CONTROL_PIN_INDEX_MACRO_3; defined_pins.bit.macro3 = true;
if (digitalRead(MACRO_BUTTON_3_PIN)) { if (digitalRead(MACRO_BUTTON_3_PIN)) {
control_state |= CONTROL_PIN_INDEX_MACRO_3; pin_states.bit.macro3 = true;
} }
#endif #endif
#ifdef INVERT_CONTROL_PIN_MASK #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 #endif
return pin_states;
return control_state;
} }
// execute the function of the control pin // execute the function of the control pin
void system_exec_control_pin(uint8_t pin) { void system_exec_control_pin(ControlPins pins) {
if (bit_istrue(pin, CONTROL_PIN_INDEX_RESET)) { if (pins.bit.reset) {
grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Reset via control pin"); grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Reset via control pin");
mc_reset(); mc_reset();
} else if (bit_istrue(pin, CONTROL_PIN_INDEX_CYCLE_START)) { } else if (pins.bit.cycleStart) {
bit_true(sys_rt_exec_state, EXEC_CYCLE_START); sys_rt_exec_state.bit.cycleStart = true;
} else if (bit_istrue(pin, CONTROL_PIN_INDEX_FEED_HOLD)) { } else if (pins.bit.feedHold) {
bit_true(sys_rt_exec_state, EXEC_FEED_HOLD); sys_rt_exec_state.bit.feedHold = true;
} else if (bit_istrue(pin, CONTROL_PIN_INDEX_SAFETY_DOOR)) { } else if (pins.bit.safetyDoor) {
bit_true(sys_rt_exec_state, EXEC_SAFETY_DOOR); 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. // 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; return precision - 1;
} }
void __attribute__((weak)) user_defined_macro(uint8_t index);

View File

@@ -6,7 +6,7 @@
Copyright (c) 2014-2016 Sungeun K. Jeon for Gnea Research LLC Copyright (c) 2014-2016 Sungeun K. Jeon for Gnea Research LLC
2018 - Bart Dring This file was modifed for use on the ESP32 2018 - Bart Dring This file was modifed for use on the ESP32
CPU. Do not use this with Grbl for atMega328P CPU. Do not use this with Grbl for atMega328P
Grbl is free software: you can redistribute it and/or modify Grbl is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by it under the terms of the GNU General Public License as published by
@@ -37,43 +37,98 @@ enum class State : uint8_t {
Sleep, // Sleep state. Sleep, // Sleep state.
}; };
// Define global system variables // Step segment generator state flags.
typedef struct { struct StepControl {
volatile State state; // Tracks the current system state of Grbl. uint8_t endMotion : 1;
uint8_t abort; // System abort flag. Forces exit back to main loop for reset. uint8_t executeHold : 1;
uint8_t suspend; // System suspend bitflag variable that manages holds, cancels, and safety door. uint8_t executeSysMotion : 1;
uint8_t soft_limit; // Tracks soft limit errors for the state machine. (boolean) uint8_t updateSpindleRpm : 1;
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. // System suspend flags. Used in various ways to manage suspend states and procedures.
uint8_t f_override; // Feed rate override value in percent struct SuspendBits {
uint8_t r_override; // Rapids override value in percent uint8_t holdComplete : 1; // Indicates initial feed hold is complete.
uint8_t spindle_speed_ovr; // Spindle speed value in percent uint8_t restartRetract : 1; // Flag to indicate a retract from a restore parking motion.
uint8_t spindle_stop_ovr; // Tracks spindle stop override states uint8_t retractComplete : 1; // (Safety door only) Indicates retraction and de-energizing is complete.
uint8_t report_ovr_counter; // Tracks when to add override data to status reports. uint8_t initiateRestore : 1; // (Safety door only) Flag to initiate resume procedures from a cycle start.
uint8_t report_wco_counter; // Tracks when to add work coordinate offset data to status reports. uint8_t restoreComplete : 1; // (Safety door only) Indicates ready to resume normal operation.
#ifdef ENABLE_PARKING_OVERRIDE_CONTROL uint8_t safetyDoorAjar : 1; // Tracks safety door state for resuming.
uint8_t override_ctrl; // Tracks override control states. 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 #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.
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
Override override_ctrl; // Tracks override control states.
#endif
uint32_t spindle_speed; uint32_t spindle_speed;
} system_t; } system_t;
extern system_t sys; 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. // 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 // 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 // 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. // know when there is a realtime command to execute.
#define EXEC_STATUS_REPORT bit(0) // bitmask 00000001 struct ExecStateBits {
#define EXEC_CYCLE_START bit(1) // bitmask 00000010 uint8_t statusReport : 1;
// #define EXEC_CYCLE_STOP bit(2) // bitmask 00000100 moved to cycle_stop uint8_t cycleStart : 1;
#define EXEC_FEED_HOLD bit(3) // bitmask 00001000 uint8_t cycleStop : 1; // Unused, per cycle_stop variable
#define EXEC_RESET bit(4) // bitmask 00010000 uint8_t feedHold : 1;
#define EXEC_SAFETY_DOOR bit(5) // bitmask 00100000 uint8_t reset : 1;
#define EXEC_MOTION_CANCEL bit(6) // bitmask 01000000 uint8_t safetyDoor : 1;
#define EXEC_SLEEP bit(7) // bitmask 10000000 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. // Alarm executor codes. Valid values (1-255). Zero is reserved.
enum class ExecAlarm : uint8_t { 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. // 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. // 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) struct ExecAccessoryBits {
#define EXEC_SPINDLE_OVR_COARSE_PLUS bit(1) uint8_t spindleOvrStop : 1;
#define EXEC_SPINDLE_OVR_COARSE_MINUS bit(2) uint8_t coolantFloodOvrToggle : 1;
#define EXEC_SPINDLE_OVR_FINE_PLUS bit(3) uint8_t coolantMistOvrToggle : 1;
#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)
// Define system suspend flags. Used in various ways to manage suspend states and procedures. union ExecAccessory {
#define SUSPEND_DISABLE 0 // Must be zero. uint8_t value;
#define SUSPEND_HOLD_COMPLETE bit(0) // Indicates initial feed hold is complete. ExecAccessoryBits bit;
#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.
// Define step segment generator state flags. // Control pin states
#define STEP_CONTROL_NORMAL_OP 0 // Must be zero. struct ControlPinBits {
#define STEP_CONTROL_END_MOTION bit(0) uint8_t safetyDoor : 1;
#define STEP_CONTROL_EXECUTE_HOLD bit(1) uint8_t reset : 1;
#define STEP_CONTROL_EXECUTE_SYS_MOTION bit(2) uint8_t feedHold : 1;
#define STEP_CONTROL_UPDATE_SPINDLE_RPM bit(3) uint8_t cycleStart : 1;
uint8_t macro0 : 1;
// Define control pin index for Grbl internal use. Pin maps may change, but these values don't. uint8_t macro1 : 1;
//#ifdef ENABLE_SAFETY_DOOR_INPUT_PIN uint8_t macro2 : 1;
#define N_CONTROL_PIN 4 uint8_t macro3 : 1;
#define CONTROL_PIN_INDEX_SAFETY_DOOR bit(0) };
#define CONTROL_PIN_INDEX_RESET bit(1) union ControlPins {
#define CONTROL_PIN_INDEX_FEED_HOLD bit(2) uint8_t value;
#define CONTROL_PIN_INDEX_CYCLE_START bit(3) ControlPinBits bit;
#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)
// NOTE: These position variables may need to be declared as volatiles, if problems arise. // 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_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 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 Probe 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 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 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 ExecAccessory sys_rt_exec_accessory_override; // Global realtime executor bitflag variable for spindle/coolant overrides.
extern volatile uint8_t 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 bool cycle_stop; 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 #ifdef DEBUG
# define EXEC_DEBUG_REPORT bit(0) extern volatile bool sys_rt_exec_debug;
extern volatile uint8_t sys_rt_exec_debug;
#endif #endif
void system_ini(); // Renamed from system_init() due to conflict with esp32 files 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). // 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. // Returns if safety door is ajar(T) or closed(F), based on pin state.
uint8_t system_check_safety_door_ajar(); uint8_t system_check_safety_door_ajar();
void isr_control_inputs(); 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 // Execute the startup script lines stored in non-volatile storage upon initialization
void system_execute_startup(char* line); void system_execute_startup(char* line);
Error execute_line(char* line, uint8_t client, WebUI::AuthenticationLevel auth_level); 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. // Checks and reports if target array exceeds machine travel limits.
uint8_t system_check_travel_limits(float* target); 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_x_axis_steps(int32_t* steps);
int32_t system_convert_corexy_to_y_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. // A task that runs after a control switch interrupt for debouncing.
void controlCheckTask(void* pvParameters); 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_io_control(uint8_t io_num_mask, bool turnOn, bool synchronized);
bool sys_pwm_control(uint8_t io_num_mask, float duty, 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_RMT_chan_num();
int8_t sys_get_next_PWM_chan_num(); int8_t sys_get_next_PWM_chan_num();
uint8_t sys_calc_pwm_precision(uint32_t freq); uint8_t sys_calc_pwm_precision(uint32_t freq);

View File

@@ -430,35 +430,7 @@ namespace WebUI {
} }
# endif # endif
bool Web_Server::is_realtime_cmd(char c) { bool Web_Server::is_realtime_cmd(char c) { return is_realtime_cmd(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;
}
}
void Web_Server::_handle_web_command(bool silent) { void Web_Server::_handle_web_command(bool silent) {
//to save time if already disconnected //to save time if already disconnected