diff --git a/.editorconfig b/.editorconfig
index a0fa3eff170e..57a5b2fb5ea4 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -4,16 +4,20 @@ root = true
[{*.patch,syntax_test_*}]
trim_trailing_whitespace = false
-[{*.c,*.cpp,*.h}]
+[{*.c,*.cpp,*.h,*.ino}]
charset = utf-8
-[{*.c,*.cpp,*.h,Makefile}]
+[{*.c,*.cpp,*.h,*.ino,Makefile}]
trim_trailing_whitespace = true
insert_final_newline = true
end_of_line = lf
indent_style = space
indent_size = 2
-[{*.py,*.conf,*.sublime-project}]
+[{*.py}]
+indent_style = space
+indent_size = 4
+
+[{*.conf,*.sublime-project}]
indent_style = tab
indent_size = 4
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
new file mode 100644
index 000000000000..efc5972325f6
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -0,0 +1,178 @@
+name: 🪲 Report a bug
+description: Create a bug report to help improve Marlin Firmware
+title: "[BUG] (bug summary)"
+body:
+ - type: markdown
+ attributes:
+ value: >
+ Do you want to ask a question? Are you looking for support? Please use one of the [support links](https://github.com/MarlinFirmware/Marlin/issues/new/choose).
+
+ - type: markdown
+ attributes:
+ value: |
+ **Thank you for reporting a bug in Marlin Firmware!**
+
+ ## Before Reporting a Bug
+
+ - Read and understand Marlin's [Code of Conduct](https://github.com/MarlinFirmware/Marlin/blob/bugfix-2.1.x/.github/code_of_conduct.md). You are expected to comply with it, including treating everyone with respect.
+
+ - Test with the [`bugfix-2.1.x` branch](https://github.com/MarlinFirmware/Marlin/archive/bugfix-2.1.x.zip) to see whether the issue still exists.
+
+ ## Instructions
+
+ Please follow the instructions below. Failure to do so may result in your issue being closed. See [Contributing to Marlin](https://github.com/MarlinFirmware/Marlin/blob/bugfix-2.1.x/.github/contributing.md) for additional guidelines.
+
+ 1. Provide a good title starting with [BUG].
+ 2. Fill out all sections of this bug report form.
+ 3. Always attach configuration files so we can build and test your setup.
+
+ - type: dropdown
+ attributes:
+ label: Did you test the latest `bugfix-2.1.x` code?
+ description: >-
+ Always try the latest code to make sure the issue you are reporting is not already fixed. To download
+ the latest code just [click this link](https://github.com/MarlinFirmware/Marlin/archive/bugfix-2.1.x.zip).
+ options:
+ - Yes, and the problem still exists.
+ - No, but I will test it now!
+ validations:
+ required: true
+
+ - type: markdown
+ attributes:
+ value: |
+ # Bug Details
+
+ - type: textarea
+ attributes:
+ label: Bug Description
+ description: >-
+ Describe the bug in this section. Tell us what you were trying to do and what
+ happened that you did not expect. Provide a clear and concise description of the
+ problem and include as many details as possible.
+
+ When pasting formatted text don't forget to put ` ``` ` (on its own line) before and after to make it readable.
+ placeholder: |
+ Marlin doesn't work.
+ validations:
+ required: true
+
+ - type: input
+ attributes:
+ label: Bug Timeline
+ description: Is this a new bug or an old issue? When did it first start?
+
+ - type: textarea
+ attributes:
+ label: Expected behavior
+ description: >-
+ What did you expect to happen?
+ placeholder: I expected it to move left.
+
+ - type: textarea
+ attributes:
+ label: Actual behavior
+ description: What actually happened instead?
+ placeholder: It moved right instead of left.
+
+ - type: textarea
+ attributes:
+ label: Steps to Reproduce
+ description: >-
+ Please describe the steps needed to reproduce the issue.
+ placeholder: |
+ 1. [First Step] ...
+ 2. [Second Step] ...
+ 3. [and so on] ...
+
+ - type: markdown
+ attributes:
+ value: |
+ # Your Setup
+
+ - type: input
+ attributes:
+ label: Version of Marlin Firmware
+ description: "See the About Menu on the LCD or the output of `M115`. NOTE: For older releases we only patch critical bugs."
+ validations:
+ required: true
+
+ - type: input
+ attributes:
+ label: Printer model
+ description: Creality Ender 3, Prusa mini, or Kossel Delta?
+
+ - type: input
+ attributes:
+ label: Electronics
+ description: Stock electronics, upgrade board, or something else?
+
+ - type: input
+ attributes:
+ label: Add-ons
+ description: Please list any hardware add-ons that could be involved.
+
+ - type: dropdown
+ attributes:
+ label: Bed Leveling
+ description: What kind of bed leveling compensation are you using?
+ options:
+ - UBL Bilinear mesh
+ - ABL Bilinear mesh
+ - ABL Linear grid
+ - ABL 3-point
+ - MBL Manual Bed Leveling
+ - No Bed Leveling
+
+ - type: dropdown
+ attributes:
+ label: Your Slicer
+ description: Do you use Slic3r, Prusa Slicer, Simplify3D, IdeaMaker...?
+ options:
+ - Slic3r
+ - Simplify3D
+ - Prusa Slicer
+ - IdeaMaker
+ - Cura
+ - Other (explain below)
+
+ - type: dropdown
+ attributes:
+ label: Host Software
+ description: Do you use OctoPrint, Repetier Host, Pronterface...?
+ options:
+ - SD Card (headless)
+ - Repetier Host
+ - OctoPrint
+ - Pronterface
+ - Cura
+ - Same as my slicer
+ - Other (explain below)
+
+ - type: markdown
+ attributes:
+ value: |
+ # Attachments
+
+ - type: checkboxes
+ attributes:
+ label: Don't forget to include
+ options:
+ - label: A ZIP file containing your `Configuration.h` and `Configuration_adv.h`.
+ required: true
+
+ - type: markdown
+ attributes:
+ value: |
+ ### Optional items to include:
+ - 'Log output from the host. (`M111 S247` for maximum logging.)'
+ - Images or videos demonstrating the problem, if it helps to make it clear.
+ - A G-Code file that exposes the problem, if not affecting _all_ G-code.
+
+ - type: textarea
+ attributes:
+ label: Additional information & file uploads
+ description: >-
+ If you've made any other modifications to the firmware, please describe them in detail.
+
+ When pasting formatted text don't forget to put ` ``` ` (on its own line) before and after to make it readable.
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 000000000000..1fe68966fbba
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,20 @@
+blank_issues_enabled: false
+contact_links:
+ - name: 📖 Marlin Documentation
+ url: https://marlinfw.org/
+ about: Lots of documentation on installing and using Marlin.
+ - name: 👤 MarlinFirmware Facebook group
+ url: https://www.facebook.com/groups/1049718498464482
+ about: Please ask and answer questions here.
+ - name: 🕹 Marlin on Discord
+ url: https://discord.gg/n5NJ59y
+ about: Join the Discord server for support and discussion.
+ - name: 🔗 Marlin Discussion Forum
+ url: https://reprap.org/forum/list.php?415
+ about: A searchable web forum hosted by RepRap dot org.
+ - name: 📺 Marlin Videos on YouTube
+ url: https://www.youtube.com/results?search_query=marlin+firmware
+ about: Tutorials and more from Marlin users all around the world. Great for new users!
+ - name: 💸 Want to donate?
+ url: https://www.thinkyhead.com/donate-to-marlin
+ about: Please take a look at the various options to support Marlin Firmware's development financially!
diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml
new file mode 100644
index 000000000000..b64383cd48b2
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/feature_request.yml
@@ -0,0 +1,44 @@
+name: ✨ Request a feature
+description: Request a new Marlin Firmware feature
+title: "[FR] (feature summary)"
+labels: 'T: Feature Request'
+body:
+ - type: markdown
+ attributes:
+ value: >
+ Do you want to ask a question? Are you looking for support? Please use one of the [support links](https://github.com/MarlinFirmware/Marlin/issues/new/choose).
+
+ - type: markdown
+ attributes:
+ value: >
+ **Thank you for requesting a new Marlin Firmware feature!**
+
+ ## Before Requesting a Feature
+
+ - Read and understand Marlin's [Code of Conduct](https://github.com/MarlinFirmware/Marlin/blob/master/.github/code_of_conduct.md). You are expected to comply with it, including treating everyone with respect.
+
+ - Check the latest [`bugfix-2.1.x` branch](https://github.com/MarlinFirmware/Marlin/archive/bugfix-2.1.x.zip) to see if the feature already exists.
+
+ - Before you proceed with your request, please consider if it is necessary to make it into a firmware feature, or if it may be better suited for a slicer or host feature.
+
+ - type: textarea
+ attributes:
+ label: Is your feature request related to a problem? Please describe.
+ description: A clear description of the problem (e.g., "I need X but Marlin can't do it [...]").
+
+ - type: textarea
+ attributes:
+ label: Are you looking for hardware support?
+ description: Tell us the printer, board, or peripheral that needs support.
+
+ - type: textarea
+ attributes:
+ label: Describe the feature you want
+ description: A clear description of the feature and how you think it should work.
+ validations:
+ required: true
+
+ - type: textarea
+ attributes:
+ label: Additional context
+ description: Add any other context or screenshots about the feature request here.
diff --git a/.github/contributing.md b/.github/contributing.md
index 6bc7b5a00514..ef1726366a7d 100644
--- a/.github/contributing.md
+++ b/.github/contributing.md
@@ -34,8 +34,11 @@ This project and everyone participating in it is governed by the [Marlin Code of
We have a Message Board and a Facebook group where our knowledgable user community can provide helpful advice if you have questions.
-* [Marlin RepRap forum](https://reprap.org/forum/list.php?415)
-* [MarlinFirmware on Facebook](https://www.facebook.com/groups/1049718498464482/)
+- [Marlin Documentation](https://marlinfw.org) - Official Marlin documentation
+- Facebook Group ["Marlin Firmware"](https://www.facebook.com/groups/1049718498464482/)
+- RepRap.org [Marlin Forum](https://forums.reprap.org/list.php?415)
+- Facebook Group ["Marlin Firmware for 3D Printers"](https://www.facebook.com/groups/3Dtechtalk/)
+- [Marlin Configuration](https://www.youtube.com/results?search_query=marlin+configuration) on YouTube
If chat is more your speed, you can join the MarlinFirmware Discord server:
@@ -50,13 +53,13 @@ If chat is more your speed, you can join the MarlinFirmware Discord server:
This section guides you through submitting a Bug Report for Marlin. Following these guidelines helps maintainers and the community understand your report, reproduce the behavior, and find related reports.
-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.md), 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:** 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?
-Bugs are tracked as [GitHub issues](https://guides.github.com/features/issues/). Use the New Issue button to create an issue and provide the following information by filling in [the template](issue_template.md).
+Bugs are tracked as [GitHub issues](https://guides.github.com/features/issues/). Use the New Issue button to create an issue and provide the following information by filling in [the template](ISSUE_TEMPLATE/bug_report.yml).
Explain the problem and include additional details to help maintainers reproduce the problem:
@@ -88,12 +91,12 @@ Include details about your configuration and environment:
This section guides you through submitting a suggestion for Marlin, including completely new features and minor improvements to existing functionality. Following these guidelines helps maintainers and the community understand your suggestion and find related suggestions.
-Before creating a suggestion, please check [this list](#before-submitting-a-suggestion) as you might find out that you don't need to create one. When you are creating an enhancement suggestion, please [include as many details as possible](#how-do-i-submit-a-good-enhancement-suggestion). Fill in [the template](issue_template.md), including the steps that you imagine you would take if the feature you're requesting existed.
+Before creating a suggestion, please check [this list](https://github.com/MarlinFirmware/Marlin/issues?q=is%3Aopen+is%3Aissue+label%3A%22T%3A+Feature+Request%22) as you might find out that you don't need to create one. When you are creating an enhancement suggestion, please [include as many details as possible](#how-do-i-submit-a-good-feature-request). Fill in [the template](ISSUE_TEMPLATE/feature_request.yml), including the steps that you imagine you would take if the feature you're requesting existed.
#### 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).
-* **Perform a [cursory search](https://github.com/MarlinFirmware/Marlin/issues?q=is%3Aissue)** 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?
@@ -116,7 +119,7 @@ Unsure where to begin contributing to Marlin? You can start by looking through t
### Pull Requests
-Pull Requests should always be targeted to working branches (e.g., `bugfix-1.1.x` and/or `bugfix-2.0.x`) and never to release branches (e.g., `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).
* Don't include issue numbers in the PR title.
diff --git a/.github/issue_template.md b/.github/issue_template.md
deleted file mode 100644
index 6cb34b8f588a..000000000000
--- a/.github/issue_template.md
+++ /dev/null
@@ -1,35 +0,0 @@
-
-
-### Description
-
-
-
-### Steps to Reproduce
-
-
-
-1. [First Step]
-2. [Second Step]
-3. [and so on...]
-
-**Expected behavior:** [What you expect to happen]
-
-**Actual behavior:** [What actually happens]
-
-#### Additional Information
-
-* Include a ZIP file containing your `Configuration.h` and `Configuration_adv.h` files.
-* Provide pictures or links to videos that clearly demonstrate the issue.
-* See [How Can I Contribute](#how-can-i-contribute) for additional guidelines.
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index d82fb0f9e37b..cd5158b3ce8c 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -1,23 +1,33 @@
-### Requirements
+
### Description
+### Requirements
+
+
+
### Benefits
-
+
### Configurations
-
+
### Related Issues
-
+
diff --git a/.github/workflows/bump-date.yml b/.github/workflows/bump-date.yml
new file mode 100644
index 000000000000..51b58ad493f0
--- /dev/null
+++ b/.github/workflows/bump-date.yml
@@ -0,0 +1,59 @@
+#
+# bump-date.yml
+# Bump the distribution date once per day
+#
+
+name: Bump Distribution Date
+
+on:
+ schedule:
+ - cron: '0 */6 * * *'
+
+jobs:
+ bump_date:
+ name: Bump Distribution Date
+ if: github.repository == 'MarlinFirmware/Marlin'
+
+ runs-on: ubuntu-latest
+
+ steps:
+
+ - name: Check out bugfix-2.1.x
+ uses: actions/checkout@v2
+ with:
+ ref: bugfix-2.1.x
+
+ - name: Bump Date (bugfix-2.0.x)
+ run: |
+ # Inline Bump Script
+ if [[ ! "$( git log -1 --pretty=%B )" =~ ^\[cron\] ]]; then
+ DIST=$( date +"%Y-%m-%d" )
+ eval "sed -E -i 's/(#define +STRING_DISTRIBUTION_DATE) .*$/\1 \"$DIST\"/g' Marlin/src/inc/Version.h" && \
+ eval "sed -E -i 's/(#define +STRING_DISTRIBUTION_DATE) .*$/\1 \"$DIST\"/g' Marlin/Version.h" && \
+ git config user.name "${GITHUB_ACTOR}" && \
+ git config user.email "${GITHUB_ACTOR}@users.noreply.github.com" && \
+ git add . && \
+ git commit -m "[cron] Bump distribution date ($DIST)" && \
+ git push
+ fi
+ exit 0
+
+ - name: Check out bugfix-2.1.x
+ uses: actions/checkout@v2
+ with:
+ ref: bugfix-2.1.x
+
+ - name: Bump Date (bugfix-2.1.x)
+ run: |
+ # Inline Bump Script
+ if [[ ! "$( git log -1 --pretty=%B )" =~ ^\[cron\] ]]; then
+ DIST=$( date +"%Y-%m-%d" )
+ eval "sed -E -i 's/(#define +STRING_DISTRIBUTION_DATE) .*$/\1 \"$DIST\"/g' Marlin/src/inc/Version.h" && \
+ eval "sed -E -i 's/(#define +STRING_DISTRIBUTION_DATE) .*$/\1 \"$DIST\"/g' Marlin/Version.h" && \
+ git config user.name "${GITHUB_ACTOR}" && \
+ git config user.email "${GITHUB_ACTOR}@users.noreply.github.com" && \
+ git add . && \
+ git commit -m "[cron] Bump distribution date ($DIST)" && \
+ git push
+ fi
+ exit 0
diff --git a/.github/workflows/check-pr.yml b/.github/workflows/check-pr.yml
new file mode 100644
index 000000000000..f631f69deae2
--- /dev/null
+++ b/.github/workflows/check-pr.yml
@@ -0,0 +1,34 @@
+#
+# check-pr.yml
+# Close PRs directed at release branches
+#
+
+name: PR Bad Target
+
+on:
+ pull_request_target:
+ types: [opened]
+ branches:
+ - 1.0.x
+ - 1.1.x
+ - 2.0.x
+ - 2.1.x
+
+jobs:
+ bad_target:
+ name: PR Bad Target
+ if: github.repository == 'MarlinFirmware/Marlin'
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: superbrothers/close-pull-request@v3
+ with:
+ comment: >
+ Thanks for your contribution! Unfortunately we can't accept PRs directed at release branches. We make patches to the bugfix branches and only later do we push them out as releases.
+
+ Please redo this PR starting with the `bugfix-2.1.x` branch and be careful to target `bugfix-2.1.x` when resubmitting the PR. Patches may also target `bugfix-2.0.x` if they are specifically for 2.0.9.x.
+
+ It may help to set your fork's default branch to `bugfix-2.0.x`.
+
+ See [this page](https://marlinfw.org/docs/development/getting_started_pull_requests.html) for full instructions.
diff --git a/.github/workflows/clean-closed.yml b/.github/workflows/clean-closed.yml
new file mode 100644
index 000000000000..befec4498f25
--- /dev/null
+++ b/.github/workflows/clean-closed.yml
@@ -0,0 +1,39 @@
+#
+# clean-closed.yml
+# Remove obsolete labels when an Issue or PR is closed
+#
+
+name: Clean Closed
+
+on:
+ pull_request:
+ types: [closed]
+ issues:
+ types: [closed]
+
+jobs:
+ remove_label:
+ runs-on: ubuntu-latest
+
+ strategy:
+ matrix:
+ label:
+ - "S: Don't Merge"
+ - "S: Hold for 2.1"
+ - "S: Please Merge"
+ - "S: Please Test"
+ - "help wanted"
+ - "Needs: Discussion"
+ - "Needs: Documentation"
+ - "Needs: More Data"
+ - "Needs: Patch"
+ - "Needs: Testing"
+ - "Needs: Work"
+
+ steps:
+ - uses: actions/checkout@v2
+ - name: Remove Labels
+ uses: actions-ecosystem/action-remove-labels@v1
+ with:
+ github_token: ${{ github.token }}
+ labels: ${{ matrix.label }}
diff --git a/.github/workflows/close-stale.yml b/.github/workflows/close-stale.yml
new file mode 100644
index 000000000000..88fea1996ddc
--- /dev/null
+++ b/.github/workflows/close-stale.yml
@@ -0,0 +1,28 @@
+#
+# close-stale.yml
+# Close open issues after a period of inactivity
+#
+
+name: Close Stale Issues
+
+on:
+ schedule:
+ - cron: "22 1 * * *"
+
+jobs:
+ stale:
+ name: Close Stale Issues
+ if: github.repository == 'MarlinFirmware/Marlin'
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: actions/stale@v3
+ with:
+ repo-token: ${{ secrets.GITHUB_TOKEN }}
+ stale-issue-message: 'This issue has had no activity in the last 60 days. Please add a reply if you want to keep this issue active, otherwise it will be automatically closed within 10 days.'
+ days-before-stale: 60
+ days-before-close: 10
+ stale-issue-label: 'stale-closing-soon'
+ exempt-all-assignees: true
+ exempt-issue-labels: 'Bug: Confirmed !,T: Feature Request,Needs: More Data,Needs: Discussion,Needs: Documentation,Needs: Patch,Needs: Work,Needs: Testing,help wanted,no-locking'
diff --git a/.github/workflows/lock-closed.yml b/.github/workflows/lock-closed.yml
new file mode 100644
index 000000000000..8cdcd7a8369e
--- /dev/null
+++ b/.github/workflows/lock-closed.yml
@@ -0,0 +1,32 @@
+#
+# lock-closed.yml
+# Lock closed issues after a period of inactivity
+#
+
+name: Lock Closed Issues
+
+on:
+ schedule:
+ - cron: '0 1/13 * * *'
+
+jobs:
+ lock:
+ name: Lock Closed Issues
+ if: github.repository == 'MarlinFirmware/Marlin'
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: dessant/lock-threads@v2
+ with:
+ github-token: ${{ github.token }}
+ process-only: 'issues'
+ issue-lock-inactive-days: '60'
+ issue-exclude-created-before: ''
+ issue-exclude-labels: 'no-locking'
+ issue-lock-labels: ''
+ issue-lock-comment: >
+ This issue has been automatically locked since there
+ has not been any recent activity after it was closed.
+ Please open a new issue for related bugs.
+ issue-lock-reason: ''
diff --git a/.github/workflows/test-builds.yml b/.github/workflows/test-builds.yml
index 962473383892..5a18a2e8bf60 100644
--- a/.github/workflows/test-builds.yml
+++ b/.github/workflows/test-builds.yml
@@ -8,7 +8,7 @@ name: CI
on:
pull_request:
branches:
- - bugfix-2.0.x
+ - bugfix-2.1.x
paths-ignore:
- config/**
- data/**
@@ -16,7 +16,7 @@ on:
- '**/*.md'
push:
branches:
- - bugfix-2.0.x
+ - bugfix-2.1.x
paths-ignore:
- config/**
- data/**
@@ -45,81 +45,108 @@ jobs:
- teensy35
- teensy41
- SAMD51_grandcentral_m4
+ - PANDA_PI_V29
# Extended AVR Environments
- - FYSETC_F6_13
+ - FYSETC_F6
- mega1280
- rambo
- sanguino1284p
- sanguino644p
- # Extended STM32 Environments
+ # STM32F1 (Maple) Environments
+
+ #- STM32F103RC_btt_maple
+ - STM32F103RC_btt_USB_maple
+ - STM32F103RC_fysetc_maple
+ - STM32F103RC_meeb_maple
+ - jgaurora_a5s_a1_maple
+ - STM32F103VE_longer_maple
+ #- mks_robin_maple
+ - mks_robin_lite_maple
+ - mks_robin_pro_maple
+ #- mks_robin_nano_v1v2_maple
+ #- STM32F103RE_creality_maple
+ - STM32F103VE_ZM3E4V2_USB_maple
+
+ # STM32 (ST) Environments
- STM32F103RC_btt
- - STM32F103RC_btt_USB
+ #- STM32F103RC_btt_USB
- STM32F103RE_btt
- STM32F103RE_btt_USB
- - STM32F103RC_fysetc
- - STM32F103RC_meeb
- - jgaurora_a5s_a1
+ - STM32F103RE_creality
+ - STM32F401RC_creality
- STM32F103VE_longer
- STM32F407VE_black
- - STM32F401VE_STEVAL
- BIGTREE_BTT002
- BIGTREE_SKR_PRO
- BIGTREE_GTR_V1_0
- mks_robin
- - mks_robin_stm32
- ARMED
- FYSETC_S6
- STM32F070CB_malyan
- STM32F070RB_malyan
- malyan_M300
- - mks_robin_lite
- FLYF407ZG
- rumba32
- - mks_robin_pro
- - STM32F103RET6_creality
- LERDGEX
- - mks_robin_nano35
+ - LERDGEK
+ - mks_robin_nano_v1v2
+ #- mks_robin_nano_v1v2_usbmod
+ #- mks_robin_nano_v1_3_f4_usbmod
- NUCLEO_F767ZI
+ - REMRAM_V1
+ - BTT_SKR_SE_BX
+ - chitu_f103
+ - Opulo_Lumen_REV3
+
+ # ESP32 environments
+ - mks_tinybee
# Put lengthy tests last
- LPC1768
- LPC1769
- # STM32 with non-STM framework. both broken for now. they should use HAL_STM32 which is working.
-
- #- STM32F4
- #- STM32F7
-
# Non-working environment tests
#- at90usb1286_cdc
#- STM32F103CB_malyan
+ #- STM32F103RE
#- mks_robin_mini
steps:
+ - name: Check out the PR
+ uses: actions/checkout@v3
+
+ - name: Cache pip
+ uses: actions/cache@v3
+ with:
+ path: ~/.cache/pip
+ key: ${{ runner.os }}-pip-${{ hashFiles('**/requirements.txt') }}
+ restore-keys: |
+ ${{ runner.os }}-pip-
+
+ - name: Cache PlatformIO
+ uses: actions/cache@v3
+ with:
+ path: ~/.platformio
+ key: ${{ runner.os }}-${{ hashFiles('**/lockfiles') }}
+
- name: Select Python 3.7
- uses: actions/setup-python@v1
+ uses: actions/setup-python@v3
with:
python-version: '3.7' # Version range or exact version of a Python version to use, using semvers version range syntax.
architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
- name: Install PlatformIO
run: |
- pip install -U https://github.com/platformio/platformio-core/archive/develop.zip
- platformio update
-
- - name: Check out the PR
- uses: actions/checkout@v2
+ pip install -U platformio
+ pio upgrade --dev
+ pio pkg update --global
- name: Run ${{ matrix.test-platform }} Tests
run: |
- # Inline tests script
- chmod +x buildroot/bin/*
- chmod +x buildroot/tests/*
- export PATH=./buildroot/bin/:./buildroot/tests/:${PATH}
- run_tests . ${{ matrix.test-platform }}
+ make tests-single-ci TEST_TARGET=${{ matrix.test-platform }}
diff --git a/.github/workflows/unlock-reopened.yml b/.github/workflows/unlock-reopened.yml
new file mode 100644
index 000000000000..614ef3fab297
--- /dev/null
+++ b/.github/workflows/unlock-reopened.yml
@@ -0,0 +1,22 @@
+#
+# unlock-reopened.yml
+# Unlock an issue whenever it is re-opened
+#
+
+name: "Unlock reopened issue"
+
+on:
+ issues:
+ types: [reopened]
+
+jobs:
+ unlock:
+ name: Unlock Reopened
+ if: github.repository == 'MarlinFirmware/Marlin'
+
+ runs-on: ubuntu-latest
+
+ steps:
+ - uses: OSDKDev/unlock-issues@v1.1
+ with:
+ repo-token: "${{ secrets.GITHUB_TOKEN }}"
diff --git a/.gitignore b/.gitignore
index 1ac1abbe15ac..0b852d767325 100755
--- a/.gitignore
+++ b/.gitignore
@@ -19,15 +19,19 @@
# along with this program. If not, see .
#
-# Our automatic versioning scheme generates the following file
-# NEVER put it in the repository
+# Generated files
_Version.h
+bdf2u8g
+marlin_config.json
+mczip.h
+*.gen
+*.sublime-workspace
#
# OS
#
applet/
-*.DS_Store
+.DS_Store
#
# Misc
@@ -37,7 +41,6 @@ applet/
*.rej
*.bak
*.idea
-*.s
*.i
*.ii
*.swp
@@ -122,33 +125,10 @@ tags
.gcc-flags.json
/lib/
-# Workaround for Deviot+platformio quirks
-Marlin/lib
-Marlin/platformio.ini
-Marlin/*/platformio.ini
-Marlin/*/*/platformio.ini
-Marlin/*/*/*/platformio.ini
-Marlin/*/*/*/*/platformio.ini
-Marlin/.travis.yml
-Marlin/*/.travis.yml
-Marlin/*/*/.travis.yml
-Marlin/*/*/*/.travis.yml
-Marlin/*/*/*/*/.travis.yml
-Marlin/.gitignore
-Marlin/*/.gitignore
-Marlin/*/*/.gitignore
-Marlin/*/*/*/.gitignore
-Marlin/*/*/*/*/.gitignore
-Marlin/readme.txt
-Marlin/*/readme.txt
-Marlin/*/*/readme.txt
-Marlin/*/*/*/readme.txt
-Marlin/*/*/*/*/readme.txt
-
# Secure Credentials
Configuration_Secure.h
-#Visual Studio
+# Visual Studio
*.sln
*.vcxproj
*.vcxproj.user
@@ -159,27 +139,33 @@ __vm/
.vs/
vc-fileutils.settings
-#Visual Studio Code
-.vscode
-.vscode/.browse.c_cpp.db*
-.vscode/c_cpp_properties.json
-.vscode/launch.json
-.vscode/*.db
+# Visual Studio Code
+.vscode/*
+!.vscode/extensions.json
+
+#Simulation
+imgui.ini
+eeprom.dat
+spi_flash.bin
#cmake
CMakeLists.txt
src/CMakeLists.txt
CMakeListsPrivate.txt
+build/
-#CLion
+# CLion
cmake-build-*
-#Eclipse
+# Eclipse
.project
.cproject
.pydevproject
.settings
.classpath
-#Python
+# Python
__pycache__
+
+# IOLogger logs
+*_log.csv
diff --git a/.vscode/extensions.json b/.vscode/extensions.json
new file mode 100644
index 000000000000..f495d14f53e8
--- /dev/null
+++ b/.vscode/extensions.json
@@ -0,0 +1,11 @@
+{
+ // See http://go.microsoft.com/fwlink/?LinkId=827846
+ // for the documentation about the extensions.json format
+ "recommendations": [
+ "marlinfirmware.auto-build",
+ "platformio.platformio-ide"
+ ],
+ "unwantedRecommendations": [
+ "ms-vscode.cpptools-extension-pack"
+ ]
+}
diff --git a/Makefile b/Makefile
new file mode 100644
index 000000000000..ebcdf25e2d6a
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,52 @@
+help:
+ @echo "Tasks for local development:"
+ @echo "* tests-single-ci: Run a single test from inside the CI"
+ @echo "* tests-single-local: Run a single test locally"
+ @echo "* tests-single-local-docker: Run a single test locally, using docker-compose"
+ @echo "* tests-all-local: Run all tests locally"
+ @echo "* tests-all-local-docker: Run all tests locally, using docker-compose"
+ @echo "* setup-local-docker: Setup local docker-compose"
+ @echo ""
+ @echo "Options for testing:"
+ @echo " TEST_TARGET Set when running tests-single-*, to select the"
+ @echo " test. If you set it to ALL it will run all "
+ @echo " tests, but some of them are broken: use "
+ @echo " tests-all-* instead to run only the ones that "
+ @echo " run on GitHub CI"
+ @echo " ONLY_TEST Limit tests to only those that contain this, or"
+ @echo " the index of the test (1-based)"
+ @echo " VERBOSE_PLATFORMIO If you want the full PIO output, set any value"
+ @echo " GIT_RESET_HARD Used by CI: reset all local changes. WARNING:"
+ @echo " THIS WILL UNDO ANY CHANGES YOU'VE MADE!"
+.PHONY: help
+
+tests-single-ci:
+ export GIT_RESET_HARD=true
+ $(MAKE) tests-single-local TEST_TARGET=$(TEST_TARGET)
+.PHONY: tests-single-ci
+
+tests-single-local:
+ @if ! test -n "$(TEST_TARGET)" ; then echo "***ERROR*** Set TEST_TARGET= or use make tests-all-local" ; return 1; fi
+ export PATH=./buildroot/bin/:./buildroot/tests/:${PATH} \
+ && export VERBOSE_PLATFORMIO=$(VERBOSE_PLATFORMIO) \
+ && run_tests . $(TEST_TARGET) "$(ONLY_TEST)"
+.PHONY: tests-single-local
+
+tests-single-local-docker:
+ @if ! test -n "$(TEST_TARGET)" ; then echo "***ERROR*** Set TEST_TARGET= or use make tests-all-local-docker" ; return 1; fi
+ docker-compose run --rm marlin $(MAKE) tests-single-local TEST_TARGET=$(TEST_TARGET) VERBOSE_PLATFORMIO=$(VERBOSE_PLATFORMIO) GIT_RESET_HARD=$(GIT_RESET_HARD) ONLY_TEST="$(ONLY_TEST)"
+.PHONY: tests-single-local-docker
+
+tests-all-local:
+ export PATH=./buildroot/bin/:./buildroot/tests/:${PATH} \
+ && export VERBOSE_PLATFORMIO=$(VERBOSE_PLATFORMIO) \
+ && for TEST_TARGET in $$(./get_test_targets.py) ; do echo "Running tests for $$TEST_TARGET" ; run_tests . $$TEST_TARGET ; done
+.PHONY: tests-all-local
+
+tests-all-local-docker:
+ docker-compose run --rm marlin $(MAKE) tests-all-local VERBOSE_PLATFORMIO=$(VERBOSE_PLATFORMIO) GIT_RESET_HARD=$(GIT_RESET_HARD)
+.PHONY: tests-all-local-docker
+
+setup-local-docker:
+ docker-compose build
+.PHONY: setup-local-docker
diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h
index c0fcd48c766d..34933da43a54 100644
--- a/Marlin/Configuration.h
+++ b/Marlin/Configuration.h
@@ -35,38 +35,28 @@
*
* Advanced settings can be found in Configuration_adv.h
*/
-#define CONFIGURATION_H_VERSION 020008
+#define CONFIGURATION_H_VERSION 02010200
//===========================================================================
//============================= Getting Started =============================
//===========================================================================
/**
- * Here are some standard links for getting your machine calibrated:
+ * Here are some useful links to help get your machine configured and calibrated:
*
- * https://reprap.org/wiki/Calibration
- * https://youtu.be/wAL9d7FgInk
- * http://calculator.josefprusa.cz
- * https://reprap.org/wiki/Triffid_Hunter%27s_Calibration_Guide
- * https://www.thingiverse.com/thing:5573
- * https://sites.google.com/site/repraplogphase/calibration-of-your-reprap
- * https://www.thingiverse.com/thing:298812
+ * Example Configs: https://github.com/MarlinFirmware/Configurations/branches/all
+ *
+ * Průša Calculator: https://blog.prusaprinters.org/calculator_3416/
+ *
+ * Calibration Guides: https://reprap.org/wiki/Calibration
+ * https://reprap.org/wiki/Triffid_Hunter%27s_Calibration_Guide
+ * https://sites.google.com/site/repraplogphase/calibration-of-your-reprap
+ * https://youtu.be/wAL9d7FgInk
+ *
+ * Calibration Objects: https://www.thingiverse.com/thing:5573
+ * https://www.thingiverse.com/thing:1278865
*/
-//===========================================================================
-//============================= DELTA Printer ===============================
-//===========================================================================
-// For a Delta printer start with one of the configuration files in the
-// config/examples/delta directory and customize for your machine.
-//
-
-//===========================================================================
-//============================= SCARA Printer ===============================
-//===========================================================================
-// For a SCARA printer start with the configuration files in
-// config/examples/SCARA and customize for your machine.
-//
-
// @section info
// Author info of this build printed to the host during boot and M115
@@ -106,14 +96,9 @@
#define SERIAL_PORT -1
/**
- * Select a secondary serial port on the board to use for communication with the host.
- * Currently Ethernet (-2) is only supported on Teensy 4.1 boards.
- * :[-2, -1, 0, 1, 2, 3, 4, 5, 6, 7]
- */
-//#define SERIAL_PORT_2 -1
-
-/**
- * This setting determines the communication speed of the printer.
+ * Serial Port Baud Rate
+ * This is the default communication speed for all serial ports.
+ * Set the baud rate defaults for additional serial ports below.
*
* 250000 works in most cases, but you might try a lower speed if
* you commonly experience drop-outs during host printing.
@@ -123,6 +108,24 @@
*/
#define BAUDRATE 250000
+//#define BAUD_RATE_GCODE // Enable G-code M575 to set the baud rate
+
+/**
+ * Select a secondary serial port on the board to use for communication with the host.
+ * Currently Ethernet (-2) is only supported on Teensy 4.1 boards.
+ * :[-2, -1, 0, 1, 2, 3, 4, 5, 6, 7]
+ */
+//#define SERIAL_PORT_2 -1
+//#define BAUDRATE_2 250000 // :[2400, 9600, 19200, 38400, 57600, 115200, 250000, 500000, 1000000] Enable to override BAUDRATE
+
+/**
+ * Select a third serial port on the board to use for communication with the host.
+ * Currently only supported for AVR, DUE, LPC1768/9 and STM32/STM32F1
+ * :[-1, 0, 1, 2, 3, 4, 5, 6, 7]
+ */
+//#define SERIAL_PORT_3 1
+//#define BAUDRATE_3 250000 // :[2400, 9600, 19200, 38400, 57600, 115200, 250000, 500000, 1000000] Enable to override BAUDRATE
+
// Enable the Bluetooth serial interface on AT90USB devices
//#define BLUETOOTH
@@ -138,6 +141,88 @@
// Choose your own or use a service like https://www.uuidgenerator.net/version4
//#define MACHINE_UUID "00000000-0000-0000-0000-000000000000"
+// @section stepper drivers
+
+/**
+ * Stepper Drivers
+ *
+ * These settings allow Marlin to tune stepper driver timing and enable advanced options for
+ * stepper drivers that support them. You may also override timing options in Configuration_adv.h.
+ *
+ * Use TMC2208/TMC2208_STANDALONE for TMC2225 drivers and TMC2209/TMC2209_STANDALONE for TMC2226 drivers.
+ *
+ * Options: A4988, A5984, DRV8825, LV8729, TB6560, TB6600, TMC2100,
+ * TMC2130, TMC2130_STANDALONE, TMC2160, TMC2160_STANDALONE,
+ * TMC2208, TMC2208_STANDALONE, TMC2209, TMC2209_STANDALONE,
+ * TMC26X, TMC26X_STANDALONE, TMC2660, TMC2660_STANDALONE,
+ * TMC5130, TMC5130_STANDALONE, TMC5160, TMC5160_STANDALONE
+ * :['A4988', 'A5984', 'DRV8825', 'LV8729', 'TB6560', 'TB6600', 'TMC2100', 'TMC2130', 'TMC2130_STANDALONE', 'TMC2160', 'TMC2160_STANDALONE', 'TMC2208', 'TMC2208_STANDALONE', 'TMC2209', 'TMC2209_STANDALONE', 'TMC26X', 'TMC26X_STANDALONE', 'TMC2660', 'TMC2660_STANDALONE', 'TMC5130', 'TMC5130_STANDALONE', 'TMC5160', 'TMC5160_STANDALONE']
+ */
+#define X_DRIVER_TYPE TMC2130
+#define Y_DRIVER_TYPE TMC2130
+#define Z_DRIVER_TYPE TMC2130
+//#define X2_DRIVER_TYPE A4988
+//#define Y2_DRIVER_TYPE A4988
+//#define Z2_DRIVER_TYPE A4988
+//#define Z3_DRIVER_TYPE A4988
+//#define Z4_DRIVER_TYPE A4988
+//#define I_DRIVER_TYPE A4988
+//#define J_DRIVER_TYPE A4988
+//#define K_DRIVER_TYPE A4988
+//#define U_DRIVER_TYPE A4988
+//#define V_DRIVER_TYPE A4988
+//#define W_DRIVER_TYPE A4988
+#define E0_DRIVER_TYPE TMC2130
+//#define E1_DRIVER_TYPE A4988
+//#define E2_DRIVER_TYPE A4988
+//#define E3_DRIVER_TYPE A4988
+//#define E4_DRIVER_TYPE A4988
+//#define E5_DRIVER_TYPE A4988
+//#define E6_DRIVER_TYPE A4988
+//#define E7_DRIVER_TYPE A4988
+
+/**
+ * Additional Axis Settings
+ *
+ * Define AXISn_ROTATES for all axes that rotate or pivot.
+ * Rotational axis coordinates are expressed in degrees.
+ *
+ * AXISn_NAME defines the letter used to refer to the axis in (most) G-code commands.
+ * By convention the names and roles are typically:
+ * 'A' : Rotational axis parallel to X
+ * 'B' : Rotational axis parallel to Y
+ * 'C' : Rotational axis parallel to Z
+ * 'U' : Secondary linear axis parallel to X
+ * 'V' : Secondary linear axis parallel to Y
+ * 'W' : Secondary linear axis parallel to Z
+ *
+ * Regardless of these settings the axes are internally named I, J, K, U, V, W.
+ */
+#ifdef I_DRIVER_TYPE
+ #define AXIS4_NAME 'A' // :['A', 'B', 'C', 'U', 'V', 'W']
+ #define AXIS4_ROTATES
+#endif
+#ifdef J_DRIVER_TYPE
+ #define AXIS5_NAME 'B' // :['B', 'C', 'U', 'V', 'W']
+ #define AXIS5_ROTATES
+#endif
+#ifdef K_DRIVER_TYPE
+ #define AXIS6_NAME 'C' // :['C', 'U', 'V', 'W']
+ #define AXIS6_ROTATES
+#endif
+#ifdef U_DRIVER_TYPE
+ #define AXIS7_NAME 'U' // :['U', 'V', 'W']
+ //#define AXIS7_ROTATES
+#endif
+#ifdef V_DRIVER_TYPE
+ #define AXIS8_NAME 'V' // :['V', 'W']
+ //#define AXIS8_ROTATES
+#endif
+#ifdef W_DRIVER_TYPE
+ #define AXIS9_NAME 'W' // :['W']
+ //#define AXIS9_ROTATES
+#endif
+
// @section extruder
// This defines the number of extruders
@@ -157,34 +242,23 @@
//#define SINGLENOZZLE_STANDBY_FAN
#endif
-/**
- * Průša MK2 Single Nozzle Multi-Material Multiplexer, and variants.
- *
- * This device allows one stepper driver on a control board to drive
- * two to eight stepper motors, one at a time, in a manner suitable
- * for extruders.
- *
- * This option only allows the multiplexer to switch on tool-change.
- * Additional options to configure custom E moves are pending.
- */
-//#define MK2_MULTIPLEXER
-#if ENABLED(MK2_MULTIPLEXER)
- // Override the default DIO selector pins here, if needed.
- // Some pins files may provide defaults for these pins.
- //#define E_MUX0_PIN 40 // Always Required
- //#define E_MUX1_PIN 42 // Needed for 3 to 8 inputs
- //#define E_MUX2_PIN 44 // Needed for 5 to 8 inputs
-#endif
+// @section multi-material
/**
- * Průša Multi-Material Unit v2
+ * Multi-Material Unit
+ * Set to one of these predefined models:
*
- * Requires NOZZLE_PARK_FEATURE to park print head in case MMU unit fails.
- * Requires EXTRUDERS = 5
+ * PRUSA_MMU1 : Průša MMU1 (The "multiplexer" version)
+ * PRUSA_MMU2 : Průša MMU2
+ * PRUSA_MMU2S : Průša MMU2S (Requires MK3S extruder with motion sensor, EXTRUDERS = 5)
+ * EXTENDABLE_EMU_MMU2 : MMU with configurable number of filaments (ERCF, SMuFF or similar with Průša MMU2 compatible firmware)
+ * EXTENDABLE_EMU_MMU2S : MMUS with configurable number of filaments (ERCF, SMuFF or similar with Průša MMU2 compatible firmware)
*
- * For additional configuration see Configuration_adv.h
+ * Requires NOZZLE_PARK_FEATURE to park print head in case MMU unit fails.
+ * See additional options in Configuration_adv.h.
+ * :["PRUSA_MMU1", "PRUSA_MMU2", "PRUSA_MMU2S", "EXTENDABLE_EMU_MMU2", "EXTENDABLE_EMU_MMU2S"]
*/
-//#define PRUSA_MMU2
+//#define MMU_MODEL PRUSA_MMU2
// A dual extruder that uses a single stepper motor
//#define SWITCHING_EXTRUDER
@@ -202,6 +276,7 @@
#define SWITCHING_NOZZLE_SERVO_NR 0
//#define SWITCHING_NOZZLE_E1_SERVO_NR 1 // If two servos are used, the index of the second
#define SWITCHING_NOZZLE_SERVO_ANGLES { 0, 90 } // Angles for E0, E1 (single servo) or lowered/raised (dual servo)
+ #define SWITCHING_NOZZLE_SERVO_DWELL 2500 // Dwell time to wait for servo to make physical move
#endif
/**
@@ -224,7 +299,6 @@
#define PARKING_EXTRUDER_PARKING_X { -78, 184 } // X positions for parking the extruders
#define PARKING_EXTRUDER_GRAB_DISTANCE 1 // (mm) Distance to move beyond the parking point to grab the extruder
- //#define MANUAL_SOLENOID_CONTROL // Manual control of docking solenoids with M380 S / M381
#if ENABLED(PARKING_EXTRUDER)
@@ -306,6 +380,7 @@
#define MIXING_VIRTUAL_TOOLS 16 // Use the Virtual Tool method with M163 and M164
//#define DIRECT_MIXING_IN_G1 // Allow ABCDHI mix factors in G1 movement commands
//#define GRADIENT_MIX // Support for gradient mixing with M166 and LCD
+ //#define MIXING_PRESETS // Assign 8 default V-tool presets for 2 or 3 MIXING_STEPPERS
#if ENABLED(GRADIENT_MIX)
//#define GRADIENT_VTOOL // Add M166 T to use a V-tool index as a Gradient alias
#endif
@@ -318,7 +393,7 @@
//#define HOTEND_OFFSET_Y { 0.0, 5.00 } // (mm) relative Y-offset for each nozzle
//#define HOTEND_OFFSET_Z { 0.0, 0.00 } // (mm) relative Z-offset for each nozzle
-// @section machine
+// @section psu control
/**
* Power Supply Control
@@ -330,10 +405,17 @@
//#define PSU_NAME "Power Supply"
#if ENABLED(PSU_CONTROL)
+ //#define MKS_PWC // Using the MKS PWC add-on
+ //#define PS_OFF_CONFIRM // Confirm dialog when power off
+ //#define PS_OFF_SOUND // Beep 1s when power off
#define PSU_ACTIVE_STATE LOW // Set 'LOW' for ATX, 'HIGH' for X-Box
- //#define PSU_DEFAULT_OFF // Keep power off until enabled directly with M80
- //#define PSU_POWERUP_DELAY 250 // (ms) Delay for the PSU to warm up to full power
+ //#define PSU_DEFAULT_OFF // Keep power off until enabled directly with M80
+ //#define PSU_POWERUP_DELAY 250 // (ms) Delay for the PSU to warm up to full power
+ //#define LED_POWEROFF_TIMEOUT 10000 // (ms) Turn off LEDs after power-off, with this amount of delay
+
+ //#define POWER_OFF_TIMER // Enable M81 D to power off after a delay
+ //#define POWER_OFF_WAIT_FOR_COOLDOWN // Enable M81 S to power off only after cooldown
//#define PSU_POWERUP_GCODE "M355 S1" // G-code to run after power-on (e.g., case light on)
//#define PSU_POWEROFF_GCODE "M355 S0" // G-code to run before power-off (e.g., case light off)
@@ -344,9 +426,14 @@
#define AUTO_POWER_E_FANS
#define AUTO_POWER_CONTROLLERFAN
#define AUTO_POWER_CHAMBER_FAN
- //#define AUTO_POWER_E_TEMP 50 // (°C) Turn on PSU over this temperature
- //#define AUTO_POWER_CHAMBER_TEMP 30 // (°C) Turn on PSU over this temperature
- #define POWER_TIMEOUT 30
+ #define AUTO_POWER_COOLER_FAN
+ #define POWER_TIMEOUT 30 // (s) Turn off power if the machine is idle for this duration
+ //#define POWER_OFF_DELAY 60 // (s) Delay of poweroff after M81 command. Useful to let fans run for extra time.
+ #endif
+ #if EITHER(AUTO_POWER_CONTROL, POWER_OFF_WAIT_FOR_COOLDOWN)
+ //#define AUTO_POWER_E_TEMP 50 // (°C) PSU on if any extruder is over this temperature
+ //#define AUTO_POWER_CHAMBER_TEMP 30 // (°C) PSU on if the chamber is over this temperature
+ //#define AUTO_POWER_COOLER_TEMP 26 // (°C) PSU on if the cooler is over this temperature
#endif
#endif
@@ -356,68 +443,97 @@
// @section temperature
/**
- * --NORMAL IS 4.7kohm PULLUP!-- 1kohm pullup can be used on hotend sensor, using correct resistor and table
+ * --NORMAL IS 4.7kΩ PULLUP!-- 1kΩ pullup can be used on hotend sensor, using correct resistor and table
*
* Temperature sensors available:
*
- * -5 : PT100 / PT1000 with MAX31865 (only for sensors 0-1)
- * -3 : thermocouple with MAX31855 (only for sensors 0-1)
- * -2 : thermocouple with MAX6675 (only for sensors 0-1)
- * -4 : thermocouple with AD8495
- * -1 : thermocouple with AD595
+ * SPI RTD/Thermocouple Boards - IMPORTANT: Read the NOTE below!
+ * -------
+ * -5 : MAX31865 with Pt100/Pt1000, 2, 3, or 4-wire (only for sensors 0-1)
+ * NOTE: You must uncomment/set the MAX31865_*_OHMS_n defines below.
+ * -3 : MAX31855 with Thermocouple, -200°C to +700°C (only for sensors 0-1)
+ * -2 : MAX6675 with Thermocouple, 0°C to +700°C (only for sensors 0-1)
+ *
+ * NOTE: Ensure TEMP_n_CS_PIN is set in your pins file for each TEMP_SENSOR_n using an SPI Thermocouple. By default,
+ * Hardware SPI on the default serial bus is used. If you have also set TEMP_n_SCK_PIN and TEMP_n_MISO_PIN,
+ * Software SPI will be used on those ports instead. You can force Hardware SPI on the default bus in the
+ * Configuration_adv.h file. At this time, separate Hardware SPI buses for sensors are not supported.
+ *
+ * Analog Themocouple Boards
+ * -------
+ * -4 : AD8495 with Thermocouple
+ * -1 : AD595 with Thermocouple
+ *
+ * Analog Thermistors - 4.7kΩ pullup - Normal
+ * -------
+ * 1 : 100kΩ EPCOS - Best choice for EPCOS thermistors
+ * 331 : 100kΩ Same as #1, but 3.3V scaled for MEGA
+ * 332 : 100kΩ Same as #1, but 3.3V scaled for DUE
+ * 2 : 200kΩ ATC Semitec 204GT-2
+ * 202 : 200kΩ Copymaster 3D
+ * 3 : ???Ω Mendel-parts thermistor
+ * 4 : 10kΩ Generic Thermistor !! DO NOT use for a hotend - it gives bad resolution at high temp. !!
+ * 5 : 100kΩ ATC Semitec 104GT-2/104NT-4-R025H42G - Used in ParCan, J-Head, and E3D, SliceEngineering 300°C
+ * 501 : 100kΩ Zonestar - Tronxy X3A
+ * 502 : 100kΩ Zonestar - used by hot bed in Zonestar Průša P802M
+ * 503 : 100kΩ Zonestar (Z8XM2) Heated Bed thermistor
+ * 504 : 100kΩ Zonestar P802QR2 (Part# QWG-104F-B3950) Hotend Thermistor
+ * 505 : 100kΩ Zonestar P802QR2 (Part# QWG-104F-3950) Bed Thermistor
+ * 512 : 100kΩ RPW-Ultra hotend
+ * 6 : 100kΩ EPCOS - Not as accurate as table #1 (created using a fluke thermocouple)
+ * 7 : 100kΩ Honeywell 135-104LAG-J01
+ * 71 : 100kΩ Honeywell 135-104LAF-J01
+ * 8 : 100kΩ Vishay 0603 SMD NTCS0603E3104FXT
+ * 9 : 100kΩ GE Sensing AL03006-58.2K-97-G1
+ * 10 : 100kΩ RS PRO 198-961
+ * 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
+ * 13 : 100kΩ Hisens up to 300°C - for "Simple ONE" & "All In ONE" hotend - beta 3950, 1%
+ * 15 : 100kΩ Calibrated for JGAurora A5 hotend
+ * 18 : 200kΩ ATC Semitec 204GT-2 Dagoma.Fr - MKS_Base_DKU001327
+ * 22 : 100kΩ GTM32 Pro vB - hotend - 4.7kΩ pullup to 3.3V and 220Ω to analog input
+ * 23 : 100kΩ GTM32 Pro vB - bed - 4.7kΩ pullup to 3.3v and 220Ω to analog input
+ * 30 : 100kΩ Kis3d Silicone heating mat 200W/300W with 6mm precision cast plate (EN AW 5083) NTC100K - beta 3950
+ * 60 : 100kΩ Maker's Tool Works Kapton Bed Thermistor - beta 3950
+ * 61 : 100kΩ Formbot/Vivedino 350°C Thermistor - beta 3950
+ * 66 : 4.7MΩ Dyze Design High Temperature Thermistor
+ * 67 : 500kΩ SliceEngineering 450°C Thermistor
+ * 68 : PT100 amplifier board from Dyze Design
+ * 70 : 100kΩ bq Hephestos 2
+ * 75 : 100kΩ Generic Silicon Heat Pad with NTC100K MGB18-104F39050L32
+ * 2000 : 100kΩ Ultimachine Rambo TDK NTCG104LH104KT1 NTC100K motherboard Thermistor
+ *
+ * Analog Thermistors - 1kΩ pullup - Atypical, and requires changing out the 4.7kΩ pullup for 1kΩ.
+ * ------- (but gives greater accuracy and more stable PID)
+ * 51 : 100kΩ EPCOS (1kΩ pullup)
+ * 52 : 200kΩ ATC Semitec 204GT-2 (1kΩ pullup)
+ * 55 : 100kΩ ATC Semitec 104GT-2 - Used in ParCan & J-Head (1kΩ pullup)
+ *
+ * Analog Thermistors - 10kΩ pullup - Atypical
+ * -------
+ * 99 : 100kΩ Found on some Wanhao i3 machines with a 10kΩ pull-up resistor
+ *
+ * Analog RTDs (Pt100/Pt1000)
+ * -------
+ * 110 : Pt100 with 1kΩ pullup (atypical)
+ * 147 : Pt100 with 4.7kΩ pullup
+ * 1010 : Pt1000 with 1kΩ pullup (atypical)
+ * 1047 : Pt1000 with 4.7kΩ pullup (E3D)
+ * 20 : Pt100 with circuit in the Ultimainboard V2.x with mainboard ADC reference voltage = INA826 amplifier-board supply voltage.
+ * NOTE: (1) Must use an ADC input with no pullup. (2) Some INA826 amplifiers are unreliable at 3.3V so consider using sensor 147, 110, or 21.
+ * 21 : Pt100 with circuit in the Ultimainboard V2.x with 3.3v ADC reference voltage (STM32, LPC176x....) and 5V INA826 amplifier board supply.
+ * NOTE: ADC pins are not 5V tolerant. Not recommended because it's possible to damage the CPU by going over 500°C.
+ * 201 : Pt100 with circuit in Overlord, similar to Ultimainboard V2.x
+ *
+ * Custom/Dummy/Other Thermal Sensors
+ * ------
* 0 : not used
- * 1 : 100k thermistor - best choice for EPCOS 100k (4.7k pullup)
- * 331 : (3.3V scaled thermistor 1 table for MEGA)
- * 332 : (3.3V scaled thermistor 1 table for DUE)
- * 2 : 200k thermistor - ATC Semitec 204GT-2 (4.7k pullup)
- * 202 : 200k thermistor - Copymaster 3D
- * 3 : Mendel-parts thermistor (4.7k pullup)
- * 4 : 10k thermistor !! do not use it for a hotend. It gives bad resolution at high temp. !!
- * 5 : 100K thermistor - ATC Semitec 104GT-2/104NT-4-R025H42G (Used in ParCan, J-Head, and E3D) (4.7k pullup)
- * 501 : 100K Zonestar (Tronxy X3A) Thermistor
- * 502 : 100K Zonestar Thermistor used by hot bed in Zonestar Průša P802M
- * 512 : 100k RPW-Ultra hotend thermistor (4.7k pullup)
- * 6 : 100k EPCOS - Not as accurate as table 1 (created using a fluke thermocouple) (4.7k pullup)
- * 7 : 100k Honeywell thermistor 135-104LAG-J01 (4.7k pullup)
- * 71 : 100k Honeywell thermistor 135-104LAF-J01 (4.7k pullup)
- * 8 : 100k 0603 SMD Vishay NTCS0603E3104FXT (4.7k pullup)
- * 9 : 100k GE Sensing AL03006-58.2K-97-G1 (4.7k pullup)
- * 10 : 100k RS thermistor 198-961 (4.7k pullup)
- * 11 : 100k beta 3950 1% thermistor (Used in Keenovo AC silicone mats and most Wanhao i3 machines) (4.7k pullup)
- * 12 : 100k 0603 SMD Vishay NTCS0603E3104FXT (4.7k pullup) (calibrated for Makibox hot bed)
- * 13 : 100k Hisens 3950 1% up to 300°C for hotend "Simple ONE " & "Hotend "All In ONE"
- * 15 : 100k thermistor calibration for JGAurora A5 hotend
- * 18 : ATC Semitec 204GT-2 (4.7k pullup) Dagoma.Fr - MKS_Base_DKU001327
- * 20 : Pt100 with circuit in the Ultimainboard V2.x with 5v excitation (AVR)
- * 21 : Pt100 with circuit in the Ultimainboard V2.x with 3.3v excitation (STM32 \ LPC176x....)
- * 22 : 100k (hotend) with 4.7k pullup to 3.3V and 220R to analog input (as in GTM32 Pro vB)
- * 23 : 100k (bed) with 4.7k pullup to 3.3v and 220R to analog input (as in GTM32 Pro vB)
- * 30 : Kis3d Silicone heating mat 200W/300W with 6mm precision cast plate (EN AW 5083) NTC100K / B3950 (4.7k pullup)
- * 201 : Pt100 with circuit in Overlord, similar to Ultimainboard V2.x
- * 60 : 100k Maker's Tool Works Kapton Bed Thermistor beta=3950
- * 61 : 100k Formbot / Vivedino 3950 350C thermistor 4.7k pullup
- * 66 : 4.7M High Temperature thermistor from Dyze Design
- * 67 : 450C thermistor from SliceEngineering
- * 70 : the 100K thermistor found in the bq Hephestos 2
- * 75 : 100k Generic Silicon Heat Pad with NTC 100K MGB18-104F39050L32 thermistor
- * 99 : 100k thermistor with a 10K pull-up resistor (found on some Wanhao i3 machines)
- *
- * 1k ohm pullup tables - This is atypical, and requires changing out the 4.7k pullup for 1k.
- * (but gives greater accuracy and more stable PID)
- * 51 : 100k thermistor - EPCOS (1k pullup)
- * 52 : 200k thermistor - ATC Semitec 204GT-2 (1k pullup)
- * 55 : 100k thermistor - ATC Semitec 104GT-2 (Used in ParCan & J-Head) (1k pullup)
- *
- * 1047 : Pt1000 with 4k7 pullup (E3D)
- * 1010 : Pt1000 with 1k pullup (non standard)
- * 147 : Pt100 with 4k7 pullup
- * 110 : Pt100 with 1k pullup (non standard)
- *
* 1000 : Custom - Specify parameters in Configuration_adv.h
*
- * Use these for Testing or Development purposes. NEVER for production machine.
+ * !!! Use these for Testing or Development purposes. NEVER for production machine. !!!
* 998 : Dummy Table that ALWAYS reads 25°C or the temperature defined below.
* 999 : Dummy Table that ALWAYS reads 100°C or the temperature defined below.
+ *
*/
#define TEMP_SENSOR_0 1
#define TEMP_SENSOR_1 0
@@ -430,29 +546,57 @@
#define TEMP_SENSOR_BED 1
#define TEMP_SENSOR_PROBE 0
#define TEMP_SENSOR_CHAMBER 0
+#define TEMP_SENSOR_COOLER 0
+#define TEMP_SENSOR_BOARD 0
+#define TEMP_SENSOR_REDUNDANT 0
// Dummy thermistor constant temperature readings, for use with 998 and 999
-#define DUMMY_THERMISTOR_998_VALUE 25
+#define DUMMY_THERMISTOR_998_VALUE 25
#define DUMMY_THERMISTOR_999_VALUE 100
-// Resistor values when using a MAX31865 (sensor -5)
-// Sensor value is typically 100 (PT100) or 1000 (PT1000)
-// Calibration value is typically 430 ohm for AdaFruit PT100 modules and 4300 ohm for AdaFruit PT1000 modules.
-//#define MAX31865_SENSOR_OHMS 100
-//#define MAX31865_CALIBRATION_OHMS 430
+// Resistor values when using MAX31865 sensors (-5) on TEMP_SENSOR_0 / 1
+#if TEMP_SENSOR_IS_MAX_TC(0)
+ #define MAX31865_SENSOR_OHMS_0 100 // (Ω) Typically 100 or 1000 (PT100 or PT1000)
+ #define MAX31865_CALIBRATION_OHMS_0 430 // (Ω) Typically 430 for Adafruit PT100; 4300 for Adafruit PT1000
+#endif
+#if TEMP_SENSOR_IS_MAX_TC(1)
+ #define MAX31865_SENSOR_OHMS_1 100
+ #define MAX31865_CALIBRATION_OHMS_1 430
+#endif
+
+#if HAS_E_TEMP_SENSOR
+ #define TEMP_RESIDENCY_TIME 10 // (seconds) Time to wait for hotend to "settle" in M109
+ #define TEMP_WINDOW 1 // (°C) Temperature proximity for the "temperature reached" timer
+ #define TEMP_HYSTERESIS 3 // (°C) Temperature proximity considered "close enough" to the target
+#endif
-// Use temp sensor 1 as a redundant sensor with sensor 0. If the readings
-// from the two sensors differ too much the print will be aborted.
-//#define TEMP_SENSOR_1_AS_REDUNDANT
-#define MAX_REDUNDANT_TEMP_SENSOR_DIFF 10
+#if TEMP_SENSOR_BED
+ #define TEMP_BED_RESIDENCY_TIME 10 // (seconds) Time to wait for bed to "settle" in M190
+ #define TEMP_BED_WINDOW 1 // (°C) Temperature proximity for the "temperature reached" timer
+ #define TEMP_BED_HYSTERESIS 3 // (°C) Temperature proximity considered "close enough" to the target
+#endif
-#define TEMP_RESIDENCY_TIME 10 // (seconds) Time to wait for hotend to "settle" in M109
-#define TEMP_WINDOW 1 // (°C) Temperature proximity for the "temperature reached" timer
-#define TEMP_HYSTERESIS 3 // (°C) Temperature proximity considered "close enough" to the target
+#if TEMP_SENSOR_CHAMBER
+ #define TEMP_CHAMBER_RESIDENCY_TIME 10 // (seconds) Time to wait for chamber to "settle" in M191
+ #define TEMP_CHAMBER_WINDOW 1 // (°C) Temperature proximity for the "temperature reached" timer
+ #define TEMP_CHAMBER_HYSTERESIS 3 // (°C) Temperature proximity considered "close enough" to the target
+#endif
-#define TEMP_BED_RESIDENCY_TIME 10 // (seconds) Time to wait for bed to "settle" in M190
-#define TEMP_BED_WINDOW 1 // (°C) Temperature proximity for the "temperature reached" timer
-#define TEMP_BED_HYSTERESIS 3 // (°C) Temperature proximity considered "close enough" to the target
+/**
+ * Redundant Temperature Sensor (TEMP_SENSOR_REDUNDANT)
+ *
+ * Use a temp sensor as a redundant sensor for another reading. Select an unused temperature sensor, and another
+ * sensor you'd like it to be redundant for. If the two thermistors differ by TEMP_SENSOR_REDUNDANT_MAX_DIFF (°C),
+ * the print will be aborted. Whichever sensor is selected will have its normal functions disabled; i.e. selecting
+ * the Bed sensor (-1) will disable bed heating/monitoring.
+ *
+ * For selecting source/target use: COOLER, PROBE, BOARD, CHAMBER, BED, E0, E1, E2, E3, E4, E5, E6, E7
+ */
+#if TEMP_SENSOR_REDUNDANT
+ #define TEMP_SENSOR_REDUNDANT_SOURCE E1 // The sensor that will provide the redundant reading.
+ #define TEMP_SENSOR_REDUNDANT_TARGET E0 // The sensor that we are providing a redundant reading for.
+ #define TEMP_SENSOR_REDUNDANT_MAX_DIFF 10 // (°C) Temperature difference that will trigger a print abort.
+#endif
// Below this temperature the heater will be switched off
// because it probably indicates a broken thermistor wire.
@@ -465,6 +609,7 @@
#define HEATER_6_MINTEMP 5
#define HEATER_7_MINTEMP 5
#define BED_MINTEMP 5
+#define CHAMBER_MINTEMP 5
// Above this temperature the heater will be switched off.
// This can protect components from overheating, but NOT from shorts and failures.
@@ -478,27 +623,41 @@
#define HEATER_6_MAXTEMP 275
#define HEATER_7_MAXTEMP 275
#define BED_MAXTEMP 150
+#define CHAMBER_MAXTEMP 60
+
+/**
+ * Thermal Overshoot
+ * During heatup (and printing) the temperature can often "overshoot" the target by many degrees
+ * (especially before PID tuning). Setting the target temperature too close to MAXTEMP guarantees
+ * a MAXTEMP shutdown! Use these values to forbid temperatures being set too close to MAXTEMP.
+ */
+#define HOTEND_OVERSHOOT 15 // (°C) Forbid temperatures over MAXTEMP - OVERSHOOT
+#define BED_OVERSHOOT 10 // (°C) Forbid temperatures over MAXTEMP - OVERSHOOT
+#define COOLER_OVERSHOOT 2 // (°C) Forbid temperatures closer than OVERSHOOT
//===========================================================================
//============================= PID Settings ================================
//===========================================================================
-// PID Tuning Guide here: https://reprap.org/wiki/PID_Tuning
-// Comment the following line to disable PID and enable bang-bang.
-#define PIDTEMP
+// @section hotend temp
+
+// Enable PIDTEMP for PID control or MPCTEMP for Predictive Model.
+// temperature control. Disable both for bang-bang heating.
+#define PIDTEMP // See the PID Tuning Guide at https://reprap.org/wiki/PID_Tuning
+//#define MPCTEMP // ** EXPERIMENTAL **
+
#define BANG_MAX 255 // Limits current to nozzle while in bang-bang mode; 255=full current
#define PID_MAX BANG_MAX // Limits current to nozzle while PID is active (see PID_FUNCTIONAL_RANGE below); 255=full current
#define PID_K1 0.95 // Smoothing factor within any PID loop
#if ENABLED(PIDTEMP)
- #define PID_EDIT_MENU // Add PID editing to the "Advanced Settings" menu. (~700 bytes of PROGMEM)
- #define PID_AUTOTUNE_MENU // Add PID auto-tuning to the "Advanced Settings" menu. (~250 bytes of PROGMEM)
- //#define PID_PARAMS_PER_HOTEND // Uses separate PID parameters for each extruder (useful for mismatched extruders)
- // Set/get with gcode: M301 E[extruder number, 0-2]
+ //#define PID_DEBUG // Print PID debug data to the serial port. Use 'M303 D' to toggle activation.
+ //#define PID_PARAMS_PER_HOTEND // Use separate PID parameters for each extruder (useful for mismatched extruders)
+ // Set/get with G-code: M301 E[extruder number, 0-2]
#if ENABLED(PID_PARAMS_PER_HOTEND)
- // Specify between 1 and HOTENDS values per array.
- // If fewer than EXTRUDER values are provided, the last element will be repeated.
+ // Specify up to one value per hotend here, according to your setup.
+ // If there are fewer values, the last one applies to the remaining hotends.
#define DEFAULT_Kp_LIST { 22.20, 22.20 }
#define DEFAULT_Ki_LIST { 1.08, 1.08 }
#define DEFAULT_Kd_LIST { 114.00, 114.00 }
@@ -507,7 +666,50 @@
#define DEFAULT_Ki 1.08
#define DEFAULT_Kd 114.00
#endif
-#endif // PIDTEMP
+#endif
+
+/**
+ * Model Predictive Control for hotend
+ *
+ * Use a physical model of the hotend to control temperature. When configured correctly
+ * this gives better responsiveness and stability than PID and it also removes the need
+ * for PID_EXTRUSION_SCALING and PID_FAN_SCALING. Use M306 T to autotune the model.
+ * @section mpctemp
+ */
+#if ENABLED(MPCTEMP)
+ //#define MPC_EDIT_MENU // Add MPC editing to the "Advanced Settings" menu. (~1300 bytes of flash)
+ //#define MPC_AUTOTUNE_MENU // Add MPC auto-tuning to the "Advanced Settings" menu. (~350 bytes of flash)
+
+ #define MPC_MAX BANG_MAX // (0..255) Current to nozzle while MPC is active.
+ #define MPC_HEATER_POWER { 40.0f } // (W) Heat cartridge powers.
+
+ #define MPC_INCLUDE_FAN // Model the fan speed?
+
+ // Measured physical constants from M306
+ #define MPC_BLOCK_HEAT_CAPACITY { 16.7f } // (J/K) Heat block heat capacities.
+ #define MPC_SENSOR_RESPONSIVENESS { 0.22f } // (K/s per ∆K) Rate of change of sensor temperature from heat block.
+ #define MPC_AMBIENT_XFER_COEFF { 0.068f } // (W/K) Heat transfer coefficients from heat block to room air with fan off.
+ #if ENABLED(MPC_INCLUDE_FAN)
+ #define MPC_AMBIENT_XFER_COEFF_FAN255 { 0.097f } // (W/K) Heat transfer coefficients from heat block to room air with fan on full.
+ #endif
+
+ // For one fan and multiple hotends MPC needs to know how to apply the fan cooling effect.
+ #if ENABLED(MPC_INCLUDE_FAN)
+ //#define MPC_FAN_0_ALL_HOTENDS
+ //#define MPC_FAN_0_ACTIVE_HOTEND
+ #endif
+
+ #define FILAMENT_HEAT_CAPACITY_PERMM { 5.6e-3f } // 0.0056 J/K/mm for 1.75mm PLA (0.0149 J/K/mm for 2.85mm PLA).
+ //#define FILAMENT_HEAT_CAPACITY_PERMM { 3.6e-3f } // 0.0036 J/K/mm for 1.75mm PETG (0.0094 J/K/mm for 2.85mm PETG).
+
+ // Advanced options
+ #define MPC_SMOOTHING_FACTOR 0.5f // (0.0...1.0) Noisy temperature sensors may need a lower value for stabilization.
+ #define MPC_MIN_AMBIENT_CHANGE 1.0f // (K/s) Modeled ambient temperature rate of change, when correcting model inaccuracies.
+ #define MPC_STEADYSTATE 0.5f // (K/s) Temperature change rate for steady state logic to be enforced.
+
+ #define MPC_TUNING_POS { X_CENTER, Y_CENTER, 1.0f } // (mm) M306 Autotuning position, ideally bed center at first layer height.
+ #define MPC_TUNING_END_Z 10.0f // (mm) M306 Autotuning final Z position.
+#endif
//===========================================================================
//====================== PID > Bed Temperature Control ======================
@@ -525,6 +727,7 @@
* impact FET heating. This also works fine on a Fotek SSR-10DA Solid State Relay into a 250W
* heater. If your configuration is significantly different than this and you don't understand
* the issues involved, don't use bed PID until someone else verifies that your hardware works.
+ * @section bed temp
*/
#define PIDTEMPBED
@@ -540,7 +743,7 @@
#if ENABLED(PIDTEMPBED)
//#define MIN_BED_POWER 0
- //#define PID_BED_DEBUG // Sends debug data to the serial port.
+ //#define PID_BED_DEBUG // Print Bed PID debug data to the serial port.
// 120V 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)
// from FOPDT model - kp=.39 Tp=405 Tdead=66, Tc set to 79.2, aggressive factor of .15 (vs .1, 1, 10)
@@ -551,15 +754,62 @@
// FIND YOUR OWN: "M303 E-1 C8 S90" to run autotune on the bed at 90 degreesC for 8 cycles.
#endif // PIDTEMPBED
-#if EITHER(PIDTEMP, PIDTEMPBED)
- //#define PID_DEBUG // Sends debug data to the serial port. Use 'M303 D' to toggle activation.
+//===========================================================================
+//==================== PID > Chamber Temperature Control ====================
+//===========================================================================
+
+/**
+ * PID Chamber Heating
+ *
+ * If this option is enabled set PID constants below.
+ * If this option is disabled, bang-bang will be used and CHAMBER_LIMIT_SWITCHING will enable
+ * hysteresis.
+ *
+ * The PID frequency will be the same as the extruder PWM.
+ * If PID_dT is the default, and correct for the hardware/configuration, that means 7.689Hz,
+ * which is fine for driving a square wave into a resistive load and does not significantly
+ * impact FET heating. This also works fine on a Fotek SSR-10DA Solid State Relay into a 200W
+ * heater. If your configuration is significantly different than this and you don't understand
+ * the issues involved, don't use chamber PID until someone else verifies that your hardware works.
+ * @section chamber temp
+ */
+//#define PIDTEMPCHAMBER
+//#define CHAMBER_LIMIT_SWITCHING
+
+/**
+ * Max Chamber Power
+ * Applies to all forms of chamber control (PID, bang-bang, and bang-bang with hysteresis).
+ * When set to any value below 255, enables a form of PWM to the chamber heater that acts like a divider
+ * so don't use it unless you are OK with PWM on your heater. (See the comment on enabling PIDTEMPCHAMBER)
+ */
+#define MAX_CHAMBER_POWER 255 // limits duty cycle to chamber heater; 255=full current
+
+#if ENABLED(PIDTEMPCHAMBER)
+ #define MIN_CHAMBER_POWER 0
+ //#define PID_CHAMBER_DEBUG // Print Chamber PID debug data to the serial port.
+
+ // Lasko "MyHeat Personal Heater" (200w) modified with a Fotek SSR-10DA to control only the heating element
+ // and placed inside the small Creality printer enclosure tent.
+ //
+ #define DEFAULT_chamberKp 37.04
+ #define DEFAULT_chamberKi 1.40
+ #define DEFAULT_chamberKd 655.17
+ // M309 P37.04 I1.04 D655.17
+
+ // FIND YOUR OWN: "M303 E-2 C8 S50" to run autotune on the chamber at 50 degreesC for 8 cycles.
+#endif // PIDTEMPCHAMBER
+
+#if ANY(PIDTEMP, PIDTEMPBED, PIDTEMPCHAMBER)
//#define PID_OPENLOOP // Puts PID in open loop. M104/M140 sets the output power from 0 to PID_MAX
//#define SLOW_PWM_HEATERS // PWM with very low frequency (roughly 0.125Hz=8s) and minimum state time of approximately 1s useful for heaters driven by a relay
#define PID_FUNCTIONAL_RANGE 10 // If the temperature difference between the target temperature and the actual temperature
// is more than PID_FUNCTIONAL_RANGE then the PID will be shut off and the heater will be set to min/max.
+
+ //#define PID_EDIT_MENU // Add PID editing to the "Advanced Settings" menu. (~700 bytes of flash)
+ //#define PID_AUTOTUNE_MENU // Add PID auto-tuning to the "Advanced Settings" menu. (~250 bytes of flash)
#endif
-// @section extruder
+// @section safety
/**
* Prevent extrusion if the temperature is below EXTRUDE_MINTEMP.
@@ -598,6 +848,7 @@
#define THERMAL_PROTECTION_HOTENDS // Enable thermal protection for all extruders
#define THERMAL_PROTECTION_BED // Enable thermal protection for the heated bed
#define THERMAL_PROTECTION_CHAMBER // Enable thermal protection for the heated chamber
+#define THERMAL_PROTECTION_COOLER // Enable thermal protection for the laser cooling
//===========================================================================
//============================= Mechanical Settings =========================
@@ -614,12 +865,166 @@
//#define COREZX
//#define COREZY
//#define MARKFORGED_XY // MarkForged. See https://reprap.org/forum/read.php?152,504042
+//#define MARKFORGED_YX
+
+// Enable for a belt style printer with endless "Z" motion
+//#define BELTPRINTER
+
+// Enable for Polargraph Kinematics
+//#define POLARGRAPH
+#if ENABLED(POLARGRAPH)
+ #define POLARGRAPH_MAX_BELT_LEN 1035.0
+ #define POLAR_SEGMENTS_PER_SECOND 5
+#endif
+
+// @section delta
+
+// Enable for DELTA kinematics and configure below
+//#define DELTA
+#if ENABLED(DELTA)
+
+ // Make delta curves from many straight lines (linear interpolation).
+ // This is a trade-off between visible corners (not enough segments)
+ // and processor overload (too many expensive sqrt calls).
+ #define DELTA_SEGMENTS_PER_SECOND 200
+
+ // After homing move down to a height where XY movement is unconstrained
+ //#define DELTA_HOME_TO_SAFE_ZONE
+
+ // Delta calibration menu
+ // uncomment to add three points calibration menu option.
+ // See http://minow.blogspot.com/index.html#4918805519571907051
+ //#define DELTA_CALIBRATION_MENU
+
+ // uncomment to add G33 Delta Auto-Calibration (Enable EEPROM_SETTINGS to store results)
+ //#define DELTA_AUTO_CALIBRATION
+
+ // NOTE NB all values for DELTA_* values MUST be floating point, so always have a decimal point in them
+
+ #if ENABLED(DELTA_AUTO_CALIBRATION)
+ // set the default number of probe points : n*n (1 -> 7)
+ #define DELTA_CALIBRATION_DEFAULT_POINTS 4
+ #endif
+
+ #if EITHER(DELTA_AUTO_CALIBRATION, DELTA_CALIBRATION_MENU)
+ // Set the steprate for papertest probing
+ #define PROBE_MANUALLY_STEP 0.05 // (mm)
+ #endif
+
+ // Print surface diameter/2 minus unreachable space (avoid collisions with vertical towers).
+ #define DELTA_PRINTABLE_RADIUS 140.0 // (mm)
+
+ // Maximum reachable area
+ #define DELTA_MAX_RADIUS 140.0 // (mm)
+
+ // Center-to-center distance of the holes in the diagonal push rods.
+ #define DELTA_DIAGONAL_ROD 250.0 // (mm)
+
+ // Distance between bed and nozzle Z home position
+ #define DELTA_HEIGHT 250.00 // (mm) Get this value from G33 auto calibrate
+
+ #define DELTA_ENDSTOP_ADJ { 0.0, 0.0, 0.0 } // Get these values from G33 auto calibrate
+
+ // Horizontal distance bridged by diagonal push rods when effector is centered.
+ #define DELTA_RADIUS 124.0 // (mm) Get this value from G33 auto calibrate
+
+ // Trim adjustments for individual towers
+ // tower angle corrections for X and Y tower / rotate XYZ so Z tower angle = 0
+ // measured in degrees anticlockwise looking from above the printer
+ #define DELTA_TOWER_ANGLE_TRIM { 0.0, 0.0, 0.0 } // Get these values from G33 auto calibrate
+
+ // Delta radius and diagonal rod adjustments (mm)
+ //#define DELTA_RADIUS_TRIM_TOWER { 0.0, 0.0, 0.0 }
+ //#define DELTA_DIAGONAL_ROD_TRIM_TOWER { 0.0, 0.0, 0.0 }
+#endif
+
+// @section scara
+
+/**
+ * MORGAN_SCARA was developed by QHARLEY in South Africa in 2012-2013.
+ * Implemented and slightly reworked by JCERNY in June, 2014.
+ *
+ * Mostly Printed SCARA is an open source design by Tyler Williams. See:
+ * https://www.thingiverse.com/thing:2487048
+ * https://www.thingiverse.com/thing:1241491
+ */
+//#define MORGAN_SCARA
+//#define MP_SCARA
+#if EITHER(MORGAN_SCARA, MP_SCARA)
+ // If movement is choppy try lowering this value
+ #define SCARA_SEGMENTS_PER_SECOND 200
+
+ // Length of inner and outer support arms. Measure arm lengths precisely.
+ #define SCARA_LINKAGE_1 150 // (mm)
+ #define SCARA_LINKAGE_2 150 // (mm)
+
+ // SCARA tower offset (position of Tower relative to bed zero position)
+ // This needs to be reasonably accurate as it defines the printbed position in the SCARA space.
+ #define SCARA_OFFSET_X 100 // (mm)
+ #define SCARA_OFFSET_Y -56 // (mm)
+
+ #if ENABLED(MORGAN_SCARA)
+
+ //#define DEBUG_SCARA_KINEMATICS
+ #define SCARA_FEEDRATE_SCALING // Convert XY feedrate from mm/s to degrees/s on the fly
+
+ // Radius around the center where the arm cannot reach
+ #define MIDDLE_DEAD_ZONE_R 0 // (mm)
+
+ #define THETA_HOMING_OFFSET 0 // Calculated from Calibration Guide and M360 / M114. See http://reprap.harleystudio.co.za/?page_id=1073
+ #define PSI_HOMING_OFFSET 0 // Calculated from Calibration Guide and M364 / M114. See http://reprap.harleystudio.co.za/?page_id=1073
+
+ #elif ENABLED(MP_SCARA)
+
+ #define SCARA_OFFSET_THETA1 12 // degrees
+ #define SCARA_OFFSET_THETA2 131 // degrees
+
+ #endif
+
+#endif
+
+// @section tpara
+
+// Enable for TPARA kinematics and configure below
+//#define AXEL_TPARA
+#if ENABLED(AXEL_TPARA)
+ #define DEBUG_ROBOT_KINEMATICS
+ #define ROBOT_SEGMENTS_PER_SECOND 200
+
+ // Length of inner and outer support arms. Measure arm lengths precisely.
+ #define ROBOT_LINKAGE_1 120 // (mm)
+ #define ROBOT_LINKAGE_2 120 // (mm)
+
+ // SCARA tower offset (position of Tower relative to bed zero position)
+ // This needs to be reasonably accurate as it defines the printbed position in the SCARA space.
+ #define ROBOT_OFFSET_X 0 // (mm)
+ #define ROBOT_OFFSET_Y 0 // (mm)
+ #define ROBOT_OFFSET_Z 0 // (mm)
+
+ #define SCARA_FEEDRATE_SCALING // Convert XY feedrate from mm/s to degrees/s on the fly
+
+ // Radius around the center where the arm cannot reach
+ #define MIDDLE_DEAD_ZONE_R 0 // (mm)
+
+ // Calculated from Calibration Guide and M360 / M114. See http://reprap.harleystudio.co.za/?page_id=1073
+ #define THETA_HOMING_OFFSET 0
+ #define PSI_HOMING_OFFSET 0
+#endif
+
+// @section machine
+
+// Articulated robot (arm). Joints are directly mapped to axes with no kinematics.
+//#define ARTICULATED_ROBOT_ARM
+
+// For a hot wire cutter with parallel horizontal axes (X, I) where the heights of the two wire
+// ends are controlled by parallel axes (Y, J). Joints are directly mapped to axes (no kinematics).
+//#define FOAMCUTTER_XYUV
//===========================================================================
//============================== Endstop Settings ===========================
//===========================================================================
-// @section homing
+// @section endstops
// Specify here all the endstop connectors that are connected to any endstop or probe.
// Almost all printers will be using one per axis. Probes will use one or more of the
@@ -627,20 +1032,44 @@
// #define USE_XMIN_PLUG
// #define USE_YMIN_PLUG
#define USE_ZMIN_PLUG
+//#define USE_IMIN_PLUG
+//#define USE_JMIN_PLUG
+//#define USE_KMIN_PLUG
+//#define USE_UMIN_PLUG
+//#define USE_VMIN_PLUG
+//#define USE_WMIN_PLUG
#define USE_XMAX_PLUG
#define USE_YMAX_PLUG
#define USE_ZMAX_PLUG
+//#define USE_IMAX_PLUG
+//#define USE_JMAX_PLUG
+//#define USE_KMAX_PLUG
+//#define USE_UMAX_PLUG
+//#define USE_VMAX_PLUG
+//#define USE_WMAX_PLUG
// Enable pullup for all endstops to prevent a floating state
#define ENDSTOPPULLUPS
#if DISABLED(ENDSTOPPULLUPS)
// Disable ENDSTOPPULLUPS to set pullups individually
- //#define ENDSTOPPULLUP_XMAX
- //#define ENDSTOPPULLUP_YMAX
- //#define ENDSTOPPULLUP_ZMAX
//#define ENDSTOPPULLUP_XMIN
//#define ENDSTOPPULLUP_YMIN
//#define ENDSTOPPULLUP_ZMIN
+ //#define ENDSTOPPULLUP_IMIN
+ //#define ENDSTOPPULLUP_JMIN
+ //#define ENDSTOPPULLUP_KMIN
+ //#define ENDSTOPPULLUP_UMIN
+ //#define ENDSTOPPULLUP_VMIN
+ //#define ENDSTOPPULLUP_WMIN
+ //#define ENDSTOPPULLUP_XMAX
+ //#define ENDSTOPPULLUP_YMAX
+ //#define ENDSTOPPULLUP_ZMAX
+ //#define ENDSTOPPULLUP_IMAX
+ //#define ENDSTOPPULLUP_JMAX
+ //#define ENDSTOPPULLUP_KMAX
+ //#define ENDSTOPPULLUP_UMAX
+ //#define ENDSTOPPULLUP_VMAX
+ //#define ENDSTOPPULLUP_WMAX
//#define ENDSTOPPULLUP_ZMIN_PROBE
#endif
@@ -648,12 +1077,24 @@
//#define ENDSTOPPULLDOWNS
#if DISABLED(ENDSTOPPULLDOWNS)
// Disable ENDSTOPPULLDOWNS to set pulldowns individually
- //#define ENDSTOPPULLDOWN_XMAX
- //#define ENDSTOPPULLDOWN_YMAX
- //#define ENDSTOPPULLDOWN_ZMAX
//#define ENDSTOPPULLDOWN_XMIN
//#define ENDSTOPPULLDOWN_YMIN
//#define ENDSTOPPULLDOWN_ZMIN
+ //#define ENDSTOPPULLDOWN_IMIN
+ //#define ENDSTOPPULLDOWN_JMIN
+ //#define ENDSTOPPULLDOWN_KMIN
+ //#define ENDSTOPPULLDOWN_UMIN
+ //#define ENDSTOPPULLDOWN_VMIN
+ //#define ENDSTOPPULLDOWN_WMIN
+ //#define ENDSTOPPULLDOWN_XMAX
+ //#define ENDSTOPPULLDOWN_YMAX
+ //#define ENDSTOPPULLDOWN_ZMAX
+ //#define ENDSTOPPULLDOWN_IMAX
+ //#define ENDSTOPPULLDOWN_JMAX
+ //#define ENDSTOPPULLDOWN_KMAX
+ //#define ENDSTOPPULLDOWN_UMAX
+ //#define ENDSTOPPULLDOWN_VMAX
+ //#define ENDSTOPPULLDOWN_WMAX
//#define ENDSTOPPULLDOWN_ZMIN_PROBE
#endif
@@ -661,44 +1102,23 @@
#define X_MIN_ENDSTOP_INVERTING true // Set to true to invert the logic of the endstop.
#define Y_MIN_ENDSTOP_INVERTING true // Set to true to invert the logic of the endstop.
#define Z_MIN_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
+#define I_MIN_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
+#define J_MIN_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
+#define K_MIN_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
+#define U_MIN_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
+#define V_MIN_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
+#define W_MIN_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
#define X_MAX_ENDSTOP_INVERTING true // Set to true to invert the logic of the endstop.
#define Y_MAX_ENDSTOP_INVERTING true // Set to true to invert the logic of the endstop.
#define Z_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
+#define I_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
+#define J_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
+#define K_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
+#define U_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
+#define V_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
+#define W_MAX_ENDSTOP_INVERTING false // Set to true to invert the logic of the endstop.
#define Z_MIN_PROBE_ENDSTOP_INVERTING false // Set to true to invert the logic of the probe.
-/**
- * Stepper Drivers
- *
- * These settings allow Marlin to tune stepper driver timing and enable advanced options for
- * stepper drivers that support them. You may also override timing options in Configuration_adv.h.
- *
- * A4988 is assumed for unspecified drivers.
- *
- * Options: A4988, A5984, DRV8825, LV8729, L6470, L6474, POWERSTEP01,
- * TB6560, TB6600, TMC2100,
- * TMC2130, TMC2130_STANDALONE, TMC2160, TMC2160_STANDALONE,
- * TMC2208, TMC2208_STANDALONE, TMC2209, TMC2209_STANDALONE,
- * TMC26X, TMC26X_STANDALONE, TMC2660, TMC2660_STANDALONE,
- * TMC5130, TMC5130_STANDALONE, TMC5160, TMC5160_STANDALONE
- * :['A4988', 'A5984', 'DRV8825', 'LV8729', 'L6470', 'L6474', 'POWERSTEP01', 'TB6560', 'TB6600', 'TMC2100', 'TMC2130', 'TMC2130_STANDALONE', 'TMC2160', 'TMC2160_STANDALONE', 'TMC2208', 'TMC2208_STANDALONE', 'TMC2209', 'TMC2209_STANDALONE', 'TMC26X', 'TMC26X_STANDALONE', 'TMC2660', 'TMC2660_STANDALONE', 'TMC5130', 'TMC5130_STANDALONE', 'TMC5160', 'TMC5160_STANDALONE']
- */
-#define X_DRIVER_TYPE TMC2130
-#define Y_DRIVER_TYPE TMC2130
-#define Z_DRIVER_TYPE TMC2130
-//#define X2_DRIVER_TYPE A4988
-//#define Y2_DRIVER_TYPE A4988
-//#define Z2_DRIVER_TYPE A4988
-//#define Z3_DRIVER_TYPE A4988
-//#define Z4_DRIVER_TYPE A4988
-#define E0_DRIVER_TYPE TMC2130
-//#define E1_DRIVER_TYPE A4988
-//#define E2_DRIVER_TYPE A4988
-//#define E3_DRIVER_TYPE A4988
-//#define E4_DRIVER_TYPE A4988
-//#define E5_DRIVER_TYPE A4988
-//#define E6_DRIVER_TYPE A4988
-//#define E7_DRIVER_TYPE A4988
-
// Enable this feature if all enabled endstop pins are interrupt-capable.
// This will remove the need to poll the interrupt pins, saving many CPU cycles.
//#define ENDSTOP_INTERRUPTS_FEATURE
@@ -741,16 +1161,16 @@
//#define DISTINCT_E_FACTORS
/**
- * Default Axis Steps Per Unit (steps/mm)
+ * Default Axis Steps Per Unit (linear=steps/mm, rotational=steps/°)
* Override with M92
- * X, Y, Z, E0 [, E1[, E2...]]
+ * X, Y, Z [, I [, J [, K...]]], E0 [, E1[, E2...]]
*/
#define DEFAULT_AXIS_STEPS_PER_UNIT { 80, 80, 400, 407.3 }
/**
- * Default Max Feed Rate (mm/s)
+ * Default Max Feed Rate (linear=mm/s, rotational=°/s)
* Override with M203
- * X, Y, Z, E0 [, E1[, E2...]]
+ * X, Y, Z [, I [, J [, K...]]], E0 [, E1[, E2...]]
*/
#define DEFAULT_MAX_FEEDRATE { 100, 100, 20, 25 }
@@ -760,10 +1180,10 @@
#endif
/**
- * Default Max Acceleration (change/s) change = mm/s
+ * Default Max Acceleration (speed change with time) (linear=mm/(s^2), rotational=°/(s^2))
* (Maximum start speed for accelerated moves)
* Override with M201
- * X, Y, Z, E0 [, E1[, E2...]]
+ * X, Y, Z [, I [, J [, K...]]], E0 [, E1[, E2...]]
*/
#define DEFAULT_MAX_ACCELERATION { 1500, 1500, 100, 10000 }
@@ -773,7 +1193,7 @@
#endif
/**
- * Default Acceleration (change/s) change = mm/s
+ * Default Acceleration (speed change with time) (linear=mm/(s^2), rotational=°/(s^2))
* Override with M204
*
* M204 P Acceleration
@@ -786,7 +1206,7 @@
/**
* Default Jerk limits (mm/s)
- * Override with M205 X Y Z E
+ * Override with M205 X Y Z . . . E
*
* "Jerk" specifies the minimum speed change that requires acceleration.
* When changing speed and direction, if the difference is less than the
@@ -797,6 +1217,12 @@
#define DEFAULT_XJERK 10.0
#define DEFAULT_YJERK 10.0
#define DEFAULT_ZJERK 0.3
+ //#define DEFAULT_IJERK 0.3
+ //#define DEFAULT_JJERK 0.3
+ //#define DEFAULT_KJERK 0.3
+ //#define DEFAULT_UJERK 0.3
+ //#define DEFAULT_VJERK 0.3
+ //#define DEFAULT_WJERK 0.3
//#define TRAVEL_EXTRA_XYJERK 0.0 // Additional jerk allowance for all travel moves
@@ -880,7 +1306,6 @@
* or (with LCD_BED_LEVELING) the LCD controller.
*/
//#define PROBE_MANUALLY
-//#define MANUAL_PROBE_START_Z 0.2
/**
* A Fix-Mounted Probe either doesn't deploy or needs manual deployment.
@@ -906,9 +1331,15 @@
#define BLTOUCH
/**
- * Pressure sensor with a BLTouch-like interface
+ * MagLev V4 probe by MDD
+ *
+ * This probe is deployed and activated by powering a built-in electromagnet.
*/
-//#define CREALITY_TOUCH
+//#define MAGLEV4
+#if ENABLED(MAGLEV4)
+ //#define MAGLEV_TRIGGER_PIN 11 // Set to the connected digital output
+ #define MAGLEV_TRIGGER_DELAY 15 // Changing this risks overheating the coil
+#endif
/**
* Touch-MI Probe by hotends.fr
@@ -941,8 +1372,29 @@
#define Z_PROBE_RETRACT_X X_MAX_POS
#endif
+/**
+ * Magnetically Mounted Probe
+ * For probes such as Euclid, Klicky, Klackender, etc.
+ */
+//#define MAG_MOUNTED_PROBE
+#if ENABLED(MAG_MOUNTED_PROBE)
+ #define PROBE_DEPLOY_FEEDRATE (133*60) // (mm/min) Probe deploy speed
+ #define PROBE_STOW_FEEDRATE (133*60) // (mm/min) Probe stow speed
+
+ #define MAG_MOUNTED_DEPLOY_1 { PROBE_DEPLOY_FEEDRATE, { 245, 114, 30 } } // Move to side Dock & Attach probe
+ #define MAG_MOUNTED_DEPLOY_2 { PROBE_DEPLOY_FEEDRATE, { 210, 114, 30 } } // Move probe off dock
+ #define MAG_MOUNTED_DEPLOY_3 { PROBE_DEPLOY_FEEDRATE, { 0, 0, 0 } } // Extra move if needed
+ #define MAG_MOUNTED_DEPLOY_4 { PROBE_DEPLOY_FEEDRATE, { 0, 0, 0 } } // Extra move if needed
+ #define MAG_MOUNTED_DEPLOY_5 { PROBE_DEPLOY_FEEDRATE, { 0, 0, 0 } } // Extra move if needed
+ #define MAG_MOUNTED_STOW_1 { PROBE_STOW_FEEDRATE, { 245, 114, 20 } } // Move to dock
+ #define MAG_MOUNTED_STOW_2 { PROBE_STOW_FEEDRATE, { 245, 114, 0 } } // Place probe beside remover
+ #define MAG_MOUNTED_STOW_3 { PROBE_STOW_FEEDRATE, { 230, 114, 0 } } // Side move to remove probe
+ #define MAG_MOUNTED_STOW_4 { PROBE_STOW_FEEDRATE, { 210, 114, 20 } } // Side move to remove probe
+ #define MAG_MOUNTED_STOW_5 { PROBE_STOW_FEEDRATE, { 0, 0, 0 } } // Extra move if needed
+#endif
+
// Duet Smart Effector (for delta printers) - https://bit.ly/2ul5U7J
-// When the pin is defined you can use M672 to set/reset the probe sensivity.
+// When the pin is defined you can use M672 to set/reset the probe sensitivity.
//#define DUET_SMART_EFFECTOR
#if ENABLED(DUET_SMART_EFFECTOR)
#define SMART_EFFECTOR_MOD_PIN -1 // Connect a GPIO pin to the Smart Effector MOD pin
@@ -956,17 +1408,55 @@
*/
//#define SENSORLESS_PROBING
-//
-// For Z_PROBE_ALLEN_KEY see the Delta example configurations.
-//
+/**
+ * Allen key retractable z-probe as seen on many Kossel delta printers - https://reprap.org/wiki/Kossel#Automatic_bed_leveling_probe
+ * Deploys by touching z-axis belt. Retracts by pushing the probe down.
+ */
+//#define Z_PROBE_ALLEN_KEY
+#if ENABLED(Z_PROBE_ALLEN_KEY)
+ // 2 or 3 sets of coordinates for deploying and retracting the spring loaded touch probe on G29,
+ // if servo actuated touch probe is not defined. Uncomment as appropriate for your printer/probe.
+
+ #define Z_PROBE_ALLEN_KEY_DEPLOY_1 { 30.0, DELTA_PRINTABLE_RADIUS, 100.0 }
+ #define Z_PROBE_ALLEN_KEY_DEPLOY_1_FEEDRATE XY_PROBE_FEEDRATE
+
+ #define Z_PROBE_ALLEN_KEY_DEPLOY_2 { 0.0, DELTA_PRINTABLE_RADIUS, 100.0 }
+ #define Z_PROBE_ALLEN_KEY_DEPLOY_2_FEEDRATE (XY_PROBE_FEEDRATE)/10
+
+ #define Z_PROBE_ALLEN_KEY_DEPLOY_3 { 0.0, (DELTA_PRINTABLE_RADIUS) * 0.75, 100.0 }
+ #define Z_PROBE_ALLEN_KEY_DEPLOY_3_FEEDRATE XY_PROBE_FEEDRATE
+
+ #define Z_PROBE_ALLEN_KEY_STOW_1 { -64.0, 56.0, 23.0 } // Move the probe into position
+ #define Z_PROBE_ALLEN_KEY_STOW_1_FEEDRATE XY_PROBE_FEEDRATE
+
+ #define Z_PROBE_ALLEN_KEY_STOW_2 { -64.0, 56.0, 3.0 } // Push it down
+ #define Z_PROBE_ALLEN_KEY_STOW_2_FEEDRATE (XY_PROBE_FEEDRATE)/10
+
+ #define Z_PROBE_ALLEN_KEY_STOW_3 { -64.0, 56.0, 50.0 } // Move it up to clear
+ #define Z_PROBE_ALLEN_KEY_STOW_3_FEEDRATE XY_PROBE_FEEDRATE
+
+ #define Z_PROBE_ALLEN_KEY_STOW_4 { 0.0, 0.0, 50.0 }
+ #define Z_PROBE_ALLEN_KEY_STOW_4_FEEDRATE XY_PROBE_FEEDRATE
+
+#endif // Z_PROBE_ALLEN_KEY
/**
* Nozzle-to-Probe offsets { X, Y, Z }
*
- * - Use a caliper or ruler to measure the distance from the tip of
+ * X and Y offset
+ * 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.
+ *
+ * Z offset
* - For the Z offset use your best known value and adjust at runtime.
- * - Probe Offsets can be tuned at runtime with 'M851', LCD menus, babystepping, etc.
+ * - Common probes trigger below the nozzle and have negative values for Z offset.
+ * - Probes triggering above the nozzle height are uncommon but do exist. When using
+ * probes such as this, carefully set Z_CLEARANCE_DEPLOY_PROBE and Z_CLEARANCE_BETWEEN_PROBES
+ * to avoid collisions during probing.
+ *
+ * Tune and Adjust
+ * - Probe Offsets can be tuned at runtime with 'M851', LCD menus, babystepping, etc.
+ * - PROBE_OFFSET_WIZARD (configuration_adv.h) can be used for setting the Z offset.
*
* Assuming the typical work area orientation:
* - Probe to RIGHT of the Nozzle has a Positive X offset
@@ -997,13 +1487,49 @@
#define PROBING_MARGIN 12
// X and Y axis travel speed (mm/min) between probes
-#define XY_PROBE_SPEED (80*60)
+#define XY_PROBE_FEEDRATE (80*60)
// Feedrate (mm/min) for the first approach when double-probing (MULTIPLE_PROBING == 2)
-#define Z_PROBE_SPEED_FAST HOMING_FEEDRATE_Z
+#define Z_PROBE_FEEDRATE_FAST (4*60)
// Feedrate (mm/min) for the "accurate" probe of each point
-#define Z_PROBE_SPEED_SLOW (Z_PROBE_SPEED_FAST / 2)
+#define Z_PROBE_FEEDRATE_SLOW (Z_PROBE_FEEDRATE_FAST / 2)
+
+/**
+ * Probe Activation Switch
+ * A switch indicating proper deployment, or an optical
+ * switch triggered when the carriage is near the bed.
+ */
+//#define PROBE_ACTIVATION_SWITCH
+#if ENABLED(PROBE_ACTIVATION_SWITCH)
+ #define PROBE_ACTIVATION_SWITCH_STATE LOW // State indicating probe is active
+ //#define PROBE_ACTIVATION_SWITCH_PIN PC6 // Override default pin
+#endif
+
+/**
+ * Tare Probe (determine zero-point) prior to each probe.
+ * Useful for a strain gauge or piezo sensor that needs to factor out
+ * elements such as cables pulling on the carriage.
+ */
+//#define PROBE_TARE
+#if ENABLED(PROBE_TARE)
+ #define PROBE_TARE_TIME 200 // (ms) Time to hold tare pin
+ #define PROBE_TARE_DELAY 200 // (ms) Delay after tare before
+ #define PROBE_TARE_STATE HIGH // State to write pin for tare
+ //#define PROBE_TARE_PIN PA5 // Override default pin
+ #if ENABLED(PROBE_ACTIVATION_SWITCH)
+ //#define PROBE_TARE_ONLY_WHILE_INACTIVE // Fail to tare/probe if PROBE_ACTIVATION_SWITCH is active
+ #endif
+#endif
+
+/**
+ * Probe Enable / Disable
+ * The probe only provides a triggered signal when enabled.
+ */
+//#define PROBE_ENABLE_DISABLE
+#if ENABLED(PROBE_ENABLE_DISABLE)
+ //#define PROBE_ENABLE_PIN -1 // Override the default pin here
+#endif
/**
* Multiple Probing
@@ -1061,23 +1587,44 @@
//#define PROBING_HEATERS_OFF // Turn heaters off when probing
#if ENABLED(PROBING_HEATERS_OFF)
//#define WAIT_FOR_BED_HEATER // Wait for bed to heat back up between probes (to improve accuracy)
+ //#define WAIT_FOR_HOTEND // Wait for hotend to heat back up between probes (to improve accuracy & prevent cold extrude)
#endif
//#define PROBING_FANS_OFF // Turn fans off when probing
-//#define PROBING_STEPPERS_OFF // Turn steppers off (unless needed to hold position) when probing
+//#define PROBING_ESTEPPERS_OFF // Turn all extruder steppers off when probing
+//#define PROBING_STEPPERS_OFF // Turn all steppers off (unless needed to hold position) when probing (including extruders)
//#define DELAY_BEFORE_PROBING 200 // (ms) To prevent vibrations from triggering piezo sensors
+// Require minimum nozzle and/or bed temperature for probing
+#define PREHEAT_BEFORE_PROBING
+#if ENABLED(PREHEAT_BEFORE_PROBING)
+ #define PROBING_NOZZLE_TEMP 120 // (°C) Only applies to E0 at this time
+ #define PROBING_BED_TEMP 50
+#endif
+
// For Inverting Stepper Enable Pins (Active Low) use 0, Non Inverting (Active High) use 1
// :{ 0:'Low', 1:'High' }
#define X_ENABLE_ON 0
#define Y_ENABLE_ON 0
#define Z_ENABLE_ON 0
#define E_ENABLE_ON 0 // For all extruders
+//#define I_ENABLE_ON 0
+//#define J_ENABLE_ON 0
+//#define K_ENABLE_ON 0
+//#define U_ENABLE_ON 0
+//#define V_ENABLE_ON 0
+//#define W_ENABLE_ON 0
// Disable axis steppers immediately when they're not being stepped.
// WARNING: When motors turn off there is a chance of losing position accuracy!
#define DISABLE_X false
#define DISABLE_Y false
#define DISABLE_Z false
+//#define DISABLE_I false
+//#define DISABLE_J false
+//#define DISABLE_K false
+//#define DISABLE_U false
+//#define DISABLE_V false
+//#define DISABLE_W false
// Turn off the display blinking that warns about possible accuracy reduction
//#define DISABLE_REDUCED_ACCURACY_WARNING
@@ -1087,12 +1634,18 @@
#define DISABLE_E true // Disable the extruder when not stepping
#define DISABLE_INACTIVE_EXTRUDER // Keep only the active extruder enabled
-// @section machine
+// @section motion
// Invert the stepper direction. Change (or reverse the motor connector) if an axis goes the wrong way.
#define INVERT_X_DIR false
-#define INVERT_Y_DIR false
+#define INVERT_Y_DIR false
#define INVERT_Z_DIR true
+//#define INVERT_I_DIR false
+//#define INVERT_J_DIR false
+//#define INVERT_K_DIR false
+//#define INVERT_U_DIR false
+//#define INVERT_V_DIR false
+//#define INVERT_W_DIR false
// @section extruder
@@ -1108,9 +1661,15 @@
// @section homing
-//#define NO_MOTION_BEFORE_HOMING // Inhibit movement until all axes have been homed
+//#define NO_MOTION_BEFORE_HOMING // Inhibit movement until all axes have been homed. Also enable HOME_AFTER_DEACTIVATE for extra safety.
+//#define HOME_AFTER_DEACTIVATE // Require rehoming after steppers are deactivated. Also enable NO_MOTION_BEFORE_HOMING for extra safety.
-//#define UNKNOWN_Z_NO_RAISE // Don't raise Z (lower the bed) if Z is "unknown." For beds that fall when Z is powered off.
+/**
+ * Set Z_IDLE_HEIGHT if the Z-Axis moves on its own when steppers are disabled.
+ * - Use a low value (i.e., Z_MIN_POS) if the nozzle falls down to the bed.
+ * - Use a large value (i.e., Z_MAX_POS) if the bed falls down, away from the nozzle.
+ */
+//#define Z_IDLE_HEIGHT Z_HOME_POS
//#define Z_HOMING_HEIGHT 4 // (mm) Minimal Z height before homing (G28) for Z clearance above the bed, clamps, ...
// Be sure to have this much clearance over your Z_MAX_POS to prevent grinding.
@@ -1122,20 +1681,38 @@
#define X_HOME_DIR 1
#define Y_HOME_DIR 1
#define Z_HOME_DIR 1
+//#define I_HOME_DIR -1
+//#define J_HOME_DIR -1
+//#define K_HOME_DIR -1
+//#define U_HOME_DIR -1
+//#define V_HOME_DIR -1
+//#define W_HOME_DIR -1
-// @section machine
+// @section geometry
-// The size of the print bed
+// The size of the printable area
#define X_BED_SIZE 236
#define Y_BED_SIZE 215
-// Travel limits (mm) after homing, corresponding to endstop positions.
+// Travel limits (linear=mm, rotational=°) after homing, corresponding to endstop positions.
#define X_MIN_POS 0
#define Y_MIN_POS 0
#define Z_MIN_POS 0
#define X_MAX_POS X_BED_SIZE
#define Y_MAX_POS Y_BED_SIZE
#define Z_MAX_POS 165
+//#define I_MIN_POS 0
+//#define I_MAX_POS 50
+//#define J_MIN_POS 0
+//#define J_MAX_POS 50
+//#define K_MIN_POS 0
+//#define K_MAX_POS 50
+//#define U_MIN_POS 0
+//#define U_MAX_POS 50
+//#define V_MIN_POS 0
+//#define V_MAX_POS 50
+//#define W_MIN_POS 0
+//#define W_MAX_POS 50
/**
* Software Endstops
@@ -1152,6 +1729,12 @@
#define MIN_SOFTWARE_ENDSTOP_X
#define MIN_SOFTWARE_ENDSTOP_Y
#define MIN_SOFTWARE_ENDSTOP_Z
+ #define MIN_SOFTWARE_ENDSTOP_I
+ #define MIN_SOFTWARE_ENDSTOP_J
+ #define MIN_SOFTWARE_ENDSTOP_K
+ #define MIN_SOFTWARE_ENDSTOP_U
+ #define MIN_SOFTWARE_ENDSTOP_V
+ #define MIN_SOFTWARE_ENDSTOP_W
#endif
// Max software endstops constrain movement within maximum coordinate bounds
@@ -1160,6 +1743,12 @@
#define MAX_SOFTWARE_ENDSTOP_X
#define MAX_SOFTWARE_ENDSTOP_Y
#define MAX_SOFTWARE_ENDSTOP_Z
+ #define MAX_SOFTWARE_ENDSTOP_I
+ #define MAX_SOFTWARE_ENDSTOP_J
+ #define MAX_SOFTWARE_ENDSTOP_K
+ #define MAX_SOFTWARE_ENDSTOP_U
+ #define MAX_SOFTWARE_ENDSTOP_V
+ #define MAX_SOFTWARE_ENDSTOP_W
#endif
#if EITHER(MIN_SOFTWARE_ENDSTOPS, MAX_SOFTWARE_ENDSTOPS)
@@ -1170,6 +1759,12 @@
* Filament Runout Sensors
* Mechanical or opto endstops are used to check for the presence of filament.
*
+ * IMPORTANT: Runout will only trigger if Marlin is aware that a print job is running.
+ * Marlin knows a print job is running when:
+ * 1. Running a print job from media started with M24.
+ * 2. The Print Job Timer has been started with M75.
+ * 3. The heaters were turned on and PRINTJOB_TIMER_AUTOSTART is enabled.
+ *
* RAMPS-based boards use SERVO3_PIN for the first runout sensor.
* For other boards you may need to define FIL_RUNOUT_PIN, FIL_RUNOUT2_PIN, etc.
*/
@@ -1177,12 +1772,49 @@
#if ENABLED(FILAMENT_RUNOUT_SENSOR)
#define FIL_RUNOUT_ENABLED_DEFAULT true // Enable the sensor on startup. Override with M412 followed by M500.
#define NUM_RUNOUT_SENSORS 1 // Number of sensors, up to one per extruder. Define a FIL_RUNOUT#_PIN for each.
+
#define FIL_RUNOUT_STATE LOW // Pin state indicating that filament is NOT present.
#define FIL_RUNOUT_PULLUP // Use internal pullup for filament runout pins.
//#define FIL_RUNOUT_PULLDOWN // Use internal pulldown for filament runout pins.
+ //#define WATCH_ALL_RUNOUT_SENSORS // Execute runout script on any triggering sensor, not only for the active extruder.
+ // This is automatically enabled for MIXING_EXTRUDERs.
+
+ // Override individually if the runout sensors vary
+ //#define FIL_RUNOUT1_STATE LOW
+ //#define FIL_RUNOUT1_PULLUP
+ //#define FIL_RUNOUT1_PULLDOWN
+
+ //#define FIL_RUNOUT2_STATE LOW
+ //#define FIL_RUNOUT2_PULLUP
+ //#define FIL_RUNOUT2_PULLDOWN
+
+ //#define FIL_RUNOUT3_STATE LOW
+ //#define FIL_RUNOUT3_PULLUP
+ //#define FIL_RUNOUT3_PULLDOWN
+
+ //#define FIL_RUNOUT4_STATE LOW
+ //#define FIL_RUNOUT4_PULLUP
+ //#define FIL_RUNOUT4_PULLDOWN
+
+ //#define FIL_RUNOUT5_STATE LOW
+ //#define FIL_RUNOUT5_PULLUP
+ //#define FIL_RUNOUT5_PULLDOWN
- // Set one or more commands to execute on filament runout.
- // (After 'M412 H' Marlin will ask the host to handle the process.)
+ //#define FIL_RUNOUT6_STATE LOW
+ //#define FIL_RUNOUT6_PULLUP
+ //#define FIL_RUNOUT6_PULLDOWN
+
+ //#define FIL_RUNOUT7_STATE LOW
+ //#define FIL_RUNOUT7_PULLUP
+ //#define FIL_RUNOUT7_PULLDOWN
+
+ //#define FIL_RUNOUT8_STATE LOW
+ //#define FIL_RUNOUT8_PULLUP
+ //#define FIL_RUNOUT8_PULLDOWN
+
+ // Commands to execute on filament runout.
+ // With multiple runout sensors use the %c placeholder for the current tool in commands (e.g., "M600 T%c")
+ // NOTE: After 'M412 H1' the host handles filament runout and this script does not apply.
#define FILAMENT_RUNOUT_SCRIPT "M600"
// After a runout is detected, continue printing this length of filament
@@ -1243,10 +1875,30 @@
//#define MESH_BED_LEVELING
/**
- * Normally G28 leaves leveling disabled on completion. Enable
- * this option to have G28 restore the prior leveling state.
+ * Normally G28 leaves leveling disabled on completion. Enable one of
+ * these options to restore the prior leveling state or to always enable
+ * leveling immediately after G28.
*/
#define RESTORE_LEVELING_AFTER_G28
+//#define ENABLE_LEVELING_AFTER_G28
+
+/**
+ * Auto-leveling needs preheating
+ */
+//#define PREHEAT_BEFORE_LEVELING
+#if ENABLED(PREHEAT_BEFORE_LEVELING)
+ #define LEVELING_NOZZLE_TEMP 120 // (°C) Only applies to E0 at this time
+ #define LEVELING_BED_TEMP 50
+#endif
+
+/**
+ * Bed Distance Sensor
+ *
+ * Measures the distance from bed to nozzle with accuracy of 0.01mm.
+ * For information about this sensor https://github.com/markniu/Bed_Distance_sensor
+ * Uses I2C port, so it requires I2C library markyue/Panda_SoftMasterI2C.
+ */
+//#define BD_SENSOR
/**
* Enable detailed logging of G28, G29, M48, etc.
@@ -1255,11 +1907,19 @@
*/
//#define DEBUG_LEVELING_FEATURE
+#if ANY(MESH_BED_LEVELING, AUTO_BED_LEVELING_UBL, PROBE_MANUALLY)
+ // Set a height for the start of manual adjustment
+ #define MANUAL_PROBE_START_Z 0.2 // (mm) Comment out to use the last-measured height
+#endif
+
#if ANY(MESH_BED_LEVELING, AUTO_BED_LEVELING_BILINEAR, AUTO_BED_LEVELING_UBL)
// Gradually reduce leveling correction until a set height is reached,
// at which point movement will be level to the machine's XY plane.
// The height can be set with M420 Z
#define ENABLE_LEVELING_FADE_HEIGHT
+ #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
+ #define DEFAULT_LEVELING_FADE_HEIGHT 10.0 // (mm) Default fade height.
+ #endif
// For Cartesian machines, instead of dividing moves on mesh boundaries,
// split up moves into short segments like a Delta. This follows the
@@ -1273,10 +1933,11 @@
#define G26_MESH_VALIDATION
#if ENABLED(G26_MESH_VALIDATION)
#define MESH_TEST_NOZZLE_SIZE 0.4 // (mm) Diameter of primary nozzle.
- #define MESH_TEST_LAYER_HEIGHT 0.2 // (mm) Default layer height for the G26 Mesh Validation Tool.
- #define MESH_TEST_HOTEND_TEMP 205 // (°C) Default nozzle temperature for the G26 Mesh Validation Tool.
- #define MESH_TEST_BED_TEMP 60 // (°C) Default bed temperature for the G26 Mesh Validation Tool.
- #define G26_XY_FEEDRATE 20 // (mm/s) Feedrate for XY Moves for the G26 Mesh Validation Tool.
+ #define MESH_TEST_LAYER_HEIGHT 0.2 // (mm) Default layer height for G26.
+ #define MESH_TEST_HOTEND_TEMP 205 // (°C) Default nozzle temperature for G26.
+ #define MESH_TEST_BED_TEMP 60 // (°C) Default bed temperature for G26.
+ #define G26_XY_FEEDRATE 20 // (mm/s) Feedrate for G26 XY moves.
+ #define G26_XY_FEEDRATE_TRAVEL 100 // (mm/s) Feedrate for G26 XY travel moves.
#define G26_RETRACT_MULTIPLIER 1.0 // G26 Q (retraction) used by default between mesh test elements.
#endif
@@ -1321,12 +1982,16 @@
#define GRID_MAX_POINTS_X 10 // Don't use more than 15 points per axis, implementation limited.
#define GRID_MAX_POINTS_Y GRID_MAX_POINTS_X
+ //#define UBL_HILBERT_CURVE // Use Hilbert distribution for less travel when probing multiple points
+
#define UBL_MESH_EDIT_MOVES_Z // Sophisticated users prefer no movement of nozzle
#define UBL_SAVE_ACTIVE_ON_M500 // Save the currently active mesh in the current slot on M500
//#define UBL_Z_RAISE_WHEN_OFF_MESH 2.5 // When the nozzle is off the mesh, this value is used
// as the Z-Height correction value.
+ //#define UBL_MESH_WIZARD // Run several commands in a row to get a complete mesh
+
#elif ENABLED(MESH_BED_LEVELING)
//===========================================================================
@@ -1354,13 +2019,38 @@
#endif
// Add a menu item to move between bed corners for manual bed adjustment
-//#define LEVEL_BED_CORNERS
+//#define 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 leveling points
+ #define BED_TRAMMING_Z_HOP 4.0 // (mm) Z height of nozzle between leveling points
+ //#define BED_TRAMMING_INCLUDE_CENTER // Move to the center after the last corner
+ //#define BED_TRAMMING_USE_PROBE
+ #if ENABLED(BED_TRAMMING_USE_PROBE)
+ #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_AUDIO_FEEDBACK
+ #endif
-#if ENABLED(LEVEL_BED_CORNERS)
- #define LEVEL_CORNERS_INSET_LFRB { 30, 30, 30, 30 } // (mm) Left, Front, Right, Back insets
- #define LEVEL_CORNERS_HEIGHT 0.0 // (mm) Z height of nozzle at leveling points
- #define LEVEL_CORNERS_Z_HOP 4.0 // (mm) Z height of nozzle between leveling points
- //#define LEVEL_CENTER_TOO // Move to the center after the last corner
+ /**
+ * Corner Leveling Order
+ *
+ * Set 2 or 4 points. When 2 points are given, the 3rd is the center of the opposite edge.
+ *
+ * LF Left-Front RF Right-Front
+ * LB Left-Back RB Right-Back
+ *
+ * Examples:
+ *
+ * Default {LF,RB,LB,RF} {LF,RF} {LB,LF}
+ * LB --------- RB LB --------- RB LB --------- RB LB --------- RB
+ * | 4 3 | | 3 2 | | <3> | | 1 |
+ * | | | | | | | <3>|
+ * | 1 2 | | 1 4 | | 1 2 | | 2 |
+ * LF --------- RF LF --------- RF LF --------- RF LF --------- RF
+ */
+ #define BED_TRAMMING_LEVELING_ORDER { LF, RF, RB, LB }
#endif
/**
@@ -1379,16 +2069,20 @@
//#define MANUAL_X_HOME_POS 0
//#define MANUAL_Y_HOME_POS 0
//#define MANUAL_Z_HOME_POS 0
+//#define MANUAL_I_HOME_POS 0
+//#define MANUAL_J_HOME_POS 0
+//#define MANUAL_K_HOME_POS 0
+//#define MANUAL_U_HOME_POS 0
+//#define MANUAL_V_HOME_POS 0
+//#define MANUAL_W_HOME_POS 0
-// Use "Z Safe Homing" to avoid homing with a Z probe outside the bed area.
-//
-// With this feature enabled:
-//
-// - Allow Z homing only after X and Y homing AND stepper drivers still enabled.
-// - If stepper drivers time out, it will need X and Y homing again before Z homing.
-// - Move the Z probe (or nozzle) to a defined XY point before Z Homing.
-// - Prevent Z homing when the Z probe is outside bed area.
-//
+/**
+ * Use "Z Safe Homing" to avoid homing with a Z probe outside the bed area.
+ *
+ * - Moves the Z probe (or nozzle) to a defined XY point before Z homing.
+ * - Allows Z homing only when XY positions are known and trusted.
+ * - If stepper drivers sleep, XY homing may be required again before Z homing.
+ */
//#define Z_SAFE_HOMING
#if ENABLED(Z_SAFE_HOMING)
@@ -1396,9 +2090,8 @@
#define Z_SAFE_HOMING_Y_POINT Y_CENTER // Y point for Z homing
#endif
-// Homing speeds (mm/min)
-#define HOMING_FEEDRATE_XY (50*60)
-#define HOMING_FEEDRATE_Z (12*60)
+// Homing speeds (linear=mm/min, rotational=°/min)
+#define HOMING_FEEDRATE_MM_M { (50*60), (50*60), (12*60) }
// Validate that endstops are triggered on homing moves
#define VALIDATE_HOMING_ENDSTOPS
@@ -1441,9 +2134,8 @@
#define XY_DIAG_BD 282.8427124746
#define XY_SIDE_AD 200
- // Or, set the default skew factors directly here
- // to override the above measurements:
- #define XY_SKEW_FACTOR 0.0
+ // Or, set the XY skew factor directly:
+ //#define XY_SKEW_FACTOR 0.0
//#define SKEW_CORRECTION_FOR_Z
#if ENABLED(SKEW_CORRECTION_FOR_Z)
@@ -1452,8 +2144,10 @@
#define YZ_DIAG_AC 282.8427124746
#define YZ_DIAG_BD 282.8427124746
#define YZ_SIDE_AD 200
- #define XZ_SKEW_FACTOR 0.0
- #define YZ_SKEW_FACTOR 0.0
+
+ // Or, set the Z skew factors directly:
+ //#define XZ_SKEW_FACTOR 0.0
+ //#define YZ_SKEW_FACTOR 0.0
#endif
// Enable this option for M852 to set skew at runtime
@@ -1464,7 +2158,7 @@
//============================= Additional Features ===========================
//=============================================================================
-// @section extras
+// @section eeprom
/**
* EEPROM
@@ -1476,13 +2170,16 @@
* M502 - Revert settings to "factory" defaults. (Follow with M500 to init the EEPROM.)
*/
#define EEPROM_SETTINGS // Persistent storage with M500 and M501
-//#define DISABLE_M503 // Saves ~2700 bytes of PROGMEM. Disable for release!
+//#define DISABLE_M503 // Saves ~2700 bytes of flash. Disable for release!
#define EEPROM_CHITCHAT // Give feedback on EEPROM commands. Disable to save PROGMEM.
#define EEPROM_BOOT_SILENT // Keep M503 quiet and only give errors during first load
#if ENABLED(EEPROM_SETTINGS)
#define EEPROM_AUTO_INIT // Init EEPROM automatically on any errors.
+ //#define EEPROM_INIT_NOW // Init EEPROM on first boot after a new build.
#endif
+// @section host
+
//
// Host Keepalive
//
@@ -1493,6 +2190,8 @@
#define DEFAULT_KEEPALIVE_INTERVAL 2 // Number of seconds between "busy" messages. Set with M113.
#define BUSY_WHILE_HEATING // Some hosts require "busy" messages even during heating
+// @section units
+
//
// G20/G21 Inch mode support
//
@@ -1505,17 +2204,23 @@
// @section temperature
-// Preheat Constants
+//
+// Preheat Constants - Up to 10 are supported without changes
+//
#define PREHEAT_1_LABEL "PLA"
#define PREHEAT_1_TEMP_HOTEND 180
#define PREHEAT_1_TEMP_BED 65
+#define PREHEAT_1_TEMP_CHAMBER 35
#define PREHEAT_1_FAN_SPEED 0 // Value from 0 to 255
#define PREHEAT_2_LABEL "ABS"
#define PREHEAT_2_TEMP_HOTEND 240
#define PREHEAT_2_TEMP_BED 110
+#define PREHEAT_2_TEMP_CHAMBER 35
#define PREHEAT_2_FAN_SPEED 0 // Value from 0 to 255
+// @section motion
+
/**
* Nozzle Park
*
@@ -1532,8 +2237,7 @@
#if ENABLED(NOZZLE_PARK_FEATURE)
// Specify a park position as { X, Y, Z_raise }
#define NOZZLE_PARK_POINT { (X_MIN_POS + 10), (Y_MAX_POS - 10), 20 }
- //#define NOZZLE_PARK_X_ONLY // X move only is required to park
- //#define NOZZLE_PARK_Y_ONLY // Y move only is required to park
+ #define NOZZLE_PARK_MOVE 0 // Park motion: 0 = XY Move, 1 = X Only, 2 = Y Only, 3 = X before Y, 4 = Y before X
#define NOZZLE_PARK_Z_RAISE_MIN 2 // (mm) Always raise Z by at least this distance
#define NOZZLE_PARK_XY_FEEDRATE 100 // (mm/s) X and Y axes feedrate (also used for delta Z axis)
#define NOZZLE_PARK_Z_FEEDRATE 5 // (mm/s) Z axis feedrate (not used for delta printers)
@@ -1606,19 +2310,34 @@
// For a purge/clean station mounted on the X axis
//#define NOZZLE_CLEAN_NO_Y
+ // Require a minimum hotend temperature for cleaning
+ #define NOZZLE_CLEAN_MIN_TEMP 170
+ //#define NOZZLE_CLEAN_HEATUP // Heat up the nozzle instead of skipping wipe
+
// Explicit wipe G-code script applies to a G12 with no arguments.
//#define WIPE_SEQUENCE_COMMANDS "G1 X-17 Y25 Z10 F4000\nG1 Z1\nM114\nG1 X-17 Y25\nG1 X-17 Y95\nG1 X-17 Y25\nG1 X-17 Y95\nG1 X-17 Y25\nG1 X-17 Y95\nG1 X-17 Y25\nG1 X-17 Y95\nG1 X-17 Y25\nG1 X-17 Y95\nG1 X-17 Y25\nG1 X-17 Y95\nG1 Z15\nM400\nG0 X-10.0 Y-9.0"
#endif
+// @section host
+
/**
* Print Job Timer
*
- * Automatically start and stop the print job timer on M104/M109/M190.
+ * Automatically start and stop the print job timer on M104/M109/M140/M190/M141/M191.
+ * The print job timer will only be stopped if the bed/chamber target temp is
+ * below BED_MINTEMP/CHAMBER_MINTEMP.
+ *
+ * M104 (hotend, no wait) - high temp = none, low temp = stop timer
+ * M109 (hotend, wait) - high temp = start timer, low temp = stop timer
+ * M140 (bed, no wait) - high temp = none, low temp = stop timer
+ * M190 (bed, wait) - high temp = start timer, low temp = none
+ * M141 (chamber, no wait) - high temp = none, low temp = stop timer
+ * M191 (chamber, wait) - high temp = start timer, low temp = none
*
- * M104 (hotend, no wait) - high temp = none, low temp = stop timer
- * M109 (hotend, wait) - high temp = start timer, low temp = stop timer
- * M190 (bed, wait) - high temp = start timer, low temp = none
+ * For M104/M109, high temp is anything over EXTRUDE_MINTEMP / 2.
+ * For M140/M190, high temp is anything over BED_MINTEMP.
+ * For M141/M191, high temp is anything over CHAMBER_MINTEMP.
*
* The timer can also be controlled with the following commands:
*
@@ -1628,6 +2347,8 @@
*/
#define PRINTJOB_TIMER_AUTOSTART
+// @section stats
+
/**
* Print Counter
*
@@ -1641,6 +2362,11 @@
* View the current statistics with M78.
*/
//#define PRINTCOUNTER
+#if ENABLED(PRINTCOUNTER)
+ #define PRINTCOUNTER_SAVE_INTERVAL 60 // (minutes) EEPROM save interval during print. A value of 0 will save stats at end of print.
+#endif
+
+// @section security
/**
* Password
@@ -1677,17 +2403,17 @@
//============================= LCD and SD support ============================
//=============================================================================
-// @section lcd
+// @section interface
/**
* LCD LANGUAGE
*
* Select the language to display on the LCD. These languages are available:
*
- * en, an, bg, ca, cz, da, de, el, el_gr, es, eu, fi, fr, gl, hr, hu, it,
- * jp_kana, ko_KR, nl, pl, pt, pt_br, ro, ru, sk, tr, uk, vi, zh_CN, zh_TW, test
+ * 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
*
- * :{ 'en':'English', 'an':'Aragonese', 'bg':'Bulgarian', 'ca':'Catalan', 'cz':'Czech', 'da':'Danish', 'de':'German', 'el':'Greek', 'el_gr':'Greek (Greece)', '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', 'tr':'Turkish', 'uk':'Ukrainian', 'vi':'Vietnamese', 'zh_CN':'Chinese (Simplified)', 'zh_TW':'Chinese (Traditional)', 'test':'TEST' }
+ * :{ '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
@@ -1728,17 +2454,7 @@
* SD Card support is disabled by default. If your controller has an SD slot,
* you must uncomment the following option or it won't work.
*/
-#define SDSUPPORT
-
-/**
- * SD CARD: SPI SPEED
- *
- * Enable one of the following items for a slower SPI transfer speed.
- * This may be required to resolve "volume init" errors.
- */
-//#define SPI_SPEED SPI_HALF_SPEED
-//#define SPI_SPEED SPI_QUARTER_SPEED
-//#define SPI_SPEED SPI_EIGHTH_SPEED
+//#define SDSUPPORT
/**
* SD CARD: ENABLE CRC
@@ -1803,12 +2519,23 @@
//
//#define REVERSE_SELECT_DIRECTION
+//
+// Encoder EMI Noise Filter
+//
+// This option increases encoder samples to filter out phantom encoder clicks caused by EMI noise.
+//
+//#define ENCODER_NOISE_FILTER
+#if ENABLED(ENCODER_NOISE_FILTER)
+ #define ENCODER_SAMPLES 10
+#endif
+
//
// Individual Axis Homing
//
// Add individual axis homing items (Home X, Home Y, and Home Z) to the LCD menu.
//
//#define INDIVIDUAL_AXIS_HOMING_MENU
+//#define INDIVIDUAL_AXIS_HOMING_SUBMENU
//
// SPEAKER/BUZZER
@@ -1832,6 +2559,7 @@
//======================== LCD / Controller Selection =========================
//======================== (Character-based LCDs) =========================
//=============================================================================
+// @section lcd
//
// RepRapDiscount Smart Controller.
@@ -1841,6 +2569,14 @@
//
//#define REPRAP_DISCOUNT_SMART_CONTROLLER
+//
+// GT2560 (YHCB2004) LCD Display
+//
+// Requires Testato, Koepel softwarewire library and
+// Andriy Golovnya's LiquidCrystal_AIP31068 library.
+//
+//#define YHCB2004
+
//
// Original RADDS LCD Display+Encoder+SDCardReader
// http://doku.radds.org/dokumentation/lcd-display/
@@ -1991,6 +2727,11 @@
//
//#define REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER
+//
+// K.3D Full Graphic Smart Controller
+//
+//#define K3D_FULL_GRAPHIC_SMART_CONTROLLER
+
//
// ReprapWorld Graphical LCD
// https://reprapworld.com/?products_details&products_id/1218
@@ -2005,6 +2746,11 @@
//#define VIKI2
//#define miniVIKI
+//
+// Alfawise Ex8 printer LCD marked as WYH L12864 COG
+//
+//#define WYH_L12864
+
//
// MakerLab Mini Panel with graphic
// controller and SD support - https://reprap.org/wiki/Mini_panel
@@ -2052,11 +2798,17 @@
//
//#define MKS_MINI_12864
+//
+// MKS MINI12864 V3 is an alias for FYSETC_MINI_12864_2_1. Type A/B. NeoPixel RGB Backlight.
+//
+//#define MKS_MINI_12864_V3
+
//
// MKS LCD12864A/B with graphic controller and SD support. Follows MKS_MINI_12864 pinout.
// https://www.aliexpress.com/item/33018110072.html
//
-//#define MKS_LCD12864
+//#define MKS_LCD12864A
+//#define MKS_LCD12864B
//
// FYSETC variant of the MINI12864 graphic controller with SD support
@@ -2068,6 +2820,11 @@
//#define FYSETC_MINI_12864_2_1 // Type A/B. NeoPixel RGB Backlight
//#define FYSETC_GENERIC_12864_1_1 // Larger display with basic ON/OFF backlight.
+//
+// BigTreeTech Mini 12864 V1.0 is an alias for FYSETC_MINI_12864_2_1. Type A/B. NeoPixel RGB Backlight.
+//
+//#define BTT_MINI_12864_V1
+
//
// Factory display for Creality CR-10
// https://www.aliexpress.com/item/32833148327.html
@@ -2087,9 +2844,10 @@
//
// Anet 128x64 full graphics lcd with rotary encoder as used on Anet A6
// A clone of the RepRapDiscount full graphics display but with
-// different pins/wiring (see pins_ANET_10.h).
+// different pins/wiring (see pins_ANET_10.h). Enable one of these.
//
//#define ANET_FULL_GRAPHICS_LCD
+//#define ANET_FULL_GRAPHICS_LCD_ALT_WIRING
//
// AZSMZ 12864 LCD with SD
@@ -2103,6 +2861,12 @@
//
//#define SILVER_GATE_GLCD_CONTROLLER
+//
+// eMotion Tech LCD with SD
+// https://www.reprap-france.com/produit/1234568748-ecran-graphique-128-x-64-points-2-1
+//
+//#define EMOTION_TECH_LCD
+
//=============================================================================
//============================== OLED Displays ==============================
//=============================================================================
@@ -2127,7 +2891,7 @@
//#define OLED_PANEL_TINYBOY2
//
-// MKS OLED 1.3" 128×64 FULL GRAPHICS CONTROLLER
+// MKS OLED 1.3" 128×64 Full Graphics Controller
// https://reprap.org/wiki/MKS_12864OLED
//
// Tiny, but very sharp OLED display
@@ -2136,7 +2900,7 @@
#define MKS_12864OLED_SSD1306 // Uses the SSD1306 controller
//
-// Zonestar OLED 128×64 FULL GRAPHICS CONTROLLER
+// Zonestar OLED 128×64 Full Graphics Controller
//
//#define ZONESTAR_12864LCD // Graphical (DOGM) with ST7920 controller
//#define ZONESTAR_12864OLED // 1.3" OLED with SH1106 controller (default)
@@ -2153,30 +2917,64 @@
//#define OVERLORD_OLED
//
-// FYSETC OLED 2.42" 128×64 FULL GRAPHICS CONTROLLER with WS2812 RGB
+// FYSETC OLED 2.42" 128×64 Full Graphics Controller with WS2812 RGB
// Where to find : https://www.aliexpress.com/item/4000345255731.html
//#define FYSETC_242_OLED_12864 // Uses the SSD1309 controller
+//
+// K.3D SSD1309 OLED 2.42" 128×64 Full Graphics Controller
+//
+//#define K3D_242_OLED_CONTROLLER // Software SPI
+
//=============================================================================
//========================== Extensible UI Displays ===========================
//=============================================================================
-//
-// DGUS Touch Display with DWIN OS. (Choose one.)
-// ORIGIN : https://www.aliexpress.com/item/32993409517.html
-// FYSETC : https://www.aliexpress.com/item/32961471929.html
-//
+/**
+ * DGUS Touch Display with DWIN OS. (Choose one.)
+ * ORIGIN : https://www.aliexpress.com/item/32993409517.html
+ * FYSETC : https://www.aliexpress.com/item/32961471929.html
+ * MKS : https://www.aliexpress.com/item/1005002008179262.html
+ *
+ * Flash display with DGUS Displays for Marlin:
+ * - Format the SD card to FAT32 with an allocation size of 4kb.
+ * - Download files as specified for your type of display.
+ * - Plug the microSD card into the back of the display.
+ * - Boot the display and wait for the update to complete.
+ *
+ * ORIGIN (Marlin DWIN_SET)
+ * - Download https://github.com/coldtobi/Marlin_DGUS_Resources
+ * - Copy the downloaded DWIN_SET folder to the SD card.
+ *
+ * FYSETC (Supplier default)
+ * - Download https://github.com/FYSETC/FYSTLCD-2.0
+ * - Copy the downloaded SCREEN folder to the SD card.
+ *
+ * HIPRECY (Supplier default)
+ * - Download https://github.com/HiPrecy/Touch-Lcd-LEO
+ * - Copy the downloaded DWIN_SET folder to the SD card.
+ *
+ * MKS (MKS-H43) (Supplier default)
+ * - Download https://github.com/makerbase-mks/MKS-H43
+ * - Copy the downloaded DWIN_SET folder to the SD card.
+ *
+ * RELOADED (T5UID1)
+ * - Download https://github.com/Desuuuu/DGUS-reloaded/releases
+ * - Copy the downloaded DWIN_SET folder to the SD card.
+ */
//#define DGUS_LCD_UI_ORIGIN
//#define DGUS_LCD_UI_FYSETC
//#define DGUS_LCD_UI_HIPRECY
+//#define DGUS_LCD_UI_MKS
+//#define DGUS_LCD_UI_RELOADED
+#if ENABLED(DGUS_LCD_UI_MKS)
+ #define USE_MKS_GREEN_UI
+#endif
//
// Touch-screen LCD for Malyan M200/M300 printers
//
//#define MALYAN_LCD
-#if ENABLED(MALYAN_LCD)
- #define LCD_SERIAL_PORT 1 // Default is 1 for Malyan M200
-#endif
//
// Touch UI for FTDI EVE (FT800/FT810) displays
@@ -2190,10 +2988,14 @@
//#define ANYCUBIC_LCD_I3MEGA
//#define ANYCUBIC_LCD_CHIRON
#if EITHER(ANYCUBIC_LCD_I3MEGA, ANYCUBIC_LCD_CHIRON)
- #define LCD_SERIAL_PORT 3 // Default is 3 for Anycubic
//#define ANYCUBIC_LCD_DEBUG
#endif
+//
+// 320x240 Nextion 2.8" serial TFT Resistive Touch Screen NX3224T028
+//
+//#define NEXTION_TFT
+
//
// Third-party or vendor-customized controller interfaces.
// Sources should be installed in 'src/lcd/extui'.
@@ -2214,32 +3016,32 @@
*/
//
-// 480x320, 3.5", SPI Display From MKS
-// Normally used in MKS Robin Nano V2
+// 480x320, 3.5", SPI Display with Rotary Encoder from MKS
+// Usually paired with MKS Robin Nano V2 & V3
//
//#define MKS_TS35_V2_0
//
// 320x240, 2.4", FSMC Display From MKS
-// Normally used in MKS Robin Nano V1.2
+// Usually paired with MKS Robin Nano V1.2
//
//#define MKS_ROBIN_TFT24
//
// 320x240, 2.8", FSMC Display From MKS
-// Normally used in MKS Robin Nano V1.2
+// Usually paired with MKS Robin Nano V1.2
//
//#define MKS_ROBIN_TFT28
//
// 320x240, 3.2", FSMC Display From MKS
-// Normally used in MKS Robin Nano V1.2
+// Usually paired with MKS Robin Nano V1.2
//
//#define MKS_ROBIN_TFT32
//
// 480x320, 3.5", FSMC Display From MKS
-// Normally used in MKS Robin Nano V1.2
+// Usually paired with MKS Robin Nano V1.2
//
//#define MKS_ROBIN_TFT35
@@ -2250,7 +3052,7 @@
//
// 320x240, 3.2", FSMC Display From MKS
-// Normally used in MKS Robin
+// Usually paired with MKS Robin
//
//#define MKS_ROBIN_TFT_V1_1R
@@ -2269,6 +3071,26 @@
//
//#define LONGER_LK_TFT28
+//
+// 320x240, 2.8", FSMC Stock Display from ET4
+//
+//#define ANET_ET4_TFT28
+
+//
+// 480x320, 3.5", FSMC Stock Display from ET5
+//
+//#define ANET_ET5_TFT35
+
+//
+// 1024x600, 7", RGB Stock Display with Rotary Encoder from BIQU-BX
+//
+//#define BIQU_BX_TFT70
+
+//
+// 480x320, 3.5", SPI Stock Display with Rotary Encoder from BIQU B1 SE Series
+//
+//#define BTT_TFT35_SPI_V1_0
+
//
// Generic TFT with detailed options
//
@@ -2285,6 +3107,7 @@
//#define TFT_RES_320x240
//#define TFT_RES_480x272
//#define TFT_RES_480x320
+ //#define TFT_RES_1024x600
#endif
/**
@@ -2301,6 +3124,10 @@
//#define TFT_COLOR_UI
//#define TFT_LVGL_UI
+#if ENABLED(TFT_LVGL_UI)
+ //#define MKS_WIFI_MODULE // MKS WiFi module
+#endif
+
/**
* TFT Rotation. Set to one of the following values:
*
@@ -2318,22 +3145,38 @@
//
// Ender-3 v2 OEM display. A DWIN display with Rotary Encoder.
//
-//#define DWIN_CREALITY_LCD
+//#define DWIN_CREALITY_LCD // Creality UI
+//#define DWIN_LCD_PROUI // Pro UI by MRiscoC
+//#define DWIN_CREALITY_LCD_JYERSUI // Jyers UI by Jacob Myers
+//#define DWIN_MARLINUI_PORTRAIT // MarlinUI (portrait orientation)
+//#define DWIN_MARLINUI_LANDSCAPE // MarlinUI (landscape orientation)
//
-// ADS7843/XPT2046 ADC Touchscreen such as ILI9341 2.8
+// Touch Screen Settings
//
//#define TOUCH_SCREEN
#if ENABLED(TOUCH_SCREEN)
- #define BUTTON_DELAY_EDIT 50 // (ms) Button repeat delay for edit screens
- #define BUTTON_DELAY_MENU 250 // (ms) Button repeat delay for menus
+ #define BUTTON_DELAY_EDIT 50 // (ms) Button repeat delay for edit screens
+ #define BUTTON_DELAY_MENU 250 // (ms) Button repeat delay for menus
+
+ //#define DISABLE_ENCODER // Disable the click encoder, if any
+ //#define TOUCH_IDLE_SLEEP_MINS 5 // (minutes) Display Sleep after a period of inactivity. Set with M255 S.
#define TOUCH_SCREEN_CALIBRATION
- //#define XPT2046_X_CALIBRATION 12316
- //#define XPT2046_Y_CALIBRATION -8981
- //#define XPT2046_X_OFFSET -43
- //#define XPT2046_Y_OFFSET 257
+ //#define TOUCH_CALIBRATION_X 12316
+ //#define TOUCH_CALIBRATION_Y -8981
+ //#define TOUCH_OFFSET_X -43
+ //#define TOUCH_OFFSET_Y 257
+ //#define TOUCH_ORIENTATION TOUCH_LANDSCAPE
+
+ #if BOTH(TOUCH_SCREEN_CALIBRATION, EEPROM_SETTINGS)
+ #define TOUCH_CALIBRATION_AUTO_SAVE // Auto save successful calibration values to EEPROM
+ #endif
+
+ #if ENABLED(TFT_COLOR_UI)
+ //#define SINGLE_TOUCH_NAVIGATION
+ #endif
#endif
//
@@ -2343,19 +3186,21 @@
//#define REPRAPWORLD_KEYPAD
//#define REPRAPWORLD_KEYPAD_MOVE_STEP 10.0 // (mm) Distance to move per key-press
+//
+// EasyThreeD ET-4000+ with button input and status LED
+//
+//#define EASYTHREED_UI
+
//=============================================================================
//=============================== Extra Features ==============================
//=============================================================================
-// @section extras
+// @section fans
// Set number of user-controlled fans. Disable to use all board-defined fans.
// :[1,2,3,4,5,6,7,8]
//#define NUM_M106_FANS 1
-// Increase the FAN PWM frequency. Removes the PWM noise but increases heating in the FET/Arduino
-//#define FAST_PWM_FAN
-
// Use software PWM to drive the fan, as for the heaters. This uses a very low frequency
// which is not as annoying as with the hardware PWM. On the other hand, if this frequency
// is too low, you should also increment SOFT_PWM_SCALE.
@@ -2374,14 +3219,18 @@
// duty cycle is attained.
//#define SOFT_PWM_DITHER
+// @section extras
+
+// Support for the BariCUDA Paste Extruder
+//#define BARICUDA
+
+// @section lights
+
// Temperature status LEDs that display the hotend and bed temperature.
// If all hotends, bed temperature, and target temperature are under 54C
// then the BLUE led is on. Otherwise the RED led is on. (1C hysteresis)
//#define TEMP_STAT_LEDS
-// Support for the BariCUDA Paste Extruder
-//#define BARICUDA
-
// Support for BlinkM/CyzRgb
//#define BLINKM
@@ -2425,28 +3274,31 @@
// Support for Adafruit NeoPixel LED driver
//#define NEOPIXEL_LED
#if ENABLED(NEOPIXEL_LED)
- #define NEOPIXEL_TYPE NEO_GRBW // NEO_GRBW / NEO_GRB - four/three channel driver type (defined in Adafruit_NeoPixel.h)
- #define NEOPIXEL_PIN 4 // LED driving pin
- //#define NEOPIXEL2_TYPE NEOPIXEL_TYPE
- //#define NEOPIXEL2_PIN 5
- #define NEOPIXEL_PIXELS 30 // Number of LEDs in the strip. (Longest strip when NEOPIXEL2_SEPARATE is disabled.)
- #define NEOPIXEL_IS_SEQUENTIAL // Sequential display for temperature change - LED by LED. Disable to change all LEDs at once.
- #define NEOPIXEL_BRIGHTNESS 127 // Initial brightness (0-255)
- //#define NEOPIXEL_STARTUP_TEST // Cycle through colors at startup
+ #define NEOPIXEL_TYPE NEO_GRBW // NEO_GRBW, NEO_RGBW, NEO_GRB, NEO_RBG, etc.
+ // See https://github.com/adafruit/Adafruit_NeoPixel/blob/master/Adafruit_NeoPixel.h
+ //#define NEOPIXEL_PIN 4 // LED driving pin
+ //#define NEOPIXEL2_TYPE NEOPIXEL_TYPE
+ //#define NEOPIXEL2_PIN 5
+ #define NEOPIXEL_PIXELS 30 // Number of LEDs in the strip. (Longest strip when NEOPIXEL2_SEPARATE is disabled.)
+ #define NEOPIXEL_IS_SEQUENTIAL // Sequential display for temperature change - LED by LED. Disable to change all LEDs at once.
+ #define NEOPIXEL_BRIGHTNESS 127 // Initial brightness (0-255)
+ //#define NEOPIXEL_STARTUP_TEST // Cycle through colors at startup
// Support for second Adafruit NeoPixel LED driver controlled with M150 S1 ...
//#define NEOPIXEL2_SEPARATE
#if ENABLED(NEOPIXEL2_SEPARATE)
- #define NEOPIXEL2_PIXELS 15 // Number of LEDs in the second strip
- #define NEOPIXEL2_BRIGHTNESS 127 // Initial brightness (0-255)
- #define NEOPIXEL2_STARTUP_TEST // Cycle through colors at startup
+ #define NEOPIXEL2_PIXELS 15 // Number of LEDs in the second strip
+ #define NEOPIXEL2_BRIGHTNESS 127 // Initial brightness (0-255)
+ #define NEOPIXEL2_STARTUP_TEST // Cycle through colors at startup
#else
- //#define NEOPIXEL2_INSERIES // Default behavior is NeoPixel 2 in parallel
+ //#define NEOPIXEL2_INSERIES // Default behavior is NeoPixel 2 in parallel
#endif
- // Use a single NeoPixel LED for static (background) lighting
- //#define NEOPIXEL_BKGD_LED_INDEX 0 // Index of the LED to use
- //#define NEOPIXEL_BKGD_COLOR { 255, 255, 255, 0 } // R, G, B, W
+ // Use some of the NeoPixel LEDs for static (background) lighting
+ //#define NEOPIXEL_BKGD_INDEX_FIRST 0 // Index of the first background LED
+ //#define NEOPIXEL_BKGD_INDEX_LAST 5 // Index of the last background LED
+ //#define NEOPIXEL_BKGD_COLOR { 255, 255, 255, 0 } // R, G, B, W
+ //#define NEOPIXEL_BKGD_ALWAYS_ON // Keep the backlight on when other NeoPixels are off
#endif
/**
@@ -2464,6 +3316,8 @@
#define PRINTER_EVENT_LEDS
#endif
+// @section servos
+
/**
* Number of servos
*
@@ -2471,9 +3325,9 @@
* Set this manually if there are extra servos needing manual control.
* Set to 0 to turn off servo support.
*/
-//#define NUM_SERVOS 3 // Servo index starts with 0 for M280 command
+//#define NUM_SERVOS 3 // Note: Servo index starts with 0 for M280-M282 commands
-// (ms) Delay before the next move will start, to give the servo time to reach its target angle.
+// (ms) Delay before the next move will start, to give the servo time to reach its target angle.
// 300ms is a good value but you can try less delay.
// If the servo can't reach the requested position, increase it.
#define SERVO_DELAY { 300 }
@@ -2483,3 +3337,6 @@
// Edit servo angles with M281 and save to EEPROM with M500
//#define EDITABLE_SERVO_ANGLES
+
+// Disable servo with M282 to reduce power consumption, noise, and heat when not in use
+//#define SERVO_DETACH_GCODE
diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h
index 1a42e6f994ce..70a7154339fd 100644
--- a/Marlin/Configuration_adv.h
+++ b/Marlin/Configuration_adv.h
@@ -30,7 +30,25 @@
*
* Basic settings can be found in Configuration.h
*/
-#define CONFIGURATION_ADV_H_VERSION 020008
+#define CONFIGURATION_ADV_H_VERSION 02010200
+
+// @section develop
+
+/**
+ * Configuration Export
+ *
+ * Export the configuration as part of the build. (See signature.py)
+ * Output files are saved with the build (e.g., .pio/build/mega2560).
+ *
+ * See `build_all_examples --ini` as an example of config.ini archiving.
+ *
+ * 1 = marlin_config.json - Dictionary containing the configuration.
+ * This file is also generated for CONFIGURATION_EMBEDDING.
+ * 2 = config.ini - File format for PlatformIO preprocessing.
+ * 3 = schema.json - The entire configuration schema. (13 = pattern groups)
+ * 4 = schema.yml - The entire configuration schema.
+ */
+//#define CONFIG_EXPORT 2 // :[1:'JSON', 2:'config.ini', 3:'schema.json', 4:'schema.yml']
//===========================================================================
//============================= Thermal Settings ============================
@@ -54,69 +72,124 @@
// Custom Thermistor 1000 parameters
//
#if TEMP_SENSOR_0 == 1000
- #define HOTEND0_PULLUP_RESISTOR_OHMS 4700 // Pullup resistor
- #define HOTEND0_RESISTANCE_25C_OHMS 100000 // Resistance at 25C
- #define HOTEND0_BETA 3950 // Beta value
+ #define HOTEND0_PULLUP_RESISTOR_OHMS 4700 // Pullup resistor
+ #define HOTEND0_RESISTANCE_25C_OHMS 100000 // Resistance at 25C
+ #define HOTEND0_BETA 3950 // Beta value
+ #define HOTEND0_SH_C_COEFF 0 // Steinhart-Hart C coefficient
#endif
#if TEMP_SENSOR_1 == 1000
- #define HOTEND1_PULLUP_RESISTOR_OHMS 4700 // Pullup resistor
- #define HOTEND1_RESISTANCE_25C_OHMS 100000 // Resistance at 25C
- #define HOTEND1_BETA 3950 // Beta value
+ #define HOTEND1_PULLUP_RESISTOR_OHMS 4700 // Pullup resistor
+ #define HOTEND1_RESISTANCE_25C_OHMS 100000 // Resistance at 25C
+ #define HOTEND1_BETA 3950 // Beta value
+ #define HOTEND1_SH_C_COEFF 0 // Steinhart-Hart C coefficient
#endif
#if TEMP_SENSOR_2 == 1000
- #define HOTEND2_PULLUP_RESISTOR_OHMS 4700 // Pullup resistor
- #define HOTEND2_RESISTANCE_25C_OHMS 100000 // Resistance at 25C
- #define HOTEND2_BETA 3950 // Beta value
+ #define HOTEND2_PULLUP_RESISTOR_OHMS 4700 // Pullup resistor
+ #define HOTEND2_RESISTANCE_25C_OHMS 100000 // Resistance at 25C
+ #define HOTEND2_BETA 3950 // Beta value
+ #define HOTEND2_SH_C_COEFF 0 // Steinhart-Hart C coefficient
#endif
#if TEMP_SENSOR_3 == 1000
- #define HOTEND3_PULLUP_RESISTOR_OHMS 4700 // Pullup resistor
- #define HOTEND3_RESISTANCE_25C_OHMS 100000 // Resistance at 25C
- #define HOTEND3_BETA 3950 // Beta value
+ #define HOTEND3_PULLUP_RESISTOR_OHMS 4700 // Pullup resistor
+ #define HOTEND3_RESISTANCE_25C_OHMS 100000 // Resistance at 25C
+ #define HOTEND3_BETA 3950 // Beta value
+ #define HOTEND3_SH_C_COEFF 0 // Steinhart-Hart C coefficient
#endif
#if TEMP_SENSOR_4 == 1000
- #define HOTEND4_PULLUP_RESISTOR_OHMS 4700 // Pullup resistor
- #define HOTEND4_RESISTANCE_25C_OHMS 100000 // Resistance at 25C
- #define HOTEND4_BETA 3950 // Beta value
+ #define HOTEND4_PULLUP_RESISTOR_OHMS 4700 // Pullup resistor
+ #define HOTEND4_RESISTANCE_25C_OHMS 100000 // Resistance at 25C
+ #define HOTEND4_BETA 3950 // Beta value
+ #define HOTEND4_SH_C_COEFF 0 // Steinhart-Hart C coefficient
#endif
#if TEMP_SENSOR_5 == 1000
- #define HOTEND5_PULLUP_RESISTOR_OHMS 4700 // Pullup resistor
- #define HOTEND5_RESISTANCE_25C_OHMS 100000 // Resistance at 25C
- #define HOTEND5_BETA 3950 // Beta value
+ #define HOTEND5_PULLUP_RESISTOR_OHMS 4700 // Pullup resistor
+ #define HOTEND5_RESISTANCE_25C_OHMS 100000 // Resistance at 25C
+ #define HOTEND5_BETA 3950 // Beta value
+ #define HOTEND5_SH_C_COEFF 0 // Steinhart-Hart C coefficient
#endif
#if TEMP_SENSOR_6 == 1000
- #define HOTEND6_PULLUP_RESISTOR_OHMS 4700 // Pullup resistor
- #define HOTEND6_RESISTANCE_25C_OHMS 100000 // Resistance at 25C
- #define HOTEND6_BETA 3950 // Beta value
+ #define HOTEND6_PULLUP_RESISTOR_OHMS 4700 // Pullup resistor
+ #define HOTEND6_RESISTANCE_25C_OHMS 100000 // Resistance at 25C
+ #define HOTEND6_BETA 3950 // Beta value
+ #define HOTEND6_SH_C_COEFF 0 // Steinhart-Hart C coefficient
#endif
#if TEMP_SENSOR_7 == 1000
- #define HOTEND7_PULLUP_RESISTOR_OHMS 4700 // Pullup resistor
- #define HOTEND7_RESISTANCE_25C_OHMS 100000 // Resistance at 25C
- #define HOTEND7_BETA 3950 // Beta value
+ #define HOTEND7_PULLUP_RESISTOR_OHMS 4700 // Pullup resistor
+ #define HOTEND7_RESISTANCE_25C_OHMS 100000 // Resistance at 25C
+ #define HOTEND7_BETA 3950 // Beta value
+ #define HOTEND7_SH_C_COEFF 0 // Steinhart-Hart C coefficient
#endif
#if TEMP_SENSOR_BED == 1000
- #define BED_PULLUP_RESISTOR_OHMS 4700 // Pullup resistor
- #define BED_RESISTANCE_25C_OHMS 100000 // Resistance at 25C
- #define BED_BETA 3950 // Beta value
+ #define BED_PULLUP_RESISTOR_OHMS 4700 // Pullup resistor
+ #define BED_RESISTANCE_25C_OHMS 100000 // Resistance at 25C
+ #define BED_BETA 3950 // Beta value
+ #define BED_SH_C_COEFF 0 // Steinhart-Hart C coefficient
#endif
#if TEMP_SENSOR_CHAMBER == 1000
- #define CHAMBER_PULLUP_RESISTOR_OHMS 4700 // Pullup resistor
- #define CHAMBER_RESISTANCE_25C_OHMS 100000 // Resistance at 25C
- #define CHAMBER_BETA 3950 // Beta value
+ #define CHAMBER_PULLUP_RESISTOR_OHMS 4700 // Pullup resistor
+ #define CHAMBER_RESISTANCE_25C_OHMS 100000 // Resistance at 25C
+ #define CHAMBER_BETA 3950 // Beta value
+ #define CHAMBER_SH_C_COEFF 0 // Steinhart-Hart C coefficient
#endif
-//
-// Hephestos 2 24V heated bed upgrade kit.
-// https://store.bq.com/en/heated-bed-kit-hephestos2
-//
+#if TEMP_SENSOR_COOLER == 1000
+ #define COOLER_PULLUP_RESISTOR_OHMS 4700 // Pullup resistor
+ #define COOLER_RESISTANCE_25C_OHMS 100000 // Resistance at 25C
+ #define COOLER_BETA 3950 // Beta value
+ #define COOLER_SH_C_COEFF 0 // Steinhart-Hart C coefficient
+#endif
+
+#if TEMP_SENSOR_PROBE == 1000
+ #define PROBE_PULLUP_RESISTOR_OHMS 4700 // Pullup resistor
+ #define PROBE_RESISTANCE_25C_OHMS 100000 // Resistance at 25C
+ #define PROBE_BETA 3950 // Beta value
+ #define PROBE_SH_C_COEFF 0 // Steinhart-Hart C coefficient
+#endif
+
+#if TEMP_SENSOR_BOARD == 1000
+ #define BOARD_PULLUP_RESISTOR_OHMS 4700 // Pullup resistor
+ #define BOARD_RESISTANCE_25C_OHMS 100000 // Resistance at 25C
+ #define BOARD_BETA 3950 // Beta value
+ #define BOARD_SH_C_COEFF 0 // Steinhart-Hart C coefficient
+#endif
+
+#if TEMP_SENSOR_REDUNDANT == 1000
+ #define REDUNDANT_PULLUP_RESISTOR_OHMS 4700 // Pullup resistor
+ #define REDUNDANT_RESISTANCE_25C_OHMS 100000 // Resistance at 25C
+ #define REDUNDANT_BETA 3950 // Beta value
+ #define REDUNDANT_SH_C_COEFF 0 // Steinhart-Hart C coefficient
+#endif
+
+/**
+ * Thermocouple Options — for MAX6675 (-2), MAX31855 (-3), and MAX31865 (-5).
+ */
+//#define TEMP_SENSOR_FORCE_HW_SPI // Ignore SCK/MOSI/MISO pins; use CS and the default SPI bus.
+//#define MAX31865_SENSOR_WIRES_0 2 // (2-4) Number of wires for the probe connected to a MAX31865 board.
+//#define MAX31865_SENSOR_WIRES_1 2
+
+//#define MAX31865_50HZ_FILTER // Use a 50Hz filter instead of the default 60Hz.
+//#define MAX31865_USE_READ_ERROR_DETECTION // Treat value spikes (20°C delta in under 1s) as read errors.
+
+//#define MAX31865_USE_AUTO_MODE // Read faster and more often than 1-shot; bias voltage always on; slight effect on RTD temperature.
+//#define MAX31865_MIN_SAMPLING_TIME_MSEC 100 // (ms) 1-shot: minimum read interval. Reduces bias voltage effects by leaving sensor unpowered for longer intervals.
+//#define MAX31865_IGNORE_INITIAL_FAULTY_READS 10 // Ignore some read faults (keeping the temperature reading) to work around a possible issue (#23439).
+
+//#define MAX31865_WIRE_OHMS_0 0.95f // For 2-wire, set the wire resistances for more accurate readings.
+//#define MAX31865_WIRE_OHMS_1 0.0f
+
+/**
+ * Hephestos 2 24V heated bed upgrade kit.
+ * https://store.bq.com/en/heated-bed-kit-hephestos2
+ */
//#define HEPHESTOS2_HEATED_BED_KIT
#if ENABLED(HEPHESTOS2_HEATED_BED_KIT)
#undef TEMP_SENSOR_BED
@@ -137,17 +210,22 @@
//
// Heated Chamber options
//
+#if DISABLED(PIDTEMPCHAMBER)
+ #define CHAMBER_CHECK_INTERVAL 5000 // (ms) Interval between checks in bang-bang control
+ #if ENABLED(CHAMBER_LIMIT_SWITCHING)
+ #define CHAMBER_HYSTERESIS 2 // (°C) Only set the relevant heater state when ABS(T-target) > CHAMBER_HYSTERESIS
+ #endif
+#endif
+
#if TEMP_SENSOR_CHAMBER
- #define CHAMBER_MINTEMP 5
- #define CHAMBER_MAXTEMP 60
- #define TEMP_CHAMBER_HYSTERESIS 1 // (°C) Temperature proximity considered "close enough" to the target
- //#define CHAMBER_LIMIT_SWITCHING
- //#define HEATER_CHAMBER_PIN 44 // Chamber heater on/off pin
+ //#define HEATER_CHAMBER_PIN P2_04 // Required heater on/off pin (example: SKR 1.4 Turbo HE1 plug)
//#define HEATER_CHAMBER_INVERTING false
+ //#define FAN1_PIN -1 // Remove the fan signal on pin P2_04 (example: SKR 1.4 Turbo HE1 plug)
//#define CHAMBER_FAN // Enable a fan on the chamber
#if ENABLED(CHAMBER_FAN)
- #define CHAMBER_FAN_MODE 2 // Fan control mode: 0=Static; 1=Linear increase when temp is higher than target; 2=V-shaped curve.
+ //#define CHAMBER_FAN_INDEX 2 // Index of a fan to repurpose as the chamber fan. (Default: first unused fan)
+ #define CHAMBER_FAN_MODE 2 // Fan control mode: 0=Static; 1=Linear increase when temp is higher than target; 2=V-shaped curve; 3=similar to 1 but fan is always on.
#if CHAMBER_FAN_MODE == 0
#define CHAMBER_FAN_BASE 255 // Chamber fan PWM (0-255)
#elif CHAMBER_FAN_MODE == 1
@@ -156,6 +234,9 @@
#elif CHAMBER_FAN_MODE == 2
#define CHAMBER_FAN_BASE 128 // Minimum chamber fan PWM (0-255)
#define CHAMBER_FAN_FACTOR 25 // PWM increase per °C difference from target
+ #elif CHAMBER_FAN_MODE == 3
+ #define CHAMBER_FAN_BASE 128 // Base chamber fan PWM (0-255)
+ #define CHAMBER_FAN_FACTOR 25 // PWM increase per °C above target
#endif
#endif
@@ -163,12 +244,43 @@
#if ENABLED(CHAMBER_VENT)
#define CHAMBER_VENT_SERVO_NR 1 // Index of the vent servo
#define HIGH_EXCESS_HEAT_LIMIT 5 // How much above target temp to consider there is excess heat in the chamber
- #define LOW_EXCESS_HEAT_LIMIT 3
+ #define LOW_EXCESS_HEAT_LIMIT 3
#define MIN_COOLING_SLOPE_TIME_CHAMBER_VENT 20
#define MIN_COOLING_SLOPE_DEG_CHAMBER_VENT 1.5
#endif
#endif
+//
+// Laser Cooler options
+//
+#if TEMP_SENSOR_COOLER
+ #define COOLER_MINTEMP 8 // (°C)
+ #define COOLER_MAXTEMP 26 // (°C)
+ #define COOLER_DEFAULT_TEMP 16 // (°C)
+ #define TEMP_COOLER_HYSTERESIS 1 // (°C) Temperature proximity considered "close enough" to the target
+ #define COOLER_PIN 8 // Laser cooler on/off pin used to control power to the cooling element (e.g., TEC, External chiller via relay)
+ #define COOLER_INVERTING false
+ #define TEMP_COOLER_PIN 15 // Laser/Cooler temperature sensor pin. ADC is required.
+ #define COOLER_FAN // Enable a fan on the cooler, Fan# 0,1,2,3 etc.
+ #define COOLER_FAN_INDEX 0 // FAN number 0, 1, 2 etc. e.g.
+ #if ENABLED(COOLER_FAN)
+ #define COOLER_FAN_BASE 100 // Base Cooler fan PWM (0-255); turns on when Cooler temperature is above the target
+ #define COOLER_FAN_FACTOR 25 // PWM increase per °C above target
+ #endif
+#endif
+
+//
+// Motherboard Sensor options
+//
+#if TEMP_SENSOR_BOARD
+ #define THERMAL_PROTECTION_BOARD // Halt the printer if the board sensor leaves the temp range below.
+ #define BOARD_MINTEMP 8 // (°C)
+ #define BOARD_MAXTEMP 70 // (°C)
+ #ifndef TEMP_BOARD_PIN
+ //#define TEMP_BOARD_PIN -1 // Board temp sensor pin, if not set in pins file.
+ #endif
+#endif
+
/**
* Thermal Protection provides additional protection to your printer from damage
* and fire. Marlin always includes safe min and max temperature ranges which
@@ -206,7 +318,7 @@
* and/or decrease WATCH_TEMP_INCREASE. WATCH_TEMP_INCREASE should not be set
* below 2.
*/
- #define WATCH_TEMP_PERIOD 20 // Seconds
+ #define WATCH_TEMP_PERIOD 40 // Seconds
#define WATCH_TEMP_INCREASE 2 // Degrees Celsius
#endif
@@ -238,6 +350,28 @@
#define WATCH_CHAMBER_TEMP_INCREASE 2 // Degrees Celsius
#endif
+/**
+ * Thermal Protection parameters for the laser cooler.
+ */
+#if ENABLED(THERMAL_PROTECTION_COOLER)
+ #define THERMAL_PROTECTION_COOLER_PERIOD 10 // Seconds
+ #define THERMAL_PROTECTION_COOLER_HYSTERESIS 3 // Degrees Celsius
+
+ /**
+ * Laser cooling watch settings (M143/M193).
+ */
+ #define WATCH_COOLER_TEMP_PERIOD 60 // Seconds
+ #define WATCH_COOLER_TEMP_INCREASE 3 // Degrees Celsius
+#endif
+
+#if ANY(THERMAL_PROTECTION_HOTENDS, THERMAL_PROTECTION_BED, THERMAL_PROTECTION_CHAMBER, THERMAL_PROTECTION_COOLER)
+ /**
+ * Thermal Protection Variance Monitor - EXPERIMENTAL.
+ * Kill the machine on a stuck temperature sensor. Disable if you get false positives.
+ */
+ //#define THERMAL_PROTECTION_VARIANCE_MONITOR // Detect a sensor malfunction preventing temperature updates
+#endif
+
#if ENABLED(PIDTEMP)
// Add an experimental additional term to the heater power, proportional to the extrusion speed.
// A well-chosen Kc value should add just enough power to melt the increased material volume.
@@ -284,8 +418,8 @@
// DEFAULT_Kf and PID_FAN_SCALING_LIN_FACTOR are calculated accordingly.
#define PID_FAN_SCALING_AT_FULL_SPEED 13.0 //=PID_FAN_SCALING_LIN_FACTOR*255+DEFAULT_Kf
- #define PID_FAN_SCALING_AT_MIN_SPEED 6.0 //=PID_FAN_SCALING_LIN_FACTOR*PID_FAN_SCALING_MIN_SPEED+DEFAULT_Kf
- #define PID_FAN_SCALING_MIN_SPEED 10.0 // Minimum fan speed at which to enable PID_FAN_SCALING
+ #define PID_FAN_SCALING_AT_MIN_SPEED 6.0 //=PID_FAN_SCALING_LIN_FACTOR*PID_FAN_SCALING_MIN_SPEED+DEFAULT_Kf
+ #define PID_FAN_SCALING_MIN_SPEED 10.0 // Minimum fan speed at which to enable PID_FAN_SCALING
#define DEFAULT_Kf (255.0*PID_FAN_SCALING_AT_MIN_SPEED-PID_FAN_SCALING_AT_FULL_SPEED*PID_FAN_SCALING_MIN_SPEED)/(255.0-PID_FAN_SCALING_MIN_SPEED)
#define PID_FAN_SCALING_LIN_FACTOR (PID_FAN_SCALING_AT_FULL_SPEED-DEFAULT_Kf)/255.0
@@ -313,7 +447,7 @@
*/
#define AUTOTEMP
#if ENABLED(AUTOTEMP)
- #define AUTOTEMP_OLDWEIGHT 0.98
+ #define AUTOTEMP_OLDWEIGHT 0.98 // Factor used to weight previous readings (0.0 < value < 1.0)
// Turn on AUTOTEMP on M104/M109 by default using proportions set here
//#define AUTOTEMP_PROPORTIONAL
#if ENABLED(AUTOTEMP_PROPORTIONAL)
@@ -331,7 +465,7 @@
* High Temperature Thermistor Support
*
* Thermistors able to support high temperature tend to have a hard time getting
- * good readings at room and lower temperatures. This means HEATER_X_RAW_LO_TEMP
+ * good readings at room and lower temperatures. This means TEMP_SENSOR_X_RAW_LO_TEMP
* will probably be caught when the heating element first turns on during the
* preheating process, which will trigger a min_temp_error as a safety measure
* and force stop everything.
@@ -347,18 +481,22 @@
// before a min_temp_error is triggered. (Shouldn't be more than 10.)
//#define MAX_CONSECUTIVE_LOW_TEMPERATURE_ERROR_ALLOWED 0
-// The number of milliseconds a hotend will preheat before starting to check
-// the temperature. This value should NOT be set to the time it takes the
-// hot end to reach the target temperature, but the time it takes to reach
-// the minimum temperature your thermistor can read. The lower the better/safer.
-// This shouldn't need to be more than 30 seconds (30000)
+/**
+ * The number of milliseconds a hotend will preheat before starting to check
+ * the temperature. This value should NOT be set to the time it takes the
+ * hot end to reach the target temperature, but the time it takes to reach
+ * the minimum temperature your thermistor can read. The lower the better/safer.
+ * This shouldn't need to be more than 30 seconds (30000)
+ */
//#define MILLISECONDS_PREHEAT_TIME 0
// @section extruder
-// Extruder runout prevention.
-// If the machine is idle and the temperature over MINTEMP
-// then extrude some filament every couple of SECONDS.
+/**
+ * Extruder runout prevention.
+ * If the machine is idle and the temperature over MINTEMP
+ * then extrude some filament every couple of SECONDS.
+ */
//#define EXTRUDER_RUNOUT_PREVENT
#if ENABLED(EXTRUDER_RUNOUT_PREVENT)
#define EXTRUDER_RUNOUT_MINTEMP 190
@@ -397,16 +535,20 @@
*/
#define USE_CONTROLLER_FAN
#if ENABLED(USE_CONTROLLER_FAN)
- // #define CONTROLLER_FAN_PIN ORIG_CONTROLLER_FAN_PIN // Set a custom pin for the controller fan
- //#define CONTROLLER_FAN_USE_Z_ONLY // With this option only the Z axis is considered
- //#define CONTROLLER_FAN_IGNORE_Z // Ignore Z stepper. Useful when stepper timeout is disabled.
- #define CONTROLLERFAN_SPEED_MIN 0 // (0-255) Minimum speed. (If set below this value the fan is turned off.)
- #define CONTROLLERFAN_SPEED_ACTIVE 255 // (0-255) Active speed, used when any motor is enabled
- #define CONTROLLERFAN_SPEED_IDLE 0 // (0-255) Idle speed, used when motors are disabled
- #define CONTROLLERFAN_IDLE_TIME 60 // (seconds) Extra time to keep the fan running after disabling motors
- #define CONTROLLER_FAN_EDITABLE // Enable M710 configurable settings
+ //#define CONTROLLER_FAN_PIN -1 // Set a custom pin for the controller fan
+ //#define CONTROLLER_FAN_USE_Z_ONLY // With this option only the Z axis is considered
+ //#define CONTROLLER_FAN_IGNORE_Z // Ignore Z stepper. Useful when stepper timeout is disabled.
+ #define CONTROLLERFAN_SPEED_MIN 0 // (0-255) Minimum speed. (If set below this value the fan is turned off.)
+ #define CONTROLLERFAN_SPEED_ACTIVE 255 // (0-255) Active speed, used when any motor is enabled
+ #define CONTROLLERFAN_SPEED_IDLE 0 // (0-255) Idle speed, used when motors are disabled
+ #define CONTROLLERFAN_IDLE_TIME 60 // (seconds) Extra time to keep the fan running after disabling motors
+
+ // Use TEMP_SENSOR_BOARD as a trigger for enabling the controller fan
+ //#define CONTROLLER_FAN_MIN_BOARD_TEMP 40 // (°C) Turn on the fan if the board reaches this temperature
+
+ #define CONTROLLER_FAN_EDITABLE // Enable M710 configurable settings
#if ENABLED(CONTROLLER_FAN_EDITABLE)
- #define CONTROLLER_FAN_MENU // Enable the Controller Fan submenu
+ #define CONTROLLER_FAN_MENU // Enable the Controller Fan submenu
#endif
#endif
@@ -434,32 +576,48 @@
//#define FAN_MAX_PWM 128
/**
- * FAST PWM FAN Settings
+ * Fan Fast PWM
*
- * Use to change the FAST FAN PWM frequency (if enabled in Configuration.h)
- * Combinations of PWM Modes, prescale values and TOP resolutions are used internally to produce a
- * frequency as close as possible to the desired frequency.
+ * Combinations of PWM Modes, prescale values and TOP resolutions are used internally
+ * to produce a frequency as close as possible to the desired frequency.
*
- * FAST_PWM_FAN_FREQUENCY [undefined by default]
+ * FAST_PWM_FAN_FREQUENCY
* Set this to your desired frequency.
- * If left undefined this defaults to F = F_CPU/(2*255*1)
- * i.e., F = 31.4kHz on 16MHz microcontrollers or F = 39.2kHz on 20MHz microcontrollers.
- * These defaults are the same as with the old FAST_PWM_FAN implementation - no migration is required
+ * For AVR, if left undefined this defaults to F = F_CPU/(2*255*1)
+ * i.e., F = 31.4kHz on 16MHz microcontrollers or F = 39.2kHz on 20MHz microcontrollers.
+ * For non AVR, if left undefined this defaults to F = 1Khz.
+ * This F value is only to protect the hardware from an absence of configuration
+ * and not to complete it when users are not aware that the frequency must be specifically set to support the target board.
+ *
* NOTE: Setting very low frequencies (< 10 Hz) may result in unexpected timer behavior.
+ * Setting very high frequencies can damage your hardware.
*
* USE_OCR2A_AS_TOP [undefined by default]
* Boards that use TIMER2 for PWM have limitations resulting in only a few possible frequencies on TIMER2:
- * 16MHz MCUs: [62.5KHz, 31.4KHz (default), 7.8KHz, 3.92KHz, 1.95KHz, 977Hz, 488Hz, 244Hz, 60Hz, 122Hz, 30Hz]
- * 20MHz MCUs: [78.1KHz, 39.2KHz (default), 9.77KHz, 4.9KHz, 2.44KHz, 1.22KHz, 610Hz, 305Hz, 153Hz, 76Hz, 38Hz]
+ * 16MHz MCUs: [62.5kHz, 31.4kHz (default), 7.8kHz, 3.92kHz, 1.95kHz, 977Hz, 488Hz, 244Hz, 60Hz, 122Hz, 30Hz]
+ * 20MHz MCUs: [78.1kHz, 39.2kHz (default), 9.77kHz, 4.9kHz, 2.44kHz, 1.22kHz, 610Hz, 305Hz, 153Hz, 76Hz, 38Hz]
* A greater range can be achieved by enabling USE_OCR2A_AS_TOP. But note that this option blocks the use of
* PWM on pin OC2A. Only use this option if you don't need PWM on 0C2A. (Check your schematic.)
* USE_OCR2A_AS_TOP sacrifices duty cycle control resolution to achieve this broader range of frequencies.
*/
+//#define FAST_PWM_FAN // Increase the fan PWM frequency. Removes the PWM noise but increases heating in the FET/Arduino
#if ENABLED(FAST_PWM_FAN)
- //#define FAST_PWM_FAN_FREQUENCY 31400
+ //#define FAST_PWM_FAN_FREQUENCY 31400 // Define here to override the defaults below
//#define USE_OCR2A_AS_TOP
+ #ifndef FAST_PWM_FAN_FREQUENCY
+ #ifdef __AVR__
+ #define FAST_PWM_FAN_FREQUENCY ((F_CPU) / (2 * 255 * 1))
+ #else
+ #define FAST_PWM_FAN_FREQUENCY 1000U
+ #endif
+ #endif
#endif
+/**
+ * Use one of the PWM fans as a redundant part-cooling fan
+ */
+//#define REDUNDANT_PART_COOLING_FAN 2 // Index of the fan to sync with FAN 0.
+
// @section extruder
/**
@@ -483,11 +641,48 @@
#define E6_AUTO_FAN_PIN -1
#define E7_AUTO_FAN_PIN -1
#define CHAMBER_AUTO_FAN_PIN -1
+#define COOLER_AUTO_FAN_PIN -1
#define EXTRUDER_AUTO_FAN_TEMPERATURE 50
#define EXTRUDER_AUTO_FAN_SPEED 255 // 255 == full speed
#define CHAMBER_AUTO_FAN_TEMPERATURE 30
#define CHAMBER_AUTO_FAN_SPEED 255
+#define COOLER_AUTO_FAN_TEMPERATURE 18
+#define COOLER_AUTO_FAN_SPEED 255
+
+/**
+ * Hotend Cooling Fans tachometers
+ *
+ * Define one or more tachometer pins to enable fan speed
+ * monitoring, and reporting of fan speeds with M123.
+ *
+ * NOTE: Only works with fans up to 7000 RPM.
+ */
+//#define FOURWIRES_FANS // Needed with AUTO_FAN when 4-wire PWM fans are installed
+//#define E0_FAN_TACHO_PIN -1
+//#define E0_FAN_TACHO_PULLUP
+//#define E0_FAN_TACHO_PULLDOWN
+//#define E1_FAN_TACHO_PIN -1
+//#define E1_FAN_TACHO_PULLUP
+//#define E1_FAN_TACHO_PULLDOWN
+//#define E2_FAN_TACHO_PIN -1
+//#define E2_FAN_TACHO_PULLUP
+//#define E2_FAN_TACHO_PULLDOWN
+//#define E3_FAN_TACHO_PIN -1
+//#define E3_FAN_TACHO_PULLUP
+//#define E3_FAN_TACHO_PULLDOWN
+//#define E4_FAN_TACHO_PIN -1
+//#define E4_FAN_TACHO_PULLUP
+//#define E4_FAN_TACHO_PULLDOWN
+//#define E5_FAN_TACHO_PIN -1
+//#define E5_FAN_TACHO_PULLUP
+//#define E5_FAN_TACHO_PULLDOWN
+//#define E6_FAN_TACHO_PIN -1
+//#define E6_FAN_TACHO_PULLUP
+//#define E6_FAN_TACHO_PULLDOWN
+//#define E7_FAN_TACHO_PIN -1
+//#define E7_FAN_TACHO_PULLUP
+//#define E7_FAN_TACHO_PULLDOWN
/**
* Part-Cooling Fan Multiplexer
@@ -508,13 +703,18 @@
// #define CASE_LIGHT_PIN ORIG_CASE_LIGHT_PIN // Override the default pin if needed
#define INVERT_CASE_LIGHT false // Set true if Case Light is ON when pin is LOW
#define CASE_LIGHT_DEFAULT_ON true // Set default power-up state on
- #define CASE_LIGHT_DEFAULT_BRIGHTNESS 255 // Set default power-up brightness (0-255, requires PWM pin)
- //#define CASE_LIGHT_MAX_PWM 128 // Limit pwm
- #define CASE_LIGHT_MENU // Add Case Light options to the LCD menu
+ #define CASE_LIGHT_DEFAULT_BRIGHTNESS 105 // Set default power-up brightness (0-255, requires PWM pin)
//#define CASE_LIGHT_NO_BRIGHTNESS // Disable brightness control. Enable for non-PWM lighting.
- //#define CASE_LIGHT_USE_NEOPIXEL // Use NeoPixel LED as case light, requires NEOPIXEL_LED.
- #if ENABLED(CASE_LIGHT_USE_NEOPIXEL)
- #define CASE_LIGHT_NEOPIXEL_COLOR { 255, 255, 255, 255 } // { Red, Green, Blue, White }
+ //#define CASE_LIGHT_MAX_PWM 128 // Limit PWM duty cycle (0-255)
+ //#define CASE_LIGHT_MENU // Add Case Light options to the LCD menu
+ #if ENABLED(NEOPIXEL_LED)
+ //#define CASE_LIGHT_USE_NEOPIXEL // Use NeoPixel LED as case light
+ #endif
+ #if EITHER(RGB_LED, RGBW_LED)
+ //#define CASE_LIGHT_USE_RGB_LED // Use RGB / RGBW LED as case light
+ #endif
+ #if EITHER(CASE_LIGHT_USE_NEOPIXEL, CASE_LIGHT_USE_RGB_LED)
+ #define CASE_LIGHT_DEFAULT_COLOR { 255, 255, 255, 255 } // { Red, Green, Blue, White }
#endif
#endif
@@ -535,62 +735,6 @@
//#define CLOSED_LOOP_MOVE_COMPLETE_PIN -1
#endif
-/**
- * Dual Steppers / Dual Endstops
- *
- * This section will allow you to use extra E drivers to drive a second motor for X, Y, or Z axes.
- *
- * For example, set X_DUAL_STEPPER_DRIVERS setting to use a second motor. If the motors need to
- * spin in opposite directions set INVERT_X2_VS_X_DIR. If the second motor needs its own endstop
- * set X_DUAL_ENDSTOPS. This can adjust for "racking." Use X2_USE_ENDSTOP to set the endstop plug
- * that should be used for the second endstop. Extra endstops will appear in the output of 'M119'.
- *
- * Use X_DUAL_ENDSTOP_ADJUSTMENT to adjust for mechanical imperfection. After homing both motors
- * this offset is applied to the X2 motor. To find the offset home the X axis, and measure the error
- * in X2. Dual endstop offsets can be set at runtime with 'M666 X Y Z'.
- */
-
-//#define X_DUAL_STEPPER_DRIVERS
-#if ENABLED(X_DUAL_STEPPER_DRIVERS)
- #define INVERT_X2_VS_X_DIR true // Set 'true' if X motors should rotate in opposite directions
- //#define X_DUAL_ENDSTOPS
- #if ENABLED(X_DUAL_ENDSTOPS)
- #define X2_USE_ENDSTOP _XMAX_
- #define X2_ENDSTOP_ADJUSTMENT 0
- #endif
-#endif
-
-//#define Y_DUAL_STEPPER_DRIVERS
-#if ENABLED(Y_DUAL_STEPPER_DRIVERS)
- #define INVERT_Y2_VS_Y_DIR true // Set 'true' if Y motors should rotate in opposite directions
- //#define Y_DUAL_ENDSTOPS
- #if ENABLED(Y_DUAL_ENDSTOPS)
- #define Y2_USE_ENDSTOP _YMAX_
- #define Y2_ENDSTOP_ADJUSTMENT 0
- #endif
-#endif
-
-//
-// For Z set the number of stepper drivers
-//
-#define NUM_Z_STEPPER_DRIVERS 1 // (1-4) Z options change based on how many
-
-#if NUM_Z_STEPPER_DRIVERS > 1
- //#define Z_MULTI_ENDSTOPS
- #if ENABLED(Z_MULTI_ENDSTOPS)
- #define Z2_USE_ENDSTOP _XMAX_
- #define Z2_ENDSTOP_ADJUSTMENT 0
- #if NUM_Z_STEPPER_DRIVERS >= 3
- #define Z3_USE_ENDSTOP _YMAX_
- #define Z3_ENDSTOP_ADJUSTMENT 0
- #endif
- #if NUM_Z_STEPPER_DRIVERS >= 4
- #define Z4_USE_ENDSTOP _ZMAX_
- #define Z4_ENDSTOP_ADJUSTMENT 0
- #endif
- #endif
-#endif
-
/**
* Dual X Carriage
*
@@ -621,22 +765,95 @@
*/
//#define DUAL_X_CARRIAGE
#if ENABLED(DUAL_X_CARRIAGE)
- #define X1_MIN_POS X_MIN_POS // Set to X_MIN_POS
- #define X1_MAX_POS X_BED_SIZE // Set a maximum so the first X-carriage can't hit the parked second X-carriage
- #define X2_MIN_POS 80 // Set a minimum to ensure the second X-carriage can't hit the parked first X-carriage
- #define X2_MAX_POS 353 // Set this to the distance between toolheads when both heads are homed
- #define X2_HOME_DIR 1 // Set to 1. The second X-carriage always homes to the maximum endstop position
- #define X2_HOME_POS X2_MAX_POS // Default X2 home position. Set to X2_MAX_POS.
- // However: In this mode the HOTEND_OFFSET_X value for the second extruder provides a software
- // override for X2_HOME_POS. This also allow recalibration of the distance between the two endstops
- // without modifying the firmware (through the "M218 T1 X???" command).
- // Remember: you should set the second extruder x-offset to 0 in your slicer.
-
- // This is the default power-up mode which can be later using M605.
+ #define X1_MIN_POS X_MIN_POS // Set to X_MIN_POS
+ #define X1_MAX_POS X_BED_SIZE // A max coordinate so the X1 carriage can't hit the parked X2 carriage
+ #define X2_MIN_POS 80 // A min coordinate so the X2 carriage can't hit the parked X1 carriage
+ #define X2_MAX_POS 353 // The max position of the X2 carriage, typically also the home position
+ #define X2_HOME_DIR 1 // Set to 1. The X2 carriage always homes to the max endstop position
+ #define X2_HOME_POS X2_MAX_POS // Default X2 home position. Set to X2_MAX_POS.
+ // NOTE: For Dual X Carriage use M218 T1 Xn to override the X2_HOME_POS.
+ // This allows recalibration of endstops distance without a rebuild.
+ // Remember to set the second extruder's X-offset to 0 in your slicer.
+
+ // This is the default power-up mode which can be changed later using M605 S.
#define DEFAULT_DUAL_X_CARRIAGE_MODE DXC_AUTO_PARK_MODE
// Default x offset in duplication mode (typically set to half print bed width)
#define DEFAULT_DUPLICATION_X_OFFSET 100
+
+ // Default action to execute following M605 mode change commands. Typically G28X to apply new mode.
+ //#define EVENT_GCODE_IDEX_AFTER_MODECHANGE "G28X"
+#endif
+
+/**
+ * Multi-Stepper / Multi-Endstop
+ *
+ * When X2_DRIVER_TYPE is defined, this indicates that the X and X2 motors work in tandem.
+ * The following explanations for X also apply to Y and Z multi-stepper setups.
+ * Endstop offsets may be changed by 'M666 X Y Z' and stored to EEPROM.
+ *
+ * - Enable INVERT_X2_VS_X_DIR if the X2 motor requires an opposite DIR signal from X.
+ *
+ * - Enable X_DUAL_ENDSTOPS if the second motor has its own endstop, with adjustable offset.
+ *
+ * - Extra endstops are included in the output of 'M119'.
+ *
+ * - Set X_DUAL_ENDSTOP_ADJUSTMENT to the known error in the X2 endstop.
+ * Applied to the X2 motor on 'G28' / 'G28 X'.
+ * Get the offset by homing X and measuring the error.
+ * Also set with 'M666 X' and stored to EEPROM with 'M500'.
+ *
+ * - Use X2_USE_ENDSTOP to set the endstop plug by name. (_XMIN_, _XMAX_, _YMIN_, _YMAX_, _ZMIN_, _ZMAX_)
+ */
+#if HAS_X2_STEPPER && DISABLED(DUAL_X_CARRIAGE)
+ //#define INVERT_X2_VS_X_DIR // X2 direction signal is the opposite of X
+ //#define X_DUAL_ENDSTOPS // X2 has its own endstop
+ #if ENABLED(X_DUAL_ENDSTOPS)
+ #define X2_USE_ENDSTOP _XMAX_ // X2 endstop board plug. Don't forget to enable USE_*_PLUG.
+ #define X2_ENDSTOP_ADJUSTMENT 0 // X2 offset relative to X endstop
+ #endif
+#endif
+
+#if HAS_DUAL_Y_STEPPERS
+ //#define INVERT_Y2_VS_Y_DIR // Y2 direction signal is the opposite of Y
+ //#define Y_DUAL_ENDSTOPS // Y2 has its own endstop
+ #if ENABLED(Y_DUAL_ENDSTOPS)
+ #define Y2_USE_ENDSTOP _YMAX_ // Y2 endstop board plug. Don't forget to enable USE_*_PLUG.
+ #define Y2_ENDSTOP_ADJUSTMENT 0 // Y2 offset relative to Y endstop
+ #endif
+#endif
+
+//
+// Multi-Z steppers
+//
+#ifdef Z2_DRIVER_TYPE
+ //#define INVERT_Z2_VS_Z_DIR // Z2 direction signal is the opposite of Z
+
+ //#define Z_MULTI_ENDSTOPS // Other Z axes have their own endstops
+ #if ENABLED(Z_MULTI_ENDSTOPS)
+ #define Z2_USE_ENDSTOP _XMAX_ // Z2 endstop board plug. Don't forget to enable USE_*_PLUG.
+ #define Z2_ENDSTOP_ADJUSTMENT 0 // Z2 offset relative to Y endstop
+ #endif
+ #ifdef Z3_DRIVER_TYPE
+ //#define INVERT_Z3_VS_Z_DIR // Z3 direction signal is the opposite of Z
+ #if ENABLED(Z_MULTI_ENDSTOPS)
+ #define Z3_USE_ENDSTOP _YMAX_ // Z3 endstop board plug. Don't forget to enable USE_*_PLUG.
+ #define Z3_ENDSTOP_ADJUSTMENT 0 // Z3 offset relative to Y endstop
+ #endif
+ #endif
+ #ifdef Z4_DRIVER_TYPE
+ //#define INVERT_Z4_VS_Z_DIR // Z4 direction signal is the opposite of Z
+ #if ENABLED(Z_MULTI_ENDSTOPS)
+ #define Z4_USE_ENDSTOP _ZMAX_ // Z4 endstop board plug. Don't forget to enable USE_*_PLUG.
+ #define Z4_ENDSTOP_ADJUSTMENT 0 // Z4 offset relative to Y endstop
+ #endif
+ #endif
+#endif
+
+// Drive the E axis with two synchronized steppers
+//#define E_DUAL_STEPPER_DRIVERS
+#if ENABLED(E_DUAL_STEPPER_DRIVERS)
+ //#define INVERT_E1_VS_E0_DIR // E direction signals are opposites
#endif
// Activate a solenoid on the active extruder with M380. Disable all with M381.
@@ -651,15 +868,16 @@
* the position of the toolhead relative to the workspace.
*/
-#define SENSORLESS_BACKOFF_MM { 2, 2 } // (mm) Backoff from endstops before sensorless homing
+#define SENSORLESS_BACKOFF_MM { 2, 2, 0 } // (linear=mm, rotational=°) Backoff from endstops before sensorless homing
-#define HOMING_BUMP_MM { 0, 0, 2 } // (mm) Backoff from endstops after first bump
+#define HOMING_BUMP_MM { 5, 5, 2 } // (linear=mm, rotational=°) Backoff from endstops after first bump
#define HOMING_BUMP_DIVISOR { 2, 2, 4 } // Re-Bump Speed Divisor (Divides the Homing Feedrate)
-#define HOMING_BACKOFF_POST_MM { 10, 10, 0 } // (mm) Backoff from endstops after homing
+#define HOMING_BACKOFF_POST_MM { 10, 10, 0 } // (linear=mm, rotational=°) Backoff from endstops after homing
//#define QUICK_HOME // If G28 contains XY do a diagonal move first
//#define HOME_Y_BEFORE_X // If G28 contains XY home Y before X
+//#define HOME_Z_FIRST // Home Z first. Requires a Z-MIN endstop (not a probe).
//#define CODEPENDENT_XY_HOMING // If X/Y can't home without homing Y/X first
// @section bltouch
@@ -719,12 +937,14 @@
//#define BLTOUCH_FORCE_MODE_SET
/**
- * Use "HIGH SPEED" mode for probing.
+ * Enable "HIGH SPEED" option for probing.
* Danger: Disable if your probe sometimes fails. Only suitable for stable well-adjusted systems.
- * This feature was designed for Delta's with very fast Z moves however higher speed cartesians may function
- * If the machine cannot raise the probe fast enough after a trigger, it may enter a fault state.
+ * This feature was designed for Deltabots with very fast Z moves; however, higher speed Cartesians
+ * might be able to use it. If the machine can't raise Z fast enough the BLTouch may go into ALARM.
+ *
+ * Set the default state here, change with 'M401 S' or UI, use M500 to save, M502 to reset.
*/
- //#define BLTOUCH_HS_MODE
+ //#define BLTOUCH_HS_MODE true
// Safety: Enable voltage mode settings in the LCD menu.
//#define BLTOUCH_LCD_VOLTAGE_MENU
@@ -739,9 +959,12 @@
*/
//#define Z_STEPPER_AUTO_ALIGN
#if ENABLED(Z_STEPPER_AUTO_ALIGN)
- // Define probe X and Y positions for Z1, Z2 [, Z3 [, Z4]]
- // If not defined, probe limits will be used.
- // Override with 'M422 S X Y'
+ /**
+ * Define probe X and Y positions for Z1, Z2 [, Z3 [, Z4]]
+ * These positions are machine-relative and do not shift with the M206 home offset!
+ * If not defined, probe limits will be used.
+ * Override with 'M422 S X Y'.
+ */
//#define Z_STEPPER_ALIGN_XY { { 10, 190 }, { 100, 10 }, { 190, 190 } }
/**
@@ -767,15 +990,17 @@
//#define Z_STEPPERS_ORIENTATION 0
#endif
- // Provide Z stepper positions for more rapid convergence in bed alignment.
- // Requires triple stepper drivers (i.e., set NUM_Z_STEPPER_DRIVERS to 3)
- //#define Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS
- #if ENABLED(Z_STEPPER_ALIGN_KNOWN_STEPPER_POSITIONS)
- // Define Stepper XY positions for Z1, Z2, Z3 corresponding to
- // the Z screw positions in the bed carriage.
- // Define one position per Z stepper in stepper driver order.
- #define Z_STEPPER_ALIGN_STEPPER_XY { { 210.7, 102.5 }, { 152.6, 220.0 }, { 94.5, 102.5 } }
- #else
+ /**
+ * Z Stepper positions for more rapid convergence in bed alignment.
+ * Requires 3 or 4 Z steppers.
+ *
+ * Define Stepper XY positions for Z1, Z2, Z3... corresponding to the screw
+ * positions in the bed carriage, with one position per Z stepper in stepper
+ * driver order.
+ */
+ //#define Z_STEPPER_ALIGN_STEPPER_XY { { 210.7, 102.5 }, { 152.6, 220.0 }, { 94.5, 102.5 } }
+
+ #ifndef Z_STEPPER_ALIGN_STEPPER_XY
// Amplification factor. Used to scale the correction step up or down in case
// the stepper (spindle) position is farther out than the test point.
#define Z_STEPPER_ALIGN_AMP 1.0 // Use a value > 1.0 NOTE: This may cause instability!
@@ -797,10 +1022,10 @@
//#define ASSISTED_TRAMMING
#if ENABLED(ASSISTED_TRAMMING)
- // Define positions for probing points, use the hotend as reference not the sensor.
- #define TRAMMING_POINT_XY { { 20, 20 }, { 200, 20 }, { 200, 200 }, { 20, 200 } }
+ // Define positions for probe points.
+ #define TRAMMING_POINT_XY { { 20, 20 }, { 180, 20 }, { 180, 180 }, { 20, 180 } }
- // Define positions names for probing points.
+ // Define position names for probe points.
#define TRAMMING_POINT_NAME_1 "Front-Left"
#define TRAMMING_POINT_NAME_2 "Front-Right"
#define TRAMMING_POINT_NAME_3 "Back-Right"
@@ -808,7 +1033,10 @@
#define RESTORE_LEVELING_AFTER_G35 // Enable to restore leveling setup after operation
//#define REPORT_TRAMMING_MM // Report Z deviation (mm) for each point relative to the first
- //#define ASSISTED_TRAMMING_MENU_ITEM // Add a menu item for Assisted Tramming
+
+ //#define ASSISTED_TRAMMING_WIZARD // Add a Tramming Wizard to the LCD menu
+
+ //#define ASSISTED_TRAMMING_WAIT_POSITION { X_CENTER, Y_CENTER, 30 } // Move the nozzle out of the way for adjustment
/**
* Screw thread:
@@ -831,6 +1059,12 @@
#define INVERT_X_STEP_PIN false
#define INVERT_Y_STEP_PIN false
#define INVERT_Z_STEP_PIN false
+#define INVERT_I_STEP_PIN false
+#define INVERT_J_STEP_PIN false
+#define INVERT_K_STEP_PIN false
+#define INVERT_U_STEP_PIN false
+#define INVERT_V_STEP_PIN false
+#define INVERT_W_STEP_PIN false
#define INVERT_E_STEP_PIN false
/**
@@ -842,16 +1076,17 @@
#define DISABLE_INACTIVE_X true
#define DISABLE_INACTIVE_Y true
#define DISABLE_INACTIVE_Z true // Set 'false' if the nozzle could fall onto your printed part!
+#define DISABLE_INACTIVE_I true
+#define DISABLE_INACTIVE_J true
+#define DISABLE_INACTIVE_K true
+#define DISABLE_INACTIVE_U true
+#define DISABLE_INACTIVE_V true
+#define DISABLE_INACTIVE_W true
#define DISABLE_INACTIVE_E true
-// If the Nozzle or Bed falls when the Z stepper is disabled, set its resting position here.
-//#define Z_AFTER_DEACTIVATE Z_HOME_POS
-
-//#define HOME_AFTER_DEACTIVATE // Require rehoming after steppers are deactivated
-
// Default Minimum Feedrates for printing and travel moves
-#define DEFAULT_MINIMUMFEEDRATE 0.0 // (mm/s) Minimum feedrate. Set with M205 S.
-#define DEFAULT_MINTRAVELFEEDRATE 0.0 // (mm/s) Minimum travel feedrate. Set with M205 T.
+#define DEFAULT_MINIMUMFEEDRATE 0.0 // (mm/s. °/s for rotational-only moves) Minimum feedrate. Set with M205 S.
+#define DEFAULT_MINTRAVELFEEDRATE 0.0 // (mm/s. °/s for rotational-only moves) Minimum travel feedrate. Set with M205 T.
// Minimum time that a segment needs to take as the buffer gets emptied
#define DEFAULT_MINSEGMENTTIME 20000 // (µs) Set with M205 B.
@@ -887,9 +1122,12 @@
#if ENABLED(BACKLASH_COMPENSATION)
// Define values for backlash distance and correction.
// If BACKLASH_GCODE is enabled these values are the defaults.
- #define BACKLASH_DISTANCE_MM { 0, 0, 0 } // (mm)
+ #define BACKLASH_DISTANCE_MM { 0, 0, 0 } // (linear=mm, rotational=°) One value for each linear axis
#define BACKLASH_CORRECTION 0.0 // 0.0 = no correction; 1.0 = full correction
+ // Add steps for motor direction changes on CORE kinematics
+ //#define CORE_BACKLASH
+
// Set BACKLASH_SMOOTHING_MM to spread backlash correction over multiple segments
// to reduce print artifacts. (Enabling this is costly in memory and computation!)
//#define BACKLASH_SMOOTHING_MM 3 // (mm)
@@ -907,7 +1145,7 @@
// increments while checking for the contact to be broken.
#define BACKLASH_MEASUREMENT_LIMIT 0.5 // (mm)
#define BACKLASH_MEASUREMENT_RESOLUTION 0.005 // (mm)
- #define BACKLASH_MEASUREMENT_FEEDRATE Z_PROBE_SPEED_SLOW // (mm/min)
+ #define BACKLASH_MEASUREMENT_FEEDRATE Z_PROBE_FEEDRATE_SLOW // (mm/min)
#endif
#endif
#endif
@@ -955,6 +1193,19 @@
#define CALIBRATION_MEASURE_LEFT
#define CALIBRATION_MEASURE_BACK
+ //#define CALIBRATION_MEASURE_IMIN
+ //#define CALIBRATION_MEASURE_IMAX
+ //#define CALIBRATION_MEASURE_JMIN
+ //#define CALIBRATION_MEASURE_JMAX
+ //#define CALIBRATION_MEASURE_KMIN
+ //#define CALIBRATION_MEASURE_KMAX
+ //#define CALIBRATION_MEASURE_UMIN
+ //#define CALIBRATION_MEASURE_UMAX
+ //#define CALIBRATION_MEASURE_VMIN
+ //#define CALIBRATION_MEASURE_VMAX
+ //#define CALIBRATION_MEASURE_WMIN
+ //#define CALIBRATION_MEASURE_WMAX
+
// Probing at the exact top center only works if the center is flat. If
// probing on a screwhead or hollow washer, probe near the edges.
//#define CALIBRATION_MEASURE_AT_TOP_EDGES
@@ -1017,7 +1268,7 @@
/**
* I2C-based DIGIPOTs (e.g., Azteeg X3 Pro)
*/
-//#define DIGIPOT_MCP4018 // Requires https://github.com/stawel/SlowSoftI2CMaster
+//#define DIGIPOT_MCP4018 // Requires https://github.com/felias-fogg/SlowSoftI2CMaster
//#define DIGIPOT_MCP4451
#if EITHER(DIGIPOT_MCP4018, DIGIPOT_MCP4451)
#define DIGIPOT_I2C_NUM_CHANNELS 8 // 5DPRINT:4 AZTEEG_X3_PRO:8 MKS_SBASE:5 MIGHTYBOARD_REVE:5
@@ -1048,9 +1299,9 @@
// @section lcd
-#if EITHER(IS_ULTIPANEL, EXTENSIBLE_UI)
+#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 SHORT_MANUAL_Z_MOVE 0.025 // (mm) Smallest manual Z move (< 0.1mm)
+ #define FINE_MANUAL_MOVE 0.025 // (mm) Smallest manual move (< 0.1mm) applying to Z on most machines
#if IS_ULTIPANEL
#define MANUAL_E_MOVES_RELATIVE // Display extruder move distance rather than "position"
#define ULTIPANEL_FEEDMULTIPLY // Encoder sets the feedrate multiplier on the Status Screen
@@ -1071,14 +1322,45 @@
#define FEEDRATE_CHANGE_BEEP_FREQUENCY 440
#endif
-#if HAS_LCD_MENU
+//
+// LCD Backlight Timeout
+//
+//#define LCD_BACKLIGHT_TIMEOUT_MINS 1 // (minutes) Timeout before turning off the backlight
+
+#if HAS_BED_PROBE && EITHER(HAS_MARLINUI_MENU, HAS_TFT_LVGL_UI)
+ //#define PROBE_OFFSET_WIZARD // Add a Probe Z Offset calibration option to the LCD menu
+ #if ENABLED(PROBE_OFFSET_WIZARD)
+ /**
+ * Enable to init the Probe Z-Offset when starting the Wizard.
+ * Use a height slightly above the estimated nozzle-to-probe Z offset.
+ * For example, with an offset of -5, consider a starting height of -4.
+ */
+ //#define PROBE_OFFSET_WIZARD_START_Z -4.0
+
+ // Set a convenient position to do the calibration (probing point and nozzle/bed-distance)
+ //#define PROBE_OFFSET_WIZARD_XY_POS { X_CENTER, Y_CENTER }
+ #endif
+#endif
+
+#if HAS_MARLINUI_MENU
- // Add Probe Z Offset calibration to the Z Probe Offsets menu
#if HAS_BED_PROBE
- #define PROBE_OFFSET_WIZARD
- #if ENABLED(PROBE_OFFSET_WIZARD)
- #define PROBE_OFFSET_START -4.0 // Estimated nozzle-to-probe Z offset, plus a little extra
+ // Add calibration in the Probe Offsets menu to compensate for X-axis twist.
+ //#define X_AXIS_TWIST_COMPENSATION
+ #if ENABLED(X_AXIS_TWIST_COMPENSATION)
+ /**
+ * Enable to init the Probe Z-Offset when starting the Wizard.
+ * Use a height slightly above the estimated nozzle-to-probe Z offset.
+ * For example, with an offset of -5, consider a starting height of -4.
+ */
+ #define XATC_START_Z 0.0
+ #define XATC_MAX_POINTS 3 // Number of points to probe in the wizard
+ #define XATC_Y_POSITION Y_CENTER // (mm) Y position to probe
+ #define XATC_Z_OFFSETS { 0, 0, 0 } // Z offsets for X axis sample points
#endif
+
+ // Show Deploy / Stow Probe options in the Motion menu.
+ #define PROBE_DEPLOY_STOW_MENU
#endif
// Include a page of printer information in the LCD Main Menu
@@ -1090,8 +1372,41 @@
// BACK menu items keep the highlight at the top
//#define TURBO_BACK_MENU_ITEM
- // Add a mute option to the LCD menu
- //#define SOUND_MENU_ITEM
+ // Insert a menu for preheating at the top level to allow for quick access
+ //#define PREHEAT_SHORTCUT_MENU_ITEM
+
+#endif // HAS_MARLINUI_MENU
+
+#if ANY(HAS_DISPLAY, DWIN_LCD_PROUI, DWIN_CREALITY_LCD_JYERSUI)
+ //#define SOUND_MENU_ITEM // Add a mute option to the LCD menu
+ #define SOUND_ON_DEFAULT // Buzzer/speaker default enabled state
+#endif
+
+#if EITHER(HAS_DISPLAY, DWIN_LCD_PROUI)
+ // The timeout to return to the status screen from sub-menus
+ //#define LCD_TIMEOUT_TO_STATUS 15000 // (ms)
+
+ #if ENABLED(SHOW_BOOTSCREEN)
+ #define BOOTSCREEN_TIMEOUT 4000 // (ms) Total Duration to display the boot screen(s)
+ #if EITHER(HAS_MARLINUI_U8GLIB, TFT_COLOR_UI)
+ #define BOOT_MARLIN_LOGO_SMALL // Show a smaller Marlin logo on the Boot Screen (saving lots of flash)
+ #endif
+ #endif
+
+ // Scroll a longer status message into view
+ //#define STATUS_MESSAGE_SCROLLING
+
+ // Apply a timeout to low-priority status messages
+ //#define STATUS_MESSAGE_TIMEOUT_SEC 30 // (seconds)
+
+ // On the Info Screen, display XY with one decimal place when possible
+ //#define LCD_DECIMAL_SMALL_XY
+
+ // Add an 'M73' G-code to set the current percentage
+ //#define LCD_SET_PROGRESS_MANUALLY
+
+ // Show the E position (filament used) during printing
+ //#define LCD_SHOW_E_TOTAL
/**
* LED Control Menu
@@ -1119,35 +1434,19 @@
#endif
#endif
-#endif // HAS_LCD_MENU
-
-// Scroll a longer status message into view
-#define STATUS_MESSAGE_SCROLLING
-
-// On the Info Screen, display XY with one decimal place when possible
-//#define LCD_DECIMAL_SMALL_XY
-
-// The timeout (in ms) to return to the status screen from sub-menus
-//#define LCD_TIMEOUT_TO_STATUS 15000
-
-// Add an 'M73' G-code to set the current percentage
-#define LCD_SET_PROGRESS_MANUALLY
-
-// Show the E position (filament used) during printing
-//#define LCD_SHOW_E_TOTAL
-
-#if ENABLED(SHOW_BOOTSCREEN)
- #define BOOTSCREEN_TIMEOUT 4000 // (ms) Total Duration to display the boot screen(s)
#endif
-#if EITHER(SDSUPPORT, LCD_SET_PROGRESS_MANUALLY) && ANY(HAS_MARLINUI_U8GLIB, HAS_MARLINUI_HD44780, IS_TFTGLCD_PANEL)
- //#define SHOW_REMAINING_TIME // Display estimated time to completion
- #if ENABLED(SHOW_REMAINING_TIME)
- //#define USE_M73_REMAINING_TIME // Use remaining time from M73 command instead of estimation
- //#define ROTATE_PROGRESS_DISPLAY // Display (P)rogress, (E)lapsed, and (R)emaining time
+// LCD Print Progress options
+#if EITHER(SDSUPPORT, LCD_SET_PROGRESS_MANUALLY)
+ #if CAN_SHOW_REMAINING_TIME
+ //#define SHOW_REMAINING_TIME // Display estimated time to completion
+ #if ENABLED(SHOW_REMAINING_TIME)
+ //#define USE_M73_REMAINING_TIME // Use remaining time from M73 command instead of estimation
+ //#define ROTATE_PROGRESS_DISPLAY // Display (P)rogress, (E)lapsed, and (R)emaining time
+ #endif
#endif
- #if HAS_MARLINUI_U8GLIB
+ #if EITHER(HAS_MARLINUI_U8GLIB, EXTENSIBLE_UI)
//#define PRINT_PROGRESS_SHOW_DECIMALS // Show progress with decimal digits
#endif
@@ -1164,13 +1463,26 @@
#endif
#if ENABLED(SDSUPPORT)
+ /**
+ * SD Card SPI Speed
+ * May be required to resolve "volume init" errors.
+ *
+ * Enable and set to SPI_HALF_SPEED, SPI_QUARTER_SPEED, or SPI_EIGHTH_SPEED
+ * otherwise full speed will be applied.
+ *
+ * :['SPI_HALF_SPEED', 'SPI_QUARTER_SPEED', 'SPI_EIGHTH_SPEED']
+ */
+ //#define SD_SPI_SPEED SPI_HALF_SPEED
// 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.
//#define SD_DETECT_STATE HIGH
+ //#define SD_IGNORE_AT_STARTUP // Don't mount the SD card when starting up
//#define SDCARD_READONLY // Read-only SD card (to save over 2K of flash)
+ //#define GCODE_REPEAT_MARKERS // Enable G-code M808 to set repeat markers and do looping
+
#define SD_PROCEDURE_DEPTH 1 // Increase if you need more nested M32 calls
#define SD_FINISHED_STEPPERRELEASE true // Disable steppers when SD Print is finished
@@ -1182,8 +1494,13 @@
#define SD_MENU_CONFIRM_START // Confirm the selected SD file before printing
+ //#define NO_SD_AUTOSTART // Remove auto#.g file support completely to save some Flash, SRAM
//#define MENU_ADDAUTOSTART // Add a menu option to run auto#.g files
+ //#define BROWSE_MEDIA_ON_INSERT // Open the file browser when media is inserted
+
+ //#define MEDIA_MENU_AT_TOP // Force the media menu to be listed on the top of the main menu
+
#define EVENT_GCODE_SD_ABORT "G28XY" // G-code to run on SD Abort Print (e.g., "G28XY" or "G27")
#if ENABLED(PRINTER_EVENT_LEDS)
@@ -1202,17 +1519,23 @@
#if ENABLED(POWER_LOSS_RECOVERY)
#define PLR_ENABLED_DEFAULT false // Power Loss Recovery enabled by default. (Set with 'M413 Sn' & M500)
//#define BACKUP_POWER_SUPPLY // Backup power / UPS to move the steppers on power loss
- //#define POWER_LOSS_RECOVER_ZHOME // Z homing is needed for proper recovery. 99.9% of the time this should be disabled!
//#define POWER_LOSS_ZRAISE 2 // (mm) Z axis raise on resume (on power loss with UPS)
//#define POWER_LOSS_PIN 44 // Pin to detect power loss. Set to -1 to disable default pin on boards without module.
//#define POWER_LOSS_STATE HIGH // State of pin indicating power loss
- //#define POWER_LOSS_PULL // Set pullup / pulldown as appropriate
+ //#define POWER_LOSS_PULLUP // Set pullup / pulldown as appropriate for your sensor
+ //#define POWER_LOSS_PULLDOWN
//#define POWER_LOSS_PURGE_LEN 20 // (mm) Length of filament to purge on resume
//#define POWER_LOSS_RETRACT_LEN 10 // (mm) Length of filament to retract on fail. Requires backup power.
// Without a POWER_LOSS_PIN the following option helps reduce wear on the SD card,
// especially with "vase mode" printing. Set too high and vases cannot be continued.
#define POWER_LOSS_MIN_Z_CHANGE 0.05 // (mm) Minimum Z change before saving power-loss data
+
+ // Enable if Z homing is needed for proper recovery. 99.9% of the time this should be disabled!
+ //#define POWER_LOSS_RECOVER_ZHOME
+ #if ENABLED(POWER_LOSS_RECOVER_ZHOME)
+ //#define POWER_LOSS_ZHOME_POS { 0, 0 } // Safe XY position to home Z while avoiding objects on the bed
+ #endif
#endif
/**
@@ -1253,33 +1576,31 @@
// Note: Only affects SCROLL_LONG_FILENAMES with SDSORT_CACHE_NAMES but not SDSORT_DYNAMIC_RAM.
#endif
- // This allows hosts to request long names for files and folders with M33
- #define LONG_FILENAME_HOST_SUPPORT
+ // Allow international symbols in long filenames. To display correctly, the
+ // LCD's font must contain the characters. Check your selected LCD language.
+ #define UTF_FILENAME_SUPPORT
- // Enable this option to scroll long filenames in the SD card menu
- //#define SCROLL_LONG_FILENAMES
+ #define LONG_FILENAME_HOST_SUPPORT // Get the long filename of a file/folder with 'M33 ' and list long filenames with 'M20 L'
+ #define LONG_FILENAME_WRITE_SUPPORT // Create / delete files with long filenames via M28, M30, and Binary Transfer Protocol
+ //#define M20_TIMESTAMP_SUPPORT // Include timestamps by adding the 'T' flag to M20 commands
- // Leave the heaters on after Stop Print (not recommended!)
- //#define SD_ABORT_NO_COOLDOWN
+ //#define SCROLL_LONG_FILENAMES // Scroll long filenames in the SD card menu
+
+ //#define SD_ABORT_NO_COOLDOWN // Leave the heaters on after Stop Print (not recommended!)
/**
- * This option allows you to abort SD printing when any endstop is triggered.
- * This feature must be enabled with "M540 S1" or from the LCD menu.
- * To have any effect, endstops must be enabled during SD printing.
+ * Abort SD printing when any endstop is triggered.
+ * This feature is enabled with 'M540 S1' or from the LCD menu.
+ * Endstops must be activated for this option to work.
*/
//#define SD_ABORT_ON_ENDSTOP_HIT
+ #if ENABLED(SD_ABORT_ON_ENDSTOP_HIT)
+ //#define SD_ABORT_ON_ENDSTOP_HIT_GCODE "G28XY" // G-code to run on endstop hit (e.g., "G28XY" or "G27")
+ #endif
- /**
- * This option makes it easier to print the same SD Card file again.
- * On print completion the LCD Menu will open with the file selected.
- * You can just click to start the print, or navigate elsewhere.
- */
- //#define SD_REPRINT_LAST_SELECTED_FILE
+ //#define SD_REPRINT_LAST_SELECTED_FILE // On print completion open the LCD Menu and select the same file
- /**
- * Auto-report SdCard status with M27 S
- */
- //#define AUTO_REPORT_SD_STATUS
+ //#define AUTO_REPORT_SD_STATUS // Auto-report media status with 'M27 S'
/**
* Support for USB thumb drives using an Arduino USB Host Shield or
@@ -1297,9 +1618,6 @@
*/
//#define USB_FLASH_DRIVE_SUPPORT
#if ENABLED(USB_FLASH_DRIVE_SUPPORT)
- #define USB_CS_PIN SDSS
- #define USB_INTR_PIN SD_DETECT_PIN
-
/**
* USB Host Shield Library
*
@@ -1310,7 +1628,20 @@
* is less tested and is known to interfere with Servos.
* [1] This requires USB_INTR_PIN to be interrupt-capable.
*/
+ //#define USE_UHS2_USB
//#define USE_UHS3_USB
+
+ #define DISABLE_DUE_SD_MMC // Disable USB Host access to USB Drive to prevent hangs on block access for DUE platform
+
+ /**
+ * Native USB Host supported by some boards (USB OTG)
+ */
+ //#define USE_OTG_USB_HOST
+
+ #if DISABLED(USE_OTG_USB_HOST)
+ #define USB_CS_PIN SDSS
+ #define USB_INTR_PIN SD_DETECT_PIN
+ #endif
#endif
/**
@@ -1329,20 +1660,53 @@
#define SD_FIRMWARE_UPDATE_INACTIVE_VALUE 0xFF
#endif
+ /**
+ * Enable this option if you have more than ~3K of unused flash space.
+ * Marlin will embed all settings in the firmware binary as compressed data.
+ * Use 'M503 C' to write the settings out to the SD Card as 'mc.zip'.
+ * See docs/ConfigEmbedding.md for details on how to use 'mc-apply.py'.
+ */
+ //#define CONFIGURATION_EMBEDDING
+
// Add an optimized binary file transfer mode, initiated with 'M28 B1'
#define BINARY_FILE_TRANSFER
+ #if ENABLED(BINARY_FILE_TRANSFER)
+ // Include extra facilities (e.g., 'M20 F') supporting firmware upload via BINARY_FILE_TRANSFER
+ //#define CUSTOM_FIRMWARE_UPLOAD
+ #endif
+
+ #if ENABLED(BINARY_FILE_TRANSFER)
+ // Include extra facilities (e.g., 'M20 F') supporting firmware upload via BINARY_FILE_TRANSFER
+ //#define CUSTOM_FIRMWARE_UPLOAD
+ #endif
+
/**
* Set this option to one of the following (or the board's defaults apply):
*
* LCD - Use the SD drive in the external LCD controller.
- * ONBOARD - Use the SD drive on the control board. (No SD_DETECT_PIN. M21 to init.)
+ * ONBOARD - Use the SD drive on the control board.
* CUSTOM_CABLE - Use a custom cable to access the SD (as defined in a pins file).
*
* :[ 'LCD', 'ONBOARD', 'CUSTOM_CABLE' ]
*/
#define SDCARD_CONNECTION LCD
+ // Enable if SD detect is rendered useless (e.g., by using an SD extender)
+ //#define NO_SD_DETECT
+
+ /**
+ * Multiple volume support - EXPERIMENTAL.
+ * Adds 'M21 Pm' / 'M21 S' / 'M21 U' to mount SD Card / USB Drive.
+ */
+ //#define MULTI_VOLUME
+ #if ENABLED(MULTI_VOLUME)
+ #define VOLUME_SD_ONBOARD
+ #define VOLUME_USB_FLASH_DRIVE
+ #define DEFAULT_VOLUME SV_SD_ONBOARD
+ #define DEFAULT_SHARED_VOLUME SV_USB_FLASH_DRIVE
+ #endif
+
#endif // SDSUPPORT
/**
@@ -1364,26 +1728,28 @@
* printing performance versus fast display updates.
*/
#if HAS_MARLINUI_U8GLIB
- // Show SD percentage next to the progress bar
- //#define DOGM_SD_PERCENT
-
// Save many cycles by drawing a hollow frame or no frame on the Info Screen
//#define XYZ_NO_FRAME
#define XYZ_HOLLOW_FRAME
- // Enable to save many cycles by drawing a hollow frame on Menu Screens
- #define MENU_HOLLOW_FRAME
-
- // A bigger font is available for edit items. Costs 3120 bytes of PROGMEM.
+ // A bigger font is available for edit items. Costs 3120 bytes of flash.
// Western only. Not available for Cyrillic, Kana, Turkish, Greek, or Chinese.
//#define USE_BIG_EDIT_FONT
- // A smaller font may be used on the Info Screen. Costs 2434 bytes of PROGMEM.
+ // A smaller font may be used on the Info Screen. Costs 2434 bytes of flash.
// Western only. Not available for Cyrillic, Kana, Turkish, Greek, or Chinese.
//#define USE_SMALL_INFOFONT
- // Swap the CW/CCW indicators in the graphics overlay
- //#define OVERLAY_GFX_REVERSE
+ /**
+ * Graphical Display Sleep
+ *
+ * The U8G library provides sleep / wake functions for SH1106, SSD1306,
+ * SSD1309, and some other DOGM displays.
+ * Enable this option to save energy and prevent OLED pixel burn-in.
+ * Adds the menu item Configuration > LCD Timeout (m) to set a wait period
+ * from 0 (disabled) to 99 minutes.
+ */
+ //#define DISPLAY_SLEEP_MINUTES 2 // (minutes) Timeout before turning off the screen. Set with M255 S.
/**
* ST7920-based LCDs can emulate a 16 x 4 character display using
@@ -1397,7 +1763,7 @@
* Set STATUS_EXPIRE_SECONDS to zero to never clear the status.
* This will prevent position updates from being displayed.
*/
- #if ENABLED(U8GLIB_ST7920)
+ #if IS_U8GLIB_ST7920
// Enable this option and reduce the value to optimize screen updates.
// The normal delay is 10µs. Use the lowest value that still gives a reliable display.
//#define DOGM_SPI_DELAY_US 5
@@ -1415,17 +1781,18 @@
*/
//#define STATUS_COMBINE_HEATERS // Use combined heater images instead of separate ones
//#define STATUS_HOTEND_NUMBERLESS // Use plain hotend icons instead of numbered ones (with 2+ hotends)
- #define STATUS_HOTEND_INVERTED // Show solid nozzle bitmaps when heating (Requires STATUS_HOTEND_ANIM)
+ #define STATUS_HOTEND_INVERTED // Show solid nozzle bitmaps when heating (Requires STATUS_HOTEND_ANIM for numbered hotends)
#define STATUS_HOTEND_ANIM // Use a second bitmap to indicate hotend heating
#define STATUS_BED_ANIM // Use a second bitmap to indicate bed heating
#define STATUS_CHAMBER_ANIM // Use a second bitmap to indicate chamber heating
//#define STATUS_CUTTER_ANIM // Use a second bitmap to indicate spindle / laser active
- #define STATUS_ALT_BED_BITMAP // Use the alternative bed bitmap
- #define STATUS_ALT_FAN_BITMAP // Use the alternative fan bitmap
+ //#define STATUS_COOLER_ANIM // Use a second bitmap to indicate laser cooling
+ //#define STATUS_FLOWMETER_ANIM // Use multiple bitmaps to indicate coolant flow
+ //#define STATUS_ALT_BED_BITMAP // Use the alternative bed bitmap
+ //#define STATUS_ALT_FAN_BITMAP // Use the alternative fan bitmap
//#define STATUS_FAN_FRAMES 3 // :[0,1,2,3,4] Number of fan animation frames
- #define STATUS_HEAT_PERCENT // Show heating in a progress bar
- #define BOOT_MARLIN_LOGO_SMALL // Show a smaller Marlin logo on the Boot Screen (saving 399 bytes of flash)
- #define BOOT_MARLIN_LOGO_ANIMATED // Animated Marlin logo. Costs ~3260 (or ~940) bytes of PROGMEM.
+ //#define STATUS_HEAT_PERCENT // Show heating in a progress bar
+ //#define BOOT_MARLIN_LOGO_ANIMATED // Animated Marlin logo. Costs ~3260 (or ~940) bytes of flash.
// Frivolous Game Options
//#define MARLIN_BRICKOUT
@@ -1435,11 +1802,21 @@
#endif // HAS_MARLINUI_U8GLIB
+#if HAS_MARLINUI_U8GLIB || IS_DWIN_MARLINUI
+ // Show SD percentage next to the progress bar
+ //#define SHOW_SD_PERCENT
+
+ // Enable to save many cycles by drawing a hollow frame on Menu Screens
+ #define MENU_HOLLOW_FRAME
+
+ // Swap the CW/CCW indicators in the graphics overlay
+ //#define OVERLAY_GFX_REVERSE
+#endif
+
//
// Additional options for DGUS / DWIN displays
//
#if HAS_DGUS_LCD
- #define LCD_SERIAL_PORT 3
#define LCD_BAUDRATE 115200
#define DGUS_RX_BUFFER_SIZE 128
@@ -1448,12 +1825,12 @@
#define DGUS_UPDATE_INTERVAL_MS 500 // (ms) Interval between automatic screen updates
- #if EITHER(DGUS_LCD_UI_FYSETC, DGUS_LCD_UI_HIPRECY)
+ #if ANY(DGUS_LCD_UI_FYSETC, DGUS_LCD_UI_MKS, DGUS_LCD_UI_HIPRECY)
#define DGUS_PRINT_FILENAME // Display the filename during printing
#define DGUS_PREHEAT_UI // Display a preheat screen during heatup
- #if ENABLED(DGUS_LCD_UI_FYSETC)
- //#define DGUS_UI_MOVE_DIS_OPTION // Disabled by default for UI_FYSETC
+ #if EITHER(DGUS_LCD_UI_FYSETC, DGUS_LCD_UI_MKS)
+ //#define DGUS_UI_MOVE_DIS_OPTION // Disabled by default for FYSETC and MKS
#else
#define DGUS_UI_MOVE_DIS_OPTION // Enabled by default for UI_HIPRECY
#endif
@@ -1472,6 +1849,44 @@
#endif
#endif // HAS_DGUS_LCD
+//
+// Additional options for AnyCubic Chiron TFT displays
+//
+#if ENABLED(ANYCUBIC_LCD_CHIRON)
+ // By default the type of panel is automatically detected.
+ // Enable one of these options if you know the panel type.
+ //#define CHIRON_TFT_STANDARD
+ //#define CHIRON_TFT_NEW
+
+ // Enable the longer Anycubic powerup startup tune
+ //#define AC_DEFAULT_STARTUP_TUNE
+
+ /**
+ * Display Folders
+ * By default the file browser lists all G-code files (including those in subfolders) in a flat list.
+ * Enable this option to display a hierarchical file browser.
+ *
+ * NOTES:
+ * - Without this option it helps to enable SDCARD_SORT_ALPHA so files are sorted before/after folders.
+ * - When used with the "new" panel, folder names will also have '.gcode' appended to their names.
+ * This hack is currently required to force the panel to show folders.
+ */
+ #define AC_SD_FOLDER_VIEW
+#endif
+
+//
+// Specify additional languages for the UI. Default specified by LCD_LANGUAGE.
+//
+#if ANY(DOGLCD, TFT_COLOR_UI, TOUCH_UI_FTDI_EVE, IS_DWIN_MARLINUI)
+ //#define LCD_LANGUAGE_2 fr
+ //#define LCD_LANGUAGE_3 de
+ //#define LCD_LANGUAGE_4 es
+ //#define LCD_LANGUAGE_5 it
+ #ifdef LCD_LANGUAGE_2
+ //#define LCD_LANGUAGE_AUTO_SAVE // Automatically save language to EEPROM on change
+ #endif
+#endif
+
//
// Touch UI for the FTDI Embedded Video Engine (EVE)
//
@@ -1481,8 +1896,10 @@
//#define LCD_4DSYSTEMS_4DLCD_FT843 // 4D Systems 4.3" (480x272)
//#define LCD_HAOYU_FT800CB // Haoyu with 4.3" or 5" (480x272)
//#define LCD_HAOYU_FT810CB // Haoyu with 5" (800x480)
- //#define LCD_ALEPHOBJECTS_CLCD_UI // Aleph Objects Color LCD UI
+ //#define LCD_LULZBOT_CLCD_UI // LulzBot Color LCD UI
//#define LCD_FYSETC_TFT81050 // FYSETC with 5" (800x480)
+ //#define LCD_EVE3_50G // Matrix Orbital 5.0", 800x480, BT815
+ //#define LCD_EVE2_50G // Matrix Orbital 5.0", 800x480, FT813
// Correct the resolution if not using the stock TFT panel.
//#define TOUCH_UI_320x240
@@ -1490,8 +1907,8 @@
//#define TOUCH_UI_800x480
// Mappings for boards with a standard RepRapDiscount Display connector
- //#define AO_EXP1_PINMAP // AlephObjects CLCD UI EXP1 mapping
- //#define AO_EXP2_PINMAP // AlephObjects CLCD UI EXP2 mapping
+ //#define AO_EXP1_PINMAP // LulzBot CLCD UI EXP1 mapping
+ //#define AO_EXP2_PINMAP // LulzBot CLCD UI EXP2 mapping
//#define CR10_TFT_PINMAP // Rudolph Riedel's CR10 pin mapping
//#define S6_TFT_PINMAP // FYSETC S6 pin mapping
//#define F6_TFT_PINMAP // FYSETC F6 pin mapping
@@ -1539,18 +1956,14 @@
//#define TOUCH_UI_UTF8_FRACTIONS // ¼ ½ ¾
//#define TOUCH_UI_UTF8_SYMBOLS // µ ¶ ¦ § ¬
#endif
+
+ // Cyrillic character set, costs about 27KiB of flash
+ //#define TOUCH_UI_UTF8_CYRILLIC_CHARSET
#endif
// Use a smaller font when labels don't fit buttons
#define TOUCH_UI_FIT_TEXT
- // Allow language selection from menu at run-time (otherwise use LCD_LANGUAGE)
- //#define LCD_LANGUAGE_1 en
- //#define LCD_LANGUAGE_2 fr
- //#define LCD_LANGUAGE_3 de
- //#define LCD_LANGUAGE_4 es
- //#define LCD_LANGUAGE_5 it
-
// Use a numeric passcode for "Screen lock" keypad.
// (recommended for smaller displays)
//#define TOUCH_UI_PASSCODE
@@ -1653,16 +2066,33 @@
*
* See https://marlinfw.org/docs/features/lin_advance.html for full instructions.
*/
-// #define LIN_ADVANCE
+#define LIN_ADVANCE
#if ENABLED(LIN_ADVANCE)
- //#define EXTRA_LIN_ADVANCE_K // Enable for second linear advance constants
- #define LIN_ADVANCE_K 0 // Unit: mm compression per 1mm/s extruder speed
- //#define LA_DEBUG // If enabled, this will generate debug information output over USB.
- // #define EXPERIMENTAL_SCURVE // Enable this option to permit S-Curve Acceleration
+ //#define EXTRA_LIN_ADVANCE_K // Add a second linear advance constant, configurable with M900.
+ #define LIN_ADVANCE_K 0.22 // Unit: mm compression per 1mm/s extruder speed
+ //#define LA_DEBUG // Print debug information to serial during operation. Disable for production use.
+ //#define EXPERIMENTAL_SCURVE // Allow S-Curve Acceleration to be used with LA.
+ //#define ALLOW_LOW_EJERK // Allow a DEFAULT_EJERK value of <10. Recommended for direct drive hotends.
+ //#define EXPERIMENTAL_I2S_LA // Allow I2S_STEPPER_STREAM to be used with LA. Performance degrades as the LA step rate reaches ~20kHz.
#endif
// @section leveling
+/**
+ * Use Safe Bed Leveling coordinates to move axes to a useful position before bed probing.
+ * For example, after homing a rotational axis the Z probe might not be perpendicular to the bed.
+ * Choose values the orient the bed horizontally and the Z-probe vertically.
+ */
+//#define SAFE_BED_LEVELING_START_X 0.0
+//#define SAFE_BED_LEVELING_START_Y 0.0
+//#define SAFE_BED_LEVELING_START_Z 0.0
+//#define SAFE_BED_LEVELING_START_I 0.0
+//#define SAFE_BED_LEVELING_START_J 0.0
+//#define SAFE_BED_LEVELING_START_K 0.0
+//#define SAFE_BED_LEVELING_START_U 0.0
+//#define SAFE_BED_LEVELING_START_V 0.0
+//#define SAFE_BED_LEVELING_START_W 0.0
+
/**
* Points to probe for all 3-point Leveling procedures.
* Override if the automatically selected points are inadequate.
@@ -1710,6 +2140,10 @@
//#define MESH_MAX_Y Y_BED_SIZE - (MESH_INSET)
#endif
+#if BOTH(AUTO_BED_LEVELING_UBL, EEPROM_SETTINGS)
+ //#define OPTIMIZED_MESH_STORAGE // Store mesh with less precision to save EEPROM space
+#endif
+
/**
* Repeatedly attempt G29 leveling until it succeeds.
* Stop after G29_MAX_RETRIES attempts.
@@ -1730,59 +2164,69 @@
/**
* Thermal Probe Compensation
- * Probe measurements are adjusted to compensate for temperature distortion.
- * Use G76 to calibrate this feature. Use M871 to set values manually.
- * For a more detailed explanation of the process see G76_M871.cpp.
+ *
+ * Adjust probe measurements to compensate for distortion associated with the temperature
+ * of the probe, bed, and/or hotend.
+ * Use G76 to automatically calibrate this feature for probe and bed temperatures.
+ * (Extruder temperature/offset values must be calibrated manually.)
+ * Use M871 to set temperature/offset values manually.
+ * For more details see https://marlinfw.org/docs/features/probe_temp_compensation.html
*/
-#if HAS_BED_PROBE && TEMP_SENSOR_PROBE && TEMP_SENSOR_BED
- // Enable thermal first layer compensation using bed and probe temperatures
- #define PROBE_TEMP_COMPENSATION
+//#define PTC_PROBE // Compensate based on probe temperature
+//#define PTC_BED // Compensate based on bed temperature
+//#define PTC_HOTEND // Compensate based on hotend temperature
- // Add additional compensation depending on hotend temperature
- // Note: this values cannot be calibrated and have to be set manually
- #if ENABLED(PROBE_TEMP_COMPENSATION)
- // Park position to wait for probe cooldown
- #define PTC_PARK_POS { 0, 0, 100 }
-
- // Probe position to probe and wait for probe to reach target temperature
- #define PTC_PROBE_POS { 90, 100 }
-
- // Enable additional compensation using hotend temperature
- // Note: this values cannot be calibrated automatically but have to be set manually
- //#define USE_TEMP_EXT_COMPENSATION
-
- // Probe temperature calibration generates a table of values starting at PTC_SAMPLE_START
- // (e.g. 30), in steps of PTC_SAMPLE_RES (e.g. 5) with PTC_SAMPLE_COUNT (e.g. 10) samples.
-
- //#define PTC_SAMPLE_START 30.0f
- //#define PTC_SAMPLE_RES 5.0f
- //#define PTC_SAMPLE_COUNT 10U
+#if ANY(PTC_PROBE, PTC_BED, PTC_HOTEND)
+ /**
+ * If the probe is outside the defined range, use linear extrapolation with the closest
+ * point and the point with index PTC_LINEAR_EXTRAPOLATION. e.g., If set to 4 it will use the
+ * linear extrapolation between data[0] and data[4] for values below PTC_PROBE_START.
+ */
+ //#define PTC_LINEAR_EXTRAPOLATION 4
+
+ #if ENABLED(PTC_PROBE)
+ // Probe temperature calibration generates a table of values starting at PTC_PROBE_START
+ // (e.g., 30), in steps of PTC_PROBE_RES (e.g., 5) with PTC_PROBE_COUNT (e.g., 10) samples.
+ #define PTC_PROBE_START 30 // (°C)
+ #define PTC_PROBE_RES 5 // (°C)
+ #define PTC_PROBE_COUNT 10
+ #define PTC_PROBE_ZOFFS { 0 } // (µm) Z adjustments per sample
+ #endif
+ #if ENABLED(PTC_BED)
// Bed temperature calibration builds a similar table.
+ #define PTC_BED_START 60 // (°C)
+ #define PTC_BED_RES 5 // (°C)
+ #define PTC_BED_COUNT 10
+ #define PTC_BED_ZOFFS { 0 } // (µm) Z adjustments per sample
+ #endif
- //#define BTC_SAMPLE_START 60.0f
- //#define BTC_SAMPLE_RES 5.0f
- //#define BTC_SAMPLE_COUNT 10U
+ #if ENABLED(PTC_HOTEND)
+ // Note: There is no automatic calibration for the hotend. Use M871.
+ #define PTC_HOTEND_START 180 // (°C)
+ #define PTC_HOTEND_RES 5 // (°C)
+ #define PTC_HOTEND_COUNT 20
+ #define PTC_HOTEND_ZOFFS { 0 } // (µm) Z adjustments per sample
+ #endif
- // The temperature the probe should be at while taking measurements during bed temperature
- // calibration.
- //#define BTC_PROBE_TEMP 30.0f
+ // G76 options
+ #if BOTH(PTC_PROBE, PTC_BED)
+ // Park position to wait for probe cooldown
+ #define PTC_PARK_POS { 0, 0, 100 }
- // Height above Z=0.0f to raise the nozzle. Lowering this can help the probe to heat faster.
- // Note: the Z=0.0f offset is determined by the probe offset which can be set using M851.
- //#define PTC_PROBE_HEATING_OFFSET 0.5f
+ // Probe position to probe and wait for probe to reach target temperature
+ //#define PTC_PROBE_POS { 12.0f, 7.3f } // Example: MK52 magnetic heatbed
+ #define PTC_PROBE_POS { 90, 100 }
- // Height to raise the Z-probe between heating and taking the next measurement. Some probes
- // may fail to untrigger if they have been triggered for a long time, which can be solved by
- // increasing the height the probe is raised to.
- //#define PTC_PROBE_RAISE 15U
+ // The temperature the probe should be at while taking measurements during
+ // bed temperature calibration.
+ #define PTC_PROBE_TEMP 30 // (°C)
- // If the probe is outside of the defined range, use linear extrapolation using the closest
- // point and the PTC_LINEAR_EXTRAPOLATION'th next point. E.g. if set to 4 it will use data[0]
- // and data[4] to perform linear extrapolation for values below PTC_SAMPLE_START.
- //#define PTC_LINEAR_EXTRAPOLATION 4
+ // Height above Z=0.0 to raise the nozzle. Lowering this can help the probe to heat faster.
+ // Note: The Z=0.0 offset is determined by the probe Z offset (e.g., as set with M851 Z).
+ #define PTC_PROBE_HEATING_OFFSET 0.5
#endif
-#endif
+#endif // PTC_PROBE || PTC_BED || PTC_HOTEND
// @section extras
@@ -1794,20 +2238,23 @@
//
// G2/G3 Arc Support
//
-#define ARC_SUPPORT // Disable this feature to save ~3226 bytes
+#define ARC_SUPPORT // Requires ~3226 bytes
#if ENABLED(ARC_SUPPORT)
- #define MM_PER_ARC_SEGMENT 1 // (mm) Length (or minimum length) of each arc segment
- //#define ARC_SEGMENTS_PER_R 1 // Max segment length, MM_PER = Min
- #define MIN_ARC_SEGMENTS 24 // Minimum number of segments in a complete circle
- //#define ARC_SEGMENTS_PER_SEC 50 // Use feedrate to choose segment length (with MM_PER_ARC_SEGMENT as the minimum)
- #define N_ARC_CORRECTION 25 // Number of interpolated segments between corrections
- //#define ARC_P_CIRCLES // Enable the 'P' parameter to specify complete circles
- //#define CNC_WORKSPACE_PLANES // Allow G2/G3 to operate in XY, ZX, or YZ planes
- //#define SF_ARC_FIX // Enable only if using SkeinForge with "Arc Point" fillet procedure
+ #define MIN_ARC_SEGMENT_MM 0.1 // (mm) Minimum length of each arc segment
+ #define MAX_ARC_SEGMENT_MM 1.0 // (mm) Maximum length of each arc segment
+ #define MIN_CIRCLE_SEGMENTS 72 // Minimum number of segments in a complete circle
+ //#define ARC_SEGMENTS_PER_SEC 50 // Use the feedrate to choose the segment length
+ #define N_ARC_CORRECTION 25 // Number of interpolated segments between corrections
+ //#define ARC_P_CIRCLES // Enable the 'P' parameter to specify complete circles
+ //#define SF_ARC_FIX // Enable only if using SkeinForge with "Arc Point" fillet procedure
#endif
-// Support for G5 with XYZE destination and IJPQ offsets. Requires ~2666 bytes.
-//#define BEZIER_CURVE_SUPPORT
+// G5 Bézier Curve Support with XYZE destination and IJPQ offsets
+//#define BEZIER_CURVE_SUPPORT // Requires ~2666 bytes
+
+#if EITHER(ARC_SUPPORT, BEZIER_CURVE_SUPPORT)
+ //#define CNC_WORKSPACE_PLANES // Allow G2/G3/G5 to operate in XY, ZX, or YZ planes
+#endif
/**
* Direct Stepping
@@ -1890,7 +2337,7 @@
// @section motion
// The number of linear moves that can be in the planner at once.
-// The value of BLOCK_BUFFER_SIZE must be a power of 2 (e.g. 8, 16, 32)
+// The value of BLOCK_BUFFER_SIZE must be a power of 2 (e.g., 8, 16, 32)
#if BOTH(SDSUPPORT, DIRECT_STEPPING)
#define BLOCK_BUFFER_SIZE 8
#elif ENABLED(SDSUPPORT)
@@ -1906,7 +2353,7 @@
#define BUFSIZE 4
// Transmission to Host Buffer Size
-// To save 386 bytes of PROGMEM (and TX_BUFFER_SIZE+3 bytes of RAM) set to 0.
+// To save 386 bytes of flash (and TX_BUFFER_SIZE+3 bytes of RAM) set to 0.
// To buffer a simple "ok" you need 4 bytes.
// For ADVANCED_OK (M105) you need 32 bytes.
// For debug-echo: 128 bytes for the optimal speed.
@@ -1926,9 +2373,6 @@
//#define SERIAL_XON_XOFF
#endif
-// Add M575 G-code to change the baud rate
-//#define BAUD_RATE_GCODE
-
#if ENABLED(SDSUPPORT)
// Enable this option to collect and display the maximum
// RX queue usage after transferring a file to SD.
@@ -1939,6 +2383,12 @@
//#define SERIAL_STATS_DROPPED_RX
#endif
+// Monitor RX buffer usage
+// Dump an error to the serial port if the serial receive buffer overflows.
+// If you see these errors, increase the RX_BUFFER_SIZE value.
+// Not supported on all platforms.
+//#define RX_BUFFER_MONITOR
+
/**
* Emergency Command Parser
*
@@ -1949,6 +2399,26 @@
*/
//#define EMERGENCY_PARSER
+/**
+ * Realtime Reporting (requires EMERGENCY_PARSER)
+ *
+ * - Report position and state of the machine (like Grbl).
+ * - Auto-report position during long moves.
+ * - Useful for CNC/LASER.
+ *
+ * Adds support for commands:
+ * S000 : Report State and Position while moving.
+ * P000 : Instant Pause / Hold while moving.
+ * R000 : Resume from Pause / Hold.
+ *
+ * - During Hold all Emergency Parser commands are available, as usual.
+ * - Enable NANODLP_Z_SYNC and NANODLP_ALL_AXIS for move command end-state reports.
+ */
+//#define REALTIME_REPORTING_COMMANDS
+#if ENABLED(REALTIME_REPORTING_COMMANDS)
+ //#define FULL_REPORT_TO_HOST_FEATURE // Auto-report the machine status like Grbl CNC
+#endif
+
// Bad Serial-connections can miss a received command by sending an 'ok'
// Therefore some clients abort after 30 seconds in a timeout.
// Some other clients start sending commands while receiving a 'wait'.
@@ -1965,6 +2435,15 @@
// For serial echo, the number of digits after the decimal point
//#define SERIAL_FLOAT_PRECISION 4
+/**
+ * Set the number of proportional font spaces required to fill up a typical character space.
+ * This can help to better align the output of commands like `G29 O` Mesh Output.
+ *
+ * For clients that use a fixed-width font (like OctoPrint), leave this set to 1.0.
+ * Otherwise, adjust according to your client and font.
+ */
+#define PROPORTIONAL_FONT_RATIO 1.0
+
// @section extras
/**
@@ -1992,21 +2471,21 @@
*/
//#define FWRETRACT
#if ENABLED(FWRETRACT)
- #define FWRETRACT_AUTORETRACT // Override slicer retractions
+ #define FWRETRACT_AUTORETRACT // Override slicer retractions
#if ENABLED(FWRETRACT_AUTORETRACT)
- #define MIN_AUTORETRACT 0.1 // (mm) Don't convert E moves under this length
- #define MAX_AUTORETRACT 10.0 // (mm) Don't convert E moves over this length
- #endif
- #define RETRACT_LENGTH 3 // (mm) Default retract length (positive value)
- #define RETRACT_LENGTH_SWAP 13 // (mm) Default swap retract length (positive value)
- #define RETRACT_FEEDRATE 45 // (mm/s) Default feedrate for retracting
- #define RETRACT_ZRAISE 0 // (mm) Default retract Z-raise
- #define RETRACT_RECOVER_LENGTH 0 // (mm) Default additional recover length (added to retract length on recover)
- #define RETRACT_RECOVER_LENGTH_SWAP 0 // (mm) Default additional swap recover length (added to retract length on recover from toolchange)
- #define RETRACT_RECOVER_FEEDRATE 8 // (mm/s) Default feedrate for recovering from retraction
- #define RETRACT_RECOVER_FEEDRATE_SWAP 8 // (mm/s) Default feedrate for recovering from swap retraction
+ #define MIN_AUTORETRACT 0.1 // (mm) Don't convert E moves under this length
+ #define MAX_AUTORETRACT 10.0 // (mm) Don't convert E moves over this length
+ #endif
+ #define RETRACT_LENGTH 3 // (mm) Default retract length (positive value)
+ #define RETRACT_LENGTH_SWAP 13 // (mm) Default swap retract length (positive value)
+ #define RETRACT_FEEDRATE 45 // (mm/s) Default feedrate for retracting
+ #define RETRACT_ZRAISE 0 // (mm) Default retract Z-raise
+ #define RETRACT_RECOVER_LENGTH 0 // (mm) Default additional recover length (added to retract length on recover)
+ #define RETRACT_RECOVER_LENGTH_SWAP 0 // (mm) Default additional swap recover length (added to retract length on recover from toolchange)
+ #define RETRACT_RECOVER_FEEDRATE 8 // (mm/s) Default feedrate for recovering from retraction
+ #define RETRACT_RECOVER_FEEDRATE_SWAP 8 // (mm/s) Default feedrate for recovering from swap retraction
#if ENABLED(MIXING_EXTRUDER)
- //#define RETRACT_SYNC_MIXING // Retract and restore all mixing steppers simultaneously
+ //#define RETRACT_SYNC_MIXING // Retract and restore all mixing steppers simultaneously
#endif
#endif
@@ -2023,6 +2502,20 @@
//#define EVENT_GCODE_AFTER_TOOLCHANGE "G12X" // Extra G-code to run after tool-change
#endif
+ /**
+ * Extra G-code to run while executing tool-change commands. Can be used to use an additional
+ * stepper motor (e.g., I axis in Configuration.h) to drive the tool-changer.
+ */
+ //#define EVENT_GCODE_TOOLCHANGE_T0 "G28 A\nG1 A0" // Extra G-code to run while executing tool-change command T0
+ //#define EVENT_GCODE_TOOLCHANGE_T1 "G1 A10" // Extra G-code to run while executing tool-change command T1
+ //#define EVENT_GCODE_TOOLCHANGE_ALWAYS_RUN // Always execute above G-code sequences. Use with caution!
+
+ /**
+ * Tool Sensors detect when tools have been picked up or dropped.
+ * Requires the pins TOOL_SENSOR1_PIN, TOOL_SENSOR2_PIN, etc.
+ */
+ //#define TOOL_SENSOR
+
/**
* Retract and prime filament on tool-change to reduce
* ooze and stringing and to get cleaner transitions.
@@ -2031,26 +2524,30 @@
#if ENABLED(TOOLCHANGE_FILAMENT_SWAP)
// Load / Unload
#define TOOLCHANGE_FS_LENGTH 12 // (mm) Load / Unload length
- #define TOOLCHANGE_FS_EXTRA_RESUME_LENGTH 0 // (mm) Extra length for better restart, fine tune by LCD/Gcode)
+ #define TOOLCHANGE_FS_EXTRA_RESUME_LENGTH 0 // (mm) Extra length for better restart. Adjust with LCD or M217 B.
#define TOOLCHANGE_FS_RETRACT_SPEED (50*60) // (mm/min) (Unloading)
#define TOOLCHANGE_FS_UNRETRACT_SPEED (25*60) // (mm/min) (On SINGLENOZZLE or Bowden loading must be slowed down)
// Longer prime to clean out a SINGLENOZZLE
#define TOOLCHANGE_FS_EXTRA_PRIME 0 // (mm) Extra priming length
#define TOOLCHANGE_FS_PRIME_SPEED (4.6*60) // (mm/min) Extra priming feedrate
- #define TOOLCHANGE_FS_WIPE_RETRACT 0 // (mm/min) Retract before cooling for less stringing, better wipe, etc.
+ #define TOOLCHANGE_FS_WIPE_RETRACT 0 // (mm) Retract before cooling for less stringing, better wipe, etc.
// Cool after prime to reduce stringing
#define TOOLCHANGE_FS_FAN -1 // Fan index or -1 to skip
#define TOOLCHANGE_FS_FAN_SPEED 255 // 0-255
#define TOOLCHANGE_FS_FAN_TIME 10 // (seconds)
- // Swap uninitialized extruder with TOOLCHANGE_FS_PRIME_SPEED for all lengths (recover + prime)
- // (May break filament if not retracted beforehand.)
- //#define TOOLCHANGE_FS_INIT_BEFORE_SWAP
+ // Use TOOLCHANGE_FS_PRIME_SPEED feedrate the first time each extruder is primed
+ //#define TOOLCHANGE_FS_SLOW_FIRST_PRIME
- // Prime on the first T0 (If other, TOOLCHANGE_FS_INIT_BEFORE_SWAP applied)
- // Enable it (M217 V[0/1]) before printing, to avoid unwanted priming on host connect
+ /**
+ * Prime T0 the first time T0 is sent to the printer:
+ * [ Power-On -> T0 { Activate & Prime T0 } -> T1 { Retract T0, Activate & Prime T1 } ]
+ * If disabled, no priming on T0 until switching back to T0 from another extruder:
+ * [ Power-On -> T0 { T0 Activated } -> T1 { Activate & Prime T1 } -> T0 { Retract T1, Activate & Prime T0 } ]
+ * Enable with M217 V1 before printing to avoid unwanted priming on host connect.
+ */
//#define TOOLCHANGE_FS_PRIME_FIRST_USED
/**
@@ -2080,15 +2577,18 @@
#endif
#endif // HAS_MULTI_EXTRUDER
+// @section advanced pause
+
/**
- * Advanced Pause
- * Experimental feature for filament change support and for parking the nozzle when paused.
- * Adds the GCode M600 for initiating filament change.
- * If PARK_HEAD_ON_PAUSE enabled, adds the GCode M125 to pause printing and park the nozzle.
+ * Advanced Pause for Filament Change
+ * - Adds the G-code M600 Filament Change to initiate a filament change.
+ * - This feature is required for the default FILAMENT_RUNOUT_SCRIPT.
+ *
+ * Requirements:
+ * - For Filament Change parking enable and configure NOZZLE_PARK_FEATURE.
+ * - For user interaction enable an LCD display, HOST_PROMPT_SUPPORT, or EMERGENCY_PARSER.
*
- * Requires an LCD display.
- * Requires NOZZLE_PARK_FEATURE.
- * This feature is required for the default FILAMENT_RUNOUT_SCRIPT.
+ * Enable PARK_HEAD_ON_PAUSE to add the G-code M125 Pause and Park.
*/
#define ADVANCED_PAUSE_FEATURE
#if ENABLED(ADVANCED_PAUSE_FEATURE)
@@ -2127,6 +2627,8 @@
#define PAUSE_PARK_NOZZLE_TIMEOUT 45 // (seconds) Time limit before the nozzle is turned off for safety.
#define FILAMENT_CHANGE_ALERT_BEEPS 10 // Number of alert beeps to play when a response is needed.
#define PAUSE_PARK_NO_STEPPER_TIMEOUT // Enable for XYZ steppers to stay powered on during filament change.
+ //#define FILAMENT_CHANGE_RESUME_ON_INSERT // Automatically continue / load filament when runout sensor is triggered again.
+ //#define PAUSE_REHEAT_FAST_RESUME // Reduce number of waits by not prompting again post-timeout before continuing.
//#define PARK_HEAD_ON_PAUSE // Park the nozzle during pause and filament change.
//#define HOME_BEFORE_FILAMENT_CHANGE // If needed, home before parking for filament change
@@ -2135,13 +2637,12 @@
//#define FILAMENT_UNLOAD_ALL_EXTRUDERS // Allow M702 to unload all extruders above a minimum target temp (as set by M302)
#endif
-// @section tmc
-
/**
* TMC26X Stepper Driver options
*
* The TMC26XStepper library is required for this stepper driver.
* https://github.com/trinamic/TMC26XStepper
+ * @section tmc/tmc26x
*/
#if HAS_DRIVER(TMC26X)
@@ -2154,7 +2655,7 @@
#if AXIS_DRIVER_TYPE_X2(TMC26X)
#define X2_MAX_CURRENT 1000
#define X2_SENSE_RESISTOR 91
- #define X2_MICROSTEPS 16
+ #define X2_MICROSTEPS X_MICROSTEPS
#endif
#if AXIS_DRIVER_TYPE_Y(TMC26X)
@@ -2166,7 +2667,7 @@
#if AXIS_DRIVER_TYPE_Y2(TMC26X)
#define Y2_MAX_CURRENT 1000
#define Y2_SENSE_RESISTOR 91
- #define Y2_MICROSTEPS 16
+ #define Y2_MICROSTEPS Y_MICROSTEPS
#endif
#if AXIS_DRIVER_TYPE_Z(TMC26X)
@@ -2178,19 +2679,55 @@
#if AXIS_DRIVER_TYPE_Z2(TMC26X)
#define Z2_MAX_CURRENT 1000
#define Z2_SENSE_RESISTOR 91
- #define Z2_MICROSTEPS 16
+ #define Z2_MICROSTEPS Z_MICROSTEPS
#endif
#if AXIS_DRIVER_TYPE_Z3(TMC26X)
#define Z3_MAX_CURRENT 1000
#define Z3_SENSE_RESISTOR 91
- #define Z3_MICROSTEPS 16
+ #define Z3_MICROSTEPS Z_MICROSTEPS
#endif
#if AXIS_DRIVER_TYPE_Z4(TMC26X)
#define Z4_MAX_CURRENT 1000
#define Z4_SENSE_RESISTOR 91
- #define Z4_MICROSTEPS 16
+ #define Z4_MICROSTEPS Z_MICROSTEPS
+ #endif
+
+ #if AXIS_DRIVER_TYPE_I(TMC26X)
+ #define I_MAX_CURRENT 1000
+ #define I_SENSE_RESISTOR 91
+ #define I_MICROSTEPS 16
+ #endif
+
+ #if AXIS_DRIVER_TYPE_J(TMC26X)
+ #define J_MAX_CURRENT 1000
+ #define J_SENSE_RESISTOR 91
+ #define J_MICROSTEPS 16
+ #endif
+
+ #if AXIS_DRIVER_TYPE_K(TMC26X)
+ #define K_MAX_CURRENT 1000
+ #define K_SENSE_RESISTOR 91
+ #define K_MICROSTEPS 16
+ #endif
+
+ #if AXIS_DRIVER_TYPE_U(TMC26X)
+ #define U_MAX_CURRENT 1000
+ #define U_SENSE_RESISTOR 91
+ #define U_MICROSTEPS 16
+ #endif
+
+ #if AXIS_DRIVER_TYPE_V(TMC26X)
+ #define V_MAX_CURRENT 1000
+ #define V_SENSE_RESISTOR 91
+ #define V_MICROSTEPS 16
+ #endif
+
+ #if AXIS_DRIVER_TYPE_W(TMC26X)
+ #define W_MAX_CURRENT 1000
+ #define W_SENSE_RESISTOR 91
+ #define W_MICROSTEPS 16
#endif
#if AXIS_DRIVER_TYPE_E0(TMC26X)
@@ -2202,49 +2739,47 @@
#if AXIS_DRIVER_TYPE_E1(TMC26X)
#define E1_MAX_CURRENT 1000
#define E1_SENSE_RESISTOR 91
- #define E1_MICROSTEPS 16
+ #define E1_MICROSTEPS E0_MICROSTEPS
#endif
#if AXIS_DRIVER_TYPE_E2(TMC26X)
#define E2_MAX_CURRENT 1000
#define E2_SENSE_RESISTOR 91
- #define E2_MICROSTEPS 16
+ #define E2_MICROSTEPS E0_MICROSTEPS
#endif
#if AXIS_DRIVER_TYPE_E3(TMC26X)
#define E3_MAX_CURRENT 1000
#define E3_SENSE_RESISTOR 91
- #define E3_MICROSTEPS 16
+ #define E3_MICROSTEPS E0_MICROSTEPS
#endif
#if AXIS_DRIVER_TYPE_E4(TMC26X)
#define E4_MAX_CURRENT 1000
#define E4_SENSE_RESISTOR 91
- #define E4_MICROSTEPS 16
+ #define E4_MICROSTEPS E0_MICROSTEPS
#endif
#if AXIS_DRIVER_TYPE_E5(TMC26X)
#define E5_MAX_CURRENT 1000
#define E5_SENSE_RESISTOR 91
- #define E5_MICROSTEPS 16
+ #define E5_MICROSTEPS E0_MICROSTEPS
#endif
#if AXIS_DRIVER_TYPE_E6(TMC26X)
#define E6_MAX_CURRENT 1000
#define E6_SENSE_RESISTOR 91
- #define E6_MICROSTEPS 16
+ #define E6_MICROSTEPS E0_MICROSTEPS
#endif
#if AXIS_DRIVER_TYPE_E7(TMC26X)
#define E7_MAX_CURRENT 1000
#define E7_SENSE_RESISTOR 91
- #define E7_MICROSTEPS 16
+ #define E7_MICROSTEPS E0_MICROSTEPS
#endif
#endif // TMC26X
-// @section tmc_smart
-
/**
* To use TMC2130, TMC2160, TMC2660, TMC5130, TMC5160 stepper drivers in SPI mode
* connect your SPI pins to the hardware SPI interface on your board and define
@@ -2260,6 +2795,7 @@
*
* TMCStepper library is required to use TMC stepper drivers.
* https://github.com/teemuatlut/TMCStepper
+ * @section tmc/config
*/
#if HAS_TRINAMIC_CONFIG
@@ -2278,15 +2814,17 @@
#define X_RSENSE 0.11
#define X_CHAIN_POS -1 // -1..0: Not chained. 1: MCU MOSI connected. 2: Next in chain, ...
//#define X_INTERPOLATE true // Enable to override 'INTERPOLATE' for the X axis
+ //#define X_HOLD_MULTIPLIER 0.5 // Enable to override 'HOLD_MULTIPLIER' for the X axis
#endif
#if AXIS_IS_TMC(X2)
#define X2_CURRENT 800
#define X2_CURRENT_HOME X2_CURRENT
- #define X2_MICROSTEPS 16
+ #define X2_MICROSTEPS X_MICROSTEPS
#define X2_RSENSE 0.11
#define X2_CHAIN_POS -1
//#define X2_INTERPOLATE true
+ //#define X2_HOLD_MULTIPLIER 0.5
#endif
#if AXIS_IS_TMC(Y)
@@ -2296,15 +2834,17 @@
#define Y_RSENSE 0.11
#define Y_CHAIN_POS -1
//#define Y_INTERPOLATE true
+ //#define Y_HOLD_MULTIPLIER 0.5
#endif
#if AXIS_IS_TMC(Y2)
#define Y2_CURRENT 600
#define Y2_CURRENT_HOME Y2_CURRENT
- #define Y2_MICROSTEPS 16
+ #define Y2_MICROSTEPS Y_MICROSTEPS
#define Y2_RSENSE 0.11
#define Y2_CHAIN_POS -1
//#define Y2_INTERPOLATE true
+ //#define Y2_HOLD_MULTIPLIER 0.5
#endif
#if AXIS_IS_TMC(Z)
@@ -2314,33 +2854,97 @@
#define Z_RSENSE 0.11
#define Z_CHAIN_POS -1
//#define Z_INTERPOLATE true
+ //#define Z_HOLD_MULTIPLIER 0.5
#endif
#if AXIS_IS_TMC(Z2)
#define Z2_CURRENT 800
#define Z2_CURRENT_HOME Z2_CURRENT
- #define Z2_MICROSTEPS 16
+ #define Z2_MICROSTEPS Z_MICROSTEPS
#define Z2_RSENSE 0.11
#define Z2_CHAIN_POS -1
//#define Z2_INTERPOLATE true
+ //#define Z2_HOLD_MULTIPLIER 0.5
#endif
#if AXIS_IS_TMC(Z3)
#define Z3_CURRENT 800
#define Z3_CURRENT_HOME Z3_CURRENT
- #define Z3_MICROSTEPS 16
+ #define Z3_MICROSTEPS Z_MICROSTEPS
#define Z3_RSENSE 0.11
#define Z3_CHAIN_POS -1
//#define Z3_INTERPOLATE true
+ //#define Z3_HOLD_MULTIPLIER 0.5
#endif
#if AXIS_IS_TMC(Z4)
#define Z4_CURRENT 800
#define Z4_CURRENT_HOME Z4_CURRENT
- #define Z4_MICROSTEPS 16
+ #define Z4_MICROSTEPS Z_MICROSTEPS
#define Z4_RSENSE 0.11
#define Z4_CHAIN_POS -1
//#define Z4_INTERPOLATE true
+ //#define Z4_HOLD_MULTIPLIER 0.5
+ #endif
+
+ #if AXIS_IS_TMC(I)
+ #define I_CURRENT 800
+ #define I_CURRENT_HOME I_CURRENT
+ #define I_MICROSTEPS 16
+ #define I_RSENSE 0.11
+ #define I_CHAIN_POS -1
+ //#define I_INTERPOLATE true
+ //#define I_HOLD_MULTIPLIER 0.5
+ #endif
+
+ #if AXIS_IS_TMC(J)
+ #define J_CURRENT 800
+ #define J_CURRENT_HOME J_CURRENT
+ #define J_MICROSTEPS 16
+ #define J_RSENSE 0.11
+ #define J_CHAIN_POS -1
+ //#define J_INTERPOLATE true
+ //#define J_HOLD_MULTIPLIER 0.5
+ #endif
+
+ #if AXIS_IS_TMC(K)
+ #define K_CURRENT 800
+ #define K_CURRENT_HOME K_CURRENT
+ #define K_MICROSTEPS 16
+ #define K_RSENSE 0.11
+ #define K_CHAIN_POS -1
+ //#define K_INTERPOLATE true
+ //#define K_HOLD_MULTIPLIER 0.5
+ #endif
+
+ #if AXIS_IS_TMC(U)
+ #define U_CURRENT 800
+ #define U_CURRENT_HOME U_CURRENT
+ #define U_MICROSTEPS 8
+ #define U_RSENSE 0.11
+ #define U_CHAIN_POS -1
+ //#define U_INTERPOLATE true
+ //#define U_HOLD_MULTIPLIER 0.5
+ #endif
+
+ #if AXIS_IS_TMC(V)
+ #define V_CURRENT 800
+ #define V_CURRENT_HOME V_CURRENT
+ #define V_MICROSTEPS 8
+ #define V_RSENSE 0.11
+ #define V_CHAIN_POS -1
+ //#define V_INTERPOLATE true
+ //#define V_HOLD_MULTIPLIER 0.5
+ #endif
+
+ #if AXIS_IS_TMC(W)
+ #define W_CURRENT 800
+ #define W_CURRENT_HOME W_CURRENT
+ #define W_MICROSTEPS 8
+ #define W_RSENSE 0.11
+ #define W_CHAIN_POS -1
+ //#define W_INTERPOLATE true
+ //#define W_HOLD_MULTIPLIER 0.5
#endif
#if AXIS_IS_TMC(E0)
@@ -2349,64 +2953,74 @@
#define E0_RSENSE 0.11
#define E0_CHAIN_POS -1
//#define E0_INTERPOLATE true
+ //#define E0_HOLD_MULTIPLIER 0.5
#endif
#if AXIS_IS_TMC(E1)
#define E1_CURRENT 800
- #define E1_MICROSTEPS 16
+ #define E1_MICROSTEPS E0_MICROSTEPS
#define E1_RSENSE 0.11
#define E1_CHAIN_POS -1
//#define E1_INTERPOLATE true
+ //#define E1_HOLD_MULTIPLIER 0.5
#endif
#if AXIS_IS_TMC(E2)
#define E2_CURRENT 800
- #define E2_MICROSTEPS 16
+ #define E2_MICROSTEPS E0_MICROSTEPS
#define E2_RSENSE 0.11
#define E2_CHAIN_POS -1
//#define E2_INTERPOLATE true
+ //#define E2_HOLD_MULTIPLIER 0.5
#endif
#if AXIS_IS_TMC(E3)
#define E3_CURRENT 800
- #define E3_MICROSTEPS 16
+ #define E3_MICROSTEPS E0_MICROSTEPS
#define E3_RSENSE 0.11
#define E3_CHAIN_POS -1
//#define E3_INTERPOLATE true
+ //#define E3_HOLD_MULTIPLIER 0.5
#endif
#if AXIS_IS_TMC(E4)
#define E4_CURRENT 800
- #define E4_MICROSTEPS 16
+ #define E4_MICROSTEPS E0_MICROSTEPS
#define E4_RSENSE 0.11
#define E4_CHAIN_POS -1
//#define E4_INTERPOLATE true
+ //#define E4_HOLD_MULTIPLIER 0.5
#endif
#if AXIS_IS_TMC(E5)
#define E5_CURRENT 800
- #define E5_MICROSTEPS 16
+ #define E5_MICROSTEPS E0_MICROSTEPS
#define E5_RSENSE 0.11
#define E5_CHAIN_POS -1
//#define E5_INTERPOLATE true
+ //#define E5_HOLD_MULTIPLIER 0.5
#endif
#if AXIS_IS_TMC(E6)
#define E6_CURRENT 800
- #define E6_MICROSTEPS 16
+ #define E6_MICROSTEPS E0_MICROSTEPS
#define E6_RSENSE 0.11
#define E6_CHAIN_POS -1
//#define E6_INTERPOLATE true
+ //#define E6_HOLD_MULTIPLIER 0.5
#endif
#if AXIS_IS_TMC(E7)
#define E7_CURRENT 800
- #define E7_MICROSTEPS 16
+ #define E7_MICROSTEPS E0_MICROSTEPS
#define E7_RSENSE 0.11
#define E7_CHAIN_POS -1
//#define E7_INTERPOLATE true
+ //#define E7_HOLD_MULTIPLIER 0.5
#endif
+ // @section tmc/spi
+
/**
* Override default SPI pins for TMC2130, TMC2160, TMC2660, TMC5130 and TMC5160 drivers here.
* The default pins can be found in your board's pins file.
@@ -2418,6 +3032,13 @@
//#define Y2_CS_PIN -1
//#define Z2_CS_PIN -1
//#define Z3_CS_PIN -1
+ //#define Z4_CS_PIN -1
+ //#define I_CS_PIN -1
+ //#define J_CS_PIN -1
+ //#define K_CS_PIN -1
+ //#define U_CS_PIN -1
+ //#define V_CS_PIN -1
+ //#define W_CS_PIN -1
//#define E0_CS_PIN -1
//#define E1_CS_PIN -1
//#define E2_CS_PIN -1
@@ -2437,6 +3058,8 @@
//#define TMC_SW_MISO -1
//#define TMC_SW_SCK -1
+ // @section tmc/serial
+
/**
* Four TMC2209 drivers can use the same HW/SW serial port with hardware configured addresses.
* Set the address using jumpers on pins MS1 and MS2.
@@ -2449,22 +3072,30 @@
* Set *_SERIAL_TX_PIN and *_SERIAL_RX_PIN to match for all drivers
* on the same serial port, either here or in your board's pins file.
*/
- #define X_SLAVE_ADDRESS 0
- #define Y_SLAVE_ADDRESS 0
- #define Z_SLAVE_ADDRESS 0
- #define X2_SLAVE_ADDRESS 0
- #define Y2_SLAVE_ADDRESS 0
- #define Z2_SLAVE_ADDRESS 0
- #define Z3_SLAVE_ADDRESS 0
- #define Z4_SLAVE_ADDRESS 0
- #define E0_SLAVE_ADDRESS 0
- #define E1_SLAVE_ADDRESS 0
- #define E2_SLAVE_ADDRESS 0
- #define E3_SLAVE_ADDRESS 0
- #define E4_SLAVE_ADDRESS 0
- #define E5_SLAVE_ADDRESS 0
- #define E6_SLAVE_ADDRESS 0
- #define E7_SLAVE_ADDRESS 0
+ //#define X_SLAVE_ADDRESS 0
+ //#define Y_SLAVE_ADDRESS 0
+ //#define Z_SLAVE_ADDRESS 0
+ //#define X2_SLAVE_ADDRESS 0
+ //#define Y2_SLAVE_ADDRESS 0
+ //#define Z2_SLAVE_ADDRESS 0
+ //#define Z3_SLAVE_ADDRESS 0
+ //#define Z4_SLAVE_ADDRESS 0
+ //#define I_SLAVE_ADDRESS 0
+ //#define J_SLAVE_ADDRESS 0
+ //#define K_SLAVE_ADDRESS 0
+ //#define U_SLAVE_ADDRESS 0
+ //#define V_SLAVE_ADDRESS 0
+ //#define W_SLAVE_ADDRESS 0
+ //#define E0_SLAVE_ADDRESS 0
+ //#define E1_SLAVE_ADDRESS 0
+ //#define E2_SLAVE_ADDRESS 0
+ //#define E3_SLAVE_ADDRESS 0
+ //#define E4_SLAVE_ADDRESS 0
+ //#define E5_SLAVE_ADDRESS 0
+ //#define E6_SLAVE_ADDRESS 0
+ //#define E7_SLAVE_ADDRESS 0
+
+ // @section tmc/smart
/**
* Software enable
@@ -2474,6 +3105,8 @@
*/
//#define SOFTWARE_DRIVER_ENABLE
+ // @section tmc/stealthchop
+
/**
* TMC2130, TMC2160, TMC2208, TMC2209, TMC5130 and TMC5160 only
* Use Trinamic's ultra quiet stepping mode.
@@ -2481,6 +3114,12 @@
*/
#define STEALTHCHOP_XY
#define STEALTHCHOP_Z
+ #define STEALTHCHOP_I
+ #define STEALTHCHOP_J
+ #define STEALTHCHOP_K
+ #define STEALTHCHOP_U
+ #define STEALTHCHOP_V
+ #define STEALTHCHOP_W
#define STEALTHCHOP_E
/**
@@ -2499,22 +3138,30 @@
* { , , hysteresis_start[1..8] }
*/
#define CHOPPER_TIMING CHOPPER_DEFAULT_24V // All axes (override below)
- //#define CHOPPER_TIMING_X CHOPPER_DEFAULT_12V // For X Axes (override below)
- //#define CHOPPER_TIMING_X2 CHOPPER_DEFAULT_12V
- //#define CHOPPER_TIMING_Y CHOPPER_DEFAULT_12V // For Y Axes (override below)
- //#define CHOPPER_TIMING_Y2 CHOPPER_DEFAULT_12V
- //#define CHOPPER_TIMING_Z CHOPPER_DEFAULT_12V // For Z Axes (override below)
- //#define CHOPPER_TIMING_Z2 CHOPPER_DEFAULT_12V
- //#define CHOPPER_TIMING_Z3 CHOPPER_DEFAULT_12V
- //#define CHOPPER_TIMING_Z4 CHOPPER_DEFAULT_12V
- //#define CHOPPER_TIMING_E CHOPPER_DEFAULT_12V // For Extruders (override below)
- //#define CHOPPER_TIMING_E1 CHOPPER_DEFAULT_12V
- //#define CHOPPER_TIMING_E2 CHOPPER_DEFAULT_12V
- //#define CHOPPER_TIMING_E3 CHOPPER_DEFAULT_12V
- //#define CHOPPER_TIMING_E4 CHOPPER_DEFAULT_12V
- //#define CHOPPER_TIMING_E5 CHOPPER_DEFAULT_12V
- //#define CHOPPER_TIMING_E6 CHOPPER_DEFAULT_12V
- //#define CHOPPER_TIMING_E7 CHOPPER_DEFAULT_12V
+ //#define CHOPPER_TIMING_X CHOPPER_TIMING // For X Axes (override below)
+ //#define CHOPPER_TIMING_X2 CHOPPER_TIMING_X
+ //#define CHOPPER_TIMING_Y CHOPPER_TIMING // For Y Axes (override below)
+ //#define CHOPPER_TIMING_Y2 CHOPPER_TIMING_Y
+ //#define CHOPPER_TIMING_Z CHOPPER_TIMING // For Z Axes (override below)
+ //#define CHOPPER_TIMING_Z2 CHOPPER_TIMING_Z
+ //#define CHOPPER_TIMING_Z3 CHOPPER_TIMING_Z
+ //#define CHOPPER_TIMING_Z4 CHOPPER_TIMING_Z
+ //#define CHOPPER_TIMING_I CHOPPER_TIMING // For I Axis
+ //#define CHOPPER_TIMING_J CHOPPER_TIMING // For J Axis
+ //#define CHOPPER_TIMING_K CHOPPER_TIMING // For K Axis
+ //#define CHOPPER_TIMING_U CHOPPER_TIMING // For U Axis
+ //#define CHOPPER_TIMING_V CHOPPER_TIMING // For V Axis
+ //#define CHOPPER_TIMING_W CHOPPER_TIMING // For W Axis
+ //#define CHOPPER_TIMING_E CHOPPER_TIMING // For Extruders (override below)
+ //#define CHOPPER_TIMING_E1 CHOPPER_TIMING_E
+ //#define CHOPPER_TIMING_E2 CHOPPER_TIMING_E
+ //#define CHOPPER_TIMING_E3 CHOPPER_TIMING_E
+ //#define CHOPPER_TIMING_E4 CHOPPER_TIMING_E
+ //#define CHOPPER_TIMING_E5 CHOPPER_TIMING_E
+ //#define CHOPPER_TIMING_E6 CHOPPER_TIMING_E
+ //#define CHOPPER_TIMING_E7 CHOPPER_TIMING_E
+
+ // @section tmc/status
/**
* Monitor Trinamic drivers
@@ -2535,6 +3182,8 @@
#define STOP_ON_ERROR
#endif
+ // @section tmc/hybrid
+
/**
* TMC2130, TMC2160, TMC2208, TMC2209, TMC5130 and TMC5160 only
* The driver will switch to spreadCycle when stepper speed is over HYBRID_THRESHOLD.
@@ -2552,6 +3201,12 @@
#define Z2_HYBRID_THRESHOLD 3
#define Z3_HYBRID_THRESHOLD 3
#define Z4_HYBRID_THRESHOLD 3
+ #define I_HYBRID_THRESHOLD 3 // [linear=mm/s, rotational=°/s]
+ #define J_HYBRID_THRESHOLD 3 // [linear=mm/s, rotational=°/s]
+ #define K_HYBRID_THRESHOLD 3 // [linear=mm/s, rotational=°/s]
+ #define U_HYBRID_THRESHOLD 3 // [mm/s]
+ #define V_HYBRID_THRESHOLD 3
+ #define W_HYBRID_THRESHOLD 3
#define E0_HYBRID_THRESHOLD 30
#define E1_HYBRID_THRESHOLD 30
#define E2_HYBRID_THRESHOLD 30
@@ -2577,7 +3232,7 @@
*
* It is recommended to set HOMING_BUMP_MM to { 0, 0, 0 }.
*
- * SPI_ENDSTOPS *** Beta feature! *** TMC2130 Only ***
+ * SPI_ENDSTOPS *** Beta feature! *** TMC2130/TMC5160 Only ***
* Poll the driver through SPI to determine load when homing.
* Removes the need for a wire from DIAG1 to an endstop pin.
*
@@ -2585,6 +3240,7 @@
* homing and adds a guard period for endstop triggering.
*
* Comment *_STALL_SENSITIVITY to disable sensorless homing for that axis.
+ * @section tmc/stallguard
*/
#define SENSORLESS_HOMING // StallGuard capable drivers only
@@ -2598,10 +3254,18 @@
//#define Z2_STALL_SENSITIVITY Z_STALL_SENSITIVITY
//#define Z3_STALL_SENSITIVITY Z_STALL_SENSITIVITY
//#define Z4_STALL_SENSITIVITY Z_STALL_SENSITIVITY
+ //#define I_STALL_SENSITIVITY 8
+ //#define J_STALL_SENSITIVITY 8
+ //#define K_STALL_SENSITIVITY 8
+ //#define U_STALL_SENSITIVITY 8
+ //#define V_STALL_SENSITIVITY 8
+ //#define W_STALL_SENSITIVITY 8
#define SPI_ENDSTOPS // TMC2130 only
#define IMPROVE_HOMING_RELIABILITY
#endif
+ // @section tmc/config
+
/**
* TMC Homing stepper phase.
*
@@ -2622,7 +3286,7 @@
/**
* Enable M122 debugging command for TMC stepper drivers.
- * M122 S0/1 will enable continous reporting.
+ * M122 S0/1 will enable continuous reporting.
*/
#define TMC_DEBUG
@@ -2641,200 +3305,6 @@
#endif // HAS_TRINAMIC_CONFIG
-// @section L64XX
-
-/**
- * L64XX Stepper Driver options
- *
- * Arduino-L6470 library (0.8.0 or higher) is required.
- * https://github.com/ameyer/Arduino-L6470
- *
- * Requires the following to be defined in your pins_YOUR_BOARD file
- * L6470_CHAIN_SCK_PIN
- * L6470_CHAIN_MISO_PIN
- * L6470_CHAIN_MOSI_PIN
- * L6470_CHAIN_SS_PIN
- * ENABLE_RESET_L64XX_CHIPS(Q) where Q is 1 to enable and 0 to reset
- */
-
-#if HAS_L64XX
-
- //#define L6470_CHITCHAT // Display additional status info
-
- #if AXIS_IS_L64XX(X)
- #define X_MICROSTEPS 128 // Number of microsteps (VALID: 1, 2, 4, 8, 16, 32, 128) - L6474 max is 16
- #define X_OVERCURRENT 2000 // (mA) Current where the driver detects an over current
- // L6470 & L6474 - VALID: 375 x (1 - 16) - 6A max - rounds down
- // POWERSTEP01: VALID: 1000 x (1 - 32) - 32A max - rounds down
- #define X_STALLCURRENT 1500 // (mA) Current where the driver detects a stall (VALID: 31.25 * (1-128) - 4A max - rounds down)
- // L6470 & L6474 - VALID: 31.25 * (1-128) - 4A max - rounds down
- // POWERSTEP01: VALID: 200 x (1 - 32) - 6.4A max - rounds down
- // L6474 - STALLCURRENT setting is used to set the nominal (TVAL) current
- #define X_MAX_VOLTAGE 127 // 0-255, Maximum effective voltage seen by stepper - not used by L6474
- #define X_CHAIN_POS -1 // Position in SPI chain, 0=Not in chain, 1=Nearest MOSI
- #define X_SLEW_RATE 1 // 0-3, Slew 0 is slowest, 3 is fastest
- #endif
-
- #if AXIS_IS_L64XX(X2)
- #define X2_MICROSTEPS 128
- #define X2_OVERCURRENT 2000
- #define X2_STALLCURRENT 1500
- #define X2_MAX_VOLTAGE 127
- #define X2_CHAIN_POS -1
- #define X2_SLEW_RATE 1
- #endif
-
- #if AXIS_IS_L64XX(Y)
- #define Y_MICROSTEPS 128
- #define Y_OVERCURRENT 2000
- #define Y_STALLCURRENT 1500
- #define Y_MAX_VOLTAGE 127
- #define Y_CHAIN_POS -1
- #define Y_SLEW_RATE 1
- #endif
-
- #if AXIS_IS_L64XX(Y2)
- #define Y2_MICROSTEPS 128
- #define Y2_OVERCURRENT 2000
- #define Y2_STALLCURRENT 1500
- #define Y2_MAX_VOLTAGE 127
- #define Y2_CHAIN_POS -1
- #define Y2_SLEW_RATE 1
- #endif
-
- #if AXIS_IS_L64XX(Z)
- #define Z_MICROSTEPS 128
- #define Z_OVERCURRENT 2000
- #define Z_STALLCURRENT 1500
- #define Z_MAX_VOLTAGE 127
- #define Z_CHAIN_POS -1
- #define Z_SLEW_RATE 1
- #endif
-
- #if AXIS_IS_L64XX(Z2)
- #define Z2_MICROSTEPS 128
- #define Z2_OVERCURRENT 2000
- #define Z2_STALLCURRENT 1500
- #define Z2_MAX_VOLTAGE 127
- #define Z2_CHAIN_POS -1
- #define Z2_SLEW_RATE 1
- #endif
-
- #if AXIS_IS_L64XX(Z3)
- #define Z3_MICROSTEPS 128
- #define Z3_OVERCURRENT 2000
- #define Z3_STALLCURRENT 1500
- #define Z3_MAX_VOLTAGE 127
- #define Z3_CHAIN_POS -1
- #define Z3_SLEW_RATE 1
- #endif
-
- #if AXIS_IS_L64XX(Z4)
- #define Z4_MICROSTEPS 128
- #define Z4_OVERCURRENT 2000
- #define Z4_STALLCURRENT 1500
- #define Z4_MAX_VOLTAGE 127
- #define Z4_CHAIN_POS -1
- #define Z4_SLEW_RATE 1
- #endif
-
- #if AXIS_IS_L64XX(E0)
- #define E0_MICROSTEPS 128
- #define E0_OVERCURRENT 2000
- #define E0_STALLCURRENT 1500
- #define E0_MAX_VOLTAGE 127
- #define E0_CHAIN_POS -1
- #define E0_SLEW_RATE 1
- #endif
-
- #if AXIS_IS_L64XX(E1)
- #define E1_MICROSTEPS 128
- #define E1_OVERCURRENT 2000
- #define E1_STALLCURRENT 1500
- #define E1_MAX_VOLTAGE 127
- #define E1_CHAIN_POS -1
- #define E1_SLEW_RATE 1
- #endif
-
- #if AXIS_IS_L64XX(E2)
- #define E2_MICROSTEPS 128
- #define E2_OVERCURRENT 2000
- #define E2_STALLCURRENT 1500
- #define E2_MAX_VOLTAGE 127
- #define E2_CHAIN_POS -1
- #define E2_SLEW_RATE 1
- #endif
-
- #if AXIS_IS_L64XX(E3)
- #define E3_MICROSTEPS 128
- #define E3_OVERCURRENT 2000
- #define E3_STALLCURRENT 1500
- #define E3_MAX_VOLTAGE 127
- #define E3_CHAIN_POS -1
- #define E3_SLEW_RATE 1
- #endif
-
- #if AXIS_IS_L64XX(E4)
- #define E4_MICROSTEPS 128
- #define E4_OVERCURRENT 2000
- #define E4_STALLCURRENT 1500
- #define E4_MAX_VOLTAGE 127
- #define E4_CHAIN_POS -1
- #define E4_SLEW_RATE 1
- #endif
-
- #if AXIS_IS_L64XX(E5)
- #define E5_MICROSTEPS 128
- #define E5_OVERCURRENT 2000
- #define E5_STALLCURRENT 1500
- #define E5_MAX_VOLTAGE 127
- #define E5_CHAIN_POS -1
- #define E5_SLEW_RATE 1
- #endif
-
- #if AXIS_IS_L64XX(E6)
- #define E6_MICROSTEPS 128
- #define E6_OVERCURRENT 2000
- #define E6_STALLCURRENT 1500
- #define E6_MAX_VOLTAGE 127
- #define E6_CHAIN_POS -1
- #define E6_SLEW_RATE 1
- #endif
-
- #if AXIS_IS_L64XX(E7)
- #define E7_MICROSTEPS 128
- #define E7_OVERCURRENT 2000
- #define E7_STALLCURRENT 1500
- #define E7_MAX_VOLTAGE 127
- #define E7_CHAIN_POS -1
- #define E7_SLEW_RATE 1
- #endif
-
- /**
- * Monitor L6470 drivers for error conditions like over temperature and over current.
- * In the case of over temperature Marlin can decrease the drive until the error condition clears.
- * Other detected conditions can be used to stop the current print.
- * Relevant G-codes:
- * M906 - I1/2/3/4/5 Set or get motor drive level using axis codes X, Y, Z, E. Report values if no axis codes given.
- * I not present or I0 or I1 - X, Y, Z or E0
- * I2 - X2, Y2, Z2 or E1
- * I3 - Z3 or E3
- * I4 - Z4 or E4
- * I5 - E5
- * M916 - Increase drive level until get thermal warning
- * M917 - Find minimum current thresholds
- * M918 - Increase speed until max or error
- * M122 S0/1 - Report driver parameters
- */
- //#define MONITOR_L6470_DRIVER_STATUS
-
- #if ENABLED(MONITOR_L6470_DRIVER_STATUS)
- #define KVAL_HOLD_STEP_DOWN 1
- //#define L6470_STOP_ON_ERROR
- #endif
-
-#endif // HAS_L64XX
-
// @section i2cbus
//
@@ -2876,7 +3346,7 @@
#define I2C_SLAVE_ADDRESS 0 // Set a value from 8 to 127 to act as a slave
#endif
-// @section extras
+// @section photo
/**
* Photo G-code
@@ -2919,6 +3389,8 @@
#endif
#endif
+// @section cnc
+
/**
* Spindle & Laser control
*
@@ -2932,22 +3404,46 @@
* You'll need to select a pin for the ON/OFF function and optionally choose a 0-5V
* hardware PWM pin for the speed control and a pin for the rotation direction.
*
- * See https://marlinfw.org/docs/configuration/laser_spindle.html for more config details.
+ * See https://marlinfw.org/docs/configuration/2.0.9/laser_spindle.html for more config details.
*/
//#define SPINDLE_FEATURE
//#define LASER_FEATURE
#if EITHER(SPINDLE_FEATURE, LASER_FEATURE)
- #define SPINDLE_LASER_ACTIVE_STATE LOW // Set to "HIGH" if the on/off function is active HIGH
- #define SPINDLE_LASER_PWM true // Set to "true" if your controller supports setting the speed/power
- #define SPINDLE_LASER_PWM_INVERT false // Set to "true" if the speed/power goes up when you want it to go slower
+ #define SPINDLE_LASER_ACTIVE_STATE LOW // Set to "HIGH" if SPINDLE_LASER_ENA_PIN is active HIGH
+
+ #define SPINDLE_LASER_USE_PWM // Enable if your controller supports setting the speed/power
+ #if ENABLED(SPINDLE_LASER_USE_PWM)
+ #define SPINDLE_LASER_PWM_INVERT false // Set to "true" if the speed/power goes up when you want it to go slower
+ #define SPINDLE_LASER_FREQUENCY 2500 // (Hz) Spindle/laser frequency (only on supported HALs: AVR, ESP32, and LPC)
+ // ESP32: If SPINDLE_LASER_PWM_PIN is onboard then <=78125Hz. For I2S expander
+ // the frequency determines the PWM resolution. 2500Hz = 0-100, 977Hz = 0-255, ...
+ // (250000 / SPINDLE_LASER_FREQUENCY) = max value.
+ #endif
+
+ //#define AIR_EVACUATION // Cutter Vacuum / Laser Blower motor control with G-codes M10-M11
+ #if ENABLED(AIR_EVACUATION)
+ #define AIR_EVACUATION_ACTIVE LOW // Set to "HIGH" if the on/off function is active HIGH
+ //#define AIR_EVACUATION_PIN 42 // Override the default Cutter Vacuum or Laser Blower pin
+ #endif
+
+ //#define AIR_ASSIST // Air Assist control with G-codes M8-M9
+ #if ENABLED(AIR_ASSIST)
+ #define AIR_ASSIST_ACTIVE LOW // Active state on air assist pin
+ //#define AIR_ASSIST_PIN 44 // Override the default Air Assist pin
+ #endif
- #define SPINDLE_LASER_FREQUENCY 2500 // (Hz) Spindle/laser frequency (only on supported HALs: AVR and LPC)
+ //#define SPINDLE_SERVO // A servo converting an angle to spindle power
+ #ifdef SPINDLE_SERVO
+ #define SPINDLE_SERVO_NR 0 // Index of servo used for spindle control
+ #define SPINDLE_SERVO_MIN 10 // Minimum angle for servo spindle
+ #endif
/**
* Speed / Power can be set ('M3 S') and displayed in terms of:
* - PWM255 (S0 - S255)
* - PERCENT (S0 - S100)
* - RPM (S0 - S50000) Best for use with a spindle
+ * - SERVO (S0 - S180)
*/
#define CUTTER_POWER_UNIT PWM255
@@ -2978,94 +3474,110 @@
* Speed/Power = (PWMDC / 255 * 100 - SPEED_POWER_INTERCEPT) / SPEED_POWER_SLOPE
* PWMDC = (spdpwr - SPEED_POWER_MIN) / (SPEED_POWER_MAX - SPEED_POWER_MIN) / SPEED_POWER_SLOPE
*/
- #define SPEED_POWER_INTERCEPT 0 // (%) 0-100 i.e., Minimum power percentage
- #define SPEED_POWER_MIN 5000 // (RPM)
- #define SPEED_POWER_MAX 30000 // (RPM) SuperPID router controller 0 - 30,000 RPM
- #define SPEED_POWER_STARTUP 25000 // (RPM) M3/M4 speed/power default (with no arguments)
+ #if ENABLED(SPINDLE_LASER_USE_PWM)
+ #define SPEED_POWER_INTERCEPT 0 // (%) 0-100 i.e., Minimum power percentage
+ #define SPEED_POWER_MIN 5000 // (RPM)
+ #define SPEED_POWER_MAX 30000 // (RPM) SuperPID router controller 0 - 30,000 RPM
+ #define SPEED_POWER_STARTUP 25000 // (RPM) M3/M4 speed/power default (with no arguments)
+ #endif
#else
- #define SPEED_POWER_INTERCEPT 0 // (%) 0-100 i.e., Minimum power percentage
- #define SPEED_POWER_MIN 0 // (%) 0-100
- #define SPEED_POWER_MAX 100 // (%) 0-100
- #define SPEED_POWER_STARTUP 80 // (%) M3/M4 speed/power default (with no arguments)
+ #if ENABLED(SPINDLE_LASER_USE_PWM)
+ #define SPEED_POWER_INTERCEPT 0 // (%) 0-100 i.e., Minimum power percentage
+ #define SPEED_POWER_MIN 0 // (%) 0-100
+ #define SPEED_POWER_MAX 100 // (%) 0-100
+ #define SPEED_POWER_STARTUP 80 // (%) M3/M4 speed/power default (with no arguments)
+ #endif
- /**
- * Enable inline laser power to be handled in the planner / stepper routines.
- * Inline power is specified by the I (inline) flag in an M3 command (e.g., M3 S20 I)
- * or by the 'S' parameter in G0/G1/G2/G3 moves (see LASER_MOVE_POWER).
- *
- * This allows the laser to keep in perfect sync with the planner and removes
- * the powerup/down delay since lasers require negligible time.
- */
- //#define LASER_POWER_INLINE
+ // Define the minimum and maximum test pulse time values for a laser test fire function
+ #define LASER_TEST_PULSE_MIN 1 // (ms) Used with Laser Control Menu
+ #define LASER_TEST_PULSE_MAX 999 // (ms) Caution: Menu may not show more than 3 characters
- #if ENABLED(LASER_POWER_INLINE)
- /**
- * Scale the laser's power in proportion to the movement rate.
- *
- * - Sets the entry power proportional to the entry speed over the nominal speed.
- * - Ramps the power up every N steps to approximate the speed trapezoid.
- * - Due to the limited power resolution this is only approximate.
- */
- #define LASER_POWER_INLINE_TRAPEZOID
+ #define SPINDLE_LASER_POWERUP_DELAY 50 // (ms) Delay to allow the spindle/laser to come up to speed/power
+ #define SPINDLE_LASER_POWERDOWN_DELAY 50 // (ms) Delay to allow the spindle to stop
- /**
- * Continuously calculate the current power (nominal_power * current_rate / nominal_rate).
- * Required for accurate power with non-trapezoidal acceleration (e.g., S_CURVE_ACCELERATION).
- * This is a costly calculation so this option is discouraged on 8-bit AVR boards.
- *
- * LASER_POWER_INLINE_TRAPEZOID_CONT_PER defines how many step cycles there are between power updates. If your
- * board isn't able to generate steps fast enough (and you are using LASER_POWER_INLINE_TRAPEZOID_CONT), increase this.
- * Note that when this is zero it means it occurs every cycle; 1 means a delay wait one cycle then run, etc.
- */
- //#define LASER_POWER_INLINE_TRAPEZOID_CONT
+ /**
+ * Laser Safety Timeout
+ *
+ * The laser should be turned off when there is no movement for a period of time.
+ * Consider material flammability, cut rate, and G-code order when setting this
+ * value. Too low and it could turn off during a very slow move; too high and
+ * the material could ignite.
+ */
+ #define LASER_SAFETY_TIMEOUT_MS 1000 // (ms)
- /**
- * Stepper iterations between power updates. Increase this value if the board
- * can't keep up with the processing demands of LASER_POWER_INLINE_TRAPEZOID_CONT.
- * Disable (or set to 0) to recalculate power on every stepper iteration.
- */
- //#define LASER_POWER_INLINE_TRAPEZOID_CONT_PER 10
+ /**
+ * Any M3 or G1/2/3/5 command with the 'I' parameter enables continuous inline power mode.
+ *
+ * e.g., 'M3 I' enables continuous inline power which is processed by the planner.
+ * Power is stored in move blocks and applied when blocks are processed by the Stepper ISR.
+ *
+ * 'M4 I' sets dynamic mode which uses the current feedrate to calculate a laser power OCR value.
+ *
+ * Any move in dynamic mode will use the current feedrate to calculate the laser power.
+ * Feed rates are set by the F parameter of a move command e.g. G1 X0 Y10 F6000
+ * Laser power would be calculated by bit shifting off 8 LSB's. In binary this is div 256.
+ * The calculation gives us ocr values from 0 to 255, values over F65535 will be set as 255 .
+ * More refined power control such as compesation for accell/decell will be addressed in future releases.
+ *
+ * M5 I clears inline mode and set power to 0, M5 sets the power output to 0 but leaves inline mode on.
+ */
- /**
- * Include laser power in G0/G1/G2/G3/G5 commands with the 'S' parameter
- */
- //#define LASER_MOVE_POWER
+ /**
+ * Enable M3 commands for laser mode inline power planner syncing.
+ * This feature enables any M3 S-value to be injected into the block buffers while in
+ * CUTTER_MODE_CONTINUOUS. The option allows M3 laser power to be commited without waiting
+ * for a planner syncronization
+ */
+ //#define LASER_POWER_SYNC
- #if ENABLED(LASER_MOVE_POWER)
- // Turn off the laser on G0 moves with no power parameter.
- // If a power parameter is provided, use that instead.
- //#define LASER_MOVE_G0_OFF
+ /**
+ * Scale the laser's power in proportion to the movement rate.
+ *
+ * - Sets the entry power proportional to the entry speed over the nominal speed.
+ * - Ramps the power up every N steps to approximate the speed trapezoid.
+ * - Due to the limited power resolution this is only approximate.
+ */
+ //#define LASER_POWER_TRAP
+
+ //
+ // Laser I2C Ammeter (High precision INA226 low/high side module)
+ //
+ //#define I2C_AMMETER
+ #if ENABLED(I2C_AMMETER)
+ #define I2C_AMMETER_IMAX 0.1 // (Amps) Calibration value for the expected current range
+ #define I2C_AMMETER_SHUNT_RESISTOR 0.1 // (Ohms) Calibration shunt resistor value
+ #endif
- // Turn off the laser on G28 homing.
- //#define LASER_MOVE_G28_OFF
+ //
+ // Laser Coolant Flow Meter
+ //
+ //#define LASER_COOLANT_FLOW_METER
+ #if ENABLED(LASER_COOLANT_FLOW_METER)
+ #define FLOWMETER_PIN 20 // Requires an external interrupt-enabled pin (e.g., RAMPS 2,3,18,19,20,21)
+ #define FLOWMETER_PPL 5880 // (pulses/liter) Flow meter pulses-per-liter on the input pin
+ #define FLOWMETER_INTERVAL 1000 // (ms) Flow rate calculation interval in milliseconds
+ #define FLOWMETER_SAFETY // Prevent running the laser without the minimum flow rate set below
+ #if ENABLED(FLOWMETER_SAFETY)
+ #define FLOWMETER_MIN_LITERS_PER_MINUTE 1.5 // (liters/min) Minimum flow required when enabled
#endif
-
- /**
- * Inline flag inverted
- *
- * WARNING: M5 will NOT turn off the laser unless another move
- * is done (so G-code files must end with 'M5 I').
- */
- //#define LASER_POWER_INLINE_INVERT
-
- /**
- * Continuously apply inline power. ('M3 S3' == 'G1 S3' == 'M3 S3 I')
- *
- * The laser might do some weird things, so only enable this
- * feature if you understand the implications.
- */
- //#define LASER_POWER_INLINE_CONTINUOUS
-
- #else
-
- #define SPINDLE_LASER_POWERUP_DELAY 50 // (ms) Delay to allow the spindle/laser to come up to speed/power
- #define SPINDLE_LASER_POWERDOWN_DELAY 50 // (ms) Delay to allow the spindle to stop
-
#endif
+
#endif
-#endif
+#endif // SPINDLE_FEATURE || LASER_FEATURE
+
+/**
+ * Synchronous Laser Control with M106/M107
+ *
+ * Marlin normally applies M106/M107 fan speeds at a time "soon after" processing
+ * a planner block. This is too inaccurate for a PWM/TTL laser attached to the fan
+ * header (as with some add-on laser kits). Enable this option to set fan/laser
+ * speeds with much more exact timing for improved print fidelity.
+ *
+ * NOTE: This option sacrifices some cooling fan speed options.
+ */
+//#define LASER_SYNCHRONOUS_M106_M107
/**
* Coolant Control
@@ -3082,6 +3594,8 @@
#define COOLANT_FLOOD_INVERT false // Set "true" if the on/off function is reversed
#endif
+// @section filament width
+
/**
* Filament Width Sensor
*
@@ -3115,6 +3629,8 @@
//#define FILAMENT_LCD_DISPLAY
#endif
+// @section power
+
/**
* Power Monitor
* Monitor voltage (V) and/or current (A), and -when possible- power (W)
@@ -3126,13 +3642,31 @@
*/
//#define POWER_MONITOR_CURRENT // Monitor the system current
//#define POWER_MONITOR_VOLTAGE // Monitor the system voltage
-#if EITHER(POWER_MONITOR_CURRENT, POWER_MONITOR_VOLTAGE)
- #define POWER_MONITOR_VOLTS_PER_AMP 0.05000 // Input voltage to the MCU analog pin per amp - DO NOT apply more than ADC_VREF!
- #define POWER_MONITOR_CURRENT_OFFSET -1 // Offset value for current sensors with linear function output
- #define POWER_MONITOR_VOLTS_PER_VOLT 0.11786 // Input voltage to the MCU analog pin per volt - DO NOT apply more than ADC_VREF!
+
+#if ENABLED(POWER_MONITOR_CURRENT)
+ #define POWER_MONITOR_VOLTS_PER_AMP 0.05000 // Input voltage to the MCU analog pin per amp - DO NOT apply more than ADC_VREF!
+ #define POWER_MONITOR_CURRENT_OFFSET 0 // Offset (in amps) applied to the calculated current
#define POWER_MONITOR_FIXED_VOLTAGE 13.6 // Voltage for a current sensor with no voltage sensor (for power display)
#endif
+#if ENABLED(POWER_MONITOR_VOLTAGE)
+ #define POWER_MONITOR_VOLTS_PER_VOLT 0.077933 // Input voltage to the MCU analog pin per volt - DO NOT apply more than ADC_VREF!
+ #define POWER_MONITOR_VOLTAGE_OFFSET 0 // Offset (in volts) applied to the calculated voltage
+#endif
+
+// @section safety
+
+/**
+ * Stepper Driver Anti-SNAFU Protection
+ *
+ * If the SAFE_POWER_PIN is defined for your board, Marlin will check
+ * that stepper drivers are properly plugged in before applying power.
+ * Disable protection if your stepper drivers don't support the feature.
+ */
+//#define DISABLE_DRIVER_SAFE_POWER_PROTECT
+
+// @section cnc
+
/**
* CNC Coordinate Systems
*
@@ -3141,10 +3675,26 @@
*/
//#define CNC_COORDINATE_SYSTEMS
+// @section reporting
+
+/**
+ * Auto-report fan speed with M123 S
+ * Requires fans with tachometer pins
+ */
+//#define AUTO_REPORT_FANS
+
/**
* Auto-report temperatures with M155 S
*/
#define AUTO_REPORT_TEMPERATURES
+#if ENABLED(AUTO_REPORT_TEMPERATURES) && TEMP_SENSOR_REDUNDANT
+ //#define AUTO_REPORT_REDUNDANT // Include the "R" sensor in the auto-report
+#endif
+
+/**
+ * Auto-report position with M154 S
+ */
+//#define AUTO_REPORT_POSITION
/**
* Include capabilities in M115 output
@@ -3154,6 +3704,8 @@
//#define M115_GEOMETRY_REPORT
#endif
+// @section security
+
/**
* Expected Printer Check
* Add the M16 G-code to compare a string to the MACHINE_NAME.
@@ -3161,6 +3713,8 @@
*/
//#define EXPECTED_PRINTER_CHECK
+// @section volumetrics
+
/**
* Disable all Volumetric extrusion options
*/
@@ -3189,14 +3743,7 @@
#endif
#endif
-/**
- * Enable this option for a leaner build of Marlin that removes all
- * workspace offsets, simplifying coordinate transformations, leveling, etc.
- *
- * - M206 and M428 are disabled.
- * - G92 will revert to its behavior from Marlin 1.0.
- */
-//#define NO_WORKSPACE_OFFSETS
+// @section reporting
// Extra options for the M114 "Current Position" report
//#define M114_DETAIL // Use 'M114` for details to check planner calculations
@@ -3205,17 +3752,10 @@
//#define REPORT_FAN_CHANGE // Report the new fan speed when changed by M106 (and others)
-/**
- * Set the number of proportional font spaces required to fill up a typical character space.
- * This can help to better align the output of commands like `G29 O` Mesh Output.
- *
- * For clients that use a fixed-width font (like OctoPrint), leave this set to 1.0.
- * Otherwise, adjust according to your client and font.
- */
-#define PROPORTIONAL_FONT_RATIO 1.0
+// @section gcode
/**
- * Spend 28 bytes of SRAM to optimize the GCode parser
+ * Spend 28 bytes of SRAM to optimize the G-code parser
*/
#define FASTER_GCODE_PARSER
@@ -3223,10 +3763,23 @@
//#define GCODE_QUOTED_STRINGS // Support for quoted string parameters
#endif
+// Support for MeatPack G-code compression (https://github.com/scottmudge/OctoPrint-MeatPack)
+//#define MEATPACK_ON_SERIAL_PORT_1
+//#define MEATPACK_ON_SERIAL_PORT_2
+
//#define GCODE_CASE_INSENSITIVE // Accept G-code sent to the firmware in lowercase
//#define REPETIER_GCODE_M360 // Add commands originally from Repetier FW
+/**
+ * Enable this option for a leaner build of Marlin that removes all
+ * workspace offsets, simplifying coordinate transformations, leveling, etc.
+ *
+ * - M206 and M428 are disabled.
+ * - G92 will revert to its behavior from Marlin 1.0.
+ */
+//#define NO_WORKSPACE_OFFSETS
+
/**
* CNC G-code options
* Support CNC-style G-code dialects used by laser cutters, drawing machine cams, etc.
@@ -3242,6 +3795,8 @@
//#define VARIABLE_G0_FEEDRATE // The G0 feedrate is set by F in G0 motion mode
#endif
+// @section gcode
+
/**
* Startup commands
*
@@ -3262,31 +3817,109 @@
#endif
/**
- * User-defined menu items that execute custom GCode
+ * User-defined menu items to run custom G-code.
+ * Up to 25 may be defined, but the actual number is LCD-dependent.
*/
-//#define CUSTOM_USER_MENUS
-#if ENABLED(CUSTOM_USER_MENUS)
- //#define CUSTOM_USER_MENU_TITLE "Custom Commands"
- #define USER_SCRIPT_DONE "M117 User Script Done"
- #define USER_SCRIPT_AUDIBLE_FEEDBACK
- //#define USER_SCRIPT_RETURN // Return to status screen after a script
- #define USER_DESC_1 "Home & UBL Info"
- #define USER_GCODE_1 "G28\nG29 W"
+// @section custom main menu
+
+// Custom Menu: Main Menu
+//#define CUSTOM_MENU_MAIN
+#if ENABLED(CUSTOM_MENU_MAIN)
+ //#define CUSTOM_MENU_MAIN_TITLE "Custom Commands"
+ #define CUSTOM_MENU_MAIN_SCRIPT_DONE "M117 User Script Done"
+ #define CUSTOM_MENU_MAIN_SCRIPT_AUDIBLE_FEEDBACK
+ //#define CUSTOM_MENU_MAIN_SCRIPT_RETURN // Return to status screen after a script
+ #define CUSTOM_MENU_MAIN_ONLY_IDLE // Only show custom menu when the machine is idle
+
+ #define MAIN_MENU_ITEM_1_DESC "Home & UBL Info"
+ #define MAIN_MENU_ITEM_1_GCODE "G28\nG29 W"
+ //#define MAIN_MENU_ITEM_1_CONFIRM // Show a confirmation dialog before this action
+
+ #define MAIN_MENU_ITEM_2_DESC "Preheat for " PREHEAT_1_LABEL
+ #define MAIN_MENU_ITEM_2_GCODE "M140 S" STRINGIFY(PREHEAT_1_TEMP_BED) "\nM104 S" STRINGIFY(PREHEAT_1_TEMP_HOTEND)
+ //#define MAIN_MENU_ITEM_2_CONFIRM
+
+ //#define MAIN_MENU_ITEM_3_DESC "Preheat for " PREHEAT_2_LABEL
+ //#define MAIN_MENU_ITEM_3_GCODE "M140 S" STRINGIFY(PREHEAT_2_TEMP_BED) "\nM104 S" STRINGIFY(PREHEAT_2_TEMP_HOTEND)
+ //#define MAIN_MENU_ITEM_3_CONFIRM
+
+ //#define MAIN_MENU_ITEM_4_DESC "Heat Bed/Home/Level"
+ //#define MAIN_MENU_ITEM_4_GCODE "M140 S" STRINGIFY(PREHEAT_2_TEMP_BED) "\nG28\nG29"
+ //#define MAIN_MENU_ITEM_4_CONFIRM
+
+ //#define MAIN_MENU_ITEM_5_DESC "Home & Info"
+ //#define MAIN_MENU_ITEM_5_GCODE "G28\nM503"
+ //#define MAIN_MENU_ITEM_5_CONFIRM
+#endif
+
+// @section custom config menu
+
+// Custom Menu: Configuration Menu
+//#define CUSTOM_MENU_CONFIG
+#if ENABLED(CUSTOM_MENU_CONFIG)
+ //#define CUSTOM_MENU_CONFIG_TITLE "Custom Commands"
+ #define CUSTOM_MENU_CONFIG_SCRIPT_DONE "M117 Wireless Script Done"
+ #define CUSTOM_MENU_CONFIG_SCRIPT_AUDIBLE_FEEDBACK
+ //#define CUSTOM_MENU_CONFIG_SCRIPT_RETURN // Return to status screen after a script
+ #define CUSTOM_MENU_CONFIG_ONLY_IDLE // Only show custom menu when the machine is idle
+
+ #define CONFIG_MENU_ITEM_1_DESC "Wifi ON"
+ #define CONFIG_MENU_ITEM_1_GCODE "M118 [ESP110] WIFI-STA pwd=12345678"
+ //#define CONFIG_MENU_ITEM_1_CONFIRM // Show a confirmation dialog before this action
+
+ #define CONFIG_MENU_ITEM_2_DESC "Bluetooth ON"
+ #define CONFIG_MENU_ITEM_2_GCODE "M118 [ESP110] BT pwd=12345678"
+ //#define CONFIG_MENU_ITEM_2_CONFIRM
+
+ //#define CONFIG_MENU_ITEM_3_DESC "Radio OFF"
+ //#define CONFIG_MENU_ITEM_3_GCODE "M118 [ESP110] OFF pwd=12345678"
+ //#define CONFIG_MENU_ITEM_3_CONFIRM
+
+ //#define CONFIG_MENU_ITEM_4_DESC "Wifi ????"
+ //#define CONFIG_MENU_ITEM_4_GCODE "M118 ????"
+ //#define CONFIG_MENU_ITEM_4_CONFIRM
+
+ //#define CONFIG_MENU_ITEM_5_DESC "Wifi ????"
+ //#define CONFIG_MENU_ITEM_5_GCODE "M118 ????"
+ //#define CONFIG_MENU_ITEM_5_CONFIRM
+#endif
- #define USER_DESC_2 "Preheat for " PREHEAT_1_LABEL
- #define USER_GCODE_2 "M140 S" STRINGIFY(PREHEAT_1_TEMP_BED) "\nM104 S" STRINGIFY(PREHEAT_1_TEMP_HOTEND)
+// @section custom buttons
- #define USER_DESC_3 "Preheat for " PREHEAT_2_LABEL
- #define USER_GCODE_3 "M140 S" STRINGIFY(PREHEAT_2_TEMP_BED) "\nM104 S" STRINGIFY(PREHEAT_2_TEMP_HOTEND)
+/**
+ * User-defined buttons to run custom G-code.
+ * Up to 25 may be defined.
+ */
+//#define CUSTOM_USER_BUTTONS
+#if ENABLED(CUSTOM_USER_BUTTONS)
+ //#define BUTTON1_PIN -1
+ #if PIN_EXISTS(BUTTON1)
+ #define BUTTON1_HIT_STATE LOW // State of the triggered button. NC=LOW. NO=HIGH.
+ #define BUTTON1_WHEN_PRINTING false // Button allowed to trigger during printing?
+ #define BUTTON1_GCODE "G28"
+ #define BUTTON1_DESC "Homing" // Optional string to set the LCD status
+ #endif
- #define USER_DESC_4 "Heat Bed/Home/Level"
- #define USER_GCODE_4 "M140 S" STRINGIFY(PREHEAT_2_TEMP_BED) "\nG28\nG29"
+ //#define BUTTON2_PIN -1
+ #if PIN_EXISTS(BUTTON2)
+ #define BUTTON2_HIT_STATE LOW
+ #define BUTTON2_WHEN_PRINTING false
+ #define BUTTON2_GCODE "M140 S" STRINGIFY(PREHEAT_1_TEMP_BED) "\nM104 S" STRINGIFY(PREHEAT_1_TEMP_HOTEND)
+ #define BUTTON2_DESC "Preheat for " PREHEAT_1_LABEL
+ #endif
- #define USER_DESC_5 "Home & Info"
- #define USER_GCODE_5 "G28\nM503"
+ //#define BUTTON3_PIN -1
+ #if PIN_EXISTS(BUTTON3)
+ #define BUTTON3_HIT_STATE LOW
+ #define BUTTON3_WHEN_PRINTING false
+ #define BUTTON3_GCODE "M140 S" STRINGIFY(PREHEAT_2_TEMP_BED) "\nM104 S" STRINGIFY(PREHEAT_2_TEMP_HOTEND)
+ #define BUTTON3_DESC "Preheat for " PREHEAT_2_LABEL
+ #endif
#endif
+// @section host
+
/**
* Host Action Commands
*
@@ -3303,16 +3936,26 @@
*/
#define HOST_ACTION_COMMANDS
#if ENABLED(HOST_ACTION_COMMANDS)
- //#define HOST_PROMPT_SUPPORT
- //#define HOST_START_MENU_ITEM // Add a menu item that tells the host to start
+ //#define HOST_PAUSE_M76 // Tell the host to pause in response to M76
+ //#define HOST_PROMPT_SUPPORT // Initiate host prompts to get user feedback
+ #if ENABLED(HOST_PROMPT_SUPPORT)
+ //#define HOST_STATUS_NOTIFICATIONS // Send some status messages to the host as notifications
+ #endif
+ //#define HOST_START_MENU_ITEM // Add a menu item that tells the host to start
+ //#define HOST_SHUTDOWN_MENU_ITEM // Add a menu item that tells the host to shut down
#endif
+// @section extras
+
/**
* Cancel Objects
*
* Implement M486 to allow Marlin to skip objects
*/
//#define CANCEL_OBJECTS
+#if ENABLED(CANCEL_OBJECTS)
+ #define CANCEL_OBJECTS_REPORTING // Emit the current object as a status message
+#endif
/**
* I2C position encoders for closed loop control.
@@ -3325,6 +3968,7 @@
* Alternative Supplier: https://reliabuild3d.com/
*
* Reliabuild encoders have been modified to improve reliability.
+ * @section i2c encoders
*/
//#define I2C_POSITION_ENCODERS
@@ -3389,13 +4033,14 @@
*/
#define I2CPE_MIN_UPD_TIME_MS 4 // (ms) Minimum time between encoder checks.
- // Use a rolling average to identify persistant errors that indicate skips, as opposed to vibration and noise.
+ // Use a rolling average to identify persistent errors that indicate skips, as opposed to vibration and noise.
#define I2CPE_ERR_ROLLING_AVERAGE
#endif // I2C_POSITION_ENCODERS
/**
* Analog Joystick(s)
+ * @section joystick
*/
//#define JOYSTICK
#if ENABLED(JOYSTICK)
@@ -3420,6 +4065,7 @@
* Modern replacement for the Prusa TMC_Z_CALIBRATION.
* Adds capability to work with any adjustable current drivers.
* Implemented as G34 because M915 is deprecated.
+ * @section calibrate
*/
//#define MECHANICAL_GANTRY_CALIBRATION
#if ENABLED(MECHANICAL_GANTRY_CALIBRATION)
@@ -3428,17 +4074,29 @@
#define GANTRY_CALIBRATION_FEEDRATE 500 // Feedrate for correction move
//#define GANTRY_CALIBRATION_TO_MIN // Enable to calibrate Z in the MIN direction
- //#define GANTRY_CALIBRATION_SAFE_POSITION { X_CENTER, Y_CENTER } // Safe position for nozzle
+ //#define GANTRY_CALIBRATION_SAFE_POSITION XY_CENTER // Safe position for nozzle
//#define GANTRY_CALIBRATION_XY_PARK_FEEDRATE 3000 // XY Park Feedrate - MMM
//#define GANTRY_CALIBRATION_COMMANDS_PRE ""
#define GANTRY_CALIBRATION_COMMANDS_POST "G28" // G28 highly recommended to ensure an accurate position
#endif
+/**
+ * Instant freeze / unfreeze functionality
+ * Potentially useful for emergency stop that allows being resumed.
+ * @section interface
+ */
+//#define FREEZE_FEATURE
+#if ENABLED(FREEZE_FEATURE)
+ //#define FREEZE_PIN 41 // Override the default (KILL) pin here
+ #define FREEZE_STATE LOW // State of pin indicating freeze
+#endif
+
/**
* MAX7219 Debug Matrix
*
* Add support for a low-cost 8x8 LED Matrix based on the Max7219 chip as a realtime status display.
* Requires 3 signal wires. Some useful debug options are included to demonstrate its usage.
+ * @section debug matrix
*/
//#define MAX7219_DEBUG
#if ENABLED(MAX7219_DEBUG)
@@ -3451,7 +4109,8 @@
#define MAX7219_NUMBER_UNITS 1 // Number of Max7219 units in chain.
#define MAX7219_ROTATE 0 // Rotate the display clockwise (in multiples of +/- 90°)
// connector at: right=0 bottom=-90 top=90 left=180
- //#define MAX7219_REVERSE_ORDER // The individual LED matrix units may be in reversed order
+ //#define MAX7219_REVERSE_ORDER // The order of the LED matrix units may be reversed
+ //#define MAX7219_REVERSE_EACH // The LEDs in each matrix unit row may be reversed
//#define MAX7219_SIDE_BY_SIDE // Big chip+matrix boards can be chained side-by-side
/**
@@ -3459,29 +4118,33 @@
* If you add more debug displays, be careful to avoid conflicts!
*/
#define MAX7219_DEBUG_PRINTER_ALIVE // Blink corner LED of 8x8 matrix to show that the firmware is functioning
- #define MAX7219_DEBUG_PLANNER_HEAD 3 // Show the planner queue head position on this and the next LED matrix row
- #define MAX7219_DEBUG_PLANNER_TAIL 5 // Show the planner queue tail position on this and the next LED matrix row
+ #define MAX7219_DEBUG_PLANNER_HEAD 2 // Show the planner queue head position on this and the next LED matrix row
+ #define MAX7219_DEBUG_PLANNER_TAIL 4 // Show the planner queue tail position on this and the next LED matrix row
#define MAX7219_DEBUG_PLANNER_QUEUE 0 // Show the current planner queue depth on this and the next LED matrix row
// If you experience stuttering, reboots, etc. this option can reveal how
// tweaks made to the configuration are affecting the printer in real-time.
+ #define MAX7219_DEBUG_PROFILE 6 // Display the fraction of CPU time spent in profiled code on this LED matrix
+ // row. By default idle() is profiled so this shows how "idle" the processor is.
+ // See class CodeProfiler.
#endif
/**
* NanoDLP Sync support
*
- * Add support for Synchronized Z moves when using with NanoDLP. G0/G1 axis moves will output "Z_move_comp"
- * string to enable synchronization with DLP projector exposure. This change will allow to use
- * [[WaitForDoneMessage]] instead of populating your gcode with M400 commands
+ * Support for Synchronized Z moves when used with NanoDLP. G0/G1 axis moves will
+ * output a "Z_move_comp" string to enable synchronization with DLP projector exposure.
+ * This feature allows you to use [[WaitForDoneMessage]] instead of M400 commands.
+ * @section nanodlp
*/
//#define NANODLP_Z_SYNC
#if ENABLED(NANODLP_Z_SYNC)
- //#define NANODLP_ALL_AXIS // Enables "Z_move_comp" output on any axis move.
- // Default behavior is limited to Z axis only.
+ //#define NANODLP_ALL_AXIS // Send a "Z_move_comp" report for any axis move (not just Z).
#endif
/**
* Ethernet. Use M552 to enable and set the IP address.
+ * @section network
*/
#if HAS_ETHERNET
#define MAC_ADDRESS { 0xDE, 0xAD, 0xBE, 0xEF, 0xF0, 0x0D } // A MAC address unique to your network
@@ -3509,17 +4172,29 @@
//#include "Configuration_Secure.h" // External file with WiFi SSID / Password
#endif
+// @section multi-material
+
/**
- * Průša Multi-Material Unit v2
+ * Průša Multi-Material Unit (MMU)
* Enable in Configuration.h
+ *
+ * These devices allow a single stepper driver on the board to drive
+ * multi-material feeders with any number of stepper motors.
*/
-#if ENABLED(PRUSA_MMU2)
-
+#if HAS_PRUSA_MMU1
+ /**
+ * This option only allows the multiplexer to switch on tool-change.
+ * Additional options to configure custom E moves are pending.
+ *
+ * Override the default DIO selector pins here, if needed.
+ * Some pins files may provide defaults for these pins.
+ */
+ //#define E_MUX0_PIN 40 // Always Required
+ //#define E_MUX1_PIN 42 // Needed for 3 to 8 inputs
+ //#define E_MUX2_PIN 44 // Needed for 5 to 8 inputs
+#elif HAS_PRUSA_MMU2
// Serial port used for communication with MMU2.
- // For AVR enable the UART port used for the MMU. (e.g., mmuSerial)
- // For 32-bit boards check your HAL for available serial ports. (e.g., Serial2)
#define MMU2_SERIAL_PORT 2
- #define MMU2_SERIAL mmuSerial
// Use hardware reset for MMU if a pin is defined for it
//#define MMU2_RST_PIN 23
@@ -3532,7 +4207,7 @@
// Add an LCD menu for MMU2
//#define MMU2_MENUS
- #if ENABLED(MMU2_MENUS)
+ #if EITHER(MMU2_MENUS, HAS_PRUSA_MMU2S)
// Settings for filament load / unload from the LCD menu.
// This is for Průša MK3-style extruders. Customize for your hardware.
#define MMU2_FILAMENTCHANGE_EJECT_FEED 80.0
@@ -3557,29 +4232,12 @@
{ -50.0, 2000 }
#endif
- /**
- * MMU Extruder Sensor
- *
- * Support for a Průša (or other) IR Sensor to detect filament near the extruder
- * and make loading more reliable. Suitable for an extruder equipped with a filament
- * sensor less than 38mm from the gears.
- *
- * During loading the extruder will stop when the sensor is triggered, then do a last
- * move up to the gears. If no filament is detected, the MMU2 can make some more attempts.
- * If all attempts fail, a filament runout will be triggered.
- */
- //#define MMU_EXTRUDER_SENSOR
- #if ENABLED(MMU_EXTRUDER_SENSOR)
- #define MMU_LOADING_ATTEMPTS_NR 5 // max. number of attempts to load filament if first load fail
- #endif
-
/**
* Using a sensor like the MMU2S
* This mode requires a MK3S extruder with a sensor at the extruder idler, like the MMU2S.
* See https://help.prusa3d.com/en/guide/3b-mk3s-mk2-5s-extruder-upgrade_41560, step 11
*/
- //#define PRUSA_MMU2_S_MODE
- #if ENABLED(PRUSA_MMU2_S_MODE)
+ #if HAS_PRUSA_MMU2S
#define MMU2_C0_RETRY 5 // Number of retries (total time = timeout*retries)
#define MMU2_CAN_LOAD_FEEDRATE 800 // (mm/min)
@@ -3595,14 +4253,33 @@
#define MMU2_CAN_LOAD_INCREMENT_SEQUENCE \
{ -MMU2_CAN_LOAD_INCREMENT, MMU2_CAN_LOAD_FEEDRATE }
+ #else
+
+ /**
+ * MMU1 Extruder Sensor
+ *
+ * Support for a Průša (or other) IR Sensor to detect filament near the extruder
+ * and make loading more reliable. Suitable for an extruder equipped with a filament
+ * sensor less than 38mm from the gears.
+ *
+ * During loading the extruder will stop when the sensor is triggered, then do a last
+ * move up to the gears. If no filament is detected, the MMU2 can make some more attempts.
+ * If all attempts fail, a filament runout will be triggered.
+ */
+ //#define MMU_EXTRUDER_SENSOR
+ #if ENABLED(MMU_EXTRUDER_SENSOR)
+ #define MMU_LOADING_ATTEMPTS_NR 5 // max. number of attempts to load filament if first load fail
+ #endif
+
#endif
//#define MMU2_DEBUG // Write debug info to serial output
-#endif // PRUSA_MMU2
+#endif // HAS_PRUSA_MMU2
/**
* Advanced Print Counter settings
+ * @section stats
*/
#if ENABLED(PRINTCOUNTER)
#define SERVICE_WARNING_BUZZES 3
@@ -3632,5 +4309,32 @@
//
//#define PINS_DEBUGGING
+// Enable Tests that will run at startup and produce a report
+//#define MARLIN_TEST_BUILD
+
// Enable Marlin dev mode which adds some special commands
//#define MARLIN_DEV_MODE
+
+#if ENABLED(MARLIN_DEV_MODE)
+ /**
+ * D576 - Buffer Monitoring
+ * To help diagnose print quality issues stemming from empty command buffers.
+ */
+ //#define BUFFER_MONITORING
+#endif
+
+/**
+ * Postmortem Debugging captures misbehavior and outputs the CPU status and backtrace to serial.
+ * When running in the debugger it will break for debugging. This is useful to help understand
+ * a crash from a remote location. Requires ~400 bytes of SRAM and 5Kb of flash.
+ */
+//#define POSTMORTEM_DEBUGGING
+
+/**
+ * Software Reset options
+ */
+//#define SOFT_RESET_VIA_SERIAL // 'KILL' and '^X' commands will soft-reset the controller
+//#define SOFT_RESET_ON_KILL // Use a digital button to soft-reset the controller after KILL
+
+// Report uncleaned reset reason from register r2 instead of MCUSR. Supported by Optiboot on AVR.
+//#define OPTIBOOT_RESET_REASON
diff --git a/Marlin/Makefile b/Marlin/Makefile
index 49cb960b92fe..c72c1d589607 100644
--- a/Marlin/Makefile
+++ b/Marlin/Makefile
@@ -109,8 +109,8 @@ LIQUID_TWI2 ?= 0
# This defines if Wire is needed
WIRE ?= 0
-# This defines if Tone is needed (i.e SPEAKER is defined in Configuration.h)
-# Disabling this (and SPEAKER) saves approximatively 350 bytes of memory.
+# This defines if Tone is needed (i.e., SPEAKER is defined in Configuration.h)
+# Disabling this (and SPEAKER) saves approximately 350 bytes of memory.
TONE ?= 1
# This defines if U8GLIB is needed (may require RELOC_WORKAROUND)
@@ -132,7 +132,7 @@ CC_MIN:=$(shell $(CC) -dM -E - < /dev/null | grep __GNUC_MINOR__ | cut -f3 -d\ )
CC_PATCHLEVEL:=$(shell $(CC) -dM -E - < /dev/null | grep __GNUC_PATCHLEVEL__ | cut -f3 -d\ )
CC_VER:=$(shell echo $$(( $(CC_MAJ) * 10000 + $(CC_MIN) * 100 + $(CC_PATCHLEVEL) )))
ifeq ($(shell test $(CC_VER) -lt 40901 && echo 1),1)
- @echo This version of GCC is likely broken. Enabling relocation workaround.
+ $(warning This GCC version $(CC_VER) is likely broken. Enabling relocation workaround.)
RELOC_WORKAROUND = 1
endif
@@ -207,11 +207,11 @@ else ifeq ($(HARDWARE_MOTHERBOARD),1105)
else ifeq ($(HARDWARE_MOTHERBOARD),1106)
# MKS BASE v1.0
else ifeq ($(HARDWARE_MOTHERBOARD),1107)
-# MKS v1.4 with A4982 stepper drivers
+# MKS BASE v1.4 with Allegro A4982 stepper drivers
else ifeq ($(HARDWARE_MOTHERBOARD),1108)
-# MKS v1.5 with Allegro A4982 stepper drivers
+# MKS BASE v1.5 with Allegro A4982 stepper drivers
else ifeq ($(HARDWARE_MOTHERBOARD),1109)
-# MKS v1.6 with Allegro A4982 stepper drivers
+# MKS BASE v1.6 with Allegro A4982 stepper drivers
else ifeq ($(HARDWARE_MOTHERBOARD),1110)
# MKS BASE 1.0 with Heroic HR4982 stepper drivers
else ifeq ($(HARDWARE_MOTHERBOARD),1111)
@@ -219,93 +219,108 @@ else ifeq ($(HARDWARE_MOTHERBOARD),1111)
else ifeq ($(HARDWARE_MOTHERBOARD),1112)
# MKS GEN L
else ifeq ($(HARDWARE_MOTHERBOARD),1113)
-# zrib V2.0 control board (Chinese knock off RAMPS replica)
-else ifeq ($(HARDWARE_MOTHERBOARD),1114)
# BigTreeTech or BIQU KFB2.0
+else ifeq ($(HARDWARE_MOTHERBOARD),1114)
+# zrib V2.0 (Chinese RAMPS replica)
else ifeq ($(HARDWARE_MOTHERBOARD),1115)
-# Felix 2.0+ Electronics Board (RAMPS like)
+# zrib V5.2 (Chinese RAMPS replica)
else ifeq ($(HARDWARE_MOTHERBOARD),1116)
-# Invent-A-Part RigidBoard
+# Felix 2.0+ Electronics Board (RAMPS like)
else ifeq ($(HARDWARE_MOTHERBOARD),1117)
-# Invent-A-Part RigidBoard V2
+# Invent-A-Part RigidBoard
else ifeq ($(HARDWARE_MOTHERBOARD),1118)
-# Sainsmart 2-in-1 board
+# Invent-A-Part RigidBoard V2
else ifeq ($(HARDWARE_MOTHERBOARD),1119)
-# Ultimaker
+# Sainsmart 2-in-1 board
else ifeq ($(HARDWARE_MOTHERBOARD),1120)
-# Ultimaker (Older electronics. Pre 1.5.4. This is rare)
+# Ultimaker
else ifeq ($(HARDWARE_MOTHERBOARD),1121)
+# Ultimaker (Older electronics. Pre 1.5.4. This is rare)
+else ifeq ($(HARDWARE_MOTHERBOARD),1122)
MCU ?= atmega1280
PROG_MCU ?= m1280
-
# Azteeg X3
-else ifeq ($(HARDWARE_MOTHERBOARD),1122)
-# Azteeg X3 Pro
else ifeq ($(HARDWARE_MOTHERBOARD),1123)
-# Ultimainboard 2.x (Uses TEMP_SENSOR 20)
+# Azteeg X3 Pro
else ifeq ($(HARDWARE_MOTHERBOARD),1124)
-# Rumba
+# Ultimainboard 2.x (Uses TEMP_SENSOR 20)
else ifeq ($(HARDWARE_MOTHERBOARD),1125)
-# Raise3D Rumba
+# Rumba
else ifeq ($(HARDWARE_MOTHERBOARD),1126)
-# Rapide Lite RL200 Rumba
+# Raise3D N series Rumba derivative
else ifeq ($(HARDWARE_MOTHERBOARD),1127)
-# Formbot T-Rex 2 Plus
+# Rapide Lite 200 (v1, low-cost RUMBA clone with drv)
else ifeq ($(HARDWARE_MOTHERBOARD),1128)
-# Formbot T-Rex 3
+# Formbot T-Rex 2 Plus
else ifeq ($(HARDWARE_MOTHERBOARD),1129)
-# Formbot Raptor
+# Formbot T-Rex 3
else ifeq ($(HARDWARE_MOTHERBOARD),1130)
-# Formbot Raptor 2
+# Formbot Raptor
else ifeq ($(HARDWARE_MOTHERBOARD),1131)
-# bq ZUM Mega 3D
+# Formbot Raptor 2
else ifeq ($(HARDWARE_MOTHERBOARD),1132)
-# MakeBoard Mini v2.1.2 is a control board sold by MicroMake
+# bq ZUM Mega 3D
else ifeq ($(HARDWARE_MOTHERBOARD),1133)
-# TriGorilla Anycubic version 1.3 based on RAMPS EFB
+# MakeBoard Mini v2.1.2 by MicroMake
else ifeq ($(HARDWARE_MOTHERBOARD),1134)
-# TriGorilla Anycubic version 1.4 based on RAMPS EFB
+# TriGorilla Anycubic version 1.3-based on RAMPS EFB
else ifeq ($(HARDWARE_MOTHERBOARD),1135)
-# TriGorilla Anycubic version 1.4 Rev 1.1
+# ... Ver 1.4
else ifeq ($(HARDWARE_MOTHERBOARD),1136)
-# Creality: Ender-4, CR-8
+# ... Rev 1.1 (new servo pin order)
else ifeq ($(HARDWARE_MOTHERBOARD),1137)
-# Creality: CR10S, CR20, CR-X
+# Creality: Ender-4, CR-8
else ifeq ($(HARDWARE_MOTHERBOARD),1138)
-# Dagoma F5
+# Creality: CR10S, CR20, CR-X
else ifeq ($(HARDWARE_MOTHERBOARD),1139)
-# FYSETC F6 1.3
+# Dagoma F5
else ifeq ($(HARDWARE_MOTHERBOARD),1140)
-# FYSETC F6 1.5
+# FYSETC F6 1.3
else ifeq ($(HARDWARE_MOTHERBOARD),1141)
-# Duplicator i3 Plus
+# FYSETC F6 1.4
else ifeq ($(HARDWARE_MOTHERBOARD),1142)
-# VORON
+# Wanhao Duplicator i3 Plus
else ifeq ($(HARDWARE_MOTHERBOARD),1143)
-# TRONXY V3 1.0
+# VORON Design
else ifeq ($(HARDWARE_MOTHERBOARD),1144)
-# Z-Bolt X Series
+# Tronxy TRONXY-V3-1.0
else ifeq ($(HARDWARE_MOTHERBOARD),1145)
-# TT OSCAR
+# Z-Bolt X Series
else ifeq ($(HARDWARE_MOTHERBOARD),1146)
-# Overlord/Overlord Pro
+# TT OSCAR
else ifeq ($(HARDWARE_MOTHERBOARD),1147)
-# ADIMLab Gantry v1
+# Overlord/Overlord Pro
else ifeq ($(HARDWARE_MOTHERBOARD),1148)
-# ADIMLab Gantry v2
+# ADIMLab Gantry v1
else ifeq ($(HARDWARE_MOTHERBOARD),1149)
-# BIQU Tango V1
+# ADIMLab Gantry v2
else ifeq ($(HARDWARE_MOTHERBOARD),1150)
-# MKS GEN L V2
+# BIQU Tango V1
else ifeq ($(HARDWARE_MOTHERBOARD),1151)
-# MKS GEN L V2.1
+# MKS GEN L V2
else ifeq ($(HARDWARE_MOTHERBOARD),1152)
-# Copymaster 3D
+# MKS GEN L V2.1
else ifeq ($(HARDWARE_MOTHERBOARD),1153)
-# Ortur 4
+# Copymaster 3D
else ifeq ($(HARDWARE_MOTHERBOARD),1154)
-# Tenlog D3 Hero
+# Ortur 4
else ifeq ($(HARDWARE_MOTHERBOARD),1155)
+# Tenlog D3 Hero IDEX printer
+else ifeq ($(HARDWARE_MOTHERBOARD),1156)
+# Ramps S 1.2 by Sakul.cz (Power outputs: Hotend0, Hotend1, Fan, Bed)
+else ifeq ($(HARDWARE_MOTHERBOARD),1157)
+# Ramps S 1.2 by Sakul.cz (Power outputs: Hotend0, Hotend1, Hotend2, Bed)
+else ifeq ($(HARDWARE_MOTHERBOARD),1158)
+# Ramps S 1.2 by Sakul.cz (Power outputs: Hotend, Fan0, Fan1, Bed)
+else ifeq ($(HARDWARE_MOTHERBOARD),1159)
+# Longer LK1 PRO / Alfawise U20 Pro (PRO version)
+else ifeq ($(HARDWARE_MOTHERBOARD),1160)
+# Longer LKx PRO / Alfawise Uxx Pro (PRO version)
+else ifeq ($(HARDWARE_MOTHERBOARD),1161)
+# Zonestar zrib V5.3 (Chinese RAMPS replica)
+else ifeq ($(HARDWARE_MOTHERBOARD),1162)
+# Pxmalion Core I3
+else ifeq ($(HARDWARE_MOTHERBOARD),1163)
#
# RAMBo and derivatives
@@ -323,6 +338,8 @@ else ifeq ($(HARDWARE_MOTHERBOARD),1203)
else ifeq ($(HARDWARE_MOTHERBOARD),1204)
# abee Scoovo X9H
else ifeq ($(HARDWARE_MOTHERBOARD),1205)
+# Rambo ThinkerV2
+else ifeq ($(HARDWARE_MOTHERBOARD),1206)
#
# Other ATmega1280, ATmega2560
@@ -356,20 +373,38 @@ else ifeq ($(HARDWARE_MOTHERBOARD),1311)
else ifeq ($(HARDWARE_MOTHERBOARD),1312)
# Mega controller
else ifeq ($(HARDWARE_MOTHERBOARD),1313)
-# Geeetech GT2560 Rev B for Mecreator2
+# Geeetech GT2560 Rev A
else ifeq ($(HARDWARE_MOTHERBOARD),1314)
-# Geeetech GT2560 Rev. A
+# Geeetech GT2560 Rev A+ (with auto level probe)
else ifeq ($(HARDWARE_MOTHERBOARD),1315)
-# Geeetech GT2560 Rev. A+ (with auto level probe)
+# Geeetech GT2560 Rev B
else ifeq ($(HARDWARE_MOTHERBOARD),1316)
-# Geeetech GT2560 Rev B for A10(M/D)
+# Geeetech GT2560 Rev B for A10(M/T/D)
else ifeq ($(HARDWARE_MOTHERBOARD),1317)
-# Geeetech GT2560 Rev B for A20(M/D)
+# Geeetech GT2560 Rev B for A10(M/T/D)
else ifeq ($(HARDWARE_MOTHERBOARD),1318)
-# Einstart retrofit
+# Geeetech GT2560 Rev B for Mecreator2
else ifeq ($(HARDWARE_MOTHERBOARD),1319)
-# Wanhao 0ne+ i3 Mini
+# Geeetech GT2560 Rev B for A20(M/T/D)
else ifeq ($(HARDWARE_MOTHERBOARD),1320)
+# Einstart retrofit
+else ifeq ($(HARDWARE_MOTHERBOARD),1321)
+# Wanhao 0ne+ i3 Mini
+else ifeq ($(HARDWARE_MOTHERBOARD),1322)
+# Leapfrog Xeed 2015
+else ifeq ($(HARDWARE_MOTHERBOARD),1323)
+# PICA Shield (original version)
+else ifeq ($(HARDWARE_MOTHERBOARD),1324)
+# PICA Shield (rev C or later)
+else ifeq ($(HARDWARE_MOTHERBOARD),1325)
+# Intamsys 4.0 (Funmat HT)
+else ifeq ($(HARDWARE_MOTHERBOARD),1326)
+# Malyan M180 Mainboard Version 2 (no display function, direct G-code only)
+else ifeq ($(HARDWARE_MOTHERBOARD),1327)
+# Geeetech GT2560 Rev B for A20(M/T/D)
+else ifeq ($(HARDWARE_MOTHERBOARD),1328)
+# Mega controller & Protoneer CNC Shield V3.00
+else ifeq ($(HARDWARE_MOTHERBOARD),1329)
#
# ATmega1281, ATmega2561
@@ -443,6 +478,11 @@ else ifeq ($(HARDWARE_MOTHERBOARD),1510)
HARDWARE_VARIANT ?= Sanguino
MCU ?= atmega1284p
PROG_MCU ?= m1284p
+# ZoneStar ZMIB V2
+else ifeq ($(HARDWARE_MOTHERBOARD),1511)
+ HARDWARE_VARIANT ?= Sanguino
+ MCU ?= atmega1284p
+ PROG_MCU ?= m1284p
#
# Other ATmega644P, ATmega644, ATmega1284P
@@ -991,5 +1031,5 @@ clean:
.PHONY: all build elf hex eep lss sym program coff extcoff clean depend sizebefore sizeafter
-# Automaticaly include the dependency files created by gcc
+# Automatically include the dependency files created by gcc
-include ${patsubst %.o, %.d, ${OBJ}}
diff --git a/Marlin/Version.h b/Marlin/Version.h
index fe0724fbfcb1..ab4a453716c1 100644
--- a/Marlin/Version.h
+++ b/Marlin/Version.h
@@ -28,7 +28,7 @@
/**
* Marlin release version identifier
*/
-//#define SHORT_BUILD_VERSION "bugfix-2.0.x"
+//#define SHORT_BUILD_VERSION "bugfix-2.1.x"
/**
* Verbose version identifier which should contain a reference to the location
@@ -41,7 +41,7 @@
* here we define this default string as the date where the latest release
* version was tagged.
*/
-//#define STRING_DISTRIBUTION_DATE "2019-07-10"
+//#define STRING_DISTRIBUTION_DATE "2022-09-05"
/**
* Defines a generic printer name to be output to the LCD after booting Marlin.
@@ -54,7 +54,7 @@
* has a distinct Github fork— the Source Code URL should just be the main
* Marlin repository.
*/
-//#define SOURCE_CODE_URL "https://github.com/MarlinFirmware/Marlin"
+//#define SOURCE_CODE_URL "github.com/MarlinFirmware/Marlin"
/**
* Default generic printer UUID.
@@ -65,7 +65,7 @@
* The WEBSITE_URL is the location where users can get more information such as
* documentation about a specific Marlin release.
*/
-//#define WEBSITE_URL "https://marlinfw.org"
+//#define WEBSITE_URL "marlinfw.org"
/**
* Set the vendor info the serial USB interface, if changable
diff --git a/Marlin/config.ini b/Marlin/config.ini
new file mode 100644
index 000000000000..0fb9fb0c9308
--- /dev/null
+++ b/Marlin/config.ini
@@ -0,0 +1,211 @@
+#
+# Marlin Firmware
+# config.ini - Options to apply before the build
+#
+[config:base]
+ini_use_config = none
+
+# Load all config: sections in this file
+;ini_use_config = all
+# Load config file relative to Marlin/
+;ini_use_config = another.ini
+# Download configurations from GitHub
+;ini_use_config = example/Creality/Ender-5 Plus @ bugfix-2.1.x
+# Download configurations from your server
+;ini_use_config = https://me.myserver.com/path/to/configs
+# Evaluate config:base and do a config dump
+;ini_use_config = base
+;config_export = 2
+
+[config:minimal]
+motherboard = BOARD_RAMPS_14_EFB
+serial_port = 0
+baudrate = 250000
+
+use_watchdog = on
+thermal_protection_hotends = on
+thermal_protection_hysteresis = 4
+thermal_protection_period = 40
+
+bufsize = 4
+block_buffer_size = 16
+max_cmd_size = 96
+
+extruders = 1
+temp_sensor_0 = 1
+
+temp_hysteresis = 3
+heater_0_mintemp = 5
+heater_0_maxtemp = 275
+preheat_1_temp_hotend = 180
+
+bang_max = 255
+pidtemp = on
+pid_k1 = 0.95
+pid_max = BANG_MAX
+pid_functional_range = 10
+
+default_kp = 22.20
+default_ki = 1.08
+default_kd = 114.00
+
+x_driver_type = A4988
+y_driver_type = A4988
+z_driver_type = A4988
+e0_driver_type = A4988
+
+x_bed_size = 200
+x_min_pos = 0
+x_max_pos = X_BED_SIZE
+
+y_bed_size = 200
+y_min_pos = 0
+y_max_pos = Y_BED_SIZE
+
+z_min_pos = 0
+z_max_pos = 200
+
+x_home_dir = -1
+y_home_dir = -1
+z_home_dir = -1
+
+use_xmin_plug = on
+use_ymin_plug = on
+use_zmin_plug = on
+
+x_min_endstop_inverting = false
+y_min_endstop_inverting = false
+z_min_endstop_inverting = false
+
+default_axis_steps_per_unit = { 80, 80, 400, 500 }
+axis_relative_modes = { false, false, false, false }
+default_max_feedrate = { 300, 300, 5, 25 }
+default_max_acceleration = { 3000, 3000, 100, 10000 }
+
+homing_feedrate_mm_m = { (50*60), (50*60), (4*60) }
+homing_bump_divisor = { 2, 2, 4 }
+
+x_enable_on = 0
+y_enable_on = 0
+z_enable_on = 0
+e_enable_on = 0
+
+invert_x_dir = false
+invert_y_dir = true
+invert_z_dir = false
+invert_e0_dir = false
+
+invert_e_step_pin = false
+invert_x_step_pin = false
+invert_y_step_pin = false
+invert_z_step_pin = false
+
+disable_x = false
+disable_y = false
+disable_z = false
+disable_e = false
+
+proportional_font_ratio = 1.0
+default_nominal_filament_dia = 1.75
+
+junction_deviation_mm = 0.013
+
+default_acceleration = 3000
+default_travel_acceleration = 3000
+default_retract_acceleration = 3000
+
+default_minimumfeedrate = 0.0
+default_mintravelfeedrate = 0.0
+
+minimum_planner_speed = 0.05
+min_steps_per_segment = 6
+default_minsegmenttime = 20000
+
+[config:basic]
+bed_overshoot = 10
+busy_while_heating = on
+default_ejerk = 5.0
+default_keepalive_interval = 2
+default_leveling_fade_height = 0.0
+disable_inactive_extruder = on
+display_charset_hd44780 = JAPANESE
+eeprom_boot_silent = on
+eeprom_chitchat = on
+endstoppullups = on
+extrude_maxlength = 200
+extrude_mintemp = 170
+host_keepalive_feature = on
+hotend_overshoot = 15
+jd_handle_small_segments = on
+lcd_info_screen_style = 0
+lcd_language = en
+max_bed_power = 255
+mesh_inset = 0
+min_software_endstops = on
+max_software_endstops = on
+min_software_endstop_x = on
+min_software_endstop_y = on
+min_software_endstop_z = on
+max_software_endstop_x = on
+max_software_endstop_y = on
+max_software_endstop_z = on
+preheat_1_fan_speed = 0
+preheat_1_label = "PLA"
+preheat_1_temp_bed = 70
+prevent_cold_extrusion = on
+prevent_lengthy_extrude = on
+printjob_timer_autostart = on
+probing_margin = 10
+show_bootscreen = on
+soft_pwm_scale = 0
+string_config_h_author = "(none, default config)"
+temp_bed_hysteresis = 3
+temp_bed_residency_time = 10
+temp_bed_window = 1
+temp_residency_time = 10
+temp_window = 1
+validate_homing_endstops = on
+xy_probe_feedrate = (133*60)
+z_clearance_between_probes = 5
+z_clearance_deploy_probe = 10
+z_clearance_multi_probe = 5
+
+[config:advanced]
+arc_support = on
+auto_report_temperatures = on
+autotemp = on
+autotemp_oldweight = 0.98
+bed_check_interval = 5000
+default_stepper_deactive_time = 120
+default_volumetric_extruder_limit = 0.00
+disable_inactive_e = true
+disable_inactive_x = true
+disable_inactive_y = true
+disable_inactive_z = true
+e0_auto_fan_pin = -1
+encoder_100x_steps_per_sec = 80
+encoder_10x_steps_per_sec = 30
+encoder_rate_multiplier = on
+extended_capabilities_report = on
+extruder_auto_fan_speed = 255
+extruder_auto_fan_temperature = 50
+fanmux0_pin = -1
+fanmux1_pin = -1
+fanmux2_pin = -1
+faster_gcode_parser = on
+homing_bump_mm = { 5, 5, 2 }
+max_arc_segment_mm = 1.0
+min_arc_segment_mm = 0.1
+min_circle_segments = 72
+n_arc_correction = 25
+serial_overrun_protection = on
+slowdown = on
+slowdown_divisor = 2
+temp_sensor_bed = 0
+thermal_protection_bed_hysteresis = 2
+thermocouple_max_errors = 15
+tx_buffer_size = 0
+watch_bed_temp_increase = 2
+watch_bed_temp_period = 60
+watch_temp_increase = 2
+watch_temp_period = 20
diff --git a/Marlin/src/HAL/AVR/HAL.cpp b/Marlin/src/HAL/AVR/HAL.cpp
index 58d57c8ee54b..5382eb36a2bd 100644
--- a/Marlin/src/HAL/AVR/HAL.cpp
+++ b/Marlin/src/HAL/AVR/HAL.cpp
@@ -23,18 +23,45 @@
#include "../../inc/MarlinConfig.h"
#include "HAL.h"
+#include
+
+#ifdef USBCON
+ DefaultSerial1 MSerial0(false, Serial);
+ #ifdef BLUETOOTH
+ BTSerial btSerial(false, bluetoothSerial);
+ #endif
+#endif
// ------------------------
// Public Variables
// ------------------------
-//uint8_t MCUSR;
+// Don't initialize/override variable (which would happen in .init4)
+uint8_t MarlinHAL::reset_reason __attribute__((section(".noinit")));
// ------------------------
// Public functions
// ------------------------
-void HAL_init() {
+__attribute__((naked)) // Don't output function pro- and epilogue
+__attribute__((used)) // Output the function, even if "not used"
+__attribute__((section(".init3"))) // Put in an early user definable section
+void save_reset_reason() {
+ #if ENABLED(OPTIBOOT_RESET_REASON)
+ __asm__ __volatile__(
+ A("STS %0, r2")
+ : "=m"(hal.reset_reason)
+ );
+ #else
+ hal.reset_reason = MCUSR;
+ #endif
+
+ // Clear within 16ms since WDRF bit enables a 16ms watchdog timer -> Boot loop
+ hal.clear_reset_source();
+ wdt_disable();
+}
+
+void MarlinHAL::init() {
// Init Servo Pins
#define INIT_SERVO(N) OUT_WRITE(SERVO##N##_PIN, LOW)
#if HAS_SERVO_0
@@ -49,8 +76,75 @@ void HAL_init() {
#if HAS_SERVO_3
INIT_SERVO(3);
#endif
+
+ init_pwm_timers(); // Init user timers to default frequency - 1000HZ
+}
+
+void MarlinHAL::reboot() {
+ #if ENABLED(USE_WATCHDOG)
+ while (1) { /* run out the watchdog */ }
+ #else
+ void (*resetFunc)() = 0; // Declare resetFunc() at address 0
+ resetFunc(); // Jump to address 0
+ #endif
}
+// ------------------------
+// Watchdog Timer
+// ------------------------
+
+#if ENABLED(USE_WATCHDOG)
+
+ #include
+ #include "../../MarlinCore.h"
+
+ // Initialize watchdog with 8s timeout, if possible. Otherwise, make it 4s.
+ void MarlinHAL::watchdog_init() {
+ #if ENABLED(WATCHDOG_DURATION_8S) && defined(WDTO_8S)
+ #define WDTO_NS WDTO_8S
+ #else
+ #define WDTO_NS WDTO_4S
+ #endif
+ #if ENABLED(WATCHDOG_RESET_MANUAL)
+ // Enable the watchdog timer, but only for the interrupt.
+ // Take care, as this requires the correct order of operation, with interrupts disabled.
+ // See the datasheet of any AVR chip for details.
+ wdt_reset();
+ cli();
+ _WD_CONTROL_REG = _BV(_WD_CHANGE_BIT) | _BV(WDE);
+ _WD_CONTROL_REG = _BV(WDIE) | (WDTO_NS & 0x07) | ((WDTO_NS & 0x08) << 2); // WDTO_NS directly does not work. bit 0-2 are consecutive in the register but the highest value bit is at bit 5
+ // So worked for up to WDTO_2S
+ sei();
+ wdt_reset();
+ #else
+ wdt_enable(WDTO_NS); // The function handles the upper bit correct.
+ #endif
+ //delay(10000); // test it!
+ }
+
+ //===========================================================================
+ //=================================== ISR ===================================
+ //===========================================================================
+
+ // Watchdog timer interrupt, called if main program blocks >4sec and manual reset is enabled.
+ #if ENABLED(WATCHDOG_RESET_MANUAL)
+ ISR(WDT_vect) {
+ sei(); // With the interrupt driven serial we need to allow interrupts.
+ SERIAL_ERROR_MSG(STR_WATCHDOG_FIRED);
+ minkill(); // interrupt-safe final kill and infinite loop
+ }
+ #endif
+
+ // Reset watchdog. MUST be called at least every 4 seconds after the
+ // first watchdog_init or AVR will go into emergency procedures.
+ void MarlinHAL::watchdog_refresh() { wdt_reset(); }
+
+#endif // USE_WATCHDOG
+
+// ------------------------
+// Free Memory Accessor
+// ------------------------
+
#if ENABLED(SDSUPPORT)
#include "../../sd/SdFatUtil.h"
@@ -58,20 +152,20 @@ void HAL_init() {
#else // !SDSUPPORT
-extern "C" {
- extern char __bss_end;
- extern char __heap_start;
- extern void* __brkval;
-
- int freeMemory() {
- int free_memory;
- if ((int)__brkval == 0)
- free_memory = ((int)&free_memory) - ((int)&__bss_end);
- else
- free_memory = ((int)&free_memory) - ((int)__brkval);
- return free_memory;
+ extern "C" {
+ extern char __bss_end;
+ extern char __heap_start;
+ extern void* __brkval;
+
+ int freeMemory() {
+ int free_memory;
+ if ((int)__brkval == 0)
+ free_memory = ((int)&free_memory) - ((int)&__bss_end);
+ else
+ free_memory = ((int)&free_memory) - ((int)__brkval);
+ return free_memory;
+ }
}
-}
#endif // !SDSUPPORT
diff --git a/Marlin/src/HAL/AVR/HAL.h b/Marlin/src/HAL/AVR/HAL.h
index ce15ed29fb3a..149186772158 100644
--- a/Marlin/src/HAL/AVR/HAL.h
+++ b/Marlin/src/HAL/AVR/HAL.h
@@ -19,16 +19,18 @@
*/
#pragma once
+/**
+ * HAL for Arduino AVR
+ */
+
#include "../shared/Marduino.h"
#include "../shared/HAL_SPI.h"
#include "fastio.h"
-#include "watchdog.h"
#include "math.h"
#ifdef USBCON
#include
#else
- #define HardwareSerial_h // Hack to prevent HardwareSerial.h header inclusion
#include "MarlinSerial.h"
#endif
@@ -39,6 +41,19 @@
#include
#include
+//
+// Default graphical display delays
+//
+#if F_CPU >= 20000000
+ #define CPU_ST7920_DELAY_1 150
+ #define CPU_ST7920_DELAY_2 0
+ #define CPU_ST7920_DELAY_3 150
+#elif F_CPU == 16000000
+ #define CPU_ST7920_DELAY_1 125
+ #define CPU_ST7920_DELAY_2 0
+ #define CPU_ST7920_DELAY_3 188
+#endif
+
#ifndef pgm_read_ptr
// Compatibility for avr-libc 1.8.0-4.1 included with Ubuntu for
// Windows Subsystem for Linux on Windows 10 as of 10/18/2019
@@ -61,9 +76,9 @@
#define CRITICAL_SECTION_START() unsigned char _sreg = SREG; cli()
#define CRITICAL_SECTION_END() SREG = _sreg
#endif
-#define ISRS_ENABLED() TEST(SREG, SREG_I)
-#define ENABLE_ISRS() sei()
-#define DISABLE_ISRS() cli()
+
+#define HAL_CAN_SET_PWM_FREQ // This HAL supports PWM Frequency adjustment
+#define PWM_FREQUENCY 1000 // Default PWM frequency when set_pwm_duty() is called without set_pwm_frequency()
// ------------------------
// Types
@@ -71,35 +86,56 @@
typedef int8_t pin_t;
-#define SHARED_SERVOS HAS_SERVOS
-#define HAL_SERVO_LIB Servo
+#define SHARED_SERVOS HAS_SERVOS // Use shared/servos.cpp
+
+class Servo;
+typedef Servo hal_servo_t;
// ------------------------
-// Public Variables
+// Serial ports
// ------------------------
-//extern uint8_t MCUSR;
-
-// Serial ports
#ifdef USBCON
- #define MYSERIAL0 TERN(BLUETOOTH, bluetoothSerial, Serial)
+ #include "../../core/serial_hook.h"
+ typedef ForwardSerial1Class< decltype(Serial) > DefaultSerial1;
+ extern DefaultSerial1 MSerial0;
+ #ifdef BLUETOOTH
+ typedef ForwardSerial1Class< decltype(bluetoothSerial) > BTSerial;
+ extern BTSerial btSerial;
+ #endif
+
+ #define MYSERIAL1 TERN(BLUETOOTH, btSerial, MSerial0)
#else
#if !WITHIN(SERIAL_PORT, -1, 3)
- #error "SERIAL_PORT must be from -1 to 3. Please update your configuration."
+ #error "SERIAL_PORT must be from 0 to 3, or -1 for USB Serial."
#endif
- #define MYSERIAL0 customizedSerial1
+ #define MYSERIAL1 customizedSerial1
#ifdef SERIAL_PORT_2
#if !WITHIN(SERIAL_PORT_2, -1, 3)
- #error "SERIAL_PORT_2 must be from -1 to 3. Please update your configuration."
+ #error "SERIAL_PORT_2 must be from 0 to 3, or -1 for USB Serial."
#endif
- #define MYSERIAL1 customizedSerial2
+ #define MYSERIAL2 customizedSerial2
+ #endif
+
+ #ifdef SERIAL_PORT_3
+ #if !WITHIN(SERIAL_PORT_3, -1, 3)
+ #error "SERIAL_PORT_3 must be from 0 to 3, or -1 for USB Serial."
+ #endif
+ #define MYSERIAL3 customizedSerial3
#endif
#endif
+#ifdef MMU2_SERIAL_PORT
+ #if !WITHIN(MMU2_SERIAL_PORT, -1, 3)
+ #error "MMU2_SERIAL_PORT must be from 0 to 3, or -1 for USB Serial."
+ #endif
+ #define MMU2_SERIAL mmuSerial
+#endif
+
#ifdef LCD_SERIAL_PORT
#if !WITHIN(LCD_SERIAL_PORT, -1, 3)
- #error "LCD_SERIAL_PORT must be from -1 to 3. Please update your configuration."
+ #error "LCD_SERIAL_PORT must be from 0 to 3, or -1 for USB Serial."
#endif
#define LCD_SERIAL lcdSerial
#if HAS_DGUS_LCD
@@ -107,85 +143,135 @@ typedef int8_t pin_t;
#endif
#endif
-// ------------------------
-// Public functions
-// ------------------------
+//
+// ADC
+//
+#define HAL_ADC_VREF 5.0
+#define HAL_ADC_RESOLUTION 10
-void HAL_init();
+//
+// Pin Mapping for M42, M43, M226
+//
+#define GET_PIN_MAP_PIN(index) index
+#define GET_PIN_MAP_INDEX(pin) pin
+#define PARSED_PIN_INDEX(code, dval) parser.intval(code, dval)
-//void cli();
+#define HAL_SENSITIVE_PINS 0, 1,
-//void _delay_ms(const int delay);
+#ifdef __AVR_AT90USB1286__
+ #define JTAG_DISABLE() do{ MCUCR = 0x80; MCUCR = 0x80; }while(0)
+#endif
-inline void HAL_clear_reset_source() { MCUSR = 0; }
-inline uint8_t HAL_get_reset_source() { return MCUSR; }
+// AVR compatibility
+#define strtof strtod
-inline void HAL_reboot() {} // reboot the board or restart the bootloader
+// ------------------------
+// Free Memory Accessor
+// ------------------------
#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-function"
-extern "C" {
- int freeMemory();
-}
+#if GCC_VERSION <= 50000
+ #pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+
+extern "C" int freeMemory();
+
#pragma GCC diagnostic pop
-// ADC
-#ifdef DIDR2
- #define HAL_ANALOG_SELECT(ind) do{ if (ind < 8) SBI(DIDR0, ind); else SBI(DIDR2, ind & 0x07); }while(0)
-#else
- #define HAL_ANALOG_SELECT(ind) SBI(DIDR0, ind);
-#endif
+// ------------------------
+// MarlinHAL Class
+// ------------------------
-inline void HAL_adc_init() {
- ADCSRA = _BV(ADEN) | _BV(ADSC) | _BV(ADIF) | 0x07;
- DIDR0 = 0;
- #ifdef DIDR2
- DIDR2 = 0;
- #endif
-}
+class MarlinHAL {
+public:
-#define SET_ADMUX_ADCSRA(ch) ADMUX = _BV(REFS0) | (ch & 0x07); SBI(ADCSRA, ADSC)
-#ifdef MUX5
- #define HAL_START_ADC(ch) if (ch > 7) ADCSRB = _BV(MUX5); else ADCSRB = 0; SET_ADMUX_ADCSRA(ch)
-#else
- #define HAL_START_ADC(ch) ADCSRB = 0; SET_ADMUX_ADCSRA(ch)
-#endif
+ // Earliest possible init, before setup()
+ MarlinHAL() {}
-#define HAL_ADC_VREF 5.0
-#define HAL_ADC_RESOLUTION 10
-#define HAL_READ_ADC() ADC
-#define HAL_ADC_READY() !TEST(ADCSRA, ADSC)
+ // Watchdog
+ static void watchdog_init() IF_DISABLED(USE_WATCHDOG, {});
+ static void watchdog_refresh() IF_DISABLED(USE_WATCHDOG, {});
-#define GET_PIN_MAP_PIN(index) index
-#define GET_PIN_MAP_INDEX(pin) pin
-#define PARSED_PIN_INDEX(code, dval) parser.intval(code, dval)
+ static void init(); // Called early in setup()
+ static void init_board() {} // Called less early in setup()
+ static void reboot(); // Restart the firmware from 0x0
-#define HAL_SENSITIVE_PINS 0, 1
+ // Interrupts
+ static bool isr_state() { return TEST(SREG, SREG_I); }
+ static void isr_on() { sei(); }
+ static void isr_off() { cli(); }
-#ifdef __AVR_AT90USB1286__
- #define JTAG_DISABLE() do{ MCUCR = 0x80; MCUCR = 0x80; }while(0)
-#endif
+ static void delay_ms(const int ms) { _delay_ms(ms); }
-// AVR compatibility
-#define strtof strtod
+ // Tasks, called from idle()
+ static void idletask() {}
-#define HAL_CAN_SET_PWM_FREQ // This HAL supports PWM Frequency adjustment
+ // Reset
+ static uint8_t reset_reason;
+ static uint8_t get_reset_source() { return reset_reason; }
+ static void clear_reset_source() { MCUSR = 0; }
-/**
- * set_pwm_frequency
- * Sets the frequency of the timer corresponding to the provided pin
- * as close as possible to the provided desired frequency. Internally
- * calculates the required waveform generation mode, prescaler and
- * resolution values required and sets the timer registers accordingly.
- * NOTE that the frequency is applied to all pins on the timer (Ex OC3A, OC3B and OC3B)
- * NOTE that there are limitations, particularly if using TIMER2. (see Configuration_adv.h -> FAST FAN PWM Settings)
- */
-void set_pwm_frequency(const pin_t pin, int f_desired);
+ // Free SRAM
+ static int freeMemory() { return ::freeMemory(); }
-/**
- * set_pwm_duty
- * Sets the PWM duty cycle of the provided pin to the provided value
- * Optionally allows inverting the duty cycle [default = false]
- * Optionally allows changing the maximum size of the provided value to enable finer PWM duty control [default = 255]
- */
-void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size=255, const bool invert=false);
+ //
+ // ADC Methods
+ //
+
+ // Called by Temperature::init once at startup
+ static void adc_init() {
+ ADCSRA = _BV(ADEN) | _BV(ADSC) | _BV(ADIF) | 0x07;
+ DIDR0 = 0;
+ #ifdef DIDR2
+ DIDR2 = 0;
+ #endif
+ }
+
+ // Called by Temperature::init for each sensor at startup
+ static void adc_enable(const uint8_t ch) {
+ #ifdef DIDR2
+ if (ch > 7) { SBI(DIDR2, ch & 0x07); return; }
+ #endif
+ SBI(DIDR0, ch);
+ }
+
+ // Begin ADC sampling on the given channel. Called from Temperature::isr!
+ static void adc_start(const uint8_t ch) {
+ #ifdef MUX5
+ ADCSRB = ch > 7 ? _BV(MUX5) : 0;
+ #else
+ ADCSRB = 0;
+ #endif
+ ADMUX = _BV(REFS0) | (ch & 0x07);
+ SBI(ADCSRA, ADSC);
+ }
+
+ // Is the ADC ready for reading?
+ static bool adc_ready() { return !TEST(ADCSRA, ADSC); }
+
+ // The current value of the ADC register
+ static __typeof__(ADC) adc_value() { return ADC; }
+
+ /**
+ * init_pwm_timers
+ * Set the default frequency for timers 2-5 to 1000HZ
+ */
+ static void init_pwm_timers();
+
+ /**
+ * Set the PWM duty cycle for the pin to the given value.
+ * Optionally invert the duty cycle [default = false]
+ * Optionally change the scale of the provided value to enable finer PWM duty control [default = 255]
+ */
+ static void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size=255, const bool invert=false);
+
+ /**
+ * Set the frequency of the timer for the given pin as close as
+ * possible to the provided desired frequency. Internally calculate
+ * the required waveform generation mode, prescaler, and resolution
+ * values and set timer registers accordingly.
+ * NOTE that the frequency is applied to all pins on the timer (Ex OC3A, OC3B and OC3B)
+ * NOTE that there are limitations, particularly if using TIMER2. (see Configuration_adv.h -> FAST_PWM_FAN Settings)
+ */
+ static void set_pwm_frequency(const pin_t pin, const uint16_t f_desired);
+};
diff --git a/Marlin/src/HAL/AVR/HAL_SPI.cpp b/Marlin/src/HAL/AVR/HAL_SPI.cpp
index 31e589746cf2..dc98f2f79e71 100644
--- a/Marlin/src/HAL/AVR/HAL_SPI.cpp
+++ b/Marlin/src/HAL/AVR/HAL_SPI.cpp
@@ -34,21 +34,21 @@
#include "../../inc/MarlinConfig.h"
void spiBegin() {
- OUT_WRITE(SS_PIN, HIGH);
- SET_OUTPUT(SCK_PIN);
- SET_INPUT(MISO_PIN);
- SET_OUTPUT(MOSI_PIN);
-
- #if DISABLED(SOFTWARE_SPI)
- // SS must be in output mode even it is not chip select
- //SET_OUTPUT(SS_PIN);
- // set SS high - may be chip select for another SPI device
- //#if SET_SPI_SS_HIGH
- //WRITE(SS_PIN, HIGH);
- //#endif
- // set a default rate
- spiInit(1);
+ #if PIN_EXISTS(SD_SS)
+ // Do not init HIGH for boards with pin 4 used as Fans or Heaters or otherwise, not likely to have multiple SPI devices anyway.
+ #if defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) || defined(__AVR_ATmega1284P__)
+ // SS must be in output mode even it is not chip select
+ SET_OUTPUT(SD_SS_PIN);
+ #else
+ // set SS high - may be chip select for another SPI device
+ OUT_WRITE(SD_SS_PIN, HIGH);
+ #endif
#endif
+ SET_OUTPUT(SD_SCK_PIN);
+ SET_INPUT(SD_MISO_PIN);
+ SET_OUTPUT(SD_MOSI_PIN);
+
+ IF_DISABLED(SOFTWARE_SPI, spiInit(SPI_HALF_SPEED));
}
#if NONE(SOFTWARE_SPI, FORCE_SOFT_SPI)
@@ -74,7 +74,8 @@ void spiBegin() {
#elif defined(PRR0)
PRR0
#endif
- , PRSPI);
+ , PRSPI
+ );
SPCR = _BV(SPE) | _BV(MSTR) | (spiRate >> 1);
SPSR = spiRate & 1 || spiRate == 6 ? 0 : _BV(SPI2X);
@@ -88,7 +89,7 @@ void spiBegin() {
}
/** SPI read data */
- void spiRead(uint8_t* buf, uint16_t nbyte) {
+ void spiRead(uint8_t *buf, uint16_t nbyte) {
if (nbyte-- == 0) return;
SPDR = 0xFF;
for (uint16_t i = 0; i < nbyte; i++) {
@@ -107,7 +108,7 @@ void spiBegin() {
}
/** SPI send block */
- void spiSendBlock(uint8_t token, const uint8_t* buf) {
+ void spiSendBlock(uint8_t token, const uint8_t *buf) {
SPDR = token;
for (uint16_t i = 0; i < 512; i += 2) {
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
@@ -195,19 +196,19 @@ void spiBegin() {
// no interrupts during byte receive - about 8µs
cli();
// output pin high - like sending 0xFF
- WRITE(MOSI_PIN, HIGH);
+ WRITE(SD_MOSI_PIN, HIGH);
LOOP_L_N(i, 8) {
- WRITE(SCK_PIN, HIGH);
+ WRITE(SD_SCK_PIN, HIGH);
nop; // adjust so SCK is nice
nop;
data <<= 1;
- if (READ(MISO_PIN)) data |= 1;
+ if (READ(SD_MISO_PIN)) data |= 1;
- WRITE(SCK_PIN, LOW);
+ WRITE(SD_SCK_PIN, LOW);
}
sei();
@@ -215,7 +216,7 @@ void spiBegin() {
}
// Soft SPI read data
- void spiRead(uint8_t* buf, uint16_t nbyte) {
+ void spiRead(uint8_t *buf, uint16_t nbyte) {
for (uint16_t i = 0; i < nbyte; i++)
buf[i] = spiRec();
}
@@ -225,10 +226,10 @@ void spiBegin() {
// no interrupts during byte send - about 8µs
cli();
LOOP_L_N(i, 8) {
- WRITE(SCK_PIN, LOW);
- WRITE(MOSI_PIN, data & 0x80);
+ WRITE(SD_SCK_PIN, LOW);
+ WRITE(SD_MOSI_PIN, data & 0x80);
data <<= 1;
- WRITE(SCK_PIN, HIGH);
+ WRITE(SD_SCK_PIN, HIGH);
}
nop; // hold SCK high for a few ns
@@ -236,13 +237,13 @@ void spiBegin() {
nop;
nop;
- WRITE(SCK_PIN, LOW);
+ WRITE(SD_SCK_PIN, LOW);
sei();
}
// Soft SPI send block
- void spiSendBlock(uint8_t token, const uint8_t* buf) {
+ void spiSendBlock(uint8_t token, const uint8_t *buf) {
spiSend(token);
for (uint16_t i = 0; i < 512; i++)
spiSend(buf[i]);
diff --git a/Marlin/src/HAL/AVR/MarlinSPI.h b/Marlin/src/HAL/AVR/MarlinSPI.h
new file mode 100644
index 000000000000..0c447ba4cb3d
--- /dev/null
+++ b/Marlin/src/HAL/AVR/MarlinSPI.h
@@ -0,0 +1,26 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#pragma once
+
+#include
+
+using MarlinSPI = SPIClass;
diff --git a/Marlin/src/HAL/AVR/MarlinSerial.cpp b/Marlin/src/HAL/AVR/MarlinSerial.cpp
index 63599efd4132..986462437c8f 100644
--- a/Marlin/src/HAL/AVR/MarlinSerial.cpp
+++ b/Marlin/src/HAL/AVR/MarlinSerial.cpp
@@ -486,7 +486,7 @@ void MarlinSerial::write(const uint8_t c) {
const uint8_t i = (tx_buffer.head + 1) & (Cfg::TX_SIZE - 1);
// If global interrupts are disabled (as the result of being called from an ISR)...
- if (!ISRS_ENABLED()) {
+ if (!hal.isr_state()) {
// Make room by polling if it is possible to transmit, and do so!
while (i == tx_buffer.tail) {
@@ -534,7 +534,7 @@ void MarlinSerial::flushTX() {
if (!_written) return;
// If global interrupts are disabled (as the result of being called from an ISR)...
- if (!ISRS_ENABLED()) {
+ if (!hal.isr_state()) {
// Wait until everything was transmitted - We must do polling, as interrupts are disabled
while (tx_buffer.head != tx_buffer.tail || !B_TXC) {
@@ -556,161 +556,6 @@ void MarlinSerial::flushTX() {
}
}
-/**
- * Imports from print.h
- */
-
-template
-void MarlinSerial::print(char c, int base) {
- print((long)c, base);
-}
-
-template
-void MarlinSerial::print(unsigned char b, int base) {
- print((unsigned long)b, base);
-}
-
-template
-void MarlinSerial::print(int n, int base) {
- print((long)n, base);
-}
-
-template
-void MarlinSerial::print(unsigned int n, int base) {
- print((unsigned long)n, base);
-}
-
-template
-void MarlinSerial::print(long n, int base) {
- if (base == 0) write(n);
- else if (base == 10) {
- if (n < 0) { print('-'); n = -n; }
- printNumber(n, 10);
- }
- else
- printNumber(n, base);
-}
-
-template
-void MarlinSerial::print(unsigned long n, int base) {
- if (base == 0) write(n);
- else printNumber(n, base);
-}
-
-template
-void MarlinSerial::print(double n, int digits) {
- printFloat(n, digits);
-}
-
-template
-void MarlinSerial::println() {
- print('\r');
- print('\n');
-}
-
-template
-void MarlinSerial::println(const String& s) {
- print(s);
- println();
-}
-
-template
-void MarlinSerial::println(const char c[]) {
- print(c);
- println();
-}
-
-template
-void MarlinSerial::println(char c, int base) {
- print(c, base);
- println();
-}
-
-template
-void MarlinSerial::println(unsigned char b, int base) {
- print(b, base);
- println();
-}
-
-template
-void MarlinSerial::println(int n, int base) {
- print(n, base);
- println();
-}
-
-template
-void MarlinSerial::println(unsigned int n, int base) {
- print(n, base);
- println();
-}
-
-template
-void MarlinSerial::println(long n, int base) {
- print(n, base);
- println();
-}
-
-template
-void MarlinSerial::println(unsigned long n, int base) {
- print(n, base);
- println();
-}
-
-template
-void MarlinSerial::println(double n, int digits) {
- print(n, digits);
- println();
-}
-
-// Private Methods
-
-template
-void MarlinSerial::printNumber(unsigned long n, uint8_t base) {
- if (n) {
- unsigned char buf[8 * sizeof(long)]; // Enough space for base 2
- int8_t i = 0;
- while (n) {
- buf[i++] = n % base;
- n /= base;
- }
- while (i--)
- print((char)(buf[i] + (buf[i] < 10 ? '0' : 'A' - 10)));
- }
- else
- print('0');
-}
-
-template
-void MarlinSerial::printFloat(double number, uint8_t digits) {
- // Handle negative numbers
- if (number < 0.0) {
- print('-');
- number = -number;
- }
-
- // Round correctly so that print(1.999, 2) prints as "2.00"
- double rounding = 0.5;
- LOOP_L_N(i, digits) rounding *= 0.1;
- number += rounding;
-
- // Extract the integer part of the number and print it
- unsigned long int_part = (unsigned long)number;
- double remainder = number - (double)int_part;
- print(int_part);
-
- // Print the decimal point, but only if there are digits beyond
- if (digits) {
- print('.');
- // Extract digits from the remainder one at a time
- while (digits--) {
- remainder *= 10.0;
- int toPrint = int(remainder);
- print(toPrint);
- remainder -= toPrint;
- }
- }
-}
-
// Hookup ISR handlers
ISR(SERIAL_REGNAME(USART, SERIAL_PORT, _RX_vect)) {
MarlinSerial>::store_rxd_char();
@@ -720,11 +565,9 @@ ISR(SERIAL_REGNAME(USART, SERIAL_PORT, _UDRE_vect)) {
MarlinSerial>::_tx_udr_empty_irq();
}
-// Preinstantiate
-template class MarlinSerial>;
-
-// Instantiate
-MarlinSerial> customizedSerial1;
+// Because of the template definition above, it's required to instantiate the template to have all methods generated
+template class MarlinSerial< MarlinSerialCfg >;
+MSerialT1 customizedSerial1(MSerialT1::HasEmergencyParser);
#ifdef SERIAL_PORT_2
@@ -737,13 +580,26 @@ MarlinSerial> customizedSerial1;
MarlinSerial>::_tx_udr_empty_irq();
}
- // Preinstantiate
- template class MarlinSerial>;
+ template class MarlinSerial< MarlinSerialCfg >;
+ MSerialT2 customizedSerial2(MSerialT2::HasEmergencyParser);
- // Instantiate
- MarlinSerial> customizedSerial2;
+#endif // SERIAL_PORT_2
-#endif
+#ifdef SERIAL_PORT_3
+
+ // Hookup ISR handlers
+ ISR(SERIAL_REGNAME(USART, SERIAL_PORT_3, _RX_vect)) {
+ MarlinSerial>::store_rxd_char();
+ }
+
+ ISR(SERIAL_REGNAME(USART, SERIAL_PORT_3, _UDRE_vect)) {
+ MarlinSerial>::_tx_udr_empty_irq();
+ }
+
+ template class MarlinSerial< MarlinSerialCfg >;
+ MSerialT3 customizedSerial3(MSerialT3::HasEmergencyParser);
+
+#endif // SERIAL_PORT_3
#ifdef MMU2_SERIAL_PORT
@@ -755,13 +611,10 @@ MarlinSerial> customizedSerial1;
MarlinSerial>::_tx_udr_empty_irq();
}
- // Preinstantiate
- template class MarlinSerial>;
-
- // Instantiate
- MarlinSerial> mmuSerial;
+ template class MarlinSerial< MMU2SerialCfg >;
+ MSerialMMU2 mmuSerial(MSerialMMU2::HasEmergencyParser);
-#endif
+#endif // MMU2_SERIAL_PORT
#ifdef LCD_SERIAL_PORT
@@ -773,11 +626,8 @@ MarlinSerial> customizedSerial1;
MarlinSerial>::_tx_udr_empty_irq();
}
- // Preinstantiate
- template class MarlinSerial>;
-
- // Instantiate
- MarlinSerial> lcdSerial;
+ template class MarlinSerial< LCDSerialCfg >;
+ MSerialLCD lcdSerial(MSerialLCD::HasEmergencyParser);
#if HAS_DGUS_LCD
template
@@ -790,13 +640,13 @@ MarlinSerial> customizedSerial1;
}
#endif
-#endif
+#endif // LCD_SERIAL_PORT
#endif // !USBCON && (UBRRH || UBRR0H || UBRR1H || UBRR2H || UBRR3H)
// For AT90USB targets use the UART for BT interfacing
#if defined(USBCON) && ENABLED(BLUETOOTH)
- HardwareSerial bluetoothSerial;
+ MSerialBT bluetoothSerial(false);
#endif
#endif // __AVR__
diff --git a/Marlin/src/HAL/AVR/MarlinSerial.h b/Marlin/src/HAL/AVR/MarlinSerial.h
index 8a0423d143d8..7eb76000d66e 100644
--- a/Marlin/src/HAL/AVR/MarlinSerial.h
+++ b/Marlin/src/HAL/AVR/MarlinSerial.h
@@ -34,6 +34,7 @@
#include
#include "../../inc/MarlinConfigPre.h"
+#include "../../core/serial_hook.h"
#ifndef SERIAL_PORT
#define SERIAL_PORT 0
@@ -135,10 +136,6 @@
UART_DECL(3);
#endif
- #define DEC 10
- #define HEX 16
- #define OCT 8
- #define BIN 2
#define BYTE 0
// Templated type selector
@@ -194,68 +191,38 @@
rx_framing_errors;
static ring_buffer_pos_t rx_max_enqueued;
- static FORCE_INLINE ring_buffer_pos_t atomic_read_rx_head();
+ FORCE_INLINE static ring_buffer_pos_t atomic_read_rx_head();
static volatile bool rx_tail_value_not_stable;
static volatile uint16_t rx_tail_value_backup;
- static FORCE_INLINE void atomic_set_rx_tail(ring_buffer_pos_t value);
- static FORCE_INLINE ring_buffer_pos_t atomic_read_rx_tail();
-
- public:
+ FORCE_INLINE static void atomic_set_rx_tail(ring_buffer_pos_t value);
+ FORCE_INLINE static ring_buffer_pos_t atomic_read_rx_tail();
+ public:
FORCE_INLINE static void store_rxd_char();
FORCE_INLINE static void _tx_udr_empty_irq();
- public:
- MarlinSerial() {};
- static void begin(const long);
- static void end();
- static int peek();
- static int read();
- static void flush();
- static ring_buffer_pos_t available();
- static void write(const uint8_t c);
- static void flushTX();
- #if HAS_DGUS_LCD
- static ring_buffer_pos_t get_tx_buffer_free();
- #endif
-
- static inline bool emergency_parser_enabled() { return Cfg::EMERGENCYPARSER; }
-
- FORCE_INLINE static uint8_t dropped() { return Cfg::DROPPED_RX ? rx_dropped_bytes : 0; }
- FORCE_INLINE static uint8_t buffer_overruns() { return Cfg::RX_OVERRUNS ? rx_buffer_overruns : 0; }
- FORCE_INLINE static uint8_t framing_errors() { return Cfg::RX_FRAMING_ERRORS ? rx_framing_errors : 0; }
- FORCE_INLINE static ring_buffer_pos_t rxMaxEnqueued() { return Cfg::MAX_RX_QUEUED ? rx_max_enqueued : 0; }
-
- FORCE_INLINE static void write(const char* str) { while (*str) write(*str++); }
- FORCE_INLINE static void write(const uint8_t* buffer, size_t size) { while (size--) write(*buffer++); }
- FORCE_INLINE static void print(const String& s) { for (int i = 0; i < (int)s.length(); i++) write(s[i]); }
- FORCE_INLINE static void print(const char* str) { write(str); }
-
- static void print(char, int = BYTE);
- static void print(unsigned char, int = BYTE);
- static void print(int, int = DEC);
- static void print(unsigned int, int = DEC);
- static void print(long, int = DEC);
- static void print(unsigned long, int = DEC);
- static void print(double, int = 2);
-
- static void println(const String& s);
- static void println(const char[]);
- static void println(char, int = BYTE);
- static void println(unsigned char, int = BYTE);
- static void println(int, int = DEC);
- static void println(unsigned int, int = DEC);
- static void println(long, int = DEC);
- static void println(unsigned long, int = DEC);
- static void println(double, int = 2);
- static void println();
- operator bool() { return true; }
-
- private:
- static void printNumber(unsigned long, const uint8_t);
- static void printFloat(double, uint8_t);
+ public:
+ static void begin(const long);
+ static void end();
+ static int peek();
+ static int read();
+ static void flush();
+ static ring_buffer_pos_t available();
+ static void write(const uint8_t c);
+ static void flushTX();
+ #if HAS_DGUS_LCD
+ static ring_buffer_pos_t get_tx_buffer_free();
+ #endif
+
+ enum { HasEmergencyParser = Cfg::EMERGENCYPARSER };
+ static bool emergency_parser_enabled() { return Cfg::EMERGENCYPARSER; }
+
+ FORCE_INLINE static uint8_t dropped() { return Cfg::DROPPED_RX ? rx_dropped_bytes : 0; }
+ FORCE_INLINE static uint8_t buffer_overruns() { return Cfg::RX_OVERRUNS ? rx_buffer_overruns : 0; }
+ FORCE_INLINE static uint8_t framing_errors() { return Cfg::RX_FRAMING_ERRORS ? rx_framing_errors : 0; }
+ FORCE_INLINE static ring_buffer_pos_t rxMaxEnqueued() { return Cfg::MAX_RX_QUEUED ? rx_max_enqueued : 0; }
};
template
@@ -270,12 +237,18 @@
static constexpr bool RX_FRAMING_ERRORS = ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS);
static constexpr bool MAX_RX_QUEUED = ENABLED(SERIAL_STATS_MAX_RX_QUEUED);
};
- extern MarlinSerial> customizedSerial1;
- #ifdef SERIAL_PORT_2
+ typedef Serial1Class< MarlinSerial< MarlinSerialCfg > > MSerialT1;
+ extern MSerialT1 customizedSerial1;
- extern MarlinSerial> customizedSerial2;
+ #ifdef SERIAL_PORT_2
+ typedef Serial1Class< MarlinSerial< MarlinSerialCfg > > MSerialT2;
+ extern MSerialT2 customizedSerial2;
+ #endif
+ #ifdef SERIAL_PORT_3
+ typedef Serial1Class< MarlinSerial< MarlinSerialCfg > > MSerialT3;
+ extern MSerialT3 customizedSerial3;
#endif
#endif // !USBCON
@@ -284,49 +257,41 @@
template
struct MMU2SerialCfg {
static constexpr int PORT = serial;
+ static constexpr unsigned int RX_SIZE = 32;
+ static constexpr unsigned int TX_SIZE = 32;
static constexpr bool XONOFF = false;
static constexpr bool EMERGENCYPARSER = false;
static constexpr bool DROPPED_RX = false;
static constexpr bool RX_FRAMING_ERRORS = false;
static constexpr bool MAX_RX_QUEUED = false;
- static constexpr unsigned int RX_SIZE = 32;
- static constexpr unsigned int TX_SIZE = 32;
static constexpr bool RX_OVERRUNS = false;
};
- extern MarlinSerial> mmuSerial;
+ typedef Serial1Class< MarlinSerial< MMU2SerialCfg > > MSerialMMU2;
+ extern MSerialMMU2 mmuSerial;
#endif
#ifdef LCD_SERIAL_PORT
template
struct LCDSerialCfg {
- static constexpr int PORT = serial;
- static constexpr bool XONOFF = false;
- static constexpr bool EMERGENCYPARSER = ENABLED(EMERGENCY_PARSER);
- static constexpr bool DROPPED_RX = false;
- static constexpr bool RX_FRAMING_ERRORS = false;
- static constexpr bool MAX_RX_QUEUED = false;
- #if HAS_DGUS_LCD
- static constexpr unsigned int RX_SIZE = DGUS_RX_BUFFER_SIZE;
- static constexpr unsigned int TX_SIZE = DGUS_TX_BUFFER_SIZE;
- static constexpr bool RX_OVERRUNS = ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS);
- #elif EITHER(ANYCUBIC_LCD_I3MEGA, ANYCUBIC_LCD_CHIRON)
- static constexpr unsigned int RX_SIZE = 64;
- static constexpr unsigned int TX_SIZE = 128;
- static constexpr bool RX_OVERRUNS = false;
- #else
- static constexpr unsigned int RX_SIZE = 64;
- static constexpr unsigned int TX_SIZE = 128;
- static constexpr bool RX_OVERRUNS = false
- #endif
+ static constexpr int PORT = serial;
+ static constexpr unsigned int RX_SIZE = TERN(HAS_DGUS_LCD, DGUS_RX_BUFFER_SIZE, 64);
+ static constexpr unsigned int TX_SIZE = TERN(HAS_DGUS_LCD, DGUS_TX_BUFFER_SIZE, 128);
+ static constexpr bool XONOFF = false;
+ static constexpr bool EMERGENCYPARSER = ENABLED(EMERGENCY_PARSER);
+ static constexpr bool DROPPED_RX = false;
+ static constexpr bool RX_FRAMING_ERRORS = false;
+ static constexpr bool MAX_RX_QUEUED = false;
+ static constexpr bool RX_OVERRUNS = BOTH(HAS_DGUS_LCD, SERIAL_STATS_RX_BUFFER_OVERRUNS);
};
- extern MarlinSerial> lcdSerial;
-
+ typedef Serial1Class< MarlinSerial< LCDSerialCfg > > MSerialLCD;
+ extern MSerialLCD lcdSerial;
#endif
// Use the UART for Bluetooth in AT90USB configurations
#if defined(USBCON) && ENABLED(BLUETOOTH)
- extern HardwareSerial bluetoothSerial;
+ typedef Serial1Class MSerialBT;
+ extern MSerialBT bluetoothSerial;
#endif
diff --git a/Marlin/src/HAL/AVR/Servo.cpp b/Marlin/src/HAL/AVR/Servo.cpp
index 526352b77339..0a1ef5337ae9 100644
--- a/Marlin/src/HAL/AVR/Servo.cpp
+++ b/Marlin/src/HAL/AVR/Servo.cpp
@@ -66,27 +66,26 @@ static volatile int8_t Channel[_Nbr_16timers]; // counter for the s
/************ static functions common to all instances ***********************/
-static inline void handle_interrupts(timer16_Sequence_t timer, volatile uint16_t* TCNTn, volatile uint16_t* OCRnA) {
- if (Channel[timer] < 0)
- *TCNTn = 0; // channel set to -1 indicated that refresh interval completed so reset the timer
- else {
- if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && SERVO(timer, Channel[timer]).Pin.isActive)
- extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, LOW); // pulse this channel low if activated
- }
-
- Channel[timer]++; // increment to the next channel
- if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) {
- *OCRnA = *TCNTn + SERVO(timer, Channel[timer]).ticks;
- if (SERVO(timer, Channel[timer]).Pin.isActive) // check if activated
- extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, HIGH); // it's an active channel so pulse it high
+static inline void handle_interrupts(const timer16_Sequence_t timer, volatile uint16_t* TCNTn, volatile uint16_t* OCRnA) {
+ int8_t cho = Channel[timer]; // Handle the prior Channel[timer] first
+ if (cho < 0) // Channel -1 indicates the refresh interval completed...
+ *TCNTn = 0; // ...so reset the timer
+ else if (SERVO_INDEX(timer, cho) < ServoCount) // prior channel handled?
+ extDigitalWrite(SERVO(timer, cho).Pin.nbr, LOW); // pulse the prior channel LOW
+
+ Channel[timer] = ++cho; // Handle the next channel (or 0)
+ if (cho < SERVOS_PER_TIMER && SERVO_INDEX(timer, cho) < ServoCount) {
+ *OCRnA = *TCNTn + SERVO(timer, cho).ticks; // set compare to current ticks plus duration
+ if (SERVO(timer, cho).Pin.isActive) // activated?
+ extDigitalWrite(SERVO(timer, cho).Pin.nbr, HIGH); // yes: pulse HIGH
}
else {
// finished all channels so wait for the refresh period to expire before starting over
- if (((unsigned)*TCNTn) + 4 < usToTicks(REFRESH_INTERVAL)) // allow a few ticks to ensure the next OCR1A not missed
- *OCRnA = (unsigned int)usToTicks(REFRESH_INTERVAL);
- else
- *OCRnA = *TCNTn + 4; // at least REFRESH_INTERVAL has elapsed
- Channel[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel
+ const unsigned int cval = ((unsigned)*TCNTn) + 32 / (SERVO_TIMER_PRESCALER), // allow 32 cycles to ensure the next OCR1A not missed
+ ival = (unsigned int)usToTicks(REFRESH_INTERVAL); // at least REFRESH_INTERVAL has elapsed
+ *OCRnA = max(cval, ival);
+
+ Channel[timer] = -1; // reset the timer counter to 0 on the next call
}
}
@@ -123,91 +122,102 @@ static inline void handle_interrupts(timer16_Sequence_t timer, volatile uint16_t
/****************** end of static functions ******************************/
-void initISR(timer16_Sequence_t timer) {
- #ifdef _useTimer1
- if (timer == _timer1) {
- TCCR1A = 0; // normal counting mode
- TCCR1B = _BV(CS11); // set prescaler of 8
- TCNT1 = 0; // clear the timer count
- #if defined(__AVR_ATmega8__) || defined(__AVR_ATmega128__)
- SBI(TIFR, OCF1A); // clear any pending interrupts;
- SBI(TIMSK, OCIE1A); // enable the output compare interrupt
- #else
- // here if not ATmega8 or ATmega128
- SBI(TIFR1, OCF1A); // clear any pending interrupts;
- SBI(TIMSK1, OCIE1A); // enable the output compare interrupt
- #endif
- #ifdef WIRING
- timerAttach(TIMER1OUTCOMPAREA_INT, Timer1Service);
- #endif
- }
- #endif
-
- #ifdef _useTimer3
- if (timer == _timer3) {
- TCCR3A = 0; // normal counting mode
- TCCR3B = _BV(CS31); // set prescaler of 8
- TCNT3 = 0; // clear the timer count
- #ifdef __AVR_ATmega128__
- SBI(TIFR, OCF3A); // clear any pending interrupts;
- SBI(ETIMSK, OCIE3A); // enable the output compare interrupt
- #else
- SBI(TIFR3, OCF3A); // clear any pending interrupts;
- SBI(TIMSK3, OCIE3A); // enable the output compare interrupt
- #endif
- #ifdef WIRING
- timerAttach(TIMER3OUTCOMPAREA_INT, Timer3Service); // for Wiring platform only
- #endif
- }
- #endif
-
- #ifdef _useTimer4
- if (timer == _timer4) {
- TCCR4A = 0; // normal counting mode
- TCCR4B = _BV(CS41); // set prescaler of 8
- TCNT4 = 0; // clear the timer count
- TIFR4 = _BV(OCF4A); // clear any pending interrupts;
- TIMSK4 = _BV(OCIE4A); // enable the output compare interrupt
- }
- #endif
-
- #ifdef _useTimer5
- if (timer == _timer5) {
- TCCR5A = 0; // normal counting mode
- TCCR5B = _BV(CS51); // set prescaler of 8
- TCNT5 = 0; // clear the timer count
- TIFR5 = _BV(OCF5A); // clear any pending interrupts;
- TIMSK5 = _BV(OCIE5A); // enable the output compare interrupt
- }
- #endif
-}
-
-void finISR(timer16_Sequence_t timer) {
- // Disable use of the given timer
- #ifdef WIRING
- if (timer == _timer1) {
- CBI(
- #if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
- TIMSK1
+void initISR(const timer16_Sequence_t timer_index) {
+ switch (timer_index) {
+ default: break;
+
+ #ifdef _useTimer1
+ case _timer1:
+ TCCR1A = 0; // normal counting mode
+ TCCR1B = _BV(CS11); // set prescaler of 8
+ TCNT1 = 0; // clear the timer count
+ #if defined(__AVR_ATmega8__) || defined(__AVR_ATmega128__)
+ SBI(TIFR, OCF1A); // clear any pending interrupts;
+ SBI(TIMSK, OCIE1A); // enable the output compare interrupt
#else
- TIMSK
+ // here if not ATmega8 or ATmega128
+ SBI(TIFR1, OCF1A); // clear any pending interrupts;
+ SBI(TIMSK1, OCIE1A); // enable the output compare interrupt
#endif
- , OCIE1A); // disable timer 1 output compare interrupt
- timerDetach(TIMER1OUTCOMPAREA_INT);
- }
- else if (timer == _timer3) {
- CBI(
- #if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
- TIMSK3
+ #ifdef WIRING
+ timerAttach(TIMER1OUTCOMPAREA_INT, Timer1Service);
+ #endif
+ break;
+ #endif
+
+ #ifdef _useTimer3
+ case _timer3:
+ TCCR3A = 0; // normal counting mode
+ TCCR3B = _BV(CS31); // set prescaler of 8
+ TCNT3 = 0; // clear the timer count
+ #ifdef __AVR_ATmega128__
+ SBI(TIFR, OCF3A); // clear any pending interrupts;
+ SBI(ETIMSK, OCIE3A); // enable the output compare interrupt
#else
- ETIMSK
+ SBI(TIFR3, OCF3A); // clear any pending interrupts;
+ SBI(TIMSK3, OCIE3A); // enable the output compare interrupt
+ #endif
+ #ifdef WIRING
+ timerAttach(TIMER3OUTCOMPAREA_INT, Timer3Service); // for Wiring platform only
#endif
- , OCIE3A); // disable the timer3 output compare A interrupt
- timerDetach(TIMER3OUTCOMPAREA_INT);
+ break;
+ #endif
+
+ #ifdef _useTimer4
+ case _timer4:
+ TCCR4A = 0; // normal counting mode
+ TCCR4B = _BV(CS41); // set prescaler of 8
+ TCNT4 = 0; // clear the timer count
+ TIFR4 = _BV(OCF4A); // clear any pending interrupts;
+ TIMSK4 = _BV(OCIE4A); // enable the output compare interrupt
+ break;
+ #endif
+
+ #ifdef _useTimer5
+ case _timer5:
+ TCCR5A = 0; // normal counting mode
+ TCCR5B = _BV(CS51); // set prescaler of 8
+ TCNT5 = 0; // clear the timer count
+ TIFR5 = _BV(OCF5A); // clear any pending interrupts;
+ TIMSK5 = _BV(OCIE5A); // enable the output compare interrupt
+ break;
+ #endif
+ }
+}
+
+void finISR(const timer16_Sequence_t timer_index) {
+ // Disable use of the given timer
+ #ifdef WIRING
+ switch (timer_index) {
+ default: break;
+
+ case _timer1:
+ CBI(
+ #if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
+ TIMSK1
+ #else
+ TIMSK
+ #endif
+ , OCIE1A // disable timer 1 output compare interrupt
+ );
+ timerDetach(TIMER1OUTCOMPAREA_INT);
+ break;
+
+ case _timer3:
+ CBI(
+ #if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
+ TIMSK3
+ #else
+ ETIMSK
+ #endif
+ , OCIE3A // disable the timer3 output compare A interrupt
+ );
+ timerDetach(TIMER3OUTCOMPAREA_INT);
+ break;
}
#else // !WIRING
// For arduino - in future: call here to a currently undefined function to reset the timer
- UNUSED(timer);
+ UNUSED(timer_index);
#endif
}
diff --git a/Marlin/src/HAL/AVR/eeprom.cpp b/Marlin/src/HAL/AVR/eeprom.cpp
index c7906985eb60..8d084dec7fdf 100644
--- a/Marlin/src/HAL/AVR/eeprom.cpp
+++ b/Marlin/src/HAL/AVR/eeprom.cpp
@@ -40,13 +40,13 @@ bool PersistentStore::access_start() { return true; }
bool PersistentStore::access_finish() { return true; }
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
+ uint16_t written = 0;
while (size--) {
uint8_t * const p = (uint8_t * const)pos;
uint8_t v = *value;
- // EEPROM has only ~100,000 write cycles,
- // so only write bytes that have changed!
- if (v != eeprom_read_byte(p)) {
+ if (v != eeprom_read_byte(p)) { // EEPROM has only ~100,000 write cycles, so only write bytes that have changed!
eeprom_write_byte(p, v);
+ if (++written & 0x7F) delay(2); else safe_delay(2); // Avoid triggering watchdog during long EEPROM writes
if (eeprom_read_byte(p) != v) {
SERIAL_ECHO_MSG(STR_ERR_EEPROM_WRITE);
return true;
@@ -59,7 +59,7 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui
return false;
}
-bool PersistentStore::read_data(int &pos, uint8_t* value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
+bool PersistentStore::read_data(int &pos, uint8_t *value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
do {
uint8_t c = eeprom_read_byte((uint8_t*)pos);
if (writing) *value = c;
diff --git a/Marlin/src/HAL/AVR/endstop_interrupts.h b/Marlin/src/HAL/AVR/endstop_interrupts.h
index ae9a605accce..5511aa406fec 100644
--- a/Marlin/src/HAL/AVR/endstop_interrupts.h
+++ b/Marlin/src/HAL/AVR/endstop_interrupts.h
@@ -124,7 +124,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(X_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(X_MAX_PIN);
#else
- static_assert(digitalPinHasPCICR(X_MAX_PIN), "X_MAX_PIN is not interrupt-capable");
+ static_assert(digitalPinHasPCICR(X_MAX_PIN), "X_MAX_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
pciSetup(X_MAX_PIN);
#endif
#endif
@@ -132,7 +132,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(X_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(X_MIN_PIN);
#else
- static_assert(digitalPinHasPCICR(X_MIN_PIN), "X_MIN_PIN is not interrupt-capable");
+ static_assert(digitalPinHasPCICR(X_MIN_PIN), "X_MIN_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
pciSetup(X_MIN_PIN);
#endif
#endif
@@ -140,7 +140,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Y_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Y_MAX_PIN);
#else
- static_assert(digitalPinHasPCICR(Y_MAX_PIN), "Y_MAX_PIN is not interrupt-capable");
+ static_assert(digitalPinHasPCICR(Y_MAX_PIN), "Y_MAX_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
pciSetup(Y_MAX_PIN);
#endif
#endif
@@ -148,7 +148,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Y_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Y_MIN_PIN);
#else
- static_assert(digitalPinHasPCICR(Y_MIN_PIN), "Y_MIN_PIN is not interrupt-capable");
+ static_assert(digitalPinHasPCICR(Y_MIN_PIN), "Y_MIN_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
pciSetup(Y_MIN_PIN);
#endif
#endif
@@ -156,7 +156,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Z_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Z_MAX_PIN);
#else
- static_assert(digitalPinHasPCICR(Z_MAX_PIN), "Z_MAX_PIN is not interrupt-capable");
+ static_assert(digitalPinHasPCICR(Z_MAX_PIN), "Z_MAX_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
pciSetup(Z_MAX_PIN);
#endif
#endif
@@ -164,15 +164,105 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Z_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Z_MIN_PIN);
#else
- static_assert(digitalPinHasPCICR(Z_MIN_PIN), "Z_MIN_PIN is not interrupt-capable");
+ static_assert(digitalPinHasPCICR(Z_MIN_PIN), "Z_MIN_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
pciSetup(Z_MIN_PIN);
#endif
#endif
+ #if HAS_I_MAX
+ #if (digitalPinToInterrupt(I_MAX_PIN) != NOT_AN_INTERRUPT)
+ _ATTACH(I_MAX_PIN);
+ #else
+ static_assert(digitalPinHasPCICR(I_MAX_PIN), "I_MAX_PIN is not interrupt-capable");
+ pciSetup(I_MAX_PIN);
+ #endif
+ #elif HAS_I_MIN
+ #if (digitalPinToInterrupt(I_MIN_PIN) != NOT_AN_INTERRUPT)
+ _ATTACH(I_MIN_PIN);
+ #else
+ static_assert(digitalPinHasPCICR(I_MIN_PIN), "I_MIN_PIN is not interrupt-capable");
+ pciSetup(I_MIN_PIN);
+ #endif
+ #endif
+ #if HAS_J_MAX
+ #if (digitalPinToInterrupt(J_MAX_PIN) != NOT_AN_INTERRUPT)
+ _ATTACH(J_MAX_PIN);
+ #else
+ static_assert(digitalPinHasPCICR(J_MAX_PIN), "J_MAX_PIN is not interrupt-capable");
+ pciSetup(J_MAX_PIN);
+ #endif
+ #elif HAS_J_MIN
+ #if (digitalPinToInterrupt(J_MIN_PIN) != NOT_AN_INTERRUPT)
+ _ATTACH(J_MIN_PIN);
+ #else
+ static_assert(digitalPinHasPCICR(J_MIN_PIN), "J_MIN_PIN is not interrupt-capable");
+ pciSetup(J_MIN_PIN);
+ #endif
+ #endif
+ #if HAS_K_MAX
+ #if (digitalPinToInterrupt(K_MAX_PIN) != NOT_AN_INTERRUPT)
+ _ATTACH(K_MAX_PIN);
+ #else
+ static_assert(digitalPinHasPCICR(K_MAX_PIN), "K_MAX_PIN is not interrupt-capable");
+ pciSetup(K_MAX_PIN);
+ #endif
+ #elif HAS_K_MIN
+ #if (digitalPinToInterrupt(K_MIN_PIN) != NOT_AN_INTERRUPT)
+ _ATTACH(K_MIN_PIN);
+ #else
+ static_assert(digitalPinHasPCICR(K_MIN_PIN), "K_MIN_PIN is not interrupt-capable");
+ pciSetup(K_MIN_PIN);
+ #endif
+ #endif
+ #if HAS_U_MAX
+ #if (digitalPinToInterrupt(U_MAX_PIN) != NOT_AN_INTERRUPT)
+ _ATTACH(U_MAX_PIN);
+ #else
+ static_assert(digitalPinHasPCICR(U_MAX_PIN), "U_MAX_PIN is not interrupt-capable");
+ pciSetup(U_MAX_PIN);
+ #endif
+ #elif HAS_U_MIN
+ #if (digitalPinToInterrupt(U_MIN_PIN) != NOT_AN_INTERRUPT)
+ _ATTACH(U_MIN_PIN);
+ #else
+ static_assert(digitalPinHasPCICR(U_MIN_PIN), "U_MIN_PIN is not interrupt-capable");
+ pciSetup(U_MIN_PIN);
+ #endif
+ #endif
+ #if HAS_V_MAX
+ #if (digitalPinToInterrupt(V_MAX_PIN) != NOT_AN_INTERRUPT)
+ _ATTACH(V_MAX_PIN);
+ #else
+ static_assert(digitalPinHasPCICR(V_MAX_PIN), "V_MAX_PIN is not interrupt-capable");
+ pciSetup(V_MAX_PIN);
+ #endif
+ #elif HAS_V_MIN
+ #if (digitalPinToInterrupt(V_MIN_PIN) != NOT_AN_INTERRUPT)
+ _ATTACH(V_MIN_PIN);
+ #else
+ static_assert(digitalPinHasPCICR(V_MIN_PIN), "V_MIN_PIN is not interrupt-capable");
+ pciSetup(V_MIN_PIN);
+ #endif
+ #endif
+ #if HAS_W_MAX
+ #if (digitalPinToInterrupt(W_MAX_PIN) != NOT_AN_INTERRUPT)
+ _ATTACH(W_MAX_PIN);
+ #else
+ static_assert(digitalPinHasPCICR(W_MAX_PIN), "W_MAX_PIN is not interrupt-capable");
+ pciSetup(W_MAX_PIN);
+ #endif
+ #elif HAS_W_MIN
+ #if (digitalPinToInterrupt(W_MIN_PIN) != NOT_AN_INTERRUPT)
+ _ATTACH(W_MIN_PIN);
+ #else
+ static_assert(digitalPinHasPCICR(W_MIN_PIN), "W_MIN_PIN is not interrupt-capable");
+ pciSetup(W_MIN_PIN);
+ #endif
+ #endif
#if HAS_X2_MAX
#if (digitalPinToInterrupt(X2_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(X2_MAX_PIN);
#else
- static_assert(digitalPinHasPCICR(X2_MAX_PIN), "X2_MAX_PIN is not interrupt-capable");
+ static_assert(digitalPinHasPCICR(X2_MAX_PIN), "X2_MAX_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
pciSetup(X2_MAX_PIN);
#endif
#endif
@@ -180,7 +270,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(X2_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(X2_MIN_PIN);
#else
- static_assert(digitalPinHasPCICR(X2_MIN_PIN), "X2_MIN_PIN is not interrupt-capable");
+ static_assert(digitalPinHasPCICR(X2_MIN_PIN), "X2_MIN_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
pciSetup(X2_MIN_PIN);
#endif
#endif
@@ -188,7 +278,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Y2_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Y2_MAX_PIN);
#else
- static_assert(digitalPinHasPCICR(Y2_MAX_PIN), "Y2_MAX_PIN is not interrupt-capable");
+ static_assert(digitalPinHasPCICR(Y2_MAX_PIN), "Y2_MAX_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
pciSetup(Y2_MAX_PIN);
#endif
#endif
@@ -196,7 +286,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Y2_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Y2_MIN_PIN);
#else
- static_assert(digitalPinHasPCICR(Y2_MIN_PIN), "Y2_MIN_PIN is not interrupt-capable");
+ static_assert(digitalPinHasPCICR(Y2_MIN_PIN), "Y2_MIN_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
pciSetup(Y2_MIN_PIN);
#endif
#endif
@@ -204,7 +294,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Z2_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Z2_MAX_PIN);
#else
- static_assert(digitalPinHasPCICR(Z2_MAX_PIN), "Z2_MAX_PIN is not interrupt-capable");
+ static_assert(digitalPinHasPCICR(Z2_MAX_PIN), "Z2_MAX_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
pciSetup(Z2_MAX_PIN);
#endif
#endif
@@ -212,7 +302,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Z2_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Z2_MIN_PIN);
#else
- static_assert(digitalPinHasPCICR(Z2_MIN_PIN), "Z2_MIN_PIN is not interrupt-capable");
+ static_assert(digitalPinHasPCICR(Z2_MIN_PIN), "Z2_MIN_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
pciSetup(Z2_MIN_PIN);
#endif
#endif
@@ -220,7 +310,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Z3_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Z3_MAX_PIN);
#else
- static_assert(digitalPinHasPCICR(Z3_MAX_PIN), "Z3_MAX_PIN is not interrupt-capable");
+ static_assert(digitalPinHasPCICR(Z3_MAX_PIN), "Z3_MAX_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
pciSetup(Z3_MAX_PIN);
#endif
#endif
@@ -228,7 +318,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Z3_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Z3_MIN_PIN);
#else
- static_assert(digitalPinHasPCICR(Z3_MIN_PIN), "Z3_MIN_PIN is not interrupt-capable");
+ static_assert(digitalPinHasPCICR(Z3_MIN_PIN), "Z3_MIN_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
pciSetup(Z3_MIN_PIN);
#endif
#endif
@@ -236,7 +326,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Z4_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Z4_MAX_PIN);
#else
- static_assert(digitalPinHasPCICR(Z4_MAX_PIN), "Z4_MAX_PIN is not interrupt-capable");
+ static_assert(digitalPinHasPCICR(Z4_MAX_PIN), "Z4_MAX_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
pciSetup(Z4_MAX_PIN);
#endif
#endif
@@ -244,7 +334,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Z4_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Z4_MIN_PIN);
#else
- static_assert(digitalPinHasPCICR(Z4_MIN_PIN), "Z4_MIN_PIN is not interrupt-capable");
+ static_assert(digitalPinHasPCICR(Z4_MIN_PIN), "Z4_MIN_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
pciSetup(Z4_MIN_PIN);
#endif
#endif
@@ -252,7 +342,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Z_MIN_PROBE_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Z_MIN_PROBE_PIN);
#else
- static_assert(digitalPinHasPCICR(Z_MIN_PROBE_PIN), "Z_MIN_PROBE_PIN is not interrupt-capable");
+ static_assert(digitalPinHasPCICR(Z_MIN_PROBE_PIN), "Z_MIN_PROBE_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
pciSetup(Z_MIN_PROBE_PIN);
#endif
#endif
diff --git a/Marlin/src/HAL/AVR/fast_pwm.cpp b/Marlin/src/HAL/AVR/fast_pwm.cpp
index 238c1124adeb..0a384172c32a 100644
--- a/Marlin/src/HAL/AVR/fast_pwm.cpp
+++ b/Marlin/src/HAL/AVR/fast_pwm.cpp
@@ -21,11 +21,7 @@
*/
#ifdef __AVR__
-#include "../../inc/MarlinConfigPre.h"
-
-#if NEEDS_HARDWARE_PWM // Specific meta-flag for features that mandate PWM
-
-#include "HAL.h"
+#include "../../inc/MarlinConfig.h"
struct Timer {
volatile uint8_t* TCCRnQ[3]; // max 3 TCCR registers per timer
@@ -33,250 +29,194 @@ struct Timer {
volatile uint16_t* ICRn; // max 1 ICR register per timer
uint8_t n; // the timer number [0->5]
uint8_t q; // the timer output [0->2] (A->C)
+ bool isPWM; // True if pin is a "hardware timer"
+ bool isProtected; // True if timer is protected
};
+// Macros for the Timer structure
+#define _SET_WGMnQ(T, V) do{ \
+ *(T.TCCRnQ)[0] = (*(T.TCCRnQ)[0] & ~(0x3 << 0)) | (( int(V) & 0x3) << 0); \
+ *(T.TCCRnQ)[1] = (*(T.TCCRnQ)[1] & ~(0x3 << 3)) | (((int(V) >> 2) & 0x3) << 3); \
+ }while(0)
+
+// Set TCCR CS bits
+#define _SET_CSn(T, V) (*(T.TCCRnQ)[1] = (*(T.TCCRnQ[1]) & ~(0x7 << 0)) | ((int(V) & 0x7) << 0))
+
+// Set TCCR COM bits
+#define _SET_COMnQ(T, Q, V) (*(T.TCCRnQ)[0] = (*(T.TCCRnQ)[0] & ~(0x3 << (6-2*(Q)))) | (int(V) << (6-2*(Q))))
+
+// Set OCRnQ register
+#define _SET_OCRnQ(T, Q, V) (*(T.OCRnQ)[Q] = int(V) & 0xFFFF)
+
+// Set ICRn register (one per timer)
+#define _SET_ICRn(T, V) (*(T.ICRn) = int(V) & 0xFFFF)
+
/**
- * get_pwm_timer
- * Get the timer information and register of the provided pin.
- * Return a Timer struct containing this information.
- * Used by set_pwm_frequency, set_pwm_duty
+ * Return a Timer struct describing a pin's timer.
*/
-Timer get_pwm_timer(const pin_t pin) {
+const Timer get_pwm_timer(const pin_t pin) {
+
uint8_t q = 0;
+
switch (digitalPinToTimer(pin)) {
- // Protect reserved timers (TIMER0 & TIMER1)
#ifdef TCCR0A
- #if !AVR_AT90USB1286_FAMILY
- case TIMER0A:
- #endif
- case TIMER0B:
+ IF_DISABLED(AVR_AT90USB1286_FAMILY, case TIMER0A:)
#endif
#ifdef TCCR1A
case TIMER1A: case TIMER1B:
#endif
- break;
- #if defined(TCCR2) || defined(TCCR2A)
- #ifdef TCCR2
- case TIMER2: {
- Timer timer = {
- /*TCCRnQ*/ { &TCCR2, nullptr, nullptr },
- /*OCRnQ*/ { (uint16_t*)&OCR2, nullptr, nullptr },
- /*ICRn*/ nullptr,
- /*n, q*/ 2, 0
- };
- }
- #elif defined(TCCR2A)
- #if ENABLED(USE_OCR2A_AS_TOP)
- case TIMER2A: break; // protect TIMER2A
- case TIMER2B: {
- Timer timer = {
- /*TCCRnQ*/ { &TCCR2A, &TCCR2B, nullptr },
- /*OCRnQ*/ { (uint16_t*)&OCR2A, (uint16_t*)&OCR2B, nullptr },
- /*ICRn*/ nullptr,
- /*n, q*/ 2, 1
- };
- return timer;
- }
- #else
- case TIMER2B: ++q;
- case TIMER2A: {
- Timer timer = {
- /*TCCRnQ*/ { &TCCR2A, &TCCR2B, nullptr },
- /*OCRnQ*/ { (uint16_t*)&OCR2A, (uint16_t*)&OCR2B, nullptr },
- /*ICRn*/ nullptr,
- 2, q
- };
- return timer;
- }
- #endif
- #endif
+
+ break; // Protect reserved timers (TIMER0 & TIMER1)
+
+ #ifdef TCCR0A
+ case TIMER0B: // Protected timer, but allow setting the duty cycle on OCR0B for pin D4 only
+ return Timer({ { &TCCR0A, nullptr, nullptr }, { (uint16_t*)&OCR0A, (uint16_t*)&OCR0B, nullptr }, nullptr, 0, 1, true, true });
+ #endif
+
+ #if HAS_TCCR2
+ case TIMER2:
+ return Timer({ { &TCCR2, nullptr, nullptr }, { (uint16_t*)&OCR2, nullptr, nullptr }, nullptr, 2, 0, true, false });
+ #elif ENABLED(USE_OCR2A_AS_TOP)
+ case TIMER2A: break; // Protect TIMER2A since its OCR is used by TIMER2B
+ case TIMER2B:
+ return Timer({ { &TCCR2A, &TCCR2B, nullptr }, { (uint16_t*)&OCR2A, (uint16_t*)&OCR2B, nullptr }, nullptr, 2, 1, true, false });
+ #elif defined(TCCR2A)
+ case TIMER2B: ++q; case TIMER2A:
+ return Timer({ { &TCCR2A, &TCCR2B, nullptr }, { (uint16_t*)&OCR2A, (uint16_t*)&OCR2B, nullptr }, nullptr, 2, q, true, false });
#endif
+
#ifdef OCR3C
- case TIMER3C: ++q;
- case TIMER3B: ++q;
- case TIMER3A: {
- Timer timer = {
- /*TCCRnQ*/ { &TCCR3A, &TCCR3B, &TCCR3C },
- /*OCRnQ*/ { &OCR3A, &OCR3B, &OCR3C },
- /*ICRn*/ &ICR3,
- /*n, q*/ 3, q
- };
- return timer;
- }
+ case TIMER3C: ++q; case TIMER3B: ++q; case TIMER3A:
+ return Timer({ { &TCCR3A, &TCCR3B, &TCCR3C }, { &OCR3A, &OCR3B, &OCR3C }, &ICR3, 3, q, true, false });
#elif defined(OCR3B)
- case TIMER3B: ++q;
- case TIMER3A: {
- Timer timer = {
- /*TCCRnQ*/ { &TCCR3A, &TCCR3B, nullptr },
- /*OCRnQ*/ { &OCR3A, &OCR3B, nullptr },
- /*ICRn*/ &ICR3,
- /*n, q*/ 3, q
- };
- return timer;
- }
+ case TIMER3B: ++q; case TIMER3A:
+ return Timer({ { &TCCR3A, &TCCR3B, nullptr }, { &OCR3A, &OCR3B, nullptr }, &ICR3, 3, q, true, false });
#endif
+
#ifdef TCCR4A
- case TIMER4C: ++q;
- case TIMER4B: ++q;
- case TIMER4A: {
- Timer timer = {
- /*TCCRnQ*/ { &TCCR4A, &TCCR4B, &TCCR4C },
- /*OCRnQ*/ { &OCR4A, &OCR4B, &OCR4C },
- /*ICRn*/ &ICR4,
- /*n, q*/ 4, q
- };
- return timer;
- }
+ case TIMER4C: ++q; case TIMER4B: ++q; case TIMER4A:
+ return Timer({ { &TCCR4A, &TCCR4B, &TCCR4C }, { &OCR4A, &OCR4B, &OCR4C }, &ICR4, 4, q, true, false });
#endif
+
#ifdef TCCR5A
- case TIMER5C: ++q;
- case TIMER5B: ++q;
- case TIMER5A: {
- Timer timer = {
- /*TCCRnQ*/ { &TCCR5A, &TCCR5B, &TCCR5C },
- /*OCRnQ*/ { &OCR5A, &OCR5B, &OCR5C },
- /*ICRn*/ &ICR5,
- /*n, q*/ 5, q
- };
- return timer;
- }
+ case TIMER5C: ++q; case TIMER5B: ++q; case TIMER5A:
+ return Timer({ { &TCCR5A, &TCCR5B, &TCCR5C }, { &OCR5A, &OCR5B, &OCR5C }, &ICR5, 5, q, true, false });
#endif
}
- Timer timer = {
- /*TCCRnQ*/ { nullptr, nullptr, nullptr },
- /*OCRnQ*/ { nullptr, nullptr, nullptr },
- /*ICRn*/ nullptr,
- 0, 0
- };
- return timer;
+
+ return Timer();
}
-void set_pwm_frequency(const pin_t pin, int f_desired) {
- Timer timer = get_pwm_timer(pin);
- if (timer.n == 0) return; // Don't proceed if protected timer or not recognised
- uint16_t size;
- if (timer.n == 2) size = 255; else size = 65535;
+void MarlinHAL::set_pwm_frequency(const pin_t pin, const uint16_t f_desired) {
+ const Timer timer = get_pwm_timer(pin);
+ if (timer.isProtected || !timer.isPWM) return; // Don't proceed if protected timer or not recognized
+
+ const bool is_timer2 = timer.n == 2;
+ const uint16_t maxtop = is_timer2 ? 0xFF : 0xFFFF;
- uint16_t res = 255; // resolution (TOP value)
- uint8_t j = 0; // prescaler index
- uint8_t wgm = 1; // waveform generation mode
+ uint16_t res = 0xFF; // resolution (TOP value)
+ uint8_t j = CS_NONE; // prescaler index
+ uint8_t wgm = WGM_PWM_PC_8; // waveform generation mode
// Calculating the prescaler and resolution to use to achieve closest frequency
if (f_desired != 0) {
- int f = (F_CPU) / (2 * 1024 * size) + 1; // Initialize frequency as lowest (non-zero) achievable
- uint16_t prescaler[] = { 0, 1, 8, /*TIMER2 ONLY*/32, 64, /*TIMER2 ONLY*/128, 256, 1024 };
-
- // loop over prescaler values
- LOOP_S_L_N(i, 1, 8) {
- uint16_t res_temp_fast = 255, res_temp_phase_correct = 255;
- if (timer.n == 2) {
- // No resolution calculation for TIMER2 unless enabled USE_OCR2A_AS_TOP
- #if ENABLED(USE_OCR2A_AS_TOP)
- const uint16_t rtf = (F_CPU) / (prescaler[i] * f_desired);
- res_temp_fast = rtf - 1;
- res_temp_phase_correct = rtf / 2;
+ constexpr uint16_t prescaler[] = { 1, 8, (32), 64, (128), 256, 1024 }; // (*) are Timer 2 only
+ uint16_t f = (F_CPU) / (2 * 1024 * maxtop) + 1; // Start with the lowest non-zero frequency achievable (1 or 31)
+
+ LOOP_L_N(i, COUNT(prescaler)) { // Loop through all prescaler values
+ const uint16_t p = prescaler[i];
+ uint16_t res_fast_temp, res_pc_temp;
+ if (is_timer2) {
+ #if ENABLED(USE_OCR2A_AS_TOP) // No resolution calculation for TIMER2 unless enabled USE_OCR2A_AS_TOP
+ const uint16_t rft = (F_CPU) / (p * f_desired);
+ res_fast_temp = rft - 1;
+ res_pc_temp = rft / 2;
+ #else
+ res_fast_temp = res_pc_temp = maxtop;
#endif
}
else {
- // Skip TIMER2 specific prescalers when not TIMER2
- if (i == 3 || i == 5) continue;
- const uint16_t rtf = (F_CPU) / (prescaler[i] * f_desired);
- res_temp_fast = rtf - 1;
- res_temp_phase_correct = rtf / 2;
+ if (p == 32 || p == 128) continue; // Skip TIMER2 specific prescalers when not TIMER2
+ const uint16_t rft = (F_CPU) / (p * f_desired);
+ res_fast_temp = rft - 1;
+ res_pc_temp = rft / 2;
}
- LIMIT(res_temp_fast, 1U, size);
- LIMIT(res_temp_phase_correct, 1U, size);
+ LIMIT(res_fast_temp, 1U, maxtop);
+ LIMIT(res_pc_temp, 1U, maxtop);
+
// Calculate frequencies of test prescaler and resolution values
- const int f_temp_fast = (F_CPU) / (prescaler[i] * (1 + res_temp_fast)),
- f_temp_phase_correct = (F_CPU) / (2 * prescaler[i] * res_temp_phase_correct),
- f_diff = ABS(f - f_desired),
- f_fast_diff = ABS(f_temp_fast - f_desired),
- f_phase_diff = ABS(f_temp_phase_correct - f_desired);
+ const uint32_t f_diff = _MAX(f, f_desired) - _MIN(f, f_desired),
+ f_fast_temp = (F_CPU) / (p * (1 + res_fast_temp)),
+ f_fast_diff = _MAX(f_fast_temp, f_desired) - _MIN(f_fast_temp, f_desired),
+ f_pc_temp = (F_CPU) / (2 * p * res_pc_temp),
+ f_pc_diff = _MAX(f_pc_temp, f_desired) - _MIN(f_pc_temp, f_desired);
- // If FAST values are closest to desired f
- if (f_fast_diff < f_diff && f_fast_diff <= f_phase_diff) {
- // Remember this combination
- f = f_temp_fast;
- res = res_temp_fast;
- j = i;
+ if (f_fast_diff < f_diff && f_fast_diff <= f_pc_diff) { // FAST values are closest to desired f
// Set the Wave Generation Mode to FAST PWM
- if (timer.n == 2) {
- wgm = (
- #if ENABLED(USE_OCR2A_AS_TOP)
- WGM2_FAST_PWM_OCR2A
- #else
- WGM2_FAST_PWM
- #endif
- );
- }
- else wgm = WGM_FAST_PWM_ICRn;
+ wgm = is_timer2 ? uint8_t(TERN(USE_OCR2A_AS_TOP, WGM2_FAST_PWM_OCR2A, WGM2_FAST_PWM)) : uint8_t(WGM_FAST_PWM_ICRn);
+ // Remember this combination
+ f = f_fast_temp; res = res_fast_temp; j = i + 1;
}
- // If PHASE CORRECT values are closes to desired f
- else if (f_phase_diff < f_diff) {
- f = f_temp_phase_correct;
- res = res_temp_phase_correct;
- j = i;
+ else if (f_pc_diff < f_diff) { // PHASE CORRECT values are closes to desired f
// Set the Wave Generation Mode to PWM PHASE CORRECT
- if (timer.n == 2) {
- wgm = (
- #if ENABLED(USE_OCR2A_AS_TOP)
- WGM2_PWM_PC_OCR2A
- #else
- WGM2_PWM_PC
- #endif
- );
- }
- else wgm = WGM_PWM_PC_ICRn;
+ wgm = is_timer2 ? uint8_t(TERN(USE_OCR2A_AS_TOP, WGM2_PWM_PC_OCR2A, WGM2_PWM_PC)) : uint8_t(WGM_PWM_PC_ICRn);
+ f = f_pc_temp; res = res_pc_temp; j = i + 1;
}
}
}
- _SET_WGMnQ(timer.TCCRnQ, wgm);
- _SET_CSn(timer.TCCRnQ, j);
- if (timer.n == 2) {
- #if ENABLED(USE_OCR2A_AS_TOP)
- _SET_OCRnQ(timer.OCRnQ, 0, res); // Set OCR2A value (TOP) = res
- #endif
+ _SET_WGMnQ(timer, wgm);
+ _SET_CSn(timer, j);
+
+ if (is_timer2) {
+ TERN_(USE_OCR2A_AS_TOP, _SET_OCRnQ(timer, 0, res)); // Set OCR2A value (TOP) = res
}
else
- _SET_ICRn(timer.ICRn, res); // Set ICRn value (TOP) = res
+ _SET_ICRn(timer, res); // Set ICRn value (TOP) = res
}
-void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) {
+void MarlinHAL::set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) {
// If v is 0 or v_size (max), digitalWrite to LOW or HIGH.
- // Note that digitalWrite also disables pwm output for us (sets COM bit to 0)
+ // Note that digitalWrite also disables PWM output for us (sets COM bit to 0)
if (v == 0)
digitalWrite(pin, invert);
else if (v == v_size)
digitalWrite(pin, !invert);
else {
- Timer timer = get_pwm_timer(pin);
- if (timer.n == 0) return; // Don't proceed if protected timer or not recognised
- // Set compare output mode to CLEAR -> SET or SET -> CLEAR (if inverted)
- _SET_COMnQ(timer.TCCRnQ, (timer.q
- #ifdef TCCR2
- + (timer.q == 2) // COM20 is on bit 4 of TCCR2, thus requires q + 1 in the macro
- #endif
- ), COM_CLEAR_SET + invert
- );
-
- uint16_t top;
- if (timer.n == 2) { // if TIMER2
- top = (
- #if ENABLED(USE_OCR2A_AS_TOP)
- *timer.OCRnQ[0] // top = OCR2A
- #else
- 255 // top = 0xFF (max)
- #endif
- );
+ const Timer timer = get_pwm_timer(pin);
+ if (timer.isPWM) {
+ if (timer.n == 0) {
+ _SET_COMnQ(timer, timer.q, COM_CLEAR_SET); // Only allow a TIMER0B select...
+ _SET_OCRnQ(timer, timer.q, v); // ...and OCR0B duty update. For output pin D4 no frequency changes are permitted.
+ }
+ else if (!timer.isProtected) {
+ const uint16_t top = timer.n == 2 ? TERN(USE_OCR2A_AS_TOP, *timer.OCRnQ[0], 255) : *timer.ICRn;
+ _SET_COMnQ(timer, SUM_TERN(HAS_TCCR2, timer.q, timer.q == 2), COM_CLEAR_SET + invert); // COM20 is on bit 4 of TCCR2, so +1 for q==2
+ _SET_OCRnQ(timer, timer.q, uint16_t(uint32_t(v) * top / v_size)); // Scale 8/16-bit v to top value
+ }
}
else
- top = *timer.ICRn; // top = ICRn
-
- _SET_OCRnQ(timer.OCRnQ, timer.q, v * float(top) / float(v_size)); // Scale 8/16-bit v to top value
+ digitalWrite(pin, v < v_size / 2 ? LOW : HIGH);
}
}
-#endif // NEEDS_HARDWARE_PWM
+void MarlinHAL::init_pwm_timers() {
+ // Init some timer frequencies to a default 1KHz
+ const pin_t pwm_pin[] = {
+ #ifdef __AVR_ATmega2560__
+ 10, 5, 6, 46
+ #elif defined(__AVR_ATmega1280__)
+ 12, 31
+ #elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega1284__)
+ 15, 6
+ #elif defined(__AVR_AT90USB1286__) || defined(__AVR_mega64) || defined(__AVR_mega128)
+ 16, 24
+ #endif
+ };
+
+ LOOP_L_N(i, COUNT(pwm_pin))
+ set_pwm_frequency(pwm_pin[i], 1000);
+}
+
#endif // __AVR__
diff --git a/Marlin/src/HAL/AVR/fastio.cpp b/Marlin/src/HAL/AVR/fastio.cpp
index b51d7f97686a..5c6ef1891512 100644
--- a/Marlin/src/HAL/AVR/fastio.cpp
+++ b/Marlin/src/HAL/AVR/fastio.cpp
@@ -241,11 +241,11 @@ uint8_t extDigitalRead(const int8_t pin) {
*
* DC values -1.0 to 1.0. Negative duty cycle inverts the pulse.
*/
-uint16_t set_pwm_frequency_hz(const float &hz, const float dca, const float dcb, const float dcc) {
+uint16_t set_pwm_frequency_hz(const_float_t hz, const float dca, const float dcb, const float dcc) {
float count = 0;
if (hz > 0 && (dca || dcb || dcc)) {
count = float(F_CPU) / hz; // 1x prescaler, TOP for 16MHz base freq.
- uint16_t prescaler; // Range of 30.5Hz (65535) 64.5KHz (>31)
+ uint16_t prescaler; // Range of 30.5Hz (65535) 64.5kHz (>31)
if (count >= 255. * 256.) { prescaler = 1024; SET_CS(5, PRESCALER_1024); }
else if (count >= 255. * 64.) { prescaler = 256; SET_CS(5, PRESCALER_256); }
@@ -257,7 +257,7 @@ uint16_t set_pwm_frequency_hz(const float &hz, const float dca, const float dcb,
const float pwm_top = round(count); // Get the rounded count
ICR5 = (uint16_t)pwm_top - 1; // Subtract 1 for TOP
- OCR5A = pwm_top * ABS(dca); // Update and scale DCs
+ OCR5A = pwm_top * ABS(dca); // Update and scale DCs
OCR5B = pwm_top * ABS(dcb);
OCR5C = pwm_top * ABS(dcc);
_SET_COM(5, A, dca ? (dca < 0 ? COM_SET_CLEAR : COM_CLEAR_SET) : COM_NORMAL); // Set compare modes
@@ -267,17 +267,17 @@ uint16_t set_pwm_frequency_hz(const float &hz, const float dca, const float dcb,
SET_WGM(5, FAST_PWM_ICRn); // Fast PWM with ICR5 as TOP
//SERIAL_ECHOLNPGM("Timer 5 Settings:");
- //SERIAL_ECHOLNPAIR(" Prescaler=", prescaler);
- //SERIAL_ECHOLNPAIR(" TOP=", ICR5);
- //SERIAL_ECHOLNPAIR(" OCR5A=", OCR5A);
- //SERIAL_ECHOLNPAIR(" OCR5B=", OCR5B);
- //SERIAL_ECHOLNPAIR(" OCR5C=", OCR5C);
+ //SERIAL_ECHOLNPGM(" Prescaler=", prescaler);
+ //SERIAL_ECHOLNPGM(" TOP=", ICR5);
+ //SERIAL_ECHOLNPGM(" OCR5A=", OCR5A);
+ //SERIAL_ECHOLNPGM(" OCR5B=", OCR5B);
+ //SERIAL_ECHOLNPGM(" OCR5C=", OCR5C);
}
else {
// Restore the default for Timer 5
SET_WGM(5, PWM_PC_8); // PWM 8-bit (Phase Correct)
SET_COMS(5, NORMAL, NORMAL, NORMAL); // Do nothing
- SET_CS(5, PRESCALER_64); // 16MHz / 64 = 250KHz
+ SET_CS(5, PRESCALER_64); // 16MHz / 64 = 250kHz
OCR5A = OCR5B = OCR5C = 0;
}
return round(count);
diff --git a/Marlin/src/HAL/AVR/fastio.h b/Marlin/src/HAL/AVR/fastio.h
index dd0163466110..51d3b311ee9d 100644
--- a/Marlin/src/HAL/AVR/fastio.h
+++ b/Marlin/src/HAL/AVR/fastio.h
@@ -118,7 +118,7 @@
*/
// Waveform Generation Modes
-enum WaveGenMode : char {
+enum WaveGenMode : uint8_t {
WGM_NORMAL, // 0
WGM_PWM_PC_8, // 1
WGM_PWM_PC_9, // 2
@@ -138,19 +138,19 @@ enum WaveGenMode : char {
};
// Wavefore Generation Modes (Timer 2 only)
-enum WaveGenMode2 : char {
- WGM2_NORMAL, // 0
- WGM2_PWM_PC, // 1
- WGM2_CTC_OCR2A, // 2
- WGM2_FAST_PWM, // 3
- WGM2_reserved_1, // 4
- WGM2_PWM_PC_OCR2A, // 5
- WGM2_reserved_2, // 6
- WGM2_FAST_PWM_OCR2A, // 7
+enum WaveGenMode2 : uint8_t {
+ WGM2_NORMAL, // 0
+ WGM2_PWM_PC, // 1
+ WGM2_CTC_OCR2A, // 2
+ WGM2_FAST_PWM, // 3
+ WGM2_reserved_1, // 4
+ WGM2_PWM_PC_OCR2A, // 5
+ WGM2_reserved_2, // 6
+ WGM2_FAST_PWM_OCR2A, // 7
};
// Compare Modes
-enum CompareMode : char {
+enum CompareMode : uint8_t {
COM_NORMAL, // 0
COM_TOGGLE, // 1 Non-PWM: OCnx ... Both PWM (WGM 9,11,14,15): OCnA only ... else NORMAL
COM_CLEAR_SET, // 2 Non-PWM: OCnx ... Fast PWM: OCnx/Bottom ... PF-FC: OCnx Up/Down
@@ -158,7 +158,7 @@ enum CompareMode : char {
};
// Clock Sources
-enum ClockSource : char {
+enum ClockSource : uint8_t {
CS_NONE, // 0
CS_PRESCALER_1, // 1
CS_PRESCALER_8, // 2
@@ -170,7 +170,7 @@ enum ClockSource : char {
};
// Clock Sources (Timer 2 only)
-enum ClockSource2 : char {
+enum ClockSource2 : uint8_t {
CS2_NONE, // 0
CS2_PRESCALER_1, // 1
CS2_PRESCALER_8, // 2
@@ -203,40 +203,33 @@ enum ClockSource2 : char {
TCCR##T##B = (TCCR##T##B & ~(0x3 << WGM##T##2)) | (((int(V) >> 2) & 0x3) << WGM##T##2); \
}while(0)
#define SET_WGM(T,V) _SET_WGM(T,WGM_##V)
-// Runtime (see set_pwm_frequency):
-#define _SET_WGMnQ(TCCRnQ, V) do{ \
- *(TCCRnQ)[0] = (*(TCCRnQ)[0] & ~(0x3 << 0)) | (( int(V) & 0x3) << 0); \
- *(TCCRnQ)[1] = (*(TCCRnQ)[1] & ~(0x3 << 3)) | (((int(V) >> 2) & 0x3) << 3); \
- }while(0)
// Set Clock Select bits
// Ex: SET_CS3(PRESCALER_64);
+#ifdef TCCR2
+ #define HAS_TCCR2 1
+#endif
#define _SET_CS(T,V) (TCCR##T##B = (TCCR##T##B & ~(0x7 << CS##T##0)) | ((int(V) & 0x7) << CS##T##0))
#define _SET_CS0(V) _SET_CS(0,V)
#define _SET_CS1(V) _SET_CS(1,V)
-#ifdef TCCR2
- #define _SET_CS2(V) (TCCR2 = (TCCR2 & ~(0x7 << CS20)) | (int(V) << CS20))
-#else
- #define _SET_CS2(V) _SET_CS(2,V)
-#endif
#define _SET_CS3(V) _SET_CS(3,V)
#define _SET_CS4(V) _SET_CS(4,V)
#define _SET_CS5(V) _SET_CS(5,V)
#define SET_CS0(V) _SET_CS0(CS_##V)
#define SET_CS1(V) _SET_CS1(CS_##V)
-#ifdef TCCR2
+
+#if HAS_TCCR2
+ #define _SET_CS2(V) (TCCR2 = (TCCR2 & ~(0x7 << CS20)) | (int(V) << CS20))
#define SET_CS2(V) _SET_CS2(CS2_##V)
#else
+ #define _SET_CS2(V) _SET_CS(2,V)
#define SET_CS2(V) _SET_CS2(CS_##V)
#endif
+
#define SET_CS3(V) _SET_CS3(CS_##V)
#define SET_CS4(V) _SET_CS4(CS_##V)
#define SET_CS5(V) _SET_CS5(CS_##V)
#define SET_CS(T,V) SET_CS##T(V)
-// Runtime (see set_pwm_frequency)
-#define _SET_CSn(TCCRnQ, V) do{ \
- (*(TCCRnQ)[1] = (*(TCCRnQ[1]) & ~(0x7 << 0)) | ((int(V) & 0x7) << 0)); \
- }while(0)
// Set Compare Mode bits
// Ex: SET_COMS(4,CLEAR_SET,CLEAR_SET,CLEAR_SET);
@@ -246,22 +239,6 @@ enum ClockSource2 : char {
#define SET_COMB(T,V) SET_COM(T,B,V)
#define SET_COMC(T,V) SET_COM(T,C,V)
#define SET_COMS(T,V1,V2,V3) do{ SET_COMA(T,V1); SET_COMB(T,V2); SET_COMC(T,V3); }while(0)
-// Runtime (see set_pwm_duty)
-#define _SET_COMnQ(TCCRnQ, Q, V) do{ \
- (*(TCCRnQ)[0] = (*(TCCRnQ)[0] & ~(0x3 << (6-2*(Q)))) | (int(V) << (6-2*(Q)))); \
- }while(0)
-
-// Set OCRnQ register
-// Runtime (see set_pwm_duty):
-#define _SET_OCRnQ(OCRnQ, Q, V) do{ \
- (*(OCRnQ)[(Q)] = (0x0000) | (int(V) & 0xFFFF)); \
- }while(0)
-
-// Set ICRn register (one per timer)
-// Runtime (see set_pwm_frequency)
-#define _SET_ICRn(ICRn, V) do{ \
- (*(ICRn) = (0x0000) | (int(V) & 0xFFFF)); \
- }while(0)
// Set Noise Canceler bit
// Ex: SET_ICNC(2,1)
@@ -284,8 +261,8 @@ enum ClockSource2 : char {
* PWM availability macros
*/
-// Determine which harware PWMs are already in use
-#define _PWM_CHK_FAN_B(P) (P == E0_AUTO_FAN_PIN || P == E1_AUTO_FAN_PIN || P == E2_AUTO_FAN_PIN || P == E3_AUTO_FAN_PIN || P == E4_AUTO_FAN_PIN || P == E5_AUTO_FAN_PIN || P == E6_AUTO_FAN_PIN || P == E7_AUTO_FAN_PIN || P == CHAMBER_AUTO_FAN_PIN)
+// Determine which hardware PWMs are already in use
+#define _PWM_CHK_FAN_B(P) (P == E0_AUTO_FAN_PIN || P == E1_AUTO_FAN_PIN || P == E2_AUTO_FAN_PIN || P == E3_AUTO_FAN_PIN || P == E4_AUTO_FAN_PIN || P == E5_AUTO_FAN_PIN || P == E6_AUTO_FAN_PIN || P == E7_AUTO_FAN_PIN || P == CHAMBER_AUTO_FAN_PIN || P == COOLER_AUTO_FAN_PIN)
#if PIN_EXISTS(CONTROLLER_FAN)
#define PWM_CHK_FAN_B(P) (_PWM_CHK_FAN_B(P) || P == CONTROLLER_FAN_PIN)
#else
diff --git a/Marlin/src/HAL/AVR/inc/SanityCheck.h b/Marlin/src/HAL/AVR/inc/SanityCheck.h
index 731cf9286582..89425ca853b3 100644
--- a/Marlin/src/HAL/AVR/inc/SanityCheck.h
+++ b/Marlin/src/HAL/AVR/inc/SanityCheck.h
@@ -25,25 +25,65 @@
* Test AVR-specific configuration values for errors at compile-time.
*/
+/**
+ * Check for common serial pin conflicts
+ */
+#define CHECK_SERIAL_PIN(N) ( \
+ X_STOP_PIN == N || Y_STOP_PIN == N || Z_STOP_PIN == N \
+ || X_MIN_PIN == N || Y_MIN_PIN == N || Z_MIN_PIN == N \
+ || X_MAX_PIN == N || Y_MAX_PIN == N || Z_MAX_PIN == N \
+ || X_STEP_PIN == N || Y_STEP_PIN == N || Z_STEP_PIN == N \
+ || X_DIR_PIN == N || Y_DIR_PIN == N || Z_DIR_PIN == N \
+ || X_ENA_PIN == N || Y_ENA_PIN == N || Z_ENA_PIN == N \
+ || BTN_EN1 == N || BTN_EN2 == N \
+)
+#if CONF_SERIAL_IS(0)
+ // D0-D1. No known conflicts.
+#endif
+#if NOT_TARGET(__AVR_ATmega644P__, __AVR_ATmega1284P__)
+ #if CONF_SERIAL_IS(1) && (CHECK_SERIAL_PIN(18) || CHECK_SERIAL_PIN(19))
+ #error "Serial Port 1 pin D18 and/or D19 conflicts with another pin on the board."
+ #endif
+#else
+ #if CONF_SERIAL_IS(1) && (CHECK_SERIAL_PIN(10) || CHECK_SERIAL_PIN(11))
+ #error "Serial Port 1 pin D10 and/or D11 conflicts with another pin on the board."
+ #endif
+#endif
+#if CONF_SERIAL_IS(2) && (CHECK_SERIAL_PIN(16) || CHECK_SERIAL_PIN(17))
+ #error "Serial Port 2 pin D16 and/or D17 conflicts with another pin on the board."
+#endif
+#if CONF_SERIAL_IS(3) && (CHECK_SERIAL_PIN(14) || CHECK_SERIAL_PIN(15))
+ #error "Serial Port 3 pin D14 and/or D15 conflicts with another pin on the board."
+#endif
+#undef CHECK_SERIAL_PIN
+
/**
* Checks for FAST PWM
*/
-#if ENABLED(FAST_PWM_FAN) && (ENABLED(USE_OCR2A_AS_TOP) && defined(TCCR2))
- #error "USE_OCR2A_AS_TOP does not apply to devices with a single output TIMER2"
+#if ALL(FAST_PWM_FAN, USE_OCR2A_AS_TOP, HAS_TCCR2)
+ #error "USE_OCR2A_AS_TOP does not apply to devices with a single output TIMER2."
+#endif
+
+/**
+ * Checks for SOFT PWM
+ */
+#if HAS_FAN0 && FAN_PIN == 9 && DISABLED(FAN_SOFT_PWM) && ENABLED(SPEAKER)
+ #error "FAN_PIN 9 Hardware PWM uses Timer 2 which conflicts with Arduino AVR Tone Timer (for SPEAKER)."
+ #error "Disable SPEAKER or enable FAN_SOFT_PWM."
#endif
/**
* Sanity checks for Spindle / Laser PWM
*/
-#if ENABLED(SPINDLE_LASER_PWM)
+#if ENABLED(SPINDLE_LASER_USE_PWM)
#include "../ServoTimers.h" // Needed to check timer availability (_useTimer3)
#if SPINDLE_LASER_PWM_PIN == 4 || WITHIN(SPINDLE_LASER_PWM_PIN, 11, 13)
#error "Counter/Timer for SPINDLE_LASER_PWM_PIN is used by a system interrupt."
#elif NUM_SERVOS > 0 && defined(_useTimer3) && (WITHIN(SPINDLE_LASER_PWM_PIN, 2, 3) || SPINDLE_LASER_PWM_PIN == 5)
#error "Counter/Timer for SPINDLE_LASER_PWM_PIN is used by the servo system."
#endif
-#elif defined(SPINDLE_LASER_FREQUENCY)
- #error "SPINDLE_LASER_FREQUENCY requires SPINDLE_LASER_PWM."
+#elif SPINDLE_LASER_FREQUENCY
+ #error "SPINDLE_LASER_FREQUENCY requires SPINDLE_LASER_USE_PWM."
#endif
/**
@@ -56,3 +96,14 @@
#if BOTH(HAS_TMC_SW_SERIAL, MONITOR_DRIVER_STATUS)
#error "MONITOR_DRIVER_STATUS causes performance issues when used with SoftwareSerial-connected drivers. Disable MONITOR_DRIVER_STATUS or use hardware serial to continue."
#endif
+
+/**
+ * Postmortem debugging
+ */
+#if ENABLED(POSTMORTEM_DEBUGGING)
+ #error "POSTMORTEM_DEBUGGING is not supported on AVR boards."
+#endif
+
+#if USING_PULLDOWNS
+ #error "PULLDOWN pin mode is not available on AVR boards."
+#endif
diff --git a/Marlin/src/HAL/AVR/math.h b/Marlin/src/HAL/AVR/math.h
index 7ede4accc09e..7dd1018ff199 100644
--- a/Marlin/src/HAL/AVR/math.h
+++ b/Marlin/src/HAL/AVR/math.h
@@ -35,7 +35,7 @@
// C B A is longIn1
// D C B A is longIn2
//
-static FORCE_INLINE uint16_t MultiU24X32toH16(uint32_t longIn1, uint32_t longIn2) {
+FORCE_INLINE static uint16_t MultiU24X32toH16(uint32_t longIn1, uint32_t longIn2) {
uint8_t tmp1;
uint8_t tmp2;
uint16_t intRes;
@@ -89,7 +89,7 @@ static FORCE_INLINE uint16_t MultiU24X32toH16(uint32_t longIn1, uint32_t longIn2
// uses:
// r26 to store 0
// r27 to store the byte 1 of the 24 bit result
-static FORCE_INLINE uint16_t MultiU16X8toH16(uint8_t charIn1, uint16_t intIn2) {
+FORCE_INLINE static uint16_t MultiU16X8toH16(uint8_t charIn1, uint16_t intIn2) {
uint8_t tmp;
uint16_t intRes;
__asm__ __volatile__ (
diff --git a/Marlin/src/HAL/AVR/pinsDebug.h b/Marlin/src/HAL/AVR/pinsDebug.h
index dac6b1b150bd..dab4e4471524 100644
--- a/Marlin/src/HAL/AVR/pinsDebug.h
+++ b/Marlin/src/HAL/AVR/pinsDebug.h
@@ -2,6 +2,9 @@
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
@@ -38,7 +41,7 @@
// portModeRegister takes a different argument
#define digitalPinToTimer_DEBUG(p) digitalPinToTimer(p)
#define digitalPinToBitMask_DEBUG(p) digitalPinToBitMask(p)
- #define digitalPinToPort_DEBUG(p) digitalPinToPort_Teensy(p)
+ #define digitalPinToPort_DEBUG(p) digitalPinToPort(p)
#define GET_PINMODE(pin) (*portModeRegister(pin) & digitalPinToBitMask_DEBUG(pin))
#elif AVR_ATmega2560_FAMILY_PLUS_70 // So we can access/display all the pins on boards using more than 70
@@ -71,7 +74,7 @@
#define MULTI_NAME_PAD 26 // space needed to be pretty if not first name assigned to a pin
void PRINT_ARRAY_NAME(uint8_t x) {
- char *name_mem_pointer = (char*)pgm_read_ptr(&pin_array[x].name);
+ PGM_P const name_mem_pointer = (PGM_P)pgm_read_ptr(&pin_array[x].name);
LOOP_L_N(y, MAX_NAME_LENGTH) {
char temp_char = pgm_read_byte(name_mem_pointer + y);
if (temp_char != 0)
@@ -99,7 +102,7 @@ void PRINT_ARRAY_NAME(uint8_t x) {
return true; \
} else return false
-
+#define ABTEST(N) defined(TCCR##N##A) && defined(COM##N##A1)
/**
* Print a pin's PWM status.
@@ -110,7 +113,7 @@ static bool pwm_status(uint8_t pin) {
switch (digitalPinToTimer_DEBUG(pin)) {
- #if defined(TCCR0A) && defined(COM0A1)
+ #if ABTEST(0)
#ifdef TIMER0A
#if !AVR_AT90USB1286_FAMILY // not available in Teensyduino type IDEs
PWM_CASE(0, A);
@@ -119,20 +122,20 @@ static bool pwm_status(uint8_t pin) {
PWM_CASE(0, B);
#endif
- #if defined(TCCR1A) && defined(COM1A1)
+ #if ABTEST(1)
PWM_CASE(1, A);
PWM_CASE(1, B);
- #if defined(COM1C1) && defined(TIMER1C)
- PWM_CASE(1, C);
- #endif
+ #if defined(COM1C1) && defined(TIMER1C)
+ PWM_CASE(1, C);
+ #endif
#endif
- #if defined(TCCR2A) && defined(COM2A1)
+ #if ABTEST(2)
PWM_CASE(2, A);
PWM_CASE(2, B);
#endif
- #if defined(TCCR3A) && defined(COM3A1)
+ #if ABTEST(3)
PWM_CASE(3, A);
PWM_CASE(3, B);
#ifdef COM3C1
@@ -146,7 +149,7 @@ static bool pwm_status(uint8_t pin) {
PWM_CASE(4, C);
#endif
- #if defined(TCCR5A) && defined(COM5A1)
+ #if ABTEST(5)
PWM_CASE(5, A);
PWM_CASE(5, B);
PWM_CASE(5, C);
@@ -163,16 +166,16 @@ static bool pwm_status(uint8_t pin) {
const volatile uint8_t* const PWM_other[][3] PROGMEM = {
{ &TCCR0A, &TCCR0B, &TIMSK0 },
{ &TCCR1A, &TCCR1B, &TIMSK1 },
- #if defined(TCCR2A) && defined(COM2A1)
+ #if ABTEST(2)
{ &TCCR2A, &TCCR2B, &TIMSK2 },
#endif
- #if defined(TCCR3A) && defined(COM3A1)
+ #if ABTEST(3)
{ &TCCR3A, &TCCR3B, &TIMSK3 },
#endif
#ifdef TCCR4A
{ &TCCR4A, &TCCR4B, &TIMSK4 },
#endif
- #if defined(TCCR5A) && defined(COM5A1)
+ #if ABTEST(5)
{ &TCCR5A, &TCCR5B, &TIMSK5 },
#endif
};
@@ -192,11 +195,11 @@ const volatile uint8_t* const PWM_OCR[][3] PROGMEM = {
{ (const uint8_t*)&OCR1A, (const uint8_t*)&OCR1B, 0 },
#endif
- #if defined(TCCR2A) && defined(COM2A1)
+ #if ABTEST(2)
{ &OCR2A, &OCR2B, 0 },
#endif
- #if defined(TCCR3A) && defined(COM3A1)
+ #if ABTEST(3)
#ifdef COM3C1
{ (const uint8_t*)&OCR3A, (const uint8_t*)&OCR3B, (const uint8_t*)&OCR3C },
#else
@@ -208,7 +211,7 @@ const volatile uint8_t* const PWM_OCR[][3] PROGMEM = {
{ (const uint8_t*)&OCR4A, (const uint8_t*)&OCR4B, (const uint8_t*)&OCR4C },
#endif
- #if defined(TCCR5A) && defined(COM5A1)
+ #if ABTEST(5)
{ (const uint8_t*)&OCR5A, (const uint8_t*)&OCR5B, (const uint8_t*)&OCR5C },
#endif
};
@@ -235,9 +238,9 @@ static void print_is_also_tied() { SERIAL_ECHOPGM(" is also tied to this pin");
inline void com_print(const uint8_t N, const uint8_t Z) {
const uint8_t *TCCRA = (uint8_t*)TCCR_A(N);
- SERIAL_ECHOPGM(" COM");
- SERIAL_CHAR('0' + N, Z);
- SERIAL_ECHOPAIR(": ", int((*TCCRA >> (6 - Z * 2)) & 0x03));
+ SERIAL_ECHOPGM(" COM", AS_DIGIT(N));
+ SERIAL_CHAR(Z);
+ SERIAL_ECHOPGM(": ", int((*TCCRA >> (6 - Z * 2)) & 0x03));
}
void timer_prefix(uint8_t T, char L, uint8_t N) { // T - timer L - pwm N - WGM bit layout
@@ -247,8 +250,8 @@ void timer_prefix(uint8_t T, char L, uint8_t N) { // T - timer L - pwm N -
uint8_t WGM = (((*TCCRB & _BV(WGM_2)) >> 1) | (*TCCRA & (_BV(WGM_0) | _BV(WGM_1))));
if (N == 4) WGM |= ((*TCCRB & _BV(WGM_3)) >> 1);
- SERIAL_ECHOPGM(" TIMER");
- SERIAL_CHAR(T + '0', L);
+ SERIAL_ECHOPGM(" TIMER", AS_DIGIT(T));
+ SERIAL_CHAR(L);
SERIAL_ECHO_SP(3);
if (N == 3) {
@@ -259,22 +262,14 @@ void timer_prefix(uint8_t T, char L, uint8_t N) { // T - timer L - pwm N -
const uint16_t *OCRVAL16 = (uint16_t*)OCR_VAL(T, L - 'A');
PWM_PRINT(*OCRVAL16);
}
- SERIAL_ECHOPAIR(" WGM: ", WGM);
+ SERIAL_ECHOPGM(" WGM: ", WGM);
com_print(T,L);
- SERIAL_ECHOPAIR(" CS: ", (*TCCRB & (_BV(CS_0) | _BV(CS_1) | _BV(CS_2)) ));
-
- SERIAL_ECHOPGM(" TCCR");
- SERIAL_CHAR(T + '0');
- SERIAL_ECHOPAIR("A: ", *TCCRA);
-
- SERIAL_ECHOPGM(" TCCR");
- SERIAL_CHAR(T + '0');
- SERIAL_ECHOPAIR("B: ", *TCCRB);
+ SERIAL_ECHOPGM(" CS: ", (*TCCRB & (_BV(CS_0) | _BV(CS_1) | _BV(CS_2)) ));
+ SERIAL_ECHOPGM(" TCCR", AS_DIGIT(T), "A: ", *TCCRA);
+ SERIAL_ECHOPGM(" TCCR", AS_DIGIT(T), "B: ", *TCCRB);
const uint8_t *TMSK = (uint8_t*)TIMSK(T);
- SERIAL_ECHOPGM(" TIMSK");
- SERIAL_CHAR(T + '0');
- SERIAL_ECHOPAIR(": ", *TMSK);
+ SERIAL_ECHOPGM(" TIMSK", AS_DIGIT(T), ": ", *TMSK);
const uint8_t OCIE = L - 'A' + 1;
if (N == 3) { if (WGM == 0 || WGM == 2 || WGM == 4 || WGM == 6) err_is_counter(); }
@@ -286,7 +281,7 @@ void timer_prefix(uint8_t T, char L, uint8_t N) { // T - timer L - pwm N -
static void pwm_details(uint8_t pin) {
switch (digitalPinToTimer_DEBUG(pin)) {
- #if defined(TCCR0A) && defined(COM0A1)
+ #if ABTEST(0)
#ifdef TIMER0A
#if !AVR_AT90USB1286_FAMILY // not available in Teensyduino type IDEs
case TIMER0A: timer_prefix(0, 'A', 3); break;
@@ -295,7 +290,7 @@ static void pwm_details(uint8_t pin) {
case TIMER0B: timer_prefix(0, 'B', 3); break;
#endif
- #if defined(TCCR1A) && defined(COM1A1)
+ #if ABTEST(1)
case TIMER1A: timer_prefix(1, 'A', 4); break;
case TIMER1B: timer_prefix(1, 'B', 4); break;
#if defined(COM1C1) && defined(TIMER1C)
@@ -303,12 +298,12 @@ static void pwm_details(uint8_t pin) {
#endif
#endif
- #if defined(TCCR2A) && defined(COM2A1)
+ #if ABTEST(2)
case TIMER2A: timer_prefix(2, 'A', 3); break;
case TIMER2B: timer_prefix(2, 'B', 3); break;
#endif
- #if defined(TCCR3A) && defined(COM3A1)
+ #if ABTEST(3)
case TIMER3A: timer_prefix(3, 'A', 4); break;
case TIMER3B: timer_prefix(3, 'B', 4); break;
#ifdef COM3C1
@@ -322,7 +317,7 @@ static void pwm_details(uint8_t pin) {
case TIMER4C: timer_prefix(4, 'C', 4); break;
#endif
- #if defined(TCCR5A) && defined(COM5A1)
+ #if ABTEST(5)
case TIMER5A: timer_prefix(5, 'A', 4); break;
case TIMER5B: timer_prefix(5, 'B', 4); break;
case TIMER5C: timer_prefix(5, 'C', 4); break;
@@ -356,7 +351,6 @@ static void pwm_details(uint8_t pin) {
#endif
} // pwm_details
-
#ifndef digitalRead_mod // Use Teensyduino's version of digitalRead - it doesn't disable the PWMs
int digitalRead_mod(const int8_t pin) { // same as digitalRead except the PWM stop section has been removed
const uint8_t port = digitalPinToPort_DEBUG(pin);
@@ -401,3 +395,6 @@ static void pwm_details(uint8_t pin) {
#endif
#define PRINT_PIN(p) do{ sprintf_P(buffer, PSTR("%3d "), p); SERIAL_ECHO(buffer); }while(0)
+#define PRINT_PIN_ANALOG(p) do{ sprintf_P(buffer, PSTR(" (A%2d) "), DIGITAL_PIN_TO_ANALOG_PIN(pin)); SERIAL_ECHO(buffer); }while(0)
+
+#undef ABTEST
diff --git a/Marlin/src/HAL/AVR/pinsDebug_Teensyduino.h b/Marlin/src/HAL/AVR/pinsDebug_Teensyduino.h
index 051972a861ad..582ae79ba787 100644
--- a/Marlin/src/HAL/AVR/pinsDebug_Teensyduino.h
+++ b/Marlin/src/HAL/AVR/pinsDebug_Teensyduino.h
@@ -2,6 +2,9 @@
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
diff --git a/Marlin/src/HAL/AVR/pinsDebug_plus_70.h b/Marlin/src/HAL/AVR/pinsDebug_plus_70.h
index db3fdf1f767b..d9aa44c3cb15 100644
--- a/Marlin/src/HAL/AVR/pinsDebug_plus_70.h
+++ b/Marlin/src/HAL/AVR/pinsDebug_plus_70.h
@@ -2,6 +2,9 @@
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
diff --git a/Marlin/src/HAL/AVR/spi_pins.h b/Marlin/src/HAL/AVR/spi_pins.h
index f3fa78e2bfaf..831972938a7b 100644
--- a/Marlin/src/HAL/AVR/spi_pins.h
+++ b/Marlin/src/HAL/AVR/spi_pins.h
@@ -51,15 +51,15 @@
#define AVR_SS_PIN 16
#endif
-#ifndef SCK_PIN
- #define SCK_PIN AVR_SCK_PIN
+#ifndef SD_SCK_PIN
+ #define SD_SCK_PIN AVR_SCK_PIN
#endif
-#ifndef MISO_PIN
- #define MISO_PIN AVR_MISO_PIN
+#ifndef SD_MISO_PIN
+ #define SD_MISO_PIN AVR_MISO_PIN
#endif
-#ifndef MOSI_PIN
- #define MOSI_PIN AVR_MOSI_PIN
+#ifndef SD_MOSI_PIN
+ #define SD_MOSI_PIN AVR_MOSI_PIN
#endif
-#ifndef SS_PIN
- #define SS_PIN AVR_SS_PIN
+#ifndef SD_SS_PIN
+ #define SD_SS_PIN AVR_SS_PIN
#endif
diff --git a/Marlin/src/HAL/AVR/timers.h b/Marlin/src/HAL/AVR/timers.h
index 82eb8b14b161..33c3880b6b99 100644
--- a/Marlin/src/HAL/AVR/timers.h
+++ b/Marlin/src/HAL/AVR/timers.h
@@ -34,14 +34,14 @@ typedef uint16_t hal_timer_t;
#define HAL_TIMER_RATE ((F_CPU) / 8) // i.e., 2MHz or 2.5MHz
-#ifndef STEP_TIMER_NUM
- #define STEP_TIMER_NUM 1
+#ifndef MF_TIMER_STEP
+ #define MF_TIMER_STEP 1
#endif
-#ifndef PULSE_TIMER_NUM
- #define PULSE_TIMER_NUM STEP_TIMER_NUM
+#ifndef MF_TIMER_PULSE
+ #define MF_TIMER_PULSE MF_TIMER_STEP
#endif
-#ifndef TEMP_TIMER_NUM
- #define TEMP_TIMER_NUM 0
+#ifndef MF_TIMER_TEMP
+ #define MF_TIMER_TEMP 0
#endif
#define TEMP_TIMER_FREQUENCY ((F_CPU) / 64.0 / 256.0)
@@ -58,13 +58,13 @@ typedef uint16_t hal_timer_t;
#define DISABLE_STEPPER_DRIVER_INTERRUPT() CBI(TIMSK1, OCIE1A)
#define STEPPER_ISR_ENABLED() TEST(TIMSK1, OCIE1A)
-#define ENABLE_TEMPERATURE_INTERRUPT() SBI(TIMSK0, OCIE0B)
-#define DISABLE_TEMPERATURE_INTERRUPT() CBI(TIMSK0, OCIE0B)
-#define TEMPERATURE_ISR_ENABLED() TEST(TIMSK0, OCIE0B)
+#define ENABLE_TEMPERATURE_INTERRUPT() SBI(TIMSK0, OCIE0A)
+#define DISABLE_TEMPERATURE_INTERRUPT() CBI(TIMSK0, OCIE0A)
+#define TEMPERATURE_ISR_ENABLED() TEST(TIMSK0, OCIE0A)
FORCE_INLINE void HAL_timer_start(const uint8_t timer_num, const uint32_t) {
switch (timer_num) {
- case STEP_TIMER_NUM:
+ case MF_TIMER_STEP:
// waveform generation = 0100 = CTC
SET_WGM(1, CTC_OCRnA);
@@ -84,10 +84,10 @@ FORCE_INLINE void HAL_timer_start(const uint8_t timer_num, const uint32_t) {
TCNT1 = 0;
break;
- case TEMP_TIMER_NUM:
+ case MF_TIMER_TEMP:
// Use timer0 for temperature measurement
// Interleave temperature interrupt with millies interrupt
- OCR0B = 128;
+ OCR0A = 128;
break;
}
}
@@ -109,12 +109,12 @@ FORCE_INLINE void HAL_timer_start(const uint8_t timer_num, const uint32_t) {
* (otherwise, characters will be lost due to UART overflow).
* Then: Stepper, Endstops, Temperature, and -finally- all others.
*/
-#define HAL_timer_isr_prologue(TIMER_NUM)
-#define HAL_timer_isr_epilogue(TIMER_NUM)
+#define HAL_timer_isr_prologue(T) NOOP
+#define HAL_timer_isr_epilogue(T) NOOP
-/* 18 cycles maximum latency */
#ifndef HAL_STEP_TIMER_ISR
+/* 18 cycles maximum latency */
#define HAL_STEP_TIMER_ISR() \
extern "C" void TIMER1_COMPA_vect() __attribute__ ((signal, naked, used, externally_visible)); \
extern "C" void TIMER1_COMPA_vect_bottom() asm ("TIMER1_COMPA_vect_bottom") __attribute__ ((used, externally_visible, noinline)); \
@@ -180,7 +180,7 @@ void TIMER1_COMPA_vect() { \
: \
: [timsk0] "i" ((uint16_t)&TIMSK0), \
[timsk1] "i" ((uint16_t)&TIMSK1), \
- [msk0] "M" ((uint8_t)(1<
+#include
-uint8_t u8g_bitData, u8g_bitNotData, u8g_bitClock, u8g_bitNotClock;
-volatile uint8_t *u8g_outData, *u8g_outClock;
+static uint8_t u8g_bitData, u8g_bitNotData, u8g_bitClock, u8g_bitNotClock;
+static volatile uint8_t *u8g_outData, *u8g_outClock;
static void u8g_com_arduino_init_shift_out(uint8_t dataPin, uint8_t clockPin) {
u8g_outData = portOutputRegister(digitalPinToPort(dataPin));
diff --git a/Marlin/src/HAL/AVR/watchdog.cpp b/Marlin/src/HAL/AVR/watchdog.cpp
deleted file mode 100644
index 3f10c4adff81..000000000000
--- a/Marlin/src/HAL/AVR/watchdog.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-/**
- * Marlin 3D Printer Firmware
- * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
- *
- * Based on Sprinter and grbl.
- * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *
- */
-#ifdef __AVR__
-
-#include "../../inc/MarlinConfig.h"
-
-#if ENABLED(USE_WATCHDOG)
-
-#include "watchdog.h"
-
-#include "../../MarlinCore.h"
-
-// Initialize watchdog with 8s timeout, if possible. Otherwise, make it 4s.
-void watchdog_init() {
- #if ENABLED(WATCHDOG_DURATION_8S) && defined(WDTO_8S)
- #define WDTO_NS WDTO_8S
- #else
- #define WDTO_NS WDTO_4S
- #endif
- #if ENABLED(WATCHDOG_RESET_MANUAL)
- // Enable the watchdog timer, but only for the interrupt.
- // Take care, as this requires the correct order of operation, with interrupts disabled.
- // See the datasheet of any AVR chip for details.
- wdt_reset();
- cli();
- _WD_CONTROL_REG = _BV(_WD_CHANGE_BIT) | _BV(WDE);
- _WD_CONTROL_REG = _BV(WDIE) | (WDTO_NS & 0x07) | ((WDTO_NS & 0x08) << 2); // WDTO_NS directly does not work. bit 0-2 are consecutive in the register but the highest value bit is at bit 5
- // So worked for up to WDTO_2S
- sei();
- wdt_reset();
- #else
- wdt_enable(WDTO_NS); // The function handles the upper bit correct.
- #endif
- //delay(10000); // test it!
-}
-
-//===========================================================================
-//=================================== ISR ===================================
-//===========================================================================
-
-// Watchdog timer interrupt, called if main program blocks >4sec and manual reset is enabled.
-#if ENABLED(WATCHDOG_RESET_MANUAL)
- ISR(WDT_vect) {
- sei(); // With the interrupt driven serial we need to allow interrupts.
- SERIAL_ERROR_MSG(STR_WATCHDOG_FIRED);
- minkill(); // interrupt-safe final kill and infinite loop
- }
-#endif
-
-#endif // USE_WATCHDOG
-#endif // __AVR__
diff --git a/Marlin/src/HAL/AVR/watchdog.h b/Marlin/src/HAL/AVR/watchdog.h
deleted file mode 100644
index a16c88b35e87..000000000000
--- a/Marlin/src/HAL/AVR/watchdog.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * Marlin 3D Printer Firmware
- * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
- *
- * Based on Sprinter and grbl.
- * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *
- */
-#pragma once
-
-#include
-
-// Initialize watchdog with a 4 second interrupt time
-void watchdog_init();
-
-// Reset watchdog. MUST be called at least every 4 seconds after the
-// first watchdog_init or AVR will go into emergency procedures.
-inline void HAL_watchdog_refresh() { wdt_reset(); }
diff --git a/Marlin/src/HAL/DUE/DebugMonitor.cpp b/Marlin/src/HAL/DUE/DebugMonitor.cpp
deleted file mode 100644
index 79759151d891..000000000000
--- a/Marlin/src/HAL/DUE/DebugMonitor.cpp
+++ /dev/null
@@ -1,342 +0,0 @@
-/**
- * Marlin 3D Printer Firmware
- * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
- *
- * Based on Sprinter and grbl.
- * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *
- */
-#ifdef ARDUINO_ARCH_SAM
-
-#include "../../core/macros.h"
-#include "../../core/serial.h"
-
-#include "../shared/backtrace/unwinder.h"
-#include "../shared/backtrace/unwmemaccess.h"
-
-#include
-
-// Debug monitor that dumps to the Programming port all status when
-// an exception or WDT timeout happens - And then resets the board
-
-// All the Monitor routines must run with interrupts disabled and
-// under an ISR execution context. That is why we cannot reuse the
-// Serial interrupt routines or any C runtime, as we don't know the
-// state we are when running them
-
-// A SW memory barrier, to ensure GCC does not overoptimize loops
-#define sw_barrier() __asm__ volatile("": : :"memory");
-
-// (re)initialize UART0 as a monitor output to 250000,n,8,1
-static void TXBegin() {
-
- // Disable UART interrupt in NVIC
- NVIC_DisableIRQ( UART_IRQn );
-
- // We NEED memory barriers to ensure Interrupts are actually disabled!
- // ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
- __DSB();
- __ISB();
-
- // Disable clock
- pmc_disable_periph_clk( ID_UART );
-
- // Configure PMC
- pmc_enable_periph_clk( ID_UART );
-
- // Disable PDC channel
- UART->UART_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS;
-
- // Reset and disable receiver and transmitter
- UART->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS;
-
- // Configure mode: 8bit, No parity, 1 bit stop
- UART->UART_MR = UART_MR_CHMODE_NORMAL | US_MR_CHRL_8_BIT | US_MR_NBSTOP_1_BIT | UART_MR_PAR_NO;
-
- // Configure baudrate (asynchronous, no oversampling) to BAUDRATE bauds
- UART->UART_BRGR = (SystemCoreClock / (BAUDRATE << 4));
-
- // Enable receiver and transmitter
- UART->UART_CR = UART_CR_RXEN | UART_CR_TXEN;
-}
-
-// Send character through UART with no interrupts
-static void TX(char c) {
- while (!(UART->UART_SR & UART_SR_TXRDY)) { WDT_Restart(WDT); sw_barrier(); };
- UART->UART_THR = c;
-}
-
-// Send String through UART
-static void TX(const char* s) {
- while (*s) TX(*s++);
-}
-
-static void TXDigit(uint32_t d) {
- if (d < 10) TX((char)(d+'0'));
- else if (d < 16) TX((char)(d+'A'-10));
- else TX('?');
-}
-
-// Send Hex number thru UART
-static void TXHex(uint32_t v) {
- TX("0x");
- for (uint8_t i = 0; i < 8; i++, v <<= 4)
- TXDigit((v >> 28) & 0xF);
-}
-
-// Send Decimal number thru UART
-static void TXDec(uint32_t v) {
- if (!v) {
- TX('0');
- return;
- }
-
- char nbrs[14];
- char *p = &nbrs[0];
- while (v != 0) {
- *p++ = '0' + (v % 10);
- v /= 10;
- }
- do {
- p--;
- TX(*p);
- } while (p != &nbrs[0]);
-}
-
-// Dump a backtrace entry
-static bool UnwReportOut(void* ctx, const UnwReport* bte) {
- int* p = (int*)ctx;
-
- (*p)++;
- TX('#'); TXDec(*p); TX(" : ");
- TX(bte->name?bte->name:"unknown"); TX('@'); TXHex(bte->function);
- TX('+'); TXDec(bte->address - bte->function);
- TX(" PC:");TXHex(bte->address); TX('\n');
- return true;
-}
-
-#ifdef UNW_DEBUG
- void UnwPrintf(const char* format, ...) {
- char dest[256];
- va_list argptr;
- va_start(argptr, format);
- vsprintf(dest, format, argptr);
- va_end(argptr);
- TX(&dest[0]);
- }
-#endif
-
-/* Table of function pointers for passing to the unwinder */
-static const UnwindCallbacks UnwCallbacks = {
- UnwReportOut,
- UnwReadW,
- UnwReadH,
- UnwReadB
- #ifdef UNW_DEBUG
- , UnwPrintf
- #endif
-};
-
-/**
- * HardFaultHandler_C:
- * This is called from the HardFault_HandlerAsm with a pointer the Fault stack
- * as the parameter. We can then read the values from the stack and place them
- * into local variables for ease of reading.
- * We then read the various Fault Status and Address Registers to help decode
- * cause of the fault.
- * The function ends with a BKPT instruction to force control back into the debugger
- */
-extern "C"
-void HardFault_HandlerC(unsigned long *sp, unsigned long lr, unsigned long cause) {
-
- static const char* causestr[] = {
- "NMI","Hard","Mem","Bus","Usage","Debug","WDT","RSTC"
- };
-
- UnwindFrame btf;
-
- // Dump report to the Programming port (interrupts are DISABLED)
- TXBegin();
- TX("\n\n## Software Fault detected ##\n");
- TX("Cause: "); TX(causestr[cause]); TX('\n');
-
- TX("R0 : "); TXHex(((unsigned long)sp[0])); TX('\n');
- TX("R1 : "); TXHex(((unsigned long)sp[1])); TX('\n');
- TX("R2 : "); TXHex(((unsigned long)sp[2])); TX('\n');
- TX("R3 : "); TXHex(((unsigned long)sp[3])); TX('\n');
- TX("R12 : "); TXHex(((unsigned long)sp[4])); TX('\n');
- TX("LR : "); TXHex(((unsigned long)sp[5])); TX('\n');
- TX("PC : "); TXHex(((unsigned long)sp[6])); TX('\n');
- TX("PSR : "); TXHex(((unsigned long)sp[7])); TX('\n');
-
- // Configurable Fault Status Register
- // Consists of MMSR, BFSR and UFSR
- TX("CFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED28)))); TX('\n');
-
- // Hard Fault Status Register
- TX("HFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED2C)))); TX('\n');
-
- // Debug Fault Status Register
- TX("DFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED30)))); TX('\n');
-
- // Auxiliary Fault Status Register
- TX("AFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED3C)))); TX('\n');
-
- // Read the Fault Address Registers. These may not contain valid values.
- // Check BFARVALID/MMARVALID to see if they are valid values
- // MemManage Fault Address Register
- TX("MMAR : "); TXHex((*((volatile unsigned long *)(0xE000ED34)))); TX('\n');
-
- // Bus Fault Address Register
- TX("BFAR : "); TXHex((*((volatile unsigned long *)(0xE000ED38)))); TX('\n');
-
- TX("ExcLR: "); TXHex(lr); TX('\n');
- TX("ExcSP: "); TXHex((unsigned long)sp); TX('\n');
-
- btf.sp = ((unsigned long)sp) + 8*4; // The original stack pointer
- btf.fp = btf.sp;
- btf.lr = ((unsigned long)sp[5]);
- btf.pc = ((unsigned long)sp[6]) | 1; // Force Thumb, as CORTEX only support it
-
- // Perform a backtrace
- TX("\nBacktrace:\n\n");
- int ctr = 0;
- UnwindStart(&btf, &UnwCallbacks, &ctr);
-
- // Disable all NVIC interrupts
- NVIC->ICER[0] = 0xFFFFFFFF;
- NVIC->ICER[1] = 0xFFFFFFFF;
-
- // Relocate VTOR table to default position
- SCB->VTOR = 0;
-
- // Disable USB
- otg_disable();
-
- // Restart watchdog
- WDT_Restart(WDT);
-
- // Reset controller
- NVIC_SystemReset();
- for (;;) WDT_Restart(WDT);
-}
-
-__attribute__((naked)) void NMI_Handler() {
- __asm__ __volatile__ (
- ".syntax unified" "\n\t"
- A("tst lr, #4")
- A("ite eq")
- A("mrseq r0, msp")
- A("mrsne r0, psp")
- A("mov r1,lr")
- A("mov r2,#0")
- A("b HardFault_HandlerC")
- );
-}
-
-__attribute__((naked)) void HardFault_Handler() {
- __asm__ __volatile__ (
- ".syntax unified" "\n\t"
- A("tst lr, #4")
- A("ite eq")
- A("mrseq r0, msp")
- A("mrsne r0, psp")
- A("mov r1,lr")
- A("mov r2,#1")
- A("b HardFault_HandlerC")
- );
-}
-
-__attribute__((naked)) void MemManage_Handler() {
- __asm__ __volatile__ (
- ".syntax unified" "\n\t"
- A("tst lr, #4")
- A("ite eq")
- A("mrseq r0, msp")
- A("mrsne r0, psp")
- A("mov r1,lr")
- A("mov r2,#2")
- A("b HardFault_HandlerC")
- );
-}
-
-__attribute__((naked)) void BusFault_Handler() {
- __asm__ __volatile__ (
- ".syntax unified" "\n\t"
- A("tst lr, #4")
- A("ite eq")
- A("mrseq r0, msp")
- A("mrsne r0, psp")
- A("mov r1,lr")
- A("mov r2,#3")
- A("b HardFault_HandlerC")
- );
-}
-
-__attribute__((naked)) void UsageFault_Handler() {
- __asm__ __volatile__ (
- ".syntax unified" "\n\t"
- A("tst lr, #4")
- A("ite eq")
- A("mrseq r0, msp")
- A("mrsne r0, psp")
- A("mov r1,lr")
- A("mov r2,#4")
- A("b HardFault_HandlerC")
- );
-}
-
-__attribute__((naked)) void DebugMon_Handler() {
- __asm__ __volatile__ (
- ".syntax unified" "\n\t"
- A("tst lr, #4")
- A("ite eq")
- A("mrseq r0, msp")
- A("mrsne r0, psp")
- A("mov r1,lr")
- A("mov r2,#5")
- A("b HardFault_HandlerC")
- );
-}
-
-/* This is NOT an exception, it is an interrupt handler - Nevertheless, the framing is the same */
-__attribute__((naked)) void WDT_Handler() {
- __asm__ __volatile__ (
- ".syntax unified" "\n\t"
- A("tst lr, #4")
- A("ite eq")
- A("mrseq r0, msp")
- A("mrsne r0, psp")
- A("mov r1,lr")
- A("mov r2,#6")
- A("b HardFault_HandlerC")
- );
-}
-
-__attribute__((naked)) void RSTC_Handler() {
- __asm__ __volatile__ (
- ".syntax unified" "\n\t"
- A("tst lr, #4")
- A("ite eq")
- A("mrseq r0, msp")
- A("mrsne r0, psp")
- A("mov r1,lr")
- A("mov r2,#7")
- A("b HardFault_HandlerC")
- );
-}
-
-#endif // ARDUINO_ARCH_SAM
diff --git a/Marlin/src/HAL/DUE/HAL.cpp b/Marlin/src/HAL/DUE/HAL.cpp
index 6ce85a4643bb..4353f1649732 100644
--- a/Marlin/src/HAL/DUE/HAL.cpp
+++ b/Marlin/src/HAL/DUE/HAL.cpp
@@ -25,7 +25,7 @@
#ifdef ARDUINO_ARCH_SAM
#include "../../inc/MarlinConfig.h"
-#include "HAL.h"
+#include "../../MarlinCore.h"
#include
#include "usb/usb_task.h"
@@ -34,36 +34,33 @@
// Public Variables
// ------------------------
-uint16_t HAL_adc_result;
+uint16_t MarlinHAL::adc_result;
// ------------------------
// Public functions
// ------------------------
-// HAL initialization task
-void HAL_init() {
- // Initialize the USB stack
+#if ENABLED(POSTMORTEM_DEBUGGING)
+ extern void install_min_serial();
+#endif
+
+void MarlinHAL::init() {
#if ENABLED(SDSUPPORT)
OUT_WRITE(SDSS, HIGH); // Try to set SDSS inactive before any other SPI users start up
#endif
- usb_task_init();
+ usb_task_init(); // Initialize the USB stack
+ TERN_(POSTMORTEM_DEBUGGING, install_min_serial()); // Install the min serial handler
}
-// HAL idle task
-void HAL_idletask() {
- // Perform USB stack housekeeping
- usb_task_idle();
+void MarlinHAL::init_board() {
+ #ifdef BOARD_INIT
+ BOARD_INIT();
+ #endif
}
-// Disable interrupts
-void cli() { noInterrupts(); }
-
-// Enable interrupts
-void sei() { interrupts(); }
+void MarlinHAL::idletask() { usb_task_idle(); } // Perform USB stack housekeeping
-void HAL_clear_reset_source() { }
-
-uint8_t HAL_get_reset_source() {
+uint8_t MarlinHAL::get_reset_source() {
switch ((RSTC->RSTC_SR >> 8) & 0x07) {
case 0: return RST_POWER_ON;
case 1: return RST_BACKUP;
@@ -74,11 +71,105 @@ uint8_t HAL_get_reset_source() {
}
}
-void _delay_ms(const int delay_ms) {
- // Todo: port for Due?
- delay(delay_ms);
+void MarlinHAL::reboot() { rstc_start_software_reset(RSTC); }
+
+// ------------------------
+// Watchdog Timer
+// ------------------------
+
+#if ENABLED(USE_WATCHDOG)
+
+ // Initialize watchdog - On SAM3X, Watchdog was already configured
+ // and enabled or disabled at startup, so no need to reconfigure it
+ // here.
+ void MarlinHAL::watchdog_init() { WDT_Restart(WDT); } // Reset watchdog to start clean
+
+ // Reset watchdog. MUST be called at least every 4 seconds after the
+ // first watchdog_init or AVR will go into emergency procedures.
+ void MarlinHAL::watchdog_refresh() { watchdogReset(); }
+
+#endif
+
+// Override Arduino runtime to either config or disable the watchdog
+//
+// We need to configure the watchdog as soon as possible in the boot
+// process, because watchdog initialization at hardware reset on SAM3X8E
+// is unreliable, and there is risk of unintended resets if we delay
+// that initialization to a later time.
+void watchdogSetup() {
+
+ #if ENABLED(USE_WATCHDOG)
+
+ // 4 seconds timeout
+ uint32_t timeout = TERN(WATCHDOG_DURATION_8S, 8000, 4000);
+
+ // Calculate timeout value in WDT counter ticks: This assumes
+ // the slow clock is running at 32.768 kHz watchdog
+ // frequency is therefore 32768 / 128 = 256 Hz
+ timeout = (timeout << 8) / 1000;
+ if (timeout == 0)
+ timeout = 1;
+ else if (timeout > 0xFFF)
+ timeout = 0xFFF;
+
+ // We want to enable the watchdog with the specified timeout
+ uint32_t value =
+ WDT_MR_WDV(timeout) | // With the specified timeout
+ WDT_MR_WDD(timeout) | // and no invalid write window
+ #if !(SAMV70 || SAMV71 || SAME70 || SAMS70)
+ WDT_MR_WDRPROC | // WDT fault resets processor only - We want
+ // to keep PIO controller state
+ #endif
+ WDT_MR_WDDBGHLT | // WDT stops in debug state.
+ WDT_MR_WDIDLEHLT; // WDT stops in idle state.
+
+ #if ENABLED(WATCHDOG_RESET_MANUAL)
+ // We enable the watchdog timer, but only for the interrupt.
+
+ // Configure WDT to only trigger an interrupt
+ value |= WDT_MR_WDFIEN; // Enable WDT fault interrupt.
+
+ // Disable WDT interrupt (just in case, to avoid triggering it!)
+ NVIC_DisableIRQ(WDT_IRQn);
+
+ // We NEED memory barriers to ensure Interrupts are actually disabled!
+ // ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
+ __DSB();
+ __ISB();
+
+ // Initialize WDT with the given parameters
+ WDT_Enable(WDT, value);
+
+ // Configure and enable WDT interrupt.
+ NVIC_ClearPendingIRQ(WDT_IRQn);
+ NVIC_SetPriority(WDT_IRQn, 0); // Use highest priority, so we detect all kinds of lockups
+ NVIC_EnableIRQ(WDT_IRQn);
+
+ #else
+
+ // a WDT fault triggers a reset
+ value |= WDT_MR_WDRSTEN;
+
+ // Initialize WDT with the given parameters
+ WDT_Enable(WDT, value);
+
+ #endif
+
+ // Reset the watchdog
+ WDT_Restart(WDT);
+
+ #else
+
+ // Make sure to completely disable the Watchdog
+ WDT_Disable(WDT);
+
+ #endif
}
+// ------------------------
+// Free Memory Accessor
+// ------------------------
+
extern "C" {
extern unsigned int _ebss; // end of bss section
}
@@ -90,16 +181,21 @@ int freeMemory() {
}
// ------------------------
-// ADC
+// Serial Ports
// ------------------------
-void HAL_adc_start_conversion(const uint8_t ch) {
- HAL_adc_result = analogRead(ch);
-}
-
-uint16_t HAL_adc_get_result() {
- // nop
- return HAL_adc_result;
-}
+// Forward the default serial ports
+#if USING_HW_SERIAL0
+ DefaultSerial1 MSerial0(false, Serial);
+#endif
+#if USING_HW_SERIAL1
+ DefaultSerial2 MSerial1(false, Serial1);
+#endif
+#if USING_HW_SERIAL2
+ DefaultSerial3 MSerial2(false, Serial2);
+#endif
+#if USING_HW_SERIAL3
+ DefaultSerial4 MSerial3(false, Serial3);
+#endif
#endif // ARDUINO_ARCH_SAM
diff --git a/Marlin/src/HAL/DUE/HAL.h b/Marlin/src/HAL/DUE/HAL.h
index 88ace5957535..4d3f4823a517 100644
--- a/Marlin/src/HAL/DUE/HAL.h
+++ b/Marlin/src/HAL/DUE/HAL.h
@@ -32,105 +32,106 @@
#include "../shared/math_32bit.h"
#include "../shared/HAL_SPI.h"
#include "fastio.h"
-#include "watchdog.h"
#include
-#define _MSERIAL(X) Serial##X
+#include "../../core/serial_hook.h"
+
+// ------------------------
+// Serial ports
+// ------------------------
+
+typedef ForwardSerial1Class< decltype(Serial) > DefaultSerial1;
+typedef ForwardSerial1Class< decltype(Serial1) > DefaultSerial2;
+typedef ForwardSerial1Class< decltype(Serial2) > DefaultSerial3;
+typedef ForwardSerial1Class< decltype(Serial3) > DefaultSerial4;
+extern DefaultSerial1 MSerial0;
+extern DefaultSerial2 MSerial1;
+extern DefaultSerial3 MSerial2;
+extern DefaultSerial4 MSerial3;
+
+#define _MSERIAL(X) MSerial##X
#define MSERIAL(X) _MSERIAL(X)
-#define Serial0 Serial
-// Define MYSERIAL0/1 before MarlinSerial includes!
#if SERIAL_PORT == -1 || ENABLED(EMERGENCY_PARSER)
- #define MYSERIAL0 customizedSerial1
+ #define MYSERIAL1 customizedSerial1
#elif WITHIN(SERIAL_PORT, 0, 3)
- #define MYSERIAL0 MSERIAL(SERIAL_PORT)
+ #define MYSERIAL1 MSERIAL(SERIAL_PORT)
#else
- #error "The required SERIAL_PORT must be from -1 to 3. Please update your configuration."
+ #error "The required SERIAL_PORT must be from 0 to 3, or -1 for USB Serial."
#endif
#ifdef SERIAL_PORT_2
#if SERIAL_PORT_2 == -1 || ENABLED(EMERGENCY_PARSER)
- #define MYSERIAL1 customizedSerial2
+ #define MYSERIAL2 customizedSerial2
#elif WITHIN(SERIAL_PORT_2, 0, 3)
- #define MYSERIAL1 MSERIAL(SERIAL_PORT_2)
+ #define MYSERIAL2 MSERIAL(SERIAL_PORT_2)
+ #else
+ #error "SERIAL_PORT_2 must be from 0 to 3, or -1 for USB Serial."
+ #endif
+#endif
+
+#ifdef SERIAL_PORT_3
+ #if SERIAL_PORT_3 == -1 || ENABLED(EMERGENCY_PARSER)
+ #define MYSERIAL3 customizedSerial3
+ #elif WITHIN(SERIAL_PORT_3, 0, 3)
+ #define MYSERIAL3 MSERIAL(SERIAL_PORT_3)
#else
- #error "SERIAL_PORT_2 must be from -1 to 3. Please update your configuration."
+ #error "SERIAL_PORT_3 must be from 0 to 3, or -1 for USB Serial."
+ #endif
+#endif
+
+#ifdef MMU2_SERIAL_PORT
+ #if WITHIN(MMU2_SERIAL_PORT, 0, 3)
+ #define MMU2_SERIAL MSERIAL(MMU2_SERIAL_PORT)
+ #else
+ #error "MMU2_SERIAL_PORT must be from 0 to 3."
#endif
#endif
#ifdef LCD_SERIAL_PORT
- #if LCD_SERIAL_PORT == -1
- #define LCD_SERIAL lcdSerial
- #elif WITHIN(LCD_SERIAL_PORT, 0, 3)
+ #if WITHIN(LCD_SERIAL_PORT, 0, 3)
#define LCD_SERIAL MSERIAL(LCD_SERIAL_PORT)
#else
- #error "LCD_SERIAL_PORT must be from -1 to 3. Please update your configuration."
+ #error "LCD_SERIAL_PORT must be from 0 to 3."
#endif
#endif
#include "MarlinSerial.h"
#include "MarlinSerialUSB.h"
-// On AVR this is in math.h?
-#define square(x) ((x)*(x))
-
-#ifndef strncpy_P
- #define strncpy_P(dest, src, num) strncpy((dest), (src), (num))
-#endif
-
-// Fix bug in pgm_read_ptr
-#undef pgm_read_ptr
-#define pgm_read_ptr(addr) (*((void**)(addr)))
-#undef pgm_read_word
-#define pgm_read_word(addr) (*((uint16_t*)(addr)))
+// ------------------------
+// Types
+// ------------------------
typedef int8_t pin_t;
-#define SHARED_SERVOS HAS_SERVOS
-#define HAL_SERVO_LIB Servo
+#define SHARED_SERVOS HAS_SERVOS // Use shared/servos.cpp
+
+class Servo;
+typedef Servo hal_servo_t;
//
// Interrupts
//
-#define CRITICAL_SECTION_START() uint32_t primask = __get_PRIMASK(); __disable_irq()
-#define CRITICAL_SECTION_END() if (!primask) __enable_irq()
-#define ISRS_ENABLED() (!__get_PRIMASK())
-#define ENABLE_ISRS() __enable_irq()
-#define DISABLE_ISRS() __disable_irq()
-
-void cli(); // Disable interrupts
-void sei(); // Enable interrupts
+#define sei() interrupts()
+#define cli() noInterrupts()
-void HAL_clear_reset_source(); // clear reset reason
-uint8_t HAL_get_reset_source(); // get reset reason
-
-inline void HAL_reboot() {} // reboot the board or restart the bootloader
+#define CRITICAL_SECTION_START() const bool _irqon = hal.isr_state(); hal.isr_off()
+#define CRITICAL_SECTION_END() if (_irqon) hal.isr_on()
//
// ADC
//
-extern uint16_t HAL_adc_result; // result of last ADC conversion
+#define HAL_ADC_VREF 3.3
+#define HAL_ADC_RESOLUTION 10
#ifndef analogInputToDigitalPin
#define analogInputToDigitalPin(p) ((p < 12U) ? (p) + 54U : -1)
#endif
-#define HAL_ANALOG_SELECT(ch)
-
-inline void HAL_adc_init() {}//todo
-
-#define HAL_ADC_VREF 3.3
-#define HAL_ADC_RESOLUTION 10
-#define HAL_START_ADC(ch) HAL_adc_start_conversion(ch)
-#define HAL_READ_ADC() HAL_adc_result
-#define HAL_ADC_READY() true
-
-void HAL_adc_start_conversion(const uint8_t ch);
-uint16_t HAL_adc_get_result();
-
//
-// Pin Map
+// Pin Mapping for M42, M43, M226
//
#define GET_PIN_MAP_PIN(index) index
#define GET_PIN_MAP_INDEX(pin) pin
@@ -139,23 +140,18 @@ uint16_t HAL_adc_get_result();
//
// Tone
//
-void toneInit();
void tone(const pin_t _pin, const unsigned int frequency, const unsigned long duration=0);
void noTone(const pin_t _pin);
-// Enable hooks into idle and setup for HAL
-#define HAL_IDLETASK 1
-void HAL_idletask();
-void HAL_init();
-
-//
-// Utility functions
-//
-void _delay_ms(const int delay);
+// ------------------------
+// Class Utilities
+// ------------------------
#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-function"
-int freeMemory();
+#if GCC_VERSION <= 50000
+ #pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+
#pragma GCC diagnostic pop
#ifdef __cplusplus
@@ -165,3 +161,73 @@ char *dtostrf(double __val, signed char __width, unsigned char __prec, char *__s
#ifdef __cplusplus
}
#endif
+
+// Return free RAM between end of heap (or end bss) and whatever is current
+int freeMemory();
+
+// ------------------------
+// MarlinHAL Class
+// ------------------------
+
+class MarlinHAL {
+public:
+
+ // Earliest possible init, before setup()
+ MarlinHAL() {}
+
+ // Watchdog
+ static void watchdog_init() IF_DISABLED(USE_WATCHDOG, {});
+ static void watchdog_refresh() IF_DISABLED(USE_WATCHDOG, {});
+
+ static void init(); // Called early in setup()
+ static void init_board(); // Called less early in setup()
+ static void reboot(); // Restart the firmware
+
+ // Interrupts
+ static bool isr_state() { return !__get_PRIMASK(); }
+ static void isr_on() { __enable_irq(); }
+ static void isr_off() { __disable_irq(); }
+
+ static void delay_ms(const int ms) { delay(ms); }
+
+ // Tasks, called from idle()
+ static void idletask();
+
+ // Reset
+ static uint8_t get_reset_source();
+ static void clear_reset_source() {}
+
+ // Free SRAM
+ static int freeMemory() { return ::freeMemory(); }
+
+ //
+ // ADC Methods
+ //
+
+ static uint16_t adc_result;
+
+ // Called by Temperature::init once at startup
+ static void adc_init() {}
+
+ // Called by Temperature::init for each sensor at startup
+ static void adc_enable(const uint8_t ch) {}
+
+ // Begin ADC sampling on the given channel. Called from Temperature::isr!
+ static void adc_start(const uint8_t ch) { adc_result = analogRead(ch); }
+
+ // Is the ADC ready for reading?
+ static bool adc_ready() { return true; }
+
+ // The current value of the ADC register
+ static uint16_t adc_value() { return adc_result; }
+
+ /**
+ * Set the PWM duty cycle for the pin to the given value.
+ * No inverting the duty cycle in this HAL.
+ * No changing the maximum size of the provided value to enable finer PWM duty control in this HAL.
+ */
+ static void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t=255, const bool=false) {
+ analogWrite(pin, v);
+ }
+
+};
diff --git a/Marlin/src/HAL/DUE/HAL_SPI.cpp b/Marlin/src/HAL/DUE/HAL_SPI.cpp
index 0451d8bcc4ff..7e3fe0135645 100644
--- a/Marlin/src/HAL/DUE/HAL_SPI.cpp
+++ b/Marlin/src/HAL/DUE/HAL_SPI.cpp
@@ -31,8 +31,6 @@
/**
* HAL for Arduino Due and compatible (SAM3X8E)
- *
- * For ARDUINO_ARCH_SAM
*/
#ifdef ARDUINO_ARCH_SAM
@@ -56,8 +54,8 @@
#pragma GCC optimize (3)
typedef uint8_t (*pfnSpiTransfer)(uint8_t b);
- typedef void (*pfnSpiRxBlock)(uint8_t* buf, uint32_t nbyte);
- typedef void (*pfnSpiTxBlock)(const uint8_t* buf, uint32_t nbyte);
+ typedef void (*pfnSpiRxBlock)(uint8_t *buf, uint32_t nbyte);
+ typedef void (*pfnSpiTxBlock)(const uint8_t *buf, uint32_t nbyte);
/* ---------------- Macros to be able to access definitions from asm */
#define _PORT(IO) DIO ## IO ## _WPORT
@@ -69,10 +67,10 @@
// run at ~8 .. ~10Mhz - Tx version (Rx data discarded)
static uint8_t spiTransferTx0(uint8_t bout) { // using Mode 0
- uint32_t MOSI_PORT_PLUS30 = ((uint32_t) PORT(MOSI_PIN)) + 0x30; /* SODR of port */
- uint32_t MOSI_MASK = PIN_MASK(MOSI_PIN);
- uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
- uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
+ uint32_t MOSI_PORT_PLUS30 = ((uint32_t) PORT(SD_MOSI_PIN)) + 0x30; /* SODR of port */
+ uint32_t MOSI_MASK = PIN_MASK(SD_MOSI_PIN);
+ uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SD_SCK_PIN)) + 0x30; /* SODR of port */
+ uint32_t SCK_MASK = PIN_MASK(SD_SCK_PIN);
uint32_t idx = 0;
/* Negate bout, as the assembler requires a negated value */
@@ -154,9 +152,9 @@
static uint8_t spiTransferRx0(uint8_t) { // using Mode 0
uint32_t bin = 0;
uint32_t work = 0;
- uint32_t BITBAND_MISO_PORT = BITBAND_ADDRESS( ((uint32_t)PORT(MISO_PIN))+0x3C, PIN_SHIFT(MISO_PIN)); /* PDSR of port in bitband area */
- uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
- uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
+ uint32_t BITBAND_MISO_PORT = BITBAND_ADDRESS( ((uint32_t)PORT(SD_MISO_PIN))+0x3C, PIN_SHIFT(SD_MISO_PIN)); /* PDSR of port in bitband area */
+ uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SD_SCK_PIN)) + 0x30; /* SODR of port */
+ uint32_t SCK_MASK = PIN_MASK(SD_SCK_PIN);
/* The software SPI routine */
__asm__ __volatile__(
@@ -225,36 +223,36 @@
static uint8_t spiTransfer1(uint8_t b) { // using Mode 0
int bits = 8;
do {
- WRITE(MOSI_PIN, b & 0x80);
+ WRITE(SD_MOSI_PIN, b & 0x80);
b <<= 1; // little setup time
- WRITE(SCK_PIN, HIGH);
+ WRITE(SD_SCK_PIN, HIGH);
DELAY_NS(125); // 10 cycles @ 84mhz
- b |= (READ(MISO_PIN) != 0);
+ b |= (READ(SD_MISO_PIN) != 0);
- WRITE(SCK_PIN, LOW);
+ WRITE(SD_SCK_PIN, LOW);
DELAY_NS(125); // 10 cycles @ 84mhz
} while (--bits);
return b;
}
// all the others
- static uint32_t spiDelayCyclesX4 = (F_CPU) / 1000000; // 4µs => 125khz
+ static uint16_t spiDelayNS = 4000; // 4000ns => 125khz
static uint8_t spiTransferX(uint8_t b) { // using Mode 0
int bits = 8;
do {
- WRITE(MOSI_PIN, b & 0x80);
+ WRITE(SD_MOSI_PIN, b & 0x80);
b <<= 1; // little setup time
- WRITE(SCK_PIN, HIGH);
- __delay_4cycles(spiDelayCyclesX4);
+ WRITE(SD_SCK_PIN, HIGH);
+ DELAY_NS(spiDelayNS);
- b |= (READ(MISO_PIN) != 0);
+ b |= (READ(SD_MISO_PIN) != 0);
- WRITE(SCK_PIN, LOW);
- __delay_4cycles(spiDelayCyclesX4);
+ WRITE(SD_SCK_PIN, LOW);
+ DELAY_NS(spiDelayNS);
} while (--bits);
return b;
}
@@ -270,11 +268,11 @@
static pfnSpiTransfer spiTransferTx = (pfnSpiTransfer)spiTransferX;
// Block transfers run at ~8 .. ~10Mhz - Tx version (Rx data discarded)
- static void spiTxBlock0(const uint8_t* ptr, uint32_t todo) {
- uint32_t MOSI_PORT_PLUS30 = ((uint32_t) PORT(MOSI_PIN)) + 0x30; /* SODR of port */
- uint32_t MOSI_MASK = PIN_MASK(MOSI_PIN);
- uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
- uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
+ static void spiTxBlock0(const uint8_t *ptr, uint32_t todo) {
+ uint32_t MOSI_PORT_PLUS30 = ((uint32_t) PORT(SD_MOSI_PIN)) + 0x30; /* SODR of port */
+ uint32_t MOSI_MASK = PIN_MASK(SD_MOSI_PIN);
+ uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SD_SCK_PIN)) + 0x30; /* SODR of port */
+ uint32_t SCK_MASK = PIN_MASK(SD_SCK_PIN);
uint32_t work = 0;
uint32_t txval = 0;
@@ -349,12 +347,12 @@
);
}
- static void spiRxBlock0(uint8_t* ptr, uint32_t todo) {
+ static void spiRxBlock0(uint8_t *ptr, uint32_t todo) {
uint32_t bin = 0;
uint32_t work = 0;
- uint32_t BITBAND_MISO_PORT = BITBAND_ADDRESS( ((uint32_t)PORT(MISO_PIN))+0x3C, PIN_SHIFT(MISO_PIN)); /* PDSR of port in bitband area */
- uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
- uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
+ uint32_t BITBAND_MISO_PORT = BITBAND_ADDRESS( ((uint32_t)PORT(SD_MISO_PIN))+0x3C, PIN_SHIFT(SD_MISO_PIN)); /* PDSR of port in bitband area */
+ uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SD_SCK_PIN)) + 0x30; /* SODR of port */
+ uint32_t SCK_MASK = PIN_MASK(SD_SCK_PIN);
/* The software SPI routine */
__asm__ __volatile__(
@@ -425,48 +423,48 @@
);
}
- static void spiTxBlockX(const uint8_t* buf, uint32_t todo) {
+ static void spiTxBlockX(const uint8_t *buf, uint32_t todo) {
do {
(void)spiTransferTx(*buf++);
} while (--todo);
}
- static void spiRxBlockX(uint8_t* buf, uint32_t todo) {
+ static void spiRxBlockX(uint8_t *buf, uint32_t todo) {
do {
*buf++ = spiTransferRx(0xFF);
} while (--todo);
}
- // Pointers to generic functions for block tranfers
+ // Pointers to generic functions for block transfers
static pfnSpiTxBlock spiTxBlock = (pfnSpiTxBlock)spiTxBlockX;
static pfnSpiRxBlock spiRxBlock = (pfnSpiRxBlock)spiRxBlockX;
#if MB(ALLIGATOR)
- #define _SS_WRITE(S) WRITE(SS_PIN, S)
+ #define _SS_WRITE(S) WRITE(SD_SS_PIN, S)
#else
#define _SS_WRITE(S) NOOP
#endif
void spiBegin() {
- SET_OUTPUT(SS_PIN);
+ SET_OUTPUT(SD_SS_PIN);
_SS_WRITE(HIGH);
- SET_OUTPUT(SCK_PIN);
- SET_INPUT(MISO_PIN);
- SET_OUTPUT(MOSI_PIN);
+ SET_OUTPUT(SD_SCK_PIN);
+ SET_INPUT(SD_MISO_PIN);
+ SET_OUTPUT(SD_MOSI_PIN);
}
uint8_t spiRec() {
_SS_WRITE(LOW);
- WRITE(MOSI_PIN, HIGH); // Output 1s 1
+ WRITE(SD_MOSI_PIN, HIGH); // Output 1s 1
uint8_t b = spiTransferRx(0xFF);
_SS_WRITE(HIGH);
return b;
}
- void spiRead(uint8_t* buf, uint16_t nbyte) {
+ void spiRead(uint8_t *buf, uint16_t nbyte) {
if (nbyte) {
_SS_WRITE(LOW);
- WRITE(MOSI_PIN, HIGH); // Output 1s 1
+ WRITE(SD_MOSI_PIN, HIGH); // Output 1s 1
spiRxBlock(buf, nbyte);
_SS_WRITE(HIGH);
}
@@ -478,7 +476,7 @@
_SS_WRITE(HIGH);
}
- void spiSendBlock(uint8_t token, const uint8_t* buf) {
+ void spiSendBlock(uint8_t token, const uint8_t *buf) {
_SS_WRITE(LOW);
(void)spiTransferTx(token);
spiTxBlock(buf, 512);
@@ -510,7 +508,7 @@
spiRxBlock = (pfnSpiRxBlock)spiRxBlockX;
break;
default:
- spiDelayCyclesX4 = ((F_CPU) / 1000000) >> (6 - spiRate);
+ spiDelayNS = 4000 >> (6 - spiRate); // spiRate of 2 gives the maximum error with current CPU
spiTransferTx = (pfnSpiTransfer)spiTransferX;
spiTransferRx = (pfnSpiTransfer)spiTransferX;
spiTxBlock = (pfnSpiTxBlock)spiTxBlockX;
@@ -519,8 +517,8 @@
}
_SS_WRITE(HIGH);
- WRITE(MOSI_PIN, HIGH);
- WRITE(SCK_PIN, LOW);
+ WRITE(SD_MOSI_PIN, HIGH);
+ WRITE(SD_SCK_PIN, LOW);
}
/** Begin SPI transaction, set clock, bit order, data mode */
@@ -575,38 +573,34 @@
// Configure SPI pins
PIO_Configure(
- g_APinDescription[SCK_PIN].pPort,
- g_APinDescription[SCK_PIN].ulPinType,
- g_APinDescription[SCK_PIN].ulPin,
- g_APinDescription[SCK_PIN].ulPinConfiguration);
+ g_APinDescription[SD_SCK_PIN].pPort,
+ g_APinDescription[SD_SCK_PIN].ulPinType,
+ g_APinDescription[SD_SCK_PIN].ulPin,
+ g_APinDescription[SD_SCK_PIN].ulPinConfiguration);
PIO_Configure(
- g_APinDescription[MOSI_PIN].pPort,
- g_APinDescription[MOSI_PIN].ulPinType,
- g_APinDescription[MOSI_PIN].ulPin,
- g_APinDescription[MOSI_PIN].ulPinConfiguration);
+ g_APinDescription[SD_MOSI_PIN].pPort,
+ g_APinDescription[SD_MOSI_PIN].ulPinType,
+ g_APinDescription[SD_MOSI_PIN].ulPin,
+ g_APinDescription[SD_MOSI_PIN].ulPinConfiguration);
PIO_Configure(
- g_APinDescription[MISO_PIN].pPort,
- g_APinDescription[MISO_PIN].ulPinType,
- g_APinDescription[MISO_PIN].ulPin,
- g_APinDescription[MISO_PIN].ulPinConfiguration);
+ g_APinDescription[SD_MISO_PIN].pPort,
+ g_APinDescription[SD_MISO_PIN].ulPinType,
+ g_APinDescription[SD_MISO_PIN].ulPin,
+ g_APinDescription[SD_MISO_PIN].ulPinConfiguration);
// set master mode, peripheral select, fault detection
SPI_Configure(SPI0, ID_SPI0, SPI_MR_MSTR | SPI_MR_MODFDIS | SPI_MR_PS);
SPI_Enable(SPI0);
- SET_OUTPUT(DAC0_SYNC);
+ SET_OUTPUT(DAC0_SYNC_PIN);
#if HAS_MULTI_EXTRUDER
- SET_OUTPUT(DAC1_SYNC);
- WRITE(DAC1_SYNC, HIGH);
+ OUT_WRITE(DAC1_SYNC_PIN, HIGH);
#endif
- SET_OUTPUT(SPI_EEPROM1_CS);
- SET_OUTPUT(SPI_EEPROM2_CS);
- SET_OUTPUT(SPI_FLASH_CS);
- WRITE(DAC0_SYNC, HIGH);
- WRITE(SPI_EEPROM1_CS, HIGH);
- WRITE(SPI_EEPROM2_CS, HIGH);
- WRITE(SPI_FLASH_CS, HIGH);
- WRITE(SS_PIN, HIGH);
+ WRITE(DAC0_SYNC_PIN, HIGH);
+ OUT_WRITE(SPI_EEPROM1_CS_PIN, HIGH);
+ OUT_WRITE(SPI_EEPROM2_CS_PIN, HIGH);
+ OUT_WRITE(SPI_FLASH_CS_PIN, HIGH);
+ WRITE(SD_SS_PIN, HIGH);
OUT_WRITE(SDSS, LOW);
@@ -645,7 +639,7 @@
}
// Read from SPI into buffer
- void spiRead(uint8_t* buf, uint16_t nbyte) {
+ void spiRead(uint8_t *buf, uint16_t nbyte) {
if (!nbyte) return;
--nbyte;
for (int i = 0; i < nbyte; i++) {
@@ -668,7 +662,7 @@
//DELAY_US(1U);
}
- void spiSend(const uint8_t* buf, size_t nbyte) {
+ void spiSend(const uint8_t *buf, size_t nbyte) {
if (!nbyte) return;
--nbyte;
for (size_t i = 0; i < nbyte; i++) {
@@ -689,7 +683,7 @@
FLUSH_RX();
}
- void spiSend(uint32_t chan, const uint8_t* buf, size_t nbyte) {
+ void spiSend(uint32_t chan, const uint8_t *buf, size_t nbyte) {
if (!nbyte) return;
--nbyte;
for (size_t i = 0; i < nbyte; i++) {
@@ -702,7 +696,7 @@
}
// Write from buffer to SPI
- void spiSendBlock(uint8_t token, const uint8_t* buf) {
+ void spiSendBlock(uint8_t token, const uint8_t *buf) {
SPI0->SPI_TDR = (uint32_t)token | SPI_PCS(SPI_CHAN);
WHILE_TX(0);
//WHILE_RX(0);
@@ -801,19 +795,19 @@
uint8_t spiRec() { return (uint8_t)spiTransfer(0xFF); }
- void spiRead(uint8_t* buf, uint16_t nbyte) {
+ void spiRead(uint8_t *buf, uint16_t nbyte) {
for (int i = 0; i < nbyte; i++)
buf[i] = spiTransfer(0xFF);
}
void spiSend(uint8_t data) { spiTransfer(data); }
- void spiSend(const uint8_t* buf, size_t nbyte) {
+ void spiSend(const uint8_t *buf, size_t nbyte) {
for (uint16_t i = 0; i < nbyte; i++)
spiTransfer(buf[i]);
}
- void spiSendBlock(uint8_t token, const uint8_t* buf) {
+ void spiSendBlock(uint8_t token, const uint8_t *buf) {
spiTransfer(token);
for (uint16_t i = 0; i < 512; i++)
spiTransfer(buf[i]);
diff --git a/Marlin/src/HAL/DUE/MarlinSPI.h b/Marlin/src/HAL/DUE/MarlinSPI.h
new file mode 100644
index 000000000000..0c447ba4cb3d
--- /dev/null
+++ b/Marlin/src/HAL/DUE/MarlinSPI.h
@@ -0,0 +1,26 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#pragma once
+
+#include
+
+using MarlinSPI = SPIClass;
diff --git a/Marlin/src/HAL/DUE/MarlinSerial.cpp b/Marlin/src/HAL/DUE/MarlinSerial.cpp
index c9a372eeb14f..638f7a100722 100644
--- a/Marlin/src/HAL/DUE/MarlinSerial.cpp
+++ b/Marlin/src/HAL/DUE/MarlinSerial.cpp
@@ -382,7 +382,7 @@ void MarlinSerial::flush() {
}
template
-void MarlinSerial::write(const uint8_t c) {
+size_t MarlinSerial::write(const uint8_t c) {
_written = true;
if (Cfg::TX_SIZE == 0) {
@@ -400,13 +400,13 @@ void MarlinSerial::write(const uint8_t c) {
// XOFF char at the RX isr, but it is properly handled there
if (!(HWUART->UART_IMR & UART_IMR_TXRDY) && (HWUART->UART_SR & UART_SR_TXRDY)) {
HWUART->UART_THR = c;
- return;
+ return 1;
}
const uint8_t i = (tx_buffer.head + 1) & (Cfg::TX_SIZE - 1);
// If global interrupts are disabled (as the result of being called from an ISR)...
- if (!ISRS_ENABLED()) {
+ if (!hal.isr_state()) {
// Make room by polling if it is possible to transmit, and do so!
while (i == tx_buffer.tail) {
@@ -428,6 +428,7 @@ void MarlinSerial::write(const uint8_t c) {
// Enable TX isr - Non atomic, but it will eventually enable TX isr
HWUART->UART_IER = UART_IER_TXRDY;
}
+ return 1;
}
template
@@ -453,7 +454,7 @@ void MarlinSerial::flushTX() {
if (!_written) return;
// If global interrupts are disabled (as the result of being called from an ISR)...
- if (!ISRS_ENABLED()) {
+ if (!hal.isr_state()) {
// Wait until everything was transmitted - We must do polling, as interrupts are disabled
while (tx_buffer.head != tx_buffer.tail || !(HWUART->UART_SR & UART_SR_TXEMPTY)) {
@@ -473,169 +474,21 @@ void MarlinSerial::flushTX() {
}
}
-/**
- * Imports from print.h
- */
-
-template
-void MarlinSerial::print(char c, int base) {
- print((long)c, base);
-}
-
-template
-void MarlinSerial::print(unsigned char b, int base) {
- print((unsigned long)b, base);
-}
-
-template
-void MarlinSerial::print(int n, int base) {
- print((long)n, base);
-}
-
-template
-void MarlinSerial::print(unsigned int n, int base) {
- print((unsigned long)n, base);
-}
-
-template
-void MarlinSerial::print(long n, int base) {
- if (base == 0) write(n);
- else if (base == 10) {
- if (n < 0) { print('-'); n = -n; }
- printNumber(n, 10);
- }
- else
- printNumber(n, base);
-}
-
-template
-void MarlinSerial::print(unsigned long n, int base) {
- if (base == 0) write(n);
- else printNumber(n, base);
-}
-
-template
-void MarlinSerial::print(double n, int digits) {
- printFloat(n, digits);
-}
-
-template
-void MarlinSerial::println() {
- print('\r');
- print('\n');
-}
-
-template
-void MarlinSerial::println(const String& s) {
- print(s);
- println();
-}
-
-template
-void MarlinSerial::println(const char c[]) {
- print(c);
- println();
-}
-
-template
-void MarlinSerial::println(char c, int base) {
- print(c, base);
- println();
-}
-
-template
-void MarlinSerial::println(unsigned char b, int base) {
- print(b, base);
- println();
-}
-
-template
-void MarlinSerial::println(int n, int base) {
- print(n, base);
- println();
-}
-
-template
-void MarlinSerial::println(unsigned int n, int base) {
- print(n, base);
- println();
-}
-
-template
-void MarlinSerial::println(long n, int base) {
- print(n, base);
- println();
-}
-
-template
-void MarlinSerial::println(unsigned long n, int base) {
- print(n, base);
- println();
-}
-
-template
-void MarlinSerial::println(double n, int digits) {
- print(n, digits);
- println();
-}
-
-// Private Methods
-template
-void MarlinSerial::printNumber(unsigned long n, uint8_t base) {
- if (n) {
- unsigned char buf[8 * sizeof(long)]; // Enough space for base 2
- int8_t i = 0;
- while (n) {
- buf[i++] = n % base;
- n /= base;
- }
- while (i--)
- print((char)(buf[i] + (buf[i] < 10 ? '0' : 'A' - 10)));
- }
- else
- print('0');
-}
-
-template
-void MarlinSerial::printFloat(double number, uint8_t digits) {
- // Handle negative numbers
- if (number < 0.0) {
- print('-');
- number = -number;
- }
-
- // Round correctly so that print(1.999, 2) prints as "2.00"
- double rounding = 0.5;
- LOOP_L_N(i, digits) rounding *= 0.1;
- number += rounding;
-
- // Extract the integer part of the number and print it
- unsigned long int_part = (unsigned long)number;
- double remainder = number - (double)int_part;
- print(int_part);
-
- // Print the decimal point, but only if there are digits beyond
- if (digits) {
- print('.');
- // Extract digits from the remainder one at a time
- while (digits--) {
- remainder *= 10.0;
- int toPrint = int(remainder);
- print(toPrint);
- remainder -= toPrint;
- }
- }
-}
// If not using the USB port as serial port
-#if SERIAL_PORT >= 0
- template class MarlinSerial>; // Define
- MarlinSerial> customizedSerial1; // Instantiate
+#if defined(SERIAL_PORT) && SERIAL_PORT >= 0
+ template class MarlinSerial< MarlinSerialCfg >;
+ MSerialT1 customizedSerial1(MarlinSerialCfg::EMERGENCYPARSER);
#endif
#if defined(SERIAL_PORT_2) && SERIAL_PORT_2 >= 0
- template class MarlinSerial>; // Define
- MarlinSerial> customizedSerial2; // Instantiate
+ template class MarlinSerial< MarlinSerialCfg >;
+ MSerialT2 customizedSerial2(MarlinSerialCfg::EMERGENCYPARSER);
+#endif
+
+#if defined(SERIAL_PORT_3) && SERIAL_PORT_3 >= 0
+ template class MarlinSerial< MarlinSerialCfg >;
+ MSerialT3 customizedSerial3(MarlinSerialCfg::EMERGENCYPARSER);
#endif
#endif // ARDUINO_ARCH_SAM
diff --git a/Marlin/src/HAL/DUE/MarlinSerial.h b/Marlin/src/HAL/DUE/MarlinSerial.h
index a194eba2f386..5a61bffee0da 100644
--- a/Marlin/src/HAL/DUE/MarlinSerial.h
+++ b/Marlin/src/HAL/DUE/MarlinSerial.h
@@ -30,11 +30,7 @@
#include
#include "../../inc/MarlinConfigPre.h"
-
-#define DEC 10
-#define HEX 16
-#define OCT 8
-#define BIN 2
+#include "../../core/serial_hook.h"
// Define constants and variables for buffering incoming serial data. We're
// using a ring buffer (I think), in which rx_buffer_head is the index of the
@@ -119,44 +115,15 @@ class MarlinSerial {
static int read();
static void flush();
static ring_buffer_pos_t available();
- static void write(const uint8_t c);
+ static size_t write(const uint8_t c);
static void flushTX();
- static inline bool emergency_parser_enabled() { return Cfg::EMERGENCYPARSER; }
+ static bool emergency_parser_enabled() { return Cfg::EMERGENCYPARSER; }
FORCE_INLINE static uint8_t dropped() { return Cfg::DROPPED_RX ? rx_dropped_bytes : 0; }
FORCE_INLINE static uint8_t buffer_overruns() { return Cfg::RX_OVERRUNS ? rx_buffer_overruns : 0; }
FORCE_INLINE static uint8_t framing_errors() { return Cfg::RX_FRAMING_ERRORS ? rx_framing_errors : 0; }
FORCE_INLINE static ring_buffer_pos_t rxMaxEnqueued() { return Cfg::MAX_RX_QUEUED ? rx_max_enqueued : 0; }
-
- FORCE_INLINE static void write(const char* str) { while (*str) write(*str++); }
- FORCE_INLINE static void write(const uint8_t* buffer, size_t size) { while (size--) write(*buffer++); }
- FORCE_INLINE static void print(const String& s) { for (int i = 0; i < (int)s.length(); i++) write(s[i]); }
- FORCE_INLINE static void print(const char* str) { write(str); }
-
- static void print(char, int = 0);
- static void print(unsigned char, int = 0);
- static void print(int, int = DEC);
- static void print(unsigned int, int = DEC);
- static void print(long, int = DEC);
- static void print(unsigned long, int = DEC);
- static void print(double, int = 2);
-
- static void println(const String& s);
- static void println(const char[]);
- static void println(char, int = 0);
- static void println(unsigned char, int = 0);
- static void println(int, int = DEC);
- static void println(unsigned int, int = DEC);
- static void println(long, int = DEC);
- static void println(unsigned long, int = DEC);
- static void println(double, int = 2);
- static void println();
- operator bool() { return true; }
-
-private:
- static void printNumber(unsigned long, const uint8_t);
- static void printFloat(double, uint8_t);
};
// Serial port configuration
@@ -173,10 +140,17 @@ struct MarlinSerialCfg {
static constexpr bool MAX_RX_QUEUED = ENABLED(SERIAL_STATS_MAX_RX_QUEUED);
};
-#if SERIAL_PORT >= 0
- extern MarlinSerial> customizedSerial1;
+#if defined(SERIAL_PORT) && SERIAL_PORT >= 0
+ typedef Serial1Class< MarlinSerial< MarlinSerialCfg > > MSerialT1;
+ extern MSerialT1 customizedSerial1;
#endif
#if defined(SERIAL_PORT_2) && SERIAL_PORT_2 >= 0
- extern MarlinSerial> customizedSerial2;
+ typedef Serial1Class< MarlinSerial< MarlinSerialCfg > > MSerialT2;
+ extern MSerialT2 customizedSerial2;
+#endif
+
+#if defined(SERIAL_PORT_3) && SERIAL_PORT_3 >= 0
+ typedef Serial1Class< MarlinSerial< MarlinSerialCfg > > MSerialT3;
+ extern MSerialT3 customizedSerial3;
#endif
diff --git a/Marlin/src/HAL/DUE/MarlinSerialUSB.cpp b/Marlin/src/HAL/DUE/MarlinSerialUSB.cpp
index a41dbfeb7a57..8de2dc7924a0 100644
--- a/Marlin/src/HAL/DUE/MarlinSerialUSB.cpp
+++ b/Marlin/src/HAL/DUE/MarlinSerialUSB.cpp
@@ -19,13 +19,13 @@
* along with this program. If not, see .
*
*/
+#ifdef ARDUINO_ARCH_SAM
/**
* MarlinSerial_Due.cpp - Hardware serial library for Arduino DUE
* Copyright (c) 2017 Eduardo José Tagle. All right reserved
* Based on MarlinSerial for AVR, copyright (c) 2006 Nicholas Zambetti. All right reserved.
*/
-#ifdef ARDUINO_ARCH_SAM
#include "../../inc/MarlinConfig.h"
@@ -33,10 +33,6 @@
#include "MarlinSerialUSB.h"
-#if ENABLED(EMERGENCY_PARSER)
- #include "../../feature/e_parser.h"
-#endif
-
// Imports from Atmel USB Stack/CDC implementation
extern "C" {
bool usb_task_cdc_isenabled();
@@ -45,15 +41,11 @@ extern "C" {
int udi_cdc_getc();
bool udi_cdc_is_tx_ready();
int udi_cdc_putc(int value);
-};
+}
// Pending character
static int pending_char = -1;
-#if ENABLED(EMERGENCY_PARSER)
- static EmergencyParser::State emergency_state; // = EP_RESET
-#endif
-
// Public Methods
void MarlinSerialUSB::begin(const long) {}
@@ -73,7 +65,7 @@ int MarlinSerialUSB::peek() {
pending_char = udi_cdc_getc();
- TERN_(EMERGENCY_PARSER, emergency_parser.update(emergency_state, (char)pending_char));
+ TERN_(EMERGENCY_PARSER, emergency_parser.update(static_cast(this)->emergency_state, (char)pending_char));
return pending_char;
}
@@ -95,29 +87,27 @@ int MarlinSerialUSB::read() {
int c = udi_cdc_getc();
- TERN_(EMERGENCY_PARSER, emergency_parser.update(emergency_state, (char)c));
+ TERN_(EMERGENCY_PARSER, emergency_parser.update(static_cast(this)->emergency_state, (char)c));
return c;
}
-bool MarlinSerialUSB::available() {
- /* If Pending chars */
- return pending_char >= 0 ||
- /* or USB CDC enumerated and configured on the PC side and some
- bytes where sent to us */
- (usb_task_cdc_isenabled() && udi_cdc_is_rx_ready());
+int MarlinSerialUSB::available() {
+ if (pending_char > 0) return pending_char;
+ return pending_char == 0 ||
+ // or USB CDC enumerated and configured on the PC side and some bytes where sent to us */
+ (usb_task_cdc_isenabled() && udi_cdc_is_rx_ready());
}
void MarlinSerialUSB::flush() { }
-void MarlinSerialUSB::flushTX() { }
-void MarlinSerialUSB::write(const uint8_t c) {
+size_t MarlinSerialUSB::write(const uint8_t c) {
/* Do not even bother sending anything if USB CDC is not enumerated
or not configured on the PC side or there is no program on the PC
listening to our messages */
if (!usb_task_cdc_isenabled() || !usb_task_cdc_dtr_active())
- return;
+ return 0;
/* Wait until the PC has read the pending to be sent data */
while (usb_task_cdc_isenabled() &&
@@ -129,161 +119,23 @@ void MarlinSerialUSB::write(const uint8_t c) {
or not configured on the PC side or there is no program on the PC
listening to our messages at this point */
if (!usb_task_cdc_isenabled() || !usb_task_cdc_dtr_active())
- return;
+ return 0;
// Fifo full
// udi_cdc_signal_overrun();
udi_cdc_putc(c);
-}
-
-/**
- * Imports from print.h
- */
-
-void MarlinSerialUSB::print(char c, int base) {
- print((long)c, base);
-}
-
-void MarlinSerialUSB::print(unsigned char b, int base) {
- print((unsigned long)b, base);
-}
-
-void MarlinSerialUSB::print(int n, int base) {
- print((long)n, base);
-}
-
-void MarlinSerialUSB::print(unsigned int n, int base) {
- print((unsigned long)n, base);
-}
-
-void MarlinSerialUSB::print(long n, int base) {
- if (base == 0)
- write(n);
- else if (base == 10) {
- if (n < 0) {
- print('-');
- n = -n;
- }
- printNumber(n, 10);
- }
- else
- printNumber(n, base);
-}
-
-void MarlinSerialUSB::print(unsigned long n, int base) {
- if (base == 0) write(n);
- else printNumber(n, base);
-}
-
-void MarlinSerialUSB::print(double n, int digits) {
- printFloat(n, digits);
-}
-
-void MarlinSerialUSB::println() {
- print('\r');
- print('\n');
-}
-
-void MarlinSerialUSB::println(const String& s) {
- print(s);
- println();
-}
-
-void MarlinSerialUSB::println(const char c[]) {
- print(c);
- println();
-}
-
-void MarlinSerialUSB::println(char c, int base) {
- print(c, base);
- println();
-}
-
-void MarlinSerialUSB::println(unsigned char b, int base) {
- print(b, base);
- println();
-}
-
-void MarlinSerialUSB::println(int n, int base) {
- print(n, base);
- println();
-}
-
-void MarlinSerialUSB::println(unsigned int n, int base) {
- print(n, base);
- println();
-}
-
-void MarlinSerialUSB::println(long n, int base) {
- print(n, base);
- println();
-}
-
-void MarlinSerialUSB::println(unsigned long n, int base) {
- print(n, base);
- println();
-}
-
-void MarlinSerialUSB::println(double n, int digits) {
- print(n, digits);
- println();
-}
-
-// Private Methods
-
-void MarlinSerialUSB::printNumber(unsigned long n, uint8_t base) {
- if (n) {
- unsigned char buf[8 * sizeof(long)]; // Enough space for base 2
- int8_t i = 0;
- while (n) {
- buf[i++] = n % base;
- n /= base;
- }
- while (i--)
- print((char)(buf[i] + (buf[i] < 10 ? '0' : 'A' - 10)));
- }
- else
- print('0');
-}
-
-void MarlinSerialUSB::printFloat(double number, uint8_t digits) {
- // Handle negative numbers
- if (number < 0.0) {
- print('-');
- number = -number;
- }
-
- // Round correctly so that print(1.999, 2) prints as "2.00"
- double rounding = 0.5;
- LOOP_L_N(i, digits)
- rounding *= 0.1;
-
- number += rounding;
-
- // Extract the integer part of the number and print it
- unsigned long int_part = (unsigned long)number;
- double remainder = number - (double)int_part;
- print(int_part);
-
- // Print the decimal point, but only if there are digits beyond
- if (digits) {
- print('.');
- // Extract digits from the remainder one at a time
- while (digits--) {
- remainder *= 10.0;
- int toPrint = int(remainder);
- print(toPrint);
- remainder -= toPrint;
- }
- }
+ return 1;
}
// Preinstantiate
#if SERIAL_PORT == -1
- MarlinSerialUSB customizedSerial1;
+ MSerialT1 customizedSerial1(TERN0(EMERGENCY_PARSER, true));
#endif
#if SERIAL_PORT_2 == -1
- MarlinSerialUSB customizedSerial2;
+ MSerialT2 customizedSerial2(TERN0(EMERGENCY_PARSER, true));
+#endif
+#if SERIAL_PORT_3 == -1
+ MSerialT3 customizedSerial3(TERN0(EMERGENCY_PARSER, true));
#endif
#endif // HAS_USB_SERIAL
diff --git a/Marlin/src/HAL/DUE/MarlinSerialUSB.h b/Marlin/src/HAL/DUE/MarlinSerialUSB.h
index 2e3622e5534a..6da1ef8c08f6 100644
--- a/Marlin/src/HAL/DUE/MarlinSerialUSB.h
+++ b/Marlin/src/HAL/DUE/MarlinSerialUSB.h
@@ -27,73 +27,39 @@
*/
#include "../../inc/MarlinConfig.h"
-
-#if HAS_USB_SERIAL
+#include "../../core/serial_hook.h"
#include
-#define DEC 10
-#define HEX 16
-#define OCT 8
-#define BIN 2
-
-class MarlinSerialUSB {
-
-public:
- MarlinSerialUSB() {};
- static void begin(const long);
- static void end();
- static int peek();
- static int read();
- static void flush();
- static void flushTX();
- static bool available();
- static void write(const uint8_t c);
+struct MarlinSerialUSB {
+ void begin(const long);
+ void end();
+ int peek();
+ int read();
+ void flush();
+ int available();
+ size_t write(const uint8_t c);
#if ENABLED(SERIAL_STATS_DROPPED_RX)
- FORCE_INLINE static uint32_t dropped() { return 0; }
+ FORCE_INLINE uint32_t dropped() { return 0; }
#endif
#if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
- FORCE_INLINE static int rxMaxEnqueued() { return 0; }
+ FORCE_INLINE int rxMaxEnqueued() { return 0; }
#endif
-
- FORCE_INLINE static void write(const char* str) { while (*str) write(*str++); }
- FORCE_INLINE static void write(const uint8_t* buffer, size_t size) { while (size--) write(*buffer++); }
- FORCE_INLINE static void print(const String& s) { for (int i = 0; i < (int)s.length(); i++) write(s[i]); }
- FORCE_INLINE static void print(const char* str) { write(str); }
-
- static void print(char, int = 0);
- static void print(unsigned char, int = 0);
- static void print(int, int = DEC);
- static void print(unsigned int, int = DEC);
- static void print(long, int = DEC);
- static void print(unsigned long, int = DEC);
- static void print(double, int = 2);
-
- static void println(const String& s);
- static void println(const char[]);
- static void println(char, int = 0);
- static void println(unsigned char, int = 0);
- static void println(int, int = DEC);
- static void println(unsigned int, int = DEC);
- static void println(long, int = DEC);
- static void println(unsigned long, int = DEC);
- static void println(double, int = 2);
- static void println();
- operator bool() { return true; }
-
-private:
- static void printNumber(unsigned long, const uint8_t);
- static void printFloat(double, uint8_t);
};
#if SERIAL_PORT == -1
- extern MarlinSerialUSB customizedSerial1;
+ typedef Serial1Class MSerialT1;
+ extern MSerialT1 customizedSerial1;
#endif
#if SERIAL_PORT_2 == -1
- extern MarlinSerialUSB customizedSerial2;
+ typedef Serial1Class MSerialT2;
+ extern MSerialT2 customizedSerial2;
#endif
-#endif // HAS_USB_SERIAL
+#if SERIAL_PORT_3 == -1
+ typedef Serial1Class MSerialT3;
+ extern MSerialT3 customizedSerial3;
+#endif
diff --git a/Marlin/src/HAL/DUE/MinSerial.cpp b/Marlin/src/HAL/DUE/MinSerial.cpp
new file mode 100644
index 000000000000..e5b3dbfe6f36
--- /dev/null
+++ b/Marlin/src/HAL/DUE/MinSerial.cpp
@@ -0,0 +1,91 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#ifdef ARDUINO_ARCH_SAM
+
+#include "../../inc/MarlinConfigPre.h"
+
+#if ENABLED(POSTMORTEM_DEBUGGING)
+
+#include "../shared/MinSerial.h"
+
+#include
+
+static void TXBegin() {
+ // Disable UART interrupt in NVIC
+ NVIC_DisableIRQ( UART_IRQn );
+
+ // We NEED memory barriers to ensure Interrupts are actually disabled!
+ // ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
+ __DSB();
+ __ISB();
+
+ // Disable clock
+ pmc_disable_periph_clk( ID_UART );
+
+ // Configure PMC
+ pmc_enable_periph_clk( ID_UART );
+
+ // Disable PDC channel
+ UART->UART_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS;
+
+ // Reset and disable receiver and transmitter
+ UART->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS;
+
+ // Configure mode: 8bit, No parity, 1 bit stop
+ UART->UART_MR = UART_MR_CHMODE_NORMAL | US_MR_CHRL_8_BIT | US_MR_NBSTOP_1_BIT | UART_MR_PAR_NO;
+
+ // Configure baudrate (asynchronous, no oversampling) to BAUDRATE bauds
+ UART->UART_BRGR = (SystemCoreClock / (BAUDRATE << 4));
+
+ // Enable receiver and transmitter
+ UART->UART_CR = UART_CR_RXEN | UART_CR_TXEN;
+}
+
+// A SW memory barrier, to ensure GCC does not overoptimize loops
+#define sw_barrier() __asm__ volatile("": : :"memory");
+static void TX(char c) {
+ while (!(UART->UART_SR & UART_SR_TXRDY)) { WDT_Restart(WDT); sw_barrier(); };
+ UART->UART_THR = c;
+}
+
+void install_min_serial() {
+ HAL_min_serial_init = &TXBegin;
+ HAL_min_serial_out = &TX;
+}
+
+#if DISABLED(DYNAMIC_VECTORTABLE)
+extern "C" {
+ __attribute__((naked)) void JumpHandler_ASM() {
+ __asm__ __volatile__ (
+ "b CommonHandler_ASM\n"
+ );
+ }
+ void __attribute__((naked, alias("JumpHandler_ASM"))) HardFault_Handler();
+ void __attribute__((naked, alias("JumpHandler_ASM"))) BusFault_Handler();
+ void __attribute__((naked, alias("JumpHandler_ASM"))) UsageFault_Handler();
+ void __attribute__((naked, alias("JumpHandler_ASM"))) MemManage_Handler();
+ void __attribute__((naked, alias("JumpHandler_ASM"))) NMI_Handler();
+}
+#endif
+
+#endif // POSTMORTEM_DEBUGGING
+#endif // ARDUINO_ARCH_SAM
diff --git a/Marlin/src/HAL/DUE/Servo.cpp b/Marlin/src/HAL/DUE/Servo.cpp
index 5524aa9cef47..2dab88238dd6 100644
--- a/Marlin/src/HAL/DUE/Servo.cpp
+++ b/Marlin/src/HAL/DUE/Servo.cpp
@@ -47,12 +47,12 @@
#include "../shared/servo.h"
#include "../shared/servo_private.h"
-static volatile int8_t Channel[_Nbr_16timers]; // counter for the servo being pulsed for each timer (or -1 if refresh interval)
+static Flags<_Nbr_16timers> DisablePending; // ISR should disable the timer at the next timer reset
// ------------------------
/// Interrupt handler for the TC0 channel 1.
// ------------------------
-void Servo_Handler(timer16_Sequence_t timer, Tc *pTc, uint8_t channel);
+void Servo_Handler(const timer16_Sequence_t, Tc*, const uint8_t);
#ifdef _useTimer1
void HANDLER_FOR_TIMER1() { Servo_Handler(_timer1, TC_FOR_TIMER1, CHANNEL_FOR_TIMER1); }
@@ -70,88 +70,92 @@ void Servo_Handler(timer16_Sequence_t timer, Tc *pTc, uint8_t channel);
void HANDLER_FOR_TIMER5() { Servo_Handler(_timer5, TC_FOR_TIMER5, CHANNEL_FOR_TIMER5); }
#endif
-void Servo_Handler(timer16_Sequence_t timer, Tc *tc, uint8_t channel) {
- // clear interrupt
- tc->TC_CHANNEL[channel].TC_SR;
- if (Channel[timer] < 0)
- tc->TC_CHANNEL[channel].TC_CCR |= TC_CCR_SWTRG; // channel set to -1 indicated that refresh interval completed so reset the timer
- else if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && SERVO(timer, Channel[timer]).Pin.isActive)
- extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, LOW); // pulse this channel low if activated
-
- Channel[timer]++; // increment to the next channel
- if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) {
- tc->TC_CHANNEL[channel].TC_RA = tc->TC_CHANNEL[channel].TC_CV + SERVO(timer,Channel[timer]).ticks;
- if (SERVO(timer,Channel[timer]).Pin.isActive) // check if activated
- extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, HIGH); // its an active channel so pulse it high
+void Servo_Handler(const timer16_Sequence_t timer, Tc *tc, const uint8_t channel) {
+ static int8_t Channel[_Nbr_16timers]; // Servo counters to pulse (or -1 for refresh interval)
+ int8_t cho = Channel[timer]; // Handle the prior Channel[timer] first
+ if (cho < 0) { // Channel -1 indicates the refresh interval completed...
+ tc->TC_CHANNEL[channel].TC_CCR |= TC_CCR_SWTRG; // ...so reset the timer
+ if (DisablePending[timer]) {
+ // Disabling only after the full servo period expires prevents
+ // pulses being too close together if immediately re-enabled.
+ DisablePending.clear(timer);
+ TC_Stop(tc, channel);
+ tc->TC_CHANNEL[channel].TC_SR; // clear interrupt
+ return;
+ }
+ }
+ else if (SERVO_INDEX(timer, cho) < ServoCount) // prior channel handled?
+ extDigitalWrite(SERVO(timer, cho).Pin.nbr, LOW); // pulse the prior channel LOW
+
+ Channel[timer] = ++cho; // go to the next channel (or 0)
+ if (cho < SERVOS_PER_TIMER && SERVO_INDEX(timer, cho) < ServoCount) {
+ tc->TC_CHANNEL[channel].TC_RA = tc->TC_CHANNEL[channel].TC_CV + SERVO(timer, cho).ticks;
+ if (SERVO(timer, cho).Pin.isActive) // activated?
+ extDigitalWrite(SERVO(timer, cho).Pin.nbr, HIGH); // yes: pulse HIGH
}
else {
// finished all channels so wait for the refresh period to expire before starting over
- tc->TC_CHANNEL[channel].TC_RA =
- tc->TC_CHANNEL[channel].TC_CV < usToTicks(REFRESH_INTERVAL) - 4
- ? (unsigned int)usToTicks(REFRESH_INTERVAL) // allow a few ticks to ensure the next OCR1A not missed
- : tc->TC_CHANNEL[channel].TC_CV + 4; // at least REFRESH_INTERVAL has elapsed
- Channel[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel
+ const unsigned int cval = tc->TC_CHANNEL[channel].TC_CV + 128 / (SERVO_TIMER_PRESCALER), // allow 128 cycles to ensure the next CV not missed
+ ival = (unsigned int)usToTicks(REFRESH_INTERVAL); // at least REFRESH_INTERVAL has elapsed
+ tc->TC_CHANNEL[channel].TC_RA = max(cval, ival);
+
+ Channel[timer] = -1; // reset the timer CCR on the next call
}
+
+ tc->TC_CHANNEL[channel].TC_SR; // clear interrupt
}
static void _initISR(Tc *tc, uint32_t channel, uint32_t id, IRQn_Type irqn) {
pmc_enable_periph_clk(id);
TC_Configure(tc, channel,
- TC_CMR_TCCLKS_TIMER_CLOCK3 | // MCK/32
- TC_CMR_WAVE | // Waveform mode
- TC_CMR_WAVSEL_UP_RC ); // Counter running up and reset when equals to RC
-
- /* 84MHz, MCK/32, for 1.5ms: 3937 */
- TC_SetRA(tc, channel, 2625); // 1ms
-
- /* Configure and enable interrupt */
+ TC_CMR_WAVE // Waveform mode
+ | TC_CMR_WAVSEL_UP_RC // Counter running up and reset when equal to RC
+ | (SERVO_TIMER_PRESCALER == 2 ? TC_CMR_TCCLKS_TIMER_CLOCK1 : 0) // MCK/2
+ | (SERVO_TIMER_PRESCALER == 8 ? TC_CMR_TCCLKS_TIMER_CLOCK2 : 0) // MCK/8
+ | (SERVO_TIMER_PRESCALER == 32 ? TC_CMR_TCCLKS_TIMER_CLOCK3 : 0) // MCK/32
+ | (SERVO_TIMER_PRESCALER == 128 ? TC_CMR_TCCLKS_TIMER_CLOCK4 : 0) // MCK/128
+ );
+
+ // Wait 1ms before the first ISR
+ TC_SetRA(tc, channel, (F_CPU) / (SERVO_TIMER_PRESCALER) / 1000UL); // 1ms
+
+ // Configure and enable interrupt
NVIC_EnableIRQ(irqn);
- // TC_IER_CPAS: RA Compare
- tc->TC_CHANNEL[channel].TC_IER = TC_IER_CPAS;
+ tc->TC_CHANNEL[channel].TC_IER = TC_IER_CPAS; // TC_IER_CPAS: RA Compare
// Enables the timer clock and performs a software reset to start the counting
TC_Start(tc, channel);
}
-void initISR(timer16_Sequence_t timer) {
- #ifdef _useTimer1
- if (timer == _timer1)
- _initISR(TC_FOR_TIMER1, CHANNEL_FOR_TIMER1, ID_TC_FOR_TIMER1, IRQn_FOR_TIMER1);
- #endif
- #ifdef _useTimer2
- if (timer == _timer2)
- _initISR(TC_FOR_TIMER2, CHANNEL_FOR_TIMER2, ID_TC_FOR_TIMER2, IRQn_FOR_TIMER2);
- #endif
- #ifdef _useTimer3
- if (timer == _timer3)
- _initISR(TC_FOR_TIMER3, CHANNEL_FOR_TIMER3, ID_TC_FOR_TIMER3, IRQn_FOR_TIMER3);
- #endif
- #ifdef _useTimer4
- if (timer == _timer4)
- _initISR(TC_FOR_TIMER4, CHANNEL_FOR_TIMER4, ID_TC_FOR_TIMER4, IRQn_FOR_TIMER4);
- #endif
- #ifdef _useTimer5
- if (timer == _timer5)
- _initISR(TC_FOR_TIMER5, CHANNEL_FOR_TIMER5, ID_TC_FOR_TIMER5, IRQn_FOR_TIMER5);
- #endif
+void initISR(const timer16_Sequence_t timer_index) {
+ CRITICAL_SECTION_START();
+ const bool disable_soon = DisablePending[timer_index];
+ DisablePending.clear(timer_index);
+ CRITICAL_SECTION_END();
+
+ if (!disable_soon) switch (timer_index) {
+ default: break;
+ #ifdef _useTimer1
+ case _timer1: return _initISR(TC_FOR_TIMER1, CHANNEL_FOR_TIMER1, ID_TC_FOR_TIMER1, IRQn_FOR_TIMER1);
+ #endif
+ #ifdef _useTimer2
+ case _timer2: return _initISR(TC_FOR_TIMER2, CHANNEL_FOR_TIMER2, ID_TC_FOR_TIMER2, IRQn_FOR_TIMER2);
+ #endif
+ #ifdef _useTimer3
+ case _timer3: return _initISR(TC_FOR_TIMER3, CHANNEL_FOR_TIMER3, ID_TC_FOR_TIMER3, IRQn_FOR_TIMER3);
+ #endif
+ #ifdef _useTimer4
+ case _timer4: return _initISR(TC_FOR_TIMER4, CHANNEL_FOR_TIMER4, ID_TC_FOR_TIMER4, IRQn_FOR_TIMER4);
+ #endif
+ #ifdef _useTimer5
+ case _timer5: return _initISR(TC_FOR_TIMER5, CHANNEL_FOR_TIMER5, ID_TC_FOR_TIMER5, IRQn_FOR_TIMER5);
+ #endif
+ }
}
-void finISR(timer16_Sequence_t) {
- #ifdef _useTimer1
- TC_Stop(TC_FOR_TIMER1, CHANNEL_FOR_TIMER1);
- #endif
- #ifdef _useTimer2
- TC_Stop(TC_FOR_TIMER2, CHANNEL_FOR_TIMER2);
- #endif
- #ifdef _useTimer3
- TC_Stop(TC_FOR_TIMER3, CHANNEL_FOR_TIMER3);
- #endif
- #ifdef _useTimer4
- TC_Stop(TC_FOR_TIMER4, CHANNEL_FOR_TIMER4);
- #endif
- #ifdef _useTimer5
- TC_Stop(TC_FOR_TIMER5, CHANNEL_FOR_TIMER5);
- #endif
+void finISR(const timer16_Sequence_t timer_index) {
+ // Timer is disabled from the ISR, to ensure proper final pulse length.
+ DisablePending.set(timer_index);
}
#endif // HAS_SERVOS
diff --git a/Marlin/src/HAL/DUE/ServoTimers.h b/Marlin/src/HAL/DUE/ServoTimers.h
index c32c93825399..95bd404c8061 100644
--- a/Marlin/src/HAL/DUE/ServoTimers.h
+++ b/Marlin/src/HAL/DUE/ServoTimers.h
@@ -37,7 +37,7 @@
#define _useTimer5
#define TRIM_DURATION 2 // compensation ticks to trim adjust for digitalWrite delays
-#define SERVO_TIMER_PRESCALER 32 // timer prescaler
+#define SERVO_TIMER_PRESCALER 2 // timer prescaler
/*
TC0, chan 0 => TC0_Handler
diff --git a/Marlin/src/HAL/DUE/Tone.cpp b/Marlin/src/HAL/DUE/Tone.cpp
index 9beb6022237f..4bc8142aba27 100644
--- a/Marlin/src/HAL/DUE/Tone.cpp
+++ b/Marlin/src/HAL/DUE/Tone.cpp
@@ -35,20 +35,20 @@
static pin_t tone_pin;
volatile static int32_t toggles;
-void tone(const pin_t _pin, const unsigned int frequency, const unsigned long duration) {
+void tone(const pin_t _pin, const unsigned int frequency, const unsigned long duration/*=0*/) {
tone_pin = _pin;
toggles = 2 * frequency * duration / 1000;
- HAL_timer_start(TONE_TIMER_NUM, 2 * frequency);
+ HAL_timer_start(MF_TIMER_TONE, 2 * frequency);
}
void noTone(const pin_t _pin) {
- HAL_timer_disable_interrupt(TONE_TIMER_NUM);
+ HAL_timer_disable_interrupt(MF_TIMER_TONE);
extDigitalWrite(_pin, LOW);
}
HAL_TONE_TIMER_ISR() {
static uint8_t pin_state = 0;
- HAL_timer_isr_prologue(TONE_TIMER_NUM);
+ HAL_timer_isr_prologue(MF_TIMER_TONE);
if (toggles) {
toggles--;
diff --git a/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_shared_hw_spi.cpp b/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_shared_hw_spi.cpp
index be4b49c0f992..68f6a5c1a7cb 100644
--- a/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_shared_hw_spi.cpp
+++ b/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_shared_hw_spi.cpp
@@ -20,7 +20,6 @@
*
*/
-
/**
* Based on u8g_com_msp430_hw_spi.c
*
@@ -60,16 +59,15 @@
#if HAS_MARLINUI_U8GLIB
-#include
+#include
#include "../../../MarlinCore.h"
-void spiBegin();
-void spiInit(uint8_t spiRate);
-void spiSend(uint8_t b);
-void spiSend(const uint8_t* buf, size_t n);
+#ifndef LCD_SPI_SPEED
+ #define LCD_SPI_SPEED SPI_QUARTER_SPEED
+#endif
-#include "../../shared/Marduino.h"
+#include "../../shared/HAL_SPI.h"
#include "../fastio.h"
void u8g_SetPIOutput_DUE_hw_spi(u8g_t *u8g, uint8_t pin_index) {
@@ -100,11 +98,7 @@ uint8_t u8g_com_HAL_DUE_shared_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_va
spiBegin();
- #ifndef SPI_SPEED
- #define SPI_SPEED SPI_FULL_SPEED // use same SPI speed as SD card
- #endif
- spiInit(2);
-
+ spiInit(LCD_SPI_SPEED);
break;
case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */
diff --git a/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_st7920_sw_spi.cpp b/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_st7920_sw_spi.cpp
index 7df180cbaa82..8268cf307e08 100644
--- a/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_st7920_sw_spi.cpp
+++ b/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_st7920_sw_spi.cpp
@@ -57,11 +57,12 @@
#include "../../../inc/MarlinConfigPre.h"
-#if ENABLED(U8GLIB_ST7920)
+#if IS_U8GLIB_ST7920
+#include "../../../inc/MarlinConfig.h"
#include "../../shared/Delay.h"
-#include
+#include
#include "u8g_com_HAL_DUE_sw_spi_shared.h"
@@ -181,5 +182,5 @@ uint8_t u8g_com_HAL_DUE_ST7920_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_va
}
#endif // LIGHTWEIGHT_UI
-#endif // U8GLIB_ST7920
+#endif // IS_U8GLIB_ST7920
#endif // ARDUINO_ARCH_SAM
diff --git a/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_sw_spi.cpp b/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_sw_spi.cpp
index ea7204fa366b..68e3e74a45a0 100644
--- a/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_sw_spi.cpp
+++ b/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_sw_spi.cpp
@@ -57,17 +57,14 @@
#include "../../../inc/MarlinConfigPre.h"
-#if HAS_MARLINUI_U8GLIB && DISABLED(U8GLIB_ST7920)
-
-#undef SPI_SPEED
-#define SPI_SPEED 2 // About 2 MHz
+#if HAS_MARLINUI_U8GLIB && !IS_U8GLIB_ST7920
#include "u8g_com_HAL_DUE_sw_spi_shared.h"
#include "../../shared/Marduino.h"
#include "../../shared/Delay.h"
-#include
+#include
#if ENABLED(FYSETC_MINI_12864)
#define SPISEND_SW_DUE u8g_spiSend_sw_DUE_mode_3
@@ -144,5 +141,5 @@ uint8_t u8g_com_HAL_DUE_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void
return 1;
}
-#endif // HAS_MARLINUI_U8GLIB && !U8GLIB_ST7920
+#endif // HAS_MARLINUI_U8GLIB && !IS_U8GLIB_ST7920
#endif // ARDUINO_ARCH_SAM
diff --git a/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_sw_spi_shared.cpp b/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_sw_spi_shared.cpp
index 615a386c3542..904924793b4c 100644
--- a/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_sw_spi_shared.cpp
+++ b/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_sw_spi_shared.cpp
@@ -59,9 +59,10 @@
#if HAS_MARLINUI_U8GLIB
+#include "../../../inc/MarlinConfig.h"
#include "../../shared/Delay.h"
-#include
+#include
#include "u8g_com_HAL_DUE_sw_spi_shared.h"
diff --git a/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_sw_spi_shared.h b/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_sw_spi_shared.h
index f076c503cac2..45231fd091eb 100644
--- a/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_sw_spi_shared.h
+++ b/Marlin/src/HAL/DUE/dogm/u8g_com_HAL_DUE_sw_spi_shared.h
@@ -23,7 +23,7 @@
#include "../../../inc/MarlinConfigPre.h"
#include "../../shared/Marduino.h"
-#include
+#include
void u8g_SetPIOutput_DUE(u8g_t *u8g, uint8_t pin_index);
void u8g_SetPILevel_DUE(u8g_t *u8g, uint8_t pin_index, uint8_t level);
diff --git a/Marlin/src/HAL/DUE/eeprom_flash.cpp b/Marlin/src/HAL/DUE/eeprom_flash.cpp
index 6f38da0967cb..607764155b0a 100644
--- a/Marlin/src/HAL/DUE/eeprom_flash.cpp
+++ b/Marlin/src/HAL/DUE/eeprom_flash.cpp
@@ -135,11 +135,11 @@ static uint8_t buffer[256] = {0}, // The RAM buffer to accumulate writes
#define DEBUG_OUT ENABLED(EE_EMU_DEBUG)
#include "../../core/debug_out.h"
-static void ee_Dump(const int page, const void* data) {
+static void ee_Dump(const int page, const void *data) {
#ifdef EE_EMU_DEBUG
- const uint8_t* c = (const uint8_t*) data;
+ const uint8_t *c = (const uint8_t*) data;
char buffer[80];
sprintf_P(buffer, PSTR("Page: %d (0x%04x)\n"), page, page);
@@ -181,7 +181,7 @@ static void ee_Dump(const int page, const void* data) {
* @param data (pointer to the data buffer)
*/
__attribute__ ((long_call, section (".ramfunc")))
-static bool ee_PageWrite(uint16_t page, const void* data) {
+static bool ee_PageWrite(uint16_t page, const void *data) {
uint16_t i;
uint32_t addrflash = uint32_t(getFlashStorage(page));
@@ -199,10 +199,9 @@ static bool ee_PageWrite(uint16_t page, const void* data) {
for (i = 0; i > 2; i++)
pageContents[i] = (((uint32_t*)data)[i]) | (~(pageContents[i] ^ ((uint32_t*)data)[i]));
- DEBUG_ECHO_START();
- DEBUG_ECHOLNPAIR("EEPROM PageWrite ", page);
- DEBUG_ECHOLNPAIR(" in FLASH address ", (uint32_t)addrflash);
- DEBUG_ECHOLNPAIR(" base address ", (uint32_t)getFlashStorage(0));
+ DEBUG_ECHO_MSG("EEPROM PageWrite ", page);
+ DEBUG_ECHOLNPGM(" in FLASH address ", (uint32_t)addrflash);
+ DEBUG_ECHOLNPGM(" base address ", (uint32_t)getFlashStorage(0));
DEBUG_FLUSH();
// Get the page relative to the start of the EFC controller, and the EFC controller to use
@@ -245,8 +244,7 @@ static bool ee_PageWrite(uint16_t page, const void* data) {
// Reenable interrupts
__enable_irq();
- DEBUG_ECHO_START();
- DEBUG_ECHOLNPAIR("EEPROM Unlock failure for page ", page);
+ DEBUG_ECHO_MSG("EEPROM Unlock failure for page ", page);
return false;
}
@@ -270,8 +268,7 @@ static bool ee_PageWrite(uint16_t page, const void* data) {
// Reenable interrupts
__enable_irq();
- DEBUG_ECHO_START();
- DEBUG_ECHOLNPAIR("EEPROM Write failure for page ", page);
+ DEBUG_ECHO_MSG("EEPROM Write failure for page ", page);
return false;
}
@@ -286,15 +283,14 @@ static bool ee_PageWrite(uint16_t page, const void* data) {
if (memcmp(getFlashStorage(page),data,PageSize)) {
#ifdef EE_EMU_DEBUG
- DEBUG_ECHO_START();
- DEBUG_ECHOLNPAIR("EEPROM Verify Write failure for page ", page);
+ DEBUG_ECHO_MSG("EEPROM Verify Write failure for page ", page);
ee_Dump( page, (uint32_t *)addrflash);
ee_Dump(-page, data);
// Calculate count of changed bits
- uint32_t* p1 = (uint32_t*)addrflash;
- uint32_t* p2 = (uint32_t*)data;
+ uint32_t *p1 = (uint32_t*)addrflash;
+ uint32_t *p2 = (uint32_t*)data;
int count = 0;
for (i =0; i> 2; i++) {
if (p1[i] != p2[i]) {
@@ -306,7 +302,7 @@ static bool ee_PageWrite(uint16_t page, const void* data) {
}
}
}
- DEBUG_ECHOLNPAIR("--> Differing bits: ", count);
+ DEBUG_ECHOLNPGM("--> Differing bits: ", count);
#endif
return false;
@@ -325,10 +321,9 @@ static bool ee_PageErase(uint16_t page) {
uint16_t i;
uint32_t addrflash = uint32_t(getFlashStorage(page));
- DEBUG_ECHO_START();
- DEBUG_ECHOLNPAIR("EEPROM PageErase ", page);
- DEBUG_ECHOLNPAIR(" in FLASH address ", (uint32_t)addrflash);
- DEBUG_ECHOLNPAIR(" base address ", (uint32_t)getFlashStorage(0));
+ DEBUG_ECHO_MSG("EEPROM PageErase ", page);
+ DEBUG_ECHOLNPGM(" in FLASH address ", (uint32_t)addrflash);
+ DEBUG_ECHOLNPGM(" base address ", (uint32_t)getFlashStorage(0));
DEBUG_FLUSH();
// Get the page relative to the start of the EFC controller, and the EFC controller to use
@@ -370,8 +365,7 @@ static bool ee_PageErase(uint16_t page) {
// Reenable interrupts
__enable_irq();
- DEBUG_ECHO_START();
- DEBUG_ECHOLNPAIR("EEPROM Unlock failure for page ",page);
+ DEBUG_ECHO_MSG("EEPROM Unlock failure for page ",page);
return false;
}
@@ -394,8 +388,7 @@ static bool ee_PageErase(uint16_t page) {
// Reenable interrupts
__enable_irq();
- DEBUG_ECHO_START();
- DEBUG_ECHOLNPAIR("EEPROM Erase failure for page ",page);
+ DEBUG_ECHO_MSG("EEPROM Erase failure for page ",page);
return false;
}
@@ -410,8 +403,7 @@ static bool ee_PageErase(uint16_t page) {
uint32_t * aligned_src = (uint32_t *) addrflash;
for (i = 0; i < PageSize >> 2; i++) {
if (*aligned_src++ != 0xFFFFFFFF) {
- DEBUG_ECHO_START();
- DEBUG_ECHOLNPAIR("EEPROM Verify Erase failure for page ",page);
+ DEBUG_ECHO_MSG("EEPROM Verify Erase failure for page ",page);
ee_Dump(page, (uint32_t *)addrflash);
return false;
}
@@ -470,7 +462,7 @@ static uint8_t ee_Read(uint32_t address, bool excludeRAMBuffer=false) {
for (int page = curPage - 1; page >= 0; --page) {
// Get a pointer to the flash page
- uint8_t* pflash = (uint8_t*)getFlashStorage(page + curGroup * PagesPerGroup);
+ uint8_t *pflash = (uint8_t*)getFlashStorage(page + curGroup * PagesPerGroup);
uint16_t i = 0;
while (i <= (PageSize - 4)) { /* (PageSize - 4) because otherwise, there is not enough room for data and headers */
@@ -550,7 +542,7 @@ static uint32_t ee_GetAddrRange(uint32_t address, bool excludeRAMBuffer=false) {
for (int page = curPage - 1; page >= 0; --page) {
// Get a pointer to the flash page
- uint8_t* pflash = (uint8_t*)getFlashStorage(page + curGroup * PagesPerGroup);
+ uint8_t *pflash = (uint8_t*)getFlashStorage(page + curGroup * PagesPerGroup);
uint16_t i = 0;
while (i <= (PageSize - 4)) { /* (PageSize - 4) because otherwise, there is not enough room for data and headers */
@@ -589,7 +581,7 @@ static uint32_t ee_GetAddrRange(uint32_t address, bool excludeRAMBuffer=false) {
}
static bool ee_IsPageClean(int page) {
- uint32_t* pflash = (uint32_t*) getFlashStorage(page);
+ uint32_t *pflash = (uint32_t*) getFlashStorage(page);
for (uint16_t i = 0; i < (PageSize >> 2); ++i)
if (*pflash++ != 0xFFFFFFFF) return false;
return true;
@@ -599,7 +591,7 @@ static bool ee_Flush(uint32_t overrideAddress = 0xFFFFFFFF, uint8_t overrideData
// Check if RAM buffer has something to be written
bool isEmpty = true;
- uint32_t* p = (uint32_t*) &buffer[0];
+ uint32_t *p = (uint32_t*) &buffer[0];
for (uint16_t j = 0; j < (PageSize >> 2); j++) {
if (*p++ != 0xFFFFFFFF) {
isEmpty = false;
@@ -921,8 +913,7 @@ static void ee_Init() {
// If all groups seem to be used, default to first group
if (curGroup >= GroupCount) curGroup = 0;
- DEBUG_ECHO_START();
- DEBUG_ECHOLNPAIR("EEPROM Current Group: ",curGroup);
+ DEBUG_ECHO_MSG("EEPROM Current Group: ",curGroup);
DEBUG_FLUSH();
// Now, validate that all the other group pages are empty
@@ -931,8 +922,7 @@ static void ee_Init() {
for (int page = 0; page < PagesPerGroup; page++) {
if (!ee_IsPageClean(grp * PagesPerGroup + page)) {
- DEBUG_ECHO_START();
- DEBUG_ECHOLNPAIR("EEPROM Page ", page, " not clean on group ", grp);
+ DEBUG_ECHO_MSG("EEPROM Page ", page, " not clean on group ", grp);
DEBUG_FLUSH();
ee_PageErase(grp * PagesPerGroup + page);
}
@@ -948,15 +938,13 @@ static void ee_Init() {
}
}
- DEBUG_ECHO_START();
- DEBUG_ECHOLNPAIR("EEPROM Active page: ", curPage);
+ DEBUG_ECHO_MSG("EEPROM Active page: ", curPage);
DEBUG_FLUSH();
// Make sure the pages following the first clean one are also clean
for (int page = curPage + 1; page < PagesPerGroup; page++) {
if (!ee_IsPageClean(curGroup * PagesPerGroup + page)) {
- DEBUG_ECHO_START();
- DEBUG_ECHOLNPAIR("EEPROM Page ", page, " not clean on active group ", curGroup);
+ DEBUG_ECHO_MSG("EEPROM Page ", page, " not clean on active group ", curGroup);
DEBUG_FLUSH();
ee_Dump(curGroup * PagesPerGroup + page, getFlashStorage(curGroup * PagesPerGroup + page));
ee_PageErase(curGroup * PagesPerGroup + page);
@@ -976,14 +964,13 @@ bool PersistentStore::access_start() { ee_Init(); return true; }
bool PersistentStore::access_finish() { ee_Flush(); return true; }
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
+ uint16_t written = 0;
while (size--) {
uint8_t * const p = (uint8_t * const)pos;
uint8_t v = *value;
- // EEPROM has only ~100,000 write cycles,
- // so only write bytes that have changed!
- if (v != ee_Read(uint32_t(p))) {
+ if (v != ee_Read(uint32_t(p))) { // EEPROM has only ~100,000 write cycles, so only write bytes that have changed!
ee_Write(uint32_t(p), v);
- delay(2);
+ if (++written & 0x7F) delay(2); else safe_delay(2); // Avoid triggering watchdog during long EEPROM writes
if (ee_Read(uint32_t(p)) != v) {
SERIAL_ECHO_MSG(STR_ERR_EEPROM_WRITE);
return true;
@@ -996,7 +983,7 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui
return false;
}
-bool PersistentStore::read_data(int &pos, uint8_t* value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
+bool PersistentStore::read_data(int &pos, uint8_t *value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
do {
uint8_t c = ee_Read(uint32_t(pos));
if (writing) *value = c;
diff --git a/Marlin/src/HAL/DUE/eeprom_wired.cpp b/Marlin/src/HAL/DUE/eeprom_wired.cpp
index 4599d6a7cd44..557a2f2cffa5 100644
--- a/Marlin/src/HAL/DUE/eeprom_wired.cpp
+++ b/Marlin/src/HAL/DUE/eeprom_wired.cpp
@@ -42,14 +42,13 @@ bool PersistentStore::access_start() { eeprom_init(); return true; }
bool PersistentStore::access_finish() { return true; }
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
+ uint16_t written = 0;
while (size--) {
uint8_t * const p = (uint8_t * const)pos;
uint8_t v = *value;
- // EEPROM has only ~100,000 write cycles,
- // so only write bytes that have changed!
- if (v != eeprom_read_byte(p)) {
+ if (v != eeprom_read_byte(p)) { // EEPROM has only ~100,000 write cycles, so only write bytes that have changed!
eeprom_write_byte(p, v);
- delay(2);
+ if (++written & 0x7F) delay(2); else safe_delay(2); // Avoid triggering watchdog during long EEPROM writes
if (eeprom_read_byte(p) != v) {
SERIAL_ECHO_MSG(STR_ERR_EEPROM_WRITE);
return true;
@@ -62,7 +61,7 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui
return false;
}
-bool PersistentStore::read_data(int &pos, uint8_t* value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
+bool PersistentStore::read_data(int &pos, uint8_t *value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
do {
uint8_t c = eeprom_read_byte((uint8_t*)pos);
if (writing) *value = c;
diff --git a/Marlin/src/HAL/DUE/endstop_interrupts.h b/Marlin/src/HAL/DUE/endstop_interrupts.h
index 999ada512761..c1bbcb121bdc 100644
--- a/Marlin/src/HAL/DUE/endstop_interrupts.h
+++ b/Marlin/src/HAL/DUE/endstop_interrupts.h
@@ -64,4 +64,16 @@ void setup_endstop_interrupts() {
TERN_(HAS_Z4_MAX, _ATTACH(Z4_MAX_PIN));
TERN_(HAS_Z4_MIN, _ATTACH(Z4_MIN_PIN));
TERN_(HAS_Z_MIN_PROBE_PIN, _ATTACH(Z_MIN_PROBE_PIN));
+ TERN_(HAS_I_MAX, _ATTACH(I_MAX_PIN));
+ TERN_(HAS_I_MIN, _ATTACH(I_MIN_PIN));
+ TERN_(HAS_J_MAX, _ATTACH(J_MAX_PIN));
+ TERN_(HAS_J_MIN, _ATTACH(J_MIN_PIN));
+ TERN_(HAS_K_MAX, _ATTACH(K_MAX_PIN));
+ TERN_(HAS_K_MIN, _ATTACH(K_MIN_PIN));
+ TERN_(HAS_U_MAX, _ATTACH(U_MAX_PIN));
+ TERN_(HAS_U_MIN, _ATTACH(U_MIN_PIN));
+ TERN_(HAS_V_MAX, _ATTACH(V_MAX_PIN));
+ TERN_(HAS_V_MIN, _ATTACH(V_MIN_PIN));
+ TERN_(HAS_W_MAX, _ATTACH(W_MAX_PIN));
+ TERN_(HAS_W_MIN, _ATTACH(W_MIN_PIN));
}
diff --git a/Marlin/src/HAL/DUE/fastio.h b/Marlin/src/HAL/DUE/fastio.h
index 119d0005af9b..a609210d8130 100644
--- a/Marlin/src/HAL/DUE/fastio.h
+++ b/Marlin/src/HAL/DUE/fastio.h
@@ -33,7 +33,7 @@
* For ARDUINO_ARCH_SAM
* Note the code here was specifically crafted by disassembling what GCC produces
* out of it, so GCC is able to optimize it out as much as possible to the least
- * amount of instructions. Be very carefull if you modify them, as "clean code"
+ * amount of instructions. Be very careful if you modify them, as "clean code"
* leads to less efficient compiled code!!
*/
@@ -50,7 +50,7 @@
#define PWM_PIN(P) WITHIN(P, 2, 13)
#ifndef MASK
- #define MASK(PIN) (1 << PIN)
+ #define MASK(PIN) _BV(PIN)
#endif
/**
@@ -163,6 +163,9 @@
#define SET_INPUT(IO) _SET_INPUT(IO)
// Set pin as input with pullup (wrapper)
#define SET_INPUT_PULLUP(IO) do{ _SET_INPUT(IO); _PULLUP(IO, HIGH); }while(0)
+// Set pin as input with pulldown (substitution)
+#define SET_INPUT_PULLDOWN SET_INPUT
+
// Set pin as output (wrapper) - reads the pin and sets the output to that value
#define SET_OUTPUT(IO) _SET_OUTPUT(IO)
// Set pin as PWM
diff --git a/Marlin/src/HAL/DUE/fastio/G2_PWM.cpp b/Marlin/src/HAL/DUE/fastio/G2_PWM.cpp
index d9fbabce2148..800915ff692b 100644
--- a/Marlin/src/HAL/DUE/fastio/G2_PWM.cpp
+++ b/Marlin/src/HAL/DUE/fastio/G2_PWM.cpp
@@ -25,7 +25,7 @@
* is NOT used to directly toggle pins. The ISR writes to the pin assigned to
* that interrupt.
*
- * All PWMs use the same repetition rate. The G2 needs about 10KHz min in order to
+ * All PWMs use the same repetition rate. The G2 needs about 10kHz min in order to
* not have obvious ripple on the Vref signals.
*
* The data structures are setup to minimize the computation done by the ISR which
diff --git a/Marlin/src/HAL/DUE/inc/SanityCheck.h b/Marlin/src/HAL/DUE/inc/SanityCheck.h
index 688069650630..13484f7029d1 100644
--- a/Marlin/src/HAL/DUE/inc/SanityCheck.h
+++ b/Marlin/src/HAL/DUE/inc/SanityCheck.h
@@ -25,6 +25,30 @@
* Test Arduino Due specific configuration values for errors at compile-time.
*/
+/**
+ * Check for common serial pin conflicts
+ */
+#define CHECK_SERIAL_PIN(N) ( \
+ X_STOP_PIN == N || Y_STOP_PIN == N || Z_STOP_PIN == N \
+ || X_MIN_PIN == N || Y_MIN_PIN == N || Z_MIN_PIN == N \
+ || X_MAX_PIN == N || Y_MAX_PIN == N || Z_MAX_PIN == N \
+ || X_STEP_PIN == N || Y_STEP_PIN == N || Z_STEP_PIN == N \
+ || X_DIR_PIN == N || Y_DIR_PIN == N || Z_DIR_PIN == N \
+ || X_ENA_PIN == N || Y_ENA_PIN == N || Z_ENA_PIN == N \
+)
+#if CONF_SERIAL_IS(0) // D0-D1. No known conflicts.
+#endif
+#if CONF_SERIAL_IS(1) && (CHECK_SERIAL_PIN(18) || CHECK_SERIAL_PIN(19))
+ #error "Serial Port 1 pin D18 and/or D19 conflicts with another pin on the board."
+#endif
+#if CONF_SERIAL_IS(2) && (CHECK_SERIAL_PIN(16) || CHECK_SERIAL_PIN(17))
+ #error "Serial Port 2 pin D16 and/or D17 conflicts with another pin on the board."
+#endif
+#if CONF_SERIAL_IS(3) && (CHECK_SERIAL_PIN(14) || CHECK_SERIAL_PIN(15))
+ #error "Serial Port 3 pin D14 and/or D15 conflicts with another pin on the board."
+#endif
+#undef CHECK_SERIAL_PIN
+
/**
* HARDWARE VS. SOFTWARE SPI COMPATIBILITY
*
@@ -40,7 +64,7 @@
* Usually the hardware SPI pins are only available to the LCD. This makes the DUE hard SPI used at the same time
* as the TMC2130 soft SPI the most common setup.
*/
-#define _IS_HW_SPI(P) (defined(TMC_SW_##P) && (TMC_SW_##P == MOSI_PIN || TMC_SW_##P == MISO_PIN || TMC_SW_##P == SCK_PIN))
+#define _IS_HW_SPI(P) (defined(TMC_SW_##P) && (TMC_SW_##P == SD_MOSI_PIN || TMC_SW_##P == SD_MISO_PIN || TMC_SW_##P == SD_SCK_PIN))
#if ENABLED(SDSUPPORT) && HAS_DRIVER(TMC2130)
#if ENABLED(TMC_USE_SW_SPI)
@@ -57,5 +81,9 @@
#endif
#if HAS_TMC_SW_SERIAL
- #error "TMC220x Software Serial is not supported on this platform."
+ #error "TMC220x Software Serial is not supported on the DUE platform."
+#endif
+
+#if USING_PULLDOWNS
+ #error "PULLDOWN pin mode is not available on DUE boards."
#endif
diff --git a/Marlin/src/HAL/DUE/pinsDebug.h b/Marlin/src/HAL/DUE/pinsDebug.h
index a99ca8ecce90..df1ba415e918 100644
--- a/Marlin/src/HAL/DUE/pinsDebug.h
+++ b/Marlin/src/HAL/DUE/pinsDebug.h
@@ -2,6 +2,9 @@
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
@@ -50,7 +53,7 @@
* The net result is that both the g_pinStatus[pin] array and the PIO_OSR register
* needs to be looked at when determining if a pin is an input or an output.
*
- * b) Due has only pins 6, 7, 8 & 9 enabled for PWMs. FYI - they run at 1KHz
+ * b) Due has only pins 6, 7, 8 & 9 enabled for PWMs. FYI - they run at 1kHz
*
* c) NUM_DIGITAL_PINS does not include the analog pins
*
@@ -64,6 +67,7 @@
#define PRINT_PORT(p)
#define PRINT_ARRAY_NAME(x) do{ sprintf_P(buffer, PSTR("%-" STRINGIFY(MAX_NAME_LENGTH) "s"), pin_array[x].name); SERIAL_ECHO(buffer); }while(0)
#define PRINT_PIN(p) do{ sprintf_P(buffer, PSTR("%02d"), p); SERIAL_ECHO(buffer); }while(0)
+#define PRINT_PIN_ANALOG(p) do{ sprintf_P(buffer, PSTR(" (A%2d) "), DIGITAL_PIN_TO_ANALOG_PIN(pin)); SERIAL_ECHO(buffer); }while(0)
#define GET_ARRAY_PIN(p) pin_array[p].pin
#define GET_ARRAY_IS_DIGITAL(p) pin_array[p].is_digital
#define VALID_PIN(pin) (pin >= 0 && pin < (int8_t)NUMBER_PINS_TOTAL ? 1 : 0)
@@ -82,11 +86,10 @@ bool GET_PINMODE(int8_t pin) { // 1: output, 0: input
|| pwm_status(pin));
}
-
void pwm_details(int32_t pin) {
if (pwm_status(pin)) {
uint32_t chan = g_APinDescription[pin].ulPWMChannel;
- SERIAL_ECHOPAIR("PWM = ", PWM_INTERFACE->PWM_CH_NUM[chan].PWM_CDTY);
+ SERIAL_ECHOPGM("PWM = ", PWM_INTERFACE->PWM_CH_NUM[chan].PWM_CDTY);
}
}
diff --git a/Marlin/src/HAL/DUE/spi_pins.h b/Marlin/src/HAL/DUE/spi_pins.h
index e28eaf827020..cec22c2c374a 100644
--- a/Marlin/src/HAL/DUE/spi_pins.h
+++ b/Marlin/src/HAL/DUE/spi_pins.h
@@ -43,22 +43,22 @@
#define SPI_PIN 87
#define SPI_CHAN 1
#endif
- #define SCK_PIN 76
- #define MISO_PIN 74
- #define MOSI_PIN 75
+ #define SD_SCK_PIN 76
+ #define SD_MISO_PIN 74
+ #define SD_MOSI_PIN 75
#else
// defaults
#define DUE_SOFTWARE_SPI
- #ifndef SCK_PIN
- #define SCK_PIN 52
+ #ifndef SD_SCK_PIN
+ #define SD_SCK_PIN 52
#endif
- #ifndef MISO_PIN
- #define MISO_PIN 50
+ #ifndef SD_MISO_PIN
+ #define SD_MISO_PIN 50
#endif
- #ifndef MOSI_PIN
- #define MOSI_PIN 51
+ #ifndef SD_MOSI_PIN
+ #define SD_MOSI_PIN 51
#endif
#endif
/* A.28, A.29, B.21, C.26, C.29 */
-#define SS_PIN SDSS
+#define SD_SS_PIN SDSS
diff --git a/Marlin/src/HAL/DUE/timers.cpp b/Marlin/src/HAL/DUE/timers.cpp
index 9b937d1a7c83..e5647817b6f0 100644
--- a/Marlin/src/HAL/DUE/timers.cpp
+++ b/Marlin/src/HAL/DUE/timers.cpp
@@ -42,7 +42,7 @@
// Private Variables
// ------------------------
-const tTimerConfig TimerConfig [NUM_HARDWARE_TIMERS] = {
+const tTimerConfig timer_config[NUM_HARDWARE_TIMERS] = {
{ TC0, 0, TC0_IRQn, 3}, // 0 - [servo timer5]
{ TC0, 1, TC1_IRQn, 0}, // 1
{ TC0, 2, TC2_IRQn, 2}, // 2 - stepper
@@ -66,9 +66,9 @@ const tTimerConfig TimerConfig [NUM_HARDWARE_TIMERS] = {
*/
void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
- Tc *tc = TimerConfig[timer_num].pTimerRegs;
- IRQn_Type irq = TimerConfig[timer_num].IRQ_Id;
- uint32_t channel = TimerConfig[timer_num].channel;
+ Tc *tc = timer_config[timer_num].pTimerRegs;
+ IRQn_Type irq = timer_config[timer_num].IRQ_Id;
+ uint32_t channel = timer_config[timer_num].channel;
// Disable interrupt, just in case it was already enabled
NVIC_DisableIRQ(irq);
@@ -86,13 +86,20 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
pmc_set_writeprotect(false);
pmc_enable_periph_clk((uint32_t)irq);
- NVIC_SetPriority(irq, TimerConfig [timer_num].priority);
+ NVIC_SetPriority(irq, timer_config[timer_num].priority);
// wave mode, reset counter on match with RC,
- TC_Configure(tc, channel, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK1);
+ TC_Configure(tc, channel,
+ TC_CMR_WAVE
+ | TC_CMR_WAVSEL_UP_RC
+ | (HAL_TIMER_PRESCALER == 2 ? TC_CMR_TCCLKS_TIMER_CLOCK1 : 0)
+ | (HAL_TIMER_PRESCALER == 8 ? TC_CMR_TCCLKS_TIMER_CLOCK2 : 0)
+ | (HAL_TIMER_PRESCALER == 32 ? TC_CMR_TCCLKS_TIMER_CLOCK3 : 0)
+ | (HAL_TIMER_PRESCALER == 128 ? TC_CMR_TCCLKS_TIMER_CLOCK4 : 0)
+ );
// Set compare value
- TC_SetRC(tc, channel, VARIANT_MCK / 2 / frequency);
+ TC_SetRC(tc, channel, VARIANT_MCK / (HAL_TIMER_PRESCALER) / frequency);
// And start timer
TC_Start(tc, channel);
@@ -105,12 +112,12 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
}
void HAL_timer_enable_interrupt(const uint8_t timer_num) {
- IRQn_Type irq = TimerConfig[timer_num].IRQ_Id;
+ IRQn_Type irq = timer_config[timer_num].IRQ_Id;
NVIC_EnableIRQ(irq);
}
void HAL_timer_disable_interrupt(const uint8_t timer_num) {
- IRQn_Type irq = TimerConfig[timer_num].IRQ_Id;
+ IRQn_Type irq = timer_config[timer_num].IRQ_Id;
NVIC_DisableIRQ(irq);
// We NEED memory barriers to ensure Interrupts are actually disabled!
@@ -121,11 +128,11 @@ void HAL_timer_disable_interrupt(const uint8_t timer_num) {
// missing from CMSIS: Check if interrupt is enabled or not
static bool NVIC_GetEnabledIRQ(IRQn_Type IRQn) {
- return (NVIC->ISER[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F))) != 0;
+ return TEST(NVIC->ISER[uint32_t(IRQn) >> 5], uint32_t(IRQn) & 0x1F);
}
bool HAL_timer_interrupt_enabled(const uint8_t timer_num) {
- IRQn_Type irq = TimerConfig[timer_num].IRQ_Id;
+ IRQn_Type irq = timer_config[timer_num].IRQ_Id;
return NVIC_GetEnabledIRQ(irq);
}
diff --git a/Marlin/src/HAL/DUE/timers.h b/Marlin/src/HAL/DUE/timers.h
index 0e1ea07cc2e4..dc35c77e6384 100644
--- a/Marlin/src/HAL/DUE/timers.h
+++ b/Marlin/src/HAL/DUE/timers.h
@@ -35,37 +35,38 @@
typedef uint32_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX 0xFFFFFFFF
-#define HAL_TIMER_RATE ((F_CPU) / 2) // frequency of timers peripherals
+#define HAL_TIMER_PRESCALER 2
+#define HAL_TIMER_RATE ((F_CPU) / (HAL_TIMER_PRESCALER)) // frequency of timers peripherals
-#ifndef STEP_TIMER_NUM
- #define STEP_TIMER_NUM 2 // Timer Index for Stepper
+#ifndef MF_TIMER_STEP
+ #define MF_TIMER_STEP 2 // Timer Index for Stepper
#endif
-#ifndef PULSE_TIMER_NUM
- #define PULSE_TIMER_NUM STEP_TIMER_NUM
+#ifndef MF_TIMER_PULSE
+ #define MF_TIMER_PULSE MF_TIMER_STEP
#endif
-#ifndef TEMP_TIMER_NUM
- #define TEMP_TIMER_NUM 4 // Timer Index for Temperature
+#ifndef MF_TIMER_TEMP
+ #define MF_TIMER_TEMP 4 // Timer Index for Temperature
#endif
-#ifndef TONE_TIMER_NUM
- #define TONE_TIMER_NUM 6 // index of timer to use for beeper tones
+#ifndef MF_TIMER_TONE
+ #define MF_TIMER_TONE 6 // index of timer to use for beeper tones
#endif
#define TEMP_TIMER_FREQUENCY 1000 // temperature interrupt frequency
-#define STEPPER_TIMER_RATE HAL_TIMER_RATE // frequency of stepper timer (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE)
-#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // stepper timer ticks per µs
-#define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US)
+#define STEPPER_TIMER_RATE HAL_TIMER_RATE // frequency of stepper timer (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE)
+#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // stepper timer ticks per µs
+#define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US)
-#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // frequency of pulse timer
-#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
-#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
+#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // frequency of pulse timer
+#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
+#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
-#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(STEP_TIMER_NUM)
-#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(STEP_TIMER_NUM)
-#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(STEP_TIMER_NUM)
+#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP)
+#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_STEP)
+#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(MF_TIMER_STEP)
-#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(TEMP_TIMER_NUM)
-#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(TEMP_TIMER_NUM)
+#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_TEMP)
+#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_TEMP)
#ifndef HAL_STEP_TIMER_ISR
#define HAL_STEP_TIMER_ISR() void TC2_Handler()
@@ -92,7 +93,7 @@ typedef struct {
// Public Variables
// ------------------------
-extern const tTimerConfig TimerConfig[];
+extern const tTimerConfig timer_config[];
// ------------------------
// Public functions
@@ -101,17 +102,17 @@ extern const tTimerConfig TimerConfig[];
void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency);
FORCE_INLINE static void HAL_timer_set_compare(const uint8_t timer_num, const hal_timer_t compare) {
- const tTimerConfig * const pConfig = &TimerConfig[timer_num];
+ const tTimerConfig * const pConfig = &timer_config[timer_num];
pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_RC = compare;
}
FORCE_INLINE static hal_timer_t HAL_timer_get_compare(const uint8_t timer_num) {
- const tTimerConfig * const pConfig = &TimerConfig[timer_num];
+ const tTimerConfig * const pConfig = &timer_config[timer_num];
return pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_RC;
}
FORCE_INLINE static hal_timer_t HAL_timer_get_count(const uint8_t timer_num) {
- const tTimerConfig * const pConfig = &TimerConfig[timer_num];
+ const tTimerConfig * const pConfig = &timer_config[timer_num];
return pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_CV;
}
@@ -120,9 +121,9 @@ void HAL_timer_disable_interrupt(const uint8_t timer_num);
bool HAL_timer_interrupt_enabled(const uint8_t timer_num);
FORCE_INLINE static void HAL_timer_isr_prologue(const uint8_t timer_num) {
- const tTimerConfig * const pConfig = &TimerConfig[timer_num];
+ const tTimerConfig * const pConfig = &timer_config[timer_num];
// Reading the status register clears the interrupt flag
pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_SR;
}
-#define HAL_timer_isr_epilogue(TIMER_NUM)
+#define HAL_timer_isr_epilogue(T) NOOP
diff --git a/Marlin/src/HAL/DUE/upload_extra_script.py b/Marlin/src/HAL/DUE/upload_extra_script.py
index d52a0a3642b4..4f7a494512b2 100644
--- a/Marlin/src/HAL/DUE/upload_extra_script.py
+++ b/Marlin/src/HAL/DUE/upload_extra_script.py
@@ -4,15 +4,16 @@
# Windows: bossac.exe
# Other: leave unchanged
#
+import pioutil
+if pioutil.is_pio_build():
+ import platform
+ current_OS = platform.system()
-import platform
-current_OS = platform.system()
+ if current_OS == 'Windows':
-if current_OS == 'Windows':
+ Import("env")
- Import("env")
-
- # Use bossac.exe on Windows
- env.Replace(
- UPLOADCMD="bossac --info --unlock --write --verify --reset --erase -U false --boot $SOURCE"
- )
+ # Use bossac.exe on Windows
+ env.Replace(
+ UPLOADCMD="bossac --info --unlock --write --verify --reset --erase -U false --boot $SOURCE"
+ )
diff --git a/Marlin/src/HAL/DUE/usb/arduino_due_x.h b/Marlin/src/HAL/DUE/usb/arduino_due_x.h
index d3b333fb349a..e7b6f3dcb303 100644
--- a/Marlin/src/HAL/DUE/usb/arduino_due_x.h
+++ b/Marlin/src/HAL/DUE/usb/arduino_due_x.h
@@ -71,7 +71,7 @@
/* ------------------------------------------------------------------------ */
/**
- * \page arduino_due_x_board_info "Arduino Due/X - Board informations"
+ * \page arduino_due_x_board_info "Arduino Due/X - Board information"
* This page lists several definition related to the board description.
*
*/
diff --git a/Marlin/src/HAL/DUE/usb/compiler.h b/Marlin/src/HAL/DUE/usb/compiler.h
index f89e554c4562..633197914eef 100644
--- a/Marlin/src/HAL/DUE/usb/compiler.h
+++ b/Marlin/src/HAL/DUE/usb/compiler.h
@@ -1059,7 +1059,7 @@ static inline void convert_64_bit_to_byte_array(uint64_t value, uint8_t *data)
while (val_index < 8)
{
data[val_index++] = value & 0xFF;
- value = value >> 8;
+ value >>= 8;
}
}
diff --git a/Marlin/src/HAL/DUE/usb/sd_mmc_spi_mem.cpp b/Marlin/src/HAL/DUE/usb/sd_mmc_spi_mem.cpp
index db5e82ec5502..34cc256b30ff 100644
--- a/Marlin/src/HAL/DUE/usb/sd_mmc_spi_mem.cpp
+++ b/Marlin/src/HAL/DUE/usb/sd_mmc_spi_mem.cpp
@@ -10,7 +10,7 @@
#include "../../../sd/cardreader.h"
extern "C" {
-#include "sd_mmc_spi_mem.h"
+ #include "sd_mmc_spi_mem.h"
}
#define SD_MMC_BLOCK_SIZE 512
@@ -32,7 +32,7 @@ Ctrl_status sd_mmc_spi_test_unit_ready() {
Ctrl_status sd_mmc_spi_read_capacity(uint32_t *nb_sector) {
if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.isMounted())
return CTRL_NO_PRESENT;
- *nb_sector = card.getSd2Card().cardSize() - 1;
+ *nb_sector = card.diskIODriver()->cardSize() - 1;
return CTRL_GOOD;
}
@@ -68,30 +68,30 @@ Ctrl_status sd_mmc_spi_usb_read_10(uint32_t addr, uint16_t nb_sector) {
{
char buffer[80];
sprintf_P(buffer, PSTR("SDRD: %d @ 0x%08x\n"), nb_sector, addr);
- PORT_REDIRECT(0);
+ PORT_REDIRECT(SERIAL_PORTMASK(0));
SERIAL_ECHO(buffer);
}
#endif
// Start reading
- if (!card.getSd2Card().readStart(addr))
+ if (!card.diskIODriver()->readStart(addr))
return CTRL_FAIL;
// For each specified sector
while (nb_sector--) {
// Read a sector
- card.getSd2Card().readData(sector_buf);
+ card.diskIODriver()->readData(sector_buf);
// RAM -> USB
if (!udi_msc_trans_block(true, sector_buf, SD_MMC_BLOCK_SIZE, nullptr)) {
- card.getSd2Card().readStop();
+ card.diskIODriver()->readStop();
return CTRL_FAIL;
}
}
// Stop reading
- card.getSd2Card().readStop();
+ card.diskIODriver()->readStop();
// Done
return CTRL_GOOD;
@@ -108,12 +108,12 @@ Ctrl_status sd_mmc_spi_usb_write_10(uint32_t addr, uint16_t nb_sector) {
{
char buffer[80];
sprintf_P(buffer, PSTR("SDWR: %d @ 0x%08x\n"), nb_sector, addr);
- PORT_REDIRECT(0);
+ PORT_REDIRECT(SERIAL_PORTMASK(0));
SERIAL_ECHO(buffer);
}
#endif
- if (!card.getSd2Card().writeStart(addr, nb_sector))
+ if (!card.diskIODriver()->writeStart(addr, nb_sector))
return CTRL_FAIL;
// For each specified sector
@@ -121,16 +121,16 @@ Ctrl_status sd_mmc_spi_usb_write_10(uint32_t addr, uint16_t nb_sector) {
// USB -> RAM
if (!udi_msc_trans_block(false, sector_buf, SD_MMC_BLOCK_SIZE, nullptr)) {
- card.getSd2Card().writeStop();
+ card.diskIODriver()->writeStop();
return CTRL_FAIL;
}
// Write a sector
- card.getSd2Card().writeData(sector_buf);
+ card.diskIODriver()->writeData(sector_buf);
}
// Stop writing
- card.getSd2Card().writeStop();
+ card.diskIODriver()->writeStop();
// Done
return CTRL_GOOD;
diff --git a/Marlin/src/HAL/DUE/usb/sd_mmc_spi_mem.h b/Marlin/src/HAL/DUE/usb/sd_mmc_spi_mem.h
index d77e4f95232b..553fd3c29a88 100644
--- a/Marlin/src/HAL/DUE/usb/sd_mmc_spi_mem.h
+++ b/Marlin/src/HAL/DUE/usb/sd_mmc_spi_mem.h
@@ -74,7 +74,7 @@
#define SD_MMC_REMOVING 2
-//---- CONTROL FONCTIONS ----
+//---- CONTROL FUNCTIONS ----
//!
//! @brief This function initializes the hw/sw resources required to drive the SD_MMC_SPI.
//!/
@@ -134,7 +134,7 @@ extern bool sd_mmc_spi_wr_protect(void);
extern bool sd_mmc_spi_removal(void);
-//---- ACCESS DATA FONCTIONS ----
+//---- ACCESS DATA FUNCTIONS ----
#if ACCESS_USB == true
// Standard functions for open in read/write mode the device
diff --git a/Marlin/src/HAL/DUE/usb/udd.h b/Marlin/src/HAL/DUE/usb/udd.h
index 7ec8c03dee63..319d8842f744 100644
--- a/Marlin/src/HAL/DUE/usb/udd.h
+++ b/Marlin/src/HAL/DUE/usb/udd.h
@@ -90,7 +90,7 @@ typedef struct {
//! This buffer must be word align for DATA IN phase (use prefix COMPILER_WORD_ALIGNED for buffer)
uint8_t *payload;
- //! Size of buffer to send or fill, and content the number of byte transfered
+ //! Size of buffer to send or fill, and content the number of byte transferred
uint16_t payload_size;
//! Callback called after reception of ZLP from setup request
@@ -132,10 +132,10 @@ typedef void (*udd_callback_halt_cleared_t)(void);
*
* \param status UDD_EP_TRANSFER_OK, if transfer is complete
* \param status UDD_EP_TRANSFER_ABORT, if transfer is aborted
- * \param n number of data transfered
+ * \param n number of data transferred
*/
typedef void (*udd_callback_trans_t) (udd_ep_status_t status,
- iram_size_t nb_transfered, udd_ep_id_t ep);
+ iram_size_t nb_transferred, udd_ep_id_t ep);
/**
* \brief Authorizes the VBUS event
@@ -303,7 +303,7 @@ bool udd_ep_wait_stall_clear(udd_ep_id_t ep,
* The driver uses a specific DMA USB to transfer data
* from internal RAM to endpoint, if this one is available.
* When the transfer is finished or aborted (stall, reset, ...), the \a callback is called.
- * The \a callback returns the transfer status and eventually the number of byte transfered.
+ * The \a callback returns the transfer status and eventually the number of byte transferred.
* Note: The control endpoint is not authorized.
*
* \param ep The ID of the endpoint to use
diff --git a/Marlin/src/HAL/DUE/usb/udi_cdc.c b/Marlin/src/HAL/DUE/usb/udi_cdc.c
index cbe23dbb68fb..89debe57f130 100644
--- a/Marlin/src/HAL/DUE/usb/udi_cdc.c
+++ b/Marlin/src/HAL/DUE/usb/udi_cdc.c
@@ -162,7 +162,7 @@ static void udi_cdc_ctrl_state_notify(uint8_t port, udd_ep_id_t ep);
*
* \param status UDD_EP_TRANSFER_OK, if transfer finished
* \param status UDD_EP_TRANSFER_ABORT, if transfer aborted
- * \param n number of data transfered
+ * \param n number of data transferred
*/
static void udi_cdc_serial_state_msg_sent(udd_ep_status_t status, iram_size_t n, udd_ep_id_t ep);
@@ -200,7 +200,7 @@ static void udi_cdc_data_received(udd_ep_status_t status, iram_size_t n, udd_ep_
*
* \param status UDD_EP_TRANSFER_OK, if transfer finished
* \param status UDD_EP_TRANSFER_ABORT, if transfer aborted
- * \param n number of data transfered
+ * \param n number of data transferred
*/
static void udi_cdc_data_sent(udd_ep_status_t status, iram_size_t n, udd_ep_id_t ep);
diff --git a/Marlin/src/HAL/DUE/usb/udi_cdc.h b/Marlin/src/HAL/DUE/usb/udi_cdc.h
index 0ecf7bb00e5e..b61845011aa2 100644
--- a/Marlin/src/HAL/DUE/usb/udi_cdc.h
+++ b/Marlin/src/HAL/DUE/usb/udi_cdc.h
@@ -675,11 +675,11 @@ iram_size_t udi_cdc_multi_write_buf(uint8_t port, const void* buf, iram_size_t s
* - \code // Waits and gets a value on CDC line
int udi_cdc_getc(void);
// Reads a RAM buffer on CDC line
- iram_size_t udi_cdc_read_buf(int* buf, iram_size_t size);
+ iram_size_t udi_cdc_read_buf(int *buf, iram_size_t size);
// Puts a byte on CDC line
int udi_cdc_putc(int value);
// Writes a RAM buffer on CDC line
- iram_size_t udi_cdc_write_buf(const int* buf, iram_size_t size); \endcode
+ iram_size_t udi_cdc_write_buf(const int *buf, iram_size_t size); \endcode
*
* \section udi_cdc_use_cases Advanced use cases
* For more advanced use of the UDI CDC module, see the following use cases:
diff --git a/Marlin/src/HAL/DUE/usb/udi_cdc_conf.h b/Marlin/src/HAL/DUE/usb/udi_cdc_conf.h
index d406a87743f3..e61b8cbaadf4 100644
--- a/Marlin/src/HAL/DUE/usb/udi_cdc_conf.h
+++ b/Marlin/src/HAL/DUE/usb/udi_cdc_conf.h
@@ -106,7 +106,7 @@ extern "C" {
*/
//@{
# if UDI_CDC_PORT_NB > 2
-# error USBB, UDP, UDPHS and UOTGHS interfaces have not enought endpoints.
+# error USBB, UDP, UDPHS and UOTGHS interfaces have not enough endpoints.
# endif
#define UDI_CDC_DATA_EP_IN_0 (1 | USB_EP_DIR_IN) // TX
#define UDI_CDC_DATA_EP_OUT_0 (2 | USB_EP_DIR_OUT) // RX
diff --git a/Marlin/src/HAL/DUE/usb/udi_msc.c b/Marlin/src/HAL/DUE/usb/udi_msc.c
index b7c3bb5ea016..dd3404877210 100644
--- a/Marlin/src/HAL/DUE/usb/udi_msc.c
+++ b/Marlin/src/HAL/DUE/usb/udi_msc.c
@@ -173,7 +173,7 @@ static void udi_msc_cbw_wait(void);
*
* \param status UDD_EP_TRANSFER_OK, if transfer is finished
* \param status UDD_EP_TRANSFER_ABORT, if transfer is aborted
- * \param nb_received number of data transfered
+ * \param nb_received number of data transferred
*/
static void udi_msc_cbw_received(udd_ep_status_t status,
iram_size_t nb_received, udd_ep_id_t ep);
@@ -211,7 +211,7 @@ static void udi_msc_data_send(uint8_t * buffer, uint8_t buf_size);
*
* \param status UDD_EP_TRANSFER_OK, if transfer finish
* \param status UDD_EP_TRANSFER_ABORT, if transfer aborted
- * \param nb_sent number of data transfered
+ * \param nb_sent number of data transferred
*/
static void udi_msc_data_sent(udd_ep_status_t status, iram_size_t nb_sent,
udd_ep_id_t ep);
@@ -244,7 +244,7 @@ void udi_msc_csw_send(void);
*
* \param status UDD_EP_TRANSFER_OK, if transfer is finished
* \param status UDD_EP_TRANSFER_ABORT, if transfer is aborted
- * \param nb_sent number of data transfered
+ * \param nb_sent number of data transferred
*/
static void udi_msc_csw_sent(udd_ep_status_t status, iram_size_t nb_sent,
udd_ep_id_t ep);
@@ -463,7 +463,7 @@ uint8_t udi_msc_getsetting(void)
static void udi_msc_cbw_invalid(void)
{
if (!udi_msc_b_cbw_invalid)
- return; // Don't re-stall endpoint if error reseted by setup
+ return; // Don't re-stall endpoint if error reset by setup
udd_ep_set_halt(UDI_MSC_EP_OUT);
// If stall cleared then re-stall it. Only Setup MSC Reset can clear it
udd_ep_wait_stall_clear(UDI_MSC_EP_OUT, udi_msc_cbw_invalid);
@@ -472,7 +472,7 @@ static void udi_msc_cbw_invalid(void)
static void udi_msc_csw_invalid(void)
{
if (!udi_msc_b_cbw_invalid)
- return; // Don't re-stall endpoint if error reseted by setup
+ return; // Don't re-stall endpoint if error reset by setup
udd_ep_set_halt(UDI_MSC_EP_IN);
// If stall cleared then re-stall it. Only Setup MSC Reset can clear it
udd_ep_wait_stall_clear(UDI_MSC_EP_IN, udi_msc_csw_invalid);
diff --git a/Marlin/src/HAL/DUE/usb/uotghs_device_due.c b/Marlin/src/HAL/DUE/usb/uotghs_device_due.c
index e13232a39c7d..c7e8f8d99135 100644
--- a/Marlin/src/HAL/DUE/usb/uotghs_device_due.c
+++ b/Marlin/src/HAL/DUE/usb/uotghs_device_due.c
@@ -325,7 +325,7 @@ static void udd_sleep_mode(bool b_idle)
/**
* \name Control endpoint low level management routine.
*
- * This function performs control endpoint mangement.
+ * This function performs control endpoint management.
* It handle the SETUP/DATA/HANDSHAKE phases of a control transaction.
*/
//@{
@@ -397,9 +397,9 @@ static void udd_ctrl_endofrequest(void);
/**
* \brief Main interrupt routine for control endpoint
*
- * This switchs control endpoint events to correct sub function.
+ * This switches control endpoint events to correct sub function.
*
- * \return \c 1 if an event about control endpoint is occured, otherwise \c 0.
+ * \return \c 1 if an event about control endpoint is occurred, otherwise \c 0.
*/
static bool udd_ctrl_interrupt(void);
@@ -410,7 +410,7 @@ static bool udd_ctrl_interrupt(void);
* \name Management of bulk/interrupt/isochronous endpoints
*
* The UDD manages the data transfer on endpoints:
- * - Start data tranfer on endpoint with USB Device DMA
+ * - Start data transfer on endpoint with USB Device DMA
* - Send a ZLP packet if requested
* - Call callback registered to signal end of transfer
* The transfer abort and stall feature are supported.
@@ -431,7 +431,7 @@ typedef struct {
uint8_t *buf;
//! Size of buffer to send or fill
iram_size_t buf_size;
- //!< Size of data transfered
+ //!< Size of data transferred
iram_size_t buf_cnt;
//!< Size of data loaded (or prepared for DMA) last time
iram_size_t buf_load;
@@ -486,7 +486,7 @@ static void udd_ep_finish_job(udd_ep_job_t * ptr_job, bool b_abort, uint8_t ep_n
#ifdef UDD_EP_DMA_SUPPORTED
/**
- * \brief Start the next transfer if necessary or complet the job associated.
+ * \brief Start the next transfer if necessary or complete the job associated.
*
* \param ep endpoint number without direction flag
*/
@@ -496,9 +496,9 @@ static void udd_ep_finish_job(udd_ep_job_t * ptr_job, bool b_abort, uint8_t ep_n
/**
* \brief Main interrupt routine for bulk/interrupt/isochronous endpoints
*
- * This switchs endpoint events to correct sub function.
+ * This switches endpoint events to correct sub function.
*
- * \return \c 1 if an event about bulk/interrupt/isochronous endpoints has occured, otherwise \c 0.
+ * \return \c 1 if an event about bulk/interrupt/isochronous endpoints has occurred, otherwise \c 0.
*/
static bool udd_ep_interrupt(void);
@@ -520,7 +520,7 @@ static bool udd_ep_interrupt(void);
*
* Note:
* Here, the global interrupt mask is not clear when an USB interrupt is enabled
- * because this one can not be occured during the USB ISR (=during INTX is masked).
+ * because this one can not be occurred during the USB ISR (=during INTX is masked).
* See Technical reference $3.8.3 Masking interrupt requests in peripheral modules.
*/
#ifdef UHD_ENABLE
@@ -787,7 +787,7 @@ void udd_attach(void)
udd_sleep_mode(true);
otg_unfreeze_clock();
- // This section of clock check can be improved with a chek of
+ // This section of clock check can be improved with a check of
// USB clock source via sysclk()
// Check USB clock because the source can be a PLL
while (!Is_otg_clock_usable());
@@ -803,7 +803,7 @@ void udd_attach(void)
#ifdef USB_DEVICE_HS_SUPPORT
udd_enable_msof_interrupt();
#endif
- // Reset following interupts flag
+ // Reset following interrupts flag
udd_ack_reset();
udd_ack_sof();
udd_ack_msof();
@@ -902,7 +902,7 @@ bool udd_ep_alloc(udd_ep_id_t ep, uint8_t bmAttributes,
}
dbg_print("alloc(%x, %d) ", ep, MaxEndpointSize);
- // Bank choise
+ // Bank choice
switch (bmAttributes & USB_EP_TYPE_MASK) {
case USB_EP_TYPE_ISOCHRONOUS:
nb_bank = UDD_ISOCHRONOUS_NB_BANK(ep);
@@ -1228,7 +1228,7 @@ bool udd_ep_wait_stall_clear(udd_ep_id_t ep,
if (Is_udd_endpoint_stall_requested(ep)
|| ptr_job->stall_requested) {
- // Endpoint halted then registes the callback
+ // Endpoint halted then registers the callback
ptr_job->busy = true;
ptr_job->call_nohalt = callback;
} else {
@@ -1386,7 +1386,7 @@ static void udd_ctrl_setup_received(void)
// Decode setup request
if (udc_process_setup() == false) {
- // Setup request unknow then stall it
+ // Setup request unknown then stall it
udd_ctrl_stall_data();
udd_ack_setup_received(0);
return;
@@ -1447,7 +1447,7 @@ static void udd_ctrl_in_sent(void)
udd_ctrl_prev_payload_buf_cnt += udd_ctrl_payload_buf_cnt;
if ((udd_g_ctrlreq.req.wLength == udd_ctrl_prev_payload_buf_cnt)
|| b_shortpacket) {
- // All data requested are transfered or a short packet has been sent
+ // All data requested are transferred or a short packet has been sent
// then it is the end of data phase.
// Generate an OUT ZLP for handshake phase.
udd_ctrl_send_zlp_out();
@@ -1516,7 +1516,7 @@ static void udd_ctrl_out_received(void)
// End of SETUP request:
// - Data IN Phase aborted,
// - or last Data IN Phase hidden by ZLP OUT sending quiclky,
- // - or ZLP OUT received normaly.
+ // - or ZLP OUT received normally.
udd_ctrl_endofrequest();
} else {
// Protocol error during SETUP request
@@ -1544,7 +1544,7 @@ static void udd_ctrl_out_received(void)
(udd_ctrl_prev_payload_buf_cnt +
udd_ctrl_payload_buf_cnt))) {
// End of reception because it is a short packet
- // Before send ZLP, call intermediat calback
+ // Before send ZLP, call intermediate callback
// in case of data receiv generate a stall
udd_g_ctrlreq.payload_size = udd_ctrl_payload_buf_cnt;
if (NULL != udd_g_ctrlreq.over_under_run) {
@@ -1565,7 +1565,7 @@ static void udd_ctrl_out_received(void)
if (udd_g_ctrlreq.payload_size == udd_ctrl_payload_buf_cnt) {
// Overrun then request a new payload buffer
if (!udd_g_ctrlreq.over_under_run) {
- // No callback availabled to request a new payload buffer
+ // No callback available to request a new payload buffer
udd_ctrl_stall_data();
// Ack reception of OUT to replace NAK by a STALL
udd_ack_out_received(0);
@@ -1805,7 +1805,7 @@ static void udd_ep_trans_done(udd_ep_id_t ep)
// transfer size of UDD_ENDPOINT_MAX_TRANS Bytes
next_trans = UDD_ENDPOINT_MAX_TRANS;
- // Set 0 to tranfer the maximum
+ // Set 0 to transfer the maximum
udd_dma_ctrl = UOTGHS_DEVDMACONTROL_BUFF_LENGTH(0);
} else {
udd_dma_ctrl = UOTGHS_DEVDMACONTROL_BUFF_LENGTH(next_trans);
@@ -1850,7 +1850,7 @@ static void udd_ep_trans_done(udd_ep_id_t ep)
}
cpu_irq_restore(flags);
- // Here a ZLP has been recieved
+ // Here a ZLP has been received
// and the DMA transfer must be not started.
// It is the end of transfer
ptr_job->buf_size = ptr_job->buf_cnt;
@@ -1991,13 +1991,13 @@ static bool udd_ep_interrupt(void)
}
dbg_print("dma%x: ", ep);
udd_disable_endpoint_dma_interrupt(ep);
- // Save number of data no transfered
+ // Save number of data no transferred
nb_remaining = (udd_endpoint_dma_get_status(ep) &
UOTGHS_DEVDMASTATUS_BUFF_COUNT_Msk)
>> UOTGHS_DEVDMASTATUS_BUFF_COUNT_Pos;
if (nb_remaining) {
// Transfer no complete (short packet or ZLP) then:
- // Update number of data transfered
+ // Update number of data transferred
ptr_job->buf_cnt -= nb_remaining;
// Set transfer complete to stop the transfer
ptr_job->buf_size = ptr_job->buf_cnt;
@@ -2056,7 +2056,7 @@ static bool udd_ep_interrupt(void)
udd_disable_endpoint_interrupt(ep);
Assert(ptr_job->stall_requested);
- // A stall has been requested during backgound transfer
+ // A stall has been requested during background transfer
ptr_job->stall_requested = false;
udd_disable_endpoint_bank_autoswitch(ep);
udd_enable_stall_handshake(ep);
diff --git a/Marlin/src/HAL/DUE/usb/usb_protocol_msc.h b/Marlin/src/HAL/DUE/usb/usb_protocol_msc.h
index 0fef30804662..e1e59237d823 100644
--- a/Marlin/src/HAL/DUE/usb/usb_protocol_msc.h
+++ b/Marlin/src/HAL/DUE/usb/usb_protocol_msc.h
@@ -130,7 +130,7 @@ struct usb_msc_cbw {
struct usb_msc_csw {
le32_t dCSWSignature; //!< Must contain 'USBS'
le32_t dCSWTag; //!< Same as dCBWTag
- le32_t dCSWDataResidue; //!< Number of bytes not transfered
+ le32_t dCSWDataResidue; //!< Number of bytes not transferred
uint8_t bCSWStatus; //!< Status code
};
diff --git a/Marlin/src/HAL/DUE/usb/usb_task.c b/Marlin/src/HAL/DUE/usb/usb_task.c
index 66bdb265d881..54a808d7f4f1 100644
--- a/Marlin/src/HAL/DUE/usb/usb_task.c
+++ b/Marlin/src/HAL/DUE/usb/usb_task.c
@@ -264,7 +264,7 @@ bool usb_task_extra_string(void) {
** Handle device requests that the ASF stack doesn't
*/
bool usb_task_other_requests(void) {
- uint8_t* ptr = 0;
+ uint8_t *ptr = 0;
uint16_t size = 0;
if (Udd_setup_type() == USB_REQ_TYPE_VENDOR) {
@@ -322,7 +322,7 @@ void usb_task_init(void) {
char *sptr;
// Patch in the filament diameter
- sprintf_P(diam, PSTR("%d"), (int)((DEFAULT_NOMINAL_FILAMENT_DIA) * 1000.0));
+ itoa((int)((DEFAULT_NOMINAL_FILAMENT_DIA) * 1000), diam, 10);
// And copy it to the proper place, expanding it to unicode
sptr = &diam[0];
diff --git a/Marlin/src/HAL/DUE/watchdog.cpp b/Marlin/src/HAL/DUE/watchdog.cpp
deleted file mode 100644
index 0f4697183056..000000000000
--- a/Marlin/src/HAL/DUE/watchdog.cpp
+++ /dev/null
@@ -1,114 +0,0 @@
-/**
- * Marlin 3D Printer Firmware
- * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
- *
- * Based on Sprinter and grbl.
- * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *
- */
-#ifdef ARDUINO_ARCH_SAM
-
-#include "../../inc/MarlinConfig.h"
-#include "../../MarlinCore.h"
-#include "watchdog.h"
-
-// Override Arduino runtime to either config or disable the watchdog
-//
-// We need to configure the watchdog as soon as possible in the boot
-// process, because watchdog initialization at hardware reset on SAM3X8E
-// is unreliable, and there is risk of unintended resets if we delay
-// that initialization to a later time.
-void watchdogSetup() {
-
- #if ENABLED(USE_WATCHDOG)
-
- // 4 seconds timeout
- uint32_t timeout = 4000;
-
- // Calculate timeout value in WDT counter ticks: This assumes
- // the slow clock is running at 32.768 kHz watchdog
- // frequency is therefore 32768 / 128 = 256 Hz
- timeout = (timeout << 8) / 1000;
- if (timeout == 0)
- timeout = 1;
- else if (timeout > 0xFFF)
- timeout = 0xFFF;
-
- // We want to enable the watchdog with the specified timeout
- uint32_t value =
- WDT_MR_WDV(timeout) | // With the specified timeout
- WDT_MR_WDD(timeout) | // and no invalid write window
- #if !(SAMV70 || SAMV71 || SAME70 || SAMS70)
- WDT_MR_WDRPROC | // WDT fault resets processor only - We want
- // to keep PIO controller state
- #endif
- WDT_MR_WDDBGHLT | // WDT stops in debug state.
- WDT_MR_WDIDLEHLT; // WDT stops in idle state.
-
- #if ENABLED(WATCHDOG_RESET_MANUAL)
- // We enable the watchdog timer, but only for the interrupt.
-
- // Configure WDT to only trigger an interrupt
- value |= WDT_MR_WDFIEN; // Enable WDT fault interrupt.
-
- // Disable WDT interrupt (just in case, to avoid triggering it!)
- NVIC_DisableIRQ(WDT_IRQn);
-
- // We NEED memory barriers to ensure Interrupts are actually disabled!
- // ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
- __DSB();
- __ISB();
-
- // Initialize WDT with the given parameters
- WDT_Enable(WDT, value);
-
- // Configure and enable WDT interrupt.
- NVIC_ClearPendingIRQ(WDT_IRQn);
- NVIC_SetPriority(WDT_IRQn, 0); // Use highest priority, so we detect all kinds of lockups
- NVIC_EnableIRQ(WDT_IRQn);
-
- #else
-
- // a WDT fault triggers a reset
- value |= WDT_MR_WDRSTEN;
-
- // Initialize WDT with the given parameters
- WDT_Enable(WDT, value);
-
- #endif
-
- // Reset the watchdog
- WDT_Restart(WDT);
-
- #else
-
- // Make sure to completely disable the Watchdog
- WDT_Disable(WDT);
-
- #endif
-}
-
-#if ENABLED(USE_WATCHDOG)
- // Initialize watchdog - On SAM3X, Watchdog was already configured
- // and enabled or disabled at startup, so no need to reconfigure it
- // here.
- void watchdog_init() {
- // Reset watchdog to start clean
- WDT_Restart(WDT);
- }
-#endif // USE_WATCHDOG
-
-#endif
diff --git a/Marlin/src/HAL/DUE/watchdog.h b/Marlin/src/HAL/DUE/watchdog.h
deleted file mode 100644
index 5725a10007a7..000000000000
--- a/Marlin/src/HAL/DUE/watchdog.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/**
- * Marlin 3D Printer Firmware
- * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
- *
- * Based on Sprinter and grbl.
- * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *
- */
-#pragma once
-
-// Arduino Due core now has watchdog support
-
-#include "HAL.h"
-
-// Initialize watchdog with a 4 second interrupt time
-void watchdog_init();
-
-// Reset watchdog. MUST be called at least every 4 seconds after the
-// first watchdog_init or AVR will go into emergency procedures.
-inline void HAL_watchdog_refresh() { watchdogReset(); }
diff --git a/Marlin/src/HAL/ESP32/FlushableHardwareSerial.cpp b/Marlin/src/HAL/ESP32/FlushableHardwareSerial.cpp
index d4b2f42c5351..145662215a9b 100644
--- a/Marlin/src/HAL/ESP32/FlushableHardwareSerial.cpp
+++ b/Marlin/src/HAL/ESP32/FlushableHardwareSerial.cpp
@@ -20,14 +20,10 @@
*
*/
-#include "FlushableHardwareSerial.h"
-
#ifdef ARDUINO_ARCH_ESP32
-FlushableHardwareSerial::FlushableHardwareSerial(int uart_nr)
- : HardwareSerial(uart_nr)
-{}
+#include "FlushableHardwareSerial.h"
-FlushableHardwareSerial flushableSerial(0);
+Serial1Class flushableSerial(false, 0);
-#endif // ARDUINO_ARCH_ESP32
+#endif
diff --git a/Marlin/src/HAL/ESP32/FlushableHardwareSerial.h b/Marlin/src/HAL/ESP32/FlushableHardwareSerial.h
index b43caea13c1d..012dda8626b0 100644
--- a/Marlin/src/HAL/ESP32/FlushableHardwareSerial.h
+++ b/Marlin/src/HAL/ESP32/FlushableHardwareSerial.h
@@ -21,17 +21,14 @@
*/
#pragma once
-#ifdef ARDUINO_ARCH_ESP32
-
#include
+#include "../shared/Marduino.h"
+#include "../../core/serial_hook.h"
+
class FlushableHardwareSerial : public HardwareSerial {
public:
- FlushableHardwareSerial(int uart_nr);
-
- inline void flushTX() { /* No need to flush the hardware serial, but defined here for compatibility. */ }
+ FlushableHardwareSerial(int uart_nr) : HardwareSerial(uart_nr) {}
};
-extern FlushableHardwareSerial flushableSerial;
-
-#endif // ARDUINO_ARCH_ESP32
+extern Serial1Class flushableSerial;
diff --git a/Marlin/src/HAL/ESP32/HAL.cpp b/Marlin/src/HAL/ESP32/HAL.cpp
index ead448d78d7a..29f3be3c028a 100644
--- a/Marlin/src/HAL/ESP32/HAL.cpp
+++ b/Marlin/src/HAL/ESP32/HAL.cpp
@@ -28,6 +28,10 @@
#include
#include
+#if ENABLED(USE_ESP32_TASK_WDT)
+ #include
+#endif
+
#if ENABLED(WIFISUPPORT)
#include
#include "wifi.h"
@@ -40,11 +44,15 @@
#endif
#endif
+#if ENABLED(ESP3D_WIFISUPPORT)
+ DefaultSerial1 MSerial0(false, Serial2Socket);
+#endif
+
// ------------------------
// Externs
// ------------------------
-portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED;
+portMUX_TYPE MarlinHAL::spinlock = portMUX_INITIALIZER_UNLOCKED;
// ------------------------
// Local defines
@@ -56,7 +64,8 @@ portMUX_TYPE spinlock = portMUX_INITIALIZER_UNLOCKED;
// Public Variables
// ------------------------
-uint16_t HAL_adc_result;
+uint16_t MarlinHAL::adc_result;
+pwm_pin_t MarlinHAL::pwm_pin_data[MAX_EXPANDER_BITS];
// ------------------------
// Private Variables
@@ -65,9 +74,16 @@ uint16_t HAL_adc_result;
esp_adc_cal_characteristics_t characteristics[ADC_ATTEN_MAX];
adc_atten_t attenuations[ADC1_CHANNEL_MAX] = {};
uint32_t thresholds[ADC_ATTEN_MAX];
-volatile int numPWMUsed = 0,
- pwmPins[MAX_PWM_PINS],
- pwmValues[MAX_PWM_PINS];
+
+volatile int numPWMUsed = 0;
+volatile struct { pin_t pin; int value; } pwmState[MAX_PWM_PINS];
+
+pin_t chan_pin[CHANNEL_MAX_NUM + 1] = { 0 }; // PWM capable IOpins - not 0 or >33 on ESP32
+
+struct {
+ uint32_t freq; // ledcReadFreq doesn't work if a duty hasn't been set yet!
+ uint16_t res;
+} pwmInfo[(CHANNEL_MAX_NUM + 1) / 2];
// ------------------------
// Public functions
@@ -86,10 +102,26 @@ volatile int numPWMUsed = 0,
#endif
-void HAL_init() { TERN_(I2S_STEPPER_STREAM, i2s_init()); }
+#if ENABLED(USE_ESP32_EXIO)
-void HAL_init_board() {
+ HardwareSerial YSerial2(2);
+ void Write_EXIO(uint8_t IO, uint8_t v) {
+ if (hal.isr_state()) {
+ hal.isr_off();
+ YSerial2.write(0x80 | (((char)v) << 5) | (IO - 100));
+ hal.isr_on();
+ }
+ else
+ YSerial2.write(0x80 | (((char)v) << 5) | (IO - 100));
+ }
+
+#endif
+
+void MarlinHAL::init_board() {
+ #if ENABLED(USE_ESP32_TASK_WDT)
+ esp_task_wdt_init(10, true);
+ #endif
#if ENABLED(ESP3D_WIFISUPPORT)
esp3dlib.init();
#elif ENABLED(WIFISUPPORT)
@@ -122,27 +154,61 @@ void HAL_init_board() {
#endif
#endif
+ // Initialize the i2s peripheral only if the I2S stepper stream is enabled.
+ // The following initialization is performed after Serial1 and Serial2 are defined as
+ // their native pins might conflict with the i2s stream even when they are remapped.
+ #if ENABLED(USE_ESP32_EXIO)
+ YSerial2.begin(460800 * 3, SERIAL_8N1, 16, 17);
+ #elif ENABLED(I2S_STEPPER_STREAM)
+ i2s_init();
+ #endif
}
-void HAL_idletask() {
+void MarlinHAL::idletask() {
#if BOTH(WIFISUPPORT, OTASUPPORT)
OTA_handle();
#endif
TERN_(ESP3D_WIFISUPPORT, esp3dlib.idletask());
}
-void HAL_clear_reset_source() { }
+uint8_t MarlinHAL::get_reset_source() { return rtc_get_reset_reason(1); }
-uint8_t HAL_get_reset_source() { return rtc_get_reset_reason(1); }
+void MarlinHAL::reboot() { ESP.restart(); }
void _delay_ms(int delay_ms) { delay(delay_ms); }
// return free memory between end of heap (or end bss) and whatever is current
-int freeMemory() { return ESP.getFreeHeap(); }
+int MarlinHAL::freeMemory() { return ESP.getFreeHeap(); }
+
+// ------------------------
+// Watchdog Timer
+// ------------------------
+
+#if ENABLED(USE_WATCHDOG)
+
+ #define WDT_TIMEOUT_US TERN(WATCHDOG_DURATION_8S, 8000000, 4000000) // 4 or 8 second timeout
+
+ extern "C" {
+ esp_err_t esp_task_wdt_reset();
+ }
+
+ void watchdogSetup() {
+ // do whatever. don't remove this function.
+ }
+
+ void MarlinHAL::watchdog_init() {
+ // TODO
+ }
+
+ // Reset watchdog.
+ void MarlinHAL::watchdog_refresh() { esp_task_wdt_reset(); }
+
+#endif
// ------------------------
// ADC
// ------------------------
+
#define ADC1_CHANNEL(pin) ADC1_GPIO ## pin ## _CHANNEL
adc1_channel_t get_channel(int pin) {
@@ -164,21 +230,24 @@ void adc1_set_attenuation(adc1_channel_t chan, adc_atten_t atten) {
}
}
-void HAL_adc_init() {
+void MarlinHAL::adc_init() {
// Configure ADC
adc1_config_width(ADC_WIDTH_12Bit);
// Configure channels only if used as (re-)configuring a pin for ADC that is used elsewhere might have adverse effects
- TERN_(HAS_TEMP_ADC_0, adc1_set_attenuation(get_channel(TEMP_0_PIN), ADC_ATTEN_11db));
- TERN_(HAS_TEMP_ADC_1, adc1_set_attenuation(get_channel(TEMP_1_PIN), ADC_ATTEN_11db));
- TERN_(HAS_TEMP_ADC_2, adc1_set_attenuation(get_channel(TEMP_2_PIN), ADC_ATTEN_11db));
- TERN_(HAS_TEMP_ADC_3, adc1_set_attenuation(get_channel(TEMP_3_PIN), ADC_ATTEN_11db));
- TERN_(HAS_TEMP_ADC_4, adc1_set_attenuation(get_channel(TEMP_4_PIN), ADC_ATTEN_11db));
- TERN_(HAS_TEMP_ADC_5, adc1_set_attenuation(get_channel(TEMP_5_PIN), ADC_ATTEN_11db));
- TERN_(HAS_TEMP_ADC_6, adc2_set_attenuation(get_channel(TEMP_6_PIN), ADC_ATTEN_11db));
- TERN_(HAS_TEMP_ADC_7, adc3_set_attenuation(get_channel(TEMP_7_PIN), ADC_ATTEN_11db));
- TERN_(HAS_HEATED_BED, adc1_set_attenuation(get_channel(TEMP_BED_PIN), ADC_ATTEN_11db));
- TERN_(HAS_TEMP_CHAMBER, adc1_set_attenuation(get_channel(TEMP_CHAMBER_PIN), ADC_ATTEN_11db));
+ TERN_(HAS_TEMP_ADC_0, adc1_set_attenuation(get_channel(TEMP_0_PIN), ADC_ATTEN_11db));
+ TERN_(HAS_TEMP_ADC_1, adc1_set_attenuation(get_channel(TEMP_1_PIN), ADC_ATTEN_11db));
+ TERN_(HAS_TEMP_ADC_2, adc1_set_attenuation(get_channel(TEMP_2_PIN), ADC_ATTEN_11db));
+ TERN_(HAS_TEMP_ADC_3, adc1_set_attenuation(get_channel(TEMP_3_PIN), ADC_ATTEN_11db));
+ TERN_(HAS_TEMP_ADC_4, adc1_set_attenuation(get_channel(TEMP_4_PIN), ADC_ATTEN_11db));
+ TERN_(HAS_TEMP_ADC_5, adc1_set_attenuation(get_channel(TEMP_5_PIN), ADC_ATTEN_11db));
+ TERN_(HAS_TEMP_ADC_6, adc2_set_attenuation(get_channel(TEMP_6_PIN), ADC_ATTEN_11db));
+ TERN_(HAS_TEMP_ADC_7, adc3_set_attenuation(get_channel(TEMP_7_PIN), ADC_ATTEN_11db));
+ TERN_(HAS_HEATED_BED, adc1_set_attenuation(get_channel(TEMP_BED_PIN), ADC_ATTEN_11db));
+ TERN_(HAS_TEMP_CHAMBER, adc1_set_attenuation(get_channel(TEMP_CHAMBER_PIN), ADC_ATTEN_11db));
+ TERN_(HAS_TEMP_PROBE, adc1_set_attenuation(get_channel(TEMP_PROBE_PIN), ADC_ATTEN_11db));
+ TERN_(HAS_TEMP_COOLER, adc1_set_attenuation(get_channel(TEMP_COOLER_PIN), ADC_ATTEN_11db));
+ TERN_(HAS_TEMP_BOARD, adc1_set_attenuation(get_channel(TEMP_BOARD_PIN), ADC_ATTEN_11db));
TERN_(FILAMENT_WIDTH_SENSOR, adc1_set_attenuation(get_channel(FILWIDTH_PIN), ADC_ATTEN_11db));
// Note that adc2 is shared with the WiFi module, which has higher priority, so the conversion may fail.
@@ -193,11 +262,16 @@ void HAL_adc_init() {
}
}
-void HAL_adc_start_conversion(const uint8_t adc_pin) {
- const adc1_channel_t chan = get_channel(adc_pin);
+#ifndef ADC_REFERENCE_VOLTAGE
+ #define ADC_REFERENCE_VOLTAGE 3.3
+#endif
+
+void MarlinHAL::adc_start(const pin_t pin) {
+ const adc1_channel_t chan = get_channel(pin);
uint32_t mv;
esp_adc_cal_get_voltage((adc_channel_t)chan, &characteristics[attenuations[chan]], &mv);
- HAL_adc_result = mv * 1023.0 / 3300.0;
+
+ adc_result = mv * isr_float_t(1023) / isr_float_t(ADC_REFERENCE_VOLTAGE) / isr_float_t(1000);
// Change the attenuation level based on the new reading
adc_atten_t atten;
@@ -214,25 +288,106 @@ void HAL_adc_start_conversion(const uint8_t adc_pin) {
adc1_set_attenuation(chan, atten);
}
-void analogWrite(pin_t pin, int value) {
- // Use ledc hardware for internal pins
- if (pin < 34) {
- static int cnt_channel = 1, pin_to_channel[40] = { 0 };
- if (pin_to_channel[pin] == 0) {
- ledcAttachPin(pin, cnt_channel);
- ledcSetup(cnt_channel, 490, 8);
- ledcWrite(cnt_channel, value);
- pin_to_channel[pin] = cnt_channel++;
+// ------------------------
+// PWM
+// ------------------------
+
+int8_t channel_for_pin(const uint8_t pin) {
+ for (int i = 0; i <= CHANNEL_MAX_NUM; i++)
+ if (chan_pin[i] == pin) return i;
+ return -1;
+}
+
+// get PWM channel for pin - if none then attach a new one
+// return -1 if fail or invalid pin#, channel # (0-15) if success
+int8_t get_pwm_channel(const pin_t pin, const uint32_t freq, const uint16_t res) {
+ if (!WITHIN(pin, 1, MAX_PWM_IOPIN)) return -1; // Not a hardware PWM pin!
+ int8_t cid = channel_for_pin(pin);
+ if (cid >= 0) return cid;
+
+ // Find an empty adjacent channel (same timer & freq/res)
+ for (int i = 0; i <= CHANNEL_MAX_NUM; i++) {
+ if (chan_pin[i] == 0) {
+ if (chan_pin[i ^ 0x1] != 0) {
+ if (pwmInfo[i / 2].freq == freq && pwmInfo[i / 2].res == res) {
+ chan_pin[i] = pin; // Allocate PWM to this channel
+ ledcAttachPin(pin, i);
+ return i;
+ }
+ }
+ else if (cid == -1) // Pair of empty channels?
+ cid = i & 0xFE; // Save lower channel number
+ }
+ }
+ // not attached, is an empty timer slot avail?
+ if (cid >= 0) {
+ chan_pin[cid] = pin;
+ pwmInfo[cid / 2].freq = freq;
+ pwmInfo[cid / 2].res = res;
+ ledcSetup(cid, freq, res);
+ ledcAttachPin(pin, cid);
+ }
+ return cid; // -1 if no channel avail
+}
+
+void MarlinHAL::set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=_BV(PWM_RESOLUTION)-1*/, const bool invert/*=false*/) {
+ #if ENABLED(I2S_STEPPER_STREAM)
+ if (pin > 127) {
+ const uint8_t pinlo = pin & 0x7F;
+ pwm_pin_t &pindata = pwm_pin_data[pinlo];
+ const uint32_t duty = map(invert ? v_size - v : v, 0, v_size, 0, pindata.pwm_cycle_ticks);
+ if (duty == 0 || duty == pindata.pwm_cycle_ticks) { // max or min (i.e., on/off)
+ pindata.pwm_duty_ticks = 0; // turn off PWM for this pin
+ duty ? SBI32(i2s_port_data, pinlo) : CBI32(i2s_port_data, pinlo); // set pin level
+ }
+ else
+ pindata.pwm_duty_ticks = duty; // PWM duty count = # of 4µs ticks per full PWM cycle
}
- ledcWrite(pin_to_channel[pin], value);
+ else
+ #endif
+ {
+ const int8_t cid = get_pwm_channel(pin, PWM_FREQUENCY, PWM_RESOLUTION);
+ if (cid >= 0) {
+ const uint32_t duty = map(invert ? v_size - v : v, 0, v_size, 0, _BV(PWM_RESOLUTION)-1);
+ ledcWrite(cid, duty);
+ }
+ }
+}
+
+int8_t MarlinHAL::set_pwm_frequency(const pin_t pin, const uint32_t f_desired) {
+ #if ENABLED(I2S_STEPPER_STREAM)
+ if (pin > 127) {
+ pwm_pin_data[pin & 0x7F].pwm_cycle_ticks = 1000000UL / f_desired / 4; // # of 4µs ticks per full PWM cycle
+ return 0;
+ }
+ else
+ #endif
+ {
+ const int8_t cid = channel_for_pin(pin);
+ if (cid >= 0) {
+ if (f_desired == ledcReadFreq(cid)) return cid; // no freq change
+ ledcDetachPin(chan_pin[cid]);
+ chan_pin[cid] = 0; // remove old freq channel
+ }
+ return get_pwm_channel(pin, f_desired, PWM_RESOLUTION); // try for new one
+ }
+}
+
+// use hardware PWM if avail, if not then ISR
+void analogWrite(const pin_t pin, const uint16_t value, const uint32_t freq/*=PWM_FREQUENCY*/, const uint16_t res/*=8*/) { // always 8 bit resolution!
+ // Use ledc hardware for internal pins
+ const int8_t cid = get_pwm_channel(pin, freq, res);
+ if (cid >= 0) {
+ ledcWrite(cid, value); // set duty value
return;
}
+ // not a hardware PWM pin OR no PWM channels available
int idx = -1;
// Search Pin
for (int i = 0; i < numPWMUsed; ++i)
- if (pwmPins[i] == pin) { idx = i; break; }
+ if (pwmState[i].pin == pin) { idx = i; break; }
// not found ?
if (idx < 0) {
@@ -241,34 +396,34 @@ void analogWrite(pin_t pin, int value) {
// Take new slot for pin
idx = numPWMUsed;
- pwmPins[idx] = pin;
+ pwmState[idx].pin = pin;
// Start timer on first use
- if (idx == 0) HAL_timer_start(PWM_TIMER_NUM, PWM_TIMER_FREQUENCY);
+ if (idx == 0) HAL_timer_start(MF_TIMER_PWM, PWM_TIMER_FREQUENCY);
++numPWMUsed;
}
// Use 7bit internal value - add 1 to have 100% high at 255
- pwmValues[idx] = (value + 1) / 2;
+ pwmState[idx].value = (value + 1) / 2;
}
// Handle PWM timer interrupt
HAL_PWM_TIMER_ISR() {
- HAL_timer_isr_prologue(PWM_TIMER_NUM);
+ HAL_timer_isr_prologue(MF_TIMER_PWM);
static uint8_t count = 0;
for (int i = 0; i < numPWMUsed; ++i) {
if (count == 0) // Start of interval
- WRITE(pwmPins[i], pwmValues[i] ? HIGH : LOW);
- else if (pwmValues[i] == count) // End of duration
- WRITE(pwmPins[i], LOW);
+ digitalWrite(pwmState[i].pin, pwmState[i].value ? HIGH : LOW);
+ else if (pwmState[i].value == count) // End of duration
+ digitalWrite(pwmState[i].pin, LOW);
}
// 128 for 7 Bit resolution
count = (count + 1) & 0x7F;
- HAL_timer_isr_epilogue(PWM_TIMER_NUM);
+ HAL_timer_isr_epilogue(MF_TIMER_PWM);
}
#endif // ARDUINO_ARCH_ESP32
diff --git a/Marlin/src/HAL/ESP32/HAL.h b/Marlin/src/HAL/ESP32/HAL.h
index ebc16c9525e7..ddfedf92eed9 100644
--- a/Marlin/src/HAL/ESP32/HAL.h
+++ b/Marlin/src/HAL/ESP32/HAL.h
@@ -32,7 +32,6 @@
#include "../shared/HAL_SPI.h"
#include "fastio.h"
-#include "watchdog.h"
#include "i2s.h"
#if ENABLED(WIFISUPPORT)
@@ -49,87 +48,68 @@
// Defines
// ------------------------
-extern portMUX_TYPE spinlock;
-
-#define MYSERIAL0 flushableSerial
+#define MYSERIAL1 flushableSerial
#if EITHER(WIFISUPPORT, ESP3D_WIFISUPPORT)
#if ENABLED(ESP3D_WIFISUPPORT)
- #define MYSERIAL1 Serial2Socket
+ typedef ForwardSerial1Class< decltype(Serial2Socket) > DefaultSerial1;
+ extern DefaultSerial1 MSerial0;
+ #define MYSERIAL2 MSerial0
#else
- #define MYSERIAL1 webSocketSerial
+ #define MYSERIAL2 webSocketSerial
#endif
#endif
-#define CRITICAL_SECTION_START() portENTER_CRITICAL(&spinlock)
-#define CRITICAL_SECTION_END() portEXIT_CRITICAL(&spinlock)
-#define ISRS_ENABLED() (spinlock.owner == portMUX_FREE_VAL)
-#define ENABLE_ISRS() if (spinlock.owner != portMUX_FREE_VAL) portEXIT_CRITICAL(&spinlock)
-#define DISABLE_ISRS() portENTER_CRITICAL(&spinlock)
+#define CRITICAL_SECTION_START() portENTER_CRITICAL(&hal.spinlock)
+#define CRITICAL_SECTION_END() portEXIT_CRITICAL(&hal.spinlock)
-// Fix bug in pgm_read_ptr
-#undef pgm_read_ptr
-#define pgm_read_ptr(addr) (*(addr))
+#define HAL_CAN_SET_PWM_FREQ // This HAL supports PWM Frequency adjustment
+#define PWM_FREQUENCY 1000u // Default PWM frequency when set_pwm_duty() is called without set_pwm_frequency()
+#define PWM_RESOLUTION 10u // Default PWM bit resolution
+#define CHANNEL_MAX_NUM 15u // max PWM channel # to allocate (7 to only use low speed, 15 to use low & high)
+#define MAX_PWM_IOPIN 33u // hardware pwm pins < 34
+#ifndef MAX_EXPANDER_BITS
+ #define MAX_EXPANDER_BITS 32 // I2S expander bit width (max 32)
+#endif
// ------------------------
// Types
// ------------------------
+typedef double isr_float_t; // FPU ops are used for single-precision, so use double for ISRs.
typedef int16_t pin_t;
-#define HAL_SERVO_LIB Servo
-
-// ------------------------
-// Public Variables
-// ------------------------
+typedef struct pwm_pin {
+ uint32_t pwm_cycle_ticks = 1000000UL / (PWM_FREQUENCY) / 4; // # ticks per pwm cycle
+ uint32_t pwm_tick_count = 0; // current tick count
+ uint32_t pwm_duty_ticks = 0; // # of ticks for current duty cycle
+} pwm_pin_t;
-/** result of last ADC conversion */
-extern uint16_t HAL_adc_result;
+class Servo;
+typedef Servo hal_servo_t;
// ------------------------
// Public functions
// ------------------------
-// clear reset reason
-void HAL_clear_reset_source();
-
-// reset reason
-uint8_t HAL_get_reset_source();
-
-inline void HAL_reboot() {} // reboot the board or restart the bootloader
-
-void _delay_ms(int delay);
-
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-function"
-int freeMemory();
-#pragma GCC diagnostic pop
-
-void analogWrite(pin_t pin, int value);
-
-// ADC
-#define HAL_ANALOG_SELECT(pin)
-
-void HAL_adc_init();
-
-#define HAL_ADC_VREF 3.3
-#define HAL_ADC_RESOLUTION 10
-#define HAL_START_ADC(pin) HAL_adc_start_conversion(pin)
-#define HAL_READ_ADC() HAL_adc_result
-#define HAL_ADC_READY() true
-
-void HAL_adc_start_conversion(const uint8_t adc_pin);
+//
+// Tone
+//
+void tone(const pin_t _pin, const unsigned int frequency, const unsigned long duration=0);
+void noTone(const pin_t _pin);
+int8_t get_pwm_channel(const pin_t pin, const uint32_t freq, const uint16_t res);
+void analogWrite(const pin_t pin, const uint16_t value, const uint32_t freq=PWM_FREQUENCY, const uint16_t res=8);
+//
+// Pin Mapping for M42, M43, M226
+//
#define GET_PIN_MAP_PIN(index) index
#define GET_PIN_MAP_INDEX(pin) pin
#define PARSED_PIN_INDEX(code, dval) parser.intval(code, dval)
-// Enable hooks into idle and setup for HAL
-#define HAL_IDLETASK 1
-#define BOARD_INIT() HAL_init_board();
-void HAL_idletask();
-void HAL_init();
-void HAL_init_board();
+#if ENABLED(USE_ESP32_EXIO)
+ void Write_EXIO(uint8_t IO, uint8_t v);
+#endif
//
// Delay in cycles (used by DELAY_NS / DELAY_US)
@@ -171,3 +151,96 @@ FORCE_INLINE static void DELAY_CYCLES(uint32_t x) {
}
}
+
+// ------------------------
+// Class Utilities
+// ------------------------
+
+#pragma GCC diagnostic push
+#if GCC_VERSION <= 50000
+ #pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+
+int freeMemory();
+
+#pragma GCC diagnostic pop
+
+void _delay_ms(const int ms);
+
+// ------------------------
+// MarlinHAL Class
+// ------------------------
+
+#define HAL_ADC_VREF 3.3
+#define HAL_ADC_RESOLUTION 10
+
+class MarlinHAL {
+public:
+
+ // Earliest possible init, before setup()
+ MarlinHAL() {}
+
+ // Watchdog
+ static void watchdog_init() IF_DISABLED(USE_WATCHDOG, {});
+ static void watchdog_refresh() IF_DISABLED(USE_WATCHDOG, {});
+
+ static void init() {} // Called early in setup()
+ static void init_board(); // Called less early in setup()
+ static void reboot(); // Restart the firmware
+
+ // Interrupts
+ static portMUX_TYPE spinlock;
+ static bool isr_state() { return spinlock.owner == portMUX_FREE_VAL; }
+ static void isr_on() { if (spinlock.owner != portMUX_FREE_VAL) portEXIT_CRITICAL(&spinlock); }
+ static void isr_off() { portENTER_CRITICAL(&spinlock); }
+
+ static void delay_ms(const int ms) { _delay_ms(ms); }
+
+ // Tasks, called from idle()
+ static void idletask();
+
+ // Reset
+ static uint8_t get_reset_source();
+ static void clear_reset_source() {}
+
+ // Free SRAM
+ static int freeMemory();
+
+ static pwm_pin_t pwm_pin_data[MAX_EXPANDER_BITS];
+
+ //
+ // ADC Methods
+ //
+
+ static uint16_t adc_result;
+
+ // Called by Temperature::init once at startup
+ static void adc_init();
+
+ // Called by Temperature::init for each sensor at startup
+ static void adc_enable(const pin_t pin) {}
+
+ // Begin ADC sampling on the given pin. Called from Temperature::isr!
+ static void adc_start(const pin_t pin);
+
+ // Is the ADC ready for reading?
+ static bool adc_ready() { return true; }
+
+ // The current value of the ADC register
+ static uint16_t adc_value() { return adc_result; }
+
+ /**
+ * If not already allocated, allocate a hardware PWM channel
+ * to the pin and set the duty cycle..
+ * Optionally invert the duty cycle [default = false]
+ * Optionally change the scale of the provided value to enable finer PWM duty control [default = 255]
+ */
+ static void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size=255, const bool invert=false);
+
+ /**
+ * Allocate and set the frequency of a hardware PWM pin
+ * Returns -1 if no pin available.
+ */
+ static int8_t set_pwm_frequency(const pin_t pin, const uint32_t f_desired);
+
+};
diff --git a/Marlin/src/HAL/ESP32/HAL_SPI.cpp b/Marlin/src/HAL/ESP32/HAL_SPI.cpp
index 8e5875fc388d..868ab1b6712d 100644
--- a/Marlin/src/HAL/ESP32/HAL_SPI.cpp
+++ b/Marlin/src/HAL/ESP32/HAL_SPI.cpp
@@ -53,11 +53,9 @@ static SPISettings spiConfig;
// ------------------------
void spiBegin() {
- #if !PIN_EXISTS(SS)
- #error "SS_PIN not defined!"
+ #if ENABLED(SDSUPPORT) && PIN_EXISTS(SD_SS)
+ OUT_WRITE(SD_SS_PIN, HIGH);
#endif
-
- OUT_WRITE(SS_PIN, HIGH);
}
void spiInit(uint8_t spiRate) {
@@ -85,7 +83,7 @@ uint8_t spiRec() {
return returnByte;
}
-void spiRead(uint8_t* buf, uint16_t nbyte) {
+void spiRead(uint8_t *buf, uint16_t nbyte) {
SPI.beginTransaction(spiConfig);
SPI.transferBytes(0, buf, nbyte);
SPI.endTransaction();
@@ -97,7 +95,7 @@ void spiSend(uint8_t b) {
SPI.endTransaction();
}
-void spiSendBlock(uint8_t token, const uint8_t* buf) {
+void spiSendBlock(uint8_t token, const uint8_t *buf) {
SPI.beginTransaction(spiConfig);
SPI.transfer(token);
SPI.writeBytes(const_cast(buf), 512);
diff --git a/Marlin/src/HAL/ESP32/MarlinSPI.h b/Marlin/src/HAL/ESP32/MarlinSPI.h
new file mode 100644
index 000000000000..0c447ba4cb3d
--- /dev/null
+++ b/Marlin/src/HAL/ESP32/MarlinSPI.h
@@ -0,0 +1,26 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#pragma once
+
+#include
+
+using MarlinSPI = SPIClass;
diff --git a/Marlin/src/HAL/ESP32/Servo.cpp b/Marlin/src/HAL/ESP32/Servo.cpp
index fcf58485819e..ca3950d07f75 100644
--- a/Marlin/src/HAL/ESP32/Servo.cpp
+++ b/Marlin/src/HAL/ESP32/Servo.cpp
@@ -31,20 +31,18 @@
// so we only allocate servo channels up high to avoid side effects with regards to analogWrite (fans, leds, laser pwm etc.)
int Servo::channel_next_free = 12;
-Servo::Servo() {
- channel = channel_next_free++;
-}
+Servo::Servo() {}
int8_t Servo::attach(const int inPin) {
- if (channel >= CHANNEL_MAX_NUM) return -1;
if (inPin > 0) pin = inPin;
-
- ledcSetup(channel, 50, 16); // channel X, 50 Hz, 16-bit depth
- ledcAttachPin(pin, channel);
- return true;
+ channel = get_pwm_channel(pin, 50u, 16u);
+ return channel; // -1 if no PWM avail.
}
-void Servo::detach() { ledcDetachPin(pin); }
+// leave channel connected to servo - set duty to zero
+void Servo::detach() {
+ if (channel >= 0) ledcWrite(channel, 0);
+}
int Servo::read() { return degrees; }
@@ -52,7 +50,7 @@ void Servo::write(int inDegrees) {
degrees = constrain(inDegrees, MIN_ANGLE, MAX_ANGLE);
int us = map(degrees, MIN_ANGLE, MAX_ANGLE, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);
int duty = map(us, 0, TAU_USEC, 0, MAX_COMPARE);
- ledcWrite(channel, duty);
+ if (channel >= 0) ledcWrite(channel, duty); // don't save duty for servos!
}
void Servo::move(const int value) {
diff --git a/Marlin/src/HAL/ESP32/Servo.h b/Marlin/src/HAL/ESP32/Servo.h
index b0d929452732..1dbb416a8317 100644
--- a/Marlin/src/HAL/ESP32/Servo.h
+++ b/Marlin/src/HAL/ESP32/Servo.h
@@ -30,8 +30,7 @@ class Servo {
MAX_PULSE_WIDTH = 2400, // Longest pulse sent to a servo
TAU_MSEC = 20,
TAU_USEC = (TAU_MSEC * 1000),
- MAX_COMPARE = ((1 << 16) - 1), // 65535
- CHANNEL_MAX_NUM = 16;
+ MAX_COMPARE = _BV(16) - 1; // 65535
public:
Servo();
diff --git a/Marlin/src/HAL/ESP32/Tone.cpp b/Marlin/src/HAL/ESP32/Tone.cpp
new file mode 100644
index 000000000000..839c612b6a87
--- /dev/null
+++ b/Marlin/src/HAL/ESP32/Tone.cpp
@@ -0,0 +1,59 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * Copypaste of SAMD51 HAL developed by Giuliano Zaro (AKA GMagician)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+
+/**
+ * Description: Tone function for ESP32
+ * Derived from https://forum.arduino.cc/index.php?topic=136500.msg2903012#msg2903012
+ */
+
+#ifdef ARDUINO_ARCH_ESP32
+
+#include "../../inc/MarlinConfig.h"
+#include "HAL.h"
+
+static pin_t tone_pin;
+volatile static int32_t toggles;
+
+void tone(const pin_t _pin, const unsigned int frequency, const unsigned long duration/*=0*/) {
+ tone_pin = _pin;
+ toggles = 2 * frequency * duration / 1000;
+ HAL_timer_start(MF_TIMER_TONE, 2 * frequency);
+}
+
+void noTone(const pin_t _pin) {
+ HAL_timer_disable_interrupt(MF_TIMER_TONE);
+ WRITE(_pin, LOW);
+}
+
+HAL_TONE_TIMER_ISR() {
+ HAL_timer_isr_prologue(MF_TIMER_TONE);
+
+ if (toggles) {
+ toggles--;
+ TOGGLE(tone_pin);
+ }
+ else noTone(tone_pin); // turn off interrupt
+}
+
+#endif // ARDUINO_ARCH_ESP32
diff --git a/Marlin/src/HAL/ESP32/WebSocketSerial.cpp b/Marlin/src/HAL/ESP32/WebSocketSerial.cpp
index ca7f47a1f8bd..eb5b9d60395a 100644
--- a/Marlin/src/HAL/ESP32/WebSocketSerial.cpp
+++ b/Marlin/src/HAL/ESP32/WebSocketSerial.cpp
@@ -29,7 +29,7 @@
#include "wifi.h"
#include
-WebSocketSerial webSocketSerial;
+MSerialWebSocketT webSocketSerial(false);
AsyncWebSocket ws("/ws"); // TODO Move inside the class.
// RingBuffer impl
@@ -137,16 +137,12 @@ size_t WebSocketSerial::write(const uint8_t c) {
return ret;
}
-size_t WebSocketSerial::write(const uint8_t* buffer, size_t size) {
+size_t WebSocketSerial::write(const uint8_t *buffer, size_t size) {
size_t written = 0;
for (size_t i = 0; i < size; i++)
written += write(buffer[i]);
return written;
}
-void WebSocketSerial::flushTX() {
- // No need to do anything as there's no benefit to sending partial lines over the websocket connection.
-}
-
#endif // WIFISUPPORT
#endif // ARDUINO_ARCH_ESP32
diff --git a/Marlin/src/HAL/ESP32/WebSocketSerial.h b/Marlin/src/HAL/ESP32/WebSocketSerial.h
index 7a25c6dc5e9c..6b3e419d10c5 100644
--- a/Marlin/src/HAL/ESP32/WebSocketSerial.h
+++ b/Marlin/src/HAL/ESP32/WebSocketSerial.h
@@ -22,6 +22,7 @@
#pragma once
#include "../../inc/MarlinConfig.h"
+#include "../../core/serial_hook.h"
#include
@@ -53,7 +54,7 @@ class RingBuffer {
ring_buffer_pos_t read(uint8_t *buffer);
void flush();
ring_buffer_pos_t write(const uint8_t c);
- ring_buffer_pos_t write(const uint8_t* buffer, ring_buffer_pos_t size);
+ ring_buffer_pos_t write(const uint8_t *buffer, ring_buffer_pos_t size);
};
class WebSocketSerial: public Stream {
@@ -68,11 +69,8 @@ class WebSocketSerial: public Stream {
int peek();
int read();
void flush();
- void flushTX();
size_t write(const uint8_t c);
- size_t write(const uint8_t* buffer, size_t size);
-
- operator bool() { return true; }
+ size_t write(const uint8_t *buffer, size_t size);
#if ENABLED(SERIAL_STATS_DROPPED_RX)
FORCE_INLINE uint32_t dropped() { return 0; }
@@ -83,4 +81,5 @@ class WebSocketSerial: public Stream {
#endif
};
-extern WebSocketSerial webSocketSerial;
+typedef Serial1Class MSerialWebSocketT;
+extern MSerialWebSocketT webSocketSerial;
diff --git a/Marlin/src/HAL/ESP32/eeprom.cpp b/Marlin/src/HAL/ESP32/eeprom.cpp
index 1bf687c6fe09..cb5f881284ec 100644
--- a/Marlin/src/HAL/ESP32/eeprom.cpp
+++ b/Marlin/src/HAL/ESP32/eeprom.cpp
@@ -44,7 +44,7 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui
return false;
}
-bool PersistentStore::read_data(int &pos, uint8_t* value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
+bool PersistentStore::read_data(int &pos, uint8_t *value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
for (size_t i = 0; i < size; i++) {
uint8_t c = EEPROM.read(pos++);
if (writing) value[i] = c;
diff --git a/Marlin/src/HAL/ESP32/endstop_interrupts.h b/Marlin/src/HAL/ESP32/endstop_interrupts.h
index 743ccd99c904..05368646101e 100644
--- a/Marlin/src/HAL/ESP32/endstop_interrupts.h
+++ b/Marlin/src/HAL/ESP32/endstop_interrupts.h
@@ -59,4 +59,16 @@ void setup_endstop_interrupts() {
TERN_(HAS_Z4_MAX, _ATTACH(Z4_MAX_PIN));
TERN_(HAS_Z4_MIN, _ATTACH(Z4_MIN_PIN));
TERN_(HAS_Z_MIN_PROBE_PIN, _ATTACH(Z_MIN_PROBE_PIN));
+ TERN_(HAS_I_MAX, _ATTACH(I_MAX_PIN));
+ TERN_(HAS_I_MIN, _ATTACH(I_MIN_PIN));
+ TERN_(HAS_J_MAX, _ATTACH(J_MAX_PIN));
+ TERN_(HAS_J_MIN, _ATTACH(J_MIN_PIN));
+ TERN_(HAS_K_MAX, _ATTACH(K_MAX_PIN));
+ TERN_(HAS_K_MIN, _ATTACH(K_MIN_PIN));
+ TERN_(HAS_U_MAX, _ATTACH(U_MAX_PIN));
+ TERN_(HAS_U_MIN, _ATTACH(U_MIN_PIN));
+ TERN_(HAS_V_MAX, _ATTACH(V_MAX_PIN));
+ TERN_(HAS_V_MIN, _ATTACH(V_MIN_PIN));
+ TERN_(HAS_W_MAX, _ATTACH(W_MAX_PIN));
+ TERN_(HAS_W_MIN, _ATTACH(W_MIN_PIN));
}
diff --git a/Marlin/src/HAL/ESP32/esp32.csv b/Marlin/src/HAL/ESP32/esp32.csv
new file mode 100644
index 000000000000..8f6e101f02ea
--- /dev/null
+++ b/Marlin/src/HAL/ESP32/esp32.csv
@@ -0,0 +1,6 @@
+# Name, Type, SubType, Offset, Size, Flags
+nvs, data, nvs, 0x9000, 0x5000,
+otadata, data, ota, 0xe000, 0x2000,
+app0, app, ota_0, 0x10000, 0x180000,
+app1, app, ota_1, 0x190000, 0x180000,
+spiffs, data, spiffs, 0x310000, 0xF0000,
diff --git a/Marlin/src/HAL/ESP32/fastio.h b/Marlin/src/HAL/ESP32/fastio.h
index 2ded3a5f62e8..c8e3f7e343e9 100644
--- a/Marlin/src/HAL/ESP32/fastio.h
+++ b/Marlin/src/HAL/ESP32/fastio.h
@@ -40,18 +40,27 @@
// Set pin as input with pullup mode
#define _PULLUP(IO, v) pinMode(IO, v ? INPUT_PULLUP : INPUT)
-// Read a pin wrapper
-#define READ(IO) (IS_I2S_EXPANDER_PIN(IO) ? i2s_state(I2S_EXPANDER_PIN_INDEX(IO)) : digitalRead(IO))
-
-// Write to a pin wrapper
-#define WRITE(IO, v) (IS_I2S_EXPANDER_PIN(IO) ? i2s_write(I2S_EXPANDER_PIN_INDEX(IO), v) : digitalWrite(IO, v))
-
-// Set pin as input wrapper
+#if ENABLED(USE_ESP32_EXIO)
+ // Read a pin wrapper
+ #define READ(IO) digitalRead(IO)
+ // Write to a pin wrapper
+ #define WRITE(IO, v) (IO >= 100 ? Write_EXIO(IO, v) : digitalWrite(IO, v))
+#else
+ // Read a pin wrapper
+ #define READ(IO) (IS_I2S_EXPANDER_PIN(IO) ? i2s_state(I2S_EXPANDER_PIN_INDEX(IO)) : digitalRead(IO))
+ // Write to a pin wrapper
+ #define WRITE(IO, v) (IS_I2S_EXPANDER_PIN(IO) ? i2s_write(I2S_EXPANDER_PIN_INDEX(IO), v) : digitalWrite(IO, v))
+#endif
+
+// Set pin as input wrapper (0x80 | (v << 5) | (IO - 100))
#define SET_INPUT(IO) _SET_INPUT(IO)
// Set pin as input with pullup wrapper
#define SET_INPUT_PULLUP(IO) do{ _SET_INPUT(IO); _PULLUP(IO, HIGH); }while(0)
+// Set pin as input with pulldown (substitution)
+#define SET_INPUT_PULLDOWN SET_INPUT
+
// Set pin as output wrapper
#define SET_OUTPUT(IO) do{ _SET_OUTPUT(IO); }while(0)
diff --git a/Marlin/src/HAL/ESP32/i2s.cpp b/Marlin/src/HAL/ESP32/i2s.cpp
index e8f380654314..d9bad4ec2d12 100644
--- a/Marlin/src/HAL/ESP32/i2s.cpp
+++ b/Marlin/src/HAL/ESP32/i2s.cpp
@@ -23,6 +23,8 @@
#include "../../inc/MarlinConfigPre.h"
+#if DISABLED(USE_ESP32_EXIO)
+
#include "i2s.h"
#include "../shared/Marduino.h"
@@ -62,12 +64,9 @@ uint32_t i2s_port_data = 0;
#define I2S_EXIT_CRITICAL() portEXIT_CRITICAL(&i2s_spinlock[i2s_num])
static inline void gpio_matrix_out_check(uint32_t gpio, uint32_t signal_idx, bool out_inv, bool oen_inv) {
- //if pin = -1, do not need to configure
- if (gpio != -1) {
- PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio], PIN_FUNC_GPIO);
- gpio_set_direction((gpio_num_t)gpio, (gpio_mode_t)GPIO_MODE_DEF_OUTPUT);
- gpio_matrix_out(gpio, signal_idx, out_inv, oen_inv);
- }
+ PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio], PIN_FUNC_GPIO);
+ gpio_set_direction((gpio_num_t)gpio, (gpio_mode_t)GPIO_MODE_DEF_OUTPUT);
+ gpio_matrix_out(gpio, signal_idx, out_inv, oen_inv);
}
static esp_err_t i2s_reset_fifo(i2s_port_t i2s_num) {
@@ -139,23 +138,41 @@ static void IRAM_ATTR i2s_intr_handler_default(void *arg) {
I2S0.int_clr.val = I2S0.int_st.val; //clear pending interrupt
}
-void stepperTask(void* parameter) {
- uint32_t remaining = 0;
+void stepperTask(void *parameter) {
+ uint32_t nextMainISR = 0;
+ #if ENABLED(LIN_ADVANCE)
+ uint32_t nextAdvanceISR = Stepper::LA_ADV_NEVER;
+ #endif
- while (1) {
+ for (;;) {
xQueueReceive(dma.queue, &dma.current, portMAX_DELAY);
dma.rw_pos = 0;
while (dma.rw_pos < DMA_SAMPLE_COUNT) {
// Fill with the port data post pulse_phase until the next step
- if (remaining) {
+ if (nextMainISR && TERN1(LIN_ADVANCE, nextAdvanceISR))
i2s_push_sample();
- remaining--;
- }
- else {
+
+ // i2s_push_sample() is also called from Stepper::pulse_phase_isr() and Stepper::advance_isr()
+ // in a rare case where both are called, we need to double decrement the counters
+ const uint8_t push_count = 1 + (!nextMainISR && TERN0(LIN_ADVANCE, !nextAdvanceISR));
+
+ #if ENABLED(LIN_ADVANCE)
+ if (!nextAdvanceISR) {
+ Stepper::advance_isr();
+ nextAdvanceISR = Stepper::la_interval;
+ }
+ else if (nextAdvanceISR == Stepper::LA_ADV_NEVER)
+ nextAdvanceISR = Stepper::la_interval;
+ #endif
+
+ if (!nextMainISR) {
Stepper::pulse_phase_isr();
- remaining = Stepper::block_phase_isr();
+ nextMainISR = Stepper::block_phase_isr();
}
+
+ nextMainISR -= push_count;
+ TERN_(LIN_ADVANCE, nextAdvanceISR -= push_count);
}
}
}
@@ -254,13 +271,7 @@ int i2s_init() {
I2S0.fifo_conf.dscr_en = 0;
- I2S0.conf_chan.tx_chan_mod = (
- #if ENABLED(I2S_STEPPER_SPLIT_STREAM)
- 4
- #else
- 0
- #endif
- );
+ I2S0.conf_chan.tx_chan_mod = TERN(I2S_STEPPER_SPLIT_STREAM, 4, 0);
I2S0.fifo_conf.tx_fifo_mod = 0;
I2S0.conf.tx_mono = 0;
@@ -311,9 +322,16 @@ int i2s_init() {
xTaskCreatePinnedToCore(stepperTask, "StepperTask", 10000, nullptr, 1, nullptr, CONFIG_ARDUINO_RUNNING_CORE); // run I2S stepper task on same core as rest of Marlin
// Route the i2s pins to the appropriate GPIO
- gpio_matrix_out_check(I2S_DATA, I2S0O_DATA_OUT23_IDX, 0, 0);
- gpio_matrix_out_check(I2S_BCK, I2S0O_BCK_OUT_IDX, 0, 0);
- gpio_matrix_out_check(I2S_WS, I2S0O_WS_OUT_IDX, 0, 0);
+ // If a pin is not defined, no need to configure
+ #if defined(I2S_DATA) && I2S_DATA >= 0
+ gpio_matrix_out_check(I2S_DATA, I2S0O_DATA_OUT23_IDX, 0, 0);
+ #endif
+ #if defined(I2S_BCK) && I2S_BCK >= 0
+ gpio_matrix_out_check(I2S_BCK, I2S0O_BCK_OUT_IDX, 0, 0);
+ #endif
+ #if defined(I2S_WS) && I2S_WS >= 0
+ gpio_matrix_out_check(I2S_WS, I2S0O_WS_OUT_IDX, 0, 0);
+ #endif
// Start the I2S peripheral
return i2s_start(I2S_NUM_0);
@@ -337,7 +355,28 @@ uint8_t i2s_state(uint8_t pin) {
}
void i2s_push_sample() {
+ // Every 4µs (when space in DMA buffer) toggle each expander PWM output using
+ // the current duty cycle/frequency so they sync with any steps (once
+ // through the DMA/FIFO buffers). PWM signal inversion handled by other functions
+ LOOP_L_N(p, MAX_EXPANDER_BITS) {
+ if (hal.pwm_pin_data[p].pwm_duty_ticks > 0) { // pin has active pwm?
+ if (hal.pwm_pin_data[p].pwm_tick_count == 0) {
+ if (TEST32(i2s_port_data, p)) { // hi->lo
+ CBI32(i2s_port_data, p);
+ hal.pwm_pin_data[p].pwm_tick_count = hal.pwm_pin_data[p].pwm_cycle_ticks - hal.pwm_pin_data[p].pwm_duty_ticks;
+ }
+ else { // lo->hi
+ SBI32(i2s_port_data, p);
+ hal.pwm_pin_data[p].pwm_tick_count = hal.pwm_pin_data[p].pwm_duty_ticks;
+ }
+ }
+ else
+ hal.pwm_pin_data[p].pwm_tick_count--;
+ }
+ }
+
dma.current[dma.rw_pos++] = i2s_port_data;
}
+#endif // !USE_ESP32_EXIO
#endif // ARDUINO_ARCH_ESP32
diff --git a/Marlin/src/HAL/ESP32/inc/Conditionals_adv.h b/Marlin/src/HAL/ESP32/inc/Conditionals_adv.h
index 5f1c4b16019d..3ca806897a89 100644
--- a/Marlin/src/HAL/ESP32/inc/Conditionals_adv.h
+++ b/Marlin/src/HAL/ESP32/inc/Conditionals_adv.h
@@ -20,3 +20,10 @@
*
*/
#pragma once
+
+//
+// Board-specific options need to be defined before HAL.h
+//
+#if MB(MKS_TINYBEE)
+ #define MAX_EXPANDER_BITS 24 // TinyBee has 3 x HC595
+#endif
diff --git a/Marlin/src/HAL/ESP32/inc/SanityCheck.h b/Marlin/src/HAL/ESP32/inc/SanityCheck.h
index f57a6c591028..a09b108f013a 100644
--- a/Marlin/src/HAL/ESP32/inc/SanityCheck.h
+++ b/Marlin/src/HAL/ESP32/inc/SanityCheck.h
@@ -25,14 +25,30 @@
#error "EMERGENCY_PARSER is not yet implemented for ESP32. Disable EMERGENCY_PARSER to continue."
#endif
-#if ENABLED(FAST_PWM_FAN) || SPINDLE_LASER_FREQUENCY
- #error "Features requiring Hardware PWM (FAST_PWM_FAN, SPINDLE_LASER_FREQUENCY) are not yet supported on ESP32."
+#if (ENABLED(SPINDLE_LASER_USE_PWM) && SPINDLE_LASER_FREQUENCY > 78125) || (ENABLED(FAST_PWM_FAN_FREQUENCY) && FAST_PWM_FAN_FREQUENCY > 78125)
+ #error "SPINDLE_LASER_FREQUENCY and FAST_PWM_FREQUENCY maximum value is 78125Hz for ESP32."
#endif
#if HAS_TMC_SW_SERIAL
- #error "TMC220x Software Serial is not supported on this platform."
+ #error "TMC220x Software Serial is not supported on ESP32."
#endif
#if BOTH(WIFISUPPORT, ESP3D_WIFISUPPORT)
#error "Only enable one WiFi option, either WIFISUPPORT or ESP3D_WIFISUPPORT."
#endif
+
+#if ENABLED(POSTMORTEM_DEBUGGING)
+ #error "POSTMORTEM_DEBUGGING is not yet supported on ESP32."
+#endif
+
+#if MB(MKS_TINYBEE) && ENABLED(FAST_PWM_FAN)
+ #error "FAST_PWM_FAN is not available on TinyBee."
+#endif
+
+#if USING_PULLDOWNS
+ #error "PULLDOWN pin mode is not available on ESP32 boards."
+#endif
+
+#if BOTH(I2S_STEPPER_STREAM, LIN_ADVANCE) && DISABLED(EXPERIMENTAL_I2S_LA)
+ #error "I2S stream is currently incompatible with LIN_ADVANCE."
+#endif
diff --git a/Marlin/src/HAL/ESP32/spi_pins.h b/Marlin/src/HAL/ESP32/spi_pins.h
index 15f8f2ab6b07..58881f0ea7ec 100644
--- a/Marlin/src/HAL/ESP32/spi_pins.h
+++ b/Marlin/src/HAL/ESP32/spi_pins.h
@@ -2,6 +2,9 @@
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
@@ -18,7 +21,7 @@
*/
#pragma once
-#define SS_PIN SDSS
-#define SCK_PIN 18
-#define MISO_PIN 19
-#define MOSI_PIN 23
+#define SD_SS_PIN SDSS
+#define SD_SCK_PIN 18
+#define SD_MISO_PIN 19
+#define SD_MOSI_PIN 23
diff --git a/Marlin/src/HAL/ESP32/timers.cpp b/Marlin/src/HAL/ESP32/timers.cpp
index 3300aea8a89c..c37ad2430cb2 100644
--- a/Marlin/src/HAL/ESP32/timers.cpp
+++ b/Marlin/src/HAL/ESP32/timers.cpp
@@ -41,11 +41,11 @@
static timg_dev_t *TG[2] = {&TIMERG0, &TIMERG1};
-const tTimerConfig TimerConfig [NUM_HARDWARE_TIMERS] = {
+const tTimerConfig timer_config[NUM_HARDWARE_TIMERS] = {
{ TIMER_GROUP_0, TIMER_0, STEPPER_TIMER_PRESCALE, stepTC_Handler }, // 0 - Stepper
{ TIMER_GROUP_0, TIMER_1, TEMP_TIMER_PRESCALE, tempTC_Handler }, // 1 - Temperature
{ TIMER_GROUP_1, TIMER_0, PWM_TIMER_PRESCALE, pwmTC_Handler }, // 2 - PWM
- { TIMER_GROUP_1, TIMER_1, 1, nullptr }, // 3
+ { TIMER_GROUP_1, TIMER_1, TONE_TIMER_PRESCALE, toneTC_Handler }, // 3 - Tone
};
// ------------------------
@@ -53,7 +53,7 @@ const tTimerConfig TimerConfig [NUM_HARDWARE_TIMERS] = {
// ------------------------
void IRAM_ATTR timer_isr(void *para) {
- const tTimerConfig& timer = TimerConfig[(int)para];
+ const tTimerConfig& timer = timer_config[(int)para];
// Retrieve the interrupt status and the counter value
// from the timer that reported the interrupt
@@ -81,8 +81,8 @@ void IRAM_ATTR timer_isr(void *para) {
* @param timer_num timer number to initialize
* @param frequency frequency of the timer
*/
-void HAL_timer_start(const uint8_t timer_num, uint32_t frequency) {
- const tTimerConfig timer = TimerConfig[timer_num];
+void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
+ const tTimerConfig timer = timer_config[timer_num];
timer_config_t config;
config.divider = timer.divider;
@@ -115,7 +115,7 @@ void HAL_timer_start(const uint8_t timer_num, uint32_t frequency) {
* @param count threshold at which the interrupt is triggered
*/
void HAL_timer_set_compare(const uint8_t timer_num, hal_timer_t count) {
- const tTimerConfig timer = TimerConfig[timer_num];
+ const tTimerConfig timer = timer_config[timer_num];
timer_set_alarm_value(timer.group, timer.idx, count);
}
@@ -125,7 +125,7 @@ void HAL_timer_set_compare(const uint8_t timer_num, hal_timer_t count) {
* @return the timer current threshold for the alarm to be triggered
*/
hal_timer_t HAL_timer_get_compare(const uint8_t timer_num) {
- const tTimerConfig timer = TimerConfig[timer_num];
+ const tTimerConfig timer = timer_config[timer_num];
uint64_t alarm_value;
timer_get_alarm_value(timer.group, timer.idx, &alarm_value);
@@ -139,7 +139,7 @@ hal_timer_t HAL_timer_get_compare(const uint8_t timer_num) {
* @return the current counter of the alarm
*/
hal_timer_t HAL_timer_get_count(const uint8_t timer_num) {
- const tTimerConfig timer = TimerConfig[timer_num];
+ const tTimerConfig timer = timer_config[timer_num];
uint64_t counter_value;
timer_get_counter_value(timer.group, timer.idx, &counter_value);
return counter_value;
@@ -150,7 +150,7 @@ hal_timer_t HAL_timer_get_count(const uint8_t timer_num) {
* @param timer_num timer number to enable interrupts on
*/
void HAL_timer_enable_interrupt(const uint8_t timer_num) {
- //const tTimerConfig timer = TimerConfig[timer_num];
+ //const tTimerConfig timer = timer_config[timer_num];
//timer_enable_intr(timer.group, timer.idx);
}
@@ -159,12 +159,12 @@ void HAL_timer_enable_interrupt(const uint8_t timer_num) {
* @param timer_num timer number to disable interrupts on
*/
void HAL_timer_disable_interrupt(const uint8_t timer_num) {
- //const tTimerConfig timer = TimerConfig[timer_num];
+ //const tTimerConfig timer = timer_config[timer_num];
//timer_disable_intr(timer.group, timer.idx);
}
bool HAL_timer_interrupt_enabled(const uint8_t timer_num) {
- const tTimerConfig timer = TimerConfig[timer_num];
+ const tTimerConfig timer = timer_config[timer_num];
return TG[timer.group]->int_ena.val | BIT(timer_num);
}
diff --git a/Marlin/src/HAL/ESP32/timers.h b/Marlin/src/HAL/ESP32/timers.h
index 7d35186b1cda..aa4e1551f066 100644
--- a/Marlin/src/HAL/ESP32/timers.h
+++ b/Marlin/src/HAL/ESP32/timers.h
@@ -32,17 +32,20 @@
typedef uint64_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX 0xFFFFFFFFFFFFFFFFULL
-#ifndef STEP_TIMER_NUM
- #define STEP_TIMER_NUM 0 // Timer Index for Stepper
+#ifndef MF_TIMER_STEP
+ #define MF_TIMER_STEP 0 // Timer Index for Stepper
#endif
-#ifndef PULSE_TIMER_NUM
- #define PULSE_TIMER_NUM STEP_TIMER_NUM
+#ifndef MF_TIMER_PULSE
+ #define MF_TIMER_PULSE MF_TIMER_STEP
#endif
-#ifndef TEMP_TIMER_NUM
- #define TEMP_TIMER_NUM 1 // Timer Index for Temperature
+#ifndef MF_TIMER_TEMP
+ #define MF_TIMER_TEMP 1 // Timer Index for Temperature
#endif
-#ifndef PWM_TIMER_NUM
- #define PWM_TIMER_NUM 2 // index of timer to use for PWM outputs
+#ifndef MF_TIMER_PWM
+ #define MF_TIMER_PWM 2 // index of timer to use for PWM outputs
+#endif
+#ifndef MF_TIMER_TONE
+ #define MF_TIMER_TONE 3 // index of timer for beeper tones
#endif
#define HAL_TIMER_RATE APB_CLK_FREQ // frequency of timer peripherals
@@ -59,6 +62,8 @@ typedef uint64_t hal_timer_t;
#define STEP_TIMER_MIN_INTERVAL 8 // minimum time in µs between stepper interrupts
+#define TONE_TIMER_PRESCALE 1000 // Arbitrary value, no idea what i'm doing here
+
#define TEMP_TIMER_PRESCALE 1000 // prescaler for setting Temp timer, 72Khz
#define TEMP_TIMER_FREQUENCY 1000 // temperature interrupt frequency
@@ -74,12 +79,12 @@ typedef uint64_t hal_timer_t;
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
-#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(STEP_TIMER_NUM)
-#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(STEP_TIMER_NUM)
-#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(STEP_TIMER_NUM)
+#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP)
+#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_STEP)
+#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(MF_TIMER_STEP)
-#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(TEMP_TIMER_NUM)
-#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(TEMP_TIMER_NUM)
+#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_TEMP)
+#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_TEMP)
#ifndef HAL_TEMP_TIMER_ISR
#define HAL_TEMP_TIMER_ISR() extern "C" void tempTC_Handler()
@@ -90,10 +95,16 @@ typedef uint64_t hal_timer_t;
#ifndef HAL_PWM_TIMER_ISR
#define HAL_PWM_TIMER_ISR() extern "C" void pwmTC_Handler()
#endif
+#ifndef HAL_TONE_TIMER_ISR
+ #define HAL_TONE_TIMER_ISR() extern "C" void toneTC_Handler()
+#endif
-extern "C" void tempTC_Handler();
-extern "C" void stepTC_Handler();
-extern "C" void pwmTC_Handler();
+extern "C" {
+ void tempTC_Handler();
+ void stepTC_Handler();
+ void pwmTC_Handler();
+ void toneTC_Handler();
+}
// ------------------------
// Types
@@ -110,13 +121,13 @@ typedef struct {
// Public Variables
// ------------------------
-extern const tTimerConfig TimerConfig[];
+extern const tTimerConfig timer_config[];
// ------------------------
// Public functions
// ------------------------
-void HAL_timer_start (const uint8_t timer_num, uint32_t frequency);
+void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency);
void HAL_timer_set_compare(const uint8_t timer_num, const hal_timer_t count);
hal_timer_t HAL_timer_get_compare(const uint8_t timer_num);
hal_timer_t HAL_timer_get_count(const uint8_t timer_num);
@@ -125,5 +136,5 @@ void HAL_timer_enable_interrupt(const uint8_t timer_num);
void HAL_timer_disable_interrupt(const uint8_t timer_num);
bool HAL_timer_interrupt_enabled(const uint8_t timer_num);
-#define HAL_timer_isr_prologue(TIMER_NUM)
-#define HAL_timer_isr_epilogue(TIMER_NUM)
+#define HAL_timer_isr_prologue(T) NOOP
+#define HAL_timer_isr_epilogue(T) NOOP
diff --git a/Marlin/src/HAL/ESP32/u8g_esp32_spi.cpp b/Marlin/src/HAL/ESP32/u8g_esp32_spi.cpp
new file mode 100644
index 000000000000..a445035b2b43
--- /dev/null
+++ b/Marlin/src/HAL/ESP32/u8g_esp32_spi.cpp
@@ -0,0 +1,94 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * Copypaste of SAMD51 HAL developed by Giuliano Zaro (AKA GMagician)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#ifdef ARDUINO_ARCH_ESP32
+
+#include "../../inc/MarlinConfig.h"
+
+#if EITHER(MKS_MINI_12864, FYSETC_MINI_12864_2_1)
+
+#include
+#include "../shared/HAL_SPI.h"
+#include "HAL.h"
+#include "SPI.h"
+
+static SPISettings spiConfig;
+
+
+#ifndef LCD_SPI_SPEED
+ #ifdef SD_SPI_SPEED
+ #define LCD_SPI_SPEED SD_SPI_SPEED // Assume SPI speed shared with SD
+ #else
+ #define LCD_SPI_SPEED SPI_FULL_SPEED // Use full speed if SD speed is not supplied
+ #endif
+#endif
+
+uint8_t u8g_eps_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
+ static uint8_t msgInitCount = 2; // Ignore all messages until 2nd U8G_COM_MSG_INIT
+ if (msgInitCount) {
+ if (msg == U8G_COM_MSG_INIT) msgInitCount--;
+ if (msgInitCount) return -1;
+ }
+
+ switch (msg) {
+ case U8G_COM_MSG_STOP: break;
+
+ case U8G_COM_MSG_INIT:
+ OUT_WRITE(DOGLCD_CS, HIGH);
+ OUT_WRITE(DOGLCD_A0, HIGH);
+ OUT_WRITE(LCD_RESET_PIN, HIGH);
+ u8g_Delay(5);
+ spiBegin();
+ spiInit(LCD_SPI_SPEED);
+ break;
+
+ case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */
+ WRITE(DOGLCD_A0, arg_val ? HIGH : LOW);
+ break;
+
+ case U8G_COM_MSG_CHIP_SELECT: /* arg_val == 0 means HIGH level of U8G_PI_CS */
+ WRITE(DOGLCD_CS, arg_val ? LOW : HIGH);
+ break;
+
+ case U8G_COM_MSG_RESET:
+ WRITE(LCD_RESET_PIN, arg_val);
+ break;
+
+ case U8G_COM_MSG_WRITE_BYTE:
+ spiSend((uint8_t)arg_val);
+ break;
+
+ case U8G_COM_MSG_WRITE_SEQ:
+ uint8_t *ptr = (uint8_t*) arg_ptr;
+ while (arg_val > 0) {
+ spiSend(*ptr++);
+ arg_val--;
+ }
+ break;
+ }
+ return 1;
+}
+
+#endif // EITHER(MKS_MINI_12864, FYSETC_MINI_12864_2_1)
+
+#endif // ARDUINO_ARCH_ESP32
diff --git a/Marlin/src/HAL/ESP32/watchdog.cpp b/Marlin/src/HAL/ESP32/watchdog.cpp
deleted file mode 100644
index f6fcfa3182c4..000000000000
--- a/Marlin/src/HAL/ESP32/watchdog.cpp
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * Marlin 3D Printer Firmware
- * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
- *
- * Based on Sprinter and grbl.
- * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *
- */
-#ifdef ARDUINO_ARCH_ESP32
-
-#include "../../inc/MarlinConfig.h"
-
-#if ENABLED(USE_WATCHDOG)
-
-#include "watchdog.h"
-
-void watchdogSetup() {
- // do whatever. don't remove this function.
-}
-
-void watchdog_init() {
- // TODO
-}
-
-#endif // USE_WATCHDOG
-
-#endif // ARDUINO_ARCH_ESP32
diff --git a/Marlin/src/HAL/ESP32/watchdog.h b/Marlin/src/HAL/ESP32/watchdog.h
deleted file mode 100644
index b6c169e34742..000000000000
--- a/Marlin/src/HAL/ESP32/watchdog.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- * Marlin 3D Printer Firmware
- * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
- *
- * Based on Sprinter and grbl.
- * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *
- */
-#pragma once
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
- esp_err_t esp_task_wdt_reset();
-
-#ifdef __cplusplus
- }
-#endif
-
-// Initialize watchdog with a 4 second interrupt time
-void watchdog_init();
-
-// Reset watchdog.
-inline void HAL_watchdog_refresh() { esp_task_wdt_reset(); }
diff --git a/Marlin/src/HAL/ESP32/wifi.cpp b/Marlin/src/HAL/ESP32/wifi.cpp
index f4cf5a606a03..060f3bdb4874 100644
--- a/Marlin/src/HAL/ESP32/wifi.cpp
+++ b/Marlin/src/HAL/ESP32/wifi.cpp
@@ -59,7 +59,7 @@ void wifi_init() {
MDNS.addService("http", "tcp", 80);
- SERIAL_ECHOLNPAIR("Successfully connected to WiFi with SSID '" WIFI_SSID "', hostname: '" WIFI_HOSTNAME "', IP address: ", WiFi.localIP().toString().c_str());
+ SERIAL_ECHOLNPGM("Successfully connected to WiFi with SSID '" WIFI_SSID "', hostname: '" WIFI_HOSTNAME "', IP address: ", WiFi.localIP().toString().c_str());
}
#endif // WIFISUPPORT
diff --git a/Marlin/src/HAL/HAL.h b/Marlin/src/HAL/HAL.h
index 5eca2f7eacfe..518657801905 100644
--- a/Marlin/src/HAL/HAL.h
+++ b/Marlin/src/HAL/HAL.h
@@ -23,14 +23,13 @@
#include "platforms.h"
-#include HAL_PATH(.,HAL.h)
-
-#ifdef SERIAL_PORT_2
- #define NUM_SERIAL 2
-#else
- #define NUM_SERIAL 1
+#ifndef GCC_VERSION
+ #define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#endif
+#include HAL_PATH(.,HAL.h)
+extern MarlinHAL hal;
+
#define HAL_ADC_RANGE _BV(HAL_ADC_RESOLUTION)
#ifndef I2C_ADDRESS
@@ -46,7 +45,3 @@
#ifndef PGMSTR
#define PGMSTR(NAM,STR) const char NAM[] = STR
#endif
-
-inline void watchdog_refresh() {
- TERN_(USE_WATCHDOG, HAL_watchdog_refresh());
-}
diff --git a/Marlin/src/HAL/LINUX/HAL.cpp b/Marlin/src/HAL/LINUX/HAL.cpp
index d7d7c2d2b4f0..db43f42eaafd 100644
--- a/Marlin/src/HAL/LINUX/HAL.cpp
+++ b/Marlin/src/HAL/LINUX/HAL.cpp
@@ -24,58 +24,38 @@
#include "../../inc/MarlinConfig.h"
#include "../shared/Delay.h"
-HalSerial usb_serial;
+// ------------------------
+// Serial ports
+// ------------------------
+
+MSerialT usb_serial(TERN0(EMERGENCY_PARSER, true));
// U8glib required functions
-extern "C" void u8g_xMicroDelay(uint16_t val) {
- DELAY_US(val);
-}
-extern "C" void u8g_MicroDelay() {
- u8g_xMicroDelay(1);
-}
-extern "C" void u8g_10MicroDelay() {
- u8g_xMicroDelay(10);
-}
-extern "C" void u8g_Delay(uint16_t val) {
- delay(val);
+extern "C" {
+ void u8g_xMicroDelay(uint16_t val) { DELAY_US(val); }
+ void u8g_MicroDelay() { u8g_xMicroDelay(1); }
+ void u8g_10MicroDelay() { u8g_xMicroDelay(10); }
+ void u8g_Delay(uint16_t val) { delay(val); }
}
+
//************************//
// return free heap space
-int freeMemory() {
- return 0;
-}
+int freeMemory() { return 0; }
// ------------------------
// ADC
// ------------------------
-void HAL_adc_init() {
-
-}
+uint8_t MarlinHAL::active_ch = 0;
-void HAL_adc_enable_channel(const uint8_t ch) {
-
-}
-
-uint8_t active_ch = 0;
-void HAL_adc_start_conversion(const uint8_t ch) {
- active_ch = ch;
-}
-
-bool HAL_adc_finished() {
- return true;
-}
-
-uint16_t HAL_adc_get_result() {
- pin_t pin = analogInputToDigitalPin(active_ch);
+uint16_t MarlinHAL::adc_value() {
+ const pin_t pin = analogInputToDigitalPin(active_ch);
if (!VALID_PIN(pin)) return 0;
- uint16_t data = ((Gpio::get(pin) >> 2) & 0x3FF);
+ const uint16_t data = ((Gpio::get(pin) >> 2) & 0x3FF);
return data; // return 10bit value as Marlin expects
}
-void HAL_pwm_init() {
-
-}
+void MarlinHAL::reboot() { /* Reset the application state and GPIO */ }
#endif // __PLAT_LINUX__
diff --git a/Marlin/src/HAL/LINUX/HAL.h b/Marlin/src/HAL/LINUX/HAL.h
index 1c8dbfd4dcfe..22c3e521f086 100644
--- a/Marlin/src/HAL/LINUX/HAL.h
+++ b/Marlin/src/HAL/LINUX/HAL.h
@@ -21,25 +21,42 @@
*/
#pragma once
-#define CPU_32_BIT
+#include "../../inc/MarlinConfigPre.h"
-#define F_CPU 100000000UL
-#define SystemCoreClock F_CPU
#include
#include
#include
-
#undef min
#undef max
-
#include
-void _printf (const char *format, ...);
+#include "hardware/Clock.h"
+#include "../shared/Marduino.h"
+#include "../shared/math_32bit.h"
+#include "../shared/HAL_SPI.h"
+#include "fastio.h"
+#include "serial.h"
+
+// ------------------------
+// Defines
+// ------------------------
+
+#define CPU_32_BIT
+#define SHARED_SERVOS HAS_SERVOS // Use shared/servos.cpp
+
+#define F_CPU 100000000UL
+#define SystemCoreClock F_CPU
+
+#define DELAY_CYCLES(x) Clock::delayCycles(x)
+
+#define CPU_ST7920_DELAY_1 600
+#define CPU_ST7920_DELAY_2 750
+#define CPU_ST7920_DELAY_3 750
+
+void _printf(const char *format, ...);
void _putc(uint8_t c);
uint8_t _getc();
-//extern "C" volatile uint32_t _millis;
-
//arduino: Print.h
#define DEC 10
#define HEX 16
@@ -49,66 +66,100 @@ uint8_t _getc();
#define B01 1
#define B10 2
-#include "hardware/Clock.h"
-
-#include "../shared/Marduino.h"
-#include "../shared/math_32bit.h"
-#include "../shared/HAL_SPI.h"
-#include "fastio.h"
-#include "watchdog.h"
-#include "serial.h"
-
-#define SHARED_SERVOS HAS_SERVOS
-
-extern HalSerial usb_serial;
-#define MYSERIAL0 usb_serial
+// ------------------------
+// Serial ports
+// ------------------------
-#define ST7920_DELAY_1 DELAY_NS(600)
-#define ST7920_DELAY_2 DELAY_NS(750)
-#define ST7920_DELAY_3 DELAY_NS(750)
+extern MSerialT usb_serial;
+#define MYSERIAL1 usb_serial
//
// Interrupts
//
#define CRITICAL_SECTION_START()
#define CRITICAL_SECTION_END()
-#define ISRS_ENABLED()
-#define ENABLE_ISRS()
-#define DISABLE_ISRS()
-inline void HAL_init() {}
+// ADC
+#define HAL_ADC_VREF 5.0
+#define HAL_ADC_RESOLUTION 10
+
+// ------------------------
+// Class Utilities
+// ------------------------
-// Utility functions
#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-function"
+#if GCC_VERSION <= 50000
+ #pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+
int freeMemory();
+
#pragma GCC diagnostic pop
-// ADC
-#define HAL_ADC_VREF 5.0
-#define HAL_ADC_RESOLUTION 10
-#define HAL_ANALOG_SELECT(ch) HAL_adc_enable_channel(ch)
-#define HAL_START_ADC(ch) HAL_adc_start_conversion(ch)
-#define HAL_READ_ADC() HAL_adc_get_result()
-#define HAL_ADC_READY() true
-
-void HAL_adc_init();
-void HAL_adc_enable_channel(const uint8_t ch);
-void HAL_adc_start_conversion(const uint8_t ch);
-uint16_t HAL_adc_get_result();
-
-// Reset source
-inline void HAL_clear_reset_source(void) {}
-inline uint8_t HAL_get_reset_source(void) { return RST_POWER_ON; }
-
-inline void HAL_reboot() {} // reboot the board or restart the bootloader
-
-/* ---------------- Delay in cycles */
-FORCE_INLINE static void DELAY_CYCLES(uint64_t x) {
- Clock::delayCycles(x);
-}
-
-// Add strcmp_P if missing
-#ifndef strcmp_P
- #define strcmp_P(a, b) strcmp((a), (b))
-#endif
+// ------------------------
+// MarlinHAL Class
+// ------------------------
+
+class MarlinHAL {
+public:
+
+ // Earliest possible init, before setup()
+ MarlinHAL() {}
+
+ // Watchdog
+ static void watchdog_init() {}
+ static void watchdog_refresh() {}
+
+ static void init() {} // Called early in setup()
+ static void init_board() {} // Called less early in setup()
+ static void reboot(); // Reset the application state and GPIO
+
+ // Interrupts
+ static bool isr_state() { return true; }
+ static void isr_on() {}
+ static void isr_off() {}
+
+ static void delay_ms(const int ms) { _delay_ms(ms); }
+
+ // Tasks, called from idle()
+ static void idletask() {}
+
+ // Reset
+ static constexpr uint8_t reset_reason = RST_POWER_ON;
+ static uint8_t get_reset_source() { return reset_reason; }
+ static void clear_reset_source() {}
+
+ // Free SRAM
+ static int freeMemory() { return ::freeMemory(); }
+
+ //
+ // ADC Methods
+ //
+
+ static uint8_t active_ch;
+
+ // Called by Temperature::init once at startup
+ static void adc_init() {}
+
+ // Called by Temperature::init for each sensor at startup
+ static void adc_enable(const uint8_t) {}
+
+ // Begin ADC sampling on the given channel
+ static void adc_start(const uint8_t ch) { active_ch = ch; }
+
+ // Is the ADC ready for reading?
+ static bool adc_ready() { return true; }
+
+ // The current value of the ADC register
+ static uint16_t adc_value();
+
+ /**
+ * Set the PWM duty cycle for the pin to the given value.
+ * No option to change the resolution or invert the duty cycle.
+ */
+ static void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t=255, const bool=false) {
+ analogWrite(pin, v);
+ }
+
+ static void set_pwm_frequency(const pin_t, int) {}
+};
diff --git a/Marlin/src/HAL/LINUX/MarlinSPI.h b/Marlin/src/HAL/LINUX/MarlinSPI.h
new file mode 100644
index 000000000000..0c447ba4cb3d
--- /dev/null
+++ b/Marlin/src/HAL/LINUX/MarlinSPI.h
@@ -0,0 +1,26 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#pragma once
+
+#include
+
+using MarlinSPI = SPIClass;
diff --git a/Marlin/src/HAL/LINUX/arduino.cpp b/Marlin/src/HAL/LINUX/arduino.cpp
index 4b56d02a389c..075b4ccde2f4 100644
--- a/Marlin/src/HAL/LINUX/arduino.cpp
+++ b/Marlin/src/HAL/LINUX/arduino.cpp
@@ -31,9 +31,7 @@ void cli() { } // Disable
void sei() { } // Enable
// Time functions
-void _delay_ms(const int delay_ms) {
- delay(delay_ms);
-}
+void _delay_ms(const int ms) { delay(ms); }
uint32_t millis() {
return (uint32_t)Clock::millis();
diff --git a/Marlin/src/HAL/LINUX/eeprom.cpp b/Marlin/src/HAL/LINUX/eeprom.cpp
index 68fff9c433b6..f878bba6a51b 100644
--- a/Marlin/src/HAL/LINUX/eeprom.cpp
+++ b/Marlin/src/HAL/LINUX/eeprom.cpp
@@ -69,34 +69,34 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui
std::size_t bytes_written = 0;
for (std::size_t i = 0; i < size; i++) {
- buffer[pos+i] = value[i];
- bytes_written ++;
+ buffer[pos + i] = value[i];
+ bytes_written++;
}
crc16(crc, value, size);
- pos = pos + size;
+ pos += size;
return (bytes_written != size); // return true for any error
}
-bool PersistentStore::read_data(int &pos, uint8_t* value, const size_t size, uint16_t *crc, const bool writing/*=true*/) {
+bool PersistentStore::read_data(int &pos, uint8_t *value, const size_t size, uint16_t *crc, const bool writing/*=true*/) {
std::size_t bytes_read = 0;
if (writing) {
for (std::size_t i = 0; i < size; i++) {
- value[i] = buffer[pos+i];
- bytes_read ++;
+ value[i] = buffer[pos + i];
+ bytes_read++;
}
crc16(crc, value, size);
}
else {
uint8_t temp[size];
for (std::size_t i = 0; i < size; i++) {
- temp[i] = buffer[pos+i];
- bytes_read ++;
+ temp[i] = buffer[pos + i];
+ bytes_read++;
}
crc16(crc, temp, size);
}
- pos = pos + size;
+ pos += size;
return bytes_read != size; // return true for any error
}
diff --git a/Marlin/src/HAL/LINUX/hardware/Gpio.h b/Marlin/src/HAL/LINUX/hardware/Gpio.h
index 2d9b1f29ebad..f946be648466 100644
--- a/Marlin/src/HAL/LINUX/hardware/Gpio.h
+++ b/Marlin/src/HAL/LINUX/hardware/Gpio.h
@@ -40,7 +40,7 @@ struct GpioEvent {
pin_type pin_id;
GpioEvent::Type event;
- GpioEvent(uint64_t timestamp, pin_type pin_id, GpioEvent::Type event){
+ GpioEvent(uint64_t timestamp, pin_type pin_id, GpioEvent::Type event) {
this->timestamp = timestamp;
this->pin_id = pin_id;
this->event = event;
diff --git a/Marlin/src/HAL/LINUX/hardware/Heater.cpp b/Marlin/src/HAL/LINUX/hardware/Heater.cpp
index 70df8161829a..44f11986c98b 100644
--- a/Marlin/src/HAL/LINUX/hardware/Heater.cpp
+++ b/Marlin/src/HAL/LINUX/hardware/Heater.cpp
@@ -54,7 +54,7 @@ void Heater::update() {
}
void Heater::interrupt(GpioEvent ev) {
- // ununsed
+ // unused
}
#endif // __PLAT_LINUX__
diff --git a/Marlin/src/HAL/LINUX/hardware/Heater.h b/Marlin/src/HAL/LINUX/hardware/Heater.h
index b17078d0b739..6d590ce6c55e 100644
--- a/Marlin/src/HAL/LINUX/hardware/Heater.h
+++ b/Marlin/src/HAL/LINUX/hardware/Heater.h
@@ -26,8 +26,8 @@
struct LowpassFilter {
uint64_t data_delay = 0;
uint16_t update(uint16_t value) {
- data_delay = data_delay - (data_delay >> 6) + value;
- return (uint16_t)(data_delay >> 6);
+ data_delay += value - (data_delay >> 6);
+ return uint16_t(data_delay >> 6);
}
};
diff --git a/Marlin/src/HAL/LINUX/hardware/LinearAxis.cpp b/Marlin/src/HAL/LINUX/hardware/LinearAxis.cpp
index c5b3ccc98656..e122ef3666c5 100644
--- a/Marlin/src/HAL/LINUX/hardware/LinearAxis.cpp
+++ b/Marlin/src/HAL/LINUX/hardware/LinearAxis.cpp
@@ -51,7 +51,7 @@ void LinearAxis::update() {
}
void LinearAxis::interrupt(GpioEvent ev) {
- if (ev.pin_id == step_pin && !Gpio::pin_map[enable_pin].value){
+ if (ev.pin_id == step_pin && !Gpio::pin_map[enable_pin].value) {
if (ev.event == GpioEvent::RISE) {
last_update = ev.timestamp;
position += -1 + 2 * Gpio::pin_map[dir_pin].value;
diff --git a/Marlin/src/HAL/LINUX/hardware/Timer.h b/Marlin/src/HAL/LINUX/hardware/Timer.h
index 757efdcdbd7e..1b3b800dca3d 100644
--- a/Marlin/src/HAL/LINUX/hardware/Timer.h
+++ b/Marlin/src/HAL/LINUX/hardware/Timer.h
@@ -52,7 +52,7 @@ class Timer {
return (*(intptr_t*)timerid);
}
- static void handler(int sig, siginfo_t *si, void *uc){
+ static void handler(int sig, siginfo_t *si, void *uc) {
Timer* _this = (Timer*)si->si_value.sival_ptr;
_this->avg_error += (Clock::nanos() - _this->start_time) - _this->period; //high_resolution_clock is also limited in precision, but best we have
_this->avg_error /= 2; //very crude precision analysis (actually within +-500ns usually)
diff --git a/Marlin/src/HAL/LINUX/inc/SanityCheck.h b/Marlin/src/HAL/LINUX/inc/SanityCheck.h
index 84167c97a144..36d3190a3e08 100644
--- a/Marlin/src/HAL/LINUX/inc/SanityCheck.h
+++ b/Marlin/src/HAL/LINUX/inc/SanityCheck.h
@@ -26,7 +26,7 @@
*/
// Emulating RAMPS
-#if ENABLED(SPINDLE_LASER_PWM) && !(SPINDLE_LASER_PWM_PIN == 4 || SPINDLE_LASER_PWM_PIN == 6 || SPINDLE_LASER_PWM_PIN == 11)
+#if ENABLED(SPINDLE_LASER_USE_PWM) && !(SPINDLE_LASER_PWM_PIN == 4 || SPINDLE_LASER_PWM_PIN == 6 || SPINDLE_LASER_PWM_PIN == 11)
#error "SPINDLE_LASER_PWM_PIN must use SERVO0, SERVO1 or SERVO3 connector"
#endif
@@ -35,5 +35,9 @@
#endif
#if HAS_TMC_SW_SERIAL
- #error "TMC220x Software Serial is not supported on this platform."
+ #error "TMC220x Software Serial is not supported on LINUX."
+#endif
+
+#if ENABLED(POSTMORTEM_DEBUGGING)
+ #error "POSTMORTEM_DEBUGGING is not yet supported on LINUX."
#endif
diff --git a/Marlin/src/HAL/LINUX/include/Arduino.h b/Marlin/src/HAL/LINUX/include/Arduino.h
index e28b474ede96..f05aaed88083 100644
--- a/Marlin/src/HAL/LINUX/include/Arduino.h
+++ b/Marlin/src/HAL/LINUX/include/Arduino.h
@@ -59,43 +59,22 @@ typedef uint8_t byte;
#endif
#define sq(v) ((v) * (v))
-#define square(v) sq(v)
#define constrain(value, arg_min, arg_max) ((value) < (arg_min) ? (arg_min) :((value) > (arg_max) ? (arg_max) : (value)))
-//Interrupts
+// Interrupts
void cli(); // Disable
void sei(); // Enable
void attachInterrupt(uint32_t pin, void (*callback)(), uint32_t mode);
void detachInterrupt(uint32_t pin);
-extern "C" void GpioEnableInt(uint32_t port, uint32_t pin, uint32_t mode);
-extern "C" void GpioDisableInt(uint32_t port, uint32_t pin);
-
-// Program Memory
-#define pgm_read_ptr(addr) (*((void**)(addr)))
-#define pgm_read_byte_near(addr) (*((uint8_t*)(addr)))
-#define pgm_read_float_near(addr) (*((float*)(addr)))
-#define pgm_read_word_near(addr) (*((uint16_t*)(addr)))
-#define pgm_read_dword_near(addr) (*((uint32_t*)(addr)))
-#define pgm_read_byte(addr) pgm_read_byte_near(addr)
-#define pgm_read_float(addr) pgm_read_float_near(addr)
-#define pgm_read_word(addr) pgm_read_word_near(addr)
-#define pgm_read_dword(addr) pgm_read_dword_near(addr)
-
-using std::memcpy;
-#define memcpy_P memcpy
-#define sprintf_P sprintf
-#define strstr_P strstr
-#define strncpy_P strncpy
-#define vsnprintf_P vsnprintf
-#define strcpy_P strcpy
-#define snprintf_P snprintf
-#define strlen_P strlen
-// Time functions
extern "C" {
- void delay(const int milis);
+ void GpioEnableInt(uint32_t port, uint32_t pin, uint32_t mode);
+ void GpioDisableInt(uint32_t port, uint32_t pin);
}
-void _delay_ms(const int delay);
+
+// Time functions
+extern "C" void delay(const int ms);
+void _delay_ms(const int ms);
void delayMicroseconds(unsigned long);
uint32_t millis();
diff --git a/Marlin/src/HAL/LINUX/include/pinmapping.cpp b/Marlin/src/HAL/LINUX/include/pinmapping.cpp
index 870ab3a96e5f..5823668cd50d 100644
--- a/Marlin/src/HAL/LINUX/include/pinmapping.cpp
+++ b/Marlin/src/HAL/LINUX/include/pinmapping.cpp
@@ -25,43 +25,6 @@
#include "../../../gcode/parser.h"
-uint8_t analog_offset = NUM_DIGITAL_PINS - NUM_ANALOG_INPUTS;
-
-// Get the digital pin for an analog index
-pin_t analogInputToDigitalPin(const int8_t p) {
- return (WITHIN(p, 0, NUM_ANALOG_INPUTS) ? analog_offset + p : P_NC);
-}
-
-// Return the index of a pin number
-int16_t GET_PIN_MAP_INDEX(const pin_t pin) {
- return pin;
-}
-
-// Test whether the pin is valid
-bool VALID_PIN(const pin_t p) {
- return WITHIN(p, 0, NUM_DIGITAL_PINS);
-}
-
-// Get the analog index for a digital pin
-int8_t DIGITAL_PIN_TO_ANALOG_PIN(const pin_t p) {
- return (WITHIN(p, analog_offset, NUM_DIGITAL_PINS) ? p - analog_offset : P_NC);
-}
-
-// Test whether the pin is PWM
-bool PWM_PIN(const pin_t p) {
- return false;
-}
-
-// Test whether the pin is interruptable
-bool INTERRUPT_PIN(const pin_t p) {
- return false;
-}
-
-// Get the pin number at the given index
-pin_t GET_PIN_MAP_PIN(const int16_t ind) {
- return ind;
-}
-
int16_t PARSED_PIN_INDEX(const char code, const int16_t dval) {
return parser.intval(code, dval);
}
diff --git a/Marlin/src/HAL/LINUX/include/pinmapping.h b/Marlin/src/HAL/LINUX/include/pinmapping.h
index 98f4b812e873..cfac5e3b48e4 100644
--- a/Marlin/src/HAL/LINUX/include/pinmapping.h
+++ b/Marlin/src/HAL/LINUX/include/pinmapping.h
@@ -34,26 +34,32 @@ constexpr uint8_t NUM_ANALOG_INPUTS = 16;
#define HAL_SENSITIVE_PINS
+constexpr uint8_t analog_offset = NUM_DIGITAL_PINS - NUM_ANALOG_INPUTS;
+
// Get the digital pin for an analog index
-pin_t analogInputToDigitalPin(const int8_t p);
+constexpr pin_t analogInputToDigitalPin(const int8_t p) {
+ return (WITHIN(p, 0, NUM_ANALOG_INPUTS) ? analog_offset + p : P_NC);
+}
+
+// Get the analog index for a digital pin
+constexpr int8_t DIGITAL_PIN_TO_ANALOG_PIN(const pin_t p) {
+ return (WITHIN(p, analog_offset, NUM_DIGITAL_PINS) ? p - analog_offset : P_NC);
+}
// Return the index of a pin number
-int16_t GET_PIN_MAP_INDEX(const pin_t pin);
+constexpr int16_t GET_PIN_MAP_INDEX(const pin_t pin) { return pin; }
// Test whether the pin is valid
-bool VALID_PIN(const pin_t p);
-
-// Get the analog index for a digital pin
-int8_t DIGITAL_PIN_TO_ANALOG_PIN(const pin_t p);
+constexpr bool VALID_PIN(const pin_t p) { return WITHIN(p, 0, NUM_DIGITAL_PINS); }
// Test whether the pin is PWM
-bool PWM_PIN(const pin_t p);
+constexpr bool PWM_PIN(const pin_t p) { return false; }
-// Test whether the pin is interruptable
-bool INTERRUPT_PIN(const pin_t p);
+// Test whether the pin is interruptible
+constexpr bool INTERRUPT_PIN(const pin_t p) { return false; }
// Get the pin number at the given index
-pin_t GET_PIN_MAP_PIN(const int16_t ind);
+constexpr pin_t GET_PIN_MAP_PIN(const int16_t ind) { return ind; }
// Parse a G-code word into a pin index
int16_t PARSED_PIN_INDEX(const char code, const int16_t dval);
diff --git a/Marlin/src/HAL/LINUX/include/serial.h b/Marlin/src/HAL/LINUX/include/serial.h
index e91624938978..ebae066c3a57 100644
--- a/Marlin/src/HAL/LINUX/include/serial.h
+++ b/Marlin/src/HAL/LINUX/include/serial.h
@@ -25,6 +25,7 @@
#if ENABLED(EMERGENCY_PARSER)
#include "../../../feature/e_parser.h"
#endif
+#include "../../../core/serial_hook.h"
#include
#include
@@ -73,19 +74,11 @@ template class RingBuffer {
volatile uint32_t index_read;
};
-class HalSerial {
-public:
-
- #if ENABLED(EMERGENCY_PARSER)
- EmergencyParser::State emergency_state;
- static inline bool emergency_parser_enabled() { return true; }
- #endif
-
+struct HalSerial {
HalSerial() { host_connected = true; }
void begin(int32_t) {}
-
- void end() {}
+ void end() {}
int peek() {
uint8_t value;
@@ -100,7 +93,7 @@ class HalSerial {
return transmit_buffer.write(c);
}
- operator bool() { return host_connected; }
+ bool connected() { return host_connected; }
uint16_t available() {
return (uint16_t)receive_buffer.available();
@@ -117,92 +110,9 @@ class HalSerial {
while (transmit_buffer.available()) { /* nada */ }
}
- void printf(const char *format, ...) {
- static char buffer[256];
- va_list vArgs;
- va_start(vArgs, format);
- int length = vsnprintf((char *) buffer, 256, (char const *) format, vArgs);
- va_end(vArgs);
- if (length > 0 && length < 256) {
- if (host_connected) {
- for (int i = 0; i < length;) {
- if (transmit_buffer.write(buffer[i])) {
- ++i;
- }
- }
- }
- }
- }
-
- #define DEC 10
- #define HEX 16
- #define OCT 8
- #define BIN 2
-
- void print_bin(uint32_t value, uint8_t num_digits) {
- uint32_t mask = 1 << (num_digits -1);
- for (uint8_t i = 0; i < num_digits; i++) {
- if (!(i % 4) && i) write(' ');
- if (!(i % 16) && i) write(' ');
- if (value & mask) write('1');
- else write('0');
- value <<= 1;
- }
- }
-
- void print(const char value[]) { printf("%s" , value); }
- void print(char value, int nbase = 0) {
- if (nbase == BIN) print_bin(value, 8);
- else if (nbase == OCT) printf("%3o", value);
- else if (nbase == HEX) printf("%2X", value);
- else if (nbase == DEC ) printf("%d", value);
- else printf("%c" , value);
- }
- void print(unsigned char value, int nbase = 0) {
- if (nbase == BIN) print_bin(value, 8);
- else if (nbase == OCT) printf("%3o", value);
- else if (nbase == HEX) printf("%2X", value);
- else printf("%u" , value);
- }
- void print(int value, int nbase = 0) {
- if (nbase == BIN) print_bin(value, 16);
- else if (nbase == OCT) printf("%6o", value);
- else if (nbase == HEX) printf("%4X", value);
- else printf("%d", value);
- }
- void print(unsigned int value, int nbase = 0) {
- if (nbase == BIN) print_bin(value, 16);
- else if (nbase == OCT) printf("%6o", value);
- else if (nbase == HEX) printf("%4X", value);
- else printf("%u" , value);
- }
- void print(long value, int nbase = 0) {
- if (nbase == BIN) print_bin(value, 32);
- else if (nbase == OCT) printf("%11o", value);
- else if (nbase == HEX) printf("%8X", value);
- else printf("%ld" , value);
- }
- void print(unsigned long value, int nbase = 0) {
- if (nbase == BIN) print_bin(value, 32);
- else if (nbase == OCT) printf("%11o", value);
- else if (nbase == HEX) printf("%8X", value);
- else printf("%lu" , value);
- }
- void print(float value, int round = 6) { printf("%f" , value); }
- void print(double value, int round = 6) { printf("%f" , value); }
-
- void println(const char value[]) { printf("%s\n" , value); }
- void println(char value, int nbase = 0) { print(value, nbase); println(); }
- void println(unsigned char value, int nbase = 0) { print(value, nbase); println(); }
- void println(int value, int nbase = 0) { print(value, nbase); println(); }
- void println(unsigned int value, int nbase = 0) { print(value, nbase); println(); }
- void println(long value, int nbase = 0) { print(value, nbase); println(); }
- void println(unsigned long value, int nbase = 0) { print(value, nbase); println(); }
- void println(float value, int round = 6) { printf("%f\n" , value); }
- void println(double value, int round = 6) { printf("%f\n" , value); }
- void println() { print('\n'); }
-
volatile RingBuffer receive_buffer;
volatile RingBuffer transmit_buffer;
volatile bool host_connected;
};
+
+typedef Serial1Class MSerialT;
diff --git a/Marlin/src/HAL/LINUX/main.cpp b/Marlin/src/HAL/LINUX/main.cpp
index 481f059030b7..f2af2ff33f52 100644
--- a/Marlin/src/HAL/LINUX/main.cpp
+++ b/Marlin/src/HAL/LINUX/main.cpp
@@ -1,8 +1,10 @@
/**
* Marlin 3D Printer Firmware
- *
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
@@ -17,24 +19,26 @@
* along with this program. If not, see .
*
*/
-#ifdef __PLAT_LINUX__
-
-extern void setup();
-extern void loop();
-#include
+#ifdef __PLAT_LINUX__
-#include
-#include
+//#define GPIO_LOGGING // Full GPIO and Positional Logging
#include "../../inc/MarlinConfig.h"
-#include
-#include
#include "../shared/Delay.h"
#include "hardware/IOLoggerCSV.h"
#include "hardware/Heater.h"
#include "hardware/LinearAxis.h"
+#include
+#include
+#include
+#include
+#include
+
+extern void setup();
+extern void loop();
+
// simple stdout / stdin implementation for fake serial port
void write_serial_thread() {
for (;;) {
@@ -64,8 +68,6 @@ void simulation_loop() {
LinearAxis z_axis(Z_ENABLE_PIN, Z_DIR_PIN, Z_STEP_PIN, Z_MIN_PIN, Z_MAX_PIN);
LinearAxis extruder0(E0_ENABLE_PIN, E0_DIR_PIN, E0_STEP_PIN, P_NC, P_NC);
- //#define GPIO_LOGGING // Full GPIO and Positional Logging
-
#ifdef GPIO_LOGGING
IOLoggerCSV logger("all_gpio_log.csv");
Gpio::attachLogger(&logger);
@@ -88,7 +90,7 @@ void simulation_loop() {
#ifdef GPIO_LOGGING
if (x_axis.position != x || y_axis.position != y || z_axis.position != z) {
- uint64_t update = MAX3(x_axis.last_update, y_axis.last_update, z_axis.last_update);
+ uint64_t update = _MAX(x_axis.last_update, y_axis.last_update, z_axis.last_update);
position_log << update << ", " << x_axis.position << ", " << y_axis.position << ", " << z_axis.position << std::endl;
position_log.flush();
x = x_axis.position;
@@ -107,8 +109,8 @@ int main() {
std::thread write_serial (write_serial_thread);
std::thread read_serial (read_serial_thread);
- #ifdef MYSERIAL0
- MYSERIAL0.begin(BAUDRATE);
+ #ifdef MYSERIAL1
+ MYSERIAL1.begin(BAUDRATE);
SERIAL_ECHOLNPGM("x86_64 Initialized");
SERIAL_FLUSHTX();
#endif
diff --git a/Marlin/src/HAL/LINUX/pinsDebug.h b/Marlin/src/HAL/LINUX/pinsDebug.h
index 8f8543ef5984..7bfd97d024f7 100644
--- a/Marlin/src/HAL/LINUX/pinsDebug.h
+++ b/Marlin/src/HAL/LINUX/pinsDebug.h
@@ -2,6 +2,9 @@
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
@@ -34,6 +37,7 @@
#define GET_ARRAY_PIN(p) pin_array[p].pin
#define PRINT_ARRAY_NAME(x) do{ sprintf_P(buffer, PSTR("%-" STRINGIFY(MAX_NAME_LENGTH) "s"), pin_array[x].name); SERIAL_ECHO(buffer); }while(0)
#define PRINT_PIN(p) do{ sprintf_P(buffer, PSTR("%3d "), p); SERIAL_ECHO(buffer); }while(0)
+#define PRINT_PIN_ANALOG(p) do{ sprintf_P(buffer, PSTR(" (A%2d) "), DIGITAL_PIN_TO_ANALOG_PIN(pin)); SERIAL_ECHO(buffer); }while(0)
#define MULTI_NAME_PAD 16 // space needed to be pretty if not first name assigned to a pin
// active ADC function/mode/code values for PINSEL registers
diff --git a/Marlin/src/HAL/LINUX/spi_pins.h b/Marlin/src/HAL/LINUX/spi_pins.h
index 01ba28e5b604..33136ac9dd80 100644
--- a/Marlin/src/HAL/LINUX/spi_pins.h
+++ b/Marlin/src/HAL/LINUX/spi_pins.h
@@ -24,31 +24,32 @@
#include "../../core/macros.h"
#include "../../inc/MarlinConfigPre.h"
-#if BOTH(HAS_MARLINUI_U8GLIB, SDSUPPORT) && (LCD_PINS_D4 == SCK_PIN || LCD_PINS_ENABLE == MOSI_PIN || DOGLCD_SCK == SCK_PIN || DOGLCD_MOSI == MOSI_PIN)
+#if BOTH(HAS_MARLINUI_U8GLIB, SDSUPPORT) && (LCD_PINS_D4 == SD_SCK_PIN || LCD_PINS_ENABLE == SD_MOSI_PIN || DOGLCD_SCK == SD_SCK_PIN || DOGLCD_MOSI == SD_MOSI_PIN)
#define LPC_SOFTWARE_SPI // If the SD card and LCD adapter share the same SPI pins, then software SPI is currently
// needed due to the speed and mode required for communicating with each device being different.
// This requirement can be removed if the SPI access to these devices is updated to use
// spiBeginTransaction.
#endif
-/** onboard SD card */
-//#define SCK_PIN P0_07
-//#define MISO_PIN P0_08
-//#define MOSI_PIN P0_09
-//#define SS_PIN P0_06
-/** external */
-#ifndef SCK_PIN
- #define SCK_PIN 50
+// Onboard SD
+//#define SD_SCK_PIN P0_07
+//#define SD_MISO_PIN P0_08
+//#define SD_MOSI_PIN P0_09
+//#define SD_SS_PIN P0_06
+
+// External SD
+#ifndef SD_SCK_PIN
+ #define SD_SCK_PIN 50
#endif
-#ifndef MISO_PIN
- #define MISO_PIN 51
+#ifndef SD_MISO_PIN
+ #define SD_MISO_PIN 51
#endif
-#ifndef MOSI_PIN
- #define MOSI_PIN 52
+#ifndef SD_MOSI_PIN
+ #define SD_MOSI_PIN 52
#endif
-#ifndef SS_PIN
- #define SS_PIN 53
+#ifndef SD_SS_PIN
+ #define SD_SS_PIN 53
#endif
#ifndef SDSS
- #define SDSS SS_PIN
+ #define SDSS SD_SS_PIN
#endif
diff --git a/Marlin/src/HAL/LINUX/timers.h b/Marlin/src/HAL/LINUX/timers.h
index 1beaea95abc6..2d2a95774c1b 100644
--- a/Marlin/src/HAL/LINUX/timers.h
+++ b/Marlin/src/HAL/LINUX/timers.h
@@ -37,14 +37,14 @@ typedef uint32_t hal_timer_t;
#define HAL_TIMER_RATE ((SystemCoreClock) / 4) // frequency of timers peripherals
-#ifndef STEP_TIMER_NUM
- #define STEP_TIMER_NUM 0 // Timer Index for Stepper
+#ifndef MF_TIMER_STEP
+ #define MF_TIMER_STEP 0 // Timer Index for Stepper
#endif
-#ifndef PULSE_TIMER_NUM
- #define PULSE_TIMER_NUM STEP_TIMER_NUM
+#ifndef MF_TIMER_PULSE
+ #define MF_TIMER_PULSE MF_TIMER_STEP
#endif
-#ifndef TEMP_TIMER_NUM
- #define TEMP_TIMER_NUM 1 // Timer Index for Temperature
+#ifndef MF_TIMER_TEMP
+ #define MF_TIMER_TEMP 1 // Timer Index for Temperature
#endif
#define TEMP_TIMER_RATE 1000000
@@ -58,12 +58,12 @@ typedef uint32_t hal_timer_t;
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
-#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(STEP_TIMER_NUM)
-#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(STEP_TIMER_NUM)
-#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(STEP_TIMER_NUM)
+#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP)
+#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_STEP)
+#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(MF_TIMER_STEP)
-#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(TEMP_TIMER_NUM)
-#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(TEMP_TIMER_NUM)
+#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_TEMP)
+#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_TEMP)
#ifndef HAL_STEP_TIMER_ISR
#define HAL_STEP_TIMER_ISR() extern "C" void TIMER0_IRQHandler()
@@ -77,7 +77,6 @@ typedef uint32_t hal_timer_t;
#define HAL_PWM_TIMER_ISR() extern "C" void TIMER3_IRQHandler()
#define HAL_PWM_TIMER_IRQn
-
void HAL_timer_init();
void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency);
@@ -93,5 +92,5 @@ void HAL_timer_enable_interrupt(const uint8_t timer_num);
void HAL_timer_disable_interrupt(const uint8_t timer_num);
bool HAL_timer_interrupt_enabled(const uint8_t timer_num);
-#define HAL_timer_isr_prologue(TIMER_NUM)
-#define HAL_timer_isr_epilogue(TIMER_NUM)
+#define HAL_timer_isr_prologue(T) NOOP
+#define HAL_timer_isr_epilogue(T) NOOP
diff --git a/Marlin/src/HAL/LINUX/watchdog.cpp b/Marlin/src/HAL/LINUX/watchdog.cpp
deleted file mode 100644
index c15b0e311c56..000000000000
--- a/Marlin/src/HAL/LINUX/watchdog.cpp
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * Marlin 3D Printer Firmware
- * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
- *
- * Based on Sprinter and grbl.
- * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *
- */
-#ifdef __PLAT_LINUX__
-
-#include "../../inc/MarlinConfig.h"
-
-#if ENABLED(USE_WATCHDOG)
-
-#include "watchdog.h"
-
-void watchdog_init() {}
-void HAL_watchdog_refresh() {}
-
-#endif
-
-#endif // __PLAT_LINUX__
diff --git a/Marlin/src/HAL/LINUX/watchdog.h b/Marlin/src/HAL/LINUX/watchdog.h
deleted file mode 100644
index 472624cc7845..000000000000
--- a/Marlin/src/HAL/LINUX/watchdog.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/**
- * Marlin 3D Printer Firmware
- * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
- *
- * Based on Sprinter and grbl.
- * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *
- */
-#pragma once
-
-#define WDT_TIMEOUT 4000000 // 4 second timeout
-
-void watchdog_init();
-void HAL_watchdog_refresh();
diff --git a/Marlin/src/HAL/LPC1768/DebugMonitor.cpp b/Marlin/src/HAL/LPC1768/DebugMonitor.cpp
deleted file mode 100644
index 783b10cfac16..000000000000
--- a/Marlin/src/HAL/LPC1768/DebugMonitor.cpp
+++ /dev/null
@@ -1,322 +0,0 @@
-/**
- * Marlin 3D Printer Firmware
- * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
- *
- * Based on Sprinter and grbl.
- * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- *
- */
-#ifdef TARGET_LPC1768
-
-#include "../../core/macros.h"
-#include "../../core/serial.h"
-#include
-
-#include "../shared/backtrace/unwinder.h"
-#include "../shared/backtrace/unwmemaccess.h"
-#include "watchdog.h"
-#include
-
-
-// Debug monitor that dumps to the Programming port all status when
-// an exception or WDT timeout happens - And then resets the board
-
-// All the Monitor routines must run with interrupts disabled and
-// under an ISR execution context. That is why we cannot reuse the
-// Serial interrupt routines or any C runtime, as we don't know the
-// state we are when running them
-
-// A SW memory barrier, to ensure GCC does not overoptimize loops
-#define sw_barrier() __asm__ volatile("": : :"memory");
-
-// (re)initialize UART0 as a monitor output to 250000,n,8,1
-static void TXBegin() {
-}
-
-// Send character through UART with no interrupts
-static void TX(char c) {
- _DBC(c);
-}
-
-// Send String through UART
-static void TX(const char* s) {
- while (*s) TX(*s++);
-}
-
-static void TXDigit(uint32_t d) {
- if (d < 10) TX((char)(d+'0'));
- else if (d < 16) TX((char)(d+'A'-10));
- else TX('?');
-}
-
-// Send Hex number thru UART
-static void TXHex(uint32_t v) {
- TX("0x");
- for (uint8_t i = 0; i < 8; i++, v <<= 4)
- TXDigit((v >> 28) & 0xF);
-}
-
-// Send Decimal number thru UART
-static void TXDec(uint32_t v) {
- if (!v) {
- TX('0');
- return;
- }
-
- char nbrs[14];
- char *p = &nbrs[0];
- while (v != 0) {
- *p++ = '0' + (v % 10);
- v /= 10;
- }
- do {
- p--;
- TX(*p);
- } while (p != &nbrs[0]);
-}
-
-// Dump a backtrace entry
-static bool UnwReportOut(void* ctx, const UnwReport* bte) {
- int* p = (int*)ctx;
-
- (*p)++;
- TX('#'); TXDec(*p); TX(" : ");
- TX(bte->name?bte->name:"unknown"); TX('@'); TXHex(bte->function);
- TX('+'); TXDec(bte->address - bte->function);
- TX(" PC:");TXHex(bte->address); TX('\n');
- return true;
-}
-
-#ifdef UNW_DEBUG
- void UnwPrintf(const char* format, ...) {
- char dest[256];
- va_list argptr;
- va_start(argptr, format);
- vsprintf(dest, format, argptr);
- va_end(argptr);
- TX(&dest[0]);
- }
-#endif
-
-/* Table of function pointers for passing to the unwinder */
-static const UnwindCallbacks UnwCallbacks = {
- UnwReportOut,
- UnwReadW,
- UnwReadH,
- UnwReadB
- #ifdef UNW_DEBUG
- ,UnwPrintf
- #endif
-};
-
-
-/**
- * HardFaultHandler_C:
- * This is called from the HardFault_HandlerAsm with a pointer the Fault stack
- * as the parameter. We can then read the values from the stack and place them
- * into local variables for ease of reading.
- * We then read the various Fault Status and Address Registers to help decode
- * cause of the fault.
- * The function ends with a BKPT instruction to force control back into the debugger
- */
-extern "C"
-void HardFault_HandlerC(unsigned long *sp, unsigned long lr, unsigned long cause) {
-
- static const char* causestr[] = {
- "NMI","Hard","Mem","Bus","Usage","Debug","WDT","RSTC"
- };
-
- UnwindFrame btf;
-
- // Dump report to the Programming port (interrupts are DISABLED)
- TXBegin();
- TX("\n\n## Software Fault detected ##\n");
- TX("Cause: "); TX(causestr[cause]); TX('\n');
-
- TX("R0 : "); TXHex(((unsigned long)sp[0])); TX('\n');
- TX("R1 : "); TXHex(((unsigned long)sp[1])); TX('\n');
- TX("R2 : "); TXHex(((unsigned long)sp[2])); TX('\n');
- TX("R3 : "); TXHex(((unsigned long)sp[3])); TX('\n');
- TX("R12 : "); TXHex(((unsigned long)sp[4])); TX('\n');
- TX("LR : "); TXHex(((unsigned long)sp[5])); TX('\n');
- TX("PC : "); TXHex(((unsigned long)sp[6])); TX('\n');
- TX("PSR : "); TXHex(((unsigned long)sp[7])); TX('\n');
-
- // Configurable Fault Status Register
- // Consists of MMSR, BFSR and UFSR
- TX("CFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED28)))); TX('\n');
-
- // Hard Fault Status Register
- TX("HFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED2C)))); TX('\n');
-
- // Debug Fault Status Register
- TX("DFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED30)))); TX('\n');
-
- // Auxiliary Fault Status Register
- TX("AFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED3C)))); TX('\n');
-
- // Read the Fault Address Registers. These may not contain valid values.
- // Check BFARVALID/MMARVALID to see if they are valid values
- // MemManage Fault Address Register
- TX("MMAR : "); TXHex((*((volatile unsigned long *)(0xE000ED34)))); TX('\n');
-
- // Bus Fault Address Register
- TX("BFAR : "); TXHex((*((volatile unsigned long *)(0xE000ED38)))); TX('\n');
-
- TX("ExcLR: "); TXHex(lr); TX('\n');
- TX("ExcSP: "); TXHex((unsigned long)sp); TX('\n');
-
- btf.sp = ((unsigned long)sp) + 8*4; // The original stack pointer
- btf.fp = btf.sp;
- btf.lr = ((unsigned long)sp[5]);
- btf.pc = ((unsigned long)sp[6]) | 1; // Force Thumb, as CORTEX only support it
-
- // Perform a backtrace
- TX("\nBacktrace:\n\n");
- int ctr = 0;
- UnwindStart(&btf, &UnwCallbacks, &ctr);
-
- // Disable all NVIC interrupts
- NVIC->ICER[0] = 0xFFFFFFFF;
- NVIC->ICER[1] = 0xFFFFFFFF;
-
- // Relocate VTOR table to default position
- SCB->VTOR = 0;
-
- // Clear cause of reset to prevent entering smoothie bootstrap
- HAL_clear_reset_source();
-
- // Restart watchdog
- #if ENABLED(USE_WATCHDOG)
- //WDT_Restart(WDT);
- watchdog_init();
- #endif
-
- // Reset controller
- NVIC_SystemReset();
-
- // Nothing below here is compiled because NVIC_SystemReset loops forever
-
- for (;;) { TERN_(USE_WATCHDOG, watchdog_init()); }
-}
-
-extern "C" {
-__attribute__((naked)) void NMI_Handler() {
- __asm__ __volatile__ (
- ".syntax unified" "\n\t"
- A("tst lr, #4")
- A("ite eq")
- A("mrseq r0, msp")
- A("mrsne r0, psp")
- A("mov r1,lr")
- A("mov r2,#0")
- A("b HardFault_HandlerC")
- );
-}
-
-__attribute__((naked)) void HardFault_Handler() {
- __asm__ __volatile__ (
- ".syntax unified" "\n\t"
- A("tst lr, #4")
- A("ite eq")
- A("mrseq r0, msp")
- A("mrsne r0, psp")
- A("mov r1,lr")
- A("mov r2,#1")
- A("b HardFault_HandlerC")
- );
-}
-
-__attribute__((naked)) void MemManage_Handler() {
- __asm__ __volatile__ (
- ".syntax unified" "\n\t"
- A("tst lr, #4")
- A("ite eq")
- A("mrseq r0, msp")
- A("mrsne r0, psp")
- A("mov r1,lr")
- A("mov r2,#2")
- A("b HardFault_HandlerC")
- );
-}
-
-__attribute__((naked)) void BusFault_Handler() {
- __asm__ __volatile__ (
- ".syntax unified" "\n\t"
- A("tst lr, #4")
- A("ite eq")
- A("mrseq r0, msp")
- A("mrsne r0, psp")
- A("mov r1,lr")
- A("mov r2,#3")
- A("b HardFault_HandlerC")
- );
-}
-
-__attribute__((naked)) void UsageFault_Handler() {
- __asm__ __volatile__ (
- ".syntax unified" "\n\t"
- A("tst lr, #4")
- A("ite eq")
- A("mrseq r0, msp")
- A("mrsne r0, psp")
- A("mov r1,lr")
- A("mov r2,#4")
- A("b HardFault_HandlerC")
- );
-}
-
-__attribute__((naked)) void DebugMon_Handler() {
- __asm__ __volatile__ (
- ".syntax unified" "\n\t"
- A("tst lr, #4")
- A("ite eq")
- A("mrseq r0, msp")
- A("mrsne r0, psp")
- A("mov r1,lr")
- A("mov r2,#5")
- A("b HardFault_HandlerC")
- );
-}
-
-/* This is NOT an exception, it is an interrupt handler - Nevertheless, the framing is the same */
-__attribute__((naked)) void WDT_IRQHandler() {
- __asm__ __volatile__ (
- ".syntax unified" "\n\t"
- A("tst lr, #4")
- A("ite eq")
- A("mrseq r0, msp")
- A("mrsne r0, psp")
- A("mov r1,lr")
- A("mov r2,#6")
- A("b HardFault_HandlerC")
- );
-}
-
-__attribute__((naked)) void RSTC_Handler() {
- __asm__ __volatile__ (
- ".syntax unified" "\n\t"
- A("tst lr, #4")
- A("ite eq")
- A("mrseq r0, msp")
- A("mrsne r0, psp")
- A("mov r1,lr")
- A("mov r2,#7")
- A("b HardFault_HandlerC")
- );
-}
-}
-#endif // TARGET_LPC1768
diff --git a/Marlin/src/HAL/LPC1768/HAL.cpp b/Marlin/src/HAL/LPC1768/HAL.cpp
index 939f1e8a9408..9ff3a6ba598f 100644
--- a/Marlin/src/HAL/LPC1768/HAL.cpp
+++ b/Marlin/src/HAL/LPC1768/HAL.cpp
@@ -25,26 +25,17 @@
#include "../shared/Delay.h"
#include "../../../gcode/parser.h"
-#if ENABLED(USE_WATCHDOG)
- #include "watchdog.h"
-#endif
+DefaultSerial1 USBSerial(false, UsbSerial);
-uint32_t HAL_adc_reading = 0;
+uint32_t MarlinHAL::adc_result = 0;
// U8glib required functions
-extern "C" void u8g_xMicroDelay(uint16_t val) {
- DELAY_US(val);
-}
-extern "C" void u8g_MicroDelay() {
- u8g_xMicroDelay(1);
-}
-extern "C" void u8g_10MicroDelay() {
- u8g_xMicroDelay(10);
+extern "C" {
+ void u8g_xMicroDelay(uint16_t val) { DELAY_US(val); }
+ void u8g_MicroDelay() { u8g_xMicroDelay(1); }
+ void u8g_10MicroDelay() { u8g_xMicroDelay(10); }
+ void u8g_Delay(uint16_t val) { delay(val); }
}
-extern "C" void u8g_Delay(uint16_t val) {
- delay(val);
-}
-//************************//
// return free heap space
int freeMemory() {
@@ -57,7 +48,71 @@ int freeMemory() {
return result;
}
-// scan command line for code
+void MarlinHAL::reboot() { NVIC_SystemReset(); }
+
+uint8_t MarlinHAL::get_reset_source() {
+ #if ENABLED(USE_WATCHDOG)
+ if (watchdog_timed_out()) return RST_WATCHDOG;
+ #endif
+ return RST_POWER_ON;
+}
+
+void MarlinHAL::clear_reset_source() { watchdog_clear_timeout_flag(); }
+
+void flashFirmware(const int16_t) {
+ delay(500); // Give OS time to disconnect
+ USB_Connect(false); // USB clear connection
+ delay(1000); // Give OS time to notice
+ hal.reboot();
+}
+
+#if ENABLED(USE_WATCHDOG)
+
+ #include
+
+ #define WDT_TIMEOUT_US TERN(WATCHDOG_DURATION_8S, 8000000, 4000000) // 4 or 8 second timeout
+
+ void MarlinHAL::watchdog_init() {
+ #if ENABLED(WATCHDOG_RESET_MANUAL)
+ // We enable the watchdog timer, but only for the interrupt.
+
+ // Configure WDT to only trigger an interrupt
+ // Disable WDT interrupt (just in case, to avoid triggering it!)
+ NVIC_DisableIRQ(WDT_IRQn);
+
+ // We NEED memory barriers to ensure Interrupts are actually disabled!
+ // ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
+ __DSB();
+ __ISB();
+
+ // Configure WDT to only trigger an interrupt
+ // Initialize WDT with the given parameters
+ WDT_Init(WDT_CLKSRC_IRC, WDT_MODE_INT_ONLY);
+
+ // Configure and enable WDT interrupt.
+ NVIC_ClearPendingIRQ(WDT_IRQn);
+ NVIC_SetPriority(WDT_IRQn, 0); // Use highest priority, so we detect all kinds of lockups
+ NVIC_EnableIRQ(WDT_IRQn);
+ #else
+ WDT_Init(WDT_CLKSRC_IRC, WDT_MODE_RESET);
+ #endif
+ WDT_Start(WDT_TIMEOUT_US);
+ }
+
+ void MarlinHAL::watchdog_refresh() {
+ WDT_Feed();
+ #if DISABLED(PINS_DEBUGGING) && PIN_EXISTS(LED)
+ TOGGLE(LED_PIN); // heartbeat indicator
+ #endif
+ }
+
+ // Timeout state
+ bool MarlinHAL::watchdog_timed_out() { return TEST(WDT_ReadTimeOutFlag(), 0); }
+ void MarlinHAL::watchdog_clear_timeout_flag() { WDT_ClrTimeOutFlag(); }
+
+#endif // USE_WATCHDOG
+
+// For M42/M43, scan command line for pin code
// return index into pin map array if found and the pin is valid.
// return dval if not found or not a valid pin.
int16_t PARSED_PIN_INDEX(const char code, const int16_t dval) {
@@ -66,17 +121,4 @@ int16_t PARSED_PIN_INDEX(const char code, const int16_t dval) {
return ind > -1 ? ind : dval;
}
-void flashFirmware(const int16_t) { NVIC_SystemReset(); }
-
-void HAL_clear_reset_source(void) {
- TERN_(USE_WATCHDOG, watchdog_clear_timeout_flag());
-}
-
-uint8_t HAL_get_reset_source(void) {
- #if ENABLED(USE_WATCHDOG)
- if (watchdog_timed_out()) return RST_WATCHDOG;
- #endif
- return RST_POWER_ON;
-}
-
#endif // TARGET_LPC1768
diff --git a/Marlin/src/HAL/LPC1768/HAL.h b/Marlin/src/HAL/LPC1768/HAL.h
index cb637e715dda..b0eeb983b445 100644
--- a/Marlin/src/HAL/LPC1768/HAL.h
+++ b/Marlin/src/HAL/LPC1768/HAL.h
@@ -28,8 +28,6 @@
#define CPU_32_BIT
-void HAL_init();
-
#include
#include
#include
@@ -40,80 +38,82 @@ extern "C" volatile uint32_t _millis;
#include "../shared/math_32bit.h"
#include "../shared/HAL_SPI.h"
#include "fastio.h"
-#include "watchdog.h"
#include "MarlinSerial.h"
#include
#include
#include
-// i2c uses 8-bit shifted address
-#define I2C_ADDRESS(A) uint8_t((A) << 1)
+// ------------------------
+// Serial ports
+// ------------------------
-//
-// Default graphical display delays
-//
-#ifndef ST7920_DELAY_1
- #define ST7920_DELAY_1 DELAY_NS(600)
-#endif
-#ifndef ST7920_DELAY_2
- #define ST7920_DELAY_2 DELAY_NS(750)
-#endif
-#ifndef ST7920_DELAY_3
- #define ST7920_DELAY_3 DELAY_NS(750)
-#endif
+typedef ForwardSerial1Class< decltype(UsbSerial) > DefaultSerial1;
+extern DefaultSerial1 USBSerial;
#define _MSERIAL(X) MSerial##X
#define MSERIAL(X) _MSERIAL(X)
-#define MSerial0 MSerial
#if SERIAL_PORT == -1
- #define MYSERIAL0 UsbSerial
+ #define MYSERIAL1 USBSerial
#elif WITHIN(SERIAL_PORT, 0, 3)
- #define MYSERIAL0 MSERIAL(SERIAL_PORT)
+ #define MYSERIAL1 MSERIAL(SERIAL_PORT)
#else
- #error "SERIAL_PORT must be from -1 to 3. Please update your configuration."
+ #error "SERIAL_PORT must be from 0 to 3. You can also use -1 if the board supports Native USB."
#endif
#ifdef SERIAL_PORT_2
#if SERIAL_PORT_2 == -1
- #define MYSERIAL1 UsbSerial
+ #define MYSERIAL2 USBSerial
#elif WITHIN(SERIAL_PORT_2, 0, 3)
- #define MYSERIAL1 MSERIAL(SERIAL_PORT_2)
+ #define MYSERIAL2 MSERIAL(SERIAL_PORT_2)
+ #else
+ #error "SERIAL_PORT_2 must be from 0 to 3. You can also use -1 if the board supports Native USB."
+ #endif
+#endif
+
+#ifdef SERIAL_PORT_3
+ #if SERIAL_PORT_3 == -1
+ #define MYSERIAL3 USBSerial
+ #elif WITHIN(SERIAL_PORT_3, 0, 3)
+ #define MYSERIAL3 MSERIAL(SERIAL_PORT_3)
+ #else
+ #error "SERIAL_PORT_3 must be from 0 to 3. You can also use -1 if the board supports Native USB."
+ #endif
+#endif
+
+#ifdef MMU2_SERIAL_PORT
+ #if MMU2_SERIAL_PORT == -1
+ #define MMU2_SERIAL USBSerial
+ #elif WITHIN(MMU2_SERIAL_PORT, 0, 3)
+ #define MMU2_SERIAL MSERIAL(MMU2_SERIAL_PORT)
#else
- #error "SERIAL_PORT_2 must be from -1 to 3. Please update your configuration."
+ #error "MMU2_SERIAL_PORT must be from 0 to 3. You can also use -1 if the board supports Native USB."
#endif
#endif
#ifdef LCD_SERIAL_PORT
#if LCD_SERIAL_PORT == -1
- #define LCD_SERIAL UsbSerial
+ #define LCD_SERIAL USBSerial
#elif WITHIN(LCD_SERIAL_PORT, 0, 3)
#define LCD_SERIAL MSERIAL(LCD_SERIAL_PORT)
#else
- #error "LCD_SERIAL_PORT must be from -1 to 3. Please update your configuration."
+ #error "LCD_SERIAL_PORT must be from 0 to 3. You can also use -1 if the board supports Native USB."
+ #endif
+ #if HAS_DGUS_LCD
+ #define SERIAL_GET_TX_BUFFER_FREE() LCD_SERIAL.available()
#endif
#endif
//
// Interrupts
//
-#define CRITICAL_SECTION_START() uint32_t primask = __get_PRIMASK(); __disable_irq()
-#define CRITICAL_SECTION_END() if (!primask) __enable_irq()
-#define ISRS_ENABLED() (!__get_PRIMASK())
-#define ENABLE_ISRS() __enable_irq()
-#define DISABLE_ISRS() __disable_irq()
-//
-// Utility functions
-//
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wunused-function"
-int freeMemory();
-#pragma GCC diagnostic pop
+#define CRITICAL_SECTION_START() const bool irqon = !__get_PRIMASK(); __disable_irq()
+#define CRITICAL_SECTION_END() if (irqon) __enable_irq()
//
-// ADC API
+// ADC
//
#define ADC_MEDIAN_FILTER_SIZE (23) // Higher values increase step delay (phase shift),
@@ -132,20 +132,9 @@ int freeMemory();
#define HAL_ADC_RESOLUTION 12 // 15 bit maximum, raw temperature is stored as int16_t
#define HAL_ADC_FILTERED // Disable oversampling done in Marlin as ADC values already filtered in HAL
-using FilteredADC = LPC176x::ADC;
-extern uint32_t HAL_adc_reading;
-[[gnu::always_inline]] inline void HAL_start_adc(const pin_t pin) {
- HAL_adc_reading = FilteredADC::read(pin) >> (16 - HAL_ADC_RESOLUTION); // returns 16bit value, reduce to required bits
-}
-[[gnu::always_inline]] inline uint16_t HAL_read_adc() {
- return HAL_adc_reading;
-}
-
-#define HAL_adc_init()
-#define HAL_ANALOG_SELECT(pin) FilteredADC::enable_channel(pin)
-#define HAL_START_ADC(pin) HAL_start_adc(pin)
-#define HAL_READ_ADC() HAL_read_adc()
-#define HAL_ADC_READY() (true)
+//
+// Pin Mapping for M42, M43, M226
+//
// Test whether the pin is valid
constexpr bool VALID_PIN(const pin_t pin) {
@@ -170,39 +159,109 @@ constexpr pin_t GET_PIN_MAP_PIN(const int16_t index) {
// Parse a G-code word into a pin index
int16_t PARSED_PIN_INDEX(const char code, const int16_t dval);
// P0.6 thru P0.9 are for the onboard SD card
-#define HAL_SENSITIVE_PINS P0_06, P0_07, P0_08, P0_09
+#define HAL_SENSITIVE_PINS P0_06, P0_07, P0_08, P0_09,
-#define HAL_IDLETASK 1
-void HAL_idletask();
+// ------------------------
+// Defines
+// ------------------------
#define PLATFORM_M997_SUPPORT
void flashFirmware(const int16_t);
#define HAL_CAN_SET_PWM_FREQ // This HAL supports PWM Frequency adjustment
-/**
- * set_pwm_frequency
- * Set the frequency of the timer corresponding to the provided pin
- * All Hardware PWM pins run at the same frequency and all
- * Software PWM pins run at the same frequency
- */
-void set_pwm_frequency(const pin_t pin, int f_desired);
+// Default graphical display delays
+#define CPU_ST7920_DELAY_1 600
+#define CPU_ST7920_DELAY_2 750
+#define CPU_ST7920_DELAY_3 750
-/**
- * set_pwm_duty
- * Set the PWM duty cycle of the provided pin to the provided value
- * Optionally allows inverting the duty cycle [default = false]
- * Optionally allows changing the maximum size of the provided value to enable finer PWM duty control [default = 255]
- */
-void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size=255, const bool invert=false);
+// ------------------------
+// Free Memory Accessor
+// ------------------------
-// Reset source
-void HAL_clear_reset_source(void);
-uint8_t HAL_get_reset_source(void);
+#pragma GCC diagnostic push
+#if GCC_VERSION <= 50000
+ #pragma GCC diagnostic ignored "-Wunused-function"
+#endif
-inline void HAL_reboot() {} // reboot the board or restart the bootloader
+int freeMemory();
-// Add strcmp_P if missing
-#ifndef strcmp_P
- #define strcmp_P(a, b) strcmp((a), (b))
-#endif
+#pragma GCC diagnostic pop
+
+// ------------------------
+// MarlinHAL Class
+// ------------------------
+
+class MarlinHAL {
+public:
+
+ // Earliest possible init, before setup()
+ MarlinHAL() {}
+
+ static void init(); // Called early in setup()
+ static void init_board() {} // Called less early in setup()
+ static void reboot(); // Restart the firmware from 0x0
+
+ // Interrupts
+ static bool isr_state() { return !__get_PRIMASK(); }
+ static void isr_on() { __enable_irq(); }
+ static void isr_off() { __disable_irq(); }
+
+ static void delay_ms(const int ms) { _delay_ms(ms); }
+
+ // Watchdog
+ static void watchdog_init() IF_DISABLED(USE_WATCHDOG, {});
+ static void watchdog_refresh() IF_DISABLED(USE_WATCHDOG, {});
+ static bool watchdog_timed_out() IF_DISABLED(USE_WATCHDOG, { return false; });
+ static void watchdog_clear_timeout_flag() IF_DISABLED(USE_WATCHDOG, {});
+
+ // Tasks, called from idle()
+ static void idletask();
+
+ // Reset
+ static uint8_t get_reset_source();
+ static void clear_reset_source();
+
+ // Free SRAM
+ static int freeMemory() { return ::freeMemory(); }
+
+ //
+ // ADC Methods
+ //
+
+ using FilteredADC = LPC176x::ADC;
+
+ // Called by Temperature::init once at startup
+ static void adc_init() {}
+
+ // Called by Temperature::init for each sensor at startup
+ static void adc_enable(const pin_t pin) {
+ FilteredADC::enable_channel(pin);
+ }
+
+ // Begin ADC sampling on the given pin. Called from Temperature::isr!
+ static uint32_t adc_result;
+ static void adc_start(const pin_t pin) {
+ adc_result = FilteredADC::read(pin) >> (16 - HAL_ADC_RESOLUTION); // returns 16bit value, reduce to required bits
+ }
+
+ // Is the ADC ready for reading?
+ static bool adc_ready() { return true; }
+
+ // The current value of the ADC register
+ static uint16_t adc_value() { return uint16_t(adc_result); }
+
+ /**
+ * Set the PWM duty cycle for the pin to the given value.
+ * Optionally invert the duty cycle [default = false]
+ * Optionally change the scale of the provided value to enable finer PWM duty control [default = 255]
+ */
+ static void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size=255, const bool invert=false);
+
+ /**
+ * Set the frequency of the timer corresponding to the provided pin
+ * All Hardware PWM pins will run at the same frequency and
+ * All Software PWM pins will run at the same frequency
+ */
+ static void set_pwm_frequency(const pin_t pin, const uint16_t f_desired);
+};
diff --git a/Marlin/src/HAL/LPC1768/HAL_SPI.cpp b/Marlin/src/HAL/LPC1768/HAL_SPI.cpp
index cb0d54c0036f..29f9b43afef0 100644
--- a/Marlin/src/HAL/LPC1768/HAL_SPI.cpp
+++ b/Marlin/src/HAL/LPC1768/HAL_SPI.cpp
@@ -55,27 +55,29 @@
#include
#include
+#include "../shared/HAL_SPI.h"
+
// ------------------------
// Public functions
// ------------------------
#if ENABLED(LPC_SOFTWARE_SPI)
- #include
-
// Software SPI
- static uint8_t SPI_speed = 0;
+ #include
+
+ static uint8_t SPI_speed = SPI_FULL_SPEED;
static uint8_t spiTransfer(uint8_t b) {
- return swSpiTransfer(b, SPI_speed, SCK_PIN, MISO_PIN, MOSI_PIN);
+ return swSpiTransfer(b, SPI_speed, SD_SCK_PIN, SD_MISO_PIN, SD_MOSI_PIN);
}
void spiBegin() {
- swSpiBegin(SCK_PIN, MISO_PIN, MOSI_PIN);
+ swSpiBegin(SD_SCK_PIN, SD_MISO_PIN, SD_MOSI_PIN);
}
void spiInit(uint8_t spiRate) {
- SPI_speed = swSpiInit(spiRate, SCK_PIN, MOSI_PIN);
+ SPI_speed = swSpiInit(spiRate, SD_SCK_PIN, SD_MOSI_PIN);
}
uint8_t spiRec() { return spiTransfer(0xFF); }
@@ -87,12 +89,12 @@
void spiSend(uint8_t b) { (void)spiTransfer(b); }
- void spiSend(const uint8_t* buf, size_t nbyte) {
+ void spiSend(const uint8_t *buf, size_t nbyte) {
for (uint16_t i = 0; i < nbyte; i++)
(void)spiTransfer(buf[i]);
}
- void spiSendBlock(uint8_t token, const uint8_t* buf) {
+ void spiSendBlock(uint8_t token, const uint8_t *buf) {
(void)spiTransfer(token);
for (uint16_t i = 0; i < 512; i++)
(void)spiTransfer(buf[i]);
@@ -100,14 +102,18 @@
#else
- void spiBegin() { // setup SCK, MOSI & MISO pins for SSP0
- spiInit(SPI_SPEED);
- }
+ #ifdef SD_SPI_SPEED
+ #define INIT_SPI_SPEED SD_SPI_SPEED
+ #else
+ #define INIT_SPI_SPEED SPI_FULL_SPEED
+ #endif
+
+ void spiBegin() { spiInit(INIT_SPI_SPEED); } // Set up SCK, MOSI & MISO pins for SSP0
void spiInit(uint8_t spiRate) {
- #if MISO_PIN == BOARD_SPI1_MISO_PIN
+ #if SD_MISO_PIN == BOARD_SPI1_MISO_PIN
SPI.setModule(1);
- #elif MISO_PIN == BOARD_SPI2_MISO_PIN
+ #elif SD_MISO_PIN == BOARD_SPI2_MISO_PIN
SPI.setModule(2);
#endif
SPI.setDataSize(DATA_SIZE_8BIT);
@@ -123,15 +129,13 @@
void spiSend(uint8_t b) { doio(b); }
- void spiSend(const uint8_t* buf, size_t nbyte) {
+ void spiSend(const uint8_t *buf, size_t nbyte) {
for (uint16_t i = 0; i < nbyte; i++) doio(buf[i]);
}
- void spiSend(uint32_t chan, byte b) {
- }
+ void spiSend(uint32_t chan, byte b) {}
- void spiSend(uint32_t chan, const uint8_t* buf, size_t nbyte) {
- }
+ void spiSend(uint32_t chan, const uint8_t *buf, size_t nbyte) {}
// Read single byte from SPI
uint8_t spiRec() { return doio(0xFF); }
@@ -143,21 +147,18 @@
for (uint16_t i = 0; i < nbyte; i++) buf[i] = doio(0xFF);
}
- uint8_t spiTransfer(uint8_t b) {
- return doio(b);
- }
+ uint8_t spiTransfer(uint8_t b) { return doio(b); }
// Write from buffer to SPI
- void spiSendBlock(uint8_t token, const uint8_t* buf) {
+ void spiSendBlock(uint8_t token, const uint8_t *buf) {
(void)spiTransfer(token);
for (uint16_t i = 0; i < 512; i++)
(void)spiTransfer(buf[i]);
}
- /** Begin SPI transaction, set clock, bit order, data mode */
+ // Begin SPI transaction, set clock, bit order, data mode
void spiBeginTransaction(uint32_t spiClock, uint8_t bitOrder, uint8_t dataMode) {
- // TODO: to be implemented
-
+ // TODO: Implement this method
}
#endif // LPC_SOFTWARE_SPI
@@ -201,6 +202,15 @@ SPIClass::SPIClass(uint8_t device) {
GPDMA_Init();
}
+SPIClass::SPIClass(pin_t mosi, pin_t miso, pin_t sclk, pin_t ssel) {
+ #if BOARD_NR_SPI >= 1
+ if (mosi == BOARD_SPI1_MOSI_PIN) SPIClass(1);
+ #endif
+ #if BOARD_NR_SPI >= 2
+ if (mosi == BOARD_SPI2_MOSI_PIN) SPIClass(2);
+ #endif
+}
+
void SPIClass::begin() {
// Init the SPI pins in the first begin call
if ((_currentSetting->spi_d == LPC_SSP0 && spiInitialised[0] == false) ||
@@ -331,25 +341,15 @@ void SPIClass::read(uint8_t *buf, uint32_t len) {
for (uint16_t i = 0; i < len; i++) buf[i] = transfer(0xFF);
}
-void SPIClass::setClock(uint32_t clock) {
- _currentSetting->clock = clock;
-}
+void SPIClass::setClock(uint32_t clock) { _currentSetting->clock = clock; }
-void SPIClass::setModule(uint8_t device) {
- _currentSetting = &_settings[device - 1];// SPI channels are called 1 2 and 3 but the array is zero indexed
-}
+void SPIClass::setModule(uint8_t device) { _currentSetting = &_settings[device - 1]; } // SPI channels are called 1, 2, and 3 but the array is zero-indexed
-void SPIClass::setBitOrder(uint8_t bitOrder) {
- _currentSetting->bitOrder = bitOrder;
-}
+void SPIClass::setBitOrder(uint8_t bitOrder) { _currentSetting->bitOrder = bitOrder; }
-void SPIClass::setDataMode(uint8_t dataMode) {
- _currentSetting->dataMode = dataMode;
-}
+void SPIClass::setDataMode(uint8_t dataMode) { _currentSetting->dataMode = dataMode; }
-void SPIClass::setDataSize(uint32_t ds) {
- _currentSetting->dataSize = ds;
-}
+void SPIClass::setDataSize(uint32_t dataSize) { _currentSetting->dataSize = dataSize; }
/**
* Set up/tear down
@@ -357,8 +357,8 @@ void SPIClass::setDataSize(uint32_t ds) {
void SPIClass::updateSettings() {
//SSP_DeInit(_currentSetting->spi_d); //todo: need force de init?!
- // divide PCLK by 2 for SSP0
- CLKPWR_SetPCLKDiv(_currentSetting->spi_d == LPC_SSP0 ? CLKPWR_PCLKSEL_SSP0 : CLKPWR_PCLKSEL_SSP1, CLKPWR_PCLKSEL_CCLK_DIV_2);
+ // Divide PCLK by 2 for SSP0
+ //CLKPWR_SetPCLKDiv(_currentSetting->spi_d == LPC_SSP0 ? CLKPWR_PCLKSEL_SSP0 : CLKPWR_PCLKSEL_SSP1, CLKPWR_PCLKSEL_CCLK_DIV_2);
SSP_CFG_Type HW_SPI_init; // data structure to hold init values
SSP_ConfigStructInit(&HW_SPI_init); // set values for SPI mode
@@ -397,9 +397,9 @@ void SPIClass::updateSettings() {
SSP_Init(_currentSetting->spi_d, &HW_SPI_init); // puts the values into the proper bits in the SSP0 registers
}
-#if MISO_PIN == BOARD_SPI1_MISO_PIN
+#if SD_MISO_PIN == BOARD_SPI1_MISO_PIN
SPIClass SPI(1);
-#elif MISO_PIN == BOARD_SPI2_MISO_PIN
+#elif SD_MISO_PIN == BOARD_SPI2_MISO_PIN
SPIClass SPI(2);
#endif
diff --git a/Marlin/src/HAL/LPC1768/MarlinSPI.h b/Marlin/src/HAL/LPC1768/MarlinSPI.h
new file mode 100644
index 000000000000..fab245f904e3
--- /dev/null
+++ b/Marlin/src/HAL/LPC1768/MarlinSPI.h
@@ -0,0 +1,45 @@
+/**
+ * Marlin 3D Printer Firmware
+ * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
+ *
+ * Based on Sprinter and grbl.
+ * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ */
+#pragma once
+
+#include
+
+/**
+ * Marlin currently requires 3 SPI classes:
+ *
+ * SPIClass:
+ * This class is normally provided by frameworks and has a semi-default interface.
+ * This is needed because some libraries reference it globally.
+ *
+ * SPISettings:
+ * Container for SPI configs for SPIClass. As above, libraries may reference it globally.
+ *
+ * These two classes are often provided by frameworks so we cannot extend them to add
+ * useful methods for Marlin.
+ *
+ * MarlinSPI:
+ * Provides the default SPIClass interface plus some Marlin goodies such as a simplified
+ * interface for SPI DMA transfer.
+ *
+ */
+
+using MarlinSPI = SPIClass;
diff --git a/Marlin/src/HAL/LPC1768/MarlinSerial.cpp b/Marlin/src/HAL/LPC1768/MarlinSerial.cpp
index 5374e005d3da..f2aecf54a050 100644
--- a/Marlin/src/HAL/LPC1768/MarlinSerial.cpp
+++ b/Marlin/src/HAL/LPC1768/MarlinSerial.cpp
@@ -21,35 +21,51 @@
*/
#ifdef TARGET_LPC1768
-#include "../../inc/MarlinConfigPre.h"
#include "MarlinSerial.h"
-#if USING_SERIAL_0
- MarlinSerial MSerial(LPC_UART0);
- extern "C" void UART0_IRQHandler() {
- MSerial.IRQHandler();
- }
-#endif
+#include "../../inc/MarlinConfig.h"
-#if USING_SERIAL_1
- MarlinSerial MSerial1((LPC_UART_TypeDef *) LPC_UART1);
- extern "C" void UART1_IRQHandler() {
- MSerial1.IRQHandler();
- }
+#if USING_HW_SERIAL0
+ MarlinSerial _MSerial0(LPC_UART0);
+ MSerialT MSerial0(true, _MSerial0);
+ extern "C" void UART0_IRQHandler() { _MSerial0.IRQHandler(); }
#endif
-
-#if USING_SERIAL_2
- MarlinSerial MSerial2(LPC_UART2);
- extern "C" void UART2_IRQHandler() {
- MSerial2.IRQHandler();
- }
+#if USING_HW_SERIAL1
+ MarlinSerial _MSerial1((LPC_UART_TypeDef *) LPC_UART1);
+ MSerialT MSerial1(true, _MSerial1);
+ extern "C" void UART1_IRQHandler() { _MSerial1.IRQHandler(); }
+#endif
+#if USING_HW_SERIAL2
+ MarlinSerial _MSerial2(LPC_UART2);
+ MSerialT MSerial2(true, _MSerial2);
+ extern "C" void UART2_IRQHandler() { _MSerial2.IRQHandler(); }
+#endif
+#if USING_HW_SERIAL3
+ MarlinSerial _MSerial3(LPC_UART3);
+ MSerialT MSerial3(true, _MSerial3);
+ extern "C" void UART3_IRQHandler() { _MSerial3.IRQHandler(); }
#endif
-#if USING_SERIAL_3
- MarlinSerial MSerial3(LPC_UART3);
- extern "C" void UART3_IRQHandler() {
- MSerial3.IRQHandler();
+#if ENABLED(EMERGENCY_PARSER)
+
+ bool MarlinSerial::recv_callback(const char c) {
+ // Need to figure out which serial port we are and react in consequence (Marlin does not have CONTAINER_OF macro)
+ if (false) {}
+ #if USING_HW_SERIAL0
+ else if (this == &_MSerial0) emergency_parser.update(MSerial0.emergency_state, c);
+ #endif
+ #if USING_HW_SERIAL1
+ else if (this == &_MSerial1) emergency_parser.update(MSerial1.emergency_state, c);
+ #endif
+ #if USING_HW_SERIAL2
+ else if (this == &_MSerial2) emergency_parser.update(MSerial2.emergency_state, c);
+ #endif
+ #if USING_HW_SERIAL3
+ else if (this == &_MSerial3) emergency_parser.update(MSerial3.emergency_state, c);
+ #endif
+ return true;
}
+
#endif
#endif // TARGET_LPC1768
diff --git a/Marlin/src/HAL/LPC1768/MarlinSerial.h b/Marlin/src/HAL/LPC1768/MarlinSerial.h
index 8d6b64378a0a..3e6848a1e3d0 100644
--- a/Marlin/src/HAL/LPC1768/MarlinSerial.h
+++ b/Marlin/src/HAL/LPC1768/MarlinSerial.h
@@ -28,6 +28,7 @@
#if ENABLED(EMERGENCY_PARSER)
#include "../../feature/e_parser.h"
#endif
+#include "../../core/serial_hook.h"
#ifndef SERIAL_PORT
#define SERIAL_PORT 0
@@ -41,27 +42,28 @@
class MarlinSerial : public HardwareSerial {
public:
- MarlinSerial(LPC_UART_TypeDef *UARTx) :
- HardwareSerial(UARTx)
- #if ENABLED(EMERGENCY_PARSER)
- , emergency_state(EmergencyParser::State::EP_RESET)
- #endif
- { }
+ MarlinSerial(LPC_UART_TypeDef *UARTx) : HardwareSerial(UARTx) { }
void end() {}
- #if ENABLED(EMERGENCY_PARSER)
- bool recv_callback(const char c) override {
- emergency_parser.update(emergency_state, c);
- return true; // do not discard character
- }
+ uint8_t availableForWrite(void) { /* flushTX(); */ return TX_BUFFER_SIZE; }
- EmergencyParser::State emergency_state;
- static inline bool emergency_parser_enabled() { return true; }
+ #if ENABLED(EMERGENCY_PARSER)
+ bool recv_callback(const char c) override;
#endif
};
-extern MarlinSerial MSerial;
-extern MarlinSerial MSerial1;
-extern MarlinSerial MSerial2;
-extern MarlinSerial MSerial3;
+// On LPC176x framework, HardwareSerial does not implement the same interface as Arduino's Serial, so overloads
+// of 'available' and 'read' method are not used in this multiple inheritance scenario.
+// Instead, use a ForwardSerial here that adapts the interface.
+typedef ForwardSerial1Class