diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000000..efc5972325 --- /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 0000000000..1fe68966fb --- /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 0000000000..b64383cd48 --- /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 6bc7b5a005..fcb87b0141 100644 --- a/.github/contributing.md +++ b/.github/contributing.md @@ -50,13 +50,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 +88,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 +116,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 6cb34b8f58..0000000000 --- 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 d82fb0f9e3..cd5158b3ce 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 0000000000..51b58ad493 --- /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 0000000000..79d0b5e2d0 --- /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](http://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 0000000000..befec4498f --- /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 0000000000..f90c079f66 --- /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: 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 0000000000..8cdcd7a836 --- /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 069f36714d..90a960430b 100644 --- a/.github/workflows/test-builds.yml +++ b/.github/workflows/test-builds.yml @@ -9,6 +9,7 @@ on: pull_request: branches: - bugfix-2.0.x + - bugfix-2.1.x paths-ignore: - config/** - data/** @@ -17,6 +18,7 @@ on: push: branches: - bugfix-2.0.x + - bugfix-2.1.x paths-ignore: - config/** - data/** @@ -59,7 +61,7 @@ jobs: #- STM32F103RC_btt_maple - STM32F103RC_btt_USB_maple - STM32F103RC_fysetc_maple - - STM32F103RC_meeb + - STM32F103RC_meeb_maple - jgaurora_a5s_a1_maple - STM32F103VE_longer_maple #- mks_robin_maple @@ -76,9 +78,9 @@ jobs: - STM32F103RE_btt - STM32F103RE_btt_USB - STM32F103RE_creality + - STM32F401RC_creality - STM32F103VE_longer - STM32F407VE_black - - STM32F401VE_STEVAL - BIGTREE_BTT002 - BIGTREE_SKR_PRO - BIGTREE_GTR_V1_0 @@ -97,7 +99,7 @@ jobs: - REMRAM_V1 - BTT_SKR_SE_BX - chitu_f103 - - Index_Mobo_Rev03 + - Opulo_Lumen_REV3 # Put lengthy tests last @@ -137,8 +139,9 @@ jobs: - name: Install PlatformIO run: | - pip install -U https://github.com/platformio/platformio-core/archive/v5.2.5.zip - platformio update + pip install -U platformio + pio upgrade --dev + pio pkg update --global - name: Run ${{ matrix.test-platform }} Tests run: | diff --git a/.github/workflows/unlock-reopened.yml b/.github/workflows/unlock-reopened.yml new file mode 100644 index 0000000000..614ef3fab2 --- /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/CR6E3Touch_NextGen_TM3D.7z b/CR6E3Touch_NextGen_TM3D.7z deleted file mode 100644 index 069875ac99..0000000000 Binary files a/CR6E3Touch_NextGen_TM3D.7z and /dev/null differ diff --git a/CR6E3_PortraitTouch_TM3D.7z b/CR6E3_PortraitTouch_TM3D.7z new file mode 100644 index 0000000000..03f3956444 Binary files /dev/null and b/CR6E3_PortraitTouch_TM3D.7z differ diff --git a/Creality_CR6DWIN_DW74.7z b/Creality_CR6DWIN_DW74.7z deleted file mode 100644 index 072ba689e2..0000000000 Binary files a/Creality_CR6DWIN_DW74.7z and /dev/null differ diff --git a/Hex Files/10SProBLTUBLEncMC_DW7.4.6.hex.zip b/Hex Files/10SProBLTUBLEncMC_DW7.4.6.hex.zip index 6180f0108b..e2ababa67c 100644 Binary files a/Hex Files/10SProBLTUBLEncMC_DW7.4.6.hex.zip and b/Hex Files/10SProBLTUBLEncMC_DW7.4.6.hex.zip differ diff --git a/Hex Files/10SProV2_BIL_DW7.4.6.hex.zip b/Hex Files/10SProV2_BIL_DW7.4.6.hex.zip index a1a99ba9bc..c064dd2672 100644 Binary files a/Hex Files/10SProV2_BIL_DW7.4.6.hex.zip and b/Hex Files/10SProV2_BIL_DW7.4.6.hex.zip differ diff --git a/Hex Files/10SProV2_BIL_MC_DW7.4.6.hex.zip b/Hex Files/10SProV2_BIL_MC_DW7.4.6.hex.zip index 09ba3b0054..eb43fba2a9 100644 Binary files a/Hex Files/10SProV2_BIL_MC_DW7.4.6.hex.zip and b/Hex Files/10SProV2_BIL_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/10SProV2_BIL_ME_DW7.4.6.hex.zip b/Hex Files/10SProV2_BIL_ME_DW7.4.6.hex.zip index 241c9f5492..73138d711a 100644 Binary files a/Hex Files/10SProV2_BIL_ME_DW7.4.6.hex.zip and b/Hex Files/10SProV2_BIL_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/10SProV2_UBL_DW7.4.6.hex.zip b/Hex Files/10SProV2_UBL_DW7.4.6.hex.zip index e28323ee0d..3b9bc9ea34 100644 Binary files a/Hex Files/10SProV2_UBL_DW7.4.6.hex.zip and b/Hex Files/10SProV2_UBL_DW7.4.6.hex.zip differ diff --git a/Hex Files/10SProV2_UBL_MC_DW7.4.6.hex.zip b/Hex Files/10SProV2_UBL_MC_DW7.4.6.hex.zip index 9070f9963d..3b86a5a4e2 100644 Binary files a/Hex Files/10SProV2_UBL_MC_DW7.4.6.hex.zip and b/Hex Files/10SProV2_UBL_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/10SProV2_UBL_ME_DW7.4.6.hex.zip b/Hex Files/10SProV2_UBL_ME_DW7.4.6.hex.zip index 1cafd244f8..8f0c45400d 100644 Binary files a/Hex Files/10SProV2_UBL_ME_DW7.4.6.hex.zip and b/Hex Files/10SProV2_UBL_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/10SPro_BIL_DW7.4.6.hex.zip b/Hex Files/10SPro_BIL_DW7.4.6.hex.zip index 4c6d74a31a..d067377016 100644 Binary files a/Hex Files/10SPro_BIL_DW7.4.6.hex.zip and b/Hex Files/10SPro_BIL_DW7.4.6.hex.zip differ diff --git a/Hex Files/10SPro_BIL_MC_DW7.4.6.hex.zip b/Hex Files/10SPro_BIL_MC_DW7.4.6.hex.zip index 56f88e9cf7..6a00185f06 100644 Binary files a/Hex Files/10SPro_BIL_MC_DW7.4.6.hex.zip and b/Hex Files/10SPro_BIL_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/10SPro_BIL_ME_DW7.4.6.hex.zip b/Hex Files/10SPro_BIL_ME_DW7.4.6.hex.zip index c89f6fff39..836bcaf85f 100644 Binary files a/Hex Files/10SPro_BIL_ME_DW7.4.6.hex.zip and b/Hex Files/10SPro_BIL_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/10SPro_BLTUBLEncME_DW7.4.6.hex.zip b/Hex Files/10SPro_BLTUBLEncME_DW7.4.6.hex.zip index 9b3c30ec54..1812a7e579 100644 Binary files a/Hex Files/10SPro_BLTUBLEncME_DW7.4.6.hex.zip and b/Hex Files/10SPro_BLTUBLEncME_DW7.4.6.hex.zip differ diff --git a/Hex Files/10SPro_BLT_BIL_DW7.4.6.hex.zip b/Hex Files/10SPro_BLT_BIL_DW7.4.6.hex.zip index bbafe2373c..0fb4030d01 100644 Binary files a/Hex Files/10SPro_BLT_BIL_DW7.4.6.hex.zip and b/Hex Files/10SPro_BLT_BIL_DW7.4.6.hex.zip differ diff --git a/Hex Files/10SPro_BLT_BIL_MC_DW7.4.6.hex.zip b/Hex Files/10SPro_BLT_BIL_MC_DW7.4.6.hex.zip index 4a9985ec1f..5516704dce 100644 Binary files a/Hex Files/10SPro_BLT_BIL_MC_DW7.4.6.hex.zip and b/Hex Files/10SPro_BLT_BIL_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/10SPro_BLT_BIL_ME_DW7.4.6.hex.zip b/Hex Files/10SPro_BLT_BIL_ME_DW7.4.6.hex.zip index 24e704232a..97b551ed05 100644 Binary files a/Hex Files/10SPro_BLT_BIL_ME_DW7.4.6.hex.zip and b/Hex Files/10SPro_BLT_BIL_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/10SPro_BLT_UBL_DW7.4.6.hex.zip b/Hex Files/10SPro_BLT_UBL_DW7.4.6.hex.zip index 95fd2440c4..677e5cf732 100644 Binary files a/Hex Files/10SPro_BLT_UBL_DW7.4.6.hex.zip and b/Hex Files/10SPro_BLT_UBL_DW7.4.6.hex.zip differ diff --git a/Hex Files/10SPro_BLT_UBL_Enc_DW7.4.6.hex.zip b/Hex Files/10SPro_BLT_UBL_Enc_DW7.4.6.hex.zip index 6d29a5759b..98a1d3301e 100644 Binary files a/Hex Files/10SPro_BLT_UBL_Enc_DW7.4.6.hex.zip and b/Hex Files/10SPro_BLT_UBL_Enc_DW7.4.6.hex.zip differ diff --git a/Hex Files/10SPro_BLT_UBL_MC_DW7.4.6.hex.zip b/Hex Files/10SPro_BLT_UBL_MC_DW7.4.6.hex.zip index 8ac7adb64c..56111c9529 100644 Binary files a/Hex Files/10SPro_BLT_UBL_MC_DW7.4.6.hex.zip and b/Hex Files/10SPro_BLT_UBL_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/10SPro_BLT_UBL_ME_DW7.4.6.hex.zip b/Hex Files/10SPro_BLT_UBL_ME_DW7.4.6.hex.zip index 511fc31ac1..f51ea84cc7 100644 Binary files a/Hex Files/10SPro_BLT_UBL_ME_DW7.4.6.hex.zip and b/Hex Files/10SPro_BLT_UBL_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/10SPro_UBL_DW7.4.6.hex.zip b/Hex Files/10SPro_UBL_DW7.4.6.hex.zip index 89388dc43a..55ad4733e7 100644 Binary files a/Hex Files/10SPro_UBL_DW7.4.6.hex.zip and b/Hex Files/10SPro_UBL_DW7.4.6.hex.zip differ diff --git a/Hex Files/10SPro_UBL_MC_DW7.4.6.hex.zip b/Hex Files/10SPro_UBL_MC_DW7.4.6.hex.zip index a856b3b4f3..0ea5cbfa09 100644 Binary files a/Hex Files/10SPro_UBL_MC_DW7.4.6.hex.zip and b/Hex Files/10SPro_UBL_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/10SPro_UBL_ME_DW7.4.6.hex.zip b/Hex Files/10SPro_UBL_ME_DW7.4.6.hex.zip index 998189dec0..bfc6045e46 100644 Binary files a/Hex Files/10SPro_UBL_ME_DW7.4.6.hex.zip and b/Hex Files/10SPro_UBL_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10Max_BIL_DW7.4.6.hex.zip b/Hex Files/CR10Max_BIL_DW7.4.6.hex.zip index ba655074ca..5c51ef16a1 100644 Binary files a/Hex Files/CR10Max_BIL_DW7.4.6.hex.zip and b/Hex Files/CR10Max_BIL_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10Max_BIL_MC_DW7.4.6.hex.zip b/Hex Files/CR10Max_BIL_MC_DW7.4.6.hex.zip index 118f2b633c..92a41d5233 100644 Binary files a/Hex Files/CR10Max_BIL_MC_DW7.4.6.hex.zip and b/Hex Files/CR10Max_BIL_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10Max_BIL_ME_DW7.4.6.hex.zip b/Hex Files/CR10Max_BIL_ME_DW7.4.6.hex.zip index 13ece73258..3461b56331 100644 Binary files a/Hex Files/CR10Max_BIL_ME_DW7.4.6.hex.zip and b/Hex Files/CR10Max_BIL_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10Max_UBL_DW7.4.6.hex.zip b/Hex Files/CR10Max_UBL_DW7.4.6.hex.zip index b9b2358e6b..063d4d3068 100644 Binary files a/Hex Files/CR10Max_UBL_DW7.4.6.hex.zip and b/Hex Files/CR10Max_UBL_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10Max_UBL_MC_DW7.4.6.hex.zip b/Hex Files/CR10Max_UBL_MC_DW7.4.6.hex.zip index 4f7f6061a2..98f5e0f2eb 100644 Binary files a/Hex Files/CR10Max_UBL_MC_DW7.4.6.hex.zip and b/Hex Files/CR10Max_UBL_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10Max_UBL_ME_DW7.4.6.hex.zip b/Hex Files/CR10Max_UBL_ME_DW7.4.6.hex.zip index 0c2bd79d06..cd63fc3714 100644 Binary files a/Hex Files/CR10Max_UBL_ME_DW7.4.6.hex.zip and b/Hex Files/CR10Max_UBL_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10MiniBLTHostMC_DW7.4.6.hex.zip b/Hex Files/CR10MiniBLTHostMC_DW7.4.6.hex.zip index 3010baa15f..d5bd1b3f6b 100644 Binary files a/Hex Files/CR10MiniBLTHostMC_DW7.4.6.hex.zip and b/Hex Files/CR10MiniBLTHostMC_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10MiniBLTHostME_DW7.4.6.hex.zip b/Hex Files/CR10MiniBLTHostME_DW7.4.6.hex.zip index 582ba6146b..6722b357f3 100644 Binary files a/Hex Files/CR10MiniBLTHostME_DW7.4.6.hex.zip and b/Hex Files/CR10MiniBLTHostME_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10Mini_BLT_Host_DW7.4.6.hex.zip b/Hex Files/CR10Mini_BLT_Host_DW7.4.6.hex.zip index 1c3f194df3..1a66c499b0 100644 Binary files a/Hex Files/CR10Mini_BLT_Host_DW7.4.6.hex.zip and b/Hex Files/CR10Mini_BLT_Host_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10Mini_BLT_SD_DW7.4.6.hex.zip b/Hex Files/CR10Mini_BLT_SD_DW7.4.6.hex.zip index 608b0a5d51..7b777e9013 100644 Binary files a/Hex Files/CR10Mini_BLT_SD_DW7.4.6.hex.zip and b/Hex Files/CR10Mini_BLT_SD_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10Mini_BLT_SD_MC_DW7.4.6.hex.zip b/Hex Files/CR10Mini_BLT_SD_MC_DW7.4.6.hex.zip index 781557c9bf..097533c33a 100644 Binary files a/Hex Files/CR10Mini_BLT_SD_MC_DW7.4.6.hex.zip and b/Hex Files/CR10Mini_BLT_SD_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10Mini_BLT_SD_ME_DW7.4.6.hex.zip b/Hex Files/CR10Mini_BLT_SD_ME_DW7.4.6.hex.zip index 7b1af655ae..8c2f9e421d 100644 Binary files a/Hex Files/CR10Mini_BLT_SD_ME_DW7.4.6.hex.zip and b/Hex Files/CR10Mini_BLT_SD_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10Mini_DW7.4.6.hex.zip b/Hex Files/CR10Mini_DW7.4.6.hex.zip index cbb04df553..fc04743f49 100644 Binary files a/Hex Files/CR10Mini_DW7.4.6.hex.zip and b/Hex Files/CR10Mini_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10Mini_MC_DW7.4.6.hex.zip b/Hex Files/CR10Mini_MC_DW7.4.6.hex.zip index 937528f745..525547ee43 100644 Binary files a/Hex Files/CR10Mini_MC_DW7.4.6.hex.zip and b/Hex Files/CR10Mini_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10Mini_ME_DW7.4.6.hex.zip b/Hex Files/CR10Mini_ME_DW7.4.6.hex.zip index 7856d83539..61915d3f99 100644 Binary files a/Hex Files/CR10Mini_ME_DW7.4.6.hex.zip and b/Hex Files/CR10Mini_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10S_BLT_DW7.4.6.hex.zip b/Hex Files/CR10S_BLT_DW7.4.6.hex.zip index 08f41bc619..e05a3dcdb1 100644 Binary files a/Hex Files/CR10S_BLT_DW7.4.6.hex.zip and b/Hex Files/CR10S_BLT_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10S_BLT_LR_DW7.4.6.hex.zip b/Hex Files/CR10S_BLT_LR_DW7.4.6.hex.zip index a23801cd81..6aeff8c8df 100644 Binary files a/Hex Files/CR10S_BLT_LR_DW7.4.6.hex.zip and b/Hex Files/CR10S_BLT_LR_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10S_BLT_MC_DW7.4.6.hex.zip b/Hex Files/CR10S_BLT_MC_DW7.4.6.hex.zip index a58113c834..9e28882ee0 100644 Binary files a/Hex Files/CR10S_BLT_MC_DW7.4.6.hex.zip and b/Hex Files/CR10S_BLT_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10S_BLT_MC_NF_DW7.4.6.hex.zip b/Hex Files/CR10S_BLT_MC_NF_DW7.4.6.hex.zip index e32bf15d9b..c428208edd 100644 Binary files a/Hex Files/CR10S_BLT_MC_NF_DW7.4.6.hex.zip and b/Hex Files/CR10S_BLT_MC_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10S_BLT_ME_DW7.4.6.hex.zip b/Hex Files/CR10S_BLT_ME_DW7.4.6.hex.zip index 8d90f8afed..4932aac101 100644 Binary files a/Hex Files/CR10S_BLT_ME_DW7.4.6.hex.zip and b/Hex Files/CR10S_BLT_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10S_BLT_ME_NF_DW7.4.6.hex.zip b/Hex Files/CR10S_BLT_ME_NF_DW7.4.6.hex.zip index eb407dcf4d..8c3c255d7a 100644 Binary files a/Hex Files/CR10S_BLT_ME_NF_DW7.4.6.hex.zip and b/Hex Files/CR10S_BLT_ME_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10S_BLT_NF_DW7.4.6.hex.zip b/Hex Files/CR10S_BLT_NF_DW7.4.6.hex.zip index 00ff6e245c..b75fccd752 100644 Binary files a/Hex Files/CR10S_BLT_NF_DW7.4.6.hex.zip and b/Hex Files/CR10S_BLT_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10S_BLT_NF_LR_DW7.4.6.hex.zip b/Hex Files/CR10S_BLT_NF_LR_DW7.4.6.hex.zip index 37cd8be475..c97e92cfb5 100644 Binary files a/Hex Files/CR10S_BLT_NF_LR_DW7.4.6.hex.zip and b/Hex Files/CR10S_BLT_NF_LR_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10S_BLT_UBL_DW7.4.6.hex.zip b/Hex Files/CR10S_BLT_UBL_DW7.4.6.hex.zip index 77d87563ed..a0e742c9a6 100644 Binary files a/Hex Files/CR10S_BLT_UBL_DW7.4.6.hex.zip and b/Hex Files/CR10S_BLT_UBL_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10S_BLT_UBL_MC_DW7.4.6.hex.zip b/Hex Files/CR10S_BLT_UBL_MC_DW7.4.6.hex.zip index c40114d755..79328e8fc3 100644 Binary files a/Hex Files/CR10S_BLT_UBL_MC_DW7.4.6.hex.zip and b/Hex Files/CR10S_BLT_UBL_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10S_BLT_UBL_MC_NF_DW7.4.6.hex.zip b/Hex Files/CR10S_BLT_UBL_MC_NF_DW7.4.6.hex.zip index 1f777cace9..3700e44b8a 100644 Binary files a/Hex Files/CR10S_BLT_UBL_MC_NF_DW7.4.6.hex.zip and b/Hex Files/CR10S_BLT_UBL_MC_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10S_BLT_UBL_ME_DW7.4.6.hex.zip b/Hex Files/CR10S_BLT_UBL_ME_DW7.4.6.hex.zip index 35ca6e0e54..bcf89e6533 100644 Binary files a/Hex Files/CR10S_BLT_UBL_ME_DW7.4.6.hex.zip and b/Hex Files/CR10S_BLT_UBL_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10S_BLT_UBL_ME_NF_DW7.4.6.hex.zip b/Hex Files/CR10S_BLT_UBL_ME_NF_DW7.4.6.hex.zip index f3f95f291d..a9becd2855 100644 Binary files a/Hex Files/CR10S_BLT_UBL_ME_NF_DW7.4.6.hex.zip and b/Hex Files/CR10S_BLT_UBL_ME_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10S_BLT_UBL_NF_DW7.4.6.hex.zip b/Hex Files/CR10S_BLT_UBL_NF_DW7.4.6.hex.zip index 045d13cfdc..27706924ea 100644 Binary files a/Hex Files/CR10S_BLT_UBL_NF_DW7.4.6.hex.zip and b/Hex Files/CR10S_BLT_UBL_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10S_BLT_UBL_NF_LR_DW7.4.6.hex.zip b/Hex Files/CR10S_BLT_UBL_NF_LR_DW7.4.6.hex.zip index de31844937..c0be631744 100644 Binary files a/Hex Files/CR10S_BLT_UBL_NF_LR_DW7.4.6.hex.zip and b/Hex Files/CR10S_BLT_UBL_NF_LR_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10S_DW7.4.6.hex.zip b/Hex Files/CR10S_DW7.4.6.hex.zip index 4b2e00d10d..0a65a81a3e 100644 Binary files a/Hex Files/CR10S_DW7.4.6.hex.zip and b/Hex Files/CR10S_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10S_LR_DW7.4.6.hex.zip b/Hex Files/CR10S_LR_DW7.4.6.hex.zip index 85c4410d21..00c0e758c2 100644 Binary files a/Hex Files/CR10S_LR_DW7.4.6.hex.zip and b/Hex Files/CR10S_LR_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10S_MC_DW7.4.6.hex.zip b/Hex Files/CR10S_MC_DW7.4.6.hex.zip index 018c5829df..40ff6212ec 100644 Binary files a/Hex Files/CR10S_MC_DW7.4.6.hex.zip and b/Hex Files/CR10S_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10S_MC_NF_DW7.4.6.hex.zip b/Hex Files/CR10S_MC_NF_DW7.4.6.hex.zip index 41caf82e63..242acccee6 100644 Binary files a/Hex Files/CR10S_MC_NF_DW7.4.6.hex.zip and b/Hex Files/CR10S_MC_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10S_ME_DW7.4.6.hex.zip b/Hex Files/CR10S_ME_DW7.4.6.hex.zip index 710e22b0d2..441ca52c31 100644 Binary files a/Hex Files/CR10S_ME_DW7.4.6.hex.zip and b/Hex Files/CR10S_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10S_ME_NF_DW7.4.6.hex.zip b/Hex Files/CR10S_ME_NF_DW7.4.6.hex.zip index b1a85f75a7..b571801fa9 100644 Binary files a/Hex Files/CR10S_ME_NF_DW7.4.6.hex.zip and b/Hex Files/CR10S_ME_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10S_NF_DW7.4.6.hex.zip b/Hex Files/CR10S_NF_DW7.4.6.hex.zip index 17f5e8e09f..7e2f961197 100644 Binary files a/Hex Files/CR10S_NF_DW7.4.6.hex.zip and b/Hex Files/CR10S_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10S_NF_LR_DW7.4.6.hex.zip b/Hex Files/CR10S_NF_LR_DW7.4.6.hex.zip index 628ffb349d..eaa0884434 100644 Binary files a/Hex Files/CR10S_NF_LR_DW7.4.6.hex.zip and b/Hex Files/CR10S_NF_LR_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10V2_BLT_DW7.4.6.hex.zip b/Hex Files/CR10V2_BLT_DW7.4.6.hex.zip index e440c4147a..28f30d97eb 100644 Binary files a/Hex Files/CR10V2_BLT_DW7.4.6.hex.zip and b/Hex Files/CR10V2_BLT_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10V2_BLT_MC_DW7.4.6.hex.zip b/Hex Files/CR10V2_BLT_MC_DW7.4.6.hex.zip index 3c811daea0..62ced13b1e 100644 Binary files a/Hex Files/CR10V2_BLT_MC_DW7.4.6.hex.zip and b/Hex Files/CR10V2_BLT_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10V2_BLT_MC_NF_DW7.4.6.hex.zip b/Hex Files/CR10V2_BLT_MC_NF_DW7.4.6.hex.zip index a766602915..63d1cbe44f 100644 Binary files a/Hex Files/CR10V2_BLT_MC_NF_DW7.4.6.hex.zip and b/Hex Files/CR10V2_BLT_MC_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10V2_BLT_ME_DW7.4.6.hex.zip b/Hex Files/CR10V2_BLT_ME_DW7.4.6.hex.zip index 9772cbfd71..7177306844 100644 Binary files a/Hex Files/CR10V2_BLT_ME_DW7.4.6.hex.zip and b/Hex Files/CR10V2_BLT_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10V2_BLT_ME_NF_DW7.4.6.hex.zip b/Hex Files/CR10V2_BLT_ME_NF_DW7.4.6.hex.zip index 0953ba61ec..da71edd835 100644 Binary files a/Hex Files/CR10V2_BLT_ME_NF_DW7.4.6.hex.zip and b/Hex Files/CR10V2_BLT_ME_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10V2_BLT_NF_DW7.4.6.hex.zip b/Hex Files/CR10V2_BLT_NF_DW7.4.6.hex.zip index e36e29b70d..dd01d7f683 100644 Binary files a/Hex Files/CR10V2_BLT_NF_DW7.4.6.hex.zip and b/Hex Files/CR10V2_BLT_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10V2_BLT_UBL_DW7.4.6.hex.zip b/Hex Files/CR10V2_BLT_UBL_DW7.4.6.hex.zip index 540ecb4beb..8d6bf17c4a 100644 Binary files a/Hex Files/CR10V2_BLT_UBL_DW7.4.6.hex.zip and b/Hex Files/CR10V2_BLT_UBL_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10V2_BLT_UBL_MC_DW7.4.6.hex.zip b/Hex Files/CR10V2_BLT_UBL_MC_DW7.4.6.hex.zip index a196fb6203..7aec8d971b 100644 Binary files a/Hex Files/CR10V2_BLT_UBL_MC_DW7.4.6.hex.zip and b/Hex Files/CR10V2_BLT_UBL_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10V2_BLT_UBL_MC_NF_DW7.4.6.hex.zip b/Hex Files/CR10V2_BLT_UBL_MC_NF_DW7.4.6.hex.zip index 9edbf3d09d..d5d06170d1 100644 Binary files a/Hex Files/CR10V2_BLT_UBL_MC_NF_DW7.4.6.hex.zip and b/Hex Files/CR10V2_BLT_UBL_MC_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10V2_BLT_UBL_ME_DW7.4.6.hex.zip b/Hex Files/CR10V2_BLT_UBL_ME_DW7.4.6.hex.zip index e26bd923c8..30dd494fff 100644 Binary files a/Hex Files/CR10V2_BLT_UBL_ME_DW7.4.6.hex.zip and b/Hex Files/CR10V2_BLT_UBL_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10V2_BLT_UBL_ME_NF_DW7.4.6.hex.zip b/Hex Files/CR10V2_BLT_UBL_ME_NF_DW7.4.6.hex.zip index abd6774bd4..00b99e4701 100644 Binary files a/Hex Files/CR10V2_BLT_UBL_ME_NF_DW7.4.6.hex.zip and b/Hex Files/CR10V2_BLT_UBL_ME_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10V2_BLT_UBL_NF_DW7.4.6.hex.zip b/Hex Files/CR10V2_BLT_UBL_NF_DW7.4.6.hex.zip index 15d96622ad..10b0725bc6 100644 Binary files a/Hex Files/CR10V2_BLT_UBL_NF_DW7.4.6.hex.zip and b/Hex Files/CR10V2_BLT_UBL_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10V2_DW7.4.6.hex.zip b/Hex Files/CR10V2_DW7.4.6.hex.zip index e8efb8bb53..68c73d44b3 100644 Binary files a/Hex Files/CR10V2_DW7.4.6.hex.zip and b/Hex Files/CR10V2_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10V2_MC_DW7.4.6.hex.zip b/Hex Files/CR10V2_MC_DW7.4.6.hex.zip index e426696b30..4d1aafde0f 100644 Binary files a/Hex Files/CR10V2_MC_DW7.4.6.hex.zip and b/Hex Files/CR10V2_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10V2_MC_NF_DW7.4.6.hex.zip b/Hex Files/CR10V2_MC_NF_DW7.4.6.hex.zip index fa6b2260ae..a2bcf5427b 100644 Binary files a/Hex Files/CR10V2_MC_NF_DW7.4.6.hex.zip and b/Hex Files/CR10V2_MC_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10V2_ME_DW7.4.6.hex.zip b/Hex Files/CR10V2_ME_DW7.4.6.hex.zip index 21b58b2126..91d7986256 100644 Binary files a/Hex Files/CR10V2_ME_DW7.4.6.hex.zip and b/Hex Files/CR10V2_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10V2_ME_NF_DW7.4.6.hex.zip b/Hex Files/CR10V2_ME_NF_DW7.4.6.hex.zip index c312fab3dd..07766acfcf 100644 Binary files a/Hex Files/CR10V2_ME_NF_DW7.4.6.hex.zip and b/Hex Files/CR10V2_ME_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10V2_NF_DW7.4.6.hex.zip b/Hex Files/CR10V2_NF_DW7.4.6.hex.zip index be3f8e71dc..80e8275639 100644 Binary files a/Hex Files/CR10V2_NF_DW7.4.6.hex.zip and b/Hex Files/CR10V2_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10V2_UBL_DW7.4.6.hex.zip b/Hex Files/CR10V2_UBL_DW7.4.6.hex.zip index b6b8d1923b..22beb484d9 100644 Binary files a/Hex Files/CR10V2_UBL_DW7.4.6.hex.zip and b/Hex Files/CR10V2_UBL_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10V2_UBL_MC_DW7.4.6.hex.zip b/Hex Files/CR10V2_UBL_MC_DW7.4.6.hex.zip index b551bae8ce..e9e7eacc1e 100644 Binary files a/Hex Files/CR10V2_UBL_MC_DW7.4.6.hex.zip and b/Hex Files/CR10V2_UBL_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10V2_UBL_MC_NF_DW7.4.6.hex.zip b/Hex Files/CR10V2_UBL_MC_NF_DW7.4.6.hex.zip index 3bf09a270d..40badba48c 100644 Binary files a/Hex Files/CR10V2_UBL_MC_NF_DW7.4.6.hex.zip and b/Hex Files/CR10V2_UBL_MC_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10V2_UBL_ME_DW7.4.6.hex.zip b/Hex Files/CR10V2_UBL_ME_DW7.4.6.hex.zip index c5a868e04e..daf0c1b2c5 100644 Binary files a/Hex Files/CR10V2_UBL_ME_DW7.4.6.hex.zip and b/Hex Files/CR10V2_UBL_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10V2_UBL_ME_NF_DW7.4.6.hex.zip b/Hex Files/CR10V2_UBL_ME_NF_DW7.4.6.hex.zip index fd66e5a027..416a2b6b4a 100644 Binary files a/Hex Files/CR10V2_UBL_ME_NF_DW7.4.6.hex.zip and b/Hex Files/CR10V2_UBL_ME_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10V2_UBL_NF_DW7.4.6.hex.zip b/Hex Files/CR10V2_UBL_NF_DW7.4.6.hex.zip index f68c9ba457..de279bc3dc 100644 Binary files a/Hex Files/CR10V2_UBL_NF_DW7.4.6.hex.zip and b/Hex Files/CR10V2_UBL_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10V3_DW7.4.6.hex.zip b/Hex Files/CR10V3_DW7.4.6.hex.zip index 00ce5b3bbd..fd196d3250 100644 Binary files a/Hex Files/CR10V3_DW7.4.6.hex.zip and b/Hex Files/CR10V3_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10_BLT_Host_DW7.4.6.hex.zip b/Hex Files/CR10_BLT_Host_DW7.4.6.hex.zip index 03afc815ae..0c58a1af1e 100644 Binary files a/Hex Files/CR10_BLT_Host_DW7.4.6.hex.zip and b/Hex Files/CR10_BLT_Host_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10_BLT_Host_MC_DW7.4.6.hex.zip b/Hex Files/CR10_BLT_Host_MC_DW7.4.6.hex.zip index 85e59bf86a..10e4a4825d 100644 Binary files a/Hex Files/CR10_BLT_Host_MC_DW7.4.6.hex.zip and b/Hex Files/CR10_BLT_Host_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10_BLT_Host_MC_NF_DW7.4.6.hex.zip b/Hex Files/CR10_BLT_Host_MC_NF_DW7.4.6.hex.zip index af3664e29f..b162873651 100644 Binary files a/Hex Files/CR10_BLT_Host_MC_NF_DW7.4.6.hex.zip and b/Hex Files/CR10_BLT_Host_MC_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10_BLT_Host_ME_DW7.4.6.hex.zip b/Hex Files/CR10_BLT_Host_ME_DW7.4.6.hex.zip index 7142435c7e..55fcaea414 100644 Binary files a/Hex Files/CR10_BLT_Host_ME_DW7.4.6.hex.zip and b/Hex Files/CR10_BLT_Host_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10_BLT_SD_DW7.4.6.hex.zip b/Hex Files/CR10_BLT_SD_DW7.4.6.hex.zip index 58ce19097f..1982c1c510 100644 Binary files a/Hex Files/CR10_BLT_SD_DW7.4.6.hex.zip and b/Hex Files/CR10_BLT_SD_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10_BLT_SD_MC_DW7.4.6.hex.zip b/Hex Files/CR10_BLT_SD_MC_DW7.4.6.hex.zip index 08fdea120e..930542f5db 100644 Binary files a/Hex Files/CR10_BLT_SD_MC_DW7.4.6.hex.zip and b/Hex Files/CR10_BLT_SD_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10_BLT_SD_MC_NF_DW7.4.6.hex.zip b/Hex Files/CR10_BLT_SD_MC_NF_DW7.4.6.hex.zip index ebf5565edd..e198af0ec8 100644 Binary files a/Hex Files/CR10_BLT_SD_MC_NF_DW7.4.6.hex.zip and b/Hex Files/CR10_BLT_SD_MC_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10_BLT_SD_ME_DW7.4.6.hex.zip b/Hex Files/CR10_BLT_SD_ME_DW7.4.6.hex.zip index 91b5e6195d..c532d114d5 100644 Binary files a/Hex Files/CR10_BLT_SD_ME_DW7.4.6.hex.zip and b/Hex Files/CR10_BLT_SD_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10_DW7.4.6.hex.zip b/Hex Files/CR10_DW7.4.6.hex.zip index 7f7ad13fca..24d158019a 100644 Binary files a/Hex Files/CR10_DW7.4.6.hex.zip and b/Hex Files/CR10_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10_MC_DW7.4.6.hex.zip b/Hex Files/CR10_MC_DW7.4.6.hex.zip index 317a461d2e..a7a747b6ed 100644 Binary files a/Hex Files/CR10_MC_DW7.4.6.hex.zip and b/Hex Files/CR10_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10_MC_NF_DW7.4.6.hex.zip b/Hex Files/CR10_MC_NF_DW7.4.6.hex.zip index f214f4a486..2018be971e 100644 Binary files a/Hex Files/CR10_MC_NF_DW7.4.6.hex.zip and b/Hex Files/CR10_MC_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR10_ME_DW7.4.6.hex.zip b/Hex Files/CR10_ME_DW7.4.6.hex.zip index bb6233fa25..904ec0a732 100644 Binary files a/Hex Files/CR10_ME_DW7.4.6.hex.zip and b/Hex Files/CR10_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR2020_DW7.4.6.hex.zip b/Hex Files/CR2020_DW7.4.6.hex.zip index 65581542ca..5a44cdf1e4 100644 Binary files a/Hex Files/CR2020_DW7.4.6.hex.zip and b/Hex Files/CR2020_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR20_BLT_DW7.4.6.hex.zip b/Hex Files/CR20_BLT_DW7.4.6.hex.zip index e192ffe386..5e59df7386 100644 Binary files a/Hex Files/CR20_BLT_DW7.4.6.hex.zip and b/Hex Files/CR20_BLT_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR20_BLT_LR_DW7.4.6.hex.zip b/Hex Files/CR20_BLT_LR_DW7.4.6.hex.zip index 89ab188ab8..acfd42fc7c 100644 Binary files a/Hex Files/CR20_BLT_LR_DW7.4.6.hex.zip and b/Hex Files/CR20_BLT_LR_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR20_BLT_MC_DW7.4.6.hex.zip b/Hex Files/CR20_BLT_MC_DW7.4.6.hex.zip index 9fcc2c1390..1a674a6d45 100644 Binary files a/Hex Files/CR20_BLT_MC_DW7.4.6.hex.zip and b/Hex Files/CR20_BLT_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR20_BLT_ME_DW7.4.6.hex.zip b/Hex Files/CR20_BLT_ME_DW7.4.6.hex.zip index 5b066301f2..ff91b66d54 100644 Binary files a/Hex Files/CR20_BLT_ME_DW7.4.6.hex.zip and b/Hex Files/CR20_BLT_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR20_BLT_UBL_DW7.4.6.hex.zip b/Hex Files/CR20_BLT_UBL_DW7.4.6.hex.zip index b03ef3660d..831e2b276f 100644 Binary files a/Hex Files/CR20_BLT_UBL_DW7.4.6.hex.zip and b/Hex Files/CR20_BLT_UBL_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR20_BLT_UBL_LR_DW7.4.6.hex.zip b/Hex Files/CR20_BLT_UBL_LR_DW7.4.6.hex.zip index 92afc6839e..4ff6df9456 100644 Binary files a/Hex Files/CR20_BLT_UBL_LR_DW7.4.6.hex.zip and b/Hex Files/CR20_BLT_UBL_LR_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR20_BLT_UBL_MC_DW7.4.6.hex.zip b/Hex Files/CR20_BLT_UBL_MC_DW7.4.6.hex.zip index 837f5f89bb..aa256be824 100644 Binary files a/Hex Files/CR20_BLT_UBL_MC_DW7.4.6.hex.zip and b/Hex Files/CR20_BLT_UBL_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR20_BLT_UBL_ME_DW7.4.6.hex.zip b/Hex Files/CR20_BLT_UBL_ME_DW7.4.6.hex.zip index 50ae11406e..fb1f98b7d1 100644 Binary files a/Hex Files/CR20_BLT_UBL_ME_DW7.4.6.hex.zip and b/Hex Files/CR20_BLT_UBL_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR20_DW7.4.6.hex.zip b/Hex Files/CR20_DW7.4.6.hex.zip index 81b70a71c3..1236895122 100644 Binary files a/Hex Files/CR20_DW7.4.6.hex.zip and b/Hex Files/CR20_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR20_LR_DW7.4.6.hex.zip b/Hex Files/CR20_LR_DW7.4.6.hex.zip index afa6477fbc..068f1da308 100644 Binary files a/Hex Files/CR20_LR_DW7.4.6.hex.zip and b/Hex Files/CR20_LR_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR20_MC_DW7.4.6.hex.zip b/Hex Files/CR20_MC_DW7.4.6.hex.zip index dbae033dfd..f161fec6de 100644 Binary files a/Hex Files/CR20_MC_DW7.4.6.hex.zip and b/Hex Files/CR20_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR20_ME_DW7.4.6.hex.zip b/Hex Files/CR20_ME_DW7.4.6.hex.zip index b173dea9b1..231d71d235 100644 Binary files a/Hex Files/CR20_ME_DW7.4.6.hex.zip and b/Hex Files/CR20_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR20_Pro_DW7.4.6.hex.zip b/Hex Files/CR20_Pro_DW7.4.6.hex.zip index 45cc4ef084..b907572474 100644 Binary files a/Hex Files/CR20_Pro_DW7.4.6.hex.zip and b/Hex Files/CR20_Pro_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR20_Pro_LR_DW7.4.6.hex.zip b/Hex Files/CR20_Pro_LR_DW7.4.6.hex.zip index c2f04f750b..6ddab2f579 100644 Binary files a/Hex Files/CR20_Pro_LR_DW7.4.6.hex.zip and b/Hex Files/CR20_Pro_LR_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR20_Pro_MC_DW7.4.6.hex.zip b/Hex Files/CR20_Pro_MC_DW7.4.6.hex.zip index cb269a2802..398fd5b4d3 100644 Binary files a/Hex Files/CR20_Pro_MC_DW7.4.6.hex.zip and b/Hex Files/CR20_Pro_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR20_Pro_ME_DW7.4.6.hex.zip b/Hex Files/CR20_Pro_ME_DW7.4.6.hex.zip index ca998768d3..86ec99cf7a 100644 Binary files a/Hex Files/CR20_Pro_ME_DW7.4.6.hex.zip and b/Hex Files/CR20_Pro_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR20_Pro_UBL_DW7.4.6.hex.zip b/Hex Files/CR20_Pro_UBL_DW7.4.6.hex.zip index bb7a00544b..aa74e170ca 100644 Binary files a/Hex Files/CR20_Pro_UBL_DW7.4.6.hex.zip and b/Hex Files/CR20_Pro_UBL_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR20_Pro_UBL_LR_DW7.4.6.hex.zip b/Hex Files/CR20_Pro_UBL_LR_DW7.4.6.hex.zip index eb6db0ea69..be5f6afc3a 100644 Binary files a/Hex Files/CR20_Pro_UBL_LR_DW7.4.6.hex.zip and b/Hex Files/CR20_Pro_UBL_LR_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR20_Pro_UBL_MC_DW7.4.6.hex.zip b/Hex Files/CR20_Pro_UBL_MC_DW7.4.6.hex.zip index 25e37125b3..8a9e40a0d2 100644 Binary files a/Hex Files/CR20_Pro_UBL_MC_DW7.4.6.hex.zip and b/Hex Files/CR20_Pro_UBL_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR20_Pro_UBL_ME_DW7.4.6.hex.zip b/Hex Files/CR20_Pro_UBL_ME_DW7.4.6.hex.zip index 49a7b53e27..851fcc39dd 100644 Binary files a/Hex Files/CR20_Pro_UBL_ME_DW7.4.6.hex.zip and b/Hex Files/CR20_Pro_UBL_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR5Pro_BLT_DW7.4.6.hex.zip b/Hex Files/CR5Pro_BLT_DW7.4.6.hex.zip index c47f0f1218..1a52a26340 100644 Binary files a/Hex Files/CR5Pro_BLT_DW7.4.6.hex.zip and b/Hex Files/CR5Pro_BLT_DW7.4.6.hex.zip differ diff --git a/Hex Files/CR5Pro_DW7.4.6.hex.zip b/Hex Files/CR5Pro_DW7.4.6.hex.zip index d781812a1c..f740cc04ab 100644 Binary files a/Hex Files/CR5Pro_DW7.4.6.hex.zip and b/Hex Files/CR5Pro_DW7.4.6.hex.zip differ diff --git a/Hex Files/CRXPro_BILNoFilMC_DW7.4.6.hex.zip b/Hex Files/CRXPro_BILNoFilMC_DW7.4.6.hex.zip index 26ef3b8e47..07b5ab7c6e 100644 Binary files a/Hex Files/CRXPro_BILNoFilMC_DW7.4.6.hex.zip and b/Hex Files/CRXPro_BILNoFilMC_DW7.4.6.hex.zip differ diff --git a/Hex Files/CRXPro_BILNoFilME_DW7.4.6.hex.zip b/Hex Files/CRXPro_BILNoFilME_DW7.4.6.hex.zip index 068e54c3c0..61656a1ed0 100644 Binary files a/Hex Files/CRXPro_BILNoFilME_DW7.4.6.hex.zip and b/Hex Files/CRXPro_BILNoFilME_DW7.4.6.hex.zip differ diff --git a/Hex Files/CRXPro_BIL_Fil_DW7.4.6.hex.zip b/Hex Files/CRXPro_BIL_Fil_DW7.4.6.hex.zip index deb133b32f..2e8dc4dded 100644 Binary files a/Hex Files/CRXPro_BIL_Fil_DW7.4.6.hex.zip and b/Hex Files/CRXPro_BIL_Fil_DW7.4.6.hex.zip differ diff --git a/Hex Files/CRXPro_BIL_Fil_MC_DW7.4.6.hex.zip b/Hex Files/CRXPro_BIL_Fil_MC_DW7.4.6.hex.zip index 6f7e91a4ae..2cb1fa062f 100644 Binary files a/Hex Files/CRXPro_BIL_Fil_MC_DW7.4.6.hex.zip and b/Hex Files/CRXPro_BIL_Fil_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/CRXPro_BIL_Fil_ME_DW7.4.6.hex.zip b/Hex Files/CRXPro_BIL_Fil_ME_DW7.4.6.hex.zip index 60ffb085a9..40022bf0b0 100644 Binary files a/Hex Files/CRXPro_BIL_Fil_ME_DW7.4.6.hex.zip and b/Hex Files/CRXPro_BIL_Fil_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/CRXPro_BIL_NoFil_DW7.4.6.hex.zip b/Hex Files/CRXPro_BIL_NoFil_DW7.4.6.hex.zip index 6bb5763237..2792ad877a 100644 Binary files a/Hex Files/CRXPro_BIL_NoFil_DW7.4.6.hex.zip and b/Hex Files/CRXPro_BIL_NoFil_DW7.4.6.hex.zip differ diff --git a/Hex Files/CRXPro_UBLNoFilMC_DW7.4.6.hex.zip b/Hex Files/CRXPro_UBLNoFilMC_DW7.4.6.hex.zip index 335cac332d..421387628f 100644 Binary files a/Hex Files/CRXPro_UBLNoFilMC_DW7.4.6.hex.zip and b/Hex Files/CRXPro_UBLNoFilMC_DW7.4.6.hex.zip differ diff --git a/Hex Files/CRXPro_UBLNoFilME_DW7.4.6.hex.zip b/Hex Files/CRXPro_UBLNoFilME_DW7.4.6.hex.zip index 07cb308b87..20dff244c4 100644 Binary files a/Hex Files/CRXPro_UBLNoFilME_DW7.4.6.hex.zip and b/Hex Files/CRXPro_UBLNoFilME_DW7.4.6.hex.zip differ diff --git a/Hex Files/CRXPro_UBL_Fil_DW7.4.6.hex.zip b/Hex Files/CRXPro_UBL_Fil_DW7.4.6.hex.zip index 0401eaf47c..46573aafd8 100644 Binary files a/Hex Files/CRXPro_UBL_Fil_DW7.4.6.hex.zip and b/Hex Files/CRXPro_UBL_Fil_DW7.4.6.hex.zip differ diff --git a/Hex Files/CRXPro_UBL_Fil_MC_DW7.4.6.hex.zip b/Hex Files/CRXPro_UBL_Fil_MC_DW7.4.6.hex.zip index a5e8c73918..152ed54d32 100644 Binary files a/Hex Files/CRXPro_UBL_Fil_MC_DW7.4.6.hex.zip and b/Hex Files/CRXPro_UBL_Fil_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/CRXPro_UBL_Fil_ME_DW7.4.6.hex.zip b/Hex Files/CRXPro_UBL_Fil_ME_DW7.4.6.hex.zip index e73d4ffa8a..62fe83faad 100644 Binary files a/Hex Files/CRXPro_UBL_Fil_ME_DW7.4.6.hex.zip and b/Hex Files/CRXPro_UBL_Fil_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/CRXPro_UBL_NoFil_DW7.4.6.hex.zip b/Hex Files/CRXPro_UBL_NoFil_DW7.4.6.hex.zip index b0d53c4eab..c617bd1589 100644 Binary files a/Hex Files/CRXPro_UBL_NoFil_DW7.4.6.hex.zip and b/Hex Files/CRXPro_UBL_NoFil_DW7.4.6.hex.zip differ diff --git a/Hex Files/CRX_BLTBILNoFilME_DW7.4.6.hex.zip b/Hex Files/CRX_BLTBILNoFilME_DW7.4.6.hex.zip index 6025efd6b8..570e023df9 100644 Binary files a/Hex Files/CRX_BLTBILNoFilME_DW7.4.6.hex.zip and b/Hex Files/CRX_BLTBILNoFilME_DW7.4.6.hex.zip differ diff --git a/Hex Files/CRX_BLTUBLNoFilME_DW7.4.6.hex.zip b/Hex Files/CRX_BLTUBLNoFilME_DW7.4.6.hex.zip index 72e7d6a4fe..5c3cbe3925 100644 Binary files a/Hex Files/CRX_BLTUBLNoFilME_DW7.4.6.hex.zip and b/Hex Files/CRX_BLTUBLNoFilME_DW7.4.6.hex.zip differ diff --git a/Hex Files/CRX_BLT_BILNoFilMC_DW7.4.6.hex.zip b/Hex Files/CRX_BLT_BILNoFilMC_DW7.4.6.hex.zip index f743e27c4b..21308e57c2 100644 Binary files a/Hex Files/CRX_BLT_BILNoFilMC_DW7.4.6.hex.zip and b/Hex Files/CRX_BLT_BILNoFilMC_DW7.4.6.hex.zip differ diff --git a/Hex Files/CRX_BLT_BIL_Fil_DW7.4.6.hex.zip b/Hex Files/CRX_BLT_BIL_Fil_DW7.4.6.hex.zip index aefe8d828a..49e9812bb0 100644 Binary files a/Hex Files/CRX_BLT_BIL_Fil_DW7.4.6.hex.zip and b/Hex Files/CRX_BLT_BIL_Fil_DW7.4.6.hex.zip differ diff --git a/Hex Files/CRX_BLT_BIL_Fil_MC_DW7.4.6.hex.zip b/Hex Files/CRX_BLT_BIL_Fil_MC_DW7.4.6.hex.zip index 8506b71f46..2b2b7ad0ec 100644 Binary files a/Hex Files/CRX_BLT_BIL_Fil_MC_DW7.4.6.hex.zip and b/Hex Files/CRX_BLT_BIL_Fil_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/CRX_BLT_BIL_Fil_ME_DW7.4.6.hex.zip b/Hex Files/CRX_BLT_BIL_Fil_ME_DW7.4.6.hex.zip index 4d6c1b458c..162aa3adca 100644 Binary files a/Hex Files/CRX_BLT_BIL_Fil_ME_DW7.4.6.hex.zip and b/Hex Files/CRX_BLT_BIL_Fil_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/CRX_BLT_BIL_NoFil_DW7.4.6.hex.zip b/Hex Files/CRX_BLT_BIL_NoFil_DW7.4.6.hex.zip index 9c2f62ddc5..b49a2c633f 100644 Binary files a/Hex Files/CRX_BLT_BIL_NoFil_DW7.4.6.hex.zip and b/Hex Files/CRX_BLT_BIL_NoFil_DW7.4.6.hex.zip differ diff --git a/Hex Files/CRX_BLT_UBLNoFilMC_DW7.4.6.hex.zip b/Hex Files/CRX_BLT_UBLNoFilMC_DW7.4.6.hex.zip index 6f67d377b8..72b48d9205 100644 Binary files a/Hex Files/CRX_BLT_UBLNoFilMC_DW7.4.6.hex.zip and b/Hex Files/CRX_BLT_UBLNoFilMC_DW7.4.6.hex.zip differ diff --git a/Hex Files/CRX_BLT_UBL_Fil_DW7.4.6.hex.zip b/Hex Files/CRX_BLT_UBL_Fil_DW7.4.6.hex.zip index aceb79bb75..29ffca7961 100644 Binary files a/Hex Files/CRX_BLT_UBL_Fil_DW7.4.6.hex.zip and b/Hex Files/CRX_BLT_UBL_Fil_DW7.4.6.hex.zip differ diff --git a/Hex Files/CRX_BLT_UBL_Fil_MC_DW7.4.6.hex.zip b/Hex Files/CRX_BLT_UBL_Fil_MC_DW7.4.6.hex.zip index 799c46afa7..6229ae7f0e 100644 Binary files a/Hex Files/CRX_BLT_UBL_Fil_MC_DW7.4.6.hex.zip and b/Hex Files/CRX_BLT_UBL_Fil_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/CRX_BLT_UBL_Fil_ME_DW7.4.6.hex.zip b/Hex Files/CRX_BLT_UBL_Fil_ME_DW7.4.6.hex.zip index ce35ccfa75..553408c568 100644 Binary files a/Hex Files/CRX_BLT_UBL_Fil_ME_DW7.4.6.hex.zip and b/Hex Files/CRX_BLT_UBL_Fil_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/CRX_BLT_UBL_NoFil_DW7.4.6.hex.zip b/Hex Files/CRX_BLT_UBL_NoFil_DW7.4.6.hex.zip index 712dac9e3b..dfc2f310d6 100644 Binary files a/Hex Files/CRX_BLT_UBL_NoFil_DW7.4.6.hex.zip and b/Hex Files/CRX_BLT_UBL_NoFil_DW7.4.6.hex.zip differ diff --git a/Hex Files/CRX_Fil_DW7.4.6.hex.zip b/Hex Files/CRX_Fil_DW7.4.6.hex.zip index 82d8cb150f..37a3e575ea 100644 Binary files a/Hex Files/CRX_Fil_DW7.4.6.hex.zip and b/Hex Files/CRX_Fil_DW7.4.6.hex.zip differ diff --git a/Hex Files/CRX_Fil_MC_DW7.4.6.hex.zip b/Hex Files/CRX_Fil_MC_DW7.4.6.hex.zip index be540b7e00..268d34b57b 100644 Binary files a/Hex Files/CRX_Fil_MC_DW7.4.6.hex.zip and b/Hex Files/CRX_Fil_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/CRX_Fil_ME_DW7.4.6.hex.zip b/Hex Files/CRX_Fil_ME_DW7.4.6.hex.zip index fd37d6741c..ea9326334d 100644 Binary files a/Hex Files/CRX_Fil_ME_DW7.4.6.hex.zip and b/Hex Files/CRX_Fil_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/CRX_NoFil_DW7.4.6.hex.zip b/Hex Files/CRX_NoFil_DW7.4.6.hex.zip index d7066994ea..a0eba5bd77 100644 Binary files a/Hex Files/CRX_NoFil_DW7.4.6.hex.zip and b/Hex Files/CRX_NoFil_DW7.4.6.hex.zip differ diff --git a/Hex Files/CRX_NoFil_MC_DW7.4.6.hex.zip b/Hex Files/CRX_NoFil_MC_DW7.4.6.hex.zip index 4534cee7b7..017da3a2d1 100644 Binary files a/Hex Files/CRX_NoFil_MC_DW7.4.6.hex.zip and b/Hex Files/CRX_NoFil_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/CRX_NoFil_ME_DW7.4.6.hex.zip b/Hex Files/CRX_NoFil_ME_DW7.4.6.hex.zip index 192abb26be..785ce23bb1 100644 Binary files a/Hex Files/CRX_NoFil_ME_DW7.4.6.hex.zip and b/Hex Files/CRX_NoFil_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/E5PBILSlntDZH_DW7.4.6.hex.zip b/Hex Files/E5PBILSlntDZH_DW7.4.6.hex.zip index c6ef5bd12d..501a8c7c88 100644 Binary files a/Hex Files/E5PBILSlntDZH_DW7.4.6.hex.zip and b/Hex Files/E5PBILSlntDZH_DW7.4.6.hex.zip differ diff --git a/Hex Files/E5PBILSlntDZ_DW7.4.6.hex.zip b/Hex Files/E5PBILSlntDZ_DW7.4.6.hex.zip index b6b748b1b9..e38a2a153c 100644 Binary files a/Hex Files/E5PBILSlntDZ_DW7.4.6.hex.zip and b/Hex Files/E5PBILSlntDZ_DW7.4.6.hex.zip differ diff --git a/Hex Files/E5PBILSlntDZ_MC_DW7.4.6.hex.zip b/Hex Files/E5PBILSlntDZ_MC_DW7.4.6.hex.zip index c8dfef720d..ce1c6ace23 100644 Binary files a/Hex Files/E5PBILSlntDZ_MC_DW7.4.6.hex.zip and b/Hex Files/E5PBILSlntDZ_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/E5PBILSlntDZ_ME_DW7.4.6.hex.zip b/Hex Files/E5PBILSlntDZ_ME_DW7.4.6.hex.zip index b89a4d4c4c..c5dc277b3b 100644 Binary files a/Hex Files/E5PBILSlntDZ_ME_DW7.4.6.hex.zip and b/Hex Files/E5PBILSlntDZ_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/E5PUBLSlntDZH_DW7.4.6.hex.zip b/Hex Files/E5PUBLSlntDZH_DW7.4.6.hex.zip index 310b80fd20..17992d44a4 100644 Binary files a/Hex Files/E5PUBLSlntDZH_DW7.4.6.hex.zip and b/Hex Files/E5PUBLSlntDZH_DW7.4.6.hex.zip differ diff --git a/Hex Files/E5PUBLSlntDZ_DW7.4.6.hex.zip b/Hex Files/E5PUBLSlntDZ_DW7.4.6.hex.zip index 0c90094d3c..53a4f6eb54 100644 Binary files a/Hex Files/E5PUBLSlntDZ_DW7.4.6.hex.zip and b/Hex Files/E5PUBLSlntDZ_DW7.4.6.hex.zip differ diff --git a/Hex Files/E5PUBLSlntDZ_MC_DW7.4.6.hex.zip b/Hex Files/E5PUBLSlntDZ_MC_DW7.4.6.hex.zip index 36433db527..1fb22d2412 100644 Binary files a/Hex Files/E5PUBLSlntDZ_MC_DW7.4.6.hex.zip and b/Hex Files/E5PUBLSlntDZ_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/E5PUBLSlntDZ_ME_DW7.4.6.hex.zip b/Hex Files/E5PUBLSlntDZ_ME_DW7.4.6.hex.zip index 173833d34e..f9802d34a9 100644 Binary files a/Hex Files/E5PUBLSlntDZ_ME_DW7.4.6.hex.zip and b/Hex Files/E5PUBLSlntDZ_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/E5P_BILH_DW7.4.6.hex.zip b/Hex Files/E5P_BILH_DW7.4.6.hex.zip index 8e3796b45b..89a5337295 100644 Binary files a/Hex Files/E5P_BILH_DW7.4.6.hex.zip and b/Hex Files/E5P_BILH_DW7.4.6.hex.zip differ diff --git a/Hex Files/E5P_BIL_DW7.4.6.hex.zip b/Hex Files/E5P_BIL_DW7.4.6.hex.zip index d35ee09e9b..306bbf2367 100644 Binary files a/Hex Files/E5P_BIL_DW7.4.6.hex.zip and b/Hex Files/E5P_BIL_DW7.4.6.hex.zip differ diff --git a/Hex Files/E5P_BIL_DZH_DW7.4.6.hex.zip b/Hex Files/E5P_BIL_DZH_DW7.4.6.hex.zip index dc31b25e7a..804515855b 100644 Binary files a/Hex Files/E5P_BIL_DZH_DW7.4.6.hex.zip and b/Hex Files/E5P_BIL_DZH_DW7.4.6.hex.zip differ diff --git a/Hex Files/E5P_BIL_DZ_DW7.4.6.hex.zip b/Hex Files/E5P_BIL_DZ_DW7.4.6.hex.zip index 04f0542dab..3e6db86402 100644 Binary files a/Hex Files/E5P_BIL_DZ_DW7.4.6.hex.zip and b/Hex Files/E5P_BIL_DZ_DW7.4.6.hex.zip differ diff --git a/Hex Files/E5P_BIL_DZ_MC_DW7.4.6.hex.zip b/Hex Files/E5P_BIL_DZ_MC_DW7.4.6.hex.zip index da7b0c5522..afdeece140 100644 Binary files a/Hex Files/E5P_BIL_DZ_MC_DW7.4.6.hex.zip and b/Hex Files/E5P_BIL_DZ_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/E5P_BIL_DZ_ME_DW7.4.6.hex.zip b/Hex Files/E5P_BIL_DZ_ME_DW7.4.6.hex.zip index d979287d1c..cd2844a8af 100644 Binary files a/Hex Files/E5P_BIL_DZ_ME_DW7.4.6.hex.zip and b/Hex Files/E5P_BIL_DZ_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/E5P_BIL_MC_DW7.4.6.hex.zip b/Hex Files/E5P_BIL_MC_DW7.4.6.hex.zip index 67ae87471a..e1d4a9fae1 100644 Binary files a/Hex Files/E5P_BIL_MC_DW7.4.6.hex.zip and b/Hex Files/E5P_BIL_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/E5P_BIL_ME_DW7.4.6.hex.zip b/Hex Files/E5P_BIL_ME_DW7.4.6.hex.zip index 403913a8cf..d2d7a3cb3b 100644 Binary files a/Hex Files/E5P_BIL_ME_DW7.4.6.hex.zip and b/Hex Files/E5P_BIL_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/E5P_BIL_SlntH_DW7.4.6.hex.zip b/Hex Files/E5P_BIL_SlntH_DW7.4.6.hex.zip index d52a7eb414..e0f88a38a1 100644 Binary files a/Hex Files/E5P_BIL_SlntH_DW7.4.6.hex.zip and b/Hex Files/E5P_BIL_SlntH_DW7.4.6.hex.zip differ diff --git a/Hex Files/E5P_BIL_Slnt_DW7.4.6.hex.zip b/Hex Files/E5P_BIL_Slnt_DW7.4.6.hex.zip index 55cd451b30..efabe72720 100644 Binary files a/Hex Files/E5P_BIL_Slnt_DW7.4.6.hex.zip and b/Hex Files/E5P_BIL_Slnt_DW7.4.6.hex.zip differ diff --git a/Hex Files/E5P_BIL_Slnt_MC_DW7.4.6.hex.zip b/Hex Files/E5P_BIL_Slnt_MC_DW7.4.6.hex.zip index bd4f6ce6d1..b07c50bf84 100644 Binary files a/Hex Files/E5P_BIL_Slnt_MC_DW7.4.6.hex.zip and b/Hex Files/E5P_BIL_Slnt_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/E5P_BIL_Slnt_ME_DW7.4.6.hex.zip b/Hex Files/E5P_BIL_Slnt_ME_DW7.4.6.hex.zip index 3a0815d4a8..6153f98cf9 100644 Binary files a/Hex Files/E5P_BIL_Slnt_ME_DW7.4.6.hex.zip and b/Hex Files/E5P_BIL_Slnt_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/E5P_UBLH_DW7.4.6.hex.zip b/Hex Files/E5P_UBLH_DW7.4.6.hex.zip index 295cd52897..16fef5b5a9 100644 Binary files a/Hex Files/E5P_UBLH_DW7.4.6.hex.zip and b/Hex Files/E5P_UBLH_DW7.4.6.hex.zip differ diff --git a/Hex Files/E5P_UBL_DW7.4.6.hex.zip b/Hex Files/E5P_UBL_DW7.4.6.hex.zip index c92597711e..99a91921c6 100644 Binary files a/Hex Files/E5P_UBL_DW7.4.6.hex.zip and b/Hex Files/E5P_UBL_DW7.4.6.hex.zip differ diff --git a/Hex Files/E5P_UBL_DZH_DW7.4.6.hex.zip b/Hex Files/E5P_UBL_DZH_DW7.4.6.hex.zip index f2c8b76c36..4f17b767bc 100644 Binary files a/Hex Files/E5P_UBL_DZH_DW7.4.6.hex.zip and b/Hex Files/E5P_UBL_DZH_DW7.4.6.hex.zip differ diff --git a/Hex Files/E5P_UBL_DZ_DW7.4.6.hex.zip b/Hex Files/E5P_UBL_DZ_DW7.4.6.hex.zip index cd01be29b3..cbea235ed0 100644 Binary files a/Hex Files/E5P_UBL_DZ_DW7.4.6.hex.zip and b/Hex Files/E5P_UBL_DZ_DW7.4.6.hex.zip differ diff --git a/Hex Files/E5P_UBL_DZ_MC_DW7.4.6.hex.zip b/Hex Files/E5P_UBL_DZ_MC_DW7.4.6.hex.zip index e4e1226776..9af2a6d60c 100644 Binary files a/Hex Files/E5P_UBL_DZ_MC_DW7.4.6.hex.zip and b/Hex Files/E5P_UBL_DZ_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/E5P_UBL_DZ_ME_DW7.4.6.hex.zip b/Hex Files/E5P_UBL_DZ_ME_DW7.4.6.hex.zip index 3b0a6b53d1..a0b26ffe1b 100644 Binary files a/Hex Files/E5P_UBL_DZ_ME_DW7.4.6.hex.zip and b/Hex Files/E5P_UBL_DZ_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/E5P_UBL_MC_DW7.4.6.hex.zip b/Hex Files/E5P_UBL_MC_DW7.4.6.hex.zip index fe99e82b24..53604c426e 100644 Binary files a/Hex Files/E5P_UBL_MC_DW7.4.6.hex.zip and b/Hex Files/E5P_UBL_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/E5P_UBL_ME_DW7.4.6.hex.zip b/Hex Files/E5P_UBL_ME_DW7.4.6.hex.zip index 839754f2bc..1f9784dc01 100644 Binary files a/Hex Files/E5P_UBL_ME_DW7.4.6.hex.zip and b/Hex Files/E5P_UBL_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/E5P_UBL_SlntH_DW7.4.6.hex.zip b/Hex Files/E5P_UBL_SlntH_DW7.4.6.hex.zip index 24065a7205..b7aaea3179 100644 Binary files a/Hex Files/E5P_UBL_SlntH_DW7.4.6.hex.zip and b/Hex Files/E5P_UBL_SlntH_DW7.4.6.hex.zip differ diff --git a/Hex Files/E5P_UBL_Slnt_DW7.4.6.hex.zip b/Hex Files/E5P_UBL_Slnt_DW7.4.6.hex.zip index c5ccfc6bac..f393e0b956 100644 Binary files a/Hex Files/E5P_UBL_Slnt_DW7.4.6.hex.zip and b/Hex Files/E5P_UBL_Slnt_DW7.4.6.hex.zip differ diff --git a/Hex Files/E5P_UBL_Slnt_MC_DW7.4.6.hex.zip b/Hex Files/E5P_UBL_Slnt_MC_DW7.4.6.hex.zip index 9d2d36cf77..4d17605797 100644 Binary files a/Hex Files/E5P_UBL_Slnt_MC_DW7.4.6.hex.zip and b/Hex Files/E5P_UBL_Slnt_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/E5P_UBL_Slnt_ME_DW7.4.6.hex.zip b/Hex Files/E5P_UBL_Slnt_ME_DW7.4.6.hex.zip index 50ba95ada9..7fc1470e96 100644 Binary files a/Hex Files/E5P_UBL_Slnt_ME_DW7.4.6.hex.zip and b/Hex Files/E5P_UBL_Slnt_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/Ender2_BLT_Host_DW7.4.6.hex.zip b/Hex Files/Ender2_BLT_Host_DW7.4.6.hex.zip index 72a347a5a4..dec2edc860 100644 Binary files a/Hex Files/Ender2_BLT_Host_DW7.4.6.hex.zip and b/Hex Files/Ender2_BLT_Host_DW7.4.6.hex.zip differ diff --git a/Hex Files/Ender2_BLT_Host_MC_DW7.4.6.hex.zip b/Hex Files/Ender2_BLT_Host_MC_DW7.4.6.hex.zip index e4eb2de095..05a6b4611b 100644 Binary files a/Hex Files/Ender2_BLT_Host_MC_DW7.4.6.hex.zip and b/Hex Files/Ender2_BLT_Host_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/Ender2_BLT_Host_ME_DW7.4.6.hex.zip b/Hex Files/Ender2_BLT_Host_ME_DW7.4.6.hex.zip index bee31b4ab7..3b3251a928 100644 Binary files a/Hex Files/Ender2_BLT_Host_ME_DW7.4.6.hex.zip and b/Hex Files/Ender2_BLT_Host_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/Ender2_BLT_SD_DW7.4.6.hex.zip b/Hex Files/Ender2_BLT_SD_DW7.4.6.hex.zip index 037b66e9c4..5041ee3782 100644 Binary files a/Hex Files/Ender2_BLT_SD_DW7.4.6.hex.zip and b/Hex Files/Ender2_BLT_SD_DW7.4.6.hex.zip differ diff --git a/Hex Files/Ender2_BLT_SD_MC_DW7.4.6.hex.zip b/Hex Files/Ender2_BLT_SD_MC_DW7.4.6.hex.zip index a7771e53c7..505482459f 100644 Binary files a/Hex Files/Ender2_BLT_SD_MC_DW7.4.6.hex.zip and b/Hex Files/Ender2_BLT_SD_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/Ender2_BLT_SD_ME_DW7.4.6.hex.zip b/Hex Files/Ender2_BLT_SD_ME_DW7.4.6.hex.zip index 1178a57095..b12b5d6b46 100644 Binary files a/Hex Files/Ender2_BLT_SD_ME_DW7.4.6.hex.zip and b/Hex Files/Ender2_BLT_SD_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/Ender2_DW7.4.6.hex.zip b/Hex Files/Ender2_DW7.4.6.hex.zip index 5cdc29a048..bd535c5c0a 100644 Binary files a/Hex Files/Ender2_DW7.4.6.hex.zip and b/Hex Files/Ender2_DW7.4.6.hex.zip differ diff --git a/Hex Files/Ender2_MC_DW7.4.6.hex.zip b/Hex Files/Ender2_MC_DW7.4.6.hex.zip index f5c9352468..eddc4d6ba5 100644 Binary files a/Hex Files/Ender2_MC_DW7.4.6.hex.zip and b/Hex Files/Ender2_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/Ender2_ME_DW7.4.6.hex.zip b/Hex Files/Ender2_ME_DW7.4.6.hex.zip index a683b6bacb..06869087e1 100644 Binary files a/Hex Files/Ender2_ME_DW7.4.6.hex.zip and b/Hex Files/Ender2_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/Ender3_BLT_Host_DW7.4.6.hex.zip b/Hex Files/Ender3_BLT_Host_DW7.4.6.hex.zip index 0ce7e24985..b157e2b86b 100644 Binary files a/Hex Files/Ender3_BLT_Host_DW7.4.6.hex.zip and b/Hex Files/Ender3_BLT_Host_DW7.4.6.hex.zip differ diff --git a/Hex Files/Ender3_BLT_Host_MC_DW7.4.6.hex.zip b/Hex Files/Ender3_BLT_Host_MC_DW7.4.6.hex.zip index 67179313b9..1fc09e372c 100644 Binary files a/Hex Files/Ender3_BLT_Host_MC_DW7.4.6.hex.zip and b/Hex Files/Ender3_BLT_Host_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/Ender3_BLT_Host_ME_DW7.4.6.hex.zip b/Hex Files/Ender3_BLT_Host_ME_DW7.4.6.hex.zip index fa65834218..65c0280f02 100644 Binary files a/Hex Files/Ender3_BLT_Host_ME_DW7.4.6.hex.zip and b/Hex Files/Ender3_BLT_Host_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/Ender3_BLT_SD_DW7.4.6.hex.zip b/Hex Files/Ender3_BLT_SD_DW7.4.6.hex.zip index 4c977940e4..b68c456559 100644 Binary files a/Hex Files/Ender3_BLT_SD_DW7.4.6.hex.zip and b/Hex Files/Ender3_BLT_SD_DW7.4.6.hex.zip differ diff --git a/Hex Files/Ender3_BLT_SD_MC_DW7.4.6.hex.zip b/Hex Files/Ender3_BLT_SD_MC_DW7.4.6.hex.zip index 5e617c432c..e22f32c3ba 100644 Binary files a/Hex Files/Ender3_BLT_SD_MC_DW7.4.6.hex.zip and b/Hex Files/Ender3_BLT_SD_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/Ender3_BLT_SD_ME_DW7.4.6.hex.zip b/Hex Files/Ender3_BLT_SD_ME_DW7.4.6.hex.zip index 3f817f5991..9a585a9035 100644 Binary files a/Hex Files/Ender3_BLT_SD_ME_DW7.4.6.hex.zip and b/Hex Files/Ender3_BLT_SD_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/Ender3_DW7.4.6.hex.zip b/Hex Files/Ender3_DW7.4.6.hex.zip index 888d2fef6a..fd1d55bd2f 100644 Binary files a/Hex Files/Ender3_DW7.4.6.hex.zip and b/Hex Files/Ender3_DW7.4.6.hex.zip differ diff --git a/Hex Files/Ender3_MC_DW7.4.6.hex.zip b/Hex Files/Ender3_MC_DW7.4.6.hex.zip index 84fc39adeb..18ac4aa8a3 100644 Binary files a/Hex Files/Ender3_MC_DW7.4.6.hex.zip and b/Hex Files/Ender3_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/Ender3_ME_DW7.4.6.hex.zip b/Hex Files/Ender3_ME_DW7.4.6.hex.zip index d711e8314e..aa29dff64a 100644 Binary files a/Hex Files/Ender3_ME_DW7.4.6.hex.zip and b/Hex Files/Ender3_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/Ender4_BLT_DW7.4.6.hex.zip b/Hex Files/Ender4_BLT_DW7.4.6.hex.zip index 8746aa7a8c..39089405fa 100644 Binary files a/Hex Files/Ender4_BLT_DW7.4.6.hex.zip and b/Hex Files/Ender4_BLT_DW7.4.6.hex.zip differ diff --git a/Hex Files/Ender4_BLT_MC_DW7.4.6.hex.zip b/Hex Files/Ender4_BLT_MC_DW7.4.6.hex.zip index 1240795db6..f67b844043 100644 Binary files a/Hex Files/Ender4_BLT_MC_DW7.4.6.hex.zip and b/Hex Files/Ender4_BLT_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/Ender4_BLT_ME_DW7.4.6.hex.zip b/Hex Files/Ender4_BLT_ME_DW7.4.6.hex.zip index 8e0323a3ca..28b56f73ee 100644 Binary files a/Hex Files/Ender4_BLT_ME_DW7.4.6.hex.zip and b/Hex Files/Ender4_BLT_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/Ender4_BLT_UBL_DW7.4.6.hex.zip b/Hex Files/Ender4_BLT_UBL_DW7.4.6.hex.zip index 9771478b41..0a771e0338 100644 Binary files a/Hex Files/Ender4_BLT_UBL_DW7.4.6.hex.zip and b/Hex Files/Ender4_BLT_UBL_DW7.4.6.hex.zip differ diff --git a/Hex Files/Ender4_BLT_UBL_MC_DW7.4.6.hex.zip b/Hex Files/Ender4_BLT_UBL_MC_DW7.4.6.hex.zip index 8be1f76601..7a266298f7 100644 Binary files a/Hex Files/Ender4_BLT_UBL_MC_DW7.4.6.hex.zip and b/Hex Files/Ender4_BLT_UBL_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/Ender4_BLT_UBL_ME_DW7.4.6.hex.zip b/Hex Files/Ender4_BLT_UBL_ME_DW7.4.6.hex.zip index 6649585b35..ee9c41facc 100644 Binary files a/Hex Files/Ender4_BLT_UBL_ME_DW7.4.6.hex.zip and b/Hex Files/Ender4_BLT_UBL_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/Ender4_DW7.4.6.hex.zip b/Hex Files/Ender4_DW7.4.6.hex.zip index 81be166bca..d2032aa429 100644 Binary files a/Hex Files/Ender4_DW7.4.6.hex.zip and b/Hex Files/Ender4_DW7.4.6.hex.zip differ diff --git a/Hex Files/Ender4_MC_DW7.4.6.hex.zip b/Hex Files/Ender4_MC_DW7.4.6.hex.zip index 93e13649d0..1f28c8a904 100644 Binary files a/Hex Files/Ender4_MC_DW7.4.6.hex.zip and b/Hex Files/Ender4_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/Ender4_ME_DW7.4.6.hex.zip b/Hex Files/Ender4_ME_DW7.4.6.hex.zip index c5a60615ca..ded052d6ce 100644 Binary files a/Hex Files/Ender4_ME_DW7.4.6.hex.zip and b/Hex Files/Ender4_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/Ender5_BLT_Host_DW7.4.6.hex.zip b/Hex Files/Ender5_BLT_Host_DW7.4.6.hex.zip index 669c780af6..2e4d3d0d6c 100644 Binary files a/Hex Files/Ender5_BLT_Host_DW7.4.6.hex.zip and b/Hex Files/Ender5_BLT_Host_DW7.4.6.hex.zip differ diff --git a/Hex Files/Ender5_BLT_Host_MC_DW7.4.6.hex.zip b/Hex Files/Ender5_BLT_Host_MC_DW7.4.6.hex.zip index be50678176..c5f91125be 100644 Binary files a/Hex Files/Ender5_BLT_Host_MC_DW7.4.6.hex.zip and b/Hex Files/Ender5_BLT_Host_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/Ender5_BLT_Host_ME_DW7.4.6.hex.zip b/Hex Files/Ender5_BLT_Host_ME_DW7.4.6.hex.zip index 49e92d5a1b..c2ba780c8a 100644 Binary files a/Hex Files/Ender5_BLT_Host_ME_DW7.4.6.hex.zip and b/Hex Files/Ender5_BLT_Host_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/Ender5_BLT_SD_DW7.4.6.hex.zip b/Hex Files/Ender5_BLT_SD_DW7.4.6.hex.zip index 82b65d6d91..7e45da8ab3 100644 Binary files a/Hex Files/Ender5_BLT_SD_DW7.4.6.hex.zip and b/Hex Files/Ender5_BLT_SD_DW7.4.6.hex.zip differ diff --git a/Hex Files/Ender5_BLT_SD_MC_DW7.4.6.hex.zip b/Hex Files/Ender5_BLT_SD_MC_DW7.4.6.hex.zip index 919c532121..17f37a9f6a 100644 Binary files a/Hex Files/Ender5_BLT_SD_MC_DW7.4.6.hex.zip and b/Hex Files/Ender5_BLT_SD_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/Ender5_BLT_SD_ME_DW7.4.6.hex.zip b/Hex Files/Ender5_BLT_SD_ME_DW7.4.6.hex.zip index 843fa28038..246f36d111 100644 Binary files a/Hex Files/Ender5_BLT_SD_ME_DW7.4.6.hex.zip and b/Hex Files/Ender5_BLT_SD_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/Ender5_DW7.4.6.hex.zip b/Hex Files/Ender5_DW7.4.6.hex.zip index 86ca672da6..82dbb5e81e 100644 Binary files a/Hex Files/Ender5_DW7.4.6.hex.zip and b/Hex Files/Ender5_DW7.4.6.hex.zip differ diff --git a/Hex Files/Ender5_MC_DW7.4.6.hex.zip b/Hex Files/Ender5_MC_DW7.4.6.hex.zip index ac57ef2717..a69a4b9703 100644 Binary files a/Hex Files/Ender5_MC_DW7.4.6.hex.zip and b/Hex Files/Ender5_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/Ender5_ME_DW7.4.6.hex.zip b/Hex Files/Ender5_ME_DW7.4.6.hex.zip index cadb501d0b..0abe4601c7 100644 Binary files a/Hex Files/Ender5_ME_DW7.4.6.hex.zip and b/Hex Files/Ender5_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_AC_DW7.4.6.hex.zip b/Hex Files/S4_AC_DW7.4.6.hex.zip index 42015ea500..cfb1380de0 100644 Binary files a/Hex Files/S4_AC_DW7.4.6.hex.zip and b/Hex Files/S4_AC_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_AC_LR_DW7.4.6.hex.zip b/Hex Files/S4_AC_LR_DW7.4.6.hex.zip index 8417bbeba4..cbcd7d518a 100644 Binary files a/Hex Files/S4_AC_LR_DW7.4.6.hex.zip and b/Hex Files/S4_AC_LR_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_AC_MC_DW7.4.6.hex.zip b/Hex Files/S4_AC_MC_DW7.4.6.hex.zip index 615a256525..251a71f0a6 100644 Binary files a/Hex Files/S4_AC_MC_DW7.4.6.hex.zip and b/Hex Files/S4_AC_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_AC_MC_NF_DW7.4.6.hex.zip b/Hex Files/S4_AC_MC_NF_DW7.4.6.hex.zip index c92a944d95..98cf540139 100644 Binary files a/Hex Files/S4_AC_MC_NF_DW7.4.6.hex.zip and b/Hex Files/S4_AC_MC_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_AC_ME_DW7.4.6.hex.zip b/Hex Files/S4_AC_ME_DW7.4.6.hex.zip index 14e1a99a04..aba4e2b338 100644 Binary files a/Hex Files/S4_AC_ME_DW7.4.6.hex.zip and b/Hex Files/S4_AC_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_AC_ME_NF_DW7.4.6.hex.zip b/Hex Files/S4_AC_ME_NF_DW7.4.6.hex.zip index b1bb8629d5..decc1e6cb5 100644 Binary files a/Hex Files/S4_AC_ME_NF_DW7.4.6.hex.zip and b/Hex Files/S4_AC_ME_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_AC_NF_DW7.4.6.hex.zip b/Hex Files/S4_AC_NF_DW7.4.6.hex.zip index 3373f4c4d2..0ad68b7707 100644 Binary files a/Hex Files/S4_AC_NF_DW7.4.6.hex.zip and b/Hex Files/S4_AC_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_AC_NF_LR_DW7.4.6.hex.zip b/Hex Files/S4_AC_NF_LR_DW7.4.6.hex.zip index 6a0fb620dd..c8050b828a 100644 Binary files a/Hex Files/S4_AC_NF_LR_DW7.4.6.hex.zip and b/Hex Files/S4_AC_NF_LR_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_BLT_AC_DW7.4.6.hex.zip b/Hex Files/S4_BLT_AC_DW7.4.6.hex.zip index 7e5a4355c4..4da2284df8 100644 Binary files a/Hex Files/S4_BLT_AC_DW7.4.6.hex.zip and b/Hex Files/S4_BLT_AC_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_BLT_AC_LR_DW7.4.6.hex.zip b/Hex Files/S4_BLT_AC_LR_DW7.4.6.hex.zip index c2d6e898a8..e0d26dac33 100644 Binary files a/Hex Files/S4_BLT_AC_LR_DW7.4.6.hex.zip and b/Hex Files/S4_BLT_AC_LR_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_BLT_AC_MC_DW7.4.6.hex.zip b/Hex Files/S4_BLT_AC_MC_DW7.4.6.hex.zip index 93754f7577..6e69c8820e 100644 Binary files a/Hex Files/S4_BLT_AC_MC_DW7.4.6.hex.zip and b/Hex Files/S4_BLT_AC_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_BLT_AC_MC_NF_DW7.4.6.hex.zip b/Hex Files/S4_BLT_AC_MC_NF_DW7.4.6.hex.zip index 55b13bad8d..385dbb4b92 100644 Binary files a/Hex Files/S4_BLT_AC_MC_NF_DW7.4.6.hex.zip and b/Hex Files/S4_BLT_AC_MC_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_BLT_AC_ME_DW7.4.6.hex.zip b/Hex Files/S4_BLT_AC_ME_DW7.4.6.hex.zip index 1d17be220a..f107e7e605 100644 Binary files a/Hex Files/S4_BLT_AC_ME_DW7.4.6.hex.zip and b/Hex Files/S4_BLT_AC_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_BLT_AC_ME_NF_DW7.4.6.hex.zip b/Hex Files/S4_BLT_AC_ME_NF_DW7.4.6.hex.zip index ab2ef10255..43f5ed0b0e 100644 Binary files a/Hex Files/S4_BLT_AC_ME_NF_DW7.4.6.hex.zip and b/Hex Files/S4_BLT_AC_ME_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_BLT_AC_NF_DW7.4.6.hex.zip b/Hex Files/S4_BLT_AC_NF_DW7.4.6.hex.zip index 1aa0288665..d2291408f3 100644 Binary files a/Hex Files/S4_BLT_AC_NF_DW7.4.6.hex.zip and b/Hex Files/S4_BLT_AC_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_BLT_AC_NF_LR_DW7.4.6.hex.zip b/Hex Files/S4_BLT_AC_NF_LR_DW7.4.6.hex.zip index f83bfe52e5..b2f4ec9c54 100644 Binary files a/Hex Files/S4_BLT_AC_NF_LR_DW7.4.6.hex.zip and b/Hex Files/S4_BLT_AC_NF_LR_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_BLT_AC_UBL_DW7.4.6.hex.zip b/Hex Files/S4_BLT_AC_UBL_DW7.4.6.hex.zip index 7b8dde4b8e..f66fbc4362 100644 Binary files a/Hex Files/S4_BLT_AC_UBL_DW7.4.6.hex.zip and b/Hex Files/S4_BLT_AC_UBL_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_BLT_AC_UBL_LR_DW7.4.6.hex.zip b/Hex Files/S4_BLT_AC_UBL_LR_DW7.4.6.hex.zip index 2838f3a3ff..b3d459d68a 100644 Binary files a/Hex Files/S4_BLT_AC_UBL_LR_DW7.4.6.hex.zip and b/Hex Files/S4_BLT_AC_UBL_LR_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_BLT_AC_UBL_MC_DW7.4.6.hex.zip b/Hex Files/S4_BLT_AC_UBL_MC_DW7.4.6.hex.zip index 73af35ca0a..f9f16bbd38 100644 Binary files a/Hex Files/S4_BLT_AC_UBL_MC_DW7.4.6.hex.zip and b/Hex Files/S4_BLT_AC_UBL_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_BLT_AC_UBL_MC_NF_DW7.4.6.hex.zip b/Hex Files/S4_BLT_AC_UBL_MC_NF_DW7.4.6.hex.zip index b72df5a150..1fd55a414b 100644 Binary files a/Hex Files/S4_BLT_AC_UBL_MC_NF_DW7.4.6.hex.zip and b/Hex Files/S4_BLT_AC_UBL_MC_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_BLT_AC_UBL_ME_DW7.4.6.hex.zip b/Hex Files/S4_BLT_AC_UBL_ME_DW7.4.6.hex.zip index 8d37f6f90a..90ac8996e1 100644 Binary files a/Hex Files/S4_BLT_AC_UBL_ME_DW7.4.6.hex.zip and b/Hex Files/S4_BLT_AC_UBL_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_BLT_AC_UBL_ME_NF_DW7.4.6.hex.zip b/Hex Files/S4_BLT_AC_UBL_ME_NF_DW7.4.6.hex.zip index 908290f60a..45b2b06d3a 100644 Binary files a/Hex Files/S4_BLT_AC_UBL_ME_NF_DW7.4.6.hex.zip and b/Hex Files/S4_BLT_AC_UBL_ME_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_BLT_AC_UBL_NF_DW7.4.6.hex.zip b/Hex Files/S4_BLT_AC_UBL_NF_DW7.4.6.hex.zip index e63ea3abf0..48ee24100f 100644 Binary files a/Hex Files/S4_BLT_AC_UBL_NF_DW7.4.6.hex.zip and b/Hex Files/S4_BLT_AC_UBL_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_BLT_AC_UBL_NF_LR_DW7.4.6.hex.zip b/Hex Files/S4_BLT_AC_UBL_NF_LR_DW7.4.6.hex.zip index fcfcd287c5..a59d6df328 100644 Binary files a/Hex Files/S4_BLT_AC_UBL_NF_LR_DW7.4.6.hex.zip and b/Hex Files/S4_BLT_AC_UBL_NF_LR_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_BLT_DW7.4.6.hex.zip b/Hex Files/S4_BLT_DW7.4.6.hex.zip index 442cd3c02c..8e6aece620 100644 Binary files a/Hex Files/S4_BLT_DW7.4.6.hex.zip and b/Hex Files/S4_BLT_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_BLT_LR_DW7.4.6.hex.zip b/Hex Files/S4_BLT_LR_DW7.4.6.hex.zip index d34c99039e..5eacdc4427 100644 Binary files a/Hex Files/S4_BLT_LR_DW7.4.6.hex.zip and b/Hex Files/S4_BLT_LR_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_BLT_MC_DW7.4.6.hex.zip b/Hex Files/S4_BLT_MC_DW7.4.6.hex.zip index ca565cd001..d7dda5e0be 100644 Binary files a/Hex Files/S4_BLT_MC_DW7.4.6.hex.zip and b/Hex Files/S4_BLT_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_BLT_MC_NF_DW7.4.6.hex.zip b/Hex Files/S4_BLT_MC_NF_DW7.4.6.hex.zip index 862291a8e8..3d795f4f97 100644 Binary files a/Hex Files/S4_BLT_MC_NF_DW7.4.6.hex.zip and b/Hex Files/S4_BLT_MC_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_BLT_ME_DW7.4.6.hex.zip b/Hex Files/S4_BLT_ME_DW7.4.6.hex.zip index ee3bd44700..536bd5c284 100644 Binary files a/Hex Files/S4_BLT_ME_DW7.4.6.hex.zip and b/Hex Files/S4_BLT_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_BLT_ME_NF_DW7.4.6.hex.zip b/Hex Files/S4_BLT_ME_NF_DW7.4.6.hex.zip index 3be22d9508..4fd5824e98 100644 Binary files a/Hex Files/S4_BLT_ME_NF_DW7.4.6.hex.zip and b/Hex Files/S4_BLT_ME_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_BLT_NF_DW7.4.6.hex.zip b/Hex Files/S4_BLT_NF_DW7.4.6.hex.zip index e7309bacb8..f04f7daf16 100644 Binary files a/Hex Files/S4_BLT_NF_DW7.4.6.hex.zip and b/Hex Files/S4_BLT_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_BLT_NF_LR_DW7.4.6.hex.zip b/Hex Files/S4_BLT_NF_LR_DW7.4.6.hex.zip index 080aa4d229..4b53aa4b26 100644 Binary files a/Hex Files/S4_BLT_NF_LR_DW7.4.6.hex.zip and b/Hex Files/S4_BLT_NF_LR_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_BLT_UBL_DW7.4.6.hex.zip b/Hex Files/S4_BLT_UBL_DW7.4.6.hex.zip index 0ccced72e3..327e298ce6 100644 Binary files a/Hex Files/S4_BLT_UBL_DW7.4.6.hex.zip and b/Hex Files/S4_BLT_UBL_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_BLT_UBL_LR_DW7.4.6.hex.zip b/Hex Files/S4_BLT_UBL_LR_DW7.4.6.hex.zip index 8e07a8c5af..b2ec1f9c51 100644 Binary files a/Hex Files/S4_BLT_UBL_LR_DW7.4.6.hex.zip and b/Hex Files/S4_BLT_UBL_LR_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_BLT_UBL_MC_DW7.4.6.hex.zip b/Hex Files/S4_BLT_UBL_MC_DW7.4.6.hex.zip index c04ce40422..563616e1d8 100644 Binary files a/Hex Files/S4_BLT_UBL_MC_DW7.4.6.hex.zip and b/Hex Files/S4_BLT_UBL_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_BLT_UBL_MC_NF_DW7.4.6.hex.zip b/Hex Files/S4_BLT_UBL_MC_NF_DW7.4.6.hex.zip index 6cb52b0a18..721eddfc40 100644 Binary files a/Hex Files/S4_BLT_UBL_MC_NF_DW7.4.6.hex.zip and b/Hex Files/S4_BLT_UBL_MC_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_BLT_UBL_ME_DW7.4.6.hex.zip b/Hex Files/S4_BLT_UBL_ME_DW7.4.6.hex.zip index 504a146794..ecde135f97 100644 Binary files a/Hex Files/S4_BLT_UBL_ME_DW7.4.6.hex.zip and b/Hex Files/S4_BLT_UBL_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_BLT_UBL_ME_NF_DW7.4.6.hex.zip b/Hex Files/S4_BLT_UBL_ME_NF_DW7.4.6.hex.zip index c90f6824b7..c7deeb23ef 100644 Binary files a/Hex Files/S4_BLT_UBL_ME_NF_DW7.4.6.hex.zip and b/Hex Files/S4_BLT_UBL_ME_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_BLT_UBL_NF_DW7.4.6.hex.zip b/Hex Files/S4_BLT_UBL_NF_DW7.4.6.hex.zip index 1777808276..f0969da4c4 100644 Binary files a/Hex Files/S4_BLT_UBL_NF_DW7.4.6.hex.zip and b/Hex Files/S4_BLT_UBL_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_BLT_UBL_NF_LR_DW7.4.6.hex.zip b/Hex Files/S4_BLT_UBL_NF_LR_DW7.4.6.hex.zip index 90a103bbf4..b683cbf1c5 100644 Binary files a/Hex Files/S4_BLT_UBL_NF_LR_DW7.4.6.hex.zip and b/Hex Files/S4_BLT_UBL_NF_LR_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_DW7.4.6.hex.zip b/Hex Files/S4_DW7.4.6.hex.zip index be021f8a67..d6e5f2c263 100644 Binary files a/Hex Files/S4_DW7.4.6.hex.zip and b/Hex Files/S4_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_LR_DW7.4.6.hex.zip b/Hex Files/S4_LR_DW7.4.6.hex.zip index 2aad1a5d28..5dec229aac 100644 Binary files a/Hex Files/S4_LR_DW7.4.6.hex.zip and b/Hex Files/S4_LR_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_MC_DW7.4.6.hex.zip b/Hex Files/S4_MC_DW7.4.6.hex.zip index 4762f36b1c..2bf5319933 100644 Binary files a/Hex Files/S4_MC_DW7.4.6.hex.zip and b/Hex Files/S4_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_MC_NF_DW7.4.6.hex.zip b/Hex Files/S4_MC_NF_DW7.4.6.hex.zip index 7ac18feacc..783a52e2ff 100644 Binary files a/Hex Files/S4_MC_NF_DW7.4.6.hex.zip and b/Hex Files/S4_MC_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_ME_DW7.4.6.hex.zip b/Hex Files/S4_ME_DW7.4.6.hex.zip index 0a42c61dce..60cd76df5a 100644 Binary files a/Hex Files/S4_ME_DW7.4.6.hex.zip and b/Hex Files/S4_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_ME_NF_DW7.4.6.hex.zip b/Hex Files/S4_ME_NF_DW7.4.6.hex.zip index 349ab29930..de11077278 100644 Binary files a/Hex Files/S4_ME_NF_DW7.4.6.hex.zip and b/Hex Files/S4_ME_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_NF_DW7.4.6.hex.zip b/Hex Files/S4_NF_DW7.4.6.hex.zip index 5e441365a9..1ed727edc6 100644 Binary files a/Hex Files/S4_NF_DW7.4.6.hex.zip and b/Hex Files/S4_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/S4_NF_LR_DW7.4.6.hex.zip b/Hex Files/S4_NF_LR_DW7.4.6.hex.zip index f07d7b1dd4..c058fc4f9a 100644 Binary files a/Hex Files/S4_NF_LR_DW7.4.6.hex.zip and b/Hex Files/S4_NF_LR_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_AC_DW7.4.6.hex.zip b/Hex Files/S5_AC_DW7.4.6.hex.zip index 8d34a034da..1aabd17786 100644 Binary files a/Hex Files/S5_AC_DW7.4.6.hex.zip and b/Hex Files/S5_AC_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_AC_LR_DW7.4.6.hex.zip b/Hex Files/S5_AC_LR_DW7.4.6.hex.zip index de21291ab4..081758c78e 100644 Binary files a/Hex Files/S5_AC_LR_DW7.4.6.hex.zip and b/Hex Files/S5_AC_LR_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_AC_MC_DW7.4.6.hex.zip b/Hex Files/S5_AC_MC_DW7.4.6.hex.zip index 0ff42dad44..9fe731fa75 100644 Binary files a/Hex Files/S5_AC_MC_DW7.4.6.hex.zip and b/Hex Files/S5_AC_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_AC_MC_NF_DW7.4.6.hex.zip b/Hex Files/S5_AC_MC_NF_DW7.4.6.hex.zip index 46dec6e2dc..cad17ea1f1 100644 Binary files a/Hex Files/S5_AC_MC_NF_DW7.4.6.hex.zip and b/Hex Files/S5_AC_MC_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_AC_ME_DW7.4.6.hex.zip b/Hex Files/S5_AC_ME_DW7.4.6.hex.zip index c342cd8989..2f17d849c5 100644 Binary files a/Hex Files/S5_AC_ME_DW7.4.6.hex.zip and b/Hex Files/S5_AC_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_AC_ME_NF_DW7.4.6.hex.zip b/Hex Files/S5_AC_ME_NF_DW7.4.6.hex.zip index 1e92ff7152..e022943eb0 100644 Binary files a/Hex Files/S5_AC_ME_NF_DW7.4.6.hex.zip and b/Hex Files/S5_AC_ME_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_AC_NF_DW7.4.6.hex.zip b/Hex Files/S5_AC_NF_DW7.4.6.hex.zip index 27218dd69f..8195ceace0 100644 Binary files a/Hex Files/S5_AC_NF_DW7.4.6.hex.zip and b/Hex Files/S5_AC_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_AC_NF_LR_DW7.4.6.hex.zip b/Hex Files/S5_AC_NF_LR_DW7.4.6.hex.zip index bd0cc97699..8d1e279633 100644 Binary files a/Hex Files/S5_AC_NF_LR_DW7.4.6.hex.zip and b/Hex Files/S5_AC_NF_LR_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_BLT_AC_DW7.4.6.hex.zip b/Hex Files/S5_BLT_AC_DW7.4.6.hex.zip index 3f9ee8ce9b..f123e8d689 100644 Binary files a/Hex Files/S5_BLT_AC_DW7.4.6.hex.zip and b/Hex Files/S5_BLT_AC_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_BLT_AC_LR_DW7.4.6.hex.zip b/Hex Files/S5_BLT_AC_LR_DW7.4.6.hex.zip index 23348ed69e..03f53fdc3a 100644 Binary files a/Hex Files/S5_BLT_AC_LR_DW7.4.6.hex.zip and b/Hex Files/S5_BLT_AC_LR_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_BLT_AC_MC_DW7.4.6.hex.zip b/Hex Files/S5_BLT_AC_MC_DW7.4.6.hex.zip index a424ce524b..9c36694461 100644 Binary files a/Hex Files/S5_BLT_AC_MC_DW7.4.6.hex.zip and b/Hex Files/S5_BLT_AC_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_BLT_AC_MC_NF_DW7.4.6.hex.zip b/Hex Files/S5_BLT_AC_MC_NF_DW7.4.6.hex.zip index 44c8adf040..c19d3f5820 100644 Binary files a/Hex Files/S5_BLT_AC_MC_NF_DW7.4.6.hex.zip and b/Hex Files/S5_BLT_AC_MC_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_BLT_AC_ME_DW7.4.6.hex.zip b/Hex Files/S5_BLT_AC_ME_DW7.4.6.hex.zip index 5c9927cecc..6036c3e6f8 100644 Binary files a/Hex Files/S5_BLT_AC_ME_DW7.4.6.hex.zip and b/Hex Files/S5_BLT_AC_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_BLT_AC_ME_NF_DW7.4.6.hex.zip b/Hex Files/S5_BLT_AC_ME_NF_DW7.4.6.hex.zip index 605714ac4a..d33d339e95 100644 Binary files a/Hex Files/S5_BLT_AC_ME_NF_DW7.4.6.hex.zip and b/Hex Files/S5_BLT_AC_ME_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_BLT_AC_NF_DW7.4.6.hex.zip b/Hex Files/S5_BLT_AC_NF_DW7.4.6.hex.zip index f5088638db..57cfb34b34 100644 Binary files a/Hex Files/S5_BLT_AC_NF_DW7.4.6.hex.zip and b/Hex Files/S5_BLT_AC_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_BLT_AC_NF_LR_DW7.4.6.hex.zip b/Hex Files/S5_BLT_AC_NF_LR_DW7.4.6.hex.zip index 53db328130..d0d675f10f 100644 Binary files a/Hex Files/S5_BLT_AC_NF_LR_DW7.4.6.hex.zip and b/Hex Files/S5_BLT_AC_NF_LR_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_BLT_AC_UBL_DW7.4.6.hex.zip b/Hex Files/S5_BLT_AC_UBL_DW7.4.6.hex.zip index 573e4c1db4..e197630b76 100644 Binary files a/Hex Files/S5_BLT_AC_UBL_DW7.4.6.hex.zip and b/Hex Files/S5_BLT_AC_UBL_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_BLT_AC_UBL_LR_DW7.4.6.hex.zip b/Hex Files/S5_BLT_AC_UBL_LR_DW7.4.6.hex.zip index cf4a8a6e4f..32716e366c 100644 Binary files a/Hex Files/S5_BLT_AC_UBL_LR_DW7.4.6.hex.zip and b/Hex Files/S5_BLT_AC_UBL_LR_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_BLT_AC_UBL_MC_DW7.4.6.hex.zip b/Hex Files/S5_BLT_AC_UBL_MC_DW7.4.6.hex.zip index 89fcbe6a8f..bdb2af3408 100644 Binary files a/Hex Files/S5_BLT_AC_UBL_MC_DW7.4.6.hex.zip and b/Hex Files/S5_BLT_AC_UBL_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_BLT_AC_UBL_MC_NF_DW7.4.6.hex.zip b/Hex Files/S5_BLT_AC_UBL_MC_NF_DW7.4.6.hex.zip index 8000252649..be22dcb12d 100644 Binary files a/Hex Files/S5_BLT_AC_UBL_MC_NF_DW7.4.6.hex.zip and b/Hex Files/S5_BLT_AC_UBL_MC_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_BLT_AC_UBL_ME_DW7.4.6.hex.zip b/Hex Files/S5_BLT_AC_UBL_ME_DW7.4.6.hex.zip index e66326512d..e8477a6af8 100644 Binary files a/Hex Files/S5_BLT_AC_UBL_ME_DW7.4.6.hex.zip and b/Hex Files/S5_BLT_AC_UBL_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_BLT_AC_UBL_ME_NF_DW7.4.6.hex.zip b/Hex Files/S5_BLT_AC_UBL_ME_NF_DW7.4.6.hex.zip index 92d76e5738..8c436fbc3d 100644 Binary files a/Hex Files/S5_BLT_AC_UBL_ME_NF_DW7.4.6.hex.zip and b/Hex Files/S5_BLT_AC_UBL_ME_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_BLT_AC_UBL_NF_DW7.4.6.hex.zip b/Hex Files/S5_BLT_AC_UBL_NF_DW7.4.6.hex.zip index 11f3bae5ea..0ebf90ac52 100644 Binary files a/Hex Files/S5_BLT_AC_UBL_NF_DW7.4.6.hex.zip and b/Hex Files/S5_BLT_AC_UBL_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_BLT_AC_UBL_NF_LR_DW7.4.6.hex.zip b/Hex Files/S5_BLT_AC_UBL_NF_LR_DW7.4.6.hex.zip index 8c2852c775..e3375a9b94 100644 Binary files a/Hex Files/S5_BLT_AC_UBL_NF_LR_DW7.4.6.hex.zip and b/Hex Files/S5_BLT_AC_UBL_NF_LR_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_BLT_DW7.4.6.hex.zip b/Hex Files/S5_BLT_DW7.4.6.hex.zip index 8baeab3f25..e02cc4a1e6 100644 Binary files a/Hex Files/S5_BLT_DW7.4.6.hex.zip and b/Hex Files/S5_BLT_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_BLT_LR_DW7.4.6.hex.zip b/Hex Files/S5_BLT_LR_DW7.4.6.hex.zip index 4e2a55d1c0..80733b36f9 100644 Binary files a/Hex Files/S5_BLT_LR_DW7.4.6.hex.zip and b/Hex Files/S5_BLT_LR_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_BLT_MC_DW7.4.6.hex.zip b/Hex Files/S5_BLT_MC_DW7.4.6.hex.zip index 8abbda19b6..95542ecc05 100644 Binary files a/Hex Files/S5_BLT_MC_DW7.4.6.hex.zip and b/Hex Files/S5_BLT_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_BLT_MC_NF_DW7.4.6.hex.zip b/Hex Files/S5_BLT_MC_NF_DW7.4.6.hex.zip index bcd5d410de..37bd27847d 100644 Binary files a/Hex Files/S5_BLT_MC_NF_DW7.4.6.hex.zip and b/Hex Files/S5_BLT_MC_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_BLT_ME_DW7.4.6.hex.zip b/Hex Files/S5_BLT_ME_DW7.4.6.hex.zip index 963bda7e16..3978207449 100644 Binary files a/Hex Files/S5_BLT_ME_DW7.4.6.hex.zip and b/Hex Files/S5_BLT_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_BLT_ME_NF_DW7.4.6.hex.zip b/Hex Files/S5_BLT_ME_NF_DW7.4.6.hex.zip index 0dd18788bf..20b0a5075e 100644 Binary files a/Hex Files/S5_BLT_ME_NF_DW7.4.6.hex.zip and b/Hex Files/S5_BLT_ME_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_BLT_NF_DW7.4.6.hex.zip b/Hex Files/S5_BLT_NF_DW7.4.6.hex.zip index 677076ff05..13ec9149eb 100644 Binary files a/Hex Files/S5_BLT_NF_DW7.4.6.hex.zip and b/Hex Files/S5_BLT_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_BLT_NF_LR_DW7.4.6.hex.zip b/Hex Files/S5_BLT_NF_LR_DW7.4.6.hex.zip index 0617287741..1dbbb9e843 100644 Binary files a/Hex Files/S5_BLT_NF_LR_DW7.4.6.hex.zip and b/Hex Files/S5_BLT_NF_LR_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_BLT_UBL_DW7.4.6.hex.zip b/Hex Files/S5_BLT_UBL_DW7.4.6.hex.zip index ad9e1337f8..1b142089e8 100644 Binary files a/Hex Files/S5_BLT_UBL_DW7.4.6.hex.zip and b/Hex Files/S5_BLT_UBL_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_BLT_UBL_LR_DW7.4.6.hex.zip b/Hex Files/S5_BLT_UBL_LR_DW7.4.6.hex.zip index 3c7e89c146..f12981dc24 100644 Binary files a/Hex Files/S5_BLT_UBL_LR_DW7.4.6.hex.zip and b/Hex Files/S5_BLT_UBL_LR_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_BLT_UBL_MC_DW7.4.6.hex.zip b/Hex Files/S5_BLT_UBL_MC_DW7.4.6.hex.zip index d3b342f3b5..6e9609e257 100644 Binary files a/Hex Files/S5_BLT_UBL_MC_DW7.4.6.hex.zip and b/Hex Files/S5_BLT_UBL_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_BLT_UBL_MC_NF_DW7.4.6.hex.zip b/Hex Files/S5_BLT_UBL_MC_NF_DW7.4.6.hex.zip index b305b4f643..0258d654fb 100644 Binary files a/Hex Files/S5_BLT_UBL_MC_NF_DW7.4.6.hex.zip and b/Hex Files/S5_BLT_UBL_MC_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_BLT_UBL_ME_DW7.4.6.hex.zip b/Hex Files/S5_BLT_UBL_ME_DW7.4.6.hex.zip index b3436dd03c..57aba72d39 100644 Binary files a/Hex Files/S5_BLT_UBL_ME_DW7.4.6.hex.zip and b/Hex Files/S5_BLT_UBL_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_BLT_UBL_ME_NF_DW7.4.6.hex.zip b/Hex Files/S5_BLT_UBL_ME_NF_DW7.4.6.hex.zip index 5995164646..df4885d281 100644 Binary files a/Hex Files/S5_BLT_UBL_ME_NF_DW7.4.6.hex.zip and b/Hex Files/S5_BLT_UBL_ME_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_BLT_UBL_NF_DW7.4.6.hex.zip b/Hex Files/S5_BLT_UBL_NF_DW7.4.6.hex.zip index a4b3266939..5a80bcf78d 100644 Binary files a/Hex Files/S5_BLT_UBL_NF_DW7.4.6.hex.zip and b/Hex Files/S5_BLT_UBL_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_BLT_UBL_NF_LR_DW7.4.6.hex.zip b/Hex Files/S5_BLT_UBL_NF_LR_DW7.4.6.hex.zip index a4052e8b6b..03c0f2a850 100644 Binary files a/Hex Files/S5_BLT_UBL_NF_LR_DW7.4.6.hex.zip and b/Hex Files/S5_BLT_UBL_NF_LR_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_DW7.4.6.hex.zip b/Hex Files/S5_DW7.4.6.hex.zip index bf8db5118c..efffa574b4 100644 Binary files a/Hex Files/S5_DW7.4.6.hex.zip and b/Hex Files/S5_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_LR_DW7.4.6.hex.zip b/Hex Files/S5_LR_DW7.4.6.hex.zip index d47709d103..0ea98bed67 100644 Binary files a/Hex Files/S5_LR_DW7.4.6.hex.zip and b/Hex Files/S5_LR_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_MC_DW7.4.6.hex.zip b/Hex Files/S5_MC_DW7.4.6.hex.zip index df5864c1c1..38ad2b0a82 100644 Binary files a/Hex Files/S5_MC_DW7.4.6.hex.zip and b/Hex Files/S5_MC_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_MC_NF_DW7.4.6.hex.zip b/Hex Files/S5_MC_NF_DW7.4.6.hex.zip index 128d1f7406..956c8b94cc 100644 Binary files a/Hex Files/S5_MC_NF_DW7.4.6.hex.zip and b/Hex Files/S5_MC_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_ME_DW7.4.6.hex.zip b/Hex Files/S5_ME_DW7.4.6.hex.zip index 6279274155..fff36cbd6c 100644 Binary files a/Hex Files/S5_ME_DW7.4.6.hex.zip and b/Hex Files/S5_ME_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_ME_NF_DW7.4.6.hex.zip b/Hex Files/S5_ME_NF_DW7.4.6.hex.zip index cf76d9739f..6c0cbb2a47 100644 Binary files a/Hex Files/S5_ME_NF_DW7.4.6.hex.zip and b/Hex Files/S5_ME_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_NF_DW7.4.6.hex.zip b/Hex Files/S5_NF_DW7.4.6.hex.zip index 9390c5dcf0..4d7990073e 100644 Binary files a/Hex Files/S5_NF_DW7.4.6.hex.zip and b/Hex Files/S5_NF_DW7.4.6.hex.zip differ diff --git a/Hex Files/S5_NF_LR_DW7.4.6.hex.zip b/Hex Files/S5_NF_LR_DW7.4.6.hex.zip index cecbf5d93d..3bbaf00ff3 100644 Binary files a/Hex Files/S5_NF_LR_DW7.4.6.hex.zip and b/Hex Files/S5_NF_LR_DW7.4.6.hex.zip differ diff --git a/Hex Files/firmware_CR10Smart_DW7.4.6.bin.zip b/Hex Files/firmware_CR10Smart_DW7.4.6.bin.zip index c03945195a..6ee3dc8764 100644 Binary files a/Hex Files/firmware_CR10Smart_DW7.4.6.bin.zip and b/Hex Files/firmware_CR10Smart_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_CR30_DW7.4.6.bin.zip b/Hex Files/firmware_CR30_DW7.4.6.bin.zip new file mode 100644 index 0000000000..d4101aa1e8 Binary files /dev/null and b/Hex Files/firmware_CR30_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_CR6Max_452_DW7.4.6.bin.zip b/Hex Files/firmware_CR6Max_452_DW7.4.6.bin.zip index 74f992be85..b7acad24e1 100644 Binary files a/Hex Files/firmware_CR6Max_452_DW7.4.6.bin.zip and b/Hex Files/firmware_CR6Max_452_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_CR6Max_453_DW7.4.6.bin.zip b/Hex Files/firmware_CR6Max_453_DW7.4.6.bin.zip index ba472d7867..14a05b3d84 100644 Binary files a/Hex Files/firmware_CR6Max_453_DW7.4.6.bin.zip and b/Hex Files/firmware_CR6Max_453_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_CR6Max_LGX_452_DW7.4.6.bin.zip b/Hex Files/firmware_CR6Max_LGX_452_DW7.4.6.bin.zip index 7f594d79aa..1ea0409678 100644 Binary files a/Hex Files/firmware_CR6Max_LGX_452_DW7.4.6.bin.zip and b/Hex Files/firmware_CR6Max_LGX_452_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_CR6Max_LGX_453_DW7.4.6.bin.zip b/Hex Files/firmware_CR6Max_LGX_453_DW7.4.6.bin.zip index 95fb1618e1..2d385bfda8 100644 Binary files a/Hex Files/firmware_CR6Max_LGX_453_DW7.4.6.bin.zip and b/Hex Files/firmware_CR6Max_LGX_453_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_CR6_452_DW7.4.6.bin.zip b/Hex Files/firmware_CR6_452_DW7.4.6.bin.zip index 74a70030f4..3b1c76a7fd 100644 Binary files a/Hex Files/firmware_CR6_452_DW7.4.6.bin.zip and b/Hex Files/firmware_CR6_452_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_CR6_453_DW7.4.6.bin.zip b/Hex Files/firmware_CR6_453_DW7.4.6.bin.zip index 8855325d4b..16823147c3 100644 Binary files a/Hex Files/firmware_CR6_453_DW7.4.6.bin.zip and b/Hex Files/firmware_CR6_453_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_CR6_LGX_452_DW7.4.6.bin.zip b/Hex Files/firmware_CR6_LGX_452_DW7.4.6.bin.zip index 06a48d8e9d..d41ad0ec31 100644 Binary files a/Hex Files/firmware_CR6_LGX_452_DW7.4.6.bin.zip and b/Hex Files/firmware_CR6_LGX_452_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_CR6_LGX_453_DW7.4.6.bin.zip b/Hex Files/firmware_CR6_LGX_453_DW7.4.6.bin.zip index cd7b1df324..14569f3908 100644 Binary files a/Hex Files/firmware_CR6_LGX_453_DW7.4.6.bin.zip and b/Hex Files/firmware_CR6_LGX_453_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender2Pro_BLT_DW7.4.6.bin.zip b/Hex Files/firmware_Ender2Pro_BLT_DW7.4.6.bin.zip new file mode 100644 index 0000000000..56eff133b0 Binary files /dev/null and b/Hex Files/firmware_Ender2Pro_BLT_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender2Pro_DW7.4.6.bin.zip b/Hex Files/firmware_Ender2Pro_DW7.4.6.bin.zip index 1706dfe453..3f7f5abaa8 100644 Binary files a/Hex Files/firmware_Ender2Pro_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender2Pro_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender3Max_422_BLT_DW7.4.6.bin.zip b/Hex Files/firmware_Ender3Max_422_BLT_DW7.4.6.bin.zip index 03aa99587d..c0e79a66d0 100644 Binary files a/Hex Files/firmware_Ender3Max_422_BLT_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender3Max_422_BLT_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender3Max_422_BLT_LR_DW7.4.6.bin.zip b/Hex Files/firmware_Ender3Max_422_BLT_LR_DW7.4.6.bin.zip index 7f67cf7dc8..6030e38ca8 100644 Binary files a/Hex Files/firmware_Ender3Max_422_BLT_LR_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender3Max_422_BLT_LR_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender3Max_422_BLT_ZM_DW7.4.6.bin.zip b/Hex Files/firmware_Ender3Max_422_BLT_ZM_DW7.4.6.bin.zip index cb0236565b..6a754ee21c 100644 Binary files a/Hex Files/firmware_Ender3Max_422_BLT_ZM_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender3Max_422_BLT_ZM_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender3Max_422_BLT_ZM_LR_DW7.4.6.bin.zip b/Hex Files/firmware_Ender3Max_422_BLT_ZM_LR_DW7.4.6.bin.zip index 880a9a7a6b..54173091cd 100644 Binary files a/Hex Files/firmware_Ender3Max_422_BLT_ZM_LR_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender3Max_422_BLT_ZM_LR_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender3Max_422_DW7.4.6.bin.zip b/Hex Files/firmware_Ender3Max_422_DW7.4.6.bin.zip index 7fa7823a2b..9b6fa78635 100644 Binary files a/Hex Files/firmware_Ender3Max_422_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender3Max_422_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender3Max_422_LR_DW7.4.6.bin.zip b/Hex Files/firmware_Ender3Max_422_LR_DW7.4.6.bin.zip index 7432bf5706..ba68a41bfb 100644 Binary files a/Hex Files/firmware_Ender3Max_422_LR_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender3Max_422_LR_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender3Max_427_BLT_DW7.4.6.bin.zip b/Hex Files/firmware_Ender3Max_427_BLT_DW7.4.6.bin.zip index 80c1ad2b3b..01cf131d83 100644 Binary files a/Hex Files/firmware_Ender3Max_427_BLT_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender3Max_427_BLT_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender3Max_427_BLT_LR_DW7.4.6.bin.zip b/Hex Files/firmware_Ender3Max_427_BLT_LR_DW7.4.6.bin.zip index 27810d4733..2043462d64 100644 Binary files a/Hex Files/firmware_Ender3Max_427_BLT_LR_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender3Max_427_BLT_LR_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender3Max_427_BLT_ZM_DW7.4.6.bin.zip b/Hex Files/firmware_Ender3Max_427_BLT_ZM_DW7.4.6.bin.zip index e0d3c54ce2..9cf12ed401 100644 Binary files a/Hex Files/firmware_Ender3Max_427_BLT_ZM_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender3Max_427_BLT_ZM_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender3Max_427_BLT_ZM_LR_DW7.4.6.bin.zip b/Hex Files/firmware_Ender3Max_427_BLT_ZM_LR_DW7.4.6.bin.zip index 434bc6945e..eebc74393f 100644 Binary files a/Hex Files/firmware_Ender3Max_427_BLT_ZM_LR_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender3Max_427_BLT_ZM_LR_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender3Max_427_DW7.4.6.bin.zip b/Hex Files/firmware_Ender3Max_427_DW7.4.6.bin.zip index b811394486..279e25c211 100644 Binary files a/Hex Files/firmware_Ender3Max_427_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender3Max_427_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender3Max_427_LR_DW7.4.6.bin.zip b/Hex Files/firmware_Ender3Max_427_LR_DW7.4.6.bin.zip index 464bce328b..915ec8c04d 100644 Binary files a/Hex Files/firmware_Ender3Max_427_LR_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender3Max_427_LR_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender3S1F4_DW7.4.6.bin.zip b/Hex Files/firmware_Ender3S1F4_DW7.4.6.bin.zip new file mode 100644 index 0000000000..27f6fcdc7e Binary files /dev/null and b/Hex Files/firmware_Ender3S1F4_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender3S1_DW7.4.6.bin.zip b/Hex Files/firmware_Ender3S1_DW7.4.6.bin.zip new file mode 100644 index 0000000000..ef93d1f9e5 Binary files /dev/null and b/Hex Files/firmware_Ender3S1_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender3V2_427_BLT_DW7.4.6.bin.zip b/Hex Files/firmware_Ender3V2_427_BLT_DW7.4.6.bin.zip index e130197ccc..cf8f6e13a7 100644 Binary files a/Hex Files/firmware_Ender3V2_427_BLT_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender3V2_427_BLT_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender3V2_427_BLT_LR_DW7.4.6.bin.zip b/Hex Files/firmware_Ender3V2_427_BLT_LR_DW7.4.6.bin.zip index 90ca551aa8..7094c54075 100644 Binary files a/Hex Files/firmware_Ender3V2_427_BLT_LR_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender3V2_427_BLT_LR_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender3V2_427_BLT_ZM_DW7.4.6.bin.zip b/Hex Files/firmware_Ender3V2_427_BLT_ZM_DW7.4.6.bin.zip index 475a908a77..2cb3f9164a 100644 Binary files a/Hex Files/firmware_Ender3V2_427_BLT_ZM_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender3V2_427_BLT_ZM_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender3V2_427_BLT_ZM_LR_DW7.4.6.bin.zip b/Hex Files/firmware_Ender3V2_427_BLT_ZM_LR_DW7.4.6.bin.zip index bee7b49aca..92a94198ec 100644 Binary files a/Hex Files/firmware_Ender3V2_427_BLT_ZM_LR_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender3V2_427_BLT_ZM_LR_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender3V2_427_DW7.4.6.bin.zip b/Hex Files/firmware_Ender3V2_427_DW7.4.6.bin.zip index a3c4cc8bd6..f84f68ad5b 100644 Binary files a/Hex Files/firmware_Ender3V2_427_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender3V2_427_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender3V2_427_LR_DW7.4.6.bin.zip b/Hex Files/firmware_Ender3V2_427_LR_DW7.4.6.bin.zip index 6eedfc4155..b0b1114376 100644 Binary files a/Hex Files/firmware_Ender3V2_427_LR_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender3V2_427_LR_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender3V2_BLT_DW7.4.6.bin.zip b/Hex Files/firmware_Ender3V2_BLT_DW7.4.6.bin.zip index 79d90661e6..fceb69915f 100644 Binary files a/Hex Files/firmware_Ender3V2_BLT_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender3V2_BLT_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender3V2_BLT_LR_DW7.4.6.bin.zip b/Hex Files/firmware_Ender3V2_BLT_LR_DW7.4.6.bin.zip index 29d931eccf..5e926a0607 100644 Binary files a/Hex Files/firmware_Ender3V2_BLT_LR_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender3V2_BLT_LR_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender3V2_BLT_ZM_DW7.4.6.bin.zip b/Hex Files/firmware_Ender3V2_BLT_ZM_DW7.4.6.bin.zip index 37553fb121..1144000d66 100644 Binary files a/Hex Files/firmware_Ender3V2_BLT_ZM_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender3V2_BLT_ZM_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender3V2_BLT_ZM_LR_DW7.4.6.bin.zip b/Hex Files/firmware_Ender3V2_BLT_ZM_LR_DW7.4.6.bin.zip index 1370bc8d34..eea4f98fcc 100644 Binary files a/Hex Files/firmware_Ender3V2_BLT_ZM_LR_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender3V2_BLT_ZM_LR_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender3V2_DW7.4.6.bin.zip b/Hex Files/firmware_Ender3V2_DW7.4.6.bin.zip index 2b87e1ff7a..4bb69d3555 100644 Binary files a/Hex Files/firmware_Ender3V2_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender3V2_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender3V2_LR_DW7.4.6.bin.zip b/Hex Files/firmware_Ender3V2_LR_DW7.4.6.bin.zip index c07e881e66..11a5fcc2b3 100644 Binary files a/Hex Files/firmware_Ender3V2_LR_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender3V2_LR_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender3_422_BLT_DW7.4.6.bin.zip b/Hex Files/firmware_Ender3_422_BLT_DW7.4.6.bin.zip index ca4d004449..8098a12e46 100644 Binary files a/Hex Files/firmware_Ender3_422_BLT_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender3_422_BLT_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender3_422_BLT_LR_DW7.4.6.bin.zip b/Hex Files/firmware_Ender3_422_BLT_LR_DW7.4.6.bin.zip index b46a29fad1..4278413a9d 100644 Binary files a/Hex Files/firmware_Ender3_422_BLT_LR_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender3_422_BLT_LR_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender3_422_BLT_ZM_DW7.4.6.bin.zip b/Hex Files/firmware_Ender3_422_BLT_ZM_DW7.4.6.bin.zip index 8cd3f52f19..50562eb0d0 100644 Binary files a/Hex Files/firmware_Ender3_422_BLT_ZM_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender3_422_BLT_ZM_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender3_422_BLT_ZM_LR_DW7.4.6.bin.zip b/Hex Files/firmware_Ender3_422_BLT_ZM_LR_DW7.4.6.bin.zip index a5f48f8507..72d147f7c7 100644 Binary files a/Hex Files/firmware_Ender3_422_BLT_ZM_LR_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender3_422_BLT_ZM_LR_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender3_422_DW7.4.6.bin.zip b/Hex Files/firmware_Ender3_422_DW7.4.6.bin.zip index b8bdf9c994..e59953d8d9 100644 Binary files a/Hex Files/firmware_Ender3_422_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender3_422_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender3_422_LR_DW7.4.6.bin.zip b/Hex Files/firmware_Ender3_422_LR_DW7.4.6.bin.zip index 5826cd20c4..049dc2597c 100644 Binary files a/Hex Files/firmware_Ender3_422_LR_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender3_422_LR_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender3_427_BLT_DW7.4.6.bin.zip b/Hex Files/firmware_Ender3_427_BLT_DW7.4.6.bin.zip index cb392e119f..2ce2352c44 100644 Binary files a/Hex Files/firmware_Ender3_427_BLT_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender3_427_BLT_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender3_427_BLT_LR_DW7.4.6.bin.zip b/Hex Files/firmware_Ender3_427_BLT_LR_DW7.4.6.bin.zip index 85e00f55ea..cfcf0b1d51 100644 Binary files a/Hex Files/firmware_Ender3_427_BLT_LR_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender3_427_BLT_LR_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender3_427_BLT_ZM_DW7.4.6.bin.zip b/Hex Files/firmware_Ender3_427_BLT_ZM_DW7.4.6.bin.zip index 07f631298e..d2fa20b05a 100644 Binary files a/Hex Files/firmware_Ender3_427_BLT_ZM_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender3_427_BLT_ZM_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender3_427_BLT_ZM_LR_DW7.4.6.bin.zip b/Hex Files/firmware_Ender3_427_BLT_ZM_LR_DW7.4.6.bin.zip index 665bdc7ce1..a270affb53 100644 Binary files a/Hex Files/firmware_Ender3_427_BLT_ZM_LR_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender3_427_BLT_ZM_LR_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender3_427_DW7.4.6.bin.zip b/Hex Files/firmware_Ender3_427_DW7.4.6.bin.zip index a3f625eea7..3604466734 100644 Binary files a/Hex Files/firmware_Ender3_427_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender3_427_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender3_427_LR_DW7.4.6.bin.zip b/Hex Files/firmware_Ender3_427_LR_DW7.4.6.bin.zip index 5d0e25f177..c922bf6a17 100644 Binary files a/Hex Files/firmware_Ender3_427_LR_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender3_427_LR_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender5Pro_422_BLT_DW7.4.6.bin.zip b/Hex Files/firmware_Ender5Pro_422_BLT_DW7.4.6.bin.zip index f8e7a76522..6a377ad639 100644 Binary files a/Hex Files/firmware_Ender5Pro_422_BLT_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender5Pro_422_BLT_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender5Pro_422_BLT_LR_DW7.4.6.bin.zip b/Hex Files/firmware_Ender5Pro_422_BLT_LR_DW7.4.6.bin.zip index e870230f61..498f2ed9a2 100644 Binary files a/Hex Files/firmware_Ender5Pro_422_BLT_LR_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender5Pro_422_BLT_LR_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender5Pro_422_BLT_ZM_DW7.4.6.bin.zip b/Hex Files/firmware_Ender5Pro_422_BLT_ZM_DW7.4.6.bin.zip index 604840bbc1..304df41c4e 100644 Binary files a/Hex Files/firmware_Ender5Pro_422_BLT_ZM_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender5Pro_422_BLT_ZM_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender5Pro_422_BLT_ZM_LR_DW7.4.6.bin.zip b/Hex Files/firmware_Ender5Pro_422_BLT_ZM_LR_DW7.4.6.bin.zip index bc1b471b50..9f043074fe 100644 Binary files a/Hex Files/firmware_Ender5Pro_422_BLT_ZM_LR_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender5Pro_422_BLT_ZM_LR_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender5Pro_422_DW7.4.6.bin.zip b/Hex Files/firmware_Ender5Pro_422_DW7.4.6.bin.zip index 0512b3657c..b30975f3ad 100644 Binary files a/Hex Files/firmware_Ender5Pro_422_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender5Pro_422_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender5Pro_422_LR_DW7.4.6.bin.zip b/Hex Files/firmware_Ender5Pro_422_LR_DW7.4.6.bin.zip index 8027072dc5..87969ee1e7 100644 Binary files a/Hex Files/firmware_Ender5Pro_422_LR_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender5Pro_422_LR_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender5Pro_427_BLT_DW7.4.6.bin.zip b/Hex Files/firmware_Ender5Pro_427_BLT_DW7.4.6.bin.zip index ed949a6a8b..18a4d074b4 100644 Binary files a/Hex Files/firmware_Ender5Pro_427_BLT_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender5Pro_427_BLT_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender5Pro_427_BLT_LR_DW7.4.6.bin.zip b/Hex Files/firmware_Ender5Pro_427_BLT_LR_DW7.4.6.bin.zip index 32c68f3df7..c0641f30af 100644 Binary files a/Hex Files/firmware_Ender5Pro_427_BLT_LR_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender5Pro_427_BLT_LR_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender5Pro_427_BLT_ZM_DW7.4.6.bin.zip b/Hex Files/firmware_Ender5Pro_427_BLT_ZM_DW7.4.6.bin.zip index 740f025bc6..4d2334e214 100644 Binary files a/Hex Files/firmware_Ender5Pro_427_BLT_ZM_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender5Pro_427_BLT_ZM_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender5Pro_427_BLT_ZM_LR_DW7.4.6.bin.zip b/Hex Files/firmware_Ender5Pro_427_BLT_ZM_LR_DW7.4.6.bin.zip index 7d84f5aed5..76982cd589 100644 Binary files a/Hex Files/firmware_Ender5Pro_427_BLT_ZM_LR_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender5Pro_427_BLT_ZM_LR_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender5Pro_427_DW7.4.6.bin.zip b/Hex Files/firmware_Ender5Pro_427_DW7.4.6.bin.zip index a175567d07..73236e3bbd 100644 Binary files a/Hex Files/firmware_Ender5Pro_427_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender5Pro_427_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender5Pro_427_LR_DW7.4.6.bin.zip b/Hex Files/firmware_Ender5Pro_427_LR_DW7.4.6.bin.zip index 812abc1c75..ba9e7be74f 100644 Binary files a/Hex Files/firmware_Ender5Pro_427_LR_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender5Pro_427_LR_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender6_BLT_DW7.4.6.bin.zip b/Hex Files/firmware_Ender6_BLT_DW7.4.6.bin.zip index 69034fdf44..6c804e7a00 100644 Binary files a/Hex Files/firmware_Ender6_BLT_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender6_BLT_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender6_BLT_ZM_DW7.4.6.bin.zip b/Hex Files/firmware_Ender6_BLT_ZM_DW7.4.6.bin.zip index b5319d6bf6..77ace4e82b 100644 Binary files a/Hex Files/firmware_Ender6_BLT_ZM_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender6_BLT_ZM_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender6_DW7.4.6.bin.zip b/Hex Files/firmware_Ender6_DW7.4.6.bin.zip index 818496a836..d4e4c4f391 100644 Binary files a/Hex Files/firmware_Ender6_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender6_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender7_BLT_DW7.4.6.bin.zip b/Hex Files/firmware_Ender7_BLT_DW7.4.6.bin.zip index 8d73984abb..60f698acc2 100644 Binary files a/Hex Files/firmware_Ender7_BLT_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender7_BLT_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender7_BLT_ZM_DW7.4.6.bin.zip b/Hex Files/firmware_Ender7_BLT_ZM_DW7.4.6.bin.zip index 94adb55ff5..61be5846c8 100644 Binary files a/Hex Files/firmware_Ender7_BLT_ZM_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender7_BLT_ZM_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_Ender7_DW7.4.6.bin.zip b/Hex Files/firmware_Ender7_DW7.4.6.bin.zip index 5ef2449332..ec3c979b60 100644 Binary files a/Hex Files/firmware_Ender7_DW7.4.6.bin.zip and b/Hex Files/firmware_Ender7_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_SermoonD1_BLT_DW7.4.6.bin.zip b/Hex Files/firmware_SermoonD1_BLT_DW7.4.6.bin.zip index 8d63227c2a..8c4f85186a 100644 Binary files a/Hex Files/firmware_SermoonD1_BLT_DW7.4.6.bin.zip and b/Hex Files/firmware_SermoonD1_BLT_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_SermoonD1_BLT_ZM_DW7.4.6.bin.zip b/Hex Files/firmware_SermoonD1_BLT_ZM_DW7.4.6.bin.zip index 61fd31817d..88714633d5 100644 Binary files a/Hex Files/firmware_SermoonD1_BLT_ZM_DW7.4.6.bin.zip and b/Hex Files/firmware_SermoonD1_BLT_ZM_DW7.4.6.bin.zip differ diff --git a/Hex Files/firmware_SermoonD1_DW7.4.6.bin.zip b/Hex Files/firmware_SermoonD1_DW7.4.6.bin.zip index ad099beb44..cfba01e5f1 100644 Binary files a/Hex Files/firmware_SermoonD1_DW7.4.6.bin.zip and b/Hex Files/firmware_SermoonD1_DW7.4.6.bin.zip differ diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h index 0b8fcc8078..bfc367e9c1 100644 --- a/Marlin/Configuration.h +++ b/Marlin/Configuration.h @@ -40,7 +40,7 @@ * * Advanced settings can be found in Configuration_adv.h */ -#define CONFIGURATION_H_VERSION 02010000 +#define CONFIGURATION_H_VERSION 02010100 //=========================================================================== //============================= Getting Started ============================= @@ -62,15 +62,6 @@ * https://www.thingiverse.com/thing:1278865 */ -//=========================================================================== -//========================== DELTA / SCARA / TPARA ========================== -//=========================================================================== -// -// Download configurations from the link above and customize for your machine. -// Examples are located in config/examples/delta, .../SCARA, and .../TPARA. -// -//=========================================================================== - // @section info // Author info of this build printed to the host during boot and M115 @@ -175,20 +166,57 @@ //#define MACHINE_UUID "00000000-0000-0000-0000-000000000000" /** - * Define the number of coordinated axes. - * See https://github.com/DerAndere1/Marlin/wiki - * Each axis gets its own stepper control and endstop: + * Stepper Drivers * - * Steppers: *_STEP_PIN, *_ENABLE_PIN, *_DIR_PIN, *_ENABLE_ON - * Endstops: *_STOP_PIN, USE_*MIN_PLUG, USE_*MAX_PLUG - * Axes: *_MIN_POS, *_MAX_POS, INVERT_*_DIR - * Planner: DEFAULT_AXIS_STEPS_PER_UNIT, DEFAULT_MAX_FEEDRATE - * DEFAULT_MAX_ACCELERATION, AXIS_RELATIVE_MODES, - * MICROSTEP_MODES, MANUAL_FEEDRATE + * 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. * - * :[3, 4, 5, 6, 7, 8, 9] + * A4988 is assumed for unspecified drivers. + * + * Use TMC2208/TMC2208_STANDALONE for TMC2225 drivers and TMC2209/TMC2209_STANDALONE for TMC2226 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 NUM_AXES 3 +#if ENABLED(Driver2208) + #define DRIVER TMC2208_STANDALONE +#elif ENABLED(Driver2208_UART) + #define DRIVER TMC2208 +#elif ENABLED(Driver2209) + #define DRIVER TMC2209_STANDALONE +#elif ENABLED(Driver2209_UART) + #define DRIVER TMC2209 +#else + #define DRIVER A4988 +#endif + +#define X_DRIVER_TYPE DRIVER +#define Y_DRIVER_TYPE DRIVER +#define Z_DRIVER_TYPE DRIVER +#define X2_DRIVER_TYPE DRIVER +//#define Y2_DRIVER_TYPE A4988 +#define Z2_DRIVER_TYPE DRIVER +//#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 DRIVER +#define E1_DRIVER_TYPE DRIVER +//#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 @@ -207,27 +235,27 @@ * * Regardless of these settings the axes are internally named I, J, K, U, V, W. */ -#if NUM_AXES >= 4 +#ifdef I_DRIVER_TYPE #define AXIS4_NAME 'A' // :['A', 'B', 'C', 'U', 'V', 'W'] #define AXIS4_ROTATES #endif -#if NUM_AXES >= 5 +#ifdef J_DRIVER_TYPE #define AXIS5_NAME 'B' // :['B', 'C', 'U', 'V', 'W'] #define AXIS5_ROTATES #endif -#if NUM_AXES >= 6 +#ifdef K_DRIVER_TYPE #define AXIS6_NAME 'C' // :['C', 'U', 'V', 'W'] #define AXIS6_ROTATES #endif -#if NUM_AXES >= 7 +#ifdef U_DRIVER_TYPE #define AXIS7_NAME 'U' // :['U', 'V', 'W'] //#define AXIS7_ROTATES #endif -#if NUM_AXES >= 8 +#ifdef V_DRIVER_TYPE #define AXIS8_NAME 'V' // :['V', 'W'] //#define AXIS8_ROTATES #endif -#if NUM_AXES >= 9 +#ifdef W_DRIVER_TYPE #define AXIS9_NAME 'W' // :['W'] //#define AXIS9_ROTATES #endif @@ -674,6 +702,9 @@ * for PID_EXTRUSION_SCALING and PID_FAN_SCALING. Use M306 to autotune the model. */ #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. @@ -693,15 +724,16 @@ //#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). + #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 just above the surface. + #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 //=========================================================================== @@ -796,6 +828,9 @@ //#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 @@ -866,6 +901,141 @@ #define POLAR_SEGMENTS_PER_SECOND 5 #endif +// 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 + +/** + * 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 + +// 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 + +// 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 =========================== //=========================================================================== @@ -973,59 +1143,6 @@ #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. - * - * Use TMC2208/TMC2208_STANDALONE for TMC2225 drivers and TMC2209/TMC2209_STANDALONE for TMC2226 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'] - */ -#if ENABLED(Driver2208) - #define DRIVER TMC2208_STANDALONE -#elif ENABLED(Driver2208_UART) - #define DRIVER TMC2208 -#elif ENABLED(Driver2209) - #define DRIVER TMC2209_STANDALONE -#elif ENABLED(Driver2209_UART) - #define DRIVER TMC2209 -#else - #define DRIVER A4988 -#endif - -#define X_DRIVER_TYPE DRIVER -#define Y_DRIVER_TYPE DRIVER -#define Z_DRIVER_TYPE DRIVER -#define X2_DRIVER_TYPE DRIVER -//#define Y2_DRIVER_TYPE A4988 -#define Z2_DRIVER_TYPE DRIVER -//#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 DRIVER -#define E1_DRIVER_TYPE DRIVER -//#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 @@ -1291,6 +1408,27 @@ #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 sensitivity. //#define DUET_SMART_EFFECTOR @@ -1306,9 +1444,37 @@ */ //#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 } @@ -1932,21 +2098,22 @@ #endif // Add a menu item to move between bed corners for manual bed adjustment -//#define LEVEL_BED_CORNERS +//#define LCD_BED_TRAMMING - #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 -#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 - //#define LEVEL_CORNERS_USE_PROBE - #if ENABLED(LEVEL_CORNERS_USE_PROBE) - #define LEVEL_CORNERS_PROBE_TOLERANCE 0.1 - #define LEVEL_CORNERS_VERIFY_RAISED // After adjustment triggers the probe, re-probe to verify - //#define LEVEL_CORNERS_AUDIO_FEEDBACK + #define BED_TRAMMING_INSET_LFRB { 22, 22, 22, 22 } // (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 + +#if ENABLED(LCD_BED_TRAMMING) + #define BED_TRAMMING_INSET_LFRB { 22, 22, 22, 22 } // (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 /** @@ -1966,7 +2133,7 @@ * | 1 2 | | 1 4 | | 1 2 | | 2 | * LF --------- RF LF --------- RF LF --------- RF LF --------- RF */ - #define LEVEL_CORNERS_LEVELING_ORDER { LF, RF, RB, LB } + #define BED_TRAMMING_LEVELING_ORDER { LF, RF, RB, LB } #endif /** @@ -2117,7 +2284,7 @@ // @section temperature // -// Preheat Constants - Up to 5 are supported without changes +// Preheat Constants - Up to 6 are supported without changes // #define PREHEAT_1_LABEL "PLA" #define PREHEAT_1_TEMP_HOTEND 180 @@ -2529,7 +2696,6 @@ //======================== LCD / Controller Selection ========================= //===================== (I2C and Shift-Register LCDs) ===================== //============================================================================= - // // CONTROLLER TYPE: I2C // @@ -2754,6 +2920,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 ============================== //============================================================================= @@ -2817,38 +2989,38 @@ //========================== 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 -// 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. -// +/** + * 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 @@ -2862,9 +3034,6 @@ // 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 @@ -2878,7 +3047,6 @@ //#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 @@ -2886,9 +3054,6 @@ // 320x240 Nextion 2.8" serial TFT Resistive Touch Screen NX3224T028 // //#define NEXTION_TFT -#if ENABLED(NEXTION_TFT) - #define LCD_SERIAL_PORT 1 // Default is 1 for Nextion -#endif // // Third-party or vendor-customized controller interfaces. @@ -3043,7 +3208,6 @@ // //#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) @@ -3165,30 +3329,30 @@ // 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_TYPE NEO_RGB // 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_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 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_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 + //#define NEOPIXEL_BKGD_ALWAYS_ON // Keep the backlight on when other NeoPixels are off #endif /** diff --git a/Marlin/Configuration_adv.h b/Marlin/Configuration_adv.h index 6e246c5c1d..af46f7fa44 100644 --- a/Marlin/Configuration_adv.h +++ b/Marlin/Configuration_adv.h @@ -30,7 +30,7 @@ * * Basic settings can be found in Configuration.h */ -#define CONFIGURATION_ADV_H_VERSION 02010000 +#define CONFIGURATION_ADV_H_VERSION 02010100 //=========================================================================== //============================= Thermal Settings ============================ @@ -54,87 +54,101 @@ // 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 #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_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_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_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_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 /** @@ -249,20 +263,6 @@ #endif #endif -// -// 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 -#endif - /** * Thermal Protection provides additional protection to your printer from damage * and fire. Marlin always includes safe min and max temperature ranges which @@ -526,7 +526,7 @@ // 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 + #define CONTROLLER_FAN_EDITABLE // Enable M710 configurable settings #if ENABLED(CONTROLLER_FAN_EDITABLE) #define CONTROLLER_FAN_MENU // Enable the Controller Fan submenu #endif @@ -627,7 +627,6 @@ #define E7_AUTO_FAN_PIN -1 #define CHAMBER_AUTO_FAN_PIN -1 #define COOLER_AUTO_FAN_PIN -1 -#define COOLER_FAN_PIN -1 #define EXTRUDER_AUTO_FAN_TEMPERATURE 50 #define EXTRUDER_AUTO_FAN_SPEED 255 // 255 == full speed @@ -727,75 +726,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 // Enable if X2 direction signal is opposite to X - //#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 // Enable if Y2 direction signal is opposite to Y - //#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 2 // (1-4) Z options change based on how many - -#if NUM_Z_STEPPER_DRIVERS > 1 - // Enable if Z motor direction signals are the opposite of Z1 - //#define INVERT_Z2_VS_Z_DIR - //#define INVERT_Z3_VS_Z_DIR - //#define INVERT_Z4_VS_Z_DIR - - #if DISABLED(BLTOUCH) - #define Z_MULTI_ENDSTOPS - #endif - #if ENABLED(Z_MULTI_ENDSTOPS) - #define Z2_USE_ENDSTOP _ZMAX_ - #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 - -// 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 // Enable if the E motors need opposite DIR states -#endif - /** * Dual X Carriage * @@ -865,6 +795,77 @@ //#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. // Define SOL0_PIN, SOL1_PIN, etc., for each extruder that has a solenoid. //#define EXT_SOLENOID @@ -1000,7 +1001,7 @@ /** * Z Stepper positions for more rapid convergence in bed alignment. - * Requires NUM_Z_STEPPER_DRIVERS to be 3 or 4. + * 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 @@ -1366,6 +1367,9 @@ #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 @@ -1382,8 +1386,9 @@ #endif // HAS_MARLINUI_MENU -#if ANY(HAS_DISPLAY, DWIN_LCD_PROUI, DWIN_CREALITY_LCD_JYERSUI) +#if EITHER(HAS_DISPLAY, DWIN_LCD_PROUI) //#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) @@ -1426,7 +1431,7 @@ #define LED_USER_PRESET_BLUE 0 // User defined BLUE value #define LED_USER_PRESET_WHITE 255 // User defined WHITE value #define LED_USER_PRESET_BRIGHTNESS 255 // User defined intensity - //#define LED_USER_PRESET_STARTUP // Have the printer display the user preset color on startup + #define LED_USER_PRESET_STARTUP // Have the printer display the user preset color on startup #endif #if ENABLED(NEO2_COLOR_PRESETS) #define NEO2_USER_PRESET_RED 255 // User defined RED value @@ -1725,14 +1730,25 @@ //#define XYZ_NO_FRAME #define XYZ_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 + /** + * 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 + /** * ST7920-based LCDs can emulate a 16 x 4 character display using * the ST7920 character-generator for very fast screen updates. @@ -2341,7 +2357,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. @@ -2492,7 +2508,7 @@ /** * Extra G-code to run while executing tool-change commands. Can be used to use an additional - * stepper motor (I axis, see option NUM_AXES in Configuration.h) to drive the tool-changer. + * 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 @@ -2526,12 +2542,16 @@ #define TOOLCHANGE_FS_FAN_SPEED 255 // 0-255 #define TOOLCHANGE_FS_FAN_TIME 10 // (seconds) - // Swap uninitialized extruder (using TOOLCHANGE_FS_PRIME_SPEED feedrate) - // (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 (For other tools use TOOLCHANGE_FS_INIT_BEFORE_SWAP) - // Enable with M217 V1 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 /** @@ -2908,6 +2928,7 @@ #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) @@ -2917,6 +2938,7 @@ #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) @@ -2926,6 +2948,7 @@ #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) @@ -3271,253 +3294,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 X_MICROSTEPS - #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 Y_MICROSTEPS - #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 Z_MICROSTEPS - #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 Z_MICROSTEPS - #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 Z_MICROSTEPS - #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(I) - #define I_MICROSTEPS 128 - #define I_OVERCURRENT 2000 - #define I_STALLCURRENT 1500 - #define I_MAX_VOLTAGE 127 - #define I_CHAIN_POS -1 - #define I_SLEW_RATE 1 - #endif - - #if AXIS_IS_L64XX(J) - #define J_MICROSTEPS 128 - #define J_OVERCURRENT 2000 - #define J_STALLCURRENT 1500 - #define J_MAX_VOLTAGE 127 - #define J_CHAIN_POS -1 - #define J_SLEW_RATE 1 - #endif - - #if AXIS_IS_L64XX(K) - #define K_MICROSTEPS 128 - #define K_OVERCURRENT 2000 - #define K_STALLCURRENT 1500 - #define K_MAX_VOLTAGE 127 - #define K_CHAIN_POS -1 - #define K_SLEW_RATE 1 - #endif - - #if AXIS_IS_L64XX(U) - #define U_MICROSTEPS 128 - #define U_OVERCURRENT 2000 - #define U_STALLCURRENT 1500 - #define U_MAX_VOLTAGE 127 - #define U_CHAIN_POS -1 - #define U_SLEW_RATE 1 - #endif - - #if AXIS_IS_L64XX(V) - #define V_MICROSTEPS 128 - #define V_OVERCURRENT 2000 - #define V_STALLCURRENT 1500 - #define V_MAX_VOLTAGE 127 - #define V_CHAIN_POS -1 - #define V_SLEW_RATE 1 - #endif - - #if AXIS_IS_L64XX(W) - #define W_MICROSTEPS 128 - #define W_OVERCURRENT 2000 - #define W_STALLCURRENT 1500 - #define W_MAX_VOLTAGE 127 - #define W_CHAIN_POS -1 - #define W_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 E0_MICROSTEPS - #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 E0_MICROSTEPS - #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 E0_MICROSTEPS - #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 E0_MICROSTEPS - #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 E0_MICROSTEPS - #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 E0_MICROSTEPS - #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 E0_MICROSTEPS - #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 @@ -3627,6 +3403,9 @@ #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 @@ -3700,83 +3479,55 @@ #endif // Define the minimum and maximum test pulse time values for a laser test fire function - #define LASER_TEST_PULSE_MIN 1 // Used with Laser Control Menu - #define LASER_TEST_PULSE_MAX 999 // Caution: Menu may not show more than 3 characters + #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 + + #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 + + /** + * 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) /** - * 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). + * Any M3 or G1/2/3/5 command with the 'I' parameter enables continuous inline power mode. * - * This allows the laser to keep in perfect sync with the planner and removes - * the powerup/down delay since lasers require negligible time. + * 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. */ - //#define LASER_POWER_INLINE - #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 + /** + * 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 - /** - * 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 - - /** - * 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 - - /** - * Include laser power in G0/G1/G2/G3/G5 commands with the 'S' parameter - */ - //#define LASER_MOVE_POWER - - #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 - - // Turn off the laser on G28 homing. - //#define LASER_MOVE_G28_OFF - #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 + /** + * 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) @@ -3787,6 +3538,20 @@ #define I2C_AMMETER_SHUNT_RESISTOR 0.1 // (Ohms) Calibration shunt resistor value #endif + // + // 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 + #endif + #endif #endif // SPINDLE_FEATURE || LASER_FEATURE @@ -3900,6 +3665,9 @@ * 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 @@ -4301,7 +4069,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 /** @@ -4309,12 +4078,15 @@ * 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 /** diff --git a/Marlin/Makefile b/Marlin/Makefile index f1c89ff7f5..c72c1d5896 100644 --- a/Marlin/Makefile +++ b/Marlin/Makefile @@ -109,7 +109,7 @@ 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) +# 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 @@ -317,123 +317,10 @@ else ifeq ($(HARDWARE_MOTHERBOARD),1159) else ifeq ($(HARDWARE_MOTHERBOARD),1160) # Longer LKx PRO / Alfawise Uxx Pro (PRO version) else ifeq ($(HARDWARE_MOTHERBOARD),1161) - - -# 3Drag Controller -else ifeq ($(HARDWARE_MOTHERBOARD),1100) -# Velleman K8200 Controller (derived from 3Drag Controller) -else ifeq ($(HARDWARE_MOTHERBOARD),1101) -# Velleman K8400 Controller (derived from 3Drag Controller) -else ifeq ($(HARDWARE_MOTHERBOARD),1102) -# Velleman K8600 Controller (Vertex Nano) -else ifeq ($(HARDWARE_MOTHERBOARD),1103) -# Velleman K8800 Controller (Vertex Delta) -else ifeq ($(HARDWARE_MOTHERBOARD),1104) -# 2PrintBeta BAM&DICE with STK drivers -else ifeq ($(HARDWARE_MOTHERBOARD),1105) -# 2PrintBeta BAM&DICE Due with STK drivers -else ifeq ($(HARDWARE_MOTHERBOARD),1106) -# MKS BASE v1.0 -else ifeq ($(HARDWARE_MOTHERBOARD),1107) -# MKS v1.4 with A4982 stepper drivers -else ifeq ($(HARDWARE_MOTHERBOARD),1108) -# MKS v1.5 with Allegro A4982 stepper drivers -else ifeq ($(HARDWARE_MOTHERBOARD),1109) -# MKS 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) -# MKS GEN v1.3 or 1.4 -else ifeq ($(HARDWARE_MOTHERBOARD),1112) -# MKS GEN L -else ifeq ($(HARDWARE_MOTHERBOARD),1113) -# zrib V2.0 control board (Chinese RAMPS replica) -else ifeq ($(HARDWARE_MOTHERBOARD),1114) -# BigTreeTech or BIQU KFB2.0 -else ifeq ($(HARDWARE_MOTHERBOARD),1115) -# Felix 2.0+ Electronics Board (RAMPS like) -else ifeq ($(HARDWARE_MOTHERBOARD),1116) -# Invent-A-Part RigidBoard -else ifeq ($(HARDWARE_MOTHERBOARD),1117) -# Invent-A-Part RigidBoard V2 -else ifeq ($(HARDWARE_MOTHERBOARD),1118) -# Sainsmart 2-in-1 board -else ifeq ($(HARDWARE_MOTHERBOARD),1119) -# Ultimaker -else ifeq ($(HARDWARE_MOTHERBOARD),1120) -# Ultimaker (Older electronics. Pre 1.5.4. This is rare) -else ifeq ($(HARDWARE_MOTHERBOARD),1121) - 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) -else ifeq ($(HARDWARE_MOTHERBOARD),1124) -# Rumba -else ifeq ($(HARDWARE_MOTHERBOARD),1125) -# Raise3D Rumba -else ifeq ($(HARDWARE_MOTHERBOARD),1126) -# Rapide Lite RL200 Rumba -else ifeq ($(HARDWARE_MOTHERBOARD),1127) -# Formbot T-Rex 2 Plus -else ifeq ($(HARDWARE_MOTHERBOARD),1128) -# Formbot T-Rex 3 -else ifeq ($(HARDWARE_MOTHERBOARD),1129) -# Formbot Raptor -else ifeq ($(HARDWARE_MOTHERBOARD),1130) -# Formbot Raptor 2 -else ifeq ($(HARDWARE_MOTHERBOARD),1131) -# bq ZUM Mega 3D -else ifeq ($(HARDWARE_MOTHERBOARD),1132) -# MakeBoard Mini v2.1.2 is a control board sold by MicroMake -else ifeq ($(HARDWARE_MOTHERBOARD),1133) -# TriGorilla Anycubic version 1.3 based on RAMPS EFB -else ifeq ($(HARDWARE_MOTHERBOARD),1134) -# TriGorilla Anycubic version 1.4 based on RAMPS EFB -else ifeq ($(HARDWARE_MOTHERBOARD),1135) -# TriGorilla Anycubic version 1.4 Rev 1.1 -else ifeq ($(HARDWARE_MOTHERBOARD),1136) -# Creality: Ender-4, CR-8 -else ifeq ($(HARDWARE_MOTHERBOARD),1137) -# Creality: CR10S, CR20, CR-X -else ifeq ($(HARDWARE_MOTHERBOARD),1138) -# Dagoma F5 -else ifeq ($(HARDWARE_MOTHERBOARD),1139) -# FYSETC F6 1.3 -else ifeq ($(HARDWARE_MOTHERBOARD),1140) -# FYSETC F6 1.5 -else ifeq ($(HARDWARE_MOTHERBOARD),1141) -# Duplicator i3 Plus -else ifeq ($(HARDWARE_MOTHERBOARD),1142) -# VORON -else ifeq ($(HARDWARE_MOTHERBOARD),1143) -# TRONXY V3 1.0 -else ifeq ($(HARDWARE_MOTHERBOARD),1144) -# Z-Bolt X Series -else ifeq ($(HARDWARE_MOTHERBOARD),1145) -# TT OSCAR -else ifeq ($(HARDWARE_MOTHERBOARD),1146) -# Overlord/Overlord Pro -else ifeq ($(HARDWARE_MOTHERBOARD),1147) -# ADIMLab Gantry v1 -else ifeq ($(HARDWARE_MOTHERBOARD),1148) -# ADIMLab Gantry v2 -else ifeq ($(HARDWARE_MOTHERBOARD),1149) -# BIQU Tango V1 -else ifeq ($(HARDWARE_MOTHERBOARD),1150) -# MKS GEN L V2 -else ifeq ($(HARDWARE_MOTHERBOARD),1151) -# MKS GEN L V2.1 -else ifeq ($(HARDWARE_MOTHERBOARD),1152) -# Copymaster 3D -else ifeq ($(HARDWARE_MOTHERBOARD),1153) -# Ortur 4 -else ifeq ($(HARDWARE_MOTHERBOARD),1154) -# Tenlog D3 Hero -else ifeq ($(HARDWARE_MOTHERBOARD),1155) +# Zonestar zrib V5.3 (Chinese RAMPS replica) +else ifeq ($(HARDWARE_MOTHERBOARD),1162) +# Pxmalion Core I3 +else ifeq ($(HARDWARE_MOTHERBOARD),1163) # # RAMBo and derivatives @@ -512,7 +399,7 @@ else ifeq ($(HARDWARE_MOTHERBOARD),1324) else ifeq ($(HARDWARE_MOTHERBOARD),1325) # Intamsys 4.0 (Funmat HT) else ifeq ($(HARDWARE_MOTHERBOARD),1326) -# Malyan M180 Mainboard Version 2 (no display function, direct gcode only) +# 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) diff --git a/Marlin/Version.h b/Marlin/Version.h index 2a5b2d5abe..1d749e783c 100644 --- a/Marlin/Version.h +++ b/Marlin/Version.h @@ -28,7 +28,7 @@ /** * Marlin release version identifier */ -#define SHORT_BUILD_VERSION "DW7.4.6" +#define SHORT_BUILD_VERSION "DW7.4.7" /** * Verbose version identifier which should contain a reference to the location @@ -131,7 +131,7 @@ * here we define this default string as the date where the latest release * version was tagged. */ -#define STRING_DISTRIBUTION_DATE "2022-04-03" +#define STRING_DISTRIBUTION_DATE "2022-07-17" /** * Defines a generic printer name to be output to the LCD after booting Marlin. diff --git a/Marlin/src/HAL/AVR/HAL.cpp b/Marlin/src/HAL/AVR/HAL.cpp index 7c39c5200b..5382eb36a2 100644 --- a/Marlin/src/HAL/AVR/HAL.cpp +++ b/Marlin/src/HAL/AVR/HAL.cpp @@ -23,6 +23,7 @@ #include "../../inc/MarlinConfig.h" #include "HAL.h" +#include #ifdef USBCON DefaultSerial1 MSerial0(false, Serial); @@ -88,6 +89,62 @@ void MarlinHAL::reboot() { #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" diff --git a/Marlin/src/HAL/AVR/HAL.h b/Marlin/src/HAL/AVR/HAL.h index 55aa24b83e..3936fcd023 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 @@ -164,7 +166,7 @@ typedef Servo hal_servo_t; #define strtof strtod // ------------------------ -// Class Utilities +// Free Memory Accessor // ------------------------ #pragma GCC diagnostic push @@ -186,6 +188,10 @@ 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 from 0x0 @@ -229,7 +235,7 @@ public: SBI(DIDR0, ch); } - // Begin ADC sampling on the given channel + // 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; diff --git a/Marlin/src/HAL/AVR/Servo.cpp b/Marlin/src/HAL/AVR/Servo.cpp index 526352b773..0a1ef5337a 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 - } +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]++; // 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 + 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 +void initISR(const timer16_Sequence_t timer_index) { + switch (timer_index) { + default: break; - #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 _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 + // 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 + break; + #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 _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 + 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 + break; + #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 + #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(timer16_Sequence_t timer) { +void finISR(const timer16_Sequence_t timer_index) { // Disable use of the given timer #ifdef WIRING - if (timer == _timer1) { - CBI( - #if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__) - TIMSK1 - #else - TIMSK - #endif - , OCIE1A); // disable timer 1 output compare interrupt - timerDetach(TIMER1OUTCOMPAREA_INT); - } - else if (timer == _timer3) { - CBI( - #if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__) - TIMSK3 - #else - ETIMSK - #endif - , OCIE3A); // disable the timer3 output compare A interrupt - timerDetach(TIMER3OUTCOMPAREA_INT); + 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/inc/SanityCheck.h b/Marlin/src/HAL/AVR/inc/SanityCheck.h index 15a5be4cd2..1c1d8d4413 100644 --- a/Marlin/src/HAL/AVR/inc/SanityCheck.h +++ b/Marlin/src/HAL/AVR/inc/SanityCheck.h @@ -25,6 +25,30 @@ * 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 \ +) +#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 + /** * Checks for FAST PWM */ diff --git a/Marlin/src/HAL/AVR/pinsDebug.h b/Marlin/src/HAL/AVR/pinsDebug.h index 0f564df987..dab4e44715 100644 --- a/Marlin/src/HAL/AVR/pinsDebug.h +++ b/Marlin/src/HAL/AVR/pinsDebug.h @@ -74,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) diff --git a/Marlin/src/HAL/AVR/watchdog.cpp b/Marlin/src/HAL/AVR/watchdog.cpp deleted file mode 100644 index 3f10c4adff..0000000000 --- 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 a16c88b35e..0000000000 --- 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/HAL.cpp b/Marlin/src/HAL/DUE/HAL.cpp index bbd13dc05a..4353f16497 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" @@ -40,14 +40,15 @@ uint16_t MarlinHAL::adc_result; // Public functions // ------------------------ -TERN_(POSTMORTEM_DEBUGGING, extern void install_min_serial()); +#if ENABLED(POSTMORTEM_DEBUGGING) + extern void install_min_serial(); +#endif void MarlinHAL::init() { - // Initialize the USB stack #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 } @@ -72,6 +73,103 @@ uint8_t MarlinHAL::get_reset_source() { 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 } @@ -82,6 +180,10 @@ int freeMemory() { return (int)&free_memory - (heap_end ?: (int)&_ebss); } +// ------------------------ +// Serial Ports +// ------------------------ + // Forward the default serial ports #if USING_HW_SERIAL0 DefaultSerial1 MSerial0(false, Serial); diff --git a/Marlin/src/HAL/DUE/HAL.h b/Marlin/src/HAL/DUE/HAL.h index 9a02c9a0dc..4d3f4823a5 100644 --- a/Marlin/src/HAL/DUE/HAL.h +++ b/Marlin/src/HAL/DUE/HAL.h @@ -32,7 +32,6 @@ #include "../shared/math_32bit.h" #include "../shared/HAL_SPI.h" #include "fastio.h" -#include "watchdog.h" #include @@ -115,8 +114,8 @@ typedef Servo hal_servo_t; // // Interrupts // -#define sei() noInterrupts() -#define cli() interrupts() +#define sei() interrupts() +#define cli() noInterrupts() #define CRITICAL_SECTION_START() const bool _irqon = hal.isr_state(); hal.isr_off() #define CRITICAL_SECTION_END() if (_irqon) hal.isr_on() @@ -176,9 +175,13 @@ 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(); // Software reset + // 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(); } @@ -209,7 +212,7 @@ public: // Called by Temperature::init for each sensor at startup static void adc_enable(const uint8_t ch) {} - // Begin ADC sampling on the given channel + // 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? diff --git a/Marlin/src/HAL/DUE/HAL_SPI.cpp b/Marlin/src/HAL/DUE/HAL_SPI.cpp index c5e8f2433d..7e3fe01356 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 diff --git a/Marlin/src/HAL/DUE/HAL_MinSerial.cpp b/Marlin/src/HAL/DUE/MinSerial.cpp similarity index 98% rename from Marlin/src/HAL/DUE/HAL_MinSerial.cpp rename to Marlin/src/HAL/DUE/MinSerial.cpp index 93c4ed67d6..e5b3dbfe6f 100644 --- a/Marlin/src/HAL/DUE/HAL_MinSerial.cpp +++ b/Marlin/src/HAL/DUE/MinSerial.cpp @@ -25,7 +25,7 @@ #if ENABLED(POSTMORTEM_DEBUGGING) -#include "../shared/HAL_MinSerial.h" +#include "../shared/MinSerial.h" #include diff --git a/Marlin/src/HAL/DUE/Servo.cpp b/Marlin/src/HAL/DUE/Servo.cpp index 5524aa9cef..2dab88238d 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 +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]++; // 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 + 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 + 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 + ); - /* 84MHz, MCK/32, for 1.5ms: 3937 */ - TC_SetRA(tc, channel, 2625); // 1ms + // Wait 1ms before the first ISR + TC_SetRA(tc, channel, (F_CPU) / (SERVO_TIMER_PRESCALER) / 1000UL); // 1ms - /* Configure and enable interrupt */ + // 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 c32c938253..95bd404c80 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/eeprom_flash.cpp b/Marlin/src/HAL/DUE/eeprom_flash.cpp index 7ce4a84df5..607764155b 100644 --- a/Marlin/src/HAL/DUE/eeprom_flash.cpp +++ b/Marlin/src/HAL/DUE/eeprom_flash.cpp @@ -199,8 +199,7 @@ 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_ECHOLNPGM("EEPROM PageWrite ", page); + DEBUG_ECHO_MSG("EEPROM PageWrite ", page); DEBUG_ECHOLNPGM(" in FLASH address ", (uint32_t)addrflash); DEBUG_ECHOLNPGM(" base address ", (uint32_t)getFlashStorage(0)); DEBUG_FLUSH(); @@ -245,8 +244,7 @@ static bool ee_PageWrite(uint16_t page, const void *data) { // Reenable interrupts __enable_irq(); - DEBUG_ECHO_START(); - DEBUG_ECHOLNPGM("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_ECHOLNPGM("EEPROM Write failure for page ", page); + DEBUG_ECHO_MSG("EEPROM Write failure for page ", page); return false; } @@ -286,8 +283,7 @@ static bool ee_PageWrite(uint16_t page, const void *data) { if (memcmp(getFlashStorage(page),data,PageSize)) { #ifdef EE_EMU_DEBUG - DEBUG_ECHO_START(); - DEBUG_ECHOLNPGM("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); @@ -325,8 +321,7 @@ static bool ee_PageErase(uint16_t page) { uint16_t i; uint32_t addrflash = uint32_t(getFlashStorage(page)); - DEBUG_ECHO_START(); - DEBUG_ECHOLNPGM("EEPROM PageErase ", page); + DEBUG_ECHO_MSG("EEPROM PageErase ", page); DEBUG_ECHOLNPGM(" in FLASH address ", (uint32_t)addrflash); DEBUG_ECHOLNPGM(" base address ", (uint32_t)getFlashStorage(0)); DEBUG_FLUSH(); @@ -370,8 +365,7 @@ static bool ee_PageErase(uint16_t page) { // Reenable interrupts __enable_irq(); - DEBUG_ECHO_START(); - DEBUG_ECHOLNPGM("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_ECHOLNPGM("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_ECHOLNPGM("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; } @@ -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_ECHOLNPGM("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_ECHOLNPGM("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_ECHOLNPGM("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_ECHOLNPGM("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); diff --git a/Marlin/src/HAL/DUE/inc/SanityCheck.h b/Marlin/src/HAL/DUE/inc/SanityCheck.h index 75480acaf2..13484f7029 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 * diff --git a/Marlin/src/HAL/DUE/pinsDebug.h b/Marlin/src/HAL/DUE/pinsDebug.h index 6c08585974..df1ba415e9 100644 --- a/Marlin/src/HAL/DUE/pinsDebug.h +++ b/Marlin/src/HAL/DUE/pinsDebug.h @@ -86,7 +86,6 @@ 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; diff --git a/Marlin/src/HAL/DUE/timers.cpp b/Marlin/src/HAL/DUE/timers.cpp index a7bf7fbd6d..e5647817b6 100644 --- a/Marlin/src/HAL/DUE/timers.cpp +++ b/Marlin/src/HAL/DUE/timers.cpp @@ -89,10 +89,17 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) { 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); diff --git a/Marlin/src/HAL/DUE/timers.h b/Marlin/src/HAL/DUE/timers.h index bcfd07e268..dc35c77e63 100644 --- a/Marlin/src/HAL/DUE/timers.h +++ b/Marlin/src/HAL/DUE/timers.h @@ -35,7 +35,8 @@ 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 MF_TIMER_STEP #define MF_TIMER_STEP 2 // Timer Index for Stepper diff --git a/Marlin/src/HAL/DUE/usb/compiler.h b/Marlin/src/HAL/DUE/usb/compiler.h index f89e554c45..633197914e 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/watchdog.cpp b/Marlin/src/HAL/DUE/watchdog.cpp deleted file mode 100644 index e144db8291..0000000000 --- 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 = 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 -} - -#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/ESP32/HAL.cpp b/Marlin/src/HAL/ESP32/HAL.cpp index e204e0b6fe..29f3be3c02 100644 --- a/Marlin/src/HAL/ESP32/HAL.cpp +++ b/Marlin/src/HAL/ESP32/HAL.cpp @@ -65,6 +65,7 @@ portMUX_TYPE MarlinHAL::spinlock = portMUX_INITIALIZER_UNLOCKED; // ------------------------ uint16_t MarlinHAL::adc_result; +pwm_pin_t MarlinHAL::pwm_pin_data[MAX_EXPANDER_BITS]; // ------------------------ // Private Variables @@ -179,6 +180,31 @@ void _delay_ms(int delay_ms) { delay(delay_ms); } // return free memory between end of heap (or end bss) and whatever is current 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 // ------------------------ @@ -244,7 +270,8 @@ 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); - adc_result = mv * 1023.0f / float(ADC_REFERENCE_VOLTAGE) / 1000.0f; + + 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; @@ -304,21 +331,46 @@ int8_t get_pwm_channel(const pin_t pin, const uint32_t freq, const uint16_t res) } 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*/) { - const int8_t cid = get_pwm_channel(pin, PWM_FREQUENCY, PWM_RESOLUTION); - if (cid >= 0) { - uint32_t duty = map(invert ? v_size - v : v, 0, v_size, 0, _BV(PWM_RESOLUTION)-1); - ledcWrite(cid, duty); - } + #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 + } + 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) { - 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 + #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 diff --git a/Marlin/src/HAL/ESP32/HAL.h b/Marlin/src/HAL/ESP32/HAL.h index 8b26c3471d..ddfedf92ee 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) @@ -61,21 +60,31 @@ #endif #endif -#define CRITICAL_SECTION_START() portENTER_CRITICAL(&spinlock) -#define CRITICAL_SECTION_END() portEXIT_CRITICAL(&spinlock) +#define CRITICAL_SECTION_START() portENTER_CRITICAL(&hal.spinlock) +#define CRITICAL_SECTION_END() portEXIT_CRITICAL(&hal.spinlock) #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; +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; + class Servo; typedef Servo hal_servo_t; @@ -88,7 +97,7 @@ typedef Servo hal_servo_t; // 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); // @@ -171,9 +180,13 @@ 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 + // 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; @@ -193,6 +206,8 @@ public: // Free SRAM static int freeMemory(); + static pwm_pin_t pwm_pin_data[MAX_EXPANDER_BITS]; + // // ADC Methods // @@ -205,7 +220,7 @@ public: // Called by Temperature::init for each sensor at startup static void adc_enable(const pin_t pin) {} - // Begin ADC sampling on the given channel + // 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? diff --git a/Marlin/src/HAL/ESP32/i2s.cpp b/Marlin/src/HAL/ESP32/i2s.cpp index 3e77b65836..cf337eeb46 100644 --- a/Marlin/src/HAL/ESP32/i2s.cpp +++ b/Marlin/src/HAL/ESP32/i2s.cpp @@ -337,6 +337,26 @@ 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; } diff --git a/Marlin/src/HAL/ESP32/inc/Conditionals_adv.h b/Marlin/src/HAL/ESP32/inc/Conditionals_adv.h index 5f1c4b1601..3ca806897a 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 04d70ec14f..3ccb15989f 100644 --- a/Marlin/src/HAL/ESP32/inc/SanityCheck.h +++ b/Marlin/src/HAL/ESP32/inc/SanityCheck.h @@ -48,3 +48,7 @@ #if USING_PULLDOWNS #error "PULLDOWN pin mode is not available on ESP32 boards." #endif + +#if BOTH(I2S_STEPPER_STREAM, LIN_ADVANCE) + #error "I2S stream is currently incompatible with LIN_ADVANCE." +#endif diff --git a/Marlin/src/HAL/ESP32/u8g_esp32_spi.cpp b/Marlin/src/HAL/ESP32/u8g_esp32_spi.cpp index 0aa66ed2cf..a445035b2b 100644 --- a/Marlin/src/HAL/ESP32/u8g_esp32_spi.cpp +++ b/Marlin/src/HAL/ESP32/u8g_esp32_spi.cpp @@ -23,24 +23,17 @@ */ #ifdef ARDUINO_ARCH_ESP32 -#include "../../inc/MarlinConfigPre.h" +#include "../../inc/MarlinConfig.h" -#if ENABLED(FYSETC_MINI_12864_2_1) +#if EITHER(MKS_MINI_12864, FYSETC_MINI_12864_2_1) #include -#include "Arduino.h" #include "../shared/HAL_SPI.h" #include "HAL.h" #include "SPI.h" static SPISettings spiConfig; -#define MDOGLCD_MOSI 23 -#define MDOGLCD_SCK 18 -#define MLCD_RESET_PIN 0 -#define MLCD_PINS_DC 4 -#define MDOGLCD_CS 21 -#define MDOGLCD_A0 4 #ifndef LCD_SPI_SPEED #ifdef SD_SPI_SPEED @@ -61,24 +54,24 @@ uint8_t u8g_eps_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_pt case U8G_COM_MSG_STOP: break; case U8G_COM_MSG_INIT: - OUT_WRITE(MDOGLCD_CS, HIGH); - OUT_WRITE(MDOGLCD_A0, HIGH); - OUT_WRITE(MLCD_RESET_PIN, HIGH); + 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(MDOGLCD_A0, arg_val ? HIGH : LOW); + 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(MDOGLCD_CS, arg_val ? LOW : HIGH); + WRITE(DOGLCD_CS, arg_val ? LOW : HIGH); break; case U8G_COM_MSG_RESET: - WRITE(MLCD_RESET_PIN, arg_val); + WRITE(LCD_RESET_PIN, arg_val); break; case U8G_COM_MSG_WRITE_BYTE: @@ -96,5 +89,6 @@ uint8_t u8g_eps_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_pt return 1; } -#endif // FYSETC_MINI_12864_2_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 5ec03c4607..0000000000 --- a/Marlin/src/HAL/ESP32/watchdog.cpp +++ /dev/null @@ -1,42 +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) - -#define WDT_TIMEOUT_US TERN(WATCHDOG_DURATION_8S, 8000000, 4000000) // 4 or 8 second timeout - -#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/HAL.h b/Marlin/src/HAL/HAL.h index 0cd836af2b..5186578019 100644 --- a/Marlin/src/HAL/HAL.h +++ b/Marlin/src/HAL/HAL.h @@ -28,6 +28,7 @@ #endif #include HAL_PATH(.,HAL.h) +extern MarlinHAL hal; #define HAL_ADC_RANGE _BV(HAL_ADC_RESOLUTION) @@ -44,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.h b/Marlin/src/HAL/LINUX/HAL.h index 43899c632d..22c3e521f0 100644 --- a/Marlin/src/HAL/LINUX/HAL.h +++ b/Marlin/src/HAL/LINUX/HAL.h @@ -21,6 +21,8 @@ */ #pragma once +#include "../../inc/MarlinConfigPre.h" + #include #include #include @@ -29,12 +31,10 @@ #include #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" // ------------------------ @@ -106,9 +106,13 @@ 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 + static void reboot(); // Reset the application state and GPIO // Interrupts static bool isr_state() { return true; } diff --git a/Marlin/src/HAL/LINUX/eeprom.cpp b/Marlin/src/HAL/LINUX/eeprom.cpp index 532f323c6e..f878bba6a5 100644 --- a/Marlin/src/HAL/LINUX/eeprom.cpp +++ b/Marlin/src/HAL/LINUX/eeprom.cpp @@ -69,12 +69,12 @@ 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 } @@ -82,21 +82,21 @@ bool PersistentStore::read_data(int &pos, uint8_t *value, const size_t size, uin 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/Heater.h b/Marlin/src/HAL/LINUX/hardware/Heater.h index b17078d0b7..6d590ce6c5 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/watchdog.cpp b/Marlin/src/HAL/LINUX/watchdog.cpp deleted file mode 100644 index 84202e48b6..0000000000 --- a/Marlin/src/HAL/LINUX/watchdog.cpp +++ /dev/null @@ -1,37 +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" - -#define WDT_TIMEOUT_US TERN(WATCHDOG_DURATION_8S, 8000000, 4000000) // 4 or 8 second timeout - -void watchdog_init() {} -void HAL_watchdog_refresh() {} - -#endif - -#endif // __PLAT_LINUX__ diff --git a/Marlin/src/HAL/LPC1768/HAL.cpp b/Marlin/src/HAL/LPC1768/HAL.cpp index 541848b08a..9ff3a6ba59 100644 --- a/Marlin/src/HAL/LPC1768/HAL.cpp +++ b/Marlin/src/HAL/LPC1768/HAL.cpp @@ -25,10 +25,6 @@ #include "../shared/Delay.h" #include "../../../gcode/parser.h" -#if ENABLED(USE_WATCHDOG) - #include "watchdog.h" -#endif - DefaultSerial1 USBSerial(false, UsbSerial); uint32_t MarlinHAL::adc_result = 0; @@ -61,9 +57,7 @@ uint8_t MarlinHAL::get_reset_source() { return RST_POWER_ON; } -void MarlinHAL::clear_reset_source() { - TERN_(USE_WATCHDOG, watchdog_clear_timeout_flag()); -} +void MarlinHAL::clear_reset_source() { watchdog_clear_timeout_flag(); } void flashFirmware(const int16_t) { delay(500); // Give OS time to disconnect @@ -72,6 +66,52 @@ void flashFirmware(const int16_t) { 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. diff --git a/Marlin/src/HAL/LPC1768/HAL.h b/Marlin/src/HAL/LPC1768/HAL.h index eefacae995..b0eeb983b4 100644 --- a/Marlin/src/HAL/LPC1768/HAL.h +++ b/Marlin/src/HAL/LPC1768/HAL.h @@ -38,7 +38,6 @@ 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 @@ -177,7 +176,7 @@ void flashFirmware(const int16_t); #define CPU_ST7920_DELAY_3 750 // ------------------------ -// Class Utilities +// Free Memory Accessor // ------------------------ #pragma GCC diagnostic push @@ -199,9 +198,9 @@ public: // Earliest possible init, before setup() MarlinHAL() {} - static void init(); // Called early in setup() + static void init(); // Called early in setup() static void init_board() {} // Called less early in setup() - static void reboot(); // Restart the firmware from 0x0 + static void reboot(); // Restart the firmware from 0x0 // Interrupts static bool isr_state() { return !__get_PRIMASK(); } @@ -210,6 +209,12 @@ public: 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(); @@ -234,7 +239,7 @@ public: FilteredADC::enable_channel(pin); } - // Begin ADC sampling on the given 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 diff --git a/Marlin/src/HAL/LPC1768/HAL_MinSerial.cpp b/Marlin/src/HAL/LPC1768/MinSerial.cpp similarity index 97% rename from Marlin/src/HAL/LPC1768/HAL_MinSerial.cpp rename to Marlin/src/HAL/LPC1768/MinSerial.cpp index 57065c49ac..7a1c038c0b 100644 --- a/Marlin/src/HAL/LPC1768/HAL_MinSerial.cpp +++ b/Marlin/src/HAL/LPC1768/MinSerial.cpp @@ -26,7 +26,7 @@ #if ENABLED(POSTMORTEM_DEBUGGING) -#include "../shared/HAL_MinSerial.h" +#include "../shared/MinSerial.h" #include static void TX(char c) { _DBC(c); } diff --git a/Marlin/src/HAL/LPC1768/eeprom_wired.cpp b/Marlin/src/HAL/LPC1768/eeprom_wired.cpp index f9286a74ac..1bbc39d4a2 100644 --- a/Marlin/src/HAL/LPC1768/eeprom_wired.cpp +++ b/Marlin/src/HAL/LPC1768/eeprom_wired.cpp @@ -34,7 +34,7 @@ #include "../shared/eeprom_api.h" #ifndef MARLIN_EEPROM_SIZE - #define MARLIN_EEPROM_SIZE 0x8000 // 32KB‬ + #define MARLIN_EEPROM_SIZE 0x8000 // 32K #endif size_t PersistentStore::capacity() { return MARLIN_EEPROM_SIZE; } diff --git a/Marlin/src/HAL/LPC1768/watchdog.cpp b/Marlin/src/HAL/LPC1768/watchdog.cpp deleted file mode 100644 index f23ccf5b51..0000000000 --- a/Marlin/src/HAL/LPC1768/watchdog.cpp +++ /dev/null @@ -1,72 +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 "../../inc/MarlinConfig.h" - -#if ENABLED(USE_WATCHDOG) - -#include -#include "watchdog.h" - -#define WDT_TIMEOUT_US TERN(WATCHDOG_DURATION_8S, 8000000, 4000000) // 4 or 8 second timeout - -void 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 HAL_watchdog_refresh() { - WDT_Feed(); - #if DISABLED(PINS_DEBUGGING) && PIN_EXISTS(LED) - TOGGLE(LED_PIN); // heartbeat indicator - #endif -} - -// Timeout state -bool watchdog_timed_out() { return TEST(WDT_ReadTimeOutFlag(), 0); } -void watchdog_clear_timeout_flag() { WDT_ClrTimeOutFlag(); } - -#endif // USE_WATCHDOG -#endif // TARGET_LPC1768 diff --git a/Marlin/src/HAL/LPC1768/watchdog.h b/Marlin/src/HAL/LPC1768/watchdog.h deleted file mode 100644 index c843f0ed55..0000000000 --- a/Marlin/src/HAL/LPC1768/watchdog.h +++ /dev/null @@ -1,28 +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 - -void watchdog_init(); -void HAL_watchdog_refresh(); - -bool watchdog_timed_out(); -void watchdog_clear_timeout_flag(); diff --git a/Marlin/src/HAL/NATIVE_SIM/HAL.h b/Marlin/src/HAL/NATIVE_SIM/HAL.h index ee2e31fc7f..6620361144 100644 --- a/Marlin/src/HAL/NATIVE_SIM/HAL.h +++ b/Marlin/src/HAL/NATIVE_SIM/HAL.h @@ -45,7 +45,6 @@ uint8_t _getc(); #include "../shared/math_32bit.h" #include "../shared/HAL_SPI.h" #include "fastio.h" -#include "watchdog.h" #include "serial.h" // ------------------------ @@ -186,7 +185,7 @@ constexpr inline char* strstr_constexpr(char* str, const char* target) { } // ------------------------ -// Class Utilities +// Free Memory Accessor // ------------------------ #pragma GCC diagnostic push @@ -208,6 +207,10 @@ 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 from 0x0 @@ -242,7 +245,7 @@ public: // Called by Temperature::init for each sensor at startup static void adc_enable(const uint8_t ch); - // Begin ADC sampling on the given channel + // Begin ADC sampling on the given channel. Called from Temperature::isr! static void adc_start(const uint8_t ch); // Is the ADC ready for reading? diff --git a/Marlin/src/HAL/NATIVE_SIM/u8g/LCD_pin_routines.cpp b/Marlin/src/HAL/NATIVE_SIM/u8g/LCD_pin_routines.cpp index 3b5acc1656..91b7e0f67f 100644 --- a/Marlin/src/HAL/NATIVE_SIM/u8g/LCD_pin_routines.cpp +++ b/Marlin/src/HAL/NATIVE_SIM/u8g/LCD_pin_routines.cpp @@ -38,13 +38,13 @@ #ifdef __cplusplus extern "C" { #endif -void u8g_SetPinOutput(uint8_t internal_pin_number){SET_DIR_OUTPUT(internal_pin_number);} -void u8g_SetPinInput(uint8_t internal_pin_number){SET_DIR_INPUT(internal_pin_number);} -void u8g_SetPinLevel(uint8_t pin, uint8_t pin_status){WRITE_PIN(pin, pin_status);} -uint8_t u8g_GetPinLevel(uint8_t pin){return READ_PIN(pin);} -void usleep(uint64_t microsec){ -assert(false); // why we here? -} + +void u8g_SetPinOutput(uint8_t internal_pin_number) { SET_DIR_OUTPUT(internal_pin_number); } +void u8g_SetPinInput(uint8_t internal_pin_number) { SET_DIR_INPUT(internal_pin_number); } +void u8g_SetPinLevel(uint8_t pin, uint8_t pin_status) { WRITE_PIN(pin, pin_status); } +uint8_t u8g_GetPinLevel(uint8_t pin) { return READ_PIN(pin); } +void usleep(uint64_t microsec) { assert(false); /* why we here? */ } + #ifdef __cplusplus } #endif diff --git a/Marlin/src/HAL/SAMD51/HAL.cpp b/Marlin/src/HAL/SAMD51/HAL.cpp index 14b6a437dc..bd1c98bfa1 100644 --- a/Marlin/src/HAL/SAMD51/HAL.cpp +++ b/Marlin/src/HAL/SAMD51/HAL.cpp @@ -203,6 +203,40 @@ enum ADCIndex { ADC_COUNT }; +#if ENABLED(USE_WATCHDOG) + + #define WDT_TIMEOUT_REG TERN(WATCHDOG_DURATION_8S, WDT_CONFIG_PER_CYC8192, WDT_CONFIG_PER_CYC4096) // 4 or 8 second timeout + + void MarlinHAL::watchdog_init() { + // The low-power oscillator used by the WDT runs at 32,768 Hz with + // a 1:32 prescale, thus 1024 Hz, though probably not super precise. + + // Setup WDT clocks + MCLK->APBAMASK.bit.OSC32KCTRL_ = true; + MCLK->APBAMASK.bit.WDT_ = true; + OSC32KCTRL->OSCULP32K.bit.EN1K = true; // Enable out 1K (this is what WDT uses) + + WDT->CTRLA.bit.ENABLE = false; // Disable watchdog for config + SYNC(WDT->SYNCBUSY.bit.ENABLE); + + WDT->INTENCLR.reg = WDT_INTENCLR_EW; // Disable early warning interrupt + WDT->CONFIG.reg = WDT_TIMEOUT_REG; // Set a 4s or 8s period for chip reset + + hal.watchdog_refresh(); + + WDT->CTRLA.reg = WDT_CTRLA_ENABLE; // Start watchdog now in normal mode + SYNC(WDT->SYNCBUSY.bit.ENABLE); + } + + // Reset watchdog. MUST be called at least every 4 seconds after the + // first watchdog_init or SAMD will go into emergency procedures. + void MarlinHAL::watchdog_refresh() { + SYNC(WDT->SYNCBUSY.bit.CLEAR); // Test first if previous is 'ongoing' to save time waiting for command execution + WDT->CLEAR.reg = WDT_CLEAR_CLEAR_KEY; + } + +#endif + // ------------------------ // Types // ------------------------ @@ -564,7 +598,7 @@ void MarlinHAL::dma_init() { void MarlinHAL::init() { TERN_(DMA_IS_REQUIRED, dma_init()); #if ENABLED(SDSUPPORT) - #if SD_CONNECTION_IS(ONBOARD) && PIN_EXISTS(SD_DETECT) + #if HAS_SD_DETECT && SD_CONNECTION_IS(ONBOARD) SET_INPUT_PULLUP(SD_DETECT_PIN); #endif OUT_WRITE(SDSS, HIGH); // Try to set SDSS inactive before any other SPI users start up diff --git a/Marlin/src/HAL/SAMD51/HAL.h b/Marlin/src/HAL/SAMD51/HAL.h index 3b09a885a5..79ba8021f4 100644 --- a/Marlin/src/HAL/SAMD51/HAL.h +++ b/Marlin/src/HAL/SAMD51/HAL.h @@ -26,7 +26,6 @@ #include "../shared/math_32bit.h" #include "../shared/HAL_SPI.h" #include "fastio.h" -#include "watchdog.h" #ifdef ADAFRUIT_GRAND_CENTRAL_M4 #include "MarlinSerial_AGCM4.h" @@ -157,6 +156,10 @@ 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 from 0x0 @@ -190,7 +193,7 @@ public: // Called by Temperature::init for each sensor at startup static void adc_enable(const uint8_t ch) {} - // Begin ADC sampling on the given channel + // 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? diff --git a/Marlin/src/HAL/SAMD51/Servo.cpp b/Marlin/src/HAL/SAMD51/Servo.cpp index 23ab21c615..665322fe24 100644 --- a/Marlin/src/HAL/SAMD51/Servo.cpp +++ b/Marlin/src/HAL/SAMD51/Servo.cpp @@ -77,7 +77,8 @@ HAL_SERVO_TIMER_ISR() { ; const uint8_t tcChannel = TIMER_TCCHANNEL(timer); - if (currentServoIndex[timer] < 0) { + int8_t cho = currentServoIndex[timer]; // Handle the prior servo first + if (cho < 0) { // Servo -1 indicates the refresh interval completed... #if defined(_useTimer1) && defined(_useTimer2) if (currentServoIndex[timer ^ 1] >= 0) { // Wait for both channels @@ -86,45 +87,37 @@ HAL_SERVO_TIMER_ISR() { return; } #endif - tc->COUNT16.COUNT.reg = TC_COUNTER_START_VAL; + tc->COUNT16.COUNT.reg = TC_COUNTER_START_VAL; // ...so reset the timer SYNC(tc->COUNT16.SYNCBUSY.bit.COUNT); } - else if (SERVO_INDEX(timer, currentServoIndex[timer]) < ServoCount && SERVO(timer, currentServoIndex[timer]).Pin.isActive) - digitalWrite(SERVO(timer, currentServoIndex[timer]).Pin.nbr, LOW); // pulse this channel low if activated + else if (SERVO_INDEX(timer, cho) < ServoCount) // prior channel handled? + digitalWrite(SERVO(timer, cho).Pin.nbr, LOW); // pulse the prior channel LOW - // Select the next servo controlled by this timer - currentServoIndex[timer]++; + currentServoIndex[timer] = ++cho; // go to the next channel (or 0) + if (cho < SERVOS_PER_TIMER && SERVO_INDEX(timer, cho) < ServoCount) { + if (SERVO(timer, cho).Pin.isActive) // activated? + digitalWrite(SERVO(timer, cho).Pin.nbr, HIGH); // yes: pulse HIGH - if (SERVO_INDEX(timer, currentServoIndex[timer]) < ServoCount && currentServoIndex[timer] < SERVOS_PER_TIMER) { - if (SERVO(timer, currentServoIndex[timer]).Pin.isActive) // check if activated - digitalWrite(SERVO(timer, currentServoIndex[timer]).Pin.nbr, HIGH); // it's an active channel so pulse it high - - tc->COUNT16.CC[tcChannel].reg = getTimerCount() - (uint16_t)SERVO(timer, currentServoIndex[timer]).ticks; + tc->COUNT16.CC[tcChannel].reg = getTimerCount() - (uint16_t)SERVO(timer, cho).ticks; } else { // finished all channels so wait for the refresh period to expire before starting over - currentServoIndex[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel - - const uint16_t tcCounterValue = getTimerCount(); - - if ((TC_COUNTER_START_VAL - tcCounterValue) + 4UL < usToTicks(REFRESH_INTERVAL)) // allow a few ticks to ensure the next OCR1A not missed - tc->COUNT16.CC[tcChannel].reg = TC_COUNTER_START_VAL - (uint16_t)usToTicks(REFRESH_INTERVAL); - else - tc->COUNT16.CC[tcChannel].reg = (uint16_t)(tcCounterValue - 4UL); // at least REFRESH_INTERVAL has elapsed + currentServoIndex[timer] = -1; // reset the timer COUNT.reg on the next call + const uint16_t cval = getTimerCount() - 256 / (SERVO_TIMER_PRESCALER), // allow 256 cycles to ensure the next CV not missed + ival = (TC_COUNTER_START_VAL) - (uint16_t)usToTicks(REFRESH_INTERVAL); // at least REFRESH_INTERVAL has elapsed + tc->COUNT16.CC[tcChannel].reg = min(cval, ival); } if (tcChannel == 0) { SYNC(tc->COUNT16.SYNCBUSY.bit.CC0); - // Clear the interrupt - tc->COUNT16.INTFLAG.reg = TC_INTFLAG_MC0; + tc->COUNT16.INTFLAG.reg = TC_INTFLAG_MC0; // Clear the interrupt } else { SYNC(tc->COUNT16.SYNCBUSY.bit.CC1); - // Clear the interrupt - tc->COUNT16.INTFLAG.reg = TC_INTFLAG_MC1; + tc->COUNT16.INTFLAG.reg = TC_INTFLAG_MC1; // Clear the interrupt } } -void initISR(timer16_Sequence_t timer) { +void initISR(const timer16_Sequence_t timer) { Tc * const tc = timer_config[SERVO_TC].pTc; const uint8_t tcChannel = TIMER_TCCHANNEL(timer); @@ -201,9 +194,9 @@ void initISR(timer16_Sequence_t timer) { } } -void finISR(timer16_Sequence_t timer) { +void finISR(const timer16_Sequence_t timer_index) { Tc * const tc = timer_config[SERVO_TC].pTc; - const uint8_t tcChannel = TIMER_TCCHANNEL(timer); + const uint8_t tcChannel = TIMER_TCCHANNEL(timer_index); // Disable the match channel interrupt request tc->COUNT16.INTENCLR.reg = (tcChannel == 0) ? TC_INTENCLR_MC0 : TC_INTENCLR_MC1; diff --git a/Marlin/src/HAL/SAMD51/watchdog.cpp b/Marlin/src/HAL/SAMD51/watchdog.cpp deleted file mode 100644 index 9de451836a..0000000000 --- a/Marlin/src/HAL/SAMD51/watchdog.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/** - * Marlin 3D Printer Firmware - * - * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] - * 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 __SAMD51__ - -#include "../../inc/MarlinConfig.h" - -#if ENABLED(USE_WATCHDOG) - -#include "watchdog.h" - -#define WDT_TIMEOUT_REG TERN(WATCHDOG_DURATION_8S, WDT_CONFIG_PER_CYC8192, WDT_CONFIG_PER_CYC4096) // 4 or 8 second timeout - -void watchdog_init() { - // The low-power oscillator used by the WDT runs at 32,768 Hz with - // a 1:32 prescale, thus 1024 Hz, though probably not super precise. - - // Setup WDT clocks - MCLK->APBAMASK.bit.OSC32KCTRL_ = true; - MCLK->APBAMASK.bit.WDT_ = true; - OSC32KCTRL->OSCULP32K.bit.EN1K = true; // Enable out 1K (this is what WDT uses) - - WDT->CTRLA.bit.ENABLE = false; // Disable watchdog for config - SYNC(WDT->SYNCBUSY.bit.ENABLE); - - WDT->INTENCLR.reg = WDT_INTENCLR_EW; // Disable early warning interrupt - WDT->CONFIG.reg = WDT_TIMEOUT_REG; // Set a 4s or 8s period for chip reset - - HAL_watchdog_refresh(); - - WDT->CTRLA.reg = WDT_CTRLA_ENABLE; // Start watchdog now in normal mode - SYNC(WDT->SYNCBUSY.bit.ENABLE); -} - -#endif // USE_WATCHDOG - -#endif // __SAMD51__ diff --git a/Marlin/src/HAL/SAMD51/watchdog.h b/Marlin/src/HAL/SAMD51/watchdog.h deleted file mode 100644 index 2cd4788229..0000000000 --- a/Marlin/src/HAL/SAMD51/watchdog.h +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Marlin 3D Printer Firmware - * - * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] - * 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 . - * - */ -#pragma once - -// 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 SAMD will go into emergency procedures. -inline void HAL_watchdog_refresh() { - SYNC(WDT->SYNCBUSY.bit.CLEAR); // Test first if previous is 'ongoing' to save time waiting for command execution - WDT->CLEAR.reg = WDT_CLEAR_CLEAR_KEY; -} diff --git a/Marlin/src/HAL/STM32/HAL.cpp b/Marlin/src/HAL/STM32/HAL.cpp index d28f506db9..aff52f597f 100644 --- a/Marlin/src/HAL/STM32/HAL.cpp +++ b/Marlin/src/HAL/STM32/HAL.cpp @@ -24,14 +24,13 @@ #ifdef HAL_STM32 -#include "HAL.h" -#include "usb_serial.h" - #include "../../inc/MarlinConfig.h" #include "../shared/Delay.h" +#include "usb_serial.h" + #ifdef USBCON - DefaultSerial1 MSerial0(false, SerialUSB); + DefaultSerial1 MSerialUSB(false, SerialUSB); #endif #if ENABLED(SRAM_EEPROM_EMULATION) @@ -141,6 +140,29 @@ uint8_t MarlinHAL::get_reset_source() { void MarlinHAL::clear_reset_source() { __HAL_RCC_CLEAR_RESET_FLAGS(); } +// ------------------------ +// Watchdog Timer +// ------------------------ + +#if ENABLED(USE_WATCHDOG) + + #define WDT_TIMEOUT_US TERN(WATCHDOG_DURATION_8S, 8000000, 4000000) // 4 or 8 second timeout + + #include + + void MarlinHAL::watchdog_init() { + IF_DISABLED(DISABLE_WATCHDOG_INIT, IWatchdog.begin(WDT_TIMEOUT_US)); + } + + void MarlinHAL::watchdog_refresh() { + IWatchdog.reload(); + #if DISABLED(PINS_DEBUGGING) && PIN_EXISTS(LED) + TOGGLE(LED_PIN); // heartbeat indicator + #endif + } + +#endif + extern "C" { extern unsigned int _ebss; // end of bss section } diff --git a/Marlin/src/HAL/STM32/HAL.h b/Marlin/src/HAL/STM32/HAL.h index 08af395382..384c684497 100644 --- a/Marlin/src/HAL/STM32/HAL.h +++ b/Marlin/src/HAL/STM32/HAL.h @@ -30,7 +30,6 @@ #include "../shared/HAL_SPI.h" #include "fastio.h" #include "Servo.h" -#include "watchdog.h" #include "MarlinSerial.h" #include "../../inc/MarlinConfigPre.h" @@ -51,57 +50,67 @@ #include #include "../../core/serial_hook.h" typedef ForwardSerial1Class< decltype(SerialUSB) > DefaultSerial1; - extern DefaultSerial1 MSerial0; + extern DefaultSerial1 MSerialUSB; #endif #define _MSERIAL(X) MSerial##X #define MSERIAL(X) _MSERIAL(X) -#if SERIAL_PORT == -1 - #define MYSERIAL1 MSerial0 -#elif WITHIN(SERIAL_PORT, 1, 6) +#if WITHIN(SERIAL_PORT, 1, 6) #define MYSERIAL1 MSERIAL(SERIAL_PORT) +#elif !defined(USBCON) + #error "SERIAL_PORT must be from 1 to 6." +#elif SERIAL_PORT == -1 + #define MYSERIAL1 MSerialUSB #else - #error "SERIAL_PORT must be from 1 to 6. You can also use -1 if the board supports Native USB." + #error "SERIAL_PORT must be from 1 to 6, or -1 for Native USB." #endif #ifdef SERIAL_PORT_2 - #if SERIAL_PORT_2 == -1 - #define MYSERIAL2 MSerial0 - #elif WITHIN(SERIAL_PORT_2, 1, 6) + #if WITHIN(SERIAL_PORT_2, 1, 6) #define MYSERIAL2 MSERIAL(SERIAL_PORT_2) + #elif !defined(USBCON) + #error "SERIAL_PORT must be from 1 to 6." + #elif SERIAL_PORT_2 == -1 + #define MYSERIAL2 MSerialUSB #else - #error "SERIAL_PORT_2 must be from 1 to 6. You can also use -1 if the board supports Native USB." + #error "SERIAL_PORT_2 must be from 1 to 6, or -1 for Native USB." #endif #endif #ifdef SERIAL_PORT_3 - #if SERIAL_PORT_3 == -1 - #define MYSERIAL3 MSerial0 - #elif WITHIN(SERIAL_PORT_3, 1, 6) + #if WITHIN(SERIAL_PORT_3, 1, 6) #define MYSERIAL3 MSERIAL(SERIAL_PORT_3) + #elif !defined(USBCON) + #error "SERIAL_PORT must be from 1 to 6." + #elif SERIAL_PORT_3 == -1 + #define MYSERIAL3 MSerialUSB #else - #error "SERIAL_PORT_3 must be from 1 to 6. You can also use -1 if the board supports Native USB." + #error "SERIAL_PORT_3 must be from 1 to 6, or -1 for Native USB." #endif #endif #ifdef MMU2_SERIAL_PORT - #if MMU2_SERIAL_PORT == -1 - #define MMU2_SERIAL MSerial0 - #elif WITHIN(MMU2_SERIAL_PORT, 1, 6) + #if WITHIN(MMU2_SERIAL_PORT, 1, 6) #define MMU2_SERIAL MSERIAL(MMU2_SERIAL_PORT) + #elif !defined(USBCON) + #error "SERIAL_PORT must be from 1 to 6." + #elif MMU2_SERIAL_PORT == -1 + #define MMU2_SERIAL MSerialUSB #else - #error "MMU2_SERIAL_PORT must be from 1 to 6. You can also use -1 if the board supports Native USB." + #error "MMU2_SERIAL_PORT must be from 1 to 6, or -1 for Native USB." #endif #endif #ifdef LCD_SERIAL_PORT - #if LCD_SERIAL_PORT == -1 - #define LCD_SERIAL MSerial0 - #elif WITHIN(LCD_SERIAL_PORT, 1, 6) + #if WITHIN(LCD_SERIAL_PORT, 1, 6) #define LCD_SERIAL MSERIAL(LCD_SERIAL_PORT) + #elif !defined(USBCON) + #error "SERIAL_PORT must be from 1 to 6." + #elif LCD_SERIAL_PORT == -1 + #define LCD_SERIAL MSerialUSB #else - #error "LCD_SERIAL_PORT must be from 1 to 6. You can also use -1 if the board supports Native USB." + #error "LCD_SERIAL_PORT must be from 1 to 6, or -1 for Native USB." #endif #if HAS_DGUS_LCD || ENABLED(DGUS_LCD_UI_CREALITY_TOUCH) #define SERIAL_GET_TX_BUFFER_FREE() LCD_SERIAL.availableForWrite() @@ -127,6 +136,8 @@ // Types // ------------------------ +typedef double isr_float_t; // FPU ops are used for single-precision, so use double for ISRs. + #ifdef STM32G0B1xx typedef int32_t pin_t; #else @@ -206,9 +217,13 @@ public: // Earliest possible init, before setup() MarlinHAL() {} - static void init(); // Called early in setup() + // 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 from 0x0 + static void reboot(); // Restart the firmware from 0x0 // Interrupts static bool isr_state() { return !__get_PRIMASK(); } @@ -241,7 +256,7 @@ public: // Called by Temperature::init for each sensor at startup static void adc_enable(const pin_t pin) { pinMode(pin, INPUT); } - // Begin ADC sampling on the given channel + // Begin ADC sampling on the given pin. Called from Temperature::isr! static void adc_start(const pin_t pin) { adc_result = analogRead(pin); } // Is the ADC ready for reading? diff --git a/Marlin/src/HAL/STM32/HAL_MinSerial.cpp b/Marlin/src/HAL/STM32/MinSerial.cpp similarity index 97% rename from Marlin/src/HAL/STM32/HAL_MinSerial.cpp rename to Marlin/src/HAL/STM32/MinSerial.cpp index b6e86b72da..b0fcff20c1 100644 --- a/Marlin/src/HAL/STM32/HAL_MinSerial.cpp +++ b/Marlin/src/HAL/STM32/MinSerial.cpp @@ -28,8 +28,7 @@ #if ENABLED(POSTMORTEM_DEBUGGING) -#include "../shared/HAL_MinSerial.h" -#include "watchdog.h" +#include "../shared/MinSerial.h" /* Instruction Synchronization Barrier */ #define isb() __asm__ __volatile__ ("isb" : : : "memory") @@ -120,7 +119,7 @@ static void TX(char c) { #if WITHIN(SERIAL_PORT, 1, 6) constexpr uint32_t usart_sr_txe = _BV(7); while (!(regs->SR & usart_sr_txe)) { - TERN_(USE_WATCHDOG, HAL_watchdog_refresh()); + hal.watchdog_refresh(); sw_barrier(); } regs->DR = c; diff --git a/Marlin/src/HAL/STM32/msc_sd.cpp b/Marlin/src/HAL/STM32/msc_sd.cpp index 4f85af0d44..a40bec9d64 100644 --- a/Marlin/src/HAL/STM32/msc_sd.cpp +++ b/Marlin/src/HAL/STM32/msc_sd.cpp @@ -57,7 +57,7 @@ public: auto sd2card = diskIODriver(); // single block if (blkLen == 1) { - watchdog_refresh(); + hal.watchdog_refresh(); sd2card->writeBlock(blkAddr, pBuf); return true; } @@ -65,7 +65,7 @@ public: // multi block optimization sd2card->writeStart(blkAddr, blkLen); while (blkLen--) { - watchdog_refresh(); + hal.watchdog_refresh(); sd2card->writeData(pBuf); pBuf += BLOCK_SIZE; } @@ -77,7 +77,7 @@ public: auto sd2card = diskIODriver(); // single block if (blkLen == 1) { - watchdog_refresh(); + hal.watchdog_refresh(); sd2card->readBlock(blkAddr, pBuf); return true; } @@ -85,7 +85,7 @@ public: // multi block optimization sd2card->readStart(blkAddr); while (blkLen--) { - watchdog_refresh(); + hal.watchdog_refresh(); sd2card->readData(pBuf); pBuf += BLOCK_SIZE; } diff --git a/Marlin/src/HAL/STM32/pinsDebug.h b/Marlin/src/HAL/STM32/pinsDebug.h index a7f022a0b6..55c64c8681 100644 --- a/Marlin/src/HAL/STM32/pinsDebug.h +++ b/Marlin/src/HAL/STM32/pinsDebug.h @@ -79,7 +79,6 @@ // make a list of the Arduino pin numbers in the Port/Pin order // -#define _PIN_ADD_2(NAME_ALPHA, ARDUINO_NUM) { {NAME_ALPHA}, ARDUINO_NUM }, #define _PIN_ADD(NAME_ALPHA, ARDUINO_NUM) { NAME_ALPHA, ARDUINO_NUM }, #define PIN_ADD(NAME) _PIN_ADD(#NAME, NAME) @@ -108,7 +107,11 @@ const XrefInfo pin_xref[] PROGMEM = { /** * Translation of routines & variables used by pinsDebug.h */ -#define NUMBER_PINS_TOTAL NUM_DIGITAL_PINS + +#if PA0 >= NUM_DIGITAL_PINS + #define HAS_HIGH_ANALOG_PINS 1 +#endif +#define NUMBER_PINS_TOTAL NUM_DIGITAL_PINS + TERN0(HAS_HIGH_ANALOG_PINS, NUM_ANALOG_INPUTS) #define VALID_PIN(ANUM) ((ANUM) >= 0 && (ANUM) < NUMBER_PINS_TOTAL) #define digitalRead_mod(Ard_num) extDigitalRead(Ard_num) // must use Arduino pin numbers when doing reads #define PRINT_PIN(Q) @@ -164,17 +167,20 @@ bool GET_PINMODE(const pin_t Ard_num) { return pin_mode == MODE_PIN_OUTPUT || pin_mode == MODE_PIN_ALT; // assume all alt definitions are PWM } -int8_t digital_pin_to_analog_pin(pin_t Ard_num) { - Ard_num -= NUM_ANALOG_FIRST; - return (Ard_num >= 0 && Ard_num < NUM_ANALOG_INPUTS) ? Ard_num : -1; +int8_t digital_pin_to_analog_pin(const pin_t Ard_num) { + if (WITHIN(Ard_num, NUM_ANALOG_FIRST, NUM_ANALOG_FIRST + NUM_ANALOG_INPUTS - 1)) + return Ard_num - NUM_ANALOG_FIRST; + + const uint32_t ind = digitalPinToAnalogInput(Ard_num); + return (ind < NUM_ANALOG_INPUTS) ? ind : -1; } bool IS_ANALOG(const pin_t Ard_num) { return get_pin_mode(Ard_num) == MODE_PIN_ANALOG; } -bool is_digital(const pin_t x) { - const uint8_t pin_mode = get_pin_mode(pin_array[x].pin); +bool is_digital(const pin_t Ard_num) { + const uint8_t pin_mode = get_pin_mode(pin_array[Ard_num].pin); return pin_mode == MODE_PIN_INPUT || pin_mode == MODE_PIN_OUTPUT; } @@ -200,10 +206,15 @@ void port_print(const pin_t Ard_num) { SERIAL_ECHO_SP(7); // Print number to be used with M42 - sprintf_P(buffer, PSTR(" M42 P%d "), Ard_num); - SERIAL_ECHO(buffer); - if (Ard_num < 10) SERIAL_CHAR(' '); - if (Ard_num < 100) SERIAL_CHAR(' '); + int calc_p = Ard_num % (NUM_DIGITAL_PINS + 1); + if (Ard_num > NUM_DIGITAL_PINS && calc_p > 7) calc_p += 8; + SERIAL_ECHOPGM(" M42 P", calc_p); + SERIAL_CHAR(' '); + if (calc_p < 100) { + SERIAL_CHAR(' '); + if (calc_p < 10) + SERIAL_CHAR(' '); + } } bool pwm_status(const pin_t Ard_num) { @@ -225,19 +236,19 @@ void pwm_details(const pin_t Ard_num) { case 'D' : alt_all = GPIOD->AFR[ind]; break; #ifdef PE_0 case 'E' : alt_all = GPIOE->AFR[ind]; break; - #elif defined (PF_0) + #elif defined(PF_0) case 'F' : alt_all = GPIOF->AFR[ind]; break; - #elif defined (PG_0) + #elif defined(PG_0) case 'G' : alt_all = GPIOG->AFR[ind]; break; - #elif defined (PH_0) + #elif defined(PH_0) case 'H' : alt_all = GPIOH->AFR[ind]; break; - #elif defined (PI_0) + #elif defined(PI_0) case 'I' : alt_all = GPIOI->AFR[ind]; break; - #elif defined (PJ_0) + #elif defined(PJ_0) case 'J' : alt_all = GPIOJ->AFR[ind]; break; - #elif defined (PK_0) + #elif defined(PK_0) case 'K' : alt_all = GPIOK->AFR[ind]; break; - #elif defined (PL_0) + #elif defined(PL_0) case 'L' : alt_all = GPIOL->AFR[ind]; break; #endif } diff --git a/Marlin/src/HAL/STM32/sdio.cpp b/Marlin/src/HAL/STM32/sdio.cpp index 0af5f9040e..41fe90b825 100644 --- a/Marlin/src/HAL/STM32/sdio.cpp +++ b/Marlin/src/HAL/STM32/sdio.cpp @@ -33,7 +33,6 @@ #include #include -// use local drivers #if defined(STM32F103xE) || defined(STM32F103xG) #include #include @@ -47,254 +46,397 @@ #include #include #include +#elif defined(STM32H7xx) + #define SDIO_FOR_STM32H7 + #include + #include + #include + #include #else - #error "SDIO only supported with STM32F103xE, STM32F103xG, STM32F4xx, or STM32F7xx." + #error "SDIO is only supported with STM32F103xE, STM32F103xG, STM32F4xx, STM32F7xx, and STM32H7xx." #endif -SD_HandleTypeDef hsd; // create SDIO structure -// F4 supports one DMA for RX and another for TX, but Marlin will never -// do read and write at same time, so we use the same DMA for both. -DMA_HandleTypeDef hdma_sdio; - -/* - SDIO_INIT_CLK_DIV is 118 - SDIO clock frequency is 48MHz / (TRANSFER_CLOCK_DIV + 2) - SDIO init clock frequency should not exceed 400kHz = 48MHz / (118 + 2) - - Default TRANSFER_CLOCK_DIV is 2 (118 / 40) - Default SDIO clock frequency is 48MHz / (2 + 2) = 12 MHz - This might be too fast for stable SDIO operations - - MKS Robin board seems to have stable SDIO with BusWide 1bit and ClockDiv 8 i.e. 4.8MHz SDIO clock frequency - Additional testing is required as there are clearly some 4bit initialization problems -*/ - -#ifndef USBD_OK - #define USBD_OK 0 -#endif +// SDIO Max Clock (naming from STM Manual, don't change) +#define SDIOCLK 48000000 // Target Clock, configurable. Default is 18MHz, from STM32F1 #ifndef SDIO_CLOCK #define SDIO_CLOCK 18000000 // 18 MHz #endif -// SDIO retries, configurable. Default is 3, from STM32F1 -#ifndef SDIO_READ_RETRIES - #define SDIO_READ_RETRIES 3 -#endif - -// SDIO Max Clock (naming from STM Manual, don't change) -#define SDIOCLK 48000000 +SD_HandleTypeDef hsd; // SDIO structure static uint32_t clock_to_divider(uint32_t clk) { - // limit the SDIO master clock to 8/3 of PCLK2. See STM32 Manuals - // Also limited to no more than 48Mhz (SDIOCLK). - const uint32_t pclk2 = HAL_RCC_GetPCLK2Freq(); - clk = min(clk, (uint32_t)(pclk2 * 8 / 3)); - clk = min(clk, (uint32_t)SDIOCLK); - // Round up divider, so we don't run the card over the speed supported, - // and subtract by 2, because STM32 will add 2, as written in the manual: - // SDIO_CK frequency = SDIOCLK / [CLKDIV + 2] - return pclk2 / clk + (pclk2 % clk != 0) - 2; -} - -void go_to_transfer_speed() { - /* Default SDIO peripheral configuration for SD card initialization */ - hsd.Init.ClockEdge = hsd.Init.ClockEdge; - hsd.Init.ClockBypass = hsd.Init.ClockBypass; - hsd.Init.ClockPowerSave = hsd.Init.ClockPowerSave; - hsd.Init.BusWide = hsd.Init.BusWide; - hsd.Init.HardwareFlowControl = hsd.Init.HardwareFlowControl; - hsd.Init.ClockDiv = clock_to_divider(SDIO_CLOCK); - - /* Initialize SDIO peripheral interface with default configuration */ - SDIO_Init(hsd.Instance, hsd.Init); -} - -void SD_LowLevel_Init(void) { - uint32_t tempreg; - - __HAL_RCC_GPIOC_CLK_ENABLE(); //enable GPIO clocks - __HAL_RCC_GPIOD_CLK_ENABLE(); //enable GPIO clocks - - GPIO_InitTypeDef GPIO_InitStruct; - - GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; - GPIO_InitStruct.Pull = 1; //GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; - - #if DISABLED(STM32F1xx) - GPIO_InitStruct.Alternate = GPIO_AF12_SDIO; - #endif - - GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_12; // D0 & SCK - HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); - - #if PINS_EXIST(SDIO_D1, SDIO_D2, SDIO_D3) // define D1-D3 only if have a four bit wide SDIO bus - GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11; // D1-D3 - HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); - #endif - - // Configure PD.02 CMD line - GPIO_InitStruct.Pin = GPIO_PIN_2; - HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); - - // Setup DMA - #if defined(STM32F1xx) - hdma_sdio.Init.Mode = DMA_NORMAL; - hdma_sdio.Instance = DMA2_Channel4; - HAL_NVIC_EnableIRQ(DMA2_Channel4_5_IRQn); - #elif defined(STM32F4xx) - hdma_sdio.Init.Mode = DMA_PFCTRL; - hdma_sdio.Instance = DMA2_Stream3; - hdma_sdio.Init.Channel = DMA_CHANNEL_4; - hdma_sdio.Init.FIFOMode = DMA_FIFOMODE_ENABLE; - hdma_sdio.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; - hdma_sdio.Init.MemBurst = DMA_MBURST_INC4; - hdma_sdio.Init.PeriphBurst = DMA_PBURST_INC4; - HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn); - #endif - HAL_NVIC_EnableIRQ(SDIO_IRQn); - hdma_sdio.Init.PeriphInc = DMA_PINC_DISABLE; - hdma_sdio.Init.MemInc = DMA_MINC_ENABLE; - hdma_sdio.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; - hdma_sdio.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; - hdma_sdio.Init.Priority = DMA_PRIORITY_LOW; - __HAL_LINKDMA(&hsd, hdmarx, hdma_sdio); - __HAL_LINKDMA(&hsd, hdmatx, hdma_sdio); - - #if defined(STM32F1xx) - __HAL_RCC_SDIO_CLK_ENABLE(); - __HAL_RCC_DMA2_CLK_ENABLE(); + #ifdef SDIO_FOR_STM32H7 + // SDMMC_CK frequency = sdmmc_ker_ck / [2 * CLKDIV]. + uint32_t sdmmc_clk = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SDMMC); + return sdmmc_clk / (2U * SDIO_CLOCK) + (sdmmc_clk % (2U * SDIO_CLOCK) != 0); #else - __HAL_RCC_SDIO_FORCE_RESET(); - delay(2); - __HAL_RCC_SDIO_RELEASE_RESET(); - delay(2); - __HAL_RCC_SDIO_CLK_ENABLE(); - - __HAL_RCC_DMA2_FORCE_RESET(); - delay(2); - __HAL_RCC_DMA2_RELEASE_RESET(); - delay(2); - __HAL_RCC_DMA2_CLK_ENABLE(); + // limit the SDIO master clock to 8/3 of PCLK2. See STM32 Manuals + // Also limited to no more than 48Mhz (SDIOCLK). + const uint32_t pclk2 = HAL_RCC_GetPCLK2Freq(); + clk = min(clk, (uint32_t)(pclk2 * 8 / 3)); + clk = min(clk, (uint32_t)SDIOCLK); + // Round up divider, so we don't run the card over the speed supported, + // and subtract by 2, because STM32 will add 2, as written in the manual: + // SDIO_CK frequency = SDIOCLK / [CLKDIV + 2] + return pclk2 / clk + (pclk2 % clk != 0) - 2; #endif - - //Initialize the SDIO (with initial <400Khz Clock) - tempreg = 0; //Reset value - tempreg |= SDIO_CLKCR_CLKEN; // Clock enabled - tempreg |= SDIO_INIT_CLK_DIV; // Clock Divider. Clock = 48000 / (118 + 2) = 400Khz - // Keep the rest at 0 => HW_Flow Disabled, Rising Clock Edge, Disable CLK ByPass, Bus Width = 0, Power save Disable - SDIO->CLKCR = tempreg; - - // Power up the SDIO - SDIO_PowerState_ON(SDIO); - hsd.Instance = SDIO; } -void HAL_SD_MspInit(SD_HandleTypeDef *hsd) { // application specific init - UNUSED(hsd); // Prevent unused argument(s) compilation warning - __HAL_RCC_SDIO_CLK_ENABLE(); // turn on SDIO clock +// Start the SDIO clock +void HAL_SD_MspInit(SD_HandleTypeDef *hsd) { + UNUSED(hsd); + #ifdef SDIO_FOR_STM32H7 + pinmap_pinout(PC_12, PinMap_SD); + pinmap_pinout(PD_2, PinMap_SD); + pinmap_pinout(PC_8, PinMap_SD); + #if PINS_EXIST(SDIO_D1, SDIO_D2, SDIO_D3) // Define D1-D3 only for 4-bit wide SDIO bus + pinmap_pinout(PC_9, PinMap_SD); + pinmap_pinout(PC_10, PinMap_SD); + pinmap_pinout(PC_11, PinMap_SD); + #endif + __HAL_RCC_SDMMC1_CLK_ENABLE(); + HAL_NVIC_EnableIRQ(SDMMC1_IRQn); + #else + __HAL_RCC_SDIO_CLK_ENABLE(); + #endif } -bool SDIO_Init() { - uint8_t retryCnt = SDIO_READ_RETRIES; +#ifdef SDIO_FOR_STM32H7 - bool status; - hsd.Instance = SDIO; - hsd.State = HAL_SD_STATE_RESET; + #define SD_TIMEOUT 1000 // ms - SD_LowLevel_Init(); + extern "C" void SDMMC1_IRQHandler(void) { HAL_SD_IRQHandler(&hsd); } - uint8_t retry_Cnt = retryCnt; - for (;;) { - TERN_(USE_WATCHDOG, HAL_watchdog_refresh()); - status = (bool) HAL_SD_Init(&hsd); - if (!status) break; - if (!--retry_Cnt) return false; // return failing status if retries are exhausted + uint8_t waitingRxCplt = 0, waitingTxCplt = 0; + void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsdio) { waitingTxCplt = 0; } + void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsdio) { waitingRxCplt = 0; } + + void HAL_SD_MspDeInit(SD_HandleTypeDef *hsd) { + __HAL_RCC_SDMMC1_FORCE_RESET(); delay(10); + __HAL_RCC_SDMMC1_RELEASE_RESET(); delay(10); } - go_to_transfer_speed(); + bool SDIO_Init() { + HAL_StatusTypeDef sd_state = HAL_OK; + if (hsd.Instance == SDMMC1) HAL_SD_DeInit(&hsd); - #if PINS_EXIST(SDIO_D1, SDIO_D2, SDIO_D3) // go to 4 bit wide mode if pins are defined - retry_Cnt = retryCnt; + // HAL SD initialization + hsd.Instance = SDMMC1; + hsd.Init.ClockEdge = SDMMC_CLOCK_EDGE_RISING; + hsd.Init.ClockPowerSave = SDMMC_CLOCK_POWER_SAVE_DISABLE; + hsd.Init.BusWide = SDMMC_BUS_WIDE_1B; + hsd.Init.HardwareFlowControl = SDMMC_HARDWARE_FLOW_CONTROL_DISABLE; + hsd.Init.ClockDiv = clock_to_divider(SDIO_CLOCK); + sd_state = HAL_SD_Init(&hsd); + + #if PINS_EXIST(SDIO_D1, SDIO_D2, SDIO_D3) + if (sd_state == HAL_OK) + sd_state = HAL_SD_ConfigWideBusOperation(&hsd, SDMMC_BUS_WIDE_4B); + #endif + + return (sd_state == HAL_OK); + } + +#else // !SDIO_FOR_STM32H7 + + #define SD_TIMEOUT 500 // ms + + // SDIO retries, configurable. Default is 3, from STM32F1 + #ifndef SDIO_READ_RETRIES + #define SDIO_READ_RETRIES 3 + #endif + + // F4 supports one DMA for RX and another for TX, but Marlin will never + // do read and write at same time, so we use the same DMA for both. + DMA_HandleTypeDef hdma_sdio; + + #ifdef STM32F1xx + #define DMA_IRQ_HANDLER DMA2_Channel4_5_IRQHandler + #elif defined(STM32F4xx) + #define DMA_IRQ_HANDLER DMA2_Stream3_IRQHandler + #else + #error "Unknown STM32 architecture." + #endif + + extern "C" void SDIO_IRQHandler(void) { HAL_SD_IRQHandler(&hsd); } + extern "C" void DMA_IRQ_HANDLER(void) { HAL_DMA_IRQHandler(&hdma_sdio); } + + /* + SDIO_INIT_CLK_DIV is 118 + SDIO clock frequency is 48MHz / (TRANSFER_CLOCK_DIV + 2) + SDIO init clock frequency should not exceed 400kHz = 48MHz / (118 + 2) + + Default TRANSFER_CLOCK_DIV is 2 (118 / 40) + Default SDIO clock frequency is 48MHz / (2 + 2) = 12 MHz + This might be too fast for stable SDIO operations + + MKS Robin SDIO seems stable with BusWide 1bit and ClockDiv 8 (i.e., 4.8MHz SDIO clock frequency) + More testing is required as there are clearly some 4bit init problems. + */ + + void go_to_transfer_speed() { + /* Default SDIO peripheral configuration for SD card initialization */ + hsd.Init.ClockEdge = hsd.Init.ClockEdge; + hsd.Init.ClockBypass = hsd.Init.ClockBypass; + hsd.Init.ClockPowerSave = hsd.Init.ClockPowerSave; + hsd.Init.BusWide = hsd.Init.BusWide; + hsd.Init.HardwareFlowControl = hsd.Init.HardwareFlowControl; + hsd.Init.ClockDiv = clock_to_divider(SDIO_CLOCK); + + /* Initialize SDIO peripheral interface with default configuration */ + SDIO_Init(hsd.Instance, hsd.Init); + } + + void SD_LowLevel_Init() { + uint32_t tempreg; + + // Enable GPIO clocks + __HAL_RCC_GPIOC_CLK_ENABLE(); + __HAL_RCC_GPIOD_CLK_ENABLE(); + + GPIO_InitTypeDef GPIO_InitStruct; + + GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; + GPIO_InitStruct.Pull = 1; // GPIO_NOPULL + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + + #if DISABLED(STM32F1xx) + GPIO_InitStruct.Alternate = GPIO_AF12_SDIO; + #endif + + GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_12; // D0 & SCK + HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + + #if PINS_EXIST(SDIO_D1, SDIO_D2, SDIO_D3) // define D1-D3 only if have a four bit wide SDIO bus + GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11; // D1-D3 + HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); + #endif + + // Configure PD.02 CMD line + GPIO_InitStruct.Pin = GPIO_PIN_2; + HAL_GPIO_Init(GPIOD, &GPIO_InitStruct); + + // Setup DMA + #ifdef STM32F1xx + hdma_sdio.Init.Mode = DMA_NORMAL; + hdma_sdio.Instance = DMA2_Channel4; + HAL_NVIC_EnableIRQ(DMA2_Channel4_5_IRQn); + #elif defined(STM32F4xx) + hdma_sdio.Init.Mode = DMA_PFCTRL; + hdma_sdio.Instance = DMA2_Stream3; + hdma_sdio.Init.Channel = DMA_CHANNEL_4; + hdma_sdio.Init.FIFOMode = DMA_FIFOMODE_ENABLE; + hdma_sdio.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; + hdma_sdio.Init.MemBurst = DMA_MBURST_INC4; + hdma_sdio.Init.PeriphBurst = DMA_PBURST_INC4; + HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn); + #endif + HAL_NVIC_EnableIRQ(SDIO_IRQn); + hdma_sdio.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_sdio.Init.MemInc = DMA_MINC_ENABLE; + hdma_sdio.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; + hdma_sdio.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; + hdma_sdio.Init.Priority = DMA_PRIORITY_LOW; + __HAL_LINKDMA(&hsd, hdmarx, hdma_sdio); + __HAL_LINKDMA(&hsd, hdmatx, hdma_sdio); + + #ifdef STM32F1xx + __HAL_RCC_SDIO_CLK_ENABLE(); + __HAL_RCC_DMA2_CLK_ENABLE(); + #else + __HAL_RCC_SDIO_FORCE_RESET(); delay(2); + __HAL_RCC_SDIO_RELEASE_RESET(); delay(2); + __HAL_RCC_SDIO_CLK_ENABLE(); + + __HAL_RCC_DMA2_FORCE_RESET(); delay(2); + __HAL_RCC_DMA2_RELEASE_RESET(); delay(2); + __HAL_RCC_DMA2_CLK_ENABLE(); + #endif + + // Initialize the SDIO (with initial <400Khz Clock) + tempreg = 0 // Reset value + | SDIO_CLKCR_CLKEN // Clock enabled + | SDIO_INIT_CLK_DIV; // Clock Divider. Clock = 48000 / (118 + 2) = 400Khz + // Keep the rest at 0 => HW_Flow Disabled, Rising Clock Edge, Disable CLK ByPass, Bus Width = 0, Power save Disable + SDIO->CLKCR = tempreg; + + // Power up the SDIO + SDIO_PowerState_ON(SDIO); + hsd.Instance = SDIO; + } + + bool SDIO_Init() { + uint8_t retryCnt = SDIO_READ_RETRIES; + + bool status; + hsd.Instance = SDIO; + hsd.State = HAL_SD_STATE_RESET; + + SD_LowLevel_Init(); + + uint8_t retry_Cnt = retryCnt; for (;;) { - TERN_(USE_WATCHDOG, HAL_watchdog_refresh()); - if (!HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B)) break; // some cards are only 1 bit wide so a pass here is not required - if (!--retry_Cnt) break; + hal.watchdog_refresh(); + status = (bool) HAL_SD_Init(&hsd); + if (!status) break; + if (!--retry_Cnt) return false; // return failing status if retries are exhausted } - if (!retry_Cnt) { // wide bus failed, go back to one bit wide mode - hsd.State = (HAL_SD_StateTypeDef) 0; // HAL_SD_STATE_RESET - SD_LowLevel_Init(); + + go_to_transfer_speed(); + + #if PINS_EXIST(SDIO_D1, SDIO_D2, SDIO_D3) // go to 4 bit wide mode if pins are defined retry_Cnt = retryCnt; for (;;) { - TERN_(USE_WATCHDOG, HAL_watchdog_refresh()); - status = (bool) HAL_SD_Init(&hsd); - if (!status) break; - if (!--retry_Cnt) return false; // return failing status if retries are exhausted + hal.watchdog_refresh(); + if (!HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B)) break; // some cards are only 1 bit wide so a pass here is not required + if (!--retry_Cnt) break; } - go_to_transfer_speed(); + if (!retry_Cnt) { // wide bus failed, go back to one bit wide mode + hsd.State = (HAL_SD_StateTypeDef) 0; // HAL_SD_STATE_RESET + SD_LowLevel_Init(); + retry_Cnt = retryCnt; + for (;;) { + hal.watchdog_refresh(); + status = (bool) HAL_SD_Init(&hsd); + if (!status) break; + if (!--retry_Cnt) return false; // return failing status if retries are exhausted + } + go_to_transfer_speed(); + } + #endif + + return true; + } + + /** + * @brief Read or Write a block + * @details Read or Write a block with SDIO + * + * @param block The block index + * @param src The data buffer source for a write + * @param dst The data buffer destination for a read + * + * @return true on success + */ + static bool SDIO_ReadWriteBlock_DMA(uint32_t block, const uint8_t *src, uint8_t *dst) { + if (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER) return false; + + hal.watchdog_refresh(); + + HAL_StatusTypeDef ret; + if (src) { + hdma_sdio.Init.Direction = DMA_MEMORY_TO_PERIPH; + HAL_DMA_Init(&hdma_sdio); + ret = HAL_SD_WriteBlocks_DMA(&hsd, (uint8_t*)src, block, 1); + } + else { + hdma_sdio.Init.Direction = DMA_PERIPH_TO_MEMORY; + HAL_DMA_Init(&hdma_sdio); + ret = HAL_SD_ReadBlocks_DMA(&hsd, (uint8_t*)dst, block, 1); } - #endif - return true; -} - -static bool SDIO_ReadWriteBlock_DMA(uint32_t block, const uint8_t *src, uint8_t *dst) { - if (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER) return false; - - TERN_(USE_WATCHDOG, HAL_watchdog_refresh()); - - HAL_StatusTypeDef ret; - if (src) { - hdma_sdio.Init.Direction = DMA_MEMORY_TO_PERIPH; - HAL_DMA_Init(&hdma_sdio); - ret = HAL_SD_WriteBlocks_DMA(&hsd, (uint8_t *)src, block, 1); - } - else { - hdma_sdio.Init.Direction = DMA_PERIPH_TO_MEMORY; - HAL_DMA_Init(&hdma_sdio); - ret = HAL_SD_ReadBlocks_DMA(&hsd, (uint8_t *)dst, block, 1); - } - - if (ret != HAL_OK) { - HAL_DMA_Abort_IT(&hdma_sdio); - HAL_DMA_DeInit(&hdma_sdio); - return false; - } - - millis_t timeout = millis() + 500; - // Wait the transfer - while (hsd.State != HAL_SD_STATE_READY) { - if (ELAPSED(millis(), timeout)) { + if (ret != HAL_OK) { HAL_DMA_Abort_IT(&hdma_sdio); HAL_DMA_DeInit(&hdma_sdio); return false; } + + millis_t timeout = millis() + SD_TIMEOUT; + // Wait the transfer + while (hsd.State != HAL_SD_STATE_READY) { + if (ELAPSED(millis(), timeout)) { + HAL_DMA_Abort_IT(&hdma_sdio); + HAL_DMA_DeInit(&hdma_sdio); + return false; + } + } + + while (__HAL_DMA_GET_FLAG(&hdma_sdio, __HAL_DMA_GET_TC_FLAG_INDEX(&hdma_sdio)) != 0 + || __HAL_DMA_GET_FLAG(&hdma_sdio, __HAL_DMA_GET_TE_FLAG_INDEX(&hdma_sdio)) != 0) { /* nada */ } + + HAL_DMA_Abort_IT(&hdma_sdio); + HAL_DMA_DeInit(&hdma_sdio); + + timeout = millis() + SD_TIMEOUT; + while (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER) if (ELAPSED(millis(), timeout)) return false; + + return true; } - while (__HAL_DMA_GET_FLAG(&hdma_sdio, __HAL_DMA_GET_TC_FLAG_INDEX(&hdma_sdio)) != 0 - || __HAL_DMA_GET_FLAG(&hdma_sdio, __HAL_DMA_GET_TE_FLAG_INDEX(&hdma_sdio)) != 0) { /* nada */ } - - HAL_DMA_Abort_IT(&hdma_sdio); - HAL_DMA_DeInit(&hdma_sdio); - - timeout = millis() + 500; - while (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER) if (ELAPSED(millis(), timeout)) return false; - - return true; -} +#endif // !SDIO_FOR_STM32H7 +/** + * @brief Read a block + * @details Read a block from media with SDIO + * + * @param block The block index + * @param src The block buffer + * + * @return true on success + */ bool SDIO_ReadBlock(uint32_t block, uint8_t *dst) { - uint8_t retries = SDIO_READ_RETRIES; - while (retries--) if (SDIO_ReadWriteBlock_DMA(block, nullptr, dst)) return true; - return false; + #ifdef SDIO_FOR_STM32H7 + + uint32_t timeout = HAL_GetTick() + SD_TIMEOUT; + + while (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER) + if (HAL_GetTick() >= timeout) return false; + + waitingRxCplt = 1; + if (HAL_SD_ReadBlocks_DMA(&hsd, (uint8_t*)dst, block, 1) != HAL_OK) + return false; + + timeout = HAL_GetTick() + SD_TIMEOUT; + while (waitingRxCplt) + if (HAL_GetTick() >= timeout) return false; + + return true; + + #else + + uint8_t retries = SDIO_READ_RETRIES; + while (retries--) if (SDIO_ReadWriteBlock_DMA(block, nullptr, dst)) return true; + return false; + + #endif } +/** + * @brief Write a block + * @details Write a block to media with SDIO + * + * @param block The block index + * @param src The block data + * + * @return true on success + */ bool SDIO_WriteBlock(uint32_t block, const uint8_t *src) { - uint8_t retries = SDIO_READ_RETRIES; - while (retries--) if (SDIO_ReadWriteBlock_DMA(block, src, nullptr)) return true; - return false; + #ifdef SDIO_FOR_STM32H7 + + uint32_t timeout = HAL_GetTick() + SD_TIMEOUT; + + while (HAL_SD_GetCardState(&hsd) != HAL_SD_CARD_TRANSFER) + if (HAL_GetTick() >= timeout) return false; + + waitingTxCplt = 1; + if (HAL_SD_WriteBlocks_DMA(&hsd, (uint8_t*)src, block, 1) != HAL_OK) + return false; + + timeout = HAL_GetTick() + SD_TIMEOUT; + while (waitingTxCplt) + if (HAL_GetTick() >= timeout) return false; + + return true; + + #else + + uint8_t retries = SDIO_READ_RETRIES; + while (retries--) if (SDIO_ReadWriteBlock_DMA(block, src, nullptr)) return true; + return false; + + #endif } bool SDIO_IsReady() { @@ -305,16 +447,5 @@ uint32_t SDIO_GetCardSize() { return (uint32_t)(hsd.SdCard.BlockNbr) * (hsd.SdCard.BlockSize); } -#if defined(STM32F1xx) - #define DMA_IRQ_HANDLER DMA2_Channel4_5_IRQHandler -#elif defined(STM32F4xx) - #define DMA_IRQ_HANDLER DMA2_Stream3_IRQHandler -#else - #error "Unknown STM32 architecture." -#endif - -extern "C" void SDIO_IRQHandler(void) { HAL_SD_IRQHandler(&hsd); } -extern "C" void DMA_IRQ_HANDLER(void) { HAL_DMA_IRQHandler(&hdma_sdio); } - #endif // SDIO_SUPPORT #endif // HAL_STM32 diff --git a/Marlin/src/HAL/STM32/tft/gt911.cpp b/Marlin/src/HAL/STM32/tft/gt911.cpp index 92e14edb20..180abc68b0 100644 --- a/Marlin/src/HAL/STM32/tft/gt911.cpp +++ b/Marlin/src/HAL/STM32/tft/gt911.cpp @@ -159,24 +159,28 @@ void GT911::read_reg(uint16_t reg, uint8_t reg_len, uint8_t* r_data, uint8_t r_l void GT911::Init() { OUT_WRITE(GT911_RST_PIN, LOW); OUT_WRITE(GT911_INT_PIN, LOW); - delay(20); + delay(11); + WRITE(GT911_INT_PIN, HIGH); + delayMicroseconds(110); WRITE(GT911_RST_PIN, HIGH); + delay(6); + WRITE(GT911_INT_PIN, LOW); + delay(55); SET_INPUT(GT911_INT_PIN); sw_iic.init(); - uint8_t clear_reg = 0x0000; - write_reg(0x814E, 2, &clear_reg, 2); // Reset to 0 for start + uint8_t clear_reg = 0x00; + write_reg(0x814E, 2, &clear_reg, 1); // Reset to 0 for start } bool GT911::getFirstTouchPoint(int16_t *x, int16_t *y) { read_reg(0x814E, 2, ®.REG.status, 1); - if (reg.REG.status & 0x80) { + if (reg.REG.status >= 0x80 && reg.REG.status <= 0x85) { + read_reg(0x8150, 2, reg.map + 2, 38); uint8_t clear_reg = 0x00; write_reg(0x814E, 2, &clear_reg, 1); // Reset to 0 for start - read_reg(0x8150, 2, reg.map + 2, 8 * (reg.REG.status & 0x0F)); - // First touch point *x = ((reg.REG.point[0].xh & 0x0F) << 8) | reg.REG.point[0].xl; *y = ((reg.REG.point[0].yh & 0x0F) << 8) | reg.REG.point[0].yl; diff --git a/Marlin/src/HAL/STM32/tft/gt911.h b/Marlin/src/HAL/STM32/tft/gt911.h index 752a554d98..6ecfe8b82e 100644 --- a/Marlin/src/HAL/STM32/tft/gt911.h +++ b/Marlin/src/HAL/STM32/tft/gt911.h @@ -23,7 +23,7 @@ #include "../../../inc/MarlinConfig.h" -#define GT911_SLAVE_ADDRESS 0xBA +#define GT911_SLAVE_ADDRESS 0x28 #if !PIN_EXISTS(GT911_RST) #error "GT911_RST_PIN is not defined." diff --git a/Marlin/src/HAL/STM32/timers.cpp b/Marlin/src/HAL/STM32/timers.cpp index a1e3372bbb..e68b59c46f 100644 --- a/Marlin/src/HAL/STM32/timers.cpp +++ b/Marlin/src/HAL/STM32/timers.cpp @@ -303,16 +303,16 @@ enum TimerPurpose { TP_SERIAL, TP_TONE, TP_SERVO, TP_STEP, TP_TEMP }; // This cannot yet account for timers used for PWM output, such as for fans. static constexpr struct { TimerPurpose p; int t; } timers_in_use[] = { #if HAS_TMC_SW_SERIAL - {TP_SERIAL, get_timer_num_from_base_address(timer_serial[0])}, // Set in variant.h, or as a define in platformio.h if not present in variant.h + { TP_SERIAL, get_timer_num_from_base_address(timer_serial[0]) }, // Set in variant.h, or as a define in platformio.h if not present in variant.h #endif #if ENABLED(SPEAKER) - {TP_TONE, get_timer_num_from_base_address(timer_tone[0])}, // Set in variant.h, or as a define in platformio.h if not present in variant.h + { TP_TONE, get_timer_num_from_base_address(timer_tone[0]) }, // Set in variant.h, or as a define in platformio.h if not present in variant.h #endif #if HAS_SERVOS - {TP_SERVO, get_timer_num_from_base_address(timer_servo[0])}, // Set in variant.h, or as a define in platformio.h if not present in variant.h + { TP_SERVO, get_timer_num_from_base_address(timer_servo[0]) }, // Set in variant.h, or as a define in platformio.h if not present in variant.h #endif - {TP_STEP, STEP_TIMER}, - {TP_TEMP, TEMP_TIMER}, + { TP_STEP, STEP_TIMER }, + { TP_TEMP, TEMP_TIMER }, }; static constexpr bool verify_no_timer_conflicts() { diff --git a/Marlin/src/HAL/STM32/watchdog.cpp b/Marlin/src/HAL/STM32/watchdog.cpp deleted file mode 100644 index 1eccdec498..0000000000 --- a/Marlin/src/HAL/STM32/watchdog.cpp +++ /dev/null @@ -1,52 +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 . - * - */ - -#include "../platforms.h" - -#ifdef HAL_STM32 - -#include "../../inc/MarlinConfigPre.h" - -#if ENABLED(USE_WATCHDOG) - -#define WDT_TIMEOUT_US TERN(WATCHDOG_DURATION_8S, 8000000, 4000000) // 4 or 8 second timeout - -#include "../../inc/MarlinConfig.h" - -#include "watchdog.h" -#include - -void watchdog_init() { - #if DISABLED(DISABLE_WATCHDOG_INIT) - IWatchdog.begin(WDT_TIMEOUT_US); - #endif -} - -void HAL_watchdog_refresh() { - IWatchdog.reload(); - #if DISABLED(PINS_DEBUGGING) && PIN_EXISTS(LED) - TOGGLE(LED_PIN); // heartbeat indicator - #endif -} - -#endif // USE_WATCHDOG -#endif // HAL_STM32 diff --git a/Marlin/src/HAL/STM32F1/HAL.cpp b/Marlin/src/HAL/STM32F1/HAL.cpp index 636dc742fc..4d3140001e 100644 --- a/Marlin/src/HAL/STM32F1/HAL.cpp +++ b/Marlin/src/HAL/STM32F1/HAL.cpp @@ -83,6 +83,7 @@ // ------------------------ #if defined(SERIAL_USB) && !HAS_SD_HOST_DRIVE + USBSerial SerialUSB; DefaultSerial1 MSerial0(true, SerialUSB); @@ -112,6 +113,47 @@ #endif #endif +// ------------------------ +// Watchdog Timer +// ------------------------ + +#if ENABLED(USE_WATCHDOG) + + #include + + void watchdogSetup() { + // do whatever. don't remove this function. + } + + /** + * The watchdog clock is 40Khz. So for a 4s or 8s interval use a /256 preescaler and 625 or 1250 reload value (counts down to 0). + */ + #define STM32F1_WD_RELOAD TERN(WATCHDOG_DURATION_8S, 1250, 625) // 4 or 8 second timeout + + /** + * @brief Initialize the independent hardware watchdog. + * + * @return No return + * + * @details The watchdog clock is 40Khz. So for a 4s or 8s interval use a /256 preescaler and 625 or 1250 reload value (counts down to 0). + */ + void MarlinHAL::watchdog_init() { + #if DISABLED(DISABLE_WATCHDOG_INIT) + iwdg_init(IWDG_PRE_256, STM32F1_WD_RELOAD); + #endif + } + + // Reset watchdog. MUST be called every 4 or 8 seconds after the + // first watchdog_init or the STM32F1 will reset. + void MarlinHAL::watchdog_refresh() { + #if DISABLED(PINS_DEBUGGING) && PIN_EXISTS(LED) + TOGGLE(LED_PIN); // heartbeat indicator + #endif + iwdg_feed(); + } + +#endif // USE_WATCHDOG + // ------------------------ // ADC // ------------------------ @@ -211,6 +253,10 @@ void MarlinHAL::idletask() { void MarlinHAL::reboot() { nvic_sys_reset(); } +// ------------------------ +// Free Memory Accessor +// ------------------------ + extern "C" { extern unsigned int _ebss; // end of bss section } @@ -243,9 +289,9 @@ extern "C" { } */ -// +// ------------------------ // ADC -// +// ------------------------ enum ADCIndex : uint8_t { OPTITEM(HAS_TEMP_ADC_0, TEMP_0) diff --git a/Marlin/src/HAL/STM32F1/HAL.h b/Marlin/src/HAL/STM32F1/HAL.h index f532c8378a..c6eef8f4fd 100644 --- a/Marlin/src/HAL/STM32F1/HAL.h +++ b/Marlin/src/HAL/STM32F1/HAL.h @@ -34,7 +34,6 @@ #include "../shared/HAL_SPI.h" #include "fastio.h" -#include "watchdog.h" #include #include @@ -247,6 +246,10 @@ 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 from 0x0 @@ -280,7 +283,7 @@ public: // Called by Temperature::init for each sensor at startup static void adc_enable(const pin_t pin) { pinMode(pin, INPUT_ANALOG); } - // Begin ADC sampling on the given channel + // 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? diff --git a/Marlin/src/HAL/STM32F1/HAL_MinSerial.cpp b/Marlin/src/HAL/STM32F1/MinSerial.cpp similarity index 97% rename from Marlin/src/HAL/STM32F1/HAL_MinSerial.cpp rename to Marlin/src/HAL/STM32F1/MinSerial.cpp index 0fc3d014d4..6cf68d8d8f 100644 --- a/Marlin/src/HAL/STM32F1/HAL_MinSerial.cpp +++ b/Marlin/src/HAL/STM32F1/MinSerial.cpp @@ -26,8 +26,7 @@ #if ENABLED(POSTMORTEM_DEBUGGING) -#include "../shared/HAL_MinSerial.h" -#include "watchdog.h" +#include "../shared/MinSerial.h" #include #include @@ -82,7 +81,7 @@ static void TX(char c) { #if WITHIN(SERIAL_PORT, 1, 6) struct usart_dev* dev = MYSERIAL1.c_dev(); while (!(dev->regs->SR & USART_SR_TXE)) { - TERN_(USE_WATCHDOG, HAL_watchdog_refresh()); + hal.watchdog_refresh(); sw_barrier(); } dev->regs->DR = c; diff --git a/Marlin/src/HAL/STM32F1/Servo.cpp b/Marlin/src/HAL/STM32F1/Servo.cpp index 8dc1ef7b6a..47ffb631cf 100644 --- a/Marlin/src/HAL/STM32F1/Servo.cpp +++ b/Marlin/src/HAL/STM32F1/Servo.cpp @@ -147,17 +147,17 @@ void libServo::move(const int32_t value) { uint16_t SR = timer_get_status(tdev); if (SR & TIMER_SR_CC1IF) { // channel 1 off #ifdef SERVO0_PWM_OD - OUT_WRITE_OD(SERVO0_PIN, 1); // off + OUT_WRITE_OD(SERVO0_PIN, HIGH); // off #else - OUT_WRITE(SERVO0_PIN, 0); + OUT_WRITE(SERVO0_PIN, LOW); #endif timer_reset_status_bit(tdev, TIMER_SR_CC1IF_BIT); } if (SR & TIMER_SR_CC2IF) { // channel 2 resume #ifdef SERVO0_PWM_OD - OUT_WRITE_OD(SERVO0_PIN, 0); // on + OUT_WRITE_OD(SERVO0_PIN, LOW); // on #else - OUT_WRITE(SERVO0_PIN, 1); + OUT_WRITE(SERVO0_PIN, HIGH); #endif timer_reset_status_bit(tdev, TIMER_SR_CC2IF_BIT); } @@ -167,9 +167,9 @@ void libServo::move(const int32_t value) { timer_dev *tdev = HAL_get_timer_dev(MF_TIMER_SERVO0); if (!tdev) return false; #ifdef SERVO0_PWM_OD - OUT_WRITE_OD(inPin, 1); + OUT_WRITE_OD(inPin, HIGH); #else - OUT_WRITE(inPin, 0); + OUT_WRITE(inPin, LOW); #endif timer_pause(tdev); @@ -200,9 +200,9 @@ void libServo::move(const int32_t value) { timer_disable_irq(tdev, 1); timer_disable_irq(tdev, 2); #ifdef SERVO0_PWM_OD - OUT_WRITE_OD(pin, 1); // off + OUT_WRITE_OD(pin, HIGH); // off #else - OUT_WRITE(pin, 0); + OUT_WRITE(pin, LOW); #endif } } diff --git a/Marlin/src/HAL/STM32F1/tft/tft_spi.cpp b/Marlin/src/HAL/STM32F1/tft/tft_spi.cpp index 9bf6bbb32b..f447cec811 100644 --- a/Marlin/src/HAL/STM32F1/tft/tft_spi.cpp +++ b/Marlin/src/HAL/STM32F1/tft/tft_spi.cpp @@ -30,7 +30,7 @@ SPIClass TFT_SPI::SPIx(1); void TFT_SPI::Init() { #if PIN_EXISTS(TFT_RESET) - OUT_WRITE(TFT_RST_PIN, HIGH); + OUT_WRITE(TFT_RESET_PIN, HIGH); delay(100); #endif diff --git a/Marlin/src/HAL/STM32F1/watchdog.cpp b/Marlin/src/HAL/STM32F1/watchdog.cpp deleted file mode 100644 index b812a4fa64..0000000000 --- a/Marlin/src/HAL/STM32F1/watchdog.cpp +++ /dev/null @@ -1,66 +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 . - * - */ - -/** - * HAL for stm32duino.com based on Libmaple and compatible (STM32F1) - */ - -#ifdef __STM32F1__ - -#include "../../inc/MarlinConfig.h" - -#if ENABLED(USE_WATCHDOG) - -#include -#include "watchdog.h" - -/** - * The watchdog clock is 40Khz. So for a 4s or 8s interval use a /256 preescaler and 625 or 1250 reload value (counts down to 0). - */ -#define STM32F1_WD_RELOAD TERN(WATCHDOG_DURATION_8S, 1250, 625) // 4 or 8 second timeout - -void HAL_watchdog_refresh() { - #if DISABLED(PINS_DEBUGGING) && PIN_EXISTS(LED) - TOGGLE(LED_PIN); // heartbeat indicator - #endif - iwdg_feed(); -} - -void watchdogSetup() { - // do whatever. don't remove this function. -} - -/** - * @brief Initialized the independent hardware watchdog. - * - * @return No return - * - * @details The watchdog clock is 40Khz. So for a 4s or 8s interval use a /256 preescaler and 625 or 1250 reload value (counts down to 0). - */ -void watchdog_init() { - #if DISABLED(DISABLE_WATCHDOG_INIT) - iwdg_init(IWDG_PRE_256, STM32F1_WD_RELOAD); - #endif -} - -#endif // USE_WATCHDOG -#endif // __STM32F1__ diff --git a/Marlin/src/HAL/STM32F1/watchdog.h b/Marlin/src/HAL/STM32F1/watchdog.h deleted file mode 100644 index 68920f8cb6..0000000000 --- a/Marlin/src/HAL/STM32F1/watchdog.h +++ /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 . - * - */ -#pragma once - -/** - * HAL for stm32duino.com based on Libmaple and compatible (STM32F1) - */ - -#include - -// Initialize watchdog with a 4 or 8 second countdown time -void watchdog_init(); - -// Reset watchdog. MUST be called every 4 or 8 seconds after the -// first watchdog_init or the STM32F1 will reset. -void HAL_watchdog_refresh(); diff --git a/Marlin/src/HAL/TEENSY31_32/HAL.cpp b/Marlin/src/HAL/TEENSY31_32/HAL.cpp index b923ab77b1..2892368967 100644 --- a/Marlin/src/HAL/TEENSY31_32/HAL.cpp +++ b/Marlin/src/HAL/TEENSY31_32/HAL.cpp @@ -44,25 +44,6 @@ #endif USBSerialType USBSerial(false, SerialUSB); -// ------------------------ -// Class Utilities -// ------------------------ - -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; - } -} - // ------------------------ // MarlinHAL Class // ------------------------ @@ -81,7 +62,31 @@ uint8_t MarlinHAL::get_reset_source() { return 0; } +// ------------------------ +// Watchdog Timer +// ------------------------ + +#if ENABLED(USE_WATCHDOG) + + #define WDT_TIMEOUT_MS TERN(WATCHDOG_DURATION_8S, 8000, 4000) // 4 or 8 second timeout + + void MarlinHAL::watchdog_init() { + WDOG_TOVALH = 0; + WDOG_TOVALL = WDT_TIMEOUT_MS; + WDOG_STCTRLH = WDOG_STCTRLH_WDOGEN; + } + + void MarlinHAL::watchdog_refresh() { + // Watchdog refresh sequence + WDOG_REFRESH = 0xA602; + WDOG_REFRESH = 0xB480; + } + +#endif + +// ------------------------ // ADC +// ------------------------ void MarlinHAL::adc_init() { analog_init(); @@ -102,4 +107,23 @@ void MarlinHAL::adc_start(const pin_t pin) { uint16_t MarlinHAL::adc_value() { return ADC0_RA; } +// ------------------------ +// Free Memory Accessor +// ------------------------ + +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 // __MK20DX256__ diff --git a/Marlin/src/HAL/TEENSY31_32/HAL.h b/Marlin/src/HAL/TEENSY31_32/HAL.h index 50c0f411cf..a7aa9f0da2 100644 --- a/Marlin/src/HAL/TEENSY31_32/HAL.h +++ b/Marlin/src/HAL/TEENSY31_32/HAL.h @@ -32,7 +32,6 @@ #include "../shared/HAL_SPI.h" #include "fastio.h" -#include "watchdog.h" #include @@ -135,6 +134,10 @@ 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 from 0x0 @@ -166,7 +169,7 @@ public: // Called by Temperature::init for each sensor at startup static void adc_enable(const pin_t ch) {} - // Begin ADC sampling on the given channel + // Begin ADC sampling on the given channel. Called from Temperature::isr! static void adc_start(const pin_t ch); // Is the ADC ready for reading? diff --git a/Marlin/src/HAL/TEENSY31_32/watchdog.cpp b/Marlin/src/HAL/TEENSY31_32/watchdog.cpp deleted file mode 100644 index 5e21236129..0000000000 --- a/Marlin/src/HAL/TEENSY31_32/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 __MK20DX256__ - -#include "../../inc/MarlinConfig.h" - -#if ENABLED(USE_WATCHDOG) - -#include "watchdog.h" - -#define WDT_TIMEOUT_MS TERN(WATCHDOG_DURATION_8S, 8000, 4000) // 4 or 8 second timeout - -void watchdog_init() { - WDOG_TOVALH = 0; - WDOG_TOVALL = WDT_TIMEOUT_MS; - WDOG_STCTRLH = WDOG_STCTRLH_WDOGEN; -} - -#endif // USE_WATCHDOG - -#endif // __MK20DX256__ diff --git a/Marlin/src/HAL/TEENSY31_32/watchdog.h b/Marlin/src/HAL/TEENSY31_32/watchdog.h deleted file mode 100644 index b8b46a4030..0000000000 --- a/Marlin/src/HAL/TEENSY31_32/watchdog.h +++ /dev/null @@ -1,34 +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 "HAL.h" - -// Arduino Due core now has watchdog support - -void watchdog_init(); - -inline void HAL_watchdog_refresh() { - // Watchdog refresh sequence - WDOG_REFRESH = 0xA602; - WDOG_REFRESH = 0xB480; -} diff --git a/Marlin/src/HAL/TEENSY35_36/HAL.cpp b/Marlin/src/HAL/TEENSY35_36/HAL.cpp index 54a5ad3855..bc02ac1c45 100644 --- a/Marlin/src/HAL/TEENSY35_36/HAL.cpp +++ b/Marlin/src/HAL/TEENSY35_36/HAL.cpp @@ -43,33 +43,12 @@ USBSerialType USBSerial(false, SerialUSB); -// ------------------------ -// Class Utilities -// ------------------------ - -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; - } -} - // ------------------------ // MarlinHAL Class // ------------------------ void MarlinHAL::reboot() { _reboot_Teensyduino_(); } -// Reset - uint8_t MarlinHAL::get_reset_source() { switch (RCM_SRS0) { case 128: return RST_POWER_ON; break; @@ -82,7 +61,31 @@ uint8_t MarlinHAL::get_reset_source() { return 0; } +// ------------------------ +// Watchdog Timer +// ------------------------ + +#if ENABLED(USE_WATCHDOG) + + #define WDT_TIMEOUT_MS TERN(WATCHDOG_DURATION_8S, 8000, 4000) // 4 or 8 second timeout + + void MarlinHAL::watchdog_init() { + WDOG_TOVALH = 0; + WDOG_TOVALL = WDT_TIMEOUT_MS; + WDOG_STCTRLH = WDOG_STCTRLH_WDOGEN; + } + + void MarlinHAL::watchdog_refresh() { + // Watchdog refresh sequence + WDOG_REFRESH = 0xA602; + WDOG_REFRESH = 0xB480; + } + +#endif + +// ------------------------ // ADC +// ------------------------ int8_t MarlinHAL::adc_select; @@ -131,4 +134,23 @@ uint16_t MarlinHAL::adc_value() { return 0; } +// ------------------------ +// Free Memory Accessor +// ------------------------ + +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 // __MK64FX512__ || __MK66FX1M0__ diff --git a/Marlin/src/HAL/TEENSY35_36/HAL.h b/Marlin/src/HAL/TEENSY35_36/HAL.h index e4c57f8d1e..2a192e4718 100644 --- a/Marlin/src/HAL/TEENSY35_36/HAL.h +++ b/Marlin/src/HAL/TEENSY35_36/HAL.h @@ -32,7 +32,6 @@ #include "../shared/HAL_SPI.h" #include "fastio.h" -#include "watchdog.h" #include #include @@ -118,7 +117,7 @@ typedef int8_t pin_t; #define PARSED_PIN_INDEX(code, dval) parser.intval(code, dval) // ------------------------ -// Class Utilities +// Free Memory Accessor // ------------------------ #pragma GCC diagnostic push @@ -140,6 +139,10 @@ 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 from 0x0 @@ -173,7 +176,7 @@ public: // Called by Temperature::init for each sensor at startup static void adc_enable(const pin_t) {} - // Begin ADC sampling on the given channel + // 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? diff --git a/Marlin/src/HAL/TEENSY35_36/watchdog.cpp b/Marlin/src/HAL/TEENSY35_36/watchdog.cpp deleted file mode 100644 index 3825e27928..0000000000 --- a/Marlin/src/HAL/TEENSY35_36/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 . - * - */ -#if defined(__MK64FX512__) || defined(__MK66FX1M0__) - -#include "../../inc/MarlinConfig.h" - -#if ENABLED(USE_WATCHDOG) - -#include "watchdog.h" - -#define WDT_TIMEOUT_MS TERN(WATCHDOG_DURATION_8S, 8000, 4000) // 4 or 8 second timeout - -void watchdog_init() { - WDOG_TOVALH = 0; - WDOG_TOVALL = WDT_TIMEOUT_MS; - WDOG_STCTRLH = WDOG_STCTRLH_WDOGEN; -} - -#endif // USE_WATCHDOG - -#endif // __MK64FX512__ || __MK66FX1M0__ diff --git a/Marlin/src/HAL/TEENSY35_36/watchdog.h b/Marlin/src/HAL/TEENSY35_36/watchdog.h deleted file mode 100644 index 981b1f0bd2..0000000000 --- a/Marlin/src/HAL/TEENSY35_36/watchdog.h +++ /dev/null @@ -1,30 +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 - -void watchdog_init(); - -inline void HAL_watchdog_refresh() { - // Watchdog refresh sequence - WDOG_REFRESH = 0xA602; - WDOG_REFRESH = 0xB480; -} diff --git a/Marlin/src/HAL/TEENSY40_41/HAL.cpp b/Marlin/src/HAL/TEENSY40_41/HAL.cpp index 68bd38f72f..1d02ab8575 100644 --- a/Marlin/src/HAL/TEENSY40_41/HAL.cpp +++ b/Marlin/src/HAL/TEENSY40_41/HAL.cpp @@ -44,25 +44,6 @@ #endif USBSerialType USBSerial(false, SerialUSB); -// ------------------------ -// Class Utilities -// ------------------------ - -#define __bss_end _ebss - -extern "C" { - extern char __bss_end; - extern char __heap_start; - extern void* __brkval; - - // Doesn't work on Teensy 4.x - uint32_t freeMemory() { - uint32_t free_memory; - free_memory = ((uint32_t)&free_memory) - (((uint32_t)__brkval) ?: ((uint32_t)&__bss_end)); - return free_memory; - } -} - // ------------------------ // FastIO // ------------------------ @@ -97,7 +78,34 @@ void MarlinHAL::clear_reset_source() { SRC_SRSR = reset_source; } +// ------------------------ +// Watchdog Timer +// ------------------------ + +#if ENABLED(USE_WATCHDOG) + + #define WDT_TIMEOUT TERN(WATCHDOG_DURATION_8S, 8, 4) // 4 or 8 second timeout + + constexpr uint8_t timeoutval = (WDT_TIMEOUT - 0.5f) / 0.5f; + + void MarlinHAL::watchdog_init() { + CCM_CCGR3 |= CCM_CCGR3_WDOG1(3); // enable WDOG1 clocks + WDOG1_WMCR = 0; // disable power down PDE + WDOG1_WCR |= WDOG_WCR_SRS | WDOG_WCR_WT(timeoutval); + WDOG1_WCR |= WDOG_WCR_WDE | WDOG_WCR_WDT | WDOG_WCR_SRE; + } + + void MarlinHAL::watchdog_refresh() { + // Watchdog refresh sequence + WDOG1_WSR = 0x5555; + WDOG1_WSR = 0xAAAA; + } + +#endif + +// ------------------------ // ADC +// ------------------------ int8_t MarlinHAL::adc_select; @@ -180,4 +188,23 @@ uint16_t MarlinHAL::adc_value() { return 0; } +// ------------------------ +// Free Memory Accessor +// ------------------------ + +#define __bss_end _ebss + +extern "C" { + extern char __bss_end; + extern char __heap_start; + extern void* __brkval; + + // Doesn't work on Teensy 4.x + uint32_t freeMemory() { + uint32_t free_memory; + free_memory = ((uint32_t)&free_memory) - (((uint32_t)__brkval) ?: ((uint32_t)&__bss_end)); + return free_memory; + } +} + #endif // __IMXRT1062__ diff --git a/Marlin/src/HAL/TEENSY40_41/HAL.h b/Marlin/src/HAL/TEENSY40_41/HAL.h index a21e652854..c54a2e8a0b 100644 --- a/Marlin/src/HAL/TEENSY40_41/HAL.h +++ b/Marlin/src/HAL/TEENSY40_41/HAL.h @@ -32,7 +32,6 @@ #include "../shared/HAL_SPI.h" #include "fastio.h" -#include "watchdog.h" #include #include @@ -140,7 +139,7 @@ typedef int8_t pin_t; bool is_output(pin_t pin); // ------------------------ -// Class Utilities +// Free Memory Accessor // ------------------------ #pragma GCC diagnostic push @@ -162,6 +161,10 @@ 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 from 0x0 @@ -195,7 +198,7 @@ public: // Called by Temperature::init for each sensor at startup static void adc_enable(const pin_t pin) {} - // Begin ADC sampling on the given channel + // 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? diff --git a/Marlin/src/HAL/TEENSY40_41/watchdog.cpp b/Marlin/src/HAL/TEENSY40_41/watchdog.cpp deleted file mode 100644 index dd7c0aa92f..0000000000 --- a/Marlin/src/HAL/TEENSY40_41/watchdog.cpp +++ /dev/null @@ -1,52 +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 __IMXRT1062__ - -/** - * HAL Watchdog for Teensy 4.0 (IMXRT1062DVL6A) / 4.1 (IMXRT1062DVJ6A) - */ - -#include "../../inc/MarlinConfig.h" - -#if ENABLED(USE_WATCHDOG) - -#include "watchdog.h" - -#define WDT_TIMEOUT TERN(WATCHDOG_DURATION_8S, 8, 4) // 4 or 8 second timeout - -constexpr uint8_t timeoutval = (WDT_TIMEOUT - 0.5f) / 0.5f; - -void watchdog_init() { - CCM_CCGR3 |= CCM_CCGR3_WDOG1(3); // enable WDOG1 clocks - WDOG1_WMCR = 0; // disable power down PDE - WDOG1_WCR |= WDOG_WCR_SRS | WDOG_WCR_WT(timeoutval); - WDOG1_WCR |= WDOG_WCR_WDE | WDOG_WCR_WDT | WDOG_WCR_SRE; -} - -void HAL_watchdog_refresh() { - // Watchdog refresh sequence - WDOG1_WSR = 0x5555; - WDOG1_WSR = 0xAAAA; -} - -#endif // USE_WATCHDOG -#endif // __IMXRT1062__ diff --git a/Marlin/src/HAL/shared/HAL_spi_L6470.cpp b/Marlin/src/HAL/shared/HAL_spi_L6470.cpp deleted file mode 100644 index 5d4ce89b27..0000000000 --- a/Marlin/src/HAL/shared/HAL_spi_L6470.cpp +++ /dev/null @@ -1,139 +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 . - * - */ - -/** - * Software L6470 SPI functions originally from Arduino Sd2Card Library - * Copyright (c) 2009 by William Greiman - */ - -#include "../../inc/MarlinConfig.h" - -#if HAS_L64XX - -#include "Delay.h" - -#include "../../core/serial.h" -#include "../../libs/L64XX/L64XX_Marlin.h" - -// Make sure GCC optimizes this file. -// Note that this line triggers a bug in GCC which is fixed by casting. -// See the note below. -#pragma GCC optimize (3) - -// run at ~4Mhz -inline uint8_t L6470_SpiTransfer_Mode_0(uint8_t b) { // using Mode 0 - for (uint8_t bits = 8; bits--;) { - WRITE(L6470_CHAIN_MOSI_PIN, b & 0x80); - b <<= 1; // little setup time - - WRITE(L6470_CHAIN_SCK_PIN, HIGH); - DELAY_NS(125); // 10 cycles @ 84mhz - - b |= (READ(L6470_CHAIN_MISO_PIN) != 0); - - WRITE(L6470_CHAIN_SCK_PIN, LOW); - DELAY_NS(125); // 10 cycles @ 84mhz - } - return b; -} - -inline uint8_t L6470_SpiTransfer_Mode_3(uint8_t b) { // using Mode 3 - for (uint8_t bits = 8; bits--;) { - WRITE(L6470_CHAIN_SCK_PIN, LOW); - WRITE(L6470_CHAIN_MOSI_PIN, b & 0x80); - - DELAY_NS(125); // 10 cycles @ 84mhz - WRITE(L6470_CHAIN_SCK_PIN, HIGH); - DELAY_NS(125); // Need more delay for fast CPUs - - b <<= 1; // little setup time - b |= (READ(L6470_CHAIN_MISO_PIN) != 0); - } - DELAY_NS(125); // 10 cycles @ 84mhz - return b; -} - -/** - * L64XX methods for SPI init and transfer - */ -void L64XX_Marlin::spi_init() { - OUT_WRITE(L6470_CHAIN_SS_PIN, HIGH); - OUT_WRITE(L6470_CHAIN_SCK_PIN, HIGH); - OUT_WRITE(L6470_CHAIN_MOSI_PIN, HIGH); - SET_INPUT(L6470_CHAIN_MISO_PIN); - - #if PIN_EXISTS(L6470_BUSY) - SET_INPUT(L6470_BUSY_PIN); - #endif - - OUT_WRITE(L6470_CHAIN_MOSI_PIN, HIGH); -} - -uint8_t L64XX_Marlin::transfer_single(uint8_t data, int16_t ss_pin) { - // First device in chain has data sent last - extDigitalWrite(ss_pin, LOW); - - hal.isr_off(); // Disable interrupts during SPI transfer (can't allow partial command to chips) - const uint8_t data_out = L6470_SpiTransfer_Mode_3(data); - hal.isr_on(); // Enable interrupts - - extDigitalWrite(ss_pin, HIGH); - return data_out; -} - -uint8_t L64XX_Marlin::transfer_chain(uint8_t data, int16_t ss_pin, uint8_t chain_position) { - uint8_t data_out = 0; - - // first device in chain has data sent last - extDigitalWrite(ss_pin, LOW); - - for (uint8_t i = L64XX::chain[0]; !L64xxManager.spi_abort && i >= 1; i--) { // Send data unless aborted - hal.isr_off(); // Disable interrupts during SPI transfer (can't allow partial command to chips) - const uint8_t temp = L6470_SpiTransfer_Mode_3(uint8_t(i == chain_position ? data : dSPIN_NOP)); - hal.isr_on(); // Enable interrupts - if (i == chain_position) data_out = temp; - } - - extDigitalWrite(ss_pin, HIGH); - return data_out; -} - -/** - * Platform-supplied L6470 buffer transfer method - */ -void L64XX_Marlin::transfer(uint8_t L6470_buf[], const uint8_t length) { - // First device in chain has its data sent last - - if (spi_active) { // Interrupted SPI transfer so need to - WRITE(L6470_CHAIN_SS_PIN, HIGH); // guarantee min high of 650ns - DELAY_US(1); - } - - WRITE(L6470_CHAIN_SS_PIN, LOW); - for (uint8_t i = length; i >= 1; i--) - L6470_SpiTransfer_Mode_3(uint8_t(L6470_buf[i])); - WRITE(L6470_CHAIN_SS_PIN, HIGH); -} - -#pragma GCC reset_options - -#endif // HAS_L64XX diff --git a/Marlin/src/HAL/shared/HAL_MinSerial.cpp b/Marlin/src/HAL/shared/MinSerial.cpp similarity index 97% rename from Marlin/src/HAL/shared/HAL_MinSerial.cpp rename to Marlin/src/HAL/shared/MinSerial.cpp index 9dda5fdf8c..2e718d83dc 100644 --- a/Marlin/src/HAL/shared/HAL_MinSerial.cpp +++ b/Marlin/src/HAL/shared/MinSerial.cpp @@ -19,7 +19,7 @@ * along with this program. If not, see . * */ -#include "HAL_MinSerial.h" +#include "MinSerial.h" #if ENABLED(POSTMORTEM_DEBUGGING) diff --git a/Marlin/src/HAL/shared/HAL_MinSerial.h b/Marlin/src/HAL/shared/MinSerial.h similarity index 100% rename from Marlin/src/HAL/shared/HAL_MinSerial.h rename to Marlin/src/HAL/shared/MinSerial.h diff --git a/Marlin/src/HAL/shared/backtrace/backtrace.cpp b/Marlin/src/HAL/shared/backtrace/backtrace.cpp index ad88de8385..33e8e65154 100644 --- a/Marlin/src/HAL/shared/backtrace/backtrace.cpp +++ b/Marlin/src/HAL/shared/backtrace/backtrace.cpp @@ -25,7 +25,7 @@ #include "unwinder.h" #include "unwmemaccess.h" -#include "../HAL_MinSerial.h" +#include "../MinSerial.h" #include // Dump a backtrace entry diff --git a/Marlin/src/HAL/shared/backtrace/unwarmbytab.cpp b/Marlin/src/HAL/shared/backtrace/unwarmbytab.cpp index f1ee81ed4a..148927a19f 100644 --- a/Marlin/src/HAL/shared/backtrace/unwarmbytab.cpp +++ b/Marlin/src/HAL/shared/backtrace/unwarmbytab.cpp @@ -135,11 +135,11 @@ static UnwResult UnwTabExecuteInstructions(const UnwindCallbacks *cb, UnwTabStat while ((instruction = UnwTabGetNextInstruction(cb, ucb)) != -1) { if ((instruction & 0xC0) == 0x00) { // ARM_EXIDX_CMD_DATA_POP - /* vsp = vsp + (xxxxxx << 2) + 4 */ + /* vsp += (xxxxxx << 2) + 4 */ ucb->vrs[13] += ((instruction & 0x3F) << 2) + 4; } else if ((instruction & 0xC0) == 0x40) { // ARM_EXIDX_CMD_DATA_PUSH - /* vsp = vsp - (xxxxxx << 2) - 4 */ + /* vsp -= (xxxxxx << 2) - 4 */ ucb->vrs[13] -= ((instruction & 0x3F) << 2) - 4; } else if ((instruction & 0xF0) == 0x80) { diff --git a/Marlin/src/HAL/shared/cpu_exception/exception_arm.cpp b/Marlin/src/HAL/shared/cpu_exception/exception_arm.cpp index a106ed2b05..e54661c770 100644 --- a/Marlin/src/HAL/shared/cpu_exception/exception_arm.cpp +++ b/Marlin/src/HAL/shared/cpu_exception/exception_arm.cpp @@ -54,7 +54,7 @@ #include "exception_hook.h" #include "../backtrace/backtrace.h" -#include "../HAL_MinSerial.h" +#include "../MinSerial.h" #define HW_REG(X) (*((volatile unsigned long *)(X))) @@ -221,7 +221,7 @@ bool resume_from_fault() { // So we'll just need to refresh the watchdog for a while and then stop for the system to reboot uint32_t last = start; while (PENDING(last, end)) { - watchdog_refresh(); + hal.watchdog_refresh(); while (millis() == last) { /* nada */ } last = millis(); MinSerial::TX('.'); diff --git a/Marlin/src/HAL/shared/servo.cpp b/Marlin/src/HAL/shared/servo.cpp index cfec6f3017..b838800de6 100644 --- a/Marlin/src/HAL/shared/servo.cpp +++ b/Marlin/src/HAL/shared/servo.cpp @@ -65,7 +65,7 @@ uint8_t ServoCount = 0; // the total number of attached /************ static functions common to all instances ***********************/ -static boolean isTimerActive(timer16_Sequence_t timer) { +static bool anyTimerChannelActive(const timer16_Sequence_t timer) { // returns true if any servo is active on this timer LOOP_L_N(channel, SERVOS_PER_TIMER) { if (SERVO(timer, channel).Pin.isActive) @@ -101,17 +101,18 @@ int8_t Servo::attach(const int inPin, const int inMin, const int inMax) { max = (MAX_PULSE_WIDTH - inMax) / 4; // initialize the timer if it has not already been initialized - timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(servoIndex); - if (!isTimerActive(timer)) initISR(timer); - servo_info[servoIndex].Pin.isActive = true; // this must be set after the check for isTimerActive + const timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(servoIndex); + if (!anyTimerChannelActive(timer)) initISR(timer); + servo_info[servoIndex].Pin.isActive = true; // this must be set after the check for anyTimerChannelActive return servoIndex; } void Servo::detach() { servo_info[servoIndex].Pin.isActive = false; - timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(servoIndex); - if (!isTimerActive(timer)) finISR(timer); + const timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(servoIndex); + if (!anyTimerChannelActive(timer)) finISR(timer); + //pinMode(servo_info[servoIndex].Pin.nbr, INPUT); // set servo pin to input } void Servo::write(int value) { diff --git a/Marlin/src/HAL/shared/servo_private.h b/Marlin/src/HAL/shared/servo_private.h index d85d8da8ba..10cc5a1988 100644 --- a/Marlin/src/HAL/shared/servo_private.h +++ b/Marlin/src/HAL/shared/servo_private.h @@ -70,10 +70,10 @@ #define ticksToUs(_ticks) (unsigned(_ticks) * (SERVO_TIMER_PRESCALER) / clockCyclesPerMicrosecond()) // convenience macros -#define SERVO_INDEX_TO_TIMER(_servo_nbr) ((timer16_Sequence_t)(_servo_nbr / (SERVOS_PER_TIMER))) // returns the timer controlling this servo -#define SERVO_INDEX_TO_CHANNEL(_servo_nbr) (_servo_nbr % (SERVOS_PER_TIMER)) // returns the index of the servo on this timer -#define SERVO_INDEX(_timer,_channel) ((_timer*(SERVOS_PER_TIMER)) + _channel) // macro to access servo index by timer and channel -#define SERVO(_timer,_channel) (servo_info[SERVO_INDEX(_timer,_channel)]) // macro to access servo class by timer and channel +#define SERVO_INDEX_TO_TIMER(_servo_nbr) timer16_Sequence_t(_servo_nbr / (SERVOS_PER_TIMER)) // the timer controlling this servo +#define SERVO_INDEX_TO_CHANNEL(_servo_nbr) (_servo_nbr % (SERVOS_PER_TIMER)) // the index of the servo on this timer +#define SERVO_INDEX(_timer,_channel) ((_timer*(SERVOS_PER_TIMER)) + _channel) // servo index by timer and channel +#define SERVO(_timer,_channel) servo_info[SERVO_INDEX(_timer,_channel)] // servo class by timer and channel // Types @@ -94,5 +94,5 @@ extern ServoInfo_t servo_info[MAX_SERVOS]; // Public functions -extern void initISR(timer16_Sequence_t timer); -extern void finISR(timer16_Sequence_t timer); +void initISR(const timer16_Sequence_t timer_index); +void finISR(const timer16_Sequence_t timer_index); diff --git a/Marlin/src/MarlinCore.cpp b/Marlin/src/MarlinCore.cpp index 2570e6ebde..099289f35b 100644 --- a/Marlin/src/MarlinCore.cpp +++ b/Marlin/src/MarlinCore.cpp @@ -76,8 +76,6 @@ #include "lcd/e3v2/creality/dwin.h" #elif ENABLED(DWIN_LCD_PROUI) #include "lcd/e3v2/proui/dwin.h" - #elif ENABLED(DWIN_CREALITY_LCD_JYERSUI) - #include "lcd/e3v2/jyersui/dwin.h" #endif #endif @@ -97,7 +95,7 @@ #include "feature/host_actions.h" #endif -#if USE_BEEPER +#if HAS_BEEPER #include "libs/buzzer.h" #endif @@ -228,10 +226,6 @@ #include "feature/mmu/mmu2.h" #endif -#if HAS_L64XX - #include "libs/L64XX/L64XX_Marlin.h" -#endif - #if ENABLED(PASSWORD_FEATURE) #include "feature/password/password.h" #endif @@ -271,6 +265,7 @@ bool wait_for_heatup = true; while (wait_for_user && !(ms && ELAPSED(millis(), ms))) idle(TERN_(ADVANCED_PAUSE_FEATURE, no_sleep)); wait_for_user = false; + while (ui.button_pressed()) safe_delay(50); } #endif @@ -320,6 +315,10 @@ bool pin_is_protected(const pin_t pin) { #pragma GCC diagnostic pop +bool printer_busy() { + return planner.movesplanned() || printingIsActive(); +} + /** * A Print Job exists when the timer is running or SD is printing */ @@ -412,41 +411,44 @@ inline void manage_inactivity(const bool no_stepper_sleep=false) { if (do_reset_timeout) gcode.reset_stepper_timeout(ms); if (gcode.stepper_max_timed_out(ms)) { - SERIAL_ERROR_MSG(STR_KILL_INACTIVE_TIME, parser.command_ptr); + SERIAL_ERROR_START(); + SERIAL_ECHOPGM(STR_KILL_PRE); + SERIAL_ECHOLNPGM(STR_KILL_INACTIVE_TIME, parser.command_ptr); kill(); } + const bool has_blocks = planner.has_blocks_queued(); // Any moves in the planner? + if (has_blocks) gcode.reset_stepper_timeout(ms); // Reset timeout for M18/M84, M85 max 'kill', and laser. + // M18 / M84 : Handle steppers inactive time timeout - if (gcode.stepper_inactive_time) { + #if HAS_DISABLE_INACTIVE_AXIS + if (gcode.stepper_inactive_time) { - static bool already_shutdown_steppers; // = false + static bool already_shutdown_steppers; // = false - // Any moves in the planner? Resets both the M18/M84 - // activity timeout and the M85 max 'kill' timeout - if (planner.has_blocks_queued()) - gcode.reset_stepper_timeout(ms); - else if (!do_reset_timeout && gcode.stepper_inactive_timeout()) { - if (!already_shutdown_steppers) { - already_shutdown_steppers = true; // L6470 SPI will consume 99% of free time without this + if (!has_blocks && !do_reset_timeout && gcode.stepper_inactive_timeout()) { + if (!already_shutdown_steppers) { + already_shutdown_steppers = true; - // Individual axes will be disabled if configured - TERN_(DISABLE_INACTIVE_X, stepper.disable_axis(X_AXIS)); - TERN_(DISABLE_INACTIVE_Y, stepper.disable_axis(Y_AXIS)); - TERN_(DISABLE_INACTIVE_Z, stepper.disable_axis(Z_AXIS)); - TERN_(DISABLE_INACTIVE_I, stepper.disable_axis(I_AXIS)); - TERN_(DISABLE_INACTIVE_J, stepper.disable_axis(J_AXIS)); - TERN_(DISABLE_INACTIVE_K, stepper.disable_axis(K_AXIS)); - TERN_(DISABLE_INACTIVE_U, stepper.disable_axis(U_AXIS)); - TERN_(DISABLE_INACTIVE_V, stepper.disable_axis(V_AXIS)); - TERN_(DISABLE_INACTIVE_W, stepper.disable_axis(W_AXIS)); - TERN_(DISABLE_INACTIVE_E, stepper.disable_e_steppers()); + // Individual axes will be disabled if configured + TERN_(DISABLE_INACTIVE_X, stepper.disable_axis(X_AXIS)); + TERN_(DISABLE_INACTIVE_Y, stepper.disable_axis(Y_AXIS)); + TERN_(DISABLE_INACTIVE_Z, stepper.disable_axis(Z_AXIS)); + TERN_(DISABLE_INACTIVE_I, stepper.disable_axis(I_AXIS)); + TERN_(DISABLE_INACTIVE_J, stepper.disable_axis(J_AXIS)); + TERN_(DISABLE_INACTIVE_K, stepper.disable_axis(K_AXIS)); + TERN_(DISABLE_INACTIVE_U, stepper.disable_axis(U_AXIS)); + TERN_(DISABLE_INACTIVE_V, stepper.disable_axis(V_AXIS)); + TERN_(DISABLE_INACTIVE_W, stepper.disable_axis(W_AXIS)); + TERN_(DISABLE_INACTIVE_E, stepper.disable_e_steppers()); - TERN_(AUTO_BED_LEVELING_UBL, ubl.steppers_were_disabled()); + TERN_(AUTO_BED_LEVELING_UBL, bedlevel.steppers_were_disabled()); + } } + else + already_shutdown_steppers = false; } - else - already_shutdown_steppers = false; - } + #endif #if ENABLED(PHOTO_GCODE) && PIN_EXISTS(CHDK) // Check if CHDK should be set to LOW (after M240 set it HIGH) @@ -473,7 +475,9 @@ inline void manage_inactivity(const bool no_stepper_sleep=false) { // KILL the machine // ---------------------------------------------------------------- if (killCount >= KILL_DELAY) { - SERIAL_ERROR_MSG(STR_KILL_BUTTON); + SERIAL_ERROR_START(); + SERIAL_ECHOPGM(STR_KILL_PRE); + SERIAL_ECHOLNPGM(STR_KILL_BUTTON); kill(); } #endif @@ -723,8 +727,6 @@ inline void manage_inactivity(const bool no_stepper_sleep=false) { TERN_(MONITOR_DRIVER_STATUS, monitor_tmc_drivers()); - TERN_(MONITOR_L6470_DRIVER_STATUS, L64xxManager.monitor_driver()); - // Limit check_axes_activity frequency to 10Hz static millis_t next_check_axes_ms = 0; if (ELAPSED(ms, next_check_axes_ms)) { @@ -766,6 +768,10 @@ inline void manage_inactivity(const bool no_stepper_sleep=false) { * - Handle Joystick jogging */ void idle(bool no_stepper_sleep/*=false*/) { + #ifdef MAX7219_DEBUG_PROFILE + CodeProfiler idle_profiler; + #endif + #if ENABLED(MARLIN_DEV_MODE) static uint16_t idle_depth = 0; if (++idle_depth > 5) SERIAL_ECHOLNPGM("idle() call depth: ", idle_depth); @@ -775,7 +781,7 @@ void idle(bool no_stepper_sleep/*=false*/) { manage_inactivity(no_stepper_sleep); // Manage Heaters (and Watchdog) - thermalManager.manage_heater(); + thermalManager.task(); // Max7219 heartbeat, animation, etc TERN_(MAX7219_DEBUG, max7219.idle_tasks()); @@ -822,7 +828,7 @@ void idle(bool no_stepper_sleep/*=false*/) { TERN_(PRINTCOUNTER, print_job_timer.tick()); // Update the Beeper queue - TERN_(USE_BEEPER, buzzer.tick()); + TERN_(HAS_BEEPER, buzzer.tick()); // Handle UI input / draw events TERN(DWIN_CREALITY_LCD, DWIN_Update(), ui.update()); @@ -881,7 +887,7 @@ void kill(FSTR_P const lcd_error/*=nullptr*/, FSTR_P const lcd_component/*=nullp // Echo the LCD message to serial for extra context if (lcd_error) { SERIAL_ECHO_START(); SERIAL_ECHOLNF(lcd_error); } - #if EITHER(HAS_DISPLAY, DWIN_LCD_PROUI) + #if HAS_DISPLAY ui.kill_screen(lcd_error ?: GET_TEXT_F(MSG_KILLED), lcd_component ?: FPSTR(NUL_STR)); #else UNUSED(lcd_error); UNUSED(lcd_component); @@ -925,18 +931,18 @@ void minkill(const bool steppers_off/*=false*/) { // Wait for both KILL and ENC to be released while (TERN0(HAS_KILL, kill_state()) || TERN0(SOFT_RESET_ON_KILL, ui.button_pressed())) - watchdog_refresh(); + hal.watchdog_refresh(); // Wait for either KILL or ENC to be pressed again while (TERN1(HAS_KILL, !kill_state()) && TERN1(SOFT_RESET_ON_KILL, !ui.button_pressed())) - watchdog_refresh(); + hal.watchdog_refresh(); // Reboot the board hal.reboot(); #else - for (;;) watchdog_refresh(); // Wait for RESET button or power-cycle + for (;;) hal.watchdog_refresh(); // Wait for RESET button or power-cycle #endif } @@ -1050,7 +1056,6 @@ inline void tmc_standby_setup() { * • TMC220x Stepper Drivers (Serial) * • PSU control * • Power-loss Recovery - * • L64XX Stepper Drivers (SPI) * • Stepper Driver Reset: DISABLE * • TMC Stepper Drivers (SPI) * • Run hal.init_board() for additional pins setup @@ -1232,6 +1237,13 @@ void setup() { SETUP_RUN(tmc_serial_begin()); #endif + #if HAS_TMC_SPI + #if DISABLED(TMC_USE_SW_SPI) + SETUP_RUN(SPI.begin()); + #endif + SETUP_RUN(tmc_init_cs_pins()); + #endif + #if ENABLED(PSU_CONTROL) SETUP_LOG("PSU_CONTROL"); powerManager.init(); @@ -1241,21 +1253,10 @@ void setup() { SETUP_RUN(recovery.setup()); #endif - #if HAS_L64XX - SETUP_RUN(L64xxManager.init()); // Set up SPI, init drivers - #endif - #if HAS_STEPPER_RESET SETUP_RUN(disableStepperDrivers()); #endif - #if HAS_TMC_SPI - #if DISABLED(TMC_USE_SW_SPI) - SETUP_RUN(SPI.begin()); - #endif - SETUP_RUN(tmc_init_cs_pins()); - #endif - SETUP_RUN(hal.init_board()); SETUP_RUN(esp_wifi_init()); @@ -1282,7 +1283,7 @@ void setup() { calibrate_delay_loop(); // Init buzzer pin(s) - #if USE_BEEPER + #if HAS_BEEPER SETUP_RUN(buzzer.init()); #endif @@ -1552,7 +1553,7 @@ void setup() { #endif #if ENABLED(USE_WATCHDOG) - SETUP_RUN(watchdog_init()); // Reinit watchdog after hal.get_reset_source call + SETUP_RUN(hal.watchdog_init()); // Reinit watchdog after hal.get_reset_source call #endif #if ENABLED(EXTERNAL_CLOSED_LOOP_CONTROLLER) @@ -1568,10 +1569,6 @@ void setup() { SETUP_RUN(hostui.prompt_end()); #endif - #if HAS_TRINAMIC_CONFIG && DISABLED(PSU_DEFAULT_OFF) - SETUP_RUN(test_tmc_connection()); - #endif - #if HAS_DRIVER_SAFE_POWER_PROTECT SETUP_RUN(stepper_driver_backward_report()); #endif @@ -1629,6 +1626,10 @@ void setup() { SETUP_RUN(easythreed_ui.init()); #endif + #if HAS_TRINAMIC_CONFIG && DISABLED(PSU_DEFAULT_OFF) + SETUP_RUN(test_tmc_connection()); + #endif + marlin_state = MF_RUNNING; SETUP_LOG("setup() completed."); diff --git a/Marlin/src/MarlinCore.h b/Marlin/src/MarlinCore.h index 7063c7e2de..f80405a302 100644 --- a/Marlin/src/MarlinCore.h +++ b/Marlin/src/MarlinCore.h @@ -61,6 +61,8 @@ bool printJobOngoing(); bool printingIsPaused(); void startOrResumeJob(); +bool printer_busy(); + extern bool wait_for_heatup; #if HAS_RESUME_CONTINUE diff --git a/Marlin/src/core/boards.h b/Marlin/src/core/boards.h index d4ec32210d..506b9cbd0e 100644 --- a/Marlin/src/core/boards.h +++ b/Marlin/src/core/boards.h @@ -161,7 +161,7 @@ #define BOARD_PICA_REVB 1324 // PICA Shield (original version) #define BOARD_PICA 1325 // PICA Shield (rev C or later) #define BOARD_INTAMSYS40 1326 // Intamsys 4.0 (Funmat HT) -#define BOARD_MALYAN_M180 1327 // Malyan M180 Mainboard Version 2 (no display function, direct gcode only) +#define BOARD_MALYAN_M180 1327 // Malyan M180 Mainboard Version 2 (no display function, direct G-code only) #define BOARD_GT2560_V4_A20 1328 // Geeetech GT2560 Rev B for A20(M/T/D) #define BOARD_PROTONEER_CNC_SHIELD_V3 1329 // Mega controller & Protoneer CNC Shield V3.00 #define BOARD_WEEDO_62A 1330 // WEEDO 62A board (TINA2, Monoprice Cadet, etc.) @@ -228,33 +228,34 @@ #define BOARD_RAMPS_14_RE_ARM_EFF 2002 // Re-ARM with RAMPS 1.4 (Power outputs: Hotend, Fan0, Fan1) #define BOARD_RAMPS_14_RE_ARM_EEF 2003 // Re-ARM with RAMPS 1.4 (Power outputs: Hotend0, Hotend1, Fan) #define BOARD_RAMPS_14_RE_ARM_SF 2004 // Re-ARM with RAMPS 1.4 (Power outputs: Spindle, Controller Fan) -#define BOARD_MKS_SBASE 2005 // MKS-Sbase (Power outputs: Hotend0, Hotend1, Bed, Fan) +#define BOARD_MKS_SBASE 2005 // MKS-Sbase #define BOARD_AZSMZ_MINI 2006 // AZSMZ Mini -#define BOARD_BIQU_BQ111_A4 2007 // BIQU BQ111-A4 (Power outputs: Hotend, Fan, Bed) -#define BOARD_SELENA_COMPACT 2008 // Selena Compact (Power outputs: Hotend0, Hotend1, Bed0, Bed1, Fan0, Fan1) -#define BOARD_BIQU_B300_V1_0 2009 // BIQU B300_V1.0 (Power outputs: Hotend0, Fan, Bed, SPI Driver) -#define BOARD_MKS_SGEN_L 2010 // MKS-SGen-L (Power outputs: Hotend0, Hotend1, Bed, Fan) +#define BOARD_BIQU_BQ111_A4 2007 // BIQU BQ111-A4 +#define BOARD_SELENA_COMPACT 2008 // Selena Compact +#define BOARD_BIQU_B300_V1_0 2009 // BIQU B300_V1.0 +#define BOARD_MKS_SGEN_L 2010 // MKS-SGen-L #define BOARD_GMARSH_X6_REV1 2011 // GMARSH X6, revision 1 prototype -#define BOARD_BTT_SKR_V1_1 2012 // BigTreeTech SKR v1.1 (Power outputs: Hotend0, Hotend1, Fan, Bed) -#define BOARD_BTT_SKR_V1_3 2013 // BigTreeTech SKR v1.3 (Power outputs: Hotend0, Hotend1, Fan, Bed) -#define BOARD_BTT_SKR_V1_4 2014 // BigTreeTech SKR v1.4 (Power outputs: Hotend0, Hotend1, Fan, Bed) +#define BOARD_BTT_SKR_V1_1 2012 // BigTreeTech SKR v1.1 +#define BOARD_BTT_SKR_V1_3 2013 // BigTreeTech SKR v1.3 +#define BOARD_BTT_SKR_V1_4 2014 // BigTreeTech SKR v1.4 +#define BOARD_EMOTRONIC 2015 // eMotion-Tech eMotronic // // LPC1769 ARM Cortex M3 // -#define BOARD_MKS_SGEN 2500 // MKS-SGen (Power outputs: Hotend0, Hotend1, Bed, Fan) -#define BOARD_AZTEEG_X5_GT 2501 // Azteeg X5 GT (Power outputs: Hotend0, Hotend1, Bed, Fan) -#define BOARD_AZTEEG_X5_MINI 2502 // Azteeg X5 Mini (Power outputs: Hotend0, Bed, Fan) -#define BOARD_AZTEEG_X5_MINI_WIFI 2503 // Azteeg X5 Mini Wifi (Power outputs: Hotend0, Bed, Fan) +#define BOARD_MKS_SGEN 2500 // MKS-SGen +#define BOARD_AZTEEG_X5_GT 2501 // Azteeg X5 GT +#define BOARD_AZTEEG_X5_MINI 2502 // Azteeg X5 Mini +#define BOARD_AZTEEG_X5_MINI_WIFI 2503 // Azteeg X5 Mini Wifi #define BOARD_COHESION3D_REMIX 2504 // Cohesion3D ReMix #define BOARD_COHESION3D_MINI 2505 // Cohesion3D Mini #define BOARD_SMOOTHIEBOARD 2506 // Smoothieboard #define BOARD_TH3D_EZBOARD 2507 // TH3D EZBoard v1.0 -#define BOARD_BTT_SKR_V1_4_TURBO 2508 // BigTreeTech SKR v1.4 TURBO (Power outputs: Hotend0, Hotend1, Fan, Bed) -#define BOARD_MKS_SGEN_L_V2 2509 // MKS SGEN_L V2 (Power outputs: Hotend0, Hotend1, Bed, Fan) -#define BOARD_BTT_SKR_E3_TURBO 2510 // BigTreeTech SKR E3 Turbo (Power outputs: Hotend0, Hotend1, Bed, Fan0, Fan1) -#define BOARD_FLY_CDY 2511 // FLYmaker FLY CDY (Power outputs: Hotend0, Hotend1, Hotend2, Bed, Fan0, Fan1, Fan2) +#define BOARD_BTT_SKR_V1_4_TURBO 2508 // BigTreeTech SKR v1.4 TURBO +#define BOARD_MKS_SGEN_L_V2 2509 // MKS SGEN_L V2 +#define BOARD_BTT_SKR_E3_TURBO 2510 // BigTreeTech SKR E3 Turbo +#define BOARD_FLY_CDY 2511 // FLYmaker FLY CDY // // SAM3X8E ARM Cortex M3 @@ -280,8 +281,8 @@ #define BOARD_RAMPS4DUE_EFF 3017 // RAMPS4DUE (Power outputs: Hotend, Fan0, Fan1) #define BOARD_RAMPS4DUE_EEF 3018 // RAMPS4DUE (Power outputs: Hotend0, Hotend1, Fan) #define BOARD_RAMPS4DUE_SF 3019 // RAMPS4DUE (Power outputs: Spindle, Controller Fan) -#define BOARD_RURAMPS4D_11 3020 // RuRAMPS4Duo v1.1 (Power outputs: Hotend0, Hotend1, Hotend2, Fan0, Fan1, Bed) -#define BOARD_RURAMPS4D_13 3021 // RuRAMPS4Duo v1.3 (Power outputs: Hotend0, Hotend1, Hotend2, Fan0, Fan1, Bed) +#define BOARD_RURAMPS4D_11 3020 // RuRAMPS4Duo v1.1 +#define BOARD_RURAMPS4D_13 3021 // RuRAMPS4Duo v1.3 #define BOARD_ULTRATRONICS_PRO 3022 // ReprapWorld Ultratronics Pro V1.0 #define BOARD_ARCHIM1 3023 // UltiMachine Archim1 (with DRV8825 drivers) #define BOARD_ARCHIM2 3024 // UltiMachine Archim2 (with TMC2130 drivers) @@ -293,7 +294,7 @@ // SAM3X8C ARM Cortex M3 // -#define BOARD_PRINTRBOARD_G2 3100 // PRINTRBOARD G2 +#define BOARD_PRINTRBOARD_G2 3100 // Printrboard G2 #define BOARD_ADSK 3101 // Arduino DUE Shield Kit (ADSK) // @@ -332,40 +333,41 @@ #define BOARD_BTT_SKR_E3_DIP 4029 // BigTreeTech SKR E3 DIP V1.0 (STM32F103RC / STM32F103RE) #define BOARD_BTT_SKR_CR6 4030 // BigTreeTech SKR CR6 v1.0 (STM32F103RE) #define BOARD_JGAURORA_A5S_A1 4031 // JGAurora A5S A1 (STM32F103ZE) -#define BOARD_FYSETC_AIO_II 4032 // FYSETC AIO_II -#define BOARD_FYSETC_CHEETAH 4033 // FYSETC Cheetah -#define BOARD_FYSETC_CHEETAH_V12 4034 // FYSETC Cheetah V1.2 -#define BOARD_LONGER3D_LK 4035 // Alfawise U20/U20+/U30 (Longer3D LK1/2) / STM32F103VE +#define BOARD_FYSETC_AIO_II 4032 // FYSETC AIO_II (STM32F103RC) +#define BOARD_FYSETC_CHEETAH 4033 // FYSETC Cheetah (STM32F103RC) +#define BOARD_FYSETC_CHEETAH_V12 4034 // FYSETC Cheetah V1.2 (STM32F103RC) +#define BOARD_LONGER3D_LK 4035 // Longer3D LK1/2 - Alfawise U20/U20+/U30 (STM32F103VE) #define BOARD_CCROBOT_MEEB_3DP 4036 // ccrobot-online.com MEEB_3DP (STM32F103RC) -#define BOARD_CHITU3D_V5 4037 // Chitu3D TronXY X5SA V5 Board -#define BOARD_CHITU3D_V6 4038 // Chitu3D TronXY X5SA V6 Board -#define BOARD_CHITU3D_V9 4039 // Chitu3D TronXY X5SA V9 Board +#define BOARD_CHITU3D_V5 4037 // Chitu3D TronXY X5SA V5 Board (STM32F103ZE) +#define BOARD_CHITU3D_V6 4038 // Chitu3D TronXY X5SA V6 Board (STM32F103ZE) +#define BOARD_CHITU3D_V9 4039 // Chitu3D TronXY X5SA V9 Board (STM32F103ZE) #define BOARD_CREALITY_V4 4040 // Creality v4.x (STM32F103RC / STM32F103RE) #define BOARD_CREALITY_V422 4041 // Creality v4.2.2 (STM32F103RC / STM32F103RE) #define BOARD_CREALITY_V423 4042 // Creality v4.2.3 (STM32F103RC / STM32F103RE) -#define BOARD_CREALITY_V427 4043 // Creality v4.2.7 (STM32F103RC / STM32F103RE) -#define BOARD_CREALITY_V4210 4044 // Creality v4.2.10 (STM32F103RC / STM32F103RE) as found in the CR-30 -#define BOARD_CREALITY_V431 4045 // Creality v4.3.1 (STM32F103RC / STM32F103RE) -#define BOARD_CREALITY_V431_A 4046 // Creality v4.3.1a (STM32F103RC / STM32F103RE) -#define BOARD_CREALITY_V431_B 4047 // Creality v4.3.1b (STM32F103RC / STM32F103RE) -#define BOARD_CREALITY_V431_C 4048 // Creality v4.3.1c (STM32F103RC / STM32F103RE) -#define BOARD_CREALITY_V431_D 4049 // Creality v4.3.1d (STM32F103RC / STM32F103RE) -#define BOARD_CREALITY_V452 4050 // Creality v4.5.2 (STM32F103RC / STM32F103RE) -#define BOARD_CREALITY_V453 4051 // Creality v4.5.3 (STM32F103RC / STM32F103RE) -#define BOARD_CREALITY_V24S1 4052 // Creality v2.4.S1 (STM32F103RC / STM32F103RE) v101 as found in the Ender 7 -#define BOARD_CREALITY_V24S1_301 4053 // Creality v2.4.S1_301 (STM32F103RC / STM32F103RE) as found in the Ender 3 S1 -#define BOARD_CREALITY_V25S1 4054 // Creality v4.5.1 (STM32F103RE) as found in the CR10 Smart Pro -#define BOARD_TRIGORILLA_PRO 4055 // Trigorilla Pro (STM32F103ZE) -#define BOARD_FLY_MINI 4056 // FLYmaker FLY MINI (STM32F103RC) -#define BOARD_FLSUN_HISPEED 4057 // FLSUN HiSpeedV1 (STM32F103VE) -#define BOARD_BEAST 4058 // STM32F103RE Libmaple-based controller -#define BOARD_MINGDA_MPX_ARM_MINI 4059 // STM32F103ZE Mingda MD-16 -#define BOARD_GTM32_PRO_VD 4060 // STM32F103VE controller -#define BOARD_ZONESTAR_ZM3E2 4061 // Zonestar ZM3E2 (STM32F103RC) -#define BOARD_ZONESTAR_ZM3E4 4062 // Zonestar ZM3E4 V1 (STM32F103VC) -#define BOARD_ZONESTAR_ZM3E4V2 4063 // Zonestar ZM3E4 V2 (STM32F103VC) -#define BOARD_ERYONE_ERY32_MINI 4064 // Eryone Ery32 mini (STM32F103VE) -#define BOARD_PANDA_PI_V29 4065 // Panda Pi V2.9 - Standalone (STM32F103RC) +#define BOARD_CREALITY_V425 4043 // Creality v4.2.5 (STM32F103RC / STM32F103RE) +#define BOARD_CREALITY_V427 4044 // Creality v4.2.7 (STM32F103RC / STM32F103RE) +#define BOARD_CREALITY_V4210 4045 // Creality v4.2.10 (STM32F103RC / STM32F103RE) as found in the CR-30 +#define BOARD_CREALITY_V431 4046 // Creality v4.3.1 (STM32F103RC / STM32F103RE) +#define BOARD_CREALITY_V431_A 4047 // Creality v4.3.1a (STM32F103RC / STM32F103RE) +#define BOARD_CREALITY_V431_B 4048 // Creality v4.3.1b (STM32F103RC / STM32F103RE) +#define BOARD_CREALITY_V431_C 4049 // Creality v4.3.1c (STM32F103RC / STM32F103RE) +#define BOARD_CREALITY_V431_D 4050 // Creality v4.3.1d (STM32F103RC / STM32F103RE) +#define BOARD_CREALITY_V452 4051 // Creality v4.5.2 (STM32F103RC / STM32F103RE) +#define BOARD_CREALITY_V453 4052 // Creality v4.5.3 (STM32F103RC / STM32F103RE) +#define BOARD_CREALITY_V24S1 4053 // Creality v2.4.S1 (STM32F103RC / STM32F103RE) v101 as found in the Ender-7 +#define BOARD_CREALITY_V24S1_301 4054 // Creality v2.4.S1_301 (STM32F103RC / STM32F103RE) v301 as found in the Ender-3 S1 +#define BOARD_CREALITY_V25S1 4055 // Creality v2.5.S1 (STM32F103RE) as found in the CR-10 Smart Pro +#define BOARD_TRIGORILLA_PRO 4056 // Trigorilla Pro (STM32F103ZE) +#define BOARD_FLY_MINI 4057 // FLYmaker FLY MINI (STM32F103RC) +#define BOARD_FLSUN_HISPEED 4058 // FLSUN HiSpeedV1 (STM32F103VE) +#define BOARD_BEAST 4059 // STM32F103RE Libmaple-based controller +#define BOARD_MINGDA_MPX_ARM_MINI 4060 // STM32F103ZE Mingda MD-16 +#define BOARD_GTM32_PRO_VD 4061 // STM32F103VE controller +#define BOARD_ZONESTAR_ZM3E2 4062 // Zonestar ZM3E2 (STM32F103RC) +#define BOARD_ZONESTAR_ZM3E4 4063 // Zonestar ZM3E4 V1 (STM32F103VC) +#define BOARD_ZONESTAR_ZM3E4V2 4064 // Zonestar ZM3E4 V2 (STM32F103VC) +#define BOARD_ERYONE_ERY32_MINI 4065 // Eryone Ery32 mini (STM32F103VE) +#define BOARD_PANDA_PI_V29 4066 // Panda Pi V2.9 - Standalone (STM32F103RC) // // ARM Cortex-M4F @@ -385,7 +387,6 @@ #define BOARD_RUMBA32_BTT 4204 // RUMBA32 STM32F446VE based controller from BIGTREETECH #define BOARD_BLACK_STM32F407VE 4205 // BLACK_STM32F407VE #define BOARD_BLACK_STM32F407ZE 4206 // BLACK_STM32F407ZE -#define BOARD_STEVAL_3DP001V1 4207 // STEVAL-3DP001V1 3D PRINTER BOARD #define BOARD_BTT_SKR_PRO_V1_1 4208 // BigTreeTech SKR Pro v1.1 (STM32F407ZG) #define BOARD_BTT_SKR_PRO_V1_2 4209 // BigTreeTech SKR Pro v1.2 (STM32F407ZG) #define BOARD_BTT_BTT002_V1_0 4210 // BigTreeTech BTT002 v1.0 (STM32F407VG) @@ -395,7 +396,7 @@ #define BOARD_BTT_GTR_V1_0 4214 // BigTreeTech GTR v1.0 (STM32F407IGT) #define BOARD_BTT_OCTOPUS_V1_0 4215 // BigTreeTech Octopus v1.0 (STM32F446ZE) #define BOARD_BTT_OCTOPUS_V1_1 4216 // BigTreeTech Octopus v1.1 (STM32F446ZE) -#define BOARD_BTT_OCTOPUS_PRO_V1_0 4217 // BigTreeTech Octopus Pro v1.0 (STM32F446ZE/STM32F429ZG) +#define BOARD_BTT_OCTOPUS_PRO_V1_0 4217 // BigTreeTech Octopus Pro v1.0 (STM32F446ZE / STM32F429ZG) #define BOARD_LERDGE_K 4218 // Lerdge K (STM32F407ZG) #define BOARD_LERDGE_S 4219 // Lerdge S (STM32F407VE) #define BOARD_LERDGE_X 4220 // Lerdge X (STM32F407VE) @@ -408,16 +409,18 @@ #define BOARD_MKS_ROBIN_PRO_V2 4227 // MKS Robin Pro V2 (STM32F407VE) #define BOARD_MKS_ROBIN_NANO_V3 4228 // MKS Robin Nano V3 (STM32F407VG) #define BOARD_MKS_ROBIN_NANO_V3_1 4229 // MKS Robin Nano V3.1 (STM32F407VE) -#define BOARD_MKS_MONSTER8 4230 // MKS Monster8 (STM32F407VG) -#define BOARD_ANET_ET4 4231 // ANET ET4 V1.x (STM32F407VG) -#define BOARD_ANET_ET4P 4232 // ANET ET4P V1.x (STM32F407VG) -#define BOARD_FYSETC_CHEETAH_V20 4233 // FYSETC Cheetah V2.0 -#define BOARD_TH3D_EZBOARD_V2 4234 // TH3D EZBoard v2.0 -#define BOARD_INDEX_REV03 4235 // Index PnP Controller REV03 (STM32F407VE/VG) -#define BOARD_MKS_ROBIN_NANO_V1_3_F4 4236 // MKS Robin Nano V1.3 and MKS Robin Nano-S V1.3 (STM32F407VE) -#define BOARD_MKS_EAGLE 4237 // MKS Eagle (STM32F407VE) -#define BOARD_ARTILLERY_RUBY 4238 // Artillery Ruby (STM32F401RC) -#define BOARD_FYSETC_SPIDER_V2_2 4239 // FYSETC Spider V2.2 (STM32F446VE) +#define BOARD_MKS_MONSTER8_V1 4230 // MKS Monster8 V1 (STM32F407VE) +#define BOARD_MKS_MONSTER8_V2 4231 // MKS Monster8 V2 (STM32F407VE) +#define BOARD_ANET_ET4 4232 // ANET ET4 V1.x (STM32F407VG) +#define BOARD_ANET_ET4P 4233 // ANET ET4P V1.x (STM32F407VG) +#define BOARD_FYSETC_CHEETAH_V20 4234 // FYSETC Cheetah V2.0 (STM32F401RC) +#define BOARD_TH3D_EZBOARD_V2 4235 // TH3D EZBoard v2.0 (STM32F405RG) +#define BOARD_OPULO_LUMEN_REV3 4236 // Opulo Lumen PnP Controller REV3 (STM32F407VE / STM32F407VG) +#define BOARD_MKS_ROBIN_NANO_V1_3_F4 4237 // MKS Robin Nano V1.3 and MKS Robin Nano-S V1.3 (STM32F407VE) +#define BOARD_MKS_EAGLE 4238 // MKS Eagle (STM32F407VE) +#define BOARD_ARTILLERY_RUBY 4239 // Artillery Ruby (STM32F401RC) +#define BOARD_FYSETC_SPIDER_V2_2 4240 // FYSETC Spider V2.2 (STM32F446VE) +#define BOARD_CREALITY_V24S1_301F4 4241 // Creality v2.4.S1_301F4 (STM32F401RC) as found in the Ender-3 S1 F4 // // ARM Cortex M7 @@ -427,7 +430,10 @@ #define BOARD_TEENSY41 5001 // Teensy 4.1 #define BOARD_T41U5XBB 5002 // T41U5XBB Teensy 4.1 breakout board #define BOARD_NUCLEO_F767ZI 5003 // ST NUCLEO-F767ZI Dev Board -#define BOARD_BTT_SKR_SE_BX 5004 // BigTreeTech SKR SE BX (STM32H743II) +#define BOARD_BTT_SKR_SE_BX_V2 5004 // BigTreeTech SKR SE BX V2.0 (STM32H743II) +#define BOARD_BTT_SKR_SE_BX_V3 5005 // BigTreeTech SKR SE BX V3.0 (STM32H743II) +#define BOARD_BTT_SKR_V3_0 5006 // BigTreeTech SKR V3.0 (STM32H743VG) +#define BOARD_BTT_SKR_V3_0_EZ 5007 // BigTreeTech SKR V3.0 EZ (STM32H743VG) // // Espressif ESP32 WiFi @@ -442,6 +448,7 @@ #define BOARD_PANDA_ZHU 6006 // Panda_ZHU #define BOARD_PANDA_M4 6007 // Panda_M4 #define BOARD_MKS_TINYBEE 6008 // MKS TinyBee based on ESP32 (with I2S stepper stream) +#define BOARD_ENWI_ESPNP 6009 // enwi ESPNP based on ESP32 (with I2S stepper stream) // // SAMD51 ARM Cortex M4 diff --git a/Marlin/src/core/drivers.h b/Marlin/src/core/drivers.h index 80262d513f..8cf03d342a 100644 --- a/Marlin/src/core/drivers.h +++ b/Marlin/src/core/drivers.h @@ -30,10 +30,6 @@ #define _A5984 0x5984 #define _DRV8825 0x8825 #define _LV8729 0x8729 -#define _L6470 0x6470 -#define _L6474 0x6474 -#define _L6480 0x6480 -#define _POWERSTEP01 0xF00D #define _TB6560 0x6560 #define _TB6600 0x6600 #define _TMC2100 0x2100 @@ -67,11 +63,11 @@ #define AXIS_DRIVER_TYPE_V(T) _AXIS_DRIVER_TYPE(V,T) #define AXIS_DRIVER_TYPE_W(T) _AXIS_DRIVER_TYPE(W,T) -#define AXIS_DRIVER_TYPE_X2(T) (EITHER(X_DUAL_STEPPER_DRIVERS, DUAL_X_CARRIAGE) && _AXIS_DRIVER_TYPE(X2,T)) -#define AXIS_DRIVER_TYPE_Y2(T) (ENABLED(Y_DUAL_STEPPER_DRIVERS) && _AXIS_DRIVER_TYPE(Y2,T)) -#define AXIS_DRIVER_TYPE_Z2(T) (NUM_Z_STEPPER_DRIVERS >= 2 && _AXIS_DRIVER_TYPE(Z2,T)) -#define AXIS_DRIVER_TYPE_Z3(T) (NUM_Z_STEPPER_DRIVERS >= 3 && _AXIS_DRIVER_TYPE(Z3,T)) -#define AXIS_DRIVER_TYPE_Z4(T) (NUM_Z_STEPPER_DRIVERS >= 4 && _AXIS_DRIVER_TYPE(Z4,T)) +#define AXIS_DRIVER_TYPE_X2(T) (HAS_X2_STEPPER && _AXIS_DRIVER_TYPE(X2,T)) +#define AXIS_DRIVER_TYPE_Y2(T) (HAS_DUAL_Y_STEPPERS && _AXIS_DRIVER_TYPE(Y2,T)) +#define AXIS_DRIVER_TYPE_Z2(T) (NUM_Z_STEPPERS >= 2 && _AXIS_DRIVER_TYPE(Z2,T)) +#define AXIS_DRIVER_TYPE_Z3(T) (NUM_Z_STEPPERS >= 3 && _AXIS_DRIVER_TYPE(Z3,T)) +#define AXIS_DRIVER_TYPE_Z4(T) (NUM_Z_STEPPERS >= 4 && _AXIS_DRIVER_TYPE(Z4,T)) #define AXIS_DRIVER_TYPE_E(N,T) (E_STEPPERS > N && _AXIS_DRIVER_TYPE(E##N,T)) #define AXIS_DRIVER_TYPE_E0(T) AXIS_DRIVER_TYPE_E(0,T) @@ -193,16 +189,3 @@ #if HAS_DRIVER(TMC26X) #define HAS_TMC26X 1 #endif - -// -// L64XX Stepper Drivers -// - -#if HAS_DRIVER(L6470) || HAS_DRIVER(L6474) || HAS_DRIVER(L6480) || HAS_DRIVER(POWERSTEP01) - #define HAS_L64XX 1 -#endif -#if HAS_L64XX && !HAS_DRIVER(L6474) - #define HAS_L64XX_NOT_L6474 1 -#endif - -#define AXIS_IS_L64XX(A) (AXIS_DRIVER_TYPE_##A(L6470) || AXIS_DRIVER_TYPE_##A(L6474) || AXIS_DRIVER_TYPE_##A(L6480) || AXIS_DRIVER_TYPE_##A(POWERSTEP01)) diff --git a/Marlin/src/core/language.h b/Marlin/src/core/language.h index 89c0babc25..157bd69185 100644 --- a/Marlin/src/core/language.h +++ b/Marlin/src/core/language.h @@ -199,16 +199,20 @@ #define STR_FILAMENT_CHANGE_INSERT_M108 "Insert filament and send M108" #define STR_FILAMENT_CHANGE_WAIT_M108 "Send M108 to resume" -#define STR_STOP_BLTOUCH "!! STOP called because of BLTouch error - restart with M999" -#define STR_STOP_UNHOMED "!! STOP called because of unhomed error - restart with M999" -#define STR_KILL_INACTIVE_TIME "!! KILL caused by too much inactive time - current command: " -#define STR_KILL_BUTTON "!! KILL caused by KILL button/pin" +#define STR_STOP_PRE "!! STOP called because of " +#define STR_STOP_POST " error - restart with M999" +#define STR_STOP_BLTOUCH "BLTouch" +#define STR_STOP_UNHOMED "unhomed" +#define STR_KILL_PRE "!! KILL caused by " +#define STR_KILL_INACTIVE_TIME "too much inactive time - current command: " +#define STR_KILL_BUTTON "KILL button/pin" // temperature.cpp strings -#define STR_PID_AUTOTUNE_START "PID Autotune start" -#define STR_PID_BAD_HEATER_ID "PID Autotune failed! Bad heater id" -#define STR_PID_TEMP_TOO_HIGH "PID Autotune failed! Temperature too high" -#define STR_PID_TIMEOUT "PID Autotune failed! timeout" +#define STR_PID_AUTOTUNE "PID Autotune" +#define STR_PID_AUTOTUNE_START " start" +#define STR_PID_BAD_HEATER_ID " failed! Bad heater id" +#define STR_PID_TEMP_TOO_HIGH " failed! Temperature too high" +#define STR_PID_TIMEOUT " failed! timeout" #define STR_BIAS " bias: " #define STR_D_COLON " d: " #define STR_T_MIN " min: " @@ -219,15 +223,19 @@ #define STR_KP " Kp: " #define STR_KI " Ki: " #define STR_KD " Kd: " -#define STR_PID_AUTOTUNE_FINISHED "PID Autotune finished! Put the last Kp, Ki and Kd constants from below into Configuration.h" +#define STR_PID_AUTOTUNE_FINISHED " finished! Put the last Kp, Ki and Kd constants from below into Configuration.h" #define STR_PID_DEBUG " PID_DEBUG " #define STR_PID_DEBUG_INPUT ": Input " #define STR_PID_DEBUG_OUTPUT " Output " -#define STR_PID_DEBUG_PTERM " pTerm " -#define STR_PID_DEBUG_ITERM " iTerm " -#define STR_PID_DEBUG_DTERM " dTerm " -#define STR_PID_DEBUG_CTERM " cTerm " #define STR_INVALID_EXTRUDER_NUM " - Invalid extruder number !" +#define STR_MPC_AUTOTUNE "MPC Autotune" +#define STR_MPC_AUTOTUNE_START " start for " STR_E +#define STR_MPC_AUTOTUNE_INTERRUPTED " interrupted!" +#define STR_MPC_AUTOTUNE_FINISHED " finished! Put the constants below into Configuration.h" +#define STR_MPC_COOLING_TO_AMBIENT "Cooling to ambient" +#define STR_MPC_HEATING_PAST_200 "Heating to over 200C" +#define STR_MPC_MEASURING_AMBIENT "Measuring ambient heatloss at " +#define STR_MPC_TEMPERATURE_ERROR "Temperature error" #define STR_HEATER_BED "bed" #define STR_HEATER_CHAMBER "chamber" @@ -303,6 +311,7 @@ #define STR_MATERIAL_HEATUP "Material heatup parameters" #define STR_LCD_CONTRAST "LCD Contrast" #define STR_LCD_BRIGHTNESS "LCD Brightness" +#define STR_DISPLAY_SLEEP "Display Sleep" #define STR_UI_LANGUAGE "UI Language" #define STR_Z_PROBE_OFFSET "Z-Probe Offset" #define STR_TEMPERATURE_UNITS "Temperature Units" diff --git a/Marlin/src/core/macros.h b/Marlin/src/core/macros.h index 629486d85f..09a6164568 100644 --- a/Marlin/src/core/macros.h +++ b/Marlin/src/core/macros.h @@ -82,11 +82,11 @@ #define FORCE_INLINE __attribute__((always_inline)) inline #define NO_INLINE __attribute__((noinline)) #define _UNUSED __attribute__((unused)) -#define _O0 __attribute__((optimize("O0"))) -#define _Os __attribute__((optimize("Os"))) -#define _O1 __attribute__((optimize("O1"))) -#define _O2 __attribute__((optimize("O2"))) -#define _O3 __attribute__((optimize("O3"))) +#define __O0 __attribute__((optimize("O0"))) +#define __Os __attribute__((optimize("Os"))) +#define __O1 __attribute__((optimize("O1"))) +#define __O2 __attribute__((optimize("O2"))) +#define __O3 __attribute__((optimize("O3"))) #define IS_CONSTEXPR(...) __builtin_constant_p(__VA_ARGS__) // Only valid solution with C++14. Should use std::is_constant_evaluated() in C++20 instead @@ -290,7 +290,7 @@ #define NUMERIC_SIGNED(a) (NUMERIC(a) || (a) == '-' || (a) == '+') #define DECIMAL_SIGNED(a) (DECIMAL(a) || (a) == '-' || (a) == '+') #define COUNT(a) (sizeof(a)/sizeof(*a)) -#define ZERO(a) memset(a,0,sizeof(a)) +#define ZERO(a) memset((void*)a,0,sizeof(a)) #define COPY(a,b) do{ \ static_assert(sizeof(a[0]) == sizeof(b[0]), "COPY: '" STRINGIFY(a) "' and '" STRINGIFY(b) "' types (sizes) don't match!"); \ memcpy(&a[0],&b[0],_MIN(sizeof(a),sizeof(b))); \ @@ -644,8 +644,8 @@ #define IS_PROBE(V...) SECOND(V, 0) // Get the second item passed, or 0 #define PROBE() ~, 1 // Second item will be 1 if this is passed #define _NOT_0 PROBE() -#define NOT(x) IS_PROBE(_CAT(_NOT_, x)) // NOT('0') gets '1'. Anything else gets '0'. -#define _BOOL(x) NOT(NOT(x)) // NOT('0') gets '0'. Anything else gets '1'. +#define NOT(x) IS_PROBE(_CAT(_NOT_, x)) // NOT('0') gets '1'. Anything else gets '0'. +#define _BOOL(x) NOT(NOT(x)) // _BOOL('0') gets '0'. Anything else gets '1'. #define IF_ELSE(TF) _IF_ELSE(_BOOL(TF)) #define _IF_ELSE(TF) _CAT(_IF_, TF) @@ -659,7 +659,6 @@ #define HAS_ARGS(V...) _BOOL(FIRST(_END_OF_ARGUMENTS_ V)()) #define _END_OF_ARGUMENTS_() 0 - // Simple Inline IF Macros, friendly to use in other macro definitions #define IF(O, A, B) ((O) ? (A) : (B)) #define IF_0(O, A) IF(O, A, 0) @@ -712,13 +711,22 @@ #define RREPEAT2_S(S,N,OP,V...) EVAL1024(_RREPEAT2(S,SUB##S(N),OP,V)) #define RREPEAT2(N,OP,V...) RREPEAT2_S(0,N,OP,V) -// See https://github.com/swansontec/map-macro -#define MAP_OUT -#define MAP_END(...) -#define MAP_GET_END() 0, MAP_END -#define MAP_NEXT0(test, next, ...) next MAP_OUT -#define MAP_NEXT1(test, next) MAP_NEXT0 (test, next, 0) -#define MAP_NEXT(test, next) MAP_NEXT1 (MAP_GET_END test, next) -#define MAP0(f, x, peek, ...) f(x) MAP_NEXT (peek, MAP1) (f, peek, __VA_ARGS__) -#define MAP1(f, x, peek, ...) f(x) MAP_NEXT (peek, MAP0) (f, peek, __VA_ARGS__) -#define MAP(f, ...) EVAL512 (MAP1 (f, __VA_ARGS__, (), 0)) +// Call OP(A) with each item as an argument +#define _MAP(_MAP_OP,A,V...) \ + _MAP_OP(A) \ + IF_ELSE(HAS_ARGS(V)) \ + ( DEFER2(__MAP)()(_MAP_OP,V) ) \ + ( /* Do nothing */ ) +#define __MAP() _MAP + +#define MAP(OP,V...) EVAL(_MAP(OP,V)) + +// Emit a list of OP(A) with the given items +#define _MAPLIST(_MAP_OP,A,V...) \ + _MAP_OP(A) \ + IF_ELSE(HAS_ARGS(V)) \ + ( , DEFER2(__MAPLIST)()(_MAP_OP,V) ) \ + ( /* Do nothing */ ) +#define __MAPLIST() _MAPLIST + +#define MAPLIST(OP,V...) EVAL(_MAPLIST(OP,V)) diff --git a/Marlin/src/core/multi_language.h b/Marlin/src/core/multi_language.h index a605a6f024..05a713e435 100644 --- a/Marlin/src/core/multi_language.h +++ b/Marlin/src/core/multi_language.h @@ -45,6 +45,7 @@ typedef const char Language_Str[]; // Set unused languages equal to each other so the // compiler can optimize away the conditionals. +#define LCD_LANGUAGE_1 LCD_LANGUAGE #ifndef LCD_LANGUAGE_2 #define LCD_LANGUAGE_2 LCD_LANGUAGE #endif diff --git a/Marlin/src/core/serial.cpp b/Marlin/src/core/serial.cpp index 819b06968c..727b191d04 100644 --- a/Marlin/src/core/serial.cpp +++ b/Marlin/src/core/serial.cpp @@ -30,20 +30,15 @@ uint8_t marlin_debug_flags = MARLIN_DEBUG_NONE; // Commonly-used strings in serial output -PGMSTR(NUL_STR, ""); PGMSTR(SP_P_STR, " P"); PGMSTR(SP_T_STR, " T"); -PGMSTR(X_STR, "X"); PGMSTR(Y_STR, "Y"); PGMSTR(Z_STR, "Z"); PGMSTR(E_STR, "E"); -PGMSTR(U_STR, STR_U); PGMSTR(V_STR, STR_V); PGMSTR(W_STR, STR_W); -PGMSTR(X_LBL, "X:"); PGMSTR(Y_LBL, "Y:"); PGMSTR(Z_LBL, "Z:"); PGMSTR(E_LBL, "E:"); -PGMSTR(U_LBL, STR_U ":"); PGMSTR(V_LBL, STR_V ":"); PGMSTR(W_LBL, STR_W ":"); -PGMSTR(SP_A_STR, " A"); PGMSTR(SP_B_STR, " B"); PGMSTR(SP_C_STR, " C"); -PGMSTR(SP_X_STR, " X"); PGMSTR(SP_Y_STR, " Y"); PGMSTR(SP_Z_STR, " Z"); PGMSTR(SP_E_STR, " E"); -PGMSTR(SP_X_LBL, " X:"); PGMSTR(SP_Y_LBL, " Y:"); PGMSTR(SP_Z_LBL, " Z:"); PGMSTR(SP_E_LBL, " E:"); -PGMSTR(I_STR, STR_I); PGMSTR(J_STR, STR_J); PGMSTR(K_STR, STR_K); -PGMSTR(I_LBL, STR_I ":"); PGMSTR(J_LBL, STR_J ":"); PGMSTR(K_LBL, STR_K ":"); -PGMSTR(SP_I_STR, " " STR_I); PGMSTR(SP_J_STR, " " STR_J); PGMSTR(SP_K_STR, " " STR_K); -PGMSTR(SP_U_STR, " " STR_U); PGMSTR(SP_V_STR, " " STR_V); PGMSTR(SP_W_STR, " " STR_W); -PGMSTR(SP_I_LBL, " " STR_I ":"); PGMSTR(SP_J_LBL, " " STR_J ":"); PGMSTR(SP_K_LBL, " " STR_K ":"); -PGMSTR(SP_U_LBL, " " STR_U ":"); PGMSTR(SP_V_LBL, " " STR_V ":"); PGMSTR(SP_W_LBL, " " STR_W ":"); +PGMSTR(SP_A_STR, " A"); PGMSTR(SP_B_STR, " B"); PGMSTR(SP_C_STR, " C"); +PGMSTR(SP_P_STR, " P"); PGMSTR(SP_T_STR, " T"); PGMSTR(NUL_STR, ""); + +#define _N_STR(N) PGMSTR(N##_STR, STR_##N); +#define _N_LBL(N) PGMSTR(N##_LBL, STR_##N ":"); +#define _SP_N_STR(N) PGMSTR(SP_##N##_STR, " " STR_##N); +#define _SP_N_LBL(N) PGMSTR(SP_##N##_LBL, " " STR_##N ":"); +MAP(_N_STR, LOGICAL_AXIS_NAMES); MAP(_SP_N_STR, LOGICAL_AXIS_NAMES); +MAP(_N_LBL, LOGICAL_AXIS_NAMES); MAP(_SP_N_LBL, LOGICAL_AXIS_NAMES); // Hook Meatpack if it's enabled on the first leaf #if ENABLED(MEATPACK_ON_SERIAL_PORT_1) @@ -77,8 +72,8 @@ void serial_print_P(PGM_P str) { while (const char c = pgm_read_byte(str++)) SERIAL_CHAR(c); } -void serial_echo_start() { static PGMSTR(echomagic, "echo:"); serial_print_P(echomagic); } -void serial_error_start() { static PGMSTR(errormagic, "Error:"); serial_print_P(errormagic); } +void serial_echo_start() { serial_print(F("echo:")); } +void serial_error_start() { serial_print(F("Error:")); } void serial_spaces(uint8_t count) { count *= (PROPORTIONAL_FONT_RATIO); while (count--) SERIAL_CHAR(' '); } diff --git a/Marlin/src/core/serial.h b/Marlin/src/core/serial.h index 2998fe803f..c19bc08783 100644 --- a/Marlin/src/core/serial.h +++ b/Marlin/src/core/serial.h @@ -28,14 +28,6 @@ #include "../feature/meatpack.h" #endif -// Commonly-used strings in serial output -extern const char NUL_STR[], SP_P_STR[], SP_T_STR[], - SP_A_STR[], SP_B_STR[], SP_C_STR[], - SP_X_STR[], SP_Y_STR[], SP_Z_STR[], SP_I_STR[], SP_J_STR[], SP_K_STR[], SP_U_STR[], SP_V_STR[], SP_W_STR[], SP_E_STR[], - SP_X_LBL[], SP_Y_LBL[], SP_Z_LBL[], SP_I_LBL[], SP_J_LBL[], SP_K_LBL[], SP_U_LBL[], SP_V_LBL[], SP_W_LBL[], SP_E_LBL[], - X_STR[], Y_STR[], Z_STR[], I_STR[], J_STR[], K_STR[], U_STR[], V_STR[], W_STR[], E_STR[], - X_LBL[], Y_LBL[], Z_LBL[], I_LBL[], J_LBL[], K_LBL[], U_LBL[], V_LBL[], W_LBL[], E_LBL[]; - // // Debugging flags for use by M111 // @@ -351,3 +343,32 @@ inline void print_pos(const xyz_pos_t &xyz, FSTR_P const prefix=nullptr, FSTR_P #define SERIAL_POS(SUFFIX,VAR) do { print_pos(VAR, F(" " STRINGIFY(VAR) "="), F(" : " SUFFIX "\n")); }while(0) #define SERIAL_XYZ(PREFIX,V...) do { print_pos(V, F(PREFIX)); }while(0) + +// +// Commonly-used strings in serial output +// + +#define _N_STR(N) N##_STR +#define _N_LBL(N) N##_LBL +#define _N_STR_A(N) _N_STR(N)[] +#define _N_LBL_A(N) _N_LBL(N)[] +#define _SP_N_STR(N) SP_##N##_STR +#define _SP_N_LBL(N) SP_##N##_LBL +#define _SP_N_STR_A(N) _SP_N_STR(N)[] +#define _SP_N_LBL_A(N) _SP_N_LBL(N)[] + +extern const char SP_A_STR[], SP_B_STR[], SP_C_STR[], SP_P_STR[], SP_T_STR[], NUL_STR[], + MAPLIST(_N_STR_A, LOGICAL_AXIS_NAMES), MAPLIST(_SP_N_STR_A, LOGICAL_AXIS_NAMES), + MAPLIST(_N_LBL_A, LOGICAL_AXIS_NAMES), MAPLIST(_SP_N_LBL_A, LOGICAL_AXIS_NAMES); + +PGM_P const SP_AXIS_LBL[] PROGMEM = { MAPLIST(_SP_N_LBL, LOGICAL_AXIS_NAMES) }; +PGM_P const SP_AXIS_STR[] PROGMEM = { MAPLIST(_SP_N_STR, LOGICAL_AXIS_NAMES) }; + +#undef _N_STR +#undef _N_LBL +#undef _N_STR_A +#undef _N_LBL_A +#undef _SP_N_STR +#undef _SP_N_LBL +#undef _SP_N_STR_A +#undef _SP_N_LBL_A diff --git a/Marlin/src/core/serial_hook.h b/Marlin/src/core/serial_hook.h index 9b9fa8fa38..65c553c702 100644 --- a/Marlin/src/core/serial_hook.h +++ b/Marlin/src/core/serial_hook.h @@ -43,7 +43,9 @@ public: } constexpr SerialMask(const uint8_t mask) : mask(mask) {} - constexpr SerialMask(const SerialMask & other) : mask(other.mask) {} // Can't use = default here since not all framework support this + constexpr SerialMask(const SerialMask &rs) : mask(rs.mask) {} // Can't use = default here since not all frameworks support this + + SerialMask& operator=(const SerialMask &rs) { mask = rs.mask; return *this; } static constexpr uint8_t All = 0xFF; }; @@ -298,7 +300,7 @@ struct MultiSerial : public SerialBase< MultiSerial< REPEAT(NUM_SERIAL, _S_NAME) // Build the actual serial object depending on current configuration #define Serial1Class TERN(SERIAL_RUNTIME_HOOK, RuntimeSerial, BaseSerial) #define ForwardSerial1Class TERN(SERIAL_RUNTIME_HOOK, RuntimeSerial, ForwardSerial) -#ifdef HAS_MULTI_SERIAL +#if HAS_MULTI_SERIAL #define Serial2Class ConditionalSerial #if NUM_SERIAL >= 3 #define Serial3Class ConditionalSerial diff --git a/Marlin/src/core/types.h b/Marlin/src/core/types.h index 47a126f165..335aa3a334 100644 --- a/Marlin/src/core/types.h +++ b/Marlin/src/core/types.h @@ -39,20 +39,28 @@ struct IF { typedef L type; }; #define NUM_AXIS_GANG(V...) GANG_N(NUM_AXES, V) #define NUM_AXIS_CODE(V...) CODE_N(NUM_AXES, V) #define NUM_AXIS_LIST(V...) LIST_N(NUM_AXES, V) +#define NUM_AXIS_LIST_1(V) LIST_N_1(NUM_AXES, V) #define NUM_AXIS_ARRAY(V...) { NUM_AXIS_LIST(V) } +#define NUM_AXIS_ARRAY_1(V) { NUM_AXIS_LIST_1(V) } #define NUM_AXIS_ARGS(T...) NUM_AXIS_LIST(T x, T y, T z, T i, T j, T k, T u, T v, T w) #define NUM_AXIS_ELEM(O) NUM_AXIS_LIST(O.x, O.y, O.z, O.i, O.j, O.k, O.u, O.v, O.w) #define NUM_AXIS_DEFS(T,V) NUM_AXIS_LIST(T x=V, T y=V, T z=V, T i=V, T j=V, T k=V, T u=V, T v=V, T w=V) +#define MAIN_AXIS_NAMES NUM_AXIS_LIST(X, Y, Z, I, J, K, U, V, W) +#define MAIN_AXIS_MAP(F) MAP(F, MAIN_AXIS_NAMES) +#define STR_AXES_MAIN NUM_AXIS_GANG("X", "Y", "Z", STR_I, STR_J, STR_K, STR_U, STR_V, STR_W) #define LOGICAL_AXIS_GANG(E,V...) NUM_AXIS_GANG(V) GANG_ITEM_E(E) #define LOGICAL_AXIS_CODE(E,V...) NUM_AXIS_CODE(V) CODE_ITEM_E(E) #define LOGICAL_AXIS_LIST(E,V...) NUM_AXIS_LIST(V) LIST_ITEM_E(E) +#define LOGICAL_AXIS_LIST_1(V) NUM_AXIS_LIST_1(V) LIST_ITEM_E(V) #define LOGICAL_AXIS_ARRAY(E,V...) { LOGICAL_AXIS_LIST(E,V) } +#define LOGICAL_AXIS_ARRAY_1(V) { LOGICAL_AXIS_LIST_1(V) } #define LOGICAL_AXIS_ARGS(T...) LOGICAL_AXIS_LIST(T e, T x, T y, T z, T i, T j, T k, T u, T v, T w) #define LOGICAL_AXIS_ELEM(O) LOGICAL_AXIS_LIST(O.e, O.x, O.y, O.z, O.i, O.j, O.k, O.u, O.v, O.w) #define LOGICAL_AXIS_DECL(T,V) LOGICAL_AXIS_LIST(T e=V, T x=V, T y=V, T z=V, T i=V, T j=V, T k=V, T u=V, T v=V, T w=V) - -#define LOGICAL_AXES_STRING LOGICAL_AXIS_GANG("E", "X", "Y", "Z", STR_I, STR_J, STR_K, STR_U, STR_V, STR_W) +#define LOGICAL_AXIS_NAMES LOGICAL_AXIS_LIST(E, X, Y, Z, I, J, K, U, V, W) +#define LOGICAL_AXIS_MAP(F) MAP(F, LOGICAL_AXIS_NAMES) +#define STR_AXES_LOGICAL LOGICAL_AXIS_GANG("E", "X", "Y", "Z", STR_I, STR_J, STR_K, STR_U, STR_V, STR_W) #define XYZ_GANG(V...) GANG_N(PRIMARY_LINEAR_AXES, V) #define XYZ_CODE(V...) CODE_N(PRIMARY_LINEAR_AXES, V) @@ -76,6 +84,59 @@ struct IF { typedef L type; }; #define AXIS_COLLISION(L) (AXIS4_NAME == L || AXIS5_NAME == L || AXIS6_NAME == L || AXIS7_NAME == L || AXIS8_NAME == L || AXIS9_NAME == L) +// General Flags for some number of states +template +struct Flags { + typedef typename IF<(N>8), uint16_t, uint8_t>::type bits_t; + typedef struct { bool b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1; } N8; + typedef struct { bool b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1, b8:1, b9:1, b10:1, b11:1, b12:1, b13:1, b14:1, b15:1; } N16; + union { + bits_t b; + typename IF<(N>8), N16, N8>::type flag; + }; + void reset() { b = 0; } + void set(const int n, const bool onoff) { onoff ? set(n) : clear(n); } + void set(const int n) { b |= (bits_t)_BV(n); } + void clear(const int n) { b &= ~(bits_t)_BV(n); } + bool test(const int n) const { return TEST(b, n); } + const bool operator[](const int n) { return test(n); } + const bool operator[](const int n) const { return test(n); } + int size() const { return sizeof(b); } +}; + +// Specialization for a single bool flag +template<> +struct Flags<1> { + bool b; + void reset() { b = false; } + void set(const int n, const bool onoff) { onoff ? set(n) : clear(n); } + void set(const int) { b = true; } + void clear(const int) { b = false; } + bool test(const int) const { return b; } + bool& operator[](const int) { return b; } + bool operator[](const int) const { return b; } + int size() const { return sizeof(b); } +}; + +typedef Flags<8> flags_8_t; +typedef Flags<16> flags_16_t; + +// Flags for some axis states, with per-axis aliases xyzijkuvwe +typedef struct AxisFlags { + union { + struct Flags flags; + struct { bool LOGICAL_AXIS_LIST(e:1, x:1, y:1, z:1, i:1, j:1, k:1, u:1, v:1, w:1); }; + }; + void reset() { flags.reset(); } + void set(const int n) { flags.set(n); } + void set(const int n, const bool onoff) { flags.set(n, onoff); } + void clear(const int n) { flags.clear(n); } + bool test(const int n) const { return flags.test(n); } + bool operator[](const int n) { return flags[n]; } + bool operator[](const int n) const { return flags[n]; } + int size() const { return sizeof(flags); } +} axis_flags_t; + // // Enumerated axis indices // @@ -120,7 +181,6 @@ enum AxisEnum : uint8_t { }; typedef IF<(NUM_AXIS_ENUMS > 8), uint16_t, uint8_t>::type axis_bits_t; -typedef IF<(NUM_AXES > 8), uint16_t, uint8_t>::type linear_axis_bits_t; // // Loop over axes diff --git a/Marlin/src/core/utility.cpp b/Marlin/src/core/utility.cpp index 986869aa07..363a490243 100644 --- a/Marlin/src/core/utility.cpp +++ b/Marlin/src/core/utility.cpp @@ -29,10 +29,10 @@ void safe_delay(millis_t ms) { while (ms > 50) { ms -= 50; delay(50); - thermalManager.manage_heater(); + thermalManager.task(); } delay(ms); - thermalManager.manage_heater(); // This keeps us safe if too many small safe_delay() calls are made + thermalManager.task(); // This keeps us safe if too many small safe_delay() calls are made } // A delay to provide brittle hosts time to receive bytes @@ -126,17 +126,16 @@ void safe_delay(millis_t ms) { #if ABL_PLANAR SERIAL_ECHOPGM("ABL Adjustment"); LOOP_NUM_AXES(a) { - SERIAL_CHAR(' ', AXIS_CHAR(a)); + SERIAL_ECHOPGM_P((PGM_P)pgm_read_ptr(&SP_AXIS_STR[a])); serial_offset(planner.get_axis_position_mm(AxisEnum(a)) - current_position[a]); } #else #if ENABLED(AUTO_BED_LEVELING_UBL) SERIAL_ECHOPGM("UBL Adjustment Z"); - const float rz = ubl.get_z_correction(current_position); #elif ENABLED(AUTO_BED_LEVELING_BILINEAR) SERIAL_ECHOPGM("ABL Adjustment Z"); - const float rz = bbl.get_z_correction(current_position); #endif + const float rz = bedlevel.get_z_correction(current_position); SERIAL_ECHO(ftostr43sign(rz, '+')); #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT) if (planner.z_fade_height) { @@ -156,11 +155,13 @@ void safe_delay(millis_t ms) { SERIAL_ECHOPGM("Mesh Bed Leveling"); if (planner.leveling_active) { SERIAL_ECHOLNPGM(" (enabled)"); - SERIAL_ECHOPGM("MBL Adjustment Z", ftostr43sign(mbl.get_z(current_position), '+')); + const float z_offset = bedlevel.get_z_offset(), + z_correction = bedlevel.get_z_correction(current_position); + SERIAL_ECHOPGM("MBL Adjustment Z", ftostr43sign(z_offset + z_correction, '+')); #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT) if (planner.z_fade_height) { SERIAL_ECHOPGM(" (", ftostr43sign( - mbl.get_z(current_position, planner.fade_scaling_factor_for_z(current_position.z)), '+' + z_offset + z_correction * planner.fade_scaling_factor_for_z(current_position.z), '+' )); SERIAL_CHAR(')'); } diff --git a/Marlin/src/core/utility.h b/Marlin/src/core/utility.h index b845cd0412..10c8201610 100644 --- a/Marlin/src/core/utility.h +++ b/Marlin/src/core/utility.h @@ -79,7 +79,7 @@ constexpr uint8_t ui8_to_percent(const uint8_t i) { return (int(i) * 100 + 127) // Axis names for G-code parsing, reports, etc. const xyze_char_t axis_codes LOGICAL_AXIS_ARRAY('E', 'X', 'Y', 'Z', AXIS4_NAME, AXIS5_NAME, AXIS6_NAME, AXIS7_NAME, AXIS8_NAME, AXIS9_NAME); -#if NUM_AXES <= XYZ +#if NUM_AXES <= XYZ && !HAS_EXTRUDERS #define AXIS_CHAR(A) ((char)('X' + A)) #define IAXIS_CHAR AXIS_CHAR #else diff --git a/Marlin/src/feature/adc/adc_mcp3426.cpp b/Marlin/src/feature/adc/adc_mcp3426.cpp index aaddf46821..49bb67ef6d 100644 --- a/Marlin/src/feature/adc/adc_mcp3426.cpp +++ b/Marlin/src/feature/adc/adc_mcp3426.cpp @@ -34,7 +34,7 @@ #include "adc_mcp3426.h" // Read the ADC value from MCP342X on a specific channel -int16_t MCP3426::ReadValue(uint8_t channel, uint8_t gain) { +int16_t MCP3426::ReadValue(uint8_t channel, uint8_t gain, uint8_t address) { Error = false; #if PINS_EXIST(I2C_SCL, I2C_SDA) && DISABLED(SOFT_I2C_EEPROM) @@ -44,7 +44,7 @@ int16_t MCP3426::ReadValue(uint8_t channel, uint8_t gain) { Wire.begin(); // No address joins the BUS as the master - Wire.beginTransmission(I2C_ADDRESS(MCP342X_ADC_I2C_ADDRESS)); + Wire.beginTransmission(I2C_ADDRESS(address)); // Continuous Conversion Mode, 16 bit, Channel 1, Gain x4 // 26 = 0b00011000 @@ -75,7 +75,7 @@ int16_t MCP3426::ReadValue(uint8_t channel, uint8_t gain) { uint8_t buffer[len] = {}; do { - Wire.requestFrom(I2C_ADDRESS(MCP342X_ADC_I2C_ADDRESS), len); + Wire.requestFrom(I2C_ADDRESS(address), len); if (Wire.available() != len) { Error = true; return 0; diff --git a/Marlin/src/feature/adc/adc_mcp3426.h b/Marlin/src/feature/adc/adc_mcp3426.h index 35458716b9..af48593369 100644 --- a/Marlin/src/feature/adc/adc_mcp3426.h +++ b/Marlin/src/feature/adc/adc_mcp3426.h @@ -29,12 +29,9 @@ #include #include -// Address of MCP342X chip -#define MCP342X_ADC_I2C_ADDRESS 104 - class MCP3426 { public: - int16_t ReadValue(uint8_t channel, uint8_t gain); + int16_t ReadValue(uint8_t channel, uint8_t gain, uint8_t address); bool Error; }; diff --git a/Marlin/src/feature/backlash.cpp b/Marlin/src/feature/backlash.cpp index 876d28a8fe..13e2cd99ec 100644 --- a/Marlin/src/feature/backlash.cpp +++ b/Marlin/src/feature/backlash.cpp @@ -162,32 +162,37 @@ int32_t Backlash::get_applied_steps(const AxisEnum axis) { } class Backlash::StepAdjuster { - xyz_long_t applied_steps; -public: - StepAdjuster() { - LOOP_NUM_AXES(axis) applied_steps[axis] = backlash.get_applied_steps((AxisEnum)axis); - } - ~StepAdjuster() { - // after backlash compensation parameter changes, ensure applied step count does not change - LOOP_NUM_AXES(axis) residual_error[axis] += backlash.get_applied_steps((AxisEnum)axis) - applied_steps[axis]; - } + private: + xyz_long_t applied_steps; + public: + StepAdjuster() { + LOOP_NUM_AXES(axis) applied_steps[axis] = backlash.get_applied_steps((AxisEnum)axis); + } + ~StepAdjuster() { + // after backlash compensation parameter changes, ensure applied step count does not change + LOOP_NUM_AXES(axis) residual_error[axis] += backlash.get_applied_steps((AxisEnum)axis) - applied_steps[axis]; + } }; -void Backlash::set_correction_uint8(const uint8_t v) { - StepAdjuster adjuster; - correction = v; -} +#if ENABLED(BACKLASH_GCODE) -void Backlash::set_distance_mm(const AxisEnum axis, const float v) { - StepAdjuster adjuster; - distance_mm[axis] = v; -} - -#ifdef BACKLASH_SMOOTHING_MM - void Backlash::set_smoothing_mm(const float v) { + void Backlash::set_correction_uint8(const uint8_t v) { StepAdjuster adjuster; - smoothing_mm = v; + correction = v; } + + void Backlash::set_distance_mm(const AxisEnum axis, const float v) { + StepAdjuster adjuster; + distance_mm[axis] = v; + } + + #ifdef BACKLASH_SMOOTHING_MM + void Backlash::set_smoothing_mm(const float v) { + StepAdjuster adjuster; + smoothing_mm = v; + } + #endif + #endif #if ENABLED(MEASURE_BACKLASH_WHEN_PROBING) diff --git a/Marlin/src/feature/bedlevel/abl/bbl.cpp b/Marlin/src/feature/bedlevel/abl/bbl.cpp index 9dcd669128..be0e862cc1 100644 --- a/Marlin/src/feature/bedlevel/abl/bbl.cpp +++ b/Marlin/src/feature/bedlevel/abl/bbl.cpp @@ -35,7 +35,7 @@ #include "../../../lcd/extui/ui_api.h" #endif -LevelingBilinear bbl; +LevelingBilinear bedlevel; xy_pos_t LevelingBilinear::grid_spacing, LevelingBilinear::grid_start; @@ -258,8 +258,8 @@ void LevelingBilinear::print_leveling_grid(const bed_mesh_t* _z_values /*= NULL* ); } } -#endif // ABL_BILINEAR_SUBDIVISION +#endif // ABL_BILINEAR_SUBDIVISION // Refresh after other values have been updated void LevelingBilinear::refresh_bed_level() { diff --git a/Marlin/src/feature/bedlevel/abl/bbl.h b/Marlin/src/feature/bedlevel/abl/bbl.h index 86da5aea10..c2be4fee82 100644 --- a/Marlin/src/feature/bedlevel/abl/bbl.h +++ b/Marlin/src/feature/bedlevel/abl/bbl.h @@ -24,9 +24,12 @@ #include "../../../inc/MarlinConfigPre.h" class LevelingBilinear { - static xy_pos_t grid_spacing, grid_start; - static xy_float_t grid_factor; +public: static bed_mesh_t z_values; + static xy_pos_t grid_spacing, grid_start; + +private: + static xy_float_t grid_factor; static xy_pos_t cached_rel; static xy_int8_t cached_g; @@ -53,20 +56,15 @@ public: static void print_leveling_grid(const bed_mesh_t* _z_values = NULL); static void refresh_bed_level(); static bool has_mesh() { return !!grid_spacing.x; } - static bed_mesh_t& get_z_values() { return z_values; } - static const xy_pos_t& get_grid_spacing() { return grid_spacing; } - static const xy_pos_t& get_grid_start() { return grid_start; } - static float get_mesh_x(int16_t i) { return grid_start.x + i * grid_spacing.x; } - static float get_mesh_y(int16_t j) { return grid_start.y + j * grid_spacing.y; } + static bool mesh_is_valid() { return has_mesh(); } + static float get_mesh_x(const uint8_t i) { return grid_start.x + i * grid_spacing.x; } + static float get_mesh_y(const uint8_t j) { return grid_start.y + j * grid_spacing.y; } static float get_z_correction(const xy_pos_t &raw); + static constexpr float get_z_offset() { return 0.0f; } #if IS_CARTESIAN && DISABLED(SEGMENT_LEVELED_MOVES) static void line_to_destination(const_feedRate_t scaled_fr_mm_s, uint16_t x_splits=0xFFFF, uint16_t y_splits=0xFFFF); #endif }; -extern LevelingBilinear bbl; - -#define _GET_MESH_X(I) bbl.get_mesh_x(I) -#define _GET_MESH_Y(J) bbl.get_mesh_y(J) -#define Z_VALUES_ARR bbl.get_z_values() +extern LevelingBilinear bedlevel; diff --git a/Marlin/src/feature/bedlevel/bedlevel.cpp b/Marlin/src/feature/bedlevel/bedlevel.cpp index 2405905d4e..1ca9696a3a 100644 --- a/Marlin/src/feature/bedlevel/bedlevel.cpp +++ b/Marlin/src/feature/bedlevel/bedlevel.cpp @@ -47,14 +47,11 @@ #endif bool leveling_is_valid() { - return TERN1(MESH_BED_LEVELING, mbl.has_mesh()) - && TERN1(AUTO_BED_LEVELING_BILINEAR, bbl.has_mesh()) - && TERN1(AUTO_BED_LEVELING_UBL, ubl.mesh_is_valid()); + return TERN1(HAS_MESH, bedlevel.mesh_is_valid()); } /** - * Turn bed leveling on or off, fixing the current - * position as-needed. + * Turn bed leveling on or off, correcting the current position. * * Disable: Current position = physical position * Enable: Current position = "unleveled" physical position @@ -65,24 +62,25 @@ void set_bed_leveling_enabled(const bool enable/*=true*/) { if (can_change && enable != planner.leveling_active) { + auto _report_leveling = []{ + if (DEBUGGING(LEVELING)) { + if (planner.leveling_active) + DEBUG_POS("Leveling ON", current_position); + else + DEBUG_POS("Leveling OFF", current_position); + } + }; + + _report_leveling(); planner.synchronize(); - if (planner.leveling_active) { // leveling from on to off - if (DEBUGGING(LEVELING)) DEBUG_POS("Leveling ON", current_position); - // change unleveled current_position to physical current_position without moving steppers. - planner.apply_leveling(current_position); - planner.leveling_active = false; // disable only AFTER calling apply_leveling - if (DEBUGGING(LEVELING)) DEBUG_POS("...Now OFF", current_position); - } - else { // leveling from off to on - if (DEBUGGING(LEVELING)) DEBUG_POS("Leveling OFF", current_position); - planner.leveling_active = true; // enable BEFORE calling unapply_leveling, otherwise ignored - // change physical current_position to unleveled current_position without moving steppers. - planner.unapply_leveling(current_position); - if (DEBUGGING(LEVELING)) DEBUG_POS("...Now ON", current_position); - } + // Get the corrected leveled / unleveled position + planner.apply_modifiers(current_position); // Physical position with all modifiers + planner.leveling_active ^= true; // Toggle leveling between apply and unapply + planner.unapply_modifiers(current_position); // Logical position with modifiers removed sync_plan_position(); + _report_leveling(); } } @@ -116,18 +114,9 @@ TemporaryBedLevelingState::TemporaryBedLevelingState(const bool enable) : saved( */ void reset_bed_level() { if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("reset_bed_level"); - #if ENABLED(AUTO_BED_LEVELING_UBL) - ubl.reset(); - #else - set_bed_leveling_enabled(false); - #if ENABLED(MESH_BED_LEVELING) - mbl.reset(); - #elif ENABLED(AUTO_BED_LEVELING_BILINEAR) - bbl.reset(); - #elif ABL_PLANAR - planner.bed_level_matrix.set_to_identity(); - #endif - #endif + IF_DISABLED(AUTO_BED_LEVELING_UBL, set_bed_leveling_enabled(false)); + TERN_(HAS_MESH, bedlevel.reset()); + TERN_(ABL_PLANAR, planner.bed_level_matrix.set_to_identity()); } #if EITHER(AUTO_BED_LEVELING_BILINEAR, MESH_BED_LEVELING) diff --git a/Marlin/src/feature/bedlevel/bedlevel.h b/Marlin/src/feature/bedlevel/bedlevel.h index f295da1d03..aeafec10d6 100644 --- a/Marlin/src/feature/bedlevel/bedlevel.h +++ b/Marlin/src/feature/bedlevel/bedlevel.h @@ -69,9 +69,6 @@ class TemporaryBedLevelingState { #include "mbl/mesh_bed_leveling.h" #endif - #define Z_VALUES(X,Y) Z_VALUES_ARR[X][Y] - #define _GET_MESH_POS(M) { _GET_MESH_X(M.a), _GET_MESH_Y(M.b) } - #if EITHER(AUTO_BED_LEVELING_BILINEAR, MESH_BED_LEVELING) #include @@ -92,7 +89,7 @@ class TemporaryBedLevelingState { bool valid() const { return pos.x >= 0 && pos.y >= 0; } #if ENABLED(AUTO_BED_LEVELING_UBL) xy_pos_t meshpos() { - return { ubl.mesh_index_to_xpos(pos.x), ubl.mesh_index_to_ypos(pos.y) }; + return { bedlevel.get_mesh_x(pos.x), bedlevel.get_mesh_y(pos.y) }; } #endif operator xy_int8_t&() { return pos; } diff --git a/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.cpp b/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.cpp index fbc3f2785e..193cbbf765 100644 --- a/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.cpp +++ b/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.cpp @@ -32,7 +32,7 @@ #include "../../../lcd/extui/ui_api.h" #endif - mesh_bed_leveling mbl; + mesh_bed_leveling bedlevel; float mesh_bed_leveling::z_offset, mesh_bed_leveling::z_values[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y], diff --git a/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.h b/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.h index 06fae16c21..1a8e693e81 100644 --- a/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.h +++ b/Marlin/src/feature/bedlevel/mbl/mesh_bed_leveling.h @@ -34,9 +34,6 @@ enum MeshLevelingState : char { #define MESH_X_DIST (float(MESH_MAX_X - (MESH_MIN_X)) / (GRID_MAX_CELLS_X)) #define MESH_Y_DIST (float(MESH_MAX_Y - (MESH_MIN_Y)) / (GRID_MAX_CELLS_Y)) -#define _GET_MESH_X(I) mbl.index_to_xpos[I] -#define _GET_MESH_Y(J) mbl.index_to_ypos[J] -#define Z_VALUES_ARR mbl.z_values class mesh_bed_leveling { public: @@ -56,6 +53,8 @@ public: return false; } + static bool mesh_is_valid() { return has_mesh(); } + static void set_z(const int8_t px, const int8_t py, const_float_t z) { z_values[px][py] = z; } static void zigzag(const int8_t index, int8_t &px, int8_t &py) { @@ -70,6 +69,9 @@ public: set_z(px, py, z); } + static float get_mesh_x(const uint8_t i) { return index_to_xpos[i]; } + static float get_mesh_y(const uint8_t i) { return index_to_ypos[i]; } + static int8_t cell_index_x(const_float_t x) { int8_t cx = (x - (MESH_MIN_X)) * RECIPROCAL(MESH_X_DIST); return constrain(cx, 0, GRID_MAX_CELLS_X - 1); @@ -102,12 +104,9 @@ public: return z1 + delta_a * delta_z; } - static float get_z(const xy_pos_t &pos - OPTARG(ENABLE_LEVELING_FADE_HEIGHT, const_float_t factor=1.0f) - ) { - #if DISABLED(ENABLE_LEVELING_FADE_HEIGHT) - constexpr float factor = 1.0f; - #endif + static float get_z_offset() { return z_offset; } + + static float get_z_correction(const xy_pos_t &pos) { const xy_int8_t ind = cell_indexes(pos); const float x1 = index_to_xpos[ind.x], x2 = index_to_xpos[ind.x+1], y1 = index_to_xpos[ind.y], y2 = index_to_xpos[ind.y+1], @@ -115,7 +114,7 @@ public: z2 = calc_z0(pos.x, x1, z_values[ind.x][ind.y+1], x2, z_values[ind.x+1][ind.y+1]), zf = calc_z0(pos.y, y1, z1, y2, z2); - return z_offset + zf * factor; + return zf; } #if IS_CARTESIAN && DISABLED(SEGMENT_LEVELED_MOVES) @@ -123,4 +122,4 @@ public: #endif }; -extern mesh_bed_leveling mbl; +extern mesh_bed_leveling bedlevel; diff --git a/Marlin/src/feature/bedlevel/ubl/ubl.cpp b/Marlin/src/feature/bedlevel/ubl/ubl.cpp index c162062f86..2aa50be34d 100644 --- a/Marlin/src/feature/bedlevel/ubl/ubl.cpp +++ b/Marlin/src/feature/bedlevel/ubl/ubl.cpp @@ -26,7 +26,7 @@ #include "../bedlevel.h" -unified_bed_leveling ubl; +unified_bed_leveling bedlevel; #include "../../../MarlinCore.h" #include "../../../gcode/gcode.h" diff --git a/Marlin/src/feature/bedlevel/ubl/ubl.h b/Marlin/src/feature/bedlevel/ubl/ubl.h index f117c1af65..a7103d6e18 100644 --- a/Marlin/src/feature/bedlevel/ubl/ubl.h +++ b/Marlin/src/feature/bedlevel/ubl/ubl.h @@ -70,20 +70,19 @@ private: static void move_z_with_encoder(const_float_t multiplier); static float measure_point_with_encoder(); static float measure_business_card_thickness(); - static void manually_probe_remaining_mesh(const xy_pos_t&, const_float_t , const_float_t , const bool) _O0; - static void fine_tune_mesh(const xy_pos_t &pos, const bool do_ubl_mesh_map) _O0; + static void manually_probe_remaining_mesh(const xy_pos_t&, const_float_t , const_float_t , const bool) __O0; + static void fine_tune_mesh(const xy_pos_t &pos, const bool do_ubl_mesh_map) __O0; #endif - static bool G29_parse_parameters() _O0; + static bool G29_parse_parameters() __O0; static void shift_mesh_height(); - static void probe_entire_mesh(const xy_pos_t &near, const bool do_ubl_mesh_map, const bool stow_probe, const bool do_furthest) _O0; + static void probe_entire_mesh(const xy_pos_t &near, const bool do_ubl_mesh_map, const bool stow_probe, const bool do_furthest) __O0; static void tilt_mesh_based_on_3pts(const_float_t z1, const_float_t z2, const_float_t z3); static void tilt_mesh_based_on_probed_grid(const bool do_ubl_mesh_map); static bool smart_fill_one(const uint8_t x, const uint8_t y, const int8_t xdir, const int8_t ydir); static bool smart_fill_one(const xy_uint8_t &pos, const xy_uint8_t &dir) { return smart_fill_one(pos.x, pos.y, dir.x, dir.y); } - static void smart_fill_mesh(); #if ENABLED(UBL_DEVEL_DEBUGGING) static void g29_what_command(); @@ -98,17 +97,18 @@ public: static void report_state(); static void save_ubl_active_state_and_disable(); static void restore_ubl_active_state_and_leave(); - static void display_map(const uint8_t) _O0; - static mesh_index_pair find_closest_mesh_point_of_type(const MeshPointType, const xy_pos_t&, const bool=false, MeshFlags *done_flags=nullptr) _O0; - static mesh_index_pair find_furthest_invalid_mesh_point() _O0; + static void display_map(const uint8_t) __O0; + static mesh_index_pair find_closest_mesh_point_of_type(const MeshPointType, const xy_pos_t&, const bool=false, MeshFlags *done_flags=nullptr) __O0; + static mesh_index_pair find_furthest_invalid_mesh_point() __O0; static void reset(); static void invalidate(); static void set_all_mesh_points_to_value(const_float_t value); static void adjust_mesh_to_mean(const bool cflag, const_float_t value); static bool sanity_check(); + static void smart_fill_mesh(); - static void G29() _O0; // O0 for no optimization - static void smart_fill_wlsf(const_float_t ) _O2; // O2 gives smaller code than Os on A2560 + static void G29() __O0; // O0 for no optimization + static void smart_fill_wlsf(const_float_t ) __O2; // O2 gives smaller code than Os on A2560 static int8_t storage_slot; @@ -215,7 +215,7 @@ public: return _UBL_OUTER_Z_RAISE; } - const float xratio = (rx0 - mesh_index_to_xpos(x1_i)) * RECIPROCAL(MESH_X_DIST), + const float xratio = (rx0 - get_mesh_x(x1_i)) * RECIPROCAL(MESH_X_DIST), z1 = z_values[x1_i][yi]; return z1 + xratio * (z_values[_MIN(x1_i, (GRID_MAX_POINTS_X) - 2) + 1][yi] - z1); // Don't allow x1_i+1 to be past the end of the array @@ -238,7 +238,7 @@ public: return _UBL_OUTER_Z_RAISE; } - const float yratio = (ry0 - mesh_index_to_ypos(y1_i)) * RECIPROCAL(MESH_Y_DIST), + const float yratio = (ry0 - get_mesh_y(y1_i)) * RECIPROCAL(MESH_Y_DIST), z1 = z_values[xi][y1_i]; return z1 + yratio * (z_values[xi][_MIN(y1_i, (GRID_MAX_POINTS_Y) - 2) + 1] - z1); // Don't allow y1_i+1 to be past the end of the array @@ -264,16 +264,17 @@ public: return UBL_Z_RAISE_WHEN_OFF_MESH; #endif - const uint8_t mx = _MIN(cx, (GRID_MAX_POINTS_X) - 2) + 1, my = _MIN(cy, (GRID_MAX_POINTS_Y) - 2) + 1; - const float z1 = calc_z0(rx0, mesh_index_to_xpos(cx), z_values[cx][cy], mesh_index_to_xpos(cx + 1), z_values[mx][cy]); - const float z2 = calc_z0(rx0, mesh_index_to_xpos(cx), z_values[cx][my], mesh_index_to_xpos(cx + 1), z_values[mx][my]); - float z0 = calc_z0(ry0, mesh_index_to_ypos(cy), z1, mesh_index_to_ypos(cy + 1), z2); + const uint8_t mx = _MIN(cx, (GRID_MAX_POINTS_X) - 2) + 1, my = _MIN(cy, (GRID_MAX_POINTS_Y) - 2) + 1, + x0 = get_mesh_x(cx), x1 = get_mesh_x(cx + 1); + const float z1 = calc_z0(rx0, x0, z_values[cx][cy], x1, z_values[mx][cy]), + z2 = calc_z0(rx0, x0, z_values[cx][my], x1, z_values[mx][my]); + float z0 = calc_z0(ry0, get_mesh_y(cy), z1, get_mesh_y(cy + 1), z2); - if (isnan(z0)) { // if part of the Mesh is undefined, it will show up as NAN - z0 = 0.0; // in ubl.z_values[][] and propagate through the - // calculations. If our correction is NAN, we throw it out - // because part of the Mesh is undefined and we don't have the - // information we need to complete the height correction. + if (isnan(z0)) { // If part of the Mesh is undefined, it will show up as NAN + z0 = 0.0; // in z_values[][] and propagate through the calculations. + // If our correction is NAN, we throw it out because part of + // the Mesh is undefined and we don't have the information + // needed to complete the height correction. if (DEBUGGING(MESH_ADJUST)) DEBUG_ECHOLNPGM("??? Yikes! NAN in "); } @@ -287,10 +288,12 @@ public: } static float get_z_correction(const xy_pos_t &pos) { return get_z_correction(pos.x, pos.y); } - static float mesh_index_to_xpos(const uint8_t i) { + static constexpr float get_z_offset() { return 0.0f; } + + static float get_mesh_x(const uint8_t i) { return i < (GRID_MAX_POINTS_X) ? pgm_read_float(&_mesh_index_to_xpos[i]) : MESH_MIN_X + i * (MESH_X_DIST); } - static float mesh_index_to_ypos(const uint8_t i) { + static float get_mesh_y(const uint8_t i) { return i < (GRID_MAX_POINTS_Y) ? pgm_read_float(&_mesh_index_to_ypos[i]) : MESH_MIN_Y + i * (MESH_Y_DIST); } @@ -307,11 +310,7 @@ public: }; // class unified_bed_leveling -extern unified_bed_leveling ubl; - -#define _GET_MESH_X(I) ubl.mesh_index_to_xpos(I) -#define _GET_MESH_Y(J) ubl.mesh_index_to_ypos(J) -#define Z_VALUES_ARR ubl.z_values +extern unified_bed_leveling bedlevel; // Prevent debugging propagating to other files #include "../../../core/debug_out.h" diff --git a/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp b/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp index 9d2aaf8247..a02918ff29 100644 --- a/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp +++ b/Marlin/src/feature/bedlevel/ubl/ubl_G29.cpp @@ -762,6 +762,8 @@ void unified_bed_leveling::shift_mesh_height() { probe.deploy(); // Deploy before ui.capture() to allow for PAUSE_BEFORE_DEPLOY_STOW TERN_(HAS_MARLINUI_MENU, ui.capture()); + TERN_(EXTENSIBLE_UI, ExtUI::onLevelingStart()); + TERN_(DWIN_LCD_PROUI, DWIN_LevelingStart()); save_ubl_active_state_and_disable(); // No bed level correction so only raw data is obtained uint8_t count = GRID_MAX_POINTS; @@ -783,6 +785,7 @@ void unified_bed_leveling::shift_mesh_height() { ui.quick_feedback(); ui.release(); probe.stow(); // Release UI before stow to allow for PAUSE_BEFORE_DEPLOY_STOW + TERN_(EXTENSIBLE_UI, ExtUI::onLevelingDone()); return restore_ubl_active_state_and_leave(); } #endif @@ -822,6 +825,9 @@ void unified_bed_leveling::shift_mesh_height() { constrain(nearby.x - probe.offset_xy.x, MESH_MIN_X, MESH_MAX_X), constrain(nearby.y - probe.offset_xy.y, MESH_MIN_Y, MESH_MAX_Y) ); + + TERN_(EXTENSIBLE_UI, ExtUI::onLevelingDone()); + TERN_(DWIN_LCD_PROUI, DWIN_LevelingDone()); } #endif // HAS_BED_PROBE @@ -921,6 +927,7 @@ void set_message_with_feedback(FSTR_P const fstr) { */ void unified_bed_leveling::manually_probe_remaining_mesh(const xy_pos_t &pos, const_float_t z_clearance, const_float_t thick, const bool do_ubl_mesh_map) { ui.capture(); + TERN_(EXTENSIBLE_UI, ExtUI::onLevelingStart()); save_ubl_active_state_and_disable(); // No bed level correction so only raw data is obtained do_blocking_move_to_xy_z(current_position, z_clearance); @@ -934,11 +941,7 @@ void set_message_with_feedback(FSTR_P const fstr) { // It doesn't matter if the probe can't reach the NAN location. This is a manual probe. if (!location.valid()) continue; - const xyz_pos_t ppos = { - mesh_index_to_xpos(lpos.x), - mesh_index_to_ypos(lpos.y), - z_clearance - }; + const xyz_pos_t ppos = { get_mesh_x(lpos.x), get_mesh_y(lpos.y), z_clearance }; if (!position_is_reachable(ppos)) break; // SHOULD NOT OCCUR (find_closest_mesh_point only returns reachable points) @@ -984,6 +987,8 @@ void set_message_with_feedback(FSTR_P const fstr) { restore_ubl_active_state_and_leave(); do_blocking_move_to_xy_z(pos, Z_CLEARANCE_DEPLOY_PROBE); + + TERN_(EXTENSIBLE_UI, ExtUI::onLevelingDone()); } /** @@ -1031,11 +1036,7 @@ void set_message_with_feedback(FSTR_P const fstr) { done_flags.mark(lpos); // Mark this location as 'adjusted' so a new // location is used on the next loop - const xyz_pos_t raw = { - mesh_index_to_xpos(lpos.x), - mesh_index_to_ypos(lpos.y), - Z_CLEARANCE_BETWEEN_PROBES - }; + const xyz_pos_t raw = { get_mesh_x(lpos.x), get_mesh_y(lpos.y), Z_CLEARANCE_BETWEEN_PROBES }; if (!position_is_reachable(raw)) break; // SHOULD NOT OCCUR (find_closest_mesh_point_of_type only returns reachable) @@ -1268,7 +1269,7 @@ mesh_index_pair unified_bed_leveling::find_furthest_invalid_mesh_point() { if (!isnan(z_values[i][j])) continue; // Skip valid mesh points // Skip unreachable points - if (!probe.can_reach(mesh_index_to_xpos(i), mesh_index_to_ypos(j))) + if (!probe.can_reach(get_mesh_x(i), get_mesh_y(j))) continue; found_a_NAN = true; @@ -1320,11 +1321,11 @@ mesh_index_pair unified_bed_leveling::find_furthest_invalid_mesh_point() { static bool test_func(uint8_t i, uint8_t j, void *data) { find_closest_t *d = (find_closest_t*)data; - if ( d->type == CLOSEST || d->type == (isnan(ubl.z_values[i][j]) ? INVALID : REAL) + if ( d->type == CLOSEST || d->type == (isnan(bedlevel.z_values[i][j]) ? INVALID : REAL) || (d->type == SET_IN_BITMAP && !d->done_flags->marked(i, j)) ) { // Found a Mesh Point of the specified type! - const xy_pos_t mpos = { ubl.mesh_index_to_xpos(i), ubl.mesh_index_to_ypos(j) }; + const xy_pos_t mpos = { bedlevel.get_mesh_x(i), bedlevel.get_mesh_y(j) }; // If using the probe as the reference there are some unreachable locations. // Also for round beds, there are grid points outside the bed the nozzle can't reach. @@ -1368,7 +1369,7 @@ mesh_index_pair unified_bed_leveling::find_closest_mesh_point_of_type(const Mesh || (type == SET_IN_BITMAP && !done_flags->marked(i, j)) ) { // Found a Mesh Point of the specified type! - const xy_pos_t mpos = { mesh_index_to_xpos(i), mesh_index_to_ypos(j) }; + const xy_pos_t mpos = { get_mesh_x(i), get_mesh_y(j) }; // If using the probe as the reference there are some unreachable locations. // Also for round beds, there are grid points outside the bed the nozzle can't reach. @@ -1424,10 +1425,10 @@ typedef struct { uint8_t sx, ex, sy, ey; bool yfirst; } smart_fill_info; void unified_bed_leveling::smart_fill_mesh() { static const smart_fill_info - info0 PROGMEM = { 0, GRID_MAX_POINTS_X, 0, GRID_MAX_POINTS_Y - 2, false }, // Bottom of the mesh looking up - info1 PROGMEM = { 0, GRID_MAX_POINTS_X, GRID_MAX_POINTS_Y - 1, 0, false }, // Top of the mesh looking down - info2 PROGMEM = { 0, GRID_MAX_POINTS_X - 2, 0, GRID_MAX_POINTS_Y, true }, // Left side of the mesh looking right - info3 PROGMEM = { GRID_MAX_POINTS_X - 1, 0, 0, GRID_MAX_POINTS_Y, true }; // Right side of the mesh looking left + info0 PROGMEM = { 0, GRID_MAX_POINTS_X, 0, (GRID_MAX_POINTS_Y) - 2, false }, // Bottom of the mesh looking up + info1 PROGMEM = { 0, GRID_MAX_POINTS_X, (GRID_MAX_POINTS_Y) - 1, 0, false }, // Top of the mesh looking down + info2 PROGMEM = { 0, (GRID_MAX_POINTS_X) - 2, 0, GRID_MAX_POINTS_Y, true }, // Left side of the mesh looking right + info3 PROGMEM = { (GRID_MAX_POINTS_X) - 1, 0, 0, GRID_MAX_POINTS_Y, true }; // Right side of the mesh looking left static const smart_fill_info * const info[] PROGMEM = { &info0, &info1, &info2, &info3 }; LOOP_L_N(i, COUNT(info)) { @@ -1616,9 +1617,7 @@ void unified_bed_leveling::smart_fill_mesh() { matrix_3x3 rotation = matrix_3x3::create_look_at(vector_3(lsf_results.A, lsf_results.B, 1)); GRID_LOOP(i, j) { - float mx = mesh_index_to_xpos(i), - my = mesh_index_to_ypos(j), - mz = z_values[i][j]; + float mx = get_mesh_x(i), my = get_mesh_y(j), mz = z_values[i][j]; if (DEBUGGING(LEVELING)) { DEBUG_ECHOPAIR_F("before rotation = [", mx, 7); @@ -1715,18 +1714,18 @@ void unified_bed_leveling::smart_fill_mesh() { xy_pos_t ppos; LOOP_L_N(ix, GRID_MAX_POINTS_X) { - ppos.x = mesh_index_to_xpos(ix); + ppos.x = get_mesh_x(ix); LOOP_L_N(iy, GRID_MAX_POINTS_Y) { - ppos.y = mesh_index_to_ypos(iy); + ppos.y = get_mesh_y(iy); if (isnan(z_values[ix][iy])) { // undefined mesh point at (ppos.x,ppos.y), compute weighted LSF from original valid mesh points. incremental_LSF_reset(&lsf_results); xy_pos_t rpos; LOOP_L_N(jx, GRID_MAX_POINTS_X) { - rpos.x = mesh_index_to_xpos(jx); + rpos.x = get_mesh_x(jx); LOOP_L_N(jy, GRID_MAX_POINTS_Y) { if (TEST(bitmap[jx], jy)) { - rpos.y = mesh_index_to_ypos(jy); + rpos.y = get_mesh_y(jy); const float rz = z_values[jx][jy], w = 1.0f + weight_scaled / (rpos - ppos).magnitude(); incremental_WLSF(&lsf_results, rpos, rz, w); @@ -1785,7 +1784,7 @@ void unified_bed_leveling::smart_fill_mesh() { SERIAL_ECHOPGM("X-Axis Mesh Points at: "); LOOP_L_N(i, GRID_MAX_POINTS_X) { - SERIAL_ECHO_F(LOGICAL_X_POSITION(mesh_index_to_xpos(i)), 3); + SERIAL_ECHO_F(LOGICAL_X_POSITION(get_mesh_x(i)), 3); SERIAL_ECHOPGM(" "); serial_delay(25); } @@ -1793,7 +1792,7 @@ void unified_bed_leveling::smart_fill_mesh() { SERIAL_ECHOPGM("Y-Axis Mesh Points at: "); LOOP_L_N(i, GRID_MAX_POINTS_Y) { - SERIAL_ECHO_F(LOGICAL_Y_POSITION(mesh_index_to_ypos(i)), 3); + SERIAL_ECHO_F(LOGICAL_Y_POSITION(get_mesh_y(i)), 3); SERIAL_ECHOPGM(" "); serial_delay(25); } diff --git a/Marlin/src/feature/bedlevel/ubl/ubl_motion.cpp b/Marlin/src/feature/bedlevel/ubl/ubl_motion.cpp index f7e98c9fa7..8121a0b9b5 100644 --- a/Marlin/src/feature/bedlevel/ubl/ubl_motion.cpp +++ b/Marlin/src/feature/bedlevel/ubl/ubl_motion.cpp @@ -36,8 +36,18 @@ #include "../../../MarlinCore.h" #include +//#define DEBUG_UBL_MOTION +#define DEBUG_OUT ENABLED(DEBUG_UBL_MOTION) +#include "../../../core/debug_out.h" + #if !UBL_SEGMENTED + // TODO: The first and last parts of a move might result in very short segment(s) + // after getting split on the cell boundary, so moves like that should not + // get split. This will be most common for moves that start/end near the + // corners of cells. To fix the issue, simply check if the start/end of the line + // is very close to a cell boundary in advance and don't split the line there. + void unified_bed_leveling::line_to_destination_cartesian(const_feedRate_t scaled_fr_mm_s, const uint8_t extruder) { /** * Much of the nozzle movement will be within the same cell. So we will do as little computation @@ -76,8 +86,8 @@ #endif // The distance is always MESH_X_DIST so multiply by the constant reciprocal. - const float xratio = (end.x - mesh_index_to_xpos(iend.x)) * RECIPROCAL(MESH_X_DIST), - yratio = (end.y - mesh_index_to_ypos(iend.y)) * RECIPROCAL(MESH_Y_DIST), + const float xratio = (end.x - get_mesh_x(iend.x)) * RECIPROCAL(MESH_X_DIST), + yratio = (end.y - get_mesh_y(iend.y)) * RECIPROCAL(MESH_Y_DIST), z1 = z_values[iend.x][iend.y ] + xratio * (z_values[iend.x + 1][iend.y ] - z_values[iend.x][iend.y ]), z2 = z_values[iend.x][iend.y + 1] + xratio * (z_values[iend.x + 1][iend.y + 1] - z_values[iend.x][iend.y + 1]); @@ -139,7 +149,7 @@ icell.y += ineg.y; // Line going down? Just go to the bottom. while (icell.y != iend.y + ineg.y) { icell.y += iadd.y; - const float next_mesh_line_y = mesh_index_to_ypos(icell.y); + const float next_mesh_line_y = get_mesh_y(icell.y); /** * Skip the calculations for an infinite slope. @@ -155,7 +165,7 @@ // Replace NAN corrections with 0.0 to prevent NAN propagation. if (isnan(z0)) z0 = 0.0; - dest.y = mesh_index_to_ypos(icell.y); + dest.y = get_mesh_y(icell.y); /** * Without this check, it's possible to generate a zero length move, as in the case where @@ -176,7 +186,9 @@ dest.z += z0; planner.buffer_segment(dest, scaled_fr_mm_s, extruder); - } //else printf("FIRST MOVE PRUNED "); + } + else + DEBUG_ECHOLNPGM("[ubl] skip Y segment"); } // At the final destination? Usually not, but when on a Y Mesh Line it's completed. @@ -196,7 +208,7 @@ while (icell.x != iend.x + ineg.x) { icell.x += iadd.x; - dest.x = mesh_index_to_xpos(icell.x); + dest.x = get_mesh_x(icell.x); dest.y = ratio * dest.x + c; // Calculate Y at the next X mesh line float z0 = z_correction_for_y_on_vertical_mesh_line(dest.y, icell.x, icell.y) @@ -225,7 +237,9 @@ dest.z += z0; if (!planner.buffer_segment(dest, scaled_fr_mm_s, extruder)) break; - } //else printf("FIRST MOVE PRUNED "); + } + else + DEBUG_ECHOLNPGM("[ubl] skip Y segment"); } if (xy_pos_t(current_position) != xy_pos_t(end)) @@ -245,8 +259,8 @@ while (cnt) { - const float next_mesh_line_x = mesh_index_to_xpos(icell.x + iadd.x), - next_mesh_line_y = mesh_index_to_ypos(icell.y + iadd.y); + const float next_mesh_line_x = get_mesh_x(icell.x + iadd.x), + next_mesh_line_y = get_mesh_y(icell.y + iadd.y); dest.y = ratio * next_mesh_line_x + c; // Calculate Y at the next X mesh line dest.x = (next_mesh_line_y - c) / ratio; // Calculate X at the next Y mesh line @@ -340,7 +354,7 @@ * Returns true if did NOT move, false if moved (requires current_position update). */ - bool _O2 unified_bed_leveling::line_to_destination_segmented(const_feedRate_t scaled_fr_mm_s) { + bool __O2 unified_bed_leveling::line_to_destination_segmented(const_feedRate_t scaled_fr_mm_s) { if (!position_is_reachable(destination)) // fail if moving outside reachable boundary return true; // did not move, so current_position still accurate @@ -360,11 +374,12 @@ #endif NOLESS(segments, 1U); // Must have at least one segment - const float inv_segments = 1.0f / segments, // Reciprocal to save calculation - segment_xyz_mm = SQRT(cart_xy_mm_2 + sq(total.z)) * inv_segments; // Length of each segment + const float inv_segments = 1.0f / segments; // Reciprocal to save calculation + // Add hints to help optimize the move + PlannerHints hints(SQRT(cart_xy_mm_2 + sq(total.z)) * inv_segments); // Length of each segment #if ENABLED(SCARA_FEEDRATE_SCALING) - const float inv_duration = scaled_fr_mm_s / segment_xyz_mm; + hints.inv_duration = scaled_fr_mm_s / hints.millimeters; #endif xyze_float_t diff = total * inv_segments; @@ -378,13 +393,9 @@ if (!planner.leveling_active || !planner.leveling_active_at_z(destination.z)) { while (--segments) { raw += diff; - planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, segment_xyz_mm - OPTARG(SCARA_FEEDRATE_SCALING, inv_duration) - ); + planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, hints); } - planner.buffer_line(destination, scaled_fr_mm_s, active_extruder, segment_xyz_mm - OPTARG(SCARA_FEEDRATE_SCALING, inv_duration) - ); + planner.buffer_line(destination, scaled_fr_mm_s, active_extruder, hints); return false; // Did not set current from destination } @@ -423,7 +434,7 @@ if (isnan(z_x0y1)) z_x0y1 = 0; // in order to avoid isnan tests per cell, if (isnan(z_x1y1)) z_x1y1 = 0; // thus guessing zero for undefined points - const xy_pos_t pos = { mesh_index_to_xpos(icell.x), mesh_index_to_ypos(icell.y) }; + const xy_pos_t pos = { get_mesh_x(icell.x), get_mesh_y(icell.y) }; xy_pos_t cell = raw - pos; const float z_xmy0 = (z_x1y0 - z_x0y0) * RECIPROCAL(MESH_X_DIST), // z slope per x along y0 (lower left to lower right) @@ -450,13 +461,10 @@ if (--segments == 0) raw = destination; // if this is last segment, use destination for exact const float z_cxcy = (z_cxy0 + z_cxym * cell.y) // interpolated mesh z height along cell.x at cell.y - #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT) - * fade_scaling_factor // apply fade factor to interpolated mesh height - #endif - ; + TERN_(ENABLE_LEVELING_FADE_HEIGHT, * fade_scaling_factor); // apply fade factor to interpolated height const float oldz = raw.z; raw.z += z_cxcy; - planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, segment_xyz_mm OPTARG(SCARA_FEEDRATE_SCALING, inv_duration) ); + planner.buffer_line(raw, scaled_fr_mm_s, active_extruder, hints); raw.z = oldz; if (segments == 0) // done with last segment diff --git a/Marlin/src/feature/bltouch.cpp b/Marlin/src/feature/bltouch.cpp index b1cc30bee0..10d3131aed 100644 --- a/Marlin/src/feature/bltouch.cpp +++ b/Marlin/src/feature/bltouch.cpp @@ -45,7 +45,7 @@ void stop(); bool BLTouch::command(const BLTCommand cmd, const millis_t &ms) { if (DEBUGGING(LEVELING)) SERIAL_ECHOLNPGM("BLTouch Command :", cmd); - MOVE_SERVO(Z_PROBE_SERVO_NR, cmd); + servo[Z_PROBE_SERVO_NR].move(cmd); safe_delay(_MAX(ms, (uint32_t)BLTOUCH_DELAY)); // BLTOUCH_DELAY is also the *minimum* delay return triggered(); } @@ -111,11 +111,8 @@ bool BLTouch::deploy_proc() { // Last attempt to DEPLOY if (_deploy_query_alarm()) { // The deploy might have failed or the probe is actually triggered (nozzle too low?) again - if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("BLTouch Recovery Failed"); - - SERIAL_ERROR_MSG(STR_STOP_BLTOUCH); // Tell the user something is wrong, needs action - stop(); // but it's not too bad, no need to kill, allow restart - + if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("BLTouch Deploy Failed"); + probe.probe_error_stop(); // Something is wrong, needs action, but not too bad, allow restart return true; // Tell our caller we goofed in case he cares to know } } @@ -153,12 +150,8 @@ bool BLTouch::stow_proc() { // But one more STOW will catch that // Last attempt to STOW if (_stow_query_alarm()) { // so if there is now STILL an ALARM condition: - - if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("BLTouch Recovery Failed"); - - SERIAL_ERROR_MSG(STR_STOP_BLTOUCH); // Tell the user something is wrong, needs action - stop(); // but it's not too bad, no need to kill, allow restart - + if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("BLTouch Stow Failed"); + probe.probe_error_stop(); // Something is wrong, needs action, but not too bad, allow restart return true; // Tell our caller we goofed in case he cares to know } } diff --git a/Marlin/src/feature/dac/stepper_dac.cpp b/Marlin/src/feature/dac/stepper_dac.cpp index ff730e93c6..f5664bc598 100644 --- a/Marlin/src/feature/dac/stepper_dac.cpp +++ b/Marlin/src/feature/dac/stepper_dac.cpp @@ -29,7 +29,6 @@ #if HAS_MOTOR_CURRENT_DAC #include "stepper_dac.h" -#include "../../MarlinCore.h" // for SP_X_LBL... bool dac_present = false; constexpr xyze_uint8_t dac_order = DAC_STEPPER_ORDER; @@ -60,7 +59,7 @@ int StepperDAC::init() { } void StepperDAC::set_current_value(const uint8_t channel, uint16_t val) { - if (!dac_present) return; + if (!(dac_present && channel < LOGICAL_AXES)) return; NOMORE(val, uint16_t(DAC_STEPPER_MAX)); @@ -85,13 +84,11 @@ void StepperDAC::print_values() { if (!dac_present) return; SERIAL_ECHO_MSG("Stepper current values in % (Amps):"); SERIAL_ECHO_START(); - SERIAL_ECHOPGM_P(SP_X_LBL, dac_perc(X_AXIS), PSTR(" ("), dac_amps(X_AXIS), PSTR(")")); - #if HAS_Y_AXIS - SERIAL_ECHOPGM_P(SP_Y_LBL, dac_perc(Y_AXIS), PSTR(" ("), dac_amps(Y_AXIS), PSTR(")")); - #endif - #if HAS_Z_AXIS - SERIAL_ECHOPGM_P(SP_Z_LBL, dac_perc(Z_AXIS), PSTR(" ("), dac_amps(Z_AXIS), PSTR(")")); - #endif + LOOP_LOGICAL_AXES(a) { + SERIAL_CHAR(' ', IAXIS_CHAR(a), ':'); + SERIAL_ECHO(dac_perc(a)); + SERIAL_ECHOPGM_P(PSTR(" ("), dac_amps(AxisEnum(a)), PSTR(")")); + } #if HAS_EXTRUDERS SERIAL_ECHOLNPGM_P(SP_E_LBL, dac_perc(E_AXIS), PSTR(" ("), dac_amps(E_AXIS), PSTR(")")); #endif diff --git a/Marlin/src/feature/encoder_i2c.cpp b/Marlin/src/feature/encoder_i2c.cpp index c1dbb906fd..092ce0f8b8 100644 --- a/Marlin/src/feature/encoder_i2c.cpp +++ b/Marlin/src/feature/encoder_i2c.cpp @@ -49,7 +49,7 @@ void I2CPositionEncoder::init(const uint8_t address, const AxisEnum axis) { initialized = true; - SERIAL_ECHOLNPGM("Setting up encoder on ", AS_CHAR(axis_codes[encoderAxis]), " axis, addr = ", address); + SERIAL_ECHOLNPGM("Setting up encoder on ", AS_CHAR(AXIS_CHAR(encoderAxis)), " axis, addr = ", address); position = get_position(); } @@ -67,7 +67,7 @@ void I2CPositionEncoder::update() { /* if (trusted) { //commented out as part of the note below trusted = false; - SERIAL_ECHOLNPGM("Fault detected on ", AS_CHAR(axis_codes[encoderAxis]), " axis encoder. Disengaging error correction until module is trusted again."); + SERIAL_ECHOLNPGM("Fault detected on ", AS_CHAR(AXIS_CHAR(encoderAxis)), " axis encoder. Disengaging error correction until module is trusted again."); } */ return; @@ -92,7 +92,7 @@ void I2CPositionEncoder::update() { if (millis() - lastErrorTime > I2CPE_TIME_TRUSTED) { trusted = true; - SERIAL_ECHOLNPGM("Untrusted encoder module on ", AS_CHAR(axis_codes[encoderAxis]), " axis has been fault-free for set duration, reinstating error correction."); + SERIAL_ECHOLNPGM("Untrusted encoder module on ", AS_CHAR(AXIS_CHAR(encoderAxis)), " axis has been fault-free for set duration, reinstating error correction."); //the encoder likely lost its place when the error occurred, so we'll reset and use the printer's //idea of where it the axis is to re-initialize @@ -172,7 +172,7 @@ void I2CPositionEncoder::update() { float sumP = 0; LOOP_L_N(i, I2CPE_ERR_PRST_ARRAY_SIZE) sumP += errPrst[i]; const int32_t errorP = int32_t(sumP * RECIPROCAL(I2CPE_ERR_PRST_ARRAY_SIZE)); - SERIAL_CHAR(axis_codes[encoderAxis]); + SERIAL_CHAR(AXIS_CHAR(encoderAxis)); SERIAL_ECHOLNPGM(" : CORRECT ERR ", errorP * planner.mm_per_step[encoderAxis], "mm"); babystep.add_steps(encoderAxis, -LROUND(errorP)); errPrstIdx = 0; @@ -192,7 +192,7 @@ void I2CPositionEncoder::update() { if (ABS(error) > I2CPE_ERR_CNT_THRESH * planner.settings.axis_steps_per_mm[encoderAxis]) { const millis_t ms = millis(); if (ELAPSED(ms, nextErrorCountTime)) { - SERIAL_CHAR(axis_codes[encoderAxis]); + SERIAL_CHAR(AXIS_CHAR(encoderAxis)); SERIAL_ECHOLNPGM(" : LARGE ERR ", error, "; diffSum=", diffSum); errorCount++; nextErrorCountTime = ms + I2CPE_ERR_CNT_DEBOUNCE_MS; @@ -212,7 +212,7 @@ void I2CPositionEncoder::set_homed() { homed = trusted = true; #ifdef I2CPE_DEBUG - SERIAL_CHAR(axis_codes[encoderAxis]); + SERIAL_CHAR(AXIS_CHAR(encoderAxis)); SERIAL_ECHOLNPGM(" axis encoder homed, offset of ", zeroOffset, " ticks."); #endif } @@ -223,7 +223,7 @@ void I2CPositionEncoder::set_unhomed() { homed = trusted = false; #ifdef I2CPE_DEBUG - SERIAL_CHAR(axis_codes[encoderAxis]); + SERIAL_CHAR(AXIS_CHAR(encoderAxis)); SERIAL_ECHOLNPGM(" axis encoder unhomed."); #endif } @@ -231,7 +231,7 @@ void I2CPositionEncoder::set_unhomed() { bool I2CPositionEncoder::passes_test(const bool report) { if (report) { if (H != I2CPE_MAG_SIG_GOOD) SERIAL_ECHOPGM("Warning. "); - SERIAL_CHAR(axis_codes[encoderAxis]); + SERIAL_CHAR(AXIS_CHAR(encoderAxis)); serial_ternary(H == I2CPE_MAG_SIG_BAD, F(" axis "), F("magnetic strip "), F("encoder ")); switch (H) { case I2CPE_MAG_SIG_GOOD: @@ -252,7 +252,7 @@ float I2CPositionEncoder::get_axis_error_mm(const bool report) { error = ABS(diff) > 10000 ? 0 : diff; // Huge error is a bad reading if (report) { - SERIAL_CHAR(axis_codes[encoderAxis]); + SERIAL_CHAR(AXIS_CHAR(encoderAxis)); SERIAL_ECHOLNPGM(" axis target=", target, "mm; actual=", actual, "mm; err=", error, "mm"); } @@ -262,7 +262,7 @@ float I2CPositionEncoder::get_axis_error_mm(const bool report) { int32_t I2CPositionEncoder::get_axis_error_steps(const bool report) { if (!active) { if (report) { - SERIAL_CHAR(axis_codes[encoderAxis]); + SERIAL_CHAR(AXIS_CHAR(encoderAxis)); SERIAL_ECHOLNPGM(" axis encoder not active!"); } return 0; @@ -287,7 +287,7 @@ int32_t I2CPositionEncoder::get_axis_error_steps(const bool report) { errorPrev = error; if (report) { - SERIAL_CHAR(axis_codes[encoderAxis]); + SERIAL_CHAR(AXIS_CHAR(encoderAxis)); SERIAL_ECHOLNPGM(" axis target=", target, "; actual=", encoderCountInStepperTicksScaled, "; err=", error); } @@ -657,7 +657,7 @@ void I2CPositionEncodersMgr::report_position(const int8_t idx, const bool units, else { if (noOffset) { const int32_t raw_count = encoders[idx].get_raw_count(); - SERIAL_CHAR(axis_codes[encoders[idx].get_axis()], ' '); + SERIAL_CHAR(AXIS_CHAR(encoders[idx).get_axis()], ' '); for (uint8_t j = 31; j > 0; j--) SERIAL_ECHO((bool)(0x00000001 & (raw_count >> j))); @@ -712,7 +712,7 @@ void I2CPositionEncodersMgr::change_module_address(const uint8_t oldaddr, const // and enable it (it will likely have failed initialization on power-up, before the address change). const int8_t idx = idx_from_addr(newaddr); if (idx >= 0 && !encoders[idx].get_active()) { - SERIAL_CHAR(axis_codes[encoders[idx].get_axis()]); + SERIAL_CHAR(AXIS_CHAR(encoders[idx).get_axis()]); SERIAL_ECHOLNPGM(" axis encoder was not detected on printer startup. Trying again."); encoders[idx].set_active(encoders[idx].passes_test(true)); } @@ -814,7 +814,7 @@ void I2CPositionEncodersMgr::M860() { if (I2CPE_idx == 0xFF) { LOOP_LOGICAL_AXES(i) { - if (!I2CPE_anyaxis || parser.seen_test(axis_codes[i])) { + if (!I2CPE_anyaxis || parser.seen_test(AXIS_CHAR(i))) { const uint8_t idx = idx_from_axis(AxisEnum(i)); if ((int8_t)idx >= 0) report_position(idx, hasU, hasO); } @@ -841,7 +841,7 @@ void I2CPositionEncodersMgr::M861() { if (I2CPE_idx == 0xFF) { LOOP_LOGICAL_AXES(i) { - if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) { + if (!I2CPE_anyaxis || parser.seen(AXIS_CHAR(i))) { const uint8_t idx = idx_from_axis(AxisEnum(i)); if ((int8_t)idx >= 0) report_status(idx); } @@ -869,7 +869,7 @@ void I2CPositionEncodersMgr::M862() { if (I2CPE_idx == 0xFF) { LOOP_LOGICAL_AXES(i) { - if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) { + if (!I2CPE_anyaxis || parser.seen(AXIS_CHAR(i))) { const uint8_t idx = idx_from_axis(AxisEnum(i)); if ((int8_t)idx >= 0) test_axis(idx); } @@ -900,7 +900,7 @@ void I2CPositionEncodersMgr::M863() { if (I2CPE_idx == 0xFF) { LOOP_LOGICAL_AXES(i) { - if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) { + if (!I2CPE_anyaxis || parser.seen(AXIS_CHAR(i))) { const uint8_t idx = idx_from_axis(AxisEnum(i)); if ((int8_t)idx >= 0) calibrate_steps_mm(idx, iterations); } @@ -976,7 +976,7 @@ void I2CPositionEncodersMgr::M865() { if (!I2CPE_addr) { LOOP_LOGICAL_AXES(i) { - if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) { + if (!I2CPE_anyaxis || parser.seen(AXIS_CHAR(i))) { const uint8_t idx = idx_from_axis(AxisEnum(i)); if ((int8_t)idx >= 0) report_module_firmware(encoders[idx].get_address()); } @@ -1007,7 +1007,7 @@ void I2CPositionEncodersMgr::M866() { if (I2CPE_idx == 0xFF) { LOOP_LOGICAL_AXES(i) { - if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) { + if (!I2CPE_anyaxis || parser.seen(AXIS_CHAR(i))) { const uint8_t idx = idx_from_axis(AxisEnum(i)); if ((int8_t)idx >= 0) { if (hasR) @@ -1045,7 +1045,7 @@ void I2CPositionEncodersMgr::M867() { if (I2CPE_idx == 0xFF) { LOOP_LOGICAL_AXES(i) { - if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) { + if (!I2CPE_anyaxis || parser.seen(AXIS_CHAR(i))) { const uint8_t idx = idx_from_axis(AxisEnum(i)); if ((int8_t)idx >= 0) { const bool ena = onoff == -1 ? !encoders[I2CPE_idx].get_ec_enabled() : !!onoff; @@ -1081,7 +1081,7 @@ void I2CPositionEncodersMgr::M868() { if (I2CPE_idx == 0xFF) { LOOP_LOGICAL_AXES(i) { - if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) { + if (!I2CPE_anyaxis || parser.seen(AXIS_CHAR(i))) { const uint8_t idx = idx_from_axis(AxisEnum(i)); if ((int8_t)idx >= 0) { if (newThreshold != -9999) @@ -1115,7 +1115,7 @@ void I2CPositionEncodersMgr::M869() { if (I2CPE_idx == 0xFF) { LOOP_LOGICAL_AXES(i) { - if (!I2CPE_anyaxis || parser.seen(axis_codes[i])) { + if (!I2CPE_anyaxis || parser.seen(AXIS_CHAR(i))) { const uint8_t idx = idx_from_axis(AxisEnum(i)); if ((int8_t)idx >= 0) report_error(idx); } diff --git a/Marlin/src/feature/encoder_i2c.h b/Marlin/src/feature/encoder_i2c.h index 50fb27a135..f25fe2ea6b 100644 --- a/Marlin/src/feature/encoder_i2c.h +++ b/Marlin/src/feature/encoder_i2c.h @@ -261,32 +261,32 @@ class I2CPositionEncodersMgr { static void report_error_count(const int8_t idx, const AxisEnum axis) { CHECK_IDX(); - SERIAL_ECHOLNPGM("Error count on ", AS_CHAR(axis_codes[axis]), " axis is ", encoders[idx].get_error_count()); + SERIAL_ECHOLNPGM("Error count on ", AS_CHAR(AXIS_CHAR(axis)), " axis is ", encoders[idx].get_error_count()); } static void reset_error_count(const int8_t idx, const AxisEnum axis) { CHECK_IDX(); encoders[idx].set_error_count(0); - SERIAL_ECHOLNPGM("Error count on ", AS_CHAR(axis_codes[axis]), " axis has been reset."); + SERIAL_ECHOLNPGM("Error count on ", AS_CHAR(AXIS_CHAR(axis)), " axis has been reset."); } static void enable_ec(const int8_t idx, const bool enabled, const AxisEnum axis) { CHECK_IDX(); encoders[idx].set_ec_enabled(enabled); - SERIAL_ECHOPGM("Error correction on ", AS_CHAR(axis_codes[axis])); + SERIAL_ECHOPGM("Error correction on ", AS_CHAR(AXIS_CHAR(axis))); SERIAL_ECHO_TERNARY(encoders[idx].get_ec_enabled(), " axis is ", "en", "dis", "abled.\n"); } static void set_ec_threshold(const int8_t idx, const float newThreshold, const AxisEnum axis) { CHECK_IDX(); encoders[idx].set_ec_threshold(newThreshold); - SERIAL_ECHOLNPGM("Error correct threshold for ", AS_CHAR(axis_codes[axis]), " axis set to ", newThreshold, "mm."); + SERIAL_ECHOLNPGM("Error correct threshold for ", AS_CHAR(AXIS_CHAR(axis)), " axis set to ", newThreshold, "mm."); } static void get_ec_threshold(const int8_t idx, const AxisEnum axis) { CHECK_IDX(); const float threshold = encoders[idx].get_ec_threshold(); - SERIAL_ECHOLNPGM("Error correct threshold for ", AS_CHAR(axis_codes[axis]), " axis is ", threshold, "mm."); + SERIAL_ECHOLNPGM("Error correct threshold for ", AS_CHAR(AXIS_CHAR(axis)), " axis is ", threshold, "mm."); } static int8_t idx_from_axis(const AxisEnum axis) { diff --git a/Marlin/src/feature/fancheck.cpp b/Marlin/src/feature/fancheck.cpp index 1b47fadecc..126b79b0a4 100644 --- a/Marlin/src/feature/fancheck.cpp +++ b/Marlin/src/feature/fancheck.cpp @@ -34,7 +34,7 @@ #if HAS_AUTO_FAN && EXTRUDER_AUTO_FAN_SPEED != 255 && DISABLED(FOURWIRES_FANS) bool FanCheck::measuring = false; #endif -bool FanCheck::tacho_state[TACHO_COUNT]; +Flags FanCheck::tacho_state; uint16_t FanCheck::edge_counter[TACHO_COUNT]; uint8_t FanCheck::rps[TACHO_COUNT]; FanCheck::TachoError FanCheck::error = FanCheck::TachoError::NONE; @@ -103,7 +103,7 @@ void FanCheck::update_tachometers() { if (status != tacho_state[f]) { if (measuring) ++edge_counter[f]; - tacho_state[f] = status; + tacho_state.set(f, status); } } } diff --git a/Marlin/src/feature/fancheck.h b/Marlin/src/feature/fancheck.h index c8665a0e96..b13a34fb19 100644 --- a/Marlin/src/feature/fancheck.h +++ b/Marlin/src/feature/fancheck.h @@ -51,7 +51,7 @@ class FanCheck { #else static constexpr bool measuring = true; #endif - static bool tacho_state[TACHO_COUNT]; + static Flags tacho_state; static uint16_t edge_counter[TACHO_COUNT]; static uint8_t rps[TACHO_COUNT]; static TachoError error; diff --git a/Marlin/src/feature/fwretract.cpp b/Marlin/src/feature/fwretract.cpp index bf47a6b2d5..172c97accd 100644 --- a/Marlin/src/feature/fwretract.cpp +++ b/Marlin/src/feature/fwretract.cpp @@ -45,7 +45,7 @@ FWRetract fwretract; // Single instance - this calls the constructor // private: #if HAS_MULTI_EXTRUDER - bool FWRetract::retracted_swap[EXTRUDERS]; // Which extruders are swap-retracted + Flags FWRetract::retracted_swap; // Which extruders are swap-retracted #endif // public: @@ -56,7 +56,7 @@ fwretract_settings_t FWRetract::settings; // M207 S F Z W, M208 S F bool FWRetract::autoretract_enabled; // M209 S - Autoretract switch #endif -bool FWRetract::retracted[EXTRUDERS]; // Which extruders are currently retracted +Flags FWRetract::retracted; // Which extruders are currently retracted float FWRetract::current_retract[EXTRUDERS], // Retract value used by planner FWRetract::current_hop; @@ -73,9 +73,9 @@ void FWRetract::reset() { settings.swap_retract_recover_feedrate_mm_s = RETRACT_RECOVER_FEEDRATE_SWAP; current_hop = 0.0; + retracted.reset(); EXTRUDER_LOOP() { - retracted[e] = false; - E_TERN_(retracted_swap[e] = false); + E_TERN_(retracted_swap.clear(e)); current_retract[e] = 0.0; } } @@ -173,11 +173,11 @@ void FWRetract::retract(const bool retracting E_OPTARG(bool swapping/*=false*/)) TERN_(RETRACT_SYNC_MIXING, mixer.T(old_mixing_tool)); // Restore original mixing tool - retracted[active_extruder] = retracting; // Active extruder now retracted / recovered + retracted.set(active_extruder, retracting); // Active extruder now retracted / recovered // If swap retract/recover update the retracted_swap flag too #if HAS_MULTI_EXTRUDER - if (swapping) retracted_swap[active_extruder] = retracting; + if (swapping) retracted_swap.set(active_extruder, retracting); #endif /* // debugging diff --git a/Marlin/src/feature/fwretract.h b/Marlin/src/feature/fwretract.h index 081ec44c05..db2a62c8d4 100644 --- a/Marlin/src/feature/fwretract.h +++ b/Marlin/src/feature/fwretract.h @@ -43,7 +43,7 @@ typedef struct { class FWRetract { private: #if HAS_MULTI_EXTRUDER - static bool retracted_swap[EXTRUDERS]; // Which extruders are swap-retracted + static Flags retracted_swap; // Which extruders are swap-retracted #endif public: @@ -55,7 +55,7 @@ public: static constexpr bool autoretract_enabled = false; #endif - static bool retracted[EXTRUDERS]; // Which extruders are currently retracted + static Flags retracted; // Which extruders are currently retracted static float current_retract[EXTRUDERS], // Retract value used by planner current_hop; // Hop value used by planner @@ -63,9 +63,7 @@ public: static void reset(); - static void refresh_autoretract() { - EXTRUDER_LOOP() retracted[e] = false; - } + static void refresh_autoretract() { retracted.reset(); } static void enable_autoretract(const bool enable) { #if ENABLED(FWRETRACT_AUTORETRACT) diff --git a/Marlin/src/feature/joystick.cpp b/Marlin/src/feature/joystick.cpp index daa642d32e..acab5d7437 100644 --- a/Marlin/src/feature/joystick.cpp +++ b/Marlin/src/feature/joystick.cpp @@ -172,8 +172,9 @@ Joystick joystick; current_position += move_dist; apply_motion_limits(current_position); const float length = sqrt(hypot2); + PlannerHints hints(length); injecting_now = true; - planner.buffer_line(current_position, length / seg_time, active_extruder, length); + planner.buffer_line(current_position, length / seg_time, active_extruder, hints); injecting_now = false; } } diff --git a/Marlin/src/feature/leds/leds.h b/Marlin/src/feature/leds/leds.h index bce9052424..8649dd014f 100644 --- a/Marlin/src/feature/leds/leds.h +++ b/Marlin/src/feature/leds/leds.h @@ -54,6 +54,8 @@ typedef struct LEDColor { OPTARG(NEOPIXEL_LED, i(NEOPIXEL_BRIGHTNESS)) {} + LEDColor(const LEDColor&) = default; + LEDColor(uint8_t r, uint8_t g, uint8_t b OPTARG(HAS_WHITE_LED, uint8_t w=0) OPTARG(NEOPIXEL_LED, uint8_t i=NEOPIXEL_BRIGHTNESS)) : r(r), g(g), b(b) OPTARG(HAS_WHITE_LED, w(w)) OPTARG(NEOPIXEL_LED, i(i)) {} @@ -68,11 +70,6 @@ typedef struct LEDColor { return *this; } - LEDColor& operator=(const LEDColor &right) { - if (this != &right) memcpy(this, &right, sizeof(LEDColor)); - return *this; - } - bool operator==(const LEDColor &right) { if (this == &right) return true; return 0 == memcmp(this, &right, sizeof(LEDColor)); diff --git a/Marlin/src/feature/max7219.cpp b/Marlin/src/feature/max7219.cpp index 474933aa19..285a86ca63 100644 --- a/Marlin/src/feature/max7219.cpp +++ b/Marlin/src/feature/max7219.cpp @@ -52,6 +52,7 @@ #define HAS_SIDE_BY_SIDE 1 #endif +#define _ROT ((MAX7219_ROTATE + 360) % 360) #if _ROT == 0 || _ROT == 180 #define MAX7219_X_LEDS TERN(HAS_SIDE_BY_SIDE, 8, MAX7219_LINES) #define MAX7219_Y_LEDS TERN(HAS_SIDE_BY_SIDE, MAX7219_LINES, 8) @@ -62,6 +63,15 @@ #error "MAX7219_ROTATE must be a multiple of +/- 90°." #endif +#ifdef MAX7219_DEBUG_PROFILE + CodeProfiler::Mode CodeProfiler::mode = ACCUMULATE_AVERAGE; + uint8_t CodeProfiler::instance_count = 0; + uint32_t CodeProfiler::last_calc_time = micros(); + uint8_t CodeProfiler::time_fraction = 0; + uint32_t CodeProfiler::total_time = 0; + uint16_t CodeProfiler::call_count = 0; +#endif + Max7219 max7219; uint8_t Max7219::led_line[MAX7219_LINES]; // = { 0 }; @@ -69,7 +79,7 @@ uint8_t Max7219::suspended; // = 0; #define LINE_REG(Q) (max7219_reg_digit0 + ((Q) & 0x7)) -#if _ROT == 0 || _ROT == 270 +#if (_ROT == 0 || _ROT == 270) == DISABLED(MAX7219_REVERSE_EACH) #define _LED_BIT(Q) (7 - ((Q) & 0x7)) #else #define _LED_BIT(Q) ((Q) & 0x7) @@ -266,26 +276,27 @@ void Max7219::set(const uint8_t line, const uint8_t bits) { #endif // MAX7219_NUMERIC // Modify a single LED bit and send the changed line -void Max7219::led_set(const uint8_t x, const uint8_t y, const bool on) { +void Max7219::led_set(const uint8_t x, const uint8_t y, const bool on, uint8_t * const rcm/*=nullptr*/) { if (x >= MAX7219_X_LEDS || y >= MAX7219_Y_LEDS) return error(F("led_set"), x, y); if (BIT_7219(x, y) == on) return; XOR_7219(x, y); refresh_unit_line(LED_IND(x, y)); + if (rcm != nullptr) *rcm |= _BV(LED_IND(x, y) & 0x07); } -void Max7219::led_on(const uint8_t x, const uint8_t y) { +void Max7219::led_on(const uint8_t x, const uint8_t y, uint8_t * const rcm/*=nullptr*/) { if (x >= MAX7219_X_LEDS || y >= MAX7219_Y_LEDS) return error(F("led_on"), x, y); - led_set(x, y, true); + led_set(x, y, true, rcm); } -void Max7219::led_off(const uint8_t x, const uint8_t y) { +void Max7219::led_off(const uint8_t x, const uint8_t y, uint8_t * const rcm/*=nullptr*/) { if (x >= MAX7219_X_LEDS || y >= MAX7219_Y_LEDS) return error(F("led_off"), x, y); - led_set(x, y, false); + led_set(x, y, false, rcm); } -void Max7219::led_toggle(const uint8_t x, const uint8_t y) { +void Max7219::led_toggle(const uint8_t x, const uint8_t y, uint8_t * const rcm/*=nullptr*/) { if (x >= MAX7219_X_LEDS || y >= MAX7219_Y_LEDS) return error(F("led_toggle"), x, y); - led_set(x, y, !BIT_7219(x, y)); + led_set(x, y, !BIT_7219(x, y), rcm); } void Max7219::send_row(const uint8_t row) { @@ -448,7 +459,7 @@ void Max7219::register_setup() { pulse_load(); // Tell the chips to load the clocked out data } -#ifdef MAX7219_INIT_TEST +#if MAX7219_INIT_TEST uint8_t test_mode = 0; millis_t next_patt_ms; @@ -536,13 +547,9 @@ void Max7219::init() { register_setup(); - LOOP_LE_N(i, 7) { // Empty registers to turn all LEDs off - led_line[i] = 0x00; - send(max7219_reg_digit0 + i, 0); - pulse_load(); // Tell the chips to load the clocked out data - } + clear(); - #ifdef MAX7219_INIT_TEST + #if MAX7219_INIT_TEST start_test_pattern(); #endif } @@ -554,41 +561,55 @@ void Max7219::init() { */ // Apply changes to update a marker -void Max7219::mark16(const uint8_t pos, const uint8_t v1, const uint8_t v2) { +void Max7219::mark16(const uint8_t pos, const uint8_t v1, const uint8_t v2, uint8_t * const rcm/*=nullptr*/) { #if MAX7219_X_LEDS > 8 // At least 16 LEDs on the X-Axis. Use single line. - led_off(v1 & 0xF, pos); - led_on(v2 & 0xF, pos); + led_off(v1 & 0xF, pos, rcm); + led_on(v2 & 0xF, pos, rcm); #elif MAX7219_Y_LEDS > 8 // At least 16 LEDs on the Y-Axis. Use a single column. - led_off(pos, v1 & 0xF); - led_on(pos, v2 & 0xF); + led_off(pos, v1 & 0xF, rcm); + led_on(pos, v2 & 0xF, rcm); #else // Single 8x8 LED matrix. Use two lines to get 16 LEDs. - led_off(v1 & 0x7, pos + (v1 >= 8)); - led_on(v2 & 0x7, pos + (v2 >= 8)); + led_off(v1 & 0x7, pos + (v1 >= 8), rcm); + led_on(v2 & 0x7, pos + (v2 >= 8), rcm); #endif } // Apply changes to update a tail-to-head range -void Max7219::range16(const uint8_t y, const uint8_t ot, const uint8_t nt, const uint8_t oh, const uint8_t nh) { +void Max7219::range16(const uint8_t y, const uint8_t ot, const uint8_t nt, const uint8_t oh, + const uint8_t nh, uint8_t * const rcm/*=nullptr*/) { #if MAX7219_X_LEDS > 8 // At least 16 LEDs on the X-Axis. Use single line. if (ot != nt) for (uint8_t n = ot & 0xF; n != (nt & 0xF) && n != (nh & 0xF); n = (n + 1) & 0xF) - led_off(n & 0xF, y); + led_off(n & 0xF, y, rcm); if (oh != nh) for (uint8_t n = (oh + 1) & 0xF; n != ((nh + 1) & 0xF); n = (n + 1) & 0xF) - led_on(n & 0xF, y); + led_on(n & 0xF, y, rcm); #elif MAX7219_Y_LEDS > 8 // At least 16 LEDs on the Y-Axis. Use a single column. if (ot != nt) for (uint8_t n = ot & 0xF; n != (nt & 0xF) && n != (nh & 0xF); n = (n + 1) & 0xF) - led_off(y, n & 0xF); + led_off(y, n & 0xF, rcm); if (oh != nh) for (uint8_t n = (oh + 1) & 0xF; n != ((nh + 1) & 0xF); n = (n + 1) & 0xF) - led_on(y, n & 0xF); + led_on(y, n & 0xF, rcm); #else // Single 8x8 LED matrix. Use two lines to get 16 LEDs. if (ot != nt) for (uint8_t n = ot & 0xF; n != (nt & 0xF) && n != (nh & 0xF); n = (n + 1) & 0xF) - led_off(n & 0x7, y + (n >= 8)); + led_off(n & 0x7, y + (n >= 8), rcm); if (oh != nh) for (uint8_t n = (oh + 1) & 0xF; n != ((nh + 1) & 0xF); n = (n + 1) & 0xF) - led_on(n & 0x7, y + (n >= 8)); + led_on(n & 0x7, y + (n >= 8), rcm); #endif } // Apply changes to update a quantity -void Max7219::quantity16(const uint8_t pos, const uint8_t ov, const uint8_t nv) { +void Max7219::quantity(const uint8_t pos, const uint8_t ov, const uint8_t nv, uint8_t * const rcm/*=nullptr*/) { + for (uint8_t i = _MIN(nv, ov); i < _MAX(nv, ov); i++) + led_set( + #if MAX7219_X_LEDS >= MAX7219_Y_LEDS + i, pos // Single matrix or multiple matrices in Landscape + #else + pos, i // Multiple matrices in Portrait + #endif + , nv >= ov + , rcm + ); +} + +void Max7219::quantity16(const uint8_t pos, const uint8_t ov, const uint8_t nv, uint8_t * const rcm/*=nullptr*/) { for (uint8_t i = _MIN(nv, ov); i < _MAX(nv, ov); i++) led_set( #if MAX7219_X_LEDS > 8 // At least 16 LEDs on the X-Axis. Use single line. @@ -599,6 +620,7 @@ void Max7219::quantity16(const uint8_t pos, const uint8_t ov, const uint8_t nv) i >> 1, pos + (i & 1) #endif , nv >= ov + , rcm ); } @@ -636,16 +658,20 @@ void Max7219::idle_tasks() { register_setup(); } - #ifdef MAX7219_INIT_TEST + #if MAX7219_INIT_TEST if (test_mode) { run_test_pattern(); return; } #endif + // suspend updates and record which lines have changed for batching later + suspended++; + uint8_t row_change_mask = 0x00; + #if ENABLED(MAX7219_DEBUG_PRINTER_ALIVE) if (do_blink) { - led_toggle(MAX7219_X_LEDS - 1, MAX7219_Y_LEDS - 1); + led_toggle(MAX7219_X_LEDS - 1, MAX7219_Y_LEDS - 1, &row_change_mask); next_blink = ms + 1000; } #endif @@ -655,7 +681,7 @@ void Max7219::idle_tasks() { static int16_t last_head_cnt = 0xF, last_tail_cnt = 0xF; if (last_head_cnt != head || last_tail_cnt != tail) { - range16(MAX7219_DEBUG_PLANNER_HEAD, last_tail_cnt, tail, last_head_cnt, head); + range16(MAX7219_DEBUG_PLANNER_HEAD, last_tail_cnt, tail, last_head_cnt, head, &row_change_mask); last_head_cnt = head; last_tail_cnt = tail; } @@ -665,7 +691,7 @@ void Max7219::idle_tasks() { #ifdef MAX7219_DEBUG_PLANNER_HEAD static int16_t last_head_cnt = 0x1; if (last_head_cnt != head) { - mark16(MAX7219_DEBUG_PLANNER_HEAD, last_head_cnt, head); + mark16(MAX7219_DEBUG_PLANNER_HEAD, last_head_cnt, head, &row_change_mask); last_head_cnt = head; } #endif @@ -673,7 +699,7 @@ void Max7219::idle_tasks() { #ifdef MAX7219_DEBUG_PLANNER_TAIL static int16_t last_tail_cnt = 0x1; if (last_tail_cnt != tail) { - mark16(MAX7219_DEBUG_PLANNER_TAIL, last_tail_cnt, tail); + mark16(MAX7219_DEBUG_PLANNER_TAIL, last_tail_cnt, tail, &row_change_mask); last_tail_cnt = tail; } #endif @@ -684,11 +710,26 @@ void Max7219::idle_tasks() { static int16_t last_depth = 0; const int16_t current_depth = (head - tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1) & 0xF; if (current_depth != last_depth) { - quantity16(MAX7219_DEBUG_PLANNER_QUEUE, last_depth, current_depth); + quantity16(MAX7219_DEBUG_PLANNER_QUEUE, last_depth, current_depth, &row_change_mask); last_depth = current_depth; } #endif + #ifdef MAX7219_DEBUG_PROFILE + static uint8_t last_time_fraction = 0; + const uint8_t current_time_fraction = (uint16_t(CodeProfiler::get_time_fraction()) * MAX7219_NUMBER_UNITS + 8) / 16; + if (current_time_fraction != last_time_fraction) { + quantity(MAX7219_DEBUG_PROFILE, last_time_fraction, current_time_fraction, &row_change_mask); + last_time_fraction = current_time_fraction; + } + #endif + + // batch line updates + suspended--; + if (!suspended) + LOOP_L_N(i, 8) if (row_change_mask & _BV(i)) + refresh_line(i); + // After resume() automatically do a refresh() if (suspended == 0x80) { suspended = 0; diff --git a/Marlin/src/feature/max7219.h b/Marlin/src/feature/max7219.h index 809bda6d4b..a6b110fdf4 100644 --- a/Marlin/src/feature/max7219.h +++ b/Marlin/src/feature/max7219.h @@ -47,7 +47,6 @@ #ifndef MAX7219_ROTATE #define MAX7219_ROTATE 0 #endif -#define _ROT ((MAX7219_ROTATE + 360) % 360) #ifndef MAX7219_NUMBER_UNITS #define MAX7219_NUMBER_UNITS 1 @@ -73,6 +72,67 @@ #define max7219_reg_shutdown 0x0C #define max7219_reg_displayTest 0x0F +#ifdef MAX7219_DEBUG_PROFILE + // This class sums up the amount of time for which its instances exist. + // By default there is one instantiated for the duration of the idle() + // function. But an instance can be created in any code block to measure + // the time spent from the point of instantiation until the CPU leaves + // block. Be careful about having multiple instances of CodeProfiler as + // it does not guard against double counting. In general mixing ISR and + // non-ISR use will require critical sections but note that mode setting + // is atomic so the total or average times can safely be read if you set + // mode to FREEZE first. + class CodeProfiler { + public: + enum Mode : uint8_t { ACCUMULATE_AVERAGE, ACCUMULATE_TOTAL, FREEZE }; + + private: + static Mode mode; + static uint8_t instance_count; + static uint32_t last_calc_time; + static uint32_t total_time; + static uint8_t time_fraction; + static uint16_t call_count; + + uint32_t start_time; + + public: + CodeProfiler() : start_time(micros()) { instance_count++; } + ~CodeProfiler() { + instance_count--; + if (mode == FREEZE) return; + + call_count++; + + const uint32_t now = micros(); + total_time += now - start_time; + + if (mode == ACCUMULATE_TOTAL) return; + + // update time_fraction every hundred milliseconds + if (instance_count == 0 && ELAPSED(now, last_calc_time + 100000)) { + time_fraction = total_time * 128 / (now - last_calc_time); + last_calc_time = now; + total_time = 0; + } + } + + static void set_mode(Mode _mode) { mode = _mode; } + static void reset() { + time_fraction = 0; + last_calc_time = micros(); + total_time = 0; + call_count = 0; + } + // returns fraction of total time which was measured, scaled from 0 to 128 + static uint8_t get_time_fraction() { return time_fraction; } + // returns total time in microseconds + static uint32_t get_total_time() { return total_time; } + + static uint16_t get_call_count() { return call_count; } + }; +#endif + class Max7219 { public: static uint8_t led_line[MAX7219_LINES]; @@ -110,10 +170,10 @@ public: #endif // Set a single LED by XY coordinate - static void led_set(const uint8_t x, const uint8_t y, const bool on); - static void led_on(const uint8_t x, const uint8_t y); - static void led_off(const uint8_t x, const uint8_t y); - static void led_toggle(const uint8_t x, const uint8_t y); + static void led_set(const uint8_t x, const uint8_t y, const bool on, uint8_t * const rcm=nullptr); + static void led_on(const uint8_t x, const uint8_t y, uint8_t * const rcm=nullptr); + static void led_off(const uint8_t x, const uint8_t y, uint8_t * const rcm=nullptr); + static void led_toggle(const uint8_t x, const uint8_t y, uint8_t * const rcm=nullptr); // Set all LEDs in a single column static void set_column(const uint8_t col, const uint32_t val); @@ -147,11 +207,12 @@ private: static void set(const uint8_t line, const uint8_t bits); static void send_row(const uint8_t row); static void send_column(const uint8_t col); - static void mark16(const uint8_t y, const uint8_t v1, const uint8_t v2); - static void range16(const uint8_t y, const uint8_t ot, const uint8_t nt, const uint8_t oh, const uint8_t nh); - static void quantity16(const uint8_t y, const uint8_t ov, const uint8_t nv); + static void mark16(const uint8_t y, const uint8_t v1, const uint8_t v2, uint8_t * const rcm=nullptr); + static void range16(const uint8_t y, const uint8_t ot, const uint8_t nt, const uint8_t oh, const uint8_t nh, uint8_t * const rcm=nullptr); + static void quantity(const uint8_t y, const uint8_t ov, const uint8_t nv, uint8_t * const rcm=nullptr); + static void quantity16(const uint8_t y, const uint8_t ov, const uint8_t nv, uint8_t * const rcm=nullptr); - #ifdef MAX7219_INIT_TEST + #if MAX7219_INIT_TEST static void test_pattern(); static void run_test_pattern(); static void start_test_pattern(); diff --git a/Marlin/src/feature/meatpack.cpp b/Marlin/src/feature/meatpack.cpp index b2899243b2..07ff41e5be 100644 --- a/Marlin/src/feature/meatpack.cpp +++ b/Marlin/src/feature/meatpack.cpp @@ -26,7 +26,7 @@ * Algorithm & Implementation: Scott Mudge - mail@scottmudge.com * Date: Dec. 2020 * - * Character Frequencies from ~30 MB of comment-stripped gcode: + * Character Frequencies from ~30 MB of comment-stripped G-code: * '1' -> 4451136 '4' -> 1353273 '\n' -> 1087683 '-' -> 90242 * '0' -> 4253577 '9' -> 1352147 'G' -> 1075806 'Z' -> 34109 * ' ' -> 3053297 '3' -> 1262929 'X' -> 975742 'M' -> 11879 diff --git a/Marlin/src/feature/meatpack.h b/Marlin/src/feature/meatpack.h index a56e65b6cc..98a535e592 100644 --- a/Marlin/src/feature/meatpack.h +++ b/Marlin/src/feature/meatpack.h @@ -29,7 +29,7 @@ * Specifically optimized for 3D printing G-Code, this is a zero-cost data compression method * which packs ~180-190% more data into the same amount of bytes going to the CNC controller. * As a majority of G-Code can be represented by a restricted alphabet, I performed histogram - * analysis on a wide variety of 3D printing gcode samples, and found ~93% of all gcode could + * analysis on a wide variety of 3D printing G-code samples, and found ~93% of all G-code could * be represented by the same 15-character alphabet. * * This allowed me to design a system of packing 2 8-bit characters into a single byte, assuming @@ -38,7 +38,7 @@ * * Combined with some logic to allow commingling of full-width characters outside of this 15- * character alphabet (at the cost of an extra 8-bits per full-width character), and by stripping - * out unnecessary comments, the end result is gcode which is roughly half the original size. + * out unnecessary comments, the end result is G-code which is roughly half the original size. * * Why did I do this? I noticed micro-stuttering and other data-bottleneck issues while printing * objects with high curvature, especially at high speeds. There is also the issue of the limited diff --git a/Marlin/src/feature/mmu/mmu2-serial-protocol.md b/Marlin/src/feature/mmu/mmu2-serial-protocol.md index 7ff0901742..93135e406f 100644 --- a/Marlin/src/feature/mmu/mmu2-serial-protocol.md +++ b/Marlin/src/feature/mmu/mmu2-serial-protocol.md @@ -51,7 +51,7 @@ When done, the MMU sends - MMU => 'ok\n' -We don't wait for a response here but immediately continue with the next gcode which should +We don't wait for a response here but immediately continue with the next G-code which should be one or more extruder moves to feed the filament into the hotend. diff --git a/Marlin/src/feature/mmu/mmu2.cpp b/Marlin/src/feature/mmu/mmu2.cpp index 63fd8ae059..227a2308eb 100644 --- a/Marlin/src/feature/mmu/mmu2.cpp +++ b/Marlin/src/feature/mmu/mmu2.cpp @@ -939,7 +939,7 @@ bool MMU2::load_filament_to_nozzle(const uint8_t index) { * Load filament to nozzle of multimaterial printer * * This function is used only after T? (user select filament) and M600 (change filament). - * It is not used after T0 .. T4 command (select filament), in such case, gcode is responsible for loading + * It is not used after T0 .. T4 command (select filament), in such case, G-code is responsible for loading * filament to nozzle. */ void MMU2::load_to_nozzle() { @@ -1031,8 +1031,7 @@ void MMU2::execute_extruder_sequence(const E_Step * sequence, int steps) { const float es = pgm_read_float(&(step->extrude)); const feedRate_t fr_mm_m = pgm_read_float(&(step->feedRate)); - DEBUG_ECHO_START(); - DEBUG_ECHOLNPGM("E step ", es, "/", fr_mm_m); + DEBUG_ECHO_MSG("E step ", es, "/", fr_mm_m); current_position.e += es; line_to_current_position(MMM_TO_MMS(fr_mm_m)); diff --git a/Marlin/src/feature/pause.cpp b/Marlin/src/feature/pause.cpp index 813c2bd0a7..998bc3bd35 100644 --- a/Marlin/src/feature/pause.cpp +++ b/Marlin/src/feature/pause.cpp @@ -681,8 +681,9 @@ void resume_print(const_float_t slow_load_length/*=0*/, const_float_t fast_load_ // If resume_position is negative //if (resume_position.e < 0) unscaled_e_move(resume_position.e, feedRate_t(PAUSE_PARK_RETRACT_FEEDRATE)); - #if ADVANCED_PAUSE_RESUME_PRIME != 0 - unscaled_e_move(ADVANCED_PAUSE_RESUME_PRIME, feedRate_t(ADVANCED_PAUSE_PURGE_FEEDRATE)); + #ifdef ADVANCED_PAUSE_RESUME_PRIME + if (ADVANCED_PAUSE_RESUME_PRIME != 0) + unscaled_e_move(ADVANCED_PAUSE_RESUME_PRIME, feedRate_t(ADVANCED_PAUSE_PURGE_FEEDRATE)); #endif // Now all extrusion positions are resumed and ready to be confirmed @@ -719,9 +720,13 @@ void resume_print(const_float_t slow_load_length/*=0*/, const_float_t fast_load_ TERN_(HAS_FILAMENT_SENSOR, runout.reset()); - TERN(DWIN_LCD_PROUI, DWIN_Print_Resume(), ui.reset_status()); - TERN_(HAS_MARLINUI_MENU, ui.return_to_status()); - TERN_(DWIN_LCD_PROUI, HMI_ReturnScreen()); + #if ENABLED(DWIN_LCD_PROUI) + DWIN_Print_Resume(); + HMI_ReturnScreen(); + #else + ui.reset_status(); + ui.return_to_status(); + #endif } #endif // ADVANCED_PAUSE_FEATURE diff --git a/Marlin/src/feature/power_monitor.cpp b/Marlin/src/feature/power_monitor.cpp index 504f1ea48e..5a9db1ec24 100644 --- a/Marlin/src/feature/power_monitor.cpp +++ b/Marlin/src/feature/power_monitor.cpp @@ -53,7 +53,7 @@ PowerMonitor power_monitor; // Single instance - this calls the constructor void PowerMonitor::draw_current() { const float amps = getAmps(); lcd_put_u8str(amps < 100 ? ftostr31ns(amps) : ui16tostr4rj((uint16_t)amps)); - lcd_put_wchar('A'); + lcd_put_lchar('A'); } #endif @@ -61,7 +61,7 @@ PowerMonitor power_monitor; // Single instance - this calls the constructor void PowerMonitor::draw_voltage() { const float volts = getVolts(); lcd_put_u8str(volts < 100 ? ftostr31ns(volts) : ui16tostr4rj((uint16_t)volts)); - lcd_put_wchar('V'); + lcd_put_lchar('V'); } #endif @@ -69,7 +69,7 @@ PowerMonitor power_monitor; // Single instance - this calls the constructor void PowerMonitor::draw_power() { const float power = getPower(); lcd_put_u8str(power < 100 ? ftostr31ns(power) : ui16tostr4rj((uint16_t)power)); - lcd_put_wchar('W'); + lcd_put_lchar('W'); } #endif diff --git a/Marlin/src/feature/power_monitor.h b/Marlin/src/feature/power_monitor.h index f6e0b292e3..fa06909053 100644 --- a/Marlin/src/feature/power_monitor.h +++ b/Marlin/src/feature/power_monitor.h @@ -32,7 +32,7 @@ struct pm_lpf_t { uint32_t filter_buf; float value; void add_sample(const uint16_t sample) { - filter_buf = filter_buf - (filter_buf >> K_VALUE) + (uint32_t(sample) << K_SCALE); + filter_buf += (uint32_t(sample) << K_SCALE) - (filter_buf >> K_VALUE); } void capture() { value = filter_buf * (SCALE * (1.0f / (1UL << (PM_K_VALUE + PM_K_SCALE)))); diff --git a/Marlin/src/feature/powerloss.cpp b/Marlin/src/feature/powerloss.cpp index 0fc195e7dd..d4450adcd8 100644 --- a/Marlin/src/feature/powerloss.cpp +++ b/Marlin/src/feature/powerloss.cpp @@ -108,13 +108,18 @@ void PrintJobRecovery::changed() { * * If a saved state exists send 'M1000 S' to initiate job recovery. */ -void PrintJobRecovery::check() { +bool PrintJobRecovery::check() { //if (!card.isMounted()) card.mount(); + bool success = false; if (card.isMounted()) { load(); - if (!valid()) return cancel(); - queue.inject(F("M1000S")); + success = valid(); + if (!success) + cancel(); + else + queue.inject(F("M1000S")); } + return success; } /** @@ -514,7 +519,7 @@ void PrintJobRecovery::resume() { EXTRUDER_LOOP() { if (info.retract[e] != 0.0) { fwretract.current_retract[e] = info.retract[e]; - fwretract.retracted[e] = true; + fwretract.retracted.set(e); } } fwretract.current_hop = info.retract_hop; diff --git a/Marlin/src/feature/powerloss.h b/Marlin/src/feature/powerloss.h index 4e97109bb7..33d9dc007c 100644 --- a/Marlin/src/feature/powerloss.h +++ b/Marlin/src/feature/powerloss.h @@ -176,11 +176,11 @@ class PrintJobRecovery { static void open(const bool read) { card.openJobRecoveryFile(read); } static void close() { file.close(); } - static void check(); + static bool check(); static void resume(); static void purge(); - static void cancel() { purge(); IF_DISABLED(NO_SD_AUTOSTART, card.autofile_begin()); } + static void cancel() { purge(); } static void load(); static void save(const bool force=ENABLED(SAVE_EACH_CMD_MODE), const float zraise=POWER_LOSS_ZRAISE, const bool raised=false); diff --git a/Marlin/src/feature/spindle_laser.cpp b/Marlin/src/feature/spindle_laser.cpp index 52bb471b0f..da38646a36 100644 --- a/Marlin/src/feature/spindle_laser.cpp +++ b/Marlin/src/feature/spindle_laser.cpp @@ -39,17 +39,26 @@ #endif SpindleLaser cutter; -uint8_t SpindleLaser::power; -#if ENABLED(LASER_FEATURE) - cutter_test_pulse_t SpindleLaser::testPulse = 50; // Test fire Pulse time ms value. -#endif -bool SpindleLaser::isReady; // Ready to apply power setting from the UI to OCR -cutter_power_t SpindleLaser::menuPower, // Power set via LCD menu in PWM, PERCENT, or RPM - SpindleLaser::unitPower; // LCD status power in PWM, PERCENT, or RPM +bool SpindleLaser::enable_state; // Virtual enable state, controls enable pin if present and or apply power if > 0 +uint8_t SpindleLaser::power, // Actual power output 0-255 ocr or "0 = off" > 0 = "on" + SpindleLaser::last_power_applied; // = 0 // Basic power state tracking -#if ENABLED(MARLIN_DEV_MODE) - cutter_frequency_t SpindleLaser::frequency; // PWM frequency setting; range: 2K - 50K +#if ENABLED(LASER_FEATURE) + cutter_test_pulse_t SpindleLaser::testPulse = 50; // (ms) Test fire pulse default duration + uint8_t SpindleLaser::last_block_power; // = 0 // Track power changes for dynamic inline power + feedRate_t SpindleLaser::feedrate_mm_m = 1500, + SpindleLaser::last_feedrate_mm_m; // = 0 // (mm/min) Track feedrate changes for dynamic power #endif + +bool SpindleLaser::isReadyForUI = false; // Ready to apply power setting from the UI to OCR +CutterMode SpindleLaser::cutter_mode = CUTTER_MODE_STANDARD; // Default is standard mode + +constexpr cutter_cpower_t SpindleLaser::power_floor; +cutter_power_t SpindleLaser::menuPower = 0, // Power value via LCD menu in PWM, PERCENT, or RPM based on configured format set by CUTTER_POWER_UNIT. + SpindleLaser::unitPower = 0; // Unit power is in PWM, PERCENT, or RPM based on CUTTER_POWER_UNIT. + +cutter_frequency_t SpindleLaser::frequency; // PWM frequency setting; range: 2K - 50K + #define SPINDLE_LASER_PWM_OFF TERN(SPINDLE_LASER_PWM_INVERT, 255, 0) /** @@ -57,21 +66,21 @@ cutter_power_t SpindleLaser::menuPower, // Power s */ void SpindleLaser::init() { #if ENABLED(SPINDLE_SERVO) - MOVE_SERVO(SPINDLE_SERVO_NR, SPINDLE_SERVO_MIN); + servo[SPINDLE_SERVO_NR].move(SPINDLE_SERVO_MIN); #else OUT_WRITE(SPINDLE_LASER_ENA_PIN, !SPINDLE_LASER_ACTIVE_STATE); // Init spindle to off #endif #if ENABLED(SPINDLE_CHANGE_DIR) OUT_WRITE(SPINDLE_DIR_PIN, SPINDLE_INVERT_DIR); // Init rotation to clockwise (M3) #endif + #if ENABLED(HAL_CAN_SET_PWM_FREQ) && SPINDLE_LASER_FREQUENCY + frequency = SPINDLE_LASER_FREQUENCY; + hal.set_pwm_frequency(pin_t(SPINDLE_LASER_PWM_PIN), SPINDLE_LASER_FREQUENCY); + #endif #if ENABLED(SPINDLE_LASER_USE_PWM) SET_PWM(SPINDLE_LASER_PWM_PIN); hal.set_pwm_duty(pin_t(SPINDLE_LASER_PWM_PIN), SPINDLE_LASER_PWM_OFF); // Set to lowest speed #endif - #if ENABLED(HAL_CAN_SET_PWM_FREQ) && SPINDLE_LASER_FREQUENCY - hal.set_pwm_frequency(pin_t(SPINDLE_LASER_PWM_PIN), SPINDLE_LASER_FREQUENCY); - TERN_(MARLIN_DEV_MODE, frequency = SPINDLE_LASER_FREQUENCY); - #endif #if ENABLED(AIR_EVACUATION) OUT_WRITE(AIR_EVACUATION_PIN, !AIR_EVACUATION_ACTIVE); // Init Vacuum/Blower OFF #endif @@ -89,7 +98,7 @@ void SpindleLaser::init() { */ void SpindleLaser::_set_ocr(const uint8_t ocr) { #if ENABLED(HAL_CAN_SET_PWM_FREQ) && SPINDLE_LASER_FREQUENCY - hal.set_pwm_frequency(pin_t(SPINDLE_LASER_PWM_PIN), TERN(MARLIN_DEV_MODE, frequency, SPINDLE_LASER_FREQUENCY)); + hal.set_pwm_frequency(pin_t(SPINDLE_LASER_PWM_PIN), frequency); #endif hal.set_pwm_duty(pin_t(SPINDLE_LASER_PWM_PIN), ocr ^ SPINDLE_LASER_PWM_OFF); } @@ -106,36 +115,41 @@ void SpindleLaser::init() { #endif // SPINDLE_LASER_USE_PWM /** - * Apply power for laser/spindle + * Apply power for Laser or Spindle * * Apply cutter power value for PWM, Servo, and on/off pin. * - * @param opwr Power value. Range 0 to MAX. When 0 disable spindle/laser. + * @param opwr Power value. Range 0 to MAX. */ void SpindleLaser::apply_power(const uint8_t opwr) { - static uint8_t last_power_applied = 0; - if (opwr == last_power_applied) return; - last_power_applied = opwr; - power = opwr; - #if ENABLED(SPINDLE_LASER_USE_PWM) - if (cutter.unitPower == 0 && CUTTER_UNIT_IS(RPM)) { - ocr_off(); - isReady = false; - } - else if (ENABLED(CUTTER_POWER_RELATIVE) || enabled()) { - set_ocr(power); - isReady = true; - } - else { - ocr_off(); - isReady = false; - } - #elif ENABLED(SPINDLE_SERVO) - MOVE_SERVO(SPINDLE_SERVO_NR, power); - #else - WRITE(SPINDLE_LASER_ENA_PIN, enabled() ? SPINDLE_LASER_ACTIVE_STATE : !SPINDLE_LASER_ACTIVE_STATE); - isReady = true; - #endif + if (enabled() || opwr == 0) { // 0 check allows us to disable where no ENA pin exists + // Test and set the last power used to improve performance + if (opwr == last_power_applied) return; + last_power_applied = opwr; + // Handle PWM driven or just simple on/off + #if ENABLED(SPINDLE_LASER_USE_PWM) + if (CUTTER_UNIT_IS(RPM) && unitPower == 0) + ocr_off(); + else if (ENABLED(CUTTER_POWER_RELATIVE) || enabled() || opwr == 0) { + set_ocr(opwr); + isReadyForUI = true; + } + else + ocr_off(); + #elif ENABLED(SPINDLE_SERVO) + MOVE_SERVO(SPINDLE_SERVO_NR, power); + #else + WRITE(SPINDLE_LASER_ENA_PIN, enabled() ? SPINDLE_LASER_ACTIVE_STATE : !SPINDLE_LASER_ACTIVE_STATE); + isReadyForUI = true; + #endif + } + else { + #if PIN_EXISTS(SPINDLE_LASER_ENA) + WRITE(SPINDLE_LASER_ENA_PIN, !SPINDLE_LASER_ACTIVE_STATE); + #endif + isReadyForUI = false; // Only used for UI display updates. + TERN_(SPINDLE_LASER_USE_PWM, ocr_off()); + } } #if ENABLED(SPINDLE_CHANGE_DIR) @@ -159,8 +173,8 @@ void SpindleLaser::apply_power(const uint8_t opwr) { #if ENABLED(AIR_ASSIST) // Enable / disable air assist - void SpindleLaser::air_assist_enable() { WRITE(AIR_ASSIST_PIN, AIR_ASSIST_PIN); } // Turn ON - void SpindleLaser::air_assist_disable() { WRITE(AIR_ASSIST_PIN, !AIR_ASSIST_PIN); } // Turn OFF + void SpindleLaser::air_assist_enable() { WRITE(AIR_ASSIST_PIN, AIR_ASSIST_ACTIVE); } // Turn ON + void SpindleLaser::air_assist_disable() { WRITE(AIR_ASSIST_PIN, !AIR_ASSIST_ACTIVE); } // Turn OFF void SpindleLaser::air_assist_toggle() { TOGGLE(AIR_ASSIST_PIN); } // Toggle state #endif diff --git a/Marlin/src/feature/spindle_laser.h b/Marlin/src/feature/spindle_laser.h index e948d2d37b..b945032d8e 100644 --- a/Marlin/src/feature/spindle_laser.h +++ b/Marlin/src/feature/spindle_laser.h @@ -30,90 +30,102 @@ #include "spindle_laser_types.h" -#if USE_BEEPER +#if HAS_BEEPER #include "../libs/buzzer.h" #endif -#if ENABLED(LASER_POWER_INLINE) - #include "../module/planner.h" -#endif +// Inline laser power +#include "../module/planner.h" #define PCT_TO_PWM(X) ((X) * 255 / 100) #define PCT_TO_SERVO(X) ((X) * 180 / 100) -// #define _MAP(N,S1,S2,D1,D2) ((N)*_MAX((D2)-(D1),0)/_MAX((S2)-(S1),1)+(D1)) + +// Laser/Cutter operation mode +enum CutterMode : int8_t { + CUTTER_MODE_ERROR = -1, + CUTTER_MODE_STANDARD, // M3 power is applied directly and waits for planner moves to sync. + CUTTER_MODE_CONTINUOUS, // M3 or G1/2/3 move power is controlled within planner blocks, set with 'M3 I', cleared with 'M5 I'. + CUTTER_MODE_DYNAMIC // M4 laser power is proportional to the feed rate, set with 'M4 I', cleared with 'M5 I'. +}; class SpindleLaser { public: - static const inline uint8_t pct_to_ocr(const_float_t pct) { return uint8_t(PCT_TO_PWM(pct)); } + static CutterMode cutter_mode; + + static constexpr uint8_t pct_to_ocr(const_float_t pct) { return uint8_t(PCT_TO_PWM(pct)); } // cpower = configured values (e.g., SPEED_POWER_MAX) - // Convert configured power range to a percentage - static const inline uint8_t cpwr_to_pct(const cutter_cpower_t cpwr) { - constexpr cutter_cpower_t power_floor = TERN(CUTTER_POWER_RELATIVE, SPEED_POWER_MIN, 0), - power_range = SPEED_POWER_MAX - power_floor; - return cpwr ? round(100.0f * (cpwr - power_floor) / power_range) : 0; + static constexpr cutter_cpower_t power_floor = TERN(CUTTER_POWER_RELATIVE, SPEED_POWER_MIN, 0); + static constexpr uint8_t cpwr_to_pct(const cutter_cpower_t cpwr) { + return cpwr ? round(100.0f * (cpwr - power_floor) / (SPEED_POWER_MAX - power_floor)) : 0; } - // Convert a cpower (e.g., SPEED_POWER_STARTUP) to unit power (upwr, upower), - // which can be PWM, Percent, Servo angle, or RPM (rel/abs). - static const inline cutter_power_t cpwr_to_upwr(const cutter_cpower_t cpwr) { // STARTUP power to Unit power - const cutter_power_t upwr = ( + // Convert config defines from RPM to %, angle or PWM when in Spindle mode + // and convert from PERCENT to PWM when in Laser mode + static constexpr cutter_power_t cpwr_to_upwr(const cutter_cpower_t cpwr) { // STARTUP power to Unit power + return ( #if ENABLED(SPINDLE_FEATURE) - // Spindle configured values are in RPM + // Spindle configured define values are in RPM #if CUTTER_UNIT_IS(RPM) - cpwr // to RPM - #elif CUTTER_UNIT_IS(PERCENT) // to PCT - cpwr_to_pct(cpwr) - #elif CUTTER_UNIT_IS(SERVO) // to SERVO angle - PCT_TO_SERVO(cpwr_to_pct(cpwr)) - #else // to PWM - PCT_TO_PWM(cpwr_to_pct(cpwr)) + cpwr // to same + #elif CUTTER_UNIT_IS(PERCENT) + cpwr_to_pct(cpwr) // to Percent + #elif CUTTER_UNIT_IS(SERVO) + PCT_TO_SERVO(cpwr_to_pct(cpwr)) // to SERVO angle + #else + PCT_TO_PWM(cpwr_to_pct(cpwr)) // to PWM #endif #else - // Laser configured values are in PCT + // Laser configured define values are in Percent #if CUTTER_UNIT_IS(PWM255) - PCT_TO_PWM(cpwr) + PCT_TO_PWM(cpwr) // to PWM #else - cpwr // to RPM/PCT + cpwr // to same #endif #endif ); - return upwr; } - static const cutter_power_t mpower_min() { return cpwr_to_upwr(SPEED_POWER_MIN); } - static const cutter_power_t mpower_max() { return cpwr_to_upwr(SPEED_POWER_MAX); } + static constexpr cutter_power_t mpower_min() { return cpwr_to_upwr(SPEED_POWER_MIN); } + static constexpr cutter_power_t mpower_max() { return cpwr_to_upwr(SPEED_POWER_MAX); } #if ENABLED(LASER_FEATURE) - static cutter_test_pulse_t testPulse; // Test fire Pulse ms value + static cutter_test_pulse_t testPulse; // (ms) Test fire pulse duration + static uint8_t last_block_power; // Track power changes for dynamic power + + static feedRate_t feedrate_mm_m, last_feedrate_mm_m; // (mm/min) Track feedrate changes for dynamic power + static bool laser_feedrate_changed() { + const bool changed = last_feedrate_mm_m != feedrate_mm_m; + if (changed) last_feedrate_mm_m = feedrate_mm_m; + return changed; + } #endif - static bool isReady; // Ready to apply power setting from the UI to OCR - static uint8_t power; + static bool isReadyForUI; // Ready to apply power setting from the UI to OCR + static bool enable_state; + static uint8_t power, + last_power_applied; // Basic power state tracking - #if ENABLED(MARLIN_DEV_MODE) - static cutter_frequency_t frequency; // Set PWM frequency; range: 2K-50K - #endif + static cutter_frequency_t frequency; // Set PWM frequency; range: 2K-50K static cutter_power_t menuPower, // Power as set via LCD menu in PWM, Percentage or RPM unitPower; // Power as displayed status in PWM, Percentage or RPM static void init(); - #if ENABLED(MARLIN_DEV_MODE) + #if ENABLED(HAL_CAN_SET_PWM_FREQ) && SPINDLE_LASER_FREQUENCY static void refresh_frequency() { hal.set_pwm_frequency(pin_t(SPINDLE_LASER_PWM_PIN), frequency); } #endif // Modifying this function should update everywhere static bool enabled(const cutter_power_t opwr) { return opwr > 0; } - static bool enabled() { return enabled(power); } + static bool enabled() { return enable_state; } static void apply_power(const uint8_t inpow); FORCE_INLINE static void refresh() { apply_power(power); } - FORCE_INLINE static void set_power(const uint8_t upwr) { power = upwr; refresh(); } #if ENABLED(SPINDLE_LASER_USE_PWM) @@ -124,7 +136,6 @@ public: public: static void set_ocr(const uint8_t ocr); - static void ocr_set_power(const uint8_t ocr) { power = ocr; set_ocr(ocr); } static void ocr_off(); /** @@ -142,78 +153,76 @@ public: ); } - /** - * Correct power to configured range - */ - static cutter_power_t power_to_range(const cutter_power_t pwr) { - return power_to_range(pwr, _CUTTER_POWER(CUTTER_POWER_UNIT)); - } - - static cutter_power_t power_to_range(const cutter_power_t pwr, const uint8_t pwrUnit) { - static constexpr float - min_pct = TERN(CUTTER_POWER_RELATIVE, 0, TERN(SPINDLE_FEATURE, round(100.0f * (SPEED_POWER_MIN) / (SPEED_POWER_MAX)), SPEED_POWER_MIN)), - max_pct = TERN(SPINDLE_FEATURE, 100, SPEED_POWER_MAX); - if (pwr <= 0) return 0; - cutter_power_t upwr; - switch (pwrUnit) { - case _CUTTER_POWER_PWM255: - upwr = cutter_power_t( - (pwr < pct_to_ocr(min_pct)) ? pct_to_ocr(min_pct) // Use minimum if set below - : (pwr > pct_to_ocr(max_pct)) ? pct_to_ocr(max_pct) // Use maximum if set above - : pwr - ); - break; - case _CUTTER_POWER_PERCENT: - upwr = cutter_power_t( - (pwr < min_pct) ? min_pct // Use minimum if set below - : (pwr > max_pct) ? max_pct // Use maximum if set above - : pwr // PCT - ); - break; - case _CUTTER_POWER_RPM: - upwr = cutter_power_t( - (pwr < SPEED_POWER_MIN) ? SPEED_POWER_MIN // Use minimum if set below - : (pwr > SPEED_POWER_MAX) ? SPEED_POWER_MAX // Use maximum if set above - : pwr // Calculate OCR value - ); - break; - default: break; - } - return upwr; - } - #endif // SPINDLE_LASER_USE_PWM /** - * Enable/Disable spindle/laser - * @param enable true = enable; false = disable + * Correct power to configured range */ - static void set_enabled(const bool enable) { - uint8_t value = 0; - if (enable) { - #if ENABLED(SPINDLE_LASER_USE_PWM) - if (power) - value = power; - else if (unitPower) - value = upower_to_ocr(cpwr_to_upwr(SPEED_POWER_STARTUP)); - #else - value = 255; - #endif + static cutter_power_t power_to_range(const cutter_power_t pwr, const uint8_t pwrUnit=_CUTTER_POWER(CUTTER_POWER_UNIT)) { + static constexpr float + min_pct = TERN(CUTTER_POWER_RELATIVE, 0, TERN(SPINDLE_FEATURE, round(100.0f * (SPEED_POWER_MIN) / (SPEED_POWER_MAX)), SPEED_POWER_MIN)), + max_pct = TERN(SPINDLE_FEATURE, 100, SPEED_POWER_MAX); + if (pwr <= 0) return 0; + cutter_power_t upwr; + switch (pwrUnit) { + case _CUTTER_POWER_PWM255: { // PWM + const uint8_t pmin = pct_to_ocr(min_pct), pmax = pct_to_ocr(max_pct); + upwr = cutter_power_t(constrain(pwr, pmin, pmax)); + } break; + case _CUTTER_POWER_PERCENT: // Percent + upwr = cutter_power_t(constrain(pwr, min_pct, max_pct)); + break; + case _CUTTER_POWER_RPM: // Calculate OCR value + upwr = cutter_power_t(constrain(pwr, SPEED_POWER_MIN, SPEED_POWER_MAX)); + break; + default: break; } - set_power(value); + return upwr; } - static void disable() { isReady = false; set_enabled(false); } - /** - * Wait for spindle to spin up or spin down + * Enable Laser or Spindle output. + * It's important to prevent changing the power output value during inline cutter operation. + * Inline power is adjusted in the planner to support LASER_TRAP_POWER and CUTTER_MODE_DYNAMIC mode. * - * @param on true = state to on; false = state to off. + * This method accepts one of the following control states: + * + * - For CUTTER_MODE_STANDARD the cutter power is either full on/off or ocr-based and it will apply + * SPEED_POWER_STARTUP if no value is assigned. + * + * - For CUTTER_MODE_CONTINUOUS inline and power remains where last set and the cutter output enable flag is set. + * + * - CUTTER_MODE_DYNAMIC is also inline-based and it just sets the enable output flag. + * + * - For CUTTER_MODE_ERROR set the output enable_state flag directly and set power to 0 for any mode. + * This mode allows a global power shutdown action to occur. */ - static void power_delay(const bool on) { - #if DISABLED(LASER_POWER_INLINE) - safe_delay(on ? SPINDLE_LASER_POWERUP_DELAY : SPINDLE_LASER_POWERDOWN_DELAY); + static void set_enabled(const bool enable) { + switch (cutter_mode) { + case CUTTER_MODE_STANDARD: + apply_power(enable ? TERN(SPINDLE_LASER_USE_PWM, (power ?: (unitPower ? upower_to_ocr(cpwr_to_upwr(SPEED_POWER_STARTUP)) : 0)), 255) : 0); + break; + case CUTTER_MODE_CONTINUOUS: + TERN_(LASER_FEATURE, set_inline_enabled(enable)); + break; + case CUTTER_MODE_DYNAMIC: + TERN_(LASER_FEATURE, set_inline_enabled(enable)); + break; + case CUTTER_MODE_ERROR: // Error mode, no enable and kill power. + enable_state = false; + apply_power(0); + } + #if SPINDLE_LASER_ENA_PIN + WRITE(SPINDLE_LASER_ENA_PIN, enable ? SPINDLE_LASER_ACTIVE_STATE : !SPINDLE_LASER_ACTIVE_STATE); #endif + enable_state = enable; + } + + static void disable() { isReadyForUI = false; set_enabled(false); } + + // Wait for spindle/laser to startup or shutdown + static void power_delay(const bool on) { + safe_delay(on ? SPINDLE_LASER_POWERUP_DELAY : SPINDLE_LASER_POWERDOWN_DELAY); } #if ENABLED(SPINDLE_CHANGE_DIR) @@ -225,122 +234,97 @@ public: #endif #if ENABLED(AIR_EVACUATION) - static void air_evac_enable(); // Turn On Cutter Vacuum or Laser Blower motor - static void air_evac_disable(); // Turn Off Cutter Vacuum or Laser Blower motor - static void air_evac_toggle(); // Toggle Cutter Vacuum or Laser Blower motor - static bool air_evac_state() { // Get current state + static void air_evac_enable(); // Turn On Cutter Vacuum or Laser Blower motor + static void air_evac_disable(); // Turn Off Cutter Vacuum or Laser Blower motor + static void air_evac_toggle(); // Toggle Cutter Vacuum or Laser Blower motor + static bool air_evac_state() { // Get current state return (READ(AIR_EVACUATION_PIN) == AIR_EVACUATION_ACTIVE); } #endif #if ENABLED(AIR_ASSIST) - static void air_assist_enable(); // Turn on air assist - static void air_assist_disable(); // Turn off air assist - static void air_assist_toggle(); // Toggle air assist - static bool air_assist_state() { // Get current state + static void air_assist_enable(); // Turn on air assist + static void air_assist_disable(); // Turn off air assist + static void air_assist_toggle(); // Toggle air assist + static bool air_assist_state() { // Get current state return (READ(AIR_ASSIST_PIN) == AIR_ASSIST_ACTIVE); } #endif #if HAS_MARLINUI_MENU - static void enable_with_dir(const bool reverse) { - isReady = true; - const uint8_t ocr = TERN(SPINDLE_LASER_USE_PWM, upower_to_ocr(menuPower), 255); - if (menuPower) - power = ocr; - else - menuPower = cpwr_to_upwr(SPEED_POWER_STARTUP); - unitPower = menuPower; - set_reverse(reverse); - set_enabled(true); - } - FORCE_INLINE static void enable_forward() { enable_with_dir(false); } - FORCE_INLINE static void enable_reverse() { enable_with_dir(true); } - FORCE_INLINE static void enable_same_dir() { enable_with_dir(is_reverse()); } + + #if ENABLED(SPINDLE_FEATURE) + static void enable_with_dir(const bool reverse) { + isReadyForUI = true; + const uint8_t ocr = TERN(SPINDLE_LASER_USE_PWM, upower_to_ocr(menuPower), 255); + if (menuPower) + power = ocr; + else + menuPower = cpwr_to_upwr(SPEED_POWER_STARTUP); + unitPower = menuPower; + set_reverse(reverse); + set_enabled(true); + } + FORCE_INLINE static void enable_forward() { enable_with_dir(false); } + FORCE_INLINE static void enable_reverse() { enable_with_dir(true); } + FORCE_INLINE static void enable_same_dir() { enable_with_dir(is_reverse()); } + #endif // SPINDLE_FEATURE #if ENABLED(SPINDLE_LASER_USE_PWM) static void update_from_mpower() { - if (isReady) power = upower_to_ocr(menuPower); + if (isReadyForUI) power = upower_to_ocr(menuPower); unitPower = menuPower; } #endif #if ENABLED(LASER_FEATURE) + // Toggle the laser on/off with menuPower. Apply SPEED_POWER_STARTUP if it was 0 on entry. + static void laser_menu_toggle(const bool state) { + set_enabled(state); + if (state) { + if (!menuPower) menuPower = cpwr_to_upwr(SPEED_POWER_STARTUP); + power = upower_to_ocr(menuPower); + apply_power(power); + } + } + /** * Test fire the laser using the testPulse ms duration * Also fires with any PWM power that was previous set * If not set defaults to 80% power */ static void test_fire_pulse() { - TERN_(USE_BEEPER, buzzer.tone(30, 3000)); - enable_forward(); // Turn Laser on (Spindle speak but same funct) + TERN_(HAS_BEEPER, buzzer.tone(30, 3000)); + cutter_mode = CUTTER_MODE_STANDARD;// Menu needs standard mode. + laser_menu_toggle(true); // Laser On delay(testPulse); // Delay for time set by user in pulse ms menu screen. - disable(); // Turn laser off + laser_menu_toggle(false); // Laser Off } - #endif + #endif // LASER_FEATURE #endif // HAS_MARLINUI_MENU - #if ENABLED(LASER_POWER_INLINE) - /** - * Inline power adds extra fields to the planner block - * to handle laser power and scale to movement speed. - */ + #if ENABLED(LASER_FEATURE) - // Force disengage planner power control - static void inline_disable() { - isReady = false; - unitPower = 0; - planner.laser_inline.status.isPlanned = false; - planner.laser_inline.status.isEnabled = false; - planner.laser_inline.power = 0; + // Dynamic mode rate calculation + static uint8_t calc_dynamic_power() { + if (feedrate_mm_m > 65535) return 255; // Too fast, go always on + uint16_t rate = uint16_t(feedrate_mm_m); // 16 bits from the G-code parser float input + rate >>= 8; // Take the G-code input e.g. F40000 and shift off the lower bits to get an OCR value from 1-255 + return uint8_t(rate); } // Inline modes of all other functions; all enable planner inline power control - static void set_inline_enabled(const bool enable) { - if (enable) - inline_power(255); - else { - isReady = false; - unitPower = menuPower = 0; - planner.laser_inline.status.isPlanned = false; - TERN(SPINDLE_LASER_USE_PWM, inline_ocr_power, inline_power)(0); - } - } + static void set_inline_enabled(const bool enable) { planner.laser_inline.status.isEnabled = enable;} // Set the power for subsequent movement blocks - static void inline_power(const cutter_power_t upwr) { - unitPower = menuPower = upwr; - #if ENABLED(SPINDLE_LASER_USE_PWM) - #if ENABLED(SPEED_POWER_RELATIVE) && !CUTTER_UNIT_IS(RPM) // relative mode does not turn laser off at 0, except for RPM - planner.laser_inline.status.isEnabled = true; - planner.laser_inline.power = upower_to_ocr(upwr); - isReady = true; - #else - inline_ocr_power(upower_to_ocr(upwr)); - #endif - #else - planner.laser_inline.status.isEnabled = enabled(upwr); - planner.laser_inline.power = upwr; - isReady = enabled(upwr); - #endif + static void inline_power(const cutter_power_t cpwr) { + TERN(SPINDLE_LASER_USE_PWM, power = planner.laser_inline.power = cpwr, planner.laser_inline.power = cpwr > 0 ? 255 : 0); } - static void inline_direction(const bool) { /* never */ } + #endif // LASER_FEATURE - #if ENABLED(SPINDLE_LASER_USE_PWM) - static void inline_ocr_power(const uint8_t ocrpwr) { - isReady = ocrpwr > 0; - planner.laser_inline.status.isEnabled = ocrpwr > 0; - planner.laser_inline.power = ocrpwr; - } - #endif - #endif // LASER_POWER_INLINE - - static void kill() { - TERN_(LASER_POWER_INLINE, inline_disable()); - disable(); - } + static void kill() { disable(); } }; extern SpindleLaser cutter; diff --git a/Marlin/src/feature/spindle_laser_types.h b/Marlin/src/feature/spindle_laser_types.h index d249a20e75..2f36a68a1a 100644 --- a/Marlin/src/feature/spindle_laser_types.h +++ b/Marlin/src/feature/spindle_laser_types.h @@ -74,12 +74,10 @@ typedef IF<(SPEED_POWER_MAX > 255), uint16_t, uint8_t>::type cutter_cpower_t; #endif #endif +typedef uint16_t cutter_frequency_t; + #if ENABLED(LASER_FEATURE) typedef uint16_t cutter_test_pulse_t; #define CUTTER_MENU_PULSE_TYPE uint16_3 -#endif - -#if ENABLED(MARLIN_DEV_MODE) - typedef uint16_t cutter_frequency_t; #define CUTTER_MENU_FREQUENCY_TYPE uint16_5 #endif diff --git a/Marlin/src/feature/z_stepper_align.cpp b/Marlin/src/feature/z_stepper_align.cpp index fdbd464ea1..9dba21d821 100644 --- a/Marlin/src/feature/z_stepper_align.cpp +++ b/Marlin/src/feature/z_stepper_align.cpp @@ -33,35 +33,35 @@ ZStepperAlign z_stepper_align; -xy_pos_t ZStepperAlign::xy[NUM_Z_STEPPER_DRIVERS]; +xy_pos_t ZStepperAlign::xy[NUM_Z_STEPPERS]; #if HAS_Z_STEPPER_ALIGN_STEPPER_XY - xy_pos_t ZStepperAlign::stepper_xy[NUM_Z_STEPPER_DRIVERS]; + xy_pos_t ZStepperAlign::stepper_xy[NUM_Z_STEPPERS]; #endif void ZStepperAlign::reset_to_default() { #ifdef Z_STEPPER_ALIGN_XY constexpr xy_pos_t xy_init[] = Z_STEPPER_ALIGN_XY; - static_assert(COUNT(xy_init) == NUM_Z_STEPPER_DRIVERS, + static_assert(COUNT(xy_init) == NUM_Z_STEPPERS, "Z_STEPPER_ALIGN_XY requires " - #if NUM_Z_STEPPER_DRIVERS == 4 + #if NUM_Z_STEPPERS == 4 "four {X,Y} entries (Z, Z2, Z3, and Z4)." - #elif NUM_Z_STEPPER_DRIVERS == 3 + #elif NUM_Z_STEPPERS == 3 "three {X,Y} entries (Z, Z2, and Z3)." #else "two {X,Y} entries (Z and Z2)." #endif ); - #define VALIDATE_ALIGN_POINT(N) static_assert(N >= NUM_Z_STEPPER_DRIVERS || Probe::build_time::can_reach(xy_init[N]), \ + #define VALIDATE_ALIGN_POINT(N) static_assert(N >= NUM_Z_STEPPERS || Probe::build_time::can_reach(xy_init[N]), \ "Z_STEPPER_ALIGN_XY point " STRINGIFY(N) " is not reachable with the default NOZZLE_TO_PROBE offset and PROBING_MARGIN.") VALIDATE_ALIGN_POINT(0); VALIDATE_ALIGN_POINT(1); VALIDATE_ALIGN_POINT(2); VALIDATE_ALIGN_POINT(3); #else // !Z_STEPPER_ALIGN_XY const xy_pos_t xy_init[] = { - #if NUM_Z_STEPPER_DRIVERS >= 3 // First probe point... + #if NUM_Z_STEPPERS >= 3 // First probe point... #if !Z_STEPPERS_ORIENTATION { probe.min_x(), probe.min_y() }, // SW #elif Z_STEPPERS_ORIENTATION == 1 @@ -73,7 +73,7 @@ void ZStepperAlign::reset_to_default() { #else #error "Z_STEPPERS_ORIENTATION must be from 0 to 3 (first point SW, NW, NE, SE)." #endif - #if NUM_Z_STEPPER_DRIVERS == 4 // 3 more points... + #if NUM_Z_STEPPERS == 4 // 3 more points... #if !Z_STEPPERS_ORIENTATION { probe.min_x(), probe.max_y() }, { probe.max_x(), probe.max_y() }, { probe.max_x(), probe.min_y() } // SW #elif Z_STEPPERS_ORIENTATION == 1 @@ -106,11 +106,11 @@ void ZStepperAlign::reset_to_default() { #if HAS_Z_STEPPER_ALIGN_STEPPER_XY constexpr xy_pos_t stepper_xy_init[] = Z_STEPPER_ALIGN_STEPPER_XY; static_assert( - COUNT(stepper_xy_init) == NUM_Z_STEPPER_DRIVERS, + COUNT(stepper_xy_init) == NUM_Z_STEPPERS, "Z_STEPPER_ALIGN_STEPPER_XY requires " - #if NUM_Z_STEPPER_DRIVERS == 4 + #if NUM_Z_STEPPERS == 4 "four {X,Y} entries (Z, Z2, Z3, and Z4)." - #elif NUM_Z_STEPPER_DRIVERS == 3 + #elif NUM_Z_STEPPERS == 3 "three {X,Y} entries (Z, Z2, and Z3)." #endif ); diff --git a/Marlin/src/feature/z_stepper_align.h b/Marlin/src/feature/z_stepper_align.h index 8a12cd18b0..f3f9abb845 100644 --- a/Marlin/src/feature/z_stepper_align.h +++ b/Marlin/src/feature/z_stepper_align.h @@ -29,10 +29,10 @@ class ZStepperAlign { public: - static xy_pos_t xy[NUM_Z_STEPPER_DRIVERS]; + static xy_pos_t xy[NUM_Z_STEPPERS]; #if HAS_Z_STEPPER_ALIGN_STEPPER_XY - static xy_pos_t stepper_xy[NUM_Z_STEPPER_DRIVERS]; + static xy_pos_t stepper_xy[NUM_Z_STEPPERS]; #endif static void reset_to_default(); diff --git a/Marlin/src/gcode/bedlevel/G26.cpp b/Marlin/src/gcode/bedlevel/G26.cpp index 6691d6c9ab..1e436ffd96 100644 --- a/Marlin/src/gcode/bedlevel/G26.cpp +++ b/Marlin/src/gcode/bedlevel/G26.cpp @@ -293,10 +293,10 @@ typedef struct { if (circle_flags.marked(p1.x, p1.y) && circle_flags.marked(p2.x, p2.y)) { xyz_pos_t s, e; - s.x = _GET_MESH_X(p1.x) + (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)) * dx; - e.x = _GET_MESH_X(p2.x) - (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)) * dx; - s.y = _GET_MESH_Y(p1.y) + (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)) * dy; - e.y = _GET_MESH_Y(p2.y) - (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)) * dy; + s.x = bedlevel.get_mesh_x(p1.x) + (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)) * dx; + e.x = bedlevel.get_mesh_x(p2.x) - (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)) * dx; + s.y = bedlevel.get_mesh_y(p1.y) + (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)) * dy; + e.y = bedlevel.get_mesh_y(p2.y) - (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)) * dy; s.z = e.z = layer_height; #if HAS_ENDSTOPS @@ -306,7 +306,7 @@ typedef struct { LIMIT(e.x, X_MIN_POS + 1, X_MAX_POS - 1); #endif - if (position_is_reachable(s.x, s.y) && position_is_reachable(e.x, e.y)) + if (position_is_reachable(s) && position_is_reachable(e)) print_line_from_here_to_there(s, e); } } @@ -448,7 +448,7 @@ typedef struct { GRID_LOOP(i, j) { if (!circle_flags.marked(i, j)) { // We found a circle that needs to be printed - const xy_pos_t m = { _GET_MESH_X(i), _GET_MESH_Y(j) }; + const xy_pos_t m = { bedlevel.get_mesh_x(i), bedlevel.get_mesh_y(j) }; // Get the distance to this intersection float f = (pos - m).magnitude(); @@ -729,7 +729,7 @@ void GcodeSuite::G26() { if (location.valid()) { TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(location.pos, ExtUI::G26_POINT_START)); - const xy_pos_t circle = _GET_MESH_POS(location.pos); + const xy_pos_t circle = { bedlevel.get_mesh_x(location.pos.a), bedlevel.get_mesh_y(location.pos.b) }; // If this mesh location is outside the printable radius, skip it. if (!position_is_reachable(circle)) continue; @@ -738,8 +738,8 @@ void GcodeSuite::G26() { // which is always drawn counter-clockwise. const xy_int8_t st = location; const bool f = st.y == 0, - r = st.x >= GRID_MAX_POINTS_X - 1, - b = st.y >= GRID_MAX_POINTS_Y - 1; + r = st.x >= (GRID_MAX_POINTS_X) - 1, + b = st.y >= (GRID_MAX_POINTS_Y) - 1; #if ENABLED(ARC_SUPPORT) diff --git a/Marlin/src/gcode/bedlevel/G42.cpp b/Marlin/src/gcode/bedlevel/G42.cpp index a2896ed6c7..cb5ed97406 100644 --- a/Marlin/src/gcode/bedlevel/G42.cpp +++ b/Marlin/src/gcode/bedlevel/G42.cpp @@ -48,8 +48,8 @@ void GcodeSuite::G42() { // Move to current_position, as modified by I, J, P parameters destination = current_position; - if (hasI) destination.x = _GET_MESH_X(ix); - if (hasJ) destination.y = _GET_MESH_Y(iy); + if (hasI) destination.x = bedlevel.get_mesh_x(ix); + if (hasJ) destination.y = bedlevel.get_mesh_y(iy); #if HAS_PROBE_XY_OFFSET if (parser.boolval('P')) { diff --git a/Marlin/src/gcode/bedlevel/M420.cpp b/Marlin/src/gcode/bedlevel/M420.cpp index c8325b1fc5..277f95b9ff 100644 --- a/Marlin/src/gcode/bedlevel/M420.cpp +++ b/Marlin/src/gcode/bedlevel/M420.cpp @@ -71,13 +71,13 @@ void GcodeSuite::M420() { start.set(x_min, y_min); spacing.set((x_max - x_min) / (GRID_MAX_CELLS_X), (y_max - y_min) / (GRID_MAX_CELLS_Y)); - bbl.set_grid(spacing, start); + bedlevel.set_grid(spacing, start); #endif GRID_LOOP(x, y) { - Z_VALUES(x, y) = 0.001 * random(-200, 200); - TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(x, y, Z_VALUES(x, y))); + bedlevel.z_values[x][y] = 0.001 * random(-200, 200); + TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(x, y, bedlevel.z_values[x][y])); } - TERN_(AUTO_BED_LEVELING_BILINEAR, bbl.refresh_bed_level()); + TERN_(AUTO_BED_LEVELING_BILINEAR, bedlevel.refresh_bed_level()); SERIAL_ECHOPGM("Simulated " STRINGIFY(GRID_MAX_POINTS_X) "x" STRINGIFY(GRID_MAX_POINTS_Y) " mesh "); SERIAL_ECHOPGM(" (", x_min); SERIAL_CHAR(','); SERIAL_ECHO(y_min); @@ -101,7 +101,7 @@ void GcodeSuite::M420() { set_bed_leveling_enabled(false); #if ENABLED(EEPROM_SETTINGS) - const int8_t storage_slot = parser.has_value() ? parser.value_int() : ubl.storage_slot; + const int8_t storage_slot = parser.has_value() ? parser.value_int() : bedlevel.storage_slot; const int16_t a = settings.calc_num_meshes(); if (!a) { @@ -116,7 +116,7 @@ void GcodeSuite::M420() { } settings.load_mesh(storage_slot); - ubl.storage_slot = storage_slot; + bedlevel.storage_slot = storage_slot; #else @@ -128,10 +128,10 @@ void GcodeSuite::M420() { // L or V display the map info if (parser.seen("LV")) { - ubl.display_map(parser.byteval('T')); + bedlevel.display_map(parser.byteval('T')); SERIAL_ECHOPGM("Mesh is "); - if (!ubl.mesh_is_valid()) SERIAL_ECHOPGM("in"); - SERIAL_ECHOLNPGM("valid\nStorage slot: ", ubl.storage_slot); + if (!bedlevel.mesh_is_valid()) SERIAL_ECHOPGM("in"); + SERIAL_ECHOLNPGM("valid\nStorage slot: ", bedlevel.storage_slot); } #endif // AUTO_BED_LEVELING_UBL @@ -148,7 +148,7 @@ void GcodeSuite::M420() { #if ENABLED(AUTO_BED_LEVELING_UBL) set_bed_leveling_enabled(false); - ubl.adjust_mesh_to_mean(true, cval); + bedlevel.adjust_mesh_to_mean(true, cval); #else @@ -156,7 +156,7 @@ void GcodeSuite::M420() { // Get the sum and average of all mesh values float mesh_sum = 0; - GRID_LOOP(x, y) mesh_sum += Z_VALUES(x, y); + GRID_LOOP(x, y) mesh_sum += bedlevel.z_values[x][y]; const float zmean = mesh_sum / float(GRID_MAX_POINTS); #else // midrange @@ -164,7 +164,7 @@ void GcodeSuite::M420() { // Find the low and high mesh values. float lo_val = 100, hi_val = -100; GRID_LOOP(x, y) { - const float z = Z_VALUES(x, y); + const float z = bedlevel.z_values[x][y]; NOMORE(lo_val, z); NOLESS(hi_val, z); } @@ -178,10 +178,10 @@ void GcodeSuite::M420() { set_bed_leveling_enabled(false); // Subtract the mean from all values GRID_LOOP(x, y) { - Z_VALUES(x, y) -= zmean; - TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(x, y, Z_VALUES(x, y))); + bedlevel.z_values[x][y] -= zmean; + TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(x, y, bedlevel.z_values[x][y])); } - TERN_(AUTO_BED_LEVELING_BILINEAR, bbl.refresh_bed_level()); + TERN_(AUTO_BED_LEVELING_BILINEAR, bedlevel.refresh_bed_level()); } #endif @@ -202,10 +202,10 @@ void GcodeSuite::M420() { #else if (leveling_is_valid()) { #if ENABLED(AUTO_BED_LEVELING_BILINEAR) - bbl.print_leveling_grid(); + bedlevel.print_leveling_grid(); #elif ENABLED(MESH_BED_LEVELING) SERIAL_ECHOLNPGM("Mesh Bed Level data:"); - mbl.report_mesh(); + bedlevel.report_mesh(); #endif } #endif diff --git a/Marlin/src/gcode/bedlevel/abl/G29.cpp b/Marlin/src/gcode/bedlevel/abl/G29.cpp index af3daf2b96..a682aceb93 100644 --- a/Marlin/src/gcode/bedlevel/abl/G29.cpp +++ b/Marlin/src/gcode/bedlevel/abl/G29.cpp @@ -74,10 +74,18 @@ #endif #endif -#define G29_RETURN(retry) do{ \ - if (TERN(G29_RETRY_AND_RECOVER, !retry, true)) { \ - TERN_(FULL_REPORT_TO_HOST_FEATURE, set_and_report_grblstate(M_IDLE, false)); \ - } \ +static void pre_g29_return(const bool retry, const bool did) { + if (!retry) { + TERN_(FULL_REPORT_TO_HOST_FEATURE, set_and_report_grblstate(M_IDLE, false)); + } + if (did) { + TERN_(HAS_DWIN_E3V2_BASIC, DWIN_LevelingDone()); + TERN_(EXTENSIBLE_UI, ExtUI::onLevelingDone()); + } +} + +#define G29_RETURN(retry, did) do{ \ + pre_g29_return(TERN0(G29_RETRY_AND_RECOVER, retry), did); \ return TERN_(G29_RETRY_AND_RECOVER, retry); \ }while(0) @@ -233,7 +241,7 @@ G29_TYPE GcodeSuite::G29() { // G29 Q is also available if debugging #if ENABLED(DEBUG_LEVELING_FEATURE) if (seenQ || DEBUGGING(LEVELING)) log_machine_info(); - if (DISABLED(PROBE_MANUALLY) && seenQ) G29_RETURN(false); + if (DISABLED(PROBE_MANUALLY) && seenQ) G29_RETURN(false, false); #endif // A = Abort manual probing @@ -245,7 +253,7 @@ G29_TYPE GcodeSuite::G29() { // O = Don't level if leveling is already active if (!no_action && planner.leveling_active && parser.boolval('O')) { if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("> Auto-level not needed, skip"); - G29_RETURN(false); + G29_RETURN(false, false); } // Send 'N' to force homing before G29 (internal only) @@ -253,7 +261,7 @@ G29_TYPE GcodeSuite::G29() { process_subcommands_now(TERN(CAN_SET_LEVELING_AFTER_G28, F("G28L0"), FPSTR(G28_STR))); // Don't allow auto-leveling without homing first - if (homing_needed_error()) G29_RETURN(false); + if (homing_needed_error()) G29_RETURN(false, false); // 3-point leveling gets points from the probe class #if ENABLED(AUTO_BED_LEVELING_3POINT) @@ -291,13 +299,13 @@ G29_TYPE GcodeSuite::G29() { if (seen_w) { if (!leveling_is_valid()) { SERIAL_ERROR_MSG("No bilinear grid"); - G29_RETURN(false); + G29_RETURN(false, false); } const float rz = parser.seenval('Z') ? RAW_Z_POSITION(parser.value_linear_units()) : current_position.z; if (!WITHIN(rz, -10, 10)) { SERIAL_ERROR_MSG("Bad Z value"); - G29_RETURN(false); + G29_RETURN(false, false); } const float rx = RAW_X_POSITION(parser.linearval('X', NAN)), @@ -309,8 +317,8 @@ G29_TYPE GcodeSuite::G29() { if (!isnan(rx) && !isnan(ry)) { // Get nearest i / j from rx / ry - i = (rx - bbl.get_grid_start().x) / bbl.get_grid_spacing().x + 0.5f; - j = (ry - bbl.get_grid_start().y) / bbl.get_grid_spacing().y + 0.5f; + i = (rx - bedlevel.grid_start.x) / bedlevel.grid_spacing.x + 0.5f; + j = (ry - bedlevel.grid_start.y) / bedlevel.grid_spacing.y + 0.5f; LIMIT(i, 0, (GRID_MAX_POINTS_X) - 1); LIMIT(j, 0, (GRID_MAX_POINTS_Y) - 1); } @@ -319,13 +327,15 @@ G29_TYPE GcodeSuite::G29() { if (WITHIN(i, 0, (GRID_MAX_POINTS_X) - 1) && WITHIN(j, 0, (GRID_MAX_POINTS_Y) - 1)) { set_bed_leveling_enabled(false); - Z_VALUES_ARR[i][j] = rz; - bbl.refresh_bed_level(); + bedlevel.z_values[i][j] = rz; + bedlevel.refresh_bed_level(); TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(i, j, rz)); - set_bed_leveling_enabled(abl.reenable); - if (abl.reenable) report_current_position(); + if (abl.reenable) { + set_bed_leveling_enabled(true); + report_current_position(); + } } - G29_RETURN(false); + G29_RETURN(false, false); } // parser.seen_test('W') #else @@ -337,13 +347,13 @@ G29_TYPE GcodeSuite::G29() { // Jettison bed leveling data if (!seen_w && parser.seen_test('J')) { reset_bed_level(); - G29_RETURN(false); + G29_RETURN(false, false); } abl.verbose_level = parser.intval('V'); if (!WITHIN(abl.verbose_level, 0, 4)) { SERIAL_ECHOLNPGM("?(V)erbose level implausible (0-4)."); - G29_RETURN(false); + G29_RETURN(false, false); } abl.dryrun = parser.boolval('D') || TERN0(PROBE_MANUALLY, no_action); @@ -364,11 +374,11 @@ G29_TYPE GcodeSuite::G29() { if (!WITHIN(abl.grid_points.x, 2, GRID_MAX_POINTS_X)) { SERIAL_ECHOLNPGM("?Probe points (X) implausible (2-" STRINGIFY(GRID_MAX_POINTS_X) ")."); - G29_RETURN(false); + G29_RETURN(false, false); } if (!WITHIN(abl.grid_points.y, 2, GRID_MAX_POINTS_Y)) { SERIAL_ECHOLNPGM("?Probe points (Y) implausible (2-" STRINGIFY(GRID_MAX_POINTS_Y) ")."); - G29_RETURN(false); + G29_RETURN(false, false); } abl.abl_points = abl.grid_points.x * abl.grid_points.y; @@ -403,7 +413,7 @@ G29_TYPE GcodeSuite::G29() { " F", abl.probe_position_lf.y, " B", abl.probe_position_rb.y); } SERIAL_ECHOLNPGM("? (L,R,F,B) out of bounds."); - G29_RETURN(false); + G29_RETURN(false, false); } // Probe at the points of a lattice grid @@ -420,20 +430,26 @@ G29_TYPE GcodeSuite::G29() { planner.synchronize(); - TERN_(EXTENSIBLE_UI, ExtUI::onLevelingStart()); - #if ENABLED(AUTO_BED_LEVELING_3POINT) if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("> 3-point Leveling"); points[0].z = points[1].z = points[2].z = 0; // Probe at 3 arbitrary points #elif ENABLED(AUTO_BED_LEVELING_BILINEAR) - TERN_(DWIN_CREALITY_LCD_ENHANCED, DWIN_LevelingStart()); + TERN_(DWIN_LCD_PROUI, DWIN_LevelingStart()); #endif + TERN_(EXTENSIBLE_UI, ExtUI::onLevelingStart()); + if (!faux) { remember_feedrate_scaling_off(); #if ENABLED(PREHEAT_BEFORE_LEVELING) - if (!abl.dryrun) probe.preheat_for_probing(LEVELING_NOZZLE_TEMP, LEVELING_BED_TEMP); + if (!abl.dryrun) probe.preheat_for_probing(LEVELING_NOZZLE_TEMP, + #if BOTH(DWIN_LCD_PROUI, HAS_HEATED_BED) + HMI_data.BedLevT + #else + LEVELING_BED_TEMP + #endif + ); #endif } @@ -483,13 +499,13 @@ G29_TYPE GcodeSuite::G29() { #elif HAS_BED_PROBE if (probe.deploy()) { // (returns true on deploy failure) set_bed_leveling_enabled(abl.reenable); - G29_RETURN(false); + G29_RETURN(false, true); } #endif #if ENABLED(AUTO_BED_LEVELING_BILINEAR) if (!abl.dryrun - && (abl.gridSpacing != bbl.get_grid_spacing() || abl.probe_position_lf != bbl.get_grid_start()) + && (abl.gridSpacing != bedlevel.grid_spacing || abl.probe_position_lf != bedlevel.grid_start) ) { // Reset grid to 0.0 or "not probed". (Also disables ABL) reset_bed_level(); @@ -497,6 +513,10 @@ G29_TYPE GcodeSuite::G29() { // Can't re-enable (on error) until the new grid is written abl.reenable = false; } + + // Pre-populate local Z values from the stored mesh + TERN_(IS_KINEMATIC, COPY(abl.z_values, bedlevel.z_values)); + #endif // AUTO_BED_LEVELING_BILINEAR } // !g29_in_progress @@ -529,7 +549,7 @@ G29_TYPE GcodeSuite::G29() { } // For 'A' or 'Q' exit with success state - if (no_action) G29_RETURN(false); + if (no_action) G29_RETURN(false, true); if (abl.abl_probe_index == 0) { // For the initial G29 S2 save software endstop state @@ -604,14 +624,13 @@ G29_TYPE GcodeSuite::G29() { // Disable software endstops to allow manual adjustment // If G29 is not completed, they will not be re-enabled SET_SOFT_ENDSTOP_LOOSE(true); - G29_RETURN(false); + G29_RETURN(false, true); } else { // Leveling done! Fall through to G29 finishing code below SERIAL_ECHOLNPGM("Grid probing done."); // Re-enable software endstops, if needed SET_SOFT_ENDSTOP_LOOSE(false); - TERN_(EXTENSIBLE_UI, ExtUI::onLevelingDone()); } #elif ENABLED(AUTO_BED_LEVELING_3POINT) @@ -623,7 +642,7 @@ G29_TYPE GcodeSuite::G29() { // Disable software endstops to allow manual adjustment // If G29 is not completed, they will not be re-enabled SET_SOFT_ENDSTOP_LOOSE(true); - G29_RETURN(false); + G29_RETURN(false, true); } else { @@ -641,8 +660,6 @@ G29_TYPE GcodeSuite::G29() { abl.reenable = false; } - TERN_(EXTENSIBLE_UI, ExtUI::onLevelingDone()); - } #endif // AUTO_BED_LEVELING_3POINT @@ -657,8 +674,6 @@ G29_TYPE GcodeSuite::G29() { bool zig = PR_OUTER_SIZE & 1; // Always end at RIGHT and BACK_PROBE_BED_POSITION - abl.measured_z = 0; - // Outer loop is X with PROBE_Y_FIRST enabled // Outer loop is Y with PROBE_Y_FIRST disabled for (PR_OUTER_VAR = 0; PR_OUTER_VAR < PR_OUTER_SIZE && !isnan(abl.measured_z); PR_OUTER_VAR++) { @@ -720,7 +735,7 @@ G29_TYPE GcodeSuite::G29() { #endif - abl.reenable = false; + abl.reenable = false; // Don't re-enable after modifying the mesh idle_no_sleep(); } // inner @@ -787,14 +802,14 @@ G29_TYPE GcodeSuite::G29() { #if ENABLED(AUTO_BED_LEVELING_BILINEAR) if (abl.dryrun) - bbl.print_leveling_grid(&abl.z_values); + bedlevel.print_leveling_grid(&abl.z_values); else { - bbl.set_grid(abl.gridSpacing, abl.probe_position_lf); - COPY(Z_VALUES_ARR, abl.z_values); - TERN_(IS_KINEMATIC, bbl.extrapolate_unprobed_bed_level()); - bbl.refresh_bed_level(); + bedlevel.set_grid(abl.gridSpacing, abl.probe_position_lf); + COPY(bedlevel.z_values, abl.z_values); + TERN_(IS_KINEMATIC, bedlevel.extrapolate_unprobed_bed_level()); + bedlevel.refresh_bed_level(); - bbl.print_leveling_grid(); + bedlevel.print_leveling_grid(); } #elif ENABLED(AUTO_BED_LEVELING_LINEAR) @@ -905,33 +920,28 @@ G29_TYPE GcodeSuite::G29() { current_position = converted; if (DEBUGGING(LEVELING)) DEBUG_POS("G29 corrected XYZ", current_position); + + abl.reenable = true; + } + + // Auto Bed Leveling is complete! Enable if possible. + if (abl.reenable) { + planner.leveling_active = true; + sync_plan_position(); } #elif ENABLED(AUTO_BED_LEVELING_BILINEAR) - if (!abl.dryrun) { - if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("G29 uncorrected Z:", current_position.z); + // Auto Bed Leveling is complete! Enable if possible. + if (!abl.dryrun || abl.reenable) set_bed_leveling_enabled(true); - // Unapply the offset because it is going to be immediately applied - // and cause compensation movement in Z - const float fade_scaling_factor = TERN(ENABLE_LEVELING_FADE_HEIGHT, planner.fade_scaling_factor_for_z(current_position.z), 1); - current_position.z -= fade_scaling_factor * bbl.get_z_correction(current_position); + #endif - if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM(" corrected Z:", current_position.z); - } - - #endif // ABL_PLANAR - - // Auto Bed Leveling is complete! Enable if possible. - planner.leveling_active = !abl.dryrun || abl.reenable; } // !isnan(abl.measured_z) // Restore state after probing if (!faux) restore_feedrate_and_scaling(); - // Sync the planner from the current_position - if (planner.leveling_active) sync_plan_position(); - TERN_(HAS_BED_PROBE, probe.move_z_after_probing()); #ifdef Z_PROBE_END_SCRIPT @@ -946,8 +956,7 @@ G29_TYPE GcodeSuite::G29() { report_current_position(); - G29_RETURN(isnan(abl.measured_z)); - + G29_RETURN(isnan(abl.measured_z), true); } #endif // HAS_ABL_NOT_UBL diff --git a/Marlin/src/gcode/bedlevel/abl/M421.cpp b/Marlin/src/gcode/bedlevel/abl/M421.cpp index 0c12268cb1..3272ea1bd2 100644 --- a/Marlin/src/gcode/bedlevel/abl/M421.cpp +++ b/Marlin/src/gcode/bedlevel/abl/M421.cpp @@ -58,11 +58,11 @@ void GcodeSuite::M421() { sy = iy >= 0 ? iy : 0, ey = iy >= 0 ? iy : GRID_MAX_POINTS_Y - 1; LOOP_S_LE_N(x, sx, ex) { LOOP_S_LE_N(y, sy, ey) { - Z_VALUES_ARR[x][y] = zval + (hasQ ? Z_VALUES_ARR[x][y] : 0); - TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(x, y, Z_VALUES_ARR[x][y])); + bedlevel.z_values[x][y] = zval + (hasQ ? bedlevel.z_values[x][y] : 0); + TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(x, y, bedlevel.z_values[x][y])); } } - bbl.refresh_bed_level(); + bedlevel.refresh_bed_level(); } else SERIAL_ERROR_MSG(STR_ERR_MESH_XY); diff --git a/Marlin/src/gcode/bedlevel/mbl/G29.cpp b/Marlin/src/gcode/bedlevel/mbl/G29.cpp index e04073b122..b9440f78b2 100644 --- a/Marlin/src/gcode/bedlevel/mbl/G29.cpp +++ b/Marlin/src/gcode/bedlevel/mbl/G29.cpp @@ -93,14 +93,14 @@ void GcodeSuite::G29() { SERIAL_ECHOPGM("Mesh Bed Leveling "); if (leveling_is_valid()) { serialprintln_onoff(planner.leveling_active); - mbl.report_mesh(); + bedlevel.report_mesh(); } else SERIAL_ECHOLNPGM("has no data."); break; case MeshStart: - mbl.reset(); + bedlevel.reset(); mbl_probe_index = 0; if (!ui.wait_for_move) { queue.inject(parser.seen_test('N') ? F("G28" TERN(CAN_SET_LEVELING_AFTER_G28, "L0", "") "\nG29S2") : F("G29S2")); @@ -165,7 +165,7 @@ void GcodeSuite::G29() { } else { // Save Z for the previous mesh position - mbl.set_zigzag_z(mbl_probe_index - 1, current_position.z); + bedlevel.set_zigzag_z(mbl_probe_index - 1, current_position.z); TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(ix, iy, current_position.z)); TERN_(DWIN_LCD_PROUI, DWIN_MeshUpdate(_MIN(mbl_probe_index, GRID_MAX_POINTS), int(GRID_MAX_POINTS), current_position.z)); SET_SOFT_ENDSTOP_LOOSE(false); @@ -175,8 +175,8 @@ void GcodeSuite::G29() { // Disable software endstops to allow manual adjustment // If G29 is left hanging without completion they won't be re-enabled! SET_SOFT_ENDSTOP_LOOSE(true); - mbl.zigzag(mbl_probe_index++, ix, iy); - _manual_goto_xy({ mbl.index_to_xpos[ix], mbl.index_to_ypos[iy] }); + bedlevel.zigzag(mbl_probe_index++, ix, iy); + _manual_goto_xy({ bedlevel.index_to_xpos[ix], bedlevel.index_to_ypos[iy] }); } else { // Move to the after probing position @@ -232,9 +232,9 @@ void GcodeSuite::G29() { return echo_not_entered('J'); if (parser.seenval('Z')) { - mbl.z_values[ix][iy] = parser.value_linear_units(); - TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(ix, iy, mbl.z_values[ix][iy])); - TERN_(DWIN_LCD_PROUI, DWIN_MeshUpdate(ix, iy, mbl.z_values[ix][iy])); + bedlevel.z_values[ix][iy] = parser.value_linear_units(); + TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(ix, iy, bedlevel.z_values[ix][iy])); + TERN_(DWIN_LCD_PROUI, DWIN_MeshUpdate(ix, iy, bedlevel.z_values[ix][iy])); } else return echo_not_entered('Z'); @@ -242,7 +242,7 @@ void GcodeSuite::G29() { case MeshSetZOffset: if (parser.seenval('Z')) - mbl.z_offset = parser.value_linear_units(); + bedlevel.z_offset = parser.value_linear_units(); else return echo_not_entered('Z'); break; diff --git a/Marlin/src/gcode/bedlevel/mbl/M421.cpp b/Marlin/src/gcode/bedlevel/mbl/M421.cpp index 1368ab0bef..e23683d55f 100644 --- a/Marlin/src/gcode/bedlevel/mbl/M421.cpp +++ b/Marlin/src/gcode/bedlevel/mbl/M421.cpp @@ -43,9 +43,9 @@ */ void GcodeSuite::M421() { const bool hasX = parser.seen('X'), hasI = parser.seen('I'); - const int8_t ix = hasI ? parser.value_int() : hasX ? mbl.probe_index_x(RAW_X_POSITION(parser.value_linear_units())) : -1; + const int8_t ix = hasI ? parser.value_int() : hasX ? bedlevel.probe_index_x(RAW_X_POSITION(parser.value_linear_units())) : -1; const bool hasY = parser.seen('Y'), hasJ = parser.seen('J'); - const int8_t iy = hasJ ? parser.value_int() : hasY ? mbl.probe_index_y(RAW_Y_POSITION(parser.value_linear_units())) : -1; + const int8_t iy = hasJ ? parser.value_int() : hasY ? bedlevel.probe_index_y(RAW_Y_POSITION(parser.value_linear_units())) : -1; const bool hasZ = parser.seen('Z'), hasQ = !hasZ && parser.seen('Q'); if (int(hasI && hasJ) + int(hasX && hasY) != 1 || !(hasZ || hasQ)) @@ -53,7 +53,7 @@ void GcodeSuite::M421() { else if (ix < 0 || iy < 0) SERIAL_ERROR_MSG(STR_ERR_MESH_XY); else - mbl.set_z(ix, iy, parser.value_linear_units() + (hasQ ? mbl.z_values[ix][iy] : 0)); + bedlevel.set_z(ix, iy, parser.value_linear_units() + (hasQ ? bedlevel.z_values[ix][iy] : 0)); } #endif // MESH_BED_LEVELING diff --git a/Marlin/src/gcode/bedlevel/ubl/G29.cpp b/Marlin/src/gcode/bedlevel/ubl/G29.cpp index 932503d72b..90deab3d2e 100644 --- a/Marlin/src/gcode/bedlevel/ubl/G29.cpp +++ b/Marlin/src/gcode/bedlevel/ubl/G29.cpp @@ -39,7 +39,7 @@ void GcodeSuite::G29() { TERN_(FULL_REPORT_TO_HOST_FEATURE, set_and_report_grblstate(M_PROBE)); - ubl.G29(); + bedlevel.G29(); TERN_(FULL_REPORT_TO_HOST_FEATURE, set_and_report_grblstate(M_IDLE)); } diff --git a/Marlin/src/gcode/bedlevel/ubl/M421.cpp b/Marlin/src/gcode/bedlevel/ubl/M421.cpp index c11a20ebf3..ff74f4c6f7 100644 --- a/Marlin/src/gcode/bedlevel/ubl/M421.cpp +++ b/Marlin/src/gcode/bedlevel/ubl/M421.cpp @@ -56,7 +56,7 @@ void GcodeSuite::M421() { hasZ = parser.seen('Z'), hasQ = !hasZ && parser.seen('Q'); - if (hasC) ij = ubl.find_closest_mesh_point_of_type(CLOSEST, current_position); + if (hasC) ij = bedlevel.find_closest_mesh_point_of_type(CLOSEST, current_position); // Test for bad parameter combinations if (int(hasC) + int(hasI && hasJ) != 1 || !(hasZ || hasQ || hasN)) @@ -66,7 +66,7 @@ void GcodeSuite::M421() { else if (!WITHIN(ij.x, 0, GRID_MAX_POINTS_X - 1) || !WITHIN(ij.y, 0, GRID_MAX_POINTS_Y - 1)) SERIAL_ERROR_MSG(STR_ERR_MESH_XY); else { - float &zval = ubl.z_values[ij.x][ij.y]; // Altering this Mesh Point + float &zval = bedlevel.z_values[ij.x][ij.y]; // Altering this Mesh Point zval = hasN ? NAN : parser.value_linear_units() + (hasQ ? zval : 0); // N=NAN, Z=NEWVAL, or Q=ADDVAL TERN_(EXTENSIBLE_UI, ExtUI::onMeshUpdate(ij.x, ij.y, zval)); // Ping ExtUI in case it's showing the mesh TERN_(DWIN_LCD_PROUI, DWIN_MeshUpdate(ij.x, ij.y, zval)); diff --git a/Marlin/src/gcode/calibrate/G28.cpp b/Marlin/src/gcode/calibrate/G28.cpp index 07896856a1..e312bf07b5 100644 --- a/Marlin/src/gcode/calibrate/G28.cpp +++ b/Marlin/src/gcode/calibrate/G28.cpp @@ -55,11 +55,7 @@ #include "../../lcd/e3v2/proui/dwin.h" #endif -#if HAS_L64XX // set L6470 absolute position registers to counts - #include "../../libs/L64XX/L64XX_Marlin.h" -#endif - -#if ENABLED(LASER_MOVE_G28_OFF) +#if ENABLED(LASER_FEATURE) #include "../../feature/spindle_laser.h" #endif @@ -169,7 +165,7 @@ motion_state.jerk_state = planner.max_jerk; planner.max_jerk.set(0, 0 OPTARG(DELTA, 0)); #endif - planner.reset_acceleration_rates(); + planner.refresh_acceleration_rates(); return motion_state; } @@ -178,7 +174,7 @@ planner.settings.max_acceleration_mm_per_s2[Y_AXIS] = motion_state.acceleration.y; TERN_(DELTA, planner.settings.max_acceleration_mm_per_s2[Z_AXIS] = motion_state.acceleration.z); TERN_(HAS_CLASSIC_JERK, planner.max_jerk = motion_state.jerk_state); - planner.reset_acceleration_rates(); + planner.refresh_acceleration_rates(); } #endif // IMPROVE_HOMING_RELIABILITY @@ -205,7 +201,12 @@ void GcodeSuite::G28() { DEBUG_SECTION(log_G28, "G28", DEBUGGING(LEVELING)); if (DEBUGGING(LEVELING)) log_machine_info(); - TERN_(LASER_MOVE_G28_OFF, cutter.set_inline_enabled(false)); // turn off laser + /* + * Set the laser power to false to stop the planner from processing the current power setting. + */ + #if ENABLED(LASER_FEATURE) + planner.laser_inline.status.isPowered = false; + #endif #if ENABLED(DUAL_X_CARRIAGE) bool IDEX_saved_duplication_state = extruder_duplication_enabled; @@ -321,6 +322,9 @@ void GcodeSuite::G28() { stepperW.rms_current(W_CURRENT_HOME); if (DEBUGGING(LEVELING)) debug_current(F(STR_W), tmc_save_current_W, W_CURRENT_HOME); #endif + #if SENSORLESS_STALLGUARD_DELAY + safe_delay(SENSORLESS_STALLGUARD_DELAY); // Short delay needed to settle + #endif #endif #if ENABLED(IMPROVE_HOMING_RELIABILITY) @@ -375,7 +379,7 @@ void GcodeSuite::G28() { homeZZ = homeZ, homeI = needI || parser.seen_test(AXIS4_NAME), homeJ = needJ || parser.seen_test(AXIS5_NAME), homeK = needK || parser.seen_test(AXIS6_NAME), homeU = needU || parser.seen_test(AXIS7_NAME), - homeV = needV || parser.seen_test(AXIS8_NAME), homeW = needW || parser.seen_test(AXIS9_NAME), + homeV = needV || parser.seen_test(AXIS8_NAME), homeW = needW || parser.seen_test(AXIS9_NAME) ), home_all = NUM_AXIS_GANG( // Home-all if all or none are flagged homeX == homeX, && homeY == homeX, && homeZ == homeX, @@ -576,6 +580,9 @@ void GcodeSuite::G28() { #if HAS_CURRENT_HOME(W) stepperW.rms_current(tmc_save_current_W); #endif + #if SENSORLESS_STALLGUARD_DELAY + safe_delay(SENSORLESS_STALLGUARD_DELAY); // Short delay needed to settle + #endif #endif // HAS_HOMING_CURRENT ui.refresh(); @@ -590,20 +597,4 @@ void GcodeSuite::G28() { TERN_(FULL_REPORT_TO_HOST_FEATURE, set_and_report_grblstate(old_grblstate)); - #if HAS_L64XX - // Set L6470 absolute position registers to counts - // constexpr *might* move this to PROGMEM. - // If not, this will need a PROGMEM directive and an accessor. - #define _EN_ITEM(N) , E_AXIS - static constexpr AxisEnum L64XX_axis_xref[MAX_L64XX] = { - NUM_AXIS_LIST(X_AXIS, Y_AXIS, Z_AXIS, I_AXIS, J_AXIS, K_AXIS, U_AXIS, V_AXIS, W_AXIS), - X_AXIS, Y_AXIS, Z_AXIS, Z_AXIS, Z_AXIS - REPEAT(E_STEPPERS, _EN_ITEM) - }; - #undef _EN_ITEM - for (uint8_t j = 1; j <= L64XX::chain[0]; j++) { - const uint8_t cv = L64XX::chain[j]; - L64xxManager.set_param((L64XX_axis_t)cv, L6470_ABS_POS, stepper.position(L64XX_axis_xref[cv])); - } - #endif } diff --git a/Marlin/src/gcode/calibrate/G33.cpp b/Marlin/src/gcode/calibrate/G33.cpp index 7f487abd6b..ffe53b63fb 100644 --- a/Marlin/src/gcode/calibrate/G33.cpp +++ b/Marlin/src/gcode/calibrate/G33.cpp @@ -71,9 +71,9 @@ float lcd_probe_pt(const xy_pos_t &xy); void ac_home() { endstops.enable(true); - TERN_(HAS_DELTA_SENSORLESS_PROBING, probe.set_homing_current(true)); + TERN_(SENSORLESS_HOMING, endstops.set_homing_current(true)); home_delta(); - TERN_(HAS_DELTA_SENSORLESS_PROBING, probe.set_homing_current(false)); + TERN_(SENSORLESS_HOMING, endstops.set_homing_current(false)); endstops.not_homing(); } @@ -390,6 +390,8 @@ static float auto_tune_a(const float dcr) { * X Don't activate stallguard on X. * Y Don't activate stallguard on Y. * Z Don't activate stallguard on Z. + * + * S Save offset_sensorless_adj */ void GcodeSuite::G33() { @@ -411,7 +413,8 @@ void GcodeSuite::G33() { dcr -= probe_at_offset ? _MAX(total_offset, PROBING_MARGIN) : total_offset; #endif NOMORE(dcr, DELTA_PRINTABLE_RADIUS); - if (parser.seenval('R')) dcr -= _MAX(parser.value_float(),0); + if (parser.seenval('R')) dcr -= _MAX(parser.value_float(), 0.0f); + TERN_(HAS_DELTA_SENSORLESS_PROBING, dcr *= sensorless_radius_factor); const float calibration_precision = parser.floatval('C', 0.0f); if (calibration_precision < 0) { @@ -434,9 +437,8 @@ void GcodeSuite::G33() { const bool stow_after_each = parser.seen_test('E'); #if HAS_DELTA_SENSORLESS_PROBING - probe.test_sensitivity.x = !parser.seen_test('X'); - TERN_(HAS_Y_AXIS, probe.test_sensitivity.y = !parser.seen_test('Y')); - TERN_(HAS_Z_AXIS, probe.test_sensitivity.z = !parser.seen_test('Z')); + probe.test_sensitivity = { !parser.seen_test('X'), !parser.seen_test('Y'), !parser.seen_test('Z') }; + const bool do_save_offset_adj = parser.seen_test('S'); #endif const bool _0p_calibration = probe_points == 0, @@ -475,6 +477,25 @@ void GcodeSuite::G33() { if (!_0p_calibration) ac_home(); + #if HAS_DELTA_SENSORLESS_PROBING + if (verbose_level > 0 && do_save_offset_adj) { + offset_sensorless_adj.reset(); + + auto caltower = [&](Probe::sense_bool_t s){ + float z_at_pt[NPP + 1]; + LOOP_CAL_ALL(rad) z_at_pt[rad] = 0.0f; + probe.test_sensitivity = s; + if (probe_calibration_points(z_at_pt, 1, dcr, false, false, probe_at_offset)) + probe.set_offset_sensorless_adj(z_at_pt[CEN]); + }; + caltower({ true, false, false }); // A + caltower({ false, true, false }); // B + caltower({ false, false, true }); // C + + probe.test_sensitivity = { true, true, true }; // reset to all + } + #endif + do { // start iterations float z_at_pt[NPP + 1] = { 0.0f }; @@ -598,8 +619,17 @@ void GcodeSuite::G33() { // print report - if (verbose_level == 3 || verbose_level == 0) + if (verbose_level == 3 || verbose_level == 0) { print_calibration_results(z_at_pt, _tower_results, _opposite_results); + #if HAS_DELTA_SENSORLESS_PROBING + if (verbose_level == 0 && probe_points == 1) { + if (do_save_offset_adj) + probe.set_offset_sensorless_adj(z_at_pt[CEN]); + else + probe.refresh_largest_sensorless_adj(); + } + #endif + } if (verbose_level != 0) { // !dry run if ((zero_std_dev >= test_precision && iterations > force_iterations) || zero_std_dev <= calibration_precision) { // end iterations @@ -660,6 +690,9 @@ void GcodeSuite::G33() { ac_cleanup(TERN_(HAS_MULTI_HOTEND, old_tool_index)); TERN_(FULL_REPORT_TO_HOST_FEATURE, set_and_report_grblstate(M_IDLE)); + #if HAS_DELTA_SENSORLESS_PROBING + probe.test_sensitivity = { true, true, true }; + #endif } #endif // DELTA_AUTO_CALIBRATION diff --git a/Marlin/src/gcode/calibrate/G34.cpp b/Marlin/src/gcode/calibrate/G34.cpp index ea5d5fa150..6fdebb69b0 100644 --- a/Marlin/src/gcode/calibrate/G34.cpp +++ b/Marlin/src/gcode/calibrate/G34.cpp @@ -79,7 +79,7 @@ void GcodeSuite::G34() { stepper.set_digipot_current(Z_AXIS, target_current); #elif HAS_MOTOR_CURRENT_PWM const uint16_t target_current = parser.intval('S', GANTRY_CALIBRATION_CURRENT); - const uint32_t previous_current = stepper.motor_current_setting[Z_AXIS]; + const uint32_t previous_current = stepper.motor_current_setting[1]; // Z stepper.set_digipot_current(1, target_current); #elif HAS_MOTOR_CURRENT_DAC const float target_current = parser.floatval('S', GANTRY_CALIBRATION_CURRENT); @@ -91,7 +91,7 @@ void GcodeSuite::G34() { digipot_i2c.set_current(Z_AXIS, target_current) #elif HAS_TRINAMIC_CONFIG const uint16_t target_current = parser.intval('S', GANTRY_CALIBRATION_CURRENT); - static uint16_t previous_current_arr[NUM_Z_STEPPER_DRIVERS]; + static uint16_t previous_current_arr[NUM_Z_STEPPERS]; #if AXIS_IS_TMC(Z) previous_current_arr[0] = stepperZ.getMilliamps(); stepperZ.rms_current(target_current); diff --git a/Marlin/src/gcode/calibrate/G34_M422.cpp b/Marlin/src/gcode/calibrate/G34_M422.cpp index d1f82e7e98..455f51a18f 100644 --- a/Marlin/src/gcode/calibrate/G34_M422.cpp +++ b/Marlin/src/gcode/calibrate/G34_M422.cpp @@ -52,9 +52,9 @@ #define DEBUG_OUT ENABLED(DEBUG_LEVELING_FEATURE) #include "../../core/debug_out.h" -#if NUM_Z_STEPPER_DRIVERS >= 3 +#if NUM_Z_STEPPERS >= 3 #define TRIPLE_Z 1 - #if NUM_Z_STEPPER_DRIVERS >= 4 + #if NUM_Z_STEPPERS >= 4 #define QUAD_Z 1 #endif #endif @@ -180,11 +180,11 @@ void GcodeSuite::G34() { // This hack is un-done at the end of G34 - either by re-homing, or by using the probed heights of the last iteration. #if !HAS_Z_STEPPER_ALIGN_STEPPER_XY - float last_z_align_move[NUM_Z_STEPPER_DRIVERS] = ARRAY_N_1(NUM_Z_STEPPER_DRIVERS, 10000.0f); + float last_z_align_move[NUM_Z_STEPPERS] = ARRAY_N_1(NUM_Z_STEPPERS, 10000.0f); #else float last_z_align_level_indicator = 10000.0f; #endif - float z_measured[NUM_Z_STEPPER_DRIVERS] = { 0 }, + float z_measured[NUM_Z_STEPPERS] = { 0 }, z_maxdiff = 0.0f, amplification = z_auto_align_amplification; @@ -217,9 +217,9 @@ void GcodeSuite::G34() { float z_measured_max = -100000.0f; // Probe all positions (one per Z-Stepper) - LOOP_L_N(i, NUM_Z_STEPPER_DRIVERS) { + LOOP_L_N(i, NUM_Z_STEPPERS) { // iteration odd/even --> downward / upward stepper sequence - const uint8_t iprobe = (iteration & 1) ? NUM_Z_STEPPER_DRIVERS - 1 - i : i; + const uint8_t iprobe = (iteration & 1) ? NUM_Z_STEPPERS - 1 - i : i; // Safe clearance even on an incline if ((iteration == 0 || i > 0) && z_probe > current_position.z) do_blocking_move_to_z(z_probe); @@ -230,7 +230,7 @@ void GcodeSuite::G34() { // Probe a Z height for each stepper. // Probing sanity check is disabled, as it would trigger even in normal cases because // current_position.z has been manually altered in the "dirty trick" above. - const float z_probed_height = probe.probe_at_point(z_stepper_align.xy[iprobe], raise_after, 0, true, false); + const float z_probed_height = probe.probe_at_point(RAW_X_POSITION(z_stepper_align.xy[iprobe].x), RAW_Y_POSITION(z_stepper_align.xy[iprobe].y), raise_after, 0, true, false); if (isnan(z_probed_height)) { SERIAL_ECHOLNPGM("Probing failed"); LCD_MESSAGE(MSG_LCD_PROBING_FAILED); @@ -270,20 +270,20 @@ void GcodeSuite::G34() { // This allows the actual adjustment logic to be shared by both algorithms. linear_fit_data lfd; incremental_LSF_reset(&lfd); - LOOP_L_N(i, NUM_Z_STEPPER_DRIVERS) { + LOOP_L_N(i, NUM_Z_STEPPERS) { SERIAL_ECHOLNPGM("PROBEPT_", i, ": ", z_measured[i]); incremental_LSF(&lfd, z_stepper_align.xy[i], z_measured[i]); } finish_incremental_LSF(&lfd); z_measured_min = 100000.0f; - LOOP_L_N(i, NUM_Z_STEPPER_DRIVERS) { + LOOP_L_N(i, NUM_Z_STEPPERS) { z_measured[i] = -(lfd.A * z_stepper_align.stepper_xy[i].x + lfd.B * z_stepper_align.stepper_xy[i].y + lfd.D); z_measured_min = _MIN(z_measured_min, z_measured[i]); } SERIAL_ECHOLNPGM( - LIST_N(DOUBLE(NUM_Z_STEPPER_DRIVERS), + LIST_N(DOUBLE(NUM_Z_STEPPERS), "Calculated Z1=", z_measured[0], " Z2=", z_measured[1], " Z3=", z_measured[2], @@ -307,7 +307,7 @@ void GcodeSuite::G34() { #if HAS_STATUS_MESSAGE char fstr1[10]; - char msg[6 + (6 + 5) * NUM_Z_STEPPER_DRIVERS + 1] + char msg[6 + (6 + 5) * NUM_Z_STEPPERS + 1] #if TRIPLE_Z , fstr2[10], fstr3[10] #if QUAD_Z @@ -345,12 +345,12 @@ void GcodeSuite::G34() { // Calculate mean value as a reference float z_measured_mean = 0.0f; - LOOP_L_N(zstepper, NUM_Z_STEPPER_DRIVERS) z_measured_mean += z_measured[zstepper]; - z_measured_mean /= NUM_Z_STEPPER_DRIVERS; + LOOP_L_N(zstepper, NUM_Z_STEPPERS) z_measured_mean += z_measured[zstepper]; + z_measured_mean /= NUM_Z_STEPPERS; // Calculate the sum of the absolute deviations from the mean value float z_align_level_indicator = 0.0f; - LOOP_L_N(zstepper, NUM_Z_STEPPER_DRIVERS) + LOOP_L_N(zstepper, NUM_Z_STEPPERS) z_align_level_indicator += ABS(z_measured[zstepper] - z_measured_mean); // If it's getting worse, stop and throw an error @@ -365,7 +365,7 @@ void GcodeSuite::G34() { bool success_break = true; // Correct the individual stepper offsets - LOOP_L_N(zstepper, NUM_Z_STEPPER_DRIVERS) { + LOOP_L_N(zstepper, NUM_Z_STEPPERS) { // Calculate current stepper move float z_align_move = z_measured[zstepper] - z_measured_min; const float z_align_abs = ABS(z_align_move); @@ -515,9 +515,9 @@ void GcodeSuite::M422() { #endif } - if (!WITHIN(position_index, 1, NUM_Z_STEPPER_DRIVERS)) { + if (!WITHIN(position_index, 1, NUM_Z_STEPPERS)) { SERIAL_ECHOF(err_string); - SERIAL_ECHOLNPGM(" index invalid (1.." STRINGIFY(NUM_Z_STEPPER_DRIVERS) ")."); + SERIAL_ECHOLNPGM(" index invalid (1.." STRINGIFY(NUM_Z_STEPPERS) ")."); return; } @@ -544,7 +544,7 @@ void GcodeSuite::M422() { void GcodeSuite::M422_report(const bool forReplay/*=true*/) { report_heading(forReplay, F(STR_Z_AUTO_ALIGN)); - LOOP_L_N(i, NUM_Z_STEPPER_DRIVERS) { + LOOP_L_N(i, NUM_Z_STEPPERS) { report_echo_start(forReplay); SERIAL_ECHOLNPGM_P( PSTR(" M422 S"), i + 1, @@ -553,7 +553,7 @@ void GcodeSuite::M422_report(const bool forReplay/*=true*/) { ); } #if HAS_Z_STEPPER_ALIGN_STEPPER_XY - LOOP_L_N(i, NUM_Z_STEPPER_DRIVERS) { + LOOP_L_N(i, NUM_Z_STEPPERS) { report_echo_start(forReplay); SERIAL_ECHOLNPGM_P( PSTR(" M422 W"), i + 1, diff --git a/Marlin/src/gcode/calibrate/G425.cpp b/Marlin/src/gcode/calibrate/G425.cpp index 450a715117..a22608f5b4 100644 --- a/Marlin/src/gcode/calibrate/G425.cpp +++ b/Marlin/src/gcode/calibrate/G425.cpp @@ -438,26 +438,26 @@ inline void probe_sides(measurements_t &m, const float uncertainty) { #endif #if HAS_U_AXIS #if ENABLED(CALIBRATION_MEASURE_UMIN) - SERIAL_ECHOLNPAIR(" " STR_U_MIN ": ", m.obj_side[UMINIMUM]); + SERIAL_ECHOLNPGM(" " STR_U_MIN ": ", m.obj_side[UMINIMUM]); #endif #if ENABLED(CALIBRATION_MEASURE_UMAX) - SERIAL_ECHOLNPAIR(" " STR_U_MAX ": ", m.obj_side[UMAXIMUM]); + SERIAL_ECHOLNPGM(" " STR_U_MAX ": ", m.obj_side[UMAXIMUM]); #endif #endif #if HAS_V_AXIS #if ENABLED(CALIBRATION_MEASURE_VMIN) - SERIAL_ECHOLNPAIR(" " STR_V_MIN ": ", m.obj_side[VMINIMUM]); + SERIAL_ECHOLNPGM(" " STR_V_MIN ": ", m.obj_side[VMINIMUM]); #endif #if ENABLED(CALIBRATION_MEASURE_VMAX) - SERIAL_ECHOLNPAIR(" " STR_V_MAX ": ", m.obj_side[VMAXIMUM]); + SERIAL_ECHOLNPGM(" " STR_V_MAX ": ", m.obj_side[VMAXIMUM]); #endif #endif #if HAS_W_AXIS #if ENABLED(CALIBRATION_MEASURE_WMIN) - SERIAL_ECHOLNPAIR(" " STR_W_MIN ": ", m.obj_side[WMINIMUM]); + SERIAL_ECHOLNPGM(" " STR_W_MIN ": ", m.obj_side[WMINIMUM]); #endif #if ENABLED(CALIBRATION_MEASURE_WMAX) - SERIAL_ECHOLNPAIR(" " STR_W_MAX ": ", m.obj_side[WMAXIMUM]); + SERIAL_ECHOLNPGM(" " STR_W_MAX ": ", m.obj_side[WMAXIMUM]); #endif #endif SERIAL_EOL(); diff --git a/Marlin/src/gcode/calibrate/G76_M871.cpp b/Marlin/src/gcode/calibrate/G76_M871.cpp index ad13b20306..c484d4f1b7 100644 --- a/Marlin/src/gcode/calibrate/G76_M871.cpp +++ b/Marlin/src/gcode/calibrate/G76_M871.cpp @@ -82,13 +82,13 @@ * - `P` - Run probe temperature calibration. */ -static void say_waiting_for() { SERIAL_ECHOPGM("Waiting for "); } -static void say_waiting_for_probe_heating() { say_waiting_for(); SERIAL_ECHOLNPGM("probe heating."); } -static void say_successfully_calibrated() { SERIAL_ECHOPGM("Successfully calibrated"); } -static void say_failed_to_calibrate() { SERIAL_ECHOPGM("!Failed to calibrate"); } - #if BOTH(PTC_PROBE, PTC_BED) + static void say_waiting_for() { SERIAL_ECHOPGM("Waiting for "); } + static void say_waiting_for_probe_heating() { say_waiting_for(); SERIAL_ECHOLNPGM("probe heating."); } + static void say_successfully_calibrated() { SERIAL_ECHOPGM("Successfully calibrated"); } + static void say_failed_to_calibrate() { SERIAL_ECHOPGM("!Failed to calibrate"); } + void GcodeSuite::G76() { auto report_temps = [](millis_t &ntr, millis_t timeout=0) { idle_no_sleep(); diff --git a/Marlin/src/gcode/calibrate/M425.cpp b/Marlin/src/gcode/calibrate/M425.cpp index bfceefdbe2..a6c6ff9dae 100644 --- a/Marlin/src/gcode/calibrate/M425.cpp +++ b/Marlin/src/gcode/calibrate/M425.cpp @@ -47,26 +47,17 @@ void GcodeSuite::M425() { bool noArgs = true; auto axis_can_calibrate = [](const uint8_t a) { + #define _CAN_CASE(N) case N##_AXIS: return AXIS_CAN_CALIBRATE(N); switch (a) { default: return false; - NUM_AXIS_CODE( - case X_AXIS: return AXIS_CAN_CALIBRATE(X), - case Y_AXIS: return AXIS_CAN_CALIBRATE(Y), - case Z_AXIS: return AXIS_CAN_CALIBRATE(Z), - case I_AXIS: return AXIS_CAN_CALIBRATE(I), - case J_AXIS: return AXIS_CAN_CALIBRATE(J), - case K_AXIS: return AXIS_CAN_CALIBRATE(K), - case U_AXIS: return AXIS_CAN_CALIBRATE(U), - case V_AXIS: return AXIS_CAN_CALIBRATE(V), - case W_AXIS: return AXIS_CAN_CALIBRATE(W) - ); + MAIN_AXIS_MAP(_CAN_CASE) } }; LOOP_NUM_AXES(a) { if (axis_can_calibrate(a) && parser.seen(AXIS_CHAR(a))) { planner.synchronize(); - backlash.set_distance_mm(AxisEnum(a), parser.has_value() ? parser.value_axis_units(AxisEnum(a)) : backlash.get_measurement(AxisEnum(a))); + backlash.set_distance_mm((AxisEnum)a, parser.has_value() ? parser.value_axis_units((AxisEnum)a) : backlash.get_measurement((AxisEnum)a)); noArgs = false; } } @@ -92,9 +83,7 @@ void GcodeSuite::M425() { SERIAL_ECHOLNPGM(" Correction Amount/Fade-out: F", backlash.get_correction(), " (F1.0 = full, F0.0 = none)"); SERIAL_ECHOPGM(" Backlash Distance (mm): "); LOOP_NUM_AXES(a) if (axis_can_calibrate(a)) { - SERIAL_CHAR(' ', AXIS_CHAR(a)); - SERIAL_ECHO(backlash.get_distance_mm(AxisEnum(a))); - SERIAL_EOL(); + SERIAL_ECHOLNPGM_P((PGM_P)pgm_read_ptr(&SP_AXIS_STR[a]), backlash.get_distance_mm((AxisEnum)a)); } #ifdef BACKLASH_SMOOTHING_MM @@ -105,8 +94,7 @@ void GcodeSuite::M425() { SERIAL_ECHOPGM(" Average measured backlash (mm):"); if (backlash.has_any_measurement()) { LOOP_NUM_AXES(a) if (axis_can_calibrate(a) && backlash.has_measurement(AxisEnum(a))) { - SERIAL_CHAR(' ', AXIS_CHAR(a)); - SERIAL_ECHO(backlash.get_measurement(AxisEnum(a))); + SERIAL_ECHOPGM_P((PGM_P)pgm_read_ptr(&SP_AXIS_STR[a]), backlash.get_measurement((AxisEnum)a)); } } else diff --git a/Marlin/src/gcode/calibrate/M665.cpp b/Marlin/src/gcode/calibrate/M665.cpp index aa21471b60..7dc657a61b 100644 --- a/Marlin/src/gcode/calibrate/M665.cpp +++ b/Marlin/src/gcode/calibrate/M665.cpp @@ -86,13 +86,13 @@ * * Parameters: * - * S[segments-per-second] - Segments-per-second + * S[segments] - Segments-per-second * * Without NO_WORKSPACE_OFFSETS: * - * P[theta-psi-offset] - Theta-Psi offset, added to the shoulder (A/X) angle - * T[theta-offset] - Theta offset, added to the elbow (B/Y) angle - * Z[z-offset] - Z offset, added to Z + * P[theta-psi-offset] - Theta-Psi offset, added to the shoulder (A/X) angle + * T[theta-offset] - Theta offset, added to the elbow (B/Y) angle + * Z[z-offset] - Z offset, added to Z * * A, P, and X are all aliases for the shoulder angle * B, T, and Y are all aliases for the elbow angle @@ -152,18 +152,35 @@ * * Parameters: * - * S[segments-per-second] - Segments-per-second + * S[segments] - Segments-per-second + * L[left] - Work area minimum X + * R[right] - Work area maximum X + * T[top] - Work area maximum Y + * B[bottom] - Work area minimum Y + * H[length] - Maximum belt length */ void GcodeSuite::M665() { - if (parser.seenval('S')) - segments_per_second = parser.value_float(); - else - M665_report(); + if (!parser.seen_any()) return M665_report(); + if (parser.seenval('S')) segments_per_second = parser.value_float(); + if (parser.seenval('L')) draw_area_min.x = parser.value_linear_units(); + if (parser.seenval('R')) draw_area_max.x = parser.value_linear_units(); + if (parser.seenval('T')) draw_area_max.y = parser.value_linear_units(); + if (parser.seenval('B')) draw_area_min.y = parser.value_linear_units(); + if (parser.seenval('H')) polargraph_max_belt_len = parser.value_linear_units(); + draw_area_size.x = draw_area_max.x - draw_area_min.x; + draw_area_size.y = draw_area_max.y - draw_area_min.y; } void GcodeSuite::M665_report(const bool forReplay/*=true*/) { - report_heading_etc(forReplay, F(STR_POLARGRAPH_SETTINGS " (" STR_S_SEG_PER_SEC ")")); - SERIAL_ECHOLNPGM(" M665 S", segments_per_second); + report_heading_etc(forReplay, F(STR_POLARGRAPH_SETTINGS)); + SERIAL_ECHOLNPGM_P( + PSTR(" M665 S"), LINEAR_UNIT(segments_per_second), + PSTR(" L"), LINEAR_UNIT(draw_area_min.x), + PSTR(" R"), LINEAR_UNIT(draw_area_max.x), + SP_T_STR, LINEAR_UNIT(draw_area_max.y), + SP_B_STR, LINEAR_UNIT(draw_area_min.y), + PSTR(" H"), LINEAR_UNIT(polargraph_max_belt_len) + ); } #endif diff --git a/Marlin/src/gcode/calibrate/M666.cpp b/Marlin/src/gcode/calibrate/M666.cpp index fe244b21f7..90fad1811c 100644 --- a/Marlin/src/gcode/calibrate/M666.cpp +++ b/Marlin/src/gcode/calibrate/M666.cpp @@ -45,7 +45,7 @@ DEBUG_SECTION(log_M666, "M666", DEBUGGING(LEVELING)); bool is_err = false, is_set = false; LOOP_NUM_AXES(i) { - if (parser.seen(AXIS_CHAR(i))) { + if (parser.seenval(AXIS_CHAR(i))) { is_set = true; const float v = parser.value_linear_units(); if (v > 0) @@ -93,12 +93,12 @@ #if ENABLED(Z_MULTI_ENDSTOPS) if (parser.seenval('Z')) { const float z_adj = parser.value_linear_units(); - #if NUM_Z_STEPPER_DRIVERS == 2 + #if NUM_Z_STEPPERS == 2 endstops.z2_endstop_adj = z_adj; #else const int ind = parser.intval('S'); #define _SET_ZADJ(N) if (!ind || ind == N) endstops.z##N##_endstop_adj = z_adj; - REPEAT_S(2, INCREMENT(NUM_Z_STEPPER_DRIVERS), _SET_ZADJ) + REPEAT_S(2, INCREMENT(NUM_Z_STEPPERS), _SET_ZADJ) #endif } #endif @@ -114,11 +114,11 @@ SERIAL_ECHOLNPGM_P(SP_Y_STR, LINEAR_UNIT(endstops.y2_endstop_adj)); #endif #if ENABLED(Z_MULTI_ENDSTOPS) - #if NUM_Z_STEPPER_DRIVERS >= 3 + #if NUM_Z_STEPPERS >= 3 SERIAL_ECHOPGM(" S2 Z", LINEAR_UNIT(endstops.z3_endstop_adj)); report_echo_start(forReplay); SERIAL_ECHOPGM(" M666 S3 Z", LINEAR_UNIT(endstops.z3_endstop_adj)); - #if NUM_Z_STEPPER_DRIVERS >= 4 + #if NUM_Z_STEPPERS >= 4 report_echo_start(forReplay); SERIAL_ECHOPGM(" M666 S4 Z", LINEAR_UNIT(endstops.z4_endstop_adj)); #endif diff --git a/Marlin/src/gcode/config/M200-M205.cpp b/Marlin/src/gcode/config/M200-M205.cpp index 5e15ff65e8..87c1f2ce30 100644 --- a/Marlin/src/gcode/config/M200-M205.cpp +++ b/Marlin/src/gcode/config/M200-M205.cpp @@ -108,12 +108,21 @@ #endif // !NO_VOLUMETRICS /** - * M201: Set max acceleration in units/s^2 for print moves (M201 X1000 Y1000) + * M201: Set max acceleration in units/s^2 for print moves. * - * With multiple extruders use T to specify which one. + * X : Max Acceleration for X + * Y : Max Acceleration for Y + * Z : Max Acceleration for Z + * ... : etc + * E : Max Acceleration for Extruder + * T : Extruder index to set + * + * With XY_FREQUENCY_LIMIT: + * F : Frequency limit for XY...IJKUVW + * S : Speed factor percentage. */ void GcodeSuite::M201() { - if (!parser.seen("T" LOGICAL_AXES_STRING)) + if (!parser.seen("T" STR_AXES_LOGICAL TERN_(XY_FREQUENCY_LIMIT, "FS"))) return M201_report(); const int8_t target_extruder = get_target_extruder_from_command(); @@ -121,13 +130,13 @@ void GcodeSuite::M201() { #ifdef XY_FREQUENCY_LIMIT if (parser.seenval('F')) planner.set_frequency_limit(parser.value_byte()); - if (parser.seenval('G')) planner.xy_freq_min_speed_factor = constrain(parser.value_float(), 1, 100) / 100; + if (parser.seenval('S')) planner.xy_freq_min_speed_factor = constrain(parser.value_float(), 1, 100) / 100; #endif LOOP_LOGICAL_AXES(i) { - if (parser.seenval(axis_codes[i])) { - const uint8_t a = TERN(HAS_EXTRUDERS, (i == E_AXIS ? uint8_t(E_AXIS_N(target_extruder)) : i), i); - planner.set_max_acceleration(a, parser.value_axis_units((AxisEnum)a)); + if (parser.seenval(AXIS_CHAR(i))) { + const AxisEnum a = TERN(HAS_EXTRUDERS, (i == E_AXIS ? E_AXIS_N(target_extruder) : (AxisEnum)i), (AxisEnum)i); + planner.set_max_acceleration(a, parser.value_axis_units(a)); } } } @@ -144,7 +153,7 @@ void GcodeSuite::M201_report(const bool forReplay/*=true*/) { SP_K_STR, K_AXIS_UNIT(planner.settings.max_acceleration_mm_per_s2[K_AXIS]), SP_U_STR, U_AXIS_UNIT(planner.settings.max_acceleration_mm_per_s2[U_AXIS]), SP_V_STR, V_AXIS_UNIT(planner.settings.max_acceleration_mm_per_s2[V_AXIS]), - SP_W_STR, W_AXIS_UNIT(planner.settings.max_acceleration_mm_per_s2[W_AXIS]), + SP_W_STR, W_AXIS_UNIT(planner.settings.max_acceleration_mm_per_s2[W_AXIS]) ) #if HAS_EXTRUDERS && DISABLED(DISTINCT_E_FACTORS) , SP_E_STR, VOLUMETRIC_UNIT(planner.settings.max_acceleration_mm_per_s2[E_AXIS]) @@ -167,16 +176,16 @@ void GcodeSuite::M201_report(const bool forReplay/*=true*/) { * With multiple extruders use T to specify which one. */ void GcodeSuite::M203() { - if (!parser.seen("T" LOGICAL_AXES_STRING)) + if (!parser.seen("T" STR_AXES_LOGICAL)) return M203_report(); const int8_t target_extruder = get_target_extruder_from_command(); if (target_extruder < 0) return; LOOP_LOGICAL_AXES(i) - if (parser.seenval(axis_codes[i])) { - const uint8_t a = TERN(HAS_EXTRUDERS, (i == E_AXIS ? uint8_t(E_AXIS_N(target_extruder)) : i), i); - planner.set_max_feedrate(a, parser.value_axis_units((AxisEnum)a)); + if (parser.seenval(AXIS_CHAR(i))) { + const AxisEnum a = TERN(HAS_EXTRUDERS, (i == E_AXIS ? E_AXIS_N(target_extruder) : (AxisEnum)i), (AxisEnum)i); + planner.set_max_feedrate(a, parser.value_axis_units(a)); } } @@ -200,7 +209,7 @@ void GcodeSuite::M203_report(const bool forReplay/*=true*/) { ); #if ENABLED(DISTINCT_E_FACTORS) LOOP_L_N(i, E_STEPPERS) { - SERIAL_ECHO_START(); + if (!forReplay) SERIAL_ECHO_START(); SERIAL_ECHOLNPGM_P( PSTR(" M203 T"), i , SP_E_STR, VOLUMETRIC_UNIT(planner.settings.max_feedrate_mm_s[E_AXIS_N(i)]) diff --git a/Marlin/src/gcode/config/M217.cpp b/Marlin/src/gcode/config/M217.cpp index ad96b2b659..989e4d0870 100644 --- a/Marlin/src/gcode/config/M217.cpp +++ b/Marlin/src/gcode/config/M217.cpp @@ -34,31 +34,31 @@ #include "../../MarlinCore.h" // for SP_X_STR, etc. /** - * M217 - Set SINGLENOZZLE toolchange parameters + * M217 - Set toolchange parameters * * // Tool change command * Q Prime active tool and exit * * // Tool change settings - * S[linear] Swap length - * B[linear] Extra Swap length - * E[linear] Prime length - * P[linear/m] Prime speed - * R[linear/m] Retract speed - * U[linear/m] UnRetract speed - * V[linear] 0/1 Enable auto prime first extruder used - * W[linear] 0/1 Enable park & Z Raise - * X[linear] Park X (Requires TOOLCHANGE_PARK) - * Y[linear] Park Y (Requires TOOLCHANGE_PARK) - * I[linear] Park I (Requires TOOLCHANGE_PARK and NUM_AXES >= 4) - * J[linear] Park J (Requires TOOLCHANGE_PARK and NUM_AXES >= 5) - * K[linear] Park K (Requires TOOLCHANGE_PARK and NUM_AXES >= 6) - * C[linear] Park U (Requires TOOLCHANGE_PARK and NUM_AXES >= 7) - * H[linear] Park V (Requires TOOLCHANGE_PARK and NUM_AXES >= 8) - * O[linear] Park W (Requires TOOLCHANGE_PARK and NUM_AXES >= 9) - * Z[linear] Z Raise - * F[linear] Fan Speed 0-255 - * G[linear/s] Fan time + * S[linear] Swap length + * B[linear] Extra Swap resume length + * E[linear] Extra Prime length (as used by M217 Q) + * P[linear/min] Prime speed + * R[linear/min] Retract speed + * U[linear/min] UnRetract speed + * V[linear] 0/1 Enable auto prime first extruder used + * W[linear] 0/1 Enable park & Z Raise + * X[linear] Park X (Requires TOOLCHANGE_PARK) + * Y[linear] Park Y (Requires TOOLCHANGE_PARK) + * I[linear] Park I (Requires TOOLCHANGE_PARK and NUM_AXES >= 4) + * J[linear] Park J (Requires TOOLCHANGE_PARK and NUM_AXES >= 5) + * K[linear] Park K (Requires TOOLCHANGE_PARK and NUM_AXES >= 6) + * C[linear] Park U (Requires TOOLCHANGE_PARK and NUM_AXES >= 7) + * H[linear] Park V (Requires TOOLCHANGE_PARK and NUM_AXES >= 8) + * O[linear] Park W (Requires TOOLCHANGE_PARK and NUM_AXES >= 9) + * Z[linear] Z Raise + * F[speed] Fan Speed 0-255 + * D[seconds] Fan time * * Tool migration settings * A[0|1] Enable auto-migration on runout @@ -82,8 +82,8 @@ void GcodeSuite::M217() { if (parser.seenval('R')) { const int16_t v = parser.value_linear_units(); toolchange_settings.retract_speed = constrain(v, 10, 5400); } if (parser.seenval('U')) { const int16_t v = parser.value_linear_units(); toolchange_settings.unretract_speed = constrain(v, 10, 5400); } #if TOOLCHANGE_FS_FAN >= 0 && HAS_FAN - if (parser.seenval('F')) { const int16_t v = parser.value_linear_units(); toolchange_settings.fan_speed = constrain(v, 0, 255); } - if (parser.seenval('G')) { const int16_t v = parser.value_linear_units(); toolchange_settings.fan_time = constrain(v, 1, 30); } + if (parser.seenval('F')) { const uint16_t v = parser.value_ushort(); toolchange_settings.fan_speed = constrain(v, 0, 255); } + if (parser.seenval('D')) { const uint16_t v = parser.value_ushort(); toolchange_settings.fan_time = constrain(v, 1, 30); } #endif #endif @@ -171,7 +171,7 @@ void GcodeSuite::M217_report(const bool forReplay/*=true*/) { SERIAL_ECHOPGM(" R", LINEAR_UNIT(toolchange_settings.retract_speed), " U", LINEAR_UNIT(toolchange_settings.unretract_speed), " F", toolchange_settings.fan_speed, - " G", toolchange_settings.fan_time); + " D", toolchange_settings.fan_time); #if ENABLED(TOOLCHANGE_MIGRATION_FEATURE) SERIAL_ECHOPGM(" A", migration.automode); @@ -186,13 +186,13 @@ void GcodeSuite::M217_report(const bool forReplay/*=true*/) { , SP_Y_STR, LINEAR_UNIT(toolchange_settings.change_point.y) #endif #if SECONDARY_AXES >= 1 - , LIST_N(DOUBLE(SECONDARY_AXES), - PSTR(" I"), I_AXIS_UNIT(toolchange_settings.change_point.i), - PSTR(" J"), J_AXIS_UNIT(toolchange_settings.change_point.j), - PSTR(" K"), K_AXIS_UNIT(toolchange_settings.change_point.k), - SP_C_STR, U_AXIS_UNIT(toolchange_settings.change_point.u), - PSTR(" H"), V_AXIS_UNIT(toolchange_settings.change_point.v), - PSTR(" O"), W_AXIS_UNIT(toolchange_settings.change_point.w), + , LIST_N(DOUBLE(SECONDARY_AXES) + , SP_I_STR, I_AXIS_UNIT(toolchange_settings.change_point.i) + , SP_J_STR, J_AXIS_UNIT(toolchange_settings.change_point.j) + , SP_K_STR, K_AXIS_UNIT(toolchange_settings.change_point.k) + , SP_C_STR, U_AXIS_UNIT(toolchange_settings.change_point.u) + , PSTR(" H"), V_AXIS_UNIT(toolchange_settings.change_point.v) + , PSTR(" O"), W_AXIS_UNIT(toolchange_settings.change_point.w) ) #endif ); diff --git a/Marlin/src/gcode/config/M281.cpp b/Marlin/src/gcode/config/M281.cpp index b90de6be30..e4ef3ab40b 100644 --- a/Marlin/src/gcode/config/M281.cpp +++ b/Marlin/src/gcode/config/M281.cpp @@ -47,8 +47,8 @@ void GcodeSuite::M281() { return; } #endif - if (parser.seen('L')) servo_angles[servo_index][0] = parser.value_int(); - if (parser.seen('U')) servo_angles[servo_index][1] = parser.value_int(); + if (parser.seenval('L')) servo_angles[servo_index][0] = parser.value_int(); + if (parser.seenval('U')) servo_angles[servo_index][1] = parser.value_int(); } else SERIAL_ERROR_MSG("Servo ", servo_index, " out of range"); diff --git a/Marlin/src/gcode/config/M304.cpp b/Marlin/src/gcode/config/M304.cpp index 97dc4be25e..c970288238 100644 --- a/Marlin/src/gcode/config/M304.cpp +++ b/Marlin/src/gcode/config/M304.cpp @@ -36,9 +36,9 @@ */ void GcodeSuite::M304() { if (!parser.seen("PID")) return M304_report(); - if (parser.seen('P')) thermalManager.temp_bed.pid.Kp = parser.value_float(); - if (parser.seen('I')) thermalManager.temp_bed.pid.Ki = scalePID_i(parser.value_float()); - if (parser.seen('D')) thermalManager.temp_bed.pid.Kd = scalePID_d(parser.value_float()); + if (parser.seenval('P')) thermalManager.temp_bed.pid.Kp = parser.value_float(); + if (parser.seenval('I')) thermalManager.temp_bed.pid.Ki = scalePID_i(parser.value_float()); + if (parser.seenval('D')) thermalManager.temp_bed.pid.Kd = scalePID_d(parser.value_float()); } void GcodeSuite::M304_report(const bool forReplay/*=true*/) { diff --git a/Marlin/src/gcode/config/M305.cpp b/Marlin/src/gcode/config/M305.cpp index 6957eef050..e7746923b3 100644 --- a/Marlin/src/gcode/config/M305.cpp +++ b/Marlin/src/gcode/config/M305.cpp @@ -52,19 +52,19 @@ void GcodeSuite::M305() { if (t_index >= (USER_THERMISTORS) || (do_set && t_index < 0)) SERIAL_ECHO_MSG("!Invalid index. (0 <= P <= ", USER_THERMISTORS - 1, ")"); else if (do_set) { - if (parser.seen('R')) // Pullup resistor value + if (parser.seenval('R')) // Pullup resistor value if (!thermalManager.set_pull_up_res(t_index, parser.value_float())) SERIAL_ECHO_MSG("!Invalid series resistance. (0 < R < 1000000)"); - if (parser.seen('T')) // Resistance at 25C + if (parser.seenval('T')) // Resistance at 25C if (!thermalManager.set_res25(t_index, parser.value_float())) SERIAL_ECHO_MSG("!Invalid 25C resistance. (0 < T < 10000000)"); - if (parser.seen('B')) // Beta value + if (parser.seenval('B')) // Beta value if (!thermalManager.set_beta(t_index, parser.value_float())) SERIAL_ECHO_MSG("!Invalid beta. (0 < B < 1000000)"); - if (parser.seen('C')) // Steinhart-Hart C coefficient + if (parser.seenval('C')) // Steinhart-Hart C coefficient if (!thermalManager.set_sh_coeff(t_index, parser.value_float())) SERIAL_ECHO_MSG("!Invalid Steinhart-Hart C coeff. (-0.01 < C < +0.01)"); } // If not setting then report parameters diff --git a/Marlin/src/gcode/config/M43.cpp b/Marlin/src/gcode/config/M43.cpp index 097aa142f0..688b94c9bf 100644 --- a/Marlin/src/gcode/config/M43.cpp +++ b/Marlin/src/gcode/config/M43.cpp @@ -69,7 +69,7 @@ inline void toggle_pins() { SERIAL_EOL(); } else { - watchdog_refresh(); + hal.watchdog_refresh(); report_pin_state_extended(pin, ignore_protection, true, F("Pulsing ")); #ifdef __STM32F1__ const auto prior_mode = _GET_MODE(i); @@ -98,10 +98,10 @@ inline void toggle_pins() { { pinMode(pin, OUTPUT); for (int16_t j = 0; j < repeat; j++) { - watchdog_refresh(); extDigitalWrite(pin, 0); safe_delay(wait); - watchdog_refresh(); extDigitalWrite(pin, 1); safe_delay(wait); - watchdog_refresh(); extDigitalWrite(pin, 0); safe_delay(wait); - watchdog_refresh(); + hal.watchdog_refresh(); extDigitalWrite(pin, 0); safe_delay(wait); + hal.watchdog_refresh(); extDigitalWrite(pin, 1); safe_delay(wait); + hal.watchdog_refresh(); extDigitalWrite(pin, 0); safe_delay(wait); + hal.watchdog_refresh(); } } #ifdef __STM32F1__ @@ -198,10 +198,10 @@ inline void servo_probe_test() { uint8_t i = 0; SERIAL_ECHOLNPGM(". Deploy & stow 4 times"); do { - MOVE_SERVO(probe_index, servo_angles[Z_PROBE_SERVO_NR][0]); // Deploy + servo[probe_index].move(servo_angles[Z_PROBE_SERVO_NR][0]); // Deploy safe_delay(500); deploy_state = READ(PROBE_TEST_PIN); - MOVE_SERVO(probe_index, servo_angles[Z_PROBE_SERVO_NR][1]); // Stow + servo[probe_index].move(servo_angles[Z_PROBE_SERVO_NR][1]); // Stow safe_delay(500); stow_state = READ(PROBE_TEST_PIN); } while (++i < 4); @@ -226,7 +226,7 @@ inline void servo_probe_test() { } // Ask the user for a trigger event and measure the pulse width. - MOVE_SERVO(probe_index, servo_angles[Z_PROBE_SERVO_NR][0]); // Deploy + servo[probe_index].move(servo_angles[Z_PROBE_SERVO_NR][0]); // Deploy safe_delay(500); SERIAL_ECHOLNPGM("** Please trigger probe within 30 sec **"); uint16_t probe_counter = 0; @@ -256,7 +256,7 @@ inline void servo_probe_test() { } else SERIAL_ECHOLNPGM("FAIL: Noise detected - please re-run test"); - MOVE_SERVO(probe_index, servo_angles[Z_PROBE_SERVO_NR][1]); // Stow + servo[probe_index].move(servo_angles[Z_PROBE_SERVO_NR][1]); // Stow return; } } @@ -313,7 +313,7 @@ void GcodeSuite::M43() { // 'P' Get the range of pins to test or watch uint8_t first_pin = PARSED_PIN_INDEX('P', 0), - last_pin = parser.seenval('P') ? first_pin : NUMBER_PINS_TOTAL - 1; + last_pin = parser.seenval('P') ? first_pin : TERN(HAS_HIGH_ANALOG_PINS, NUM_DIGITAL_PINS, NUMBER_PINS_TOTAL) - 1; if (first_pin > last_pin) return; @@ -333,12 +333,12 @@ void GcodeSuite::M43() { if (M43_NEVER_TOUCH(i) || (!ignore_protection && pin_is_protected(pin))) continue; pinMode(pin, INPUT_PULLUP); delay(1); - /* - if (IS_ANALOG(pin)) - pin_state[pin - first_pin] = analogRead(DIGITAL_PIN_TO_ANALOG_PIN(pin)); // int16_t pin_state[...] - else - //*/ - pin_state[i - first_pin] = extDigitalRead(pin); + /* + if (IS_ANALOG(pin)) + pin_state[pin - first_pin] = analogRead(DIGITAL_PIN_TO_ANALOG_PIN(pin)); // int16_t pin_state[...] + else + //*/ + pin_state[i - first_pin] = extDigitalRead(pin); } #if HAS_RESUME_CONTINUE diff --git a/Marlin/src/gcode/config/M92.cpp b/Marlin/src/gcode/config/M92.cpp index cca4f7f12a..c7610b83a9 100644 --- a/Marlin/src/gcode/config/M92.cpp +++ b/Marlin/src/gcode/config/M92.cpp @@ -43,11 +43,11 @@ void GcodeSuite::M92() { if (target_extruder < 0) return; // No arguments? Show M92 report. - if (!parser.seen(LOGICAL_AXES_STRING TERN_(MAGIC_NUMBERS_GCODE, "HL"))) + if (!parser.seen(STR_AXES_LOGICAL TERN_(MAGIC_NUMBERS_GCODE, "HL"))) return M92_report(true, target_extruder); LOOP_LOGICAL_AXES(i) { - if (parser.seenval(axis_codes[i])) { + if (parser.seenval(AXIS_CHAR(i))) { if (TERN1(HAS_EXTRUDERS, i != E_AXIS)) planner.settings.axis_steps_per_mm[i] = parser.value_per_axis_units((AxisEnum)i); else { diff --git a/Marlin/src/gcode/control/M111.cpp b/Marlin/src/gcode/control/M111.cpp index d6aeb77410..a92d334ae9 100644 --- a/Marlin/src/gcode/control/M111.cpp +++ b/Marlin/src/gcode/control/M111.cpp @@ -49,7 +49,7 @@ void GcodeSuite::M111() { LOOP_L_N(i, COUNT(debug_strings)) { if (TEST(marlin_debug_flags, i)) { if (comma++) SERIAL_CHAR(','); - SERIAL_ECHOPGM_P((char*)pgm_read_ptr(&debug_strings[i])); + SERIAL_ECHOPGM_P((PGM_P)pgm_read_ptr(&debug_strings[i])); } } } diff --git a/Marlin/src/gcode/control/M17_M18_M84.cpp b/Marlin/src/gcode/control/M17_M18_M84.cpp index c6473af48f..c2c8a702a1 100644 --- a/Marlin/src/gcode/control/M17_M18_M84.cpp +++ b/Marlin/src/gcode/control/M17_M18_M84.cpp @@ -23,6 +23,7 @@ #include "../gcode.h" #include "../../MarlinCore.h" // for stepper_inactive_time, disable_e_steppers #include "../../lcd/marlinui.h" +#include "../../module/motion.h" // for e_axis_mask #include "../../module/stepper.h" #if ENABLED(AUTO_BED_LEVELING_UBL) @@ -33,8 +34,8 @@ #include "../../core/debug_out.h" #include "../../libs/hex_print.h" -inline axis_flags_t selected_axis_bits() { - axis_flags_t selected{0}; +inline stepper_flags_t selected_axis_bits() { + stepper_flags_t selected{0}; #if HAS_EXTRUDERS if (parser.seen('E')) { if (E_TERN0(parser.has_value())) { @@ -43,7 +44,7 @@ inline axis_flags_t selected_axis_bits() { selected.bits = _BV(INDEX_OF_AXIS(E_AXIS, e)); } else - selected.bits = selected.e_bits(); + selected.bits = e_axis_mask; } #endif selected.bits |= NUM_AXIS_GANG( @@ -61,7 +62,7 @@ inline axis_flags_t selected_axis_bits() { } // Enable specified axes and warn about other affected axes -void do_enable(const axis_flags_t to_enable) { +void do_enable(const stepper_flags_t to_enable) { const ena_mask_t was_enabled = stepper.axis_enabled.bits, shall_enable = to_enable.bits & ~was_enabled; @@ -75,7 +76,7 @@ void do_enable(const axis_flags_t to_enable) { LOOP_NUM_AXES(a) { if (TEST(shall_enable, a)) { stepper.enable_axis(AxisEnum(a)); // Mark and enable the requested axis - DEBUG_ECHOLNPGM("Enabled ", axis_codes[a], " (", a, ") with overlap ", hex_word(enable_overlap[a]), " ... Enabled: ", hex_word(stepper.axis_enabled.bits)); + DEBUG_ECHOLNPGM("Enabled ", AXIS_CHAR(a), " (", a, ") with overlap ", hex_word(enable_overlap[a]), " ... Enabled: ", hex_word(stepper.axis_enabled.bits)); also_enabled |= enable_overlap[a]; } } @@ -92,7 +93,7 @@ void do_enable(const axis_flags_t to_enable) { if ((also_enabled &= ~(shall_enable | was_enabled))) { SERIAL_CHAR('('); - LOOP_NUM_AXES(a) if (TEST(also_enabled, a)) SERIAL_CHAR(axis_codes[a], ' '); + LOOP_NUM_AXES(a) if (TEST(also_enabled, a)) SERIAL_CHAR(AXIS_CHAR(a), ' '); #if HAS_EXTRUDERS #define _EN_ALSO(N) if (TEST(also_enabled, INDEX_OF_AXIS(E_AXIS, N))) SERIAL_CHAR('E', '0' + N, ' '); REPEAT(EXTRUDERS, _EN_ALSO) @@ -128,17 +129,8 @@ void GcodeSuite::M17() { stepper.enable_e_steppers(); } #endif - NUM_AXIS_CODE( - if (parser.seen_test('X')) stepper.enable_axis(X_AXIS), - if (parser.seen_test('Y')) stepper.enable_axis(Y_AXIS), - if (parser.seen_test('Z')) stepper.enable_axis(Z_AXIS), - if (parser.seen_test(AXIS4_NAME)) stepper.enable_axis(I_AXIS), - if (parser.seen_test(AXIS5_NAME)) stepper.enable_axis(J_AXIS), - if (parser.seen_test(AXIS6_NAME)) stepper.enable_axis(K_AXIS), - if (parser.seen_test(AXIS7_NAME)) stepper.enable_axis(U_AXIS), - if (parser.seen_test(AXIS8_NAME)) stepper.enable_axis(V_AXIS), - if (parser.seen_test(AXIS9_NAME)) stepper.enable_axis(W_AXIS) - ); + LOOP_NUM_AXES(a) + if (parser.seen_test(AXIS_CHAR(a))) stepper.enable_axis((AxisEnum)a); } } else { @@ -147,7 +139,7 @@ void GcodeSuite::M17() { } } -void try_to_disable(const axis_flags_t to_disable) { +void try_to_disable(const stepper_flags_t to_disable) { ena_mask_t still_enabled = to_disable.bits & stepper.axis_enabled.bits; DEBUG_ECHOLNPGM("Enabled: ", hex_word(stepper.axis_enabled.bits), " To Disable: ", hex_word(to_disable.bits), " | ", hex_word(still_enabled)); @@ -157,7 +149,7 @@ void try_to_disable(const axis_flags_t to_disable) { // Attempt to disable all flagged axes LOOP_NUM_AXES(a) if (TEST(to_disable.bits, a)) { - DEBUG_ECHOPGM("Try to disable ", axis_codes[a], " (", a, ") with overlap ", hex_word(enable_overlap[a]), " ... "); + DEBUG_ECHOPGM("Try to disable ", AXIS_CHAR(a), " (", a, ") with overlap ", hex_word(enable_overlap[a]), " ... "); if (stepper.disable_axis(AxisEnum(a))) { // Mark the requested axis and request to disable DEBUG_ECHOPGM("OK"); still_enabled &= ~(_BV(a) | enable_overlap[a]); // If actually disabled, clear one or more tracked bits @@ -184,7 +176,7 @@ void try_to_disable(const axis_flags_t to_disable) { auto overlap_warning = [](const ena_mask_t axis_bits) { SERIAL_ECHOPGM(" not disabled. Shared with"); - LOOP_NUM_AXES(a) if (TEST(axis_bits, a)) SERIAL_CHAR(' ', axis_codes[a]); + LOOP_NUM_AXES(a) if (TEST(axis_bits, a)) SERIAL_ECHOPGM_P((PGM_P)pgm_read_ptr(&SP_AXIS_STR[a])); #if HAS_EXTRUDERS #define _EN_STILLON(N) if (TEST(axis_bits, INDEX_OF_AXIS(E_AXIS, N))) SERIAL_CHAR(' ', 'E', '0' + N); REPEAT(EXTRUDERS, _EN_STILLON) @@ -195,7 +187,7 @@ void try_to_disable(const axis_flags_t to_disable) { // If any of the requested axes are still enabled, give a warning LOOP_NUM_AXES(a) { if (TEST(still_enabled, a)) { - SERIAL_CHAR(axis_codes[a]); + SERIAL_CHAR(AXIS_CHAR(a)); overlap_warning(stepper.axis_enabled.bits & enable_overlap[a]); } } @@ -219,7 +211,16 @@ void try_to_disable(const axis_flags_t to_disable) { void GcodeSuite::M18_M84() { if (parser.seenval('S')) { reset_stepper_timeout(); - stepper_inactive_time = parser.value_millis_from_seconds(); + #if HAS_DISABLE_INACTIVE_AXIS + const millis_t ms = parser.value_millis_from_seconds(); + #if LASER_SAFETY_TIMEOUT_MS > 0 + if (ms && ms <= LASER_SAFETY_TIMEOUT_MS) { + SERIAL_ECHO_MSG("M18 timeout must be > ", MS_TO_SEC(LASER_SAFETY_TIMEOUT_MS + 999), " s for laser safety."); + return; + } + #endif + stepper_inactive_time = ms; + #endif } else { if (parser.seen_axis()) { @@ -235,22 +236,13 @@ void GcodeSuite::M18_M84() { stepper.disable_e_steppers(); } #endif - NUM_AXIS_CODE( - if (parser.seen_test('X')) stepper.disable_axis(X_AXIS), - if (parser.seen_test('Y')) stepper.disable_axis(Y_AXIS), - if (parser.seen_test('Z')) stepper.disable_axis(Z_AXIS), - if (parser.seen_test(AXIS4_NAME)) stepper.disable_axis(I_AXIS), - if (parser.seen_test(AXIS5_NAME)) stepper.disable_axis(J_AXIS), - if (parser.seen_test(AXIS6_NAME)) stepper.disable_axis(K_AXIS), - if (parser.seen_test(AXIS7_NAME)) stepper.disable_axis(U_AXIS), - if (parser.seen_test(AXIS8_NAME)) stepper.disable_axis(V_AXIS), - if (parser.seen_test(AXIS9_NAME)) stepper.disable_axis(W_AXIS) - ); + LOOP_NUM_AXES(a) + if (parser.seen_test(AXIS_CHAR(a))) stepper.disable_axis((AxisEnum)a); } } else planner.finish_and_disable(); - TERN_(AUTO_BED_LEVELING_UBL, ubl.steppers_were_disabled()); + TERN_(AUTO_BED_LEVELING_UBL, bedlevel.steppers_were_disabled()); } } diff --git a/Marlin/src/gcode/control/M280.cpp b/Marlin/src/gcode/control/M280.cpp index 2a8e73eafb..82981e44bc 100644 --- a/Marlin/src/gcode/control/M280.cpp +++ b/Marlin/src/gcode/control/M280.cpp @@ -48,7 +48,7 @@ void GcodeSuite::M280() { const int anew = parser.value_int(); if (anew >= 0) { #if ENABLED(POLARGRAPH) - if (parser.seen('T')) { // (ms) Total duration of servo move + if (parser.seenval('T')) { // (ms) Total duration of servo move const int16_t t = constrain(parser.value_int(), 0, 10000); const int aold = servo[servo_index].read(); millis_t now = millis(); @@ -56,14 +56,14 @@ void GcodeSuite::M280() { while (PENDING(now, end)) { safe_delay(50); now = _MIN(millis(), end); - MOVE_SERVO(servo_index, LROUND(aold + (anew - aold) * (float(now - start) / t))); + servo[servo_index].move(LROUND(aold + (anew - aold) * (float(now - start) / t))); } } #endif // POLARGRAPH - MOVE_SERVO(servo_index, anew); + servo[servo_index].move(anew); } else - DETACH_SERVO(servo_index); + servo[servo_index].detach(); } else SERIAL_ECHO_MSG(" Servo ", servo_index, ": ", servo[servo_index].read()); diff --git a/Marlin/src/gcode/control/M282.cpp b/Marlin/src/gcode/control/M282.cpp index e6f5ce7dcc..3ac5ac9f5b 100644 --- a/Marlin/src/gcode/control/M282.cpp +++ b/Marlin/src/gcode/control/M282.cpp @@ -36,7 +36,7 @@ void GcodeSuite::M282() { const int servo_index = parser.value_int(); if (WITHIN(servo_index, 0, NUM_SERVOS - 1)) - DETACH_SERVO(servo_index); + servo[servo_index].detach(); else SERIAL_ECHO_MSG("Servo ", servo_index, " out of range"); diff --git a/Marlin/src/gcode/control/M3-M5.cpp b/Marlin/src/gcode/control/M3-M5.cpp index 2cf22e81ce..3c51de6f6f 100644 --- a/Marlin/src/gcode/control/M3-M5.cpp +++ b/Marlin/src/gcode/control/M3-M5.cpp @@ -31,17 +31,27 @@ /** * Laser: * M3 - Laser ON/Power (Ramped power) - * M4 - Laser ON/Power (Continuous power) + * M4 - Laser ON/Power (Ramped power) + * M5 - Set power output to 0 (leaving inline mode unchanged). + * + * M3I - Enable continuous inline power to be processed by the planner, with power + * calculated and set in the planner blocks, processed inline during stepping. + * Within inline mode M3 S-Values will set the power for the next moves e.g. G1 X10 Y10 powers on with the last S-Value. + * M3I must be set before using planner-synced M3 inline S-Values (LASER_POWER_SYNC). + * + * M4I - Set dynamic mode which calculates laser power OCR based on the current feedrate. + * + * M5I - Clear inline mode and set power to 0. * * Spindle: * M3 - Spindle ON (Clockwise) * M4 - Spindle ON (Counter-clockwise) + * M5 - Spindle OFF * * Parameters: - * S - Set power. S0 will turn the spindle/laser off, except in relative mode. - * O - Set power and OCR (oscillator count register) + * S - Set power. S0 will turn the spindle/laser off. * - * If no PWM pin is defined then M3/M4 just turns it on. + * If no PWM pin is defined then M3/M4 just turns it on or off. * * At least 12.8kHz (50Hz * 256) is needed for Spindle PWM. * Hardware PWM is required on AVR. ISRs are too slow. @@ -66,77 +76,81 @@ * PWM duty cycle goes from 0 (off) to 255 (always on). */ void GcodeSuite::M3_M4(const bool is_M4) { - #if EITHER(SPINDLE_LASER_USE_PWM, SPINDLE_SERVO) - auto get_s_power = [] { - if (parser.seenval('S')) { - const float spwr = parser.value_float(); - #if ENABLED(SPINDLE_SERVO) - cutter.unitPower = spwr; - #else - cutter.unitPower = TERN(SPINDLE_LASER_USE_PWM, - cutter.power_to_range(cutter_power_t(round(spwr))), - spwr > 0 ? 255 : 0); - #endif - } - else - cutter.unitPower = cutter.cpwr_to_upwr(SPEED_POWER_STARTUP); - return cutter.unitPower; - }; + #if LASER_SAFETY_TIMEOUT_MS > 0 + reset_stepper_timeout(); // Reset timeout to allow subsequent G-code to power the laser (imm.) #endif - #if ENABLED(LASER_POWER_INLINE) - if (parser.seen('I') == DISABLED(LASER_POWER_INLINE_INVERT)) { - // Laser power in inline mode - cutter.inline_direction(is_M4); // Should always be unused - #if ENABLED(SPINDLE_LASER_USE_PWM) - if (parser.seen('O')) { - cutter.unitPower = cutter.power_to_range(parser.value_byte(), 0); - cutter.inline_ocr_power(cutter.unitPower); // The OCR is a value from 0 to 255 (uint8_t) - } - else - cutter.inline_power(cutter.upower_to_ocr(get_s_power())); + if (cutter.cutter_mode == CUTTER_MODE_STANDARD) + planner.synchronize(); // Wait for previous movement commands (G0/G1/G2/G3) to complete before changing power + + #if ENABLED(LASER_FEATURE) + if (parser.seen_test('I')) { + cutter.cutter_mode = is_M4 ? CUTTER_MODE_DYNAMIC : CUTTER_MODE_CONTINUOUS; + cutter.inline_power(0); + cutter.set_enabled(true); + } + #endif + + auto get_s_power = [] { + float u; + if (parser.seenval('S')) { + const float v = parser.value_float(); + u = TERN(LASER_POWER_TRAP, v, cutter.power_to_range(v)); + } + else if (cutter.cutter_mode == CUTTER_MODE_STANDARD) + u = cutter.cpwr_to_upwr(SPEED_POWER_STARTUP); + + cutter.menuPower = cutter.unitPower = u; + + // PWM not implied, power converted to OCR from unit definition and on/off if not PWM. + cutter.power = TERN(SPINDLE_LASER_USE_PWM, cutter.upower_to_ocr(u), u > 0 ? 255 : 0); + return u; + }; + + if (cutter.cutter_mode == CUTTER_MODE_CONTINUOUS || cutter.cutter_mode == CUTTER_MODE_DYNAMIC) { // Laser power in inline mode + #if ENABLED(LASER_FEATURE) + planner.laser_inline.status.isPowered = true; // M3 or M4 is powered either way + get_s_power(); // Update cutter.power if seen + #if ENABLED(LASER_POWER_SYNC) + // With power sync we only set power so it does not effect queued inline power sets + planner.buffer_sync_block(BLOCK_BIT_LASER_PWR); // Send the flag, queueing inline power #else - cutter.set_inline_enabled(true); + planner.synchronize(); + cutter.inline_power(cutter.power); #endif - return; - } - // Non-inline, standard case - cutter.inline_disable(); // Prevent future blocks re-setting the power - #endif - - planner.synchronize(); // Wait for previous movement commands (G0/G0/G2/G3) to complete before changing power - cutter.set_reverse(is_M4); - - #if ENABLED(SPINDLE_LASER_USE_PWM) - if (parser.seenval('O')) { - cutter.unitPower = cutter.power_to_range(parser.value_byte(), 0); - cutter.ocr_set_power(cutter.unitPower); // The OCR is a value from 0 to 255 (uint8_t) - } - else - cutter.set_power(cutter.upower_to_ocr(get_s_power())); - #elif ENABLED(SPINDLE_SERVO) - cutter.set_power(get_s_power()); - #else + #endif + } + else { cutter.set_enabled(true); - #endif - cutter.menuPower = cutter.unitPower; + get_s_power(); + cutter.apply_power( + #if ENABLED(SPINDLE_SERVO) + cutter.unitPower + #elif ENABLED(SPINDLE_LASER_USE_PWM) + cutter.upower_to_ocr(cutter.unitPower) + #else + cutter.unitPower > 0 ? 255 : 0 + #endif + ); + TERN_(SPINDLE_CHANGE_DIR, cutter.set_reverse(is_M4)); + } } /** * M5 - Cutter OFF (when moves are complete) */ void GcodeSuite::M5() { - #if ENABLED(LASER_POWER_INLINE) - if (parser.seen('I') == DISABLED(LASER_POWER_INLINE_INVERT)) { - cutter.set_inline_enabled(false); // Laser power in inline mode - return; - } - // Non-inline, standard case - cutter.inline_disable(); // Prevent future blocks re-setting the power - #endif planner.synchronize(); - cutter.set_enabled(false); - cutter.menuPower = cutter.unitPower; + cutter.power = 0; + cutter.apply_power(0); // M5 just kills power, leaving inline mode unchanged + if (cutter.cutter_mode != CUTTER_MODE_STANDARD) { + if (parser.seen_test('I')) { + TERN_(LASER_FEATURE, cutter.inline_power(cutter.power)); + cutter.set_enabled(false); // Needs to happen while we are in inline mode to clear inline power. + cutter.cutter_mode = CUTTER_MODE_STANDARD; // Switch from inline to standard mode. + } + } + cutter.set_enabled(false); // Disable enable output setting } #endif // HAS_CUTTER diff --git a/Marlin/src/gcode/control/M350_M351.cpp b/Marlin/src/gcode/control/M350_M351.cpp index a92238e4bb..ac6b5a329b 100644 --- a/Marlin/src/gcode/control/M350_M351.cpp +++ b/Marlin/src/gcode/control/M350_M351.cpp @@ -27,35 +27,45 @@ #include "../gcode.h" #include "../../module/stepper.h" +#if NUM_AXES == XYZ && EXTRUDERS >= 1 + #define HAS_M350_B_PARAM 1 // "5th axis" (after E0) for an original XYZEB setup. + #if AXIS_COLLISION('B') + #error "M350 parameter 'B' collision with axis name." + #endif +#endif + /** * M350: Set axis microstepping modes. S sets mode for all drivers. * * Warning: Steps-per-unit remains unchanged. */ void GcodeSuite::M350() { - if (parser.seen('S')) LOOP_LE_N(i, 4) stepper.microstep_mode(i, parser.value_byte()); - LOOP_LOGICAL_AXES(i) if (parser.seen(axis_codes[i])) stepper.microstep_mode(i, parser.value_byte()); - if (parser.seen('B')) stepper.microstep_mode(4, parser.value_byte()); + if (parser.seen('S')) LOOP_DISTINCT_AXES(i) stepper.microstep_mode(i, parser.value_byte()); + LOOP_LOGICAL_AXES(i) if (parser.seenval(AXIS_CHAR(i))) stepper.microstep_mode(i, parser.value_byte()); + TERN_(HAS_M350_B_PARAM, if (parser.seenval('B')) stepper.microstep_mode(E_AXIS + 1, parser.value_byte())); stepper.microstep_readings(); } /** - * M351: Toggle MS1 MS2 pins directly with axis codes X Y Z E B + * M351: Toggle MS1 MS2 pins directly with axis codes X Y Z . . . E [B] * S# determines MS1, MS2 or MS3, X# sets the pin high/low. + * + * Parameter 'B' sets "5th axis" (after E0) only for an original XYZEB setup. */ void GcodeSuite::M351() { + const int8_t bval = TERN(HAS_M350_B_PARAM, parser.byteval('B', -1), -1); UNUSED(bval); if (parser.seenval('S')) switch (parser.value_byte()) { case 1: - LOOP_LOGICAL_AXES(i) if (parser.seenval(axis_codes[i])) stepper.microstep_ms(i, parser.value_byte(), -1, -1); - if (parser.seenval('B')) stepper.microstep_ms(4, parser.value_byte(), -1, -1); + LOOP_LOGICAL_AXES(i) if (parser.seenval(AXIS_CHAR(i))) stepper.microstep_ms(i, parser.value_byte(), -1, -1); + TERN_(HAS_M350_B_PARAM, if (bval >= 0) stepper.microstep_ms(E_AXIS + 1, bval != 0, -1, -1)); break; case 2: - LOOP_LOGICAL_AXES(i) if (parser.seenval(axis_codes[i])) stepper.microstep_ms(i, -1, parser.value_byte(), -1); - if (parser.seenval('B')) stepper.microstep_ms(4, -1, parser.value_byte(), -1); + LOOP_LOGICAL_AXES(i) if (parser.seenval(AXIS_CHAR(i))) stepper.microstep_ms(i, -1, parser.value_byte(), -1); + TERN_(HAS_M350_B_PARAM, if (bval >= 0) stepper.microstep_ms(E_AXIS + 1, -1, bval != 0, -1)); break; case 3: - LOOP_LOGICAL_AXES(i) if (parser.seenval(axis_codes[i])) stepper.microstep_ms(i, -1, -1, parser.value_byte()); - if (parser.seenval('B')) stepper.microstep_ms(4, -1, -1, parser.value_byte()); + LOOP_LOGICAL_AXES(i) if (parser.seenval(AXIS_CHAR(i))) stepper.microstep_ms(i, -1, -1, parser.value_byte()); + TERN_(HAS_M350_B_PARAM, if (bval >= 0) stepper.microstep_ms(E_AXIS + 1, -1, -1, bval != 0)); break; } stepper.microstep_readings(); diff --git a/Marlin/src/gcode/control/M605.cpp b/Marlin/src/gcode/control/M605.cpp index a0296bba57..06d92c8448 100644 --- a/Marlin/src/gcode/control/M605.cpp +++ b/Marlin/src/gcode/control/M605.cpp @@ -64,7 +64,7 @@ void GcodeSuite::M605() { planner.synchronize(); - if (parser.seen('S')) { + if (parser.seenval('S')) { const DualXMode previous_mode = dual_x_carriage_mode; dual_x_carriage_mode = (DualXMode)parser.value_byte(); @@ -78,8 +78,8 @@ case DXC_DUPLICATION_MODE: // Set the X offset, but no less than the safety gap - if (parser.seen('X')) duplicate_extruder_x_offset = _MAX(parser.value_linear_units(), (X2_MIN_POS) - (X1_MIN_POS)); - if (parser.seen('R')) duplicate_extruder_temp_offset = parser.value_celsius_diff(); + if (parser.seenval('X')) duplicate_extruder_x_offset = _MAX(parser.value_linear_units(), (X2_MIN_POS) - (X1_MIN_POS)); + if (parser.seenval('R')) duplicate_extruder_temp_offset = parser.value_celsius_diff(); // Always switch back to tool 0 if (active_extruder != 0) tool_change(0); break; diff --git a/Marlin/src/gcode/control/M85.cpp b/Marlin/src/gcode/control/M85.cpp index 9c8c02c59a..ee868349ed 100644 --- a/Marlin/src/gcode/control/M85.cpp +++ b/Marlin/src/gcode/control/M85.cpp @@ -29,7 +29,14 @@ void GcodeSuite::M85() { if (parser.seen('S')) { reset_stepper_timeout(); - max_inactive_time = parser.value_millis_from_seconds(); + const millis_t ms = parser.value_millis_from_seconds(); + #if LASER_SAFETY_TIMEOUT_MS > 0 + if (ms && ms <= LASER_SAFETY_TIMEOUT_MS) { + SERIAL_ECHO_MSG("M85 timeout must be > ", MS_TO_SEC(LASER_SAFETY_TIMEOUT_MS + 999), " s for laser safety."); + return; + } + #endif + max_inactive_time = ms; } } diff --git a/Marlin/src/gcode/feature/L6470/M122.cpp b/Marlin/src/gcode/feature/L6470/M122.cpp deleted file mode 100644 index 4a5629b049..0000000000 --- a/Marlin/src/gcode/feature/L6470/M122.cpp +++ /dev/null @@ -1,151 +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 . - * - */ - -#include "../../../inc/MarlinConfig.h" - -#if HAS_L64XX - -#include "../../gcode.h" -#include "../../../libs/L64XX/L64XX_Marlin.h" -#include "../../../module/stepper/indirection.h" - -void echo_yes_no(const bool yes); - -inline void L6470_say_status(const L64XX_axis_t axis) { - if (L64xxManager.spi_abort) return; - const L64XX_Marlin::L64XX_shadow_t &sh = L64xxManager.shadow; - L64xxManager.get_status(axis); - L64xxManager.say_axis(axis); - #if ENABLED(L6470_CHITCHAT) - char temp_buf[20]; - sprintf_P(temp_buf, PSTR(" status: %4x "), sh.STATUS_AXIS_RAW); - SERIAL_ECHO(temp_buf); - print_bin(sh.STATUS_AXIS_RAW); - switch (sh.STATUS_AXIS_LAYOUT) { - case L6470_STATUS_LAYOUT: SERIAL_ECHOPGM(" L6470"); break; - case L6474_STATUS_LAYOUT: SERIAL_ECHOPGM(" L6474"); break; - case L6480_STATUS_LAYOUT: SERIAL_ECHOPGM(" L6480/powerSTEP01"); break; - } - #endif - SERIAL_ECHOPGM("\n...OUTPUT: "); - SERIAL_ECHOF(sh.STATUS_AXIS & STATUS_HIZ ? F("OFF") : F("ON ")); - SERIAL_ECHOPGM(" BUSY: "); echo_yes_no((sh.STATUS_AXIS & STATUS_BUSY) == 0); - SERIAL_ECHOPGM(" DIR: "); - SERIAL_ECHOF((((sh.STATUS_AXIS & STATUS_DIR) >> 4) ^ L64xxManager.index_to_dir[axis]) ? F("FORWARD") : F("REVERSE")); - if (sh.STATUS_AXIS_LAYOUT == L6480_STATUS_LAYOUT) { - SERIAL_ECHOPGM(" Last Command: "); - if (sh.STATUS_AXIS & sh.STATUS_AXIS_WRONG_CMD) SERIAL_ECHOPGM("VALID"); - else SERIAL_ECHOPGM("ERROR"); - SERIAL_ECHOPGM("\n...THERMAL: "); - switch ((sh.STATUS_AXIS & (sh.STATUS_AXIS_TH_SD | sh.STATUS_AXIS_TH_WRN)) >> 11) { - case 0: SERIAL_ECHOPGM("DEVICE SHUTDOWN"); break; - case 1: SERIAL_ECHOPGM("BRIDGE SHUTDOWN"); break; - case 2: SERIAL_ECHOPGM("WARNING "); break; - case 3: SERIAL_ECHOPGM("OK "); break; - } - } - else { - SERIAL_ECHOPGM(" Last Command: "); - if (!(sh.STATUS_AXIS & sh.STATUS_AXIS_WRONG_CMD)) SERIAL_ECHOPGM("IN"); - SERIAL_ECHOPGM("VALID "); - SERIAL_ECHOF(sh.STATUS_AXIS & sh.STATUS_AXIS_NOTPERF_CMD ? F("COMPLETED ") : F("Not PERFORMED")); - SERIAL_ECHOPGM("\n...THERMAL: ", !(sh.STATUS_AXIS & sh.STATUS_AXIS_TH_SD) ? "SHUTDOWN " : !(sh.STATUS_AXIS & sh.STATUS_AXIS_TH_WRN) ? "WARNING " : "OK "); - } - SERIAL_ECHOPGM(" OVERCURRENT:"); echo_yes_no((sh.STATUS_AXIS & sh.STATUS_AXIS_OCD) == 0); - if (sh.STATUS_AXIS_LAYOUT != L6474_STATUS_LAYOUT) { - SERIAL_ECHOPGM(" STALL:"); echo_yes_no((sh.STATUS_AXIS & sh.STATUS_AXIS_STEP_LOSS_A) == 0 || (sh.STATUS_AXIS & sh.STATUS_AXIS_STEP_LOSS_B) == 0); - SERIAL_ECHOPGM(" STEP-CLOCK MODE:"); echo_yes_no((sh.STATUS_AXIS & sh.STATUS_AXIS_SCK_MOD) != 0); - } - else { - SERIAL_ECHOPGM(" STALL: NA " - " STEP-CLOCK MODE: NA" - " UNDER VOLTAGE LOCKOUT: "); echo_yes_no((sh.STATUS_AXIS & sh.STATUS_AXIS_UVLO) == 0); - } - SERIAL_EOL(); -} - -/** - * M122: Debug L6470 drivers - */ -void GcodeSuite::M122() { - L64xxManager.pause_monitor(true); // Keep monitor_driver() from stealing status - L64xxManager.spi_active = true; // Tell set_directions() a series of SPI transfers is underway - - //if (parser.seen('S')) - // tmc_set_report_interval(parser.value_bool()); - //else - - #if AXIS_IS_L64XX(X) - L6470_say_status(X); - #endif - #if AXIS_IS_L64XX(X2) - L6470_say_status(X2); - #endif - #if AXIS_IS_L64XX(Y) - L6470_say_status(Y); - #endif - #if AXIS_IS_L64XX(Y2) - L6470_say_status(Y2); - #endif - #if AXIS_IS_L64XX(Z) - L6470_say_status(Z); - #endif - #if AXIS_IS_L64XX(Z2) - L6470_say_status(Z2); - #endif - #if AXIS_IS_L64XX(Z3) - L6470_say_status(Z3); - #endif - #if AXIS_IS_L64XX(Z4) - L6470_say_status(Z4); - #endif - #if AXIS_IS_L64XX(E0) - L6470_say_status(E0); - #endif - #if AXIS_IS_L64XX(E1) - L6470_say_status(E1); - #endif - #if AXIS_IS_L64XX(E2) - L6470_say_status(E2); - #endif - #if AXIS_IS_L64XX(E3) - L6470_say_status(E3); - #endif - #if AXIS_IS_L64XX(E4) - L6470_say_status(E4); - #endif - #if AXIS_IS_L64XX(E5) - L6470_say_status(E5); - #endif - #if AXIS_IS_L64XX(E6) - L6470_say_status(E6); - #endif - #if AXIS_IS_L64XX(E7) - L6470_say_status(E7); - #endif - - L64xxManager.spi_active = false; // done with all SPI transfers - clear handshake flags - L64xxManager.spi_abort = false; - L64xxManager.pause_monitor(false); -} - -#endif // HAS_L64XX diff --git a/Marlin/src/gcode/feature/L6470/M906.cpp b/Marlin/src/gcode/feature/L6470/M906.cpp deleted file mode 100644 index f55405b798..0000000000 --- a/Marlin/src/gcode/feature/L6470/M906.cpp +++ /dev/null @@ -1,380 +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 . - * - */ - -#include "../../../inc/MarlinConfig.h" - -#if HAS_L64XX - -#if AXIS_COLLISION('I') - #error "M906 parameter collision with axis name." -#endif - -#include "../../gcode.h" -#include "../../../libs/L64XX/L64XX_Marlin.h" -#include "../../../module/stepper/indirection.h" -#include "../../../module/planner.h" - -#define DEBUG_OUT ENABLED(L6470_CHITCHAT) -#include "../../../core/debug_out.h" - -/** - * MACRO to fetch information on the items associated with current limiting - * and maximum voltage output. - * - * L6470 can be setup to shutdown if either current threshold is exceeded. - * - * L6470 output current can not be set directly. It is set indirectly by - * setting the maximum effective output voltage. - * - * Effective output voltage is set by PWM duty cycle. - * - * Maximum effective output voltage is affected by MANY variables. The main ones are: - * KVAL_HOLD - * KVAL_RUN - * KVAL_ACC - * KVAL_DEC - * Vs compensation (if enabled) - */ -void L64XX_report_current(L64XX &motor, const L64XX_axis_t axis) { - - if (L64xxManager.spi_abort) return; // don't do anything if set_directions() has occurred - - const L64XX_Marlin::L64XX_shadow_t &sh = L64xxManager.shadow; - const uint16_t status = L64xxManager.get_status(axis); //also populates shadow structure - const uint8_t OverCurrent_Threshold = uint8_t(motor.GetParam(L6470_OCD_TH)); - - auto say_axis_status = [](const L64XX_axis_t axis, const uint16_t status) { - L64xxManager.say_axis(axis); - #if ENABLED(L6470_CHITCHAT) - char tmp[10]; - sprintf_P(tmp, PSTR("%4x "), status); - DEBUG_ECHOPGM(" status: ", tmp); - print_bin(status); - #else - UNUSED(status); - #endif - SERIAL_EOL(); - }; - - char temp_buf[10]; - - switch (sh.STATUS_AXIS_LAYOUT) { - case L6470_STATUS_LAYOUT: // L6470 - case L6480_STATUS_LAYOUT: { // L6480 & powerstep01 - const uint16_t Stall_Threshold = (uint8_t)motor.GetParam(L6470_STALL_TH), - motor_status = (status & (STATUS_MOT_STATUS)) >> 5, - L6470_ADC_out = motor.GetParam(L6470_ADC_OUT), - L6470_ADC_out_limited = constrain(L6470_ADC_out, 8, 24); - const float comp_coef = 1600.0f / L6470_ADC_out_limited; - const uint16_t MicroSteps = _BV(motor.GetParam(L6470_STEP_MODE) & 0x07); - - say_axis_status(axis, sh.STATUS_AXIS_RAW); - - SERIAL_ECHOPGM("...OverCurrent Threshold: "); - sprintf_P(temp_buf, PSTR("%2d ("), OverCurrent_Threshold); - SERIAL_ECHO(temp_buf); - SERIAL_ECHO((OverCurrent_Threshold + 1) * motor.OCD_CURRENT_CONSTANT_INV); - SERIAL_ECHOPGM(" mA)"); - SERIAL_ECHOPGM(" Stall Threshold: "); - sprintf_P(temp_buf, PSTR("%2d ("), Stall_Threshold); - SERIAL_ECHO(temp_buf); - SERIAL_ECHO((Stall_Threshold + 1) * motor.STALL_CURRENT_CONSTANT_INV); - SERIAL_ECHOPGM(" mA)"); - SERIAL_ECHOPGM(" Motor Status: "); - switch (motor_status) { - case 0: SERIAL_ECHOPGM("stopped"); break; - case 1: SERIAL_ECHOPGM("accelerating"); break; - case 2: SERIAL_ECHOPGM("decelerating"); break; - case 3: SERIAL_ECHOPGM("at constant speed"); break; - } - SERIAL_EOL(); - - SERIAL_ECHOPGM("...MicroSteps: ", MicroSteps, - " ADC_OUT: ", L6470_ADC_out); - SERIAL_ECHOPGM(" Vs_compensation: "); - SERIAL_ECHOF((motor.GetParam(sh.L6470_AXIS_CONFIG) & CONFIG_EN_VSCOMP) ? F("ENABLED ") : F("DISABLED")); - SERIAL_ECHOLNPGM(" Compensation coefficient: ~", comp_coef * 0.01f); - - SERIAL_ECHOPGM("...KVAL_HOLD: ", motor.GetParam(L6470_KVAL_HOLD), - " KVAL_RUN : ", motor.GetParam(L6470_KVAL_RUN), - " KVAL_ACC: ", motor.GetParam(L6470_KVAL_ACC), - " KVAL_DEC: ", motor.GetParam(L6470_KVAL_DEC), - " V motor max = "); - switch (motor_status) { - case 0: SERIAL_ECHO(motor.GetParam(L6470_KVAL_HOLD) * 100 / 256); SERIAL_ECHOPGM("% (KVAL_HOLD)"); break; - case 1: SERIAL_ECHO(motor.GetParam(L6470_KVAL_RUN) * 100 / 256); SERIAL_ECHOPGM("% (KVAL_RUN)"); break; - case 2: SERIAL_ECHO(motor.GetParam(L6470_KVAL_ACC) * 100 / 256); SERIAL_ECHOPGM("% (KVAL_ACC)"); break; - case 3: SERIAL_ECHO(motor.GetParam(L6470_KVAL_DEC) * 100 / 256); SERIAL_ECHOPGM("% (KVAL_HOLD)"); break; - } - SERIAL_EOL(); - - #if ENABLED(L6470_CHITCHAT) - DEBUG_ECHOPGM("...SLEW RATE: "); - switch (sh.STATUS_AXIS_LAYOUT) { - case L6470_STATUS_LAYOUT: { - switch ((motor.GetParam(sh.L6470_AXIS_CONFIG) & CONFIG_POW_SR) >> CONFIG_POW_SR_BIT) { - case 0: { DEBUG_ECHOLNPGM("320V/uS") ; break; } - case 1: { DEBUG_ECHOLNPGM("75V/uS") ; break; } - case 2: { DEBUG_ECHOLNPGM("110V/uS") ; break; } - case 3: { DEBUG_ECHOLNPGM("260V/uS") ; break; } - } - break; - } - case L6480_STATUS_LAYOUT: { - switch (motor.GetParam(L6470_GATECFG1) & CONFIG1_SR ) { - case CONFIG1_SR_220V_us: { DEBUG_ECHOLNPGM("220V/uS") ; break; } - case CONFIG1_SR_400V_us: { DEBUG_ECHOLNPGM("400V/uS") ; break; } - case CONFIG1_SR_520V_us: { DEBUG_ECHOLNPGM("520V/uS") ; break; } - case CONFIG1_SR_980V_us: { DEBUG_ECHOLNPGM("980V/uS") ; break; } - default: { DEBUG_ECHOLNPGM("unknown") ; break; } - } - } - } - #endif - SERIAL_EOL(); - break; - } - - case L6474_STATUS_LAYOUT: { // L6474 - const uint16_t L6470_ADC_out = motor.GetParam(L6470_ADC_OUT) & 0x1F, - L6474_TVAL_val = motor.GetParam(L6474_TVAL) & 0x7F; - - say_axis_status(axis, sh.STATUS_AXIS_RAW); - - SERIAL_ECHOPGM("...OverCurrent Threshold: "); - sprintf_P(temp_buf, PSTR("%2d ("), OverCurrent_Threshold); - SERIAL_ECHO(temp_buf); - SERIAL_ECHO((OverCurrent_Threshold + 1) * motor.OCD_CURRENT_CONSTANT_INV); - SERIAL_ECHOPGM(" mA)"); - SERIAL_ECHOPGM(" TVAL: "); - sprintf_P(temp_buf, PSTR("%2d ("), L6474_TVAL_val); - SERIAL_ECHO(temp_buf); - SERIAL_ECHO((L6474_TVAL_val + 1) * motor.STALL_CURRENT_CONSTANT_INV); - SERIAL_ECHOLNPGM(" mA) Motor Status: NA"); - - const uint16_t MicroSteps = _BV(motor.GetParam(L6470_STEP_MODE) & 0x07); //NOMORE(MicroSteps, 16); - SERIAL_ECHOPGM("...MicroSteps: ", MicroSteps, - " ADC_OUT: ", L6470_ADC_out); - - SERIAL_ECHOLNPGM(" Vs_compensation: NA\n"); - SERIAL_ECHOLNPGM("...KVAL_HOLD: NA" - " KVAL_RUN : NA" - " KVAL_ACC: NA" - " KVAL_DEC: NA" - " V motor max = NA"); - - #if ENABLED(L6470_CHITCHAT) - DEBUG_ECHOPGM("...SLEW RATE: "); - switch ((motor.GetParam(sh.L6470_AXIS_CONFIG) & CONFIG_POW_SR) >> CONFIG_POW_SR_BIT) { - case 0: DEBUG_ECHOLNPGM("320V/uS") ; break; - case 1: DEBUG_ECHOLNPGM("75V/uS") ; break; - case 2: DEBUG_ECHOLNPGM("110V/uS") ; break; - case 3: DEBUG_ECHOLNPGM("260V/uS") ; break; - default: DEBUG_ECHOLNPGM("slew rate: ", (motor.GetParam(sh.L6470_AXIS_CONFIG) & CONFIG_POW_SR) >> CONFIG_POW_SR_BIT); break; - } - #endif - SERIAL_EOL(); - SERIAL_EOL(); - break; - } - } -} - -/** - * M906: report or set KVAL_HOLD which sets the maximum effective voltage provided by the - * PWMs to the steppers - * - * On L6474 this sets the TVAL register (same address). - * - * I - select which driver(s) to change on multi-driver axis - * (default) all drivers on the axis - * 0 - monitor only the first XYZ... driver - * 1 - monitor only X2, Y2, Z2 - * 2 - monitor only Z3 - * 3 - monitor only Z4 - * Xxxx, Yxxx, Zxxx, Exxx - axis to change (optional) - * L6474 - current in mA (4A max) - * All others - 0-255 - * - * Sets KVAL_HOLD which affects the current being driven through the stepper. - * - * L6470 is used in the STEP-CLOCK mode. KVAL_HOLD is the only KVAL_xxx - * that affects the effective voltage seen by the stepper. - */ -void GcodeSuite::M906() { - - L64xxManager.pause_monitor(true); // Keep monitor_driver() from stealing status - - #define L6470_SET_KVAL_HOLD(Q) (AXIS_IS_L64XX(Q) ? stepper##Q.setTVALCurrent(value) : stepper##Q.SetParam(L6470_KVAL_HOLD, uint8_t(value))) - - DEBUG_ECHOLNPGM("M906"); - - uint8_t report_current = true; - - #if AXIS_IS_L64XX(X2) || AXIS_IS_L64XX(Y2) || AXIS_IS_L64XX(Z2) || AXIS_IS_L64XX(Z3) || AXIS_IS_L64XX(Z4) - const int8_t index = parser.byteval('I', -1); - #else - constexpr int8_t index = -1; - #endif - - LOOP_LOGICAL_AXES(i) if (uint16_t value = parser.intval(axis_codes[i])) { - - report_current = false; - - if (planner.has_blocks_queued() || planner.cleaning_buffer_counter) { - SERIAL_ECHOLNPGM("Test aborted. Can't set KVAL_HOLD while steppers are moving."); - return; - } - - switch (i) { - #if AXIS_IS_L64XX(X) || AXIS_IS_L64XX(X2) - case X_AXIS: - #if AXIS_IS_L64XX(X) - if (index < 0 || index == 0) L6470_SET_KVAL_HOLD(X); - #endif - #if AXIS_IS_L64XX(X2) - if (index < 0 || index == 1) L6470_SET_KVAL_HOLD(X2); - #endif - break; - #endif - - #if AXIS_IS_L64XX(Y) || AXIS_IS_L64XX(Y2) - case Y_AXIS: - #if AXIS_IS_L64XX(Y) - if (index < 0 || index == 0) L6470_SET_KVAL_HOLD(Y); - #endif - #if AXIS_IS_L64XX(Y2) - if (index < 0 || index == 1) L6470_SET_KVAL_HOLD(Y2); - #endif - break; - #endif - - #if AXIS_IS_L64XX(Z) || AXIS_IS_L64XX(Z2) || AXIS_IS_L64XX(Z3) || AXIS_IS_L64XX(Z4) - case Z_AXIS: - #if AXIS_IS_L64XX(Z) - if (index < 0 || index == 0) L6470_SET_KVAL_HOLD(Z); - #endif - #if AXIS_IS_L64XX(Z2) - if (index < 0 || index == 1) L6470_SET_KVAL_HOLD(Z2); - #endif - #if AXIS_IS_L64XX(Z3) - if (index < 0 || index == 2) L6470_SET_KVAL_HOLD(Z3); - #endif - #if AXIS_IS_L64XX(Z4) - if (index < 0 || index == 3) L6470_SET_KVAL_HOLD(Z4); - #endif - break; - #endif - - #if AXIS_IS_L64XX(E0) || AXIS_IS_L64XX(E1) || AXIS_IS_L64XX(E2) || AXIS_IS_L64XX(E3) || AXIS_IS_L64XX(E4) || AXIS_IS_L64XX(E5) || AXIS_IS_L64XX(E6) || AXIS_IS_L64XX(E7) - case E_AXIS: { - const int8_t eindex = get_target_e_stepper_from_command(-2); - #if AXIS_IS_L64XX(E0) - if (eindex < 0 || eindex == 0) L6470_SET_KVAL_HOLD(E0); - #endif - #if AXIS_IS_L64XX(E1) - if (eindex < 0 || eindex == 1) L6470_SET_KVAL_HOLD(E1); - #endif - #if AXIS_IS_L64XX(E2) - if (eindex < 0 || eindex == 2) L6470_SET_KVAL_HOLD(E2); - #endif - #if AXIS_IS_L64XX(E3) - if (eindex < 0 || eindex == 3) L6470_SET_KVAL_HOLD(E3); - #endif - #if AXIS_IS_L64XX(E4) - if (eindex < 0 || eindex == 4) L6470_SET_KVAL_HOLD(E4); - #endif - #if AXIS_IS_L64XX(E5) - if (eindex < 0 || eindex == 5) L6470_SET_KVAL_HOLD(E5); - #endif - #if AXIS_IS_L64XX(E6) - if (eindex < 0 || eindex == 6) L6470_SET_KVAL_HOLD(E6); - #endif - #if AXIS_IS_L64XX(E7) - if (eindex < 0 || eindex == 7) L6470_SET_KVAL_HOLD(E7); - #endif - } break; - #endif - } - } - - if (report_current) { - #define L64XX_REPORT_CURRENT(Q) L64XX_report_current(stepper##Q, Q) - - L64xxManager.spi_active = true; // Tell set_directions() a series of SPI transfers is underway - - #if AXIS_IS_L64XX(X) - L64XX_REPORT_CURRENT(X); - #endif - #if AXIS_IS_L64XX(X2) - L64XX_REPORT_CURRENT(X2); - #endif - #if AXIS_IS_L64XX(Y) - L64XX_REPORT_CURRENT(Y); - #endif - #if AXIS_IS_L64XX(Y2) - L64XX_REPORT_CURRENT(Y2); - #endif - #if AXIS_IS_L64XX(Z) - L64XX_REPORT_CURRENT(Z); - #endif - #if AXIS_IS_L64XX(Z2) - L64XX_REPORT_CURRENT(Z2); - #endif - #if AXIS_IS_L64XX(Z3) - L64XX_REPORT_CURRENT(Z3); - #endif - #if AXIS_IS_L64XX(Z4) - L64XX_REPORT_CURRENT(Z4); - #endif - #if AXIS_IS_L64XX(E0) - L64XX_REPORT_CURRENT(E0); - #endif - #if AXIS_IS_L64XX(E1) - L64XX_REPORT_CURRENT(E1); - #endif - #if AXIS_IS_L64XX(E2) - L64XX_REPORT_CURRENT(E2); - #endif - #if AXIS_IS_L64XX(E3) - L64XX_REPORT_CURRENT(E3); - #endif - #if AXIS_IS_L64XX(E4) - L64XX_REPORT_CURRENT(E4); - #endif - #if AXIS_IS_L64XX(E5) - L64XX_REPORT_CURRENT(E5); - #endif - #if AXIS_IS_L64XX(E6) - L64XX_REPORT_CURRENT(E6); - #endif - #if AXIS_IS_L64XX(E7) - L64XX_REPORT_CURRENT(E7); - #endif - - L64xxManager.spi_active = false; // done with all SPI transfers - clear handshake flags - L64xxManager.spi_abort = false; - L64xxManager.pause_monitor(false); - } -} - -#endif // HAS_L64XX diff --git a/Marlin/src/gcode/feature/L6470/M916-M918.cpp b/Marlin/src/gcode/feature/L6470/M916-M918.cpp deleted file mode 100644 index 8d614603ed..0000000000 --- a/Marlin/src/gcode/feature/L6470/M916-M918.cpp +++ /dev/null @@ -1,651 +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 . - * - */ - -// -// NOTE: All tests assume each axis uses matching driver chips. -// - -#include "../../../inc/MarlinConfig.h" - -#if HAS_L64XX - -#include "../../gcode.h" -#include "../../../module/stepper/indirection.h" -#include "../../../module/planner.h" -#include "../../../libs/L64XX/L64XX_Marlin.h" - -#define DEBUG_OUT ENABLED(L6470_CHITCHAT) -#include "../../../core/debug_out.h" - -/** - * M916: increase KVAL_HOLD until get thermal warning - * NOTE - on L6474 it is TVAL that is used - * - * J - select which driver(s) to monitor on multi-driver axis - * 0 - (default) monitor all drivers on the axis or E0 - * 1 - monitor only X, Y, Z, E1 - * 2 - monitor only X2, Y2, Z2, E2 - * 3 - monitor only Z3, E3 - * 4 - monitor only Z4, E4 - * - * Xxxx, Yxxx, Zxxx, Exxx - axis to be monitored with displacement - * xxx (1-255) is distance moved on either side of current position - * - * F - feedrate - * optional - will use default max feedrate from configuration.h if not specified - * - * T - current (mA) setting for TVAL (0 - 4A in 31.25mA increments, rounds down) - L6474 only - * optional - will report current value from driver if not specified - * - * K - value for KVAL_HOLD (0 - 255) (ignored for L6474) - * optional - will report current value from driver if not specified - * - * D - time (in seconds) to run each setting of KVAL_HOLD/TVAL - * optional - defaults to zero (runs each setting once) - */ - -/** - * This routine is also useful for determining the approximate KVAL_HOLD - * where the stepper stops losing steps. The sound will get noticeably quieter - * as it stops losing steps. - */ - -void GcodeSuite::M916() { - - DEBUG_ECHOLNPGM("M916"); - - L64xxManager.pause_monitor(true); // Keep monitor_driver() from stealing status - - // Variables used by L64xxManager.get_user_input function - some may not be used - char axis_mon[3][3] = { {" "}, {" "}, {" "} }; // list of Axes to be monitored - L64XX_axis_t axis_index[3]; - uint16_t axis_status[3]; - uint8_t driver_count = 1; - float position_max; - float position_min; - float final_feedrate; - uint8_t kval_hold; - uint8_t OCD_TH_val = 0; - uint8_t STALL_TH_val = 0; - uint16_t over_current_threshold; - constexpr uint8_t over_current_flag = false; // M916 doesn't play with the overcurrent thresholds - - #define DRIVER_TYPE_L6474(Q) AXIS_DRIVER_TYPE_##Q(L6474) - - uint8_t j; // general purpose counter - - if (L64xxManager.get_user_input(driver_count, axis_index, axis_mon, position_max, position_min, final_feedrate, kval_hold, over_current_flag, OCD_TH_val, STALL_TH_val, over_current_threshold)) - return; // quit if invalid user input - - DEBUG_ECHOLNPGM("feedrate = ", final_feedrate); - - planner.synchronize(); // wait for all current movement commands to complete - - const L64XX_Marlin::L64XX_shadow_t &sh = L64xxManager.shadow; - for (j = 0; j < driver_count; j++) - L64xxManager.get_status(axis_index[j]); // clear out any pre-existing error flags - - char temp_axis_string[] = " "; - temp_axis_string[0] = axis_mon[0][0]; // need to have a string for use within sprintf format section - char gcode_string[80]; - uint16_t status_composite = 0; - - uint16_t M91x_counter = kval_hold; - uint16_t M91x_counter_max; - if (sh.STATUS_AXIS_LAYOUT == L6474_STATUS_LAYOUT) { - M91x_counter_max = 128; // TVAL is 7 bits - LIMIT(M91x_counter, 0U, 127U); - } - else - M91x_counter_max = 256; // KVAL_HOLD is 8 bits - - uint8_t M91x_delay_s = parser.byteval('D'); // get delay in seconds - millis_t M91x_delay_ms = SEC_TO_MS(M91x_delay_s * 60); - millis_t M91x_delay_end; - - DEBUG_ECHOLNPGM(".\n."); - - do { - - if (sh.STATUS_AXIS_LAYOUT == L6474_STATUS_LAYOUT) - DEBUG_ECHOLNPGM("TVAL current (mA) = ", (M91x_counter + 1) * sh.AXIS_STALL_CURRENT_CONSTANT_INV); // report TVAL current for this run - else - DEBUG_ECHOLNPGM("kval_hold = ", M91x_counter); // report KVAL_HOLD for this run - - for (j = 0; j < driver_count; j++) - L64xxManager.set_param(axis_index[j], L6470_KVAL_HOLD, M91x_counter); //set KVAL_HOLD or TVAL (same register address) - - M91x_delay_end = millis() + M91x_delay_ms; - do { - // turn the motor(s) both directions - sprintf_P(gcode_string, PSTR("G0 %s%03d F%03d"), temp_axis_string, uint16_t(position_min), uint16_t(final_feedrate)); - process_subcommands_now(gcode_string); - - sprintf_P(gcode_string, PSTR("G0 %s%03d F%03d"), temp_axis_string, uint16_t(position_max), uint16_t(final_feedrate)); - process_subcommands_now(gcode_string); - - // get the status after the motors have stopped - planner.synchronize(); - - status_composite = 0; // clear out the old bits - - for (j = 0; j < driver_count; j++) { - axis_status[j] = (~L64xxManager.get_status(axis_index[j])) & sh.L6470_ERROR_MASK; // bits of interest are all active low - status_composite |= axis_status[j] ; - } - - if (status_composite) break; - } while (millis() < M91x_delay_end); - - if (status_composite) break; - - M91x_counter++; - - } while (!(status_composite & (sh.STATUS_AXIS_TH_WRN | sh.STATUS_AXIS_TH_SD)) && (M91x_counter < M91x_counter_max)); - - DEBUG_ECHOLNPGM("."); - - #if ENABLED(L6470_CHITCHAT) - if (status_composite) { - L64xxManager.error_status_decode(status_composite, axis_index[0], - sh.STATUS_AXIS_TH_SD, sh.STATUS_AXIS_TH_WRN, - sh.STATUS_AXIS_STEP_LOSS_A, sh.STATUS_AXIS_STEP_LOSS_B, - sh.STATUS_AXIS_OCD, sh.STATUS_AXIS_LAYOUT); - DEBUG_ECHOLNPGM("."); - } - #endif - - if ((status_composite & (sh.STATUS_AXIS_TH_WRN | sh.STATUS_AXIS_TH_SD))) - DEBUG_ECHOLNPGM(".\n.\nTest completed normally - Thermal warning/shutdown has occurred"); - else if (status_composite) - DEBUG_ECHOLNPGM(".\n.\nTest completed abnormally - non-thermal error has occurred"); - else - DEBUG_ECHOLNPGM(".\n.\nTest completed normally - Unable to get to thermal warning/shutdown"); - - L64xxManager.pause_monitor(false); -} - -/** - * M917: Find minimum current thresholds - * - * Decrease OCD current until overcurrent error - * Increase OCD until overcurrent error goes away - * Decrease stall threshold until stall (not done on L6474) - * Increase stall until stall error goes away (not done on L6474) - * - * J - select which driver(s) to monitor on multi-driver axis - * 0 - (default) monitor all drivers on the axis or E0 - * 1 - monitor only X, Y, Z, E1 - * 2 - monitor only X2, Y2, Z2, E2 - * Xxxx, Yxxx, Zxxx, Exxx - axis to be monitored with displacement - * xxx (1-255) is distance moved on either side of current position - * - * F - feedrate - * optional - will use default max feedrate from Configuration.h if not specified - * - * I - starting over-current threshold - * optional - will report current value from driver if not specified - * if there are multiple drivers on the axis then all will be set the same - * - * T - current (mA) setting for TVAL (0 - 4A in 31.25mA increments, rounds down) - L6474 only - * optional - will report current value from driver if not specified - * - * K - value for KVAL_HOLD (0 - 255) (ignored for L6474) - * optional - will report current value from driver if not specified - */ -void GcodeSuite::M917() { - - DEBUG_ECHOLNPGM("M917"); - - L64xxManager.pause_monitor(true); // Keep monitor_driver() from stealing status - - char axis_mon[3][3] = { {" "}, {" "}, {" "} }; // list of Axes to be monitored - L64XX_axis_t axis_index[3]; - uint16_t axis_status[3]; - uint8_t driver_count = 1; - float position_max; - float position_min; - float final_feedrate; - uint8_t kval_hold; - uint8_t OCD_TH_val = 0; - uint8_t STALL_TH_val = 0; - uint16_t over_current_threshold; - constexpr uint8_t over_current_flag = true; - - uint8_t j; // general purpose counter - - if (L64xxManager.get_user_input(driver_count, axis_index, axis_mon, position_max, position_min, final_feedrate, kval_hold, over_current_flag, OCD_TH_val, STALL_TH_val, over_current_threshold)) - return; // quit if invalid user input - - DEBUG_ECHOLNPGM("feedrate = ", final_feedrate); - - planner.synchronize(); // wait for all current movement commands to complete - - const L64XX_Marlin::L64XX_shadow_t &sh = L64xxManager.shadow; - for (j = 0; j < driver_count; j++) - L64xxManager.get_status(axis_index[j]); // clear error flags - char temp_axis_string[] = " "; - temp_axis_string[0] = axis_mon[0][0]; // need a sprintf format string - char gcode_string[80]; - uint16_t status_composite = 0; - uint8_t test_phase = 0; // 0 - decreasing OCD - exit when OCD warning occurs (ignore STALL) - // 1 - increasing OCD - exit when OCD warning stops (ignore STALL) - // 2 - OCD finalized - decreasing STALL - exit when STALL warning happens - // 3 - OCD finalized - increasing STALL - exit when STALL warning stop - // 4 - all testing completed - DEBUG_ECHOPGM(".\n.\n.\nover_current threshold : ", (OCD_TH_val + 1) * 375); // first status display - DEBUG_ECHOPGM(" (OCD_TH: : ", OCD_TH_val); - if (sh.STATUS_AXIS_LAYOUT != L6474_STATUS_LAYOUT) { - DEBUG_ECHOPGM(") Stall threshold: ", (STALL_TH_val + 1) * 31.25); - DEBUG_ECHOPGM(" (STALL_TH: ", STALL_TH_val); - } - DEBUG_ECHOLNPGM(")"); - - do { - - if (sh.STATUS_AXIS_LAYOUT != L6474_STATUS_LAYOUT) DEBUG_ECHOPGM("STALL threshold : ", (STALL_TH_val + 1) * 31.25); - DEBUG_ECHOLNPGM(" OCD threshold : ", (OCD_TH_val + 1) * 375); - - sprintf_P(gcode_string, PSTR("G0 %s%03d F%03d"), temp_axis_string, uint16_t(position_min), uint16_t(final_feedrate)); - process_subcommands_now(gcode_string); - - sprintf_P(gcode_string, PSTR("G0 %s%03d F%03d"), temp_axis_string, uint16_t(position_max), uint16_t(final_feedrate)); - process_subcommands_now(gcode_string); - - planner.synchronize(); - - status_composite = 0; // clear out the old bits - - for (j = 0; j < driver_count; j++) { - axis_status[j] = (~L64xxManager.get_status(axis_index[j])) & sh.L6470_ERROR_MASK; // bits of interest are all active low - status_composite |= axis_status[j]; - } - - if (status_composite && (status_composite & sh.STATUS_AXIS_UVLO)) { - DEBUG_ECHOLNPGM("Test aborted (Undervoltage lockout active)"); - #if ENABLED(L6470_CHITCHAT) - for (j = 0; j < driver_count; j++) { - if (j) DEBUG_ECHOPGM("..."); - L64xxManager.error_status_decode(axis_status[j], axis_index[j], - sh.STATUS_AXIS_TH_SD, sh.STATUS_AXIS_TH_WRN, - sh.STATUS_AXIS_STEP_LOSS_A, sh.STATUS_AXIS_STEP_LOSS_B, - sh.STATUS_AXIS_OCD, sh.STATUS_AXIS_LAYOUT); - } - #endif - return; - } - - if (status_composite & (sh.STATUS_AXIS_TH_WRN | sh.STATUS_AXIS_TH_SD)) { - DEBUG_ECHOLNPGM("thermal problem - waiting for chip(s) to cool down "); - uint16_t status_composite_temp = 0; - uint8_t k = 0; - do { - k++; - if (!(k % 4)) { - kval_hold *= 0.95; - DEBUG_EOL(); - DEBUG_ECHOLNPGM("Lowering KVAL_HOLD by about 5% to ", kval_hold); - for (j = 0; j < driver_count; j++) - L64xxManager.set_param(axis_index[j], L6470_KVAL_HOLD, kval_hold); - } - DEBUG_ECHOLNPGM("."); - reset_stepper_timeout(); // keep steppers powered - watchdog_refresh(); - safe_delay(5000); - status_composite_temp = 0; - for (j = 0; j < driver_count; j++) { - axis_status[j] = (~L64xxManager.get_status(axis_index[j])) & sh.L6470_ERROR_MASK; // bits of interest are all active low - status_composite_temp |= axis_status[j]; - } - } - while (status_composite_temp & (sh.STATUS_AXIS_TH_WRN | sh.STATUS_AXIS_TH_SD)); - DEBUG_EOL(); - } - if (status_composite & (sh.STATUS_AXIS_STEP_LOSS_A | sh.STATUS_AXIS_STEP_LOSS_B | sh.STATUS_AXIS_OCD)) { - switch (test_phase) { - - case 0: { - if (status_composite & sh.STATUS_AXIS_OCD) { - // phase 0 with OCD warning - time to go to next phase - if (OCD_TH_val >= sh.AXIS_OCD_TH_MAX) { - OCD_TH_val = sh.AXIS_OCD_TH_MAX; // limit to max - test_phase = 2; // at highest value so skip phase 1 - //DEBUG_ECHOLNPGM("LOGIC E0A OCD at highest - skip to 2"); - DEBUG_ECHOLNPGM("OCD at highest - OCD finalized"); - } - else { - OCD_TH_val++; // normal exit to next phase - test_phase = 1; // setup for first pass of phase 1 - //DEBUG_ECHOLNPGM("LOGIC E0B - inc OCD & go to 1"); - DEBUG_ECHOLNPGM("inc OCD"); - } - } - else { // phase 0 without OCD warning - keep on decrementing if can - if (OCD_TH_val) { - OCD_TH_val--; // try lower value - //DEBUG_ECHOLNPGM("LOGIC E0C - dec OCD"); - DEBUG_ECHOLNPGM("dec OCD"); - } - else { - test_phase = 2; // at lowest value without warning so skip phase 1 - //DEBUG_ECHOLNPGM("LOGIC E0D - OCD at latest - go to 2"); - DEBUG_ECHOLNPGM("OCD finalized"); - } - } - } break; - - case 1: { - if (status_composite & sh.STATUS_AXIS_OCD) { - // phase 1 with OCD warning - increment if can - if (OCD_TH_val >= sh.AXIS_OCD_TH_MAX) { - OCD_TH_val = sh.AXIS_OCD_TH_MAX; // limit to max - test_phase = 2; // at highest value so go to next phase - //DEBUG_ECHOLNPGM("LOGIC E1A - OCD at max - go to 2"); - DEBUG_ECHOLNPGM("OCD finalized"); - } - else { - OCD_TH_val++; // try a higher value - //DEBUG_ECHOLNPGM("LOGIC E1B - inc OCD"); - DEBUG_ECHOLNPGM("inc OCD"); - } - } - else { // phase 1 without OCD warning - normal exit to phase 2 - test_phase = 2; - //DEBUG_ECHOLNPGM("LOGIC E1C - no OCD warning - go to 1"); - DEBUG_ECHOLNPGM("OCD finalized"); - } - } break; - - case 2: { - if (sh.STATUS_AXIS_LAYOUT == L6474_STATUS_LAYOUT) { // skip all STALL_TH steps if L6474 - test_phase = 4; - break; - } - if (status_composite & (sh.STATUS_AXIS_STEP_LOSS_A | sh.STATUS_AXIS_STEP_LOSS_B)) { - // phase 2 with stall warning - time to go to next phase - if (STALL_TH_val >= 127) { - STALL_TH_val = 127; // limit to max - //DEBUG_ECHOLNPGM("LOGIC E2A - STALL warning, STALL at max, quit"); - DEBUG_ECHOLNPGM("finished - STALL at maximum value but still have stall warning"); - test_phase = 4; - } - else { - test_phase = 3; // normal exit to next phase (found failing value of STALL) - STALL_TH_val++; // setup for first pass of phase 3 - //DEBUG_ECHOLNPGM("LOGIC E2B - INC - STALL warning, inc Stall, go to 3"); - DEBUG_ECHOLNPGM("inc Stall"); - } - } - else { // phase 2 without stall warning - decrement if can - if (STALL_TH_val) { - STALL_TH_val--; // try a lower value - //DEBUG_ECHOLNPGM("LOGIC E2C - no STALL, dec STALL"); - DEBUG_ECHOLNPGM("dec STALL"); - } - else { - DEBUG_ECHOLNPGM("finished - STALL at lowest value but still do NOT have stall warning"); - test_phase = 4; - //DEBUG_ECHOLNPGM("LOGIC E2D - no STALL, at lowest so quit"); - } - } - } break; - - case 3: { - if (sh.STATUS_AXIS_LAYOUT == L6474_STATUS_LAYOUT) { // skip all STALL_TH steps if L6474 - test_phase = 4; - break; - } - if (status_composite & (sh.STATUS_AXIS_STEP_LOSS_A | sh.STATUS_AXIS_STEP_LOSS_B)) { - // phase 3 with stall warning - increment if can - if (STALL_TH_val >= 127) { - STALL_TH_val = 127; // limit to max - DEBUG_ECHOLNPGM("finished - STALL at maximum value but still have stall warning"); - test_phase = 4; - //DEBUG_ECHOLNPGM("LOGIC E3A - STALL, at max so quit"); - } - else { - STALL_TH_val++; // still looking for passing value - //DEBUG_ECHOLNPGM("LOGIC E3B - STALL, inc stall"); - DEBUG_ECHOLNPGM("inc stall"); - } - } - else { //phase 3 without stall warning but have OCD warning - DEBUG_ECHOLNPGM("Hardware problem - OCD warning without STALL warning"); - test_phase = 4; - //DEBUG_ECHOLNPGM("LOGIC E3C - not STALLED, hardware problem (quit)"); - } - } break; - - } - - } - else { - switch (test_phase) { - case 0: { // phase 0 without OCD warning - keep on decrementing if can - if (OCD_TH_val) { - OCD_TH_val--; // try lower value - //DEBUG_ECHOLNPGM("LOGIC N0A - DEC OCD"); - DEBUG_ECHOLNPGM("DEC OCD"); - } - else { - test_phase = 2; // at lowest value without warning so skip phase 1 - //DEBUG_ECHOLNPGM("LOGIC N0B - OCD at lowest (go to phase 2)"); - DEBUG_ECHOLNPGM("OCD finalized"); - } - } break; - - case 1: //DEBUG_ECHOLNPGM("LOGIC N1 (go directly to 2)"); // phase 1 without OCD warning - drop directly to phase 2 - DEBUG_ECHOLNPGM("OCD finalized"); - - case 2: { // phase 2 without stall warning - keep on decrementing if can - if (sh.STATUS_AXIS_LAYOUT == L6474_STATUS_LAYOUT) { // skip all STALL_TH steps if L6474 - test_phase = 4; - break; - } - if (STALL_TH_val) { - STALL_TH_val--; // try a lower value (stay in phase 2) - //DEBUG_ECHOLNPGM("LOGIC N2B - dec STALL"); - DEBUG_ECHOLNPGM("dec STALL"); - } - else { - DEBUG_ECHOLNPGM("finished - STALL at lowest value but still no stall warning"); - test_phase = 4; - //DEBUG_ECHOLNPGM("LOGIC N2C - STALL at lowest (quit)"); - } - } break; - - case 3: { - if (sh.STATUS_AXIS_LAYOUT == L6474_STATUS_LAYOUT) { // skip all STALL_TH steps if L6474 - test_phase = 4; - break; - } - test_phase = 4; - //DEBUG_ECHOLNPGM("LOGIC N3 - finished!"); - DEBUG_ECHOLNPGM("finished!"); - } break; // phase 3 without any warnings - desired exit - } // - } // end of status checks - - if (test_phase != 4) { - for (j = 0; j < driver_count; j++) { // update threshold(s) - L64xxManager.set_param(axis_index[j], L6470_OCD_TH, OCD_TH_val); - if (sh.STATUS_AXIS_LAYOUT != L6474_STATUS_LAYOUT) L64xxManager.set_param(axis_index[j], L6470_STALL_TH, STALL_TH_val); - if (L64xxManager.get_param(axis_index[j], L6470_OCD_TH) != OCD_TH_val) DEBUG_ECHOLNPGM("OCD mismatch"); - if ((L64xxManager.get_param(axis_index[j], L6470_STALL_TH) != STALL_TH_val) && (sh.STATUS_AXIS_LAYOUT != L6474_STATUS_LAYOUT)) DEBUG_ECHOLNPGM("STALL mismatch"); - } - } - - } while (test_phase != 4); - - DEBUG_ECHOLNPGM("."); - if (status_composite) { - #if ENABLED(L6470_CHITCHAT) - for (j = 0; j < driver_count; j++) { - if (j) DEBUG_ECHOPGM("..."); - L64xxManager.error_status_decode(axis_status[j], axis_index[j], - sh.STATUS_AXIS_TH_SD, sh.STATUS_AXIS_TH_WRN, - sh.STATUS_AXIS_STEP_LOSS_A, sh.STATUS_AXIS_STEP_LOSS_B, - sh.STATUS_AXIS_OCD, sh.STATUS_AXIS_LAYOUT); - } - DEBUG_ECHOLNPGM("."); - #endif - DEBUG_ECHOLNPGM("Completed with errors"); - } - else - DEBUG_ECHOLNPGM("Completed with no errors"); - DEBUG_ECHOLNPGM("."); - - L64xxManager.pause_monitor(false); -} - -/** - * M918: increase speed until error or max feedrate achieved (as shown in configuration.h)) - * - * J - select which driver(s) to monitor on multi-driver axis - * 0 - (default) monitor all drivers on the axis or E0 - * 1 - monitor only X, Y, Z, E1 - * 2 - monitor only X2, Y2, Z2, E2 - * Xxxx, Yxxx, Zxxx, Exxx - axis to be monitored with displacement - * xxx (1-255) is distance moved on either side of current position - * - * I - over current threshold - * optional - will report current value from driver if not specified - * - * T - current (mA) setting for TVAL (0 - 4A in 31.25mA increments, rounds down) - L6474 only - * optional - will report current value from driver if not specified - * - * K - value for KVAL_HOLD (0 - 255) (ignored for L6474) - * optional - will report current value from driver if not specified - * - * M - value for microsteps (1 - 128) (optional) - * optional - will report current value from driver if not specified - */ -void GcodeSuite::M918() { - - DEBUG_ECHOLNPGM("M918"); - - L64xxManager.pause_monitor(true); // Keep monitor_driver() from stealing status - - char axis_mon[3][3] = { {" "}, {" "}, {" "} }; // list of Axes to be monitored - L64XX_axis_t axis_index[3]; - uint16_t axis_status[3]; - uint8_t driver_count = 1; - float position_max, position_min; - float final_feedrate; - uint8_t kval_hold; - uint8_t OCD_TH_val = 0; - uint8_t STALL_TH_val = 0; - uint16_t over_current_threshold; - constexpr uint8_t over_current_flag = true; - - const L64XX_Marlin::L64XX_shadow_t &sh = L64xxManager.shadow; - - uint8_t j; // general purpose counter - - if (L64xxManager.get_user_input(driver_count, axis_index, axis_mon, position_max, position_min, final_feedrate, kval_hold, over_current_flag, OCD_TH_val, STALL_TH_val, over_current_threshold)) - return; // quit if invalid user input - - L64xxManager.get_status(axis_index[0]); // populate shadow array - - uint8_t m_steps = parser.byteval('M'); - - if (m_steps != 0) { - LIMIT(m_steps, 1, sh.STATUS_AXIS_LAYOUT == L6474_STATUS_LAYOUT ? 16 : 128); // L6474 - - uint8_t stepVal; - for (stepVal = 0; stepVal < 8; stepVal++) { // convert to L64xx register value - if (m_steps == 1) break; - m_steps >>= 1; - } - - if (sh.STATUS_AXIS_LAYOUT == L6474_STATUS_LAYOUT) - stepVal |= 0x98; // NO SYNC - else - stepVal |= (!SYNC_EN) | SYNC_SEL_1 | stepVal; - - for (j = 0; j < driver_count; j++) { - L64xxManager.set_param(axis_index[j], dSPIN_HARD_HIZ, 0); // can't write STEP register if stepper being powered - // results in an extra NOOP being sent (data 00) - L64xxManager.set_param(axis_index[j], L6470_STEP_MODE, stepVal); // set microsteps - } - } - m_steps = L64xxManager.get_param(axis_index[0], L6470_STEP_MODE) & 0x07; // get microsteps - - DEBUG_ECHOLNPGM("Microsteps = ", _BV(m_steps)); - DEBUG_ECHOLNPGM("target (maximum) feedrate = ", final_feedrate); - - const float feedrate_inc = final_feedrate / 10, // Start at 1/10 of max & go up by 1/10 per step - fr_limit = final_feedrate * 0.99f; // Rounding-safe comparison value - float current_feedrate = 0; - - planner.synchronize(); // Wait for moves to complete - - for (j = 0; j < driver_count; j++) - L64xxManager.get_status(axis_index[j]); // Clear error flags - - char temp_axis_string[2] = " "; - temp_axis_string[0] = axis_mon[0][0]; // Need a sprintf format string - //temp_axis_string[1] = '\n'; - - char gcode_string[80]; - uint16_t status_composite = 0; - DEBUG_ECHOLNPGM(".\n.\n."); // Make feedrate outputs easier to read - - do { - current_feedrate += feedrate_inc; - DEBUG_ECHOLNPGM("...feedrate = ", current_feedrate); - - sprintf_P(gcode_string, PSTR("G0 %s%03d F%03d"), temp_axis_string, uint16_t(position_min), uint16_t(current_feedrate)); - process_subcommands_now(gcode_string); - - sprintf_P(gcode_string, PSTR("G0 %s%03d F%03d"), temp_axis_string, uint16_t(position_max), uint16_t(current_feedrate)); - process_subcommands_now(gcode_string); - - planner.synchronize(); - - for (j = 0; j < driver_count; j++) { - axis_status[j] = (~L64xxManager.get_status(axis_index[j])) & 0x0800; // Bits of interest are all active LOW - status_composite |= axis_status[j]; - } - if (status_composite) break; // Break on any error - } while (current_feedrate < fr_limit); - - DEBUG_ECHOPGM("Completed with "); - if (status_composite) { - DEBUG_ECHOLNPGM("errors"); - #if ENABLED(L6470_CHITCHAT) - for (j = 0; j < driver_count; j++) { - if (j) DEBUG_ECHOPGM("..."); - L64xxManager.error_status_decode(axis_status[j], axis_index[j], - sh.STATUS_AXIS_TH_SD, sh.STATUS_AXIS_TH_WRN, - sh.STATUS_AXIS_STEP_LOSS_A, sh.STATUS_AXIS_STEP_LOSS_B, - sh.STATUS_AXIS_OCD, sh.STATUS_AXIS_LAYOUT); - } - #endif - } - else - DEBUG_ECHOLNPGM("no errors"); - - L64xxManager.pause_monitor(false); -} - -#endif // HAS_L64XX diff --git a/Marlin/src/gcode/feature/adc/M3426.cpp b/Marlin/src/gcode/feature/adc/M3426.cpp index 8205fa01f2..2820c8b880 100644 --- a/Marlin/src/gcode/feature/adc/M3426.cpp +++ b/Marlin/src/gcode/feature/adc/M3426.cpp @@ -28,6 +28,8 @@ #include "../../../feature/adc/adc_mcp3426.h" +#define MCP3426_BASE_ADDR (0b1101 << 3) + /** * M3426: Read 16 bit (signed) value from I2C MCP3426 ADC device * @@ -36,12 +38,15 @@ * M3426 I 0 or 1, invert reply */ void GcodeSuite::M3426() { - uint8_t channel = parser.byteval('C', 1), // Select the channel 1 or 2 - gain = parser.byteval('G', 1); - const bool inverted = parser.byteval('I') == 1; + uint8_t channel = parser.byteval('C', 1), // Channel 1 or 2 + gain = parser.byteval('G', 1), // Gain 1, 2, 4, or 8 + address = parser.byteval('A', 3); // Address 0-7 (or 104-111) + const bool inverted = parser.boolval('I'); - if (channel <= 2 && (gain == 1 || gain == 2 || gain == 4 || gain == 8)) { - int16_t result = mcp3426.ReadValue(channel, gain); + if (address <= 7) address += MCP3426_BASE_ADDR; + + if (WITHIN(channel, 1, 2) && (gain == 1 || gain == 2 || gain == 4 || gain == 8) && WITHIN(address, MCP3426_BASE_ADDR, MCP3426_BASE_ADDR + 7)) { + int16_t result = mcp3426.ReadValue(channel, gain, address); if (mcp3426.Error == false) { if (inverted) { diff --git a/Marlin/src/gcode/feature/cancel/M486.cpp b/Marlin/src/gcode/feature/cancel/M486.cpp index 1f14ae0fd2..c1e90d1b96 100644 --- a/Marlin/src/gcode/feature/cancel/M486.cpp +++ b/Marlin/src/gcode/feature/cancel/M486.cpp @@ -44,14 +44,14 @@ void GcodeSuite::M486() { cancelable.object_count = parser.intval('T', 1); } - if (parser.seen('S')) + if (parser.seenval('S')) cancelable.set_active_object(parser.value_int()); if (parser.seen('C')) cancelable.cancel_active_object(); - if (parser.seen('P')) cancelable.cancel_object(parser.value_int()); + if (parser.seenval('P')) cancelable.cancel_object(parser.value_int()); - if (parser.seen('U')) cancelable.uncancel_object(parser.value_int()); + if (parser.seenval('U')) cancelable.uncancel_object(parser.value_int()); } #endif // CANCEL_OBJECTS diff --git a/Marlin/src/gcode/feature/clean/G12.cpp b/Marlin/src/gcode/feature/clean/G12.cpp index 999a9b10bd..0113170f1d 100644 --- a/Marlin/src/gcode/feature/clean/G12.cpp +++ b/Marlin/src/gcode/feature/clean/G12.cpp @@ -45,9 +45,10 @@ * X, Y, Z : Specify axes to move during cleaning. Default: ALL. */ void GcodeSuite::G12() { + // Don't allow nozzle cleaning without homing first - if (homing_needed_error(linear_bits & ~TERN0(NOZZLE_CLEAN_NO_Z, Z_AXIS) & ~TERN0(NOZZLE_CLEAN_NO_Y, Y_AXIS))) - return; + constexpr main_axes_bits_t clean_axis_mask = main_axes_mask & ~TERN0(NOZZLE_CLEAN_NO_Z, Z_AXIS) & ~TERN0(NOZZLE_CLEAN_NO_Y, Y_AXIS); + if (homing_needed_error(clean_axis_mask)) return; #ifdef WIPE_SEQUENCE_COMMANDS if (!parser.seen_any()) { diff --git a/Marlin/src/gcode/feature/digipot/M907-M910.cpp b/Marlin/src/gcode/feature/digipot/M907-M910.cpp index 3b66f78593..9ebe713cde 100644 --- a/Marlin/src/gcode/feature/digipot/M907-M910.cpp +++ b/Marlin/src/gcode/feature/digipot/M907-M910.cpp @@ -40,56 +40,76 @@ /** * M907: Set digital trimpot motor current using axis codes X [Y] [Z] [I] [J] [K] [U] [V] [W] [E] - * B - Special case for 4th (E) axis - * S - Special case to set first 3 axes + * B - Special case for E1 (Requires DIGIPOTSS_PIN or DIGIPOT_MCP4018 or DIGIPOT_MCP4451) + * C - Special case for E2 (Requires DIGIPOTSS_PIN or DIGIPOT_MCP4018 or DIGIPOT_MCP4451) + * S - Set current in mA for all axes (Requires DIGIPOTSS_PIN or DIGIPOT_MCP4018 or DIGIPOT_MCP4451), or + * Set percentage of max current for all axes (Requires HAS_DIGIPOT_DAC) */ void GcodeSuite::M907() { #if HAS_MOTOR_CURRENT_SPI - if (!parser.seen("BS" LOGICAL_AXES_STRING)) + if (!parser.seen("BS" STR_AXES_LOGICAL)) return M907_report(); - LOOP_LOGICAL_AXES(i) if (parser.seenval(IAXIS_CHAR(i))) stepper.set_digipot_current(i, parser.value_int()); - if (parser.seenval('B')) stepper.set_digipot_current(4, parser.value_int()); - if (parser.seenval('S')) LOOP_LE_N(i, 4) stepper.set_digipot_current(i, parser.value_int()); + if (parser.seenval('S')) LOOP_L_N(i, MOTOR_CURRENT_COUNT) stepper.set_digipot_current(i, parser.value_int()); + LOOP_LOGICAL_AXES(i) if (parser.seenval(IAXIS_CHAR(i))) stepper.set_digipot_current(i, parser.value_int()); // X Y Z (I J K U V W) E (map to drivers according to DIGIPOT_CHANNELS. Default with NUM_AXES 3: map X Y Z E to X Y Z E0) + // Additional extruders use B,C. + // TODO: Change these parameters because 'E' is used and D should be reserved for debugging. B? + #if E_STEPPERS >= 2 + if (parser.seenval('B')) stepper.set_digipot_current(E_AXIS + 1, parser.value_int()); + #if E_STEPPERS >= 3 + if (parser.seenval('C')) stepper.set_digipot_current(E_AXIS + 2, parser.value_int()); + #endif + #endif #elif HAS_MOTOR_CURRENT_PWM - if (!parser.seen( - #if ANY_PIN(MOTOR_CURRENT_PWM_X, MOTOR_CURRENT_PWM_Y, MOTOR_CURRENT_PWM_XY, MOTOR_CURRENT_PWM_I, MOTOR_CURRENT_PWM_J, MOTOR_CURRENT_PWM_K, MOTOR_CURRENT_PWM_U, MOTOR_CURRENT_PWM_V, MOTOR_CURRENT_PWM_W) - "XY" SECONDARY_AXIS_GANG("I", "J", "K", "U", "V", "W") + #if ANY_PIN(MOTOR_CURRENT_PWM_X, MOTOR_CURRENT_PWM_Y, MOTOR_CURRENT_PWM_XY, MOTOR_CURRENT_PWM_I, MOTOR_CURRENT_PWM_J, MOTOR_CURRENT_PWM_K, MOTOR_CURRENT_PWM_U, MOTOR_CURRENT_PWM_V, MOTOR_CURRENT_PWM_W) + #define HAS_X_Y_XY_I_J_K_U_V_W 1 + #endif + + #if HAS_X_Y_XY_I_J_K_U_V_W || ANY_PIN(MOTOR_CURRENT_PWM_E, MOTOR_CURRENT_PWM_Z) + + if (!parser.seen("S" + #if HAS_X_Y_XY_I_J_K_U_V_W + "XY" SECONDARY_AXIS_GANG("I", "J", "K", "U", "V", "W") + #endif + #if PIN_EXISTS(MOTOR_CURRENT_PWM_Z) + "Z" + #endif + #if PIN_EXISTS(MOTOR_CURRENT_PWM_E) + "E" + #endif + )) return M907_report(); + + if (parser.seenval('S')) LOOP_L_N(a, MOTOR_CURRENT_COUNT) stepper.set_digipot_current(a, parser.value_int()); + + #if HAS_X_Y_XY_I_J_K_U_V_W + if (NUM_AXIS_GANG( + parser.seenval('X'), || parser.seenval('Y'), || false, + || parser.seenval('I'), || parser.seenval('J'), || parser.seenval('K'), + || parser.seenval('U'), || parser.seenval('V'), || parser.seenval('W') + )) stepper.set_digipot_current(0, parser.value_int()); #endif #if PIN_EXISTS(MOTOR_CURRENT_PWM_Z) - "Z" + if (parser.seenval('Z')) stepper.set_digipot_current(1, parser.value_int()); #endif #if PIN_EXISTS(MOTOR_CURRENT_PWM_E) - "E" + if (parser.seenval('E')) stepper.set_digipot_current(2, parser.value_int()); #endif - )) return M907_report(); - #if ANY_PIN(MOTOR_CURRENT_PWM_X, MOTOR_CURRENT_PWM_Y, MOTOR_CURRENT_PWM_XY, MOTOR_CURRENT_PWM_I, MOTOR_CURRENT_PWM_J, MOTOR_CURRENT_PWM_K, MOTOR_CURRENT_PWM_U, MOTOR_CURRENT_PWM_V, MOTOR_CURRENT_PWM_W) - if (NUM_AXIS_GANG( - parser.seenval('X'), || parser.seenval('Y'), || false, - || parser.seenval('I'), || parser.seenval('J'), || parser.seenval('K'), - || parser.seenval('U'), || parser.seenval('V'), || parser.seenval('W') - )) stepper.set_digipot_current(0, parser.value_int()); - #endif - #if PIN_EXISTS(MOTOR_CURRENT_PWM_Z) - if (parser.seenval('Z')) stepper.set_digipot_current(1, parser.value_int()); - #endif - #if PIN_EXISTS(MOTOR_CURRENT_PWM_E) - if (parser.seenval('E')) stepper.set_digipot_current(2, parser.value_int()); #endif #endif // HAS_MOTOR_CURRENT_PWM #if HAS_MOTOR_CURRENT_I2C // this one uses actual amps in floating point - LOOP_LOGICAL_AXES(i) if (parser.seenval(IAXIS_CHAR(i))) digipot_i2c.set_current(i, parser.value_float()); - // Additional extruders use B,C,D for channels 4,5,6. - // TODO: Change these parameters because 'E' is used. B? - #if HAS_EXTRUDERS - for (uint8_t i = E_AXIS + 1; i < DIGIPOT_I2C_NUM_CHANNELS; i++) + if (parser.seenval('S')) LOOP_L_N(q, DIGIPOT_I2C_NUM_CHANNELS) digipot_i2c.set_current(q, parser.value_float()); + LOOP_LOGICAL_AXES(i) if (parser.seenval(IAXIS_CHAR(i))) digipot_i2c.set_current(i, parser.value_float()); // X Y Z (I J K U V W) E (map to drivers according to pots adresses. Default with NUM_AXES 3 X Y Z E: map to X Y Z E0) + // Additional extruders use B,C,D. + // TODO: Change these parameters because 'E' is used and because 'D' should be reserved for debugging. B? + #if E_STEPPERS >= 2 + for (uint8_t i = E_AXIS + 1; i < _MAX(DIGIPOT_I2C_NUM_CHANNELS, (NUM_AXES + 3)); i++) if (parser.seenval('B' + i - (E_AXIS + 1))) digipot_i2c.set_current(i, parser.value_float()); #endif #endif @@ -97,9 +117,9 @@ void GcodeSuite::M907() { #if HAS_MOTOR_CURRENT_DAC if (parser.seenval('S')) { const float dac_percent = parser.value_float(); - LOOP_LE_N(i, 4) stepper_dac.set_current_percent(i, dac_percent); + LOOP_LOGICAL_AXES(i) stepper_dac.set_current_percent(i, dac_percent); } - LOOP_LOGICAL_AXES(i) if (parser.seenval(IAXIS_CHAR(i))) stepper_dac.set_current_percent(i, parser.value_float()); + LOOP_LOGICAL_AXES(i) if (parser.seenval(IAXIS_CHAR(i))) stepper_dac.set_current_percent(i, parser.value_float()); // X Y Z (I J K U V W) E (map to drivers according to DAC_STEPPER_ORDER. Default with NUM_AXES 3: X Y Z E map to X Y Z E0) #endif } @@ -119,8 +139,14 @@ void GcodeSuite::M907() { SERIAL_CHAR(' ', IAXIS_CHAR(q)); SERIAL_ECHO(stepper.motor_current_setting[q]); } - SERIAL_CHAR(' ', 'B'); // B (maps to E1 by default) - SERIAL_ECHOLN(stepper.motor_current_setting[4]); + #if E_STEPPERS >= 2 + SERIAL_ECHOPGM_P(PSTR(" B"), stepper.motor_current_setting[E_AXIS + 1] // B (maps to E1 with NUM_AXES 3 according to DIGIPOT_CHANNELS) + #if E_STEPPERS >= 3 + , PSTR(" C"), stepper.motor_current_setting[E_AXIS + 2] // C (mapping to E2 must be defined by DIGIPOT_CHANNELS) + #endif + ); + #endif + SERIAL_EOL(); #endif } diff --git a/Marlin/src/gcode/feature/i2c/M260_M261.cpp b/Marlin/src/gcode/feature/i2c/M260_M261.cpp index e978fb5048..cf9bb7e583 100644 --- a/Marlin/src/gcode/feature/i2c/M260_M261.cpp +++ b/Marlin/src/gcode/feature/i2c/M260_M261.cpp @@ -45,10 +45,10 @@ */ void GcodeSuite::M260() { // Set the target address - if (parser.seen('A')) i2c.address(parser.value_byte()); + if (parser.seenval('A')) i2c.address(parser.value_byte()); // Add a new byte to the buffer - if (parser.seen('B')) i2c.addbyte(parser.value_byte()); + if (parser.seenval('B')) i2c.addbyte(parser.value_byte()); // Flush the buffer to the bus if (parser.seen('S')) i2c.send(); @@ -63,7 +63,7 @@ void GcodeSuite::M260() { * Usage: M261 A B S