Compare commits

..

3 Commits

Author SHA1 Message Date
Scott Lahteine
30245b47ad Update .gitignore 2023-12-27 15:26:52 -06:00
Scott Lahteine
88e43c1ba3 🔖 Marlin 2.0.5.5 2023-07-20 14:10:45 -05:00
Scott Lahteine
49bab19bb5 🔨 PlatformIO 6 compatibility 2023-07-20 14:10:45 -05:00
2785 changed files with 87657 additions and 349347 deletions

View File

@@ -4,20 +4,16 @@ root = true
[{*.patch,syntax_test_*}] [{*.patch,syntax_test_*}]
trim_trailing_whitespace = false trim_trailing_whitespace = false
[{*.c,*.cpp,*.h,*.ino}] [{*.c,*.cpp,*.h}]
charset = utf-8 charset = utf-8
[{*.c,*.cpp,*.h,*.ino,Makefile}] [{*.c,*.cpp,*.h,Makefile}]
trim_trailing_whitespace = true trim_trailing_whitespace = true
insert_final_newline = true insert_final_newline = true
end_of_line = lf end_of_line = lf
indent_style = space indent_style = space
indent_size = 2 indent_size = 2
[{*.py}] [{*.py,*.conf,*.sublime-project}]
indent_style = space
indent_size = 4
[{*.conf,*.sublime-project}]
indent_style = tab indent_style = tab
indent_size = 4 indent_size = 4

2
.gitattributes vendored
View File

@@ -17,5 +17,3 @@
*.png binary *.png binary
*.jpg binary *.jpg binary
*.fon binary *.fon binary
*.bin binary
*.woff binary

2
.github/FUNDING.yml vendored
View File

@@ -1,3 +1,3 @@
github: [thinkyhead] github: [thinkyhead]
patreon: thinkyhead patreon: thinkyhead
custom: ["https://www.thinkyhead.com/donate-to-marlin"] custom: ["http://www.thinkyhead.com/donate-to-marlin"]

43
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,43 @@
---
name: Bug report
about: Report a bug in Marlin
title: "[BUG] (short description)"
labels: ''
assignees: ''
---
<!--
Have you read Marlin's Code of Conduct? By filing an Issue, you are expected to comply with it, including treating everyone with respect: https://github.com/MarlinFirmware/Marlin/blob/master/.github/code_of_conduct.md
Do you want to ask a question? Are you looking for support? Please don't post here. Instead please use one of the support links at https://github.com/MarlinFirmware/Marlin/issues/new/choose
Before filing an issue be sure to test the "bugfix" branches to see whether the issue has been resolved.
-->
### Bug Description
<!-- Description of the bug -->
### My Configurations
**Required:** Please include a ZIP file containing your `Configuration.h` and `Configuration_adv.h` files.
### Steps to Reproduce
<!-- Please describe the steps needed to reproduce the issue -->
1. [First Step]
2. [Second Step]
3. [and so on...]
**Expected behavior:** [What you expect to happen]
**Actual behavior:** [What actually happens]
#### Additional Information
* Provide pictures or links to videos that clearly demonstrate the issue.
* See [How Can I Contribute](#how-can-i-contribute) for additional guidelines.

17
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1,17 @@
blank_issues_enabled: false
contact_links:
- name: Marlin Documentation
url: http://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: http://forums.reprap.org/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!

View File

@@ -0,0 +1,35 @@
---
name: Feature request
about: Request a Feature
title: "[FR] (feature request title)"
labels: ''
assignees: ''
---
<!--
Have you read Marlin's Code of Conduct? By filing an Issue, you are expected to comply with it, including treating everyone with respect: https://github.com/MarlinFirmware/Marlin/blob/master/.github/code_of_conduct.md
Do you want to ask a question? Are you looking for support? Please don't post here. Instead please use one of the support links at https://github.com/MarlinFirmware/Marlin/issues/new/choose
Before filing an issue be sure to test the "bugfix" branches to see whether the issue has been resolved.
-->
### Description
<!-- Description of the requested feature -->
### Feature Workflow
<!-- Please describe the feature's behavior, user interaction, etc. -->
1. [First Action]
2. [Second Action]
3. [and so on...]
#### Additional Information
* Provide pictures or links that demonstrate a similar feature or concept.
* See [How Can I Contribute](#how-can-i-contribute) for additional guidelines.

View File

@@ -34,18 +34,16 @@ This project and everyone participating in it is governed by the [Marlin Code of
We have a Message Board and a Facebook group where our knowledgable user community can provide helpful advice if you have questions. We have a Message Board and a Facebook group where our knowledgable user community can provide helpful advice if you have questions.
- [Marlin Documentation](https://marlinfw.org) - Official Marlin documentation * [Marlin RepRap forum](http://forums.reprap.org/list.php?415)
- Facebook Group ["Marlin Firmware"](https://www.facebook.com/groups/1049718498464482/) * [MarlinFirmware on Facebook](https://www.facebook.com/groups/1049718498464482/)
- RepRap.org [Marlin Forum](https://forums.reprap.org/list.php?415)
- Facebook Group ["Marlin Firmware for 3D Printers"](https://www.facebook.com/groups/3Dtechtalk/)
- [Marlin Configuration](https://www.youtube.com/results?search_query=marlin+configuration) on YouTube
If chat is more your speed, you can join the MarlinFirmware Discord server: If chat is more your speed, you can join the MarlinFirmware Slack team:
* Use the link https://discord.gg/n5NJ59y to join up as a General User. * Join the Marlin Slack Team
* Even though our Discord is pretty active, it may take a while for community members to respond &mdash; please be patient! * To obtain group access, please [send a request](http://www.thinkyhead.com/contact/9) to @thinkyhead.
* Use the `#general` channel for general questions or discussion about Marlin. * Even though Slack is a chat service, sometimes it takes several hours for community members to respond &mdash; please be patient!
* Other channels exist for certain topics or are limited to Patrons. Check the channel list. * Use the `#general` channel for general questions or discussion about Marlin.
* Other channels exist for certain topics. Check the channel list.
## How Can I Contribute? ## How Can I Contribute?
@@ -53,13 +51,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. 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/bug_report.yml), the information it asks for helps us resolve issues faster. Before creating a Bug Report, please test the "nightly" development branch, as you might find out that you don't need to create one. When you are creating a Bug Report, please [include as many details as possible](#how-do-i-submit-a-good-bug-report). Fill out [the required template](issue_template.md), 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. > **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? #### 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/bug_report.yml). 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).
Explain the problem and include additional details to help maintainers reproduce the problem: Explain the problem and include additional details to help maintainers reproduce the problem:
@@ -91,12 +89,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. 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](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 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 Submitting a Feature Request #### Before Submitting a Feature Request
* **Check the [Marlin website](https://marlinfw.org/)** for tips — you might discover that the feature is already included. Most importantly, check if you're using [the latest version of Marlin](https://github.com/MarlinFirmware/Marlin/releases) and if you can get the desired behavior by changing [Marlin's config settings](https://marlinfw.org/docs/configuration/configuration.html). * **Check the [Marlin website](http://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](http://marlinfw.org/docs/configuration/configuration.html).
* **Perform a [cursory search](https://github.com/MarlinFirmware/Marlin/issues?q=is%3Aopen+is%3Aissue+label%3A%22T%3A+Feature+Request%22)** to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one. * **Perform a [cursory search](https://github.com/MarlinFirmware/Marlin/issues?q=is%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.
#### How Do I Submit A (Good) Feature Request? #### How Do I Submit A (Good) Feature Request?
@@ -119,12 +117,12 @@ Unsure where to begin contributing to Marlin? You can start by looking through t
### Pull Requests ### Pull Requests
Pull Requests should always be targeted to working branches (e.g., `bugfix-2.0.x` and/or `bugfix-1.1.x`) and never to release branches (e.g., `2.0.x` and/or `1.1.x`). If this is your first Pull Request, please read our [Guide to Pull Requests](https://marlinfw.org/docs/development/getting_started_pull_requests.html) and Github's [Pull Request](https://help.github.com/articles/creating-a-pull-request/) documentation. Pull Requests should always be targeted to working branches (e.g., `bugfix-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](http://marlinfw.org/docs/development/getting_started_pull_requests.html) and Github's [Pull Request](https://help.github.com/articles/creating-a-pull-request/) documentation.
* Fill in [the required template](pull_request_template.md). * Fill in [the required template](pull_request_template.md).
* Don't include issue numbers in the PR title. * Don't include issue numbers in the PR title.
* Include pictures, diagrams, and links to videos in your Pull Request to demonstrate your changes, if needed. * Include pictures, diagrams, and links to videos in your Pull Request to demonstrate your changes, if needed.
* Follow the [Coding Standards](https://marlinfw.org/docs/development/coding_standards.html) posted on our website. * Follow the [Coding Standards](http://marlinfw.org/docs/development/coding_standards.html) posted on our website.
* Document new code with clear and concise comments. * Document new code with clear and concise comments.
* End all files with a newline. * End all files with a newline.
@@ -139,7 +137,7 @@ Pull Requests should always be targeted to working branches (e.g., `bugfix-2.0.x
### C++ Coding Standards ### C++ Coding Standards
* Please read and follow the [Coding Standards](https://marlinfw.org/docs/development/coding_standards.html) posted on our website. Failure to follow these guidelines will delay evaluation and acceptance of Pull Requests. * Please read and follow the [Coding Standards](http://marlinfw.org/docs/development/coding_standards.html) posted on our website. Failure to follow these guidelines will delay evaluation and acceptance of Pull Requests.
### Documentation ### Documentation

16
.github/issue_template.md vendored Normal file
View File

@@ -0,0 +1,16 @@
# NO SUPPORT REQUESTS PLEASE
Support Requests posted here will be automatically closed!
This Issue Queue is for Marlin bug reports and development-related issues, and we prefer not to handle user-support questions here. See https://github.com/MarlinFirmware/Marlin/blob/1.1.x/.github/contributing.md#i-dont-want-to-read-this-whole-thing-i-just-have-a-question.
For best results getting help with configuration and troubleshooting, please use the following resources:
- RepRap.org Marlin Forum http://forums.reprap.org/list.php?415
- Tom's 3D Forums https://discuss.toms3d.org/
- Facebook Group "Marlin Firmware" https://www.facebook.com/groups/1049718498464482/
- Facebook Group "Marlin Firmware for 3D Printers" https://www.facebook.com/groups/3Dtechtalk/
- Marlin Configuration https://www.youtube.com/results?search_query=marlin+configuration on YouTube
- Marlin Discord server. Join link: https://discord.gg/n5NJ59y
After seeking help from the community, if the consensus points to to a bug in Marlin, then you should post a Bug Report at https://github.com/MarlinFirmware/Marlin/issues/new/choose).

View File

@@ -1,33 +1,19 @@
<!-- ### Requirements
Submitting a Pull Request * Filling out this template is required. Pull Requests without a clear description may be closed at the maintainers' discretion.
- Please fill out all sections of this form. You can delete the helpful comments.
- Pull Requests without clear information will take longer and may even be rejected.
- We get a high volume of submissions so please be patient during review.
-->
### Description ### Description
<!-- <!--
Clearly describe the submitted changes with lots of details. Include images where helpful. Initial reviewers may not be familiar with the subject, so be as thorough as possible. You can use MarkDown syntax to improve readability with bullet lists, code blocks, and so on. PREVIEW and fix up formatting before submitting. We must be able to understand your proposed change from this description. If we can't understand what the code will do from this description, the Pull Request may be closed at the maintainers' discretion. Keep in mind that the maintainer reviewing this PR may not be familiar with or have worked with the code recently, so please walk us through the concepts.
--> -->
### Requirements
<!-- Does this PR require a specific board, LCD, etc.? -->
### Benefits ### Benefits
<!-- What does this PR fix or improve? --> <!-- What does this fix or improve? -->
### Configurations
<!-- Attach Configurations ZIP and any other files needed to test this PR. -->
### Related Issues ### Related Issues
<!-- Does this PR fix a bug or fulfill a Feature Request? Link related Issues here. --> <!-- Whether this fixes a bug or fulfills a feature request, please list any related Issues here. -->

35
.github/workflows/bump-date.yml vendored Normal file
View File

@@ -0,0 +1,35 @@
#
# bump-date.yml
# Bump the distribution date once per day
#
name: Bump Distribution Date
on:
schedule:
- cron: '0 0 * * *'
jobs:
bump_date:
name: Bump Distribution Date
if: github.repository == 'MarlinFirmware/Marlin'
runs-on: ubuntu-latest
steps:
- name: Check out bugfix-2.0.x
uses: actions/checkout@v2
with:
ref: bugfix-2.0.x
- name: Bump Distribution Date
run: |
# Inline Bump Script
DIST=$( date +"%Y-%m-%d" )
eval "sed -E -i 's/(#define +STRING_DISTRIBUTION_DATE) .*$/\1 \"$DIST\"/g' Marlin/src/inc/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

33
.github/workflows/check-pr.yml vendored Normal file
View File

@@ -0,0 +1,33 @@
#
# check-pr.yml
# Close PRs directed at release branches
#
name: PR Bad Target
on:
pull_request:
branches:
- 1.0.x
- 1.1.x
- 2.0.x
jobs:
bad_target:
name: PR Bad Target
if: github.repository == 'MarlinFirmware/Marlin'
runs-on: ubuntu-latest
steps:
- uses: peter-evans/close-pull@v1
with:
delete-branch: false
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.0.x` branch and be careful to target `bugfix-2.0.x` when resubmitting the PR.
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.

27
.github/workflows/close-stale.yml vendored Normal file
View File

@@ -0,0 +1,27 @@
#
# 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 is stale because it has been open 30 days with no activity. Remove stale label / comment or this will be closed in 5 days.'
days-before-stale: 30
days-before-close: 5
stale-issue-label: 'stale-closing-soon'
exempt-issue-labels: 'T: Feature Request'

32
.github/workflows/lock-closed.yml vendored Normal file
View File

@@ -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: ''

113
.github/workflows/test-builds.yml vendored Normal file
View File

@@ -0,0 +1,113 @@
#
# test-builds.yml
# Do test builds to catch compile errors
#
name: CI
on:
pull_request:
branches:
- bugfix-2.0.x
paths-ignore:
- config/**
- data/**
- docs/**
- '**/*.md'
push:
branches:
- bugfix-2.0.x
paths-ignore:
- config/**
- data/**
- docs/**
- '**/*.md'
jobs:
test_builds:
name: Run All Tests
if: github.repository == 'MarlinFirmware/Marlin'
runs-on: ubuntu-latest
strategy:
matrix:
test-platform:
# Base Environments
- DUE
- esp32
- linux_native
- mega2560
- teensy31
- teensy35
- SAMD51_grandcentral_m4
# Extended AVR Environments
- FYSETC_F6_13
- mega1280
- rambo
- sanguino1284p
- sanguino644p
# Extended STM32 Environments
- STM32F103RC_btt
- STM32F103RC_btt_USB
- STM32F103RE_btt
- STM32F103RE_btt_USB
- STM32F103RC_fysetc
- jgaurora_a5s_a1
- STM32F103VE_longer
- STM32F407VE_black
- BIGTREE_SKR_PRO
- BIGTREE_GTR_V1_0
- mks_robin
- ARMED
- FYSETC_S6
# Put lengthy tests last
- LPC1768
- LPC1769
# STM32 with non-STM framework. both broken for now. they should use HAL_STM32 which is working.
#- STM32F4
#- STM32F7
# Non-working environment tests
#- BIGTREE_BTT002
#- at90usb1286_cdc
#- at90usb1286_dfu
#- STM32F103CB_malyan
#- mks_robin_lite
#- mks_robin_mini
#- mks_robin_nano
steps:
- name: Select Python 3.7
uses: actions/setup-python@v1
with:
python-version: '3.7' # Version range or exact version of a Python version to use, using semvers version range syntax.
architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
- name: Install PlatformIO
run: |
pip install -U https://github.com/platformio/platformio-core/archive/master.zip
platformio update
- name: Check out the PR
uses: actions/checkout@v2
- name: Run ${{ matrix.test-platform }} Tests
run: |
# Inline tests script
[[ "$GITHUB_REPOSITORY" == "MarlinFirmware/Marlin" ]] || exit 0
chmod +x buildroot/bin/*
chmod +x buildroot/share/tests/*
export PATH=./buildroot/bin/:./buildroot/share/tests/:${PATH}
run_tests . ${{ matrix.test-platform }}

22
.github/workflows/unlock-reopened.yml vendored Normal file
View File

@@ -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 }}"

53
.gitignore vendored
View File

@@ -1,6 +1,6 @@
# #
# Marlin 3D Printer Firmware # Marlin 3D Printer Firmware
# Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] # Copyright (c) 2023 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
# #
# Based on Sprinter and grbl. # Based on Sprinter and grbl.
# Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm # Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
@@ -21,35 +21,21 @@
# Generated files # Generated files
_Version.h _Version.h
bdf2u8g bdf2u8g.exe
genpages.exe
marlin_config.json marlin_config.json
mczip.h mczip.h
language*.csv
out-csv/
out-language/
*.gen *.gen
*.sublime-workspace *.sublime-workspace
#
# OS # OS
#
applet/ applet/
.DS_Store .DS_Store
# # Compiled C++ Object files
# Misc
#
*~
*.orig
*.rej
*.bak
*.idea
*.i
*.ii
*.swp
tags
#
# C++
#
# Compiled Object files
*.slo *.slo
*.lo *.lo
*.o *.o
@@ -80,10 +66,7 @@ tags
*.out *.out
*.app *.app
# # Compiled C Object files
# C
#
# Object files
*.o *.o
*.ko *.ko
*.obj *.obj
@@ -143,13 +126,16 @@ vc-fileutils.settings
.vscode/* .vscode/*
!.vscode/extensions.json !.vscode/extensions.json
#Simulation # Simulation files
imgui.ini imgui.ini
eeprom.dat eeprom.dat
spi_flash.bin spi_flash.bin
fs.img
#cmake # CMake
buildroot/share/cmake/*
CMakeLists.txt CMakeLists.txt
!buildroot/share/cmake/CMakeLists.txt
src/CMakeLists.txt src/CMakeLists.txt
CMakeListsPrivate.txt CMakeListsPrivate.txt
build/ build/
@@ -169,3 +155,16 @@ __pycache__
# IOLogger logs # IOLogger logs
*_log.csv *_log.csv
# Misc.
*~
*.orig
*.rej
*.bak
*.idea
*.i
*.ii
*.swp
tags
*.logs
*.bak

View File

@@ -1,11 +0,0 @@
{
// See http://go.microsoft.com/fwlink/?LinkId=827846
// for the documentation about the extensions.json format
"recommendations": [
"marlinfirmware.auto-build",
"platformio.platformio-ide"
],
"unwantedRecommendations": [
"ms-vscode.cpptools-extension-pack"
]
}

View File

@@ -3,7 +3,7 @@
GNU GENERAL PUBLIC LICENSE GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007 Version 3, 29 June 2007
Copyright (c) 2007 Free Software Foundation, Inc. <https://www.fsf.org/> Copyright (c) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed. of this license document, but changing it is not allowed.
@@ -647,7 +647,7 @@ the "copyright" line and a pointer to where the full notice is found.
GNU General Public License for more details. GNU General Public License for more details.
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail. Also add information on how to contact you by electronic and paper mail.
@@ -666,11 +666,12 @@ might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school, You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary. if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>. <http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>. <http://www.gnu.org/philosophy/why-not-lgpl.html>.

View File

@@ -1,52 +0,0 @@
help:
@echo "Tasks for local development:"
@echo "* tests-single-ci: Run a single test from inside the CI"
@echo "* tests-single-local: Run a single test locally"
@echo "* tests-single-local-docker: Run a single test locally, using docker-compose"
@echo "* tests-all-local: Run all tests locally"
@echo "* tests-all-local-docker: Run all tests locally, using docker-compose"
@echo "* setup-local-docker: Setup local docker-compose"
@echo ""
@echo "Options for testing:"
@echo " TEST_TARGET Set when running tests-single-*, to select the"
@echo " test. If you set it to ALL it will run all "
@echo " tests, but some of them are broken: use "
@echo " tests-all-* instead to run only the ones that "
@echo " run on GitHub CI"
@echo " ONLY_TEST Limit tests to only those that contain this, or"
@echo " the index of the test (1-based)"
@echo " VERBOSE_PLATFORMIO If you want the full PIO output, set any value"
@echo " GIT_RESET_HARD Used by CI: reset all local changes. WARNING:"
@echo " THIS WILL UNDO ANY CHANGES YOU'VE MADE!"
.PHONY: help
tests-single-ci:
export GIT_RESET_HARD=true
$(MAKE) tests-single-local TEST_TARGET=$(TEST_TARGET)
.PHONY: tests-single-ci
tests-single-local:
@if ! test -n "$(TEST_TARGET)" ; then echo "***ERROR*** Set TEST_TARGET=<your-module> or use make tests-all-local" ; return 1; fi
export PATH=./buildroot/bin/:./buildroot/tests/:${PATH} \
&& export VERBOSE_PLATFORMIO=$(VERBOSE_PLATFORMIO) \
&& run_tests . $(TEST_TARGET) "$(ONLY_TEST)"
.PHONY: tests-single-local
tests-single-local-docker:
@if ! test -n "$(TEST_TARGET)" ; then echo "***ERROR*** Set TEST_TARGET=<your-module> or use make tests-all-local-docker" ; return 1; fi
docker-compose run --rm marlin $(MAKE) tests-single-local TEST_TARGET=$(TEST_TARGET) VERBOSE_PLATFORMIO=$(VERBOSE_PLATFORMIO) GIT_RESET_HARD=$(GIT_RESET_HARD) ONLY_TEST="$(ONLY_TEST)"
.PHONY: tests-single-local-docker
tests-all-local:
export PATH=./buildroot/bin/:./buildroot/tests/:${PATH} \
&& export VERBOSE_PLATFORMIO=$(VERBOSE_PLATFORMIO) \
&& for TEST_TARGET in $$(./get_test_targets.py) ; do echo "Running tests for $$TEST_TARGET" ; run_tests . $$TEST_TARGET ; done
.PHONY: tests-all-local
tests-all-local-docker:
docker-compose run --rm marlin $(MAKE) tests-all-local VERBOSE_PLATFORMIO=$(VERBOSE_PLATFORMIO) GIT_RESET_HARD=$(GIT_RESET_HARD)
.PHONY: tests-all-local-docker
setup-local-docker:
docker-compose build
.PHONY: setup-local-docker

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -14,7 +14,7 @@
# Detailed instructions for using the makefile: # Detailed instructions for using the makefile:
# #
# 1. Modify the line containing "ARDUINO_INSTALL_DIR" to point to the directory that # 1. Modify the line containing "ARDUINO_INSTALL_DIR" to point to the directory that
# contains the Arduino installation (for example, under macOS, this # contains the Arduino installation (for example, under Mac OS X, this
# might be /Applications/Arduino.app/Contents/Resources/Java). # might be /Applications/Arduino.app/Contents/Resources/Java).
# #
# 2. Modify the line containing "UPLOAD_PORT" to refer to the filename # 2. Modify the line containing "UPLOAD_PORT" to refer to the filename
@@ -22,10 +22,8 @@
# (e.g. UPLOAD_PORT = /dev/tty.USB0). If the exact name of this file # (e.g. UPLOAD_PORT = /dev/tty.USB0). If the exact name of this file
# changes, you can use * as a wild card (e.g. UPLOAD_PORT = /dev/tty.usb*). # changes, you can use * as a wild card (e.g. UPLOAD_PORT = /dev/tty.usb*).
# #
# 3. Set the line containing "MCU" to match your board's processor. Set # 3. Set the line containing "MCU" to match your board's processor.
# "PROG_MCU" as the AVR part name corresponding to "MCU". You can use the # Older one's are atmega8 based, newer ones like Arduino Mini, Bluetooth
# following command to get a list of correspondences: `avrdude -c alf -p x`
# Older boards are atmega8 based, newer ones like Arduino Mini, Bluetooth
# or Diecimila have the atmega168. If you're using a LilyPad Arduino, # or Diecimila have the atmega168. If you're using a LilyPad Arduino,
# change F_CPU to 8000000. If you are using Gen7 electronics, you # change F_CPU to 8000000. If you are using Gen7 electronics, you
# probably need to use 20000000. Either way, you must regenerate # probably need to use 20000000. Either way, you must regenerate
@@ -36,18 +34,18 @@
# 5. Type "make upload", reset your Arduino board, and press enter to # 5. Type "make upload", reset your Arduino board, and press enter to
# upload your program to the Arduino board. # upload your program to the Arduino board.
# #
# Note that all settings at the top of this file can be overridden from # Note that all settings at the top of this file can be overriden from
# the command line with, for example, "make HARDWARE_MOTHERBOARD=71" # the command line with, for example, "make HARDWARE_MOTHERBOARD=71"
# #
# To compile for RAMPS (atmega2560) with Arduino 1.6.9 at root/arduino you would use... # To compile for RAMPS (atmega2560) with Arduino 1.6.9 at root/arduino you would use...
# #
# make ARDUINO_VERSION=10609 AVR_TOOLS_PATH=/root/arduino/hardware/tools/avr/bin/ \ # make ARDUINO_VERSION=10609 AVR_TOOLS_PATH=/root/arduino/hardware/tools/avr/bin/ \
# HARDWARE_MOTHERBOARD=1200 ARDUINO_INSTALL_DIR=/root/arduino # HARDWARE_MOTHERBOARD=33 ARDUINO_INSTALL_DIR=/root/arduino
# #
# To compile and upload simply add "upload" to the end of the line... # To compile and upload simply add "upload" to the end of the line...
# #
# make ARDUINO_VERSION=10609 AVR_TOOLS_PATH=/root/arduino/hardware/tools/avr/bin/ \ # make ARDUINO_VERSION=10609 AVR_TOOLS_PATH=/root/arduino/hardware/tools/avr/bin/ \
# HARDWARE_MOTHERBOARD=1200 ARDUINO_INSTALL_DIR=/root/arduino upload # HARDWARE_MOTHERBOARD=33 ARDUINO_INSTALL_DIR=/root/arduino upload
# #
# If uploading doesn't work try adding the parameter "AVRDUDE_PROGRAMMER=wiring" or # If uploading doesn't work try adding the parameter "AVRDUDE_PROGRAMMER=wiring" or
# start upload manually (using stk500) like so: # start upload manually (using stk500) like so:
@@ -59,26 +57,7 @@
# #
# This defines the board to compile for (see boards.h for your board's ID) # This defines the board to compile for (see boards.h for your board's ID)
HARDWARE_MOTHERBOARD ?= 1020 HARDWARE_MOTHERBOARD ?= 11
ifeq ($(OS),Windows_NT)
# Windows
ARDUINO_INSTALL_DIR ?= ${HOME}/Arduino
ARDUINO_USER_DIR ?= ${HOME}/Arduino
else
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Linux)
# Linux
ARDUINO_INSTALL_DIR ?= /usr/share/arduino
ARDUINO_USER_DIR ?= ${HOME}/Arduino
endif
ifeq ($(UNAME_S),Darwin)
# Darwin (macOS)
ARDUINO_INSTALL_DIR ?= /Applications/Arduino.app/Contents/Java
ARDUINO_USER_DIR ?= ${HOME}/Documents/Arduino
AVR_TOOLS_PATH ?= /Applications/Arduino.app/Contents/Java/hardware/tools/avr/bin/
endif
endif
# Arduino source install directory, and version number # Arduino source install directory, and version number
# On most linuxes this will be /usr/share/arduino # On most linuxes this will be /usr/share/arduino
@@ -88,51 +67,45 @@ ARDUINO_VERSION ?= 106
# The installed Libraries are in the User folder # The installed Libraries are in the User folder
ARDUINO_USER_DIR ?= ${HOME}/Arduino ARDUINO_USER_DIR ?= ${HOME}/Arduino
# You can optionally set a path to the avr-gcc tools. # You can optionally set a path to the avr-gcc tools. Requires a trailing slash. (ex: /usr/local/avr-gcc/bin)
# Requires a trailing slash. For example, /usr/local/avr-gcc/bin/
AVR_TOOLS_PATH ?= AVR_TOOLS_PATH ?=
# Programmer configuration #Programmer configuration
UPLOAD_RATE ?= 57600 UPLOAD_RATE ?= 57600
AVRDUDE_PROGRAMMER ?= arduino AVRDUDE_PROGRAMMER ?= arduino
# On most linuxes this will be /dev/ttyACM0 or /dev/ttyACM1 # on most linuxes this will be /dev/ttyACM0 or /dev/ttyACM1
UPLOAD_PORT ?= /dev/ttyUSB0 UPLOAD_PORT ?= /dev/ttyUSB0
# Directory used to build files in, contains all the build files, from object #Directory used to build files in, contains all the build files, from object files to the final hex file
# files to the final hex file on linux it is best to put an absolute path #on linux it is best to put an absolute path like /home/username/tmp .
# like /home/username/tmp .
BUILD_DIR ?= applet BUILD_DIR ?= applet
# This defines whether Liquid_TWI2 support will be built # This defines whether Liquid_TWI2 support will be built
LIQUID_TWI2 ?= 0 LIQUID_TWI2 ?= 0
# This defines if Wire is needed # this defines if Wire is needed
WIRE ?= 0 WIRE ?= 0
# This defines if Tone is needed (i.e., SPEAKER is defined in Configuration.h) # this defines if U8GLIB is needed (may require RELOC_WORKAROUND)
# Disabling this (and SPEAKER) saves approximately 350 bytes of memory. U8GLIB ?= 1
TONE ?= 1
# This defines if U8GLIB is needed (may require RELOC_WORKAROUND) # this defines whether to include the Trinamic TMCStepper library
U8GLIB ?= 0 TMC ?= 1
# This defines whether to include the Trinamic TMCStepper library # this defines whether to include the AdaFruit NeoPixel library
TMC ?= 0
# This defines whether to include the AdaFruit NeoPixel library
NEOPIXEL ?= 0 NEOPIXEL ?= 0
############ ############
# Try to automatically determine whether RELOC_WORKAROUND is needed based # Try to automatically determine whether RELOC_WORKAROUND is needed based
# on GCC versions: # on GCC versions:
# https://www.avrfreaks.net/comment/1789106#comment-1789106 # http://www.avrfreaks.net/comment/1789106#comment-1789106
CC_MAJ:=$(shell $(CC) -dM -E - < /dev/null | grep __GNUC__ | cut -f3 -d\ ) CC_MAJ:=$(shell $(CC) -dM -E - < /dev/null | grep __GNUC__ | cut -f3 -d\ )
CC_MIN:=$(shell $(CC) -dM -E - < /dev/null | grep __GNUC_MINOR__ | cut -f3 -d\ ) CC_MIN:=$(shell $(CC) -dM -E - < /dev/null | grep __GNUC_MINOR__ | cut -f3 -d\ )
CC_PATCHLEVEL:=$(shell $(CC) -dM -E - < /dev/null | grep __GNUC_PATCHLEVEL__ | cut -f3 -d\ ) CC_PATCHLEVEL:=$(shell $(CC) -dM -E - < /dev/null | grep __GNUC_PATCHLEVEL__ | cut -f3 -d\ )
CC_VER:=$(shell echo $$(( $(CC_MAJ) * 10000 + $(CC_MIN) * 100 + $(CC_PATCHLEVEL) ))) CC_VER:=$(shell echo $$(( $(CC_MAJ) * 10000 + $(CC_MIN) * 100 + $(CC_PATCHLEVEL) )))
ifeq ($(shell test $(CC_VER) -lt 40901 && echo 1),1) ifeq ($(shell test $(CC_VER) -lt 40901 && echo 1),1)
$(warning This GCC version $(CC_VER) is likely broken. Enabling relocation workaround.) @echo This version of GCC is likely broken. Enabling relocation workaround.
RELOC_WORKAROUND = 1 RELOC_WORKAROUND = 1
endif endif
@@ -197,130 +170,105 @@ else ifeq ($(HARDWARE_MOTHERBOARD),1100)
else ifeq ($(HARDWARE_MOTHERBOARD),1101) else ifeq ($(HARDWARE_MOTHERBOARD),1101)
# Velleman K8400 Controller (derived from 3Drag Controller) # Velleman K8400 Controller (derived from 3Drag Controller)
else ifeq ($(HARDWARE_MOTHERBOARD),1102) 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 # 2PrintBeta BAM&DICE with STK drivers
else ifeq ($(HARDWARE_MOTHERBOARD),1105) else ifeq ($(HARDWARE_MOTHERBOARD),1103)
# 2PrintBeta BAM&DICE Due with STK drivers # 2PrintBeta BAM&DICE Due with STK drivers
else ifeq ($(HARDWARE_MOTHERBOARD),1106) else ifeq ($(HARDWARE_MOTHERBOARD),1104)
# MKS BASE v1.0 # MKS BASE v1.0
else ifeq ($(HARDWARE_MOTHERBOARD),1105)
# MKS v1.4 with A4982 stepper drivers
else ifeq ($(HARDWARE_MOTHERBOARD),1106)
# MKS v1.5 with Allegro A4982 stepper drivers
else ifeq ($(HARDWARE_MOTHERBOARD),1107) else ifeq ($(HARDWARE_MOTHERBOARD),1107)
# MKS BASE v1.4 with Allegro A4982 stepper drivers # MKS v1.6 with Allegro A4982 stepper drivers
else ifeq ($(HARDWARE_MOTHERBOARD),1108) else ifeq ($(HARDWARE_MOTHERBOARD),1108)
# MKS BASE v1.5 with Allegro A4982 stepper drivers
else ifeq ($(HARDWARE_MOTHERBOARD),1109)
# MKS BASE v1.6 with Allegro A4982 stepper drivers
else ifeq ($(HARDWARE_MOTHERBOARD),1110)
# MKS BASE 1.0 with Heroic HR4982 stepper drivers # MKS BASE 1.0 with Heroic HR4982 stepper drivers
else ifeq ($(HARDWARE_MOTHERBOARD),1111) else ifeq ($(HARDWARE_MOTHERBOARD),1109)
# MKS GEN v1.3 or 1.4 # MKS GEN v1.3 or 1.4
else ifeq ($(HARDWARE_MOTHERBOARD),1112) else ifeq ($(HARDWARE_MOTHERBOARD),1110)
# MKS GEN L # MKS GEN L
else ifeq ($(HARDWARE_MOTHERBOARD),1113) else ifeq ($(HARDWARE_MOTHERBOARD),1111)
# zrib V2.0 control board (Chinese knock off RAMPS replica)
else ifeq ($(HARDWARE_MOTHERBOARD),1112)
# BigTreeTech or BIQU KFB2.0 # BigTreeTech or BIQU KFB2.0
else ifeq ($(HARDWARE_MOTHERBOARD),1114) else ifeq ($(HARDWARE_MOTHERBOARD),1113)
# zrib V2.0 (Chinese RAMPS replica)
else ifeq ($(HARDWARE_MOTHERBOARD),1115)
# zrib V5.2 (Chinese RAMPS replica)
else ifeq ($(HARDWARE_MOTHERBOARD),1116)
# Felix 2.0+ Electronics Board (RAMPS like) # Felix 2.0+ Electronics Board (RAMPS like)
else ifeq ($(HARDWARE_MOTHERBOARD),1117) else ifeq ($(HARDWARE_MOTHERBOARD),1114)
# Invent-A-Part RigidBoard # Invent-A-Part RigidBoard
else ifeq ($(HARDWARE_MOTHERBOARD),1118) else ifeq ($(HARDWARE_MOTHERBOARD),1115)
# Invent-A-Part RigidBoard V2 # Invent-A-Part RigidBoard V2
else ifeq ($(HARDWARE_MOTHERBOARD),1119) else ifeq ($(HARDWARE_MOTHERBOARD),1116)
# Sainsmart 2-in-1 board # Sainsmart 2-in-1 board
else ifeq ($(HARDWARE_MOTHERBOARD),1120) else ifeq ($(HARDWARE_MOTHERBOARD),1117)
# Ultimaker # Ultimaker
else ifeq ($(HARDWARE_MOTHERBOARD),1121) else ifeq ($(HARDWARE_MOTHERBOARD),1118)
# Ultimaker (Older electronics. Pre 1.5.4. This is rare) # Ultimaker (Older electronics. Pre 1.5.4. This is rare)
else ifeq ($(HARDWARE_MOTHERBOARD),1122) else ifeq ($(HARDWARE_MOTHERBOARD),1119)
MCU ?= atmega1280 MCU ?= atmega1280
PROG_MCU ?= m1280
# Azteeg X3 # Azteeg X3
else ifeq ($(HARDWARE_MOTHERBOARD),1123) else ifeq ($(HARDWARE_MOTHERBOARD),1120)
# Azteeg X3 Pro # Azteeg X3 Pro
else ifeq ($(HARDWARE_MOTHERBOARD),1124) else ifeq ($(HARDWARE_MOTHERBOARD),1121)
# Ultimainboard 2.x (Uses TEMP_SENSOR 20) # Ultimainboard 2.x (Uses TEMP_SENSOR 20)
else ifeq ($(HARDWARE_MOTHERBOARD),1125) else ifeq ($(HARDWARE_MOTHERBOARD),1122)
# Rumba # Rumba
else ifeq ($(HARDWARE_MOTHERBOARD),1126) else ifeq ($(HARDWARE_MOTHERBOARD),1123)
# Raise3D N series Rumba derivative # Raise3D Rumba
else ifeq ($(HARDWARE_MOTHERBOARD),1127) else ifeq ($(HARDWARE_MOTHERBOARD),1124)
# Rapide Lite 200 (v1, low-cost RUMBA clone with drv) # Rapide Lite RL200 Rumba
else ifeq ($(HARDWARE_MOTHERBOARD),1128) else ifeq ($(HARDWARE_MOTHERBOARD),1125)
# Formbot T-Rex 2 Plus # Formbot T-Rex 2 Plus
else ifeq ($(HARDWARE_MOTHERBOARD),1129) else ifeq ($(HARDWARE_MOTHERBOARD),1126)
# Formbot T-Rex 3 # Formbot T-Rex 3
else ifeq ($(HARDWARE_MOTHERBOARD),1130) else ifeq ($(HARDWARE_MOTHERBOARD),1127)
# Formbot Raptor # Formbot Raptor
else ifeq ($(HARDWARE_MOTHERBOARD),1131) else ifeq ($(HARDWARE_MOTHERBOARD),1128)
# Formbot Raptor 2 # Formbot Raptor 2
else ifeq ($(HARDWARE_MOTHERBOARD),1132) else ifeq ($(HARDWARE_MOTHERBOARD),1129)
# bq ZUM Mega 3D # bq ZUM Mega 3D
else ifeq ($(HARDWARE_MOTHERBOARD),1130)
# MakeBoard Mini v2.1.2 is a control board sold by MicroMake
else ifeq ($(HARDWARE_MOTHERBOARD),1131)
# TriGorilla Anycubic version 1.3 based on RAMPS EFB
else ifeq ($(HARDWARE_MOTHERBOARD),1132)
# TriGorilla Anycubic version 1.4 based on RAMPS EFB
else ifeq ($(HARDWARE_MOTHERBOARD),1133) else ifeq ($(HARDWARE_MOTHERBOARD),1133)
# MakeBoard Mini v2.1.2 by MicroMake # TriGorilla Anycubic version 1.4 Rev 1.1
else ifeq ($(HARDWARE_MOTHERBOARD),1134) else ifeq ($(HARDWARE_MOTHERBOARD),1134)
# TriGorilla Anycubic version 1.3-based on RAMPS EFB
else ifeq ($(HARDWARE_MOTHERBOARD),1135)
# ... Ver 1.4
else ifeq ($(HARDWARE_MOTHERBOARD),1136)
# ... Rev 1.1 (new servo pin order)
else ifeq ($(HARDWARE_MOTHERBOARD),1137)
# Creality: Ender-4, CR-8 # Creality: Ender-4, CR-8
else ifeq ($(HARDWARE_MOTHERBOARD),1138) else ifeq ($(HARDWARE_MOTHERBOARD),1135)
# Creality: CR10S, CR20, CR-X # Creality: CR10S, CR20, CR-X
else ifeq ($(HARDWARE_MOTHERBOARD),1139) else ifeq ($(HARDWARE_MOTHERBOARD),1136)
# Dagoma F5 # Dagoma F5
else ifeq ($(HARDWARE_MOTHERBOARD),1140) else ifeq ($(HARDWARE_MOTHERBOARD),1137)
# FYSETC F6 1.3 # FYSETC F6 1.3
else ifeq ($(HARDWARE_MOTHERBOARD),1138)
# FYSETC F6 1.5
else ifeq ($(HARDWARE_MOTHERBOARD),1139)
# Duplicator i3 Plus
else ifeq ($(HARDWARE_MOTHERBOARD),1140)
# VORON
else ifeq ($(HARDWARE_MOTHERBOARD),1141) else ifeq ($(HARDWARE_MOTHERBOARD),1141)
# FYSETC F6 1.4 # TRONXY V3 1.0
else ifeq ($(HARDWARE_MOTHERBOARD),1142) else ifeq ($(HARDWARE_MOTHERBOARD),1142)
# Wanhao Duplicator i3 Plus
else ifeq ($(HARDWARE_MOTHERBOARD),1143)
# VORON Design
else ifeq ($(HARDWARE_MOTHERBOARD),1144)
# Tronxy TRONXY-V3-1.0
else ifeq ($(HARDWARE_MOTHERBOARD),1145)
# Z-Bolt X Series # Z-Bolt X Series
else ifeq ($(HARDWARE_MOTHERBOARD),1146) else ifeq ($(HARDWARE_MOTHERBOARD),1143)
# TT OSCAR # TT OSCAR
else ifeq ($(HARDWARE_MOTHERBOARD),1147) else ifeq ($(HARDWARE_MOTHERBOARD),1144)
# Overlord/Overlord Pro # Overlord/Overlord Pro
else ifeq ($(HARDWARE_MOTHERBOARD),1148) else ifeq ($(HARDWARE_MOTHERBOARD),1145)
# ADIMLab Gantry v1 # ADIMLab Gantry v1
else ifeq ($(HARDWARE_MOTHERBOARD),1149) else ifeq ($(HARDWARE_MOTHERBOARD),1146)
# ADIMLab Gantry v2 # ADIMLab Gantry v2
else ifeq ($(HARDWARE_MOTHERBOARD),1150) else ifeq ($(HARDWARE_MOTHERBOARD),1147)
# BIQU Tango V1 # BIQU Tango V1
else ifeq ($(HARDWARE_MOTHERBOARD),1151) else ifeq ($(HARDWARE_MOTHERBOARD),1148)
# MKS GEN L V2 # MKS GEN L V2
else ifeq ($(HARDWARE_MOTHERBOARD),1152) else ifeq ($(HARDWARE_MOTHERBOARD),1149)
# MKS GEN L V2.1
else ifeq ($(HARDWARE_MOTHERBOARD),1153)
# Copymaster 3D # Copymaster 3D
else ifeq ($(HARDWARE_MOTHERBOARD),1154) else ifeq ($(HARDWARE_MOTHERBOARD),1150)
# Ortur 4
else ifeq ($(HARDWARE_MOTHERBOARD),1155)
# Tenlog D3 Hero IDEX printer
else ifeq ($(HARDWARE_MOTHERBOARD),1156)
# Ramps S 1.2 by Sakul.cz (Power outputs: Hotend0, Hotend1, Fan, Bed)
else ifeq ($(HARDWARE_MOTHERBOARD),1157)
# Ramps S 1.2 by Sakul.cz (Power outputs: Hotend0, Hotend1, Hotend2, Bed)
else ifeq ($(HARDWARE_MOTHERBOARD),1158)
# Ramps S 1.2 by Sakul.cz (Power outputs: Hotend, Fan0, Fan1, Bed)
else ifeq ($(HARDWARE_MOTHERBOARD),1159)
# Longer LK1 PRO / Alfawise U20 Pro (PRO version)
else ifeq ($(HARDWARE_MOTHERBOARD),1160)
# Longer LKx PRO / Alfawise Uxx Pro (PRO version)
else ifeq ($(HARDWARE_MOTHERBOARD),1161)
# Zonestar zrib V5.3 (Chinese RAMPS replica)
else ifeq ($(HARDWARE_MOTHERBOARD),1162)
# Pxmalion Core I3
else ifeq ($(HARDWARE_MOTHERBOARD),1163)
# #
# RAMBo and derivatives # RAMBo and derivatives
@@ -338,8 +286,6 @@ else ifeq ($(HARDWARE_MOTHERBOARD),1203)
else ifeq ($(HARDWARE_MOTHERBOARD),1204) else ifeq ($(HARDWARE_MOTHERBOARD),1204)
# abee Scoovo X9H # abee Scoovo X9H
else ifeq ($(HARDWARE_MOTHERBOARD),1205) else ifeq ($(HARDWARE_MOTHERBOARD),1205)
# Rambo ThinkerV2
else ifeq ($(HARDWARE_MOTHERBOARD),1206)
# #
# Other ATmega1280, ATmega2560 # Other ATmega1280, ATmega2560
@@ -373,38 +319,20 @@ else ifeq ($(HARDWARE_MOTHERBOARD),1311)
else ifeq ($(HARDWARE_MOTHERBOARD),1312) else ifeq ($(HARDWARE_MOTHERBOARD),1312)
# Mega controller # Mega controller
else ifeq ($(HARDWARE_MOTHERBOARD),1313) else ifeq ($(HARDWARE_MOTHERBOARD),1313)
# Geeetech GT2560 Rev A
else ifeq ($(HARDWARE_MOTHERBOARD),1314)
# Geeetech GT2560 Rev A+ (with auto level probe)
else ifeq ($(HARDWARE_MOTHERBOARD),1315)
# Geeetech GT2560 Rev B
else ifeq ($(HARDWARE_MOTHERBOARD),1316)
# Geeetech GT2560 Rev B for A10(M/T/D)
else ifeq ($(HARDWARE_MOTHERBOARD),1317)
# Geeetech GT2560 Rev B for A10(M/T/D)
else ifeq ($(HARDWARE_MOTHERBOARD),1318)
# Geeetech GT2560 Rev B for Mecreator2 # Geeetech GT2560 Rev B for Mecreator2
else ifeq ($(HARDWARE_MOTHERBOARD),1319) else ifeq ($(HARDWARE_MOTHERBOARD),1314)
# Geeetech GT2560 Rev B for A20(M/T/D) # Geeetech GT2560 Rev. A
else ifeq ($(HARDWARE_MOTHERBOARD),1320) else ifeq ($(HARDWARE_MOTHERBOARD),1315)
# Geeetech GT2560 Rev. A+ (with auto level probe)
else ifeq ($(HARDWARE_MOTHERBOARD),1316)
# Geeetech GT2560 Rev B for A10(M/D)
else ifeq ($(HARDWARE_MOTHERBOARD),1317)
# Geeetech GT2560 Rev B for A20(M/D)
else ifeq ($(HARDWARE_MOTHERBOARD),1318)
# Einstart retrofit # Einstart retrofit
else ifeq ($(HARDWARE_MOTHERBOARD),1321) else ifeq ($(HARDWARE_MOTHERBOARD),1319)
# Wanhao 0ne+ i3 Mini # Wanhao 0ne+ i3 Mini
else ifeq ($(HARDWARE_MOTHERBOARD),1322) else ifeq ($(HARDWARE_MOTHERBOARD),1320)
# Leapfrog Xeed 2015
else ifeq ($(HARDWARE_MOTHERBOARD),1323)
# PICA Shield (original version)
else ifeq ($(HARDWARE_MOTHERBOARD),1324)
# PICA Shield (rev C or later)
else ifeq ($(HARDWARE_MOTHERBOARD),1325)
# Intamsys 4.0 (Funmat HT)
else ifeq ($(HARDWARE_MOTHERBOARD),1326)
# Malyan M180 Mainboard Version 2 (no display function, direct G-code only)
else ifeq ($(HARDWARE_MOTHERBOARD),1327)
# Geeetech GT2560 Rev B for A20(M/T/D)
else ifeq ($(HARDWARE_MOTHERBOARD),1328)
# Mega controller & Protoneer CNC Shield V3.00
else ifeq ($(HARDWARE_MOTHERBOARD),1329)
# #
# ATmega1281, ATmega2561 # ATmega1281, ATmega2561
@@ -413,11 +341,9 @@ else ifeq ($(HARDWARE_MOTHERBOARD),1329)
# Minitronics v1.0/1.1 # Minitronics v1.0/1.1
else ifeq ($(HARDWARE_MOTHERBOARD),1400) else ifeq ($(HARDWARE_MOTHERBOARD),1400)
MCU ?= atmega1281 MCU ?= atmega1281
PROG_MCU ?= m1281
# Silvergate v1.0 # Silvergate v1.0
else ifeq ($(HARDWARE_MOTHERBOARD),1401) else ifeq ($(HARDWARE_MOTHERBOARD),1401)
MCU ?= atmega1281 MCU ?= atmega1281
PROG_MCU ?= m1281
# #
# Sanguinololu and Derivatives - ATmega644P, ATmega1284P # Sanguinololu and Derivatives - ATmega644P, ATmega1284P
@@ -427,62 +353,42 @@ else ifeq ($(HARDWARE_MOTHERBOARD),1401)
else ifeq ($(HARDWARE_MOTHERBOARD),1500) else ifeq ($(HARDWARE_MOTHERBOARD),1500)
HARDWARE_VARIANT ?= Sanguino HARDWARE_VARIANT ?= Sanguino
MCU ?= atmega644p MCU ?= atmega644p
PROG_MCU ?= m644p
# Sanguinololu 1.2 and above # Sanguinololu 1.2 and above
else ifeq ($(HARDWARE_MOTHERBOARD),1501) else ifeq ($(HARDWARE_MOTHERBOARD),1501)
HARDWARE_VARIANT ?= Sanguino HARDWARE_VARIANT ?= Sanguino
MCU ?= atmega644p MCU ?= atmega644p
PROG_MCU ?= m644p
# Melzi # Melzi
else ifeq ($(HARDWARE_MOTHERBOARD),1502) else ifeq ($(HARDWARE_MOTHERBOARD),1502)
HARDWARE_VARIANT ?= Sanguino HARDWARE_VARIANT ?= Sanguino
MCU ?= atmega644p MCU ?= atmega644p
PROG_MCU ?= m644p # Melzi with ATmega1284 (MaKr3d version)
# Melzi V2.0
else ifeq ($(HARDWARE_MOTHERBOARD),1503) else ifeq ($(HARDWARE_MOTHERBOARD),1503)
HARDWARE_VARIANT ?= Sanguino HARDWARE_VARIANT ?= Sanguino
MCU ?= atmega1284p MCU ?= atmega1284p
PROG_MCU ?= m1284p # Melzi Creality3D board (for CR-10 etc)
# Melzi with ATmega1284 (MaKr3d version)
else ifeq ($(HARDWARE_MOTHERBOARD),1504) else ifeq ($(HARDWARE_MOTHERBOARD),1504)
HARDWARE_VARIANT ?= Sanguino HARDWARE_VARIANT ?= Sanguino
MCU ?= atmega1284p MCU ?= atmega1284p
PROG_MCU ?= m1284p # Melzi Malyan M150 board
# Melzi Creality3D board (for CR-10 etc)
else ifeq ($(HARDWARE_MOTHERBOARD),1505) else ifeq ($(HARDWARE_MOTHERBOARD),1505)
HARDWARE_VARIANT ?= Sanguino HARDWARE_VARIANT ?= Sanguino
MCU ?= atmega1284p MCU ?= atmega1284p
PROG_MCU ?= m1284p # Tronxy X5S
# Melzi Malyan M150 board
else ifeq ($(HARDWARE_MOTHERBOARD),1506) else ifeq ($(HARDWARE_MOTHERBOARD),1506)
HARDWARE_VARIANT ?= Sanguino HARDWARE_VARIANT ?= Sanguino
MCU ?= atmega1284p MCU ?= atmega1284p
PROG_MCU ?= m1284p # STB V1.1
# Tronxy X5S
else ifeq ($(HARDWARE_MOTHERBOARD),1507) else ifeq ($(HARDWARE_MOTHERBOARD),1507)
HARDWARE_VARIANT ?= Sanguino HARDWARE_VARIANT ?= Sanguino
MCU ?= atmega1284p MCU ?= atmega1284p
PROG_MCU ?= m1284p # Azteeg X1
# STB V1.1
else ifeq ($(HARDWARE_MOTHERBOARD),1508) else ifeq ($(HARDWARE_MOTHERBOARD),1508)
HARDWARE_VARIANT ?= Sanguino HARDWARE_VARIANT ?= Sanguino
MCU ?= atmega1284p MCU ?= atmega1284p
PROG_MCU ?= m1284p # Anet 1.0 (Melzi clone)
# Azteeg X1
else ifeq ($(HARDWARE_MOTHERBOARD),1509) else ifeq ($(HARDWARE_MOTHERBOARD),1509)
HARDWARE_VARIANT ?= Sanguino HARDWARE_VARIANT ?= Sanguino
MCU ?= atmega1284p MCU ?= atmega1284p
PROG_MCU ?= m1284p
# Anet 1.0 (Melzi clone)
else ifeq ($(HARDWARE_MOTHERBOARD),1510)
HARDWARE_VARIANT ?= Sanguino
MCU ?= atmega1284p
PROG_MCU ?= m1284p
# ZoneStar ZMIB V2
else ifeq ($(HARDWARE_MOTHERBOARD),1511)
HARDWARE_VARIANT ?= Sanguino
MCU ?= atmega1284p
PROG_MCU ?= m1284p
# #
# Other ATmega644P, ATmega644, ATmega1284P # Other ATmega644P, ATmega644, ATmega1284P
@@ -492,61 +398,50 @@ else ifeq ($(HARDWARE_MOTHERBOARD),1511)
else ifeq ($(HARDWARE_MOTHERBOARD),1600) else ifeq ($(HARDWARE_MOTHERBOARD),1600)
HARDWARE_VARIANT ?= Sanguino HARDWARE_VARIANT ?= Sanguino
MCU ?= atmega644p MCU ?= atmega644p
PROG_MCU ?= m644p
# Gen3+ # Gen3+
else ifeq ($(HARDWARE_MOTHERBOARD),1601) else ifeq ($(HARDWARE_MOTHERBOARD),1601)
HARDWARE_VARIANT ?= Sanguino HARDWARE_VARIANT ?= Sanguino
MCU ?= atmega644p MCU ?= atmega644p
PROG_MCU ?= m644p
# Gen6 # Gen6
else ifeq ($(HARDWARE_MOTHERBOARD),1602) else ifeq ($(HARDWARE_MOTHERBOARD),1602)
HARDWARE_VARIANT ?= Gen6 HARDWARE_VARIANT ?= Gen6
MCU ?= atmega644p MCU ?= atmega644p
PROG_MCU ?= m644p
# Gen6 deluxe # Gen6 deluxe
else ifeq ($(HARDWARE_MOTHERBOARD),1603) else ifeq ($(HARDWARE_MOTHERBOARD),1603)
HARDWARE_VARIANT ?= Gen6 HARDWARE_VARIANT ?= Gen6
MCU ?= atmega644p MCU ?= atmega644p
PROG_MCU ?= m644p
# Gen7 custom (Alfons3 Version) # Gen7 custom (Alfons3 Version)
else ifeq ($(HARDWARE_MOTHERBOARD),1604) else ifeq ($(HARDWARE_MOTHERBOARD),1604)
HARDWARE_VARIANT ?= Gen7 HARDWARE_VARIANT ?= Gen7
MCU ?= atmega644 MCU ?= atmega644
PROG_MCU ?= m644
F_CPU ?= 20000000 F_CPU ?= 20000000
# Gen7 v1.1, v1.2 # Gen7 v1.1, v1.2
else ifeq ($(HARDWARE_MOTHERBOARD),1605) else ifeq ($(HARDWARE_MOTHERBOARD),1605)
HARDWARE_VARIANT ?= Gen7 HARDWARE_VARIANT ?= Gen7
MCU ?= atmega644p MCU ?= atmega644p
PROG_MCU ?= m644p
F_CPU ?= 20000000 F_CPU ?= 20000000
# Gen7 v1.3 # Gen7 v1.3
else ifeq ($(HARDWARE_MOTHERBOARD),1606) else ifeq ($(HARDWARE_MOTHERBOARD),1606)
HARDWARE_VARIANT ?= Gen7 HARDWARE_VARIANT ?= Gen7
MCU ?= atmega644p MCU ?= atmega644p
PROG_MCU ?= m644p
F_CPU ?= 20000000 F_CPU ?= 20000000
# Gen7 v1.4 # Gen7 v1.4
else ifeq ($(HARDWARE_MOTHERBOARD),1607) else ifeq ($(HARDWARE_MOTHERBOARD),1607)
HARDWARE_VARIANT ?= Gen7 HARDWARE_VARIANT ?= Gen7
MCU ?= atmega1284p MCU ?= atmega1284p
PROG_MCU ?= m1284p
F_CPU ?= 20000000 F_CPU ?= 20000000
# Alpha OMCA board # Alpha OMCA board
else ifeq ($(HARDWARE_MOTHERBOARD),1608) else ifeq ($(HARDWARE_MOTHERBOARD),1608)
HARDWARE_VARIANT ?= SanguinoA HARDWARE_VARIANT ?= SanguinoA
MCU ?= atmega644 MCU ?= atmega644
PROG_MCU ?= m644
# Final OMCA board # Final OMCA board
else ifeq ($(HARDWARE_MOTHERBOARD),1609) else ifeq ($(HARDWARE_MOTHERBOARD),1609)
HARDWARE_VARIANT ?= Sanguino HARDWARE_VARIANT ?= Sanguino
MCU ?= atmega644p MCU ?= atmega644p
PROG_MCU ?= m644p
# Sethi 3D_1 # Sethi 3D_1
else ifeq ($(HARDWARE_MOTHERBOARD),1610) else ifeq ($(HARDWARE_MOTHERBOARD),1610)
HARDWARE_VARIANT ?= Sanguino HARDWARE_VARIANT ?= Sanguino
MCU ?= atmega644p MCU ?= atmega644p
PROG_MCU ?= m644p
# #
# Teensyduino - AT90USB1286, AT90USB1286P # Teensyduino - AT90USB1286, AT90USB1286P
@@ -556,60 +451,51 @@ else ifeq ($(HARDWARE_MOTHERBOARD),1610)
else ifeq ($(HARDWARE_MOTHERBOARD),1700) else ifeq ($(HARDWARE_MOTHERBOARD),1700)
HARDWARE_VARIANT ?= Teensy HARDWARE_VARIANT ?= Teensy
MCU ?= at90usb1286 MCU ?= at90usb1286
PROG_MCU ?= usb1286
# Printrboard (AT90USB1286) # Printrboard (AT90USB1286)
else ifeq ($(HARDWARE_MOTHERBOARD),1701) else ifeq ($(HARDWARE_MOTHERBOARD),1701)
HARDWARE_VARIANT ?= Teensy HARDWARE_VARIANT ?= Teensy
MCU ?= at90usb1286 MCU ?= at90usb1286
PROG_MCU ?= usb1286
# Printrboard Revision F (AT90USB1286) # Printrboard Revision F (AT90USB1286)
else ifeq ($(HARDWARE_MOTHERBOARD),1702) else ifeq ($(HARDWARE_MOTHERBOARD),1702)
HARDWARE_VARIANT ?= Teensy HARDWARE_VARIANT ?= Teensy
MCU ?= at90usb1286 MCU ?= at90usb1286
PROG_MCU ?= usb1286
# Brainwave (AT90USB646) # Brainwave (AT90USB646)
else ifeq ($(HARDWARE_MOTHERBOARD),1703) else ifeq ($(HARDWARE_MOTHERBOARD),1703)
HARDWARE_VARIANT ?= Teensy HARDWARE_VARIANT ?= Teensy
MCU ?= at90usb646 MCU ?= at90usb646
PROG_MCU ?= usb646
# Brainwave Pro (AT90USB1286) # Brainwave Pro (AT90USB1286)
else ifeq ($(HARDWARE_MOTHERBOARD),1704) else ifeq ($(HARDWARE_MOTHERBOARD),1704)
HARDWARE_VARIANT ?= Teensy HARDWARE_VARIANT ?= Teensy
MCU ?= at90usb1286 MCU ?= at90usb1286
PROG_MCU ?= usb1286
# SAV Mk-I (AT90USB1286) # SAV Mk-I (AT90USB1286)
else ifeq ($(HARDWARE_MOTHERBOARD),1705) else ifeq ($(HARDWARE_MOTHERBOARD),1705)
HARDWARE_VARIANT ?= Teensy HARDWARE_VARIANT ?= Teensy
MCU ?= at90usb1286 MCU ?= at90usb1286
PROG_MCU ?= usb1286
# Teensy++2.0 (AT90USB1286) # Teensy++2.0 (AT90USB1286)
else ifeq ($(HARDWARE_MOTHERBOARD),1706) else ifeq ($(HARDWARE_MOTHERBOARD),1706)
HARDWARE_VARIANT ?= Teensy HARDWARE_VARIANT ?= Teensy
MCU ?= at90usb1286 MCU ?= at90usb1286
PROG_MCU ?= usb1286
# 5DPrint D8 Driver Board # 5DPrint D8 Driver Board
else ifeq ($(HARDWARE_MOTHERBOARD),1707) else ifeq ($(HARDWARE_MOTHERBOARD),1707)
HARDWARE_VARIANT ?= Teensy HARDWARE_VARIANT ?= Teensy
MCU ?= at90usb1286 MCU ?= at90usb1286
PROG_MCU ?= usb1286
# UltiMachine Archim1 (with DRV8825 drivers) # UltiMachine Archim1 (with DRV8825 drivers)
else ifeq ($(HARDWARE_MOTHERBOARD),3023) else ifeq ($(HARDWARE_MOTHERBOARD),3023)
HARDWARE_VARIANT ?= archim HARDWARE_VARIANT ?= archim
MCPU = cortex-m3 MCPU = cortex-m3
F_CPU = 84000000 F_CPU = 84000000L
IS_MCU = 0 IS_MCU = 0
# UltiMachine Archim2 (with TMC2130 drivers) # UltiMachine Archim2 (with TMC2130 drivers)
else ifeq ($(HARDWARE_MOTHERBOARD),3024) else ifeq ($(HARDWARE_MOTHERBOARD),3024)
HARDWARE_VARIANT ?= archim HARDWARE_VARIANT ?= archim
MCPU = cortex-m3 MCPU = cortex-m3
F_CPU = 84000000 F_CPU = 84000000L
IS_MCU = 0 IS_MCU = 0
endif endif
# Be sure to regenerate speed_lookuptable.h with create_speed_lookuptable.py # Be sure to regenerate speed_lookuptable.h with create_speed_lookuptable.py
# if you are setting this to something other than 16MHz # if you are setting this to something other than 16MHz
# Do not put the UL suffix, it's done later on.
# Set to 16Mhz if not yet set. # Set to 16Mhz if not yet set.
F_CPU ?= 16000000 F_CPU ?= 16000000
@@ -619,8 +505,7 @@ IS_MCU ?= 1
ifeq ($(IS_MCU),1) ifeq ($(IS_MCU),1)
# Set to arduino, ATmega2560 if not yet set. # Set to arduino, ATmega2560 if not yet set.
HARDWARE_VARIANT ?= arduino HARDWARE_VARIANT ?= arduino
MCU ?= atmega2560 MCU ?= atmega2560
PROG_MCU ?= m2560
TOOL_PREFIX = avr TOOL_PREFIX = avr
MCU_FLAGS = -mmcu=$(MCU) MCU_FLAGS = -mmcu=$(MCU)
@@ -651,36 +536,27 @@ VPATH += $(BUILD_DIR)
VPATH += $(HARDWARE_SRC) VPATH += $(HARDWARE_SRC)
ifeq ($(HARDWARE_VARIANT), $(filter $(HARDWARE_VARIANT),arduino Teensy Sanguino)) ifeq ($(HARDWARE_VARIANT), $(filter $(HARDWARE_VARIANT),arduino Teensy Sanguino))
# Old libraries (avr-core 1.6.21 < / Arduino < 1.6.8) VPATH += $(ARDUINO_INSTALL_DIR)/hardware/marlin/avr/libraries/LiquidCrystal/src
VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/libraries/SPI VPATH += $(ARDUINO_INSTALL_DIR)/hardware/marlin/avr/libraries/SPI
# New libraries (avr-core >= 1.6.21 / Arduino >= 1.6.8)
VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/libraries/SPI/src
endif endif
ifeq ($(IS_MCU),1) ifeq ($(IS_MCU),1)
VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/cores/arduino VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/cores/arduino
# Old libraries (avr-core 1.6.21 < / Arduino < 1.6.8)
VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/libraries/SPI VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/libraries/SPI
VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/libraries/SoftwareSerial
# New libraries (avr-core >= 1.6.21 / Arduino >= 1.6.8)
VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/libraries/SPI/src VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/libraries/SPI/src
VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/libraries/SoftwareSerial/src VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/libraries/SoftwareSerial/src
endif endif
VPATH += $(ARDUINO_INSTALL_DIR)/libraries/LiquidCrystal/src VPATH += $(ARDUINO_INSTALL_DIR)/libraries/LiquidCrystal/src
ifeq ($(LIQUID_TWI2), 1) ifeq ($(LIQUID_TWI2), 1)
WIRE = 1 VPATH += $(ARDUINO_INSTALL_DIR)/libraries/Wire
VPATH += $(ARDUINO_INSTALL_DIR)/libraries/LiquidTWI2 VPATH += $(ARDUINO_INSTALL_DIR)/libraries/Wire/utility
VPATH += $(ARDUINO_INSTALL_DIR)/libraries/LiquidTWI2
endif endif
ifeq ($(WIRE), 1) ifeq ($(WIRE), 1)
# Old libraries (avr-core 1.6.21 / Arduino < 1.6.8) VPATH += $(ARDUINO_INSTALL_DIR)/libraries/Wire
VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/libraries/Wire VPATH += $(ARDUINO_INSTALL_DIR)/libraries/Wire/utility
VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/libraries/Wire/utility
# New libraries (avr-core >= 1.6.21 / Arduino >= 1.6.8)
VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/libraries/Wire/src
VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/libraries/Wire/src/utility
endif endif
ifeq ($(NEOPIXEL), 1) ifeq ($(NEOPIXEL), 1)
VPATH += $(ARDUINO_INSTALL_DIR)/libraries/Adafruit_NeoPixel VPATH += $(ARDUINO_INSTALL_DIR)/libraries/Adafruit_NeoPixel
@@ -752,23 +628,13 @@ ifeq ($(WIRE), 1)
LIB_CXXSRC += Wire.cpp LIB_CXXSRC += Wire.cpp
endif endif
ifeq ($(TONE), 1)
LIB_CXXSRC += Tone.cpp
endif
ifeq ($(U8GLIB), 1) ifeq ($(U8GLIB), 1)
LIB_CXXSRC += U8glib.cpp LIB_CXXSRC += U8glib.cpp
LIB_SRC += u8g_ll_api.c u8g_bitmap.c u8g_clip.c u8g_com_null.c u8g_delay.c \ LIB_SRC += u8g_ll_api.c u8g_bitmap.c u8g_clip.c u8g_com_null.c u8g_delay.c u8g_page.c u8g_pb.c u8g_pb16h1.c u8g_rect.c u8g_state.c u8g_font.c u8g_font_6x13.c u8g_font_04b_03.c u8g_font_5x8.c
u8g_page.c u8g_pb.c u8g_pb16h1.c u8g_rect.c u8g_state.c u8g_font.c \
u8g_font_6x13.c u8g_font_04b_03.c u8g_font_5x8.c
endif endif
ifeq ($(TMC), 1) ifeq ($(TMC), 1)
LIB_CXXSRC += TMCStepper.cpp COOLCONF.cpp DRV_STATUS.cpp IHOLD_IRUN.cpp \ LIB_CXXSRC += TMCStepper.cpp COOLCONF.cpp DRV_STATUS.cpp IHOLD_IRUN.cpp CHOPCONF.cpp GCONF.cpp PWMCONF.cpp DRV_CONF.cpp DRVCONF.cpp DRVCTRL.cpp DRVSTATUS.cpp ENCMODE.cpp RAMP_STAT.cpp SGCSCONF.cpp SHORT_CONF.cpp SMARTEN.cpp SW_MODE.cpp SW_SPI.cpp TMC2130Stepper.cpp TMC2208Stepper.cpp TMC2209Stepper.cpp TMC2660Stepper.cpp TMC5130Stepper.cpp TMC5160Stepper.cpp
CHOPCONF.cpp GCONF.cpp PWMCONF.cpp DRV_CONF.cpp DRVCONF.cpp DRVCTRL.cpp \
DRVSTATUS.cpp ENCMODE.cpp RAMP_STAT.cpp SGCSCONF.cpp SHORT_CONF.cpp \
SMARTEN.cpp SW_MODE.cpp SW_SPI.cpp TMC2130Stepper.cpp TMC2208Stepper.cpp \
TMC2209Stepper.cpp TMC2660Stepper.cpp TMC5130Stepper.cpp TMC5160Stepper.cpp
endif endif
ifeq ($(RELOC_WORKAROUND), 1) ifeq ($(RELOC_WORKAROUND), 1)
@@ -810,23 +676,17 @@ REMOVE = rm -f
MV = mv -f MV = mv -f
# Place -D or -U options here # Place -D or -U options here
CDEFS = -DF_CPU=$(F_CPU)UL ${addprefix -D , $(DEFINES)} -DARDUINO=$(ARDUINO_VERSION) CDEFS = -DF_CPU=$(F_CPU) ${addprefix -D , $(DEFINES)} -DARDUINO=$(ARDUINO_VERSION)
CXXDEFS = $(CDEFS) CXXDEFS = $(CDEFS)
ifeq ($(HARDWARE_VARIANT), Teensy) ifeq ($(HARDWARE_VARIANT), Teensy)
CDEFS += -DUSB_SERIAL CDEFS += -DUSB_SERIAL
LIB_SRC += usb.c pins_teensy.c LIB_SRC += usb.c pins_teensy.c
LIB_CXXSRC += usb_api.cpp LIB_CXXSRC += usb_api.cpp
else ifeq ($(HARDWARE_VARIANT), archim) else ifeq ($(HARDWARE_VARIANT), archim)
CDEFS += -DARDUINO_SAM_ARCHIM -DARDUINO_ARCH_SAM -D__SAM3X8E__ CDEFS += -DARDUINO_SAM_ARCHIM -DARDUINO_ARCH_SAM -D__SAM3X8E__ -DUSB_VID=0x27b1 -DUSB_PID=0x0001 -DUSBCON '-DUSB_MANUFACTURER="UltiMachine"' '-DUSB_PRODUCT="Archim"'
CDEFS += -DUSB_VID=0x27B1 -DUSB_PID=0x0001 -DUSBCON LIB_CXXSRC += variant.cpp IPAddress.cpp Reset.cpp RingBuffer.cpp Stream.cpp UARTClass.cpp USARTClass.cpp abi.cpp new.cpp watchdog.cpp CDC.cpp PluggableUSB.cpp USBCore.cpp
CDEFS += '-DUSB_MANUFACTURER="UltiMachine"' '-DUSB_PRODUCT_STRING="Archim"'
LIB_CXXSRC += variant.cpp IPAddress.cpp Reset.cpp RingBuffer.cpp Stream.cpp \
UARTClass.cpp USARTClass.cpp abi.cpp new.cpp watchdog.cpp CDC.cpp \
PluggableUSB.cpp USBCore.cpp
LIB_SRC += cortex_handlers.c iar_calls_sam3.c syscalls_sam3.c dtostrf.c itoa.c LIB_SRC += cortex_handlers.c iar_calls_sam3.c syscalls_sam3.c dtostrf.c itoa.c
ifeq ($(U8GLIB), 1) ifeq ($(U8GLIB), 1)
@@ -852,20 +712,16 @@ CTUNING = -fsigned-char -funsigned-bitfields -fno-exceptions \
ifneq ($(HARDWARE_MOTHERBOARD),) ifneq ($(HARDWARE_MOTHERBOARD),)
CTUNING += -DMOTHERBOARD=${HARDWARE_MOTHERBOARD} CTUNING += -DMOTHERBOARD=${HARDWARE_MOTHERBOARD}
endif endif
#CEXTRA = -Wa,-adhlns=$(<:.c=.lst) #CEXTRA = -Wa,-adhlns=$(<:.c=.lst)
CXXEXTRA = -fno-use-cxa-atexit -fno-threadsafe-statics -fno-rtti CXXEXTRA = -fno-use-cxa-atexit -fno-threadsafe-statics -fno-rtti
CFLAGS := $(CDEBUG) $(CDEFS) $(CINCS) -O$(OPT) $(CEXTRA) $(CTUNING) $(CSTANDARD) CFLAGS := $(CDEBUG) $(CDEFS) $(CINCS) -O$(OPT) $(CEXTRA) $(CTUNING) $(CSTANDARD)
CXXFLAGS := $(CDEFS) $(CINCS) -O$(OPT) $(CXXEXTRA) $(CTUNING) $(CXXSTANDARD) CXXFLAGS := $(CDEFS) $(CINCS) -O$(OPT) $(CXXEXTRA) $(CTUNING) $(CXXSTANDARD)
ASFLAGS := $(CDEFS) ASFLAGS := $(CDEFS)
#ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs #ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
ifeq ($(HARDWARE_VARIANT), archim) ifeq ($(HARDWARE_VARIANT), archim)
LD_PREFIX = -Wl,--gc-sections,-Map,Marlin.ino.map,--cref,--check-sections,--entry=Reset_Handler,--unresolved-symbols=report-all,--warn-common,--warn-section-align LD_PREFIX = -Wl,--gc-sections,-Map,Marlin.ino.map,--cref,--check-sections,--entry=Reset_Handler,--unresolved-symbols=report-all,--warn-common,--warn-section-align
LD_SUFFIX = $(LDLIBS) LD_SUFFIX = $(LDLIBS)
LDFLAGS = -lm -T$(LDSCRIPT) -u _sbrk -u link -u _close -u _fstat -u _isatty -u _lseek -u _read -u _write -u _exit -u kill -u _getpid
LDFLAGS = -lm -T$(LDSCRIPT) -u _sbrk -u link -u _close -u _fstat -u _isatty
LDFLAGS += -u _lseek -u _read -u _write -u _exit -u kill -u _getpid
else else
LD_PREFIX = -Wl,--gc-sections,--relax LD_PREFIX = -Wl,--gc-sections,--relax
LDFLAGS = -lm LDFLAGS = -lm
@@ -881,7 +737,7 @@ else
AVRDUDE_CONF = $(ARDUINO_INSTALL_DIR)/hardware/tools/avr/etc/avrdude.conf AVRDUDE_CONF = $(ARDUINO_INSTALL_DIR)/hardware/tools/avr/etc/avrdude.conf
endif endif
AVRDUDE_FLAGS = -D -C$(AVRDUDE_CONF) \ AVRDUDE_FLAGS = -D -C$(AVRDUDE_CONF) \
-p$(PROG_MCU) -P$(AVRDUDE_PORT) -c$(AVRDUDE_PROGRAMMER) \ -p$(MCU) -P$(AVRDUDE_PORT) -c$(AVRDUDE_PROGRAMMER) \
-b$(UPLOAD_RATE) -b$(UPLOAD_RATE)
# Since Marlin 2.0, the source files may be distributed into several # Since Marlin 2.0, the source files may be distributed into several
@@ -982,7 +838,7 @@ extcoff: $(TARGET).elf
.elf.eep: .elf.eep:
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \ -$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 -O $(FORMAT) $< $@ --change-section-lma .eeprom=0 -O $(FORMAT) $< $@
# Create extended listing file from ELF output file. # Create extended listing file from ELF output file.
.elf.lss: .elf.lss:
@@ -996,7 +852,7 @@ extcoff: $(TARGET).elf
$(BUILD_DIR)/$(TARGET).elf: $(OBJ) Configuration.h $(BUILD_DIR)/$(TARGET).elf: $(OBJ) Configuration.h
$(Pecho) " CXX $@" $(Pecho) " CXX $@"
$P $(CXX) $(LD_PREFIX) $(ALL_CXXFLAGS) -o $@ -L. $(OBJ) $(LDFLAGS) $(LD_SUFFIX) $P $(CC) $(LD_PREFIX) $(ALL_CXXFLAGS) -o $@ -L. $(OBJ) $(LDFLAGS) $(LD_SUFFIX)
# Object files that were found in "src" will be stored in $(BUILD_DIR) # Object files that were found in "src" will be stored in $(BUILD_DIR)
# in directories that mirror the structure of "src" # in directories that mirror the structure of "src"
@@ -1031,5 +887,5 @@ clean:
.PHONY: all build elf hex eep lss sym program coff extcoff clean depend sizebefore sizeafter .PHONY: all build elf hex eep lss sym program coff extcoff clean depend sizebefore sizeafter
# Automatically include the dependency files created by gcc # Automaticaly include the dependency files created by gcc
-include ${patsubst %.o, %.d, ${OBJ}} -include ${patsubst %.o, %.d, ${OBJ}}

View File

@@ -1,8 +1,9 @@
/*============================================================================== /*
================================================================================
Marlin Firmware Marlin Firmware
(c) 2011-2020 MarlinFirmware (c) 2011-2019 MarlinFirmware
Portions of Marlin are (c) by their respective authors. Portions of Marlin are (c) by their respective authors.
All code complies with GPLv2 and/or GPLv3 All code complies with GPLv2 and/or GPLv3
@@ -11,33 +12,30 @@
Greetings! Thank you for choosing Marlin 2 as your 3D printer firmware. Greetings! Thank you for choosing Marlin 2 as your 3D printer firmware.
To configure Marlin you must edit Configuration.h and Configuration_adv.h To configure Marlin you must edit Configuration.h and Configuration_adv.h
located in the root 'Marlin' folder. Check our Configurations repository to located in the root 'Marlin' folder. Check the config/examples folder to see if
see if there's a more suitable starting-point for your specific hardware. there's a more suitable starting-point for your specific hardware.
Before diving in, we recommend the following essential links: Before diving in, we recommend the following essential links:
Marlin Firmware Official Website Marlin Firmware Official Website
- https://marlinfw.org/ - http://marlinfw.org/
The official Marlin Firmware website contains the most up-to-date The official Marlin Firmware website contains the most up-to-date
documentation. Contributions are always welcome! documentation. Contributions are always welcome!
Configuration Configuration
- https://github.com/MarlinFirmware/Configurations
Example configurations for several printer models.
- https://www.youtube.com/watch?v=3gwWVFtdg-4 - https://www.youtube.com/watch?v=3gwWVFtdg-4
A good 20-minute overview of Marlin configuration by Tom Sanladerer. A good 20-minute overview of Marlin configuration by Tom Sanladerer.
(Applies to Marlin 1.0.x, so Jerk and Acceleration should be halved.) (Applies to Marlin 1.0.x, so Jerk and Acceleration should be halved.)
Also... https://www.google.com/search?tbs=vid%3A1&q=configure+marlin Also... https://www.google.com/search?tbs=vid%3A1&q=configure+marlin
- https://marlinfw.org/docs/configuration/configuration.html - http://marlinfw.org/docs/configuration/configuration.html
Marlin's configuration options are explained in more detail here. Marlin's configuration options are explained in more detail here.
Getting Help Getting Help
- https://reprap.org/forum/list.php?415 - http://forums.reprap.org/list.php?415
The Marlin Discussion Forum is a great place to get help from other Marlin The Marlin Discussion Forum is a great place to get help from other Marlin
users who may have experienced similar issues to your own. users who may have experienced similar issues to your own.
@@ -47,11 +45,9 @@ Getting Help
Contributing Contributing
- https://marlinfw.org/docs/development/contributing.html - http://marlinfw.org/docs/development/contributing.html
If you'd like to contribute to Marlin, read this first! If you'd like to contribute to Marlin, read this first!
- https://marlinfw.org/docs/development/coding_standards.html - http://marlinfw.org/docs/development/coding_standards.html
Before submitting code get to know the Coding Standards. Before submitting code get to know the Coding Standards.
*/
------------------------------------------------------------------------------*/

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#pragma once #pragma once
@@ -28,20 +28,20 @@
/** /**
* Marlin release version identifier * Marlin release version identifier
*/ */
//#define SHORT_BUILD_VERSION "2.0.9.7" //#define SHORT_BUILD_VERSION "2.0.5.5"
/** /**
* Verbose version identifier which should contain a reference to the location * Verbose version identifier which should contain a reference to the location
* from where the binary was downloaded or the source code was compiled. * from where the binary was downloaded or the source code was compiled.
*/ */
//#define DETAILED_BUILD_VERSION SHORT_BUILD_VERSION //#define DETAILED_BUILD_VERSION SHORT_BUILD_VERSION " (Github)"
/** /**
* The STRING_DISTRIBUTION_DATE represents when the binary file was built, * The STRING_DISTRIBUTION_DATE represents when the binary file was built,
* here we define this default string as the date where the latest release * here we define this default string as the date where the latest release
* version was tagged. * version was tagged.
*/ */
//#define STRING_DISTRIBUTION_DATE "2023-07-04" //#define STRING_DISTRIBUTION_DATE "2023-07-18"
/** /**
* Defines a generic printer name to be output to the LCD after booting Marlin. * Defines a generic printer name to be output to the LCD after booting Marlin.
@@ -54,7 +54,7 @@
* has a distinct Github fork— the Source Code URL should just be the main * has a distinct Github fork— the Source Code URL should just be the main
* Marlin repository. * Marlin repository.
*/ */
//#define SOURCE_CODE_URL "github.com/MarlinFirmware/Marlin" //#define SOURCE_CODE_URL "https://github.com/MarlinFirmware/Marlin"
/** /**
* Default generic printer UUID. * Default generic printer UUID.
@@ -65,12 +65,12 @@
* The WEBSITE_URL is the location where users can get more information such as * The WEBSITE_URL is the location where users can get more information such as
* documentation about a specific Marlin release. * documentation about a specific Marlin release.
*/ */
//#define WEBSITE_URL "marlinfw.org" //#define WEBSITE_URL "http://marlinfw.org"
/** /**
* Set the vendor info the serial USB interface, if changable * Set the vendor info the serial USB interface, if changable
* Currently only supported by DUE platform * Currently only supported by DUE platform
*/ */
//#define USB_DEVICE_VENDOR_ID 0x0000 //#define USB_DEVICE_VENDOR_ID 0x0000
//#define USB_DEVICE_PRODUCT_ID 0x0000 //#define USB_DEVICE_PRODUCT_ID 0x0000
//#define USB_DEVICE_MANUFACTURE_NAME WEBSITE_URL //#define USB_DEVICE_MANUFACTURE_NAME WEBSITE_URL

View File

@@ -1,211 +0,0 @@
#
# Marlin Firmware
# config.ini - Options to apply before the build
#
[config:base]
ini_use_config = none
# Load all config: sections in this file
;ini_use_config = all
# Load config file relative to Marlin/
;ini_use_config = another.ini
# Download configurations from GitHub
;ini_use_config = example/Creality/Ender-5 Plus @ bugfix-2.1.x
# Download configurations from your server
;ini_use_config = https://me.myserver.com/path/to/configs
# Evaluate config:base and do a config dump
;ini_use_config = base
;config_export = 2
[config:minimal]
motherboard = BOARD_RAMPS_14_EFB
serial_port = 0
baudrate = 250000
use_watchdog = on
thermal_protection_hotends = on
thermal_protection_hysteresis = 4
thermal_protection_period = 40
bufsize = 4
block_buffer_size = 16
max_cmd_size = 96
extruders = 1
temp_sensor_0 = 1
temp_hysteresis = 3
heater_0_mintemp = 5
heater_0_maxtemp = 275
preheat_1_temp_hotend = 180
bang_max = 255
pidtemp = on
pid_k1 = 0.95
pid_max = BANG_MAX
pid_functional_range = 10
default_kp = 22.20
default_ki = 1.08
default_kd = 114.00
x_driver_type = A4988
y_driver_type = A4988
z_driver_type = A4988
e0_driver_type = A4988
x_bed_size = 200
x_min_pos = 0
x_max_pos = X_BED_SIZE
y_bed_size = 200
y_min_pos = 0
y_max_pos = Y_BED_SIZE
z_min_pos = 0
z_max_pos = 200
x_home_dir = -1
y_home_dir = -1
z_home_dir = -1
use_xmin_plug = on
use_ymin_plug = on
use_zmin_plug = on
x_min_endstop_inverting = false
y_min_endstop_inverting = false
z_min_endstop_inverting = false
default_axis_steps_per_unit = { 80, 80, 400, 500 }
axis_relative_modes = { false, false, false, false }
default_max_feedrate = { 300, 300, 5, 25 }
default_max_acceleration = { 3000, 3000, 100, 10000 }
homing_feedrate_mm_m = { (50*60), (50*60), (4*60) }
homing_bump_divisor = { 2, 2, 4 }
x_enable_on = 0
y_enable_on = 0
z_enable_on = 0
e_enable_on = 0
invert_x_dir = false
invert_y_dir = true
invert_z_dir = false
invert_e0_dir = false
invert_e_step_pin = false
invert_x_step_pin = false
invert_y_step_pin = false
invert_z_step_pin = false
disable_x = false
disable_y = false
disable_z = false
disable_e = false
proportional_font_ratio = 1.0
default_nominal_filament_dia = 1.75
junction_deviation_mm = 0.013
default_acceleration = 3000
default_travel_acceleration = 3000
default_retract_acceleration = 3000
default_minimumfeedrate = 0.0
default_mintravelfeedrate = 0.0
minimum_planner_speed = 0.05
min_steps_per_segment = 6
default_minsegmenttime = 20000
[config:basic]
bed_overshoot = 10
busy_while_heating = on
default_ejerk = 5.0
default_keepalive_interval = 2
default_leveling_fade_height = 0.0
disable_inactive_extruder = on
display_charset_hd44780 = JAPANESE
eeprom_boot_silent = on
eeprom_chitchat = on
endstoppullups = on
extrude_maxlength = 200
extrude_mintemp = 170
host_keepalive_feature = on
hotend_overshoot = 15
jd_handle_small_segments = on
lcd_info_screen_style = 0
lcd_language = en
max_bed_power = 255
mesh_inset = 0
min_software_endstops = on
max_software_endstops = on
min_software_endstop_x = on
min_software_endstop_y = on
min_software_endstop_z = on
max_software_endstop_x = on
max_software_endstop_y = on
max_software_endstop_z = on
preheat_1_fan_speed = 0
preheat_1_label = "PLA"
preheat_1_temp_bed = 70
prevent_cold_extrusion = on
prevent_lengthy_extrude = on
printjob_timer_autostart = on
probing_margin = 10
show_bootscreen = on
soft_pwm_scale = 0
string_config_h_author = "(none, default config)"
temp_bed_hysteresis = 3
temp_bed_residency_time = 10
temp_bed_window = 1
temp_residency_time = 10
temp_window = 1
validate_homing_endstops = on
xy_probe_feedrate = (133*60)
z_clearance_between_probes = 5
z_clearance_deploy_probe = 10
z_clearance_multi_probe = 5
[config:advanced]
arc_support = on
auto_report_temperatures = on
autotemp = on
autotemp_oldweight = 0.98
bed_check_interval = 5000
default_stepper_deactive_time = 120
default_volumetric_extruder_limit = 0.00
disable_inactive_e = true
disable_inactive_x = true
disable_inactive_y = true
disable_inactive_z = true
e0_auto_fan_pin = -1
encoder_100x_steps_per_sec = 80
encoder_10x_steps_per_sec = 30
encoder_rate_multiplier = on
extended_capabilities_report = on
extruder_auto_fan_speed = 255
extruder_auto_fan_temperature = 50
fanmux0_pin = -1
fanmux1_pin = -1
fanmux2_pin = -1
faster_gcode_parser = on
homing_bump_mm = { 5, 5, 2 }
max_arc_segment_mm = 1.0
min_arc_segment_mm = 0.1
min_circle_segments = 72
n_arc_correction = 25
serial_overrun_protection = on
slowdown = on
slowdown_divisor = 2
temp_sensor_bed = 0
thermal_protection_bed_hysteresis = 2
thermocouple_max_errors = 15
tx_buffer_size = 0
watch_bed_temp_increase = 2
watch_bed_temp_period = 60
watch_temp_increase = 2
watch_temp_period = 20

View File

@@ -33,4 +33,4 @@ PlatformIO will find your libraries automatically, configure preprocessor's
include paths and build them. include paths and build them.
More information about PlatformIO Library Dependency Finder More information about PlatformIO Library Dependency Finder
- https://docs.platformio.org/page/librarymanager/ldf.html - http://docs.platformio.org/page/librarymanager/ldf.html

View File

@@ -16,52 +16,26 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#ifdef __AVR__ #ifdef __AVR__
#include "../../inc/MarlinConfig.h" #include "../../inc/MarlinConfig.h"
#include "HAL.h" #include "HAL.h"
#include <avr/wdt.h>
#ifdef USBCON
DefaultSerial1 MSerial0(false, Serial);
#ifdef BLUETOOTH
BTSerial btSerial(false, bluetoothSerial);
#endif
#endif
// ------------------------ // ------------------------
// Public Variables // Public Variables
// ------------------------ // ------------------------
// Don't initialize/override variable (which would happen in .init4) //uint8_t MCUSR;
uint8_t MarlinHAL::reset_reason __attribute__((section(".noinit")));
// ------------------------ // ------------------------
// Public functions // Public functions
// ------------------------ // ------------------------
__attribute__((naked)) // Don't output function pro- and epilogue void HAL_init() {
__attribute__((used)) // Output the function, even if "not used"
__attribute__((section(".init3"))) // Put in an early user definable section
void save_reset_reason() {
#if ENABLED(OPTIBOOT_RESET_REASON)
__asm__ __volatile__(
A("STS %0, r2")
: "=m"(hal.reset_reason)
);
#else
hal.reset_reason = MCUSR;
#endif
// Clear within 16ms since WDRF bit enables a 16ms watchdog timer -> Boot loop
hal.clear_reset_source();
wdt_disable();
}
void MarlinHAL::init() {
// Init Servo Pins // Init Servo Pins
#define INIT_SERVO(N) OUT_WRITE(SERVO##N##_PIN, LOW) #define INIT_SERVO(N) OUT_WRITE(SERVO##N##_PIN, LOW)
#if HAS_SERVO_0 #if HAS_SERVO_0
@@ -76,75 +50,8 @@ void MarlinHAL::init() {
#if HAS_SERVO_3 #if HAS_SERVO_3
INIT_SERVO(3); INIT_SERVO(3);
#endif #endif
init_pwm_timers(); // Init user timers to default frequency - 1000HZ
} }
void MarlinHAL::reboot() {
#if ENABLED(USE_WATCHDOG)
while (1) { /* run out the watchdog */ }
#else
void (*resetFunc)() = 0; // Declare resetFunc() at address 0
resetFunc(); // Jump to address 0
#endif
}
// ------------------------
// Watchdog Timer
// ------------------------
#if ENABLED(USE_WATCHDOG)
#include <avr/wdt.h>
#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) #if ENABLED(SDSUPPORT)
#include "../../sd/SdFatUtil.h" #include "../../sd/SdFatUtil.h"
@@ -152,20 +59,20 @@ void MarlinHAL::reboot() {
#else // !SDSUPPORT #else // !SDSUPPORT
extern "C" { extern "C" {
extern char __bss_end; extern char __bss_end;
extern char __heap_start; extern char __heap_start;
extern void* __brkval; extern void* __brkval;
int freeMemory() { int freeMemory() {
int free_memory; int free_memory;
if ((int)__brkval == 0) if ((int)__brkval == 0)
free_memory = ((int)&free_memory) - ((int)&__bss_end); free_memory = ((int)&free_memory) - ((int)&__bss_end);
else else
free_memory = ((int)&free_memory) - ((int)__brkval); free_memory = ((int)&free_memory) - ((int)__brkval);
return free_memory; return free_memory;
}
} }
}
#endif // !SDSUPPORT #endif // !SDSUPPORT

View File

@@ -14,23 +14,20 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/ */
#pragma once #pragma once
/**
* HAL for Arduino AVR
*/
#include "../shared/Marduino.h" #include "../shared/Marduino.h"
#include "../shared/HAL_SPI.h" #include "../shared/HAL_SPI.h"
#include "fastio.h" #include "fastio.h"
#include "watchdog.h"
#include "math.h" #include "math.h"
#ifdef USBCON #ifdef USBCON
#include <HardwareSerial.h> #include <HardwareSerial.h>
#else #else
#define HardwareSerial_h // Hack to prevent HardwareSerial.h header inclusion
#include "MarlinSerial.h" #include "MarlinSerial.h"
#endif #endif
@@ -41,19 +38,6 @@
#include <avr/interrupt.h> #include <avr/interrupt.h>
#include <avr/io.h> #include <avr/io.h>
//
// Default graphical display delays
//
#if F_CPU >= 20000000
#define CPU_ST7920_DELAY_1 150
#define CPU_ST7920_DELAY_2 0
#define CPU_ST7920_DELAY_3 150
#elif F_CPU == 16000000
#define CPU_ST7920_DELAY_1 125
#define CPU_ST7920_DELAY_2 0
#define CPU_ST7920_DELAY_3 188
#endif
#ifndef pgm_read_ptr #ifndef pgm_read_ptr
// Compatibility for avr-libc 1.8.0-4.1 included with Ubuntu for // Compatibility for avr-libc 1.8.0-4.1 included with Ubuntu for
// Windows Subsystem for Linux on Windows 10 as of 10/18/2019 // Windows Subsystem for Linux on Windows 10 as of 10/18/2019
@@ -66,97 +50,343 @@
// Defines // Defines
// ------------------------ // ------------------------
// AVR PROGMEM extension for sprintf_P //#define analogInputToDigitalPin(IO) IO
#define S_FMT "%S"
// AVR PROGMEM extension for string define
#define PGMSTR(NAM,STR) const char NAM[] PROGMEM = STR
#ifndef CRITICAL_SECTION_START #ifndef CRITICAL_SECTION_START
#define CRITICAL_SECTION_START() unsigned char _sreg = SREG; cli() #define CRITICAL_SECTION_START() unsigned char _sreg = SREG; cli()
#define CRITICAL_SECTION_END() SREG = _sreg #define CRITICAL_SECTION_END() SREG = _sreg
#endif #endif
#define ISRS_ENABLED() TEST(SREG, SREG_I)
#define ENABLE_ISRS() sei()
#define DISABLE_ISRS() cli()
#define HAL_CAN_SET_PWM_FREQ // This HAL supports PWM Frequency adjustment // On AVR this is in math.h?
#define PWM_FREQUENCY 1000 // Default PWM frequency when set_pwm_duty() is called without set_pwm_frequency() //#define square(x) ((x)*(x))
// ------------------------ // ------------------------
// Types // Types
// ------------------------ // ------------------------
typedef uint16_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX 0xFFFF
typedef int8_t pin_t; typedef int8_t pin_t;
#define SHARED_SERVOS HAS_SERVOS // Use shared/servos.cpp #define SHARED_SERVOS HAS_SERVOS
#define HAL_SERVO_LIB Servo
class Servo;
typedef Servo hal_servo_t;
// ------------------------ // ------------------------
// Public Variables
// ------------------------
//extern uint8_t MCUSR;
// Serial ports // Serial ports
// ------------------------
#ifdef USBCON #ifdef USBCON
#include "../../core/serial_hook.h" #if ENABLED(BLUETOOTH)
typedef ForwardSerial1Class< decltype(Serial) > DefaultSerial1; #define MYSERIAL0 bluetoothSerial
extern DefaultSerial1 MSerial0; #else
#ifdef BLUETOOTH #define MYSERIAL0 Serial
typedef ForwardSerial1Class< decltype(bluetoothSerial) > BTSerial;
extern BTSerial btSerial;
#endif #endif
#define NUM_SERIAL 1
#define MYSERIAL1 TERN(BLUETOOTH, btSerial, MSerial0)
#else #else
#if !WITHIN(SERIAL_PORT, -1, 3) #if !WITHIN(SERIAL_PORT, -1, 3)
#error "SERIAL_PORT must be from 0 to 3, or -1 for USB Serial." #error "SERIAL_PORT must be from -1 to 3. Please update your configuration."
#endif #endif
#define MYSERIAL1 customizedSerial1
#define MYSERIAL0 customizedSerial1
#ifdef SERIAL_PORT_2 #ifdef SERIAL_PORT_2
#if !WITHIN(SERIAL_PORT_2, -1, 3) #if !WITHIN(SERIAL_PORT_2, -1, 3)
#error "SERIAL_PORT_2 must be from 0 to 3, or -1 for USB Serial." #error "SERIAL_PORT_2 must be from -1 to 3. Please update your configuration."
#elif SERIAL_PORT_2 == SERIAL_PORT
#error "SERIAL_PORT_2 must be different than SERIAL_PORT. Please update your configuration."
#endif #endif
#define MYSERIAL2 customizedSerial2 #define MYSERIAL1 customizedSerial2
#endif #define NUM_SERIAL 2
#else
#ifdef SERIAL_PORT_3 #define NUM_SERIAL 1
#if !WITHIN(SERIAL_PORT_3, -1, 3)
#error "SERIAL_PORT_3 must be from 0 to 3, or -1 for USB Serial."
#endif
#define MYSERIAL3 customizedSerial3
#endif #endif
#endif #endif
#ifdef MMU2_SERIAL_PORT #ifdef DGUS_SERIAL_PORT
#if !WITHIN(MMU2_SERIAL_PORT, -1, 3) #if !WITHIN(DGUS_SERIAL_PORT, -1, 3)
#error "MMU2_SERIAL_PORT must be from 0 to 3, or -1 for USB Serial." #error "DGUS_SERIAL_PORT must be from -1 to 3. Please update your configuration."
#elif DGUS_SERIAL_PORT == SERIAL_PORT
#error "DGUS_SERIAL_PORT must be different than SERIAL_PORT. Please update your configuration."
#elif defined(SERIAL_PORT_2) && DGUS_SERIAL_PORT == SERIAL_PORT_2
#error "DGUS_SERIAL_PORT must be different than SERIAL_PORT_2. Please update your configuration."
#endif #endif
#define MMU2_SERIAL mmuSerial #define DGUS_SERIAL internalDgusSerial
#define DGUS_SERIAL_GET_TX_BUFFER_FREE DGUS_SERIAL.get_tx_buffer_free
#endif #endif
#ifdef LCD_SERIAL_PORT // ------------------------
#if !WITHIN(LCD_SERIAL_PORT, -1, 3) // Public functions
#error "LCD_SERIAL_PORT must be from 0 to 3, or -1 for USB Serial." // ------------------------
#endif
#define LCD_SERIAL lcdSerial void HAL_init();
#if HAS_DGUS_LCD
#define SERIAL_GET_TX_BUFFER_FREE() LCD_SERIAL.get_tx_buffer_free() //void cli();
#endif
#endif //void _delay_ms(const int delay);
inline void HAL_clear_reset_source() { MCUSR = 0; }
inline uint8_t HAL_get_reset_source() { return MCUSR; }
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-function"
extern "C" {
int freeMemory();
}
#pragma GCC diagnostic pop
// timers
#define HAL_TIMER_RATE ((F_CPU) / 8) // i.e., 2MHz or 2.5MHz
#define STEP_TIMER_NUM 1
#define TEMP_TIMER_NUM 0
#define PULSE_TIMER_NUM STEP_TIMER_NUM
#define TEMP_TIMER_FREQUENCY ((F_CPU) / 64.0 / 256.0)
#define STEPPER_TIMER_RATE HAL_TIMER_RATE
#define STEPPER_TIMER_PRESCALE 8
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // Cannot be of type double
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // frequency of pulse timer
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define ENABLE_STEPPER_DRIVER_INTERRUPT() SBI(TIMSK1, OCIE1A)
#define DISABLE_STEPPER_DRIVER_INTERRUPT() CBI(TIMSK1, OCIE1A)
#define STEPPER_ISR_ENABLED() TEST(TIMSK1, OCIE1A)
#define ENABLE_TEMPERATURE_INTERRUPT() SBI(TIMSK0, OCIE0B)
#define DISABLE_TEMPERATURE_INTERRUPT() CBI(TIMSK0, OCIE0B)
#define TEMPERATURE_ISR_ENABLED() TEST(TIMSK0, OCIE0B)
FORCE_INLINE void HAL_timer_start(const uint8_t timer_num, const uint32_t) {
switch (timer_num) {
case STEP_TIMER_NUM:
// waveform generation = 0100 = CTC
SET_WGM(1, CTC_OCRnA);
// output mode = 00 (disconnected)
SET_COMA(1, NORMAL);
// Set the timer pre-scaler
// Generally we use a divider of 8, resulting in a 2MHz timer
// frequency on a 16MHz MCU. If you are going to change this, be
// sure to regenerate speed_lookuptable.h with
// create_speed_lookuptable.py
SET_CS(1, PRESCALER_8); // CS 2 = 1/8 prescaler
// Init Stepper ISR to 122 Hz for quick starting
// (F_CPU) / (STEPPER_TIMER_PRESCALE) / frequency
OCR1A = 0x4000;
TCNT1 = 0;
break;
case TEMP_TIMER_NUM:
// Use timer0 for temperature measurement
// Interleave temperature interrupt with millies interrupt
OCR0B = 128;
break;
}
}
#define TIMER_OCR_1 OCR1A
#define TIMER_COUNTER_1 TCNT1
#define TIMER_OCR_0 OCR0A
#define TIMER_COUNTER_0 TCNT0
#define _CAT(a,V...) a##V
#define HAL_timer_set_compare(timer, compare) (_CAT(TIMER_OCR_, timer) = compare)
#define HAL_timer_get_compare(timer) _CAT(TIMER_OCR_, timer)
#define HAL_timer_get_count(timer) _CAT(TIMER_COUNTER_, timer)
/**
* On AVR there is no hardware prioritization and preemption of
* interrupts, so this emulates it. The UART has first priority
* (otherwise, characters will be lost due to UART overflow).
* Then: Stepper, Endstops, Temperature, and -finally- all others.
*/
#define HAL_timer_isr_prologue(TIMER_NUM)
#define HAL_timer_isr_epilogue(TIMER_NUM)
/* 18 cycles maximum latency */
#define HAL_STEP_TIMER_ISR() \
extern "C" void TIMER1_COMPA_vect() __attribute__ ((signal, naked, used, externally_visible)); \
extern "C" void TIMER1_COMPA_vect_bottom() asm ("TIMER1_COMPA_vect_bottom") __attribute__ ((used, externally_visible, noinline)); \
void TIMER1_COMPA_vect() { \
__asm__ __volatile__ ( \
A("push r16") /* 2 Save R16 */ \
A("in r16, __SREG__") /* 1 Get SREG */ \
A("push r16") /* 2 Save SREG into stack */ \
A("lds r16, %[timsk0]") /* 2 Load into R0 the Temperature timer Interrupt mask register */ \
A("push r16") /* 2 Save TIMSK0 into the stack */ \
A("andi r16,~%[msk0]") /* 1 Disable the temperature ISR */ \
A("sts %[timsk0], r16") /* 2 And set the new value */ \
A("lds r16, %[timsk1]") /* 2 Load into R0 the stepper timer Interrupt mask register [TIMSK1] */ \
A("andi r16,~%[msk1]") /* 1 Disable the stepper ISR */ \
A("sts %[timsk1], r16") /* 2 And set the new value */ \
A("push r16") /* 2 Save TIMSK1 into stack */ \
A("in r16, 0x3B") /* 1 Get RAMPZ register */ \
A("push r16") /* 2 Save RAMPZ into stack */ \
A("in r16, 0x3C") /* 1 Get EIND register */ \
A("push r0") /* C runtime can modify all the following registers without restoring them */ \
A("push r1") \
A("push r18") \
A("push r19") \
A("push r20") \
A("push r21") \
A("push r22") \
A("push r23") \
A("push r24") \
A("push r25") \
A("push r26") \
A("push r27") \
A("push r30") \
A("push r31") \
A("clr r1") /* C runtime expects this register to be 0 */ \
A("call TIMER1_COMPA_vect_bottom") /* Call the bottom handler - No inlining allowed, otherwise registers used are not saved */ \
A("pop r31") \
A("pop r30") \
A("pop r27") \
A("pop r26") \
A("pop r25") \
A("pop r24") \
A("pop r23") \
A("pop r22") \
A("pop r21") \
A("pop r20") \
A("pop r19") \
A("pop r18") \
A("pop r1") \
A("pop r0") \
A("out 0x3C, r16") /* 1 Restore EIND register */ \
A("pop r16") /* 2 Get the original RAMPZ register value */ \
A("out 0x3B, r16") /* 1 Restore RAMPZ register to its original value */ \
A("pop r16") /* 2 Get the original TIMSK1 value but with stepper ISR disabled */ \
A("ori r16,%[msk1]") /* 1 Reenable the stepper ISR */ \
A("cli") /* 1 Disable global interrupts - Reenabling Stepper ISR can reenter amd temperature can reenter, and we want that, if it happens, after this ISR has ended */ \
A("sts %[timsk1], r16") /* 2 And restore the old value - This reenables the stepper ISR */ \
A("pop r16") /* 2 Get the temperature timer Interrupt mask register [TIMSK0] */ \
A("sts %[timsk0], r16") /* 2 And restore the old value - This reenables the temperature ISR */ \
A("pop r16") /* 2 Get the old SREG value */ \
A("out __SREG__, r16") /* 1 And restore the SREG value */ \
A("pop r16") /* 2 Restore R16 value */ \
A("reti") /* 4 Return from interrupt */ \
: \
: [timsk0] "i" ((uint16_t)&TIMSK0), \
[timsk1] "i" ((uint16_t)&TIMSK1), \
[msk0] "M" ((uint8_t)(1<<OCIE0B)),\
[msk1] "M" ((uint8_t)(1<<OCIE1A)) \
: \
); \
} \
void TIMER1_COMPA_vect_bottom()
/* 14 cycles maximum latency */
#define HAL_TEMP_TIMER_ISR() \
extern "C" void TIMER0_COMPB_vect() __attribute__ ((signal, naked, used, externally_visible)); \
extern "C" void TIMER0_COMPB_vect_bottom() asm ("TIMER0_COMPB_vect_bottom") __attribute__ ((used, externally_visible, noinline)); \
void TIMER0_COMPB_vect() { \
__asm__ __volatile__ ( \
A("push r16") /* 2 Save R16 */ \
A("in r16, __SREG__") /* 1 Get SREG */ \
A("push r16") /* 2 Save SREG into stack */ \
A("lds r16, %[timsk0]") /* 2 Load into R0 the Temperature timer Interrupt mask register */ \
A("andi r16,~%[msk0]") /* 1 Disable the temperature ISR */ \
A("sts %[timsk0], r16") /* 2 And set the new value */ \
A("sei") /* 1 Enable global interrupts - It is safe, as the temperature ISR is disabled, so we cannot reenter it */ \
A("push r16") /* 2 Save TIMSK0 into stack */ \
A("in r16, 0x3B") /* 1 Get RAMPZ register */ \
A("push r16") /* 2 Save RAMPZ into stack */ \
A("in r16, 0x3C") /* 1 Get EIND register */ \
A("push r0") /* C runtime can modify all the following registers without restoring them */ \
A("push r1") \
A("push r18") \
A("push r19") \
A("push r20") \
A("push r21") \
A("push r22") \
A("push r23") \
A("push r24") \
A("push r25") \
A("push r26") \
A("push r27") \
A("push r30") \
A("push r31") \
A("clr r1") /* C runtime expects this register to be 0 */ \
A("call TIMER0_COMPB_vect_bottom") /* Call the bottom handler - No inlining allowed, otherwise registers used are not saved */ \
A("pop r31") \
A("pop r30") \
A("pop r27") \
A("pop r26") \
A("pop r25") \
A("pop r24") \
A("pop r23") \
A("pop r22") \
A("pop r21") \
A("pop r20") \
A("pop r19") \
A("pop r18") \
A("pop r1") \
A("pop r0") \
A("out 0x3C, r16") /* 1 Restore EIND register */ \
A("pop r16") /* 2 Get the original RAMPZ register value */ \
A("out 0x3B, r16") /* 1 Restore RAMPZ register to its original value */ \
A("pop r16") /* 2 Get the original TIMSK0 value but with temperature ISR disabled */ \
A("ori r16,%[msk0]") /* 1 Enable temperature ISR */ \
A("cli") /* 1 Disable global interrupts - We must do this, as we will reenable the temperature ISR, and we don't want to reenter this handler until the current one is done */ \
A("sts %[timsk0], r16") /* 2 And restore the old value */ \
A("pop r16") /* 2 Get the old SREG */ \
A("out __SREG__, r16") /* 1 And restore the SREG value */ \
A("pop r16") /* 2 Restore R16 */ \
A("reti") /* 4 Return from interrupt */ \
: \
: [timsk0] "i"((uint16_t)&TIMSK0), \
[msk0] "M" ((uint8_t)(1<<OCIE0B)) \
: \
); \
} \
void TIMER0_COMPB_vect_bottom()
//
// ADC // ADC
// #ifdef DIDR2
#define HAL_ADC_VREF 5.0 #define HAL_ANALOG_SELECT(ind) do{ if (ind < 8) SBI(DIDR0, ind); else SBI(DIDR2, ind & 0x07); }while(0)
#define HAL_ADC_RESOLUTION 10 #else
#define HAL_ANALOG_SELECT(ind) SBI(DIDR0, ind);
#endif
inline void HAL_adc_init() {
ADCSRA = _BV(ADEN) | _BV(ADSC) | _BV(ADIF) | 0x07;
DIDR0 = 0;
#ifdef DIDR2
DIDR2 = 0;
#endif
}
#define SET_ADMUX_ADCSRA(ch) ADMUX = _BV(REFS0) | (ch & 0x07); SBI(ADCSRA, ADSC)
#ifdef MUX5
#define HAL_START_ADC(ch) if (ch > 7) ADCSRB = _BV(MUX5); else ADCSRB = 0; SET_ADMUX_ADCSRA(ch)
#else
#define HAL_START_ADC(ch) ADCSRB = 0; SET_ADMUX_ADCSRA(ch)
#endif
#define HAL_ADC_RESOLUTION 10
#define HAL_READ_ADC() ADC
#define HAL_ADC_READY() !TEST(ADCSRA, ADSC)
//
// Pin Mapping for M42, M43, M226
//
#define GET_PIN_MAP_PIN(index) index #define GET_PIN_MAP_PIN(index) index
#define GET_PIN_MAP_INDEX(pin) pin #define GET_PIN_MAP_INDEX(pin) pin
#define PARSED_PIN_INDEX(code, dval) parser.intval(code, dval) #define PARSED_PIN_INDEX(code, dval) parser.intval(code, dval)
#define HAL_SENSITIVE_PINS 0, 1, #define HAL_SENSITIVE_PINS 0, 1
#ifdef __AVR_AT90USB1286__ #ifdef __AVR_AT90USB1286__
#define JTAG_DISABLE() do{ MCUCR = 0x80; MCUCR = 0x80; }while(0) #define JTAG_DISABLE() do{ MCUCR = 0x80; MCUCR = 0x80; }while(0)
@@ -165,113 +395,21 @@ typedef Servo hal_servo_t;
// AVR compatibility // AVR compatibility
#define strtof strtod #define strtof strtod
// ------------------------ /**
// Free Memory Accessor * set_pwm_frequency
// ------------------------ * Sets the frequency of the timer corresponding to the provided pin
* as close as possible to the provided desired frequency. Internally
* calculates the required waveform generation mode, prescaler and
* resolution values required and sets the timer registers accordingly.
* NOTE that the frequency is applied to all pins on the timer (Ex OC3A, OC3B and OC3B)
* NOTE that there are limitations, particularly if using TIMER2. (see Configuration_adv.h -> FAST FAN PWM Settings)
*/
void set_pwm_frequency(const pin_t pin, int f_desired);
#pragma GCC diagnostic push /**
#if GCC_VERSION <= 50000 * set_pwm_duty
#pragma GCC diagnostic ignored "-Wunused-function" * Sets the PWM duty cycle of the provided pin to the provided value
#endif * Optionally allows inverting the duty cycle [default = false]
* Optionally allows changing the maximum size of the provided value to enable finer PWM duty control [default = 255]
extern "C" int freeMemory(); */
void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size=255, const bool invert=false);
#pragma GCC diagnostic pop
// ------------------------
// MarlinHAL Class
// ------------------------
class MarlinHAL {
public:
// Earliest possible init, before setup()
MarlinHAL() {}
// Watchdog
static void watchdog_init() IF_DISABLED(USE_WATCHDOG, {});
static void watchdog_refresh() IF_DISABLED(USE_WATCHDOG, {});
static void init(); // Called early in setup()
static void init_board() {} // Called less early in setup()
static void reboot(); // Restart the firmware from 0x0
// Interrupts
static bool isr_state() { return TEST(SREG, SREG_I); }
static void isr_on() { sei(); }
static void isr_off() { cli(); }
static void delay_ms(const int ms) { _delay_ms(ms); }
// Tasks, called from idle()
static void idletask() {}
// Reset
static uint8_t reset_reason;
static uint8_t get_reset_source() { return reset_reason; }
static void clear_reset_source() { MCUSR = 0; }
// Free SRAM
static int freeMemory() { return ::freeMemory(); }
//
// ADC Methods
//
// Called by Temperature::init once at startup
static void adc_init() {
ADCSRA = _BV(ADEN) | _BV(ADSC) | _BV(ADIF) | 0x07;
DIDR0 = 0;
#ifdef DIDR2
DIDR2 = 0;
#endif
}
// Called by Temperature::init for each sensor at startup
static void adc_enable(const uint8_t ch) {
#ifdef DIDR2
if (ch > 7) { SBI(DIDR2, ch & 0x07); return; }
#endif
SBI(DIDR0, ch);
}
// Begin ADC sampling on the given channel. Called from Temperature::isr!
static void adc_start(const uint8_t ch) {
#ifdef MUX5
ADCSRB = ch > 7 ? _BV(MUX5) : 0;
#else
ADCSRB = 0;
#endif
ADMUX = _BV(REFS0) | (ch & 0x07);
SBI(ADCSRA, ADSC);
}
// Is the ADC ready for reading?
static bool adc_ready() { return !TEST(ADCSRA, ADSC); }
// The current value of the ADC register
static __typeof__(ADC) adc_value() { return ADC; }
/**
* init_pwm_timers
* Set the default frequency for timers 2-5 to 1000HZ
*/
static void init_pwm_timers();
/**
* Set the PWM duty cycle for the pin to the given value.
* Optionally invert the duty cycle [default = false]
* Optionally change the scale of the provided value to enable finer PWM duty control [default = 255]
*/
static void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size=255, const bool invert=false);
/**
* Set the frequency of the timer for the given pin as close as
* possible to the provided desired frequency. Internally calculate
* the required waveform generation mode, prescaler, and resolution
* values and set timer registers accordingly.
* NOTE that the frequency is applied to all pins on the timer (Ex OC3A, OC3B and OC3B)
* NOTE that there are limitations, particularly if using TIMER2. (see Configuration_adv.h -> FAST_PWM_FAN Settings)
*/
static void set_pwm_frequency(const pin_t pin, const uint16_t f_desired);
};

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@@ -34,21 +34,21 @@
#include "../../inc/MarlinConfig.h" #include "../../inc/MarlinConfig.h"
void spiBegin() { void spiBegin() {
#if PIN_EXISTS(SD_SS) OUT_WRITE(SS_PIN, HIGH);
// Do not init HIGH for boards with pin 4 used as Fans or Heaters or otherwise, not likely to have multiple SPI devices anyway. SET_OUTPUT(SCK_PIN);
#if defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) || defined(__AVR_ATmega1284P__) SET_INPUT(MISO_PIN);
// SS must be in output mode even it is not chip select SET_OUTPUT(MOSI_PIN);
SET_OUTPUT(SD_SS_PIN);
#else
// set SS high - may be chip select for another SPI device
OUT_WRITE(SD_SS_PIN, HIGH);
#endif
#endif
SET_OUTPUT(SD_SCK_PIN);
SET_INPUT(SD_MISO_PIN);
SET_OUTPUT(SD_MOSI_PIN);
IF_DISABLED(SOFTWARE_SPI, spiInit(SPI_HALF_SPEED)); #if DISABLED(SOFTWARE_SPI)
// SS must be in output mode even it is not chip select
//SET_OUTPUT(SS_PIN);
// set SS high - may be chip select for another SPI device
//#if SET_SPI_SS_HIGH
//WRITE(SS_PIN, HIGH);
//#endif
// set a default rate
spiInit(1);
#endif
} }
#if NONE(SOFTWARE_SPI, FORCE_SOFT_SPI) #if NONE(SOFTWARE_SPI, FORCE_SOFT_SPI)
@@ -74,8 +74,7 @@ void spiBegin() {
#elif defined(PRR0) #elif defined(PRR0)
PRR0 PRR0
#endif #endif
, PRSPI , PRSPI);
);
SPCR = _BV(SPE) | _BV(MSTR) | (spiRate >> 1); SPCR = _BV(SPE) | _BV(MSTR) | (spiRate >> 1);
SPSR = spiRate & 1 || spiRate == 6 ? 0 : _BV(SPI2X); SPSR = spiRate & 1 || spiRate == 6 ? 0 : _BV(SPI2X);
@@ -89,7 +88,7 @@ void spiBegin() {
} }
/** SPI read data */ /** SPI read data */
void spiRead(uint8_t *buf, uint16_t nbyte) { void spiRead(uint8_t* buf, uint16_t nbyte) {
if (nbyte-- == 0) return; if (nbyte-- == 0) return;
SPDR = 0xFF; SPDR = 0xFF;
for (uint16_t i = 0; i < nbyte; i++) { for (uint16_t i = 0; i < nbyte; i++) {
@@ -108,7 +107,7 @@ void spiBegin() {
} }
/** SPI send block */ /** SPI send block */
void spiSendBlock(uint8_t token, const uint8_t *buf) { void spiSendBlock(uint8_t token, const uint8_t* buf) {
SPDR = token; SPDR = token;
for (uint16_t i = 0; i < 512; i += 2) { for (uint16_t i = 0; i < 512; i += 2) {
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ } while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
@@ -196,19 +195,19 @@ void spiBegin() {
// no interrupts during byte receive - about 8µs // no interrupts during byte receive - about 8µs
cli(); cli();
// output pin high - like sending 0xFF // output pin high - like sending 0xFF
WRITE(SD_MOSI_PIN, HIGH); WRITE(MOSI_PIN, HIGH);
LOOP_L_N(i, 8) { LOOP_L_N(i, 8) {
WRITE(SD_SCK_PIN, HIGH); WRITE(SCK_PIN, HIGH);
nop; // adjust so SCK is nice nop; // adjust so SCK is nice
nop; nop;
data <<= 1; data <<= 1;
if (READ(SD_MISO_PIN)) data |= 1; if (READ(MISO_PIN)) data |= 1;
WRITE(SD_SCK_PIN, LOW); WRITE(SCK_PIN, LOW);
} }
sei(); sei();
@@ -216,7 +215,7 @@ void spiBegin() {
} }
// Soft SPI read data // Soft SPI read data
void spiRead(uint8_t *buf, uint16_t nbyte) { void spiRead(uint8_t* buf, uint16_t nbyte) {
for (uint16_t i = 0; i < nbyte; i++) for (uint16_t i = 0; i < nbyte; i++)
buf[i] = spiRec(); buf[i] = spiRec();
} }
@@ -226,10 +225,10 @@ void spiBegin() {
// no interrupts during byte send - about 8µs // no interrupts during byte send - about 8µs
cli(); cli();
LOOP_L_N(i, 8) { LOOP_L_N(i, 8) {
WRITE(SD_SCK_PIN, LOW); WRITE(SCK_PIN, LOW);
WRITE(SD_MOSI_PIN, data & 0x80); WRITE(MOSI_PIN, data & 0x80);
data <<= 1; data <<= 1;
WRITE(SD_SCK_PIN, HIGH); WRITE(SCK_PIN, HIGH);
} }
nop; // hold SCK high for a few ns nop; // hold SCK high for a few ns
@@ -237,13 +236,13 @@ void spiBegin() {
nop; nop;
nop; nop;
WRITE(SD_SCK_PIN, LOW); WRITE(SCK_PIN, LOW);
sei(); sei();
} }
// Soft SPI send block // Soft SPI send block
void spiSendBlock(uint8_t token, const uint8_t *buf) { void spiSendBlock(uint8_t token, const uint8_t* buf) {
spiSend(token); spiSend(token);
for (uint16_t i = 0; i < 512; i++) for (uint16_t i = 0; i < 512; i++)
spiSend(buf[i]); spiSend(buf[i]);

View File

@@ -1,26 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#include <SPI.h>
using MarlinSPI = SPIClass;

File diff suppressed because it is too large Load Diff

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#pragma once #pragma once
@@ -34,7 +34,6 @@
#include <WString.h> #include <WString.h>
#include "../../inc/MarlinConfigPre.h" #include "../../inc/MarlinConfigPre.h"
#include "../../core/serial_hook.h"
#ifndef SERIAL_PORT #ifndef SERIAL_PORT
#define SERIAL_PORT 0 #define SERIAL_PORT 0
@@ -49,11 +48,11 @@
// These are macros to build serial port register names for the selected SERIAL_PORT (C preprocessor // These are macros to build serial port register names for the selected SERIAL_PORT (C preprocessor
// requires two levels of indirection to expand macro values properly) // requires two levels of indirection to expand macro values properly)
#define SERIAL_REGNAME(registerbase,number,suffix) _SERIAL_REGNAME(registerbase,number,suffix) #define SERIAL_REGNAME(registerbase,number,suffix) SERIAL_REGNAME_INTERNAL(registerbase,number,suffix)
#if SERIAL_PORT == 0 && (!defined(UBRR0H) || !defined(UDR0)) // use un-numbered registers if necessary #if SERIAL_PORT == 0 && (!defined(UBRR0H) || !defined(UDR0)) // use un-numbered registers if necessary
#define _SERIAL_REGNAME(registerbase,number,suffix) registerbase##suffix #define SERIAL_REGNAME_INTERNAL(registerbase,number,suffix) registerbase##suffix
#else #else
#define _SERIAL_REGNAME(registerbase,number,suffix) registerbase##number##suffix #define SERIAL_REGNAME_INTERNAL(registerbase,number,suffix) registerbase##number##suffix
#endif #endif
// Registers used by MarlinSerial class (expanded depending on selected serial port) // Registers used by MarlinSerial class (expanded depending on selected serial port)
@@ -136,6 +135,10 @@
UART_DECL(3); UART_DECL(3);
#endif #endif
#define DEC 10
#define HEX 16
#define OCT 8
#define BIN 2
#define BYTE 0 #define BYTE 0
// Templated type selector // Templated type selector
@@ -191,38 +194,66 @@
rx_framing_errors; rx_framing_errors;
static ring_buffer_pos_t rx_max_enqueued; static ring_buffer_pos_t rx_max_enqueued;
FORCE_INLINE static ring_buffer_pos_t atomic_read_rx_head(); static FORCE_INLINE ring_buffer_pos_t atomic_read_rx_head();
static volatile bool rx_tail_value_not_stable; static volatile bool rx_tail_value_not_stable;
static volatile uint16_t rx_tail_value_backup; static volatile uint16_t rx_tail_value_backup;
FORCE_INLINE static void atomic_set_rx_tail(ring_buffer_pos_t value); static FORCE_INLINE void atomic_set_rx_tail(ring_buffer_pos_t value);
FORCE_INLINE static ring_buffer_pos_t atomic_read_rx_tail(); static FORCE_INLINE ring_buffer_pos_t atomic_read_rx_tail();
public:
public:
FORCE_INLINE static void store_rxd_char(); FORCE_INLINE static void store_rxd_char();
FORCE_INLINE static void _tx_udr_empty_irq(); FORCE_INLINE static void _tx_udr_empty_irq();
public: public:
static void begin(const long); MarlinSerial() {};
static void end(); static void begin(const long);
static int peek(); static void end();
static int read(); static int peek();
static void flush(); static int read();
static ring_buffer_pos_t available(); static void flush();
static void write(const uint8_t c); static ring_buffer_pos_t available();
static void flushTX(); static void write(const uint8_t c);
#if HAS_DGUS_LCD static void flushTX();
static ring_buffer_pos_t get_tx_buffer_free(); #ifdef DGUS_SERIAL_PORT
#endif static ring_buffer_pos_t get_tx_buffer_free();
#endif
enum { HasEmergencyParser = Cfg::EMERGENCYPARSER }; FORCE_INLINE static uint8_t dropped() { return Cfg::DROPPED_RX ? rx_dropped_bytes : 0; }
static bool emergency_parser_enabled() { return Cfg::EMERGENCYPARSER; } FORCE_INLINE static uint8_t buffer_overruns() { return Cfg::RX_OVERRUNS ? rx_buffer_overruns : 0; }
FORCE_INLINE static uint8_t framing_errors() { return Cfg::RX_FRAMING_ERRORS ? rx_framing_errors : 0; }
FORCE_INLINE static ring_buffer_pos_t rxMaxEnqueued() { return Cfg::MAX_RX_QUEUED ? rx_max_enqueued : 0; }
FORCE_INLINE static uint8_t dropped() { return Cfg::DROPPED_RX ? rx_dropped_bytes : 0; } FORCE_INLINE static void write(const char* str) { while (*str) write(*str++); }
FORCE_INLINE static uint8_t buffer_overruns() { return Cfg::RX_OVERRUNS ? rx_buffer_overruns : 0; } FORCE_INLINE static void write(const uint8_t* buffer, size_t size) { while (size--) write(*buffer++); }
FORCE_INLINE static uint8_t framing_errors() { return Cfg::RX_FRAMING_ERRORS ? rx_framing_errors : 0; } FORCE_INLINE static void print(const String& s) { for (int i = 0; i < (int)s.length(); i++) write(s[i]); }
FORCE_INLINE static ring_buffer_pos_t rxMaxEnqueued() { return Cfg::MAX_RX_QUEUED ? rx_max_enqueued : 0; } FORCE_INLINE static void print(const char* str) { write(str); }
static void print(char, int = BYTE);
static void print(unsigned char, int = BYTE);
static void print(int, int = DEC);
static void print(unsigned int, int = DEC);
static void print(long, int = DEC);
static void print(unsigned long, int = DEC);
static void print(double, int = 2);
static void println(const String& s);
static void println(const char[]);
static void println(char, int = BYTE);
static void println(unsigned char, int = BYTE);
static void println(int, int = DEC);
static void println(unsigned int, int = DEC);
static void println(long, int = DEC);
static void println(unsigned long, int = DEC);
static void println(double, int = 2);
static void println();
operator bool() { return true; }
private:
static void printNumber(unsigned long, const uint8_t);
static void printFloat(double, uint8_t);
}; };
template <uint8_t serial> template <uint8_t serial>
@@ -237,61 +268,51 @@
static constexpr bool RX_FRAMING_ERRORS = ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS); static constexpr bool RX_FRAMING_ERRORS = ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS);
static constexpr bool MAX_RX_QUEUED = ENABLED(SERIAL_STATS_MAX_RX_QUEUED); static constexpr bool MAX_RX_QUEUED = ENABLED(SERIAL_STATS_MAX_RX_QUEUED);
}; };
extern MarlinSerial<MarlinSerialCfg<SERIAL_PORT>> customizedSerial1;
typedef Serial1Class< MarlinSerial< MarlinSerialCfg<SERIAL_PORT> > > MSerialT1;
extern MSerialT1 customizedSerial1;
#ifdef SERIAL_PORT_2 #ifdef SERIAL_PORT_2
typedef Serial1Class< MarlinSerial< MarlinSerialCfg<SERIAL_PORT_2> > > MSerialT2;
extern MSerialT2 customizedSerial2;
#endif
#ifdef SERIAL_PORT_3 extern MarlinSerial<MarlinSerialCfg<SERIAL_PORT_2>> customizedSerial2;
typedef Serial1Class< MarlinSerial< MarlinSerialCfg<SERIAL_PORT_3> > > MSerialT3;
extern MSerialT3 customizedSerial3;
#endif #endif
#endif // !USBCON #endif // !USBCON
#ifdef MMU2_SERIAL_PORT #ifdef INTERNAL_SERIAL_PORT
template <uint8_t serial> template <uint8_t serial>
struct MMU2SerialCfg { struct MarlinInternalSerialCfg {
static constexpr int PORT = serial; static constexpr int PORT = serial;
static constexpr unsigned int RX_SIZE = 32; static constexpr unsigned int RX_SIZE = 32;
static constexpr unsigned int TX_SIZE = 32; static constexpr unsigned int TX_SIZE = 32;
static constexpr bool XONOFF = false; static constexpr bool XONOFF = false;
static constexpr bool EMERGENCYPARSER = false; static constexpr bool EMERGENCYPARSER = false;
static constexpr bool DROPPED_RX = false; static constexpr bool DROPPED_RX = false;
static constexpr bool RX_OVERRUNS = false;
static constexpr bool RX_FRAMING_ERRORS = false; static constexpr bool RX_FRAMING_ERRORS = false;
static constexpr bool MAX_RX_QUEUED = false; static constexpr bool MAX_RX_QUEUED = false;
static constexpr bool RX_OVERRUNS = false;
}; };
typedef Serial1Class< MarlinSerial< MMU2SerialCfg<MMU2_SERIAL_PORT> > > MSerialMMU2; extern MarlinSerial<MarlinInternalSerialCfg<INTERNAL_SERIAL_PORT>> internalSerial;
extern MSerialMMU2 mmuSerial;
#endif #endif
#ifdef LCD_SERIAL_PORT #ifdef DGUS_SERIAL_PORT
template <uint8_t serial> template <uint8_t serial>
struct LCDSerialCfg { struct MarlinInternalSerialCfg {
static constexpr int PORT = serial; static constexpr int PORT = serial;
static constexpr unsigned int RX_SIZE = TERN(HAS_DGUS_LCD, DGUS_RX_BUFFER_SIZE, 64); static constexpr unsigned int RX_SIZE = 128;
static constexpr unsigned int TX_SIZE = TERN(HAS_DGUS_LCD, DGUS_TX_BUFFER_SIZE, 128); static constexpr unsigned int TX_SIZE = 48;
static constexpr bool XONOFF = false; static constexpr bool XONOFF = false;
static constexpr bool EMERGENCYPARSER = ENABLED(EMERGENCY_PARSER); static constexpr bool EMERGENCYPARSER = false;
static constexpr bool DROPPED_RX = false; static constexpr bool DROPPED_RX = false;
static constexpr bool RX_OVERRUNS = HAS_DGUS_LCD && ENABLED(DGUS_SERIAL_STATS_RX_BUFFER_OVERRUNS);
static constexpr bool RX_FRAMING_ERRORS = false; static constexpr bool RX_FRAMING_ERRORS = false;
static constexpr bool MAX_RX_QUEUED = false; static constexpr bool MAX_RX_QUEUED = false;
static constexpr bool RX_OVERRUNS = BOTH(HAS_DGUS_LCD, SERIAL_STATS_RX_BUFFER_OVERRUNS);
}; };
typedef Serial1Class< MarlinSerial< LCDSerialCfg<LCD_SERIAL_PORT> > > MSerialLCD; extern MarlinSerial<MarlinInternalSerialCfg<DGUS_SERIAL_PORT>> internalDgusSerial;
extern MSerialLCD lcdSerial;
#endif #endif
// Use the UART for Bluetooth in AT90USB configurations // Use the UART for Bluetooth in AT90USB configurations
#if defined(USBCON) && ENABLED(BLUETOOTH) #if defined(USBCON) && ENABLED(BLUETOOTH)
typedef Serial1Class<HardwareSerial> MSerialBT; extern HardwareSerial bluetoothSerial;
extern MSerialBT bluetoothSerial;
#endif #endif

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@@ -48,6 +48,7 @@
* readMicroseconds() - Get the last-written servo pulse width in microseconds. * readMicroseconds() - Get the last-written servo pulse width in microseconds.
* attached() - Return true if a servo is attached. * attached() - Return true if a servo is attached.
* detach() - Stop an attached servo from pulsing its i/o pin. * detach() - Stop an attached servo from pulsing its i/o pin.
*
*/ */
#ifdef __AVR__ #ifdef __AVR__
@@ -58,6 +59,7 @@
#include <avr/interrupt.h> #include <avr/interrupt.h>
#include "../shared/Marduino.h"
#include "../shared/servo.h" #include "../shared/servo.h"
#include "../shared/servo_private.h" #include "../shared/servo_private.h"
@@ -66,26 +68,27 @@ static volatile int8_t Channel[_Nbr_16timers]; // counter for the s
/************ static functions common to all instances ***********************/ /************ static functions common to all instances ***********************/
static inline void handle_interrupts(const timer16_Sequence_t timer, volatile uint16_t* TCNTn, volatile uint16_t* OCRnA) { static inline void handle_interrupts(timer16_Sequence_t timer, volatile uint16_t* TCNTn, volatile uint16_t* OCRnA) {
int8_t cho = Channel[timer]; // Handle the prior Channel[timer] first if (Channel[timer] < 0)
if (cho < 0) // Channel -1 indicates the refresh interval completed... *TCNTn = 0; // channel set to -1 indicated that refresh interval completed so reset the timer
*TCNTn = 0; // ...so reset the timer else {
else if (SERVO_INDEX(timer, cho) < ServoCount) // prior channel handled? if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && SERVO(timer, Channel[timer]).Pin.isActive)
extDigitalWrite(SERVO(timer, cho).Pin.nbr, LOW); // pulse the prior channel LOW extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, LOW); // pulse this channel low if activated
}
Channel[timer] = ++cho; // Handle the next channel (or 0) Channel[timer]++; // increment to the next channel
if (cho < SERVOS_PER_TIMER && SERVO_INDEX(timer, cho) < ServoCount) { if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) {
*OCRnA = *TCNTn + SERVO(timer, cho).ticks; // set compare to current ticks plus duration *OCRnA = *TCNTn + SERVO(timer, Channel[timer]).ticks;
if (SERVO(timer, cho).Pin.isActive) // activated? if (SERVO(timer, Channel[timer]).Pin.isActive) // check if activated
extDigitalWrite(SERVO(timer, cho).Pin.nbr, HIGH); // yes: pulse HIGH extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, HIGH); // it's an active channel so pulse it high
} }
else { else {
// finished all channels so wait for the refresh period to expire before starting over // finished all channels so wait for the refresh period to expire before starting over
const unsigned int cval = ((unsigned)*TCNTn) + 32 / (SERVO_TIMER_PRESCALER), // allow 32 cycles to ensure the next OCR1A not missed if (((unsigned)*TCNTn) + 4 < usToTicks(REFRESH_INTERVAL)) // allow a few ticks to ensure the next OCR1A not missed
ival = (unsigned int)usToTicks(REFRESH_INTERVAL); // at least REFRESH_INTERVAL has elapsed *OCRnA = (unsigned int)usToTicks(REFRESH_INTERVAL);
*OCRnA = max(cval, ival); else
*OCRnA = *TCNTn + 4; // at least REFRESH_INTERVAL has elapsed
Channel[timer] = -1; // reset the timer counter to 0 on the next call Channel[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel
} }
} }
@@ -122,102 +125,91 @@ static inline void handle_interrupts(const timer16_Sequence_t timer, volatile ui
/****************** end of static functions ******************************/ /****************** end of static functions ******************************/
void initISR(const timer16_Sequence_t timer_index) { void initISR(timer16_Sequence_t timer) {
switch (timer_index) { #ifdef _useTimer1
default: break; if (timer == _timer1) {
TCCR1A = 0; // normal counting mode
TCCR1B = _BV(CS11); // set prescaler of 8
TCNT1 = 0; // clear the timer count
#if defined(__AVR_ATmega8__) || defined(__AVR_ATmega128__)
SBI(TIFR, OCF1A); // clear any pending interrupts;
SBI(TIMSK, OCIE1A); // enable the output compare interrupt
#else
// here if not ATmega8 or ATmega128
SBI(TIFR1, OCF1A); // clear any pending interrupts;
SBI(TIMSK1, OCIE1A); // enable the output compare interrupt
#endif
#ifdef WIRING
timerAttach(TIMER1OUTCOMPAREA_INT, Timer1Service);
#endif
}
#endif
#ifdef _useTimer1 #ifdef _useTimer3
case _timer1: if (timer == _timer3) {
TCCR1A = 0; // normal counting mode TCCR3A = 0; // normal counting mode
TCCR1B = _BV(CS11); // set prescaler of 8 TCCR3B = _BV(CS31); // set prescaler of 8
TCNT1 = 0; // clear the timer count TCNT3 = 0; // clear the timer count
#if defined(__AVR_ATmega8__) || defined(__AVR_ATmega128__) #ifdef __AVR_ATmega128__
SBI(TIFR, OCF1A); // clear any pending interrupts; SBI(TIFR, OCF3A); // clear any pending interrupts;
SBI(TIMSK, OCIE1A); // enable the output compare interrupt SBI(ETIMSK, OCIE3A); // enable the output compare interrupt
#else #else
// here if not ATmega8 or ATmega128 SBI(TIFR3, OCF3A); // clear any pending interrupts;
SBI(TIFR1, OCF1A); // clear any pending interrupts; SBI(TIMSK3, OCIE3A); // enable the output compare interrupt
SBI(TIMSK1, OCIE1A); // enable the output compare interrupt #endif
#endif #ifdef WIRING
#ifdef WIRING timerAttach(TIMER3OUTCOMPAREA_INT, Timer3Service); // for Wiring platform only
timerAttach(TIMER1OUTCOMPAREA_INT, Timer1Service); #endif
#endif }
break; #endif
#endif
#ifdef _useTimer3 #ifdef _useTimer4
case _timer3: if (timer == _timer4) {
TCCR3A = 0; // normal counting mode TCCR4A = 0; // normal counting mode
TCCR3B = _BV(CS31); // set prescaler of 8 TCCR4B = _BV(CS41); // set prescaler of 8
TCNT3 = 0; // clear the timer count TCNT4 = 0; // clear the timer count
#ifdef __AVR_ATmega128__ TIFR4 = _BV(OCF4A); // clear any pending interrupts;
SBI(TIFR, OCF3A); // clear any pending interrupts; TIMSK4 = _BV(OCIE4A); // enable the output compare interrupt
SBI(ETIMSK, OCIE3A); // enable the output compare interrupt }
#else #endif
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 _useTimer4 #ifdef _useTimer5
case _timer4: if (timer == _timer5) {
TCCR4A = 0; // normal counting mode TCCR5A = 0; // normal counting mode
TCCR4B = _BV(CS41); // set prescaler of 8 TCCR5B = _BV(CS51); // set prescaler of 8
TCNT4 = 0; // clear the timer count TCNT5 = 0; // clear the timer count
TIFR4 = _BV(OCF4A); // clear any pending interrupts; TIFR5 = _BV(OCF5A); // clear any pending interrupts;
TIMSK4 = _BV(OCIE4A); // enable the output compare interrupt TIMSK5 = _BV(OCIE5A); // enable the output compare interrupt
break; }
#endif #endif
#ifdef _useTimer5
case _timer5:
TCCR5A = 0; // normal counting mode
TCCR5B = _BV(CS51); // set prescaler of 8
TCNT5 = 0; // clear the timer count
TIFR5 = _BV(OCF5A); // clear any pending interrupts;
TIMSK5 = _BV(OCIE5A); // enable the output compare interrupt
break;
#endif
}
} }
void finISR(const timer16_Sequence_t timer_index) { void finISR(timer16_Sequence_t timer) {
// Disable use of the given timer // Disable use of the given timer
#ifdef WIRING #ifdef WIRING
switch (timer_index) { if (timer == _timer1) {
default: break; CBI(
#if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
case _timer1: TIMSK1
CBI( #else
#if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__) TIMSK
TIMSK1 #endif
#else , OCIE1A); // disable timer 1 output compare interrupt
TIMSK timerDetach(TIMER1OUTCOMPAREA_INT);
#endif }
, OCIE1A // disable timer 1 output compare interrupt else if (timer == _timer3) {
); CBI(
timerDetach(TIMER1OUTCOMPAREA_INT); #if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
break; TIMSK3
#else
case _timer3: ETIMSK
CBI( #endif
#if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__) , OCIE3A); // disable the timer3 output compare A interrupt
TIMSK3 timerDetach(TIMER3OUTCOMPAREA_INT);
#else
ETIMSK
#endif
, OCIE3A // disable the timer3 output compare A interrupt
);
timerDetach(TIMER3OUTCOMPAREA_INT);
break;
} }
#else // !WIRING #else // !WIRING
// For arduino - in future: call here to a currently undefined function to reset the timer // For arduino - in future: call here to a currently undefined function to reset the timer
UNUSED(timer_index); UNUSED(timer);
#endif #endif
} }

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#pragma once #pragma once
@@ -59,12 +59,10 @@
// Say which 16 bit timers can be used and in what order // Say which 16 bit timers can be used and in what order
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) #if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
//#define _useTimer1 //#define _useTimer1
#define _useTimer3
#define _useTimer4 #define _useTimer4
#if NUM_SERVOS > SERVOS_PER_TIMER #if !HAS_MOTOR_CURRENT_PWM
#define _useTimer3 #define _useTimer5 // Timer 5 is used for motor current PWM and can't be used for servos.
#if !HAS_MOTOR_CURRENT_PWM && SERVOS > 2 * SERVOS_PER_TIMER
#define _useTimer5 // Timer 5 is used for motor current PWM and can't be used for servos.
#endif
#endif #endif
#elif defined(__AVR_ATmega32U4__) #elif defined(__AVR_ATmega32U4__)
#define _useTimer3 #define _useTimer3

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#ifdef __AVR__ #ifdef __AVR__
@@ -25,28 +25,19 @@
#if EITHER(EEPROM_SETTINGS, SD_FIRMWARE_UPDATE) #if EITHER(EEPROM_SETTINGS, SD_FIRMWARE_UPDATE)
/**
* PersistentStore for Arduino-style EEPROM interface
* with implementations supplied by the framework.
*/
#include "../shared/eeprom_api.h" #include "../shared/eeprom_api.h"
#ifndef MARLIN_EEPROM_SIZE bool PersistentStore::access_start() { return true; }
#define MARLIN_EEPROM_SIZE size_t(E2END + 1)
#endif
size_t PersistentStore::capacity() { return MARLIN_EEPROM_SIZE; }
bool PersistentStore::access_start() { return true; }
bool PersistentStore::access_finish() { return true; } bool PersistentStore::access_finish() { return true; }
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) { bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
uint16_t written = 0;
while (size--) { while (size--) {
uint8_t * const p = (uint8_t * const)pos; uint8_t * const p = (uint8_t * const)pos;
uint8_t v = *value; uint8_t v = *value;
if (v != eeprom_read_byte(p)) { // EEPROM has only ~100,000 write cycles, so only write bytes that have changed! // EEPROM has only ~100,000 write cycles,
// so only write bytes that have changed!
if (v != eeprom_read_byte(p)) {
eeprom_write_byte(p, v); eeprom_write_byte(p, v);
if (++written & 0x7F) delay(2); else safe_delay(2); // Avoid triggering watchdog during long EEPROM writes
if (eeprom_read_byte(p) != v) { if (eeprom_read_byte(p) != v) {
SERIAL_ECHO_MSG(STR_ERR_EEPROM_WRITE); SERIAL_ECHO_MSG(STR_ERR_EEPROM_WRITE);
return true; return true;
@@ -55,11 +46,11 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui
crc16(crc, &v, 1); crc16(crc, &v, 1);
pos++; pos++;
value++; value++;
} };
return false; return false;
} }
bool PersistentStore::read_data(int &pos, uint8_t *value, size_t size, uint16_t *crc, const bool writing/*=true*/) { bool PersistentStore::read_data(int &pos, uint8_t* value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
do { do {
uint8_t c = eeprom_read_byte((uint8_t*)pos); uint8_t c = eeprom_read_byte((uint8_t*)pos);
if (writing) *value = c; if (writing) *value = c;
@@ -70,5 +61,7 @@ bool PersistentStore::read_data(int &pos, uint8_t *value, size_t size, uint16_t
return false; // always assume success for AVR's return false; // always assume success for AVR's
} }
size_t PersistentStore::capacity() { return E2END + 1; }
#endif // EEPROM_SETTINGS || SD_FIRMWARE_UPDATE #endif // EEPROM_SETTINGS || SD_FIRMWARE_UPDATE
#endif // __AVR__ #endif // __AVR__

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#pragma once #pragma once
@@ -124,7 +124,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(X_MAX_PIN) != NOT_AN_INTERRUPT) #if (digitalPinToInterrupt(X_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(X_MAX_PIN); _ATTACH(X_MAX_PIN);
#else #else
static_assert(digitalPinHasPCICR(X_MAX_PIN), "X_MAX_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."); static_assert(digitalPinHasPCICR(X_MAX_PIN), "X_MAX_PIN is not interrupt-capable");
pciSetup(X_MAX_PIN); pciSetup(X_MAX_PIN);
#endif #endif
#endif #endif
@@ -132,7 +132,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(X_MIN_PIN) != NOT_AN_INTERRUPT) #if (digitalPinToInterrupt(X_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(X_MIN_PIN); _ATTACH(X_MIN_PIN);
#else #else
static_assert(digitalPinHasPCICR(X_MIN_PIN), "X_MIN_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."); static_assert(digitalPinHasPCICR(X_MIN_PIN), "X_MIN_PIN is not interrupt-capable");
pciSetup(X_MIN_PIN); pciSetup(X_MIN_PIN);
#endif #endif
#endif #endif
@@ -140,7 +140,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Y_MAX_PIN) != NOT_AN_INTERRUPT) #if (digitalPinToInterrupt(Y_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Y_MAX_PIN); _ATTACH(Y_MAX_PIN);
#else #else
static_assert(digitalPinHasPCICR(Y_MAX_PIN), "Y_MAX_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."); static_assert(digitalPinHasPCICR(Y_MAX_PIN), "Y_MAX_PIN is not interrupt-capable");
pciSetup(Y_MAX_PIN); pciSetup(Y_MAX_PIN);
#endif #endif
#endif #endif
@@ -148,7 +148,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Y_MIN_PIN) != NOT_AN_INTERRUPT) #if (digitalPinToInterrupt(Y_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Y_MIN_PIN); _ATTACH(Y_MIN_PIN);
#else #else
static_assert(digitalPinHasPCICR(Y_MIN_PIN), "Y_MIN_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."); static_assert(digitalPinHasPCICR(Y_MIN_PIN), "Y_MIN_PIN is not interrupt-capable");
pciSetup(Y_MIN_PIN); pciSetup(Y_MIN_PIN);
#endif #endif
#endif #endif
@@ -156,7 +156,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Z_MAX_PIN) != NOT_AN_INTERRUPT) #if (digitalPinToInterrupt(Z_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Z_MAX_PIN); _ATTACH(Z_MAX_PIN);
#else #else
static_assert(digitalPinHasPCICR(Z_MAX_PIN), "Z_MAX_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."); static_assert(digitalPinHasPCICR(Z_MAX_PIN), "Z_MAX_PIN is not interrupt-capable");
pciSetup(Z_MAX_PIN); pciSetup(Z_MAX_PIN);
#endif #endif
#endif #endif
@@ -164,60 +164,15 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Z_MIN_PIN) != NOT_AN_INTERRUPT) #if (digitalPinToInterrupt(Z_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Z_MIN_PIN); _ATTACH(Z_MIN_PIN);
#else #else
static_assert(digitalPinHasPCICR(Z_MIN_PIN), "Z_MIN_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."); static_assert(digitalPinHasPCICR(Z_MIN_PIN), "Z_MIN_PIN is not interrupt-capable");
pciSetup(Z_MIN_PIN); pciSetup(Z_MIN_PIN);
#endif #endif
#endif #endif
#if HAS_I_MAX
#if (digitalPinToInterrupt(I_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(I_MAX_PIN);
#else
static_assert(digitalPinHasPCICR(I_MAX_PIN), "I_MAX_PIN is not interrupt-capable");
pciSetup(I_MAX_PIN);
#endif
#elif HAS_I_MIN
#if (digitalPinToInterrupt(I_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(I_MIN_PIN);
#else
static_assert(digitalPinHasPCICR(I_MIN_PIN), "I_MIN_PIN is not interrupt-capable");
pciSetup(I_MIN_PIN);
#endif
#endif
#if HAS_J_MAX
#if (digitalPinToInterrupt(J_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(J_MAX_PIN);
#else
static_assert(digitalPinHasPCICR(J_MAX_PIN), "J_MAX_PIN is not interrupt-capable");
pciSetup(J_MAX_PIN);
#endif
#elif HAS_J_MIN
#if (digitalPinToInterrupt(J_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(J_MIN_PIN);
#else
static_assert(digitalPinHasPCICR(J_MIN_PIN), "J_MIN_PIN is not interrupt-capable");
pciSetup(J_MIN_PIN);
#endif
#endif
#if HAS_K_MAX
#if (digitalPinToInterrupt(K_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(K_MAX_PIN);
#else
static_assert(digitalPinHasPCICR(K_MAX_PIN), "K_MAX_PIN is not interrupt-capable");
pciSetup(K_MAX_PIN);
#endif
#elif HAS_K_MIN
#if (digitalPinToInterrupt(K_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(K_MIN_PIN);
#else
static_assert(digitalPinHasPCICR(K_MIN_PIN), "K_MIN_PIN is not interrupt-capable");
pciSetup(K_MIN_PIN);
#endif
#endif
#if HAS_X2_MAX #if HAS_X2_MAX
#if (digitalPinToInterrupt(X2_MAX_PIN) != NOT_AN_INTERRUPT) #if (digitalPinToInterrupt(X2_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(X2_MAX_PIN); _ATTACH(X2_MAX_PIN);
#else #else
static_assert(digitalPinHasPCICR(X2_MAX_PIN), "X2_MAX_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."); static_assert(digitalPinHasPCICR(X2_MAX_PIN), "X2_MAX_PIN is not interrupt-capable");
pciSetup(X2_MAX_PIN); pciSetup(X2_MAX_PIN);
#endif #endif
#endif #endif
@@ -225,7 +180,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(X2_MIN_PIN) != NOT_AN_INTERRUPT) #if (digitalPinToInterrupt(X2_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(X2_MIN_PIN); _ATTACH(X2_MIN_PIN);
#else #else
static_assert(digitalPinHasPCICR(X2_MIN_PIN), "X2_MIN_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."); static_assert(digitalPinHasPCICR(X2_MIN_PIN), "X2_MIN_PIN is not interrupt-capable");
pciSetup(X2_MIN_PIN); pciSetup(X2_MIN_PIN);
#endif #endif
#endif #endif
@@ -233,7 +188,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Y2_MAX_PIN) != NOT_AN_INTERRUPT) #if (digitalPinToInterrupt(Y2_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Y2_MAX_PIN); _ATTACH(Y2_MAX_PIN);
#else #else
static_assert(digitalPinHasPCICR(Y2_MAX_PIN), "Y2_MAX_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."); static_assert(digitalPinHasPCICR(Y2_MAX_PIN), "Y2_MAX_PIN is not interrupt-capable");
pciSetup(Y2_MAX_PIN); pciSetup(Y2_MAX_PIN);
#endif #endif
#endif #endif
@@ -241,7 +196,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Y2_MIN_PIN) != NOT_AN_INTERRUPT) #if (digitalPinToInterrupt(Y2_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Y2_MIN_PIN); _ATTACH(Y2_MIN_PIN);
#else #else
static_assert(digitalPinHasPCICR(Y2_MIN_PIN), "Y2_MIN_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."); static_assert(digitalPinHasPCICR(Y2_MIN_PIN), "Y2_MIN_PIN is not interrupt-capable");
pciSetup(Y2_MIN_PIN); pciSetup(Y2_MIN_PIN);
#endif #endif
#endif #endif
@@ -249,7 +204,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Z2_MAX_PIN) != NOT_AN_INTERRUPT) #if (digitalPinToInterrupt(Z2_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Z2_MAX_PIN); _ATTACH(Z2_MAX_PIN);
#else #else
static_assert(digitalPinHasPCICR(Z2_MAX_PIN), "Z2_MAX_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."); static_assert(digitalPinHasPCICR(Z2_MAX_PIN), "Z2_MAX_PIN is not interrupt-capable");
pciSetup(Z2_MAX_PIN); pciSetup(Z2_MAX_PIN);
#endif #endif
#endif #endif
@@ -257,7 +212,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Z2_MIN_PIN) != NOT_AN_INTERRUPT) #if (digitalPinToInterrupt(Z2_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Z2_MIN_PIN); _ATTACH(Z2_MIN_PIN);
#else #else
static_assert(digitalPinHasPCICR(Z2_MIN_PIN), "Z2_MIN_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."); static_assert(digitalPinHasPCICR(Z2_MIN_PIN), "Z2_MIN_PIN is not interrupt-capable");
pciSetup(Z2_MIN_PIN); pciSetup(Z2_MIN_PIN);
#endif #endif
#endif #endif
@@ -265,7 +220,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Z3_MAX_PIN) != NOT_AN_INTERRUPT) #if (digitalPinToInterrupt(Z3_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Z3_MAX_PIN); _ATTACH(Z3_MAX_PIN);
#else #else
static_assert(digitalPinHasPCICR(Z3_MAX_PIN), "Z3_MAX_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."); static_assert(digitalPinHasPCICR(Z3_MAX_PIN), "Z3_MAX_PIN is not interrupt-capable");
pciSetup(Z3_MAX_PIN); pciSetup(Z3_MAX_PIN);
#endif #endif
#endif #endif
@@ -273,7 +228,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Z3_MIN_PIN) != NOT_AN_INTERRUPT) #if (digitalPinToInterrupt(Z3_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Z3_MIN_PIN); _ATTACH(Z3_MIN_PIN);
#else #else
static_assert(digitalPinHasPCICR(Z3_MIN_PIN), "Z3_MIN_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."); static_assert(digitalPinHasPCICR(Z3_MIN_PIN), "Z3_MIN_PIN is not interrupt-capable");
pciSetup(Z3_MIN_PIN); pciSetup(Z3_MIN_PIN);
#endif #endif
#endif #endif
@@ -281,7 +236,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Z4_MAX_PIN) != NOT_AN_INTERRUPT) #if (digitalPinToInterrupt(Z4_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Z4_MAX_PIN); _ATTACH(Z4_MAX_PIN);
#else #else
static_assert(digitalPinHasPCICR(Z4_MAX_PIN), "Z4_MAX_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."); static_assert(digitalPinHasPCICR(Z4_MAX_PIN), "Z4_MAX_PIN is not interrupt-capable");
pciSetup(Z4_MAX_PIN); pciSetup(Z4_MAX_PIN);
#endif #endif
#endif #endif
@@ -289,7 +244,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Z4_MIN_PIN) != NOT_AN_INTERRUPT) #if (digitalPinToInterrupt(Z4_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Z4_MIN_PIN); _ATTACH(Z4_MIN_PIN);
#else #else
static_assert(digitalPinHasPCICR(Z4_MIN_PIN), "Z4_MIN_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."); static_assert(digitalPinHasPCICR(Z4_MIN_PIN), "Z4_MIN_PIN is not interrupt-capable");
pciSetup(Z4_MIN_PIN); pciSetup(Z4_MIN_PIN);
#endif #endif
#endif #endif
@@ -297,7 +252,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Z_MIN_PROBE_PIN) != NOT_AN_INTERRUPT) #if (digitalPinToInterrupt(Z_MIN_PROBE_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Z_MIN_PROBE_PIN); _ATTACH(Z_MIN_PROBE_PIN);
#else #else
static_assert(digitalPinHasPCICR(Z_MIN_PROBE_PIN), "Z_MIN_PROBE_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."); static_assert(digitalPinHasPCICR(Z_MIN_PROBE_PIN), "Z_MIN_PROBE_PIN is not interrupt-capable");
pciSetup(Z_MIN_PROBE_PIN); pciSetup(Z_MIN_PROBE_PIN);
#endif #endif
#endif #endif

View File

@@ -16,12 +16,16 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#ifdef __AVR__ #ifdef __AVR__
#include "../../inc/MarlinConfig.h" #include "../../inc/MarlinConfigPre.h"
#if ENABLED(FAST_PWM_FAN) || SPINDLE_LASER_PWM
#include "HAL.h"
struct Timer { struct Timer {
volatile uint8_t* TCCRnQ[3]; // max 3 TCCR registers per timer volatile uint8_t* TCCRnQ[3]; // max 3 TCCR registers per timer
@@ -29,194 +33,250 @@ struct Timer {
volatile uint16_t* ICRn; // max 1 ICR register per timer volatile uint16_t* ICRn; // max 1 ICR register per timer
uint8_t n; // the timer number [0->5] uint8_t n; // the timer number [0->5]
uint8_t q; // the timer output [0->2] (A->C) uint8_t q; // the timer output [0->2] (A->C)
bool isPWM; // True if pin is a "hardware timer"
bool isProtected; // True if timer is protected
}; };
// Macros for the Timer structure
#define _SET_WGMnQ(T, V) do{ \
*(T.TCCRnQ)[0] = (*(T.TCCRnQ)[0] & ~(0x3 << 0)) | (( int(V) & 0x3) << 0); \
*(T.TCCRnQ)[1] = (*(T.TCCRnQ)[1] & ~(0x3 << 3)) | (((int(V) >> 2) & 0x3) << 3); \
}while(0)
// Set TCCR CS bits
#define _SET_CSn(T, V) (*(T.TCCRnQ)[1] = (*(T.TCCRnQ[1]) & ~(0x7 << 0)) | ((int(V) & 0x7) << 0))
// Set TCCR COM bits
#define _SET_COMnQ(T, Q, V) (*(T.TCCRnQ)[0] = (*(T.TCCRnQ)[0] & ~(0x3 << (6-2*(Q)))) | (int(V) << (6-2*(Q))))
// Set OCRnQ register
#define _SET_OCRnQ(T, Q, V) (*(T.OCRnQ)[Q] = int(V) & 0xFFFF)
// Set ICRn register (one per timer)
#define _SET_ICRn(T, V) (*(T.ICRn) = int(V) & 0xFFFF)
/** /**
* Return a Timer struct describing a pin's timer. * get_pwm_timer
* Get the timer information and register of the provided pin.
* Return a Timer struct containing this information.
* Used by set_pwm_frequency, set_pwm_duty
*/ */
const Timer get_pwm_timer(const pin_t pin) { Timer get_pwm_timer(const pin_t pin) {
uint8_t q = 0; uint8_t q = 0;
switch (digitalPinToTimer(pin)) { switch (digitalPinToTimer(pin)) {
// Protect reserved timers (TIMER0 & TIMER1)
#ifdef TCCR0A #ifdef TCCR0A
IF_DISABLED(AVR_AT90USB1286_FAMILY, case TIMER0A:) #if !AVR_AT90USB1286_FAMILY
case TIMER0A:
#endif
case TIMER0B:
#endif #endif
#ifdef TCCR1A #ifdef TCCR1A
case TIMER1A: case TIMER1B: case TIMER1A: case TIMER1B:
#endif #endif
break;
break; // Protect reserved timers (TIMER0 & TIMER1) #if defined(TCCR2) || defined(TCCR2A)
#ifdef TCCR2
#ifdef TCCR0A case TIMER2: {
case TIMER0B: // Protected timer, but allow setting the duty cycle on OCR0B for pin D4 only Timer timer = {
return Timer({ { &TCCR0A, nullptr, nullptr }, { (uint16_t*)&OCR0A, (uint16_t*)&OCR0B, nullptr }, nullptr, 0, 1, true, true }); /*TCCRnQ*/ { &TCCR2, nullptr, nullptr },
/*OCRnQ*/ { (uint16_t*)&OCR2, nullptr, nullptr },
/*ICRn*/ nullptr,
/*n, q*/ 2, 0
};
}
#elif defined(TCCR2A)
#if ENABLED(USE_OCR2A_AS_TOP)
case TIMER2A: break; // protect TIMER2A
case TIMER2B: {
Timer timer = {
/*TCCRnQ*/ { &TCCR2A, &TCCR2B, nullptr },
/*OCRnQ*/ { (uint16_t*)&OCR2A, (uint16_t*)&OCR2B, nullptr },
/*ICRn*/ nullptr,
/*n, q*/ 2, 1
};
return timer;
}
#else
case TIMER2B: ++q;
case TIMER2A: {
Timer timer = {
/*TCCRnQ*/ { &TCCR2A, &TCCR2B, nullptr },
/*OCRnQ*/ { (uint16_t*)&OCR2A, (uint16_t*)&OCR2B, nullptr },
/*ICRn*/ nullptr,
2, q
};
return timer;
}
#endif
#endif
#endif #endif
#if HAS_TCCR2
case TIMER2:
return Timer({ { &TCCR2, nullptr, nullptr }, { (uint16_t*)&OCR2, nullptr, nullptr }, nullptr, 2, 0, true, false });
#elif ENABLED(USE_OCR2A_AS_TOP)
case TIMER2A: break; // Protect TIMER2A since its OCR is used by TIMER2B
case TIMER2B:
return Timer({ { &TCCR2A, &TCCR2B, nullptr }, { (uint16_t*)&OCR2A, (uint16_t*)&OCR2B, nullptr }, nullptr, 2, 1, true, false });
#elif defined(TCCR2A)
case TIMER2B: ++q; case TIMER2A:
return Timer({ { &TCCR2A, &TCCR2B, nullptr }, { (uint16_t*)&OCR2A, (uint16_t*)&OCR2B, nullptr }, nullptr, 2, q, true, false });
#endif
#ifdef OCR3C #ifdef OCR3C
case TIMER3C: ++q; case TIMER3B: ++q; case TIMER3A: case TIMER3C: ++q;
return Timer({ { &TCCR3A, &TCCR3B, &TCCR3C }, { &OCR3A, &OCR3B, &OCR3C }, &ICR3, 3, q, true, false }); case TIMER3B: ++q;
case TIMER3A: {
Timer timer = {
/*TCCRnQ*/ { &TCCR3A, &TCCR3B, &TCCR3C },
/*OCRnQ*/ { &OCR3A, &OCR3B, &OCR3C },
/*ICRn*/ &ICR3,
/*n, q*/ 3, q
};
return timer;
}
#elif defined(OCR3B) #elif defined(OCR3B)
case TIMER3B: ++q; case TIMER3A: case TIMER3B: ++q;
return Timer({ { &TCCR3A, &TCCR3B, nullptr }, { &OCR3A, &OCR3B, nullptr }, &ICR3, 3, q, true, false }); case TIMER3A: {
Timer timer = {
/*TCCRnQ*/ { &TCCR3A, &TCCR3B, nullptr },
/*OCRnQ*/ { &OCR3A, &OCR3B, nullptr },
/*ICRn*/ &ICR3,
/*n, q*/ 3, q
};
return timer;
}
#endif #endif
#ifdef TCCR4A #ifdef TCCR4A
case TIMER4C: ++q; case TIMER4B: ++q; case TIMER4A: case TIMER4C: ++q;
return Timer({ { &TCCR4A, &TCCR4B, &TCCR4C }, { &OCR4A, &OCR4B, &OCR4C }, &ICR4, 4, q, true, false }); case TIMER4B: ++q;
case TIMER4A: {
Timer timer = {
/*TCCRnQ*/ { &TCCR4A, &TCCR4B, &TCCR4C },
/*OCRnQ*/ { &OCR4A, &OCR4B, &OCR4C },
/*ICRn*/ &ICR4,
/*n, q*/ 4, q
};
return timer;
}
#endif #endif
#ifdef TCCR5A #ifdef TCCR5A
case TIMER5C: ++q; case TIMER5B: ++q; case TIMER5A: case TIMER5C: ++q;
return Timer({ { &TCCR5A, &TCCR5B, &TCCR5C }, { &OCR5A, &OCR5B, &OCR5C }, &ICR5, 5, q, true, false }); case TIMER5B: ++q;
case TIMER5A: {
Timer timer = {
/*TCCRnQ*/ { &TCCR5A, &TCCR5B, &TCCR5C },
/*OCRnQ*/ { &OCR5A, &OCR5B, &OCR5C },
/*ICRn*/ &ICR5,
/*n, q*/ 5, q
};
return timer;
}
#endif #endif
} }
Timer timer = {
return Timer(); /*TCCRnQ*/ { nullptr, nullptr, nullptr },
/*OCRnQ*/ { nullptr, nullptr, nullptr },
/*ICRn*/ nullptr,
0, 0
};
return timer;
} }
void MarlinHAL::set_pwm_frequency(const pin_t pin, const uint16_t f_desired) { void set_pwm_frequency(const pin_t pin, int f_desired) {
const Timer timer = get_pwm_timer(pin); Timer timer = get_pwm_timer(pin);
if (timer.isProtected || !timer.isPWM) return; // Don't proceed if protected timer or not recognized if (timer.n == 0) return; // Don't proceed if protected timer or not recognised
uint16_t size;
if (timer.n == 2) size = 255; else size = 65535;
const bool is_timer2 = timer.n == 2; uint16_t res = 255; // resolution (TOP value)
const uint16_t maxtop = is_timer2 ? 0xFF : 0xFFFF; uint8_t j = 0; // prescaler index
uint8_t wgm = 1; // waveform generation mode
uint16_t res = 0xFF; // resolution (TOP value)
uint8_t j = CS_NONE; // prescaler index
uint8_t wgm = WGM_PWM_PC_8; // waveform generation mode
// Calculating the prescaler and resolution to use to achieve closest frequency // Calculating the prescaler and resolution to use to achieve closest frequency
if (f_desired != 0) { if (f_desired != 0) {
constexpr uint16_t prescaler[] = { 1, 8, (32), 64, (128), 256, 1024 }; // (*) are Timer 2 only int f = (F_CPU) / (2 * 1024 * size) + 1; // Initialize frequency as lowest (non-zero) achievable
uint16_t f = (F_CPU) / (2 * 1024 * maxtop) + 1; // Start with the lowest non-zero frequency achievable (1 or 31) uint16_t prescaler[] = { 0, 1, 8, /*TIMER2 ONLY*/32, 64, /*TIMER2 ONLY*/128, 256, 1024 };
LOOP_L_N(i, COUNT(prescaler)) { // Loop through all prescaler values // loop over prescaler values
const uint16_t p = prescaler[i]; LOOP_S_L_N(i, 1, 8) {
uint16_t res_fast_temp, res_pc_temp; uint16_t res_temp_fast = 255, res_temp_phase_correct = 255;
if (is_timer2) { if (timer.n == 2) {
#if ENABLED(USE_OCR2A_AS_TOP) // No resolution calculation for TIMER2 unless enabled USE_OCR2A_AS_TOP // No resolution calculation for TIMER2 unless enabled USE_OCR2A_AS_TOP
const uint16_t rft = (F_CPU) / (p * f_desired); #if ENABLED(USE_OCR2A_AS_TOP)
res_fast_temp = rft - 1; const uint16_t rtf = (F_CPU) / (prescaler[i] * f_desired);
res_pc_temp = rft / 2; res_temp_fast = rtf - 1;
#else res_temp_phase_correct = rtf / 2;
res_fast_temp = res_pc_temp = maxtop;
#endif #endif
} }
else { else {
if (p == 32 || p == 128) continue; // Skip TIMER2 specific prescalers when not TIMER2 // Skip TIMER2 specific prescalers when not TIMER2
const uint16_t rft = (F_CPU) / (p * f_desired); if (i == 3 || i == 5) continue;
res_fast_temp = rft - 1; const uint16_t rtf = (F_CPU) / (prescaler[i] * f_desired);
res_pc_temp = rft / 2; res_temp_fast = rtf - 1;
res_temp_phase_correct = rtf / 2;
} }
LIMIT(res_fast_temp, 1U, maxtop); LIMIT(res_temp_fast, 1u, size);
LIMIT(res_pc_temp, 1U, maxtop); LIMIT(res_temp_phase_correct, 1u, size);
// Calculate frequencies of test prescaler and resolution values // Calculate frequencies of test prescaler and resolution values
const uint32_t f_diff = _MAX(f, f_desired) - _MIN(f, f_desired), const int f_temp_fast = (F_CPU) / (prescaler[i] * (1 + res_temp_fast)),
f_fast_temp = (F_CPU) / (p * (1 + res_fast_temp)), f_temp_phase_correct = (F_CPU) / (2 * prescaler[i] * res_temp_phase_correct),
f_fast_diff = _MAX(f_fast_temp, f_desired) - _MIN(f_fast_temp, f_desired), f_diff = ABS(f - f_desired),
f_pc_temp = (F_CPU) / (2 * p * res_pc_temp), f_fast_diff = ABS(f_temp_fast - f_desired),
f_pc_diff = _MAX(f_pc_temp, f_desired) - _MIN(f_pc_temp, f_desired); f_phase_diff = ABS(f_temp_phase_correct - f_desired);
if (f_fast_diff < f_diff && f_fast_diff <= f_pc_diff) { // FAST values are closest to desired f // If FAST values are closest to desired f
// Set the Wave Generation Mode to FAST PWM if (f_fast_diff < f_diff && f_fast_diff <= f_phase_diff) {
wgm = is_timer2 ? uint8_t(TERN(USE_OCR2A_AS_TOP, WGM2_FAST_PWM_OCR2A, WGM2_FAST_PWM)) : uint8_t(WGM_FAST_PWM_ICRn);
// Remember this combination // Remember this combination
f = f_fast_temp; res = res_fast_temp; j = i + 1; f = f_temp_fast;
res = res_temp_fast;
j = i;
// Set the Wave Generation Mode to FAST PWM
if (timer.n == 2) {
wgm = (
#if ENABLED(USE_OCR2A_AS_TOP)
WGM2_FAST_PWM_OCR2A
#else
WGM2_FAST_PWM
#endif
);
}
else wgm = WGM_FAST_PWM_ICRn;
} }
else if (f_pc_diff < f_diff) { // PHASE CORRECT values are closes to desired f // If PHASE CORRECT values are closes to desired f
else if (f_phase_diff < f_diff) {
f = f_temp_phase_correct;
res = res_temp_phase_correct;
j = i;
// Set the Wave Generation Mode to PWM PHASE CORRECT // Set the Wave Generation Mode to PWM PHASE CORRECT
wgm = is_timer2 ? uint8_t(TERN(USE_OCR2A_AS_TOP, WGM2_PWM_PC_OCR2A, WGM2_PWM_PC)) : uint8_t(WGM_PWM_PC_ICRn); if (timer.n == 2) {
f = f_pc_temp; res = res_pc_temp; j = i + 1; wgm = (
#if ENABLED(USE_OCR2A_AS_TOP)
WGM2_PWM_PC_OCR2A
#else
WGM2_PWM_PC
#endif
);
}
else wgm = WGM_PWM_PC_ICRn;
} }
} }
} }
_SET_WGMnQ(timer.TCCRnQ, wgm);
_SET_CSn(timer.TCCRnQ, j);
_SET_WGMnQ(timer, wgm); if (timer.n == 2) {
_SET_CSn(timer, j); #if ENABLED(USE_OCR2A_AS_TOP)
_SET_OCRnQ(timer.OCRnQ, 0, res); // Set OCR2A value (TOP) = res
if (is_timer2) { #endif
TERN_(USE_OCR2A_AS_TOP, _SET_OCRnQ(timer, 0, res)); // Set OCR2A value (TOP) = res
} }
else else
_SET_ICRn(timer, res); // Set ICRn value (TOP) = res _SET_ICRn(timer.ICRn, res); // Set ICRn value (TOP) = res
} }
void MarlinHAL::set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) { void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) {
// If v is 0 or v_size (max), digitalWrite to LOW or HIGH. // If v is 0 or v_size (max), digitalWrite to LOW or HIGH.
// Note that digitalWrite also disables PWM output for us (sets COM bit to 0) // Note that digitalWrite also disables pwm output for us (sets COM bit to 0)
if (v == 0) if (v == 0)
digitalWrite(pin, invert); digitalWrite(pin, invert);
else if (v == v_size) else if (v == v_size)
digitalWrite(pin, !invert); digitalWrite(pin, !invert);
else { else {
const Timer timer = get_pwm_timer(pin); Timer timer = get_pwm_timer(pin);
if (timer.isPWM) { if (timer.n == 0) return; // Don't proceed if protected timer or not recognised
if (timer.n == 0) { // Set compare output mode to CLEAR -> SET or SET -> CLEAR (if inverted)
_SET_COMnQ(timer, timer.q, COM_CLEAR_SET); // Only allow a TIMER0B select... _SET_COMnQ(timer.TCCRnQ, (timer.q
_SET_OCRnQ(timer, timer.q, v); // ...and OCR0B duty update. For output pin D4 no frequency changes are permitted. #ifdef TCCR2
} + (timer.q == 2) // COM20 is on bit 4 of TCCR2, thus requires q + 1 in the macro
else if (!timer.isProtected) { #endif
const uint16_t top = timer.n == 2 ? TERN(USE_OCR2A_AS_TOP, *timer.OCRnQ[0], 255) : *timer.ICRn; ), COM_CLEAR_SET + invert
_SET_COMnQ(timer, SUM_TERN(HAS_TCCR2, timer.q, timer.q == 2), COM_CLEAR_SET + invert); // COM20 is on bit 4 of TCCR2, so +1 for q==2 );
_SET_OCRnQ(timer, timer.q, uint16_t(uint32_t(v) * top / v_size)); // Scale 8/16-bit v to top value
} uint16_t top;
if (timer.n == 2) { // if TIMER2
top = (
#if ENABLED(USE_OCR2A_AS_TOP)
*timer.OCRnQ[0] // top = OCR2A
#else
255 // top = 0xFF (max)
#endif
);
} }
else else
digitalWrite(pin, v < v_size / 2 ? LOW : HIGH); top = *timer.ICRn; // top = ICRn
_SET_OCRnQ(timer.OCRnQ, timer.q, v * float(top / v_size)); // Scale 8/16-bit v to top value
} }
} }
void MarlinHAL::init_pwm_timers() { #endif // FAST_PWM_FAN || SPINDLE_LASER_PWM
// Init some timer frequencies to a default 1KHz
const pin_t pwm_pin[] = {
#ifdef __AVR_ATmega2560__
10, 5, 6, 46
#elif defined(__AVR_ATmega1280__)
12, 31
#elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega1284__)
15, 6
#elif defined(__AVR_AT90USB1286__) || defined(__AVR_mega64) || defined(__AVR_mega128)
16, 24
#endif
};
LOOP_L_N(i, COUNT(pwm_pin))
set_pwm_frequency(pwm_pin[i], 1000);
}
#endif // __AVR__ #endif // __AVR__

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@@ -234,55 +234,5 @@ uint8_t extDigitalRead(const int8_t pin) {
} }
} }
#if 0
/**
* Set Timer 5 PWM frequency in Hz, from 3.8Hz up to ~16MHz
* with a minimum resolution of 100 steps.
*
* DC values -1.0 to 1.0. Negative duty cycle inverts the pulse.
*/
uint16_t set_pwm_frequency_hz(const_float_t hz, const float dca, const float dcb, const float dcc) {
float count = 0;
if (hz > 0 && (dca || dcb || dcc)) {
count = float(F_CPU) / hz; // 1x prescaler, TOP for 16MHz base freq.
uint16_t prescaler; // Range of 30.5Hz (65535) 64.5kHz (>31)
if (count >= 255. * 256.) { prescaler = 1024; SET_CS(5, PRESCALER_1024); }
else if (count >= 255. * 64.) { prescaler = 256; SET_CS(5, PRESCALER_256); }
else if (count >= 255. * 8.) { prescaler = 64; SET_CS(5, PRESCALER_64); }
else if (count >= 255.) { prescaler = 8; SET_CS(5, PRESCALER_8); }
else { prescaler = 1; SET_CS(5, PRESCALER_1); }
count /= float(prescaler);
const float pwm_top = round(count); // Get the rounded count
ICR5 = (uint16_t)pwm_top - 1; // Subtract 1 for TOP
OCR5A = pwm_top * ABS(dca); // Update and scale DCs
OCR5B = pwm_top * ABS(dcb);
OCR5C = pwm_top * ABS(dcc);
_SET_COM(5, A, dca ? (dca < 0 ? COM_SET_CLEAR : COM_CLEAR_SET) : COM_NORMAL); // Set compare modes
_SET_COM(5, B, dcb ? (dcb < 0 ? COM_SET_CLEAR : COM_CLEAR_SET) : COM_NORMAL);
_SET_COM(5, C, dcc ? (dcc < 0 ? COM_SET_CLEAR : COM_CLEAR_SET) : COM_NORMAL);
SET_WGM(5, FAST_PWM_ICRn); // Fast PWM with ICR5 as TOP
//SERIAL_ECHOLNPGM("Timer 5 Settings:");
//SERIAL_ECHOLNPGM(" Prescaler=", prescaler);
//SERIAL_ECHOLNPGM(" TOP=", ICR5);
//SERIAL_ECHOLNPGM(" OCR5A=", OCR5A);
//SERIAL_ECHOLNPGM(" OCR5B=", OCR5B);
//SERIAL_ECHOLNPGM(" OCR5C=", OCR5C);
}
else {
// Restore the default for Timer 5
SET_WGM(5, PWM_PC_8); // PWM 8-bit (Phase Correct)
SET_COMS(5, NORMAL, NORMAL, NORMAL); // Do nothing
SET_CS(5, PRESCALER_64); // 16MHz / 64 = 250kHz
OCR5A = OCR5B = OCR5C = 0;
}
return round(count);
}
#endif
#endif // FASTIO_EXT_START #endif // FASTIO_EXT_START
#endif // __AVR__ #endif // __AVR__

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#pragma once #pragma once
@@ -29,17 +29,11 @@
#include <avr/io.h> #include <avr/io.h>
#if defined(__AVR_AT90USB1287__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1286P__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB646P__) || defined(__AVR_AT90USB647__) #define AVR_AT90USB1286_FAMILY (defined(__AVR_AT90USB1287__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1286P__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB646P__) || defined(__AVR_AT90USB647__))
#define AVR_AT90USB1286_FAMILY 1 #define AVR_ATmega1284_FAMILY (defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) || defined(__AVR_ATmega1284P__))
#elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) || defined(__AVR_ATmega1284P__) #define AVR_ATmega2560_FAMILY (defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__))
#define AVR_ATmega1284_FAMILY 1 #define AVR_ATmega2561_FAMILY (defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__))
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) #define AVR_ATmega328_FAMILY (defined(__AVR_ATmega168__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__))
#define AVR_ATmega2560_FAMILY 1
#elif defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
#define AVR_ATmega2561_FAMILY 1
#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__)
#define AVR_ATmega328_FAMILY 1
#endif
/** /**
* Include Ports and Functions * Include Ports and Functions
@@ -63,7 +57,7 @@
* *
* Now you can simply SET_OUTPUT(PIN); WRITE(PIN, HIGH); WRITE(PIN, LOW); * Now you can simply SET_OUTPUT(PIN); WRITE(PIN, HIGH); WRITE(PIN, LOW);
* *
* Why double up on these macros? see https://gcc.gnu.org/onlinedocs/cpp/Stringification.html * Why double up on these macros? see http://gcc.gnu.org/onlinedocs/cpp/Stringification.html
*/ */
#define _READ(IO) TEST(DIO ## IO ## _RPORT, DIO ## IO ## _PIN) #define _READ(IO) TEST(DIO ## IO ## _RPORT, DIO ## IO ## _PIN)
@@ -118,7 +112,7 @@
*/ */
// Waveform Generation Modes // Waveform Generation Modes
enum WaveGenMode : uint8_t { enum WaveGenMode : char {
WGM_NORMAL, // 0 WGM_NORMAL, // 0
WGM_PWM_PC_8, // 1 WGM_PWM_PC_8, // 1
WGM_PWM_PC_9, // 2 WGM_PWM_PC_9, // 2
@@ -138,19 +132,19 @@ enum WaveGenMode : uint8_t {
}; };
// Wavefore Generation Modes (Timer 2 only) // Wavefore Generation Modes (Timer 2 only)
enum WaveGenMode2 : uint8_t { enum WaveGenMode2 : char {
WGM2_NORMAL, // 0 WGM2_NORMAL, // 0
WGM2_PWM_PC, // 1 WGM2_PWM_PC, // 1
WGM2_CTC_OCR2A, // 2 WGM2_CTC_OCR2A, // 2
WGM2_FAST_PWM, // 3 WGM2_FAST_PWM, // 3
WGM2_reserved_1, // 4 WGM2_reserved_1, // 4
WGM2_PWM_PC_OCR2A, // 5 WGM2_PWM_PC_OCR2A, // 5
WGM2_reserved_2, // 6 WGM2_reserved_2, // 6
WGM2_FAST_PWM_OCR2A, // 7 WGM2_FAST_PWM_OCR2A, // 7
}; };
// Compare Modes // Compare Modes
enum CompareMode : uint8_t { enum CompareMode : char {
COM_NORMAL, // 0 COM_NORMAL, // 0
COM_TOGGLE, // 1 Non-PWM: OCnx ... Both PWM (WGM 9,11,14,15): OCnA only ... else NORMAL COM_TOGGLE, // 1 Non-PWM: OCnx ... Both PWM (WGM 9,11,14,15): OCnA only ... else NORMAL
COM_CLEAR_SET, // 2 Non-PWM: OCnx ... Fast PWM: OCnx/Bottom ... PF-FC: OCnx Up/Down COM_CLEAR_SET, // 2 Non-PWM: OCnx ... Fast PWM: OCnx/Bottom ... PF-FC: OCnx Up/Down
@@ -158,7 +152,7 @@ enum CompareMode : uint8_t {
}; };
// Clock Sources // Clock Sources
enum ClockSource : uint8_t { enum ClockSource : char {
CS_NONE, // 0 CS_NONE, // 0
CS_PRESCALER_1, // 1 CS_PRESCALER_1, // 1
CS_PRESCALER_8, // 2 CS_PRESCALER_8, // 2
@@ -170,7 +164,7 @@ enum ClockSource : uint8_t {
}; };
// Clock Sources (Timer 2 only) // Clock Sources (Timer 2 only)
enum ClockSource2 : uint8_t { enum ClockSource2 : char {
CS2_NONE, // 0 CS2_NONE, // 0
CS2_PRESCALER_1, // 1 CS2_PRESCALER_1, // 1
CS2_PRESCALER_8, // 2 CS2_PRESCALER_8, // 2
@@ -203,33 +197,40 @@ enum ClockSource2 : uint8_t {
TCCR##T##B = (TCCR##T##B & ~(0x3 << WGM##T##2)) | (((int(V) >> 2) & 0x3) << WGM##T##2); \ TCCR##T##B = (TCCR##T##B & ~(0x3 << WGM##T##2)) | (((int(V) >> 2) & 0x3) << WGM##T##2); \
}while(0) }while(0)
#define SET_WGM(T,V) _SET_WGM(T,WGM_##V) #define SET_WGM(T,V) _SET_WGM(T,WGM_##V)
// Runtime (see set_pwm_frequency):
#define _SET_WGMnQ(TCCRnQ, V) do{ \
*(TCCRnQ)[0] = (*(TCCRnQ)[0] & ~(0x3 << 0)) | (( int(V) & 0x3) << 0); \
*(TCCRnQ)[1] = (*(TCCRnQ)[1] & ~(0x3 << 3)) | (((int(V) >> 2) & 0x3) << 3); \
}while(0)
// Set Clock Select bits // Set Clock Select bits
// Ex: SET_CS3(PRESCALER_64); // Ex: SET_CS3(PRESCALER_64);
#ifdef TCCR2
#define HAS_TCCR2 1
#endif
#define _SET_CS(T,V) (TCCR##T##B = (TCCR##T##B & ~(0x7 << CS##T##0)) | ((int(V) & 0x7) << CS##T##0)) #define _SET_CS(T,V) (TCCR##T##B = (TCCR##T##B & ~(0x7 << CS##T##0)) | ((int(V) & 0x7) << CS##T##0))
#define _SET_CS0(V) _SET_CS(0,V) #define _SET_CS0(V) _SET_CS(0,V)
#define _SET_CS1(V) _SET_CS(1,V) #define _SET_CS1(V) _SET_CS(1,V)
#ifdef TCCR2
#define _SET_CS2(V) (TCCR2 = (TCCR2 & ~(0x7 << CS20)) | (int(V) << CS20))
#else
#define _SET_CS2(V) _SET_CS(2,V)
#endif
#define _SET_CS3(V) _SET_CS(3,V) #define _SET_CS3(V) _SET_CS(3,V)
#define _SET_CS4(V) _SET_CS(4,V) #define _SET_CS4(V) _SET_CS(4,V)
#define _SET_CS5(V) _SET_CS(5,V) #define _SET_CS5(V) _SET_CS(5,V)
#define SET_CS0(V) _SET_CS0(CS_##V) #define SET_CS0(V) _SET_CS0(CS_##V)
#define SET_CS1(V) _SET_CS1(CS_##V) #define SET_CS1(V) _SET_CS1(CS_##V)
#ifdef TCCR2
#if HAS_TCCR2
#define _SET_CS2(V) (TCCR2 = (TCCR2 & ~(0x7 << CS20)) | (int(V) << CS20))
#define SET_CS2(V) _SET_CS2(CS2_##V) #define SET_CS2(V) _SET_CS2(CS2_##V)
#else #else
#define _SET_CS2(V) _SET_CS(2,V)
#define SET_CS2(V) _SET_CS2(CS_##V) #define SET_CS2(V) _SET_CS2(CS_##V)
#endif #endif
#define SET_CS3(V) _SET_CS3(CS_##V) #define SET_CS3(V) _SET_CS3(CS_##V)
#define SET_CS4(V) _SET_CS4(CS_##V) #define SET_CS4(V) _SET_CS4(CS_##V)
#define SET_CS5(V) _SET_CS5(CS_##V) #define SET_CS5(V) _SET_CS5(CS_##V)
#define SET_CS(T,V) SET_CS##T(V) #define SET_CS(T,V) SET_CS##T(V)
// Runtime (see set_pwm_frequency)
#define _SET_CSn(TCCRnQ, V) do{ \
(*(TCCRnQ)[1] = (*(TCCRnQ[1]) & ~(0x7 << 0)) | ((int(V) & 0x7) << 0)); \
}while(0)
// Set Compare Mode bits // Set Compare Mode bits
// Ex: SET_COMS(4,CLEAR_SET,CLEAR_SET,CLEAR_SET); // Ex: SET_COMS(4,CLEAR_SET,CLEAR_SET,CLEAR_SET);
@@ -239,6 +240,22 @@ enum ClockSource2 : uint8_t {
#define SET_COMB(T,V) SET_COM(T,B,V) #define SET_COMB(T,V) SET_COM(T,B,V)
#define SET_COMC(T,V) SET_COM(T,C,V) #define SET_COMC(T,V) SET_COM(T,C,V)
#define SET_COMS(T,V1,V2,V3) do{ SET_COMA(T,V1); SET_COMB(T,V2); SET_COMC(T,V3); }while(0) #define SET_COMS(T,V1,V2,V3) do{ SET_COMA(T,V1); SET_COMB(T,V2); SET_COMC(T,V3); }while(0)
// Runtime (see set_pwm_duty)
#define _SET_COMnQ(TCCRnQ, Q, V) do{ \
(*(TCCRnQ)[0] = (*(TCCRnQ)[0] & ~(0x3 << (6-2*(Q)))) | (int(V) << (6-2*(Q)))); \
}while(0)
// Set OCRnQ register
// Runtime (see set_pwm_duty):
#define _SET_OCRnQ(OCRnQ, Q, V) do{ \
(*(OCRnQ)[(Q)] = (0x0000) | (int(V) & 0xFFFF)); \
}while(0)
// Set ICRn register (one per timer)
// Runtime (see set_pwm_frequency)
#define _SET_ICRn(ICRn, V) do{ \
(*(ICRn) = (0x0000) | (int(V) & 0xFFFF)); \
}while(0)
// Set Noise Canceler bit // Set Noise Canceler bit
// Ex: SET_ICNC(2,1) // Ex: SET_ICNC(2,1)
@@ -261,8 +278,8 @@ enum ClockSource2 : uint8_t {
* PWM availability macros * PWM availability macros
*/ */
// Determine which hardware PWMs are already in use // Determine which harware PWMs are already in use
#define _PWM_CHK_FAN_B(P) (P == E0_AUTO_FAN_PIN || P == E1_AUTO_FAN_PIN || P == E2_AUTO_FAN_PIN || P == E3_AUTO_FAN_PIN || P == E4_AUTO_FAN_PIN || P == E5_AUTO_FAN_PIN || P == E6_AUTO_FAN_PIN || P == E7_AUTO_FAN_PIN || P == CHAMBER_AUTO_FAN_PIN || P == COOLER_AUTO_FAN_PIN) #define _PWM_CHK_FAN_B(P) (P == E0_AUTO_FAN_PIN || P == E1_AUTO_FAN_PIN || P == E2_AUTO_FAN_PIN || P == E3_AUTO_FAN_PIN || P == E4_AUTO_FAN_PIN || P == E5_AUTO_FAN_PIN || P == E6_AUTO_FAN_PIN || P == E7_AUTO_FAN_PIN || P == CHAMBER_AUTO_FAN_PIN)
#if PIN_EXISTS(CONTROLLER_FAN) #if PIN_EXISTS(CONTROLLER_FAN)
#define PWM_CHK_FAN_B(P) (_PWM_CHK_FAN_B(P) || P == CONTROLLER_FAN_PIN) #define PWM_CHK_FAN_B(P) (_PWM_CHK_FAN_B(P) || P == CONTROLLER_FAN_PIN)
#else #else

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#pragma once #pragma once

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#pragma once #pragma once

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#pragma once #pragma once

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#pragma once #pragma once

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#pragma once #pragma once

View File

@@ -16,11 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#pragma once #pragma once
#if HAS_SPI_TFT || HAS_FSMC_TFT
#error "Sorry! TFT displays are not available for HAL/AVR."
#endif

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#pragma once #pragma once

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#pragma once #pragma once

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#pragma once #pragma once
@@ -26,76 +26,40 @@
*/ */
/** /**
* Check for common serial pin conflicts * Digipot requirement
*/ */
#define CHECK_SERIAL_PIN(N) ( \ #if ENABLED(DIGIPOT_MCP4018)
X_STOP_PIN == N || Y_STOP_PIN == N || Z_STOP_PIN == N \ #if !defined(DIGIPOTS_I2C_SDA_X) || !defined(DIGIPOTS_I2C_SDA_Y) || !defined(DIGIPOTS_I2C_SDA_Z) \
|| X_MIN_PIN == N || Y_MIN_PIN == N || Z_MIN_PIN == N \ || !defined(DIGIPOTS_I2C_SDA_E0) || !defined(DIGIPOTS_I2C_SDA_E1)
|| X_MAX_PIN == N || Y_MAX_PIN == N || Z_MAX_PIN == N \ #error "DIGIPOT_MCP4018 requires DIGIPOTS_I2C_SDA_* pins to be defined."
|| X_STEP_PIN == N || Y_STEP_PIN == N || Z_STEP_PIN == N \ #endif
|| 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 #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 * Checks for FAST PWM
*/ */
#if ALL(FAST_PWM_FAN, USE_OCR2A_AS_TOP, HAS_TCCR2) #if ENABLED(FAST_PWM_FAN) && (ENABLED(USE_OCR2A_AS_TOP) && defined(TCCR2))
#error "USE_OCR2A_AS_TOP does not apply to devices with a single output TIMER2." #error "USE_OCR2A_AS_TOP does not apply to devices with a single output TIMER2"
#endif
/**
* Checks for SOFT PWM
*/
#if HAS_FAN0 && FAN_PIN == 9 && DISABLED(FAN_SOFT_PWM) && ENABLED(SPEAKER)
#error "FAN_PIN 9 Hardware PWM uses Timer 2 which conflicts with Arduino AVR Tone Timer (for SPEAKER)."
#error "Disable SPEAKER or enable FAN_SOFT_PWM."
#endif #endif
/** /**
* Sanity checks for Spindle / Laser PWM * Sanity checks for Spindle / Laser PWM
*/ */
#if ENABLED(SPINDLE_LASER_USE_PWM) #if ENABLED(SPINDLE_LASER_PWM)
#include "../ServoTimers.h" // Needed to check timer availability (_useTimer3)
#if SPINDLE_LASER_PWM_PIN == 4 || WITHIN(SPINDLE_LASER_PWM_PIN, 11, 13) #if SPINDLE_LASER_PWM_PIN == 4 || WITHIN(SPINDLE_LASER_PWM_PIN, 11, 13)
#error "Counter/Timer for SPINDLE_LASER_PWM_PIN is used by a system interrupt." #error "Counter/Timer for SPINDLE_LASER_PWM_PIN is used by a system interrupt."
#elif NUM_SERVOS > 0 && defined(_useTimer3) && (WITHIN(SPINDLE_LASER_PWM_PIN, 2, 3) || SPINDLE_LASER_PWM_PIN == 5) #elif NUM_SERVOS > 0 && (WITHIN(SPINDLE_LASER_PWM_PIN, 2, 3) || SPINDLE_LASER_PWM_PIN == 5)
#error "Counter/Timer for SPINDLE_LASER_PWM_PIN is used by the servo system." #error "Counter/Timer for SPINDLE_LASER_PWM_PIN is used by the servo system."
#endif #endif
#elif SPINDLE_LASER_FREQUENCY
#error "SPINDLE_LASER_FREQUENCY requires SPINDLE_LASER_USE_PWM."
#endif #endif
/** /**
* The Trinamic library includes SoftwareSerial.h, leading to a compile error. * The Trinamic library includes SoftwareSerial.h, leading to a compile error.
*/ */
#if BOTH(HAS_TRINAMIC_CONFIG, ENDSTOP_INTERRUPTS_FEATURE) #if HAS_TRINAMIC_CONFIG && ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
#error "TMCStepper includes SoftwareSerial.h which is incompatible with ENDSTOP_INTERRUPTS_FEATURE. Disable ENDSTOP_INTERRUPTS_FEATURE to continue." #error "TMCStepper includes SoftwareSerial.h which is incompatible with ENDSTOP_INTERRUPTS_FEATURE. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
#endif #endif
#if BOTH(HAS_TMC_SW_SERIAL, MONITOR_DRIVER_STATUS) #if HAS_TMC_SW_SERIAL && ENABLED(MONITOR_DRIVER_STATUS)
#error "MONITOR_DRIVER_STATUS causes performance issues when used with SoftwareSerial-connected drivers. Disable MONITOR_DRIVER_STATUS or use hardware serial to continue." #error "MONITOR_DRIVER_STATUS causes performance issues when used with SoftwareSerial-connected drivers. Disable MONITOR_DRIVER_STATUS or use hardware serial to continue."
#endif #endif
/**
* Postmortem debugging
*/
#if ENABLED(POSTMORTEM_DEBUGGING)
#error "POSTMORTEM_DEBUGGING is not supported on AVR boards."
#endif
#if USING_PULLDOWNS
#error "PULLDOWN pin mode is not available on AVR boards."
#endif

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#pragma once #pragma once
@@ -35,7 +35,7 @@
// C B A is longIn1 // C B A is longIn1
// D C B A is longIn2 // D C B A is longIn2
// //
FORCE_INLINE static uint16_t MultiU24X32toH16(uint32_t longIn1, uint32_t longIn2) { static FORCE_INLINE uint16_t MultiU24X32toH16(uint32_t longIn1, uint32_t longIn2) {
uint8_t tmp1; uint8_t tmp1;
uint8_t tmp2; uint8_t tmp2;
uint16_t intRes; uint16_t intRes;
@@ -89,7 +89,7 @@ FORCE_INLINE static uint16_t MultiU24X32toH16(uint32_t longIn1, uint32_t longIn2
// uses: // uses:
// r26 to store 0 // r26 to store 0
// r27 to store the byte 1 of the 24 bit result // r27 to store the byte 1 of the 24 bit result
FORCE_INLINE static uint16_t MultiU16X8toH16(uint8_t charIn1, uint16_t intIn2) { static FORCE_INLINE uint16_t MultiU16X8toH16(uint8_t charIn1, uint16_t intIn2) {
uint8_t tmp; uint8_t tmp;
uint16_t intRes; uint16_t intRes;
__asm__ __volatile__ ( __asm__ __volatile__ (

View File

@@ -2,9 +2,6 @@
* Marlin 3D Printer Firmware * Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] * 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 * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
@@ -16,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#pragma once #pragma once
@@ -29,9 +26,7 @@
#define NUMBER_PINS_TOTAL NUM_DIGITAL_PINS #define NUMBER_PINS_TOTAL NUM_DIGITAL_PINS
#if MB(BQ_ZUM_MEGA_3D, MIGHTYBOARD_REVE, MINIRAMBO, SCOOVO_X9H, TRIGORILLA_14) #define AVR_ATmega2560_FAMILY_PLUS_70 MB(BQ_ZUM_MEGA_3D, MIGHTYBOARD_REVE, MINIRAMBO, SCOOVO_X9H)
#define AVR_ATmega2560_FAMILY_PLUS_70 1
#endif
#if AVR_AT90USB1286_FAMILY #if AVR_AT90USB1286_FAMILY
@@ -41,7 +36,7 @@
// portModeRegister takes a different argument // portModeRegister takes a different argument
#define digitalPinToTimer_DEBUG(p) digitalPinToTimer(p) #define digitalPinToTimer_DEBUG(p) digitalPinToTimer(p)
#define digitalPinToBitMask_DEBUG(p) digitalPinToBitMask(p) #define digitalPinToBitMask_DEBUG(p) digitalPinToBitMask(p)
#define digitalPinToPort_DEBUG(p) digitalPinToPort(p) #define digitalPinToPort_DEBUG(p) digitalPinToPort_Teensy(p)
#define GET_PINMODE(pin) (*portModeRegister(pin) & digitalPinToBitMask_DEBUG(pin)) #define GET_PINMODE(pin) (*portModeRegister(pin) & digitalPinToBitMask_DEBUG(pin))
#elif AVR_ATmega2560_FAMILY_PLUS_70 // So we can access/display all the pins on boards using more than 70 #elif AVR_ATmega2560_FAMILY_PLUS_70 // So we can access/display all the pins on boards using more than 70
@@ -74,7 +69,7 @@
#define MULTI_NAME_PAD 26 // space needed to be pretty if not first name assigned to a pin #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) { void PRINT_ARRAY_NAME(uint8_t x) {
PGM_P const name_mem_pointer = (PGM_P)pgm_read_ptr(&pin_array[x].name); char *name_mem_pointer = (char*)pgm_read_ptr(&pin_array[x].name);
LOOP_L_N(y, MAX_NAME_LENGTH) { LOOP_L_N(y, MAX_NAME_LENGTH) {
char temp_char = pgm_read_byte(name_mem_pointer + y); char temp_char = pgm_read_byte(name_mem_pointer + y);
if (temp_char != 0) if (temp_char != 0)
@@ -102,7 +97,7 @@ void PRINT_ARRAY_NAME(uint8_t x) {
return true; \ return true; \
} else return false } else return false
#define ABTEST(N) defined(TCCR##N##A) && defined(COM##N##A1)
/** /**
* Print a pin's PWM status. * Print a pin's PWM status.
@@ -113,7 +108,7 @@ static bool pwm_status(uint8_t pin) {
switch (digitalPinToTimer_DEBUG(pin)) { switch (digitalPinToTimer_DEBUG(pin)) {
#if ABTEST(0) #if defined(TCCR0A) && defined(COM0A1)
#ifdef TIMER0A #ifdef TIMER0A
#if !AVR_AT90USB1286_FAMILY // not available in Teensyduino type IDEs #if !AVR_AT90USB1286_FAMILY // not available in Teensyduino type IDEs
PWM_CASE(0, A); PWM_CASE(0, A);
@@ -122,20 +117,20 @@ static bool pwm_status(uint8_t pin) {
PWM_CASE(0, B); PWM_CASE(0, B);
#endif #endif
#if ABTEST(1) #if defined(TCCR1A) && defined(COM1A1)
PWM_CASE(1, A); PWM_CASE(1, A);
PWM_CASE(1, B); PWM_CASE(1, B);
#if defined(COM1C1) && defined(TIMER1C) #if defined(COM1C1) && defined(TIMER1C)
PWM_CASE(1, C); PWM_CASE(1, C);
#endif #endif
#endif #endif
#if ABTEST(2) #if defined(TCCR2A) && defined(COM2A1)
PWM_CASE(2, A); PWM_CASE(2, A);
PWM_CASE(2, B); PWM_CASE(2, B);
#endif #endif
#if ABTEST(3) #if defined(TCCR3A) && defined(COM3A1)
PWM_CASE(3, A); PWM_CASE(3, A);
PWM_CASE(3, B); PWM_CASE(3, B);
#ifdef COM3C1 #ifdef COM3C1
@@ -149,7 +144,7 @@ static bool pwm_status(uint8_t pin) {
PWM_CASE(4, C); PWM_CASE(4, C);
#endif #endif
#if ABTEST(5) #if defined(TCCR5A) && defined(COM5A1)
PWM_CASE(5, A); PWM_CASE(5, A);
PWM_CASE(5, B); PWM_CASE(5, B);
PWM_CASE(5, C); PWM_CASE(5, C);
@@ -166,16 +161,16 @@ static bool pwm_status(uint8_t pin) {
const volatile uint8_t* const PWM_other[][3] PROGMEM = { const volatile uint8_t* const PWM_other[][3] PROGMEM = {
{ &TCCR0A, &TCCR0B, &TIMSK0 }, { &TCCR0A, &TCCR0B, &TIMSK0 },
{ &TCCR1A, &TCCR1B, &TIMSK1 }, { &TCCR1A, &TCCR1B, &TIMSK1 },
#if ABTEST(2) #if defined(TCCR2A) && defined(COM2A1)
{ &TCCR2A, &TCCR2B, &TIMSK2 }, { &TCCR2A, &TCCR2B, &TIMSK2 },
#endif #endif
#if ABTEST(3) #if defined(TCCR3A) && defined(COM3A1)
{ &TCCR3A, &TCCR3B, &TIMSK3 }, { &TCCR3A, &TCCR3B, &TIMSK3 },
#endif #endif
#ifdef TCCR4A #ifdef TCCR4A
{ &TCCR4A, &TCCR4B, &TIMSK4 }, { &TCCR4A, &TCCR4B, &TIMSK4 },
#endif #endif
#if ABTEST(5) #if defined(TCCR5A) && defined(COM5A1)
{ &TCCR5A, &TCCR5B, &TIMSK5 }, { &TCCR5A, &TCCR5B, &TIMSK5 },
#endif #endif
}; };
@@ -195,11 +190,11 @@ const volatile uint8_t* const PWM_OCR[][3] PROGMEM = {
{ (const uint8_t*)&OCR1A, (const uint8_t*)&OCR1B, 0 }, { (const uint8_t*)&OCR1A, (const uint8_t*)&OCR1B, 0 },
#endif #endif
#if ABTEST(2) #if defined(TCCR2A) && defined(COM2A1)
{ &OCR2A, &OCR2B, 0 }, { &OCR2A, &OCR2B, 0 },
#endif #endif
#if ABTEST(3) #if defined(TCCR3A) && defined(COM3A1)
#ifdef COM3C1 #ifdef COM3C1
{ (const uint8_t*)&OCR3A, (const uint8_t*)&OCR3B, (const uint8_t*)&OCR3C }, { (const uint8_t*)&OCR3A, (const uint8_t*)&OCR3B, (const uint8_t*)&OCR3C },
#else #else
@@ -211,7 +206,7 @@ const volatile uint8_t* const PWM_OCR[][3] PROGMEM = {
{ (const uint8_t*)&OCR4A, (const uint8_t*)&OCR4B, (const uint8_t*)&OCR4C }, { (const uint8_t*)&OCR4A, (const uint8_t*)&OCR4B, (const uint8_t*)&OCR4C },
#endif #endif
#if ABTEST(5) #if defined(TCCR5A) && defined(COM5A1)
{ (const uint8_t*)&OCR5A, (const uint8_t*)&OCR5B, (const uint8_t*)&OCR5C }, { (const uint8_t*)&OCR5A, (const uint8_t*)&OCR5B, (const uint8_t*)&OCR5C },
#endif #endif
}; };
@@ -238,9 +233,9 @@ static void print_is_also_tied() { SERIAL_ECHOPGM(" is also tied to this pin");
inline void com_print(const uint8_t N, const uint8_t Z) { inline void com_print(const uint8_t N, const uint8_t Z) {
const uint8_t *TCCRA = (uint8_t*)TCCR_A(N); const uint8_t *TCCRA = (uint8_t*)TCCR_A(N);
SERIAL_ECHOPGM(" COM", AS_DIGIT(N)); SERIAL_ECHOPGM(" COM");
SERIAL_CHAR(Z); SERIAL_CHAR('0' + N, Z);
SERIAL_ECHOPGM(": ", int((*TCCRA >> (6 - Z * 2)) & 0x03)); SERIAL_ECHOPAIR(": ", int((*TCCRA >> (6 - Z * 2)) & 0x03));
} }
void timer_prefix(uint8_t T, char L, uint8_t N) { // T - timer L - pwm N - WGM bit layout void timer_prefix(uint8_t T, char L, uint8_t N) { // T - timer L - pwm N - WGM bit layout
@@ -250,8 +245,8 @@ void timer_prefix(uint8_t T, char L, uint8_t N) { // T - timer L - pwm N -
uint8_t WGM = (((*TCCRB & _BV(WGM_2)) >> 1) | (*TCCRA & (_BV(WGM_0) | _BV(WGM_1)))); uint8_t WGM = (((*TCCRB & _BV(WGM_2)) >> 1) | (*TCCRA & (_BV(WGM_0) | _BV(WGM_1))));
if (N == 4) WGM |= ((*TCCRB & _BV(WGM_3)) >> 1); if (N == 4) WGM |= ((*TCCRB & _BV(WGM_3)) >> 1);
SERIAL_ECHOPGM(" TIMER", AS_DIGIT(T)); SERIAL_ECHOPGM(" TIMER");
SERIAL_CHAR(L); SERIAL_CHAR(T + '0', L);
SERIAL_ECHO_SP(3); SERIAL_ECHO_SP(3);
if (N == 3) { if (N == 3) {
@@ -262,14 +257,22 @@ void timer_prefix(uint8_t T, char L, uint8_t N) { // T - timer L - pwm N -
const uint16_t *OCRVAL16 = (uint16_t*)OCR_VAL(T, L - 'A'); const uint16_t *OCRVAL16 = (uint16_t*)OCR_VAL(T, L - 'A');
PWM_PRINT(*OCRVAL16); PWM_PRINT(*OCRVAL16);
} }
SERIAL_ECHOPGM(" WGM: ", WGM); SERIAL_ECHOPAIR(" WGM: ", WGM);
com_print(T,L); com_print(T,L);
SERIAL_ECHOPGM(" CS: ", (*TCCRB & (_BV(CS_0) | _BV(CS_1) | _BV(CS_2)) )); SERIAL_ECHOPAIR(" CS: ", (*TCCRB & (_BV(CS_0) | _BV(CS_1) | _BV(CS_2)) ));
SERIAL_ECHOPGM(" TCCR", AS_DIGIT(T), "A: ", *TCCRA);
SERIAL_ECHOPGM(" TCCR", AS_DIGIT(T), "B: ", *TCCRB); SERIAL_ECHOPGM(" TCCR");
SERIAL_CHAR(T + '0');
SERIAL_ECHOPAIR("A: ", *TCCRA);
SERIAL_ECHOPGM(" TCCR");
SERIAL_CHAR(T + '0');
SERIAL_ECHOPAIR("B: ", *TCCRB);
const uint8_t *TMSK = (uint8_t*)TIMSK(T); const uint8_t *TMSK = (uint8_t*)TIMSK(T);
SERIAL_ECHOPGM(" TIMSK", AS_DIGIT(T), ": ", *TMSK); SERIAL_ECHOPGM(" TIMSK");
SERIAL_CHAR(T + '0');
SERIAL_ECHOPAIR(": ", *TMSK);
const uint8_t OCIE = L - 'A' + 1; const uint8_t OCIE = L - 'A' + 1;
if (N == 3) { if (WGM == 0 || WGM == 2 || WGM == 4 || WGM == 6) err_is_counter(); } if (N == 3) { if (WGM == 0 || WGM == 2 || WGM == 4 || WGM == 6) err_is_counter(); }
@@ -281,7 +284,7 @@ void timer_prefix(uint8_t T, char L, uint8_t N) { // T - timer L - pwm N -
static void pwm_details(uint8_t pin) { static void pwm_details(uint8_t pin) {
switch (digitalPinToTimer_DEBUG(pin)) { switch (digitalPinToTimer_DEBUG(pin)) {
#if ABTEST(0) #if defined(TCCR0A) && defined(COM0A1)
#ifdef TIMER0A #ifdef TIMER0A
#if !AVR_AT90USB1286_FAMILY // not available in Teensyduino type IDEs #if !AVR_AT90USB1286_FAMILY // not available in Teensyduino type IDEs
case TIMER0A: timer_prefix(0, 'A', 3); break; case TIMER0A: timer_prefix(0, 'A', 3); break;
@@ -290,7 +293,7 @@ static void pwm_details(uint8_t pin) {
case TIMER0B: timer_prefix(0, 'B', 3); break; case TIMER0B: timer_prefix(0, 'B', 3); break;
#endif #endif
#if ABTEST(1) #if defined(TCCR1A) && defined(COM1A1)
case TIMER1A: timer_prefix(1, 'A', 4); break; case TIMER1A: timer_prefix(1, 'A', 4); break;
case TIMER1B: timer_prefix(1, 'B', 4); break; case TIMER1B: timer_prefix(1, 'B', 4); break;
#if defined(COM1C1) && defined(TIMER1C) #if defined(COM1C1) && defined(TIMER1C)
@@ -298,12 +301,12 @@ static void pwm_details(uint8_t pin) {
#endif #endif
#endif #endif
#if ABTEST(2) #if defined(TCCR2A) && defined(COM2A1)
case TIMER2A: timer_prefix(2, 'A', 3); break; case TIMER2A: timer_prefix(2, 'A', 3); break;
case TIMER2B: timer_prefix(2, 'B', 3); break; case TIMER2B: timer_prefix(2, 'B', 3); break;
#endif #endif
#if ABTEST(3) #if defined(TCCR3A) && defined(COM3A1)
case TIMER3A: timer_prefix(3, 'A', 4); break; case TIMER3A: timer_prefix(3, 'A', 4); break;
case TIMER3B: timer_prefix(3, 'B', 4); break; case TIMER3B: timer_prefix(3, 'B', 4); break;
#ifdef COM3C1 #ifdef COM3C1
@@ -317,7 +320,7 @@ static void pwm_details(uint8_t pin) {
case TIMER4C: timer_prefix(4, 'C', 4); break; case TIMER4C: timer_prefix(4, 'C', 4); break;
#endif #endif
#if ABTEST(5) #if defined(TCCR5A) && defined(COM5A1)
case TIMER5A: timer_prefix(5, 'A', 4); break; case TIMER5A: timer_prefix(5, 'A', 4); break;
case TIMER5B: timer_prefix(5, 'B', 4); break; case TIMER5B: timer_prefix(5, 'B', 4); break;
case TIMER5C: timer_prefix(5, 'C', 4); break; case TIMER5C: timer_prefix(5, 'C', 4); break;
@@ -351,6 +354,7 @@ static void pwm_details(uint8_t pin) {
#endif #endif
} // pwm_details } // pwm_details
#ifndef digitalRead_mod // Use Teensyduino's version of digitalRead - it doesn't disable the PWMs #ifndef digitalRead_mod // Use Teensyduino's version of digitalRead - it doesn't disable the PWMs
int digitalRead_mod(const int8_t pin) { // same as digitalRead except the PWM stop section has been removed int digitalRead_mod(const int8_t pin) { // same as digitalRead except the PWM stop section has been removed
const uint8_t port = digitalPinToPort_DEBUG(pin); const uint8_t port = digitalPinToPort_DEBUG(pin);
@@ -395,6 +399,3 @@ static void pwm_details(uint8_t pin) {
#endif #endif
#define PRINT_PIN(p) do{ sprintf_P(buffer, PSTR("%3d "), p); SERIAL_ECHO(buffer); }while(0) #define PRINT_PIN(p) do{ sprintf_P(buffer, PSTR("%3d "), p); SERIAL_ECHO(buffer); }while(0)
#define PRINT_PIN_ANALOG(p) do{ sprintf_P(buffer, PSTR(" (A%2d) "), DIGITAL_PIN_TO_ANALOG_PIN(pin)); SERIAL_ECHO(buffer); }while(0)
#undef ABTEST

View File

@@ -2,9 +2,6 @@
* Marlin 3D Printer Firmware * Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] * 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 * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
@@ -16,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#pragma once #pragma once

View File

@@ -2,9 +2,6 @@
* Marlin 3D Printer Firmware * Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] * 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 * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
@@ -16,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#pragma once #pragma once
@@ -25,12 +22,15 @@
* Structures for 2560 family boards that use more than 70 pins * Structures for 2560 family boards that use more than 70 pins
*/ */
#if MB(BQ_ZUM_MEGA_3D, MINIRAMBO, SCOOVO_X9H, TRIGORILLA_14) #undef NUM_DIGITAL_PINS
#undef NUM_DIGITAL_PINS #if MB(BQ_ZUM_MEGA_3D)
#define NUM_DIGITAL_PINS 85 #define NUM_DIGITAL_PINS 85
#elif MB(MIGHTYBOARD_REVE) #elif MB(MIGHTYBOARD_REVE)
#undef NUM_DIGITAL_PINS
#define NUM_DIGITAL_PINS 80 #define NUM_DIGITAL_PINS 80
#elif MB(MINIRAMBO)
#define NUM_DIGITAL_PINS 85
#elif MB(SCOOVO_X9H)
#define NUM_DIGITAL_PINS 85
#endif #endif
#define PA 1 #define PA 1

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#pragma once #pragma once
@@ -51,15 +51,15 @@
#define AVR_SS_PIN 16 #define AVR_SS_PIN 16
#endif #endif
#ifndef SD_SCK_PIN #ifndef SCK_PIN
#define SD_SCK_PIN AVR_SCK_PIN #define SCK_PIN AVR_SCK_PIN
#endif #endif
#ifndef SD_MISO_PIN #ifndef MISO_PIN
#define SD_MISO_PIN AVR_MISO_PIN #define MISO_PIN AVR_MISO_PIN
#endif #endif
#ifndef SD_MOSI_PIN #ifndef MOSI_PIN
#define SD_MOSI_PIN AVR_MOSI_PIN #define MOSI_PIN AVR_MOSI_PIN
#endif #endif
#ifndef SD_SS_PIN #ifndef SS_PIN
#define SD_SS_PIN AVR_SS_PIN #define SS_PIN AVR_SS_PIN
#endif #endif

View File

@@ -1,260 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
* Copyright (c) 2016 Bob Cousins bobcousins42@googlemail.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#include <stdint.h>
// ------------------------
// Types
// ------------------------
typedef uint16_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX 0xFFFF
// ------------------------
// Defines
// ------------------------
#define HAL_TIMER_RATE ((F_CPU) / 8) // i.e., 2MHz or 2.5MHz
#ifndef MF_TIMER_STEP
#define MF_TIMER_STEP 1
#endif
#ifndef MF_TIMER_PULSE
#define MF_TIMER_PULSE MF_TIMER_STEP
#endif
#ifndef MF_TIMER_TEMP
#define MF_TIMER_TEMP 0
#endif
#define TEMP_TIMER_FREQUENCY ((F_CPU) / 64.0 / 256.0)
#define STEPPER_TIMER_RATE HAL_TIMER_RATE
#define STEPPER_TIMER_PRESCALE 8
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // Cannot be of type double
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // frequency of pulse timer
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define ENABLE_STEPPER_DRIVER_INTERRUPT() SBI(TIMSK1, OCIE1A)
#define DISABLE_STEPPER_DRIVER_INTERRUPT() CBI(TIMSK1, OCIE1A)
#define STEPPER_ISR_ENABLED() TEST(TIMSK1, OCIE1A)
#define ENABLE_TEMPERATURE_INTERRUPT() SBI(TIMSK0, OCIE0A)
#define DISABLE_TEMPERATURE_INTERRUPT() CBI(TIMSK0, OCIE0A)
#define TEMPERATURE_ISR_ENABLED() TEST(TIMSK0, OCIE0A)
FORCE_INLINE void HAL_timer_start(const uint8_t timer_num, const uint32_t) {
switch (timer_num) {
case MF_TIMER_STEP:
// waveform generation = 0100 = CTC
SET_WGM(1, CTC_OCRnA);
// output mode = 00 (disconnected)
SET_COMA(1, NORMAL);
// Set the timer pre-scaler
// Generally we use a divider of 8, resulting in a 2MHz timer
// frequency on a 16MHz MCU. If you are going to change this, be
// sure to regenerate speed_lookuptable.h with
// create_speed_lookuptable.py
SET_CS(1, PRESCALER_8); // CS 2 = 1/8 prescaler
// Init Stepper ISR to 122 Hz for quick starting
// (F_CPU) / (STEPPER_TIMER_PRESCALE) / frequency
OCR1A = 0x4000;
TCNT1 = 0;
break;
case MF_TIMER_TEMP:
// Use timer0 for temperature measurement
// Interleave temperature interrupt with millies interrupt
OCR0A = 128;
break;
}
}
#define TIMER_OCR_1 OCR1A
#define TIMER_COUNTER_1 TCNT1
#define TIMER_OCR_0 OCR0A
#define TIMER_COUNTER_0 TCNT0
#define _CAT(a,V...) a##V
#define HAL_timer_set_compare(timer, compare) (_CAT(TIMER_OCR_, timer) = compare)
#define HAL_timer_get_compare(timer) _CAT(TIMER_OCR_, timer)
#define HAL_timer_get_count(timer) _CAT(TIMER_COUNTER_, timer)
/**
* On AVR there is no hardware prioritization and preemption of
* interrupts, so this emulates it. The UART has first priority
* (otherwise, characters will be lost due to UART overflow).
* Then: Stepper, Endstops, Temperature, and -finally- all others.
*/
#define HAL_timer_isr_prologue(T) NOOP
#define HAL_timer_isr_epilogue(T) NOOP
#ifndef HAL_STEP_TIMER_ISR
/* 18 cycles maximum latency */
#define HAL_STEP_TIMER_ISR() \
extern "C" void TIMER1_COMPA_vect() __attribute__ ((signal, naked, used, externally_visible)); \
extern "C" void TIMER1_COMPA_vect_bottom() asm ("TIMER1_COMPA_vect_bottom") __attribute__ ((used, externally_visible, noinline)); \
void TIMER1_COMPA_vect() { \
__asm__ __volatile__ ( \
A("push r16") /* 2 Save R16 */ \
A("in r16, __SREG__") /* 1 Get SREG */ \
A("push r16") /* 2 Save SREG into stack */ \
A("lds r16, %[timsk0]") /* 2 Load into R0 the Temperature timer Interrupt mask register */ \
A("push r16") /* 2 Save TIMSK0 into the stack */ \
A("andi r16,~%[msk0]") /* 1 Disable the temperature ISR */ \
A("sts %[timsk0], r16") /* 2 And set the new value */ \
A("lds r16, %[timsk1]") /* 2 Load into R0 the stepper timer Interrupt mask register [TIMSK1] */ \
A("andi r16,~%[msk1]") /* 1 Disable the stepper ISR */ \
A("sts %[timsk1], r16") /* 2 And set the new value */ \
A("push r16") /* 2 Save TIMSK1 into stack */ \
A("in r16, 0x3B") /* 1 Get RAMPZ register */ \
A("push r16") /* 2 Save RAMPZ into stack */ \
A("in r16, 0x3C") /* 1 Get EIND register */ \
A("push r0") /* C runtime can modify all the following registers without restoring them */ \
A("push r1") \
A("push r18") \
A("push r19") \
A("push r20") \
A("push r21") \
A("push r22") \
A("push r23") \
A("push r24") \
A("push r25") \
A("push r26") \
A("push r27") \
A("push r30") \
A("push r31") \
A("clr r1") /* C runtime expects this register to be 0 */ \
A("call TIMER1_COMPA_vect_bottom") /* Call the bottom handler - No inlining allowed, otherwise registers used are not saved */ \
A("pop r31") \
A("pop r30") \
A("pop r27") \
A("pop r26") \
A("pop r25") \
A("pop r24") \
A("pop r23") \
A("pop r22") \
A("pop r21") \
A("pop r20") \
A("pop r19") \
A("pop r18") \
A("pop r1") \
A("pop r0") \
A("out 0x3C, r16") /* 1 Restore EIND register */ \
A("pop r16") /* 2 Get the original RAMPZ register value */ \
A("out 0x3B, r16") /* 1 Restore RAMPZ register to its original value */ \
A("pop r16") /* 2 Get the original TIMSK1 value but with stepper ISR disabled */ \
A("ori r16,%[msk1]") /* 1 Reenable the stepper ISR */ \
A("cli") /* 1 Disable global interrupts - Reenabling Stepper ISR can reenter amd temperature can reenter, and we want that, if it happens, after this ISR has ended */ \
A("sts %[timsk1], r16") /* 2 And restore the old value - This reenables the stepper ISR */ \
A("pop r16") /* 2 Get the temperature timer Interrupt mask register [TIMSK0] */ \
A("sts %[timsk0], r16") /* 2 And restore the old value - This reenables the temperature ISR */ \
A("pop r16") /* 2 Get the old SREG value */ \
A("out __SREG__, r16") /* 1 And restore the SREG value */ \
A("pop r16") /* 2 Restore R16 value */ \
A("reti") /* 4 Return from interrupt */ \
: \
: [timsk0] "i" ((uint16_t)&TIMSK0), \
[timsk1] "i" ((uint16_t)&TIMSK1), \
[msk0] "M" ((uint8_t)(1<<OCIE0A)),\
[msk1] "M" ((uint8_t)(1<<OCIE1A)) \
: \
); \
} \
void TIMER1_COMPA_vect_bottom()
#endif // HAL_STEP_TIMER_ISR
#ifndef HAL_TEMP_TIMER_ISR
/* 14 cycles maximum latency */
#define HAL_TEMP_TIMER_ISR() \
extern "C" void TIMER0_COMPA_vect() __attribute__ ((signal, naked, used, externally_visible)); \
extern "C" void TIMER0_COMPA_vect_bottom() asm ("TIMER0_COMPA_vect_bottom") __attribute__ ((used, externally_visible, noinline)); \
void TIMER0_COMPA_vect() { \
__asm__ __volatile__ ( \
A("push r16") /* 2 Save R16 */ \
A("in r16, __SREG__") /* 1 Get SREG */ \
A("push r16") /* 2 Save SREG into stack */ \
A("lds r16, %[timsk0]") /* 2 Load into R0 the Temperature timer Interrupt mask register */ \
A("andi r16,~%[msk0]") /* 1 Disable the temperature ISR */ \
A("sts %[timsk0], r16") /* 2 And set the new value */ \
A("sei") /* 1 Enable global interrupts - It is safe, as the temperature ISR is disabled, so we cannot reenter it */ \
A("push r16") /* 2 Save TIMSK0 into stack */ \
A("in r16, 0x3B") /* 1 Get RAMPZ register */ \
A("push r16") /* 2 Save RAMPZ into stack */ \
A("in r16, 0x3C") /* 1 Get EIND register */ \
A("push r0") /* C runtime can modify all the following registers without restoring them */ \
A("push r1") \
A("push r18") \
A("push r19") \
A("push r20") \
A("push r21") \
A("push r22") \
A("push r23") \
A("push r24") \
A("push r25") \
A("push r26") \
A("push r27") \
A("push r30") \
A("push r31") \
A("clr r1") /* C runtime expects this register to be 0 */ \
A("call TIMER0_COMPA_vect_bottom") /* Call the bottom handler - No inlining allowed, otherwise registers used are not saved */ \
A("pop r31") \
A("pop r30") \
A("pop r27") \
A("pop r26") \
A("pop r25") \
A("pop r24") \
A("pop r23") \
A("pop r22") \
A("pop r21") \
A("pop r20") \
A("pop r19") \
A("pop r18") \
A("pop r1") \
A("pop r0") \
A("out 0x3C, r16") /* 1 Restore EIND register */ \
A("pop r16") /* 2 Get the original RAMPZ register value */ \
A("out 0x3B, r16") /* 1 Restore RAMPZ register to its original value */ \
A("pop r16") /* 2 Get the original TIMSK0 value but with temperature ISR disabled */ \
A("ori r16,%[msk0]") /* 1 Enable temperature ISR */ \
A("cli") /* 1 Disable global interrupts - We must do this, as we will reenable the temperature ISR, and we don't want to reenter this handler until the current one is done */ \
A("sts %[timsk0], r16") /* 2 And restore the old value */ \
A("pop r16") /* 2 Get the old SREG */ \
A("out __SREG__, r16") /* 1 And restore the SREG value */ \
A("pop r16") /* 2 Restore R16 */ \
A("reti") /* 4 Return from interrupt */ \
: \
: [timsk0] "i"((uint16_t)&TIMSK0), \
[msk0] "M" ((uint8_t)(1<<OCIE0A)) \
: \
); \
} \
void TIMER0_COMPA_vect_bottom()
#endif // HAL_TEMP_TIMER_ISR

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@@ -57,15 +57,15 @@
#include "../../inc/MarlinConfigPre.h" #include "../../inc/MarlinConfigPre.h"
#if HAS_MARLINUI_U8GLIB #if HAS_GRAPHICAL_LCD
#include "../shared/Marduino.h" #include "../shared/Marduino.h"
#include "../shared/Delay.h" #include "../shared/Delay.h"
#include <U8glib-HAL.h> #include <U8glib.h>
static uint8_t u8g_bitData, u8g_bitNotData, u8g_bitClock, u8g_bitNotClock; uint8_t u8g_bitData, u8g_bitNotData, u8g_bitClock, u8g_bitNotClock;
static volatile uint8_t *u8g_outData, *u8g_outClock; volatile uint8_t *u8g_outData, *u8g_outClock;
static void u8g_com_arduino_init_shift_out(uint8_t dataPin, uint8_t clockPin) { static void u8g_com_arduino_init_shift_out(uint8_t dataPin, uint8_t clockPin) {
u8g_outData = portOutputRegister(digitalPinToPort(dataPin)); u8g_outData = portOutputRegister(digitalPinToPort(dataPin));
@@ -189,5 +189,5 @@ uint8_t u8g_com_HAL_AVR_sw_sp_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void
return 1; return 1;
} }
#endif // HAS_MARLINUI_U8GLIB #endif // HAS_GRAPHICAL_LCD
#endif // ARDUINO_ARCH_SAM #endif // ARDUINO_ARCH_SAM

View File

@@ -0,0 +1,71 @@
/**
* 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 <http://www.gnu.org/licenses/>.
*
*/
#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__

View File

@@ -16,22 +16,16 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#pragma once #pragma once
#ifdef __cplusplus #include <avr/wdt.h>
extern "C" {
#endif
#ifndef PGM_P // Initialize watchdog with a 4 second interrupt time
#define PGM_P const char * void watchdog_init();
#endif
void lv_draw_error_message(FSTR_P const fmsg); // Reset watchdog. MUST be called at least every 4 seconds after the
void lv_clear_error_message(); // first watchdog_init or AVR will go into emergency procedures.
inline void HAL_watchdog_refresh() { wdt_reset(); }
#ifdef __cplusplus
} /* C-declarations for C++ */
#endif

View File

@@ -0,0 +1,343 @@
/**
* 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 <http://www.gnu.org/licenses/>.
*
*/
#ifdef ARDUINO_ARCH_SAM
#include "../../core/macros.h"
#include "../../core/serial.h"
#include "../shared/backtrace/unwinder.h"
#include "../shared/backtrace/unwmemaccess.h"
#include <stdarg.h>
// Debug monitor that dumps to the Programming port all status when
// an exception or WDT timeout happens - And then resets the board
// All the Monitor routines must run with interrupts disabled and
// under an ISR execution context. That is why we cannot reuse the
// Serial interrupt routines or any C runtime, as we don't know the
// state we are when running them
// A SW memory barrier, to ensure GCC does not overoptimize loops
#define sw_barrier() __asm__ volatile("": : :"memory");
// (re)initialize UART0 as a monitor output to 250000,n,8,1
static void TXBegin() {
// Disable UART interrupt in NVIC
NVIC_DisableIRQ( UART_IRQn );
// We NEED memory barriers to ensure Interrupts are actually disabled!
// ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
__DSB();
__ISB();
// Disable clock
pmc_disable_periph_clk( ID_UART );
// Configure PMC
pmc_enable_periph_clk( ID_UART );
// Disable PDC channel
UART->UART_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS;
// Reset and disable receiver and transmitter
UART->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS;
// Configure mode: 8bit, No parity, 1 bit stop
UART->UART_MR = UART_MR_CHMODE_NORMAL | US_MR_CHRL_8_BIT | US_MR_NBSTOP_1_BIT | UART_MR_PAR_NO;
// Configure baudrate (asynchronous, no oversampling) to BAUDRATE bauds
UART->UART_BRGR = (SystemCoreClock / (BAUDRATE << 4));
// Enable receiver and transmitter
UART->UART_CR = UART_CR_RXEN | UART_CR_TXEN;
}
// Send character through UART with no interrupts
static void TX(char c) {
while (!(UART->UART_SR & UART_SR_TXRDY)) { WDT_Restart(WDT); sw_barrier(); };
UART->UART_THR = c;
}
// Send String through UART
static void TX(const char* s) {
while (*s) TX(*s++);
}
static void TXDigit(uint32_t d) {
if (d < 10) TX((char)(d+'0'));
else if (d < 16) TX((char)(d+'A'-10));
else TX('?');
}
// Send Hex number thru UART
static void TXHex(uint32_t v) {
TX("0x");
for (uint8_t i = 0; i < 8; i++, v <<= 4)
TXDigit((v >> 28) & 0xF);
}
// Send Decimal number thru UART
static void TXDec(uint32_t v) {
if (!v) {
TX('0');
return;
}
char nbrs[14];
char *p = &nbrs[0];
while (v != 0) {
*p++ = '0' + (v % 10);
v /= 10;
}
do {
p--;
TX(*p);
} while (p != &nbrs[0]);
}
// Dump a backtrace entry
static bool UnwReportOut(void* ctx, const UnwReport* bte) {
int* p = (int*)ctx;
(*p)++;
TX('#'); TXDec(*p); TX(" : ");
TX(bte->name?bte->name:"unknown"); TX('@'); TXHex(bte->function);
TX('+'); TXDec(bte->address - bte->function);
TX(" PC:");TXHex(bte->address); TX('\n');
return true;
}
#ifdef UNW_DEBUG
void UnwPrintf(const char* format, ...) {
char dest[256];
va_list argptr;
va_start(argptr, format);
vsprintf(dest, format, argptr);
va_end(argptr);
TX(&dest[0]);
}
#endif
/* Table of function pointers for passing to the unwinder */
static const UnwindCallbacks UnwCallbacks = {
UnwReportOut,
UnwReadW,
UnwReadH,
UnwReadB
#ifdef UNW_DEBUG
, UnwPrintf
#endif
};
/**
* HardFaultHandler_C:
* This is called from the HardFault_HandlerAsm with a pointer the Fault stack
* as the parameter. We can then read the values from the stack and place them
* into local variables for ease of reading.
* We then read the various Fault Status and Address Registers to help decode
* cause of the fault.
* The function ends with a BKPT instruction to force control back into the debugger
*/
extern "C"
void HardFault_HandlerC(unsigned long *sp, unsigned long lr, unsigned long cause) {
static const char* causestr[] = {
"NMI","Hard","Mem","Bus","Usage","Debug","WDT","RSTC"
};
UnwindFrame btf;
// Dump report to the Programming port (interrupts are DISABLED)
TXBegin();
TX("\n\n## Software Fault detected ##\n");
TX("Cause: "); TX(causestr[cause]); TX('\n');
TX("R0 : "); TXHex(((unsigned long)sp[0])); TX('\n');
TX("R1 : "); TXHex(((unsigned long)sp[1])); TX('\n');
TX("R2 : "); TXHex(((unsigned long)sp[2])); TX('\n');
TX("R3 : "); TXHex(((unsigned long)sp[3])); TX('\n');
TX("R12 : "); TXHex(((unsigned long)sp[4])); TX('\n');
TX("LR : "); TXHex(((unsigned long)sp[5])); TX('\n');
TX("PC : "); TXHex(((unsigned long)sp[6])); TX('\n');
TX("PSR : "); TXHex(((unsigned long)sp[7])); TX('\n');
// Configurable Fault Status Register
// Consists of MMSR, BFSR and UFSR
TX("CFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED28)))); TX('\n');
// Hard Fault Status Register
TX("HFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED2C)))); TX('\n');
// Debug Fault Status Register
TX("DFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED30)))); TX('\n');
// Auxiliary Fault Status Register
TX("AFSR : "); TXHex((*((volatile unsigned long *)(0xE000ED3C)))); TX('\n');
// Read the Fault Address Registers. These may not contain valid values.
// Check BFARVALID/MMARVALID to see if they are valid values
// MemManage Fault Address Register
TX("MMAR : "); TXHex((*((volatile unsigned long *)(0xE000ED34)))); TX('\n');
// Bus Fault Address Register
TX("BFAR : "); TXHex((*((volatile unsigned long *)(0xE000ED38)))); TX('\n');
TX("ExcLR: "); TXHex(lr); TX('\n');
TX("ExcSP: "); TXHex((unsigned long)sp); TX('\n');
btf.sp = ((unsigned long)sp) + 8*4; // The original stack pointer
btf.fp = btf.sp;
btf.lr = ((unsigned long)sp[5]);
btf.pc = ((unsigned long)sp[6]) | 1; // Force Thumb, as CORTEX only support it
// Perform a backtrace
TX("\nBacktrace:\n\n");
int ctr = 0;
UnwindStart(&btf, &UnwCallbacks, &ctr);
// Disable all NVIC interrupts
NVIC->ICER[0] = 0xFFFFFFFF;
NVIC->ICER[1] = 0xFFFFFFFF;
// Relocate VTOR table to default position
SCB->VTOR = 0;
// Disable USB
otg_disable();
// Restart watchdog
WDT_Restart(WDT);
// Reset controller
NVIC_SystemReset();
for (;;) WDT_Restart(WDT);
}
__attribute__((naked)) void NMI_Handler() {
__asm__ __volatile__ (
".syntax unified" "\n\t"
A("tst lr, #4")
A("ite eq")
A("mrseq r0, msp")
A("mrsne r0, psp")
A("mov r1,lr")
A("mov r2,#0")
A("b HardFault_HandlerC")
);
}
__attribute__((naked)) void HardFault_Handler() {
__asm__ __volatile__ (
".syntax unified" "\n\t"
A("tst lr, #4")
A("ite eq")
A("mrseq r0, msp")
A("mrsne r0, psp")
A("mov r1,lr")
A("mov r2,#1")
A("b HardFault_HandlerC")
);
}
__attribute__((naked)) void MemManage_Handler() {
__asm__ __volatile__ (
".syntax unified" "\n\t"
A("tst lr, #4")
A("ite eq")
A("mrseq r0, msp")
A("mrsne r0, psp")
A("mov r1,lr")
A("mov r2,#2")
A("b HardFault_HandlerC")
);
}
__attribute__((naked)) void BusFault_Handler() {
__asm__ __volatile__ (
".syntax unified" "\n\t"
A("tst lr, #4")
A("ite eq")
A("mrseq r0, msp")
A("mrsne r0, psp")
A("mov r1,lr")
A("mov r2,#3")
A("b HardFault_HandlerC")
);
}
__attribute__((naked)) void UsageFault_Handler() {
__asm__ __volatile__ (
".syntax unified" "\n\t"
A("tst lr, #4")
A("ite eq")
A("mrseq r0, msp")
A("mrsne r0, psp")
A("mov r1,lr")
A("mov r2,#4")
A("b HardFault_HandlerC")
);
}
__attribute__((naked)) void DebugMon_Handler() {
__asm__ __volatile__ (
".syntax unified" "\n\t"
A("tst lr, #4")
A("ite eq")
A("mrseq r0, msp")
A("mrsne r0, psp")
A("mov r1,lr")
A("mov r2,#5")
A("b HardFault_HandlerC")
);
}
/* This is NOT an exception, it is an interrupt handler - Nevertheless, the framing is the same */
__attribute__((naked)) void WDT_Handler() {
__asm__ __volatile__ (
".syntax unified" "\n\t"
A("tst lr, #4")
A("ite eq")
A("mrseq r0, msp")
A("mrsne r0, psp")
A("mov r1,lr")
A("mov r2,#6")
A("b HardFault_HandlerC")
);
}
__attribute__((naked)) void RSTC_Handler() {
__asm__ __volatile__ (
".syntax unified" "\n\t"
A("tst lr, #4")
A("ite eq")
A("mrseq r0, msp")
A("mrsne r0, psp")
A("mov r1,lr")
A("mov r2,#7")
A("b HardFault_HandlerC")
);
}
#endif // ARDUINO_ARCH_SAM

View File

@@ -1,10 +1,9 @@
/** /**
* Marlin 3D Printer Firmware * Marlin 3D Printer Firmware
*
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
* Copyright (c) 2016 Bob Cousins bobcousins42@googlemail.com *
* Copyright (c) 2015-2016 Nico Tonnhofer wurstnase.reprap@gmail.com * Based on Sprinter and grbl.
* Copyright (c) 2016 Victor Perez victor_pv@hotmail.com * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
* *
* This program is free software: you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@@ -17,14 +16,9 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#ifdef ARDUINO_ARCH_SAM
#include "../../inc/MarlinConfig.h"
#if ENABLED(FLASH_EEPROM_EMULATION)
/* EEPROM emulation over flash with reduced wear /* EEPROM emulation over flash with reduced wear
* *
@@ -53,14 +47,22 @@
* per page. We can't emulate EE endurance with FLASH for all * per page. We can't emulate EE endurance with FLASH for all
* bytes, but we can emulate endurance for a given percent of * bytes, but we can emulate endurance for a given percent of
* bytes. * bytes.
*
*/ */
//#define EE_EMU_DEBUG #ifdef ARDUINO_ARCH_SAM
#include "../../inc/MarlinConfig.h"
#if ENABLED(FLASH_EEPROM_EMULATION)
#include "../shared/Marduino.h"
#include "../shared/eeprom_api.h"
#define EEPROMSize 4096 #define EEPROMSize 4096
#define PagesPerGroup 128 #define PagesPerGroup 128
#define GroupCount 2 #define GroupCount 2
#define PageSize 256U #define PageSize 256u
/* Flash storage */ /* Flash storage */
typedef struct FLASH_SECTOR { typedef struct FLASH_SECTOR {
@@ -132,18 +134,15 @@ static uint8_t buffer[256] = {0}, // The RAM buffer to accumulate writes
curPage = 0, // Current FLASH page inside the group curPage = 0, // Current FLASH page inside the group
curGroup = 0xFF; // Current FLASH group curGroup = 0xFF; // Current FLASH group
#define DEBUG_OUT ENABLED(EE_EMU_DEBUG) //#define EE_EMU_DEBUG
#include "../../core/debug_out.h" #ifdef EE_EMU_DEBUG
static void ee_Dump(int page,const void* data) {
static void ee_Dump(const int page, const void *data) { const uint8_t* c = (const uint8_t*) data;
#ifdef EE_EMU_DEBUG
const uint8_t *c = (const uint8_t*) data;
char buffer[80]; char buffer[80];
sprintf_P(buffer, PSTR("Page: %d (0x%04x)\n"), page, page); sprintf_P(buffer, PSTR("Page: %d (0x%04x)\n"), page, page);
DEBUG_ECHO(buffer); SERIAL_ECHO(buffer);
char* p = &buffer[0]; char* p = &buffer[0];
for (int i = 0; i< PageSize; ++i) { for (int i = 0; i< PageSize; ++i) {
@@ -153,16 +152,12 @@ static void ee_Dump(const int page, const void *data) {
if ((i & 0xF) == 0xF) { if ((i & 0xF) == 0xF) {
*p++ = '\n'; *p++ = '\n';
*p = 0; *p = 0;
DEBUG_ECHO(buffer); SERIAL_ECHO(buffer);
p = &buffer[0]; p = &buffer[0];
} }
} }
}
#else #endif
UNUSED(page);
UNUSED(data);
#endif
}
/* Flash Writing Protection Key */ /* Flash Writing Protection Key */
#define FWP_KEY 0x5Au #define FWP_KEY 0x5Au
@@ -175,16 +170,17 @@ static void ee_Dump(const int page, const void *data) {
#define EEFC_ERROR_FLAGS (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE) #define EEFC_ERROR_FLAGS (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE)
#endif #endif
/** /**
* Writes the contents of the specified page (no previous erase) * Writes the contents of the specified page (no previous erase)
* @param page (page #) * @param page (page #)
* @param data (pointer to the data buffer) * @param data (pointer to the data buffer)
*/ */
__attribute__ ((long_call, section (".ramfunc"))) __attribute__ ((long_call, section (".ramfunc")))
static bool ee_PageWrite(uint16_t page, const void *data) { static bool ee_PageWrite(uint16_t page,const void* data) {
uint16_t i; uint16_t i;
uint32_t addrflash = uint32_t(getFlashStorage(page)); uint32_t addrflash = ((uint32_t)getFlashStorage(page));
// Read the flash contents // Read the flash contents
uint32_t pageContents[PageSize>>2]; uint32_t pageContents[PageSize>>2];
@@ -199,10 +195,13 @@ static bool ee_PageWrite(uint16_t page, const void *data) {
for (i = 0; i <PageSize >> 2; i++) for (i = 0; i <PageSize >> 2; i++)
pageContents[i] = (((uint32_t*)data)[i]) | (~(pageContents[i] ^ ((uint32_t*)data)[i])); pageContents[i] = (((uint32_t*)data)[i]) | (~(pageContents[i] ^ ((uint32_t*)data)[i]));
DEBUG_ECHO_MSG("EEPROM PageWrite ", page); #ifdef EE_EMU_DEBUG
DEBUG_ECHOLNPGM(" in FLASH address ", (uint32_t)addrflash); SERIAL_ECHO_START();
DEBUG_ECHOLNPGM(" base address ", (uint32_t)getFlashStorage(0)); SERIAL_ECHOLNPAIR("EEPROM PageWrite ", page);
DEBUG_FLUSH(); SERIAL_ECHOLNPAIR(" in FLASH address ", (uint32_t)addrflash);
SERIAL_ECHOLNPAIR(" base address ", (uint32_t)getFlashStorage(0));
SERIAL_FLUSH();
#endif
// Get the page relative to the start of the EFC controller, and the EFC controller to use // Get the page relative to the start of the EFC controller, and the EFC controller to use
Efc *efc; Efc *efc;
@@ -244,7 +243,10 @@ static bool ee_PageWrite(uint16_t page, const void *data) {
// Reenable interrupts // Reenable interrupts
__enable_irq(); __enable_irq();
DEBUG_ECHO_MSG("EEPROM Unlock failure for page ", page); #ifdef EE_EMU_DEBUG
SERIAL_ECHO_START();
SERIAL_ECHOLNPAIR("EEPROM Unlock failure for page ", page);
#endif
return false; return false;
} }
@@ -268,8 +270,10 @@ static bool ee_PageWrite(uint16_t page, const void *data) {
// Reenable interrupts // Reenable interrupts
__enable_irq(); __enable_irq();
DEBUG_ECHO_MSG("EEPROM Write failure for page ", page); #ifdef EE_EMU_DEBUG
SERIAL_ECHO_START();
SERIAL_ECHOLNPAIR("EEPROM Write failure for page ", page);
#endif
return false; return false;
} }
@@ -283,14 +287,15 @@ static bool ee_PageWrite(uint16_t page, const void *data) {
if (memcmp(getFlashStorage(page),data,PageSize)) { if (memcmp(getFlashStorage(page),data,PageSize)) {
#ifdef EE_EMU_DEBUG #ifdef EE_EMU_DEBUG
DEBUG_ECHO_MSG("EEPROM Verify Write failure for page ", page); SERIAL_ECHO_START();
SERIAL_ECHOLNPAIR("EEPROM Verify Write failure for page ", page);
ee_Dump( page, (uint32_t *)addrflash); ee_Dump( page,(uint32_t *) addrflash);
ee_Dump(-page, data); ee_Dump(-page,data);
// Calculate count of changed bits // Calculate count of changed bits
uint32_t *p1 = (uint32_t*)addrflash; uint32_t* p1 = (uint32_t*)addrflash;
uint32_t *p2 = (uint32_t*)data; uint32_t* p2 = (uint32_t*)data;
int count = 0; int count = 0;
for (i =0; i<PageSize >> 2; i++) { for (i =0; i<PageSize >> 2; i++) {
if (p1[i] != p2[i]) { if (p1[i] != p2[i]) {
@@ -302,7 +307,7 @@ static bool ee_PageWrite(uint16_t page, const void *data) {
} }
} }
} }
DEBUG_ECHOLNPGM("--> Differing bits: ", count); SERIAL_ECHOLNPAIR("--> Differing bits: ", count);
#endif #endif
return false; return false;
@@ -319,12 +324,15 @@ __attribute__ ((long_call, section (".ramfunc")))
static bool ee_PageErase(uint16_t page) { static bool ee_PageErase(uint16_t page) {
uint16_t i; uint16_t i;
uint32_t addrflash = uint32_t(getFlashStorage(page)); uint32_t addrflash = ((uint32_t)getFlashStorage(page));
DEBUG_ECHO_MSG("EEPROM PageErase ", page); #ifdef EE_EMU_DEBUG
DEBUG_ECHOLNPGM(" in FLASH address ", (uint32_t)addrflash); SERIAL_ECHO_START();
DEBUG_ECHOLNPGM(" base address ", (uint32_t)getFlashStorage(0)); SERIAL_ECHOLNPAIR("EEPROM PageErase ", page);
DEBUG_FLUSH(); SERIAL_ECHOLNPAIR(" in FLASH address ", (uint32_t)addrflash);
SERIAL_ECHOLNPAIR(" base address ", (uint32_t)getFlashStorage(0));
SERIAL_FLUSH();
#endif
// Get the page relative to the start of the EFC controller, and the EFC controller to use // Get the page relative to the start of the EFC controller, and the EFC controller to use
Efc *efc; Efc *efc;
@@ -365,8 +373,10 @@ static bool ee_PageErase(uint16_t page) {
// Reenable interrupts // Reenable interrupts
__enable_irq(); __enable_irq();
DEBUG_ECHO_MSG("EEPROM Unlock failure for page ",page); #ifdef EE_EMU_DEBUG
SERIAL_ECHO_START();
SERIAL_ECHOLNPAIR("EEPROM Unlock failure for page ",page);
#endif
return false; return false;
} }
@@ -388,8 +398,10 @@ static bool ee_PageErase(uint16_t page) {
// Reenable interrupts // Reenable interrupts
__enable_irq(); __enable_irq();
DEBUG_ECHO_MSG("EEPROM Erase failure for page ",page); #ifdef EE_EMU_DEBUG
SERIAL_ECHO_START();
SERIAL_ECHOLNPAIR("EEPROM Erase failure for page ",page);
#endif
return false; return false;
} }
@@ -403,16 +415,20 @@ static bool ee_PageErase(uint16_t page) {
uint32_t * aligned_src = (uint32_t *) addrflash; uint32_t * aligned_src = (uint32_t *) addrflash;
for (i = 0; i < PageSize >> 2; i++) { for (i = 0; i < PageSize >> 2; i++) {
if (*aligned_src++ != 0xFFFFFFFF) { if (*aligned_src++ != 0xFFFFFFFF) {
DEBUG_ECHO_MSG("EEPROM Verify Erase failure for page ",page);
ee_Dump(page, (uint32_t *)addrflash); #ifdef EE_EMU_DEBUG
SERIAL_ECHO_START();
SERIAL_ECHOLNPAIR("EEPROM Verify Erase failure for page ",page);
ee_Dump( page,(uint32_t *) addrflash);
#endif
return false; return false;
} }
} }
return true; return true;
} }
static uint8_t ee_Read(uint32_t address, bool excludeRAMBuffer = false) {
static uint8_t ee_Read(uint32_t address, bool excludeRAMBuffer=false) {
uint32_t baddr; uint32_t baddr;
uint32_t blen; uint32_t blen;
@@ -462,7 +478,7 @@ static uint8_t ee_Read(uint32_t address, bool excludeRAMBuffer=false) {
for (int page = curPage - 1; page >= 0; --page) { for (int page = curPage - 1; page >= 0; --page) {
// Get a pointer to the flash page // Get a pointer to the flash page
uint8_t *pflash = (uint8_t*)getFlashStorage(page + curGroup * PagesPerGroup); uint8_t* pflash = (uint8_t*)getFlashStorage(page + curGroup * PagesPerGroup);
uint16_t i = 0; uint16_t i = 0;
while (i <= (PageSize - 4)) { /* (PageSize - 4) because otherwise, there is not enough room for data and headers */ while (i <= (PageSize - 4)) { /* (PageSize - 4) because otherwise, there is not enough room for data and headers */
@@ -495,7 +511,7 @@ static uint8_t ee_Read(uint32_t address, bool excludeRAMBuffer=false) {
return 0xFF; return 0xFF;
} }
static uint32_t ee_GetAddrRange(uint32_t address, bool excludeRAMBuffer=false) { static uint32_t ee_GetAddrRange(uint32_t address, bool excludeRAMBuffer = false) {
uint32_t baddr, uint32_t baddr,
blen, blen,
nextAddr = 0xFFFF, nextAddr = 0xFFFF,
@@ -542,7 +558,7 @@ static uint32_t ee_GetAddrRange(uint32_t address, bool excludeRAMBuffer=false) {
for (int page = curPage - 1; page >= 0; --page) { for (int page = curPage - 1; page >= 0; --page) {
// Get a pointer to the flash page // Get a pointer to the flash page
uint8_t *pflash = (uint8_t*)getFlashStorage(page + curGroup * PagesPerGroup); uint8_t* pflash = (uint8_t*)getFlashStorage(page + curGroup * PagesPerGroup);
uint16_t i = 0; uint16_t i = 0;
while (i <= (PageSize - 4)) { /* (PageSize - 4) because otherwise, there is not enough room for data and headers */ while (i <= (PageSize - 4)) { /* (PageSize - 4) because otherwise, there is not enough room for data and headers */
@@ -581,17 +597,17 @@ static uint32_t ee_GetAddrRange(uint32_t address, bool excludeRAMBuffer=false) {
} }
static bool ee_IsPageClean(int page) { static bool ee_IsPageClean(int page) {
uint32_t *pflash = (uint32_t*) getFlashStorage(page); uint32_t* pflash = (uint32_t*) getFlashStorage(page);
for (uint16_t i = 0; i < (PageSize >> 2); ++i) for (uint16_t i = 0; i < (PageSize >> 2); ++i)
if (*pflash++ != 0xFFFFFFFF) return false; if (*pflash++ != 0xFFFFFFFF) return false;
return true; return true;
} }
static bool ee_Flush(uint32_t overrideAddress = 0xFFFFFFFF, uint8_t overrideData=0xFF) { static bool ee_Flush(uint32_t overrideAddress = 0xFFFFFFFF, uint8_t overrideData = 0xFF) {
// Check if RAM buffer has something to be written // Check if RAM buffer has something to be written
bool isEmpty = true; bool isEmpty = true;
uint32_t *p = (uint32_t*) &buffer[0]; uint32_t* p = (uint32_t*) &buffer[0];
for (uint16_t j = 0; j < (PageSize >> 2); j++) { for (uint16_t j = 0; j < (PageSize >> 2); j++) {
if (*p++ != 0xFFFFFFFF) { if (*p++ != 0xFFFFFFFF) {
isEmpty = false; isEmpty = false;
@@ -913,8 +929,11 @@ static void ee_Init() {
// If all groups seem to be used, default to first group // If all groups seem to be used, default to first group
if (curGroup >= GroupCount) curGroup = 0; if (curGroup >= GroupCount) curGroup = 0;
DEBUG_ECHO_MSG("EEPROM Current Group: ",curGroup); #ifdef EE_EMU_DEBUG
DEBUG_FLUSH(); SERIAL_ECHO_START();
SERIAL_ECHOLNPAIR("EEPROM Current Group: ",curGroup);
SERIAL_FLUSH();
#endif
// Now, validate that all the other group pages are empty // Now, validate that all the other group pages are empty
for (int grp = 0; grp < GroupCount; grp++) { for (int grp = 0; grp < GroupCount; grp++) {
@@ -922,8 +941,11 @@ static void ee_Init() {
for (int page = 0; page < PagesPerGroup; page++) { for (int page = 0; page < PagesPerGroup; page++) {
if (!ee_IsPageClean(grp * PagesPerGroup + page)) { if (!ee_IsPageClean(grp * PagesPerGroup + page)) {
DEBUG_ECHO_MSG("EEPROM Page ", page, " not clean on group ", grp); #ifdef EE_EMU_DEBUG
DEBUG_FLUSH(); SERIAL_ECHO_START();
SERIAL_ECHOLNPAIR("EEPROM Page ", page, " not clean on group ", grp);
SERIAL_FLUSH();
#endif
ee_PageErase(grp * PagesPerGroup + page); ee_PageErase(grp * PagesPerGroup + page);
} }
} }
@@ -933,66 +955,66 @@ static void ee_Init() {
// and also validate that all the other ones are clean // and also validate that all the other ones are clean
for (curPage = 0; curPage < PagesPerGroup; curPage++) { for (curPage = 0; curPage < PagesPerGroup; curPage++) {
if (ee_IsPageClean(curGroup * PagesPerGroup + curPage)) { if (ee_IsPageClean(curGroup * PagesPerGroup + curPage)) {
ee_Dump(curGroup * PagesPerGroup + curPage, getFlashStorage(curGroup * PagesPerGroup + curPage)); #ifdef EE_EMU_DEBUG
ee_Dump(curGroup * PagesPerGroup + curPage, getFlashStorage(curGroup * PagesPerGroup + curPage));
#endif
break; break;
} }
} }
DEBUG_ECHO_MSG("EEPROM Active page: ", curPage); #ifdef EE_EMU_DEBUG
DEBUG_FLUSH(); SERIAL_ECHO_START();
SERIAL_ECHOLNPAIR("EEPROM Active page: ", curPage);
SERIAL_FLUSH();
#endif
// Make sure the pages following the first clean one are also clean // Make sure the pages following the first clean one are also clean
for (int page = curPage + 1; page < PagesPerGroup; page++) { for (int page = curPage + 1; page < PagesPerGroup; page++) {
if (!ee_IsPageClean(curGroup * PagesPerGroup + page)) { if (!ee_IsPageClean(curGroup * PagesPerGroup + page)) {
DEBUG_ECHO_MSG("EEPROM Page ", page, " not clean on active group ", curGroup); #ifdef EE_EMU_DEBUG
DEBUG_FLUSH(); SERIAL_ECHO_START();
ee_Dump(curGroup * PagesPerGroup + page, getFlashStorage(curGroup * PagesPerGroup + page)); SERIAL_ECHOLNPAIR("EEPROM Page ", page, " not clean on active group ", curGroup);
SERIAL_FLUSH();
ee_Dump(curGroup * PagesPerGroup + page, getFlashStorage(curGroup * PagesPerGroup + page));
#endif
ee_PageErase(curGroup * PagesPerGroup + page); ee_PageErase(curGroup * PagesPerGroup + page);
} }
} }
} }
/* PersistentStore -----------------------------------------------------------*/ uint8_t eeprom_read_byte(uint8_t* addr) {
ee_Init();
#include "../shared/eeprom_api.h" return ee_Read((uint32_t)addr);
#ifndef MARLIN_EEPROM_SIZE
#define MARLIN_EEPROM_SIZE 0x1000 // 4KB
#endif
size_t PersistentStore::capacity() { return MARLIN_EEPROM_SIZE; }
bool PersistentStore::access_start() { ee_Init(); return true; }
bool PersistentStore::access_finish() { ee_Flush(); return true; }
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
uint16_t written = 0;
while (size--) {
uint8_t * const p = (uint8_t * const)pos;
uint8_t v = *value;
if (v != ee_Read(uint32_t(p))) { // EEPROM has only ~100,000 write cycles, so only write bytes that have changed!
ee_Write(uint32_t(p), v);
if (++written & 0x7F) delay(2); else safe_delay(2); // Avoid triggering watchdog during long EEPROM writes
if (ee_Read(uint32_t(p)) != v) {
SERIAL_ECHO_MSG(STR_ERR_EEPROM_WRITE);
return true;
}
}
crc16(crc, &v, 1);
pos++;
value++;
}
return false;
} }
bool PersistentStore::read_data(int &pos, uint8_t *value, size_t size, uint16_t *crc, const bool writing/*=true*/) { void eeprom_write_byte(uint8_t* addr, uint8_t value) {
do { ee_Init();
uint8_t c = ee_Read(uint32_t(pos)); ee_Write((uint32_t)addr, value);
if (writing) *value = c; }
crc16(crc, &c, 1);
pos++; void eeprom_update_block(const void* __src, void* __dst, size_t __n) {
value++; uint8_t* dst = (uint8_t*)__dst;
} while (--size); const uint8_t* src = (const uint8_t*)__src;
return false; while (__n--) {
eeprom_write_byte(dst, *src);
++dst;
++src;
}
}
void eeprom_read_block(void* __dst, const void* __src, size_t __n) {
uint8_t* dst = (uint8_t*)__dst;
uint8_t* src = (uint8_t*)__src;
while (__n--) {
*dst = eeprom_read_byte(src);
++dst;
++src;
}
}
void eeprom_flush() {
ee_Flush();
} }
#endif // FLASH_EEPROM_EMULATION #endif // FLASH_EEPROM_EMULATION
#endif // ARDUINO_ARCH_SAM #endif // ARDUINO_ARCH_AVR

View File

@@ -14,18 +14,19 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/ */
/** /**
* HAL for Arduino Due and compatible (SAM3X8E) * Description: HAL for Arduino Due and compatible (SAM3X8E)
*
* For ARDUINO_ARCH_SAM
*/ */
#ifdef ARDUINO_ARCH_SAM #ifdef ARDUINO_ARCH_SAM
#include "../../inc/MarlinConfig.h" #include "../../inc/MarlinConfig.h"
#include "../../MarlinCore.h" #include "HAL.h"
#include <Wire.h> #include <Wire.h>
#include "usb/usb_task.h" #include "usb/usb_task.h"
@@ -34,33 +35,36 @@
// Public Variables // Public Variables
// ------------------------ // ------------------------
uint16_t MarlinHAL::adc_result; uint16_t HAL_adc_result;
// ------------------------ // ------------------------
// Public functions // Public functions
// ------------------------ // ------------------------
#if ENABLED(POSTMORTEM_DEBUGGING) // HAL initialization task
extern void install_min_serial(); void HAL_init() {
#endif // Initialize the USB stack
void MarlinHAL::init() {
#if ENABLED(SDSUPPORT) #if ENABLED(SDSUPPORT)
OUT_WRITE(SDSS, HIGH); // Try to set SDSS inactive before any other SPI users start up OUT_WRITE(SDSS, HIGH); // Try to set SDSS inactive before any other SPI users start up
#endif #endif
usb_task_init(); // Initialize the USB stack usb_task_init();
TERN_(POSTMORTEM_DEBUGGING, install_min_serial()); // Install the min serial handler
} }
void MarlinHAL::init_board() { // HAL idle task
#ifdef BOARD_INIT void HAL_idletask() {
BOARD_INIT(); // Perform USB stack housekeeping
#endif usb_task_idle();
} }
void MarlinHAL::idletask() { usb_task_idle(); } // Perform USB stack housekeeping // Disable interrupts
void cli() { noInterrupts(); }
uint8_t MarlinHAL::get_reset_source() { // Enable interrupts
void sei() { interrupts(); }
void HAL_clear_reset_source() { }
uint8_t HAL_get_reset_source() {
switch ((RSTC->RSTC_SR >> 8) & 0x07) { switch ((RSTC->RSTC_SR >> 8) & 0x07) {
case 0: return RST_POWER_ON; case 0: return RST_POWER_ON;
case 1: return RST_BACKUP; case 1: return RST_BACKUP;
@@ -71,105 +75,11 @@ uint8_t MarlinHAL::get_reset_source() {
} }
} }
void MarlinHAL::reboot() { rstc_start_software_reset(RSTC); } void _delay_ms(const int delay_ms) {
// Todo: port for Due?
// ------------------------ delay(delay_ms);
// 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 "C" {
extern unsigned int _ebss; // end of bss section extern unsigned int _ebss; // end of bss section
} }
@@ -181,21 +91,16 @@ int freeMemory() {
} }
// ------------------------ // ------------------------
// Serial Ports // ADC
// ------------------------ // ------------------------
// Forward the default serial ports void HAL_adc_start_conversion(const uint8_t ch) {
#if USING_HW_SERIAL0 HAL_adc_result = analogRead(ch);
DefaultSerial1 MSerial0(false, Serial); }
#endif
#if USING_HW_SERIAL1 uint16_t HAL_adc_get_result() {
DefaultSerial2 MSerial1(false, Serial1); // nop
#endif return HAL_adc_result;
#if USING_HW_SERIAL2 }
DefaultSerial3 MSerial2(false, Serial2);
#endif
#if USING_HW_SERIAL3
DefaultSerial4 MSerial3(false, Serial3);
#endif
#endif // ARDUINO_ARCH_SAM #endif // ARDUINO_ARCH_SAM

View File

@@ -16,122 +16,151 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#pragma once #pragma once
/** /**
* HAL for Arduino Due and compatible (SAM3X8E) * Description: HAL for Arduino Due and compatible (SAM3X8E)
*
* For ARDUINO_ARCH_SAM
*/ */
#define CPU_32_BIT #define CPU_32_BIT
#include "../shared/Marduino.h" #include "../shared/Marduino.h"
#include "../shared/eeprom_if.h"
#include "../shared/math_32bit.h" #include "../shared/math_32bit.h"
#include "../shared/HAL_SPI.h" #include "../shared/HAL_SPI.h"
#include "fastio.h" #include "fastio.h"
#include "watchdog.h"
#include "timers.h"
#include <stdint.h> #include <stdint.h>
#include "../../core/serial_hook.h" // Define MYSERIAL0/1 before MarlinSerial includes!
// ------------------------
// Serial ports
// ------------------------
typedef ForwardSerial1Class< decltype(Serial) > DefaultSerial1;
typedef ForwardSerial1Class< decltype(Serial1) > DefaultSerial2;
typedef ForwardSerial1Class< decltype(Serial2) > DefaultSerial3;
typedef ForwardSerial1Class< decltype(Serial3) > DefaultSerial4;
extern DefaultSerial1 MSerial0;
extern DefaultSerial2 MSerial1;
extern DefaultSerial3 MSerial2;
extern DefaultSerial4 MSerial3;
#define _MSERIAL(X) MSerial##X
#define MSERIAL(X) _MSERIAL(X)
#if SERIAL_PORT == -1 || ENABLED(EMERGENCY_PARSER) #if SERIAL_PORT == -1 || ENABLED(EMERGENCY_PARSER)
#define MYSERIAL1 customizedSerial1 #define MYSERIAL0 customizedSerial1
#elif WITHIN(SERIAL_PORT, 0, 3) #elif SERIAL_PORT == 0
#define MYSERIAL1 MSERIAL(SERIAL_PORT) #define MYSERIAL0 Serial
#elif SERIAL_PORT == 1
#define MYSERIAL0 Serial1
#elif SERIAL_PORT == 2
#define MYSERIAL0 Serial2
#elif SERIAL_PORT == 3
#define MYSERIAL0 Serial3
#else #else
#error "The required SERIAL_PORT must be from 0 to 3, or -1 for USB Serial." #error "The required SERIAL_PORT must be from -1 to 3. Please update your configuration."
#endif #endif
#ifdef SERIAL_PORT_2 #ifdef SERIAL_PORT_2
#if SERIAL_PORT_2 == -1 || ENABLED(EMERGENCY_PARSER) #if SERIAL_PORT_2 == SERIAL_PORT
#define MYSERIAL2 customizedSerial2 #error "SERIAL_PORT_2 must be different from SERIAL_PORT. Please update your configuration."
#elif WITHIN(SERIAL_PORT_2, 0, 3) #elif SERIAL_PORT_2 == -1 || ENABLED(EMERGENCY_PARSER)
#define MYSERIAL2 MSERIAL(SERIAL_PORT_2) #define MYSERIAL1 customizedSerial2
#elif SERIAL_PORT_2 == 0
#define MYSERIAL1 Serial
#elif SERIAL_PORT_2 == 1
#define MYSERIAL1 Serial1
#elif SERIAL_PORT_2 == 2
#define MYSERIAL1 Serial2
#elif SERIAL_PORT_2 == 3
#define MYSERIAL1 Serial3
#else #else
#error "SERIAL_PORT_2 must be from 0 to 3, or -1 for USB Serial." #error "SERIAL_PORT_2 must be from -1 to 3. Please update your configuration."
#endif #endif
#define NUM_SERIAL 2
#else
#define NUM_SERIAL 1
#endif #endif
#ifdef SERIAL_PORT_3 #ifdef DGUS_SERIAL_PORT
#if SERIAL_PORT_3 == -1 || ENABLED(EMERGENCY_PARSER) #if DGUS_SERIAL_PORT == SERIAL_PORT
#define MYSERIAL3 customizedSerial3 #error "DGUS_SERIAL_PORT must be different from SERIAL_PORT. Please update your configuration."
#elif WITHIN(SERIAL_PORT_3, 0, 3) #elif defined(SERIAL_PORT_2) && DGUS_SERIAL_PORT == SERIAL_PORT_2
#define MYSERIAL3 MSERIAL(SERIAL_PORT_3) #error "DGUS_SERIAL_PORT must be different than SERIAL_PORT_2. Please update your configuration."
#elif DGUS_SERIAL_PORT == -1
#define DGUS_SERIAL internalDgusSerial
#elif DGUS_SERIAL_PORT == 0
#define DGUS_SERIAL Serial
#elif DGUS_SERIAL_PORT == 1
#define DGUS_SERIAL Serial1
#elif DGUS_SERIAL_PORT == 2
#define DGUS_SERIAL Serial2
#elif DGUS_SERIAL_PORT == 3
#define DGUS_SERIAL Serial3
#else #else
#error "SERIAL_PORT_3 must be from 0 to 3, or -1 for USB Serial." #error "DGUS_SERIAL_PORT must be from -1 to 3. Please update your configuration."
#endif
#endif
#ifdef MMU2_SERIAL_PORT
#if WITHIN(MMU2_SERIAL_PORT, 0, 3)
#define MMU2_SERIAL MSERIAL(MMU2_SERIAL_PORT)
#else
#error "MMU2_SERIAL_PORT must be from 0 to 3."
#endif
#endif
#ifdef LCD_SERIAL_PORT
#if WITHIN(LCD_SERIAL_PORT, 0, 3)
#define LCD_SERIAL MSERIAL(LCD_SERIAL_PORT)
#else
#error "LCD_SERIAL_PORT must be from 0 to 3."
#endif #endif
#endif #endif
#include "MarlinSerial.h" #include "MarlinSerial.h"
#include "MarlinSerialUSB.h" #include "MarlinSerialUSB.h"
// ------------------------ // On AVR this is in math.h?
// Types #define square(x) ((x)*(x))
// ------------------------
#ifndef strncpy_P
#define strncpy_P(dest, src, num) strncpy((dest), (src), (num))
#endif
// Fix bug in pgm_read_ptr
#undef pgm_read_ptr
#define pgm_read_ptr(addr) (*((void**)(addr)))
#undef pgm_read_word
#define pgm_read_word(addr) (*((uint16_t*)(addr)))
typedef int8_t pin_t; typedef int8_t pin_t;
#define SHARED_SERVOS HAS_SERVOS // Use shared/servos.cpp #define SHARED_SERVOS HAS_SERVOS
#define HAL_SERVO_LIB Servo
class Servo;
typedef Servo hal_servo_t;
// //
// Interrupts // Interrupts
// //
#define sei() interrupts() #define CRITICAL_SECTION_START() uint32_t primask = __get_PRIMASK(); __disable_irq()
#define cli() noInterrupts() #define CRITICAL_SECTION_END() if (!primask) __enable_irq()
#define ISRS_ENABLED() (!__get_PRIMASK())
#define ENABLE_ISRS() __enable_irq()
#define DISABLE_ISRS() __disable_irq()
#define CRITICAL_SECTION_START() const bool _irqon = hal.isr_state(); hal.isr_off() void cli(); // Disable interrupts
#define CRITICAL_SECTION_END() if (_irqon) hal.isr_on() void sei(); // Enable interrupts
void HAL_clear_reset_source(); // clear reset reason
uint8_t HAL_get_reset_source(); // get reset reason
//
// EEPROM
//
void eeprom_write_byte(uint8_t *pos, unsigned char value);
uint8_t eeprom_read_byte(uint8_t *pos);
void eeprom_read_block (void *__dst, const void *__src, size_t __n);
void eeprom_update_block (const void *__src, void *__dst, size_t __n);
// //
// ADC // ADC
// //
#define HAL_ADC_VREF 3.3 extern uint16_t HAL_adc_result; // result of last ADC conversion
#define HAL_ADC_RESOLUTION 10
#ifndef analogInputToDigitalPin #ifndef analogInputToDigitalPin
#define analogInputToDigitalPin(p) ((p < 12U) ? (p) + 54U : -1) #define analogInputToDigitalPin(p) ((p < 12u) ? (p) + 54u : -1)
#endif #endif
#define HAL_ANALOG_SELECT(ch)
inline void HAL_adc_init() {}//todo
#define HAL_START_ADC(ch) HAL_adc_start_conversion(ch)
#define HAL_ADC_RESOLUTION 10
#define HAL_READ_ADC() HAL_adc_result
#define HAL_ADC_READY() true
void HAL_adc_start_conversion(const uint8_t ch);
uint16_t HAL_adc_get_result();
// //
// Pin Mapping for M42, M43, M226 // Pin Map
// //
#define GET_PIN_MAP_PIN(index) index #define GET_PIN_MAP_PIN(index) index
#define GET_PIN_MAP_INDEX(pin) pin #define GET_PIN_MAP_INDEX(pin) pin
@@ -140,18 +169,23 @@ typedef Servo hal_servo_t;
// //
// Tone // Tone
// //
void toneInit();
void tone(const pin_t _pin, const unsigned int frequency, const unsigned long duration=0); void tone(const pin_t _pin, const unsigned int frequency, const unsigned long duration=0);
void noTone(const pin_t _pin); void noTone(const pin_t _pin);
// ------------------------ // Enable hooks into idle and setup for HAL
// Class Utilities #define HAL_IDLETASK 1
// ------------------------ void HAL_idletask();
void HAL_init();
//
// Utility functions
//
void _delay_ms(const int delay);
#pragma GCC diagnostic push #pragma GCC diagnostic push
#if GCC_VERSION <= 50000 #pragma GCC diagnostic ignored "-Wunused-function"
#pragma GCC diagnostic ignored "-Wunused-function" int freeMemory();
#endif
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#ifdef __cplusplus #ifdef __cplusplus
@@ -161,73 +195,3 @@ char *dtostrf(double __val, signed char __width, unsigned char __prec, char *__s
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
// Return free RAM between end of heap (or end bss) and whatever is current
int freeMemory();
// ------------------------
// MarlinHAL Class
// ------------------------
class MarlinHAL {
public:
// Earliest possible init, before setup()
MarlinHAL() {}
// Watchdog
static void watchdog_init() IF_DISABLED(USE_WATCHDOG, {});
static void watchdog_refresh() IF_DISABLED(USE_WATCHDOG, {});
static void init(); // Called early in setup()
static void init_board(); // Called less early in setup()
static void reboot(); // Restart the firmware
// Interrupts
static bool isr_state() { return !__get_PRIMASK(); }
static void isr_on() { __enable_irq(); }
static void isr_off() { __disable_irq(); }
static void delay_ms(const int ms) { delay(ms); }
// Tasks, called from idle()
static void idletask();
// Reset
static uint8_t get_reset_source();
static void clear_reset_source() {}
// Free SRAM
static int freeMemory() { return ::freeMemory(); }
//
// ADC Methods
//
static uint16_t adc_result;
// Called by Temperature::init once at startup
static void adc_init() {}
// Called by Temperature::init for each sensor at startup
static void adc_enable(const uint8_t ch) {}
// Begin ADC sampling on the given channel. Called from Temperature::isr!
static void adc_start(const uint8_t ch) { adc_result = analogRead(ch); }
// Is the ADC ready for reading?
static bool adc_ready() { return true; }
// The current value of the ADC register
static uint16_t adc_value() { return adc_result; }
/**
* Set the PWM duty cycle for the pin to the given value.
* No inverting the duty cycle in this HAL.
* No changing the maximum size of the provided value to enable finer PWM duty control in this HAL.
*/
static void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t=255, const bool=false) {
analogWrite(pin, v);
}
};

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@@ -30,7 +30,9 @@
*/ */
/** /**
* HAL for Arduino Due and compatible (SAM3X8E) * Description: HAL for Arduino Due and compatible (SAM3X8E)
*
* For ARDUINO_ARCH_SAM
*/ */
#ifdef ARDUINO_ARCH_SAM #ifdef ARDUINO_ARCH_SAM
@@ -54,8 +56,8 @@
#pragma GCC optimize (3) #pragma GCC optimize (3)
typedef uint8_t (*pfnSpiTransfer)(uint8_t b); typedef uint8_t (*pfnSpiTransfer)(uint8_t b);
typedef void (*pfnSpiRxBlock)(uint8_t *buf, uint32_t nbyte); typedef void (*pfnSpiRxBlock)(uint8_t* buf, uint32_t nbyte);
typedef void (*pfnSpiTxBlock)(const uint8_t *buf, uint32_t nbyte); typedef void (*pfnSpiTxBlock)(const uint8_t* buf, uint32_t nbyte);
/* ---------------- Macros to be able to access definitions from asm */ /* ---------------- Macros to be able to access definitions from asm */
#define _PORT(IO) DIO ## IO ## _WPORT #define _PORT(IO) DIO ## IO ## _WPORT
@@ -67,10 +69,10 @@
// run at ~8 .. ~10Mhz - Tx version (Rx data discarded) // run at ~8 .. ~10Mhz - Tx version (Rx data discarded)
static uint8_t spiTransferTx0(uint8_t bout) { // using Mode 0 static uint8_t spiTransferTx0(uint8_t bout) { // using Mode 0
uint32_t MOSI_PORT_PLUS30 = ((uint32_t) PORT(SD_MOSI_PIN)) + 0x30; /* SODR of port */ uint32_t MOSI_PORT_PLUS30 = ((uint32_t) PORT(MOSI_PIN)) + 0x30; /* SODR of port */
uint32_t MOSI_MASK = PIN_MASK(SD_MOSI_PIN); uint32_t MOSI_MASK = PIN_MASK(MOSI_PIN);
uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SD_SCK_PIN)) + 0x30; /* SODR of port */ uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
uint32_t SCK_MASK = PIN_MASK(SD_SCK_PIN); uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
uint32_t idx = 0; uint32_t idx = 0;
/* Negate bout, as the assembler requires a negated value */ /* Negate bout, as the assembler requires a negated value */
@@ -152,9 +154,9 @@
static uint8_t spiTransferRx0(uint8_t) { // using Mode 0 static uint8_t spiTransferRx0(uint8_t) { // using Mode 0
uint32_t bin = 0; uint32_t bin = 0;
uint32_t work = 0; uint32_t work = 0;
uint32_t BITBAND_MISO_PORT = BITBAND_ADDRESS( ((uint32_t)PORT(SD_MISO_PIN))+0x3C, PIN_SHIFT(SD_MISO_PIN)); /* PDSR of port in bitband area */ uint32_t BITBAND_MISO_PORT = BITBAND_ADDRESS( ((uint32_t)PORT(MISO_PIN))+0x3C, PIN_SHIFT(MISO_PIN)); /* PDSR of port in bitband area */
uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SD_SCK_PIN)) + 0x30; /* SODR of port */ uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
uint32_t SCK_MASK = PIN_MASK(SD_SCK_PIN); uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
/* The software SPI routine */ /* The software SPI routine */
__asm__ __volatile__( __asm__ __volatile__(
@@ -223,36 +225,36 @@
static uint8_t spiTransfer1(uint8_t b) { // using Mode 0 static uint8_t spiTransfer1(uint8_t b) { // using Mode 0
int bits = 8; int bits = 8;
do { do {
WRITE(SD_MOSI_PIN, b & 0x80); WRITE(MOSI_PIN, b & 0x80);
b <<= 1; // little setup time b <<= 1; // little setup time
WRITE(SD_SCK_PIN, HIGH); WRITE(SCK_PIN, HIGH);
DELAY_NS(125); // 10 cycles @ 84mhz DELAY_NS(125); // 10 cycles @ 84mhz
b |= (READ(SD_MISO_PIN) != 0); b |= (READ(MISO_PIN) != 0);
WRITE(SD_SCK_PIN, LOW); WRITE(SCK_PIN, LOW);
DELAY_NS(125); // 10 cycles @ 84mhz DELAY_NS(125); // 10 cycles @ 84mhz
} while (--bits); } while (--bits);
return b; return b;
} }
// all the others // all the others
static uint16_t spiDelayNS = 4000; // 4000ns => 125khz static uint32_t spiDelayCyclesX4 = (F_CPU) / 1000000; // 4µs => 125khz
static uint8_t spiTransferX(uint8_t b) { // using Mode 0 static uint8_t spiTransferX(uint8_t b) { // using Mode 0
int bits = 8; int bits = 8;
do { do {
WRITE(SD_MOSI_PIN, b & 0x80); WRITE(MOSI_PIN, b & 0x80);
b <<= 1; // little setup time b <<= 1; // little setup time
WRITE(SD_SCK_PIN, HIGH); WRITE(SCK_PIN, HIGH);
DELAY_NS(spiDelayNS); __delay_4cycles(spiDelayCyclesX4);
b |= (READ(SD_MISO_PIN) != 0); b |= (READ(MISO_PIN) != 0);
WRITE(SD_SCK_PIN, LOW); WRITE(SCK_PIN, LOW);
DELAY_NS(spiDelayNS); __delay_4cycles(spiDelayCyclesX4);
} while (--bits); } while (--bits);
return b; return b;
} }
@@ -268,11 +270,11 @@
static pfnSpiTransfer spiTransferTx = (pfnSpiTransfer)spiTransferX; static pfnSpiTransfer spiTransferTx = (pfnSpiTransfer)spiTransferX;
// Block transfers run at ~8 .. ~10Mhz - Tx version (Rx data discarded) // Block transfers run at ~8 .. ~10Mhz - Tx version (Rx data discarded)
static void spiTxBlock0(const uint8_t *ptr, uint32_t todo) { static void spiTxBlock0(const uint8_t* ptr, uint32_t todo) {
uint32_t MOSI_PORT_PLUS30 = ((uint32_t) PORT(SD_MOSI_PIN)) + 0x30; /* SODR of port */ uint32_t MOSI_PORT_PLUS30 = ((uint32_t) PORT(MOSI_PIN)) + 0x30; /* SODR of port */
uint32_t MOSI_MASK = PIN_MASK(SD_MOSI_PIN); uint32_t MOSI_MASK = PIN_MASK(MOSI_PIN);
uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SD_SCK_PIN)) + 0x30; /* SODR of port */ uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
uint32_t SCK_MASK = PIN_MASK(SD_SCK_PIN); uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
uint32_t work = 0; uint32_t work = 0;
uint32_t txval = 0; uint32_t txval = 0;
@@ -347,12 +349,12 @@
); );
} }
static void spiRxBlock0(uint8_t *ptr, uint32_t todo) { static void spiRxBlock0(uint8_t* ptr, uint32_t todo) {
uint32_t bin = 0; uint32_t bin = 0;
uint32_t work = 0; uint32_t work = 0;
uint32_t BITBAND_MISO_PORT = BITBAND_ADDRESS( ((uint32_t)PORT(SD_MISO_PIN))+0x3C, PIN_SHIFT(SD_MISO_PIN)); /* PDSR of port in bitband area */ uint32_t BITBAND_MISO_PORT = BITBAND_ADDRESS( ((uint32_t)PORT(MISO_PIN))+0x3C, PIN_SHIFT(MISO_PIN)); /* PDSR of port in bitband area */
uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SD_SCK_PIN)) + 0x30; /* SODR of port */ uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SCK_PIN)) + 0x30; /* SODR of port */
uint32_t SCK_MASK = PIN_MASK(SD_SCK_PIN); uint32_t SCK_MASK = PIN_MASK(SCK_PIN);
/* The software SPI routine */ /* The software SPI routine */
__asm__ __volatile__( __asm__ __volatile__(
@@ -423,48 +425,48 @@
); );
} }
static void spiTxBlockX(const uint8_t *buf, uint32_t todo) { static void spiTxBlockX(const uint8_t* buf, uint32_t todo) {
do { do {
(void)spiTransferTx(*buf++); (void)spiTransferTx(*buf++);
} while (--todo); } while (--todo);
} }
static void spiRxBlockX(uint8_t *buf, uint32_t todo) { static void spiRxBlockX(uint8_t* buf, uint32_t todo) {
do { do {
*buf++ = spiTransferRx(0xFF); *buf++ = spiTransferRx(0xFF);
} while (--todo); } while (--todo);
} }
// Pointers to generic functions for block transfers // Pointers to generic functions for block tranfers
static pfnSpiTxBlock spiTxBlock = (pfnSpiTxBlock)spiTxBlockX; static pfnSpiTxBlock spiTxBlock = (pfnSpiTxBlock)spiTxBlockX;
static pfnSpiRxBlock spiRxBlock = (pfnSpiRxBlock)spiRxBlockX; static pfnSpiRxBlock spiRxBlock = (pfnSpiRxBlock)spiRxBlockX;
#if MB(ALLIGATOR) #if MB(ALLIGATOR)
#define _SS_WRITE(S) WRITE(SD_SS_PIN, S) #define _SS_WRITE(S) WRITE(SS_PIN, S)
#else #else
#define _SS_WRITE(S) NOOP #define _SS_WRITE(S) NOOP
#endif #endif
void spiBegin() { void spiBegin() {
SET_OUTPUT(SD_SS_PIN); SET_OUTPUT(SS_PIN);
_SS_WRITE(HIGH); _SS_WRITE(HIGH);
SET_OUTPUT(SD_SCK_PIN); SET_OUTPUT(SCK_PIN);
SET_INPUT(SD_MISO_PIN); SET_INPUT(MISO_PIN);
SET_OUTPUT(SD_MOSI_PIN); SET_OUTPUT(MOSI_PIN);
} }
uint8_t spiRec() { uint8_t spiRec() {
_SS_WRITE(LOW); _SS_WRITE(LOW);
WRITE(SD_MOSI_PIN, HIGH); // Output 1s 1 WRITE(MOSI_PIN, HIGH); // Output 1s 1
uint8_t b = spiTransferRx(0xFF); uint8_t b = spiTransferRx(0xFF);
_SS_WRITE(HIGH); _SS_WRITE(HIGH);
return b; return b;
} }
void spiRead(uint8_t *buf, uint16_t nbyte) { void spiRead(uint8_t* buf, uint16_t nbyte) {
if (nbyte) { if (nbyte) {
_SS_WRITE(LOW); _SS_WRITE(LOW);
WRITE(SD_MOSI_PIN, HIGH); // Output 1s 1 WRITE(MOSI_PIN, HIGH); // Output 1s 1
spiRxBlock(buf, nbyte); spiRxBlock(buf, nbyte);
_SS_WRITE(HIGH); _SS_WRITE(HIGH);
} }
@@ -476,7 +478,7 @@
_SS_WRITE(HIGH); _SS_WRITE(HIGH);
} }
void spiSendBlock(uint8_t token, const uint8_t *buf) { void spiSendBlock(uint8_t token, const uint8_t* buf) {
_SS_WRITE(LOW); _SS_WRITE(LOW);
(void)spiTransferTx(token); (void)spiTransferTx(token);
spiTxBlock(buf, 512); spiTxBlock(buf, 512);
@@ -508,7 +510,7 @@
spiRxBlock = (pfnSpiRxBlock)spiRxBlockX; spiRxBlock = (pfnSpiRxBlock)spiRxBlockX;
break; break;
default: default:
spiDelayNS = 4000 >> (6 - spiRate); // spiRate of 2 gives the maximum error with current CPU spiDelayCyclesX4 = ((F_CPU) / 1000000) >> (6 - spiRate);
spiTransferTx = (pfnSpiTransfer)spiTransferX; spiTransferTx = (pfnSpiTransfer)spiTransferX;
spiTransferRx = (pfnSpiTransfer)spiTransferX; spiTransferRx = (pfnSpiTransfer)spiTransferX;
spiTxBlock = (pfnSpiTxBlock)spiTxBlockX; spiTxBlock = (pfnSpiTxBlock)spiTxBlockX;
@@ -517,8 +519,8 @@
} }
_SS_WRITE(HIGH); _SS_WRITE(HIGH);
WRITE(SD_MOSI_PIN, HIGH); WRITE(MOSI_PIN, HIGH);
WRITE(SD_SCK_PIN, LOW); WRITE(SCK_PIN, LOW);
} }
/** Begin SPI transaction, set clock, bit order, data mode */ /** Begin SPI transaction, set clock, bit order, data mode */
@@ -573,34 +575,38 @@
// Configure SPI pins // Configure SPI pins
PIO_Configure( PIO_Configure(
g_APinDescription[SD_SCK_PIN].pPort, g_APinDescription[SCK_PIN].pPort,
g_APinDescription[SD_SCK_PIN].ulPinType, g_APinDescription[SCK_PIN].ulPinType,
g_APinDescription[SD_SCK_PIN].ulPin, g_APinDescription[SCK_PIN].ulPin,
g_APinDescription[SD_SCK_PIN].ulPinConfiguration); g_APinDescription[SCK_PIN].ulPinConfiguration);
PIO_Configure( PIO_Configure(
g_APinDescription[SD_MOSI_PIN].pPort, g_APinDescription[MOSI_PIN].pPort,
g_APinDescription[SD_MOSI_PIN].ulPinType, g_APinDescription[MOSI_PIN].ulPinType,
g_APinDescription[SD_MOSI_PIN].ulPin, g_APinDescription[MOSI_PIN].ulPin,
g_APinDescription[SD_MOSI_PIN].ulPinConfiguration); g_APinDescription[MOSI_PIN].ulPinConfiguration);
PIO_Configure( PIO_Configure(
g_APinDescription[SD_MISO_PIN].pPort, g_APinDescription[MISO_PIN].pPort,
g_APinDescription[SD_MISO_PIN].ulPinType, g_APinDescription[MISO_PIN].ulPinType,
g_APinDescription[SD_MISO_PIN].ulPin, g_APinDescription[MISO_PIN].ulPin,
g_APinDescription[SD_MISO_PIN].ulPinConfiguration); g_APinDescription[MISO_PIN].ulPinConfiguration);
// set master mode, peripheral select, fault detection // set master mode, peripheral select, fault detection
SPI_Configure(SPI0, ID_SPI0, SPI_MR_MSTR | SPI_MR_MODFDIS | SPI_MR_PS); SPI_Configure(SPI0, ID_SPI0, SPI_MR_MSTR | SPI_MR_MODFDIS | SPI_MR_PS);
SPI_Enable(SPI0); SPI_Enable(SPI0);
SET_OUTPUT(DAC0_SYNC_PIN); SET_OUTPUT(DAC0_SYNC);
#if HAS_MULTI_EXTRUDER #if EXTRUDERS > 1
OUT_WRITE(DAC1_SYNC_PIN, HIGH); SET_OUTPUT(DAC1_SYNC);
WRITE(DAC1_SYNC, HIGH);
#endif #endif
WRITE(DAC0_SYNC_PIN, HIGH); SET_OUTPUT(SPI_EEPROM1_CS);
OUT_WRITE(SPI_EEPROM1_CS_PIN, HIGH); SET_OUTPUT(SPI_EEPROM2_CS);
OUT_WRITE(SPI_EEPROM2_CS_PIN, HIGH); SET_OUTPUT(SPI_FLASH_CS);
OUT_WRITE(SPI_FLASH_CS_PIN, HIGH); WRITE(DAC0_SYNC, HIGH);
WRITE(SD_SS_PIN, HIGH); WRITE(SPI_EEPROM1_CS, HIGH);
WRITE(SPI_EEPROM2_CS, HIGH);
WRITE(SPI_FLASH_CS, HIGH);
WRITE(SS_PIN, HIGH);
OUT_WRITE(SDSS, LOW); OUT_WRITE(SDSS, LOW);
@@ -639,7 +645,7 @@
} }
// Read from SPI into buffer // Read from SPI into buffer
void spiRead(uint8_t *buf, uint16_t nbyte) { void spiRead(uint8_t* buf, uint16_t nbyte) {
if (!nbyte) return; if (!nbyte) return;
--nbyte; --nbyte;
for (int i = 0; i < nbyte; i++) { for (int i = 0; i < nbyte; i++) {
@@ -662,7 +668,7 @@
//DELAY_US(1U); //DELAY_US(1U);
} }
void spiSend(const uint8_t *buf, size_t nbyte) { void spiSend(const uint8_t* buf, size_t nbyte) {
if (!nbyte) return; if (!nbyte) return;
--nbyte; --nbyte;
for (size_t i = 0; i < nbyte; i++) { for (size_t i = 0; i < nbyte; i++) {
@@ -683,7 +689,7 @@
FLUSH_RX(); FLUSH_RX();
} }
void spiSend(uint32_t chan, const uint8_t *buf, size_t nbyte) { void spiSend(uint32_t chan, const uint8_t* buf, size_t nbyte) {
if (!nbyte) return; if (!nbyte) return;
--nbyte; --nbyte;
for (size_t i = 0; i < nbyte; i++) { for (size_t i = 0; i < nbyte; i++) {
@@ -696,7 +702,7 @@
} }
// Write from buffer to SPI // Write from buffer to SPI
void spiSendBlock(uint8_t token, const uint8_t *buf) { void spiSendBlock(uint8_t token, const uint8_t* buf) {
SPI0->SPI_TDR = (uint32_t)token | SPI_PCS(SPI_CHAN); SPI0->SPI_TDR = (uint32_t)token | SPI_PCS(SPI_CHAN);
WHILE_TX(0); WHILE_TX(0);
//WHILE_RX(0); //WHILE_RX(0);
@@ -753,6 +759,7 @@
* *
* All of the above can be avoided by defining FORCE_SOFT_SPI to force the * All of the above can be avoided by defining FORCE_SOFT_SPI to force the
* display to use software SPI. * display to use software SPI.
*
*/ */
void spiInit(uint8_t spiRate=6) { // Default to slowest rate if not specified) void spiInit(uint8_t spiRate=6) { // Default to slowest rate if not specified)
@@ -795,19 +802,19 @@
uint8_t spiRec() { return (uint8_t)spiTransfer(0xFF); } uint8_t spiRec() { return (uint8_t)spiTransfer(0xFF); }
void spiRead(uint8_t *buf, uint16_t nbyte) { void spiRead(uint8_t* buf, uint16_t nbyte) {
for (int i = 0; i < nbyte; i++) for (int i = 0; i < nbyte; i++)
buf[i] = spiTransfer(0xFF); buf[i] = spiTransfer(0xFF);
} }
void spiSend(uint8_t data) { spiTransfer(data); } void spiSend(uint8_t data) { spiTransfer(data); }
void spiSend(const uint8_t *buf, size_t nbyte) { void spiSend(const uint8_t* buf, size_t nbyte) {
for (uint16_t i = 0; i < nbyte; i++) for (uint16_t i = 0; i < nbyte; i++)
spiTransfer(buf[i]); spiTransfer(buf[i]);
} }
void spiSendBlock(uint8_t token, const uint8_t *buf) { void spiSendBlock(uint8_t token, const uint8_t* buf) {
spiTransfer(token); spiTransfer(token);
for (uint16_t i = 0; i < 512; i++) for (uint16_t i = 0; i < 512; i++)
spiTransfer(buf[i]); spiTransfer(buf[i]);

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#pragma once #pragma once

View File

@@ -1,26 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#include <SPI.h>
using MarlinSPI = SPIClass;

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@@ -382,7 +382,7 @@ void MarlinSerial<Cfg>::flush() {
} }
template<typename Cfg> template<typename Cfg>
size_t MarlinSerial<Cfg>::write(const uint8_t c) { void MarlinSerial<Cfg>::write(const uint8_t c) {
_written = true; _written = true;
if (Cfg::TX_SIZE == 0) { if (Cfg::TX_SIZE == 0) {
@@ -400,13 +400,13 @@ size_t MarlinSerial<Cfg>::write(const uint8_t c) {
// XOFF char at the RX isr, but it is properly handled there // XOFF char at the RX isr, but it is properly handled there
if (!(HWUART->UART_IMR & UART_IMR_TXRDY) && (HWUART->UART_SR & UART_SR_TXRDY)) { if (!(HWUART->UART_IMR & UART_IMR_TXRDY) && (HWUART->UART_SR & UART_SR_TXRDY)) {
HWUART->UART_THR = c; HWUART->UART_THR = c;
return 1; return;
} }
const uint8_t i = (tx_buffer.head + 1) & (Cfg::TX_SIZE - 1); const uint8_t i = (tx_buffer.head + 1) & (Cfg::TX_SIZE - 1);
// If global interrupts are disabled (as the result of being called from an ISR)... // If global interrupts are disabled (as the result of being called from an ISR)...
if (!hal.isr_state()) { if (!ISRS_ENABLED()) {
// Make room by polling if it is possible to transmit, and do so! // Make room by polling if it is possible to transmit, and do so!
while (i == tx_buffer.tail) { while (i == tx_buffer.tail) {
@@ -428,7 +428,6 @@ size_t MarlinSerial<Cfg>::write(const uint8_t c) {
// Enable TX isr - Non atomic, but it will eventually enable TX isr // Enable TX isr - Non atomic, but it will eventually enable TX isr
HWUART->UART_IER = UART_IER_TXRDY; HWUART->UART_IER = UART_IER_TXRDY;
} }
return 1;
} }
template<typename Cfg> template<typename Cfg>
@@ -454,7 +453,7 @@ void MarlinSerial<Cfg>::flushTX() {
if (!_written) return; if (!_written) return;
// If global interrupts are disabled (as the result of being called from an ISR)... // If global interrupts are disabled (as the result of being called from an ISR)...
if (!hal.isr_state()) { if (!ISRS_ENABLED()) {
// Wait until everything was transmitted - We must do polling, as interrupts are disabled // Wait until everything was transmitted - We must do polling, as interrupts are disabled
while (tx_buffer.head != tx_buffer.tail || !(HWUART->UART_SR & UART_SR_TXEMPTY)) { while (tx_buffer.head != tx_buffer.tail || !(HWUART->UART_SR & UART_SR_TXEMPTY)) {
@@ -474,21 +473,169 @@ void MarlinSerial<Cfg>::flushTX() {
} }
} }
/**
* Imports from print.h
*/
template<typename Cfg>
void MarlinSerial<Cfg>::print(char c, int base) {
print((long)c, base);
}
template<typename Cfg>
void MarlinSerial<Cfg>::print(unsigned char b, int base) {
print((unsigned long)b, base);
}
template<typename Cfg>
void MarlinSerial<Cfg>::print(int n, int base) {
print((long)n, base);
}
template<typename Cfg>
void MarlinSerial<Cfg>::print(unsigned int n, int base) {
print((unsigned long)n, base);
}
template<typename Cfg>
void MarlinSerial<Cfg>::print(long n, int base) {
if (base == 0) write(n);
else if (base == 10) {
if (n < 0) { print('-'); n = -n; }
printNumber(n, 10);
}
else
printNumber(n, base);
}
template<typename Cfg>
void MarlinSerial<Cfg>::print(unsigned long n, int base) {
if (base == 0) write(n);
else printNumber(n, base);
}
template<typename Cfg>
void MarlinSerial<Cfg>::print(double n, int digits) {
printFloat(n, digits);
}
template<typename Cfg>
void MarlinSerial<Cfg>::println() {
print('\r');
print('\n');
}
template<typename Cfg>
void MarlinSerial<Cfg>::println(const String& s) {
print(s);
println();
}
template<typename Cfg>
void MarlinSerial<Cfg>::println(const char c[]) {
print(c);
println();
}
template<typename Cfg>
void MarlinSerial<Cfg>::println(char c, int base) {
print(c, base);
println();
}
template<typename Cfg>
void MarlinSerial<Cfg>::println(unsigned char b, int base) {
print(b, base);
println();
}
template<typename Cfg>
void MarlinSerial<Cfg>::println(int n, int base) {
print(n, base);
println();
}
template<typename Cfg>
void MarlinSerial<Cfg>::println(unsigned int n, int base) {
print(n, base);
println();
}
template<typename Cfg>
void MarlinSerial<Cfg>::println(long n, int base) {
print(n, base);
println();
}
template<typename Cfg>
void MarlinSerial<Cfg>::println(unsigned long n, int base) {
print(n, base);
println();
}
template<typename Cfg>
void MarlinSerial<Cfg>::println(double n, int digits) {
print(n, digits);
println();
}
// Private Methods
template<typename Cfg>
void MarlinSerial<Cfg>::printNumber(unsigned long n, uint8_t base) {
if (n) {
unsigned char buf[8 * sizeof(long)]; // Enough space for base 2
int8_t i = 0;
while (n) {
buf[i++] = n % base;
n /= base;
}
while (i--)
print((char)(buf[i] + (buf[i] < 10 ? '0' : 'A' - 10)));
}
else
print('0');
}
template<typename Cfg>
void MarlinSerial<Cfg>::printFloat(double number, uint8_t digits) {
// Handle negative numbers
if (number < 0.0) {
print('-');
number = -number;
}
// Round correctly so that print(1.999, 2) prints as "2.00"
double rounding = 0.5;
LOOP_L_N(i, digits) rounding *= 0.1;
number += rounding;
// Extract the integer part of the number and print it
unsigned long int_part = (unsigned long)number;
double remainder = number - (double)int_part;
print(int_part);
// Print the decimal point, but only if there are digits beyond
if (digits) {
print('.');
// Extract digits from the remainder one at a time
while (digits--) {
remainder *= 10.0;
int toPrint = int(remainder);
print(toPrint);
remainder -= toPrint;
}
}
}
// If not using the USB port as serial port // If not using the USB port as serial port
#if defined(SERIAL_PORT) && SERIAL_PORT >= 0 #if SERIAL_PORT >= 0
template class MarlinSerial< MarlinSerialCfg<SERIAL_PORT> >; template class MarlinSerial<MarlinSerialCfg<SERIAL_PORT>>; // Define
MSerialT1 customizedSerial1(MarlinSerialCfg<SERIAL_PORT>::EMERGENCYPARSER); MarlinSerial<MarlinSerialCfg<SERIAL_PORT>> customizedSerial1; // Instantiate
#endif #endif
#if defined(SERIAL_PORT_2) && SERIAL_PORT_2 >= 0 #if defined(SERIAL_PORT_2) && SERIAL_PORT_2 >= 0
template class MarlinSerial< MarlinSerialCfg<SERIAL_PORT_2> >; template class MarlinSerial<MarlinSerialCfg<SERIAL_PORT_2>>; // Define
MSerialT2 customizedSerial2(MarlinSerialCfg<SERIAL_PORT_2>::EMERGENCYPARSER); MarlinSerial<MarlinSerialCfg<SERIAL_PORT_2>> customizedSerial2; // Instantiate
#endif
#if defined(SERIAL_PORT_3) && SERIAL_PORT_3 >= 0
template class MarlinSerial< MarlinSerialCfg<SERIAL_PORT_3> >;
MSerialT3 customizedSerial3(MarlinSerialCfg<SERIAL_PORT_3>::EMERGENCYPARSER);
#endif #endif
#endif // ARDUINO_ARCH_SAM #endif // ARDUINO_ARCH_SAM

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#pragma once #pragma once
@@ -30,7 +30,11 @@
#include <WString.h> #include <WString.h>
#include "../../inc/MarlinConfigPre.h" #include "../../inc/MarlinConfigPre.h"
#include "../../core/serial_hook.h"
#define DEC 10
#define HEX 16
#define OCT 8
#define BIN 2
// Define constants and variables for buffering incoming serial data. We're // Define constants and variables for buffering incoming serial data. We're
// using a ring buffer (I think), in which rx_buffer_head is the index of the // using a ring buffer (I think), in which rx_buffer_head is the index of the
@@ -115,15 +119,42 @@ public:
static int read(); static int read();
static void flush(); static void flush();
static ring_buffer_pos_t available(); static ring_buffer_pos_t available();
static size_t write(const uint8_t c); static void write(const uint8_t c);
static void flushTX(); static void flushTX();
static bool emergency_parser_enabled() { return Cfg::EMERGENCYPARSER; }
FORCE_INLINE static uint8_t dropped() { return Cfg::DROPPED_RX ? rx_dropped_bytes : 0; } FORCE_INLINE static uint8_t dropped() { return Cfg::DROPPED_RX ? rx_dropped_bytes : 0; }
FORCE_INLINE static uint8_t buffer_overruns() { return Cfg::RX_OVERRUNS ? rx_buffer_overruns : 0; } FORCE_INLINE static uint8_t buffer_overruns() { return Cfg::RX_OVERRUNS ? rx_buffer_overruns : 0; }
FORCE_INLINE static uint8_t framing_errors() { return Cfg::RX_FRAMING_ERRORS ? rx_framing_errors : 0; } FORCE_INLINE static uint8_t framing_errors() { return Cfg::RX_FRAMING_ERRORS ? rx_framing_errors : 0; }
FORCE_INLINE static ring_buffer_pos_t rxMaxEnqueued() { return Cfg::MAX_RX_QUEUED ? rx_max_enqueued : 0; } FORCE_INLINE static ring_buffer_pos_t rxMaxEnqueued() { return Cfg::MAX_RX_QUEUED ? rx_max_enqueued : 0; }
FORCE_INLINE static void write(const char* str) { while (*str) write(*str++); }
FORCE_INLINE static void write(const uint8_t* buffer, size_t size) { while (size--) write(*buffer++); }
FORCE_INLINE static void print(const String& s) { for (int i = 0; i < (int)s.length(); i++) write(s[i]); }
FORCE_INLINE static void print(const char* str) { write(str); }
static void print(char, int = 0);
static void print(unsigned char, int = 0);
static void print(int, int = DEC);
static void print(unsigned int, int = DEC);
static void print(long, int = DEC);
static void print(unsigned long, int = DEC);
static void print(double, int = 2);
static void println(const String& s);
static void println(const char[]);
static void println(char, int = 0);
static void println(unsigned char, int = 0);
static void println(int, int = DEC);
static void println(unsigned int, int = DEC);
static void println(long, int = DEC);
static void println(unsigned long, int = DEC);
static void println(double, int = 2);
static void println();
operator bool() { return true; }
private:
static void printNumber(unsigned long, const uint8_t);
static void printFloat(double, uint8_t);
}; };
// Serial port configuration // Serial port configuration
@@ -140,17 +171,10 @@ struct MarlinSerialCfg {
static constexpr bool MAX_RX_QUEUED = ENABLED(SERIAL_STATS_MAX_RX_QUEUED); static constexpr bool MAX_RX_QUEUED = ENABLED(SERIAL_STATS_MAX_RX_QUEUED);
}; };
#if defined(SERIAL_PORT) && SERIAL_PORT >= 0 #if SERIAL_PORT >= 0
typedef Serial1Class< MarlinSerial< MarlinSerialCfg<SERIAL_PORT> > > MSerialT1; extern MarlinSerial<MarlinSerialCfg<SERIAL_PORT>> customizedSerial1;
extern MSerialT1 customizedSerial1;
#endif #endif
#if defined(SERIAL_PORT_2) && SERIAL_PORT_2 >= 0 #if defined(SERIAL_PORT_2) && SERIAL_PORT_2 >= 0
typedef Serial1Class< MarlinSerial< MarlinSerialCfg<SERIAL_PORT_2> > > MSerialT2; extern MarlinSerial<MarlinSerialCfg<SERIAL_PORT_2>> customizedSerial2;
extern MSerialT2 customizedSerial2;
#endif
#if defined(SERIAL_PORT_3) && SERIAL_PORT_3 >= 0
typedef Serial1Class< MarlinSerial< MarlinSerialCfg<SERIAL_PORT_3> > > MSerialT3;
extern MSerialT3 customizedSerial3;
#endif #endif

View File

@@ -16,16 +16,16 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#ifdef ARDUINO_ARCH_SAM
/** /**
* MarlinSerial_Due.cpp - Hardware serial library for Arduino DUE * MarlinSerial_Due.cpp - Hardware serial library for Arduino DUE
* Copyright (c) 2017 Eduardo José Tagle. All right reserved * Copyright (c) 2017 Eduardo José Tagle. All right reserved
* Based on MarlinSerial for AVR, copyright (c) 2006 Nicholas Zambetti. All right reserved. * Based on MarlinSerial for AVR, copyright (c) 2006 Nicholas Zambetti. All right reserved.
*/ */
#ifdef ARDUINO_ARCH_SAM
#include "../../inc/MarlinConfig.h" #include "../../inc/MarlinConfig.h"
@@ -33,6 +33,10 @@
#include "MarlinSerialUSB.h" #include "MarlinSerialUSB.h"
#if ENABLED(EMERGENCY_PARSER)
#include "../../feature/e_parser.h"
#endif
// Imports from Atmel USB Stack/CDC implementation // Imports from Atmel USB Stack/CDC implementation
extern "C" { extern "C" {
bool usb_task_cdc_isenabled(); bool usb_task_cdc_isenabled();
@@ -41,11 +45,15 @@ extern "C" {
int udi_cdc_getc(); int udi_cdc_getc();
bool udi_cdc_is_tx_ready(); bool udi_cdc_is_tx_ready();
int udi_cdc_putc(int value); int udi_cdc_putc(int value);
} };
// Pending character // Pending character
static int pending_char = -1; static int pending_char = -1;
#if ENABLED(EMERGENCY_PARSER)
static EmergencyParser::State emergency_state; // = EP_RESET
#endif
// Public Methods // Public Methods
void MarlinSerialUSB::begin(const long) {} void MarlinSerialUSB::begin(const long) {}
@@ -65,7 +73,9 @@ int MarlinSerialUSB::peek() {
pending_char = udi_cdc_getc(); pending_char = udi_cdc_getc();
TERN_(EMERGENCY_PARSER, emergency_parser.update(static_cast<MSerialT1*>(this)->emergency_state, (char)pending_char)); #if ENABLED(EMERGENCY_PARSER)
emergency_parser.update(emergency_state, (char)pending_char);
#endif
return pending_char; return pending_char;
} }
@@ -87,27 +97,31 @@ int MarlinSerialUSB::read() {
int c = udi_cdc_getc(); int c = udi_cdc_getc();
TERN_(EMERGENCY_PARSER, emergency_parser.update(static_cast<MSerialT1*>(this)->emergency_state, (char)c)); #if ENABLED(EMERGENCY_PARSER)
emergency_parser.update(emergency_state, (char)c);
#endif
return c; return c;
} }
int MarlinSerialUSB::available() { bool MarlinSerialUSB::available() {
if (pending_char > 0) return pending_char; /* If Pending chars */
return pending_char == 0 || return pending_char >= 0 ||
// or USB CDC enumerated and configured on the PC side and some bytes where sent to us */ /* or USB CDC enumerated and configured on the PC side and some
(usb_task_cdc_isenabled() && udi_cdc_is_rx_ready()); bytes where sent to us */
(usb_task_cdc_isenabled() && udi_cdc_is_rx_ready());
} }
void MarlinSerialUSB::flush() { } void MarlinSerialUSB::flush() { }
void MarlinSerialUSB::flushTX() { }
size_t MarlinSerialUSB::write(const uint8_t c) { void MarlinSerialUSB::write(const uint8_t c) {
/* Do not even bother sending anything if USB CDC is not enumerated /* Do not even bother sending anything if USB CDC is not enumerated
or not configured on the PC side or there is no program on the PC or not configured on the PC side or there is no program on the PC
listening to our messages */ listening to our messages */
if (!usb_task_cdc_isenabled() || !usb_task_cdc_dtr_active()) if (!usb_task_cdc_isenabled() || !usb_task_cdc_dtr_active())
return 0; return;
/* Wait until the PC has read the pending to be sent data */ /* Wait until the PC has read the pending to be sent data */
while (usb_task_cdc_isenabled() && while (usb_task_cdc_isenabled() &&
@@ -119,23 +133,161 @@ size_t MarlinSerialUSB::write(const uint8_t c) {
or not configured on the PC side or there is no program on the PC or not configured on the PC side or there is no program on the PC
listening to our messages at this point */ listening to our messages at this point */
if (!usb_task_cdc_isenabled() || !usb_task_cdc_dtr_active()) if (!usb_task_cdc_isenabled() || !usb_task_cdc_dtr_active())
return 0; return;
// Fifo full // Fifo full
// udi_cdc_signal_overrun(); // udi_cdc_signal_overrun();
udi_cdc_putc(c); udi_cdc_putc(c);
return 1; }
/**
* Imports from print.h
*/
void MarlinSerialUSB::print(char c, int base) {
print((long)c, base);
}
void MarlinSerialUSB::print(unsigned char b, int base) {
print((unsigned long)b, base);
}
void MarlinSerialUSB::print(int n, int base) {
print((long)n, base);
}
void MarlinSerialUSB::print(unsigned int n, int base) {
print((unsigned long)n, base);
}
void MarlinSerialUSB::print(long n, int base) {
if (base == 0)
write(n);
else if (base == 10) {
if (n < 0) {
print('-');
n = -n;
}
printNumber(n, 10);
}
else
printNumber(n, base);
}
void MarlinSerialUSB::print(unsigned long n, int base) {
if (base == 0) write(n);
else printNumber(n, base);
}
void MarlinSerialUSB::print(double n, int digits) {
printFloat(n, digits);
}
void MarlinSerialUSB::println() {
print('\r');
print('\n');
}
void MarlinSerialUSB::println(const String& s) {
print(s);
println();
}
void MarlinSerialUSB::println(const char c[]) {
print(c);
println();
}
void MarlinSerialUSB::println(char c, int base) {
print(c, base);
println();
}
void MarlinSerialUSB::println(unsigned char b, int base) {
print(b, base);
println();
}
void MarlinSerialUSB::println(int n, int base) {
print(n, base);
println();
}
void MarlinSerialUSB::println(unsigned int n, int base) {
print(n, base);
println();
}
void MarlinSerialUSB::println(long n, int base) {
print(n, base);
println();
}
void MarlinSerialUSB::println(unsigned long n, int base) {
print(n, base);
println();
}
void MarlinSerialUSB::println(double n, int digits) {
print(n, digits);
println();
}
// Private Methods
void MarlinSerialUSB::printNumber(unsigned long n, uint8_t base) {
if (n) {
unsigned char buf[8 * sizeof(long)]; // Enough space for base 2
int8_t i = 0;
while (n) {
buf[i++] = n % base;
n /= base;
}
while (i--)
print((char)(buf[i] + (buf[i] < 10 ? '0' : 'A' - 10)));
}
else
print('0');
}
void MarlinSerialUSB::printFloat(double number, uint8_t digits) {
// Handle negative numbers
if (number < 0.0) {
print('-');
number = -number;
}
// Round correctly so that print(1.999, 2) prints as "2.00"
double rounding = 0.5;
LOOP_L_N(i, digits)
rounding *= 0.1;
number += rounding;
// Extract the integer part of the number and print it
unsigned long int_part = (unsigned long)number;
double remainder = number - (double)int_part;
print(int_part);
// Print the decimal point, but only if there are digits beyond
if (digits) {
print('.');
// Extract digits from the remainder one at a time
while (digits--) {
remainder *= 10.0;
int toPrint = int(remainder);
print(toPrint);
remainder -= toPrint;
}
}
} }
// Preinstantiate // Preinstantiate
#if SERIAL_PORT == -1 #if SERIAL_PORT == -1
MSerialT1 customizedSerial1(TERN0(EMERGENCY_PARSER, true)); MarlinSerialUSB customizedSerial1;
#endif #endif
#if SERIAL_PORT_2 == -1 #if SERIAL_PORT_2 == -1
MSerialT2 customizedSerial2(TERN0(EMERGENCY_PARSER, true)); MarlinSerialUSB customizedSerial2;
#endif
#if SERIAL_PORT_3 == -1
MSerialT3 customizedSerial3(TERN0(EMERGENCY_PARSER, true));
#endif #endif
#endif // HAS_USB_SERIAL #endif // HAS_USB_SERIAL

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#pragma once #pragma once
@@ -27,39 +27,73 @@
*/ */
#include "../../inc/MarlinConfig.h" #include "../../inc/MarlinConfig.h"
#include "../../core/serial_hook.h"
#if HAS_USB_SERIAL
#include <WString.h> #include <WString.h>
struct MarlinSerialUSB { #define DEC 10
void begin(const long); #define HEX 16
void end(); #define OCT 8
int peek(); #define BIN 2
int read();
void flush(); class MarlinSerialUSB {
int available();
size_t write(const uint8_t c); public:
MarlinSerialUSB() {};
static void begin(const long);
static void end();
static int peek();
static int read();
static void flush();
static void flushTX();
static bool available();
static void write(const uint8_t c);
#if ENABLED(SERIAL_STATS_DROPPED_RX) #if ENABLED(SERIAL_STATS_DROPPED_RX)
FORCE_INLINE uint32_t dropped() { return 0; } FORCE_INLINE static uint32_t dropped() { return 0; }
#endif #endif
#if ENABLED(SERIAL_STATS_MAX_RX_QUEUED) #if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
FORCE_INLINE int rxMaxEnqueued() { return 0; } FORCE_INLINE static int rxMaxEnqueued() { return 0; }
#endif #endif
FORCE_INLINE static void write(const char* str) { while (*str) write(*str++); }
FORCE_INLINE static void write(const uint8_t* buffer, size_t size) { while (size--) write(*buffer++); }
FORCE_INLINE static void print(const String& s) { for (int i = 0; i < (int)s.length(); i++) write(s[i]); }
FORCE_INLINE static void print(const char* str) { write(str); }
static void print(char, int = 0);
static void print(unsigned char, int = 0);
static void print(int, int = DEC);
static void print(unsigned int, int = DEC);
static void print(long, int = DEC);
static void print(unsigned long, int = DEC);
static void print(double, int = 2);
static void println(const String& s);
static void println(const char[]);
static void println(char, int = 0);
static void println(unsigned char, int = 0);
static void println(int, int = DEC);
static void println(unsigned int, int = DEC);
static void println(long, int = DEC);
static void println(unsigned long, int = DEC);
static void println(double, int = 2);
static void println();
operator bool() { return true; }
private:
static void printNumber(unsigned long, const uint8_t);
static void printFloat(double, uint8_t);
}; };
#if SERIAL_PORT == -1 #if SERIAL_PORT == -1
typedef Serial1Class<MarlinSerialUSB> MSerialT1; extern MarlinSerialUSB customizedSerial1;
extern MSerialT1 customizedSerial1;
#endif #endif
#if SERIAL_PORT_2 == -1 #if SERIAL_PORT_2 == -1
typedef Serial1Class<MarlinSerialUSB> MSerialT2; extern MarlinSerialUSB customizedSerial2;
extern MSerialT2 customizedSerial2;
#endif #endif
#if SERIAL_PORT_3 == -1 #endif // HAS_USB_SERIAL
typedef Serial1Class<MarlinSerialUSB> MSerialT3;
extern MSerialT3 customizedSerial3;
#endif

View File

@@ -1,91 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#ifdef ARDUINO_ARCH_SAM
#include "../../inc/MarlinConfigPre.h"
#if ENABLED(POSTMORTEM_DEBUGGING)
#include "../shared/MinSerial.h"
#include <stdarg.h>
static void TXBegin() {
// Disable UART interrupt in NVIC
NVIC_DisableIRQ( UART_IRQn );
// We NEED memory barriers to ensure Interrupts are actually disabled!
// ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
__DSB();
__ISB();
// Disable clock
pmc_disable_periph_clk( ID_UART );
// Configure PMC
pmc_enable_periph_clk( ID_UART );
// Disable PDC channel
UART->UART_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS;
// Reset and disable receiver and transmitter
UART->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS;
// Configure mode: 8bit, No parity, 1 bit stop
UART->UART_MR = UART_MR_CHMODE_NORMAL | US_MR_CHRL_8_BIT | US_MR_NBSTOP_1_BIT | UART_MR_PAR_NO;
// Configure baudrate (asynchronous, no oversampling) to BAUDRATE bauds
UART->UART_BRGR = (SystemCoreClock / (BAUDRATE << 4));
// Enable receiver and transmitter
UART->UART_CR = UART_CR_RXEN | UART_CR_TXEN;
}
// A SW memory barrier, to ensure GCC does not overoptimize loops
#define sw_barrier() __asm__ volatile("": : :"memory");
static void TX(char c) {
while (!(UART->UART_SR & UART_SR_TXRDY)) { WDT_Restart(WDT); sw_barrier(); };
UART->UART_THR = c;
}
void install_min_serial() {
HAL_min_serial_init = &TXBegin;
HAL_min_serial_out = &TX;
}
#if DISABLED(DYNAMIC_VECTORTABLE)
extern "C" {
__attribute__((naked)) void JumpHandler_ASM() {
__asm__ __volatile__ (
"b CommonHandler_ASM\n"
);
}
void __attribute__((naked, alias("JumpHandler_ASM"))) HardFault_Handler();
void __attribute__((naked, alias("JumpHandler_ASM"))) BusFault_Handler();
void __attribute__((naked, alias("JumpHandler_ASM"))) UsageFault_Handler();
void __attribute__((naked, alias("JumpHandler_ASM"))) MemManage_Handler();
void __attribute__((naked, alias("JumpHandler_ASM"))) NMI_Handler();
}
#endif
#endif // POSTMORTEM_DEBUGGING
#endif // ARDUINO_ARCH_SAM

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@@ -44,15 +44,16 @@
#if HAS_SERVOS #if HAS_SERVOS
#include "../shared/Marduino.h"
#include "../shared/servo.h" #include "../shared/servo.h"
#include "../shared/servo_private.h" #include "../shared/servo_private.h"
static Flags<_Nbr_16timers> DisablePending; // ISR should disable the timer at the next timer reset static volatile int8_t Channel[_Nbr_16timers]; // counter for the servo being pulsed for each timer (or -1 if refresh interval)
// ------------------------ // ------------------------
/// Interrupt handler for the TC0 channel 1. /// Interrupt handler for the TC0 channel 1.
// ------------------------ // ------------------------
void Servo_Handler(const timer16_Sequence_t, Tc*, const uint8_t); void Servo_Handler(timer16_Sequence_t timer, Tc *pTc, uint8_t channel);
#ifdef _useTimer1 #ifdef _useTimer1
void HANDLER_FOR_TIMER1() { Servo_Handler(_timer1, TC_FOR_TIMER1, CHANNEL_FOR_TIMER1); } void HANDLER_FOR_TIMER1() { Servo_Handler(_timer1, TC_FOR_TIMER1, CHANNEL_FOR_TIMER1); }
@@ -70,92 +71,88 @@ void Servo_Handler(const timer16_Sequence_t, Tc*, const uint8_t);
void HANDLER_FOR_TIMER5() { Servo_Handler(_timer5, TC_FOR_TIMER5, CHANNEL_FOR_TIMER5); } void HANDLER_FOR_TIMER5() { Servo_Handler(_timer5, TC_FOR_TIMER5, CHANNEL_FOR_TIMER5); }
#endif #endif
void Servo_Handler(const timer16_Sequence_t timer, Tc *tc, const uint8_t channel) { void Servo_Handler(timer16_Sequence_t timer, Tc *tc, uint8_t channel) {
static int8_t Channel[_Nbr_16timers]; // Servo counters to pulse (or -1 for refresh interval) // clear interrupt
int8_t cho = Channel[timer]; // Handle the prior Channel[timer] first tc->TC_CHANNEL[channel].TC_SR;
if (cho < 0) { // Channel -1 indicates the refresh interval completed... if (Channel[timer] < 0)
tc->TC_CHANNEL[channel].TC_CCR |= TC_CCR_SWTRG; // ...so reset the timer tc->TC_CHANNEL[channel].TC_CCR |= TC_CCR_SWTRG; // channel set to -1 indicated that refresh interval completed so reset the timer
if (DisablePending[timer]) { else if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && SERVO(timer, Channel[timer]).Pin.isActive)
// Disabling only after the full servo period expires prevents extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, LOW); // pulse this channel low if activated
// pulses being too close together if immediately re-enabled.
DisablePending.clear(timer);
TC_Stop(tc, channel);
tc->TC_CHANNEL[channel].TC_SR; // clear interrupt
return;
}
}
else if (SERVO_INDEX(timer, cho) < ServoCount) // prior channel handled?
extDigitalWrite(SERVO(timer, cho).Pin.nbr, LOW); // pulse the prior channel LOW
Channel[timer] = ++cho; // go to the next channel (or 0) Channel[timer]++; // increment to the next channel
if (cho < SERVOS_PER_TIMER && SERVO_INDEX(timer, cho) < ServoCount) { 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, cho).ticks; tc->TC_CHANNEL[channel].TC_RA = tc->TC_CHANNEL[channel].TC_CV + SERVO(timer,Channel[timer]).ticks;
if (SERVO(timer, cho).Pin.isActive) // activated? if (SERVO(timer,Channel[timer]).Pin.isActive) // check if activated
extDigitalWrite(SERVO(timer, cho).Pin.nbr, HIGH); // yes: pulse HIGH extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, HIGH); // its an active channel so pulse it high
} }
else { else {
// finished all channels so wait for the refresh period to expire before starting over // finished all channels so wait for the refresh period to expire before starting over
const unsigned int cval = tc->TC_CHANNEL[channel].TC_CV + 128 / (SERVO_TIMER_PRESCALER), // allow 128 cycles to ensure the next CV not missed tc->TC_CHANNEL[channel].TC_RA =
ival = (unsigned int)usToTicks(REFRESH_INTERVAL); // at least REFRESH_INTERVAL has elapsed tc->TC_CHANNEL[channel].TC_CV < usToTicks(REFRESH_INTERVAL) - 4
tc->TC_CHANNEL[channel].TC_RA = max(cval, ival); ? (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; // reset the timer CCR on the next call Channel[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel
} }
tc->TC_CHANNEL[channel].TC_SR; // clear interrupt
} }
static void _initISR(Tc *tc, uint32_t channel, uint32_t id, IRQn_Type irqn) { static void _initISR(Tc *tc, uint32_t channel, uint32_t id, IRQn_Type irqn) {
pmc_enable_periph_clk(id); pmc_enable_periph_clk(id);
TC_Configure(tc, channel, TC_Configure(tc, channel,
TC_CMR_WAVE // Waveform mode TC_CMR_TCCLKS_TIMER_CLOCK3 | // MCK/32
| TC_CMR_WAVSEL_UP_RC // Counter running up and reset when equal to RC TC_CMR_WAVE | // Waveform mode
| (SERVO_TIMER_PRESCALER == 2 ? TC_CMR_TCCLKS_TIMER_CLOCK1 : 0) // MCK/2 TC_CMR_WAVSEL_UP_RC ); // Counter running up and reset when equals to RC
| (SERVO_TIMER_PRESCALER == 8 ? TC_CMR_TCCLKS_TIMER_CLOCK2 : 0) // MCK/8
| (SERVO_TIMER_PRESCALER == 32 ? TC_CMR_TCCLKS_TIMER_CLOCK3 : 0) // MCK/32
| (SERVO_TIMER_PRESCALER == 128 ? TC_CMR_TCCLKS_TIMER_CLOCK4 : 0) // MCK/128
);
// Wait 1ms before the first ISR /* 84MHz, MCK/32, for 1.5ms: 3937 */
TC_SetRA(tc, channel, (F_CPU) / (SERVO_TIMER_PRESCALER) / 1000UL); // 1ms TC_SetRA(tc, channel, 2625); // 1ms
// Configure and enable interrupt /* Configure and enable interrupt */
NVIC_EnableIRQ(irqn); NVIC_EnableIRQ(irqn);
tc->TC_CHANNEL[channel].TC_IER = TC_IER_CPAS; // TC_IER_CPAS: RA Compare // TC_IER_CPAS: RA Compare
tc->TC_CHANNEL[channel].TC_IER = TC_IER_CPAS;
// Enables the timer clock and performs a software reset to start the counting // Enables the timer clock and performs a software reset to start the counting
TC_Start(tc, channel); TC_Start(tc, channel);
} }
void initISR(const timer16_Sequence_t timer_index) { void initISR(timer16_Sequence_t timer) {
CRITICAL_SECTION_START(); #ifdef _useTimer1
const bool disable_soon = DisablePending[timer_index]; if (timer == _timer1)
DisablePending.clear(timer_index); _initISR(TC_FOR_TIMER1, CHANNEL_FOR_TIMER1, ID_TC_FOR_TIMER1, IRQn_FOR_TIMER1);
CRITICAL_SECTION_END(); #endif
#ifdef _useTimer2
if (!disable_soon) switch (timer_index) { if (timer == _timer2)
default: break; _initISR(TC_FOR_TIMER2, CHANNEL_FOR_TIMER2, ID_TC_FOR_TIMER2, IRQn_FOR_TIMER2);
#ifdef _useTimer1 #endif
case _timer1: return _initISR(TC_FOR_TIMER1, CHANNEL_FOR_TIMER1, ID_TC_FOR_TIMER1, IRQn_FOR_TIMER1); #ifdef _useTimer3
#endif if (timer == _timer3)
#ifdef _useTimer2 _initISR(TC_FOR_TIMER3, CHANNEL_FOR_TIMER3, ID_TC_FOR_TIMER3, IRQn_FOR_TIMER3);
case _timer2: return _initISR(TC_FOR_TIMER2, CHANNEL_FOR_TIMER2, ID_TC_FOR_TIMER2, IRQn_FOR_TIMER2); #endif
#endif #ifdef _useTimer4
#ifdef _useTimer3 if (timer == _timer4)
case _timer3: return _initISR(TC_FOR_TIMER3, CHANNEL_FOR_TIMER3, ID_TC_FOR_TIMER3, IRQn_FOR_TIMER3); _initISR(TC_FOR_TIMER4, CHANNEL_FOR_TIMER4, ID_TC_FOR_TIMER4, IRQn_FOR_TIMER4);
#endif #endif
#ifdef _useTimer4 #ifdef _useTimer5
case _timer4: return _initISR(TC_FOR_TIMER4, CHANNEL_FOR_TIMER4, ID_TC_FOR_TIMER4, IRQn_FOR_TIMER4); if (timer == _timer5)
#endif _initISR(TC_FOR_TIMER5, CHANNEL_FOR_TIMER5, ID_TC_FOR_TIMER5, IRQn_FOR_TIMER5);
#ifdef _useTimer5 #endif
case _timer5: return _initISR(TC_FOR_TIMER5, CHANNEL_FOR_TIMER5, ID_TC_FOR_TIMER5, IRQn_FOR_TIMER5);
#endif
}
} }
void finISR(const timer16_Sequence_t timer_index) { void finISR(timer16_Sequence_t) {
// Timer is disabled from the ISR, to ensure proper final pulse length. #ifdef _useTimer1
DisablePending.set(timer_index); 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
} }
#endif // HAS_SERVOS #endif // HAS_SERVOS

View File

@@ -37,7 +37,7 @@
#define _useTimer5 #define _useTimer5
#define TRIM_DURATION 2 // compensation ticks to trim adjust for digitalWrite delays #define TRIM_DURATION 2 // compensation ticks to trim adjust for digitalWrite delays
#define SERVO_TIMER_PRESCALER 2 // timer prescaler #define SERVO_TIMER_PRESCALER 32 // timer prescaler
/* /*
TC0, chan 0 => TC0_Handler TC0, chan 0 => TC0_Handler

View File

@@ -18,37 +18,38 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
/** /**
* Description: Tone function for Arduino Due and compatible (SAM3X8E) * Description: Tone function for Arduino Due and compatible (SAM3X8E)
* Derived from https://forum.arduino.cc/index.php?topic=136500.msg2903012#msg2903012 * Derived from http://forum.arduino.cc/index.php?topic=136500.msg2903012#msg2903012
*/ */
#ifdef ARDUINO_ARCH_SAM #ifdef ARDUINO_ARCH_SAM
#include "../../inc/MarlinConfig.h" #include "../../inc/MarlinConfig.h"
#include "HAL.h" #include "HAL.h"
#include "timers.h"
static pin_t tone_pin; static pin_t tone_pin;
volatile static int32_t toggles; volatile static int32_t toggles;
void tone(const pin_t _pin, const unsigned int frequency, const unsigned long duration/*=0*/) { void tone(const pin_t _pin, const unsigned int frequency, const unsigned long duration) {
tone_pin = _pin; tone_pin = _pin;
toggles = 2 * frequency * duration / 1000; toggles = 2 * frequency * duration / 1000;
HAL_timer_start(MF_TIMER_TONE, 2 * frequency); HAL_timer_start(TONE_TIMER_NUM, 2 * frequency);
} }
void noTone(const pin_t _pin) { void noTone(const pin_t _pin) {
HAL_timer_disable_interrupt(MF_TIMER_TONE); HAL_timer_disable_interrupt(TONE_TIMER_NUM);
extDigitalWrite(_pin, LOW); extDigitalWrite(_pin, LOW);
} }
HAL_TONE_TIMER_ISR() { HAL_TONE_TIMER_ISR() {
static uint8_t pin_state = 0; static uint8_t pin_state = 0;
HAL_timer_isr_prologue(MF_TIMER_TONE); HAL_timer_isr_prologue(TONE_TIMER_NUM);
if (toggles) { if (toggles) {
toggles--; toggles--;

View File

@@ -16,10 +16,11 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
/** /**
* Based on u8g_com_msp430_hw_spi.c * Based on u8g_com_msp430_hw_spi.c
* *
@@ -51,23 +52,25 @@
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/ */
#ifdef __SAM3X8E__ #ifdef __SAM3X8E__
#include "../../../inc/MarlinConfigPre.h" #include "../../../inc/MarlinConfigPre.h"
#if HAS_MARLINUI_U8GLIB #if HAS_GRAPHICAL_LCD
#include <U8glib-HAL.h> #include <U8glib.h>
#include "../../../MarlinCore.h" #include "../../../MarlinCore.h"
#ifndef LCD_SPI_SPEED void spiBegin();
#define LCD_SPI_SPEED SPI_QUARTER_SPEED void spiInit(uint8_t spiRate);
#endif void spiSend(uint8_t b);
void spiSend(const uint8_t* buf, size_t n);
#include "../../shared/HAL_SPI.h" #include "../../shared/Marduino.h"
#include "../fastio.h" #include "../fastio.h"
void u8g_SetPIOutput_DUE_hw_spi(u8g_t *u8g, uint8_t pin_index) { void u8g_SetPIOutput_DUE_hw_spi(u8g_t *u8g, uint8_t pin_index) {
@@ -98,7 +101,11 @@ uint8_t u8g_com_HAL_DUE_shared_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_va
spiBegin(); spiBegin();
spiInit(LCD_SPI_SPEED); #ifndef SPI_SPEED
#define SPI_SPEED SPI_FULL_SPEED // use same SPI speed as SD card
#endif
spiInit(2);
break; break;
case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */ case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */
@@ -138,6 +145,6 @@ uint8_t u8g_com_HAL_DUE_shared_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_va
return 1; return 1;
} }
#endif // HAS_MARLINUI_U8GLIB #endif // HAS_GRAPHICAL_LCD
#endif // __SAM3X8E__ #endif //__SAM3X8E__

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@@ -57,12 +57,11 @@
#include "../../../inc/MarlinConfigPre.h" #include "../../../inc/MarlinConfigPre.h"
#if IS_U8GLIB_ST7920 #if ENABLED(U8GLIB_ST7920)
#include "../../../inc/MarlinConfig.h"
#include "../../shared/Delay.h" #include "../../shared/Delay.h"
#include <U8glib-HAL.h> #include <U8glib.h>
#include "u8g_com_HAL_DUE_sw_spi_shared.h" #include "u8g_com_HAL_DUE_sw_spi_shared.h"
@@ -146,7 +145,7 @@ uint8_t u8g_com_HAL_DUE_ST7920_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_va
} }
#if ENABLED(LIGHTWEIGHT_UI) #if ENABLED(LIGHTWEIGHT_UI)
#include "../../../lcd/marlinui.h" #include "../../../lcd/ultralcd.h"
#include "../../shared/HAL_ST7920.h" #include "../../shared/HAL_ST7920.h"
#define ST7920_CS_PIN LCD_PINS_RS #define ST7920_CS_PIN LCD_PINS_RS
@@ -182,5 +181,5 @@ uint8_t u8g_com_HAL_DUE_ST7920_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_va
} }
#endif // LIGHTWEIGHT_UI #endif // LIGHTWEIGHT_UI
#endif // IS_U8GLIB_ST7920 #endif // U8GLIB_ST7920
#endif // ARDUINO_ARCH_SAM #endif // ARDUINO_ARCH_SAM

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@@ -57,14 +57,17 @@
#include "../../../inc/MarlinConfigPre.h" #include "../../../inc/MarlinConfigPre.h"
#if HAS_MARLINUI_U8GLIB && !IS_U8GLIB_ST7920 #if HAS_GRAPHICAL_LCD && DISABLED(U8GLIB_ST7920)
#undef SPI_SPEED
#define SPI_SPEED 2 // About 2 MHz
#include "u8g_com_HAL_DUE_sw_spi_shared.h" #include "u8g_com_HAL_DUE_sw_spi_shared.h"
#include "../../shared/Marduino.h" #include "../../shared/Marduino.h"
#include "../../shared/Delay.h" #include "../../shared/Delay.h"
#include <U8glib-HAL.h> #include <U8glib.h>
#if ENABLED(FYSETC_MINI_12864) #if ENABLED(FYSETC_MINI_12864)
#define SPISEND_SW_DUE u8g_spiSend_sw_DUE_mode_3 #define SPISEND_SW_DUE u8g_spiSend_sw_DUE_mode_3
@@ -141,5 +144,5 @@ uint8_t u8g_com_HAL_DUE_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void
return 1; return 1;
} }
#endif // HAS_MARLINUI_U8GLIB && !IS_U8GLIB_ST7920 #endif // HAS_GRAPHICAL_LCD && !U8GLIB_ST7920
#endif // ARDUINO_ARCH_SAM #endif // ARDUINO_ARCH_SAM

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@@ -57,12 +57,11 @@
#include "../../../inc/MarlinConfigPre.h" #include "../../../inc/MarlinConfigPre.h"
#if HAS_MARLINUI_U8GLIB #if HAS_GRAPHICAL_LCD
#include "../../../inc/MarlinConfig.h"
#include "../../shared/Delay.h" #include "../../shared/Delay.h"
#include <U8glib-HAL.h> #include <U8glib.h>
#include "u8g_com_HAL_DUE_sw_spi_shared.h" #include "u8g_com_HAL_DUE_sw_spi_shared.h"
@@ -109,5 +108,5 @@ void u8g_spiSend_sw_DUE_mode_3(uint8_t val) { // 3.5MHz
} }
} }
#endif // HAS_MARLINUI_U8GLIB #endif // HAS_GRAPHICAL_LCD
#endif // ARDUINO_ARCH_SAM #endif // ARDUINO_ARCH_SAM

View File

@@ -16,14 +16,14 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#pragma once #pragma once
#include "../../../inc/MarlinConfigPre.h" #include "../../../inc/MarlinConfigPre.h"
#include "../../shared/Marduino.h" #include "../../shared/Marduino.h"
#include <U8glib-HAL.h> #include <U8glib.h>
void u8g_SetPIOutput_DUE(u8g_t *u8g, uint8_t pin_index); void u8g_SetPIOutput_DUE(u8g_t *u8g, uint8_t pin_index);
void u8g_SetPILevel_DUE(u8g_t *u8g, uint8_t pin_index, uint8_t level); void u8g_SetPILevel_DUE(u8g_t *u8g, uint8_t pin_index, uint8_t level);

View File

@@ -17,38 +17,42 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#ifdef ARDUINO_ARCH_SAM #ifdef ARDUINO_ARCH_SAM
#include "../../inc/MarlinConfigPre.h"
#if ENABLED(EEPROM_SETTINGS)
#include "../../inc/MarlinConfig.h" #include "../../inc/MarlinConfig.h"
#if USE_WIRED_EEPROM
/**
* PersistentStore for Arduino-style EEPROM interface
* with simple implementations supplied by Marlin.
*/
#include "../shared/eeprom_if.h"
#include "../shared/eeprom_api.h" #include "../shared/eeprom_api.h"
#ifndef MARLIN_EEPROM_SIZE #if !defined(E2END) && ENABLED(FLASH_EEPROM_EMULATION)
#error "MARLIN_EEPROM_SIZE is required for I2C / SPI EEPROM." #define E2END 0xFFF // Default to Flash emulated EEPROM size (EepromEmulation_Due.cpp)
#endif #endif
size_t PersistentStore::capacity() { return MARLIN_EEPROM_SIZE; }
bool PersistentStore::access_start() { eeprom_init(); return true; } extern void eeprom_flush();
bool PersistentStore::access_finish() { return true; }
bool PersistentStore::access_start() { return true; }
bool PersistentStore::access_finish() {
#if ENABLED(FLASH_EEPROM_EMULATION)
eeprom_flush();
#endif
return true;
}
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) { bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
uint16_t written = 0;
while (size--) { while (size--) {
uint8_t * const p = (uint8_t * const)pos; uint8_t * const p = (uint8_t * const)pos;
uint8_t v = *value; uint8_t v = *value;
if (v != eeprom_read_byte(p)) { // EEPROM has only ~100,000 write cycles, so only write bytes that have changed! // EEPROM has only ~100,000 write cycles,
// so only write bytes that have changed!
if (v != eeprom_read_byte(p)) {
eeprom_write_byte(p, v); eeprom_write_byte(p, v);
if (++written & 0x7F) delay(2); else safe_delay(2); // Avoid triggering watchdog during long EEPROM writes delay(2);
if (eeprom_read_byte(p) != v) { if (eeprom_read_byte(p) != v) {
SERIAL_ECHO_MSG(STR_ERR_EEPROM_WRITE); SERIAL_ECHO_MSG(STR_ERR_EEPROM_WRITE);
return true; return true;
@@ -57,11 +61,11 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui
crc16(crc, &v, 1); crc16(crc, &v, 1);
pos++; pos++;
value++; value++;
} };
return false; return false;
} }
bool PersistentStore::read_data(int &pos, uint8_t *value, size_t size, uint16_t *crc, const bool writing/*=true*/) { bool PersistentStore::read_data(int &pos, uint8_t* value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
do { do {
uint8_t c = eeprom_read_byte((uint8_t*)pos); uint8_t c = eeprom_read_byte((uint8_t*)pos);
if (writing) *value = c; if (writing) *value = c;
@@ -72,5 +76,7 @@ bool PersistentStore::read_data(int &pos, uint8_t *value, size_t size, uint16_t
return false; return false;
} }
#endif // USE_WIRED_EEPROM size_t PersistentStore::capacity() { return E2END + 1; }
#endif // EEPROM_SETTINGS
#endif // ARDUINO_ARCH_SAM #endif // ARDUINO_ARCH_SAM

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#pragma once #pragma once
@@ -47,27 +47,43 @@ void endstop_ISR() { endstops.update(); }
void setup_endstop_interrupts() { void setup_endstop_interrupts() {
#define _ATTACH(P) attachInterrupt(digitalPinToInterrupt(P), endstop_ISR, CHANGE) #define _ATTACH(P) attachInterrupt(digitalPinToInterrupt(P), endstop_ISR, CHANGE)
TERN_(HAS_X_MAX, _ATTACH(X_MAX_PIN)); #if HAS_X_MAX
TERN_(HAS_X_MIN, _ATTACH(X_MIN_PIN)); _ATTACH(X_MAX_PIN);
TERN_(HAS_Y_MAX, _ATTACH(Y_MAX_PIN)); #endif
TERN_(HAS_Y_MIN, _ATTACH(Y_MIN_PIN)); #if HAS_X_MIN
TERN_(HAS_Z_MAX, _ATTACH(Z_MAX_PIN)); _ATTACH(X_MIN_PIN);
TERN_(HAS_Z_MIN, _ATTACH(Z_MIN_PIN)); #endif
TERN_(HAS_X2_MAX, _ATTACH(X2_MAX_PIN)); #if HAS_Y_MAX
TERN_(HAS_X2_MIN, _ATTACH(X2_MIN_PIN)); _ATTACH(Y_MAX_PIN);
TERN_(HAS_Y2_MAX, _ATTACH(Y2_MAX_PIN)); #endif
TERN_(HAS_Y2_MIN, _ATTACH(Y2_MIN_PIN)); #if HAS_Y_MIN
TERN_(HAS_Z2_MAX, _ATTACH(Z2_MAX_PIN)); _ATTACH(Y_MIN_PIN);
TERN_(HAS_Z2_MIN, _ATTACH(Z2_MIN_PIN)); #endif
TERN_(HAS_Z3_MAX, _ATTACH(Z3_MAX_PIN)); #if HAS_Z_MAX
TERN_(HAS_Z3_MIN, _ATTACH(Z3_MIN_PIN)); _ATTACH(Z_MAX_PIN);
TERN_(HAS_Z4_MAX, _ATTACH(Z4_MAX_PIN)); #endif
TERN_(HAS_Z4_MIN, _ATTACH(Z4_MIN_PIN)); #if HAS_Z_MIN
TERN_(HAS_Z_MIN_PROBE_PIN, _ATTACH(Z_MIN_PROBE_PIN)); _ATTACH(Z_MIN_PIN);
TERN_(HAS_I_MAX, _ATTACH(I_MAX_PIN)); #endif
TERN_(HAS_I_MIN, _ATTACH(I_MIN_PIN)); #if HAS_Z2_MAX
TERN_(HAS_J_MAX, _ATTACH(J_MAX_PIN)); _ATTACH(Z2_MAX_PIN);
TERN_(HAS_J_MIN, _ATTACH(J_MIN_PIN)); #endif
TERN_(HAS_K_MAX, _ATTACH(K_MAX_PIN)); #if HAS_Z2_MIN
TERN_(HAS_K_MIN, _ATTACH(K_MIN_PIN)); _ATTACH(Z2_MIN_PIN);
#endif
#if HAS_Z3_MAX
_ATTACH(Z3_MAX_PIN);
#endif
#if HAS_Z3_MIN
_ATTACH(Z3_MIN_PIN);
#endif
#if HAS_Z4_MAX
_ATTACH(Z4_MAX_PIN);
#endif
#if HAS_Z4_MIN
_ATTACH(Z4_MIN_PIN);
#endif
#if HAS_Z_MIN_PROBE_PIN
_ATTACH(Z_MIN_PROBE_PIN);
#endif
} }

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#pragma once #pragma once
@@ -33,7 +33,7 @@
* For ARDUINO_ARCH_SAM * For ARDUINO_ARCH_SAM
* Note the code here was specifically crafted by disassembling what GCC produces * Note the code here was specifically crafted by disassembling what GCC produces
* out of it, so GCC is able to optimize it out as much as possible to the least * out of it, so GCC is able to optimize it out as much as possible to the least
* amount of instructions. Be very careful if you modify them, as "clean code" * amount of instructions. Be very carefull if you modify them, as "clean code"
* leads to less efficient compiled code!! * leads to less efficient compiled code!!
*/ */
@@ -50,7 +50,7 @@
#define PWM_PIN(P) WITHIN(P, 2, 13) #define PWM_PIN(P) WITHIN(P, 2, 13)
#ifndef MASK #ifndef MASK
#define MASK(PIN) _BV(PIN) #define MASK(PIN) (1 << PIN)
#endif #endif
/** /**
@@ -58,7 +58,7 @@
* *
* Now you can simply SET_OUTPUT(STEP); WRITE(STEP, HIGH); WRITE(STEP, LOW); * Now you can simply SET_OUTPUT(STEP); WRITE(STEP, HIGH); WRITE(STEP, LOW);
* *
* Why double up on these macros? see https://gcc.gnu.org/onlinedocs/cpp/Stringification.html * Why double up on these macros? see http://gcc.gnu.org/onlinedocs/cpp/Stringification.html
*/ */
// Read a pin // Read a pin
@@ -163,9 +163,6 @@
#define SET_INPUT(IO) _SET_INPUT(IO) #define SET_INPUT(IO) _SET_INPUT(IO)
// Set pin as input with pullup (wrapper) // Set pin as input with pullup (wrapper)
#define SET_INPUT_PULLUP(IO) do{ _SET_INPUT(IO); _PULLUP(IO, HIGH); }while(0) #define SET_INPUT_PULLUP(IO) do{ _SET_INPUT(IO); _PULLUP(IO, HIGH); }while(0)
// Set pin as input with pulldown (substitution)
#define SET_INPUT_PULLDOWN SET_INPUT
// Set pin as output (wrapper) - reads the pin and sets the output to that value // Set pin as output (wrapper) - reads the pin and sets the output to that value
#define SET_OUTPUT(IO) _SET_OUTPUT(IO) #define SET_OUTPUT(IO) _SET_OUTPUT(IO)
// Set pin as PWM // Set pin as PWM
@@ -177,7 +174,7 @@
#define IS_OUTPUT(IO) ((digitalPinToPort(IO)->PIO_OSR & digitalPinToBitMask(IO)) != 0) #define IS_OUTPUT(IO) ((digitalPinToPort(IO)->PIO_OSR & digitalPinToBitMask(IO)) != 0)
// Shorthand // Shorthand
#define OUT_WRITE(IO,V) do{ SET_OUTPUT(IO); WRITE(IO,V); }while(0) #define OUT_WRITE(IO,V) { SET_OUTPUT(IO); WRITE(IO,V); }
// digitalRead/Write wrappers // digitalRead/Write wrappers
#define extDigitalRead(IO) digitalRead(IO) #define extDigitalRead(IO) digitalRead(IO)
@@ -480,7 +477,7 @@
#define DIO91_PIN 15 #define DIO91_PIN 15
#define DIO91_WPORT PIOB #define DIO91_WPORT PIOB
#ifdef ARDUINO_SAM_ARCHIM #if ARDUINO_SAM_ARCHIM
#define DIO92_PIN 11 #define DIO92_PIN 11
#define DIO92_WPORT PIOC #define DIO92_WPORT PIOC

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@@ -25,7 +25,7 @@
* is NOT used to directly toggle pins. The ISR writes to the pin assigned to * is NOT used to directly toggle pins. The ISR writes to the pin assigned to
* that interrupt. * that interrupt.
* *
* All PWMs use the same repetition rate. The G2 needs about 10kHz min in order to * All PWMs use the same repetition rate. The G2 needs about 10KHz min in order to
* not have obvious ripple on the Vref signals. * not have obvious ripple on the Vref signals.
* *
* The data structures are setup to minimize the computation done by the ISR which * The data structures are setup to minimize the computation done by the ISR which
@@ -154,7 +154,7 @@ void Stepper::digipot_init() {
NVIC_SetPriority(PWM_IRQn, NVIC_EncodePriority(0, 10, 0)); // normal priority for PWM module (can stand some jitter on the Vref signals) NVIC_SetPriority(PWM_IRQn, NVIC_EncodePriority(0, 10, 0)); // normal priority for PWM module (can stand some jitter on the Vref signals)
} }
void Stepper::set_digipot_current(const uint8_t driver, const int16_t current) { void Stepper::digipot_current(const uint8_t driver, const int16_t current) {
if (!(PWM->PWM_CH_NUM[0].PWM_CPRD == PWM_PERIOD_US)) digipot_init(); // Init PWM system if needed if (!(PWM->PWM_CH_NUM[0].PWM_CPRD == PWM_PERIOD_US)) digipot_init(); // Init PWM system if needed

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#pragma once #pragma once

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#pragma once #pragma once

View File

@@ -16,11 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#pragma once #pragma once
#if HAS_SPI_TFT || HAS_FSMC_TFT
#error "Sorry! TFT displays are not available for HAL/DUE."
#endif

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#pragma once #pragma once

View File

@@ -16,13 +16,13 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#pragma once #pragma once
#if USE_FALLBACK_EEPROM #if USE_FALLBACK_EEPROM
#undef SRAM_EEPROM_EMULATION
#undef SDCARD_EEPROM_EMULATION
#define FLASH_EEPROM_EMULATION #define FLASH_EEPROM_EMULATION
#elif EITHER(I2C_EEPROM, SPI_EEPROM)
#define USE_SHARED_EEPROM 1
#endif #endif

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#pragma once #pragma once
@@ -25,30 +25,6 @@
* Test Arduino Due specific configuration values for errors at compile-time. * 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 * HARDWARE VS. SOFTWARE SPI COMPATIBILITY
* *
@@ -64,7 +40,7 @@
* Usually the hardware SPI pins are only available to the LCD. This makes the DUE hard SPI used at the same time * Usually the hardware SPI pins are only available to the LCD. This makes the DUE hard SPI used at the same time
* as the TMC2130 soft SPI the most common setup. * as the TMC2130 soft SPI the most common setup.
*/ */
#define _IS_HW_SPI(P) (defined(TMC_SW_##P) && (TMC_SW_##P == SD_MOSI_PIN || TMC_SW_##P == SD_MISO_PIN || TMC_SW_##P == SD_SCK_PIN)) #define _IS_HW_SPI(P) (defined(TMC_SW_##P) && (TMC_SW_##P == MOSI_PIN || TMC_SW_##P == MISO_PIN || TMC_SW_##P == SCK_PIN))
#if ENABLED(SDSUPPORT) && HAS_DRIVER(TMC2130) #if ENABLED(SDSUPPORT) && HAS_DRIVER(TMC2130)
#if ENABLED(TMC_USE_SW_SPI) #if ENABLED(TMC_USE_SW_SPI)
@@ -76,14 +52,10 @@
#endif #endif
#endif #endif
#if ENABLED(FAST_PWM_FAN) || SPINDLE_LASER_FREQUENCY #if ENABLED(FAST_PWM_FAN)
#error "Features requiring Hardware PWM (FAST_PWM_FAN, SPINDLE_LASER_FREQUENCY) are not yet supported on DUE." #error "FAST_PWM_FAN is not yet implemented for this platform."
#endif #endif
#if HAS_TMC_SW_SERIAL #if HAS_TMC_SW_SERIAL
#error "TMC220x Software Serial is not supported on the DUE platform." #error "TMC220x Software Serial is not supported on this platform."
#endif
#if USING_PULLDOWNS
#error "PULLDOWN pin mode is not available on DUE boards."
#endif #endif

View File

@@ -2,9 +2,6 @@
* Marlin 3D Printer Firmware * Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] * 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 * 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 * it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or * the Free Software Foundation, either version 3 of the License, or
@@ -16,7 +13,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
@@ -53,7 +50,7 @@
* The net result is that both the g_pinStatus[pin] array and the PIO_OSR register * The net result is that both the g_pinStatus[pin] array and the PIO_OSR register
* needs to be looked at when determining if a pin is an input or an output. * needs to be looked at when determining if a pin is an input or an output.
* *
* b) Due has only pins 6, 7, 8 & 9 enabled for PWMs. FYI - they run at 1kHz * b) Due has only pins 6, 7, 8 & 9 enabled for PWMs. FYI - they run at 1KHz
* *
* c) NUM_DIGITAL_PINS does not include the analog pins * c) NUM_DIGITAL_PINS does not include the analog pins
* *
@@ -67,7 +64,6 @@
#define PRINT_PORT(p) #define PRINT_PORT(p)
#define PRINT_ARRAY_NAME(x) do{ sprintf_P(buffer, PSTR("%-" STRINGIFY(MAX_NAME_LENGTH) "s"), pin_array[x].name); SERIAL_ECHO(buffer); }while(0) #define PRINT_ARRAY_NAME(x) do{ sprintf_P(buffer, PSTR("%-" STRINGIFY(MAX_NAME_LENGTH) "s"), pin_array[x].name); SERIAL_ECHO(buffer); }while(0)
#define PRINT_PIN(p) do{ sprintf_P(buffer, PSTR("%02d"), p); SERIAL_ECHO(buffer); }while(0) #define PRINT_PIN(p) do{ sprintf_P(buffer, PSTR("%02d"), p); SERIAL_ECHO(buffer); }while(0)
#define PRINT_PIN_ANALOG(p) do{ sprintf_P(buffer, PSTR(" (A%2d) "), DIGITAL_PIN_TO_ANALOG_PIN(pin)); SERIAL_ECHO(buffer); }while(0)
#define GET_ARRAY_PIN(p) pin_array[p].pin #define GET_ARRAY_PIN(p) pin_array[p].pin
#define GET_ARRAY_IS_DIGITAL(p) pin_array[p].is_digital #define GET_ARRAY_IS_DIGITAL(p) pin_array[p].is_digital
#define VALID_PIN(pin) (pin >= 0 && pin < (int8_t)NUMBER_PINS_TOTAL ? 1 : 0) #define VALID_PIN(pin) (pin >= 0 && pin < (int8_t)NUMBER_PINS_TOTAL ? 1 : 0)
@@ -86,10 +82,11 @@ bool GET_PINMODE(int8_t pin) { // 1: output, 0: input
|| pwm_status(pin)); || pwm_status(pin));
} }
void pwm_details(int32_t pin) { void pwm_details(int32_t pin) {
if (pwm_status(pin)) { if (pwm_status(pin)) {
uint32_t chan = g_APinDescription[pin].ulPWMChannel; uint32_t chan = g_APinDescription[pin].ulPWMChannel;
SERIAL_ECHOPGM("PWM = ", PWM_INTERFACE->PWM_CH_NUM[chan].PWM_CDTY); SERIAL_ECHOPAIR("PWM = ", PWM_INTERFACE->PWM_CH_NUM[chan].PWM_CDTY);
} }
} }
@@ -182,4 +179,5 @@ void pwm_details(int32_t pin) {
* ----------------+-------- * ----------------+--------
* ID | PB11 * ID | PB11
* VBOF | PB10 * VBOF | PB10
*
*/ */

View File

@@ -16,7 +16,7 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#pragma once #pragma once
@@ -43,22 +43,22 @@
#define SPI_PIN 87 #define SPI_PIN 87
#define SPI_CHAN 1 #define SPI_CHAN 1
#endif #endif
#define SD_SCK_PIN 76 #define SCK_PIN 76
#define SD_MISO_PIN 74 #define MISO_PIN 74
#define SD_MOSI_PIN 75 #define MOSI_PIN 75
#else #else
// defaults // defaults
#define DUE_SOFTWARE_SPI #define DUE_SOFTWARE_SPI
#ifndef SD_SCK_PIN #ifndef SCK_PIN
#define SD_SCK_PIN 52 #define SCK_PIN 52
#endif #endif
#ifndef SD_MISO_PIN #ifndef MISO_PIN
#define SD_MISO_PIN 50 #define MISO_PIN 50
#endif #endif
#ifndef SD_MOSI_PIN #ifndef MOSI_PIN
#define SD_MOSI_PIN 51 #define MOSI_PIN 51
#endif #endif
#endif #endif
/* A.28, A.29, B.21, C.26, C.29 */ /* A.28, A.29, B.21, C.26, C.29 */
#define SD_SS_PIN SDSS #define SS_PIN SDSS

View File

@@ -16,12 +16,14 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
/** /**
* HAL Timers for Arduino Due and compatible (SAM3X8E) * Description: HAL for Arduino Due and compatible (SAM3X8E)
*
* For ARDUINO_ARCH_SAM
*/ */
#ifdef ARDUINO_ARCH_SAM #ifdef ARDUINO_ARCH_SAM
@@ -32,6 +34,8 @@
#include "../../inc/MarlinConfig.h" #include "../../inc/MarlinConfig.h"
#include "HAL.h" #include "HAL.h"
#include "timers.h"
// ------------------------ // ------------------------
// Local defines // Local defines
// ------------------------ // ------------------------
@@ -42,7 +46,7 @@
// Private Variables // Private Variables
// ------------------------ // ------------------------
const tTimerConfig timer_config[NUM_HARDWARE_TIMERS] = { const tTimerConfig TimerConfig [NUM_HARDWARE_TIMERS] = {
{ TC0, 0, TC0_IRQn, 3}, // 0 - [servo timer5] { TC0, 0, TC0_IRQn, 3}, // 0 - [servo timer5]
{ TC0, 1, TC1_IRQn, 0}, // 1 { TC0, 1, TC1_IRQn, 0}, // 1
{ TC0, 2, TC2_IRQn, 2}, // 2 - stepper { TC0, 2, TC2_IRQn, 2}, // 2 - stepper
@@ -66,9 +70,9 @@ const tTimerConfig timer_config[NUM_HARDWARE_TIMERS] = {
*/ */
void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) { void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
Tc *tc = timer_config[timer_num].pTimerRegs; Tc *tc = TimerConfig[timer_num].pTimerRegs;
IRQn_Type irq = timer_config[timer_num].IRQ_Id; IRQn_Type irq = TimerConfig[timer_num].IRQ_Id;
uint32_t channel = timer_config[timer_num].channel; uint32_t channel = TimerConfig[timer_num].channel;
// Disable interrupt, just in case it was already enabled // Disable interrupt, just in case it was already enabled
NVIC_DisableIRQ(irq); NVIC_DisableIRQ(irq);
@@ -86,20 +90,13 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
pmc_set_writeprotect(false); pmc_set_writeprotect(false);
pmc_enable_periph_clk((uint32_t)irq); pmc_enable_periph_clk((uint32_t)irq);
NVIC_SetPriority(irq, timer_config[timer_num].priority); NVIC_SetPriority(irq, TimerConfig [timer_num].priority);
// wave mode, reset counter on match with RC, // wave mode, reset counter on match with RC,
TC_Configure(tc, channel, TC_Configure(tc, channel, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK1);
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 // Set compare value
TC_SetRC(tc, channel, VARIANT_MCK / (HAL_TIMER_PRESCALER) / frequency); TC_SetRC(tc, channel, VARIANT_MCK / 2 / frequency);
// And start timer // And start timer
TC_Start(tc, channel); TC_Start(tc, channel);
@@ -112,12 +109,12 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
} }
void HAL_timer_enable_interrupt(const uint8_t timer_num) { void HAL_timer_enable_interrupt(const uint8_t timer_num) {
IRQn_Type irq = timer_config[timer_num].IRQ_Id; IRQn_Type irq = TimerConfig[timer_num].IRQ_Id;
NVIC_EnableIRQ(irq); NVIC_EnableIRQ(irq);
} }
void HAL_timer_disable_interrupt(const uint8_t timer_num) { void HAL_timer_disable_interrupt(const uint8_t timer_num) {
IRQn_Type irq = timer_config[timer_num].IRQ_Id; IRQn_Type irq = TimerConfig[timer_num].IRQ_Id;
NVIC_DisableIRQ(irq); NVIC_DisableIRQ(irq);
// We NEED memory barriers to ensure Interrupts are actually disabled! // We NEED memory barriers to ensure Interrupts are actually disabled!
@@ -128,11 +125,11 @@ void HAL_timer_disable_interrupt(const uint8_t timer_num) {
// missing from CMSIS: Check if interrupt is enabled or not // missing from CMSIS: Check if interrupt is enabled or not
static bool NVIC_GetEnabledIRQ(IRQn_Type IRQn) { static bool NVIC_GetEnabledIRQ(IRQn_Type IRQn) {
return TEST(NVIC->ISER[uint32_t(IRQn) >> 5], uint32_t(IRQn) & 0x1F); return (NVIC->ISER[(uint32_t)(IRQn) >> 5] & (1 << ((uint32_t)(IRQn) & 0x1F))) != 0;
} }
bool HAL_timer_interrupt_enabled(const uint8_t timer_num) { bool HAL_timer_interrupt_enabled(const uint8_t timer_num) {
IRQn_Type irq = timer_config[timer_num].IRQ_Id; IRQn_Type irq = TimerConfig[timer_num].IRQ_Id;
return NVIC_GetEnabledIRQ(irq); return NVIC_GetEnabledIRQ(irq);
} }

View File

@@ -15,13 +15,15 @@
* GNU General Public License for more details. * GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <http://www.gnu.org/licenses/>.
* *
*/ */
#pragma once #pragma once
/** /**
* HAL Timers for Arduino Due and compatible (SAM3X8E) * HAL for Arduino Due and compatible (SAM3X8E)
*
* For ARDUINO_ARCH_SAM
*/ */
#include <stdint.h> #include <stdint.h>
@@ -35,48 +37,37 @@
typedef uint32_t hal_timer_t; typedef uint32_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX 0xFFFFFFFF #define HAL_TIMER_TYPE_MAX 0xFFFFFFFF
#define HAL_TIMER_PRESCALER 2 #define HAL_TIMER_RATE ((F_CPU) / 2) // frequency of timers peripherals
#define HAL_TIMER_RATE ((F_CPU) / (HAL_TIMER_PRESCALER)) // frequency of timers peripherals
#ifndef MF_TIMER_STEP #ifndef STEP_TIMER_NUM
#define MF_TIMER_STEP 2 // Timer Index for Stepper #define STEP_TIMER_NUM 2 // index of timer to use for stepper
#endif
#ifndef MF_TIMER_PULSE
#define MF_TIMER_PULSE MF_TIMER_STEP
#endif
#ifndef MF_TIMER_TEMP
#define MF_TIMER_TEMP 4 // Timer Index for Temperature
#endif
#ifndef MF_TIMER_TONE
#define MF_TIMER_TONE 6 // index of timer to use for beeper tones
#endif #endif
#define TEMP_TIMER_NUM 4 // index of timer to use for temperature
#define PULSE_TIMER_NUM STEP_TIMER_NUM
#define TONE_TIMER_NUM 6 // index of timer to use for beeper tones
#define TEMP_TIMER_FREQUENCY 1000 // temperature interrupt frequency #define TEMP_TIMER_FREQUENCY 1000 // temperature interrupt frequency
#define STEPPER_TIMER_RATE HAL_TIMER_RATE // frequency of stepper timer (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE) #define STEPPER_TIMER_RATE HAL_TIMER_RATE // frequency of stepper timer (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE)
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // stepper timer ticks per µs #define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // stepper timer ticks per µs
#define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US) #define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US)
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // frequency of pulse timer #define PULSE_TIMER_RATE STEPPER_TIMER_RATE // frequency of pulse timer
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE #define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US #define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP) #define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(STEP_TIMER_NUM)
#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_STEP) #define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(STEP_TIMER_NUM)
#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(MF_TIMER_STEP) #define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(STEP_TIMER_NUM)
#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_TEMP) #define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(TEMP_TIMER_NUM)
#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_TEMP) #define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(TEMP_TIMER_NUM)
#ifndef HAL_STEP_TIMER_ISR #ifndef HAL_STEP_TIMER_ISR
#define HAL_STEP_TIMER_ISR() void TC2_Handler() #define HAL_STEP_TIMER_ISR() void TC2_Handler()
#endif #endif
#ifndef HAL_TEMP_TIMER_ISR #define HAL_TEMP_TIMER_ISR() void TC4_Handler()
#define HAL_TEMP_TIMER_ISR() void TC4_Handler() #define HAL_TONE_TIMER_ISR() void TC6_Handler()
#endif
#ifndef HAL_TONE_TIMER_ISR
#define HAL_TONE_TIMER_ISR() void TC6_Handler()
#endif
// ------------------------ // ------------------------
// Types // Types
@@ -93,7 +84,7 @@ typedef struct {
// Public Variables // Public Variables
// ------------------------ // ------------------------
extern const tTimerConfig timer_config[]; extern const tTimerConfig TimerConfig[];
// ------------------------ // ------------------------
// Public functions // Public functions
@@ -102,17 +93,17 @@ extern const tTimerConfig timer_config[];
void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency); void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency);
FORCE_INLINE static void HAL_timer_set_compare(const uint8_t timer_num, const hal_timer_t compare) { FORCE_INLINE static void HAL_timer_set_compare(const uint8_t timer_num, const hal_timer_t compare) {
const tTimerConfig * const pConfig = &timer_config[timer_num]; const tTimerConfig * const pConfig = &TimerConfig[timer_num];
pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_RC = compare; pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_RC = compare;
} }
FORCE_INLINE static hal_timer_t HAL_timer_get_compare(const uint8_t timer_num) { FORCE_INLINE static hal_timer_t HAL_timer_get_compare(const uint8_t timer_num) {
const tTimerConfig * const pConfig = &timer_config[timer_num]; const tTimerConfig * const pConfig = &TimerConfig[timer_num];
return pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_RC; return pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_RC;
} }
FORCE_INLINE static hal_timer_t HAL_timer_get_count(const uint8_t timer_num) { FORCE_INLINE static hal_timer_t HAL_timer_get_count(const uint8_t timer_num) {
const tTimerConfig * const pConfig = &timer_config[timer_num]; const tTimerConfig * const pConfig = &TimerConfig[timer_num];
return pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_CV; return pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_CV;
} }
@@ -121,9 +112,9 @@ void HAL_timer_disable_interrupt(const uint8_t timer_num);
bool HAL_timer_interrupt_enabled(const uint8_t timer_num); bool HAL_timer_interrupt_enabled(const uint8_t timer_num);
FORCE_INLINE static void HAL_timer_isr_prologue(const uint8_t timer_num) { FORCE_INLINE static void HAL_timer_isr_prologue(const uint8_t timer_num) {
const tTimerConfig * const pConfig = &timer_config[timer_num]; const tTimerConfig * const pConfig = &TimerConfig[timer_num];
// Reading the status register clears the interrupt flag // Reading the status register clears the interrupt flag
pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_SR; pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_SR;
} }
#define HAL_timer_isr_epilogue(T) NOOP #define HAL_timer_isr_epilogue(TIMER_NUM)

View File

@@ -1,19 +0,0 @@
#
# Set upload_command
#
# Windows: bossac.exe
# Other: leave unchanged
#
import pioutil
if pioutil.is_pio_build():
import platform
current_OS = platform.system()
if current_OS == 'Windows':
Import("env")
# Use bossac.exe on Windows
env.Replace(
UPLOADCMD="bossac --info --unlock --write --verify --reset --erase -U false --boot $SOURCE"
)

View File

@@ -43,7 +43,7 @@
#pragma once #pragma once
/** /**
* Support and FAQ: visit <a href="https://www.atmel.com/design-support/">Atmel Support</a> * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/ */
/** /**
@@ -71,7 +71,7 @@
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
/** /**
* \page arduino_due_x_board_info "Arduino Due/X - Board information" * \page arduino_due_x_board_info "Arduino Due/X - Board informations"
* This page lists several definition related to the board description. * This page lists several definition related to the board description.
* *
*/ */
@@ -93,5 +93,5 @@
#define USB_VBOF_GPIO (PIO_PB10_IDX) #define USB_VBOF_GPIO (PIO_PB10_IDX)
#define USB_VBOF_FLAGS (PIO_PERIPH_A | PIO_DEFAULT) #define USB_VBOF_FLAGS (PIO_PERIPH_A | PIO_DEFAULT)
/*! Active level of the USB_VBOF output pin. */ /*! Active level of the USB_VBOF output pin. */
#define USB_VBOF_ACTIVE_STATE LOW #define USB_VBOF_ACTIVE_LEVEL LOW
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */

View File

@@ -41,7 +41,7 @@
* *
*/ */
/* /*
* Support and FAQ: visit <a href="https://www.atmel.com/design-support/">Atmel Support</a> * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/ */
#ifndef UTILS_COMPILER_H #ifndef UTILS_COMPILER_H
@@ -173,11 +173,11 @@
# define __always_inline __forceinline # define __always_inline __forceinline
#elif (defined __GNUC__) #elif (defined __GNUC__)
#ifdef __always_inline #ifdef __always_inline
# undef __always_inline # undef __always_inline
#endif #endif
# define __always_inline inline __attribute__((__always_inline__)) # define __always_inline inline __attribute__((__always_inline__))
#elif (defined __ICCARM__) #elif (defined __ICCARM__)
# define __always_inline _Pragma("inline=forced") # define __always_inline _Pragma("inline=forced")
#endif #endif
/** /**
@@ -188,11 +188,11 @@
* heuristics and not inline the function. * heuristics and not inline the function.
*/ */
#ifdef __CC_ARM #ifdef __CC_ARM
# define __no_inline __attribute__((noinline)) # define __no_inline __attribute__((noinline))
#elif (defined __GNUC__) #elif (defined __GNUC__)
# define __no_inline __attribute__((__noinline__)) # define __no_inline __attribute__((__noinline__))
#elif (defined __ICCARM__) #elif (defined __ICCARM__)
# define __no_inline _Pragma("inline=never") # define __no_inline _Pragma("inline=never")
#endif #endif
/*! \brief This macro is used to test fatal errors. /*! \brief This macro is used to test fatal errors.
@@ -211,9 +211,9 @@
# else # else
#undef TEST_SUITE_DEFINE_ASSERT_MACRO #undef TEST_SUITE_DEFINE_ASSERT_MACRO
# define Assert(expr) \ # define Assert(expr) \
{\ {\
if (!(expr)) while (true);\ if (!(expr)) while (true);\
} }
# endif # endif
#else #else
# define Assert(expr) ((void) 0) # define Assert(expr) ((void) 0)
@@ -609,37 +609,37 @@ typedef struct
# define clz(u) ((u) ? __CLZ(u) : 32) # define clz(u) ((u) ? __CLZ(u) : 32)
#else #else
# define clz(u) (((u) == 0) ? 32 : \ # define clz(u) (((u) == 0) ? 32 : \
((u) & (1UL << 31)) ? 0 : \ ((u) & (1ul << 31)) ? 0 : \
((u) & (1UL << 30)) ? 1 : \ ((u) & (1ul << 30)) ? 1 : \
((u) & (1UL << 29)) ? 2 : \ ((u) & (1ul << 29)) ? 2 : \
((u) & (1UL << 28)) ? 3 : \ ((u) & (1ul << 28)) ? 3 : \
((u) & (1UL << 27)) ? 4 : \ ((u) & (1ul << 27)) ? 4 : \
((u) & (1UL << 26)) ? 5 : \ ((u) & (1ul << 26)) ? 5 : \
((u) & (1UL << 25)) ? 6 : \ ((u) & (1ul << 25)) ? 6 : \
((u) & (1UL << 24)) ? 7 : \ ((u) & (1ul << 24)) ? 7 : \
((u) & (1UL << 23)) ? 8 : \ ((u) & (1ul << 23)) ? 8 : \
((u) & (1UL << 22)) ? 9 : \ ((u) & (1ul << 22)) ? 9 : \
((u) & (1UL << 21)) ? 10 : \ ((u) & (1ul << 21)) ? 10 : \
((u) & (1UL << 20)) ? 11 : \ ((u) & (1ul << 20)) ? 11 : \
((u) & (1UL << 19)) ? 12 : \ ((u) & (1ul << 19)) ? 12 : \
((u) & (1UL << 18)) ? 13 : \ ((u) & (1ul << 18)) ? 13 : \
((u) & (1UL << 17)) ? 14 : \ ((u) & (1ul << 17)) ? 14 : \
((u) & (1UL << 16)) ? 15 : \ ((u) & (1ul << 16)) ? 15 : \
((u) & (1UL << 15)) ? 16 : \ ((u) & (1ul << 15)) ? 16 : \
((u) & (1UL << 14)) ? 17 : \ ((u) & (1ul << 14)) ? 17 : \
((u) & (1UL << 13)) ? 18 : \ ((u) & (1ul << 13)) ? 18 : \
((u) & (1UL << 12)) ? 19 : \ ((u) & (1ul << 12)) ? 19 : \
((u) & (1UL << 11)) ? 20 : \ ((u) & (1ul << 11)) ? 20 : \
((u) & (1UL << 10)) ? 21 : \ ((u) & (1ul << 10)) ? 21 : \
((u) & (1UL << 9)) ? 22 : \ ((u) & (1ul << 9)) ? 22 : \
((u) & (1UL << 8)) ? 23 : \ ((u) & (1ul << 8)) ? 23 : \
((u) & (1UL << 7)) ? 24 : \ ((u) & (1ul << 7)) ? 24 : \
((u) & (1UL << 6)) ? 25 : \ ((u) & (1ul << 6)) ? 25 : \
((u) & (1UL << 5)) ? 26 : \ ((u) & (1ul << 5)) ? 26 : \
((u) & (1UL << 4)) ? 27 : \ ((u) & (1ul << 4)) ? 27 : \
((u) & (1UL << 3)) ? 28 : \ ((u) & (1ul << 3)) ? 28 : \
((u) & (1UL << 2)) ? 29 : \ ((u) & (1ul << 2)) ? 29 : \
((u) & (1UL << 1)) ? 30 : \ ((u) & (1ul << 1)) ? 30 : \
31) 31)
#endif #endif
#endif #endif
@@ -654,38 +654,38 @@ typedef struct
#if (defined __GNUC__) || (defined __CC_ARM) #if (defined __GNUC__) || (defined __CC_ARM)
# define ctz(u) ((u) ? __builtin_ctz(u) : 32) # define ctz(u) ((u) ? __builtin_ctz(u) : 32)
#else #else
# define ctz(u) ((u) & (1UL << 0) ? 0 : \ # define ctz(u) ((u) & (1ul << 0) ? 0 : \
(u) & (1UL << 1) ? 1 : \ (u) & (1ul << 1) ? 1 : \
(u) & (1UL << 2) ? 2 : \ (u) & (1ul << 2) ? 2 : \
(u) & (1UL << 3) ? 3 : \ (u) & (1ul << 3) ? 3 : \
(u) & (1UL << 4) ? 4 : \ (u) & (1ul << 4) ? 4 : \
(u) & (1UL << 5) ? 5 : \ (u) & (1ul << 5) ? 5 : \
(u) & (1UL << 6) ? 6 : \ (u) & (1ul << 6) ? 6 : \
(u) & (1UL << 7) ? 7 : \ (u) & (1ul << 7) ? 7 : \
(u) & (1UL << 8) ? 8 : \ (u) & (1ul << 8) ? 8 : \
(u) & (1UL << 9) ? 9 : \ (u) & (1ul << 9) ? 9 : \
(u) & (1UL << 10) ? 10 : \ (u) & (1ul << 10) ? 10 : \
(u) & (1UL << 11) ? 11 : \ (u) & (1ul << 11) ? 11 : \
(u) & (1UL << 12) ? 12 : \ (u) & (1ul << 12) ? 12 : \
(u) & (1UL << 13) ? 13 : \ (u) & (1ul << 13) ? 13 : \
(u) & (1UL << 14) ? 14 : \ (u) & (1ul << 14) ? 14 : \
(u) & (1UL << 15) ? 15 : \ (u) & (1ul << 15) ? 15 : \
(u) & (1UL << 16) ? 16 : \ (u) & (1ul << 16) ? 16 : \
(u) & (1UL << 17) ? 17 : \ (u) & (1ul << 17) ? 17 : \
(u) & (1UL << 18) ? 18 : \ (u) & (1ul << 18) ? 18 : \
(u) & (1UL << 19) ? 19 : \ (u) & (1ul << 19) ? 19 : \
(u) & (1UL << 20) ? 20 : \ (u) & (1ul << 20) ? 20 : \
(u) & (1UL << 21) ? 21 : \ (u) & (1ul << 21) ? 21 : \
(u) & (1UL << 22) ? 22 : \ (u) & (1ul << 22) ? 22 : \
(u) & (1UL << 23) ? 23 : \ (u) & (1ul << 23) ? 23 : \
(u) & (1UL << 24) ? 24 : \ (u) & (1ul << 24) ? 24 : \
(u) & (1UL << 25) ? 25 : \ (u) & (1ul << 25) ? 25 : \
(u) & (1UL << 26) ? 26 : \ (u) & (1ul << 26) ? 26 : \
(u) & (1UL << 27) ? 27 : \ (u) & (1ul << 27) ? 27 : \
(u) & (1UL << 28) ? 28 : \ (u) & (1ul << 28) ? 28 : \
(u) & (1UL << 29) ? 29 : \ (u) & (1ul << 29) ? 29 : \
(u) & (1UL << 30) ? 30 : \ (u) & (1ul << 30) ? 30 : \
(u) & (1UL << 31) ? 31 : \ (u) & (1ul << 31) ? 31 : \
32) 32)
#endif #endif
#endif #endif
@@ -1059,7 +1059,7 @@ static inline void convert_64_bit_to_byte_array(uint64_t value, uint8_t *data)
while (val_index < 8) while (val_index < 8)
{ {
data[val_index++] = value & 0xFF; data[val_index++] = value & 0xFF;
value >>= 8; value = value >> 8;
} }
} }
@@ -1106,16 +1106,17 @@ static inline uint16_t convert_byte_array_to_16_bit(uint8_t *data)
/* Converts a 8 Byte array into a 32-Bit value */ /* Converts a 8 Byte array into a 32-Bit value */
static inline uint32_t convert_byte_array_to_32_bit(uint8_t *data) static inline uint32_t convert_byte_array_to_32_bit(uint8_t *data)
{ {
union union
{ {
uint32_t u32; uint32_t u32;
uint8_t u8[8]; uint8_t u8[8];
}long_addr; }long_addr;
uint8_t index; uint8_t index;
for (index = 0; index < 4; index++) { for (index = 0; index < 4; index++)
long_addr.u8[index] = *data++; {
} long_addr.u8[index] = *data++;
return long_addr.u32; }
return long_addr.u32;
} }
/** /**

View File

@@ -41,7 +41,7 @@
* *
*/ */
/* /*
* Support and FAQ: visit <a href="https://www.atmel.com/design-support/">Atmel Support</a> * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/ */
#ifndef _CONF_ACCESS_H_ #ifndef _CONF_ACCESS_H_

View File

@@ -41,7 +41,7 @@
* *
*/ */
/* /*
* Support and FAQ: visit <a href="https://www.atmel.com/design-support/">Atmel Support</a> * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/ */
#ifndef CONF_CLOCK_H_INCLUDED #ifndef CONF_CLOCK_H_INCLUDED

View File

@@ -41,7 +41,7 @@
* *
*/ */
/* /*
* Support and FAQ: visit <a href="https://www.atmel.com/design-support/">Atmel Support</a> * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/ */
#ifndef _CONF_USB_H_ #ifndef _CONF_USB_H_
@@ -78,6 +78,10 @@
//! To define a Full speed device //! To define a Full speed device
//#define USB_DEVICE_FULL_SPEED //#define USB_DEVICE_FULL_SPEED
#if MB(ARCHIM1)
#define USB_DEVICE_FULL_SPEED
#endif
//! To authorize the High speed //! To authorize the High speed
#ifndef USB_DEVICE_FULL_SPEED #ifndef USB_DEVICE_FULL_SPEED
#if (UC3A3||UC3A4) #if (UC3A3||UC3A4)

View File

@@ -53,7 +53,7 @@
* *
******************************************************************************/ ******************************************************************************/
/* /*
* Support and FAQ: visit <a href="https://www.atmel.com/design-support/">Atmel Support</a> * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/ */
#ifdef ARDUINO_ARCH_SAM #ifdef ARDUINO_ARCH_SAM

View File

@@ -53,7 +53,7 @@
* *
******************************************************************************/ ******************************************************************************/
/* /*
* Support and FAQ: visit <a href="https://www.atmel.com/design-support/">Atmel Support</a> * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
*/ */

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