diff --git a/CMakeLists.txt b/CMakeLists.txt
index fd74df4..db8fcc3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -5,7 +5,7 @@ target_sources(grbl INTERFACE
${CMAKE_CURRENT_LIST_DIR}/coolant_control.c
${CMAKE_CURRENT_LIST_DIR}/nvs_buffer.c
${CMAKE_CURRENT_LIST_DIR}/gcode.c
- ${CMAKE_CURRENT_LIST_DIR}/limits.c
+ ${CMAKE_CURRENT_LIST_DIR}/machine_limits.c
${CMAKE_CURRENT_LIST_DIR}/motion_control.c
${CMAKE_CURRENT_LIST_DIR}/my_plugin.c
${CMAKE_CURRENT_LIST_DIR}/nuts_bolts.c
diff --git a/README.md b/README.md
index a726af0..2340a91 100644
--- a/README.md
+++ b/README.md
@@ -11,7 +11,7 @@ It has been written to complement grblHAL and has features such as proper keyboa
---
-Latest build date is 20220904, see the [changelog](changelog.md) for details.
+Latest build date is 20220907, see the [changelog](changelog.md) for details.
__NOTE:__ A settings reset will be performed on an update for versions earlier than 20211122. Backup and restore of settings is recommended.
__IMPORTANT!__ A new setting has been introduced for ganged axes motors in version 20211121.
I have only bench tested this for a couple of drivers, correct function should be verified after updating by those who have more than three motors configured.
@@ -84,4 +84,4 @@ List of Supported G-Codes:
Some [plugins](https://github.com/grblHAL/plugins) implements additional M-codes.
---
-2022-09-04
+2022-09-07
diff --git a/changelog.md b/changelog.md
index 0ccf718..b9927a9 100644
--- a/changelog.md
+++ b/changelog.md
@@ -1,20 +1,46 @@
## grblHAL changelog
+20220905:
+
+Core:
+
+* Added `$RTC` system command for outputting or setting current real time clock date and time. Uses ISO8601 format.
+__Driver developers:__
+_grbl/limits.h_ has been renamed to _grbl/machine_limits.h_ (along with the _.c_ counterpart).
+[hal.enumerate_pins](http://svn.io-engineering.com/grblHAL/html/structgrbl__hal__t.html#a661c9aa458a2e6fc5fb1657e121999a3) and the associated [callback function](http://svn.io-engineering.com/grblHAL/html/hal_8h.html#a41e902cfc3da615f9494aba956d895ba) parameter has a new signature, a void pointer has been added. Driver implementations should pass this on to the callback.
+The HAL version number has been increased to 10 due to this, update _driver.c_ to match!
+
+Plugins:
+
+* WebUI: added many ESP commands to v3 command handler, some code refactoring. Still WIP.
+
+* Networking: some minor bug fixes.
+
+Drivers:
+
+* All: updated for _grbl/limits.h_ name change and HAL version number increase.
+
+* iMXRT1062, STM32F4xx, STM32F7xx and ESP32: Added RTC support.
+
+* ESP32: WebUI backend support improved.
+
+---
+
20220904:
Core:
-* Added optional RTC (Real Time Clock) support to the HAL. VFS improvements.
+* Added optional RTC \(Real Time Clock\) support to the HAL. VFS improvements.
Plugins:
-* Networking: improved websocket protocol handling.
+* Networking: improved websocket subprotocol handling.
* WebUI: separated command handlers for v2 and v3 and improved detection of v3 clients. Now sets RTC from ESP800 if HAL allows.
Drivers:
-* RP2040: Added RTC support++.
+* RP2040: Added RTC support++.
* iMXRT1062: updated uSDFS patch - needed for VFS changes.
diff --git a/grbl.h b/grbl.h
index cebad7c..51c4b3d 100644
--- a/grbl.h
+++ b/grbl.h
@@ -34,7 +34,7 @@
#else
#define GRBL_VERSION "1.1f"
#endif
-#define GRBL_BUILD 20220904
+#define GRBL_BUILD 20220906
// The following symbols are set here if not already set by the compiler or in config.h
// Do NOT change here!
diff --git a/grbllib.c b/grbllib.c
index 0997a67..576a42a 100644
--- a/grbllib.c
+++ b/grbllib.c
@@ -30,7 +30,7 @@
#include "tool_change.h"
#include "override.h"
#include "protocol.h"
-#include "limits.h"
+#include "machine_limits.h"
#include "report.h"
#include "state_machine.h"
#include "nvs_buffer.h"
diff --git a/hal.h b/hal.h
index 53c5aa8..e434052 100644
--- a/hal.h
+++ b/hal.h
@@ -40,7 +40,7 @@
#include "ioports.h"
#include "plugins.h"
-#define HAL_VERSION 9
+#define HAL_VERSION 10
/// Bitmap flags for driver capabilities, to be set by driver in driver_init(), flags may be cleared after to switch off option.
typedef union {
@@ -104,14 +104,15 @@ typedef struct {
/*! \brief Pointer to callback function for pin enumerations.
\param pin pointer to the \a xbar_t structure holding the pin information.
*/
-typedef void (*pin_info_ptr)(xbar_t *pin);
+typedef void (*pin_info_ptr)(xbar_t *pin, void *data);
/*! \brief Pointer to function for enumerate pin information.
\param low_level true if low level information is required, false if used for reporting.
\param callback pointer to a \a pin_info_ptr type function to receive the pin information.
The callback function will be called for each pin.
*/
-typedef void (*enumerate_pins_ptr)(bool low_level, pin_info_ptr callback);
+typedef void (*enumerate_pins_ptr)(bool low_level, pin_info_ptr callback, void *data);
+
/*************
* Coolant *
@@ -359,6 +360,7 @@ typedef struct {
probe_connected_toggle_ptr connected_toggle; //!< Optional handler for toggling probe connected status.
} probe_ptrs_t;
+
/*******************************
* Tool selection and change *
*******************************/
@@ -385,6 +387,7 @@ typedef struct {
tool_change_ptr change; //!< Optional handler for executing a tool change (M6).
} tool_ptrs_t;
+
/*****************
* User M-code *
*****************/
@@ -439,6 +442,7 @@ typedef struct {
user_mcode_execute_ptr execute; //!< Handler for executing a user defined M-code.
} user_mcode_ptrs_t;
+
/*******************
* Encoder input *
*******************/
diff --git a/limits.c b/machine_limits.c
similarity index 99%
rename from limits.c
rename to machine_limits.c
index 8d82c57..c6bf96d 100644
--- a/limits.c
+++ b/machine_limits.c
@@ -1,5 +1,5 @@
/*
- limits.c - code pertaining to limit-switches and performing the homing cycle
+ machine_limits.c - code pertaining to limit-switches and performing the homing cycle
Part of grblHAL
@@ -29,7 +29,7 @@
#include "nuts_bolts.h"
#include "protocol.h"
#include "motion_control.h"
-#include "limits.h"
+#include "machine_limits.h"
#include "tool_change.h"
#include "state_machine.h"
#ifdef KINEMATICS_API
diff --git a/limits.h b/machine_limits.h
similarity index 87%
rename from limits.h
rename to machine_limits.h
index 1d234e1..7719372 100644
--- a/limits.h
+++ b/machine_limits.h
@@ -1,9 +1,9 @@
/*
- limits.h - code pertaining to limit-switches and performing the homing cycle
+ machine_limits.h - code pertaining to limit-switches and performing the homing cycle
Part of grblHAL
- Copyright (c) 2017-2018 Terje Io
+ Copyright (c) 2017-2022 Terje Io
Copyright (c) 2012-2015 Sungeun K. Jeon
Copyright (c) 2009-2011 Simen Svale Skogsrud
@@ -21,8 +21,8 @@
along with Grbl. If not, see .
*/
-#ifndef _LIMITS_H_
-#define _LIMITS_H_
+#ifndef _MACHINE_LIMITS_H_
+#define _MACHINE_LIMITS_H_
#include "nuts_bolts.h"
diff --git a/motion_control.c b/motion_control.c
index 73307b4..cb1e73a 100644
--- a/motion_control.c
+++ b/motion_control.c
@@ -32,7 +32,7 @@
#include "hal.h"
#include "nuts_bolts.h"
#include "protocol.h"
-#include "limits.h"
+#include "machine_limits.h"
#include "state_machine.h"
#include "motion_control.h"
#include "tool_change.h"
diff --git a/nuts_bolts.c b/nuts_bolts.c
index 3417877..61fd90c 100644
--- a/nuts_bolts.c
+++ b/nuts_bolts.c
@@ -3,7 +3,7 @@
Part of grblHAL
- Copyright (c) 2017-2021 Terje Io
+ Copyright (c) 2017-2022 Terje Io
Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC
Copyright (c) 2009-2011 Simen Svale Skogsrud
@@ -24,6 +24,8 @@
#include
#include
#include
+#include
+#include
#include "hal.h"
#include "protocol.h"
@@ -263,6 +265,66 @@ float convert_delta_vector_to_unit_vector (float *vector)
return magnitude;
}
+// parse ISO8601 datetime: YYYY-MM-DDTHH:MM:SSZxxx
+struct tm *get_datetime (const char *s)
+{
+ static struct tm dt;
+ PROGMEM static const uint8_t mdays[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+
+ char *s1 = (char *)s, c;
+ uint_fast16_t idx = 0, value = 0;
+
+ memset(&dt, 0, sizeof(struct tm));
+ dt.tm_year = dt.tm_mon = dt.tm_mday = dt.tm_hour = dt.tm_min = dt.tm_sec = -1;
+
+ do {
+ c = *s1++;
+
+ if(isdigit(c))
+ value = (value * 10) + c - '0';
+
+ else if(!(c == '-' || c == ':' || c == 'T' || c == 'Z' || c == '\0'))
+ break;
+
+ else {
+ switch(idx) {
+ case 0:
+ if(c == '-' && value >= 1970 && value <= 2099)
+ dt.tm_year = value - 1900;
+ break;
+
+ case 1:
+ if(c == '-' && value >= 1 && value <= 12)
+ dt.tm_mon = value - 1;
+ break;
+
+ case 2:
+ if(c == 'T' && value >= 1 && value <= (mdays[dt.tm_mon >= 0 ? dt.tm_mon : 0] + (dt.tm_mon == 1 && dt.tm_year != 100 && (dt.tm_year % 4) == 0 ? 1 : 0)))
+ dt.tm_mday = value;
+ break;
+
+ case 3:
+ if(c == ':' && value <= 23)
+ dt.tm_hour = value;
+ break;
+
+ case 4:
+ if(c == ':' && value <= 59)
+ dt.tm_min = value;
+ break;
+
+ case 5:
+ if((c == 'Z' || c == '\0') && value <= 59)
+ dt.tm_sec = value;
+ break;
+ }
+ idx++;
+ value = 0;
+ }
+ } while(c);
+
+ return (dt.tm_year | dt.tm_mon | dt.tm_mday | dt.tm_hour | dt.tm_min | dt.tm_sec) > 0 ? &dt : NULL;
+}
// calculate checksum byte for data
uint8_t calc_checksum (uint8_t *data, uint32_t size) {
diff --git a/nuts_bolts.h b/nuts_bolts.h
index faecef4..ffb8ae8 100644
--- a/nuts_bolts.h
+++ b/nuts_bolts.h
@@ -206,6 +206,9 @@ void delay_sec(float seconds, delaymode_t mode);
float convert_delta_vector_to_unit_vector(float *vector);
+// parse ISO8601 datetime
+struct tm *get_datetime (const char *s);
+
// calculate checksum byte for data
uint8_t calc_checksum (uint8_t *data, uint32_t size);
diff --git a/plugins.h b/plugins.h
index 2034102..ed68b07 100644
--- a/plugins.h
+++ b/plugins.h
@@ -67,6 +67,7 @@ typedef union {
typedef char ssid_t[65];
typedef char password_t[33];
typedef char hostname_t[33];
+typedef char sntp_server_t[129]; // URI
typedef struct {
char ip[16];
diff --git a/protocol.c b/protocol.c
index 21dfff4..44fd60f 100644
--- a/protocol.c
+++ b/protocol.c
@@ -32,7 +32,7 @@
#include "motion_control.h"
#include "sleep.h"
#include "protocol.h"
-#include "limits.h"
+#include "machine_limits.h"
#ifndef RT_QUEUE_SIZE
#define RT_QUEUE_SIZE 8 // must be a power of 2
diff --git a/report.c b/report.c
index 177ed3b..5116518 100644
--- a/report.c
+++ b/report.c
@@ -36,7 +36,7 @@
#include "hal.h"
#include "report.h"
#include "nvs_buffer.h"
-#include "limits.h"
+#include "machine_limits.h"
#include "state_machine.h"
#include "regex.h"
@@ -842,6 +842,8 @@ void report_execute_startup_message (char *line, status_code_t status_code)
// Prints build info line
void report_build_info (char *line, bool extended)
{
+ char buf[100];
+
hal.stream.write("[VER:" GRBL_VERSION ".");
hal.stream.write(uitoa(GRBL_BUILD));
hal.stream.write(":");
@@ -997,6 +999,9 @@ void report_build_info (char *line, bool extended)
strcat(buf, "SED,");
#endif
+ if(hal.rtc.get_datetime)
+ strcat(buf, "RTC,");
+
#ifdef PID_LOG
strcat(buf, "PID,");
#endif
@@ -2072,7 +2077,7 @@ static const char *get_pinname (pin_function_t function)
return name ? name : "N/A";
}
-static void report_pin (xbar_t *pin)
+static void report_pin (xbar_t *pin, void *data)
{
hal.stream.write("[PIN:");
if(pin->port)
@@ -2090,11 +2095,40 @@ static void report_pin (xbar_t *pin)
status_code_t report_pins (sys_state_t state, char *args)
{
if(hal.enumerate_pins)
- hal.enumerate_pins(false, report_pin);
+ hal.enumerate_pins(false, report_pin, NULL);
return Status_OK;
}
+static void print_uito2a (char *prefix, uint32_t v)
+{
+ hal.stream.write(prefix);
+ if(v < 10)
+ hal.stream.write("0");
+ hal.stream.write(uitoa(v));
+}
+
+status_code_t report_time (void)
+{
+ bool ok = false;
+
+ if(hal.rtc.get_datetime) {
+ struct tm time;
+ if((ok = !!hal.rtc.get_datetime(&time))) {
+ hal.stream.write("[RTC:");
+ hal.stream.write(uitoa(time.tm_year + 1900));
+ print_uito2a("-", time.tm_mon + 1);
+ print_uito2a("-", time.tm_mday);
+ print_uito2a("T", time.tm_hour);
+ print_uito2a(":", time.tm_min);
+ print_uito2a(":", time.tm_sec);
+ hal.stream.write("]" ASCII_EOL);
+ }
+ }
+
+ return ok ? Status_OK : Status_InvalidStatement;
+}
+
void report_pid_log (void)
{
#ifdef PID_LOG
diff --git a/report.h b/report.h
index 9fda85b..e078fdb 100644
--- a/report.h
+++ b/report.h
@@ -117,6 +117,9 @@ status_code_t report_spindle_data (sys_state_t state, char *args);
// Prints pin assignments
status_code_t report_pins (sys_state_t state, char *args);
+// Prints current RTC datetime in ISO8601 format (when available)
+status_code_t report_time (void);
+
// Prints current PID log.
void report_pid_log (void);
diff --git a/settings.c b/settings.c
index e4f10ac..e54a3a6 100644
--- a/settings.c
+++ b/settings.c
@@ -29,7 +29,7 @@
#include "hal.h"
#include "defaults.h"
-#include "limits.h"
+#include "machine_limits.h"
#include "nvs_buffer.h"
#include "tool_change.h"
#include "state_machine.h"
diff --git a/settings.h b/settings.h
index 98135c0..da52482 100644
--- a/settings.h
+++ b/settings.h
@@ -197,6 +197,11 @@ typedef enum {
Setting_AdminPassword = 330,
Setting_UserPassword = 331,
+ Setting_NTPServerURI = 332,
+ Setting_NTPServerURI_2 = 333,
+ Setting_NTPServerURI_3 = 334,
+ Setting_Timezone = 335,
+ Setting_DSTActive = 336,
Setting_TrinamicDriver = 338,
Setting_TrinamicHoming = 339,
@@ -344,7 +349,7 @@ typedef union {
struct {
uint16_t report_inches :1,
restore_overrides :1,
- unused0 :1,
+ dst_active :1, // Daylight savings time
sleep_enable :1,
disable_laser_during_hold :1,
force_initialization_alarm :1,
diff --git a/stream.h b/stream.h
index a57240f..de0aa28 100644
--- a/stream.h
+++ b/stream.h
@@ -82,8 +82,8 @@ typedef enum {
StreamType_Bluetooth,
StreamType_Telnet,
StreamType_WebSocket,
- StreamType_SDCard,
- StreamType_FlashFs,
+ StreamType_SDCard, // deprecated, use StreamType_File instead
+ StreamType_File = StreamType_SDCard,
StreamType_Redirected,
StreamType_Null
} stream_type_t;
diff --git a/system.c b/system.c
index b9a04f7..b13816d 100644
--- a/system.c
+++ b/system.c
@@ -28,7 +28,7 @@
#include "protocol.h"
#include "tool_change.h"
#include "state_machine.h"
-#include "limits.h"
+#include "machine_limits.h"
#ifdef KINEMATICS_API
#include "kinematics.h"
#endif
@@ -79,6 +79,7 @@ static status_code_t settings_reset (sys_state_t state, char *args);
static status_code_t output_startup_lines (sys_state_t state, char *args);
static status_code_t set_startup_line0 (sys_state_t state, char *args);
static status_code_t set_startup_line1 (sys_state_t state, char *args);
+static status_code_t rtc_action (sys_state_t state, char *args);
#ifdef DEBUGOUT
static status_code_t output_memmap (sys_state_t state, char *args);
#endif
@@ -232,6 +233,7 @@ PROGMEM static const sys_command_t sys_commands[] = {
{ "LIM", true, report_current_limit_state },
{ "SD", false, report_spindle_data },
{ "SR", false, spindle_reset_data },
+ { "RTC", false, rtc_action },
#ifdef DEBUGOUT
{ "Q", true, output_memmap },
#endif
@@ -286,6 +288,10 @@ void system_command_help (void)
hal.stream.write("$PINS - enumerate pin bindings" ASCII_EOL);
hal.stream.write("$LEV - output last control signal events" ASCII_EOL);
hal.stream.write("$LIM - output current limit pins state" ASCII_EOL);
+ if(hal.rtc.get_datetime) {
+ hal.stream.write("$RTC - output current time" ASCII_EOL);
+ hal.stream.write("$RTC= - set current time" ASCII_EOL);
+ }
#ifndef NO_SETTINGS_DESCRIPTIONS
hal.stream.write("$SED= - output settings description for setting " ASCII_EOL);
#endif
@@ -869,6 +875,24 @@ static status_code_t set_startup_line1 (sys_state_t state, char *args)
return set_startup_line(state, args, 1);
}
+static status_code_t rtc_action (sys_state_t state, char *args)
+{
+ status_code_t retval = Status_OK;
+
+ if(args) {
+
+ struct tm *time = get_datetime(args);
+
+ if(time)
+ hal.rtc.set_datetime(time);
+ else
+ retval = Status_BadNumberFormat;
+ } else
+ retval = report_time();
+
+ return retval;
+}
+
#ifdef DEBUGOUT
#include "nvs_buffer.h"
diff --git a/vfs.c b/vfs.c
index 47fc5a0..105d9f6 100644
--- a/vfs.c
+++ b/vfs.c
@@ -101,6 +101,9 @@ static char *fs_getcwd (char *buf, size_t size)
}
static const vfs_t fs_null = {
+ .mode.directory = true,
+ .mode.hidden = true,
+ .mode.read_only = true,
.fopen = fs_open,
.fclose = fs_close,
.fread = fs_read,
@@ -412,19 +415,73 @@ bool vfs_unmount (const char *path)
return true;
}
-#endif
-
-/*
-struct tm *gmtime (const time_t *c_t)
+vfs_drives_t *vfs_drives_open (void)
{
- static struct tm dummy = {
- .tm_year = 70,
- .tm_mon = 0,
- .tm_mday = 1,
- .tm_hour = 0,
- .tm_min = 0
- };
+ vfs_drives_t *handle;
+ vfs_mount_t *mount = &root;
- return &dummy;
+ if((handle = malloc(sizeof(vfs_drives_t)))) {
+
+ handle->mount = NULL;
+ do {
+ if(mount->vfs->mode.hidden)
+ mount = mount->next;
+ else
+ handle->mount = mount;
+ } while(mount && handle->mount == NULL);
+
+ if(handle->mount == NULL) {
+ free(handle);
+ handle = NULL;
+ }
+ }
+
+ return handle;
}
-*/
+
+vfs_drive_t *vfs_drives_read (vfs_drives_t *handle)
+{
+ static vfs_drive_t drive;
+
+ bool ok;
+
+ if((ok = handle->mount != NULL)) {
+
+ drive.name = handle->mount->vfs->fs_name;
+ drive.path = (const char *)handle->mount->path;
+ drive.mode = handle->mount->vfs->mode;
+ drive.fs = handle->mount->vfs;
+
+ handle->mount = handle->mount->next;
+
+ if(handle->mount) do {
+ if(!handle->mount->vfs->mode.hidden && handle->mount->vfs->fs_name)
+ break;
+ } while((handle->mount = handle->mount->next));
+ }
+
+ return ok ? &drive : NULL;
+}
+
+void vfs_drives_close (vfs_drives_t *handle)
+{
+ free(handle);
+}
+
+vfs_free_t *vfs_drive_getfree (vfs_drive_t *drive)
+{
+ static vfs_free_t free;
+
+ const vfs_t *fs = drive->fs;
+
+ return fs->fgetfree && fs->fgetfree(&free) ? &free : NULL;
+}
+
+int vfs_drive_format (vfs_drive_t *drive)
+{
+ const vfs_t *fs = drive->fs;
+
+ return fs->format ? fs->format() : -1;
+}
+
+#endif
diff --git a/vfs.h b/vfs.h
index f6671a7..e01d14d 100644
--- a/vfs.h
+++ b/vfs.h
@@ -92,8 +92,8 @@ typedef struct {
} vfs_dirent_t;
typedef struct {
- uint64_t size;
- uint64_t used;
+ size_t size;
+ size_t used;
} vfs_free_t;
typedef struct {
@@ -123,6 +123,7 @@ typedef int (*vfs_stat_ptr)(const char *filename, vfs_stat_t *st);
typedef int (*vfs_utime_ptr)(const char *filename, struct tm *modified);
typedef bool (*vfs_getfree_ptr)(vfs_free_t *free);
+typedef int (*vfs_format_ptr)(void);
typedef struct
{
@@ -147,6 +148,7 @@ typedef struct
vfs_utime_ptr futime;
vfs_getcwd_ptr fgetcwd;
vfs_getfree_ptr fgetfree;
+ vfs_format_ptr format;
} vfs_t;
typedef struct vfs_mount
@@ -156,6 +158,17 @@ typedef struct vfs_mount
struct vfs_mount *next;
} vfs_mount_t;
+typedef struct {
+ vfs_mount_t *mount;
+} vfs_drives_t;
+
+typedef struct {
+ const char *name;
+ const char *path;
+ vfs_st_mode_t mode;
+ const void *fs;
+} vfs_drive_t;
+
extern int vfs_errno;
char *vfs_fixpath (char *path);
@@ -183,4 +196,10 @@ 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);
-#endif
+vfs_drives_t *vfs_drives_open (void);
+vfs_drive_t *vfs_drives_read (vfs_drives_t *handle);
+void vfs_drives_close (vfs_drives_t *handle);
+vfs_free_t *vfs_drive_getfree (vfs_drive_t *drive);
+int vfs_drive_format (vfs_drive_t *drive);
+
+#endif // INCLUDE_VFS_H