1
0
mirror of https://github.com/bdring/Grbl_Esp32.git synced 2025-08-16 11:35:44 +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) {
bool isPenUp;
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
// if the state has not change, we only count down to the pull time
if (previousPenState == isPenUp) {
@@ -247,23 +247,17 @@ void atari_next_pen() {
void user_defined_macro(uint8_t index) {
char gcode_line[20];
switch (index) {
#ifdef MACRO_BUTTON_0_PIN
case CONTROL_PIN_INDEX_MACRO_0:
case 0:
grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Pen switch");
WebUI::inputBuffer.push("$H\r");
break;
#endif
#ifdef MACRO_BUTTON_1_PIN
case CONTROL_PIN_INDEX_MACRO_1:
case 1:
grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Color switch");
atari_next_pen();
sprintf(gcode_line, "G90G0X%3.2f\r", ATARI_PAPER_WIDTH); // alway return to right side to reduce home travel stalls
WebUI::inputBuffer.push(gcode_line);
break;
#endif
#ifdef MACRO_BUTTON_2_PIN
case CONTROL_PIN_INDEX_MACRO_2:
// feed out some paper and reset the Y 0
case 2:
grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Paper switch");
WebUI::inputBuffer.push("G0Y-25\r");
WebUI::inputBuffer.push("G4P0.1\r"); // sync...forces wait for planner to clear
@@ -271,9 +265,7 @@ void user_defined_macro(uint8_t index) {
gc_sync_position();
plan_sync_position();
break;
#endif
default:
grbl_msg_sendf(CLIENT_SERIAL, MsgLevel::Info, "Unknown Switch %d", index);
break;
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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