From ee1cd5a7454c29e2ad13f5364d2d0b4fb7f1e07f Mon Sep 17 00:00:00 2001 From: Terje Io Date: Wed, 6 Aug 2025 18:32:29 +0200 Subject: [PATCH] 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. --- changelog.md | 23 +++++++++++++++++++- core_handlers.h | 6 +++--- grbl.h | 2 +- ioports.c | 52 +++++++++++++++++++++++---------------------- kinematics/corexy.c | 6 +++--- kinematics/delta.c | 12 +++++------ machine_limits.c | 22 +++++++++---------- motion_control.c | 8 +++---- spindle_control.c | 2 +- 9 files changed, 78 insertions(+), 55 deletions(-) diff --git a/changelog.md b/changelog.md index e3808f0..3195db4 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,26 @@ ## grblHAL changelog +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. + +--- + 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: diff --git a/core_handlers.h b/core_handlers.h index 6dc9936..f1255a9 100644 --- a/core_handlers.h +++ b/core_handlers.h @@ -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); diff --git a/grbl.h b/grbl.h index 2b53b1d..6ac07d8 100644 --- a/grbl.h +++ b/grbl.h @@ -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" diff --git a/ioports.c b/ioports.c index f49e975..8648344 100644 --- a/ioports.c +++ b/ioports.c @@ -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); diff --git a/kinematics/corexy.c b/kinematics/corexy.c index 022aacd..ad54ee2 100644 --- a/kinematics/corexy.c +++ b/kinematics/corexy.c @@ -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. diff --git a/kinematics/delta.c b/kinematics/delta.c index 5e76020..2ef9b73 100644 --- a/kinematics/delta.c +++ b/kinematics/delta.c @@ -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)) { diff --git a/machine_limits.c b/machine_limits.c index 3ebcce7..6770911 100644 --- a/machine_limits.c +++ b/machine_limits.c @@ -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); } diff --git a/motion_control.c b/motion_control.c index 8ef5bc5..9495bd9 100644 --- a/motion_control.c +++ b/motion_control.c @@ -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--; diff --git a/spindle_control.c b/spindle_control.c index 099fdea..f3f6a6f 100644 --- a/spindle_control.c +++ b/spindle_control.c @@ -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);