diff --git a/README.md b/README.md index dd9a8f7..53b095d 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ## grblHAL ## -Latest build date is 20250718, see the [changelog](changelog.md) for details. +Latest build date is 20250724, 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. diff --git a/changelog.md b/changelog.md index d397ddf..81100c9 100644 --- a/changelog.md +++ b/changelog.md @@ -1,6 +1,23 @@ ## grblHAL changelog -Build 20250724 + +Core: + +Fix for optional control signals not respecting `$14` inversion setting. Ref. issue [#780](https://github.com/grblHAL/core/issues/780). + +For developers: added core `on_spindle_at_speed` event. This must be verified with actual VFD spindles, I only have a simulator available. +Improved handling of "iterated" settings, can now be fully implemented by plugins. + +Plugins: + +* Spindle, select: updated for core change, fixed bug in tool number start vs. spindle settings \($52x\). Ref. iMXRT1062 issue [#99](https://github.com/grblHAL/iMXRT1062/issues/99). + +* Spindle, offset: added setting `$772` for options, currently _Update G92 on spindle change_ is available. + +--- + +Build 20250720 Core: diff --git a/core_handlers.h b/core_handlers.h index ac253ef..6dc9936 100644 --- a/core_handlers.h +++ b/core_handlers.h @@ -88,6 +88,7 @@ typedef void (*on_parser_init_ptr)(parser_state_t *gc_state); typedef void (*on_state_change_ptr)(sys_state_t state); typedef void (*on_override_changed_ptr)(override_changed_t override); typedef void (*on_spindle_programmed_ptr)(spindle_ptrs_t *spindle, spindle_state_t state, float rpm, spindle_rpm_mode_t mode); +typedef void (*on_spindle_at_speed_ptr)(spindle_ptrs_t *spindle, spindle_state_t state); typedef void (*on_wco_changed_ptr)(void); typedef void (*on_wco_saved_ptr)(coord_system_id_t id, coord_data_t *data); typedef void (*on_program_completed_ptr)(program_flow_t program_flow, bool check_mode); @@ -223,6 +224,7 @@ typedef struct { on_override_changed_ptr on_override_changed; on_report_handlers_init_ptr on_report_handlers_init; on_spindle_programmed_ptr on_spindle_programmed; + on_spindle_at_speed_ptr on_spindle_at_speed; on_wco_changed_ptr on_wco_changed; on_wco_saved_ptr on_wco_saved; on_program_completed_ptr on_program_completed; diff --git a/grbl.h b/grbl.h index 8c86072..69259f1 100644 --- a/grbl.h +++ b/grbl.h @@ -42,7 +42,7 @@ #else #define GRBL_VERSION "1.1f" #endif -#define GRBL_BUILD 20250720 +#define GRBL_BUILD 20250724 #define GRBL_URL "https://github.com/grblHAL" diff --git a/ioports.c b/ioports.c index 04c0164..759a1fe 100644 --- a/ioports.c +++ b/ioports.c @@ -1276,8 +1276,6 @@ static const setting_detail_t ioport_settings[] = { // { Settings_IoPort_OD_Enable, Group_AuxPorts, "I/O Port outputs as open drain", NULL, Format_Bitfield, digital.out.port_names, NULL, NULL, Setting_NonCoreFn, aux_set_value, aux_get_value, is_setting_available } }; -#ifndef NO_SETTINGS_DESCRIPTIONS - static const setting_descr_t ioport_settings_descr[] = { { Settings_IoPort_InvertIn, "Invert IOPort inputs." }, // { Settings_IoPort_Pullup_Disable, "Disable IOPort input pullups." }, @@ -1285,8 +1283,6 @@ static const setting_descr_t ioport_settings_descr[] = { // { Settings_IoPort_OD_Enable, "Set IOPort outputs as open drain (OD)." } }; -#endif - static bool config_probe_pins (pin_function_t function, gpio_in_config_t *config) { bool ok = true; @@ -1360,12 +1356,13 @@ void ioport_setting_changed (setting_id_t id) if(xbar->config && xbar->function < Input_Probe) { in_config.debounce = xbar->mode.debounce; - in_config.inverted = !!(settings.ioport.invert_in.mask & (1 << port)); - in_config.pull_mode = (pull_mode_t)xbar->mode.pull_mode; if((ctrl = xbar_fn_to_signals_mask(xbar->function)).mask) { in_config.inverted = !!(settings.control_invert.mask & ctrl.mask); in_config.pull_mode = (settings.control_disable_pullup.mask & ctrl.mask) ? PullMode_None : PullMode_Up; + } else { + in_config.inverted = !!(settings.ioport.invert_in.mask & (1 << port)); + in_config.pull_mode = (pull_mode_t)xbar->mode.pull_mode; } if(in_config.inverted) @@ -1417,9 +1414,7 @@ static void ioports_configure (settings_t *settings) if(!config_probe_pins(xbar->function, &in_config) && xbar->function < Input_Probe) { control_signals_t ctrl; if((ctrl = xbar_fn_to_signals_mask(xbar->function)).mask) { -#ifdef RP2040 // RP2xxx MCUs use hardware signal inversion in_config.inverted = !!(settings->control_invert.mask & ctrl.mask); -#endif in_config.pull_mode = (settings->control_disable_pullup.mask & ctrl.mask) ? PullMode_None : PullMode_Up; } } @@ -1463,10 +1458,8 @@ void ioports_add_settings (driver_settings_load_ptr settings_loaded, setting_cha .n_groups = sizeof(ioport_groups) / sizeof(setting_group_detail_t), .settings = ioport_settings, .n_settings = sizeof(ioport_settings) / sizeof(setting_detail_t), - #ifndef NO_SETTINGS_DESCRIPTIONS .descriptions = ioport_settings_descr, .n_descriptions = sizeof(ioport_settings_descr) / sizeof(setting_descr_t), - #endif .save = settings_write_global }; diff --git a/pin_bits_masks.h b/pin_bits_masks.h index 8c57369..d7f0994 100644 --- a/pin_bits_masks.h +++ b/pin_bits_masks.h @@ -297,8 +297,10 @@ typedef bool (*aux_claim_explicit_ptr)(aux_ctrl_t *aux_ctrl); static bool aux_ctrl_claim_port (xbar_t *properties, uint8_t port, void *data) { - if(ioport_claim(Port_Digital, Port_Input, &port, xbar_fn_to_pinname(((aux_ctrl_t *)data)->function))) + if(ioport_claim(Port_Digital, Port_Input, &port, NULL)) { ((aux_ctrl_t *)data)->aux_port = port; + ioport_set_function(properties, ((aux_ctrl_t *)data)->function, &((aux_ctrl_t *)data)->cap); + } return ((aux_ctrl_t *)data)->aux_port != IOPORT_UNASSIGNED; } diff --git a/settings.c b/settings.c index 0fa8aec..7824c08 100644 --- a/settings.c +++ b/settings.c @@ -1233,8 +1233,7 @@ inline static setting_id_t normalize_id (setting_id_t id) (id > Setting_MacroPort0 && id <= Setting_MacroPort9) || (id > Setting_ButtonAction0 && id <= Setting_ButtonAction9) || (id > Setting_Action0 && id <= Setting_Action9) || - (id > Setting_ActionPort0 && id <= Setting_ActionPort9) || - (id > Setting_SpindleToolStart0 && id <= Setting_SpindleToolStart7)) + (id > Setting_ActionPort0 && id <= Setting_ActionPort9)) id = (setting_id_t)(id - (id % 10)); return id; @@ -2151,7 +2150,7 @@ PROGMEM static const setting_detail_t setting_detail[] = { { Setting_DoorCoolantOnDelay, Group_SafetyDoor, "Coolant on delay", "s", Format_Decimal, "#0.0", "0.5", "20", Setting_IsExtended, &settings.safety_door.coolant_on_delay, NULL, is_setting_available, { .allow_null = On } }, #endif { Setting_SpindleOnDelay, Group_Spindle, "Spindle on delay", "s", Format_Decimal, "#0.0", "0.5", "20", Setting_IsExtendedFn, set_float, get_float, is_setting_available, { .allow_null = On } }, - { Setting_SpindleType, Group_Spindle, "Default spindle", NULL, Format_RadioButtons, spindle_types, NULL, NULL, Setting_IsExtendedFn, set_default_spindle, get_int, is_setting_available }, + { Setting_SpindleType, Group_Spindle, "Default spindle", NULL, Format_RadioButtons, spindle_types, NULL, NULL, Setting_IsExtendedFn, set_default_spindle, get_int, is_setting_available, { .reboot_required = On } }, { Setting_PlannerBlocks, Group_General, "Planner buffer blocks", NULL, Format_Int16, "####0", "30", "1000", Setting_IsExtended, &settings.planner_buffer_blocks, NULL, NULL, { .reboot_required = On } }, { Setting_AutoReportInterval, Group_General, "Autoreport interval", "ms", Format_Int16, "###0", "100", "1000", Setting_IsExtendedFn, set_report_interval, get_int, NULL, { .reboot_required = On, .allow_null = On } }, // { Setting_TimeZoneOffset, Group_General, "Timezone offset", NULL, Format_Decimal, "-#0.00", "0", "12", Setting_IsExtended, &settings.timezone, NULL, NULL }, @@ -2841,9 +2840,9 @@ bool settings_iterator (const setting_detail_t *setting, setting_output_ptr call return ok; } -const setting_detail_t *setting_get_details (setting_id_t id, setting_details_t **set) +static inline const setting_detail_t *_setting_get_details (setting_id_t id, uint_fast16_t offset, setting_details_t **set) { - uint_fast16_t idx, offset = id - normalize_id(id); + uint_fast16_t idx; setting_details_t *details = settings_get_details(); id -= offset; @@ -2869,6 +2868,37 @@ const setting_detail_t *setting_get_details (setting_id_t id, setting_details_t return NULL; } +const setting_detail_t *setting_get_details (setting_id_t id, setting_details_t **set) +{ + const setting_detail_t *detail; + + if((detail = _setting_get_details(id, id - normalize_id(id), set)) == NULL) { + + uint_fast16_t idx, offset; + setting_details_t *details = settings_get_details(); + + do { + if(details->normalize && (offset = id - details->normalize(id))) { + + id -= offset; + + for(idx = 0; idx < details->n_settings; idx++) { + if(details->settings[idx].id == id && is_available(&details->settings[idx], offset)) { + + detail = &details->settings[idx]; + + if(set) + *set = details; + } + } + break; + } + } while((details = details->next)); + } + + return detail; +} + const char *setting_get_description (setting_id_t id) { const char *description = NULL; diff --git a/settings.h b/settings.h index 32a1202..238cbc5 100644 --- a/settings.h +++ b/settings.h @@ -509,10 +509,11 @@ typedef enum { Setting_ActionPort8 = 768, Setting_ActionPort9 = 769, - Setting_SpindleOffsetX = 770, - Setting_SpindleOffsetY = 771, + Setting_SpindleOffsetX = 770, + Setting_SpindleOffsetY = 771, + Setting_SpindleOffsetOptions = 772, // -// 772-779 - reserved for spindle offset settings +// 773-779 - reserved for spindle offset settings // // Reserving settings in the range 800 - 899 for axis settings. @@ -1074,6 +1075,7 @@ typedef void (*driver_settings_load_ptr)(void); typedef void (*driver_settings_save_ptr)(void); typedef void (*driver_settings_restore_ptr)(void); typedef bool (*driver_settings_iterator_ptr)(const setting_detail_t *setting, setting_output_ptr callback, void *data); +typedef setting_id_t (*driver_settings_normalize_ptr)(setting_id_t id); typedef struct setting_details { const bool is_core; @@ -1092,6 +1094,7 @@ typedef struct setting_details { driver_settings_load_ptr load; driver_settings_restore_ptr restore; driver_settings_iterator_ptr iterator; + driver_settings_normalize_ptr normalize; } setting_details_t; // NOTE: this must match the signature of on_get_settings in the setting_details_t structure above! @@ -1105,7 +1108,7 @@ void settings_clear (void); // Initialize the configuration subsystem (load settings from persistent storage) void settings_init(); -// Write Grbl global settings and version number to persistent storage +// Write grblHAL global settings and version number to persistent storage void settings_write_global(void); // Helper function to clear and restore persistent storage defaults diff --git a/spindle_control.c b/spindle_control.c index 8edbccf..099fdea 100644 --- a/spindle_control.c +++ b/spindle_control.c @@ -332,7 +332,7 @@ static spindle_num_t spindle_get_num (spindle_id_t spindle_id) do { idx--; if((setting = setting_get_details(idx == 0 ? Setting_SpindleType : (setting_id_t)(Setting_SpindleEnable0 + idx), NULL))) { - if(setting_get_int_value(setting, 0) - (idx == 0 ? 0 : 1) == spindle_id) + if(setting_get_int_value(setting, setting->flags.increment ? idx : 0) - (idx == 0 ? 0 : 1) == spindle_id) spindle_num = idx; } } while(idx && spindle_num == -1); @@ -652,6 +652,9 @@ static bool spindle_set_state_wait (spindle_ptrs_t *spindle, spindle_state_t sta ok &= at_speed; } } + + if(ok && grbl.on_spindle_at_speed) + grbl.on_spindle_at_speed(spindle, state); } return ok; diff --git a/spindle_control.h b/spindle_control.h index 9e2bcfd..6c19fe3 100644 --- a/spindle_control.h +++ b/spindle_control.h @@ -209,7 +209,8 @@ typedef union { uint8_t enable_rpm_controlled :1, // PWM spindle only laser_mode_disable :1, // PWM spindle only pwm_disable :1, // PWM spindle only - unassigned :5; + g92offset :1, + unassigned :4; }; } spindle_settings_flags_t;