Merge branch 'bugfix-2.1.x' into Raptor_2.0.X_Devel
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.187.0/containers/python-3/.devcontainer/base.Dockerfile
|
||||
|
||||
# [Choice] Python version: 3, 3.9, 3.8, 3.7, 3.6
|
||||
ARG VARIANT="3.9.0-buster"
|
||||
FROM python:${VARIANT}
|
||||
|
||||
# [Option] Install Node.js
|
||||
ARG INSTALL_NODE="true"
|
||||
ARG NODE_VERSION="lts/*"
|
||||
RUN if [ "${INSTALL_NODE}" = "true" ]; then su vscode -c "umask 0002 && . /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi
|
||||
|
||||
# [Optional] If your pip requirements rarely change, uncomment this section to add them to the image.
|
||||
# COPY requirements.txt /tmp/pip-tmp/
|
||||
# RUN pip3 --disable-pip-version-check --no-cache-dir install -r /tmp/pip-tmp/requirements.txt \
|
||||
# && rm -rf /tmp/pip-tmp
|
||||
|
||||
# [Optional] Uncomment this section to install additional OS packages.
|
||||
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
|
||||
# && apt-get -y install --no-install-recommends <your-package-list-here>
|
||||
|
||||
# [Optional] Uncomment this line to install global node packages.
|
||||
# RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g <your-package-here>" 2>&1
|
||||
|
||||
|
||||
RUN pip install -U https://github.com/platformio/platformio-core/archive/develop.zip
|
||||
RUN platformio update
|
||||
# To get the test platforms
|
||||
RUN pip install PyYaml
|
||||
#ENV PATH /code/buildroot/bin/:/code/buildroot/tests/:${PATH}
|
||||
@@ -0,0 +1,51 @@
|
||||
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
|
||||
// https://github.com/microsoft/vscode-dev-containers/tree/v0.187.0/containers/python-3
|
||||
{
|
||||
"name": "Python 3",
|
||||
"build": {
|
||||
"dockerfile": "Dockerfile",
|
||||
"context": "..",
|
||||
"args": {
|
||||
// Update 'VARIANT' to pick a Python version: 3, 3.6, 3.7, 3.8, 3.9
|
||||
"VARIANT": "3.9.0-buster",
|
||||
// Options
|
||||
"INSTALL_NODE": "false",
|
||||
"NODE_VERSION": "lts/*"
|
||||
}
|
||||
},
|
||||
|
||||
// Set *default* container specific settings.json values on container create.
|
||||
"settings": {
|
||||
"python.pythonPath": "/usr/local/bin/python",
|
||||
"python.languageServer": "Pylance",
|
||||
"python.linting.enabled": true,
|
||||
"python.linting.pylintEnabled": true,
|
||||
"python.formatting.autopep8Path": "/usr/local/py-utils/bin/autopep8",
|
||||
"python.formatting.blackPath": "/usr/local/py-utils/bin/black",
|
||||
"python.formatting.yapfPath": "/usr/local/py-utils/bin/yapf",
|
||||
"python.linting.banditPath": "/usr/local/py-utils/bin/bandit",
|
||||
"python.linting.flake8Path": "/usr/local/py-utils/bin/flake8",
|
||||
"python.linting.mypyPath": "/usr/local/py-utils/bin/mypy",
|
||||
"python.linting.pycodestylePath": "/usr/local/py-utils/bin/pycodestyle",
|
||||
"python.linting.pydocstylePath": "/usr/local/py-utils/bin/pydocstyle",
|
||||
"python.linting.pylintPath": "/usr/local/py-utils/bin/pylint"
|
||||
},
|
||||
|
||||
// Add the IDs of extensions you want installed when the container is created.
|
||||
"extensions": [
|
||||
"ms-python.python",
|
||||
"ms-python.vscode-pylance",
|
||||
"platformio.platformio-ide",
|
||||
"marlinfirmware.auto-build",
|
||||
"editorconfig.editorconfig"
|
||||
],
|
||||
|
||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||
// "forwardPorts": [],
|
||||
|
||||
// Use 'postCreateCommand' to run commands after the container is created.
|
||||
// "postCreateCommand": "pip3 install --user -r requirements.txt",
|
||||
|
||||
// Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
|
||||
// "remoteUser": "vscode"
|
||||
}
|
||||
+5
-1
@@ -14,6 +14,10 @@ end_of_line = lf
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[{*.py,*.conf,*.sublime-project}]
|
||||
[{*.py}]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[{*.conf,*.sublime-project}]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
name: 🪲 Report a bug
|
||||
description: Create a bug report to help improve Marlin Firmware
|
||||
title: "[BUG] (bug summary)"
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: >
|
||||
Do you want to ask a question? Are you looking for support? Please use one of the [support links](https://github.com/MarlinFirmware/Marlin/issues/new/choose).
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
**Thank you for reporting a bug in Marlin Firmware!**
|
||||
|
||||
## Before Reporting a Bug
|
||||
|
||||
- Read and understand Marlin's [Code of Conduct](https://github.com/MarlinFirmware/Marlin/blob/bugfix-2.1.x/.github/code_of_conduct.md). You are expected to comply with it, including treating everyone with respect.
|
||||
|
||||
- Test with the [`bugfix-2.1.x` branch](https://github.com/MarlinFirmware/Marlin/archive/bugfix-2.1.x.zip) to see whether the issue still exists.
|
||||
|
||||
## Instructions
|
||||
|
||||
Please follow the instructions below. Failure to do so may result in your issue being closed. See [Contributing to Marlin](https://github.com/MarlinFirmware/Marlin/blob/bugfix-2.1.x/.github/contributing.md) for additional guidelines.
|
||||
|
||||
1. Provide a good title starting with [BUG].
|
||||
2. Fill out all sections of this bug report form.
|
||||
3. Always attach configuration files so we can build and test your setup.
|
||||
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Did you test the latest `bugfix-2.1.x` code?
|
||||
description: >-
|
||||
Always try the latest code to make sure the issue you are reporting is not already fixed. To download
|
||||
the latest code just [click this link](https://github.com/MarlinFirmware/Marlin/archive/bugfix-2.1.x.zip).
|
||||
options:
|
||||
- Yes, and the problem still exists.
|
||||
- No, but I will test it now!
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
# Bug Details
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Bug Description
|
||||
description: >-
|
||||
Describe the bug in this section. Tell us what you were trying to do and what
|
||||
happened that you did not expect. Provide a clear and concise description of the
|
||||
problem and include as many details as possible.
|
||||
|
||||
When pasting formatted text don't forget to put ` ``` ` (on its own line) before and after to make it readable.
|
||||
placeholder: |
|
||||
Marlin doesn't work.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Bug Timeline
|
||||
description: Is this a new bug or an old issue? When did it first start?
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Expected behavior
|
||||
description: >-
|
||||
What did you expect to happen?
|
||||
placeholder: I expected it to move left.
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Actual behavior
|
||||
description: What actually happened instead?
|
||||
placeholder: It moved right instead of left.
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Steps to Reproduce
|
||||
description: >-
|
||||
Please describe the steps needed to reproduce the issue.
|
||||
placeholder: |
|
||||
1. [First Step] ...
|
||||
2. [Second Step] ...
|
||||
3. [and so on] ...
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
# Your Setup
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Version of Marlin Firmware
|
||||
description: "See the About Menu on the LCD or the output of `M115`. NOTE: For older releases we only patch critical bugs."
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Printer model
|
||||
description: Creality Ender 3, Prusa mini, or Kossel Delta?
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Electronics
|
||||
description: Stock electronics, upgrade board, or something else?
|
||||
|
||||
- type: input
|
||||
attributes:
|
||||
label: Add-ons
|
||||
description: Please list any hardware add-ons that could be involved.
|
||||
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Bed Leveling
|
||||
description: What kind of bed leveling compensation are you using?
|
||||
options:
|
||||
- UBL Bilinear mesh
|
||||
- ABL Bilinear mesh
|
||||
- ABL Linear grid
|
||||
- ABL 3-point
|
||||
- MBL Manual Bed Leveling
|
||||
- No Bed Leveling
|
||||
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Your Slicer
|
||||
description: Do you use Slic3r, Prusa Slicer, Simplify3D, IdeaMaker...?
|
||||
options:
|
||||
- Slic3r
|
||||
- Simplify3D
|
||||
- Prusa Slicer
|
||||
- IdeaMaker
|
||||
- Cura
|
||||
- Other (explain below)
|
||||
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Host Software
|
||||
description: Do you use OctoPrint, Repetier Host, Pronterface...?
|
||||
options:
|
||||
- SD Card (headless)
|
||||
- Repetier Host
|
||||
- OctoPrint
|
||||
- Pronterface
|
||||
- Cura
|
||||
- Same as my slicer
|
||||
- Other (explain below)
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
# Attachments
|
||||
|
||||
- type: checkboxes
|
||||
attributes:
|
||||
label: Don't forget to include
|
||||
options:
|
||||
- label: A ZIP file containing your `Configuration.h` and `Configuration_adv.h`.
|
||||
required: true
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
### Optional items to include:
|
||||
- 'Log output from the host. (`M111 S247` for maximum logging.)'
|
||||
- Images or videos demonstrating the problem, if it helps to make it clear.
|
||||
- A G-Code file that exposes the problem, if not affecting _all_ G-code.
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional information & file uploads
|
||||
description: >-
|
||||
If you've made any other modifications to the firmware, please describe them in detail.
|
||||
|
||||
When pasting formatted text don't forget to put ` ``` ` (on its own line) before and after to make it readable.
|
||||
@@ -0,0 +1,20 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: 📖 Marlin Documentation
|
||||
url: https://marlinfw.org/
|
||||
about: Lots of documentation on installing and using Marlin.
|
||||
- name: 👤 MarlinFirmware Facebook group
|
||||
url: https://www.facebook.com/groups/1049718498464482
|
||||
about: Please ask and answer questions here.
|
||||
- name: 🕹 Marlin on Discord
|
||||
url: https://discord.gg/n5NJ59y
|
||||
about: Join the Discord server for support and discussion.
|
||||
- name: 🔗 Marlin Discussion Forum
|
||||
url: https://reprap.org/forum/list.php?415
|
||||
about: A searchable web forum hosted by RepRap dot org.
|
||||
- name: 📺 Marlin Videos on YouTube
|
||||
url: https://www.youtube.com/results?search_query=marlin+firmware
|
||||
about: Tutorials and more from Marlin users all around the world. Great for new users!
|
||||
- name: 💸 Want to donate?
|
||||
url: https://www.thinkyhead.com/donate-to-marlin
|
||||
about: Please take a look at the various options to support Marlin Firmware's development financially!
|
||||
@@ -0,0 +1,44 @@
|
||||
name: ✨ Request a feature
|
||||
description: Request a new Marlin Firmware feature
|
||||
title: "[FR] (feature summary)"
|
||||
labels: 'T: Feature Request'
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: >
|
||||
Do you want to ask a question? Are you looking for support? Please use one of the [support links](https://github.com/MarlinFirmware/Marlin/issues/new/choose).
|
||||
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: >
|
||||
**Thank you for requesting a new Marlin Firmware feature!**
|
||||
|
||||
## Before Requesting a Feature
|
||||
|
||||
- Read and understand Marlin's [Code of Conduct](https://github.com/MarlinFirmware/Marlin/blob/master/.github/code_of_conduct.md). You are expected to comply with it, including treating everyone with respect.
|
||||
|
||||
- Check the latest [`bugfix-2.1.x` branch](https://github.com/MarlinFirmware/Marlin/archive/bugfix-2.1.x.zip) to see if the feature already exists.
|
||||
|
||||
- Before you proceed with your request, please consider if it is necessary to make it into a firmware feature, or if it may be better suited for a slicer or host feature.
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Is your feature request related to a problem? Please describe.
|
||||
description: A clear description of the problem (e.g., "I need X but Marlin can't do it [...]").
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Are you looking for hardware support?
|
||||
description: Tell us the printer, board, or peripheral that needs support.
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Describe the feature you want
|
||||
description: A clear description of the feature and how you think it should work.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional context
|
||||
description: Add any other context or screenshots about the feature request here.
|
||||
+10
-7
@@ -34,8 +34,11 @@ This project and everyone participating in it is governed by the [Marlin Code of
|
||||
|
||||
We have a Message Board and a Facebook group where our knowledgable user community can provide helpful advice if you have questions.
|
||||
|
||||
* [Marlin RepRap forum](https://reprap.org/forum/list.php?415)
|
||||
* [MarlinFirmware on Facebook](https://www.facebook.com/groups/1049718498464482/)
|
||||
- [Marlin Documentation](https://marlinfw.org) - Official Marlin documentation
|
||||
- Facebook Group ["Marlin Firmware"](https://www.facebook.com/groups/1049718498464482/)
|
||||
- RepRap.org [Marlin Forum](https://forums.reprap.org/list.php?415)
|
||||
- Facebook Group ["Marlin Firmware for 3D Printers"](https://www.facebook.com/groups/3Dtechtalk/)
|
||||
- [Marlin Configuration](https://www.youtube.com/results?search_query=marlin+configuration) on YouTube
|
||||
|
||||
If chat is more your speed, you can join the MarlinFirmware Discord server:
|
||||
|
||||
@@ -50,13 +53,13 @@ If chat is more your speed, you can join the MarlinFirmware Discord server:
|
||||
|
||||
This section guides you through submitting a Bug Report for Marlin. Following these guidelines helps maintainers and the community understand your report, reproduce the behavior, and find related reports.
|
||||
|
||||
Before creating a Bug Report, please test the "nightly" development branch, as you might find out that you don't need to create one. When you are creating a Bug Report, please [include as many details as possible](#how-do-i-submit-a-good-bug-report). Fill out [the required template](issue_template.md), the information it asks for helps us resolve issues faster.
|
||||
Before creating a Bug Report, please test the "nightly" development branch, as you might find out that you don't need to create one. When you are creating a Bug Report, please [include as many details as possible](#how-do-i-submit-a-good-bug-report). Fill out [the required template](ISSUE_TEMPLATE/bug_report.yml), the information it asks for helps us resolve issues faster.
|
||||
|
||||
> **Note:** Regressions can happen. If you find a **Closed** issue that seems like your issue, go ahead and open a new issue and include a link to the original issue in the body of your new one. All you need to create a link is the issue number, preceded by #. For example, #8888.
|
||||
|
||||
#### How Do I Submit A (Good) Bug Report?
|
||||
|
||||
Bugs are tracked as [GitHub issues](https://guides.github.com/features/issues/). Use the New Issue button to create an issue and provide the following information by filling in [the template](issue_template.md).
|
||||
Bugs are tracked as [GitHub issues](https://guides.github.com/features/issues/). Use the New Issue button to create an issue and provide the following information by filling in [the template](ISSUE_TEMPLATE/bug_report.yml).
|
||||
|
||||
Explain the problem and include additional details to help maintainers reproduce the problem:
|
||||
|
||||
@@ -88,12 +91,12 @@ Include details about your configuration and environment:
|
||||
|
||||
This section guides you through submitting a suggestion for Marlin, including completely new features and minor improvements to existing functionality. Following these guidelines helps maintainers and the community understand your suggestion and find related suggestions.
|
||||
|
||||
Before creating a suggestion, please check [this list](#before-submitting-a-suggestion) as you might find out that you don't need to create one. When you are creating an enhancement suggestion, please [include as many details as possible](#how-do-i-submit-a-good-enhancement-suggestion). Fill in [the template](issue_template.md), including the steps that you imagine you would take if the feature you're requesting existed.
|
||||
Before creating a suggestion, please check [this list](https://github.com/MarlinFirmware/Marlin/issues?q=is%3Aopen+is%3Aissue+label%3A%22T%3A+Feature+Request%22) as you might find out that you don't need to create one. When you are creating an enhancement suggestion, please [include as many details as possible](#how-do-i-submit-a-good-feature-request). Fill in [the template](ISSUE_TEMPLATE/feature_request.yml), including the steps that you imagine you would take if the feature you're requesting existed.
|
||||
|
||||
#### Before Submitting a Feature Request
|
||||
|
||||
* **Check the [Marlin website](https://marlinfw.org/)** for tips — you might discover that the feature is already included. Most importantly, check if you're using [the latest version of Marlin](https://github.com/MarlinFirmware/Marlin/releases) and if you can get the desired behavior by changing [Marlin's config settings](https://marlinfw.org/docs/configuration/configuration.html).
|
||||
* **Perform a [cursory search](https://github.com/MarlinFirmware/Marlin/issues?q=is%3Aissue)** to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one.
|
||||
* **Perform a [cursory search](https://github.com/MarlinFirmware/Marlin/issues?q=is%3Aopen+is%3Aissue+label%3A%22T%3A+Feature+Request%22)** to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one.
|
||||
|
||||
#### How Do I Submit A (Good) Feature Request?
|
||||
|
||||
@@ -116,7 +119,7 @@ Unsure where to begin contributing to Marlin? You can start by looking through t
|
||||
|
||||
### Pull Requests
|
||||
|
||||
Pull Requests should always be targeted to working branches (e.g., `bugfix-1.1.x` and/or `bugfix-2.0.x`) and never to release branches (e.g., `1.1.x`). If this is your first Pull Request, please read our [Guide to Pull Requests](https://marlinfw.org/docs/development/getting_started_pull_requests.html) and Github's [Pull Request](https://help.github.com/articles/creating-a-pull-request/) documentation.
|
||||
Pull Requests should always be targeted to working branches (e.g., `bugfix-2.1.x` and/or `bugfix-1.1.x`) and never to release branches (e.g., `2.0.x` and/or `1.1.x`). If this is your first Pull Request, please read our [Guide to Pull Requests](https://marlinfw.org/docs/development/getting_started_pull_requests.html) and Github's [Pull Request](https://help.github.com/articles/creating-a-pull-request/) documentation.
|
||||
|
||||
* Fill in [the required template](pull_request_template.md).
|
||||
* Don't include issue numbers in the PR title.
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
<!--
|
||||
|
||||
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/bugfix-2.0.x/.github/code_of_conduct.md
|
||||
|
||||
Do you want to ask a question? Are you looking for support? Please don't post here. Instead use one of the following options:
|
||||
|
||||
- The Marlin Firmware forum at https://reprap.org/forum/list.php?415
|
||||
- The MarlinFirmware Facebook Group at https://www.facebook.com/groups/1049718498464482/
|
||||
- The MarlinFirmware Discord Server at https://discord.gg/n5NJ59y.
|
||||
|
||||
Before filing an issue be sure to test the latest "bugfix" branch to see whether the issue is already addressed.
|
||||
|
||||
-->
|
||||
|
||||
### Description
|
||||
|
||||
<!-- Description of the bug or requested feature -->
|
||||
|
||||
### Steps to Reproduce
|
||||
|
||||
<!-- If this is a Bug Report, 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
|
||||
|
||||
* Include a ZIP file containing your `Configuration.h` and `Configuration_adv.h` files.
|
||||
* Provide pictures or links to videos that clearly demonstrate the issue.
|
||||
* See [How Can I Contribute](#how-can-i-contribute) for additional guidelines.
|
||||
@@ -1,23 +1,33 @@
|
||||
### Requirements
|
||||
<!--
|
||||
|
||||
* Filling out this template is required. Pull Requests without a clear description may be closed at the maintainers' discretion.
|
||||
Submitting a Pull Request
|
||||
|
||||
- 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
|
||||
|
||||
<!--
|
||||
|
||||
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.
|
||||
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.
|
||||
|
||||
-->
|
||||
|
||||
### Requirements
|
||||
|
||||
<!-- Does this PR require a specific board, LCD, etc.? -->
|
||||
|
||||
### Benefits
|
||||
|
||||
<!-- What does this fix or improve? -->
|
||||
<!-- What does this PR fix or improve? -->
|
||||
|
||||
### Configurations
|
||||
|
||||
<!-- Attach any Configuration.h, Configuration_adv.h, or platformio.ini files needed to compile/test your Pull Request. -->
|
||||
<!-- Attach Configurations ZIP and any other files needed to test this PR. -->
|
||||
|
||||
### Related Issues
|
||||
|
||||
<!-- Whether this fixes a bug or fulfills a feature request, please list any related Issues here. -->
|
||||
<!-- Does this PR fix a bug or fulfill a Feature Request? Link related Issues here. -->
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
#
|
||||
# bump-date.yml
|
||||
# Bump the distribution date once per day
|
||||
#
|
||||
|
||||
name: Bump Distribution Date
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 */6 * * *'
|
||||
|
||||
jobs:
|
||||
bump_date:
|
||||
name: Bump Distribution Date
|
||||
if: github.repository == 'MarlinFirmware/Marlin'
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
|
||||
- name: Check out bugfix-2.1.x
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: bugfix-2.1.x
|
||||
|
||||
- name: Bump Date (bugfix-2.0.x)
|
||||
run: |
|
||||
# Inline Bump Script
|
||||
if [[ ! "$( git log -1 --pretty=%B )" =~ ^\[cron\] ]]; then
|
||||
DIST=$( date +"%Y-%m-%d" )
|
||||
eval "sed -E -i 's/(#define +STRING_DISTRIBUTION_DATE) .*$/\1 \"$DIST\"/g' Marlin/src/inc/Version.h" && \
|
||||
eval "sed -E -i 's/(#define +STRING_DISTRIBUTION_DATE) .*$/\1 \"$DIST\"/g' Marlin/Version.h" && \
|
||||
git config user.name "${GITHUB_ACTOR}" && \
|
||||
git config user.email "${GITHUB_ACTOR}@users.noreply.github.com" && \
|
||||
git add . && \
|
||||
git commit -m "[cron] Bump distribution date ($DIST)" && \
|
||||
git push
|
||||
fi
|
||||
exit 0
|
||||
|
||||
- name: Check out bugfix-2.1.x
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
ref: bugfix-2.1.x
|
||||
|
||||
- name: Bump Date (bugfix-2.1.x)
|
||||
run: |
|
||||
# Inline Bump Script
|
||||
if [[ ! "$( git log -1 --pretty=%B )" =~ ^\[cron\] ]]; then
|
||||
DIST=$( date +"%Y-%m-%d" )
|
||||
eval "sed -E -i 's/(#define +STRING_DISTRIBUTION_DATE) .*$/\1 \"$DIST\"/g' Marlin/src/inc/Version.h" && \
|
||||
eval "sed -E -i 's/(#define +STRING_DISTRIBUTION_DATE) .*$/\1 \"$DIST\"/g' Marlin/Version.h" && \
|
||||
git config user.name "${GITHUB_ACTOR}" && \
|
||||
git config user.email "${GITHUB_ACTOR}@users.noreply.github.com" && \
|
||||
git add . && \
|
||||
git commit -m "[cron] Bump distribution date ($DIST)" && \
|
||||
git push
|
||||
fi
|
||||
exit 0
|
||||
@@ -0,0 +1,34 @@
|
||||
#
|
||||
# check-pr.yml
|
||||
# Close PRs directed at release branches
|
||||
#
|
||||
|
||||
name: PR Bad Target
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened]
|
||||
branches:
|
||||
- 1.0.x
|
||||
- 1.1.x
|
||||
- 2.0.x
|
||||
- 2.1.x
|
||||
|
||||
jobs:
|
||||
bad_target:
|
||||
name: PR Bad Target
|
||||
if: github.repository == 'MarlinFirmware/Marlin'
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: superbrothers/close-pull-request@v3
|
||||
with:
|
||||
comment: >
|
||||
Thanks for your contribution! Unfortunately we can't accept PRs directed at release branches. We make patches to the bugfix branches and only later do we push them out as releases.
|
||||
|
||||
Please redo this PR starting with the `bugfix-2.1.x` branch and be careful to target `bugfix-2.1.x` when resubmitting the PR. Patches may also target `bugfix-2.0.x` if they are specifically for 2.0.9.x.
|
||||
|
||||
It may help to set your fork's default branch to `bugfix-2.1.x`.
|
||||
|
||||
See [this page](https://marlinfw.org/docs/development/getting_started_pull_requests.html) for full instructions.
|
||||
@@ -0,0 +1,39 @@
|
||||
#
|
||||
# clean-closed.yml
|
||||
# Remove obsolete labels when an Issue or PR is closed
|
||||
#
|
||||
|
||||
name: Clean Closed
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [closed]
|
||||
issues:
|
||||
types: [closed]
|
||||
|
||||
jobs:
|
||||
remove_label:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
label:
|
||||
- "S: Don't Merge"
|
||||
- "S: Hold for 2.1"
|
||||
- "S: Please Merge"
|
||||
- "S: Please Test"
|
||||
- "help wanted"
|
||||
- "Needs: Discussion"
|
||||
- "Needs: Documentation"
|
||||
- "Needs: More Data"
|
||||
- "Needs: Patch"
|
||||
- "Needs: Testing"
|
||||
- "Needs: Work"
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Remove Labels
|
||||
uses: actions-ecosystem/action-remove-labels@v1
|
||||
with:
|
||||
github_token: ${{ github.token }}
|
||||
labels: ${{ matrix.label }}
|
||||
@@ -0,0 +1,28 @@
|
||||
#
|
||||
# close-stale.yml
|
||||
# Close open issues after a period of inactivity
|
||||
#
|
||||
|
||||
name: Close Stale Issues
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "22 1 * * *"
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
name: Close Stale Issues
|
||||
if: github.repository == 'MarlinFirmware/Marlin'
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/stale@v3
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
stale-issue-message: 'This issue has had no activity in the last 60 days. Please add a reply if you want to keep this issue active, otherwise it will be automatically closed within 10 days.'
|
||||
days-before-stale: 60
|
||||
days-before-close: 10
|
||||
stale-issue-label: 'stale-closing-soon'
|
||||
exempt-all-assignees: true
|
||||
exempt-issue-labels: 'Bug: Confirmed !,T: Feature Request,Needs: More Data,Needs: Discussion,Needs: Documentation,Needs: Patch,Needs: Work,Needs: Testing,help wanted,no-locking'
|
||||
@@ -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: ''
|
||||
@@ -8,7 +8,7 @@ name: CI
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- bugfix-2.0.x
|
||||
- bugfix-2.1.x
|
||||
paths-ignore:
|
||||
- config/**
|
||||
- data/**
|
||||
@@ -16,7 +16,7 @@ on:
|
||||
- '**/*.md'
|
||||
push:
|
||||
branches:
|
||||
- bugfix-2.0.x
|
||||
- bugfix-2.1.x
|
||||
paths-ignore:
|
||||
- config/**
|
||||
- data/**
|
||||
@@ -44,7 +44,9 @@ jobs:
|
||||
- teensy31
|
||||
- teensy35
|
||||
- teensy41
|
||||
- SAMD21_minitronics20
|
||||
- SAMD51_grandcentral_m4
|
||||
- PANDA_PI_V29
|
||||
|
||||
# Extended AVR Environments
|
||||
|
||||
@@ -59,13 +61,13 @@ jobs:
|
||||
#- STM32F103RC_btt_maple
|
||||
- STM32F103RC_btt_USB_maple
|
||||
- STM32F103RC_fysetc_maple
|
||||
- STM32F103RC_meeb
|
||||
- STM32F103RC_meeb_maple
|
||||
- jgaurora_a5s_a1_maple
|
||||
- STM32F103VE_longer_maple
|
||||
#- mks_robin_maple
|
||||
- mks_robin_lite_maple
|
||||
- mks_robin_pro_maple
|
||||
#- mks_robin_nano35_maple
|
||||
#- mks_robin_nano_v1v2_maple
|
||||
#- STM32F103RE_creality_maple
|
||||
- STM32F103VE_ZM3E4V2_USB_maple
|
||||
|
||||
@@ -76,9 +78,9 @@ jobs:
|
||||
- STM32F103RE_btt
|
||||
- STM32F103RE_btt_USB
|
||||
- STM32F103RE_creality
|
||||
- STM32F401RC_creality
|
||||
- STM32F103VE_longer
|
||||
- STM32F407VE_black
|
||||
- STM32F401VE_STEVAL
|
||||
- BIGTREE_BTT002
|
||||
- BIGTREE_SKR_PRO
|
||||
- BIGTREE_GTR_V1_0
|
||||
@@ -92,12 +94,17 @@ jobs:
|
||||
- rumba32
|
||||
- LERDGEX
|
||||
- LERDGEK
|
||||
- mks_robin_nano35
|
||||
- mks_robin_nano_v1v2
|
||||
#- mks_robin_nano_v1v2_usbmod
|
||||
#- mks_robin_nano_v1_3_f4_usbmod
|
||||
- NUCLEO_F767ZI
|
||||
- REMRAM_V1
|
||||
- BTT_SKR_SE_BX
|
||||
- chitu_f103
|
||||
- Index_Mobo_Rev03
|
||||
- Opulo_Lumen_REV3
|
||||
|
||||
# ESP32 environments
|
||||
- mks_tinybee
|
||||
|
||||
# Put lengthy tests last
|
||||
|
||||
@@ -137,8 +144,9 @@ jobs:
|
||||
|
||||
- name: Install PlatformIO
|
||||
run: |
|
||||
pip install -U https://github.com/platformio/platformio-core/archive/v5.2.5.zip
|
||||
platformio update
|
||||
pip install -U platformio
|
||||
pio upgrade --dev
|
||||
pio pkg update --global
|
||||
|
||||
- name: Run ${{ matrix.test-platform }} Tests
|
||||
run: |
|
||||
|
||||
@@ -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 }}"
|
||||
+3
-1
@@ -21,7 +21,8 @@
|
||||
|
||||
# Generated files
|
||||
_Version.h
|
||||
bdf2u8g
|
||||
bdf2u8g.exe
|
||||
genpages.exe
|
||||
marlin_config.json
|
||||
mczip.h
|
||||
*.gen
|
||||
@@ -147,6 +148,7 @@ vc-fileutils.settings
|
||||
imgui.ini
|
||||
eeprom.dat
|
||||
spi_flash.bin
|
||||
fs.img
|
||||
|
||||
#cmake
|
||||
CMakeLists.txt
|
||||
|
||||
@@ -27,7 +27,7 @@ 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 PATH="./buildroot/bin/:./buildroot/tests/:${PATH}" \
|
||||
&& export VERBOSE_PLATFORMIO=$(VERBOSE_PLATFORMIO) \
|
||||
&& run_tests . $(TEST_TARGET) "$(ONLY_TEST)"
|
||||
.PHONY: tests-single-local
|
||||
@@ -38,7 +38,7 @@ tests-single-local-docker:
|
||||
.PHONY: tests-single-local-docker
|
||||
|
||||
tests-all-local:
|
||||
export PATH=./buildroot/bin/:./buildroot/tests/:${PATH} \
|
||||
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
|
||||
|
||||
+596
-238
File diff suppressed because it is too large
Load Diff
+524
-759
File diff suppressed because it is too large
Load Diff
+13
-124
@@ -109,7 +109,7 @@ LIQUID_TWI2 ?= 0
|
||||
# This defines if Wire is needed
|
||||
WIRE ?= 0
|
||||
|
||||
# This defines if Tone is needed (i.e SPEAKER is defined in Configuration.h)
|
||||
# This defines if Tone is needed (i.e., SPEAKER is defined in Configuration.h)
|
||||
# Disabling this (and SPEAKER) saves approximately 350 bytes of memory.
|
||||
TONE ?= 1
|
||||
|
||||
@@ -307,133 +307,22 @@ else ifeq ($(HARDWARE_MOTHERBOARD),1154)
|
||||
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)
|
||||
# Tenlog D3,5,6 Pro IDEX printers
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1157)
|
||||
# Ramps S 1.2 by Sakul.cz (Power outputs: Hotend0, Hotend1, Hotend2, Bed)
|
||||
# Ramps S 1.2 by Sakul.cz (Power outputs: Hotend0, Hotend1, Fan, Bed)
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1158)
|
||||
# Ramps S 1.2 by Sakul.cz (Power outputs: Hotend, Fan0, Fan1, Bed)
|
||||
# Ramps S 1.2 by Sakul.cz (Power outputs: Hotend0, Hotend1, Hotend2, Bed)
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1159)
|
||||
# Longer LK1 PRO / Alfawise U20 Pro (PRO version)
|
||||
# Ramps S 1.2 by Sakul.cz (Power outputs: Hotend, Fan0, Fan1, Bed)
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1160)
|
||||
# Longer LKx PRO / Alfawise Uxx Pro (PRO version)
|
||||
# Longer LK1 PRO / Alfawise U20 Pro (PRO version)
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1161)
|
||||
|
||||
|
||||
# 3Drag Controller
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1100)
|
||||
# Velleman K8200 Controller (derived from 3Drag Controller)
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1101)
|
||||
# Velleman K8400 Controller (derived from 3Drag Controller)
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1102)
|
||||
# Velleman K8600 Controller (Vertex Nano)
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1103)
|
||||
# Velleman K8800 Controller (Vertex Delta)
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1104)
|
||||
# 2PrintBeta BAM&DICE with STK drivers
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1105)
|
||||
# 2PrintBeta BAM&DICE Due with STK drivers
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1106)
|
||||
# MKS BASE v1.0
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1107)
|
||||
# MKS v1.4 with A4982 stepper drivers
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1108)
|
||||
# MKS v1.5 with Allegro A4982 stepper drivers
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1109)
|
||||
# MKS v1.6 with Allegro A4982 stepper drivers
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1110)
|
||||
# MKS BASE 1.0 with Heroic HR4982 stepper drivers
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1111)
|
||||
# MKS GEN v1.3 or 1.4
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1112)
|
||||
# MKS GEN L
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1113)
|
||||
# zrib V2.0 control board (Chinese RAMPS replica)
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1114)
|
||||
# BigTreeTech or BIQU KFB2.0
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1115)
|
||||
# Felix 2.0+ Electronics Board (RAMPS like)
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1116)
|
||||
# Invent-A-Part RigidBoard
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1117)
|
||||
# Invent-A-Part RigidBoard V2
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1118)
|
||||
# Sainsmart 2-in-1 board
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1119)
|
||||
# Ultimaker
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1120)
|
||||
# Ultimaker (Older electronics. Pre 1.5.4. This is rare)
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1121)
|
||||
MCU ?= atmega1280
|
||||
PROG_MCU ?= m1280
|
||||
|
||||
# Azteeg X3
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1122)
|
||||
# Azteeg X3 Pro
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1123)
|
||||
# Ultimainboard 2.x (Uses TEMP_SENSOR 20)
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1124)
|
||||
# Rumba
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1125)
|
||||
# Raise3D Rumba
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1126)
|
||||
# Rapide Lite RL200 Rumba
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1127)
|
||||
# Formbot T-Rex 2 Plus
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1128)
|
||||
# Formbot T-Rex 3
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1129)
|
||||
# Formbot Raptor
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1130)
|
||||
# Formbot Raptor 2
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1131)
|
||||
# bq ZUM Mega 3D
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1132)
|
||||
# MakeBoard Mini v2.1.2 is a control board sold by MicroMake
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1133)
|
||||
# TriGorilla Anycubic version 1.3 based on RAMPS EFB
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1134)
|
||||
# TriGorilla Anycubic version 1.4 based on RAMPS EFB
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1135)
|
||||
# TriGorilla Anycubic version 1.4 Rev 1.1
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1136)
|
||||
# Creality: Ender-4, CR-8
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1137)
|
||||
# Creality: CR10S, CR20, CR-X
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1138)
|
||||
# Dagoma F5
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1139)
|
||||
# FYSETC F6 1.3
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1140)
|
||||
# FYSETC F6 1.5
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1141)
|
||||
# Duplicator i3 Plus
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1142)
|
||||
# VORON
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1143)
|
||||
# TRONXY V3 1.0
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1144)
|
||||
# Z-Bolt X Series
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1145)
|
||||
# TT OSCAR
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1146)
|
||||
# Overlord/Overlord Pro
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1147)
|
||||
# ADIMLab Gantry v1
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1148)
|
||||
# ADIMLab Gantry v2
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1149)
|
||||
# BIQU Tango V1
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1150)
|
||||
# MKS GEN L V2
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1151)
|
||||
# MKS GEN L V2.1
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1152)
|
||||
# Copymaster 3D
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1153)
|
||||
# Ortur 4
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1154)
|
||||
# Tenlog D3 Hero
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1155)
|
||||
# Longer LKx PRO / Alfawise Uxx Pro (PRO version)
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1162)
|
||||
# Zonestar zrib V5.3 (Chinese RAMPS replica)
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1163)
|
||||
# Pxmalion Core I3
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1164)
|
||||
|
||||
#
|
||||
# RAMBo and derivatives
|
||||
@@ -512,7 +401,7 @@ else ifeq ($(HARDWARE_MOTHERBOARD),1324)
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1325)
|
||||
# Intamsys 4.0 (Funmat HT)
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1326)
|
||||
# Malyan M180 Mainboard Version 2 (no display function, direct gcode only)
|
||||
# Malyan M180 Mainboard Version 2 (no display function, direct G-code only)
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1327)
|
||||
# Geeetech GT2560 Rev B for A20(M/T/D)
|
||||
else ifeq ($(HARDWARE_MOTHERBOARD),1328)
|
||||
|
||||
+2
-2
@@ -28,7 +28,7 @@
|
||||
/**
|
||||
* Marlin release version identifier
|
||||
*/
|
||||
#define SHORT_BUILD_VERSION "2.0.9_R01"
|
||||
#define SHORT_BUILD_VERSION "bugfix-2.1.x_R01"
|
||||
|
||||
/**
|
||||
* Verbose version identifier which should contain a reference to the location
|
||||
@@ -41,7 +41,7 @@
|
||||
* here we define this default string as the date where the latest release
|
||||
* version was tagged.
|
||||
*/
|
||||
#define STRING_DISTRIBUTION_DATE "2022-04-10"
|
||||
#define STRING_DISTRIBUTION_DATE "2023-03-10"
|
||||
|
||||
/**
|
||||
* Defines a generic printer name to be output to the LCD after booting Marlin.
|
||||
|
||||
@@ -0,0 +1,211 @@
|
||||
#
|
||||
# Marlin Firmware
|
||||
# config.ini - Options to apply before the build
|
||||
#
|
||||
[config:base]
|
||||
ini_use_config = none
|
||||
|
||||
# Load all config: sections in this file
|
||||
;ini_use_config = all
|
||||
# Load config file relative to Marlin/
|
||||
;ini_use_config = another.ini
|
||||
# Download configurations from GitHub
|
||||
;ini_use_config = example/Creality/Ender-5 Plus @ bugfix-2.1.x
|
||||
# Download configurations from your server
|
||||
;ini_use_config = https://me.myserver.com/path/to/configs
|
||||
# Evaluate config:base and do a config dump
|
||||
;ini_use_config = base
|
||||
;config_export = 2
|
||||
|
||||
[config:minimal]
|
||||
motherboard = BOARD_RAMPS_14_EFB
|
||||
serial_port = 0
|
||||
baudrate = 250000
|
||||
|
||||
use_watchdog = on
|
||||
thermal_protection_hotends = on
|
||||
thermal_protection_hysteresis = 4
|
||||
thermal_protection_period = 40
|
||||
|
||||
bufsize = 4
|
||||
block_buffer_size = 16
|
||||
max_cmd_size = 96
|
||||
|
||||
extruders = 1
|
||||
temp_sensor_0 = 1
|
||||
|
||||
temp_hysteresis = 3
|
||||
heater_0_mintemp = 5
|
||||
heater_0_maxtemp = 275
|
||||
preheat_1_temp_hotend = 180
|
||||
|
||||
bang_max = 255
|
||||
pidtemp = on
|
||||
pid_k1 = 0.95
|
||||
pid_max = BANG_MAX
|
||||
pid_functional_range = 10
|
||||
|
||||
default_kp = 22.20
|
||||
default_ki = 1.08
|
||||
default_kd = 114.00
|
||||
|
||||
x_driver_type = A4988
|
||||
y_driver_type = A4988
|
||||
z_driver_type = A4988
|
||||
e0_driver_type = A4988
|
||||
|
||||
x_bed_size = 200
|
||||
x_min_pos = 0
|
||||
x_max_pos = X_BED_SIZE
|
||||
|
||||
y_bed_size = 200
|
||||
y_min_pos = 0
|
||||
y_max_pos = Y_BED_SIZE
|
||||
|
||||
z_min_pos = 0
|
||||
z_max_pos = 200
|
||||
|
||||
x_home_dir = -1
|
||||
y_home_dir = -1
|
||||
z_home_dir = -1
|
||||
|
||||
use_xmin_plug = on
|
||||
use_ymin_plug = on
|
||||
use_zmin_plug = on
|
||||
|
||||
x_min_endstop_inverting = false
|
||||
y_min_endstop_inverting = false
|
||||
z_min_endstop_inverting = false
|
||||
|
||||
default_axis_steps_per_unit = { 80, 80, 400, 500 }
|
||||
axis_relative_modes = { false, false, false, false }
|
||||
default_max_feedrate = { 300, 300, 5, 25 }
|
||||
default_max_acceleration = { 3000, 3000, 100, 10000 }
|
||||
|
||||
homing_feedrate_mm_m = { (50*60), (50*60), (4*60) }
|
||||
homing_bump_divisor = { 2, 2, 4 }
|
||||
|
||||
x_enable_on = 0
|
||||
y_enable_on = 0
|
||||
z_enable_on = 0
|
||||
e_enable_on = 0
|
||||
|
||||
invert_x_dir = false
|
||||
invert_y_dir = true
|
||||
invert_z_dir = false
|
||||
invert_e0_dir = false
|
||||
|
||||
step_state_e = HIGH
|
||||
step_state_x = HIGH
|
||||
step_state_y = HIGH
|
||||
step_state_z = HIGH
|
||||
|
||||
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_extruder = 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
|
||||
@@ -23,6 +23,7 @@
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
#include "HAL.h"
|
||||
#include <avr/wdt.h>
|
||||
|
||||
#ifdef USBCON
|
||||
DefaultSerial1 MSerial0(false, Serial);
|
||||
@@ -88,6 +89,62 @@ void MarlinHAL::reboot() {
|
||||
#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)
|
||||
|
||||
#include "../../sd/SdFatUtil.h"
|
||||
|
||||
+20
-13
@@ -19,17 +19,20 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* HAL for Arduino AVR
|
||||
*/
|
||||
|
||||
#include "../shared/Marduino.h"
|
||||
#include "../shared/HAL_SPI.h"
|
||||
#include "fastio.h"
|
||||
#include "watchdog.h"
|
||||
#include "math.h"
|
||||
|
||||
#ifdef USBCON
|
||||
#include <HardwareSerial.h>
|
||||
#else
|
||||
#define HardwareSerial_h // Hack to prevent HardwareSerial.h header inclusion
|
||||
#include "MarlinSerial.h"
|
||||
#define BOARD_NO_NATIVE_USB
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
@@ -104,36 +107,36 @@ typedef Servo hal_servo_t;
|
||||
|
||||
#define MYSERIAL1 TERN(BLUETOOTH, btSerial, MSerial0)
|
||||
#else
|
||||
#if !WITHIN(SERIAL_PORT, -1, 3)
|
||||
#error "SERIAL_PORT must be from 0 to 3, or -1 for USB Serial."
|
||||
#if !WITHIN(SERIAL_PORT, 0, 3)
|
||||
#error "SERIAL_PORT must be from 0 to 3."
|
||||
#endif
|
||||
#define MYSERIAL1 customizedSerial1
|
||||
|
||||
#ifdef SERIAL_PORT_2
|
||||
#if !WITHIN(SERIAL_PORT_2, -1, 3)
|
||||
#error "SERIAL_PORT_2 must be from 0 to 3, or -1 for USB Serial."
|
||||
#if !WITHIN(SERIAL_PORT_2, 0, 3)
|
||||
#error "SERIAL_PORT_2 must be from 0 to 3."
|
||||
#endif
|
||||
#define MYSERIAL2 customizedSerial2
|
||||
#endif
|
||||
|
||||
#ifdef SERIAL_PORT_3
|
||||
#if !WITHIN(SERIAL_PORT_3, -1, 3)
|
||||
#error "SERIAL_PORT_3 must be from 0 to 3, or -1 for USB Serial."
|
||||
#if !WITHIN(SERIAL_PORT_3, 0, 3)
|
||||
#error "SERIAL_PORT_3 must be from 0 to 3."
|
||||
#endif
|
||||
#define MYSERIAL3 customizedSerial3
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef MMU2_SERIAL_PORT
|
||||
#if !WITHIN(MMU2_SERIAL_PORT, -1, 3)
|
||||
#error "MMU2_SERIAL_PORT must be from 0 to 3, or -1 for USB Serial."
|
||||
#if !WITHIN(MMU2_SERIAL_PORT, 0, 3)
|
||||
#error "MMU2_SERIAL_PORT must be from 0 to 3"
|
||||
#endif
|
||||
#define MMU2_SERIAL mmuSerial
|
||||
#endif
|
||||
|
||||
#ifdef LCD_SERIAL_PORT
|
||||
#if !WITHIN(LCD_SERIAL_PORT, -1, 3)
|
||||
#error "LCD_SERIAL_PORT must be from 0 to 3, or -1 for USB Serial."
|
||||
#if !WITHIN(LCD_SERIAL_PORT, 0, 3)
|
||||
#error "LCD_SERIAL_PORT must be from 0 to 3."
|
||||
#endif
|
||||
#define LCD_SERIAL lcdSerial
|
||||
#if HAS_DGUS_LCD
|
||||
@@ -164,7 +167,7 @@ typedef Servo hal_servo_t;
|
||||
#define strtof strtod
|
||||
|
||||
// ------------------------
|
||||
// Class Utilities
|
||||
// Free Memory Accessor
|
||||
// ------------------------
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
@@ -186,6 +189,10 @@ public:
|
||||
// Earliest possible init, before setup()
|
||||
MarlinHAL() {}
|
||||
|
||||
// Watchdog
|
||||
static void watchdog_init() IF_DISABLED(USE_WATCHDOG, {});
|
||||
static void watchdog_refresh() IF_DISABLED(USE_WATCHDOG, {});
|
||||
|
||||
static void init(); // Called early in setup()
|
||||
static void init_board() {} // Called less early in setup()
|
||||
static void reboot(); // Restart the firmware from 0x0
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
#include <WString.h>
|
||||
|
||||
#include "../../inc/MarlinConfigPre.h"
|
||||
#include "../../core/types.h"
|
||||
#include "../../core/serial_hook.h"
|
||||
|
||||
#ifndef SERIAL_PORT
|
||||
@@ -138,10 +139,6 @@
|
||||
|
||||
#define BYTE 0
|
||||
|
||||
// Templated type selector
|
||||
template<bool b, typename T, typename F> struct TypeSelector { typedef T type;} ;
|
||||
template<typename T, typename F> struct TypeSelector<false, T, F> { typedef F type; };
|
||||
|
||||
template<typename Cfg>
|
||||
class MarlinSerial {
|
||||
protected:
|
||||
@@ -164,7 +161,7 @@
|
||||
static constexpr B_U2Xx<Cfg::PORT> B_U2X = 0;
|
||||
|
||||
// Base size of type on buffer size
|
||||
typedef typename TypeSelector<(Cfg::RX_SIZE>256), uint16_t, uint8_t>::type ring_buffer_pos_t;
|
||||
typedef uvalue_t(Cfg::RX_SIZE - 1) ring_buffer_pos_t;
|
||||
|
||||
struct ring_buffer_r {
|
||||
volatile ring_buffer_pos_t head, tail;
|
||||
|
||||
+102
-92
@@ -66,27 +66,26 @@ static volatile int8_t Channel[_Nbr_16timers]; // counter for the s
|
||||
|
||||
/************ static functions common to all instances ***********************/
|
||||
|
||||
static inline void handle_interrupts(timer16_Sequence_t timer, volatile uint16_t* TCNTn, volatile uint16_t* OCRnA) {
|
||||
if (Channel[timer] < 0)
|
||||
*TCNTn = 0; // channel set to -1 indicated that refresh interval completed so reset the timer
|
||||
else {
|
||||
if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && SERVO(timer, Channel[timer]).Pin.isActive)
|
||||
extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, LOW); // pulse this channel low if activated
|
||||
}
|
||||
static inline void handle_interrupts(const timer16_Sequence_t timer, volatile uint16_t* TCNTn, volatile uint16_t* OCRnA) {
|
||||
int8_t cho = Channel[timer]; // Handle the prior Channel[timer] first
|
||||
if (cho < 0) // Channel -1 indicates the refresh interval completed...
|
||||
*TCNTn = 0; // ...so reset the timer
|
||||
else if (SERVO_INDEX(timer, cho) < ServoCount) // prior channel handled?
|
||||
extDigitalWrite(SERVO(timer, cho).Pin.nbr, LOW); // pulse the prior channel LOW
|
||||
|
||||
Channel[timer]++; // increment to the next channel
|
||||
if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) {
|
||||
*OCRnA = *TCNTn + SERVO(timer, Channel[timer]).ticks;
|
||||
if (SERVO(timer, Channel[timer]).Pin.isActive) // check if activated
|
||||
extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, HIGH); // it's an active channel so pulse it high
|
||||
Channel[timer] = ++cho; // Handle the next channel (or 0)
|
||||
if (cho < SERVOS_PER_TIMER && SERVO_INDEX(timer, cho) < ServoCount) {
|
||||
*OCRnA = *TCNTn + SERVO(timer, cho).ticks; // set compare to current ticks plus duration
|
||||
if (SERVO(timer, cho).Pin.isActive) // activated?
|
||||
extDigitalWrite(SERVO(timer, cho).Pin.nbr, HIGH); // yes: pulse HIGH
|
||||
}
|
||||
else {
|
||||
// finished all channels so wait for the refresh period to expire before starting over
|
||||
if (((unsigned)*TCNTn) + 4 < usToTicks(REFRESH_INTERVAL)) // allow a few ticks to ensure the next OCR1A not missed
|
||||
*OCRnA = (unsigned int)usToTicks(REFRESH_INTERVAL);
|
||||
else
|
||||
*OCRnA = *TCNTn + 4; // at least REFRESH_INTERVAL has elapsed
|
||||
Channel[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel
|
||||
const unsigned int cval = ((unsigned)*TCNTn) + 32 / (SERVO_TIMER_PRESCALER), // allow 32 cycles to ensure the next OCR1A not missed
|
||||
ival = (unsigned int)usToTicks(REFRESH_INTERVAL); // at least REFRESH_INTERVAL has elapsed
|
||||
*OCRnA = max(cval, ival);
|
||||
|
||||
Channel[timer] = -1; // reset the timer counter to 0 on the next call
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,91 +122,102 @@ static inline void handle_interrupts(timer16_Sequence_t timer, volatile uint16_t
|
||||
|
||||
/****************** end of static functions ******************************/
|
||||
|
||||
void initISR(timer16_Sequence_t timer) {
|
||||
#ifdef _useTimer1
|
||||
if (timer == _timer1) {
|
||||
TCCR1A = 0; // normal counting mode
|
||||
TCCR1B = _BV(CS11); // set prescaler of 8
|
||||
TCNT1 = 0; // clear the timer count
|
||||
#if defined(__AVR_ATmega8__) || defined(__AVR_ATmega128__)
|
||||
SBI(TIFR, OCF1A); // clear any pending interrupts;
|
||||
SBI(TIMSK, OCIE1A); // enable the output compare interrupt
|
||||
#else
|
||||
// here if not ATmega8 or ATmega128
|
||||
SBI(TIFR1, OCF1A); // clear any pending interrupts;
|
||||
SBI(TIMSK1, OCIE1A); // enable the output compare interrupt
|
||||
#endif
|
||||
#ifdef WIRING
|
||||
timerAttach(TIMER1OUTCOMPAREA_INT, Timer1Service);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
void initISR(const timer16_Sequence_t timer_index) {
|
||||
switch (timer_index) {
|
||||
default: break;
|
||||
|
||||
#ifdef _useTimer3
|
||||
if (timer == _timer3) {
|
||||
TCCR3A = 0; // normal counting mode
|
||||
TCCR3B = _BV(CS31); // set prescaler of 8
|
||||
TCNT3 = 0; // clear the timer count
|
||||
#ifdef __AVR_ATmega128__
|
||||
SBI(TIFR, OCF3A); // clear any pending interrupts;
|
||||
SBI(ETIMSK, OCIE3A); // enable the output compare interrupt
|
||||
#else
|
||||
SBI(TIFR3, OCF3A); // clear any pending interrupts;
|
||||
SBI(TIMSK3, OCIE3A); // enable the output compare interrupt
|
||||
#endif
|
||||
#ifdef WIRING
|
||||
timerAttach(TIMER3OUTCOMPAREA_INT, Timer3Service); // for Wiring platform only
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#ifdef _useTimer1
|
||||
case _timer1:
|
||||
TCCR1A = 0; // normal counting mode
|
||||
TCCR1B = _BV(CS11); // set prescaler of 8
|
||||
TCNT1 = 0; // clear the timer count
|
||||
#if defined(__AVR_ATmega8__) || defined(__AVR_ATmega128__)
|
||||
SBI(TIFR, OCF1A); // clear any pending interrupts;
|
||||
SBI(TIMSK, OCIE1A); // enable the output compare interrupt
|
||||
#else
|
||||
// here if not ATmega8 or ATmega128
|
||||
SBI(TIFR1, OCF1A); // clear any pending interrupts;
|
||||
SBI(TIMSK1, OCIE1A); // enable the output compare interrupt
|
||||
#endif
|
||||
#ifdef WIRING
|
||||
timerAttach(TIMER1OUTCOMPAREA_INT, Timer1Service);
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef _useTimer4
|
||||
if (timer == _timer4) {
|
||||
TCCR4A = 0; // normal counting mode
|
||||
TCCR4B = _BV(CS41); // set prescaler of 8
|
||||
TCNT4 = 0; // clear the timer count
|
||||
TIFR4 = _BV(OCF4A); // clear any pending interrupts;
|
||||
TIMSK4 = _BV(OCIE4A); // enable the output compare interrupt
|
||||
}
|
||||
#endif
|
||||
#ifdef _useTimer3
|
||||
case _timer3:
|
||||
TCCR3A = 0; // normal counting mode
|
||||
TCCR3B = _BV(CS31); // set prescaler of 8
|
||||
TCNT3 = 0; // clear the timer count
|
||||
#ifdef __AVR_ATmega128__
|
||||
SBI(TIFR, OCF3A); // clear any pending interrupts;
|
||||
SBI(ETIMSK, OCIE3A); // enable the output compare interrupt
|
||||
#else
|
||||
SBI(TIFR3, OCF3A); // clear any pending interrupts;
|
||||
SBI(TIMSK3, OCIE3A); // enable the output compare interrupt
|
||||
#endif
|
||||
#ifdef WIRING
|
||||
timerAttach(TIMER3OUTCOMPAREA_INT, Timer3Service); // for Wiring platform only
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef _useTimer5
|
||||
if (timer == _timer5) {
|
||||
TCCR5A = 0; // normal counting mode
|
||||
TCCR5B = _BV(CS51); // set prescaler of 8
|
||||
TCNT5 = 0; // clear the timer count
|
||||
TIFR5 = _BV(OCF5A); // clear any pending interrupts;
|
||||
TIMSK5 = _BV(OCIE5A); // enable the output compare interrupt
|
||||
}
|
||||
#endif
|
||||
#ifdef _useTimer4
|
||||
case _timer4:
|
||||
TCCR4A = 0; // normal counting mode
|
||||
TCCR4B = _BV(CS41); // set prescaler of 8
|
||||
TCNT4 = 0; // clear the timer count
|
||||
TIFR4 = _BV(OCF4A); // clear any pending interrupts;
|
||||
TIMSK4 = _BV(OCIE4A); // enable the output compare interrupt
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef _useTimer5
|
||||
case _timer5:
|
||||
TCCR5A = 0; // normal counting mode
|
||||
TCCR5B = _BV(CS51); // set prescaler of 8
|
||||
TCNT5 = 0; // clear the timer count
|
||||
TIFR5 = _BV(OCF5A); // clear any pending interrupts;
|
||||
TIMSK5 = _BV(OCIE5A); // enable the output compare interrupt
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void finISR(timer16_Sequence_t timer) {
|
||||
void finISR(const timer16_Sequence_t timer_index) {
|
||||
// Disable use of the given timer
|
||||
#ifdef WIRING
|
||||
if (timer == _timer1) {
|
||||
CBI(
|
||||
#if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
|
||||
TIMSK1
|
||||
#else
|
||||
TIMSK
|
||||
#endif
|
||||
, OCIE1A); // disable timer 1 output compare interrupt
|
||||
timerDetach(TIMER1OUTCOMPAREA_INT);
|
||||
}
|
||||
else if (timer == _timer3) {
|
||||
CBI(
|
||||
#if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
|
||||
TIMSK3
|
||||
#else
|
||||
ETIMSK
|
||||
#endif
|
||||
, OCIE3A); // disable the timer3 output compare A interrupt
|
||||
timerDetach(TIMER3OUTCOMPAREA_INT);
|
||||
switch (timer_index) {
|
||||
default: break;
|
||||
|
||||
case _timer1:
|
||||
CBI(
|
||||
#if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
|
||||
TIMSK1
|
||||
#else
|
||||
TIMSK
|
||||
#endif
|
||||
, OCIE1A // disable timer 1 output compare interrupt
|
||||
);
|
||||
timerDetach(TIMER1OUTCOMPAREA_INT);
|
||||
break;
|
||||
|
||||
case _timer3:
|
||||
CBI(
|
||||
#if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
|
||||
TIMSK3
|
||||
#else
|
||||
ETIMSK
|
||||
#endif
|
||||
, OCIE3A // disable the timer3 output compare A interrupt
|
||||
);
|
||||
timerDetach(TIMER3OUTCOMPAREA_INT);
|
||||
break;
|
||||
}
|
||||
#else // !WIRING
|
||||
// For arduino - in future: call here to a currently undefined function to reset the timer
|
||||
UNUSED(timer);
|
||||
UNUSED(timer_index);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,10 @@
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
//#define DEBUG_AVR_FAST_PWM
|
||||
#define DEBUG_OUT ENABLED(DEBUG_AVR_FAST_PWM)
|
||||
#include "../../core/debug_out.h"
|
||||
|
||||
struct Timer {
|
||||
volatile uint8_t* TCCRnQ[3]; // max 3 TCCR registers per timer
|
||||
volatile uint16_t* OCRnQ[3]; // max 3 OCR registers per timer
|
||||
@@ -108,12 +112,15 @@ const Timer get_pwm_timer(const pin_t pin) {
|
||||
}
|
||||
|
||||
void MarlinHAL::set_pwm_frequency(const pin_t pin, const uint16_t f_desired) {
|
||||
DEBUG_ECHOLNPGM("set_pwm_frequency(pin=", pin, ", freq=", f_desired, ")");
|
||||
const Timer timer = get_pwm_timer(pin);
|
||||
if (timer.isProtected || !timer.isPWM) return; // Don't proceed if protected timer or not recognized
|
||||
|
||||
const bool is_timer2 = timer.n == 2;
|
||||
const uint16_t maxtop = is_timer2 ? 0xFF : 0xFFFF;
|
||||
|
||||
DEBUG_ECHOLNPGM("maxtop=", maxtop);
|
||||
|
||||
uint16_t res = 0xFF; // resolution (TOP value)
|
||||
uint8_t j = CS_NONE; // prescaler index
|
||||
uint8_t wgm = WGM_PWM_PC_8; // waveform generation mode
|
||||
@@ -121,23 +128,29 @@ void MarlinHAL::set_pwm_frequency(const pin_t pin, const uint16_t f_desired) {
|
||||
// Calculating the prescaler and resolution to use to achieve closest frequency
|
||||
if (f_desired != 0) {
|
||||
constexpr uint16_t prescaler[] = { 1, 8, (32), 64, (128), 256, 1024 }; // (*) are Timer 2 only
|
||||
uint16_t f = (F_CPU) / (2 * 1024 * maxtop) + 1; // Start with the lowest non-zero frequency achievable (1 or 31)
|
||||
uint16_t f = (F_CPU) / (uint32_t(maxtop) << 11) + 1; // Start with the lowest non-zero frequency achievable (for 16MHz, 1 or 31)
|
||||
|
||||
DEBUG_ECHOLNPGM("f=", f);
|
||||
DEBUG_ECHOLNPGM("(prescaler loop)");
|
||||
LOOP_L_N(i, COUNT(prescaler)) { // Loop through all prescaler values
|
||||
const uint16_t p = prescaler[i];
|
||||
const uint32_t p = prescaler[i]; // Extend to 32 bits for calculations
|
||||
DEBUG_ECHOLNPGM("prescaler[", i, "]=", p);
|
||||
uint16_t res_fast_temp, res_pc_temp;
|
||||
if (is_timer2) {
|
||||
#if ENABLED(USE_OCR2A_AS_TOP) // No resolution calculation for TIMER2 unless enabled USE_OCR2A_AS_TOP
|
||||
const uint16_t rft = (F_CPU) / (p * f_desired);
|
||||
res_fast_temp = rft - 1;
|
||||
res_pc_temp = rft / 2;
|
||||
DEBUG_ECHOLNPGM("(Timer2) res_fast_temp=", res_fast_temp, " res_pc_temp=", res_pc_temp);
|
||||
#else
|
||||
res_fast_temp = res_pc_temp = maxtop;
|
||||
DEBUG_ECHOLNPGM("(Timer2) res_fast_temp=", maxtop, " res_pc_temp=", maxtop);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
if (p == 32 || p == 128) continue; // Skip TIMER2 specific prescalers when not TIMER2
|
||||
const uint16_t rft = (F_CPU) / (p * f_desired);
|
||||
DEBUG_ECHOLNPGM("(Not Timer 2) F_CPU=" STRINGIFY(F_CPU), " prescaler=", p, " f_desired=", f_desired);
|
||||
res_fast_temp = rft - 1;
|
||||
res_pc_temp = rft / 2;
|
||||
}
|
||||
@@ -146,24 +159,28 @@ void MarlinHAL::set_pwm_frequency(const pin_t pin, const uint16_t f_desired) {
|
||||
LIMIT(res_pc_temp, 1U, maxtop);
|
||||
|
||||
// Calculate frequencies of test prescaler and resolution values
|
||||
const uint32_t f_diff = _MAX(f, f_desired) - _MIN(f, f_desired),
|
||||
f_fast_temp = (F_CPU) / (p * (1 + res_fast_temp)),
|
||||
const uint16_t f_fast_temp = (F_CPU) / (p * (1 + res_fast_temp)),
|
||||
f_pc_temp = (F_CPU) / ((p * res_pc_temp) << 1),
|
||||
f_diff = _MAX(f, f_desired) - _MIN(f, f_desired),
|
||||
f_fast_diff = _MAX(f_fast_temp, f_desired) - _MIN(f_fast_temp, f_desired),
|
||||
f_pc_temp = (F_CPU) / (2 * p * res_pc_temp),
|
||||
f_pc_diff = _MAX(f_pc_temp, f_desired) - _MIN(f_pc_temp, f_desired);
|
||||
|
||||
DEBUG_ECHOLNPGM("f_fast_temp=", f_fast_temp, " f_pc_temp=", f_pc_temp, " f_diff=", f_diff, " f_fast_diff=", f_fast_diff, " f_pc_diff=", f_pc_diff);
|
||||
|
||||
if (f_fast_diff < f_diff && f_fast_diff <= f_pc_diff) { // FAST values are closest to desired f
|
||||
// Set the Wave Generation Mode to FAST PWM
|
||||
wgm = is_timer2 ? uint8_t(TERN(USE_OCR2A_AS_TOP, WGM2_FAST_PWM_OCR2A, WGM2_FAST_PWM)) : uint8_t(WGM_FAST_PWM_ICRn);
|
||||
// Remember this combination
|
||||
f = f_fast_temp; res = res_fast_temp; j = i + 1;
|
||||
DEBUG_ECHOLNPGM("(FAST) updated f=", f);
|
||||
}
|
||||
else if (f_pc_diff < f_diff) { // PHASE CORRECT values are closes to desired f
|
||||
// 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);
|
||||
f = f_pc_temp; res = res_pc_temp; j = i + 1;
|
||||
DEBUG_ECHOLNPGM("(PHASE) updated f=", f);
|
||||
}
|
||||
}
|
||||
} // prescaler loop
|
||||
}
|
||||
|
||||
_SET_WGMnQ(timer, wgm);
|
||||
|
||||
@@ -293,11 +293,11 @@ enum ClockSource2 : uint8_t {
|
||||
|
||||
#if HAS_MOTOR_CURRENT_PWM
|
||||
#if PIN_EXISTS(MOTOR_CURRENT_PWM_XY)
|
||||
#define PWM_CHK_MOTOR_CURRENT(P) (P == MOTOR_CURRENT_PWM_E || P == MOTOR_CURRENT_PWM_Z || P == MOTOR_CURRENT_PWM_XY)
|
||||
#define PWM_CHK_MOTOR_CURRENT(P) (P == MOTOR_CURRENT_PWM_E_PIN || P == MOTOR_CURRENT_PWM_E0_PIN || P == MOTOR_CURRENT_PWM_E1_PIN || P == MOTOR_CURRENT_PWM_Z_PIN || P == MOTOR_CURRENT_PWM_XY_PIN)
|
||||
#elif PIN_EXISTS(MOTOR_CURRENT_PWM_Z)
|
||||
#define PWM_CHK_MOTOR_CURRENT(P) (P == MOTOR_CURRENT_PWM_E || P == MOTOR_CURRENT_PWM_Z)
|
||||
#define PWM_CHK_MOTOR_CURRENT(P) (P == MOTOR_CURRENT_PWM_E_PIN || P == MOTOR_CURRENT_PWM_E0_PIN || P == MOTOR_CURRENT_PWM_E1_PIN || P == MOTOR_CURRENT_PWM_Z_PIN)
|
||||
#else
|
||||
#define PWM_CHK_MOTOR_CURRENT(P) (P == MOTOR_CURRENT_PWM_E)
|
||||
#define PWM_CHK_MOTOR_CURRENT(P) (P == MOTOR_CURRENT_PWM_E_PIN || P == MOTOR_CURRENT_PWM_E0_PIN || P == MOTOR_CURRENT_PWM_E1_PIN)
|
||||
#endif
|
||||
#else
|
||||
#define PWM_CHK_MOTOR_CURRENT(P) false
|
||||
|
||||
@@ -25,6 +25,40 @@
|
||||
* Test AVR-specific configuration values for errors at compile-time.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Check for common serial pin conflicts
|
||||
*/
|
||||
#define CHECK_SERIAL_PIN(N) ( \
|
||||
X_STOP_PIN == N || Y_STOP_PIN == N || Z_STOP_PIN == N \
|
||||
|| X_MIN_PIN == N || Y_MIN_PIN == N || Z_MIN_PIN == N \
|
||||
|| X_MAX_PIN == N || Y_MAX_PIN == N || Z_MAX_PIN == N \
|
||||
|| X_STEP_PIN == N || Y_STEP_PIN == N || Z_STEP_PIN == N \
|
||||
|| X_DIR_PIN == N || Y_DIR_PIN == N || Z_DIR_PIN == N \
|
||||
|| X_ENA_PIN == N || Y_ENA_PIN == N || Z_ENA_PIN == N \
|
||||
|| BTN_EN1 == N || BTN_EN2 == N \
|
||||
)
|
||||
#if SERIAL_IN_USE(0)
|
||||
// D0-D1. No known conflicts.
|
||||
#endif
|
||||
#if SERIAL_IN_USE(1)
|
||||
#if NOT_TARGET(__AVR_ATmega644P__, __AVR_ATmega1284P__)
|
||||
#if CHECK_SERIAL_PIN(18) || CHECK_SERIAL_PIN(19)
|
||||
#error "Serial Port 1 pin D18 and/or D19 conflicts with another pin on the board."
|
||||
#endif
|
||||
#else
|
||||
#if CHECK_SERIAL_PIN(10) || CHECK_SERIAL_PIN(11)
|
||||
#error "Serial Port 1 pin D10 and/or D11 conflicts with another pin on the board."
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#if SERIAL_IN_USE(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 SERIAL_IN_USE(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
|
||||
*/
|
||||
|
||||
+21
-19
@@ -27,13 +27,14 @@
|
||||
|
||||
// intRes = longIn1 * longIn2 >> 24
|
||||
// uses:
|
||||
// A[tmp] to store 0
|
||||
// B[tmp] to store bits 16-23 of the 48bit result. The top bit is used to round the two byte result.
|
||||
// note that the lower two bytes and the upper byte of the 48bit result are not calculated.
|
||||
// this can cause the result to be out by one as the lower bytes may cause carries into the upper ones.
|
||||
// B A are bits 24-39 and are the returned value
|
||||
// C B A is longIn1
|
||||
// D C B A is longIn2
|
||||
// r1, r0 for the result of mul.
|
||||
// [tmp1] to store 0.
|
||||
// [tmp2] to store bits 16-23 of the 56 bit result. The top bit of [tmp2] is used for rounding.
|
||||
// Note that the lower two bytes and the upper two bytes of the 56 bit result are not calculated.
|
||||
// This can cause the result to be out by one as the lower bytes may cause carries into the upper ones.
|
||||
// [intRes] (A B) is bits 24-39 and is the returned value.
|
||||
// [longIn1] (C B A) is a 24 bit parameter.
|
||||
// [longIn2] (D C B A) is a 32 bit parameter.
|
||||
//
|
||||
FORCE_INLINE static uint16_t MultiU24X32toH16(uint32_t longIn1, uint32_t longIn2) {
|
||||
uint8_t tmp1;
|
||||
@@ -66,11 +67,9 @@ FORCE_INLINE static uint16_t MultiU24X32toH16(uint32_t longIn1, uint32_t longIn2
|
||||
A("add %[tmp2], r1")
|
||||
A("adc %A[intRes], %[tmp1]")
|
||||
A("adc %B[intRes], %[tmp1]")
|
||||
A("lsr %[tmp2]")
|
||||
A("adc %A[intRes], %[tmp1]")
|
||||
A("adc %B[intRes], %[tmp1]")
|
||||
A("mul %D[longIn2], %A[longIn1]")
|
||||
A("add %A[intRes], r0")
|
||||
A("lsl %[tmp2]")
|
||||
A("adc %A[intRes], r0")
|
||||
A("adc %B[intRes], r1")
|
||||
A("mul %D[longIn2], %B[longIn1]")
|
||||
A("add %B[intRes], r0")
|
||||
@@ -85,11 +84,16 @@ FORCE_INLINE static uint16_t MultiU24X32toH16(uint32_t longIn1, uint32_t longIn2
|
||||
return intRes;
|
||||
}
|
||||
|
||||
// intRes = intIn1 * intIn2 >> 16
|
||||
// intRes = intIn1 * intIn2 >> 8
|
||||
// uses:
|
||||
// r26 to store 0
|
||||
// r27 to store the byte 1 of the 24 bit result
|
||||
FORCE_INLINE static uint16_t MultiU16X8toH16(uint8_t charIn1, uint16_t intIn2) {
|
||||
// r1, r0 for the result of mul. After the second mul, r0 holds bits 0-7 of the 24 bit result and
|
||||
// the top bit of r0 is used for rounding.
|
||||
// [tmp] to store 0.
|
||||
// [intRes] (A B) is bits 8-15 and is the returned value.
|
||||
// [charIn1] is an 8 bit parameter.
|
||||
// [intIn2] (B A) is a 16 bit parameter.
|
||||
//
|
||||
FORCE_INLINE static uint16_t MultiU8X16toH16(uint8_t charIn1, uint16_t intIn2) {
|
||||
uint8_t tmp;
|
||||
uint16_t intRes;
|
||||
__asm__ __volatile__ (
|
||||
@@ -97,10 +101,8 @@ FORCE_INLINE static uint16_t MultiU16X8toH16(uint8_t charIn1, uint16_t intIn2) {
|
||||
A("mul %[charIn1], %B[intIn2]")
|
||||
A("movw %A[intRes], r0")
|
||||
A("mul %[charIn1], %A[intIn2]")
|
||||
A("add %A[intRes], r1")
|
||||
A("adc %B[intRes], %[tmp]")
|
||||
A("lsr r0")
|
||||
A("adc %A[intRes], %[tmp]")
|
||||
A("lsl r0")
|
||||
A("adc %A[intRes], r1")
|
||||
A("adc %B[intRes], %[tmp]")
|
||||
A("clr r1")
|
||||
: [intRes] "=&r" (intRes),
|
||||
|
||||
@@ -74,7 +74,7 @@
|
||||
#define MULTI_NAME_PAD 26 // space needed to be pretty if not first name assigned to a pin
|
||||
|
||||
void PRINT_ARRAY_NAME(uint8_t x) {
|
||||
char *name_mem_pointer = (PGM_P)pgm_read_ptr(&pin_array[x].name);
|
||||
PGM_P const name_mem_pointer = (PGM_P)pgm_read_ptr(&pin_array[x].name);
|
||||
LOOP_L_N(y, MAX_NAME_LENGTH) {
|
||||
char temp_char = pgm_read_byte(name_mem_pointer + y);
|
||||
if (temp_char != 0)
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://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__
|
||||
+106
-4
@@ -25,7 +25,7 @@
|
||||
#ifdef ARDUINO_ARCH_SAM
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
#include "HAL.h"
|
||||
#include "../../MarlinCore.h"
|
||||
|
||||
#include <Wire.h>
|
||||
#include "usb/usb_task.h"
|
||||
@@ -40,14 +40,15 @@ uint16_t MarlinHAL::adc_result;
|
||||
// Public functions
|
||||
// ------------------------
|
||||
|
||||
TERN_(POSTMORTEM_DEBUGGING, extern void install_min_serial());
|
||||
#if ENABLED(POSTMORTEM_DEBUGGING)
|
||||
extern void install_min_serial();
|
||||
#endif
|
||||
|
||||
void MarlinHAL::init() {
|
||||
// Initialize the USB stack
|
||||
#if ENABLED(SDSUPPORT)
|
||||
OUT_WRITE(SDSS, HIGH); // Try to set SDSS inactive before any other SPI users start up
|
||||
#endif
|
||||
usb_task_init();
|
||||
usb_task_init(); // Initialize the USB stack
|
||||
TERN_(POSTMORTEM_DEBUGGING, install_min_serial()); // Install the min serial handler
|
||||
}
|
||||
|
||||
@@ -72,6 +73,103 @@ uint8_t MarlinHAL::get_reset_source() {
|
||||
|
||||
void MarlinHAL::reboot() { rstc_start_software_reset(RSTC); }
|
||||
|
||||
// ------------------------
|
||||
// Watchdog Timer
|
||||
// ------------------------
|
||||
|
||||
#if ENABLED(USE_WATCHDOG)
|
||||
|
||||
// Initialize watchdog - On SAM3X, Watchdog was already configured
|
||||
// and enabled or disabled at startup, so no need to reconfigure it
|
||||
// here.
|
||||
void MarlinHAL::watchdog_init() { WDT_Restart(WDT); } // Reset watchdog to start clean
|
||||
|
||||
// Reset watchdog. MUST be called at least every 4 seconds after the
|
||||
// first watchdog_init or AVR will go into emergency procedures.
|
||||
void MarlinHAL::watchdog_refresh() { watchdogReset(); }
|
||||
|
||||
#endif
|
||||
|
||||
// Override Arduino runtime to either config or disable the watchdog
|
||||
//
|
||||
// We need to configure the watchdog as soon as possible in the boot
|
||||
// process, because watchdog initialization at hardware reset on SAM3X8E
|
||||
// is unreliable, and there is risk of unintended resets if we delay
|
||||
// that initialization to a later time.
|
||||
void watchdogSetup() {
|
||||
|
||||
#if ENABLED(USE_WATCHDOG)
|
||||
|
||||
// 4 seconds timeout
|
||||
uint32_t timeout = TERN(WATCHDOG_DURATION_8S, 8000, 4000);
|
||||
|
||||
// Calculate timeout value in WDT counter ticks: This assumes
|
||||
// the slow clock is running at 32.768 kHz watchdog
|
||||
// frequency is therefore 32768 / 128 = 256 Hz
|
||||
timeout = (timeout << 8) / 1000;
|
||||
if (timeout == 0)
|
||||
timeout = 1;
|
||||
else if (timeout > 0xFFF)
|
||||
timeout = 0xFFF;
|
||||
|
||||
// We want to enable the watchdog with the specified timeout
|
||||
uint32_t value =
|
||||
WDT_MR_WDV(timeout) | // With the specified timeout
|
||||
WDT_MR_WDD(timeout) | // and no invalid write window
|
||||
#if !(SAMV70 || SAMV71 || SAME70 || SAMS70)
|
||||
WDT_MR_WDRPROC | // WDT fault resets processor only - We want
|
||||
// to keep PIO controller state
|
||||
#endif
|
||||
WDT_MR_WDDBGHLT | // WDT stops in debug state.
|
||||
WDT_MR_WDIDLEHLT; // WDT stops in idle state.
|
||||
|
||||
#if ENABLED(WATCHDOG_RESET_MANUAL)
|
||||
// We enable the watchdog timer, but only for the interrupt.
|
||||
|
||||
// Configure WDT to only trigger an interrupt
|
||||
value |= WDT_MR_WDFIEN; // Enable WDT fault interrupt.
|
||||
|
||||
// Disable WDT interrupt (just in case, to avoid triggering it!)
|
||||
NVIC_DisableIRQ(WDT_IRQn);
|
||||
|
||||
// We NEED memory barriers to ensure Interrupts are actually disabled!
|
||||
// ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
|
||||
__DSB();
|
||||
__ISB();
|
||||
|
||||
// Initialize WDT with the given parameters
|
||||
WDT_Enable(WDT, value);
|
||||
|
||||
// Configure and enable WDT interrupt.
|
||||
NVIC_ClearPendingIRQ(WDT_IRQn);
|
||||
NVIC_SetPriority(WDT_IRQn, 0); // Use highest priority, so we detect all kinds of lockups
|
||||
NVIC_EnableIRQ(WDT_IRQn);
|
||||
|
||||
#else
|
||||
|
||||
// a WDT fault triggers a reset
|
||||
value |= WDT_MR_WDRSTEN;
|
||||
|
||||
// Initialize WDT with the given parameters
|
||||
WDT_Enable(WDT, value);
|
||||
|
||||
#endif
|
||||
|
||||
// Reset the watchdog
|
||||
WDT_Restart(WDT);
|
||||
|
||||
#else
|
||||
|
||||
// Make sure to completely disable the Watchdog
|
||||
WDT_Disable(WDT);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
// ------------------------
|
||||
// Free Memory Accessor
|
||||
// ------------------------
|
||||
|
||||
extern "C" {
|
||||
extern unsigned int _ebss; // end of bss section
|
||||
}
|
||||
@@ -82,6 +180,10 @@ int freeMemory() {
|
||||
return (int)&free_memory - (heap_end ?: (int)&_ebss);
|
||||
}
|
||||
|
||||
// ------------------------
|
||||
// Serial Ports
|
||||
// ------------------------
|
||||
|
||||
// Forward the default serial ports
|
||||
#if USING_HW_SERIAL0
|
||||
DefaultSerial1 MSerial0(false, Serial);
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
#include "../shared/math_32bit.h"
|
||||
#include "../shared/HAL_SPI.h"
|
||||
#include "fastio.h"
|
||||
#include "watchdog.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -115,8 +114,8 @@ typedef Servo hal_servo_t;
|
||||
//
|
||||
// Interrupts
|
||||
//
|
||||
#define sei() noInterrupts()
|
||||
#define cli() interrupts()
|
||||
#define sei() interrupts()
|
||||
#define cli() noInterrupts()
|
||||
|
||||
#define CRITICAL_SECTION_START() const bool _irqon = hal.isr_state(); hal.isr_off()
|
||||
#define CRITICAL_SECTION_END() if (_irqon) hal.isr_on()
|
||||
@@ -176,9 +175,13 @@ public:
|
||||
// Earliest possible init, before setup()
|
||||
MarlinHAL() {}
|
||||
|
||||
static void init(); // Called early in setup()
|
||||
static void init_board(); // Called less early in setup()
|
||||
static void reboot(); // Software reset
|
||||
// Watchdog
|
||||
static void watchdog_init() IF_DISABLED(USE_WATCHDOG, {});
|
||||
static void watchdog_refresh() IF_DISABLED(USE_WATCHDOG, {});
|
||||
|
||||
static void init(); // Called early in setup()
|
||||
static void init_board(); // Called less early in setup()
|
||||
static void reboot(); // Restart the firmware
|
||||
|
||||
// Interrupts
|
||||
static bool isr_state() { return !__get_PRIMASK(); }
|
||||
@@ -207,7 +210,7 @@ public:
|
||||
static void adc_init() {}
|
||||
|
||||
// Called by Temperature::init for each sensor at startup
|
||||
static void adc_enable(const uint8_t ch) {}
|
||||
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); }
|
||||
|
||||
@@ -31,8 +31,6 @@
|
||||
|
||||
/**
|
||||
* HAL for Arduino Due and compatible (SAM3X8E)
|
||||
*
|
||||
* For ARDUINO_ARCH_SAM
|
||||
*/
|
||||
|
||||
#ifdef ARDUINO_ARCH_SAM
|
||||
@@ -249,12 +247,12 @@
|
||||
b <<= 1; // little setup time
|
||||
|
||||
WRITE(SD_SCK_PIN, HIGH);
|
||||
DELAY_NS(spiDelayNS);
|
||||
DELAY_NS_VAR(spiDelayNS);
|
||||
|
||||
b |= (READ(SD_MISO_PIN) != 0);
|
||||
|
||||
WRITE(SD_SCK_PIN, LOW);
|
||||
DELAY_NS(spiDelayNS);
|
||||
DELAY_NS_VAR(spiDelayNS);
|
||||
} while (--bits);
|
||||
return b;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
practice, we need alignment to 256 bytes to make this work in all
|
||||
cases */
|
||||
__attribute__ ((aligned(256)))
|
||||
static DeviceVectors ram_tab = { nullptr };
|
||||
static DeviceVectors ram_tab[61] = { nullptr };
|
||||
|
||||
/**
|
||||
* This function checks if the exception/interrupt table is already in SRAM or not.
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include <WString.h>
|
||||
|
||||
#include "../../inc/MarlinConfigPre.h"
|
||||
#include "../../core/types.h"
|
||||
#include "../../core/serial_hook.h"
|
||||
|
||||
// Define constants and variables for buffering incoming serial data. We're
|
||||
@@ -52,10 +53,6 @@
|
||||
// #error "TX_BUFFER_SIZE must be 0, a power of 2 greater than 1, and no greater than 256."
|
||||
//#endif
|
||||
|
||||
// Templated type selector
|
||||
template<bool b, typename T, typename F> struct TypeSelector { typedef T type;} ;
|
||||
template<typename T, typename F> struct TypeSelector<false, T, F> { typedef F type; };
|
||||
|
||||
// Templated structure wrapper
|
||||
template<typename S, unsigned int addr> struct StructWrapper {
|
||||
constexpr StructWrapper(int) {}
|
||||
@@ -76,7 +73,7 @@ protected:
|
||||
static constexpr int HWUART_IRQ_ID = IRQ_IDS[Cfg::PORT];
|
||||
|
||||
// Base size of type on buffer size
|
||||
typedef typename TypeSelector<(Cfg::RX_SIZE>256), uint16_t, uint8_t>::type ring_buffer_pos_t;
|
||||
typedef uvalue_t(Cfg::RX_SIZE - 1) ring_buffer_pos_t;
|
||||
|
||||
struct ring_buffer_r {
|
||||
volatile ring_buffer_pos_t head, tail;
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
#if ENABLED(POSTMORTEM_DEBUGGING)
|
||||
|
||||
#include "../shared/HAL_MinSerial.h"
|
||||
#include "../shared/MinSerial.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
@@ -47,12 +47,12 @@
|
||||
#include "../shared/servo.h"
|
||||
#include "../shared/servo_private.h"
|
||||
|
||||
static volatile int8_t Channel[_Nbr_16timers]; // counter for the servo being pulsed for each timer (or -1 if refresh interval)
|
||||
static Flags<_Nbr_16timers> DisablePending; // ISR should disable the timer at the next timer reset
|
||||
|
||||
// ------------------------
|
||||
/// Interrupt handler for the TC0 channel 1.
|
||||
// ------------------------
|
||||
void Servo_Handler(timer16_Sequence_t timer, Tc *pTc, uint8_t channel);
|
||||
void Servo_Handler(const timer16_Sequence_t, Tc*, const uint8_t);
|
||||
|
||||
#ifdef _useTimer1
|
||||
void HANDLER_FOR_TIMER1() { Servo_Handler(_timer1, TC_FOR_TIMER1, CHANNEL_FOR_TIMER1); }
|
||||
@@ -70,88 +70,92 @@ void Servo_Handler(timer16_Sequence_t timer, Tc *pTc, uint8_t channel);
|
||||
void HANDLER_FOR_TIMER5() { Servo_Handler(_timer5, TC_FOR_TIMER5, CHANNEL_FOR_TIMER5); }
|
||||
#endif
|
||||
|
||||
void Servo_Handler(timer16_Sequence_t timer, Tc *tc, uint8_t channel) {
|
||||
// clear interrupt
|
||||
tc->TC_CHANNEL[channel].TC_SR;
|
||||
if (Channel[timer] < 0)
|
||||
tc->TC_CHANNEL[channel].TC_CCR |= TC_CCR_SWTRG; // channel set to -1 indicated that refresh interval completed so reset the timer
|
||||
else if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && SERVO(timer, Channel[timer]).Pin.isActive)
|
||||
extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, LOW); // pulse this channel low if activated
|
||||
void Servo_Handler(const timer16_Sequence_t timer, Tc *tc, const uint8_t channel) {
|
||||
static int8_t Channel[_Nbr_16timers]; // Servo counters to pulse (or -1 for refresh interval)
|
||||
int8_t cho = Channel[timer]; // Handle the prior Channel[timer] first
|
||||
if (cho < 0) { // Channel -1 indicates the refresh interval completed...
|
||||
tc->TC_CHANNEL[channel].TC_CCR |= TC_CCR_SWTRG; // ...so reset the timer
|
||||
if (DisablePending[timer]) {
|
||||
// Disabling only after the full servo period expires prevents
|
||||
// pulses being too close together if immediately re-enabled.
|
||||
DisablePending.clear(timer);
|
||||
TC_Stop(tc, channel);
|
||||
tc->TC_CHANNEL[channel].TC_SR; // clear interrupt
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (SERVO_INDEX(timer, cho) < ServoCount) // prior channel handled?
|
||||
extDigitalWrite(SERVO(timer, cho).Pin.nbr, LOW); // pulse the prior channel LOW
|
||||
|
||||
Channel[timer]++; // increment to the next channel
|
||||
if (SERVO_INDEX(timer, Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) {
|
||||
tc->TC_CHANNEL[channel].TC_RA = tc->TC_CHANNEL[channel].TC_CV + SERVO(timer,Channel[timer]).ticks;
|
||||
if (SERVO(timer,Channel[timer]).Pin.isActive) // check if activated
|
||||
extDigitalWrite(SERVO(timer, Channel[timer]).Pin.nbr, HIGH); // its an active channel so pulse it high
|
||||
Channel[timer] = ++cho; // go to the next channel (or 0)
|
||||
if (cho < SERVOS_PER_TIMER && SERVO_INDEX(timer, cho) < ServoCount) {
|
||||
tc->TC_CHANNEL[channel].TC_RA = tc->TC_CHANNEL[channel].TC_CV + SERVO(timer, cho).ticks;
|
||||
if (SERVO(timer, cho).Pin.isActive) // activated?
|
||||
extDigitalWrite(SERVO(timer, cho).Pin.nbr, HIGH); // yes: pulse HIGH
|
||||
}
|
||||
else {
|
||||
// finished all channels so wait for the refresh period to expire before starting over
|
||||
tc->TC_CHANNEL[channel].TC_RA =
|
||||
tc->TC_CHANNEL[channel].TC_CV < usToTicks(REFRESH_INTERVAL) - 4
|
||||
? (unsigned int)usToTicks(REFRESH_INTERVAL) // allow a few ticks to ensure the next OCR1A not missed
|
||||
: tc->TC_CHANNEL[channel].TC_CV + 4; // at least REFRESH_INTERVAL has elapsed
|
||||
Channel[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel
|
||||
const unsigned int cval = tc->TC_CHANNEL[channel].TC_CV + 128 / (SERVO_TIMER_PRESCALER), // allow 128 cycles to ensure the next CV not missed
|
||||
ival = (unsigned int)usToTicks(REFRESH_INTERVAL); // at least REFRESH_INTERVAL has elapsed
|
||||
tc->TC_CHANNEL[channel].TC_RA = max(cval, ival);
|
||||
|
||||
Channel[timer] = -1; // reset the timer CCR on the next call
|
||||
}
|
||||
|
||||
tc->TC_CHANNEL[channel].TC_SR; // clear interrupt
|
||||
}
|
||||
|
||||
static void _initISR(Tc *tc, uint32_t channel, uint32_t id, IRQn_Type irqn) {
|
||||
pmc_enable_periph_clk(id);
|
||||
TC_Configure(tc, channel,
|
||||
TC_CMR_TCCLKS_TIMER_CLOCK3 | // MCK/32
|
||||
TC_CMR_WAVE | // Waveform mode
|
||||
TC_CMR_WAVSEL_UP_RC ); // Counter running up and reset when equals to RC
|
||||
TC_CMR_WAVE // Waveform mode
|
||||
| TC_CMR_WAVSEL_UP_RC // Counter running up and reset when equal to RC
|
||||
| (SERVO_TIMER_PRESCALER == 2 ? TC_CMR_TCCLKS_TIMER_CLOCK1 : 0) // MCK/2
|
||||
| (SERVO_TIMER_PRESCALER == 8 ? TC_CMR_TCCLKS_TIMER_CLOCK2 : 0) // MCK/8
|
||||
| (SERVO_TIMER_PRESCALER == 32 ? TC_CMR_TCCLKS_TIMER_CLOCK3 : 0) // MCK/32
|
||||
| (SERVO_TIMER_PRESCALER == 128 ? TC_CMR_TCCLKS_TIMER_CLOCK4 : 0) // MCK/128
|
||||
);
|
||||
|
||||
/* 84MHz, MCK/32, for 1.5ms: 3937 */
|
||||
TC_SetRA(tc, channel, 2625); // 1ms
|
||||
// Wait 1ms before the first ISR
|
||||
TC_SetRA(tc, channel, (F_CPU) / (SERVO_TIMER_PRESCALER) / 1000UL); // 1ms
|
||||
|
||||
/* Configure and enable interrupt */
|
||||
// Configure and enable interrupt
|
||||
NVIC_EnableIRQ(irqn);
|
||||
// TC_IER_CPAS: RA Compare
|
||||
tc->TC_CHANNEL[channel].TC_IER = TC_IER_CPAS;
|
||||
tc->TC_CHANNEL[channel].TC_IER = TC_IER_CPAS; // TC_IER_CPAS: RA Compare
|
||||
|
||||
// Enables the timer clock and performs a software reset to start the counting
|
||||
TC_Start(tc, channel);
|
||||
}
|
||||
|
||||
void initISR(timer16_Sequence_t timer) {
|
||||
#ifdef _useTimer1
|
||||
if (timer == _timer1)
|
||||
_initISR(TC_FOR_TIMER1, CHANNEL_FOR_TIMER1, ID_TC_FOR_TIMER1, IRQn_FOR_TIMER1);
|
||||
#endif
|
||||
#ifdef _useTimer2
|
||||
if (timer == _timer2)
|
||||
_initISR(TC_FOR_TIMER2, CHANNEL_FOR_TIMER2, ID_TC_FOR_TIMER2, IRQn_FOR_TIMER2);
|
||||
#endif
|
||||
#ifdef _useTimer3
|
||||
if (timer == _timer3)
|
||||
_initISR(TC_FOR_TIMER3, CHANNEL_FOR_TIMER3, ID_TC_FOR_TIMER3, IRQn_FOR_TIMER3);
|
||||
#endif
|
||||
#ifdef _useTimer4
|
||||
if (timer == _timer4)
|
||||
_initISR(TC_FOR_TIMER4, CHANNEL_FOR_TIMER4, ID_TC_FOR_TIMER4, IRQn_FOR_TIMER4);
|
||||
#endif
|
||||
#ifdef _useTimer5
|
||||
if (timer == _timer5)
|
||||
_initISR(TC_FOR_TIMER5, CHANNEL_FOR_TIMER5, ID_TC_FOR_TIMER5, IRQn_FOR_TIMER5);
|
||||
#endif
|
||||
void initISR(const timer16_Sequence_t timer_index) {
|
||||
CRITICAL_SECTION_START();
|
||||
const bool disable_soon = DisablePending[timer_index];
|
||||
DisablePending.clear(timer_index);
|
||||
CRITICAL_SECTION_END();
|
||||
|
||||
if (!disable_soon) switch (timer_index) {
|
||||
default: break;
|
||||
#ifdef _useTimer1
|
||||
case _timer1: return _initISR(TC_FOR_TIMER1, CHANNEL_FOR_TIMER1, ID_TC_FOR_TIMER1, IRQn_FOR_TIMER1);
|
||||
#endif
|
||||
#ifdef _useTimer2
|
||||
case _timer2: return _initISR(TC_FOR_TIMER2, CHANNEL_FOR_TIMER2, ID_TC_FOR_TIMER2, IRQn_FOR_TIMER2);
|
||||
#endif
|
||||
#ifdef _useTimer3
|
||||
case _timer3: return _initISR(TC_FOR_TIMER3, CHANNEL_FOR_TIMER3, ID_TC_FOR_TIMER3, IRQn_FOR_TIMER3);
|
||||
#endif
|
||||
#ifdef _useTimer4
|
||||
case _timer4: return _initISR(TC_FOR_TIMER4, CHANNEL_FOR_TIMER4, ID_TC_FOR_TIMER4, IRQn_FOR_TIMER4);
|
||||
#endif
|
||||
#ifdef _useTimer5
|
||||
case _timer5: return _initISR(TC_FOR_TIMER5, CHANNEL_FOR_TIMER5, ID_TC_FOR_TIMER5, IRQn_FOR_TIMER5);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void finISR(timer16_Sequence_t) {
|
||||
#ifdef _useTimer1
|
||||
TC_Stop(TC_FOR_TIMER1, CHANNEL_FOR_TIMER1);
|
||||
#endif
|
||||
#ifdef _useTimer2
|
||||
TC_Stop(TC_FOR_TIMER2, CHANNEL_FOR_TIMER2);
|
||||
#endif
|
||||
#ifdef _useTimer3
|
||||
TC_Stop(TC_FOR_TIMER3, CHANNEL_FOR_TIMER3);
|
||||
#endif
|
||||
#ifdef _useTimer4
|
||||
TC_Stop(TC_FOR_TIMER4, CHANNEL_FOR_TIMER4);
|
||||
#endif
|
||||
#ifdef _useTimer5
|
||||
TC_Stop(TC_FOR_TIMER5, CHANNEL_FOR_TIMER5);
|
||||
#endif
|
||||
void finISR(const timer16_Sequence_t timer_index) {
|
||||
// Timer is disabled from the ISR, to ensure proper final pulse length.
|
||||
DisablePending.set(timer_index);
|
||||
}
|
||||
|
||||
#endif // HAS_SERVOS
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
#define _useTimer5
|
||||
|
||||
#define TRIM_DURATION 2 // compensation ticks to trim adjust for digitalWrite delays
|
||||
#define SERVO_TIMER_PRESCALER 32 // timer prescaler
|
||||
#define SERVO_TIMER_PRESCALER 2 // timer prescaler
|
||||
|
||||
/*
|
||||
TC0, chan 0 => TC0_Handler
|
||||
|
||||
@@ -199,8 +199,7 @@ static bool ee_PageWrite(uint16_t page, const void *data) {
|
||||
for (i = 0; i <PageSize >> 2; i++)
|
||||
pageContents[i] = (((uint32_t*)data)[i]) | (~(pageContents[i] ^ ((uint32_t*)data)[i]));
|
||||
|
||||
DEBUG_ECHO_START();
|
||||
DEBUG_ECHOLNPGM("EEPROM PageWrite ", page);
|
||||
DEBUG_ECHO_MSG("EEPROM PageWrite ", page);
|
||||
DEBUG_ECHOLNPGM(" in FLASH address ", (uint32_t)addrflash);
|
||||
DEBUG_ECHOLNPGM(" base address ", (uint32_t)getFlashStorage(0));
|
||||
DEBUG_FLUSH();
|
||||
@@ -245,8 +244,7 @@ static bool ee_PageWrite(uint16_t page, const void *data) {
|
||||
// Reenable interrupts
|
||||
__enable_irq();
|
||||
|
||||
DEBUG_ECHO_START();
|
||||
DEBUG_ECHOLNPGM("EEPROM Unlock failure for page ", page);
|
||||
DEBUG_ECHO_MSG("EEPROM Unlock failure for page ", page);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -270,8 +268,7 @@ static bool ee_PageWrite(uint16_t page, const void *data) {
|
||||
// Reenable interrupts
|
||||
__enable_irq();
|
||||
|
||||
DEBUG_ECHO_START();
|
||||
DEBUG_ECHOLNPGM("EEPROM Write failure for page ", page);
|
||||
DEBUG_ECHO_MSG("EEPROM Write failure for page ", page);
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -286,8 +283,7 @@ static bool ee_PageWrite(uint16_t page, const void *data) {
|
||||
if (memcmp(getFlashStorage(page),data,PageSize)) {
|
||||
|
||||
#ifdef EE_EMU_DEBUG
|
||||
DEBUG_ECHO_START();
|
||||
DEBUG_ECHOLNPGM("EEPROM Verify Write failure for page ", page);
|
||||
DEBUG_ECHO_MSG("EEPROM Verify Write failure for page ", page);
|
||||
|
||||
ee_Dump( page, (uint32_t *)addrflash);
|
||||
ee_Dump(-page, data);
|
||||
@@ -325,8 +321,7 @@ static bool ee_PageErase(uint16_t page) {
|
||||
uint16_t i;
|
||||
uint32_t addrflash = uint32_t(getFlashStorage(page));
|
||||
|
||||
DEBUG_ECHO_START();
|
||||
DEBUG_ECHOLNPGM("EEPROM PageErase ", page);
|
||||
DEBUG_ECHO_MSG("EEPROM PageErase ", page);
|
||||
DEBUG_ECHOLNPGM(" in FLASH address ", (uint32_t)addrflash);
|
||||
DEBUG_ECHOLNPGM(" base address ", (uint32_t)getFlashStorage(0));
|
||||
DEBUG_FLUSH();
|
||||
@@ -370,8 +365,7 @@ static bool ee_PageErase(uint16_t page) {
|
||||
// Reenable interrupts
|
||||
__enable_irq();
|
||||
|
||||
DEBUG_ECHO_START();
|
||||
DEBUG_ECHOLNPGM("EEPROM Unlock failure for page ",page);
|
||||
DEBUG_ECHO_MSG("EEPROM Unlock failure for page ",page);
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -394,8 +388,7 @@ static bool ee_PageErase(uint16_t page) {
|
||||
// Reenable interrupts
|
||||
__enable_irq();
|
||||
|
||||
DEBUG_ECHO_START();
|
||||
DEBUG_ECHOLNPGM("EEPROM Erase failure for page ",page);
|
||||
DEBUG_ECHO_MSG("EEPROM Erase failure for page ",page);
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -410,8 +403,7 @@ static bool ee_PageErase(uint16_t page) {
|
||||
uint32_t * aligned_src = (uint32_t *) addrflash;
|
||||
for (i = 0; i < PageSize >> 2; i++) {
|
||||
if (*aligned_src++ != 0xFFFFFFFF) {
|
||||
DEBUG_ECHO_START();
|
||||
DEBUG_ECHOLNPGM("EEPROM Verify Erase failure for page ",page);
|
||||
DEBUG_ECHO_MSG("EEPROM Verify Erase failure for page ",page);
|
||||
ee_Dump(page, (uint32_t *)addrflash);
|
||||
return false;
|
||||
}
|
||||
@@ -921,8 +913,7 @@ static void ee_Init() {
|
||||
// If all groups seem to be used, default to first group
|
||||
if (curGroup >= GroupCount) curGroup = 0;
|
||||
|
||||
DEBUG_ECHO_START();
|
||||
DEBUG_ECHOLNPGM("EEPROM Current Group: ",curGroup);
|
||||
DEBUG_ECHO_MSG("EEPROM Current Group: ",curGroup);
|
||||
DEBUG_FLUSH();
|
||||
|
||||
// Now, validate that all the other group pages are empty
|
||||
@@ -931,8 +922,7 @@ static void ee_Init() {
|
||||
|
||||
for (int page = 0; page < PagesPerGroup; page++) {
|
||||
if (!ee_IsPageClean(grp * PagesPerGroup + page)) {
|
||||
DEBUG_ECHO_START();
|
||||
DEBUG_ECHOLNPGM("EEPROM Page ", page, " not clean on group ", grp);
|
||||
DEBUG_ECHO_MSG("EEPROM Page ", page, " not clean on group ", grp);
|
||||
DEBUG_FLUSH();
|
||||
ee_PageErase(grp * PagesPerGroup + page);
|
||||
}
|
||||
@@ -948,15 +938,13 @@ static void ee_Init() {
|
||||
}
|
||||
}
|
||||
|
||||
DEBUG_ECHO_START();
|
||||
DEBUG_ECHOLNPGM("EEPROM Active page: ", curPage);
|
||||
DEBUG_ECHO_MSG("EEPROM Active page: ", curPage);
|
||||
DEBUG_FLUSH();
|
||||
|
||||
// Make sure the pages following the first clean one are also clean
|
||||
for (int page = curPage + 1; page < PagesPerGroup; page++) {
|
||||
if (!ee_IsPageClean(curGroup * PagesPerGroup + page)) {
|
||||
DEBUG_ECHO_START();
|
||||
DEBUG_ECHOLNPGM("EEPROM Page ", page, " not clean on active group ", curGroup);
|
||||
DEBUG_ECHO_MSG("EEPROM Page ", page, " not clean on active group ", curGroup);
|
||||
DEBUG_FLUSH();
|
||||
ee_Dump(curGroup * PagesPerGroup + page, getFlashStorage(curGroup * PagesPerGroup + page));
|
||||
ee_PageErase(curGroup * PagesPerGroup + page);
|
||||
|
||||
@@ -25,6 +25,30 @@
|
||||
* Test Arduino Due specific configuration values for errors at compile-time.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Check for common serial pin conflicts
|
||||
*/
|
||||
#define CHECK_SERIAL_PIN(N) ( \
|
||||
X_STOP_PIN == N || Y_STOP_PIN == N || Z_STOP_PIN == N \
|
||||
|| X_MIN_PIN == N || Y_MIN_PIN == N || Z_MIN_PIN == N \
|
||||
|| X_MAX_PIN == N || Y_MAX_PIN == N || Z_MAX_PIN == N \
|
||||
|| X_STEP_PIN == N || Y_STEP_PIN == N || Z_STEP_PIN == N \
|
||||
|| X_DIR_PIN == N || Y_DIR_PIN == N || Z_DIR_PIN == N \
|
||||
|| X_ENA_PIN == N || Y_ENA_PIN == N || Z_ENA_PIN == N \
|
||||
)
|
||||
#if SERIAL_IN_USE(0) // D0-D1. No known conflicts.
|
||||
#endif
|
||||
#if SERIAL_IN_USE(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 SERIAL_IN_USE(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 SERIAL_IN_USE(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
|
||||
*
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
#define PRINT_PIN_ANALOG(p) do{ sprintf_P(buffer, PSTR(" (A%2d) "), DIGITAL_PIN_TO_ANALOG_PIN(pin)); SERIAL_ECHO(buffer); }while(0)
|
||||
#define GET_ARRAY_PIN(p) pin_array[p].pin
|
||||
#define GET_ARRAY_IS_DIGITAL(p) pin_array[p].is_digital
|
||||
#define VALID_PIN(pin) (pin >= 0 && pin < (int8_t)NUMBER_PINS_TOTAL ? 1 : 0)
|
||||
#define VALID_PIN(pin) (pin >= 0 && pin < int8_t(NUMBER_PINS_TOTAL))
|
||||
#define DIGITAL_PIN_TO_ANALOG_PIN(p) int(p - analogInputToDigitalPin(0))
|
||||
#define IS_ANALOG(P) WITHIN(P, char(analogInputToDigitalPin(0)), char(analogInputToDigitalPin(NUM_ANALOG_INPUTS - 1)))
|
||||
#define pwm_status(pin) (((g_pinStatus[pin] & 0xF) == PIN_STATUS_PWM) && \
|
||||
@@ -86,7 +86,6 @@ bool GET_PINMODE(int8_t pin) { // 1: output, 0: input
|
||||
|| pwm_status(pin));
|
||||
}
|
||||
|
||||
|
||||
void pwm_details(int32_t pin) {
|
||||
if (pwm_status(pin)) {
|
||||
uint32_t chan = g_APinDescription[pin].ulPWMChannel;
|
||||
|
||||
@@ -89,10 +89,17 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
|
||||
NVIC_SetPriority(irq, timer_config[timer_num].priority);
|
||||
|
||||
// wave mode, reset counter on match with RC,
|
||||
TC_Configure(tc, channel, TC_CMR_WAVE | TC_CMR_WAVSEL_UP_RC | TC_CMR_TCCLKS_TIMER_CLOCK1);
|
||||
TC_Configure(tc, channel,
|
||||
TC_CMR_WAVE
|
||||
| TC_CMR_WAVSEL_UP_RC
|
||||
| (HAL_TIMER_PRESCALER == 2 ? TC_CMR_TCCLKS_TIMER_CLOCK1 : 0)
|
||||
| (HAL_TIMER_PRESCALER == 8 ? TC_CMR_TCCLKS_TIMER_CLOCK2 : 0)
|
||||
| (HAL_TIMER_PRESCALER == 32 ? TC_CMR_TCCLKS_TIMER_CLOCK3 : 0)
|
||||
| (HAL_TIMER_PRESCALER == 128 ? TC_CMR_TCCLKS_TIMER_CLOCK4 : 0)
|
||||
);
|
||||
|
||||
// Set compare value
|
||||
TC_SetRC(tc, channel, VARIANT_MCK / 2 / frequency);
|
||||
TC_SetRC(tc, channel, VARIANT_MCK / (HAL_TIMER_PRESCALER) / frequency);
|
||||
|
||||
// And start timer
|
||||
TC_Start(tc, channel);
|
||||
|
||||
@@ -35,7 +35,8 @@
|
||||
typedef uint32_t hal_timer_t;
|
||||
#define HAL_TIMER_TYPE_MAX 0xFFFFFFFF
|
||||
|
||||
#define HAL_TIMER_RATE ((F_CPU) / 2) // frequency of timers peripherals
|
||||
#define HAL_TIMER_PRESCALER 2
|
||||
#define HAL_TIMER_RATE ((F_CPU) / (HAL_TIMER_PRESCALER)) // frequency of timers peripherals
|
||||
|
||||
#ifndef MF_TIMER_STEP
|
||||
#define MF_TIMER_STEP 2 // Timer Index for Stepper
|
||||
|
||||
@@ -6,14 +6,14 @@
|
||||
#
|
||||
import pioutil
|
||||
if pioutil.is_pio_build():
|
||||
import platform
|
||||
current_OS = platform.system()
|
||||
import platform
|
||||
current_OS = platform.system()
|
||||
|
||||
if current_OS == 'Windows':
|
||||
if current_OS == 'Windows':
|
||||
|
||||
Import("env")
|
||||
Import("env")
|
||||
|
||||
# Use bossac.exe on Windows
|
||||
env.Replace(
|
||||
UPLOADCMD="bossac --info --unlock --write --verify --reset --erase -U false --boot $SOURCE"
|
||||
)
|
||||
# Use bossac.exe on Windows
|
||||
env.Replace(
|
||||
UPLOADCMD="bossac --info --unlock --write --verify --reset --erase -U false --boot $SOURCE"
|
||||
)
|
||||
|
||||
@@ -1059,7 +1059,7 @@ static inline void convert_64_bit_to_byte_array(uint64_t value, uint8_t *data)
|
||||
while (val_index < 8)
|
||||
{
|
||||
data[val_index++] = value & 0xFF;
|
||||
value = value >> 8;
|
||||
value >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ void usb_task_idle(void) {
|
||||
// Attend SD card access from the USB MSD -- Prioritize access to improve speed
|
||||
int delay = 2;
|
||||
while (main_b_msc_enable && --delay > 0) {
|
||||
if (udi_msc_process_trans()) delay = 10000;
|
||||
if (udi_msc_process_trans()) delay = 20;
|
||||
|
||||
// Reset the watchdog, just to be sure
|
||||
REG_WDT_CR = WDT_CR_WDRSTT | WDT_CR_KEY(0xA5);
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifdef ARDUINO_ARCH_SAM
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
#include "../../MarlinCore.h"
|
||||
#include "watchdog.h"
|
||||
|
||||
// Override Arduino runtime to either config or disable the watchdog
|
||||
//
|
||||
// We need to configure the watchdog as soon as possible in the boot
|
||||
// process, because watchdog initialization at hardware reset on SAM3X8E
|
||||
// is unreliable, and there is risk of unintended resets if we delay
|
||||
// that initialization to a later time.
|
||||
void watchdogSetup() {
|
||||
|
||||
#if ENABLED(USE_WATCHDOG)
|
||||
|
||||
// 4 seconds timeout
|
||||
uint32_t timeout = TERN(WATCHDOG_DURATION_8S, 8000, 4000);
|
||||
|
||||
// Calculate timeout value in WDT counter ticks: This assumes
|
||||
// the slow clock is running at 32.768 kHz watchdog
|
||||
// frequency is therefore 32768 / 128 = 256 Hz
|
||||
timeout = (timeout << 8) / 1000;
|
||||
if (timeout == 0)
|
||||
timeout = 1;
|
||||
else if (timeout > 0xFFF)
|
||||
timeout = 0xFFF;
|
||||
|
||||
// We want to enable the watchdog with the specified timeout
|
||||
uint32_t value =
|
||||
WDT_MR_WDV(timeout) | // With the specified timeout
|
||||
WDT_MR_WDD(timeout) | // and no invalid write window
|
||||
#if !(SAMV70 || SAMV71 || SAME70 || SAMS70)
|
||||
WDT_MR_WDRPROC | // WDT fault resets processor only - We want
|
||||
// to keep PIO controller state
|
||||
#endif
|
||||
WDT_MR_WDDBGHLT | // WDT stops in debug state.
|
||||
WDT_MR_WDIDLEHLT; // WDT stops in idle state.
|
||||
|
||||
#if ENABLED(WATCHDOG_RESET_MANUAL)
|
||||
// We enable the watchdog timer, but only for the interrupt.
|
||||
|
||||
// Configure WDT to only trigger an interrupt
|
||||
value |= WDT_MR_WDFIEN; // Enable WDT fault interrupt.
|
||||
|
||||
// Disable WDT interrupt (just in case, to avoid triggering it!)
|
||||
NVIC_DisableIRQ(WDT_IRQn);
|
||||
|
||||
// We NEED memory barriers to ensure Interrupts are actually disabled!
|
||||
// ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
|
||||
__DSB();
|
||||
__ISB();
|
||||
|
||||
// Initialize WDT with the given parameters
|
||||
WDT_Enable(WDT, value);
|
||||
|
||||
// Configure and enable WDT interrupt.
|
||||
NVIC_ClearPendingIRQ(WDT_IRQn);
|
||||
NVIC_SetPriority(WDT_IRQn, 0); // Use highest priority, so we detect all kinds of lockups
|
||||
NVIC_EnableIRQ(WDT_IRQn);
|
||||
|
||||
#else
|
||||
|
||||
// a WDT fault triggers a reset
|
||||
value |= WDT_MR_WDRSTEN;
|
||||
|
||||
// Initialize WDT with the given parameters
|
||||
WDT_Enable(WDT, value);
|
||||
|
||||
#endif
|
||||
|
||||
// Reset the watchdog
|
||||
WDT_Restart(WDT);
|
||||
|
||||
#else
|
||||
|
||||
// Make sure to completely disable the Watchdog
|
||||
WDT_Disable(WDT);
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ENABLED(USE_WATCHDOG)
|
||||
// Initialize watchdog - On SAM3X, Watchdog was already configured
|
||||
// and enabled or disabled at startup, so no need to reconfigure it
|
||||
// here.
|
||||
void watchdog_init() {
|
||||
// Reset watchdog to start clean
|
||||
WDT_Restart(WDT);
|
||||
}
|
||||
#endif // USE_WATCHDOG
|
||||
|
||||
#endif
|
||||
@@ -65,6 +65,7 @@ portMUX_TYPE MarlinHAL::spinlock = portMUX_INITIALIZER_UNLOCKED;
|
||||
// ------------------------
|
||||
|
||||
uint16_t MarlinHAL::adc_result;
|
||||
pwm_pin_t MarlinHAL::pwm_pin_data[MAX_EXPANDER_BITS];
|
||||
|
||||
// ------------------------
|
||||
// Private Variables
|
||||
@@ -179,6 +180,31 @@ void _delay_ms(int delay_ms) { delay(delay_ms); }
|
||||
// return free memory between end of heap (or end bss) and whatever is current
|
||||
int MarlinHAL::freeMemory() { return ESP.getFreeHeap(); }
|
||||
|
||||
// ------------------------
|
||||
// Watchdog Timer
|
||||
// ------------------------
|
||||
|
||||
#if ENABLED(USE_WATCHDOG)
|
||||
|
||||
#define WDT_TIMEOUT_US TERN(WATCHDOG_DURATION_8S, 8000000, 4000000) // 4 or 8 second timeout
|
||||
|
||||
extern "C" {
|
||||
esp_err_t esp_task_wdt_reset();
|
||||
}
|
||||
|
||||
void watchdogSetup() {
|
||||
// do whatever. don't remove this function.
|
||||
}
|
||||
|
||||
void MarlinHAL::watchdog_init() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
// Reset watchdog.
|
||||
void MarlinHAL::watchdog_refresh() { esp_task_wdt_reset(); }
|
||||
|
||||
#endif
|
||||
|
||||
// ------------------------
|
||||
// ADC
|
||||
// ------------------------
|
||||
@@ -305,14 +331,37 @@ int8_t get_pwm_channel(const pin_t pin, const uint32_t freq, const uint16_t res)
|
||||
}
|
||||
|
||||
void MarlinHAL::set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=_BV(PWM_RESOLUTION)-1*/, const bool invert/*=false*/) {
|
||||
#if ENABLED(I2S_STEPPER_STREAM)
|
||||
if (pin > 127) {
|
||||
const uint8_t pinlo = pin & 0x7F;
|
||||
pwm_pin_t &pindata = pwm_pin_data[pinlo];
|
||||
const uint32_t duty = map(invert ? v_size - v : v, 0, v_size, 0, pindata.pwm_cycle_ticks);
|
||||
if (duty == 0 || duty == pindata.pwm_cycle_ticks) { // max or min (i.e., on/off)
|
||||
pindata.pwm_duty_ticks = 0; // turn off PWM for this pin
|
||||
duty ? SBI32(i2s_port_data, pinlo) : CBI32(i2s_port_data, pinlo); // set pin level
|
||||
}
|
||||
else
|
||||
pindata.pwm_duty_ticks = duty; // PWM duty count = # of 4µs ticks per full PWM cycle
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
const int8_t cid = get_pwm_channel(pin, PWM_FREQUENCY, PWM_RESOLUTION);
|
||||
if (cid >= 0) {
|
||||
uint32_t duty = map(invert ? v_size - v : v, 0, v_size, 0, _BV(PWM_RESOLUTION)-1);
|
||||
const uint32_t duty = map(invert ? v_size - v : v, 0, v_size, 0, _BV(PWM_RESOLUTION)-1);
|
||||
ledcWrite(cid, duty);
|
||||
}
|
||||
}
|
||||
|
||||
int8_t MarlinHAL::set_pwm_frequency(const pin_t pin, const uint32_t f_desired) {
|
||||
#if ENABLED(I2S_STEPPER_STREAM)
|
||||
if (pin > 127) {
|
||||
pwm_pin_data[pin & 0x7F].pwm_cycle_ticks = 1000000UL / f_desired / 4; // # of 4µs ticks per full PWM cycle
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
const int8_t cid = channel_for_pin(pin);
|
||||
if (cid >= 0) {
|
||||
if (f_desired == ledcReadFreq(cid)) return cid; // no freq change
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
#include "../shared/HAL_SPI.h"
|
||||
|
||||
#include "fastio.h"
|
||||
#include "watchdog.h"
|
||||
#include "i2s.h"
|
||||
|
||||
#if ENABLED(WIFISUPPORT)
|
||||
@@ -61,14 +60,17 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define CRITICAL_SECTION_START() portENTER_CRITICAL(&spinlock)
|
||||
#define CRITICAL_SECTION_END() portEXIT_CRITICAL(&spinlock)
|
||||
#define CRITICAL_SECTION_START() portENTER_CRITICAL(&hal.spinlock)
|
||||
#define CRITICAL_SECTION_END() portEXIT_CRITICAL(&hal.spinlock)
|
||||
|
||||
#define HAL_CAN_SET_PWM_FREQ // This HAL supports PWM Frequency adjustment
|
||||
#define PWM_FREQUENCY 1000u // Default PWM frequency when set_pwm_duty() is called without set_pwm_frequency()
|
||||
#define PWM_RESOLUTION 10u // Default PWM bit resolution
|
||||
#define CHANNEL_MAX_NUM 15u // max PWM channel # to allocate (7 to only use low speed, 15 to use low & high)
|
||||
#define MAX_PWM_IOPIN 33u // hardware pwm pins < 34
|
||||
#ifndef MAX_EXPANDER_BITS
|
||||
#define MAX_EXPANDER_BITS 32 // I2S expander bit width (max 32)
|
||||
#endif
|
||||
|
||||
// ------------------------
|
||||
// Types
|
||||
@@ -77,6 +79,12 @@
|
||||
typedef double isr_float_t; // FPU ops are used for single-precision, so use double for ISRs.
|
||||
typedef int16_t pin_t;
|
||||
|
||||
typedef struct pwm_pin {
|
||||
uint32_t pwm_cycle_ticks = 1000000UL / (PWM_FREQUENCY) / 4; // # ticks per pwm cycle
|
||||
uint32_t pwm_tick_count = 0; // current tick count
|
||||
uint32_t pwm_duty_ticks = 0; // # of ticks for current duty cycle
|
||||
} pwm_pin_t;
|
||||
|
||||
class Servo;
|
||||
typedef Servo hal_servo_t;
|
||||
|
||||
@@ -89,7 +97,7 @@ typedef Servo hal_servo_t;
|
||||
//
|
||||
void tone(const pin_t _pin, const unsigned int frequency, const unsigned long duration=0);
|
||||
void noTone(const pin_t _pin);
|
||||
|
||||
int8_t get_pwm_channel(const pin_t pin, const uint32_t freq, const uint16_t res);
|
||||
void analogWrite(const pin_t pin, const uint16_t value, const uint32_t freq=PWM_FREQUENCY, const uint16_t res=8);
|
||||
|
||||
//
|
||||
@@ -172,9 +180,13 @@ public:
|
||||
// Earliest possible init, before setup()
|
||||
MarlinHAL() {}
|
||||
|
||||
static void init() {} // Called early in setup()
|
||||
static void init_board(); // Called less early in setup()
|
||||
static void reboot(); // Restart the firmware
|
||||
// Watchdog
|
||||
static void watchdog_init() IF_DISABLED(USE_WATCHDOG, {});
|
||||
static void watchdog_refresh() IF_DISABLED(USE_WATCHDOG, {});
|
||||
|
||||
static void init() {} // Called early in setup()
|
||||
static void init_board(); // Called less early in setup()
|
||||
static void reboot(); // Restart the firmware
|
||||
|
||||
// Interrupts
|
||||
static portMUX_TYPE spinlock;
|
||||
@@ -194,6 +206,8 @@ public:
|
||||
// Free SRAM
|
||||
static int freeMemory();
|
||||
|
||||
static pwm_pin_t pwm_pin_data[MAX_EXPANDER_BITS];
|
||||
|
||||
//
|
||||
// ADC Methods
|
||||
//
|
||||
|
||||
@@ -139,22 +139,38 @@ static void IRAM_ATTR i2s_intr_handler_default(void *arg) {
|
||||
}
|
||||
|
||||
void stepperTask(void *parameter) {
|
||||
uint32_t remaining = 0;
|
||||
uint32_t nextMainISR = 0;
|
||||
#if ENABLED(LIN_ADVANCE)
|
||||
uint32_t nextAdvanceISR = Stepper::LA_ADV_NEVER;
|
||||
#endif
|
||||
|
||||
while (1) {
|
||||
for (;;) {
|
||||
xQueueReceive(dma.queue, &dma.current, portMAX_DELAY);
|
||||
dma.rw_pos = 0;
|
||||
|
||||
while (dma.rw_pos < DMA_SAMPLE_COUNT) {
|
||||
// Fill with the port data post pulse_phase until the next step
|
||||
if (remaining) {
|
||||
i2s_push_sample();
|
||||
remaining--;
|
||||
}
|
||||
else {
|
||||
if (!nextMainISR) {
|
||||
Stepper::pulse_phase_isr();
|
||||
remaining = Stepper::block_phase_isr();
|
||||
nextMainISR = Stepper::block_phase_isr();
|
||||
}
|
||||
#if ENABLED(LIN_ADVANCE)
|
||||
else if (!nextAdvanceISR) {
|
||||
Stepper::advance_isr();
|
||||
nextAdvanceISR = Stepper::la_interval;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
i2s_push_sample();
|
||||
|
||||
nextMainISR--;
|
||||
|
||||
#if ENABLED(LIN_ADVANCE)
|
||||
if (nextAdvanceISR == Stepper::LA_ADV_NEVER)
|
||||
nextAdvanceISR = Stepper::la_interval;
|
||||
|
||||
if (nextAdvanceISR && nextAdvanceISR != Stepper::LA_ADV_NEVER)
|
||||
nextAdvanceISR--;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -337,6 +353,26 @@ uint8_t i2s_state(uint8_t pin) {
|
||||
}
|
||||
|
||||
void i2s_push_sample() {
|
||||
// Every 4µs (when space in DMA buffer) toggle each expander PWM output using
|
||||
// the current duty cycle/frequency so they sync with any steps (once
|
||||
// through the DMA/FIFO buffers). PWM signal inversion handled by other functions
|
||||
LOOP_L_N(p, MAX_EXPANDER_BITS) {
|
||||
if (hal.pwm_pin_data[p].pwm_duty_ticks > 0) { // pin has active pwm?
|
||||
if (hal.pwm_pin_data[p].pwm_tick_count == 0) {
|
||||
if (TEST32(i2s_port_data, p)) { // hi->lo
|
||||
CBI32(i2s_port_data, p);
|
||||
hal.pwm_pin_data[p].pwm_tick_count = hal.pwm_pin_data[p].pwm_cycle_ticks - hal.pwm_pin_data[p].pwm_duty_ticks;
|
||||
}
|
||||
else { // lo->hi
|
||||
SBI32(i2s_port_data, p);
|
||||
hal.pwm_pin_data[p].pwm_tick_count = hal.pwm_pin_data[p].pwm_duty_ticks;
|
||||
}
|
||||
}
|
||||
else
|
||||
hal.pwm_pin_data[p].pwm_tick_count--;
|
||||
}
|
||||
}
|
||||
|
||||
dma.current[dma.rw_pos++] = i2s_port_data;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,3 +20,10 @@
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
//
|
||||
// Board-specific options need to be defined before HAL.h
|
||||
//
|
||||
#if MB(MKS_TINYBEE)
|
||||
#define MAX_EXPANDER_BITS 24 // TinyBee has 3 x HC595
|
||||
#endif
|
||||
|
||||
@@ -45,6 +45,14 @@
|
||||
#error "FAST_PWM_FAN is not available on TinyBee."
|
||||
#endif
|
||||
|
||||
#if BOTH(I2S_STEPPER_STREAM, BABYSTEPPING) && DISABLED(INTEGRATED_BABYSTEPPING)
|
||||
#error "BABYSTEPPING on I2S stream requires INTEGRATED_BABYSTEPPING."
|
||||
#endif
|
||||
|
||||
#if USING_PULLDOWNS
|
||||
#error "PULLDOWN pin mode is not available on ESP32 boards."
|
||||
#endif
|
||||
|
||||
#if BOTH(I2S_STEPPER_STREAM, LIN_ADVANCE) && DISABLED(EXPERIMENTAL_I2S_LA)
|
||||
#error "I2S stream is currently incompatible with LIN_ADVANCE."
|
||||
#endif
|
||||
|
||||
@@ -23,24 +23,24 @@
|
||||
*/
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
|
||||
#include "../../inc/MarlinConfigPre.h"
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#if ENABLED(FYSETC_MINI_12864_2_1)
|
||||
#if EITHER(MKS_MINI_12864, FYSETC_MINI_12864_2_1)
|
||||
|
||||
#include <U8glib-HAL.h>
|
||||
#include "Arduino.h"
|
||||
#include "../shared/HAL_SPI.h"
|
||||
#include "HAL.h"
|
||||
#include "SPI.h"
|
||||
|
||||
#if ENABLED(SDSUPPORT)
|
||||
#include "../../sd/cardreader.h"
|
||||
#if ENABLED(ESP3D_WIFISUPPORT)
|
||||
#include "sd_ESP32.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static SPISettings spiConfig;
|
||||
|
||||
#define MDOGLCD_MOSI 23
|
||||
#define MDOGLCD_SCK 18
|
||||
#define MLCD_RESET_PIN 0
|
||||
#define MLCD_PINS_DC 4
|
||||
#define MDOGLCD_CS 21
|
||||
#define MDOGLCD_A0 4
|
||||
|
||||
#ifndef LCD_SPI_SPEED
|
||||
#ifdef SD_SPI_SPEED
|
||||
@@ -52,6 +52,11 @@ static SPISettings spiConfig;
|
||||
|
||||
uint8_t u8g_eps_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
|
||||
static uint8_t msgInitCount = 2; // Ignore all messages until 2nd U8G_COM_MSG_INIT
|
||||
|
||||
#if ENABLED(PAUSE_LCD_FOR_BUSY_SD)
|
||||
if (card.flag.saving || card.flag.logging || TERN0(ESP3D_WIFISUPPORT, sd_busy_lock == true)) return 0;
|
||||
#endif
|
||||
|
||||
if (msgInitCount) {
|
||||
if (msg == U8G_COM_MSG_INIT) msgInitCount--;
|
||||
if (msgInitCount) return -1;
|
||||
@@ -61,24 +66,24 @@ uint8_t u8g_eps_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_pt
|
||||
case U8G_COM_MSG_STOP: break;
|
||||
|
||||
case U8G_COM_MSG_INIT:
|
||||
OUT_WRITE(MDOGLCD_CS, HIGH);
|
||||
OUT_WRITE(MDOGLCD_A0, HIGH);
|
||||
OUT_WRITE(MLCD_RESET_PIN, HIGH);
|
||||
OUT_WRITE(DOGLCD_CS, HIGH);
|
||||
OUT_WRITE(DOGLCD_A0, HIGH);
|
||||
OUT_WRITE(LCD_RESET_PIN, HIGH);
|
||||
u8g_Delay(5);
|
||||
spiBegin();
|
||||
spiInit(LCD_SPI_SPEED);
|
||||
break;
|
||||
|
||||
case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */
|
||||
WRITE(MDOGLCD_A0, arg_val ? HIGH : LOW);
|
||||
WRITE(DOGLCD_A0, arg_val ? HIGH : LOW);
|
||||
break;
|
||||
|
||||
case U8G_COM_MSG_CHIP_SELECT: /* arg_val == 0 means HIGH level of U8G_PI_CS */
|
||||
WRITE(MDOGLCD_CS, arg_val ? LOW : HIGH);
|
||||
WRITE(DOGLCD_CS, arg_val ? LOW : HIGH);
|
||||
break;
|
||||
|
||||
case U8G_COM_MSG_RESET:
|
||||
WRITE(MLCD_RESET_PIN, arg_val);
|
||||
WRITE(LCD_RESET_PIN, arg_val);
|
||||
break;
|
||||
|
||||
case U8G_COM_MSG_WRITE_BYTE:
|
||||
@@ -96,5 +101,6 @@ uint8_t u8g_eps_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_pt
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif // FYSETC_MINI_12864_2_1
|
||||
#endif // EITHER(MKS_MINI_12864, FYSETC_MINI_12864_2_1)
|
||||
|
||||
#endif // ARDUINO_ARCH_ESP32
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#endif
|
||||
|
||||
#include HAL_PATH(.,HAL.h)
|
||||
extern MarlinHAL hal;
|
||||
|
||||
#define HAL_ADC_RANGE _BV(HAL_ADC_RESOLUTION)
|
||||
|
||||
@@ -44,7 +45,3 @@
|
||||
#ifndef PGMSTR
|
||||
#define PGMSTR(NAM,STR) const char NAM[] = STR
|
||||
#endif
|
||||
|
||||
inline void watchdog_refresh() {
|
||||
TERN_(USE_WATCHDOG, HAL_watchdog_refresh());
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../../inc/MarlinConfigPre.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <stdint.h>
|
||||
#include <stdarg.h>
|
||||
@@ -29,12 +31,10 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include "hardware/Clock.h"
|
||||
|
||||
#include "../shared/Marduino.h"
|
||||
#include "../shared/math_32bit.h"
|
||||
#include "../shared/HAL_SPI.h"
|
||||
#include "fastio.h"
|
||||
#include "watchdog.h"
|
||||
#include "serial.h"
|
||||
|
||||
// ------------------------
|
||||
@@ -106,9 +106,13 @@ public:
|
||||
// Earliest possible init, before setup()
|
||||
MarlinHAL() {}
|
||||
|
||||
// Watchdog
|
||||
static void watchdog_init() {}
|
||||
static void watchdog_refresh() {}
|
||||
|
||||
static void init() {} // Called early in setup()
|
||||
static void init_board() {} // Called less early in setup()
|
||||
static void reboot(); // Reset the application state and GPIO
|
||||
static void reboot(); // Reset the application state and GPIO
|
||||
|
||||
// Interrupts
|
||||
static bool isr_state() { return true; }
|
||||
|
||||
@@ -69,12 +69,12 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui
|
||||
std::size_t bytes_written = 0;
|
||||
|
||||
for (std::size_t i = 0; i < size; i++) {
|
||||
buffer[pos+i] = value[i];
|
||||
bytes_written ++;
|
||||
buffer[pos + i] = value[i];
|
||||
bytes_written++;
|
||||
}
|
||||
|
||||
crc16(crc, value, size);
|
||||
pos = pos + size;
|
||||
pos += size;
|
||||
return (bytes_written != size); // return true for any error
|
||||
}
|
||||
|
||||
@@ -82,21 +82,21 @@ bool PersistentStore::read_data(int &pos, uint8_t *value, const size_t size, uin
|
||||
std::size_t bytes_read = 0;
|
||||
if (writing) {
|
||||
for (std::size_t i = 0; i < size; i++) {
|
||||
value[i] = buffer[pos+i];
|
||||
bytes_read ++;
|
||||
value[i] = buffer[pos + i];
|
||||
bytes_read++;
|
||||
}
|
||||
crc16(crc, value, size);
|
||||
}
|
||||
else {
|
||||
uint8_t temp[size];
|
||||
for (std::size_t i = 0; i < size; i++) {
|
||||
temp[i] = buffer[pos+i];
|
||||
bytes_read ++;
|
||||
temp[i] = buffer[pos + i];
|
||||
bytes_read++;
|
||||
}
|
||||
crc16(crc, temp, size);
|
||||
}
|
||||
|
||||
pos = pos + size;
|
||||
pos += size;
|
||||
return bytes_read != size; // return true for any error
|
||||
}
|
||||
|
||||
|
||||
@@ -26,8 +26,8 @@
|
||||
struct LowpassFilter {
|
||||
uint64_t data_delay = 0;
|
||||
uint16_t update(uint16_t value) {
|
||||
data_delay = data_delay - (data_delay >> 6) + value;
|
||||
return (uint16_t)(data_delay >> 6);
|
||||
data_delay += value - (data_delay >> 6);
|
||||
return uint16_t(data_delay >> 6);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -25,10 +25,6 @@
|
||||
#include "../shared/Delay.h"
|
||||
#include "../../../gcode/parser.h"
|
||||
|
||||
#if ENABLED(USE_WATCHDOG)
|
||||
#include "watchdog.h"
|
||||
#endif
|
||||
|
||||
DefaultSerial1 USBSerial(false, UsbSerial);
|
||||
|
||||
uint32_t MarlinHAL::adc_result = 0;
|
||||
@@ -61,9 +57,7 @@ uint8_t MarlinHAL::get_reset_source() {
|
||||
return RST_POWER_ON;
|
||||
}
|
||||
|
||||
void MarlinHAL::clear_reset_source() {
|
||||
TERN_(USE_WATCHDOG, watchdog_clear_timeout_flag());
|
||||
}
|
||||
void MarlinHAL::clear_reset_source() { watchdog_clear_timeout_flag(); }
|
||||
|
||||
void flashFirmware(const int16_t) {
|
||||
delay(500); // Give OS time to disconnect
|
||||
@@ -72,6 +66,52 @@ void flashFirmware(const int16_t) {
|
||||
hal.reboot();
|
||||
}
|
||||
|
||||
#if ENABLED(USE_WATCHDOG)
|
||||
|
||||
#include <lpc17xx_wdt.h>
|
||||
|
||||
#define WDT_TIMEOUT_US TERN(WATCHDOG_DURATION_8S, 8000000, 4000000) // 4 or 8 second timeout
|
||||
|
||||
void MarlinHAL::watchdog_init() {
|
||||
#if ENABLED(WATCHDOG_RESET_MANUAL)
|
||||
// We enable the watchdog timer, but only for the interrupt.
|
||||
|
||||
// Configure WDT to only trigger an interrupt
|
||||
// Disable WDT interrupt (just in case, to avoid triggering it!)
|
||||
NVIC_DisableIRQ(WDT_IRQn);
|
||||
|
||||
// We NEED memory barriers to ensure Interrupts are actually disabled!
|
||||
// ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
|
||||
__DSB();
|
||||
__ISB();
|
||||
|
||||
// Configure WDT to only trigger an interrupt
|
||||
// Initialize WDT with the given parameters
|
||||
WDT_Init(WDT_CLKSRC_IRC, WDT_MODE_INT_ONLY);
|
||||
|
||||
// Configure and enable WDT interrupt.
|
||||
NVIC_ClearPendingIRQ(WDT_IRQn);
|
||||
NVIC_SetPriority(WDT_IRQn, 0); // Use highest priority, so we detect all kinds of lockups
|
||||
NVIC_EnableIRQ(WDT_IRQn);
|
||||
#else
|
||||
WDT_Init(WDT_CLKSRC_IRC, WDT_MODE_RESET);
|
||||
#endif
|
||||
WDT_Start(WDT_TIMEOUT_US);
|
||||
}
|
||||
|
||||
void MarlinHAL::watchdog_refresh() {
|
||||
WDT_Feed();
|
||||
#if DISABLED(PINS_DEBUGGING) && PIN_EXISTS(LED)
|
||||
TOGGLE(LED_PIN); // heartbeat indicator
|
||||
#endif
|
||||
}
|
||||
|
||||
// Timeout state
|
||||
bool MarlinHAL::watchdog_timed_out() { return TEST(WDT_ReadTimeOutFlag(), 0); }
|
||||
void MarlinHAL::watchdog_clear_timeout_flag() { WDT_ClrTimeOutFlag(); }
|
||||
|
||||
#endif // USE_WATCHDOG
|
||||
|
||||
// For M42/M43, scan command line for pin code
|
||||
// return index into pin map array if found and the pin is valid.
|
||||
// return dval if not found or not a valid pin.
|
||||
|
||||
@@ -38,7 +38,6 @@ extern "C" volatile uint32_t _millis;
|
||||
#include "../shared/math_32bit.h"
|
||||
#include "../shared/HAL_SPI.h"
|
||||
#include "fastio.h"
|
||||
#include "watchdog.h"
|
||||
#include "MarlinSerial.h"
|
||||
|
||||
#include <adc.h>
|
||||
@@ -177,7 +176,7 @@ void flashFirmware(const int16_t);
|
||||
#define CPU_ST7920_DELAY_3 750
|
||||
|
||||
// ------------------------
|
||||
// Class Utilities
|
||||
// Free Memory Accessor
|
||||
// ------------------------
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
@@ -199,9 +198,9 @@ public:
|
||||
// Earliest possible init, before setup()
|
||||
MarlinHAL() {}
|
||||
|
||||
static void init(); // Called early in setup()
|
||||
static void init(); // Called early in setup()
|
||||
static void init_board() {} // Called less early in setup()
|
||||
static void reboot(); // Restart the firmware from 0x0
|
||||
static void reboot(); // Restart the firmware from 0x0
|
||||
|
||||
// Interrupts
|
||||
static bool isr_state() { return !__get_PRIMASK(); }
|
||||
@@ -210,6 +209,12 @@ public:
|
||||
|
||||
static void delay_ms(const int ms) { _delay_ms(ms); }
|
||||
|
||||
// Watchdog
|
||||
static void watchdog_init() IF_DISABLED(USE_WATCHDOG, {});
|
||||
static void watchdog_refresh() IF_DISABLED(USE_WATCHDOG, {});
|
||||
static bool watchdog_timed_out() IF_DISABLED(USE_WATCHDOG, { return false; });
|
||||
static void watchdog_clear_timeout_flag() IF_DISABLED(USE_WATCHDOG, {});
|
||||
|
||||
// Tasks, called from idle()
|
||||
static void idletask();
|
||||
|
||||
|
||||
@@ -318,8 +318,16 @@ void SPIClass::dmaSend(void *buf, uint16_t length, bool minc) {
|
||||
// Enable DMA
|
||||
GPDMA_ChannelCmd(0, ENABLE);
|
||||
|
||||
/*
|
||||
* Observed behaviour on normal data transfer completion (SKR 1.3 board / LPC1768 MCU)
|
||||
* GPDMA_STAT_INTTC flag is SET
|
||||
* GPDMA_STAT_INTERR flag is NOT SET
|
||||
* GPDMA_STAT_RAWINTTC flag is NOT SET
|
||||
* GPDMA_STAT_RAWINTERR flag is SET
|
||||
*/
|
||||
|
||||
// Wait for data transfer
|
||||
while (!GPDMA_IntGetStatus(GPDMA_STAT_RAWINTTC, 0) && !GPDMA_IntGetStatus(GPDMA_STAT_RAWINTERR, 0)) { }
|
||||
while (!GPDMA_IntGetStatus(GPDMA_STAT_INTTC, 0) && !GPDMA_IntGetStatus(GPDMA_STAT_INTERR, 0)) {}
|
||||
|
||||
// Clear err and int
|
||||
GPDMA_ClearIntPending (GPDMA_STATCLR_INTTC, 0);
|
||||
@@ -333,6 +341,43 @@ void SPIClass::dmaSend(void *buf, uint16_t length, bool minc) {
|
||||
SSP_DMACmd(_currentSetting->spi_d, SSP_DMA_TX, DISABLE);
|
||||
}
|
||||
|
||||
void SPIClass::dmaSendAsync(void *buf, uint16_t length, bool minc) {
|
||||
//TODO: LPC dma can only write 0xFFF bytes at once.
|
||||
GPDMA_Channel_CFG_Type GPDMACfg;
|
||||
|
||||
/* Configure GPDMA channel 0 -------------------------------------------------------------*/
|
||||
/* DMA Channel 0 */
|
||||
GPDMACfg.ChannelNum = 0;
|
||||
// Source memory
|
||||
GPDMACfg.SrcMemAddr = (uint32_t)buf;
|
||||
// Destination memory - Not used
|
||||
GPDMACfg.DstMemAddr = 0;
|
||||
// Transfer size
|
||||
GPDMACfg.TransferSize = length;
|
||||
// Transfer width
|
||||
GPDMACfg.TransferWidth = (_currentSetting->dataSize == DATA_SIZE_16BIT) ? GPDMA_WIDTH_HALFWORD : GPDMA_WIDTH_BYTE;
|
||||
// Transfer type
|
||||
GPDMACfg.TransferType = GPDMA_TRANSFERTYPE_M2P;
|
||||
// Source connection - unused
|
||||
GPDMACfg.SrcConn = 0;
|
||||
// Destination connection
|
||||
GPDMACfg.DstConn = (_currentSetting->spi_d == LPC_SSP0) ? GPDMA_CONN_SSP0_Tx : GPDMA_CONN_SSP1_Tx;
|
||||
|
||||
GPDMACfg.DMALLI = 0;
|
||||
|
||||
// Enable dma on SPI
|
||||
SSP_DMACmd(_currentSetting->spi_d, SSP_DMA_TX, ENABLE);
|
||||
|
||||
// Only increase memory if minc is true
|
||||
GPDMACfg.MemoryIncrease = (minc ? GPDMA_DMACCxControl_SI : 0);
|
||||
|
||||
// Setup channel with given parameter
|
||||
GPDMA_Setup(&GPDMACfg);
|
||||
|
||||
// Enable DMA
|
||||
GPDMA_ChannelCmd(0, ENABLE);
|
||||
}
|
||||
|
||||
uint16_t SPIClass::read() {
|
||||
return SSP_ReceiveData(_currentSetting->spi_d);
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
#if ENABLED(POSTMORTEM_DEBUGGING)
|
||||
|
||||
#include "../shared/HAL_MinSerial.h"
|
||||
#include "../shared/MinSerial.h"
|
||||
#include <debug_frmwrk.h>
|
||||
|
||||
static void TX(char c) { _DBC(c); }
|
||||
@@ -34,7 +34,7 @@
|
||||
#include "../shared/eeprom_api.h"
|
||||
|
||||
#ifndef MARLIN_EEPROM_SIZE
|
||||
#define MARLIN_EEPROM_SIZE 0x8000 // 32KB
|
||||
#define MARLIN_EEPROM_SIZE 0x8000 // 32K
|
||||
#endif
|
||||
size_t PersistentStore::capacity() { return MARLIN_EEPROM_SIZE; }
|
||||
|
||||
|
||||
@@ -29,6 +29,6 @@
|
||||
|
||||
// LPC1768 boards seem to lose steps when saving to EEPROM during print (issue #20785)
|
||||
// TODO: Which other boards are incompatible?
|
||||
#if defined(MCU_LPC1768) && PRINTCOUNTER_SAVE_INTERVAL > 0
|
||||
#if defined(MCU_LPC1768) && ENABLED(FLASH_EEPROM_EMULATION) && PRINTCOUNTER_SAVE_INTERVAL > 0
|
||||
#define PRINTCOUNTER_SYNC 1
|
||||
#endif
|
||||
|
||||
@@ -155,6 +155,7 @@ public:
|
||||
void read(uint8_t *buf, uint32_t len);
|
||||
|
||||
void dmaSend(void *buf, uint16_t length, bool minc);
|
||||
void dmaSendAsync(void *buf, uint16_t length, bool minc);
|
||||
|
||||
/**
|
||||
* @brief Sets the number of the SPI peripheral to be used by
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
#include "tft_spi.h"
|
||||
|
||||
SPIClass TFT_SPI::SPIx(1);
|
||||
SPIClass TFT_SPI::SPIx(TFT_SPI_DEVICE);
|
||||
|
||||
void TFT_SPI::Init() {
|
||||
#if PIN_EXISTS(TFT_RESET)
|
||||
@@ -38,40 +38,10 @@ void TFT_SPI::Init() {
|
||||
OUT_WRITE(TFT_BACKLIGHT_PIN, HIGH);
|
||||
#endif
|
||||
|
||||
SET_OUTPUT(TFT_DC_PIN);
|
||||
SET_OUTPUT(TFT_CS_PIN);
|
||||
WRITE(TFT_DC_PIN, HIGH);
|
||||
WRITE(TFT_CS_PIN, HIGH);
|
||||
OUT_WRITE(TFT_DC_PIN, HIGH);
|
||||
OUT_WRITE(TFT_CS_PIN, HIGH);
|
||||
|
||||
/**
|
||||
* STM32F1 APB2 = 72MHz, APB1 = 36MHz, max SPI speed of this MCU if 18Mhz
|
||||
* STM32F1 has 3 SPI ports, SPI1 in APB2, SPI2/SPI3 in APB1
|
||||
* so the minimum prescale of SPI1 is DIV4, SPI2/SPI3 is DIV2
|
||||
*/
|
||||
#if 0
|
||||
#if SPI_DEVICE == 1
|
||||
#define SPI_CLOCK_MAX SPI_CLOCK_DIV4
|
||||
#else
|
||||
#define SPI_CLOCK_MAX SPI_CLOCK_DIV2
|
||||
#endif
|
||||
uint8_t clock;
|
||||
uint8_t spiRate = SPI_FULL_SPEED;
|
||||
switch (spiRate) {
|
||||
case SPI_FULL_SPEED: clock = SPI_CLOCK_MAX ; break;
|
||||
case SPI_HALF_SPEED: clock = SPI_CLOCK_DIV4 ; break;
|
||||
case SPI_QUARTER_SPEED: clock = SPI_CLOCK_DIV8 ; break;
|
||||
case SPI_EIGHTH_SPEED: clock = SPI_CLOCK_DIV16; break;
|
||||
case SPI_SPEED_5: clock = SPI_CLOCK_DIV32; break;
|
||||
case SPI_SPEED_6: clock = SPI_CLOCK_DIV64; break;
|
||||
default: clock = SPI_CLOCK_DIV2; // Default from the SPI library
|
||||
}
|
||||
#endif
|
||||
|
||||
#if TFT_MISO_PIN == BOARD_SPI1_MISO_PIN
|
||||
SPIx.setModule(1);
|
||||
#elif TFT_MISO_PIN == BOARD_SPI2_MISO_PIN
|
||||
SPIx.setModule(2);
|
||||
#endif
|
||||
SPIx.setModule(TFT_SPI_DEVICE);
|
||||
SPIx.setClock(SPI_CLOCK_MAX_TFT);
|
||||
SPIx.setBitOrder(MSBFIRST);
|
||||
SPIx.setDataMode(SPI_MODE0);
|
||||
@@ -114,17 +84,62 @@ uint32_t TFT_SPI::ReadID(uint16_t Reg) {
|
||||
return data >> 7;
|
||||
}
|
||||
|
||||
bool TFT_SPI::isBusy() { return false; }
|
||||
bool TFT_SPI::isBusy() {
|
||||
#define __IS_DMA_CONFIGURED(__HANDLE__) ((__HANDLE__)->DMACCSrcAddr != 0)
|
||||
|
||||
void TFT_SPI::Abort() { DataTransferEnd(); }
|
||||
// DMA Channel 0 is hardcoded in dmaSendAsync() and dmaSend()
|
||||
if (!__IS_DMA_CONFIGURED(LPC_GPDMACH0)) return false;
|
||||
|
||||
void TFT_SPI::Transmit(uint16_t Data) { SPIx.transfer(Data); }
|
||||
if (GPDMA_IntGetStatus(GPDMA_STAT_INTERR, 0)) {
|
||||
// You should not be here - DMA transfer error flag is set
|
||||
// Abort DMA transfer and release SPI
|
||||
}
|
||||
else {
|
||||
// Check if DMA transfer completed flag is set
|
||||
if (!GPDMA_IntGetStatus(GPDMA_STAT_INTTC, 0)) return true;
|
||||
// Check if SPI TX butter is empty and SPI is idle
|
||||
if ((SSP_GetStatus(LPC_SSPx, SSP_STAT_TXFIFO_EMPTY) == RESET) || (SSP_GetStatus(LPC_SSPx, SSP_STAT_BUSY) == SET)) return true;
|
||||
}
|
||||
|
||||
Abort();
|
||||
return false;
|
||||
}
|
||||
|
||||
void TFT_SPI::Abort() {
|
||||
// DMA Channel 0 is hardcoded in dmaSendAsync() and dmaSend()
|
||||
|
||||
// Disable DMA
|
||||
GPDMA_ChannelCmd(0, DISABLE);
|
||||
|
||||
// Clear ERR and TC
|
||||
GPDMA_ClearIntPending(GPDMA_STATCLR_INTTC, 0);
|
||||
GPDMA_ClearIntPending(GPDMA_STATCLR_INTERR, 0);
|
||||
|
||||
// Disable DMA on SPI
|
||||
SSP_DMACmd(LPC_SSPx, SSP_DMA_TX, DISABLE);
|
||||
|
||||
// Deconfigure DMA Channel 0
|
||||
LPC_GPDMACH0->DMACCControl = 0U;
|
||||
LPC_GPDMACH0->DMACCConfig = 0U;
|
||||
LPC_GPDMACH0->DMACCSrcAddr = 0U;
|
||||
LPC_GPDMACH0->DMACCDestAddr = 0U;
|
||||
|
||||
void TFT_SPI::TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count) {
|
||||
DataTransferBegin(DATASIZE_16BIT);
|
||||
WRITE(TFT_DC_PIN, HIGH);
|
||||
SPIx.dmaSend(Data, Count, MemoryIncrease);
|
||||
DataTransferEnd();
|
||||
}
|
||||
|
||||
void TFT_SPI::Transmit(uint16_t Data) { SPIx.transfer(Data); }
|
||||
|
||||
void TFT_SPI::Transmit(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count) {
|
||||
DataTransferBegin(DATASIZE_16BIT);
|
||||
SPIx.dmaSend(Data, Count, MemoryIncrease);
|
||||
Abort();
|
||||
}
|
||||
|
||||
void TFT_SPI::TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count) {
|
||||
DataTransferBegin(DATASIZE_16BIT);
|
||||
SPIx.dmaSendAsync(Data, Count, MemoryIncrease);
|
||||
|
||||
TERN_(TFT_SHARED_SPI, while (isBusy()));
|
||||
}
|
||||
|
||||
#endif // HAS_SPI_TFT
|
||||
|
||||
@@ -27,6 +27,18 @@
|
||||
#include <lpc17xx_ssp.h>
|
||||
// #include <lpc17xx_gpdma.h>
|
||||
|
||||
#define IS_SPI(N) (BOARD_NR_SPI >= N && (TFT_SCK_PIN == BOARD_SPI##N##_SCK_PIN) && (TFT_MOSI_PIN == BOARD_SPI##N##_MOSI_PIN) && (TFT_MISO_PIN == BOARD_SPI##N##_MISO_PIN))
|
||||
#if IS_SPI(1)
|
||||
#define TFT_SPI_DEVICE 1
|
||||
#define LPC_SSPx LPC_SSP0
|
||||
#elif IS_SPI(2)
|
||||
#define TFT_SPI_DEVICE 2
|
||||
#define LPC_SSPx LPC_SSP1
|
||||
#else
|
||||
#error "Invalid TFT SPI configuration."
|
||||
#endif
|
||||
#undef IS_SPI
|
||||
|
||||
#ifndef LCD_READ_ID
|
||||
#define LCD_READ_ID 0x04 // Read display identification information (0xD3 on ILI9341)
|
||||
#endif
|
||||
@@ -34,17 +46,19 @@
|
||||
#define LCD_READ_ID4 0xD3 // Read display identification information (0xD3 on ILI9341)
|
||||
#endif
|
||||
|
||||
#define DATASIZE_8BIT SSP_DATABIT_8
|
||||
#define DATASIZE_16BIT SSP_DATABIT_16
|
||||
#define TFT_IO_DRIVER TFT_SPI
|
||||
#define DATASIZE_8BIT SSP_DATABIT_8
|
||||
#define DATASIZE_16BIT SSP_DATABIT_16
|
||||
#define TFT_IO_DRIVER TFT_SPI
|
||||
#define DMA_MAX_SIZE 0xFFF
|
||||
|
||||
#define DMA_MINC_ENABLE 1
|
||||
#define DMA_MINC_DISABLE 0
|
||||
#define DMA_MINC_ENABLE 1
|
||||
#define DMA_MINC_DISABLE 0
|
||||
|
||||
class TFT_SPI {
|
||||
private:
|
||||
static uint32_t ReadID(uint16_t Reg);
|
||||
static void Transmit(uint16_t Data);
|
||||
static void Transmit(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count);
|
||||
static void TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count);
|
||||
|
||||
public:
|
||||
@@ -56,22 +70,20 @@ public:
|
||||
static void Abort();
|
||||
|
||||
static void DataTransferBegin(uint16_t DataWidth = DATASIZE_16BIT);
|
||||
static void DataTransferEnd() { OUT_WRITE(TFT_CS_PIN, HIGH); SPIx.end(); };
|
||||
static void DataTransferEnd() { WRITE(TFT_CS_PIN, HIGH); SSP_Cmd(LPC_SSPx, DISABLE); };
|
||||
static void DataTransferAbort();
|
||||
|
||||
static void WriteData(uint16_t Data) { Transmit(Data); }
|
||||
static void WriteReg(uint16_t Reg) { OUT_WRITE(TFT_A0_PIN, LOW); Transmit(Reg); OUT_WRITE(TFT_A0_PIN, HIGH); }
|
||||
static void WriteReg(uint16_t Reg) { WRITE(TFT_DC_PIN, LOW); Transmit(Reg); WRITE(TFT_DC_PIN, HIGH); }
|
||||
|
||||
static void WriteSequence(uint16_t *Data, uint16_t Count) { TransmitDMA(DMA_MINC_ENABLE, Data, Count); }
|
||||
// static void WriteMultiple(uint16_t Color, uint16_t Count) { static uint16_t Data; Data = Color; TransmitDMA(DMA_MINC_DISABLE, &Data, Count); }
|
||||
static void WriteSequence_DMA(uint16_t *Data, uint16_t Count) { TransmitDMA(DMA_MINC_ENABLE, Data, Count); }
|
||||
static void WriteMultiple_DMA(uint16_t Color, uint16_t Count) { static uint16_t Data; Data = Color; TransmitDMA(DMA_MINC_DISABLE, &Data, Count); }
|
||||
|
||||
static void WriteSequence(uint16_t *Data, uint16_t Count) { Transmit(DMA_MINC_ENABLE, Data, Count); }
|
||||
static void WriteMultiple(uint16_t Color, uint32_t Count) {
|
||||
static uint16_t Data; Data = Color;
|
||||
//LPC dma can only write 0xFFF bytes at once.
|
||||
#define MAX_DMA_SIZE (0xFFF - 1)
|
||||
while (Count > 0) {
|
||||
TransmitDMA(DMA_MINC_DISABLE, &Data, Count > MAX_DMA_SIZE ? MAX_DMA_SIZE : Count);
|
||||
Count = Count > MAX_DMA_SIZE ? Count - MAX_DMA_SIZE : 0;
|
||||
Transmit(DMA_MINC_DISABLE, &Color, Count > DMA_MAX_SIZE ? DMA_MAX_SIZE : Count);
|
||||
Count = Count > DMA_MAX_SIZE ? Count - DMA_MAX_SIZE : 0;
|
||||
}
|
||||
#undef MAX_DMA_SIZE
|
||||
}
|
||||
};
|
||||
|
||||
@@ -44,9 +44,11 @@ uint16_t delta(uint16_t a, uint16_t b) { return a > b ? a - b : b - a; }
|
||||
#endif
|
||||
|
||||
void XPT2046::Init() {
|
||||
SET_INPUT(TOUCH_MISO_PIN);
|
||||
SET_OUTPUT(TOUCH_MOSI_PIN);
|
||||
SET_OUTPUT(TOUCH_SCK_PIN);
|
||||
#if DISABLED(TOUCH_BUTTONS_HW_SPI)
|
||||
SET_INPUT(TOUCH_MISO_PIN);
|
||||
SET_OUTPUT(TOUCH_MOSI_PIN);
|
||||
SET_OUTPUT(TOUCH_SCK_PIN);
|
||||
#endif
|
||||
OUT_WRITE(TOUCH_CS_PIN, HIGH);
|
||||
|
||||
#if PIN_EXISTS(TOUCH_INT)
|
||||
|
||||
@@ -9,119 +9,127 @@ from __future__ import print_function
|
||||
import pioutil
|
||||
if pioutil.is_pio_build():
|
||||
|
||||
target_filename = "FIRMWARE.CUR"
|
||||
target_drive = "REARM"
|
||||
target_filename = "FIRMWARE.CUR"
|
||||
target_drive = "REARM"
|
||||
|
||||
import os,getpass,platform
|
||||
import platform
|
||||
|
||||
current_OS = platform.system()
|
||||
Import("env")
|
||||
current_OS = platform.system()
|
||||
Import("env")
|
||||
|
||||
def print_error(e):
|
||||
print('\nUnable to find destination disk (%s)\n' \
|
||||
'Please select it in platformio.ini using the upload_port keyword ' \
|
||||
'(https://docs.platformio.org/en/latest/projectconf/section_env_upload.html) ' \
|
||||
'or copy the firmware (.pio/build/%s/firmware.bin) manually to the appropriate disk\n' \
|
||||
%(e, env.get('PIOENV')))
|
||||
def print_error(e):
|
||||
print('\nUnable to find destination disk (%s)\n' \
|
||||
'Please select it in platformio.ini using the upload_port keyword ' \
|
||||
'(https://docs.platformio.org/en/latest/projectconf/section_env_upload.html) ' \
|
||||
'or copy the firmware (.pio/build/%s/firmware.bin) manually to the appropriate disk\n' \
|
||||
%(e, env.get('PIOENV')))
|
||||
|
||||
def before_upload(source, target, env):
|
||||
try:
|
||||
#
|
||||
# Find a disk for upload
|
||||
#
|
||||
upload_disk = 'Disk not found'
|
||||
target_file_found = False
|
||||
target_drive_found = False
|
||||
if current_OS == 'Windows':
|
||||
#
|
||||
# platformio.ini will accept this for a Windows upload port designation: 'upload_port = L:'
|
||||
# Windows - doesn't care about the disk's name, only cares about the drive letter
|
||||
import subprocess,string
|
||||
from ctypes import windll
|
||||
def before_upload(source, target, env):
|
||||
try:
|
||||
from pathlib import Path
|
||||
#
|
||||
# Find a disk for upload
|
||||
#
|
||||
upload_disk = 'Disk not found'
|
||||
target_file_found = False
|
||||
target_drive_found = False
|
||||
if current_OS == 'Windows':
|
||||
#
|
||||
# platformio.ini will accept this for a Windows upload port designation: 'upload_port = L:'
|
||||
# Windows - doesn't care about the disk's name, only cares about the drive letter
|
||||
import subprocess,string
|
||||
from ctypes import windll
|
||||
from pathlib import PureWindowsPath
|
||||
|
||||
# getting list of drives
|
||||
# https://stackoverflow.com/questions/827371/is-there-a-way-to-list-all-the-available-drive-letters-in-python
|
||||
drives = []
|
||||
bitmask = windll.kernel32.GetLogicalDrives()
|
||||
for letter in string.ascii_uppercase:
|
||||
if bitmask & 1:
|
||||
drives.append(letter)
|
||||
bitmask >>= 1
|
||||
# getting list of drives
|
||||
# https://stackoverflow.com/questions/827371/is-there-a-way-to-list-all-the-available-drive-letters-in-python
|
||||
drives = []
|
||||
bitmask = windll.kernel32.GetLogicalDrives()
|
||||
for letter in string.ascii_uppercase:
|
||||
if bitmask & 1:
|
||||
drives.append(letter)
|
||||
bitmask >>= 1
|
||||
|
||||
for drive in drives:
|
||||
final_drive_name = drive + ':\\'
|
||||
# print ('disc check: {}'.format(final_drive_name))
|
||||
try:
|
||||
volume_info = str(subprocess.check_output('cmd /C dir ' + final_drive_name, stderr=subprocess.STDOUT))
|
||||
except Exception as e:
|
||||
print ('error:{}'.format(e))
|
||||
continue
|
||||
else:
|
||||
if target_drive in volume_info and not target_file_found: # set upload if not found target file yet
|
||||
target_drive_found = True
|
||||
upload_disk = final_drive_name
|
||||
if target_filename in volume_info:
|
||||
if not target_file_found:
|
||||
upload_disk = final_drive_name
|
||||
target_file_found = True
|
||||
for drive in drives:
|
||||
final_drive_name = drive + ':'
|
||||
# print ('disc check: {}'.format(final_drive_name))
|
||||
try:
|
||||
volume_info = str(subprocess.check_output('cmd /C dir ' + final_drive_name, stderr=subprocess.STDOUT))
|
||||
except Exception as e:
|
||||
print ('error:{}'.format(e))
|
||||
continue
|
||||
else:
|
||||
if target_drive in volume_info and not target_file_found: # set upload if not found target file yet
|
||||
target_drive_found = True
|
||||
upload_disk = PureWindowsPath(final_drive_name)
|
||||
if target_filename in volume_info:
|
||||
if not target_file_found:
|
||||
upload_disk = PureWindowsPath(final_drive_name)
|
||||
target_file_found = True
|
||||
|
||||
elif current_OS == 'Linux':
|
||||
#
|
||||
# platformio.ini will accept this for a Linux upload port designation: 'upload_port = /media/media_name/drive'
|
||||
#
|
||||
drives = os.listdir(os.path.join(os.sep, 'media', getpass.getuser()))
|
||||
if target_drive in drives: # If target drive is found, use it.
|
||||
target_drive_found = True
|
||||
upload_disk = os.path.join(os.sep, 'media', getpass.getuser(), target_drive) + os.sep
|
||||
else:
|
||||
for drive in drives:
|
||||
try:
|
||||
files = os.listdir(os.path.join(os.sep, 'media', getpass.getuser(), drive))
|
||||
except:
|
||||
continue
|
||||
else:
|
||||
if target_filename in files:
|
||||
upload_disk = os.path.join(os.sep, 'media', getpass.getuser(), drive) + os.sep
|
||||
target_file_found = True
|
||||
break
|
||||
#
|
||||
# set upload_port to drive if found
|
||||
#
|
||||
elif current_OS == 'Linux':
|
||||
#
|
||||
# platformio.ini will accept this for a Linux upload port designation: 'upload_port = /media/media_name/drive'
|
||||
#
|
||||
import getpass
|
||||
user = getpass.getuser()
|
||||
mpath = Path('/media', user)
|
||||
drives = [ x for x in mpath.iterdir() if x.is_dir() ]
|
||||
if target_drive in drives: # If target drive is found, use it.
|
||||
target_drive_found = True
|
||||
upload_disk = mpath / target_drive
|
||||
else:
|
||||
for drive in drives:
|
||||
try:
|
||||
fpath = mpath / drive
|
||||
filenames = [ x.name for x in fpath.iterdir() if x.is_file() ]
|
||||
except:
|
||||
continue
|
||||
else:
|
||||
if target_filename in filenames:
|
||||
upload_disk = mpath / drive
|
||||
target_file_found = True
|
||||
break
|
||||
#
|
||||
# set upload_port to drive if found
|
||||
#
|
||||
|
||||
if target_file_found or target_drive_found:
|
||||
env.Replace(
|
||||
UPLOAD_FLAGS="-P$UPLOAD_PORT"
|
||||
)
|
||||
if target_file_found or target_drive_found:
|
||||
env.Replace(
|
||||
UPLOAD_FLAGS="-P$UPLOAD_PORT"
|
||||
)
|
||||
|
||||
elif current_OS == 'Darwin': # MAC
|
||||
#
|
||||
# platformio.ini will accept this for a OSX upload port designation: 'upload_port = /media/media_name/drive'
|
||||
#
|
||||
drives = os.listdir('/Volumes') # human readable names
|
||||
if target_drive in drives and not target_file_found: # set upload if not found target file yet
|
||||
target_drive_found = True
|
||||
upload_disk = '/Volumes/' + target_drive + '/'
|
||||
for drive in drives:
|
||||
try:
|
||||
filenames = os.listdir('/Volumes/' + drive + '/') # will get an error if the drive is protected
|
||||
except:
|
||||
continue
|
||||
else:
|
||||
if target_filename in filenames:
|
||||
if not target_file_found:
|
||||
upload_disk = '/Volumes/' + drive + '/'
|
||||
target_file_found = True
|
||||
elif current_OS == 'Darwin': # MAC
|
||||
#
|
||||
# platformio.ini will accept this for a OSX upload port designation: 'upload_port = /media/media_name/drive'
|
||||
#
|
||||
dpath = Path('/Volumes') # human readable names
|
||||
drives = [ x for x in dpath.iterdir() if x.is_dir() ]
|
||||
if target_drive in drives and not target_file_found: # set upload if not found target file yet
|
||||
target_drive_found = True
|
||||
upload_disk = dpath / target_drive
|
||||
for drive in drives:
|
||||
try:
|
||||
fpath = dpath / drive # will get an error if the drive is protected
|
||||
filenames = [ x.name for x in fpath.iterdir() if x.is_file() ]
|
||||
except:
|
||||
continue
|
||||
else:
|
||||
if target_filename in filenames:
|
||||
upload_disk = dpath / drive
|
||||
target_file_found = True
|
||||
break
|
||||
|
||||
#
|
||||
# Set upload_port to drive if found
|
||||
#
|
||||
if target_file_found or target_drive_found:
|
||||
env.Replace(UPLOAD_PORT=upload_disk)
|
||||
print('\nUpload disk: ', upload_disk, '\n')
|
||||
else:
|
||||
print_error('Autodetect Error')
|
||||
#
|
||||
# Set upload_port to drive if found
|
||||
#
|
||||
if target_file_found or target_drive_found:
|
||||
env.Replace(UPLOAD_PORT=str(upload_disk))
|
||||
print('\nUpload disk: ', upload_disk, '\n')
|
||||
else:
|
||||
print_error('Autodetect Error')
|
||||
|
||||
except Exception as e:
|
||||
print_error(str(e))
|
||||
except Exception as e:
|
||||
print_error(str(e))
|
||||
|
||||
env.AddPreAction("upload", before_upload)
|
||||
env.AddPreAction("upload", before_upload)
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifdef TARGET_LPC1768
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#if ENABLED(USE_WATCHDOG)
|
||||
|
||||
#include <lpc17xx_wdt.h>
|
||||
#include "watchdog.h"
|
||||
|
||||
#define WDT_TIMEOUT_US TERN(WATCHDOG_DURATION_8S, 8000000, 4000000) // 4 or 8 second timeout
|
||||
|
||||
void watchdog_init() {
|
||||
#if ENABLED(WATCHDOG_RESET_MANUAL)
|
||||
// We enable the watchdog timer, but only for the interrupt.
|
||||
|
||||
// Configure WDT to only trigger an interrupt
|
||||
// Disable WDT interrupt (just in case, to avoid triggering it!)
|
||||
NVIC_DisableIRQ(WDT_IRQn);
|
||||
|
||||
// We NEED memory barriers to ensure Interrupts are actually disabled!
|
||||
// ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
|
||||
__DSB();
|
||||
__ISB();
|
||||
|
||||
// Configure WDT to only trigger an interrupt
|
||||
// Initialize WDT with the given parameters
|
||||
WDT_Init(WDT_CLKSRC_IRC, WDT_MODE_INT_ONLY);
|
||||
|
||||
// Configure and enable WDT interrupt.
|
||||
NVIC_ClearPendingIRQ(WDT_IRQn);
|
||||
NVIC_SetPriority(WDT_IRQn, 0); // Use highest priority, so we detect all kinds of lockups
|
||||
NVIC_EnableIRQ(WDT_IRQn);
|
||||
#else
|
||||
WDT_Init(WDT_CLKSRC_IRC, WDT_MODE_RESET);
|
||||
#endif
|
||||
WDT_Start(WDT_TIMEOUT_US);
|
||||
}
|
||||
|
||||
void HAL_watchdog_refresh() {
|
||||
WDT_Feed();
|
||||
#if DISABLED(PINS_DEBUGGING) && PIN_EXISTS(LED)
|
||||
TOGGLE(LED_PIN); // heartbeat indicator
|
||||
#endif
|
||||
}
|
||||
|
||||
// Timeout state
|
||||
bool watchdog_timed_out() { return TEST(WDT_ReadTimeOutFlag(), 0); }
|
||||
void watchdog_clear_timeout_flag() { WDT_ClrTimeOutFlag(); }
|
||||
|
||||
#endif // USE_WATCHDOG
|
||||
#endif // TARGET_LPC1768
|
||||
@@ -45,7 +45,6 @@ uint8_t _getc();
|
||||
#include "../shared/math_32bit.h"
|
||||
#include "../shared/HAL_SPI.h"
|
||||
#include "fastio.h"
|
||||
#include "watchdog.h"
|
||||
#include "serial.h"
|
||||
|
||||
// ------------------------
|
||||
@@ -186,7 +185,7 @@ constexpr inline char* strstr_constexpr(char* str, const char* target) {
|
||||
}
|
||||
|
||||
// ------------------------
|
||||
// Class Utilities
|
||||
// Free Memory Accessor
|
||||
// ------------------------
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
@@ -208,6 +207,10 @@ public:
|
||||
// Earliest possible init, before setup()
|
||||
MarlinHAL() {}
|
||||
|
||||
// Watchdog
|
||||
static void watchdog_init();
|
||||
static void watchdog_refresh();
|
||||
|
||||
static void init() {} // Called early in setup()
|
||||
static void init_board() {} // Called less early in setup()
|
||||
static void reboot(); // Restart the firmware from 0x0
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
*
|
||||
* Now you can simply SET_OUTPUT(STEP); WRITE(STEP, HIGH); WRITE(STEP, LOW);
|
||||
*
|
||||
* Why double up on these macros? see http://gcc.gnu.org/onlinedocs/cpp/Stringification.html
|
||||
* Why double up on these macros? see https://gcc.gnu.org/onlinedocs/cpp/Stringification.html
|
||||
*/
|
||||
|
||||
/// Read a pin
|
||||
|
||||
@@ -31,10 +31,11 @@
|
||||
#endif
|
||||
|
||||
#define DATASIZE_8BIT 8
|
||||
#define DATASIZE_16BIT 16
|
||||
#define TFT_IO_DRIVER TFT_SPI
|
||||
#define DATASIZE_16BIT 16
|
||||
#define TFT_IO_DRIVER TFT_SPI
|
||||
#define DMA_MAX_SIZE 0xFFFF
|
||||
|
||||
#define DMA_MINC_ENABLE 1
|
||||
#define DMA_MINC_ENABLE 1
|
||||
#define DMA_MINC_DISABLE 0
|
||||
|
||||
class TFT_SPI {
|
||||
@@ -58,7 +59,9 @@ public:
|
||||
static void WriteData(uint16_t Data);
|
||||
static void WriteReg(uint16_t Reg);
|
||||
|
||||
static void WriteSequence_DMA(uint16_t *Data, uint16_t Count) { WriteSequence(Data, Count); }
|
||||
static void WriteMultiple_DMA(uint16_t Color, uint16_t Count) { WriteMultiple(Color, Count); }
|
||||
|
||||
static void WriteSequence(uint16_t *Data, uint16_t Count);
|
||||
// static void WriteMultiple(uint16_t Color, uint16_t Count);
|
||||
static void WriteMultiple(uint16_t Color, uint32_t Count);
|
||||
};
|
||||
|
||||
@@ -51,7 +51,7 @@ enum XPTCoordinate : uint8_t {
|
||||
XPT2046_Z2 = 0x40 | XPT2046_CONTROL | XPT2046_DFR_MODE,
|
||||
};
|
||||
|
||||
#if !defined(XPT2046_Z1_THRESHOLD)
|
||||
#ifndef XPT2046_Z1_THRESHOLD
|
||||
#define XPT2046_Z1_THRESHOLD 10
|
||||
#endif
|
||||
|
||||
|
||||
@@ -38,13 +38,13 @@
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
void u8g_SetPinOutput(uint8_t internal_pin_number){SET_DIR_OUTPUT(internal_pin_number);}
|
||||
void u8g_SetPinInput(uint8_t internal_pin_number){SET_DIR_INPUT(internal_pin_number);}
|
||||
void u8g_SetPinLevel(uint8_t pin, uint8_t pin_status){WRITE_PIN(pin, pin_status);}
|
||||
uint8_t u8g_GetPinLevel(uint8_t pin){return READ_PIN(pin);}
|
||||
void usleep(uint64_t microsec){
|
||||
assert(false); // why we here?
|
||||
}
|
||||
|
||||
void u8g_SetPinOutput(uint8_t internal_pin_number) { SET_DIR_OUTPUT(internal_pin_number); }
|
||||
void u8g_SetPinInput(uint8_t internal_pin_number) { SET_DIR_INPUT(internal_pin_number); }
|
||||
void u8g_SetPinLevel(uint8_t pin, uint8_t pin_status) { WRITE_PIN(pin, pin_status); }
|
||||
uint8_t u8g_GetPinLevel(uint8_t pin) { return READ_PIN(pin); }
|
||||
void usleep(uint64_t microsec) { assert(false); /* why we here? */ }
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -168,4 +168,4 @@ uint8_t u8g_com_ST7920_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void
|
||||
#endif
|
||||
|
||||
#endif // IS_U8GLIB_ST7920
|
||||
#endif // TARGET_LPC1768
|
||||
#endif // __PLAT_NATIVE_SIM__
|
||||
|
||||
@@ -0,0 +1,212 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
#ifdef __SAMD21__
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#include <wiring_private.h>
|
||||
|
||||
#if USING_HW_SERIALUSB
|
||||
DefaultSerial1 MSerialUSB(false, SerialUSB);
|
||||
#endif
|
||||
#if USING_HW_SERIAL0
|
||||
DefaultSerial2 MSerial1(false, Serial1);
|
||||
#endif
|
||||
#if USING_HW_SERIAL1
|
||||
DefaultSerial3 MSerial2(false, Serial2);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define WDT_CONFIG_PER_7_Val 0x9u
|
||||
#define WDT_CONFIG_PER_Pos 0
|
||||
#define WDT_CONFIG_PER_7 (WDT_CONFIG_PER_7_Val << WDT_CONFIG_PER_Pos)
|
||||
|
||||
#if ENABLED(USE_WATCHDOG)
|
||||
|
||||
#define WDT_TIMEOUT_REG TERN(WATCHDOG_DURATION_8S, WDT_CONFIG_PER_CYC8192, WDT_CONFIG_PER_CYC4096) // 4 or 8 second timeout
|
||||
|
||||
void MarlinHAL::watchdog_init() {
|
||||
// Set up the generic clock (GCLK2) used to clock the watchdog timer at 1.024kHz
|
||||
GCLK->GENDIV.reg = GCLK_GENDIV_DIV(4) | // Divide the 32.768kHz clock source by divisor 32, where 2^(4 + 1): 32.768kHz/32=1.024kHz
|
||||
GCLK_GENDIV_ID(2); // Select Generic Clock (GCLK) 2
|
||||
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
|
||||
|
||||
REG_GCLK_GENCTRL = GCLK_GENCTRL_DIVSEL | // Set to divide by 2^(GCLK_GENDIV_DIV(4) + 1)
|
||||
GCLK_GENCTRL_IDC | // Set the duty cycle to 50/50 HIGH/LOW
|
||||
GCLK_GENCTRL_GENEN | // Enable GCLK2
|
||||
GCLK_GENCTRL_SRC_OSCULP32K | // Set the clock source to the ultra low power oscillator (OSCULP32K)
|
||||
GCLK_GENCTRL_ID(2); // Select GCLK2
|
||||
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
|
||||
|
||||
// Feed GCLK2 to WDT (Watchdog Timer)
|
||||
REG_GCLK_CLKCTRL = GCLK_CLKCTRL_CLKEN | // Enable GCLK2 to the WDT
|
||||
GCLK_CLKCTRL_GEN_GCLK2 | // Select GCLK2
|
||||
GCLK_CLKCTRL_ID_WDT; // Feed the GCLK2 to the WDT
|
||||
while (GCLK->STATUS.bit.SYNCBUSY); // Wait for synchronization
|
||||
|
||||
WDT->CONFIG.bit.PER = WDT_CONFIG_PER_7; // Set the WDT reset timeout to 4 seconds
|
||||
while (WDT->STATUS.bit.SYNCBUSY); // Wait for synchronization
|
||||
REG_WDT_CTRL = WDT_CTRL_ENABLE; // Enable the WDT in normal mode
|
||||
while (WDT->STATUS.bit.SYNCBUSY); // Wait for synchronization
|
||||
}
|
||||
|
||||
// Reset watchdog. MUST be called at least every 4 seconds after the
|
||||
// first watchdog_init or SAMD will go into emergency procedures.
|
||||
void MarlinHAL::watchdog_refresh() {
|
||||
WDT->CLEAR.reg = WDT_CLEAR_CLEAR_KEY;
|
||||
while (WDT->STATUS.bit.SYNCBUSY);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// ------------------------
|
||||
// Types
|
||||
// ------------------------
|
||||
|
||||
// ------------------------
|
||||
// Private Variables
|
||||
// ------------------------
|
||||
|
||||
// ------------------------
|
||||
// Private functions
|
||||
// ------------------------
|
||||
|
||||
void MarlinHAL::dma_init() {}
|
||||
|
||||
// ------------------------
|
||||
// Public functions
|
||||
// ------------------------
|
||||
|
||||
// HAL initialization task
|
||||
void MarlinHAL::init() {
|
||||
TERN_(DMA_IS_REQUIRED, dma_init());
|
||||
#if ENABLED(SDSUPPORT)
|
||||
#if HAS_SD_DETECT && SD_CONNECTION_IS(ONBOARD)
|
||||
SET_INPUT_PULLUP(SD_DETECT_PIN);
|
||||
#endif
|
||||
OUT_WRITE(SDSS, HIGH); // Try to set SDSS inactive before any other SPI users start up
|
||||
#endif
|
||||
}
|
||||
|
||||
#pragma push_macro("WDT")
|
||||
#undef WDT // Required to be able to use '.bit.WDT'. Compiler wrongly replace struct field with WDT define
|
||||
uint8_t MarlinHAL::get_reset_source() {
|
||||
|
||||
return 0;
|
||||
}
|
||||
#pragma pop_macro("WDT")
|
||||
|
||||
void MarlinHAL::reboot() { NVIC_SystemReset(); }
|
||||
|
||||
extern "C" {
|
||||
void * _sbrk(int incr);
|
||||
extern unsigned int __bss_end__; // end of bss section
|
||||
}
|
||||
|
||||
// Return free memory between end of heap (or end bss) and whatever is current
|
||||
int freeMemory() {
|
||||
int free_memory, heap_end = (int)_sbrk(0);
|
||||
return (int)&free_memory - (heap_end ?: (int)&__bss_end__);
|
||||
}
|
||||
|
||||
// ------------------------
|
||||
// ADC
|
||||
// ------------------------
|
||||
|
||||
uint16_t MarlinHAL::adc_result;
|
||||
|
||||
void MarlinHAL::adc_init() {
|
||||
/* thanks to https://www.eevblog.com/forum/microcontrollers/samd21g18-adc-with-resrdy-interrupts-only-reads-once-or-twice/ */
|
||||
|
||||
ADC->CTRLA.bit.ENABLE = false;
|
||||
while(ADC->STATUS.bit.SYNCBUSY);
|
||||
|
||||
// load chip corrections
|
||||
uint32_t bias = (*((uint32_t *) ADC_FUSES_BIASCAL_ADDR) & ADC_FUSES_BIASCAL_Msk) >> ADC_FUSES_BIASCAL_Pos;
|
||||
uint32_t linearity = (*((uint32_t *) ADC_FUSES_LINEARITY_0_ADDR) & ADC_FUSES_LINEARITY_0_Msk) >> ADC_FUSES_LINEARITY_0_Pos;
|
||||
linearity |= ((*((uint32_t *) ADC_FUSES_LINEARITY_1_ADDR) & ADC_FUSES_LINEARITY_1_Msk) >> ADC_FUSES_LINEARITY_1_Pos) << 5;
|
||||
|
||||
/* Wait for bus synchronization. */
|
||||
while (ADC->STATUS.bit.SYNCBUSY) {};
|
||||
|
||||
ADC->CALIB.reg = ADC_CALIB_BIAS_CAL(bias) | ADC_CALIB_LINEARITY_CAL(linearity);
|
||||
|
||||
/* Wait for bus synchronization. */
|
||||
while (ADC->STATUS.bit.SYNCBUSY) {};
|
||||
|
||||
ADC->CTRLA.bit.SWRST = true;
|
||||
while(ADC->STATUS.bit.SYNCBUSY);
|
||||
|
||||
ADC->REFCTRL.reg = ADC_REFCTRL_REFSEL_INTVCC1;
|
||||
ADC->AVGCTRL.reg = ADC_AVGCTRL_SAMPLENUM_32| ADC_AVGCTRL_ADJRES(4);;
|
||||
|
||||
|
||||
ADC->CTRLB.reg = ADC_CTRLB_PRESCALER_DIV128 |
|
||||
ADC_CTRLB_RESSEL_16BIT |
|
||||
ADC_CTRLB_FREERUN;
|
||||
while(ADC->STATUS.bit.SYNCBUSY);
|
||||
|
||||
ADC->SAMPCTRL.bit.SAMPLEN = 0x00;
|
||||
while(ADC->STATUS.bit.SYNCBUSY);
|
||||
|
||||
ADC->INPUTCTRL.reg = ADC_INPUTCTRL_INPUTSCAN(HAL_ADC_AIN_LEN) // scan (INPUTSCAN + NUM_EXTUDERS - 1) pins
|
||||
| ADC_INPUTCTRL_GAIN_DIV2 |ADC_INPUTCTRL_MUXNEG_GND| HAL_ADC_AIN_START ; /* set to first AIN */
|
||||
|
||||
while(ADC->STATUS.bit.SYNCBUSY);
|
||||
|
||||
ADC->INTENSET.reg |= ADC_INTENSET_RESRDY; // enable Result Ready ADC interrupts
|
||||
while (ADC->STATUS.bit.SYNCBUSY);
|
||||
|
||||
NVIC_EnableIRQ(ADC_IRQn); // enable ADC interrupts
|
||||
|
||||
NVIC_SetPriority(ADC_IRQn, 3);
|
||||
|
||||
ADC->CTRLA.bit.ENABLE = true;
|
||||
}
|
||||
|
||||
volatile uint32_t adc_results[HAL_ADC_AIN_NUM_SENSORS];
|
||||
|
||||
void ADC_Handler() {
|
||||
while(ADC->STATUS.bit.SYNCBUSY == 1);
|
||||
int pos = ADC->INPUTCTRL.bit.INPUTOFFSET;
|
||||
|
||||
adc_results[pos] = ADC->RESULT.reg; /* Read the value. */
|
||||
ADC->INTFLAG.reg = ADC_INTENSET_RESRDY; /* Clear the data ready flag. */
|
||||
}
|
||||
|
||||
void MarlinHAL::adc_start(const pin_t pin) {
|
||||
/* due to the way INPUTOFFSET works, the last sensor is the first position in the array
|
||||
and we want the ADC_handler interrupt to be as simple possible, so we do the calculation here.
|
||||
*/
|
||||
unsigned int pos = PIN_TO_INPUTCTRL(pin) - HAL_ADC_AIN_START + 1;
|
||||
if (pos == HAL_ADC_AIN_NUM_SENSORS) pos = 0;
|
||||
adc_result = adc_results[pos]; // 16-bit resolution
|
||||
//adc_result = 0xFFFF;
|
||||
}
|
||||
|
||||
#endif // __SAMD21__
|
||||
@@ -0,0 +1,223 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* 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
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
|
||||
#define CPU_32_BIT
|
||||
|
||||
#include "../shared/Marduino.h"
|
||||
#include "../shared/math_32bit.h"
|
||||
#include "../shared/HAL_SPI.h"
|
||||
#include "fastio.h"
|
||||
|
||||
// ------------------------
|
||||
// Serial ports
|
||||
// ------------------------
|
||||
#include "../../core/serial_hook.h"
|
||||
typedef ForwardSerial1Class< decltype(SerialUSB) > DefaultSerial1;
|
||||
extern DefaultSerial1 MSerialUSB;
|
||||
|
||||
// Serial ports
|
||||
typedef ForwardSerial1Class< decltype(Serial1) > DefaultSerial2;
|
||||
typedef ForwardSerial1Class< decltype(Serial2) > DefaultSerial3;
|
||||
|
||||
extern DefaultSerial2 MSerial0;
|
||||
extern DefaultSerial3 MSerial1;
|
||||
|
||||
|
||||
#define __MSERIAL(X) MSerial##X
|
||||
#define _MSERIAL(X) __MSERIAL(X)
|
||||
#define MSERIAL(X) _MSERIAL(INCREMENT(X))
|
||||
|
||||
#if WITHIN(SERIAL_PORT, 0, 1)
|
||||
#define MYSERIAL1 MSERIAL(SERIAL_PORT)
|
||||
#elif SERIAL_PORT == -1
|
||||
#define MYSERIAL1 MSerialUSB
|
||||
#else
|
||||
#error "SERIAL_PORT must be -1 (Native USB only)."
|
||||
#endif
|
||||
|
||||
#ifdef SERIAL_PORT_2
|
||||
#if WITHIN(SERIAL_PORT_2, 0, 1)
|
||||
#define MYSERIAL2 MSERIAL(SERIAL_PORT)
|
||||
#elif SERIAL_PORT_2 == -1
|
||||
#define MYSERIAL2 MSerialUSB
|
||||
#else
|
||||
#error "SERIAL_PORT_2 must be -1 (Native USB only)."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef MMU2_SERIAL_PORT
|
||||
#if WITHIN(MMU2_SERIAL_PORT, 0, 1)
|
||||
#define MMU2_SERIAL MSERIAL(SERIAL_PORT)
|
||||
#elif MMU2_SERIAL_PORT == -1
|
||||
#define MMU2_SERIAL MSerialUSB
|
||||
#else
|
||||
#error "MMU2_SERIAL_PORT must be -1 (Native USB only)."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef LCD_SERIAL_PORT
|
||||
#if WITHIN(LCD_SERIAL_PORT, 0, 1)
|
||||
#define LCD_SERIAL MSERIAL(SERIAL_PORT)
|
||||
#elif LCD_SERIAL_PORT == -1
|
||||
#define LCD_SERIAL MSerialUSB
|
||||
#else
|
||||
#error "LCD_SERIAL_PORT must be -1 (Native USB only)."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef int8_t pin_t;
|
||||
|
||||
#define SHARED_SERVOS HAS_SERVOS // Use shared/servos.cpp
|
||||
|
||||
class Servo;
|
||||
typedef Servo hal_servo_t;
|
||||
|
||||
//
|
||||
// Interrupts
|
||||
//
|
||||
#define CRITICAL_SECTION_START() const bool irqon = !__get_PRIMASK(); __disable_irq()
|
||||
#define CRITICAL_SECTION_END() if (irqon) __enable_irq()
|
||||
|
||||
#define cli() __disable_irq() // Disable interrupts
|
||||
#define sei() __enable_irq() // Enable interrupts
|
||||
|
||||
//
|
||||
// ADC
|
||||
//
|
||||
|
||||
#define HAL_ADC_FILTERED 1 // Disable Marlin's oversampling. The HAL filters ADC values.
|
||||
#define HAL_ADC_VREF 3.3
|
||||
#define HAL_ADC_RESOLUTION 12
|
||||
#define HAL_ADC_AIN_START ADC_INPUTCTRL_MUXPOS_PIN3
|
||||
#define HAL_ADC_AIN_NUM_SENSORS 3
|
||||
#define HAL_ADC_AIN_LEN HAL_ADC_AIN_NUM_SENSORS-1
|
||||
|
||||
//
|
||||
// Pin Mapping for M42, M43, M226
|
||||
//
|
||||
#define GET_PIN_MAP_PIN(index) index
|
||||
#define GET_PIN_MAP_INDEX(pin) pin
|
||||
#define PARSED_PIN_INDEX(code, dval) parser.intval(code, dval)
|
||||
|
||||
//
|
||||
// Tone
|
||||
//
|
||||
void tone(const pin_t _pin, const unsigned int frequency, const unsigned long duration=0);
|
||||
void noTone(const pin_t _pin);
|
||||
|
||||
// ------------------------
|
||||
// Class Utilities
|
||||
// ------------------------
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#if GCC_VERSION <= 50000
|
||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
char *dtostrf(double __val, signed char __width, unsigned char __prec, char *__s);
|
||||
|
||||
extern "C" int freeMemory();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#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 !__get_PRIMASK(); }
|
||||
static void isr_on() { sei(); }
|
||||
static void isr_off() { cli(); }
|
||||
|
||||
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 pin. Called from Temperature::isr!
|
||||
static void adc_start(const pin_t pin);
|
||||
|
||||
// Is the ADC ready for reading?
|
||||
static bool adc_ready() { return true; }
|
||||
|
||||
// The current value of the ADC register
|
||||
static uint16_t adc_value() { return adc_result; }
|
||||
|
||||
/**
|
||||
* Set the PWM duty cycle for the pin to the given value.
|
||||
* No option to invert the duty cycle [default = false]
|
||||
* No option to 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=255, const bool=false) {
|
||||
analogWrite(pin, v);
|
||||
}
|
||||
|
||||
private:
|
||||
static void dma_init();
|
||||
};
|
||||
@@ -0,0 +1,148 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Hardware and software SPI implementations are included in this file.
|
||||
*
|
||||
* Control of the slave select pin(s) is handled by the calling routines and
|
||||
* SAMD21 let hardware SPI handling to remove SS from its logic.
|
||||
*/
|
||||
|
||||
#ifdef __SAMD21__
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Includes
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
#include <SPI.h>
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Public functions
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
#if EITHER(SOFTWARE_SPI, FORCE_SOFT_SPI)
|
||||
|
||||
// ------------------------
|
||||
// Software SPI
|
||||
// ------------------------
|
||||
#error "Software SPI not supported for SAMD21. Use Hardware SPI."
|
||||
|
||||
#else // !SOFTWARE_SPI
|
||||
|
||||
static SPISettings spiConfig;
|
||||
|
||||
// ------------------------
|
||||
// Hardware SPI
|
||||
// ------------------------
|
||||
void spiBegin() {
|
||||
spiInit(SPI_HALF_SPEED);
|
||||
}
|
||||
|
||||
void spiInit(uint8_t spiRate) {
|
||||
// Use datarates Marlin uses
|
||||
uint32_t clock;
|
||||
switch (spiRate) {
|
||||
case SPI_FULL_SPEED: clock = 8000000; break;
|
||||
case SPI_HALF_SPEED: clock = 4000000; break;
|
||||
case SPI_QUARTER_SPEED: clock = 2000000; break;
|
||||
case SPI_EIGHTH_SPEED: clock = 1000000; break;
|
||||
case SPI_SIXTEENTH_SPEED: clock = 500000; break;
|
||||
case SPI_SPEED_5: clock = 250000; break;
|
||||
case SPI_SPEED_6: clock = 125000; break;
|
||||
default: clock = 4000000; break; // Default from the SPI library
|
||||
}
|
||||
spiConfig = SPISettings(clock, MSBFIRST, SPI_MODE0);
|
||||
SPI.begin();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receives a single byte from the SPI port.
|
||||
*
|
||||
* @return Byte received
|
||||
*
|
||||
* @details
|
||||
*/
|
||||
uint8_t spiRec() {
|
||||
SPI.beginTransaction(spiConfig);
|
||||
uint8_t returnByte = SPI.transfer(0xFF);
|
||||
SPI.endTransaction();
|
||||
return returnByte;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receives a number of bytes from the SPI port to a buffer
|
||||
*
|
||||
* @param buf Pointer to starting address of buffer to write to.
|
||||
* @param nbyte Number of bytes to receive.
|
||||
* @return Nothing
|
||||
*/
|
||||
void spiRead(uint8_t *buf, uint16_t nbyte) {
|
||||
if (nbyte == 0) return;
|
||||
memset(buf, 0xFF, nbyte);
|
||||
|
||||
SPI.beginTransaction(spiConfig);
|
||||
SPI.transfer(buf, nbyte);
|
||||
SPI.endTransaction();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sends a single byte on SPI port
|
||||
*
|
||||
* @param b Byte to send
|
||||
*
|
||||
* @details
|
||||
*/
|
||||
void spiSend(uint8_t b) {
|
||||
SPI.beginTransaction(spiConfig);
|
||||
SPI.transfer(b);
|
||||
SPI.endTransaction();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write token and then write from 512 byte buffer to SPI (for SD card)
|
||||
*
|
||||
* @param buf Pointer with buffer start address
|
||||
* @return Nothing
|
||||
*
|
||||
* @details Uses DMA
|
||||
*/
|
||||
void spiSendBlock(uint8_t token, const uint8_t *buf) {
|
||||
SPI.beginTransaction(spiConfig);
|
||||
SPI.transfer(token);
|
||||
SPI.transfer((uint8_t*)buf, 512);
|
||||
SPI.endTransaction();
|
||||
}
|
||||
|
||||
void spiBeginTransaction(uint32_t spiClock, uint8_t bitOrder, uint8_t dataMode) {
|
||||
spiConfig = SPISettings(spiClock, (BitOrder)bitOrder, dataMode);
|
||||
SPI.beginTransaction(spiConfig);
|
||||
}
|
||||
#endif // !SOFTWARE_SPI
|
||||
|
||||
#endif // __SAMD21__
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
* Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
@@ -19,12 +19,13 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
void watchdog_init();
|
||||
#include <SPI.h>
|
||||
|
||||
inline void HAL_watchdog_refresh() {
|
||||
// Watchdog refresh sequence
|
||||
WDOG_REFRESH = 0xA602;
|
||||
WDOG_REFRESH = 0xB480;
|
||||
}
|
||||
using MarlinSPI = SPIClass;
|
||||
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#if ENABLED(QSPI_EEPROM)
|
||||
|
||||
#include "QSPIFlash.h"
|
||||
|
||||
#define INVALID_ADDR 0xFFFFFFFF
|
||||
#define SECTOR_OF(a) (a & ~(SFLASH_SECTOR_SIZE - 1))
|
||||
#define OFFSET_OF(a) (a & (SFLASH_SECTOR_SIZE - 1))
|
||||
|
||||
Adafruit_SPIFlashBase * QSPIFlash::_flashBase = nullptr;
|
||||
uint8_t QSPIFlash::_buf[SFLASH_SECTOR_SIZE];
|
||||
uint32_t QSPIFlash::_addr = INVALID_ADDR;
|
||||
|
||||
void QSPIFlash::begin() {
|
||||
if (_flashBase) return;
|
||||
|
||||
_flashBase = new Adafruit_SPIFlashBase(new Adafruit_FlashTransport_QSPI());
|
||||
_flashBase->begin(nullptr);
|
||||
}
|
||||
|
||||
size_t QSPIFlash::size() {
|
||||
return _flashBase->size();
|
||||
}
|
||||
|
||||
uint8_t QSPIFlash::readByte(const uint32_t address) {
|
||||
if (SECTOR_OF(address) == _addr) return _buf[OFFSET_OF(address)];
|
||||
|
||||
return _flashBase->read8(address);
|
||||
}
|
||||
|
||||
void QSPIFlash::writeByte(const uint32_t address, const uint8_t value) {
|
||||
uint32_t const sector_addr = SECTOR_OF(address);
|
||||
|
||||
// Page changes, flush old and update new cache
|
||||
if (sector_addr != _addr) {
|
||||
flush();
|
||||
_addr = sector_addr;
|
||||
|
||||
// read a whole page from flash
|
||||
_flashBase->readBuffer(sector_addr, _buf, SFLASH_SECTOR_SIZE);
|
||||
}
|
||||
|
||||
_buf[OFFSET_OF(address)] = value;
|
||||
}
|
||||
|
||||
void QSPIFlash::flush() {
|
||||
if (_addr == INVALID_ADDR) return;
|
||||
|
||||
_flashBase->eraseSector(_addr / SFLASH_SECTOR_SIZE);
|
||||
_flashBase->writeBuffer(_addr, _buf, SFLASH_SECTOR_SIZE);
|
||||
|
||||
_addr = INVALID_ADDR;
|
||||
}
|
||||
|
||||
#endif // QSPI_EEPROM
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* @file QSPIFlash.h
|
||||
*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Ha Thach and Dean Miller for Adafruit Industries LLC
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
* Derived from Adafruit_SPIFlash class with no SdFat references
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <Adafruit_SPIFlashBase.h>
|
||||
|
||||
// This class extends Adafruit_SPIFlashBase by adding caching support.
|
||||
//
|
||||
// This class will use 4096 Bytes of RAM as a block cache.
|
||||
class QSPIFlash {
|
||||
public:
|
||||
static void begin();
|
||||
static size_t size();
|
||||
static uint8_t readByte(const uint32_t address);
|
||||
static void writeByte(const uint32_t address, const uint8_t v);
|
||||
static void flush();
|
||||
|
||||
private:
|
||||
static Adafruit_SPIFlashBase * _flashBase;
|
||||
static uint8_t _buf[SFLASH_SECTOR_SIZE];
|
||||
static uint32_t _addr;
|
||||
};
|
||||
|
||||
extern QSPIFlash qspi;
|
||||
@@ -0,0 +1,66 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* 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
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
|
||||
#define SYNC(sc) while (sc) { \
|
||||
asm(""); \
|
||||
}
|
||||
|
||||
// Get SAMD port/pin from specified arduino pin
|
||||
#define GET_SAMD_PORT(P) _GET_SAMD_PORT(PIN_TO_SAMD_PIN(P))
|
||||
#define GET_SAMD_PIN(P) _GET_SAMD_PIN(PIN_TO_SAMD_PIN(P))
|
||||
|
||||
// Get external interrupt line associated to specified arduino pin
|
||||
#define PIN_TO_EILINE(P) _SAMDPORTPIN_TO_EILINE(GET_SAMD_PORT(P), GET_SAMD_PIN(P))
|
||||
|
||||
// Get adc/ain associated to specified arduino pin
|
||||
#define PIN_TO_ADC(P) (ANAPIN_TO_ADCAIN(P) >> 8)
|
||||
|
||||
// Private defines
|
||||
#define PIN_TO_SAMD_PIN(P) DIO##P##_PIN
|
||||
|
||||
#define _GET_SAMD_PORT(P) ((P) >> 5)
|
||||
#define _GET_SAMD_PIN(P) ((P) & 0x1F)
|
||||
|
||||
// Get external interrupt line
|
||||
#define _SAMDPORTPIN_TO_EILINE(P,B) ((P == 0 && WITHIN(B, 0, 31) && B != 26 && B != 28 && B != 29) ? (B) & 0xF \
|
||||
: (P == 1 && (WITHIN(B, 0, 25) || WITHIN(B, 30, 31))) ? (B) & 0xF \
|
||||
: (P == 1 && WITHIN(B, 26, 29)) ? 12 + (B) - 26 \
|
||||
: (P == 2 && (WITHIN(B, 0, 6) || WITHIN(B, 10, 31)) && B != 29) ? (B) & 0xF \
|
||||
: (P == 2 && B == 7) ? 9 \
|
||||
: (P == 3 && WITHIN(B, 0, 1)) ? (B) \
|
||||
: (P == 3 && WITHIN(B, 8, 12)) ? 3 + (B) - 8 \
|
||||
: (P == 3 && WITHIN(B, 20, 21)) ? 10 + (B) - 20 \
|
||||
: -1)
|
||||
|
||||
|
||||
|
||||
#define A2_AIN 3
|
||||
#define A3_AIN 4
|
||||
#define A4_AIN 5
|
||||
#define PIN_TO_AIN(P) A##P##_AIN
|
||||
#define AIN_TO_RESULT(P) ( (P - HAL_ADC_AIN_START == HAL_ADC_AIN_NUM_SENSORS-1) ? 0 : (P - HAL_ADC_AIN_START + 1) )
|
||||
@@ -0,0 +1,220 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
|
||||
/**
|
||||
* This comes from Arduino library which at the moment is buggy and uncompilable
|
||||
*/
|
||||
|
||||
#ifdef __SAMD21__
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#if HAS_SERVOS
|
||||
|
||||
#include "../shared/servo.h"
|
||||
#include "../shared/servo_private.h"
|
||||
#include "SAMD21.h"
|
||||
|
||||
#define __TC_GCLK_ID(t) TC##t##_GCLK_ID
|
||||
#define _TC_GCLK_ID(t) __TC_GCLK_ID(t)
|
||||
#define TC_GCLK_ID _TC_GCLK_ID(SERVO_TC)
|
||||
|
||||
#define _TC_PRESCALER(d) TC_CTRLA_PRESCALER_DIV##d##_Val
|
||||
#define TC_PRESCALER(d) _TC_PRESCALER(d)
|
||||
|
||||
#define __SERVO_IRQn(t) TC##t##_IRQn
|
||||
#define _SERVO_IRQn(t) __SERVO_IRQn(t)
|
||||
#define SERVO_IRQn _SERVO_IRQn(SERVO_TC)
|
||||
|
||||
#define HAL_SERVO_TIMER_ISR() TC_HANDLER(SERVO_TC)
|
||||
|
||||
#define TIMER_TCCHANNEL(t) ((t) & 1)
|
||||
#define TC_COUNTER_START_VAL 0xFFFF
|
||||
|
||||
|
||||
static volatile int8_t currentServoIndex[_Nbr_16timers]; // index for the servo being pulsed for each timer (or -1 if refresh interval)
|
||||
|
||||
FORCE_INLINE static uint16_t getTimerCount() {
|
||||
Tcc * const tc = timer_config[SERVO_TC].pTcc;
|
||||
|
||||
tc->CTRLBSET.reg = TCC_CTRLBCLR_CMD_READSYNC;
|
||||
SYNC(tc->STATUS.reg & TC_STATUS_SYNCBUSY);
|
||||
|
||||
return tc->COUNT.bit.COUNT;
|
||||
}
|
||||
|
||||
// ----------------------------
|
||||
// Interrupt handler for the TC
|
||||
// ----------------------------
|
||||
HAL_SERVO_TIMER_ISR() {
|
||||
Tcc * const tc = timer_config[SERVO_TC].pTcc;
|
||||
const timer16_Sequence_t timer =
|
||||
#ifndef _useTimer1
|
||||
_timer2
|
||||
#elif !defined(_useTimer2)
|
||||
_timer1
|
||||
#else
|
||||
(tc->INTFLAG.reg & tc->INTENSET.reg & TC_INTFLAG_MC0) ? _timer1 : _timer2
|
||||
#endif
|
||||
;
|
||||
const uint8_t tcChannel = TIMER_TCCHANNEL(timer);
|
||||
|
||||
int8_t cho = currentServoIndex[timer]; // Handle the prior servo first
|
||||
if (cho < 0) { // Servo -1 indicates the refresh interval completed...
|
||||
#if defined(_useTimer1) && defined(_useTimer2)
|
||||
if (currentServoIndex[timer ^ 1] >= 0) {
|
||||
// Wait for both channels
|
||||
// Clear the interrupt
|
||||
tc->INTFLAG.reg = (tcChannel == 0) ? TC_INTFLAG_MC0 : TC_INTFLAG_MC1;
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
tc->COUNT.reg = TC_COUNTER_START_VAL; // ...so reset the timer
|
||||
SYNC(tc->STATUS.reg & TC_STATUS_SYNCBUSY);
|
||||
}
|
||||
else if (SERVO_INDEX(timer, cho) < ServoCount) // prior channel handled?
|
||||
digitalWrite(SERVO(timer, cho).Pin.nbr, LOW); // pulse the prior channel LOW
|
||||
|
||||
currentServoIndex[timer] = ++cho; // go to the next channel (or 0)
|
||||
if (cho < SERVOS_PER_TIMER && SERVO_INDEX(timer, cho) < ServoCount) {
|
||||
if (SERVO(timer, cho).Pin.isActive) // activated?
|
||||
digitalWrite(SERVO(timer, cho).Pin.nbr, HIGH); // yes: pulse HIGH
|
||||
|
||||
tc->CC[tcChannel].reg = getTimerCount() - (uint16_t)SERVO(timer, cho).ticks;
|
||||
}
|
||||
else {
|
||||
// finished all channels so wait for the refresh period to expire before starting over
|
||||
currentServoIndex[timer] = -1; // reset the timer COUNT.reg on the next call
|
||||
const uint16_t cval = getTimerCount() - 256 / (SERVO_TIMER_PRESCALER), // allow 256 cycles to ensure the next CV not missed
|
||||
ival = (TC_COUNTER_START_VAL) - (uint16_t)usToTicks(REFRESH_INTERVAL); // at least REFRESH_INTERVAL has elapsed
|
||||
tc->CC[tcChannel].reg = min(cval, ival);
|
||||
}
|
||||
if (tcChannel == 0) {
|
||||
SYNC(tc->SYNCBUSY.bit.CC0);
|
||||
tc->INTFLAG.reg = TC_INTFLAG_MC0; // Clear the interrupt
|
||||
}
|
||||
else {
|
||||
SYNC(tc->SYNCBUSY.bit.CC1);
|
||||
tc->INTFLAG.reg = TC_INTFLAG_MC1; // Clear the interrupt
|
||||
}
|
||||
}
|
||||
|
||||
void initISR(const timer16_Sequence_t timer) {
|
||||
Tcc * const tc = timer_config[SERVO_TC].pTcc;
|
||||
const uint8_t tcChannel = TIMER_TCCHANNEL(timer);
|
||||
|
||||
static bool initialized = false; // Servo TC has been initialized
|
||||
if (!initialized) {
|
||||
NVIC_DisableIRQ(SERVO_IRQn);
|
||||
|
||||
// Disable the timer
|
||||
tc->CTRLA.bit.ENABLE = false;
|
||||
SYNC(tc->STATUS.reg & TC_STATUS_SYNCBUSY);
|
||||
|
||||
// Select GCLK0 as timer/counter input clock source
|
||||
GCLK->CLKCTRL.reg =(GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(TCC0_GCLK_ID));
|
||||
SYNC (GCLK->STATUS.bit.SYNCBUSY);
|
||||
|
||||
// Reset the timer
|
||||
tc->CTRLA.bit.SWRST = true;
|
||||
SYNC(tc->CTRLA.bit.SWRST);
|
||||
|
||||
// Set timer counter mode to 16 bits
|
||||
tc->CTRLA.reg = TC_CTRLA_MODE_COUNT16;
|
||||
|
||||
// Set timer counter mode as normal PWM
|
||||
tc->WAVE.bit.WAVEGEN = TCC_WAVE_WAVEGEN_NPWM_Val;
|
||||
|
||||
// Set the prescaler factor
|
||||
tc->CTRLA.bit.PRESCALER = TC_PRESCALER(SERVO_TIMER_PRESCALER);
|
||||
|
||||
// Count down
|
||||
tc->CTRLBSET.reg = TCC_CTRLBCLR_DIR;
|
||||
SYNC(tc->SYNCBUSY.bit.CTRLB);
|
||||
|
||||
// Reset all servo indexes
|
||||
memset((void *)currentServoIndex, 0xFF, sizeof(currentServoIndex));
|
||||
|
||||
// Configure interrupt request
|
||||
NVIC_ClearPendingIRQ(SERVO_IRQn);
|
||||
NVIC_SetPriority(SERVO_IRQn, 5);
|
||||
NVIC_EnableIRQ(SERVO_IRQn);
|
||||
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
if (!tc->CTRLA.bit.ENABLE) {
|
||||
// Reset the timer counter
|
||||
tc->COUNT.reg = TC_COUNTER_START_VAL;
|
||||
SYNC(tc->STATUS.reg & TC_STATUS_SYNCBUSY);
|
||||
|
||||
// Enable the timer and start it
|
||||
tc->CTRLA.bit.ENABLE = true;
|
||||
SYNC(tc->STATUS.reg & TC_STATUS_SYNCBUSY);
|
||||
}
|
||||
// First interrupt request after 1 ms
|
||||
tc->CC[tcChannel].reg = getTimerCount() - (uint16_t)usToTicks(1000UL);
|
||||
|
||||
if (tcChannel == 0 ) {
|
||||
SYNC(tc->SYNCBUSY.bit.CC0);
|
||||
|
||||
// Clear pending match interrupt
|
||||
tc->INTFLAG.reg = TC_INTENSET_MC0;
|
||||
// Enable the match channel interrupt request
|
||||
tc->INTENSET.reg = TC_INTENSET_MC0;
|
||||
}
|
||||
else {
|
||||
SYNC(tc->SYNCBUSY.bit.CC1);
|
||||
|
||||
// Clear pending match interrupt
|
||||
tc->INTFLAG.reg = TC_INTENSET_MC1;
|
||||
// Enable the match channel interrupt request
|
||||
tc->INTENSET.reg = TC_INTENSET_MC1;
|
||||
}
|
||||
}
|
||||
|
||||
void finISR(const timer16_Sequence_t timer_index) {
|
||||
Tcc * const tc = timer_config[SERVO_TC].pTcc;
|
||||
const uint8_t tcChannel = TIMER_TCCHANNEL(timer_index);
|
||||
|
||||
// Disable the match channel interrupt request
|
||||
tc->INTENCLR.reg = (tcChannel == 0) ? TC_INTENCLR_MC0 : TC_INTENCLR_MC1;
|
||||
|
||||
if (true
|
||||
#if defined(_useTimer1) && defined(_useTimer2)
|
||||
&& (tc->INTENCLR.reg & (TC_INTENCLR_MC0|TC_INTENCLR_MC1)) == 0
|
||||
#endif
|
||||
) {
|
||||
// Disable the timer if not used
|
||||
tc->CTRLA.bit.ENABLE = false;
|
||||
SYNC(tc->STATUS.reg & TC_STATUS_SYNCBUSY);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // HAS_SERVOS
|
||||
|
||||
#endif // __SAMD21__
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
* Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
@@ -21,13 +21,25 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
// Arduino Due core now has watchdog support
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
|
||||
#include "HAL.h"
|
||||
#define _useTimer1
|
||||
#define _useTimer2
|
||||
|
||||
// Initialize watchdog with a 4 second interrupt time
|
||||
void watchdog_init();
|
||||
#define TRIM_DURATION 5 // compensation ticks to trim adjust for digitalWrite delays
|
||||
#define SERVO_TIMER_PRESCALER 64 // timer prescaler factor to 64 (avoid overflowing 16-bit clock counter, at 120MHz this is 1831 ticks per millisecond
|
||||
|
||||
// Reset watchdog. MUST be called at least every 4 seconds after the
|
||||
// first watchdog_init or AVR will go into emergency procedures.
|
||||
inline void HAL_watchdog_refresh() { watchdogReset(); }
|
||||
#define SERVO_TC 3
|
||||
|
||||
typedef enum {
|
||||
#ifdef _useTimer1
|
||||
_timer1,
|
||||
#endif
|
||||
#ifdef _useTimer2
|
||||
_timer2,
|
||||
#endif
|
||||
_Nbr_16timers
|
||||
} timer16_Sequence_t;
|
||||
@@ -0,0 +1,141 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
#ifdef __SAMD21__
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#if ENABLED(FLASH_EEPROM_EMULATION)
|
||||
|
||||
#define TOTAL_FLASH_SIZE (MARLIN_EEPROM_SIZE+255)/256*256
|
||||
|
||||
/* reserve flash memory */
|
||||
static const uint8_t flashdata[TOTAL_FLASH_SIZE] __attribute__((__aligned__(256))) { }; \
|
||||
|
||||
#include "../shared/eeprom_api.h"
|
||||
|
||||
size_t PersistentStore::capacity() {
|
||||
return MARLIN_EEPROM_SIZE;
|
||||
/* const uint8_t psz = NVMCTRL->SEESTAT.bit.PSZ,
|
||||
sblk = NVMCTRL->SEESTAT.bit.SBLK;
|
||||
|
||||
return (!psz && !sblk) ? 0
|
||||
: (psz <= 2) ? (0x200 << psz)
|
||||
: (sblk == 1 || psz == 3) ? 4096
|
||||
: (sblk == 2 || psz == 4) ? 8192
|
||||
: (sblk <= 4 || psz == 5) ? 16384
|
||||
: (sblk >= 9 && psz == 7) ? 65536
|
||||
: 32768;*/
|
||||
}
|
||||
|
||||
uint32_t PAGE_SIZE;
|
||||
uint32_t ROW_SIZE;
|
||||
bool hasWritten = false;
|
||||
uint8_t * buffer;
|
||||
|
||||
void _erase(const volatile void *flash_ptr) {
|
||||
NVMCTRL->ADDR.reg = ((uint32_t)flash_ptr) / 2;
|
||||
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_ER;
|
||||
while (!NVMCTRL->INTFLAG.bit.READY) { }
|
||||
|
||||
}
|
||||
|
||||
void erase(const volatile void *flash_ptr, uint32_t size) {
|
||||
const uint8_t *ptr = (const uint8_t *)flash_ptr;
|
||||
while (size > ROW_SIZE) {
|
||||
_erase(ptr);
|
||||
ptr += ROW_SIZE;
|
||||
size -= ROW_SIZE;
|
||||
}
|
||||
_erase(ptr);
|
||||
}
|
||||
|
||||
bool PersistentStore::access_start() {
|
||||
/* clear page buffer*/
|
||||
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_PBC;
|
||||
while (NVMCTRL->INTFLAG.bit.READY == 0) { }
|
||||
|
||||
PAGE_SIZE = pow(2,3 + NVMCTRL->PARAM.bit.PSZ);
|
||||
ROW_SIZE= PAGE_SIZE * 4;
|
||||
/*NVMCTRL->SEECFG.reg = NVMCTRL_SEECFG_WMODE_BUFFERED; // Buffered mode and segment reallocation active
|
||||
if (NVMCTRL->SEESTAT.bit.RLOCK)
|
||||
NVMCTRL_CMD(NVMCTRL_CTRLB_CMD_USEE); */ // Unlock E2P data write access
|
||||
// erase(&flashdata[0], TOTAL_FLASH_SIZE);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PersistentStore::access_finish() {
|
||||
if (hasWritten) {
|
||||
erase(&flashdata[0], TOTAL_FLASH_SIZE);
|
||||
|
||||
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_PBC;
|
||||
while (NVMCTRL->INTFLAG.bit.READY == 0) { }
|
||||
|
||||
NVMCTRL->CTRLB.bit.MANW = 0;
|
||||
|
||||
volatile uint32_t *dst_addr = (volatile uint32_t *) &flashdata;
|
||||
|
||||
uint32_t *pointer = (uint32_t *) buffer;
|
||||
for (uint32_t i = 0; i < TOTAL_FLASH_SIZE; i+=4) {
|
||||
|
||||
*dst_addr = (uint32_t) *pointer;
|
||||
pointer++;
|
||||
dst_addr ++;
|
||||
}
|
||||
|
||||
// Execute "WP" Write Page
|
||||
NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_WP;
|
||||
while (NVMCTRL->INTFLAG.bit.READY == 0) { }
|
||||
|
||||
free(buffer);
|
||||
hasWritten = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
|
||||
if (!hasWritten) {
|
||||
// init temp buffer
|
||||
buffer = (uint8_t *) malloc(MARLIN_EEPROM_SIZE);
|
||||
hasWritten=true;
|
||||
}
|
||||
|
||||
memcpy(buffer+pos,value,size);
|
||||
pos += size;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PersistentStore::read_data(int &pos, uint8_t *value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
|
||||
volatile uint8_t *dst_addr = (volatile uint8_t *) &flashdata;
|
||||
dst_addr += pos;
|
||||
|
||||
memcpy(value,(const void *) dst_addr,size);
|
||||
pos += size;
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // FLASH_EEPROM_EMULATION
|
||||
#endif // __SAMD21__
|
||||
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
#ifdef __SAMD21__
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#if ENABLED(QSPI_EEPROM)
|
||||
|
||||
#error "QSPI_EEPROM emulation Not implemented on SAMD21"
|
||||
|
||||
#include "../shared/eeprom_api.h"
|
||||
|
||||
#include "QSPIFlash.h"
|
||||
|
||||
static bool initialized;
|
||||
|
||||
size_t PersistentStore::capacity() { return qspi.size(); }
|
||||
|
||||
bool PersistentStore::access_start() {
|
||||
if (!initialized) {
|
||||
qspi.begin();
|
||||
initialized = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PersistentStore::access_finish() {
|
||||
qspi.flush();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
|
||||
while (size--) {
|
||||
const uint8_t v = *value;
|
||||
qspi.writeByte(pos, v);
|
||||
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*/) {
|
||||
while (size--) {
|
||||
uint8_t c = qspi.readByte(pos);
|
||||
if (writing) *value = c;
|
||||
crc16(crc, &c, 1);
|
||||
pos++;
|
||||
value++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // QSPI_EEPROM
|
||||
#endif // __SAMD21__
|
||||
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
#ifdef __SAMD21__
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#if USE_WIRED_EEPROM
|
||||
|
||||
#error "USE_WIRED_EEPROM emulation Not implemented on SAMD21"
|
||||
/**
|
||||
* PersistentStore for Arduino-style EEPROM interface
|
||||
* with simple implementations supplied by Marlin.
|
||||
*/
|
||||
|
||||
#include "../shared/eeprom_if.h"
|
||||
#include "../shared/eeprom_api.h"
|
||||
|
||||
#ifndef MARLIN_EEPROM_SIZE
|
||||
#error "MARLIN_EEPROM_SIZE is required for I2C / SPI EEPROM."
|
||||
#endif
|
||||
size_t PersistentStore::capacity() { return MARLIN_EEPROM_SIZE; }
|
||||
|
||||
bool PersistentStore::access_start() { eeprom_init(); return true; }
|
||||
bool PersistentStore::access_finish() { return true; }
|
||||
|
||||
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
|
||||
uint16_t written = 0;
|
||||
while (size--) {
|
||||
const uint8_t v = *value;
|
||||
uint8_t * const p = (uint8_t * const)pos;
|
||||
if (v != eeprom_read_byte(p)) { // EEPROM has only ~100,000 write cycles, so only write bytes that have changed!
|
||||
eeprom_write_byte(p, v);
|
||||
if (++written & 0x7F) delay(2); else safe_delay(2); // Avoid triggering watchdog during long EEPROM writes
|
||||
if (eeprom_read_byte(p) != v) {
|
||||
SERIAL_ECHO_MSG(STR_ERR_EEPROM_WRITE);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
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*/) {
|
||||
while (size--) {
|
||||
uint8_t c = eeprom_read_byte((uint8_t*)pos);
|
||||
if (writing) *value = c;
|
||||
crc16(crc, &c, 1);
|
||||
pos++;
|
||||
value++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // USE_WIRED_EEPROM
|
||||
#endif // __SAMD21__
|
||||
@@ -0,0 +1,253 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* 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
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Endstop interrupts for ATMEL SAMD21 based targets.
|
||||
*
|
||||
* On SAMD21, all pins support external interrupt capability.
|
||||
* Any pin can be used for external interrupts, but there are some restrictions.
|
||||
* At most 16 different external interrupts can be used at one time.
|
||||
* Further, you can’t just pick any 16 pins to use. This is because every pin on the SAMD21
|
||||
* connects to what is called an EXTINT line, and only one pin per EXTINT line can be used for external
|
||||
* interrupts at a time
|
||||
*/
|
||||
|
||||
/**
|
||||
* Endstop Interrupts
|
||||
*
|
||||
* Without endstop interrupts the endstop pins must be polled continually in
|
||||
* the temperature-ISR via endstops.update(), most of the time finding no change.
|
||||
* With this feature endstops.update() is called only when we know that at
|
||||
* least one endstop has changed state, saving valuable CPU cycles.
|
||||
*
|
||||
* This feature only works when all used endstop pins can generate an 'external interrupt'.
|
||||
*
|
||||
* Test whether pins issue interrupts on your board by flashing 'pin_interrupt_test.ino'.
|
||||
* (Located in Marlin/buildroot/share/pin_interrupt_test/pin_interrupt_test.ino)
|
||||
*/
|
||||
|
||||
#include "../../module/endstops.h"
|
||||
|
||||
#define MATCH_EILINE(P1,P2) (P1 != P2 && PIN_TO_EILINE(P1) == PIN_TO_EILINE(P2))
|
||||
#define MATCH_X_MAX_EILINE(P) TERN0(HAS_X_MAX, DEFER4(MATCH_EILINE)(P, X_MAX_PIN))
|
||||
#define MATCH_X_MIN_EILINE(P) TERN0(HAS_X_MIN, DEFER4(MATCH_EILINE)(P, X_MIN_PIN))
|
||||
#define MATCH_Y_MAX_EILINE(P) TERN0(HAS_Y_MAX, DEFER4(MATCH_EILINE)(P, Y_MAX_PIN))
|
||||
#define MATCH_Y_MIN_EILINE(P) TERN0(HAS_Y_MIN, DEFER4(MATCH_EILINE)(P, Y_MIN_PIN))
|
||||
#define MATCH_Z_MAX_EILINE(P) TERN0(HAS_Z_MAX, DEFER4(MATCH_EILINE)(P, Z_MAX_PIN))
|
||||
#define MATCH_Z_MIN_EILINE(P) TERN0(HAS_Z_MIN, DEFER4(MATCH_EILINE)(P, Z_MIN_PIN))
|
||||
#define MATCH_I_MAX_EILINE(P) TERN0(HAS_I_MAX, DEFER4(MATCH_EILINE)(P, I_MAX_PIN))
|
||||
#define MATCH_I_MIN_EILINE(P) TERN0(HAS_I_MIN, DEFER4(MATCH_EILINE)(P, I_MIN_PIN))
|
||||
#define MATCH_J_MAX_EILINE(P) TERN0(HAS_J_MAX, DEFER4(MATCH_EILINE)(P, J_MAX_PIN))
|
||||
#define MATCH_J_MIN_EILINE(P) TERN0(HAS_J_MIN, DEFER4(MATCH_EILINE)(P, J_MIN_PIN))
|
||||
#define MATCH_K_MAX_EILINE(P) TERN0(HAS_K_MAX, DEFER4(MATCH_EILINE)(P, K_MAX_PIN))
|
||||
#define MATCH_K_MIN_EILINE(P) TERN0(HAS_K_MIN, DEFER4(MATCH_EILINE)(P, K_MIN_PIN))
|
||||
#define MATCH_U_MAX_EILINE(P) TERN0(HAS_U_MAX, DEFER4(MATCH_EILINE)(P, U_MAX_PIN))
|
||||
#define MATCH_U_MIN_EILINE(P) TERN0(HAS_U_MIN, DEFER4(MATCH_EILINE)(P, U_MIN_PIN))
|
||||
#define MATCH_V_MAX_EILINE(P) TERN0(HAS_V_MAX, DEFER4(MATCH_EILINE)(P, V_MAX_PIN))
|
||||
#define MATCH_V_MIN_EILINE(P) TERN0(HAS_V_MIN, DEFER4(MATCH_EILINE)(P, V_MIN_PIN))
|
||||
#define MATCH_W_MAX_EILINE(P) TERN0(HAS_W_MAX, DEFER4(MATCH_EILINE)(P, W_MAX_PIN))
|
||||
#define MATCH_W_MIN_EILINE(P) TERN0(HAS_W_MIN, DEFER4(MATCH_EILINE)(P, W_MIN_PIN))
|
||||
#define MATCH_Z2_MAX_EILINE(P) TERN0(HAS_Z2_MAX, DEFER4(MATCH_EILINE)(P, Z2_MAX_PIN))
|
||||
#define MATCH_Z2_MIN_EILINE(P) TERN0(HAS_Z2_MIN, DEFER4(MATCH_EILINE)(P, Z2_MIN_PIN))
|
||||
#define MATCH_Z3_MAX_EILINE(P) TERN0(HAS_Z3_MAX, DEFER4(MATCH_EILINE)(P, Z3_MAX_PIN))
|
||||
#define MATCH_Z3_MIN_EILINE(P) TERN0(HAS_Z3_MIN, DEFER4(MATCH_EILINE)(P, Z3_MIN_PIN))
|
||||
#define MATCH_Z4_MAX_EILINE(P) TERN0(HAS_Z4_MAX, DEFER4(MATCH_EILINE)(P, Z4_MAX_PIN))
|
||||
#define MATCH_Z4_MIN_EILINE(P) TERN0(HAS_Z4_MIN, DEFER4(MATCH_EILINE)(P, Z4_MIN_PIN))
|
||||
#define MATCH_Z_MIN_PROBE_EILINE(P) TERN0(HAS_Z_MIN_PROBE_PIN, DEFER4(MATCH_EILINE)(P, Z_MIN_PROBE_PIN))
|
||||
|
||||
#define AVAILABLE_EILINE(P) ( PIN_TO_EILINE(P) != -1 \
|
||||
&& !MATCH_X_MAX_EILINE(P) && !MATCH_X_MIN_EILINE(P) \
|
||||
&& !MATCH_Y_MAX_EILINE(P) && !MATCH_Y_MIN_EILINE(P) \
|
||||
&& !MATCH_Z_MAX_EILINE(P) && !MATCH_Z_MIN_EILINE(P) \
|
||||
&& !MATCH_I_MAX_EILINE(P) && !MATCH_I_MIN_EILINE(P) \
|
||||
&& !MATCH_J_MAX_EILINE(P) && !MATCH_J_MIN_EILINE(P) \
|
||||
&& !MATCH_K_MAX_EILINE(P) && !MATCH_K_MIN_EILINE(P) \
|
||||
&& !MATCH_U_MAX_EILINE(P) && !MATCH_U_MIN_EILINE(P) \
|
||||
&& !MATCH_V_MAX_EILINE(P) && !MATCH_V_MIN_EILINE(P) \
|
||||
&& !MATCH_W_MAX_EILINE(P) && !MATCH_W_MIN_EILINE(P) \
|
||||
&& !MATCH_Z2_MAX_EILINE(P) && !MATCH_Z2_MIN_EILINE(P) \
|
||||
&& !MATCH_Z3_MAX_EILINE(P) && !MATCH_Z3_MIN_EILINE(P) \
|
||||
&& !MATCH_Z4_MAX_EILINE(P) && !MATCH_Z4_MIN_EILINE(P) \
|
||||
&& !MATCH_Z_MIN_PROBE_EILINE(P) )
|
||||
|
||||
// One ISR for all EXT-Interrupts
|
||||
void endstop_ISR() { endstops.update(); }
|
||||
|
||||
void setup_endstop_interrupts() {
|
||||
#define _ATTACH(P) attachInterrupt(P, endstop_ISR, CHANGE)
|
||||
#if HAS_X_MAX
|
||||
#if !AVAILABLE_EILINE(X_MAX_PIN)
|
||||
#error "X_MAX_PIN has no EXTINT line available."
|
||||
#endif
|
||||
_ATTACH(X_MAX_PIN);
|
||||
#endif
|
||||
#if HAS_X_MIN
|
||||
#if !AVAILABLE_EILINE(X_MIN_PIN)
|
||||
#error "X_MIN_PIN has no EXTINT line available."
|
||||
#endif
|
||||
_ATTACH(X_MIN_PIN);
|
||||
#endif
|
||||
#if HAS_Y_MAX
|
||||
#if !AVAILABLE_EILINE(Y_MAX_PIN)
|
||||
#error "Y_MAX_PIN has no EXTINT line available."
|
||||
#endif
|
||||
_ATTACH(Y_MAX_PIN);
|
||||
#endif
|
||||
#if HAS_Y_MIN
|
||||
#if !AVAILABLE_EILINE(Y_MIN_PIN)
|
||||
#error "Y_MIN_PIN has no EXTINT line available."
|
||||
#endif
|
||||
_ATTACH(Y_MIN_PIN);
|
||||
#endif
|
||||
#if HAS_Z_MAX
|
||||
#if !AVAILABLE_EILINE(Z_MAX_PIN)
|
||||
#error "Z_MAX_PIN has no EXTINT line available."
|
||||
#endif
|
||||
_ATTACH(Z_MAX_PIN);
|
||||
#endif
|
||||
#if HAS_Z_MIN
|
||||
#if !AVAILABLE_EILINE(Z_MIN_PIN)
|
||||
#error "Z_MIN_PIN has no EXTINT line available."
|
||||
#endif
|
||||
_ATTACH(Z_MIN_PIN);
|
||||
#endif
|
||||
#if HAS_Z2_MAX
|
||||
#if !AVAILABLE_EILINE(Z2_MAX_PIN)
|
||||
#error "Z2_MAX_PIN has no EXTINT line available."
|
||||
#endif
|
||||
_ATTACH(Z2_MAX_PIN);
|
||||
#endif
|
||||
#if HAS_Z2_MIN
|
||||
#if !AVAILABLE_EILINE(Z2_MIN_PIN)
|
||||
#error "Z2_MIN_PIN has no EXTINT line available."
|
||||
#endif
|
||||
_ATTACH(Z2_MIN_PIN);
|
||||
#endif
|
||||
#if HAS_Z3_MAX
|
||||
#if !AVAILABLE_EILINE(Z3_MAX_PIN)
|
||||
#error "Z3_MAX_PIN has no EXTINT line available."
|
||||
#endif
|
||||
_ATTACH(Z3_MAX_PIN);
|
||||
#endif
|
||||
#if HAS_Z3_MIN
|
||||
#if !AVAILABLE_EILINE(Z3_MIN_PIN)
|
||||
#error "Z3_MIN_PIN has no EXTINT line available."
|
||||
#endif
|
||||
_ATTACH(Z3_MIN_PIN);
|
||||
#endif
|
||||
#if HAS_Z4_MAX
|
||||
#if !AVAILABLE_EILINE(Z4_MAX_PIN)
|
||||
#error "Z4_MAX_PIN has no EXTINT line available."
|
||||
#endif
|
||||
_ATTACH(Z4_MAX_PIN);
|
||||
#endif
|
||||
#if HAS_Z4_MIN
|
||||
#if !AVAILABLE_EILINE(Z4_MIN_PIN)
|
||||
#error "Z4_MIN_PIN has no EXTINT line available."
|
||||
#endif
|
||||
_ATTACH(Z4_MIN_PIN);
|
||||
#endif
|
||||
#if HAS_Z_MIN_PROBE_PIN
|
||||
#if !AVAILABLE_EILINE(Z_MIN_PROBE_PIN)
|
||||
#error "Z_MIN_PROBE_PIN has no EXTINT line available."
|
||||
#endif
|
||||
_ATTACH(Z_MIN_PROBE_PIN);
|
||||
#endif
|
||||
#if HAS_I_MAX
|
||||
#if !AVAILABLE_EILINE(I_MAX_PIN)
|
||||
#error "I_MAX_PIN has no EXTINT line available."
|
||||
#endif
|
||||
attachInterrupt(I_MAX_PIN, endstop_ISR, CHANGE);
|
||||
#endif
|
||||
#if HAS_I_MIN
|
||||
#if !AVAILABLE_EILINE(I_MIN_PIN)
|
||||
#error "I_MIN_PIN has no EXTINT line available."
|
||||
#endif
|
||||
attachInterrupt(I_MIN_PIN, endstop_ISR, CHANGE);
|
||||
#endif
|
||||
#if HAS_J_MAX
|
||||
#if !AVAILABLE_EILINE(J_MAX_PIN)
|
||||
#error "J_MAX_PIN has no EXTINT line available."
|
||||
#endif
|
||||
attachInterrupt(J_MAX_PIN, endstop_ISR, CHANGE);
|
||||
#endif
|
||||
#if HAS_J_MIN
|
||||
#if !AVAILABLE_EILINE(J_MIN_PIN)
|
||||
#error "J_MIN_PIN has no EXTINT line available."
|
||||
#endif
|
||||
attachInterrupt(J_MIN_PIN, endstop_ISR, CHANGE);
|
||||
#endif
|
||||
#if HAS_K_MAX
|
||||
#if !AVAILABLE_EILINE(K_MAX_PIN)
|
||||
#error "K_MAX_PIN has no EXTINT line available."
|
||||
#endif
|
||||
attachInterrupt(K_MAX_PIN, endstop_ISR, CHANGE);
|
||||
#endif
|
||||
#if HAS_K_MIN
|
||||
#if !AVAILABLE_EILINE(K_MIN_PIN)
|
||||
#error "K_MIN_PIN has no EXTINT line available."
|
||||
#endif
|
||||
attachInterrupt(K_MIN_PIN, endstop_ISR, CHANGE);
|
||||
#endif
|
||||
#if HAS_U_MAX
|
||||
#if !AVAILABLE_EILINE(U_MAX_PIN)
|
||||
#error "U_MAX_PIN has no EXTINT line available."
|
||||
#endif
|
||||
attachInterrupt(U_MAX_PIN, endstop_ISR, CHANGE);
|
||||
#endif
|
||||
#if HAS_U_MIN
|
||||
#if !AVAILABLE_EILINE(U_MIN_PIN)
|
||||
#error "U_MIN_PIN has no EXTINT line available."
|
||||
#endif
|
||||
attachInterrupt(U_MIN_PIN, endstop_ISR, CHANGE);
|
||||
#endif
|
||||
#if HAS_V_MAX
|
||||
#if !AVAILABLE_EILINE(V_MAX_PIN)
|
||||
#error "V_MAX_PIN has no EXTINT line available."
|
||||
#endif
|
||||
attachInterrupt(V_MAX_PIN, endstop_ISR, CHANGE);
|
||||
#endif
|
||||
#if HAS_V_MIN
|
||||
#if !AVAILABLE_EILINE(V_MIN_PIN)
|
||||
#error "V_MIN_PIN has no EXTINT line available."
|
||||
#endif
|
||||
attachInterrupt(V_MIN_PIN, endstop_ISR, CHANGE);
|
||||
#endif
|
||||
#if HAS_W_MAX
|
||||
#if !AVAILABLE_EILINE(W_MAX_PIN)
|
||||
#error "W_MAX_PIN has no EXTINT line available."
|
||||
#endif
|
||||
attachInterrupt(W_MAX_PIN, endstop_ISR, CHANGE);
|
||||
#endif
|
||||
#if HAS_W_MIN
|
||||
#if !AVAILABLE_EILINE(W_MIN_PIN)
|
||||
#error "W_MIN_PIN has no EXTINT line available."
|
||||
#endif
|
||||
attachInterrupt(W_MIN_PIN, endstop_ISR, CHANGE);
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* 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
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fast IO functions for SAMD21
|
||||
*/
|
||||
|
||||
#include "SAMD21.h"
|
||||
|
||||
/**
|
||||
* Utility functions
|
||||
*/
|
||||
|
||||
#ifndef MASK
|
||||
#define MASK(PIN) _BV(PIN)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Magic I/O routines
|
||||
*
|
||||
* Now you can simply SET_OUTPUT(IO); WRITE(IO, HIGH); WRITE(IO, LOW);
|
||||
*/
|
||||
|
||||
// Read a pin
|
||||
#define READ(IO) ((PORT->Group[(EPortType)GET_SAMD_PORT(IO)].IN.reg & MASK(GET_SAMD_PIN(IO))) != 0)
|
||||
|
||||
// Write to a pin
|
||||
#define WRITE(IO,V) do{ \
|
||||
const EPortType port = (EPortType)GET_SAMD_PORT(IO); \
|
||||
const uint32_t mask = MASK(GET_SAMD_PIN(IO)); \
|
||||
\
|
||||
if (V) PORT->Group[port].OUTSET.reg = mask; \
|
||||
else PORT->Group[port].OUTCLR.reg = mask; \
|
||||
}while(0)
|
||||
|
||||
// Toggle a pin
|
||||
#define TOGGLE(IO) PORT->Group[(EPortType)GET_SAMD_PORT(IO)].OUTTGL.reg = MASK(GET_SAMD_PIN(IO));
|
||||
|
||||
// Set pin as input
|
||||
#define SET_INPUT(IO) do{ \
|
||||
const EPortType port = (EPortType)GET_SAMD_PORT(IO); \
|
||||
const uint32_t pin = GET_SAMD_PIN(IO); \
|
||||
\
|
||||
PORT->Group[port].PINCFG[pin].reg = (uint8_t)(PORT_PINCFG_INEN); \
|
||||
PORT->Group[port].DIRCLR.reg = MASK(pin); \
|
||||
}while(0)
|
||||
// Set pin as input with pullup
|
||||
#define SET_INPUT_PULLUP(IO) do{ \
|
||||
const EPortType port = (EPortType)GET_SAMD_PORT(IO); \
|
||||
const uint32_t pin = GET_SAMD_PIN(IO); \
|
||||
const uint32_t mask = MASK(pin); \
|
||||
\
|
||||
PORT->Group[port].PINCFG[pin].reg = (uint8_t)(PORT_PINCFG_INEN | PORT_PINCFG_PULLEN); \
|
||||
PORT->Group[port].DIRCLR.reg = mask; \
|
||||
PORT->Group[port].OUTSET.reg = mask; \
|
||||
}while(0)
|
||||
// Set pin as input with pulldown
|
||||
#define SET_INPUT_PULLDOWN(IO) do{ \
|
||||
const EPortType port = (EPortType)GET_SAMD_PORT(IO); \
|
||||
const uint32_t pin = GET_SAMD_PIN(IO); \
|
||||
const uint32_t mask = MASK(pin); \
|
||||
\
|
||||
PORT->Group[port].PINCFG[pin].reg = (uint8_t)(PORT_PINCFG_INEN | PORT_PINCFG_PULLEN); \
|
||||
PORT->Group[port].DIRCLR.reg = mask; \
|
||||
PORT->Group[port].OUTCLR.reg = mask; \
|
||||
}while(0)
|
||||
// Set pin as output (push pull)
|
||||
#define SET_OUTPUT(IO) do{ \
|
||||
const EPortType port = (EPortType)GET_SAMD_PORT(IO); \
|
||||
const uint32_t pin = GET_SAMD_PIN(IO); \
|
||||
\
|
||||
PORT->Group[port].DIRSET.reg = MASK(pin); \
|
||||
PORT->Group[port].PINCFG[pin].reg = 0; \
|
||||
}while(0)
|
||||
// Set pin as output (open drain)
|
||||
#define SET_OUTPUT_OD(IO) do{ \
|
||||
const EPortType port = (EPortType)GET_SAMD_PORT(IO); \
|
||||
const uint32_t pin = GET_SAMD_PIN(IO); \
|
||||
\
|
||||
PORT->Group[port].PINCFG[pin].reg = (uint8_t)(PORT_PINCFG_PULLEN); \
|
||||
PORT->Group[port].DIRCLR.reg = MASK(pin); \
|
||||
}while(0)
|
||||
// Set pin as PWM (push pull)
|
||||
#define SET_PWM SET_OUTPUT
|
||||
// Set pin as PWM (open drain)
|
||||
#define SET_PWM_OD SET_OUTPUT_OD
|
||||
|
||||
// check if pin is an output
|
||||
#define IS_OUTPUT(IO) ((PORT->Group[(EPortType)GET_SAMD_PORT(IO)].DIR.reg & MASK(GET_SAMD_PIN(IO))) \
|
||||
|| (PORT->Group[(EPortType)GET_SAMD_PORT(IO)].PINCFG[GET_SAMD_PIN(IO)].reg & (PORT_PINCFG_INEN | PORT_PINCFG_PULLEN)) == PORT_PINCFG_PULLEN)
|
||||
// check if pin is an input
|
||||
#define IS_INPUT(IO) !IS_OUTPUT(IO)
|
||||
|
||||
// Shorthand
|
||||
#define OUT_WRITE(IO,V) do{ SET_OUTPUT(IO); WRITE(IO,V); }while(0)
|
||||
#define OUT_WRITE_OD(IO,V) do{ SET_OUTPUT_OD(IO); WRITE(IO,V); }while(0)
|
||||
|
||||
// digitalRead/Write wrappers
|
||||
#define extDigitalRead(IO) digitalRead(IO)
|
||||
#define extDigitalWrite(IO,V) digitalWrite(IO,V)
|
||||
|
||||
/**
|
||||
* Ports and functions
|
||||
* Added as necessary or if I feel like it- not a comprehensive list!
|
||||
*/
|
||||
|
||||
/*
|
||||
* Some of these share the same source and so can't be used in the same time
|
||||
*/
|
||||
#define PWM_PIN(P) (WITHIN(P, 2, 13) || WITHIN(P, 22, 23) || WITHIN(P, 44, 45) || P == 48)
|
||||
|
||||
// Return fulfilled ADCx->INPUTCTRL.reg
|
||||
#define PIN_TO_INPUTCTRL(P) ( (P == 0) ? ADC_INPUTCTRL_MUXPOS_PIN0 \
|
||||
: ((P) == 1) ? ADC_INPUTCTRL_MUXPOS_PIN1 \
|
||||
: ((P) == 2) ? ADC_INPUTCTRL_MUXPOS_PIN3 \
|
||||
: ((P) == 3) ? ADC_INPUTCTRL_MUXPOS_PIN4 \
|
||||
: ((P) == 4) ? ADC_INPUTCTRL_MUXPOS_PIN5 \
|
||||
: ((P) == 5) ? ADC_INPUTCTRL_MUXPOS_PIN5 \
|
||||
: ((P) == 6) ? ADC_INPUTCTRL_MUXPOS_PIN6 \
|
||||
: ((P) == 7) ? ADC_INPUTCTRL_MUXPOS_PIN7 \
|
||||
: ((P) == 8) ? ADC_INPUTCTRL_MUXPOS_PIN8 \
|
||||
: ((P) == 9) ? ADC_INPUTCTRL_MUXPOS_PIN9 \
|
||||
: ((P) == 10) ? ADC_INPUTCTRL_MUXPOS_PIN10 \
|
||||
: ((P) == 11) ? ADC_INPUTCTRL_MUXPOS_PIN11 \
|
||||
: ((P) == 12) ? ADC_INPUTCTRL_MUXPOS_PIN12 \
|
||||
: ((P) == 13) ? ADC_INPUTCTRL_MUXPOS_PIN13 \
|
||||
: ((P) == 14) ? ADC_INPUTCTRL_MUXPOS_PIN14 \
|
||||
: ADC_INPUTCTRL_MUXPOS_PIN15)
|
||||
|
||||
#define digitalPinToAnalogInput(P) (WITHIN(P, 67, 74) ? (P) - 67 : WITHIN(P, 54, 61) ? 8 + (P) - 54 : WITHIN(P, 12, 13) ? 16 + (P) - 12 : P == 9 ? 18 : -1)
|
||||
|
||||
/**
|
||||
* pins
|
||||
*/
|
||||
|
||||
// PORTA
|
||||
#define DIO28_PIN PIN_PA02 // A0
|
||||
#define DIO56_PIN PIN_PA03 // A13
|
||||
#define DIO31_PIN PIN_PA04 // A13
|
||||
#define DIO32_PIN PIN_PA05 // A1
|
||||
#define DIO8_PIN PIN_PA06 // A14
|
||||
#define DIO9_PIN PIN_PA07 // A15
|
||||
#define DIO4_PIN PIN_PA08 // A15
|
||||
#define DIO3_PIN PIN_PA09 // A15
|
||||
#define DIO1_PIN PIN_PA10
|
||||
#define DIO0_PIN PIN_PA11
|
||||
#define DIO18_PIN PIN_PA12
|
||||
#define DIO52_PIN PIN_PA13
|
||||
#define DIO2_PIN PIN_PA14
|
||||
#define DIO5_PIN PIN_PA15
|
||||
#define DIO11_PIN PIN_PA16
|
||||
#define DIO13_PIN PIN_PA17
|
||||
#define DIO10_PIN PIN_PA18
|
||||
#define DIO12_PIN PIN_PA19
|
||||
#define DIO6_PIN PIN_PA20
|
||||
#define DIO07_PIN PIN_PA21
|
||||
#define DIO34_PIN PIN_PA22
|
||||
#define DIO35_PIN PIN_PA23
|
||||
#define DIO42_PIN PIN_PA24
|
||||
#define DIO43_PIN PIN_PA25
|
||||
|
||||
#define DIO40_PIN PIN_PA27
|
||||
|
||||
#define DIO26_PIN PIN_PB00
|
||||
#define DIO27_PIN PIN_PB01 // A0
|
||||
#define DIO33_PIN PIN_PB02
|
||||
#define DIO39_PIN PIN_PB03
|
||||
#define DIO14_PIN PIN_PB04
|
||||
#define DIO15_PIN PIN_PB05
|
||||
#define DIO16_PIN PIN_PB06
|
||||
#define DIO17_PIN PIN_PB07
|
||||
#define DIO29_PIN PIN_PB08
|
||||
#define DIO30_PIN PIN_PB09
|
||||
#define DIO37_PIN PIN_PB10
|
||||
#define DIO38_PIN PIN_PB11
|
||||
#define DIO36_PIN PIN_PB12
|
||||
#define DIO19_PIN PIN_PB13
|
||||
#define DIO20_PIN PIN_PB14
|
||||
#define DIO21_PIN PIN_PB15
|
||||
#define DIO22_PIN PIN_PB16
|
||||
#define DIO23_PIN PIN_PB17
|
||||
|
||||
#define DIO44_PIN PIN_PB22
|
||||
#define DIO45_PIN PIN_PB23
|
||||
#define DIO24_PIN PIN_PB30
|
||||
#define DIO25_PIN PIN_PB31
|
||||
|
||||
#define DIO53_PIN PIN_PA21
|
||||
#define DIO54_PIN PIN_PA06
|
||||
#define DIO55_PIN PIN_PA07
|
||||
|
||||
+9
-12
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
* Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
@@ -19,16 +19,13 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "HAL.h"
|
||||
|
||||
// Arduino Due core now has watchdog support
|
||||
|
||||
void watchdog_init();
|
||||
|
||||
inline void HAL_watchdog_refresh() {
|
||||
// Watchdog refresh sequence
|
||||
WDOG_REFRESH = 0xA602;
|
||||
WDOG_REFRESH = 0xB480;
|
||||
}
|
||||
#if HAS_SPI_TFT || HAS_FSMC_TFT
|
||||
#error "Sorry! TFT displays are not available for HAL/SAMD21."
|
||||
#endif
|
||||
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
#pragma once
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#if USE_FALLBACK_EEPROM
|
||||
#define FLASH_EEPROM_EMULATION
|
||||
#elif EITHER(I2C_EEPROM, SPI_EEPROM)
|
||||
#define USE_SHARED_EEPROM 1
|
||||
#endif
|
||||
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
|
||||
/**
|
||||
* Test SAMD21 specific configuration values for errors at compile-time.
|
||||
*/
|
||||
|
||||
#if SERVO_TC == MF_TIMER_RTC
|
||||
#error "Servos can't use RTC timer"
|
||||
#endif
|
||||
|
||||
#if ENABLED(EMERGENCY_PARSER)
|
||||
#error "EMERGENCY_PARSER is not yet implemented for SAMD21. Disable EMERGENCY_PARSER to continue."
|
||||
#endif
|
||||
|
||||
#if ENABLED(SDIO_SUPPORT)
|
||||
#error "SDIO_SUPPORT is not supported on SAMD21."
|
||||
#endif
|
||||
|
||||
#if ENABLED(FAST_PWM_FAN)
|
||||
#error "Features requiring Hardware PWM (FAST_PWM_FAN) are not yet supported on SAMD21."
|
||||
#endif
|
||||
|
||||
#if ENABLED(POSTMORTEM_DEBUGGING)
|
||||
#error "POSTMORTEM_DEBUGGING is not yet supported on SAMD21."
|
||||
#endif
|
||||
@@ -0,0 +1,160 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* 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
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
|
||||
#define NUMBER_PINS_TOTAL PINS_COUNT
|
||||
|
||||
#define digitalRead_mod(p) extDigitalRead(p)
|
||||
#define PRINT_PORT(p) do{ SERIAL_ECHOPGM(" Port: "); sprintf_P(buffer, PSTR("%c%02ld"), 'A' + g_APinDescription[p].ulPort, g_APinDescription[p].ulPin); 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("%3d "), p); SERIAL_ECHO(buffer); }while(0)
|
||||
#define PRINT_PIN_ANALOG(p) do{ sprintf_P(buffer, PSTR(" (A%2d) "), DIGITAL_PIN_TO_ANALOG_PIN(pin)); SERIAL_ECHO(buffer); }while(0)
|
||||
#define GET_ARRAY_PIN(p) pin_array[p].pin
|
||||
#define GET_ARRAY_IS_DIGITAL(p) pin_array[p].is_digital
|
||||
#define VALID_PIN(pin) (pin >= 0 && pin < (int8_t)NUMBER_PINS_TOTAL)
|
||||
#define DIGITAL_PIN_TO_ANALOG_PIN(p) digitalPinToAnalogInput(p)
|
||||
#define IS_ANALOG(P) (DIGITAL_PIN_TO_ANALOG_PIN(P)!=-1)
|
||||
#define pwm_status(pin) digitalPinHasPWM(pin)
|
||||
#define MULTI_NAME_PAD 27 // space needed to be pretty if not first name assigned to a pin
|
||||
|
||||
// pins that will cause hang/reset/disconnect in M43 Toggle and Watch utilities
|
||||
// uses pin index
|
||||
#define M43_NEVER_TOUCH(Q) ((Q) >= 75)
|
||||
|
||||
bool GET_PINMODE(int8_t pin) { // 1: output, 0: input
|
||||
const EPortType samdport = g_APinDescription[pin].ulPort;
|
||||
const uint32_t samdpin = g_APinDescription[pin].ulPin;
|
||||
return PORT->Group[samdport].DIR.reg & MASK(samdpin) || (PORT->Group[samdport].PINCFG[samdpin].reg & (PORT_PINCFG_INEN | PORT_PINCFG_PULLEN)) == PORT_PINCFG_PULLEN;
|
||||
}
|
||||
|
||||
void pwm_details(int32_t pin) {
|
||||
if (pwm_status(pin)) {
|
||||
//uint32_t chan = g_APinDescription[pin].ulPWMChannel TODO when fast pwm is operative;
|
||||
//SERIAL_ECHOPGM("PWM = ", duty);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* SAMD21 Board pin| PORT | Label
|
||||
* ----------------+--------+-------
|
||||
* 0 | PB25 | "RX0"
|
||||
* 1 | PB24 | "TX0"
|
||||
* 2 | PC18 |
|
||||
* 3 | PC19 |
|
||||
* 4 | PC20 |
|
||||
* 5 | PC21 |
|
||||
* 6 | PD20 |
|
||||
* 7 | PD21 |
|
||||
* 8 | PB18 |
|
||||
* 9 | PB2 |
|
||||
* 10 | PB22 |
|
||||
* 11 | PB23 |
|
||||
* 12 | PB0 | "A16"
|
||||
* 13 | PB1 | LED AMBER "L" / "A17"
|
||||
* 14 | PB16 | "TX3"
|
||||
* 15 | PB17 | "RX3"
|
||||
* 16 | PC22 | "TX2"
|
||||
* 17 | PC23 | "RX2"
|
||||
* 18 | PB12 | "TX1" / "A18"
|
||||
* 19 | PB13 | "RX1"
|
||||
* 20 | PB20 | "SDA"
|
||||
* 21 | PB21 | "SCL"
|
||||
* 22 | PD12 |
|
||||
* 23 | PA15 |
|
||||
* 24 | PC17 |
|
||||
* 25 | PC16 |
|
||||
* 26 | PA12 |
|
||||
* 27 | PA13 |
|
||||
* 28 | PA14 |
|
||||
* 29 | PB19 |
|
||||
* 30 | PA23 |
|
||||
* 31 | PA22 |
|
||||
* 32 | PA21 |
|
||||
* 33 | PA20 |
|
||||
* 34 | PA19 |
|
||||
* 35 | PA18 |
|
||||
* 36 | PA17 |
|
||||
* 37 | PA16 |
|
||||
* 38 | PB15 |
|
||||
* 39 | PB14 |
|
||||
* 40 | PC13 |
|
||||
* 41 | PC12 |
|
||||
* 42 | PC15 |
|
||||
* 43 | PC14 |
|
||||
* 44 | PC11 |
|
||||
* 45 | PC10 |
|
||||
* 46 | PC6 |
|
||||
* 47 | PC7 |
|
||||
* 48 | PC4 |
|
||||
* 49 | PC5 |
|
||||
* 50 | PD11 |
|
||||
* 51 | PD8 |
|
||||
* 52 | PD9 |
|
||||
* 53 | PD10 |
|
||||
* 54 | PB5 | "A8"
|
||||
* 55 | PB6 | "A9"
|
||||
* 56 | PB7 | "A10"
|
||||
* 57 | PB8 | "A11"
|
||||
* 58 | PB9 | "A12"
|
||||
* 69 | PA4 | "A13"
|
||||
* 60 | PA6 | "A14"
|
||||
* 61 | PA7 | "A15"
|
||||
* 62 | PB17 |
|
||||
* 63 | PB20 |
|
||||
* 64 | PD11 |
|
||||
* 65 | PD8 |
|
||||
* 66 | PD9 |
|
||||
* 67 | PA2 | "A0" / "DAC0"
|
||||
* 68 | PA5 | "A1" / "DAC1"
|
||||
* 69 | PB3 | "A2"
|
||||
* 70 | PC0 | "A3"
|
||||
* 71 | PC1 | "A4"
|
||||
* 72 | PC2 | "A5"
|
||||
* 73 | PC3 | "A6"
|
||||
* 74 | PB4 | "A7"
|
||||
* 75 | PC31 | LED GREEN "RX"
|
||||
* 76 | PC30 | LED GREEN "TX"
|
||||
* 77 | PA27 | USB: Host enable
|
||||
* 78 | PA24 | USB: D-
|
||||
* 79 | PA25 | USB: D+
|
||||
* 80 | PB29 | SD: MISO
|
||||
* 81 | PB27 | SD: SCK
|
||||
* 82 | PB26 | SD: MOSI
|
||||
* 83 | PB28 | SD: CS
|
||||
* 84 | PA3 | AREF
|
||||
* 85 | PA2 | DAC0 (Duplicate)
|
||||
* 86 | PA5 | DAC1 (Duplicate)
|
||||
* 87 | PB1 | LED AMBER "L" (Duplicate)
|
||||
* 88 | PC24 | NeoPixel
|
||||
* 89 | PB10 | QSPI: SCK
|
||||
* 90 | PB11 | QSPI: CS
|
||||
* 91 | PA8 | QSPI: IO0
|
||||
* 92 | PA9 | QSPI: IO1
|
||||
* 93 | PA10 | QSPI: IO2
|
||||
* 94 | PA11 | QSPI: IO3
|
||||
* 95 | PB31 | SD: DETECT
|
||||
*/
|
||||
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* 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
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
|
||||
/**
|
||||
* SAMD21 Default SPI Pins
|
||||
*
|
||||
* SS SCK MISO MOSI
|
||||
* +-------------------------+
|
||||
* SPI | 53 52 50 51 |
|
||||
* SPI1 | 83 81 80 82 |
|
||||
* +-------------------------+
|
||||
* Any pin can be used for Chip Select (SD_SS_PIN)
|
||||
*/
|
||||
#ifndef SD_SCK_PIN
|
||||
#define SD_SCK_PIN 38
|
||||
#endif
|
||||
#ifndef SD_MISO_PIN
|
||||
#define SD_MISO_PIN 36
|
||||
#endif
|
||||
#ifndef SD_MOSI_PIN
|
||||
#define SD_MOSI_PIN 37
|
||||
#endif
|
||||
#ifndef SDSS
|
||||
#define SDSS 18
|
||||
#endif
|
||||
|
||||
#ifndef SD_SS_PIN
|
||||
#define SD_SS_PIN SDSS
|
||||
#endif
|
||||
@@ -0,0 +1,217 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
#ifdef __SAMD21__
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Includes
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
#include "ServoTimers.h" // for SERVO_TC
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Local defines
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
#define NUM_HARDWARE_TIMERS 9
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Private Variables
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
const tTimerConfig timer_config[NUM_HARDWARE_TIMERS] = {
|
||||
{ {.pTcc=TCC0}, TimerType::tcc, TCC0_IRQn, TC_PRIORITY(0) }, // 0 - stepper (assigned priority 2)
|
||||
{ {.pTcc=TCC1}, TimerType::tcc, TCC1_IRQn, TC_PRIORITY(1) }, // 1 - stepper (needed by 32 bit timers)
|
||||
{ {.pTcc=TCC2}, TimerType::tcc, TCC2_IRQn, 5 }, // 2 - tone (reserved by framework and fixed assigned priority 5)
|
||||
{ {.pTc=TC3}, TimerType::tc, TC3_IRQn, TC_PRIORITY(3) }, // 3 - servo (assigned priority 1)
|
||||
{ {.pTc=TC4}, TimerType::tc, TC4_IRQn, TC_PRIORITY(4) }, // 4 - software serial (no interrupts used)
|
||||
{ {.pTc=TC5}, TimerType::tc, TC5_IRQn, TC_PRIORITY(5) },
|
||||
{ {.pTc=TC6}, TimerType::tc, TC6_IRQn, TC_PRIORITY(6) },
|
||||
{ {.pTc=TC7}, TimerType::tc, TC7_IRQn, TC_PRIORITY(7) },
|
||||
{ {.pRtc=RTC}, TimerType::rtc, RTC_IRQn, TC_PRIORITY(8) } // 8 - temperature (assigned priority 6)
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Private functions
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
FORCE_INLINE void Disable_Irq(IRQn_Type irq) {
|
||||
NVIC_DisableIRQ(irq);
|
||||
|
||||
// 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();
|
||||
}
|
||||
|
||||
static bool tcIsSyncing(Tc * tc) {
|
||||
return tc->COUNT32.STATUS.reg & TC_STATUS_SYNCBUSY;
|
||||
}
|
||||
|
||||
static void tcReset( Tc * tc) {
|
||||
tc->COUNT32.CTRLA.reg = TC_CTRLA_SWRST;
|
||||
while (tcIsSyncing(tc)) {}
|
||||
while (tc->COUNT32.CTRLA.bit.SWRST) {}
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Public functions
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
|
||||
IRQn_Type irq = timer_config[timer_num].IRQ_Id;
|
||||
|
||||
// Disable interrupt, just in case it was already enabled
|
||||
NVIC_DisableIRQ(irq);
|
||||
NVIC_ClearPendingIRQ(irq);
|
||||
|
||||
if (timer_num == MF_TIMER_RTC) {
|
||||
|
||||
// https://github.com/arduino-libraries/RTCZero
|
||||
Rtc * const rtc = timer_config[timer_num].pRtc;
|
||||
PM->APBAMASK.reg |= PM_APBAMASK_RTC;
|
||||
|
||||
GCLK->CLKCTRL.reg = (uint32_t)((GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK4 | (RTC_GCLK_ID << GCLK_CLKCTRL_ID_Pos)));
|
||||
while (GCLK->STATUS.bit.SYNCBUSY) {}
|
||||
|
||||
GCLK->GENCTRL.reg = (GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSCULP32K | GCLK_GENCTRL_ID(4) | GCLK_GENCTRL_DIVSEL );
|
||||
while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) {}
|
||||
|
||||
GCLK->GENDIV.reg = GCLK_GENDIV_ID(4);
|
||||
GCLK->GENDIV.bit.DIV=4;
|
||||
while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY) {}
|
||||
|
||||
// Disable timer interrupt
|
||||
rtc->MODE0.INTENCLR.reg = RTC_MODE0_INTENCLR_CMP0;
|
||||
SYNC(rtc->MODE0.STATUS.bit.SYNCBUSY);
|
||||
|
||||
while(rtc->MODE0.STATUS.bit.SYNCBUSY) {}
|
||||
|
||||
// Stop timer, just in case, to be able to reconfigure it
|
||||
rtc->MODE0.CTRL.reg =
|
||||
RTC_MODE0_CTRL_MODE_COUNT32 | // Mode 0 = 32-bits counter
|
||||
RTC_MODE0_CTRL_PRESCALER_DIV1024; // Divisor = 1024
|
||||
|
||||
while(rtc->MODE0.STATUS.bit.SYNCBUSY) {}
|
||||
|
||||
// Mode, reset counter on match
|
||||
rtc->MODE0.CTRL.reg = RTC_MODE0_CTRL_MODE_COUNT32 | RTC_MODE0_CTRL_MATCHCLR;
|
||||
|
||||
// Set compare value
|
||||
rtc->MODE0.COMP[0].reg = (32768 + frequency / 2) / frequency;
|
||||
SYNC(rtc->MODE0.STATUS.bit.SYNCBUSY);
|
||||
|
||||
// Enable interrupt on compare
|
||||
rtc->MODE0.INTFLAG.reg = RTC_MODE0_INTFLAG_CMP0; // reset pending interrupt
|
||||
rtc->MODE0.INTENSET.reg = RTC_MODE0_INTENSET_CMP0; // enable compare 0 interrupt
|
||||
|
||||
// And start timer
|
||||
rtc->MODE0.CTRL.bit.ENABLE = true;
|
||||
SYNC(rtc->MODE0.STATUS.bit.SYNCBUSY);
|
||||
|
||||
}
|
||||
else if (timer_config[timer_num].type==TimerType::tcc) {
|
||||
|
||||
Tcc * const tc = timer_config[timer_num].pTcc;
|
||||
|
||||
PM->APBCMASK.reg |= PM_APBCMASK_TCC0;
|
||||
GCLK->CLKCTRL.reg =(GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(TCC0_GCLK_ID));
|
||||
SYNC (GCLK->STATUS.bit.SYNCBUSY);
|
||||
|
||||
tc->CTRLA.reg = TCC_CTRLA_SWRST;
|
||||
SYNC (tc->SYNCBUSY.reg & TCC_SYNCBUSY_SWRST) {}
|
||||
|
||||
SYNC (tc->CTRLA.bit.SWRST);
|
||||
|
||||
tc->CTRLA.reg &= ~(TCC_CTRLA_ENABLE); // disable TC module
|
||||
|
||||
tc->CTRLA.reg |= TCC_WAVE_WAVEGEN_MFRQ;
|
||||
tc->CTRLA.reg |= TCC_CTRLA_PRESCALER_DIV2;
|
||||
tc->CC[0].reg = (HAL_TIMER_RATE) / frequency;
|
||||
tc->INTENSET.reg = TCC_INTFLAG_MC0;
|
||||
tc->CTRLA.reg |= TCC_CTRLA_ENABLE;
|
||||
tc->INTFLAG.reg = 0xFF;
|
||||
SYNC ( tc->STATUS.reg & TC_STATUS_SYNCBUSY);
|
||||
|
||||
}
|
||||
else {
|
||||
Tc * const tc = timer_config[timer_num].pTc;
|
||||
|
||||
// Disable timer interrupt
|
||||
tc->COUNT32.INTENCLR.reg = TC_INTENCLR_OVF; // disable overflow interrupt
|
||||
|
||||
// TCn clock setup
|
||||
GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCM_TC4_TC5)) ;
|
||||
SYNC (GCLK->STATUS.bit.SYNCBUSY);
|
||||
|
||||
tcReset(tc); // reset TC
|
||||
|
||||
// Set Timer counter 5 Mode to 16 bits, it will become a 16bit counter ('mode1' in the datasheet)
|
||||
tc->COUNT32.CTRLA.reg |= TC_CTRLA_MODE_COUNT32;
|
||||
// Set TC waveform generation mode to 'match frequency'
|
||||
tc->COUNT32.CTRLA.reg |= TC_CTRLA_WAVEGEN_MFRQ;
|
||||
//set prescaler
|
||||
//the clock normally counts at the GCLK_TC frequency, but we can set it to divide that frequency to slow it down
|
||||
//you can use different prescaler divisons here like TC_CTRLA_PRESCALER_DIV1 to get a different range
|
||||
tc->COUNT32.CTRLA.reg |= TC_CTRLA_PRESCALER_DIV1 | TC_CTRLA_ENABLE; //it will divide GCLK_TC frequency by 1024
|
||||
//set the compare-capture register.
|
||||
//The counter will count up to this value (it's a 16bit counter so we use uint16_t)
|
||||
//this is how we fine-tune the frequency, make it count to a lower or higher value
|
||||
//system clock should be 1MHz (8MHz/8) at Reset by default
|
||||
tc->COUNT32.CC[0].reg = (uint16_t) (HAL_TIMER_RATE / frequency);
|
||||
while (tcIsSyncing(tc)) {}
|
||||
|
||||
// Enable the TC interrupt request
|
||||
tc->COUNT32.INTENSET.bit.MC0 = 1;
|
||||
while (tcIsSyncing(tc)) {}
|
||||
}
|
||||
|
||||
NVIC_SetPriority(irq, timer_config[timer_num].priority);
|
||||
NVIC_EnableIRQ(irq);
|
||||
}
|
||||
|
||||
void HAL_timer_enable_interrupt(const uint8_t timer_num) {
|
||||
const IRQn_Type irq = timer_config[timer_num].IRQ_Id;
|
||||
NVIC_EnableIRQ(irq);
|
||||
}
|
||||
|
||||
void HAL_timer_disable_interrupt(const uint8_t timer_num) {
|
||||
const IRQn_Type irq = timer_config[timer_num].IRQ_Id;
|
||||
Disable_Irq(irq);
|
||||
}
|
||||
|
||||
// missing from CMSIS: Check if interrupt is enabled or not
|
||||
static bool NVIC_GetEnabledIRQ(IRQn_Type IRQn) {
|
||||
return TEST(NVIC->ISER[uint32_t(IRQn) >> 5], uint32_t(IRQn) & 0x1F);
|
||||
}
|
||||
|
||||
bool HAL_timer_interrupt_enabled(const uint8_t timer_num) {
|
||||
const IRQn_Type irq = timer_config[timer_num].IRQ_Id;
|
||||
return NVIC_GetEnabledIRQ(irq);
|
||||
}
|
||||
|
||||
#endif // __SAMD21__
|
||||
@@ -0,0 +1,160 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2022 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* 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
|
||||
|
||||
/**
|
||||
* SAMD21 HAL developed by Bart Meijer (brupje)
|
||||
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Defines
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
typedef uint32_t hal_timer_t;
|
||||
#define HAL_TIMER_TYPE_MAX 0xFFFFFFFF
|
||||
|
||||
#define HAL_TIMER_RATE F_CPU // frequency of timers peripherals
|
||||
|
||||
#define MF_TIMER_RTC 8 // This is not a TC but a RTC
|
||||
|
||||
#ifndef MF_TIMER_STEP
|
||||
#define MF_TIMER_STEP 4 // Timer Index for Stepper
|
||||
#endif
|
||||
#ifndef MF_TIMER_PULSE
|
||||
#define MF_TIMER_PULSE MF_TIMER_STEP
|
||||
#endif
|
||||
#ifndef MF_TIMER_TEMP
|
||||
#define MF_TIMER_TEMP MF_TIMER_RTC // Timer Index for Temperature
|
||||
#endif
|
||||
|
||||
#define TEMP_TIMER_FREQUENCY 1000 // temperature interrupt frequency
|
||||
|
||||
#define STEPPER_TIMER_RATE HAL_TIMER_RATE // frequency of stepper timer (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE)
|
||||
#define STEPPER_TIMER_TICKS_PER_US (STEPPER_TIMER_RATE / 1000000) // stepper timer ticks per µs
|
||||
#define STEPPER_TIMER_PRESCALE (CYCLES_PER_MICROSECOND / STEPPER_TIMER_TICKS_PER_US)
|
||||
|
||||
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE
|
||||
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
|
||||
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
|
||||
|
||||
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_STEP)
|
||||
#define DISABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_STEP)
|
||||
#define STEPPER_ISR_ENABLED() HAL_timer_interrupt_enabled(MF_TIMER_STEP)
|
||||
|
||||
#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(MF_TIMER_TEMP)
|
||||
#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(MF_TIMER_TEMP)
|
||||
|
||||
#define TC_PRIORITY(t) ( t == SERVO_TC ? 1 \
|
||||
: (t == MF_TIMER_STEP || t == MF_TIMER_PULSE) ? 2 \
|
||||
: (t == MF_TIMER_TEMP) ? 6 : 7 )
|
||||
|
||||
#define _TC_HANDLER(t) void TC##t##_Handler()
|
||||
#define TC_HANDLER(t) _TC_HANDLER(t)
|
||||
#ifndef HAL_STEP_TIMER_ISR
|
||||
#define HAL_STEP_TIMER_ISR() TC_HANDLER(MF_TIMER_STEP)
|
||||
#endif
|
||||
#if MF_TIMER_STEP != MF_TIMER_PULSE
|
||||
#define HAL_PULSE_TIMER_ISR() TC_HANDLER(MF_TIMER_PULSE)
|
||||
#endif
|
||||
#if MF_TIMER_TEMP == MF_TIMER_RTC
|
||||
#define HAL_TEMP_TIMER_ISR() void RTC_Handler()
|
||||
#else
|
||||
#define HAL_TEMP_TIMER_ISR() TC_HANDLER(MF_TIMER_TEMP)
|
||||
#endif
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Types
|
||||
// --------------------------------------------------------------------------
|
||||
typedef enum { tcc, tc, rtc } TimerType;
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
Tc *pTc;
|
||||
Tcc *pTcc;
|
||||
Rtc *pRtc;
|
||||
};
|
||||
TimerType type;
|
||||
IRQn_Type IRQ_Id;
|
||||
uint8_t priority;
|
||||
} tTimerConfig;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Public Variables
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
extern const tTimerConfig timer_config[];
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Public functions
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
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) {
|
||||
// Should never be called with timer MF_TIMER_RTC
|
||||
Tc * const tc = timer_config[timer_num].pTc;
|
||||
tc->COUNT32.CC[0].reg = compare;
|
||||
}
|
||||
|
||||
FORCE_INLINE static hal_timer_t HAL_timer_get_compare(const uint8_t timer_num) {
|
||||
// Should never be called with timer MF_TIMER_RTC
|
||||
Tc * const tc = timer_config[timer_num].pTc;
|
||||
return (hal_timer_t)tc->COUNT32.CC[0].reg;
|
||||
}
|
||||
|
||||
FORCE_INLINE static hal_timer_t HAL_timer_get_count(const uint8_t timer_num) {
|
||||
// Should never be called with timer MF_TIMER_RTC
|
||||
Tc * const tc = timer_config[timer_num].pTc;
|
||||
tc->COUNT32.READREQ.reg = TC_READREQ_RREQ;
|
||||
// Request a read synchronization
|
||||
SYNC (tc->COUNT32.STATUS.bit.SYNCBUSY);
|
||||
//SYNC(tc->COUNT32.STATUS.bit.SYNCBUSY );
|
||||
return tc->COUNT32.COUNT.reg;
|
||||
}
|
||||
|
||||
void HAL_timer_enable_interrupt(const uint8_t timer_num);
|
||||
void HAL_timer_disable_interrupt(const uint8_t timer_num);
|
||||
bool HAL_timer_interrupt_enabled(const uint8_t timer_num);
|
||||
|
||||
FORCE_INLINE static void HAL_timer_isr_prologue(const uint8_t timer_num) {
|
||||
if (timer_num == MF_TIMER_RTC) {
|
||||
Rtc * const rtc = timer_config[timer_num].pRtc;
|
||||
// Clear interrupt flag
|
||||
rtc->MODE0.INTFLAG.reg = RTC_MODE0_INTFLAG_CMP0| RTC_MODE0_INTFLAG_OVF;
|
||||
|
||||
}
|
||||
else if (timer_config[timer_num].type == TimerType::tcc){
|
||||
Tcc * const tc = timer_config[timer_num].pTcc;
|
||||
// Clear interrupt flag
|
||||
tc->INTFLAG.reg = TCC_INTFLAG_OVF;
|
||||
}
|
||||
else {
|
||||
Tc * const tc = timer_config[timer_num].pTc;
|
||||
// Clear interrupt flag
|
||||
tc->COUNT32.INTFLAG.bit.MC0 = 1;
|
||||
}
|
||||
}
|
||||
|
||||
#define HAL_timer_isr_epilogue(timer_num)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user