From 994de40724a6173f70715d2cc64f154acc6ef443 Mon Sep 17 00:00:00 2001 From: Mitch Bradley Date: Wed, 7 Oct 2020 18:43:31 -1000 Subject: [PATCH] Most #defines are gone (#595) * Many more #defines bite the dust * Fixed botch in rt accessory logic * Update Probe.cpp * Update System.cpp * Typo --- Grbl_Esp32/Custom/atari_1020.cpp | 16 +- Grbl_Esp32/Custom/polar_coaster.cpp | 16 +- Grbl_Esp32/src/Config.h | 90 ++++--- Grbl_Esp32/src/GCode.cpp | 10 +- Grbl_Esp32/src/GCode.h | 9 - Grbl_Esp32/src/Grbl.cpp | 22 +- Grbl_Esp32/src/Grbl.h | 2 +- Grbl_Esp32/src/Limits.cpp | 63 ++--- Grbl_Esp32/src/Limits.h | 2 +- Grbl_Esp32/src/MotionControl.cpp | 36 +-- Grbl_Esp32/src/NutsBolts.cpp | 2 +- Grbl_Esp32/src/Probe.cpp | 4 +- Grbl_Esp32/src/Probe.h | 6 +- Grbl_Esp32/src/ProcessSettings.cpp | 2 +- Grbl_Esp32/src/Protocol.cpp | 357 +++++++++++-------------- Grbl_Esp32/src/Report.cpp | 52 ++-- Grbl_Esp32/src/Serial.cpp | 136 ++++++---- Grbl_Esp32/src/Serial.h | 2 +- Grbl_Esp32/src/Spindles/VFDSpindle.cpp | 2 +- Grbl_Esp32/src/Stepper.cpp | 28 +- Grbl_Esp32/src/System.cpp | 184 +++++-------- Grbl_Esp32/src/System.h | 238 ++++++++--------- Grbl_Esp32/src/WebUI/WebServer.cpp | 30 +-- 23 files changed, 592 insertions(+), 717 deletions(-) diff --git a/Grbl_Esp32/Custom/atari_1020.cpp b/Grbl_Esp32/Custom/atari_1020.cpp index 64aa5d68..278e052a 100644 --- a/Grbl_Esp32/Custom/atari_1020.cpp +++ b/Grbl_Esp32/Custom/atari_1020.cpp @@ -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; } } diff --git a/Grbl_Esp32/Custom/polar_coaster.cpp b/Grbl_Esp32/Custom/polar_coaster.cpp index ba279da0..85cf3f8a 100644 --- a/Grbl_Esp32/Custom/polar_coaster.cpp +++ b/Grbl_Esp32/Custom/polar_coaster.cpp @@ -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; } diff --git a/Grbl_Esp32/src/Config.h b/Grbl_Esp32/src/Config.h index f69dcaf6..2de0ac50 100644 --- a/Grbl_Esp32/src/Config.h +++ b/Grbl_Esp32/src/Config.h @@ -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 diff --git a/Grbl_Esp32/src/GCode.cpp b/Grbl_Esp32/src/GCode.cpp index 0118bb31..c26f4b53 100644 --- a/Grbl_Esp32/src/GCode.cpp +++ b/Grbl_Esp32/src/GCode.cpp @@ -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) { diff --git a/Grbl_Esp32/src/GCode.h b/Grbl_Esp32/src/GCode.h index f602a8f7..4b070459 100644 --- a/Grbl_Esp32/src/GCode.h +++ b/Grbl_Esp32/src/GCode.h @@ -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 { diff --git a/Grbl_Esp32/src/Grbl.cpp b/Grbl_Esp32/src/Grbl.cpp index 9743d06b..7a29bc4f 100644 --- a/Grbl_Esp32/src/Grbl.cpp +++ b/Grbl_Esp32/src/Grbl.cpp @@ -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 diff --git a/Grbl_Esp32/src/Grbl.h b/Grbl_Esp32/src/Grbl.h index 77513749..e898f5eb 100644 --- a/Grbl_Esp32/src/Grbl.h +++ b/Grbl_Esp32/src/Grbl.h @@ -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" diff --git a/Grbl_Esp32/src/Limits.cpp b/Grbl_Esp32/src/Limits.cpp index 707d5775..bf8ca591 100644 --- a/Grbl_Esp32/src/Limits.cpp +++ b/Grbl_Esp32/src/Limits.cpp @@ -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 } } } diff --git a/Grbl_Esp32/src/Limits.h b/Grbl_Esp32/src/Limits.h index c0782ed6..1f27208f 100644 --- a/Grbl_Esp32/src/Limits.h +++ b/Grbl_Esp32/src/Limits.h @@ -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); diff --git a/Grbl_Esp32/src/MotionControl.cpp b/Grbl_Esp32/src/MotionControl.cpp index 33238736..9b454be3 100644 --- a/Grbl_Esp32/src/MotionControl.cpp +++ b/Grbl_Esp32/src/MotionControl.cpp @@ -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. } diff --git a/Grbl_Esp32/src/NutsBolts.cpp b/Grbl_Esp32/src/NutsBolts.cpp index 1ded98fa..591ef5e3 100644 --- a/Grbl_Esp32/src/NutsBolts.cpp +++ b/Grbl_Esp32/src/NutsBolts.cpp @@ -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. } } diff --git a/Grbl_Esp32/src/Probe.cpp b/Grbl_Esp32/src/Probe.cpp index 058b936e..661c2d84 100644 --- a/Grbl_Esp32/src/Probe.cpp +++ b/Grbl_Esp32/src/Probe.cpp @@ -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; } } diff --git a/Grbl_Esp32/src/Probe.h b/Grbl_Esp32/src/Probe.h index f1612c93..82e4a196 100644 --- a/Grbl_Esp32/src/Probe.h +++ b/Grbl_Esp32/src/Probe.h @@ -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(); diff --git a/Grbl_Esp32/src/ProcessSettings.cpp b/Grbl_Esp32/src/ProcessSettings.cpp index 67ce2b90..f1a42673 100644 --- a/Grbl_Esp32/src/ProcessSettings.cpp +++ b/Grbl_Esp32/src/ProcessSettings.cpp @@ -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) { diff --git a/Grbl_Esp32/src/Protocol.cpp b/Grbl_Esp32/src/Protocol.cpp index abf37c12..982cecca 100644 --- a/Grbl_Esp32/src/Protocol.cpp +++ b/Grbl_Esp32/src/Protocol.cpp @@ -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; } } } diff --git a/Grbl_Esp32/src/Report.cpp b/Grbl_Esp32/src/Report.cpp index 077f67d9..8f895b6c 100644 --- a/Grbl_Esp32/src/Report.cpp +++ b/Grbl_Esp32/src/Report.cpp @@ -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 diff --git a/Grbl_Esp32/src/Serial.cpp b/Grbl_Esp32/src/Serial.cpp index ae559c4b..f3c75676 100644 --- a/Grbl_Esp32/src/Serial.cpp +++ b/Grbl_Esp32/src/Serial.cpp @@ -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(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(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 } } diff --git a/Grbl_Esp32/src/Serial.h b/Grbl_Esp32/src/Serial.h index 8d3f4b93..7cca0d94 100644 --- a/Grbl_Esp32/src/Serial.h +++ b/Grbl_Esp32/src/Serial.h @@ -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); diff --git a/Grbl_Esp32/src/Spindles/VFDSpindle.cpp b/Grbl_Esp32/src/Spindles/VFDSpindle.cpp index 7df1f4ae..a5e75fcb 100644 --- a/Grbl_Esp32/src/Spindles/VFDSpindle.cpp +++ b/Grbl_Esp32/src/Spindles/VFDSpindle.cpp @@ -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; } diff --git a/Grbl_Esp32/src/Stepper.cpp b/Grbl_Esp32/src/Stepper.cpp index 858e15c2..d78a0d88 100644 --- a/Grbl_Esp32/src/Stepper.cpp +++ b/Grbl_Esp32/src/Stepper.cpp @@ -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. diff --git a/Grbl_Esp32/src/System.cpp b/Grbl_Esp32/src/System.cpp index 7c434ec3..ab5c7a62 100644 --- a/Grbl_Esp32/src/System.cpp +++ b/Grbl_Esp32/src/System.cpp @@ -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); diff --git a/Grbl_Esp32/src/System.h b/Grbl_Esp32/src/System.h index 6ea38625..31b9b343 100644 --- a/Grbl_Esp32/src/System.h +++ b/Grbl_Esp32/src/System.h @@ -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); diff --git a/Grbl_Esp32/src/WebUI/WebServer.cpp b/Grbl_Esp32/src/WebUI/WebServer.cpp index 6fc21ab9..39d5067f 100644 --- a/Grbl_Esp32/src/WebUI/WebServer.cpp +++ b/Grbl_Esp32/src/WebUI/WebServer.cpp @@ -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