diff --git a/.github/workflows/ci-build-tests.yml b/.github/workflows/ci-build-tests.yml index ad37100d60..546faa5f38 100644 --- a/.github/workflows/ci-build-tests.yml +++ b/.github/workflows/ci-build-tests.yml @@ -14,6 +14,8 @@ on: - config/** - data/** - docs/** + - test/** + - Marlin/tests/** - '**/*.md' push: branches: @@ -23,6 +25,8 @@ on: - config/** - data/** - docs/** + - test/** + - Marlin/tests/** - '**/*.md' jobs: diff --git a/.github/workflows/ci-validate-pins.yml b/.github/workflows/ci-validate-pins.yml new file mode 100644 index 0000000000..e093eb92c7 --- /dev/null +++ b/.github/workflows/ci-validate-pins.yml @@ -0,0 +1,51 @@ +# +# ci-validate-pins.yml +# Validate that all of the pins files are unchanged by pinsformat.py +# + +name: CI - Validate Pins Files + +on: + pull_request: + branches: + - bugfix-2.1.x + # Cannot be enabled on 2.1.x until it contains the unit test framework + #- 2.1.x + paths: + - 'Marlin/src/pins/*/**' + push: + branches: + - bugfix-2.1.x + # Cannot be enabled on 2.1.x until it contains the unit test framework + #- 2.1.x + paths: + - 'Marlin/src/pins/*/**' + +jobs: + validate_pins_files: + name: Validate Pins Files + if: github.repository == 'MarlinFirmware/Marlin' + + runs-on: ubuntu-latest + + steps: + - name: Check out the PR + uses: actions/checkout@v4 + + - name: Cache pip + uses: actions/cache@v4 + with: + path: ~/.cache/pip + key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }} + restore-keys: | + ${{ runner.os }}-pip- + + - name: Select Python 3.9 + uses: actions/setup-python@v5 + with: + python-version: '3.9' + architecture: 'x64' + + - name: Validate all pins files + run: | + make validate-pins -j diff --git a/Makefile b/Makefile index 029ab3ada1..02722b9ca2 100644 --- a/Makefile +++ b/Makefile @@ -2,22 +2,23 @@ SCRIPTS_DIR := buildroot/share/scripts CONTAINER_RT_BIN := docker CONTAINER_RT_OPTS := --rm -v $(PWD):/code -v platformio-cache:/root/.platformio CONTAINER_IMAGE := marlin-dev +UNIT_TEST_CONFIG ?= default help: @echo "Tasks for local development:" @echo "make marlin : Build marlin for the configured board" - @echo "make format-pins : Reformat all pins files" + @echo "make format-pins -j : Reformat all pins files (-j for parallel execution)" + @echo "make validate-pins -j : Validate all pins files, fails if any require reformatting" @echo "make tests-single-ci : Run a single test from inside the CI" @echo "make tests-single-local : Run a single test locally" @echo "make tests-single-local-docker : Run a single test locally, using docker" @echo "make tests-all-local : Run all tests locally" @echo "make tests-all-local-docker : Run all tests locally, using docker" -# @echo "make unit-test-single-ci : Run a single code test from inside the CI" -# @echo "make unit-test-single-local : Run a single code test locally" -# @echo "make unit-test-single-local-docker : Run a single code test locally, using docker-compose" + @echo "make unit-test-single-local : Run unit tests for a single config locally" + @echo "make unit-test-single-local-docker : Run unit tests for a single config locally, using docker" @echo "make unit-test-all-local : Run all code tests locally" - @echo "make unit-test-all-local-docker : Run all code tests locally, using docker-compose" - @echo "make setup-local-docker : Setup local docker-compose" + @echo "make unit-test-all-local-docker : Run all code tests locally, using docker" + @echo "make setup-local-docker : Setup local docker using buildx" @echo "" @echo "Options for testing:" @echo " TEST_TARGET Set when running tests-single-*, to select the" @@ -27,6 +28,9 @@ help: @echo " run on GitHub CI" @echo " ONLY_TEST Limit tests to only those that contain this, or" @echo " the index of the test (1-based)" + @echo " UNIT_TEST_CONFIG Set the name of the config from the test folder, without" + @echo " the leading number. Default is 'default'". Used with the + @echo " unit-test-single-* tasks" @echo " VERBOSE_PLATFORMIO If you want the full PIO output, set any value" @echo " GIT_RESET_HARD Used by CI: reset all local changes. WARNING:" @echo " THIS WILL UNDO ANY CHANGES YOU'VE MADE!" @@ -51,27 +55,29 @@ tests-single-local-docker: $(CONTAINER_RT_BIN) run $(CONTAINER_RT_OPTS) $(CONTAINER_IMAGE) make tests-single-local TEST_TARGET=$(TEST_TARGET) VERBOSE_PLATFORMIO=$(VERBOSE_PLATFORMIO) GIT_RESET_HARD=$(GIT_RESET_HARD) ONLY_TEST="$(ONLY_TEST)" tests-all-local: + @python -c "import yaml" 2>/dev/null || (echo 'pyyaml module is not installed. Install it with "python -m pip install pyyaml"' && exit 1) export PATH="./buildroot/bin/:./buildroot/tests/:${PATH}" \ && export VERBOSE_PLATFORMIO=$(VERBOSE_PLATFORMIO) \ - && for TEST_TARGET in $$($(SCRIPTS_DIR)/get_test_targets.py) ; do echo "Running tests for $$TEST_TARGET" ; run_tests . $$TEST_TARGET ; done + && for TEST_TARGET in $$(python $(SCRIPTS_DIR)/get_test_targets.py) ; do \ + if [ "$$TEST_TARGET" = "linux_native" ] && [ "$$(uname)" = "Darwin" ]; then \ + echo "Skipping tests for $$TEST_TARGET on macOS" ; \ + continue ; \ + fi ; \ + echo "Running tests for $$TEST_TARGET" ; \ + run_tests . $$TEST_TARGET || exit 1 ; \ + sleep 5; \ + done tests-all-local-docker: @if ! $(CONTAINER_RT_BIN) images -q $(CONTAINER_IMAGE) > /dev/null ; then $(MAKE) setup-local-docker ; fi $(CONTAINER_RT_BIN) run $(CONTAINER_RT_OPTS) $(CONTAINER_IMAGE) make tests-all-local VERBOSE_PLATFORMIO=$(VERBOSE_PLATFORMIO) GIT_RESET_HARD=$(GIT_RESET_HARD) -#unit-test-single-ci: -# export GIT_RESET_HARD=true -# $(MAKE) unit-test-single-local TEST_TARGET=$(TEST_TARGET) +unit-test-single-local: + platformio run -t marlin_$(UNIT_TEST_CONFIG) -e linux_native_test -# TODO: How can we limit tests with ONLY_TEST with platformio? -#unit-test-single-local: -# @if ! test -n "$(TEST_TARGET)" ; then echo "***ERROR*** Set TEST_TARGET= or use make unit-test-all-local" ; return 1; fi -# platformio run -t marlin_$(TEST_TARGET) - -#unit-test-single-local-docker: -# @if ! test -n "$(TEST_TARGET)" ; then echo "***ERROR*** Set TEST_TARGET= or use make unit-test-all-local-docker" ; return 1; fi -# @if ! $(CONTAINER_RT_BIN) images -q $(CONTAINER_IMAGE) > /dev/null ; then $(MAKE) setup-local-docker ; fi -# $(CONTAINER_RT_BIN) run $(CONTAINER_RT_OPTS) $(CONTAINER_IMAGE) make unit-test-single-local TEST_TARGET=$(TEST_TARGET) ONLY_TEST="$(ONLY_TEST)" +unit-test-single-local-docker: + @if ! $(CONTAINER_RT_BIN) images -q $(CONTAINER_IMAGE) > /dev/null ; then $(MAKE) setup-local-docker ; fi + $(CONTAINER_RT_BIN) run $(CONTAINER_RT_OPTS) $(CONTAINER_IMAGE) make unit-test-single-local UNIT_TEST_CONFIG=$(UNIT_TEST_CONFIG) unit-test-all-local: platformio run -t test-marlin -e linux_native_test @@ -85,7 +91,14 @@ setup-local-docker: PINS := $(shell find Marlin/src/pins -mindepth 2 -name '*.h') +.PHONY: $(PINS) format-pins validate-pins + $(PINS): %: - @echo "Formatting $@" && node $(SCRIPTS_DIR)/pinsformat.js $@ + @echo "Formatting $@" + @python $(SCRIPTS_DIR)/pinsformat.py $< $@ format-pins: $(PINS) + +validate-pins: format-pins + @echo "Validating pins files" + @git diff --exit-code || (git status && echo "\nError: Pins files are not formatted correctly. Run \"make format-pins\" to fix.\n" && exit 1) diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index 95e680a6d4..f0066338c1 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -4261,7 +4261,8 @@ /** * Instant freeze / unfreeze functionality - * Potentially useful for emergency stop that allows being resumed. + * Potentially useful for rapid stop that allows being resumed. Halts stepper movement. + * Note this does NOT pause spindles, lasers, fans, heaters or any other auxiliary device. * @section interface */ //#define FREEZE_FEATURE diff --git a/Marlin/Version.h b/Marlin/Version.h index d9ddcdd0b8..2c8425a2cb 100644 --- a/Marlin/Version.h +++ b/Marlin/Version.h @@ -41,7 +41,7 @@ * here we define this default string as the date where the latest release * version was tagged. */ -//#define STRING_DISTRIBUTION_DATE "2024-04-19" +//#define STRING_DISTRIBUTION_DATE "2024-05-10" /** * Defines a generic printer name to be output to the LCD after booting Marlin. diff --git a/Marlin/src/HAL/HC32/HAL.h b/Marlin/src/HAL/HC32/HAL.h index dd02183dd0..2f8da95580 100644 --- a/Marlin/src/HAL/HC32/HAL.h +++ b/Marlin/src/HAL/HC32/HAL.h @@ -148,6 +148,25 @@ #define GET_PIN_MAP_INDEX(pin) pin #define PARSED_PIN_INDEX(code, dval) parser.intval(code, dval) +// +// Debug port disable +// JTMS / SWDIO = PA13 +// JTCK / SWCLK = PA14 +// JTDI = PA15 +// JTDO = PB3 +// NJTRST = PB4 +// +#define DBG_SWCLK _BV(0) +#define DBG_SWDIO _BV(1) +#define DBG_TDO _BV(2) +#define DBG_TDI _BV(3) +#define DBG_TRST _BV(4) +#define DBG_ALL (DBG_SWCLK | DBG_SWDIO | DBG_TDO | DBG_TDI | DBG_TRST) + +#define JTAGSWD_RESET() PORT_DebugPortSetting(DBG_ALL, Enable); +#define JTAG_DISABLE() PORT_DebugPortSetting(DBG_TDO | DBG_TDI | DBG_TRST, Disable); +#define JTAGSWD_DISABLE() PORT_DebugPortSetting(DBG_ALL, Disable); + // // MarlinHAL implementation // diff --git a/Marlin/src/HAL/HC32/MarlinSerial.h b/Marlin/src/HAL/HC32/MarlinSerial.h index b63b069b9d..bb4630eb1d 100644 --- a/Marlin/src/HAL/HC32/MarlinSerial.h +++ b/Marlin/src/HAL/HC32/MarlinSerial.h @@ -31,8 +31,8 @@ struct MarlinSerial : public Usart { MarlinSerial( - struct usart_config_t *usart_device, - gpio_pin_t tx_pin, + struct usart_config_t *usart_device, + gpio_pin_t tx_pin, gpio_pin_t rx_pin #if ENABLED(SERIAL_DMA) , M4_DMA_TypeDef *dma_unit = nullptr, diff --git a/Marlin/src/HAL/HC32/app_config.h b/Marlin/src/HAL/HC32/app_config.h index bc9d14b4c6..69d7f60646 100644 --- a/Marlin/src/HAL/HC32/app_config.h +++ b/Marlin/src/HAL/HC32/app_config.h @@ -1,6 +1,6 @@ /** * app_config.h is included by the hc32f460 arduino build script for every source file. - * it is used to configure the arduino core (and ddl) automatically according + * it is used to configure the arduino core (and ddl) automatically according * to the settings in Configuration.h and Configuration_adv.h. */ #pragma once @@ -44,7 +44,7 @@ #define DISABLE_SERIAL_GLOBALS 1 // increase the size of the Usart buffers (both RX and TX) -// NOTE: +// NOTE: // the heap usage will increase by (SERIAL_BUFFER_SIZE - 64) * "number of serial ports used" // if running out of heap, the system may become unstable //#define SERIAL_BUFFER_SIZE 256 diff --git a/Marlin/src/HAL/HC32/inc/SanityCheck.h b/Marlin/src/HAL/HC32/inc/SanityCheck.h index 0d05448f98..6b12e4d047 100644 --- a/Marlin/src/HAL/HC32/inc/SanityCheck.h +++ b/Marlin/src/HAL/HC32/inc/SanityCheck.h @@ -30,7 +30,7 @@ #endif #if ARDUINO_CORE_VERSION_INT < GET_VERSION_INT(1, 1, 0) - // because we use app_config.h introduced in arduino core version 1.1.0, the + // because we use app_config.h introduced in arduino core version 1.1.0, the // HAL is not compatible with older versions #error "The HC32 HAL is not compatible with Arduino Core versions < 1.1.0. Consider updating the Arduino Core." #endif diff --git a/Marlin/src/MarlinCore.cpp b/Marlin/src/MarlinCore.cpp index 97e7c32bf6..2dba3944e5 100644 --- a/Marlin/src/MarlinCore.cpp +++ b/Marlin/src/MarlinCore.cpp @@ -266,7 +266,7 @@ PGMSTR(M112_KILL_STR, "M112 Shutdown"); MarlinState marlin_state = MF_INITIALIZING; // For M109 and M190, this flag may be cleared (by M108) to exit the wait loop -bool wait_for_heatup = true; +bool wait_for_heatup = false; // For M0/M1, this flag may be cleared (by M108) to exit the wait-for-user loop #if HAS_RESUME_CONTINUE diff --git a/Marlin/src/core/boards.h b/Marlin/src/core/boards.h index cef30c5cd2..ef2a5f1fa9 100644 --- a/Marlin/src/core/boards.h +++ b/Marlin/src/core/boards.h @@ -383,9 +383,9 @@ #define BOARD_CREALITY_V452 5050 // Creality v4.5.2 (STM32F103RC / STM32F103RE) #define BOARD_CREALITY_V453 5051 // Creality v4.5.3 (STM32F103RC / STM32F103RE) #define BOARD_CREALITY_V521 5052 // Creality v5.2.1 (STM32F103VE) as found in the SV04 -#define BOARD_CREALITY_V24S1 5053 // Creality v2.4.S1 (STM32F103RC / STM32F103RE) v101 as found in the Ender-7 -#define BOARD_CREALITY_V24S1_301 5054 // Creality v2.4.S1_301 (STM32F103RC / STM32F103RE) v301 as found in the Ender-3 S1 -#define BOARD_CREALITY_V25S1 5055 // Creality v2.5.S1 (STM32F103RE) as found in the CR-10 Smart Pro +#define BOARD_CREALITY_V24S1 5053 // Creality v2.4.S1 (STM32F103RC / STM32F103RE) CR-FDM-v2.4.S1_v101 as found in the Ender-7 +#define BOARD_CREALITY_V24S1_301 5054 // Creality v2.4.S1_301 (STM32F103RC / STM32F103RE) CR-FDM-v24S1_301 as found in the Ender-3 S1 +#define BOARD_CREALITY_V25S1 5055 // Creality v2.5.S1 (STM32F103RE) CR-FDM-v2.5.S1_100 as found in the CR-10 Smart Pro #define BOARD_TRIGORILLA_PRO 5056 // Trigorilla Pro (STM32F103ZE) #define BOARD_FLY_MINI 5057 // FLYmaker FLY MINI (STM32F103RC) #define BOARD_FLSUN_HISPEED 5058 // FLSUN HiSpeedV1 (STM32F103VE) diff --git a/Marlin/src/core/mstring.h b/Marlin/src/core/mstring.h index 31e8c8c6e6..b405262d30 100644 --- a/Marlin/src/core/mstring.h +++ b/Marlin/src/core/mstring.h @@ -143,13 +143,13 @@ public: // Set with format string and arguments, like printf template - MString& setf_P(PGM_P const fmt, Args... more) { SNPRINTF_P(str, SIZE, fmt, more...); debug(F("setf_P")); return *this; } + MString& setf_P(PGM_P const pfmt, Args... more) { SNPRINTF_P(str, SIZE, pfmt, more...); debug(F("setf_P")); return *this; } template - MString& setf(const char *fmt, Args... more) { SNPRINTF(str, SIZE, fmt, more...); debug(F("setf")); return *this; } + MString& setf(const char *fmt, Args... more) { SNPRINTF(str, SIZE, fmt, more...); debug(F("setf")); return *this; } template - MString& setf(FSTR_P const fmt, Args... more) { return setf_P(FTOP(fmt), more...); } + MString& setf(FSTR_P const ffmt, Args... more) { return setf_P(FTOP(ffmt), more...); } // Chainable String appenders MString& append() { debug(F("nil")); return *this; } // for macros that might emit no output @@ -206,9 +206,9 @@ public: MString& append(const spaces_t &s) { return append(repchr_t(' ', s.count)); } template - MString& appendf_P(PGM_P const fmt, Args... more) { + MString& appendf_P(PGM_P const pfmt, Args... more) { int sz = length(); - if (sz < SIZE) SNPRINTF_P(str + sz, SIZE - sz, fmt, more...); + if (sz < SIZE) SNPRINTF_P(str + sz, SIZE - sz, pfmt, more...); debug(F("appendf_P")); return *this; } diff --git a/Marlin/src/core/serial.h b/Marlin/src/core/serial.h index f9b73e6d26..db8d06a297 100644 --- a/Marlin/src/core/serial.h +++ b/Marlin/src/core/serial.h @@ -271,13 +271,13 @@ public: SString& set() { super::set(); return *this; } template - SString& setf_P(PGM_P const fmt, Args... more) { super::setf_P(fmt, more...); return *this; } + SString& setf_P(PGM_P const pfmt, Args... more) { super::setf_P(pfmt, more...); return *this; } template - SString& setf(const char *fmt, Args... more) { super::setf(fmt, more...); return *this; } + SString& setf(const char *fmt, Args... more) { super::setf(fmt, more...); return *this; } template - SString& setf(FSTR_P const fmt, Args... more) { super::setf(fmt, more...); return *this; } + SString& setf(FSTR_P const ffmt, Args... more) { super::setf(ffmt, more...); return *this; } template SString& set(const T &v) { super::set(v); return *this; } diff --git a/Marlin/src/core/types.h b/Marlin/src/core/types.h index 44805e130a..bbb152174f 100644 --- a/Marlin/src/core/types.h +++ b/Marlin/src/core/types.h @@ -46,6 +46,7 @@ template struct IF { typedef L type; }; #define NUM_AXIS_ELEM(O) NUM_AXIS_LIST(O.x, O.y, O.z, O.i, O.j, O.k, O.u, O.v, O.w) #define NUM_AXIS_DECL(T,V) NUM_AXIS_LIST(T x=V, T y=V, T z=V, T i=V, T j=V, T k=V, T u=V, T v=V, T w=V) #define MAIN_AXIS_NAMES NUM_AXIS_LIST(X, Y, Z, I, J, K, U, V, W) +#define MAIN_AXIS_NAMES_LC NUM_AXIS_LIST(x, y, z, i, j, k, u, v, w) #define STR_AXES_MAIN NUM_AXIS_GANG("X", "Y", "Z", STR_I, STR_J, STR_K, STR_U, STR_V, STR_W) #define LOGICAL_AXIS_GANG(E,V...) NUM_AXIS_GANG(V) GANG_ITEM_E(E) @@ -58,17 +59,21 @@ template struct IF { typedef L type; }; #define LOGICAL_AXIS_ELEM(O) LOGICAL_AXIS_LIST(O.e, O.x, O.y, O.z, O.i, O.j, O.k, O.u, O.v, O.w) #define LOGICAL_AXIS_DECL(T,V) LOGICAL_AXIS_LIST(T e=V, T x=V, T y=V, T z=V, T i=V, T j=V, T k=V, T u=V, T v=V, T w=V) #define LOGICAL_AXIS_NAMES LOGICAL_AXIS_LIST(E, X, Y, Z, I, J, K, U, V, W) +#define LOGICAL_AXIS_NAMES_LC LOGICAL_AXIS_LIST(e, x, y, z, i, j, k, u, v, w) #define LOGICAL_AXIS_MAP(F) MAP(F, LOGICAL_AXIS_NAMES) +#define LOGICAL_AXIS_MAP_LC(F) MAP(F, LOGICAL_AXIS_NAMES_LC) #define STR_AXES_LOGICAL LOGICAL_AXIS_GANG("E", "X", "Y", "Z", STR_I, STR_J, STR_K, STR_U, STR_V, STR_W) #if NUM_AXES #define NUM_AXES_SEP , #define MAIN_AXIS_MAP(F) MAP(F, MAIN_AXIS_NAMES) + #define MAIN_AXIS_MAP_LC(F) MAP(F, MAIN_AXIS_NAMES_LC) #define OPTARGS_NUM(T) , NUM_AXIS_ARGS(T) #define OPTARGS_LOGICAL(T) , LOGICAL_AXIS_ARGS(T) #else #define NUM_AXES_SEP #define MAIN_AXIS_MAP(F) + #define MAIN_AXIS_MAP_LC(F) #define OPTARGS_NUM(T) #define OPTARGS_LOGICAL(T) #endif @@ -79,6 +84,7 @@ template struct IF { typedef L type; }; #define NUM_AXIS_ARGS_(T) NUM_AXIS_ARGS(T) NUM_AXES_SEP #define NUM_AXIS_ELEM_(T) NUM_AXIS_ELEM(T) NUM_AXES_SEP #define MAIN_AXIS_NAMES_ MAIN_AXIS_NAMES NUM_AXES_SEP +#define MAIN_AXIS_NAMES_LC_ MAIN_AXIS_NAMES_LC NUM_AXES_SEP #if LOGICAL_AXES #define LOGICAL_AXES_SEP , @@ -92,6 +98,7 @@ template struct IF { typedef L type; }; #define LOGICAL_AXIS_ARGS_(T) LOGICAL_AXIS_ARGS(T) LOGICAL_AXES_SEP #define LOGICAL_AXIS_ELEM_(T) LOGICAL_AXIS_ELEM(T) LOGICAL_AXES_SEP #define LOGICAL_AXIS_NAMES_ LOGICAL_AXIS_NAMES LOGICAL_AXES_SEP +#define LOGICAL_AXIS_NAMES_LC_ LOGICAL_AXIS_NAMES_LC LOGICAL_AXES_SEP #define SECONDARY_AXIS_GANG(V...) GANG_N(SECONDARY_AXES, V) #define SECONDARY_AXIS_CODE(V...) CODE_N(SECONDARY_AXES, V) @@ -159,7 +166,7 @@ template struct IF { typedef L type; }; // General Flags for some number of states template struct Flags { - typedef uvalue_t(N) flagbits_t; + typedef bits_t(N) flagbits_t; typedef struct { bool b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1; } N8; typedef struct { bool b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1, b8:1, b9:1, b10:1, b11:1, b12:1, b13:1, b14:1, b15:1; } N16; typedef struct { bool b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1, b8:1, b9:1, b10:1, b11:1, b12:1, b13:1, b14:1, b15:1, @@ -219,7 +226,7 @@ typedef struct { // // - X_AXIS, Y_AXIS, and Z_AXIS should be used for axes in Cartesian space // - A_AXIS, B_AXIS, and C_AXIS should be used for Steppers, corresponding to XYZ on Cartesians -// - X_HEAD, Y_HEAD, and Z_HEAD should be used for Steppers on Core kinematics +// - X_HEAD, Y_HEAD, and Z_HEAD should be used for axes on Core kinematics // enum AxisEnum : uint8_t { @@ -1084,6 +1091,7 @@ public: FI bool toggle(const AxisEnum n) { TBI(bits, n); return TEST(bits, n); } FI void bset(const AxisEnum n) { SBI(bits, n); } FI void bclr(const AxisEnum n) { CBI(bits, n); } + FI void bset(const AxisEnum n, const bool b) { if (b) bset(n); else bclr(n); } // Accessor via an AxisEnum (or any integer) [index] FI bool operator[](const int n) const { return TEST(bits, n); } diff --git a/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp b/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp index fcf408b34e..4637bf87e8 100644 --- a/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp +++ b/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp @@ -765,7 +765,7 @@ void unified_bed_leveling::shift_mesh_height() { const grid_count_t point_num = (GRID_MAX_POINTS - count) + 1; SERIAL_ECHOLNPGM("Probing mesh point ", point_num, "/", GRID_MAX_POINTS, "."); - TERN_(HAS_STATUS_MESSAGE, ui.status_printf(0, F(S_FMT " %i/%i"), GET_TEXT(MSG_PROBING_POINT), point_num, int(GRID_MAX_POINTS))); + TERN_(HAS_STATUS_MESSAGE, ui.status_printf(0, F(S_FMT " %i/%i"), GET_TEXT_F(MSG_PROBING_POINT), point_num, int(GRID_MAX_POINTS))); TERN_(HAS_BACKLIGHT_TIMEOUT, ui.refresh_backlight_timeout()); #if HAS_MARLINUI_MENU @@ -1494,7 +1494,7 @@ void unified_bed_leveling::smart_fill_mesh() { for (uint8_t i = 0; i < 3; ++i) { SERIAL_ECHOLNPGM("Tilting mesh (", i + 1, "/3)"); - TERN_(HAS_STATUS_MESSAGE, ui.status_printf(0, F(S_FMT " %i/3"), GET_TEXT(MSG_LCD_TILTING_MESH), i + 1)); + TERN_(HAS_STATUS_MESSAGE, ui.status_printf(0, F(S_FMT " %i/3"), GET_TEXT_F(MSG_LCD_TILTING_MESH), i + 1)); measured_z = probe.probe_at_point(points[i], i < 2 ? PROBE_PT_RAISE : PROBE_PT_LAST_STOW, param.V_verbosity); if ((abort_flag = isnan(measured_z))) break; @@ -1550,7 +1550,7 @@ void unified_bed_leveling::smart_fill_mesh() { #endif SERIAL_ECHOLNPGM("Tilting mesh point ", point_num, "/", total_points, "\n"); - TERN_(HAS_STATUS_MESSAGE, ui.status_printf(0, F(S_FMT " %i/%i"), GET_TEXT(MSG_LCD_TILTING_MESH), point_num, total_points)); + TERN_(HAS_STATUS_MESSAGE, ui.status_printf(0, F(S_FMT " %i/%i"), GET_TEXT_F(MSG_LCD_TILTING_MESH), point_num, total_points)); measured_z = probe.probe_at_point(rpos, parser.seen_test('E') ? PROBE_PT_STOW : PROBE_PT_RAISE, param.V_verbosity); // TODO: Needs error handling diff --git a/Marlin/src/feature/stepper_driver_safety.cpp b/Marlin/src/feature/stepper_driver_safety.cpp index acdd695909..3ddc05ea1e 100644 --- a/Marlin/src/feature/stepper_driver_safety.cpp +++ b/Marlin/src/feature/stepper_driver_safety.cpp @@ -31,7 +31,7 @@ static uint32_t axis_plug_backward = 0; void stepper_driver_backward_error(FSTR_P const fstr) { SERIAL_ERROR_START(); SERIAL_ECHOLN(fstr, F(" driver is backward!")); - ui.status_printf(2, F(S_FMT S_FMT), FTOP(fstr), GET_TEXT(MSG_DRIVER_BACKWARD)); + ui.status_printf(2, F(S_FMT S_FMT), FTOP(fstr), GET_TEXT_F(MSG_DRIVER_BACKWARD)); } void stepper_driver_backward_check() { diff --git a/Marlin/src/gcode/bedlevel/abl/G29.cpp b/Marlin/src/gcode/bedlevel/abl/G29.cpp index 449c25fefd..d97fc48906 100644 --- a/Marlin/src/gcode/bedlevel/abl/G29.cpp +++ b/Marlin/src/gcode/bedlevel/abl/G29.cpp @@ -683,7 +683,7 @@ G29_TYPE GcodeSuite::G29() { if (TERN0(IS_KINEMATIC, !probe.can_reach(abl.probePos))) continue; if (abl.verbose_level) SERIAL_ECHOLNPGM("Probing mesh point ", pt_index, "/", abl.abl_points, "."); - TERN_(HAS_STATUS_MESSAGE, ui.status_printf(0, F(S_FMT " %i/%i"), GET_TEXT(MSG_PROBING_POINT), int(pt_index), int(abl.abl_points))); + TERN_(HAS_STATUS_MESSAGE, ui.status_printf(0, F(S_FMT " %i/%i"), GET_TEXT_F(MSG_PROBING_POINT), int(pt_index), int(abl.abl_points))); #if ENABLED(BD_SENSOR_PROBE_NO_STOP) if (PR_INNER_VAR == inStart) { @@ -782,7 +782,7 @@ G29_TYPE GcodeSuite::G29() { for (uint8_t i = 0; i < 3; ++i) { if (abl.verbose_level) SERIAL_ECHOLNPGM("Probing point ", i + 1, "/3."); - TERN_(HAS_STATUS_MESSAGE, ui.status_printf(0, F(S_FMT " %i/3"), GET_TEXT(MSG_PROBING_POINT), int(i + 1))); + TERN_(HAS_STATUS_MESSAGE, ui.status_printf(0, F(S_FMT " %i/3"), GET_TEXT_F(MSG_PROBING_POINT), int(i + 1))); // Retain the last probe position abl.probePos = xy_pos_t(points[i]); diff --git a/Marlin/src/gcode/bedlevel/mbl/G29.cpp b/Marlin/src/gcode/bedlevel/mbl/G29.cpp index c9c04b4f0c..6d23de4f77 100644 --- a/Marlin/src/gcode/bedlevel/mbl/G29.cpp +++ b/Marlin/src/gcode/bedlevel/mbl/G29.cpp @@ -253,7 +253,7 @@ void GcodeSuite::G29() { if (state == MeshNext) { SERIAL_ECHOLNPGM("MBL G29 point ", _MIN(mbl_probe_index, GRID_MAX_POINTS), " of ", GRID_MAX_POINTS); - if (mbl_probe_index > 0) TERN_(HAS_STATUS_MESSAGE, ui.status_printf(0, F(S_FMT " %i/%i"), GET_TEXT(MSG_PROBING_POINT), _MIN(mbl_probe_index, GRID_MAX_POINTS), int(GRID_MAX_POINTS))); + if (mbl_probe_index > 0) TERN_(HAS_STATUS_MESSAGE, ui.status_printf(0, F(S_FMT " %i/%i"), GET_TEXT_F(MSG_PROBING_POINT), _MIN(mbl_probe_index, GRID_MAX_POINTS), int(GRID_MAX_POINTS))); } report_current_position(); diff --git a/Marlin/src/gcode/calibrate/M48.cpp b/Marlin/src/gcode/calibrate/M48.cpp index 8dd951e054..910395e561 100644 --- a/Marlin/src/gcode/calibrate/M48.cpp +++ b/Marlin/src/gcode/calibrate/M48.cpp @@ -149,7 +149,7 @@ void GcodeSuite::M48() { for (uint8_t n = 0; n < n_samples; ++n) { #if HAS_STATUS_MESSAGE // Display M48 progress in the status bar - ui.status_printf(0, F(S_FMT ": %d/%d"), GET_TEXT(MSG_M48_POINT), int(n + 1), int(n_samples)); + ui.status_printf(0, F(S_FMT ": %d/%d"), GET_TEXT_F(MSG_M48_POINT), int(n + 1), int(n_samples)); #endif // When there are "legs" of movement move around the point before probing diff --git a/Marlin/src/inc/Conditionals_LCD.h b/Marlin/src/inc/Conditionals_LCD.h index a3756217e6..efda2d493e 100644 --- a/Marlin/src/inc/Conditionals_LCD.h +++ b/Marlin/src/inc/Conditionals_LCD.h @@ -893,10 +893,11 @@ #endif #endif -// FSMC/SPI TFT Panels (LVGL) +// FSMC/SPI TFT Panels (LVGL) with encoder click wheel #if ENABLED(TFT_LVGL_UI) #define HAS_TFT_LVGL_UI 1 #define SERIAL_RUNTIME_HOOK 1 + #define STD_ENCODER_PULSES_PER_STEP 4 #endif // FSMC/SPI TFT Panels @@ -976,6 +977,17 @@ #define DETECT_I2C_LCD_DEVICE 1 #endif +/** + * Ender-3 V2 DWIN with Encoder + */ +#if ANY(DWIN_CREALITY_LCD, DWIN_LCD_PROUI) + #define HAS_DWIN_E3V2_BASIC 1 +#endif +#if ANY(HAS_DWIN_E3V2_BASIC, DWIN_CREALITY_LCD_JYERSUI) + #define HAS_DWIN_E3V2 1 + #define STD_ENCODER_PULSES_PER_STEP 4 +#endif + // Encoder behavior #ifndef STD_ENCODER_PULSES_PER_STEP #if ENABLED(TOUCH_SCREEN) @@ -997,10 +1009,12 @@ #define ENCODER_FEEDRATE_DEADZONE 6 #endif -// Shift register panels -// --------------------- -// 2 wire Non-latching LCD SR from: -// https://github.com/fmalpartida/New-LiquidCrystal/wiki/schematics#user-content-ShiftRegister_connection +/** + * Shift register panels + * --------------------- + * 2 wire Non-latching LCD SR from: + * https://github.com/fmalpartida/New-LiquidCrystal/wiki/schematics#user-content-ShiftRegister_connection + */ #if ENABLED(FF_INTERFACEBOARD) #define SR_LCD_3W_NL // Non latching 3 wire shift register #define IS_ULTIPANEL 1 @@ -1040,11 +1054,6 @@ #define EXTENSIBLE_UI #endif -// Aliases for LCD features -#if ANY(DWIN_CREALITY_LCD, DWIN_LCD_PROUI, DWIN_CREALITY_LCD_JYERSUI) - #define HAS_DWIN_E3V2 1 -#endif - // E3V2 extras #if HAS_DWIN_E3V2 || IS_DWIN_MARLINUI #define SERIAL_CATCHALL 0 @@ -1594,8 +1603,6 @@ #endif #if CORE_IS_XY || CORE_IS_XZ || CORE_IS_YZ #define IS_CORE 1 -#endif -#if IS_CORE #if CORE_IS_XY #define CORE_AXIS_1 A_AXIS #define CORE_AXIS_2 B_AXIS diff --git a/Marlin/src/inc/Conditionals_adv.h b/Marlin/src/inc/Conditionals_adv.h index 78da97f67b..de3d8d2b24 100644 --- a/Marlin/src/inc/Conditionals_adv.h +++ b/Marlin/src/inc/Conditionals_adv.h @@ -1185,7 +1185,7 @@ #elif HAS_DRIVER(A4988) #define MINIMUM_STEPPER_POST_DIR_DELAY 200 #elif HAS_TRINAMIC_CONFIG || HAS_TRINAMIC_STANDALONE - #define MINIMUM_STEPPER_POST_DIR_DELAY 70 + #define MINIMUM_STEPPER_POST_DIR_DELAY 100 #else #define MINIMUM_STEPPER_POST_DIR_DELAY 0 // Expect at least 10µS since one Stepper ISR must transpire #endif diff --git a/Marlin/src/inc/Version.h b/Marlin/src/inc/Version.h index 4a15d226ad..afab2f695f 100644 --- a/Marlin/src/inc/Version.h +++ b/Marlin/src/inc/Version.h @@ -42,7 +42,7 @@ * version was tagged. */ #ifndef STRING_DISTRIBUTION_DATE - #define STRING_DISTRIBUTION_DATE "2024-04-19" + #define STRING_DISTRIBUTION_DATE "2024-05-10" #endif /** diff --git a/Marlin/src/inc/Warnings.cpp b/Marlin/src/inc/Warnings.cpp index 2c2a824978..3f60964e59 100644 --- a/Marlin/src/inc/Warnings.cpp +++ b/Marlin/src/inc/Warnings.cpp @@ -99,8 +99,8 @@ #warning "Warning! Don't use dummy thermistors (998/999) for final build!" #endif -#if NONE(HAS_RESUME_CONTINUE, HOST_PROMPT_SUPPORT, UNIT_TEST) - #warning "Your Configuration provides no method to acquire user feedback!" +#if NONE(HAS_RESUME_CONTINUE, HOST_PROMPT_SUPPORT, UNIT_TEST, NO_USER_FEEDBACK_WARNING) + #warning "Your Configuration provides no method to acquire user feedback! (Define NO_USER_FEEDBACK_WARNING to suppress this warning.)" #endif #if MB(DUE3DOM_MINI) && PIN_EXISTS(TEMP_2) && !TEMP_SENSOR_BOARD @@ -690,8 +690,12 @@ #warning "To prevent step loss, motion will pause for PRINTCOUNTER auto-save." #endif -#if HOMING_Z_WITH_PROBE && IS_CARTESIAN && DISABLED(Z_SAFE_HOMING) - #error "Z_SAFE_HOMING is recommended when homing with a probe. Enable Z_SAFE_HOMING or comment out this line to continue." +#if HOMING_Z_WITH_PROBE && IS_CARTESIAN && NONE(Z_SAFE_HOMING, NO_Z_SAFE_HOMING_WARNING) + #error "Z_SAFE_HOMING is recommended when homing with a probe. (Enable Z_SAFE_HOMING or define NO_Z_SAFE_HOMING_WARNING to suppress this warning.)" +#endif + +#if ENABLED(BIQU_MICROPROBE_V2) && NONE(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN, NO_MICROPROBE_WARNING) + #warning "BIQU MicroProbe V2 detect signal requires a strong pull-up. Some processors have weak internal pull-up capabilities, so we recommended connecting MicroProbe SIGNAL / GND to Z-MIN / Z-STOP instead of the dedicated PROBE port. (Define NO_MICROPROBE_WARNING to suppress this warning.)" #endif // @@ -714,8 +718,8 @@ #warning "Disabled CONFIGURATION_EMBEDDING because the target usually has less flash storage. Define FORCE_CONFIG_EMBED to override." #endif -#if HAS_LCD_CONTRAST && LCD_CONTRAST_MIN >= LCD_CONTRAST_MAX - #warning "Contrast cannot be changed when LCD_CONTRAST_MIN >= LCD_CONTRAST_MAX." +#if HAS_LCD_CONTRAST && LCD_CONTRAST_MIN >= LCD_CONTRAST_MAX && DISABLED(NO_LCD_CONTRAST_WARNING) + #warning "Contrast cannot be changed when LCD_CONTRAST_MIN >= LCD_CONTRAST_MAX. (Define NO_LCD_CONTRAST_WARNING to suppress this warning.)" #endif #if PROGRESS_MSG_EXPIRE > 0 && HAS_STATUS_MESSAGE_TIMEOUT diff --git a/Marlin/src/lcd/buttons.h b/Marlin/src/lcd/buttons.h index 601e8a70ae..2bd5fd7b35 100644 --- a/Marlin/src/lcd/buttons.h +++ b/Marlin/src/lcd/buttons.h @@ -24,9 +24,9 @@ #include "../inc/MarlinConfig.h" #if ((!HAS_ADC_BUTTONS && IS_NEWPANEL) || BUTTONS_EXIST(EN1, EN2)) && !IS_TFTGLCD_PANEL - #define HAS_ENCODER_WHEEL 1 + #define HAS_MARLINUI_ENCODER 1 #endif -#if (HAS_ENCODER_WHEEL || ANY_BUTTON(ENC, BACK, UP, DOWN, LEFT, RIGHT)) && DISABLED(TOUCH_UI_FTDI_EVE) +#if (HAS_MARLINUI_ENCODER || ANY_BUTTON(ENC, BACK, UP, DOWN, LEFT, RIGHT)) && DISABLED(TOUCH_UI_FTDI_EVE) #define HAS_DIGITAL_BUTTONS 1 #endif #if !HAS_ADC_BUTTONS && (IS_RRW_KEYPAD || (HAS_WIRED_LCD && !IS_NEWPANEL)) diff --git a/Marlin/src/lcd/dogm/marlinui_DOGM.cpp b/Marlin/src/lcd/dogm/marlinui_DOGM.cpp index 06a234d04d..1bc55630af 100644 --- a/Marlin/src/lcd/dogm/marlinui_DOGM.cpp +++ b/Marlin/src/lcd/dogm/marlinui_DOGM.cpp @@ -377,10 +377,10 @@ void MarlinUI::draw_kill_screen() { void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop #if HAS_DISPLAY_SLEEP - void MarlinUI::sleep_display(const bool sleep/*=true*/) { + void MarlinUI::sleep_display(const bool sleep/*=true*/) { static bool asleep = false; if (asleep != sleep){ - sleep ? u8g.sleepOn() : u8g.sleepOff(); + sleep ? u8g.sleepOn() : u8g.sleepOff(); asleep = sleep; } } diff --git a/Marlin/src/lcd/e3v2/common/encoder.cpp b/Marlin/src/lcd/e3v2/common/encoder.cpp index 5825fb0f77..889d1c61f3 100644 --- a/Marlin/src/lcd/e3v2/common/encoder.cpp +++ b/Marlin/src/lcd/e3v2/common/encoder.cpp @@ -42,10 +42,6 @@ #include -#ifndef ENCODER_PULSES_PER_STEP - #define ENCODER_PULSES_PER_STEP 4 -#endif - EncoderRate encoderRate; // TODO: Replace with ui.quick_feedback @@ -53,32 +49,12 @@ void Encoder_tick() { TERN_(HAS_BEEPER, if (ui.sound_on) buzzer.click(10)); } -// Encoder initialization -void encoderConfiguration() { - #if BUTTON_EXISTS(EN1) - SET_INPUT_PULLUP(BTN_EN1); - #endif - #if BUTTON_EXISTS(EN2) - SET_INPUT_PULLUP(BTN_EN2); - #endif - #if BUTTON_EXISTS(ENC) - SET_INPUT_PULLUP(BTN_ENC); - #endif - #if HAS_BEEPER - SET_OUTPUT(BEEPER_PIN); // TODO: Use buzzer.h which already inits this - #endif -} - // Analyze encoder value and return state EncoderState encoderReceiveAnalyze() { const millis_t now = millis(); - static uint8_t lastEncoderBits; - uint8_t newbutton = 0; - static signed char temp_diff = 0; + static int8_t temp_diff = 0; // Cleared on each full step, as configured EncoderState temp_diffState = ENCODER_DIFF_NO; - if (BUTTON_PRESSED(EN1)) newbutton |= EN_A; - if (BUTTON_PRESSED(EN2)) newbutton |= EN_B; if (BUTTON_PRESSED(ENC)) { static millis_t next_click_update_ms; if (ELAPSED(now, next_click_update_ms)) { @@ -98,71 +74,47 @@ EncoderState encoderReceiveAnalyze() { } else return ENCODER_DIFF_NO; } - if (newbutton != lastEncoderBits) { - switch (newbutton) { - case 0: - if (lastEncoderBits == 1) temp_diff++; - else if (lastEncoderBits == 2) temp_diff--; - break; - case 2: - if (lastEncoderBits == 0) temp_diff++; - else if (lastEncoderBits == 3) temp_diff--; - break; - case 3: - if (lastEncoderBits == 2) temp_diff++; - else if (lastEncoderBits == 1) temp_diff--; - break; - case 1: - if (lastEncoderBits == 3) temp_diff++; - else if (lastEncoderBits == 0) temp_diff--; - break; - } - lastEncoderBits = newbutton; - } - if (ABS(temp_diff) >= ENCODER_PULSES_PER_STEP) { - if (temp_diff > 0) temp_diffState = TERN(REVERSE_ENCODER_DIRECTION, ENCODER_DIFF_CCW, ENCODER_DIFF_CW); - else temp_diffState = TERN(REVERSE_ENCODER_DIRECTION, ENCODER_DIFF_CW, ENCODER_DIFF_CCW); + temp_diff += ui.get_encoder_delta(); + + const int8_t abs_diff = ABS(temp_diff); + if (abs_diff >= ENCODER_PULSES_PER_STEP) { + temp_diffState = temp_diff > 0 + ? TERN(REVERSE_ENCODER_DIRECTION, ENCODER_DIFF_CCW, ENCODER_DIFF_CW) + : TERN(REVERSE_ENCODER_DIRECTION, ENCODER_DIFF_CW, ENCODER_DIFF_CCW); + + int32_t encoder_multiplier = 1; #if ENABLED(ENCODER_RATE_MULTIPLIER) - millis_t ms = millis(); - int32_t encoder_multiplier = 1; + const millis_t ms = millis(); - // if must encoder rati multiplier + // Encoder rate multiplier if (encoderRate.enabled) { - const float abs_diff = ABS(temp_diff), - encoderMovementSteps = abs_diff / (ENCODER_PULSES_PER_STEP); - if (encoderRate.lastEncoderTime) { - // Note that the rate is always calculated between two passes through the - // loop and that the abs of the temp_diff value is tracked. - const float encoderStepRate = encoderMovementSteps / float(ms - encoderRate.lastEncoderTime) * 1000; - if (ENCODER_100X_STEPS_PER_SEC > 0 && encoderStepRate >= ENCODER_100X_STEPS_PER_SEC) - encoder_multiplier = 100; - else if (ENCODER_10X_STEPS_PER_SEC > 0 && encoderStepRate >= ENCODER_10X_STEPS_PER_SEC) - encoder_multiplier = 10; - else if (ENCODER_5X_STEPS_PER_SEC > 0 && encoderStepRate >= ENCODER_5X_STEPS_PER_SEC) - encoder_multiplier = 5; - } + // Note that the rate is always calculated between two passes through the + // loop and that the abs of the temp_diff value is tracked. + const float encoderStepRate = ((float(abs_diff) / float(ENCODER_PULSES_PER_STEP)) * 1000.0f) / float(ms - encoderRate.lastEncoderTime); encoderRate.lastEncoderTime = ms; + if (ENCODER_100X_STEPS_PER_SEC > 0 && encoderStepRate >= ENCODER_100X_STEPS_PER_SEC) + encoder_multiplier = 100; + else if (ENCODER_10X_STEPS_PER_SEC > 0 && encoderStepRate >= ENCODER_10X_STEPS_PER_SEC) + encoder_multiplier = 10; + else if (ENCODER_5X_STEPS_PER_SEC > 0 && encoderStepRate >= ENCODER_5X_STEPS_PER_SEC) + encoder_multiplier = 5; } - #else - - constexpr int32_t encoder_multiplier = 1; - #endif - // encoderRate.encoderMoveValue += (temp_diff * encoder_multiplier) / (ENCODER_PULSES_PER_STEP); - encoderRate.encoderMoveValue = (temp_diff * encoder_multiplier) / (ENCODER_PULSES_PER_STEP); - if (encoderRate.encoderMoveValue < 0) encoderRate.encoderMoveValue = -encoderRate.encoderMoveValue; + encoderRate.encoderMoveValue = abs_diff * encoder_multiplier / (ENCODER_PULSES_PER_STEP); temp_diff = 0; } + if (temp_diffState != ENCODER_DIFF_NO) { TERN_(HAS_BACKLIGHT_TIMEOUT, ui.refresh_backlight_timeout()); if (!ui.backlight) ui.refresh_brightness(); } + return temp_diffState; } diff --git a/Marlin/src/lcd/e3v2/common/encoder.h b/Marlin/src/lcd/e3v2/common/encoder.h index ce431c9811..428193ca65 100644 --- a/Marlin/src/lcd/e3v2/common/encoder.h +++ b/Marlin/src/lcd/e3v2/common/encoder.h @@ -47,9 +47,6 @@ typedef enum { #define ENCODER_WAIT_MS TERN(DWIN_LCD_PROUI, 10, 20) -// Encoder initialization -void encoderConfiguration(); - // Analyze encoder value and return state EncoderState encoderReceiveAnalyze(); diff --git a/Marlin/src/lcd/e3v2/creality/dwin.cpp b/Marlin/src/lcd/e3v2/creality/dwin.cpp index 9ecfbfe1fa..7f057137d8 100644 --- a/Marlin/src/lcd/e3v2/creality/dwin.cpp +++ b/Marlin/src/lcd/e3v2/creality/dwin.cpp @@ -4078,7 +4078,6 @@ void hmiInit() { } void dwinInitScreen() { - encoderConfiguration(); hmiInit(); hmiSetLanguageCache(); hmiStartFrame(true); diff --git a/Marlin/src/lcd/e3v2/jyersui/dwin.cpp b/Marlin/src/lcd/e3v2/jyersui/dwin.cpp index a29f5fc42f..c9191dd31d 100644 --- a/Marlin/src/lcd/e3v2/jyersui/dwin.cpp +++ b/Marlin/src/lcd/e3v2/jyersui/dwin.cpp @@ -5143,7 +5143,6 @@ void MarlinUI::init_lcd() { if (dwinHandshake()) SERIAL_ECHOLNPGM("ok."); else SERIAL_ECHOLNPGM("error."); dwinFrameSetDir(1); // Orientation 90° dwinUpdateLCD(); // Show bootscreen (first image) - encoderConfiguration(); for (uint16_t t = 0; t <= 100; t += 2) { dwinIconShow(ICON, ICON_Bar, 15, 260); dwinDrawRectangle(1, COLOR_BG_BLACK, 15 + t * 242 / 100, 260, 257, 280); diff --git a/Marlin/src/lcd/e3v2/proui/dwin.cpp b/Marlin/src/lcd/e3v2/proui/dwin.cpp index a0e2f8898b..923f02696d 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin.cpp +++ b/Marlin/src/lcd/e3v2/proui/dwin.cpp @@ -37,6 +37,7 @@ #include "../../utf8.h" #include "../../marlinui.h" +#include "../../extui/ui_api.h" #include "../../../MarlinCore.h" #include "../../../core/serial.h" #include "../../../core/macros.h" @@ -1311,7 +1312,7 @@ void eachMomentUpdate() { TERN_(PIDTEMP, if (hmiValue.tempControl == PIDTEMP_START) { plot.update(thermalManager.wholeDegHotend(0)); }) TERN_(PIDTEMPBED, if (hmiValue.tempControl == PIDTEMPBED_START) { plot.update(thermalManager.wholeDegBed()); }) TERN_(PIDTEMPCHAMBER, if (hmiValue.tempControl == PIDTEMPCHAMBER_START) { plot.update(thermalManager.wholeDegChamber()); }) - TERN_(MPCTEMP, if (hmiValue.tempControl == MPCTEMP_START) { plot.update(thermalManager.wholeDegHotend(0)); }) + TERN_(MPCTEMP, if (hmiValue.tempControl == MPC_STARTED) { plot.update(thermalManager.wholeDegHotend(0)); }) if (hmiFlag.abort_flag || hmiFlag.pause_flag || print_job_timer.isPaused()) { hmiReturnScreen(); } @@ -1566,7 +1567,7 @@ void dwinLevelingDone() { switch (hmiValue.tempControl) { default: return; #if ENABLED(MPC_AUTOTUNE) - case MPCTEMP_START: + case MPC_STARTED: DWINUI::drawCenteredString(hmiData.colorPopupTxt, 70, GET_TEXT_F(MSG_MPC_AUTOTUNE)); DWINUI::drawString(hmiData.colorPopupTxt, gfrm.x, gfrm.y - DWINUI::fontHeight() - 4, F("MPC target: Celsius")); DWINUI::drawCenteredString(hmiData.colorPopupTxt, 92, GET_TEXT_F(MSG_PID_FOR_NOZZLE)); @@ -1619,7 +1620,7 @@ void dwinLevelingDone() { switch (result) { #if ENABLED(MPCTEMP) - case MPCTEMP_START: + case MPC_STARTED: #elif ENABLED(PIDTEMP) case PIDTEMP_START: #endif @@ -1655,7 +1656,7 @@ void dwinLevelingDone() { void drawHPlot() { TERN_(PIDTEMP, dwinDrawPlot(PIDTEMP_START)); - TERN_(MPCTEMP, dwinDrawPlot(MPCTEMP_START)); + TERN_(MPCTEMP, dwinDrawPlot(MPC_STARTED)); } void drawBPlot() { TERN_(PIDTEMPBED, dwinDrawPlot(PIDTEMPBED_START)); @@ -1741,7 +1742,7 @@ void dwinLevelingDone() { void dwinMPCTuning(tempcontrol_t result) { hmiValue.tempControl = result; switch (result) { - case MPCTEMP_START: + case MPC_STARTED: hmiSaveProcessID(ID_MPCProcess); #if PROUI_TUNING_GRAPH dwinDrawPIDMPCPopup(); @@ -1909,7 +1910,6 @@ void MarlinUI::init_lcd() { const bool hs = dwinHandshake(); UNUSED(hs); dwinFrameSetDir(1); dwinJPGCacheTo1(Language_English); - encoderConfiguration(); } void dwinInitScreen() { diff --git a/Marlin/src/lcd/e3v2/proui/dwin.h b/Marlin/src/lcd/e3v2/proui/dwin.h index 7d264b8b12..9ec7b54421 100644 --- a/Marlin/src/lcd/e3v2/proui/dwin.h +++ b/Marlin/src/lcd/e3v2/proui/dwin.h @@ -90,7 +90,7 @@ enum processID : uint8_t { PID_TUNING_TIMEOUT, #endif #if ENABLED(MPC_AUTOTUNE) - MPCTEMP_START, + MPC_STARTED, MPC_TEMP_ERROR, MPC_INTERRUPTED, #endif diff --git a/Marlin/src/lcd/e3v2/proui/printstats.cpp b/Marlin/src/lcd/e3v2/proui/printstats.cpp index 732e80542d..2942261b7c 100644 --- a/Marlin/src/lcd/e3v2/proui/printstats.cpp +++ b/Marlin/src/lcd/e3v2/proui/printstats.cpp @@ -55,9 +55,9 @@ void PrintStats::draw() { DWINUI::drawString(MRG, 80, TS(GET_TEXT_F(MSG_INFO_PRINT_COUNT), F(": "), ps.totalPrints)); DWINUI::drawString(MRG, 100, TS(GET_TEXT_F(MSG_INFO_COMPLETED_PRINTS), F(": "), ps.finishedPrints)); duration_t(print_job_timer.getStats().printTime).toDigital(str, true); - DWINUI::drawString(MRG, 120, MString<50>(GET_TEXT_F(MSG_INFO_PRINT_TIME), F(": "), str)); + DWINUI::drawString(MRG, 120, TS(GET_TEXT_F(MSG_INFO_PRINT_TIME), F(": "), str)); duration_t(print_job_timer.getStats().longestPrint).toDigital(str, true); - DWINUI::drawString(MRG, 140, MString<50>(GET_TEXT(MSG_INFO_PRINT_LONGEST), F(": "), str)); + DWINUI::drawString(MRG, 140, TS(GET_TEXT_F(MSG_INFO_PRINT_LONGEST), F(": "), str)); DWINUI::drawString(MRG, 160, TS(GET_TEXT_F(MSG_INFO_PRINT_FILAMENT), F(": "), p_float_t(ps.filamentUsed / 1000, 2), F(" m"))); } diff --git a/Marlin/src/lcd/e3v2/proui/proui_extui.cpp b/Marlin/src/lcd/e3v2/proui/proui_extui.cpp index d377ca5fdc..d7aad208cc 100644 --- a/Marlin/src/lcd/e3v2/proui/proui_extui.cpp +++ b/Marlin/src/lcd/e3v2/proui/proui_extui.cpp @@ -222,7 +222,7 @@ namespace ExtUI { void onMPCTuning(const mpcresult_t rst) { // Called for temperature MPC tuning result switch (rst) { - case MPC_STARTED: dwinMPCTuning(MPCTEMP_START); break; + case MPC_STARTED: dwinMPCTuning(MPC_STARTED); break; case MPC_TEMP_ERROR: dwinMPCTuning(MPC_TEMP_ERROR); break; case MPC_INTERRUPTED: dwinMPCTuning(MPC_INTERRUPTED); break; case MPC_DONE: dwinMPCTuning(AUTOTUNE_DONE); break; diff --git a/Marlin/src/lcd/extui/ia_creality/ia_creality_rts.cpp b/Marlin/src/lcd/extui/ia_creality/ia_creality_rts.cpp index 797b80b0d5..15bbf3dc07 100644 --- a/Marlin/src/lcd/extui/ia_creality/ia_creality_rts.cpp +++ b/Marlin/src/lcd/extui/ia_creality/ia_creality_rts.cpp @@ -793,7 +793,7 @@ void RTS::handleData() { tmp_zprobe_offset = (float(recdat.data[0]) - 65536) / 100; else tmp_zprobe_offset = float(recdat.data[0]) / 100; - if (WITHIN((tmp_zprobe_offset), PROBE_OFFSET_ZMIN, PROBE_OFFSET_ZMAX)) { + if (WITHIN(tmp_zprobe_offset, PROBE_OFFSET_ZMIN, PROBE_OFFSET_ZMAX)) { int16_t tmpSteps = mmToWholeSteps(getZOffset_mm() - tmp_zprobe_offset, axis_t(Z)); if (tmpSteps == 0) tmpSteps = getZOffset_mm() < tmp_zprobe_offset ? 1 : -1; smartAdjustAxis_steps(-tmpSteps, axis_t(Z), false); diff --git a/Marlin/src/lcd/extui/mks_ui/tft_lvgl_configuration.cpp b/Marlin/src/lcd/extui/mks_ui/tft_lvgl_configuration.cpp index a10d0119f0..f8dda5bd7b 100644 --- a/Marlin/src/lcd/extui/mks_ui/tft_lvgl_configuration.cpp +++ b/Marlin/src/lcd/extui/mks_ui/tft_lvgl_configuration.cpp @@ -216,7 +216,6 @@ void tft_lvgl_init() { tft_style_init(); filament_pin_setup(); - lv_encoder_pin_init(); #if ENABLED(MKS_WIFI_MODULE) mks_esp_wifi_init(); @@ -331,12 +330,12 @@ bool my_touchpad_read(lv_indev_drv_t * indev_driver, lv_indev_data_t * data) { } int16_t enc_diff = 0; -lv_indev_state_t state = LV_INDEV_STATE_REL; +lv_indev_state_t indev_enc_state = LV_INDEV_STATE_REL; // ENC button is pressed or released bool my_mousewheel_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data) { - (void) indev_drv; // Unused + UNUSED(indev_drv); - data->state = state; + data->state = indev_enc_state; data->enc_diff = enc_diff; enc_diff = 0; @@ -446,102 +445,50 @@ lv_fs_res_t sd_tell_cb(lv_fs_drv_t * drv, void * file_p, uint32_t * pos_p) { return LV_FS_RES_OK; } -void lv_encoder_pin_init() { - #if BUTTON_EXISTS(EN1) - SET_INPUT_PULLUP(BTN_EN1); +void lv_update_encoder() { + + #if ANY_BUTTON(EN1, EN2) + constexpr uint8_t epps = ENCODER_PULSES_PER_STEP; // We can fill in + static uint8_t pulse_count; + pulse_count += ui.get_encoder_delta(); + const int8_t fullSteps = pulse_count / epps; + pulse_count -= fullSteps * epps; + enc_diff += fullSteps; #endif - #if BUTTON_EXISTS(EN2) - SET_INPUT_PULLUP(BTN_EN2); + + #if ANY_BUTTON(ENC, BACK, UP, DOWN, LEFT, RIGHT) + static millis_t last_encoder_ms; + const millis_t now = millis(), diffTime = getTickDiff(now, last_encoder_ms); + if (diffTime <= 50) return; #endif + #if BUTTON_EXISTS(ENC) - SET_INPUT_PULLUP(BTN_ENC); + static uint8_t old_button_enc = LV_INDEV_STATE_REL; + const uint8_t enc_c = BUTTON_PRESSED(ENC) ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL; + if (enc_c != old_button_enc) { + indev_enc_state = enc_c ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL; + old_button_enc = enc_c; + } #endif #if BUTTON_EXISTS(BACK) - SET_INPUT_PULLUP(BTN_BACK); + if (BUTTON_PRESSED(BACK)) {} #endif - #if BUTTON_EXISTS(UP) - SET_INPUT(BTN_UP); + if (BUTTON_PRESSED(UP)) {} #endif #if BUTTON_EXISTS(DOWN) - SET_INPUT(BTN_DOWN); + if (BUTTON_PRESSED(DOWN)) {} #endif #if BUTTON_EXISTS(LEFT) - SET_INPUT(BTN_LEFT); + if (BUTTON_PRESSED(LEFT)) {} #endif #if BUTTON_EXISTS(RIGHT) - SET_INPUT(BTN_RIGHT); + if (BUTTON_PRESSED(RIGHT)) {} #endif + } -#if 1 // HAS_ENCODER_ACTION - - void lv_update_encoder() { - static uint32_t encoder_time1; - uint32_t tmpTime, diffTime = 0; - tmpTime = millis(); - diffTime = getTickDiff(tmpTime, encoder_time1); - if (diffTime > 50) { - - #if HAS_ENCODER_WHEEL - - #if ANY_BUTTON(EN1, EN2, ENC, BACK) - - uint8_t newbutton = 0; - if (BUTTON_PRESSED(EN1)) newbutton |= EN_A; - if (BUTTON_PRESSED(EN2)) newbutton |= EN_B; - if (BUTTON_PRESSED(ENC)) newbutton |= EN_C; - if (BUTTON_PRESSED(BACK)) newbutton |= EN_D; - - #else - - constexpr uint8_t newbutton = 0; - - #endif - - static uint8_t buttons = 0; - buttons = newbutton; - static uint8_t lastEncoderBits; - - #define encrot0 0 - #define encrot1 1 - #define encrot2 2 - - uint8_t enc = 0; - if (buttons & EN_A) enc |= B01; - if (buttons & EN_B) enc |= B10; - if (enc != lastEncoderBits) { - switch (enc) { - case encrot1: - if (lastEncoderBits == encrot0) { - enc_diff--; - encoder_time1 = tmpTime; - } - break; - case encrot2: - if (lastEncoderBits == encrot0) { - enc_diff++; - encoder_time1 = tmpTime; - } - break; - } - lastEncoderBits = enc; - } - static uint8_t last_button_state = LV_INDEV_STATE_REL; - const uint8_t enc_c = (buttons & EN_C) ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL; - if (enc_c != last_button_state) { - state = enc_c ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL; - last_button_state = enc_c; - } - - #endif // HAS_ENCODER_WHEEL - - } // encoder_time1 - } - -#endif // HAS_ENCODER_ACTION - #ifdef __PLAT_NATIVE_SIM__ #include typedef void (*lv_log_print_g_cb_t)(lv_log_level_t level, const char *, uint32_t, const char *); diff --git a/Marlin/src/lcd/extui/mks_ui/tft_lvgl_configuration.h b/Marlin/src/lcd/extui/mks_ui/tft_lvgl_configuration.h index d847cfb193..43e82bd34d 100644 --- a/Marlin/src/lcd/extui/mks_ui/tft_lvgl_configuration.h +++ b/Marlin/src/lcd/extui/mks_ui/tft_lvgl_configuration.h @@ -41,7 +41,6 @@ bool my_touchpad_read(lv_indev_drv_t * indev_driver, lv_indev_data_t * data); bool my_mousewheel_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data); void lcdClear(uint16_t color); -void lv_encoder_pin_init(); void lv_update_encoder(); lv_fs_res_t spi_flash_open_cb(lv_fs_drv_t * drv, void * file_p, const char * path, lv_fs_mode_t mode); diff --git a/Marlin/src/lcd/marlinui.cpp b/Marlin/src/lcd/marlinui.cpp index dca18f2125..930a87a520 100644 --- a/Marlin/src/lcd/marlinui.cpp +++ b/Marlin/src/lcd/marlinui.cpp @@ -227,34 +227,32 @@ void MarlinUI::init() { init_lcd(); - #if HAS_DIGITAL_BUTTONS - #if BUTTON_EXISTS(EN1) - SET_INPUT_PULLUP(BTN_EN1); - #endif - #if BUTTON_EXISTS(EN2) - SET_INPUT_PULLUP(BTN_EN2); - #endif - #if BUTTON_EXISTS(ENC) - SET_INPUT_PULLUP(BTN_ENC); - #endif - #if BUTTON_EXISTS(ENC_EN) - SET_INPUT_PULLUP(BTN_ENC_EN); - #endif - #if BUTTON_EXISTS(BACK) - SET_INPUT_PULLUP(BTN_BACK); - #endif - #if BUTTON_EXISTS(UP) - SET_INPUT(BTN_UP); - #endif - #if BUTTON_EXISTS(DOWN) - SET_INPUT(BTN_DOWN); - #endif - #if BUTTON_EXISTS(LFT) - SET_INPUT(BTN_LEFT); - #endif - #if BUTTON_EXISTS(RT) - SET_INPUT(BTN_RIGHT); - #endif + #if BUTTON_EXISTS(EN1) + SET_INPUT_PULLUP(BTN_EN1); + #endif + #if BUTTON_EXISTS(EN2) + SET_INPUT_PULLUP(BTN_EN2); + #endif + #if BUTTON_EXISTS(ENC) + SET_INPUT_PULLUP(BTN_ENC); + #endif + #if BUTTON_EXISTS(ENC_EN) + SET_INPUT_PULLUP(BTN_ENC_EN); + #endif + #if BUTTON_EXISTS(BACK) + SET_INPUT_PULLUP(BTN_BACK); + #endif + #if BUTTON_EXISTS(UP) + SET_INPUT(BTN_UP); + #endif + #if BUTTON_EXISTS(DOWN) + SET_INPUT(BTN_DOWN); + #endif + #if BUTTON_EXISTS(LFT) + SET_INPUT(BTN_LEFT); + #endif + #if BUTTON_EXISTS(RT) + SET_INPUT(BTN_RIGHT); #endif #if HAS_SHIFT_ENCODER @@ -739,7 +737,7 @@ void MarlinUI::init() { void MarlinUI::kill_screen(FSTR_P const lcd_error, FSTR_P const lcd_component) { init(); - status_printf(1, F(S_FMT ": " S_FMT), FTOP(lcd_error), FTOP(lcd_component)); + status_printf(1, F(S_FMT ": " S_FMT), lcd_error, lcd_component); TERN_(HAS_MARLINUI_MENU, return_to_status()); // RED ALERT. RED ALERT. @@ -1026,72 +1024,56 @@ void MarlinUI::init() { if (TERN0(IS_RRW_KEYPAD, handle_keypad())) reset_status_timeout(ms); - uint8_t abs_diff = ABS(encoderDiff); - - #if ENCODER_PULSES_PER_STEP > 1 - // When reversing the encoder direction, a movement step can be missed because - // encoderDiff has a non-zero residual value, making the controller unresponsive. - // The fix clears the residual value when the encoder is idle. - // Also check if past half the threshold to compensate for missed single steps. - static int8_t lastEncoderDiff; - - // Timeout? No decoder change since last check. 10 or 20 times per second. - if (encoderDiff == lastEncoderDiff && abs_diff <= epps / 2) // Same direction & size but not over a half-step? - encoderDiff = 0; // Clear residual pulses. - else if (WITHIN(abs_diff, epps / 2 + 1, epps - 1)) { // Past half of threshold? - abs_diff = epps; // Treat as a full step size - encoderDiff = (encoderDiff < 0 ? -1 : 1) * abs_diff; // ...in the spin direction. - } - if (lastEncoderDiff != encoderDiff) wake_display(); - lastEncoderDiff = encoderDiff; - #endif + static int8_t lastEncoderDiff; + if (lastEncoderDiff != encoderDiff) wake_display(); + lastEncoderDiff = encoderDiff; + const uint8_t abs_diff = ABS(encoderDiff); const bool encoderPastThreshold = (abs_diff >= epps); - if (encoderPastThreshold || lcd_clicked) { - if (encoderPastThreshold && TERN1(IS_TFTGLCD_PANEL, !external_control)) { + if (encoderPastThreshold && TERN1(IS_TFTGLCD_PANEL, !external_control)) { - #if ALL(HAS_MARLINUI_MENU, ENCODER_RATE_MULTIPLIER) + int32_t encoder_multiplier = 1; - int32_t encoder_multiplier = 1; + #if ALL(HAS_MARLINUI_MENU, ENCODER_RATE_MULTIPLIER) - if (encoder_multiplier_enabled) { - // Note that the rate is always calculated between two passes through the - // loop and that the abs of the encoderDiff value is tracked. - static millis_t encoder_mult_prev_ms = 0; - const float encoderStepRate = ((float(abs_diff) / float(epps)) * 1000.0f) / float(ms - encoder_mult_prev_ms); - encoder_mult_prev_ms = ms; + if (encoder_multiplier_enabled) { + // Note that the rate is always calculated between two passes through the + // loop and that the abs of the encoderDiff value is tracked. + static millis_t encoder_mult_prev_ms = 0; + const float encoderStepRate = ((float(abs_diff) / float(epps)) * 1000.0f) / float(ms - encoder_mult_prev_ms); + encoder_mult_prev_ms = ms; - if (ENCODER_100X_STEPS_PER_SEC > 0 && encoderStepRate >= ENCODER_100X_STEPS_PER_SEC) - encoder_multiplier = 100; - else if (ENCODER_10X_STEPS_PER_SEC > 0 && encoderStepRate >= ENCODER_10X_STEPS_PER_SEC) - encoder_multiplier = 10; - else if (ENCODER_5X_STEPS_PER_SEC > 0 && encoderStepRate >= ENCODER_5X_STEPS_PER_SEC) - encoder_multiplier = 5; + if (ENCODER_100X_STEPS_PER_SEC > 0 && encoderStepRate >= ENCODER_100X_STEPS_PER_SEC) + encoder_multiplier = 100; + else if (ENCODER_10X_STEPS_PER_SEC > 0 && encoderStepRate >= ENCODER_10X_STEPS_PER_SEC) + encoder_multiplier = 10; + else if (ENCODER_5X_STEPS_PER_SEC > 0 && encoderStepRate >= ENCODER_5X_STEPS_PER_SEC) + encoder_multiplier = 5; - // Enable to output the encoder steps per second value - //#define ENCODER_RATE_MULTIPLIER_DEBUG - #if ENABLED(ENCODER_RATE_MULTIPLIER_DEBUG) - SERIAL_ECHO_MSG( - "Enc Step Rate: ", encoderStepRate, - " Mult: ", encoder_multiplier, - " 5X Steps: ", ENCODER_5X_STEPS_PER_SEC, - " 10X Steps: ", ENCODER_10X_STEPS_PER_SEC, - " 100X Steps: ", ENCODER_100X_STEPS_PER_SEC - ); - #endif - } + // Enable to output the encoder steps per second value + //#define ENCODER_RATE_MULTIPLIER_DEBUG + #if ENABLED(ENCODER_RATE_MULTIPLIER_DEBUG) + SERIAL_ECHO_MSG( + "Enc Step Rate: ", encoderStepRate, + " Mult: ", encoder_multiplier, + " 5X Steps: ", ENCODER_5X_STEPS_PER_SEC, + " 10X Steps: ", ENCODER_10X_STEPS_PER_SEC, + " 100X Steps: ", ENCODER_100X_STEPS_PER_SEC + ); + #endif + } - #else + #endif // ENCODER_RATE_MULTIPLIER - constexpr int32_t encoder_multiplier = 1; - - #endif // ENCODER_RATE_MULTIPLIER - - if (can_encode()) encoderPosition += (encoderDiff * encoder_multiplier) / epps; - - encoderDiff = 0; + const int8_t fullSteps = encoderDiff / epps; + if (fullSteps != 0) { + encoderDiff -= fullSteps * epps; + if (can_encode() && !lcd_clicked) + encoderPosition += (fullSteps * encoder_multiplier); } + } + if (encoderPastThreshold || lcd_clicked) { reset_status_timeout(ms); #if HAS_BACKLIGHT_TIMEOUT @@ -1312,124 +1294,156 @@ void MarlinUI::init() { */ void MarlinUI::update_buttons() { const millis_t now = millis(); - if (ELAPSED(now, next_button_update_ms)) { - #if HAS_DIGITAL_BUTTONS + #if HAS_MARLINUI_ENCODER - #if ANY_BUTTON(EN1, EN2, ENC, BACK) - - uint8_t newbutton = 0; - if (BUTTON_PRESSED(EN1)) newbutton |= EN_A; - if (BUTTON_PRESSED(EN2)) newbutton |= EN_B; - if (can_encode() && BUTTON_PRESSED(ENC)) newbutton |= EN_C; - if (BUTTON_PRESSED(BACK)) newbutton |= EN_D; - - #else - - constexpr uint8_t newbutton = 0; - - #endif - - // - // Directional buttons - // - #if ANY_BUTTON(UP, DOWN, LEFT, RIGHT) - - const int8_t pulses = epps * encoderDirection; - - if (BUTTON_PRESSED(UP)) { - encoderDiff = (ENCODER_STEPS_PER_MENU_ITEM) * pulses; - next_button_update_ms = now + 300; - } - else if (BUTTON_PRESSED(DOWN)) { - encoderDiff = -(ENCODER_STEPS_PER_MENU_ITEM) * pulses; - next_button_update_ms = now + 300; - } - else if (BUTTON_PRESSED(LEFT)) { - encoderDiff = -pulses; - next_button_update_ms = now + 300; - } - else if (BUTTON_PRESSED(RIGHT)) { - encoderDiff = pulses; - next_button_update_ms = now + 300; - } - - #endif // UP || DOWN || LEFT || RIGHT - - buttons = (newbutton | TERN0(HAS_SLOW_BUTTONS, slow_buttons) - #if ALL(HAS_TOUCH_BUTTONS, HAS_ENCODER_ACTION) - | (touch_buttons & TERN(HAS_ENCODER_WHEEL, ~(EN_A | EN_B), 0xFF)) - #endif - ); - - #elif HAS_ADC_BUTTONS - - buttons = 0; - - #endif - - #if HAS_ADC_BUTTONS - if (keypad_buttons == 0) { - const uint8_t b = get_ADC_keyValue(); - if (WITHIN(b, 1, 8)) keypad_buttons = _BV(b - 1); - } - #endif - - #if HAS_SHIFT_ENCODER - /** - * Set up Rotary Encoder bit values (for two pin encoders to indicate movement). - * These values are independent of which pins are used for EN_A / EN_B indications. - * The rotary encoder part is also independent of the LCD chipset. - */ - uint8_t val = 0; - WRITE(SHIFT_LD_PIN, LOW); - WRITE(SHIFT_LD_PIN, HIGH); - for (uint8_t i = 0; i < 8; ++i) { - val >>= 1; - if (READ(SHIFT_OUT_PIN)) SBI(val, 7); - WRITE(SHIFT_CLK_PIN, HIGH); - WRITE(SHIFT_CLK_PIN, LOW); - } - TERN(REPRAPWORLD_KEYPAD, keypad_buttons, buttons) = ~val; - #endif - - #if IS_TFTGLCD_PANEL - next_button_update_ms = now + (LCD_UPDATE_INTERVAL / 2); - buttons = slow_buttons; - TERN_(AUTO_BED_LEVELING_UBL, external_encoder()); - #endif - - } // next_button_update_ms - - #if HAS_ENCODER_WHEEL - static uint8_t lastEncoderBits; - - // Manage encoder rotation - #define ENCODER_SPIN(_E1, _E2) switch (lastEncoderBits) { case _E1: encoderDiff += encoderDirection; break; case _E2: encoderDiff -= encoderDirection; } - - uint8_t enc = 0; - if (buttons & EN_A) enc |= B01; - if (buttons & EN_B) enc |= B10; - if (enc != lastEncoderBits) { - switch (enc) { - case 0: ENCODER_SPIN(1, 2); break; - case 2: ENCODER_SPIN(0, 3); break; - case 3: ENCODER_SPIN(2, 1); break; - case 1: ENCODER_SPIN(3, 0); break; - } + const int8_t delta = get_encoder_delta(now); + if (delta) { + encoderDiff += delta * encoderDirection; #if ALL(HAS_MARLINUI_MENU, AUTO_BED_LEVELING_UBL) external_encoder(); #endif - lastEncoderBits = enc; } - #endif // HAS_ENCODER_WHEEL - } + #endif + + if (PENDING(now, next_button_update_ms)) return; + + #if HAS_DIGITAL_BUTTONS + + uint8_t newbuttons = 0; + #if ANY_BUTTON(ENC, BACK) + if (can_encode() && BUTTON_PRESSED(ENC)) newbuttons |= EN_C; + if (BUTTON_PRESSED(BACK)) newbuttons |= EN_D; + #endif + + // + // Directional buttons + // + #if ANY_BUTTON(UP, DOWN, LEFT, RIGHT) + + const int8_t pulses = epps * encoderDirection; + + if (BUTTON_PRESSED(UP)) { + encoderDiff = (ENCODER_STEPS_PER_MENU_ITEM) * pulses; + next_button_update_ms = now + 300; + } + else if (BUTTON_PRESSED(DOWN)) { + encoderDiff = -(ENCODER_STEPS_PER_MENU_ITEM) * pulses; + next_button_update_ms = now + 300; + } + else if (BUTTON_PRESSED(LEFT)) { + encoderDiff = -pulses; + next_button_update_ms = now + 300; + } + else if (BUTTON_PRESSED(RIGHT)) { + encoderDiff = pulses; + next_button_update_ms = now + 300; + } + + #endif // UP || DOWN || LEFT || RIGHT + + buttons = (newbuttons | TERN0(HAS_SLOW_BUTTONS, slow_buttons) + #if ALL(HAS_TOUCH_BUTTONS, HAS_ENCODER_ACTION) + | (touch_buttons & TERN(HAS_MARLINUI_ENCODER, ~(EN_A | EN_B), 0xFF)) + #endif + ); + + #elif HAS_ADC_BUTTONS + + buttons = 0; + + #endif + + #if HAS_ADC_BUTTONS + if (keypad_buttons == 0) { + const uint8_t b = get_ADC_keyValue(); + if (WITHIN(b, 1, 8)) keypad_buttons = _BV(b - 1); + } + #endif + + #if HAS_SHIFT_ENCODER + /** + * Set up Rotary Encoder bit values (for two pin encoders to indicate movement). + * These values are independent of which pins are used for EN_A / EN_B indications. + * The rotary encoder part is also independent of the LCD chipset. + */ + uint8_t val = 0; + WRITE(SHIFT_LD_PIN, LOW); + WRITE(SHIFT_LD_PIN, HIGH); + for (uint8_t i = 0; i < 8; ++i) { + val >>= 1; + if (READ(SHIFT_OUT_PIN)) SBI(val, 7); + WRITE(SHIFT_CLK_PIN, HIGH); + WRITE(SHIFT_CLK_PIN, LOW); + } + TERN(REPRAPWORLD_KEYPAD, keypad_buttons, buttons) = ~val; + #endif + + #if IS_TFTGLCD_PANEL + next_button_update_ms = now + (LCD_UPDATE_INTERVAL / 2); + buttons = slow_buttons; + TERN_(AUTO_BED_LEVELING_UBL, external_encoder()); + #endif + + } // update_buttons #endif // HAS_ENCODER_ACTION #endif // HAS_WIRED_LCD +#if MARLINUI_ENCODER_DELTA + + #define ENCODER_DEBOUNCE_MS 2 + + /** + * Get the encoder delta (-2 -1 0 +1 +2) since the last call, reading the live encoder state. + * Pins may be debounced to filter noise. + */ + int8_t MarlinUI::get_encoder_delta(const millis_t &now/*=millis()*/) { + + typedef struct { bool a:1, b:1; } enc_t; + + const enc_t live_enc = { BUTTON_PRESSED(EN1), BUTTON_PRESSED(EN2) }; + + #if ENCODER_DEBOUNCE_MS + + static enc_t enc; + static enc_t old_live; + + static millis_t en_A_bounce_ms; + if (old_live.a != live_enc.a) en_A_bounce_ms = now + (ENCODER_DEBOUNCE_MS); + else if (ELAPSED(now, en_A_bounce_ms)) enc.a = live_enc.a; + + static millis_t en_B_bounce_ms; + if (old_live.b != live_enc.b) en_B_bounce_ms = now + (ENCODER_DEBOUNCE_MS); + else if (ELAPSED(now, en_B_bounce_ms)) enc.b = live_enc.b; + + old_live = live_enc; + + #else + + const enc_t &enc = live_enc; + + #endif + + static uint8_t old_pos; + const uint8_t pos = (enc.a ^ enc.b) | (enc.a << 1); // 0:00 1:10 2:11 3:01 + int8_t delta = 0; + if (pos != old_pos) { + delta = (pos - old_pos + 4 + 1) % 4 - 1; + old_pos = pos; + + static int8_t last_dir; + if (delta == 2) delta = last_dir * 2; + else last_dir = delta; + } + return delta; + + } // get_encoder_delta + +#endif // MARLINUI_ENCODER_DELTA + void MarlinUI::completion_feedback(const bool good/*=true*/) { wake_display(); // Wake the screen for all audio feedback #if HAS_SOUND @@ -1563,12 +1577,12 @@ void MarlinUI::host_notify(const char * const cstr) { * * @param pfmt A constant format P-string */ - void MarlinUI::status_printf_P(int8_t level, PGM_P const fmt, ...) { + void MarlinUI::status_printf_P(int8_t level, PGM_P const pfmt, ...) { if (set_alert_level(level)) return; va_list args; - va_start(args, fmt); - vsnprintf_P(status_message, MAX_MESSAGE_LENGTH, fmt, args); + va_start(args, pfmt); + vsnprintf_P(status_message, MAX_MESSAGE_LENGTH, pfmt, args); va_end(args); host_notify(status_message); @@ -1642,12 +1656,12 @@ void MarlinUI::host_notify(const char * const cstr) { void MarlinUI::_set_status_and_level(const char * const ustr, const int8_t=0, const bool pgm) { pgm ? host_notify_P(ustr) : host_notify(ustr); } - void MarlinUI::status_printf_P(int8_t level, PGM_P const fmt, ...) { + void MarlinUI::status_printf_P(int8_t level, PGM_P const pfmt, ...) { MString<30> msg; va_list args; - va_start(args, fmt); - vsnprintf_P(&msg, 30, fmt, args); + va_start(args, pfmt); + vsnprintf_P(&msg, 30, pfmt, args); va_end(args); host_notify(msg); diff --git a/Marlin/src/lcd/marlinui.h b/Marlin/src/lcd/marlinui.h index f21d2565be..ad4be03900 100644 --- a/Marlin/src/lcd/marlinui.h +++ b/Marlin/src/lcd/marlinui.h @@ -254,6 +254,11 @@ public: } #endif + #if (HAS_WIRED_LCD && HAS_ENCODER_ACTION && HAS_MARLINUI_ENCODER) || HAS_DWIN_E3V2 || HAS_TFT_LVGL_UI + #define MARLINUI_ENCODER_DELTA 1 + static int8_t get_encoder_delta(const millis_t &now=millis()); + #endif + #if HAS_MEDIA #define MEDIA_MENU_GATEWAY TERN(PASSWORD_ON_SD_PRINT_MENU, password.media_gatekeeper, menu_media) static void media_changed(const uint8_t old_stat, const uint8_t stat); diff --git a/Marlin/src/lcd/menu/menu_main.cpp b/Marlin/src/lcd/menu/menu_main.cpp index 622b03379a..460305f5d4 100644 --- a/Marlin/src/lcd/menu/menu_main.cpp +++ b/Marlin/src/lcd/menu/menu_main.cpp @@ -246,7 +246,7 @@ void menu_main() { START_MENU(); BACK_ITEM(MSG_INFO_SCREEN); - #if HAS_MEDIA && !defined(MEDIA_MENU_AT_TOP) && !HAS_ENCODER_WHEEL + #if HAS_MEDIA && !defined(MEDIA_MENU_AT_TOP) && !HAS_MARLINUI_ENCODER #define MEDIA_MENU_AT_TOP #endif diff --git a/Marlin/src/lcd/menu/menu_ubl.cpp b/Marlin/src/lcd/menu/menu_ubl.cpp index 701d2ae97a..64c9cc382b 100644 --- a/Marlin/src/lcd/menu/menu_ubl.cpp +++ b/Marlin/src/lcd/menu/menu_ubl.cpp @@ -144,7 +144,7 @@ void _lcd_ubl_custom_mesh() { * UBL Adjust Mesh Height Command */ void _lcd_ubl_adjust_height_cmd() { - char ubl_lcd_gcode[13]; + char ubl_lcd_gcode[14]; const int ind = ubl_height_amount > 0 ? 6 : 7; strcpy_P(ubl_lcd_gcode, PSTR("G29P6C-")); sprintf_P(&ubl_lcd_gcode[ind], PSTR(".%i"), ABS(ubl_height_amount)); diff --git a/Marlin/src/lcd/tft/ui_common.cpp b/Marlin/src/lcd/tft/ui_common.cpp index 944be77ab5..c1c14c3bb5 100644 --- a/Marlin/src/lcd/tft/ui_common.cpp +++ b/Marlin/src/lcd/tft/ui_common.cpp @@ -71,12 +71,16 @@ void moveAxis(const AxisEnum axis, const int8_t direction) { } #endif - const float diff = motionAxisState.currentStepSize * direction; + float diff = motionAxisState.currentStepSize * direction; #if HAS_BED_PROBE if (axis == Z_AXIS && motionAxisState.z_selection == Z_SELECTION_Z_PROBE) { + #if ENABLED(BABYSTEP_ZPROBE_OFFSET) + + diff = 0; + const int16_t babystep_increment = direction * BABYSTEP_SIZE_Z; const bool do_probe = DISABLED(BABYSTEP_HOTEND_Z_OFFSET) || active_extruder == 0; const float bsDiff = planner.mm_per_step[Z_AXIS] * babystep_increment, @@ -92,12 +96,12 @@ void moveAxis(const AxisEnum axis, const int8_t direction) { else TERN(BABYSTEP_HOTEND_Z_OFFSET, hotend_offset[active_extruder].z = new_offs, NOOP); drawMessage_P(NUL_STR); // Clear the error - drawAxisValue(axis); } else drawMessage(GET_TEXT_F(MSG_LCD_SOFT_ENDSTOPS)); - #else + #else // !BABYSTEP_ZPROBE_OFFSET + // Only change probe.offset.z probe.offset.z += diff; if (direction < 0 && current_position.z < PROBE_OFFSET_ZMIN) { @@ -111,13 +115,12 @@ void moveAxis(const AxisEnum axis, const int8_t direction) { else drawMessage_P(NUL_STR); // Clear the error - drawAxisValue(axis); - #endif + #endif // !BABYSTEP_ZPROBE_OFFSET } #endif // HAS_BED_PROBE - if (!ui.manual_move.processing) { + if (diff && !ui.manual_move.processing) { // Get motion limit from software endstops, if any float min, max; soft_endstop.get_manual_axis_limits(axis, min, max); diff --git a/Marlin/src/module/endstops.cpp b/Marlin/src/module/endstops.cpp index 490d6bc2ce..d0ad234a7f 100644 --- a/Marlin/src/module/endstops.cpp +++ b/Marlin/src/module/endstops.cpp @@ -50,6 +50,10 @@ #include "../feature/joystick.h" #endif +#if ENABLED(FT_MOTION) + #include "ft_motion.h" +#endif + #if HAS_BED_PROBE #include "probe.h" #endif @@ -351,7 +355,7 @@ void Endstops::event_handler() { TERN_(HAS_STATUS_MESSAGE, ui.status_printf(0, F(S_FMT GANG_N_1(NUM_AXES, " %c") " %c"), - GET_TEXT(MSG_LCD_ENDSTOPS), + GET_TEXT_F(MSG_LCD_ENDSTOPS), NUM_AXIS_LIST_(chrX, chrY, chrZ, chrI, chrJ, chrK, chrU, chrV, chrW) chrP ) ); @@ -782,6 +786,7 @@ void Endstops::update() { #define PROCESS_ENDSTOP_Z(MINMAX) PROCESS_DUAL_ENDSTOP(Z, MINMAX) #endif + #if ENABLED(G38_PROBE_TARGET) // For G38 moves check the probe's pin for ALL movement if (G38_move && TEST_ENDSTOP(Z_MIN_PROBE) == TERN1(G38_PROBE_AWAY, (G38_move < 4))) { @@ -796,8 +801,17 @@ void Endstops::update() { // Signal, after validation, if an endstop limit is pressed or not #if HAS_X_AXIS - if (stepper.axis_is_moving(X_AXIS)) { - if (!stepper.motor_direction(X_AXIS_HEAD)) { // -direction + #if ENABLED(FT_MOTION) + const bool x_moving_pos = ftMotion.axis_moving_pos(X_AXIS_HEAD), + x_moving_neg = ftMotion.axis_moving_neg(X_AXIS_HEAD); + #define X_MOVE_TEST x_moving_pos || x_moving_neg + #define X_NEG_DIR_TEST x_moving_neg + #else + #define X_MOVE_TEST stepper.axis_is_moving(X_AXIS) + #define X_NEG_DIR_TEST !stepper.motor_direction(X_AXIS_HEAD) + #endif + if (X_MOVE_TEST) { + if (X_NEG_DIR_TEST) { // -direction #if HAS_X_MIN_STATE PROCESS_ENDSTOP_X(MIN); #if CORE_DIAG(XY, Y, MIN) @@ -829,8 +843,17 @@ void Endstops::update() { #endif // HAS_X_AXIS #if HAS_Y_AXIS - if (stepper.axis_is_moving(Y_AXIS)) { - if (!stepper.motor_direction(Y_AXIS_HEAD)) { // -direction + #if ENABLED(FT_MOTION) + const bool y_moving_pos = ftMotion.axis_moving_pos(Y_AXIS_HEAD), + y_moving_neg = ftMotion.axis_moving_neg(Y_AXIS_HEAD); + #define Y_MOVE_TEST y_moving_pos || y_moving_neg + #define Y_NEG_DIR_TEST y_moving_neg + #else + #define Y_MOVE_TEST stepper.axis_is_moving(Y_AXIS) + #define Y_NEG_DIR_TEST !stepper.motor_direction(Y_AXIS_HEAD) + #endif + if (Y_MOVE_TEST) { + if (Y_NEG_DIR_TEST) { // -direction #if HAS_Y_MIN_STATE PROCESS_ENDSTOP_Y(MIN); #if CORE_DIAG(XY, X, MIN) @@ -862,8 +885,17 @@ void Endstops::update() { #endif // HAS_Y_AXIS #if HAS_Z_AXIS - if (stepper.axis_is_moving(Z_AXIS)) { - if (!stepper.motor_direction(Z_AXIS_HEAD)) { // Z -direction. Gantry down, bed up. + #if ENABLED(FT_MOTION) + const bool z_moving_pos = ftMotion.axis_moving_pos(Z_AXIS_HEAD), + z_moving_neg = ftMotion.axis_moving_neg(Z_AXIS_HEAD); + #define Z_MOVE_TEST z_moving_pos || z_moving_neg + #define Z_NEG_DIR_TEST z_moving_neg + #else + #define Z_MOVE_TEST stepper.axis_is_moving(Z_AXIS) + #define Z_NEG_DIR_TEST !stepper.motor_direction(Z_AXIS_HEAD) + #endif + if (Z_MOVE_TEST) { + if (Z_NEG_DIR_TEST) { // Z -direction. Gantry down, bed up. #if HAS_Z_MIN_STATE // If the Z_MIN_PIN is being used for the probe there's no // separate Z_MIN endstop. But a Z endstop could be wired @@ -907,6 +939,7 @@ void Endstops::update() { #endif // HAS_Z_AXIS #if HAS_I_AXIS + // TODO: FT_Motion logic. if (stepper.axis_is_moving(I_AXIS)) { if (!stepper.motor_direction(I_AXIS_HEAD)) { // -direction #if HAS_I_MIN_STATE diff --git a/Marlin/src/module/ft_motion.cpp b/Marlin/src/module/ft_motion.cpp index e912255561..f92caa7d72 100644 --- a/Marlin/src/module/ft_motion.cpp +++ b/Marlin/src/module/ft_motion.cpp @@ -26,6 +26,7 @@ #include "ft_motion.h" #include "stepper.h" // Access stepper block queue function and abort status. +#include "endstops.h" FTMotion ftMotion; @@ -59,6 +60,9 @@ int32_t FTMotion::stepperCmdBuff_produceIdx = 0, // Index of next stepper comman FTMotion::stepperCmdBuff_consumeIdx = 0; // Index of next stepper command read from the buffer. bool FTMotion::sts_stepperBusy = false; // The stepper buffer has items and is in use. +millis_t FTMotion::axis_pos_move_end_ti[NUM_AXIS_ENUMS] = {0}, + FTMotion::axis_neg_move_end_ti[NUM_AXIS_ENUMS] = {0}; + // Private variables. @@ -110,9 +114,9 @@ uint32_t FTMotion::interpIdx = 0, // Index of current data point b #if HAS_X_AXIS FTMotion::shaping_t FTMotion::shaping = { 0, 0, - x:{ { 0.0f }, { 0.0f }, { 0 } }, // d_zi, Ai, Ni + x:{ false, { 0.0f }, { 0.0f }, { 0 } }, // d_zi, Ai, Ni #if HAS_Y_AXIS - y:{ { 0.0f }, { 0.0f }, { 0 } } // d_zi, Ai, Ni + y:{ false, { 0.0f }, { 0.0f }, { 0 } } // d_zi, Ai, Ni #endif }; #endif @@ -131,7 +135,10 @@ constexpr uint32_t last_batchIdx = (FTM_WINDOW_SIZE) - (FTM_BATCH_SIZE); // Public functions. +static bool markBlockStart = false; + // Sets controller states to begin processing a block. +// Called by Stepper::ftMotion_blockQueueUpdate, invoked from the main loop. void FTMotion::startBlockProc() { blockProcRdy = true; blockProcDn = false; @@ -166,11 +173,13 @@ void FTMotion::loop() { if (!cfg.mode) return; - // Handle block abort with the following sequence: - // 1. Zero out commands in stepper ISR. - // 2. Drain the motion buffer, stop processing until they are emptied. - // 3. Reset all the states / memory. - // 4. Signal ready for new block. + /** + * Handle block abort with the following sequence: + * 1. Zero out commands in stepper ISR. + * 2. Drain the motion buffer, stop processing until they are emptied. + * 3. Reset all the states / memory. + * 4. Signal ready for new block. + */ if (stepper.abort_current_block) { if (sts_stepperBusy) return; // Wait until motion buffers are emptied reset(); @@ -183,7 +192,10 @@ void FTMotion::loop() { if (blockProcRdy) { if (!blockProcRdy_z1) { // One-shot. - if (!blockDataIsRunout) loadBlockData(stepper.current_block); + if (!blockDataIsRunout) { + loadBlockData(stepper.current_block); + markBlockStart = true; + } else blockDataIsRunout = false; } while (!blockProcDn && !batchRdy && (makeVector_idx - makeVector_idx_z1 < (FTM_POINTS_PER_LOOP))) @@ -199,22 +211,12 @@ void FTMotion::loop() { trajMod = traj; // Move the window to traj #else // Copy the uncompensated vectors. - #define TCOPY(A) memcpy(trajMod.A, traj.A, sizeof(trajMod.A)) - LOGICAL_AXIS_CODE( - TCOPY(e), - TCOPY(x), TCOPY(y), TCOPY(z), - TCOPY(i), TCOPY(j), TCOPY(k), - TCOPY(u), TCOPY(v), TCOPY(w) - ); + #define TCOPY(A) memcpy(trajMod.A, traj.A, sizeof(trajMod.A)); + LOGICAL_AXIS_MAP_LC(TCOPY); // Shift the time series back in the window - #define TSHIFT(A) memcpy(traj.A, &traj.A[FTM_BATCH_SIZE], last_batchIdx * sizeof(traj.A[0])) - LOGICAL_AXIS_CODE( - TSHIFT(e), - TSHIFT(x), TSHIFT(y), TSHIFT(z), - TSHIFT(i), TSHIFT(j), TSHIFT(k), - TSHIFT(u), TSHIFT(v), TSHIFT(w) - ); + #define TSHIFT(A) memcpy(traj.A, &traj.A[FTM_BATCH_SIZE], last_batchIdx * sizeof(traj.A[0])); + LOGICAL_AXIS_MAP_LC(TSHIFT); #endif // ... data is ready in trajMod. @@ -471,6 +473,9 @@ void FTMotion::reset() { #endif TERN_(HAS_EXTRUDERS, e_raw_z1 = e_advanced_z1 = 0.0f); + + ZERO(axis_pos_move_end_ti); + ZERO(axis_neg_move_end_ti); } // Private functions. @@ -490,14 +495,14 @@ void FTMotion::init() { reset(); // Precautionary. } -// Loads / converts block data from planner to fixed-time control variables. +// Load / convert block data from planner to fixed-time control variables. void FTMotion::loadBlockData(block_t * const current_block) { const float totalLength = current_block->millimeters, oneOverLength = 1.0f / totalLength; startPosn = endPosn_prevBlock; - xyze_pos_t moveDist = LOGICAL_AXIS_ARRAY( + const xyze_pos_t moveDist = LOGICAL_AXIS_ARRAY( current_block->steps.e * planner.mm_per_step[E_AXIS_N(current_block->extruder)] * (current_block->direction_bits.e ? 1 : -1), current_block->steps.x * planner.mm_per_step[X_AXIS] * (current_block->direction_bits.x ? 1 : -1), current_block->steps.y * planner.mm_per_step[Y_AXIS] * (current_block->direction_bits.y ? 1 : -1), @@ -574,7 +579,8 @@ void FTMotion::loadBlockData(block_t * const current_block) { * f_s * T1_P : (mm) Distance traveled during the accel phase * f_e * T3_P : (mm) Distance traveled during the decel phase */ - F_P = (2.0f * totalLength - f_s * T1_P - f_e * T3_P) / (T1_P + 2.0f * T2_P + T3_P); // (mm/s) Feedrate at the end of the accel phase + const float adist = f_s * T1_P; + F_P = (2.0f * totalLength - adist - f_e * T3_P) / (T1_P + 2.0f * T2_P + T3_P); // (mm/s) Feedrate at the end of the accel phase // Calculate the acceleration and deceleration rates accel_P = N1 ? ((F_P - f_s) / T1_P) : 0.0f; @@ -582,7 +588,7 @@ void FTMotion::loadBlockData(block_t * const current_block) { decel_P = (f_e - F_P) / T3_P; // Calculate the distance traveled during the accel phase - s_1e = f_s * T1_P + 0.5f * accel_P * sq(T1_P); + s_1e = adist + 0.5f * accel_P * sq(T1_P); // Calculate the distance traveled during the decel phase s_2e = s_1e + F_P * T2_P; @@ -591,6 +597,43 @@ void FTMotion::loadBlockData(block_t * const current_block) { max_intervals = N1 + N2 + N3; endPosn_prevBlock += moveDist; + + millis_t move_end_ti = millis() + SEC_TO_MS(FTM_TS*(float)(max_intervals + num_samples_cmpnstr_settle() + (PROP_BATCHES+1)*FTM_BATCH_SIZE) + ((float)FTM_STEPPERCMD_BUFF_SIZE/(float)FTM_STEPPER_FS)); + + #if CORE_IS_XY + if (moveDist.x > 0.f) axis_pos_move_end_ti[A_AXIS] = move_end_ti; + if (moveDist.y > 0.f) axis_pos_move_end_ti[B_AXIS] = move_end_ti; + if (moveDist.x + moveDist.y > 0.f) axis_pos_move_end_ti[X_HEAD] = move_end_ti; + if (moveDist.x - moveDist.y > 0.f) axis_pos_move_end_ti[Y_HEAD] = move_end_ti; + if (moveDist.x < 0.f) axis_neg_move_end_ti[A_AXIS] = move_end_ti; + if (moveDist.y < 0.f) axis_neg_move_end_ti[B_AXIS] = move_end_ti; + if (moveDist.x + moveDist.y < 0.f) axis_neg_move_end_ti[X_HEAD] = move_end_ti; + if (moveDist.x - moveDist.y < 0.f) axis_neg_move_end_ti[Y_HEAD] = move_end_ti; + #else + if (moveDist.x > 0.f) axis_pos_move_end_ti[X_AXIS] = move_end_ti; + if (moveDist.y > 0.f) axis_pos_move_end_ti[Y_AXIS] = move_end_ti; + if (moveDist.x < 0.f) axis_neg_move_end_ti[X_AXIS] = move_end_ti; + if (moveDist.y < 0.f) axis_neg_move_end_ti[Y_AXIS] = move_end_ti; + #endif + if (moveDist.z > 0.f) axis_pos_move_end_ti[Z_AXIS] = move_end_ti; + if (moveDist.z < 0.f) axis_neg_move_end_ti[Z_AXIS] = move_end_ti; + // if (moveDist.i > 0.f) axis_pos_move_end_ti[I_AXIS] = move_end_ti; + // if (moveDist.i < 0.f) axis_neg_move_end_ti[I_AXIS] = move_end_ti; + // if (moveDist.j > 0.f) axis_pos_move_end_ti[J_AXIS] = move_end_ti; + // if (moveDist.j < 0.f) axis_neg_move_end_ti[J_AXIS] = move_end_ti; + // if (moveDist.k > 0.f) axis_pos_move_end_ti[K_AXIS] = move_end_ti; + // if (moveDist.k < 0.f) axis_neg_move_end_ti[K_AXIS] = move_end_ti; + // if (moveDist.u > 0.f) axis_pos_move_end_ti[U_AXIS] = move_end_ti; + // if (moveDist.u < 0.f) axis_neg_move_end_ti[U_AXIS] = move_end_ti; + // . + // . + // . + + // If the endstop is already pressed, endstop interrupts won't invoke + // endstop_triggered and the move will grind. So check here for a + // triggered endstop, which shortly marks the block for discard. + endstops.update(); + } // Generate data points of the trajectory. @@ -607,7 +650,6 @@ void FTMotion::makeVector() { else if (makeVector_idx < (N1 + N2)) { // Coasting phase dist = s_1e + F_P * (tau - N1 * (FTM_TS)); // (mm) Distance traveled for coasting phase since start of block - //accel_k = 0.0f; } else { // Deceleration phase @@ -616,18 +658,8 @@ void FTMotion::makeVector() { accel_k = decel_P; // (mm/s^2) Acceleration K factor from Decel phase } - LOGICAL_AXIS_CODE( - traj.e[makeVector_batchIdx] = startPosn.e + ratio.e * dist, - traj.x[makeVector_batchIdx] = startPosn.x + ratio.x * dist, - traj.y[makeVector_batchIdx] = startPosn.y + ratio.y * dist, - traj.z[makeVector_batchIdx] = startPosn.z + ratio.z * dist, - traj.i[makeVector_batchIdx] = startPosn.i + ratio.i * dist, - traj.j[makeVector_batchIdx] = startPosn.j + ratio.j * dist, - traj.k[makeVector_batchIdx] = startPosn.k + ratio.k * dist, - traj.u[makeVector_batchIdx] = startPosn.u + ratio.u * dist, - traj.v[makeVector_batchIdx] = startPosn.v + ratio.v * dist, - traj.w[makeVector_batchIdx] = startPosn.w + ratio.w * dist - ); + #define _FTM_TRAJ(A) traj.A[makeVector_batchIdx] = startPosn.A + ratio.A * dist; + LOGICAL_AXIS_MAP_LC(_FTM_TRAJ); #if HAS_EXTRUDERS if (cfg.linearAdvEna) { @@ -706,7 +738,7 @@ void FTMotion::makeVector() { * - Tests for delta are moved outside the loop. * - Two functions are used for command computation with an array of function pointers. */ -static void (*command_set[NUM_AXES TERN0(HAS_EXTRUDERS, +1)])(int32_t&, int32_t&, ft_command_t&, int32_t, int32_t); +static void (*command_set[SUM_TERN(HAS_EXTRUDERS, NUM_AXES, 1)])(int32_t&, int32_t&, ft_command_t&, int32_t, int32_t); static void command_set_pos(int32_t &e, int32_t &s, ft_command_t &b, int32_t bd, int32_t bs) { if (e < FTM_CTS_COMPARE_VAL) return; @@ -746,40 +778,30 @@ void FTMotion::convertToSteps(const uint32_t idx) { ); #endif - LOGICAL_AXIS_CODE( - command_set[E_AXIS_N(current_block->extruder)] = delta.e >= 0 ? command_set_pos : command_set_neg, - command_set[X_AXIS] = delta.x >= 0 ? command_set_pos : command_set_neg, - command_set[Y_AXIS] = delta.y >= 0 ? command_set_pos : command_set_neg, - command_set[Z_AXIS] = delta.z >= 0 ? command_set_pos : command_set_neg, - command_set[I_AXIS] = delta.i >= 0 ? command_set_pos : command_set_neg, - command_set[J_AXIS] = delta.j >= 0 ? command_set_pos : command_set_neg, - command_set[K_AXIS] = delta.k >= 0 ? command_set_pos : command_set_neg, - command_set[U_AXIS] = delta.u >= 0 ? command_set_pos : command_set_neg, - command_set[V_AXIS] = delta.v >= 0 ? command_set_pos : command_set_neg, - command_set[W_AXIS] = delta.w >= 0 ? command_set_pos : command_set_neg - ); + #define _COMMAND_SET(AXIS) command_set[_AXIS(AXIS)] = delta[_AXIS(AXIS)] >= 0 ? command_set_pos : command_set_neg; + LOGICAL_AXIS_MAP(_COMMAND_SET); for (uint32_t i = 0U; i < (FTM_STEPS_PER_UNIT_TIME); i++) { - // Init all step/dir bits to 0 (defaulting to reverse/negative motion) - stepperCmdBuff[stepperCmdBuff_produceIdx] = 0; + ft_command_t &cmd = stepperCmdBuff[stepperCmdBuff_produceIdx]; + // Init all step/dir bits to 0 (defaulting to reverse/negative motion) + cmd = 0; + + // Mark the start of a new block + if (markBlockStart) { + cmd = _BV(FT_BIT_START); + markBlockStart = false; + } + + // Accumulate the errors for all axes err_P += delta; // Set up step/dir bits for all axes - LOGICAL_AXIS_CODE( - command_set[E_AXIS_N(current_block->extruder)](err_P.e, steps.e, stepperCmdBuff[stepperCmdBuff_produceIdx], _BV(FT_BIT_DIR_E), _BV(FT_BIT_STEP_E)), - command_set[X_AXIS](err_P.x, steps.x, stepperCmdBuff[stepperCmdBuff_produceIdx], _BV(FT_BIT_DIR_X), _BV(FT_BIT_STEP_X)), - command_set[Y_AXIS](err_P.y, steps.y, stepperCmdBuff[stepperCmdBuff_produceIdx], _BV(FT_BIT_DIR_Y), _BV(FT_BIT_STEP_Y)), - command_set[Z_AXIS](err_P.z, steps.z, stepperCmdBuff[stepperCmdBuff_produceIdx], _BV(FT_BIT_DIR_Z), _BV(FT_BIT_STEP_Z)), - command_set[I_AXIS](err_P.i, steps.i, stepperCmdBuff[stepperCmdBuff_produceIdx], _BV(FT_BIT_DIR_I), _BV(FT_BIT_STEP_I)), - command_set[J_AXIS](err_P.j, steps.j, stepperCmdBuff[stepperCmdBuff_produceIdx], _BV(FT_BIT_DIR_J), _BV(FT_BIT_STEP_J)), - command_set[K_AXIS](err_P.k, steps.k, stepperCmdBuff[stepperCmdBuff_produceIdx], _BV(FT_BIT_DIR_K), _BV(FT_BIT_STEP_K)), - command_set[U_AXIS](err_P.u, steps.u, stepperCmdBuff[stepperCmdBuff_produceIdx], _BV(FT_BIT_DIR_U), _BV(FT_BIT_STEP_U)), - command_set[V_AXIS](err_P.v, steps.v, stepperCmdBuff[stepperCmdBuff_produceIdx], _BV(FT_BIT_DIR_V), _BV(FT_BIT_STEP_V)), - command_set[W_AXIS](err_P.w, steps.w, stepperCmdBuff[stepperCmdBuff_produceIdx], _BV(FT_BIT_DIR_W), _BV(FT_BIT_STEP_W)), - ); + #define _COMMAND_RUN(AXIS) command_set[_AXIS(AXIS)](err_P[_AXIS(AXIS)], steps[_AXIS(AXIS)], cmd, _BV(FT_BIT_DIR_##AXIS), _BV(FT_BIT_STEP_##AXIS)); + LOGICAL_AXIS_MAP(_COMMAND_RUN); + // Next circular buffer index if (++stepperCmdBuff_produceIdx == (FTM_STEPPERCMD_BUFF_SIZE)) stepperCmdBuff_produceIdx = 0; diff --git a/Marlin/src/module/ft_motion.h b/Marlin/src/module/ft_motion.h index 884a183479..3325005ae2 100644 --- a/Marlin/src/module/ft_motion.h +++ b/Marlin/src/module/ft_motion.h @@ -107,6 +107,9 @@ class FTMotion { static bool sts_stepperBusy; // The stepper buffer has items and is in use. + static millis_t axis_pos_move_end_ti[NUM_AXIS_ENUMS], + axis_neg_move_end_ti[NUM_AXIS_ENUMS]; + // Public methods static void init(); static void startBlockProc(); // Set controller states to begin processing a block. @@ -129,6 +132,9 @@ class FTMotion { static void reset(); // Reset all states of the fixed time conversion to defaults. + static bool axis_moving_pos(const AxisEnum axis) { return !ELAPSED(millis(), axis_pos_move_end_ti[axis]); } + static bool axis_moving_neg(const AxisEnum axis) { return !ELAPSED(millis(), axis_neg_move_end_ti[axis]); } + private: static xyze_trajectory_t traj; @@ -152,6 +158,8 @@ class FTMotion { static uint32_t N1, N2, N3; static uint32_t max_intervals; + static constexpr uint32_t PROP_BATCHES = CEIL(FTM_WINDOW_SIZE/FTM_BATCH_SIZE) - 1; // Number of batches needed to propagate the current trajectory to the stepper. + #define _DIVCEIL(A,B) (((A) + (B) - 1) / (B)) static constexpr uint32_t _ftm_ratio = TERN(FTM_UNIFIED_BWS, 2, _DIVCEIL(FTM_WINDOW_SIZE, FTM_BATCH_SIZE)), shaper_intervals = (FTM_BATCH_SIZE) * _DIVCEIL(FTM_ZMAX, FTM_BATCH_SIZE), @@ -172,6 +180,7 @@ class FTMotion { #if HAS_X_AXIS typedef struct AxisShaping { + bool ena = false; // Enabled indication. float d_zi[FTM_ZMAX] = { 0.0f }; // Data point delay vector. float Ai[5]; // Shaping gain vector. uint32_t Ni[5]; // Shaping time index vector. @@ -207,6 +216,9 @@ class FTMotion { static void makeVector(); static void convertToSteps(const uint32_t idx); + FORCE_INLINE static int32_t num_samples_cmpnstr_settle() { return ( shaping.x.ena || shaping.y.ena ) ? FTM_ZMAX : 0; } + + }; // class FTMotion extern FTMotion ftMotion; diff --git a/Marlin/src/module/ft_types.h b/Marlin/src/module/ft_types.h index d460853262..e6a2506017 100644 --- a/Marlin/src/module/ft_types.h +++ b/Marlin/src/module/ft_types.h @@ -47,7 +47,9 @@ enum dynFreqMode_t : uint8_t { typedef struct XYZEarray xyze_trajectory_t; typedef struct XYZEarray xyze_trajectoryMod_t; +// TODO: Convert ft_command_t to a struct with bitfields instead of using a primitive type enum { + FT_BIT_START, LIST_N(DOUBLE(LOGICAL_AXES), FT_BIT_DIR_E, FT_BIT_STEP_E, FT_BIT_DIR_X, FT_BIT_STEP_X, FT_BIT_DIR_Y, FT_BIT_STEP_Y, FT_BIT_DIR_Z, FT_BIT_STEP_Z, diff --git a/Marlin/src/module/planner.cpp b/Marlin/src/module/planner.cpp index 1f3e4069aa..7c1ac7eb16 100644 --- a/Marlin/src/module/planner.cpp +++ b/Marlin/src/module/planner.cpp @@ -1979,32 +1979,35 @@ bool Planner::_populate_block( // Compute direction bit-mask for this block AxisBits dm; - #if ANY(CORE_IS_XY, MARKFORGED_XY, MARKFORGED_YX) - dm.hx = (dist.a > 0); // Save the toolhead's true direction in X - dm.hy = (dist.b > 0); // ...and Y - TERN_(HAS_Z_AXIS, dm.z = (dist.c > 0)); + #if ANY(CORE_IS_XY, CORE_IS_XZ, MARKFORGED_XY, MARKFORGED_YX) + dm.hx = (dist.a > 0); // True direction in X + #endif + #if ANY(CORE_IS_XY, CORE_IS_YZ, MARKFORGED_XY, MARKFORGED_YX) + dm.hy = (dist.b > 0); // True direction in Y + #endif + #if ANY(CORE_IS_XZ, CORE_IS_YZ) + dm.hz = (dist.c > 0); // True direction in Z #endif #if CORE_IS_XY - dm.a = (dist.a + dist.b > 0); // Motor A direction - dm.b = (CORESIGN(dist.a - dist.b) > 0); // Motor B direction + dm.a = (dist.a + dist.b > 0); // Motor A direction + dm.b = (CORESIGN(dist.a - dist.b) > 0); // Motor B direction + TERN_(HAS_Z_AXIS, dm.z = (dist.c > 0)); // Axis Z direction #elif CORE_IS_XZ - dm.hx = (dist.a > 0); // Save the toolhead's true direction in X - dm.y = (dist.b > 0); - dm.hz = (dist.c > 0); // ...and Z dm.a = (dist.a + dist.c > 0); // Motor A direction + dm.y = (dist.b > 0); // Axis Y direction dm.c = (CORESIGN(dist.a - dist.c) > 0); // Motor C direction #elif CORE_IS_YZ - dm.x = (dist.a > 0); - dm.hy = (dist.b > 0); // Save the toolhead's true direction in Y - dm.hz = (dist.c > 0); // ...and Z + dm.x = (dist.a > 0); // Axis X direction dm.b = (dist.b + dist.c > 0); // Motor B direction dm.c = (CORESIGN(dist.b - dist.c) > 0); // Motor C direction #elif ENABLED(MARKFORGED_XY) dm.a = (dist.a TERN(MARKFORGED_INVERSE, -, +) dist.b > 0); // Motor A direction dm.b = (dist.b > 0); // Motor B direction + TERN_(HAS_Z_AXIS, dm.z = (dist.c > 0)); // Axis Z direction #elif ENABLED(MARKFORGED_YX) dm.a = (dist.a > 0); // Motor A direction dm.b = (dist.b TERN(MARKFORGED_INVERSE, -, +) dist.a > 0); // Motor B direction + TERN_(HAS_Z_AXIS, dm.z = (dist.c > 0)); // Axis Z direction #else XYZ_CODE( dm.x = (dist.a > 0), @@ -2901,10 +2904,12 @@ void Planner::buffer_sync_block(const BlockFlagBit sync_flag/*=BLOCK_BIT_SYNC_PO block->flag.apply(sync_flag); block->position = position; + #if ENABLED(BACKLASH_COMPENSATION) LOOP_NUM_AXES(axis) block->position[axis] += backlash.get_applied_steps((AxisEnum)axis); #endif - #if ALL(HAS_FAN, LASER_SYNCHRONOUS_M106_M107) + + #if ENABLED(LASER_SYNCHRONOUS_M106_M107) FANS_LOOP(i) block->fan_speed[i] = thermalManager.fan_speed[i]; #endif @@ -3233,6 +3238,10 @@ bool Planner::buffer_line(const xyze_pos_t &cart, const_feedRate_t fr_mm_s * The provided ABCE position is in machine units. */ void Planner::set_machine_position_mm(const abce_pos_t &abce) { + + // When FT Motion is enabled, call synchronize() here instead of generating a sync block + if (TERN0(FT_MOTION, ftMotion.cfg.mode)) synchronize(); + TERN_(DISTINCT_E_FACTORS, last_extruder = active_extruder); TERN_(HAS_POSITION_FLOAT, position_float = abce); position.set( diff --git a/Marlin/src/module/planner.h b/Marlin/src/module/planner.h index 4bc3d3be04..adc4ef5c9f 100644 --- a/Marlin/src/module/planner.h +++ b/Marlin/src/module/planner.h @@ -214,9 +214,10 @@ typedef struct PlannerBlock { volatile block_flags_t flag; // Block flags - bool is_fan_sync() { return TERN0(LASER_SYNCHRONOUS_M106_M107, flag.sync_fans); } - bool is_pwr_sync() { return TERN0(LASER_POWER_SYNC, flag.sync_laser_pwr); } - bool is_sync() { return flag.sync_position || is_fan_sync() || is_pwr_sync(); } + bool is_sync_pos() { return flag.sync_position; } + bool is_sync_fan() { return TERN0(LASER_SYNCHRONOUS_M106_M107, flag.sync_fans); } + bool is_sync_pwr() { return TERN0(LASER_POWER_SYNC, flag.sync_laser_pwr); } + bool is_sync() { return is_sync_pos() || is_sync_fan() || is_sync_pwr(); } bool is_page() { return TERN0(DIRECT_STEPPING, flag.page); } bool is_move() { return !(is_sync() || is_page()); } diff --git a/Marlin/src/module/stepper.cpp b/Marlin/src/module/stepper.cpp index 4edbd6a189..a10f25b4d3 100644 --- a/Marlin/src/module/stepper.cpp +++ b/Marlin/src/module/stepper.cpp @@ -654,6 +654,11 @@ void Stepper::disable_all_steppers() { TERN_(EXTENSIBLE_UI, ExtUI::onSteppersDisabled()); } +#if ENABLED(FTM_OPTIMIZE_DIR_STATES) + // We'll compare the updated DIR bits to the last set state + static AxisBits last_set_direction; +#endif + // Set a single axis direction based on the last set flags. // A direction bit of "1" indicates forward or positive motion. #define SET_STEP_DIR(A) do{ \ @@ -679,6 +684,8 @@ void Stepper::apply_directions() { SET_STEP_DIR(U), SET_STEP_DIR(V), SET_STEP_DIR(W) ); + TERN_(FTM_OPTIMIZE_DIR_STATES, last_set_direction = last_direction_bits); + DIR_WAIT_AFTER(); } @@ -1549,8 +1556,20 @@ void Stepper::isr() { nextMainISR = FTM_MIN_TICKS; // Set to minimum interval (a limit on the top speed) ftMotion_stepper(); // Run FTM Stepping } - interval = nextMainISR; // Interval is either some old nextMainISR or FTM_MIN_TICKS - nextMainISR = 0; // For FT Motion fire again ASAP + + #if ENABLED(BABYSTEPPING) + if (nextBabystepISR == 0) { // Avoid ANY stepping too soon after baby-stepping + nextBabystepISR = babystepping_isr(); + NOLESS(nextMainISR, (BABYSTEP_TICKS) / 8); // FULL STOP for 125µs after a baby-step + } + if (nextBabystepISR != BABYSTEP_NEVER) // Avoid baby-stepping too close to axis Stepping + NOLESS(nextBabystepISR, nextMainISR / 2); // TODO: Only look at axes enabled for baby-stepping + #endif + + interval = nextMainISR; // Interval is either some old nextMainISR or FTM_MIN_TICKS + TERN_(BABYSTEPPING, NOMORE(interval, nextBabystepISR)); // Come back early for Babystepping? + + nextMainISR = 0; // For FT Motion fire again ASAP } #endif @@ -1808,6 +1827,7 @@ void Stepper::pulse_phase_isr() { last_direction_bits.toggle(_AXIS(AXIS)); \ DIR_WAIT_BEFORE(); \ SET_STEP_DIR(AXIS); \ + TERN_(FTM_OPTIMIZE_DIR_STATES, last_set_direction = last_direction_bits); \ DIR_WAIT_AFTER(); \ } \ } \ @@ -2255,6 +2275,90 @@ hal_timer_t Stepper::calc_multistep_timer_interval(uint32_t step_rate) { return calc_timer_interval(step_rate); } +// Method to get all moving axes (for proper endstop handling) +void Stepper::set_axis_moved_for_current_block() { + + #if IS_CORE + // Define conditions for checking endstops + #define S_(N) current_block->steps[CORE_AXIS_##N] + #define D_(N) current_block->direction_bits[CORE_AXIS_##N] + #endif + + #if CORE_IS_XY || CORE_IS_XZ + /** + * Head direction in -X axis for CoreXY and CoreXZ bots. + * + * If steps differ, both axes are moving. + * If DeltaA == -DeltaB, the movement is only in the 2nd axis (Y or Z, handled below) + * If DeltaA == DeltaB, the movement is only in the 1st axis (X) + */ + #if ANY(COREXY, COREXZ) + #define X_CMP(A,B) ((A)==(B)) + #else + #define X_CMP(A,B) ((A)!=(B)) + #endif + #define X_MOVE_TEST ( S_(1) != S_(2) || (S_(1) > 0 && X_CMP(D_(1),D_(2))) ) + #elif ENABLED(MARKFORGED_XY) + #define X_MOVE_TEST (current_block->steps.a != current_block->steps.b) + #else + #define X_MOVE_TEST !!current_block->steps.a + #endif + + #if CORE_IS_XY || CORE_IS_YZ + /** + * Head direction in -Y axis for CoreXY / CoreYZ bots. + * + * If steps differ, both axes are moving + * If DeltaA == DeltaB, the movement is only in the 1st axis (X or Y) + * If DeltaA == -DeltaB, the movement is only in the 2nd axis (Y or Z) + */ + #if ANY(COREYX, COREYZ) + #define Y_CMP(A,B) ((A)==(B)) + #else + #define Y_CMP(A,B) ((A)!=(B)) + #endif + #define Y_MOVE_TEST ( S_(1) != S_(2) || (S_(1) > 0 && Y_CMP(D_(1),D_(2))) ) + #elif ENABLED(MARKFORGED_YX) + #define Y_MOVE_TEST (current_block->steps.a != current_block->steps.b) + #else + #define Y_MOVE_TEST !!current_block->steps.b + #endif + + #if CORE_IS_XZ || CORE_IS_YZ + /** + * Head direction in -Z axis for CoreXZ or CoreYZ bots. + * + * If steps differ, both axes are moving + * If DeltaA == DeltaB, the movement is only in the 1st axis (X or Y, already handled above) + * If DeltaA == -DeltaB, the movement is only in the 2nd axis (Z) + */ + #if ANY(COREZX, COREZY) + #define Z_CMP(A,B) ((A)==(B)) + #else + #define Z_CMP(A,B) ((A)!=(B)) + #endif + #define Z_MOVE_TEST ( S_(1) != S_(2) || (S_(1) > 0 && Z_CMP(D_(1),D_(2))) ) + #else + #define Z_MOVE_TEST !!current_block->steps.c + #endif + + // Set flags for all axes that move in this block + // These are set per-axis, not per-stepper + AxisBits didmove; + NUM_AXIS_CODE( + if (X_MOVE_TEST) didmove.a = true, // Cartesian X or Kinematic A + if (Y_MOVE_TEST) didmove.b = true, // Cartesian Y or Kinematic B + if (Z_MOVE_TEST) didmove.c = true, // Cartesian Z or Kinematic C + if (!!current_block->steps.i) didmove.i = true, + if (!!current_block->steps.j) didmove.j = true, + if (!!current_block->steps.k) didmove.k = true, + if (!!current_block->steps.u) didmove.u = true, + if (!!current_block->steps.v) didmove.v = true, + if (!!current_block->steps.w) didmove.w = true + ); + axis_did_move = didmove; +} + /** * This last phase of the stepper interrupt processes and properly * schedules planner blocks. This is executed after the step pulses @@ -2412,6 +2516,8 @@ hal_timer_t Stepper::block_phase_isr() { E_APPLY_DIR(forward_e, false); + TERN_(FTM_OPTIMIZE_DIR_STATES, last_set_direction = last_direction_bits); + DIR_WAIT_AFTER(); } } @@ -2513,25 +2619,31 @@ hal_timer_t Stepper::block_phase_isr() { // Anything in the buffer? if ((current_block = planner.get_current_block())) { - // Sync block? Sync the stepper counts or fan speeds and return + // Run through all sync blocks while (current_block->is_sync()) { + // Set laser power #if ENABLED(LASER_POWER_SYNC) if (cutter.cutter_mode == CUTTER_MODE_CONTINUOUS) { - if (current_block->is_pwr_sync()) { + if (current_block->is_sync_pwr()) { planner.laser_inline.status.isSyncPower = true; cutter.apply_power(current_block->laser.power); } } #endif - TERN_(LASER_SYNCHRONOUS_M106_M107, if (current_block->is_fan_sync()) planner.sync_fan_speeds(current_block->fan_speed)); + // Set "fan speeds" for a laser module + #if ENABLED(LASER_SYNCHRONOUS_M106_M107) + if (current_block->is_sync_fan()) planner.sync_fan_speeds(current_block->fan_speed); + #endif - if (!(current_block->is_fan_sync() || current_block->is_pwr_sync())) _set_position(current_block->position); + // Set position + if (current_block->is_sync_pos()) _set_position(current_block->position); + // Done with this block discard_current_block(); - // Try to get a new block + // Try to get a new block. Exit if there are no more. if (!(current_block = planner.get_current_block())) return interval; // No more queued movements! } @@ -2565,85 +2677,8 @@ hal_timer_t Stepper::block_phase_isr() { } #endif - // Flag all moving axes for proper endstop handling - - #if IS_CORE - // Define conditions for checking endstops - #define S_(N) current_block->steps[CORE_AXIS_##N] - #define D_(N) current_block->direction_bits[CORE_AXIS_##N] - #endif - - #if CORE_IS_XY || CORE_IS_XZ - /** - * Head direction in -X axis for CoreXY and CoreXZ bots. - * - * If steps differ, both axes are moving. - * If DeltaA == -DeltaB, the movement is only in the 2nd axis (Y or Z, handled below) - * If DeltaA == DeltaB, the movement is only in the 1st axis (X) - */ - #if ANY(COREXY, COREXZ) - #define X_CMP(A,B) ((A)==(B)) - #else - #define X_CMP(A,B) ((A)!=(B)) - #endif - #define X_MOVE_TEST ( S_(1) != S_(2) || (S_(1) > 0 && X_CMP(D_(1),D_(2))) ) - #elif ENABLED(MARKFORGED_XY) - #define X_MOVE_TEST (current_block->steps.a != current_block->steps.b) - #else - #define X_MOVE_TEST !!current_block->steps.a - #endif - - #if CORE_IS_XY || CORE_IS_YZ - /** - * Head direction in -Y axis for CoreXY / CoreYZ bots. - * - * If steps differ, both axes are moving - * If DeltaA == DeltaB, the movement is only in the 1st axis (X or Y) - * If DeltaA == -DeltaB, the movement is only in the 2nd axis (Y or Z) - */ - #if ANY(COREYX, COREYZ) - #define Y_CMP(A,B) ((A)==(B)) - #else - #define Y_CMP(A,B) ((A)!=(B)) - #endif - #define Y_MOVE_TEST ( S_(1) != S_(2) || (S_(1) > 0 && Y_CMP(D_(1),D_(2))) ) - #elif ENABLED(MARKFORGED_YX) - #define Y_MOVE_TEST (current_block->steps.a != current_block->steps.b) - #else - #define Y_MOVE_TEST !!current_block->steps.b - #endif - - #if CORE_IS_XZ || CORE_IS_YZ - /** - * Head direction in -Z axis for CoreXZ or CoreYZ bots. - * - * If steps differ, both axes are moving - * If DeltaA == DeltaB, the movement is only in the 1st axis (X or Y, already handled above) - * If DeltaA == -DeltaB, the movement is only in the 2nd axis (Z) - */ - #if ANY(COREZX, COREZY) - #define Z_CMP(A,B) ((A)==(B)) - #else - #define Z_CMP(A,B) ((A)!=(B)) - #endif - #define Z_MOVE_TEST ( S_(1) != S_(2) || (S_(1) > 0 && Z_CMP(D_(1),D_(2))) ) - #else - #define Z_MOVE_TEST !!current_block->steps.c - #endif - - AxisBits didmove; - NUM_AXIS_CODE( - if (X_MOVE_TEST) didmove.a = true, - if (Y_MOVE_TEST) didmove.b = true, - if (Z_MOVE_TEST) didmove.c = true, - if (!!current_block->steps.i) didmove.i = true, - if (!!current_block->steps.j) didmove.j = true, - if (!!current_block->steps.k) didmove.k = true, - if (!!current_block->steps.u) didmove.u = true, - if (!!current_block->steps.v) didmove.v = true, - if (!!current_block->steps.w) didmove.w = true - ); - axis_did_move = didmove; + // Set flags for all moving axes, accounting for kinematics + set_axis_moved_for_current_block(); #if ENABLED(ADAPTIVE_STEP_SMOOTHING) // Nonlinear Extrusion needs at least 2x oversampling to permit increase of E step rate @@ -3261,15 +3296,12 @@ void Stepper::_set_position(const abce_long_t &spos) { #endif #if ANY(IS_CORE, MARKFORGED_XY, MARKFORGED_YX) + // Core equations follow the form of the dA and dB equations at https://www.corexy.com/theory.html #if CORE_IS_XY - // corexy positioning - // these equations follow the form of the dA and dB equations on https://www.corexy.com/theory.html count_position.set(spos.a + spos.b, CORESIGN(spos.a - spos.b) OPTARG(HAS_Z_AXIS, spos.c)); #elif CORE_IS_XZ - // corexz planning count_position.set(spos.a + spos.c, spos.b, CORESIGN(spos.a - spos.c)); #elif CORE_IS_YZ - // coreyz planning count_position.set(spos.a, spos.b + spos.c, CORESIGN(spos.b - spos.c)); #elif ENABLED(MARKFORGED_XY) count_position.set(spos.a TERN(MARKFORGED_INVERSE, +, -) spos.b, spos.b, spos.c); @@ -3465,16 +3497,24 @@ void Stepper::report_positions() { #if ENABLED(FT_MOTION) - // Set stepper I/O for fixed time controller. + /** + * Run stepping from the Stepper ISR at regular short intervals. + * + * - Set ftMotion.sts_stepperBusy state to reflect whether there are any commands in the circular buffer. + * - If there are no commands in the buffer, return. + * - Get the next command from the circular buffer ftMotion.stepperCmdBuff[]. + * - If the block is being aborted, return without processing the command. + * - Apply STEP/DIR along with any delays required. A command may be empty, with no STEP/DIR. + */ void Stepper::ftMotion_stepper() { + static AxisBits direction_bits{0}; + // Check if the buffer is empty. ftMotion.sts_stepperBusy = (ftMotion.stepperCmdBuff_produceIdx != ftMotion.stepperCmdBuff_consumeIdx); if (!ftMotion.sts_stepperBusy) return; // "Pop" one command from current motion buffer - // Use one byte to restore one stepper command in the format: - // |X_step|X_direction|Y_step|Y_direction|Z_step|Z_direction|E_step|E_direction| const ft_command_t command = ftMotion.stepperCmdBuff[ftMotion.stepperCmdBuff_consumeIdx]; if (++ftMotion.stepperCmdBuff_consumeIdx == (FTM_STEPPERCMD_BUFF_SIZE)) ftMotion.stepperCmdBuff_consumeIdx = 0; @@ -3483,58 +3523,80 @@ void Stepper::report_positions() { USING_TIMED_PULSE(); - axis_did_move = LOGICAL_AXIS_ARRAY( + // Get FT Motion command flags for axis STEP / DIR + #define _FTM_STEP(AXIS) TEST(command, FT_BIT_STEP_##AXIS) + #define _FTM_DIR(AXIS) TEST(command, FT_BIT_DIR_##AXIS) + + AxisBits axis_step; + axis_step = LOGICAL_AXIS_ARRAY( TEST(command, FT_BIT_STEP_E), TEST(command, FT_BIT_STEP_X), TEST(command, FT_BIT_STEP_Y), TEST(command, FT_BIT_STEP_Z), TEST(command, FT_BIT_STEP_I), TEST(command, FT_BIT_STEP_J), TEST(command, FT_BIT_STEP_K), TEST(command, FT_BIT_STEP_U), TEST(command, FT_BIT_STEP_V), TEST(command, FT_BIT_STEP_W) ); - last_direction_bits = LOGICAL_AXIS_ARRAY( - axis_did_move.e ? TEST(command, FT_BIT_DIR_E) : last_direction_bits.e, - axis_did_move.x ? TEST(command, FT_BIT_DIR_X) : last_direction_bits.x, - axis_did_move.y ? TEST(command, FT_BIT_DIR_Y) : last_direction_bits.y, - axis_did_move.z ? TEST(command, FT_BIT_DIR_Z) : last_direction_bits.z, - axis_did_move.i ? TEST(command, FT_BIT_DIR_I) : last_direction_bits.i, - axis_did_move.j ? TEST(command, FT_BIT_DIR_J) : last_direction_bits.j, - axis_did_move.k ? TEST(command, FT_BIT_DIR_K) : last_direction_bits.k, - axis_did_move.u ? TEST(command, FT_BIT_DIR_U) : last_direction_bits.u, - axis_did_move.v ? TEST(command, FT_BIT_DIR_V) : last_direction_bits.v, - axis_did_move.w ? TEST(command, FT_BIT_DIR_W) : last_direction_bits.w + direction_bits = LOGICAL_AXIS_ARRAY( + axis_step.e ? TEST(command, FT_BIT_DIR_E) : direction_bits.e, + axis_step.x ? TEST(command, FT_BIT_DIR_X) : direction_bits.x, + axis_step.y ? TEST(command, FT_BIT_DIR_Y) : direction_bits.y, + axis_step.z ? TEST(command, FT_BIT_DIR_Z) : direction_bits.z, + axis_step.i ? TEST(command, FT_BIT_DIR_I) : direction_bits.i, + axis_step.j ? TEST(command, FT_BIT_DIR_J) : direction_bits.j, + axis_step.k ? TEST(command, FT_BIT_DIR_K) : direction_bits.k, + axis_step.u ? TEST(command, FT_BIT_DIR_U) : direction_bits.u, + axis_step.v ? TEST(command, FT_BIT_DIR_V) : direction_bits.v, + axis_step.w ? TEST(command, FT_BIT_DIR_W) : direction_bits.w ); // Apply directions (which will apply to the entire linear move) LOGICAL_AXIS_CODE( - E_APPLY_DIR(last_direction_bits.e, false), - X_APPLY_DIR(last_direction_bits.x, false), Y_APPLY_DIR(last_direction_bits.y, false), Z_APPLY_DIR(last_direction_bits.z, false), - I_APPLY_DIR(last_direction_bits.i, false), J_APPLY_DIR(last_direction_bits.j, false), K_APPLY_DIR(last_direction_bits.k, false), - U_APPLY_DIR(last_direction_bits.u, false), V_APPLY_DIR(last_direction_bits.v, false), W_APPLY_DIR(last_direction_bits.w, false) + E_APPLY_DIR(direction_bits.e, false), + X_APPLY_DIR(direction_bits.x, false), Y_APPLY_DIR(direction_bits.y, false), Z_APPLY_DIR(direction_bits.z, false), + I_APPLY_DIR(direction_bits.i, false), J_APPLY_DIR(direction_bits.j, false), K_APPLY_DIR(direction_bits.k, false), + U_APPLY_DIR(direction_bits.u, false), V_APPLY_DIR(direction_bits.v, false), W_APPLY_DIR(direction_bits.w, false) ); - DIR_WAIT_AFTER(); + /** + * Update direction bits for steppers that were stepped by this command. + * HX, HY, HZ direction bits were set for Core kinematics + * when the block was fetched and are not overwritten here. + */ // Start a step pulse LOGICAL_AXIS_CODE( - E_APPLY_STEP(axis_did_move.e, false), - X_APPLY_STEP(axis_did_move.x, false), Y_APPLY_STEP(axis_did_move.y, false), Z_APPLY_STEP(axis_did_move.z, false), - I_APPLY_STEP(axis_did_move.i, false), J_APPLY_STEP(axis_did_move.j, false), K_APPLY_STEP(axis_did_move.k, false), - U_APPLY_STEP(axis_did_move.u, false), V_APPLY_STEP(axis_did_move.v, false), W_APPLY_STEP(axis_did_move.w, false) + E_APPLY_STEP(axis_step.e, false), + X_APPLY_STEP(axis_step.x, false), Y_APPLY_STEP(axis_step.y, false), Z_APPLY_STEP(axis_step.z, false), + I_APPLY_STEP(axis_step.i, false), J_APPLY_STEP(axis_step.j, false), K_APPLY_STEP(axis_step.k, false), + U_APPLY_STEP(axis_step.u, false), V_APPLY_STEP(axis_step.v, false), W_APPLY_STEP(axis_step.w, false) ); + if (TERN1(FTM_OPTIMIZE_DIR_STATES, last_set_direction != last_direction_bits)) { + // Apply directions (generally applying to the entire linear move) + #define _FTM_APPLY_DIR(AXIS) if (TERN1(FTM_OPTIMIZE_DIR_STATES, last_direction_bits[_AXIS(A)] != last_set_direction[_AXIS(AXIS)])) \ + SET_STEP_DIR(AXIS); + LOGICAL_AXIS_MAP(_FTM_APPLY_DIR); + + TERN_(FTM_OPTIMIZE_DIR_STATES, last_set_direction = last_direction_bits); + + // Any DIR change requires a wait period + DIR_WAIT_AFTER(); + } + + // Start step pulses. Edge stepping will toggle the STEP pin. + #define _FTM_STEP_START(AXIS) AXIS##_APPLY_STEP(_FTM_STEP(AXIS), false); + LOGICAL_AXIS_MAP(_FTM_STEP_START); + + // Apply steps via I2S TERN_(I2S_STEPPER_STREAM, i2s_push_sample()); // Begin waiting for the minimum pulse duration START_TIMED_PULSE(); // Update step counts - LOGICAL_AXIS_CODE( - if (axis_did_move.e) count_position.e += last_direction_bits.e ? 1 : -1, if (axis_did_move.x) count_position.x += last_direction_bits.x ? 1 : -1, - if (axis_did_move.y) count_position.y += last_direction_bits.y ? 1 : -1, if (axis_did_move.z) count_position.z += last_direction_bits.z ? 1 : -1, - if (axis_did_move.i) count_position.i += last_direction_bits.i ? 1 : -1, if (axis_did_move.j) count_position.j += last_direction_bits.j ? 1 : -1, - if (axis_did_move.k) count_position.k += last_direction_bits.k ? 1 : -1, if (axis_did_move.u) count_position.u += last_direction_bits.u ? 1 : -1, - if (axis_did_move.v) count_position.v += last_direction_bits.v ? 1 : -1, if (axis_did_move.w) count_position.w += last_direction_bits.w ? 1 : -1 - ); + #define _FTM_STEP_COUNT(AXIS) if (axis_step[_AXIS(AXIS)]) count_position[_AXIS(AXIS)] += direction_bits[_AXIS(AXIS)] ? 1 : -1; + LOGICAL_AXIS_MAP(_FTM_STEP_COUNT); + // Provide EDGE flags for E stepper(s) #if HAS_EXTRUDERS #if ENABLED(E_DUAL_STEPPER_DRIVERS) constexpr bool e_axis_has_dedge = AXIS_HAS_DEDGE(E0) && AXIS_HAS_DEDGE(E1); @@ -3547,38 +3609,32 @@ void Stepper::report_positions() { // Only wait for axes without edge stepping const bool any_wait = false LOGICAL_AXIS_GANG( - || (!e_axis_has_dedge && axis_did_move.e), - || (!AXIS_HAS_DEDGE(X) && axis_did_move.x), || (!AXIS_HAS_DEDGE(Y) && axis_did_move.y), || (!AXIS_HAS_DEDGE(Z) && axis_did_move.z), - || (!AXIS_HAS_DEDGE(I) && axis_did_move.i), || (!AXIS_HAS_DEDGE(J) && axis_did_move.j), || (!AXIS_HAS_DEDGE(K) && axis_did_move.k), - || (!AXIS_HAS_DEDGE(U) && axis_did_move.u), || (!AXIS_HAS_DEDGE(V) && axis_did_move.v), || (!AXIS_HAS_DEDGE(W) && axis_did_move.w) + || (!e_axis_has_dedge && axis_step.e), + || (!AXIS_HAS_DEDGE(X) && axis_step.x), || (!AXIS_HAS_DEDGE(Y) && axis_step.y), || (!AXIS_HAS_DEDGE(Z) && axis_step.z), + || (!AXIS_HAS_DEDGE(I) && axis_step.i), || (!AXIS_HAS_DEDGE(J) && axis_step.j), || (!AXIS_HAS_DEDGE(K) && axis_step.k), + || (!AXIS_HAS_DEDGE(U) && axis_step.u), || (!AXIS_HAS_DEDGE(V) && axis_step.v), || (!AXIS_HAS_DEDGE(W) && axis_step.w) ); // Allow pulses to be registered by stepper drivers if (any_wait) AWAIT_HIGH_PULSE(); // Stop pulses. Axes with DEDGE will do nothing, assuming STEP_STATE_* is HIGH - LOGICAL_AXIS_CODE( - E_APPLY_STEP(!STEP_STATE_E, false), - X_APPLY_STEP(!STEP_STATE_X, false), Y_APPLY_STEP(!STEP_STATE_Y, false), Z_APPLY_STEP(!STEP_STATE_Z, false), - I_APPLY_STEP(!STEP_STATE_I, false), J_APPLY_STEP(!STEP_STATE_J, false), K_APPLY_STEP(!STEP_STATE_K, false), - U_APPLY_STEP(!STEP_STATE_U, false), V_APPLY_STEP(!STEP_STATE_V, false), W_APPLY_STEP(!STEP_STATE_W, false) - ); - - // Check endstops on every step - IF_DISABLED(ENDSTOP_INTERRUPTS_FEATURE, endstops.update()); + #define _FTM_STEP_STOP(AXIS) AXIS##_APPLY_STEP(!STEP_STATE_##AXIS, false); + LOGICAL_AXIS_MAP(_FTM_STEP_STOP); // Also handle babystepping here TERN_(BABYSTEPPING, if (babystep.has_steps()) babystepping_isr()); } // Stepper::ftMotion_stepper + // Called from FTMotion::loop (when !blockProcRdy) which is called from Marlin idle() void Stepper::ftMotion_blockQueueUpdate() { if (current_block) { - // If the current block is not done processing, return right away + // If the current block is not done processing, return right away. + // A block is done processing when the command buffer has been + // filled, not necessarily when it's done running. if (!ftMotion.getBlockProcDn()) return; - - axis_did_move.reset(); planner.release_current_block(); } @@ -3586,10 +3642,37 @@ void Stepper::report_positions() { current_block = planner.get_current_block(); if (current_block) { - // Sync block? Sync the stepper counts and return - while (current_block->is_sync()) { - TERN_(LASER_FEATURE, if (!(current_block->is_fan_sync() || current_block->is_pwr_sync()))) _set_position(current_block->position); + // Sync position, fan power, laser power? + while (current_block->is_sync()) { + + #if 0 + + // TODO: Implement compatible sync blocks with FT Motion commands, + // perhaps by setting a FT_BIT_SYNC flag that holds the current block + // until it is processed by ftMotion_stepper + + // Set laser power + #if ENABLED(LASER_POWER_SYNC) + if (cutter.cutter_mode == CUTTER_MODE_CONTINUOUS) { + if (current_block->is_sync_pwr()) { + planner.laser_inline.status.isSyncPower = true; + cutter.apply_power(current_block->laser.power); + } + } + #endif + + // Set "fan speeds" for a laser module + #if ENABLED(LASER_SYNCHRONOUS_M106_M107) + if (current_block->is_sync_fan()) planner.sync_fan_speeds(current_block->fan_speed); + #endif + + // Set position + if (current_block->is_sync_pos()) _set_position(current_block->position); + + #endif + + // Done with this block planner.release_current_block(); // Try to get a new block @@ -3597,6 +3680,17 @@ void Stepper::report_positions() { return; // No queued blocks. } + // Some kinematics track axis motion in HX, HY, HZ + #if ANY(CORE_IS_XY, CORE_IS_XZ, MARKFORGED_XY, MARKFORGED_YX) + last_direction_bits.hx = current_block->direction_bits.hx; + #endif + #if ANY(CORE_IS_XY, CORE_IS_YZ, MARKFORGED_XY, MARKFORGED_YX) + last_direction_bits.hy = current_block->direction_bits.hy; + #endif + #if ANY(CORE_IS_XZ, CORE_IS_YZ) + last_direction_bits.hz = current_block->direction_bits.hz; + #endif + ftMotion.startBlockProc(); return; } diff --git a/Marlin/src/module/stepper.h b/Marlin/src/module/stepper.h index d69d007366..82b41290bf 100644 --- a/Marlin/src/module/stepper.h +++ b/Marlin/src/module/stepper.h @@ -684,6 +684,9 @@ class Stepper { // Calculate timing interval and steps-per-ISR for the given step rate static hal_timer_t calc_multistep_timer_interval(uint32_t step_rate); + // Evaluate axis motions and set bits in axis_did_move + static void set_axis_moved_for_current_block(); + #if ENABLED(NONLINEAR_EXTRUSION) static void calc_nonlinear_e(uint32_t step_rate); #endif diff --git a/Marlin/src/module/temperature.cpp b/Marlin/src/module/temperature.cpp index a1fe14c75d..95d2da38f1 100644 --- a/Marlin/src/module/temperature.cpp +++ b/Marlin/src/module/temperature.cpp @@ -806,7 +806,7 @@ volatile bool Temperature::raw_temps_ready = false; } } SHV((bias + d) >> 1); - TERN_(HAS_STATUS_MESSAGE, ui.status_printf(0, F(S_FMT " %i/%i"), GET_TEXT(MSG_PID_CYCLE), cycles, ncycles)); + TERN_(HAS_STATUS_MESSAGE, ui.status_printf(0, F(S_FMT " %i/%i"), GET_TEXT_F(MSG_PID_CYCLE), cycles, ncycles)); cycles++; minT = target; } @@ -1195,7 +1195,7 @@ volatile bool Temperature::raw_temps_ready = false; // Determine ambient temperature. SERIAL_ECHOLNPGM(STR_MPC_COOLING_TO_AMBIENT); - TERN_(EXTENSIBLE_UI, ExtUI::onMPCTuning(ExtUI::mpcresult_t::MPCTEMP_START)); + TERN_(EXTENSIBLE_UI, ExtUI::onMPCTuning(ExtUI::mpcresult_t::MPC_STARTED)); TERN(DWIN_LCD_PROUI, LCD_ALERTMESSAGE(MSG_MPC_COOLING_TO_AMBIENT), LCD_MESSAGE(MSG_COOLING)); if (tuner.measure_ambient_temp() != MPC_autotuner::MeasurementState::SUCCESS) return; @@ -2019,7 +2019,7 @@ void Temperature::mintemp_error(const heater_id_t heater_id OPTARG(ERR_INCLUDE_T if (watch_cooler.elapsed(ms)) { // Time to check the cooler? const auto deg = degCooler(); if (deg > watch_cooler.target) // Failed to decrease enough? - _TEMP_ERROR(H_COOLER, GET_EN_TEXT_F(MSG_ERR_COOLING_FAILED), MSG_ERR_COOLING_FAILED, deg); + _TEMP_ERROR(H_COOLER, GET_TEXT_F(MSG_ERR_COOLING_FAILED), MSG_ERR_COOLING_FAILED, deg); else start_watching_cooler(); // Start again if the target is still far off } @@ -4419,6 +4419,7 @@ void Temperature::isr() { #if ENABLED(AUTO_REPORT_TEMPERATURES) AutoReporter Temperature::auto_reporter; void Temperature::AutoReportTemp::report() { + if (wait_for_heatup) return; print_heater_states(active_extruder OPTARG(HAS_TEMP_REDUNDANT, ENABLED(AUTO_REPORT_REDUNDANT))); SERIAL_EOL(); } @@ -4433,7 +4434,7 @@ void Temperature::isr() { #else F("E1 " S_FMT) #endif - , heating ? GET_TEXT(MSG_HEATING) : GET_TEXT(MSG_COOLING) + , heating ? GET_TEXT_F(MSG_HEATING) : GET_TEXT_F(MSG_COOLING) ); if (isM104) { diff --git a/Marlin/src/module/temperature.h b/Marlin/src/module/temperature.h index 088a17ec1b..16d4a38e08 100644 --- a/Marlin/src/module/temperature.h +++ b/Marlin/src/module/temperature.h @@ -204,31 +204,35 @@ typedef struct { float p, i, d, c, f; } raw_pidcf_t; float get_pid_output(const float target, const float current) { const float pid_error = target - current; + float output_pow; if (!target || pid_error < -(PID_FUNCTIONAL_RANGE)) { pid_reset = true; - return 0; + output_pow = 0; } else if (pid_error > PID_FUNCTIONAL_RANGE) { pid_reset = true; - return MAX_POW; + output_pow = MAX_POW; } + else { + if (pid_reset) { + pid_reset = false; + temp_iState = 0.0; + work_d = 0.0; + } - if (pid_reset) { - pid_reset = false; - temp_iState = 0.0; - work_d = 0.0; + const float max_power_over_i_gain = float(MAX_POW) / Ki - float(MIN_POW); + temp_iState = constrain(temp_iState + pid_error, 0, max_power_over_i_gain); + + work_p = Kp * pid_error; + work_i = Ki * temp_iState; + work_d = work_d + PID_K2 * (Kd * (temp_dState - current) - work_d); + + output_pow = constrain(work_p + work_i + work_d + float(MIN_POW), 0, MAX_POW); } - const float max_power_over_i_gain = float(MAX_POW) / Ki - float(MIN_POW); - temp_iState = constrain(temp_iState + pid_error, 0, max_power_over_i_gain); - - work_p = Kp * pid_error; - work_i = Ki * temp_iState; - work_d = work_d + PID_K2 * (Kd * (temp_dState - current) - work_d); - temp_dState = current; - return constrain(work_p + work_i + work_d + float(MIN_POW), 0, MAX_POW); + return output_pow; } }; diff --git a/Marlin/src/pins/gd32f1/pins_SOVOL_V131.h b/Marlin/src/pins/gd32f1/pins_SOVOL_V131.h index e92c24b86c..2f6dd12c49 100644 --- a/Marlin/src/pins/gd32f1/pins_SOVOL_V131.h +++ b/Marlin/src/pins/gd32f1/pins_SOVOL_V131.h @@ -62,6 +62,24 @@ #define E0_SERIAL_TX_PIN PC14 #define E0_SERIAL_RX_PIN PC14 + // Default TMC slave addresses + #ifndef X_SLAVE_ADDRESS + #define X_SLAVE_ADDRESS 3 + #endif + #ifndef Y_SLAVE_ADDRESS + #define Y_SLAVE_ADDRESS 3 + #endif + #ifndef Z_SLAVE_ADDRESS + #define Z_SLAVE_ADDRESS 3 + #endif + #ifndef E0_SLAVE_ADDRESS + #define E0_SLAVE_ADDRESS 3 + #endif + static_assert(X_SLAVE_ADDRESS == 3, "X_SLAVE_ADDRESS must be 3 for BOARD_SOVOL_V131."); + static_assert(Y_SLAVE_ADDRESS == 3, "Y_SLAVE_ADDRESS must be 3 for BOARD_SOVOL_V131."); + static_assert(Z_SLAVE_ADDRESS == 3, "Z_SLAVE_ADDRESS must be 3 for BOARD_SOVOL_V131."); + static_assert(E0_SLAVE_ADDRESS == 3, "E0_SLAVE_ADDRESS must be 3 for BOARD_SOVOL_V131."); + // Reduce baud rate to improve software serial reliability #ifndef TMC_BAUD_RATE #define TMC_BAUD_RATE 19200 diff --git a/Marlin/src/pins/hc32f4/pins_AQUILA_101.h b/Marlin/src/pins/hc32f4/pins_AQUILA_101.h index 2834d56c96..4716984933 100644 --- a/Marlin/src/pins/hc32f4/pins_AQUILA_101.h +++ b/Marlin/src/pins/hc32f4/pins_AQUILA_101.h @@ -45,10 +45,13 @@ #endif // -// Release PB4 (Y_ENABLE_PIN) from JTAG NRST role +// Release JTAG pins but keep SWD enabled +// - PA15 (JTDI / USART2 RX) +// - PB3 (JTDO / E0_DIR) +// - PB4 (NJTRST / E0_STEP) // //#define DISABLE_DEBUG -//#define DISABLE_JTAG +#define DISABLE_JTAG // // EEPROM diff --git a/Marlin/src/pins/hc32f4/pins_CREALITY_ENDER2P_V24S4.h b/Marlin/src/pins/hc32f4/pins_CREALITY_ENDER2P_V24S4.h index 89c3136620..3eed3951d2 100644 --- a/Marlin/src/pins/hc32f4/pins_CREALITY_ENDER2P_V24S4.h +++ b/Marlin/src/pins/hc32f4/pins_CREALITY_ENDER2P_V24S4.h @@ -46,10 +46,13 @@ #endif // -// Release PB4 (Y_ENABLE_PIN) from JTAG NRST role +// Release JTAG pins but keep SWD enabled +// - PA15 (JTDI / E0_DIR_PIN) +// - PB3 (JTDO / E0_STEP_PIN) +// - PB4 (NJTRST / E0_ENABLE_PIN) // //#define DISABLE_DEBUG -//#define DISABLE_JTAG +#define DISABLE_JTAG // // EEPROM diff --git a/Marlin/src/pins/lpc1768/pins_MKS_SBASE.h b/Marlin/src/pins/lpc1768/pins_MKS_SBASE.h index 8a39e2790a..dbacb0fa26 100644 --- a/Marlin/src/pins/lpc1768/pins_MKS_SBASE.h +++ b/Marlin/src/pins/lpc1768/pins_MKS_SBASE.h @@ -211,19 +211,19 @@ * ------ ------ * EXP1 EXP2 */ -#define EXP1_01_PIN P1_31 -#define EXP1_02_PIN P1_30 -#define EXP1_03_PIN P0_18 -#define EXP1_04_PIN P0_16 -#define EXP1_05_PIN P0_15 +#define EXP1_01_PIN P1_31 +#define EXP1_02_PIN P1_30 +#define EXP1_03_PIN P0_18 +#define EXP1_04_PIN P0_16 +#define EXP1_05_PIN P0_15 -#define EXP2_01_PIN P0_08 -#define EXP2_02_PIN P0_07 -#define EXP2_03_PIN P3_25 -#define EXP2_04_PIN P0_28 -#define EXP2_05_PIN P3_26 -#define EXP2_06_PIN P0_09 -#define EXP2_07_PIN P0_27 +#define EXP2_01_PIN P0_08 +#define EXP2_02_PIN P0_07 +#define EXP2_03_PIN P3_25 +#define EXP2_04_PIN P0_28 +#define EXP2_05_PIN P3_26 +#define EXP2_06_PIN P0_09 +#define EXP2_07_PIN P0_27 // // LCD / Controller diff --git a/Marlin/src/pins/pins_postprocess.h b/Marlin/src/pins/pins_postprocess.h index e6fdac2155..ac81eb3f25 100644 --- a/Marlin/src/pins/pins_postprocess.h +++ b/Marlin/src/pins/pins_postprocess.h @@ -1247,7 +1247,7 @@ #define J_STEP_PIN _EPIN(J_E_INDEX, STEP) #define J_DIR_PIN _EPIN(J_E_INDEX, DIR) #define J_ENABLE_PIN _EPIN(J_E_INDEX, ENABLE) - #if I_E_INDEX >= MAX_E_STEPPERS || !PIN_EXISTS(J_STEP) + #if J_E_INDEX >= MAX_E_STEPPERS || !PIN_EXISTS(J_STEP) #error "No E stepper plug left for J!" #else #define AUTO_ASSIGNED_J_STEPPER 1 @@ -1417,7 +1417,7 @@ #define U_STEP_PIN _EPIN(U_E_INDEX, STEP) #define U_DIR_PIN _EPIN(U_E_INDEX, DIR) #define U_ENABLE_PIN _EPIN(U_E_INDEX, ENABLE) - #if M_E_INDEX >= MAX_E_STEPPERS || !PIN_EXISTS(U_STEP) + #if U_E_INDEX >= MAX_E_STEPPERS || !PIN_EXISTS(U_STEP) #error "No E stepper plug left for U!" #else #define AUTO_ASSIGNED_U_STEPPER 1 diff --git a/Marlin/src/pins/ramps/pins_RAMPS.h b/Marlin/src/pins/ramps/pins_RAMPS.h index 0195f3a1bc..3868439102 100644 --- a/Marlin/src/pins/ramps/pins_RAMPS.h +++ b/Marlin/src/pins/ramps/pins_RAMPS.h @@ -320,17 +320,29 @@ #endif // -// TMC software SPI +// TMC SPI // #if HAS_TMC_SPI - #ifndef TMC_SPI_MOSI - #define TMC_SPI_MOSI AUX2_09 - #endif - #ifndef TMC_SPI_MISO - #define TMC_SPI_MISO AUX2_07 - #endif - #ifndef TMC_SPI_SCK - #define TMC_SPI_SCK AUX2_05 + #if ENABLED(TMC_USE_SW_SPI) + #ifndef TMC_SPI_MOSI + #define TMC_SPI_MOSI AUX2_09 + #endif + #ifndef TMC_SPI_MISO + #define TMC_SPI_MISO AUX2_07 + #endif + #ifndef TMC_SPI_SCK + #define TMC_SPI_SCK AUX2_05 + #endif + #else + #ifndef TMC_SPI_MOSI + #define TMC_SPI_MOSI AUX3_04 + #endif + #ifndef TMC_SPI_MISO + #define TMC_SPI_MISO AUX3_03 + #endif + #ifndef TMC_SPI_SCK + #define TMC_SPI_SCK AUX3_05 + #endif #endif #endif diff --git a/Marlin/src/pins/samd/pins_BRICOLEMON_LITE_V1_0.h b/Marlin/src/pins/samd/pins_BRICOLEMON_LITE_V1_0.h index 87f83a5c96..d2ad928066 100644 --- a/Marlin/src/pins/samd/pins_BRICOLEMON_LITE_V1_0.h +++ b/Marlin/src/pins/samd/pins_BRICOLEMON_LITE_V1_0.h @@ -569,9 +569,15 @@ #if HAS_TMC_UART /** - * Address for the UART Configuration of the TMC2209. Override in Configuration files. - * To test TMC2209 Steppers enable TMC_DEBUG in Configuration_adv.h and test the M122 command with voltage on the steppers. + * TMC2208/TMC2209 stepper drivers + * It seems to work perfectly fine on Software Serial, if an advanced user wants to test, you could use the SAMD51 Serial1 and Serial 2. Be careful with the Sercom configurations. */ + //#define X_HARDWARE_SERIAL Serial1 + //#define Y_HARDWARE_SERIAL Serial1 + //#define Z_HARDWARE_SERIAL Serial1 + //#define E0_HARDWARE_SERIAL Serial1 + + // Default TMC slave addresses #ifndef X_SLAVE_ADDRESS #define X_SLAVE_ADDRESS 0b00 #endif @@ -584,18 +590,15 @@ #ifndef E0_SLAVE_ADDRESS #define E0_SLAVE_ADDRESS 0b11 #endif + static_assert(X_SLAVE_ADDRESS == 0b00, "X_SLAVE_ADDRESS must be 0b00 for BOARD_BRICOLEMON_LITE_V1_0."); + static_assert(Y_SLAVE_ADDRESS == 0b01, "Y_SLAVE_ADDRESS must be 0b01 for BOARD_BRICOLEMON_LITE_V1_0."); + static_assert(Z_SLAVE_ADDRESS == 0b10, "Z_SLAVE_ADDRESS must be 0b10 for BOARD_BRICOLEMON_LITE_V1_0."); + static_assert(E0_SLAVE_ADDRESS == 0b11, "E0_SLAVE_ADDRESS must be 0b11 for BOARD_BRICOLEMON_LITE_V1_0."); - /** - * TMC2208/TMC2209 stepper drivers - * It seems to work perfectly fine on Software Serial, if an advanced user wants to test, you could use the SAMD51 Serial1 and Serial 2. Be careful with the Sercom configurations. - */ - //#define X_HARDWARE_SERIAL Serial1 - //#define Y_HARDWARE_SERIAL Serial1 - //#define Z_HARDWARE_SERIAL Serial1 - //#define E0_HARDWARE_SERIAL Serial1 - - // This is the stable default value after testing, but, higher UART rates could be configured, remeber to test the Steppers with the M122 command to check if everything works. - #define TMC_BAUD_RATE 250000 + // Reduce baud rate to improve software serial reliability + #ifndef TMC_BAUD_RATE + #define TMC_BAUD_RATE 19200 // 250000 + #endif // // Software serial diff --git a/Marlin/src/pins/samd/pins_BRICOLEMON_V1_0.h b/Marlin/src/pins/samd/pins_BRICOLEMON_V1_0.h index d55669ac90..8dfad8dc56 100644 --- a/Marlin/src/pins/samd/pins_BRICOLEMON_V1_0.h +++ b/Marlin/src/pins/samd/pins_BRICOLEMON_V1_0.h @@ -620,11 +620,19 @@ #endif #if HAS_TMC_UART - /** - * Address for the UART Configuration of the TMC2209. Override in Configuration files. - * To test TMC2209 Steppers enable TMC_DEBUG in Configuration_adv.h and test the M122 command with voltage on the steppers. + * TMC2208/TMC2209 stepper drivers + * It seems to work perfectly fine on Software Serial, if an advanced user wants to test, you could use the SAMD51 Serial1 and Serial 2. Be careful with the Sercom configurations. + * Steppers 1,2,3,4 (X,Y,Z,E0) are on the Serial1, Sercom (RX = 0, TX = 1), extra stepper 5 (E1 or any axis you want) is on Serial2, Sercom (RX = 17, TX = 16) */ + + //#define X_HARDWARE_SERIAL Serial1 + //#define Y_HARDWARE_SERIAL Serial1 + //#define Z_HARDWARE_SERIAL Serial1 + //#define E0_HARDWARE_SERIAL Serial1 + //#define E1_HARDWARE_SERIAL Serial2 + + // Default TMC slave addresses #ifndef X_SLAVE_ADDRESS #define X_SLAVE_ADDRESS 0b00 #endif @@ -640,20 +648,16 @@ #ifndef E1_SLAVE_ADDRESS #define E1_SLAVE_ADDRESS 0b00 #endif + static_assert(X_SLAVE_ADDRESS == 0b00, "X_SLAVE_ADDRESS must be 0b00 for BOARD_BRICOLEMON_V1_0."); + static_assert(Y_SLAVE_ADDRESS == 0b01, "Y_SLAVE_ADDRESS must be 0b01 for BOARD_BRICOLEMON_V1_0."); + static_assert(Z_SLAVE_ADDRESS == 0b10, "Z_SLAVE_ADDRESS must be 0b10 for BOARD_BRICOLEMON_V1_0."); + static_assert(E0_SLAVE_ADDRESS == 0b11, "E0_SLAVE_ADDRESS must be 0b11 for BOARD_BRICOLEMON_V1_0."); + static_assert(E1_SLAVE_ADDRESS == 0b00, "E1_SLAVE_ADDRESS must be 0b00 for BOARD_BRICOLEMON_V1_0."); - /** - * TMC2208/TMC2209 stepper drivers - * It seems to work perfectly fine on Software Serial, if an advanced user wants to test, you could use the SAMD51 Serial1 and Serial 2. Be careful with the Sercom configurations. - * Steppers 1,2,3,4 (X,Y,Z,E0) are on the Serial1, Sercom (RX = 0, TX = 1), extra stepper 5 (E1 or any axis you want) is on Serial2, Sercom (RX = 17, TX = 16) - */ - - //#define X_HARDWARE_SERIAL Serial1 - //#define Y_HARDWARE_SERIAL Serial1 - //#define Z_HARDWARE_SERIAL Serial1 - //#define E0_HARDWARE_SERIAL Serial1 - //#define E1_HARDWARE_SERIAL Serial2 - - #define TMC_BAUD_RATE 250000 + // Reduce baud rate to improve software serial reliability + #ifndef TMC_BAUD_RATE + #define TMC_BAUD_RATE 19200 // 250000 + #endif // // Software serial diff --git a/Marlin/src/pins/samd/pins_MINITRONICS20.h b/Marlin/src/pins/samd/pins_MINITRONICS20.h index 2a450698d1..85583b62b9 100644 --- a/Marlin/src/pins/samd/pins_MINITRONICS20.h +++ b/Marlin/src/pins/samd/pins_MINITRONICS20.h @@ -497,11 +497,19 @@ #define SD_DETECT_PIN 22 #if HAS_TMC_UART - /** - * TMC2209 UART Address. Override in Configuration files. - * To test TMC2209 Steppers enable TMC_DEBUG and test M122 with voltage on the steppers. + * TMC2208/TMC2209 stepper drivers + * Seems to work fine with Software Serial. If you want to test, use SAMD51 Serial1 and Serial2. Be careful with the Sercom configurations. + * Steppers 1,2,3,4 (X,Y,Z,E0) are on Serial1, Sercom (RX=0, TX=1), extra stepper 5 (E1 or any axis you want) is on Serial2, Sercom (RX=17, TX=16) */ + + //#define X_HARDWARE_SERIAL Serial1 + //#define Y_HARDWARE_SERIAL Serial1 + //#define Z_HARDWARE_SERIAL Serial1 + //#define E0_HARDWARE_SERIAL Serial1 + //#define E1_HARDWARE_SERIAL Serial2 + + // Default TMC slave addresses #ifndef X_SLAVE_ADDRESS #define X_SLAVE_ADDRESS 0b00 #endif @@ -517,20 +525,16 @@ #ifndef E1_SLAVE_ADDRESS #define E1_SLAVE_ADDRESS 0b00 #endif + static_assert(X_SLAVE_ADDRESS == 0b00, "X_SLAVE_ADDRESS must be 0b00 for BOARD_MINITRONICS20."); + static_assert(Y_SLAVE_ADDRESS == 0b01, "Y_SLAVE_ADDRESS must be 0b01 for BOARD_MINITRONICS20."); + static_assert(Z_SLAVE_ADDRESS == 0b10, "Z_SLAVE_ADDRESS must be 0b10 for BOARD_MINITRONICS20."); + static_assert(E0_SLAVE_ADDRESS == 0b11, "E0_SLAVE_ADDRESS must be 0b11 for BOARD_MINITRONICS20."); + static_assert(E1_SLAVE_ADDRESS == 0b00, "E1_SLAVE_ADDRESS must be 0b00 for BOARD_MINITRONICS20."); - /** - * TMC2208/TMC2209 stepper drivers - * Seems to work fine with Software Serial. If you want to test, use SAMD51 Serial1 and Serial2. Be careful with the Sercom configurations. - * Steppers 1,2,3,4 (X,Y,Z,E0) are on Serial1, Sercom (RX=0, TX=1), extra stepper 5 (E1 or any axis you want) is on Serial2, Sercom (RX=17, TX=16) - */ - - //#define X_HARDWARE_SERIAL Serial1 - //#define Y_HARDWARE_SERIAL Serial1 - //#define Z_HARDWARE_SERIAL Serial1 - //#define E0_HARDWARE_SERIAL Serial1 - //#define E1_HARDWARE_SERIAL Serial2 - - #define TMC_BAUD_RATE 250000 + // Reduce baud rate to improve software serial reliability + #ifndef TMC_BAUD_RATE + #define TMC_BAUD_RATE 19200 // 250000 + #endif // // Software serial diff --git a/Marlin/src/pins/sanguino/pins_MELZI_CREALITY.h b/Marlin/src/pins/sanguino/pins_MELZI_CREALITY.h index 2915c77d70..ba3c6767b2 100644 --- a/Marlin/src/pins/sanguino/pins_MELZI_CREALITY.h +++ b/Marlin/src/pins/sanguino/pins_MELZI_CREALITY.h @@ -101,7 +101,7 @@ #endif #if PIN_EXISTS(BEEPER) && (SERVO0_PIN == BEEPER_PIN || FIL_RUNOUT_PIN == BEEPER_PIN) #undef BEEPER_PIN - #define BEEPER_PIN -1 + #define BEEPER_PIN -1 #endif /** diff --git a/Marlin/src/pins/sanguino/pins_SANGUINOLOLU_11.h b/Marlin/src/pins/sanguino/pins_SANGUINOLOLU_11.h index a381088ecf..74d2b5549b 100644 --- a/Marlin/src/pins/sanguino/pins_SANGUINOLOLU_11.h +++ b/Marlin/src/pins/sanguino/pins_SANGUINOLOLU_11.h @@ -108,7 +108,7 @@ #endif #define E0_ENABLE_PIN 4 #else - #if !HAS_CUTTER && !ALL(HAS_WIRED_LCD, IS_NEWPANEL) // Use IO Header + #if !HAS_CUTTER && !ALL(HAS_WIRED_LCD, IS_NEWPANEL) // Use IO Header #define CASE_LIGHT_PIN 4 // Hardware PWM - see if IO Header is available #endif #endif diff --git a/Marlin/src/pins/stm32f1/pins_BTT_SKR_CR6.h b/Marlin/src/pins/stm32f1/pins_BTT_SKR_CR6.h index b6a3c4141f..725a3f9914 100644 --- a/Marlin/src/pins/stm32f1/pins_BTT_SKR_CR6.h +++ b/Marlin/src/pins/stm32f1/pins_BTT_SKR_CR6.h @@ -25,8 +25,9 @@ * BigTreeTech SKR CR-6 (STM32F103RET6) board pin assignments */ -#define DEFAULT_MACHINE_NAME "Creality3D" +#define DEFAULT_MACHINE_NAME "Creality CR-6 SE" #define BOARD_INFO_NAME "BTT SKR CR-6" +#define BOARD_WEBSITE_URL "github.com/bigtreetech/BIGTREETECH-SKR-CR6" #include "env_validate.h" @@ -145,17 +146,21 @@ // Default TMC slave addresses #ifndef X_SLAVE_ADDRESS - #define X_SLAVE_ADDRESS 0 + #define X_SLAVE_ADDRESS 0 #endif #ifndef Y_SLAVE_ADDRESS - #define Y_SLAVE_ADDRESS 1 + #define Y_SLAVE_ADDRESS 1 #endif #ifndef Z_SLAVE_ADDRESS - #define Z_SLAVE_ADDRESS 2 + #define Z_SLAVE_ADDRESS 2 #endif #ifndef E0_SLAVE_ADDRESS - #define E0_SLAVE_ADDRESS 3 + #define E0_SLAVE_ADDRESS 3 #endif + static_assert(X_SLAVE_ADDRESS == 0, "X_SLAVE_ADDRESS must be 0 for BOARD_BTT_SKR_CR6."); + static_assert(Y_SLAVE_ADDRESS == 1, "Y_SLAVE_ADDRESS must be 1 for BOARD_BTT_SKR_CR6."); + static_assert(Z_SLAVE_ADDRESS == 2, "Z_SLAVE_ADDRESS must be 2 for BOARD_BTT_SKR_CR6."); + static_assert(E0_SLAVE_ADDRESS == 3, "E0_SLAVE_ADDRESS must be 3 for BOARD_BTT_SKR_CR6."); #endif // diff --git a/Marlin/src/pins/stm32f1/pins_BTT_SKR_MINI_E3_V1_0.h b/Marlin/src/pins/stm32f1/pins_BTT_SKR_MINI_E3_V1_0.h index a09da02e15..7b780f7c9f 100644 --- a/Marlin/src/pins/stm32f1/pins_BTT_SKR_MINI_E3_V1_0.h +++ b/Marlin/src/pins/stm32f1/pins_BTT_SKR_MINI_E3_V1_0.h @@ -24,6 +24,7 @@ #include "pins_BTT_SKR_MINI_E3_common.h" #define BOARD_INFO_NAME "BTT SKR Mini E3 V1.0" +#define BOARD_WEBSITE_URL "github.com/bigtreetech/BIGTREETECH-SKR-mini-E3/tree/master/hardware/BIGTREETECH-SKR-mini-E3%20V1.0" /** * TMC220x stepper drivers @@ -37,15 +38,19 @@ // Default TMC slave addresses #ifndef X_SLAVE_ADDRESS - #define X_SLAVE_ADDRESS 0 + #define X_SLAVE_ADDRESS 0 #endif #ifndef Y_SLAVE_ADDRESS - #define Y_SLAVE_ADDRESS 2 + #define Y_SLAVE_ADDRESS 2 #endif #ifndef Z_SLAVE_ADDRESS - #define Z_SLAVE_ADDRESS 1 + #define Z_SLAVE_ADDRESS 1 #endif #ifndef E0_SLAVE_ADDRESS - #define E0_SLAVE_ADDRESS 3 + #define E0_SLAVE_ADDRESS 3 #endif + static_assert(X_SLAVE_ADDRESS == 0, "X_SLAVE_ADDRESS must be 0 for BOARD_BTT_SKR_MINI_E3_V1_0."); + static_assert(Y_SLAVE_ADDRESS == 2, "Y_SLAVE_ADDRESS must be 2 for BOARD_BTT_SKR_MINI_E3_V1_0."); + static_assert(Z_SLAVE_ADDRESS == 1, "Z_SLAVE_ADDRESS must be 1 for BOARD_BTT_SKR_MINI_E3_V1_0."); + static_assert(E0_SLAVE_ADDRESS == 3, "E0_SLAVE_ADDRESS must be 3 for BOARD_BTT_SKR_MINI_E3_V1_0."); #endif diff --git a/Marlin/src/pins/stm32f1/pins_BTT_SKR_MINI_E3_V2_0.h b/Marlin/src/pins/stm32f1/pins_BTT_SKR_MINI_E3_V2_0.h index c182f2febe..d0f856b123 100644 --- a/Marlin/src/pins/stm32f1/pins_BTT_SKR_MINI_E3_V2_0.h +++ b/Marlin/src/pins/stm32f1/pins_BTT_SKR_MINI_E3_V2_0.h @@ -95,17 +95,21 @@ // Default TMC slave addresses #ifndef X_SLAVE_ADDRESS - #define X_SLAVE_ADDRESS 0 + #define X_SLAVE_ADDRESS 0 #endif #ifndef Y_SLAVE_ADDRESS - #define Y_SLAVE_ADDRESS 2 + #define Y_SLAVE_ADDRESS 2 #endif #ifndef Z_SLAVE_ADDRESS - #define Z_SLAVE_ADDRESS 1 + #define Z_SLAVE_ADDRESS 1 #endif #ifndef E0_SLAVE_ADDRESS - #define E0_SLAVE_ADDRESS 3 + #define E0_SLAVE_ADDRESS 3 #endif + static_assert(X_SLAVE_ADDRESS == 0, "X_SLAVE_ADDRESS must be 0 for BOARD_SKR_MINI_E3_V2_0."); + static_assert(Y_SLAVE_ADDRESS == 2, "Y_SLAVE_ADDRESS must be 2 for BOARD_SKR_MINI_E3_V2_0."); + static_assert(Z_SLAVE_ADDRESS == 1, "Z_SLAVE_ADDRESS must be 1 for BOARD_SKR_MINI_E3_V2_0."); + static_assert(E0_SLAVE_ADDRESS == 3, "E0_SLAVE_ADDRESS must be 3 for BOARD_SKR_MINI_E3_V2_0."); #endif // Pins for documentation and sanity checks only. diff --git a/Marlin/src/pins/stm32f1/pins_ERYONE_ERY32_MINI.h b/Marlin/src/pins/stm32f1/pins_ERYONE_ERY32_MINI.h index b18bd09de8..1a43f2e414 100644 --- a/Marlin/src/pins/stm32f1/pins_ERYONE_ERY32_MINI.h +++ b/Marlin/src/pins/stm32f1/pins_ERYONE_ERY32_MINI.h @@ -135,6 +135,8 @@ #define Y_HARDWARE_SERIAL MSerial4 #define Z_HARDWARE_SERIAL MSerial4 #define E0_HARDWARE_SERIAL MSerial4 + + // Default TMC slave addresses #ifndef X_SLAVE_ADDRESS #define X_SLAVE_ADDRESS 2 #endif @@ -147,6 +149,10 @@ #ifndef E0_SLAVE_ADDRESS #define E0_SLAVE_ADDRESS 0 #endif + static_assert(X_SLAVE_ADDRESS == 2, "X_SLAVE_ADDRESS must be 2 for BOARD_ERYONE_ERY32_MINI."); + static_assert(Y_SLAVE_ADDRESS == 3, "Y_SLAVE_ADDRESS must be 3 for BOARD_ERYONE_ERY32_MINI."); + static_assert(Z_SLAVE_ADDRESS == 1, "Z_SLAVE_ADDRESS must be 1 for BOARD_ERYONE_ERY32_MINI."); + static_assert(E0_SLAVE_ADDRESS == 0, "E0_SLAVE_ADDRESS must be 0 for BOARD_ERYONE_ERY32_MINI."); #endif // diff --git a/Marlin/src/pins/stm32f1/pins_FYSETC_AIO_II.h b/Marlin/src/pins/stm32f1/pins_FYSETC_AIO_II.h index 93ef7b75d4..fc9e24b790 100644 --- a/Marlin/src/pins/stm32f1/pins_FYSETC_AIO_II.h +++ b/Marlin/src/pins/stm32f1/pins_FYSETC_AIO_II.h @@ -24,13 +24,13 @@ #include "env_validate.h" #define BOARD_INFO_NAME "FYSETC AIO II" -#define BOARD_WEBSITE_URL "fysetc.com" +#define BOARD_WEBSITE_URL "github.com/FYSETC/FYSETC-AIO_II" #define BOARD_NO_NATIVE_USB #define RESET_STEPPERS_ON_MEDIA_INSERT #define DISABLE_JTAG -#define pins_v2_20190128 // new pins define +#define PINS_V2_20190128 // new pins define // Ignore temp readings during development. //#define BOGUS_TEMPERATURE_GRACE_PERIOD 2000 @@ -55,7 +55,7 @@ // // Filament runout // -#ifdef pins_v2_20190128 +#ifdef PINS_V2_20190128 #define FIL_RUNOUT_PIN PB15 #else #define FIL_RUNOUT_PIN PB5 @@ -69,7 +69,7 @@ #define X_ENABLE_PIN PA8 #define Y_STEP_PIN PB2 -#ifdef pins_v2_20190128 +#ifdef PINS_V2_20190128 #define Y_DIR_PIN PB3 #else #define Y_DIR_PIN PB0 @@ -97,20 +97,22 @@ // Default TMC slave addresses #ifndef X_SLAVE_ADDRESS - #define X_SLAVE_ADDRESS 0 + #define X_SLAVE_ADDRESS 0 #endif #ifndef Y_SLAVE_ADDRESS - #define Y_SLAVE_ADDRESS 1 + #define Y_SLAVE_ADDRESS 1 #endif #ifndef Z_SLAVE_ADDRESS - #define Z_SLAVE_ADDRESS 2 + #define Z_SLAVE_ADDRESS 2 #endif #ifndef E0_SLAVE_ADDRESS - #define E0_SLAVE_ADDRESS 3 + #define E0_SLAVE_ADDRESS 3 #endif + static_assert(X_SLAVE_ADDRESS == 0, "X_SLAVE_ADDRESS must be 0 for BOARD_FYSETC_AIO_II."); + static_assert(Y_SLAVE_ADDRESS == 1, "Y_SLAVE_ADDRESS must be 1 for BOARD_FYSETC_AIO_II."); + static_assert(Z_SLAVE_ADDRESS == 2, "Z_SLAVE_ADDRESS must be 2 for BOARD_FYSETC_AIO_II."); + static_assert(E0_SLAVE_ADDRESS == 3, "E0_SLAVE_ADDRESS must be 3 for BOARD_FYSETC_AIO_II."); - // The 4xTMC2209 module doesn't have a serial multiplexer and - // needs to set *_SLAVE_ADDRESS in Configuration_adv.h for X,Y,Z,E0 #if HAS_DRIVER(TMC2208) #define TMC_SERIAL_MULTIPLEXER #define SERIAL_MUL_PIN1 PB13 @@ -162,7 +164,7 @@ #if HAS_MARLINUI_U8GLIB #define DOGLCD_A0 PA15 - #ifdef pins_v2_20190128 + #ifdef PINS_V2_20190128 #define DOGLCD_CS PB5 #else #define DOGLCD_CS PB7 @@ -183,7 +185,7 @@ #define BTN_ENC PC12 #endif - #ifdef pins_v2_20190128 + #ifdef PINS_V2_20190128 #define LCD_RESET_PIN PB4 #ifndef RGB_LED_R_PIN #define RGB_LED_R_PIN PB0 diff --git a/Marlin/src/pins/stm32f1/pins_FYSETC_CHEETAH.h b/Marlin/src/pins/stm32f1/pins_FYSETC_CHEETAH.h index 49b6f25a47..042966cb3a 100644 --- a/Marlin/src/pins/stm32f1/pins_FYSETC_CHEETAH.h +++ b/Marlin/src/pins/stm32f1/pins_FYSETC_CHEETAH.h @@ -23,10 +23,8 @@ #include "env_validate.h" -#define DEFAULT_MACHINE_NAME "3D Printer" - #define BOARD_INFO_NAME "FYSETC Cheetah" -#define BOARD_WEBSITE_URL "fysetc.com" +#define BOARD_WEBSITE_URL "github.com/FYSETC/FYSETC-Cheetah" // Ignore temp readings during development. //#define BOGUS_TEMPERATURE_GRACE_PERIOD 2000 @@ -86,17 +84,21 @@ // Default TMC slave addresses #ifndef X_SLAVE_ADDRESS - #define X_SLAVE_ADDRESS 0 + #define X_SLAVE_ADDRESS 0 #endif #ifndef Y_SLAVE_ADDRESS - #define Y_SLAVE_ADDRESS 1 + #define Y_SLAVE_ADDRESS 1 #endif #ifndef Z_SLAVE_ADDRESS - #define Z_SLAVE_ADDRESS 2 + #define Z_SLAVE_ADDRESS 2 #endif #ifndef E0_SLAVE_ADDRESS - #define E0_SLAVE_ADDRESS 3 + #define E0_SLAVE_ADDRESS 3 #endif + static_assert(X_SLAVE_ADDRESS == 0, "X_SLAVE_ADDRESS must be 0 for BOARD_FYSETC_CHEETAH."); + static_assert(Y_SLAVE_ADDRESS == 1, "Y_SLAVE_ADDRESS must be 1 for BOARD_FYSETC_CHEETAH."); + static_assert(Z_SLAVE_ADDRESS == 2, "Z_SLAVE_ADDRESS must be 2 for BOARD_FYSETC_CHEETAH."); + static_assert(E0_SLAVE_ADDRESS == 3, "E0_SLAVE_ADDRESS must be 3 for BOARD_FYSETC_CHEETAH."); #endif // diff --git a/Marlin/src/pins/stm32f4/pins_BTT_SKR_MINI_E3_V3_0_1.h b/Marlin/src/pins/stm32f4/pins_BTT_SKR_MINI_E3_V3_0_1.h index b1ea4bca4c..dfeb545130 100644 --- a/Marlin/src/pins/stm32f4/pins_BTT_SKR_MINI_E3_V3_0_1.h +++ b/Marlin/src/pins/stm32f4/pins_BTT_SKR_MINI_E3_V3_0_1.h @@ -140,6 +140,10 @@ #ifndef E0_SLAVE_ADDRESS #define E0_SLAVE_ADDRESS 3 #endif + static_assert(X_SLAVE_ADDRESS == 0, "X_SLAVE_ADDRESS must be 0 for BOARD_BTT_SKR_MINI_E3_V3_0_1."); + static_assert(Y_SLAVE_ADDRESS == 2, "Y_SLAVE_ADDRESS must be 2 for BOARD_BTT_SKR_MINI_E3_V3_0_1."); + static_assert(Z_SLAVE_ADDRESS == 1, "Z_SLAVE_ADDRESS must be 1 for BOARD_BTT_SKR_MINI_E3_V3_0_1."); + static_assert(E0_SLAVE_ADDRESS == 3, "E0_SLAVE_ADDRESS must be 3 for BOARD_BTT_SKR_MINI_E3_V3_0_1."); #endif // diff --git a/Marlin/src/pins/stm32f4/pins_CREALITY_CR4NTXXC10.h b/Marlin/src/pins/stm32f4/pins_CREALITY_CR4NTXXC10.h index e1cd5945a6..d1077cd5d0 100644 --- a/Marlin/src/pins/stm32f4/pins_CREALITY_CR4NTXXC10.h +++ b/Marlin/src/pins/stm32f4/pins_CREALITY_CR4NTXXC10.h @@ -153,18 +153,23 @@ #define Z_HARDWARE_SERIAL X_HARDWARE_SERIAL #define E0_HARDWARE_SERIAL X_HARDWARE_SERIAL + // Default TMC slave addresses #ifndef X_SLAVE_ADDRESS - #define X_SLAVE_ADDRESS 0 + #define X_SLAVE_ADDRESS 0 #endif #ifndef Y_SLAVE_ADDRESS - #define Y_SLAVE_ADDRESS 1 + #define Y_SLAVE_ADDRESS 1 #endif #ifndef Z_SLAVE_ADDRESS - #define Z_SLAVE_ADDRESS 2 + #define Z_SLAVE_ADDRESS 2 #endif #ifndef E0_SLAVE_ADDRESS - #define E0_SLAVE_ADDRESS 3 + #define E0_SLAVE_ADDRESS 3 #endif + static_assert(X_SLAVE_ADDRESS == 0, "X_SLAVE_ADDRESS must be 0 for BOARD_CREALITY_CR4NTXXC10."); + static_assert(Y_SLAVE_ADDRESS == 1, "Y_SLAVE_ADDRESS must be 1 for BOARD_CREALITY_CR4NTXXC10."); + static_assert(Z_SLAVE_ADDRESS == 2, "Z_SLAVE_ADDRESS must be 2 for BOARD_CREALITY_CR4NTXXC10."); + static_assert(E0_SLAVE_ADDRESS == 3, "E0_SLAVE_ADDRESS must be 3 for BOARD_CREALITY_CR4NTXXC10."); // Software serial diff --git a/Marlin/src/pins/stm32f4/pins_FYSETC_CHEETAH_V20.h b/Marlin/src/pins/stm32f4/pins_FYSETC_CHEETAH_V20.h index 16973b344f..7d7126b640 100644 --- a/Marlin/src/pins/stm32f4/pins_FYSETC_CHEETAH_V20.h +++ b/Marlin/src/pins/stm32f4/pins_FYSETC_CHEETAH_V20.h @@ -23,10 +23,8 @@ #include "env_validate.h" -#define DEFAULT_MACHINE_NAME "3D Printer" - #define BOARD_INFO_NAME "FYSETC Cheetah V2.0" -#define BOARD_WEBSITE_URL "fysetc.com" +#define BOARD_WEBSITE_URL "github.com/FYSETC/FYSETC-Cheetah-v2" // USB Flash Drive support //#define HAS_OTG_USB_HOST_SUPPORT @@ -94,17 +92,21 @@ // Default TMC slave addresses #ifndef X_SLAVE_ADDRESS - #define X_SLAVE_ADDRESS 0 + #define X_SLAVE_ADDRESS 0 #endif #ifndef Y_SLAVE_ADDRESS - #define Y_SLAVE_ADDRESS 2 + #define Y_SLAVE_ADDRESS 2 #endif #ifndef Z_SLAVE_ADDRESS - #define Z_SLAVE_ADDRESS 1 + #define Z_SLAVE_ADDRESS 1 #endif #ifndef E0_SLAVE_ADDRESS - #define E0_SLAVE_ADDRESS 3 + #define E0_SLAVE_ADDRESS 3 #endif + static_assert(X_SLAVE_ADDRESS == 0, "X_SLAVE_ADDRESS must be 0 for BOARD_FYSETC_CHEETAH_V20."); + static_assert(Y_SLAVE_ADDRESS == 2, "Y_SLAVE_ADDRESS must be 2 for BOARD_FYSETC_CHEETAH_V20."); + static_assert(Z_SLAVE_ADDRESS == 1, "Z_SLAVE_ADDRESS must be 1 for BOARD_FYSETC_CHEETAH_V20."); + static_assert(E0_SLAVE_ADDRESS == 3, "E0_SLAVE_ADDRESS must be 3 for BOARD_FYSETC_CHEETAH_V20."); #endif // diff --git a/Marlin/src/pins/stm32f4/pins_FYSETC_CHEETAH_V30.h b/Marlin/src/pins/stm32f4/pins_FYSETC_CHEETAH_V30.h index 70a9bf9de2..5eb398c3cf 100644 --- a/Marlin/src/pins/stm32f4/pins_FYSETC_CHEETAH_V30.h +++ b/Marlin/src/pins/stm32f4/pins_FYSETC_CHEETAH_V30.h @@ -24,7 +24,7 @@ #include "env_validate.h" #define BOARD_INFO_NAME "FYSETC Cheetah V3.0" -#define BOARD_WEBSITE_URL "fysetc.com" +#define BOARD_WEBSITE_URL "github.com/FYSETC/Cheetah_V3.0" // USB Flash Drive support //#define HAS_OTG_USB_HOST_SUPPORT @@ -41,12 +41,12 @@ // // Z Probe // -//#if ENABLED(BLTOUCH) -// #error "You need to set jumper to 5V for BLTouch, then comment out this line to proceed." -// #define SERVO0_PIN PA0 -//#elif !defined(Z_MIN_PROBE_PIN) -// #define Z_MIN_PROBE_PIN PA0 -//#endif +#if ENABLED(BLTOUCH) + #error "You need to set jumper to 5V for BLTouch, then comment out this line to proceed." + #define SERVO0_PIN PA0 // PROBE +#elif !defined(Z_MIN_PROBE_PIN) + #define Z_MIN_PROBE_PIN PA0 +#endif // // Limit Switches @@ -55,17 +55,10 @@ #define Y_STOP_PIN PA3 #define Z_STOP_PIN PC4 -#if 1 -#define TEST_IO1 PA0 // PROBE -#define TEST_IO2 PA1 // FIL-D -//#define TEST_IO3 PA9 -//#define TEST_IO4 PA10 -#endif - // // Filament runout // -//#define FIL_RUNOUT_PIN PA1 +#define FIL_RUNOUT_PIN PA1 // FIL-D // // Steppers @@ -87,66 +80,61 @@ #define E0_ENABLE_PIN PD2 #if HAS_TMC_UART - #if 1 - #ifndef X_SERIAL_TX_PIN - #define X_SERIAL_TX_PIN PB3 - #endif - #ifndef X_SERIAL_RX_PIN - #define X_SERIAL_RX_PIN X_SERIAL_TX_PIN - #endif + /** + * TMC2208/TMC2209 stepper drivers + * + * Hardware serial communication ports. + * If undefined software serial is used according to the pins below + */ + //#define X_HARDWARE_SERIAL Serial2 + //#define Y_HARDWARE_SERIAL Serial2 + //#define Z_HARDWARE_SERIAL Serial2 + //#define E0_HARDWARE_SERIAL Serial2 - #ifndef Y_SERIAL_TX_PIN - #define Y_SERIAL_TX_PIN PB3 - #endif - #ifndef Y_SERIAL_RX_PIN - #define Y_SERIAL_RX_PIN Y_SERIAL_TX_PIN - #endif + #ifndef X_SERIAL_TX_PIN + #define X_SERIAL_TX_PIN PB3 + #endif + #ifndef X_SERIAL_RX_PIN + #define X_SERIAL_RX_PIN X_SERIAL_TX_PIN + #endif - #ifndef Z_SERIAL_TX_PIN - #define Z_SERIAL_TX_PIN PB3 - #endif - #ifndef Z_SERIAL_RX_PIN - #define Z_SERIAL_RX_PIN Z_SERIAL_TX_PIN - #endif - #ifndef E0_SERIAL_TX_PIN - #define E0_SERIAL_TX_PIN PB3 - #endif - #ifndef E0_SERIAL_RX_PIN - #define E0_SERIAL_RX_PIN E0_SERIAL_TX_PIN - #endif + #ifndef Y_SERIAL_TX_PIN + #define Y_SERIAL_TX_PIN PB3 + #endif + #ifndef Y_SERIAL_RX_PIN + #define Y_SERIAL_RX_PIN Y_SERIAL_TX_PIN + #endif - #ifndef X_SLAVE_ADDRESS - #define X_SLAVE_ADDRESS 0 - #endif - #ifndef Y_SLAVE_ADDRESS - #define Y_SLAVE_ADDRESS 2 - #endif - #ifndef Z_SLAVE_ADDRESS - #define Z_SLAVE_ADDRESS 1 - #endif - #ifndef E0_SLAVE_ADDRESS - #define E0_SLAVE_ADDRESS 3 - #endif - #else - #define X_HARDWARE_SERIAL Serial2 - #define Y_HARDWARE_SERIAL Serial2 - #define Z_HARDWARE_SERIAL Serial2 - #define E0_HARDWARE_SERIAL Serial2 + #ifndef Z_SERIAL_TX_PIN + #define Z_SERIAL_TX_PIN PB3 + #endif + #ifndef Z_SERIAL_RX_PIN + #define Z_SERIAL_RX_PIN Z_SERIAL_TX_PIN + #endif + #ifndef E0_SERIAL_TX_PIN + #define E0_SERIAL_TX_PIN PB3 + #endif + #ifndef E0_SERIAL_RX_PIN + #define E0_SERIAL_RX_PIN E0_SERIAL_TX_PIN + #endif // Default TMC slave addresses #ifndef X_SLAVE_ADDRESS - #define X_SLAVE_ADDRESS 0 + #define X_SLAVE_ADDRESS 0 #endif #ifndef Y_SLAVE_ADDRESS - #define Y_SLAVE_ADDRESS 2 + #define Y_SLAVE_ADDRESS 2 #endif #ifndef Z_SLAVE_ADDRESS - #define Z_SLAVE_ADDRESS 1 + #define Z_SLAVE_ADDRESS 1 #endif #ifndef E0_SLAVE_ADDRESS - #define E0_SLAVE_ADDRESS 3 + #define E0_SLAVE_ADDRESS 3 #endif - #endif + static_assert(X_SLAVE_ADDRESS == 0, "X_SLAVE_ADDRESS must be 0 for BOARD_FYSETC_CHEETAH_V30."); + static_assert(Y_SLAVE_ADDRESS == 2, "Y_SLAVE_ADDRESS must be 2 for BOARD_FYSETC_CHEETAH_V30."); + static_assert(Z_SLAVE_ADDRESS == 1, "Z_SLAVE_ADDRESS must be 1 for BOARD_FYSETC_CHEETAH_V30."); + static_assert(E0_SLAVE_ADDRESS == 3, "E0_SLAVE_ADDRESS must be 3 for BOARD_FYSETC_CHEETAH_V30."); #endif // diff --git a/Marlin/src/pins/stm32f4/pins_MKS_MONSTER8_common.h b/Marlin/src/pins/stm32f4/pins_MKS_MONSTER8_common.h index e96a679360..b832a14b2a 100644 --- a/Marlin/src/pins/stm32f4/pins_MKS_MONSTER8_common.h +++ b/Marlin/src/pins/stm32f4/pins_MKS_MONSTER8_common.h @@ -245,43 +245,120 @@ #define EXP2_07_PIN PB11 #define EXP2_08_PIN -1 // RESET -#if HAS_MEDIA - #ifndef SDCARD_CONNECTION +// +// SD Support +// +#ifndef SDCARD_CONNECTION + #if HAS_WIRED_LCD && DISABLED(NO_LCD_SDCARD) + #define SDCARD_CONNECTION LCD + #else #define SDCARD_CONNECTION ONBOARD #endif - #if SD_CONNECTION_IS(ONBOARD) - #define ENABLE_SPI3 - #define SD_SS_PIN -1 - #define SDSS PC9 - #define SD_SCK_PIN PC10 - #define SD_MISO_PIN PC11 - #define SD_MOSI_PIN PC12 - #define SD_DETECT_PIN PC4 // SD_DETECT_PIN doesn't work with NO_SD_HOST_DRIVE disabled - #elif SD_CONNECTION_IS(LCD) - #define ENABLE_SPI1 - #define SDSS EXP2_04_PIN - #define SD_SCK_PIN EXP2_02_PIN - #define SD_MISO_PIN EXP2_01_PIN - #define SD_MOSI_PIN EXP2_06_PIN - #define SD_DETECT_PIN EXP2_07_PIN - #endif #endif -#if ANY(TFT_COLOR_UI, TFT_CLASSIC_UI) - #define TFT_CS_PIN EXP1_07_PIN +// +// Onboard SD card +// Must use soft SPI because Marlin's default hardware SPI is tied to LCD's EXP2 +// +#if SD_CONNECTION_IS(ONBOARD) + #define ENABLE_SPI3 + #define SD_SS_PIN -1 + #define SDSS PC9 + #define SD_SCK_PIN PC10 + #define SD_MISO_PIN PC11 + #define SD_MOSI_PIN PC12 + #define SD_DETECT_PIN PC4 // SD_DETECT_PIN doesn't work with NO_SD_HOST_DRIVE disabled +#elif SD_CONNECTION_IS(LCD) + #define ENABLE_SPI1 + #define SDSS EXP2_04_PIN + #define SD_SCK_PIN EXP2_02_PIN + #define SD_MISO_PIN EXP2_01_PIN + #define SD_MOSI_PIN EXP2_06_PIN + #define SD_DETECT_PIN EXP2_07_PIN +#elif SD_CONNECTION_IS(CUSTOM_CABLE) + #error "CUSTOM_CABLE is not a supported SDCARD_CONNECTION for BOARD_MKS_MONSTER8_V1/V2." +#endif + +#if HAS_WIRED_LCD + + #define BEEPER_PIN EXP1_01_PIN + #define BTN_ENC EXP1_02_PIN + + #if ENABLED(CR10_STOCKDISPLAY) + #define LCD_PINS_RS EXP1_07_PIN + + #define BTN_EN1 EXP1_03_PIN + #define BTN_EN2 EXP1_05_PIN + + #define LCD_PINS_EN EXP1_08_PIN + #define LCD_PINS_D4 EXP1_06_PIN + + #else + + #define LCD_PINS_EN EXP1_03_PIN + #define LCD_PINS_RS EXP1_04_PIN + + #define BTN_EN1 EXP2_03_PIN + #define BTN_EN2 EXP2_05_PIN + + // MKS MINI12864 and MKS LCD12864B; If using MKS LCD12864A (Need to remove RPK2 resistor) + #if ENABLED(MKS_MINI_12864) + + #define ENABLE_SPI1 + #define FORCE_SOFT_SPI + #define DOGLCD_A0 EXP1_07_PIN + #define DOGLCD_CS EXP1_06_PIN + #define DOGLCD_SCK EXP2_02_PIN + #define DOGLCD_MOSI EXP2_06_PIN + //#define LCD_BACKLIGHT_PIN -1 + //#define LCD_RESET_PIN -1 + + #elif ENABLED(FYSETC_MINI_12864_2_1) + + #define LCD_PINS_DC EXP1_04_PIN + #define DOGLCD_CS EXP1_03_PIN + #define DOGLCD_A0 LCD_PINS_DC + #define LCD_BACKLIGHT_PIN -1 + #define LCD_RESET_PIN EXP1_05_PIN + #define NEOPIXEL_PIN EXP1_06_PIN + #define DOGLCD_MOSI EXP2_06_PIN + #define DOGLCD_SCK EXP2_02_PIN + #if SD_CONNECTION_IS(ONBOARD) + #define FORCE_SOFT_SPI + #endif + //#define LCD_SCREEN_ROTATE 180 // 0, 90, 180, 270 + + #else + + #define LCD_PINS_D4 EXP1_05_PIN + #if IS_ULTIPANEL + #define LCD_PINS_D5 EXP1_06_PIN + #define LCD_PINS_D6 EXP1_07_PIN + #define LCD_PINS_D7 EXP1_08_PIN + #endif + + #ifndef BOARD_ST7920_DELAY_1 + #define BOARD_ST7920_DELAY_1 96 + #endif + #ifndef BOARD_ST7920_DELAY_2 + #define BOARD_ST7920_DELAY_2 48 + #endif + #ifndef BOARD_ST7920_DELAY_3 + #define BOARD_ST7920_DELAY_3 600 + #endif + + #endif + #endif +#endif // HAS_WIRED_LCD + +#if HAS_SPI_TFT // Config for Classic UI (emulated DOGM) and Color UI + #define TFT_SCK_PIN EXP2_02_PIN #define TFT_MISO_PIN EXP2_01_PIN #define TFT_MOSI_PIN EXP2_06_PIN - #define TFT_DC_PIN EXP1_08_PIN - #define TFT_A0_PIN TFT_DC_PIN - #define TFT_RESET_PIN EXP1_04_PIN - - #define LCD_BACKLIGHT_PIN EXP1_03_PIN - #define TFT_BACKLIGHT_PIN LCD_BACKLIGHT_PIN - - #define TOUCH_BUTTONS_HW_SPI - #define TOUCH_BUTTONS_HW_SPI_DEVICE 1 + #define BTN_EN1 EXP2_03_PIN + #define BTN_EN2 EXP2_05_PIN #ifndef TFT_WIDTH #define TFT_WIDTH 480 @@ -290,85 +367,97 @@ #define TFT_HEIGHT 320 #endif - #define TOUCH_CS_PIN EXP1_05_PIN // SPI1_NSS - #define TOUCH_SCK_PIN EXP2_02_PIN // SPI1_SCK - #define TOUCH_MISO_PIN EXP2_01_PIN // SPI1_MISO - #define TOUCH_MOSI_PIN EXP2_06_PIN // SPI1_MOSI + #if ENABLED(BTT_TFT35_SPI_V1_0) - #define LCD_READ_ID 0xD3 - #define LCD_USE_DMA_SPI + /** + * ------ ------ + * BEEPER | 1 2 | LCD-BTN MISO | 1 2 | CLK + * T_MOSI | 3 4 | T_CS LCD-ENCA | 3 4 | TFTCS + * T_CLK | 5 6 T_MISO LCD-ENCB | 5 6 MOSI + * PENIRQ | 7 8 | F_CS RS | 7 8 | RESET + * GND | 9 10 | VCC GND | 9 10 | NC + * ------ ------ + * EXP1 EXP2 + * + * 480x320, 3.5", SPI Display with Rotary Encoder. + * Stock Display for the BIQU B1 SE Series. + * Schematic: https://github.com/bigtreetech/TFT35-SPI/blob/master/v1/Hardware/BTT%20TFT35-SPI%20V1-SCH.pdf + */ + #define TFT_CS_PIN EXP2_04_PIN + #define TFT_DC_PIN EXP2_07_PIN + #define TFT_A0_PIN TFT_DC_PIN - #define TFT_BUFFER_WORDS 14400 + #define TOUCH_CS_PIN EXP1_04_PIN + #define TOUCH_SCK_PIN EXP1_05_PIN + #define TOUCH_MISO_PIN EXP1_06_PIN + #define TOUCH_MOSI_PIN EXP1_03_PIN + #define TOUCH_INT_PIN EXP1_07_PIN - #ifndef TOUCH_CALIBRATION_X - #define TOUCH_CALIBRATION_X -17253 - #endif - #ifndef TOUCH_CALIBRATION_Y - #define TOUCH_CALIBRATION_Y 11579 - #endif - #ifndef TOUCH_OFFSET_X - #define TOUCH_OFFSET_X 514 - #endif - #ifndef TOUCH_OFFSET_Y - #define TOUCH_OFFSET_Y -24 - #endif - #ifndef TOUCH_ORIENTATION - #define TOUCH_ORIENTATION TOUCH_LANDSCAPE - #endif - -#elif HAS_WIRED_LCD - - #define LCD_PINS_EN EXP1_03_PIN - #define LCD_PINS_RS EXP1_04_PIN - #define LCD_BACKLIGHT_PIN -1 - - // MKS MINI12864 and MKS LCD12864B; If using MKS LCD12864A (Need to remove RPK2 resistor) - #if ENABLED(MKS_MINI_12864) - - #define ENABLE_SPI1 - #define FORCE_SOFT_SPI - #define DOGLCD_A0 EXP1_07_PIN - #define DOGLCD_CS EXP1_06_PIN - #define DOGLCD_SCK EXP2_02_PIN - #define DOGLCD_MOSI EXP2_06_PIN - //#define LCD_BACKLIGHT_PIN -1 - //#define LCD_RESET_PIN -1 - - #elif ENABLED(FYSETC_MINI_12864_2_1) - - #define LCD_PINS_DC EXP1_04_PIN - #define DOGLCD_CS EXP1_03_PIN - #define DOGLCD_A0 LCD_PINS_DC - #define LCD_BACKLIGHT_PIN -1 - #define LCD_RESET_PIN EXP1_05_PIN - #define NEOPIXEL_PIN EXP1_06_PIN - #define DOGLCD_MOSI EXP2_06_PIN - #define DOGLCD_SCK EXP2_02_PIN - #if SD_CONNECTION_IS(ONBOARD) - #define FORCE_SOFT_SPI + #ifndef TOUCH_CALIBRATION_X + #define TOUCH_CALIBRATION_X 17540 #endif - //#define LCD_SCREEN_ROTATE 180 // 0, 90, 180, 270 - - #else - - #define LCD_PINS_D4 EXP1_05_PIN - #if IS_ULTIPANEL - #define LCD_PINS_D5 EXP1_06_PIN - #define LCD_PINS_D6 EXP1_07_PIN - #define LCD_PINS_D7 EXP1_08_PIN + #ifndef TOUCH_CALIBRATION_Y + #define TOUCH_CALIBRATION_Y -11388 + #endif + #ifndef TOUCH_OFFSET_X + #define TOUCH_OFFSET_X -21 + #endif + #ifndef TOUCH_OFFSET_Y + #define TOUCH_OFFSET_Y 337 + #endif + #ifndef TOUCH_ORIENTATION + #define TOUCH_ORIENTATION TOUCH_LANDSCAPE #endif - #define BOARD_ST7920_DELAY_1 96 - #define BOARD_ST7920_DELAY_2 48 - #define BOARD_ST7920_DELAY_3 600 + #elif ENABLED(MKS_TS35_V2_0) - #endif // !MKS_MINI_12864 + /** ------ ------ + * BEEPER | 1 2 | BTN_ENC SPI1_MISO | 1 2 | SPI1_SCK + * TFT_BKL / LCD_EN | 3 4 | TFT_RESET / LCD_RS BTN_EN1 | 3 4 | SPI1_CS + * TOUCH_CS / LCD_D4 | 5 6 TOUCH_INT / LCD_D5 BTN_EN2 | 5 6 SPI1_MOSI + * SPI1_CS / LCD_D6 | 7 8 | SPI1_RS / LCD_D7 SPI1_RS | 7 8 | RESET + * GND | 9 10 | VCC GND | 9 10 | VCC + * ------ ------ + * EXP1 EXP2 + */ + #define TFT_CS_PIN EXP1_07_PIN // SPI1_CS + #define TFT_DC_PIN EXP1_08_PIN // SPI1_RS + #define TFT_A0_PIN TFT_DC_PIN -#endif // HAS_WIRED_LCD + #define TFT_RESET_PIN EXP1_04_PIN + + #define LCD_BACKLIGHT_PIN EXP1_03_PIN + #define TFT_BACKLIGHT_PIN LCD_BACKLIGHT_PIN + + #define TOUCH_BUTTONS_HW_SPI + #define TOUCH_BUTTONS_HW_SPI_DEVICE 1 + + #define TOUCH_CS_PIN EXP1_05_PIN // SPI1_NSS + #define TOUCH_SCK_PIN EXP2_02_PIN // SPI1_SCK + #define TOUCH_MISO_PIN EXP2_01_PIN // SPI1_MISO + #define TOUCH_MOSI_PIN EXP2_06_PIN // SPI1_MOSI + + #define LCD_READ_ID 0xD3 + #define LCD_USE_DMA_SPI + + #define TFT_BUFFER_WORDS 14400 + + #ifndef TOUCH_CALIBRATION_X + #define TOUCH_CALIBRATION_X -17253 + #endif + #ifndef TOUCH_CALIBRATION_Y + #define TOUCH_CALIBRATION_Y 11579 + #endif + #ifndef TOUCH_OFFSET_X + #define TOUCH_OFFSET_X 514 + #endif + #ifndef TOUCH_OFFSET_Y + #define TOUCH_OFFSET_Y -24 + #endif + #ifndef TOUCH_ORIENTATION + #define TOUCH_ORIENTATION TOUCH_LANDSCAPE + #endif + + #endif -#if ANY(TFT_COLOR_UI, TFT_CLASSIC_UI, HAS_WIRED_LCD) - #define BEEPER_PIN EXP1_01_PIN - #define BTN_EN1 EXP2_03_PIN - #define BTN_EN2 EXP2_05_PIN - #define BTN_ENC EXP1_02_PIN #endif diff --git a/Marlin/src/pins/stm32f4/pins_TH3D_EZBOARD_V2.h b/Marlin/src/pins/stm32f4/pins_TH3D_EZBOARD_V2.h index 9151e5e07f..cec7780b94 100644 --- a/Marlin/src/pins/stm32f4/pins_TH3D_EZBOARD_V2.h +++ b/Marlin/src/pins/stm32f4/pins_TH3D_EZBOARD_V2.h @@ -134,17 +134,21 @@ // Default TMC slave addresses #ifndef X_SLAVE_ADDRESS - #define X_SLAVE_ADDRESS 0 + #define X_SLAVE_ADDRESS 0 #endif #ifndef Y_SLAVE_ADDRESS - #define Y_SLAVE_ADDRESS 1 + #define Y_SLAVE_ADDRESS 1 #endif #ifndef Z_SLAVE_ADDRESS - #define Z_SLAVE_ADDRESS 2 + #define Z_SLAVE_ADDRESS 2 #endif #ifndef E0_SLAVE_ADDRESS - #define E0_SLAVE_ADDRESS 3 + #define E0_SLAVE_ADDRESS 3 #endif + static_assert(X_SLAVE_ADDRESS == 0, "X_SLAVE_ADDRESS must be 0 for BOARD_TH3D_EZBOARD_V2."); + static_assert(Y_SLAVE_ADDRESS == 1, "Y_SLAVE_ADDRESS must be 1 for BOARD_TH3D_EZBOARD_V2."); + static_assert(Z_SLAVE_ADDRESS == 2, "Z_SLAVE_ADDRESS must be 2 for BOARD_TH3D_EZBOARD_V2."); + static_assert(E0_SLAVE_ADDRESS == 3, "E0_SLAVE_ADDRESS must be 3 for BOARD_TH3D_EZBOARD_V2."); // Reduce baud rate to improve software serial reliability #ifndef TMC_BAUD_RATE diff --git a/Marlin/src/pins/stm32g0/pins_BTT_EBB42_V1_1.h b/Marlin/src/pins/stm32g0/pins_BTT_EBB42_V1_1.h index 103a148911..df2ab4652e 100644 --- a/Marlin/src/pins/stm32g0/pins_BTT_EBB42_V1_1.h +++ b/Marlin/src/pins/stm32g0/pins_BTT_EBB42_V1_1.h @@ -34,6 +34,7 @@ #ifndef BOARD_INFO_NAME #define BOARD_INFO_NAME "BTT EBB42 V1.1" #endif +#define BOARD_WEBSITE_URL "github.com/bigtreetech/EBB/tree/master/EBB%20CAN%20V1.1%20(STM32G0B1)/EBB42%20CAN%20V1.1" // // EEPROM @@ -105,8 +106,9 @@ // Default TMC slave addresses #ifndef E0_SLAVE_ADDRESS - #define E0_SLAVE_ADDRESS 0b00 + #define E0_SLAVE_ADDRESS 0b00 #endif + static_assert(E0_SLAVE_ADDRESS == 0b00, "E0_SLAVE_ADDRESS must be 0b00 for BOARD_BTT_EBB42_V1_1."); #endif // diff --git a/Marlin/src/pins/stm32g0/pins_BTT_SKR_MINI_E3_V3_0.h b/Marlin/src/pins/stm32g0/pins_BTT_SKR_MINI_E3_V3_0.h index df91933d71..81d2ff94a0 100644 --- a/Marlin/src/pins/stm32g0/pins_BTT_SKR_MINI_E3_V3_0.h +++ b/Marlin/src/pins/stm32g0/pins_BTT_SKR_MINI_E3_V3_0.h @@ -119,17 +119,21 @@ // Default TMC slave addresses #ifndef X_SLAVE_ADDRESS - #define X_SLAVE_ADDRESS 0 + #define X_SLAVE_ADDRESS 0 #endif #ifndef Y_SLAVE_ADDRESS - #define Y_SLAVE_ADDRESS 2 + #define Y_SLAVE_ADDRESS 2 #endif #ifndef Z_SLAVE_ADDRESS - #define Z_SLAVE_ADDRESS 1 + #define Z_SLAVE_ADDRESS 1 #endif #ifndef E0_SLAVE_ADDRESS - #define E0_SLAVE_ADDRESS 3 + #define E0_SLAVE_ADDRESS 3 #endif + static_assert(X_SLAVE_ADDRESS == 0, "X_SLAVE_ADDRESS must be 0 for BOARD_BTT_SKR_MINI_E3_V3_0."); + static_assert(Y_SLAVE_ADDRESS == 2, "Y_SLAVE_ADDRESS must be 2 for BOARD_BTT_SKR_MINI_E3_V3_0."); + static_assert(Z_SLAVE_ADDRESS == 1, "Z_SLAVE_ADDRESS must be 1 for BOARD_BTT_SKR_MINI_E3_V3_0."); + static_assert(E0_SLAVE_ADDRESS == 3, "E0_SLAVE_ADDRESS must be 3 for BOARD_BTT_SKR_MINI_E3_V3_0."); #endif // diff --git a/Marlin/tests/core/test_macros.cpp b/Marlin/tests/core/test_macros.cpp index 2353342928..bb269dec2b 100644 --- a/Marlin/tests/core/test_macros.cpp +++ b/Marlin/tests/core/test_macros.cpp @@ -557,7 +557,7 @@ MARLIN_TEST(macros_options, OPTITEM) { MARLIN_TEST(macros_options, OPTARG) { int enabledArgs[] = {0 OPTARG(OPTION_ENABLED, 1, 2)}; int disabledArgs[] = {0 OPTARG(OPTION_DISABLED, 1, 2)}; - + int sumEnabledArgs = 0; for (const auto& arg : enabledArgs) { sumEnabledArgs += arg; diff --git a/Marlin/tests/core/test_types.cpp b/Marlin/tests/core/test_types.cpp new file mode 100644 index 0000000000..865d35de15 --- /dev/null +++ b/Marlin/tests/core/test_types.cpp @@ -0,0 +1,605 @@ +/** + * Marlin 3D Printer Firmware + * Copyright (c) 2024 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * + * Based on Sprinter and grbl. + * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm + * + * This program 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. + * + * This program 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 this program. If not, see . + * + */ + +#include "../test/unit_tests.h" +#include "src/core/types.h" + +MARLIN_TEST(types, XYval_const_as_bools) { + const XYval xy_const_true = {1, 2}; + TEST_ASSERT_TRUE(xy_const_true); + + const XYval xy_const_false = {0, 0}; + TEST_ASSERT_FALSE(xy_const_false); +} + +MARLIN_TEST(types, XYval_non_const_as_bools) { + XYval xy_true = {1, 2}; + TEST_ASSERT_TRUE(xy_true); + + XYval xy_false = {0, 0}; + TEST_ASSERT_FALSE(xy_false); +} + +MARLIN_TEST(types, XYval_reset) { + XYval xy = {1, 2}; + xy.reset(); + TEST_ASSERT_EQUAL(0, xy.x); + TEST_ASSERT_EQUAL(0, xy.y); +} + +MARLIN_TEST(types, XYval_set) { + XYval xy; + xy.set(3, 4); + TEST_ASSERT_EQUAL(3, xy.x); + TEST_ASSERT_EQUAL(4, xy.y); +} + +MARLIN_TEST(types, XYval_magnitude) { + XYval xy; + + xy.set(3, 4); + TEST_ASSERT_EQUAL(5, xy.magnitude()); + + xy.set(-3, -4); + TEST_ASSERT_EQUAL(5, xy.magnitude()); + + xy.set(-3, 4); + TEST_ASSERT_EQUAL(5, xy.magnitude()); + + xy.set(3, -4); + TEST_ASSERT_EQUAL(5, xy.magnitude()); +} + +MARLIN_TEST(types, XYval_small_large) { + XYval xy; + + xy.set(3, 4); + TEST_ASSERT_EQUAL(3, xy.small()); + TEST_ASSERT_EQUAL(4, xy.large()); + + xy.set(4, 3); + TEST_ASSERT_EQUAL(3, xy.small()); + TEST_ASSERT_EQUAL(4, xy.large()); + + // BUG?: Is this behavior actually correct? + // Does small mean "less than", or should it mean + // "closer to zero"? If the latter, then the following + // tests are incorrect. + xy.set(-3, -4); + TEST_ASSERT_EQUAL(-4, xy.small()); + TEST_ASSERT_EQUAL(-3, xy.large()); + + xy.set(-3, 2); + TEST_ASSERT_EQUAL(-3, xy.small()); + TEST_ASSERT_EQUAL(2, xy.large()); + + xy.set(2, -3); + TEST_ASSERT_EQUAL(-3, xy.small()); + TEST_ASSERT_EQUAL(2, xy.large()); +} + +MARLIN_TEST(types, XYval_operators) { + XYval xy1 = {2, 3}, xy2 = {6, 12}; + XYval xy3 = xy1 + xy2; + TEST_ASSERT_EQUAL(8, xy3.x); + TEST_ASSERT_EQUAL(15, xy3.y); + xy3 = xy1 - xy2; + TEST_ASSERT_EQUAL(-4, xy3.x); + TEST_ASSERT_EQUAL(-9, xy3.y); + xy3 = xy1 * xy2; + TEST_ASSERT_EQUAL(12, xy3.x); + TEST_ASSERT_EQUAL(36, xy3.y); + xy3 = xy2 / xy1; + TEST_ASSERT_EQUAL(3, xy3.x); + TEST_ASSERT_EQUAL(4, xy3.y); +} + +MARLIN_TEST(types, XYval_ABS) { + XYval xy = {-3, -4}; + XYval xy_abs = xy.ABS(); + TEST_ASSERT_EQUAL(3, xy_abs.x); + TEST_ASSERT_EQUAL(4, xy_abs.y); +} + +MARLIN_TEST(types, XYval_ROUNDL) { + XYval xy = {3.3f, 4.7f}; + auto xy_round = xy.ROUNDL(); + TEST_ASSERT_EQUAL(3, xy_round.x); + TEST_ASSERT_EQUAL(5, xy_round.y); +} + +MARLIN_TEST(types, XYval_reciprocal) { + XYval xy = {0.5f, 4.0f}; + XYval xy_reciprocal = xy.reciprocal(); + TEST_ASSERT_EQUAL_FLOAT(2.0f, xy_reciprocal.x); + TEST_ASSERT_EQUAL_FLOAT(0.25f, xy_reciprocal.y); +} + +MARLIN_TEST(types, XYZval_const_as_bools) { + const XYZval xyz_const_true = {1, 2, 3}; + TEST_ASSERT_TRUE(xyz_const_true); + + const XYZval xyz_const_false = {0, 0, 0}; + TEST_ASSERT_FALSE(xyz_const_false); +} + +MARLIN_TEST(types, XYZval_non_const_as_bools) { + XYZval xyz_true = {1, 2, 3}; + TEST_ASSERT_TRUE(xyz_true); + + XYZval xyz_false = {0, 0, 0}; + TEST_ASSERT_FALSE(xyz_false); +} + +MARLIN_TEST(types, XYZval_reset) { + XYZval xyz = {1, 2, 3}; + xyz.reset(); + TEST_ASSERT_EQUAL(0, xyz.x); + TEST_ASSERT_EQUAL(0, xyz.y); + TEST_ASSERT_EQUAL(0, xyz.z); +} + +MARLIN_TEST(types, XYZval_set) { + XYZval xyz; + xyz.set(3, 4, 5); + TEST_ASSERT_EQUAL(3, xyz.x); + TEST_ASSERT_EQUAL(4, xyz.y); + TEST_ASSERT_EQUAL(5, xyz.z); +} + +MARLIN_TEST(types, XYZval_magnitude) { + XYZval xyz; + + xyz.set(3.0f, 4.0f, 5.0f); + TEST_ASSERT_FLOAT_WITHIN(0.001f, 7.071f, xyz.magnitude()); + + xyz.set(-3.0f, -4.0f, -5.0f); + TEST_ASSERT_FLOAT_WITHIN(0.001f, 7.071f, xyz.magnitude()); + + xyz.set(-3.0f, 4.0f, 5.0f); + TEST_ASSERT_FLOAT_WITHIN(0.001f, 7.071f, xyz.magnitude()); + + xyz.set(3.0f, -4.0f, 5.0f); + TEST_ASSERT_FLOAT_WITHIN(0.001f, 7.071f, xyz.magnitude()); + + xyz.set(3.0f, 4.0f, -5.0f); + TEST_ASSERT_FLOAT_WITHIN(0.001f, 7.071f, xyz.magnitude()); +} + +MARLIN_TEST(types, XYZval_small_large) { + XYZval xyz; + + xyz.set(3, 4, 5); + TEST_ASSERT_EQUAL(3, xyz.small()); + TEST_ASSERT_EQUAL(5, xyz.large()); + + xyz.set(5, 4, 3); + TEST_ASSERT_EQUAL(3, xyz.small()); + TEST_ASSERT_EQUAL(5, xyz.large()); + + xyz.set(4, 3, 5); + TEST_ASSERT_EQUAL(3, xyz.small()); + TEST_ASSERT_EQUAL(5, xyz.large()); + + xyz.set(3, 5, 4); + TEST_ASSERT_EQUAL(3, xyz.small()); + TEST_ASSERT_EQUAL(5, xyz.large()); + + // Test with negative numbers + xyz.set(-3, -4, -5); + TEST_ASSERT_EQUAL(-5, xyz.small()); + TEST_ASSERT_EQUAL(-3, xyz.large()); + + // Test with mixed negative/positive numbers + xyz.set(-3, 4, 5); + TEST_ASSERT_EQUAL(-3, xyz.small()); + TEST_ASSERT_EQUAL(5, xyz.large()); + + xyz.set(3, -4, 5); + TEST_ASSERT_EQUAL(-4, xyz.small()); + TEST_ASSERT_EQUAL(5, xyz.large()); + + xyz.set(3, 4, -5); + TEST_ASSERT_EQUAL(-5, xyz.small()); + TEST_ASSERT_EQUAL(4, xyz.large()); +} + +MARLIN_TEST(types, XYZval_operators) { + XYZval xyz1 = {2, 3, 4}, xyz2 = {6, 12, 24}; + XYZval xyz3 = xyz1 + xyz2; + TEST_ASSERT_EQUAL(8, xyz3.x); + TEST_ASSERT_EQUAL(15, xyz3.y); + TEST_ASSERT_EQUAL(28, xyz3.z); + xyz3 = xyz1 - xyz2; + TEST_ASSERT_EQUAL(-4, xyz3.x); + TEST_ASSERT_EQUAL(-9, xyz3.y); + TEST_ASSERT_EQUAL(-20, xyz3.z); + xyz3 = xyz1 * xyz2; + TEST_ASSERT_EQUAL(12, xyz3.x); + TEST_ASSERT_EQUAL(36, xyz3.y); + TEST_ASSERT_EQUAL(96, xyz3.z); + xyz3 = xyz2 / xyz1; + TEST_ASSERT_EQUAL(3, xyz3.x); + TEST_ASSERT_EQUAL(4, xyz3.y); + TEST_ASSERT_EQUAL(6, xyz3.z); +} + +MARLIN_TEST(types, XYZval_ABS) { + XYZval xyz = {-3, -4, -5}; + XYZval xyz_abs = xyz.ABS(); + TEST_ASSERT_EQUAL(3, xyz_abs.x); + TEST_ASSERT_EQUAL(4, xyz_abs.y); + TEST_ASSERT_EQUAL(5, xyz_abs.z); +} + +MARLIN_TEST(types, XYZval_ROUNDL) { + XYZval xyz = {3.3f, 4.7f, 5.5f}; + XYZval xyz_round = xyz.ROUNDL(); + TEST_ASSERT_EQUAL(3, xyz_round.x); + TEST_ASSERT_EQUAL(5, xyz_round.y); + TEST_ASSERT_EQUAL(6, xyz_round.z); +} + +MARLIN_TEST(types, XYZval_reciprocal) { + XYZval xyz = {0.5f, 2.0f, 0.33333f}; + XYZval xyz_reciprocal = xyz.reciprocal(); + TEST_ASSERT_EQUAL_FLOAT(2.0f, xyz_reciprocal.x); + TEST_ASSERT_EQUAL_FLOAT(0.5f, xyz_reciprocal.y); + TEST_ASSERT_FLOAT_WITHIN(0.001f, 3.0f, xyz_reciprocal.z); +} + +MARLIN_TEST(types, XYZEval_const_as_bools) { + const XYZEval xyze_const_true = {1, 2, 3, 4}; + TEST_ASSERT_TRUE(xyze_const_true); + + const XYZEval xyze_const_false = {0, 0, 0, 0}; + TEST_ASSERT_FALSE(xyze_const_false); +} + +MARLIN_TEST(types, XYZEval_non_const_as_bools) { + XYZEval xyze_true = {1, 2, 3, 4}; + TEST_ASSERT_TRUE(xyze_true); + + XYZEval xyze_false = {0, 0, 0, 0}; + TEST_ASSERT_FALSE(xyze_false); +} + +MARLIN_TEST(types, XYZEval_reset) { + XYZEval xyze = {1, 2, 3, 4}; + xyze.reset(); + TEST_ASSERT_EQUAL(0, xyze.x); + TEST_ASSERT_EQUAL(0, xyze.y); + TEST_ASSERT_EQUAL(0, xyze.z); + TEST_ASSERT_EQUAL(0, xyze.e); +} + +MARLIN_TEST(types, XYZEval_set) { + XYZEval xyze; + xyze.set(3, 4, 5, 6); + TEST_ASSERT_EQUAL(3, xyze.x); + TEST_ASSERT_EQUAL(4, xyze.y); + TEST_ASSERT_EQUAL(5, xyze.z); + TEST_ASSERT_EQUAL(6, xyze.e); +} + +MARLIN_TEST(types, XYZEval_magnitude) { + XYZEval xyze; + + xyze.set(3.0f, 4.0f, 5.0f, 6.0f); + TEST_ASSERT_FLOAT_WITHIN(0.001f, 9.274f, xyze.magnitude()); + + xyze.set(-3.0f, -4.0f, -5.0f, -6.0f); + TEST_ASSERT_FLOAT_WITHIN(0.001f, 9.274f, xyze.magnitude()); + + xyze.set(-3.0f, 4.0f, 5.0f, 6.0f); + TEST_ASSERT_FLOAT_WITHIN(0.001f, 9.274f, xyze.magnitude()); + + xyze.set(3.0f, -4.0f, 5.0f, 6.0f); + TEST_ASSERT_FLOAT_WITHIN(0.001f, 9.274f, xyze.magnitude()); + + xyze.set(3.0f, 4.0f, -5.0f, 6.0f); + TEST_ASSERT_FLOAT_WITHIN(0.001f, 9.274f, xyze.magnitude()); + + xyze.set(3.0f, 4.0f, 5.0f, -6.0f); + TEST_ASSERT_FLOAT_WITHIN(0.001f, 9.274f, xyze.magnitude()); +} + +MARLIN_TEST(types, XYZEval_small_large) { + XYZEval xyze; + + xyze.set(3, 4, 5, 6); + TEST_ASSERT_EQUAL(3, xyze.small()); + TEST_ASSERT_EQUAL(6, xyze.large()); + + xyze.set(6, 5, 4, 3); + TEST_ASSERT_EQUAL(3, xyze.small()); + TEST_ASSERT_EQUAL(6, xyze.large()); + + xyze.set(4, 3, 6, 5); + TEST_ASSERT_EQUAL(3, xyze.small()); + TEST_ASSERT_EQUAL(6, xyze.large()); + + xyze.set(3, 6, 5, 4); + TEST_ASSERT_EQUAL(3, xyze.small()); + TEST_ASSERT_EQUAL(6, xyze.large()); + + xyze.set(-3, -4, -5, -6); + TEST_ASSERT_EQUAL(-6, xyze.small()); + TEST_ASSERT_EQUAL(-3, xyze.large()); + + xyze.set(-3, 4, 5, 6); + TEST_ASSERT_EQUAL(-3, xyze.small()); + TEST_ASSERT_EQUAL(6, xyze.large()); + + xyze.set(3, -4, 5, 6); + TEST_ASSERT_EQUAL(-4, xyze.small()); + TEST_ASSERT_EQUAL(6, xyze.large()); + + xyze.set(3, 4, -5, 6); + TEST_ASSERT_EQUAL(-5, xyze.small()); + TEST_ASSERT_EQUAL(6, xyze.large()); + + xyze.set(3, 4, 5, -6); + TEST_ASSERT_EQUAL(-6, xyze.small()); + TEST_ASSERT_EQUAL(5, xyze.large()); +} + +MARLIN_TEST(types, XYZEval_operators) { + XYZEval xyze1 = {2, 3, 4, 5}, xyze2 = {6, 12, 24, 48}; + XYZEval xyze3 = xyze1 + xyze2; + TEST_ASSERT_EQUAL(8, xyze3.x); + TEST_ASSERT_EQUAL(15, xyze3.y); + TEST_ASSERT_EQUAL(28, xyze3.z); + TEST_ASSERT_EQUAL(53, xyze3.e); + xyze3 = xyze1 - xyze2; + TEST_ASSERT_EQUAL(-4, xyze3.x); + TEST_ASSERT_EQUAL(-9, xyze3.y); + TEST_ASSERT_EQUAL(-20, xyze3.z); + TEST_ASSERT_EQUAL(-43, xyze3.e); + xyze3 = xyze1 * xyze2; + TEST_ASSERT_EQUAL(12, xyze3.x); + TEST_ASSERT_EQUAL(36, xyze3.y); + TEST_ASSERT_EQUAL(96, xyze3.z); + TEST_ASSERT_EQUAL(240, xyze3.e); + xyze3 = xyze2 / xyze1; + TEST_ASSERT_EQUAL(3, xyze3.x); + TEST_ASSERT_EQUAL(4, xyze3.y); + TEST_ASSERT_EQUAL(6, xyze3.z); + TEST_ASSERT_EQUAL(9, xyze3.e); +} + +MARLIN_TEST(types, XYZEval_ABS) { + XYZEval xyze = {-3, -4, -5, -6}; + XYZEval xyze_abs = xyze.ABS(); + TEST_ASSERT_EQUAL(3, xyze_abs.x); + TEST_ASSERT_EQUAL(4, xyze_abs.y); + TEST_ASSERT_EQUAL(5, xyze_abs.z); + TEST_ASSERT_EQUAL(6, xyze_abs.e); +} + +MARLIN_TEST(types, XYZEval_ROUNDL) { + XYZEval xyze = {3.3f, 4.7f, 5.5f, 6.6f}; + XYZEval xyze_round = xyze.ROUNDL(); + TEST_ASSERT_EQUAL(3, xyze_round.x); + TEST_ASSERT_EQUAL(5, xyze_round.y); + TEST_ASSERT_EQUAL(6, xyze_round.z); + TEST_ASSERT_EQUAL(7, xyze_round.e); +} + +MARLIN_TEST(types, XYZEval_reciprocal) { + XYZEval xyze = {0.5f, 2.0f, 0.33333f, 0.25f}; + XYZEval xyze_reciprocal = xyze.reciprocal(); + TEST_ASSERT_EQUAL_FLOAT(2.0f, xyze_reciprocal.x); + TEST_ASSERT_EQUAL_FLOAT(0.5f, xyze_reciprocal.y); + TEST_ASSERT_FLOAT_WITHIN(0.001f, 3.0f, xyze_reciprocal.z); + TEST_ASSERT_EQUAL_FLOAT(4.0f, xyze_reciprocal.e); +} + +MARLIN_TEST(types, Flags_const_as_bools) { + const Flags<32> flags_const_false = {0}; + TEST_ASSERT_FALSE(flags_const_false); + + const Flags<32> flags_const_true = {1}; + TEST_ASSERT_TRUE(flags_const_true); +} + +MARLIN_TEST(types, Flags_non_const_as_bools) { + Flags<32> flags_false = {0}; + TEST_ASSERT_FALSE(flags_false); + + Flags<32> flags_true = {1}; + TEST_ASSERT_TRUE(flags_true); +} + +MARLIN_TEST(types, Flags_1) { + Flags<1> flags; + + flags.set(0, true); + TEST_ASSERT_EQUAL(1, flags.b); + + flags.reset(); + TEST_ASSERT_EQUAL(0, flags.b); + + flags.set(0, true); + flags.clear(0); + TEST_ASSERT_EQUAL(0, flags.b); + + TEST_ASSERT_EQUAL(false, flags.test(0)); + flags.set(0, true); + TEST_ASSERT_EQUAL(true, flags.test(0)); + + TEST_ASSERT_EQUAL(true, flags[0]); + flags.clear(0); + TEST_ASSERT_EQUAL(false, flags[0]); + + TEST_ASSERT_EQUAL(1, flags.size()); +} + +MARLIN_TEST(types, Flags_8) { + Flags<8> flags; + + flags.reset(); + TEST_ASSERT_EQUAL(0, flags.b); + + flags.set(3, true); + TEST_ASSERT_EQUAL(8, flags.b); + + flags.clear(3); + TEST_ASSERT_EQUAL(0, flags.b); + + flags.set(3, true); + TEST_ASSERT_EQUAL(true, flags.test(3)); + TEST_ASSERT_EQUAL(false, flags.test(2)); + + TEST_ASSERT_EQUAL(true, flags[3]); + TEST_ASSERT_EQUAL(false, flags[2]); + + TEST_ASSERT_EQUAL(1, flags.size()); +} + +MARLIN_TEST(types, Flags_16) { + Flags<16> flags; + + flags.reset(); + TEST_ASSERT_EQUAL(0, flags.b); + + flags.set(0, true); + flags.set(15, true); + TEST_ASSERT_EQUAL(32769, flags.b); + + flags.clear(0); + TEST_ASSERT_EQUAL(32768, flags.b); + + flags.reset(); + flags.set(7, true); + flags.set(15, true); + TEST_ASSERT_EQUAL(true, flags.test(7)); + TEST_ASSERT_EQUAL(false, flags.test(8)); + TEST_ASSERT_EQUAL(true, flags.test(15)); + + TEST_ASSERT_EQUAL(true, flags[7]); + TEST_ASSERT_EQUAL(false, flags[8]); + TEST_ASSERT_EQUAL(true, flags[15]); + + TEST_ASSERT_EQUAL(2, flags.size()); +} + +MARLIN_TEST(types, Flags_32) { + Flags<32> flags; + + flags.reset(); + TEST_ASSERT_EQUAL(0, flags.b); + + flags.set(0, true); + flags.set(31, true); + TEST_ASSERT_EQUAL(2147483649, flags.b); + + flags.clear(0); + flags.clear(31); + TEST_ASSERT_EQUAL(0, flags.b); + + flags.set(0, true); + flags.set(31, true); + TEST_ASSERT_EQUAL(true, flags.test(0)); + TEST_ASSERT_EQUAL(true, flags.test(31)); + TEST_ASSERT_EQUAL(false, flags.test(1)); + TEST_ASSERT_EQUAL(false, flags.test(30)); + + TEST_ASSERT_EQUAL(true, flags[0]); + TEST_ASSERT_EQUAL(true, flags[31]); + TEST_ASSERT_EQUAL(false, flags[1]); + TEST_ASSERT_EQUAL(false, flags[30]); + + TEST_ASSERT_EQUAL(4, flags.size()); +} + +MARLIN_TEST(types, AxisFlags_const_as_bools) { + const AxisFlags axis_flags_const_false = {0}; + TEST_ASSERT_FALSE(axis_flags_const_false); + + const AxisFlags axis_flags_const_true = {1}; + TEST_ASSERT_TRUE(axis_flags_const_true); +} + +MARLIN_TEST(types, AxisFlags_non_const_as_bools) { + AxisFlags axis_flags_false = {0}; + TEST_ASSERT_FALSE(axis_flags_false); + + AxisFlags axis_flags_true = {1}; + TEST_ASSERT_TRUE(axis_flags_true); +} + +MARLIN_TEST(types, AxisBits_const_as_bools) { + const AxisBits axis_bits_const_false = {0}; + TEST_ASSERT_FALSE(axis_bits_const_false); + + const AxisBits axis_bits_const_true = {1}; + TEST_ASSERT_TRUE(axis_bits_const_true); +} + +MARLIN_TEST(types, AxisBits_non_const_as_bools) { + AxisBits axis_bits_false = {0}; + TEST_ASSERT_FALSE(axis_bits_false); + + AxisBits axis_bits_true = {1}; + TEST_ASSERT_TRUE(axis_bits_true); +} + +MARLIN_TEST(types, MString1) { + // String with cutoff at 20 chars: + // "F-string, 1234.50, 2" + MString<20> str20; + str20 = F("F-string, "); + str20.append(1234.5f).append(',').append(' ') + .append(2345.67).append(',').append(' '); + + TEST_ASSERT_TRUE(strcmp_P(str20, PSTR("F-string, 1234.50, 2")) == 0); + + // Truncate to "F-string" + str20.trunc(8); + + TEST_ASSERT_FALSE(strcmp_P(&str20, PSTR("F-string")) != 0); +} + +MARLIN_TEST(types, MString2) { + // 100 dashes, but chopped down to DEFAULT_MSTRING_SIZE (20) + TEST_ASSERT_TRUE(TSS(repchr_t('-', 100)).length() == 20); +} + +MARLIN_TEST(types, SString) { + // Hello World!-123456------ < spaces!33 + // ^ eol! ... 1234.50*2345.602 = 2895645.67 + SString<100> str(F("Hello")); + str.append(F(" World!")); + str += '-'; + str += uint8_t(123); + str += F("456"); + str += repchr_t('-', 6); + str += Spaces(3); + str += "< spaces!"; + str += int8_t(33); + str.eol(); + str += "^ eol!"; + str.append(" ... ", 1234.5f, '*', p_float_t(2345.602, 3), F(" = "), 1234.5 * 2345.602); + + TEST_ASSERT_TRUE(strcmp_P(str, PSTR("Hello World!-123456------ < spaces!33\n^ eol! ... 1234.50*2345.602 = 2895645.67")) == 0); +} diff --git a/Marlin/tests/runout/test_runout_sensor.cpp b/Marlin/tests/feature/test_runout.cpp similarity index 100% rename from Marlin/tests/runout/test_runout_sensor.cpp rename to Marlin/tests/feature/test_runout.cpp diff --git a/Marlin/tests/types/test_types.cpp b/Marlin/tests/types/test_types.cpp deleted file mode 100644 index 11ed19f4c3..0000000000 --- a/Marlin/tests/types/test_types.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/** - * Marlin 3D Printer Firmware - * Copyright (c) 2024 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] - * - * Based on Sprinter and grbl. - * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm - * - * This program 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. - * - * This program 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 this program. If not, see . - * - */ - -#include "../test/unit_tests.h" -#include "src/core/types.h" - -MARLIN_TEST(types, XYval_const_as_bools) { - const XYval xy_const_true = {1, 2}; - TEST_ASSERT_TRUE(xy_const_true); - - const XYval xy_const_false = {0, 0}; - TEST_ASSERT_FALSE(xy_const_false); -} - -MARLIN_TEST(types, XYval_non_const_as_bools) { - XYval xy_true = {1, 2}; - TEST_ASSERT_TRUE(xy_true); - - XYval xy_false = {0, 0}; - TEST_ASSERT_FALSE(xy_false); -} - -MARLIN_TEST(types, XYZval_const_as_bools) { - const XYZval xyz_const_true = {1, 2, 3}; - TEST_ASSERT_TRUE(xyz_const_true); - - const XYZval xyz_const_false = {0, 0, 0}; - TEST_ASSERT_FALSE(xyz_const_false); -} - -MARLIN_TEST(types, XYZval_non_const_as_bools) { - XYZval xyz_true = {1, 2, 3}; - TEST_ASSERT_TRUE(xyz_true); - - XYZval xyz_false = {0, 0, 0}; - TEST_ASSERT_FALSE(xyz_false); -} - -MARLIN_TEST(types, XYZEval_const_as_bools) { - const XYZEval xyze_const_true = {1, 2, 3, 4}; - TEST_ASSERT_TRUE(xyze_const_true); - - const XYZEval xyze_const_false = {0, 0, 0, 0}; - TEST_ASSERT_FALSE(xyze_const_false); -} - -MARLIN_TEST(types, XYZEval_non_const_as_bools) { - XYZEval xyze_true = {1, 2, 3, 4}; - TEST_ASSERT_TRUE(xyze_true); - - XYZEval xyze_false = {0, 0, 0, 0}; - TEST_ASSERT_FALSE(xyze_false); -} - -MARLIN_TEST(types, Flags_const_as_bools) { - const Flags<32> flags_const_false = {0}; - TEST_ASSERT_FALSE(flags_const_false); - - const Flags<32> flags_const_true = {1}; - TEST_ASSERT_TRUE(flags_const_true); -} - -MARLIN_TEST(types, Flags_non_const_as_bools) { - Flags<32> flags_false = {0}; - TEST_ASSERT_FALSE(flags_false); - - Flags<32> flags_true = {1}; - TEST_ASSERT_TRUE(flags_true); -} - -MARLIN_TEST(types, AxisFlags_const_as_bools) { - const AxisFlags axis_flags_const_false = {0}; - TEST_ASSERT_FALSE(axis_flags_const_false); - - const AxisFlags axis_flags_const_true = {1}; - TEST_ASSERT_TRUE(axis_flags_const_true); -} - -MARLIN_TEST(types, AxisFlags_non_const_as_bools) { - AxisFlags axis_flags_false = {0}; - TEST_ASSERT_FALSE(axis_flags_false); - - AxisFlags axis_flags_true = {1}; - TEST_ASSERT_TRUE(axis_flags_true); -} - -MARLIN_TEST(types, AxisBits_const_as_bools) { - const AxisBits axis_bits_const_false = {0}; - TEST_ASSERT_FALSE(axis_bits_const_false); - - const AxisBits axis_bits_const_true = {1}; - TEST_ASSERT_TRUE(axis_bits_const_true); -} - -MARLIN_TEST(types, AxisBits_non_const_as_bools) { - AxisBits axis_bits_false = {0}; - TEST_ASSERT_FALSE(axis_bits_false); - - AxisBits axis_bits_true = {1}; - TEST_ASSERT_TRUE(axis_bits_true); -} - -MARLIN_TEST(types, MString1) { - // String with cutoff at 20 chars: - // "F-string, 1234.50, 2" - MString<20> str20; - str20 = F("F-string, "); - str20.append(1234.5f).append(',').append(' ') - .append(2345.67).append(',').append(' '); - - TEST_ASSERT_TRUE(strcmp_P(str20, PSTR("F-string, 1234.50, 2")) == 0); - - // Truncate to "F-string" - str20.trunc(8); - - TEST_ASSERT_FALSE(strcmp_P(&str20, PSTR("F-string")) != 0); -} - -MARLIN_TEST(types, MString2) { - // 100 dashes, but chopped down to DEFAULT_MSTRING_SIZE (20) - TEST_ASSERT_TRUE(TSS(repchr_t('-', 100)).length() == 20); -} - -MARLIN_TEST(types, SString) { - // Hello World!-123456------ < spaces!33 - // ^ eol! ... 1234.50*2345.602 = 2895645.67 - SString<100> str(F("Hello")); - str.append(F(" World!")); - str += '-'; - str += uint8_t(123); - str += F("456"); - str += repchr_t('-', 6); - str += Spaces(3); - str += "< spaces!"; - str += int8_t(33); - str.eol(); - str += "^ eol!"; - str.append(" ... ", 1234.5f, '*', p_float_t(2345.602, 3), F(" = "), 1234.5 * 2345.602); - - TEST_ASSERT_TRUE(strcmp_P(str, PSTR("Hello World!-123456------ < spaces!33\n^ eol! ... 1234.50*2345.602 = 2895645.67")) == 0); -} diff --git a/buildroot/bin/restore_configs b/buildroot/bin/restore_configs index 51f72c5792..e1a601679b 100755 --- a/buildroot/bin/restore_configs +++ b/buildroot/bin/restore_configs @@ -7,5 +7,6 @@ if [[ $1 == '-d' || $1 == '--default' ]]; then else git checkout Marlin/Configuration.h 2>/dev/null git checkout Marlin/Configuration_adv.h 2>/dev/null + git checkout Marlin/config.ini 2>/dev/null git checkout Marlin/src/pins/*/pins_*.h 2>/dev/null fi diff --git a/buildroot/share/git/mfhelp b/buildroot/share/git/mfhelp index 46a0ebfc53..aff34b866f 100755 --- a/buildroot/share/git/mfhelp +++ b/buildroot/share/git/mfhelp @@ -41,6 +41,6 @@ Modify Configuration.h / Configuration_adv.h: Modify pins files: pins_set ............. Set the value of a pin in a pins file - pinsformat.js ........ Node.js script to format pins files + pinsformat.py ........ Python script to format pins files THIS diff --git a/buildroot/share/scripts/get_test_targets.py b/buildroot/share/scripts/get_test_targets.py index f51951ae12..b187de9cac 100644 --- a/buildroot/share/scripts/get_test_targets.py +++ b/buildroot/share/scripts/get_test_targets.py @@ -5,7 +5,7 @@ Extract the builds used in Github CI, so that we can run them locally import yaml # Set the yaml file to parse -yaml_file = '.github/workflows/test-builds.yml' +yaml_file = '.github/workflows/ci-build-tests.yml' # Parse the yaml file, and load it into a dictionary (github_configuration) with open(yaml_file) as f: diff --git a/buildroot/share/scripts/pinsformat.js b/buildroot/share/scripts/pinsformat.js deleted file mode 100755 index 16e9dcb88f..0000000000 --- a/buildroot/share/scripts/pinsformat.js +++ /dev/null @@ -1,197 +0,0 @@ -#!/usr/bin/env node - -// -// Formatter script for pins_MYPINS.h files -// -// Usage: mffmt [infile] [outfile] -// -// With no parameters convert STDIN to STDOUT -// - -const fs = require("fs"); - -var do_log = false -function logmsg(msg, line='') { - if (do_log) console.log(msg, line); -} - -// String lpad / rpad -String.prototype.lpad = function(len, chr) { - if (!len) return this; - if (chr === undefined) chr = ' '; - var s = this+'', need = len - s.length; - if (need > 0) s = new Array(need+1).join(chr) + s; - return s; -}; - -String.prototype.rpad = function(len, chr) { - if (!len) return this; - if (chr === undefined) chr = ' '; - var s = this+'', need = len - s.length; - if (need > 0) s += new Array(need+1).join(chr); - return s; -}; - -// Concatenate a string, adding a space if necessary -// to avoid merging two words -String.prototype.concat_with_space = function(str) { - const c = this.substr(-1), d = str.charAt(0); - if (c !== ' ' && c !== '' && d !== ' ' && d !== '') - str = ' ' + str; - return this + str; -}; - -const mpatt = [ '-?\\d{1,3}', 'P[A-I]\\d+', 'P\\d_\\d+', 'Pin[A-Z]\\d\\b' ], - definePatt = new RegExp(`^\\s*(//)?#define\\s+[A-Z_][A-Z0-9_]+\\s+(${mpatt.join('|')})\\s*(//.*)?$`, 'gm'), - ppad = [ 3, 4, 5, 5 ], - col_comment = 50, - col_value_rj = col_comment - 3; - -var mexpr = []; -for (let m of mpatt) mexpr.push(new RegExp('^' + m + '$')); - -const argv = process.argv.slice(2), argc = argv.length; - -var src_file = 0, dst_file; -if (argc > 0) { - let ind = 0; - if (argv[0] == '-v') { do_log = true; ind++; } - dst_file = src_file = argv[ind++]; - if (ind < argc) dst_file = argv[ind]; -} - -// Read from file or STDIN until it terminates -const filtered = process_text(fs.readFileSync(src_file).toString()); -if (dst_file) - fs.writeFileSync(dst_file, filtered); -else - console.log(filtered); - -// Find the pin pattern so non-pin defines can be skipped -function get_pin_pattern(txt) { - var r, m = 0, match_count = [ 0, 0, 0, 0 ]; - var max_match_count = 0, max_match_index = -1; - definePatt.lastIndex = 0; - while ((r = definePatt.exec(txt)) !== null) { - let ind = -1; - if (mexpr.some((p) => { - ind++; - const didmatch = r[2].match(p); - return r[2].match(p); - }) ) { - const m = ++match_count[ind]; - if (m > max_match_count) { - max_match_count = m; - max_match_index = ind; - } - } - } - if (max_match_index === -1) return null; - - return { match:mpatt[max_match_index], pad:ppad[max_match_index] }; -} - -function process_text(txt) { - if (!txt.length) return '(no text)'; - const patt = get_pin_pattern(txt); - if (!patt) return txt; - const pindefPatt = new RegExp(`^(\\s*(//)?#define)\\s+([A-Z_][A-Z0-9_]+)\\s+(${patt.match})\\s*(//.*)?$`), - noPinPatt = new RegExp(`^(\\s*(//)?#define)\\s+([A-Z_][A-Z0-9_]+)\\s+(-1)\\s*(//.*)?$`), - skipPatt1 = new RegExp('^(\\s*(//)?#define)\\s+(AT90USB|USBCON|(BOARD|DAC|FLASH|HAS|IS|USE)_.+|.+_(ADDRESS|AVAILABLE|BAUDRATE|CLOCK|CONNECTION|DEFAULT|ERROR|EXTRUDERS|FREQ|ITEM|MKS_BASE_VERSION|MODULE|NAME|ONLY|ORIENTATION|PERIOD|RANGE|RATE|READ_RETRIES|SERIAL|SIZE|SPI|STATE|STEP|TIMER|VERSION))\\s+(.+)\\s*(//.*)?$'), - skipPatt2 = new RegExp('^(\\s*(//)?#define)\\s+([A-Z_][A-Z0-9_]+)\\s+(0x[0-9A-Fa-f]+|\d+|.+[a-z].+)\\s*(//.*)?$'), - skipPatt3 = /^\s*#e(lse|ndif)\b.*$/, - aliasPatt = new RegExp('^(\\s*(//)?#define)\\s+([A-Z_][A-Z0-9_]+)\\s+([A-Z_][A-Z0-9_()]+)\\s*(//.*)?$'), - switchPatt = new RegExp('^(\\s*(//)?#define)\\s+([A-Z_][A-Z0-9_]+)\\s*(//.*)?$'), - undefPatt = new RegExp('^(\\s*(//)?#undef)\\s+([A-Z_][A-Z0-9_]+)\\s*(//.*)?$'), - defPatt = new RegExp('^(\\s*(//)?#define)\\s+([A-Z_][A-Z0-9_]+)\\s+([-_\\w]+)\\s*(//.*)?$'), - condPatt = new RegExp('^(\\s*(//)?#(if|ifn?def|elif)(\\s+\\S+)*)\\s+(//.*)$'), - commPatt = new RegExp('^\\s{20,}(//.*)?$'); - const col_value_lj = col_comment - patt.pad - 2; - var r, out = '', check_comment_next = false; - txt.split('\n').forEach((line) => { - if (check_comment_next) - check_comment_next = ((r = commPatt.exec(line)) !== null); - - if (check_comment_next) - // Comments in column 45 - line = ''.rpad(col_comment) + r[1]; - - else if (skipPatt1.exec(line) !== null) { - // - // #define SKIP_ME - // - logmsg("skip:", line); - } - else if ((r = pindefPatt.exec(line)) !== null) { - // - // #define MY_PIN [pin] - // - logmsg("pin:", line); - const pinnum = r[4].charAt(0) == 'P' ? r[4] : r[4].lpad(patt.pad); - line = r[1] + ' ' + r[3]; - line = line.rpad(col_value_lj).concat_with_space(pinnum); - if (r[5]) line = line.rpad(col_comment).concat_with_space(r[5]); - } - else if ((r = noPinPatt.exec(line)) !== null) { - // - // #define MY_PIN -1 - // - logmsg("pin -1:", line); - line = r[1] + ' ' + r[3]; - line = line.rpad(col_value_lj).concat_with_space('-1'); - if (r[5]) line = line.rpad(col_comment).concat_with_space(r[5]); - } - else if (skipPatt2.exec(line) !== null || skipPatt3.exec(line) !== null) { - // - // #define SKIP_ME - // #else, #endif - // - logmsg("skip:", line); - } - else if ((r = aliasPatt.exec(line)) !== null) { - // - // #define ALIAS OTHER - // - logmsg("alias:", line); - line = r[1] + ' ' + r[3]; - line = line.concat_with_space(r[4].lpad(col_value_rj + 1 - line.length)); - if (r[5]) line = line.rpad(col_comment).concat_with_space(r[5]); - } - else if ((r = switchPatt.exec(line)) !== null) { - // - // #define SWITCH - // - logmsg("switch:", line); - line = r[1] + ' ' + r[3]; - if (r[4]) line = line.rpad(col_comment).concat_with_space(r[4]); - check_comment_next = true; - } - else if ((r = defPatt.exec(line)) !== null) { - // - // #define ... - // - logmsg("def:", line); - line = r[1] + ' ' + r[3] + ' '; - line = line.concat_with_space(r[4].lpad(col_value_rj + 1 - line.length)); - if (r[5]) line = line.rpad(col_comment - 1) + ' ' + r[5]; - } - else if ((r = undefPatt.exec(line)) !== null) { - // - // #undef ... - // - logmsg("undef:", line); - line = r[1] + ' ' + r[3]; - if (r[4]) line = line.rpad(col_comment).concat_with_space(r[4]); - } - else if ((r = condPatt.exec(line)) !== null) { - // - // #if, #ifdef, #ifndef, #elif ... - // - logmsg("cond:", line); - line = r[1].rpad(col_comment).concat_with_space(r[5]); - check_comment_next = true; - } - out += line + '\n'; - }); - return out.replace(/\n\n+/g, '\n\n').replace(/\n\n$/g, '\n'); -} diff --git a/buildroot/share/scripts/pinsformat.py b/buildroot/share/scripts/pinsformat.py index b49ae4931d..e4bd69d855 100755 --- a/buildroot/share/scripts/pinsformat.py +++ b/buildroot/share/scripts/pinsformat.py @@ -27,6 +27,13 @@ def rpad(astr, fill, c=' '): need = fill - len(astr) return astr if need <= 0 else astr + (need * c) +# Concatenate a string, adding a space if necessary +# to avoid merging two words +def concat_with_space(s1, s2): + if not s1.endswith(' ') and not s2.startswith(' '): + s1 += ' ' + return s1 + s2 + # Pin patterns mpatt = [ r'-?\d{1,3}', r'P[A-I]\d+', r'P\d_\d+', r'Pin[A-Z]\d\b' ] mstr = '|'.join(mpatt) @@ -45,6 +52,7 @@ def format_pins(argv): scnt = 0 for arg in argv: if arg == '-v': + global do_log do_log = True elif scnt == 0: # Get a source file if specified. Default destination is the same file @@ -135,7 +143,7 @@ def process_text(txt): logmsg("pin:", line) pinnum = r[4] if r[4][0] == 'P' else lpad(r[4], patt['pad']) line = f'{r[1]} {r[3]}' - line = rpad(line, col_value_lj) + pinnum + line = concat_with_space(rpad(line, col_value_lj), pinnum) if r[5]: line = rpad(line, col_comment) + r[5] d['line'] = line return True @@ -149,7 +157,7 @@ def process_text(txt): if r == None: return False logmsg("pin -1:", line) line = f'{r[1]} {r[3]}' - line = rpad(line, col_value_lj) + '-1' + line = concat_with_space(rpad(line, col_value_lj), '-1') if r[5]: line = rpad(line, col_comment) + r[5] d['line'] = line return True @@ -179,8 +187,8 @@ def process_text(txt): if r == None: return False logmsg("alias:", line) line = f'{r[1]} {r[3]}' - line += lpad(r[4], col_value_rj + 1 - len(line)) - if r[5]: line = rpad(line, col_comment) + r[5] + line = concat_with_space(line, lpad(r[4], col_value_rj + 1 - len(line))) + if r[5]: line = concat_with_space(rpad(line, col_comment), r[5]) d['line'] = line return True @@ -193,7 +201,7 @@ def process_text(txt): if r == None: return False logmsg("switch:", line) line = f'{r[1]} {r[3]}' - if r[4]: line = rpad(line, col_comment) + r[4] + if r[4]: line = concat_with_space(rpad(line, col_comment), r[4]) d['line'] = line d['check_comment_next'] = True return True @@ -207,7 +215,7 @@ def process_text(txt): if r == None: return False logmsg("def:", line) line = f'{r[1]} {r[3]} ' - line += lpad(r[4], col_value_rj + 1 - len(line)) + line = concat_with_space(line, lpad(r[4], col_value_rj + 1 - len(line))) if r[5]: line = rpad(line, col_comment - 1) + ' ' + r[5] d['line'] = line return True @@ -221,7 +229,7 @@ def process_text(txt): if r == None: return False logmsg("undef:", line) line = f'{r[1]} {r[3]}' - if r[4]: line = rpad(line, col_comment) + r[4] + if r[4]: line = concat_with_space(rpad(line, col_comment), r[4]) d['line'] = line return True @@ -233,7 +241,7 @@ def process_text(txt): r = condPatt.match(line) if r == None: return False logmsg("cond:", line) - line = rpad(r[1], col_comment) + r[5] + line = concat_with_space(rpad(r[1], col_comment), r[5]) d['line'] = line d['check_comment_next'] = True return True diff --git a/ini/hc32.ini b/ini/hc32.ini index 2af761128c..c9533bad17 100644 --- a/ini/hc32.ini +++ b/ini/hc32.ini @@ -34,7 +34,7 @@ build_type = release build_flags = -D ARDUINO_ARCH_HC32 -D PLATFORM_M997_SUPPORT # Enable M997 command - # note: ddl and arduino debug mode are + # note: ddl and arduino debug mode are # automatically enabled with MARLIN_DEV_MODE #-D __DEBUG # force DDL debug mode #-D __CORE_DEBUG # force Arduino core debug mode diff --git a/ini/native.ini b/ini/native.ini index 9df621172d..bbb6724dae 100644 --- a/ini/native.ini +++ b/ini/native.ini @@ -32,7 +32,7 @@ extra_scripts = ${common.extra_scripts} build_src_filter = ${env:linux_native.build_src_filter} + lib_deps = throwtheswitch/Unity@^2.5.2 test_build_src = true -build_unflags = +build_unflags = build_flags = ${env:linux_native.build_flags} -Werror #