Compare commits

..

20 Commits

Author SHA1 Message Date
Scott Lahteine dc6d166567 Merge remote-tracking branch 'upstream/bugfix-2.1.x' into pr/26944 2025-12-02 12:14:56 -06:00
Scott Lahteine bf7433c937 make a friend 2025-11-18 12:15:12 -06:00
Scott Lahteine 81a9eb27ad use handlers 2025-11-18 12:05:18 -06:00
Scott Lahteine 6ed3ea9a6b ws 2025-11-18 11:11:24 -06:00
Scott Lahteine 371ab1eea2 Add BUTTON*_IMMEDIATE option 2025-11-18 11:02:10 -06:00
Scott Lahteine e38075710d Menu item to run a G-code now 2025-11-18 10:48:36 -06:00
Scott Lahteine ea2e832dc8 Merge branch 'bugfix-2.1.x' into pr/26944 2025-11-18 10:25:09 -06:00
Scott Lahteine 09e336f78c Merge branch 'bugfix-2.1.x' into pr/26944 2025-05-27 00:09:04 -05:00
InsanityAutomation 471228018a Merge branch 'bugfix-2.1.x' into ParseSafetyCommandsEvenWithEParser 2025-05-13 16:17:41 -04:00
InsanityAutomation 766210b8f1 Merge branch 'ParseSafetyCommandsEvenWithEParser' of https://github.com/InsanityAutomation/Marlin into ParseSafetyCommandsEvenWithEParser 2025-04-18 13:39:47 -04:00
InsanityAutomation b5c05e32ea Update M876.cpp 2025-04-18 13:39:36 -04:00
InsanityAutomation 1d702b3601 Merge branch 'bugfix-2.1.x' into ParseSafetyCommandsEvenWithEParser 2025-04-18 13:38:14 -04:00
InsanityAutomation 2e7b7c8b72 Update pause.cpp 2025-04-18 13:36:38 -04:00
Scott Lahteine a4fbbf9075 clean up 2025-03-17 19:46:43 -05:00
Scott Lahteine 25e6852022 Merge branch 'bugfix-2.1.x' into pr/26944 2025-03-17 18:06:41 -05:00
Scott Lahteine 5edec5b3a3 tweak 2025-03-17 18:06:18 -05:00
InsanityAutomation 0bfa253b73 Use getter 2024-04-10 15:15:24 -04:00
InsanityAutomation 1117aff777 Merge branch 'MarlinFirmware:bugfix-2.1.x' into ParseSafetyCommandsEvenWithEParser 2024-04-07 18:59:07 -04:00
InsanityAutomation b616b0a67a Update Conditionals_adv.h 2024-04-07 13:24:13 -04:00
InsanityAutomation bca0f55a5e Always parse safety commands at all levels 2024-04-07 13:13:15 -04:00
610 changed files with 25159 additions and 29676 deletions
+10 -10
View File
@@ -8,19 +8,19 @@ In the interest of fostering an open and welcoming environment, we as contributo
Examples of behavior that contributes to creating a positive environment include: Examples of behavior that contributes to creating a positive environment include:
- Using welcoming and inclusive language * Using welcoming and inclusive language
- Being respectful of differing viewpoints and experiences * Being respectful of differing viewpoints and experiences
- Gracefully accepting constructive criticism * Gracefully accepting constructive criticism
- Focusing on what is best for the community * Focusing on what is best for the community
- Showing empathy towards other community members * Showing empathy towards other community members
Examples of unacceptable behavior by participants include: Examples of unacceptable behavior by participants include:
- The use of sexualized language or imagery and unwelcome sexual attention or advances * The use of sexualized language or imagery and unwelcome sexual attention or advances
- Trolling, insulting/derogatory comments, and personal or political attacks * Trolling, insulting/derogatory comments, and personal or political attacks
- Public or private harassment * Public or private harassment
- Publishing others' private information, such as a physical or electronic address, without explicit permission * Publishing others' private information, such as a physical or electronic address, without explicit permission
- Other conduct which could reasonably be considered inappropriate in a professional setting * Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities ## Our Responsibilities
+53 -58
View File
@@ -11,21 +11,18 @@ The following is a set of guidelines for contributing to Marlin, hosted by the [
[I don't want to read this whole thing, I just have a question!!!](#i-dont-want-to-read-this-whole-thing-i-just-have-a-question) [I don't want to read this whole thing, I just have a question!!!](#i-dont-want-to-read-this-whole-thing-i-just-have-a-question)
[How Can I Contribute?](#how-can-i-contribute) [How Can I Contribute?](#how-can-i-contribute)
* [Reporting Bugs](#reporting-bugs)
- [Reporting Bugs](#reporting-bugs) * [Suggesting Features or Changes](#suggesting-features-or-changes)
- [Suggesting Features or Changes](#suggesting-features-or-changes) * [Your First Code Contribution](#your-first-code-contribution)
- [Your First Code Contribution](#your-first-code-contribution) * [Pull Requests](#pull-requests)
- [Pull Requests](#pull-requests)
[Styleguides](#styleguides) [Styleguides](#styleguides)
* [Git Commit Messages](#git-commit-messages)
- [Git Commit Messages](#git-commit-messages) * [C++ Coding Standards](#c++-coding-standards)
- [C++ Coding Standards](#c++-coding-standards) * [Documentation Styleguide](#documentation)
- [Documentation Styleguide](#documentation)
[Additional Notes](#additional-notes) [Additional Notes](#additional-notes)
* [Issue and Pull Request Labels](#issue-and-pull-request-labels)
- [Issue and Pull Request Labels](#issue-and-pull-request-labels)
## Code of Conduct ## Code of Conduct
@@ -34,7 +31,6 @@ This project and everyone participating in it is governed by the [Marlin Code of
## I don't want to read this whole thing I just have a question!!! ## I don't want to read this whole thing I just have a question!!!
> [!NOTE] > [!NOTE]
>
> Please don't file an issue to ask a question. You'll get faster results by using the resources below. > Please don't file an issue to ask a question. You'll get faster results by using the resources below.
We have a Message Board and a Facebook group where our knowledgable user community can provide helpful advice if you have questions. We have a Message Board and a Facebook group where our knowledgable user community can provide helpful advice if you have questions.
@@ -47,10 +43,10 @@ We have a Message Board and a Facebook group where our knowledgable user communi
If chat is more your speed, you can join the MarlinFirmware Discord server: If chat is more your speed, you can join the MarlinFirmware Discord server:
- Use the link https://discord.com/servers/marlin-firmware-461605380783472640 to join up as a General User. * Use the link https://discord.com/servers/marlin-firmware-461605380783472640 to join up as a General User.
- Even though our Discord is pretty active, it may take a while for community members to respond — please be patient! * Even though our Discord is pretty active, it may take a while for community members to respond — please be patient!
- Use the `#general` channel for general questions or discussion about Marlin. * Use the `#general` channel for general questions or discussion about Marlin.
- Other channels exist for certain topics or are limited to Patrons. Check the channel list. * Other channels exist for certain topics or are limited to Patrons. Check the channel list.
## How Can I Contribute? ## How Can I Contribute?
@@ -61,7 +57,6 @@ This section guides you through submitting a Bug Report for Marlin. Following th
Before creating a Bug Report, please test the "nightly" development branch, as you might find out that you don't need to create one. When you are creating a Bug Report, please [include as many details as possible](#how-do-i-submit-a-good-bug-report). Fill out [the required template](ISSUE_TEMPLATE/bug_report.yml), the information it asks for helps us resolve issues faster. Before creating a Bug Report, please test the "nightly" development branch, as you might find out that you don't need to create one. When you are creating a Bug Report, please [include as many details as possible](#how-do-i-submit-a-good-bug-report). Fill out [the required template](ISSUE_TEMPLATE/bug_report.yml), the information it asks for helps us resolve issues faster.
> [!NOTE] > [!NOTE]
>
> Regressions can happen. If you find a **Closed** issue that seems like your issue, go ahead and open a new issue and include a link to the original issue in the body of your new one. All you need to create a link is the issue number, preceded by #. For example, #8888. > Regressions can happen. If you find a **Closed** issue that seems like your issue, go ahead and open a new issue and include a link to the original issue in the body of your new one. All you need to create a link is the issue number, preceded by #. For example, #8888.
#### How Do I Submit A (Good) Bug Report? #### How Do I Submit A (Good) Bug Report?
@@ -70,29 +65,29 @@ Bugs are tracked as [GitHub issues](https://guides.github.com/features/issues/).
Explain the problem and include additional details to help maintainers reproduce the problem: Explain the problem and include additional details to help maintainers reproduce the problem:
- **Use a clear and descriptive title** for the issue to identify the problem. * **Use a clear and descriptive title** for the issue to identify the problem.
- **Describe the exact steps which reproduce the problem** in as many details as possible. For example, start by explaining how you started Marlin, e.g. which command exactly you used in the terminal, or how you started Marlin otherwise. When listing steps, **don't just say what you did, but explain how you did it**. For example, if you moved the cursor to the end of a line, explain if you used the mouse, or a keyboard shortcut or an Marlin command, and if so which one? * **Describe the exact steps which reproduce the problem** in as many details as possible. For example, start by explaining how you started Marlin, e.g. which command exactly you used in the terminal, or how you started Marlin otherwise. When listing steps, **don't just say what you did, but explain how you did it**. For example, if you moved the cursor to the end of a line, explain if you used the mouse, or a keyboard shortcut or an Marlin command, and if so which one?
- **Provide specific examples to demonstrate the steps**. Include links to files or GitHub projects, or copy/pasteable snippets, which you use in those examples. If you're providing snippets or log output in the issue, use [Markdown code blocks](https://help.github.com/articles/markdown-basics/#multiple-lines). * **Provide specific examples to demonstrate the steps**. Include links to files or GitHub projects, or copy/pasteable snippets, which you use in those examples. If you're providing snippets or log output in the issue, use [Markdown code blocks](https://help.github.com/articles/markdown-basics/#multiple-lines).
- **Describe the behavior you observed after following the steps** and point out what exactly is the problem with that behavior. * **Describe the behavior you observed after following the steps** and point out what exactly is the problem with that behavior.
- **Explain which behavior you expected to see instead and why.** * **Explain which behavior you expected to see instead and why.**
- **Include detailed log output** especially for probing and leveling. See below for usage of `DEBUG_LEVELING_FEATURE`. * **Include detailed log output** especially for probing and leveling. See below for usage of `DEBUG_LEVELING_FEATURE`.
- **Include screenshots, links to videos, etc.** which clearly demonstrate the problem. * **Include screenshots, links to videos, etc.** which clearly demonstrate the problem.
- **Include G-code** (if relevant) that reliably causes the problem to show itself. * **Include G-code** (if relevant) that reliably causes the problem to show itself.
- **If the problem wasn't triggered by a specific action**, describe what you were doing before the problem happened and share more information using the guidelines below. * **If the problem wasn't triggered by a specific action**, describe what you were doing before the problem happened and share more information using the guidelines below.
Provide more context: Provide more context:
- **Can you reproduce the problem with a minimum of options enabled?** * **Can you reproduce the problem with a minimum of options enabled?**
- **Did the problem start happening recently** (e.g. after updating to a new version of Marlin) or was this always a problem? * **Did the problem start happening recently** (e.g. after updating to a new version of Marlin) or was this always a problem?
- If the problem started happening recently, **can you reproduce the problem in an older version of Marlin?** What's the most recent version in which the problem doesn't happen? You can download older versions of Marlin from [the releases page](https://github.com/MarlinFirmware/Marlin/releases). * If the problem started happening recently, **can you reproduce the problem in an older version of Marlin?** What's the most recent version in which the problem doesn't happen? You can download older versions of Marlin from [the releases page](https://github.com/MarlinFirmware/Marlin/releases).
- **Can you reliably reproduce the issue?** If not, provide details about how often the problem happens and under which conditions it normally happens. * **Can you reliably reproduce the issue?** If not, provide details about how often the problem happens and under which conditions it normally happens.
Include details about your configuration and environment: Include details about your configuration and environment:
- **Which version of Marlin are you using?** Marlin's exact version and build date can be seen in the startup message when a host connects to Marlin, or in the LCD Info menu (if enabled). * **Which version of Marlin are you using?** Marlin's exact version and build date can be seen in the startup message when a host connects to Marlin, or in the LCD Info menu (if enabled).
- **What kind of 3D Printer and electronics are you using**? * **What kind of 3D Printer and electronics are you using**?
- **What kind of add-ons (probe, filament sensor) do you have**? * **What kind of add-ons (probe, filament sensor) do you have**?
- **Include your Configuration files.** Make a ZIP file containing `Configuration.h` and `Configuration_adv.h` and drop it on your reply. * **Include your Configuration files.** Make a ZIP file containing `Configuration.h` and `Configuration_adv.h` and drop it on your reply.
### Suggesting Features or Changes ### Suggesting Features or Changes
@@ -102,52 +97,52 @@ Before creating a suggestion, please check [this list](https://github.com/Marlin
#### Before Submitting a Feature Request #### Before Submitting a Feature Request
- **Check the [Marlin website](https://marlinfw.org/)** for tips — you might discover that the feature is already included. Most importantly, check if you're using [the latest version of Marlin](https://github.com/MarlinFirmware/Marlin/releases) and if you can get the desired behavior by changing [Marlin's config settings](https://marlinfw.org/docs/configuration/configuration.html). * **Check the [Marlin website](https://marlinfw.org/)** for tips — you might discover that the feature is already included. Most importantly, check if you're using [the latest version of Marlin](https://github.com/MarlinFirmware/Marlin/releases) and if you can get the desired behavior by changing [Marlin's config settings](https://marlinfw.org/docs/configuration/configuration.html).
- **Perform a [cursory search](https://github.com/MarlinFirmware/Marlin/issues?q=is%3Aopen+is%3Aissue+label%3A%22T%3A+Feature+Request%22)** to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one. * **Perform a [cursory search](https://github.com/MarlinFirmware/Marlin/issues?q=is%3Aopen+is%3Aissue+label%3A%22T%3A+Feature+Request%22)** to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one.
#### How Do I Submit A (Good) Feature Request? #### How Do I Submit A (Good) Feature Request?
Feature Requests are tracked as [GitHub issues](https://guides.github.com/features/issues/). Please follow these guidelines in your request: Feature Requests are tracked as [GitHub issues](https://guides.github.com/features/issues/). Please follow these guidelines in your request:
- **Use a clear and descriptive title** for the issue to identify the suggestion. * **Use a clear and descriptive title** for the issue to identify the suggestion.
- **Provide a step-by-step description of the requested feature** in as much detail as possible. * **Provide a step-by-step description of the requested feature** in as much detail as possible.
- **Provide specific examples to demonstrate the steps**. * **Provide specific examples to demonstrate the steps**.
- **Describe the current behavior** and **explain which behavior you expected to see instead** and why. * **Describe the current behavior** and **explain which behavior you expected to see instead** and why.
- **Include screenshots and links to videos** which demonstrate the feature or point out the part of Marlin to which the request is related. * **Include screenshots and links to videos** which demonstrate the feature or point out the part of Marlin to which the request is related.
- **Explain why this feature would be useful** to most Marlin users. * **Explain why this feature would be useful** to most Marlin users.
- **Name other firmwares that have this feature, if any.** * **Name other firmwares that have this feature, if any.**
### Your First Code Contribution ### Your First Code Contribution
Unsure where to begin contributing to Marlin? You can start by looking through these `good-first-issue` and `help-wanted` issues: Unsure where to begin contributing to Marlin? You can start by looking through these `good-first-issue` and `help-wanted` issues:
- [Beginner issues][good-first-issue] - issues which should only require a few lines of code, and a test or two. * [Beginner issues][good-first-issue] - issues which should only require a few lines of code, and a test or two.
- [Help Wanted issues][help-wanted] - issues which should be a bit more involved than `beginner` issues. * [Help Wanted issues][help-wanted] - issues which should be a bit more involved than `beginner` issues.
### Pull Requests ### Pull Requests
Pull Requests should always be targeted to working branches (e.g., `bugfix-2.1.x` and/or `bugfix-1.1.x`) and never to release branches (e.g., `2.0.x` and/or `1.1.x`). If this is your first Pull Request, please read our [Guide to Pull Requests](https://marlinfw.org/docs/development/getting_started_pull_requests.html) and GitHub's [Pull Request](https://help.github.com/articles/creating-a-pull-request/) documentation. Pull Requests should always be targeted to working branches (e.g., `bugfix-2.1.x` and/or `bugfix-1.1.x`) and never to release branches (e.g., `2.0.x` and/or `1.1.x`). If this is your first Pull Request, please read our [Guide to Pull Requests](https://marlinfw.org/docs/development/getting_started_pull_requests.html) and Github's [Pull Request](https://help.github.com/articles/creating-a-pull-request/) documentation.
- Fill in [the required template](pull_request_template.md). * Fill in [the required template](pull_request_template.md).
- Don't include issue numbers in the PR title. * Don't include issue numbers in the PR title.
- Include pictures, diagrams, and links to videos in your Pull Request to demonstrate your changes, if needed. * Include pictures, diagrams, and links to videos in your Pull Request to demonstrate your changes, if needed.
- Follow the [Coding Standards](https://marlinfw.org/docs/development/coding_standards.html) posted on our website. * Follow the [Coding Standards](https://marlinfw.org/docs/development/coding_standards.html) posted on our website.
- Document new code with clear and concise comments. * Document new code with clear and concise comments.
- End all files with a newline. * End all files with a newline.
## Styleguides ## Styleguides
### Git Commit Messages ### Git Commit Messages
- Use the present tense ("Add feature" not "Added feature"). * Use the present tense ("Add feature" not "Added feature").
- Use the imperative mood ("Move cursor to..." not "Moves cursor to..."). * Use the imperative mood ("Move cursor to..." not "Moves cursor to...").
- Limit the first line to 72 characters or fewer. * Limit the first line to 72 characters or fewer.
- Reference issues and Pull Requests liberally after the first line. * Reference issues and Pull Requests liberally after the first line.
### C++ Coding Standards ### C++ Coding Standards
- Please read and follow the [Coding Standards](https://marlinfw.org/docs/development/coding_standards.html) posted on our website. Failure to follow these guidelines will delay evaluation and acceptance of Pull Requests. * Please read and follow the [Coding Standards](https://marlinfw.org/docs/development/coding_standards.html) posted on our website. Failure to follow these guidelines will delay evaluation and acceptance of Pull Requests.
### Documentation ### Documentation
- Guidelines for documentation are still under development. In-general, be clear, concise, and to-the-point. * Guidelines for documentation are still under development. In-general, be clear, concise, and to-the-point.
+7 -12
View File
@@ -1,5 +1,4 @@
SCRIPTS_DIR := buildroot/share/scripts SCRIPTS_DIR := buildroot/share/scripts
MAKESCRIPTS_DIR := buildroot/share/make
CONTAINER_RT_BIN := docker CONTAINER_RT_BIN := docker
CONTAINER_RT_OPTS := --rm -v $(PWD):/code -v platformio-cache:/root/.platformio CONTAINER_RT_OPTS := --rm -v $(PWD):/code -v platformio-cache:/root/.platformio
CONTAINER_IMAGE := marlin-dev CONTAINER_IMAGE := marlin-dev
@@ -9,8 +8,9 @@ UNIT_TEST_CONFIG ?= default
ifeq ($(OS),Windows_NT) ifeq ($(OS),Windows_NT)
# Windows: use `where` fall back through the three common names # Windows: use `where` fall back through the three common names
PYTHON := $(shell which python 2>nul || which python3 2>nul || which py 2>nul) PYTHON := $(shell which python 2>nul || which python3 2>nul || which py 2>nul)
# Windows: Use Python script to find pins files # Windows: Use cmd tools to find pins files
PINS := $(shell $(PYTHON) $(MAKESCRIPTS_DIR)/find.py Marlin/src/pins -mindepth 2 -name 'pins_*.h') PINS_RAW := $(shell cmd //c "dir /s /b Marlin\src\pins\*.h 2>nul | findstr /r ".*Marlin\\\\src\\\\pins\\\\.*\\\\pins_.*\.h"")
PINS := $(subst \,/,$(PINS_RAW))
else else
# POSIX: use `command -v` prefer python3 over python # POSIX: use `command -v` prefer python3 over python
PYTHON := $(shell command -v python3 2>/dev/null || command -v python 2>/dev/null) PYTHON := $(shell command -v python3 2>/dev/null || command -v python 2>/dev/null)
@@ -36,7 +36,6 @@ help:
@echo "make validate-lines -j : Validate line endings, fails on trailing whitespace, etc." @echo "make validate-lines -j : Validate line endings, fails on trailing whitespace, etc."
@echo "make validate-pins -j : Validate all pins files, fails if any require reformatting" @echo "make validate-pins -j : Validate all pins files, fails if any require reformatting"
@echo "make validate-boards -j : Validate boards.h and pins.h for standards compliance" @echo "make validate-boards -j : Validate boards.h and pins.h for standards compliance"
@echo "make validate-urls : Validate URLs in source files"
@echo "make tests-single-ci : Run a single test from inside the CI" @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 : Run a single test locally"
@echo "make tests-single-local-docker : Run a single test locally, using docker" @echo "make tests-single-local-docker : Run a single test locally, using docker"
@@ -89,7 +88,7 @@ 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) @$(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 PATH="./buildroot/bin/:./buildroot/tests/:${PATH}" \
&& export VERBOSE_PLATFORMIO=$(VERBOSE_PLATFORMIO) \ && export VERBOSE_PLATFORMIO=$(VERBOSE_PLATFORMIO) \
&& for TEST_TARGET in $$($(PYTHON) $(MAKESCRIPTS_DIR)/get_test_targets.py) ; do \ && for TEST_TARGET in $$($(PYTHON) $(SCRIPTS_DIR)/get_test_targets.py) ; do \
if [ "$$TEST_TARGET" = "linux_native" ] && [ "$$(uname)" = "Darwin" ]; then \ if [ "$$TEST_TARGET" = "linux_native" ] && [ "$$(uname)" = "Darwin" ]; then \
echo "Skipping tests for $$TEST_TARGET on macOS" ; \ echo "Skipping tests for $$TEST_TARGET on macOS" ; \
continue ; \ continue ; \
@@ -152,7 +151,7 @@ validate-pins: format-pins
@echo "Validating pins files" @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) @git diff --exit-code || (git status && echo "\nError: Pins files are not formatted correctly. Run \"make format-pins\" to fix.\n" && exit 1)
.PHONY: format-lines validate-lines validate-urls .PHONY: format-lines validate-lines
format-lines: format-lines:
@echo "Formatting all sources" @echo "Formatting all sources"
@@ -161,11 +160,7 @@ format-lines:
validate-lines: validate-lines:
@echo "Validating text formatting" @echo "Validating text formatting"
@npx prettier --check . --editorconfig --object-wrap preserve --prose-wrap never @npx prettier --check . --editorconfig --object-wrap preserve
validate-urls:
@echo "Checking URLs in source files"
@$(MAKESCRIPTS_DIR)/check-urls.sh
BOARDS_FILE := Marlin/src/core/boards.h BOARDS_FILE := Marlin/src/core/boards.h
@@ -173,4 +168,4 @@ BOARDS_FILE := Marlin/src/core/boards.h
validate-boards: validate-boards:
@echo "Validating boards.h file" @echo "Validating boards.h file"
@$(PYTHON) $(MAKESCRIPTS_DIR)/validate_boards.py $(BOARDS_FILE) || (echo "\nError: boards.h file is not valid. Please check and correct it.\n" && exit 1) @$(PYTHON) $(SCRIPTS_DIR)/validate_boards.py $(BOARDS_FILE) || (echo "\nError: boards.h file is not valid. Please check and correct it.\n" && exit 1)
+16 -26
View File
@@ -61,7 +61,7 @@
// @section info // @section info
// Author info of this build printed to the host during boot and M115 // Author info of this build printed to the host during boot and M115
#define STRING_CONFIG_H_AUTHOR "(MarlinFirmware)" // Original author or contributor. #define STRING_CONFIG_H_AUTHOR "(none, default config)" // Original author or contributor.
//#define CUSTOM_VERSION_FILE Version.h // Path from the root directory (no quotes) //#define CUSTOM_VERSION_FILE Version.h // Path from the root directory (no quotes)
// @section machine // @section machine
@@ -468,7 +468,7 @@
//=========================================================================== //===========================================================================
//============================= Thermal Settings ============================ //============================= Thermal Settings ============================
//=========================================================================== //===========================================================================
// @section temperature sensors // @section temperature
/** /**
* Temperature Sensors: * Temperature Sensors:
@@ -500,8 +500,8 @@
* 10 : 100kΩ RS PRO 198-961 * 10 : 100kΩ RS PRO 198-961
* 11 : 100kΩ Keenovo AC silicone mats, most Wanhao i3 machines - beta 3950, 1% * 11 : 100kΩ Keenovo AC silicone mats, most Wanhao i3 machines - beta 3950, 1%
* 12 : 100kΩ Vishay 0603 SMD NTCS0603E3104FXT (#8) - calibrated for Makibox hot bed * 12 : 100kΩ Vishay 0603 SMD NTCS0603E3104FXT (#8) - calibrated for Makibox hot bed
* 13 : 100kΩ Hisense up to 300°C - for "Simple ONE" & "All In ONE" hotend - R25 = 100 kOhm, beta25 = 4100 K, 4.7kΩ pull-up * 13 : 100kΩ Hisens up to 300°C - for "Simple ONE" & "All In ONE" hotend - beta 3950, 1%
* 14 : 100kΩ (R25), 4092K (beta25), 4.7kΩ pull-up, bed thermistor (as used in Ender-5 S1) * 14 : 100kΩ (R25), 4092K (beta25), 4.7kΩ pull-up, bed thermistor as used in Ender-5 S1
* 15 : 100kΩ Calibrated for JGAurora A5 hotend * 15 : 100kΩ Calibrated for JGAurora A5 hotend
* 17 : 100kΩ Dagoma NTC white thermistor * 17 : 100kΩ Dagoma NTC white thermistor
* 18 : 200kΩ ATC Semitec 204GT-2 Dagoma.Fr - MKS_Base_DKU001327 * 18 : 200kΩ ATC Semitec 204GT-2 Dagoma.Fr - MKS_Base_DKU001327
@@ -652,8 +652,6 @@
#define TEMP_SENSOR_REDUNDANT_MAX_DIFF 10 // (°C) Temperature difference that will trigger a print abort. #define TEMP_SENSOR_REDUNDANT_MAX_DIFF 10 // (°C) Temperature difference that will trigger a print abort.
#endif #endif
// @section temperature
// Below this temperature the heater will be switched off // Below this temperature the heater will be switched off
// because it probably indicates a broken thermistor wire. // because it probably indicates a broken thermistor wire.
#define HEATER_0_MINTEMP 5 #define HEATER_0_MINTEMP 5
@@ -1663,7 +1661,7 @@
* Nozzle-to-Probe offsets { X, Y, Z } * Nozzle-to-Probe offsets { X, Y, Z }
* *
* X and Y offset * X and Y offset
* Use a caliper or ruler to measure the distance (in mm) from the tip of * Use a caliper or ruler to measure the distance from the tip of
* the Nozzle to the center-point of the Probe in the X and Y axes. * the Nozzle to the center-point of the Probe in the X and Y axes.
* *
* Z offset * Z offset
@@ -1699,7 +1697,7 @@
* | [-] | * | [-] |
* O-- FRONT --+ * O-- FRONT --+
*/ */
#define NOZZLE_TO_PROBE_OFFSET { 10, 10, 0 } // (mm) X, Y, Z distance from Nozzle tip to Probe trigger-point #define NOZZLE_TO_PROBE_OFFSET { 10, 10, 0 }
// Enable and set to use a specific tool for probing. Disable to allow any tool. // Enable and set to use a specific tool for probing. Disable to allow any tool.
#define PROBING_TOOL 0 #define PROBING_TOOL 0
@@ -1862,12 +1860,15 @@
//#define DISABLE_V //#define DISABLE_V
//#define DISABLE_W //#define DISABLE_W
// Turn off the display blinking that warns about possible accuracy reduction
//#define DISABLE_REDUCED_ACCURACY_WARNING
// @section extruder // @section extruder
//#define DISABLE_E // Disable the extruder when not stepping //#define DISABLE_E // Disable the extruder when not stepping
#define DISABLE_OTHER_EXTRUDERS // Keep only the active extruder enabled #define DISABLE_OTHER_EXTRUDERS // Keep only the active extruder enabled
// @section stepper drivers // @section motion
// Invert the stepper direction. Change (or reverse the motor connector) if an axis goes the wrong way. // Invert the stepper direction. Change (or reverse the motor connector) if an axis goes the wrong way.
#define INVERT_X_DIR false #define INVERT_X_DIR false
@@ -1880,6 +1881,8 @@
//#define INVERT_V_DIR false //#define INVERT_V_DIR false
//#define INVERT_W_DIR false //#define INVERT_W_DIR false
// @section extruder
// For direct drive extruder v9 set to true, for geared extruder set to false. // For direct drive extruder v9 set to true, for geared extruder set to false.
#define INVERT_E0_DIR false #define INVERT_E0_DIR false
#define INVERT_E1_DIR false #define INVERT_E1_DIR false
@@ -2346,6 +2349,7 @@
//#define LCD_BED_TRAMMING //#define LCD_BED_TRAMMING
#if ENABLED(LCD_BED_TRAMMING) #if ENABLED(LCD_BED_TRAMMING)
#define BED_TRAMMING_INSET_LFRB { 30, 30, 30, 30 } // (mm) Left, Front, Right, Back insets
#define BED_TRAMMING_HEIGHT 0.0 // (mm) Z height of nozzle at tramming points #define BED_TRAMMING_HEIGHT 0.0 // (mm) Z height of nozzle at tramming points
#define BED_TRAMMING_Z_HOP 4.0 // (mm) Z raise between tramming points #define BED_TRAMMING_Z_HOP 4.0 // (mm) Z raise between tramming points
//#define BED_TRAMMING_INCLUDE_CENTER // Move to the center after the last corner //#define BED_TRAMMING_INCLUDE_CENTER // Move to the center after the last corner
@@ -2354,8 +2358,6 @@
#define BED_TRAMMING_PROBE_TOLERANCE 0.1 // (mm) #define BED_TRAMMING_PROBE_TOLERANCE 0.1 // (mm)
#define BED_TRAMMING_VERIFY_RAISED // After adjustment triggers the probe, re-probe to verify #define BED_TRAMMING_VERIFY_RAISED // After adjustment triggers the probe, re-probe to verify
//#define BED_TRAMMING_AUDIO_FEEDBACK //#define BED_TRAMMING_AUDIO_FEEDBACK
#else
#define BED_TRAMMING_INSET_LFRB { 30, 30, 30, 30 } // (mm) Left, Front, Right, Back insets
#endif #endif
/** /**
@@ -2525,7 +2527,7 @@
// //
//#define TEMPERATURE_UNITS_SUPPORT //#define TEMPERATURE_UNITS_SUPPORT
// @section temperature presets // @section temperature
// //
// Preheat Constants - Up to 10 are supported without changes // Preheat Constants - Up to 10 are supported without changes
@@ -2755,10 +2757,10 @@
* *
* Select the language to display on the LCD. These languages are available: * Select the language to display on the LCD. These languages are available:
* *
* en, an, bg, ca, cz, da, de, el, el_CY, es, eu, fi, fr, gl, hg, hr, hu, id, it, * en, an, bg, ca, cz, da, de, el, el_CY, es, eu, fi, fr, gl, hr, hu, it,
* jp_kana, ko_KR, nl, pl, pt, pt_br, ro, ru, sk, sv, tr, uk, vi, zh_CN, zh_TW * jp_kana, ko_KR, nl, pl, pt, pt_br, ro, ru, sk, sv, tr, uk, vi, zh_CN, zh_TW
* *
* :{ 'en':'English', 'an':'Aragonese', 'bg':'Bulgarian', 'ca':'Catalan', 'cz':'Czech', 'da':'Danish', 'de':'German', 'el':'Greek (Greece)', 'el_CY':'Greek (Cyprus)', 'es':'Spanish', 'eu':'Basque-Euskera', 'fi':'Finnish', 'fr':'French', 'gl':'Galician', 'hg':'Hinglish (Hindi-Latin)', 'hr':'Croatian', 'hu':'Hungarian', 'id':'Indonesian', 'it':'Italian', 'jp_kana':'Japanese', 'ko_KR':'Korean (South Korea)', 'nl':'Dutch', 'pl':'Polish', 'pt':'Portuguese', 'pt_br':'Portuguese (Brazilian)', 'ro':'Romanian', 'ru':'Russian', 'sk':'Slovak', 'sv':'Swedish', 'tr':'Turkish', 'uk':'Ukrainian', 'vi':'Vietnamese', 'zh_CN':'Chinese (Simplified)', 'zh_TW':'Chinese (Traditional)' } * :{ 'en':'English', 'an':'Aragonese', 'bg':'Bulgarian', 'ca':'Catalan', 'cz':'Czech', 'da':'Danish', 'de':'German', 'el':'Greek (Greece)', 'el_CY':'Greek (Cyprus)', 'es':'Spanish', 'eu':'Basque-Euskera', 'fi':'Finnish', 'fr':'French', 'gl':'Galician', 'hr':'Croatian', 'hu':'Hungarian', 'it':'Italian', 'jp_kana':'Japanese', 'ko_KR':'Korean (South Korea)', 'nl':'Dutch', 'pl':'Polish', 'pt':'Portuguese', 'pt_br':'Portuguese (Brazilian)', 'ro':'Romanian', 'ru':'Russian', 'sk':'Slovak', 'sv':'Swedish', 'tr':'Turkish', 'uk':'Ukrainian', 'vi':'Vietnamese', 'zh_CN':'Chinese (Simplified)', 'zh_TW':'Chinese (Traditional)' }
*/ */
#define LCD_LANGUAGE en #define LCD_LANGUAGE en
@@ -3043,18 +3045,6 @@
// //
//#define FF_INTERFACEBOARD //#define FF_INTERFACEBOARD
//
// MightyBoard LCD and Interface
//
//#define MIGHTYBOARD_LCD
#if ENABLED(MIGHTYBOARD_LCD)
//#define MIGHTYBOARD_DEBUG // Lightweight debug output for buttons and encoder
//#define MIGHTYBOARD_DISABLE_ENC_PULLUP // Enable if the encoder button is unreliable
//#define MIGHTYBOARD_BUTTON_PULLUPS // Enable if other buttons are unreliable
//#define MIGHTYBOARD_BACK_STATUS_BUTTONS // Use LEFT/RIGHT buttons for Back / Home.
// Otherwise they act like encoder down / up.
#endif
// //
// TFT GLCD Panel with Marlin UI // TFT GLCD Panel with Marlin UI
// Panel connected to main board by SPI or I2C interface. // Panel connected to main board by SPI or I2C interface.
+30 -124
View File
@@ -1160,26 +1160,9 @@
#if ENABLED(FT_MOTION) #if ENABLED(FT_MOTION)
//#define FTM_IS_DEFAULT_MOTION // Use FT Motion as the factory default? //#define FTM_IS_DEFAULT_MOTION // Use FT Motion as the factory default?
//#define FT_MOTION_MENU // Provide a MarlinUI menu to set M493 and M494 parameters //#define FT_MOTION_MENU // Provide a MarlinUI menu to set M493 and M494 parameters
//#define FTM_HOME_AND_PROBE // Use FT Motion for homing / probing. Disable if FT Motion breaks these functions.
//#define NO_STANDARD_MOTION // Disable the standard motion system entirely to save Flash and RAM #define FTM_DEFAULT_DYNFREQ_MODE dynFreqMode_DISABLED // Default mode of dynamic frequency calculation. (DISABLED, Z_BASED, MASS_BASED)
#if DISABLED(NO_STANDARD_MOTION)
//#define FTM_HOME_AND_PROBE // Use FT Motion for homing / probing. Disable if FT Motion breaks these functions.
#endif
//#define FTM_DYNAMIC_FREQ // Enable for linear adjustment of XY shaping frequency according to Z or E
#if ENABLED(FTM_DYNAMIC_FREQ)
#define FTM_DEFAULT_DYNFREQ_MODE dynFreqMode_DISABLED // Default mode of dynamic frequency calculation. (DISABLED, Z_BASED, MASS_BASED)
#endif
// Disable unused shapers if you need more free space
#define FTM_SHAPER_ZV
#define FTM_SHAPER_ZVD
#define FTM_SHAPER_ZVDD
#define FTM_SHAPER_ZVDDD
#define FTM_SHAPER_EI
#define FTM_SHAPER_2HEI
#define FTM_SHAPER_3HEI
#define FTM_SHAPER_MZV
#define FTM_DEFAULT_SHAPER_X ftMotionShaper_NONE // Default shaper mode on X axis (NONE, ZV, ZVD, ZVDD, ZVDDD, EI, 2HEI, 3HEI, MZV) #define FTM_DEFAULT_SHAPER_X ftMotionShaper_NONE // Default shaper mode on X axis (NONE, ZV, ZVD, ZVDD, ZVDDD, EI, 2HEI, 3HEI, MZV)
#define FTM_SHAPING_DEFAULT_FREQ_X 37.0f // (Hz) Default peak frequency used by input shapers #define FTM_SHAPING_DEFAULT_FREQ_X 37.0f // (Hz) Default peak frequency used by input shapers
@@ -1236,27 +1219,9 @@
#define FTM_BUFFER_SIZE 128 // Window size for trajectory generation, must be a power of 2 (e.g 64, 128, 256, ...) #define FTM_BUFFER_SIZE 128 // Window size for trajectory generation, must be a power of 2 (e.g 64, 128, 256, ...)
// The total buffered time in seconds is (FTM_BUFFER_SIZE/FTM_FS) // The total buffered time in seconds is (FTM_BUFFER_SIZE/FTM_FS)
#define FTM_FS 1000 // (Hz) Frequency for trajectory generation. #define FTM_FS 1000 // (Hz) Frequency for trajectory generation.
#define FTM_STEPPER_FS 2'000'000 // (Hz) Time resolution of stepper I/O update. Shouldn't affect CPU much (slower board testing needed)
#define FTM_MIN_SHAPE_FREQ 20 // (Hz) Minimum shaping frequency, lower consumes more RAM #define FTM_MIN_SHAPE_FREQ 20 // (Hz) Minimum shaping frequency, lower consumes more RAM
/**
* TMC2208 / TMC2208_STANDALONE drivers require a brief pause after a DIR change
* to prevent a standstill shutdown when using StealthChop (the standalone default).
* These options cause FT Motion to delay for > 750µs after a DIR change on a given axis.
* Disable only if you are certain that this can never happen with your TMC2208s.
*/
#if AXIS_DRIVER_TYPE_X(TMC2208) || AXIS_DRIVER_TYPE_X(TMC2208_STANDALONE)
#define FTM_DIR_CHANGE_HOLD_X
#endif
#if AXIS_DRIVER_TYPE_Y(TMC2208) || AXIS_DRIVER_TYPE_Y(TMC2208_STANDALONE)
#define FTM_DIR_CHANGE_HOLD_Y
#endif
#if AXIS_DRIVER_TYPE_Z(TMC2208) || AXIS_DRIVER_TYPE_Z(TMC2208_STANDALONE)
#define FTM_DIR_CHANGE_HOLD_Z
#endif
#if HAS_E_DRIVER(TMC2208) || HAS_E_DRIVER(TMC2208_STANDALONE)
#define FTM_DIR_CHANGE_HOLD_E
#endif
#endif // FT_MOTION #endif // FT_MOTION
/** /**
@@ -1545,9 +1510,6 @@
// @section lcd // @section lcd
// Turn off the display blinking that warns about possible accuracy reduction
//#define DISABLE_REDUCED_ACCURACY_WARNING
#if HAS_MANUAL_MOVE_MENU #if HAS_MANUAL_MOVE_MENU
#define MANUAL_FEEDRATE { 50*60, 50*60, 4*60, 2*60 } // (mm/min) Feedrates for manual moves along X, Y, Z, E from panel #define MANUAL_FEEDRATE { 50*60, 50*60, 4*60, 2*60 } // (mm/min) Feedrates for manual moves along X, Y, Z, E from panel
#define FINE_MANUAL_MOVE 0.025 // (mm) Smallest manual move (< 0.1mm) applying to Z on most machines #define FINE_MANUAL_MOVE 0.025 // (mm) Smallest manual move (< 0.1mm) applying to Z on most machines
@@ -1617,7 +1579,7 @@
#define XATC_Z_OFFSETS { 0, 0, 0 } // Z offsets for X axis sample points #define XATC_Z_OFFSETS { 0, 0, 0 } // Z offsets for X axis sample points
#endif #endif
#endif // HAS_BED_PROBE #endif
// Include a page of printer information in the LCD Main Menu // Include a page of printer information in the LCD Main Menu
//#define LCD_INFO_MENU //#define LCD_INFO_MENU
@@ -1801,12 +1763,6 @@
*/ */
//#define SD_SPI_SPEED SPI_HALF_SPEED //#define SD_SPI_SPEED SPI_HALF_SPEED
/**
* Reinit the LCD after SD Card insert/remove or when entering the menu.
* Required for some LCDs that use shared SPI with an external SD Card reader.
*/
#define REINIT_NOISY_LCD
// The standard SD detect circuit reads LOW when media is inserted and HIGH when empty. // The standard SD detect circuit reads LOW when media is inserted and HIGH when empty.
// Enable this option and set to HIGH if your SD cards are incorrectly detected. // Enable this option and set to HIGH if your SD cards are incorrectly detected.
//#define SD_DETECT_STATE HIGH //#define SD_DETECT_STATE HIGH
@@ -1841,14 +1797,6 @@
#define PE_LEDS_COMPLETED_TIME (30*60) // (seconds) Time to keep the LED "done" color before restoring normal illumination #define PE_LEDS_COMPLETED_TIME (30*60) // (seconds) Time to keep the LED "done" color before restoring normal illumination
#endif #endif
/**
* Priming for the Remaining Time estimate
* Long processes at the start of a G-code file can skew the Remaining Time estimate.
* Enable these options to start this estimation at a later point in the G-code file.
*/
//#define REMAINING_TIME_PRIME // Provide G-code 'M75 R' to prime the Remaining Time estimate
//#define REMAINING_TIME_AUTOPRIME // Prime the Remaining Time estimate later (e.g., at the end of 'M109')
/** /**
* Continue after Power-Loss (Creality3D) * Continue after Power-Loss (Creality3D)
* *
@@ -1915,21 +1863,17 @@
// SD Card Sorting options // SD Card Sorting options
#if ENABLED(SDCARD_SORT_ALPHA) #if ENABLED(SDCARD_SORT_ALPHA)
#define SDSORT_QUICK true // Use Quick Sort as a sorting algorithm. Otherwise use Bubble Sort. #define SDSORT_REVERSE false // Default to sorting file names in reverse order.
#define SDSORT_REVERSE false // Default to sorting file names in reverse order. #define SDSORT_LIMIT 40 // Maximum number of sorted items (10-256). Costs 27 bytes each.
#define SDSORT_LIMIT 40 // Maximum number of sorted items (10-256). Costs 27 bytes each. #define SDSORT_FOLDERS -1 // -1=above 0=none 1=below
#define SDSORT_FOLDERS -1 // -1=above 0=none 1=below #define SDSORT_GCODE false // Enable G-code M34 to set sorting behaviors: M34 S<-1|0|1> F<-1|0|1>
#define SDSORT_GCODE false // Enable G-code M34 to set sorting behaviors: M34 S<-1|0|1> F<-1|0|1> #define SDSORT_USES_RAM false // Pre-allocate a static array for faster pre-sorting.
#define SDSORT_USES_STACK false // Prefer the stack for pre-sorting to give back some SRAM. (Negated by next 2 options.) #define SDSORT_USES_STACK false // Prefer the stack for pre-sorting to give back some SRAM. (Negated by next 2 options.)
#define SDSORT_USES_RAM false // Pre-allocate a static array for faster pre-sorting. #define SDSORT_CACHE_NAMES false // Keep sorted items in RAM longer for speedy performance. Most expensive option.
#if ENABLED(SDSORT_USES_RAM) #define SDSORT_DYNAMIC_RAM false // Use dynamic allocation (within SD menus). Least expensive option. Set SDSORT_LIMIT before use!
#define SDSORT_CACHE_NAMES false // Keep sorted items in RAM longer for speedy performance. Most expensive option. #define SDSORT_CACHE_VFATS 2 // Maximum number of 13-byte VFAT entries to use for sorting.
#if ENABLED(SDSORT_CACHE_NAMES) // Note: Only affects SCROLL_LONG_FILENAMES with SDSORT_CACHE_NAMES but not SDSORT_DYNAMIC_RAM.
#define SDSORT_DYNAMIC_RAM false // Use dynamic allocation (within SD menus). Least expensive option. Set SDSORT_LIMIT before use! #define SDSORT_QUICK true // Use Quick Sort as a sorting algorithm. Otherwise use Bubble Sort.
#define SDSORT_CACHE_VFATS 2 // Maximum number of 13-byte VFAT entries to use for sorting.
// Note: Only affects SCROLL_LONG_FILENAMES with SDSORT_CACHE_NAMES but not SDSORT_DYNAMIC_RAM.
#endif
#endif
#endif #endif
// Allow international symbols in long filenames. To display correctly, the // Allow international symbols in long filenames. To display correctly, the
@@ -2383,7 +2327,7 @@
//#define WATCHDOG_RESET_MANUAL //#define WATCHDOG_RESET_MANUAL
#endif #endif
// @section baby-stepping // @section lcd
/** /**
* Babystepping enables movement of the axes by tiny increments without changing * Babystepping enables movement of the axes by tiny increments without changing
@@ -2636,15 +2580,13 @@
#endif #endif
#endif // PTC_PROBE || PTC_BED || PTC_HOTEND #endif // PTC_PROBE || PTC_BED || PTC_HOTEND
// @section gcode // @section extras
// //
// G60/G61 Position Save and Return // G60/G61 Position Save and Return
// //
//#define SAVED_POSITIONS 1 // Each saved position slot costs 12 bytes //#define SAVED_POSITIONS 1 // Each saved position slot costs 12 bytes
// @section motion
// //
// G2/G3 Arc Support // G2/G3 Arc Support
// //
@@ -2676,8 +2618,6 @@
*/ */
//#define DIRECT_STEPPING //#define DIRECT_STEPPING
// @section calibrate
/** /**
* G38 Probe Target * G38 Probe Target
* *
@@ -2799,11 +2739,6 @@
// Enable this option to collect and display the number // Enable this option to collect and display the number
// of dropped bytes after a file transfer to SD. // of dropped bytes after a file transfer to SD.
//#define SERIAL_STATS_DROPPED_RX //#define SERIAL_STATS_DROPPED_RX
// Enable this option to collect and display framing errors.
// Framing errors occur when invalid start/stop bits or other
// serial protocol violations are detected.
//#define SERIAL_STATS_RX_FRAMING_ERRORS
#endif #endif
// Monitor RX buffer usage // Monitor RX buffer usage
@@ -2831,8 +2766,8 @@
* *
* Adds support for commands: * Adds support for commands:
* S000 : Report State and Position while moving. * S000 : Report State and Position while moving.
* P000 : Instant Pause / Hold while moving. Enable SOFT_FEED_HOLD for soft deceleration. * P000 : Instant Pause / Hold while moving.
* R000 : Resume from Pause / Hold. Enable SOFT_FEED_HOLD for soft acceleration. * R000 : Resume from Pause / Hold.
* *
* - During Hold all Emergency Parser commands are available, as usual. * - During Hold all Emergency Parser commands are available, as usual.
* - Enable NANODLP_Z_SYNC and NANODLP_ALL_AXIS for move command end-state reports. * - Enable NANODLP_Z_SYNC and NANODLP_ALL_AXIS for move command end-state reports.
@@ -2889,7 +2824,7 @@
*/ */
//#define EXTRA_FAN_SPEED //#define EXTRA_FAN_SPEED
// @section firmware retraction // @section gcode
/** /**
* Firmware-based and LCD-controlled retract * Firmware-based and LCD-controlled retract
@@ -3609,13 +3544,7 @@
//#define SPI_ENDSTOPS // TMC2130, TMC2240, and TMC5160 //#define SPI_ENDSTOPS // TMC2130, TMC2240, and TMC5160
//#define IMPROVE_HOMING_RELIABILITY //#define IMPROVE_HOMING_RELIABILITY
//#define SENSORLESS_STALLGUARD_DELAY 0 // (ms) Delay to allow drivers to settle //#define SENSORLESS_STALLGUARD_DELAY 0 // (ms) Delay to allow drivers to settle
#endif
#if HAS_MARLINUI_MENU
// Convenient homing menu items next to Sensorless Homing edit items
//#define SENSORLESS_HOMING_TEST_MENU_ITEMS
#endif
#endif // SENSORLESS_HOMING || SENSORLESS_PROBING
// @section tmc/config // @section tmc/config
@@ -3712,7 +3641,7 @@
//#define PHOTO_RETRACT_MM 6.5 // (mm) E retract/recover for the photo move (M240 R S) //#define PHOTO_RETRACT_MM 6.5 // (mm) E retract/recover for the photo move (M240 R S)
// Canon RC-1 or homebrew digital camera trigger // Canon RC-1 or homebrew digital camera trigger
// Data from: https://web.archive.org/web/20250327153953/www.doc-diy.net/photo/rc-1_hacked/ // Data from: https://www.doc-diy.net/photo/rc-1_hacked/
//#define PHOTOGRAPH_PIN 23 //#define PHOTOGRAPH_PIN 23
// Canon Hack Development Kit // Canon Hack Development Kit
@@ -4283,7 +4212,7 @@
#define BUTTON1_WHEN_PRINTING false // Button allowed to trigger during printing? #define BUTTON1_WHEN_PRINTING false // Button allowed to trigger during printing?
#define BUTTON1_GCODE "G28" #define BUTTON1_GCODE "G28"
#define BUTTON1_DESC "Homing" // Optional string to set the LCD status #define BUTTON1_DESC "Homing" // Optional string to set the LCD status
//#define BUTTON1_IMMEDIATE // Skip the queue and execute immediately. Rarely needed. //#define BUTTON1_IMMEDIATE // Skip the queue and run the G-code immediately. Rarely needed.
#endif #endif
//#define BUTTON2_PIN -1 //#define BUTTON2_PIN -1
@@ -4349,7 +4278,7 @@
* Developed by Chris Barr at Aus3D. * Developed by Chris Barr at Aus3D.
* *
* Wiki: https://wiki.aus3d.com.au/Magnetic_Encoder * Wiki: https://wiki.aus3d.com.au/Magnetic_Encoder
* GitHub: https://github.com/Aus3D/MagneticEncoder * Github: https://github.com/Aus3D/MagneticEncoder
* *
* Supplier: https://aus3d.com.au/products/magnetic-encoder-module * Supplier: https://aus3d.com.au/products/magnetic-encoder-module
* Alternative Supplier: https://reliabuild3d.com/ * Alternative Supplier: https://reliabuild3d.com/
@@ -4468,38 +4397,15 @@
#endif #endif
/** /**
* Freeze / Unfreeze * Instant freeze / unfreeze functionality
* * Potentially useful for rapid stop that allows being resumed. Halts stepper movement.
* Pause / Hold that keeps power available and does not stop the spindle can be initiated by * Note this does NOT pause spindles, lasers, fans, heaters or any other auxiliary device.
* the FREEZE_PIN. Halts instantly (default) or performs a soft feed hold that decelerates and * @section interface
* halts movement at FREEZE_JERK (requires SOFT_FEED_HOLD).
* Motion can be resumed by using the FREEZE_PIN.
*
* NOTE: Controls Laser PWM but does NOT pause Spindle, Fans, Heaters or other devices.
* @section freeze
*/ */
//#define FREEZE_FEATURE //#define FREEZE_FEATURE
#if ENABLED(FREEZE_FEATURE) #if ENABLED(FREEZE_FEATURE)
//#define FREEZE_PIN -1 // Override the default (KILL) pin here //#define FREEZE_PIN 41 // Override the default (KILL) pin here
#define FREEZE_STATE LOW // State of pin indicating freeze #define FREEZE_STATE LOW // State of pin indicating freeze
#endif
#if ANY(FREEZE_FEATURE, REALTIME_REPORTING_COMMANDS)
/**
* Command P000 (REALTIME_REPORTING_COMMANDS and EMERGENCY_PARSER) or
* FREEZE_PIN (FREEZE_FEATURE) initiates a soft feed hold that keeps
* power available and does not stop the spindle.
*
* The soft feed hold decelerates and halts movement at FREEZE_JERK.
* Motion can be resumed with command R000 (requires REALTIME_REPORTING_COMMANDS) or
* by using the FREEZE_PIN (requires FREEZE_FEATURE).
*
* NOTE: Affects Laser PWM but DOES NOT pause Spindle, Fans, Heaters or other devices.
*/
//#define SOFT_FEED_HOLD
#if ENABLED(SOFT_FEED_HOLD)
#define FREEZE_JERK 2 // (mm/s) Completely halt when motion has decelerated below this value
#endif
#endif #endif
/** /**
+2 -2
View File
@@ -41,7 +41,7 @@
* here we define this default string as the date where the latest release * here we define this default string as the date where the latest release
* version was tagged. * version was tagged.
*/ */
//#define STRING_DISTRIBUTION_DATE "2026-03-19" //#define STRING_DISTRIBUTION_DATE "2025-12-02"
/** /**
* The protocol for communication to the host. Protocol indicates communication * The protocol for communication to the host. Protocol indicates communication
@@ -58,7 +58,7 @@
/** /**
* The SOURCE_CODE_URL is the location where users will find the Marlin Source * The SOURCE_CODE_URL is the location where users will find the Marlin Source
* Code which is installed on the device. In most cases —unless the manufacturer * Code which is installed on the device. In most cases —unless the manufacturer
* has a distinct GitHub fork— the Source Code URL should just be the main * has a distinct Github fork— the Source Code URL should just be the main
* Marlin repository. * Marlin repository.
*/ */
//#define SOURCE_CODE_URL "github.com/MarlinFirmware/Marlin" //#define SOURCE_CODE_URL "github.com/MarlinFirmware/Marlin"
+1 -1
View File
@@ -96,7 +96,7 @@ void MarlinHAL::init() {
// Might disable other peripherals using the pin; to circumvent that please undefine one of the above things! // Might disable other peripherals using the pin; to circumvent that please undefine one of the above things!
// The true culprit is the AVR ArduinoCore that enables peripherals redundantly. // The true culprit is the AVR ArduinoCore that enables peripherals redundantly.
// (USART1 on the GeeeTech GT2560) // (USART1 on the GeeeTech GT2560)
// https://youtube.be/jMgCvRXkexk // https://www.youtube.com/watch?v=jMgCvRXkexk
_ATmega_savePinAlternate(BEEPER_PIN); _ATmega_savePinAlternate(BEEPER_PIN);
OUT_WRITE(BEEPER_PIN, LOW); OUT_WRITE(BEEPER_PIN, LOW);
+1 -1
View File
@@ -45,7 +45,7 @@
#define NUMBER_PINS_TOTAL NUM_DIGITAL_PINS #define NUMBER_PINS_TOTAL NUM_DIGITAL_PINS
#if MB(BQ_ZUM_MEGA_3D, MIGHTYBOARD_REVE, MINIRAMBO, SCOOVO_X9H, TRIGORILLA_14, MIGHTYBOARD_REVG) #if MB(BQ_ZUM_MEGA_3D, MIGHTYBOARD_REVE, MINIRAMBO, SCOOVO_X9H, TRIGORILLA_14)
#define AVR_ATmega2560_FAMILY_PLUS_70 1 #define AVR_ATmega2560_FAMILY_PLUS_70 1
#endif #endif
+1 -1
View File
@@ -25,7 +25,7 @@
* Structures for 2560 family boards that use more than 70 pins * Structures for 2560 family boards that use more than 70 pins
*/ */
#if MB(BQ_ZUM_MEGA_3D, MINIRAMBO, SCOOVO_X9H, TRIGORILLA_14, MIGHTYBOARD_REVG) #if MB(BQ_ZUM_MEGA_3D, MINIRAMBO, SCOOVO_X9H, TRIGORILLA_14)
#undef NUM_DIGITAL_PINS #undef NUM_DIGITAL_PINS
#define NUM_DIGITAL_PINS 85 #define NUM_DIGITAL_PINS 85
#elif MB(MIGHTYBOARD_REVE) #elif MB(MIGHTYBOARD_REVE)
+3 -2
View File
@@ -28,7 +28,7 @@
// ------------------------ // ------------------------
typedef uint16_t hal_timer_t; typedef uint16_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX hal_timer_t(UINT16_MAX) #define HAL_TIMER_TYPE_MAX 0xFFFFU
// ------------------------ // ------------------------
// Defines // Defines
@@ -50,9 +50,10 @@ typedef uint16_t hal_timer_t;
#define STEPPER_TIMER_RATE HAL_TIMER_RATE #define STEPPER_TIMER_RATE HAL_TIMER_RATE
#define STEPPER_TIMER_PRESCALE 8 #define STEPPER_TIMER_PRESCALE 8
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000UL) // (MHz) Stepper Timer ticks per µs #define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000UL)
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer #define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE #define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define ENABLE_STEPPER_DRIVER_INTERRUPT() SBI(TIMSK1, OCIE1A) #define ENABLE_STEPPER_DRIVER_INTERRUPT() SBI(TIMSK1, OCIE1A)
+1 -1
View File
@@ -24,7 +24,7 @@
/** /**
* Description: Tone function for Arduino Due and compatible (SAM3X8E) * Description: Tone function for Arduino Due and compatible (SAM3X8E)
* Derived from https://forum.arduino.cc/t/arduino-due-and-tone/133302/13 * Derived from https://forum.arduino.cc/index.php?topic=136500.msg2903012#msg2903012
*/ */
#ifdef ARDUINO_ARCH_SAM #ifdef ARDUINO_ARCH_SAM
+2 -1
View File
@@ -34,7 +34,7 @@
#define FORCE_INLINE __attribute__((always_inline)) inline #define FORCE_INLINE __attribute__((always_inline)) inline
typedef uint32_t hal_timer_t; typedef uint32_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX hal_timer_t(UINT32_MAX) #define HAL_TIMER_TYPE_MAX 0xFFFFFFFFUL
#define HAL_TIMER_PRESCALER 2 #define HAL_TIMER_PRESCALER 2
#define HAL_TIMER_RATE ((F_CPU) / (HAL_TIMER_PRESCALER)) // frequency of timers peripherals #define HAL_TIMER_RATE ((F_CPU) / (HAL_TIMER_PRESCALER)) // frequency of timers peripherals
@@ -59,6 +59,7 @@ typedef uint32_t hal_timer_t;
#define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US) #define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US)
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer #define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE #define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP) #define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP)
-5
View File
@@ -1,5 +0,0 @@
# editorconfig.org
[{*.c,*.cpp,*.h}]
indent_style = tab
indent_size = 4
+1 -2
View File
@@ -271,8 +271,7 @@ void MarlinHAL::adc_start(const pin_t pin) {
uint32_t mv; uint32_t mv;
esp_adc_cal_get_voltage((adc_channel_t)chan, &characteristics[attenuations[chan]], &mv); esp_adc_cal_get_voltage((adc_channel_t)chan, &characteristics[attenuations[chan]], &mv);
static constexpr uint32_t adc_divisor = uint32_t((ADC_REFERENCE_VOLTAGE) * 1000UL); adc_result = mv * isr_float_t(1023) / isr_float_t(ADC_REFERENCE_VOLTAGE) / isr_float_t(1000);
adc_result = (mv * 1023UL) / adc_divisor;
// Change the attenuation level based on the new reading // Change the attenuation level based on the new reading
adc_atten_t atten; adc_atten_t atten;
+1
View File
@@ -76,6 +76,7 @@
// Types // Types
// ------------------------ // ------------------------
typedef double isr_float_t; // FPU ops are used for single-precision, so use double for ISRs.
typedef int16_t pin_t; typedef int16_t pin_t;
typedef struct pwm_pin { typedef struct pwm_pin {
+1 -1
View File
@@ -24,7 +24,7 @@
/** /**
* Description: Tone function for ESP32 * Description: Tone function for ESP32
* Derived from https://forum.arduino.cc/t/arduino-due-and-tone/133302/13 * Derived from https://forum.arduino.cc/index.php?topic=136500.msg2903012#msg2903012
*/ */
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
+23 -28
View File
@@ -156,43 +156,38 @@ void stepperTask(void *parameter) {
while (dma.rw_pos < DMA_SAMPLE_COUNT) { while (dma.rw_pos < DMA_SAMPLE_COUNT) {
if (using_ftMotion) { #if ENABLED(FT_MOTION)
#if ENABLED(FT_MOTION) if (using_ftMotion) {
if (!nextMainISR) stepper.ftMotion_stepper(); if (!nextMainISR) stepper.ftMotion_stepper();
nextMainISR = 0; nextMainISR = 0;
#endif }
} #endif
else {
#if HAS_STANDARD_MOTION if (!using_ftMotion) {
if (!nextMainISR) {
if (!nextMainISR) { stepper.pulse_phase_isr();
stepper.pulse_phase_isr(); nextMainISR = stepper.block_phase_isr();
nextMainISR = stepper.block_phase_isr(); }
#if ENABLED(LIN_ADVANCE)
else if (!nextAdvanceISR) {
stepper.advance_isr();
nextAdvanceISR = stepper.la_interval;
} }
#if ENABLED(LIN_ADVANCE) #endif
else if (!nextAdvanceISR) { else
stepper.advance_isr(); i2s_push_sample();
nextAdvanceISR = stepper.la_interval;
}
#endif
else
i2s_push_sample();
nextMainISR--; nextMainISR--;
#if ENABLED(LIN_ADVANCE) #if ENABLED(LIN_ADVANCE)
if (nextAdvanceISR == stepper.LA_ADV_NEVER) if (nextAdvanceISR == stepper.LA_ADV_NEVER)
nextAdvanceISR = stepper.la_interval; nextAdvanceISR = stepper.la_interval;
if (nextAdvanceISR && nextAdvanceISR != stepper.LA_ADV_NEVER)
nextAdvanceISR--;
#endif
#endif // HAS_STANDARD_MOTION
if (nextAdvanceISR && nextAdvanceISR != stepper.LA_ADV_NEVER)
nextAdvanceISR--;
#endif
} }
} }
} }
+1 -1
View File
@@ -57,7 +57,7 @@
#endif #endif
#if ALL(I2S_STEPPER_STREAM, LIN_ADVANCE) && DISABLED(EXPERIMENTAL_I2S_LA) #if ALL(I2S_STEPPER_STREAM, LIN_ADVANCE) && DISABLED(EXPERIMENTAL_I2S_LA)
#error "I2S stream is currently incompatible with LIN_ADVANCE. Enable EXPERIMENTAL_I2S_LA to proceed anyway." #error "I2S stream is currently incompatible with LIN_ADVANCE."
#endif #endif
#if ALL(I2S_STEPPER_STREAM, PRINTCOUNTER) && PRINTCOUNTER_SAVE_INTERVAL > 0 && DISABLED(PRINTCOUNTER_SYNC) #if ALL(I2S_STEPPER_STREAM, PRINTCOUNTER) && PRINTCOUNTER_SAVE_INTERVAL > 0 && DISABLED(PRINTCOUNTER_SYNC)
+2 -1
View File
@@ -30,7 +30,7 @@
#define FORCE_INLINE __attribute__((always_inline)) inline #define FORCE_INLINE __attribute__((always_inline)) inline
typedef uint64_t hal_timer_t; typedef uint64_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX hal_timer_t(UINT64_MAX) #define HAL_TIMER_TYPE_MAX 0xFFFF'FFFF'FFFF'FFFFULL
#ifndef MF_TIMER_STEP #ifndef MF_TIMER_STEP
#define MF_TIMER_STEP 0 // Timer Index for Stepper #define MF_TIMER_STEP 0 // Timer Index for Stepper
@@ -66,6 +66,7 @@ typedef uint64_t hal_timer_t;
#define STEP_TIMER_MIN_INTERVAL 8 // minimum time in µs between stepper interrupts #define STEP_TIMER_MIN_INTERVAL 8 // minimum time in µs between stepper interrupts
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer #define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE #define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define TONE_TIMER_PRESCALE 1000 // Arbitrary value, no idea what i'm doing here #define TONE_TIMER_PRESCALE 1000 // Arbitrary value, no idea what i'm doing here
+1
View File
@@ -57,6 +57,7 @@
#define __bss_end __bss_end__ #define __bss_end __bss_end__
// Types // Types
typedef double isr_float_t; // FPU ops are used for single-precision, so use double for ISRs.
typedef uint8_t pin_t; // Parity with mfl platform typedef uint8_t pin_t; // Parity with mfl platform
// Servo // Servo
+7 -4
View File
@@ -69,6 +69,10 @@
#endif #endif
#endif #endif
#ifndef HAL_TIMER_RATE
#define HAL_TIMER_RATE GetStepperTimerClkFreq()
#endif
#ifndef STEP_TIMER #ifndef STEP_TIMER
#define STEP_TIMER MF_TIMER_STEP #define STEP_TIMER MF_TIMER_STEP
#endif #endif
@@ -117,10 +121,9 @@ void HAL_timer_start(const uint8_t timer_number, const uint32_t frequency) {
if (is_step) { if (is_step) {
timer.setPrescaler(STEPPER_TIMER_PRESCALE); timer.setPrescaler(STEPPER_TIMER_PRESCALE);
timer.setRolloverValue( timer.setRolloverValue(_MIN(static_cast<hal_timer_t>(HAL_TIMER_TYPE_MAX),
_MIN(HAL_TIMER_TYPE_MAX, hal_timer_t((HAL_TIMER_RATE) / (STEPPER_TIMER_PRESCALE))), (HAL_TIMER_RATE) / (STEPPER_TIMER_PRESCALE)),
TimerFormat::TICK TimerFormat::TICK);
);
is_step_timer_initialized = true; is_step_timer_initialized = true;
} }
else { else {
+7 -10
View File
@@ -34,24 +34,21 @@
#define MF_TIMER_TEMP 1 #define MF_TIMER_TEMP 1
#define MF_TIMER_PULSE MF_TIMER_STEP #define MF_TIMER_PULSE MF_TIMER_STEP
typedef uint32_t hal_timer_t; #define hal_timer_t uint32_t
#define HAL_TIMER_TYPE_MAX hal_timer_t(UINT16_MAX) #define HAL_TIMER_TYPE_MAX UINT16_MAX
#ifndef HAL_TIMER_RATE extern uint32_t GetStepperTimerClkFreq();
extern uint32_t GetStepperTimerClkFreq();
#define HAL_TIMER_RATE GetStepperTimerClkFreq()
#endif
// Timer configuration constants // Timer configuration constants
#define STEPPER_TIMER_RATE 2000000 #define STEPPER_TIMER_RATE 2000000
#define TEMP_TIMER_FREQUENCY 1000 #define TEMP_TIMER_FREQUENCY 1000
// Timer prescaler calculations // Timer prescaler calculations
#define STEPPER_TIMER_PRESCALE ((HAL_TIMER_RATE) / (STEPPER_TIMER_RATE)) // Prescaler = 30 #define STEPPER_TIMER_PRESCALE (GetStepperTimerClkFreq() / STEPPER_TIMER_RATE) // Prescaler = 30
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000UL) // (MHz) Stepper Timer ticks per µs #define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000UL) // (MHz) Stepper Timer ticks per µs
// Pulse Timer (counter) calculations #define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer #define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE #define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
// Timer interrupt priorities // Timer interrupt priorities
+13 -18
View File
@@ -30,17 +30,17 @@
* it would not make sense to parse G-Code from TMC responses * it would not make sense to parse G-Code from TMC responses
*/ */
constexpr bool serial_handles_emergency(int port) { constexpr bool serial_handles_emergency(int port) {
return (false return false
#ifdef SERIAL_PORT #ifdef SERIAL_PORT
|| (SERIAL_PORT) == port || (SERIAL_PORT) == port
#endif #endif
#ifdef SERIAL_PORT_2 #ifdef SERIAL_PORT_2
|| (SERIAL_PORT_2) == port || (SERIAL_PORT_2) == port
#endif #endif
#ifdef LCD_SERIAL_PORT #ifdef LCD_SERIAL_PORT
|| (LCD_SERIAL_PORT) == port || (LCD_SERIAL_PORT) == port
#endif #endif
); ;
} }
// //
@@ -48,7 +48,7 @@ constexpr bool serial_handles_emergency(int port) {
// //
// serial port where RX and TX use IRQs // serial port where RX and TX use IRQs
#define DEFINE_IRQ_SERIAL_MARLIN(name, n) \ #define DEFINE_IRQ_SERIAL_MARLIN(name, n) \
MSerialT name(serial_handles_emergency(n), \ MSerialT name(serial_handles_emergency(n), \
&USART##n##_config, \ &USART##n##_config, \
BOARD_USART##n##_TX_PIN, \ BOARD_USART##n##_TX_PIN, \
@@ -57,7 +57,7 @@ constexpr bool serial_handles_emergency(int port) {
// serial port where RX uses DMA and TX uses IRQs // serial port where RX uses DMA and TX uses IRQs
// all serial ports use DMA1 // all serial ports use DMA1
// since there are 4 USARTs and 4 DMA channels, we can use the USART number as the DMA channel // since there are 4 USARTs and 4 DMA channels, we can use the USART number as the DMA channel
#define DEFINE_DMA_SERIAL_MARLIN(name, n) \ #define DEFINE_DMA_SERIAL_MARLIN(name, n) \
MSerialT name(serial_handles_emergency(n), \ MSerialT name(serial_handles_emergency(n), \
&USART##n##_config, \ &USART##n##_config, \
BOARD_USART##n##_TX_PIN, \ BOARD_USART##n##_TX_PIN, \
@@ -67,17 +67,12 @@ constexpr bool serial_handles_emergency(int port) {
#define DEFINE_SERIAL_MARLIN(name, n) TERN(SERIAL_DMA, DEFINE_DMA_SERIAL_MARLIN(name, n), DEFINE_IRQ_SERIAL_MARLIN(name, n)) #define DEFINE_SERIAL_MARLIN(name, n) TERN(SERIAL_DMA, DEFINE_DMA_SERIAL_MARLIN(name, n), DEFINE_IRQ_SERIAL_MARLIN(name, n))
#if PINS_EXIST(BOARD_USART1_RX, BOARD_USART1_TX) DEFINE_SERIAL_MARLIN(MSerial1, 1);
DEFINE_SERIAL_MARLIN(MSerial1, 1); DEFINE_SERIAL_MARLIN(MSerial2, 2);
#endif
#if PINS_EXIST(BOARD_USART2_RX, BOARD_USART2_TX) // TODO: remove this warning when SERIAL_DMA has been tested some more
DEFINE_SERIAL_MARLIN(MSerial2, 2); #if ENABLED(SERIAL_DMA)
#endif #warning "SERIAL_DMA may be unstable on HC32F460."
#if PINS_EXIST(BOARD_USART3_RX, BOARD_USART3_TX)
DEFINE_SERIAL_MARLIN(MSerial3, 3);
#endif
#if PINS_EXIST(BOARD_USART4_RX, BOARD_USART4_TX)
DEFINE_SERIAL_MARLIN(MSerial4, 4);
#endif #endif
// //
-2
View File
@@ -92,5 +92,3 @@ typedef Serial1Class<MarlinSerial> MSerialT;
extern MSerialT MSerial1; extern MSerialT MSerial1;
extern MSerialT MSerial2; extern MSerialT MSerial2;
extern MSerialT MSerial3;
extern MSerialT MSerial4;
+1 -1
View File
@@ -33,7 +33,7 @@
// Shared by both panic and PostMortem debugging // Shared by both panic and PostMortem debugging
// //
static void minserial_begin() { static void minserial_begin() {
#if !WITHIN(SERIAL_PORT, 1, 4) #if !WITHIN(SERIAL_PORT, 1, 3)
#warning "MinSerial requires a physical UART port for output." #warning "MinSerial requires a physical UART port for output."
#warning "Disabling MinSerial because the used serial port is not a HW port." #warning "Disabling MinSerial because the used serial port is not a HW port."
#else #else
+10 -13
View File
@@ -6,7 +6,7 @@ This document provides notes on the HAL for the HC32F460 MCU.
The HC32F460 HAL is designed to be generic enough for any HC32F460-based board. Adding support for a new HC32F460-based board will require the following steps: The HC32F460 HAL is designed to be generic enough for any HC32F460-based board. Adding support for a new HC32F460-based board will require the following steps:
1. Follow [the usual instructions](//marlinfw.org/docs/development/boards.html#adding-a-new-board) to add a new board to Marlin. (i.e., Add a pins file, edit `boards.h` and `pins.h`, etc.) 1. Follow [the usual instructions](https://marlinfw.org/docs/development/boards.html#adding-a-new-board) to add a new board to Marlin. (i.e., Add a pins file, edit `boards.h` and `pins.h`, etc.)
2. Determine the flash size your board uses: 2. Determine the flash size your board uses:
- Examine the board's main processor. (Refer the naming key in `hc32.ini`.) - Examine the board's main processor. (Refer the naming key in `hc32.ini`.)
- Extend the `HC32F460C_common` base env for 256K, or `HC32F460E_common` for 512K. - Extend the `HC32F460C_common` base env for 256K, or `HC32F460E_common` for 512K.
@@ -50,12 +50,10 @@ SCB->VTOR = ((uint32_t) APP_START_ADDRESS & SCB_VTOR_TBLOFF_Msk);
Just searching for `SCB->VTOR` should yield some results. From there, you just need to look at the value that's assigned to it. The example uses `APP_START_ADDRESS`. Just searching for `SCB->VTOR` should yield some results. From there, you just need to look at the value that's assigned to it. The example uses `APP_START_ADDRESS`.
> [!NOTE] > [!NOTE]
>
> Some vendors publish incomplete source code. But they sometimes leave version control related files in the repo, which can contain previous version of files that were removed. Find these by including folders like `.git` or `.svn` in your search. > Some vendors publish incomplete source code. But they sometimes leave version control related files in the repo, which can contain previous version of files that were removed. Find these by including folders like `.git` or `.svn` in your search.
> [!NOTE] > [!NOTE]
> > The example is based on the [Voxelab-64/Aquila_X2](https://github.com/Voxelab-64/Aquila_X2/blob/d1f23adf96920996b979bc31023d1dce236d05db/firmware/Sources/.svn/pristine/ec/ec82bcb480b511906bc3e6658450e3a803ab9813.svn-base#L96) which actually includes deleted files in its repo.
> The example is based on the [Voxelab-64/Aquila_X2](//github.com/Voxelab-64/Aquila_X2/blob/main/firmware/Sources/.svn/pristine/ec/ec82bcb480b511906bc3e6658450e3a803ab9813.svn-base#L96) which actually includes deleted files in its repo.
2. Using a linker script 2. Using a linker script
@@ -74,8 +72,7 @@ MEMORY
``` ```
> [!NOTE] > [!NOTE]
> > This example is based on [Voxelab-64/Aquila_X2](https://github.com/Voxelab-64/Aquila_X2/blob/d1f23adf96920996b979bc31023d1dce236d05db/firmware/Sources/main/hdsc32core/hc32f46x_flash.ld#L55)
> This example is based on [Voxelab-64/Aquila_X2](//github.com/Voxelab-64/Aquila_X2/blob/d1f23adf96920996b979bc31023d1dce236d05db/firmware/Sources/main/hdsc32core/hc32f46x_flash.ld#L55)
## Documentation on the HC32F460 ## Documentation on the HC32F460
@@ -99,15 +96,15 @@ Contact me on Discord (@shadow578) if you need it.
This HAL depends on the following projects: This HAL depends on the following projects:
- [shadow578/platform-hc32f46x](//github.com/shadow578/platform-hc32f46x) (PlatformIO platform for HC32F46x) - [shadow578/platform-hc32f46x](https://github.com/shadow578/platform-hc32f46x) (PlatformIO platform for HC32F46x)
- [shadow578/framework-arduino-hc32f46x](//github.com/shadow578/framework-arduino-hc32f46x) (Arduino framework for HC32F46x) - [shadow578/framework-arduino-hc32f46x](https://github.com/shadow578/framework-arduino-hc32f46x) (Arduino framework for HC32F46x)
- [shadow578/framework-hc32f46x-ddl](//github.com/shadow578/framework-hc32f46x-ddl) (HC32F46x DDL framework) - [shadow578/framework-hc32f46x-ddl](https://github.com/shadow578/framework-hc32f46x-ddl) (HC32F46x DDL framework)
## Credits ## Credits
This HAL wouldn't be possible without the following projects: This HAL wouldn't be possible without the following projects:
- [Voxelab-64/Aquila_X2](//github.com/Voxelab-64/Aquila_X2) (original implementation) - [Voxelab-64/Aquila_X2](https://github.com/Voxelab-64/Aquila_X2) (original implementation)
- [alexqzd/Marlin-H32](//github.com/alexqzd/Marlin-H32) (misc. fixes to the original implementation) - [alexqzd/Marlin-H32](https://github.com/alexqzd/Marlin-H32) (misc. fixes to the original implementation)
- [kgoveas/Arduino-Core-Template](//github.com/kgoveas/Arduino-Core-Template) (template for Arduino headers) - [kgoveas/Arduino-Core-Template](https://github.com/kgoveas/Arduino-Core-Template) (template for Arduino headers)
- [stm32duino/Arduino_Core_STM32](//github.com/stm32duino/Arduino_Core_STM32) (misc. Arduino functions) - [stm32duino/Arduino_Core_STM32](https://github.com/stm32duino/Arduino_Core_STM32) (misc. Arduino functions)
-3
View File
@@ -58,9 +58,6 @@
#define USART_RX_DMA_SUPPORT 1 #define USART_RX_DMA_SUPPORT 1
#endif #endif
// SoftwareSerial uses STM32duino API compatibility mode
#define SOFTWARE_SERIAL_STM32_API_COMPATIBILITY 1
// //
// Misc. // Misc.
// //
+2 -5
View File
@@ -43,11 +43,8 @@
#error "FAST_PWM_FAN is not yet implemented for this platform." #error "FAST_PWM_FAN is not yet implemented for this platform."
#endif #endif
// SoftwareSerial introduced in arduino core version 1.3.1 #if !defined(HAVE_SW_SERIAL) && HAS_TMC_SW_SERIAL
#if ARDUINO_CORE_VERSION_INT < GET_VERSION_INT(1, 3, 1) #error "Missing SoftwareSerial implementation."
#if !defined(HAVE_SW_SERIAL) && HAS_TMC_SW_SERIAL
#error "Missing SoftwareSerial implementation."
#endif
#endif #endif
#if ENABLED(SDCARD_EEPROM_EMULATION) && !HAS_MEDIA #if ENABLED(SDCARD_EEPROM_EMULATION) && !HAS_MEDIA
+2 -2
View File
@@ -109,7 +109,7 @@ bool SDIO_ReadBlock(uint32_t block, uint8_t *dst) {
WITH_RETRY(SDIO_READ_RETRIES, { WITH_RETRY(SDIO_READ_RETRIES, {
en_result_t rc = SDCARD_ReadBlocks(handle, block, 1, dst, SDIO_READ_TIMEOUT); en_result_t rc = SDCARD_ReadBlocks(handle, block, 1, dst, SDIO_READ_TIMEOUT);
if (rc == Ok) return true; if (rc == Ok) return true;
printf("SDIO_ReadBlock error (rc=%u; ErrorCode=%" PRIu32 ")\n", rc, handle->u32ErrorCode); printf("SDIO_ReadBlock error (rc=%u; ErrorCode=%lu)\n", rc, handle->u32ErrorCode);
}) })
return false; return false;
@@ -122,7 +122,7 @@ bool SDIO_WriteBlock(uint32_t block, const uint8_t *src) {
WITH_RETRY(SDIO_WRITE_RETRIES, { WITH_RETRY(SDIO_WRITE_RETRIES, {
en_result_t rc = SDCARD_WriteBlocks(handle, block, 1, (uint8_t *)src, SDIO_WRITE_TIMEOUT); en_result_t rc = SDCARD_WriteBlocks(handle, block, 1, (uint8_t *)src, SDIO_WRITE_TIMEOUT);
if (rc == Ok) return true; if (rc == Ok) return true;
printf("SDIO_WriteBlock error (rc=%u; ErrorCode=%" PRIu32 ")\n", rc, handle->u32ErrorCode); printf("SDIO_WriteBlock error (rc=%u; ErrorCode=%lu)\n", rc, handle->u32ErrorCode);
}) })
return false; return false;
+1 -1
View File
@@ -204,7 +204,7 @@ void core_hook_sysclock_init() {
power_mode_update_post(F_SYSTEM_CLOCK); power_mode_update_post(F_SYSTEM_CLOCK);
// Verify clocks match expected values (at runtime) // Verify clocks match expected values (at runtime)
#if ANY(MARLIN_DEV_MODE, ALWAYS_VALIDATE_CLOCKS) #if ENABLED(MARLIN_DEV_MODE) || ENABLED(ALWAYS_VALIDATE_CLOCKS)
validate_system_clocks(); validate_system_clocks();
#endif #endif
+4 -4
View File
@@ -27,7 +27,7 @@
// //
typedef Timer0 *timer_channel_t; typedef Timer0 *timer_channel_t;
typedef uint16_t hal_timer_t; typedef uint16_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX hal_timer_t(UINT16_MAX) #define HAL_TIMER_TYPE_MAX 0xFFFFU
// //
// Timer instances // Timer instances
@@ -69,9 +69,9 @@ extern Timer0 step_timer;
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000UL) // Integer 3 #define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000UL) // Integer 3
// Pulse timer (== stepper timer) // Pulse timer (== stepper timer)
#define MF_TIMER_PULSE MF_TIMER_STEP #define MF_TIMER_PULSE MF_TIMER_STEP
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer #define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE #define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
// //
// HAL functions // HAL functions
+2 -1
View File
@@ -34,7 +34,7 @@
#define FORCE_INLINE __attribute__((always_inline)) inline #define FORCE_INLINE __attribute__((always_inline)) inline
typedef uint32_t hal_timer_t; typedef uint32_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX hal_timer_t(UINT32_MAX) #define HAL_TIMER_TYPE_MAX 0xFFFFFFFFUL
#define HAL_TIMER_RATE ((SystemCoreClock) / 4) // frequency of timers peripherals #define HAL_TIMER_RATE ((SystemCoreClock) / 4) // frequency of timers peripherals
@@ -56,6 +56,7 @@ typedef uint32_t hal_timer_t;
#define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US) #define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US)
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer #define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE #define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP) #define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP)
+4
View File
@@ -40,6 +40,10 @@
* SPI sharing pins. The SCK, MOSI & MISO pins can NOT be set/cleared with * SPI sharing pins. The SCK, MOSI & MISO pins can NOT be set/cleared with
* WRITE nor digitalWrite when the hardware SPI module within the LPC17xx is * WRITE nor digitalWrite when the hardware SPI module within the LPC17xx is
* active. If any of these pins are shared then the software SPI must be used. * active. If any of these pins are shared then the software SPI must be used.
*
* A more sophisticated hardware SPI can be found at the following link.
* This implementation has not been fully debugged.
* https://github.com/MarlinFirmware/Marlin/tree/071c7a78f27078fd4aee9a3ef365fcf5e143531e
*/ */
#ifdef TARGET_LPC1768 #ifdef TARGET_LPC1768
@@ -22,7 +22,7 @@
/** /**
* digipot_mcp4451_I2C_routines.c * digipot_mcp4451_I2C_routines.c
* Adapted from https://www-users.york.ac.uk/~pcc1/MCP/HAPR-Course-web/CMSIS/examples/html/master_8c_source.html * Adapted from https://www-users.cs.york.ac.uk/~pcc/MCP/HAPR-Course-web/CMSIS/examples/html/master_8c_source.html
*/ */
#ifdef TARGET_LPC1768 #ifdef TARGET_LPC1768
@@ -23,7 +23,7 @@
/** /**
* digipot_mcp4451_I2C_routines.h * digipot_mcp4451_I2C_routines.h
* Adapted from https://www-users.york.ac.uk/~pcc1/MCP/HAPR-Course-web/CMSIS/examples/html/master_8c_source.html * Adapted from https://www-users.cs.york.ac.uk/~pcc/MCP/HAPR-Course-web/CMSIS/examples/html/master_8c_source.html
*/ */
#ifdef __cplusplus #ifdef __cplusplus
+5 -4
View File
@@ -57,7 +57,7 @@
#define _HAL_TIMER_ISR(T) __HAL_TIMER_ISR(T) #define _HAL_TIMER_ISR(T) __HAL_TIMER_ISR(T)
typedef uint32_t hal_timer_t; typedef uint32_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX hal_timer_t(UINT32_MAX) #define HAL_TIMER_TYPE_MAX 0xFFFFFFFFUL
#define HAL_TIMER_RATE ((F_CPU) / 4) // (Hz) Frequency of timers peripherals #define HAL_TIMER_RATE ((F_CPU) / 4) // (Hz) Frequency of timers peripherals
@@ -77,11 +77,12 @@ typedef uint32_t hal_timer_t;
#define TEMP_TIMER_RATE 1000000 // 1MHz #define TEMP_TIMER_RATE 1000000 // 1MHz
#define TEMP_TIMER_FREQUENCY 1000 // (Hz) Temperature ISR frequency #define TEMP_TIMER_FREQUENCY 1000 // (Hz) Temperature ISR frequency
#define STEPPER_TIMER_RATE HAL_TIMER_RATE // (Hz) Frequency of stepper timer (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE) #define STEPPER_TIMER_RATE HAL_TIMER_RATE // (Hz) Frequency of stepper timer (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE)
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000UL) // (MHz) Stepper Timer ticks per µs #define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000UL) // (MHz) Stepper Timer ticks per µs
#define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US) #define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US)
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer #define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE #define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP) #define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP)
@@ -21,7 +21,7 @@
*/ */
// adapted from I2C/master/master.c example // adapted from I2C/master/master.c example
// https://www-users.york.ac.uk/~pcc1/MCP/HAPR-Course-web/CMSIS/examples/html/master_8c_source.html // https://www-users.cs.york.ac.uk/~pcc/MCP/HAPR-Course-web/CMSIS/examples/html/master_8c_source.html
#ifdef TARGET_LPC1768 #ifdef TARGET_LPC1768
@@ -41,8 +41,8 @@ if pioutil.is_pio_build():
from ctypes import windll from ctypes import windll
from pathlib import PureWindowsPath from pathlib import PureWindowsPath
# Getting a list of drives # getting list of drives
# https://stackoverflow.com/questions/827371/is-there-a-way-to-list-all-the-available-windows-drives # https://stackoverflow.com/questions/827371/is-there-a-way-to-list-all-the-available-drive-letters-in-python
drives = [] drives = []
bitmask = windll.kernel32.GetLogicalDrives() bitmask = windll.kernel32.GetLogicalDrives()
for letter in string.ascii_uppercase: for letter in string.ascii_uppercase:
+5 -4
View File
@@ -34,7 +34,7 @@
#define FORCE_INLINE __attribute__((always_inline)) inline #define FORCE_INLINE __attribute__((always_inline)) inline
typedef uint64_t hal_timer_t; typedef uint64_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX hal_timer_t(UINT64_MAX) #define HAL_TIMER_TYPE_MAX 0xFFFF'FFFF'FFFF'FFFFULL
#define HAL_TIMER_RATE ((SystemCoreClock) / 4) // frequency of timers peripherals #define HAL_TIMER_RATE ((SystemCoreClock) / 4) // frequency of timers peripherals
@@ -55,11 +55,12 @@ typedef uint64_t hal_timer_t;
#define TEMP_TIMER_RATE 1'000'000 // (Hz) Temperature Timer count rate #define TEMP_TIMER_RATE 1'000'000 // (Hz) Temperature Timer count rate
#define TEMP_TIMER_FREQUENCY 1000 // (Hz) Temperature ISR call frequency #define TEMP_TIMER_FREQUENCY 1000 // (Hz) Temperature ISR call frequency
#define STEPPER_TIMER_RATE HAL_TIMER_RATE // (Hz) Frequency of Stepper Timer (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE) #define STEPPER_TIMER_RATE HAL_TIMER_RATE // (Hz) Frequency of Stepper Timer (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE)
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1'000'000) // (MHz) Stepper Timer ticks per µs #define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1'000'000) // (MHz) Stepper Timer ticks per µs
#define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US) #define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US)
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer #define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE #define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP) #define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP)
@@ -21,7 +21,7 @@
*/ */
// adapted from I2C/master/master.c example // adapted from I2C/master/master.c example
// https://www-users.york.ac.uk/~pcc1/MCP/HAPR-Course-web/CMSIS/examples/html/master_8c_source.html // https://www-users.cs.york.ac.uk/~pcc/MCP/HAPR-Course-web/CMSIS/examples/html/master_8c_source.html
#ifdef __PLAT_NATIVE_SIM__ #ifdef __PLAT_NATIVE_SIM__
+68 -64
View File
@@ -28,7 +28,6 @@
#include "../../inc/MarlinConfig.h" #include "../../inc/MarlinConfig.h"
#include "../shared/Delay.h" #include "../shared/Delay.h"
#include "../../module/temperature.h" // For OVERSAMPLENR
extern "C" { extern "C" {
#include "pico/bootrom.h" #include "pico/bootrom.h"
@@ -42,38 +41,50 @@ extern "C" {
#include "msc_sd.h" #include "msc_sd.h"
#endif #endif
// Core 1 watchdog configuration
#define CORE1_MAX_RESETS 5 // Maximum number of Core 1 resets before halting system
// ------------------------ // ------------------------
// Public Variables // Public Variables
// ------------------------ // ------------------------
volatile uint32_t adc_accumulators[5] = {0}; // Accumulators for oversampling (sum of readings) volatile uint32_t adc_accumulators[5] = {0}; // Accumulators for oversampling (sum of readings)
volatile uint8_t adc_counts[5] = {0}; // Count of readings accumulated per channel volatile uint8_t adc_counts[5] = {0}; // Count of readings accumulated per channel
volatile uint16_t adc_values[5] = {4095, 4095, 4095, 4095, 4095}; // Averaged ADC values (single reading equivalent) - initialized to max (open circuit) volatile uint16_t adc_values[5] = {512, 512, 512, 512, 512}; // Final oversampled ADC values (averages) - initialized to mid-range
// Core monitoring for watchdog // Core 1 watchdog monitoring
volatile uint32_t core0_last_heartbeat = 0; // Timestamp of Core 0's last activity
volatile uint32_t core1_last_heartbeat = 0; // Timestamp of Core 1's last activity volatile uint32_t core1_last_heartbeat = 0; // Timestamp of Core 1's last activity
#if ENABLED(MARLIN_DEV_MODE) volatile bool core1_watchdog_triggered = false; // Flag to indicate Core 1 reset
volatile bool core1_freeze_test = false; // Flag to freeze Core 1 for watchdog testing volatile uint8_t core1_reset_count = 0; // Count of Core 1 resets - halt system if >= CORE1_MAX_RESETS
#endif
volatile uint8_t current_pin; volatile uint8_t current_pin;
volatile bool MarlinHAL::adc_has_result; volatile bool MarlinHAL::adc_has_result;
volatile uint8_t adc_channels_enabled[5] = {false}; // Track which ADC channels are enabled volatile uint8_t adc_channels_enabled[5] = {false}; // Track which ADC channels are enabled
// Helper function for LED blinking patterns
void blink_led_pattern(uint8_t blink_count, uint32_t blink_duration_us = 100000) {
#if DISABLED(PINS_DEBUGGING) && PIN_EXISTS(LED)
for (uint8_t i = 0; i < blink_count; i++) {
WRITE(LED_PIN, HIGH);
busy_wait_us(blink_duration_us);
WRITE(LED_PIN, LOW);
if (i < blink_count - 1) { // Don't delay after the last blink
busy_wait_us(blink_duration_us);
}
}
#endif
}
// Core 1 ADC reading task - dynamically reads all enabled channels with oversampling // Core 1 ADC reading task - dynamically reads all enabled channels with oversampling
void core1_adc_task() { void core1_adc_task() {
static uint32_t last_temp_update = 0; static uint32_t last_led_toggle = 0;
const uint8_t OVERSAMPLENR = 16; // Standard Marlin oversampling count
// Signal successful Core 1 startup/restart
SERIAL_ECHO_MSG("Core 1 ADC task started");
while (true) { while (true) {
#if ENABLED(MARLIN_DEV_MODE) // Update heartbeat timestamp at start of each scan cycle
// Check if we should freeze for watchdog test core1_last_heartbeat = time_us_32();
if (core1_freeze_test) {
// Stop updating heartbeat and spin forever
while (core1_freeze_test) {
busy_wait_us(100000); // 100ms delay
}
}
#endif
// Scan all enabled ADC channels // Scan all enabled ADC channels
for (uint8_t channel = 0; channel < 5; channel++) { for (uint8_t channel = 0; channel < 5; channel++) {
@@ -103,9 +114,11 @@ void core1_adc_task() {
adc_accumulators[channel] += reading; adc_accumulators[channel] += reading;
adc_counts[channel]++; adc_counts[channel]++;
// When we reach the full oversampling count, calculate averaged value (Marlin ISR does its own oversampling) // Update the averaged value with current accumulation (provides immediate valid data)
adc_values[channel] = adc_accumulators[channel] / adc_counts[channel];
// When we reach the full oversampling count, reset accumulator for next cycle
if (adc_counts[channel] >= OVERSAMPLENR) { if (adc_counts[channel] >= OVERSAMPLENR) {
adc_values[channel] = adc_accumulators[channel] / OVERSAMPLENR; // Return single-reading equivalent
adc_accumulators[channel] = 0; adc_accumulators[channel] = 0;
adc_counts[channel] = 0; adc_counts[channel] = 0;
} }
@@ -116,19 +129,17 @@ void core1_adc_task() {
} }
} }
// Core 1 just provides ADC readings - don't trigger temperature updates from here // Core 1 LED indicator: Double blink every 2 seconds to show Core 1 is active
// Let Marlin's main temperature ISR on Core 0 handle the timing and updates
uint32_t now = time_us_32(); uint32_t now = time_us_32();
if (now - last_temp_update >= 100000) { // 100ms = 100000 microseconds if (now - last_led_toggle >= 2000000) { // 2 seconds
last_temp_update = now; last_led_toggle = now;
#if ENABLED(USE_WATCHDOG) #if DISABLED(PINS_DEBUGGING) && PIN_EXISTS(LED)
// Refresh watchdog here like AVR ISR does indirectly via temperature updates // Triple blink pattern if watchdog was triggered (shows Core 1 was reset)
// Use 2 second delay to allow watchdog_init to be called during boot if (core1_watchdog_triggered) {
static uint32_t core1_start_time = 0; core1_watchdog_triggered = false; // Clear flag
if (core1_start_time == 0) core1_start_time = time_us_32(); blink_led_pattern(3); // Triple blink for watchdog reset
} else {
if (time_us_32() - core1_start_time > 2000000) { blink_led_pattern(2); // Normal double blink
hal.watchdog_refresh(1); // Refresh from Core 1
} }
#endif #endif
} }
@@ -208,42 +219,37 @@ void MarlinHAL::reboot() { watchdog_reboot(0, 0, 1); }
void MarlinHAL::watchdog_init() { void MarlinHAL::watchdog_init() {
#if DISABLED(DISABLE_WATCHDOG_INIT) #if DISABLED(DISABLE_WATCHDOG_INIT)
static_assert(WDT_TIMEOUT_US > 1000, "WDT Timeout is too small, aborting"); static_assert(WDT_TIMEOUT_US > 1000, "WDT Timeout is too small, aborting");
// Initialize Core 0 heartbeat
core0_last_heartbeat = time_us_32();
watchdog_enable(WDT_TIMEOUT_US/1000, true); watchdog_enable(WDT_TIMEOUT_US/1000, true);
#endif #endif
} }
void MarlinHAL::watchdog_refresh(const uint8_t core/*=0*/) { void MarlinHAL::watchdog_refresh() {
if (core == 0) { // If Core 1 has reset CORE1_MAX_RESETS+ times, stop updating watchdog to halt system
// Update Core 0 heartbeat if (core1_reset_count >= CORE1_MAX_RESETS) {
core0_last_heartbeat = time_us_32(); SERIAL_ECHO_MSG("Core 1 reset limit exceeded (", core1_reset_count, " resets) - halting system for safety");
return; // Don't update watchdog - system will halt
// Check if Core 1 is alive (2 second timeout)
if (time_us_32() - core1_last_heartbeat < 2000000) {
watchdog_update(); // Only refresh if Core 1 is responding
#if DISABLED(PINS_DEBUGGING) && PIN_EXISTS(LED)
TOGGLE(LED_PIN); // Heartbeat indicator
#endif
}
// If Core 1 is stuck, don't refresh - let watchdog reset the system
} }
else {
// Update Core 1 heartbeat
core1_last_heartbeat = time_us_32();
// Check if Core 0 is alive (2 second timeout) watchdog_update();
if (time_us_32() - core0_last_heartbeat < 2000000) {
watchdog_update(); // Only refresh if Core 0 is responding // Check Core 1 watchdog (15 second timeout)
#if DISABLED(PINS_DEBUGGING) && PIN_EXISTS(LED) uint32_t now = time_us_32();
TOGGLE(LED_PIN); // Heartbeat indicator if (now - core1_last_heartbeat > 15000000) { // 15 seconds
#endif // Core 1 appears stuck - reset it
} multicore_reset_core1();
// If Core 0 is stuck, don't refresh - let watchdog reset the system multicore_launch_core1(core1_adc_task);
core1_watchdog_triggered = true; // Signal for LED indicator
core1_reset_count++; // Increment reset counter
SERIAL_ECHO_MSG("Core 1 ADC watchdog triggered - resetting Core 1 (attempt ", core1_reset_count, ")");
} }
#if DISABLED(PINS_DEBUGGING) && PIN_EXISTS(LED)
// Core 0 LED indicator: Single toggle every watchdog refresh (shows Core 0 activity)
TOGGLE(LED_PIN);
#endif
} }
#endif // USE_WATCHDOG #endif
// ------------------------ // ------------------------
// ADC // ADC
@@ -284,15 +290,13 @@ void flashFirmware(const int16_t) { hal.reboot(); }
extern "C" { extern "C" {
void * _sbrk(int incr); void * _sbrk(int incr);
extern unsigned int __StackLimit; // Lowest address the stack can grow to extern unsigned int __bss_end__; // end of bss section
} }
// Return free memory between end of heap and start of stack // Return free memory between end of heap (or end bss) and whatever is current
int freeMemory() { int freeMemory() {
void* heap_end = _sbrk(0); int free_memory, heap_end = (int)_sbrk(0);
// Use the linker-provided stack limit instead of a local variable return (int)&free_memory - (heap_end ?: (int)&__bss_end__);
// __StackLimit is the lowest address the stack can grow to
return (char*)&__StackLimit - (char*)heap_end;
} }
#endif // __PLAT_RP2040__ #endif // __PLAT_RP2040__
+1 -23
View File
@@ -51,28 +51,6 @@
#include "MarlinSerial.h" #include "MarlinSerial.h"
#if !WITHIN(SERIAL_PORT, -1, 1)
#error "SERIAL_PORT must be from -1 to 1."
#endif
#ifdef SERIAL_PORT_2
#if !WITHIN(SERIAL_PORT_2, -1, 1)
#error "SERIAL_PORT_2 must be from -1 to 1."
#endif
#endif
#ifdef SERIAL_PORT_3
#if !WITHIN(SERIAL_PORT_3, -1, 1)
#error "SERIAL_PORT_3 must be from -1 to 1."
#endif
#endif
#ifdef LCD_SERIAL_PORT
#if !WITHIN(LCD_SERIAL_PORT, -1, 1)
#error "LCD_SERIAL_PORT must be from -1 to 1."
#endif
#endif
// ------------------------ // ------------------------
// Defines // Defines
// ------------------------ // ------------------------
@@ -153,7 +131,7 @@ public:
// Watchdog // Watchdog
static void watchdog_init() IF_DISABLED(USE_WATCHDOG, {}); static void watchdog_init() IF_DISABLED(USE_WATCHDOG, {});
static void watchdog_refresh(const uint8_t=0) IF_DISABLED(USE_WATCHDOG, {}); static void watchdog_refresh() IF_DISABLED(USE_WATCHDOG, {});
static void init(); // Called early in setup() static void init(); // Called early in setup()
static void init_board() {} // Called less early in setup() static void init_board() {} // Called less early in setup()
+9 -9
View File
@@ -44,15 +44,15 @@ static void TXBegin() {
#endif #endif
} }
static void TX(char b) { static void TX(char b){
#if SERIAL_PORT == -1 #if SERIAL_PORT == -1
USBSerial USBSerial
#elif SERIAL_PORT == 0 #elif SERIAL_PORT == 0
USBSerial USBSerial
#elif SERIAL_PORT == 1 #elif SERIAL_PORT == 1
Serial1 Serial1
#endif #endif
.write(b); .write(b);
} }
// A SW memory barrier, to ensure GCC does not overoptimize loops // A SW memory barrier, to ensure GCC does not overoptimize loops
+4 -34
View File
@@ -30,40 +30,10 @@
#include "../../feature/e_parser.h" #include "../../feature/e_parser.h"
#endif #endif
#include <HardwareSerial.h> #define _IMPLEMENT_SERIAL(X) DefaultSerial##X MSerial##X(false, Serial##X)
#define IMPLEMENT_SERIAL(X) _IMPLEMENT_SERIAL(X)
// Marlin uses: -1=USB, 0=UART0, 1=UART1 #if WITHIN(SERIAL_PORT, 0, 3)
// Arduino uses: Serial=USB, Serial1=UART0, Serial2=UART1 IMPLEMENT_SERIAL(SERIAL_PORT);
//
// To remap Arduino's numbering to Marlin's convention, we create MarlinSerial0/MarlinSerial1
// as new UART instances with custom pins.
//
// We use distinct names (MarlinSerial0/MarlinSerial1) to avoid symbol conflicts with
// the Arduino framework's pre-defined Serial1/Serial2 objects, which use the same
// underlying hardware (_UART0_ and _UART1_).
// Create Serial0 as UART0 with custom or default pins
arduino::UART MarlinSerial0(
#if PINS_EXIST(SERIAL0_TX, SERIAL0_RX)
SERIAL0_TX_PIN, SERIAL0_RX_PIN // Custom pins for UART0 (Marlin Serial0)
#else
0, 1 // Default UART0 pins (GP0/GP1)
#endif
);
// Not using PINS_EXIST(SERIAL1_TX, SERIAL1_RX) because SERIAL1_TX and SERIAL1_RX
// are defined in framework-arduino-mbed/variants/RASPBERRY_PI_PICO/pins_arduino.h
// Create Serial1 as UART1 with custom or default pins
#if defined(SERIAL1_TX_PIN) && defined(SERIAL1_RX_PIN)
arduino::UART MarlinSerial1(SERIAL1_TX_PIN, SERIAL1_RX_PIN); // Custom pins for UART1 (Marlin Serial1)
#endif #endif
// Wrap the serial ports for Marlin
DefaultSerial0 MSerial0(false, MarlinSerial0); // Marlin Serial0 = UART0
#if defined(SERIAL1_TX_PIN) && defined(SERIAL1_RX_PIN)
DefaultSerial1 MSerial1(false, MarlinSerial1); // Marlin Serial1 = UART1
#endif
DefaultSerial2 MSerial2(false, Serial); // Marlin Serial2 = USB (-1)
#endif // __PLAT_RP2040__ #endif // __PLAT_RP2040__
+6 -36
View File
@@ -29,50 +29,20 @@
#include "../../core/serial_hook.h" #include "../../core/serial_hook.h"
/** typedef ForwardSerial1Class< decltype(Serial) > DefaultSerial1;
* Serial Port Configuration for RP2040 (Raspberry Pi Pico) extern DefaultSerial1 MSerial0;
*
* Arduino-Pico Core Serial Objects:
* - Serial: USB Serial (CDC ACM)
* - Serial1: Hardware UART0
* - Serial2: Hardware UART1
* - SerialUSB: Alias for Serial (USB)
*
* Marlin Serial Wrappers:
* - MSerial0: Wrapper for MarlinSerial0 (UART0), used as Serial0
* - MSerial1: Wrapper for MarlinSerial1 (UART1), declared dynamically if used
* - MSerial2: Wrapper for Serial (USB)
* - USBSerial: Wrapper for SerialUSB (USB)
*
* How it all joins together:
* - Configuration defines SERIAL_PORT, SERIAL_PORT_2, etc. (-1 to 1 range)
* - shared/serial_ports.h maps these to MYSERIAL1, MYSERIAL2, etc.
* - MYSERIAL1 uses MSerialX based on the port index
* - USB ports (-1) use USB_SERIAL_PORT (MSerial2)
*/
// Forward declare our custom Serial objects (defined in MarlinSerial.cpp)
namespace arduino { class UART; }
extern arduino::UART MarlinSerial0; // Always declared
extern arduino::UART MarlinSerial1; // Custom Marlin Serial1 to avoid conflict
typedef ForwardSerial1Class< decltype(MarlinSerial0) > DefaultSerial0;
extern DefaultSerial0 MSerial0;
typedef ForwardSerial1Class< decltype(MarlinSerial1) > DefaultSerial1;
extern DefaultSerial1 MSerial1;
typedef ForwardSerial1Class< decltype(Serial) > DefaultSerial2;
extern DefaultSerial2 MSerial2;
typedef ForwardSerial1Class<decltype(SerialUSB)> USBSerialType; typedef ForwardSerial1Class<decltype(SerialUSB)> USBSerialType;
extern USBSerialType USBSerial; extern USBSerialType USBSerial;
#define Serial0 Serial
#define _DECLARE_SERIAL(X) \ #define _DECLARE_SERIAL(X) \
typedef ForwardSerial1Class<decltype(MarlinSerial##X)> DefaultSerial##X; \ typedef ForwardSerial1Class<decltype(Serial##X)> DefaultSerial##X; \
extern DefaultSerial##X MSerial##X extern DefaultSerial##X MSerial##X
#define DECLARE_SERIAL(X) _DECLARE_SERIAL(X) #define DECLARE_SERIAL(X) _DECLARE_SERIAL(X)
#define SERIAL_INDEX_MIN 0 #define SERIAL_INDEX_MIN 0
#define SERIAL_INDEX_MAX 1 #define SERIAL_INDEX_MAX 6
#define USB_SERIAL_PORT(...) MSerial2 #define USB_SERIAL_PORT(...) MSerial0
#include "../shared/serial_ports.h" #include "../shared/serial_ports.h"
#if defined(LCD_SERIAL_PORT) && ANY(HAS_DGUS_LCD, EXTENSIBLE_UI) #if defined(LCD_SERIAL_PORT) && ANY(HAS_DGUS_LCD, EXTENSIBLE_UI)
+1 -1
View File
@@ -137,7 +137,7 @@ int8_t digital_pin_to_analog_pin(pin_t pin) {
} }
bool isAnalogPin(const pin_t pin) { bool isAnalogPin(const pin_t pin) {
return digital_pin_to_analog_pin(pin) >= 0; return digital_pin_to_analog_pin(pin) != -1;
} }
#define digitalRead_mod(A) extDigitalRead(A) // must use Arduino pin numbers when doing reads #define digitalRead_mod(A) extDigitalRead(A) // must use Arduino pin numbers when doing reads
+6 -5
View File
@@ -41,7 +41,7 @@
#define _HAL_TIMER_ISR(T) __HAL_TIMER_ISR(T) #define _HAL_TIMER_ISR(T) __HAL_TIMER_ISR(T)
typedef uint64_t hal_timer_t; typedef uint64_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX hal_timer_t(UINT64_MAX) #define HAL_TIMER_TYPE_MAX 0xFFFF'FFFF'FFFF'FFFFULL
#define HAL_TIMER_RATE (1'000'000ULL) // fixed value as we use a microsecond timesource #define HAL_TIMER_RATE (1'000'000ULL) // fixed value as we use a microsecond timesource
#ifndef MF_TIMER_STEP #ifndef MF_TIMER_STEP
@@ -65,6 +65,7 @@ typedef uint64_t hal_timer_t;
#define STEPPER_TIMER_PRESCALE (10) #define STEPPER_TIMER_PRESCALE (10)
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer #define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE #define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP) #define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP)
@@ -128,16 +129,16 @@ FORCE_INLINE static void HAL_timer_set_compare(const uint8_t timer_num, hal_time
switch (timer_num) { switch (timer_num) {
case 0: case 0:
alarm_pool_add_alarm_in_us(HAL_timer_pool_0, compare, HAL_timer_alarm_pool_0_callback, 0, true); alarm_pool_add_alarm_in_us(HAL_timer_pool_0, compare, HAL_timer_alarm_pool_0_callback, 0, false);
break; break;
case 1: case 1:
alarm_pool_add_alarm_in_us(HAL_timer_pool_1, compare, HAL_timer_alarm_pool_1_callback, 0, true); alarm_pool_add_alarm_in_us(HAL_timer_pool_1, compare, HAL_timer_alarm_pool_1_callback, 0, false);
break; break;
case 2: case 2:
alarm_pool_add_alarm_in_us(HAL_timer_pool_2, compare, HAL_timer_alarm_pool_2_callback, 0, true); alarm_pool_add_alarm_in_us(HAL_timer_pool_2, compare, HAL_timer_alarm_pool_2_callback, 0, false);
break; break;
case 3: case 3:
alarm_pool_add_alarm_in_us(HAL_timer_pool_3, compare, HAL_timer_alarm_pool_3_callback, 0, true); alarm_pool_add_alarm_in_us(HAL_timer_pool_3, compare, HAL_timer_alarm_pool_3_callback, 0, false);
break; break;
} }
} }
+1 -1
View File
@@ -32,7 +32,7 @@
* On SAMD21, all pins support external interrupt capability. * On SAMD21, all pins support external interrupt capability.
* Any pin can be used for external interrupts, but there are some restrictions. * Any pin can be used for external interrupts, but there are some restrictions.
* At most 16 different external interrupts can be used at one time. * At most 16 different external interrupts can be used at one time.
* Further, you can't just pick any 16 pins to use. This is because every pin on the SAMD21 * Further, you cant just pick any 16 pins to use. This is because every pin on the SAMD21
* connects to what is called an EXTINT line, and only one pin per EXTINT line can be used for external * connects to what is called an EXTINT line, and only one pin per EXTINT line can be used for external
* interrupts at a time * interrupts at a time
*/ */
+1 -1
View File
@@ -50,7 +50,7 @@
#define getPinByIndex(x) pin_array[x].pin #define getPinByIndex(x) pin_array[x].pin
#define getPinIsDigitalByIndex(x) pin_array[x].is_digital #define getPinIsDigitalByIndex(x) pin_array[x].is_digital
#define isValidPin(P) (P >= 0 && P < pin_t(NUMBER_PINS_TOTAL)) #define isValidPin(P) (P >= 0 && P < pin_t(NUMBER_PINS_TOTAL))
#define isAnalogPin(P) (digitalPinToAnalogIndex(P) >= 0) #define isAnalogPin(P) (digitalPinToAnalogIndex(P) != -1)
#define pwm_status(P) digitalPinHasPWM(P) #define pwm_status(P) digitalPinHasPWM(P)
#define MULTI_NAME_PAD 27 // space needed to be pretty if not first name assigned to a pin #define MULTI_NAME_PAD 27 // space needed to be pretty if not first name assigned to a pin
+4 -2
View File
@@ -33,7 +33,7 @@
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
typedef uint32_t hal_timer_t; typedef uint32_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX hal_timer_t(UINT32_MAX) #define HAL_TIMER_TYPE_MAX 0xFFFFFFFFUL
#define HAL_TIMER_RATE F_CPU // frequency of timers peripherals #define HAL_TIMER_RATE F_CPU // frequency of timers peripherals
@@ -56,6 +56,7 @@ typedef uint32_t hal_timer_t;
#define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US) #define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US)
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer #define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE #define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP) #define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP)
@@ -142,8 +143,9 @@ FORCE_INLINE static void HAL_timer_isr_prologue(const uint8_t timer_num) {
Rtc * const rtc = timer_config[timer_num].pRtc; Rtc * const rtc = timer_config[timer_num].pRtc;
// Clear interrupt flag // Clear interrupt flag
rtc->MODE0.INTFLAG.reg = RTC_MODE0_INTFLAG_CMP0| RTC_MODE0_INTFLAG_OVF; rtc->MODE0.INTFLAG.reg = RTC_MODE0_INTFLAG_CMP0| RTC_MODE0_INTFLAG_OVF;
} }
else if (timer_config[timer_num].type == TimerType::tcc) { else if (timer_config[timer_num].type == TimerType::tcc){
Tcc * const tc = timer_config[timer_num].pTcc; Tcc * const tc = timer_config[timer_num].pTcc;
// Clear interrupt flag // Clear interrupt flag
tc->INTFLAG.reg = TCC_INTFLAG_OVF; tc->INTFLAG.reg = TCC_INTFLAG_OVF;
@@ -25,7 +25,7 @@
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician) * Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
*/ */
// adapted from I2C/master/master.c example // adapted from I2C/master/master.c example
// https://www-users.york.ac.uk/~pcc1/MCP/HAPR-Course-web/CMSIS/examples/html/master_8c_source.html // https://www-users.cs.york.ac.uk/~pcc/MCP/HAPR-Course-web/CMSIS/examples/html/master_8c_source.html
#ifdef __SAMD21__ #ifdef __SAMD21__
+1 -1
View File
@@ -31,7 +31,7 @@
* On SAMD51, all pins support external interrupt capability. * On SAMD51, all pins support external interrupt capability.
* Any pin can be used for external interrupts, but there are some restrictions. * Any pin can be used for external interrupts, but there are some restrictions.
* At most 16 different external interrupts can be used at one time. * At most 16 different external interrupts can be used at one time.
* Further, you can't just pick any 16 pins to use. This is because every pin on the SAMD51 * Further, you cant just pick any 16 pins to use. This is because every pin on the SAMD51
* connects to what is called an EXTINT line, and only one pin per EXTINT line can be used for external * connects to what is called an EXTINT line, and only one pin per EXTINT line can be used for external
* interrupts at a time * interrupts at a time
*/ */
+1 -1
View File
@@ -50,7 +50,7 @@
#define getPinByIndex(x) pin_array[x].pin #define getPinByIndex(x) pin_array[x].pin
#define getPinIsDigitalByIndex(x) pin_array[x].is_digital #define getPinIsDigitalByIndex(x) pin_array[x].is_digital
#define isValidPin(P) (P >= 0 && P < pin_t(NUMBER_PINS_TOTAL)) #define isValidPin(P) (P >= 0 && P < pin_t(NUMBER_PINS_TOTAL))
#define isAnalogPin(P) (digitalPinToAnalogIndex(P) >= 0) #define isAnalogPin(P) (digitalPinToAnalogIndex(P) != -1)
#define pwm_status(P) digitalPinHasPWM(P) #define pwm_status(P) digitalPinHasPWM(P)
#define MULTI_NAME_PAD 27 // space needed to be pretty if not first name assigned to a pin #define MULTI_NAME_PAD 27 // space needed to be pretty if not first name assigned to a pin
+2 -1
View File
@@ -32,7 +32,7 @@
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
typedef uint32_t hal_timer_t; typedef uint32_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX hal_timer_t(UINT32_MAX) #define HAL_TIMER_TYPE_MAX 0xFFFFFFFFUL
#define HAL_TIMER_RATE F_CPU // frequency of timers peripherals #define HAL_TIMER_RATE F_CPU // frequency of timers peripherals
@@ -55,6 +55,7 @@ typedef uint32_t hal_timer_t;
#define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US) #define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US)
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer #define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE #define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP) #define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP)
+2
View File
@@ -63,6 +63,8 @@
// Types // Types
// ------------------------ // ------------------------
typedef double isr_float_t; // FPU ops are used for single-precision, so use double for ISRs.
typedef int32_t pin_t; // Parity with platform/ststm32 typedef int32_t pin_t; // Parity with platform/ststm32
class libServo; class libServo;
+2 -6
View File
@@ -39,16 +39,12 @@ static void spi_init(spi_t *obj, uint32_t speed, spi_mode_e mode, uint8_t msb, u
void MarlinSPI::setClockDivider(uint8_t _div) { void MarlinSPI::setClockDivider(uint8_t _div) {
_speed = spi_getClkFreq(&_spi);// / _div; _speed = spi_getClkFreq(&_spi);// / _div;
if (_clockDivider != _div) { _clockDivider = _div;
_clockDivider = _div;
_mustInit = true;
}
} }
void MarlinSPI::begin(void) { void MarlinSPI::begin(void) {
if (!_mustInit) return; //TODO: only call spi_init if any parameter changed!!
spi_init(&_spi, _speed, _dataMode, _bitOrder, _dataSize); spi_init(&_spi, _speed, _dataMode, _bitOrder, _dataSize);
_mustInit = false;
} }
void MarlinSPI::setupDma(SPI_HandleTypeDef &_spiHandle, DMA_HandleTypeDef &_dmaHandle, uint32_t direction, bool minc) { void MarlinSPI::setupDma(SPI_HandleTypeDef &_spiHandle, DMA_HandleTypeDef &_dmaHandle, uint32_t direction, bool minc) {
+3 -12
View File
@@ -76,23 +76,15 @@ public:
/* These methods are deprecated and kept for compatibility. /* These methods are deprecated and kept for compatibility.
* Use SPISettings with SPI.beginTransaction() to configure SPI parameters. * Use SPISettings with SPI.beginTransaction() to configure SPI parameters.
*/ */
void setBitOrder(BitOrder order) { void setBitOrder(BitOrder _order) { _bitOrder = _order; }
if (_bitOrder == order) return;
_bitOrder = order;
_mustInit = true;
}
void setDataMode(uint8_t mode) { void setDataMode(uint8_t _mode) {
auto previous_mode = _dataMode; switch (_mode) {
switch (mode) {
case SPI_MODE0: _dataMode = SPI_MODE_0; break; case SPI_MODE0: _dataMode = SPI_MODE_0; break;
case SPI_MODE1: _dataMode = SPI_MODE_1; break; case SPI_MODE1: _dataMode = SPI_MODE_1; break;
case SPI_MODE2: _dataMode = SPI_MODE_2; break; case SPI_MODE2: _dataMode = SPI_MODE_2; break;
case SPI_MODE3: _dataMode = SPI_MODE_3; break; case SPI_MODE3: _dataMode = SPI_MODE_3; break;
default: return;
} }
if (previous_mode != _dataMode)
_mustInit = true;
} }
void setClockDivider(uint8_t _div); void setClockDivider(uint8_t _div);
@@ -112,5 +104,4 @@ private:
pin_t _misoPin; pin_t _misoPin;
pin_t _sckPin; pin_t _sckPin;
pin_t _ssPin; pin_t _ssPin;
bool _mustInit = true;
}; };
+3 -3
View File
@@ -88,9 +88,9 @@ void USBHost::setUsbTaskState(uint8_t state) {
capacity = info.capacity.block_nbr / 2000; capacity = info.capacity.block_nbr / 2000;
block_size = info.capacity.block_size; block_size = info.capacity.block_size;
block_count = info.capacity.block_nbr; block_count = info.capacity.block_nbr;
//SERIAL_ECHOLNPGM("info.capacity.block_nbr : ", info.capacity.block_nbr); //SERIAL_ECHOLNPGM("info.capacity.block_nbr : %ld\n", info.capacity.block_nbr);
//SERIAL_ECHOLNPGM("info.capacity.block_size: ", info.capacity.block_size); //SERIAL_ECHOLNPGM("info.capacity.block_size: %d\n", info.capacity.block_size);
//SERIAL_ECHOLNPGM("capacity : ", capacity, "MB"); //SERIAL_ECHOLNPGM("capacity : %d MB\n", capacity);
} }
}; };
+5 -1
View File
@@ -81,6 +81,10 @@
#define MCU_TEMP_TIMER 14 // TIM7 is consumed by Software Serial if used. #define MCU_TEMP_TIMER 14 // TIM7 is consumed by Software Serial if used.
#endif #endif
#ifndef HAL_TIMER_RATE
#define HAL_TIMER_RATE GetStepperTimerClkFreq()
#endif
#ifndef STEP_TIMER #ifndef STEP_TIMER
#define STEP_TIMER MCU_STEP_TIMER #define STEP_TIMER MCU_STEP_TIMER
#endif #endif
@@ -137,7 +141,7 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
*/ */
timer_instance[timer_num]->setPrescaleFactor(STEPPER_TIMER_PRESCALE); //the -1 is done internally timer_instance[timer_num]->setPrescaleFactor(STEPPER_TIMER_PRESCALE); //the -1 is done internally
timer_instance[timer_num]->setOverflow(_MIN(HAL_TIMER_TYPE_MAX, hal_timer_t((HAL_TIMER_RATE) / (STEPPER_TIMER_PRESCALE) /* / frequency */)), TICK_FORMAT); timer_instance[timer_num]->setOverflow(_MIN(hal_timer_t(HAL_TIMER_TYPE_MAX), (HAL_TIMER_RATE) / (STEPPER_TIMER_PRESCALE) /* /frequency */), TICK_FORMAT);
break; break;
case MF_TIMER_TEMP: // TEMP TIMER - any available 16bit timer case MF_TIMER_TEMP: // TEMP TIMER - any available 16bit timer
timer_instance[timer_num] = new HardwareTimer(TEMP_TIMER_DEV); timer_instance[timer_num] = new HardwareTimer(TEMP_TIMER_DEV);
+8 -13
View File
@@ -48,21 +48,16 @@
#define TIMER_INDEX_(T) TIMER##T##_INDEX // TIMER#_INDEX enums (timer_index_t) depend on TIM#_BASE defines. #define TIMER_INDEX_(T) TIMER##T##_INDEX // TIMER#_INDEX enums (timer_index_t) depend on TIM#_BASE defines.
#define TIMER_INDEX(T) TIMER_INDEX_(T) // Convert Timer ID to HardwareTimer_Handle index. #define TIMER_INDEX(T) TIMER_INDEX_(T) // Convert Timer ID to HardwareTimer_Handle index.
#ifndef HAL_TIMER_RATE #define TEMP_TIMER_FREQUENCY 1000 // Temperature::isr() is expected to be called at around 1kHz
extern uint32_t GetStepperTimerClkFreq();
#define HAL_TIMER_RATE GetStepperTimerClkFreq()
#endif
// Timer configuration constants // TODO: get rid of manual rate/prescale/ticks/cycles taken for procedures in stepper.cpp
#define STEPPER_TIMER_RATE 2000000 #define STEPPER_TIMER_RATE 2000000 // 2 Mhz
#define TEMP_TIMER_FREQUENCY 1000 // Temperature::isr() should run at ~1kHz extern uint32_t GetStepperTimerClkFreq();
#define STEPPER_TIMER_PRESCALE (GetStepperTimerClkFreq() / (STEPPER_TIMER_RATE))
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000UL) // (MHz) Stepper Timer ticks per µs
// Timer prescaler calculations #define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer
#define STEPPER_TIMER_PRESCALE ((HAL_TIMER_RATE) / (STEPPER_TIMER_RATE)) #define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000UL) // (ticks/μs) Stepper Timer ticks per µs
// Pulse Timer (counter) calculations
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE #define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP) #define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP)
+1 -1
View File
@@ -27,7 +27,7 @@
* On STM32F, all pins support external interrupt capability. * On STM32F, all pins support external interrupt capability.
* Any pin can be used for external interrupts, but there are some restrictions. * Any pin can be used for external interrupts, but there are some restrictions.
* At most 16 different external interrupts can be used at one time. * At most 16 different external interrupts can be used at one time.
* Further, you can't just pick any 16 pins to use. This is because every pin on the STM32 * Further, you cant just pick any 16 pins to use. This is because every pin on the STM32
* connects to what is called an EXTI line, and only one pin per EXTI line can be used for external interrupts at a time * connects to what is called an EXTI line, and only one pin per EXTI line can be used for external interrupts at a time
* Check the Reference Manual of the MCU to confirm which line is used by each pin * Check the Reference Manual of the MCU to confirm which line is used by each pin
*/ */
+2 -2
View File
@@ -84,7 +84,7 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
timer_set_prescaler(STEP_TIMER_DEV, (uint16_t)(STEPPER_TIMER_PRESCALE - 1)); timer_set_prescaler(STEP_TIMER_DEV, (uint16_t)(STEPPER_TIMER_PRESCALE - 1));
timer_set_reload(STEP_TIMER_DEV, 0xFFFF); timer_set_reload(STEP_TIMER_DEV, 0xFFFF);
timer_oc_set_mode(STEP_TIMER_DEV, STEP_TIMER_CHAN, TIMER_OC_MODE_FROZEN, TIMER_OC_NO_PRELOAD); // no output pin change timer_oc_set_mode(STEP_TIMER_DEV, STEP_TIMER_CHAN, TIMER_OC_MODE_FROZEN, TIMER_OC_NO_PRELOAD); // no output pin change
timer_set_compare(STEP_TIMER_DEV, STEP_TIMER_CHAN, _MIN(HAL_TIMER_TYPE_MAX, hal_timer_t((STEPPER_TIMER_RATE) / frequency))); timer_set_compare(STEP_TIMER_DEV, STEP_TIMER_CHAN, _MIN(hal_timer_t(HAL_TIMER_TYPE_MAX), (STEPPER_TIMER_RATE) / frequency));
timer_no_ARR_preload_ARPE(STEP_TIMER_DEV); // Need to be sure no preload on ARR register timer_no_ARR_preload_ARPE(STEP_TIMER_DEV); // Need to be sure no preload on ARR register
timer_attach_interrupt(STEP_TIMER_DEV, STEP_TIMER_CHAN, stepTC_Handler); timer_attach_interrupt(STEP_TIMER_DEV, STEP_TIMER_CHAN, stepTC_Handler);
HAL_timer_set_interrupt_priority(MF_TIMER_STEP, STEP_TIMER_IRQ_PRIO); HAL_timer_set_interrupt_priority(MF_TIMER_STEP, STEP_TIMER_IRQ_PRIO);
@@ -97,7 +97,7 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
timer_set_count(TEMP_TIMER_DEV, 0); timer_set_count(TEMP_TIMER_DEV, 0);
timer_set_prescaler(TEMP_TIMER_DEV, (uint16_t)(TEMP_TIMER_PRESCALE - 1)); timer_set_prescaler(TEMP_TIMER_DEV, (uint16_t)(TEMP_TIMER_PRESCALE - 1));
timer_set_reload(TEMP_TIMER_DEV, 0xFFFF); timer_set_reload(TEMP_TIMER_DEV, 0xFFFF);
timer_set_compare(TEMP_TIMER_DEV, TEMP_TIMER_CHAN, _MIN(HAL_TIMER_TYPE_MAX, hal_timer_t((F_CPU) / (TEMP_TIMER_PRESCALE) / frequency))); timer_set_compare(TEMP_TIMER_DEV, TEMP_TIMER_CHAN, _MIN(hal_timer_t(HAL_TIMER_TYPE_MAX), (F_CPU) / (TEMP_TIMER_PRESCALE) / frequency));
timer_attach_interrupt(TEMP_TIMER_DEV, TEMP_TIMER_CHAN, tempTC_Handler); timer_attach_interrupt(TEMP_TIMER_DEV, TEMP_TIMER_CHAN, tempTC_Handler);
HAL_timer_set_interrupt_priority(MF_TIMER_TEMP, TEMP_TIMER_IRQ_PRIO); HAL_timer_set_interrupt_priority(MF_TIMER_TEMP, TEMP_TIMER_IRQ_PRIO);
timer_generate_update(TEMP_TIMER_DEV); timer_generate_update(TEMP_TIMER_DEV);
+2 -1
View File
@@ -40,7 +40,7 @@
*/ */
typedef uint16_t hal_timer_t; typedef uint16_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX hal_timer_t(UINT16_MAX) #define HAL_TIMER_TYPE_MAX 0xFFFFU
#define HAL_TIMER_RATE uint32_t(F_CPU) // frequency of timers peripherals #define HAL_TIMER_RATE uint32_t(F_CPU) // frequency of timers peripherals
@@ -103,6 +103,7 @@ typedef uint16_t hal_timer_t;
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000UL) // (MHz) Stepper Timer ticks per µs #define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000UL) // (MHz) Stepper Timer ticks per µs
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer #define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE #define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
timer_dev* HAL_get_timer_dev(int number); timer_dev* HAL_get_timer_dev(int number);
+2
View File
@@ -31,5 +31,7 @@ class libServo : public Servo {
void move(const int value); void move(const int value);
private: private:
typedef Servo super; typedef Servo super;
uint16_t min_ticks;
uint16_t max_ticks;
uint8_t servoIndex; // index into the channel data for this servo uint8_t servoIndex; // index into the channel data for this servo
}; };
+3 -2
View File
@@ -34,7 +34,7 @@
#define FORCE_INLINE __attribute__((always_inline)) inline #define FORCE_INLINE __attribute__((always_inline)) inline
typedef uint32_t hal_timer_t; typedef uint32_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX hal_timer_t(UINT32_MAX) #define HAL_TIMER_TYPE_MAX 0xFFFFFFFFUL
#define FTM0_TIMER_PRESCALE 8 #define FTM0_TIMER_PRESCALE 8
#define FTM1_TIMER_PRESCALE 4 #define FTM1_TIMER_PRESCALE 4
@@ -59,10 +59,11 @@ typedef uint32_t hal_timer_t;
#define TEMP_TIMER_FREQUENCY 1000 #define TEMP_TIMER_FREQUENCY 1000
#define STEPPER_TIMER_RATE HAL_TIMER_RATE #define STEPPER_TIMER_RATE HAL_TIMER_RATE
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000UL) // (MHz) Stepper Timer ticks per µs #define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000UL)
#define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US) #define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US)
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer #define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE #define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP) #define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP)
+2
View File
@@ -35,5 +35,7 @@ class libServo : public Servo {
void move(const int value); void move(const int value);
private: private:
typedef Servo super; typedef Servo super;
uint16_t min_ticks;
uint16_t max_ticks;
uint8_t servoIndex; // Index into the channel data for this servo uint8_t servoIndex; // Index into the channel data for this servo
}; };
+3 -2
View File
@@ -34,7 +34,7 @@
#define FORCE_INLINE __attribute__((always_inline)) inline #define FORCE_INLINE __attribute__((always_inline)) inline
typedef uint32_t hal_timer_t; typedef uint32_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX hal_timer_t(UINT32_MAX) #define HAL_TIMER_TYPE_MAX 0xFFFFFFFFUL
#define FTM0_TIMER_PRESCALE 8 #define FTM0_TIMER_PRESCALE 8
#define FTM1_TIMER_PRESCALE 4 #define FTM1_TIMER_PRESCALE 4
@@ -59,10 +59,11 @@ typedef uint32_t hal_timer_t;
#define TEMP_TIMER_FREQUENCY 1000 #define TEMP_TIMER_FREQUENCY 1000
#define STEPPER_TIMER_RATE HAL_TIMER_RATE #define STEPPER_TIMER_RATE HAL_TIMER_RATE
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000UL) // (MHz) Stepper Timer ticks per µs #define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000UL)
#define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US) #define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US)
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer #define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE #define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP) #define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP)
+2
View File
@@ -37,5 +37,7 @@ class libServo : public PWMServo {
private: private:
typedef PWMServo super; typedef PWMServo super;
uint8_t servoPin; uint8_t servoPin;
uint16_t min_ticks;
uint16_t max_ticks;
uint8_t servoIndex; // Index into the channel data for this servo uint8_t servoIndex; // Index into the channel data for this servo
}; };
+1 -1
View File
@@ -41,7 +41,7 @@
#error "POSTMORTEM_DEBUGGING is not yet supported for Teensy 4.0/4.1." #error "POSTMORTEM_DEBUGGING is not yet supported for Teensy 4.0/4.1."
#endif #endif
#if ANY(SERIAL_STATS_MAX_RX_QUEUED, SERIAL_STATS_DROPPED_RX, SERIAL_STATS_RX_FRAMING_ERRORS, SERIAL_STATS_RX_BUFFER_OVERRUNS) #if ENABLED(SERIAL_STATS_MAX_RX_QUEUED) || ENABLED(SERIAL_STATS_DROPPED_RX) || ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS) || ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
#error "SERIAL_STATS_* features not supported on Teensy 4.0/4.1." #error "SERIAL_STATS_* features not supported on Teensy 4.0/4.1."
#endif #endif
+6 -5
View File
@@ -34,7 +34,7 @@
#define FORCE_INLINE __attribute__((always_inline)) inline #define FORCE_INLINE __attribute__((always_inline)) inline
typedef uint32_t hal_timer_t; typedef uint32_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX hal_timer_t(UINT32_MAX-1UL) #define HAL_TIMER_TYPE_MAX 0xFFFFFFFEUL
#define GPT_TIMER_RATE (F_CPU / 4) // 150MHz (Can't use F_BUS_ACTUAL because it's extern volatile) #define GPT_TIMER_RATE (F_CPU / 4) // 150MHz (Can't use F_BUS_ACTUAL because it's extern volatile)
@@ -57,12 +57,13 @@ typedef uint32_t hal_timer_t;
#define TEMP_TIMER_RATE 1000000 #define TEMP_TIMER_RATE 1000000
#define TEMP_TIMER_FREQUENCY 1000 #define TEMP_TIMER_FREQUENCY 1000
#define HAL_TIMER_RATE GPT1_TIMER_RATE #define HAL_TIMER_RATE GPT1_TIMER_RATE
#define STEPPER_TIMER_RATE HAL_TIMER_RATE #define STEPPER_TIMER_RATE HAL_TIMER_RATE
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000UL) #define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000UL)
#define STEPPER_TIMER_PRESCALE (GPT_TIMER_RATE / STEPPER_TIMER_RATE) #define STEPPER_TIMER_PRESCALE (GPT_TIMER_RATE / STEPPER_TIMER_RATE)
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer #define PULSE_TIMER_RATE STEPPER_TIMER_RATE // (Hz) Frequency of Pulse Timer
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE #define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP) #define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP)
+1 -1
View File
@@ -85,7 +85,7 @@
} }
else { else {
// Enable DWT counter // Enable DWT counter
// From https://stackoverflow.com/questions/36378280/stm32-how-to-enable-dwt-cycle-counter/41188674#41188674 // From https://stackoverflow.com/a/41188674/1469714
HW_REG(_DEM_CR) = HW_REG(_DEM_CR) | 0x01000000; // Enable trace HW_REG(_DEM_CR) = HW_REG(_DEM_CR) | 0x01000000; // Enable trace
#if __CORTEX_M == 7 #if __CORTEX_M == 7
HW_REG(_LAR) = 0xC5ACCE55; // Unlock access to DWT registers, see https://developer.arm.com/documentation/ihi0029/e/ section B2.3.10 HW_REG(_LAR) = 0xC5ACCE55; // Unlock access to DWT registers, see https://developer.arm.com/documentation/ihi0029/e/ section B2.3.10
@@ -66,7 +66,7 @@ void * hook_get_usagefault_vector_address(unsigned vtor) { return (void*)(vtor +
void * hook_get_reserved_vector_address(unsigned vtor) { return (void*)(vtor + 0x07); } void * hook_get_reserved_vector_address(unsigned vtor) { return (void*)(vtor + 0x07); }
// Common exception frame for ARM, should work for all ARM CPU // Common exception frame for ARM, should work for all ARM CPU
// Described here (modified for convenience): https://interrupt.memfault.com/blog/cortex-m-hardfault-debug // Described here (modified for convenience): https://interrupt.memfault.com/blog/cortex-m-fault-debug
struct __attribute__((packed)) ContextStateFrame { struct __attribute__((packed)) ContextStateFrame {
uint32_t r0; uint32_t r0;
uint32_t r1; uint32_t r1;
+41 -51
View File
@@ -74,11 +74,11 @@
#endif #endif
#if HAS_DWIN_E3V2 #if HAS_DWIN_E3V2
#include "lcd/dwin/common/encoder.h" #include "lcd/e3v2/common/encoder.h"
#if ENABLED(DWIN_CREALITY_LCD) #if ENABLED(DWIN_CREALITY_LCD)
#include "lcd/dwin/creality/dwin.h" #include "lcd/e3v2/creality/dwin.h"
#elif ENABLED(DWIN_CREALITY_LCD_JYERSUI) #elif ENABLED(DWIN_CREALITY_LCD_JYERSUI)
#include "lcd/dwin/jyersui/dwin.h" #include "lcd/e3v2/jyersui/dwin.h"
#elif ENABLED(SOVOL_SV06_RTS) #elif ENABLED(SOVOL_SV06_RTS)
#include "lcd/sovol_rts/sovol_rts.h" #include "lcd/sovol_rts/sovol_rts.h"
#endif #endif
@@ -260,10 +260,6 @@
#include "feature/rs485.h" #include "feature/rs485.h"
#endif #endif
#if ENABLED(SOFT_FEED_HOLD)
#include "feature/e_parser.h"
#endif
/** /**
* Spin in place here while keeping temperature processing alive * Spin in place here while keeping temperature processing alive
*/ */
@@ -286,7 +282,7 @@ Marlin marlin;
#endif #endif
// Global state of the firmware // Global state of the firmware
MarlinState Marlin::state = MF_INITIALIZING; MarlinState Marlin::state = MarlinState::MF_INITIALIZING;
// For M109 and M190, this flag may be cleared (by M108) to exit the wait loop // For M109 and M190, this flag may be cleared (by M108) to exit the wait loop
bool Marlin::wait_for_heatup = false; bool Marlin::wait_for_heatup = false;
@@ -374,7 +370,7 @@ void Marlin::startOrResumeJob() {
if (!printingIsPaused()) { if (!printingIsPaused()) {
TERN_(GCODE_REPEAT_MARKERS, repeat.reset()); TERN_(GCODE_REPEAT_MARKERS, repeat.reset());
TERN_(CANCEL_OBJECTS, cancelable.reset()); TERN_(CANCEL_OBJECTS, cancelable.reset());
TERN_(LCD_SHOW_E_TOTAL, motion.e_move_accumulator = 0); TERN_(LCD_SHOW_E_TOTAL, e_move_accumulator = 0);
TERN_(SET_REMAINING_TIME, ui.reset_remaining_time()); TERN_(SET_REMAINING_TIME, ui.reset_remaining_time());
TERN_(HAS_PRUSA_MMU3, MMU3::operation_statistics.reset_per_print_stats()); TERN_(HAS_PRUSA_MMU3, MMU3::operation_statistics.reset_per_print_stats());
} }
@@ -388,7 +384,7 @@ void Marlin::startOrResumeJob() {
card.abortFilePrintNow(TERN_(SD_RESORT, true)); card.abortFilePrintNow(TERN_(SD_RESORT, true));
queue.clear(); queue.clear();
motion.quickstop_stepper(); quickstop_stepper();
print_job_timer.abort(); print_job_timer.abort();
@@ -408,8 +404,8 @@ void Marlin::startOrResumeJob() {
} }
inline void finishSDPrinting() { inline void finishSDPrinting() {
if (queue.enqueue_one(F("M1001"))) { // Keep trying until it gets queued if (queue.enqueue_one(F("M1001"))) { // Keep trying until it gets queued
marlin.setState(MF_RUNNING); // Signal to stop trying marlin.setState(MarlinState::MF_RUNNING); // Signal to stop trying
TERN_(PASSWORD_AFTER_SD_PRINT_END, password.lock_machine()); TERN_(PASSWORD_AFTER_SD_PRINT_END, password.lock_machine());
TERN_(DGUS_LCD_UI_MKS, screen.sdPrintingFinished()); TERN_(DGUS_LCD_UI_MKS, screen.sdPrintingFinished());
} }
@@ -518,14 +514,8 @@ void Marlin::manage_inactivity(const bool no_stepper_sleep/*=false*/) {
} }
#endif #endif
// Handle the FREEZE button #if ENABLED(FREEZE_FEATURE)
#if ANY(FREEZE_FEATURE, SOFT_FEED_HOLD) stepper.frozen = READ(FREEZE_PIN) == FREEZE_STATE;
stepper.set_frozen_triggered(
TERN0(FREEZE_FEATURE, READ(FREEZE_PIN) == FREEZE_STATE)
#if ALL(SOFT_FEED_HOLD, REALTIME_REPORTING_COMMANDS)
|| realtime_ramping_pause_flag
#endif
);
#endif #endif
#if HAS_HOME #if HAS_HOME
@@ -709,19 +699,19 @@ void Marlin::manage_inactivity(const bool no_stepper_sleep/*=false*/) {
#endif #endif
#if ENABLED(EXTRUDER_RUNOUT_PREVENT) #if ENABLED(EXTRUDER_RUNOUT_PREVENT)
if (thermalManager.degHotend(motion.extruder) > (EXTRUDER_RUNOUT_MINTEMP) if (thermalManager.degHotend(active_extruder) > (EXTRUDER_RUNOUT_MINTEMP)
&& ELAPSED(ms, gcode.previous_move_ms, SEC_TO_MS(EXTRUDER_RUNOUT_SECONDS)) && ELAPSED(ms, gcode.previous_move_ms, SEC_TO_MS(EXTRUDER_RUNOUT_SECONDS))
&& !planner.has_blocks_queued() && !planner.has_blocks_queued()
) { ) {
const int8_t e_stepper = TERN(HAS_SWITCHING_EXTRUDER, motion.extruder / 2, motion.extruder); const int8_t e_stepper = TERN(HAS_SWITCHING_EXTRUDER, active_extruder >> 1, active_extruder);
const bool e_off = !stepper.AXIS_IS_ENABLED(E_AXIS, e_stepper); const bool e_off = !stepper.AXIS_IS_ENABLED(E_AXIS, e_stepper);
if (e_off) stepper.ENABLE_EXTRUDER(e_stepper); if (e_off) stepper.ENABLE_EXTRUDER(e_stepper);
const float olde = motion.position.e; const float olde = current_position.e;
motion.position.e += EXTRUDER_RUNOUT_EXTRUDE; current_position.e += EXTRUDER_RUNOUT_EXTRUDE;
motion.goto_current_position(MMM_TO_MMS(EXTRUDER_RUNOUT_SPEED)); line_to_current_position(MMM_TO_MMS(EXTRUDER_RUNOUT_SPEED));
motion.position.e = olde; current_position.e = olde;
motion.sync_plan_position_e(); planner.set_e_position_mm(olde);
planner.synchronize(); planner.synchronize();
if (e_off) stepper.DISABLE_EXTRUDER(e_stepper); if (e_off) stepper.DISABLE_EXTRUDER(e_stepper);
@@ -732,11 +722,11 @@ void Marlin::manage_inactivity(const bool no_stepper_sleep/*=false*/) {
#if ENABLED(DUAL_X_CARRIAGE) #if ENABLED(DUAL_X_CARRIAGE)
// handle delayed move timeout // handle delayed move timeout
if (motion.delayed_move_time && ELAPSED(ms, motion.delayed_move_time) && isRunning()) { if (delayed_move_time && ELAPSED(ms, delayed_move_time) && isRunning()) {
// travel moves have been received so enact them // travel moves have been received so enact them
motion.delayed_move_time = UINT32_MAX; // force moves to be done delayed_move_time = 0xFFFFFFFFUL; // force moves to be done
motion.destination = motion.position; destination = current_position;
motion.prepare_line_to_destination(); prepare_line_to_destination();
planner.synchronize(); planner.synchronize();
} }
#endif #endif
@@ -813,10 +803,10 @@ void Marlin::idle(const bool no_stepper_sleep/*=false*/) {
TERN_(MAX7219_DEBUG, max7219.idle_tasks()); TERN_(MAX7219_DEBUG, max7219.idle_tasks());
// Return if setup() isn't completed // Return if setup() isn't completed
if (is(MF_INITIALIZING)) goto IDLE_DONE; if (state == MarlinState::MF_INITIALIZING) goto IDLE_DONE;
// TODO: Still causing errors // TODO: Still causing errors
TERN_(TOOL_SENSOR, (void)check_tool_sensor_stats(motion.extruder, true)); TERN_(TOOL_SENSOR, (void)check_tool_sensor_stats(active_extruder, true));
// Handle filament runout sensors // Handle filament runout sensors
#if HAS_FILAMENT_SENSOR #if HAS_FILAMENT_SENSOR
@@ -853,17 +843,6 @@ void Marlin::idle(const bool no_stepper_sleep/*=false*/) {
// Update the Beeper queue // Update the Beeper queue
TERN_(HAS_BEEPER, buzzer.tick()); TERN_(HAS_BEEPER, buzzer.tick());
// Async Babystepping via the Emergency Parser
#if ALL(EP_BABYSTEPPING, EMERGENCY_PARSER)
babystep.do_ep_steps();
#endif
// Direct Stepping
TERN_(DIRECT_STEPPING, page_manager.write_responses());
// Manage Fixed-time Motion Control
TERN_(FT_MOTION, ftMotion.loop());
// Handle UI input / draw events // Handle UI input / draw events
#if ENABLED(SOVOL_SV06_RTS) #if ENABLED(SOVOL_SV06_RTS)
RTS_Update(); RTS_Update();
@@ -891,7 +870,7 @@ void Marlin::idle(const bool no_stepper_sleep/*=false*/) {
TERN_(AUTO_REPORT_TEMPERATURES, thermalManager.auto_reporter.tick()); TERN_(AUTO_REPORT_TEMPERATURES, thermalManager.auto_reporter.tick());
TERN_(AUTO_REPORT_FANS, fan_check.auto_reporter.tick()); TERN_(AUTO_REPORT_FANS, fan_check.auto_reporter.tick());
TERN_(AUTO_REPORT_SD_STATUS, card.auto_reporter.tick()); TERN_(AUTO_REPORT_SD_STATUS, card.auto_reporter.tick());
TERN_(AUTO_REPORT_POSITION, motion.position_auto_reporter.tick()); TERN_(AUTO_REPORT_POSITION, position_auto_reporter.tick());
TERN_(BUFFER_MONITORING, queue.auto_report_buffer_statistics()); TERN_(BUFFER_MONITORING, queue.auto_report_buffer_statistics());
} }
#endif #endif
@@ -906,9 +885,20 @@ void Marlin::idle(const bool no_stepper_sleep/*=false*/) {
// Handle Joystick jogging // Handle Joystick jogging
TERN_(POLL_JOG, joystick.inject_jog_moves()); TERN_(POLL_JOG, joystick.inject_jog_moves());
// Async Babystepping via the Emergency Parser
#if ALL(EP_BABYSTEPPING, EMERGENCY_PARSER)
babystep.do_ep_steps();
#endif
// Direct Stepping
TERN_(DIRECT_STEPPING, page_manager.write_responses());
// Update the LVGL interface // Update the LVGL interface
TERN_(HAS_TFT_LVGL_UI, LV_TASK_HANDLER()); TERN_(HAS_TFT_LVGL_UI, LV_TASK_HANDLER());
// Manage Fixed-time Motion Control
TERN_(FT_MOTION, ftMotion.loop());
IDLE_DONE: IDLE_DONE:
TERN_(MARLIN_DEV_MODE, idle_depth--); TERN_(MARLIN_DEV_MODE, idle_depth--);
@@ -1006,7 +996,7 @@ void Marlin::stop() {
SERIAL_ERROR_MSG(STR_ERR_STOPPED); SERIAL_ERROR_MSG(STR_ERR_STOPPED);
LCD_MESSAGE(MSG_STOPPED); LCD_MESSAGE(MSG_STOPPED);
safe_delay(350); // Allow enough time for messages to get out before stopping safe_delay(350); // Allow enough time for messages to get out before stopping
setState(MF_STOPPED); state = MarlinState::MF_STOPPED;
} }
} // Marlin::stop() } // Marlin::stop()
@@ -1231,7 +1221,7 @@ void setup() {
#endif #endif
#endif #endif
#if ENABLED(FREEZE_FEATURE) && DISABLED(NO_FREEZE_PIN) #if ENABLED(FREEZE_FEATURE)
SETUP_LOG("FREEZE_PIN"); SETUP_LOG("FREEZE_PIN");
#if FREEZE_STATE #if FREEZE_STATE
SET_INPUT_PULLDOWN(FREEZE_PIN); SET_INPUT_PULLDOWN(FREEZE_PIN);
@@ -1411,9 +1401,9 @@ void setup() {
SETUP_RUN(touchBt.init()); SETUP_RUN(touchBt.init());
#endif #endif
TERN_(HAS_HOME_OFFSET, motion.position += motion.home_offset); // Init current position based on home_offset TERN_(HAS_HOME_OFFSET, current_position += home_offset); // Init current position based on home_offset
motion.sync_plan_position(); // Vital to init stepper/planner equivalent for motion.position sync_plan_position(); // Vital to init stepper/planner equivalent for current_position
SETUP_RUN(thermalManager.init()); // Initialize temperature loop SETUP_RUN(thermalManager.init()); // Initialize temperature loop
@@ -1719,7 +1709,7 @@ void setup() {
SETUP_RUN(ftMotion.init()); SETUP_RUN(ftMotion.init());
#endif #endif
marlin.setState(MF_RUNNING); marlin.setState(MarlinState::MF_RUNNING);
#ifdef STARTUP_TUNE #ifdef STARTUP_TUNE
// Play a short startup tune before continuing. // Play a short startup tune before continuing.
@@ -1751,7 +1741,7 @@ void loop() {
#if HAS_MEDIA #if HAS_MEDIA
if (card.flag.abort_sd_printing) abortSDPrinting(); if (card.flag.abort_sd_printing) abortSDPrinting();
if (marlin.is(MF_SD_COMPLETE)) finishSDPrinting(); if (marlin.is(MarlinState::MF_SD_COMPLETE)) finishSDPrinting();
#endif #endif
queue.advance(); queue.advance();
+3 -3
View File
@@ -28,7 +28,7 @@
#include <stdlib.h> #include <stdlib.h>
// Global State of the firmware // Global State of the firmware
enum MarlinState : uint8_t { enum class MarlinState : uint8_t {
MF_INITIALIZING = 0, MF_INITIALIZING = 0,
MF_STOPPED, MF_STOPPED,
MF_KILLED, MF_KILLED,
@@ -54,8 +54,8 @@ public:
static MarlinState state; static MarlinState state;
static void setState(const MarlinState s) { state = s; } static void setState(const MarlinState s) { state = s; }
static bool is(const MarlinState s) { return state == s; } static bool is(const MarlinState s) { return state == s; }
static bool isStopped() { return is(MF_STOPPED); } static bool isStopped() { return is(MarlinState::MF_STOPPED); }
static bool isRunning() { return state >= MF_RUNNING; } static bool isRunning() { return state >= MarlinState::MF_RUNNING; }
static bool printingIsActive(); static bool printingIsActive();
static bool printJobOngoing(); static bool printJobOngoing();
+10 -13
View File
@@ -187,7 +187,6 @@
#define BOARD_MALYAN_M180 1333 // Malyan M180 Mainboard Version 2 (no display function, direct G-code only) #define BOARD_MALYAN_M180 1333 // Malyan M180 Mainboard Version 2 (no display function, direct G-code only)
#define BOARD_PROTONEER_CNC_SHIELD_V3 1334 // Mega controller & Protoneer CNC Shield V3.00 #define BOARD_PROTONEER_CNC_SHIELD_V3 1334 // Mega controller & Protoneer CNC Shield V3.00
#define BOARD_WEEDO_62A 1335 // WEEDO 62A board (TINA2, Monoprice Cadet, etc.) #define BOARD_WEEDO_62A 1335 // WEEDO 62A board (TINA2, Monoprice Cadet, etc.)
#define BOARD_MIGHTYBOARD_REVG 1336 // Makerbot Mightyboard Revision G and H
// //
// ATmega1281, ATmega2561 // ATmega1281, ATmega2561
@@ -420,7 +419,6 @@
#define BOARD_MD_D301 5068 // Mingda D2 DZ301 V1.0 (STM32F103ZE) #define BOARD_MD_D301 5068 // Mingda D2 DZ301 V1.0 (STM32F103ZE)
#define BOARD_VOXELAB_AQUILA 5069 // Voxelab Aquila V1.0.0/V1.0.1 (GD32F103RC / N32G455RE / STM32F103RE) #define BOARD_VOXELAB_AQUILA 5069 // Voxelab Aquila V1.0.0/V1.0.1 (GD32F103RC / N32G455RE / STM32F103RE)
#define BOARD_SPRINGER_CONTROLLER 5070 // ORCA 3D SPRINGER Modular Controller (STM32F103VC) #define BOARD_SPRINGER_CONTROLLER 5070 // ORCA 3D SPRINGER Modular Controller (STM32F103VC)
#define BOARD_ATOMSTACK_FB5_V2 5071 // Atomstack FB5 V2.0 (STM32F103RCT6)
// //
// ARM Cortex-M4F // ARM Cortex-M4F
@@ -485,17 +483,16 @@
#define BOARD_BLACKPILL_CUSTOM 5249 // Custom board based on STM32F401CDU6. #define BOARD_BLACKPILL_CUSTOM 5249 // Custom board based on STM32F401CDU6.
#define BOARD_I3DBEEZ9_V1 5250 // I3DBEEZ9 V1 (STM32F407ZG) #define BOARD_I3DBEEZ9_V1 5250 // I3DBEEZ9 V1 (STM32F407ZG)
#define BOARD_MELLOW_FLY_E3_V2 5251 // Mellow Fly E3 V2 (STM32F407VG) #define BOARD_MELLOW_FLY_E3_V2 5251 // Mellow Fly E3 V2 (STM32F407VG)
#define BOARD_MELLOW_FLY_E3_PRO_V3 5252 // Mellow Fly E3 Pro V3 (STM32F407VG) #define BOARD_BLACKBEEZMINI_V1 5252 // BlackBeezMini V1 (STM32F401CCU6)
#define BOARD_BLACKBEEZMINI_V1 5253 // BlackBeezMini V1 (STM32F401CCU6) #define BOARD_XTLW_CLIMBER_8TH 5253 // XTLW Climber-8th (STM32F407VGT6)
#define BOARD_XTLW_CLIMBER_8TH 5254 // XTLW Climber-8th (STM32F407VGT6) #define BOARD_FLY_RRF_E3_V1 5254 // Fly RRF E3 V1.0 (STM32F407VG)
#define BOARD_FLY_RRF_E3_V1 5255 // Fly RRF E3 V1.0 (STM32F407VG) #define BOARD_FLY_SUPER8 5255 // Fly SUPER8 (STM32F407ZGT6)
#define BOARD_FLY_SUPER8 5256 // Fly SUPER8 (STM32F407ZGT6) #define BOARD_FLY_D8 5256 // FLY D8 (STM32F407VG)
#define BOARD_FLY_D8 5257 // FLY D8 (STM32F407VG) #define BOARD_FLY_CDY_V3 5257 // FLY CDY V3 (STM32F407VGT6)
#define BOARD_FLY_CDY_V3 5258 // FLY CDY V3 (STM32F407VGT6) #define BOARD_ZNP_ROBIN_NANO 5258 // Elegoo Neptune 2 v1.2 board
#define BOARD_ZNP_ROBIN_NANO 5259 // Elegoo Neptune 2 v1.2 board #define BOARD_ZNP_ROBIN_NANO_V1_3 5259 // Elegoo Neptune 2 v1.3 board
#define BOARD_ZNP_ROBIN_NANO_V1_3 5260 // Elegoo Neptune 2 v1.3 board #define BOARD_MKS_NEPTUNE_X 5260 // Elegoo Neptune X
#define BOARD_MKS_NEPTUNE_X 5261 // Elegoo Neptune X #define BOARD_MKS_NEPTUNE_3 5261 // Elegoo Neptune 3
#define BOARD_MKS_NEPTUNE_3 5262 // Elegoo Neptune 3
// //
// Other ARM Cortex-M4 // Other ARM Cortex-M4
+1 -1
View File
@@ -41,6 +41,6 @@ private:
SERIAL_ECHO(fpre); SERIAL_ECHO(fpre);
if (the_msg) SERIAL_ECHO(C(' '), the_msg); if (the_msg) SERIAL_ECHO(C(' '), the_msg);
SERIAL_CHAR(' '); SERIAL_CHAR(' ');
print_xyz(xyz_pos_t(motion.position)); print_xyz(xyz_pos_t(current_position));
} }
}; };
+3 -5
View File
@@ -57,10 +57,8 @@
// fr French // fr French
// fr_na French without accents (DWIN T5UID1 touchscreen) // fr_na French without accents (DWIN T5UID1 touchscreen)
// gl Galician // gl Galician
// hg Hinglish (Hindi in Latin script)
// hr Croatian // hr Croatian
// hu Hungarian // hu Hungarian
// id Indonesian (Bahasa)
// it Italian // it Italian
// jp_kana Japanese // jp_kana Japanese
// ko_KR Korean (South Korea) // ko_KR Korean (South Korea)
@@ -368,17 +366,17 @@
#define STR_Z2 STR_C "2" #define STR_Z2 STR_C "2"
#define STR_Z3 STR_C "3" #define STR_Z3 STR_C "3"
#define STR_Z4 STR_C "4" #define STR_Z4 STR_C "4"
#if ANY(HAS_REAL_X, IS_SCARA, DELTA) #if CORE_IS_XY || CORE_IS_XZ
#define STEPPER_A_NAME 'A' #define STEPPER_A_NAME 'A'
#else #else
#define STEPPER_A_NAME 'X' #define STEPPER_A_NAME 'X'
#endif #endif
#if ANY(HAS_REAL_Y, IS_SCARA, DELTA, POLAR) #if CORE_IS_XY || CORE_IS_YZ
#define STEPPER_B_NAME 'B' #define STEPPER_B_NAME 'B'
#else #else
#define STEPPER_B_NAME 'Y' #define STEPPER_B_NAME 'Y'
#endif #endif
#if ANY(HAS_REAL_Z, DELTA) #if CORE_IS_XZ || CORE_IS_YZ
#define STEPPER_C_NAME 'C' #define STEPPER_C_NAME 'C'
#else #else
#define STEPPER_C_NAME 'Z' #define STEPPER_C_NAME 'Z'
-1
View File
@@ -256,7 +256,6 @@
// Array shorthand // Array shorthand
#define COUNT(a) (sizeof(a)/sizeof(*a)) #define COUNT(a) (sizeof(a)/sizeof(*a))
#define ZERO(a) memset((void*)a,0,sizeof(a)) #define ZERO(a) memset((void*)a,0,sizeof(a))
#define OBJZERO(a) memset(&a,0,sizeof(a))
#define COPY(a,b) do{ \ #define COPY(a,b) do{ \
static_assert(sizeof(a[0]) == sizeof(b[0]), "COPY: '" STRINGIFY(a) "' and '" STRINGIFY(b) "' types (sizes) don't match!"); \ static_assert(sizeof(a[0]) == sizeof(b[0]), "COPY: '" STRINGIFY(a) "' and '" STRINGIFY(b) "' types (sizes) don't match!"); \
memcpy(&a[0],&b[0],_MIN(sizeof(a),sizeof(b))); \ memcpy(&a[0],&b[0],_MIN(sizeof(a),sizeof(b))); \
+9 -9
View File
@@ -158,16 +158,16 @@ public:
MString& append_P(PGM_P const s) { int sz = length(); if (sz < SIZE) strlcpy_P(str + sz, s, SIZE - sz + 1); debug(F("pstring")); return *this; } MString& append_P(PGM_P const s) { int sz = length(); if (sz < SIZE) strlcpy_P(str + sz, s, SIZE - sz + 1); debug(F("pstring")); return *this; }
MString& append(FSTR_P const f) { return append_P(FTOP(f)); } MString& append(FSTR_P const f) { return append_P(FTOP(f)); }
MString& append(const bool &b) { return append(b ? F("true") : F("false")); } MString& append(const bool &b) { return append(b ? F("true") : F("false")); }
MString& append(const char c) { int sz = length(); if (sz < SIZE) { str[sz] = c; if (sz < SIZE - 1) str[sz + 1] = '\0'; } debug(F("char")); return *this; } MString& append(const char c) { int sz = length(); if (sz < SIZE) { str[sz] = c; if (sz < SIZE - 1) str[sz + 1] = '\0'; } return *this; }
#if ENABLED(FASTER_APPEND) #if ENABLED(FASTER_APPEND)
MString& append(const int8_t &i) { int sz = length(); SNPRINTF(&str[sz], SIZE - sz, "%d", i); debug(F("int8_t")); return *this; } MString& append(const int8_t &i) { int sz = length(); SNPRINTF(&str[sz], SIZE - sz, "%d", i); return *this; }
MString& append(const short &i) { int sz = length(); SNPRINTF(&str[sz], SIZE - sz, "%d", i); debug(F("short")); return *this; } MString& append(const short &i) { int sz = length(); SNPRINTF(&str[sz], SIZE - sz, "%d", i); return *this; }
MString& append(const int &i) { int sz = length(); SNPRINTF(&str[sz], SIZE - sz, "%d", i); debug(F("int")); return *this; } MString& append(const int &i) { int sz = length(); SNPRINTF(&str[sz], SIZE - sz, "%d", i); return *this; }
MString& append(const long &l) { int sz = length(); SNPRINTF(&str[sz], SIZE - sz, "%ld", l); debug(F("long")); return *this; } MString& append(const long &l) { int sz = length(); SNPRINTF(&str[sz], SIZE - sz, "%ld", l); return *this; }
MString& append(const unsigned char &i) { int sz = length(); SNPRINTF(&str[sz], SIZE - sz, "%u", i); debug(F("uchar")); return *this; } MString& append(const unsigned char &i) { int sz = length(); SNPRINTF(&str[sz], SIZE - sz, "%u", i); return *this; }
MString& append(const unsigned short &i) { int sz = length(); SNPRINTF(&str[sz], SIZE - sz, "%u", i); debug(F("ushort")); return *this; } MString& append(const unsigned short &i) { int sz = length(); SNPRINTF(&str[sz], SIZE - sz, "%u", i); return *this; }
MString& append(const unsigned int &i) { int sz = length(); SNPRINTF(&str[sz], SIZE - sz, "%u", i); debug(F("uint")); return *this; } MString& append(const unsigned int &i) { int sz = length(); SNPRINTF(&str[sz], SIZE - sz, "%u", i); return *this; }
MString& append(const unsigned long &l) { int sz = length(); SNPRINTF(&str[sz], SIZE - sz, "%lu", l); debug(F("ulong")); return *this; } MString& append(const unsigned long &l) { int sz = length(); SNPRINTF(&str[sz], SIZE - sz, "%lu", l); return *this; }
#else #else
MString& append(const int8_t &i) { char buf[ 5]; sprintf(buf, "%d", i); return append(buf); } MString& append(const int8_t &i) { char buf[ 5]; sprintf(buf, "%d", i); return append(buf); }
MString& append(const short &i) { char buf[12]; sprintf(buf, "%d", i); return append(buf); } MString& append(const short &i) { char buf[12]; sprintf(buf, "%d", i); return append(buf); }
+84 -162
View File
@@ -52,11 +52,6 @@ template <class L, class R> struct IF<true, L, R> { typedef L type; };
#define MAIN_AXIS_NAMES_LC 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 NUM_AXIS_CALL(G) do { NUM_AXIS_CODE(G(X_AXIS), G(Y_AXIS), G(Z_AXIS), G(I_AXIS), G(J_AXIS), G(K_AXIS), G(U_AXIS), G(V_AXIS), G(W_AXIS)); } while(0) #define NUM_AXIS_CALL(G) do { NUM_AXIS_CODE(G(X_AXIS), G(Y_AXIS), G(Z_AXIS), G(I_AXIS), G(J_AXIS), G(K_AXIS), G(U_AXIS), G(V_AXIS), G(W_AXIS)); } while(0)
#define STR_AXES_MAIN NUM_AXIS_GANG("X", "Y", "Z", STR_I, STR_J, STR_K, STR_U, STR_V, STR_W) #define STR_AXES_MAIN NUM_AXIS_GANG("X", "Y", "Z", STR_I, STR_J, STR_K, STR_U, STR_V, STR_W)
#define NUM_AXIS_ANY(x, y, z, i, j, k, u, v, w) (false \
NUM_AXIS_GANG(|| (x), || (y), || (z), || (i), || (j), || (k), || (u), || (v), || (w)))
#define NUM_AXIS_ALL(x, y, z, i, j, k, u, v, w) ((NUM_AXES > 0) \
NUM_AXIS_GANG(&& (x), && (y), && (z), && (i), && (j), && (k), && (u), && (v), && (w)))
#define NUM_AXIS_NONE(V...) !NUM_AXIS_ANY(V)
#define LOGICAL_AXIS_GANG(N,V...) NUM_AXIS_GANG(V) GANG_ITEM_E(N) #define LOGICAL_AXIS_GANG(N,V...) NUM_AXIS_GANG(V) GANG_ITEM_E(N)
#define LOGICAL_AXIS_CODE(N,V...) NUM_AXIS_CODE(V) CODE_ITEM_E(N) #define LOGICAL_AXIS_CODE(N,V...) NUM_AXIS_CODE(V) CODE_ITEM_E(N)
@@ -76,11 +71,6 @@ template <class L, class R> struct IF<true, L, R> { typedef L type; };
#define LOGICAL_AXIS_MAP_LC(F) MAP(F, LOGICAL_AXIS_NAMES_LC) #define LOGICAL_AXIS_MAP_LC(F) MAP(F, LOGICAL_AXIS_NAMES_LC)
#define LOGICAL_AXIS_CALL(G) do { LOGICAL_AXIS_CODE(G(E_AXIS), G(X_AXIS), G(Y_AXIS), G(Z_AXIS), G(I_AXIS), G(J_AXIS), G(K_AXIS), G(U_AXIS), G(V_AXIS), G(W_AXIS)); } while(0) #define LOGICAL_AXIS_CALL(G) do { LOGICAL_AXIS_CODE(G(E_AXIS), G(X_AXIS), G(Y_AXIS), G(Z_AXIS), G(I_AXIS), G(J_AXIS), G(K_AXIS), G(U_AXIS), G(V_AXIS), G(W_AXIS)); } while(0)
#define STR_AXES_LOGICAL LOGICAL_AXIS_GANG("E", "X", "Y", "Z", STR_I, STR_J, STR_K, STR_U, STR_V, STR_W) #define STR_AXES_LOGICAL LOGICAL_AXIS_GANG("E", "X", "Y", "Z", STR_I, STR_J, STR_K, STR_U, STR_V, STR_W)
#define LOGICAL_AXIS_ANY(e, x, y, z, i, j, k, u, v, w) (false \
LOGICAL_AXIS_GANG(|| (e), || (x), || (y), || (z), || (i), || (j), || (k), || (u), || (v), || (w)))
#define LOGICAL_AXIS_ALL(e, x, y, z, i, j, k, u, v, w) ((LOGICAL_AXES > 0) \
LOGICAL_AXIS_GANG(&& (e), && (x), && (y), && (z), && (i), && (j), && (k), && (u), && (v), && (w)))
#define LOGICAL_AXIS_NONE(V...) !LOGICAL_AXIS_ANY(V)
#define NUM_AXIS_PAIRED_LIST(V...) LIST_N(DOUBLE(NUM_AXES), V) #define NUM_AXIS_PAIRED_LIST(V...) LIST_N(DOUBLE(NUM_AXES), V)
#define LOGICAL_AXIS_PAIRED_LIST(EA,EB,V...) NUM_AXIS_PAIRED_LIST(V) LIST_ITEM_E(EA) LIST_ITEM_E(EB) #define LOGICAL_AXIS_PAIRED_LIST(EA,EB,V...) NUM_AXIS_PAIRED_LIST(V) LIST_ITEM_E(EA) LIST_ITEM_E(EB)
@@ -155,14 +145,10 @@ template <class L, class R> struct IF<true, L, R> { typedef L type; };
#define XY_ARRAY(V...) ARRAY_N(XY_COUNT, V) #define XY_ARRAY(V...) ARRAY_N(XY_COUNT, V)
#define XY_CODE(V...) CODE_N(XY_COUNT, V) #define XY_CODE(V...) CODE_N(XY_COUNT, V)
#define XY_GANG(V...) GANG_N(XY_COUNT, V) #define XY_GANG(V...) GANG_N(XY_COUNT, V)
#define XY_ANY(x,y) (false XY_GANG(|| (x), || (y)))
#define XY_ALL(x,y) ((NUM_AXES > 0) XY_GANG(&& (x), && (y)))
#define XYZ_LIST(V...) LIST_N(XYZ_COUNT, V) #define XYZ_LIST(V...) LIST_N(XYZ_COUNT, V)
#define XYZ_ARRAY(V...) ARRAY_N(XYZ_COUNT, V) #define XYZ_ARRAY(V...) ARRAY_N(XYZ_COUNT, V)
#define XYZ_CODE(V...) CODE_N(XYZ_COUNT, V) #define XYZ_CODE(V...) CODE_N(XYZ_COUNT, V)
#define XYZ_GANG(V...) GANG_N(XYZ_COUNT, V) #define XYZ_GANG(V...) GANG_N(XYZ_COUNT, V)
#define XYZ_ANY(x,y,z) (false XYZ_GANG(|| (x), || (y), || (z)))
#define XYZ_ALL(x,y,z) ((NUM_AXES > 0) XYZ_GANG(&& (x), && (y), && (z)))
#if HAS_ROTATIONAL_AXES #if HAS_ROTATIONAL_AXES
#define ROTATIONAL_AXIS_GANG(V...) GANG_N(ROTATIONAL_AXES, V) #define ROTATIONAL_AXIS_GANG(V...) GANG_N(ROTATIONAL_AXES, V)
@@ -191,7 +177,6 @@ template <class L, class R> struct IF<true, L, R> { typedef L type; };
#define CARTES_CODE(x,y,z,e) XYZ_CODE(x,y,z) CODE_ITEM_E(e) #define CARTES_CODE(x,y,z,e) XYZ_CODE(x,y,z) CODE_ITEM_E(e)
#define CARTES_GANG(x,y,z,e) XYZ_GANG(x,y,z) GANG_ITEM_E(e) #define CARTES_GANG(x,y,z,e) XYZ_GANG(x,y,z) GANG_ITEM_E(e)
#define CARTES_AXIS_NAMES CARTES_LIST(X,Y,Z,E) #define CARTES_AXIS_NAMES CARTES_LIST(X,Y,Z,E)
#define CARTES_AXIS_NAMES_LC CARTES_LIST(x,y,z,e)
#define CARTES_MAP(F) MAP(F, CARTES_AXIS_NAMES) #define CARTES_MAP(F) MAP(F, CARTES_AXIS_NAMES)
#if CARTES_COUNT #if CARTES_COUNT
#define CARTES_COMMA , #define CARTES_COMMA ,
@@ -350,9 +335,9 @@ typedef struct {
// //
// Enumerated axis indices // Enumerated axis indices
// //
// - X_REAL, Y_REAL, and Z_REAL should be used for axes in Cartesian space // - 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 // - A_AXIS, B_AXIS, and C_AXIS should be used for Steppers, corresponding to XYZ on Cartesians
// - X_AXIS, Y_AXIS, and Z_AXIS are now more generic interchangeble indexes // - X_HEAD, Y_HEAD, and Z_HEAD should be used for axes on Core kinematics
// //
enum AxisEnum : uint8_t { enum AxisEnum : uint8_t {
@@ -364,14 +349,8 @@ enum AxisEnum : uint8_t {
#undef _EN_ITEM #undef _EN_ITEM
// Core also keeps toolhead directions // Core also keeps toolhead directions
#if HAS_REAL_X #if ANY(IS_CORE, MARKFORGED_XY, MARKFORGED_YX)
X_REAL, X_HEAD, Y_HEAD, Z_HEAD,
#endif
#if HAS_REAL_Y
Y_REAL,
#endif
#if HAS_REAL_Z
Z_REAL,
#endif #endif
// Distinct axes, including all E and Core // Distinct axes, including all E and Core
@@ -380,10 +359,6 @@ enum AxisEnum : uint8_t {
// Most of the time we refer only to the single E_AXIS // Most of the time we refer only to the single E_AXIS
#if HAS_EXTRUDERS #if HAS_EXTRUDERS
E_AXIS = E0_AXIS, E_AXIS = E0_AXIS,
E_REAL = E_AXIS,
#define _EN_REAL(N) E##N##_REAL = E##N##_AXIS,
REPEAT(EXTRUDERS, _EN_REAL)
#undef _EN_REAL
#endif #endif
// A, B, and C are for DELTA, SCARA, etc. // A, B, and C are for DELTA, SCARA, etc.
@@ -397,35 +372,6 @@ enum AxisEnum : uint8_t {
C_AXIS = Z_AXIS, C_AXIS = Z_AXIS,
#endif #endif
// Aliases to distinguish tool axes from stepper indexes
#if HAS_X_AXIS && !HAS_REAL_X
X_REAL = X_AXIS,
#endif
#if HAS_Y_AXIS && !HAS_REAL_Y
Y_REAL = Y_AXIS,
#endif
#if HAS_Z_AXIS && !HAS_REAL_Z
Z_REAL = Z_AXIS,
#endif
#if HAS_I_AXIS
I_REAL = I_AXIS,
#endif
#if HAS_J_AXIS
J_REAL = J_AXIS,
#endif
#if HAS_K_AXIS
K_REAL = K_AXIS,
#endif
#if HAS_U_AXIS
U_REAL = U_AXIS,
#endif
#if HAS_V_AXIS
V_REAL = V_AXIS,
#endif
#if HAS_W_AXIS
W_REAL = W_AXIS,
#endif
// To refer to all or none // To refer to all or none
ALL_AXES_ENUM = 0xFE, NO_AXIS_ENUM = 0xFF ALL_AXES_ENUM = 0xFE, NO_AXIS_ENUM = 0xFF
}; };
@@ -610,7 +556,7 @@ struct XYval {
#endif #endif
// Length reduced to one dimension // Length reduced to one dimension
FI constexpr T magnitude() const { return (T)SQRT(x*x + y*y); } FI constexpr T magnitude() const { return (T)sqrtf(x*x + y*y); }
// Pointer to the data as a simple array // Pointer to the data as a simple array
explicit FI operator T* () { return pos; } explicit FI operator T* () { return pos; }
// If any element is true then it's true // If any element is true then it's true
@@ -632,7 +578,7 @@ struct XYval {
FI constexpr XYval<uint32_t> asUInt32() const { return { uint32_t(x), uint32_t(y) }; } FI constexpr XYval<uint32_t> asUInt32() const { return { uint32_t(x), uint32_t(y) }; }
FI constexpr XYval<int64_t> asInt64() const { return { int64_t(x), int64_t(y) }; } FI constexpr XYval<int64_t> asInt64() const { return { int64_t(x), int64_t(y) }; }
FI constexpr XYval<uint64_t> asUInt64() const { return { uint64_t(x), uint64_t(y) }; } FI constexpr XYval<uint64_t> asUInt64() const { return { uint64_t(x), uint64_t(y) }; }
FI constexpr XYval<float> asFloat() const { return { float(x), float(y) }; } FI constexpr XYval<float> asFloat() const { return { static_cast<float>(x), static_cast<float>(y) }; }
// Marlin workspace shifting is done with G92 and M206 // Marlin workspace shifting is done with G92 and M206
FI XYval<float> asLogical() const { XYval<float> o = asFloat(); toLogical(o); return o; } FI XYval<float> asLogical() const { XYval<float> o = asFloat(); toLogical(o); return o; }
@@ -699,8 +645,8 @@ struct XYval {
// Exact comparisons. For floats a "NEAR" operation may be better. // Exact comparisons. For floats a "NEAR" operation may be better.
FI bool operator==(const XYval<T> &rs) const { return x == rs.x && y == rs.y; } FI bool operator==(const XYval<T> &rs) const { return x == rs.x && y == rs.y; }
FI bool operator==(const XYZval<T> &rs) const { return XY_ALL(x == rs.x, y == rs.y); } FI bool operator==(const XYZval<T> &rs) const { return ENABLED(HAS_X_AXIS) XY_GANG(&& x == rs.x, && y == rs.y); }
FI bool operator==(const XYZEval<T> &rs) const { return XY_ALL(x == rs.x, y == rs.y); } FI bool operator==(const XYZEval<T> &rs) const { return ENABLED(HAS_X_AXIS) XY_GANG(&& x == rs.x, && y == rs.y); }
FI bool operator!=(const XYval<T> &rs) const { return !operator==(rs); } FI bool operator!=(const XYval<T> &rs) const { return !operator==(rs); }
FI bool operator!=(const XYZval<T> &rs) const { return !operator==(rs); } FI bool operator!=(const XYZval<T> &rs) const { return !operator==(rs); }
FI bool operator!=(const XYZEval<T> &rs) const { return !operator==(rs); } FI bool operator!=(const XYZEval<T> &rs) const { return !operator==(rs); }
@@ -714,15 +660,15 @@ struct XYval {
FI bool operator> (const XYval<T> &rs) const { return x > rs.x && y > rs.y; } FI bool operator> (const XYval<T> &rs) const { return x > rs.x && y > rs.y; }
FI bool operator>=(const XYval<T> &rs) const { return x >= rs.x && y >= rs.y; } FI bool operator>=(const XYval<T> &rs) const { return x >= rs.x && y >= rs.y; }
FI bool operator< (const XYZval<T> &rs) const { return XY_ALL(x < rs.x, y < rs.y); } FI bool operator< (const XYZval<T> &rs) const { return true XY_GANG(&& x < rs.x, && y < rs.y); }
FI bool operator<=(const XYZval<T> &rs) const { return XY_ALL(x <= rs.x, y <= rs.y); } FI bool operator<=(const XYZval<T> &rs) const { return true XY_GANG(&& x <= rs.x, && y <= rs.y); }
FI bool operator> (const XYZval<T> &rs) const { return XY_ALL(x > rs.x, y > rs.y); } FI bool operator> (const XYZval<T> &rs) const { return true XY_GANG(&& x > rs.x, && y > rs.y); }
FI bool operator>=(const XYZval<T> &rs) const { return XY_ALL(x >= rs.x, y >= rs.y); } FI bool operator>=(const XYZval<T> &rs) const { return true XY_GANG(&& x >= rs.x, && y >= rs.y); }
FI bool operator< (const XYZEval<T> &rs) const { return XY_ALL(x < rs.x, y < rs.y); } FI bool operator< (const XYZEval<T> &rs) const { return true XY_GANG(&& x < rs.x, && y < rs.y); }
FI bool operator<=(const XYZEval<T> &rs) const { return XY_ALL(x <= rs.x, y <= rs.y); } FI bool operator<=(const XYZEval<T> &rs) const { return true XY_GANG(&& x <= rs.x, && y <= rs.y); }
FI bool operator> (const XYZEval<T> &rs) const { return XY_ALL(x > rs.x, y > rs.y); } FI bool operator> (const XYZEval<T> &rs) const { return true XY_GANG(&& x > rs.x, && y > rs.y); }
FI bool operator>=(const XYZEval<T> &rs) const { return XY_ALL(x >= rs.x, y >= rs.y); } FI bool operator>=(const XYZEval<T> &rs) const { return true XY_GANG(&& x >= rs.x, && y >= rs.y); }
}; };
@@ -762,36 +708,36 @@ struct XYZval {
// Setters with fewer elements leave the rest untouched // Setters with fewer elements leave the rest untouched
#if HAS_Y_AXIS #if HAS_Y_AXIS
FI void set(const T px) { x = px; } FI void set(const T px) { x = px; }
#endif #endif
#if HAS_Z_AXIS #if HAS_Z_AXIS
FI void set(const T px, const T py) { set(px); y = py; } FI void set(const T px, const T py) { x = px; y = py; }
#endif #endif
#if HAS_I_AXIS #if HAS_I_AXIS
FI void set(const T px, const T py, const T pz) { set(px, py); z = pz; } FI void set(const T px, const T py, const T pz) { x = px; y = py; z = pz; }
#endif #endif
#if HAS_J_AXIS #if HAS_J_AXIS
FI void set(const T px, const T py, const T pz, const T pi) { set(px, py, pz); i = pi; } FI void set(const T px, const T py, const T pz, const T pi) { x = px; y = py; z = pz; i = pi; }
#endif #endif
#if HAS_K_AXIS #if HAS_K_AXIS
FI void set(const T px, const T py, const T pz, const T pi, const T pj) { set(px, py, pz, pi); j = pj; } FI void set(const T px, const T py, const T pz, const T pi, const T pj) { x = px; y = py; z = pz; i = pi; j = pj; }
#endif #endif
#if HAS_U_AXIS #if HAS_U_AXIS
FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk) { set(px, py, pz, pi, pj); k = pk; } FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; }
#endif #endif
#if HAS_V_AXIS #if HAS_V_AXIS
FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pu) { set(px, py, pz, pi, pj, pk); u = pu; } FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pu) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; u = pu; }
#endif #endif
#if HAS_W_AXIS #if HAS_W_AXIS
FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pu, const T pv) { set(px, py, pz, pi, pj, pk, pu); v = pv; } FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pu, const T pv) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; u = pu; v = pv; }
#endif #endif
// Length reduced to one dimension // Length reduced to one dimension
FI constexpr T magnitude() const { return (T)TERN(HAS_X_AXIS, SQRT(NUM_AXIS_GANG(x*x, + y*y, + z*z, + i*i, + j*j, + k*k, + u*u, + v*v, + w*w)), 0); } FI constexpr T magnitude() const { return (T)TERN(HAS_X_AXIS, sqrtf(NUM_AXIS_GANG(x*x, + y*y, + z*z, + i*i, + j*j, + k*k, + u*u, + v*v, + w*w)), 0); }
// Pointer to the data as a simple array // Pointer to the data as a simple array
explicit FI operator T* () { return pos; } explicit FI operator T* () { return pos; }
// If any element is true then it's true // If any element is true then it's true
FI constexpr operator bool() const { return NUM_AXIS_ANY(x, y, z, i, j, k, u, v, w); } FI constexpr operator bool() const { return 0 NUM_AXIS_GANG(|| x, || y, || z, || i, || j, || k, || u, || v, || w); }
// Smallest element // Smallest element
FI constexpr T small() const { return TERN0(HAS_X_AXIS, _MIN(NUM_AXIS_LIST(x, y, z, i, j, k, u, v, w))); } FI constexpr T small() const { return TERN0(HAS_X_AXIS, _MIN(NUM_AXIS_LIST(x, y, z, i, j, k, u, v, w))); }
// Largest element // Largest element
@@ -809,13 +755,13 @@ struct XYZval {
FI constexpr XYZval<uint32_t> asUInt32() const { return NUM_AXIS_ARRAY(uint32_t(x), uint32_t(y), uint32_t(z), uint32_t(i), uint32_t(j), uint32_t(k), uint32_t(u), uint32_t(v), uint32_t(w)); } FI constexpr XYZval<uint32_t> asUInt32() const { return NUM_AXIS_ARRAY(uint32_t(x), uint32_t(y), uint32_t(z), uint32_t(i), uint32_t(j), uint32_t(k), uint32_t(u), uint32_t(v), uint32_t(w)); }
FI constexpr XYZval<int64_t> asInt64() const { return NUM_AXIS_ARRAY(int64_t(x), int64_t(y), int64_t(z), int64_t(i), int64_t(j), int64_t(k), int64_t(u), int64_t(v), int64_t(w)); } FI constexpr XYZval<int64_t> asInt64() const { return NUM_AXIS_ARRAY(int64_t(x), int64_t(y), int64_t(z), int64_t(i), int64_t(j), int64_t(k), int64_t(u), int64_t(v), int64_t(w)); }
FI constexpr XYZval<uint64_t> asUInt64() const { return NUM_AXIS_ARRAY(uint64_t(x), uint64_t(y), uint64_t(z), uint64_t(i), uint64_t(j), uint64_t(k), uint64_t(u), uint64_t(v), uint64_t(w)); } FI constexpr XYZval<uint64_t> asUInt64() const { return NUM_AXIS_ARRAY(uint64_t(x), uint64_t(y), uint64_t(z), uint64_t(i), uint64_t(j), uint64_t(k), uint64_t(u), uint64_t(v), uint64_t(w)); }
FI constexpr XYZval<float> asFloat() const { return NUM_AXIS_ARRAY(float(x), float(y), float(z), float(i), float(j), float(k), float(u), float(v), float(w)); } FI constexpr XYZval<float> asFloat() const { return NUM_AXIS_ARRAY(static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(i), static_cast<float>(j), static_cast<float>(k), static_cast<float>(u), static_cast<float>(v), static_cast<float>(w)); }
// Marlin workspace shifting is done with G92 and M206 // Marlin workspace shifting is done with G92 and M206
FI XYZval<float> asLogical() const { XYZval<float> o = asFloat(); toLogical(o); return o; } FI XYZval<float> asLogical() const { XYZval<float> o = asFloat(); toLogical(o); return o; }
FI XYZval<float> asNative() const { XYZval<float> o = asFloat(); toNative(o); return o; } FI XYZval<float> asNative() const { XYZval<float> o = asFloat(); toNative(o); return o; }
// In-place reinterpret-cast to types having fewer fields // In-place cast to types having fewer fields
FI operator XYval<T>&() { return *(XYval<T>*)this; } FI operator XYval<T>&() { return *(XYval<T>*)this; }
FI operator const XYval<T>&() const { return *(const XYval<T>*)this; } FI operator const XYval<T>&() const { return *(const XYval<T>*)this; }
@@ -870,29 +816,29 @@ struct XYZval {
FI XYZval<T>& operator-=(const XYZEval<T> &rs) { NUM_AXIS_CODE(x -= rs.x, y -= rs.y, z -= rs.z, i -= rs.i, j -= rs.j, k -= rs.k, u -= rs.u, v -= rs.v, w -= rs.w); return *this; } FI XYZval<T>& operator-=(const XYZEval<T> &rs) { NUM_AXIS_CODE(x -= rs.x, y -= rs.y, z -= rs.z, i -= rs.i, j -= rs.j, k -= rs.k, u -= rs.u, v -= rs.v, w -= rs.w); return *this; }
FI XYZval<T>& operator*=(const XYZEval<T> &rs) { NUM_AXIS_CODE(x *= rs.x, y *= rs.y, z *= rs.z, i *= rs.i, j *= rs.j, k *= rs.k, u *= rs.u, v *= rs.v, w *= rs.w); return *this; } FI XYZval<T>& operator*=(const XYZEval<T> &rs) { NUM_AXIS_CODE(x *= rs.x, y *= rs.y, z *= rs.z, i *= rs.i, j *= rs.j, k *= rs.k, u *= rs.u, v *= rs.v, w *= rs.w); return *this; }
FI XYZval<T>& operator/=(const XYZEval<T> &rs) { NUM_AXIS_CODE(x /= rs.x, y /= rs.y, z /= rs.z, i /= rs.i, j /= rs.j, k /= rs.k, u /= rs.u, v /= rs.v, w /= rs.w); return *this; } FI XYZval<T>& operator/=(const XYZEval<T> &rs) { NUM_AXIS_CODE(x /= rs.x, y /= rs.y, z /= rs.z, i /= rs.i, j /= rs.j, k /= rs.k, u /= rs.u, v /= rs.v, w /= rs.w); return *this; }
FI XYZval<T>& operator*=(const float &p) { NUM_AXIS_CODE(x *= p, y *= p, z *= p, i *= p, j *= p, k *= p, u *= p, v *= p, w *= p); return *this; } FI XYZval<T>& operator*=(const float p) { NUM_AXIS_CODE(x *= p, y *= p, z *= p, i *= p, j *= p, k *= p, u *= p, v *= p, w *= p); return *this; }
FI XYZval<T>& operator*=(const int &p) { NUM_AXIS_CODE(x *= p, y *= p, z *= p, i *= p, j *= p, k *= p, u *= p, v *= p, w *= p); return *this; } FI XYZval<T>& operator*=(const int &p) { NUM_AXIS_CODE(x *= p, y *= p, z *= p, i *= p, j *= p, k *= p, u *= p, v *= p, w *= p); return *this; }
FI XYZval<T>& operator/=(const float &p) { NUM_AXIS_CODE(x /= p, y /= p, z /= p, i /= p, j /= p, k /= p, u /= p, v /= p, w /= p); return *this; } FI XYZval<T>& operator/=(const float p) { NUM_AXIS_CODE(x /= p, y /= p, z /= p, i /= p, j /= p, k /= p, u /= p, v /= p, w /= p); return *this; }
FI XYZval<T>& operator>>=(const int &p) { NUM_AXIS_CODE(_RSE(x), _RSE(y), _RSE(z), _RSE(i), _RSE(j), _RSE(k), _RSE(u), _RSE(v), _RSE(w)); return *this; } FI XYZval<T>& operator>>=(const int &p) { NUM_AXIS_CODE(_RSE(x), _RSE(y), _RSE(z), _RSE(i), _RSE(j), _RSE(k), _RSE(u), _RSE(v), _RSE(w)); return *this; }
FI XYZval<T>& operator<<=(const int &p) { NUM_AXIS_CODE(_LSE(x), _LSE(y), _LSE(z), _LSE(i), _LSE(j), _LSE(k), _LSE(u), _LSE(v), _LSE(w)); return *this; } FI XYZval<T>& operator<<=(const int &p) { NUM_AXIS_CODE(_LSE(x), _LSE(y), _LSE(z), _LSE(i), _LSE(j), _LSE(k), _LSE(u), _LSE(v), _LSE(w)); return *this; }
// Exact comparisons. For floats a "NEAR" operation may be better. // Exact comparisons. For floats a "NEAR" operation may be better.
FI bool operator==(const XYZEval<T> &rs) const { return NUM_AXIS_ALL(x == rs.x, y == rs.y, z == rs.z, i == rs.i, j == rs.j, k == rs.k, u == rs.u, v == rs.v, w == rs.w); } FI bool operator==(const XYZEval<T> &rs) const { return ENABLED(HAS_X_AXIS) NUM_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k, && u == rs.u, && v == rs.v, && w == rs.w); }
FI bool operator!=(const XYZEval<T> &rs) const { return !operator==(rs); } FI bool operator!=(const XYZEval<T> &rs) const { return !operator==(rs); }
// Exact comparison to a single value // Exact comparison to a single value
FI bool operator==(const T &p) const { return NUM_AXIS_ALL(x == p, y == p, z == p, i == p, j == p, k == p, u == p, v == p, w == p); } FI bool operator==(const T &p) const { return ENABLED(HAS_X_AXIS) NUM_AXIS_GANG(&& x == p, && y == p, && z == p, && i == p, && j == p, && k == p, && u == p, && v == p, && w == p); }
FI bool operator!=(const T &p) const { return !operator==(p); } FI bool operator!=(const T &p) const { return !operator==(p); }
FI bool operator< (const XYZval<T> &rs) const { return NUM_AXIS_ALL(x < rs.x, y < rs.y, z < rs.z, i < rs.i, j < rs.j, k < rs.k, u < rs.u, v < rs.v, w < rs.w); } FI bool operator< (const XYZval<T> &rs) const { return true NUM_AXIS_GANG(&& x < rs.x, && y < rs.y, && z < rs.z, && i < rs.i, && j < rs.j, && k < rs.k, && u < rs.u, && v < rs.v, && w < rs.w); }
FI bool operator<=(const XYZval<T> &rs) const { return NUM_AXIS_ALL(x <= rs.x, y <= rs.y, z <= rs.z, i <= rs.i, j <= rs.j, k <= rs.k, u <= rs.u, v <= rs.v, w <= rs.w); } FI bool operator<=(const XYZval<T> &rs) const { return true NUM_AXIS_GANG(&& x <= rs.x, && y <= rs.y, && z <= rs.z, && i <= rs.i, && j <= rs.j, && k <= rs.k, && u <= rs.u, && v <= rs.v, && w <= rs.w); }
FI bool operator> (const XYZval<T> &rs) const { return NUM_AXIS_ALL(x > rs.x, y > rs.y, z > rs.z, i > rs.i, j > rs.j, k > rs.k, u > rs.u, v > rs.v, w > rs.w); } FI bool operator> (const XYZval<T> &rs) const { return true NUM_AXIS_GANG(&& x > rs.x, && y > rs.y, && z > rs.z, && i > rs.i, && j > rs.j, && k > rs.k, && u > rs.u, && v > rs.v, && w > rs.w); }
FI bool operator>=(const XYZval<T> &rs) const { return NUM_AXIS_ALL(x >= rs.x, y >= rs.y, z >= rs.z, i >= rs.i, j >= rs.j, k >= rs.k, u >= rs.u, v >= rs.v, w >= rs.w); } FI bool operator>=(const XYZval<T> &rs) const { return true NUM_AXIS_GANG(&& x >= rs.x, && y >= rs.y, && z >= rs.z, && i >= rs.i, && j >= rs.j, && k >= rs.k, && u >= rs.u, && v >= rs.v, && w >= rs.w); }
FI bool operator< (const XYZEval<T> &rs) const { return NUM_AXIS_ALL(x < rs.x, y < rs.y, z < rs.z, i < rs.i, j < rs.j, k < rs.k, u < rs.u, v < rs.v, w < rs.w); } FI bool operator< (const XYZEval<T> &rs) const { return true NUM_AXIS_GANG(&& x < rs.x, && y < rs.y, && z < rs.z, && i < rs.i, && j < rs.j, && k < rs.k, && u < rs.u, && v < rs.v, && w < rs.w); }
FI bool operator<=(const XYZEval<T> &rs) const { return NUM_AXIS_ALL(x <= rs.x, y <= rs.y, z <= rs.z, i <= rs.i, j <= rs.j, k <= rs.k, u <= rs.u, v <= rs.v, w <= rs.w); } FI bool operator<=(const XYZEval<T> &rs) const { return true NUM_AXIS_GANG(&& x <= rs.x, && y <= rs.y, && z <= rs.z, && i <= rs.i, && j <= rs.j, && k <= rs.k, && u <= rs.u, && v <= rs.v, && w <= rs.w); }
FI bool operator> (const XYZEval<T> &rs) const { return NUM_AXIS_ALL(x > rs.x, y > rs.y, z > rs.z, i > rs.i, j > rs.j, k > rs.k, u > rs.u, v > rs.v, w > rs.w); } FI bool operator> (const XYZEval<T> &rs) const { return true NUM_AXIS_GANG(&& x > rs.x, && y > rs.y, && z > rs.z, && i > rs.i, && j > rs.j, && k > rs.k, && u > rs.u, && v > rs.v, && w > rs.w); }
FI bool operator>=(const XYZEval<T> &rs) const { return NUM_AXIS_ALL(x >= rs.x, y >= rs.y, z >= rs.z, i >= rs.i, j >= rs.j, k >= rs.k, u >= rs.u, v >= rs.v, w >= rs.w); } FI bool operator>=(const XYZEval<T> &rs) const { return true NUM_AXIS_GANG(&& x >= rs.x, && y >= rs.y, && z >= rs.z, && i >= rs.i, && j >= rs.j, && k >= rs.k, && u >= rs.u, && v >= rs.v, && w >= rs.w); }
}; };
@@ -911,7 +857,7 @@ struct XYZEval {
T pos[LOGICAL_AXES]; T pos[LOGICAL_AXES];
}; };
// Reset all to 0 // Reset all to 0
FI void reset() { LOGICAL_AXIS_GANG(e =, x =, y =, z =, i =, j =, k =, u =, v =, w =) 0; } FI void reset() { LOGICAL_AXIS_GANG(e =, x =, y =, z =, i =, j =, k =, u =, v =, w =) 0; }
// Setters taking struct types and arrays // Setters taking struct types and arrays
FI void set(const XYval<T> &pxy) { XY_CODE(x = pxy.x, y = pxy.y); } FI void set(const XYval<T> &pxy) { XY_CODE(x = pxy.x, y = pxy.y); }
@@ -936,33 +882,33 @@ struct XYZEval {
FI void set(const T px) { x = px; } FI void set(const T px) { x = px; }
#endif #endif
#if HAS_Z_AXIS #if HAS_Z_AXIS
FI void set(const T px, const T py) { set(px); y = py; } FI void set(const T px, const T py) { x = px; y = py; }
#endif #endif
#if HAS_I_AXIS #if HAS_I_AXIS
FI void set(const T px, const T py, const T pz) { set(px, py); z = pz; } FI void set(const T px, const T py, const T pz) { x = px; y = py; z = pz; }
#endif #endif
#if HAS_J_AXIS #if HAS_J_AXIS
FI void set(const T px, const T py, const T pz, const T pi) { set(px, py, pz); i = pi; } FI void set(const T px, const T py, const T pz, const T pi) { x = px; y = py; z = pz; i = pi; }
#endif #endif
#if HAS_K_AXIS #if HAS_K_AXIS
FI void set(const T px, const T py, const T pz, const T pi, const T pj) { set(px, py, pz, pi); j = pj; } FI void set(const T px, const T py, const T pz, const T pi, const T pj) { x = px; y = py; z = pz; i = pi; j = pj; }
#endif #endif
#if HAS_U_AXIS #if HAS_U_AXIS
FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk) { set(px, py, pz, pi, pj); k = pk; } FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; }
#endif #endif
#if HAS_V_AXIS #if HAS_V_AXIS
FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pu) { set(px, py, pz, pi, pj, pk); u = pu; } FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pu) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; u = pu; }
#endif #endif
#if HAS_W_AXIS #if HAS_W_AXIS
FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pu, const T pv) { set(px, py, pz, pi, pj, pk, pu); v = pv; } FI void set(const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pu, const T pv) { x = px; y = py; z = pz; i = pi; j = pj; k = pk; u = pu; v = pv; }
#endif #endif
// Length reduced to one dimension // Length reduced to one dimension
FI constexpr T magnitude() const { return (T)SQRT(LOGICAL_AXIS_GANG(+ e*e, + x*x, + y*y, + z*z, + i*i, + j*j, + k*k, + u*u, + v*v, + w*w)); } FI constexpr T magnitude() const { return (T)sqrtf(LOGICAL_AXIS_GANG(+ e*e, + x*x, + y*y, + z*z, + i*i, + j*j, + k*k, + u*u, + v*v, + w*w)); }
// Pointer to the data as a simple array // Pointer to the data as a simple array
explicit FI operator T* () { return pos; } explicit FI operator T* () { return pos; }
// If any element is true then it's true // If any element is true then it's true
FI constexpr operator bool() const { return LOGICAL_AXIS_ANY(e, x, y, z, i, j, k, u, v, w); } FI constexpr operator bool() const { return 0 LOGICAL_AXIS_GANG(|| e, || x, || y, || z, || i, || j, || k, || u, || v, || w); }
// Smallest element // Smallest element
FI constexpr T small() const { return _MIN(LOGICAL_AXIS_LIST(e, x, y, z, i, j, k, u, v, w)); } FI constexpr T small() const { return _MIN(LOGICAL_AXIS_LIST(e, x, y, z, i, j, k, u, v, w)); }
// Largest element // Largest element
@@ -980,13 +926,13 @@ struct XYZEval {
FI constexpr XYZEval<uint32_t> asUInt32() const { return LOGICAL_AXIS_ARRAY(uint32_t(e), uint32_t(x), uint32_t(y), uint32_t(z), uint32_t(i), uint32_t(j), uint32_t(k), uint32_t(u), uint32_t(v), uint32_t(w)); } FI constexpr XYZEval<uint32_t> asUInt32() const { return LOGICAL_AXIS_ARRAY(uint32_t(e), uint32_t(x), uint32_t(y), uint32_t(z), uint32_t(i), uint32_t(j), uint32_t(k), uint32_t(u), uint32_t(v), uint32_t(w)); }
FI constexpr XYZEval<int64_t> asInt64() const { return LOGICAL_AXIS_ARRAY(int64_t(e), int64_t(x), int64_t(y), int64_t(z), int64_t(i), int64_t(j), int64_t(k), int64_t(u), int64_t(v), int64_t(w)); } FI constexpr XYZEval<int64_t> asInt64() const { return LOGICAL_AXIS_ARRAY(int64_t(e), int64_t(x), int64_t(y), int64_t(z), int64_t(i), int64_t(j), int64_t(k), int64_t(u), int64_t(v), int64_t(w)); }
FI constexpr XYZEval<uint64_t> asUInt64() const { return LOGICAL_AXIS_ARRAY(uint64_t(e), uint64_t(x), uint64_t(y), uint64_t(z), uint64_t(i), uint64_t(j), uint64_t(k), uint64_t(u), uint64_t(v), uint64_t(w)); } FI constexpr XYZEval<uint64_t> asUInt64() const { return LOGICAL_AXIS_ARRAY(uint64_t(e), uint64_t(x), uint64_t(y), uint64_t(z), uint64_t(i), uint64_t(j), uint64_t(k), uint64_t(u), uint64_t(v), uint64_t(w)); }
FI constexpr XYZEval<float> asFloat() const { return LOGICAL_AXIS_ARRAY(float(e), float(x), float(y), float(z), float(i), float(j), float(k), float(u), float(v), float(w)); } FI constexpr XYZEval<float> asFloat() const { return LOGICAL_AXIS_ARRAY(static_cast<float>(e), static_cast<float>(x), static_cast<float>(y), static_cast<float>(z), static_cast<float>(i), static_cast<float>(j), static_cast<float>(k), static_cast<float>(u), static_cast<float>(v), static_cast<float>(w)); }
// Marlin workspace shifting is done with G92 and M206 // Marlin workspace shifting is done with G92 and M206
FI XYZEval<float> asLogical() const { XYZEval<float> o = asFloat(); toLogical(o); return o; } FI XYZEval<float> asLogical() const { XYZEval<float> o = asFloat(); toLogical(o); return o; }
FI XYZEval<float> asNative() const { XYZEval<float> o = asFloat(); toNative(o); return o; } FI XYZEval<float> asNative() const { XYZEval<float> o = asFloat(); toNative(o); return o; }
// In-place reinterpret-cast to types having fewer fields // In-place cast to types having fewer fields
FI operator XYval<T>&() { return *(XYval<T>*)this; } FI operator XYval<T>&() { return *(XYval<T>*)this; }
FI operator const XYval<T>&() const { return *(const XYval<T>*)this; } FI operator const XYval<T>&() const { return *(const XYval<T>*)this; }
FI operator XYZval<T>&() { return *(XYZval<T>*)this; } FI operator XYZval<T>&() { return *(XYZval<T>*)this; }
@@ -1051,24 +997,24 @@ struct XYZEval {
FI XYZEval<T>& operator<<=(const int &p) { LOGICAL_AXIS_CODE(_LSE(e), _LSE(x), _LSE(y), _LSE(z), _LSE(i), _LSE(j), _LSE(k), _LSE(u), _LSE(v), _LSE(w)); return *this; } FI XYZEval<T>& operator<<=(const int &p) { LOGICAL_AXIS_CODE(_LSE(e), _LSE(x), _LSE(y), _LSE(z), _LSE(i), _LSE(j), _LSE(k), _LSE(u), _LSE(v), _LSE(w)); return *this; }
// Exact comparisons. For floats a "NEAR" operation may be better. // Exact comparisons. For floats a "NEAR" operation may be better.
FI bool operator==(const XYZval<T> &rs) const { return NUM_AXIS_ALL(x == rs.x, y == rs.y, z == rs.z, i == rs.i, j == rs.j, k == rs.k, u == rs.u, v == rs.v, w == rs.w); } FI bool operator==(const XYZval<T> &rs) const { return ENABLED(HAS_X_AXIS) NUM_AXIS_GANG(&& x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k, && u == rs.u, && v == rs.v, && w == rs.w); }
FI bool operator==(const XYZEval<T> &rs) const { return LOGICAL_AXIS_ALL(e == rs.e, x == rs.x, y == rs.y, z == rs.z, i == rs.i, j == rs.j, k == rs.k, u == rs.u, v == rs.v, w == rs.w); } FI bool operator==(const XYZEval<T> &rs) const { return ANY(HAS_X_AXIS, HAS_EXTRUDERS) LOGICAL_AXIS_GANG(&& e == rs.e, && x == rs.x, && y == rs.y, && z == rs.z, && i == rs.i, && j == rs.j, && k == rs.k, && u == rs.u, && v == rs.v, && w == rs.w); }
FI bool operator!=(const XYZval<T> &rs) const { return !operator==(rs); } FI bool operator!=(const XYZval<T> &rs) const { return !operator==(rs); }
FI bool operator!=(const XYZEval<T> &rs) const { return !operator==(rs); } FI bool operator!=(const XYZEval<T> &rs) const { return !operator==(rs); }
// Exact comparison to a single value // Exact comparison to a single value
FI bool operator==(const T &p) const { return LOGICAL_AXIS_ALL(e == p, x == p, y == p, z == p, i == p, j == p, k == p, u == p, v == p, w == p); } FI bool operator==(const T &p) const { return ENABLED(HAS_X_AXIS) LOGICAL_AXIS_GANG(&& e == p, && x == p, && y == p, && z == p, && i == p, && j == p, && k == p, && u == p, && v == p, && w == p); }
FI bool operator!=(const T &p) const { return !operator==(p); } FI bool operator!=(const T &p) const { return !operator==(p); }
FI bool operator< (const XYZEval<T> &rs) const { return LOGICAL_AXIS_ALL(e < rs.e, x < rs.x, y < rs.y, z < rs.z, i < rs.i, j < rs.j, k < rs.k, u < rs.u, v < rs.v, w < rs.w); } FI bool operator< (const XYZEval<T> &rs) const { return true LOGICAL_AXIS_GANG(&& e < rs.e, && x < rs.x, && y < rs.y, && z < rs.z, && i < rs.i, && j < rs.j, && k < rs.k, && u < rs.u, && v < rs.v, && w < rs.w); }
FI bool operator<=(const XYZEval<T> &rs) const { return LOGICAL_AXIS_ALL(e <= rs.e, x <= rs.x, y <= rs.y, z <= rs.z, i <= rs.i, j <= rs.j, k <= rs.k, u <= rs.u, v <= rs.v, w <= rs.w); } FI bool operator<=(const XYZEval<T> &rs) const { return true LOGICAL_AXIS_GANG(&& e <= rs.e, && x <= rs.x, && y <= rs.y, && z <= rs.z, && i <= rs.i, && j <= rs.j, && k <= rs.k, && u <= rs.u, && v <= rs.v, && w <= rs.w); }
FI bool operator> (const XYZEval<T> &rs) const { return LOGICAL_AXIS_ALL(e > rs.e, x > rs.x, y > rs.y, z > rs.z, i > rs.i, j > rs.j, k > rs.k, u > rs.u, v > rs.v, w > rs.w); } FI bool operator> (const XYZEval<T> &rs) const { return true LOGICAL_AXIS_GANG(&& e > rs.e, && x > rs.x, && y > rs.y, && z > rs.z, && i > rs.i, && j > rs.j, && k > rs.k, && u > rs.u, && v > rs.v, && w > rs.w); }
FI bool operator>=(const XYZEval<T> &rs) const { return LOGICAL_AXIS_ALL(e >= rs.e, x >= rs.x, y >= rs.y, z >= rs.z, i >= rs.i, j >= rs.j, k >= rs.k, u >= rs.u, v >= rs.v, w >= rs.w); } FI bool operator>=(const XYZEval<T> &rs) const { return true LOGICAL_AXIS_GANG(&& e >= rs.e, && x >= rs.x, && y >= rs.y, && z >= rs.z, && i >= rs.i, && j >= rs.j, && k >= rs.k, && u >= rs.u, && v >= rs.v, && w >= rs.w); }
FI bool operator< (const XYZval<T> &rs) const { return NUM_AXIS_ALL(x < rs.x, y < rs.y, z < rs.z, i < rs.i, j < rs.j, k < rs.k, u < rs.u, v < rs.v, w < rs.w); } FI bool operator< (const XYZval<T> &rs) const { return true NUM_AXIS_GANG(&& x < rs.x, && y < rs.y, && z < rs.z, && i < rs.i, && j < rs.j, && k < rs.k, && u < rs.u, && v < rs.v, && w < rs.w); }
FI bool operator<=(const XYZval<T> &rs) const { return NUM_AXIS_ALL(x <= rs.x, y <= rs.y, z <= rs.z, i <= rs.i, j <= rs.j, k <= rs.k, u <= rs.u, v <= rs.v, w <= rs.w); } FI bool operator<=(const XYZval<T> &rs) const { return true NUM_AXIS_GANG(&& x <= rs.x, && y <= rs.y, && z <= rs.z, && i <= rs.i, && j <= rs.j, && k <= rs.k, && u <= rs.u, && v <= rs.v, && w <= rs.w); }
FI bool operator> (const XYZval<T> &rs) const { return NUM_AXIS_ALL(x > rs.x, y > rs.y, z > rs.z, i > rs.i, j > rs.j, k > rs.k, u > rs.u, v > rs.v, w > rs.w); } FI bool operator> (const XYZval<T> &rs) const { return true NUM_AXIS_GANG(&& x > rs.x, && y > rs.y, && z > rs.z, && i > rs.i, && j > rs.j, && k > rs.k, && u > rs.u, && v > rs.v, && w > rs.w); }
FI bool operator>=(const XYZval<T> &rs) const { return NUM_AXIS_ALL(x >= rs.x, y >= rs.y, z >= rs.z, i >= rs.i, j >= rs.j, k >= rs.k, u >= rs.u, v >= rs.v, w >= rs.w); } FI bool operator>=(const XYZval<T> &rs) const { return true NUM_AXIS_GANG(&& x >= rs.x, && y >= rs.y, && z >= rs.z, && i >= rs.i, && j >= rs.j, && k >= rs.k, && u >= rs.u, && v >= rs.v, && w >= rs.w); }
}; };
@@ -1098,28 +1044,28 @@ struct XYZarray {
// Setters with fewer elements leave the rest untouched // Setters with fewer elements leave the rest untouched
#if HAS_Y_AXIS #if HAS_Y_AXIS
FI void set(const int n, const T px) { x[n] = px; } FI void set(const int n, const T px) { x[n] = px; }
#endif #endif
#if HAS_Z_AXIS #if HAS_Z_AXIS
FI void set(const int n, const T px, const T py) { set(n, px); y[n] = py; } FI void set(const int n, const T px, const T py) { x[n] = px; y[n] = py; }
#endif #endif
#if HAS_I_AXIS #if HAS_I_AXIS
FI void set(const int n, const T px, const T py, const T pz) { set(n, px, py); z[n] = pz; } FI void set(const int n, const T px, const T py, const T pz) { x[n] = px; y[n] = py; z[n] = pz; }
#endif #endif
#if HAS_J_AXIS #if HAS_J_AXIS
FI void set(const int n, const T px, const T py, const T pz, const T pi) { set(n, px, py, pz); i[n] = pi; } FI void set(const int n, const T px, const T py, const T pz, const T pi) { x[n] = px; y[n] = py; z[n] = pz; i[n] = pi; }
#endif #endif
#if HAS_K_AXIS #if HAS_K_AXIS
FI void set(const int n, const T px, const T py, const T pz, const T pi, const T pj) { set(n, px, py, pz, pi); j[n] = pj; } FI void set(const int n, const T px, const T py, const T pz, const T pi, const T pj) { x[n] = px; y[n] = py; z[n] = pz; i[n] = pi; j[n] = pj; }
#endif #endif
#if HAS_U_AXIS #if HAS_U_AXIS
FI void set(const int n, const T px, const T py, const T pz, const T pi, const T pj, const T pk) { set(n, px, py, pz, pi, pj); k[n] = pk; } FI void set(const int n, const T px, const T py, const T pz, const T pi, const T pj, const T pk) { x[n] = px; y[n] = py; z[n] = pz; i[n] = pi; j[n] = pj; k[n] = pk; }
#endif #endif
#if HAS_V_AXIS #if HAS_V_AXIS
FI void set(const int n, const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pu) { set(n, px, py, pz, pi, pj, pk); u[n] = pu; } FI void set(const int n, const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pu) { x[n] = px; y[n] = py; z[n] = pz; i[n] = pi; j[n] = pj; k[n] = pk; u[n] = pu; }
#endif #endif
#if HAS_W_AXIS #if HAS_W_AXIS
FI void set(const int n, const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pu, const T pv) { set(n, px, py, pz, pi, pj, pk, pu); v[n] = pv; } FI void set(const int n, const T px, const T py, const T pz, const T pi, const T pj, const T pk, const T pu, const T pv) { x[n] = px; y[n] = py; z[n] = pz; i[n] = pi; j[n] = pj; k[n] = pk; u[n] = pu; v[n] = pv; }
#endif #endif
FI XYZval<T> operator[](const int n) const { return XYZval<T>(NUM_AXIS_ARRAY(x[n], y[n], z[n], i[n], j[n], k[n], u[n], v[n], w[n])); } FI XYZval<T> operator[](const int n) const { return XYZval<T>(NUM_AXIS_ARRAY(x[n], y[n], z[n], i[n], j[n], k[n], u[n], v[n], w[n])); }
@@ -1184,7 +1130,7 @@ public:
typedef bits_t(NUM_AXIS_HEADS) el; typedef bits_t(NUM_AXIS_HEADS) el;
union { union {
el bits; el bits;
// Axes x, y, z ... e0, e1, e2 ... rx, ry, rz // Axes x, y, z ... e0, e1, e2 ... hx, hy, hz
struct { struct {
#if NUM_AXES #if NUM_AXES
bool NUM_AXIS_LIST(x:1, y:1, z:1, i:1, j:1, k:1, u:1, v:1, w:1); bool NUM_AXIS_LIST(x:1, y:1, z:1, i:1, j:1, k:1, u:1, v:1, w:1);
@@ -1192,17 +1138,11 @@ public:
#define _EN_ITEM(N) bool e##N:1; #define _EN_ITEM(N) bool e##N:1;
REPEAT(EXTRUDERS,_EN_ITEM) REPEAT(EXTRUDERS,_EN_ITEM)
#undef _EN_ITEM #undef _EN_ITEM
#if HAS_REAL_X #if ANY(IS_CORE, MARKFORGED_XY, MARKFORGED_YX)
bool rx:1; bool hx:1, hy:1, hz:1;
#endif
#if HAS_REAL_Y
bool ry:1;
#endif
#if HAS_REAL_Z
bool rz:1;
#endif #endif
}; };
// Axes X, Y, Z ... E0, E1, E2 ... RX, RY, RZ // Axes X, Y, Z ... E0, E1, E2 ... HX, HY, HZ
struct { struct {
#if NUM_AXES #if NUM_AXES
bool NUM_AXIS_LIST(X:1, Y:1, Z:1, I:1, J:1, K:1, U:1, V:1, W:1); bool NUM_AXIS_LIST(X:1, Y:1, Z:1, I:1, J:1, K:1, U:1, V:1, W:1);
@@ -1210,17 +1150,11 @@ public:
#define _EN_ITEM(N) bool E##N:1; #define _EN_ITEM(N) bool E##N:1;
REPEAT(EXTRUDERS,_EN_ITEM) REPEAT(EXTRUDERS,_EN_ITEM)
#undef _EN_ITEM #undef _EN_ITEM
#if HAS_REAL_X #if ANY(IS_CORE, MARKFORGED_XY, MARKFORGED_YX)
bool RX:1; bool HX:1, HY:1, HZ:1;
#endif
#if HAS_REAL_Y
bool RY:1;
#endif
#if HAS_REAL_Z
bool RZ:1;
#endif #endif
}; };
// a, b, c, e ... ra, rb, rc // a, b, c, e ... ha, hb, hc
struct { struct {
bool LOGICAL_AXIS_LIST(e:1, a:1, b:1, c:1, ii:1, jj:1, kk:1, uu:1, vv:1, ww:1); bool LOGICAL_AXIS_LIST(e:1, a:1, b:1, c:1, ii:1, jj:1, kk:1, uu:1, vv:1, ww:1);
#if EXTRUDERS > 1 #if EXTRUDERS > 1
@@ -1228,17 +1162,11 @@ public:
REPEAT_S(1,EXTRUDERS,_EN_ITEM) REPEAT_S(1,EXTRUDERS,_EN_ITEM)
#undef _EN_ITEM #undef _EN_ITEM
#endif #endif
#if HAS_REAL_X #if ANY(IS_CORE, MARKFORGED_XY, MARKFORGED_YX)
bool ra:1; bool ha:1, hb:1, hc:1;
#endif
#if HAS_REAL_Y
bool rb:1;
#endif
#if HAS_REAL_Z
bool rc:1;
#endif #endif
}; };
// A, B, C, E ... RA, RB, RC // A, B, C, E ... HA, HB, HC
struct { struct {
bool LOGICAL_AXIS_LIST(E:1, A:1, B:1, C:1, II:1, JJ:1, KK:1, UU:1, VV:1, WW:1); bool LOGICAL_AXIS_LIST(E:1, A:1, B:1, C:1, II:1, JJ:1, KK:1, UU:1, VV:1, WW:1);
#if EXTRUDERS > 1 #if EXTRUDERS > 1
@@ -1246,14 +1174,8 @@ public:
REPEAT_S(1,EXTRUDERS,_EN_ITEM) REPEAT_S(1,EXTRUDERS,_EN_ITEM)
#undef _EN_ITEM #undef _EN_ITEM
#endif #endif
#if HAS_REAL_X #if ANY(IS_CORE, MARKFORGED_XY, MARKFORGED_YX)
bool RA:1; bool HA:1, HB:1, HC:1;
#endif
#if HAS_REAL_Y
bool RB:1;
#endif
#if HAS_REAL_Z
bool RC:1;
#endif #endif
}; };
}; };
+5 -5
View File
@@ -133,7 +133,7 @@
SERIAL_ECHOPGM("ABL Adjustment"); SERIAL_ECHOPGM("ABL Adjustment");
LOOP_NUM_AXES(a) { LOOP_NUM_AXES(a) {
SERIAL_ECHOPGM_P((PGM_P)pgm_read_ptr(&SP_AXIS_STR[a])); SERIAL_ECHOPGM_P((PGM_P)pgm_read_ptr(&SP_AXIS_STR[a]));
serial_offset(planner.get_axis_position_mm((AxisEnum)a) - motion.position[a]); serial_offset(planner.get_axis_position_mm((AxisEnum)a) - current_position[a]);
} }
#else #else
#if ENABLED(AUTO_BED_LEVELING_UBL) #if ENABLED(AUTO_BED_LEVELING_UBL)
@@ -141,11 +141,11 @@
#elif ENABLED(AUTO_BED_LEVELING_BILINEAR) #elif ENABLED(AUTO_BED_LEVELING_BILINEAR)
SERIAL_ECHOPGM("ABL Adjustment Z"); SERIAL_ECHOPGM("ABL Adjustment Z");
#endif #endif
const float rz = bedlevel.get_z_correction(motion.position); const float rz = bedlevel.get_z_correction(current_position);
SERIAL_ECHO(ftostr43sign(rz, '+')); SERIAL_ECHO(ftostr43sign(rz, '+'));
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT) #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
if (planner.z_fade_height) if (planner.z_fade_height)
SERIAL_ECHO(F(" ("), ftostr43sign(rz * planner.fade_scaling_factor_for_z(motion.position.z), '+'), C(')')); SERIAL_ECHO(F(" ("), ftostr43sign(rz * planner.fade_scaling_factor_for_z(current_position.z), '+'), C(')'));
#endif #endif
#endif #endif
} }
@@ -160,11 +160,11 @@
if (planner.leveling_active) { if (planner.leveling_active) {
SERIAL_ECHOLNPGM(" (enabled)"); SERIAL_ECHOLNPGM(" (enabled)");
const float z_offset = bedlevel.get_z_offset(), const float z_offset = bedlevel.get_z_offset(),
z_correction = bedlevel.get_z_correction(motion.position); z_correction = bedlevel.get_z_correction(current_position);
SERIAL_ECHOPGM("MBL Adjustment Z", ftostr43sign(z_offset + z_correction, '+')); SERIAL_ECHOPGM("MBL Adjustment Z", ftostr43sign(z_offset + z_correction, '+'));
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT) #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
if (planner.z_fade_height) { if (planner.z_fade_height) {
SERIAL_ECHO(F(" ("), ftostr43sign(z_offset + z_correction * planner.fade_scaling_factor_for_z(motion.position.z), '+'), C(')')); SERIAL_ECHO(F(" ("), ftostr43sign(z_offset + z_correction * planner.fade_scaling_factor_for_z(current_position.z), '+'), C(')'));
} }
#endif #endif
} }
+2 -2
View File
@@ -59,7 +59,7 @@ void Babystep::add_mm(const AxisEnum axis, const float mm) {
#if ENABLED(BD_SENSOR) #if ENABLED(BD_SENSOR)
void Babystep::set_mm(const AxisEnum axis, const float mm) { void Babystep::set_mm(const AxisEnum axis, const float mm) {
//if (DISABLED(BABYSTEP_WITHOUT_HOMING) && motion.axis_should_home(axis)) return; //if (DISABLED(BABYSTEP_WITHOUT_HOMING) && axis_should_home(axis)) return;
const int16_t distance = mm * planner.settings.axis_steps_per_mm[axis]; const int16_t distance = mm * planner.settings.axis_steps_per_mm[axis];
accum = distance; // Count up babysteps for the UI accum = distance; // Count up babysteps for the UI
steps[BS_AXIS_IND(axis)] = distance; steps[BS_AXIS_IND(axis)] = distance;
@@ -70,7 +70,7 @@ void Babystep::add_mm(const AxisEnum axis, const float mm) {
#endif #endif
bool Babystep::can_babystep(const AxisEnum axis) { bool Babystep::can_babystep(const AxisEnum axis) {
return (ENABLED(BABYSTEP_WITHOUT_HOMING) || !motion.axis_should_home(axis)); return (ENABLED(BABYSTEP_WITHOUT_HOMING) || !axis_should_home(axis));
} }
void Babystep::add_steps(const AxisEnum axis, const int16_t distance) { void Babystep::add_steps(const AxisEnum axis, const int16_t distance) {
+8 -8
View File
@@ -29,7 +29,7 @@
#include "../module/motion.h" #include "../module/motion.h"
#include "../module/planner.h" #include "../module/planner.h"
AxisBits Backlash::last_direction; AxisBits Backlash::last_direction_bits;
xyz_long_t Backlash::residual_error{0}; xyz_long_t Backlash::residual_error{0};
#ifdef BACKLASH_DISTANCE_MM #ifdef BACKLASH_DISTANCE_MM
@@ -64,7 +64,7 @@ Backlash backlash;
*/ */
void Backlash::add_correction_steps(const xyze_long_t &dist, const AxisBits dm, block_t * const block) { void Backlash::add_correction_steps(const xyze_long_t &dist, const AxisBits dm, block_t * const block) {
AxisBits changed_dir = last_direction ^ dm; AxisBits changed_dir = last_direction_bits ^ dm;
// Ignore direction change unless steps are taken in that direction // Ignore direction change unless steps are taken in that direction
#if DISABLED(CORE_BACKLASH) || ANY(MARKFORGED_XY, MARKFORGED_YX) #if DISABLED(CORE_BACKLASH) || ANY(MARKFORGED_XY, MARKFORGED_YX)
if (!dist.a) changed_dir.x = false; if (!dist.a) changed_dir.x = false;
@@ -83,7 +83,7 @@ void Backlash::add_correction_steps(const xyze_long_t &dist, const AxisBits dm,
if (!(dist.b - dist.c)) changed_dir.z = false; if (!(dist.b - dist.c)) changed_dir.z = false;
if (!dist.a) changed_dir.x = false; if (!dist.a) changed_dir.x = false;
#endif #endif
last_direction ^= changed_dir; last_direction_bits ^= changed_dir;
if (!correction && !residual_error) return; if (!correction && !residual_error) return;
@@ -167,7 +167,7 @@ void Backlash::add_correction_steps(const xyze_long_t &dist, const AxisBits dm,
int32_t Backlash::get_applied_steps(const AxisEnum axis) { int32_t Backlash::get_applied_steps(const AxisEnum axis) {
if (axis >= NUM_AXES) return 0; if (axis >= NUM_AXES) return 0;
const bool forward = last_direction[axis]; const bool forward = last_direction_bits[axis];
const int32_t residual_error_axis = residual_error[axis]; const int32_t residual_error_axis = residual_error[axis];
@@ -224,12 +224,12 @@ class Backlash::StepAdjuster {
void Backlash::measure_with_probe() { void Backlash::measure_with_probe() {
if (measured_count.z == 255) return; if (measured_count.z == 255) return;
const float start_height = motion.position.z; const float start_height = current_position.z;
while (motion.position.z < (start_height + BACKLASH_MEASUREMENT_LIMIT) && PROBE_TRIGGERED()) while (current_position.z < (start_height + BACKLASH_MEASUREMENT_LIMIT) && PROBE_TRIGGERED())
motion.blocking_move_z(motion.position.z + BACKLASH_MEASUREMENT_RESOLUTION, MMM_TO_MMS(BACKLASH_MEASUREMENT_FEEDRATE)); do_blocking_move_to_z(current_position.z + BACKLASH_MEASUREMENT_RESOLUTION, MMM_TO_MMS(BACKLASH_MEASUREMENT_FEEDRATE));
// The backlash from all probe points is averaged, so count the number of measurements // The backlash from all probe points is averaged, so count the number of measurements
measured_mm.z += motion.position.z - start_height; measured_mm.z += current_position.z - start_height;
measured_count.z++; measured_count.z++;
} }
+1 -1
View File
@@ -29,7 +29,7 @@ public:
static constexpr uint8_t all_on = 0xFF, all_off = 0x00; static constexpr uint8_t all_on = 0xFF, all_off = 0x00;
private: private:
static AxisBits last_direction; static AxisBits last_direction_bits;
static xyz_long_t residual_error; static xyz_long_t residual_error;
#if ENABLED(BACKLASH_GCODE) #if ENABLED(BACKLASH_GCODE)
+24 -32
View File
@@ -37,12 +37,12 @@
LevelingBilinear bedlevel; LevelingBilinear bedlevel;
xy_pos_t LevelingBilinear::grid_spacing,
LevelingBilinear::grid_start;
xy_float_t LevelingBilinear::grid_factor; xy_float_t LevelingBilinear::grid_factor;
xy_pos_t LevelingBilinear::grid_spacing,
LevelingBilinear::grid_start,
LevelingBilinear::cached_rel;
xy_int8_t LevelingBilinear::cached_g;
bed_mesh_t LevelingBilinear::z_values; bed_mesh_t LevelingBilinear::z_values;
xy_pos_t LevelingBilinear::cached_rel;
xy_int8_t LevelingBilinear::cached_g;
/** /**
* Extrapolate a single point from its neighbors * Extrapolate a single point from its neighbors
@@ -106,17 +106,9 @@ void LevelingBilinear::reset() {
} }
} }
/**
* Set grid spacing and start position
*/
void LevelingBilinear::set_grid(const xy_pos_t& _grid_spacing, const xy_pos_t& _grid_start) { void LevelingBilinear::set_grid(const xy_pos_t& _grid_spacing, const xy_pos_t& _grid_start) {
#if HAS_PROUI_MESH_EDIT grid_spacing = _grid_spacing;
grid_spacing.set(MESH_X_DIST, MESH_Y_DIST); grid_start = _grid_start;
grid_start = mesh_min;
#else
grid_spacing = _grid_spacing;
grid_start = _grid_start;
#endif
grid_factor = grid_spacing.reciprocal(); grid_factor = grid_spacing.reciprocal();
} }
@@ -379,8 +371,8 @@ float LevelingBilinear::get_z_correction(const xy_pos_t &raw) {
*/ */
void LevelingBilinear::line_to_destination(const feedRate_t scaled_fr_mm_s, uint16_t x_splits, uint16_t y_splits) { void LevelingBilinear::line_to_destination(const feedRate_t scaled_fr_mm_s, uint16_t x_splits, uint16_t y_splits) {
// Get current and destination cells for this line // Get current and destination cells for this line
xy_int_t c1 { CELL_INDEX(x, motion.position.x), CELL_INDEX(y, motion.position.y) }, xy_int_t c1 { CELL_INDEX(x, current_position.x), CELL_INDEX(y, current_position.y) },
c2 { CELL_INDEX(x, motion.destination.x), CELL_INDEX(y, motion.destination.y) }; c2 { CELL_INDEX(x, destination.x), CELL_INDEX(y, destination.y) };
LIMIT(c1.x, 0, ABL_BG_POINTS_X - 2); LIMIT(c1.x, 0, ABL_BG_POINTS_X - 2);
LIMIT(c1.y, 0, ABL_BG_POINTS_Y - 2); LIMIT(c1.y, 0, ABL_BG_POINTS_Y - 2);
LIMIT(c2.x, 0, ABL_BG_POINTS_X - 2); LIMIT(c2.x, 0, ABL_BG_POINTS_X - 2);
@@ -388,12 +380,12 @@ float LevelingBilinear::get_z_correction(const xy_pos_t &raw) {
// Start and end in the same cell? No split needed. // Start and end in the same cell? No split needed.
if (c1 == c2) { if (c1 == c2) {
motion.position = motion.destination; current_position = destination;
motion.goto_current_position(scaled_fr_mm_s); line_to_current_position(scaled_fr_mm_s);
return; return;
} }
#define LINE_SEGMENT_END(A) (motion.position.A + (motion.destination.A - motion.position.A) * normalized_dist) #define LINE_SEGMENT_END(A) (current_position.A + (destination.A - current_position.A) * normalized_dist)
float normalized_dist; float normalized_dist;
xyze_pos_t end; xyze_pos_t end;
@@ -404,36 +396,36 @@ float LevelingBilinear::get_z_correction(const xy_pos_t &raw) {
if (c2.x != c1.x && TEST(x_splits, gc.x)) { if (c2.x != c1.x && TEST(x_splits, gc.x)) {
// Split on the X grid line // Split on the X grid line
CBI(x_splits, gc.x); CBI(x_splits, gc.x);
end = motion.destination; end = destination;
motion.destination.x = grid_start.x + ABL_BG_SPACING(x) * gc.x; destination.x = grid_start.x + ABL_BG_SPACING(x) * gc.x;
normalized_dist = (motion.destination.x - motion.position.x) / (end.x - motion.position.x); normalized_dist = (destination.x - current_position.x) / (end.x - current_position.x);
motion.destination.y = LINE_SEGMENT_END(y); destination.y = LINE_SEGMENT_END(y);
} }
// Crosses on the Y and not already split on this Y? // Crosses on the Y and not already split on this Y?
else if (c2.y != c1.y && TEST(y_splits, gc.y)) { else if (c2.y != c1.y && TEST(y_splits, gc.y)) {
// Split on the Y grid line // Split on the Y grid line
CBI(y_splits, gc.y); CBI(y_splits, gc.y);
end = motion.destination; end = destination;
motion.destination.y = grid_start.y + ABL_BG_SPACING(y) * gc.y; destination.y = grid_start.y + ABL_BG_SPACING(y) * gc.y;
normalized_dist = (motion.destination.y - motion.position.y) / (end.y - motion.position.y); normalized_dist = (destination.y - current_position.y) / (end.y - current_position.y);
motion.destination.x = LINE_SEGMENT_END(x); destination.x = LINE_SEGMENT_END(x);
} }
else { else {
// Must already have been split on these border(s) // Must already have been split on these border(s)
// This should be a rare case. // This should be a rare case.
motion.position = motion.destination; current_position = destination;
motion.goto_current_position(scaled_fr_mm_s); line_to_current_position(scaled_fr_mm_s);
return; return;
} }
motion.destination.z = LINE_SEGMENT_END(z); destination.z = LINE_SEGMENT_END(z);
motion.destination.e = LINE_SEGMENT_END(e); destination.e = LINE_SEGMENT_END(e);
// Do the split and look for more borders // Do the split and look for more borders
line_to_destination(scaled_fr_mm_s, x_splits, y_splits); line_to_destination(scaled_fr_mm_s, x_splits, y_splits);
// Restore destination from stack // Restore destination from stack
motion.destination = end; destination = end;
line_to_destination(scaled_fr_mm_s, x_splits, y_splits); line_to_destination(scaled_fr_mm_s, x_splits, y_splits);
} }
+14 -14
View File
@@ -72,8 +72,8 @@ void BDS_Leveling::init(uint8_t _sda, uint8_t _scl, uint16_t delay_s) {
config_state = BDS_IDLE; config_state = BDS_IDLE;
const int ret = BD_I2C_SENSOR.i2c_init(_sda, _scl, BD_SENSOR_I2C_ADDR, delay_s); const int ret = BD_I2C_SENSOR.i2c_init(_sda, _scl, BD_SENSOR_I2C_ADDR, delay_s);
if (ret != 1) SERIAL_ECHOLNPGM("BD Sensor Init Fail (", ret, ")"); if (ret != 1) SERIAL_ECHOLNPGM("BD Sensor Init Fail (", ret, ")");
motion.sync_plan_position(); sync_plan_position();
pos_zero_offset = planner.get_axis_position_mm(Z_AXIS) - motion.position.z; pos_zero_offset = planner.get_axis_position_mm(Z_AXIS) - current_position.z;
SERIAL_ECHOLNPGM("BD Sensor Zero Offset:", pos_zero_offset); SERIAL_ECHOLNPGM("BD Sensor Zero Offset:", pos_zero_offset);
} }
@@ -119,7 +119,7 @@ void BDS_Leveling::process() {
uint16_t tmp = 0; uint16_t tmp = 0;
const float cur_z = planner.get_axis_position_mm(Z_AXIS) - pos_zero_offset; const float cur_z = planner.get_axis_position_mm(Z_AXIS) - pos_zero_offset;
static float old_cur_z = cur_z, old_buf_z = motion.position.z; static float old_cur_z = cur_z, old_buf_z = current_position.z;
tmp = BD_I2C_SENSOR.BD_i2c_read(); tmp = BD_I2C_SENSOR.BD_i2c_read();
if (BD_I2C_SENSOR.BD_Check_OddEven(tmp) && good_data(tmp)) { if (BD_I2C_SENSOR.BD_Check_OddEven(tmp) && good_data(tmp)) {
const float z_sensor = interpret(tmp); const float z_sensor = interpret(tmp);
@@ -127,11 +127,11 @@ void BDS_Leveling::process() {
if (config_state > 0) { if (config_state > 0) {
if (cur_z < config_state * 0.1f if (cur_z < config_state * 0.1f
&& old_cur_z == cur_z && old_cur_z == cur_z
&& old_buf_z == motion.position.z && old_buf_z == current_position.z
&& z_sensor < (MAX_BD_HEIGHT) - 0.1f && z_sensor < (MAX_BD_HEIGHT) - 0.1f
) { ) {
babystep.set_mm(Z_AXIS, cur_z - z_sensor); babystep.set_mm(Z_AXIS, cur_z - z_sensor);
DEBUG_ECHOLNPGM("BD:", z_sensor, ", Z:", cur_z, "|", motion.position.z); DEBUG_ECHOLNPGM("BD:", z_sensor, ", Z:", cur_z, "|", current_position.z);
} }
else else
babystep.set_mm(Z_AXIS, 0); babystep.set_mm(Z_AXIS, 0);
@@ -139,7 +139,7 @@ void BDS_Leveling::process() {
#endif #endif
old_cur_z = cur_z; old_cur_z = cur_z;
old_buf_z = motion.position.z; old_buf_z = current_position.z;
endstops.bdp_state_update(z_sensor <= BD_SENSOR_HOME_Z_POSITION); endstops.bdp_state_update(z_sensor <= BD_SENSOR_HOME_Z_POSITION);
#if HAS_STATUS_MESSAGE #if HAS_STATUS_MESSAGE
@@ -158,7 +158,7 @@ void BDS_Leveling::process() {
marlin.kill(F("BDsensor connect Err!")); marlin.kill(F("BDsensor connect Err!"));
} }
DEBUG_ECHOLNPGM("BD:", tmp & 0x3FF, " Z:", cur_z, "|", motion.position.z); DEBUG_ECHOLNPGM("BD:", tmp & 0x3FF, " Z:", cur_z, "|", current_position.z);
if (TERN0(DEBUG_OUT_BD, BD_I2C_SENSOR.BD_Check_OddEven(tmp) == 0)) DEBUG_ECHOLNPGM("CRC error"); if (TERN0(DEBUG_OUT_BD, BD_I2C_SENSOR.BD_Check_OddEven(tmp) == 0)) DEBUG_ECHOLNPGM("CRC error");
if (!good_data(tmp)) { if (!good_data(tmp)) {
@@ -204,15 +204,15 @@ void BDS_Leveling::process() {
SERIAL_ECHOLNPGM("c_z0:", planner.get_axis_position_mm(Z_AXIS), "-", pos_zero_offset); SERIAL_ECHOLNPGM("c_z0:", planner.get_axis_position_mm(Z_AXIS), "-", pos_zero_offset);
// Move the z axis instead of enabling the Z axis with M17 // Move the z axis instead of enabling the Z axis with M17
// TODO: Use motion.blocking_move_z for synchronized move. // TODO: Use do_blocking_move_to_z for synchronized move.
motion.position.z = 0; current_position.z = 0;
motion.sync_plan_position(); sync_plan_position();
gcode.process_subcommands_now(F("G1Z0.05")); gcode.process_subcommands_now(F("G1Z0.05"));
safe_delay(300); safe_delay(300);
gcode.process_subcommands_now(F("G1Z0.00")); gcode.process_subcommands_now(F("G1Z0.00"));
safe_delay(300); safe_delay(300);
motion.position.z = 0; current_position.z = 0;
motion.sync_plan_position(); sync_plan_position();
//safe_delay(1000); //safe_delay(1000);
while ((planner.get_axis_position_mm(Z_AXIS) - pos_zero_offset) > 0.00001f) { while ((planner.get_axis_position_mm(Z_AXIS) - pos_zero_offset) > 0.00001f) {
@@ -235,10 +235,10 @@ void BDS_Leveling::process() {
} }
else { else {
char tmp_1[32]; char tmp_1[32];
// TODO: Use motion.prepare_internal_move_to_destination to guarantee machine space // TODO: Use prepare_internal_move_to_destination to guarantee machine space
sprintf_P(tmp_1, PSTR("G1Z%d.%d"), int(zpos), int(zpos * 10) % 10); sprintf_P(tmp_1, PSTR("G1Z%d.%d"), int(zpos), int(zpos * 10) % 10);
gcode.process_subcommands_now(tmp_1); gcode.process_subcommands_now(tmp_1);
SERIAL_ECHO(tmp_1); SERIAL_ECHOLNPGM(", Z:", motion.position.z); SERIAL_ECHO(tmp_1); SERIAL_ECHOLNPGM(", Z:", current_position.z);
uint16_t failcount = 300; uint16_t failcount = 300;
for (float tmp_k = 0; abs(zpos - tmp_k) > 0.006f && failcount--;) { for (float tmp_k = 0; abs(zpos - tmp_k) > 0.006f && failcount--;) {
tmp_k = planner.get_axis_position_mm(Z_AXIS) - pos_zero_offset; tmp_k = planner.get_axis_position_mm(Z_AXIS) - pos_zero_offset;
+18 -28
View File
@@ -46,18 +46,8 @@
#include "../../lcd/extui/ui_api.h" #include "../../lcd/extui/ui_api.h"
#endif #endif
#if ALL(HAS_MESH, DWIN_LCD_PROUI)
#include "../../lcd/dwin/proui/bedlevel_tools.h"
#endif
bool leveling_is_valid() { bool leveling_is_valid() {
return ( return TERN1(HAS_MESH, bedlevel.mesh_is_valid());
#if ALL(HAS_MESH, DWIN_LCD_PROUI)
bedLevelTools.meshValidate()
#else
TERN1(HAS_MESH, bedlevel.mesh_is_valid())
#endif
);
} }
/** /**
@@ -76,9 +66,9 @@ void set_bed_leveling_enabled(const bool enable/*=true*/) {
auto _report_leveling = []{ auto _report_leveling = []{
if (DEBUGGING(LEVELING)) { if (DEBUGGING(LEVELING)) {
if (planner.leveling_active) if (planner.leveling_active)
DEBUG_POS("Leveling ON", motion.position); DEBUG_POS("Leveling ON", current_position);
else else
DEBUG_POS("Leveling OFF", motion.position); DEBUG_POS("Leveling OFF", current_position);
} }
}; };
@@ -86,11 +76,11 @@ void set_bed_leveling_enabled(const bool enable/*=true*/) {
planner.synchronize(); planner.synchronize();
// Get the corrected leveled / unleveled position // Get the corrected leveled / unleveled position
planner.apply_modifiers(motion.position, true); // Physical position with all modifiers planner.apply_modifiers(current_position, true); // Physical position with all modifiers
FLIP(planner.leveling_active); // Toggle leveling between apply and unapply FLIP(planner.leveling_active); // Toggle leveling between apply and unapply
planner.unapply_modifiers(motion.position, true); // Logical position with modifiers removed planner.unapply_modifiers(current_position, true); // Logical position with modifiers removed
motion.sync_plan_position(); sync_plan_position();
_report_leveling(); _report_leveling();
} }
} }
@@ -111,10 +101,10 @@ TemporaryBedLevelingState::TemporaryBedLevelingState(const bool enable) : saved(
planner.set_z_fade_height(zfh); planner.set_z_fade_height(zfh);
if (leveling_was_active) { if (leveling_was_active) {
const xyz_pos_t oldpos = motion.position; const xyz_pos_t oldpos = current_position;
set_bed_leveling_enabled(true); set_bed_leveling_enabled(true);
if (do_report && oldpos != motion.position) if (do_report && oldpos != current_position)
motion.report_position(); report_current_position();
} }
} }
@@ -208,16 +198,16 @@ void reset_bed_level() {
#else #else
#warning "It's recommended to set some MANUAL_PROBE_START_Z value for manual leveling." #warning "It's recommended to set some MANUAL_PROBE_START_Z value for manual leveling."
#endif #endif
#if Z_CLEARANCE_BETWEEN_MANUAL_PROBES > 0 // A probe/obstacle clearance exists so there is a raise: #if Z_CLEARANCE_BETWEEN_MANUAL_PROBES > 0 // A probe/obstacle clearance exists so there is a raise:
#ifndef MANUAL_PROBE_START_Z #ifndef MANUAL_PROBE_START_Z
const float finalz = motion.position.z; // - Use the current Z for starting-Z if no MANUAL_PROBE_START_Z was provided const float finalz = current_position.z; // - Use the current Z for starting-Z if no MANUAL_PROBE_START_Z was provided
#endif #endif
motion.blocking_move_xy_z(pos, Z_CLEARANCE_BETWEEN_MANUAL_PROBES); // - Raise Z, then move to the new XY do_blocking_move_to_xy_z(pos, Z_CLEARANCE_BETWEEN_MANUAL_PROBES); // - Raise Z, then move to the new XY
motion.blocking_move_z(finalz); // - Lower down to the starting Z height, ready for adjustment! do_blocking_move_to_z(finalz); // - Lower down to the starting Z height, ready for adjustment!
#elif defined(MANUAL_PROBE_START_Z) // A starting-Z was provided, but there's no raise: #elif defined(MANUAL_PROBE_START_Z) // A starting-Z was provided, but there's no raise:
motion.blocking_move_xy_z(pos, finalz); // - Move in XY then down to the starting Z height, ready for adjustment! do_blocking_move_to_xy_z(pos, finalz); // - Move in XY then down to the starting Z height, ready for adjustment!
#else // Zero raise and no starting Z height either: #else // Zero raise and no starting Z height either:
motion.blocking_move_xy(pos); // - Move over with no raise, ready for adjustment! do_blocking_move_to_xy(pos); // - Move over with no raise, ready for adjustment!
#endif #endif
TERN_(LCD_BED_LEVELING, ui.wait_for_move = false); TERN_(LCD_BED_LEVELING, ui.wait_for_move = false);
@@ -102,8 +102,8 @@ bool hilbert_curve::search_from(uint8_t x, uint8_t y, hilbert_curve::callback_pt
*/ */
bool hilbert_curve::search_from_closest(const xy_pos_t &pos, hilbert_curve::callback_ptr func, void *data) { bool hilbert_curve::search_from_closest(const xy_pos_t &pos, hilbert_curve::callback_ptr func, void *data) {
// Find closest grid intersection // Find closest grid intersection
const uint8_t grid_x = LROUND(constrain((pos.x - mesh_min.x) / (MESH_X_DIST), 0, (GRID_MAX_POINTS_X) - 1)); const uint8_t grid_x = LROUND(constrain(float(pos.x - (MESH_MIN_X)) / (MESH_X_DIST), 0, (GRID_MAX_POINTS_X) - 1));
const uint8_t grid_y = LROUND(constrain((pos.y - mesh_min.y) / (MESH_Y_DIST), 0, (GRID_MAX_POINTS_Y) - 1)); const uint8_t grid_y = LROUND(constrain(float(pos.y - (MESH_MIN_Y)) / (MESH_Y_DIST), 0, (GRID_MAX_POINTS_Y) - 1));
return search_from(grid_x, grid_y, func, data); return search_from(grid_x, grid_y, func, data);
} }
@@ -39,21 +39,14 @@
mesh_bed_leveling::index_to_xpos[GRID_MAX_POINTS_X], mesh_bed_leveling::index_to_xpos[GRID_MAX_POINTS_X],
mesh_bed_leveling::index_to_ypos[GRID_MAX_POINTS_Y]; mesh_bed_leveling::index_to_ypos[GRID_MAX_POINTS_Y];
mesh_bed_leveling::mesh_bed_leveling() { initialize(); } mesh_bed_leveling::mesh_bed_leveling() {
void mesh_bed_leveling::initialize() {
for (uint8_t i = 0; i < GRID_MAX_POINTS_X; ++i) for (uint8_t i = 0; i < GRID_MAX_POINTS_X; ++i)
index_to_xpos[i] = mesh_min.x + i * (MESH_X_DIST); index_to_xpos[i] = MESH_MIN_X + i * (MESH_X_DIST);
for (uint8_t i = 0; i < GRID_MAX_POINTS_Y; ++i) for (uint8_t i = 0; i < GRID_MAX_POINTS_Y; ++i)
index_to_ypos[i] = mesh_min.y + i * (MESH_Y_DIST); index_to_ypos[i] = MESH_MIN_Y + i * (MESH_Y_DIST);
reset(); reset();
} }
void mesh_bed_leveling::report_mesh() {
SERIAL_ECHOLN(F(STRINGIFY(GRID_MAX_POINTS_X) "x" STRINGIFY(GRID_MAX_POINTS_Y) " mesh. Z offset: "), p_float_t(z_offset, 5), F("\nMeasured points:"));
print_2d_array(GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y, 5, z_values[0]);
}
void mesh_bed_leveling::reset() { void mesh_bed_leveling::reset() {
z_offset = 0; z_offset = 0;
ZERO(z_values); ZERO(z_values);
@@ -70,7 +63,7 @@
*/ */
void mesh_bed_leveling::line_to_destination(const feedRate_t scaled_fr_mm_s, uint8_t x_splits, uint8_t y_splits) { void mesh_bed_leveling::line_to_destination(const feedRate_t scaled_fr_mm_s, uint8_t x_splits, uint8_t y_splits) {
// Get current and destination cells for this line // Get current and destination cells for this line
xy_uint8_t scel = cell_indexes(motion.position), ecel = cell_indexes(motion.destination); xy_uint8_t scel = cell_indexes(current_position), ecel = cell_indexes(destination);
NOMORE(scel.x, GRID_MAX_CELLS_X - 1); NOMORE(scel.x, GRID_MAX_CELLS_X - 1);
NOMORE(scel.y, GRID_MAX_CELLS_Y - 1); NOMORE(scel.y, GRID_MAX_CELLS_Y - 1);
NOMORE(ecel.x, GRID_MAX_CELLS_X - 1); NOMORE(ecel.x, GRID_MAX_CELLS_X - 1);
@@ -78,12 +71,12 @@
// Start and end in the same cell? No split needed. // Start and end in the same cell? No split needed.
if (scel == ecel) { if (scel == ecel) {
motion.position = motion.destination; current_position = destination;
motion.goto_current_position(scaled_fr_mm_s); line_to_current_position(scaled_fr_mm_s);
return; return;
} }
#define MBL_SEGMENT_END(A) (motion.position.A + (motion.destination.A - motion.position.A) * normalized_dist) #define MBL_SEGMENT_END(A) (current_position.A + (destination.A - current_position.A) * normalized_dist)
float normalized_dist; float normalized_dist;
xyze_pos_t dest; xyze_pos_t dest;
@@ -94,39 +87,44 @@
if (ecel.x != scel.x && TEST(x_splits, gcx)) { if (ecel.x != scel.x && TEST(x_splits, gcx)) {
// Split on the X grid line // Split on the X grid line
CBI(x_splits, gcx); CBI(x_splits, gcx);
dest = motion.destination; dest = destination;
motion.destination.x = index_to_xpos[gcx]; destination.x = index_to_xpos[gcx];
normalized_dist = (motion.destination.x - motion.position.x) / (dest.x - motion.position.x); normalized_dist = (destination.x - current_position.x) / (dest.x - current_position.x);
motion.destination.y = MBL_SEGMENT_END(y); destination.y = MBL_SEGMENT_END(y);
} }
// Crosses on the Y and not already split on this Y? // Crosses on the Y and not already split on this Y?
else if (ecel.y != scel.y && TEST(y_splits, gcy)) { else if (ecel.y != scel.y && TEST(y_splits, gcy)) {
// Split on the Y grid line // Split on the Y grid line
CBI(y_splits, gcy); CBI(y_splits, gcy);
dest = motion.destination; dest = destination;
motion.destination.y = index_to_ypos[gcy]; destination.y = index_to_ypos[gcy];
normalized_dist = (motion.destination.y - motion.position.y) / (dest.y - motion.position.y); normalized_dist = (destination.y - current_position.y) / (dest.y - current_position.y);
motion.destination.x = MBL_SEGMENT_END(x); destination.x = MBL_SEGMENT_END(x);
} }
else { else {
// Must already have been split on these border(s) // Must already have been split on these border(s)
// This should be a rare case. // This should be a rare case.
motion.position = motion.destination; current_position = destination;
motion.goto_current_position(scaled_fr_mm_s); line_to_current_position(scaled_fr_mm_s);
return; return;
} }
motion.destination.z = MBL_SEGMENT_END(z); destination.z = MBL_SEGMENT_END(z);
motion.destination.e = MBL_SEGMENT_END(e); destination.e = MBL_SEGMENT_END(e);
// Do the split and look for more borders // Do the split and look for more borders
line_to_destination(scaled_fr_mm_s, x_splits, y_splits); line_to_destination(scaled_fr_mm_s, x_splits, y_splits);
// Restore destination from stack // Restore destination from stack
motion.destination = dest; destination = dest;
line_to_destination(scaled_fr_mm_s, x_splits, y_splits); line_to_destination(scaled_fr_mm_s, x_splits, y_splits);
} }
#endif // IS_CARTESIAN && !SEGMENT_LEVELED_MOVES #endif // IS_CARTESIAN && !SEGMENT_LEVELED_MOVES
void mesh_bed_leveling::report_mesh() {
SERIAL_ECHOLN(F(STRINGIFY(GRID_MAX_POINTS_X) "x" STRINGIFY(GRID_MAX_POINTS_Y) " mesh. Z offset: "), p_float_t(z_offset, 5), F("\nMeasured points:"));
print_2d_array(GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y, 5, z_values[0]);
}
#endif // MESH_BED_LEVELING #endif // MESH_BED_LEVELING
@@ -32,7 +32,8 @@ enum MeshLevelingState : char {
MeshReset // G29 S5 MeshReset // G29 S5
}; };
#include "../../../module/motion.h" #define MESH_X_DIST (float((MESH_MAX_X) - (MESH_MIN_X)) / (GRID_MAX_CELLS_X))
#define MESH_Y_DIST (float((MESH_MAX_Y) - (MESH_MIN_Y)) / (GRID_MAX_CELLS_Y))
class mesh_bed_leveling { class mesh_bed_leveling {
public: public:
@@ -43,12 +44,10 @@ public:
mesh_bed_leveling(); mesh_bed_leveling();
static void reset();
static void initialize();
static void report_mesh(); static void report_mesh();
static void reset();
FORCE_INLINE static bool has_mesh() { FORCE_INLINE static bool has_mesh() {
GRID_LOOP(x, y) if (z_values[x][y]) return true; GRID_LOOP(x, y) if (z_values[x][y]) return true;
return false; return false;
@@ -74,11 +73,11 @@ public:
static float get_mesh_y(const uint8_t i) { return index_to_ypos[i]; } static float get_mesh_y(const uint8_t i) { return index_to_ypos[i]; }
static uint8_t cell_index_x(const float x) { static uint8_t cell_index_x(const float x) {
const int8_t cx = (x - mesh_min.x) * RECIPROCAL(MESH_X_DIST); int8_t cx = (x - (MESH_MIN_X)) * RECIPROCAL(MESH_X_DIST);
return constrain(cx, 0, GRID_MAX_CELLS_X - 1); return constrain(cx, 0, GRID_MAX_CELLS_X - 1);
} }
static uint8_t cell_index_y(const float y) { static uint8_t cell_index_y(const float y) {
const int8_t cy = (y - mesh_min.y) * RECIPROCAL(MESH_Y_DIST); int8_t cy = (y - (MESH_MIN_Y)) * RECIPROCAL(MESH_Y_DIST);
return constrain(cy, 0, GRID_MAX_CELLS_Y - 1); return constrain(cy, 0, GRID_MAX_CELLS_Y - 1);
} }
static xy_uint8_t cell_indexes(const float x, const float y) { static xy_uint8_t cell_indexes(const float x, const float y) {
@@ -87,11 +86,11 @@ public:
static xy_uint8_t cell_indexes(const xy_pos_t &xy) { return cell_indexes(xy.x, xy.y); } static xy_uint8_t cell_indexes(const xy_pos_t &xy) { return cell_indexes(xy.x, xy.y); }
static int8_t probe_index_x(const float x) { static int8_t probe_index_x(const float x) {
const int8_t px = (x - mesh_min.x + 0.5f * (MESH_X_DIST)) * RECIPROCAL(MESH_X_DIST); int8_t px = (x - (MESH_MIN_X) + 0.5f * (MESH_X_DIST)) * RECIPROCAL(MESH_X_DIST);
return WITHIN(px, 0, (GRID_MAX_POINTS_X) - 1) ? px : -1; return WITHIN(px, 0, (GRID_MAX_POINTS_X) - 1) ? px : -1;
} }
static int8_t probe_index_y(const float y) { static int8_t probe_index_y(const float y) {
const int8_t py = (y - mesh_min.y + 0.5f * (MESH_Y_DIST)) * RECIPROCAL(MESH_Y_DIST); int8_t py = (y - (MESH_MIN_Y) + 0.5f * (MESH_Y_DIST)) * RECIPROCAL(MESH_Y_DIST);
return WITHIN(py, 0, (GRID_MAX_POINTS_Y) - 1) ? py : -1; return WITHIN(py, 0, (GRID_MAX_POINTS_Y) - 1) ? py : -1;
} }
static xy_int8_t probe_indexes(const float x, const float y) { static xy_int8_t probe_indexes(const float x, const float y) {
+21 -24
View File
@@ -63,25 +63,23 @@ void unified_bed_leveling::report_state() {
int8_t unified_bed_leveling::storage_slot; int8_t unified_bed_leveling::storage_slot;
bed_mesh_t unified_bed_leveling::z_values; float unified_bed_leveling::z_values[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y];
#if !HAS_PROUI_MESH_EDIT #define _GRIDPOS(A,N) (MESH_MIN_##A + N * (MESH_##A##_DIST))
#define _GRIDPOS(A,N) (MESH_MIN_##A + N * (MESH_##A##_DIST))
const float const float
unified_bed_leveling::_mesh_index_to_xpos[GRID_MAX_POINTS_X] PROGMEM = ARRAY_N(GRID_MAX_POINTS_X, unified_bed_leveling::_mesh_index_to_xpos[GRID_MAX_POINTS_X] PROGMEM = ARRAY_N(GRID_MAX_POINTS_X,
_GRIDPOS(X, 0), _GRIDPOS(X, 1), _GRIDPOS(X, 2), _GRIDPOS(X, 3), _GRIDPOS(X, 0), _GRIDPOS(X, 1), _GRIDPOS(X, 2), _GRIDPOS(X, 3),
_GRIDPOS(X, 4), _GRIDPOS(X, 5), _GRIDPOS(X, 6), _GRIDPOS(X, 7), _GRIDPOS(X, 4), _GRIDPOS(X, 5), _GRIDPOS(X, 6), _GRIDPOS(X, 7),
_GRIDPOS(X, 8), _GRIDPOS(X, 9), _GRIDPOS(X, 10), _GRIDPOS(X, 11), _GRIDPOS(X, 8), _GRIDPOS(X, 9), _GRIDPOS(X, 10), _GRIDPOS(X, 11),
_GRIDPOS(X, 12), _GRIDPOS(X, 13), _GRIDPOS(X, 14), _GRIDPOS(X, 15) _GRIDPOS(X, 12), _GRIDPOS(X, 13), _GRIDPOS(X, 14), _GRIDPOS(X, 15)
), ),
unified_bed_leveling::_mesh_index_to_ypos[GRID_MAX_POINTS_Y] PROGMEM = ARRAY_N(GRID_MAX_POINTS_Y, unified_bed_leveling::_mesh_index_to_ypos[GRID_MAX_POINTS_Y] PROGMEM = ARRAY_N(GRID_MAX_POINTS_Y,
_GRIDPOS(Y, 0), _GRIDPOS(Y, 1), _GRIDPOS(Y, 2), _GRIDPOS(Y, 3), _GRIDPOS(Y, 0), _GRIDPOS(Y, 1), _GRIDPOS(Y, 2), _GRIDPOS(Y, 3),
_GRIDPOS(Y, 4), _GRIDPOS(Y, 5), _GRIDPOS(Y, 6), _GRIDPOS(Y, 7), _GRIDPOS(Y, 4), _GRIDPOS(Y, 5), _GRIDPOS(Y, 6), _GRIDPOS(Y, 7),
_GRIDPOS(Y, 8), _GRIDPOS(Y, 9), _GRIDPOS(Y, 10), _GRIDPOS(Y, 11), _GRIDPOS(Y, 8), _GRIDPOS(Y, 9), _GRIDPOS(Y, 10), _GRIDPOS(Y, 11),
_GRIDPOS(Y, 12), _GRIDPOS(Y, 13), _GRIDPOS(Y, 14), _GRIDPOS(Y, 15) _GRIDPOS(Y, 12), _GRIDPOS(Y, 13), _GRIDPOS(Y, 14), _GRIDPOS(Y, 15)
); );
#endif
volatile int16_t unified_bed_leveling::encoder_diff; volatile int16_t unified_bed_leveling::encoder_diff;
@@ -95,7 +93,7 @@ void unified_bed_leveling::reset() {
#if ENABLED(EXTENSIBLE_UI) #if ENABLED(EXTENSIBLE_UI)
GRID_LOOP(x, y) ExtUI::onMeshUpdate(x, y, 0); GRID_LOOP(x, y) ExtUI::onMeshUpdate(x, y, 0);
#endif #endif
if (was_enabled) motion.report_position(); if (was_enabled) report_current_position();
} }
void unified_bed_leveling::invalidate() { void unified_bed_leveling::invalidate() {
@@ -175,8 +173,8 @@ void unified_bed_leveling::display_map(const uint8_t map_type) {
SERIAL_ECHOPGM("\nBed Topography Report"); SERIAL_ECHOPGM("\nBed Topography Report");
if (human) { if (human) {
SERIAL_ECHOLNPGM(":\n"); SERIAL_ECHOLNPGM(":\n");
serial_echo_xy(4, mesh_min.x, mesh_max.y); serial_echo_xy(4, MESH_MIN_X, MESH_MAX_Y);
serial_echo_xy(twixt, mesh_max.x, mesh_max.y); serial_echo_xy(twixt, MESH_MAX_X, MESH_MAX_Y);
SERIAL_EOL(); SERIAL_EOL();
serial_echo_column_labels(eachsp - 2); serial_echo_column_labels(eachsp - 2);
} }
@@ -186,7 +184,7 @@ void unified_bed_leveling::display_map(const uint8_t map_type) {
// Add XY probe offset from extruder because probe.probe_at_point() subtracts them when // Add XY probe offset from extruder because probe.probe_at_point() subtracts them when
// moving to the XY position to be measured. This ensures better agreement between // moving to the XY position to be measured. This ensures better agreement between
// the current Z position after G28 and the mesh values. // the current Z position after G28 and the mesh values.
const xy_int8_t curr = closest_indexes(xy_pos_t(motion.position) + probe.offset_xy); const xy_int8_t curr = closest_indexes(xy_pos_t(current_position) + probe.offset_xy);
if (!lcd) SERIAL_EOL(); if (!lcd) SERIAL_EOL();
for (int8_t j = (GRID_MAX_POINTS_Y) - 1; j >= 0; j--) { for (int8_t j = (GRID_MAX_POINTS_Y) - 1; j >= 0; j--) {
@@ -209,7 +207,6 @@ void unified_bed_leveling::display_map(const uint8_t map_type) {
const float f = z_values[i][j]; const float f = z_values[i][j];
if (lcd) { if (lcd) {
// TODO: Display on Graphical LCD // TODO: Display on Graphical LCD
TERN_(DWIN_LCD_PROUI, dwinMeshViewer());
} }
else if (isnan(f)) else if (isnan(f))
SERIAL_ECHO(human ? F(" . ") : F("NAN")); SERIAL_ECHO(human ? F(" . ") : F("NAN"));
@@ -234,8 +231,8 @@ void unified_bed_leveling::display_map(const uint8_t map_type) {
if (human) { if (human) {
serial_echo_column_labels(eachsp - 2); serial_echo_column_labels(eachsp - 2);
SERIAL_EOL(); SERIAL_EOL();
serial_echo_xy(4, mesh_min.x, mesh_min.y); serial_echo_xy(4, MESH_MIN_X, MESH_MIN_Y);
serial_echo_xy(twixt, mesh_max.x, mesh_min.y); serial_echo_xy(twixt, MESH_MAX_X, MESH_MIN_Y);
SERIAL_EOL(); SERIAL_EOL();
SERIAL_EOL(); SERIAL_EOL();
} }
+16 -34
View File
@@ -38,6 +38,9 @@ enum MeshPointType : char { INVALID, REAL, SET_IN_BITMAP, CLOSEST };
struct mesh_index_pair; struct mesh_index_pair;
#define MESH_X_DIST (float((MESH_MAX_X) - (MESH_MIN_X)) / (GRID_MAX_CELLS_X))
#define MESH_Y_DIST (float((MESH_MAX_Y) - (MESH_MIN_Y)) / (GRID_MAX_CELLS_Y))
#if ENABLED(OPTIMIZED_MESH_STORAGE) #if ENABLED(OPTIMIZED_MESH_STORAGE)
typedef int16_t mesh_store_t[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y]; typedef int16_t mesh_store_t[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y];
#endif #endif
@@ -80,16 +83,6 @@ private:
return smart_fill_one(pos.x, pos.y, dir.x, dir.y); return smart_fill_one(pos.x, pos.y, dir.x, dir.y);
} }
// G29 sub-function handlers
static void G29_handle_homing_and_setup();
static void G29_handle_invalidate();
static bool G29_handle_test_patterns();
#if HAS_BED_PROBE
static void G29_handle_tilt_mesh();
#endif
static bool G29_handle_phase_ops();
static void G29_handle_post_processing();
#if ENABLED(UBL_DEVEL_DEBUGGING) #if ENABLED(UBL_DEVEL_DEBUGGING)
static void g29_what_command(); static void g29_what_command();
static void g29_eeprom_dump(); static void g29_eeprom_dump();
@@ -123,11 +116,8 @@ public:
static void set_store_from_mesh(const bed_mesh_t &in_values, mesh_store_t &stored_values); static void set_store_from_mesh(const bed_mesh_t &in_values, mesh_store_t &stored_values);
static void set_mesh_from_store(const mesh_store_t &stored_values, bed_mesh_t &out_values); static void set_mesh_from_store(const mesh_store_t &stored_values, bed_mesh_t &out_values);
#endif #endif
static const float _mesh_index_to_xpos[GRID_MAX_POINTS_X],
#if !HAS_PROUI_MESH_EDIT _mesh_index_to_ypos[GRID_MAX_POINTS_Y];
static const float _mesh_index_to_xpos[GRID_MAX_POINTS_X],
_mesh_index_to_ypos[GRID_MAX_POINTS_Y];
#endif
#if HAS_MARLINUI_MENU #if HAS_MARLINUI_MENU
static bool lcd_map_control; static bool lcd_map_control;
@@ -143,11 +133,11 @@ public:
FORCE_INLINE static void set_z(const int8_t px, const int8_t py, const float z) { z_values[px][py] = z; } FORCE_INLINE static void set_z(const int8_t px, const int8_t py, const float z) { z_values[px][py] = z; }
static int8_t cell_index_x_raw(const float x) { static int8_t cell_index_x_raw(const float x) {
return FLOOR((x - mesh_min.x) * RECIPROCAL(MESH_X_DIST)); return FLOOR((x - (MESH_MIN_X)) * RECIPROCAL(MESH_X_DIST));
} }
static int8_t cell_index_y_raw(const float y) { static int8_t cell_index_y_raw(const float y) {
return FLOOR((y - mesh_min.y) * RECIPROCAL(MESH_Y_DIST)); return FLOOR((y - (MESH_MIN_Y)) * RECIPROCAL(MESH_Y_DIST));
} }
static bool cell_index_x_valid(const float x) { static bool cell_index_x_valid(const float x) {
@@ -172,11 +162,11 @@ public:
static xy_uint8_t cell_indexes(const xy_pos_t &xy) { return cell_indexes(xy.x, xy.y); } static xy_uint8_t cell_indexes(const xy_pos_t &xy) { return cell_indexes(xy.x, xy.y); }
static int8_t closest_x_index(const float x) { static int8_t closest_x_index(const float x) {
const int8_t px = (x - mesh_min.x + (MESH_X_DIST) * 0.5) * RECIPROCAL(MESH_X_DIST); const int8_t px = (x - (MESH_MIN_X) + (MESH_X_DIST) * 0.5) * RECIPROCAL(MESH_X_DIST);
return WITHIN(px, 0, (GRID_MAX_POINTS_X) - 1) ? px : -1; return WITHIN(px, 0, (GRID_MAX_POINTS_X) - 1) ? px : -1;
} }
static int8_t closest_y_index(const float y) { static int8_t closest_y_index(const float y) {
const int8_t py = (y - mesh_min.y + (MESH_Y_DIST) * 0.5) * RECIPROCAL(MESH_Y_DIST); const int8_t py = (y - (MESH_MIN_Y) + (MESH_Y_DIST) * 0.5) * RECIPROCAL(MESH_Y_DIST);
return WITHIN(py, 0, (GRID_MAX_POINTS_Y) - 1) ? py : -1; return WITHIN(py, 0, (GRID_MAX_POINTS_Y) - 1) ? py : -1;
} }
static xy_int8_t closest_indexes(const xy_pos_t &xy) { static xy_int8_t closest_indexes(const xy_pos_t &xy) {
@@ -269,7 +259,7 @@ public:
* UBL_Z_RAISE_WHEN_OFF_MESH is specified, that value is returned. * UBL_Z_RAISE_WHEN_OFF_MESH is specified, that value is returned.
*/ */
#ifdef UBL_Z_RAISE_WHEN_OFF_MESH #ifdef UBL_Z_RAISE_WHEN_OFF_MESH
if (!WITHIN(rx0, mesh_min.x, mesh_max.x) || !WITHIN(ry0, mesh_min.y, mesh_max.y)) if (!WITHIN(rx0, MESH_MIN_X, MESH_MAX_X) || !WITHIN(ry0, MESH_MIN_Y, MESH_MAX_Y))
return UBL_Z_RAISE_WHEN_OFF_MESH; return UBL_Z_RAISE_WHEN_OFF_MESH;
#endif #endif
@@ -297,20 +287,12 @@ public:
static constexpr float get_z_offset() { return 0.0f; } static constexpr float get_z_offset() { return 0.0f; }
static float _get_mesh_x(const uint8_t i) { return mesh_min.x + i * (MESH_X_DIST); } static float get_mesh_x(const uint8_t i) {
static float _get_mesh_y(const uint8_t i) { return mesh_min.y + i * (MESH_Y_DIST); } return i < (GRID_MAX_POINTS_X) ? pgm_read_float(&_mesh_index_to_xpos[i]) : MESH_MIN_X + i * (MESH_X_DIST);
}
#if HAS_PROUI_MESH_EDIT static float get_mesh_y(const uint8_t i) {
static float get_mesh_x(const uint8_t i) { return _get_mesh_x(i); } return i < (GRID_MAX_POINTS_Y) ? pgm_read_float(&_mesh_index_to_ypos[i]) : MESH_MIN_Y + i * (MESH_Y_DIST);
static float get_mesh_y(const uint8_t i) { return _get_mesh_y(i); } }
#else
static float get_mesh_x(const uint8_t i) {
return i < (GRID_MAX_POINTS_X) ? pgm_read_float(&_mesh_index_to_xpos[i]) : _get_mesh_x(i);
}
static float get_mesh_y(const uint8_t i) {
return i < (GRID_MAX_POINTS_Y) ? pgm_read_float(&_mesh_index_to_ypos[i]) : _get_mesh_y(i);
}
#endif
#if UBL_SEGMENTED #if UBL_SEGMENTED
static bool line_to_destination_segmented(const feedRate_t scaled_fr_mm_s); static bool line_to_destination_segmented(const feedRate_t scaled_fr_mm_s);
+354 -414
View File
@@ -43,10 +43,6 @@
#include "../../../lcd/extui/ui_api.h" #include "../../../lcd/extui/ui_api.h"
#endif #endif
#if ENABLED(DWIN_LCD_PROUI)
#include "../../../lcd/dwin/proui/meshviewer.h"
#endif
#if ENABLED(UBL_HILBERT_CURVE) #if ENABLED(UBL_HILBERT_CURVE)
#include "../hilbert_curve.h" #include "../hilbert_curve.h"
#endif #endif
@@ -319,31 +315,305 @@ void unified_bed_leveling::G29() {
// Potentially disable Fixed-Time Motion for probing // Potentially disable Fixed-Time Motion for probing
TERN_(FT_MOTION, FTM_DISABLE_IN_SCOPE()); TERN_(FT_MOTION, FTM_DISABLE_IN_SCOPE());
// Handle homing and initial setup // Check for commands that require the printer to be homed
if (may_move) G29_handle_homing_and_setup(); if (may_move) {
planner.synchronize();
#if ALL(DWIN_LCD_PROUI, ZHOME_BEFORE_LEVELING)
save_ubl_active_state_and_disable();
gcode.process_subcommands_now(F("G28Z"));
restore_ubl_active_state(false); // ...without telling ExtUI "done"
#else
// Send 'N' to force homing before G29 (internal only)
if (axes_should_home() || parser.seen_test('N')) gcode.home_all_axes();
#endif
probe.use_probing_tool();
// Handle mesh invalidation (I parameter) #ifdef EVENT_GCODE_BEFORE_G29
if (parser.seen('I')) G29_handle_invalidate(); if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Before G29 G-code: ", EVENT_GCODE_BEFORE_G29);
gcode.process_subcommands_now(F(EVENT_GCODE_BEFORE_G29));
#endif
// Handle test patterns (Q parameter) // Position bed horizontally and Z probe vertically.
if (parser.seen('Q') && !G29_handle_test_patterns()) return; #if HAS_SAFE_BED_LEVELING
xyze_pos_t safe_position = current_position;
#ifdef SAFE_BED_LEVELING_START_X
safe_position.x = SAFE_BED_LEVELING_START_X;
#endif
#ifdef SAFE_BED_LEVELING_START_Y
safe_position.y = SAFE_BED_LEVELING_START_Y;
#endif
#ifdef SAFE_BED_LEVELING_START_Z
safe_position.z = SAFE_BED_LEVELING_START_Z;
#endif
#ifdef SAFE_BED_LEVELING_START_I
safe_position.i = SAFE_BED_LEVELING_START_I;
#endif
#ifdef SAFE_BED_LEVELING_START_J
safe_position.j = SAFE_BED_LEVELING_START_J;
#endif
#ifdef SAFE_BED_LEVELING_START_K
safe_position.k = SAFE_BED_LEVELING_START_K;
#endif
#ifdef SAFE_BED_LEVELING_START_U
safe_position.u = SAFE_BED_LEVELING_START_U;
#endif
#ifdef SAFE_BED_LEVELING_START_V
safe_position.v = SAFE_BED_LEVELING_START_V;
#endif
#ifdef SAFE_BED_LEVELING_START_W
safe_position.w = SAFE_BED_LEVELING_START_W;
#endif
do_blocking_move_to(safe_position);
#endif // HAS_SAFE_BED_LEVELING
}
// Invalidate one or more nearby mesh points, possibly all.
if (parser.seen('I')) {
grid_count_t count = parser.has_value() ? parser.value_ushort() : 1;
bool invalidate_all = count >= GRID_MAX_POINTS;
if (!invalidate_all) {
while (count--) {
if ((count & 0x0F) == 0x0F) marlin.idle();
const mesh_index_pair closest = find_closest_mesh_point_of_type(REAL, param.XY_pos);
// No more REAL mesh points to invalidate? Assume the user meant
// to invalidate the ENTIRE mesh, which can't be done with
// find_closest_mesh_point (which only returns REAL points).
if (closest.pos.x < 0) { invalidate_all = true; break; }
z_values[closest.pos.x][closest.pos.y] = NAN;
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(closest.pos, 0.0f));
}
}
if (invalidate_all) {
invalidate();
SERIAL_ECHOPGM("Entire Mesh");
}
else
SERIAL_ECHOPGM("Locations");
SERIAL_ECHOLNPGM(" invalidated.\n");
}
if (parser.seen('Q')) {
const int16_t test_pattern = parser.has_value() ? parser.value_int() : -99;
if (!WITHIN(test_pattern, TERN0(UBL_DEVEL_DEBUGGING, -1), 2)) {
SERIAL_ECHOLN(F("?Invalid "), F("(Q) test pattern. (" TERN(UBL_DEVEL_DEBUGGING, "-1", "0") " to 2)\n"));
return;
}
SERIAL_ECHOLNPGM("Applying test pattern.\n");
switch (test_pattern) {
default:
case -1: TERN_(UBL_DEVEL_DEBUGGING, g29_eeprom_dump()); break;
case 0:
GRID_LOOP(x, y) { // Create a bowl shape similar to a poorly-calibrated Delta
const float p1 = 0.5f * (GRID_MAX_POINTS_X) - x,
p2 = 0.5f * (GRID_MAX_POINTS_Y) - y;
z_values[x][y] += 2.0f * HYPOT(p1, p2);
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(x, y, z_values[x][y]));
}
break;
case 1:
for (uint8_t x = 0; x < GRID_MAX_POINTS_X; ++x) { // Create a diagonal line several Mesh cells thick that is raised
const uint8_t x2 = x + (x < (GRID_MAX_POINTS_Y) - 1 ? 1 : -1);
z_values[x][x] += 9.999f;
z_values[x][x2] += 9.999f; // We want the altered line several mesh points thick
#if ENABLED(EXTENSIBLE_UI)
ExtUI::onMeshUpdate(x, x, z_values[x][x]);
ExtUI::onMeshUpdate(x, x2, z_values[x][x2]);
#endif
}
break;
case 2:
// Allow the user to specify the height because 10mm is a little extreme in some cases.
for (uint8_t x = (GRID_MAX_POINTS_X) / 3; x < 2 * (GRID_MAX_POINTS_X) / 3; x++) // Create a rectangular raised area in
for (uint8_t y = (GRID_MAX_POINTS_Y) / 3; y < 2 * (GRID_MAX_POINTS_Y) / 3; y++) { // the center of the bed
z_values[x][y] += parser.seen_test('C') ? param.C_constant : 9.99f;
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(x, y, z_values[x][y]));
}
break;
}
}
// Handle tilt mesh (J parameter)
#if HAS_BED_PROBE #if HAS_BED_PROBE
if (parser.seen_test('J')) G29_handle_tilt_mesh();
#endif
// Handle phase operations (P parameter) if (parser.seen_test('J')) {
if (parser.seen_test('P') && !G29_handle_phase_ops()) return; save_ubl_active_state_and_disable();
tilt_mesh_based_on_probed_grid(param.J_grid_size == 0); // Zero size does 3-Point
restore_ubl_active_state();
#if ENABLED(UBL_G29_J_RECENTER)
do_blocking_move_to_xy(0.5f * ((MESH_MIN_X) + (MESH_MAX_X)), 0.5f * ((MESH_MIN_Y) + (MESH_MAX_Y)));
#endif
report_current_position();
SET_PROBE_DEPLOYED(true);
}
// Handle post-processing and cleanup #endif // HAS_BED_PROBE
G29_handle_post_processing();
} if (parser.seen_test('P')) {
if (WITHIN(param.P_phase, 0, 1) && storage_slot == -1) {
storage_slot = 0;
SERIAL_ECHOLNPGM("Default storage slot 0 selected.");
}
switch (param.P_phase) {
case 0:
//
// Zero Mesh Data
//
reset();
SERIAL_ECHOLNPGM("Mesh zeroed.");
break;
#if HAS_BED_PROBE
case 1: {
//
// Invalidate Entire Mesh and Automatically Probe Mesh in areas that can be reached by the probe
//
if (!parser.seen_test('C')) {
invalidate();
SERIAL_ECHOLNPGM("Mesh invalidated. Probing mesh.");
}
if (param.V_verbosity > 1)
SERIAL_ECHOLN(F("Probing around ("), param.XY_pos.x, C(','), param.XY_pos.y, F(").\n"));
probe_entire_mesh(param.XY_pos, parser.seen_test('T'), parser.seen_test('E'), parser.seen_test('U'));
report_current_position();
SET_PROBE_DEPLOYED(true);
} break;
#endif // HAS_BED_PROBE
case 2: {
#if HAS_MARLINUI_MENU
//
// Manually Probe Mesh in areas that can't be reached by the probe
//
SERIAL_ECHOLNPGM("Manually probing unreachable points.");
do_z_clearance(Z_CLEARANCE_BETWEEN_PROBES);
if (parser.seen_test('C') && !param.XY_seen) {
/**
* Use a good default location for the path.
* The flipped > and < operators in these comparisons is intentional.
* It should cause the probed points to follow a nice path on Cartesian printers.
* It may make sense to have Delta printers default to the center of the bed.
* Until that is decided, this can be forced with the X and Y parameters.
*/
param.XY_pos.set(
#if IS_KINEMATIC
X_HOME_POS, Y_HOME_POS
#else
probe.offset_xy.x > 0 ? X_BED_SIZE : 0,
probe.offset_xy.y < 0 ? Y_BED_SIZE : 0
#endif
);
}
if (parser.seen('B')) {
param.B_shim_thickness = parser.has_value() ? parser.value_float() : measure_business_card_thickness();
if (ABS(param.B_shim_thickness) > 1.5f) {
SERIAL_ECHOLNPGM("?Error in Business Card measurement.");
return;
}
SET_PROBE_DEPLOYED(true);
}
if (!position_is_reachable(param.XY_pos)) {
SERIAL_ECHOLNPGM("XY outside printable radius.");
return;
}
const float height = parser.floatval('H', Z_CLEARANCE_BETWEEN_PROBES);
manually_probe_remaining_mesh(param.XY_pos, height, param.B_shim_thickness, parser.seen_test('T'));
SERIAL_ECHOLNPGM("G29 P2 finished.");
report_current_position();
#else
SERIAL_ECHOLNPGM("?P2 is only available when an LCD is present.");
return;
#endif
} break;
case 3: {
/**
* Populate invalid mesh areas. Proceed with caution.
* Two choices are available:
* - Specify a constant with the 'C' parameter.
* - Allow 'G29 P3' to choose a 'reasonable' constant.
*/
if (param.C_seen) {
if (param.R_repetition >= GRID_MAX_POINTS) {
set_all_mesh_points_to_value(param.C_constant);
}
else {
while (param.R_repetition--) { // this only populates reachable mesh points near
const mesh_index_pair closest = find_closest_mesh_point_of_type(INVALID, param.XY_pos);
const xy_int8_t &cpos = closest.pos;
if (cpos.x < 0) {
// No more REAL INVALID mesh points to populate, so we ASSUME
// user meant to populate ALL INVALID mesh points to value
GRID_LOOP(x, y) if (isnan(z_values[x][y])) z_values[x][y] = param.C_constant;
break; // No more invalid Mesh Points to populate
}
else {
z_values[cpos.x][cpos.y] = param.C_constant;
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(cpos, param.C_constant));
}
}
}
}
else {
const float cvf = parser.value_float();
switch ((int)TRUNC(cvf * 10.0f) - 30) { // 3.1 -> 1
#if ENABLED(UBL_G29_P31)
case 1: {
// P3.1 use least squares fit to fill missing mesh values
// P3.10 zero weighting for distance, all grid points equal, best fit tilted plane
// P3.11 10X weighting for nearest grid points versus farthest grid points
// P3.12 100X distance weighting
// P3.13 1000X distance weighting, approaches simple average of nearest points
const float weight_power = (cvf - 3.10f) * 100.0f, // 3.12345 -> 2.345
weight_factor = weight_power ? POW(10.0f, weight_power) : 0;
smart_fill_wlsf(weight_factor);
}
break;
#endif
case 0: // P3 or P3.0
default: // and anything P3.x that's not P3.1
smart_fill_mesh(); // Do a 'Smart' fill using nearby known values
break;
}
}
break;
}
case 4: // Fine Tune (i.e., Edit) the Mesh
#if HAS_MARLINUI_MENU
fine_tune_mesh(param.XY_pos, parser.seen_test('T'));
#else
SERIAL_ECHOLNPGM("?P4 is only available when an LCD is present.");
return;
#endif
break;
case 5: adjust_mesh_to_mean(param.C_seen, param.C_constant); break;
case 6: shift_mesh_height(param.C_constant); break;
}
}
/**
* Handle post-processing and cleanup
*/
void unified_bed_leveling::G29_handle_post_processing() {
#if ENABLED(UBL_DEVEL_DEBUGGING) #if ENABLED(UBL_DEVEL_DEBUGGING)
// //
@@ -391,7 +661,7 @@ void unified_bed_leveling::G29_handle_post_processing() {
// Store a Mesh in the EEPROM // Store a Mesh in the EEPROM
// //
else if (parser.seen('S')) { // Store (or Save) Current Mesh Data if (parser.seen('S')) { // Store (or Save) Current Mesh Data
param.KLS_storage_slot = parser.has_value() ? (int8_t)parser.value_int() : storage_slot; param.KLS_storage_slot = parser.has_value() ? (int8_t)parser.value_int() : storage_slot;
if (param.KLS_storage_slot == -1) // Special case: 'Export' the mesh to the if (param.KLS_storage_slot == -1) // Special case: 'Export' the mesh to the
@@ -436,337 +706,7 @@ void unified_bed_leveling::G29_handle_post_processing() {
#endif #endif
probe.use_probing_tool(false); probe.use_probing_tool(false);
} return;
/**
* Handle phase operations (P parameter)
* @return true if successful, false if error occurred
*/
bool unified_bed_leveling::G29_handle_phase_ops() {
if (WITHIN(param.P_phase, 0, 1) && storage_slot == -1) {
storage_slot = 0;
SERIAL_ECHOLNPGM("Default storage slot 0 selected.");
}
switch (param.P_phase) {
case 0:
//
// Zero Mesh Data
//
reset();
SERIAL_ECHOLNPGM("Mesh zeroed.");
break;
#if HAS_BED_PROBE
case 1: {
//
// Invalidate Entire Mesh and Automatically Probe Mesh in areas that can be reached by the probe
//
if (!parser.seen_test('C')) {
invalidate();
SERIAL_ECHOLNPGM("Mesh invalidated. Probing mesh.");
}
if (param.V_verbosity > 1)
SERIAL_ECHOLN(F("Probing around ("), param.XY_pos.x, C(','), param.XY_pos.y, F(").\n"));
probe_entire_mesh(param.XY_pos, parser.seen_test('T'), parser.seen_test('E'), parser.seen_test('U'));
motion.report_position();
SET_PROBE_DEPLOYED(true);
} break;
#endif // HAS_BED_PROBE
case 2: {
#if HAS_MARLINUI_MENU
//
// Manually Probe Mesh in areas that can't be reached by the probe
//
SERIAL_ECHOLNPGM("Manually probing unreachable points.");
motion.do_z_clearance(Z_CLEARANCE_BETWEEN_PROBES);
if (parser.seen_test('C') && !param.XY_seen) {
/**
* Use a good default location for the path.
* The flipped > and < operators in these comparisons is intentional.
* It should cause the probed points to follow a nice path on Cartesian printers.
* It may make sense to have Delta printers default to the center of the bed.
* Until that is decided, this can be forced with the X and Y parameters.
*/
param.XY_pos.set(
#if IS_KINEMATIC
X_HOME_POS, Y_HOME_POS
#else
probe.offset_xy.x > 0 ? X_BED_SIZE : 0,
probe.offset_xy.y < 0 ? Y_BED_SIZE : 0
#endif
);
}
if (parser.seen('B')) {
param.B_shim_thickness = parser.has_value() ? parser.value_float() : measure_business_card_thickness();
if (ABS(param.B_shim_thickness) > 1.5f) {
SERIAL_ECHOLNPGM("?Error in Business Card measurement.");
return false;
}
SET_PROBE_DEPLOYED(true);
}
if (!motion.can_reach(param.XY_pos)) {
SERIAL_ECHOLNPGM("XY outside printable radius.");
return false;
}
const float height = parser.floatval('H', Z_CLEARANCE_BETWEEN_PROBES);
manually_probe_remaining_mesh(param.XY_pos, height, param.B_shim_thickness, parser.seen_test('T'));
SERIAL_ECHOLNPGM("G29 P2 finished.");
motion.report_position();
#else
SERIAL_ECHOLNPGM("?P2 is only available when an LCD is present.");
return false;
#endif
} break;
case 3: {
/**
* Populate invalid mesh areas. Proceed with caution.
* Two choices are available:
* - Specify a constant with the 'C' parameter.
* - Allow 'G29 P3' to choose a 'reasonable' constant.
*/
if (param.C_seen) {
if (param.R_repetition >= GRID_MAX_POINTS) {
set_all_mesh_points_to_value(param.C_constant);
}
else {
while (param.R_repetition--) { // this only populates reachable mesh points near
const mesh_index_pair closest = find_closest_mesh_point_of_type(INVALID, param.XY_pos);
const xy_int8_t &cpos = closest.pos;
if (cpos.x < 0) {
// No more REAL INVALID mesh points to populate, so we ASSUME
// user meant to populate ALL INVALID mesh points to value
GRID_LOOP(x, y) if (isnan(z_values[x][y])) z_values[x][y] = param.C_constant;
break; // No more invalid Mesh Points to populate
}
else {
z_values[cpos.x][cpos.y] = param.C_constant;
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(cpos, param.C_constant));
}
}
}
}
else {
const float cvf = parser.value_float();
switch ((int)TRUNC(cvf * 10.0f) - 30) { // 3.1 -> 1
#if ENABLED(UBL_G29_P31)
case 1: {
// P3.1 use least squares fit to fill missing mesh values
// P3.10 zero weighting for distance, all grid points equal, best fit tilted plane
// P3.11 10X weighting for nearest grid points versus farthest grid points
// P3.12 100X distance weighting
// P3.13 1000X distance weighting, approaches simple average of nearest points
const float weight_power = (cvf - 3.10f) * 100.0f, // 3.12345 -> 2.345
weight_factor = weight_power ? POW(10.0f, weight_power) : 0;
smart_fill_wlsf(weight_factor);
}
break;
#endif
case 0: // P3 or P3.0
default: // and anything P3.x that's not P3.1
smart_fill_mesh(); // Do a 'Smart' fill using nearby known values
break;
}
}
break;
}
case 4: // Fine Tune (i.e., Edit) the Mesh
#if HAS_MARLINUI_MENU
fine_tune_mesh(param.XY_pos, parser.seen_test('T'));
#else
SERIAL_ECHOLNPGM("?P4 is only available when an LCD is present.");
return false;
#endif
break;
case 5: adjust_mesh_to_mean(param.C_seen, param.C_constant); break;
case 6: shift_mesh_height(param.C_constant); break;
default:
SERIAL_ECHOLNPGM("?Invalid P value.\n");
return false;
}
return true;
}
/**
* Handle homing and initial setup for G29 command
* @param may_move Whether the command requires printer movement
* @return true if successful, false if error occurred
*/
void unified_bed_leveling::G29_handle_homing_and_setup() {
planner.synchronize();
#if ALL(DWIN_LCD_PROUI, ZHOME_BEFORE_LEVELING)
save_ubl_active_state_and_disable();
gcode.process_subcommands_now(F("G28Z"));
restore_ubl_active_state(false); // ...without telling ExtUI "done"
#else
// Send 'N' to force homing before G29 (internal only)
if (motion.axes_should_home() || parser.seen_test('N')) gcode.home_all_axes();
#endif
probe.use_probing_tool();
#ifdef EVENT_GCODE_BEFORE_G29
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Before G29 G-code: ", EVENT_GCODE_BEFORE_G29);
gcode.process_subcommands_now(F(EVENT_GCODE_BEFORE_G29));
#endif
// Position bed horizontally and Z probe vertically.
#if HAS_SAFE_BED_LEVELING
xyze_pos_t safe_position = motion.position;
#ifdef SAFE_BED_LEVELING_START_X
safe_position.x = SAFE_BED_LEVELING_START_X;
#endif
#ifdef SAFE_BED_LEVELING_START_Y
safe_position.y = SAFE_BED_LEVELING_START_Y;
#endif
#ifdef SAFE_BED_LEVELING_START_Z
safe_position.z = SAFE_BED_LEVELING_START_Z;
#endif
#ifdef SAFE_BED_LEVELING_START_I
safe_position.i = SAFE_BED_LEVELING_START_I;
#endif
#ifdef SAFE_BED_LEVELING_START_J
safe_position.j = SAFE_BED_LEVELING_START_J;
#endif
#ifdef SAFE_BED_LEVELING_START_K
safe_position.k = SAFE_BED_LEVELING_START_K;
#endif
#ifdef SAFE_BED_LEVELING_START_U
safe_position.u = SAFE_BED_LEVELING_START_U;
#endif
#ifdef SAFE_BED_LEVELING_START_V
safe_position.v = SAFE_BED_LEVELING_START_V;
#endif
#ifdef SAFE_BED_LEVELING_START_W
safe_position.w = SAFE_BED_LEVELING_START_W;
#endif
motion.blocking_move(safe_position);
#endif // HAS_SAFE_BED_LEVELING
}
/**
* Handle mesh invalidation (I parameter)
*/
void unified_bed_leveling::G29_handle_invalidate() {
// Invalidate one or more nearby mesh points, possibly all.
grid_count_t count = parser.has_value() ? parser.value_ushort() : 1;
bool invalidate_all = count >= GRID_MAX_POINTS;
if (!invalidate_all) {
while (count--) {
if ((count & 0x0F) == 0x0F) marlin.idle();
const mesh_index_pair closest = find_closest_mesh_point_of_type(REAL, param.XY_pos);
// No more REAL mesh points to invalidate? Assume the user meant
// to invalidate the ENTIRE mesh, which can't be done with
// find_closest_mesh_point (which only returns REAL points).
if (closest.pos.x < 0) { invalidate_all = true; break; }
z_values[closest.pos.x][closest.pos.y] = NAN;
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(closest.pos, 0.0f));
}
}
if (invalidate_all) {
invalidate();
SERIAL_ECHOPGM("Entire Mesh");
}
else
SERIAL_ECHOPGM("Locations");
SERIAL_ECHOLNPGM(" invalidated.\n");
}
#if HAS_BED_PROBE
/**
* Handle tilt mesh (J parameter)
*/
void unified_bed_leveling::G29_handle_tilt_mesh() {
save_ubl_active_state_and_disable();
tilt_mesh_based_on_probed_grid(param.J_grid_size == 0); // Zero size does 3-Point
restore_ubl_active_state();
#if ENABLED(UBL_G29_J_RECENTER)
motion.blocking_move_xy(0.5f * (mesh_min.x + mesh_max.x), 0.5f * (mesh_min.y + mesh_max.y));
#endif
motion.report_position();
SET_PROBE_DEPLOYED(true);
}
#endif // HAS_BED_PROBE
/**
* Handle test patterns (Q parameter)
* @return true if successful, false if error occurred
*/
bool unified_bed_leveling::G29_handle_test_patterns() {
const int16_t test_pattern = parser.has_value() ? parser.value_int() : -99;
if (!WITHIN(test_pattern, TERN0(UBL_DEVEL_DEBUGGING, -1), 2)) {
SERIAL_ECHOLN(F("?Invalid "), F("(Q) test pattern. (" TERN(UBL_DEVEL_DEBUGGING, "-1", "0") " to 2)\n"));
return false;
}
SERIAL_ECHOLNPGM("Applying test pattern.\n");
switch (test_pattern) {
default:
case -1: TERN_(UBL_DEVEL_DEBUGGING, g29_eeprom_dump()); break;
case 0:
// Create a bowl shape similar to a poorly-calibrated Delta
GRID_LOOP(x, y) {
const float p1 = 0.5f * (GRID_MAX_POINTS_X) - x,
p2 = 0.5f * (GRID_MAX_POINTS_Y) - y;
z_values[x][y] += 2.0f * HYPOT(p1, p2);
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(x, y, z_values[x][y]));
}
break;
case 1:
// Create a diagonal line several Mesh cells thick that is raised
for (uint8_t x = 0; x < GRID_MAX_POINTS_X; ++x) {
const uint8_t x2 = x + (x < (GRID_MAX_POINTS_Y) - 1 ? 1 : -1);
z_values[x][x] += 9.999f;
z_values[x][x2] += 9.999f; // We want the altered line several mesh points thick
#if ENABLED(EXTENSIBLE_UI)
ExtUI::onMeshUpdate(x, x, z_values[x][x]);
ExtUI::onMeshUpdate(x, x2, z_values[x][x2]);
#endif
}
break;
case 2:
// Allow the user to specify the height because 10mm is a little extreme in some cases.
for (uint8_t x = (GRID_MAX_POINTS_X) / 3; x < 2 * (GRID_MAX_POINTS_X) / 3; x++) // Create a rectangular raised area in
for (uint8_t y = (GRID_MAX_POINTS_Y) / 3; y < 2 * (GRID_MAX_POINTS_Y) / 3; y++) { // the center of the bed
z_values[x][y] += parser.seen_test('C') ? param.C_constant : 9.99f;
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(x, y, z_values[x][y]));
}
break;
}
return true;
}
void unified_bed_leveling::shift_mesh_height(const float zoffs) {
GRID_LOOP(x, y)
if (!isnan(z_values[x][y])) {
z_values[x][y] += zoffs;
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(x, y, z_values[x][y]));
}
} }
/** /**
@@ -807,6 +747,17 @@ void unified_bed_leveling::adjust_mesh_to_mean(const bool cflag, const float off
} }
} }
/**
* G29 P6 C<offset> : Shift Mesh Height by a uniform constant.
*/
void unified_bed_leveling::shift_mesh_height(const float zoffs) {
GRID_LOOP(x, y)
if (!isnan(z_values[x][y])) {
z_values[x][y] += zoffs;
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(x, y, z_values[x][y]));
}
}
#if HAS_BED_PROBE #if HAS_BED_PROBE
/** /**
* G29 P1 T<maptype> V<verbosity> : Probe Entire Mesh * G29 P1 T<maptype> V<verbosity> : Probe Entire Mesh
@@ -832,10 +783,6 @@ void unified_bed_leveling::adjust_mesh_to_mean(const bool cflag, const float off
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(MSG_PROBING_POINT), point_num, int(GRID_MAX_POINTS)));
TERN_(HAS_BACKLIGHT_TIMEOUT, ui.refresh_backlight_timeout()); TERN_(HAS_BACKLIGHT_TIMEOUT, ui.refresh_backlight_timeout());
#if ENABLED(DWIN_LCD_PROUI)
if (!hmiFlag.cancel_lev) dwinRedrawScreen(); else break;
#endif
#if HAS_MARLINUI_MENU #if HAS_MARLINUI_MENU
if (ui.button_pressed()) { if (ui.button_pressed()) {
ui.quick_feedback(false); // Preserve button state for click-and-hold ui.quick_feedback(false); // Preserve button state for click-and-hold
@@ -869,9 +816,6 @@ void unified_bed_leveling::adjust_mesh_to_mean(const bool cflag, const float off
} while (best.pos.x >= 0 && --count); } while (best.pos.x >= 0 && --count);
if (TERN0(DWIN_LCD_PROUI, hmiFlag.cancel_lev))
goto EXIT_PROBE_MESH;
GRID_LOOP(x, y) if (z_values[x][y] == HUGE_VALF) z_values[x][y] = NAN; // Restore NAN for HUGE_VALF marks GRID_LOOP(x, y) if (z_values[x][y] == HUGE_VALF) z_values[x][y] = NAN; // Restore NAN for HUGE_VALF marks
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(best.pos, ExtUI::G29_FINISH)); TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(best.pos, ExtUI::G29_FINISH));
@@ -883,16 +827,10 @@ void unified_bed_leveling::adjust_mesh_to_mean(const bool cflag, const float off
probe.move_z_after_probing(); probe.move_z_after_probing();
#if ENABLED(DWIN_LCD_PROUI) do_blocking_move_to_xy(
bedlevel.smart_fill_mesh(); constrain(nearby.x - probe.offset_xy.x, MESH_MIN_X, MESH_MAX_X),
#else constrain(nearby.y - probe.offset_xy.y, MESH_MIN_Y, MESH_MAX_Y)
motion.blocking_move_xy( );
constrain(nearby.x - probe.offset_xy.x, mesh_min.x, mesh_max.x),
constrain(nearby.y - probe.offset_xy.y, mesh_min.y, mesh_max.y)
);
#endif
EXIT_PROBE_MESH:
restore_ubl_active_state(); restore_ubl_active_state();
} }
@@ -936,7 +874,7 @@ void set_message_with_feedback(FSTR_P const fstr) {
marlin.idle(); marlin.idle();
gcode.reset_stepper_timeout(); // Keep steppers powered gcode.reset_stepper_timeout(); // Keep steppers powered
if (encoder_diff) { if (encoder_diff) {
motion.blocking_move_z(motion.position.z + float(encoder_diff) * multiplier); do_blocking_move_to_z(current_position.z + float(encoder_diff) * multiplier);
encoder_diff = 0; encoder_diff = 0;
} }
} }
@@ -946,7 +884,7 @@ void set_message_with_feedback(FSTR_P const fstr) {
KEEPALIVE_STATE(PAUSED_FOR_USER); KEEPALIVE_STATE(PAUSED_FOR_USER);
const float z_step = 0.01f; const float z_step = 0.01f;
move_z_with_encoder(z_step); move_z_with_encoder(z_step);
return motion.position.z; return current_position.z;
} }
static void echo_and_take_a_measurement() { SERIAL_ECHOLNPGM(" and take a measurement."); } static void echo_and_take_a_measurement() { SERIAL_ECHOLNPGM(" and take a measurement."); }
@@ -955,10 +893,10 @@ void set_message_with_feedback(FSTR_P const fstr) {
ui.capture(); ui.capture();
save_ubl_active_state_and_disable(); // Disable bed level correction for probing save_ubl_active_state_and_disable(); // Disable bed level correction for probing
motion.blocking_move( do_blocking_move_to(
xyz_pos_t({ xyz_pos_t({
0.5f * (mesh_min.x + mesh_max.x), 0.5f * ((MESH_MAX_X) - (MESH_MIN_X)),
0.5f * (mesh_min.y + mesh_max.y), 0.5f * ((MESH_MAX_Y) - (MESH_MIN_Y)),
MANUAL_PROBE_START_Z MANUAL_PROBE_START_Z
#ifdef SAFE_BED_LEVELING_START_I #ifdef SAFE_BED_LEVELING_START_I
, SAFE_BED_LEVELING_START_I , SAFE_BED_LEVELING_START_I
@@ -989,14 +927,14 @@ void set_message_with_feedback(FSTR_P const fstr) {
echo_and_take_a_measurement(); echo_and_take_a_measurement();
const float z1 = measure_point_with_encoder(); const float z1 = measure_point_with_encoder();
motion.do_z_clearance_by(SIZE_OF_LITTLE_RAISE); do_z_clearance_by(SIZE_OF_LITTLE_RAISE);
SERIAL_ECHOPGM("Remove shim"); SERIAL_ECHOPGM("Remove shim");
LCD_MESSAGE(MSG_UBL_BC_REMOVE); LCD_MESSAGE(MSG_UBL_BC_REMOVE);
echo_and_take_a_measurement(); echo_and_take_a_measurement();
const float z2 = measure_point_with_encoder(); const float z2 = measure_point_with_encoder();
motion.do_z_clearance_by(Z_CLEARANCE_BETWEEN_PROBES); do_z_clearance_by(Z_CLEARANCE_BETWEEN_PROBES);
const float thickness = ABS(z1 - z2); const float thickness = ABS(z1 - z2);
@@ -1018,7 +956,7 @@ void set_message_with_feedback(FSTR_P const fstr) {
TERN_(EXTENSIBLE_UI, ExtUI::onLevelingStart()); TERN_(EXTENSIBLE_UI, ExtUI::onLevelingStart());
save_ubl_active_state_and_disable(); // No bed level correction so only raw data is obtained save_ubl_active_state_and_disable(); // No bed level correction so only raw data is obtained
motion.blocking_move_xy_z(motion.position, z_clearance); do_blocking_move_to_xy_z(current_position, z_clearance);
ui.return_to_status(); ui.return_to_status();
@@ -1031,12 +969,12 @@ void set_message_with_feedback(FSTR_P const fstr) {
const xyz_pos_t ppos = { get_mesh_x(lpos.x), get_mesh_y(lpos.y), z_clearance }; const xyz_pos_t ppos = { get_mesh_x(lpos.x), get_mesh_y(lpos.y), z_clearance };
if (!motion.can_reach(ppos)) break; // SHOULD NOT OCCUR (find_closest_mesh_point only returns reachable points) if (!position_is_reachable(ppos)) break; // SHOULD NOT OCCUR (find_closest_mesh_point only returns reachable points)
LCD_MESSAGE(MSG_UBL_MOVING_TO_NEXT); LCD_MESSAGE(MSG_UBL_MOVING_TO_NEXT);
motion.blocking_move(ppos); do_blocking_move_to(ppos);
motion.do_z_clearance(z_clearance); do_z_clearance(z_clearance);
KEEPALIVE_STATE(PAUSED_FOR_USER); KEEPALIVE_STATE(PAUSED_FOR_USER);
ui.capture(); ui.capture();
@@ -1057,11 +995,11 @@ void set_message_with_feedback(FSTR_P const fstr) {
if (_click_and_hold([]{ if (_click_and_hold([]{
SERIAL_ECHOLNPGM("\nMesh only partially populated."); SERIAL_ECHOLNPGM("\nMesh only partially populated.");
motion.do_z_clearance(Z_CLEARANCE_DEPLOY_PROBE); do_z_clearance(Z_CLEARANCE_DEPLOY_PROBE);
})) return restore_ubl_active_state(); })) return restore_ubl_active_state();
// Store the Z position minus the shim height // Store the Z position minus the shim height
z_values[lpos.x][lpos.y] = motion.position.z - thick; z_values[lpos.x][lpos.y] = current_position.z - thick;
// Tell the external UI to update // Tell the external UI to update
TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(location, z_values[lpos.x][lpos.y])); TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(location, z_values[lpos.x][lpos.y]));
@@ -1074,7 +1012,7 @@ void set_message_with_feedback(FSTR_P const fstr) {
if (do_ubl_mesh_map) display_map(param.T_map_type); // show user where we're probing if (do_ubl_mesh_map) display_map(param.T_map_type); // show user where we're probing
restore_ubl_active_state(); restore_ubl_active_state();
motion.blocking_move_xy_z(pos, Z_CLEARANCE_DEPLOY_PROBE); do_blocking_move_to_xy_z(pos, Z_CLEARANCE_DEPLOY_PROBE);
} }
/** /**
@@ -1095,7 +1033,7 @@ void set_message_with_feedback(FSTR_P const fstr) {
mesh_index_pair location; mesh_index_pair location;
if (!motion.can_reach(pos)) { if (!position_is_reachable(pos)) {
SERIAL_ECHOLNPGM("(X,Y) outside printable radius."); SERIAL_ECHOLNPGM("(X,Y) outside printable radius.");
return; return;
} }
@@ -1105,7 +1043,7 @@ void set_message_with_feedback(FSTR_P const fstr) {
LCD_MESSAGE(MSG_UBL_FINE_TUNE_MESH); LCD_MESSAGE(MSG_UBL_FINE_TUNE_MESH);
ui.capture(); // Take over control of the LCD encoder ui.capture(); // Take over control of the LCD encoder
motion.blocking_move_xy_z(pos, Z_TWEEN_SAFE_CLEARANCE); // Move to the given XY with probe clearance do_blocking_move_to_xy_z(pos, Z_TWEEN_SAFE_CLEARANCE); // Move to the given XY with probe clearance
MeshFlags done_flags{0}; MeshFlags done_flags{0};
const xy_int8_t &lpos = location.pos; const xy_int8_t &lpos = location.pos;
@@ -1124,18 +1062,18 @@ void set_message_with_feedback(FSTR_P const fstr) {
// location is used on the next loop // location is used on the next loop
const xyz_pos_t raw = { get_mesh_x(lpos.x), get_mesh_y(lpos.y), Z_TWEEN_SAFE_CLEARANCE }; const xyz_pos_t raw = { get_mesh_x(lpos.x), get_mesh_y(lpos.y), Z_TWEEN_SAFE_CLEARANCE };
if (!motion.can_reach(raw)) break; // SHOULD NOT OCCUR (find_closest_mesh_point_of_type only returns reachable) if (!position_is_reachable(raw)) break; // SHOULD NOT OCCUR (find_closest_mesh_point_of_type only returns reachable)
motion.blocking_move(raw); // Move the nozzle to the edit point with probe clearance do_blocking_move_to(raw); // Move the nozzle to the edit point with probe clearance
TERN_(UBL_MESH_EDIT_MOVES_Z, motion.blocking_move_z(h_offset)); // Move Z to the given 'H' offset before editing TERN_(UBL_MESH_EDIT_MOVES_Z, do_blocking_move_to_z(h_offset)); // Move Z to the given 'H' offset before editing
KEEPALIVE_STATE(PAUSED_FOR_USER); KEEPALIVE_STATE(PAUSED_FOR_USER);
if (do_ubl_mesh_map) display_map(param.T_map_type); // Display the current point if (do_ubl_mesh_map) display_map(param.T_map_type); // Display the current point
#if IS_TFTGLCD_PANEL #if IS_TFTGLCD_PANEL
ui.ubl_plot(lpos.x, lpos.y); // Update plot screen ui.ubl_plot(lpos.x, lpos.y); // update plot screen
#endif #endif
ui.refresh(); ui.refresh();
@@ -1146,23 +1084,23 @@ void set_message_with_feedback(FSTR_P const fstr) {
ui.ubl_mesh_edit_start(new_z); ui.ubl_mesh_edit_start(new_z);
motion.set_soft_endstop_loose(true); SET_SOFT_ENDSTOP_LOOSE(true);
do { do {
marlin.idle_no_sleep(); marlin.idle_no_sleep();
new_z = ui.ubl_mesh_value(); new_z = ui.ubl_mesh_value();
TERN_(UBL_MESH_EDIT_MOVES_Z, motion.blocking_move_z(h_offset + new_z)); // Move the nozzle as the point is edited TERN_(UBL_MESH_EDIT_MOVES_Z, do_blocking_move_to_z(h_offset + new_z)); // Move the nozzle as the point is edited
SERIAL_FLUSH(); // Prevent host M105 buffer overrun. SERIAL_FLUSH(); // Prevent host M105 buffer overrun.
} while (!ui.button_pressed()); } while (!ui.button_pressed());
motion.set_soft_endstop_loose(false); SET_SOFT_ENDSTOP_LOOSE(false);
if (!lcd_map_control) ui.return_to_status(); // Just editing a single point? Return to status if (!lcd_map_control) ui.return_to_status(); // Just editing a single point? Return to status
// Button held down? Abort editing // Button held down? Abort editing
if (_click_and_hold([]{ if (_click_and_hold([]{
ui.return_to_status(); ui.return_to_status();
motion.do_z_clearance(Z_TWEEN_SAFE_CLEARANCE); do_z_clearance(Z_TWEEN_SAFE_CLEARANCE);
set_message_with_feedback(GET_TEXT_F(MSG_EDITING_STOPPED)); set_message_with_feedback(GET_TEXT_F(MSG_EDITING_STOPPED));
})) break; })) break;
@@ -1182,7 +1120,7 @@ void set_message_with_feedback(FSTR_P const fstr) {
if (do_ubl_mesh_map) display_map(param.T_map_type); if (do_ubl_mesh_map) display_map(param.T_map_type);
restore_ubl_active_state(); restore_ubl_active_state();
motion.blocking_move_xy_z(pos, Z_TWEEN_SAFE_CLEARANCE); do_blocking_move_to_xy_z(pos, Z_TWEEN_SAFE_CLEARANCE);
LCD_MESSAGE(MSG_UBL_DONE_EDITING_MESH); LCD_MESSAGE(MSG_UBL_DONE_EDITING_MESH);
SERIAL_ECHOLNPGM("Done Editing Mesh"); SERIAL_ECHOLNPGM("Done Editing Mesh");
@@ -1253,9 +1191,9 @@ bool unified_bed_leveling::G29_parse_parameters() {
} }
param.XY_seen.x = parser.seenval('X'); param.XY_seen.x = parser.seenval('X');
float sx = param.XY_seen.x ? parser.value_float() : DIFF_TERN(HAS_BED_PROBE, motion.position.x, probe.offset.x); float sx = param.XY_seen.x ? parser.value_float() : current_position.x;
param.XY_seen.y = parser.seenval('Y'); param.XY_seen.y = parser.seenval('Y');
float sy = param.XY_seen.y ? parser.value_float() : DIFF_TERN(HAS_BED_PROBE, motion.position.y, probe.offset.y); float sy = param.XY_seen.y ? parser.value_float() : current_position.y;
if (param.XY_seen.x != param.XY_seen.y) { if (param.XY_seen.x != param.XY_seen.y) {
SERIAL_ECHOLNPGM("Both X & Y locations must be specified.\n"); SERIAL_ECHOLNPGM("Both X & Y locations must be specified.\n");
@@ -1264,8 +1202,8 @@ bool unified_bed_leveling::G29_parse_parameters() {
// If X or Y are not valid, use center of the bed values // If X or Y are not valid, use center of the bed values
// (for UBL_HILBERT_CURVE default to lower-left corner instead) // (for UBL_HILBERT_CURVE default to lower-left corner instead)
if (!COORDINATE_OKAY(sx, X_MIN_BED, X_MAX_BED)) sx = TERN(UBL_HILBERT_CURVE, 0, DIFF_TERN(HAS_BED_PROBE, X_CENTER, probe.offset.x)); if (!COORDINATE_OKAY(sx, X_MIN_BED, X_MAX_BED)) sx = TERN(UBL_HILBERT_CURVE, 0, X_CENTER);
if (!COORDINATE_OKAY(sy, Y_MIN_BED, Y_MAX_BED)) sy = TERN(UBL_HILBERT_CURVE, 0, DIFF_TERN(HAS_BED_PROBE, Y_CENTER, probe.offset.y)); if (!COORDINATE_OKAY(sy, Y_MIN_BED, Y_MAX_BED)) sy = TERN(UBL_HILBERT_CURVE, 0, Y_CENTER);
if (err_flag) return UBL_ERR; if (err_flag) return UBL_ERR;
@@ -1420,7 +1358,7 @@ mesh_index_pair unified_bed_leveling::find_furthest_invalid_mesh_point() {
// Also for round beds, there are grid points outside the bed the nozzle can't reach. // Also for round beds, there are grid points outside the bed the nozzle can't reach.
// Prune them from the list and ignore them till the next Phase (manual nozzle probing). // Prune them from the list and ignore them till the next Phase (manual nozzle probing).
if (!(d->probe_relative ? probe.can_reach(mpos) : motion.can_reach(mpos))) if (!(d->probe_relative ? probe.can_reach(mpos) : position_is_reachable(mpos)))
return false; return false;
d->closest.pos.set(i, j); d->closest.pos.set(i, j);
return true; return true;
@@ -1464,12 +1402,12 @@ mesh_index_pair unified_bed_leveling::find_closest_mesh_point_of_type(const Mesh
// Also for round beds, there are grid points outside the bed the nozzle can't reach. // Also for round beds, there are grid points outside the bed the nozzle can't reach.
// Prune them from the list and ignore them till the next Phase (manual nozzle probing). // Prune them from the list and ignore them till the next Phase (manual nozzle probing).
if (!(probe_relative ? probe.can_reach(mpos) : motion.can_reach(mpos))) if (!(probe_relative ? probe.can_reach(mpos) : position_is_reachable(mpos)))
continue; continue;
// Reachable. Check if it's the best_so_far location to the nozzle. // Reachable. Check if it's the best_so_far location to the nozzle.
const xy_pos_t diff = motion.position - mpos; const xy_pos_t diff = current_position - mpos;
const float distance = (ref - mpos).magnitude() + diff.magnitude() * 0.1f; const float distance = (ref - mpos).magnitude() + diff.magnitude() * 0.1f;
// factor in the distance from the current location for the normal case // factor in the distance from the current location for the normal case
@@ -1597,10 +1535,10 @@ void unified_bed_leveling::smart_fill_mesh() {
#ifndef G29J_MESH_TILT_MARGIN #ifndef G29J_MESH_TILT_MARGIN
#define G29J_MESH_TILT_MARGIN 0 #define G29J_MESH_TILT_MARGIN 0
#endif #endif
const float x_min = _MAX((X_MIN_POS) + (G29J_MESH_TILT_MARGIN), mesh_min.x, probe.min_x()), const float x_min = _MAX((X_MIN_POS) + (G29J_MESH_TILT_MARGIN), MESH_MIN_X, probe.min_x()),
x_max = _MIN((X_MAX_POS) - (G29J_MESH_TILT_MARGIN), mesh_max.x, probe.max_x()), x_max = _MIN((X_MAX_POS) - (G29J_MESH_TILT_MARGIN), MESH_MAX_X, probe.max_x()),
y_min = _MAX((Y_MIN_POS) + (G29J_MESH_TILT_MARGIN), mesh_min.y, probe.min_y()), y_min = _MAX((Y_MIN_POS) + (G29J_MESH_TILT_MARGIN), MESH_MIN_Y, probe.min_y()),
y_max = _MIN((Y_MAX_POS) - (G29J_MESH_TILT_MARGIN), mesh_max.y, probe.max_y()), y_max = _MIN((Y_MAX_POS) - (G29J_MESH_TILT_MARGIN), MESH_MAX_Y, probe.max_y()),
dx = (x_max - x_min) / (param.J_grid_size - 1), dx = (x_max - x_min) / (param.J_grid_size - 1),
dy = (y_max - y_min) / (param.J_grid_size - 1); dy = (y_max - y_min) / (param.J_grid_size - 1);
@@ -1822,23 +1760,25 @@ void unified_bed_leveling::smart_fill_mesh() {
SERIAL_ECHOLNPGM("Probe Offset M851 Z", p_float_t(probe.offset.z, 7)); SERIAL_ECHOLNPGM("Probe Offset M851 Z", p_float_t(probe.offset.z, 7));
#endif #endif
SERIAL_ECHOLNPGM("mesh_min ", mesh_min.x, ", ", mesh_min.y); serial_delay(50); SERIAL_ECHOLNPGM("MESH_MIN_X " STRINGIFY(MESH_MIN_X) "=", MESH_MIN_X); serial_delay(50);
SERIAL_ECHOLNPGM("mesh_max ", mesh_max.x, ", ", mesh_max.y); serial_delay(50); SERIAL_ECHOLNPGM("MESH_MIN_Y " STRINGIFY(MESH_MIN_Y) "=", MESH_MIN_Y); serial_delay(50);
SERIAL_ECHOLNPGM("GRID_MAX_POINTS_X ", GRID_MAX_POINTS_X); serial_delay(50); SERIAL_ECHOLNPGM("MESH_MAX_X " STRINGIFY(MESH_MAX_X) "=", MESH_MAX_X); serial_delay(50);
SERIAL_ECHOLNPGM("GRID_MAX_POINTS_Y ", GRID_MAX_POINTS_Y); serial_delay(50); SERIAL_ECHOLNPGM("MESH_MAX_Y " STRINGIFY(MESH_MAX_Y) "=", MESH_MAX_Y); serial_delay(50);
SERIAL_ECHOLNPGM("GRID_MAX_POINTS_X ", GRID_MAX_POINTS_X); serial_delay(50);
SERIAL_ECHOLNPGM("GRID_MAX_POINTS_Y ", GRID_MAX_POINTS_Y); serial_delay(50);
SERIAL_ECHOLNPGM("MESH_X_DIST ", MESH_X_DIST); SERIAL_ECHOLNPGM("MESH_X_DIST ", MESH_X_DIST);
SERIAL_ECHOLNPGM("MESH_Y_DIST ", MESH_Y_DIST); serial_delay(50); SERIAL_ECHOLNPGM("MESH_Y_DIST ", MESH_Y_DIST); serial_delay(50);
SERIAL_ECHOPGM("X-Axis Mesh Points at: "); SERIAL_ECHOPGM("X-Axis Mesh Points at: ");
for (uint8_t i = 0; i < GRID_MAX_POINTS_X; ++i) { for (uint8_t i = 0; i < GRID_MAX_POINTS_X; ++i) {
SERIAL_ECHO(p_float_t(motion.logical_x(get_mesh_x(i)), 3), F(" ")); SERIAL_ECHO(p_float_t(LOGICAL_X_POSITION(get_mesh_x(i)), 3), F(" "));
serial_delay(25); serial_delay(25);
} }
SERIAL_EOL(); SERIAL_EOL();
SERIAL_ECHOPGM("Y-Axis Mesh Points at: "); SERIAL_ECHOPGM("Y-Axis Mesh Points at: ");
for (uint8_t i = 0; i < GRID_MAX_POINTS_Y; ++i) { for (uint8_t i = 0; i < GRID_MAX_POINTS_Y; ++i) {
SERIAL_ECHO(p_float_t(motion.logical_y(get_mesh_y(i)), 3), F(" ")); SERIAL_ECHO(p_float_t(LOGICAL_Y_POSITION(get_mesh_y(i)), 3), F(" "));
serial_delay(25); serial_delay(25);
} }
SERIAL_EOL(); SERIAL_EOL();
+24 -24
View File
@@ -53,11 +53,11 @@
* just do the required Z-Height correction, call the Planner's buffer_line() routine, and leave * just do the required Z-Height correction, call the Planner's buffer_line() routine, and leave
*/ */
#if HAS_POSITION_MODIFIERS #if HAS_POSITION_MODIFIERS
xyze_pos_t start = motion.position, end = motion.destination; xyze_pos_t start = current_position, end = destination;
planner.apply_modifiers(start); planner.apply_modifiers(start);
planner.apply_modifiers(end); planner.apply_modifiers(end);
#else #else
const xyze_pos_t &start = motion.position, &end = motion.destination; const xyze_pos_t &start = current_position, &end = destination;
#endif #endif
const xy_uint8_t istart = cell_indexes(start), iend = cell_indexes(end); const xy_uint8_t istart = cell_indexes(start), iend = cell_indexes(end);
@@ -78,7 +78,7 @@
end.z += UBL_Z_RAISE_WHEN_OFF_MESH; end.z += UBL_Z_RAISE_WHEN_OFF_MESH;
planner.buffer_segment(end, scaled_fr_mm_s, extruder); planner.buffer_segment(end, scaled_fr_mm_s, extruder);
motion.position = motion.destination; current_position = destination;
return; return;
} }
#endif #endif
@@ -96,7 +96,7 @@
// Replace NAN corrections with 0.0 to prevent NAN propagation. // Replace NAN corrections with 0.0 to prevent NAN propagation.
if (!isnan(z0)) end.z += z0; if (!isnan(z0)) end.z += z0;
planner.buffer_segment(end, scaled_fr_mm_s, extruder); planner.buffer_segment(end, scaled_fr_mm_s, extruder);
motion.position = motion.destination; current_position = destination;
return; return;
} }
@@ -190,10 +190,10 @@
} }
// At the final destination? Usually not, but when on a Y Mesh Line it's completed. // At the final destination? Usually not, but when on a Y Mesh Line it's completed.
if (xy_pos_t(motion.position) != xy_pos_t(end)) if (xy_pos_t(current_position) != xy_pos_t(end))
goto FINAL_MOVE; goto FINAL_MOVE;
motion.position = motion.destination; current_position = destination;
return; return;
} }
@@ -240,10 +240,10 @@
DEBUG_ECHOLNPGM("[ubl] skip Y segment"); DEBUG_ECHOLNPGM("[ubl] skip Y segment");
} }
if (xy_pos_t(motion.position) != xy_pos_t(end)) if (xy_pos_t(current_position) != xy_pos_t(end))
goto FINAL_MOVE; goto FINAL_MOVE;
motion.position = motion.destination; current_position = destination;
return; return;
} }
@@ -324,10 +324,10 @@
if (cnt.x < 0 || cnt.y < 0) break; // Too far! Exit the loop and go to FINAL_MOVE if (cnt.x < 0 || cnt.y < 0) break; // Too far! Exit the loop and go to FINAL_MOVE
} }
if (xy_pos_t(motion.position) != xy_pos_t(end)) if (xy_pos_t(current_position) != xy_pos_t(end))
goto FINAL_MOVE; goto FINAL_MOVE;
motion.position = motion.destination; current_position = destination;
} }
#else // UBL_SEGMENTED #else // UBL_SEGMENTED
@@ -347,15 +347,15 @@
/** /**
* Prepare a segmented linear move for DELTA/SCARA/CARTESIAN with UBL and FADE semantics. * Prepare a segmented linear move for DELTA/SCARA/CARTESIAN with UBL and FADE semantics.
* This calls planner.buffer_segment multiple times for small incremental moves. * This calls planner.buffer_segment multiple times for small incremental moves.
* Returns true if did NOT move, false if moved (requires motion.position update). * Returns true if did NOT move, false if moved (requires current_position update).
*/ */
bool __O2 unified_bed_leveling::line_to_destination_segmented(const feedRate_t scaled_fr_mm_s) { bool __O2 unified_bed_leveling::line_to_destination_segmented(const feedRate_t scaled_fr_mm_s) {
if (!motion.can_reach(motion.destination)) // Fail if moving outside reachable boundary if (!position_is_reachable(destination)) // fail if moving outside reachable boundary
return true; // Did not move, so motion.position still accurate return true; // did not move, so current_position still accurate
const xyze_pos_t total = motion.destination - motion.position; const xyze_pos_t total = destination - current_position;
const float cart_xy_mm_2 = HYPOT2(total.x, total.y), const float cart_xy_mm_2 = HYPOT2(total.x, total.y),
cart_xy_mm = SQRT(cart_xy_mm_2); // Total XY distance cart_xy_mm = SQRT(cart_xy_mm_2); // Total XY distance
@@ -383,22 +383,22 @@
// Note that E segment distance could vary slightly as z mesh height // Note that E segment distance could vary slightly as z mesh height
// changes for each segment, but small enough to ignore. // changes for each segment, but small enough to ignore.
xyze_pos_t raw = motion.position; xyze_pos_t raw = current_position;
// Just do plain segmentation if UBL is inactive or the target is above the fade height // Just do plain segmentation if UBL is inactive or the target is above the fade height
if (!planner.leveling_active || !planner.leveling_active_at_z(motion.destination.z)) { if (!planner.leveling_active || !planner.leveling_active_at_z(destination.z)) {
while (--segments) { while (--segments) {
raw += diff; raw += diff;
planner.buffer_line(raw, scaled_fr_mm_s, motion.extruder, hints); planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, hints);
} }
planner.buffer_line(motion.destination, scaled_fr_mm_s, motion.extruder, hints); planner.buffer_line(destination, scaled_fr_mm_s, active_extruder, hints);
return false; // Did not set current from destination return false; // Did not set current from destination
} }
// Otherwise perform per-segment leveling // Otherwise perform per-segment leveling
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT) #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
const float fade_scaling_factor = planner.fade_scaling_factor_for_z(motion.destination.z); const float fade_scaling_factor = planner.fade_scaling_factor_for_z(destination.z);
#endif #endif
// Move to first segment destination // Move to first segment destination
@@ -414,8 +414,8 @@
// for mesh inset area. // for mesh inset area.
xy_int8_t icell = { xy_int8_t icell = {
int8_t((raw.x - mesh_min.x) * RECIPROCAL(MESH_X_DIST)), int8_t((raw.x - (MESH_MIN_X)) * RECIPROCAL(MESH_X_DIST)),
int8_t((raw.y - mesh_min.y) * RECIPROCAL(MESH_Y_DIST)) int8_t((raw.y - (MESH_MIN_Y)) * RECIPROCAL(MESH_Y_DIST))
}; };
LIMIT(icell.x, 0, GRID_MAX_CELLS_X); LIMIT(icell.x, 0, GRID_MAX_CELLS_X);
LIMIT(icell.y, 0, GRID_MAX_CELLS_Y); LIMIT(icell.y, 0, GRID_MAX_CELLS_Y);
@@ -456,13 +456,13 @@
for (;;) { // for all segments within this mesh cell for (;;) { // for all segments within this mesh cell
if (--segments == 0) raw = motion.destination; // If this is last segment, use destination for exact if (--segments == 0) raw = destination; // if this is last segment, use destination for exact
const float z_cxcy = (z_cxy0 + z_cxym * cell.y) // interpolated mesh z height along cell.x at cell.y const float z_cxcy = (z_cxy0 + z_cxym * cell.y) // interpolated mesh z height along cell.x at cell.y
TERN_(ENABLE_LEVELING_FADE_HEIGHT, * fade_scaling_factor); // apply fade factor to interpolated height TERN_(ENABLE_LEVELING_FADE_HEIGHT, * fade_scaling_factor); // apply fade factor to interpolated height
const float oldz = raw.z; raw.z += z_cxcy; const float oldz = raw.z; raw.z += z_cxcy;
planner.buffer_line(raw, scaled_fr_mm_s, motion.extruder, hints); planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, hints);
raw.z = oldz; raw.z = oldz;
if (segments == 0) // done with last segment if (segments == 0) // done with last segment
@@ -483,7 +483,7 @@
} // segment loop } // segment loop
} // cell loop } // cell loop
return false; // caller will update motion.position return false; // caller will update current_position
} }
#endif // UBL_SEGMENTED #endif // UBL_SEGMENTED
+1 -1
View File
@@ -134,7 +134,7 @@ void ControllerFan::update() {
} while (0) } while (0)
#if ENABLED(FAN_SOFT_PWM) #if ENABLED(FAN_SOFT_PWM)
soft_pwm_speed = speed >> 1; // Controller Fan Soft PWM uses 0-127 as 0-100% so cut the 0-255 range in half. soft_pwm_speed = speed;
#else #else
SET_CONTROLLER_FAN(); SET_CONTROLLER_FAN();
#if PIN_EXISTS(CONTROLLER_FAN2) #if PIN_EXISTS(CONTROLLER_FAN2)
+8 -9
View File
@@ -54,11 +54,10 @@ EmergencyParser emergency_parser;
#endif #endif
#if ENABLED(REALTIME_REPORTING_COMMANDS) #if ENABLED(REALTIME_REPORTING_COMMANDS)
#include "../module/motion.h" // From motion.h, which cannot be included here
#endif void report_current_position_moving();
void quickpause_stepper();
#if ENABLED(SOFT_FEED_HOLD) void quickresume_stepper();
bool realtime_ramping_pause_flag = false;
#endif #endif
void EmergencyParser::update(EmergencyParser::State &state, const uint8_t c) { void EmergencyParser::update(EmergencyParser::State &state, const uint8_t c) {
@@ -151,7 +150,7 @@ void EmergencyParser::update(EmergencyParser::State &state, const uint8_t c) {
case EP_M4: case EP_M4:
switch (c) { switch (c) {
case '1' :state = EP_M41; break; case '1' :state = EP_M41; break;
#if ENABLED(FTM_RESONANCE_TEST) #if ENABLED(FT_MOTION_RESONANCE_TEST)
case '9': state = EP_M49; break; case '9': state = EP_M49; break;
#endif #endif
default: state = EP_IGNORE; default: state = EP_IGNORE;
@@ -223,9 +222,9 @@ void EmergencyParser::update(EmergencyParser::State &state, const uint8_t c) {
case EP_M876SN: hostui.handle_response(M876_reason); break; case EP_M876SN: hostui.handle_response(M876_reason); break;
#endif #endif
#if ENABLED(REALTIME_REPORTING_COMMANDS) #if ENABLED(REALTIME_REPORTING_COMMANDS)
case EP_GRBL_STATUS: motion.report_position_moving(); break; case EP_GRBL_STATUS: report_current_position_moving(); break;
case EP_GRBL_PAUSE: TERN(SOFT_FEED_HOLD, realtime_ramping_pause_flag = true, motion.quickpause_stepper()); break; case EP_GRBL_PAUSE: quickpause_stepper(); break;
case EP_GRBL_RESUME: TERN(SOFT_FEED_HOLD, realtime_ramping_pause_flag = false, motion.quickresume_stepper()); break; case EP_GRBL_RESUME: quickresume_stepper(); break;
#endif #endif
#if ENABLED(SOFT_RESET_VIA_SERIAL) #if ENABLED(SOFT_RESET_VIA_SERIAL)
case EP_KILL: hal.reboot(); break; case EP_KILL: hal.reboot(); break;
-4
View File
@@ -93,7 +93,3 @@ private:
}; };
extern EmergencyParser emergency_parser; extern EmergencyParser emergency_parser;
#if ENABLED(SOFT_FEED_HOLD)
extern bool realtime_ramping_pause_flag;
#endif
+1 -1
View File
@@ -136,7 +136,7 @@ void EasythreedUI::loadButton() {
if (READ(BTN_RETRACT) && READ(BTN_FEED)) { // Switch in center position (stop) if (READ(BTN_RETRACT) && READ(BTN_FEED)) { // Switch in center position (stop)
flag = false; // Restore flag to false flag = false; // Restore flag to false
filament_status = FS_IDLE; // Go back to idle state filament_status = FS_IDLE; // Go back to idle state
motion.quickstop_stepper(); // Hard-stop all the steppers ... now! quickstop_stepper(); // Hard-stop all the steppers ... now!
thermalManager.disable_all_heaters(); // And disable all the heaters thermalManager.disable_all_heaters(); // And disable all the heaters
blink_interval_ms = LED_ON; blink_interval_ms = LED_ON;
} }
+6 -6
View File
@@ -318,9 +318,9 @@ bool I2CPositionEncoder::test_axis() {
// Only works on XYZ Cartesian machines for the time being // Only works on XYZ Cartesian machines for the time being
if (!(encoderAxis == X_AXIS || encoderAxis == Y_AXIS || encoderAxis == Z_AXIS)) return false; if (!(encoderAxis == X_AXIS || encoderAxis == Y_AXIS || encoderAxis == Z_AXIS)) return false;
const float startPosition = motion.soft_endstop.min[encoderAxis] + 10, const float startPosition = soft_endstop.min[encoderAxis] + 10,
endPosition = motion.soft_endstop.max[encoderAxis] - 10; endPosition = soft_endstop.max[encoderAxis] - 10;
const feedRate_t fr_mm_s = FLOOR(motion.homing_feedrate(encoderAxis)); const feedRate_t fr_mm_s = FLOOR(homing_feedrate(encoderAxis));
ec = false; ec = false;
@@ -373,13 +373,13 @@ void I2CPositionEncoder::calibrate_steps_mm(const uint8_t iter) {
int32_t startCount, stopCount; int32_t startCount, stopCount;
const feedRate_t fr_mm_s = motion.homing_feedrate(encoderAxis); const feedRate_t fr_mm_s = homing_feedrate(encoderAxis);
bool oldec = ec; bool oldec = ec;
ec = false; ec = false;
startDistance = 20; startDistance = 20;
endDistance = motion.soft_endstop.max[encoderAxis] - 20; endDistance = soft_endstop.max[encoderAxis] - 20;
travelDistance = endDistance - startDistance; travelDistance = endDistance - startDistance;
xyze_pos_t startCoord, endCoord; xyze_pos_t startCoord, endCoord;
@@ -400,7 +400,7 @@ void I2CPositionEncoder::calibrate_steps_mm(const uint8_t iter) {
delay(250); delay(250);
startCount = get_position(); startCount = get_position();
//motion.blocking_move(endCoord); //do_blocking_move_to(endCoord);
TERN_(HAS_EXTRUDERS, endCoord.e = planner.get_axis_position_mm(E_AXIS)); TERN_(HAS_EXTRUDERS, endCoord.e = planner.get_axis_position_mm(E_AXIS));
planner.buffer_line(endCoord, fr_mm_s, 0); planner.buffer_line(endCoord, fr_mm_s, 0);
+22 -21
View File
@@ -92,14 +92,14 @@ void FWRetract::reset() {
*/ */
void FWRetract::retract(const bool retracting E_OPTARG(bool swapping/*=false*/)) { void FWRetract::retract(const bool retracting E_OPTARG(bool swapping/*=false*/)) {
// Prevent two retracts or recovers in a row // Prevent two retracts or recovers in a row
if (retracted[motion.extruder] == retracting) return; if (retracted[active_extruder] == retracting) return;
// Prevent two swap-retract or recovers in a row // Prevent two swap-retract or recovers in a row
#if HAS_MULTI_EXTRUDER #if HAS_MULTI_EXTRUDER
// Allow G10 S1 only after G11 // Allow G10 S1 only after G11
if (swapping && retracted_swap[motion.extruder] == retracting) return; if (swapping && retracted_swap[active_extruder] == retracting) return;
// G11 priority to recover the long retract if activated // G11 priority to recover the long retract if activated
if (!retracting) swapping = retracted_swap[motion.extruder]; if (!retracting) swapping = retracted_swap[active_extruder];
#else #else
constexpr bool swapping = false; constexpr bool swapping = false;
#endif #endif
@@ -108,7 +108,7 @@ void FWRetract::retract(const bool retracting E_OPTARG(bool swapping/*=false*/))
SERIAL_ECHOLNPGM( SERIAL_ECHOLNPGM(
"retracting ", AS_DIGIT(retracting), "retracting ", AS_DIGIT(retracting),
" swapping ", swapping, " swapping ", swapping,
" active extruder ", motion.extruder " active extruder ", active_extruder
); );
EXTRUDER_LOOP() { EXTRUDER_LOOP() {
SERIAL_ECHOLNPGM("retracted[", e, "] ", AS_DIGIT(retracted[e])); SERIAL_ECHOLNPGM("retracted[", e, "] ", AS_DIGIT(retracted[e]));
@@ -116,8 +116,8 @@ void FWRetract::retract(const bool retracting E_OPTARG(bool swapping/*=false*/))
SERIAL_ECHOLNPGM("retracted_swap[", e, "] ", AS_DIGIT(retracted_swap[e])); SERIAL_ECHOLNPGM("retracted_swap[", e, "] ", AS_DIGIT(retracted_swap[e]));
#endif #endif
} }
SERIAL_ECHOLNPGM("motion.position.z ", motion.position.z); SERIAL_ECHOLNPGM("current_position.z ", current_position.z);
SERIAL_ECHOLNPGM("motion.position.e ", motion.position.e); SERIAL_ECHOLNPGM("current_position.e ", current_position.e);
SERIAL_ECHOLNPGM("current_hop ", current_hop); SERIAL_ECHOLNPGM("current_hop ", current_hop);
//*/ //*/
@@ -125,7 +125,7 @@ void FWRetract::retract(const bool retracting E_OPTARG(bool swapping/*=false*/))
* (swapping ? settings.swap_retract_length : settings.retract_length); * (swapping ? settings.swap_retract_length : settings.retract_length);
// The current position will be the destination for E and Z moves // The current position will be the destination for E and Z moves
motion.destination = motion.position; destination = current_position;
#if ENABLED(RETRACT_SYNC_MIXING) #if ENABLED(RETRACT_SYNC_MIXING)
const uint8_t old_mixing_tool = mixer.get_current_vtool(); const uint8_t old_mixing_tool = mixer.get_current_vtool();
@@ -135,8 +135,8 @@ void FWRetract::retract(const bool retracting E_OPTARG(bool swapping/*=false*/))
const feedRate_t fr_max_z = planner.settings.max_feedrate_mm_s[Z_AXIS]; const feedRate_t fr_max_z = planner.settings.max_feedrate_mm_s[Z_AXIS];
if (retracting) { if (retracting) {
// Retract by moving from a faux E position back to the current E position // Retract by moving from a faux E position back to the current E position
current_retract[motion.extruder] = base_retract; current_retract[active_extruder] = base_retract;
motion.prepare_internal_move_to_destination( // Set current from destination prepare_internal_move_to_destination( // set current from destination
MUL_TERN(RETRACT_SYNC_MIXING, settings.retract_feedrate_mm_s, MIXING_STEPPERS) MUL_TERN(RETRACT_SYNC_MIXING, settings.retract_feedrate_mm_s, MIXING_STEPPERS)
); );
@@ -144,7 +144,7 @@ void FWRetract::retract(const bool retracting E_OPTARG(bool swapping/*=false*/))
if (!current_hop && settings.retract_zraise > 0.01f) { // Apply hop only once if (!current_hop && settings.retract_zraise > 0.01f) { // Apply hop only once
current_hop += settings.retract_zraise; // Add to the hop total (again, only once) current_hop += settings.retract_zraise; // Add to the hop total (again, only once)
// Raise up, set_current_to_destination. Maximum Z feedrate // Raise up, set_current_to_destination. Maximum Z feedrate
motion.prepare_internal_move_to_destination(fr_max_z); prepare_internal_move_to_destination(fr_max_z);
} }
} }
else { else {
@@ -152,42 +152,43 @@ void FWRetract::retract(const bool retracting E_OPTARG(bool swapping/*=false*/))
if (current_hop) { if (current_hop) {
current_hop = 0; current_hop = 0;
// Lower Z, set_current_to_destination. Maximum Z feedrate // Lower Z, set_current_to_destination. Maximum Z feedrate
motion.prepare_internal_move_to_destination(fr_max_z); prepare_internal_move_to_destination(fr_max_z);
} }
// Adjust the current E position by the extra amount to recover
// Sync the planner position so the extra amount is recovered
const float extra_recover = swapping ? settings.swap_retract_recover_extra : settings.retract_recover_extra; const float extra_recover = swapping ? settings.swap_retract_recover_extra : settings.retract_recover_extra;
if (extra_recover) motion.set_and_sync_e(motion.position.e - extra_recover); if (extra_recover) {
current_position.e -= extra_recover; // Adjust the current E position by the extra amount to recover
sync_plan_position_e(); // Sync the planner position so the extra amount is recovered
}
current_retract[motion.extruder] = 0; current_retract[active_extruder] = 0;
// Recover E, set_current_to_destination // Recover E, set_current_to_destination
const feedRate_t fr_mm_s = swapping ? settings.swap_retract_recover_feedrate_mm_s : settings.retract_recover_feedrate_mm_s; const feedRate_t fr_mm_s = swapping ? settings.swap_retract_recover_feedrate_mm_s : settings.retract_recover_feedrate_mm_s;
motion.prepare_internal_move_to_destination(MUL_TERN(RETRACT_SYNC_MIXING, fr_mm_s, MIXING_STEPPERS)); prepare_internal_move_to_destination(MUL_TERN(RETRACT_SYNC_MIXING, fr_mm_s, MIXING_STEPPERS));
} }
TERN_(RETRACT_SYNC_MIXING, mixer.T(old_mixing_tool)); // Restore original mixing tool TERN_(RETRACT_SYNC_MIXING, mixer.T(old_mixing_tool)); // Restore original mixing tool
retracted.set(motion.extruder, retracting); // Active extruder now retracted / recovered retracted.set(active_extruder, retracting); // Active extruder now retracted / recovered
// If swap retract/recover update the retracted_swap flag too // If swap retract/recover update the retracted_swap flag too
#if HAS_MULTI_EXTRUDER #if HAS_MULTI_EXTRUDER
if (swapping) retracted_swap.set(motion.extruder, retracting); if (swapping) retracted_swap.set(active_extruder, retracting);
#endif #endif
/* // debugging /* // debugging
SERIAL_ECHOLNPGM("retracting ", AS_DIGIT(retracting)); SERIAL_ECHOLNPGM("retracting ", AS_DIGIT(retracting));
SERIAL_ECHOLNPGM("swapping ", AS_DIGIT(swapping)); SERIAL_ECHOLNPGM("swapping ", AS_DIGIT(swapping));
SERIAL_ECHOLNPGM("motion.extruder ", motion.extruder); SERIAL_ECHOLNPGM("active_extruder ", active_extruder);
EXTRUDER_LOOP() { EXTRUDER_LOOP() {
SERIAL_ECHOLNPGM("retracted[", e, "] ", AS_DIGIT(retracted[e])); SERIAL_ECHOLNPGM("retracted[", e, "] ", AS_DIGIT(retracted[e]));
#if HAS_MULTI_EXTRUDER #if HAS_MULTI_EXTRUDER
SERIAL_ECHOLNPGM("retracted_swap[", e, "] ", AS_DIGIT(retracted_swap[e])); SERIAL_ECHOLNPGM("retracted_swap[", e, "] ", AS_DIGIT(retracted_swap[e]));
#endif #endif
} }
SERIAL_ECHOLNPGM("motion.position.z ", motion.position.z); SERIAL_ECHOLNPGM("current_position.z ", current_position.z);
SERIAL_ECHOLNPGM("motion.position.e ", motion.position.e); SERIAL_ECHOLNPGM("current_position.e ", current_position.e);
SERIAL_ECHOLNPGM("current_hop ", current_hop); SERIAL_ECHOLNPGM("current_hop ", current_hop);
//*/ //*/
} }

Some files were not shown because too many files have changed in this diff Show More