From ea51f156a3f664bdf495b447d5ebd51165b18fef Mon Sep 17 00:00:00 2001 From: Terje Io Date: Mon, 19 Sep 2022 15:20:41 +0200 Subject: [PATCH] Added new configuration options. See the changelog for details. --- README.md | 4 +-- changelog.md | 33 +++++++++++++++++- config.h | 19 ++++++++++- crossbar.h | 68 +++++++++++++++++++++++++------------ gcode.c | 37 ++++++++++++++------- grbl.h | 2 +- motor_pins.h | 89 ++++++++++++++++++++++++++++++++++++++++++++++++- nuts_bolts.c | 16 +++++++++ nuts_bolts.h | 6 +++- nvs.h | 6 +++- planner.c | 94 ++++++++++++++++++++++++++++++++++++++++------------ planner.h | 30 ++++++++--------- report.c | 49 +++++++++++++-------------- settings.c | 82 ++++++++++++++++++++++++++++++++++++--------- settings.h | 5 +++ 15 files changed, 421 insertions(+), 119 deletions(-) diff --git a/README.md b/README.md index 573c22d..fab0be8 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 20220916, see the [changelog](changelog.md) for details. +Latest build date is 20220918, 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-16 +2022-09-18 diff --git a/changelog.md b/changelog.md index cdee332..ad09b6c 100644 --- a/changelog.md +++ b/changelog.md @@ -1,6 +1,37 @@ ## grblHAL changelog -20220916: +Build 20220918: + +Core: + +* Added [configuration option](https://github.com/grblHAL/core/blob/master/config.h) `BLOCK_BUFFER_DYNAMIC` for dynamically allocate planner buffer. If enabled setting `$398` can be used to set number of blocks in the buffer. +__NOTE:__ A restart of the controller is required after changing `$398`. +__NOTE:__ If not enough free memory is available the actual allocation size will be reduced until it fits. The actual allocation can be checked with `$I`. +Each block requires around 100 bytes of memory. +__NOTE:__ All setting values will be reset when this option is changed, backup and restore! +__NOTE:__ In a later version this option will be removed and dynamic allocation will become standard. + +* Added experimental [configuration option](https://github.com/grblHAL/core/blob/master/config.h) `AXIS_REMAP_ABC2UVW` for remapping ABC axis letters to UVW. +When enabled the string `ABC2UVW` will be added to the `NEWOPT` element in the `$I` response, this can be used by senders to set up the UI etc. + +Drivers: + +* ESP32: Applied workaround for wifi/pin36/pin39 silicon bug. Reenabled HAL function for reboot. + +* STM32F7xx: Added support for up to 8 axes in the driver, with the reference board map only. As of now untested but it compiles and runs! +Are there any senders that can candle 8 axes available? [ioSender](https://github.com/terjeio/ioSender) can not but that may change. + +Plugins: + +* WebUI: added new and missing settings options for ESP400, added axisletters from configuration to ESP800 response. + +* SDCard: updated FatFs VFS wrapper for read-only configuration. + +* Some: moved reboot required message for some settings to reporting by using a settings flag. + +--- + +Build 20220916: Core: diff --git a/config.h b/config.h index c343148..67a72c5 100644 --- a/config.h +++ b/config.h @@ -32,14 +32,31 @@ // Compile time only default configuration + +// Uncomment this line to enable $398 for configuring number of blocks in the planner buffer. +// NOTE: Changing this will usually reset the settings to default values. Backup and restore! +// NOTE: If the $398 value is set too high number of blocks will be reduced until +// a buffer can be allocated. Use $I to check if value was set too high. +// NOTE: this compile time option will be removed in a later version and dynamic allocation +// will become the default. +//#define BLOCK_BUFFER_DYNAMIC + #ifndef N_AXIS -/*! Defines number of axes supported - minimum 3, maximum 6 +/*! Defines number of axes supported - minimum 3, maximum 8 If more than 3 axes are configured a compliant driver and map file is needed. */ #define N_AXIS 3 // Number of axes #endif +/*! Remap ABC axis letters to UVW + +Experimental: if more than 3 and less than 7 axes are configured the ABC axis letters can be remapped to UWV. +*/ +#if N_AXIS > 3 && N_AXIS < 7 +//#define AXIS_REMAP_ABC2UVW // Default disabled. Uncomment to enable. +#endif + #ifndef N_SPINDLE /*! Defines number of spindles supported - minimum 1, maximum 32 */ diff --git a/crossbar.h b/crossbar.h index f7d55ba..e7f690c 100644 --- a/crossbar.h +++ b/crossbar.h @@ -22,6 +22,8 @@ #ifndef _CROSSBAR_H_ #define _CROSSBAR_H_ +#include "nuts_bolts.h" + typedef enum { Input_Probe = 0, Input_Reset, @@ -101,6 +103,8 @@ typedef enum { Output_MotorChipSelectM3, Output_MotorChipSelectM4, Output_MotorChipSelectM5, + Output_MotorChipSelectM6, + Output_MotorChipSelectM7, Output_StepperPower, Output_StepperEnable, Output_StepperEnableX, @@ -137,7 +141,9 @@ typedef enum { Bidirectional_MotorUARTZ, Bidirectional_MotorUARTM3, Bidirectional_MotorUARTM4, - Bidirectional_MotorUARTM5 + Bidirectional_MotorUARTM5, + Bidirectional_MotorUARTM6, + Bidirectional_MotorUARTM7 } pin_function_t; #define PIN_ISINPUT(pin) (pin < Outputs) @@ -167,16 +173,6 @@ PROGMEM static const pin_name_t pin_names[] = { { .function = Input_LimitZ, .name = "Z limit min" }, { .function = Input_LimitZ_2, .name = "Z limit min 2" }, { .function = Input_LimitZ_Max, .name = "Z limit max" }, - { .function = Input_LimitA, .name = "A limit min" }, - { .function = Input_LimitA_Max, .name = "A limit max" }, - { .function = Input_LimitB, .name = "B limit min" }, - { .function = Input_LimitB_Max, .name = "B limit max" }, - { .function = Input_LimitC, .name = "C limit min" }, - { .function = Input_LimitC_Max, .name = "C limit max" }, - { .function = Input_LimitU, .name = "U limit min" }, - { .function = Input_LimitU_Max, .name = "U limit max" }, - { .function = Input_LimitV, .name = "V limit min" }, - { .function = Input_LimitV_Max, .name = "V limit max" }, { .function = Input_MISO, .name = "MISO" }, { .function = Input_RX, .name = "RX" }, { .function = Input_KeypadStrobe, .name = "Keypad strobe" }, @@ -203,28 +199,54 @@ PROGMEM static const pin_name_t pin_names[] = { { .function = Output_StepY_2, .name = "Y2 step" }, { .function = Output_StepZ, .name = "Z step" }, { .function = Output_StepZ_2, .name = "Z2 step" }, - { .function = Output_StepA, .name = "A step" }, - { .function = Output_StepB, .name = "B step" }, - { .function = Output_StepC, .name = "C step" }, { .function = Output_DirX, .name = "X dir" }, { .function = Output_DirX_2, .name = "X2 dir" }, { .function = Output_DirY, .name = "Y dir" }, { .function = Output_DirY_2, .name = "Y2 dir" }, { .function = Output_DirZ, .name = "Z dir" }, { .function = Output_DirZ_2, .name = "Z2 dir" }, - { .function = Output_DirA, .name = "A dir" }, - { .function = Output_DirB, .name = "B dir" }, - { .function = Output_DirC, .name = "C dir" }, { .function = Output_StepperPower, .name = "Stepper power" }, { .function = Output_StepperEnable, .name = "Steppers enable" }, { .function = Output_StepperEnableX, .name = "X enable" }, { .function = Output_StepperEnableY, .name = "Y enable" }, { .function = Output_StepperEnableZ, .name = "Z enable" }, - { .function = Output_StepperEnableA, .name = "A enable" }, - { .function = Output_StepperEnableB, .name = "B enable" }, - { .function = Output_StepperEnableC, .name = "C enable" }, { .function = Output_StepperEnableXY, .name = "XY enable" }, +#ifdef A_AXIS + { .function = Output_StepA, .name = "A step" }, + { .function = Output_DirA, .name = "A dir" }, + { .function = Output_StepperEnableA, .name = "A enable" }, + { .function = Input_LimitA, .name = "A limit min" }, + { .function = Input_LimitA_Max, .name = "A limit max" }, +#endif +#ifdef B_AXIS + { .function = Output_StepB, .name = "B step" }, + { .function = Output_DirB, .name = "B dir" }, + { .function = Output_StepperEnableB, .name = "B enable" }, { .function = Output_StepperEnableAB, .name = "AB enable" }, + { .function = Input_LimitB, .name = "B limit min" }, + { .function = Input_LimitB_Max, .name = "B limit max" }, +#endif +#ifdef C_AXIS + { .function = Output_StepC, .name = "C step" }, + { .function = Output_DirC, .name = "C dir" }, + { .function = Output_StepperEnableC, .name = "C enable" }, + { .function = Input_LimitC, .name = "C limit min" }, + { .function = Input_LimitC_Max, .name = "C limit max" }, +#endif +#ifdef U_AXIS + { .function = Output_StepU, .name = "U step" }, + { .function = Output_DirU, .name = "U dir" }, + { .function = Output_StepperEnableU, .name = "U enable" }, + { .function = Input_LimitU, .name = "U limit min" }, + { .function = Input_LimitU_Max, .name = "U limit max" }, +#endif +#ifdef V_AXIS + { .function = Output_StepV, .name = "V step" }, + { .function = Output_DirV, .name = "V dir" }, + { .function = Output_StepperEnableV, .name = "V enable" }, + { .function = Input_LimitV, .name = "V limit min" }, + { .function = Input_LimitV_Max, .name = "V limit max" }, +#endif { .function = Output_MotorChipSelect, .name = "Motor CS" }, { .function = Output_MotorChipSelectX, .name = "Motor CSX" }, { .function = Output_MotorChipSelectY, .name = "Motor CSY" }, @@ -232,6 +254,8 @@ PROGMEM static const pin_name_t pin_names[] = { { .function = Output_MotorChipSelectM3, .name = "Motor CSM3" }, { .function = Output_MotorChipSelectM4, .name = "Motor CSM4" }, { .function = Output_MotorChipSelectM5, .name = "Motor CSM5" }, + { .function = Output_MotorChipSelectM6, .name = "Motor CSM6" }, + { .function = Output_MotorChipSelectM7, .name = "Motor CSM7" }, { .function = Output_SpindleOn, .name = "Spindle on" }, { .function = Output_SpindleDir, .name = "Spindle direction" }, { .function = Output_SpindlePWM, .name = "Spindle PWM" }, @@ -255,7 +279,9 @@ PROGMEM static const pin_name_t pin_names[] = { { .function = Bidirectional_MotorUARTZ, .name = "UART Z" }, { .function = Bidirectional_MotorUARTM3, .name = "UART M3" }, { .function = Bidirectional_MotorUARTM4, .name = "UART M4" }, - { .function = Bidirectional_MotorUARTM5, .name = "UART M5" } + { .function = Bidirectional_MotorUARTM5, .name = "UART M5" }, + { .function = Bidirectional_MotorUARTM6, .name = "UART M6" }, + { .function = Bidirectional_MotorUARTM7, .name = "UART M7" } }; typedef enum { diff --git a/gcode.c b/gcode.c index 29740c3..f994e39 100644 --- a/gcode.c +++ b/gcode.c @@ -1117,29 +1117,41 @@ status_code_t gc_execute_block(char *block) switch(letter) { - #ifdef A_AXIS +#ifdef A_AXIS + #ifndef AXIS_REMAP_ABC2UVW case 'A': + #else + case 'U': + #endif axis_words.a = On; word_bit.parameter.a = On; gc_block.values.xyz[A_AXIS] = value; break; - #endif +#endif - #ifdef B_AXIS +#ifdef B_AXIS + #ifndef AXIS_REMAP_ABC2UVW case 'B': + #else + case 'V': + #endif axis_words.b = On; word_bit.parameter.b = On; gc_block.values.xyz[B_AXIS] = value; break; - #endif +#endif - #ifdef C_AXIS - case 'C': +#ifdef C_AXIS + #ifndef AXIS_REMAP_ABC2UVW + case 'C': + #else + case 'W': + #endif axis_words.c = On; word_bit.parameter.c = On; gc_block.values.xyz[C_AXIS] = value; break; - #endif +#endif case 'D': word_bit.parameter.d = On; @@ -1222,21 +1234,21 @@ status_code_t gc_execute_block(char *block) gc_block.values.t = isnan(value) ? 0xFFFFFFFF : int_value; break; - #ifdef U_AXIS +#ifdef U_AXIS case 'U': axis_words.u = On; word_bit.parameter.u = On; gc_block.values.xyz[U_AXIS] = value; break; - #endif +#endif - #ifdef V_AXIS +#ifdef V_AXIS case 'V': axis_words.v = On; word_bit.parameter.v = On; gc_block.values.xyz[V_AXIS] = value; break; - #endif +#endif case 'X': axis_words.x = On; @@ -3059,7 +3071,8 @@ status_code_t gc_execute_block(char *block) gc_state.modal.feed_mode = FeedMode_UnitsPerMin; // TODO: check gc_state.distance_per_rev = 0.0f; // gc_state.modal.cutter_comp = CUTTER_COMP_DISABLE; // Not supported. - gc_state.modal.coord_system.id = CoordinateSystem_G54; + if((sys.report.gwco = gc_state.modal.coord_system.id != CoordinateSystem_G54)) + gc_state.modal.coord_system.id = CoordinateSystem_G54; gc_state.modal.spindle = (spindle_state_t){0}; gc_state.modal.coolant = (coolant_state_t){0}; gc_state.modal.override_ctrl.feed_rate_disable = Off; diff --git a/grbl.h b/grbl.h index 5aedd64..3d4825a 100644 --- a/grbl.h +++ b/grbl.h @@ -34,7 +34,7 @@ #else #define GRBL_VERSION "1.1f" #endif -#define GRBL_BUILD 20220916 +#define GRBL_BUILD 20220918 // The following symbols are set here if not already set by the compiler or in config.h // Do NOT change here! diff --git a/motor_pins.h b/motor_pins.h index 2262759..528b0a9 100644 --- a/motor_pins.h +++ b/motor_pins.h @@ -5,7 +5,7 @@ Part of grblHAL - Copyright (c) 2021 Terje Io + Copyright (c) 2021-2022 Terje Io Grbl is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -477,6 +477,61 @@ #endif #endif +#ifdef U_AXIS +#ifndef M6_AVAILABLE + #error "U_AXIS pins are not available" +#endif +#define U_STEP_PORT M6_STEP_PORT +#define U_STEP_PIN M6_STEP_PIN +#define U_STEP_BIT (1<= 7 && !defined(U_LIMIT_BIT) +#ifdef U_LIMIT_PIN +#define U_LIMIT_BIT (1< 6 && defined(AXIS_REMAP_ABC2UVW) +#error "Illegal remapping of ABC axes!" +#endif + char const *const axis_letter[N_AXIS] = { "X", "Y", "Z" #if N_AXIS > 3 + #ifndef AXIS_REMAP_ABC2UVW ,"A" + #else + ,"U" + #endif #endif #if N_AXIS > 4 + #ifndef AXIS_REMAP_ABC2UVW ,"B" + #else + ,"V" + #endif #endif #if N_AXIS > 5 + #ifndef AXIS_REMAP_ABC2UVW ,"C" + #else + ,"W" + #endif #endif #if N_AXIS > 6 ,"U" diff --git a/nuts_bolts.h b/nuts_bolts.h index ffb8ae8..bc144b1 100644 --- a/nuts_bolts.h +++ b/nuts_bolts.h @@ -104,7 +104,11 @@ #define AXES_BITMASK (X_AXIS_BIT|Y_AXIS_BIT|Z_AXIS_BIT|A_AXIS_BIT|B_AXIS_BIT|C_AXIS_BIT|U_AXIS_BIT|V_AXIS_BIT) #endif -#ifdef C_AXIS +#ifdef V_AXIS +#define N_ABC_AXIS 5 +#elif defined(U_AXIS) +#define N_ABC_AXIS 4 +#elif defined(C_AXIS) #define N_ABC_AXIS 3 #elif defined(B_AXIS) #define N_ABC_AXIS 2 diff --git a/nvs.h b/nvs.h index 18c000e..644d708 100644 --- a/nvs.h +++ b/nvs.h @@ -33,7 +33,11 @@ Minimum 1024 bytes required, more if space for driver and/or plugin data and set /*! \brief Number of bytes at the start of the NVS area reserved for core settings and parameters. Minimum 1024 bytes required. */ +#if N_AXIS > 6 +#define GRBL_NVS_END 1151 +#else #define GRBL_NVS_END 1023 +#endif //! Number of bytes used for storing CRC values. Do not change this! #define NVS_CRC_BYTES 1 @@ -47,7 +51,7 @@ __NOTE:__ 1024 bytes of persistent storage is the minimum required. ///@{ #define NVS_ADDR_GLOBAL 1U #define NVS_ADDR_PARAMETERS 512U -#define NVS_ADDR_BUILD_INFO 942U +#define NVS_ADDR_BUILD_INFO (GRBL_NVS_END - 81U) #define NVS_ADDR_STARTUP_BLOCK (NVS_ADDR_BUILD_INFO - 1 - N_STARTUP_LINE * (sizeof(stored_line_t) + NVS_CRC_BYTES)) #ifdef N_TOOLS #define NVS_ADDR_TOOL_TABLE (GRBL_NVS_END + 1) diff --git a/planner.c b/planner.c index 91be424..7db71d4 100644 --- a/planner.c +++ b/planner.c @@ -29,6 +29,7 @@ #include "hal.h" #include "nuts_bolts.h" #include "planner.h" +#include "protocol.h" #ifndef MINIMUM_JUNCTION_SPEED #define MINIMUM_JUNCTION_SPEED 0.0f @@ -40,7 +41,13 @@ void mc_sync_backlash_position (void); #endif -static plan_block_t block_buffer[BLOCK_BUFFER_SIZE]; // A ring buffer for motion instructions +// The number of linear motions that can be in the plan at any give time +#ifndef BLOCK_BUFFER_SIZE + #define BLOCK_BUFFER_SIZE 35 +#endif + +static uint_fast16_t block_buffer_size; // Number of blocks in the planner buffer minus 1 +static plan_block_t *block_buffer = NULL; // A ring buffer for motion instructions static plan_block_t *block_buffer_tail = NULL; // Pointer to the block to process now static plan_block_t *block_buffer_head; // Pointer to the next block to be pushed static plan_block_t *next_buffer_head; // Pointer to the next buffer head @@ -114,7 +121,7 @@ static planner_t pl; look-ahead blocks numbering up to a hundred or more. */ -static void planner_recalculate () +static void planner_recalculate (void) { // Initialize block pointer to the last block in the planner buffer. plan_block_t *block = block_buffer_head->prev; @@ -203,7 +210,7 @@ inline static void plan_cleanup (plan_block_t *block) } -inline static void plan_reset_buffer () +inline static void plan_reset_buffer (void) { if(block_buffer_tail) { // Free memory for any pending messages and output commands after soft reset @@ -213,14 +220,58 @@ inline static void plan_reset_buffer () } } - block_buffer_tail = block_buffer_head = &block_buffer[0]; // Empty = tail == head - next_buffer_head = block_buffer_head->next; // = next block - block_buffer_planned = block_buffer_tail; // = block_buffer_tail + block_buffer_tail = block_buffer_head = block_buffer; // Empty = tail == head + next_buffer_head = block_buffer_head->next; // = next block + block_buffer_planned = block_buffer_tail; // = block_buffer_tail } -void plan_reset () +#ifdef BLOCK_BUFFER_DYNAMIC + +static void planner_warning (sys_state_t state) { + report_message("Planner buffer size was reduced!", Message_Plain); +} + +#endif + + +uint_fast16_t plan_get_buffer_size (void) +{ + return block_buffer_size; +} + +bool plan_reset (void) +{ +#ifndef BLOCK_BUFFER_DYNAMIC + + static plan_block_t block_buffer_s[BLOCK_BUFFER_SIZE + 1]; + + block_buffer = block_buffer_s; + block_buffer_size = BLOCK_BUFFER_SIZE; + +#else + + if(block_buffer == NULL) { + + block_buffer_size = settings.planner_buffer_blocks; + + while((block_buffer = malloc((block_buffer_size + 1) * sizeof(plan_block_t))) == NULL) { + if(block_buffer_size > 40) + block_buffer_size -= block_buffer_size >= 250 ? 100 : 10; + else + break; + } + } + + if(block_buffer_size != settings.planner_buffer_blocks) + protocol_enqueue_rt_command(planner_warning); + + if(block_buffer == NULL) + return false; + +#endif + if(block_buffer_tail) { // Free memory for any pending messages and output commands after soft reset while(block_buffer_tail != block_buffer_head) { @@ -234,16 +285,18 @@ void plan_reset () // Set up stepper block ringbuffer as circular doubly linked list uint_fast8_t idx; - for(idx = 0 ; idx <= BLOCK_BUFFER_SIZE - 1 ; idx++) { - block_buffer[idx].prev = &block_buffer[idx == 0 ? BLOCK_BUFFER_SIZE - 1 : idx - 1]; - block_buffer[idx].next = &block_buffer[idx == BLOCK_BUFFER_SIZE - 1 ? 0 : idx + 1]; + for(idx = 0 ; idx <= block_buffer_size ; idx++) { + block_buffer[idx].prev = &block_buffer[idx == 0 ? block_buffer_size : idx - 1]; + block_buffer[idx].next = &block_buffer[idx == block_buffer_size ? 0 : idx + 1]; } plan_reset_buffer(); + + return true; } -void plan_discard_current_block () +void plan_discard_current_block (void) { if (block_buffer_tail != block_buffer_head) { // Discard non-empty buffer. plan_cleanup(block_buffer_tail); @@ -256,20 +309,20 @@ void plan_discard_current_block () // Returns address of planner buffer block used by system motions. Called by segment generator. -plan_block_t *plan_get_system_motion_block () +plan_block_t *plan_get_system_motion_block (void) { return block_buffer_head; } // Returns address of first planner block, if available. Called by various main program functions. -plan_block_t *plan_get_current_block () +plan_block_t *plan_get_current_block (void) { return block_buffer_head == block_buffer_tail ? NULL : block_buffer_tail; } -inline float plan_get_exec_block_exit_speed_sqr () +inline float plan_get_exec_block_exit_speed_sqr (void) { plan_block_t *block = block_buffer_tail->next; return block == block_buffer_head ? 0.0f : block->entry_speed_sqr; @@ -277,7 +330,7 @@ inline float plan_get_exec_block_exit_speed_sqr () // Returns the availability status of the block ring buffer. True, if full. -bool plan_check_full_buffer () +bool plan_check_full_buffer (void) { return block_buffer_tail == next_buffer_head; } @@ -315,7 +368,7 @@ inline static float plan_compute_profile_parameters (plan_block_t *block, float } // Re-calculates buffered motions profile parameters upon a motion-based override change. -void plan_update_velocity_profile_parameters () +void plan_update_velocity_profile_parameters (void) { plan_block_t *block = block_buffer_tail; float prev_nominal_speed = SOME_LARGE_VALUE; // Set high for first block nominal speed calculation. @@ -354,7 +407,6 @@ static inline float limit_max_rate_by_axis_maximum (float *unit_vec) } - /* Add a new linear movement to the buffer. target[N_AXIS] is the signed, absolute target position in millimeters. Feed rate specifies the speed of the motion. If feed rate is inverted, the feed rate is taken to mean "frequency" and would complete the operation in 1/feed_rate minutes. @@ -549,7 +601,7 @@ float *plan_get_position (void) // Reset the planner position vectors. Called by the system abort/initialization routine. -void plan_sync_position () +void plan_sync_position (void) { memcpy(pl.position, sys.position, sizeof(pl.position)); #ifdef ENABLE_BACKLASH_COMPENSATION @@ -559,17 +611,17 @@ void plan_sync_position () // Returns the number of available blocks are in the planner buffer. -uint_fast16_t plan_get_block_buffer_available () +uint_fast16_t plan_get_block_buffer_available (void) { return (uint_fast16_t)(block_buffer_head >= block_buffer_tail - ? ((BLOCK_BUFFER_SIZE - 1) - (block_buffer_head - block_buffer_tail)) + ? (block_buffer_size - (block_buffer_head - block_buffer_tail)) : ((block_buffer_tail - block_buffer_head) - 1)); } // Re-initialize buffer plan with a partially completed block, assumed to exist at the buffer tail. // Called after a steppers have come to a complete stop for a feed hold and the cycle is stopped. -void plan_cycle_reinitialize () +void plan_cycle_reinitialize (void) { // Re-plan from a complete stop. Reset planner entry speeds and buffer planned pointer. st_update_plan_block_parameters(); diff --git a/planner.h b/planner.h index 427ec32..c3247a2 100644 --- a/planner.h +++ b/planner.h @@ -24,11 +24,6 @@ #ifndef _PLANNER_H_ #define _PLANNER_H_ -// The number of linear motions that can be in the plan at any give time -#ifndef BLOCK_BUFFER_SIZE - #define BLOCK_BUFFER_SIZE 36 -#endif - typedef union { uint32_t value; struct { @@ -108,44 +103,45 @@ typedef struct { } planner_t; // Initialize and reset the motion plan subsystem -void plan_reset(); // Reset all -//void plan_reset_buffer(); // Reset buffer only. +bool plan_reset (void); // Reset all + +uint_fast16_t plan_get_buffer_size (void); // Add a new linear movement to the buffer. target[N_AXIS] is the signed, absolute target position // in millimeters. Feed rate specifies the speed of the motion. If feed rate is inverted, the feed // rate is taken to mean "frequency" and would complete the operation in 1/feed_rate minutes. -bool plan_buffer_line(float *target, plan_line_data_t *pl_data); +bool plan_buffer_line (float *target, plan_line_data_t *pl_data); // Called when the current block is no longer needed. Discards the block and makes the memory // available for new blocks. -void plan_discard_current_block(); +void plan_discard_current_block (void); // Gets the planner block for the special system motion cases. (Parking/Homing) -plan_block_t *plan_get_system_motion_block(); +plan_block_t *plan_get_system_motion_block (void); // Gets the current block. Returns NULL if buffer empty -plan_block_t *plan_get_current_block(); +plan_block_t *plan_get_current_block (void); // Called by step segment buffer when computing executing block velocity profile. -float plan_get_exec_block_exit_speed_sqr(); +float plan_get_exec_block_exit_speed_sqr (void); // Called by main program during planner calculations and step segment buffer during initialization. -float plan_compute_profile_nominal_speed(plan_block_t *block); +float plan_compute_profile_nominal_speed (plan_block_t *block); // Get the planner position vectors. float *plan_get_position (void); // Reset the planner position vector (in steps) -void plan_sync_position(); +void plan_sync_position (void); // Reinitialize plan with a partially completed block -void plan_cycle_reinitialize(); +void plan_cycle_reinitialize (void); // Returns the number of available blocks in the planner buffer. -uint_fast16_t plan_get_block_buffer_available(); +uint_fast16_t plan_get_block_buffer_available (void); // Returns the status of the block ring buffer. True, if buffer is full. -bool plan_check_full_buffer(); +bool plan_check_full_buffer (void); void plan_feed_override (uint_fast8_t feed_override, uint_fast8_t rapid_override); diff --git a/report.c b/report.c index 5116518..8216a87 100644 --- a/report.c +++ b/report.c @@ -193,29 +193,16 @@ static char *get_rate_value_inch (float value) // NOTE: returns pointer to null terminator! inline static char *axis_signals_tostring (char *buf, axes_signals_t signals) { - if(signals.x) - *buf++ = 'X'; + uint_fast16_t idx = 0; - if(signals.y) - *buf++ = 'Y'; + signals.mask &= AXES_BITMASK; - if (signals.z) - *buf++ = 'Z'; - -#ifdef A_AXIS - if (signals.a) - *buf++ = 'A'; -#endif - -#ifdef B_AXIS - if (signals.b) - *buf++ = 'B'; -#endif - -#ifdef C_AXIS - if (signals.c) - *buf++ = 'C'; -#endif + while(signals.mask) { + if(signals.mask & 0x01) + *buf++ = *axis_letter[idx]; + idx++; + signals.mask >>= 1; + }; *buf = '\0'; @@ -929,7 +916,7 @@ void report_build_info (char *line, bool extended) hal.stream.write(buf); // NOTE: Compiled values, like override increments/max/min values, may be added at some point later. - hal.stream.write(uitoa((uint32_t)(BLOCK_BUFFER_SIZE - 1))); + hal.stream.write(uitoa((uint32_t)plan_get_buffer_size())); hal.stream.write(","); hal.stream.write(uitoa(hal.rx_buffer_size)); if(extended) { @@ -1002,6 +989,10 @@ void report_build_info (char *line, bool extended) if(hal.rtc.get_datetime) strcat(buf, "RTC,"); +#ifdef AXIS_REMAP_ABC2UVW + strcat(buf, "ABC2UVW,"); +#endif + #ifdef PID_LOG strcat(buf, "PID,"); #endif @@ -1504,7 +1495,7 @@ static void report_settings_detail (settings_format_t format, const setting_deta if(setting->reboot_required) hal.stream.write(", reboot required"); - #ifndef NO_SETTINGS_DESCRIPTIONS +#ifndef NO_SETTINGS_DESCRIPTIONS // Add description if driver is capable of outputting it... if(hal.stream.write_n) { const char *description = setting_get_description(setting->id); @@ -1522,6 +1513,11 @@ static void report_settings_detail (settings_format_t format, const setting_deta hal.stream.write(description); } } + if(setting->reboot_required) { + if(description && *description != '\0') + hal.stream.write(ASCII_EOL ASCII_EOL); + hal.stream.write(SETTINGS_HARD_RESET_REQUIRED + 4); + } } #endif break; @@ -1668,6 +1664,8 @@ static void report_settings_detail (settings_format_t format, const setting_deta #ifndef NO_SETTINGS_DESCRIPTIONS const char *description = setting_get_description((setting_id_t)(setting->id + offset)); hal.stream.write(description ? description : ""); + if(setting->reboot_required) + hal.stream.write(SETTINGS_HARD_RESET_REQUIRED + (description && *description != '\0' ? 0 : 4)); #endif hal.stream.write("\t"); @@ -1796,6 +1794,7 @@ status_code_t report_settings_details (settings_format_t format, setting_id_t id status_code_t report_setting_description (settings_format_t format, setting_id_t id) { + const setting_detail_t *setting = setting_get_details(id, NULL); const char *description = setting_get_description(id); if(format == SettingsFormat_MachineReadable) { @@ -1804,7 +1803,9 @@ status_code_t report_setting_description (settings_format_t format, setting_id_t hal.stream.write(vbar); } // hal.stream.write(description == NULL ? (is_setting_available(setting_get_details(id, NULL)) ? "" : "N/A") : description); // TODO? - hal.stream.write(description == NULL ? (setting_get_details(id, NULL) ? "" : "N/A") : description); + hal.stream.write(description ? description : (setting ? "" : "N/A")); + if(setting && setting->reboot_required) + hal.stream.write(SETTINGS_HARD_RESET_REQUIRED + (description && *description != '\0' ? 0 : 4)); if(format == SettingsFormat_MachineReadable) hal.stream.write("]" ASCII_EOL); diff --git a/settings.c b/settings.c index ce053ef..31608ef 100644 --- a/settings.c +++ b/settings.c @@ -73,7 +73,15 @@ PROGMEM const settings_t defaults = { .junction_deviation = DEFAULT_JUNCTION_DEVIATION, .arc_tolerance = DEFAULT_ARC_TOLERANCE, .g73_retract = DEFAULT_G73_RETRACT, - +#ifdef BLOCK_BUFFER_DYNAMIC + #ifdef PLANNER_BUFFER_BLOCKS + .planner_buffer_blocks = PLANNER_BUFFER_BLOCKS, + #elif defined(BLOCK_BUFFER_SIZE) + .planner_buffer_blocks = BLOCK_BUFFER_SIZE, + #else + .planner_buffer_blocks = 35, + #endif +#endif .flags.legacy_rt_commands = DEFAULT_LEGACY_RTCOMMANDS, .flags.report_inches = DEFAULT_REPORT_INCHES, .flags.sleep_enable = DEFAULT_SLEEP_ENABLE, @@ -318,20 +326,32 @@ PROGMEM static const setting_group_detail_t setting_group_detail [] = { { Group_Axis, Group_XAxis, "X-axis"}, { Group_Axis, Group_YAxis, "Y-axis"}, { Group_Axis, Group_ZAxis, "Z-axis"}, -#ifdef A_AXIS +#ifndef AXIS_REMAP_ABC2UVW + #ifdef A_AXIS { Group_Axis, Group_AAxis, "A-axis"}, -#endif -#ifdef B_AXIS + #endif + #ifdef B_AXIS { Group_Axis, Group_BAxis, "B-axis"}, -#endif -#ifdef C_AXIS + #endif + #ifdef C_AXIS { Group_Axis, Group_CAxis, "C-axis"}, -#endif -#ifdef U_AXIS + #endif + #ifdef U_AXIS { Group_Axis, Group_UAxis, "U-axis"}, -#endif -#ifdef V_AXIS + #endif + #ifdef V_AXIS { Group_Axis, Group_VAxis, "V-axis"} + #endif +#else + #ifdef A_AXIS + { Group_Axis, Group_AAxis, "U-axis"}, + #endif + #ifdef B_AXIS + { Group_Axis, Group_BAxis, "V-axis"}, + #endif + #ifdef C_AXIS + { Group_Axis, Group_CAxis, "W-axis"}, + #endif #endif }; @@ -518,12 +538,26 @@ PROGMEM static const setting_detail_t setting_detail[] = { #if COMPATIBILITY_LEVEL <= 1 { Setting_DisableG92Persistence, Group_General, "Disable G92 persistence", NULL, Format_Bool, NULL, NULL, NULL, Setting_IsExtendedFn, set_g92_disable_persistence, get_int, NULL }, #endif -#if N_AXIS == 4 - { Settings_Axis_Rotational, Group_Stepper, "Rotational axes", NULL, Format_Bitfield, "A-Axis", NULL, NULL, Setting_IsExtendedFn, set_rotational_axes, get_int, NULL }, -#elif N_AXIS == 5 - { Settings_Axis_Rotational, Group_Stepper, "Rotational axes", NULL, Format_Bitfield, "A-Axis,B-Axis", NULL, NULL, Setting_IsExtendedFn, set_rotational_axes, get_int, NULL }, -#elif N_AXIS > 5 - { Settings_Axis_Rotational, Group_Stepper, "Rotational axes", NULL, Format_Bitfield, "A-Axis,B-Axis,C-Axis", NULL, NULL, Setting_IsExtendedFn, set_rotational_axes, get_int, NULL }, +#ifndef AXIS_REMAP_ABC2UVW + #if N_AXIS == 4 + { Settings_Axis_Rotational, Group_Stepper, "Rotational axes", NULL, Format_Bitfield, "A-Axis", NULL, NULL, Setting_IsExtendedFn, set_rotational_axes, get_int, NULL }, + #elif N_AXIS == 5 + { Settings_Axis_Rotational, Group_Stepper, "Rotational axes", NULL, Format_Bitfield, "A-Axis,B-Axis", NULL, NULL, Setting_IsExtendedFn, set_rotational_axes, get_int, NULL }, + #elif N_AXIS == 6 + { Settings_Axis_Rotational, Group_Stepper, "Rotational axes", NULL, Format_Bitfield, "A-Axis,B-Axis,C-Axis", NULL, NULL, Setting_IsExtendedFn, set_rotational_axes, get_int, NULL }, + #elif N_AXIS == 7 + { Settings_Axis_Rotational, Group_Stepper, "Rotational axes", NULL, Format_Bitfield, "A-Axis,B-Axis,C-Axis,U-Axis", NULL, NULL, Setting_IsExtendedFn, set_rotational_axes, get_int, NULL }, + #elif N_AXIS == 8 + { Settings_Axis_Rotational, Group_Stepper, "Rotational axes", NULL, Format_Bitfield, "A-Axis,B-Axis,C-Axis,U-Axis,V-Axis", NULL, NULL, Setting_IsExtendedFn, set_rotational_axes, get_int, NULL }, + #endif +#else + #if N_AXIS == 4 + { Settings_Axis_Rotational, Group_Stepper, "Rotational axes", NULL, Format_Bitfield, "U-Axis", NULL, NULL, Setting_IsExtendedFn, set_rotational_axes, get_int, NULL }, + #elif N_AXIS == 5 + { Settings_Axis_Rotational, Group_Stepper, "Rotational axes", NULL, Format_Bitfield, "U-Axis,V-Axis", NULL, NULL, Setting_IsExtendedFn, set_rotational_axes, get_int, NULL }, + #elif N_AXIS = 6 + { Settings_Axis_Rotational, Group_Stepper, "Rotational axes", NULL, Format_Bitfield, "U-Axis,V-Axis,W-Axis", NULL, NULL, Setting_IsExtendedFn, set_rotational_axes, get_int, NULL }, + #endif #endif #ifndef NO_SAFETY_DOOR_SUPPORT { Setting_DoorSpindleOnDelay, Group_SafetyDoor, "Spindle on delay", "s", Format_Decimal, "#0.0", "0.5", "20", Setting_IsExtended, &settings.safety_door.spindle_on_delay, NULL, is_setting_available }, @@ -531,6 +565,9 @@ PROGMEM static const setting_detail_t setting_detail[] = { #endif { Setting_SpindleOnDelay, Group_Spindle, "Spindle on delay", "s", Format_Decimal, "#0.0", "0.5", "20", Setting_IsExtended, &settings.safety_door.spindle_on_delay, NULL, is_setting_available }, { Setting_SpindleType, Group_Spindle, "Default spindle", NULL, Format_RadioButtons, spindle_types, NULL, NULL, Setting_IsExtendedFn, set_spindle_type, get_int, is_setting_available }, +#ifdef BLOCK_BUFFER_DYNAMIC + { Setting_PlannerBlocks, Group_General, "Planner buffer blocks", NULL, Format_Int16, "####0", "30", "1000", Setting_IsExtended, &settings.planner_buffer_blocks, NULL, NULL, true }, +#endif }; #ifndef NO_SETTINGS_DESCRIPTIONS @@ -679,6 +716,9 @@ PROGMEM static const setting_descr_t setting_descr[] = { { Setting_DoorSpindleOnDelay, "Delay to allow spindle to spin up when spindle at speed tolerance is > 0." }, #endif { Setting_SpindleType, "Spindle selected on startup." }, +#ifdef BLOCK_BUFFER_DYNAMIC + { Setting_PlannerBlocks, "Number of blocks in the planner buffer." }, +#endif }; #endif @@ -1794,6 +1834,11 @@ bool read_global_settings () if(settings.spindle.flags.type >= spindle_get_count()) settings.spindle.flags.type = 0; +#ifdef BLOCK_BUFFER_DYNAMIC + if(settings.planner_buffer_blocks < 30 || settings.planner_buffer_blocks > 1000) + settings.planner_buffer_blocks = 35; +#endif + sys.mode = settings.mode; if(!(hal.driver_cap.spindle_sync || hal.driver_cap.spindle_pid)) @@ -2178,6 +2223,11 @@ bool setting_is_list (const setting_detail_t *setting) return setting->datatype == Format_Bitfield || setting->datatype == Format_XBitfield || setting->datatype == Format_RadioButtons; } +bool setting_is_integer (const setting_detail_t *setting) +{ + return setting->datatype == Format_Integer || setting->datatype == Format_Int8 || setting->datatype == Format_Int16; +} + static char *remove_element (char *s, uint_fast8_t entry) { while(entry && *s) { diff --git a/settings.h b/settings.h index 13dcf1b..1adfe72 100644 --- a/settings.h +++ b/settings.h @@ -266,6 +266,7 @@ typedef enum { Setting_SpindleType = 395, Setting_WebUiTimeout = 396, Setting_WebUiAutoReportInterval = 397, + Setting_PlannerBlocks = 398, Setting_EncoderSettingsBase = 400, // NOTE: Reserving settings values >= 400 for encoder settings. Up to 449. Setting_EncoderSettingsMax = 449, @@ -592,6 +593,9 @@ typedef struct { float junction_deviation; float arc_tolerance; float g73_retract; +#ifdef BLOCK_BUFFER_DYNAMIC + uint16_t planner_buffer_blocks; +#endif machine_mode_t mode; tool_change_settings_t tool_change; axis_settings_t axis[N_AXIS]; @@ -817,6 +821,7 @@ uint32_t setting_get_int_value (const setting_detail_t *setting, uint_fast16_t o float setting_get_float_value (const setting_detail_t *setting, uint_fast16_t offset); setting_id_t settings_get_axis_base (setting_id_t id, uint_fast8_t *idx); bool setting_is_list (const setting_detail_t *setting); +bool setting_is_integer (const setting_detail_t *setting); void setting_remove_elements (setting_id_t id, uint32_t mask); bool settings_add_spindle_type (const char *type);