Added helper code for plugins claiming auxiliary ports to make plugin coding easier and behaviour consistent.

Some minor bug fixes such as incorrect error code returned for unknown $-commands and temporary incorrect position reporting on in-flight G92 offset changes.
This commit is contained in:
Terje Io
2025-10-11 18:28:21 +02:00
parent 5d48dd5c43
commit 8c3d44bfca
27 changed files with 388 additions and 213 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
## grblHAL ##
Latest build date is 20251003, see the [changelog](changelog.md) for details.
Latest build date is 20251011, 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.
+32 -1
View File
@@ -1,5 +1,36 @@
## grblHAL changelog
<a name="20251011">Build 20251011
Core:
* Added helper code for plugins claiming auxiliary ports to make plugin coding easier and behaviour consistent.
* Some minor bug fixes such as incorrect error code returned for unknown $-commands and temporary incorrect position reporting on in-flight G92 offset changes.
Drivers:
* ESP32: fix for some unreported compilation failures, triggered by certain configuration options - due to unique build system.
* iMXRT1062: addd tentative support for SPI based Trinamic drivers. Ref. issue [#101](https://github.com/grblHAL/iMXRT1062/issues/101).
A known issue is that PWM spindle cannot be enabled whith Trinamic drivers. Testing required.
* STM32F4xx: updated board specific code to use new core helper code.
Plugins:
*all having configurable auxiliary ports: updated to use new core helper code.
* SD card: fixed/improved error code returned on formatting errors.
* Plasma: changed order of arc voltage calulation, now offset (`$362`) is applied before scaling factor (`$361`) to make calibration easier. WIP: some tweaks for voltage THC.
Libraries:
* Trinamic: made compilable with cpp.
---
<a name="20251005">Build 20251005
Core:
@@ -12,7 +43,7 @@ Drivers:
* STM32F1xx: fixed board map causing compilation errors.
* STM32F4xx: changed code that older compiler used by platformio flagged as invalid.
* STM32F4xx
Plugins:
+2
View File
@@ -255,6 +255,7 @@ typedef enum {
Input_RX,
Output_TX,
Output_RTS,
Output_RS485_Direction,
Input_QEI_A,
Input_QEI_B,
Input_QEI_Select,
@@ -497,6 +498,7 @@ PROGMEM static const pin_name_t pin_names[] = {
{ .function = Input_RX, .name = "RX" },
{ .function = Output_TX, .name = "TX" },
{ .function = Output_RTS, .name = "RTS" },
{ .function = Output_RS485_Direction, .name = "RS485 RX/TX direction" },
{ .function = Input_QEI_A, .name = "QEI A" },
{ .function = Input_QEI_B, .name = "QEI B" },
{ .function = Input_QEI_Select, .name = "QEI select" },
+2 -1
View File
@@ -107,7 +107,8 @@ PROGMEM static const status_detail_t status_detail[] = {
{ Status_FlowControlOutOfMemory, "Out of memory while executing flow statement." },
#endif
{ Status_FileOpenFailed, "Could not open file." },
{ Status_UserException, "User defined error occured." }
{ Status_UserException, "User defined error occured." },
{ Status_AuxiliaryPortUnusable, "Port is not usable." }
#endif // NO_SETTINGS_DESCRIPTIONS
};
+2 -1
View File
@@ -117,7 +117,8 @@ typedef enum {
Status_FlowControlOutOfMemory = 83,
Status_FileOpenFailed = 84,
Status_FsFormatFailed = 85,
Status_StatusMax = Status_FlowControlOutOfMemory,
Status_AuxiliaryPortUnusable = 86,
Status_StatusMax = Status_AuxiliaryPortUnusable,
Status_UserException = 253,
Status_Handled, // For internal use only
Status_Unhandled // For internal use only
+22 -20
View File
@@ -491,10 +491,10 @@ void gc_coolant (coolant_state_t state)
system_add_rt_report(Report_Coolant);
}
static void add_offset (void)
static void add_offset (const coord_data_t *offset)
{
gc_state.offset_id = (gc_state.offset_id + 1) & (MAX_OFFSET_ENTRIES - 1);
memcpy(&gc_state.offset_queue[gc_state.offset_id], &gc_state.g92_coord_offset, sizeof(coord_data_t));
memcpy(&gc_state.offset_queue[gc_state.offset_id], offset, sizeof(coord_data_t));
system_flag_wco_change();
}
@@ -3714,7 +3714,7 @@ status_code_t gc_execute_block (char *block)
}
}
}
// no break
// No break. Continues to next line.
#endif
case NonModal_GoHome_1:
@@ -3789,31 +3789,31 @@ status_code_t gc_execute_block (char *block)
break;
case NonModal_SetCoordinateOffset: // G92
add_offset((coord_data_t *)gc_block.values.xyz);
gc_state.g92_coord_offset_applied = true; // TODO: check for all zero?
memcpy(gc_state.g92_coord_offset, gc_block.values.xyz, sizeof(gc_state.g92_coord_offset));
gc_state.g92_coord_offset_applied = memcmp(gc_state.g92_coord_offset, null_vector.values, sizeof(coord_data_t)) != 0;
if(!settings.flags.g92_is_volatile)
settings_write_coord_data(CoordinateSystem_G92, &gc_state.g92_coord_offset); // Save G92 offsets to non-volatile storage
add_offset();
break;
case NonModal_ResetCoordinateOffset: // G92.1
gc_state.g92_coord_offset_applied = false;
clear_vector(gc_state.g92_coord_offset); // Disable G92 offsets by zeroing offset vector.
if(!settings.flags.g92_is_volatile)
settings_write_coord_data(CoordinateSystem_G92, &gc_state.g92_coord_offset); // Save G92 offsets to non-volatile storage
add_offset();
break;
settings_write_coord_data(CoordinateSystem_G92, &null_vector.values); // Save G92 offsets to non-volatile storage
// No break. Continues to next line.
case NonModal_ClearCoordinateOffset: // G92.2
add_offset(&null_vector);
gc_state.g92_coord_offset_applied = false;
clear_vector(gc_state.g92_coord_offset); // Disable G92 offsets by zeroing offset vector.
add_offset();
memcpy(gc_state.g92_coord_offset, null_vector.values, sizeof(coord_data_t)); // Disable G92 offsets by zeroing offset vector.
break;
case NonModal_RestoreCoordinateOffset: // G92.3
gc_state.g92_coord_offset_applied = true; // TODO: check for all zero?
settings_read_coord_data(CoordinateSystem_G92, &gc_state.g92_coord_offset); // Restore G92 offsets from non-volatile storage
add_offset();
case NonModal_RestoreCoordinateOffset:; // G92.3
coord_data_t offset;
settings_read_coord_data(CoordinateSystem_G92, &offset.values); // Restore G92 offsets from non-volatile storage
add_offset(&offset);
gc_state.g92_coord_offset_applied = memcmp(offset.values, null_vector.values, sizeof(coord_data_t)) != 0;
memcpy(gc_state.g92_coord_offset, offset.values, sizeof(coord_data_t)); // Disable G92 offsets by zeroing offset vector.
break;
default:
@@ -4052,15 +4052,17 @@ status_code_t gc_execute_block (char *block)
}
// Execute coordinate change and spindle/coolant stop.
if (!check_mode) {
if(!check_mode) {
if (!(settings_read_coord_data(gc_state.modal.coord_system.id, &gc_state.modal.coord_system.xyz)))
if(!(settings_read_coord_data(gc_state.modal.coord_system.id, &gc_state.modal.coord_system.xyz)))
FAIL(Status_SettingReadFail);
#if COMPATIBILITY_LEVEL <= 1
float g92_offset_stored[N_AXIS];
if(settings_read_coord_data(CoordinateSystem_G92, &g92_offset_stored) && !isequal_position_vector(g92_offset_stored, gc_state.g92_coord_offset))
settings_write_coord_data(CoordinateSystem_G92, &gc_state.g92_coord_offset); // Save G92 offsets to non-volatile storage
if(!settings.flags.g92_is_volatile) {
float g92_offset_stored[N_AXIS];
if(settings_read_coord_data(CoordinateSystem_G92, &g92_offset_stored) && !isequal_position_vector(g92_offset_stored, gc_state.g92_coord_offset))
settings_write_coord_data(CoordinateSystem_G92, &gc_state.g92_coord_offset); // Save G92 offsets to non-volatile storage
}
#endif
system_flag_wco_change(); // Set to refresh immediately just in case something altered.
-45
View File
@@ -352,51 +352,6 @@ typedef union {
};
} gc_override_flags_t;
//! Coordinate data.
typedef union {
float values[N_AXIS];
struct {
float x;
float y;
float z;
#ifdef A_AXIS
float a;
#endif
#ifdef B_AXIS
float b;
#endif
#ifdef C_AXIS
float c;
#endif
#ifdef U_AXIS
float u;
#endif
#ifdef V_AXIS
float v;
#endif
};
struct {
float m0;
float m1;
float m2;
#if N_AXIS > 3
float m3;
#endif
#if N_AXIS > 4
float m4;
#endif
#if N_AXIS > 5
float m5;
#endif
#if N_AXIS > 6
float m6;
#endif
#if N_AXIS == 8
float m7;
#endif
};
} coord_data_t;
//! Coordinate data including id.
typedef struct {
float xyz[N_AXIS];
+1 -1
View File
@@ -42,7 +42,7 @@
#else
#define GRBL_VERSION "1.1f"
#endif
#define GRBL_BUILD 20251005
#define GRBL_BUILD 20251011
#define GRBL_URL "https://github.com/grblHAL"
+4 -1
View File
@@ -498,7 +498,10 @@ typedef union {
uint8_t periodic :1, //!<
up :1, //!< Timer supports upcounting
comp1 :1, //!< Timer supports compare interrupt 0
comp2 :1; //!< Timer supports compare interrupt 1
comp2 :1, //!< Timer supports compare interrupt 1
ext_clk :1, //!< External clock supported
encoder :1, //!< Emcode mode supported
unused :2;
};
} timer_cap_t;
+116 -18
View File
@@ -41,7 +41,7 @@ typedef enum {
Port_DigitalOut
} ioport_type_xxx_t;
typedef struct {
struct ioports_handle {
ioport_type_xxx_t type;
io_ports_detail_t *ports;
const char *pnum;
@@ -57,7 +57,9 @@ typedef struct {
pin_function_t max_fn;
uint8_t map[MAX_PORTS];
ioport_bus_t bus;
} io_ports_private_t;
};
typedef struct ioports_handle io_ports_private_t;
typedef struct {
digital_out_ptr digital_out; //!< Optional handler for setting a digital output.
@@ -197,16 +199,24 @@ struct ff_data {
static bool match_port (xbar_t *properties, uint8_t port, void *data)
{
bool ok;
struct ff_data *ff_data = (struct ff_data *)data;
if(ff_data->description
? (properties->description == NULL || strcmp(properties->description, ff_data->description))
: port >= ff_data->max_port)
return false;
if((ok = properties->id <= ff_data->max_port))
ff_data->port = port;
ff_data->port = port;
return ok;
}
return true;
static bool match_description (xbar_t *properties, uint8_t port, void *data)
{
bool ok;
struct ff_data *ff_data = (struct ff_data *)data;
if((ok = properties->description && !strcmp(properties->description, ff_data->description)))
ff_data->port = port;
return ok;
}
/*! \brief find claimable or claimed analog or digital port. Search starts from the last port number.
@@ -216,6 +226,7 @@ static bool match_port (xbar_t *properties, uint8_t port, void *data)
or a port number to be used as the upper limit for the search, or \a NULL if searching for the first free port.
\returns the port number if successful, 0xFF (255) if not.
*/
uint8_t ioport_find_free (io_port_type_t type, io_port_direction_t dir, pin_cap_t filter, const char *description)
{
struct ff_data ff_data = { .port = IOPORT_UNASSIGNED, .max_port = IOPORT_UNASSIGNED + 1 };
@@ -227,11 +238,9 @@ uint8_t ioport_find_free (io_port_type_t type, io_port_direction_t dir, pin_cap_
ff_data.description = NULL;
}
// TODO: pass modified filter with .claimable off when looking for description match?
if(ff_data.description && !ioports_enumerate(type, dir, (pin_cap_t){}, match_port, (void *)&ff_data))
ff_data.description = NULL;
if(ff_data.description == NULL && ff_data.max_port != IOPORT_UNASSIGNED)
if(ff_data.description)
ioports_enumerate(type, dir, (pin_cap_t){ .claimable = On }, match_description, (void *)&ff_data);
else
ioports_enumerate(type, dir, filter, match_port, (void *)&ff_data);
return ff_data.port;
@@ -260,12 +269,12 @@ static xbar_t *get_info (io_port_type_t type, io_port_direction_t dir, uint8_t p
/*! \brief Return information about a digital or analog 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 the port aux number.
\param port the claimed port aux number.
\returns pointer to \a xbar_t struct if successful, \a NULL if not.
*/
xbar_t *ioport_get_info (io_port_type_t type, io_port_direction_t dir, uint8_t port)
{
return get_info(type, dir, port, false);
return hal.port.get_pin_info(type, dir, port);
}
/* code to keep deprecated data updated, to be removed */
@@ -333,7 +342,7 @@ xbar_t *ioport_claim (io_port_type_t type, io_port_direction_t dir, uint8_t *por
*/
bool ioport_claimable (io_port_type_t type, io_port_direction_t dir, uint8_t port)
{
xbar_t *portinfo = port == IOPORT_UNASSIGNED ? NULL : get_info(type, dir, port, false);
xbar_t *portinfo = port == IOPORT_UNASSIGNED ? NULL : hal.port.get_pin_info(type, dir, map_reverse(get_port_data(type, dir), port));
return port == IOPORT_UNASSIGNED || (portinfo && portinfo->cap.claimable);
}
@@ -392,7 +401,7 @@ bool ioport_set_function (xbar_t *pin, pin_function_t function, driver_caps_t ca
case Port_DigitalIn:
if(caps.control)
hal.signals_cap.mask |= caps.control->mask;
if(function == Input_Probe || xbar_fn_to_signals_mask(function).mask)
if(function == Input_Probe || function == Input_Probe2 || function == Input_Toolsetter || xbar_fn_to_signals_mask(function).mask)
setting_remove_elements(Settings_IoPort_InvertIn, cfg->bus.mask);
break;
@@ -443,6 +452,95 @@ bool ioport_can_claim_explicit (void)
return ioports_can_do().claim_explicit;
}
//
// Some helper functions for plugins using ports
//
static float _get_value (io_port_cfg_t *p, uint8_t port)
{
return port > p->port_max ? -1.0f : (float)port;
}
static status_code_t _set_value (io_port_cfg_t *p, uint8_t *port, pin_cap_t caps, float value)
{
status_code_t status;
if((status = isintf(value) ? Status_OK : Status_BadNumberFormat) == Status_OK) {
if(value >= 0.0f) {
xbar_t *portinfo = hal.port.get_pin_info(p->handle->type >> 1, p->handle->type & 1, map_reverse(&ports_cfg[p->handle->type], (uint8_t)value));
if(portinfo == NULL || !portinfo->cap.claimable)
status = Status_AuxiliaryPortUnavailable;
else if(!(caps.mask == 0 || (portinfo->cap.mask & caps.mask)))
status = Status_AuxiliaryPortUnusable;
else
*port = (uint8_t)value;
} else
*port = IOPORT_UNASSIGNED;
}
return status;
}
uint8_t _get_next (io_port_cfg_t *p, uint8_t port, const char *description, pin_cap_t caps)
{
uint8_t px = IOPORT_UNASSIGNED;
caps.claimable = On;
if(description && *description)
px = ioport_find_free(p->handle->type >> 1, p->handle->type & 1, (pin_cap_t){ .claimable = On }, description);
if(px == IOPORT_UNASSIGNED && !(port == 0 && port == p->port_max))
px = ioport_find_free(p->handle->type >> 1, p->handle->type & 1, caps, uitoa(port == IOPORT_UNASSIGNED ? p->port_max : (port > p->port_max ? p->port_max : port) - 1));
return px;
}
static xbar_t *_claim (io_port_cfg_t *p, uint8_t *port, const char *description, pin_cap_t caps)
{
xbar_t *portinfo = *port <= p->port_max ? hal.port.get_pin_info(p->handle->type >> 1, p->handle->type & 1, map_reverse(&ports_cfg[p->handle->type], *port)) : NULL;
if(!portinfo)
*port = IOPORT_UNASSIGNED;
return portinfo && !portinfo->mode.claimed && (caps.mask == 0 || (portinfo->cap.mask & caps.mask) == caps.mask) && ioport_claim(p->handle->type >> 1, p->handle->type & 1, port, description)
? portinfo
: NULL;
}
/*! \brief Get data and pointers to helper functions for managing ports and port settings.
\param pp a pointer to a \a io_port_cfg_t struct to hold the data and pointers.
\param type as an \a #io_port_type_t enum value.
\param dir as an \a #io_port_direction_t enum value.
\returns the pointer to the \a io_port_cfg_t struct passed in the pp argument.
*/
io_port_cfg_t *ioports_cfg (io_port_cfg_t *pp, io_port_type_t type, io_port_direction_t dir)
{
static io_port_cfg_t cfg[4] = {0};
io_port_cfg_t *p = &cfg[(type << 1) | dir];
if(p->n_ports == 0 && !!hal.port.claim) {
if((p->n_ports = ioports_available(type, dir))) {
p->handle = &ports_cfg[(type << 1) | dir];
p->port_max = ioport_find_free(type, dir, (pin_cap_t){ .claimable = On }, NULL);
p->get_value = _get_value;
p->set_value = _set_value;
p->get_next = _get_next;
p->claim = _claim;
strcpy((char *)p->port_maxs, uitoa(p->port_max));
}
}
memcpy(pp, p, sizeof(io_port_cfg_t));
return pp;
}
// ---
/*! \brief Enumerate ports.
\param type as an \a #io_port_type_t enum value.
\param dir as an \a #io_port_direction_t enum value.
@@ -456,7 +554,7 @@ bool ioports_enumerate (io_port_type_t type, io_port_direction_t dir, pin_cap_t
bool ok = false;
io_ports_private_t *p_data = get_port_data(type, dir);
if(p_data->ports && p_data->n_ports && ioport_can_claim_explicit()) {
if(p_data->ports && p_data->n_ports && ioports_can_do().claim_explicit) {
xbar_t *portinfo;
uint_fast16_t n_ports;
+22
View File
@@ -193,6 +193,28 @@ typedef union {
};
} io_port_cando_t;
struct ioports_cfg;
struct ioports_handle; // members defined in ioports.c
typedef status_code_t (*ioport_set_value_ptr)(struct ioports_cfg *p, uint8_t *port, pin_cap_t caps, float value);
typedef float (*ioport_get_value_ptr)(struct ioports_cfg *p, uint8_t port);
typedef uint8_t (*ioport_get_next_ptr)(struct ioports_cfg *p, uint8_t port, const char *description, pin_cap_t caps);
typedef xbar_t *(*ioport_claim_ptr)(struct ioports_cfg *p, uint8_t *port, const char *description, pin_cap_t caps);
struct ioports_cfg {
struct ioports_handle *handle;
uint8_t n_ports;
uint8_t port_max;
const char port_maxs[4];
ioport_get_value_ptr get_value;
ioport_set_value_ptr set_value;
ioport_get_next_ptr get_next;
ioport_claim_ptr claim;
};
typedef struct ioports_cfg io_port_cfg_t;
io_port_cfg_t *ioports_cfg (io_port_cfg_t *p, io_port_type_t type, io_port_direction_t dir);
uint8_t ioports_available (io_port_type_t type, io_port_direction_t dir);
uint8_t ioports_unclaimed (io_port_type_t type, io_port_direction_t dir);
xbar_t *ioport_get_info (io_port_type_t type, io_port_direction_t dir, uint8_t port);
+25 -18
View File
@@ -44,8 +44,6 @@ typedef enum {
ModBus_Retry
} modbus_state_t;
typedef void (*stream_set_direction_ptr)(bool tx);
typedef struct {
set_baud_rate_ptr set_baud_rate;
set_format_ptr set_format; //!< Optional handler for setting the stream format.
@@ -535,7 +533,7 @@ static bool claim_stream (io_stream_properties_t const *sstream)
stream.read = claimed->read;
stream.flush_tx_buffer = claimed->reset_write_buffer;
stream.flush_rx_buffer = claimed->reset_read_buffer;
stream.set_direction = dir_port != IOPORT_UNASSIGNED ? modbus_set_direction : NULL;
stream.set_direction = claimed->set_direction;
if(hal.periph_port.set_pin_description) {
hal.periph_port.set_pin_description(Output_TX, (pin_group_t)(PinGroup_UART + claimed->instance), "Modbus");
@@ -547,6 +545,7 @@ static bool claim_stream (io_stream_properties_t const *sstream)
return claimed != NULL;
}
static status_code_t report_stats (sys_state_t state, char *args)
{
char buf[110];
@@ -562,7 +561,7 @@ static status_code_t report_stats (sys_state_t state, char *args)
return Status_OK;
}
void modbus_rtu_init (int8_t stream, int8_t dir_aux)
void modbus_rtu_init (int8_t instance, int8_t dir_aux)
{
static const modbus_api_t api = {
.interface = Modbus_InterfaceRTU,
@@ -592,23 +591,31 @@ void modbus_rtu_init (int8_t stream, int8_t dir_aux)
.commands = command_list
};
if(dir_aux != -2) {
int8_t n_out = ioports_available(Port_Digital, Port_Output);
dir_port = dir_aux != -1 ? dir_aux : (n_out ? n_out - 1 : IOPORT_UNASSIGNED);
if(!(dir_port != IOPORT_UNASSIGNED && ioport_claim(Port_Digital, Port_Output, &dir_port, "Modbus RX/TX direction"))) {
task_run_on_startup(report_warning, "Modbus failed to initialize!");
system_raise_alarm(Alarm_SelftestFailed);
return;
}
}
stream_instance = stream;
stream_instance = instance;
if(stream_enumerate_streams(claim_stream) && (nvs_address = nvs_alloc(sizeof(modbus_settings_t)))) {
if(stream.set_direction == NULL && dir_aux != -2) {
xbar_t *dir_pin; // TODO: move to top and use for direct access
io_port_cfg_t d_out;
ioports_cfg(&d_out, Port_Digital, Port_Output);
dir_port = dir_aux != -1 ? dir_aux : (d_out.n_ports ? d_out.n_ports - 1 : IOPORT_UNASSIGNED);
if((dir_pin = d_out.claim(&d_out, &dir_port, NULL, (pin_cap_t){}))) {
stream.set_direction = modbus_set_direction;
ioport_set_function(dir_pin, Output_RS485_Direction, NULL);
}
if(stream.set_direction == NULL) {
task_run_on_startup(report_warning, "Modbus failed to initialize!");
system_raise_alarm(Alarm_SelftestFailed);
return;
}
}
driver_reset = hal.driver_reset;
hal.driver_reset = modbus_reset;
+2
View File
@@ -59,6 +59,8 @@ static const float froundvalues[MAX_PRECISION + 1] =
#error "Illegal remapping of ABC axes!"
#endif
const coord_data_t null_vector = {0};
char const *const axis_letter[N_AXIS] = {
"X",
"Y",
+48 -2
View File
@@ -120,8 +120,6 @@
#define N_ABC_AXIS 0
#endif
extern char const *const axis_letter[];
typedef union {
uint8_t mask;
uint8_t bits;
@@ -138,6 +136,51 @@ typedef union {
};
} axes_signals_t;
//! Coordinate data.
typedef union {
float values[N_AXIS];
struct {
float x;
float y;
float z;
#ifdef A_AXIS
float a;
#endif
#ifdef B_AXIS
float b;
#endif
#ifdef C_AXIS
float c;
#endif
#ifdef U_AXIS
float u;
#endif
#ifdef V_AXIS
float v;
#endif
};
struct {
float m0;
float m1;
float m2;
#if N_AXIS > 3
float m3;
#endif
#if N_AXIS > 4
float m4;
#endif
#if N_AXIS > 5
float m5;
#endif
#if N_AXIS > 6
float m6;
#endif
#if N_AXIS == 8
float m7;
#endif
};
} coord_data_t;
typedef union {
int32_t value[N_AXIS];
struct {
@@ -240,6 +283,9 @@ typedef enum {
#define bit_istrue(x, mask) (((x) & (mask)) != 0)
#define bit_isfalse(x, mask) (((x) & (mask)) == 0)
extern char const *const axis_letter[];
extern const coord_data_t null_vector;
// Converts an uint32 variable to string.
char *uitoa (uint32_t n);
+4
View File
@@ -558,6 +558,10 @@ static inline void aux_ctrl_claim_out_ports (aux_claim_explicit_out_ptr aux_clai
#define RTS_BIT (1<<RTS_PIN)
#endif
#if defined(RS485_DIR_PIN) && !defined(RS485_DIR_BIT)
#define RS485_DIR_BIT (1<<RS485_DIR_PIN)
#endif
// IRQ enabled input singnals
#if QEI_ENABLE
+2 -4
View File
@@ -364,10 +364,8 @@ bool protocol_buffer_synchronize (void)
// If system is queued, ensure cycle resumes if the auto start flag is present.
protocol_auto_cycle_start();
sys.flags.synchronizing = gc_state.modal.program_flow == ProgramFlow_Running;
while ((ok = protocol_execute_realtime()) && (plan_get_current_block() || state_get() == STATE_CYCLE));
sys.flags.synchronizing = Off;
while((ok = protocol_execute_realtime()) && (plan_get_current_block() || state_get() == STATE_CYCLE));
return ok;
}
+20 -19
View File
@@ -1161,8 +1161,6 @@ void report_realtime_status (stream_write_ptr stream_write)
.triggered = Off
};
system_convert_array_steps_to_mpos(print_position, sys.position);
if(hal.probe.get_state)
probe_state = hal.probe.get_state();
@@ -1226,6 +1224,18 @@ void report_realtime_status (stream_write_ptr stream_write)
break;
}
system_convert_array_steps_to_mpos(print_position, sys.position);
if((report.distance_to_go = settings.status_report.distance_to_go)) {
// Calulate distance-to-go in current block (i.e., difference between target / end-of-block) and current position)
plan_block_t *cur_block = plan_get_current_block();
if((report.distance_to_go = !!cur_block)) {
for(idx = 0; idx < N_AXIS; idx++) {
dist_remaining[idx] = cur_block->target_mm[idx] - print_position[idx];
}
}
}
if(!settings.status_report.machine_position) {
// Apply work coordinate offsets and tool length offset to current position.
for(idx = 0; idx < N_AXIS; idx++) {
@@ -1240,7 +1250,7 @@ void report_realtime_status (stream_write_ptr stream_write)
// Returns planner and output stream buffer states.
if (settings.status_report.buffer_state) {
if(settings.status_report.buffer_state) {
stream_write("|Bf:");
stream_write(uitoa((uint32_t)plan_get_block_buffer_available()));
stream_write(",");
@@ -1254,19 +1264,10 @@ void report_realtime_status (stream_write_ptr stream_write)
stream_write(appendbuf(2, "|Ln:", uitoa((uint32_t)cur_block->line_number)));
}
if(settings.status_report.distance_to_go) {
// Report distance-to-go in current block (i.e., difference between target / end-of-block) and current position)
plan_block_t *cur_block = plan_get_current_block();
if (cur_block != NULL) {
system_convert_array_steps_to_mpos(dist_remaining, sys.position);
for(idx = 0; idx < N_AXIS; idx++) {
dist_remaining[idx] = cur_block->target_mm[idx] - dist_remaining[idx];
}
stream_write("|DTG:");
stream_write(get_axis_values(dist_remaining));
}
if(report.distance_to_go) {
// Report distance-to-go.
stream_write("|DTG:");
stream_write(get_axis_values(dist_remaining));
}
spindle_ptrs_t *spindle_0;
@@ -1320,7 +1321,7 @@ void report_realtime_status (stream_write_ptr stream_write)
ctrl_pin_state.probe_triggered = probe_state.triggered;
ctrl_pin_state.probe_disconnected = !probe_state.connected;
ctrl_pin_state.cycle_start |= sys.report.cycle_start;
ctrl_pin_state.cycle_start |= report.cycle_start;
if(sys.flags.value & sys_switches.value) {
if(!hal.signals_cap.stop_disable)
ctrl_pin_state.stop_disable = sys.flags.optional_stop_disable;
@@ -1378,7 +1379,7 @@ void report_realtime_status (stream_write_ptr stream_write)
// If protocol_buffer_synchronize() is running
// delay outputting WCO until sync is completed
// unless requested from stepper_driver_interrupt_handler.
if(!report.all && (report.overrides || (sys.flags.synchronizing && !report.force_wco))) {
if(!report.all && (report.overrides || !report.force_wco)) {
report.wco = Off;
delayed_report.wco = On;
}
@@ -1487,7 +1488,7 @@ void report_realtime_status (stream_write_ptr stream_write)
}
if(grbl.on_realtime_report)
grbl.on_realtime_report(stream_write, sys.report);
grbl.on_realtime_report(stream_write, report);
#if COMPATIBILITY_LEVEL <= 1
if(report.all) {
+3 -3
View File
@@ -2460,7 +2460,7 @@ bool settings_read_startup_line (uint8_t idx, char *line)
}
// Write selected coordinate data to persistent storage.
void settings_write_coord_data (coord_system_id_t id, float (*coord_data)[N_AXIS])
void settings_write_coord_data (coord_system_id_t id, const float (*coord_data)[N_AXIS])
{
assert(id <= N_CoordinateSystems);
@@ -2476,13 +2476,13 @@ void settings_write_coord_data (coord_system_id_t id, float (*coord_data)[N_AXIS
}
// Read selected coordinate data from persistent storage.
bool settings_read_coord_data (coord_system_id_t id, float (*coord_data)[N_AXIS])
bool settings_read_coord_data (coord_system_id_t id, const float (*coord_data)[N_AXIS])
{
assert(id <= N_CoordinateSystems);
if (!(hal.nvs.type != NVS_None && hal.nvs.memcpy_from_nvs((uint8_t *)coord_data, NVS_ADDR_PARAMETERS + id * (sizeof(coord_data_t) + NVS_CRC_BYTES), sizeof(coord_data_t), true) == NVS_TransferResult_OK)) {
// Reset with default zero vector
memset(coord_data, 0, sizeof(coord_data_t));
memcpy((float *)coord_data, null_vector.values, sizeof(coord_data_t));
settings_write_coord_data(id, coord_data);
return false;
}
+2 -2
View File
@@ -1134,10 +1134,10 @@ void settings_write_build_info(char *line);
bool settings_read_build_info(char *line);
// Writes selected coordinate data to persistent storage
void settings_write_coord_data(coord_system_id_t id, float (*coord_data)[N_AXIS]);
void settings_write_coord_data(coord_system_id_t id, const float (*coord_data)[N_AXIS]);
// Reads selected coordinate data from persistent storage
bool settings_read_coord_data(coord_system_id_t id, float (*coord_data)[N_AXIS]);
bool settings_read_coord_data(coord_system_id_t id, const float (*coord_data)[N_AXIS]);
// Temporarily override acceleration, if 0 restore to configured setting value
bool settings_override_acceleration (uint8_t axis, float acceleration);
+2 -2
View File
@@ -465,9 +465,9 @@ ISR_CODE void ISR_FUNC(stepper_driver_interrupt_handler)(void)
while(st.exec_block->output_commands) {
output_command_t *cmd = st.exec_block->output_commands;
if(cmd->is_digital)
hal.port.digital_out(cmd->port, cmd->value != 0.0f);
ioport_digital_out(cmd->port, cmd->value != 0.0f);
else
hal.port.analog_out(cmd->port, cmd->value);
ioport_analog_out(cmd->port, cmd->value);
st.exec_block->output_commands = cmd->next;
}
+11 -20
View File
@@ -29,6 +29,12 @@
#include "stepper2.h"
#ifdef DEBUGOUT
#define ST2_DEBUG 0
#else
#define ST2_DEBUG 0
#endif
typedef enum {
State_Idle = 0, //!< 0
State_Accel, //!< 1
@@ -339,16 +345,8 @@ float st2_motor_set_speed (st2_motor_t *motor, float speed)
if(pn == 0)
return motor->speed;
#ifdef DEBUGOUT
debug_writeln("!!");
debug_writeln(uitoa(motor->state));
debug_writeln(ftoa(motor->prev_speed, 2));
debug_writeln(ftoa(motor->speed, 2));
debug_writeln(uitoa((motor->denom - 1) >> 2));
debug_writeln(uitoa(motor->n));
debug_write(pn < 0 ? "-" : "+");
debug_writeln(uitoa(pn < 0 ? -pn : pn));
debug_writeln(uitoa(motor->denom));
#if ST2_DEBUG
debug_printf("!!: %d %.2f %.3f %d %d %d %d", motor->state, motor->prev_speed, motor->speed, motor->denom - 1, motor->n, pn, motor->denom);
#endif
if(motor->speed > motor->prev_speed) {
@@ -445,21 +443,14 @@ bool st2_motor_move (st2_motor_t *motor, const float move, const float speed, po
if(motor->step_inject_timer)
hal.timer.start(motor->step_inject_timer, motor->delay);
#ifdef DEBUGOUT
#if ST2_DEBUG
uint32_t nn = motor->n;
float cn = motor->first_delay;
do {
cn -= (2.0f * cn) / (4.0f * nn + 1);
} while(--nn);
debug_writeln("move");
debug_writeln(ftoa(speed, 2));
debug_writeln(ftoa(settings.axis[motor->idx].steps_per_mm, 3));
debug_writeln(uitoa(motor->n));
debug_writeln(uitoa(motor->delay));
debug_writeln(uitoa(motor->min_delay));
debug_writeln(ftoa(cn, 2));
debug_writeln(ftoa(motor->speed, 2));
debug_printf("mv: %.2f %.3f %d %d %d %.2f %.2f", speed, settings.axis[motor->idx].steps_per_mm, motor->n, move, motor->delay, cn, motor->speed);
#endif
return true;
@@ -529,7 +520,7 @@ __attribute__((always_inline)) static inline bool _motor_run (st2_motor_t *motor
motor->state = State_Idle;
motor->prev_speed = 0.0f;
motor->n = 0;
#ifdef DEBUGOUT
#if ST2_DEBUG
debug_writeln(uitoa(motor->position));
#endif
} else {
+13 -5
View File
@@ -724,18 +724,26 @@ 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());
}
}
void debug_writeln (const char *s)
{
if(dbg_write) {
static volatile bool lock = false;
if(!lock && dbg_write) {
lock = true;
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;
}
}
+9 -4
View File
@@ -177,6 +177,10 @@ This should be called by driver code prior to inserting a character into the inp
*/
typedef bool (*enqueue_realtime_command_ptr)(char c);
/*! \brief Pointer to function for setting the transfer direction control signal for half-duplex connections (RS-485).
\param tx \a true when transmitting, \a false when receiving.
*/
typedef void (*stream_set_direction_ptr)(bool tx);
/*! \brief Optional, but recommended, pointer to function for enqueueing realtime command characters.
\param c character to enqueue.
@@ -300,17 +304,18 @@ typedef struct {
stream_write_n_ptr write_n; //!< Optional handler for writing n characters to current output stream only. Required for Modbus support.
disable_rx_stream_ptr disable_rx; //!< Optional handler for disabling/enabling a stream. Recommended?
get_stream_buffer_count_ptr get_rx_buffer_count; //!< Optional handler for getting number of characters in the input buffer.
get_stream_buffer_count_ptr get_tx_buffer_count; //!< Optional handler for getting number of characters in the output buffer(s). Count shall include any unsent characters in any transmit FIFO and/or transmit register. Required for Modbus support.
flush_stream_buffer_ptr reset_write_buffer; //!< Optional handler for flushing the output buffer. Any transmit FIFO shall be flushed as well. Required for Modbus support.
set_baud_rate_ptr set_baud_rate; //!< Optional handler for setting the stream baud rate. Required for Modbus support, recommended for Bluetooth support.
get_stream_buffer_count_ptr get_tx_buffer_count; //!< Optional handler for getting number of characters in the output buffer(s). Count shall include any unsent characters in any transmit FIFO and/or transmit register. Required for Modbus/RS-485 support.
flush_stream_buffer_ptr reset_write_buffer; //!< Optional handler for flushing the output buffer. Any transmit FIFO shall be flushed as well. Required for Modbus/RS-485 support.
set_baud_rate_ptr set_baud_rate; //!< Optional handler for setting the stream baud rate. Required for Modbus/RS-485 support, recommended for Bluetooth support.
set_format_ptr set_format; //!< Optional handler for setting the stream format.
stream_set_direction_ptr set_direction; //!< Optional handler for setting the transfer direction for half-duplex communication.
on_linestate_changed_ptr on_linestate_changed; //!< Optional handler to be called when line state changes. Set by client.
vfs_file_t *file; //!< File handle, non-null if streaming from a file.
} io_stream_t;
typedef struct {
io_stream_state_t state; //!< Optional status flags such as connected status.
io_stream_flags_t flags; //!< Handler for getting stream connected status.
io_stream_flags_t flags; //!< Stream capability flags.
uint32_t baud_rate;
serial_format_t format;
} io_stream_status_t;
+9 -9
View File
@@ -83,14 +83,14 @@ static void onLinestateChanged (serial_linestate_t state)
if(conn_ok) {
if(state.dtr == state.rts) {
hal.port.digital_out(boot0_port, 0);
hal.port.digital_out(reset_port, 1);
ioport_digital_out(boot0_port, 0);
ioport_digital_out(reset_port, 1);
} else if(state.dtr) {
hal.port.digital_out(reset_port, 0);
hal.port.digital_out(boot0_port, 0);
ioport_digital_out(reset_port, 0);
ioport_digital_out(boot0_port, 0);
} else {
hal.port.digital_out(boot0_port, 0);
hal.port.digital_out(reset_port, 1);
ioport_digital_out(boot0_port, 0);
ioport_digital_out(reset_port, 1);
}
}
}
@@ -98,7 +98,7 @@ static void onLinestateChanged (serial_linestate_t state)
static void passthru_start2 (void *data)
{
conn_ok = true;
hal.port.digital_out(reset_port, 1);
ioport_digital_out(reset_port, 1);
task_add_delayed(forward_uart_rx, NULL, 8);
@@ -108,8 +108,8 @@ static void passthru_start2 (void *data)
static void passthru_start1 (void *data)
{
hal.port.digital_out(boot0_port, 1);
hal.port.digital_out(reset_port, 0);
ioport_digital_out(boot0_port, 1);
ioport_digital_out(reset_port, 0);
on_linestate_changed = hal.stream.on_linestate_changed;
hal.stream.on_linestate_changed = onLinestateChanged;
+6 -9
View File
@@ -1141,19 +1141,16 @@ status_code_t system_execute_line (char *line)
*args++ = '\0';
}
if (retval == Status_Unhandled) {
// Check for global setting, store if so
if(retval == Status_Unhandled) {
// Check for global setting, store or report if so
if(state_get() == STATE_IDLE || (state_get() & (STATE_ALARM|STATE_ESTOP|STATE_CHECK_MODE))) {
uint_fast8_t counter = 0;
float parameter;
if(!read_float(line, &counter, &parameter))
retval = Status_BadNumberFormat;
else if(!isintf(parameter))
retval = Status_InvalidStatement;
else if(args)
retval = settings_store_setting((setting_id_t)parameter, args);
if(read_float(line, &counter, &parameter) && parameter >= 0.0f && isintf(parameter))
retval = args ? settings_store_setting((setting_id_t)parameter, args)
: report_grbl_setting((setting_id_t)parameter, NULL);
else
retval = report_grbl_setting((setting_id_t)parameter, NULL);
retval = Status_InvalidStatement;
} else
retval = Status_IdleError;
}
+27 -26
View File
@@ -228,6 +228,7 @@ typedef enum {
Report_Fan = (1 << 16),
Report_SpindleId = (1 << 17),
Report_ProbeId = (1 << 18),
Report_DistanceToGo = (1 << 19),
Report_ForceWCO = (1 << 29),
Report_CycleStart = (1 << 30),
Report_All = 0x8003FFFF
@@ -236,29 +237,30 @@ typedef enum {
typedef union {
uint32_t value;
struct {
uint32_t mpg_mode :1, //!< MPG mode changed.
scaling :1, //!< Scaling (G50/G51) changed.
homed :1, //!< Homed state changed.
xmode :1, //!< Lathe radius/diameter mode changed.
spindle :1, //!< Spindle state changed.
coolant :1, //!< Coolant state changed.
overrides :1, //!< Overrides changed.
tool :1, //!< Tool changed.
wco :1, //!< Add work coordinates.
gwco :1, //!< Add work coordinate.
tool_offset :1, //!< Tool offsets changed.
m66result :1, //!< M66 result updated.
pwm :1, //!< Add PWM information (optional: to be added by driver).
motor :1, //!< Add motor information (optional: to be added by driver).
encoder :1, //!< Add encoder information (optional: to be added by driver).
tlo_reference :1, //!< Tool length offset reference changed.
fan :1, //!< Fan on/off changed.
spindle_id :1, //!< Spindle changed.
probe_id :1, //!< Probe changed.
unassigned :10, //
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.
uint32_t mpg_mode :1, //!< MPG mode changed.
scaling :1, //!< Scaling (G50/G51) changed.
homed :1, //!< Homed state changed.
xmode :1, //!< Lathe radius/diameter mode changed.
spindle :1, //!< Spindle state changed.
coolant :1, //!< Coolant state changed.
overrides :1, //!< Overrides changed.
tool :1, //!< Tool changed.
wco :1, //!< Add work coordinates.
gwco :1, //!< Add work coordinate.
tool_offset :1, //!< Tool offsets changed.
m66result :1, //!< M66 result updated.
pwm :1, //!< Add PWM information (optional: to be added by driver).
motor :1, //!< Add motor information (optional: to be added by driver).
encoder :1, //!< Add encoder information (optional: to be added by driver).
tlo_reference :1, //!< Tool length offset reference changed.
fan :1, //!< Fan on/off changed.
spindle_id :1, //!< Spindle changed.
probe_id :1, //!< Probe changed.
distance_to_go :1, //!< Distance to go.
unassigned :9, //
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.
};
} report_tracking_flags_t;
@@ -293,10 +295,9 @@ typedef union {
single_block :1, //!< Set to true to disable M1 (optional stop), via realtime command.
keep_input :1, //!< Set to true to not flush stream input buffer on executing STOP.
auto_reporting :1, //!< Set to true when auto real time reporting is enabled.
synchronizing :1, //!< Set to true when protocol_buffer_synchronize() is running.
travel_changed :1, //!< Set to true when maximum travel settings has changed.
is_homing :1,
unused :3;
unused :4;
};
} system_flags_t;
@@ -321,7 +322,7 @@ typedef struct system {
bool blocking_event; //!< Set when a blocking event that requires reset to clear is active.
volatile bool steppers_deenergize; //!< Set to true to deenergize stepperes
alarm_code_t alarm_pending; //!< Delayed alarm, currently used for probe protection
system_flags_t flags; //!< Assorted state flags
volatile system_flags_t flags; //!< Assorted state flags
step_control_t step_control; //!< Governs the step segment generator depending on system state.
axes_signals_t homing_axis_lock; //!< Locks axes when limits engage. Used as an axis motion mask in the stepper ISR.
axes_signals_t homing; //!< Axes with homing enabled.
+1 -1
View File
@@ -721,5 +721,5 @@ int vfs_drive_format (vfs_drive_t *drive)
{
const vfs_t *fs = drive->fs;
return fs->format ? fs->format() : -1;
return (vfs_errno = fs->format ? fs->format() : -1);
}