Fix for optional control signals not respecting $14 inversion setting. Ref. issue #780.

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.
This commit is contained in:
Terje Io
2025-07-24 08:25:25 +02:00
parent f951c266ac
commit 5aff8fe767
10 changed files with 76 additions and 25 deletions

View File

@@ -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.

View File

@@ -1,6 +1,23 @@
## grblHAL changelog
<a name="20250720>Build 20250720
<a name="20250724">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.
---
<a name="20250720">Build 20250720
Core:

View File

@@ -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;

2
grbl.h
View File

@@ -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"

View File

@@ -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
};

View File

@@ -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;
}

View File

@@ -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;

View File

@@ -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

View File

@@ -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;

View File

@@ -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;