Added event definition for SD card file open, fix for issue #118.

This commit is contained in:
Terje Io
2023-03-13 10:05:44 +01:00
parent 71aa2a426c
commit 20aa4ec941
12 changed files with 295 additions and 154 deletions

View File

@@ -1,10 +1,27 @@
## grblHAL changelog
<a name="20230312"/>20230312
Core:
* Added event definition for SD card file open, fix for issue #118.
Drivers:
* ESP32: Added aux I/O and cycle start/feed hold inputs to MKS DLC32 board, expanded max aux out to 4.
__NOTE:__ The aux input 0 port on the MKS DLC32 board does not have an internal pullup.
Plugins:
* SD card: added publish for file open event allowing plugins to take over stream handling. Added `$F+` command for listing all files on card.
---
<a name="20230311"/>20230311
Core:
* Fix for isisue #264, stepper motors not disabled when entering sleep mode.
* Fix for issue #264, stepper motors not disabled when entering sleep mode.
__NOTE:__ all stepper motors will now be disabled even if the $37 setting is set to keep some enabled.
* Fix for recent regression that disabled G7/G8 handling in lathe mode.

View File

@@ -33,6 +33,7 @@
#include "report.h"
#include "planner.h"
#include "machine_limits.h"
#include "vfs.h"
typedef enum {
OverrideChanged_FeedRate = 0,
@@ -107,6 +108,7 @@ typedef bool (*on_spindle_select_ptr)(spindle_ptrs_t *spindle);
typedef void (*on_spindle_selected_ptr)(spindle_ptrs_t *spindle);
typedef void (*on_gcode_message_ptr)(char *msg);
typedef void (*on_rt_reports_added_ptr)(report_tracking_flags_t report);
typedef status_code_t (*on_file_open_ptr)(const char *fname, vfs_file_t *handle, bool stream);
typedef status_code_t (*on_unknown_sys_command_ptr)(sys_state_t state, char *line); // return Status_Unhandled.
typedef status_code_t (*on_user_command_ptr)(char *line);
typedef sys_commands_t *(*on_get_commands_ptr)(void);
@@ -148,9 +150,10 @@ typedef struct {
on_toolchange_ack_ptr on_toolchange_ack; //!< Called from interrupt context.
on_jog_cancel_ptr on_jog_cancel; //!< Called from interrupt context.
on_laser_ppi_enable_ptr on_laser_ppi_enable;
on_spindle_select_ptr on_spindle_select; //!< Called before spindle is selected, hook in HAL overrides here
on_spindle_selected_ptr on_spindle_selected; //!< Called when spindle is selected, do not change HAL pointers here!
on_spindle_select_ptr on_spindle_select; //!< Called before spindle is selected, hook in HAL overrides here
on_spindle_selected_ptr on_spindle_selected; //!< Called when spindle is selected, do not change HAL pointers here!
on_reset_ptr on_reset; //!< Called from interrupt context.
on_file_open_ptr on_file_open; //!< Called when a file is opened for streaming.
// core entry points - set up by core before driver_init() is called.
enqueue_gcode_ptr enqueue_gcode;
enqueue_realtime_command_ptr enqueue_realtime_command;

View File

@@ -1014,7 +1014,7 @@ status_code_t gc_execute_block (char *block)
word_bit.modal_group.M7 = On;
gc_block.modal.spindle.state.on = !(int_value == 5);
gc_block.modal.spindle.state.ccw = int_value == 4;
sys.flags.delay_overrides = On;
sys.override_delay.spindle = On;
break;
case 6:
@@ -1028,7 +1028,7 @@ status_code_t gc_execute_block (char *block)
case 7: case 8: case 9:
word_bit.modal_group.M8 = On;
sys.flags.delay_overrides = On;
sys.override_delay.coolant = On;
gc_parser_flags.set_coolant = On;
switch(int_value) {
@@ -2856,7 +2856,7 @@ status_code_t gc_execute_block (char *block)
plan_data.condition.coolant = gc_state.modal.coolant; // Set condition flag for planner use.
sys.flags.delay_overrides = Off;
sys.override_delay.flags = 0;
// [9. Override control ]:
if (gc_state.modal.override_ctrl.value != gc_block.modal.override_ctrl.value) {

2
grbl.h
View File

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

View File

@@ -5,7 +5,7 @@
Part of grblHAL
Copyright (c) 2017-2019 Terje Io
Copyright (c) 2017-2023 Terje Io
Grbl is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -30,7 +30,7 @@ typedef struct {
uint8_t buf[OVERRIDE_BUFSIZE];
} override_queue_t;
static override_queue_t feed = {0}, accessory = {0};
static override_queue_t feed = {0}, spindle = {0}, coolant = {0};
ISR_CODE void ISR_FUNC(enqueue_feed_override)(uint8_t cmd)
{
@@ -56,30 +56,55 @@ uint8_t get_feed_override (void)
return data;
}
ISR_CODE void ISR_FUNC(enqueue_accessory_override)(uint8_t cmd)
ISR_CODE void ISR_FUNC(enqueue_spindle_override)(uint8_t cmd)
{
uint_fast8_t bptr = (accessory.head + 1) & (OVERRIDE_BUFSIZE - 1); // Get next head pointer
uint_fast8_t bptr = (spindle.head + 1) & (OVERRIDE_BUFSIZE - 1); // Get next head pointer
if(bptr != accessory.tail) { // If not buffer full
accessory.buf[accessory.head] = cmd; // add data to buffer
accessory.head = bptr; // and update pointer
if(bptr != spindle.tail) { // If not buffer full
spindle.buf[spindle.head] = cmd; // add data to buffer
spindle.head = bptr; // and update pointer
}
}
// Returns 0 if no commands enqueued
uint8_t get_accessory_override (void)
uint8_t get_spindle_override (void)
{
uint8_t data = 0;
uint_fast8_t bptr = accessory.tail;
uint_fast8_t bptr = spindle.tail;
if(bptr != accessory.head) {
data = accessory.buf[bptr++]; // Get next character, increment tmp pointer
accessory.tail = bptr & (OVERRIDE_BUFSIZE - 1); // and update pointer
if(bptr != spindle.head) {
data = spindle.buf[bptr++]; // Get next character, increment tmp pointer
spindle.tail = bptr & (OVERRIDE_BUFSIZE - 1); // and update pointer
}
return data;
}
void flush_override_buffers () {
feed.head = feed.tail = accessory.head = accessory.tail = 0;
ISR_CODE void ISR_FUNC(enqueue_coolant_override)(uint8_t cmd)
{
uint_fast8_t bptr = (coolant.head + 1) & (OVERRIDE_BUFSIZE - 1); // Get next head pointer
if(bptr != coolant.tail) { // If not buffer full
coolant.buf[coolant.head] = cmd; // add data to buffer
coolant.head = bptr; // and update pointer
}
}
// Returns 0 if no commands enqueued
uint8_t get_coolant_override (void)
{
uint8_t data = 0;
uint_fast8_t bptr = coolant.tail;
if(bptr != coolant.head) {
data = coolant.buf[bptr++]; // Get next character, increment tmp pointer
coolant.tail = bptr & (OVERRIDE_BUFSIZE - 1); // and update pointer
}
return data;
}
void flush_override_buffers (void)
{
feed.head = feed.tail = spindle.head = spindle.tail = coolant.head = coolant.tail = 0;
}

View File

@@ -5,7 +5,7 @@
Part of grblHAL
Copyright (c) 2016-2019 Terje Io
Copyright (c) 2016-2023 Terje Io
Grbl is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -31,7 +31,9 @@
void flush_override_buffers ();
void enqueue_feed_override (uint8_t cmd);
uint8_t get_feed_override (void);
void enqueue_accessory_override (uint8_t cmd);
uint8_t get_accessory_override (void);
void enqueue_spindle_override (uint8_t cmd);
uint8_t get_spindle_override (void);
void enqueue_coolant_override (uint8_t cmd);
uint8_t get_coolant_override (void);
#endif

View File

@@ -85,6 +85,11 @@
webui_init();
#endif
#if EMBROIDERY_ENABLE
extern void embroidery_init (void);
embroidery_init();
#endif
extern void my_plugin_init (void);
my_plugin_init();

View File

@@ -495,7 +495,7 @@ bool protocol_exec_rt_system (void)
sys.cancel = true;
sys.step_control.flags = 0;
sys.flags.feed_hold_pending = Off;
sys.flags.delay_overrides = Off;
sys.override_delay.flags = 0;
if(sys.override.control.sync)
sys.override.control = gc_state.modal.override_ctrl;
@@ -562,137 +562,152 @@ bool protocol_exec_rt_system (void)
grbl.on_execute_realtime(state_get());
if(!sys.flags.delay_overrides) {
// Execute overrides.
// Execute overrides.
if(!sys.override_delay.feedrate && (rt_exec = get_feed_override())) {
if((rt_exec = get_feed_override())) {
override_t new_f_override = sys.override.feed_rate;
override_t new_r_override = sys.override.rapid_rate;
override_t new_f_override = sys.override.feed_rate;
override_t new_r_override = sys.override.rapid_rate;
do {
do {
switch(rt_exec) {
switch(rt_exec) {
case CMD_OVERRIDE_FEED_RESET:
new_f_override = DEFAULT_FEED_OVERRIDE;
break;
case CMD_OVERRIDE_FEED_RESET:
new_f_override = DEFAULT_FEED_OVERRIDE;
break;
case CMD_OVERRIDE_FEED_COARSE_PLUS:
new_f_override += FEED_OVERRIDE_COARSE_INCREMENT;
break;
case CMD_OVERRIDE_FEED_COARSE_PLUS:
new_f_override += FEED_OVERRIDE_COARSE_INCREMENT;
break;
case CMD_OVERRIDE_FEED_COARSE_MINUS:
new_f_override -= FEED_OVERRIDE_COARSE_INCREMENT;
break;
case CMD_OVERRIDE_FEED_COARSE_MINUS:
new_f_override -= FEED_OVERRIDE_COARSE_INCREMENT;
break;
case CMD_OVERRIDE_FEED_FINE_PLUS:
new_f_override += FEED_OVERRIDE_FINE_INCREMENT;
break;
case CMD_OVERRIDE_FEED_FINE_PLUS:
new_f_override += FEED_OVERRIDE_FINE_INCREMENT;
break;
case CMD_OVERRIDE_FEED_FINE_MINUS:
new_f_override -= FEED_OVERRIDE_FINE_INCREMENT;
break;
case CMD_OVERRIDE_FEED_FINE_MINUS:
new_f_override -= FEED_OVERRIDE_FINE_INCREMENT;
break;
case CMD_OVERRIDE_RAPID_RESET:
new_r_override = DEFAULT_RAPID_OVERRIDE;
break;
case CMD_OVERRIDE_RAPID_RESET:
new_r_override = DEFAULT_RAPID_OVERRIDE;
break;
case CMD_OVERRIDE_RAPID_MEDIUM:
new_r_override = RAPID_OVERRIDE_MEDIUM;
break;
case CMD_OVERRIDE_RAPID_MEDIUM:
new_r_override = RAPID_OVERRIDE_MEDIUM;
break;
case CMD_OVERRIDE_RAPID_LOW:
new_r_override = RAPID_OVERRIDE_LOW;
break;
}
new_f_override = constrain(new_f_override, MIN_FEED_RATE_OVERRIDE, MAX_FEED_RATE_OVERRIDE);
} while((rt_exec = get_feed_override()));
plan_feed_override(new_f_override, new_r_override);
}
if((rt_exec = get_accessory_override())) {
bool spindle_stop = false;
spindle_ptrs_t *spindle = gc_spindle_get();
override_t last_s_override = spindle->param->override_pct;
coolant_state_t coolant_state = gc_state.modal.coolant;
do {
switch(rt_exec) {
case CMD_OVERRIDE_SPINDLE_RESET:
last_s_override = DEFAULT_SPINDLE_RPM_OVERRIDE;
break;
case CMD_OVERRIDE_SPINDLE_COARSE_PLUS:
last_s_override += SPINDLE_OVERRIDE_COARSE_INCREMENT;
break;
case CMD_OVERRIDE_SPINDLE_COARSE_MINUS:
last_s_override -= SPINDLE_OVERRIDE_COARSE_INCREMENT;
break;
case CMD_OVERRIDE_SPINDLE_FINE_PLUS:
last_s_override += SPINDLE_OVERRIDE_FINE_INCREMENT;
break;
case CMD_OVERRIDE_SPINDLE_FINE_MINUS:
last_s_override -= SPINDLE_OVERRIDE_FINE_INCREMENT;
break;
case CMD_OVERRIDE_SPINDLE_STOP:
spindle_stop = !spindle_stop;
break;
case CMD_OVERRIDE_COOLANT_MIST_TOGGLE:
if (hal.driver_cap.mist_control && ((state_get() == STATE_IDLE) || (state_get() & (STATE_CYCLE | STATE_HOLD)))) {
coolant_state.mist = !coolant_state.mist;
}
break;
case CMD_OVERRIDE_COOLANT_FLOOD_TOGGLE:
if ((state_get() == STATE_IDLE) || (state_get() & (STATE_CYCLE | STATE_HOLD))) {
coolant_state.flood = !coolant_state.flood;
}
break;
default:
if(grbl.on_unknown_accessory_override)
grbl.on_unknown_accessory_override(rt_exec);
break;
}
last_s_override = constrain(last_s_override, MIN_SPINDLE_RPM_OVERRIDE, MAX_SPINDLE_RPM_OVERRIDE);
} while((rt_exec = get_accessory_override()));
spindle_set_override(spindle, last_s_override);
// NOTE: Since coolant state always performs a planner sync whenever it changes, the current
// run state can be determined by checking the parser state.
if(coolant_state.value != gc_state.modal.coolant.value) {
coolant_set_state(coolant_state); // Report flag set in coolant_set_state().
gc_state.modal.coolant = coolant_state;
if(grbl.on_override_changed)
grbl.on_override_changed(OverrideChanged_CoolantState);
case CMD_OVERRIDE_RAPID_LOW:
new_r_override = RAPID_OVERRIDE_LOW;
break;
}
if (spindle_stop && state_get() == STATE_HOLD && gc_state.modal.spindle.state.on) {
// Spindle stop override allowed only while in HOLD state.
// NOTE: Report flag is set in spindle_set_state() when spindle stop is executed.
if (!sys.override.spindle_stop.value)
sys.override.spindle_stop.initiate = On;
else if (sys.override.spindle_stop.enabled)
sys.override.spindle_stop.restore = On;
new_f_override = constrain(new_f_override, MIN_FEED_RATE_OVERRIDE, MAX_FEED_RATE_OVERRIDE);
} while((rt_exec = get_feed_override()));
plan_feed_override(new_f_override, new_r_override);
}
if(!sys.override_delay.spindle && (rt_exec = get_spindle_override())) {
bool spindle_stop = false;
spindle_ptrs_t *spindle = gc_spindle_get();
override_t last_s_override = spindle->param->override_pct;
do {
switch(rt_exec) {
case CMD_OVERRIDE_SPINDLE_RESET:
last_s_override = DEFAULT_SPINDLE_RPM_OVERRIDE;
break;
case CMD_OVERRIDE_SPINDLE_COARSE_PLUS:
last_s_override += SPINDLE_OVERRIDE_COARSE_INCREMENT;
break;
case CMD_OVERRIDE_SPINDLE_COARSE_MINUS:
last_s_override -= SPINDLE_OVERRIDE_COARSE_INCREMENT;
break;
case CMD_OVERRIDE_SPINDLE_FINE_PLUS:
last_s_override += SPINDLE_OVERRIDE_FINE_INCREMENT;
break;
case CMD_OVERRIDE_SPINDLE_FINE_MINUS:
last_s_override -= SPINDLE_OVERRIDE_FINE_INCREMENT;
break;
case CMD_OVERRIDE_SPINDLE_STOP:
spindle_stop = !spindle_stop;
break;
default:
if(grbl.on_unknown_accessory_override)
grbl.on_unknown_accessory_override(rt_exec);
break;
}
last_s_override = constrain(last_s_override, MIN_SPINDLE_RPM_OVERRIDE, MAX_SPINDLE_RPM_OVERRIDE);
} while((rt_exec = get_spindle_override()));
spindle_set_override(spindle, last_s_override);
if (spindle_stop && state_get() == STATE_HOLD && gc_state.modal.spindle.state.on) {
// Spindle stop override allowed only while in HOLD state.
// NOTE: Report flag is set in spindle_set_state() when spindle stop is executed.
if (!sys.override.spindle_stop.value)
sys.override.spindle_stop.initiate = On;
else if (sys.override.spindle_stop.enabled)
sys.override.spindle_stop.restore = On;
}
} // End execute overrides.
}
if(!sys.override_delay.coolant && (rt_exec = get_coolant_override())) {
coolant_state_t coolant_state = gc_state.modal.coolant;
do {
switch(rt_exec) {
case CMD_OVERRIDE_COOLANT_MIST_TOGGLE:
if (hal.driver_cap.mist_control && ((state_get() == STATE_IDLE) || (state_get() & (STATE_CYCLE | STATE_HOLD)))) {
coolant_state.mist = !coolant_state.mist;
}
break;
case CMD_OVERRIDE_COOLANT_FLOOD_TOGGLE:
if ((state_get() == STATE_IDLE) || (state_get() & (STATE_CYCLE | STATE_HOLD))) {
coolant_state.flood = !coolant_state.flood;
}
break;
default:
if(grbl.on_unknown_accessory_override)
grbl.on_unknown_accessory_override(rt_exec);
break;
}
} while((rt_exec = get_coolant_override()));
// NOTE: Since coolant state always performs a planner sync whenever it changes, the current
// run state can be determined by checking the parser state.
if(coolant_state.value != gc_state.modal.coolant.value) {
coolant_set_state(coolant_state); // Report flag set in coolant_set_state().
gc_state.modal.coolant = coolant_state;
if(grbl.on_override_changed)
grbl.on_override_changed(OverrideChanged_CoolantState);
}
}
// End execute overrides.
// Reload step segment buffer
if (state_get() & (STATE_CYCLE | STATE_HOLD | STATE_SAFETY_DOOR | STATE_HOMING | STATE_SLEEP| STATE_JOG))
@@ -876,11 +891,15 @@ ISR_CODE bool ISR_FUNC(protocol_enqueue_realtime_command)(char c)
case CMD_OVERRIDE_SPINDLE_FINE_PLUS:
case CMD_OVERRIDE_SPINDLE_FINE_MINUS:
case CMD_OVERRIDE_SPINDLE_STOP:
drop = true;
enqueue_spindle_override((uint8_t)c);
break;
case CMD_OVERRIDE_COOLANT_FLOOD_TOGGLE:
case CMD_OVERRIDE_COOLANT_MIST_TOGGLE:
case CMD_OVERRIDE_FAN0_TOGGLE:
drop = true;
enqueue_accessory_override((uint8_t)c);
enqueue_coolant_override((uint8_t)c);
break;
case CMD_REBOOT:

View File

@@ -709,6 +709,7 @@ typedef enum {
Group_MotorDriver,
Group_VFD,
Group_CANbus,
Group_Embroidery,
Group_Axis,
// NOTE: axis groups MUST be sequential AND last
Group_Axis0,

View File

@@ -163,7 +163,7 @@ static bool initiate_hold (uint_fast16_t new_state)
restore_condition.coolant.mask = gc_state.modal.coolant.mask | hal.coolant.get_state().mask;
if (restore_condition.spindle[restore_condition.spindle_num].hal->cap.laser && settings.flags.disable_laser_during_hold)
enqueue_accessory_override(CMD_OVERRIDE_SPINDLE_STOP);
enqueue_spindle_override(CMD_OVERRIDE_SPINDLE_STOP);
if (sys_state & (STATE_CYCLE|STATE_JOG)) {
st_update_plan_block_parameters(); // Notify stepper module to recompute for hold deceleration.

View File

@@ -219,21 +219,30 @@ typedef struct {
gc_override_flags_t control; //!< Tracks override control states.
} overrides_t;
typedef union {
uint8_t flags;
struct {
uint16_t feedrate :1,
coolant :1,
spindle :1,
unused :5;
};
} system_override_delay_t;
typedef union {
uint16_t value;
struct {
uint16_t mpg_mode :1, //!< MPG mode flag. Set when switched to secondary input stream. (unused for now).
probe_succeeded :1, //!< Tracks if last probing cycle was successful.
soft_limit :1, //!< Tracks soft limit errors for the state machine.
exit :1, //!< System exit flag. Used in combination with abort to terminate main loop.
block_delete_enabled :1, //!< Set to true to enable block delete.
feed_hold_pending :1,
delay_overrides :1,
optional_stop_disable :1,
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.
unused :5;
uint16_t mpg_mode :1, //!< MPG mode flag. Set when switched to secondary input stream. (unused for now).
probe_succeeded :1, //!< Tracks if last probing cycle was successful.
soft_limit :1, //!< Tracks soft limit errors for the state machine.
exit :1, //!< System exit flag. Used in combination with abort to terminate main loop.
block_delete_enabled :1, //!< Set to true to enable block delete.
feed_hold_pending :1,
optional_stop_disable :1,
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.
unused :6;
};
} system_flags_t;
@@ -260,6 +269,7 @@ typedef struct system {
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.
overrides_t override; //!< Override values & states
system_override_delay_t override_delay; //!< Flags for delayed overrides.
report_tracking_flags_t report; //!< Tracks when to add data to status reports.
parking_state_t parking_state; //!< Tracks parking state
hold_state_t holding_state; //!< Tracks holding state

59
task.c Normal file
View File

@@ -0,0 +1,59 @@
#include "core_handlers.h"
/*
typedef struct {
volatile uint_fast8_t head;
volatile uint_fast8_t tail;
on_execute_realtime_ptr fn[RT_QUEUE_SIZE];
} realtime_queue_t;
static realtime_queue_t realtime_queue = {0};
// Enqueue a function to be called once by the
// foreground process, typically enqueued from an interrupt handler.
ISR_CODE bool ISR_FUNC(grbl_task_enqueue)(on_execute_realtime_ptr fn)
{
bool ok;
uint_fast8_t bptr = (realtime_queue.head + 1) & (RT_QUEUE_SIZE - 1); // Get next head pointer
if((ok = bptr != realtime_queue.tail)) { // If not buffer full
realtime_queue.fn[realtime_queue.head] = fn; // add function pointer to buffer,
realtime_queue.head = bptr; // update pointer and
system_set_exec_state_flag(EXEC_RT_COMMAND); // flag it for execute
}
return ok;
}
// Enqueue a function to be called once by the
// foreground process, typically enqueued from an interrupt handler.
ISR_CODE bool ISR_FUNC(grbl_task_enqueue_delayed)(on_execute_realtime_ptr fn, uint32_t ms_delay, void *context)
{
bool ok;
uint_fast8_t bptr = (realtime_queue.head + 1) & (RT_QUEUE_SIZE - 1); // Get next head pointer
if((ok = bptr != realtime_queue.tail)) { // If not buffer full
realtime_queue.fn[realtime_queue.head] = fn; // add function pointer to buffer,
realtime_queue.head = bptr; // update pointer and
system_set_exec_state_flag(EXEC_RT_COMMAND); // flag it for execute
}
return ok;
}
// Execute enqueued functions.
static void grbl_task_execute (void)
{
while(realtime_queue.tail != realtime_queue.head) {
uint_fast8_t bptr = realtime_queue.tail;
on_execute_realtime_ptr call;
if((call = realtime_queue.fn[bptr])) {
realtime_queue.fn[bptr] = NULL;
call(state_get());
}
realtime_queue.tail = (bptr + 1) & (RT_QUEUE_SIZE - 1);
}
if(!sys.driver_started)
while(true);
}
*/