diff --git a/README.md b/README.md index 59efef3..c36e9ad 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ## grblHAL ## -Latest build date is 20250222, see the [changelog](changelog.md) for details. +Latest build date is 20250225, 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. @@ -89,4 +89,4 @@ G/M-codes not supported by [legacy Grbl](https://github.com/gnea/grbl/wiki) are Some [plugins](https://github.com/grblHAL/plugins) implements additional M-codes. --- -20250222 +20250225 diff --git a/changelog.md b/changelog.md index 3b56655..f05763b 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,33 @@ ## grblHAL changelog +Build 20250225 + +Core \(for developers\): + +* Added `vfs_chmod()` to VFS \(Virtual File System\), for setting basic file attributes. + +* Changed signature of `vfs.on_mount() event`. + +* Added `grbl.on_cycle_start()` event, fired on cycle start signal asserted or on cycle start real time command received. + +Drivers: + +* ESP32 and RP2040: updated for plugin changes. + +Plugins: + +* SD card: moved file streaming code out of main _SD card_ plugin to new sub-plugin _FS stream_ - allows builds without SD card enabled to stream gcode from flash \(stored in littlefs\). +Add `#define LITTLEFS_ENABLE 2` to _my_machine.h_ to enable, this will mount littlefs as the root file system. Only available for drivers/boards that has littlefs support. +Added `vfs_chmod()` implementation for FatFS and littlefs VFS drivers. +Fixed rewind bug, ref. issue [#8](https://github.com/grblHAL/Plugin_SD_card/issues/8). + +* Networking, WebUI and Plasma: removed reliance on SD card plugin for related features, moved to new _FS stream_ plugin instead. Updated file headers and done some general cleanup. + +* WebUI: now checks _hidden_ file attribute and only lists hidden files in the management \(forcefallback\) page. +Files uploaded to littlefs from the management page will now get the _hidden_ attribute set automatically. + +--- + Build 20250223 Core: @@ -11,7 +39,7 @@ Plugins: * Networking and WebUI: updated for move of string utilities to the core. * Plasma: enhanced basic materials support and added import of LinuxCNC and SheetCam style [material files](https://github.com/grblHAL/Plugin_plasma#materials). - Added support for setting feedrate via named parameter set from value in seleced material. + Added support for setting feedrate via named parameter set from value in selected material. --- diff --git a/core_handlers.h b/core_handlers.h index 62620c4..c7140bd 100644 --- a/core_handlers.h +++ b/core_handlers.h @@ -92,6 +92,7 @@ typedef void (*on_wco_changed_ptr)(void); typedef void (*on_program_completed_ptr)(program_flow_t program_flow, bool check_mode); typedef void (*on_execute_realtime_ptr)(sys_state_t state); typedef void (*on_unknown_accessory_override_ptr)(uint8_t cmd); +typedef void (*on_cycle_start_ptr)(void); typedef bool (*on_unknown_realtime_cmd_ptr)(char c); typedef void (*on_report_handlers_init_ptr)(void); typedef void (*on_report_options_ptr)(bool newopt); @@ -233,9 +234,10 @@ typedef struct { on_get_settings_ptr on_get_settings; on_realtime_report_ptr on_realtime_report; on_unknown_feedback_message_ptr on_unknown_feedback_message; - on_unknown_realtime_cmd_ptr on_unknown_realtime_cmd; - on_unknown_sys_command_ptr on_unknown_sys_command; //!< return Status_Unhandled if not handled. - on_get_commands_ptr on_get_commands; //!< Deprecated, use system_register_commands() to register new commands. + on_cycle_start_ptr on_cycle_start; //!< Called from interrupt context. NOTE: this is for the cycle start signal. + on_unknown_realtime_cmd_ptr on_unknown_realtime_cmd; //!< Called from interrupt context. + on_unknown_sys_command_ptr on_unknown_sys_command; //!< return Status_Unhandled if not handled. + on_get_commands_ptr on_get_commands; //!< Deprecated, use system_register_commands() to register new commands. on_user_command_ptr on_user_command; on_stream_changed_ptr on_stream_changed; on_homing_rate_set_ptr on_homing_rate_set; diff --git a/driver_opts.h b/driver_opts.h index 4ed209f..7483c38 100644 --- a/driver_opts.h +++ b/driver_opts.h @@ -512,13 +512,17 @@ #undef WEBSOCKET_ENABLE #endif #define WEBSOCKET_ENABLE 1 -#if defined(SDCARD_ENABLE) && SDCARD_ENABLE == 0 +#if defined(SDCARD_ENABLE) && SDCARD_ENABLE == 0 && LITTLEFS_ENABLE != 2 #undef SDCARD_ENABLE #endif #ifndef SDCARD_ENABLE +#if LITTLEFS_ENABLE == 2 +#define SDCARD_ENABLE 0 +#else #define SDCARD_ENABLE 1 #endif #endif +#endif #ifndef ETHERNET_ENABLE #define ETHERNET_ENABLE 0 @@ -664,6 +668,30 @@ #endif #endif +#define FS_FATFS 0b00001 +#define FS_SDCARD 0b00010 +#define FS_LFS 0b00100 +#define FS_LFS_ROOT 0b01000 +#define FS_YMODEM 0b10000 + +#if SDCARD_ENABLE && LITTLEFS_ENABLE +#if SDCARD_ENABLE == 2 +#define FS_ENABLE (FS_SDCARD|FS_FATFS|FS_LFS|FS_YMODEM) +#else +#define FS_ENABLE (FS_SDCARD|FS_FATFS|FS_LFS) +#endif +#elif LITTLEFS_ENABLE == 2 +#define FS_ENABLE (FS_LFS|FS_LFS_ROOT|FS_YMODEM) +#elif LITTLEFS_ENABLE +#define FS_ENABLE FS_LFS +#elif SDCARD_ENABLE == 1 +#define FS_ENABLE (FS_SDCARD|FS_FATFS) +#elif SDCARD_ENABLE == 2 +#define FS_ENABLE (FS_SDCARD|FS_FATFS|FS_YMODEM) +#else +#define FS_ENABLE 0 +#endif + #ifndef SPI_ENABLE #if SDCARD_ENABLE || TRINAMIC_SPI_ENABLE #define SPI_ENABLE 1 diff --git a/errors.h b/errors.h index 00c015c..8fe5443 100644 --- a/errors.h +++ b/errors.h @@ -89,10 +89,12 @@ typedef enum { Status_UnexpectedDemarcation = 57, Status_SDMountError = 60, - Status_SDReadError = 61, - Status_SDFailedOpenDir = 62, - Status_SDDirNotFound = 63, + Status_FileReadError = 61, + Status_FsFailedOpenDir = 62, + Status_FSDirNotFound = 63, Status_SDNotMounted = 64, + Status_FsNotMounted = 65, + Status_FsReadOnly = 66, Status_BTInitError = 70, diff --git a/plugins_init.h b/plugins_init.h index ed0fb39..a4fed6b 100644 --- a/plugins_init.h +++ b/plugins_init.h @@ -7,22 +7,27 @@ Part of grblHAL - Copyright (c) 2021-2023 Terje Io + Copyright (c) 2021-2025 Terje Io - Grbl is free software: you can redistribute it and/or modify + 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. - Grbl is distributed in the hope that it will be useful, + 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 + 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 Grbl. If not, see . + along with grblHAL. If not, see . */ +#if SDCARD_ENABLE || LITTLEFS_ENABLE == 2 + extern void fs_stream_init (void); + fs_stream_init(); +#endif + #if TRINAMIC_ENABLE extern bool trinamic_init (void); trinamic_init(); diff --git a/protocol.c b/protocol.c index cc7318c..721fe2e 100644 --- a/protocol.c +++ b/protocol.c @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2017-2024 Terje Io + Copyright (c) 2017-2025 Terje Io Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC Copyright (c) 2009-2011 Simen Svale Skogsrud @@ -914,6 +914,8 @@ ISR_CODE bool ISR_FUNC(protocol_enqueue_realtime_command)(char c) // Cancel any pending tool change gc_state.tool_change = false; drop = true; + if(grbl.on_cycle_start) + grbl.on_cycle_start(); break; case CMD_FEED_HOLD: @@ -1034,6 +1036,8 @@ ISR_CODE bool ISR_FUNC(protocol_enqueue_realtime_command)(char c) // Cancel any pending tool change gc_state.tool_change = false; drop = true; + if(grbl.on_cycle_start) + grbl.on_cycle_start(); } break; diff --git a/settings.c b/settings.c index 15893ca..fe2fb74 100644 --- a/settings.c +++ b/settings.c @@ -2109,7 +2109,7 @@ PROGMEM static const setting_detail_t setting_detail[] = { { Setting_AxisHomingFeedRate, Group_Axis0, "-axis homing locate feed rate", axis_rate, Format_Decimal, "###0", NULL, NULL, Setting_NonCoreFn, set_axis_setting, get_float, is_setting_available, AXIS_OPTS }, { Setting_AxisHomingSeekRate, Group_Axis0, "-axis homing search seek rate", axis_rate, Format_Decimal, "###0", NULL, NULL, Setting_NonCoreFn, set_axis_setting, get_float, is_setting_available, AXIS_OPTS }, { Setting_SpindleAtSpeedTolerance, Group_Spindle, "Spindle at speed tolerance", "percent", Format_Decimal, "##0.0", NULL, NULL, Setting_IsExtendedFn, set_float, get_float, is_setting_available }, - { Setting_ToolChangeMode, Group_Toolchange, "Tool change mode", NULL, Format_RadioButtons, "Normal,Manual touch off,Manual touch off @ G59.3,Automatic touch off @ G59.3,Ignore M6, Fast Automatic touch off @ G59.3", NULL, NULL, Setting_IsExtendedFn, set_tool_change_mode, get_int, is_setting_available }, + { Setting_ToolChangeMode, Group_Toolchange, "Tool change mode", NULL, Format_RadioButtons, "Normal,Manual touch off,Manual touch off @ G59.3,Automatic touch off @ G59.3,Ignore M6,Fast Automatic touch off @ G59.3", NULL, NULL, Setting_IsExtendedFn, set_tool_change_mode, get_int, is_setting_available }, { Setting_ToolChangeProbingDistance, Group_Toolchange, "Tool change probing distance", "mm", Format_Decimal, "#####0.0", NULL, NULL, Setting_IsExtendedFn, set_tool_change_probing_distance, get_float, is_setting_available }, { Setting_ToolChangeFeedRate, Group_Toolchange, "Tool change locate feed rate", "mm/min", Format_Decimal, "#####0.0", NULL, NULL, Setting_IsExtended, &settings.tool_change.feed_rate, NULL, is_setting_available }, { Setting_ToolChangeSeekRate, Group_Toolchange, "Tool change search seek rate", "mm/min", Format_Decimal, "#####0.0", NULL, NULL, Setting_IsExtended, &settings.tool_change.seek_rate, NULL, is_setting_available }, diff --git a/stream.c b/stream.c index 765c025..52ec5bf 100644 --- a/stream.c +++ b/stream.c @@ -300,8 +300,6 @@ static bool stream_select (const io_stream_t *stream, bool add) } else if(add_connection(stream) == NULL) return false; - bool webui_connected = hal.stream.state.webui_connected; - switch(stream->type) { case StreamType_Serial: @@ -354,9 +352,6 @@ static bool stream_select (const io_stream_t *stream, bool add) if(hal.stream.is_connected == NULL) hal.stream.is_connected = stream == base.stream ? base.is_up : stream_connected; - if(stream->type == StreamType_WebSocket && !stream->state.webui_connected) - hal.stream.state.webui_connected = webui_connected; - if(send_init_message) grbl.report.init_message(stream->write); diff --git a/system.c b/system.c index 8fd96ea..83034a6 100644 --- a/system.c +++ b/system.c @@ -3,7 +3,7 @@ Part of grblHAL - Copyright (c) 2017-2024 Terje Io + Copyright (c) 2017-2025 Terje Io Copyright (c) 2014-2016 Sungeun K. Jeon for Gnea Research LLC grblHAL is free software: you can redistribute it and/or modify @@ -112,6 +112,8 @@ ISR_CODE void ISR_FUNC(control_interrupt_handler)(control_signals_t signals) system_set_exec_state_flag(EXEC_CYCLE_START); sys.report.cycle_start = settings.status_report.pin_state; gc_state.tool_change = false; + if(grbl.on_cycle_start) + grbl.on_cycle_start(); } if(signals.block_delete) diff --git a/vfs.c b/vfs.c index 36ccdea..bc3e521 100644 --- a/vfs.c +++ b/vfs.c @@ -502,6 +502,13 @@ char *vfs_getcwd (char *buf, size_t len) return buf ? buf : cwds; } +int vfs_chmod (const char *filename, vfs_st_mode_t attr, vfs_st_mode_t mask) +{ + vfs_mount_t *mount = get_mount(filename); + + return mount && mount->vfs->fchmod ? mount->vfs->fchmod(get_filename(mount, filename), attr, mask) : -1; +} + int vfs_stat (const char *filename, vfs_stat_t *st) { vfs_mount_t *mount = get_mount(filename); @@ -598,7 +605,7 @@ bool vfs_mount (const char *path, const vfs_t *fs, vfs_st_mode_t mode) hal.rtc.get_datetime = vfs_get_time; if(fs && vfs.on_mount) - vfs.on_mount(path, fs); + vfs.on_mount(path, fs, mode); return fs != NULL; } diff --git a/vfs.h b/vfs.h index bacb789..b2d4a33 100644 --- a/vfs.h +++ b/vfs.h @@ -101,6 +101,7 @@ typedef struct { typedef struct { const char *name; size_t size; + vfs_st_mode_t st_mode; const uint8_t data[]; } embedded_file_t; @@ -121,6 +122,7 @@ typedef int (*vfs_rmdir_ptr)(const char *path); typedef vfs_dir_t *(*vfs_opendir_ptr)(const char *path); typedef char *(*vfs_readdir_ptr)(vfs_dir_t *dir, vfs_dirent_t *dirent); typedef void (*vfs_closedir_ptr)(vfs_dir_t *dir); +typedef int (*vfs_chmod_ptr)(const char *filename, vfs_st_mode_t attr, vfs_st_mode_t mask); typedef int (*vfs_stat_ptr)(const char *filename, vfs_stat_t *st); typedef int (*vfs_utime_ptr)(const char *filename, struct tm *modified); @@ -146,6 +148,7 @@ typedef struct vfs_opendir_ptr fopendir; vfs_readdir_ptr readdir; vfs_closedir_ptr fclosedir; + vfs_chmod_ptr fchmod; vfs_stat_ptr fstat; vfs_utime_ptr futime; vfs_getcwd_ptr fgetcwd; @@ -154,7 +157,7 @@ typedef struct } vfs_t; typedef void (*on_vfs_changed_ptr)(const vfs_t *fs); -typedef void (*on_vfs_mount_ptr)(const char *path, const vfs_t *fs); +typedef void (*on_vfs_mount_ptr)(const char *path, const vfs_t *fs, vfs_st_mode_t mode); typedef void (*on_vfs_unmount_ptr)(const char *path); typedef struct { @@ -224,6 +227,7 @@ vfs_dir_t *vfs_opendir (const char *path); vfs_dirent_t *vfs_readdir (vfs_dir_t *dir); void vfs_closedir (vfs_dir_t *dir); char *vfs_getcwd (char *buf, size_t len); +int vfs_chmod (const char *filename, vfs_st_mode_t attr, vfs_st_mode_t mask); int vfs_stat (const char *filename, vfs_stat_t *st); int vfs_utime (const char *filename, struct tm *modified); vfs_free_t *vfs_fgetfree (const char *path);