diff --git a/README.md b/README.md index ddc0e1b..ca15116 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ## grblHAL ## -Latest build date is 20260331, see the [changelog](changelog.md) for details. +Latest build date is 202603416, 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 3429a47..b510cc0 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,27 @@ ## grblHAL changelog +Build 20260416 + +Core: + +* Formalized SPI API, added init call for 74HC595 I/O expander. + +* Fix for G30 not cleared on $RST, added code for syncing parser state on offsets clear. Ref. issue [#940](https://github.com/grblHAL/core/issues/940). + +Drivers: + +* ESP32, RP2040, STM32F4xx and STM32F7xx: updated SPI implementation to match new formalized API. + +Plugins: + +* Misc: added support for 74HC595 shift register(s) I/O expansion via SPI, up to 4 chips can be chained. +> [!NOTE] +> Do not use for step/dir signals due to latency. The ESP32 is the slowest, it takes a long time to switch devices when the SPI bus is shared. + +* SD card: fix to allow listing files in littlefs if no SD card mounted. + +--- + Build 20260331 Core: diff --git a/crossbar.h b/crossbar.h index 0b6d275..e46eb42 100644 --- a/crossbar.h +++ b/crossbar.h @@ -319,6 +319,10 @@ typedef enum { Output_MOSI, Output_SPICLK, Output_SPICS, + Output_SPICS0 = Output_SPICS, + Output_SPICS1, + Output_SPICS2, + Output_SPICS3, Output_FlashCS, Output_SdCardCS, Input_SdCardDetect, @@ -613,7 +617,10 @@ PROGMEM static const pin_name_t pin_names[] = { { .function = Input_MISO, .name = "MISO" }, { .function = Output_MOSI, .name = "MOSI" }, { .function = Output_SPICLK, .name = "SPI CLK" }, - { .function = Output_SPICS, .name = "SPI CS" }, + { .function = Output_SPICS0, .name = "SPI CS0" }, + { .function = Output_SPICS1, .name = "SPI CS1" }, + { .function = Output_SPICS2, .name = "SPI CS2" }, + { .function = Output_SPICS3, .name = "SPI CS3" }, { .function = Output_FlashCS, .name = "Flash CS" }, { .function = Output_SdCardCS, .name = "SD card CS" }, { .function = Input_SdCardDetect, .name = "SD card detect" }, @@ -659,6 +666,7 @@ typedef enum { PinGroup_MotorUART, PinGroup_I2C, PinGroup_SPI, + PinGroup_SPICS, PinGroup_UART1, PinGroup_UART = PinGroup_UART1, PinGroup_UART2, diff --git a/expanders_init.h b/expanders_init.h index 0d47d85..bfa5176 100644 --- a/expanders_init.h +++ b/expanders_init.h @@ -9,7 +9,7 @@ Part of grblHAL - Copyright (c) 2025 Terje Io + Copyright (c) 2025-2026 Terje Io grblHAL is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -50,19 +50,35 @@ extern void mcp4725_init (void); #endif #if PCA9654E_ENABLE -extern void pca9654e_init(void); +extern void pca9654e_init (void); #endif // Third party I2C expander plugins goes after this line #if FLEXGPIO_ENABLE -extern void flexgpio_init(void); +extern void flexgpio_init (void); #endif #endif // I2C expanders // SPI expanders +#if HC595_ENABLE + +#if defined(SPI_ENABLE) && !SPI_ENABLE +#undef SPI_ENABLE +#endif + +#ifndef SPI_ENABLE +#define SPI_ENABLE 1 +#endif + +#endif + +#if HC595_ENABLE +extern void hc595_init (void); +#endif + // // ModBus expanders @@ -105,6 +121,10 @@ static inline void io_expanders_init (void) { board_ports_init(); // can be implemented by board specific code +#if HC595_ENABLE + hc595_init(); +#endif + #if MCP3221_ENABLE mcp3221_init(); #endif diff --git a/gcode.c b/gcode.c index 08ef861..075887d 100644 --- a/gcode.c +++ b/gcode.c @@ -273,6 +273,29 @@ axes_signals_t gc_get_g51_state (void) return scaled; } +void gc_clear_offset (coord_system_id_t id) +{ + bool clear; + coord_system_data_t coord_data = {0}; + + if((id == CoordinateSystem_G92)) { + clear = !settings.flags.g92_is_volatile; + gc_state.g92_offset_applied = false; + memcpy(&gc_state.g92_offset, &coord_data, sizeof(coord_system_data_t)); +#if COMPATIBILITY_LEVEL <= 1 + } else if((clear = (id < CoordinateSystem_G59_1 || id > CoordinateSystem_G59_3 || bit_isfalse(settings.offset_lock.mask, bit(id - CoordinateSystem_G59_1))))) { +#else + } else { + clear = true; +#endif + if(id == gc_state.modal.g5x_offset.id) + memcpy(&gc_state.modal.g5x_offset.data, &coord_data, sizeof(coord_system_data_t)); + } + + if(clear) + settings_write_coord_data(id, &coord_data); +} + float gc_get_offset (uint_fast8_t idx, bool real_time) { offset_id_t offset_id; diff --git a/gcode.h b/gcode.h index 816c4f9..824fd4c 100644 --- a/gcode.h +++ b/gcode.h @@ -751,6 +751,8 @@ float *gc_get_scaling (void); // Get current axis offset. float gc_get_offset (uint_fast8_t idx, bool real_time); +void gc_clear_offset (coord_system_id_t id); + char *gc_coord_system_to_str (coord_system_id_t id); void gc_clear_output_commands (output_command_t *cmd); diff --git a/grbl.h b/grbl.h index 8fd8957..1c3da6c 100644 --- a/grbl.h +++ b/grbl.h @@ -42,7 +42,7 @@ #else #define GRBL_VERSION "1.1f" #endif -#define GRBL_BUILD 20260331 +#define GRBL_BUILD 20260416 #define GRBL_URL "https://github.com/grblHAL" diff --git a/modbus_rtu.c b/modbus_rtu.c index 1d67e6c..68f29cf 100644 --- a/modbus_rtu.c +++ b/modbus_rtu.c @@ -327,9 +327,10 @@ static bool modbus_send_rtu (modbus_message_t *msg, const modbus_callbacks_t *ca packet = NULL; is_blocking = false; + sync_msg.msg.adu[1] = 0; state = silence_until > 0 ? ModBus_Silent : ModBus_Idle; - } else if(packet != &sync_msg) { + } else if(packet == NULL || sync_msg.msg.adu[1] == 0 || packet->msg.adu[0] != sync_msg.msg.adu[0]) { if(head->next != tail) { add_message((queue_entry_t *)head, msg, true, callbacks); head = head->next; diff --git a/pin_bits_masks.h b/pin_bits_masks.h index 9d42a20..098b6a1 100644 --- a/pin_bits_masks.h +++ b/pin_bits_masks.h @@ -118,7 +118,7 @@ #else #define add_aux_input(fn, aux, irq, signal_bit) { .function = fn, .irq_mode = irq, .signal.value = signal_bit, .port = IOPORT_UNASSIGNED, .gpio.port = (void *)aux##_PORT, .gpio.pin = aux##_PIN }, #endif -#if defined(__IMXRT1062__) || defined(ESP_PLATFORM) +#if defined(__IMXRT1062__) // || defined(ESP_PLATFORM) #define add_aux_output(fn, aux) { .function = fn, .port = IOPORT_UNASSIGNED, .gpio.pin = aux##_PIN }, #else #define add_aux_output(fn, aux) { .function = fn, .port = IOPORT_UNASSIGNED, .gpio.port = (void *)aux##_PORT, .gpio.pin = aux##_PIN }, @@ -433,6 +433,53 @@ static inline control_signals_t aux_ctrl_scan_status (control_signals_t signals) return signals; } +#if defined(__IMXRT1062__) || defined(ESP_PLATFORM) +/* +#ifndef STEPPERS_ENABLE_PORT +#define STEPPERS_ENABLE_PORT 0 +#endif +*/ +#if defined(SPINDLE_ENABLE_PIN) && !defined(SPINDLE_ENABLE_PORT) +#define SPINDLE_ENABLE_PORT 0 +#endif +#if defined(SPINDLE_DIRECTION_PIN) && !defined(SPINDLE_DIRECTION_PORT) +#define SPINDLE_DIRECTION_PORT 0 +#endif +#if defined(SPINDLE_PWM_PIN) && !defined(SPINDLE_PWM_PORT) +#define SPINDLE_PWM_PORT 0 +#endif + +#if defined(SPINDLE1_ENABLE_PIN) && !defined(SPINDLE1_ENABLE_PORT) +#define SPINDLE1_ENABLE_PORT 0 +#endif +#if defined(SPINDLE1_DIRECTION_PIN) && !defined(SPINDLE1_DIRECTION_PORT) +#define SPINDLE1_DIRECTION_PORT 0 +#endif +#if defined(SPINDLE1_PWM_PIN) && !defined(SPINDLE1_PWM_PORT) +#define SPINDLE1_PWM_PORT 0 +#endif + +#if defined(COOLANT_FLOOD_PIN) && !defined(COOLANT_FLOOD_PORT) +#define COOLANT_FLOOD_PORT 0 +#endif +#if defined(COOLANT_MIST_PIN) && !defined(COOLANT_MIST_PORT) +#define COOLANT_MIST_PORT 0 +#endif + +#if defined(COPROC_RESET_PIN) && !defined(COPROC_RESET_PORT) +#define COPROC_RESET_PORT 0 +#endif +#if defined(COPROC_BOOT0_PIN) && !defined(COPROC_BOOT0_PORT) +#define COPROC_BOOT0_PORT 0 +#endif + +#if defined(SPI_RST_PIN) && !defined(SPI_RST_PORT) +#define SPI_RST_PORT 0 +#endif + +#endif + + // The following pins are bound explicitly to aux output pins static aux_ctrl_out_t aux_ctrl_out[] = { #if defined(ESP_PLATFORM) || defined(RP2040) // for now @@ -508,9 +555,6 @@ static aux_ctrl_out_t aux_ctrl_out[] = { add_aux_output(Output_CoProc_Boot0, COPROC_BOOT0) #endif #if defined(SPI_RST_PIN) && defined(RP2040) - #ifndef SPI_RST_PORT - #define SPI_RST_PORT 0 - #endif add_aux_output(Output_SPIRST, SPI_RST) #endif }; diff --git a/plugins.h b/plugins.h index db468e0..f822f56 100644 --- a/plugins.h +++ b/plugins.h @@ -226,13 +226,12 @@ extern bool i2c_transfer (i2c_transfer_t *i2c, bool read); // SPI interface: -/* -typedef void (*spi_cs_ptr)(const char c); - typedef struct { - spi_cs_ptr cs; - uint32_t f_clk; -} spi_cfg_t; + uint8_t cs_pin; + void *cs_port; + uint32_t f_clock; + void *handle; +} spi_slave_t; typedef union { uint8_t ok; @@ -244,14 +243,13 @@ typedef union { }; } spi_cap_t; -extern spi_cap_t spi_start (spi_cfg_t *cfg); -extern uint32_t spi_set_speed (uint32_t prescaler); +extern spi_cap_t spi_start (spi_slave_t *slave); +extern bool spi_select (spi_slave_t *slave); +extern bool spi_deselect (spi_slave_t *slave); extern uint8_t spi_get_byte (void); extern uint8_t spi_put_byte (uint8_t byte); -extern void spi_write (uint8_t *data, size_t size); -extern void spi_read (uint8_t *data, size_t size); -extern void spi_write (uint8_t *data, size_t size); -*/ +extern bool spi_read (uint8_t *data, uint16_t size); +extern bool spi_write (uint8_t *data, uint16_t size); // EEPROM/FRAM: diff --git a/settings.c b/settings.c index d379008..a00af07 100644 --- a/settings.c +++ b/settings.c @@ -2337,7 +2337,7 @@ PROGMEM static const setting_descr_t setting_descr[] = { { Setting_RestoreOverrides, "Restore overrides to default values at program end." }, #ifndef NO_SAFETY_DOOR_SUPPORT { Setting_DoorOptions, "Ignore when idle: disregard door signal in IDLE state to allow jogging etc. Available when controller has door input.\n" - "Keep coolant state on open: do not turn off coolant if on." }, + "Keep coolant state on open: do not turn off coolant if on." }, #endif { Setting_SleepEnable, "Enable sleep mode." }, { Setting_HoldActions, "Actions taken during feed hold and on resume from feed hold." }, @@ -2616,14 +2616,14 @@ FLASHMEM static tool_table_entry_t *settings_get_tool_data (tool_id_t tool_id) { static tool_table_entry_t tool = {0}; - if(tool_id <= MAX_TOOL_NUMBER) { - tool_data.tool_id = tool_id; + if(tool_id <= MAX_TOOL_NUMBER) { + tool_data.tool_id = tool_id; tool.pocket = (pocket_id_t)tool_id; - tool.data = &tool_data; - } else { + tool.data = &tool_data; + } else { tool.data = NULL; tool.pocket = (pocket_id_t)-1; - } + } return &tool; } @@ -2772,15 +2772,8 @@ FLASHMEM void settings_restore (settings_restore_t restore) } if(restore.parameters) { - coord_system_data_t coord_data = {0}; - for(idx = 0; idx <= N_WorkCoordinateSystems; idx++) { -#if COMPATIBILITY_LEVEL <= 1 - if(idx < CoordinateSystem_G59_1 || idx > CoordinateSystem_G59_3 || bit_isfalse(settings.offset_lock.mask, bit(idx - CoordinateSystem_G59_1))) -#endif - settings_write_coord_data((coord_system_id_t)idx, &coord_data); - } - settings_write_coord_data(CoordinateSystem_G92, &coord_data); // Clear G92 offsets - + for(idx = 0; idx < N_CoordinateSystems; idx++) + gc_clear_offset((coord_system_id_t)idx); #if N_TOOLS settings_clear_tool_data(); #endif diff --git a/stream.c b/stream.c index 0c00067..31c6f59 100644 --- a/stream.c +++ b/stream.c @@ -889,7 +889,7 @@ void debug_printf (const char *fmt, ...) debug_writeln(debug_out); } -static bool debug_claim_stream (io_stream_properties_t const *stream) +static bool debug_claim_stream (io_stream_properties_t const *stream, void *data) { io_stream_t const *claimed = NULL;