From 6afe6d1a7ca32be545135ba6dbbd374acfb5dcfc Mon Sep 17 00:00:00 2001 From: Terje Io Date: Fri, 12 Jan 2024 13:49:36 +0100 Subject: [PATCH] Fix for issue #426, decreasing the $30 setting value (max spindle RPM) causes incorrect PWM output. Implemented handling of single block, block delete and optional stop disable control signal events. Added help for $S (single block), $B (block delete) and $O (optional stop disable) commands. Added optional HAL entry point for outputting WRGB values to lights such as neopixels. Improved $-commands registration to make it easier to add help text. --- changelog.md | 36 +++++ config.h | 12 +- crossbar.c | 11 +- crossbar.h | 55 ++++++-- driver_opts.h | 2 +- grbl.h | 4 +- grbllib.c | 3 +- hal.h | 29 +++- ioports.c | 62 +++++++-- ioports.h | 3 +- motion_control.c | 8 +- pin_bits_masks.h | 37 ++--- report.c | 48 +++---- settings.c | 7 +- spindle_control.c | 4 +- stream.c | 5 +- system.c | 339 +++++++++++++++++++++++++++++----------------- system.h | 17 ++- 18 files changed, 458 insertions(+), 224 deletions(-) diff --git a/changelog.md b/changelog.md index a759965..c817ddf 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,41 @@ ## grblHAL changelog +Build 20240111 + +Core: + +* Fix for issue #426, decreasing the `$30` setting value \(max spindle RPM\) causes incorrect PWM output. + +* Implemented handling of _single block_, _block delete_ and _optional stop disable_ control signal events. +Added help for `$S` \(single block\), `$B` \(block delete\) and `$O` \(optional stop disable\) commands that can be used +to toggle the functionality when the corresponding switch inputs are not available. + +* Added [optional HAL entry point](http://svn.io-engineering.com/grblHAL/html/structrgb__ptr__t.html) for outputting WRGB values to lights such as neopixels. The WRGB API may be extended later. + +* Improved $-commands registration to make it easier to add help text and keep it in sync. Added missing help text for some core commands. +Tip: send `$help commands` to output command help. + +Drivers: + +* ESP32: moved build configuration from [CMakeLists.txt](https://github.com/grblHAL/ESP32/blob/master/main/CMakeLists.txt) to +[my_machine.h](https://github.com/grblHAL/ESP32/blob/master/main/my_machine.h), mainly for reducing build time in the Web Builder. +More changes for ESP32-S3 compatibility, still work in progress but getting closer. +Added support for third UART \(serial port\). + +* SAM3X8E \(Due\): fix for incorrect pin map, [issue #20](https://github.com/grblHAL/SAM3X8E/issues/20). + +* STM32F1xx: fix for [issue #47](https://github.com/grblHAL/STM32F1xx/issues/47) - bad linker file. +__NOTE:__ this moves settings storage to the end of available flash, if updating backup and restore your settings! + +* Most: further updates for assigning optional signals to aux input ports - should be working now. +__NOTE:__ some signals requires aux pins that support pin change interrupt. + +Plugins: + +* SD card: updated for new $-commands registration \(help text\). + +--- + Build 20231229 Core: diff --git a/config.h b/config.h index 05453a4..c62657e 100644 --- a/config.h +++ b/config.h @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2020-2023 Terje Io + Copyright (c) 2020-2024 Terje Io Grbl is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -1658,7 +1658,7 @@ since the spindle may pull down the Z due to its weight. /*! @name $2 - Setting_StepInvertMask \brief \ref axismask controlling the polarity of the step signals. The default is positive pulses. -Set this value to -1 to invert for all steppers or specify which by mask. +Set this value to -1 or AXES_BITMASK to invert for all steppers or specify which by mask. */ ///@{ #if !defined DEFAULT_STEP_SIGNALS_INVERT_MASK || defined __DOXYGEN__ @@ -1669,7 +1669,7 @@ Set this value to -1 to invert for all steppers or specify which by mask. /*! @name $3 - Setting_DirInvertMask \brief \ref axismask controling the polarity of the stepper direction signals. The default is positive voltage for motions in negative direction. -Set this value to -1 to invert for all steppers or specify which by mask.*/ +Set this value to -1 or AXES_BITMASK to invert for all steppers or specify which by mask.*/ ///@{ #if !defined DEFAULT_DIR_SIGNALS_INVERT_MASK || defined __DOXYGEN__ #define DEFAULT_DIR_SIGNALS_INVERT_MASK 0 @@ -1678,6 +1678,8 @@ Set this value to -1 to invert for all steppers or specify which by mask.*/ /*! @name $4 - Setting_InvertStepperEnable \brief \ref axismask for inverting the polarity of the stepper enable signal(s). + +Set this value to -1 or AXES_BITMASK to invert for all steppers or specify which by mask.
__NOTE:__ If \ref COMPATIBILITY_LEVEL > 2 this setting reverts to the legacy Grbl behaviour where 0 inverts the enable signals for all drivers and 1 does not. @@ -1687,9 +1689,7 @@ Set this value to -1 to invert for all steppers or specify which by mask.*/ */ ///@{ #if !defined DEFAULT_ENABLE_SIGNALS_INVERT_MASK || defined __DOXYGEN__ -#define DEFAULT_ENABLE_SIGNALS_INVERT_MASK (X_AXIS_BIT|Y_AXIS_BIT|Z_AXIS_BIT) // Default disabled. Uncomment to enable. -#else -//#define DEFAULT_ENABLE_SIGNALS_INVERT_MASK 1 +#define DEFAULT_ENABLE_SIGNALS_INVERT_MASK AXES_BITMASK #endif ///@} diff --git a/crossbar.c b/crossbar.c index efd535b..83102bd 100644 --- a/crossbar.c +++ b/crossbar.c @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2023 Terje Io + Copyright (c) 2023-2024 Terje Io Grbl is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -140,3 +140,12 @@ const char *xbar_fn_to_pinname (pin_function_t fn) return name ? name : "N/A"; } + +control_signals_t xbar_fn_to_signals_mask (pin_function_t fn) +{ + control_signals_t signals; + + signals.mask = fn > Input_Probe ? 0 : 1 << (uint32_t)fn; + + return signals; +} diff --git a/crossbar.h b/crossbar.h index 66899a5..f4d1fb9 100644 --- a/crossbar.h +++ b/crossbar.h @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2021-2023 Terje Io + Copyright (c) 2021-2024 Terje Io Grbl is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,17 +25,23 @@ #include "nuts_bolts.h" typedef enum { - Input_Probe = 0, - Input_Reset, +// NOTE: the sequence of the following enums MUST match the control_signals_t layout + Input_Reset = 0, Input_FeedHold, Input_CycleStart, Input_SafetyDoor, - Input_LimitsOverride, - Input_EStop, Input_BlockDelete, - Input_SingleBlock, Input_StopDisable, + Input_EStop, Input_ProbeDisconnect, + Input_MotorFault, + Input_MotorWarning, + Input_LimitsOverride, + Input_SingleBlock, + Input_Unassigned, + Input_ProbeOvertravel, + Input_Probe, +// end control_signals_t sequence Input_MPGSelect, Input_ModeSelect = Input_MPGSelect, // Deprecated Input_LimitX, @@ -93,8 +99,6 @@ typedef enum { Input_Analog_Aux5, Input_Analog_Aux6, Input_Analog_Aux7, - Input_MotorWarning, - Input_MotorFault, Outputs, Output_StepX = Outputs, Output_StepX_2, @@ -189,17 +193,20 @@ typedef struct { } pin_name_t; PROGMEM static const pin_name_t pin_names[] = { - { .function = Input_Probe, .name = "Probe" }, { .function = Input_Reset, .name = "Reset" }, { .function = Input_FeedHold, .name = "Feed hold" }, { .function = Input_CycleStart, .name = "Cycle start" }, { .function = Input_SafetyDoor, .name = "Safety door" }, - { .function = Input_LimitsOverride, .name = "Limits override" }, - { .function = Input_EStop, .name = "Emergency stop" }, { .function = Input_BlockDelete, .name = "Block delete" }, - { .function = Input_SingleBlock, .name = "Single block" }, { .function = Input_StopDisable, .name = "Stop disable" }, + { .function = Input_EStop, .name = "Emergency stop" }, { .function = Input_ProbeDisconnect, .name = "Probe disconnect" }, + { .function = Input_MotorFault, .name = "Motor fault" }, + { .function = Input_MotorWarning, .name = "Motor warning" }, + { .function = Input_LimitsOverride, .name = "Limits override" }, + { .function = Input_SingleBlock, .name = "Single block" }, + { .function = Input_ProbeOvertravel, .name = "Probe overtravel" }, + { .function = Input_Probe, .name = "Probe" }, { .function = Input_MPGSelect, .name = "MPG mode select" }, { .function = Input_LimitX, .name = "X limit min" }, { .function = Input_LimitX_2, .name = "X limit min 2" }, @@ -225,8 +232,6 @@ PROGMEM static const pin_name_t pin_names[] = { { .function = Input_QEI_Index, .name = "QEI index" }, { .function = Input_SpindleIndex, .name = "Spindle index" }, { .function = Input_SpindlePulse, .name = "Spindle pulse" }, - { .function = Input_MotorWarning, .name = "Motor warning" }, - { .function = Input_MotorFault, .name = "Motor fault" }, { .function = Input_Aux0, .name = "Aux input 0" }, { .function = Input_Aux1, .name = "Aux input 1" }, { .function = Input_Aux2, .name = "Aux input 2" }, @@ -470,6 +475,27 @@ typedef void (*xbar_set_value_ptr)(struct xbar *pin, float value); typedef void (*xbar_event_ptr)(bool on); typedef bool (*xbar_config_ptr)(struct xbar *pin, void *cfg_data); +typedef enum { + AuxCtrl_SafetyDoor = 0, + AuxCtrl_MotorFault, + AuxCtrl_MotorWarning, + AuxCtrl_ProbeDisconnect, + AuxCtrl_StopDisable, + AuxCtrl_BlockDelete, + AuxCtrl_SingleBlock, + AuxCtrl_LimitsOverride, + AuxCtrl_NumEntries, +} aux_ctrl_signals_t; + +typedef struct { + bool enabled; + bool debouncing; + uint8_t port; + pin_irq_mode_t irq_mode; + control_signals_t cap; + pin_function_t function; +} aux_ctrl_t; + typedef struct xbar { pin_function_t function; pin_group_t group; @@ -504,5 +530,6 @@ limit_signals_t xbar_get_homing_source (void); limit_signals_t xbar_get_homing_source_from_cycle (axes_signals_t homing_cycle); axes_signals_t xbar_fn_to_axismask (pin_function_t id); const char *xbar_fn_to_pinname (pin_function_t id); +control_signals_t xbar_fn_to_signals_mask (pin_function_t id); #endif diff --git a/driver_opts.h b/driver_opts.h index ec8a820..95df02a 100644 --- a/driver_opts.h +++ b/driver_opts.h @@ -438,7 +438,7 @@ #define WEBUI_INFLASH 0 #endif -#if WEBUI_ENABLE && !defined(ESP_PLATFORM) +#if WEBUI_ENABLE #if !WIFI_ENABLE #ifdef ETHERNET_ENABLE diff --git a/grbl.h b/grbl.h index ced1557..08673bf 100644 --- a/grbl.h +++ b/grbl.h @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2017-2023 Terje Io + Copyright (c) 2017-2024 Terje Io Copyright (c) 2015-2016 Sungeun K. Jeon for Gnea Research LLC Grbl is free software: you can redistribute it and/or modify @@ -42,7 +42,7 @@ #else #define GRBL_VERSION "1.1f" #endif -#define GRBL_BUILD 20231229 +#define GRBL_BUILD 20240109 #define GRBL_URL "https://github.com/grblHAL" diff --git a/grbllib.c b/grbllib.c index 97dc70c..8308525 100644 --- a/grbllib.c +++ b/grbllib.c @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2017-2023 Terje Io + Copyright (c) 2017-2024 Terje Io Copyright (c) 2011-2015 Sungeun K. Jeon Copyright (c) 2009-2011 Simen Svale Skogsrud @@ -334,6 +334,7 @@ int grbl_enter (void) plan_reset(); // Clear block buffer and planner variables st_reset(); // Clear stepper subsystem variables. limits_set_homing_axes(); // Set axes to be homed from settings. + system_init_switches(); // Set switches from inputs. // Sync cleared gcode and planner positions to current system position. sync_position(); diff --git a/hal.h b/hal.h index 57e45ec..5b14297 100644 --- a/hal.h +++ b/hal.h @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2016-2023 Terje Io + Copyright (c) 2016-2024 Terje Io Grbl is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -506,6 +506,32 @@ typedef struct { rtc_set_datetime_ptr set_datetime; //!< Optional handler setting the current datetime. } rtc_ptrs_t; +/******************* + * RGB (LED) API * + *******************/ + +typedef union { + uint32_t value; + struct { + uint8_t B; //!< Blue + uint8_t G; //!< Green + uint8_t R; //!< Red + uint8_t W; //!< White + }; +} rgb_color_t; + +/*! \brief Pointer to function for setting RGB (LED) output. +\param color a \a rgb_color_t union. +*/ +typedef void (*rgb_set_color)(uint8_t device, rgb_color_t color); + +typedef struct { + rgb_set_color out; //!< Optional handler for setting device (LED) color. + uint8_t num_devices; //!< Number of devices (LEDS) available. +} rgb_ptr_t; + +/**/ + /*! \brief Pointer to function for performing a pallet shuttle. */ typedef void (*pallet_shuttle_ptr)(void); @@ -595,6 +621,7 @@ typedef struct { tool_ptrs_t tool; //!< Optional handlers for tool changes. rtc_ptrs_t rtc; //!< Optional handlers for real time clock (RTC). io_port_t port; //!< Optional handlers for axuillary I/O (adds support for M62-M66). + rgb_ptr_t rgb; //!< Optional handler for RGB output to LEDs (neopixels) or lamps. periph_port_t periph_port; //!< Optional handlers for peripheral pin registration. driver_reset_ptr driver_reset; //!< Optional handler, called on soft resets. Set to a dummy handler by the core at startup. nvs_io_t nvs; //!< Optional handlers for storing/retrieving settings and data to/from non-volatile storage (NVS). diff --git a/ioports.c b/ioports.c index bb9bdc3..3dc912c 100644 --- a/ioports.c +++ b/ioports.c @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2021-2023 Terje Io + Copyright (c) 2021-2024 Terje Io Grbl is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -153,7 +153,7 @@ bool ioports_enumerate (io_port_type_t type, io_port_direction_t dir, pin_mode_t portinfo = hal.port.get_pin_info(type, dir, --n_ports); if(claimable && portinfo->mode.claimed) continue; - if((portinfo->mode.mask & filter.mask) == filter.mask && (ok = callback(portinfo, n_ports, data))) + if((portinfo->cap.mask & filter.mask) == filter.mask && (ok = callback(portinfo, n_ports, data))) break; } while(n_ports); @@ -257,7 +257,7 @@ bool ioports_add (io_ports_data_t *ports, io_port_type_t type, uint8_t n_in, uin return n_ports > 0; } -uint8_t ioports_map_reverse (io_ports_detail_t *type, uint8_t port) +ISR_CODE uint8_t ISR_FUNC(ioports_map_reverse)(io_ports_detail_t *type, uint8_t port) { if(type->map) { uint_fast8_t idx = type->n_ports; @@ -360,25 +360,55 @@ static bool is_setting_available (const setting_detail_t *setting) return available; } -static status_code_t aux_set_invert_out (setting_id_t id, uint_fast16_t value) +static status_code_t aux_set_value (setting_id_t id, uint_fast16_t value) { ioport_bus_t invert; - invert.mask = (uint8_t)value & digital.outx.mask; - if(settings.ioport.invert_out.mask != invert.mask) { + switch(id) { - settings.ioport.invert_out.mask = invert.mask; + case Settings_IoPort_InvertIn: + settings.ioport.invert_in.mask = value; + if(on_setting_changed) + on_setting_changed(id); + break; - if(on_setting_changed) - on_setting_changed(id); + case Settings_IoPort_InvertOut: + invert.mask = (uint8_t)value & digital.outx.mask; + if(settings.ioport.invert_out.mask != invert.mask) { + + settings.ioport.invert_out.mask = invert.mask; + + if(on_setting_changed) + on_setting_changed(id); + } + break; + + default: + break; } return Status_OK; } -static uint32_t aux_get_invert_out (setting_id_t setting) +static uint32_t aux_get_value (setting_id_t id) { - return settings.ioport.invert_out.mask; + uint32_t value = 0; + + switch(id) { + + case Settings_IoPort_InvertIn: + value = settings.ioport.invert_in.mask; + break; + + case Settings_IoPort_InvertOut: + value = settings.ioport.invert_out.mask; + break; + + default: + break; + } + + return value; } static const setting_group_detail_t ioport_groups[] = { @@ -386,9 +416,9 @@ static const setting_group_detail_t ioport_groups[] = { }; static const setting_detail_t ioport_settings[] = { - { Settings_IoPort_InvertIn, Group_AuxPorts, "Invert I/O Port inputs", NULL, Format_Bitfield, digital.in.port_names, NULL, NULL, Setting_NonCore, &settings.ioport.invert_in.mask, NULL, is_setting_available }, + { Settings_IoPort_InvertIn, Group_AuxPorts, "Invert I/O Port inputs", NULL, Format_Bitfield, digital.in.port_names, NULL, NULL, Setting_NonCoreFn, aux_set_value, aux_get_value, is_setting_available }, // { Settings_IoPort_Pullup_Disable, Group_AuxPorts, "I/O Port inputs pullup disable", NULL, Format_Bitfield, "Port 0,Port 1,Port 2,Port 3,Port 4,Port 5,Port 6,Port 7", NULL, NULL }, - { Settings_IoPort_InvertOut, Group_AuxPorts, "Invert I/O Port outputs", NULL, Format_Bitfield, digital.out.port_names, NULL, NULL, Setting_NonCoreFn, aux_set_invert_out, aux_get_invert_out, is_setting_available }, + { Settings_IoPort_InvertOut, Group_AuxPorts, "Invert I/O Port outputs", NULL, Format_Bitfield, digital.out.port_names, NULL, NULL, Setting_NonCoreFn, aux_set_value, aux_get_value, is_setting_available }, // { Settings_IoPort_OD_Enable, Group_AuxPorts, "I/O Port outputs as open drain", NULL, Format_Bitfield, "Port 0,Port 1,Port 2,Port 3,Port 4,Port 5,Port 6,Port 7", NULL, NULL } }; @@ -422,6 +452,12 @@ static setting_details_t setting_details = { .save = settings_write_global }; +void ioport_setting_changed (setting_id_t id) +{ + if(on_setting_changed) + on_setting_changed(id); +} + void ioports_add_settings (driver_settings_load_ptr settings_loaded, setting_changed_ptr setting_changed) { if(settings_loaded) diff --git a/ioports.h b/ioports.h index 0295db4..fd1bfa2 100644 --- a/ioports.h +++ b/ioports.h @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2021-2023 Terje Io + Copyright (c) 2021-2024 Terje Io Grbl is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -159,6 +159,7 @@ typedef struct { bool ioports_add (io_ports_data_t *ports, io_port_type_t type, uint8_t n_in, uint8_t n_out); void ioports_add_settings (driver_settings_load_ptr settings_loaded, setting_changed_ptr setting_changed); +void ioport_setting_changed (setting_id_t id); #define iports_get_pnum(type, port) type.get_pnum(&type, port) #define ioports_map(type, port) ( type.map ? type.map[port] : port ) uint8_t ioports_map_reverse (io_ports_detail_t *type, uint8_t port); diff --git a/motion_control.c b/motion_control.c index 7db630b..6c2683a 100644 --- a/motion_control.c +++ b/motion_control.c @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2017-2023 Terje Io + Copyright (c) 2017-2024 Terje Io Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC Copyright (c) 2009-2011 Simen Svale Skogsrud @@ -1139,9 +1139,11 @@ ISR_CODE void ISR_FUNC(mc_reset)(void) st_go_idle(); // Force kill steppers. Position has likely been lost. } - if(hal.control.get_state().e_stop) + control_signals_t signals = hal.control.get_state(); + + if(signals.e_stop) system_set_exec_alarm(Alarm_EStop); - else if(hal.control.get_state().motor_fault) + else if(signals.motor_fault) system_set_exec_alarm(Alarm_MotorFault); if(grbl.on_reset) diff --git a/pin_bits_masks.h b/pin_bits_masks.h index 7b6c7b9..0395427 100644 --- a/pin_bits_masks.h +++ b/pin_bits_masks.h @@ -5,7 +5,7 @@ Part of grblHAL - Copyright (c) 2021-2023 Terje Io + Copyright (c) 2021-2024 Terje Io Grbl is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -173,45 +173,30 @@ #endif #if SAFETY_DOOR_ENABLE || MOTOR_FAULT_ENABLE || MOTOR_WARNING_ENABLE || PROBE_DISCONNECT_ENABLE || \ - STOP_DISABLE_ENABLE || BLOCK_DELETE_ENABLE || SINGLE_BLOCK_PIN || LIMITS_OVERRIDE_ENABLE || defined __DOXYGEN__ + STOP_DISABLE_ENABLE || BLOCK_DELETE_ENABLE || SINGLE_BLOCK_ENABLE || LIMITS_OVERRIDE_ENABLE || defined __DOXYGEN__ #define AUX_CONTROLS_ENABLED 1 -#if PROBE_DISCONNECT_ENABLE || STOP_DISABLE_ENABLE || BLOCK_DELETE_ENABLE || SINGLE_BLOCK_PIN || LIMITS_OVERRIDE_ENABLE +#if PROBE_DISCONNECT_ENABLE || STOP_DISABLE_ENABLE || BLOCK_DELETE_ENABLE || SINGLE_BLOCK_ENABLE || LIMITS_OVERRIDE_ENABLE #define AUX_CONTROLS_SCAN 3 // start index for scanned inputs #else #define AUX_CONTROLS_SCAN 0 #endif -typedef enum { - AuxCtrl_SafetyDoor = 0, - AuxCtrl_MotorFault, - AuxCtrl_MotorWarning, - AuxCtrl_ProbeDisconnect, - AuxCtrl_StopDisable, - AuxCtrl_BlockDelete, - AuxCtrl_SingleBlock, - AuxCtrl_LimitsOverride, - AuxCtrl_NumEntries, -} aux_ctrl_signals_t; - -typedef struct { - bool enabled; - bool debouncing; - uint8_t port; - pin_irq_mode_t irq_mode; - control_signals_t cap; - pin_function_t function; -} aux_ctrl_t; +#if SAFETY_DOOR_ENABLE || MOTOR_FAULT_ENABLE || MOTOR_WARNING_ENABLE +#define AUX_CONTROLS_XMAP 1 +#else +#define AUX_CONTROLS_XMAP 0 +#endif static aux_ctrl_t aux_ctrl[] = { { .enabled = SAFETY_DOOR_ENABLE, .port = 0xFF, .irq_mode = (pin_irq_mode_t)(IRQ_Mode_Rising|IRQ_Mode_Falling), .cap = { .safety_door_ajar = On }, .function = Input_SafetyDoor }, { .enabled = MOTOR_FAULT_ENABLE, .port = 0xFF, .irq_mode = (pin_irq_mode_t)(IRQ_Mode_Rising|IRQ_Mode_Falling), .cap = { .motor_fault = On }, .function = Input_MotorFault }, { .enabled = MOTOR_WARNING_ENABLE, .port = 0xFF, .irq_mode = (pin_irq_mode_t)(IRQ_Mode_Rising|IRQ_Mode_Falling), .cap = { .motor_warning = On }, .function = Input_MotorWarning }, { .enabled = PROBE_DISCONNECT_ENABLE, .port = 0xFF, .irq_mode = (pin_irq_mode_t)(IRQ_Mode_Rising|IRQ_Mode_Falling), .cap = { .motor_fault = On }, .function = Input_ProbeDisconnect }, - { .enabled = STOP_DISABLE_ENABLE, .port = 0xFF, .irq_mode = IRQ_Mode_None, .cap = { .stop_disable = On }, .function = Input_StopDisable }, - { .enabled = BLOCK_DELETE_ENABLE, .port = 0xFF, .irq_mode = IRQ_Mode_None, .cap = { .block_delete = On }, .function = Input_BlockDelete }, - { .enabled = SINGLE_BLOCK_ENABLE, .port = 0xFF, .irq_mode = IRQ_Mode_None, .cap = { .single_block = On }, .function = Input_SingleBlock }, + { .enabled = STOP_DISABLE_ENABLE, .port = 0xFF, .irq_mode = IRQ_Mode_Change, .cap = { .stop_disable = On }, .function = Input_StopDisable }, + { .enabled = BLOCK_DELETE_ENABLE, .port = 0xFF, .irq_mode = IRQ_Mode_Change, .cap = { .block_delete = On }, .function = Input_BlockDelete }, + { .enabled = SINGLE_BLOCK_ENABLE, .port = 0xFF, .irq_mode = IRQ_Mode_Change, .cap = { .single_block = On }, .function = Input_SingleBlock }, { .enabled = LIMITS_OVERRIDE_ENABLE, .port = 0xFF, .irq_mode = IRQ_Mode_None, .cap = { .limits_override = On }, .function = Input_LimitsOverride } }; diff --git a/report.c b/report.c index 6c3d225..a0af00a 100644 --- a/report.c +++ b/report.c @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2017-2023 Terje Io + Copyright (c) 2017-2024 Terje Io Copyright (c) 2012-2016 Sungeun K. Jeon for Gnea Research LLC Grbl is free software: you can redistribute it and/or modify @@ -175,15 +175,12 @@ inline static char *axis_signals_tostring (char *buf, axes_signals_t signals) // Convert control signals bits to string representation. // NOTE: returns pointer to null terminator! -inline static char *control_signals_tostring (char *buf, control_signals_t signals, bool all) +inline static char *control_signals_tostring (char *buf, control_signals_t signals) { - static const char signals_map[] = "RHSDLTE FM P "; + static const char signals_map[] = "RHSDLTEOFM Q P "; char *map = (char *)signals_map; - if(!hal.signals_cap.stop_disable) - signals.stop_disable = sys.flags.optional_stop_disable; - if(!signals.deasserted) while(signals.mask) { @@ -199,11 +196,6 @@ inline static char *control_signals_tostring (char *buf, control_signals_t signa *buf++ = *map; break; - case 'L': - if(all || sys.flags.block_delete_enabled) - *buf++ = *map; - break; - default: *buf++ = *map; break; @@ -976,13 +968,13 @@ void report_build_info (char *line, bool extended) grbl.on_report_options(true); hal.stream.write("]" ASCII_EOL); + hal.stream.write("[FIRMWARE:grblHAL]" ASCII_EOL); + hal.stream.write("[SIGNALS:"); - control_signals_tostring(buf, hal.signals_cap, true); + control_signals_tostring(buf, hal.signals_cap); hal.stream.write(buf); hal.stream.write("]" ASCII_EOL); - hal.stream.write("[FIRMWARE:grblHAL]" ASCII_EOL); - if(!(nvs->type == NVS_None || nvs->type == NVS_Emulated)) { hal.stream.write("[NVS STORAGE:"); *buf = '\0'; @@ -1216,28 +1208,38 @@ void report_realtime_status (void) if(settings.status_report.pin_state) { + static const system_flags_t sys_switches = { + .block_delete_enabled = On, + .optional_stop_disable = On, + .single_block = On + }; + axes_signals_t lim_pin_state = limit_signals_merge(hal.limits.get_state()); control_signals_t ctrl_pin_state = hal.control.get_state(); + ctrl_pin_state.probe_triggered = probe_state.triggered; + ctrl_pin_state.probe_disconnected = !probe_state.connected; ctrl_pin_state.cycle_start |= sys.report.cycle_start; + if(sys.flags.value & sys_switches.value) { + if(!hal.signals_cap.stop_disable) + ctrl_pin_state.stop_disable = sys.flags.optional_stop_disable; + if(!hal.signals_cap.block_delete) + ctrl_pin_state.block_delete = sys.flags.block_delete_enabled; + if(!hal.signals_cap.single_block) + ctrl_pin_state.single_block = sys.flags.single_block; + } - if (lim_pin_state.value | ctrl_pin_state.value | probe_state.triggered | !probe_state.connected | sys.flags.block_delete_enabled) { + if(lim_pin_state.value | ctrl_pin_state.value) { char *append = &buf[4]; strcpy(buf, "|Pn:"); - if(probe_state.triggered) - *append++ = 'P'; - - if(!probe_state.connected) - *append++ = 'O'; - if(lim_pin_state.value && !ctrl_pin_state.limits_override) append = axis_signals_tostring(append, lim_pin_state); if(ctrl_pin_state.value) - append = control_signals_tostring(append, ctrl_pin_state, false); + append = control_signals_tostring(append, ctrl_pin_state); *append = '\0'; hal.stream.write_all(buf); @@ -2079,7 +2081,7 @@ status_code_t report_last_signals_event (sys_state_t state, char *args) strcpy(buf, "[LASTEVENTS:"); - append = control_signals_tostring(append, sys.last_event.control, false); + append = control_signals_tostring(append, sys.last_event.control); *append++ = ','; append = add_limits(append, sys.last_event.limits); diff --git a/settings.c b/settings.c index dcda797..52321f1 100644 --- a/settings.c +++ b/settings.c @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2017-2023 Terje Io + Copyright (c) 2017-2024 Terje Io Copyright (c) 2011-2015 Sungeun K. Jeon Copyright (c) 2009-2011 Simen Svale Skogsrud @@ -423,7 +423,7 @@ static status_code_t set_ngc_debug_out (setting_id_t id, uint_fast16_t int_value #endif static bool machine_mode_changed = false; -static char control_signals[] = "Reset,Feed hold,Cycle start,Safety door,Block delete,Optional stop,EStop,Probe connected,Motor fault"; +static char control_signals[] = "Reset,Feed hold,Cycle start,Safety door,Block delete,Optional stop,EStop,Probe connected,Motor fault,Motor warning,Limits override,Single step blocks"; static char spindle_signals[] = "Spindle enable,Spindle direction,PWM"; static char coolant_signals[] = "Flood,Mist"; static char ganged_axes[] = "X-Axis,Y-Axis,Z-Axis"; @@ -972,6 +972,9 @@ static status_code_t set_control_invert (setting_id_t id, uint_fast16_t int_valu { settings.control_invert.mask = (int_value & hal.signals_cap.mask) | limits_override.mask; + ioport_setting_changed(id); + system_init_switches(); + return Status_OK; } diff --git a/spindle_control.c b/spindle_control.c index 3a57429..7a9b3cd 100644 --- a/spindle_control.c +++ b/spindle_control.c @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2017-2023 Terje Io + Copyright (c) 2017-2024 Terje Io Copyright (c) 2012-2015 Sungeun K. Jeon Copyright (c) 2009-2011 Simen Svale Skogsrud @@ -281,6 +281,8 @@ void spindle_update_caps (spindle_ptrs_t *spindle, spindle_pwm_t *pwm_caps) if(sys_spindle[idx].enabled && spindle->id == sys_spindle[idx].hal.id) { sys_spindle[idx].hal.type = spindle->type; sys_spindle[idx].hal.cap.laser = spindle->cap.laser; + sys_spindle[idx].hal.rpm_min = spindle->rpm_min; + sys_spindle[idx].hal.rpm_max = spindle->rpm_max; sys_spindle[idx].hal.pwm_off_value = spindle->pwm_off_value; break; } diff --git a/stream.c b/stream.c index 0105f94..82b43e8 100644 --- a/stream.c +++ b/stream.c @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2021-2023 Terje Io + Copyright (c) 2021-2024 Terje Io Grbl is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -433,6 +433,9 @@ bool stream_mpg_register (const io_stream_t *stream, bool rx_only, stream_write_ mpg.stream = stream; mpg.is_up = is_connected; + if(hal.periph_port.set_pin_description) + hal.periph_port.set_pin_description(Input_RX, (pin_group_t)(PinGroup_UART + stream->instance), "MPG"); + return true; } diff --git a/system.c b/system.c index f5df9d8..29380bd 100644 --- a/system.c +++ b/system.c @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2017-2023 Terje Io + Copyright (c) 2017-2024 Terje Io Copyright (c) 2014-2016 Sungeun K. Jeon for Gnea mResearch LLC Grbl is free software: you can redistribute it and/or modify @@ -42,6 +42,16 @@ inline static float hypot_f (float x, float y) { return sqrtf(x * x + y * y); } + +void system_init_switches (void) +{ + control_signals_t signals = hal.control.get_state(); + + sys.flags.block_delete_enabled = signals.block_delete; + sys.flags.single_block = signals.single_block; + sys.flags.optional_stop_disable = signals.stop_disable; +} + /*! \brief Pin change interrupt handler for pin-out commands, i.e. cycle start, feed hold, reset etc. Mainly sets the realtime command execute variable to have the main program execute these when its ready. This works exactly like the character-based realtime commands when picked off @@ -50,10 +60,17 @@ directly from the incoming data stream. */ ISR_CODE void ISR_FUNC(control_interrupt_handler)(control_signals_t signals) { - if(signals.deasserted) - return; // for now... + static control_signals_t onoff_signals = { + .block_delete = On, + .single_block = On, + .stop_disable = On, + .deasserted = On + }; - if (signals.value) { + if(signals.deasserted) + signals.value &= onoff_signals.mask; + + if(signals.value) { sys.last_event.control.value = signals.value; @@ -96,6 +113,15 @@ ISR_CODE void ISR_FUNC(control_interrupt_handler)(control_signals_t signals) system_set_exec_state_flag(EXEC_CYCLE_START); sys.report.cycle_start = settings.status_report.pin_state; } + + if(signals.block_delete) + sys.flags.block_delete_enabled = !signals.deasserted; + + if(signals.single_block) + sys.flags.single_block = !signals.deasserted; + + if(signals.stop_disable) + sys.flags.optional_stop_disable = !signals.deasserted; } } } @@ -281,26 +307,32 @@ static status_code_t output_parser_state (sys_state_t state, char *args) static status_code_t toggle_single_block (sys_state_t state, char *args) { - sys.flags.single_block = !sys.flags.single_block; - grbl.report.feedback_message(sys.flags.single_block ? Message_Enabled : Message_Disabled); + if(!hal.signals_cap.single_block) { + sys.flags.single_block = !sys.flags.single_block; + grbl.report.feedback_message(sys.flags.single_block ? Message_Enabled : Message_Disabled); + } - return Status_OK; + return hal.signals_cap.single_block ? Status_InvalidStatement : Status_OK; } static status_code_t toggle_block_delete (sys_state_t state, char *args) { - sys.flags.block_delete_enabled = !sys.flags.block_delete_enabled; - grbl.report.feedback_message(sys.flags.block_delete_enabled ? Message_Enabled : Message_Disabled); + if(!hal.signals_cap.block_delete) { + sys.flags.block_delete_enabled = !sys.flags.block_delete_enabled; + grbl.report.feedback_message(sys.flags.block_delete_enabled ? Message_Enabled : Message_Disabled); + } - return Status_OK; + return hal.signals_cap.block_delete ? Status_InvalidStatement : Status_OK; } static status_code_t toggle_optional_stop (sys_state_t state, char *args) { - sys.flags.optional_stop_disable = !sys.flags.optional_stop_disable; - grbl.report.feedback_message(sys.flags.block_delete_enabled ? Message_Enabled : Message_Disabled); + if(!hal.signals_cap.stop_disable) { + sys.flags.optional_stop_disable = !sys.flags.optional_stop_disable; + grbl.report.feedback_message(sys.flags.block_delete_enabled ? Message_Enabled : Message_Disabled); + } - return Status_OK; + return hal.signals_cap.stop_disable ? Status_InvalidStatement : Status_OK; } static status_code_t check_mode (sys_state_t state, char *args) @@ -688,23 +720,117 @@ static status_code_t output_memmap (sys_state_t state, char *args) } #endif +const char *help_rst (const char *cmd) +{ +#if ENABLE_RESTORE_NVS_WIPE_ALL + hal.stream.write("$RST=* - restore/reset all settings." ASCII_EOL); +#endif +#if ENABLE_RESTORE_NVS_DEFAULT_SETTINGS + hal.stream.write("$RST=$ - restore default settings." ASCII_EOL); +#endif +#if ENABLE_RESTORE_NVS_DRIVER_PARAMETERS + if(settings_get_details()->next) + hal.stream.write("$RST=& - restore driver and plugin default settings." ASCII_EOL); +#endif +#if ENABLE_RESTORE_NVS_CLEAR_PARAMETERS + if(grbl.tool_table.n_tools) + hal.stream.write("$RST=# - reset offsets and tool data." ASCII_EOL); + else + hal.stream.write("$RST=# - reset offsets." ASCII_EOL); +#endif + + return NULL; +} + +const char *help_rtc (const char *cmd) +{ + if(hal.rtc.get_datetime) { + hal.stream.write("$RTC - output current time." ASCII_EOL); + hal.stream.write("$RTC= - set current time." ASCII_EOL); + } + + return NULL; +} + +const char *help_spindle (const char *cmd) +{ + spindle_ptrs_t *spindle = gc_spindle_get(); + + if(cmd[1] == 'R' && spindle->reset_data) + hal.stream.write("$SR - reset spindle encoder data." ASCII_EOL); + + if(cmd[1] == 'D' && spindle->get_data) + hal.stream.write("$SD - output spindle encoder data." ASCII_EOL); + + return NULL; +} + +const char *help_pins (const char *cmd) +{ + return hal.enumerate_pins ? "enumerate pin bindings" : NULL; +} + +const char *help_switches (const char *cmd) +{ + const char *help = NULL; + + switch(*cmd) { + + case 'B': + if(!hal.signals_cap.block_delete) + help = "toggle block delete switch"; + break; + + case 'O': + if(!hal.signals_cap.stop_disable) + help = "toggle optional stop switch (M1)"; + break; + + case 'S': + if(!hal.signals_cap.single_block) + help = "toggle single stepping switch"; + break; + } + + return help; +} + +const char *help_homing (const char *cmd) +{ + if(settings.homing.flags.enabled) + hal.stream.write("$H - home configured axes." ASCII_EOL); + + if(settings.homing.flags.single_axis_commands) + hal.stream.write("$H - home single axis." ASCII_EOL); + + return NULL; +} + /*! \brief Command dispatch table */ PROGMEM static const sys_command_t sys_commands[] = { - { "G", output_parser_state, { .noargs = On, .allow_blocking = On } }, - { "J", jog }, - { "#", output_ngc_parameters, { .allow_blocking = On } }, - { "$", output_settings, { .allow_blocking = On } }, - { "+", output_all_settings, { .allow_blocking = On } }, + { "G", output_parser_state, { .noargs = On, .allow_blocking = On }, { .str = "output parser state" } }, + { "J", jog, {}, { .str = "$J= - jog machine" } }, + { "#", output_ngc_parameters, { .allow_blocking = On }, { + .str = "output offsets, tool table, probing and home position" + ASCII_EOL "$#= - output value for parameter " + } }, + { "$", output_settings, { .allow_blocking = On }, { + .str = "$ - output setting value" + ASCII_EOL "$= - assign to settings " + ASCII_EOL "$$ - output all setting values" + ASCII_EOL "$$= - output setting details for setting " + } }, + { "+", output_all_settings, { .allow_blocking = On }, { .str = "output all setting values" } }, #ifndef NO_SETTINGS_DESCRIPTIONS - { "SED", output_setting_description, { .allow_blocking = On } }, + { "SED", output_setting_description, { .allow_blocking = On }, { .str = "$SED= - output settings description for setting " } }, #endif - { "B", toggle_block_delete, { .noargs = On } }, - { "S", toggle_single_block, { .noargs = On } }, - { "O", toggle_optional_stop, { .noargs = On } }, - { "C", check_mode, { .noargs = On } }, - { "X", disable_lock }, - { "H", home }, + { "B", toggle_block_delete, { .noargs = On, .help_fn = On }, { .fn = help_switches } }, + { "S", toggle_single_block, { .noargs = On, .help_fn = On }, { .fn = help_switches } }, + { "O", toggle_optional_stop, { .noargs = On, .help_fn = On }, { .fn = help_switches } }, + { "C", check_mode, { .noargs = On }, { .str = "enable check mode, to exit" } }, + { "X", disable_lock, {}, { .str = "unlock machine" } }, + { "H", home, { .help_fn = On }, { .fn = help_homing } }, { "HX", home_x }, { "HY", home_y }, { "HZ", home_z }, @@ -735,110 +861,77 @@ PROGMEM static const sys_command_t sys_commands[] = { #ifdef V_AXIS { "HV", home_v }, #endif - { "HSS", report_current_home_signal_state, { .noargs = On, .allow_blocking = On } }, - { "HELP", output_help, { .allow_blocking = On } }, - { "SPINDLES", enumerate_spindles, { .noargs = On, .allow_blocking = On } }, - { "SPINDLESH", enumerate_spindles_mr, { .noargs = On, .allow_blocking = On } }, - { "SLP", enter_sleep, { .noargs = On } }, - { "TLR", set_tool_reference, { .noargs = On } }, - { "TPW", tool_probe_workpiece, { .noargs = On } }, - { "I", build_info, { .allow_blocking = On } }, - { "I+", output_all_build_info, { .noargs = On, .allow_blocking = On } }, - { "RST", settings_reset, { .allow_blocking = On } }, - { "N", output_startup_lines, { .noargs = On, .allow_blocking = On } }, - { "N0", set_startup_line0 }, - { "N1", set_startup_line1 }, - { "EA", enumerate_alarms, { .noargs = On, .allow_blocking = On } }, - { "EAG", enumerate_alarms_grblformatted, { .noargs = On, .allow_blocking = On } }, - { "EE", enumerate_errors, { .noargs = On, .allow_blocking = On } }, - { "EEG", enumerate_errors_grblformatted, { .noargs = On, .allow_blocking = On } }, - { "EG", enumerate_groups, { .noargs = On, .allow_blocking = On } }, - { "ES", enumerate_settings, { .noargs = On, .allow_blocking = On } }, - { "ESG", enumerate_settings_grblformatted, { .noargs = On, .allow_blocking = On } }, - { "ESH", enumerate_settings_halformatted, { .noargs = On, .allow_blocking = On } }, - { "E*", enumerate_all, { .noargs = On, .allow_blocking = On } }, - { "PINS", enumerate_pins, { .noargs = On, .allow_blocking = On } }, - { "RST", settings_reset, { .allow_blocking = On } }, - { "LEV", report_last_signals_event, { .noargs = On, .allow_blocking = On } }, - { "LIM", report_current_limit_state, { .noargs = On, .allow_blocking = On } }, - { "SD", report_spindle_data }, - { "SR", spindle_reset_data }, - { "RTC", rtc_action, { .allow_blocking = On } }, + { "HSS", report_current_home_signal_state, { .noargs = On, .allow_blocking = On }, { .str = "report homing switches status" } }, + { "HELP", output_help, { .allow_blocking = On }, { + .str = "$HELP - output help topics" + ASCII_EOL "$HELP - output help for " + } }, + { "SPINDLES", enumerate_spindles, { .noargs = On, .allow_blocking = On }, { .str = "enumerate spindles, human readable" } }, + { "SPINDLESH", enumerate_spindles_mr, { .noargs = On, .allow_blocking = On }, { .str = "enumerate spindles, machine readable" } }, + { "SLP", enter_sleep, { .noargs = On }, { .str = "enter sleep mode" } }, + { "TLR", set_tool_reference, { .noargs = On }, { .str = "set tool offset reference" } }, + { "TPW", tool_probe_workpiece, { .noargs = On }, { .str = "probe tool plate" } }, + { "I", build_info, { .allow_blocking = On }, { + .str = "output system information" +#if !DISABLE_BUILD_INFO_WRITE_COMMAND + ASCII_EOL "$I= - set build info string" +#endif + } }, + { "I+", output_all_build_info, { .noargs = On, .allow_blocking = On }, { .str = "output extended system information" } }, + { "RST", settings_reset, { .allow_blocking = On, .help_fn = On }, { .fn = help_rst } }, + { "N", output_startup_lines, { .noargs = On, .allow_blocking = On }, { .str = "output startup lines" } }, + { "N0", set_startup_line0, {}, { .str = "N0= - set startup line 0" } }, + { "N1", set_startup_line1, {}, { .str = "N1= - set startup line 1" } }, + { "EA", enumerate_alarms, { .noargs = On, .allow_blocking = On }, { .str = "enumerate alarms" } }, + { "EAG", enumerate_alarms_grblformatted, { .noargs = On, .allow_blocking = On }, { .str = "enumerate alarms, Grbl formatted" } }, + { "EE", enumerate_errors, { .noargs = On, .allow_blocking = On }, { .str = "enumerate status codes" } }, + { "EEG", enumerate_errors_grblformatted, { .noargs = On, .allow_blocking = On }, { .str = "enumerate status codes, Grbl formatted" } }, + { "EG", enumerate_groups, { .noargs = On, .allow_blocking = On }, { .str = "enumerate setting groups" } }, + { "ES", enumerate_settings, { .noargs = On, .allow_blocking = On }, { .str = "enumerate settings" } }, + { "ESG", enumerate_settings_grblformatted, { .noargs = On, .allow_blocking = On }, { .str = "enumerate settings, Grbl formatted" } }, + { "ESH", enumerate_settings_halformatted, { .noargs = On, .allow_blocking = On }, { .str = "enumerate settings, grblHAL formatted" } }, + { "E*", enumerate_all, { .noargs = On, .allow_blocking = On }, { .str = "enumerate alarms, status codes and settings" } }, + { "PINS", enumerate_pins, { .noargs = On, .allow_blocking = On, .help_fn = On }, { .fn = help_pins } }, + { "LEV", report_last_signals_event, { .noargs = On, .allow_blocking = On }, { .str = "output last control signal events" } }, + { "LIM", report_current_limit_state, { .noargs = On, .allow_blocking = On }, { .str = "output current limit pins" } }, + { "SD", report_spindle_data, { .help_fn = On }, { .fn = help_spindle } }, + { "SR", spindle_reset_data, { .help_fn = On }, { .fn = help_spindle } }, + { "RTC", rtc_action, { .allow_blocking = On, .help_fn = On }, { .fn = help_rtc } }, #ifdef DEBUGOUT - { "Q", output_memmap, { .noargs = On } }, + { "Q", output_memmap, { .noargs = On }, { .str = "output NVS memory allocation" } }, #endif }; +void system_output_help (const sys_command_t *commands, uint32_t num_commands) +{ + const char *help; + uint_fast8_t idx; + + for(idx = 0; idx < num_commands; idx++) { + + if(commands[idx].help.str) { + + if(commands[idx].flags.help_fn) + help = commands[idx].help.fn(commands[idx].command); + else + help = commands[idx].help.str; + + if(help) { + if(*help != '$') { + hal.stream.write_char('$'); + hal.stream.write(commands[idx].command); + hal.stream.write(" - "); + } + hal.stream.write(help); + hal.stream.write("." ASCII_EOL); + } + } + } +} + void system_command_help (void) { - hal.stream.write("$I - output system information" ASCII_EOL); - hal.stream.write("$I+ - output extended system information" ASCII_EOL); -#if !DISABLE_BUILD_INFO_WRITE_COMMAND - hal.stream.write("$I= set build info string" ASCII_EOL); -#endif - hal.stream.write("$ - output setting value" ASCII_EOL); - hal.stream.write("$= - assign to settings " ASCII_EOL); - hal.stream.write("$$ - output all setting values" ASCII_EOL); - hal.stream.write("$+ - output all setting values" ASCII_EOL); - hal.stream.write("$$= - output setting details for setting " ASCII_EOL); - hal.stream.write("$# - output offsets, tool table, probing and home position" ASCII_EOL); - hal.stream.write("$#= - output value for parameter " ASCII_EOL); - hal.stream.write("$G - output parser state" ASCII_EOL); - hal.stream.write("$N - output startup lines" ASCII_EOL); - if(settings.homing.flags.enabled) - hal.stream.write("$H - home configured axes" ASCII_EOL); - if(settings.homing.flags.single_axis_commands) - hal.stream.write("$H - home single axis" ASCII_EOL); - hal.stream.write("$HSS - report homing switches status" ASCII_EOL); - hal.stream.write("$X - unlock machine" ASCII_EOL); - hal.stream.write("$SLP - enter sleep mode" ASCII_EOL); - hal.stream.write("$HELP - output help topics" ASCII_EOL); - hal.stream.write("$HELP - output help for " ASCII_EOL); - hal.stream.write("$SPINDLES - enumerate spindles, human readable" ASCII_EOL); - hal.stream.write("$SPINDLESH - enumerate spindles, machine readable" ASCII_EOL); -#if ENABLE_RESTORE_NVS_WIPE_ALL - hal.stream.write("$RST=* - restore/reset all settings" ASCII_EOL); -#endif -#if ENABLE_RESTORE_NVS_DEFAULT_SETTINGS - hal.stream.write("$RST=$ - restore default settings" ASCII_EOL); -#endif -#if ENABLE_RESTORE_NVS_DRIVER_PARAMETERS - if(settings_get_details()->next) - hal.stream.write("$RST=& - restore driver and plugin default settings" ASCII_EOL); -#endif -#if ENABLE_RESTORE_NVS_CLEAR_PARAMETERS - if(grbl.tool_table.n_tools) - hal.stream.write("$RST=# - reset offsets and tool data" ASCII_EOL); - else - hal.stream.write("$RST=# - reset offsets" ASCII_EOL); -#endif - spindle_ptrs_t *spindle = gc_spindle_get(); - if(spindle->reset_data) - hal.stream.write("$SR - reset spindle encoder data" ASCII_EOL); - if(spindle->get_data) - hal.stream.write("$SD - output spindle encoder data" ASCII_EOL); - - hal.stream.write("$TLR - set tool offset reference" ASCII_EOL); - hal.stream.write("$TPW - probe tool plate" ASCII_EOL); - hal.stream.write("$EA - enumerate alarms" ASCII_EOL); - hal.stream.write("$EAG - enumerate alarms, Grbl formatted" ASCII_EOL); - hal.stream.write("$EE - enumerate status codes" ASCII_EOL); - hal.stream.write("$EEG - enumerate status codes, Grbl formatted" ASCII_EOL); - hal.stream.write("$ES - enumerate settings" ASCII_EOL); - hal.stream.write("$ESG - enumerate settings, Grbl formatted" ASCII_EOL); - hal.stream.write("$ESH- enumerate settings, grblHAL formatted" ASCII_EOL); - hal.stream.write("$E* - enumerate alarms, status codes and settings" ASCII_EOL); - if(hal.enumerate_pins) - hal.stream.write("$PINS - enumerate pin bindings" ASCII_EOL); - hal.stream.write("$LEV - output last control signal events" ASCII_EOL); - hal.stream.write("$LIM - output current limit pins state" ASCII_EOL); - if(hal.rtc.get_datetime) { - hal.stream.write("$RTC - output current time" ASCII_EOL); - hal.stream.write("$RTC= - set current time" ASCII_EOL); - } -#ifndef NO_SETTINGS_DESCRIPTIONS - hal.stream.write("$SED= - output settings description for setting " ASCII_EOL); -#endif + system_output_help(sys_commands, sizeof(sys_commands) / sizeof(sys_command_t)); } /*! \brief Directs and executes one line of input from protocol_process. diff --git a/system.h b/system.h index 155467f..8760cdb 100644 --- a/system.h +++ b/system.h @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2017-2023 Terje Io + Copyright (c) 2017-2024 Terje Io Copyright (c) 2014-2016 Sungeun K. Jeon for Gnea Research LLC Grbl is free software: you can redistribute it and/or modify @@ -119,7 +119,7 @@ typedef union { }; } step_control_t; - +// NOTE: the pin_function_t enum must be kept in sync with any changes! typedef union { uint16_t value; uint16_t mask; @@ -139,11 +139,10 @@ typedef union { unassigned :1, probe_overtravel :1, //! used for probe protection probe_triggered :1, //! used for probe protection - deasserted :1; //! this flag is set if signals are deasserted. Note: do NOT pass on to the control_interrupt_handler if set. + deasserted :1; //! this flag is set if signals are deasserted. }; } control_signals_t; - // Define spindle stop override control states. typedef union { uint8_t value; @@ -313,13 +312,15 @@ typedef struct system { } system_t; typedef status_code_t (*sys_command_ptr)(sys_state_t state, char *args); +typedef const char *(*sys_help_ptr)(const char *command); typedef union { uint8_t flags; struct { uint8_t noargs :1, //!< System command does not handle arguments. allow_blocking :1, //!< System command can be used when blocking event is active. - unused :6; + help_fn :1, + unused :5; }; } sys_command_flags_t; @@ -328,6 +329,10 @@ typedef struct const char *command; sys_command_ptr execute; sys_command_flags_t flags; + union { + const char *str; + sys_help_ptr fn; + } help; } sys_command_t; typedef struct sys_commands_str { @@ -344,7 +349,9 @@ void system_flag_wco_change (void); void system_convert_array_steps_to_mpos (float *position, int32_t *steps); bool system_xy_at_fixture (coord_system_id_t id, float tolerance); void system_raise_alarm (alarm_code_t alarm); +void system_init_switches (void); void system_command_help (void); +void system_output_help (const sys_command_t *commands, uint32_t num_commands); void system_add_rt_report (report_tracking_t report); report_tracking_flags_t system_get_rt_report_flags (void);