diff --git a/README.md b/README.md
index 683143f..f59973f 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
## grblHAL ##
-Latest build date is 20250110, see the [changelog](changelog.md) for details.
+Latest build date is 20250114, see the [changelog](changelog.md) for details.
> [!NOTE]
> A settings reset will be performed on an update of builds prior to 20241208. Backup and restore of settings is recommended.
@@ -93,4 +93,4 @@ G/M-codes not supported by [legacy Grbl](https://github.com/gnea/grbl/wiki) are
Some [plugins](https://github.com/grblHAL/plugins) implements additional M-codes.
---
-20250107
+20250115
diff --git a/changelog.md b/changelog.md
index bc41123..c638528 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,5 +1,39 @@
## grblHAL changelog
+20250115
+
+Plugins:
+
+Fans, Keypad, macros: bug fixes and changes to avoid compiler warnings.
+
+---
+
+Build 20250114
+
+Core:
+
+* "hardened" task deregistration code and changed signature of setting available and `ioport_find_free()` calls.
+
+* Some low-level ioport improvements, added definition for virtual pins/ports.
+Deprecated direct access to number of the different ioport ports in `hal.port` struct, use `ioports_unclaimed()` instead.
+
+Drivers:
+
+* ESP32: some fixes for Trinamic SPI comms.
+
+Plugins:
+
+* Many: updated for setting call signature changes and to take advantage of latest core functionality.
+Plugins claiming auxiliary ports changed to use `-1` for port number settings that are to be ignored/not claimed.
+
+* Plasma: refactored, uses new task functionality for processing and has improved settings handling. Virtual auxiliary ports disabled for now.
+
+Templates:
+
+* Many: updated to take advandage of latest core functionality etc. Removed some superfluous ones.
+
+---
+
Build 20250111
Core:
diff --git a/crossbar.h b/crossbar.h
index 2bc1287..7cd4547 100644
--- a/crossbar.h
+++ b/crossbar.h
@@ -213,6 +213,7 @@ typedef enum {
Input_QEI_B,
Input_QEI_Select,
Input_QEI_Index,
+ Virtual_Pin,
// Single pin bidirectional peripherals
Bidirectional_MotorUARTX,
Bidirectional = Bidirectional_MotorUARTX,
@@ -421,6 +422,7 @@ PROGMEM static const pin_name_t pin_names[] = {
{ .function = Input_QEI_B, .name = "QEI B" },
{ .function = Input_QEI_Select, .name = "QEI select" },
{ .function = Input_QEI_Index, .name = "QEI index" },
+ { .function = Virtual_Pin, .name = "Virtual" },
{ .function = Bidirectional_MotorUARTX, .name = "UART X" },
{ .function = Bidirectional_MotorUARTY, .name = "UART Y" },
{ .function = Bidirectional_MotorUARTZ, .name = "UART Z" },
@@ -458,6 +460,7 @@ typedef enum {
PinGroup_CAN,
PinGroup_LED,
PinGroup_Home,
+ PinGroup_Virtual,
// Interrupt capable pins that may have debounce processing enabled
PinGroup_Control = (1<<8),
PinGroup_Limit = (1<<9),
diff --git a/errors.c b/errors.c
index 46bb8b8..4027cd8 100644
--- a/errors.c
+++ b/errors.c
@@ -3,7 +3,7 @@
Part of grblHAL
- Copyright (c) 2017-2024 Terje Io
+ Copyright (c) 2017-2025 Terje Io
Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC
Copyright (c) 2009-2011 Simen Svale Skogsrud
@@ -87,6 +87,7 @@ PROGMEM static const status_detail_t status_detail[] = {
#if COMPATIBILITY_LEVEL <= 1
{ Status_GCodeCoordSystemLocked, "Coordinate system is locked." },
#endif
+ { Status_UnexpectedDemarcation, "Unexpected file demarcation." },
#if NGC_EXPRESSIONS_ENABLE
{ Status_ExpressionUknownOp, "Unknown operation found in expression." },
{ Status_ExpressionDivideByZero, "Divide by zero in expression attempted." },
diff --git a/errors.h b/errors.h
index 79adfda..dd42e16 100644
--- a/errors.h
+++ b/errors.h
@@ -3,7 +3,7 @@
Part of grblHAL
- Copyright (c) 2017-2024 Terje Io
+ Copyright (c) 2017-2025 Terje Io
Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC
Copyright (c) 2009-2011 Simen Svale Skogsrud
@@ -86,6 +86,7 @@ typedef enum {
Status_GcodeInvalidRetractPosition = 54,
Status_IllegalHomingConfiguration = 55,
Status_GCodeCoordSystemLocked = 56,
+ Status_UnexpectedDemarcation = 57,
// Some error codes as defined in bdring's ESP32 port
Status_SDMountError = 60,
diff --git a/gcode.c b/gcode.c
index 7ecbcb0..5f5406a 100644
--- a/gcode.c
+++ b/gcode.c
@@ -798,34 +798,42 @@ status_code_t gc_execute_block (char *block)
tool_id_t t;
} single_meaning_value = {0};
- block = gc_normalize_block(block, &status, &message);
+ bool fs_changed;
+ if((fs_changed = gc_state.file_stream ? hal.stream.file == NULL : hal.stream.file != NULL))
+ gc_state.file_stream = hal.stream.file != NULL;
+ block = gc_normalize_block(block, &status, &message);
if(status != Status_OK)
FAIL(status);
+ // Determine if the line is a program start/end marker.
+ if(block[0] == CMD_PROGRAM_DEMARCATION && block[1] == '\0') {
+
+ block[0] = '\0';
+
+ if(gc_state.file_stream) {
+
+ if(!fs_changed && !gc_state.file_run)
+ status = Status_UnexpectedDemarcation;
+ else if(!(gc_state.file_run = fs_changed)) {
+ protocol_buffer_synchronize(); // Empty planner buffer
+ grbl.report.feedback_message(Message_ProgramEnd);
+ if(grbl.on_program_completed)
+ grbl.on_program_completed(ProgramFlow_EndPercent, state_get() == STATE_CHECK_MODE);
+ }
+ } else
+ gc_state.file_run = !gc_state.file_run;
+
+ if(status == Status_OK && grbl.on_file_demarcate)
+ grbl.on_file_demarcate(gc_state.file_run);
+ }
+
if(block[0] == '\0') {
if(message)
gc_output_message(message);
return status;
}
- // Determine if the line is a program start/end marker.
- // Old comment from protocol.c:
- // NOTE: This maybe installed to tell grblHAL when a program is running vs manual input,
- // where, during a program, the system auto-cycle start will continue to execute
- // everything until the next '%' sign. This will help fix resuming issues with certain
- // functions that empty the planner buffer to execute its task on-time.
- if (block[0] == CMD_PROGRAM_DEMARCATION && block[1] == '\0') {
- gc_state.file_run = !gc_state.file_run;
- if(message)
- gc_output_message(message);
-
- if(grbl.on_file_demarcate)
- grbl.on_file_demarcate(gc_state.file_run);
-
- return Status_OK;
- }
-
/* -------------------------------------------------------------------------------------
STEP 1: Initialize parser block struct and copy current g-code state modes. The parser
updates these modes and commands as the block line is parsed and will only be used and
diff --git a/gcode.h b/gcode.h
index 6f02bf7..89540d6 100644
--- a/gcode.h
+++ b/gcode.h
@@ -3,7 +3,7 @@
Part of grblHAL
- Copyright (c) 2017-2024 Terje Io
+ Copyright (c) 2017-2025 Terje Io
Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC
Copyright (c) 2009-2011 Simen Svale Skogsrud
@@ -207,7 +207,8 @@ typedef enum {
ProgramFlow_CompletedM2 = 2, //!< 2 - M2
ProgramFlow_CompletedM30 = 30, //!< 30 - M30
ProgramFlow_CompletedM60 = 60, //!< 60 - M60
- ProgramFlow_Return = 99 //!< 99 - M99
+ ProgramFlow_Return = 99, //!< 99 - M99
+ ProgramFlow_EndPercent = 255 //!< 255 - %
} program_flow_t;
// Modal Group M9: Override control
@@ -625,6 +626,7 @@ typedef struct {
uint32_t g43_pending; //!< Tool offset to be selected on next M6, for macro ATC
#endif
bool file_run; //!< Tracks % command
+ bool file_stream; //!< Tracks streaming from file
bool is_laser_ppi_mode;
bool is_rpm_rate_adjusted;
bool tool_change;
diff --git a/grbl.h b/grbl.h
index 37db197..84b0e06 100644
--- a/grbl.h
+++ b/grbl.h
@@ -42,7 +42,7 @@
#else
#define GRBL_VERSION "1.1f"
#endif
-#define GRBL_BUILD 20250111
+#define GRBL_BUILD 20250114
#define GRBL_URL "https://github.com/grblHAL"
diff --git a/grbllib.c b/grbllib.c
index 038a81b..d912a46 100644
--- a/grbllib.c
+++ b/grbllib.c
@@ -420,7 +420,7 @@ int grbl_enter (void)
return 0;
}
-static inline core_task_t *task_alloc (void)
+__attribute__((always_inline)) static inline core_task_t *task_alloc (void)
{
core_task_t *task = NULL;
uint_fast8_t idx = CORE_TASK_POOL_SIZE;
@@ -436,7 +436,7 @@ static inline core_task_t *task_alloc (void)
return task;
}
-static inline void task_free (core_task_t *task)
+__attribute__((always_inline)) static inline void task_free (core_task_t *task)
{
task->fn = NULL;
if(last_freed == NULL)
@@ -525,6 +525,8 @@ void task_delete (foreground_task_ptr fn, void *data)
{
core_task_t *task, *prev = NULL;
+ hal.irq_disable();
+
if((task = next_task)) do {
if(fn == task->fn && data == task->data) {
if(prev)
@@ -536,6 +538,8 @@ void task_delete (foreground_task_ptr fn, void *data)
}
prev = task;
} while((task = task->next));
+
+ hal.irq_enable();
}
ISR_CODE bool ISR_FUNC(task_add_systick)(foreground_task_ptr fn, void *data)
@@ -569,6 +573,8 @@ void task_delete_systick (foreground_task_ptr fn, void *data)
{
core_task_t *task, *prev = NULL;
+ hal.irq_disable();
+
if((task = systick_task)) do {
if(fn == task->fn && data == task->data) {
if(prev)
@@ -580,6 +586,8 @@ void task_delete_systick (foreground_task_ptr fn, void *data)
}
prev = task;
} while((task = task->next));
+
+ hal.irq_enable();
}
/*! \brief Enqueue a function to be called once by the foreground process.
diff --git a/ioports.c b/ioports.c
index 7b9da42..b099733 100644
--- a/ioports.c
+++ b/ioports.c
@@ -96,39 +96,57 @@ uint8_t ioports_available (io_port_type_t type, io_port_direction_t dir)
return ports;
}
+/*! \brief Get number of unclaimed digital or analog ports available.
+\param type as an \a #io_port_type_t enum value.
+\param dir as an \a #io_port_direction_t enum value.
+\returns number of ports available.
+*/
+uint8_t ioports_unclaimed (io_port_type_t type, io_port_direction_t dir)
+{
+ xbar_t *port;
+ uint8_t idx = 0, n_ports = 0;
+
+ if(hal.port.get_pin_info) do {
+ if((port = hal.port.get_pin_info(type, dir, idx++)) && !port->mode.claimed)
+ n_ports++;
+ } while(port);
+
+ return n_ports;
+}
+
+static struct ff_data {
+ uint8_t port;
+ const char *description;
+} ff_data;
+
+static bool match_port (xbar_t *properties, uint8_t port, void *data)
+{
+ if(((struct ff_data *)data)->description && (!properties->description || strcmp(properties->description, ((struct ff_data *)data)->description)))
+ return false;
+
+ ((struct ff_data *)data)->port = port;
+
+ return true;
+}
+
/*! \brief find first free or claimed digital or analog port.
\param type as an \a #io_port_type_t enum value.
\param dir as an \a #io_port_direction_t enum value.
\param description pointer to a \a char constant for the pin description of a previousely claimed port or NULL if searching for the first free port.
-\returns the port number if successful, 255 if not.
+\returns the port number if successful, 0xFF (255) if not.
*/
-uint8_t ioport_find_free (io_port_type_t type, io_port_direction_t dir, const char *description)
+uint8_t ioport_find_free (io_port_type_t type, io_port_direction_t dir, pin_cap_t filter, const char *description)
{
- uint8_t port;
- bool found = false;
- xbar_t *pin;
+ ff_data.port = 0xFF;
+ ff_data.description = (description && *description) ? description : NULL;
- if(description) {
- port = ioports_available(type, dir);
- do {
- if((pin = hal.port.get_pin_info(type, dir, --port))) {
- if((found = pin->description && !strcmp(pin->description, description)))
- port = pin->id;
- }
- } while(port && !found);
+ // TODO: pass modified filter with .claimable off when looking for description match?
+ if(ff_data.description && !ioports_enumerate(type, dir, (pin_cap_t){}, match_port, (void *)&ff_data)) {
+ ff_data.description = NULL;
+ ioports_enumerate(type, dir, filter, match_port, (void *)&ff_data);
}
- if(!found) {
- port = ioports_available(type, dir);
- do {
- if((pin = hal.port.get_pin_info(type, dir, --port))) {
- if((found = !pin->mode.claimed))
- port = pin->id;
- }
- } while(port && !found);
- }
-
- return found ? port : 255;
+ return ff_data.port;
}
/*! \brief Return information about a digital or analog port.
@@ -170,15 +188,24 @@ bool ioport_claim (io_port_type_t type, io_port_direction_t dir, uint8_t *port,
ok = (portinfo = ioport_get_info(type, dir, *port)) && !portinfo->mode.claimed && hal.port.claim(type, dir, port, description);
- } else if((ok = ioports_available(type, dir) > 0)) {
+ } else {
- if(type == Port_Digital)
- *port = dir == Port_Input ? --hal.port.num_digital_in : --hal.port.num_digital_out;
- else
- *port = dir == Port_Input ? --hal.port.num_analog_in : --hal.port.num_analog_out;
+ uint_fast8_t count;
+ get_pin_info_ptr get_pin_info = hal.port.get_pin_info;
- if(hal.port.set_pin_description)
- hal.port.set_pin_description(type, dir, *port, description);
+ hal.port.get_pin_info = NULL; // Force count of unclaimed ports only.
+
+ if((ok = (count = ioports_available(type, dir)) > 0 && *port == count - 1 )) {
+ if(type == Port_Digital)
+ *port = dir == Port_Input ? --hal.port.num_digital_in : --hal.port.num_digital_out;
+ else
+ *port = dir == Port_Input ? --hal.port.num_analog_in : --hal.port.num_analog_out;
+
+ if(hal.port.set_pin_description)
+ hal.port.set_pin_description(type, dir, *port, description);
+ }
+
+ hal.port.get_pin_info = get_pin_info;
}
return ok;
@@ -296,39 +323,41 @@ bool ioports_add (io_ports_data_t *ports, io_port_type_t type, uint8_t n_in, uin
if(type == Port_Digital) {
cfg = &digital;
- digital_in = digital_out = -1;
if(n_in) {
- ports->in.n_start = hal.port.num_digital_in;
+ ports->in.n_start = ioports_available(Port_Digital, Port_Input);
hal.port.num_digital_in += (ports->in.n_ports = n_in);
ports->in.map = malloc(ports->in.n_ports * sizeof(ports->in.n_ports));
digital.in.ports = &ports->in;
+ digital_in = -1;
}
if(n_out) {
- ports->out.n_start = hal.port.num_digital_out;
+ ports->out.n_start = ioports_available(Port_Digital, Port_Output);
hal.port.num_digital_out += (ports->out.n_ports = n_out);
ports->out.map = malloc(ports->out.n_ports * sizeof(ports->out.n_ports));
digital.out.ports = &ports->out;
+ digital_out = -1;
}
} else {
cfg = &analog;
- analog_in = analog_out = -1;
if(n_in) {
- ports->in.n_start = hal.port.num_analog_in;
+ ports->in.n_start = ioports_available(Port_Analog, Port_Input);
hal.port.num_analog_in += (ports->in.n_ports = n_in);
ports->in.map = malloc(ports->in.n_ports * sizeof(ports->in.n_ports));
analog.in.ports = &ports->in;
+ analog_in = -1;
}
if(n_out) {
- ports->out.n_start = hal.port.num_analog_out;
+ ports->out.n_start = ioports_available(Port_Analog, Port_Output);
hal.port.num_analog_out += (ports->out.n_ports = n_out);
ports->out.map = malloc(ports->out.n_ports * sizeof(ports->out.n_ports));
analog.out.ports = &ports->out;
+ analog_out = -1;
}
}
@@ -496,7 +525,7 @@ void ioport_save_output_settings (xbar_t *xbar, gpio_out_config_t *config)
settings_write_global();
}
-static bool is_setting_available (const setting_detail_t *setting)
+static bool is_setting_available (const setting_detail_t *setting, uint_fast16_t offset)
{
bool available = false;
diff --git a/ioports.h b/ioports.h
index 8214f58..bcb56aa 100644
--- a/ioports.h
+++ b/ioports.h
@@ -109,10 +109,10 @@ typedef bool (*ioports_enumerate_callback_ptr)(xbar_t *properties, uint8_t port,
//! Properties and handlers for auxiliary digital and analog I/O.
typedef struct {
- uint8_t num_digital_in; //!< Number of digital inputs available.
- uint8_t num_digital_out; //!< Number of digital outputs available.
- uint8_t num_analog_in; //!< Number of analog inputs available.
- uint8_t num_analog_out; //!< Number of analog outputs available.
+ uint8_t num_digital_in; //!< Deprecated, use ioports_unclaimed() to get count.
+ uint8_t num_digital_out; //!< Deprecated, use ioports_unclaimed() to get count.
+ uint8_t num_analog_in; //!< Deprecated, use ioports_unclaimed() to get count.
+ uint8_t num_analog_out; //!< Deprecated, use ioports_unclaimed() to get count.
digital_out_ptr digital_out; //!< Optional handler for setting a digital output.
analog_out_ptr analog_out; //!< Optional handler for setting an analog output.
wait_on_input_ptr wait_on_input; //!< Optional handler for reading a digital or analog input.
@@ -124,10 +124,11 @@ typedef struct {
} io_port_t;
uint8_t ioports_available (io_port_type_t type, io_port_direction_t dir);
+uint8_t ioports_unclaimed (io_port_type_t type, io_port_direction_t dir);
xbar_t *ioport_get_info (io_port_type_t type, io_port_direction_t dir, uint8_t port);
bool ioport_claim (io_port_type_t type, io_port_direction_t dir, uint8_t *port, const char *description);
bool ioport_can_claim_explicit (void);
-uint8_t ioport_find_free (io_port_type_t type, io_port_direction_t dir, const char *description);
+uint8_t ioport_find_free (io_port_type_t type, io_port_direction_t dir, pin_cap_t filter, const char *description);
bool ioports_enumerate (io_port_type_t type, io_port_direction_t dir, pin_cap_t filter, ioports_enumerate_callback_ptr callback, void *data);
void ioport_assign_function (aux_ctrl_t *aux_ctrl, pin_function_t *function);
void ioport_assign_out_function (aux_ctrl_out_t *aux_ctrl, pin_function_t *function);
diff --git a/report.c b/report.c
index db15086..8aa7915 100644
--- a/report.c
+++ b/report.c
@@ -502,7 +502,7 @@ void report_grbl_settings (bool all, void *data)
for(idx = 0; idx < details->n_settings; idx++) {
setting = &details->settings[idx];
if(!is_hidden(setting) && (all || setting->type == Setting_IsLegacy || setting->type == Setting_IsLegacyFn) &&
- (setting->is_available == NULL ||setting->is_available(setting))) {
+ (setting->is_available == NULL ||setting->is_available(setting, 0))) {
*psetting++ = (setting_detail_t *)setting;
n_settings++;
}
@@ -512,7 +512,7 @@ void report_grbl_settings (bool all, void *data)
if(all && (details = details->next)) do {
for(idx = 0; idx < details->n_settings; idx++) {
setting = &details->settings[idx];
- if(!setting->flags.hidden && (setting->is_available == NULL || setting->is_available(setting))) {
+ if(!setting->flags.hidden && (setting->is_available == NULL || setting->is_available(setting, 0))) {
*psetting++ = (setting_detail_t *)setting;
n_settings++;
}
@@ -1101,15 +1101,20 @@ void report_build_info (char *line, bool extended)
hal.stream.write("]" ASCII_EOL);
#endif
- if(hal.port.num_digital_in + hal.port.num_digital_out + hal.port.num_analog_in + hal.port.num_analog_out > 0) {
+ uint8_t digital_in = ioports_unclaimed(Port_Digital, Port_Input),
+ digital_out = ioports_unclaimed(Port_Digital, Port_Output),
+ analog_in = ioports_unclaimed(Port_Analog, Port_Input),
+ analog_out = ioports_unclaimed(Port_Analog, Port_Output);
+
+ if(digital_in || digital_out || analog_in || analog_out) {
hal.stream.write("[AUX IO:");
- hal.stream.write(uitoa(hal.port.num_digital_in));
+ hal.stream.write(uitoa(digital_in));
hal.stream.write(",");
- hal.stream.write(uitoa(hal.port.num_digital_out));
+ hal.stream.write(uitoa(digital_out));
hal.stream.write(",");
- hal.stream.write(uitoa(hal.port.num_analog_in));
+ hal.stream.write(uitoa(analog_in));
hal.stream.write(",");
- hal.stream.write(uitoa(hal.port.num_analog_out));
+ hal.stream.write(uitoa(analog_out));
hal.stream.write("]" ASCII_EOL);
}
@@ -1844,7 +1849,7 @@ static bool print_sorted (const setting_detail_t *setting, uint_fast16_t offset,
static bool print_unsorted (const setting_detail_t *setting, uint_fast16_t offset, void *args)
{
if(!(((report_args_t *)args)->group == setting->group && ((report_args_t *)args)->offset != offset) &&
- (setting->is_available == NULL ||setting->is_available(setting)))
+ (setting->is_available == NULL ||setting->is_available(setting, 0)))
report_settings_detail(((report_args_t *)args)->format, setting, offset);
return true;
@@ -1881,7 +1886,7 @@ static status_code_t print_settings_details (settings_format_t format, setting_g
do {
for(idx = 0; idx < details->n_settings; idx++) {
setting = &details->settings[idx];
- if(!is_hidden(setting) && (group == Group_All || setting->group == args.group) && (setting->is_available == NULL || setting->is_available(setting))) {
+ if(!is_hidden(setting) && (group == Group_All || setting->group == args.group) && (setting->is_available == NULL || setting->is_available(setting, 0))) {
*psetting++ = (setting_detail_t *)setting;
n_settings++;
}
diff --git a/settings.c b/settings.c
index bbebcfc..4d45c4d 100644
--- a/settings.c
+++ b/settings.c
@@ -1716,16 +1716,16 @@ float setting_get_float_value (const setting_detail_t *setting, uint_fast16_t of
return value;
}
-static bool is_group_available (const setting_detail_t *setting)
+static bool is_group_available (const setting_detail_t *setting, uint_fast16_t offset)
{
return settings_is_group_available(setting->group);
}
-static bool is_setting_available (const setting_detail_t *setting)
+static bool is_setting_available (const setting_detail_t *setting, uint_fast16_t offset)
{
bool available = false;
- if(setting) switch(normalize_id(setting->id)) {
+ if(setting) switch(setting->id) {
case Setting_GangedDirInvertMask:
available = hal.stepper.get_ganged && hal.stepper.get_ganged(false).mask != 0;
@@ -1843,7 +1843,7 @@ static bool is_setting_available (const setting_detail_t *setting)
break;
case Setting_CoolantOnDelay:
- available = !hal.signals_cap.safety_door_ajar && hal.coolant_cap.mask;
+ available = hal.coolant_cap.mask;
break;
default:
@@ -1853,7 +1853,7 @@ static bool is_setting_available (const setting_detail_t *setting)
return available;
}
-static bool toolsetter_available (const setting_detail_t *setting)
+static bool toolsetter_available (const setting_detail_t *setting, uint_fast16_t offset)
{
bool available = false;
@@ -1878,7 +1878,7 @@ static bool toolsetter_available (const setting_detail_t *setting)
return available;
}
-static bool no_toolsetter_available (const setting_detail_t *setting)
+static bool no_toolsetter_available (const setting_detail_t *setting, uint_fast16_t offset)
{
#if COMPATIBILITY_LEVEL <= 1
@@ -2563,9 +2563,9 @@ void settings_restore (settings_restore_t restore)
nvs_buffer_sync_physical();
}
-inline static bool is_available (const setting_detail_t *setting)
+inline static bool is_available (const setting_detail_t *setting, uint_fast16_t offset)
{
- return setting->is_available == NULL || setting->is_available(setting);
+ return setting->is_available == NULL || setting->is_available(setting, offset);
}
bool settings_is_group_available (setting_group_t id)
@@ -2611,7 +2611,7 @@ bool settings_is_group_available (setting_group_t id)
do {
if(details->settings) {
for(idx = 0; idx < details->n_settings; idx++) {
- if(details->settings[idx].group == id && (available = is_available(&details->settings[idx])))
+ if(details->settings[idx].group == id && (available = is_available(&details->settings[idx], 0)))
break;
}
}
@@ -2664,7 +2664,7 @@ const setting_detail_t *setting_get_details (setting_id_t id, setting_details_t
do {
for(idx = 0; idx < details->n_settings; idx++) {
- if(details->settings[idx].id == id && is_available(&details->settings[idx])) {
+ if(details->settings[idx].id == id && is_available(&details->settings[idx], offset)) {
if(details->settings[idx].group == Group_Axis0 && grbl.on_set_axis_setting_unit)
set_axis_unit(&details->settings[idx], grbl.on_set_axis_setting_unit(details->settings[idx].id, offset));
diff --git a/settings.h b/settings.h
index 83f5cf9..5425b46 100644
--- a/settings.h
+++ b/settings.h
@@ -985,7 +985,7 @@ typedef struct setting_detail {
setting_type_t type;
void *value;
void *get_value;
- bool (*is_available)(const struct setting_detail *setting);
+ bool (*is_available)(const struct setting_detail *setting, uint_fast16_t offset);
setting_detail_flags_t flags;
} setting_detail_t;
diff --git a/stream_file.c b/stream_file.c
index 391fa39..8fcdcf6 100644
--- a/stream_file.c
+++ b/stream_file.c
@@ -3,7 +3,7 @@
Part of grblHAL
- Copyright (c) 2024 Terje Io
+ Copyright (c) 2025 Terje Io
grblHAL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -120,6 +120,13 @@ static void onReportHandlersInit (void)
grbl.report.status_message = trap_status_messages;
}
+void stream_set_type (stream_type_t type, vfs_file_t *file)
+{
+ hal.stream.type = type;
+ if(!(hal.stream.file = file))
+ gc_state.file_stream = false;
+}
+
bool stream_is_file (void)
{
return hal.stream.type == StreamType_File;
@@ -141,9 +148,8 @@ vfs_file_t *stream_redirect_read (char *filename, status_message_ptr status_hand
rd_stream->eof_handler = eof_handler;
rd_stream->status_handler = status_handler;
rd_stream->next = NULL;
- hal.stream.file = file;
- hal.stream.type = StreamType_File;
hal.stream.read = stream_read_file;
+ stream_set_type(StreamType_File, file);
if(streams == NULL)
rd_streams = rd_stream;
else do {
@@ -181,9 +187,8 @@ void stream_redirect_close (vfs_file_t *file)
if(stream) do {
if(stream->file_new == file) {
vfs_close(file);
- hal.stream.file = stream->file;
hal.stream.read = stream->read;
- hal.stream.type = stream->type;
+ stream_set_type(stream->type, stream->file);
if(stream == rd_streams)
rd_streams = stream->next;
else
diff --git a/stream_file.h b/stream_file.h
index 11d04ec..048ce69 100644
--- a/stream_file.h
+++ b/stream_file.h
@@ -3,7 +3,7 @@
Part of grblHAL
- Copyright (c) 2024 Terje Io
+ Copyright (c) 2024-2025 Terje Io
grblHAL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -26,4 +26,5 @@
bool stream_is_file (void);
void stream_redirect_close (vfs_file_t *file);
+void stream_set_type (stream_type_t type, vfs_file_t *file);
vfs_file_t *stream_redirect_read (char *filename, status_message_ptr status_handler, on_file_end_ptr eof_handler);