Refactored assignment of of auxiliary I/O for "standard" inputs and outputs to make it more robust and easier to follow for developers.

Moved probe signal handling from drivers to the core, improved handling of probe disconnected signal.
NOTE: The changes above are quite large, please verify probe operation after installation.
This commit is contained in:
Terje Io
2025-10-16 17:22:32 +02:00
parent 0679a0c6d4
commit 106f5fd573
21 changed files with 583 additions and 299 deletions

View File

@@ -16,6 +16,7 @@ target_sources(grbl INTERFACE
${CMAKE_CURRENT_LIST_DIR}/nuts_bolts.c
${CMAKE_CURRENT_LIST_DIR}/override.c
${CMAKE_CURRENT_LIST_DIR}/planner.c
${CMAKE_CURRENT_LIST_DIR}/probe.c
${CMAKE_CURRENT_LIST_DIR}/protocol.c
${CMAKE_CURRENT_LIST_DIR}/report.c
${CMAKE_CURRENT_LIST_DIR}/settings.c

View File

@@ -1,6 +1,6 @@
## grblHAL ##
Latest build date is 20251011, see the [changelog](changelog.md) for details.
Latest build date is 20251016, 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,5 +1,28 @@
## grblHAL changelog
<a name="20251016">Build 20251016
Core:
* Refactored assignment of of auxiliary I/O for "standard" inputs and outputs to make it more robust and easier to follow for developers.
* Moved probe signal handling from drivers to the core, improved handling of probe disconnected signal.
> [!NOTE]
> The changes above are quite large, please verify probe operation after installation.
Drivers:
* All: updated for move of probe signal handling to the core.
* RP2040: fixed "leak" of stepper signals between axes when plasma plugin is enabled, affects the PicoCNC board.
* ESP32: fix for compilation failure for boards using the SDIO interface for SD card interface.
* STM32F4xx: SuperLongBoards, now returns unambigous values for `_probe_state` and `_toolsetter_state` system parameters.
---
<a name="20251015">20251015
Drivers:
@@ -8,7 +31,7 @@ Drivers:
Plugins:
* Keypad, macros: "hardened" code to avoid hardfault when macros settings data is bad.
* Keypad, macros: "hardened" code to avoid hardfault when macros settings data are bad.
---

View File

@@ -736,7 +736,7 @@ If set to \ref Off or 0 the `|DTG:` distance-to-go element is not included in th
\internal Bit 13 in settings.status_report.
*/
#if !defined DEFAULT_REPORT_DISTANCE_TO_GO || defined __DOXYGEN__
#define DEFAULT_REPORT_DISTANCE_TO_GO On // Default on. Set to \ref Off or 0 to disable.
#define DEFAULT_REPORT_DISTANCE_TO_GO Off // Default off. Set to \ref On or 1 to enable.
#endif
///@}
@@ -933,14 +933,13 @@ Enable this setting to feedrate override over a soft reset.
///@}
// Control signals settings (Group_ControlSignals)
#ifndef __DOXYGEN__ // For now do not include in documentation
/*! @name Control signals bit definitions and mask.
__NOTE:__ these definitions are only referenced in this file. Do __NOT__ change!
__NOTE:__ Do __NOT__ change! Definitions MUST match #control_signals_t struct bit order.
*/
///@{
#define SIGNALS_RESET_BIT (1<<0)
@@ -952,6 +951,12 @@ __NOTE:__ these definitions are only referenced in this file. Do __NOT__ change!
#define SIGNALS_ESTOP_BIT (1<<6)
#define SIGNALS_PROBE_CONNECTED_BIT (1<<7)
#define SIGNALS_MOTOR_FAULT_BIT (1<<8)
#define SIGNALS_MOTOR_WARNING_BIT (1<<9)
#define SIGNALS_LIMITS_OVERRIDE_BIT (1<<10)
#define SIGNALS_SINGLE_BLOCK_BIT (1<<11)
#define SIGNALS_TLS_OVERTRAVEL_BIT (1<<12)
#define SIGNALS_PROBE_OVERTRAVEL (1<<13)
#define SIGNALS_PROBE_TRIGGERED_BIT (1<<14)
#define SIGNALS_BITMASK (SIGNALS_RESET_BIT|SIGNALS_FEEDHOLD_BIT|SIGNALS_CYCLESTART_BIT|SIGNALS_SAFETYDOOR_BIT|SIGNALS_BLOCKDELETE_BIT|SIGNALS_STOPDISABLE_BIT|SIGNALS_ESTOP_BIT|SIGNALS_PROBE_CONNECTED_BIT|SIGNALS_MOTOR_FAULT_BIT)
///@}

View File

@@ -38,7 +38,7 @@ typedef enum {
Input_MotorWarning,
Input_LimitsOverride,
Input_SingleBlock,
Input_Unassigned,
Input_ToolsetterOvertravel,
Input_ProbeOvertravel,
Input_Probe,
// end control_signals_t sequence
@@ -56,7 +56,6 @@ typedef enum {
Input_Probe2,
Input_Probe2Overtravel,
Input_Toolsetter,
Input_ToolsetterOvertravel,
Input_MPGSelect,
Input_ModeSelect = Input_MPGSelect, // Deprecated
Input_LimitX,
@@ -726,22 +725,27 @@ typedef bool (*xbar_set_function_ptr)(struct xbar *pin, pin_function_t function)
typedef void (*xbar_event_ptr)(bool on);
typedef bool (*xbar_config_ptr)(struct xbar *pin, xbar_cfg_ptr_t cfg_data, bool persistent);
// MCU port base address and pin number
typedef struct {
pin_function_t function;
uint8_t aux_port;
pin_irq_mode_t irq_mode;
control_signals_t cap;
uint8_t pin;
void *port;
void *input;
void *port; //!< MCU port address (may be NULL).
uint8_t pin; //!< MCU pin number.
} aux_gpio_t;
typedef struct {
pin_function_t function; //!< Pin function.
uint8_t port; //!< Auxiliary port number, post claimed.
pin_irq_mode_t irq_mode; //!< Required IRQ mode for the input.
control_signals_t signal; //!< Set to the pin the input maps to, 0 if none.
aux_gpio_t gpio; //!< MCU port base address (may be NULL) and pin number.
void *input; //!< Pointer to the driver input array entry for the pin.
bool scan; //!< true if the pin is to be scanned when control state is requested.
} aux_ctrl_t;
typedef struct {
pin_function_t function;
uint8_t aux_port;
uint8_t pin;
void *port;
void *output;
pin_function_t function; //!< Pin function.
uint8_t port; //!< Auxiliary port number, post claimed.
aux_gpio_t gpio; //!< MCU port base address (may be NULL) and pin number.
void *output; //!< Pointer to the driver input array entry for the pin.
} aux_ctrl_out_t;
typedef struct xbar {
@@ -806,6 +810,11 @@ static inline bool xbar_stepper_state_get (stepper_state_t state, uint8_t axis,
return bit_istrue(b ? state.details.b.bits : state.details.a.bits, bit(axis));
}
static inline bool xbar_is_probe_in (pin_function_t fn)
{
return fn == Input_Probe || fn == Input_Probe2 || fn == Input_Toolsetter;
}
void xbar_set_homing_source (void);
limit_signals_t xbar_get_homing_source (void);
limit_signals_t xbar_get_homing_source_from_cycle (axes_signals_t homing_cycle);

2
grbl.h
View File

@@ -42,7 +42,7 @@
#else
#define GRBL_VERSION "1.1f"
#endif
#define GRBL_BUILD 20251011
#define GRBL_BUILD 20251016
#define GRBL_URL "https://github.com/grblHAL"

View File

@@ -411,6 +411,9 @@ int grbl_enter (void)
if(grbl.on_probe_toolsetter == NULL && hal.driver_cap.toolsetter && hal.probe.select)
grbl.on_probe_toolsetter = onProbeToolsetter;
if(hal.driver_cap.probe && hal.signals_cap.probe_disconnected)
task_run_on_startup(probe_connected_event, hal.control.get_state().probe_disconnected ? NULL : (void *)1);
// Initialization loop upon power-up or a system abort. For the latter, all processes
// will return to this loop to be cleanly re-initialized.
while(looping) {

18
hal.h
View File

@@ -373,6 +373,12 @@ __NOTE:__ this function will be called from an interrupt context.
*/
typedef probe_state_t (*probe_get_state_ptr)(void);
/*! \brief Pointer to function for getting triggered status for a specific probe.
\param probe_id probe number. 0 - default probe, 1 - toolsetter, ...
\returns \a true if triggered, \a false otherwise.
*/
typedef bool (*probe_is_triggered_ptr)(probe_id_t probe_id);
/*! \brief Pointer to function for setting probe operation mode.
\param is_probe_away true if probing away from the workpiece, false otherwise. When probing away the signal must be inverted in the probe_get_state_ptr() implementation.
\param probing true if probe cycle is active, false otherwise.
@@ -381,13 +387,17 @@ typedef void (*probe_configure_ptr)(bool is_probe_away, bool probing);
/*! \brief Pointer to function for selecting probe input.
\param probe_id probe number. 0 - default probe, 1 - toolsetter, ...
\returns true if selectetion succeded, false otherwise.
\returns true if selection succeded, false otherwise.
*/
typedef bool (*probe_select_ptr)(probe_id_t probe_id);
/*! \brief Pointer to function for getting probe capabilities.
\param probe_id probe number. 0 - default probe, 1 - toolsetter, ...
\returns a \a probe_flags_t struct.
*/
typedef probe_flags_t (*probe_get_caps_ptr)(probe_id_t probe_id);
/*! \brief Pointer to function for toggling probe connected status.
If the driver does not support a probe connected input signal this can be used to implement
toggling of probe connected status via a #CMD_PROBE_CONNECTED_TOGGLE real time command.
*/
@@ -397,7 +407,9 @@ typedef void (*probe_connected_toggle_ptr)(void);
typedef struct {
probe_configure_ptr configure; //!< Optional handler for setting probe operation mode.
probe_get_state_ptr get_state; //!< Optional handler for getting probe status. Called from interrupt context.
probe_is_triggered_ptr is_triggered; //!< Optional handler for getting probe triggered status.
probe_select_ptr select; //!< Optional handler for selecting probe to use.
probe_get_caps_ptr get_caps; //!< Optional handler for getting probe capabilities.
probe_connected_toggle_ptr connected_toggle; //!< Optional handler for toggling probe connected status.
} probe_ptrs_t;

View File

@@ -352,12 +352,12 @@ void ioport_assign_function (aux_ctrl_t *aux_ctrl, pin_function_t *function)
{
xbar_t *input;
if((input = hal.port.get_pin_info(Port_Digital, Port_Input, aux_ctrl->aux_port))) {
if((input = hal.port.get_pin_info(Port_Digital, Port_Input, aux_ctrl->port))) {
*function = aux_ctrl->function;
ports_cfg[Port_DigitalIn].bus.mask &= ~(1 << input->id);
ports_cfg[Port_DigitalIn].count = ports_cfg[Port_DigitalIn].free = -1;
hal.signals_cap.mask |= aux_ctrl->cap.mask;
hal.signals_cap.mask |= aux_ctrl->signal.mask;
if(aux_ctrl->function == Input_Probe || xbar_fn_to_signals_mask(aux_ctrl->function).mask)
setting_remove_elements(Settings_IoPort_InvertIn, ports_cfg[Port_DigitalIn].bus.mask);
@@ -369,7 +369,7 @@ void ioport_assign_out_function (aux_ctrl_out_t *aux_ctrl, pin_function_t *funct
{
xbar_t *output;
if((output = hal.port.get_pin_info(Port_Digital, Port_Output, aux_ctrl->aux_port))) {
if((output = hal.port.get_pin_info(Port_Digital, Port_Output, aux_ctrl->port))) {
*function = aux_ctrl->function;
ports_cfg[Port_DigitalOut].bus.mask &= ~(1UL << output->id);

View File

@@ -409,10 +409,10 @@ static inline float interp (const float a, const float b, const float t)
}
/**
* Compute a B<EFBFBD>zier curve using the De Casteljau's algorithm (see
* Compute a Bezier curve using the De Casteljau's algorithm (see
* https://en.wikipedia.org/wiki/De_Casteljau's_algorithm), which is
* easy to code and has good numerical stability (very important,
* since Arudino works with limited precision real numbers).
* since Arduino works with limited precision real numbers).
*/
static inline float eval_bezier (const float a, const float b, const float c, const float d, const float t)
{

View File

@@ -612,40 +612,11 @@ float ngc_named_param_get_by_id (ncg_name_param_id_t id)
// grblHAL extensions
case NGCParam_probe_state:
value = -1.0f;
if(hal.probe.get_state /*&& hal.driver_cap.probe*/) {
probe_state_t probe_state = hal.probe.get_state();
if((probe_id_t)probe_state.probe_id == Probe_Default)
value = (float)probe_state.triggered;
else if(hal.probe.select) {
if(hal.probe.select(Probe_Default))
value = (float)hal.probe.get_state().triggered;
hal.probe.select((probe_id_t)probe_state.probe_id);
}
}
value = hal.driver_cap.probe && hal.probe.is_triggered ? (float)hal.probe.is_triggered(Probe_Default) : -1.0f;
break;
case NGCParam_toolsetter_state:
value = -1.0f;
if(hal.probe.get_state && hal.driver_cap.toolsetter) {
probe_state_t probe_state = hal.probe.get_state();
if((probe_id_t)probe_state.probe_id == Probe_Toolsetter)
value = (float)probe_state.triggered;
else if(hal.probe.select) {
if(hal.probe.select(Probe_Toolsetter))
value = (float)hal.probe.get_state().triggered;
hal.probe.select((probe_id_t)probe_state.probe_id);
} else
value = (float)probe_state.tls_triggered;
}
value = hal.driver_cap.toolsetter && hal.probe.is_triggered ? (float)hal.probe.is_triggered(Probe_Toolsetter) : -1.0f;
break;
case NGCParam_homed_state:

View File

@@ -246,6 +246,31 @@ typedef struct {
#pragma pack(pop)
// NOTE: the pin_function_t enum must be kept in sync with any changes!
typedef union {
uint16_t bits;
uint16_t mask;
uint16_t value;
struct {
uint16_t reset :1,
feed_hold :1,
cycle_start :1,
safety_door_ajar :1,
block_delete :1,
stop_disable :1, //! M1
e_stop :1,
probe_disconnected :1,
motor_fault :1,
motor_warning :1,
limits_override :1,
single_block :1,
tls_overtravel :1, //! used for probe (toolsetter) protection
probe_overtravel :1, //! used for probe protection
probe_triggered :1, //! used for probe protection
deasserted :1; //! this flag is set if signals are deasserted.
};
} control_signals_t;
typedef enum {
DelayMode_Dwell = 0,
DelayMode_SysSuspend

File diff suppressed because it is too large Load Diff

227
probe.c Normal file
View File

@@ -0,0 +1,227 @@
/*
probe.c - An embedded CNC Controller with rs274/ngc (g-code) support
Part of grblHAL
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
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
grblHAL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with grblHAL. If not, see <http://www.gnu.org/licenses/>.
*/
#include "hal.h"
typedef struct {
probe_id_t probe_id;
probe_flags_t flags;
probeflags_t inverted_bit;
uint8_t port;
void *input;
get_probe_input_ptr get_input;
} probe_t;
static probe_state_t probe_state = { .connected = On };
static probe_t probes[N_PROBE_MAX], *probe = NULL;
static void probe_irq_handler (uint8_t port, bool state)
{
if(probe_state.is_probing) {
probe_state.triggered = On;
if(!probe_state.was_probing) {
probe_state.was_probing = true;
}
} else {
control_signals_t signals = { .mask = hal.control.get_state().mask };
signals.probe_triggered = On;
hal.control.interrupt_callback(signals);
}
}
// Toggle probe connected status.
static void probe_connected_toggle (void)
{
if(!probe_state.is_probing) {
if((probe->flags.connected = probe_state.connected = !probe_state.connected)) {
if(probe->flags.watchable && settings.probe.enable_protection)
probe->flags.guarded = probe_state.irq_enabled = ioport_enable_irq(probe->port, IRQ_Mode_Change, probe_irq_handler);
} else if(probe->flags.guarded && ioport_enable_irq(probe->port, IRQ_Mode_None, probe_irq_handler))
probe->flags.guarded = probe_state.irq_enabled = Off;
if(settings.probe.enable_protection)
system_add_rt_report(Report_ProbeProtect);
}
}
// Sets up the probe pin invert mask to
// appropriately set the pin logic according to setting for normal-high/normal-low operation
// and the probing cycle modes for toward-workpiece/away-from-workpiece.
static void probe_configure (bool is_probe_away, bool probing)
{
bool invert = !!(settings.probe.value & probe->inverted_bit.value);
probe_state.inverted = is_probe_away ? !invert : invert;
if(probing) {
if(probe->flags.latchable) {
probe_state.is_probing = probe_state.was_probing = Off;
probe_state.triggered = hal.probe.get_state().triggered;
probe_state.irq_mode = probe_state.triggered ? IRQ_Mode_None : (probe_state.inverted ? IRQ_Mode_Falling : IRQ_Mode_Rising);
}
} else
probe_state.irq_mode = probe->flags.connected && probe->flags.watchable && settings.probe.enable_protection ? IRQ_Mode_Change : IRQ_Mode_None;
if(ioport_enable_irq(probe->port, probe_state.irq_mode, probe_irq_handler)) {
probe_state.irq_enabled = probe_state.irq_mode != IRQ_Mode_None;
probe->flags.guarded = !probing && probe_state.irq_enabled;
}
if(settings.probe.enable_protection)
system_add_rt_report(Report_ProbeProtect);
if(!probe_state.irq_enabled)
probe_state.triggered = Off;
probe_state.is_probing = probing;
}
static bool probe_select (probe_id_t probe_id)
{
uint_fast8_t idx = 0;
probe_t *selected_probe = NULL;
do {
if(probes[idx].probe_id == probe_id && probes[idx].get_input)
selected_probe = &probes[idx];
} while(selected_probe == NULL && ++idx < N_PROBE_MAX);
if(!probe_state.is_probing && selected_probe && selected_probe != probe) {
if(probe_state.irq_mode != IRQ_Mode_None)
ioport_enable_irq(probe->port, IRQ_Mode_None, probe_irq_handler);
probe = selected_probe;
hal.probe.configure(false, false);
}
return probe == selected_probe;
}
static probe_flags_t probe_get_caps (probe_id_t probe_id)
{
uint_fast8_t idx = 0;
probe_t *probe = NULL;
do {
if(probes[idx].probe_id == probe_id && probes[idx].get_input)
probe = &probes[idx];
} while(probe == NULL && ++idx < N_PROBE_MAX);
return probe ? probe->flags : (probe_flags_t){0};
}
static bool is_triggered (probe_id_t probe_id)
{
uint_fast8_t idx = 0;
probe_t *probe = NULL;
do {
if(probes[idx].probe_id == probe_id && probes[idx].get_input)
probe = &probes[idx];
} while(probe == NULL && ++idx < N_PROBE_MAX);
return !!probe && probe->get_input(probe->input) ^ !!(settings.probe.value & probe->inverted_bit.value);
}
// Returns the probe connected and triggered pin states.
static probe_state_t get_state (void)
{
probe_state_t state = { .value = probe_state.value };
state.probe_id = probe->probe_id;
state.connected = probe->flags.connected;
if(probe_state.is_probing && probe_state.irq_enabled)
state.triggered = probe_state.triggered;
else
state.triggered = probe->get_input(probe->input) ^ probe_state.inverted;
return state;
}
bool probe_add (probe_id_t probe_id, uint8_t port, pin_irq_mode_t irq_mode, void *input, get_probe_input_ptr get_input)
{
static uint_fast8_t n_probes = 0;
if(get_input == NULL || n_probes >= N_PROBE_MAX)
return false;
bool can_latch;
if(!(can_latch = (irq_mode & IRQ_Mode_RisingFalling) == IRQ_Mode_RisingFalling))
hal.signals_cap.probe_triggered = Off;
else if(n_probes == 0)
hal.signals_cap.probe_triggered = On;
probes[n_probes].probe_id = probe_id;
probes[n_probes].port = port;
probes[n_probes].flags.available = On;
probes[n_probes].flags.connected = probe_state.connected;
probes[n_probes].flags.latchable = can_latch;
probes[n_probes].flags.watchable = !!(irq_mode & IRQ_Mode_Change);
probes[n_probes].input = input;
probes[n_probes].get_input = get_input;
switch(probe_id) {
case Probe_Toolsetter:
probes[n_probes].inverted_bit.invert_toolsetter_input = On;
break;
case Probe_2:
probes[n_probes].inverted_bit.invert_probe2_input = On;
break;
default: // Probe_Default
probes[n_probes].inverted_bit.invert_probe_pin = On;
break;
}
hal.driver_cap.probe_pull_up = On;
hal.probe.configure = probe_configure;
hal.probe.connected_toggle = probe_connected_toggle;
hal.probe.get_caps = probe_get_caps;
hal.probe.get_state = get_state;
hal.probe.is_triggered = is_triggered;
if(probe == NULL || probe_id == Probe_Default)
probe = &probes[n_probes];
if(++n_probes == 2)
hal.probe.select = probe_select;
return true;
}
void probe_connected_event (void *data)
{
if(hal.probe.connected_toggle) {
if((uint32_t)data == 2)
hal.probe.connected_toggle();
else {
probe_state_t state = hal.probe.get_state();
if(state.probe_id == Probe_Default && hal.driver_cap.probe && state.connected != !!data)
hal.probe.connected_toggle();
}
}
}

40
probe.h
View File

@@ -22,8 +22,14 @@
#ifndef _PROBE_H_
#define _PROBE_H_
#include "crossbar.h"
#define N_PROBE_MAX 3
// Values that define the probing state machine.
typedef bool (*get_probe_input_ptr)(void *input);
typedef enum {
Probing_Off = 0, //!< 0
Probing_Active //!< 1
@@ -36,33 +42,33 @@ typedef enum {
} probe_id_t;
typedef union {
uint8_t value;
uint16_t value;
struct {
uint8_t triggered :1, //!< Set to true when probe or toolsetter is triggered.
connected :1, //!< Set to true when probe is connected. Always set to true if the driver does not have a probe connected input.
inverted :1, //!< For driver use
is_probing :1, //!< For driver use
irq_enabled :1, //!< For driver use
tls_triggered :1, //!< Set to true when toolsetter is triggered.
probe_id :2; //!< Id of active probe (for now).
uint16_t triggered :1, //!< Set to true when probe or toolsetter is triggered.
connected :1, //!< Set to true when probe is connected. Always set to true if the driver does not have a probe connected input.
inverted :1, //!< For driver use
is_probing :1, //!< For driver use
was_probing :1, //!< For driver use
irq_enabled :1, //!< For driver use
irq_mode :5, //!< pin_irq_mode_t - for driver use
unused :3,
probe_id :2; //!< Id of active probe (for now).
};
} probe_state_t;
typedef union {
uint8_t value;
struct {
uint8_t connected :1, //!< Set to true when probe is connected. Always set to true if the driver does not have a probe connected input.
uint8_t available :1, //!< Set to true when probe input is available.
connected :1, //!< Set to true when probe is connected. Always set to true if the driver does not have a probe connected input.
latchable :1, //!< Set to true when probe input supports change rising/falling.
watchable :1, //!< Set to true when probe input supports change interrupt.
unassigned :5;
guarded :1, //!< Set to true when probe protection is enabled.
unassigned :3;
};
} probe_flags_t;
typedef struct {
probe_id_t probe_id;
probe_flags_t flags;
uint8_t port;
void *input;
} probe_t;
void probe_connected_event (void *data);
bool probe_add (probe_id_t probe_id, uint8_t port, pin_irq_mode_t irq_mode, void *input, get_probe_input_ptr get_input);
#endif
#endif // _PROBE_H_

View File

@@ -183,7 +183,7 @@ bool protocol_main_loop (void)
spindle_all_off();
hal.coolant.set_state((coolant_state_t){0});
sys.cold_start = false;
system_set_exec_state_flag(EXEC_RT_COMMAND); // execute any statup up tasks
system_set_exec_state_flag(EXEC_RT_COMMAND); // execute any startup up tasks
}
// ---------------------------------------------------------------------------------
@@ -918,17 +918,17 @@ ISR_CODE bool ISR_FUNC(protocol_enqueue_realtime_command)(char c)
break;
case CMD_PROBE_CONNECTED_TOGGLE:
if(hal.probe.connected_toggle)
hal.probe.connected_toggle();
if((drop = !!hal.probe.connected_toggle))
task_add_immediate(probe_connected_event, (void *)2);
break;
case CMD_OPTIONAL_STOP_TOGGLE:
if((signals.stop_disable = !hal.signals_cap.stop_disable)) // Not available as realtime command if HAL supports physical switch
if((drop = (signals.stop_disable = !hal.signals_cap.stop_disable))) // Not available as realtime command if HAL supports physical switch
sys.flags.optional_stop_disable = !sys.flags.optional_stop_disable;
break;
case CMD_SINGLE_BLOCK_TOGGLE:
if((signals.single_block = !hal.signals_cap.single_block)) // Not available as realtime command if HAL supports physical switch
if((drop = (signals.single_block = !hal.signals_cap.single_block))) // Not available as realtime command if HAL supports physical switch
sys.flags.single_block = !sys.flags.single_block;
break;

View File

@@ -1473,8 +1473,11 @@ void report_realtime_status (stream_write_ptr stream_write)
if(report.tool)
stream_write(appendbuf(2, "|T:", uitoa((uint32_t)gc_state.tool->tool_id)));
if(report.probe_id)
if(report.probe_id || report.probe_protect) {
stream_write(appendbuf(2, "|P:", uitoa((uint32_t)probe_state.probe_id)));
if(report.probe_protect && !probe_state.is_probing && probe_state.irq_enabled)
stream_write(",P");
}
if(report.tlo_reference)
stream_write(appendbuf(2, "|TLR:", uitoa(sys.tlo_reference_set.mask != 0)));

View File

@@ -426,8 +426,8 @@ static char homing_options[] = "Enable,Enable single axis commands,Homing on sta
#else
static char probe_signals[] = "Probe";
#endif
static char probing_options[] = "Allow feed override,Apply soft limits,N/A,Auto select toolsetter,Auto select probe 2";
static char control_signals[] = "Reset,Feed hold,Cycle start,Safety door,Block delete,Optional stop,EStop,Probe connected,Motor fault,Motor warning,Limits override,Single step blocks";
static char probing_options[] = "Allow feed override,Apply soft limits,N/A,Auto select toolsetter,Auto select probe 2,Probe protection";
static char control_signals[] = "Reset,Feed hold,Cycle start,Safety door,Block delete,Optional stop,EStop,Probe disconnected,Motor fault,Motor warning,Limits override,Single step blocks,Toolsetter overtravel";
static char spindle_signals[] = "Spindle enable,Spindle direction,PWM";
static char coolant_signals[] = "Flood,Mist";
static char ganged_axes[] = "X-Axis,Y-Axis,Z-Axis";
@@ -702,11 +702,18 @@ static status_code_t set_ngc_debug_out (setting_id_t id, uint_fast16_t int_value
static status_code_t set_control_invert (setting_id_t id, uint_fast16_t int_value)
{
settings.control_invert.mask = (int_value & hal.signals_cap.mask) | limits_override.mask;
int_value = (int_value & hal.signals_cap.mask) | limits_override.mask;
bool pd_changed = hal.probe.connected_toggle && settings.control_invert.probe_disconnected != (control_signals_t){ .value = int_value }.probe_disconnected;
settings.control_invert.mask = int_value;
ioport_setting_changed(id);
system_init_switches();
if(pd_changed)
hal.probe.connected_toggle();
return Status_OK;
}
@@ -1077,9 +1084,12 @@ static status_code_t set_probe_flags (setting_id_t id, uint_fast16_t int_value)
{
settings.probe.allow_feed_override = bit_istrue(int_value, bit(0));
settings.probe.soft_limited = bit_istrue(int_value, bit(1));
settings.probe.enable_protection = bit_istrue(int_value, bit(2));
// settings.probe.? = bit_istrue(int_value, bit(2));
settings.probe.toolsetter_auto_select = bit_istrue(int_value, bit(3)) && hal.driver_cap.toolsetter && hal.probe.select;
settings.probe.probe2_auto_select = bit_istrue(int_value, bit(4)) && hal.driver_cap.probe2 && hal.probe.select;
settings.probe.enable_protection = bit_istrue(int_value, bit(5));
hal.probe.configure(false, false);
return Status_OK;
}
@@ -1601,9 +1611,10 @@ static uint32_t get_int (setting_id_t id)
case Setting_ProbingFlags:
value = settings.probe.allow_feed_override |
(settings.probe.soft_limited << 1) |
(settings.probe.enable_protection << 2) |
// (settings.probe.enable_protection << 2) |
(settings.probe.toolsetter_auto_select << 3) |
(settings.probe.probe2_auto_select << 4);
(settings.probe.probe2_auto_select << 4) |
(settings.probe.enable_protection << 5);
break;
case Setting_ToolChangeMode:
@@ -3509,6 +3520,14 @@ void settings_init (void)
setting_remove_elements(Setting_ProbePullUpDisable, mask);
mask = 0b00011 | (hal.probe.select ? ((hal.driver_cap.toolsetter << 3) | (hal.driver_cap.probe2 << 4)) : 0);
#if 0
if(hal.probe.get_caps) {
if(hal.probe.get_caps(Probe_Default).watchable)
mask |= (1 << 5);
}
#else
settings.probe.enable_protection = Off;
#endif
setting_remove_elements(Setting_ProbingFlags, mask);
if(!settings.flags.settings_downgrade && settings.version.build != (GRBL_BUILD - 20000000UL)) {

View File

@@ -724,8 +724,8 @@ void debug_write (const char *s)
{
if(dbg_write) {
dbg_write(s);
// while(hal.debug.get_tx_buffer_count()) // Wait until message is delivered
// grbl.on_execute_realtime(state_get());
while(hal.debug.get_tx_buffer_count()) // Wait until message is delivered
grbl.on_execute_realtime(state_get());
}
}
@@ -740,8 +740,8 @@ void debug_writeln (const char *s)
dbg_write(s);
dbg_write(ASCII_EOL);
// while(hal.debug.get_tx_buffer_count()) // Wait until message is delivered
// grbl.on_execute_realtime(state_get());
while(hal.debug.get_tx_buffer_count()) // Wait until message is delivered
grbl.on_execute_realtime(state_get());
lock = false;
}

View File

@@ -72,8 +72,13 @@ ISR_CODE void ISR_FUNC(control_interrupt_handler)(control_signals_t signals)
.motor_fault = On
};
if(signals.deasserted)
if(signals.deasserted) {
if(signals.probe_disconnected) {
signals.probe_disconnected = Off;
task_add_immediate(probe_connected_event, (void *)1);
}
signals.bits &= onoff_signals.bits;
}
if(signals.bits) {
@@ -116,7 +121,8 @@ ISR_CODE void ISR_FUNC(control_interrupt_handler)(control_signals_t signals)
if(sys.probing_state == Probing_Active && state_get() == STATE_CYCLE) {
system_set_exec_state_flag(EXEC_FEED_HOLD);
sys.alarm_pending = Alarm_ProbeProtect;
}
} else
task_add_immediate(probe_connected_event, NULL);
} else if(signals.feed_hold)
system_set_exec_state_flag(EXEC_FEED_HOLD);
else if(signals.cycle_start)

View File

@@ -158,31 +158,6 @@ typedef union {
};
} step_control_t;
// NOTE: the pin_function_t enum must be kept in sync with any changes!
typedef union {
uint16_t bits;
uint16_t mask;
uint16_t value;
struct {
uint16_t reset :1,
feed_hold :1,
cycle_start :1,
safety_door_ajar :1,
block_delete :1,
stop_disable :1, //! M1
e_stop :1,
probe_disconnected :1,
motor_fault :1,
motor_warning :1,
limits_override :1,
single_block :1,
tls_overtravel :1, //! used for probe (toolsetter) protection
probe_overtravel :1, //! used for probe protection
probe_triggered :1, //! used for probe protection
deasserted :1; //! this flag is set if signals are deasserted.
};
} control_signals_t;
// Define spindle stop override control states.
typedef union {
uint8_t value;
@@ -229,9 +204,10 @@ typedef enum {
Report_SpindleId = (1 << 17),
Report_ProbeId = (1 << 18),
Report_DistanceToGo = (1 << 19),
Report_ProbeProtect = (1 << 20),
Report_ForceWCO = (1 << 29),
Report_CycleStart = (1 << 30),
Report_All = 0x8003FFFF
Report_All = 0x801FFFFF
} report_tracking_t;
typedef union {
@@ -257,7 +233,8 @@ typedef union {
spindle_id :1, //!< Spindle changed.
probe_id :1, //!< Probe changed.
distance_to_go :1, //!< Distance to go.
unassigned :9, //
probe_protect :1, //!< Probe protection state changed.
unassigned :8, //
force_wco :1, //!< Add work coordinates (due to WCO changed during motion).
cycle_start :1, //!< Cycle start signal triggered. __NOTE:__ do __NOT__ add to Report_All enum above!
all :1; //!< Set when CMD_STATUS_REPORT_ALL is requested, may be used by user code.