Updated to allow Bluetooth serial streams to be used for MPG/pendants.

Parking mode improvements.
Removed requirement for external encoder for spindle sync if stepper spindle is enabled.
Improved handling of $680 stepper enable delay.
This commit is contained in:
terjeio
2025-12-01 17:55:53 +07:00
parent e272f773b5
commit 13145a4a46
21 changed files with 487 additions and 182 deletions

View File

@@ -39,6 +39,7 @@ target_sources(grbl INTERFACE
${CMAKE_CURRENT_LIST_DIR}/ngc_flowctrl.c ${CMAKE_CURRENT_LIST_DIR}/ngc_flowctrl.c
${CMAKE_CURRENT_LIST_DIR}/regex.c ${CMAKE_CURRENT_LIST_DIR}/regex.c
${CMAKE_CURRENT_LIST_DIR}/ioports.c ${CMAKE_CURRENT_LIST_DIR}/ioports.c
${CMAKE_CURRENT_LIST_DIR}/utf8.c
${CMAKE_CURRENT_LIST_DIR}/vfs.c ${CMAKE_CURRENT_LIST_DIR}/vfs.c
${CMAKE_CURRENT_LIST_DIR}/canbus.c ${CMAKE_CURRENT_LIST_DIR}/canbus.c
${CMAKE_CURRENT_LIST_DIR}/pid.c ${CMAKE_CURRENT_LIST_DIR}/pid.c

View File

@@ -1,6 +1,6 @@
## grblHAL ## ## grblHAL ##
Latest build date is 20251109, see the [changelog](changelog.md) for details. Latest build date is 20251130, see the [changelog](changelog.md) for details.
> [!NOTE] > [!NOTE]
> A settings reset will be performed on an update of builds prior to 20241208. Backup and restore of settings is recommended. > A settings reset will be performed on an update of builds prior to 20241208. Backup and restore of settings is recommended.

View File

@@ -7,18 +7,18 @@
Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC
Copyright (c) 2009-2011 Simen Svale Skogsrud Copyright (c) 2009-2011 Simen Svale Skogsrud
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 it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (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 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. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with Grbl. If not, see <http://www.gnu.org/licenses/>. along with grblHAL. If not, see <http://www.gnu.org/licenses/>.
*/ */
#include <stdint.h> #include <stdint.h>

View File

@@ -3,22 +3,22 @@
Part of grblHAL Part of grblHAL
Copyright (c) 2017-2023 Terje Io Copyright (c) 2017-2025 Terje Io
Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC Copyright (c) 2011-2016 Sungeun K. Jeon for Gnea Research LLC
Copyright (c) 2009-2011 Simen Svale Skogsrud Copyright (c) 2009-2011 Simen Svale Skogsrud
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 it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or the Free Software Foundation, either version 3 of the License, or
(at your option) any later version. (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 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. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with Grbl. If not, see <http://www.gnu.org/licenses/>. along with grblHAL. If not, see <http://www.gnu.org/licenses/>.
*/ */
#ifndef _ALARMS_H_ #ifndef _ALARMS_H_
@@ -67,5 +67,13 @@ alarm_details_t *alarms_get_details (void);
const char *alarms_get_description (alarm_code_t id); const char *alarms_get_description (alarm_code_t id);
void alarms_register (alarm_details_t *details); void alarms_register (alarm_details_t *details);
#endif static inline bool alarm_is_critical (alarm_code_t alarm)
{
return alarm == Alarm_HardLimit ||
alarm == Alarm_SoftLimit ||
alarm == Alarm_EStop ||
alarm == Alarm_MotorFault ||
alarm == Alarm_ExpanderException;
}
#endif

View File

@@ -1,5 +1,36 @@
## grblHAL changelog ## grblHAL changelog
<a name="20251130">Build 20251130
Core:
* Updated to allow Bluetooth serial streams to be used for MPG/pendants.
* Parking mode improvements.
* Removed requirement for external encoder for spindle sync if stepper spindle is enabled.
* Improved handling of `$680` stepper enable delay.
Drivers:
* ESP32, RP2040: Updated native Bluetooth implementations to allow Bluetooth serial streams to be used for MPG/pendants.
* RP2040: updated LED strip code to use non-blocking DMA.
Extended spindle PWM frequency range down to ~10Hz. Ref. discussion [#155](https://github.com/grblHAL/RP2040/discussions/155).
* STM32F3xx: fixed compiler errors and warnings for generic board, ref. issue [#5](https://github.com/grblHAL/STM32F3xx/issues/5).
* STM32F4xx: refactored LED strip drivers, now supports up to two strips via DMA based PWM.
Plugins:
* Bluetooth: updated to allow use for MPG/pendants.
* Misc, FNC Expander: added compile time option for PWM outputs, some general improvements.
---
<a name="20251111">Build 20251111 <a name="20251111">Build 20251111
Core: Core:

View File

@@ -198,14 +198,6 @@
#define SPINDLE_SYNC_ENABLE 0 #define SPINDLE_SYNC_ENABLE 0
#endif #endif
#ifndef SPINDLE_ENCODER_ENABLE
#if SPINDLE_SYNC_ENABLE
#define SPINDLE_ENCODER_ENABLE 1
#else
#define SPINDLE_ENCODER_ENABLE 0
#endif
#endif
#ifndef TRINAMIC_ENABLE #ifndef TRINAMIC_ENABLE
#define TRINAMIC_ENABLE 0 #define TRINAMIC_ENABLE 0
#endif #endif
@@ -450,6 +442,14 @@
#endif #endif
#endif #endif
#ifndef SPINDLE_ENCODER_ENABLE
#if SPINDLE_SYNC_ENABLE && !(SPINDLE_ENABLE & (1 << SPINDLE_STEPPER))
#define SPINDLE_ENCODER_ENABLE 1
#else
#define SPINDLE_ENCODER_ENABLE 0
#endif
#endif
#ifndef QEI_ENABLE #ifndef QEI_ENABLE
#define QEI_ENABLE 0 #define QEI_ENABLE 0
#endif #endif

View File

@@ -246,6 +246,26 @@
#define TRINAMIC_MOTOR_ENABLE 0 #define TRINAMIC_MOTOR_ENABLE 0
#endif #endif
#if MPG_ENABLE && !defined(MPG_STREAM)
#if USB_SERIAL_CDC
#define MPG_STREAM 0
#else
#define MPG_STREAM 1
#endif
#if (MODBUS_ENABLE & MODBUS_RTU_ENABLED) && defined(MODBUS_RTU_STREAM) && MODBUS_RTU_STREAM == MPG_STREAM
#undef MPG_STREAM
#define MPG_STREAM (MODBUS_RTU_STREAM + 1)
#endif
#endif
#if MPG_ENABLE && MPG_ENABLE != 2 && MPG_STREAM == 20 && BLUETOOTH_ENABLE != 1
#error "MPG can only be used with native Bluetooth and character mode switching!"
#endif
#if BLUETOOTH_ENABLE == 2 && !defined(BLUETOOTH_STREAM)
#define BLUETOOTH_STREAM 255 // Select first free UART stream
#endif
#if USB_SERIAL_CDC && defined(SERIAL_PORT) #if USB_SERIAL_CDC && defined(SERIAL_PORT)
#define SP0 1 #define SP0 1
#else #else
@@ -276,35 +296,37 @@
#define TRINAMIC_TEST 0 #define TRINAMIC_TEST 0
#endif #endif
#if KEYPAD_ENABLE == 2 && MPG_ENABLE == 0 #if MPG_ENABLE && MPG_STREAM != 20
#define MPG_TEST 1
#else
#define MPG_TEST 0
#endif
#if KEYPAD_ENABLE == 2 && !MPG_TEST
#define KEYPAD_TEST 1 #define KEYPAD_TEST 1
#else #else
#define KEYPAD_TEST 0 #define KEYPAD_TEST 0
#endif #endif
#if (MODBUS_TEST + KEYPAD_TEST + (MPG_ENABLE ? 1 : 0) + TRINAMIC_TEST + (BLUETOOTH_ENABLE == 2 ? 1 : 0)) > (SP0 + SP1 + SP2) #if BLUETOOTH_ENABLE == 2 && (!MPG_ENABLE || MPG_STREAM != BLUETOOTH_STREAM)
#error "Too many options that uses a serial port are enabled!" #define BT_TEST 1
#else
#define BT_TEST 0
#endif
#if (MODBUS_TEST + KEYPAD_TEST + MPG_TEST + TRINAMIC_TEST + BT_TEST) > (SP0 + SP1 + SP2)
#error "Too many options that requires a serial port are enabled!"
#endif #endif
#undef SP0 #undef SP0
#undef SP1 #undef SP1
#undef SP2 #undef SP2
#undef BT_TEST
#undef MODBUS_TEST #undef MODBUS_TEST
#undef MPG_TEST
#undef KEYPAD_TEST #undef KEYPAD_TEST
#undef TRINAMIC_TEST #undef TRINAMIC_TEST
#if MPG_ENABLE && !defined(MPG_STREAM)
#if USB_SERIAL_CDC
#define MPG_STREAM 0
#else
#define MPG_STREAM 1
#endif
#if (MODBUS_ENABLE & MODBUS_RTU_ENABLED) && defined(MODBUS_RTU_STREAM) && MODBUS_RTU_STREAM == MPG_STREAM
#undef MPG_STREAM
#define MPG_STREAM (MODBUS_RTU_STREAM + 1)
#endif
#endif
#if KEYPAD_ENABLE == 2 && !defined(KEYPAD_STREAM) #if KEYPAD_ENABLE == 2 && !defined(KEYPAD_STREAM)
#if MPG_ENABLE #if MPG_ENABLE
#define KEYPAD_STREAM MPG_STREAM #define KEYPAD_STREAM MPG_STREAM

80
grbl.h
View File

@@ -42,7 +42,7 @@
#else #else
#define GRBL_VERSION "1.1f" #define GRBL_VERSION "1.1f"
#endif #endif
#define GRBL_BUILD 20251111 #define GRBL_BUILD 20251130
#define GRBL_URL "https://github.com/grblHAL" #define GRBL_URL "https://github.com/grblHAL"
@@ -113,48 +113,48 @@
// at character value 128 (0x80) and up to 255 (0xFF). If the normal set of realtime commands, // at character value 128 (0x80) and up to 255 (0xFF). If the normal set of realtime commands,
// such as status reports, feed hold, reset, and cycle start, are moved to the extended set // such as status reports, feed hold, reset, and cycle start, are moved to the extended set
// space, protocol.c's protocol_process_realtime() will need to be modified to accommodate the change. // space, protocol.c's protocol_process_realtime() will need to be modified to accommodate the change.
#define CMD_STATUS_REPORT 0x80 // TODO: use 0x05 ctrl-E ENQ instead? #define CMD_STATUS_REPORT 0x80 // (128) TODO: use 0x05 ctrl-E ENQ instead?
#define CMD_CYCLE_START 0x81 // TODO: use 0x06 ctrl-F ACK instead? or SYN/DC2/DC3? #define CMD_CYCLE_START 0x81 // (129) TODO: use 0x06 ctrl-F ACK instead? or SYN/DC2/DC3?
#define CMD_FEED_HOLD 0x82 // TODO: use 0x15 ctrl-U NAK instead? #define CMD_FEED_HOLD 0x82 // (130) TODO: use 0x15 ctrl-U NAK instead?
#define CMD_GCODE_REPORT 0x83 #define CMD_GCODE_REPORT 0x83 // (131)
#define CMD_SAFETY_DOOR 0x84 #define CMD_SAFETY_DOOR 0x84 // (132)
#define CMD_JOG_CANCEL 0x85 #define CMD_JOG_CANCEL 0x85 // (133)
//#define CMD_DEBUG_REPORT 0x86 // Only when DEBUG enabled, sends debug report in '{}' braces. //#define CMD_DEBUG_REPORT 0x86 // Only when DEBUG enabled, sends debug report in '{}' braces.
#define CMD_STATUS_REPORT_ALL 0x87 #define CMD_STATUS_REPORT_ALL 0x87 // (135)
#define CMD_OPTIONAL_STOP_TOGGLE 0x88 #define CMD_OPTIONAL_STOP_TOGGLE 0x88 // (136)
#define CMD_SINGLE_BLOCK_TOGGLE 0x89 #define CMD_SINGLE_BLOCK_TOGGLE 0x89 // (137)
#define CMD_OVERRIDE_FAN0_TOGGLE 0x8A //!< Toggle Fan 0 on/off, not implemented by the core. #define CMD_OVERRIDE_FAN0_TOGGLE 0x8A //!< (138) Toggle Fan 0 on/off, not implemented by the core.
#define CMD_MPG_MODE_TOGGLE 0x8B //!< Toggle MPG mode on/off, available when the MPG stream is enabled with MPG mode 2. #define CMD_MPG_MODE_TOGGLE 0x8B //!< (139) Toggle MPG mode on/off, available when the MPG stream is enabled with MPG mode 2.
#define CMD_AUTO_REPORTING_TOGGLE 0x8C //!< Toggle auto real time reporting if configured. #define CMD_AUTO_REPORTING_TOGGLE 0x8C //!< (140) Toggle auto real time reporting if configured.
#define CMD_OVERRIDE_FEED_RESET 0x90 //!< Restores feed override value to 100%. #define CMD_OVERRIDE_FEED_RESET 0x90 //!< (144) Restores feed override value to 100%.
#define CMD_OVERRIDE_FEED_COARSE_PLUS 0x91 #define CMD_OVERRIDE_FEED_COARSE_PLUS 0x91 // (145)
#define CMD_OVERRIDE_FEED_COARSE_MINUS 0x92 #define CMD_OVERRIDE_FEED_COARSE_MINUS 0x92 // (146)
#define CMD_OVERRIDE_FEED_FINE_PLUS 0x93 #define CMD_OVERRIDE_FEED_FINE_PLUS 0x93 // (147)
#define CMD_OVERRIDE_FEED_FINE_MINUS 0x94 #define CMD_OVERRIDE_FEED_FINE_MINUS 0x94 // (148)
#define CMD_OVERRIDE_RAPID_RESET 0x95 //!< Restores rapid override value to 100%. #define CMD_OVERRIDE_RAPID_RESET 0x95 //!< (149) Restores rapid override value to 100%.
#define CMD_OVERRIDE_RAPID_MEDIUM 0x96 #define CMD_OVERRIDE_RAPID_MEDIUM 0x96 // (150)
#define CMD_OVERRIDE_RAPID_LOW 0x97 #define CMD_OVERRIDE_RAPID_LOW 0x97 // (151)
// #define CMD_OVERRIDE_RAPID_EXTRA_LOW 0x98 // *NOT SUPPORTED* // #define CMD_OVERRIDE_RAPID_EXTRA_LOW 0x98 // *NOT SUPPORTED*
#define CMD_OVERRIDE_SPINDLE_RESET 0x99 // Restores spindle override value to 100%. #define CMD_OVERRIDE_SPINDLE_RESET 0x99 // (153) Restores spindle override value to 100%.
#define CMD_OVERRIDE_SPINDLE_COARSE_PLUS 0x9A #define CMD_OVERRIDE_SPINDLE_COARSE_PLUS 0x9A // (154)
#define CMD_OVERRIDE_SPINDLE_COARSE_MINUS 0x9B #define CMD_OVERRIDE_SPINDLE_COARSE_MINUS 0x9B // (155)
#define CMD_OVERRIDE_SPINDLE_FINE_PLUS 0x9C #define CMD_OVERRIDE_SPINDLE_FINE_PLUS 0x9C // (156)
#define CMD_OVERRIDE_SPINDLE_FINE_MINUS 0x9D #define CMD_OVERRIDE_SPINDLE_FINE_MINUS 0x9D // (157)
#define CMD_OVERRIDE_SPINDLE_STOP 0x9E #define CMD_OVERRIDE_SPINDLE_STOP 0x9E // (158)
#define CMD_OVERRIDE_COOLANT_FLOOD_TOGGLE 0xA0 #define CMD_OVERRIDE_COOLANT_FLOOD_TOGGLE 0xA0 // (160)
#define CMD_OVERRIDE_COOLANT_MIST_TOGGLE 0xA1 #define CMD_OVERRIDE_COOLANT_MIST_TOGGLE 0xA1 // (161)
#define CMD_PID_REPORT 0xA2 #define CMD_PID_REPORT 0xA2 // (162)
#define CMD_TOOL_ACK 0xA3 #define CMD_TOOL_ACK 0xA3 // (163)
#define CMD_PROBE_CONNECTED_TOGGLE 0xA4 #define CMD_PROBE_CONNECTED_TOGGLE 0xA4 // (164)
// The following character codes are reserved for plugin use // The following character codes are reserved for plugin use
#define CMD_MACRO_0 0xB0 #define CMD_MACRO_0 0xB0 // (176)
#define CMD_MACRO_1 0xB1 #define CMD_MACRO_1 0xB1 // (177)
#define CMD_MACRO_2 0xB2 #define CMD_MACRO_2 0xB2 // (178)
#define CMD_MACRO_3 0xB3 #define CMD_MACRO_3 0xB3 // (179)
#define CMD_MACRO_4 0xB4 #define CMD_MACRO_4 0xB4 // (180)
#define CMD_MACRO_5 0xB5 #define CMD_MACRO_5 0xB5 // (181)
#define CMD_MACRO_6 0xB6 #define CMD_MACRO_6 0xB6 // (182)
#define CMD_MACRO_7 0xB7 #define CMD_MACRO_7 0xB7 // (183)
// System motion line numbers must be zero. // System motion line numbers must be zero.
#define JOG_LINE_NUMBER 0 #define JOG_LINE_NUMBER 0

View File

@@ -95,6 +95,7 @@ static driver_startup_t driver = { .ok = 0xFF };
static core_task_t *next_task = NULL, *immediate_task = NULL, *on_booted = NULL, *systick_task = NULL, *last_freed = NULL; static core_task_t *next_task = NULL, *immediate_task = NULL, *on_booted = NULL, *systick_task = NULL, *last_freed = NULL;
static on_linestate_changed_ptr on_linestate_changed; static on_linestate_changed_ptr on_linestate_changed;
static settings_changed_ptr hal_settings_changed; static settings_changed_ptr hal_settings_changed;
static stepper_enable_ptr stepper_enable;
#ifdef KINEMATICS_API #ifdef KINEMATICS_API
kinematics_t kinematics; kinematics_t kinematics;
@@ -211,6 +212,14 @@ static void onLinestateChanged (serial_linestate_t state)
on_linestate_changed(state); on_linestate_changed(state);
} }
static void stepperEnable (axes_signals_t enable, bool hold)
{
if(stepper_enable)
stepper_enable(enable, hold);
sys.steppers_enabled = /*!hold &&*/ enable.bits == AXES_BITMASK;
}
static void print_pos_msg (void *data) static void print_pos_msg (void *data)
{ {
hal.stream.write("grblHAL: power on self-test (POS) failed!" ASCII_EOL); hal.stream.write("grblHAL: power on self-test (POS) failed!" ASCII_EOL);
@@ -354,6 +363,9 @@ int grbl_enter (void)
// check and configure driver // check and configure driver
stepper_enable = hal.stepper.enable;
hal.stepper.enable = stepperEnable;
#if ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING #if ADAPTIVE_MULTI_AXIS_STEP_SMOOTHING
driver.amass = hal.driver_cap.amass_level >= MAX_AMASS_LEVEL; driver.amass = hal.driver_cap.amass_level >= MAX_AMASS_LEVEL;
hal.driver_cap.amass_level = MAX_AMASS_LEVEL; hal.driver_cap.amass_level = MAX_AMASS_LEVEL;

View File

@@ -519,7 +519,7 @@ static void modbus_set_direction (bool tx)
ioport_digital_out(dir_port, tx); ioport_digital_out(dir_port, tx);
} }
static bool claim_stream (io_stream_properties_t const *sstream) static bool claim_stream (io_stream_properties_t const *sstream, void *data)
{ {
io_stream_t const *claimed = NULL; io_stream_t const *claimed = NULL;
@@ -598,7 +598,7 @@ void modbus_rtu_init (int8_t instance, int8_t dir_aux)
stream_instance = instance; stream_instance = instance;
if((hal.driver_cap.modbus_rtu = stream_enumerate_streams(claim_stream) && (nvs_address = nvs_alloc(sizeof(rtu_settings_t))))) { if((hal.driver_cap.modbus_rtu = stream_enumerate_streams(claim_stream, NULL) && (nvs_address = nvs_alloc(sizeof(rtu_settings_t))))) {
if(stream.set_direction == NULL && dir_aux != -2) { if(stream.set_direction == NULL && dir_aux != -2) {

View File

@@ -462,10 +462,7 @@ bool protocol_exec_rt_system (void)
hal.driver_reset(); hal.driver_reset();
// Halt everything upon a critical event flag. Currently hard and soft limits flag this. // Halt everything upon a critical event flag. Currently hard and soft limits flag this.
if((sys.blocking_event = (alarm_code_t)rt_exec == Alarm_HardLimit || if((sys.blocking_event = alarm_is_critical((alarm_code_t)rt_exec))) {
(alarm_code_t)rt_exec == Alarm_SoftLimit ||
(alarm_code_t)rt_exec == Alarm_EStop ||
(alarm_code_t)rt_exec == Alarm_MotorFault)) {
static const control_signals_t blocking_signals = { .e_stop = On, .motor_fault = On }; static const control_signals_t blocking_signals = { .e_stop = On, .motor_fault = On };
@@ -894,9 +891,9 @@ ISR_CODE bool ISR_FUNC(protocol_enqueue_realtime_command)(uint8_t c)
break; break;
case CMD_SAFETY_DOOR: case CMD_SAFETY_DOOR:
if(state_get() != STATE_SAFETY_DOOR) { if((drop = state_get() != STATE_SAFETY_DOOR)) {
sys.flags.is_parking = settings.parking.flags.enabled;
system_set_exec_state_flag(EXEC_SAFETY_DOOR); system_set_exec_state_flag(EXEC_SAFETY_DOOR);
drop = true;
} }
break; break;

157
report.c
View File

@@ -2366,86 +2366,121 @@ status_code_t report_pins (sys_state_t state, char *args)
return Status_OK; return Status_OK;
} }
typedef struct {
uint32_t idx;
const io_stream_properties_t *port;
} port_data_t;
typedef struct {
uint8_t instance;
uint32_t n_pins;
pin_info_t data[2];
} port_pins_t;
static void get_uart_pins (xbar_t *pin, void *data) static void get_uart_pins (xbar_t *pin, void *data)
{ {
if(pin->group >= PinGroup_UART && pin->group <= PinGroup_UART4) if(pin->group == PinGroup_UART + ((port_pins_t *)data)->instance)
get_pin_info(pin, &((pin_data_t *)data)->pins[((pin_data_t *)data)->idx++]); get_pin_info(pin, &((port_pins_t *)data)->data[((port_pins_t *)data)->n_pins++]);
} }
static void count_uart_pins (xbar_t *pin, void *data) static bool report_port_info (const io_stream_properties_t *port, void *data)
{ {
if(pin->group >= PinGroup_UART && pin->group <= PinGroup_UART4) if(!stream_is_uart(port->type))
((pin_data_t *)data)->n_pins++; return false;
}
static void report_port_info (pin_info_t *pin) port_pins_t pins = {0};
{
const io_stream_status_t *status; const io_stream_status_t *status;
if(pin->function == Input_RX) { hal.stream.write("[PORT:");
strcpy(buf, pin->port); hal.stream.write(uitoa(port->instance));
strcat(buf, uitoa(pin->pin)); hal.stream.write("|");
strcat(buf, ","); if(port->type == StreamType_Bluetooth) {
strcat(buf, xbar_fn_to_pinname(Input_RX)); hal.stream.write("BT||");
strcat(buf, "|");
} else { } else {
uint32_t idx = 0;
uint8_t instance = (pin->sortkey >> 16) - PinGroup_UART; pins.instance = port->instance;
if(hal.enumerate_pins)
hal.stream.write("[PORT:"); hal.enumerate_pins(false, get_uart_pins, &pins);
hal.stream.write(uitoa(instance)); if(pins.n_pins) {
hal.stream.write("|"); hal.stream.write(pins.data[0].description);
hal.stream.write(pin->description); for(idx = 0; idx < pins.n_pins; idx++) {
hal.stream.write("|"); hal.stream.write("|");
hal.stream.write(*buf ? buf : "-|"); if(*pins.data[idx].port)
if(*pin->port) hal.stream.write(pins.data[idx].port);
hal.stream.write(pin->port); hal.stream.write(uitoa(pins.data[idx].pin));
hal.stream.write(uitoa(pin->pin)); hal.stream.write(",");
hal.stream.write(","); hal.stream.write(xbar_fn_to_pinname(pins.data[idx].function));
hal.stream.write(xbar_fn_to_pinname(pin->function)); }
if(hal.stream.write_char && (status = stream_get_uart_status(instance))) { for(; idx < 2; idx++)
hal.stream.write("|"); hal.stream.write("|");
hal.stream.write(uitoa(status->baud_rate)); } else
hal.stream.write(","); hal.stream.write("UART||");
hal.stream.write_char("87"[status->format.width]);
hal.stream.write(",");
hal.stream.write_char("NEOMS"[status->format.parity]);
hal.stream.write(",");
hal.stream.write(((const char * const[]){"1", "1.5", "2", "0.5"})[status->format.stopbits]);
if(status->flags.rts_handshake)
hal.stream.write(",P");
hal.stream.write("|");
hal.stream.write_char("FC"[status->flags.claimed]);
}
hal.stream.write("]" ASCII_EOL);
*buf = '\0';
} }
if(hal.stream.write_char && (status = stream_get_uart_status(port->instance))) {
hal.stream.write("|");
hal.stream.write(uitoa(status->baud_rate));
hal.stream.write(",");
hal.stream.write_char("87"[status->format.width]);
hal.stream.write(",");
hal.stream.write_char("NEOMS"[status->format.parity]);
hal.stream.write(",");
hal.stream.write(((const char * const[]){"1", "1.5", "2", "0.5"})[status->format.stopbits]);
if(status->flags.rts_handshake)
hal.stream.write(",P");
hal.stream.write("|");
hal.stream.write_char("FC"[status->flags.claimed]);
}
hal.stream.write("]" ASCII_EOL);
return false;
}
bool get_ports (io_stream_properties_t const *port, void *data)
{
if(stream_is_uart(port->type)) {
((port_data_t *)data)[((port_data_t *)data)->idx].port = port;
((port_data_t *)data)->idx++;
}
return false;
}
bool count_ports (io_stream_properties_t const *port, void *data)
{
if(stream_is_uart(port->type))
(*(uint32_t *)data)++;
return false;
}
static int cmp_ports (const void *a, const void *b)
{
return ((port_data_t *)a)->port->instance - ((port_data_t *)b)->port->instance;
} }
status_code_t report_uart_ports (sys_state_t state, char *args) status_code_t report_uart_ports (sys_state_t state, char *args)
{ {
pin_data_t pin_data = {0}; uint32_t n_ports = 0;
port_data_t *port_data;
if(hal.enumerate_pins) { stream_enumerate_streams(count_ports, &n_ports);
if(n_ports) {
if((port_data = malloc(n_ports * sizeof(port_data_t)))) {
hal.enumerate_pins(false, count_uart_pins, (void *)&pin_data); port_data->idx = 0;
stream_enumerate_streams(get_ports, port_data);
if((pin_data.pins = malloc(pin_data.n_pins * sizeof(pin_info_t)))) { qsort(port_data, n_ports, sizeof(port_data_t), cmp_ports);
for(port_data->idx = 0; port_data->idx < n_ports; port_data->idx++)
*buf = '\0'; report_port_info(port_data[port_data->idx].port, NULL);
hal.enumerate_pins(false, get_uart_pins, (void *)&pin_data);
qsort(pin_data.pins, pin_data.n_pins, sizeof(pin_info_t), cmp_pins);
for(pin_data.idx = 0; pin_data.idx < pin_data.n_pins; pin_data.idx++)
report_port_info(&pin_data.pins[pin_data.idx]);
free(pin_data.pins);
free(port_data);
} else } else
hal.enumerate_pins(false, report_pin, NULL); stream_enumerate_streams(report_port_info, NULL);
} }
return Status_OK; return Status_OK;
} }

View File

@@ -434,6 +434,7 @@ static char probing_options[] = "Allow feed override,Apply soft limits,N/A,Auto
static char control_signals[] = "Reset,Feed hold,Cycle start,Safety door,Block delete,Optional stop,EStop,Probe disconnected,Motor fault,Motor warning,Limits override,Single step blocks,Toolsetter overtravel"; static char control_signals[] = "Reset,Feed hold,Cycle start,Safety door,Block delete,Optional stop,EStop,Probe disconnected,Motor fault,Motor warning,Limits override,Single step blocks,Toolsetter overtravel";
static char spindle_signals[] = "Spindle enable,Spindle direction,PWM"; static char spindle_signals[] = "Spindle enable,Spindle direction,PWM";
static char coolant_signals[] = "Flood,Mist"; static char coolant_signals[] = "Flood,Mist";
static char door_options[] = "Ignore when idle,Keep coolant state on door open";
static char ganged_axes[] = "X-Axis,Y-Axis,Z-Axis"; static char ganged_axes[] = "X-Axis,Y-Axis,Z-Axis";
#if !AXIS_REMAP_ABC2UVW #if !AXIS_REMAP_ABC2UVW
#if N_AXIS == 4 #if N_AXIS == 4
@@ -950,6 +951,8 @@ static status_code_t set_parking_enable (setting_id_t id, uint_fast16_t int_valu
if(settings.parking.flags.deactivate_upon_init) if(settings.parking.flags.deactivate_upon_init)
settings.parking.flags.enable_override_control = On; settings.parking.flags.enable_override_control = On;
//setting_remove_elements(Setting_ProbePullUpDisable, mask);
return Status_OK; return Status_OK;
} }
@@ -1951,7 +1954,7 @@ static bool is_setting_available (const setting_detail_t *setting, uint_fast16_t
#ifndef NO_SAFETY_DOOR_SUPPORT #ifndef NO_SAFETY_DOOR_SUPPORT
case Setting_DoorOptions: case Setting_DoorOptions:
available = hal.signals_cap.safety_door_ajar; available = hal.signals_cap.safety_door_ajar || !settings.parking.flags.enabled;
break; break;
case Setting_DoorSpindleOnDelay: case Setting_DoorSpindleOnDelay:
@@ -2106,7 +2109,7 @@ PROGMEM static const setting_detail_t setting_detail[] = {
{ Setting_ParkingFastRate, Group_SafetyDoor, "Parking fast rate", "mm/min", Format_Decimal, "###0.0", NULL, NULL, Setting_IsExtended, &settings.parking.rate, NULL, NULL }, { Setting_ParkingFastRate, Group_SafetyDoor, "Parking fast rate", "mm/min", Format_Decimal, "###0.0", NULL, NULL, Setting_IsExtended, &settings.parking.rate, NULL, NULL },
{ Setting_RestoreOverrides, Group_General, "Restore overrides", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsExtendedFn, set_restore_overrides, get_int, NULL }, { Setting_RestoreOverrides, Group_General, "Restore overrides", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsExtendedFn, set_restore_overrides, get_int, NULL },
#ifndef NO_SAFETY_DOOR_SUPPORT #ifndef NO_SAFETY_DOOR_SUPPORT
{ Setting_DoorOptions, Group_SafetyDoor, "Safety door options", NULL, Format_Bitfield, "Ignore when idle,Keep coolant state on open", NULL, NULL, Setting_IsExtended, &settings.safety_door.flags.value, NULL, is_setting_available }, { Setting_DoorOptions, Group_SafetyDoor, "Safety door options", NULL, Format_Bitfield, door_options, NULL, NULL, Setting_IsExtended, &settings.safety_door.flags.value, NULL, is_setting_available },
#endif #endif
{ Setting_SleepEnable, Group_General, "Sleep enable", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsExtendedFn, set_sleep_enable, get_int, is_setting_available }, { Setting_SleepEnable, Group_General, "Sleep enable", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsExtendedFn, set_sleep_enable, get_int, is_setting_available },
{ Setting_HoldActions, Group_General, "Feed hold actions", NULL, Format_Bitfield, "Disable laser during hold,Restore spindle and coolant state on resume", NULL, NULL, Setting_IsExtendedFn, set_hold_actions, get_int, NULL }, { Setting_HoldActions, Group_General, "Feed hold actions", NULL, Format_Bitfield, "Disable laser during hold,Restore spindle and coolant state on resume", NULL, NULL, Setting_IsExtendedFn, set_hold_actions, get_int, NULL },
@@ -2287,7 +2290,8 @@ PROGMEM static const setting_descr_t setting_descr[] = {
{ Setting_ParkingFastRate, "Parking fast rate to target after pull-out in mm/min." }, { Setting_ParkingFastRate, "Parking fast rate to target after pull-out in mm/min." },
{ Setting_RestoreOverrides, "Restore overrides to default values at program end." }, { Setting_RestoreOverrides, "Restore overrides to default values at program end." },
#ifndef NO_SAFETY_DOOR_SUPPORT #ifndef NO_SAFETY_DOOR_SUPPORT
{ Setting_DoorOptions, "Enable this if it is desirable to open the safety door when in IDLE mode (eg. for jogging)." }, { 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." },
#endif #endif
{ Setting_SleepEnable, "Enable sleep mode." }, { Setting_SleepEnable, "Enable sleep mode." },
{ Setting_HoldActions, "Actions taken during feed hold and on resume from feed hold." }, { Setting_HoldActions, "Actions taken during feed hold and on resume from feed hold." },
@@ -3518,6 +3522,9 @@ void settings_init (void)
uint32_t mask = 0b001 | (hal.driver_cap.toolsetter << 1) | (hal.driver_cap.probe2 << 2); uint32_t mask = 0b001 | (hal.driver_cap.toolsetter << 1) | (hal.driver_cap.probe2 << 2);
setting_remove_elements(Setting_InvertProbePin, mask); setting_remove_elements(Setting_InvertProbePin, mask);
setting_remove_elements(Setting_ProbePullUpDisable, mask); setting_remove_elements(Setting_ProbePullUpDisable, mask);
#ifndef NO_SAFETY_DOOR_SUPPORT
setting_remove_elements(Setting_DoorOptions, ((!settings.parking.flags.enabled || hal.signals_cap.safety_door_ajar) << 1) | hal.signals_cap.safety_door_ajar);
#endif
mask = 0b00011 | (hal.probe.select ? ((hal.driver_cap.toolsetter << 3) | (hal.driver_cap.probe2 << 4)) : 0); mask = 0b00011 | (hal.probe.select ? ((hal.driver_cap.toolsetter << 3) | (hal.driver_cap.probe2 << 4)) : 0);
#if 0 #if 0

View File

@@ -576,16 +576,17 @@ static void state_await_hold (uint_fast16_t rt_exec)
// Parking motion not possible. Just disable the spindle and coolant. // Parking motion not possible. Just disable the spindle and coolant.
// NOTE: Laser mode does not start a parking motion to ensure the laser stops immediately. // NOTE: Laser mode does not start a parking motion to ensure the laser stops immediately.
spindle_all_off(); // De-energize spindle_all_off(); // De-energize
if (!settings.safety_door.flags.keep_coolant_on || sys_state == STATE_SLEEP) if(sys.flags.is_parking || sys_state == STATE_SLEEP || !settings.safety_door.flags.keep_coolant_on)
hal.coolant.set_state((coolant_state_t){0}); // De-energize hal.coolant.set_state((coolant_state_t){0}); // De-energize
sys.parking_state = hal.control.get_state().safety_door_ajar ? Parking_DoorAjar : Parking_DoorClosed; sys.parking_state = hal.control.get_state().safety_door_ajar ? Parking_DoorAjar : Parking_DoorClosed;
} }
} else { } else {
spindle_all_off(); // De-energize spindle_all_off(); // De-energize
if (!settings.safety_door.flags.keep_coolant_on || sys_state == STATE_SLEEP) if(sys.flags.is_parking || sys_state == STATE_SLEEP || !settings.safety_door.flags.keep_coolant_on)
hal.coolant.set_state((coolant_state_t){0}); // De-energize hal.coolant.set_state((coolant_state_t){0}); // De-energize
sys.parking_state = hal.control.get_state().safety_door_ajar ? Parking_DoorAjar : Parking_DoorClosed; sys.parking_state = hal.control.get_state().safety_door_ajar ? Parking_DoorAjar : Parking_DoorClosed;
} }
sys.flags.is_parking = false;
break; break;
default: default:

View File

@@ -200,10 +200,11 @@ void st_wake_up (void)
sys.steppers_deenergize = false; sys.steppers_deenergize = false;
hal.stepper.go_idle(true); // Reset step & dir outputs hal.stepper.go_idle(true); // Reset step & dir outputs
hal.stepper.wake_up();
if(settings.stepper_enable_delay) // TODO: do not add delay if deenergize is pending? if(!sys.steppers_enabled && settings.stepper_enable_delay)
hal.delay_ms(settings.stepper_enable_delay, NULL); hal.delay_ms(settings.stepper_enable_delay, NULL);
hal.stepper.wake_up();
} }
// Stepper shutdown // Stepper shutdown

View File

@@ -89,7 +89,7 @@ void stream_register_streams (io_stream_details_t *details)
} }
} }
bool stream_enumerate_streams (stream_enumerate_callback_ptr callback) bool stream_enumerate_streams (stream_enumerate_callback_ptr callback, void *data)
{ {
if(callback == NULL) if(callback == NULL)
return false; return false;
@@ -100,7 +100,7 @@ bool stream_enumerate_streams (stream_enumerate_callback_ptr callback)
while(details && !claimed) { while(details && !claimed) {
uint_fast8_t idx; uint_fast8_t idx;
for(idx = 0; idx < details->n_streams; idx++) { for(idx = 0; idx < details->n_streams; idx++) {
if((claimed = callback(&details->streams[idx]))) if((claimed = callback(&details->streams[idx], data)))
break; break;
} }
details = details->next; details = details->next;
@@ -134,7 +134,8 @@ const io_stream_status_t *stream_get_uart_status (uint8_t instance)
while(details) { while(details) {
uint_fast8_t idx; uint_fast8_t idx;
for(idx = 0; idx < details->n_streams; idx++) { for(idx = 0; idx < details->n_streams; idx++) {
if(details->streams[idx].type == StreamType_Serial && details->streams[idx].instance == instance) { if(details->streams[idx].instance == instance &&
stream_is_uart(details->streams[idx].type)) {
if(details->streams[idx].get_status) if(details->streams[idx].get_status)
status = details->streams[idx].get_status(instance); status = details->streams[idx].get_status(instance);
break; break;
@@ -439,33 +440,38 @@ bool stream_connect (const io_stream_t *stream)
{ {
bool ok; bool ok;
if((ok = stream_select(stream, true))) if((ok = stream && stream_select(stream, true)))
stream_set_description(stream, "Primary UART"); stream_set_description(stream, "Primary UART");
return ok; return ok;
} }
static struct { typedef struct {
uint8_t instance; uint8_t instance;
uint32_t baud_rate; uint32_t baud_rate;
io_stream_t const *stream; io_stream_t const *stream;
} connection; } connection_t;
static bool _open_instance (io_stream_properties_t const *stream) static bool _open_instance (io_stream_properties_t const *stream, void *data)
{ {
if(stream->type == StreamType_Serial && (connection.instance == 255 || stream->instance == connection.instance) && stream->flags.claimable && !stream->flags.claimed) connection_t *connection = (connection_t *)data;
connection.stream = stream->claim(connection.baud_rate);
return connection.stream != NULL; if(stream_is_uart(stream->type) &&
(connection->instance == 255 || stream->instance == connection->instance) &&
stream->flags.claimable && !stream->flags.claimed)
connection->stream = stream->claim(connection->baud_rate);
return connection->stream != NULL;
} }
bool stream_connect_instance (uint8_t instance, uint32_t baud_rate) bool stream_connect_instance (uint8_t instance, uint32_t baud_rate)
{ {
connection.instance = instance; connection_t connection = {
connection.baud_rate = baud_rate; .instance = instance,
connection.stream = NULL; .baud_rate = baud_rate
};
return stream_enumerate_streams(_open_instance) && stream_connect(connection.stream); return stream_enumerate_streams(_open_instance, &connection) && stream_connect(connection.stream);
} }
void stream_disconnect (const io_stream_t *stream) void stream_disconnect (const io_stream_t *stream)
@@ -476,11 +482,12 @@ void stream_disconnect (const io_stream_t *stream)
io_stream_t const *stream_open_instance (uint8_t instance, uint32_t baud_rate, stream_write_char_ptr rx_handler, const char *description) io_stream_t const *stream_open_instance (uint8_t instance, uint32_t baud_rate, stream_write_char_ptr rx_handler, const char *description)
{ {
connection.instance = instance; connection_t connection = {
connection.baud_rate = baud_rate; .instance = instance,
connection.stream = NULL; .baud_rate = baud_rate
};
if(stream_enumerate_streams(_open_instance)) { if(stream_enumerate_streams(_open_instance, &connection)) {
connection.stream->set_enqueue_rt_handler(rx_handler); connection.stream->set_enqueue_rt_handler(rx_handler);
if(description) if(description)
stream_set_description(connection.stream, description); stream_set_description(connection.stream, description);
@@ -539,7 +546,7 @@ void stream_mpg_set_mode (void *data)
stream_mpg_enable(data != NULL); stream_mpg_enable(data != NULL);
} }
ISR_CODE bool ISR_FUNC(stream_mpg_check_enable)(char c) ISR_CODE bool ISR_FUNC(stream_mpg_check_enable)(uint8_t c)
{ {
if(c == CMD_MPG_MODE_TOGGLE) if(c == CMD_MPG_MODE_TOGGLE)
task_add_immediate(stream_mpg_set_mode, (void *)1); task_add_immediate(stream_mpg_set_mode, (void *)1);
@@ -554,7 +561,7 @@ ISR_CODE bool ISR_FUNC(stream_mpg_check_enable)(char c)
bool stream_mpg_register (const io_stream_t *stream, bool rx_only, stream_write_char_ptr write_char) bool stream_mpg_register (const io_stream_t *stream, bool rx_only, stream_write_char_ptr write_char)
{ {
if(stream == NULL || stream->type != StreamType_Serial || stream->disable_rx == NULL) if(stream == NULL || !stream_is_uart(stream->type) || stream->disable_rx == NULL)
return false; return false;
// base.flags.is_up = On; // base.flags.is_up = On;
@@ -630,8 +637,11 @@ bool stream_mpg_enable (bool on)
hal.stream.read = mpg.stream.read; hal.stream.read = mpg.stream.read;
mpg.stream.disable_rx(false); mpg.stream.disable_rx(false);
mpg.stream.set_enqueue_rt_handler(hal.stream.set_enqueue_rt_handler(NULL)); mpg.stream.set_enqueue_rt_handler(hal.stream.set_enqueue_rt_handler(NULL));
if(mpg.flags.is_mpg_tx) if(mpg.flags.is_mpg_tx) {
hal.stream.write = mpg.stream.write; hal.stream.write = mpg.stream.write;
hal.stream.write_n = mpg.stream.write_n;
hal.stream.write_char = mpg.stream.write_char;
}
hal.stream.get_rx_buffer_free = mpg.stream.get_rx_buffer_free; hal.stream.get_rx_buffer_free = mpg.stream.get_rx_buffer_free;
hal.stream.cancel_read_buffer = mpg.stream.cancel_read_buffer; hal.stream.cancel_read_buffer = mpg.stream.cancel_read_buffer;
hal.stream.reset_read_buffer = mpg.stream.reset_read_buffer; hal.stream.reset_read_buffer = mpg.stream.reset_read_buffer;

View File

@@ -131,8 +131,10 @@ typedef union {
uint8_t value; uint8_t value;
struct { struct {
uint8_t dtr :1, uint8_t dtr :1,
dsr :1,
rts :1, rts :1,
unused :6; cts :1,
unused :4;
}; };
} serial_linestate_t; } serial_linestate_t;
@@ -282,7 +284,9 @@ typedef union {
is_usb :1, is_usb :1,
linestate_event :1, //!< Set when driver supports on_linestate_changed event. linestate_event :1, //!< Set when driver supports on_linestate_changed event.
passthru :1, //!< Set when stream is in passthru mode. passthru :1, //!< Set when stream is in passthru mode.
unused :4; utf8 :1, //!< Set when stream is in UTF8 mode.
eof :1, //!< Set when a file stream reaches end-of-file.
unused :2;
}; };
} io_stream_state_t; } io_stream_state_t;
@@ -334,7 +338,7 @@ typedef struct {
stream_get_status_ptr get_status; //!< Optional handler for getting stream status, for UART streams only stream_get_status_ptr get_status; //!< Optional handler for getting stream status, for UART streams only
} io_stream_properties_t; } io_stream_properties_t;
typedef bool (*stream_enumerate_callback_ptr)(io_stream_properties_t const *properties); typedef bool (*stream_enumerate_callback_ptr)(io_stream_properties_t const *properties, void *data);
typedef struct io_stream_details { typedef struct io_stream_details {
uint8_t n_streams; uint8_t n_streams;
@@ -380,6 +384,11 @@ typedef struct {
extern "C" { extern "C" {
#endif #endif
static inline bool stream_is_uart (stream_type_t type)
{
return type == StreamType_Serial || type == StreamType_Bluetooth;
}
/*! \brief Dummy function for reading data from a virtual empty input buffer. /*! \brief Dummy function for reading data from a virtual empty input buffer.
\returns always -1 as there is no data available. \returns always -1 as there is no data available.
*/ */
@@ -404,7 +413,7 @@ bool stream_mpg_enable (bool on);
void stream_mpg_set_mode (void *data); void stream_mpg_set_mode (void *data);
bool stream_mpg_check_enable (char c); bool stream_mpg_check_enable (uint8_t c);
bool stream_buffer_all (uint8_t c); bool stream_buffer_all (uint8_t c);
@@ -414,7 +423,7 @@ bool stream_enqueue_realtime_command (uint8_t c);
void stream_register_streams (io_stream_details_t *details); void stream_register_streams (io_stream_details_t *details);
bool stream_enumerate_streams (stream_enumerate_callback_ptr callback); bool stream_enumerate_streams (stream_enumerate_callback_ptr callback, void *data);
bool stream_connect (const io_stream_t *stream); bool stream_connect (const io_stream_t *stream);

View File

@@ -92,6 +92,7 @@ ISR_CODE void ISR_FUNC(control_interrupt_handler)(control_signals_t signals)
} else { } else {
#ifndef NO_SAFETY_DOOR_SUPPORT #ifndef NO_SAFETY_DOOR_SUPPORT
if(signals.safety_door_ajar && hal.signals_cap.safety_door_ajar && !gc_state.tool_change) { if(signals.safety_door_ajar && hal.signals_cap.safety_door_ajar && !gc_state.tool_change) {
sys.flags.is_parking = false;
if(settings.safety_door.flags.ignore_when_idle) { if(settings.safety_door.flags.ignore_when_idle) {
// Only stop the spindle (laser off) when idle or jogging, // Only stop the spindle (laser off) when idle or jogging,
// this to allow positioning the controlled point (spindle) when door is open. // this to allow positioning the controlled point (spindle) when door is open.
@@ -1254,11 +1255,7 @@ void system_raise_alarm (alarm_code_t alarm)
system_set_exec_alarm(alarm); system_set_exec_alarm(alarm);
else if(sys.alarm != alarm) { else if(sys.alarm != alarm) {
sys.alarm = alarm; sys.alarm = alarm;
sys.blocking_event = sys.alarm == Alarm_HardLimit || sys.blocking_event = alarm_is_critical(sys.alarm);
sys.alarm == Alarm_SoftLimit ||
sys.alarm == Alarm_EStop ||
sys.alarm == Alarm_MotorFault;
state_set(alarm == Alarm_EStop ? STATE_ESTOP : STATE_ALARM);
if(sys.driver_started || sys.alarm == Alarm_SelftestFailed) if(sys.driver_started || sys.alarm == Alarm_SelftestFailed)
grbl.report.alarm_message(alarm); grbl.report.alarm_message(alarm);
} }

View File

@@ -274,7 +274,8 @@ typedef union {
auto_reporting :1, //!< Set to true when auto real time reporting is enabled. auto_reporting :1, //!< Set to true when auto real time reporting is enabled.
travel_changed :1, //!< Set to true when maximum travel settings has changed. travel_changed :1, //!< Set to true when maximum travel settings has changed.
is_homing :1, is_homing :1,
unused :4; is_parking :1, //!< Set to true when CMD_SAFETY_DOOR is received.
unused :3;
}; };
} system_flags_t; } system_flags_t;
@@ -331,6 +332,7 @@ typedef struct system {
bool cold_start; //!< Set to true on boot, is false on subsequent soft resets. bool cold_start; //!< Set to true on boot, is false on subsequent soft resets.
bool ioinit_pending; bool ioinit_pending;
bool driver_started; //!< Set to true when driver initialization is completed. bool driver_started; //!< Set to true when driver initialization is completed.
bool steppers_enabled; //!< Set to true when all steppers are enabled.
bool mpg_mode; //!< To be moved to system_flags_t bool mpg_mode; //!< To be moved to system_flags_t
signal_event_t last_event; //!< Last signal events (control and limits signal). signal_event_t last_event; //!< Last signal events (control and limits signal).
int32_t position[N_AXIS]; //!< Real-time machine (aka home) position vector in steps. int32_t position[N_AXIS]; //!< Real-time machine (aka home) position vector in steps.

148
utf8.c Normal file
View File

@@ -0,0 +1,148 @@
/*
utf8.c - An embedded CNC Controller with rs274/ngc (g-code) support
Part of grblHAL
Copyright (c) 2025 Terje Io
utf32_to_utf8() is Copyright 2025 Kang-Che Sung, see license below.
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.
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
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with grblHAL. If not, see <http://www.gnu.org/licenses/>.
*/
#include <stdint.h>
/*
static enqueue_realtime_command_ptr utf8_base_handler = NULL;
int32_t utf8_decode (const io_stream_t *stream)
{
static int32_t count = 0, utf8_c = SERIAL_NO_DATA;
if((count && (stream->get_rx_buffer_count()) < count) || (utf8_c = stream->read()) == SERIAL_NO_DATA)
return SERIAL_NO_DATA;
if(utf8_c & 0b11100000) {
count = (c & 0b11100000) == 0b11100000 ? (c & 0b00110000) >> 4 : 1;
if(c & (0b01000000 >> count)) {
count = 0;
utf8_c = 0xFFFD;
} else
utf8_c = c & (0b00111111 >> count);
}
if(count) do {
int32_t c;
if(((c = stream->read())& 0b11000000) != 0b10000000) {
count = 1;
utf8_c = 0xFFFD;
} else {
utf8_c = (utf8_c << 6) | (c & 0b00111111);
}
} while(--count);
return utf8_c;
}
ISR_CODE bool ISR_FUNC(utf8_insert)(uint8_t c)
{
static int32_t count = 0, utf8_c = 0;
if((c & 0b11000000) == 0b11000000)
count = (utf8_c & 0b11100000) == 0b11100000 ? (utf8_c & 0b00110000) >> 4 : 1;
else if(count)
count--;
return count ? false : utf8_base_handler(c);
}
bool stream_utf8_enable (const io_stream_t *stream, bool enable)
{
if(enable) {
if(utf8_base_handler == NULL)
utf8_base_handler = hal.stream.set_enqueue_rt_handler(utf8_insert);
} else {
if(utf8_base_handler) {
hal.stream.set_enqueue_rt_handler(utf8_base_handler);
utf8_base_handler = NULL;
}
}
return true;
}
*/
/*
<https://gitlab.com/-/snippets/3718423>
Copyright 2025 Kang-Che Sung <explorer09 @ gmail.com>
MIT License (MIT/Expat)
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/* SPDX-License-Identifier: MIT */
uint16_t utf32_to_utf8 (uint8_t *buffer, uint32_t code_point)
{
// assert(code_point <= 0x10FFFF);
// assert(code_point < 0xD800 || code_point > 0xDFFF);
if(code_point > 0x10FFFF)
return 0;
uint16_t idx, length = 1;
uint32_t first_byte = code_point, mask;
if(code_point <= 0x7F) {
mask = 0b0111111; // We assume ASCII characters appear most frequently.
} else {
// Find out how many bytes are needed.
mask = 0b00111111;
do {
length++;
first_byte >>= 6;
mask >>= 1;
} while(first_byte > mask);
}
if(length <= 4) {
buffer[0] = (uint8_t)(first_byte + (~mask << 1));
for(idx = length - 1; idx > 0; idx--) {
buffer[idx] = (code_point & 0b00111111) | 0b10000000;
code_point >>= 6;
}
}
return length;
}

24
utf8.h Normal file
View File

@@ -0,0 +1,24 @@
/*
utf8.c - An embedded CNC Controller with rs274/ngc (g-code) support
Part of grblHAL
Copyright (c) 2025 Terje Io
utf32_to_utf8() is Copyright 2025 Kang-Che Sung, see license in utf8.c.
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.
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
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with grblHAL. If not, see <http://www.gnu.org/licenses/>.
*/
uint16_t utf32_to_utf8 (uint8_t *buffer, uint32_t code_point);