Merge branch 'bugfix-2.1.x' into pr/27013

This commit is contained in:
Scott Lahteine
2024-05-11 12:36:20 -05:00
87 changed files with 1984 additions and 1355 deletions
+4
View File
@@ -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:
+51
View File
@@ -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
+33 -20
View File
@@ -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=<your-module> 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=<your-module> 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)
+2 -1
View File
@@ -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
+1 -1
View File
@@ -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.
+19
View File
@@ -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
//
+2 -2
View File
@@ -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,
+2 -2
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
+3 -3
View File
@@ -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)
+5 -5
View File
@@ -143,13 +143,13 @@ public:
// Set with format string and arguments, like printf
template<typename... Args>
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<typename... Args>
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<typename... Args>
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<typename... Args>
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;
}
+3 -3
View File
@@ -271,13 +271,13 @@ public:
SString& set() { super::set(); return *this; }
template<typename... Args>
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<typename... Args>
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<typename... Args>
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 <typename T>
SString& set(const T &v) { super::set(v); return *this; }
+10 -2
View File
@@ -46,6 +46,7 @@ template <class L, class R> struct IF<true, L, R> { 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 <class L, class R> struct IF<true, L, R> { 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 <class L, class R> struct IF<true, L, R> { 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 <class L, class R> struct IF<true, L, R> { 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 <class L, class R> struct IF<true, L, R> { typedef L type; };
// General Flags for some number of states
template<size_t N>
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); }
+3 -3
View File
@@ -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
+1 -1
View File
@@ -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() {
+2 -2
View File
@@ -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]);
+1 -1
View File
@@ -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();
+1 -1
View File
@@ -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
+19 -12
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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
/**
+10 -6
View File
@@ -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
+2 -2
View File
@@ -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))
+2 -2
View File
@@ -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;
}
}
+24 -72
View File
@@ -42,10 +42,6 @@
#include <stdlib.h>
#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;
}
-3
View File
@@ -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();
-1
View File
@@ -4078,7 +4078,6 @@ void hmiInit() {
}
void dwinInitScreen() {
encoderConfiguration();
hmiInit();
hmiSetLanguageCache();
hmiStartFrame(true);
-1
View File
@@ -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);
+6 -6
View File
@@ -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() {
+1 -1
View File
@@ -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
+2 -2
View File
@@ -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")));
}
+1 -1
View File
@@ -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;
@@ -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);
@@ -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 <lv_misc/lv_log.h>
typedef void (*lv_log_print_g_cb_t)(lv_log_level_t level, const char *, uint32_t, const char *);
@@ -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);
+210 -196
View File
@@ -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);
+5
View File
@@ -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);
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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));
+9 -6
View File
@@ -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);
+40 -7
View File
@@ -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
+88 -66
View File
@@ -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;
+12
View File
@@ -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;
+2
View File
@@ -47,7 +47,9 @@ enum dynFreqMode_t : uint8_t {
typedef struct XYZEarray<float, FTM_WINDOW_SIZE> xyze_trajectory_t;
typedef struct XYZEarray<float, FTM_BATCH_SIZE> 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,
+22 -13
View File
@@ -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(
+4 -3
View File
@@ -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()); }
+234 -140
View File
@@ -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;
}
+3
View File
@@ -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
+5 -4
View File
@@ -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::AutoReportTemp> 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) {
+18 -14
View File
@@ -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;
}
};
+18
View File
@@ -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
+5 -2
View File
@@ -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
@@ -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
+12 -12
View File
@@ -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
+2 -2
View File
@@ -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
+21 -9
View File
@@ -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
@@ -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
+20 -16
View File
@@ -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
+20 -16
View File
@@ -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
@@ -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
/**
@@ -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
+10 -5
View File
@@ -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
//
@@ -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
@@ -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.
@@ -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
//
+14 -12
View File
@@ -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
@@ -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
//
@@ -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
//
@@ -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
@@ -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
//
@@ -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
//
+190 -101
View File
@@ -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
@@ -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
@@ -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
//
@@ -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
//
+1 -1
View File
@@ -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;
+605
View File
@@ -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 <https://www.gnu.org/licenses/>.
*
*/
#include "../test/unit_tests.h"
#include "src/core/types.h"
MARLIN_TEST(types, XYval_const_as_bools) {
const XYval<int> xy_const_true = {1, 2};
TEST_ASSERT_TRUE(xy_const_true);
const XYval<int> xy_const_false = {0, 0};
TEST_ASSERT_FALSE(xy_const_false);
}
MARLIN_TEST(types, XYval_non_const_as_bools) {
XYval<int> xy_true = {1, 2};
TEST_ASSERT_TRUE(xy_true);
XYval<int> xy_false = {0, 0};
TEST_ASSERT_FALSE(xy_false);
}
MARLIN_TEST(types, XYval_reset) {
XYval<int> xy = {1, 2};
xy.reset();
TEST_ASSERT_EQUAL(0, xy.x);
TEST_ASSERT_EQUAL(0, xy.y);
}
MARLIN_TEST(types, XYval_set) {
XYval<int> xy;
xy.set(3, 4);
TEST_ASSERT_EQUAL(3, xy.x);
TEST_ASSERT_EQUAL(4, xy.y);
}
MARLIN_TEST(types, XYval_magnitude) {
XYval<int> 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<int> 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<int> xy1 = {2, 3}, xy2 = {6, 12};
XYval<int> 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<int> xy = {-3, -4};
XYval<int> xy_abs = xy.ABS();
TEST_ASSERT_EQUAL(3, xy_abs.x);
TEST_ASSERT_EQUAL(4, xy_abs.y);
}
MARLIN_TEST(types, XYval_ROUNDL) {
XYval<float> 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<float> xy = {0.5f, 4.0f};
XYval<float> 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<int> xyz_const_true = {1, 2, 3};
TEST_ASSERT_TRUE(xyz_const_true);
const XYZval<int> xyz_const_false = {0, 0, 0};
TEST_ASSERT_FALSE(xyz_const_false);
}
MARLIN_TEST(types, XYZval_non_const_as_bools) {
XYZval<int> xyz_true = {1, 2, 3};
TEST_ASSERT_TRUE(xyz_true);
XYZval<int> xyz_false = {0, 0, 0};
TEST_ASSERT_FALSE(xyz_false);
}
MARLIN_TEST(types, XYZval_reset) {
XYZval<int> 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<int> 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<float> 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<int> 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<int> xyz1 = {2, 3, 4}, xyz2 = {6, 12, 24};
XYZval<int> 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<int> xyz = {-3, -4, -5};
XYZval<int> 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<float> xyz = {3.3f, 4.7f, 5.5f};
XYZval<int> 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<float> xyz = {0.5f, 2.0f, 0.33333f};
XYZval<float> 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<int> xyze_const_true = {1, 2, 3, 4};
TEST_ASSERT_TRUE(xyze_const_true);
const XYZEval<int> xyze_const_false = {0, 0, 0, 0};
TEST_ASSERT_FALSE(xyze_const_false);
}
MARLIN_TEST(types, XYZEval_non_const_as_bools) {
XYZEval<int> xyze_true = {1, 2, 3, 4};
TEST_ASSERT_TRUE(xyze_true);
XYZEval<int> xyze_false = {0, 0, 0, 0};
TEST_ASSERT_FALSE(xyze_false);
}
MARLIN_TEST(types, XYZEval_reset) {
XYZEval<int> 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<int> 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<float> 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<int> 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<int> xyze1 = {2, 3, 4, 5}, xyze2 = {6, 12, 24, 48};
XYZEval<int> 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<int> xyze = {-3, -4, -5, -6};
XYZEval<int> 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<float> xyze = {3.3f, 4.7f, 5.5f, 6.6f};
XYZEval<int> 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<float> xyze = {0.5f, 2.0f, 0.33333f, 0.25f};
XYZEval<float> 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);
}
-160
View File
@@ -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 <https://www.gnu.org/licenses/>.
*
*/
#include "../test/unit_tests.h"
#include "src/core/types.h"
MARLIN_TEST(types, XYval_const_as_bools) {
const XYval<int> xy_const_true = {1, 2};
TEST_ASSERT_TRUE(xy_const_true);
const XYval<int> xy_const_false = {0, 0};
TEST_ASSERT_FALSE(xy_const_false);
}
MARLIN_TEST(types, XYval_non_const_as_bools) {
XYval<int> xy_true = {1, 2};
TEST_ASSERT_TRUE(xy_true);
XYval<int> xy_false = {0, 0};
TEST_ASSERT_FALSE(xy_false);
}
MARLIN_TEST(types, XYZval_const_as_bools) {
const XYZval<int> xyz_const_true = {1, 2, 3};
TEST_ASSERT_TRUE(xyz_const_true);
const XYZval<int> xyz_const_false = {0, 0, 0};
TEST_ASSERT_FALSE(xyz_const_false);
}
MARLIN_TEST(types, XYZval_non_const_as_bools) {
XYZval<int> xyz_true = {1, 2, 3};
TEST_ASSERT_TRUE(xyz_true);
XYZval<int> xyz_false = {0, 0, 0};
TEST_ASSERT_FALSE(xyz_false);
}
MARLIN_TEST(types, XYZEval_const_as_bools) {
const XYZEval<int> xyze_const_true = {1, 2, 3, 4};
TEST_ASSERT_TRUE(xyze_const_true);
const XYZEval<int> xyze_const_false = {0, 0, 0, 0};
TEST_ASSERT_FALSE(xyze_const_false);
}
MARLIN_TEST(types, XYZEval_non_const_as_bools) {
XYZEval<int> xyze_true = {1, 2, 3, 4};
TEST_ASSERT_TRUE(xyze_true);
XYZEval<int> 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);
}
+1
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -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:
-197
View File
@@ -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');
}
+16 -8
View File
@@ -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
+1 -1
View File
@@ -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
+1 -1
View File
@@ -32,7 +32,7 @@ extra_scripts = ${common.extra_scripts}
build_src_filter = ${env:linux_native.build_src_filter} +<tests>
lib_deps = throwtheswitch/Unity@^2.5.2
test_build_src = true
build_unflags =
build_unflags =
build_flags = ${env:linux_native.build_flags} -Werror
#