From 74eb4565330df45386573e1423dc051cc1dff7b7 Mon Sep 17 00:00:00 2001 From: Terje Io Date: Sat, 5 Jul 2025 14:17:11 +0200 Subject: [PATCH] Added ioports API call for remapping port numbers. Added HAL support for setting serial stream format. Added setting $681 for configuring Modbus RTU stream parity, available when the underlying driver supports format setting. --- README.md | 2 +- changelog.md | 19 +++++++++++++++++++ config.h | 18 ++++++++++++++++++ grbl.h | 2 +- ioports.c | 25 +++++++++++++++++++++++++ ioports.h | 1 + modbus_rtu.c | 47 +++++++++++++++++++++++++++++++++++------------ settings.c | 3 +++ settings.h | 5 ++++- stream.h | 35 +++++++++++++++++++++++++++++++++++ 10 files changed, 142 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index b30da88..89b8087 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ## grblHAL ## -Latest build date is 20250702, see the [changelog](changelog.md) for details. +Latest build date is 20250705, 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. diff --git a/changelog.md b/changelog.md index ce1bca7..6e1cd4b 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,24 @@ ## grblHAL changelog +Build 20250705 + +Core: + +* Added ioports API call for remapping port numbers. + +* Added HAL support for setting serial stream format. Added setting `$681` for configuring Modbus RTU stream parity, available when the underlying driver supports format setting. +Ref. STM32F7xx driver PR [#51](https://github.com/dresco/STM32H7xx/pull/51). + +Drivers: + +* STM32F4xx: added basic support for setting serial stream format, parity only for now. + +Plugins: + +* Plasma: updated to use new call for remapping portnumbers for virtual ports. Potential fix for ioSender issue [#470](https://github.com/terjeio/ioSender/issues/470). + +--- + Build 20250702 Core: diff --git a/config.h b/config.h index 1fde663..9997066 100644 --- a/config.h +++ b/config.h @@ -2055,6 +2055,24 @@ G90 #endif ///@} +/*! @name $374 - Settings_ModBus_BaudRate +Default baud rate for ModBus RTU stream. +*/ +///@{ +#if !defined DEFAULT_MODBUS_STREAM_BAUD || defined __DOXYGEN__ +#define DEFAULT_MODBUS_STREAM_BAUD 3 // 0 = 2400, 1 = 4800, 2 = 9600, 3 = 19200, 4 = 38400, 5 = 115200 +#endif +///@} + +/*! @name $681 - Setting_ModBus_StreamFormat +Default stream format settings for ModBus RTU stream. +*/ +///@{ +#if !defined DEFAULT_MODBUS_STREAM_PARITY || defined __DOXYGEN__ +#define DEFAULT_MODBUS_STREAM_PARITY 0 // 0 = None, 1 = Even, 2 = Odd +#endif +///@} + // Axis settings (Group_XAxis - Group_VAxis) /*! @name $10x - Setting_AxisStepsPerMM diff --git a/grbl.h b/grbl.h index 9c722c6..7d246d3 100644 --- a/grbl.h +++ b/grbl.h @@ -42,7 +42,7 @@ #else #define GRBL_VERSION "1.1f" #endif -#define GRBL_BUILD 20250702 +#define GRBL_BUILD 20250705 #define GRBL_URL "https://github.com/grblHAL" diff --git a/ioports.c b/ioports.c index b9cb565..4a092ce 100644 --- a/ioports.c +++ b/ioports.c @@ -532,6 +532,31 @@ bool ioport_digital_pwm_config (uint8_t port, pwm_config_t *config) return ok && pin->config(pin, config, false); } +/*! \brief Remap (virtual) 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_from the assigned port number. +\param port_to the remapped port number. The original port number will be shadowed. +\returns \a true if successful, \a false if original port is already claimed. +*/ +bool ioport_remap (io_port_type_t type, io_port_direction_t dir, uint8_t port_from, uint8_t port_to) +{ + uint8_t org_port; + bool ok; + io_ports_private_t *cfg = get_port_data(type, dir); + + if((ok = (cfg->claimed.mask & (1UL << port_to))) == 0) { + + if((org_port = map_reverse(cfg, port_from)) != port_to) + cfg->map[org_port] = 255; + + cfg->free = -1; + cfg->map[port_to] = port_from; + } + + return ok; +} + // HAL wrapper/veneers __STATIC_FORCEINLINE bool is_match (io_ports_list_t *io_port, io_port_type_t type, io_port_direction_t dir, uint8_t port) diff --git a/ioports.h b/ioports.h index 8dcb149..ecd6759 100644 --- a/ioports.h +++ b/ioports.h @@ -269,6 +269,7 @@ typedef struct { bool ioports_add_analog (io_analog_t *ports); bool ioports_add_digital (io_digital_t *ports); void ioports_add_settings (driver_settings_load_ptr settings_loaded, setting_changed_ptr setting_changed); +bool ioport_remap (io_port_type_t type, io_port_direction_t dir, uint8_t from, uint8_t to); void ioport_save_input_settings (xbar_t *xbar, gpio_in_config_t *config); void ioport_save_output_settings (xbar_t *xbar, gpio_out_config_t *config); void ioport_setting_changed (setting_id_t id); diff --git a/modbus_rtu.c b/modbus_rtu.c index a91d23d..0ce8fc6 100644 --- a/modbus_rtu.c +++ b/modbus_rtu.c @@ -33,10 +33,6 @@ #include "state_machine.h" #include "modbus.h" -#ifndef MODBUS_BAUDRATE -#define MODBUS_BAUDRATE 3 // 19200 -#endif - typedef enum { ModBus_Idle, ModBus_Silent, @@ -52,7 +48,8 @@ typedef void (*stream_set_direction_ptr)(bool tx); typedef struct { set_baud_rate_ptr set_baud_rate; - stream_set_direction_ptr set_direction; // NULL if auto direction + set_format_ptr set_format; //!< Optional handler for setting the stream format. + stream_set_direction_ptr set_direction; //!< NULL if auto direction get_stream_buffer_count_ptr get_tx_buffer_count; get_stream_buffer_count_ptr get_rx_buffer_count; stream_write_n_ptr write; @@ -389,7 +386,7 @@ static uint32_t get_baudrate (uint32_t rate) return idx; } while(idx); - return MODBUS_BAUDRATE; + return DEFAULT_MODBUS_STREAM_BAUD; } static const setting_group_detail_t modbus_groups [] = { @@ -398,8 +395,9 @@ static const setting_group_detail_t modbus_groups [] = { static status_code_t modbus_set_baud (setting_id_t id, uint_fast16_t value) { - modbus.baud_rate = baud[(uint32_t)value]; - silence_timeout = silence.timeout[(uint32_t)value]; + settings.modbus_baud = (uint8_t)value; + modbus.baud_rate = settings.modbus_baud = baud[settings.modbus_baud]; + silence_timeout = silence.timeout[settings.modbus_baud]; stream.set_baud_rate(modbus.baud_rate); return Status_OK; @@ -410,9 +408,30 @@ static uint32_t modbus_get_baud (setting_id_t setting) return get_baudrate(modbus.baud_rate); } +static status_code_t modbus_set_format (setting_id_t id, uint_fast16_t value) +{ + if(stream.set_format) { + settings.modbus_stream_format.parity = (serial_parity_t)value; + stream.set_format(settings.modbus_stream_format); + } + + return stream.set_format ? Status_OK : Status_SettingDisabled; +} + +static uint32_t modbus_get_format (setting_id_t setting) +{ + return (uint32_t)settings.modbus_stream_format.parity; +} + +static bool can_set_format (const setting_detail_t *setting, uint_fast16_t offset) +{ + return stream.set_format != NULL; +} + static const setting_detail_t modbus_settings[] = { { Settings_ModBus_BaudRate, Group_ModBus, "ModBus baud rate", NULL, Format_RadioButtons, "2400,4800,9600,19200,38400,115200", NULL, NULL, Setting_NonCoreFn, modbus_set_baud, modbus_get_baud, NULL }, - { Settings_ModBus_RXTimeout, Group_ModBus, "ModBus RX timeout", "milliseconds", Format_Integer, "####0", "50", "250", Setting_NonCore, &modbus.rx_timeout, NULL, NULL } + { Settings_ModBus_RXTimeout, Group_ModBus, "ModBus RX timeout", "milliseconds", Format_Integer, "####0", "50", "250", Setting_NonCore, &modbus.rx_timeout, NULL, NULL }, + { Setting_ModBus_StreamFormat, Group_ModBus, "ModBus serial format", NULL, Format_RadioButtons, "8-bit no parity, 8-bit even parity, 8-bit odd parity", NULL, NULL, Setting_NonCoreFn, modbus_set_format, modbus_get_format, can_set_format } }; static void modbus_settings_save (void) @@ -423,7 +442,7 @@ static void modbus_settings_save (void) static void modbus_settings_restore (void) { modbus.rx_timeout = 50; - modbus.baud_rate = baud[MODBUS_BAUDRATE]; + modbus.baud_rate = baud[DEFAULT_MODBUS_STREAM_BAUD]; hal.nvs.memcpy_to_nvs(nvs_address, (uint8_t *)&modbus, sizeof(modbus_settings_t), true); } @@ -438,6 +457,9 @@ static void modbus_settings_load (void) silence_timeout = silence.timeout[get_baudrate(modbus.baud_rate)]; stream.set_baud_rate(modbus.baud_rate); + + if(stream.set_format) + stream.set_format(settings.modbus_stream_format); } static void onReportOptions (bool newopt) @@ -445,7 +467,7 @@ static void onReportOptions (bool newopt) on_report_options(newopt); if(!newopt) - report_plugin("MODBUS", "0.19"); + report_plugin("MODBUS", "0.20"); } static bool modbus_rtu_isup (void) @@ -500,11 +522,12 @@ static bool claim_stream (io_stream_properties_t const *sstream) if(sstream->type == StreamType_Serial && (stream_instance >= 0 ? sstream->instance == (uint8_t)stream_instance : sstream->flags.modbus_ready && !sstream->flags.claimed)) { - if((claimed = sstream->claim(baud[MODBUS_BAUDRATE])) && stream_is_valid(claimed)) { + if((claimed = sstream->claim(baud[DEFAULT_MODBUS_STREAM_BAUD])) && stream_is_valid(claimed)) { claimed->set_enqueue_rt_handler(stream_buffer_all); stream.set_baud_rate = claimed->set_baud_rate; + stream.set_format = claimed->set_format; //!< Optional handler for setting the stream format. stream.get_tx_buffer_count = claimed->get_tx_buffer_count; stream.get_rx_buffer_count = claimed->get_rx_buffer_count; stream.write = claimed->write_n; diff --git a/settings.c b/settings.c index d387d8b..0e10fcc 100644 --- a/settings.c +++ b/settings.c @@ -354,6 +354,9 @@ PROGMEM const settings_t defaults = { .safety_door.spindle_on_delay = DEFAULT_SAFETY_DOOR_SPINDLE_DELAY, .safety_door.coolant_on_delay = DEFAULT_SAFETY_DOOR_COOLANT_DELAY, + .modbus_baud = DEFAULT_MODBUS_STREAM_BAUD, + .modbus_stream_format = (DEFAULT_MODBUS_STREAM_PARITY << 4), + .rgb_strip.length0 = DEFAULT_RGB_STRIP0_LENGTH, .rgb_strip.length1 = DEFAULT_RGB_STRIP1_LENGTH }; diff --git a/settings.h b/settings.h index ef4f8ca..32a1202 100644 --- a/settings.h +++ b/settings.h @@ -26,6 +26,7 @@ #include "config.h" #include "system.h" +#include "stream.h" #include "plugins.h" // Version of the persistent storage data. Always stored in byte 0 of non-volatile storage. @@ -459,6 +460,7 @@ typedef enum { Setting_RelayPortToolsetter = 678, Setting_RelayPortProbe2 = 679, Setting_StepperEnableDelay = 680, + Setting_ModBus_StreamFormat = 681, Setting_SpindlePWMOptions1 = 709, @@ -901,7 +903,8 @@ typedef struct { stepper_spindle_settings_flags_t stepper_spindle_flags; uint16_t stepper_enable_delay; // Move to stepper_settings_t tool_id_t tool_id; - char reserved[10]; // Reserved For future expansion + serial_format_t modbus_stream_format; + char reserved[9]; // Reserved For future expansion } settings_t; typedef enum { diff --git a/stream.h b/stream.h index a87c033..8947a1b 100644 --- a/stream.h +++ b/stream.h @@ -91,6 +91,35 @@ typedef enum { StreamType_Null } stream_type_t; +typedef enum { + Serial_8bit = 0, + Serial_7bit +} serial_width_t; + +typedef enum { + Serial_StopBits2 = 0, + Serial_StopBits1_5, + Serial_StopBits1, + Serial_StopBits0_5, +} serial_stopbits_t; + +typedef enum { + Serial_ParityNone = 0, + Serial_ParityEven, + Serial_ParityOdd, + Serial_ParityMarkSPace, +} serial_parity_t; + +typedef union { + uint8_t value; + struct { + uint8_t width :2, + stopbits :2, + parity :2, + unused :2; + }; +} serial_format_t; + typedef union { uint8_t value; struct { @@ -162,6 +191,11 @@ set it to protocol_enqueue_realtime_command() on initialization. */ typedef enqueue_realtime_command_ptr (*set_enqueue_rt_handler_ptr)(enqueue_realtime_command_ptr handler); +/*! \brief Pointer to function for setting the stream format. +\param format a \a serial_format_t struct. +\returns true if successful. +*/ +typedef bool (*set_format_ptr)(serial_format_t format); /*! \brief Pointer to function for setting the stream baud rate. \param baud_rate @@ -262,6 +296,7 @@ typedef struct { 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. + set_format_ptr set_format; //!< Optional handler for setting the stream format. 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;