From efe4245a06b8244d801b8f54acda017456bbb680 Mon Sep 17 00:00:00 2001 From: Terje Io Date: Tue, 14 Jan 2025 17:13:56 +0100 Subject: [PATCH] "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. --- changelog.md | 26 +++++++++++++ crossbar.h | 3 ++ errors.c | 3 +- errors.h | 3 +- gcode.c | 44 ++++++++++++--------- gcode.h | 6 ++- grbl.h | 2 +- grbllib.c | 12 +++++- ioports.c | 105 ++++++++++++++++++++++++++++++++------------------ ioports.h | 11 +++--- report.c | 23 ++++++----- settings.c | 20 +++++----- settings.h | 2 +- stream_file.c | 15 +++++--- stream_file.h | 3 +- 15 files changed, 184 insertions(+), 94 deletions(-) diff --git a/changelog.md b/changelog.md index bc41123..fee3018 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,31 @@ ## grblHAL changelog +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 advandage 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);