Improved ioport remapping of auxiliary pins (used by plasma plugin).

Changed signature of limit check functions, grbl.travel_limits() et. al.
to include a pointer to the work envelope to use.
Updated spindle off handling to check for "at speed" on deceleration when spindle is "at speed" capable.
This commit is contained in:
Terje Io
2025-08-06 18:32:29 +02:00
parent 255d02b020
commit ee1cd5a745
9 changed files with 78 additions and 55 deletions
+22 -1
View File
@@ -1,5 +1,26 @@
## grblHAL changelog
<a name="20250806">Build 20250806
Core:
* Improved ioport remapping of auxiliary pins \(used by plasma plugin\).
* Changed signature of limit check functions, [grbl.travel_limits()](https://svn.io-engineering.com/grblHAL/html/core__handlers_8h.html#a56eced06d1c379782d86c2f139cd3f96) et. al. to include a pointer to the work envelope to use.
This may simplify implementations of plugins that want to alter the envelope.
* Updated spindle off handling to check for "at speed" on deceleration when spindle is "at speed" capable
Drivers:
* STM32F4xx, STM32F7xx: fix for I2C transmits sometimes blocking when they should not. Will cause I2C displays to fail.
Plugins:
* Plasma: improved/fixed handling of virtual auxiliary ports.
---
<a name="20250802">20250802
Core:
@@ -10,7 +31,7 @@ Drivers:
* ESP32: added missing define for I2C for MKS DLC 32 v2.0 board. Ref. discussion comment in [#645](https://github.com/grblHAL/core/discussions/645#discussioncomment-13960933)
* RP2040: added tentative support for Mesa THCAD2 voltage to frequency converter. Not complete!
* RP2040: added tentative support for [Mesa THCAD2](https://mesaus.com/product/thcad2/) voltage to frequency converter. Not complete!
Added option for using Aux out 1 for Neopixels on the RP23U5XBB board. Ref. discussion [#143](https://github.com/grblHAL/RP2040/discussions/143).
Plugins:
+3 -3
View File
@@ -78,10 +78,10 @@ typedef struct {
typedef bool (*enqueue_gcode_ptr)(char *data);
typedef bool (*protocol_enqueue_realtime_command_ptr)(char c);
typedef bool (*travel_limits_ptr)(float *target, axes_signals_t axes, bool is_cartesian);
typedef bool (*arc_limits_ptr)(coord_data_t *target, coord_data_t *position, point_2d_t center, float radius, plane_t plane, int32_t turns);
typedef bool (*travel_limits_ptr)(float *target, axes_signals_t axes, bool is_cartesian, work_envelope_t *envelope);
typedef bool (*arc_limits_ptr)(coord_data_t *target, coord_data_t *position, point_2d_t center, float radius, plane_t plane, int32_t turns, work_envelope_t *envelope);
typedef void (*apply_travel_limits_ptr)(float *target, float *position);
typedef void (*apply_travel_limits_ptr)(float *target, float *position, work_envelope_t *envelope);
typedef bool (*home_machine_ptr)(axes_signals_t cycle, axes_signals_t auto_square);
typedef void (*on_parser_init_ptr)(parser_state_t *gc_state);
+1 -1
View File
@@ -42,7 +42,7 @@
#else
#define GRBL_VERSION "1.1f"
#endif
#define GRBL_BUILD 20250731
#define GRBL_BUILD 20250806
#define GRBL_URL "https://github.com/grblHAL"
+27 -25
View File
@@ -553,31 +553,6 @@ bool ioport_digital_pwm_config (uint8_t port, pwm_config_t *config)
return ok && pin->config(pin, config, false);
}
/*! \brief Remap (virtual) port.
\param type as an \a #io_port_type_t enum value.
\param dir as an \a #io_port_direction_t enum value.
\param port_from the assigned port number.
\param port_to the remapped port number. The original port number will be shadowed.
\returns \a true if successful, \a false if original port is already claimed.
*/
bool ioport_remap (io_port_type_t type, io_port_direction_t dir, uint8_t port_from, uint8_t port_to)
{
uint8_t org_port;
bool ok;
io_ports_private_t *cfg = get_port_data(type, dir);
if((ok = (cfg->claimed.mask & (1UL << port_to))) == 0) {
if((org_port = map_reverse(cfg, port_from)) != port_to)
cfg->map[org_port] = 255;
cfg->free = -1;
cfg->map[port_to] = port_from;
}
return ok;
}
// HAL wrapper/veneers
__STATIC_FORCEINLINE bool is_match (io_ports_list_t *io_port, io_port_type_t type, io_port_direction_t dir, uint8_t port)
@@ -902,6 +877,33 @@ static bool _ioports_add (io_ports_data_t *ports, io_port_type_t type, uint8_t n
return n_ports > 0;
}
/*! \brief Remap (virtual) port.
\param type as an \a #io_port_type_t enum value.
\param dir as an \a #io_port_direction_t enum value.
\param port_from the assigned port number.
\param port_to the remapped port number. The original port number will be swapped with \a port_from.
\returns \a true if successful, \a false if original port is already claimed.
*/
bool ioport_remap (io_port_type_t type, io_port_direction_t dir, uint8_t port_from, uint8_t port_to)
{
uint8_t org_port;
bool ok;
io_ports_private_t *cfg = get_port_data(type, dir);
if((ok = (cfg->claimed.mask & (1UL << cfg->map[port_to])) == 0)) {
if((org_port = map_reverse(cfg, port_from)) != port_to) {
cfg->map[org_port] = cfg->map[port_to];
hal.port.set_pin_description(type, dir, org_port, pnum_to_string(org_port, cfg->pnum));
}
cfg->free = -1;
cfg->map[port_to] = port_from;
}
return ok;
}
bool ioports_add (io_ports_data_t *ports, io_port_type_t type, uint8_t n_in, uint8_t n_out)
{
return hal.port.get_pin_info != io_get_pin_info && _ioports_add(ports, type, n_in, n_out, hal.port.set_pin_description);
+3 -3
View File
@@ -118,16 +118,16 @@ static void corexy_limits_set_target_pos (uint_fast8_t idx) // fn name?
// Checks and reports if target array exceeds machine travel limits. Returns false if check failed.
// NOTE: target for axes X and Y are in motor coordinates if is_cartesian is false.
static bool corexy_check_travel_limits (float *target, axes_signals_t axes, bool is_cartesian)
static bool corexy_check_travel_limits (float *target, axes_signals_t axes, bool is_cartesian, work_envelope_t *envelope)
{
if(is_cartesian)
return check_travel_limits(target, axes, true);
return check_travel_limits(target, axes, true, envelope);
float cartesian_coords[N_AXIS];
transform_to_cartesian(cartesian_coords, target);
return check_travel_limits(cartesian_coords, axes, true);
return check_travel_limits(cartesian_coords, axes, true, envelope);
}
// Set machine positions for homed limit switches. Don't update non-homed axes.
+6 -6
View File
@@ -234,7 +234,7 @@ static float *delta_segment_line (float *target, float *position, plan_line_data
if(!pl_data->condition.target_validated) {
pl_data->condition.target_validated = On;
pl_data->condition.target_valid = grbl.check_travel_limits(mpos.values, sys.soft_limits, false);
pl_data->condition.target_valid = grbl.check_travel_limits(mpos.values, sys.soft_limits, false, &sys.work_envelope);
}
transform_to_cartesian(segment_target.values, position);
@@ -576,14 +576,14 @@ static inline bool pos_ok (coord_data_t *pos)
}
// Checks and reports if target array exceeds machine travel limits. Returns false if check failed.
static bool delta_check_travel_limits (float *target, axes_signals_t axes, bool is_cartesian)
static bool delta_check_travel_limits (float *target, axes_signals_t axes, bool is_cartesian, work_envelope_t *envelope)
{
bool failed = false;
uint_fast8_t idx = N_AXIS;
coord_data_t pos;
#if N_AXIS > 3
if((axes.mask & ~0b111) && !check_travel_limits(target, (axes_signals_t){ axes.mask & ~0b111 }, is_cartesian))
if((axes.mask & ~0b111) && !check_travel_limits(target, (axes_signals_t){ axes.mask & ~0b111 }, is_cartesian, envelope))
return false;
#endif
@@ -607,7 +607,7 @@ static bool delta_check_travel_limits (float *target, axes_signals_t axes, bool
idx--;
if(bit_istrue(sys.homed.mask, bit(idx)) && settings.axis[idx].max_travel < -0.0f) {
if(idx > Z_AXIS)
failed = target[idx] < sys.work_envelope.min.values[idx] || target[idx] > sys.work_envelope.max.values[idx];
failed = target[idx] < envelope->min.values[idx] || target[idx] > envelope->max.values[idx];
else
failed = pos.values[idx] < machine.min_angle[idx] || pos.values[idx] > machine.max_angle[idx];
}
@@ -616,13 +616,13 @@ static bool delta_check_travel_limits (float *target, axes_signals_t axes, bool
return !failed;
}
static void delta_apply_travel_limits (float *target, float *position)
static void delta_apply_travel_limits (float *target, float *position, work_envelope_t *envelope)
{
if(sys.homed.mask == 0)
return;
if(machine.cfg.flags.limit_to_cuboid)
apply_travel_limits(target, position);
apply_travel_limits(target, position, envelope);
else if(position && !is_target_inside_cuboid(target, true)) {
+11 -11
View File
@@ -607,9 +607,9 @@ status_code_t limits_go_home (axes_signals_t cycle)
void limits_soft_check (float *target, planner_cond_t condition)
{
#ifdef KINEMATICS_API
if(condition.target_validated ? !condition.target_valid : !grbl.check_travel_limits(target, sys.soft_limits, false)) {
if(condition.target_validated ? !condition.target_valid : !grbl.check_travel_limits(target, sys.soft_limits, false, &sys.work_envelope)) {
#else
if(condition.target_validated ? !condition.target_valid : !grbl.check_travel_limits(target, sys.soft_limits, true)) {
if(condition.target_validated ? !condition.target_valid : !grbl.check_travel_limits(target, sys.soft_limits, true, &sys.work_envelope)) {
#endif
sys.flags.soft_limit = On;
@@ -663,7 +663,7 @@ static float get_homing_rate (axes_signals_t cycle, homing_mode_t mode)
}
// Checks and reports if target array exceeds machine travel limits. Returns false if check failed.
static bool check_travel_limits (float *target, axes_signals_t axes, bool is_cartesian)
static bool check_travel_limits (float *target, axes_signals_t axes, bool is_cartesian, work_envelope_t *envelope)
{
bool failed = false;
uint_fast8_t idx = N_AXIS;
@@ -671,7 +671,7 @@ static bool check_travel_limits (float *target, axes_signals_t axes, bool is_car
if(is_cartesian && (sys.homed.mask & axes.mask)) do {
idx--;
if(bit_istrue(sys.homed.mask, bit(idx)) && bit_istrue(axes.mask, bit(idx)))
failed = target[idx] < sys.work_envelope.min.values[idx] || target[idx] > sys.work_envelope.max.values[idx];
failed = target[idx] < envelope->min.values[idx] || target[idx] > envelope->max.values[idx];
} while(!failed && idx);
return is_cartesian && !failed;
@@ -679,7 +679,7 @@ static bool check_travel_limits (float *target, axes_signals_t axes, bool is_car
// Checks and reports if the arc exceeds machine travel limits. Returns false if check failed.
// NOTE: needs the work envelope to be a cuboid!
static bool check_arc_travel_limits (coord_data_t *target, coord_data_t *position, point_2d_t center, float radius, plane_t plane, int32_t turns)
static bool check_arc_travel_limits (coord_data_t *target, coord_data_t *position, point_2d_t center, float radius, plane_t plane, int32_t turns, work_envelope_t *envelope)
{
typedef union {
uint_fast8_t value;
@@ -694,7 +694,7 @@ static bool check_arc_travel_limits (coord_data_t *target, coord_data_t *positio
static const axes_signals_t xyz = { .x = On, .y = On, .z = On };
if((sys.soft_limits.mask & xyz.mask) == 0)
return grbl.check_travel_limits(target->values, sys.soft_limits, true);
return grbl.check_travel_limits(target->values, sys.soft_limits, true, envelope);
arc_x_t x = {0};
point_2d_t start, end;
@@ -764,14 +764,14 @@ static bool check_arc_travel_limits (coord_data_t *target, coord_data_t *positio
corner1.values[plane.axis_0] = x.neg_x ? center.x - radius : min(position->values[plane.axis_0], target->values[plane.axis_0]);
corner1.values[plane.axis_1] = x.neg_y ? center.y - radius : max(position->values[plane.axis_1], target->values[plane.axis_1]);
if(!grbl.check_travel_limits(corner1.values, sys.soft_limits, true))
if(!grbl.check_travel_limits(corner1.values, sys.soft_limits, true, envelope))
return false;
memcpy(&corner2, turns > 0 ? target : position, sizeof(coord_data_t));
corner2.values[plane.axis_0] = x.pos_x ? center.x + radius : max(position->values[plane.axis_0], target->values[plane.axis_0]);
corner2.values[plane.axis_1] = x.pos_y ? center.y + radius : min(position->values[plane.axis_1], target->values[plane.axis_1]);
return grbl.check_travel_limits(corner2.values, sys.soft_limits, true);
return grbl.check_travel_limits(corner2.values, sys.soft_limits, true, envelope);
}
// Derived from code by Dimitrios Matthes & Vasileios Drakopoulos
@@ -815,7 +815,7 @@ static void clip_3d_target (coord_data_t *position, coord_data_t *target, work_e
// Limits jog commands to be within machine limits, homed axes only.
// If position is non-null clip XYZ motion.
static void apply_travel_limits (float *target, float *position)
static void apply_travel_limits (float *target, float *position, work_envelope_t *envelope)
{
if(sys.homed.mask == 0)
return;
@@ -834,14 +834,14 @@ static void apply_travel_limits (float *target, float *position)
} while(idx && n_axes < 2);
if(n_axes > 1)
clip_3d_target((coord_data_t *)position, (coord_data_t *)target, &sys.work_envelope);
clip_3d_target((coord_data_t *)position, (coord_data_t *)target, envelope);
}
idx = N_AXIS;
do {
idx--;
if(bit_istrue(sys.homed.mask, bit(idx)) && settings.axis[idx].max_travel < -0.0f)
target[idx] = max(min(target[idx], sys.work_envelope.max.values[idx]), sys.work_envelope.min.values[idx]);
target[idx] = max(min(target[idx], envelope->max.values[idx]), envelope->min.values[idx]);
} while(idx);
}
+4 -4
View File
@@ -246,7 +246,7 @@ void mc_arc (float *target, plan_line_data_t *pl_data, float *position, float *o
pl_data->condition.target_validated = On;
pl_data->condition.target_valid = grbl.check_arc_travel_limits((coord_data_t *)target, (coord_data_t *)position,
(point_2d_t){ .x = (float)center.x, .y = (float)center.y },
radius, plane, turns);
radius, plane, turns, &sys.work_envelope);
}
if(labs(turns) > 1) {
@@ -795,8 +795,8 @@ status_code_t mc_jog_execute (plan_line_data_t *pl_data, parser_block_t *gc_bloc
pl_data->line_number = gc_block->values.n;
if(settings.limits.flags.jog_soft_limited)
grbl.apply_travel_limits(gc_block->values.xyz, position);
else if(sys.soft_limits.mask && !grbl.check_travel_limits(gc_block->values.xyz, sys.soft_limits, true))
grbl.apply_travel_limits(gc_block->values.xyz, position, &sys.work_envelope);
else if(sys.soft_limits.mask && !grbl.check_travel_limits(gc_block->values.xyz, sys.soft_limits, true, &sys.work_envelope))
return Status_TravelExceeded;
// Valid jog command. Plan, set state, and execute.
@@ -987,7 +987,7 @@ gc_probe_t mc_probe_cycle (float *target, plan_line_data_t *pl_data, gc_parser_f
return GCProbe_CheckMode;
if(settings.probe.soft_limited)
grbl.apply_travel_limits(target, NULL);
grbl.apply_travel_limits(target, NULL, &sys.work_envelope);
do {
idx--;
+1 -1
View File
@@ -631,7 +631,7 @@ static bool spindle_set_state_wait (spindle_ptrs_t *spindle, spindle_state_t sta
if((ok = spindle_set_state(spindle, state, rpm))) {
bool at_speed = !state.on || spindle->cap.torch || !spindle->cap.at_speed || spindle->at_speed_tolerance <= 0.0f;
bool at_speed = !spindle->cap.at_speed || spindle->cap.torch || spindle->at_speed_tolerance <= 0.0f;
if(at_speed)
ok = delay_ms == 0 || spindle->cap.torch || delay_sec((float)delay_ms / 1000.0f, delay_mode);