New Maerkbot Marlin Version
Hab eine neue Version von Marlin für den Makerbot erstellt
This commit is contained in:
parent
d812e4a03f
commit
7a7752b374
|
@ -0,0 +1,213 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Based on u8g_dev_uc1701_mini12864.c (dealextreme)
|
||||
*
|
||||
* Universal 8bit Graphics Library
|
||||
*
|
||||
* Copyright (c) 2011, olikraus@gmail.com
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "../../inc/MarlinConfigPre.h"
|
||||
|
||||
#if HAS_MARLINUI_U8GLIB
|
||||
|
||||
#include "HAL_LCD_com_defines.h"
|
||||
|
||||
#define WIDTH 128
|
||||
#define HEIGHT 64
|
||||
#define PAGE_HEIGHT 8
|
||||
|
||||
#define UC1701_ADC_REVERSE(N) ((N) ? 0xA1 : 0xA0)
|
||||
#define UC1701_BIAS_MODE(N) ((N) ? 0xA3 : 0xA2)
|
||||
#define UC1701_ALL_PIX(N) ((N) ? 0xA5 : 0xA4)
|
||||
#define UC1701_INVERTED(N) ((N) ? 0xA7 : 0xA6)
|
||||
#define UC1701_ON(N) ((N) ? 0xAF : 0xAE)
|
||||
#define UC1701_OUT_MODE(N) ((N) ? 0xC8 : 0xC0)
|
||||
#define UC1701_POWER_CONTROL(N) (0x28 | (N))
|
||||
#define UC1701_V5_RATIO(N) (0x20 | ((N) & 0x7))
|
||||
#define UC1701_CONTRAST(N) (0x81), (N)
|
||||
|
||||
#define UC1701_COLUMN_HI(N) (0x10 | (((N) >> 4) & 0xF))
|
||||
#define UC1701_COLUMN_ADR(N) UC1701_COLUMN_HI(N), ((N) & 0xF)
|
||||
#define UC1701_PAGE_ADR(N) (0xB0 | (N))
|
||||
#define UC1701_START_LINE(N) (0x40 | (N))
|
||||
#define UC1701_INDICATOR(N) (0xAC), (N)
|
||||
#define UC1701_RESET() (0xE2)
|
||||
#define UC1701_NOOP() (0xE3)
|
||||
#define UC1701_BOOST_RATIO(N) (0xF8), (N)
|
||||
|
||||
static const uint8_t u8g_dev_uc1701_mini12864_HAL_init_seq[] PROGMEM = {
|
||||
U8G_ESC_CS(0), // disable chip
|
||||
U8G_ESC_ADR(0), // instruction mode
|
||||
U8G_ESC_RST(1), // do reset low pulse with (1*16)+2 milliseconds
|
||||
U8G_ESC_CS(1), // enable chip
|
||||
|
||||
UC1701_RESET(), // soft reset
|
||||
UC1701_START_LINE(0), // set display start line to 0
|
||||
UC1701_ADC_REVERSE(0), // ADC set to reverse
|
||||
UC1701_OUT_MODE(1), // common output mode
|
||||
UC1701_INVERTED(0), // display normal, bit val 0: LCD pixel off
|
||||
UC1701_BIAS_MODE(0), // LCD bias 1/9
|
||||
UC1701_POWER_CONTROL(0x7), // all power control circuits on
|
||||
UC1701_BOOST_RATIO(0x0), // set booster ratio to 4x
|
||||
UC1701_V5_RATIO(3), // set V0 voltage resistor ratio to large
|
||||
UC1701_CONTRAST(0x27), // set contrast
|
||||
UC1701_INDICATOR(0), // indicator disable
|
||||
UC1701_ON(1), // display on
|
||||
|
||||
U8G_ESC_CS(0), // disable chip
|
||||
U8G_ESC_DLY(100), // delay 100 ms
|
||||
U8G_ESC_CS(1), // enable chip
|
||||
|
||||
UC1701_ALL_PIX(1), // display all points, ST7565
|
||||
U8G_ESC_CS(0), // disable chip
|
||||
U8G_ESC_DLY(100), // delay 100 ms
|
||||
U8G_ESC_DLY(100), // delay 100 ms
|
||||
U8G_ESC_CS(1), // enable chip
|
||||
UC1701_ALL_PIX(0), // normal display
|
||||
U8G_ESC_CS(0), // disable chip
|
||||
U8G_ESC_DLY(150), // delay 150 ms before sending any data
|
||||
U8G_ESC_END // end of sequence
|
||||
};
|
||||
|
||||
static const uint8_t u8g_dev_uc1701_mini12864_HAL_data_start[] PROGMEM = {
|
||||
U8G_ESC_ADR(0), // instruction mode
|
||||
U8G_ESC_CS(1), // enable chip
|
||||
#if ANY(MKS_MINI_12864, ENDER2_STOCKDISPLAY, FYSETC_MINI_12864)
|
||||
UC1701_START_LINE(0), // set display start line to 0
|
||||
UC1701_ADC_REVERSE(0), // ADC set to reverse
|
||||
UC1701_OUT_MODE(1), // common output mode
|
||||
UC1701_INVERTED(0), // display normal, bit val 0: LCD pixel off
|
||||
UC1701_BIAS_MODE(0), // LCD bias 1/9
|
||||
UC1701_POWER_CONTROL(0x7),// all power control circuits on
|
||||
UC1701_BOOST_RATIO(0x0), // set booster ratio to 4x
|
||||
UC1701_V5_RATIO(3), // set V0 voltage resistor ratio to large
|
||||
UC1701_INDICATOR(0), // indicator disable
|
||||
UC1701_ON(1), // display on
|
||||
UC1701_COLUMN_HI(0), // set upper 4 bit of the col adr to 0
|
||||
U8G_ESC_END, // end of sequence
|
||||
U8G_ESC_DLY(5) // delay 5 ms
|
||||
#else
|
||||
UC1701_COLUMN_ADR(0), // address 0
|
||||
U8G_ESC_END // end of sequence
|
||||
#endif
|
||||
};
|
||||
|
||||
uint8_t u8g_dev_uc1701_mini12864_HAL_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg) {
|
||||
switch (msg) {
|
||||
case U8G_DEV_MSG_INIT:
|
||||
u8g_InitCom(u8g, dev, U8G_SPI_CLK_CYCLE_300NS);
|
||||
u8g_WriteEscSeqP(u8g, dev, u8g_dev_uc1701_mini12864_HAL_init_seq);
|
||||
break;
|
||||
|
||||
case U8G_DEV_MSG_STOP: break;
|
||||
|
||||
case U8G_DEV_MSG_PAGE_NEXT: {
|
||||
u8g_pb_t *pb = (u8g_pb_t *)(dev->dev_mem);
|
||||
u8g_WriteEscSeqP(u8g, dev, u8g_dev_uc1701_mini12864_HAL_data_start);
|
||||
u8g_WriteByte(u8g, dev, 0x0B0 | pb->p.page); /* select current page */
|
||||
u8g_SetAddress(u8g, dev, 1); /* data mode */
|
||||
if (!u8g_pb_WriteBuffer(pb, u8g, dev)) return 0;
|
||||
u8g_SetChipSelect(u8g, dev, 0);
|
||||
} break;
|
||||
|
||||
case U8G_DEV_MSG_CONTRAST:
|
||||
u8g_SetChipSelect(u8g, dev, 1);
|
||||
u8g_SetAddress(u8g, dev, 0); /* instruction mode */
|
||||
u8g_WriteByte(u8g, dev, 0x081);
|
||||
u8g_WriteByte(u8g, dev, (*(uint8_t *)arg) >> 2);
|
||||
u8g_SetChipSelect(u8g, dev, 0);
|
||||
return 1;
|
||||
}
|
||||
return u8g_dev_pb8v1_base_fn(u8g, dev, msg, arg);
|
||||
}
|
||||
|
||||
uint8_t u8g_dev_uc1701_mini12864_HAL_2x_fn(u8g_t *u8g, u8g_dev_t *dev, uint8_t msg, void *arg) {
|
||||
switch (msg) {
|
||||
case U8G_DEV_MSG_INIT:
|
||||
u8g_InitCom(u8g, dev, U8G_SPI_CLK_CYCLE_300NS);
|
||||
u8g_WriteEscSeqP(u8g, dev, u8g_dev_uc1701_mini12864_HAL_init_seq);
|
||||
break;
|
||||
|
||||
case U8G_DEV_MSG_STOP: break;
|
||||
|
||||
case U8G_DEV_MSG_PAGE_NEXT: {
|
||||
u8g_pb_t *pb = (u8g_pb_t *)(dev->dev_mem);
|
||||
u8g_WriteEscSeqP(u8g, dev, u8g_dev_uc1701_mini12864_HAL_data_start);
|
||||
u8g_WriteByte(u8g, dev, 0x0B0 | (2 * pb->p.page)); /* select current page */
|
||||
u8g_SetAddress(u8g, dev, 1); /* data mode */
|
||||
u8g_WriteSequence(u8g, dev, pb->width, (uint8_t *)pb->buf);
|
||||
u8g_SetChipSelect(u8g, dev, 0);
|
||||
u8g_WriteEscSeqP(u8g, dev, u8g_dev_uc1701_mini12864_HAL_data_start);
|
||||
u8g_WriteByte(u8g, dev, 0x0B0 | (2 * pb->p.page + 1)); /* select current page */
|
||||
u8g_SetAddress(u8g, dev, 1); /* data mode */
|
||||
u8g_WriteSequence(u8g, dev, pb->width, (uint8_t *)(pb->buf)+pb->width);
|
||||
u8g_SetChipSelect(u8g, dev, 0);
|
||||
} break;
|
||||
|
||||
case U8G_DEV_MSG_CONTRAST:
|
||||
u8g_SetChipSelect(u8g, dev, 1);
|
||||
u8g_SetAddress(u8g, dev, 0); /* instruction mode */
|
||||
u8g_WriteByte(u8g, dev, 0x081);
|
||||
u8g_WriteByte(u8g, dev, (*(uint8_t *)arg) >> 2);
|
||||
u8g_SetChipSelect(u8g, dev, 0);
|
||||
return 1;
|
||||
}
|
||||
return u8g_dev_pb16v1_base_fn(u8g, dev, msg, arg);
|
||||
}
|
||||
|
||||
U8G_PB_DEV(u8g_dev_uc1701_mini12864_HAL_sw_spi, WIDTH, HEIGHT, PAGE_HEIGHT, u8g_dev_uc1701_mini12864_HAL_fn, U8G_COM_HAL_SW_SPI_FN);
|
||||
U8G_PB_DEV(u8g_dev_uc1701_mini12864_HAL_hw_spi, WIDTH, HEIGHT, PAGE_HEIGHT, u8g_dev_uc1701_mini12864_HAL_fn, U8G_COM_HAL_HW_SPI_FN);
|
||||
|
||||
uint8_t u8g_dev_uc1701_mini12864_HAL_2x_buf[WIDTH*2] U8G_NOCOMMON ;
|
||||
u8g_pb_t u8g_dev_uc1701_mini12864_HAL_2x_pb = { {16, HEIGHT, 0, 0, 0}, WIDTH, u8g_dev_uc1701_mini12864_HAL_2x_buf};
|
||||
u8g_dev_t u8g_dev_uc1701_mini12864_HAL_2x_sw_spi = { u8g_dev_uc1701_mini12864_HAL_2x_fn, &u8g_dev_uc1701_mini12864_HAL_2x_pb, U8G_COM_HAL_SW_SPI_FN };
|
||||
u8g_dev_t u8g_dev_uc1701_mini12864_HAL_2x_hw_spi = { u8g_dev_uc1701_mini12864_HAL_2x_fn, &u8g_dev_uc1701_mini12864_HAL_2x_pb, U8G_COM_HAL_HW_SPI_FN };
|
||||
|
||||
#endif // HAS_MARLINUI_U8GLIB
|
|
@ -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"
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
# editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[{*.patch,syntax_test_*}]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[{*.c,*.cpp,*.h,*.ino,*.py,Makefile}]
|
||||
end_of_line = lf
|
||||
|
||||
[{*.c,*.cpp,*.h,*.ino}]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[{Makefile}]
|
||||
indent_style = tab
|
||||
indent_size = 2
|
||||
|
||||
[*.md]
|
||||
# Two spaces at the end of the line means newline in Markdown
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[{*.py}]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[{*.conf,*.sublime-project}]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
|
@ -0,0 +1,21 @@
|
|||
# Set the default behavior, in case people don't have core.autocrlf set.
|
||||
* text=auto
|
||||
|
||||
# Files with Unix line endings
|
||||
*.c text eol=lf
|
||||
*.cpp text eol=lf
|
||||
*.h text eol=lf
|
||||
*.ino text eol=lf
|
||||
*.py text eol=lf
|
||||
*.sh text eol=lf
|
||||
*.scad text eol=lf
|
||||
|
||||
# Files with native line endings
|
||||
# *.sln text
|
||||
|
||||
# Binary files
|
||||
*.png binary
|
||||
*.jpg binary
|
||||
*.fon binary
|
||||
*.bin binary
|
||||
*.woff binary
|
|
@ -0,0 +1,3 @@
|
|||
github: [thinkyhead]
|
||||
patreon: thinkyhead
|
||||
custom: ["https://www.thinkyhead.com/donate-to-marlin"]
|
|
@ -0,0 +1,40 @@
|
|||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by following GitHub's [reporting abuse or spam article](https://docs.github.com/en/communities/maintaining-your-safety-on-github/reporting-abuse-or-spam). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [https://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[homepage]: https://contributor-covenant.org
|
||||
[version]: https://contributor-covenant.org/version/1/4/
|
|
@ -0,0 +1,148 @@
|
|||
# Contributing to Marlin
|
||||
|
||||
Thanks for your interest in contributing to Marlin Firmware!
|
||||
|
||||
The following is a set of guidelines for contributing to Marlin, hosted by the [MarlinFirmware Organization](https://github.com/MarlinFirmware) on GitHub. These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a Pull Request.
|
||||
|
||||
#### Table Of Contents
|
||||
|
||||
[Code of Conduct](#code-of-conduct)
|
||||
|
||||
[I don't want to read this whole thing, I just have a question!!!](#i-dont-want-to-read-this-whole-thing-i-just-have-a-question)
|
||||
|
||||
[How Can I Contribute?](#how-can-i-contribute)
|
||||
* [Reporting Bugs](#reporting-bugs)
|
||||
* [Suggesting Features or Changes](#suggesting-features-or-changes)
|
||||
* [Your First Code Contribution](#your-first-code-contribution)
|
||||
* [Pull Requests](#pull-requests)
|
||||
|
||||
[Styleguides](#styleguides)
|
||||
* [Git Commit Messages](#git-commit-messages)
|
||||
* [C++ Coding Standards](#c++-coding-standards)
|
||||
* [Documentation Styleguide](#documentation)
|
||||
|
||||
[Additional Notes](#additional-notes)
|
||||
* [Issue and Pull Request Labels](#issue-and-pull-request-labels)
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
This project and everyone participating in it is governed by the [Marlin Code of Conduct](code_of_conduct.md). By participating, you are expected to uphold this code. Please report unacceptable behavior by following GitHub's [reporting abuse or spam article](https://docs.github.com/en/communities/maintaining-your-safety-on-github/reporting-abuse-or-spam).
|
||||
|
||||
## I don't want to read this whole thing I just have a question!!!
|
||||
|
||||
> [!NOTE]
|
||||
> Please don't file an issue to ask a question. You'll get faster results by using the resources below.
|
||||
|
||||
We have a Message Board and a Facebook group where our knowledgable user community can provide helpful advice if you have questions.
|
||||
|
||||
- [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:
|
||||
|
||||
* Use the link https://discord.gg/n5NJ59y to join up as a General User.
|
||||
* Even though our Discord is pretty active, it may take a while for community members to respond — please be patient!
|
||||
* Use the `#general` channel for general questions or discussion about Marlin.
|
||||
* Other channels exist for certain topics or are limited to Patrons. Check the channel list.
|
||||
|
||||
## How Can I Contribute?
|
||||
|
||||
### Reporting Bugs
|
||||
|
||||
This section guides you through submitting a Bug Report for Marlin. Following these guidelines helps maintainers and the community understand your report, reproduce the behavior, and find related reports.
|
||||
|
||||
Before creating a Bug Report, please test the "nightly" development branch, as you might find out that you don't need to create one. When you are creating a Bug Report, please [include as many details as possible](#how-do-i-submit-a-good-bug-report). Fill out [the required template](ISSUE_TEMPLATE/bug_report.yml), the information it asks for helps us resolve issues faster.
|
||||
|
||||
> [!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/bug_report.yml).
|
||||
|
||||
Explain the problem and include additional details to help maintainers reproduce the problem:
|
||||
|
||||
* **Use a clear and descriptive title** for the issue to identify the problem.
|
||||
* **Describe the exact steps which reproduce the problem** in as many details as possible. For example, start by explaining how you started Marlin, e.g. which command exactly you used in the terminal, or how you started Marlin otherwise. When listing steps, **don't just say what you did, but explain how you did it**. For example, if you moved the cursor to the end of a line, explain if you used the mouse, or a keyboard shortcut or an Marlin command, and if so which one?
|
||||
* **Provide specific examples to demonstrate the steps**. Include links to files or GitHub projects, or copy/pasteable snippets, which you use in those examples. If you're providing snippets or log output in the issue, use [Markdown code blocks](https://help.github.com/articles/markdown-basics/#multiple-lines).
|
||||
* **Describe the behavior you observed after following the steps** and point out what exactly is the problem with that behavior.
|
||||
* **Explain which behavior you expected to see instead and why.**
|
||||
* **Include detailed log output** especially for probing and leveling. See below for usage of `DEBUG_LEVELING_FEATURE`.
|
||||
* **Include screenshots, links to videos, etc.** which clearly demonstrate the problem.
|
||||
* **Include G-code** (if relevant) that reliably causes the problem to show itself.
|
||||
* **If the problem wasn't triggered by a specific action**, describe what you were doing before the problem happened and share more information using the guidelines below.
|
||||
|
||||
Provide more context:
|
||||
|
||||
* **Can you reproduce the problem with a minimum of options enabled?**
|
||||
* **Did the problem start happening recently** (e.g. after updating to a new version of Marlin) or was this always a problem?
|
||||
* If the problem started happening recently, **can you reproduce the problem in an older version of Marlin?** What's the most recent version in which the problem doesn't happen? You can download older versions of Marlin from [the releases page](https://github.com/MarlinFirmware/Marlin/releases).
|
||||
* **Can you reliably reproduce the issue?** If not, provide details about how often the problem happens and under which conditions it normally happens.
|
||||
|
||||
Include details about your configuration and environment:
|
||||
|
||||
* **Which version of Marlin are you using?** Marlin's exact version and build date can be seen in the startup message when a host connects to Marlin, or in the LCD Info menu (if enabled).
|
||||
* **What kind of 3D Printer and electronics are you using**?
|
||||
* **What kind of add-ons (probe, filament sensor) do you have**?
|
||||
* **Include your Configuration files.** Make a ZIP file containing `Configuration.h` and `Configuration_adv.h` and drop it on your reply.
|
||||
|
||||
### Suggesting Features or Changes
|
||||
|
||||
This section guides you through submitting a suggestion for Marlin, including completely new features and minor improvements to existing functionality. Following these guidelines helps maintainers and the community understand your suggestion and find related suggestions.
|
||||
|
||||
Before creating a suggestion, please check [this list](https://github.com/MarlinFirmware/Marlin/issues?q=is%3Aopen+is%3Aissue+label%3A%22T%3A+Feature+Request%22) as you might find out that you don't need to create one. When you are creating an enhancement suggestion, please [include as many details as possible](#how-do-i-submit-a-good-feature-request). Fill in [the template](ISSUE_TEMPLATE/feature_request.yml), including the steps that you imagine you would take if the feature you're requesting existed.
|
||||
|
||||
#### Before 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%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?
|
||||
|
||||
Feature Requests are tracked as [GitHub issues](https://guides.github.com/features/issues/). Please follow these guidelines in your request:
|
||||
|
||||
* **Use a clear and descriptive title** for the issue to identify the suggestion.
|
||||
* **Provide a step-by-step description of the requested feature** in as much detail as possible.
|
||||
* **Provide specific examples to demonstrate the steps**.
|
||||
* **Describe the current behavior** and **explain which behavior you expected to see instead** and why.
|
||||
* **Include screenshots and links to videos** which demonstrate the feature or point out the part of Marlin to which the request is related.
|
||||
* **Explain why this feature would be useful** to most Marlin users.
|
||||
* **Name other firmwares that have this feature, if any.**
|
||||
|
||||
### Your First Code Contribution
|
||||
|
||||
Unsure where to begin contributing to Marlin? You can start by looking through these `good-first-issue` and `help-wanted` issues:
|
||||
|
||||
* [Beginner issues][good-first-issue] - issues which should only require a few lines of code, and a test or two.
|
||||
* [Help Wanted issues][help-wanted] - issues which should be a bit more involved than `beginner` issues.
|
||||
|
||||
### Pull Requests
|
||||
|
||||
Pull Requests should always be targeted to working branches (e.g., `bugfix-2.1.x` and/or `bugfix-1.1.x`) and never to release branches (e.g., `2.0.x` and/or `1.1.x`). If this is your first Pull Request, please read our [Guide to Pull Requests](https://marlinfw.org/docs/development/getting_started_pull_requests.html) and Github's [Pull Request](https://help.github.com/articles/creating-a-pull-request/) documentation.
|
||||
|
||||
* Fill in [the required template](pull_request_template.md).
|
||||
* Don't include issue numbers in the PR title.
|
||||
* Include pictures, diagrams, and links to videos in your Pull Request to demonstrate your changes, if needed.
|
||||
* Follow the [Coding Standards](https://marlinfw.org/docs/development/coding_standards.html) posted on our website.
|
||||
* Document new code with clear and concise comments.
|
||||
* End all files with a newline.
|
||||
|
||||
## Styleguides
|
||||
|
||||
### Git Commit Messages
|
||||
|
||||
* Use the present tense ("Add feature" not "Added feature").
|
||||
* Use the imperative mood ("Move cursor to..." not "Moves cursor to...").
|
||||
* Limit the first line to 72 characters or fewer.
|
||||
* Reference issues and Pull Requests liberally after the first line.
|
||||
|
||||
### C++ Coding Standards
|
||||
|
||||
* Please read and follow the [Coding Standards](https://marlinfw.org/docs/development/coding_standards.html) posted on our website. Failure to follow these guidelines will delay evaluation and acceptance of Pull Requests.
|
||||
|
||||
### Documentation
|
||||
|
||||
* Guidelines for documentation are still under development. In-general, be clear, concise, and to-the-point.
|
|
@ -0,0 +1,33 @@
|
|||
<!--
|
||||
|
||||
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
|
||||
|
||||
<!--
|
||||
|
||||
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 PR fix or improve? -->
|
||||
|
||||
### Configurations
|
||||
|
||||
<!-- Attach Configurations ZIP and any other files needed to test this PR. -->
|
||||
|
||||
### Related Issues
|
||||
|
||||
<!-- Does this PR fix a bug or fulfill a Feature Request? Link related Issues here. -->
|
|
@ -0,0 +1,170 @@
|
|||
#
|
||||
# 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/>.
|
||||
#
|
||||
|
||||
# Generated files
|
||||
_Version.h
|
||||
bdf2u8g.exe
|
||||
genpages.exe
|
||||
marlin_config.json
|
||||
mczip.h
|
||||
language*.csv
|
||||
out-csv/
|
||||
out-language/
|
||||
*.gen
|
||||
*.sublime-workspace
|
||||
|
||||
# OS
|
||||
applet/
|
||||
.DS_Store
|
||||
|
||||
# Compiled C++ Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.obj
|
||||
*.ino.cpp
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Fortran module files
|
||||
*.mod
|
||||
*.smod
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
*.lib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
|
||||
# Compiled C Object files
|
||||
*.o
|
||||
*.ko
|
||||
*.obj
|
||||
*.elf
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Libraries
|
||||
*.lib
|
||||
*.a
|
||||
*.la
|
||||
*.lo
|
||||
|
||||
# Shared objects (inc. Windows DLLs)
|
||||
*.dll
|
||||
*.so
|
||||
*.so.*
|
||||
*.dylib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
*.i*86
|
||||
*.x86_64
|
||||
*.hex
|
||||
|
||||
# Debug files
|
||||
*.dSYM/
|
||||
*.su
|
||||
|
||||
# PlatformIO files/dirs
|
||||
.pio*
|
||||
.pioenvs
|
||||
.piolibdeps
|
||||
.clang_complete
|
||||
.gcc-flags.json
|
||||
/lib/
|
||||
|
||||
# Secure Credentials
|
||||
Configuration_Secure.h
|
||||
|
||||
# Visual Studio
|
||||
*.sln
|
||||
*.vcxproj
|
||||
*.vcxproj.user
|
||||
*.vcxproj.filters
|
||||
Release/
|
||||
Debug/
|
||||
__vm/
|
||||
.vs/
|
||||
vc-fileutils.settings
|
||||
|
||||
# Visual Studio Code
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
|
||||
# Simulation files
|
||||
imgui.ini
|
||||
eeprom.dat
|
||||
spi_flash.bin
|
||||
fs.img
|
||||
|
||||
# CMake
|
||||
buildroot/share/cmake/*
|
||||
CMakeLists.txt
|
||||
!buildroot/share/cmake/CMakeLists.txt
|
||||
src/CMakeLists.txt
|
||||
CMakeListsPrivate.txt
|
||||
build/
|
||||
|
||||
# CLion
|
||||
cmake-build-*
|
||||
|
||||
# Eclipse
|
||||
.project
|
||||
.cproject
|
||||
.pydevproject
|
||||
.settings
|
||||
.classpath
|
||||
|
||||
# Python
|
||||
__pycache__
|
||||
|
||||
# IOLogger logs
|
||||
*_log.csv
|
||||
|
||||
# Misc.
|
||||
*~
|
||||
*.orig
|
||||
*.rej
|
||||
*.bak
|
||||
*.idea
|
||||
*.i
|
||||
*.ii
|
||||
*.swp
|
||||
tags
|
||||
*.logs
|
||||
*.bak
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||
// for the documentation about the extensions.json format
|
||||
"recommendations": [
|
||||
"marlinfirmware.auto-build",
|
||||
"platformio.platformio-ide"
|
||||
],
|
||||
"unwantedRecommendations": [
|
||||
"ms-vscode-remote.remote-containers",
|
||||
"ms-vscode.cpptools-extension-pack"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,676 @@
|
|||
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (c) 2007 Free Software Foundation, Inc. <https://www.fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
{one line to give the program's name and a brief idea of what it does.}
|
||||
Copyright (c) {year} {name of author}
|
||||
|
||||
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/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
{project} Copyright (c) {year} {fullname}
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
|
@ -0,0 +1,65 @@
|
|||
SCRIPTS_DIR := buildroot/share/scripts
|
||||
CONTAINER_RT_BIN := docker
|
||||
CONTAINER_RT_OPTS := --rm -v $(PWD):/code -v platformio-cache:/root/.platformio
|
||||
CONTAINER_IMAGE := marlin-dev
|
||||
|
||||
help:
|
||||
@echo "Tasks for local development:"
|
||||
@echo "make marlin : Build marlin for the configured board"
|
||||
@echo "make format-pins : Reformat all pins files"
|
||||
@echo "make tests-single-ci : Run a single test from inside the CI"
|
||||
@echo "make tests-single-local : Run a single test locally"
|
||||
@echo "make tests-single-local-docker : Run a single test locally, using docker"
|
||||
@echo "make tests-all-local : Run all tests locally"
|
||||
@echo "make tests-all-local-docker : Run all tests locally, using docker"
|
||||
@echo "make setup-local-docker : Build the local docker image"
|
||||
@echo ""
|
||||
@echo "Options for testing:"
|
||||
@echo " TEST_TARGET Set when running tests-single-*, to select the"
|
||||
@echo " test. If you set it to ALL it will run all "
|
||||
@echo " tests, but some of them are broken: use "
|
||||
@echo " tests-all-* instead to run only the ones that "
|
||||
@echo " run on GitHub CI"
|
||||
@echo " ONLY_TEST Limit tests to only those that contain this, or"
|
||||
@echo " the index of the test (1-based)"
|
||||
@echo " VERBOSE_PLATFORMIO If you want the full PIO output, set any value"
|
||||
@echo " GIT_RESET_HARD Used by CI: reset all local changes. WARNING:"
|
||||
@echo " THIS WILL UNDO ANY CHANGES YOU'VE MADE!"
|
||||
|
||||
marlin:
|
||||
./buildroot/bin/mftest -a
|
||||
.PHONY: marlin
|
||||
|
||||
tests-single-ci:
|
||||
export GIT_RESET_HARD=true
|
||||
$(MAKE) tests-single-local TEST_TARGET=$(TEST_TARGET) PLATFORMIO_BUILD_FLAGS=-DGITHUB_ACTION
|
||||
|
||||
tests-single-local:
|
||||
@if ! test -n "$(TEST_TARGET)" ; then echo "***ERROR*** Set TEST_TARGET=<your-module> or use make tests-all-local" ; return 1; fi
|
||||
export PATH="./buildroot/bin/:./buildroot/tests/:${PATH}" \
|
||||
&& export VERBOSE_PLATFORMIO=$(VERBOSE_PLATFORMIO) \
|
||||
&& run_tests . $(TEST_TARGET) "$(ONLY_TEST)"
|
||||
|
||||
tests-single-local-docker:
|
||||
@if ! test -n "$(TEST_TARGET)" ; then echo "***ERROR*** Set TEST_TARGET=<your-module> or use make tests-all-local-docker" ; return 1; fi
|
||||
@if ! $(CONTAINER_RT_BIN) images -q $(CONTAINER_IMAGE) > /dev/null ; then $(MAKE) setup-local-docker ; fi
|
||||
$(CONTAINER_RT_BIN) run $(CONTAINER_RT_OPTS) $(CONTAINER_IMAGE) $(MAKE) tests-single-local TEST_TARGET=$(TEST_TARGET) VERBOSE_PLATFORMIO=$(VERBOSE_PLATFORMIO) GIT_RESET_HARD=$(GIT_RESET_HARD) ONLY_TEST="$(ONLY_TEST)"
|
||||
|
||||
tests-all-local:
|
||||
export PATH="./buildroot/bin/:./buildroot/tests/:${PATH}" \
|
||||
&& export VERBOSE_PLATFORMIO=$(VERBOSE_PLATFORMIO) \
|
||||
&& for TEST_TARGET in $$($(SCRIPTS_DIR)/get_test_targets.py) ; do echo "Running tests for $$TEST_TARGET" ; run_tests . $$TEST_TARGET ; done
|
||||
|
||||
tests-all-local-docker:
|
||||
@if ! $(CONTAINER_RT_BIN) images -q $(CONTAINER_IMAGE) > /dev/null ; then $(MAKE) setup-local-docker ; fi
|
||||
$(CONTAINER_RT_BIN) run $(CONTAINER_RT_OPTS) $(CONTAINER_IMAGE) $(MAKE) tests-all-local VERBOSE_PLATFORMIO=$(VERBOSE_PLATFORMIO) GIT_RESET_HARD=$(GIT_RESET_HARD)
|
||||
|
||||
setup-local-docker:
|
||||
$(CONTAINER_RT_BIN) build -t $(CONTAINER_IMAGE) -f docker/Dockerfile .
|
||||
|
||||
PINS := $(shell find Marlin/src/pins -mindepth 2 -name '*.h')
|
||||
|
||||
$(PINS): %:
|
||||
@echo "Formatting $@" && node $(SCRIPTS_DIR)/pinsformat.js $@
|
||||
|
||||
format-pins: $(PINS)
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,57 @@
|
|||
/*==============================================================================
|
||||
|
||||
Marlin Firmware
|
||||
|
||||
(c) 2011-2024 MarlinFirmware
|
||||
Portions of Marlin are (c) by their respective authors.
|
||||
All code complies with GPLv2 and/or GPLv3
|
||||
|
||||
================================================================================
|
||||
|
||||
Greetings! Thank you for choosing Marlin 2 as your 3D printer firmware.
|
||||
|
||||
To configure Marlin you must edit Configuration.h and Configuration_adv.h
|
||||
located in the root 'Marlin' folder. Check our Configurations repository to
|
||||
see if there's a more suitable starting-point for your specific hardware.
|
||||
|
||||
Before diving in, we recommend the following essential links:
|
||||
|
||||
Marlin Firmware Official Website
|
||||
|
||||
- https://marlinfw.org/
|
||||
The official Marlin Firmware website contains the most up-to-date
|
||||
documentation. Contributions are always welcome!
|
||||
|
||||
Configuration
|
||||
|
||||
- https://github.com/MarlinFirmware/Configurations
|
||||
Example configurations for several printer models.
|
||||
|
||||
- https://youtu.be/3gwWVFtdg-4
|
||||
A good 20-minute overview of Marlin configuration by Tom Sanladerer.
|
||||
(Applies to Marlin 1.0.x, so Jerk and Acceleration should be halved.)
|
||||
Also... https://www.google.com/search?tbs=vid%3A1&q=configure+marlin
|
||||
|
||||
- https://marlinfw.org/docs/configuration/configuration.html
|
||||
Marlin's configuration options are explained in more detail here.
|
||||
|
||||
Getting Help
|
||||
|
||||
- https://reprap.org/forum/list.php?415
|
||||
The Marlin Discussion Forum is a great place to get help from other Marlin
|
||||
users who may have experienced similar issues to your own.
|
||||
|
||||
- https://github.com/MarlinFirmware/Marlin/issues
|
||||
With a free GitHub account you can provide us with feedback, bug reports,
|
||||
and feature requests via the Marlin Issue Queue.
|
||||
|
||||
Contributing
|
||||
|
||||
- https://marlinfw.org/docs/development/contributing.html
|
||||
If you'd like to contribute to Marlin, read this first!
|
||||
|
||||
- https://marlinfw.org/docs/development/coding_standards.html
|
||||
Before submitting code get to know the Coding Standards.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------*/
|
|
@ -0,0 +1,76 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
////////////////////////////
|
||||
// VENDOR VERSION EXAMPLE //
|
||||
////////////////////////////
|
||||
|
||||
/**
|
||||
* Marlin release version identifier
|
||||
*/
|
||||
//#define SHORT_BUILD_VERSION "2.1.2.4"
|
||||
|
||||
/**
|
||||
* Verbose version identifier which should contain a reference to the location
|
||||
* from where the binary was downloaded or the source code was compiled.
|
||||
*/
|
||||
//#define DETAILED_BUILD_VERSION SHORT_BUILD_VERSION
|
||||
|
||||
/**
|
||||
* The STRING_DISTRIBUTION_DATE represents when the binary file was built,
|
||||
* here we define this default string as the date where the latest release
|
||||
* version was tagged.
|
||||
*/
|
||||
//#define STRING_DISTRIBUTION_DATE "2024-05-29"
|
||||
|
||||
/**
|
||||
* Defines a generic printer name to be output to the LCD after booting Marlin.
|
||||
*/
|
||||
//#define MACHINE_NAME "Makerbot Replicator"
|
||||
|
||||
/**
|
||||
* The SOURCE_CODE_URL is the location where users will find the Marlin Source
|
||||
* Code which is installed on the device. In most cases —unless the manufacturer
|
||||
* has a distinct Github fork— the Source Code URL should just be the main
|
||||
* Marlin repository.
|
||||
*/
|
||||
//#define SOURCE_CODE_URL "github.com/MarlinFirmware/Marlin"
|
||||
|
||||
/**
|
||||
* Default generic printer UUID.
|
||||
*/
|
||||
//#define DEFAULT_MACHINE_UUID "cede2a2f-41a2-4748-9b12-c55c62f367ff"
|
||||
|
||||
/**
|
||||
* The WEBSITE_URL is the location where users can get more information such as
|
||||
* documentation about a specific Marlin release.
|
||||
*/
|
||||
//#define WEBSITE_URL "marlinfw.org"
|
||||
|
||||
/**
|
||||
* Set the vendor info the serial USB interface, if changable
|
||||
* Currently only supported by DUE platform
|
||||
*/
|
||||
//#define USB_DEVICE_VENDOR_ID 0x0000
|
||||
//#define USB_DEVICE_PRODUCT_ID 0x0000
|
||||
//#define USB_DEVICE_MANUFACTURE_NAME WEBSITE_URL
|
|
@ -0,0 +1,251 @@
|
|||
#
|
||||
# Marlin Firmware
|
||||
# config.ini - Options to apply before the build
|
||||
#
|
||||
[config:base]
|
||||
#
|
||||
# ini_use_config - A comma-separated list of actions to apply to the Configuration files.
|
||||
# The actions will be applied in the listed order.
|
||||
# - none
|
||||
# Ignore this file and don't apply any configuration options
|
||||
#
|
||||
# - base
|
||||
# Just apply the options in config:base to the configuration
|
||||
#
|
||||
# - minimal
|
||||
# Just apply the options in config:minimal to the configuration
|
||||
#
|
||||
# - all
|
||||
# Apply all 'config:*' sections in this file to the configuration
|
||||
#
|
||||
# - another.ini
|
||||
# Load another INI file with a path relative to this config.ini file (i.e., within Marlin/)
|
||||
#
|
||||
# - https://me.myserver.com/path/to/configs
|
||||
# Fetch configurations from any URL.
|
||||
#
|
||||
# - example/Creality/Ender-5 Plus @ bugfix-2.1.x
|
||||
# Fetch example configuration files from the MarlinFirmware/Configurations repository
|
||||
# https://raw.githubusercontent.com/MarlinFirmware/Configurations/bugfix-2.1.x/config/examples/Creality/Ender-5%20Plus/
|
||||
#
|
||||
# - example/default @ release-2.0.9.7
|
||||
# Fetch default configuration files from the MarlinFirmware/Configurations repository
|
||||
# https://raw.githubusercontent.com/MarlinFirmware/Configurations/release-2.0.9.7/config/default/
|
||||
#
|
||||
# - [disable]
|
||||
# Comment out all #defines in both Configuration.h and Configuration_adv.h. This is useful
|
||||
# to start with a clean slate before applying any config: options, so only the options explicitly
|
||||
# set in config.ini will be enabled in the configuration.
|
||||
#
|
||||
# - [flatten] (Not yet implemented)
|
||||
# Produce a flattened set of Configuration.h and Configuration_adv.h files with only the enabled
|
||||
# #defines and no comments. A clean look, but context-free.
|
||||
#
|
||||
ini_use_config = none
|
||||
|
||||
# Load all config: sections in this file
|
||||
;ini_use_config = all
|
||||
# Disable everything and apply subsequent config:base options
|
||||
;ini_use_config = [disable], base
|
||||
# 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 = 255
|
||||
pid_functional_range = 10
|
||||
|
||||
default_kp = 22.20
|
||||
default_ki = 1.08
|
||||
default_kd = 114.00
|
||||
|
||||
x_driver_type = A4988
|
||||
y_driver_type = A4988
|
||||
z_driver_type = A4988
|
||||
e0_driver_type = A4988
|
||||
|
||||
x_bed_size = 200
|
||||
x_min_pos = 0
|
||||
x_max_pos = X_BED_SIZE
|
||||
|
||||
y_bed_size = 200
|
||||
y_min_pos = 0
|
||||
y_max_pos = Y_BED_SIZE
|
||||
|
||||
z_min_pos = 0
|
||||
z_max_pos = 200
|
||||
|
||||
x_home_dir = -1
|
||||
y_home_dir = -1
|
||||
z_home_dir = -1
|
||||
|
||||
use_xmin_plug = on
|
||||
use_ymin_plug = on
|
||||
use_zmin_plug = on
|
||||
|
||||
x_min_endstop_inverting = false
|
||||
y_min_endstop_inverting = false
|
||||
z_min_endstop_inverting = false
|
||||
|
||||
default_axis_steps_per_unit = { 80, 80, 400, 500 }
|
||||
axis_relative_modes = { false, false, false, false }
|
||||
default_max_feedrate = { 300, 300, 5, 25 }
|
||||
default_max_acceleration = { 3000, 3000, 100, 10000 }
|
||||
|
||||
homing_feedrate_mm_m = { (50*60), (50*60), (4*60) }
|
||||
homing_bump_divisor = { 2, 2, 4 }
|
||||
|
||||
x_enable_on = 0
|
||||
y_enable_on = 0
|
||||
z_enable_on = 0
|
||||
e_enable_on = 0
|
||||
|
||||
invert_x_dir = false
|
||||
invert_y_dir = true
|
||||
invert_z_dir = false
|
||||
invert_e0_dir = false
|
||||
|
||||
invert_e_step_pin = false
|
||||
invert_x_step_pin = false
|
||||
invert_y_step_pin = false
|
||||
invert_z_step_pin = false
|
||||
|
||||
disable_x = off
|
||||
disable_y = off
|
||||
disable_z = off
|
||||
disable_e = off
|
||||
|
||||
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_other_extruders = 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_timeout_sec = 120
|
||||
default_volumetric_extruder_limit = 0.00
|
||||
disable_idle_x = on
|
||||
disable_idle_y = on
|
||||
disable_idle_z = on
|
||||
disable_idle_e = on
|
||||
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
|
|
@ -0,0 +1,36 @@
|
|||
|
||||
This directory is intended for the project specific (private) libraries.
|
||||
PlatformIO will compile them to static libraries and link to executable file.
|
||||
|
||||
The source code of each library should be placed in separate directory, like
|
||||
"lib/private_lib/[here are source files]".
|
||||
|
||||
For example, see how can be organized `Foo` and `Bar` libraries:
|
||||
|
||||
|--lib
|
||||
| |--Bar
|
||||
| | |--docs
|
||||
| | |--examples
|
||||
| | |--src
|
||||
| | |- Bar.c
|
||||
| | |- Bar.h
|
||||
| |--Foo
|
||||
| | |- Foo.c
|
||||
| | |- Foo.h
|
||||
| |- readme.txt --> THIS FILE
|
||||
|- platformio.ini
|
||||
|--src
|
||||
|- main.c
|
||||
|
||||
Then in `src/main.c` you should use:
|
||||
|
||||
#include <Foo.h>
|
||||
#include <Bar.h>
|
||||
|
||||
// rest H/C/CPP code
|
||||
|
||||
PlatformIO will find your libraries automatically, configure preprocessor's
|
||||
include paths and build them.
|
||||
|
||||
More information about PlatformIO Library Dependency Finder
|
||||
- https://docs.platformio.org/page/librarymanager/ldf.html
|
|
@ -0,0 +1,177 @@
|
|||
/**
|
||||
* 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"
|
||||
#include "HAL.h"
|
||||
#include <avr/wdt.h>
|
||||
|
||||
#ifdef USBCON
|
||||
DefaultSerial1 MSerial0(false, Serial);
|
||||
#ifdef BLUETOOTH
|
||||
BTSerial btSerial(false, bluetoothSerial);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// ------------------------
|
||||
// Public Variables
|
||||
// ------------------------
|
||||
|
||||
// Don't initialize/override variable (which would happen in .init4)
|
||||
uint8_t MarlinHAL::reset_reason __attribute__((section(".noinit")));
|
||||
|
||||
// ------------------------
|
||||
// Public functions
|
||||
// ------------------------
|
||||
|
||||
__attribute__((naked)) // Don't output function pro- and epilogue
|
||||
__attribute__((used)) // Output the function, even if "not used"
|
||||
__attribute__((section(".init3"))) // Put in an early user definable section
|
||||
void save_reset_reason() {
|
||||
#if ENABLED(OPTIBOOT_RESET_REASON)
|
||||
__asm__ __volatile__(
|
||||
A("STS %0, r2")
|
||||
: "=m"(hal.reset_reason)
|
||||
);
|
||||
#else
|
||||
hal.reset_reason = MCUSR;
|
||||
#endif
|
||||
|
||||
// Clear within 16ms since WDRF bit enables a 16ms watchdog timer -> Boot loop
|
||||
hal.clear_reset_source();
|
||||
wdt_disable();
|
||||
}
|
||||
|
||||
void MarlinHAL::init() {
|
||||
// Init Servo Pins
|
||||
#if HAS_SERVO_0
|
||||
OUT_WRITE(SERVO0_PIN, LOW);
|
||||
#endif
|
||||
#if HAS_SERVO_1
|
||||
OUT_WRITE(SERVO1_PIN, LOW);
|
||||
#endif
|
||||
#if HAS_SERVO_2
|
||||
OUT_WRITE(SERVO2_PIN, LOW);
|
||||
#endif
|
||||
#if HAS_SERVO_3
|
||||
OUT_WRITE(SERVO3_PIN, LOW);
|
||||
#endif
|
||||
#if HAS_SERVO_4
|
||||
OUT_WRITE(SERVO4_PIN, LOW);
|
||||
#endif
|
||||
#if HAS_SERVO_5
|
||||
OUT_WRITE(SERVO5_PIN, LOW);
|
||||
#endif
|
||||
|
||||
init_pwm_timers(); // Init user timers to default frequency - 1000HZ
|
||||
}
|
||||
|
||||
void MarlinHAL::reboot() {
|
||||
#if ENABLED(USE_WATCHDOG)
|
||||
while (1) { /* run out the watchdog */ }
|
||||
#else
|
||||
void (*resetFunc)() = 0; // Declare resetFunc() at address 0
|
||||
resetFunc(); // Jump to address 0
|
||||
#endif
|
||||
}
|
||||
|
||||
// ------------------------
|
||||
// Watchdog Timer
|
||||
// ------------------------
|
||||
|
||||
#if ENABLED(USE_WATCHDOG)
|
||||
|
||||
#include <avr/wdt.h>
|
||||
#include "../../MarlinCore.h"
|
||||
|
||||
// Initialize watchdog with 8s timeout, if possible. Otherwise, make it 4s.
|
||||
void MarlinHAL::watchdog_init() {
|
||||
#if ENABLED(WATCHDOG_DURATION_8S) && defined(WDTO_8S)
|
||||
#define WDTO_NS WDTO_8S
|
||||
#else
|
||||
#define WDTO_NS WDTO_4S
|
||||
#endif
|
||||
#if ENABLED(WATCHDOG_RESET_MANUAL)
|
||||
// Enable the watchdog timer, but only for the interrupt.
|
||||
// Take care, as this requires the correct order of operation, with interrupts disabled.
|
||||
// See the datasheet of any AVR chip for details.
|
||||
wdt_reset();
|
||||
cli();
|
||||
_WD_CONTROL_REG = _BV(_WD_CHANGE_BIT) | _BV(WDE);
|
||||
_WD_CONTROL_REG = _BV(WDIE) | (WDTO_NS & 0x07) | ((WDTO_NS & 0x08) << 2); // WDTO_NS directly does not work. bit 0-2 are consecutive in the register but the highest value bit is at bit 5
|
||||
// So worked for up to WDTO_2S
|
||||
sei();
|
||||
wdt_reset();
|
||||
#else
|
||||
wdt_enable(WDTO_NS); // The function handles the upper bit correct.
|
||||
#endif
|
||||
//delay(10000); // test it!
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
//=================================== ISR ===================================
|
||||
//===========================================================================
|
||||
|
||||
// Watchdog timer interrupt, called if main program blocks >4sec and manual reset is enabled.
|
||||
#if ENABLED(WATCHDOG_RESET_MANUAL)
|
||||
ISR(WDT_vect) {
|
||||
sei(); // With the interrupt driven serial we need to allow interrupts.
|
||||
SERIAL_ERROR_MSG(STR_WATCHDOG_FIRED);
|
||||
minkill(); // interrupt-safe final kill and infinite loop
|
||||
}
|
||||
#endif
|
||||
|
||||
// Reset watchdog. MUST be called at least every 4 seconds after the
|
||||
// first watchdog_init or AVR will go into emergency procedures.
|
||||
void MarlinHAL::watchdog_refresh() { wdt_reset(); }
|
||||
|
||||
#endif // USE_WATCHDOG
|
||||
|
||||
// ------------------------
|
||||
// Free Memory Accessor
|
||||
// ------------------------
|
||||
|
||||
#if HAS_MEDIA
|
||||
|
||||
#include "../../sd/SdFatUtil.h"
|
||||
int freeMemory() { return SdFatUtil::FreeRam(); }
|
||||
|
||||
#else // !HAS_MEDIA
|
||||
|
||||
extern "C" {
|
||||
extern char __bss_end;
|
||||
extern char __heap_start;
|
||||
extern void* __brkval;
|
||||
|
||||
int freeMemory() {
|
||||
int free_memory;
|
||||
if ((int)__brkval == 0)
|
||||
free_memory = ((int)&free_memory) - ((int)&__bss_end);
|
||||
else
|
||||
free_memory = ((int)&free_memory) - ((int)__brkval);
|
||||
return free_memory;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // !HAS_MEDIA
|
||||
|
||||
#endif // __AVR__
|
|
@ -0,0 +1,280 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* HAL for Arduino AVR
|
||||
*/
|
||||
|
||||
#include "../shared/Marduino.h"
|
||||
#include "../shared/HAL_SPI.h"
|
||||
#include "fastio.h"
|
||||
#include "math.h"
|
||||
|
||||
#ifdef USBCON
|
||||
#include <HardwareSerial.h>
|
||||
#else
|
||||
#include "MarlinSerial.h"
|
||||
#define BOARD_NO_NATIVE_USB
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <util/delay.h>
|
||||
#include <avr/eeprom.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/io.h>
|
||||
|
||||
//
|
||||
// Default graphical display delays
|
||||
//
|
||||
#if F_CPU >= 20000000
|
||||
#define CPU_ST7920_DELAY_1 150
|
||||
#define CPU_ST7920_DELAY_2 0
|
||||
#define CPU_ST7920_DELAY_3 150
|
||||
#elif F_CPU == 16000000
|
||||
#define CPU_ST7920_DELAY_1 125
|
||||
#define CPU_ST7920_DELAY_2 0
|
||||
#define CPU_ST7920_DELAY_3 188
|
||||
#endif
|
||||
|
||||
#ifndef pgm_read_ptr
|
||||
// Compatibility for avr-libc 1.8.0-4.1 included with Ubuntu for
|
||||
// Windows Subsystem for Linux on Windows 10 as of 10/18/2019
|
||||
#define pgm_read_ptr_far(address_long) (void*)__ELPM_word((uint32_t)(address_long))
|
||||
#define pgm_read_ptr_near(address_short) (void*)__LPM_word((uint16_t)(address_short))
|
||||
#define pgm_read_ptr(address_short) pgm_read_ptr_near(address_short)
|
||||
#endif
|
||||
|
||||
// ------------------------
|
||||
// Defines
|
||||
// ------------------------
|
||||
|
||||
// AVR PROGMEM extension for sprintf_P
|
||||
#define S_FMT "%S"
|
||||
|
||||
// AVR PROGMEM extension for string define
|
||||
#define PGMSTR(NAM,STR) const char NAM[] PROGMEM = STR
|
||||
|
||||
#ifndef CRITICAL_SECTION_START
|
||||
#define CRITICAL_SECTION_START() unsigned char _sreg = SREG; cli()
|
||||
#define CRITICAL_SECTION_END() SREG = _sreg
|
||||
#endif
|
||||
|
||||
#define HAL_CAN_SET_PWM_FREQ // This HAL supports PWM Frequency adjustment
|
||||
#define PWM_FREQUENCY 1000 // Default PWM frequency when set_pwm_duty() is called without set_pwm_frequency()
|
||||
|
||||
// ------------------------
|
||||
// Types
|
||||
// ------------------------
|
||||
|
||||
typedef int8_t pin_t;
|
||||
|
||||
#define SHARED_SERVOS HAS_SERVOS // Use shared/servos.cpp
|
||||
|
||||
class Servo;
|
||||
typedef Servo hal_servo_t;
|
||||
|
||||
// ------------------------
|
||||
// Serial ports
|
||||
// ------------------------
|
||||
|
||||
#ifdef USBCON
|
||||
#include "../../core/serial_hook.h"
|
||||
typedef ForwardSerial1Class< decltype(Serial) > DefaultSerial1;
|
||||
extern DefaultSerial1 MSerial0;
|
||||
#ifdef BLUETOOTH
|
||||
typedef ForwardSerial1Class< decltype(bluetoothSerial) > BTSerial;
|
||||
extern BTSerial btSerial;
|
||||
#endif
|
||||
|
||||
#define MYSERIAL1 TERN(BLUETOOTH, btSerial, MSerial0)
|
||||
#else
|
||||
#if !WITHIN(SERIAL_PORT, 0, 3)
|
||||
#error "SERIAL_PORT must be from 0 to 3."
|
||||
#endif
|
||||
#define MYSERIAL1 customizedSerial1
|
||||
|
||||
#ifdef SERIAL_PORT_2
|
||||
#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, 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, 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, 0, 3)
|
||||
#error "LCD_SERIAL_PORT must be from 0 to 3."
|
||||
#endif
|
||||
#define LCD_SERIAL lcdSerial
|
||||
#if HAS_DGUS_LCD
|
||||
#define LCD_SERIAL_TX_BUFFER_FREE() LCD_SERIAL.get_tx_buffer_free()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//
|
||||
// ADC
|
||||
//
|
||||
#define HAL_ADC_VREF_MV 5000
|
||||
#define HAL_ADC_RESOLUTION 10
|
||||
|
||||
//
|
||||
// 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)
|
||||
|
||||
#define HAL_SENSITIVE_PINS 0, 1,
|
||||
|
||||
#ifdef __AVR_AT90USB1286__
|
||||
#define JTAG_DISABLE() do{ MCUCR = 0x80; MCUCR = 0x80; }while(0)
|
||||
#endif
|
||||
|
||||
// AVR compatibility
|
||||
#define strtof strtod
|
||||
|
||||
// ------------------------
|
||||
// Free Memory Accessor
|
||||
// ------------------------
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#if GCC_VERSION <= 50000
|
||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
#endif
|
||||
|
||||
extern "C" int freeMemory();
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
// ------------------------
|
||||
// MarlinHAL Class
|
||||
// ------------------------
|
||||
|
||||
class MarlinHAL {
|
||||
public:
|
||||
|
||||
// Earliest possible init, before setup()
|
||||
MarlinHAL() {}
|
||||
|
||||
// Watchdog
|
||||
static void watchdog_init() IF_DISABLED(USE_WATCHDOG, {});
|
||||
static void watchdog_refresh() IF_DISABLED(USE_WATCHDOG, {});
|
||||
|
||||
static void init(); // Called early in setup()
|
||||
static void init_board() {} // Called less early in setup()
|
||||
static void reboot(); // Restart the firmware from 0x0
|
||||
|
||||
// Interrupts
|
||||
static bool isr_state() { return TEST(SREG, SREG_I); }
|
||||
static void isr_on() { sei(); }
|
||||
static void isr_off() { cli(); }
|
||||
|
||||
static void delay_ms(const int ms) { _delay_ms(ms); }
|
||||
|
||||
// Tasks, called from idle()
|
||||
static void idletask() {}
|
||||
|
||||
// Reset
|
||||
static uint8_t reset_reason;
|
||||
static uint8_t get_reset_source() { return reset_reason; }
|
||||
static void clear_reset_source() { MCUSR = 0; }
|
||||
|
||||
// Free SRAM
|
||||
static int freeMemory() { return ::freeMemory(); }
|
||||
|
||||
//
|
||||
// ADC Methods
|
||||
//
|
||||
|
||||
// Called by Temperature::init once at startup
|
||||
static void adc_init() {
|
||||
ADCSRA = _BV(ADEN) | _BV(ADSC) | _BV(ADIF) | 0x07;
|
||||
DIDR0 = 0;
|
||||
#ifdef DIDR2
|
||||
DIDR2 = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Called by Temperature::init for each sensor at startup
|
||||
static void adc_enable(const uint8_t ch) {
|
||||
#ifdef DIDR2
|
||||
if (ch > 7) { SBI(DIDR2, ch & 0x07); return; }
|
||||
#endif
|
||||
SBI(DIDR0, ch);
|
||||
}
|
||||
|
||||
// Begin ADC sampling on the given channel. Called from Temperature::isr!
|
||||
static void adc_start(const uint8_t ch) {
|
||||
#ifdef MUX5
|
||||
ADCSRB = ch > 7 ? _BV(MUX5) : 0;
|
||||
#else
|
||||
ADCSRB = 0;
|
||||
#endif
|
||||
ADMUX = _BV(REFS0) | (ch & 0x07);
|
||||
SBI(ADCSRA, ADSC);
|
||||
}
|
||||
|
||||
// Is the ADC ready for reading?
|
||||
static bool adc_ready() { return !TEST(ADCSRA, ADSC); }
|
||||
|
||||
// The current value of the ADC register
|
||||
static __typeof__(ADC) adc_value() { return ADC; }
|
||||
|
||||
/**
|
||||
* init_pwm_timers
|
||||
* Set the default frequency for timers 2-5 to 1000HZ
|
||||
*/
|
||||
static void init_pwm_timers();
|
||||
|
||||
/**
|
||||
* Set the PWM duty cycle for the pin to the given value.
|
||||
* Optionally invert the duty cycle [default = false]
|
||||
* Optionally change the scale of the provided value to enable finer PWM duty control [default = 255]
|
||||
*/
|
||||
static void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size=255, const bool invert=false);
|
||||
|
||||
/**
|
||||
* Set the frequency of the timer for the given pin as close as
|
||||
* possible to the provided desired frequency. Internally calculate
|
||||
* the required waveform generation mode, prescaler, and resolution
|
||||
* values and set timer registers accordingly.
|
||||
* NOTE that the frequency is applied to all pins on the timer (Ex OC3A, OC3B and OC3B)
|
||||
* NOTE that there are limitations, particularly if using TIMER2. (see Configuration_adv.h -> FAST_PWM_FAN Settings)
|
||||
*/
|
||||
static void set_pwm_frequency(const pin_t pin, const uint16_t f_desired);
|
||||
};
|
|
@ -0,0 +1,252 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Adapted from Arduino Sd2Card Library
|
||||
* Copyright (c) 2009 by William Greiman
|
||||
*/
|
||||
|
||||
/**
|
||||
* HAL for AVR - SPI functions
|
||||
*/
|
||||
|
||||
#ifdef __AVR__
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
void spiBegin() {
|
||||
#if PIN_EXISTS(SD_SS)
|
||||
// Do not init HIGH for boards with pin 4 used as Fans or Heaters or otherwise, not likely to have multiple SPI devices anyway.
|
||||
#if defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) || defined(__AVR_ATmega1284P__)
|
||||
// SS must be in output mode even it is not chip select
|
||||
SET_OUTPUT(SD_SS_PIN);
|
||||
#else
|
||||
// set SS high - may be chip select for another SPI device
|
||||
OUT_WRITE(SD_SS_PIN, HIGH);
|
||||
#endif
|
||||
#endif
|
||||
SET_OUTPUT(SD_SCK_PIN);
|
||||
SET_INPUT(SD_MISO_PIN);
|
||||
SET_OUTPUT(SD_MOSI_PIN);
|
||||
|
||||
IF_DISABLED(SOFTWARE_SPI, spiInit(SPI_HALF_SPEED));
|
||||
}
|
||||
|
||||
#if NONE(SOFTWARE_SPI, FORCE_SOFT_SPI)
|
||||
|
||||
// ------------------------
|
||||
// Hardware SPI
|
||||
// ------------------------
|
||||
|
||||
// make sure SPCR rate is in expected bits
|
||||
#if (SPR0 != 0 || SPR1 != 1)
|
||||
#error "unexpected SPCR bits"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Initialize hardware SPI
|
||||
* Set SCK rate to F_CPU/pow(2, 1 + spiRate) for spiRate [0,6]
|
||||
*/
|
||||
void spiInit(uint8_t spiRate) {
|
||||
// See avr processor documentation
|
||||
CBI(
|
||||
#ifdef PRR
|
||||
PRR
|
||||
#elif defined(PRR0)
|
||||
PRR0
|
||||
#endif
|
||||
, PRSPI
|
||||
);
|
||||
|
||||
SPCR = _BV(SPE) | _BV(MSTR) | (spiRate >> 1);
|
||||
SPSR = spiRate & 1 || spiRate == 6 ? 0 : _BV(SPI2X);
|
||||
}
|
||||
|
||||
/** SPI receive a byte */
|
||||
uint8_t spiRec() {
|
||||
SPDR = 0xFF;
|
||||
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
|
||||
return SPDR;
|
||||
}
|
||||
|
||||
/** SPI read data */
|
||||
void spiRead(uint8_t *buf, uint16_t nbyte) {
|
||||
if (nbyte-- == 0) return;
|
||||
SPDR = 0xFF;
|
||||
for (uint16_t i = 0; i < nbyte; i++) {
|
||||
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
|
||||
buf[i] = SPDR;
|
||||
SPDR = 0xFF;
|
||||
}
|
||||
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
|
||||
buf[nbyte] = SPDR;
|
||||
}
|
||||
|
||||
/** SPI send a byte */
|
||||
void spiSend(uint8_t b) {
|
||||
SPDR = b;
|
||||
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
|
||||
}
|
||||
|
||||
/** SPI send block */
|
||||
void spiSendBlock(uint8_t token, const uint8_t *buf) {
|
||||
SPDR = token;
|
||||
for (uint16_t i = 0; i < 512; i += 2) {
|
||||
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
|
||||
SPDR = buf[i];
|
||||
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
|
||||
SPDR = buf[i + 1];
|
||||
}
|
||||
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
|
||||
}
|
||||
|
||||
/** begin spi transaction */
|
||||
void spiBeginTransaction(uint32_t spiClock, uint8_t bitOrder, uint8_t dataMode) {
|
||||
// Based on Arduino SPI library
|
||||
// Clock settings are defined as follows. Note that this shows SPI2X
|
||||
// inverted, so the bits form increasing numbers. Also note that
|
||||
// fosc/64 appears twice
|
||||
// SPR1 SPR0 ~SPI2X Freq
|
||||
// 0 0 0 fosc/2
|
||||
// 0 0 1 fosc/4
|
||||
// 0 1 0 fosc/8
|
||||
// 0 1 1 fosc/16
|
||||
// 1 0 0 fosc/32
|
||||
// 1 0 1 fosc/64
|
||||
// 1 1 0 fosc/64
|
||||
// 1 1 1 fosc/128
|
||||
|
||||
// We find the fastest clock that is less than or equal to the
|
||||
// given clock rate. The clock divider that results in clock_setting
|
||||
// is 2 ^^ (clock_div + 1). If nothing is slow enough, we'll use the
|
||||
// slowest (128 == 2 ^^ 7, so clock_div = 6).
|
||||
uint8_t clockDiv;
|
||||
|
||||
// When the clock is known at compiletime, use this if-then-else
|
||||
// cascade, which the compiler knows how to completely optimize
|
||||
// away. When clock is not known, use a loop instead, which generates
|
||||
// shorter code.
|
||||
if (__builtin_constant_p(spiClock)) {
|
||||
if (spiClock >= F_CPU / 2) clockDiv = 0;
|
||||
else if (spiClock >= F_CPU / 4) clockDiv = 1;
|
||||
else if (spiClock >= F_CPU / 8) clockDiv = 2;
|
||||
else if (spiClock >= F_CPU / 16) clockDiv = 3;
|
||||
else if (spiClock >= F_CPU / 32) clockDiv = 4;
|
||||
else if (spiClock >= F_CPU / 64) clockDiv = 5;
|
||||
else clockDiv = 6;
|
||||
}
|
||||
else {
|
||||
uint32_t clockSetting = F_CPU / 2;
|
||||
clockDiv = 0;
|
||||
while (clockDiv < 6 && spiClock < clockSetting) {
|
||||
clockSetting /= 2;
|
||||
clockDiv++;
|
||||
}
|
||||
}
|
||||
|
||||
// Compensate for the duplicate fosc/64
|
||||
if (clockDiv == 6) clockDiv = 7;
|
||||
|
||||
// Invert the SPI2X bit
|
||||
clockDiv ^= 0x1;
|
||||
|
||||
SPCR = _BV(SPE) | _BV(MSTR) | ((bitOrder == LSBFIRST) ? _BV(DORD) : 0) |
|
||||
(dataMode << CPHA) | ((clockDiv >> 1) << SPR0);
|
||||
SPSR = clockDiv | 0x01;
|
||||
}
|
||||
|
||||
#else // SOFTWARE_SPI || FORCE_SOFT_SPI
|
||||
|
||||
// ------------------------
|
||||
// Software SPI
|
||||
// ------------------------
|
||||
|
||||
// nop to tune soft SPI timing
|
||||
#define nop asm volatile ("\tnop\n")
|
||||
|
||||
void spiInit(uint8_t) { /* do nothing */ }
|
||||
|
||||
// Begin SPI transaction, set clock, bit order, data mode
|
||||
void spiBeginTransaction(uint32_t spiClock, uint8_t bitOrder, uint8_t dataMode) { /* do nothing */ }
|
||||
|
||||
// Soft SPI receive byte
|
||||
uint8_t spiRec() {
|
||||
uint8_t data = 0;
|
||||
// no interrupts during byte receive - about 8µs
|
||||
cli();
|
||||
// output pin high - like sending 0xFF
|
||||
WRITE(SD_MOSI_PIN, HIGH);
|
||||
|
||||
for (uint8_t i = 0; i < 8; ++i) {
|
||||
WRITE(SD_SCK_PIN, HIGH);
|
||||
|
||||
nop; // adjust so SCK is nice
|
||||
nop;
|
||||
|
||||
data <<= 1;
|
||||
|
||||
if (READ(SD_MISO_PIN)) data |= 1;
|
||||
|
||||
WRITE(SD_SCK_PIN, LOW);
|
||||
}
|
||||
|
||||
sei();
|
||||
return data;
|
||||
}
|
||||
|
||||
// Soft SPI read data
|
||||
void spiRead(uint8_t *buf, uint16_t nbyte) {
|
||||
for (uint16_t i = 0; i < nbyte; i++)
|
||||
buf[i] = spiRec();
|
||||
}
|
||||
|
||||
// Soft SPI send byte
|
||||
void spiSend(uint8_t data) {
|
||||
// no interrupts during byte send - about 8µs
|
||||
cli();
|
||||
for (uint8_t i = 0; i < 8; ++i) {
|
||||
WRITE(SD_SCK_PIN, LOW);
|
||||
WRITE(SD_MOSI_PIN, data & 0x80);
|
||||
data <<= 1;
|
||||
WRITE(SD_SCK_PIN, HIGH);
|
||||
}
|
||||
|
||||
nop; // hold SCK high for a few ns
|
||||
nop;
|
||||
nop;
|
||||
nop;
|
||||
|
||||
WRITE(SD_SCK_PIN, LOW);
|
||||
|
||||
sei();
|
||||
}
|
||||
|
||||
// Soft SPI send block
|
||||
void spiSendBlock(uint8_t token, const uint8_t *buf) {
|
||||
spiSend(token);
|
||||
for (uint16_t i = 0; i < 512; i++)
|
||||
spiSend(buf[i]);
|
||||
}
|
||||
|
||||
#endif // SOFTWARE_SPI || FORCE_SOFT_SPI
|
||||
|
||||
#endif // __AVR__
|
|
@ -0,0 +1,26 @@
|
|||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <SPI.h>
|
||||
|
||||
using MarlinSPI = SPIClass;
|
|
@ -0,0 +1,652 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* MarlinSerial.cpp - Hardware serial library for Wiring
|
||||
* Copyright (c) 2006 Nicholas Zambetti. All right reserved.
|
||||
*
|
||||
* Modified 23 November 2006 by David A. Mellis
|
||||
* Modified 28 September 2010 by Mark Sproul
|
||||
* Modified 14 February 2016 by Andreas Hardtung (added tx buffer)
|
||||
* Modified 01 October 2017 by Eduardo José Tagle (added XON/XOFF)
|
||||
* Modified 10 June 2018 by Eduardo José Tagle (See #10991)
|
||||
* Templatized 01 October 2018 by Eduardo José Tagle to allow multiple instances
|
||||
*/
|
||||
|
||||
#ifdef __AVR__
|
||||
|
||||
// Disable HardwareSerial.cpp to support chips without a UART (Attiny, etc.)
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#if !defined(USBCON) && (defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) || defined(UBRR2H) || defined(UBRR3H))
|
||||
|
||||
#include "MarlinSerial.h"
|
||||
#include "../../MarlinCore.h"
|
||||
|
||||
#if ENABLED(DIRECT_STEPPING)
|
||||
#include "../../feature/direct_stepping.h"
|
||||
#endif
|
||||
|
||||
template<typename Cfg> typename MarlinSerial<Cfg>::ring_buffer_r MarlinSerial<Cfg>::rx_buffer = { 0, 0, { 0 } };
|
||||
template<typename Cfg> typename MarlinSerial<Cfg>::ring_buffer_t MarlinSerial<Cfg>::tx_buffer = { 0 };
|
||||
template<typename Cfg> bool MarlinSerial<Cfg>::_written = false;
|
||||
template<typename Cfg> uint8_t MarlinSerial<Cfg>::xon_xoff_state = MarlinSerial<Cfg>::XON_XOFF_CHAR_SENT | MarlinSerial<Cfg>::XON_CHAR;
|
||||
template<typename Cfg> uint8_t MarlinSerial<Cfg>::rx_dropped_bytes = 0;
|
||||
template<typename Cfg> uint8_t MarlinSerial<Cfg>::rx_buffer_overruns = 0;
|
||||
template<typename Cfg> uint8_t MarlinSerial<Cfg>::rx_framing_errors = 0;
|
||||
template<typename Cfg> typename MarlinSerial<Cfg>::ring_buffer_pos_t MarlinSerial<Cfg>::rx_max_enqueued = 0;
|
||||
|
||||
// A SW memory barrier, to ensure GCC does not overoptimize loops
|
||||
#define sw_barrier() asm volatile("": : :"memory");
|
||||
|
||||
#include "../../feature/e_parser.h"
|
||||
|
||||
// "Atomically" read the RX head index value without disabling interrupts:
|
||||
// This MUST be called with RX interrupts enabled, and CAN'T be called
|
||||
// from the RX ISR itself!
|
||||
template<typename Cfg>
|
||||
FORCE_INLINE typename MarlinSerial<Cfg>::ring_buffer_pos_t MarlinSerial<Cfg>::atomic_read_rx_head() {
|
||||
if (Cfg::RX_SIZE > 256) {
|
||||
// Keep reading until 2 consecutive reads return the same value,
|
||||
// meaning there was no update in-between caused by an interrupt.
|
||||
// This works because serial RX interrupts happen at a slower rate
|
||||
// than successive reads of a variable, so 2 consecutive reads with
|
||||
// the same value means no interrupt updated it.
|
||||
ring_buffer_pos_t vold, vnew = rx_buffer.head;
|
||||
sw_barrier();
|
||||
do {
|
||||
vold = vnew;
|
||||
vnew = rx_buffer.head;
|
||||
sw_barrier();
|
||||
} while (vold != vnew);
|
||||
return vnew;
|
||||
}
|
||||
else {
|
||||
// With an 8bit index, reads are always atomic. No need for special handling
|
||||
return rx_buffer.head;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Cfg>
|
||||
volatile bool MarlinSerial<Cfg>::rx_tail_value_not_stable = false;
|
||||
template<typename Cfg>
|
||||
volatile uint16_t MarlinSerial<Cfg>::rx_tail_value_backup = 0;
|
||||
|
||||
// Set RX tail index, taking into account the RX ISR could interrupt
|
||||
// the write to this variable in the middle - So a backup strategy
|
||||
// is used to ensure reads of the correct values.
|
||||
// -Must NOT be called from the RX ISR -
|
||||
template<typename Cfg>
|
||||
FORCE_INLINE void MarlinSerial<Cfg>::atomic_set_rx_tail(typename MarlinSerial<Cfg>::ring_buffer_pos_t value) {
|
||||
if (Cfg::RX_SIZE > 256) {
|
||||
// Store the new value in the backup
|
||||
rx_tail_value_backup = value;
|
||||
sw_barrier();
|
||||
// Flag we are about to change the true value
|
||||
rx_tail_value_not_stable = true;
|
||||
sw_barrier();
|
||||
// Store the new value
|
||||
rx_buffer.tail = value;
|
||||
sw_barrier();
|
||||
// Signal the new value is completely stored into the value
|
||||
rx_tail_value_not_stable = false;
|
||||
sw_barrier();
|
||||
}
|
||||
else
|
||||
rx_buffer.tail = value;
|
||||
}
|
||||
|
||||
// Get the RX tail index, taking into account the read could be
|
||||
// interrupting in the middle of the update of that index value
|
||||
// -Called from the RX ISR -
|
||||
template<typename Cfg>
|
||||
FORCE_INLINE typename MarlinSerial<Cfg>::ring_buffer_pos_t MarlinSerial<Cfg>::atomic_read_rx_tail() {
|
||||
if (Cfg::RX_SIZE > 256) {
|
||||
// If the true index is being modified, return the backup value
|
||||
if (rx_tail_value_not_stable) return rx_tail_value_backup;
|
||||
}
|
||||
// The true index is stable, return it
|
||||
return rx_buffer.tail;
|
||||
}
|
||||
|
||||
// (called with RX interrupts disabled)
|
||||
template<typename Cfg>
|
||||
FORCE_INLINE void MarlinSerial<Cfg>::store_rxd_char() {
|
||||
|
||||
static EmergencyParser::State emergency_state; // = EP_RESET
|
||||
|
||||
// This must read the R_UCSRA register before reading the received byte to detect error causes
|
||||
if (Cfg::DROPPED_RX && B_DOR && !++rx_dropped_bytes) --rx_dropped_bytes;
|
||||
if (Cfg::RX_OVERRUNS && B_DOR && !++rx_buffer_overruns) --rx_buffer_overruns;
|
||||
if (Cfg::RX_FRAMING_ERRORS && B_FE && !++rx_framing_errors) --rx_framing_errors;
|
||||
|
||||
// Read the character from the USART
|
||||
uint8_t c = R_UDR;
|
||||
|
||||
#if ENABLED(DIRECT_STEPPING)
|
||||
if (page_manager.maybe_store_rxd_char(c)) return;
|
||||
#endif
|
||||
|
||||
// Get the tail - Nothing can alter its value while this ISR is executing, but there's
|
||||
// a chance that this ISR interrupted the main process while it was updating the index.
|
||||
// The backup mechanism ensures the correct value is always returned.
|
||||
const ring_buffer_pos_t t = atomic_read_rx_tail();
|
||||
|
||||
// Get the head pointer - This ISR is the only one that modifies its value, so it's safe to read here
|
||||
ring_buffer_pos_t h = rx_buffer.head;
|
||||
|
||||
// Get the next element
|
||||
ring_buffer_pos_t i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(Cfg::RX_SIZE - 1);
|
||||
|
||||
if (Cfg::EMERGENCYPARSER) emergency_parser.update(emergency_state, c);
|
||||
|
||||
// If the character is to be stored at the index just before the tail
|
||||
// (such that the head would advance to the current tail), the RX FIFO is
|
||||
// full, so don't write the character or advance the head.
|
||||
if (i != t) {
|
||||
rx_buffer.buffer[h] = c;
|
||||
h = i;
|
||||
}
|
||||
else if (Cfg::DROPPED_RX && !++rx_dropped_bytes)
|
||||
--rx_dropped_bytes;
|
||||
|
||||
if (Cfg::MAX_RX_QUEUED) {
|
||||
// Calculate count of bytes stored into the RX buffer
|
||||
const ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(Cfg::RX_SIZE - 1);
|
||||
|
||||
// Keep track of the maximum count of enqueued bytes
|
||||
NOLESS(rx_max_enqueued, rx_count);
|
||||
}
|
||||
|
||||
if (Cfg::XONOFF) {
|
||||
// If the last char that was sent was an XON
|
||||
if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XON_CHAR) {
|
||||
|
||||
// Bytes stored into the RX buffer
|
||||
const ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(Cfg::RX_SIZE - 1);
|
||||
|
||||
// If over 12.5% of RX buffer capacity, send XOFF before running out of
|
||||
// RX buffer space .. 325 bytes @ 250kbits/s needed to let the host react
|
||||
// and stop sending bytes. This translates to 13mS propagation time.
|
||||
if (rx_count >= (Cfg::RX_SIZE) / 8) {
|
||||
|
||||
// At this point, definitely no TX interrupt was executing, since the TX ISR can't be preempted.
|
||||
// Don't enable the TX interrupt here as a means to trigger the XOFF char, because if it happens
|
||||
// to be in the middle of trying to disable the RX interrupt in the main program, eventually the
|
||||
// enabling of the TX interrupt could be undone. The ONLY reliable thing this can do to ensure
|
||||
// the sending of the XOFF char is to send it HERE AND NOW.
|
||||
|
||||
// About to send the XOFF char
|
||||
xon_xoff_state = XOFF_CHAR | XON_XOFF_CHAR_SENT;
|
||||
|
||||
// Wait until the TX register becomes empty and send it - Here there could be a problem
|
||||
// - While waiting for the TX register to empty, the RX register could receive a new
|
||||
// character. This must also handle that situation!
|
||||
while (!B_UDRE) {
|
||||
|
||||
if (B_RXC) {
|
||||
// A char arrived while waiting for the TX buffer to be empty - Receive and process it!
|
||||
|
||||
i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(Cfg::RX_SIZE - 1);
|
||||
|
||||
// Read the character from the USART
|
||||
c = R_UDR;
|
||||
|
||||
if (Cfg::EMERGENCYPARSER) emergency_parser.update(emergency_state, c);
|
||||
|
||||
// If the character is to be stored at the index just before the tail
|
||||
// (such that the head would advance to the current tail), the FIFO is
|
||||
// full, so don't write the character or advance the head.
|
||||
if (i != t) {
|
||||
rx_buffer.buffer[h] = c;
|
||||
h = i;
|
||||
}
|
||||
else if (Cfg::DROPPED_RX && !++rx_dropped_bytes)
|
||||
--rx_dropped_bytes;
|
||||
}
|
||||
sw_barrier();
|
||||
}
|
||||
|
||||
R_UDR = XOFF_CHAR;
|
||||
|
||||
// Clear the TXC bit -- "can be cleared by writing a one to its bit
|
||||
// location". This makes sure flush() won't return until the bytes
|
||||
// actually got written
|
||||
B_TXC = 1;
|
||||
|
||||
// At this point there could be a race condition between the write() function
|
||||
// and this sending of the XOFF char. This interrupt could happen between the
|
||||
// wait to be empty TX buffer loop and the actual write of the character. Since
|
||||
// the TX buffer is full because it's sending the XOFF char, the only way to be
|
||||
// sure the write() function will succeed is to wait for the XOFF char to be
|
||||
// completely sent. Since an extra character could be received during the wait
|
||||
// it must also be handled!
|
||||
while (!B_UDRE) {
|
||||
|
||||
if (B_RXC) {
|
||||
// A char arrived while waiting for the TX buffer to be empty - Receive and process it!
|
||||
|
||||
i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(Cfg::RX_SIZE - 1);
|
||||
|
||||
// Read the character from the USART
|
||||
c = R_UDR;
|
||||
|
||||
if (Cfg::EMERGENCYPARSER)
|
||||
emergency_parser.update(emergency_state, c);
|
||||
|
||||
// If the character is to be stored at the index just before the tail
|
||||
// (such that the head would advance to the current tail), the FIFO is
|
||||
// full, so don't write the character or advance the head.
|
||||
if (i != t) {
|
||||
rx_buffer.buffer[h] = c;
|
||||
h = i;
|
||||
}
|
||||
else if (Cfg::DROPPED_RX && !++rx_dropped_bytes)
|
||||
--rx_dropped_bytes;
|
||||
}
|
||||
sw_barrier();
|
||||
}
|
||||
|
||||
// At this point everything is ready. The write() function won't
|
||||
// have any issues writing to the UART TX register if it needs to!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Store the new head value - The main loop will retry until the value is stable
|
||||
rx_buffer.head = h;
|
||||
}
|
||||
|
||||
// (called with TX irqs disabled)
|
||||
template<typename Cfg>
|
||||
FORCE_INLINE void MarlinSerial<Cfg>::_tx_udr_empty_irq() {
|
||||
if (Cfg::TX_SIZE > 0) {
|
||||
// Read positions
|
||||
uint8_t t = tx_buffer.tail;
|
||||
const uint8_t h = tx_buffer.head;
|
||||
|
||||
if (Cfg::XONOFF) {
|
||||
// If an XON char is pending to be sent, do it now
|
||||
if (xon_xoff_state == XON_CHAR) {
|
||||
|
||||
// Send the character
|
||||
R_UDR = XON_CHAR;
|
||||
|
||||
// clear the TXC bit -- "can be cleared by writing a one to its bit
|
||||
// location". This makes sure flush() won't return until the bytes
|
||||
// actually got written
|
||||
B_TXC = 1;
|
||||
|
||||
// Remember we sent it.
|
||||
xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
|
||||
|
||||
// If nothing else to transmit, just disable TX interrupts.
|
||||
if (h == t) B_UDRIE = 0; // (Non-atomic, could be reenabled by the main program, but eventually this will succeed)
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If nothing to transmit, just disable TX interrupts. This could
|
||||
// happen as the result of the non atomicity of the disabling of RX
|
||||
// interrupts that could end reenabling TX interrupts as a side effect.
|
||||
if (h == t) {
|
||||
B_UDRIE = 0; // (Non-atomic, could be reenabled by the main program, but eventually this will succeed)
|
||||
return;
|
||||
}
|
||||
|
||||
// There is something to TX, Send the next byte
|
||||
const uint8_t c = tx_buffer.buffer[t];
|
||||
t = (t + 1) & (Cfg::TX_SIZE - 1);
|
||||
R_UDR = c;
|
||||
tx_buffer.tail = t;
|
||||
|
||||
// Clear the TXC bit (by writing a one to its bit location).
|
||||
// Ensures flush() won't return until the bytes are actually written/
|
||||
B_TXC = 1;
|
||||
|
||||
// Disable interrupts if there is nothing to transmit following this byte
|
||||
if (h == t) B_UDRIE = 0; // (Non-atomic, could be reenabled by the main program, but eventually this will succeed)
|
||||
}
|
||||
}
|
||||
|
||||
// Public Methods
|
||||
template<typename Cfg>
|
||||
void MarlinSerial<Cfg>::begin(const long baud) {
|
||||
uint16_t baud_setting;
|
||||
bool useU2X = true;
|
||||
|
||||
#if F_CPU == 16000000UL && SERIAL_PORT == 0
|
||||
// Hard-coded exception for compatibility with the bootloader shipped
|
||||
// with the Duemilanove and previous boards, and the firmware on the
|
||||
// 8U2 on the Uno and Mega 2560.
|
||||
if (baud == 57600) useU2X = false;
|
||||
#endif
|
||||
|
||||
R_UCSRA = 0;
|
||||
if (useU2X) {
|
||||
B_U2X = 1;
|
||||
baud_setting = (F_CPU / 4 / baud - 1) / 2;
|
||||
}
|
||||
else
|
||||
baud_setting = (F_CPU / 8 / baud - 1) / 2;
|
||||
|
||||
// assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register)
|
||||
R_UBRRH = baud_setting >> 8;
|
||||
R_UBRRL = baud_setting;
|
||||
|
||||
B_RXEN = 1;
|
||||
B_TXEN = 1;
|
||||
B_RXCIE = 1;
|
||||
if (Cfg::TX_SIZE > 0) B_UDRIE = 0;
|
||||
_written = false;
|
||||
}
|
||||
|
||||
template<typename Cfg>
|
||||
void MarlinSerial<Cfg>::end() {
|
||||
B_RXEN = 0;
|
||||
B_TXEN = 0;
|
||||
B_RXCIE = 0;
|
||||
B_UDRIE = 0;
|
||||
}
|
||||
|
||||
template<typename Cfg>
|
||||
int MarlinSerial<Cfg>::peek() {
|
||||
const ring_buffer_pos_t h = atomic_read_rx_head(), t = rx_buffer.tail;
|
||||
return h == t ? -1 : rx_buffer.buffer[t];
|
||||
}
|
||||
|
||||
template<typename Cfg>
|
||||
int MarlinSerial<Cfg>::read() {
|
||||
const ring_buffer_pos_t h = atomic_read_rx_head();
|
||||
|
||||
// Read the tail. Main thread owns it, so it is safe to directly read it
|
||||
ring_buffer_pos_t t = rx_buffer.tail;
|
||||
|
||||
// If nothing to read, return now
|
||||
if (h == t) return -1;
|
||||
|
||||
// Get the next char
|
||||
const int v = rx_buffer.buffer[t];
|
||||
t = (ring_buffer_pos_t)(t + 1) & (Cfg::RX_SIZE - 1);
|
||||
|
||||
// Advance tail - Making sure the RX ISR will always get an stable value, even
|
||||
// if it interrupts the writing of the value of that variable in the middle.
|
||||
atomic_set_rx_tail(t);
|
||||
|
||||
if (Cfg::XONOFF) {
|
||||
// If the XOFF char was sent, or about to be sent...
|
||||
if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XOFF_CHAR) {
|
||||
// Get count of bytes in the RX buffer
|
||||
const ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(Cfg::RX_SIZE - 1);
|
||||
if (rx_count < (Cfg::RX_SIZE) / 10) {
|
||||
if (Cfg::TX_SIZE > 0) {
|
||||
// Signal we want an XON character to be sent.
|
||||
xon_xoff_state = XON_CHAR;
|
||||
// Enable TX ISR. Non atomic, but it will eventually enable them
|
||||
B_UDRIE = 1;
|
||||
}
|
||||
else {
|
||||
// If not using TX interrupts, we must send the XON char now
|
||||
xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
|
||||
while (!B_UDRE) sw_barrier();
|
||||
R_UDR = XON_CHAR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
template<typename Cfg>
|
||||
typename MarlinSerial<Cfg>::ring_buffer_pos_t MarlinSerial<Cfg>::available() {
|
||||
const ring_buffer_pos_t h = atomic_read_rx_head(), t = rx_buffer.tail;
|
||||
return (ring_buffer_pos_t)(Cfg::RX_SIZE + h - t) & (Cfg::RX_SIZE - 1);
|
||||
}
|
||||
|
||||
template<typename Cfg>
|
||||
void MarlinSerial<Cfg>::flush() {
|
||||
|
||||
// Set the tail to the head:
|
||||
// - Read the RX head index in a safe way. (See atomic_read_rx_head.)
|
||||
// - Set the tail, making sure the RX ISR will always get a stable value, even
|
||||
// if it interrupts the writing of the value of that variable in the middle.
|
||||
atomic_set_rx_tail(atomic_read_rx_head());
|
||||
|
||||
if (Cfg::XONOFF) {
|
||||
// If the XOFF char was sent, or about to be sent...
|
||||
if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XOFF_CHAR) {
|
||||
if (Cfg::TX_SIZE > 0) {
|
||||
// Signal we want an XON character to be sent.
|
||||
xon_xoff_state = XON_CHAR;
|
||||
// Enable TX ISR. Non atomic, but it will eventually enable it.
|
||||
B_UDRIE = 1;
|
||||
}
|
||||
else {
|
||||
// If not using TX interrupts, we must send the XON char now
|
||||
xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
|
||||
while (!B_UDRE) sw_barrier();
|
||||
R_UDR = XON_CHAR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Cfg>
|
||||
void MarlinSerial<Cfg>::write(const uint8_t c) {
|
||||
if (Cfg::TX_SIZE == 0) {
|
||||
|
||||
_written = true;
|
||||
while (!B_UDRE) sw_barrier();
|
||||
R_UDR = c;
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
_written = true;
|
||||
|
||||
// If the TX interrupts are disabled and the data register
|
||||
// is empty, just write the byte to the data register and
|
||||
// be done. This shortcut helps significantly improve the
|
||||
// effective datarate at high (>500kbit/s) bitrates, where
|
||||
// interrupt overhead becomes a slowdown.
|
||||
// Yes, there is a race condition between the sending of the
|
||||
// XOFF char at the RX ISR, but it is properly handled there
|
||||
if (!B_UDRIE && B_UDRE) {
|
||||
R_UDR = c;
|
||||
|
||||
// clear the TXC bit -- "can be cleared by writing a one to its bit
|
||||
// location". This makes sure flush() won't return until the bytes
|
||||
// actually got written
|
||||
B_TXC = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
const uint8_t i = (tx_buffer.head + 1) & (Cfg::TX_SIZE - 1);
|
||||
|
||||
// If global interrupts are disabled (as the result of being called from an ISR)...
|
||||
if (!hal.isr_state()) {
|
||||
|
||||
// Make room by polling if it is possible to transmit, and do so!
|
||||
while (i == tx_buffer.tail) {
|
||||
|
||||
// If we can transmit another byte, do it.
|
||||
if (B_UDRE) _tx_udr_empty_irq();
|
||||
|
||||
// Make sure compiler rereads tx_buffer.tail
|
||||
sw_barrier();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Interrupts are enabled, just wait until there is space
|
||||
while (i == tx_buffer.tail) sw_barrier();
|
||||
}
|
||||
|
||||
// Store new char. head is always safe to move
|
||||
tx_buffer.buffer[tx_buffer.head] = c;
|
||||
tx_buffer.head = i;
|
||||
|
||||
// Enable TX ISR - Non atomic, but it will eventually enable TX ISR
|
||||
B_UDRIE = 1;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Cfg>
|
||||
void MarlinSerial<Cfg>::flushTX() {
|
||||
|
||||
if (Cfg::TX_SIZE == 0) {
|
||||
// No bytes written, no need to flush. This special case is needed since there's
|
||||
// no way to force the TXC (transmit complete) bit to 1 during initialization.
|
||||
if (!_written) return;
|
||||
|
||||
// Wait until everything was transmitted
|
||||
while (!B_TXC) sw_barrier();
|
||||
|
||||
// At this point nothing is queued anymore (DRIE is disabled) and
|
||||
// the hardware finished transmission (TXC is set).
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
// No bytes written, no need to flush. This special case is needed since there's
|
||||
// no way to force the TXC (transmit complete) bit to 1 during initialization.
|
||||
if (!_written) return;
|
||||
|
||||
// If global interrupts are disabled (as the result of being called from an ISR)...
|
||||
if (!hal.isr_state()) {
|
||||
|
||||
// Wait until everything was transmitted - We must do polling, as interrupts are disabled
|
||||
while (tx_buffer.head != tx_buffer.tail || !B_TXC) {
|
||||
|
||||
// If there is more space, send an extra character
|
||||
if (B_UDRE) _tx_udr_empty_irq();
|
||||
|
||||
sw_barrier();
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
// Wait until everything was transmitted
|
||||
while (tx_buffer.head != tx_buffer.tail || !B_TXC) sw_barrier();
|
||||
}
|
||||
|
||||
// At this point nothing is queued anymore (DRIE is disabled) and
|
||||
// the hardware finished transmission (TXC is set).
|
||||
}
|
||||
}
|
||||
|
||||
// Hookup ISR handlers
|
||||
ISR(SERIAL_REGNAME(USART, SERIAL_PORT, _RX_vect)) {
|
||||
MarlinSerial<MarlinSerialCfg<SERIAL_PORT>>::store_rxd_char();
|
||||
}
|
||||
|
||||
ISR(SERIAL_REGNAME(USART, SERIAL_PORT, _UDRE_vect)) {
|
||||
MarlinSerial<MarlinSerialCfg<SERIAL_PORT>>::_tx_udr_empty_irq();
|
||||
}
|
||||
|
||||
// Because of the template definition above, it's required to instantiate the template to have all methods generated
|
||||
template class MarlinSerial< MarlinSerialCfg<SERIAL_PORT> >;
|
||||
MSerialT1 customizedSerial1(MSerialT1::HasEmergencyParser);
|
||||
|
||||
#ifdef SERIAL_PORT_2
|
||||
|
||||
// Hookup ISR handlers
|
||||
ISR(SERIAL_REGNAME(USART, SERIAL_PORT_2, _RX_vect)) {
|
||||
MarlinSerial<MarlinSerialCfg<SERIAL_PORT_2>>::store_rxd_char();
|
||||
}
|
||||
|
||||
ISR(SERIAL_REGNAME(USART, SERIAL_PORT_2, _UDRE_vect)) {
|
||||
MarlinSerial<MarlinSerialCfg<SERIAL_PORT_2>>::_tx_udr_empty_irq();
|
||||
}
|
||||
|
||||
template class MarlinSerial< MarlinSerialCfg<SERIAL_PORT_2> >;
|
||||
MSerialT2 customizedSerial2(MSerialT2::HasEmergencyParser);
|
||||
|
||||
#endif // SERIAL_PORT_2
|
||||
|
||||
#ifdef SERIAL_PORT_3
|
||||
|
||||
// Hookup ISR handlers
|
||||
ISR(SERIAL_REGNAME(USART, SERIAL_PORT_3, _RX_vect)) {
|
||||
MarlinSerial<MarlinSerialCfg<SERIAL_PORT_3>>::store_rxd_char();
|
||||
}
|
||||
|
||||
ISR(SERIAL_REGNAME(USART, SERIAL_PORT_3, _UDRE_vect)) {
|
||||
MarlinSerial<MarlinSerialCfg<SERIAL_PORT_3>>::_tx_udr_empty_irq();
|
||||
}
|
||||
|
||||
template class MarlinSerial< MarlinSerialCfg<SERIAL_PORT_3> >;
|
||||
MSerialT3 customizedSerial3(MSerialT3::HasEmergencyParser);
|
||||
|
||||
#endif // SERIAL_PORT_3
|
||||
|
||||
#ifdef MMU2_SERIAL_PORT
|
||||
|
||||
ISR(SERIAL_REGNAME(USART, MMU2_SERIAL_PORT, _RX_vect)) {
|
||||
MarlinSerial<MMU2SerialCfg<MMU2_SERIAL_PORT>>::store_rxd_char();
|
||||
}
|
||||
|
||||
ISR(SERIAL_REGNAME(USART, MMU2_SERIAL_PORT, _UDRE_vect)) {
|
||||
MarlinSerial<MMU2SerialCfg<MMU2_SERIAL_PORT>>::_tx_udr_empty_irq();
|
||||
}
|
||||
|
||||
template class MarlinSerial< MMU2SerialCfg<MMU2_SERIAL_PORT> >;
|
||||
MSerialMMU2 mmuSerial(MSerialMMU2::HasEmergencyParser);
|
||||
|
||||
#endif // MMU2_SERIAL_PORT
|
||||
|
||||
#ifdef LCD_SERIAL_PORT
|
||||
|
||||
ISR(SERIAL_REGNAME(USART, LCD_SERIAL_PORT, _RX_vect)) {
|
||||
MarlinSerial<LCDSerialCfg<LCD_SERIAL_PORT>>::store_rxd_char();
|
||||
}
|
||||
|
||||
ISR(SERIAL_REGNAME(USART, LCD_SERIAL_PORT, _UDRE_vect)) {
|
||||
MarlinSerial<LCDSerialCfg<LCD_SERIAL_PORT>>::_tx_udr_empty_irq();
|
||||
}
|
||||
|
||||
template class MarlinSerial< LCDSerialCfg<LCD_SERIAL_PORT> >;
|
||||
MSerialLCD lcdSerial(MSerialLCD::HasEmergencyParser);
|
||||
|
||||
#if HAS_DGUS_LCD
|
||||
template<typename Cfg>
|
||||
typename MarlinSerial<Cfg>::ring_buffer_pos_t MarlinSerial<Cfg>::get_tx_buffer_free() {
|
||||
const ring_buffer_pos_t t = tx_buffer.tail, // next byte to send.
|
||||
h = tx_buffer.head; // next pos for queue.
|
||||
int ret = t - h - 1;
|
||||
if (ret < 0) ret += Cfg::TX_SIZE + 1;
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // LCD_SERIAL_PORT
|
||||
|
||||
#endif // !USBCON && (UBRRH || UBRR0H || UBRR1H || UBRR2H || UBRR3H)
|
||||
|
||||
// For AT90USB targets use the UART for BT interfacing
|
||||
#if defined(USBCON) && ENABLED(BLUETOOTH)
|
||||
MSerialBT bluetoothSerial(false);
|
||||
#endif
|
||||
|
||||
#endif // __AVR__
|
|
@ -0,0 +1,290 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* MarlinSerial.h - Hardware serial library for Wiring
|
||||
* Copyright (c) 2006 Nicholas Zambetti. All right reserved.
|
||||
*
|
||||
* Modified 28 September 2010 by Mark Sproul
|
||||
* Modified 14 February 2016 by Andreas Hardtung (added tx buffer)
|
||||
* Modified 01 October 2017 by Eduardo José Tagle (added XON/XOFF)
|
||||
* Templatized 01 October 2018 by Eduardo José Tagle to allow multiple instances
|
||||
*/
|
||||
|
||||
#include <WString.h>
|
||||
|
||||
#include "../../inc/MarlinConfigPre.h"
|
||||
#include "../../core/types.h"
|
||||
#include "../../core/serial_hook.h"
|
||||
|
||||
#ifndef USBCON
|
||||
|
||||
// The presence of the UBRRH register is used to detect a UART.
|
||||
#define UART_PRESENT(port) ((port == 0 && (defined(UBRRH) || defined(UBRR0H))) || \
|
||||
(port == 1 && defined(UBRR1H)) || (port == 2 && defined(UBRR2H)) || \
|
||||
(port == 3 && defined(UBRR3H)))
|
||||
|
||||
// These are macros to build serial port register names for the selected SERIAL_PORT (C preprocessor
|
||||
// requires two levels of indirection to expand macro values properly)
|
||||
#define SERIAL_REGNAME(registerbase,number,suffix) _SERIAL_REGNAME(registerbase,number,suffix)
|
||||
#if SERIAL_PORT == 0 && (!defined(UBRR0H) || !defined(UDR0)) // use un-numbered registers if necessary
|
||||
#define _SERIAL_REGNAME(registerbase,number,suffix) registerbase##suffix
|
||||
#else
|
||||
#define _SERIAL_REGNAME(registerbase,number,suffix) registerbase##number##suffix
|
||||
#endif
|
||||
|
||||
// Registers used by MarlinSerial class (expanded depending on selected serial port)
|
||||
|
||||
// Templated 8bit register (generic)
|
||||
#define UART_REGISTER_DECL_BASE(registerbase, suffix) \
|
||||
template<int portNr> struct R_##registerbase##x##suffix {}
|
||||
|
||||
// Templated 8bit register (specialization for each port)
|
||||
#define UART_REGISTER_DECL(port, registerbase, suffix) \
|
||||
template<> struct R_##registerbase##x##suffix<port> { \
|
||||
constexpr R_##registerbase##x##suffix(int) {} \
|
||||
FORCE_INLINE void operator=(uint8_t newVal) const { SERIAL_REGNAME(registerbase,port,suffix) = newVal; } \
|
||||
FORCE_INLINE operator uint8_t() const { return SERIAL_REGNAME(registerbase,port,suffix); } \
|
||||
}
|
||||
|
||||
// Templated 1bit register (generic)
|
||||
#define UART_BIT_DECL_BASE(registerbase, suffix, bit) \
|
||||
template<int portNr>struct B_##bit##x {}
|
||||
|
||||
// Templated 1bit register (specialization for each port)
|
||||
#define UART_BIT_DECL(port, registerbase, suffix, bit) \
|
||||
template<> struct B_##bit##x<port> { \
|
||||
constexpr B_##bit##x(int) {} \
|
||||
FORCE_INLINE void operator=(int newVal) const { \
|
||||
if (newVal) \
|
||||
SBI(SERIAL_REGNAME(registerbase,port,suffix),SERIAL_REGNAME(bit,port,)); \
|
||||
else \
|
||||
CBI(SERIAL_REGNAME(registerbase,port,suffix),SERIAL_REGNAME(bit,port,)); \
|
||||
} \
|
||||
FORCE_INLINE operator bool() const { return TEST(SERIAL_REGNAME(registerbase,port,suffix),SERIAL_REGNAME(bit,port,)); } \
|
||||
}
|
||||
|
||||
#define UART_DECL_BASE() \
|
||||
UART_REGISTER_DECL_BASE(UCSR,A);\
|
||||
UART_REGISTER_DECL_BASE(UDR,);\
|
||||
UART_REGISTER_DECL_BASE(UBRR,H);\
|
||||
UART_REGISTER_DECL_BASE(UBRR,L);\
|
||||
UART_BIT_DECL_BASE(UCSR,B,RXEN);\
|
||||
UART_BIT_DECL_BASE(UCSR,B,TXEN);\
|
||||
UART_BIT_DECL_BASE(UCSR,A,TXC);\
|
||||
UART_BIT_DECL_BASE(UCSR,B,RXCIE);\
|
||||
UART_BIT_DECL_BASE(UCSR,A,UDRE);\
|
||||
UART_BIT_DECL_BASE(UCSR,A,FE);\
|
||||
UART_BIT_DECL_BASE(UCSR,A,DOR);\
|
||||
UART_BIT_DECL_BASE(UCSR,B,UDRIE);\
|
||||
UART_BIT_DECL_BASE(UCSR,A,RXC);\
|
||||
UART_BIT_DECL_BASE(UCSR,A,U2X)
|
||||
|
||||
#define UART_DECL(port) \
|
||||
UART_REGISTER_DECL(port,UCSR,A);\
|
||||
UART_REGISTER_DECL(port,UDR,);\
|
||||
UART_REGISTER_DECL(port,UBRR,H);\
|
||||
UART_REGISTER_DECL(port,UBRR,L);\
|
||||
UART_BIT_DECL(port,UCSR,B,RXEN);\
|
||||
UART_BIT_DECL(port,UCSR,B,TXEN);\
|
||||
UART_BIT_DECL(port,UCSR,A,TXC);\
|
||||
UART_BIT_DECL(port,UCSR,B,RXCIE);\
|
||||
UART_BIT_DECL(port,UCSR,A,UDRE);\
|
||||
UART_BIT_DECL(port,UCSR,A,FE);\
|
||||
UART_BIT_DECL(port,UCSR,A,DOR);\
|
||||
UART_BIT_DECL(port,UCSR,B,UDRIE);\
|
||||
UART_BIT_DECL(port,UCSR,A,RXC);\
|
||||
UART_BIT_DECL(port,UCSR,A,U2X)
|
||||
|
||||
// Declare empty templates
|
||||
UART_DECL_BASE();
|
||||
|
||||
// And all the specializations for each possible serial port
|
||||
#if UART_PRESENT(0)
|
||||
UART_DECL(0);
|
||||
#endif
|
||||
#if UART_PRESENT(1)
|
||||
UART_DECL(1);
|
||||
#endif
|
||||
#if UART_PRESENT(2)
|
||||
UART_DECL(2);
|
||||
#endif
|
||||
#if UART_PRESENT(3)
|
||||
UART_DECL(3);
|
||||
#endif
|
||||
|
||||
#define BYTE 0
|
||||
|
||||
template<typename Cfg>
|
||||
class MarlinSerial {
|
||||
protected:
|
||||
// Registers
|
||||
static constexpr R_UCSRxA<Cfg::PORT> R_UCSRA = 0;
|
||||
static constexpr R_UDRx<Cfg::PORT> R_UDR = 0;
|
||||
static constexpr R_UBRRxH<Cfg::PORT> R_UBRRH = 0;
|
||||
static constexpr R_UBRRxL<Cfg::PORT> R_UBRRL = 0;
|
||||
|
||||
// Bits
|
||||
static constexpr B_RXENx<Cfg::PORT> B_RXEN = 0;
|
||||
static constexpr B_TXENx<Cfg::PORT> B_TXEN = 0;
|
||||
static constexpr B_TXCx<Cfg::PORT> B_TXC = 0;
|
||||
static constexpr B_RXCIEx<Cfg::PORT> B_RXCIE = 0;
|
||||
static constexpr B_UDREx<Cfg::PORT> B_UDRE = 0;
|
||||
static constexpr B_FEx<Cfg::PORT> B_FE = 0;
|
||||
static constexpr B_DORx<Cfg::PORT> B_DOR = 0;
|
||||
static constexpr B_UDRIEx<Cfg::PORT> B_UDRIE = 0;
|
||||
static constexpr B_RXCx<Cfg::PORT> B_RXC = 0;
|
||||
static constexpr B_U2Xx<Cfg::PORT> B_U2X = 0;
|
||||
|
||||
// Base size of type on buffer size
|
||||
typedef uvalue_t(Cfg::RX_SIZE - 1) ring_buffer_pos_t;
|
||||
|
||||
struct ring_buffer_r {
|
||||
volatile ring_buffer_pos_t head, tail;
|
||||
unsigned char buffer[Cfg::RX_SIZE];
|
||||
};
|
||||
|
||||
struct ring_buffer_t {
|
||||
volatile uint8_t head, tail;
|
||||
unsigned char buffer[Cfg::TX_SIZE];
|
||||
};
|
||||
|
||||
static ring_buffer_r rx_buffer;
|
||||
static ring_buffer_t tx_buffer;
|
||||
static bool _written;
|
||||
|
||||
static constexpr uint8_t XON_XOFF_CHAR_SENT = 0x80, // XON / XOFF Character was sent
|
||||
XON_XOFF_CHAR_MASK = 0x1F; // XON / XOFF character to send
|
||||
|
||||
// XON / XOFF character definitions
|
||||
static constexpr uint8_t XON_CHAR = 17, XOFF_CHAR = 19;
|
||||
static uint8_t xon_xoff_state,
|
||||
rx_dropped_bytes,
|
||||
rx_buffer_overruns,
|
||||
rx_framing_errors;
|
||||
static ring_buffer_pos_t rx_max_enqueued;
|
||||
|
||||
FORCE_INLINE static ring_buffer_pos_t atomic_read_rx_head();
|
||||
|
||||
static volatile bool rx_tail_value_not_stable;
|
||||
static volatile uint16_t rx_tail_value_backup;
|
||||
|
||||
FORCE_INLINE static void atomic_set_rx_tail(ring_buffer_pos_t value);
|
||||
FORCE_INLINE static ring_buffer_pos_t atomic_read_rx_tail();
|
||||
|
||||
public:
|
||||
FORCE_INLINE static void store_rxd_char();
|
||||
FORCE_INLINE static void _tx_udr_empty_irq();
|
||||
|
||||
public:
|
||||
static void begin(const long);
|
||||
static void end();
|
||||
static int peek();
|
||||
static int read();
|
||||
static void flush();
|
||||
static ring_buffer_pos_t available();
|
||||
static void write(const uint8_t c);
|
||||
static void flushTX();
|
||||
#if HAS_DGUS_LCD
|
||||
static ring_buffer_pos_t get_tx_buffer_free();
|
||||
#endif
|
||||
|
||||
enum { HasEmergencyParser = Cfg::EMERGENCYPARSER };
|
||||
static bool emergency_parser_enabled() { return Cfg::EMERGENCYPARSER; }
|
||||
|
||||
FORCE_INLINE static uint8_t dropped() { return Cfg::DROPPED_RX ? rx_dropped_bytes : 0; }
|
||||
FORCE_INLINE static uint8_t buffer_overruns() { return Cfg::RX_OVERRUNS ? rx_buffer_overruns : 0; }
|
||||
FORCE_INLINE static uint8_t framing_errors() { return Cfg::RX_FRAMING_ERRORS ? rx_framing_errors : 0; }
|
||||
FORCE_INLINE static ring_buffer_pos_t rxMaxEnqueued() { return Cfg::MAX_RX_QUEUED ? rx_max_enqueued : 0; }
|
||||
};
|
||||
|
||||
template <uint8_t serial>
|
||||
struct MarlinSerialCfg {
|
||||
static constexpr int PORT = serial;
|
||||
static constexpr unsigned int RX_SIZE = RX_BUFFER_SIZE;
|
||||
static constexpr unsigned int TX_SIZE = TX_BUFFER_SIZE;
|
||||
static constexpr bool XONOFF = ENABLED(SERIAL_XON_XOFF);
|
||||
static constexpr bool EMERGENCYPARSER = ENABLED(EMERGENCY_PARSER);
|
||||
static constexpr bool DROPPED_RX = ENABLED(SERIAL_STATS_DROPPED_RX);
|
||||
static constexpr bool RX_OVERRUNS = ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS);
|
||||
static constexpr bool RX_FRAMING_ERRORS = ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS);
|
||||
static constexpr bool MAX_RX_QUEUED = ENABLED(SERIAL_STATS_MAX_RX_QUEUED);
|
||||
};
|
||||
|
||||
typedef Serial1Class< MarlinSerial< MarlinSerialCfg<SERIAL_PORT> > > MSerialT1;
|
||||
extern MSerialT1 customizedSerial1;
|
||||
|
||||
#ifdef SERIAL_PORT_2
|
||||
typedef Serial1Class< MarlinSerial< MarlinSerialCfg<SERIAL_PORT_2> > > MSerialT2;
|
||||
extern MSerialT2 customizedSerial2;
|
||||
#endif
|
||||
|
||||
#ifdef SERIAL_PORT_3
|
||||
typedef Serial1Class< MarlinSerial< MarlinSerialCfg<SERIAL_PORT_3> > > MSerialT3;
|
||||
extern MSerialT3 customizedSerial3;
|
||||
#endif
|
||||
|
||||
#endif // !USBCON
|
||||
|
||||
#ifdef MMU2_SERIAL_PORT
|
||||
template <uint8_t serial>
|
||||
struct MMU2SerialCfg {
|
||||
static constexpr int PORT = serial;
|
||||
static constexpr unsigned int RX_SIZE = 32;
|
||||
static constexpr unsigned int TX_SIZE = 32;
|
||||
static constexpr bool XONOFF = false;
|
||||
static constexpr bool EMERGENCYPARSER = false;
|
||||
static constexpr bool DROPPED_RX = false;
|
||||
static constexpr bool RX_FRAMING_ERRORS = false;
|
||||
static constexpr bool MAX_RX_QUEUED = false;
|
||||
static constexpr bool RX_OVERRUNS = false;
|
||||
};
|
||||
|
||||
typedef Serial1Class< MarlinSerial< MMU2SerialCfg<MMU2_SERIAL_PORT> > > MSerialMMU2;
|
||||
extern MSerialMMU2 mmuSerial;
|
||||
#endif
|
||||
|
||||
#ifdef LCD_SERIAL_PORT
|
||||
|
||||
template <uint8_t serial>
|
||||
struct LCDSerialCfg {
|
||||
static constexpr int PORT = serial;
|
||||
static constexpr unsigned int RX_SIZE = TERN(HAS_DGUS_LCD, DGUS_RX_BUFFER_SIZE, 64);
|
||||
static constexpr unsigned int TX_SIZE = TERN(HAS_DGUS_LCD, DGUS_TX_BUFFER_SIZE, 128);
|
||||
static constexpr bool XONOFF = false;
|
||||
static constexpr bool EMERGENCYPARSER = ENABLED(EMERGENCY_PARSER);
|
||||
static constexpr bool DROPPED_RX = false;
|
||||
static constexpr bool RX_FRAMING_ERRORS = false;
|
||||
static constexpr bool MAX_RX_QUEUED = false;
|
||||
static constexpr bool RX_OVERRUNS = ALL(HAS_DGUS_LCD, SERIAL_STATS_RX_BUFFER_OVERRUNS);
|
||||
};
|
||||
|
||||
typedef Serial1Class< MarlinSerial< LCDSerialCfg<LCD_SERIAL_PORT> > > MSerialLCD;
|
||||
extern MSerialLCD lcdSerial;
|
||||
#endif
|
||||
|
||||
// Use the UART for Bluetooth in AT90USB configurations
|
||||
#if defined(USBCON) && ENABLED(BLUETOOTH)
|
||||
typedef Serial1Class<HardwareSerial> MSerialBT;
|
||||
extern MSerialBT bluetoothSerial;
|
||||
#endif
|
|
@ -0,0 +1,225 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* servo.cpp - Interrupt driven Servo library for Arduino using 16 bit timers- Version 2
|
||||
* Copyright (c) 2009 Michael Margolis. All right reserved.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A servo is activated by creating an instance of the Servo class passing the desired pin to the attach() method.
|
||||
* The servos are pulsed in the background using the value most recently written using the write() method
|
||||
*
|
||||
* Note that analogWrite of PWM on pins associated with the timer are disabled when the first servo is attached.
|
||||
* Timers are seized as needed in groups of 12 servos - 24 servos use two timers, 48 servos will use four.
|
||||
*
|
||||
* The methods are:
|
||||
*
|
||||
* Servo - Class for manipulating servo motors connected to Arduino pins.
|
||||
*
|
||||
* attach(pin) - Attach a servo motor to an i/o pin.
|
||||
* attach(pin, min, max) - Attach to a pin, setting min and max values in microseconds
|
||||
* Default min is 544, max is 2400
|
||||
*
|
||||
* write() - Set the servo angle in degrees. (Invalid angles —over MIN_PULSE_WIDTH— are treated as µs.)
|
||||
* writeMicroseconds() - Set the servo pulse width in microseconds.
|
||||
* move(pin, angle) - Sequence of attach(pin), write(angle), safe_delay(servo_delay[servoIndex]).
|
||||
* With DEACTIVATE_SERVOS_AFTER_MOVE it detaches after servo_delay[servoIndex].
|
||||
* read() - Get the last-written servo pulse width as an angle between 0 and 180.
|
||||
* readMicroseconds() - Get the last-written servo pulse width in microseconds.
|
||||
* attached() - Return true if a servo is attached.
|
||||
* detach() - Stop an attached servo from pulsing its i/o pin.
|
||||
*/
|
||||
|
||||
#ifdef __AVR__
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#if HAS_SERVOS
|
||||
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
#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 functions common to all instances ***********************/
|
||||
|
||||
static inline void handle_interrupts(const timer16_Sequence_t timer, volatile uint16_t* TCNTn, volatile uint16_t* OCRnA) {
|
||||
int8_t cho = Channel[timer]; // Handle the prior Channel[timer] first
|
||||
if (cho < 0) // Channel -1 indicates the refresh interval completed...
|
||||
*TCNTn = 0; // ...so reset the timer
|
||||
else if (SERVO_INDEX(timer, cho) < ServoCount) // prior channel handled?
|
||||
extDigitalWrite(SERVO(timer, cho).Pin.nbr, LOW); // pulse the prior channel LOW
|
||||
|
||||
Channel[timer] = ++cho; // Handle the next channel (or 0)
|
||||
if (cho < SERVOS_PER_TIMER && SERVO_INDEX(timer, cho) < ServoCount) {
|
||||
*OCRnA = *TCNTn + SERVO(timer, cho).ticks; // set compare to current ticks plus duration
|
||||
if (SERVO(timer, cho).Pin.isActive) // activated?
|
||||
extDigitalWrite(SERVO(timer, cho).Pin.nbr, HIGH); // yes: pulse HIGH
|
||||
}
|
||||
else {
|
||||
// finished all channels so wait for the refresh period to expire before starting over
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef WIRING // Wiring pre-defines signal handlers so don't define any if compiling for the Wiring platform
|
||||
|
||||
// Interrupt handlers for Arduino
|
||||
#ifdef _useTimer1
|
||||
SIGNAL(TIMER1_COMPA_vect) { handle_interrupts(_timer1, &TCNT1, &OCR1A); }
|
||||
#endif
|
||||
|
||||
#ifdef _useTimer3
|
||||
SIGNAL(TIMER3_COMPA_vect) { handle_interrupts(_timer3, &TCNT3, &OCR3A); }
|
||||
#endif
|
||||
|
||||
#ifdef _useTimer4
|
||||
SIGNAL(TIMER4_COMPA_vect) { handle_interrupts(_timer4, &TCNT4, &OCR4A); }
|
||||
#endif
|
||||
|
||||
#ifdef _useTimer5
|
||||
SIGNAL(TIMER5_COMPA_vect) { handle_interrupts(_timer5, &TCNT5, &OCR5A); }
|
||||
#endif
|
||||
|
||||
#else // WIRING
|
||||
|
||||
// Interrupt handlers for Wiring
|
||||
#ifdef _useTimer1
|
||||
void Timer1Service() { handle_interrupts(_timer1, &TCNT1, &OCR1A); }
|
||||
#endif
|
||||
#ifdef _useTimer3
|
||||
void Timer3Service() { handle_interrupts(_timer3, &TCNT3, &OCR3A); }
|
||||
#endif
|
||||
|
||||
#endif // WIRING
|
||||
|
||||
/****************** end of static functions ******************************/
|
||||
|
||||
void initISR(const timer16_Sequence_t timer_index) {
|
||||
switch (timer_index) {
|
||||
default: break;
|
||||
|
||||
#ifdef _useTimer1
|
||||
case _timer1:
|
||||
TCCR1A = 0; // normal counting mode
|
||||
TCCR1B = _BV(CS11); // set prescaler of 8
|
||||
TCNT1 = 0; // clear the timer count
|
||||
#if defined(__AVR_ATmega8__) || defined(__AVR_ATmega128__)
|
||||
SBI(TIFR, OCF1A); // clear any pending interrupts;
|
||||
SBI(TIMSK, OCIE1A); // enable the output compare interrupt
|
||||
#else
|
||||
// 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 _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 _useTimer4
|
||||
case _timer4:
|
||||
TCCR4A = 0; // normal counting mode
|
||||
TCCR4B = _BV(CS41); // set prescaler of 8
|
||||
TCNT4 = 0; // clear the timer count
|
||||
TIFR4 = _BV(OCF4A); // clear any pending interrupts;
|
||||
TIMSK4 = _BV(OCIE4A); // enable the output compare interrupt
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef _useTimer5
|
||||
case _timer5:
|
||||
TCCR5A = 0; // normal counting mode
|
||||
TCCR5B = _BV(CS51); // set prescaler of 8
|
||||
TCNT5 = 0; // clear the timer count
|
||||
TIFR5 = _BV(OCF5A); // clear any pending interrupts;
|
||||
TIMSK5 = _BV(OCIE5A); // enable the output compare interrupt
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void finISR(const timer16_Sequence_t timer_index) {
|
||||
// Disable use of the given timer
|
||||
#ifdef WIRING
|
||||
switch (timer_index) {
|
||||
default: break;
|
||||
|
||||
case _timer1:
|
||||
CBI(
|
||||
#if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
|
||||
TIMSK1
|
||||
#else
|
||||
TIMSK
|
||||
#endif
|
||||
, OCIE1A // disable timer 1 output compare interrupt
|
||||
);
|
||||
timerDetach(TIMER1OUTCOMPAREA_INT);
|
||||
break;
|
||||
|
||||
case _timer3:
|
||||
CBI(
|
||||
#if defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
|
||||
TIMSK3
|
||||
#else
|
||||
ETIMSK
|
||||
#endif
|
||||
, OCIE3A // disable the timer3 output compare A interrupt
|
||||
);
|
||||
timerDetach(TIMER3OUTCOMPAREA_INT);
|
||||
break;
|
||||
}
|
||||
#else // !WIRING
|
||||
// For arduino - in future: call here to a currently undefined function to reset the timer
|
||||
UNUSED(timer_index);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // HAS_SERVOS
|
||||
|
||||
#endif // __AVR__
|
|
@ -0,0 +1,93 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* ServoTimers.h - Interrupt driven Servo library for Arduino using 16 bit timers- Version 2
|
||||
* Copyright (c) 2009 Michael Margolis. All right reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* Defines for 16 bit timers used with Servo library
|
||||
*
|
||||
* If _useTimerX is defined then TimerX is a 16 bit timer on the current board
|
||||
* timer16_Sequence_t enumerates the sequence that the timers should be allocated
|
||||
* _Nbr_16timers indicates how many 16 bit timers are available.
|
||||
*/
|
||||
|
||||
/**
|
||||
* AVR Only definitions
|
||||
* --------------------
|
||||
*/
|
||||
|
||||
#define TRIM_DURATION 2 // compensation ticks to trim adjust for digitalWrite delays
|
||||
#define SERVO_TIMER_PRESCALER 8 // timer prescaler
|
||||
|
||||
// Say which 16 bit timers can be used and in what order
|
||||
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||||
//#define _useTimer1
|
||||
#define _useTimer4
|
||||
#if NUM_SERVOS > SERVOS_PER_TIMER
|
||||
#define _useTimer3
|
||||
#if !HAS_MOTOR_CURRENT_PWM && SERVOS > 2 * SERVOS_PER_TIMER
|
||||
#define _useTimer5 // Timer 5 is used for motor current PWM and can't be used for servos.
|
||||
#endif
|
||||
#endif
|
||||
#elif defined(__AVR_ATmega32U4__)
|
||||
#define _useTimer3
|
||||
#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
|
||||
#define _useTimer3
|
||||
#elif defined(__AVR_ATmega128__) || defined(__AVR_ATmega1281__) || defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega2561__)
|
||||
#define _useTimer3
|
||||
#else
|
||||
// everything else
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
#ifdef _useTimer1
|
||||
_timer1,
|
||||
#endif
|
||||
#ifdef _useTimer3
|
||||
_timer3,
|
||||
#endif
|
||||
#ifdef _useTimer4
|
||||
_timer4,
|
||||
#endif
|
||||
#ifdef _useTimer5
|
||||
_timer5,
|
||||
#endif
|
||||
_Nbr_16timers
|
||||
} timer16_Sequence_t;
|
|
@ -0,0 +1,74 @@
|
|||
/**
|
||||
* 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 ANY(EEPROM_SETTINGS, SD_FIRMWARE_UPDATE)
|
||||
|
||||
/**
|
||||
* PersistentStore for Arduino-style EEPROM interface
|
||||
* with implementations supplied by the framework.
|
||||
*/
|
||||
|
||||
#include "../shared/eeprom_api.h"
|
||||
|
||||
#ifndef MARLIN_EEPROM_SIZE
|
||||
#define MARLIN_EEPROM_SIZE size_t(E2END + 1)
|
||||
#endif
|
||||
size_t PersistentStore::capacity() { return MARLIN_EEPROM_SIZE; }
|
||||
bool PersistentStore::access_start() { return true; }
|
||||
bool PersistentStore::access_finish() { return true; }
|
||||
|
||||
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
|
||||
uint16_t written = 0;
|
||||
while (size--) {
|
||||
uint8_t * const p = (uint8_t * const)pos;
|
||||
uint8_t v = *value;
|
||||
if (v != 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*/) {
|
||||
do {
|
||||
uint8_t c = eeprom_read_byte((uint8_t*)pos);
|
||||
if (writing) *value = c;
|
||||
crc16(crc, &c, 1);
|
||||
pos++;
|
||||
value++;
|
||||
} while (--size);
|
||||
return false; // always assume success for AVR's
|
||||
}
|
||||
|
||||
#endif // EEPROM_SETTINGS || SD_FIRMWARE_UPDATE
|
||||
#endif // __AVR__
|
|
@ -0,0 +1,350 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* 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 either an
|
||||
* 'external interrupt' or a 'pin change 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"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// One ISR for all EXT-Interrupts
|
||||
void endstop_ISR() { endstops.update(); }
|
||||
|
||||
/**
|
||||
* Patch for pins_arduino.h (...\Arduino\hardware\arduino\avr\variants\mega\pins_arduino.h)
|
||||
*
|
||||
* These macros for the Arduino MEGA do not include the two connected pins on Port J (D14, D15).
|
||||
* So we extend them here because these are the normal pins for Y_MIN and Y_MAX on RAMPS.
|
||||
* There are more PCI-enabled processor pins on Port J, but they are not connected to Arduino MEGA.
|
||||
*/
|
||||
#if defined(ARDUINO_AVR_MEGA2560) || defined(ARDUINO_AVR_MEGA)
|
||||
|
||||
#define digitalPinHasPCICR(p) (WITHIN(p, 10, 15) || WITHIN(p, 50, 53) || WITHIN(p, 62, 69))
|
||||
|
||||
#undef digitalPinToPCICR
|
||||
#define digitalPinToPCICR(p) (digitalPinHasPCICR(p) ? (&PCICR) : nullptr)
|
||||
|
||||
#undef digitalPinToPCICRbit
|
||||
#define digitalPinToPCICRbit(p) (WITHIN(p, 10, 13) || WITHIN(p, 50, 53) ? 0 : \
|
||||
WITHIN(p, 14, 15) ? 1 : \
|
||||
WITHIN(p, 62, 69) ? 2 : \
|
||||
0)
|
||||
|
||||
#undef digitalPinToPCMSK
|
||||
#define digitalPinToPCMSK(p) (WITHIN(p, 10, 13) || WITHIN(p, 50, 53) ? (&PCMSK0) : \
|
||||
WITHIN(p, 14, 15) ? (&PCMSK1) : \
|
||||
WITHIN(p, 62, 69) ? (&PCMSK2) : \
|
||||
nullptr)
|
||||
|
||||
#undef digitalPinToPCMSKbit
|
||||
#define digitalPinToPCMSKbit(p) (WITHIN(p, 10, 13) ? ((p) - 6) : \
|
||||
(p) == 14 || (p) == 51 ? 2 : \
|
||||
(p) == 15 || (p) == 52 ? 1 : \
|
||||
(p) == 50 ? 3 : \
|
||||
(p) == 53 ? 0 : \
|
||||
WITHIN(p, 62, 69) ? ((p) - 62) : \
|
||||
0)
|
||||
|
||||
#elif defined(__AVR_ATmega164A__) || defined(__AVR_ATmega164P__) || defined(__AVR_ATmega324A__) || \
|
||||
defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324PA__) || defined(__AVR_ATmega324PB__) || \
|
||||
defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284__) || \
|
||||
defined(__AVR_ATmega1284P__)
|
||||
|
||||
#define digitalPinHasPCICR(p) WITHIN(p, 0, NUM_DIGITAL_PINS)
|
||||
|
||||
#else
|
||||
|
||||
#error "Unsupported AVR variant!"
|
||||
|
||||
#endif
|
||||
|
||||
// Install Pin change interrupt for a pin. Can be called multiple times.
|
||||
void pciSetup(const int8_t pin) {
|
||||
if (digitalPinHasPCICR(pin)) {
|
||||
SBI(*digitalPinToPCMSK(pin), digitalPinToPCMSKbit(pin)); // enable pin
|
||||
SBI(PCIFR, digitalPinToPCICRbit(pin)); // clear any outstanding interrupt
|
||||
SBI(PCICR, digitalPinToPCICRbit(pin)); // enable interrupt for the group
|
||||
}
|
||||
}
|
||||
|
||||
// Handlers for pin change interrupts
|
||||
#ifdef PCINT0_vect
|
||||
ISR(PCINT0_vect) { endstop_ISR(); }
|
||||
#endif
|
||||
|
||||
#ifdef PCINT1_vect
|
||||
ISR(PCINT1_vect, ISR_ALIASOF(PCINT0_vect));
|
||||
#endif
|
||||
|
||||
#ifdef PCINT2_vect
|
||||
ISR(PCINT2_vect, ISR_ALIASOF(PCINT0_vect));
|
||||
#endif
|
||||
|
||||
#ifdef PCINT3_vect
|
||||
ISR(PCINT3_vect, ISR_ALIASOF(PCINT0_vect));
|
||||
#endif
|
||||
|
||||
void setup_endstop_interrupts() {
|
||||
#define _ATTACH(P) attachInterrupt(digitalPinToInterrupt(P), endstop_ISR, CHANGE)
|
||||
#if USE_X_MAX
|
||||
#if (digitalPinToInterrupt(X_MAX_PIN) != NOT_AN_INTERRUPT)
|
||||
_ATTACH(X_MAX_PIN);
|
||||
#else
|
||||
static_assert(digitalPinHasPCICR(X_MAX_PIN), "X_MAX_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
|
||||
pciSetup(X_MAX_PIN);
|
||||
#endif
|
||||
#endif
|
||||
#if USE_X_MIN
|
||||
#if (digitalPinToInterrupt(X_MIN_PIN) != NOT_AN_INTERRUPT)
|
||||
_ATTACH(X_MIN_PIN);
|
||||
#else
|
||||
static_assert(digitalPinHasPCICR(X_MIN_PIN), "X_MIN_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
|
||||
pciSetup(X_MIN_PIN);
|
||||
#endif
|
||||
#endif
|
||||
#if USE_Y_MAX
|
||||
#if (digitalPinToInterrupt(Y_MAX_PIN) != NOT_AN_INTERRUPT)
|
||||
_ATTACH(Y_MAX_PIN);
|
||||
#else
|
||||
static_assert(digitalPinHasPCICR(Y_MAX_PIN), "Y_MAX_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
|
||||
pciSetup(Y_MAX_PIN);
|
||||
#endif
|
||||
#endif
|
||||
#if USE_Y_MIN
|
||||
#if (digitalPinToInterrupt(Y_MIN_PIN) != NOT_AN_INTERRUPT)
|
||||
_ATTACH(Y_MIN_PIN);
|
||||
#else
|
||||
static_assert(digitalPinHasPCICR(Y_MIN_PIN), "Y_MIN_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
|
||||
pciSetup(Y_MIN_PIN);
|
||||
#endif
|
||||
#endif
|
||||
#if USE_Z_MAX
|
||||
#if (digitalPinToInterrupt(Z_MAX_PIN) != NOT_AN_INTERRUPT)
|
||||
_ATTACH(Z_MAX_PIN);
|
||||
#else
|
||||
static_assert(digitalPinHasPCICR(Z_MAX_PIN), "Z_MAX_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
|
||||
pciSetup(Z_MAX_PIN);
|
||||
#endif
|
||||
#endif
|
||||
#if USE_Z_MIN
|
||||
#if (digitalPinToInterrupt(Z_MIN_PIN) != NOT_AN_INTERRUPT)
|
||||
_ATTACH(Z_MIN_PIN);
|
||||
#else
|
||||
static_assert(digitalPinHasPCICR(Z_MIN_PIN), "Z_MIN_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
|
||||
pciSetup(Z_MIN_PIN);
|
||||
#endif
|
||||
#endif
|
||||
#if USE_I_MAX
|
||||
#if (digitalPinToInterrupt(I_MAX_PIN) != NOT_AN_INTERRUPT)
|
||||
_ATTACH(I_MAX_PIN);
|
||||
#else
|
||||
static_assert(digitalPinHasPCICR(I_MAX_PIN), "I_MAX_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
|
||||
pciSetup(I_MAX_PIN);
|
||||
#endif
|
||||
#elif USE_I_MIN
|
||||
#if (digitalPinToInterrupt(I_MIN_PIN) != NOT_AN_INTERRUPT)
|
||||
_ATTACH(I_MIN_PIN);
|
||||
#else
|
||||
static_assert(digitalPinHasPCICR(I_MIN_PIN), "I_MIN_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
|
||||
pciSetup(I_MIN_PIN);
|
||||
#endif
|
||||
#endif
|
||||
#if USE_J_MAX
|
||||
#if (digitalPinToInterrupt(J_MAX_PIN) != NOT_AN_INTERRUPT)
|
||||
_ATTACH(J_MAX_PIN);
|
||||
#else
|
||||
static_assert(digitalPinHasPCICR(J_MAX_PIN), "J_MAX_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
|
||||
pciSetup(J_MAX_PIN);
|
||||
#endif
|
||||
#elif USE_J_MIN
|
||||
#if (digitalPinToInterrupt(J_MIN_PIN) != NOT_AN_INTERRUPT)
|
||||
_ATTACH(J_MIN_PIN);
|
||||
#else
|
||||
static_assert(digitalPinHasPCICR(J_MIN_PIN), "J_MIN_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
|
||||
pciSetup(J_MIN_PIN);
|
||||
#endif
|
||||
#endif
|
||||
#if USE_K_MAX
|
||||
#if (digitalPinToInterrupt(K_MAX_PIN) != NOT_AN_INTERRUPT)
|
||||
_ATTACH(K_MAX_PIN);
|
||||
#else
|
||||
static_assert(digitalPinHasPCICR(K_MAX_PIN), "K_MAX_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
|
||||
pciSetup(K_MAX_PIN);
|
||||
#endif
|
||||
#elif USE_K_MIN
|
||||
#if (digitalPinToInterrupt(K_MIN_PIN) != NOT_AN_INTERRUPT)
|
||||
_ATTACH(K_MIN_PIN);
|
||||
#else
|
||||
static_assert(digitalPinHasPCICR(K_MIN_PIN), "K_MIN_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
|
||||
pciSetup(K_MIN_PIN);
|
||||
#endif
|
||||
#endif
|
||||
#if USE_U_MAX
|
||||
#if (digitalPinToInterrupt(U_MAX_PIN) != NOT_AN_INTERRUPT)
|
||||
_ATTACH(U_MAX_PIN);
|
||||
#else
|
||||
static_assert(digitalPinHasPCICR(U_MAX_PIN), "U_MAX_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
|
||||
pciSetup(U_MAX_PIN);
|
||||
#endif
|
||||
#elif USE_U_MIN
|
||||
#if (digitalPinToInterrupt(U_MIN_PIN) != NOT_AN_INTERRUPT)
|
||||
_ATTACH(U_MIN_PIN);
|
||||
#else
|
||||
static_assert(digitalPinHasPCICR(U_MIN_PIN), "U_MIN_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
|
||||
pciSetup(U_MIN_PIN);
|
||||
#endif
|
||||
#endif
|
||||
#if USE_V_MAX
|
||||
#if (digitalPinToInterrupt(V_MAX_PIN) != NOT_AN_INTERRUPT)
|
||||
_ATTACH(V_MAX_PIN);
|
||||
#else
|
||||
static_assert(digitalPinHasPCICR(V_MAX_PIN), "V_MAX_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
|
||||
pciSetup(V_MAX_PIN);
|
||||
#endif
|
||||
#elif USE_V_MIN
|
||||
#if (digitalPinToInterrupt(V_MIN_PIN) != NOT_AN_INTERRUPT)
|
||||
_ATTACH(V_MIN_PIN);
|
||||
#else
|
||||
static_assert(digitalPinHasPCICR(V_MIN_PIN), "V_MIN_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
|
||||
pciSetup(V_MIN_PIN);
|
||||
#endif
|
||||
#endif
|
||||
#if USE_W_MAX
|
||||
#if (digitalPinToInterrupt(W_MAX_PIN) != NOT_AN_INTERRUPT)
|
||||
_ATTACH(W_MAX_PIN);
|
||||
#else
|
||||
static_assert(digitalPinHasPCICR(W_MAX_PIN), "W_MAX_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
|
||||
pciSetup(W_MAX_PIN);
|
||||
#endif
|
||||
#elif USE_W_MIN
|
||||
#if (digitalPinToInterrupt(W_MIN_PIN) != NOT_AN_INTERRUPT)
|
||||
_ATTACH(W_MIN_PIN);
|
||||
#else
|
||||
static_assert(digitalPinHasPCICR(W_MIN_PIN), "W_MIN_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
|
||||
pciSetup(W_MIN_PIN);
|
||||
#endif
|
||||
#endif
|
||||
#if USE_X2_MAX
|
||||
#if (digitalPinToInterrupt(X2_MAX_PIN) != NOT_AN_INTERRUPT)
|
||||
_ATTACH(X2_MAX_PIN);
|
||||
#else
|
||||
static_assert(digitalPinHasPCICR(X2_MAX_PIN), "X2_MAX_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
|
||||
pciSetup(X2_MAX_PIN);
|
||||
#endif
|
||||
#endif
|
||||
#if USE_X2_MIN
|
||||
#if (digitalPinToInterrupt(X2_MIN_PIN) != NOT_AN_INTERRUPT)
|
||||
_ATTACH(X2_MIN_PIN);
|
||||
#else
|
||||
static_assert(digitalPinHasPCICR(X2_MIN_PIN), "X2_MIN_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
|
||||
pciSetup(X2_MIN_PIN);
|
||||
#endif
|
||||
#endif
|
||||
#if USE_Y2_MAX
|
||||
#if (digitalPinToInterrupt(Y2_MAX_PIN) != NOT_AN_INTERRUPT)
|
||||
_ATTACH(Y2_MAX_PIN);
|
||||
#else
|
||||
static_assert(digitalPinHasPCICR(Y2_MAX_PIN), "Y2_MAX_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
|
||||
pciSetup(Y2_MAX_PIN);
|
||||
#endif
|
||||
#endif
|
||||
#if USE_Y2_MIN
|
||||
#if (digitalPinToInterrupt(Y2_MIN_PIN) != NOT_AN_INTERRUPT)
|
||||
_ATTACH(Y2_MIN_PIN);
|
||||
#else
|
||||
static_assert(digitalPinHasPCICR(Y2_MIN_PIN), "Y2_MIN_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
|
||||
pciSetup(Y2_MIN_PIN);
|
||||
#endif
|
||||
#endif
|
||||
#if USE_Z2_MAX
|
||||
#if (digitalPinToInterrupt(Z2_MAX_PIN) != NOT_AN_INTERRUPT)
|
||||
_ATTACH(Z2_MAX_PIN);
|
||||
#else
|
||||
static_assert(digitalPinHasPCICR(Z2_MAX_PIN), "Z2_MAX_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
|
||||
pciSetup(Z2_MAX_PIN);
|
||||
#endif
|
||||
#endif
|
||||
#if USE_Z2_MIN
|
||||
#if (digitalPinToInterrupt(Z2_MIN_PIN) != NOT_AN_INTERRUPT)
|
||||
_ATTACH(Z2_MIN_PIN);
|
||||
#else
|
||||
static_assert(digitalPinHasPCICR(Z2_MIN_PIN), "Z2_MIN_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
|
||||
pciSetup(Z2_MIN_PIN);
|
||||
#endif
|
||||
#endif
|
||||
#if USE_Z3_MAX
|
||||
#if (digitalPinToInterrupt(Z3_MAX_PIN) != NOT_AN_INTERRUPT)
|
||||
_ATTACH(Z3_MAX_PIN);
|
||||
#else
|
||||
static_assert(digitalPinHasPCICR(Z3_MAX_PIN), "Z3_MAX_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
|
||||
pciSetup(Z3_MAX_PIN);
|
||||
#endif
|
||||
#endif
|
||||
#if USE_Z3_MIN
|
||||
#if (digitalPinToInterrupt(Z3_MIN_PIN) != NOT_AN_INTERRUPT)
|
||||
_ATTACH(Z3_MIN_PIN);
|
||||
#else
|
||||
static_assert(digitalPinHasPCICR(Z3_MIN_PIN), "Z3_MIN_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
|
||||
pciSetup(Z3_MIN_PIN);
|
||||
#endif
|
||||
#endif
|
||||
#if USE_Z4_MAX
|
||||
#if (digitalPinToInterrupt(Z4_MAX_PIN) != NOT_AN_INTERRUPT)
|
||||
_ATTACH(Z4_MAX_PIN);
|
||||
#else
|
||||
static_assert(digitalPinHasPCICR(Z4_MAX_PIN), "Z4_MAX_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
|
||||
pciSetup(Z4_MAX_PIN);
|
||||
#endif
|
||||
#endif
|
||||
#if USE_Z4_MIN
|
||||
#if (digitalPinToInterrupt(Z4_MIN_PIN) != NOT_AN_INTERRUPT)
|
||||
_ATTACH(Z4_MIN_PIN);
|
||||
#else
|
||||
static_assert(digitalPinHasPCICR(Z4_MIN_PIN), "Z4_MIN_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
|
||||
pciSetup(Z4_MIN_PIN);
|
||||
#endif
|
||||
#endif
|
||||
#if HAS_Z_MIN_PROBE_PIN
|
||||
#if (digitalPinToInterrupt(Z_MIN_PROBE_PIN) != NOT_AN_INTERRUPT)
|
||||
_ATTACH(Z_MIN_PROBE_PIN);
|
||||
#else
|
||||
static_assert(digitalPinHasPCICR(Z_MIN_PROBE_PIN), "Z_MIN_PROBE_PIN is not interrupt-capable. Disable ENDSTOP_INTERRUPTS_FEATURE to continue.");
|
||||
pciSetup(Z_MIN_PROBE_PIN);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// If we arrive here without raising an assertion, each pin has either an EXT-interrupt or a PCI.
|
||||
}
|
|
@ -0,0 +1,239 @@
|
|||
/**
|
||||
* 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"
|
||||
|
||||
//#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
|
||||
volatile uint16_t* ICRn; // max 1 ICR register per timer
|
||||
uint8_t n; // the timer number [0->5]
|
||||
uint8_t q; // the timer output [0->2] (A->C)
|
||||
bool isPWM; // True if pin is a "hardware timer"
|
||||
bool isProtected; // True if timer is protected
|
||||
};
|
||||
|
||||
// Macros for the Timer structure
|
||||
#define _SET_WGMnQ(T, V) do{ \
|
||||
*(T.TCCRnQ)[0] = (*(T.TCCRnQ)[0] & ~(0x3 << 0)) | (( int(V) & 0x3) << 0); \
|
||||
*(T.TCCRnQ)[1] = (*(T.TCCRnQ)[1] & ~(0x3 << 3)) | (((int(V) >> 2) & 0x3) << 3); \
|
||||
}while(0)
|
||||
|
||||
// Set TCCR CS bits
|
||||
#define _SET_CSn(T, V) (*(T.TCCRnQ)[1] = (*(T.TCCRnQ[1]) & ~(0x7 << 0)) | ((int(V) & 0x7) << 0))
|
||||
|
||||
// Set TCCR COM bits
|
||||
#define _SET_COMnQ(T, Q, V) (*(T.TCCRnQ)[0] = (*(T.TCCRnQ)[0] & ~(0x3 << (6-2*(Q)))) | (int(V) << (6-2*(Q))))
|
||||
|
||||
// Set OCRnQ register
|
||||
#define _SET_OCRnQ(T, Q, V) (*(T.OCRnQ)[Q] = int(V) & 0xFFFF)
|
||||
|
||||
// Set ICRn register (one per timer)
|
||||
#define _SET_ICRn(T, V) (*(T.ICRn) = int(V) & 0xFFFF)
|
||||
|
||||
/**
|
||||
* Return a Timer struct describing a pin's timer.
|
||||
*/
|
||||
const Timer get_pwm_timer(const pin_t pin) {
|
||||
|
||||
uint8_t q = 0;
|
||||
|
||||
switch (digitalPinToTimer(pin)) {
|
||||
#ifdef TCCR0A
|
||||
IF_DISABLED(AVR_AT90USB1286_FAMILY, case TIMER0A:)
|
||||
#endif
|
||||
#ifdef TCCR1A
|
||||
case TIMER1A: case TIMER1B:
|
||||
#endif
|
||||
|
||||
break; // Protect reserved timers (TIMER0 & TIMER1)
|
||||
|
||||
#ifdef TCCR0A
|
||||
case TIMER0B: // Protected timer, but allow setting the duty cycle on OCR0B for pin D4 only
|
||||
return Timer({ { &TCCR0A, nullptr, nullptr }, { (uint16_t*)&OCR0A, (uint16_t*)&OCR0B, nullptr }, nullptr, 0, 1, true, true });
|
||||
#endif
|
||||
|
||||
#if HAS_TCCR2
|
||||
case TIMER2:
|
||||
return Timer({ { &TCCR2, nullptr, nullptr }, { (uint16_t*)&OCR2, nullptr, nullptr }, nullptr, 2, 0, true, false });
|
||||
#elif ENABLED(USE_OCR2A_AS_TOP)
|
||||
case TIMER2A: break; // Protect TIMER2A since its OCR is used by TIMER2B
|
||||
case TIMER2B:
|
||||
return Timer({ { &TCCR2A, &TCCR2B, nullptr }, { (uint16_t*)&OCR2A, (uint16_t*)&OCR2B, nullptr }, nullptr, 2, 1, true, false });
|
||||
#elif defined(TCCR2A)
|
||||
case TIMER2B: ++q; case TIMER2A:
|
||||
return Timer({ { &TCCR2A, &TCCR2B, nullptr }, { (uint16_t*)&OCR2A, (uint16_t*)&OCR2B, nullptr }, nullptr, 2, q, true, false });
|
||||
#endif
|
||||
|
||||
#ifdef OCR3C
|
||||
case TIMER3C: ++q; case TIMER3B: ++q; case TIMER3A:
|
||||
return Timer({ { &TCCR3A, &TCCR3B, &TCCR3C }, { &OCR3A, &OCR3B, &OCR3C }, &ICR3, 3, q, true, false });
|
||||
#elif defined(OCR3B)
|
||||
case TIMER3B: ++q; case TIMER3A:
|
||||
return Timer({ { &TCCR3A, &TCCR3B, nullptr }, { &OCR3A, &OCR3B, nullptr }, &ICR3, 3, q, true, false });
|
||||
#endif
|
||||
|
||||
#ifdef TCCR4A
|
||||
case TIMER4C: ++q; case TIMER4B: ++q; case TIMER4A:
|
||||
return Timer({ { &TCCR4A, &TCCR4B, &TCCR4C }, { &OCR4A, &OCR4B, &OCR4C }, &ICR4, 4, q, true, false });
|
||||
#endif
|
||||
|
||||
#ifdef TCCR5A
|
||||
case TIMER5C: ++q; case TIMER5B: ++q; case TIMER5A:
|
||||
return Timer({ { &TCCR5A, &TCCR5B, &TCCR5C }, { &OCR5A, &OCR5B, &OCR5C }, &ICR5, 5, q, true, false });
|
||||
#endif
|
||||
}
|
||||
|
||||
return Timer();
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
// 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) / (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)");
|
||||
for (uint8_t i = 0; i < COUNT(prescaler); ++i) { // Loop through all prescaler values
|
||||
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;
|
||||
}
|
||||
|
||||
LIMIT(res_fast_temp, 1U, maxtop);
|
||||
LIMIT(res_pc_temp, 1U, maxtop);
|
||||
|
||||
// Calculate frequencies of test prescaler and resolution values
|
||||
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_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);
|
||||
_SET_CSn(timer, j);
|
||||
|
||||
if (is_timer2) {
|
||||
TERN_(USE_OCR2A_AS_TOP, _SET_OCRnQ(timer, 0, res)); // Set OCR2A value (TOP) = res
|
||||
}
|
||||
else
|
||||
_SET_ICRn(timer, res); // Set ICRn value (TOP) = res
|
||||
}
|
||||
|
||||
void MarlinHAL::set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) {
|
||||
// If v is 0 or v_size (max), digitalWrite to LOW or HIGH.
|
||||
// Note that digitalWrite also disables PWM output for us (sets COM bit to 0)
|
||||
if (v == 0)
|
||||
digitalWrite(pin, invert);
|
||||
else if (v == v_size)
|
||||
digitalWrite(pin, !invert);
|
||||
else {
|
||||
const Timer timer = get_pwm_timer(pin);
|
||||
if (timer.isPWM) {
|
||||
if (timer.n == 0) {
|
||||
_SET_COMnQ(timer, timer.q, COM_CLEAR_SET); // Only allow a TIMER0B select...
|
||||
_SET_OCRnQ(timer, timer.q, v); // ...and OCR0B duty update. For output pin D4 no frequency changes are permitted.
|
||||
}
|
||||
else if (!timer.isProtected) {
|
||||
const uint16_t top = timer.n == 2 ? TERN(USE_OCR2A_AS_TOP, *timer.OCRnQ[0], 255) : *timer.ICRn;
|
||||
_SET_COMnQ(timer, SUM_TERN(HAS_TCCR2, timer.q, timer.q == 2), COM_CLEAR_SET + invert); // COM20 is on bit 4 of TCCR2, so +1 for q==2
|
||||
_SET_OCRnQ(timer, timer.q, uint16_t(uint32_t(v) * top / v_size)); // Scale 8/16-bit v to top value
|
||||
}
|
||||
}
|
||||
else
|
||||
digitalWrite(pin, v < v_size / 2 ? LOW : HIGH);
|
||||
}
|
||||
}
|
||||
|
||||
void MarlinHAL::init_pwm_timers() {
|
||||
// Init some timer frequencies to a default 1KHz
|
||||
const pin_t pwm_pin[] = {
|
||||
#ifdef __AVR_ATmega2560__
|
||||
10, 5, 6, 46
|
||||
#elif defined(__AVR_ATmega1280__)
|
||||
12, 31
|
||||
#elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega1284__)
|
||||
15, 6
|
||||
#elif defined(__AVR_AT90USB1286__) || defined(__AVR_mega64) || defined(__AVR_mega128)
|
||||
16, 24
|
||||
#endif
|
||||
};
|
||||
|
||||
for (uint8_t i = 0; i < COUNT(pwm_pin); ++i)
|
||||
set_pwm_frequency(pwm_pin[i], 1000);
|
||||
}
|
||||
|
||||
#endif // __AVR__
|
|
@ -0,0 +1,288 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Fast I/O for extended pins
|
||||
*/
|
||||
|
||||
#ifdef __AVR__
|
||||
|
||||
#include "fastio.h"
|
||||
|
||||
#ifdef FASTIO_EXT_START
|
||||
|
||||
#include "../shared/Marduino.h"
|
||||
|
||||
#define _IS_EXT(P) WITHIN(P, FASTIO_EXT_START, FASTIO_EXT_END)
|
||||
|
||||
void extDigitalWrite(const int8_t pin, const uint8_t state) {
|
||||
#define _WCASE(N) case N: WRITE(N, state); break
|
||||
switch (pin) {
|
||||
default: digitalWrite(pin, state);
|
||||
#if _IS_EXT(70)
|
||||
_WCASE(70);
|
||||
#endif
|
||||
#if _IS_EXT(71)
|
||||
_WCASE(71);
|
||||
#endif
|
||||
#if _IS_EXT(72)
|
||||
_WCASE(72);
|
||||
#endif
|
||||
#if _IS_EXT(73)
|
||||
_WCASE(73);
|
||||
#endif
|
||||
#if _IS_EXT(74)
|
||||
_WCASE(74);
|
||||
#endif
|
||||
#if _IS_EXT(75)
|
||||
_WCASE(75);
|
||||
#endif
|
||||
#if _IS_EXT(76)
|
||||
_WCASE(76);
|
||||
#endif
|
||||
#if _IS_EXT(77)
|
||||
_WCASE(77);
|
||||
#endif
|
||||
#if _IS_EXT(78)
|
||||
_WCASE(78);
|
||||
#endif
|
||||
#if _IS_EXT(79)
|
||||
_WCASE(79);
|
||||
#endif
|
||||
#if _IS_EXT(80)
|
||||
_WCASE(80);
|
||||
#endif
|
||||
#if _IS_EXT(81)
|
||||
_WCASE(81);
|
||||
#endif
|
||||
#if _IS_EXT(82)
|
||||
_WCASE(82);
|
||||
#endif
|
||||
#if _IS_EXT(83)
|
||||
_WCASE(83);
|
||||
#endif
|
||||
#if _IS_EXT(84)
|
||||
_WCASE(84);
|
||||
#endif
|
||||
#if _IS_EXT(85)
|
||||
_WCASE(85);
|
||||
#endif
|
||||
#if _IS_EXT(86)
|
||||
_WCASE(86);
|
||||
#endif
|
||||
#if _IS_EXT(87)
|
||||
_WCASE(87);
|
||||
#endif
|
||||
#if _IS_EXT(88)
|
||||
_WCASE(88);
|
||||
#endif
|
||||
#if _IS_EXT(89)
|
||||
_WCASE(89);
|
||||
#endif
|
||||
#if _IS_EXT(90)
|
||||
_WCASE(90);
|
||||
#endif
|
||||
#if _IS_EXT(91)
|
||||
_WCASE(91);
|
||||
#endif
|
||||
#if _IS_EXT(92)
|
||||
_WCASE(92);
|
||||
#endif
|
||||
#if _IS_EXT(93)
|
||||
_WCASE(93);
|
||||
#endif
|
||||
#if _IS_EXT(94)
|
||||
_WCASE(94);
|
||||
#endif
|
||||
#if _IS_EXT(95)
|
||||
_WCASE(95);
|
||||
#endif
|
||||
#if _IS_EXT(96)
|
||||
_WCASE(96);
|
||||
#endif
|
||||
#if _IS_EXT(97)
|
||||
_WCASE(97);
|
||||
#endif
|
||||
#if _IS_EXT(98)
|
||||
_WCASE(98);
|
||||
#endif
|
||||
#if _IS_EXT(99)
|
||||
_WCASE(99);
|
||||
#endif
|
||||
#if _IS_EXT(100)
|
||||
_WCASE(100);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t extDigitalRead(const int8_t pin) {
|
||||
#define _RCASE(N) case N: return READ(N)
|
||||
switch (pin) {
|
||||
default: return digitalRead(pin);
|
||||
#if _IS_EXT(70)
|
||||
_RCASE(70);
|
||||
#endif
|
||||
#if _IS_EXT(71)
|
||||
_RCASE(71);
|
||||
#endif
|
||||
#if _IS_EXT(72)
|
||||
_RCASE(72);
|
||||
#endif
|
||||
#if _IS_EXT(73)
|
||||
_RCASE(73);
|
||||
#endif
|
||||
#if _IS_EXT(74)
|
||||
_RCASE(74);
|
||||
#endif
|
||||
#if _IS_EXT(75)
|
||||
_RCASE(75);
|
||||
#endif
|
||||
#if _IS_EXT(76)
|
||||
_RCASE(76);
|
||||
#endif
|
||||
#if _IS_EXT(77)
|
||||
_RCASE(77);
|
||||
#endif
|
||||
#if _IS_EXT(78)
|
||||
_RCASE(78);
|
||||
#endif
|
||||
#if _IS_EXT(79)
|
||||
_RCASE(79);
|
||||
#endif
|
||||
#if _IS_EXT(80)
|
||||
_RCASE(80);
|
||||
#endif
|
||||
#if _IS_EXT(81)
|
||||
_RCASE(81);
|
||||
#endif
|
||||
#if _IS_EXT(82)
|
||||
_RCASE(82);
|
||||
#endif
|
||||
#if _IS_EXT(83)
|
||||
_RCASE(83);
|
||||
#endif
|
||||
#if _IS_EXT(84)
|
||||
_RCASE(84);
|
||||
#endif
|
||||
#if _IS_EXT(85)
|
||||
_RCASE(85);
|
||||
#endif
|
||||
#if _IS_EXT(86)
|
||||
_RCASE(86);
|
||||
#endif
|
||||
#if _IS_EXT(87)
|
||||
_RCASE(87);
|
||||
#endif
|
||||
#if _IS_EXT(88)
|
||||
_RCASE(88);
|
||||
#endif
|
||||
#if _IS_EXT(89)
|
||||
_RCASE(89);
|
||||
#endif
|
||||
#if _IS_EXT(90)
|
||||
_RCASE(90);
|
||||
#endif
|
||||
#if _IS_EXT(91)
|
||||
_RCASE(91);
|
||||
#endif
|
||||
#if _IS_EXT(92)
|
||||
_RCASE(92);
|
||||
#endif
|
||||
#if _IS_EXT(93)
|
||||
_RCASE(93);
|
||||
#endif
|
||||
#if _IS_EXT(94)
|
||||
_RCASE(94);
|
||||
#endif
|
||||
#if _IS_EXT(95)
|
||||
_RCASE(95);
|
||||
#endif
|
||||
#if _IS_EXT(96)
|
||||
_RCASE(96);
|
||||
#endif
|
||||
#if _IS_EXT(97)
|
||||
_RCASE(97);
|
||||
#endif
|
||||
#if _IS_EXT(98)
|
||||
_RCASE(98);
|
||||
#endif
|
||||
#if _IS_EXT(99)
|
||||
_RCASE(99);
|
||||
#endif
|
||||
#if _IS_EXT(100)
|
||||
_RCASE(100);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* Set Timer 5 PWM frequency in Hz, from 3.8Hz up to ~16MHz
|
||||
* with a minimum resolution of 100 steps.
|
||||
*
|
||||
* DC values -1.0 to 1.0. Negative duty cycle inverts the pulse.
|
||||
*/
|
||||
uint16_t set_pwm_frequency_hz(const_float_t hz, const float dca, const float dcb, const float dcc) {
|
||||
float count = 0;
|
||||
if (hz > 0 && (dca || dcb || dcc)) {
|
||||
count = float(F_CPU) / hz; // 1x prescaler, TOP for 16MHz base freq.
|
||||
uint16_t prescaler; // Range of 30.5Hz (65535) 64.5kHz (>31)
|
||||
|
||||
if (count >= 255. * 256.) { prescaler = 1024; SET_CS(5, PRESCALER_1024); }
|
||||
else if (count >= 255. * 64.) { prescaler = 256; SET_CS(5, PRESCALER_256); }
|
||||
else if (count >= 255. * 8.) { prescaler = 64; SET_CS(5, PRESCALER_64); }
|
||||
else if (count >= 255.) { prescaler = 8; SET_CS(5, PRESCALER_8); }
|
||||
else { prescaler = 1; SET_CS(5, PRESCALER_1); }
|
||||
|
||||
count /= float(prescaler);
|
||||
const float pwm_top = round(count); // Get the rounded count
|
||||
|
||||
ICR5 = (uint16_t)pwm_top - 1; // Subtract 1 for TOP
|
||||
OCR5A = pwm_top * ABS(dca); // Update and scale DCs
|
||||
OCR5B = pwm_top * ABS(dcb);
|
||||
OCR5C = pwm_top * ABS(dcc);
|
||||
_SET_COM(5, A, dca ? (dca < 0 ? COM_SET_CLEAR : COM_CLEAR_SET) : COM_NORMAL); // Set compare modes
|
||||
_SET_COM(5, B, dcb ? (dcb < 0 ? COM_SET_CLEAR : COM_CLEAR_SET) : COM_NORMAL);
|
||||
_SET_COM(5, C, dcc ? (dcc < 0 ? COM_SET_CLEAR : COM_CLEAR_SET) : COM_NORMAL);
|
||||
|
||||
SET_WGM(5, FAST_PWM_ICRn); // Fast PWM with ICR5 as TOP
|
||||
|
||||
//SERIAL_ECHOLNPGM("Timer 5 Settings:");
|
||||
//SERIAL_ECHOLNPGM(" Prescaler=", prescaler);
|
||||
//SERIAL_ECHOLNPGM(" TOP=", ICR5);
|
||||
//SERIAL_ECHOLNPGM(" OCR5A=", OCR5A);
|
||||
//SERIAL_ECHOLNPGM(" OCR5B=", OCR5B);
|
||||
//SERIAL_ECHOLNPGM(" OCR5C=", OCR5C);
|
||||
}
|
||||
else {
|
||||
// Restore the default for Timer 5
|
||||
SET_WGM(5, PWM_PC_8); // PWM 8-bit (Phase Correct)
|
||||
SET_COMS(5, NORMAL, NORMAL, NORMAL); // Do nothing
|
||||
SET_CS(5, PRESCALER_64); // 16MHz / 64 = 250kHz
|
||||
OCR5A = OCR5B = OCR5C = 0;
|
||||
}
|
||||
return round(count);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // FASTIO_EXT_START
|
||||
#endif // __AVR__
|
|
@ -0,0 +1,272 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Fast I/O Routines for AVR
|
||||
* Use direct port manipulation to save scads of processor time.
|
||||
* Contributed by Triffid_Hunter and modified by Kliment, thinkyhead, Bob-the-Kuhn, et.al.
|
||||
*/
|
||||
|
||||
#include <avr/io.h>
|
||||
|
||||
#if defined(__AVR_AT90USB1287__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1286P__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB646P__) || defined(__AVR_AT90USB647__)
|
||||
#define AVR_AT90USB1286_FAMILY 1
|
||||
#elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) || defined(__AVR_ATmega1284P__)
|
||||
#define AVR_ATmega1284_FAMILY 1
|
||||
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||||
#define AVR_ATmega2560_FAMILY 1
|
||||
#elif defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
|
||||
#define AVR_ATmega2561_FAMILY 1
|
||||
#elif defined(__AVR_ATmega168__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__)
|
||||
#define AVR_ATmega328_FAMILY 1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Include Ports and Functions
|
||||
*/
|
||||
#if AVR_ATmega328_FAMILY
|
||||
#include "fastio/fastio_168.h"
|
||||
#elif AVR_ATmega1284_FAMILY
|
||||
#include "fastio/fastio_644.h"
|
||||
#elif AVR_ATmega2560_FAMILY
|
||||
#include "fastio/fastio_1280.h"
|
||||
#elif AVR_AT90USB1286_FAMILY
|
||||
#include "fastio/fastio_AT90USB.h"
|
||||
#elif AVR_ATmega2561_FAMILY
|
||||
#include "fastio/fastio_1281.h"
|
||||
#else
|
||||
#error "No FastIO definition for the selected AVR Board."
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Magic I/O routines
|
||||
*
|
||||
* Now you can simply SET_OUTPUT(PIN); WRITE(PIN, HIGH); WRITE(PIN, LOW);
|
||||
*
|
||||
* Why double up on these macros? see https://gcc.gnu.org/onlinedocs/cpp/Stringification.html
|
||||
*/
|
||||
|
||||
#define _READ(IO) TEST(DIO ## IO ## _RPORT, DIO ## IO ## _PIN)
|
||||
|
||||
#define _WRITE_NC(IO,V) do{ \
|
||||
if (V) SBI(DIO ## IO ## _WPORT, DIO ## IO ## _PIN); \
|
||||
else CBI(DIO ## IO ## _WPORT, DIO ## IO ## _PIN); \
|
||||
}while(0)
|
||||
|
||||
#define _WRITE_C(IO,V) do{ \
|
||||
uint8_t port_bits = DIO ## IO ## _WPORT; /* Get a mask from the current port bits */ \
|
||||
if (V) port_bits = ~port_bits; /* For setting bits, invert the mask */ \
|
||||
DIO ## IO ## _RPORT = port_bits & _BV(DIO ## IO ## _PIN); /* Atomically toggle the output port bits */ \
|
||||
}while(0)
|
||||
|
||||
#define _WRITE(IO,V) do{ if (&(DIO ## IO ## _RPORT) < (uint8_t*)0x100) _WRITE_NC(IO,V); else _WRITE_C(IO,V); }while(0)
|
||||
|
||||
#define _TOGGLE(IO) (DIO ## IO ## _RPORT = _BV(DIO ## IO ## _PIN))
|
||||
|
||||
#define _SET_INPUT(IO) CBI(DIO ## IO ## _DDR, DIO ## IO ## _PIN)
|
||||
#define _SET_OUTPUT(IO) SBI(DIO ## IO ## _DDR, DIO ## IO ## _PIN)
|
||||
|
||||
#define _IS_INPUT(IO) !TEST(DIO ## IO ## _DDR, DIO ## IO ## _PIN)
|
||||
#define _IS_OUTPUT(IO) TEST(DIO ## IO ## _DDR, DIO ## IO ## _PIN)
|
||||
|
||||
// digitalRead/Write wrappers
|
||||
#ifdef FASTIO_EXT_START
|
||||
void extDigitalWrite(const int8_t pin, const uint8_t state);
|
||||
uint8_t extDigitalRead(const int8_t pin);
|
||||
#else
|
||||
#define extDigitalWrite(IO,V) digitalWrite(IO,V)
|
||||
#define extDigitalRead(IO) digitalRead(IO)
|
||||
#endif
|
||||
|
||||
#define READ(IO) _READ(IO)
|
||||
#define WRITE(IO,V) _WRITE(IO,V)
|
||||
#define TOGGLE(IO) _TOGGLE(IO)
|
||||
|
||||
#define SET_INPUT(IO) _SET_INPUT(IO)
|
||||
#define SET_INPUT_PULLUP(IO) do{ _SET_INPUT(IO); _WRITE(IO, HIGH); }while(0)
|
||||
#define SET_INPUT_PULLDOWN SET_INPUT
|
||||
#define SET_OUTPUT(IO) _SET_OUTPUT(IO)
|
||||
#define SET_PWM SET_OUTPUT
|
||||
|
||||
#define IS_INPUT(IO) _IS_INPUT(IO)
|
||||
#define IS_OUTPUT(IO) _IS_OUTPUT(IO)
|
||||
|
||||
#define OUT_WRITE(IO,V) do{ SET_OUTPUT(IO); WRITE(IO,V); }while(0)
|
||||
|
||||
/**
|
||||
* Timer and Interrupt Control
|
||||
*/
|
||||
|
||||
// Waveform Generation Modes
|
||||
enum WaveGenMode : uint8_t {
|
||||
WGM_NORMAL, // 0
|
||||
WGM_PWM_PC_8, // 1
|
||||
WGM_PWM_PC_9, // 2
|
||||
WGM_PWM_PC_10, // 3
|
||||
WGM_CTC_OCRnA, // 4 COM OCnx
|
||||
WGM_FAST_PWM_8, // 5
|
||||
WGM_FAST_PWM_9, // 6
|
||||
WGM_FAST_PWM_10, // 7
|
||||
WGM_PWM_PC_FC_ICRn, // 8
|
||||
WGM_PWM_PC_FC_OCRnA, // 9 COM OCnA
|
||||
WGM_PWM_PC_ICRn, // 10
|
||||
WGM_PWM_PC_OCRnA, // 11 COM OCnA
|
||||
WGM_CTC_ICRn, // 12 COM OCnx
|
||||
WGM_reserved, // 13
|
||||
WGM_FAST_PWM_ICRn, // 14 COM OCnA
|
||||
WGM_FAST_PWM_OCRnA // 15 COM OCnA
|
||||
};
|
||||
|
||||
// Wavefore Generation Modes (Timer 2 only)
|
||||
enum WaveGenMode2 : uint8_t {
|
||||
WGM2_NORMAL, // 0
|
||||
WGM2_PWM_PC, // 1
|
||||
WGM2_CTC_OCR2A, // 2
|
||||
WGM2_FAST_PWM, // 3
|
||||
WGM2_reserved_1, // 4
|
||||
WGM2_PWM_PC_OCR2A, // 5
|
||||
WGM2_reserved_2, // 6
|
||||
WGM2_FAST_PWM_OCR2A, // 7
|
||||
};
|
||||
|
||||
// Compare Modes
|
||||
enum CompareMode : uint8_t {
|
||||
COM_NORMAL, // 0
|
||||
COM_TOGGLE, // 1 Non-PWM: OCnx ... Both PWM (WGM 9,11,14,15): OCnA only ... else NORMAL
|
||||
COM_CLEAR_SET, // 2 Non-PWM: OCnx ... Fast PWM: OCnx/Bottom ... PF-FC: OCnx Up/Down
|
||||
COM_SET_CLEAR // 3 Non-PWM: OCnx ... Fast PWM: OCnx/Bottom ... PF-FC: OCnx Up/Down
|
||||
};
|
||||
|
||||
// Clock Sources
|
||||
enum ClockSource : uint8_t {
|
||||
CS_NONE, // 0
|
||||
CS_PRESCALER_1, // 1
|
||||
CS_PRESCALER_8, // 2
|
||||
CS_PRESCALER_64, // 3
|
||||
CS_PRESCALER_256, // 4
|
||||
CS_PRESCALER_1024, // 5
|
||||
CS_EXT_FALLING, // 6
|
||||
CS_EXT_RISING // 7
|
||||
};
|
||||
|
||||
// Clock Sources (Timer 2 only)
|
||||
enum ClockSource2 : uint8_t {
|
||||
CS2_NONE, // 0
|
||||
CS2_PRESCALER_1, // 1
|
||||
CS2_PRESCALER_8, // 2
|
||||
CS2_PRESCALER_32, // 3
|
||||
CS2_PRESCALER_64, // 4
|
||||
CS2_PRESCALER_128, // 5
|
||||
CS2_PRESCALER_256, // 6
|
||||
CS2_PRESCALER_1024 // 7
|
||||
};
|
||||
|
||||
// Get interrupt bits in an orderly way
|
||||
// Ex: cs = GET_CS(0); coma1 = GET_COM(A,1);
|
||||
#define GET_WGM(T) (((TCCR##T##A >> WGM##T##0) & 0x3) | ((TCCR##T##B >> WGM##T##2 << 2) & 0xC))
|
||||
#define GET_CS(T) ((TCCR##T##B >> CS##T##0) & 0x7)
|
||||
#define GET_COM(T,Q) ((TCCR##T##Q >> COM##T##Q##0) & 0x3)
|
||||
#define GET_COMA(T) GET_COM(T,A)
|
||||
#define GET_COMB(T) GET_COM(T,B)
|
||||
#define GET_COMC(T) GET_COM(T,C)
|
||||
#define GET_ICNC(T) (!!(TCCR##T##B & _BV(ICNC##T)))
|
||||
#define GET_ICES(T) (!!(TCCR##T##B & _BV(ICES##T)))
|
||||
#define GET_FOC(T,Q) (!!(TCCR##T##C & _BV(FOC##T##Q)))
|
||||
#define GET_FOCA(T) GET_FOC(T,A)
|
||||
#define GET_FOCB(T) GET_FOC(T,B)
|
||||
#define GET_FOCC(T) GET_FOC(T,C)
|
||||
|
||||
// Set Wave Generation Mode bits
|
||||
// Ex: SET_WGM(5,CTC_ICRn);
|
||||
#define _SET_WGM(T,V) do{ \
|
||||
TCCR##T##A = (TCCR##T##A & ~(0x3 << WGM##T##0)) | (( int(V) & 0x3) << WGM##T##0); \
|
||||
TCCR##T##B = (TCCR##T##B & ~(0x3 << WGM##T##2)) | (((int(V) >> 2) & 0x3) << WGM##T##2); \
|
||||
}while(0)
|
||||
#define SET_WGM(T,V) _SET_WGM(T,WGM_##V)
|
||||
|
||||
// Set Clock Select bits
|
||||
// Ex: SET_CS3(PRESCALER_64);
|
||||
#ifdef TCCR2
|
||||
#define HAS_TCCR2 1
|
||||
#endif
|
||||
#define _SET_CS(T,V) (TCCR##T##B = (TCCR##T##B & ~(0x7 << CS##T##0)) | ((int(V) & 0x7) << CS##T##0))
|
||||
#define _SET_CS0(V) _SET_CS(0,V)
|
||||
#define _SET_CS1(V) _SET_CS(1,V)
|
||||
#define _SET_CS3(V) _SET_CS(3,V)
|
||||
#define _SET_CS4(V) _SET_CS(4,V)
|
||||
#define _SET_CS5(V) _SET_CS(5,V)
|
||||
#define SET_CS0(V) _SET_CS0(CS_##V)
|
||||
#define SET_CS1(V) _SET_CS1(CS_##V)
|
||||
|
||||
#if HAS_TCCR2
|
||||
#define _SET_CS2(V) (TCCR2 = (TCCR2 & ~(0x7 << CS20)) | (int(V) << CS20))
|
||||
#define SET_CS2(V) _SET_CS2(CS2_##V)
|
||||
#else
|
||||
#define _SET_CS2(V) _SET_CS(2,V)
|
||||
#define SET_CS2(V) _SET_CS2(CS_##V)
|
||||
#endif
|
||||
|
||||
#define SET_CS3(V) _SET_CS3(CS_##V)
|
||||
#define SET_CS4(V) _SET_CS4(CS_##V)
|
||||
#define SET_CS5(V) _SET_CS5(CS_##V)
|
||||
#define SET_CS(T,V) SET_CS##T(V)
|
||||
|
||||
// Set Compare Mode bits
|
||||
// Ex: SET_COMS(4,CLEAR_SET,CLEAR_SET,CLEAR_SET);
|
||||
#define _SET_COM(T,Q,V) (TCCR##T##Q = (TCCR##T##Q & ~(0x3 << COM##T##Q##0)) | (int(V) << COM##T##Q##0))
|
||||
#define SET_COM(T,Q,V) _SET_COM(T,Q,COM_##V)
|
||||
#define SET_COMA(T,V) SET_COM(T,A,V)
|
||||
#define SET_COMB(T,V) SET_COM(T,B,V)
|
||||
#define SET_COMC(T,V) SET_COM(T,C,V)
|
||||
#define SET_COMS(T,V1,V2,V3) do{ SET_COMA(T,V1); SET_COMB(T,V2); SET_COMC(T,V3); }while(0)
|
||||
|
||||
// Set Noise Canceler bit
|
||||
// Ex: SET_ICNC(2,1)
|
||||
#define SET_ICNC(T,V) (TCCR##T##B = (V) ? TCCR##T##B | _BV(ICNC##T) : TCCR##T##B & ~_BV(ICNC##T))
|
||||
|
||||
// Set Input Capture Edge Select bit
|
||||
// Ex: SET_ICES(5,0)
|
||||
#define SET_ICES(T,V) (TCCR##T##B = (V) ? TCCR##T##B | _BV(ICES##T) : TCCR##T##B & ~_BV(ICES##T))
|
||||
|
||||
// Set Force Output Compare bit
|
||||
// Ex: SET_FOC(3,A,1)
|
||||
#define SET_FOC(T,Q,V) (TCCR##T##C = (V) ? TCCR##T##C | _BV(FOC##T##Q) : TCCR##T##C & ~_BV(FOC##T##Q))
|
||||
#define SET_FOCA(T,V) SET_FOC(T,A,V)
|
||||
#define SET_FOCB(T,V) SET_FOC(T,B,V)
|
||||
#define SET_FOCC(T,V) SET_FOC(T,C,V)
|
||||
|
||||
// define which hardware PWMs are available for the current CPU
|
||||
// all timer 1 PWMS deleted from this list because they are never available
|
||||
#if AVR_ATmega2560_FAMILY
|
||||
#define PWM_PIN(P) ((P >= 2 && P <= 10) || P == 13 || P == 44 || P == 45 || P == 46)
|
||||
#elif AVR_ATmega2561_FAMILY
|
||||
#define PWM_PIN(P) ((P >= 2 && P <= 6) || P == 9)
|
||||
#elif AVR_ATmega1284_FAMILY
|
||||
#define PWM_PIN(P) (P == 3 || P == 4 || P == 14 || P == 15)
|
||||
#elif AVR_AT90USB1286_FAMILY
|
||||
#define PWM_PIN(P) (P == 0 || P == 1 || P == 14 || P == 15 || P == 16 || P == 24)
|
||||
#elif AVR_ATmega328_FAMILY
|
||||
#define PWM_PIN(P) (P == 3 || P == 5 || P == 6 || P == 11)
|
||||
#else
|
||||
#error "unknown CPU"
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,712 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Pin mapping for the 1281 and 2561
|
||||
*
|
||||
* Logical Pin: 38 39 40 41 42 43 44 45 16 10 11 12 06 07 08 09 30 31 32 33 34 35 36 37 17 18 19 20 21 22 23 24 00 01 13 05 02 03 14 15 46 47 48 49 50 51 52 53 25 26 27 28 29 04
|
||||
* Port: A0 A1 A2 A3 A4 A5 A6 A7 B0 B1 B2 B3 B4 B5 B6 B7 C0 C1 C2 C3 C4 C5 C6 C7 D0 D1 D2 D3 D4 D5 D6 D7 E0 E1 E2 E3 E4 E5 E6 E7 F0 F1 F2 F3 F4 F5 F6 F7 G0 G1 G2 G3 G4 G5
|
||||
*/
|
||||
|
||||
#include "../fastio.h"
|
||||
|
||||
// UART
|
||||
#define RXD 0
|
||||
#define TXD 1
|
||||
|
||||
// SPI
|
||||
#define SCK 10
|
||||
#define MISO 12
|
||||
#define MOSI 11
|
||||
#define SS 16
|
||||
|
||||
// TWI (I2C)
|
||||
#define SCL 17
|
||||
#define SDA 18
|
||||
|
||||
// Timers and PWM
|
||||
#define OC0A 9
|
||||
#define OC0B 4
|
||||
#define OC1A 7
|
||||
#define OC1B 8
|
||||
#define OC2A 6
|
||||
#define OC3A 5
|
||||
#define OC3B 2
|
||||
#define OC3C 3
|
||||
|
||||
// Digital I/O
|
||||
|
||||
#define DIO0_PIN PINE0
|
||||
#define DIO0_RPORT PINE
|
||||
#define DIO0_WPORT PORTE
|
||||
#define DIO0_DDR DDRE
|
||||
#define DIO0_PWM nullptr
|
||||
|
||||
#define DIO1_PIN PINE1
|
||||
#define DIO1_RPORT PINE
|
||||
#define DIO1_WPORT PORTE
|
||||
#define DIO1_DDR DDRE
|
||||
#define DIO1_PWM nullptr
|
||||
|
||||
#define DIO2_PIN PINE4
|
||||
#define DIO2_RPORT PINE
|
||||
#define DIO2_WPORT PORTE
|
||||
#define DIO2_DDR DDRE
|
||||
#define DIO2_PWM &OCR3BL
|
||||
|
||||
#define DIO3_PIN PINE5
|
||||
#define DIO3_RPORT PINE
|
||||
#define DIO3_WPORT PORTE
|
||||
#define DIO3_DDR DDRE
|
||||
#define DIO3_PWM &OCR3CL
|
||||
|
||||
#define DIO4_PIN PING5
|
||||
#define DIO4_RPORT PING
|
||||
#define DIO4_WPORT PORTG
|
||||
#define DIO4_DDR DDRG
|
||||
#define DIO4_PWM &OCR0B
|
||||
|
||||
#define DIO5_PIN PINE3
|
||||
#define DIO5_RPORT PINE
|
||||
#define DIO5_WPORT PORTE
|
||||
#define DIO5_DDR DDRE
|
||||
#define DIO5_PWM &OCR3AL
|
||||
|
||||
#define DIO6_PIN PINB4
|
||||
#define DIO6_RPORT PINB
|
||||
#define DIO6_WPORT PORTB
|
||||
#define DIO6_DDR DDRB
|
||||
#define DIO6_PWM &OCR2AL
|
||||
|
||||
#define DIO7_PIN PINB5
|
||||
#define DIO7_RPORT PINB
|
||||
#define DIO7_WPORT PORTB
|
||||
#define DIO7_DDR DDRB
|
||||
#define DIO7_PWM &OCR1AL
|
||||
|
||||
#define DIO8_PIN PINB6
|
||||
#define DIO8_RPORT PINB
|
||||
#define DIO8_WPORT PORTB
|
||||
#define DIO8_DDR DDRB
|
||||
#define DIO8_PWM &OCR1BL
|
||||
|
||||
#define DIO9_PIN PINB7
|
||||
#define DIO9_RPORT PINB
|
||||
#define DIO9_WPORT PORTB
|
||||
#define DIO9_DDR DDRB
|
||||
#define DIO9_PWM &OCR0AL
|
||||
|
||||
#define DIO10_PIN PINB1
|
||||
#define DIO10_RPORT PINB
|
||||
#define DIO10_WPORT PORTB
|
||||
#define DIO10_DDR DDRB
|
||||
#define DIO10_PWM nullptr
|
||||
|
||||
#define DIO11_PIN PINB2
|
||||
#define DIO11_RPORT PINB
|
||||
#define DIO11_WPORT PORTB
|
||||
#define DIO11_DDR DDRB
|
||||
#define DIO11_PWM nullptr
|
||||
|
||||
#define DIO12_PIN PINB3
|
||||
#define DIO12_RPORT PINB
|
||||
#define DIO12_WPORT PORTB
|
||||
#define DIO12_DDR DDRB
|
||||
#define DIO12_PWM nullptr
|
||||
|
||||
#define DIO13_PIN PINE2
|
||||
#define DIO13_RPORT PINE
|
||||
#define DIO13_WPORT PORTE
|
||||
#define DIO13_DDR DDRE
|
||||
#define DIO13_PWM nullptr
|
||||
|
||||
#define DIO14_PIN PINE6
|
||||
#define DIO14_RPORT PINE
|
||||
#define DIO14_WPORT PORTE
|
||||
#define DIO14_DDR DDRE
|
||||
#define DIO14_PWM nullptr
|
||||
|
||||
#define DIO15_PIN PINE7
|
||||
#define DIO15_RPORT PINE
|
||||
#define DIO15_WPORT PORTE
|
||||
#define DIO15_DDR DDRE
|
||||
#define DIO15_PWM nullptr
|
||||
|
||||
#define DIO16_PIN PINB0
|
||||
#define DIO16_RPORT PINB
|
||||
#define DIO16_WPORT PORTB
|
||||
#define DIO16_DDR DDRB
|
||||
#define DIO16_PWM nullptr
|
||||
|
||||
#define DIO17_PIN PIND0
|
||||
#define DIO17_RPORT PIND
|
||||
#define DIO17_WPORT PORTD
|
||||
#define DIO17_DDR DDRD
|
||||
#define DIO17_PWM nullptr
|
||||
|
||||
#define DIO18_PIN PIND1
|
||||
#define DIO18_RPORT PIND
|
||||
#define DIO18_WPORT PORTD
|
||||
#define DIO18_DDR DDRD
|
||||
#define DIO18_PWM nullptr
|
||||
|
||||
#define DIO19_PIN PIND2
|
||||
#define DIO19_RPORT PIND
|
||||
#define DIO19_WPORT PORTD
|
||||
#define DIO19_DDR DDRD
|
||||
#define DIO19_PWM nullptr
|
||||
|
||||
#define DIO20_PIN PIND3
|
||||
#define DIO20_RPORT PIND
|
||||
#define DIO20_WPORT PORTD
|
||||
#define DIO20_DDR DDRD
|
||||
#define DIO20_PWM nullptr
|
||||
|
||||
#define DIO21_PIN PIND4
|
||||
#define DIO21_RPORT PIND
|
||||
#define DIO21_WPORT PORTD
|
||||
#define DIO21_DDR DDRD
|
||||
#define DIO21_PWM nullptr
|
||||
|
||||
#define DIO22_PIN PIND5
|
||||
#define DIO22_RPORT PIND
|
||||
#define DIO22_WPORT PORTD
|
||||
#define DIO22_DDR DDRD
|
||||
#define DIO22_PWM nullptr
|
||||
|
||||
#define DIO23_PIN PIND6
|
||||
#define DIO23_RPORT PIND
|
||||
#define DIO23_WPORT PORTD
|
||||
#define DIO23_DDR DDRD
|
||||
#define DIO23_PWM nullptr
|
||||
|
||||
#define DIO24_PIN PIND7
|
||||
#define DIO24_RPORT PIND
|
||||
#define DIO24_WPORT PORTD
|
||||
#define DIO24_DDR DDRD
|
||||
#define DIO24_PWM nullptr
|
||||
|
||||
#define DIO25_PIN PING0
|
||||
#define DIO25_RPORT PING
|
||||
#define DIO25_WPORT PORTG
|
||||
#define DIO25_DDR DDRG
|
||||
#define DIO25_PWM nullptr
|
||||
|
||||
#define DIO26_PIN PING1
|
||||
#define DIO26_RPORT PING
|
||||
#define DIO26_WPORT PORTG
|
||||
#define DIO26_DDR DDRG
|
||||
#define DIO26_PWM nullptr
|
||||
|
||||
#define DIO27_PIN PING2
|
||||
#define DIO27_RPORT PING
|
||||
#define DIO27_WPORT PORTG
|
||||
#define DIO27_DDR DDRG
|
||||
#define DIO27_PWM nullptr
|
||||
|
||||
#define DIO28_PIN PING3
|
||||
#define DIO28_RPORT PING
|
||||
#define DIO28_WPORT PORTG
|
||||
#define DIO28_DDR DDRG
|
||||
#define DIO28_PWM nullptr
|
||||
|
||||
#define DIO29_PIN PING4
|
||||
#define DIO29_RPORT PING
|
||||
#define DIO29_WPORT PORTG
|
||||
#define DIO29_DDR DDRG
|
||||
#define DIO29_PWM nullptr
|
||||
|
||||
#define DIO30_PIN PINC0
|
||||
#define DIO30_RPORT PINC
|
||||
#define DIO30_WPORT PORTC
|
||||
#define DIO30_DDR DDRC
|
||||
#define DIO30_PWM nullptr
|
||||
|
||||
#define DIO31_PIN PINC1
|
||||
#define DIO31_RPORT PINC
|
||||
#define DIO31_WPORT PORTC
|
||||
#define DIO31_DDR DDRC
|
||||
#define DIO31_PWM nullptr
|
||||
|
||||
#define DIO32_PIN PINC2
|
||||
#define DIO32_RPORT PINC
|
||||
#define DIO32_WPORT PORTC
|
||||
#define DIO32_DDR DDRC
|
||||
#define DIO32_PWM nullptr
|
||||
|
||||
#define DIO33_PIN PINC3
|
||||
#define DIO33_RPORT PINC
|
||||
#define DIO33_WPORT PORTC
|
||||
#define DIO33_DDR DDRC
|
||||
#define DIO33_PWM nullptr
|
||||
|
||||
#define DIO34_PIN PINC4
|
||||
#define DIO34_RPORT PINC
|
||||
#define DIO34_WPORT PORTC
|
||||
#define DIO34_DDR DDRC
|
||||
#define DIO34_PWM nullptr
|
||||
|
||||
#define DIO35_PIN PINC5
|
||||
#define DIO35_RPORT PINC
|
||||
#define DIO35_WPORT PORTC
|
||||
#define DIO35_DDR DDRC
|
||||
#define DIO35_PWM nullptr
|
||||
|
||||
#define DIO36_PIN PINC6
|
||||
#define DIO36_RPORT PINC
|
||||
#define DIO36_WPORT PORTC
|
||||
#define DIO36_DDR DDRC
|
||||
#define DIO36_PWM nullptr
|
||||
|
||||
#define DIO37_PIN PINC7
|
||||
#define DIO37_RPORT PINC
|
||||
#define DIO37_WPORT PORTC
|
||||
#define DIO37_DDR DDRC
|
||||
#define DIO37_PWM nullptr
|
||||
|
||||
#define DIO38_PIN PINA0
|
||||
#define DIO38_RPORT PINA
|
||||
#define DIO38_WPORT PORTA
|
||||
#define DIO38_DDR DDRA
|
||||
#define DIO38_PWM nullptr
|
||||
|
||||
#define DIO39_PIN PINA1
|
||||
#define DIO39_RPORT PINA
|
||||
#define DIO39_WPORT PORTA
|
||||
#define DIO39_DDR DDRA
|
||||
#define DIO39_PWM nullptr
|
||||
|
||||
#define DIO40_PIN PINA2
|
||||
#define DIO40_RPORT PINA
|
||||
#define DIO40_WPORT PORTA
|
||||
#define DIO40_DDR DDRA
|
||||
#define DIO40_PWM nullptr
|
||||
|
||||
#define DIO41_PIN PINA3
|
||||
#define DIO41_RPORT PINA
|
||||
#define DIO41_WPORT PORTA
|
||||
#define DIO41_DDR DDRA
|
||||
#define DIO41_PWM nullptr
|
||||
|
||||
#define DIO42_PIN PINA4
|
||||
#define DIO42_RPORT PINA
|
||||
#define DIO42_WPORT PORTA
|
||||
#define DIO42_DDR DDRA
|
||||
#define DIO42_PWM nullptr
|
||||
|
||||
#define DIO43_PIN PINA5
|
||||
#define DIO43_RPORT PINA
|
||||
#define DIO43_WPORT PORTA
|
||||
#define DIO43_DDR DDRA
|
||||
#define DIO43_PWM nullptr
|
||||
|
||||
#define DIO44_PIN PINA6
|
||||
#define DIO44_RPORT PINA
|
||||
#define DIO44_WPORT PORTA
|
||||
#define DIO44_DDR DDRA
|
||||
#define DIO44_PWM nullptr
|
||||
|
||||
#define DIO45_PIN PINA7
|
||||
#define DIO45_RPORT PINA
|
||||
#define DIO45_WPORT PORTA
|
||||
#define DIO45_DDR DDRA
|
||||
#define DIO45_PWM nullptr
|
||||
|
||||
#define DIO46_PIN PINF0
|
||||
#define DIO46_RPORT PINF
|
||||
#define DIO46_WPORT PORTF
|
||||
#define DIO46_DDR DDRF
|
||||
#define DIO46_PWM nullptr
|
||||
|
||||
#define DIO47_PIN PINF1
|
||||
#define DIO47_RPORT PINF
|
||||
#define DIO47_WPORT PORTF
|
||||
#define DIO47_DDR DDRF
|
||||
#define DIO47_PWM nullptr
|
||||
|
||||
#define DIO48_PIN PINF2
|
||||
#define DIO48_RPORT PINF
|
||||
#define DIO48_WPORT PORTF
|
||||
#define DIO48_DDR DDRF
|
||||
#define DIO48_PWM nullptr
|
||||
|
||||
#define DIO49_PIN PINF3
|
||||
#define DIO49_RPORT PINF
|
||||
#define DIO49_WPORT PORTF
|
||||
#define DIO49_DDR DDRF
|
||||
#define DIO49_PWM nullptr
|
||||
|
||||
#define DIO50_PIN PINF4
|
||||
#define DIO50_RPORT PINF
|
||||
#define DIO50_WPORT PORTF
|
||||
#define DIO50_DDR DDRF
|
||||
#define DIO50_PWM nullptr
|
||||
|
||||
#define DIO51_PIN PINF5
|
||||
#define DIO51_RPORT PINF
|
||||
#define DIO51_WPORT PORTF
|
||||
#define DIO51_DDR DDRF
|
||||
#define DIO51_PWM nullptr
|
||||
|
||||
#define DIO52_PIN PINF6
|
||||
#define DIO52_RPORT PINF
|
||||
#define DIO52_WPORT PORTF
|
||||
#define DIO52_DDR DDRF
|
||||
#define DIO52_PWM nullptr
|
||||
|
||||
#define DIO53_PIN PINF7
|
||||
#define DIO53_RPORT PINF
|
||||
#define DIO53_WPORT PORTF
|
||||
#define DIO53_DDR DDRF
|
||||
#define DIO53_PWM nullptr
|
||||
|
||||
#undef PA0
|
||||
#define PA0_PIN PINA0
|
||||
#define PA0_RPORT PINA
|
||||
#define PA0_WPORT PORTA
|
||||
#define PA0_DDR DDRA
|
||||
#define PA0_PWM nullptr
|
||||
#undef PA1
|
||||
#define PA1_PIN PINA1
|
||||
#define PA1_RPORT PINA
|
||||
#define PA1_WPORT PORTA
|
||||
#define PA1_DDR DDRA
|
||||
#define PA1_PWM nullptr
|
||||
#undef PA2
|
||||
#define PA2_PIN PINA2
|
||||
#define PA2_RPORT PINA
|
||||
#define PA2_WPORT PORTA
|
||||
#define PA2_DDR DDRA
|
||||
#define PA2_PWM nullptr
|
||||
#undef PA3
|
||||
#define PA3_PIN PINA3
|
||||
#define PA3_RPORT PINA
|
||||
#define PA3_WPORT PORTA
|
||||
#define PA3_DDR DDRA
|
||||
#define PA3_PWM nullptr
|
||||
#undef PA4
|
||||
#define PA4_PIN PINA4
|
||||
#define PA4_RPORT PINA
|
||||
#define PA4_WPORT PORTA
|
||||
#define PA4_DDR DDRA
|
||||
#define PA4_PWM nullptr
|
||||
#undef PA5
|
||||
#define PA5_PIN PINA5
|
||||
#define PA5_RPORT PINA
|
||||
#define PA5_WPORT PORTA
|
||||
#define PA5_DDR DDRA
|
||||
#define PA5_PWM nullptr
|
||||
#undef PA6
|
||||
#define PA6_PIN PINA6
|
||||
#define PA6_RPORT PINA
|
||||
#define PA6_WPORT PORTA
|
||||
#define PA6_DDR DDRA
|
||||
#define PA6_PWM nullptr
|
||||
#undef PA7
|
||||
#define PA7_PIN PINA7
|
||||
#define PA7_RPORT PINA
|
||||
#define PA7_WPORT PORTA
|
||||
#define PA7_DDR DDRA
|
||||
#define PA7_PWM nullptr
|
||||
|
||||
#undef PB0
|
||||
#define PB0_PIN PINB0
|
||||
#define PB0_RPORT PINB
|
||||
#define PB0_WPORT PORTB
|
||||
#define PB0_DDR DDRB
|
||||
#define PB0_PWM nullptr
|
||||
#undef PB1
|
||||
#define PB1_PIN PINB1
|
||||
#define PB1_RPORT PINB
|
||||
#define PB1_WPORT PORTB
|
||||
#define PB1_DDR DDRB
|
||||
#define PB1_PWM nullptr
|
||||
#undef PB2
|
||||
#define PB2_PIN PINB2
|
||||
#define PB2_RPORT PINB
|
||||
#define PB2_WPORT PORTB
|
||||
#define PB2_DDR DDRB
|
||||
#define PB2_PWM nullptr
|
||||
#undef PB3
|
||||
#define PB3_PIN PINB3
|
||||
#define PB3_RPORT PINB
|
||||
#define PB3_WPORT PORTB
|
||||
#define PB3_DDR DDRB
|
||||
#define PB3_PWM nullptr
|
||||
#undef PB4
|
||||
#define PB4_PIN PINB4
|
||||
#define PB4_RPORT PINB
|
||||
#define PB4_WPORT PORTB
|
||||
#define PB4_DDR DDRB
|
||||
#define PB4_PWM &OCR2A
|
||||
#undef PB5
|
||||
#define PB5_PIN PINB5
|
||||
#define PB5_RPORT PINB
|
||||
#define PB5_WPORT PORTB
|
||||
#define PB5_DDR DDRB
|
||||
#define PB5_PWM nullptr
|
||||
#undef PB6
|
||||
#define PB6_PIN PINB6
|
||||
#define PB6_RPORT PINB
|
||||
#define PB6_WPORT PORTB
|
||||
#define PB6_DDR DDRB
|
||||
#define PB6_PWM nullptr
|
||||
#undef PB7
|
||||
#define PB7_PIN PINB7
|
||||
#define PB7_RPORT PINB
|
||||
#define PB7_WPORT PORTB
|
||||
#define PB7_DDR DDRB
|
||||
#define PB7_PWM &OCR0A
|
||||
|
||||
#undef PC0
|
||||
#define PC0_PIN PINC0
|
||||
#define PC0_RPORT PINC
|
||||
#define PC0_WPORT PORTC
|
||||
#define PC0_DDR DDRC
|
||||
#define PC0_PWM nullptr
|
||||
#undef PC1
|
||||
#define PC1_PIN PINC1
|
||||
#define PC1_RPORT PINC
|
||||
#define PC1_WPORT PORTC
|
||||
#define PC1_DDR DDRC
|
||||
#define PC1_PWM nullptr
|
||||
#undef PC2
|
||||
#define PC2_PIN PINC2
|
||||
#define PC2_RPORT PINC
|
||||
#define PC2_WPORT PORTC
|
||||
#define PC2_DDR DDRC
|
||||
#define PC2_PWM nullptr
|
||||
#undef PC3
|
||||
#define PC3_PIN PINC3
|
||||
#define PC3_RPORT PINC
|
||||
#define PC3_WPORT PORTC
|
||||
#define PC3_DDR DDRC
|
||||
#define PC3_PWM nullptr
|
||||
#undef PC4
|
||||
#define PC4_PIN PINC4
|
||||
#define PC4_RPORT PINC
|
||||
#define PC4_WPORT PORTC
|
||||
#define PC4_DDR DDRC
|
||||
#define PC4_PWM nullptr
|
||||
#undef PC5
|
||||
#define PC5_PIN PINC5
|
||||
#define PC5_RPORT PINC
|
||||
#define PC5_WPORT PORTC
|
||||
#define PC5_DDR DDRC
|
||||
#define PC5_PWM nullptr
|
||||
#undef PC6
|
||||
#define PC6_PIN PINC6
|
||||
#define PC6_RPORT PINC
|
||||
#define PC6_WPORT PORTC
|
||||
#define PC6_DDR DDRC
|
||||
#define PC6_PWM nullptr
|
||||
#undef PC7
|
||||
#define PC7_PIN PINC7
|
||||
#define PC7_RPORT PINC
|
||||
#define PC7_WPORT PORTC
|
||||
#define PC7_DDR DDRC
|
||||
#define PC7_PWM nullptr
|
||||
|
||||
#undef PD0
|
||||
#define PD0_PIN PIND0
|
||||
#define PD0_RPORT PIND
|
||||
#define PD0_WPORT PORTD
|
||||
#define PD0_DDR DDRD
|
||||
#define PD0_PWM nullptr
|
||||
#undef PD1
|
||||
#define PD1_PIN PIND1
|
||||
#define PD1_RPORT PIND
|
||||
#define PD1_WPORT PORTD
|
||||
#define PD1_DDR DDRD
|
||||
#define PD1_PWM nullptr
|
||||
#undef PD2
|
||||
#define PD2_PIN PIND2
|
||||
#define PD2_RPORT PIND
|
||||
#define PD2_WPORT PORTD
|
||||
#define PD2_DDR DDRD
|
||||
#define PD2_PWM nullptr
|
||||
#undef PD3
|
||||
#define PD3_PIN PIND3
|
||||
#define PD3_RPORT PIND
|
||||
#define PD3_WPORT PORTD
|
||||
#define PD3_DDR DDRD
|
||||
#define PD3_PWM nullptr
|
||||
#undef PD4
|
||||
#define PD4_PIN PIND4
|
||||
#define PD4_RPORT PIND
|
||||
#define PD4_WPORT PORTD
|
||||
#define PD4_DDR DDRD
|
||||
#define PD4_PWM nullptr
|
||||
#undef PD5
|
||||
#define PD5_PIN PIND5
|
||||
#define PD5_RPORT PIND
|
||||
#define PD5_WPORT PORTD
|
||||
#define PD5_DDR DDRD
|
||||
#define PD5_PWM nullptr
|
||||
#undef PD6
|
||||
#define PD6_PIN PIND6
|
||||
#define PD6_RPORT PIND
|
||||
#define PD6_WPORT PORTD
|
||||
#define PD6_DDR DDRD
|
||||
#define PD6_PWM nullptr
|
||||
#undef PD7
|
||||
#define PD7_PIN PIND7
|
||||
#define PD7_RPORT PIND
|
||||
#define PD7_WPORT PORTD
|
||||
#define PD7_DDR DDRD
|
||||
#define PD7_PWM nullptr
|
||||
|
||||
#undef PE0
|
||||
#define PE0_PIN PINE0
|
||||
#define PE0_RPORT PINE
|
||||
#define PE0_WPORT PORTE
|
||||
#define PE0_DDR DDRE
|
||||
#define PE0_PWM nullptr
|
||||
#undef PE1
|
||||
#define PE1_PIN PINE1
|
||||
#define PE1_RPORT PINE
|
||||
#define PE1_WPORT PORTE
|
||||
#define PE1_DDR DDRE
|
||||
#define PE1_PWM nullptr
|
||||
#undef PE2
|
||||
#define PE2_PIN PINE2
|
||||
#define PE2_RPORT PINE
|
||||
#define PE2_WPORT PORTE
|
||||
#define PE2_DDR DDRE
|
||||
#define PE2_PWM nullptr
|
||||
#undef PE3
|
||||
#define PE3_PIN PINE3
|
||||
#define PE3_RPORT PINE
|
||||
#define PE3_WPORT PORTE
|
||||
#define PE3_DDR DDRE
|
||||
#define PE3_PWM &OCR3AL
|
||||
#undef PE4
|
||||
#define PE4_PIN PINE4
|
||||
#define PE4_RPORT PINE
|
||||
#define PE4_WPORT PORTE
|
||||
#define PE4_DDR DDRE
|
||||
#define PE4_PWM &OCR3BL
|
||||
#undef PE5
|
||||
#define PE5_PIN PINE5
|
||||
#define PE5_RPORT PINE
|
||||
#define PE5_WPORT PORTE
|
||||
#define PE5_DDR DDRE
|
||||
#define PE5_PWM &OCR3CL
|
||||
#undef PE6
|
||||
#define PE6_PIN PINE6
|
||||
#define PE6_RPORT PINE
|
||||
#define PE6_WPORT PORTE
|
||||
#define PE6_DDR DDRE
|
||||
#define PE6_PWM nullptr
|
||||
#undef PE7
|
||||
#define PE7_PIN PINE7
|
||||
#define PE7_RPORT PINE
|
||||
#define PE7_WPORT PORTE
|
||||
#define PE7_DDR DDRE
|
||||
#define PE7_PWM nullptr
|
||||
|
||||
#undef PF0
|
||||
#define PF0_PIN PINF0
|
||||
#define PF0_RPORT PINF
|
||||
#define PF0_WPORT PORTF
|
||||
#define PF0_DDR DDRF
|
||||
#define PF0_PWM nullptr
|
||||
#undef PF1
|
||||
#define PF1_PIN PINF1
|
||||
#define PF1_RPORT PINF
|
||||
#define PF1_WPORT PORTF
|
||||
#define PF1_DDR DDRF
|
||||
#define PF1_PWM nullptr
|
||||
#undef PF2
|
||||
#define PF2_PIN PINF2
|
||||
#define PF2_RPORT PINF
|
||||
#define PF2_WPORT PORTF
|
||||
#define PF2_DDR DDRF
|
||||
#define PF2_PWM nullptr
|
||||
#undef PF3
|
||||
#define PF3_PIN PINF3
|
||||
#define PF3_RPORT PINF
|
||||
#define PF3_WPORT PORTF
|
||||
#define PF3_DDR DDRF
|
||||
#define PF3_PWM nullptr
|
||||
#undef PF4
|
||||
#define PF4_PIN PINF4
|
||||
#define PF4_RPORT PINF
|
||||
#define PF4_WPORT PORTF
|
||||
#define PF4_DDR DDRF
|
||||
#define PF4_PWM nullptr
|
||||
#undef PF5
|
||||
#define PF5_PIN PINF5
|
||||
#define PF5_RPORT PINF
|
||||
#define PF5_WPORT PORTF
|
||||
#define PF5_DDR DDRF
|
||||
#define PF5_PWM nullptr
|
||||
#undef PF6
|
||||
#define PF6_PIN PINF6
|
||||
#define PF6_RPORT PINF
|
||||
#define PF6_WPORT PORTF
|
||||
#define PF6_DDR DDRF
|
||||
#define PF6_PWM nullptr
|
||||
#undef PF7
|
||||
#define PF7_PIN PINF7
|
||||
#define PF7_RPORT PINF
|
||||
#define PF7_WPORT PORTF
|
||||
#define PF7_DDR DDRF
|
||||
#define PF7_PWM nullptr
|
||||
|
||||
#undef PG0
|
||||
#define PG0_PIN PING0
|
||||
#define PG0_RPORT PING
|
||||
#define PG0_WPORT PORTG
|
||||
#define PG0_DDR DDRG
|
||||
#define PG0_PWM nullptr
|
||||
#undef PG1
|
||||
#define PG1_PIN PING1
|
||||
#define PG1_RPORT PING
|
||||
#define PG1_WPORT PORTG
|
||||
#define PG1_DDR DDRG
|
||||
#define PG1_PWM nullptr
|
||||
#undef PG2
|
||||
#define PG2_PIN PING2
|
||||
#define PG2_RPORT PING
|
||||
#define PG2_WPORT PORTG
|
||||
#define PG2_DDR DDRG
|
||||
#define PG2_PWM nullptr
|
||||
#undef PG3
|
||||
#define PG3_PIN PING3
|
||||
#define PG3_RPORT PING
|
||||
#define PG3_WPORT PORTG
|
||||
#define PG3_DDR DDRG
|
||||
#define PG3_PWM nullptr
|
||||
#undef PG4
|
||||
#define PG4_PIN PING4
|
||||
#define PG4_RPORT PING
|
||||
#define PG4_WPORT PORTG
|
||||
#define PG4_DDR DDRG
|
||||
#define PG4_PWM nullptr
|
||||
#undef PG5
|
||||
#define PG5_PIN PING5
|
||||
#define PG5_RPORT PING
|
||||
#define PG5_WPORT PORTG
|
||||
#define PG5_DDR DDRG
|
||||
#define PG5_PWM &OCR0B
|
|
@ -0,0 +1,355 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Pin mapping for the 168, 328, and 328P
|
||||
*
|
||||
* Logical Pin: 08 09 10 11 12 13 14 15 16 17 18 19 20 21 00 01 02 03 04 05 06 07
|
||||
* Port: B0 B1 B2 B3 B4 B5 C0 C1 C2 C3 C4 C5 C6 C7 D0 D1 D2 D3 D4 D5 D6 D7
|
||||
*/
|
||||
|
||||
#include "../fastio.h"
|
||||
|
||||
// UART
|
||||
#define RXD 0
|
||||
#define TXD 1
|
||||
|
||||
// SPI
|
||||
#define SS 10
|
||||
#define MOSI 11
|
||||
#define MISO 12
|
||||
#define SCK 13
|
||||
|
||||
// TWI (I2C)
|
||||
#define SCL AIO5
|
||||
#define SDA AIO4
|
||||
|
||||
// Timers and PWM
|
||||
#define OC0A 6
|
||||
#define OC0B 5
|
||||
#define OC1A 9
|
||||
#define OC1B 10
|
||||
#define OC2A 11
|
||||
#define OC2B 3
|
||||
|
||||
// Digital I/O
|
||||
|
||||
#define DIO0_PIN PIND0
|
||||
#define DIO0_RPORT PIND
|
||||
#define DIO0_WPORT PORTD
|
||||
#define DIO0_DDR DDRD
|
||||
#define DIO0_PWM nullptr
|
||||
|
||||
#define DIO1_PIN PIND1
|
||||
#define DIO1_RPORT PIND
|
||||
#define DIO1_WPORT PORTD
|
||||
#define DIO1_DDR DDRD
|
||||
#define DIO1_PWM nullptr
|
||||
|
||||
#define DIO2_PIN PIND2
|
||||
#define DIO2_RPORT PIND
|
||||
#define DIO2_WPORT PORTD
|
||||
#define DIO2_DDR DDRD
|
||||
#define DIO2_PWM nullptr
|
||||
|
||||
#define DIO3_PIN PIND3
|
||||
#define DIO3_RPORT PIND
|
||||
#define DIO3_WPORT PORTD
|
||||
#define DIO3_DDR DDRD
|
||||
#define DIO3_PWM &OCR2B
|
||||
|
||||
#define DIO4_PIN PIND4
|
||||
#define DIO4_RPORT PIND
|
||||
#define DIO4_WPORT PORTD
|
||||
#define DIO4_DDR DDRD
|
||||
#define DIO4_PWM nullptr
|
||||
|
||||
#define DIO5_PIN PIND5
|
||||
#define DIO5_RPORT PIND
|
||||
#define DIO5_WPORT PORTD
|
||||
#define DIO5_DDR DDRD
|
||||
#define DIO5_PWM &OCR0B
|
||||
|
||||
#define DIO6_PIN PIND6
|
||||
#define DIO6_RPORT PIND
|
||||
#define DIO6_WPORT PORTD
|
||||
#define DIO6_DDR DDRD
|
||||
#define DIO6_PWM &OCR0A
|
||||
|
||||
#define DIO7_PIN PIND7
|
||||
#define DIO7_RPORT PIND
|
||||
#define DIO7_WPORT PORTD
|
||||
#define DIO7_DDR DDRD
|
||||
#define DIO7_PWM nullptr
|
||||
|
||||
#define DIO8_PIN PINB0
|
||||
#define DIO8_RPORT PINB
|
||||
#define DIO8_WPORT PORTB
|
||||
#define DIO8_DDR DDRB
|
||||
#define DIO8_PWM nullptr
|
||||
|
||||
#define DIO9_PIN PINB1
|
||||
#define DIO9_RPORT PINB
|
||||
#define DIO9_WPORT PORTB
|
||||
#define DIO9_DDR DDRB
|
||||
#define DIO9_PWM nullptr
|
||||
|
||||
#define DIO10_PIN PINB2
|
||||
#define DIO10_RPORT PINB
|
||||
#define DIO10_WPORT PORTB
|
||||
#define DIO10_DDR DDRB
|
||||
#define DIO10_PWM nullptr
|
||||
|
||||
#define DIO11_PIN PINB3
|
||||
#define DIO11_RPORT PINB
|
||||
#define DIO11_WPORT PORTB
|
||||
#define DIO11_DDR DDRB
|
||||
#define DIO11_PWM &OCR2A
|
||||
|
||||
#define DIO12_PIN PINB4
|
||||
#define DIO12_RPORT PINB
|
||||
#define DIO12_WPORT PORTB
|
||||
#define DIO12_DDR DDRB
|
||||
#define DIO12_PWM nullptr
|
||||
|
||||
#define DIO13_PIN PINB5
|
||||
#define DIO13_RPORT PINB
|
||||
#define DIO13_WPORT PORTB
|
||||
#define DIO13_DDR DDRB
|
||||
#define DIO13_PWM nullptr
|
||||
|
||||
#define DIO14_PIN PINC0
|
||||
#define DIO14_RPORT PINC
|
||||
#define DIO14_WPORT PORTC
|
||||
#define DIO14_DDR DDRC
|
||||
#define DIO14_PWM nullptr
|
||||
|
||||
#define DIO15_PIN PINC1
|
||||
#define DIO15_RPORT PINC
|
||||
#define DIO15_WPORT PORTC
|
||||
#define DIO15_DDR DDRC
|
||||
#define DIO15_PWM nullptr
|
||||
|
||||
#define DIO16_PIN PINC2
|
||||
#define DIO16_RPORT PINC
|
||||
#define DIO16_WPORT PORTC
|
||||
#define DIO16_DDR DDRC
|
||||
#define DIO16_PWM nullptr
|
||||
|
||||
#define DIO17_PIN PINC3
|
||||
#define DIO17_RPORT PINC
|
||||
#define DIO17_WPORT PORTC
|
||||
#define DIO17_DDR DDRC
|
||||
#define DIO17_PWM nullptr
|
||||
|
||||
#define DIO18_PIN PINC4
|
||||
#define DIO18_RPORT PINC
|
||||
#define DIO18_WPORT PORTC
|
||||
#define DIO18_DDR DDRC
|
||||
#define DIO18_PWM nullptr
|
||||
|
||||
#define DIO19_PIN PINC5
|
||||
#define DIO19_RPORT PINC
|
||||
#define DIO19_WPORT PORTC
|
||||
#define DIO19_DDR DDRC
|
||||
#define DIO19_PWM nullptr
|
||||
|
||||
#define DIO20_PIN PINC6
|
||||
#define DIO20_RPORT PINC
|
||||
#define DIO20_WPORT PORTC
|
||||
#define DIO20_DDR DDRC
|
||||
#define DIO20_PWM nullptr
|
||||
|
||||
#define DIO21_PIN PINC7
|
||||
#define DIO21_RPORT PINC
|
||||
#define DIO21_WPORT PORTC
|
||||
#define DIO21_DDR DDRC
|
||||
#define DIO21_PWM nullptr
|
||||
|
||||
#undef PB0
|
||||
#define PB0_PIN PINB0
|
||||
#define PB0_RPORT PINB
|
||||
#define PB0_WPORT PORTB
|
||||
#define PB0_DDR DDRB
|
||||
#define PB0_PWM nullptr
|
||||
|
||||
#undef PB1
|
||||
#define PB1_PIN PINB1
|
||||
#define PB1_RPORT PINB
|
||||
#define PB1_WPORT PORTB
|
||||
#define PB1_DDR DDRB
|
||||
#define PB1_PWM nullptr
|
||||
|
||||
#undef PB2
|
||||
#define PB2_PIN PINB2
|
||||
#define PB2_RPORT PINB
|
||||
#define PB2_WPORT PORTB
|
||||
#define PB2_DDR DDRB
|
||||
#define PB2_PWM nullptr
|
||||
|
||||
#undef PB3
|
||||
#define PB3_PIN PINB3
|
||||
#define PB3_RPORT PINB
|
||||
#define PB3_WPORT PORTB
|
||||
#define PB3_DDR DDRB
|
||||
#define PB3_PWM &OCR2A
|
||||
|
||||
#undef PB4
|
||||
#define PB4_PIN PINB4
|
||||
#define PB4_RPORT PINB
|
||||
#define PB4_WPORT PORTB
|
||||
#define PB4_DDR DDRB
|
||||
#define PB4_PWM nullptr
|
||||
|
||||
#undef PB5
|
||||
#define PB5_PIN PINB5
|
||||
#define PB5_RPORT PINB
|
||||
#define PB5_WPORT PORTB
|
||||
#define PB5_DDR DDRB
|
||||
#define PB5_PWM nullptr
|
||||
|
||||
#undef PB6
|
||||
#define PB6_PIN PINB6
|
||||
#define PB6_RPORT PINB
|
||||
#define PB6_WPORT PORTB
|
||||
#define PB6_DDR DDRB
|
||||
#define PB6_PWM nullptr
|
||||
|
||||
#undef PB7
|
||||
#define PB7_PIN PINB7
|
||||
#define PB7_RPORT PINB
|
||||
#define PB7_WPORT PORTB
|
||||
#define PB7_DDR DDRB
|
||||
#define PB7_PWM nullptr
|
||||
|
||||
#undef PC0
|
||||
#define PC0_PIN PINC0
|
||||
#define PC0_RPORT PINC
|
||||
#define PC0_WPORT PORTC
|
||||
#define PC0_DDR DDRC
|
||||
#define PC0_PWM nullptr
|
||||
|
||||
#undef PC1
|
||||
#define PC1_PIN PINC1
|
||||
#define PC1_RPORT PINC
|
||||
#define PC1_WPORT PORTC
|
||||
#define PC1_DDR DDRC
|
||||
#define PC1_PWM nullptr
|
||||
|
||||
#undef PC2
|
||||
#define PC2_PIN PINC2
|
||||
#define PC2_RPORT PINC
|
||||
#define PC2_WPORT PORTC
|
||||
#define PC2_DDR DDRC
|
||||
#define PC2_PWM nullptr
|
||||
|
||||
#undef PC3
|
||||
#define PC3_PIN PINC3
|
||||
#define PC3_RPORT PINC
|
||||
#define PC3_WPORT PORTC
|
||||
#define PC3_DDR DDRC
|
||||
#define PC3_PWM nullptr
|
||||
|
||||
#undef PC4
|
||||
#define PC4_PIN PINC4
|
||||
#define PC4_RPORT PINC
|
||||
#define PC4_WPORT PORTC
|
||||
#define PC4_DDR DDRC
|
||||
#define PC4_PWM nullptr
|
||||
|
||||
#undef PC5
|
||||
#define PC5_PIN PINC5
|
||||
#define PC5_RPORT PINC
|
||||
#define PC5_WPORT PORTC
|
||||
#define PC5_DDR DDRC
|
||||
#define PC5_PWM nullptr
|
||||
|
||||
#undef PC6
|
||||
#define PC6_PIN PINC6
|
||||
#define PC6_RPORT PINC
|
||||
#define PC6_WPORT PORTC
|
||||
#define PC6_DDR DDRC
|
||||
#define PC6_PWM nullptr
|
||||
|
||||
#undef PC7
|
||||
#define PC7_PIN PINC7
|
||||
#define PC7_RPORT PINC
|
||||
#define PC7_WPORT PORTC
|
||||
#define PC7_DDR DDRC
|
||||
#define PC7_PWM nullptr
|
||||
|
||||
#undef PD0
|
||||
#define PD0_PIN PIND0
|
||||
#define PD0_RPORT PIND
|
||||
#define PD0_WPORT PORTD
|
||||
#define PD0_DDR DDRD
|
||||
#define PD0_PWM nullptr
|
||||
|
||||
#undef PD1
|
||||
#define PD1_PIN PIND1
|
||||
#define PD1_RPORT PIND
|
||||
#define PD1_WPORT PORTD
|
||||
#define PD1_DDR DDRD
|
||||
#define PD1_PWM nullptr
|
||||
|
||||
#undef PD2
|
||||
#define PD2_PIN PIND2
|
||||
#define PD2_RPORT PIND
|
||||
#define PD2_WPORT PORTD
|
||||
#define PD2_DDR DDRD
|
||||
#define PD2_PWM nullptr
|
||||
|
||||
#undef PD3
|
||||
#define PD3_PIN PIND3
|
||||
#define PD3_RPORT PIND
|
||||
#define PD3_WPORT PORTD
|
||||
#define PD3_DDR DDRD
|
||||
#define PD3_PWM &OCR2B
|
||||
|
||||
#undef PD4
|
||||
#define PD4_PIN PIND4
|
||||
#define PD4_RPORT PIND
|
||||
#define PD4_WPORT PORTD
|
||||
#define PD4_DDR DDRD
|
||||
#define PD4_PWM nullptr
|
||||
|
||||
#undef PD5
|
||||
#define PD5_PIN PIND5
|
||||
#define PD5_RPORT PIND
|
||||
#define PD5_WPORT PORTD
|
||||
#define PD5_DDR DDRD
|
||||
#define PD5_PWM &OCR0B
|
||||
|
||||
#undef PD6
|
||||
#define PD6_PIN PIND6
|
||||
#define PD6_RPORT PIND
|
||||
#define PD6_WPORT PORTD
|
||||
#define PD6_DDR DDRD
|
||||
#define PD6_PWM &OCR0A
|
||||
|
||||
#undef PD7
|
||||
#define PD7_PIN PIND7
|
||||
#define PD7_RPORT PIND
|
||||
#define PD7_WPORT PORTD
|
||||
#define PD7_DDR DDRD
|
||||
#define PD7_PWM nullptr
|
|
@ -0,0 +1,550 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Pin mapping for the 644, 644p, 644pa, and 1284p
|
||||
*
|
||||
* Logical Pin: 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
|
||||
* Port: B0 B1 B2 B3 B4 B5 B6 B7 D0 D1 D2 D3 D4 D5 D6 D7 C0 C1 C2 C3 C4 C5 C6 C7 A7 A6 A5 A4 A3 A2 A1 A0
|
||||
*/
|
||||
|
||||
/** ATMega644
|
||||
*
|
||||
* +---\/---+
|
||||
* (D 0) PB0 1| |40 PA0 (AI 0 / D31)
|
||||
* (D 1) PB1 2| |39 PA1 (AI 1 / D30)
|
||||
* INT2 (D 2) PB2 3| |38 PA2 (AI 2 / D29)
|
||||
* PWM (D 3) PB3 4| |37 PA3 (AI 3 / D28)
|
||||
* PWM (D 4) PB4 5| |36 PA4 (AI 4 / D27)
|
||||
* MOSI (D 5) PB5 6| |35 PA5 (AI 5 / D26)
|
||||
* MISO (D 6) PB6 7| |34 PA6 (AI 6 / D25)
|
||||
* SCK (D 7) PB7 8| |33 PA7 (AI 7 / D24)
|
||||
* RST 9| |32 AREF
|
||||
* VCC 10| |31 GND
|
||||
* GND 11| |30 AVCC
|
||||
* XTAL2 12| |29 PC7 (D 23)
|
||||
* XTAL1 13| |28 PC6 (D 22)
|
||||
* RX0 (D 8) PD0 14| |27 PC5 (D 21) TDI
|
||||
* TX0 (D 9) PD1 15| |26 PC4 (D 20) TDO
|
||||
* INT0 RX1 (D 10) PD2 16| |25 PC3 (D 19) TMS
|
||||
* INT1 TX1 (D 11) PD3 17| |24 PC2 (D 18) TCK
|
||||
* PWM (D 12) PD4 18| |23 PC1 (D 17) SDA
|
||||
* PWM (D 13) PD5 19| |22 PC0 (D 16) SCL
|
||||
* PWM (D 14) PD6 20| |21 PD7 (D 15) PWM
|
||||
* +--------+
|
||||
*/
|
||||
|
||||
#include "../fastio.h"
|
||||
|
||||
// UART
|
||||
#define RXD 8
|
||||
#define TXD 9
|
||||
#define RXD0 8
|
||||
#define TXD0 9
|
||||
|
||||
#define RXD1 10
|
||||
#define TXD1 11
|
||||
|
||||
// SPI
|
||||
#define SS 4
|
||||
#define MOSI 5
|
||||
#define MISO 6
|
||||
#define SCK 7
|
||||
|
||||
// TWI (I2C)
|
||||
#define SCL 16
|
||||
#define SDA 17
|
||||
|
||||
// Timers and PWM
|
||||
#define OC0A 3
|
||||
#define OC0B 4
|
||||
#define OC1A 13
|
||||
#define OC1B 12
|
||||
#define OC2A 15
|
||||
#define OC2B 14
|
||||
|
||||
// Digital I/O
|
||||
|
||||
#define DIO0_PIN PINB0
|
||||
#define DIO0_RPORT PINB
|
||||
#define DIO0_WPORT PORTB
|
||||
#define DIO0_DDR DDRB
|
||||
#define DIO0_PWM nullptr
|
||||
|
||||
#define DIO1_PIN PINB1
|
||||
#define DIO1_RPORT PINB
|
||||
#define DIO1_WPORT PORTB
|
||||
#define DIO1_DDR DDRB
|
||||
#define DIO1_PWM nullptr
|
||||
|
||||
#define DIO2_PIN PINB2
|
||||
#define DIO2_RPORT PINB
|
||||
#define DIO2_WPORT PORTB
|
||||
#define DIO2_DDR DDRB
|
||||
#define DIO2_PWM nullptr
|
||||
|
||||
#define DIO3_PIN PINB3
|
||||
#define DIO3_RPORT PINB
|
||||
#define DIO3_WPORT PORTB
|
||||
#define DIO3_DDR DDRB
|
||||
#define DIO3_PWM &OCR0A
|
||||
|
||||
#define DIO4_PIN PINB4
|
||||
#define DIO4_RPORT PINB
|
||||
#define DIO4_WPORT PORTB
|
||||
#define DIO4_DDR DDRB
|
||||
#define DIO4_PWM &OCR0B
|
||||
|
||||
#define DIO5_PIN PINB5
|
||||
#define DIO5_RPORT PINB
|
||||
#define DIO5_WPORT PORTB
|
||||
#define DIO5_DDR DDRB
|
||||
#define DIO5_PWM nullptr
|
||||
|
||||
#define DIO6_PIN PINB6
|
||||
#define DIO6_RPORT PINB
|
||||
#define DIO6_WPORT PORTB
|
||||
#define DIO6_DDR DDRB
|
||||
#define DIO6_PWM nullptr
|
||||
|
||||
#define DIO7_PIN PINB7
|
||||
#define DIO7_RPORT PINB
|
||||
#define DIO7_WPORT PORTB
|
||||
#define DIO7_DDR DDRB
|
||||
#define DIO7_PWM nullptr
|
||||
|
||||
#define DIO8_PIN PIND0
|
||||
#define DIO8_RPORT PIND
|
||||
#define DIO8_WPORT PORTD
|
||||
#define DIO8_DDR DDRD
|
||||
#define DIO8_PWM nullptr
|
||||
|
||||
#define DIO9_PIN PIND1
|
||||
#define DIO9_RPORT PIND
|
||||
#define DIO9_WPORT PORTD
|
||||
#define DIO9_DDR DDRD
|
||||
#define DIO9_PWM nullptr
|
||||
|
||||
#define DIO10_PIN PIND2
|
||||
#define DIO10_RPORT PIND
|
||||
#define DIO10_WPORT PORTD
|
||||
#define DIO10_DDR DDRD
|
||||
#define DIO10_PWM nullptr
|
||||
|
||||
#define DIO11_PIN PIND3
|
||||
#define DIO11_RPORT PIND
|
||||
#define DIO11_WPORT PORTD
|
||||
#define DIO11_DDR DDRD
|
||||
#define DIO11_PWM nullptr
|
||||
|
||||
#define DIO12_PIN PIND4
|
||||
#define DIO12_RPORT PIND
|
||||
#define DIO12_WPORT PORTD
|
||||
#define DIO12_DDR DDRD
|
||||
#define DIO12_PWM &OCR1B
|
||||
|
||||
#define DIO13_PIN PIND5
|
||||
#define DIO13_RPORT PIND
|
||||
#define DIO13_WPORT PORTD
|
||||
#define DIO13_DDR DDRD
|
||||
#define DIO13_PWM &OCR1A
|
||||
|
||||
#define DIO14_PIN PIND6
|
||||
#define DIO14_RPORT PIND
|
||||
#define DIO14_WPORT PORTD
|
||||
#define DIO14_DDR DDRD
|
||||
#define DIO14_PWM &OCR2B
|
||||
|
||||
#define DIO15_PIN PIND7
|
||||
#define DIO15_RPORT PIND
|
||||
#define DIO15_WPORT PORTD
|
||||
#define DIO15_DDR DDRD
|
||||
#define DIO15_PWM &OCR2A
|
||||
|
||||
#define DIO16_PIN PINC0
|
||||
#define DIO16_RPORT PINC
|
||||
#define DIO16_WPORT PORTC
|
||||
#define DIO16_DDR DDRC
|
||||
#define DIO16_PWM nullptr
|
||||
|
||||
#define DIO17_PIN PINC1
|
||||
#define DIO17_RPORT PINC
|
||||
#define DIO17_WPORT PORTC
|
||||
#define DIO17_DDR DDRC
|
||||
#define DIO17_PWM nullptr
|
||||
|
||||
#define DIO18_PIN PINC2
|
||||
#define DIO18_RPORT PINC
|
||||
#define DIO18_WPORT PORTC
|
||||
#define DIO18_DDR DDRC
|
||||
#define DIO18_PWM nullptr
|
||||
|
||||
#define DIO19_PIN PINC3
|
||||
#define DIO19_RPORT PINC
|
||||
#define DIO19_WPORT PORTC
|
||||
#define DIO19_DDR DDRC
|
||||
#define DIO19_PWM nullptr
|
||||
|
||||
#define DIO20_PIN PINC4
|
||||
#define DIO20_RPORT PINC
|
||||
#define DIO20_WPORT PORTC
|
||||
#define DIO20_DDR DDRC
|
||||
#define DIO20_PWM nullptr
|
||||
|
||||
#define DIO21_PIN PINC5
|
||||
#define DIO21_RPORT PINC
|
||||
#define DIO21_WPORT PORTC
|
||||
#define DIO21_DDR DDRC
|
||||
#define DIO21_PWM nullptr
|
||||
|
||||
#define DIO22_PIN PINC6
|
||||
#define DIO22_RPORT PINC
|
||||
#define DIO22_WPORT PORTC
|
||||
#define DIO22_DDR DDRC
|
||||
#define DIO22_PWM nullptr
|
||||
|
||||
#define DIO23_PIN PINC7
|
||||
#define DIO23_RPORT PINC
|
||||
#define DIO23_WPORT PORTC
|
||||
#define DIO23_DDR DDRC
|
||||
#define DIO23_PWM nullptr
|
||||
|
||||
#define DIO24_PIN PINA7
|
||||
#define DIO24_RPORT PINA
|
||||
#define DIO24_WPORT PORTA
|
||||
#define DIO24_DDR DDRA
|
||||
#define DIO24_PWM nullptr
|
||||
|
||||
#define DIO25_PIN PINA6
|
||||
#define DIO25_RPORT PINA
|
||||
#define DIO25_WPORT PORTA
|
||||
#define DIO25_DDR DDRA
|
||||
#define DIO25_PWM nullptr
|
||||
|
||||
#define DIO26_PIN PINA5
|
||||
#define DIO26_RPORT PINA
|
||||
#define DIO26_WPORT PORTA
|
||||
#define DIO26_DDR DDRA
|
||||
#define DIO26_PWM nullptr
|
||||
|
||||
#define DIO27_PIN PINA4
|
||||
#define DIO27_RPORT PINA
|
||||
#define DIO27_WPORT PORTA
|
||||
#define DIO27_DDR DDRA
|
||||
#define DIO27_PWM nullptr
|
||||
|
||||
#define DIO28_PIN PINA3
|
||||
#define DIO28_RPORT PINA
|
||||
#define DIO28_WPORT PORTA
|
||||
#define DIO28_DDR DDRA
|
||||
#define DIO28_PWM nullptr
|
||||
|
||||
#define DIO29_PIN PINA2
|
||||
#define DIO29_RPORT PINA
|
||||
#define DIO29_WPORT PORTA
|
||||
#define DIO29_DDR DDRA
|
||||
#define DIO29_PWM nullptr
|
||||
|
||||
#define DIO30_PIN PINA1
|
||||
#define DIO30_RPORT PINA
|
||||
#define DIO30_WPORT PORTA
|
||||
#define DIO30_DDR DDRA
|
||||
#define DIO30_PWM nullptr
|
||||
|
||||
#define DIO31_PIN PINA0
|
||||
#define DIO31_RPORT PINA
|
||||
#define DIO31_WPORT PORTA
|
||||
#define DIO31_DDR DDRA
|
||||
#define DIO31_PWM nullptr
|
||||
|
||||
#define AIO0_PIN PINA0
|
||||
#define AIO0_RPORT PINA
|
||||
#define AIO0_WPORT PORTA
|
||||
#define AIO0_DDR DDRA
|
||||
#define AIO0_PWM nullptr
|
||||
|
||||
#define AIO1_PIN PINA1
|
||||
#define AIO1_RPORT PINA
|
||||
#define AIO1_WPORT PORTA
|
||||
#define AIO1_DDR DDRA
|
||||
#define AIO1_PWM nullptr
|
||||
|
||||
#define AIO2_PIN PINA2
|
||||
#define AIO2_RPORT PINA
|
||||
#define AIO2_WPORT PORTA
|
||||
#define AIO2_DDR DDRA
|
||||
#define AIO2_PWM nullptr
|
||||
|
||||
#define AIO3_PIN PINA3
|
||||
#define AIO3_RPORT PINA
|
||||
#define AIO3_WPORT PORTA
|
||||
#define AIO3_DDR DDRA
|
||||
#define AIO3_PWM nullptr
|
||||
|
||||
#define AIO4_PIN PINA4
|
||||
#define AIO4_RPORT PINA
|
||||
#define AIO4_WPORT PORTA
|
||||
#define AIO4_DDR DDRA
|
||||
#define AIO4_PWM nullptr
|
||||
|
||||
#define AIO5_PIN PINA5
|
||||
#define AIO5_RPORT PINA
|
||||
#define AIO5_WPORT PORTA
|
||||
#define AIO5_DDR DDRA
|
||||
#define AIO5_PWM nullptr
|
||||
|
||||
#define AIO6_PIN PINA6
|
||||
#define AIO6_RPORT PINA
|
||||
#define AIO6_WPORT PORTA
|
||||
#define AIO6_DDR DDRA
|
||||
#define AIO6_PWM nullptr
|
||||
|
||||
#define AIO7_PIN PINA7
|
||||
#define AIO7_RPORT PINA
|
||||
#define AIO7_WPORT PORTA
|
||||
#define AIO7_DDR DDRA
|
||||
#define AIO7_PWM nullptr
|
||||
|
||||
#undef PA0
|
||||
#define PA0_PIN PINA0
|
||||
#define PA0_RPORT PINA
|
||||
#define PA0_WPORT PORTA
|
||||
#define PA0_DDR DDRA
|
||||
#define PA0_PWM nullptr
|
||||
|
||||
#undef PA1
|
||||
#define PA1_PIN PINA1
|
||||
#define PA1_RPORT PINA
|
||||
#define PA1_WPORT PORTA
|
||||
#define PA1_DDR DDRA
|
||||
#define PA1_PWM nullptr
|
||||
|
||||
#undef PA2
|
||||
#define PA2_PIN PINA2
|
||||
#define PA2_RPORT PINA
|
||||
#define PA2_WPORT PORTA
|
||||
#define PA2_DDR DDRA
|
||||
#define PA2_PWM nullptr
|
||||
|
||||
#undef PA3
|
||||
#define PA3_PIN PINA3
|
||||
#define PA3_RPORT PINA
|
||||
#define PA3_WPORT PORTA
|
||||
#define PA3_DDR DDRA
|
||||
#define PA3_PWM nullptr
|
||||
|
||||
#undef PA4
|
||||
#define PA4_PIN PINA4
|
||||
#define PA4_RPORT PINA
|
||||
#define PA4_WPORT PORTA
|
||||
#define PA4_DDR DDRA
|
||||
#define PA4_PWM nullptr
|
||||
|
||||
#undef PA5
|
||||
#define PA5_PIN PINA5
|
||||
#define PA5_RPORT PINA
|
||||
#define PA5_WPORT PORTA
|
||||
#define PA5_DDR DDRA
|
||||
#define PA5_PWM nullptr
|
||||
|
||||
#undef PA6
|
||||
#define PA6_PIN PINA6
|
||||
#define PA6_RPORT PINA
|
||||
#define PA6_WPORT PORTA
|
||||
#define PA6_DDR DDRA
|
||||
#define PA6_PWM nullptr
|
||||
|
||||
#undef PA7
|
||||
#define PA7_PIN PINA7
|
||||
#define PA7_RPORT PINA
|
||||
#define PA7_WPORT PORTA
|
||||
#define PA7_DDR DDRA
|
||||
#define PA7_PWM nullptr
|
||||
|
||||
#undef PB0
|
||||
#define PB0_PIN PINB0
|
||||
#define PB0_RPORT PINB
|
||||
#define PB0_WPORT PORTB
|
||||
#define PB0_DDR DDRB
|
||||
#define PB0_PWM nullptr
|
||||
|
||||
#undef PB1
|
||||
#define PB1_PIN PINB1
|
||||
#define PB1_RPORT PINB
|
||||
#define PB1_WPORT PORTB
|
||||
#define PB1_DDR DDRB
|
||||
#define PB1_PWM nullptr
|
||||
|
||||
#undef PB2
|
||||
#define PB2_PIN PINB2
|
||||
#define PB2_RPORT PINB
|
||||
#define PB2_WPORT PORTB
|
||||
#define PB2_DDR DDRB
|
||||
#define PB2_PWM nullptr
|
||||
|
||||
#undef PB3
|
||||
#define PB3_PIN PINB3
|
||||
#define PB3_RPORT PINB
|
||||
#define PB3_WPORT PORTB
|
||||
#define PB3_DDR DDRB
|
||||
#define PB3_PWM &OCR0A
|
||||
|
||||
#undef PB4
|
||||
#define PB4_PIN PINB4
|
||||
#define PB4_RPORT PINB
|
||||
#define PB4_WPORT PORTB
|
||||
#define PB4_DDR DDRB
|
||||
#define PB4_PWM &OCR0B
|
||||
|
||||
#undef PB5
|
||||
#define PB5_PIN PINB5
|
||||
#define PB5_RPORT PINB
|
||||
#define PB5_WPORT PORTB
|
||||
#define PB5_DDR DDRB
|
||||
#define PB5_PWM nullptr
|
||||
|
||||
#undef PB6
|
||||
#define PB6_PIN PINB6
|
||||
#define PB6_RPORT PINB
|
||||
#define PB6_WPORT PORTB
|
||||
#define PB6_DDR DDRB
|
||||
#define PB6_PWM nullptr
|
||||
|
||||
#undef PB7
|
||||
#define PB7_PIN PINB7
|
||||
#define PB7_RPORT PINB
|
||||
#define PB7_WPORT PORTB
|
||||
#define PB7_DDR DDRB
|
||||
#define PB7_PWM nullptr
|
||||
|
||||
#undef PC0
|
||||
#define PC0_PIN PINC0
|
||||
#define PC0_RPORT PINC
|
||||
#define PC0_WPORT PORTC
|
||||
#define PC0_DDR DDRC
|
||||
#define PC0_PWM nullptr
|
||||
|
||||
#undef PC1
|
||||
#define PC1_PIN PINC1
|
||||
#define PC1_RPORT PINC
|
||||
#define PC1_WPORT PORTC
|
||||
#define PC1_DDR DDRC
|
||||
#define PC1_PWM nullptr
|
||||
|
||||
#undef PC2
|
||||
#define PC2_PIN PINC2
|
||||
#define PC2_RPORT PINC
|
||||
#define PC2_WPORT PORTC
|
||||
#define PC2_DDR DDRC
|
||||
#define PC2_PWM nullptr
|
||||
|
||||
#undef PC3
|
||||
#define PC3_PIN PINC3
|
||||
#define PC3_RPORT PINC
|
||||
#define PC3_WPORT PORTC
|
||||
#define PC3_DDR DDRC
|
||||
#define PC3_PWM nullptr
|
||||
|
||||
#undef PC4
|
||||
#define PC4_PIN PINC4
|
||||
#define PC4_RPORT PINC
|
||||
#define PC4_WPORT PORTC
|
||||
#define PC4_DDR DDRC
|
||||
#define PC4_PWM nullptr
|
||||
|
||||
#undef PC5
|
||||
#define PC5_PIN PINC5
|
||||
#define PC5_RPORT PINC
|
||||
#define PC5_WPORT PORTC
|
||||
#define PC5_DDR DDRC
|
||||
#define PC5_PWM nullptr
|
||||
|
||||
#undef PC6
|
||||
#define PC6_PIN PINC6
|
||||
#define PC6_RPORT PINC
|
||||
#define PC6_WPORT PORTC
|
||||
#define PC6_DDR DDRC
|
||||
#define PC6_PWM nullptr
|
||||
|
||||
#undef PC7
|
||||
#define PC7_PIN PINC7
|
||||
#define PC7_RPORT PINC
|
||||
#define PC7_WPORT PORTC
|
||||
#define PC7_DDR DDRC
|
||||
#define PC7_PWM nullptr
|
||||
|
||||
#undef PD0
|
||||
#define PD0_PIN PIND0
|
||||
#define PD0_RPORT PIND
|
||||
#define PD0_WPORT PORTD
|
||||
#define PD0_DDR DDRD
|
||||
#define PD0_PWM nullptr
|
||||
|
||||
#undef PD1
|
||||
#define PD1_PIN PIND1
|
||||
#define PD1_RPORT PIND
|
||||
#define PD1_WPORT PORTD
|
||||
#define PD1_DDR DDRD
|
||||
#define PD1_PWM nullptr
|
||||
|
||||
#undef PD2
|
||||
#define PD2_PIN PIND2
|
||||
#define PD2_RPORT PIND
|
||||
#define PD2_WPORT PORTD
|
||||
#define PD2_DDR DDRD
|
||||
#define PD2_PWM nullptr
|
||||
|
||||
#undef PD3
|
||||
#define PD3_PIN PIND3
|
||||
#define PD3_RPORT PIND
|
||||
#define PD3_WPORT PORTD
|
||||
#define PD3_DDR DDRD
|
||||
#define PD3_PWM nullptr
|
||||
|
||||
#undef PD4
|
||||
#define PD4_PIN PIND4
|
||||
#define PD4_RPORT PIND
|
||||
#define PD4_WPORT PORTD
|
||||
#define PD4_DDR DDRD
|
||||
#define PD4_PWM nullptr
|
||||
|
||||
#undef PD5
|
||||
#define PD5_PIN PIND5
|
||||
#define PD5_RPORT PIND
|
||||
#define PD5_WPORT PORTD
|
||||
#define PD5_DDR DDRD
|
||||
#define PD5_PWM nullptr
|
||||
|
||||
#undef PD6
|
||||
#define PD6_PIN PIND6
|
||||
#define PD6_RPORT PIND
|
||||
#define PD6_WPORT PORTD
|
||||
#define PD6_DDR DDRD
|
||||
#define PD6_PWM &OCR2B
|
||||
|
||||
#undef PD7
|
||||
#define PD7_PIN PIND7
|
||||
#define PD7_RPORT PIND
|
||||
#define PD7_WPORT PORTD
|
||||
#define PD7_DDR DDRD
|
||||
#define PD7_PWM &OCR2A
|
|
@ -0,0 +1,693 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Pin mapping (Teensy) for AT90USB646, 647, 1286, and 1287
|
||||
*
|
||||
* Logical Pin: 28 29 30 31 32 33 34 35 20 21 22 23 24 25 26 27 10 11 12 13 14 15 16 17 00 01 02 03 04 05 06 07 08 09(46*47)36 37 18 19 38 39 40 41 42 43 44 45
|
||||
* Port: A0 A1 A2 A3 A4 A5 A6 A7 B0 B1 B2 B3 B4 B5 B6 B7 C0 C1 C2 C3 C4 C5 C6 C7 D0 D1 D2 D3 D4 D5 D6 D7 E0 E1 E2 E3 E4 E5 E6 E7 F0 F1 F2 F3 F4 F5 F6 F7
|
||||
* The logical pins 46 and 47 are not supported by Teensyduino, but are supported below as E2 and E3
|
||||
*/
|
||||
|
||||
#include "../fastio.h"
|
||||
|
||||
// SPI
|
||||
#define SS 20 // 8
|
||||
#define SCK 21 // 9
|
||||
#define MOSI 22 // 10
|
||||
#define MISO 23 // 11
|
||||
|
||||
// Digital I/O
|
||||
|
||||
#define DIO0_PIN PIND0
|
||||
#define DIO0_RPORT PIND
|
||||
#define DIO0_WPORT PORTD
|
||||
#define DIO0_PWM 0
|
||||
#define DIO0_DDR DDRD
|
||||
|
||||
#define DIO1_PIN PIND1
|
||||
#define DIO1_RPORT PIND
|
||||
#define DIO1_WPORT PORTD
|
||||
#define DIO1_PWM 0
|
||||
#define DIO1_DDR DDRD
|
||||
|
||||
#define DIO2_PIN PIND2
|
||||
#define DIO2_RPORT PIND
|
||||
#define DIO2_WPORT PORTD
|
||||
#define DIO2_PWM 0
|
||||
#define DIO2_DDR DDRD
|
||||
|
||||
#define DIO3_PIN PIND3
|
||||
#define DIO3_RPORT PIND
|
||||
#define DIO3_WPORT PORTD
|
||||
#define DIO3_PWM 0
|
||||
#define DIO3_DDR DDRD
|
||||
|
||||
#define DIO4_PIN PIND4
|
||||
#define DIO4_RPORT PIND
|
||||
#define DIO4_WPORT PORTD
|
||||
#define DIO4_PWM 0
|
||||
#define DIO4_DDR DDRD
|
||||
|
||||
#define DIO5_PIN PIND5
|
||||
#define DIO5_RPORT PIND
|
||||
#define DIO5_WPORT PORTD
|
||||
#define DIO5_PWM 0
|
||||
#define DIO5_DDR DDRD
|
||||
|
||||
#define DIO6_PIN PIND6
|
||||
#define DIO6_RPORT PIND
|
||||
#define DIO6_WPORT PORTD
|
||||
#define DIO6_PWM 0
|
||||
#define DIO6_DDR DDRD
|
||||
|
||||
#define DIO7_PIN PIND7
|
||||
#define DIO7_RPORT PIND
|
||||
#define DIO7_WPORT PORTD
|
||||
#define DIO7_PWM 0
|
||||
#define DIO7_DDR DDRD
|
||||
|
||||
#define DIO8_PIN PINE0
|
||||
#define DIO8_RPORT PINE
|
||||
#define DIO8_WPORT PORTE
|
||||
#define DIO8_PWM 0
|
||||
#define DIO8_DDR DDRE
|
||||
|
||||
#define DIO9_PIN PINE1
|
||||
#define DIO9_RPORT PINE
|
||||
#define DIO9_WPORT PORTE
|
||||
#define DIO9_PWM 0
|
||||
#define DIO9_DDR DDRE
|
||||
|
||||
#define DIO10_PIN PINC0
|
||||
#define DIO10_RPORT PINC
|
||||
#define DIO10_WPORT PORTC
|
||||
#define DIO10_PWM 0
|
||||
#define DIO10_DDR DDRC
|
||||
|
||||
#define DIO11_PIN PINC1
|
||||
#define DIO11_RPORT PINC
|
||||
#define DIO11_WPORT PORTC
|
||||
#define DIO11_PWM 0
|
||||
#define DIO11_DDR DDRC
|
||||
|
||||
#define DIO12_PIN PINC2
|
||||
#define DIO12_RPORT PINC
|
||||
#define DIO12_WPORT PORTC
|
||||
#define DIO12_PWM 0
|
||||
#define DIO12_DDR DDRC
|
||||
|
||||
#define DIO13_PIN PINC3
|
||||
#define DIO13_RPORT PINC
|
||||
#define DIO13_WPORT PORTC
|
||||
#define DIO13_PWM 0
|
||||
#define DIO13_DDR DDRC
|
||||
|
||||
#define DIO14_PIN PINC4
|
||||
#define DIO14_RPORT PINC
|
||||
#define DIO14_WPORT PORTC
|
||||
#define DIO14_PWM 0 // OC3C
|
||||
#define DIO14_DDR DDRC
|
||||
|
||||
#define DIO15_PIN PINC5
|
||||
#define DIO15_RPORT PINC
|
||||
#define DIO15_WPORT PORTC
|
||||
#define DIO15_PWM 0 // OC3B
|
||||
#define DIO15_DDR DDRC
|
||||
|
||||
#define DIO16_PIN PINC6
|
||||
#define DIO16_RPORT PINC
|
||||
#define DIO16_WPORT PORTC
|
||||
#define DIO16_PWM 0 // OC3A
|
||||
#define DIO16_DDR DDRC
|
||||
|
||||
#define DIO17_PIN PINC7
|
||||
#define DIO17_RPORT PINC
|
||||
#define DIO17_WPORT PORTC
|
||||
#define DIO17_PWM 0
|
||||
#define DIO17_DDR DDRC
|
||||
|
||||
#define DIO18_PIN PINE6
|
||||
#define DIO18_RPORT PINE
|
||||
#define DIO18_WPORT PORTE
|
||||
#define DIO18_PWM 0
|
||||
#define DIO18_DDR DDRE
|
||||
|
||||
#define DIO19_PIN PINE7
|
||||
#define DIO19_RPORT PINE
|
||||
#define DIO19_WPORT PORTE
|
||||
#define DIO19_PWM 0
|
||||
#define DIO19_DDR DDRE
|
||||
|
||||
#define DIO20_PIN PINB0
|
||||
#define DIO20_RPORT PINB
|
||||
#define DIO20_WPORT PORTB
|
||||
#define DIO20_PWM 0
|
||||
#define DIO20_DDR DDRB
|
||||
|
||||
#define DIO21_PIN PINB1
|
||||
#define DIO21_RPORT PINB
|
||||
#define DIO21_WPORT PORTB
|
||||
#define DIO21_PWM 0
|
||||
#define DIO21_DDR DDRB
|
||||
|
||||
#define DIO22_PIN PINB2
|
||||
#define DIO22_RPORT PINB
|
||||
#define DIO22_WPORT PORTB
|
||||
#define DIO22_PWM 0
|
||||
#define DIO22_DDR DDRB
|
||||
|
||||
#define DIO23_PIN PINB3
|
||||
#define DIO23_RPORT PINB
|
||||
#define DIO23_WPORT PORTB
|
||||
#define DIO23_PWM 0
|
||||
#define DIO23_DDR DDRB
|
||||
|
||||
#define DIO24_PIN PINB4
|
||||
#define DIO24_RPORT PINB
|
||||
#define DIO24_WPORT PORTB
|
||||
#define DIO24_PWM 0 // OC2A
|
||||
#define DIO24_DDR DDRB
|
||||
|
||||
#define DIO25_PIN PINB5
|
||||
#define DIO25_RPORT PINB
|
||||
#define DIO25_WPORT PORTB
|
||||
#define DIO25_PWM 0 // OC1A
|
||||
#define DIO25_DDR DDRB
|
||||
|
||||
#define DIO26_PIN PINB6
|
||||
#define DIO26_RPORT PINB
|
||||
#define DIO26_WPORT PORTB
|
||||
#define DIO26_PWM 0 // OC1B
|
||||
#define DIO26_DDR DDRB
|
||||
|
||||
#define DIO27_PIN PINB7
|
||||
#define DIO27_RPORT PINB
|
||||
#define DIO27_WPORT PORTB
|
||||
#define DIO27_PWM 0 // OC1C
|
||||
#define DIO27_DDR DDRB
|
||||
|
||||
#define DIO28_PIN PINA0
|
||||
#define DIO28_RPORT PINA
|
||||
#define DIO28_WPORT PORTA
|
||||
#define DIO28_PWM 0
|
||||
#define DIO28_DDR DDRA
|
||||
|
||||
#define DIO29_PIN PINA1
|
||||
#define DIO29_RPORT PINA
|
||||
#define DIO29_WPORT PORTA
|
||||
#define DIO29_PWM 0
|
||||
#define DIO29_DDR DDRA
|
||||
|
||||
#define DIO30_PIN PINA2
|
||||
#define DIO30_RPORT PINA
|
||||
#define DIO30_WPORT PORTA
|
||||
#define DIO30_PWM 0
|
||||
#define DIO30_DDR DDRA
|
||||
|
||||
#define DIO31_PIN PINA3
|
||||
#define DIO31_RPORT PINA
|
||||
#define DIO31_WPORT PORTA
|
||||
#define DIO31_PWM 0
|
||||
#define DIO31_DDR DDRA
|
||||
|
||||
#define DIO32_PIN PINA4
|
||||
#define DIO32_RPORT PINA
|
||||
#define DIO32_WPORT PORTA
|
||||
#define DIO32_PWM 0
|
||||
#define DIO32_DDR DDRA
|
||||
|
||||
#define DIO33_PIN PINA5
|
||||
#define DIO33_RPORT PINA
|
||||
#define DIO33_WPORT PORTA
|
||||
#define DIO33_PWM 0
|
||||
#define DIO33_DDR DDRA
|
||||
|
||||
#define DIO34_PIN PINA6
|
||||
#define DIO34_RPORT PINA
|
||||
#define DIO34_WPORT PORTA
|
||||
#define DIO34_PWM 0
|
||||
#define DIO34_DDR DDRA
|
||||
|
||||
#define DIO35_PIN PINA7
|
||||
#define DIO35_RPORT PINA
|
||||
#define DIO35_WPORT PORTA
|
||||
#define DIO35_PWM 0
|
||||
#define DIO35_DDR DDRA
|
||||
|
||||
#define DIO36_PIN PINE4
|
||||
#define DIO36_RPORT PINE
|
||||
#define DIO36_WPORT PORTE
|
||||
#define DIO36_PWM 0
|
||||
#define DIO36_DDR DDRE
|
||||
|
||||
#define DIO37_PIN PINE5
|
||||
#define DIO37_RPORT PINE
|
||||
#define DIO37_WPORT PORTE
|
||||
#define DIO37_PWM 0
|
||||
#define DIO37_DDR DDRE
|
||||
|
||||
#define DIO38_PIN PINF0
|
||||
#define DIO38_RPORT PINF
|
||||
#define DIO38_WPORT PORTF
|
||||
#define DIO38_PWM 0
|
||||
#define DIO38_DDR DDRF
|
||||
|
||||
#define DIO39_PIN PINF1
|
||||
#define DIO39_RPORT PINF
|
||||
#define DIO39_WPORT PORTF
|
||||
#define DIO39_PWM 0
|
||||
#define DIO39_DDR DDRF
|
||||
|
||||
#define DIO40_PIN PINF2
|
||||
#define DIO40_RPORT PINF
|
||||
#define DIO40_WPORT PORTF
|
||||
#define DIO40_PWM 0
|
||||
#define DIO40_DDR DDRF
|
||||
|
||||
#define DIO41_PIN PINF3
|
||||
#define DIO41_RPORT PINF
|
||||
#define DIO41_WPORT PORTF
|
||||
#define DIO41_PWM 0
|
||||
#define DIO41_DDR DDRF
|
||||
|
||||
#define DIO42_PIN PINF4
|
||||
#define DIO42_RPORT PINF
|
||||
#define DIO42_WPORT PORTF
|
||||
#define DIO42_PWM 0
|
||||
#define DIO42_DDR DDRF
|
||||
|
||||
#define DIO43_PIN PINF5
|
||||
#define DIO43_RPORT PINF
|
||||
#define DIO43_WPORT PORTF
|
||||
#define DIO43_PWM 0
|
||||
#define DIO43_DDR DDRF
|
||||
|
||||
#define DIO44_PIN PINF6
|
||||
#define DIO44_RPORT PINF
|
||||
#define DIO44_WPORT PORTF
|
||||
#define DIO44_PWM 0
|
||||
#define DIO44_DDR DDRF
|
||||
|
||||
#define DIO45_PIN PINF7
|
||||
#define DIO45_RPORT PINF
|
||||
#define DIO45_WPORT PORTF
|
||||
#define DIO45_PWM 0
|
||||
#define DIO45_DDR DDRF
|
||||
|
||||
#define AIO0_PIN PINF0
|
||||
#define AIO0_RPORT PINF
|
||||
#define AIO0_WPORT PORTF
|
||||
#define AIO0_PWM 0
|
||||
#define AIO0_DDR DDRF
|
||||
|
||||
#define AIO1_PIN PINF1
|
||||
#define AIO1_RPORT PINF
|
||||
#define AIO1_WPORT PORTF
|
||||
#define AIO1_PWM 0
|
||||
#define AIO1_DDR DDRF
|
||||
|
||||
#define AIO2_PIN PINF2
|
||||
#define AIO2_RPORT PINF
|
||||
#define AIO2_WPORT PORTF
|
||||
#define AIO2_PWM 0
|
||||
#define AIO2_DDR DDRF
|
||||
|
||||
#define AIO3_PIN PINF3
|
||||
#define AIO3_RPORT PINF
|
||||
#define AIO3_WPORT PORTF
|
||||
#define AIO3_PWM 0
|
||||
#define AIO3_DDR DDRF
|
||||
|
||||
#define AIO4_PIN PINF4
|
||||
#define AIO4_RPORT PINF
|
||||
#define AIO4_WPORT PORTF
|
||||
#define AIO4_PWM 0
|
||||
#define AIO4_DDR DDRF
|
||||
|
||||
#define AIO5_PIN PINF5
|
||||
#define AIO5_RPORT PINF
|
||||
#define AIO5_WPORT PORTF
|
||||
#define AIO5_PWM 0
|
||||
#define AIO5_DDR DDRF
|
||||
|
||||
#define AIO6_PIN PINF6
|
||||
#define AIO6_RPORT PINF
|
||||
#define AIO6_WPORT PORTF
|
||||
#define AIO6_PWM 0
|
||||
#define AIO6_DDR DDRF
|
||||
|
||||
#define AIO7_PIN PINF7
|
||||
#define AIO7_RPORT PINF
|
||||
#define AIO7_WPORT PORTF
|
||||
#define AIO7_PWM 0
|
||||
#define AIO7_DDR DDRF
|
||||
|
||||
//-- Begin not supported by Teensyduino
|
||||
//-- don't use Arduino functions on these pins pinMode/digitalWrite/etc
|
||||
#define DIO46_PIN PINE2
|
||||
#define DIO46_RPORT PINE
|
||||
#define DIO46_WPORT PORTE
|
||||
#define DIO46_PWM 0
|
||||
#define DIO46_DDR DDRE
|
||||
|
||||
#define DIO47_PIN PINE3
|
||||
#define DIO47_RPORT PINE
|
||||
#define DIO47_WPORT PORTE
|
||||
#define DIO47_PWM 0
|
||||
#define DIO47_DDR DDRE
|
||||
|
||||
#define TEENSY_E2 46
|
||||
#define TEENSY_E3 47
|
||||
|
||||
//-- end not supported by Teensyduino
|
||||
|
||||
#undef PA0
|
||||
#define PA0_PIN PINA0
|
||||
#define PA0_RPORT PINA
|
||||
#define PA0_WPORT PORTA
|
||||
#define PA0_PWM 0
|
||||
#define PA0_DDR DDRA
|
||||
#undef PA1
|
||||
#define PA1_PIN PINA1
|
||||
#define PA1_RPORT PINA
|
||||
#define PA1_WPORT PORTA
|
||||
#define PA1_PWM 0
|
||||
#define PA1_DDR DDRA
|
||||
#undef PA2
|
||||
#define PA2_PIN PINA2
|
||||
#define PA2_RPORT PINA
|
||||
#define PA2_WPORT PORTA
|
||||
#define PA2_PWM 0
|
||||
#define PA2_DDR DDRA
|
||||
#undef PA3
|
||||
#define PA3_PIN PINA3
|
||||
#define PA3_RPORT PINA
|
||||
#define PA3_WPORT PORTA
|
||||
#define PA3_PWM 0
|
||||
#define PA3_DDR DDRA
|
||||
#undef PA4
|
||||
#define PA4_PIN PINA4
|
||||
#define PA4_RPORT PINA
|
||||
#define PA4_WPORT PORTA
|
||||
#define PA4_PWM 0
|
||||
#define PA4_DDR DDRA
|
||||
#undef PA5
|
||||
#define PA5_PIN PINA5
|
||||
#define PA5_RPORT PINA
|
||||
#define PA5_WPORT PORTA
|
||||
#define PA5_PWM 0
|
||||
#define PA5_DDR DDRA
|
||||
#undef PA6
|
||||
#define PA6_PIN PINA6
|
||||
#define PA6_RPORT PINA
|
||||
#define PA6_WPORT PORTA
|
||||
#define PA6_PWM 0
|
||||
#define PA6_DDR DDRA
|
||||
#undef PA7
|
||||
#define PA7_PIN PINA7
|
||||
#define PA7_RPORT PINA
|
||||
#define PA7_WPORT PORTA
|
||||
#define PA7_PWM 0
|
||||
#define PA7_DDR DDRA
|
||||
|
||||
#undef PB0
|
||||
#define PB0_PIN PINB0
|
||||
#define PB0_RPORT PINB
|
||||
#define PB0_WPORT PORTB
|
||||
#define PB0_PWM 0
|
||||
#define PB0_DDR DDRB
|
||||
#undef PB1
|
||||
#define PB1_PIN PINB1
|
||||
#define PB1_RPORT PINB
|
||||
#define PB1_WPORT PORTB
|
||||
#define PB1_PWM 0
|
||||
#define PB1_DDR DDRB
|
||||
#undef PB2
|
||||
#define PB2_PIN PINB2
|
||||
#define PB2_RPORT PINB
|
||||
#define PB2_WPORT PORTB
|
||||
#define PB2_PWM 0
|
||||
#define PB2_DDR DDRB
|
||||
#undef PB3
|
||||
#define PB3_PIN PINB3
|
||||
#define PB3_RPORT PINB
|
||||
#define PB3_WPORT PORTB
|
||||
#define PB3_PWM 0
|
||||
#define PB3_DDR DDRB
|
||||
#undef PB4
|
||||
#define PB4_PIN PINB4
|
||||
#define PB4_RPORT PINB
|
||||
#define PB4_WPORT PORTB
|
||||
#define PB4_PWM 0
|
||||
#define PB4_DDR DDRB
|
||||
#undef PB5
|
||||
#define PB5_PIN PINB5
|
||||
#define PB5_RPORT PINB
|
||||
#define PB5_WPORT PORTB
|
||||
#define PB5_PWM 0
|
||||
#define PB5_DDR DDRB
|
||||
#undef PB6
|
||||
#define PB6_PIN PINB6
|
||||
#define PB6_RPORT PINB
|
||||
#define PB6_WPORT PORTB
|
||||
#define PB6_PWM 0
|
||||
#define PB6_DDR DDRB
|
||||
#undef PB7
|
||||
#define PB7_PIN PINB7
|
||||
#define PB7_RPORT PINB
|
||||
#define PB7_WPORT PORTB
|
||||
#define PB7_PWM 0
|
||||
#define PB7_DDR DDRB
|
||||
|
||||
#undef PC0
|
||||
#define PC0_PIN PINC0
|
||||
#define PC0_RPORT PINC
|
||||
#define PC0_WPORT PORTC
|
||||
#define PC0_PWM 0
|
||||
#define PC0_DDR DDRC
|
||||
#undef PC1
|
||||
#define PC1_PIN PINC1
|
||||
#define PC1_RPORT PINC
|
||||
#define PC1_WPORT PORTC
|
||||
#define PC1_PWM 0
|
||||
#define PC1_DDR DDRC
|
||||
#undef PC2
|
||||
#define PC2_PIN PINC2
|
||||
#define PC2_RPORT PINC
|
||||
#define PC2_WPORT PORTC
|
||||
#define PC2_PWM 0
|
||||
#define PC2_DDR DDRC
|
||||
#undef PC3
|
||||
#define PC3_PIN PINC3
|
||||
#define PC3_RPORT PINC
|
||||
#define PC3_WPORT PORTC
|
||||
#define PC3_PWM 0
|
||||
#define PC3_DDR DDRC
|
||||
#undef PC4
|
||||
#define PC4_PIN PINC4
|
||||
#define PC4_RPORT PINC
|
||||
#define PC4_WPORT PORTC
|
||||
#define PC4_PWM 0
|
||||
#define PC4_DDR DDRC
|
||||
#undef PC5
|
||||
#define PC5_PIN PINC5
|
||||
#define PC5_RPORT PINC
|
||||
#define PC5_WPORT PORTC
|
||||
#define PC5_PWM 0
|
||||
#define PC5_DDR DDRC
|
||||
#undef PC6
|
||||
#define PC6_PIN PINC6
|
||||
#define PC6_RPORT PINC
|
||||
#define PC6_WPORT PORTC
|
||||
#define PC6_PWM 0
|
||||
#define PC6_DDR DDRC
|
||||
#undef PC7
|
||||
#define PC7_PIN PINC7
|
||||
#define PC7_RPORT PINC
|
||||
#define PC7_WPORT PORTC
|
||||
#define PC7_PWM 0
|
||||
#define PC7_DDR DDRC
|
||||
|
||||
#undef PD0
|
||||
#define PD0_PIN PIND0
|
||||
#define PD0_RPORT PIND
|
||||
#define PD0_WPORT PORTD
|
||||
#define PD0_PWM 0 // OC0B
|
||||
#define PD0_DDR DDRD
|
||||
#undef PD1
|
||||
#define PD1_PIN PIND1
|
||||
#define PD1_RPORT PIND
|
||||
#define PD1_WPORT PORTD
|
||||
#define PD1_PWM 0 // OC2B
|
||||
#define PD1_DDR DDRD
|
||||
#undef PD2
|
||||
#define PD2_PIN PIND2
|
||||
#define PD2_RPORT PIND
|
||||
#define PD2_WPORT PORTD
|
||||
#define PD2_PWM 0
|
||||
#define PD2_DDR DDRD
|
||||
#undef PD3
|
||||
#define PD3_PIN PIND3
|
||||
#define PD3_RPORT PIND
|
||||
#define PD3_WPORT PORTD
|
||||
#define PD3_PWM 0
|
||||
#define PD3_DDR DDRD
|
||||
#undef PD4
|
||||
#define PD4_PIN PIND4
|
||||
#define PD4_RPORT PIND
|
||||
#define PD4_WPORT PORTD
|
||||
#define PD4_PWM 0
|
||||
#define PD4_DDR DDRD
|
||||
#undef PD5
|
||||
#define PD5_PIN PIND5
|
||||
#define PD5_RPORT PIND
|
||||
#define PD5_WPORT PORTD
|
||||
#define PD5_PWM 0
|
||||
#define PD5_DDR DDRD
|
||||
#undef PD6
|
||||
#define PD6_PIN PIND6
|
||||
#define PD6_RPORT PIND
|
||||
#define PD6_WPORT PORTD
|
||||
#define PD6_PWM 0
|
||||
#define PD6_DDR DDRD
|
||||
#undef PD7
|
||||
#define PD7_PIN PIND7
|
||||
#define PD7_RPORT PIND
|
||||
#define PD7_WPORT PORTD
|
||||
#define PD7_PWM 0
|
||||
#define PD7_DDR DDRD
|
||||
|
||||
#undef PE0
|
||||
#define PE0_PIN PINE0
|
||||
#define PE0_RPORT PINE
|
||||
#define PE0_WPORT PORTE
|
||||
#define PE0_PWM 0
|
||||
#define PE0_DDR DDRE
|
||||
#undef PE1
|
||||
#define PE1_PIN PINE1
|
||||
#define PE1_RPORT PINE
|
||||
#define PE1_WPORT PORTE
|
||||
#define PE1_PWM 0
|
||||
#define PE1_DDR DDRE
|
||||
#undef PE2
|
||||
#define PE2_PIN PINE2
|
||||
#define PE2_RPORT PINE
|
||||
#define PE2_WPORT PORTE
|
||||
#define PE2_PWM 0
|
||||
#define PE2_DDR DDRE
|
||||
#undef PE3
|
||||
#define PE3_PIN PINE3
|
||||
#define PE3_RPORT PINE
|
||||
#define PE3_WPORT PORTE
|
||||
#define PE3_PWM 0
|
||||
#define PE3_DDR DDRE
|
||||
#undef PE4
|
||||
#define PE4_PIN PINE4
|
||||
#define PE4_RPORT PINE
|
||||
#define PE4_WPORT PORTE
|
||||
#define PE4_PWM 0
|
||||
#define PE4_DDR DDRE
|
||||
#undef PE5
|
||||
#define PE5_PIN PINE5
|
||||
#define PE5_RPORT PINE
|
||||
#define PE5_WPORT PORTE
|
||||
#define PE5_PWM 0
|
||||
#define PE5_DDR DDRE
|
||||
#undef PE6
|
||||
#define PE6_PIN PINE6
|
||||
#define PE6_RPORT PINE
|
||||
#define PE6_WPORT PORTE
|
||||
#define PE6_PWM 0
|
||||
#define PE6_DDR DDRE
|
||||
#undef PE7
|
||||
#define PE7_PIN PINE7
|
||||
#define PE7_RPORT PINE
|
||||
#define PE7_WPORT PORTE
|
||||
#define PE7_PWM 0
|
||||
#define PE7_DDR DDRE
|
||||
|
||||
#undef PF0
|
||||
#define PF0_PIN PINF0
|
||||
#define PF0_RPORT PINF
|
||||
#define PF0_WPORT PORTF
|
||||
#define PF0_PWM 0
|
||||
#define PF0_DDR DDRF
|
||||
#undef PF1
|
||||
#define PF1_PIN PINF1
|
||||
#define PF1_RPORT PINF
|
||||
#define PF1_WPORT PORTF
|
||||
#define PF1_PWM 0
|
||||
#define PF1_DDR DDRF
|
||||
#undef PF2
|
||||
#define PF2_PIN PINF2
|
||||
#define PF2_RPORT PINF
|
||||
#define PF2_WPORT PORTF
|
||||
#define PF2_PWM 0
|
||||
#define PF2_DDR DDRF
|
||||
#undef PF3
|
||||
#define PF3_PIN PINF3
|
||||
#define PF3_RPORT PINF
|
||||
#define PF3_WPORT PORTF
|
||||
#define PF3_PWM 0
|
||||
#define PF3_DDR DDRF
|
||||
#undef PF4
|
||||
#define PF4_PIN PINF4
|
||||
#define PF4_RPORT PINF
|
||||
#define PF4_WPORT PORTF
|
||||
#define PF4_PWM 0
|
||||
#define PF4_DDR DDRF
|
||||
#undef PF5
|
||||
#define PF5_PIN PINF5
|
||||
#define PF5_RPORT PINF
|
||||
#define PF5_WPORT PORTF
|
||||
#define PF5_PWM 0
|
||||
#define PF5_DDR DDRF
|
||||
#undef PF6
|
||||
#define PF6_PIN PINF6
|
||||
#define PF6_RPORT PINF
|
||||
#define PF6_WPORT PORTF
|
||||
#define PF6_PWM 0
|
||||
#define PF6_DDR DDRF
|
||||
#undef PF7
|
||||
#define PF7_PIN PINF7
|
||||
#define PF7_RPORT PINF
|
||||
#define PF7_WPORT PORTF
|
||||
#define PF7_PWM 0
|
||||
#define PF7_DDR DDRF
|
||||
|
||||
/**
|
||||
* Some of the pin mapping functions of the Teensduino extension to the Arduino IDE
|
||||
* do not function the same as the other Arduino extensions.
|
||||
*/
|
||||
|
||||
//digitalPinToTimer(pin) function works like Arduino but Timers are not defined
|
||||
#define TIMER0B 1
|
||||
#define TIMER1A 7
|
||||
#define TIMER1B 8
|
||||
#define TIMER1C 9
|
||||
#define TIMER2A 6
|
||||
#define TIMER2B 2
|
||||
#define TIMER3A 5
|
||||
#define TIMER3B 4
|
||||
#define TIMER3C 3
|
|
@ -0,0 +1,26 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#ifndef SERIAL_PORT
|
||||
#define SERIAL_PORT 0
|
||||
#endif
|
|
@ -0,0 +1,22 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
|
@ -0,0 +1,22 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
|
@ -0,0 +1,115 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Test AVR-specific configuration values for errors at compile-time.
|
||||
*/
|
||||
|
||||
#if HAS_SPI_TFT || HAS_FSMC_TFT
|
||||
#error "Sorry! TFT displays are not available for HAL/AVR."
|
||||
#endif
|
||||
|
||||
/**
|
||||
* 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 || LCD_PINS_EN == 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
|
||||
*/
|
||||
#if ALL(FAST_PWM_FAN, USE_OCR2A_AS_TOP, HAS_TCCR2)
|
||||
#error "USE_OCR2A_AS_TOP does not apply to devices with a single output TIMER2."
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Checks for SOFT PWM
|
||||
*/
|
||||
#if HAS_FAN0 && FAN0_PIN == 9 && DISABLED(FAN_SOFT_PWM) && ENABLED(SPEAKER)
|
||||
#error "FAN0_PIN 9 Hardware PWM uses Timer 2 which conflicts with Arduino AVR Tone Timer (for SPEAKER)."
|
||||
#error "Disable SPEAKER or enable FAN_SOFT_PWM."
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Sanity checks for Spindle / Laser PWM
|
||||
*/
|
||||
#if ENABLED(SPINDLE_LASER_USE_PWM)
|
||||
#include "../ServoTimers.h" // Needed to check timer availability (_useTimer3)
|
||||
#if SPINDLE_LASER_PWM_PIN == 4 || WITHIN(SPINDLE_LASER_PWM_PIN, 11, 13)
|
||||
#error "Counter/Timer for SPINDLE_LASER_PWM_PIN is used by a system interrupt."
|
||||
#elif NUM_SERVOS > 0 && defined(_useTimer3) && (WITHIN(SPINDLE_LASER_PWM_PIN, 2, 3) || SPINDLE_LASER_PWM_PIN == 5)
|
||||
#error "Counter/Timer for SPINDLE_LASER_PWM_PIN is used by the servo system."
|
||||
#endif
|
||||
#elif SPINDLE_LASER_FREQUENCY
|
||||
#error "SPINDLE_LASER_FREQUENCY requires SPINDLE_LASER_USE_PWM."
|
||||
#endif
|
||||
|
||||
/**
|
||||
* The Trinamic library includes SoftwareSerial.h, leading to a compile error.
|
||||
*/
|
||||
#if ALL(HAS_TRINAMIC_CONFIG, ENDSTOP_INTERRUPTS_FEATURE)
|
||||
#error "TMCStepper includes SoftwareSerial.h which is incompatible with ENDSTOP_INTERRUPTS_FEATURE. Disable ENDSTOP_INTERRUPTS_FEATURE to continue."
|
||||
#endif
|
||||
|
||||
#if ALL(HAS_TMC_SW_SERIAL, MONITOR_DRIVER_STATUS)
|
||||
#error "MONITOR_DRIVER_STATUS causes performance issues when used with SoftwareSerial-connected drivers. Disable MONITOR_DRIVER_STATUS or use hardware serial to continue."
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Postmortem debugging
|
||||
*/
|
||||
#if ENABLED(POSTMORTEM_DEBUGGING)
|
||||
#error "POSTMORTEM_DEBUGGING is not supported on AVR boards."
|
||||
#endif
|
||||
|
||||
#if USING_PULLDOWNS
|
||||
#error "PULLDOWN pin mode is not available on AVR boards."
|
||||
#endif
|
|
@ -0,0 +1,115 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Optimized math functions for AVR
|
||||
*/
|
||||
|
||||
// intRes = longIn1 * longIn2 >> 24
|
||||
// uses:
|
||||
// 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;
|
||||
uint8_t tmp2;
|
||||
uint16_t intRes;
|
||||
__asm__ __volatile__(
|
||||
A("clr %[tmp1]")
|
||||
A("mul %A[longIn1], %B[longIn2]")
|
||||
A("mov %[tmp2], r1")
|
||||
A("mul %B[longIn1], %C[longIn2]")
|
||||
A("movw %A[intRes], r0")
|
||||
A("mul %C[longIn1], %C[longIn2]")
|
||||
A("add %B[intRes], r0")
|
||||
A("mul %C[longIn1], %B[longIn2]")
|
||||
A("add %A[intRes], r0")
|
||||
A("adc %B[intRes], r1")
|
||||
A("mul %A[longIn1], %C[longIn2]")
|
||||
A("add %[tmp2], r0")
|
||||
A("adc %A[intRes], r1")
|
||||
A("adc %B[intRes], %[tmp1]")
|
||||
A("mul %B[longIn1], %B[longIn2]")
|
||||
A("add %[tmp2], r0")
|
||||
A("adc %A[intRes], r1")
|
||||
A("adc %B[intRes], %[tmp1]")
|
||||
A("mul %C[longIn1], %A[longIn2]")
|
||||
A("add %[tmp2], r0")
|
||||
A("adc %A[intRes], r1")
|
||||
A("adc %B[intRes], %[tmp1]")
|
||||
A("mul %B[longIn1], %A[longIn2]")
|
||||
A("add %[tmp2], r1")
|
||||
A("adc %A[intRes], %[tmp1]")
|
||||
A("adc %B[intRes], %[tmp1]")
|
||||
A("mul %D[longIn2], %A[longIn1]")
|
||||
A("lsl %[tmp2]")
|
||||
A("adc %A[intRes], r0")
|
||||
A("adc %B[intRes], r1")
|
||||
A("mul %D[longIn2], %B[longIn1]")
|
||||
A("add %B[intRes], r0")
|
||||
A("clr r1")
|
||||
: [intRes] "=&r" (intRes),
|
||||
[tmp1] "=&r" (tmp1),
|
||||
[tmp2] "=&r" (tmp2)
|
||||
: [longIn1] "d" (longIn1),
|
||||
[longIn2] "d" (longIn2)
|
||||
: "cc"
|
||||
);
|
||||
return intRes;
|
||||
}
|
||||
|
||||
// intRes = intIn1 * intIn2 >> 8
|
||||
// uses:
|
||||
// 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__ (
|
||||
A("clr %[tmp]")
|
||||
A("mul %[charIn1], %B[intIn2]")
|
||||
A("movw %A[intRes], r0")
|
||||
A("mul %[charIn1], %A[intIn2]")
|
||||
A("lsl r0")
|
||||
A("adc %A[intRes], r1")
|
||||
A("adc %B[intRes], %[tmp]")
|
||||
A("clr r1")
|
||||
: [intRes] "=&r" (intRes),
|
||||
[tmp] "=&r" (tmp)
|
||||
: [charIn1] "d" (charIn1),
|
||||
[intIn2] "d" (intIn2)
|
||||
: "cc"
|
||||
);
|
||||
return intRes;
|
||||
}
|
|
@ -0,0 +1,392 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* PWM print routines for Atmel 8 bit AVR CPUs
|
||||
*/
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#define NUMBER_PINS_TOTAL NUM_DIGITAL_PINS
|
||||
|
||||
#if MB(BQ_ZUM_MEGA_3D, MIGHTYBOARD_REVE, MINIRAMBO, SCOOVO_X9H, TRIGORILLA_14)
|
||||
#define AVR_ATmega2560_FAMILY_PLUS_70 1
|
||||
#endif
|
||||
|
||||
#if AVR_AT90USB1286_FAMILY
|
||||
|
||||
// Working with Teensyduino extension so need to re-define some things
|
||||
#include "pinsDebug_Teensyduino.h"
|
||||
// Can't use the "digitalPinToPort" function from the Teensyduino type IDEs
|
||||
// portModeRegister takes a different argument
|
||||
#define digitalPinToTimer_DEBUG(p) digitalPinToTimer(p)
|
||||
#define digitalPinToBitMask_DEBUG(p) digitalPinToBitMask(p)
|
||||
#define digitalPinToPort_DEBUG(p) digitalPinToPort(p)
|
||||
#define GET_PINMODE(pin) (*portModeRegister(pin) & digitalPinToBitMask_DEBUG(pin))
|
||||
|
||||
#elif AVR_ATmega2560_FAMILY_PLUS_70 // So we can access/display all the pins on boards using more than 70
|
||||
|
||||
#include "pinsDebug_plus_70.h"
|
||||
#define digitalPinToTimer_DEBUG(p) digitalPinToTimer_plus_70(p)
|
||||
#define digitalPinToBitMask_DEBUG(p) digitalPinToBitMask_plus_70(p)
|
||||
#define digitalPinToPort_DEBUG(p) digitalPinToPort_plus_70(p)
|
||||
bool GET_PINMODE(int8_t pin) {return *portModeRegister(digitalPinToPort_DEBUG(pin)) & digitalPinToBitMask_DEBUG(pin); }
|
||||
|
||||
#else
|
||||
|
||||
#define digitalPinToTimer_DEBUG(p) digitalPinToTimer(p)
|
||||
#define digitalPinToBitMask_DEBUG(p) digitalPinToBitMask(p)
|
||||
#define digitalPinToPort_DEBUG(p) digitalPinToPort(p)
|
||||
bool GET_PINMODE(int8_t pin) {return *portModeRegister(digitalPinToPort_DEBUG(pin)) & digitalPinToBitMask_DEBUG(pin); }
|
||||
#define GET_ARRAY_PIN(p) pgm_read_byte(&pin_array[p].pin)
|
||||
|
||||
#endif
|
||||
|
||||
#define VALID_PIN(pin) (pin >= 0 && pin < NUM_DIGITAL_PINS ? 1 : 0)
|
||||
#if AVR_ATmega1284_FAMILY
|
||||
#define IS_ANALOG(P) WITHIN(P, analogInputToDigitalPin(7), analogInputToDigitalPin(0))
|
||||
#define DIGITAL_PIN_TO_ANALOG_PIN(P) int(IS_ANALOG(P) ? (P) - analogInputToDigitalPin(7) : -1)
|
||||
#else
|
||||
#define _ANALOG1(P) WITHIN(P, analogInputToDigitalPin(0), analogInputToDigitalPin(7))
|
||||
#define _ANALOG2(P) WITHIN(P, analogInputToDigitalPin(8), analogInputToDigitalPin(15))
|
||||
#define IS_ANALOG(P) (_ANALOG1(P) || _ANALOG2(P))
|
||||
#define DIGITAL_PIN_TO_ANALOG_PIN(P) int(_ANALOG1(P) ? (P) - analogInputToDigitalPin(0) : _ANALOG2(P) ? (P) - analogInputToDigitalPin(8) + 8 : -1)
|
||||
#endif
|
||||
#define GET_ARRAY_PIN(p) pgm_read_byte(&pin_array[p].pin)
|
||||
#define MULTI_NAME_PAD 26 // space needed to be pretty if not first name assigned to a pin
|
||||
|
||||
void PRINT_ARRAY_NAME(uint8_t x) {
|
||||
PGM_P const name_mem_pointer = (PGM_P)pgm_read_ptr(&pin_array[x].name);
|
||||
for (uint8_t y = 0; y < MAX_NAME_LENGTH; ++y) {
|
||||
char temp_char = pgm_read_byte(name_mem_pointer + y);
|
||||
if (temp_char != 0)
|
||||
SERIAL_CHAR(temp_char);
|
||||
else {
|
||||
for (uint8_t i = 0; i < MAX_NAME_LENGTH - y; ++i) SERIAL_CHAR(' ');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define GET_ARRAY_IS_DIGITAL(x) pgm_read_byte(&pin_array[x].is_digital)
|
||||
|
||||
#if defined(__AVR_ATmega1284P__) // 1284 IDE extensions set this to the number of
|
||||
#undef NUM_DIGITAL_PINS // digital only pins while all other CPUs have it
|
||||
#define NUM_DIGITAL_PINS 32 // set to digital only + digital/analog
|
||||
#endif
|
||||
|
||||
#define PWM_PRINT(V) do{ sprintf_P(buffer, PSTR("PWM: %4d"), V); SERIAL_ECHO(buffer); }while(0)
|
||||
#define PWM_CASE(N,Z) \
|
||||
case TIMER##N##Z: \
|
||||
if (TCCR##N##A & (_BV(COM##N##Z##1) | _BV(COM##N##Z##0))) { \
|
||||
PWM_PRINT(OCR##N##Z); \
|
||||
return true; \
|
||||
} else return false
|
||||
|
||||
#define ABTEST(N) defined(TCCR##N##A) && defined(COM##N##A1)
|
||||
|
||||
/**
|
||||
* Print a pin's PWM status.
|
||||
* Return true if it's currently a PWM pin.
|
||||
*/
|
||||
bool pwm_status(uint8_t pin) {
|
||||
char buffer[20]; // for the sprintf statements
|
||||
|
||||
switch (digitalPinToTimer_DEBUG(pin)) {
|
||||
|
||||
#if ABTEST(0)
|
||||
#ifdef TIMER0A
|
||||
#if !AVR_AT90USB1286_FAMILY // not available in Teensyduino type IDEs
|
||||
PWM_CASE(0, A);
|
||||
#endif
|
||||
#endif
|
||||
PWM_CASE(0, B);
|
||||
#endif
|
||||
|
||||
#if ABTEST(1)
|
||||
PWM_CASE(1, A);
|
||||
PWM_CASE(1, B);
|
||||
#if defined(COM1C1) && defined(TIMER1C)
|
||||
PWM_CASE(1, C);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ABTEST(2)
|
||||
PWM_CASE(2, A);
|
||||
PWM_CASE(2, B);
|
||||
#endif
|
||||
|
||||
#if ABTEST(3)
|
||||
PWM_CASE(3, A);
|
||||
PWM_CASE(3, B);
|
||||
#ifdef COM3C1
|
||||
PWM_CASE(3, C);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef TCCR4A
|
||||
PWM_CASE(4, A);
|
||||
PWM_CASE(4, B);
|
||||
PWM_CASE(4, C);
|
||||
#endif
|
||||
|
||||
#if ABTEST(5)
|
||||
PWM_CASE(5, A);
|
||||
PWM_CASE(5, B);
|
||||
PWM_CASE(5, C);
|
||||
#endif
|
||||
|
||||
case NOT_ON_TIMER:
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
SERIAL_ECHO_SP(2);
|
||||
} // pwm_status
|
||||
|
||||
const volatile uint8_t* const PWM_other[][3] PROGMEM = {
|
||||
{ &TCCR0A, &TCCR0B, &TIMSK0 },
|
||||
{ &TCCR1A, &TCCR1B, &TIMSK1 },
|
||||
#if ABTEST(2)
|
||||
{ &TCCR2A, &TCCR2B, &TIMSK2 },
|
||||
#endif
|
||||
#if ABTEST(3)
|
||||
{ &TCCR3A, &TCCR3B, &TIMSK3 },
|
||||
#endif
|
||||
#ifdef TCCR4A
|
||||
{ &TCCR4A, &TCCR4B, &TIMSK4 },
|
||||
#endif
|
||||
#if ABTEST(5)
|
||||
{ &TCCR5A, &TCCR5B, &TIMSK5 },
|
||||
#endif
|
||||
};
|
||||
|
||||
const volatile uint8_t* const PWM_OCR[][3] PROGMEM = {
|
||||
|
||||
#ifdef TIMER0A
|
||||
{ &OCR0A, &OCR0B, 0 },
|
||||
#else
|
||||
{ 0, &OCR0B, 0 },
|
||||
#endif
|
||||
|
||||
#if defined(COM1C1) && defined(TIMER1C)
|
||||
{ (const uint8_t*)&OCR1A, (const uint8_t*)&OCR1B, (const uint8_t*)&OCR1C },
|
||||
#else
|
||||
{ (const uint8_t*)&OCR1A, (const uint8_t*)&OCR1B, 0 },
|
||||
#endif
|
||||
|
||||
#if ABTEST(2)
|
||||
{ &OCR2A, &OCR2B, 0 },
|
||||
#endif
|
||||
|
||||
#if ABTEST(3)
|
||||
#ifdef COM3C1
|
||||
{ (const uint8_t*)&OCR3A, (const uint8_t*)&OCR3B, (const uint8_t*)&OCR3C },
|
||||
#else
|
||||
{ (const uint8_t*)&OCR3A, (const uint8_t*)&OCR3B, 0 },
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef TCCR4A
|
||||
{ (const uint8_t*)&OCR4A, (const uint8_t*)&OCR4B, (const uint8_t*)&OCR4C },
|
||||
#endif
|
||||
|
||||
#if ABTEST(5)
|
||||
{ (const uint8_t*)&OCR5A, (const uint8_t*)&OCR5B, (const uint8_t*)&OCR5C },
|
||||
#endif
|
||||
};
|
||||
|
||||
#define TCCR_A(T) pgm_read_word(&PWM_other[T][0])
|
||||
#define TCCR_B(T) pgm_read_word(&PWM_other[T][1])
|
||||
#define TIMSK(T) pgm_read_word(&PWM_other[T][2])
|
||||
#define CS_0 0
|
||||
#define CS_1 1
|
||||
#define CS_2 2
|
||||
#define WGM_0 0
|
||||
#define WGM_1 1
|
||||
#define WGM_2 3
|
||||
#define WGM_3 4
|
||||
#define TOIE 0
|
||||
|
||||
#define OCR_VAL(T, L) pgm_read_word(&PWM_OCR[T][L])
|
||||
|
||||
void err_is_counter() { SERIAL_ECHOPGM(" non-standard PWM mode"); }
|
||||
void err_is_interrupt() { SERIAL_ECHOPGM(" compare interrupt enabled"); }
|
||||
void err_prob_interrupt() { SERIAL_ECHOPGM(" overflow interrupt enabled"); }
|
||||
void print_is_also_tied() { SERIAL_ECHOPGM(" is also tied to this pin"); SERIAL_ECHO_SP(14); }
|
||||
|
||||
void com_print(const uint8_t N, const uint8_t Z) {
|
||||
const uint8_t *TCCRA = (uint8_t*)TCCR_A(N);
|
||||
SERIAL_ECHOPGM(" COM", AS_DIGIT(N));
|
||||
SERIAL_CHAR(Z);
|
||||
SERIAL_ECHOPGM(": ", int((*TCCRA >> (6 - Z * 2)) & 0x03));
|
||||
}
|
||||
|
||||
void timer_prefix(uint8_t T, char L, uint8_t N) { // T - timer L - pwm N - WGM bit layout
|
||||
char buffer[20]; // for the sprintf statements
|
||||
const uint8_t *TCCRB = (uint8_t*)TCCR_B(T),
|
||||
*TCCRA = (uint8_t*)TCCR_A(T);
|
||||
uint8_t WGM = (((*TCCRB & _BV(WGM_2)) >> 1) | (*TCCRA & (_BV(WGM_0) | _BV(WGM_1))));
|
||||
if (N == 4) WGM |= ((*TCCRB & _BV(WGM_3)) >> 1);
|
||||
|
||||
SERIAL_ECHOPGM(" TIMER", AS_DIGIT(T));
|
||||
SERIAL_CHAR(L);
|
||||
SERIAL_ECHO_SP(3);
|
||||
|
||||
if (N == 3) {
|
||||
const uint8_t *OCRVAL8 = (uint8_t*)OCR_VAL(T, L - 'A');
|
||||
PWM_PRINT(*OCRVAL8);
|
||||
}
|
||||
else {
|
||||
const uint16_t *OCRVAL16 = (uint16_t*)OCR_VAL(T, L - 'A');
|
||||
PWM_PRINT(*OCRVAL16);
|
||||
}
|
||||
SERIAL_ECHOPGM(" WGM: ", WGM);
|
||||
com_print(T,L);
|
||||
SERIAL_ECHOPGM(" CS: ", (*TCCRB & (_BV(CS_0) | _BV(CS_1) | _BV(CS_2)) ));
|
||||
SERIAL_ECHOPGM(" TCCR", AS_DIGIT(T), "A: ", *TCCRA);
|
||||
SERIAL_ECHOPGM(" TCCR", AS_DIGIT(T), "B: ", *TCCRB);
|
||||
|
||||
const uint8_t *TMSK = (uint8_t*)TIMSK(T);
|
||||
SERIAL_ECHOPGM(" TIMSK", AS_DIGIT(T), ": ", *TMSK);
|
||||
|
||||
const uint8_t OCIE = L - 'A' + 1;
|
||||
if (N == 3) { if (WGM == 0 || WGM == 2 || WGM == 4 || WGM == 6) err_is_counter(); }
|
||||
else { if (WGM == 0 || WGM == 4 || WGM == 12 || WGM == 13) err_is_counter(); }
|
||||
if (TEST(*TMSK, OCIE)) err_is_interrupt();
|
||||
if (TEST(*TMSK, TOIE)) err_prob_interrupt();
|
||||
}
|
||||
|
||||
void pwm_details(uint8_t pin) {
|
||||
switch (digitalPinToTimer_DEBUG(pin)) {
|
||||
|
||||
#if ABTEST(0)
|
||||
#ifdef TIMER0A
|
||||
#if !AVR_AT90USB1286_FAMILY // not available in Teensyduino type IDEs
|
||||
case TIMER0A: timer_prefix(0, 'A', 3); break;
|
||||
#endif
|
||||
#endif
|
||||
case TIMER0B: timer_prefix(0, 'B', 3); break;
|
||||
#endif
|
||||
|
||||
#if ABTEST(1)
|
||||
case TIMER1A: timer_prefix(1, 'A', 4); break;
|
||||
case TIMER1B: timer_prefix(1, 'B', 4); break;
|
||||
#if defined(COM1C1) && defined(TIMER1C)
|
||||
case TIMER1C: timer_prefix(1, 'C', 4); break;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ABTEST(2)
|
||||
case TIMER2A: timer_prefix(2, 'A', 3); break;
|
||||
case TIMER2B: timer_prefix(2, 'B', 3); break;
|
||||
#endif
|
||||
|
||||
#if ABTEST(3)
|
||||
case TIMER3A: timer_prefix(3, 'A', 4); break;
|
||||
case TIMER3B: timer_prefix(3, 'B', 4); break;
|
||||
#ifdef COM3C1
|
||||
case TIMER3C: timer_prefix(3, 'C', 4); break;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef TCCR4A
|
||||
case TIMER4A: timer_prefix(4, 'A', 4); break;
|
||||
case TIMER4B: timer_prefix(4, 'B', 4); break;
|
||||
case TIMER4C: timer_prefix(4, 'C', 4); break;
|
||||
#endif
|
||||
|
||||
#if ABTEST(5)
|
||||
case TIMER5A: timer_prefix(5, 'A', 4); break;
|
||||
case TIMER5B: timer_prefix(5, 'B', 4); break;
|
||||
case TIMER5C: timer_prefix(5, 'C', 4); break;
|
||||
#endif
|
||||
|
||||
case NOT_ON_TIMER: break;
|
||||
|
||||
}
|
||||
SERIAL_ECHOPGM(" ");
|
||||
|
||||
// on pins that have two PWMs, print info on second PWM
|
||||
#if AVR_ATmega2560_FAMILY || AVR_AT90USB1286_FAMILY
|
||||
// looking for port B7 - PWMs 0A and 1C
|
||||
if (digitalPinToPort_DEBUG(pin) == 'B' - 64 && 0x80 == digitalPinToBitMask_DEBUG(pin)) {
|
||||
#if !AVR_AT90USB1286_FAMILY
|
||||
SERIAL_ECHOPGM("\n .");
|
||||
SERIAL_ECHO_SP(18);
|
||||
SERIAL_ECHOPGM("TIMER1C");
|
||||
print_is_also_tied();
|
||||
timer_prefix(1, 'C', 4);
|
||||
#else
|
||||
SERIAL_ECHOPGM("\n .");
|
||||
SERIAL_ECHO_SP(18);
|
||||
SERIAL_ECHOPGM("TIMER0A");
|
||||
print_is_also_tied();
|
||||
timer_prefix(0, 'A', 3);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
UNUSED(print_is_also_tied);
|
||||
#endif
|
||||
} // pwm_details
|
||||
|
||||
#ifndef digitalRead_mod // Use Teensyduino's version of digitalRead - it doesn't disable the PWMs
|
||||
int digitalRead_mod(const pin_t pin) { // same as digitalRead except the PWM stop section has been removed
|
||||
const uint8_t port = digitalPinToPort_DEBUG(pin);
|
||||
return (port != NOT_A_PIN) && (*portInputRegister(port) & digitalPinToBitMask_DEBUG(pin)) ? HIGH : LOW;
|
||||
}
|
||||
#endif
|
||||
|
||||
void print_port(const pin_t pin) { // print port number
|
||||
#ifdef digitalPinToPort_DEBUG
|
||||
uint8_t x;
|
||||
SERIAL_ECHOPGM(" Port: ");
|
||||
#if AVR_AT90USB1286_FAMILY
|
||||
x = (pin == 46 || pin == 47) ? 'E' : digitalPinToPort_DEBUG(pin) + 64;
|
||||
#else
|
||||
x = digitalPinToPort_DEBUG(pin) + 64;
|
||||
#endif
|
||||
SERIAL_CHAR(x);
|
||||
|
||||
#if AVR_AT90USB1286_FAMILY
|
||||
if (pin == 46)
|
||||
x = '2';
|
||||
else if (pin == 47)
|
||||
x = '3';
|
||||
else {
|
||||
uint8_t temp = digitalPinToBitMask_DEBUG(pin);
|
||||
for (x = '0'; x < '9' && temp != 1; x++) temp >>= 1;
|
||||
}
|
||||
#else
|
||||
uint8_t temp = digitalPinToBitMask_DEBUG(pin);
|
||||
for (x = '0'; x < '9' && temp != 1; x++) temp >>= 1;
|
||||
#endif
|
||||
SERIAL_CHAR(x);
|
||||
#else
|
||||
SERIAL_ECHO_SP(10);
|
||||
#endif
|
||||
}
|
||||
|
||||
#define PRINT_PIN(p) do{ sprintf_P(buffer, PSTR("%3d "), p); SERIAL_ECHO(buffer); }while(0)
|
||||
#define PRINT_PIN_ANALOG(p) do{ sprintf_P(buffer, PSTR(" (A%2d) "), DIGITAL_PIN_TO_ANALOG_PIN(pin)); SERIAL_ECHO(buffer); }while(0)
|
||||
|
||||
#undef ABTEST
|
|
@ -0,0 +1,108 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
//
|
||||
// Some of the pin mapping functions of the Arduino IDE Teensduino extension
|
||||
// function differently from other Arduino extensions.
|
||||
//
|
||||
|
||||
#define TEENSYDUINO_IDE
|
||||
|
||||
//digitalPinToTimer(pin) function works like Arduino but Timers are not defined
|
||||
#define TIMER0B 1
|
||||
#define TIMER1A 7
|
||||
#define TIMER1B 8
|
||||
#define TIMER1C 9
|
||||
#define TIMER2A 6
|
||||
#define TIMER2B 2
|
||||
#define TIMER3A 5
|
||||
#define TIMER3B 4
|
||||
#define TIMER3C 3
|
||||
|
||||
// digitalPinToPort function just returns the pin number so need to create our own
|
||||
#define PA 1
|
||||
#define PB 2
|
||||
#define PC 3
|
||||
#define PD 4
|
||||
#define PE 5
|
||||
#define PF 6
|
||||
|
||||
const uint8_t PROGMEM digital_pin_to_port_PGM[] = {
|
||||
PD, // 0 - PD0 - INT0 - PWM
|
||||
PD, // 1 - PD1 - INT1 - PWM
|
||||
PD, // 2 - PD2 - INT2 - RX
|
||||
PD, // 3 - PD3 - INT3 - TX
|
||||
PD, // 4 - PD4
|
||||
PD, // 5 - PD5
|
||||
PD, // 6 - PD6
|
||||
PD, // 7 - PD7
|
||||
PE, // 8 - PE0
|
||||
PE, // 9 - PE1
|
||||
PC, // 10 - PC0
|
||||
PC, // 11 - PC1
|
||||
PC, // 12 - PC2
|
||||
PC, // 13 - PC3
|
||||
PC, // 14 - PC4 - PWM
|
||||
PC, // 15 - PC5 - PWM
|
||||
PC, // 16 - PC6 - PWM
|
||||
PC, // 17 - PC7
|
||||
PE, // 18 - PE6 - INT6
|
||||
PE, // 19 - PE7 - INT7
|
||||
PB, // 20 - PB0
|
||||
PB, // 21 - PB1
|
||||
PB, // 22 - PB2
|
||||
PB, // 23 - PB3
|
||||
PB, // 24 - PB4 - PWM
|
||||
PB, // 25 - PB5 - PWM
|
||||
PB, // 26 - PB6 - PWM
|
||||
PB, // 27 - PB7 - PWM
|
||||
PA, // 28 - PA0
|
||||
PA, // 29 - PA1
|
||||
PA, // 30 - PA2
|
||||
PA, // 31 - PA3
|
||||
PA, // 32 - PA4
|
||||
PA, // 33 - PA5
|
||||
PA, // 34 - PA6
|
||||
PA, // 35 - PA7
|
||||
PE, // 36 - PE4 - INT4
|
||||
PE, // 37 - PE5 - INT5
|
||||
PF, // 38 - PF0 - A0
|
||||
PF, // 39 - PF1 - A1
|
||||
PF, // 40 - PF2 - A2
|
||||
PF, // 41 - PF3 - A3
|
||||
PF, // 42 - PF4 - A4
|
||||
PF, // 43 - PF5 - A5
|
||||
PF, // 44 - PF6 - A6
|
||||
PF, // 45 - PF7 - A7
|
||||
PE, // 46 - PE2 (not defined in teensyduino)
|
||||
PE, // 47 - PE3 (not defined in teensyduino)
|
||||
};
|
||||
|
||||
#define digitalPinToPort(P) pgm_read_byte(digital_pin_to_port_PGM[P])
|
||||
|
||||
// digitalPinToBitMask(pin) is OK
|
||||
|
||||
#define digitalRead_mod(p) extDigitalRead(p) // Teensyduino's version of digitalRead doesn't
|
||||
// disable the PWMs so we can use it as is
|
||||
|
||||
// portModeRegister(pin) is OK
|
|
@ -0,0 +1,331 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Structures for 2560 family boards that use more than 70 pins
|
||||
*/
|
||||
|
||||
#if MB(BQ_ZUM_MEGA_3D, MINIRAMBO, SCOOVO_X9H, TRIGORILLA_14)
|
||||
#undef NUM_DIGITAL_PINS
|
||||
#define NUM_DIGITAL_PINS 85
|
||||
#elif MB(MIGHTYBOARD_REVE)
|
||||
#undef NUM_DIGITAL_PINS
|
||||
#define NUM_DIGITAL_PINS 80
|
||||
#endif
|
||||
|
||||
#define PA 1
|
||||
#define PB 2
|
||||
#define PC 3
|
||||
#define PD 4
|
||||
#define PE 5
|
||||
#define PF 6
|
||||
#define PG 7
|
||||
#define PH 8
|
||||
#define PJ 10
|
||||
#define PK 11
|
||||
#define PL 12
|
||||
|
||||
const uint8_t PROGMEM digital_pin_to_port_PGM_plus_70[] = {
|
||||
// PORTLIST
|
||||
// ------------------------
|
||||
PE , // PE 0 ** 0 ** USART0_RX
|
||||
PE , // PE 1 ** 1 ** USART0_TX
|
||||
PE , // PE 4 ** 2 ** PWM2
|
||||
PE , // PE 5 ** 3 ** PWM3
|
||||
PG , // PG 5 ** 4 ** PWM4
|
||||
PE , // PE 3 ** 5 ** PWM5
|
||||
PH , // PH 3 ** 6 ** PWM6
|
||||
PH , // PH 4 ** 7 ** PWM7
|
||||
PH , // PH 5 ** 8 ** PWM8
|
||||
PH , // PH 6 ** 9 ** PWM9
|
||||
PB , // PB 4 ** 10 ** PWM10
|
||||
PB , // PB 5 ** 11 ** PWM11
|
||||
PB , // PB 6 ** 12 ** PWM12
|
||||
PB , // PB 7 ** 13 ** PWM13
|
||||
PJ , // PJ 1 ** 14 ** USART3_TX
|
||||
PJ , // PJ 0 ** 15 ** USART3_RX
|
||||
PH , // PH 1 ** 16 ** USART2_TX
|
||||
PH , // PH 0 ** 17 ** USART2_RX
|
||||
PD , // PD 3 ** 18 ** USART1_TX
|
||||
PD , // PD 2 ** 19 ** USART1_RX
|
||||
PD , // PD 1 ** 20 ** I2C_SDA
|
||||
PD , // PD 0 ** 21 ** I2C_SCL
|
||||
PA , // PA 0 ** 22 ** D22
|
||||
PA , // PA 1 ** 23 ** D23
|
||||
PA , // PA 2 ** 24 ** D24
|
||||
PA , // PA 3 ** 25 ** D25
|
||||
PA , // PA 4 ** 26 ** D26
|
||||
PA , // PA 5 ** 27 ** D27
|
||||
PA , // PA 6 ** 28 ** D28
|
||||
PA , // PA 7 ** 29 ** D29
|
||||
PC , // PC 7 ** 30 ** D30
|
||||
PC , // PC 6 ** 31 ** D31
|
||||
PC , // PC 5 ** 32 ** D32
|
||||
PC , // PC 4 ** 33 ** D33
|
||||
PC , // PC 3 ** 34 ** D34
|
||||
PC , // PC 2 ** 35 ** D35
|
||||
PC , // PC 1 ** 36 ** D36
|
||||
PC , // PC 0 ** 37 ** D37
|
||||
PD , // PD 7 ** 38 ** D38
|
||||
PG , // PG 2 ** 39 ** D39
|
||||
PG , // PG 1 ** 40 ** D40
|
||||
PG , // PG 0 ** 41 ** D41
|
||||
PL , // PL 7 ** 42 ** D42
|
||||
PL , // PL 6 ** 43 ** D43
|
||||
PL , // PL 5 ** 44 ** D44
|
||||
PL , // PL 4 ** 45 ** D45
|
||||
PL , // PL 3 ** 46 ** D46
|
||||
PL , // PL 2 ** 47 ** D47
|
||||
PL , // PL 1 ** 48 ** D48
|
||||
PL , // PL 0 ** 49 ** D49
|
||||
PB , // PB 3 ** 50 ** SPI_MISO
|
||||
PB , // PB 2 ** 51 ** SPI_MOSI
|
||||
PB , // PB 1 ** 52 ** SPI_SCK
|
||||
PB , // PB 0 ** 53 ** SPI_SS
|
||||
PF , // PF 0 ** 54 ** A0
|
||||
PF , // PF 1 ** 55 ** A1
|
||||
PF , // PF 2 ** 56 ** A2
|
||||
PF , // PF 3 ** 57 ** A3
|
||||
PF , // PF 4 ** 58 ** A4
|
||||
PF , // PF 5 ** 59 ** A5
|
||||
PF , // PF 6 ** 60 ** A6
|
||||
PF , // PF 7 ** 61 ** A7
|
||||
PK , // PK 0 ** 62 ** A8
|
||||
PK , // PK 1 ** 63 ** A9
|
||||
PK , // PK 2 ** 64 ** A10
|
||||
PK , // PK 3 ** 65 ** A11
|
||||
PK , // PK 4 ** 66 ** A12
|
||||
PK , // PK 5 ** 67 ** A13
|
||||
PK , // PK 6 ** 68 ** A14
|
||||
PK , // PK 7 ** 69 ** A15
|
||||
PG , // PG 4 ** 70 **
|
||||
PG , // PG 3 ** 71 **
|
||||
PJ , // PJ 2 ** 72 **
|
||||
PJ , // PJ 3 ** 73 **
|
||||
PJ , // PJ 7 ** 74 **
|
||||
PJ , // PJ 4 ** 75 **
|
||||
PJ , // PJ 5 ** 76 **
|
||||
PJ , // PJ 6 ** 77 **
|
||||
PE , // PE 2 ** 78 **
|
||||
PE , // PE 6 ** 79 **
|
||||
PE , // PE 7 ** 80 **
|
||||
PD , // PD 4 ** 81 **
|
||||
PD , // PD 5 ** 82 **
|
||||
PD , // PD 6 ** 83 **
|
||||
PH , // PH 2 ** 84 **
|
||||
PH , // PH 7 ** 85 **
|
||||
};
|
||||
|
||||
#define digitalPinToPort_plus_70(P) ( pgm_read_byte( digital_pin_to_port_PGM_plus_70 + (P) ) )
|
||||
|
||||
const uint8_t PROGMEM digital_pin_to_bit_mask_PGM_plus_70[] = {
|
||||
// PIN IN PORT
|
||||
// ------------------------
|
||||
_BV( 0 ) , // PE 0 ** 0 ** USART0_RX
|
||||
_BV( 1 ) , // PE 1 ** 1 ** USART0_TX
|
||||
_BV( 4 ) , // PE 4 ** 2 ** PWM2
|
||||
_BV( 5 ) , // PE 5 ** 3 ** PWM3
|
||||
_BV( 5 ) , // PG 5 ** 4 ** PWM4
|
||||
_BV( 3 ) , // PE 3 ** 5 ** PWM5
|
||||
_BV( 3 ) , // PH 3 ** 6 ** PWM6
|
||||
_BV( 4 ) , // PH 4 ** 7 ** PWM7
|
||||
_BV( 5 ) , // PH 5 ** 8 ** PWM8
|
||||
_BV( 6 ) , // PH 6 ** 9 ** PWM9
|
||||
_BV( 4 ) , // PB 4 ** 10 ** PWM10
|
||||
_BV( 5 ) , // PB 5 ** 11 ** PWM11
|
||||
_BV( 6 ) , // PB 6 ** 12 ** PWM12
|
||||
_BV( 7 ) , // PB 7 ** 13 ** PWM13
|
||||
_BV( 1 ) , // PJ 1 ** 14 ** USART3_TX
|
||||
_BV( 0 ) , // PJ 0 ** 15 ** USART3_RX
|
||||
_BV( 1 ) , // PH 1 ** 16 ** USART2_TX
|
||||
_BV( 0 ) , // PH 0 ** 17 ** USART2_RX
|
||||
_BV( 3 ) , // PD 3 ** 18 ** USART1_TX
|
||||
_BV( 2 ) , // PD 2 ** 19 ** USART1_RX
|
||||
_BV( 1 ) , // PD 1 ** 20 ** I2C_SDA
|
||||
_BV( 0 ) , // PD 0 ** 21 ** I2C_SCL
|
||||
_BV( 0 ) , // PA 0 ** 22 ** D22
|
||||
_BV( 1 ) , // PA 1 ** 23 ** D23
|
||||
_BV( 2 ) , // PA 2 ** 24 ** D24
|
||||
_BV( 3 ) , // PA 3 ** 25 ** D25
|
||||
_BV( 4 ) , // PA 4 ** 26 ** D26
|
||||
_BV( 5 ) , // PA 5 ** 27 ** D27
|
||||
_BV( 6 ) , // PA 6 ** 28 ** D28
|
||||
_BV( 7 ) , // PA 7 ** 29 ** D29
|
||||
_BV( 7 ) , // PC 7 ** 30 ** D30
|
||||
_BV( 6 ) , // PC 6 ** 31 ** D31
|
||||
_BV( 5 ) , // PC 5 ** 32 ** D32
|
||||
_BV( 4 ) , // PC 4 ** 33 ** D33
|
||||
_BV( 3 ) , // PC 3 ** 34 ** D34
|
||||
_BV( 2 ) , // PC 2 ** 35 ** D35
|
||||
_BV( 1 ) , // PC 1 ** 36 ** D36
|
||||
_BV( 0 ) , // PC 0 ** 37 ** D37
|
||||
_BV( 7 ) , // PD 7 ** 38 ** D38
|
||||
_BV( 2 ) , // PG 2 ** 39 ** D39
|
||||
_BV( 1 ) , // PG 1 ** 40 ** D40
|
||||
_BV( 0 ) , // PG 0 ** 41 ** D41
|
||||
_BV( 7 ) , // PL 7 ** 42 ** D42
|
||||
_BV( 6 ) , // PL 6 ** 43 ** D43
|
||||
_BV( 5 ) , // PL 5 ** 44 ** D44
|
||||
_BV( 4 ) , // PL 4 ** 45 ** D45
|
||||
_BV( 3 ) , // PL 3 ** 46 ** D46
|
||||
_BV( 2 ) , // PL 2 ** 47 ** D47
|
||||
_BV( 1 ) , // PL 1 ** 48 ** D48
|
||||
_BV( 0 ) , // PL 0 ** 49 ** D49
|
||||
_BV( 3 ) , // PB 3 ** 50 ** SPI_MISO
|
||||
_BV( 2 ) , // PB 2 ** 51 ** SPI_MOSI
|
||||
_BV( 1 ) , // PB 1 ** 52 ** SPI_SCK
|
||||
_BV( 0 ) , // PB 0 ** 53 ** SPI_SS
|
||||
_BV( 0 ) , // PF 0 ** 54 ** A0
|
||||
_BV( 1 ) , // PF 1 ** 55 ** A1
|
||||
_BV( 2 ) , // PF 2 ** 56 ** A2
|
||||
_BV( 3 ) , // PF 3 ** 57 ** A3
|
||||
_BV( 4 ) , // PF 4 ** 58 ** A4
|
||||
_BV( 5 ) , // PF 5 ** 59 ** A5
|
||||
_BV( 6 ) , // PF 6 ** 60 ** A6
|
||||
_BV( 7 ) , // PF 7 ** 61 ** A7
|
||||
_BV( 0 ) , // PK 0 ** 62 ** A8
|
||||
_BV( 1 ) , // PK 1 ** 63 ** A9
|
||||
_BV( 2 ) , // PK 2 ** 64 ** A10
|
||||
_BV( 3 ) , // PK 3 ** 65 ** A11
|
||||
_BV( 4 ) , // PK 4 ** 66 ** A12
|
||||
_BV( 5 ) , // PK 5 ** 67 ** A13
|
||||
_BV( 6 ) , // PK 6 ** 68 ** A14
|
||||
_BV( 7 ) , // PK 7 ** 69 ** A15
|
||||
_BV( 4 ) , // PG 4 ** 70 **
|
||||
_BV( 3 ) , // PG 3 ** 71 **
|
||||
_BV( 2 ) , // PJ 2 ** 72 **
|
||||
_BV( 3 ) , // PJ 3 ** 73 **
|
||||
_BV( 7 ) , // PJ 7 ** 74 **
|
||||
_BV( 4 ) , // PJ 4 ** 75 **
|
||||
_BV( 5 ) , // PJ 5 ** 76 **
|
||||
_BV( 6 ) , // PJ 6 ** 77 **
|
||||
_BV( 2 ) , // PE 2 ** 78 **
|
||||
_BV( 6 ) , // PE 6 ** 79 **
|
||||
_BV( 7 ) , // PE 7 ** 80 **
|
||||
_BV( 4 ) , // PD 4 ** 81 **
|
||||
_BV( 5 ) , // PD 5 ** 82 **
|
||||
_BV( 6 ) , // PD 6 ** 83 **
|
||||
_BV( 2 ) , // PH 2 ** 84 **
|
||||
_BV( 7 ) , // PH 7 ** 85 **
|
||||
};
|
||||
|
||||
#define digitalPinToBitMask_plus_70(P) ( pgm_read_byte( digital_pin_to_bit_mask_PGM_plus_70 + (P) ) )
|
||||
|
||||
const uint8_t PROGMEM digital_pin_to_timer_PGM_plus_70[] = {
|
||||
// TIMERS
|
||||
// ------------------------
|
||||
NOT_ON_TIMER , // PE 0 ** 0 ** USART0_RX
|
||||
NOT_ON_TIMER , // PE 1 ** 1 ** USART0_TX
|
||||
TIMER3B , // PE 4 ** 2 ** PWM2
|
||||
TIMER3C , // PE 5 ** 3 ** PWM3
|
||||
TIMER0B , // PG 5 ** 4 ** PWM4
|
||||
TIMER3A , // PE 3 ** 5 ** PWM5
|
||||
TIMER4A , // PH 3 ** 6 ** PWM6
|
||||
TIMER4B , // PH 4 ** 7 ** PWM7
|
||||
TIMER4C , // PH 5 ** 8 ** PWM8
|
||||
TIMER2B , // PH 6 ** 9 ** PWM9
|
||||
TIMER2A , // PB 4 ** 10 ** PWM10
|
||||
TIMER1A , // PB 5 ** 11 ** PWM11
|
||||
TIMER1B , // PB 6 ** 12 ** PWM12
|
||||
TIMER0A , // PB 7 ** 13 ** PWM13
|
||||
NOT_ON_TIMER , // PJ 1 ** 14 ** USART3_TX
|
||||
NOT_ON_TIMER , // PJ 0 ** 15 ** USART3_RX
|
||||
NOT_ON_TIMER , // PH 1 ** 16 ** USART2_TX
|
||||
NOT_ON_TIMER , // PH 0 ** 17 ** USART2_RX
|
||||
NOT_ON_TIMER , // PD 3 ** 18 ** USART1_TX
|
||||
NOT_ON_TIMER , // PD 2 ** 19 ** USART1_RX
|
||||
NOT_ON_TIMER , // PD 1 ** 20 ** I2C_SDA
|
||||
NOT_ON_TIMER , // PD 0 ** 21 ** I2C_SCL
|
||||
NOT_ON_TIMER , // PA 0 ** 22 ** D22
|
||||
NOT_ON_TIMER , // PA 1 ** 23 ** D23
|
||||
NOT_ON_TIMER , // PA 2 ** 24 ** D24
|
||||
NOT_ON_TIMER , // PA 3 ** 25 ** D25
|
||||
NOT_ON_TIMER , // PA 4 ** 26 ** D26
|
||||
NOT_ON_TIMER , // PA 5 ** 27 ** D27
|
||||
NOT_ON_TIMER , // PA 6 ** 28 ** D28
|
||||
NOT_ON_TIMER , // PA 7 ** 29 ** D29
|
||||
NOT_ON_TIMER , // PC 7 ** 30 ** D30
|
||||
NOT_ON_TIMER , // PC 6 ** 31 ** D31
|
||||
NOT_ON_TIMER , // PC 5 ** 32 ** D32
|
||||
NOT_ON_TIMER , // PC 4 ** 33 ** D33
|
||||
NOT_ON_TIMER , // PC 3 ** 34 ** D34
|
||||
NOT_ON_TIMER , // PC 2 ** 35 ** D35
|
||||
NOT_ON_TIMER , // PC 1 ** 36 ** D36
|
||||
NOT_ON_TIMER , // PC 0 ** 37 ** D37
|
||||
NOT_ON_TIMER , // PD 7 ** 38 ** D38
|
||||
NOT_ON_TIMER , // PG 2 ** 39 ** D39
|
||||
NOT_ON_TIMER , // PG 1 ** 40 ** D40
|
||||
NOT_ON_TIMER , // PG 0 ** 41 ** D41
|
||||
NOT_ON_TIMER , // PL 7 ** 42 ** D42
|
||||
NOT_ON_TIMER , // PL 6 ** 43 ** D43
|
||||
TIMER5C , // PL 5 ** 44 ** D44
|
||||
TIMER5B , // PL 4 ** 45 ** D45
|
||||
TIMER5A , // PL 3 ** 46 ** D46
|
||||
NOT_ON_TIMER , // PL 2 ** 47 ** D47
|
||||
NOT_ON_TIMER , // PL 1 ** 48 ** D48
|
||||
NOT_ON_TIMER , // PL 0 ** 49 ** D49
|
||||
NOT_ON_TIMER , // PB 3 ** 50 ** SPI_MISO
|
||||
NOT_ON_TIMER , // PB 2 ** 51 ** SPI_MOSI
|
||||
NOT_ON_TIMER , // PB 1 ** 52 ** SPI_SCK
|
||||
NOT_ON_TIMER , // PB 0 ** 53 ** SPI_SS
|
||||
NOT_ON_TIMER , // PF 0 ** 54 ** A0
|
||||
NOT_ON_TIMER , // PF 1 ** 55 ** A1
|
||||
NOT_ON_TIMER , // PF 2 ** 56 ** A2
|
||||
NOT_ON_TIMER , // PF 3 ** 57 ** A3
|
||||
NOT_ON_TIMER , // PF 4 ** 58 ** A4
|
||||
NOT_ON_TIMER , // PF 5 ** 59 ** A5
|
||||
NOT_ON_TIMER , // PF 6 ** 60 ** A6
|
||||
NOT_ON_TIMER , // PF 7 ** 61 ** A7
|
||||
NOT_ON_TIMER , // PK 0 ** 62 ** A8
|
||||
NOT_ON_TIMER , // PK 1 ** 63 ** A9
|
||||
NOT_ON_TIMER , // PK 2 ** 64 ** A10
|
||||
NOT_ON_TIMER , // PK 3 ** 65 ** A11
|
||||
NOT_ON_TIMER , // PK 4 ** 66 ** A12
|
||||
NOT_ON_TIMER , // PK 5 ** 67 ** A13
|
||||
NOT_ON_TIMER , // PK 6 ** 68 ** A14
|
||||
NOT_ON_TIMER , // PK 7 ** 69 ** A15
|
||||
NOT_ON_TIMER , // PG 4 ** 70 **
|
||||
NOT_ON_TIMER , // PG 3 ** 71 **
|
||||
NOT_ON_TIMER , // PJ 2 ** 72 **
|
||||
NOT_ON_TIMER , // PJ 3 ** 73 **
|
||||
NOT_ON_TIMER , // PJ 7 ** 74 **
|
||||
NOT_ON_TIMER , // PJ 4 ** 75 **
|
||||
NOT_ON_TIMER , // PJ 5 ** 76 **
|
||||
NOT_ON_TIMER , // PJ 6 ** 77 **
|
||||
NOT_ON_TIMER , // PE 2 ** 78 **
|
||||
NOT_ON_TIMER , // PE 6 ** 79 **
|
||||
};
|
||||
|
||||
#define digitalPinToTimer_plus_70(P) ( pgm_read_byte( digital_pin_to_timer_PGM_plus_70 + (P) ) )
|
||||
|
||||
/**
|
||||
* Interrupts that are not implemented
|
||||
*
|
||||
* INT6 E6 79
|
||||
* INT7 E7 80
|
||||
* PCINT11 J2 72
|
||||
* PCINT12 J3 73
|
||||
* PCINT13 J4 75
|
||||
* PCINT14 J5 76
|
||||
* PCINT15 J6 77
|
||||
*/
|
|
@ -0,0 +1,65 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Define SPI Pins: SCK, MISO, MOSI, SS
|
||||
*/
|
||||
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328__) || defined(__AVR_ATmega328P__)
|
||||
#define AVR_SCK_PIN 13
|
||||
#define AVR_MISO_PIN 12
|
||||
#define AVR_MOSI_PIN 11
|
||||
#define AVR_SS_PIN 10
|
||||
#elif defined(__AVR_ATmega644__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644PA__) || defined(__AVR_ATmega1284P__)
|
||||
#define AVR_SCK_PIN 7
|
||||
#define AVR_MISO_PIN 6
|
||||
#define AVR_MOSI_PIN 5
|
||||
#define AVR_SS_PIN 4
|
||||
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||||
#define AVR_SCK_PIN 52
|
||||
#define AVR_MISO_PIN 50
|
||||
#define AVR_MOSI_PIN 51
|
||||
#define AVR_SS_PIN 53
|
||||
#elif defined(__AVR_AT90USB1287__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__)
|
||||
#define AVR_SCK_PIN 21
|
||||
#define AVR_MISO_PIN 23
|
||||
#define AVR_MOSI_PIN 22
|
||||
#define AVR_SS_PIN 20
|
||||
#elif defined(__AVR_ATmega1281__) || defined(__AVR_ATmega2561__)
|
||||
#define AVR_SCK_PIN 10
|
||||
#define AVR_MISO_PIN 12
|
||||
#define AVR_MOSI_PIN 11
|
||||
#define AVR_SS_PIN 16
|
||||
#endif
|
||||
|
||||
#ifndef SD_SCK_PIN
|
||||
#define SD_SCK_PIN AVR_SCK_PIN
|
||||
#endif
|
||||
#ifndef SD_MISO_PIN
|
||||
#define SD_MISO_PIN AVR_MISO_PIN
|
||||
#endif
|
||||
#ifndef SD_MOSI_PIN
|
||||
#define SD_MOSI_PIN AVR_MOSI_PIN
|
||||
#endif
|
||||
#ifndef SD_SS_PIN
|
||||
#define SD_SS_PIN AVR_SS_PIN
|
||||
#endif
|
|
@ -0,0 +1,262 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// ------------------------
|
||||
// Types
|
||||
// ------------------------
|
||||
|
||||
typedef uint16_t hal_timer_t;
|
||||
#define HAL_TIMER_TYPE_MAX 0xFFFF
|
||||
|
||||
// ------------------------
|
||||
// Defines
|
||||
// ------------------------
|
||||
|
||||
#define HAL_TIMER_RATE ((F_CPU) / 8) // i.e., 2MHz or 2.5MHz
|
||||
|
||||
#ifndef MF_TIMER_STEP
|
||||
#define MF_TIMER_STEP 1
|
||||
#endif
|
||||
#ifndef MF_TIMER_PULSE
|
||||
#define MF_TIMER_PULSE MF_TIMER_STEP
|
||||
#endif
|
||||
#ifndef MF_TIMER_TEMP
|
||||
#define MF_TIMER_TEMP 0
|
||||
#endif
|
||||
|
||||
#define TEMP_TIMER_FREQUENCY (((F_CPU) + 0x2000) / 0x4000)
|
||||
|
||||
#define STEPPER_TIMER_RATE HAL_TIMER_RATE
|
||||
#define STEPPER_TIMER_PRESCALE 8
|
||||
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000)
|
||||
|
||||
#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() SBI(TIMSK1, OCIE1A)
|
||||
#define DISABLE_STEPPER_DRIVER_INTERRUPT() CBI(TIMSK1, OCIE1A)
|
||||
#define STEPPER_ISR_ENABLED() TEST(TIMSK1, OCIE1A)
|
||||
|
||||
#define ENABLE_TEMPERATURE_INTERRUPT() SBI(TIMSK0, OCIE0A)
|
||||
#define DISABLE_TEMPERATURE_INTERRUPT() CBI(TIMSK0, OCIE0A)
|
||||
#define TEMPERATURE_ISR_ENABLED() TEST(TIMSK0, OCIE0A)
|
||||
|
||||
FORCE_INLINE void HAL_timer_start(const uint8_t timer_num, const uint32_t) {
|
||||
switch (timer_num) {
|
||||
case MF_TIMER_STEP:
|
||||
// waveform generation = 0100 = CTC
|
||||
SET_WGM(1, CTC_OCRnA);
|
||||
|
||||
// output mode = 00 (disconnected)
|
||||
SET_COMA(1, NORMAL);
|
||||
|
||||
// Set the timer pre-scaler
|
||||
// Generally we use a divider of 8, resulting in a 2MHz timer
|
||||
// frequency on a 16MHz MCU. If you are going to change this, be
|
||||
// sure to regenerate speed_lookuptable.h with
|
||||
// create_speed_lookuptable.py
|
||||
SET_CS(1, PRESCALER_8); // CS 2 = 1/8 prescaler
|
||||
|
||||
// Init Stepper ISR to 122 Hz for quick starting
|
||||
// (F_CPU) / (STEPPER_TIMER_PRESCALE) / frequency
|
||||
OCR1A = 0x4000;
|
||||
TCNT1 = 0;
|
||||
break;
|
||||
|
||||
case MF_TIMER_TEMP:
|
||||
// Use timer0 for temperature measurement
|
||||
// Interleave temperature interrupt with millies interrupt
|
||||
OCR0A = 128;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define TIMER_OCR_1 OCR1A
|
||||
#define TIMER_COUNTER_1 TCNT1
|
||||
|
||||
#define TIMER_OCR_0 OCR0A
|
||||
#define TIMER_COUNTER_0 TCNT0
|
||||
|
||||
#define _CAT(a,V...) a##V
|
||||
#define HAL_timer_set_compare(timer, compare) (_CAT(TIMER_OCR_, timer) = compare)
|
||||
#define HAL_timer_get_compare(timer) _CAT(TIMER_OCR_, timer)
|
||||
#define HAL_timer_get_count(timer) _CAT(TIMER_COUNTER_, timer)
|
||||
|
||||
/**
|
||||
* On AVR there is no hardware prioritization and preemption of
|
||||
* interrupts, so this emulates it. The UART has first priority
|
||||
* (otherwise, characters will be lost due to UART overflow).
|
||||
* Then: Stepper, Endstops, Temperature, and -finally- all others.
|
||||
*/
|
||||
#define HAL_timer_isr_prologue(T) NOOP
|
||||
#define HAL_timer_isr_epilogue(T) NOOP
|
||||
|
||||
#ifndef HAL_STEP_TIMER_ISR
|
||||
|
||||
/* 18 cycles maximum latency */
|
||||
#define HAL_STEP_TIMER_ISR() \
|
||||
extern "C" void TIMER1_COMPA_vect() __attribute__ ((signal, naked, used, externally_visible)); \
|
||||
extern "C" void TIMER1_COMPA_vect_bottom() asm ("TIMER1_COMPA_vect_bottom") __attribute__ ((used, externally_visible, noinline)); \
|
||||
void TIMER1_COMPA_vect() { \
|
||||
__asm__ __volatile__ ( \
|
||||
A("push r16") /* 2 Save R16 */ \
|
||||
A("in r16, __SREG__") /* 1 Get SREG */ \
|
||||
A("push r16") /* 2 Save SREG into stack */ \
|
||||
A("lds r16, %[timsk0]") /* 2 Load into R0 the Temperature timer Interrupt mask register */ \
|
||||
A("push r16") /* 2 Save TIMSK0 into the stack */ \
|
||||
A("andi r16,~%[msk0]") /* 1 Disable the temperature ISR */ \
|
||||
A("sts %[timsk0], r16") /* 2 And set the new value */ \
|
||||
A("lds r16, %[timsk1]") /* 2 Load into R0 the stepper timer Interrupt mask register [TIMSK1] */ \
|
||||
A("andi r16,~%[msk1]") /* 1 Disable the stepper ISR */ \
|
||||
A("sts %[timsk1], r16") /* 2 And set the new value */ \
|
||||
A("push r16") /* 2 Save TIMSK1 into stack */ \
|
||||
A("in r16, 0x3B") /* 1 Get RAMPZ register */ \
|
||||
A("push r16") /* 2 Save RAMPZ into stack */ \
|
||||
A("in r16, 0x3C") /* 1 Get EIND register */ \
|
||||
A("push r0") /* C runtime can modify all the following registers without restoring them */ \
|
||||
A("push r1") \
|
||||
A("push r18") \
|
||||
A("push r19") \
|
||||
A("push r20") \
|
||||
A("push r21") \
|
||||
A("push r22") \
|
||||
A("push r23") \
|
||||
A("push r24") \
|
||||
A("push r25") \
|
||||
A("push r26") \
|
||||
A("push r27") \
|
||||
A("push r30") \
|
||||
A("push r31") \
|
||||
A("clr r1") /* C runtime expects this register to be 0 */ \
|
||||
A("call TIMER1_COMPA_vect_bottom") /* Call the bottom handler - No inlining allowed, otherwise registers used are not saved */ \
|
||||
A("pop r31") \
|
||||
A("pop r30") \
|
||||
A("pop r27") \
|
||||
A("pop r26") \
|
||||
A("pop r25") \
|
||||
A("pop r24") \
|
||||
A("pop r23") \
|
||||
A("pop r22") \
|
||||
A("pop r21") \
|
||||
A("pop r20") \
|
||||
A("pop r19") \
|
||||
A("pop r18") \
|
||||
A("pop r1") \
|
||||
A("pop r0") \
|
||||
A("out 0x3C, r16") /* 1 Restore EIND register */ \
|
||||
A("pop r16") /* 2 Get the original RAMPZ register value */ \
|
||||
A("out 0x3B, r16") /* 1 Restore RAMPZ register to its original value */ \
|
||||
A("pop r16") /* 2 Get the original TIMSK1 value but with stepper ISR disabled */ \
|
||||
A("ori r16,%[msk1]") /* 1 Reenable the stepper ISR */ \
|
||||
A("cli") /* 1 Disable global interrupts - Reenabling Stepper ISR can reenter amd temperature can reenter, and we want that, if it happens, after this ISR has ended */ \
|
||||
A("sts %[timsk1], r16") /* 2 And restore the old value - This reenables the stepper ISR */ \
|
||||
A("pop r16") /* 2 Get the temperature timer Interrupt mask register [TIMSK0] */ \
|
||||
A("sts %[timsk0], r16") /* 2 And restore the old value - This reenables the temperature ISR */ \
|
||||
A("pop r16") /* 2 Get the old SREG value */ \
|
||||
A("out __SREG__, r16") /* 1 And restore the SREG value */ \
|
||||
A("pop r16") /* 2 Restore R16 value */ \
|
||||
A("reti") /* 4 Return from interrupt */ \
|
||||
: \
|
||||
: [timsk0] "i" ((uint16_t)&TIMSK0), \
|
||||
[timsk1] "i" ((uint16_t)&TIMSK1), \
|
||||
[msk0] "M" ((uint8_t)(1<<OCIE0A)),\
|
||||
[msk1] "M" ((uint8_t)(1<<OCIE1A)) \
|
||||
: \
|
||||
); \
|
||||
} \
|
||||
void TIMER1_COMPA_vect_bottom()
|
||||
|
||||
#endif // HAL_STEP_TIMER_ISR
|
||||
|
||||
#ifndef HAL_TEMP_TIMER_ISR
|
||||
|
||||
/* 14 cycles maximum latency */
|
||||
#define HAL_TEMP_TIMER_ISR() \
|
||||
extern "C" void TIMER0_COMPA_vect() __attribute__ ((signal, naked, used, externally_visible)); \
|
||||
extern "C" void TIMER0_COMPA_vect_bottom() asm ("TIMER0_COMPA_vect_bottom") __attribute__ ((used, externally_visible, noinline)); \
|
||||
void TIMER0_COMPA_vect() { \
|
||||
__asm__ __volatile__ ( \
|
||||
A("push r16") /* 2 Save R16 */ \
|
||||
A("in r16, __SREG__") /* 1 Get SREG */ \
|
||||
A("push r16") /* 2 Save SREG into stack */ \
|
||||
A("lds r16, %[timsk0]") /* 2 Load into R0 the Temperature timer Interrupt mask register */ \
|
||||
A("andi r16,~%[msk0]") /* 1 Disable the temperature ISR */ \
|
||||
A("sts %[timsk0], r16") /* 2 And set the new value */ \
|
||||
A("sei") /* 1 Enable global interrupts - It is safe, as the temperature ISR is disabled, so we cannot reenter it */ \
|
||||
A("push r16") /* 2 Save TIMSK0 into stack */ \
|
||||
A("in r16, 0x3B") /* 1 Get RAMPZ register */ \
|
||||
A("push r16") /* 2 Save RAMPZ into stack */ \
|
||||
A("in r16, 0x3C") /* 1 Get EIND register */ \
|
||||
A("push r0") /* C runtime can modify all the following registers without restoring them */ \
|
||||
A("push r1") \
|
||||
A("push r18") \
|
||||
A("push r19") \
|
||||
A("push r20") \
|
||||
A("push r21") \
|
||||
A("push r22") \
|
||||
A("push r23") \
|
||||
A("push r24") \
|
||||
A("push r25") \
|
||||
A("push r26") \
|
||||
A("push r27") \
|
||||
A("push r30") \
|
||||
A("push r31") \
|
||||
A("clr r1") /* C runtime expects this register to be 0 */ \
|
||||
A("call TIMER0_COMPA_vect_bottom") /* Call the bottom handler - No inlining allowed, otherwise registers used are not saved */ \
|
||||
A("pop r31") \
|
||||
A("pop r30") \
|
||||
A("pop r27") \
|
||||
A("pop r26") \
|
||||
A("pop r25") \
|
||||
A("pop r24") \
|
||||
A("pop r23") \
|
||||
A("pop r22") \
|
||||
A("pop r21") \
|
||||
A("pop r20") \
|
||||
A("pop r19") \
|
||||
A("pop r18") \
|
||||
A("pop r1") \
|
||||
A("pop r0") \
|
||||
A("out 0x3C, r16") /* 1 Restore EIND register */ \
|
||||
A("pop r16") /* 2 Get the original RAMPZ register value */ \
|
||||
A("out 0x3B, r16") /* 1 Restore RAMPZ register to its original value */ \
|
||||
A("pop r16") /* 2 Get the original TIMSK0 value but with temperature ISR disabled */ \
|
||||
A("ori r16,%[msk0]") /* 1 Enable temperature ISR */ \
|
||||
A("cli") /* 1 Disable global interrupts - We must do this, as we will reenable the temperature ISR, and we don't want to reenter this handler until the current one is done */ \
|
||||
A("sts %[timsk0], r16") /* 2 And restore the old value */ \
|
||||
A("pop r16") /* 2 Get the old SREG */ \
|
||||
A("out __SREG__, r16") /* 1 And restore the SREG value */ \
|
||||
A("pop r16") /* 2 Restore R16 */ \
|
||||
A("reti") /* 4 Return from interrupt */ \
|
||||
: \
|
||||
: [timsk0] "i"((uint16_t)&TIMSK0), \
|
||||
[msk0] "M" ((uint8_t)(1<<OCIE0A)) \
|
||||
: \
|
||||
); \
|
||||
} \
|
||||
void TIMER0_COMPA_vect_bottom()
|
||||
|
||||
#endif // HAL_TEMP_TIMER_ISR
|
|
@ -0,0 +1,192 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Based on u8g_com_st7920_hw_spi.c
|
||||
*
|
||||
* Universal 8bit Graphics Library
|
||||
*
|
||||
* Copyright (c) 2011, olikraus@gmail.com
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if defined(ARDUINO) && !defined(ARDUINO_ARCH_STM32) && !defined(ARDUINO_ARCH_SAM)
|
||||
|
||||
#include "../../inc/MarlinConfigPre.h"
|
||||
|
||||
#if HAS_MARLINUI_U8GLIB
|
||||
|
||||
#include "../shared/Marduino.h"
|
||||
#include "../shared/Delay.h"
|
||||
|
||||
#include <U8glib-HAL.h>
|
||||
|
||||
static uint8_t u8g_bitData, u8g_bitNotData, u8g_bitClock, u8g_bitNotClock;
|
||||
static volatile uint8_t *u8g_outData, *u8g_outClock;
|
||||
|
||||
static void u8g_com_arduino_init_shift_out(uint8_t dataPin, uint8_t clockPin) {
|
||||
u8g_outData = portOutputRegister(digitalPinToPort(dataPin));
|
||||
u8g_outClock = portOutputRegister(digitalPinToPort(clockPin));
|
||||
u8g_bitData = digitalPinToBitMask(dataPin);
|
||||
u8g_bitClock = digitalPinToBitMask(clockPin);
|
||||
|
||||
u8g_bitNotClock = u8g_bitClock;
|
||||
u8g_bitNotClock ^= 0xFF;
|
||||
|
||||
u8g_bitNotData = u8g_bitData;
|
||||
u8g_bitNotData ^= 0xFF;
|
||||
}
|
||||
|
||||
void u8g_spiSend_sw_AVR_mode_0(uint8_t val) {
|
||||
uint8_t bitData = u8g_bitData,
|
||||
bitNotData = u8g_bitNotData,
|
||||
bitClock = u8g_bitClock,
|
||||
bitNotClock = u8g_bitNotClock;
|
||||
volatile uint8_t *outData = u8g_outData,
|
||||
*outClock = u8g_outClock;
|
||||
U8G_ATOMIC_START();
|
||||
for (uint8_t i = 0; i < 8; ++i) {
|
||||
if (val & 0x80)
|
||||
*outData |= bitData;
|
||||
else
|
||||
*outData &= bitNotData;
|
||||
*outClock |= bitClock;
|
||||
val <<= 1;
|
||||
*outClock &= bitNotClock;
|
||||
}
|
||||
U8G_ATOMIC_END();
|
||||
}
|
||||
|
||||
void u8g_spiSend_sw_AVR_mode_3(uint8_t val) {
|
||||
uint8_t bitData = u8g_bitData,
|
||||
bitNotData = u8g_bitNotData,
|
||||
bitClock = u8g_bitClock,
|
||||
bitNotClock = u8g_bitNotClock;
|
||||
volatile uint8_t *outData = u8g_outData,
|
||||
*outClock = u8g_outClock;
|
||||
U8G_ATOMIC_START();
|
||||
for (uint8_t i = 0; i < 8; ++i) {
|
||||
*outClock &= bitNotClock;
|
||||
if (val & 0x80)
|
||||
*outData |= bitData;
|
||||
else
|
||||
*outData &= bitNotData;
|
||||
*outClock |= bitClock;
|
||||
val <<= 1;
|
||||
}
|
||||
U8G_ATOMIC_END();
|
||||
}
|
||||
|
||||
#if ENABLED(FYSETC_MINI_12864)
|
||||
#define SPISEND_SW_AVR u8g_spiSend_sw_AVR_mode_3
|
||||
#else
|
||||
#define SPISEND_SW_AVR u8g_spiSend_sw_AVR_mode_0
|
||||
#endif
|
||||
|
||||
uint8_t u8g_com_HAL_AVR_sw_sp_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
|
||||
switch (msg) {
|
||||
case U8G_COM_MSG_INIT:
|
||||
u8g_com_arduino_init_shift_out(u8g->pin_list[U8G_PI_MOSI], u8g->pin_list[U8G_PI_SCK]);
|
||||
u8g_com_arduino_assign_pin_output_high(u8g);
|
||||
u8g_com_arduino_digital_write(u8g, U8G_PI_SCK, 0);
|
||||
u8g_com_arduino_digital_write(u8g, U8G_PI_MOSI, 0);
|
||||
break;
|
||||
|
||||
case U8G_COM_MSG_STOP:
|
||||
break;
|
||||
|
||||
case U8G_COM_MSG_RESET:
|
||||
if (U8G_PIN_NONE != u8g->pin_list[U8G_PI_RESET]) u8g_com_arduino_digital_write(u8g, U8G_PI_RESET, arg_val);
|
||||
break;
|
||||
|
||||
case U8G_COM_MSG_CHIP_SELECT:
|
||||
#if ENABLED(FYSETC_MINI_12864) // LCD SPI is running mode 3 while SD card is running mode 0
|
||||
if (arg_val) { // SCK idle state needs to be set to the proper idle state before
|
||||
// the next chip select goes active
|
||||
u8g_com_arduino_digital_write(u8g, U8G_PI_SCK, 1); // Set SCK to mode 3 idle state before CS goes active
|
||||
u8g_com_arduino_digital_write(u8g, U8G_PI_CS, LOW);
|
||||
}
|
||||
else {
|
||||
u8g_com_arduino_digital_write(u8g, U8G_PI_CS, HIGH);
|
||||
u8g_com_arduino_digital_write(u8g, U8G_PI_SCK, 0); // Set SCK to mode 0 idle state after CS goes inactive
|
||||
}
|
||||
#else
|
||||
u8g_com_arduino_digital_write(u8g, U8G_PI_CS, !arg_val);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case U8G_COM_MSG_WRITE_BYTE:
|
||||
SPISEND_SW_AVR(arg_val);
|
||||
break;
|
||||
|
||||
case U8G_COM_MSG_WRITE_SEQ: {
|
||||
uint8_t *ptr = (uint8_t *)arg_ptr;
|
||||
while (arg_val > 0) {
|
||||
SPISEND_SW_AVR(*ptr++);
|
||||
arg_val--;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case U8G_COM_MSG_WRITE_SEQ_P: {
|
||||
uint8_t *ptr = (uint8_t *)arg_ptr;
|
||||
while (arg_val > 0) {
|
||||
SPISEND_SW_AVR(u8g_pgm_read(ptr));
|
||||
ptr++;
|
||||
arg_val--;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */
|
||||
u8g_com_arduino_digital_write(u8g, U8G_PI_A0, arg_val);
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif // HAS_MARLINUI_U8GLIB
|
||||
#endif // ARDUINO_ARCH_SAM
|
|
@ -0,0 +1,203 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* HAL for Arduino Due and compatible (SAM3X8E)
|
||||
*/
|
||||
|
||||
#ifdef ARDUINO_ARCH_SAM
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
#include "../../MarlinCore.h"
|
||||
|
||||
#include <Wire.h>
|
||||
#include "usb/usb_task.h"
|
||||
|
||||
// ------------------------
|
||||
// Public Variables
|
||||
// ------------------------
|
||||
|
||||
uint16_t MarlinHAL::adc_result;
|
||||
|
||||
// ------------------------
|
||||
// Public functions
|
||||
// ------------------------
|
||||
|
||||
#if ENABLED(POSTMORTEM_DEBUGGING)
|
||||
extern void install_min_serial();
|
||||
#endif
|
||||
|
||||
void MarlinHAL::init() {
|
||||
#if HAS_MEDIA
|
||||
OUT_WRITE(SDSS, HIGH); // Try to set SDSS inactive before any other SPI users start up
|
||||
#endif
|
||||
usb_task_init(); // Initialize the USB stack
|
||||
TERN_(POSTMORTEM_DEBUGGING, install_min_serial()); // Install the min serial handler
|
||||
}
|
||||
|
||||
void MarlinHAL::init_board() {
|
||||
#ifdef BOARD_INIT
|
||||
BOARD_INIT();
|
||||
#endif
|
||||
}
|
||||
|
||||
void MarlinHAL::idletask() { usb_task_idle(); } // Perform USB stack housekeeping
|
||||
|
||||
uint8_t MarlinHAL::get_reset_source() {
|
||||
switch ((RSTC->RSTC_SR >> 8) & 0x07) {
|
||||
case 0: return RST_POWER_ON;
|
||||
case 1: return RST_BACKUP;
|
||||
case 2: return RST_WATCHDOG;
|
||||
case 3: return RST_SOFTWARE;
|
||||
case 4: return RST_EXTERNAL;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// 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)&_ebss);
|
||||
}
|
||||
|
||||
// ------------------------
|
||||
// Serial Ports
|
||||
// ------------------------
|
||||
|
||||
// Forward the default serial ports
|
||||
#if USING_HW_SERIAL0
|
||||
DefaultSerial1 MSerial0(false, Serial);
|
||||
#endif
|
||||
#if USING_HW_SERIAL1
|
||||
DefaultSerial2 MSerial1(false, Serial1);
|
||||
#endif
|
||||
#if USING_HW_SERIAL2
|
||||
DefaultSerial3 MSerial2(false, Serial2);
|
||||
#endif
|
||||
#if USING_HW_SERIAL3
|
||||
DefaultSerial4 MSerial3(false, Serial3);
|
||||
#endif
|
||||
|
||||
#endif // ARDUINO_ARCH_SAM
|
|
@ -0,0 +1,233 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* HAL for Arduino Due and compatible (SAM3X8E)
|
||||
*/
|
||||
|
||||
#define CPU_32_BIT
|
||||
|
||||
#include "../shared/Marduino.h"
|
||||
#include "../shared/eeprom_if.h"
|
||||
#include "../shared/math_32bit.h"
|
||||
#include "../shared/HAL_SPI.h"
|
||||
#include "fastio.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "../../core/serial_hook.h"
|
||||
|
||||
// ------------------------
|
||||
// Serial ports
|
||||
// ------------------------
|
||||
|
||||
typedef ForwardSerial1Class< decltype(Serial) > DefaultSerial1;
|
||||
typedef ForwardSerial1Class< decltype(Serial1) > DefaultSerial2;
|
||||
typedef ForwardSerial1Class< decltype(Serial2) > DefaultSerial3;
|
||||
typedef ForwardSerial1Class< decltype(Serial3) > DefaultSerial4;
|
||||
extern DefaultSerial1 MSerial0;
|
||||
extern DefaultSerial2 MSerial1;
|
||||
extern DefaultSerial3 MSerial2;
|
||||
extern DefaultSerial4 MSerial3;
|
||||
|
||||
#define _MSERIAL(X) MSerial##X
|
||||
#define MSERIAL(X) _MSERIAL(X)
|
||||
|
||||
#if SERIAL_PORT == -1 || ENABLED(EMERGENCY_PARSER)
|
||||
#define MYSERIAL1 customizedSerial1
|
||||
#elif WITHIN(SERIAL_PORT, 0, 3)
|
||||
#define MYSERIAL1 MSERIAL(SERIAL_PORT)
|
||||
#else
|
||||
#error "The required SERIAL_PORT must be from 0 to 3, or -1 for USB Serial."
|
||||
#endif
|
||||
|
||||
#ifdef SERIAL_PORT_2
|
||||
#if SERIAL_PORT_2 == -1 || ENABLED(EMERGENCY_PARSER)
|
||||
#define MYSERIAL2 customizedSerial2
|
||||
#elif WITHIN(SERIAL_PORT_2, 0, 3)
|
||||
#define MYSERIAL2 MSERIAL(SERIAL_PORT_2)
|
||||
#else
|
||||
#error "SERIAL_PORT_2 must be from 0 to 3, or -1 for USB Serial."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef SERIAL_PORT_3
|
||||
#if SERIAL_PORT_3 == -1 || ENABLED(EMERGENCY_PARSER)
|
||||
#define MYSERIAL3 customizedSerial3
|
||||
#elif WITHIN(SERIAL_PORT_3, 0, 3)
|
||||
#define MYSERIAL3 MSERIAL(SERIAL_PORT_3)
|
||||
#else
|
||||
#error "SERIAL_PORT_3 must be from 0 to 3, or -1 for USB Serial."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef MMU2_SERIAL_PORT
|
||||
#if WITHIN(MMU2_SERIAL_PORT, 0, 3)
|
||||
#define MMU2_SERIAL MSERIAL(MMU2_SERIAL_PORT)
|
||||
#else
|
||||
#error "MMU2_SERIAL_PORT must be from 0 to 3."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef LCD_SERIAL_PORT
|
||||
#if WITHIN(LCD_SERIAL_PORT, 0, 3)
|
||||
#define LCD_SERIAL MSERIAL(LCD_SERIAL_PORT)
|
||||
#else
|
||||
#error "LCD_SERIAL_PORT must be from 0 to 3."
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "MarlinSerial.h"
|
||||
#include "MarlinSerialUSB.h"
|
||||
|
||||
// ------------------------
|
||||
// Types
|
||||
// ------------------------
|
||||
|
||||
typedef int8_t pin_t;
|
||||
|
||||
#define SHARED_SERVOS HAS_SERVOS // Use shared/servos.cpp
|
||||
|
||||
class Servo;
|
||||
typedef Servo hal_servo_t;
|
||||
|
||||
//
|
||||
// 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()
|
||||
|
||||
//
|
||||
// ADC
|
||||
//
|
||||
#define HAL_ADC_VREF_MV 3300
|
||||
#define HAL_ADC_RESOLUTION 10
|
||||
|
||||
#ifndef analogInputToDigitalPin
|
||||
#define analogInputToDigitalPin(p) ((p < 12U) ? (p) + 54U : -1)
|
||||
#endif
|
||||
|
||||
//
|
||||
// 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
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
char *dtostrf(double __val, signed char __width, unsigned char __prec, char *__s);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
// Return free RAM between end of heap (or end bss) and whatever is current
|
||||
int freeMemory();
|
||||
|
||||
// ------------------------
|
||||
// MarlinHAL Class
|
||||
// ------------------------
|
||||
|
||||
class MarlinHAL {
|
||||
public:
|
||||
|
||||
// Earliest possible init, before setup()
|
||||
MarlinHAL() {}
|
||||
|
||||
// Watchdog
|
||||
static void watchdog_init() IF_DISABLED(USE_WATCHDOG, {});
|
||||
static void watchdog_refresh() IF_DISABLED(USE_WATCHDOG, {});
|
||||
|
||||
static void init(); // Called early in setup()
|
||||
static void init_board(); // Called less early in setup()
|
||||
static void reboot(); // Restart the firmware
|
||||
|
||||
// Interrupts
|
||||
static bool isr_state() { return !__get_PRIMASK(); }
|
||||
static void isr_on() { __enable_irq(); }
|
||||
static void isr_off() { __disable_irq(); }
|
||||
|
||||
static void delay_ms(const int ms) { delay(ms); }
|
||||
|
||||
// Tasks, called from idle()
|
||||
static void idletask();
|
||||
|
||||
// Reset
|
||||
static uint8_t get_reset_source();
|
||||
static void clear_reset_source() {}
|
||||
|
||||
// Free SRAM
|
||||
static int freeMemory() { return ::freeMemory(); }
|
||||
|
||||
//
|
||||
// ADC Methods
|
||||
//
|
||||
|
||||
static uint16_t adc_result;
|
||||
|
||||
// Called by Temperature::init once at startup
|
||||
static void adc_init() {}
|
||||
|
||||
// Called by Temperature::init for each sensor at startup
|
||||
static void adc_enable(const uint8_t /*ch*/) {}
|
||||
|
||||
// Begin ADC sampling on the given channel. Called from Temperature::isr!
|
||||
static void adc_start(const uint8_t ch) { adc_result = analogRead(ch); }
|
||||
|
||||
// Is the ADC ready for reading?
|
||||
static bool adc_ready() { return true; }
|
||||
|
||||
// The current value of the ADC register
|
||||
static uint16_t adc_value() { return adc_result; }
|
||||
|
||||
/**
|
||||
* Set the PWM duty cycle for the pin to the given value.
|
||||
* No inverting the duty cycle in this HAL.
|
||||
* No changing the maximum size of the provided value to enable finer PWM duty control in this HAL.
|
||||
*/
|
||||
static void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t=255, const bool=false) {
|
||||
analogWrite(pin, v);
|
||||
}
|
||||
|
||||
};
|
|
@ -0,0 +1,819 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Software SPI functions originally from Arduino Sd2Card Library
|
||||
* Copyright (c) 2009 by William Greiman
|
||||
*
|
||||
* Completely rewritten and tuned by Eduardo José Tagle in 2017/2018
|
||||
* in ARM thumb2 inline assembler and tuned for maximum speed and performance
|
||||
* allowing SPI clocks of up to 12 Mhz to increase SD card read/write performance
|
||||
*/
|
||||
|
||||
/**
|
||||
* HAL for Arduino Due and compatible (SAM3X8E)
|
||||
*/
|
||||
|
||||
#ifdef ARDUINO_ARCH_SAM
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
#include "../shared/Delay.h"
|
||||
|
||||
// ------------------------
|
||||
// Public functions
|
||||
// ------------------------
|
||||
|
||||
#if ANY(DUE_SOFTWARE_SPI, FORCE_SOFT_SPI)
|
||||
|
||||
// ------------------------
|
||||
// Software SPI
|
||||
// ------------------------
|
||||
|
||||
// Make sure GCC optimizes this file.
|
||||
// Note that this line triggers a bug in GCC which is fixed by casting.
|
||||
// See the note below.
|
||||
#pragma GCC optimize (3)
|
||||
|
||||
typedef uint8_t (*pfnSpiTransfer)(uint8_t b);
|
||||
typedef void (*pfnSpiRxBlock)(uint8_t *buf, uint32_t nbyte);
|
||||
typedef void (*pfnSpiTxBlock)(const uint8_t *buf, uint32_t nbyte);
|
||||
|
||||
/* ---------------- Macros to be able to access definitions from asm */
|
||||
#define _PORT(IO) DIO ## IO ## _WPORT
|
||||
#define _PIN_MASK(IO) MASK(DIO ## IO ## _PIN)
|
||||
#define _PIN_SHIFT(IO) DIO ## IO ## _PIN
|
||||
#define PORT(IO) _PORT(IO)
|
||||
#define PIN_MASK(IO) _PIN_MASK(IO)
|
||||
#define PIN_SHIFT(IO) _PIN_SHIFT(IO)
|
||||
|
||||
// run at ~8 .. ~10Mhz - Tx version (Rx data discarded)
|
||||
static uint8_t spiTransferTx0(uint8_t bout) { // using Mode 0
|
||||
uint32_t MOSI_PORT_PLUS30 = ((uint32_t) PORT(SD_MOSI_PIN)) + 0x30; /* SODR of port */
|
||||
uint32_t MOSI_MASK = PIN_MASK(SD_MOSI_PIN);
|
||||
uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SD_SCK_PIN)) + 0x30; /* SODR of port */
|
||||
uint32_t SCK_MASK = PIN_MASK(SD_SCK_PIN);
|
||||
uint32_t idx = 0;
|
||||
|
||||
/* Negate bout, as the assembler requires a negated value */
|
||||
bout = ~bout;
|
||||
|
||||
/* The software SPI routine */
|
||||
__asm__ __volatile__(
|
||||
A(".syntax unified") // is to prevent CM0,CM1 non-unified syntax
|
||||
|
||||
/* Bit 7 */
|
||||
A("ubfx %[idx],%[txval],#7,#1") /* Place bit 7 in bit 0 of idx*/
|
||||
|
||||
A("str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
||||
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
||||
A("ubfx %[idx],%[txval],#6,#1") /* Place bit 6 in bit 0 of idx*/
|
||||
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
||||
|
||||
/* Bit 6 */
|
||||
A("str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
||||
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
||||
A("ubfx %[idx],%[txval],#5,#1") /* Place bit 5 in bit 0 of idx*/
|
||||
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
||||
|
||||
/* Bit 5 */
|
||||
A("str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
||||
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
||||
A("ubfx %[idx],%[txval],#4,#1") /* Place bit 4 in bit 0 of idx*/
|
||||
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
||||
|
||||
/* Bit 4 */
|
||||
A("str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
||||
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
||||
A("ubfx %[idx],%[txval],#3,#1") /* Place bit 3 in bit 0 of idx*/
|
||||
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
||||
|
||||
/* Bit 3 */
|
||||
A("str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
||||
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
||||
A("ubfx %[idx],%[txval],#2,#1") /* Place bit 2 in bit 0 of idx*/
|
||||
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
||||
|
||||
/* Bit 2 */
|
||||
A("str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
||||
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
||||
A("ubfx %[idx],%[txval],#1,#1") /* Place bit 1 in bit 0 of idx*/
|
||||
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
||||
|
||||
/* Bit 1 */
|
||||
A("str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
||||
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
||||
A("ubfx %[idx],%[txval],#0,#1") /* Place bit 0 in bit 0 of idx*/
|
||||
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
||||
|
||||
/* Bit 0 */
|
||||
A("str %[mosi_mask],[%[mosi_port], %[idx],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
||||
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
||||
A("nop") /* Result will be 0 */
|
||||
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
||||
|
||||
: [idx]"+r"( idx )
|
||||
: [txval]"r"( bout ) ,
|
||||
[mosi_mask]"r"( MOSI_MASK ),
|
||||
[mosi_port]"r"( MOSI_PORT_PLUS30 ),
|
||||
[sck_mask]"r"( SCK_MASK ),
|
||||
[sck_port]"r"( SCK_PORT_PLUS30 )
|
||||
: "cc"
|
||||
);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Calculates the bit band alias address and returns a pointer address to word.
|
||||
// addr: The byte address of bitbanding bit.
|
||||
// bit: The bit position of bitbanding bit.
|
||||
#define BITBAND_ADDRESS(addr, bit) \
|
||||
(((uint32_t)(addr) & 0xF0000000) + 0x02000000 + ((uint32_t)(addr)&0xFFFFF)*32 + (bit)*4)
|
||||
|
||||
// run at ~8 .. ~10Mhz - Rx version (Tx line not altered)
|
||||
static uint8_t spiTransferRx0(uint8_t) { // using Mode 0
|
||||
uint32_t bin = 0;
|
||||
uint32_t work = 0;
|
||||
uint32_t BITBAND_MISO_PORT = BITBAND_ADDRESS( ((uint32_t)PORT(SD_MISO_PIN))+0x3C, PIN_SHIFT(SD_MISO_PIN)); /* PDSR of port in bitband area */
|
||||
uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SD_SCK_PIN)) + 0x30; /* SODR of port */
|
||||
uint32_t SCK_MASK = PIN_MASK(SD_SCK_PIN);
|
||||
|
||||
/* The software SPI routine */
|
||||
__asm__ __volatile__(
|
||||
A(".syntax unified") // is to prevent CM0,CM1 non-unified syntax
|
||||
|
||||
/* bit 7 */
|
||||
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
||||
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
||||
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
||||
A("bfi %[bin],%[work],#7,#1") /* Store read bit as the bit 7 */
|
||||
|
||||
/* bit 6 */
|
||||
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
||||
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
||||
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
||||
A("bfi %[bin],%[work],#6,#1") /* Store read bit as the bit 6 */
|
||||
|
||||
/* bit 5 */
|
||||
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
||||
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
||||
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
||||
A("bfi %[bin],%[work],#5,#1") /* Store read bit as the bit 5 */
|
||||
|
||||
/* bit 4 */
|
||||
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
||||
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
||||
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
||||
A("bfi %[bin],%[work],#4,#1") /* Store read bit as the bit 4 */
|
||||
|
||||
/* bit 3 */
|
||||
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
||||
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
||||
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
||||
A("bfi %[bin],%[work],#3,#1") /* Store read bit as the bit 3 */
|
||||
|
||||
/* bit 2 */
|
||||
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
||||
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
||||
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
||||
A("bfi %[bin],%[work],#2,#1") /* Store read bit as the bit 2 */
|
||||
|
||||
/* bit 1 */
|
||||
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
||||
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
||||
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
||||
A("bfi %[bin],%[work],#1,#1") /* Store read bit as the bit 1 */
|
||||
|
||||
/* bit 0 */
|
||||
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
||||
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
||||
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
||||
A("bfi %[bin],%[work],#0,#1") /* Store read bit as the bit 0 */
|
||||
|
||||
: [bin]"+r"(bin),
|
||||
[work]"+r"(work)
|
||||
: [bitband_miso_port]"r"( BITBAND_MISO_PORT ),
|
||||
[sck_mask]"r"( SCK_MASK ),
|
||||
[sck_port]"r"( SCK_PORT_PLUS30 )
|
||||
: "cc"
|
||||
);
|
||||
|
||||
return bin;
|
||||
}
|
||||
|
||||
// run at ~4Mhz
|
||||
static uint8_t spiTransfer1(uint8_t b) { // using Mode 0
|
||||
int bits = 8;
|
||||
do {
|
||||
WRITE(SD_MOSI_PIN, b & 0x80);
|
||||
b <<= 1; // little setup time
|
||||
|
||||
WRITE(SD_SCK_PIN, HIGH);
|
||||
DELAY_NS(125); // 10 cycles @ 84mhz
|
||||
|
||||
b |= (READ(SD_MISO_PIN) != 0);
|
||||
|
||||
WRITE(SD_SCK_PIN, LOW);
|
||||
DELAY_NS(125); // 10 cycles @ 84mhz
|
||||
} while (--bits);
|
||||
return b;
|
||||
}
|
||||
|
||||
// all the others
|
||||
static uint16_t spiDelayNS = 4000; // 4000ns => 125khz
|
||||
|
||||
static uint8_t spiTransferX(uint8_t b) { // using Mode 0
|
||||
int bits = 8;
|
||||
do {
|
||||
WRITE(SD_MOSI_PIN, b & 0x80);
|
||||
b <<= 1; // little setup time
|
||||
|
||||
WRITE(SD_SCK_PIN, HIGH);
|
||||
DELAY_NS_VAR(spiDelayNS);
|
||||
|
||||
b |= (READ(SD_MISO_PIN) != 0);
|
||||
|
||||
WRITE(SD_SCK_PIN, LOW);
|
||||
DELAY_NS_VAR(spiDelayNS);
|
||||
} while (--bits);
|
||||
return b;
|
||||
}
|
||||
|
||||
// Pointers to generic functions for byte transfers
|
||||
|
||||
/**
|
||||
* Note: The cast is unnecessary, but without it, this file triggers a GCC 4.8.3-2014 bug.
|
||||
* Later GCC versions do not have this problem, but at this time (May 2018) Arduino still
|
||||
* uses that buggy and obsolete GCC version!!
|
||||
*/
|
||||
static pfnSpiTransfer spiTransferRx = (pfnSpiTransfer)spiTransferX;
|
||||
static pfnSpiTransfer spiTransferTx = (pfnSpiTransfer)spiTransferX;
|
||||
|
||||
// Block transfers run at ~8 .. ~10Mhz - Tx version (Rx data discarded)
|
||||
static void spiTxBlock0(const uint8_t *ptr, uint32_t todo) {
|
||||
uint32_t MOSI_PORT_PLUS30 = ((uint32_t) PORT(SD_MOSI_PIN)) + 0x30; /* SODR of port */
|
||||
uint32_t MOSI_MASK = PIN_MASK(SD_MOSI_PIN);
|
||||
uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SD_SCK_PIN)) + 0x30; /* SODR of port */
|
||||
uint32_t SCK_MASK = PIN_MASK(SD_SCK_PIN);
|
||||
uint32_t work = 0;
|
||||
uint32_t txval = 0;
|
||||
|
||||
/* The software SPI routine */
|
||||
__asm__ __volatile__(
|
||||
A(".syntax unified") // is to prevent CM0,CM1 non-unified syntax
|
||||
|
||||
L("loop%=")
|
||||
A("ldrb.w %[txval], [%[ptr]], #1") /* Load value to send, increment buffer */
|
||||
A("mvn %[txval],%[txval]") /* Negate value */
|
||||
|
||||
/* Bit 7 */
|
||||
A("ubfx %[work],%[txval],#7,#1") /* Place bit 7 in bit 0 of work*/
|
||||
|
||||
A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
||||
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
||||
A("ubfx %[work],%[txval],#6,#1") /* Place bit 6 in bit 0 of work*/
|
||||
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
||||
|
||||
/* Bit 6 */
|
||||
A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
||||
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
||||
A("ubfx %[work],%[txval],#5,#1") /* Place bit 5 in bit 0 of work*/
|
||||
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
||||
|
||||
/* Bit 5 */
|
||||
A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
||||
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
||||
A("ubfx %[work],%[txval],#4,#1") /* Place bit 4 in bit 0 of work*/
|
||||
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
||||
|
||||
/* Bit 4 */
|
||||
A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
||||
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
||||
A("ubfx %[work],%[txval],#3,#1") /* Place bit 3 in bit 0 of work*/
|
||||
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
||||
|
||||
/* Bit 3 */
|
||||
A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
||||
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
||||
A("ubfx %[work],%[txval],#2,#1") /* Place bit 2 in bit 0 of work*/
|
||||
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
||||
|
||||
/* Bit 2 */
|
||||
A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
||||
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
||||
A("ubfx %[work],%[txval],#1,#1") /* Place bit 1 in bit 0 of work*/
|
||||
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
||||
|
||||
/* Bit 1 */
|
||||
A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
||||
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
||||
A("ubfx %[work],%[txval],#0,#1") /* Place bit 0 in bit 0 of work*/
|
||||
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
||||
|
||||
/* Bit 0 */
|
||||
A("str %[mosi_mask],[%[mosi_port], %[work],LSL #2]") /* Access the proper SODR or CODR registers based on that bit */
|
||||
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
||||
A("subs %[todo],#1") /* Decrement count of pending words to send, update status */
|
||||
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
||||
A("bne.n loop%=") /* Repeat until done */
|
||||
|
||||
: [ptr]"+r" ( ptr ) ,
|
||||
[todo]"+r" ( todo ) ,
|
||||
[work]"+r"( work ) ,
|
||||
[txval]"+r"( txval )
|
||||
: [mosi_mask]"r"( MOSI_MASK ),
|
||||
[mosi_port]"r"( MOSI_PORT_PLUS30 ),
|
||||
[sck_mask]"r"( SCK_MASK ),
|
||||
[sck_port]"r"( SCK_PORT_PLUS30 )
|
||||
: "cc"
|
||||
);
|
||||
}
|
||||
|
||||
static void spiRxBlock0(uint8_t *ptr, uint32_t todo) {
|
||||
uint32_t bin = 0;
|
||||
uint32_t work = 0;
|
||||
uint32_t BITBAND_MISO_PORT = BITBAND_ADDRESS( ((uint32_t)PORT(SD_MISO_PIN))+0x3C, PIN_SHIFT(SD_MISO_PIN)); /* PDSR of port in bitband area */
|
||||
uint32_t SCK_PORT_PLUS30 = ((uint32_t) PORT(SD_SCK_PIN)) + 0x30; /* SODR of port */
|
||||
uint32_t SCK_MASK = PIN_MASK(SD_SCK_PIN);
|
||||
|
||||
/* The software SPI routine */
|
||||
__asm__ __volatile__(
|
||||
A(".syntax unified") // is to prevent CM0,CM1 non-unified syntax
|
||||
|
||||
L("loop%=")
|
||||
|
||||
/* bit 7 */
|
||||
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
||||
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
||||
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
||||
A("bfi %[bin],%[work],#7,#1") /* Store read bit as the bit 7 */
|
||||
|
||||
/* bit 6 */
|
||||
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
||||
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
||||
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
||||
A("bfi %[bin],%[work],#6,#1") /* Store read bit as the bit 6 */
|
||||
|
||||
/* bit 5 */
|
||||
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
||||
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
||||
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
||||
A("bfi %[bin],%[work],#5,#1") /* Store read bit as the bit 5 */
|
||||
|
||||
/* bit 4 */
|
||||
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
||||
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
||||
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
||||
A("bfi %[bin],%[work],#4,#1") /* Store read bit as the bit 4 */
|
||||
|
||||
/* bit 3 */
|
||||
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
||||
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
||||
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
||||
A("bfi %[bin],%[work],#3,#1") /* Store read bit as the bit 3 */
|
||||
|
||||
/* bit 2 */
|
||||
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
||||
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
||||
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
||||
A("bfi %[bin],%[work],#2,#1") /* Store read bit as the bit 2 */
|
||||
|
||||
/* bit 1 */
|
||||
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
||||
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
||||
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
||||
A("bfi %[bin],%[work],#1,#1") /* Store read bit as the bit 1 */
|
||||
|
||||
/* bit 0 */
|
||||
A("str %[sck_mask],[%[sck_port]]") /* SODR */
|
||||
A("ldr %[work],[%[bitband_miso_port]]") /* PDSR on bitband area for required bit: work will be 1 or 0 based on port */
|
||||
A("str %[sck_mask],[%[sck_port],#0x4]") /* CODR */
|
||||
A("bfi %[bin],%[work],#0,#1") /* Store read bit as the bit 0 */
|
||||
|
||||
A("subs %[todo],#1") /* Decrement count of pending words to send, update status */
|
||||
A("strb.w %[bin], [%[ptr]], #1") /* Store read value into buffer, increment buffer pointer */
|
||||
A("bne.n loop%=") /* Repeat until done */
|
||||
|
||||
: [ptr]"+r"(ptr),
|
||||
[todo]"+r"(todo),
|
||||
[bin]"+r"(bin),
|
||||
[work]"+r"(work)
|
||||
: [bitband_miso_port]"r"( BITBAND_MISO_PORT ),
|
||||
[sck_mask]"r"( SCK_MASK ),
|
||||
[sck_port]"r"( SCK_PORT_PLUS30 )
|
||||
: "cc"
|
||||
);
|
||||
}
|
||||
|
||||
static void spiTxBlockX(const uint8_t *buf, uint32_t todo) {
|
||||
do {
|
||||
(void)spiTransferTx(*buf++);
|
||||
} while (--todo);
|
||||
}
|
||||
|
||||
static void spiRxBlockX(uint8_t *buf, uint32_t todo) {
|
||||
do {
|
||||
*buf++ = spiTransferRx(0xFF);
|
||||
} while (--todo);
|
||||
}
|
||||
|
||||
// Pointers to generic functions for block transfers
|
||||
static pfnSpiTxBlock spiTxBlock = (pfnSpiTxBlock)spiTxBlockX;
|
||||
static pfnSpiRxBlock spiRxBlock = (pfnSpiRxBlock)spiRxBlockX;
|
||||
|
||||
#if MB(ALLIGATOR)
|
||||
#define _SS_WRITE(S) WRITE(SD_SS_PIN, S)
|
||||
#else
|
||||
#define _SS_WRITE(S) NOOP
|
||||
#endif
|
||||
|
||||
void spiBegin() {
|
||||
SET_OUTPUT(SD_SS_PIN);
|
||||
_SS_WRITE(HIGH);
|
||||
SET_OUTPUT(SD_SCK_PIN);
|
||||
SET_INPUT(SD_MISO_PIN);
|
||||
SET_OUTPUT(SD_MOSI_PIN);
|
||||
}
|
||||
|
||||
uint8_t spiRec() {
|
||||
_SS_WRITE(LOW);
|
||||
WRITE(SD_MOSI_PIN, HIGH); // Output 1s 1
|
||||
uint8_t b = spiTransferRx(0xFF);
|
||||
_SS_WRITE(HIGH);
|
||||
return b;
|
||||
}
|
||||
|
||||
void spiRead(uint8_t *buf, uint16_t nbyte) {
|
||||
if (nbyte) {
|
||||
_SS_WRITE(LOW);
|
||||
WRITE(SD_MOSI_PIN, HIGH); // Output 1s 1
|
||||
spiRxBlock(buf, nbyte);
|
||||
_SS_WRITE(HIGH);
|
||||
}
|
||||
}
|
||||
|
||||
void spiSend(uint8_t b) {
|
||||
_SS_WRITE(LOW);
|
||||
(void)spiTransferTx(b);
|
||||
_SS_WRITE(HIGH);
|
||||
}
|
||||
|
||||
void spiSendBlock(uint8_t token, const uint8_t *buf) {
|
||||
_SS_WRITE(LOW);
|
||||
(void)spiTransferTx(token);
|
||||
spiTxBlock(buf, 512);
|
||||
_SS_WRITE(HIGH);
|
||||
}
|
||||
|
||||
/**
|
||||
* spiRate should be
|
||||
* 0 : 8 - 10 MHz
|
||||
* 1 : 4 - 5 MHz
|
||||
* 2 : 2 - 2.5 MHz
|
||||
* 3 : 1 - 1.25 MHz
|
||||
* 4 : 500 - 625 kHz
|
||||
* 5 : 250 - 312 kHz
|
||||
* 6 : 125 - 156 kHz
|
||||
*/
|
||||
void spiInit(uint8_t spiRate) {
|
||||
switch (spiRate) {
|
||||
case 0:
|
||||
spiTransferTx = (pfnSpiTransfer)spiTransferTx0;
|
||||
spiTransferRx = (pfnSpiTransfer)spiTransferRx0;
|
||||
spiTxBlock = (pfnSpiTxBlock)spiTxBlock0;
|
||||
spiRxBlock = (pfnSpiRxBlock)spiRxBlock0;
|
||||
break;
|
||||
case 1:
|
||||
spiTransferTx = (pfnSpiTransfer)spiTransfer1;
|
||||
spiTransferRx = (pfnSpiTransfer)spiTransfer1;
|
||||
spiTxBlock = (pfnSpiTxBlock)spiTxBlockX;
|
||||
spiRxBlock = (pfnSpiRxBlock)spiRxBlockX;
|
||||
break;
|
||||
default:
|
||||
spiDelayNS = 4000 >> (6 - spiRate); // spiRate of 2 gives the maximum error with current CPU
|
||||
spiTransferTx = (pfnSpiTransfer)spiTransferX;
|
||||
spiTransferRx = (pfnSpiTransfer)spiTransferX;
|
||||
spiTxBlock = (pfnSpiTxBlock)spiTxBlockX;
|
||||
spiRxBlock = (pfnSpiRxBlock)spiRxBlockX;
|
||||
break;
|
||||
}
|
||||
|
||||
_SS_WRITE(HIGH);
|
||||
WRITE(SD_MOSI_PIN, HIGH);
|
||||
WRITE(SD_SCK_PIN, LOW);
|
||||
}
|
||||
|
||||
/** Begin SPI transaction, set clock, bit order, data mode */
|
||||
void spiBeginTransaction(uint32_t spiClock, uint8_t bitOrder, uint8_t dataMode) {
|
||||
// TODO: to be implemented
|
||||
}
|
||||
|
||||
#pragma GCC reset_options
|
||||
|
||||
#else // !SOFTWARE_SPI
|
||||
|
||||
#define WHILE_TX(N) while ((SPI0->SPI_SR & SPI_SR_TDRE) == (N))
|
||||
#define WHILE_RX(N) while ((SPI0->SPI_SR & SPI_SR_RDRF) == (N))
|
||||
#define FLUSH_TX() do{ WHILE_RX(1) SPI0->SPI_RDR; }while(0)
|
||||
|
||||
#if MB(ALLIGATOR)
|
||||
|
||||
// slave selects controlled by SPI controller
|
||||
// doesn't support changing SPI speeds for SD card
|
||||
|
||||
// ------------------------
|
||||
// hardware SPI
|
||||
// ------------------------
|
||||
static bool spiInitialized = false;
|
||||
|
||||
void spiInit(uint8_t spiRate) {
|
||||
if (spiInitialized) return;
|
||||
|
||||
// 8.4 MHz, 4 MHz, 2 MHz, 1 MHz, 0.5 MHz, 0.329 MHz, 0.329 MHz
|
||||
constexpr int spiDivider[] = { 10, 21, 42, 84, 168, 255, 255 };
|
||||
if (spiRate > 6) spiRate = 1;
|
||||
|
||||
// Set SPI mode 1, clock, select not active after transfer, with delay between transfers
|
||||
SPI_ConfigureNPCS(SPI0, SPI_CHAN_DAC,
|
||||
SPI_CSR_CSAAT | SPI_CSR_SCBR(spiDivider[spiRate]) |
|
||||
SPI_CSR_DLYBCT(1));
|
||||
// Set SPI mode 0, clock, select not active after transfer, with delay between transfers
|
||||
SPI_ConfigureNPCS(SPI0, SPI_CHAN_EEPROM1, SPI_CSR_NCPHA |
|
||||
SPI_CSR_CSAAT | SPI_CSR_SCBR(spiDivider[spiRate]) |
|
||||
SPI_CSR_DLYBCT(1));
|
||||
|
||||
// Set SPI mode 0, clock, select not active after transfer, with delay between transfers
|
||||
SPI_ConfigureNPCS(SPI0, SPI_CHAN, SPI_CSR_NCPHA |
|
||||
SPI_CSR_CSAAT | SPI_CSR_SCBR(spiDivider[spiRate]) |
|
||||
SPI_CSR_DLYBCT(1));
|
||||
SPI_Enable(SPI0);
|
||||
spiInitialized = true;
|
||||
}
|
||||
|
||||
void spiBegin() {
|
||||
if (spiInitialized) return;
|
||||
|
||||
// Configure SPI pins
|
||||
PIO_Configure(
|
||||
g_APinDescription[SD_SCK_PIN].pPort,
|
||||
g_APinDescription[SD_SCK_PIN].ulPinType,
|
||||
g_APinDescription[SD_SCK_PIN].ulPin,
|
||||
g_APinDescription[SD_SCK_PIN].ulPinConfiguration);
|
||||
PIO_Configure(
|
||||
g_APinDescription[SD_MOSI_PIN].pPort,
|
||||
g_APinDescription[SD_MOSI_PIN].ulPinType,
|
||||
g_APinDescription[SD_MOSI_PIN].ulPin,
|
||||
g_APinDescription[SD_MOSI_PIN].ulPinConfiguration);
|
||||
PIO_Configure(
|
||||
g_APinDescription[SD_MISO_PIN].pPort,
|
||||
g_APinDescription[SD_MISO_PIN].ulPinType,
|
||||
g_APinDescription[SD_MISO_PIN].ulPin,
|
||||
g_APinDescription[SD_MISO_PIN].ulPinConfiguration);
|
||||
|
||||
// set master mode, peripheral select, fault detection
|
||||
SPI_Configure(SPI0, ID_SPI0, SPI_MR_MSTR | SPI_MR_MODFDIS | SPI_MR_PS);
|
||||
SPI_Enable(SPI0);
|
||||
|
||||
SET_OUTPUT(DAC0_SYNC_PIN);
|
||||
#if HAS_MULTI_EXTRUDER
|
||||
OUT_WRITE(DAC1_SYNC_PIN, HIGH);
|
||||
#endif
|
||||
WRITE(DAC0_SYNC_PIN, HIGH);
|
||||
OUT_WRITE(SPI_EEPROM1_CS_PIN, HIGH);
|
||||
OUT_WRITE(SPI_EEPROM2_CS_PIN, HIGH);
|
||||
OUT_WRITE(SPI_FLASH_CS_PIN, HIGH);
|
||||
WRITE(SD_SS_PIN, HIGH);
|
||||
|
||||
OUT_WRITE(SDSS, LOW);
|
||||
|
||||
PIO_Configure(
|
||||
g_APinDescription[SPI_PIN].pPort,
|
||||
g_APinDescription[SPI_PIN].ulPinType,
|
||||
g_APinDescription[SPI_PIN].ulPin,
|
||||
g_APinDescription[SPI_PIN].ulPinConfiguration
|
||||
);
|
||||
|
||||
spiInit(1);
|
||||
}
|
||||
|
||||
// Read single byte from SPI
|
||||
uint8_t spiRec() {
|
||||
// write dummy byte with address and end transmission flag
|
||||
SPI0->SPI_TDR = 0x000000FF | SPI_PCS(SPI_CHAN) | SPI_TDR_LASTXFER;
|
||||
|
||||
WHILE_TX(0);
|
||||
WHILE_RX(0);
|
||||
|
||||
//DELAY_US(1U);
|
||||
return SPI0->SPI_RDR;
|
||||
}
|
||||
|
||||
uint8_t spiRec(uint32_t chan) {
|
||||
|
||||
WHILE_TX(0);
|
||||
FLUSH_RX();
|
||||
|
||||
// write dummy byte with address and end transmission flag
|
||||
SPI0->SPI_TDR = 0x000000FF | SPI_PCS(chan) | SPI_TDR_LASTXFER;
|
||||
WHILE_RX(0);
|
||||
|
||||
return SPI0->SPI_RDR;
|
||||
}
|
||||
|
||||
// Read from SPI into buffer
|
||||
void spiRead(uint8_t *buf, uint16_t nbyte) {
|
||||
if (!nbyte) return;
|
||||
--nbyte;
|
||||
for (int i = 0; i < nbyte; i++) {
|
||||
//WHILE_TX(0);
|
||||
SPI0->SPI_TDR = 0x000000FF | SPI_PCS(SPI_CHAN);
|
||||
WHILE_RX(0);
|
||||
buf[i] = SPI0->SPI_RDR;
|
||||
//DELAY_US(1U);
|
||||
}
|
||||
buf[nbyte] = spiRec();
|
||||
}
|
||||
|
||||
// Write single byte to SPI
|
||||
void spiSend(const byte b) {
|
||||
// write byte with address and end transmission flag
|
||||
SPI0->SPI_TDR = (uint32_t)b | SPI_PCS(SPI_CHAN) | SPI_TDR_LASTXFER;
|
||||
WHILE_TX(0);
|
||||
WHILE_RX(0);
|
||||
SPI0->SPI_RDR;
|
||||
//DELAY_US(1U);
|
||||
}
|
||||
|
||||
void spiSend(const uint8_t *buf, size_t nbyte) {
|
||||
if (!nbyte) return;
|
||||
--nbyte;
|
||||
for (size_t i = 0; i < nbyte; i++) {
|
||||
SPI0->SPI_TDR = (uint32_t)buf[i] | SPI_PCS(SPI_CHAN);
|
||||
WHILE_TX(0);
|
||||
WHILE_RX(0);
|
||||
SPI0->SPI_RDR;
|
||||
//DELAY_US(1U);
|
||||
}
|
||||
spiSend(buf[nbyte]);
|
||||
}
|
||||
|
||||
void spiSend(uint32_t chan, byte b) {
|
||||
WHILE_TX(0);
|
||||
// write byte with address and end transmission flag
|
||||
SPI0->SPI_TDR = (uint32_t)b | SPI_PCS(chan) | SPI_TDR_LASTXFER;
|
||||
WHILE_RX(0);
|
||||
FLUSH_RX();
|
||||
}
|
||||
|
||||
void spiSend(uint32_t chan, const uint8_t *buf, size_t nbyte) {
|
||||
if (!nbyte) return;
|
||||
--nbyte;
|
||||
for (size_t i = 0; i < nbyte; i++) {
|
||||
WHILE_TX(0);
|
||||
SPI0->SPI_TDR = (uint32_t)buf[i] | SPI_PCS(chan);
|
||||
WHILE_RX(0);
|
||||
FLUSH_RX();
|
||||
}
|
||||
spiSend(chan, buf[nbyte]);
|
||||
}
|
||||
|
||||
// Write from buffer to SPI
|
||||
void spiSendBlock(uint8_t token, const uint8_t *buf) {
|
||||
SPI0->SPI_TDR = (uint32_t)token | SPI_PCS(SPI_CHAN);
|
||||
WHILE_TX(0);
|
||||
//WHILE_RX(0);
|
||||
//SPI0->SPI_RDR;
|
||||
for (int i = 0; i < 511; i++) {
|
||||
SPI0->SPI_TDR = (uint32_t)buf[i] | SPI_PCS(SPI_CHAN);
|
||||
WHILE_TX(0);
|
||||
WHILE_RX(0);
|
||||
SPI0->SPI_RDR;
|
||||
//DELAY_US(1U);
|
||||
}
|
||||
spiSend(buf[511]);
|
||||
}
|
||||
|
||||
/** Begin SPI transaction, set clock, bit order, data mode */
|
||||
void spiBeginTransaction(uint32_t spiClock, uint8_t bitOrder, uint8_t dataMode) {
|
||||
// TODO: to be implemented
|
||||
}
|
||||
|
||||
#else // U8G compatible hardware SPI
|
||||
|
||||
#define SPI_MODE_0_DUE_HW 2 // DUE CPHA control bit is inverted
|
||||
#define SPI_MODE_1_DUE_HW 3
|
||||
#define SPI_MODE_2_DUE_HW 0
|
||||
#define SPI_MODE_3_DUE_HW 1
|
||||
|
||||
/**
|
||||
* The DUE SPI controller is set up so the upper word of the longword
|
||||
* written to the transmit data register selects which SPI Chip Select
|
||||
* Register is used. This allows different streams to have different SPI
|
||||
* settings.
|
||||
*
|
||||
* In practice it's spooky. Some combinations hang the system, while others
|
||||
* upset the peripheral device.
|
||||
*
|
||||
* SPI mode should be the same for all streams. The FYSETC_MINI_12864 gets
|
||||
* upset if the clock phase changes after chip select goes active.
|
||||
*
|
||||
* SPI_CSR_CSAAT should be set for all streams. If not the WHILE_TX(0)
|
||||
* macro returns immediately which can result in the SPI chip select going
|
||||
* inactive before all the data has been sent.
|
||||
*
|
||||
* The TMC2130 library uses SPI0->SPI_CSR[3].
|
||||
*
|
||||
* The U8G hardware SPI uses SPI0->SPI_CSR[0]. The system hangs and/or the
|
||||
* FYSETC_MINI_12864 gets upset if lower baud rates are used and the SD card
|
||||
* is inserted or removed.
|
||||
*
|
||||
* The SD card uses SPI0->SPI_CSR[3]. Efforts were made to use [1] and [2]
|
||||
* but they all resulted in hangs or garbage on the LCD.
|
||||
*
|
||||
* The SPI controlled chip selects are NOT enabled in the GPIO controller.
|
||||
* The application must control the chip select.
|
||||
*
|
||||
* All of the above can be avoided by defining FORCE_SOFT_SPI to force the
|
||||
* display to use software SPI.
|
||||
*/
|
||||
|
||||
void spiInit(uint8_t spiRate=6) { // Default to slowest rate if not specified)
|
||||
// Also sets U8G SPI rate to 4MHz and the SPI mode to 3
|
||||
|
||||
// 8.4 MHz, 4 MHz, 2 MHz, 1 MHz, 0.5 MHz, 0.329 MHz, 0.329 MHz
|
||||
constexpr int spiDivider[] = { 10, 21, 42, 84, 168, 255, 255 };
|
||||
if (spiRate > 6) spiRate = 1;
|
||||
|
||||
// Enable PIOA and SPI0
|
||||
REG_PMC_PCER0 = (1UL << ID_PIOA) | (1UL << ID_SPI0);
|
||||
|
||||
// Disable PIO on A26 and A27
|
||||
REG_PIOA_PDR = 0x0C000000;
|
||||
OUT_WRITE(SDSS, HIGH);
|
||||
|
||||
// Reset SPI0 (from sam lib)
|
||||
SPI0->SPI_CR = SPI_CR_SPIDIS;
|
||||
SPI0->SPI_CR = SPI_CR_SWRST;
|
||||
SPI0->SPI_CR = SPI_CR_SWRST;
|
||||
SPI0->SPI_CR = SPI_CR_SPIEN;
|
||||
|
||||
// TMC2103 compatible setup
|
||||
// Master mode, no fault detection, PCS bits in data written to TDR select CSR register
|
||||
SPI0->SPI_MR = SPI_MR_MSTR | SPI_MR_PS | SPI_MR_MODFDIS;
|
||||
// SPI mode 3, 8 Bit data transfer, baud rate
|
||||
SPI0->SPI_CSR[3] = SPI_CSR_SCBR(spiDivider[spiRate]) | SPI_CSR_CSAAT | SPI_MODE_3_DUE_HW; // use same CSR as TMC2130
|
||||
SPI0->SPI_CSR[0] = SPI_CSR_SCBR(spiDivider[1]) | SPI_CSR_CSAAT | SPI_MODE_3_DUE_HW; // U8G default to 4MHz
|
||||
}
|
||||
|
||||
void spiBegin() { spiInit(); }
|
||||
|
||||
static uint8_t spiTransfer(uint8_t data) {
|
||||
WHILE_TX(0);
|
||||
SPI0->SPI_TDR = (uint32_t)data | 0x00070000UL; // Add TMC2130 PCS bits to every byte (use SPI0->SPI_CSR[3])
|
||||
WHILE_TX(0);
|
||||
WHILE_RX(0);
|
||||
return SPI0->SPI_RDR;
|
||||
}
|
||||
|
||||
uint8_t spiRec() { return (uint8_t)spiTransfer(0xFF); }
|
||||
|
||||
void spiRead(uint8_t *buf, uint16_t nbyte) {
|
||||
for (int i = 0; i < nbyte; i++)
|
||||
buf[i] = spiTransfer(0xFF);
|
||||
}
|
||||
|
||||
void spiSend(uint8_t data) { spiTransfer(data); }
|
||||
|
||||
void spiSend(const uint8_t *buf, size_t nbyte) {
|
||||
for (uint16_t i = 0; i < nbyte; i++)
|
||||
spiTransfer(buf[i]);
|
||||
}
|
||||
|
||||
void spiSendBlock(uint8_t token, const uint8_t *buf) {
|
||||
spiTransfer(token);
|
||||
for (uint16_t i = 0; i < 512; i++)
|
||||
spiTransfer(buf[i]);
|
||||
}
|
||||
|
||||
#endif // !ALLIGATOR
|
||||
#endif // !SOFTWARE_SPI
|
||||
|
||||
#endif // ARDUINO_ARCH_SAM
|
|
@ -0,0 +1,98 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* InterruptVectors_Due.cpp - This module relocates the Interrupt vector table to SRAM,
|
||||
* allowing to register new interrupt handlers at runtime. Specially valuable and needed
|
||||
* because Arduino runtime allocates some interrupt handlers that we NEED to override to
|
||||
* properly support extended functionality, as for example, USB host or USB device (MSD, MTP)
|
||||
* and custom serial port handlers, and we don't actually want to modify and/or recompile the
|
||||
* Arduino runtime. We just want to run as much as possible on Stock Arduino
|
||||
*
|
||||
* Copyright (c) 2017 Eduardo José Tagle. All right reserved
|
||||
*/
|
||||
#ifdef ARDUINO_ARCH_SAM
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
#include "HAL.h"
|
||||
#include "InterruptVectors.h"
|
||||
|
||||
/* The relocated Exception/Interrupt Table - According to the ARM
|
||||
reference manual, alignment to 128 bytes should suffice, but in
|
||||
practice, we need alignment to 256 bytes to make this work in all
|
||||
cases */
|
||||
__attribute__ ((aligned(256)))
|
||||
static DeviceVectors ram_tab[61] = { nullptr };
|
||||
|
||||
/**
|
||||
* This function checks if the exception/interrupt table is already in SRAM or not.
|
||||
* If it is not, then it copies the ROM table to the SRAM and relocates the table
|
||||
* by reprogramming the NVIC registers
|
||||
*/
|
||||
static pfnISR_Handler* get_relocated_table_addr() {
|
||||
// Get the address of the interrupt/exception table
|
||||
uint32_t isrtab = SCB->VTOR;
|
||||
|
||||
// If already relocated, we are done!
|
||||
if (isrtab >= IRAM0_ADDR)
|
||||
return (pfnISR_Handler*)isrtab;
|
||||
|
||||
// Get the address of the table stored in FLASH
|
||||
const pfnISR_Handler* romtab = (const pfnISR_Handler*)isrtab;
|
||||
|
||||
// Copy it to SRAM
|
||||
memcpy(&ram_tab, romtab, sizeof(ram_tab));
|
||||
|
||||
// Disable global interrupts
|
||||
CRITICAL_SECTION_START();
|
||||
|
||||
// Set the vector table base address to the SRAM copy
|
||||
SCB->VTOR = (uint32_t)(&ram_tab);
|
||||
|
||||
// Reenable interrupts
|
||||
CRITICAL_SECTION_END();
|
||||
|
||||
// Return the address of the table
|
||||
return (pfnISR_Handler*)(&ram_tab);
|
||||
}
|
||||
|
||||
pfnISR_Handler install_isr(IRQn_Type irq, pfnISR_Handler newHandler) {
|
||||
// Get the address of the relocated table
|
||||
pfnISR_Handler *isrtab = get_relocated_table_addr();
|
||||
|
||||
// Disable global interrupts
|
||||
CRITICAL_SECTION_START();
|
||||
|
||||
// Get the original handler
|
||||
pfnISR_Handler oldHandler = isrtab[irq + 16];
|
||||
|
||||
// Install the new one
|
||||
isrtab[irq + 16] = newHandler;
|
||||
|
||||
// Reenable interrupts
|
||||
CRITICAL_SECTION_END();
|
||||
|
||||
// Return the original one
|
||||
return oldHandler;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,45 @@
|
|||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* InterruptVectors_Due.h
|
||||
*
|
||||
* This module relocates the Interrupt vector table to SRAM, allowing new
|
||||
* interrupt handlers to be added at runtime. This is required because the
|
||||
* Arduino runtime steals interrupt handlers that Marlin MUST use to support
|
||||
* extended functionality such as USB hosts and USB devices (MSD, MTP) and
|
||||
* custom serial port handlers. Rather than modifying and/or recompiling the
|
||||
* Arduino runtime, We just want to run as much as possible on Stock Arduino.
|
||||
*
|
||||
* Copyright (c) 2017 Eduardo José Tagle. All right reserved
|
||||
*/
|
||||
|
||||
#ifdef ARDUINO_ARCH_SAM
|
||||
|
||||
// ISR handler type
|
||||
typedef void (*pfnISR_Handler)();
|
||||
|
||||
// Install a new interrupt vector handler for the given irq, returning the old one
|
||||
pfnISR_Handler install_isr(IRQn_Type irq, pfnISR_Handler newHandler);
|
||||
|
||||
#endif // ARDUINO_ARCH_SAM
|
|
@ -0,0 +1,26 @@
|
|||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <SPI.h>
|
||||
|
||||
using MarlinSPI = SPIClass;
|
|
@ -0,0 +1,493 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* MarlinSerial_Due.cpp - Hardware serial library for Arduino DUE
|
||||
* Copyright (c) 2017 Eduardo José Tagle. All right reserved
|
||||
* Based on MarlinSerial for AVR, copyright (c) 2006 Nicholas Zambetti. All right reserved.
|
||||
*/
|
||||
#ifdef ARDUINO_ARCH_SAM
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#include "MarlinSerial.h"
|
||||
#include "InterruptVectors.h"
|
||||
#include "../../MarlinCore.h"
|
||||
|
||||
template<typename Cfg> typename MarlinSerial<Cfg>::ring_buffer_r MarlinSerial<Cfg>::rx_buffer = { 0, 0, { 0 } };
|
||||
template<typename Cfg> typename MarlinSerial<Cfg>::ring_buffer_t MarlinSerial<Cfg>::tx_buffer = { 0 };
|
||||
template<typename Cfg> bool MarlinSerial<Cfg>::_written = false;
|
||||
template<typename Cfg> uint8_t MarlinSerial<Cfg>::xon_xoff_state = MarlinSerial<Cfg>::XON_XOFF_CHAR_SENT | MarlinSerial<Cfg>::XON_CHAR;
|
||||
template<typename Cfg> uint8_t MarlinSerial<Cfg>::rx_dropped_bytes = 0;
|
||||
template<typename Cfg> uint8_t MarlinSerial<Cfg>::rx_buffer_overruns = 0;
|
||||
template<typename Cfg> uint8_t MarlinSerial<Cfg>::rx_framing_errors = 0;
|
||||
template<typename Cfg> typename MarlinSerial<Cfg>::ring_buffer_pos_t MarlinSerial<Cfg>::rx_max_enqueued = 0;
|
||||
|
||||
// A SW memory barrier, to ensure GCC does not overoptimize loops
|
||||
#define sw_barrier() asm volatile("": : :"memory");
|
||||
|
||||
#include "../../feature/e_parser.h"
|
||||
|
||||
// (called with RX interrupts disabled)
|
||||
template<typename Cfg>
|
||||
FORCE_INLINE void MarlinSerial<Cfg>::store_rxd_char() {
|
||||
|
||||
static EmergencyParser::State emergency_state; // = EP_RESET
|
||||
|
||||
// Get the tail - Nothing can alter its value while we are at this ISR
|
||||
const ring_buffer_pos_t t = rx_buffer.tail;
|
||||
|
||||
// Get the head pointer
|
||||
ring_buffer_pos_t h = rx_buffer.head;
|
||||
|
||||
// Get the next element
|
||||
ring_buffer_pos_t i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(Cfg::RX_SIZE - 1);
|
||||
|
||||
// Read the character from the USART
|
||||
uint8_t c = HWUART->UART_RHR;
|
||||
|
||||
if (Cfg::EMERGENCYPARSER) emergency_parser.update(emergency_state, c);
|
||||
|
||||
// If the character is to be stored at the index just before the tail
|
||||
// (such that the head would advance to the current tail), the RX FIFO is
|
||||
// full, so don't write the character or advance the head.
|
||||
if (i != t) {
|
||||
rx_buffer.buffer[h] = c;
|
||||
h = i;
|
||||
}
|
||||
else if (Cfg::DROPPED_RX && !++rx_dropped_bytes)
|
||||
--rx_dropped_bytes;
|
||||
|
||||
const ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(Cfg::RX_SIZE - 1);
|
||||
// Calculate count of bytes stored into the RX buffer
|
||||
|
||||
// Keep track of the maximum count of enqueued bytes
|
||||
if (Cfg::MAX_RX_QUEUED) NOLESS(rx_max_enqueued, rx_count);
|
||||
|
||||
if (Cfg::XONOFF) {
|
||||
// If the last char that was sent was an XON
|
||||
if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XON_CHAR) {
|
||||
|
||||
// Bytes stored into the RX buffer
|
||||
const ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(Cfg::RX_SIZE - 1);
|
||||
|
||||
// If over 12.5% of RX buffer capacity, send XOFF before running out of
|
||||
// RX buffer space .. 325 bytes @ 250kbits/s needed to let the host react
|
||||
// and stop sending bytes. This translates to 13mS propagation time.
|
||||
if (rx_count >= (Cfg::RX_SIZE) / 8) {
|
||||
|
||||
// At this point, definitely no TX interrupt was executing, since the TX isr can't be preempted.
|
||||
// Don't enable the TX interrupt here as a means to trigger the XOFF char, because if it happens
|
||||
// to be in the middle of trying to disable the RX interrupt in the main program, eventually the
|
||||
// enabling of the TX interrupt could be undone. The ONLY reliable thing this can do to ensure
|
||||
// the sending of the XOFF char is to send it HERE AND NOW.
|
||||
|
||||
// About to send the XOFF char
|
||||
xon_xoff_state = XOFF_CHAR | XON_XOFF_CHAR_SENT;
|
||||
|
||||
// Wait until the TX register becomes empty and send it - Here there could be a problem
|
||||
// - While waiting for the TX register to empty, the RX register could receive a new
|
||||
// character. This must also handle that situation!
|
||||
uint32_t status;
|
||||
while (!((status = HWUART->UART_SR) & UART_SR_TXRDY)) {
|
||||
|
||||
if (status & UART_SR_RXRDY) {
|
||||
// We received a char while waiting for the TX buffer to be empty - Receive and process it!
|
||||
|
||||
i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(Cfg::RX_SIZE - 1);
|
||||
|
||||
// Read the character from the USART
|
||||
c = HWUART->UART_RHR;
|
||||
|
||||
if (Cfg::EMERGENCYPARSER) emergency_parser.update(emergency_state, c);
|
||||
|
||||
// If the character is to be stored at the index just before the tail
|
||||
// (such that the head would advance to the current tail), the FIFO is
|
||||
// full, so don't write the character or advance the head.
|
||||
if (i != t) {
|
||||
rx_buffer.buffer[h] = c;
|
||||
h = i;
|
||||
}
|
||||
else if (Cfg::DROPPED_RX && !++rx_dropped_bytes)
|
||||
--rx_dropped_bytes;
|
||||
}
|
||||
sw_barrier();
|
||||
}
|
||||
|
||||
HWUART->UART_THR = XOFF_CHAR;
|
||||
|
||||
// At this point there could be a race condition between the write() function
|
||||
// and this sending of the XOFF char. This interrupt could happen between the
|
||||
// wait to be empty TX buffer loop and the actual write of the character. Since
|
||||
// the TX buffer is full because it's sending the XOFF char, the only way to be
|
||||
// sure the write() function will succeed is to wait for the XOFF char to be
|
||||
// completely sent. Since an extra character could be received during the wait
|
||||
// it must also be handled!
|
||||
while (!((status = HWUART->UART_SR) & UART_SR_TXRDY)) {
|
||||
|
||||
if (status & UART_SR_RXRDY) {
|
||||
// A char arrived while waiting for the TX buffer to be empty - Receive and process it!
|
||||
|
||||
i = (ring_buffer_pos_t)(h + 1) & (ring_buffer_pos_t)(Cfg::RX_SIZE - 1);
|
||||
|
||||
// Read the character from the USART
|
||||
c = HWUART->UART_RHR;
|
||||
|
||||
if (Cfg::EMERGENCYPARSER) emergency_parser.update(emergency_state, c);
|
||||
|
||||
// If the character is to be stored at the index just before the tail
|
||||
// (such that the head would advance to the current tail), the FIFO is
|
||||
// full, so don't write the character or advance the head.
|
||||
if (i != t) {
|
||||
rx_buffer.buffer[h] = c;
|
||||
h = i;
|
||||
}
|
||||
else if (Cfg::DROPPED_RX && !++rx_dropped_bytes)
|
||||
--rx_dropped_bytes;
|
||||
}
|
||||
sw_barrier();
|
||||
}
|
||||
|
||||
// At this point everything is ready. The write() function won't
|
||||
// have any issues writing to the UART TX register if it needs to!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Store the new head value
|
||||
rx_buffer.head = h;
|
||||
}
|
||||
|
||||
template<typename Cfg>
|
||||
FORCE_INLINE void MarlinSerial<Cfg>::_tx_thr_empty_irq() {
|
||||
if (Cfg::TX_SIZE > 0) {
|
||||
// Read positions
|
||||
uint8_t t = tx_buffer.tail;
|
||||
const uint8_t h = tx_buffer.head;
|
||||
|
||||
if (Cfg::XONOFF) {
|
||||
// If an XON char is pending to be sent, do it now
|
||||
if (xon_xoff_state == XON_CHAR) {
|
||||
|
||||
// Send the character
|
||||
HWUART->UART_THR = XON_CHAR;
|
||||
|
||||
// Remember we sent it.
|
||||
xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
|
||||
|
||||
// If nothing else to transmit, just disable TX interrupts.
|
||||
if (h == t) HWUART->UART_IDR = UART_IDR_TXRDY;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// If nothing to transmit, just disable TX interrupts. This could
|
||||
// happen as the result of the non atomicity of the disabling of RX
|
||||
// interrupts that could end reenabling TX interrupts as a side effect.
|
||||
if (h == t) {
|
||||
HWUART->UART_IDR = UART_IDR_TXRDY;
|
||||
return;
|
||||
}
|
||||
|
||||
// There is something to TX, Send the next byte
|
||||
const uint8_t c = tx_buffer.buffer[t];
|
||||
t = (t + 1) & (Cfg::TX_SIZE - 1);
|
||||
HWUART->UART_THR = c;
|
||||
tx_buffer.tail = t;
|
||||
|
||||
// Disable interrupts if there is nothing to transmit following this byte
|
||||
if (h == t) HWUART->UART_IDR = UART_IDR_TXRDY;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Cfg>
|
||||
void MarlinSerial<Cfg>::UART_ISR() {
|
||||
const uint32_t status = HWUART->UART_SR;
|
||||
|
||||
// Data received?
|
||||
if (status & UART_SR_RXRDY) store_rxd_char();
|
||||
|
||||
if (Cfg::TX_SIZE > 0) {
|
||||
// Something to send, and TX interrupts are enabled (meaning something to send)?
|
||||
if ((status & UART_SR_TXRDY) && (HWUART->UART_IMR & UART_IMR_TXRDY)) _tx_thr_empty_irq();
|
||||
}
|
||||
|
||||
// Acknowledge errors
|
||||
if ((status & UART_SR_OVRE) || (status & UART_SR_FRAME)) {
|
||||
if (Cfg::DROPPED_RX && (status & UART_SR_OVRE) && !++rx_dropped_bytes) --rx_dropped_bytes;
|
||||
if (Cfg::RX_OVERRUNS && (status & UART_SR_OVRE) && !++rx_buffer_overruns) --rx_buffer_overruns;
|
||||
if (Cfg::RX_FRAMING_ERRORS && (status & UART_SR_FRAME) && !++rx_framing_errors) --rx_framing_errors;
|
||||
|
||||
// TODO: error reporting outside ISR
|
||||
HWUART->UART_CR = UART_CR_RSTSTA;
|
||||
}
|
||||
}
|
||||
|
||||
// Public Methods
|
||||
template<typename Cfg>
|
||||
void MarlinSerial<Cfg>::begin(const long baud_setting) {
|
||||
|
||||
// Disable UART interrupt in NVIC
|
||||
NVIC_DisableIRQ( HWUART_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();
|
||||
|
||||
// Disable clock
|
||||
pmc_disable_periph_clk( HWUART_IRQ_ID );
|
||||
|
||||
// Configure PMC
|
||||
pmc_enable_periph_clk( HWUART_IRQ_ID );
|
||||
|
||||
// Disable PDC channel
|
||||
HWUART->UART_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS;
|
||||
|
||||
// Reset and disable receiver and transmitter
|
||||
HWUART->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS;
|
||||
|
||||
// Configure mode: 8bit, No parity, 1 bit stop
|
||||
HWUART->UART_MR = UART_MR_CHMODE_NORMAL | US_MR_CHRL_8_BIT | US_MR_NBSTOP_1_BIT | UART_MR_PAR_NO;
|
||||
|
||||
// Configure baudrate (asynchronous, no oversampling)
|
||||
HWUART->UART_BRGR = (SystemCoreClock / (baud_setting << 4));
|
||||
|
||||
// Configure interrupts
|
||||
HWUART->UART_IDR = 0xFFFFFFFF;
|
||||
HWUART->UART_IER = UART_IER_RXRDY | UART_IER_OVRE | UART_IER_FRAME;
|
||||
|
||||
// Install interrupt handler
|
||||
install_isr(HWUART_IRQ, UART_ISR);
|
||||
|
||||
// Configure priority. We need a very high priority to avoid losing characters
|
||||
// and we need to be able to preempt the Stepper ISR and everything else!
|
||||
// (this could probably be fixed by using DMA with the Serial port)
|
||||
NVIC_SetPriority(HWUART_IRQ, 1);
|
||||
|
||||
// Enable UART interrupt in NVIC
|
||||
NVIC_EnableIRQ(HWUART_IRQ);
|
||||
|
||||
// Enable receiver and transmitter
|
||||
HWUART->UART_CR = UART_CR_RXEN | UART_CR_TXEN;
|
||||
|
||||
if (Cfg::TX_SIZE > 0) _written = false;
|
||||
}
|
||||
|
||||
template<typename Cfg>
|
||||
void MarlinSerial<Cfg>::end() {
|
||||
// Disable UART interrupt in NVIC
|
||||
NVIC_DisableIRQ( HWUART_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();
|
||||
|
||||
pmc_disable_periph_clk( HWUART_IRQ_ID );
|
||||
}
|
||||
|
||||
template<typename Cfg>
|
||||
int MarlinSerial<Cfg>::peek() {
|
||||
const int v = rx_buffer.head == rx_buffer.tail ? -1 : rx_buffer.buffer[rx_buffer.tail];
|
||||
return v;
|
||||
}
|
||||
|
||||
template<typename Cfg>
|
||||
int MarlinSerial<Cfg>::read() {
|
||||
|
||||
const ring_buffer_pos_t h = rx_buffer.head;
|
||||
ring_buffer_pos_t t = rx_buffer.tail;
|
||||
|
||||
if (h == t) return -1;
|
||||
|
||||
int v = rx_buffer.buffer[t];
|
||||
t = (ring_buffer_pos_t)(t + 1) & (Cfg::RX_SIZE - 1);
|
||||
|
||||
// Advance tail
|
||||
rx_buffer.tail = t;
|
||||
|
||||
if (Cfg::XONOFF) {
|
||||
// If the XOFF char was sent, or about to be sent...
|
||||
if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XOFF_CHAR) {
|
||||
// Get count of bytes in the RX buffer
|
||||
const ring_buffer_pos_t rx_count = (ring_buffer_pos_t)(h - t) & (ring_buffer_pos_t)(Cfg::RX_SIZE - 1);
|
||||
// When below 10% of RX buffer capacity, send XON before running out of RX buffer bytes
|
||||
if (rx_count < (Cfg::RX_SIZE) / 10) {
|
||||
if (Cfg::TX_SIZE > 0) {
|
||||
// Signal we want an XON character to be sent.
|
||||
xon_xoff_state = XON_CHAR;
|
||||
// Enable TX isr.
|
||||
HWUART->UART_IER = UART_IER_TXRDY;
|
||||
}
|
||||
else {
|
||||
// If not using TX interrupts, we must send the XON char now
|
||||
xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
|
||||
while (!(HWUART->UART_SR & UART_SR_TXRDY)) sw_barrier();
|
||||
HWUART->UART_THR = XON_CHAR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return v;
|
||||
}
|
||||
|
||||
template<typename Cfg>
|
||||
typename MarlinSerial<Cfg>::ring_buffer_pos_t MarlinSerial<Cfg>::available() {
|
||||
const ring_buffer_pos_t h = rx_buffer.head, t = rx_buffer.tail;
|
||||
return (ring_buffer_pos_t)(Cfg::RX_SIZE + h - t) & (Cfg::RX_SIZE - 1);
|
||||
}
|
||||
|
||||
template<typename Cfg>
|
||||
void MarlinSerial<Cfg>::flush() {
|
||||
rx_buffer.tail = rx_buffer.head;
|
||||
|
||||
if (Cfg::XONOFF) {
|
||||
if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XOFF_CHAR) {
|
||||
if (Cfg::TX_SIZE > 0) {
|
||||
// Signal we want an XON character to be sent.
|
||||
xon_xoff_state = XON_CHAR;
|
||||
// Enable TX isr.
|
||||
HWUART->UART_IER = UART_IER_TXRDY;
|
||||
}
|
||||
else {
|
||||
// If not using TX interrupts, we must send the XON char now
|
||||
xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
|
||||
while (!(HWUART->UART_SR & UART_SR_TXRDY)) sw_barrier();
|
||||
HWUART->UART_THR = XON_CHAR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Cfg>
|
||||
size_t MarlinSerial<Cfg>::write(const uint8_t c) {
|
||||
_written = true;
|
||||
|
||||
if (Cfg::TX_SIZE == 0) {
|
||||
while (!(HWUART->UART_SR & UART_SR_TXRDY)) sw_barrier();
|
||||
HWUART->UART_THR = c;
|
||||
}
|
||||
else {
|
||||
|
||||
// If the TX interrupts are disabled and the data register
|
||||
// is empty, just write the byte to the data register and
|
||||
// be done. This shortcut helps significantly improve the
|
||||
// effective datarate at high (>500kbit/s) bitrates, where
|
||||
// interrupt overhead becomes a slowdown.
|
||||
// Yes, there is a race condition between the sending of the
|
||||
// XOFF char at the RX isr, but it is properly handled there
|
||||
if (!(HWUART->UART_IMR & UART_IMR_TXRDY) && (HWUART->UART_SR & UART_SR_TXRDY)) {
|
||||
HWUART->UART_THR = c;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const uint8_t i = (tx_buffer.head + 1) & (Cfg::TX_SIZE - 1);
|
||||
|
||||
// If global interrupts are disabled (as the result of being called from an ISR)...
|
||||
if (!hal.isr_state()) {
|
||||
|
||||
// Make room by polling if it is possible to transmit, and do so!
|
||||
while (i == tx_buffer.tail) {
|
||||
// If we can transmit another byte, do it.
|
||||
if (HWUART->UART_SR & UART_SR_TXRDY) _tx_thr_empty_irq();
|
||||
// Make sure compiler rereads tx_buffer.tail
|
||||
sw_barrier();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Interrupts are enabled, just wait until there is space
|
||||
while (i == tx_buffer.tail) sw_barrier();
|
||||
}
|
||||
|
||||
// Store new char. head is always safe to move
|
||||
tx_buffer.buffer[tx_buffer.head] = c;
|
||||
tx_buffer.head = i;
|
||||
|
||||
// Enable TX isr - Non atomic, but it will eventually enable TX isr
|
||||
HWUART->UART_IER = UART_IER_TXRDY;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
template<typename Cfg>
|
||||
void MarlinSerial<Cfg>::flushTX() {
|
||||
// TX
|
||||
|
||||
if (Cfg::TX_SIZE == 0) {
|
||||
// No bytes written, no need to flush. This special case is needed since there's
|
||||
// no way to force the TXC (transmit complete) bit to 1 during initialization.
|
||||
if (!_written) return;
|
||||
|
||||
// Wait until everything was transmitted
|
||||
while (!(HWUART->UART_SR & UART_SR_TXEMPTY)) sw_barrier();
|
||||
|
||||
// At this point nothing is queued anymore (DRIE is disabled) and
|
||||
// the hardware finished transmission (TXC is set).
|
||||
|
||||
}
|
||||
else {
|
||||
// If we have never written a byte, no need to flush. This special
|
||||
// case is needed since there is no way to force the TXC (transmit
|
||||
// complete) bit to 1 during initialization
|
||||
if (!_written) return;
|
||||
|
||||
// If global interrupts are disabled (as the result of being called from an ISR)...
|
||||
if (!hal.isr_state()) {
|
||||
|
||||
// Wait until everything was transmitted - We must do polling, as interrupts are disabled
|
||||
while (tx_buffer.head != tx_buffer.tail || !(HWUART->UART_SR & UART_SR_TXEMPTY)) {
|
||||
// If there is more space, send an extra character
|
||||
if (HWUART->UART_SR & UART_SR_TXRDY) _tx_thr_empty_irq();
|
||||
sw_barrier();
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
// Wait until everything was transmitted
|
||||
while (tx_buffer.head != tx_buffer.tail || !(HWUART->UART_SR & UART_SR_TXEMPTY)) sw_barrier();
|
||||
}
|
||||
|
||||
// At this point nothing is queued anymore (DRIE is disabled) and
|
||||
// the hardware finished transmission (TXC is set).
|
||||
}
|
||||
}
|
||||
|
||||
// If not using the USB port as serial port
|
||||
#if defined(SERIAL_PORT) && SERIAL_PORT >= 0
|
||||
template class MarlinSerial< MarlinSerialCfg<SERIAL_PORT> >;
|
||||
MSerialT1 customizedSerial1(MarlinSerialCfg<SERIAL_PORT>::EMERGENCYPARSER);
|
||||
#endif
|
||||
|
||||
#if defined(SERIAL_PORT_2) && SERIAL_PORT_2 >= 0
|
||||
template class MarlinSerial< MarlinSerialCfg<SERIAL_PORT_2> >;
|
||||
MSerialT2 customizedSerial2(MarlinSerialCfg<SERIAL_PORT_2>::EMERGENCYPARSER);
|
||||
#endif
|
||||
|
||||
#if defined(SERIAL_PORT_3) && SERIAL_PORT_3 >= 0
|
||||
template class MarlinSerial< MarlinSerialCfg<SERIAL_PORT_3> >;
|
||||
MSerialT3 customizedSerial3(MarlinSerialCfg<SERIAL_PORT_3>::EMERGENCYPARSER);
|
||||
#endif
|
||||
|
||||
#endif // ARDUINO_ARCH_SAM
|
|
@ -0,0 +1,153 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* MarlinSerial_Due.h - Hardware serial library for Arduino DUE
|
||||
* Copyright (c) 2017 Eduardo José Tagle. All right reserved
|
||||
* Based on MarlinSerial for AVR, copyright (c) 2006 Nicholas Zambetti. All right reserved.
|
||||
*/
|
||||
|
||||
#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
|
||||
// using a ring buffer (I think), in which rx_buffer_head is the index of the
|
||||
// location to which to write the next incoming character and rx_buffer_tail
|
||||
// is the index of the location from which to read.
|
||||
// 256 is the max limit due to uint8_t head and tail. Use only powers of 2. (...,16,32,64,128,256)
|
||||
#ifndef RX_BUFFER_SIZE
|
||||
#define RX_BUFFER_SIZE 128
|
||||
#endif
|
||||
#ifndef TX_BUFFER_SIZE
|
||||
#define TX_BUFFER_SIZE 32
|
||||
#endif
|
||||
|
||||
//#if ENABLED(SERIAL_XON_XOFF) && RX_BUFFER_SIZE < 1024
|
||||
// #error "SERIAL_XON_XOFF requires RX_BUFFER_SIZE >= 1024 for reliable transfers without drops."
|
||||
//#elif RX_BUFFER_SIZE && (RX_BUFFER_SIZE < 2 || !IS_POWER_OF_2(RX_BUFFER_SIZE))
|
||||
// #error "RX_BUFFER_SIZE must be a power of 2 greater than 1."
|
||||
//#elif TX_BUFFER_SIZE && (TX_BUFFER_SIZE < 2 || TX_BUFFER_SIZE > 256 || !IS_POWER_OF_2(TX_BUFFER_SIZE))
|
||||
// #error "TX_BUFFER_SIZE must be 0, a power of 2 greater than 1, and no greater than 256."
|
||||
//#endif
|
||||
|
||||
// Templated structure wrapper
|
||||
template<typename S, unsigned int addr> struct StructWrapper {
|
||||
constexpr StructWrapper(int) {}
|
||||
FORCE_INLINE S* operator->() const { return (S*)addr; }
|
||||
};
|
||||
|
||||
template<typename Cfg>
|
||||
class MarlinSerial {
|
||||
protected:
|
||||
// Information for all supported UARTs
|
||||
static constexpr uint32_t BASES[] = {0x400E0800U, 0x40098000U, 0x4009C000U, 0x400A0000U, 0x400A4000U};
|
||||
static constexpr IRQn_Type IRQS[] = { UART_IRQn, USART0_IRQn, USART1_IRQn, USART2_IRQn, USART3_IRQn};
|
||||
static constexpr int IRQ_IDS[] = { ID_UART, ID_USART0, ID_USART1, ID_USART2, ID_USART3};
|
||||
|
||||
// Alias for shorter code
|
||||
static constexpr StructWrapper<Uart,BASES[Cfg::PORT]> HWUART = 0;
|
||||
static constexpr IRQn_Type HWUART_IRQ = IRQS[Cfg::PORT];
|
||||
static constexpr int HWUART_IRQ_ID = IRQ_IDS[Cfg::PORT];
|
||||
|
||||
// Base size of type on buffer size
|
||||
typedef uvalue_t(Cfg::RX_SIZE - 1) ring_buffer_pos_t;
|
||||
|
||||
struct ring_buffer_r {
|
||||
volatile ring_buffer_pos_t head, tail;
|
||||
unsigned char buffer[Cfg::RX_SIZE];
|
||||
};
|
||||
|
||||
struct ring_buffer_t {
|
||||
volatile uint8_t head, tail;
|
||||
unsigned char buffer[Cfg::TX_SIZE];
|
||||
};
|
||||
|
||||
static ring_buffer_r rx_buffer;
|
||||
static ring_buffer_t tx_buffer;
|
||||
static bool _written;
|
||||
|
||||
static constexpr uint8_t XON_XOFF_CHAR_SENT = 0x80, // XON / XOFF Character was sent
|
||||
XON_XOFF_CHAR_MASK = 0x1F; // XON / XOFF character to send
|
||||
|
||||
// XON / XOFF character definitions
|
||||
static constexpr uint8_t XON_CHAR = 17, XOFF_CHAR = 19;
|
||||
static uint8_t xon_xoff_state,
|
||||
rx_dropped_bytes,
|
||||
rx_buffer_overruns,
|
||||
rx_framing_errors;
|
||||
static ring_buffer_pos_t rx_max_enqueued;
|
||||
|
||||
FORCE_INLINE static void store_rxd_char();
|
||||
FORCE_INLINE static void _tx_thr_empty_irq();
|
||||
static void UART_ISR();
|
||||
|
||||
public:
|
||||
MarlinSerial() {};
|
||||
static void begin(const long);
|
||||
static void end();
|
||||
static int peek();
|
||||
static int read();
|
||||
static void flush();
|
||||
static ring_buffer_pos_t available();
|
||||
static size_t write(const uint8_t c);
|
||||
static void flushTX();
|
||||
|
||||
static bool emergency_parser_enabled() { return Cfg::EMERGENCYPARSER; }
|
||||
|
||||
FORCE_INLINE static uint8_t dropped() { return Cfg::DROPPED_RX ? rx_dropped_bytes : 0; }
|
||||
FORCE_INLINE static uint8_t buffer_overruns() { return Cfg::RX_OVERRUNS ? rx_buffer_overruns : 0; }
|
||||
FORCE_INLINE static uint8_t framing_errors() { return Cfg::RX_FRAMING_ERRORS ? rx_framing_errors : 0; }
|
||||
FORCE_INLINE static ring_buffer_pos_t rxMaxEnqueued() { return Cfg::MAX_RX_QUEUED ? rx_max_enqueued : 0; }
|
||||
};
|
||||
|
||||
// Serial port configuration
|
||||
template <uint8_t serial>
|
||||
struct MarlinSerialCfg {
|
||||
static constexpr int PORT = serial;
|
||||
static constexpr unsigned int RX_SIZE = RX_BUFFER_SIZE;
|
||||
static constexpr unsigned int TX_SIZE = TX_BUFFER_SIZE;
|
||||
static constexpr bool XONOFF = ENABLED(SERIAL_XON_XOFF);
|
||||
static constexpr bool EMERGENCYPARSER = ENABLED(EMERGENCY_PARSER);
|
||||
static constexpr bool DROPPED_RX = ENABLED(SERIAL_STATS_DROPPED_RX);
|
||||
static constexpr bool RX_OVERRUNS = ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS);
|
||||
static constexpr bool RX_FRAMING_ERRORS = ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS);
|
||||
static constexpr bool MAX_RX_QUEUED = ENABLED(SERIAL_STATS_MAX_RX_QUEUED);
|
||||
};
|
||||
|
||||
#if defined(SERIAL_PORT) && SERIAL_PORT >= 0
|
||||
typedef Serial1Class< MarlinSerial< MarlinSerialCfg<SERIAL_PORT> > > MSerialT1;
|
||||
extern MSerialT1 customizedSerial1;
|
||||
#endif
|
||||
|
||||
#if defined(SERIAL_PORT_2) && SERIAL_PORT_2 >= 0
|
||||
typedef Serial1Class< MarlinSerial< MarlinSerialCfg<SERIAL_PORT_2> > > MSerialT2;
|
||||
extern MSerialT2 customizedSerial2;
|
||||
#endif
|
||||
|
||||
#if defined(SERIAL_PORT_3) && SERIAL_PORT_3 >= 0
|
||||
typedef Serial1Class< MarlinSerial< MarlinSerialCfg<SERIAL_PORT_3> > > MSerialT3;
|
||||
extern MSerialT3 customizedSerial3;
|
||||
#endif
|
|
@ -0,0 +1,142 @@
|
|||
/**
|
||||
* 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
|
||||
|
||||
/**
|
||||
* MarlinSerial_Due.cpp - Hardware serial library for Arduino DUE
|
||||
* Copyright (c) 2017 Eduardo José Tagle. All right reserved
|
||||
* Based on MarlinSerial for AVR, copyright (c) 2006 Nicholas Zambetti. All right reserved.
|
||||
*/
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#if HAS_USB_SERIAL
|
||||
|
||||
#include "MarlinSerialUSB.h"
|
||||
|
||||
// Imports from Atmel USB Stack/CDC implementation
|
||||
extern "C" {
|
||||
bool usb_task_cdc_isenabled();
|
||||
bool usb_task_cdc_dtr_active();
|
||||
bool udi_cdc_is_rx_ready();
|
||||
int udi_cdc_getc();
|
||||
bool udi_cdc_is_tx_ready();
|
||||
int udi_cdc_putc(int value);
|
||||
}
|
||||
|
||||
// Pending character
|
||||
static int pending_char = -1;
|
||||
|
||||
// Public Methods
|
||||
void MarlinSerialUSB::begin(const long) {}
|
||||
|
||||
void MarlinSerialUSB::end() {}
|
||||
|
||||
int MarlinSerialUSB::peek() {
|
||||
if (pending_char >= 0)
|
||||
return pending_char;
|
||||
|
||||
// If USB CDC not enumerated or not configured on the PC side
|
||||
if (!usb_task_cdc_isenabled())
|
||||
return -1;
|
||||
|
||||
// If no bytes sent from the PC
|
||||
if (!udi_cdc_is_rx_ready())
|
||||
return -1;
|
||||
|
||||
pending_char = udi_cdc_getc();
|
||||
|
||||
TERN_(EMERGENCY_PARSER, emergency_parser.update(static_cast<MSerialT1*>(this)->emergency_state, (char)pending_char));
|
||||
|
||||
return pending_char;
|
||||
}
|
||||
|
||||
int MarlinSerialUSB::read() {
|
||||
if (pending_char >= 0) {
|
||||
int ret = pending_char;
|
||||
pending_char = -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// If USB CDC not enumerated or not configured on the PC side
|
||||
if (!usb_task_cdc_isenabled())
|
||||
return -1;
|
||||
|
||||
// If no bytes sent from the PC
|
||||
if (!udi_cdc_is_rx_ready())
|
||||
return -1;
|
||||
|
||||
int c = udi_cdc_getc();
|
||||
|
||||
TERN_(EMERGENCY_PARSER, emergency_parser.update(static_cast<MSerialT1*>(this)->emergency_state, (char)c));
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
int MarlinSerialUSB::available() {
|
||||
if (pending_char > 0) return pending_char;
|
||||
return pending_char == 0 ||
|
||||
// or USB CDC enumerated and configured on the PC side and some bytes where sent to us */
|
||||
(usb_task_cdc_isenabled() && udi_cdc_is_rx_ready());
|
||||
}
|
||||
|
||||
void MarlinSerialUSB::flush() { }
|
||||
|
||||
size_t MarlinSerialUSB::write(const uint8_t c) {
|
||||
|
||||
/* Do not even bother sending anything if USB CDC is not enumerated
|
||||
or not configured on the PC side or there is no program on the PC
|
||||
listening to our messages */
|
||||
if (!usb_task_cdc_isenabled() || !usb_task_cdc_dtr_active())
|
||||
return 0;
|
||||
|
||||
/* Wait until the PC has read the pending to be sent data */
|
||||
while (usb_task_cdc_isenabled() &&
|
||||
usb_task_cdc_dtr_active() &&
|
||||
!udi_cdc_is_tx_ready()) {
|
||||
};
|
||||
|
||||
/* Do not even bother sending anything if USB CDC is not enumerated
|
||||
or not configured on the PC side or there is no program on the PC
|
||||
listening to our messages at this point */
|
||||
if (!usb_task_cdc_isenabled() || !usb_task_cdc_dtr_active())
|
||||
return 0;
|
||||
|
||||
// Fifo full
|
||||
// udi_cdc_signal_overrun();
|
||||
udi_cdc_putc(c);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Preinstantiate
|
||||
#if SERIAL_PORT == -1
|
||||
MSerialT1 customizedSerial1(TERN0(EMERGENCY_PARSER, true));
|
||||
#endif
|
||||
#if SERIAL_PORT_2 == -1
|
||||
MSerialT2 customizedSerial2(TERN0(EMERGENCY_PARSER, true));
|
||||
#endif
|
||||
#if SERIAL_PORT_3 == -1
|
||||
MSerialT3 customizedSerial3(TERN0(EMERGENCY_PARSER, true));
|
||||
#endif
|
||||
|
||||
#endif // HAS_USB_SERIAL
|
||||
#endif // ARDUINO_ARCH_SAM
|
|
@ -0,0 +1,65 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* MarlinSerialUSB_Due.h - Hardware Serial over USB (CDC) library for Arduino DUE
|
||||
* Copyright (c) 2017 Eduardo José Tagle. All right reserved
|
||||
*/
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
#include "../../core/serial_hook.h"
|
||||
|
||||
#include <WString.h>
|
||||
|
||||
struct MarlinSerialUSB {
|
||||
void begin(const long);
|
||||
void end();
|
||||
int peek();
|
||||
int read();
|
||||
void flush();
|
||||
int available();
|
||||
size_t write(const uint8_t c);
|
||||
|
||||
#if ENABLED(SERIAL_STATS_DROPPED_RX)
|
||||
FORCE_INLINE uint32_t dropped() { return 0; }
|
||||
#endif
|
||||
|
||||
#if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
|
||||
FORCE_INLINE int rxMaxEnqueued() { return 0; }
|
||||
#endif
|
||||
};
|
||||
|
||||
#if SERIAL_PORT == -1
|
||||
typedef Serial1Class<MarlinSerialUSB> MSerialT1;
|
||||
extern MSerialT1 customizedSerial1;
|
||||
#endif
|
||||
|
||||
#if SERIAL_PORT_2 == -1
|
||||
typedef Serial1Class<MarlinSerialUSB> MSerialT2;
|
||||
extern MSerialT2 customizedSerial2;
|
||||
#endif
|
||||
|
||||
#if SERIAL_PORT_3 == -1
|
||||
typedef Serial1Class<MarlinSerialUSB> MSerialT3;
|
||||
extern MSerialT3 customizedSerial3;
|
||||
#endif
|
|
@ -0,0 +1,91 @@
|
|||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (c) 2021 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
#ifdef ARDUINO_ARCH_SAM
|
||||
|
||||
#include "../../inc/MarlinConfigPre.h"
|
||||
|
||||
#if ENABLED(POSTMORTEM_DEBUGGING)
|
||||
|
||||
#include "../shared/MinSerial.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
static void TXBegin() {
|
||||
// Disable UART interrupt in NVIC
|
||||
NVIC_DisableIRQ( UART_IRQn );
|
||||
|
||||
// We NEED memory barriers to ensure Interrupts are actually disabled!
|
||||
// ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
|
||||
__DSB();
|
||||
__ISB();
|
||||
|
||||
// Disable clock
|
||||
pmc_disable_periph_clk( ID_UART );
|
||||
|
||||
// Configure PMC
|
||||
pmc_enable_periph_clk( ID_UART );
|
||||
|
||||
// Disable PDC channel
|
||||
UART->UART_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS;
|
||||
|
||||
// Reset and disable receiver and transmitter
|
||||
UART->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS;
|
||||
|
||||
// Configure mode: 8bit, No parity, 1 bit stop
|
||||
UART->UART_MR = UART_MR_CHMODE_NORMAL | US_MR_CHRL_8_BIT | US_MR_NBSTOP_1_BIT | UART_MR_PAR_NO;
|
||||
|
||||
// Configure baudrate (asynchronous, no oversampling) to BAUDRATE bauds
|
||||
UART->UART_BRGR = (SystemCoreClock / (BAUDRATE << 4));
|
||||
|
||||
// Enable receiver and transmitter
|
||||
UART->UART_CR = UART_CR_RXEN | UART_CR_TXEN;
|
||||
}
|
||||
|
||||
// A SW memory barrier, to ensure GCC does not overoptimize loops
|
||||
#define sw_barrier() __asm__ volatile("": : :"memory");
|
||||
static void TX(char c) {
|
||||
while (!(UART->UART_SR & UART_SR_TXRDY)) { WDT_Restart(WDT); sw_barrier(); };
|
||||
UART->UART_THR = c;
|
||||
}
|
||||
|
||||
void install_min_serial() {
|
||||
HAL_min_serial_init = &TXBegin;
|
||||
HAL_min_serial_out = &TX;
|
||||
}
|
||||
|
||||
#if DISABLED(DYNAMIC_VECTORTABLE)
|
||||
extern "C" {
|
||||
__attribute__((naked)) void JumpHandler_ASM() {
|
||||
__asm__ __volatile__ (
|
||||
"b CommonHandler_ASM\n"
|
||||
);
|
||||
}
|
||||
void __attribute__((naked, alias("JumpHandler_ASM"))) HardFault_Handler();
|
||||
void __attribute__((naked, alias("JumpHandler_ASM"))) BusFault_Handler();
|
||||
void __attribute__((naked, alias("JumpHandler_ASM"))) UsageFault_Handler();
|
||||
void __attribute__((naked, alias("JumpHandler_ASM"))) MemManage_Handler();
|
||||
void __attribute__((naked, alias("JumpHandler_ASM"))) NMI_Handler();
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // POSTMORTEM_DEBUGGING
|
||||
#endif // ARDUINO_ARCH_SAM
|
|
@ -0,0 +1,163 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2013 Arduino LLC. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifdef ARDUINO_ARCH_SAM
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
|
||||
#if HAS_SERVOS
|
||||
|
||||
#include "../shared/servo.h"
|
||||
#include "../shared/servo_private.h"
|
||||
|
||||
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(const timer16_Sequence_t, Tc*, const uint8_t);
|
||||
|
||||
#ifdef _useTimer1
|
||||
void HANDLER_FOR_TIMER1() { Servo_Handler(_timer1, TC_FOR_TIMER1, CHANNEL_FOR_TIMER1); }
|
||||
#endif
|
||||
#ifdef _useTimer2
|
||||
void HANDLER_FOR_TIMER2() { Servo_Handler(_timer2, TC_FOR_TIMER2, CHANNEL_FOR_TIMER2); }
|
||||
#endif
|
||||
#ifdef _useTimer3
|
||||
void HANDLER_FOR_TIMER3() { Servo_Handler(_timer3, TC_FOR_TIMER3, CHANNEL_FOR_TIMER3); }
|
||||
#endif
|
||||
#ifdef _useTimer4
|
||||
void HANDLER_FOR_TIMER4() { Servo_Handler(_timer4, TC_FOR_TIMER4, CHANNEL_FOR_TIMER4); }
|
||||
#endif
|
||||
#ifdef _useTimer5
|
||||
void HANDLER_FOR_TIMER5() { Servo_Handler(_timer5, TC_FOR_TIMER5, CHANNEL_FOR_TIMER5); }
|
||||
#endif
|
||||
|
||||
void Servo_Handler(const timer16_Sequence_t timer, Tc *tc, const uint8_t channel) {
|
||||
static int8_t Channel[_Nbr_16timers]; // Servo counters to pulse (or -1 for refresh interval)
|
||||
int8_t cho = Channel[timer]; // Handle the prior Channel[timer] first
|
||||
if (cho < 0) { // Channel -1 indicates the refresh interval completed...
|
||||
tc->TC_CHANNEL[channel].TC_CCR |= TC_CCR_SWTRG; // ...so reset the timer
|
||||
if (DisablePending[timer]) {
|
||||
// Disabling only after the full servo period expires prevents
|
||||
// pulses being too close together if immediately re-enabled.
|
||||
DisablePending.clear(timer);
|
||||
TC_Stop(tc, channel);
|
||||
tc->TC_CHANNEL[channel].TC_SR; // clear interrupt
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (SERVO_INDEX(timer, cho) < ServoCount) // prior channel handled?
|
||||
extDigitalWrite(SERVO(timer, cho).Pin.nbr, LOW); // pulse the prior channel LOW
|
||||
|
||||
Channel[timer] = ++cho; // go to the next channel (or 0)
|
||||
if (cho < SERVOS_PER_TIMER && SERVO_INDEX(timer, cho) < ServoCount) {
|
||||
tc->TC_CHANNEL[channel].TC_RA = tc->TC_CHANNEL[channel].TC_CV + SERVO(timer, cho).ticks;
|
||||
if (SERVO(timer, cho).Pin.isActive) // activated?
|
||||
extDigitalWrite(SERVO(timer, cho).Pin.nbr, HIGH); // yes: pulse HIGH
|
||||
}
|
||||
else {
|
||||
// finished all channels so wait for the refresh period to expire before starting over
|
||||
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_WAVE // Waveform mode
|
||||
| TC_CMR_WAVSEL_UP_RC // Counter running up and reset when equal to RC
|
||||
| (SERVO_TIMER_PRESCALER == 2 ? TC_CMR_TCCLKS_TIMER_CLOCK1 : 0) // MCK/2
|
||||
| (SERVO_TIMER_PRESCALER == 8 ? TC_CMR_TCCLKS_TIMER_CLOCK2 : 0) // MCK/8
|
||||
| (SERVO_TIMER_PRESCALER == 32 ? TC_CMR_TCCLKS_TIMER_CLOCK3 : 0) // MCK/32
|
||||
| (SERVO_TIMER_PRESCALER == 128 ? TC_CMR_TCCLKS_TIMER_CLOCK4 : 0) // MCK/128
|
||||
);
|
||||
|
||||
// Wait 1ms before the first ISR
|
||||
TC_SetRA(tc, channel, (F_CPU) / (SERVO_TIMER_PRESCALER) / 1000UL); // 1ms
|
||||
|
||||
// Configure and enable interrupt
|
||||
NVIC_EnableIRQ(irqn);
|
||||
tc->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(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(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
|
||||
|
||||
#endif // ARDUINO_ARCH_SAM
|
|
@ -0,0 +1,107 @@
|
|||
/**
|
||||
* Copyright (c) 2013 Arduino LLC. All right reserved.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* Defines for 16 bit timers used with Servo library
|
||||
*
|
||||
* If _useTimerX is defined then TimerX is a 32 bit timer on the current board
|
||||
* timer16_Sequence_t enumerates the sequence that the timers should be allocated
|
||||
* _Nbr_16timers indicates how many timers are available.
|
||||
*/
|
||||
|
||||
/**
|
||||
* SAM Only definitions
|
||||
* --------------------
|
||||
*/
|
||||
|
||||
// For SAM3X:
|
||||
//!#define _useTimer1
|
||||
//!#define _useTimer2
|
||||
#define _useTimer3
|
||||
//!#define _useTimer4
|
||||
#define _useTimer5
|
||||
|
||||
#define TRIM_DURATION 2 // compensation ticks to trim adjust for digitalWrite delays
|
||||
#define SERVO_TIMER_PRESCALER 2 // timer prescaler
|
||||
|
||||
/*
|
||||
TC0, chan 0 => TC0_Handler
|
||||
TC0, chan 1 => TC1_Handler
|
||||
TC0, chan 2 => TC2_Handler
|
||||
TC1, chan 0 => TC3_Handler
|
||||
TC1, chan 1 => TC4_Handler
|
||||
TC1, chan 2 => TC5_Handler
|
||||
TC2, chan 0 => TC6_Handler
|
||||
TC2, chan 1 => TC7_Handler
|
||||
TC2, chan 2 => TC8_Handler
|
||||
*/
|
||||
|
||||
#ifdef _useTimer1
|
||||
#define TC_FOR_TIMER1 TC1
|
||||
#define CHANNEL_FOR_TIMER1 0
|
||||
#define ID_TC_FOR_TIMER1 ID_TC3
|
||||
#define IRQn_FOR_TIMER1 TC3_IRQn
|
||||
#define HANDLER_FOR_TIMER1 TC3_Handler
|
||||
#endif
|
||||
#ifdef _useTimer2
|
||||
#define TC_FOR_TIMER2 TC1
|
||||
#define CHANNEL_FOR_TIMER2 1
|
||||
#define ID_TC_FOR_TIMER2 ID_TC4
|
||||
#define IRQn_FOR_TIMER2 TC4_IRQn
|
||||
#define HANDLER_FOR_TIMER2 TC4_Handler
|
||||
#endif
|
||||
#ifdef _useTimer3
|
||||
#define TC_FOR_TIMER3 TC1
|
||||
#define CHANNEL_FOR_TIMER3 2
|
||||
#define ID_TC_FOR_TIMER3 ID_TC5
|
||||
#define IRQn_FOR_TIMER3 TC5_IRQn
|
||||
#define HANDLER_FOR_TIMER3 TC5_Handler
|
||||
#endif
|
||||
#ifdef _useTimer4
|
||||
#define TC_FOR_TIMER4 TC0
|
||||
#define CHANNEL_FOR_TIMER4 2
|
||||
#define ID_TC_FOR_TIMER4 ID_TC2
|
||||
#define IRQn_FOR_TIMER4 TC2_IRQn
|
||||
#define HANDLER_FOR_TIMER4 TC2_Handler
|
||||
#endif
|
||||
#ifdef _useTimer5
|
||||
#define TC_FOR_TIMER5 TC0
|
||||
#define CHANNEL_FOR_TIMER5 0
|
||||
#define ID_TC_FOR_TIMER5 ID_TC0
|
||||
#define IRQn_FOR_TIMER5 TC0_IRQn
|
||||
#define HANDLER_FOR_TIMER5 TC0_Handler
|
||||
#endif
|
||||
|
||||
typedef enum : unsigned char {
|
||||
#ifdef _useTimer1
|
||||
_timer1,
|
||||
#endif
|
||||
#ifdef _useTimer2
|
||||
_timer2,
|
||||
#endif
|
||||
#ifdef _useTimer3
|
||||
_timer3,
|
||||
#endif
|
||||
#ifdef _useTimer4
|
||||
_timer4,
|
||||
#endif
|
||||
#ifdef _useTimer5
|
||||
_timer5,
|
||||
#endif
|
||||
_Nbr_16timers
|
||||
} timer16_Sequence_t;
|
|
@ -0,0 +1,60 @@
|
|||
/**
|
||||
* 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
|
||||
*
|
||||
* SAMD51 HAL developed by Giuliano Zaro (AKA GMagician)
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Description: Tone function for Arduino Due and compatible (SAM3X8E)
|
||||
* Derived from https://forum.arduino.cc/index.php?topic=136500.msg2903012#msg2903012
|
||||
*/
|
||||
|
||||
#ifdef ARDUINO_ARCH_SAM
|
||||
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
#include "HAL.h"
|
||||
|
||||
static pin_t tone_pin;
|
||||
volatile static int32_t toggles;
|
||||
|
||||
void tone(const pin_t _pin, const unsigned int frequency, const unsigned long duration/*=0*/) {
|
||||
tone_pin = _pin;
|
||||
toggles = 2 * frequency * duration / 1000;
|
||||
HAL_timer_start(MF_TIMER_TONE, 2 * frequency);
|
||||
}
|
||||
|
||||
void noTone(const pin_t _pin) {
|
||||
HAL_timer_disable_interrupt(MF_TIMER_TONE);
|
||||
extDigitalWrite(_pin, LOW);
|
||||
}
|
||||
|
||||
HAL_TONE_TIMER_ISR() {
|
||||
static uint8_t pin_state = 0;
|
||||
HAL_timer_isr_prologue(MF_TIMER_TONE);
|
||||
|
||||
if (toggles) {
|
||||
toggles--;
|
||||
extDigitalWrite(tone_pin, (pin_state ^= 1));
|
||||
}
|
||||
else noTone(tone_pin); // turn off interrupt
|
||||
}
|
||||
|
||||
#endif // ARDUINO_ARCH_SAM
|
|
@ -0,0 +1,143 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Based on u8g_com_msp430_hw_spi.c
|
||||
*
|
||||
* Universal 8bit Graphics Library
|
||||
*
|
||||
* Copyright (c) 2012, olikraus@gmail.com
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef __SAM3X8E__
|
||||
|
||||
#include "../../../inc/MarlinConfigPre.h"
|
||||
|
||||
#if HAS_MARLINUI_U8GLIB
|
||||
|
||||
#include <U8glib-HAL.h>
|
||||
|
||||
#include "../../../MarlinCore.h"
|
||||
|
||||
#ifndef LCD_SPI_SPEED
|
||||
#define LCD_SPI_SPEED SPI_QUARTER_SPEED
|
||||
#endif
|
||||
|
||||
#include "../../shared/HAL_SPI.h"
|
||||
#include "../fastio.h"
|
||||
|
||||
void u8g_SetPIOutput_DUE_hw_spi(u8g_t *u8g, uint8_t pin_index) {
|
||||
PIO_Configure(g_APinDescription[u8g->pin_list[pin_index]].pPort, PIO_OUTPUT_1,
|
||||
g_APinDescription[u8g->pin_list[pin_index]].ulPin, g_APinDescription[u8g->pin_list[pin_index]].ulPinConfiguration); // OUTPUT
|
||||
}
|
||||
|
||||
void u8g_SetPILevel_DUE_hw_spi(u8g_t *u8g, uint8_t pin_index, uint8_t level) {
|
||||
volatile Pio* port = g_APinDescription[u8g->pin_list[pin_index]].pPort;
|
||||
uint32_t mask = g_APinDescription[u8g->pin_list[pin_index]].ulPin;
|
||||
if (level) port->PIO_SODR = mask;
|
||||
else port->PIO_CODR = mask;
|
||||
}
|
||||
|
||||
uint8_t u8g_com_HAL_DUE_shared_hw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
|
||||
switch (msg) {
|
||||
case U8G_COM_MSG_STOP:
|
||||
break;
|
||||
|
||||
case U8G_COM_MSG_INIT:
|
||||
u8g_SetPILevel_DUE_hw_spi(u8g, U8G_PI_CS, 1);
|
||||
u8g_SetPILevel_DUE_hw_spi(u8g, U8G_PI_A0, 1);
|
||||
|
||||
u8g_SetPIOutput_DUE_hw_spi(u8g, U8G_PI_CS);
|
||||
u8g_SetPIOutput_DUE_hw_spi(u8g, U8G_PI_A0);
|
||||
|
||||
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) */
|
||||
u8g_SetPILevel_DUE_hw_spi(u8g, U8G_PI_A0, arg_val);
|
||||
break;
|
||||
|
||||
case U8G_COM_MSG_CHIP_SELECT:
|
||||
u8g_SetPILevel_DUE_hw_spi(u8g, U8G_PI_CS, (arg_val ? 0 : 1));
|
||||
break;
|
||||
|
||||
case U8G_COM_MSG_RESET:
|
||||
break;
|
||||
|
||||
case U8G_COM_MSG_WRITE_BYTE:
|
||||
|
||||
spiSend((uint8_t)arg_val);
|
||||
break;
|
||||
|
||||
case U8G_COM_MSG_WRITE_SEQ: {
|
||||
uint8_t *ptr = (uint8_t*) arg_ptr;
|
||||
while (arg_val > 0) {
|
||||
spiSend(*ptr++);
|
||||
arg_val--;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case U8G_COM_MSG_WRITE_SEQ_P: {
|
||||
uint8_t *ptr = (uint8_t*) arg_ptr;
|
||||
while (arg_val > 0) {
|
||||
spiSend(*ptr++);
|
||||
arg_val--;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif // HAS_MARLINUI_U8GLIB
|
||||
|
||||
#endif // __SAM3X8E__
|
|
@ -0,0 +1,186 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Based on u8g_com_st7920_hw_spi.c
|
||||
*
|
||||
* Universal 8bit Graphics Library
|
||||
*
|
||||
* Copyright (c) 2011, olikraus@gmail.com
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef ARDUINO_ARCH_SAM
|
||||
|
||||
#include "../../../inc/MarlinConfigPre.h"
|
||||
|
||||
#if IS_U8GLIB_ST7920
|
||||
|
||||
#include "../../../inc/MarlinConfig.h"
|
||||
#include "../../shared/Delay.h"
|
||||
|
||||
#include <U8glib-HAL.h>
|
||||
|
||||
#include "u8g_com_HAL_DUE_sw_spi_shared.h"
|
||||
|
||||
#define SPISEND_SW_DUE u8g_spiSend_sw_DUE_mode_0
|
||||
|
||||
static uint8_t rs_last_state = 255;
|
||||
|
||||
static void u8g_com_DUE_st7920_write_byte_sw_spi(uint8_t rs, uint8_t val) {
|
||||
if (rs != rs_last_state) { // time to send a command/data byte
|
||||
rs_last_state = rs;
|
||||
SPISEND_SW_DUE(rs ? 0x0FA : 0x0F8); // Command or Data
|
||||
DELAY_US(40); // give the controller some time to process the data: 20 is bad, 30 is OK, 40 is safe
|
||||
}
|
||||
SPISEND_SW_DUE(val & 0xF0);
|
||||
SPISEND_SW_DUE(val << 4);
|
||||
}
|
||||
|
||||
uint8_t u8g_com_HAL_DUE_ST7920_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
|
||||
switch (msg) {
|
||||
case U8G_COM_MSG_INIT:
|
||||
SCK_pPio = g_APinDescription[u8g->pin_list[U8G_PI_SCK]].pPort;
|
||||
SCK_dwMask = g_APinDescription[u8g->pin_list[U8G_PI_SCK]].ulPin;
|
||||
MOSI_pPio = g_APinDescription[u8g->pin_list[U8G_PI_MOSI]].pPort;
|
||||
MOSI_dwMask = g_APinDescription[u8g->pin_list[U8G_PI_MOSI]].ulPin;
|
||||
|
||||
u8g_SetPILevel_DUE(u8g, U8G_PI_CS, 0);
|
||||
u8g_SetPIOutput_DUE(u8g, U8G_PI_CS);
|
||||
u8g_SetPILevel_DUE(u8g, U8G_PI_SCK, 0);
|
||||
u8g_SetPIOutput_DUE(u8g, U8G_PI_SCK);
|
||||
u8g_SetPILevel_DUE(u8g, U8G_PI_MOSI, 0);
|
||||
u8g_SetPIOutput_DUE(u8g, U8G_PI_MOSI);
|
||||
|
||||
SCK_pPio->PIO_CODR = SCK_dwMask; //SCK low - needed at power up but not after reset
|
||||
MOSI_pPio->PIO_CODR = MOSI_dwMask; //MOSI low - needed at power up but not after reset
|
||||
|
||||
u8g_Delay(5);
|
||||
|
||||
u8g->pin_list[U8G_PI_A0_STATE] = 0; /* initial RS state: command mode */
|
||||
break;
|
||||
|
||||
case U8G_COM_MSG_STOP:
|
||||
break;
|
||||
|
||||
case U8G_COM_MSG_RESET:
|
||||
if (U8G_PIN_NONE != u8g->pin_list[U8G_PI_RESET]) u8g_SetPILevel_DUE(u8g, U8G_PI_RESET, arg_val);
|
||||
break;
|
||||
|
||||
case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */
|
||||
u8g->pin_list[U8G_PI_A0_STATE] = arg_val;
|
||||
break;
|
||||
|
||||
case U8G_COM_MSG_CHIP_SELECT:
|
||||
if (U8G_PIN_NONE != u8g->pin_list[U8G_PI_CS])
|
||||
u8g_SetPILevel_DUE(u8g, U8G_PI_CS, arg_val); //note: the st7920 has an active high chip select
|
||||
break;
|
||||
|
||||
case U8G_COM_MSG_WRITE_BYTE:
|
||||
|
||||
u8g_com_DUE_st7920_write_byte_sw_spi(u8g->pin_list[U8G_PI_A0_STATE], arg_val);
|
||||
break;
|
||||
|
||||
case U8G_COM_MSG_WRITE_SEQ: {
|
||||
uint8_t *ptr = (uint8_t*) arg_ptr;
|
||||
while (arg_val > 0) {
|
||||
u8g_com_DUE_st7920_write_byte_sw_spi(u8g->pin_list[U8G_PI_A0_STATE], *ptr++);
|
||||
arg_val--;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case U8G_COM_MSG_WRITE_SEQ_P: {
|
||||
uint8_t *ptr = (uint8_t*) arg_ptr;
|
||||
while (arg_val > 0) {
|
||||
u8g_com_DUE_st7920_write_byte_sw_spi(u8g->pin_list[U8G_PI_A0_STATE], *ptr++);
|
||||
arg_val--;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if ENABLED(LIGHTWEIGHT_UI)
|
||||
#include "../../../lcd/marlinui.h"
|
||||
#include "../../shared/HAL_ST7920.h"
|
||||
|
||||
#define ST7920_CS_PIN LCD_PINS_RS
|
||||
|
||||
#if DOGM_SPI_DELAY_US > 0
|
||||
#define U8G_DELAY() DELAY_US(DOGM_SPI_DELAY_US)
|
||||
#else
|
||||
#define U8G_DELAY() DELAY_US(10)
|
||||
#endif
|
||||
|
||||
void ST7920_cs() {
|
||||
WRITE(ST7920_CS_PIN, HIGH);
|
||||
U8G_DELAY();
|
||||
}
|
||||
|
||||
void ST7920_ncs() {
|
||||
WRITE(ST7920_CS_PIN, LOW);
|
||||
}
|
||||
|
||||
void ST7920_set_cmd() {
|
||||
SPISEND_SW_DUE(0xF8);
|
||||
DELAY_US(40);
|
||||
}
|
||||
|
||||
void ST7920_set_dat() {
|
||||
SPISEND_SW_DUE(0xFA);
|
||||
DELAY_US(40);
|
||||
}
|
||||
|
||||
void ST7920_write_byte(const uint8_t val) {
|
||||
SPISEND_SW_DUE(val & 0xF0);
|
||||
SPISEND_SW_DUE(val << 4);
|
||||
}
|
||||
#endif // LIGHTWEIGHT_UI
|
||||
|
||||
#endif // IS_U8GLIB_ST7920
|
||||
#endif // ARDUINO_ARCH_SAM
|
|
@ -0,0 +1,145 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Based on u8g_com_std_sw_spi.c
|
||||
*
|
||||
* Universal 8bit Graphics Library
|
||||
*
|
||||
* Copyright (c) 2015, olikraus@gmail.com
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef ARDUINO_ARCH_SAM
|
||||
|
||||
#include "../../../inc/MarlinConfigPre.h"
|
||||
|
||||
#if HAS_MARLINUI_U8GLIB && !IS_U8GLIB_ST7920
|
||||
|
||||
#include "u8g_com_HAL_DUE_sw_spi_shared.h"
|
||||
|
||||
#include "../../shared/Marduino.h"
|
||||
#include "../../shared/Delay.h"
|
||||
|
||||
#include <U8glib-HAL.h>
|
||||
|
||||
#if ENABLED(FYSETC_MINI_12864)
|
||||
#define SPISEND_SW_DUE u8g_spiSend_sw_DUE_mode_3
|
||||
#else
|
||||
#define SPISEND_SW_DUE u8g_spiSend_sw_DUE_mode_0
|
||||
#endif
|
||||
|
||||
uint8_t u8g_com_HAL_DUE_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
|
||||
switch (msg) {
|
||||
case U8G_COM_MSG_INIT:
|
||||
SCK_pPio = g_APinDescription[u8g->pin_list[U8G_PI_SCK]].pPort;
|
||||
SCK_dwMask = g_APinDescription[u8g->pin_list[U8G_PI_SCK]].ulPin;
|
||||
MOSI_pPio = g_APinDescription[u8g->pin_list[U8G_PI_MOSI]].pPort;
|
||||
MOSI_dwMask = g_APinDescription[u8g->pin_list[U8G_PI_MOSI]].ulPin;
|
||||
u8g_SetPIOutput_DUE(u8g, U8G_PI_SCK);
|
||||
u8g_SetPIOutput_DUE(u8g, U8G_PI_MOSI);
|
||||
u8g_SetPIOutput_DUE(u8g, U8G_PI_CS);
|
||||
u8g_SetPIOutput_DUE(u8g, U8G_PI_A0);
|
||||
if (U8G_PIN_NONE != u8g->pin_list[U8G_PI_RESET]) u8g_SetPIOutput_DUE(u8g, U8G_PI_RESET);
|
||||
u8g_SetPILevel_DUE(u8g, U8G_PI_SCK, 0);
|
||||
u8g_SetPILevel_DUE(u8g, U8G_PI_MOSI, 0);
|
||||
break;
|
||||
|
||||
case U8G_COM_MSG_STOP:
|
||||
break;
|
||||
|
||||
case U8G_COM_MSG_RESET:
|
||||
if (U8G_PIN_NONE != u8g->pin_list[U8G_PI_RESET]) u8g_SetPILevel_DUE(u8g, U8G_PI_RESET, arg_val);
|
||||
break;
|
||||
|
||||
case U8G_COM_MSG_CHIP_SELECT:
|
||||
#if ENABLED(FYSETC_MINI_12864) // LCD SPI is running mode 3 while SD card is running mode 0
|
||||
if (arg_val) { // SCK idle state needs to be set to the proper idle state before
|
||||
// the next chip select goes active
|
||||
u8g_SetPILevel_DUE(u8g, U8G_PI_SCK, 1); //set SCK to mode 3 idle state before CS goes active
|
||||
u8g_SetPILevel_DUE(u8g, U8G_PI_CS, LOW);
|
||||
}
|
||||
else {
|
||||
u8g_SetPILevel_DUE(u8g, U8G_PI_CS, HIGH);
|
||||
u8g_SetPILevel_DUE(u8g, U8G_PI_SCK, 0); //set SCK to mode 0 idle state after CS goes inactive
|
||||
}
|
||||
#else
|
||||
u8g_SetPILevel_DUE(u8g, U8G_PI_CS, !arg_val);
|
||||
#endif
|
||||
break;
|
||||
|
||||
case U8G_COM_MSG_WRITE_BYTE:
|
||||
SPISEND_SW_DUE(arg_val);
|
||||
break;
|
||||
|
||||
case U8G_COM_MSG_WRITE_SEQ: {
|
||||
uint8_t *ptr = (uint8_t *)arg_ptr;
|
||||
while (arg_val > 0) {
|
||||
SPISEND_SW_DUE(*ptr++);
|
||||
arg_val--;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case U8G_COM_MSG_WRITE_SEQ_P: {
|
||||
uint8_t *ptr = (uint8_t *)arg_ptr;
|
||||
while (arg_val > 0) {
|
||||
SPISEND_SW_DUE(u8g_pgm_read(ptr));
|
||||
ptr++;
|
||||
arg_val--;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case U8G_COM_MSG_ADDRESS: /* define cmd (arg_val = 0) or data mode (arg_val = 1) */
|
||||
u8g_SetPILevel_DUE(u8g, U8G_PI_A0, arg_val);
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif // HAS_MARLINUI_U8GLIB && !IS_U8GLIB_ST7920
|
||||
#endif // ARDUINO_ARCH_SAM
|
|
@ -0,0 +1,113 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Based on u8g_com_st7920_hw_spi.c
|
||||
*
|
||||
* Universal 8bit Graphics Library
|
||||
*
|
||||
* Copyright (c) 2011, olikraus@gmail.com
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice, this
|
||||
* list of conditions and the following disclaimer in the documentation and/or other
|
||||
* materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
||||
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef ARDUINO_ARCH_SAM
|
||||
|
||||
#include "../../../inc/MarlinConfigPre.h"
|
||||
|
||||
#if HAS_MARLINUI_U8GLIB
|
||||
|
||||
#include "../../../inc/MarlinConfig.h"
|
||||
#include "../../shared/Delay.h"
|
||||
|
||||
#include <U8glib-HAL.h>
|
||||
|
||||
#include "u8g_com_HAL_DUE_sw_spi_shared.h"
|
||||
|
||||
void u8g_SetPIOutput_DUE(u8g_t *u8g, uint8_t pin_index) {
|
||||
PIO_Configure(g_APinDescription[u8g->pin_list[pin_index]].pPort, PIO_OUTPUT_1,
|
||||
g_APinDescription[u8g->pin_list[pin_index]].ulPin, g_APinDescription[u8g->pin_list[pin_index]].ulPinConfiguration); // OUTPUT
|
||||
}
|
||||
|
||||
void u8g_SetPILevel_DUE(u8g_t *u8g, uint8_t pin_index, uint8_t level) {
|
||||
volatile Pio* port = g_APinDescription[u8g->pin_list[pin_index]].pPort;
|
||||
uint32_t mask = g_APinDescription[u8g->pin_list[pin_index]].ulPin;
|
||||
if (level) port->PIO_SODR = mask; else port->PIO_CODR = mask;
|
||||
}
|
||||
|
||||
Pio *SCK_pPio, *MOSI_pPio;
|
||||
uint32_t SCK_dwMask, MOSI_dwMask;
|
||||
|
||||
void u8g_spiSend_sw_DUE_mode_0(uint8_t val) { // 3MHz
|
||||
for (uint8_t i = 0; i < 8; ++i) {
|
||||
if (val & 0x80)
|
||||
MOSI_pPio->PIO_SODR = MOSI_dwMask;
|
||||
else
|
||||
MOSI_pPio->PIO_CODR = MOSI_dwMask;
|
||||
DELAY_NS(48);
|
||||
SCK_pPio->PIO_SODR = SCK_dwMask;
|
||||
DELAY_NS(905);
|
||||
val <<= 1;
|
||||
SCK_pPio->PIO_CODR = SCK_dwMask;
|
||||
}
|
||||
}
|
||||
|
||||
void u8g_spiSend_sw_DUE_mode_3(uint8_t val) { // 3.5MHz
|
||||
for (uint8_t i = 0; i < 8; ++i) {
|
||||
SCK_pPio->PIO_CODR = SCK_dwMask;
|
||||
DELAY_NS(50);
|
||||
if (val & 0x80)
|
||||
MOSI_pPio->PIO_SODR = MOSI_dwMask;
|
||||
else
|
||||
MOSI_pPio->PIO_CODR = MOSI_dwMask;
|
||||
val <<= 1;
|
||||
DELAY_NS(10);
|
||||
SCK_pPio->PIO_SODR = SCK_dwMask;
|
||||
DELAY_NS(70);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // HAS_MARLINUI_U8GLIB
|
||||
#endif // ARDUINO_ARCH_SAM
|
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "../../../inc/MarlinConfigPre.h"
|
||||
#include "../../shared/Marduino.h"
|
||||
#include <U8glib-HAL.h>
|
||||
|
||||
void u8g_SetPIOutput_DUE(u8g_t *u8g, uint8_t pin_index);
|
||||
void u8g_SetPILevel_DUE(u8g_t *u8g, uint8_t pin_index, uint8_t level);
|
||||
|
||||
void u8g_spiSend_sw_DUE_mode_0(uint8_t val);
|
||||
void u8g_spiSend_sw_DUE_mode_3(uint8_t val);
|
||||
|
||||
extern Pio *SCK_pPio, *MOSI_pPio;
|
||||
extern uint32_t SCK_dwMask, MOSI_dwMask;
|
|
@ -0,0 +1,997 @@
|
|||
/**
|
||||
* 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"
|
||||
|
||||
#if ENABLED(FLASH_EEPROM_EMULATION)
|
||||
|
||||
/* EEPROM emulation over flash with reduced wear
|
||||
*
|
||||
* We will use 2 contiguous groups of pages as main and alternate.
|
||||
* We want an structure that allows to read as fast as possible,
|
||||
* without the need of scanning the whole FLASH memory.
|
||||
*
|
||||
* FLASH bits default erased state is 1, and can be set to 0
|
||||
* on a per bit basis. To reset them to 1, a full page erase
|
||||
* is needed.
|
||||
*
|
||||
* Values are stored as differences that should be applied to a
|
||||
* completely erased EEPROM (filled with 0xFFs). We just encode
|
||||
* the starting address of the values to change, the length of
|
||||
* the block of new values, and the values themselves. All diffs
|
||||
* are accumulated into a RAM buffer, compacted into the least
|
||||
* amount of non overlapping diffs possible and sorted by starting
|
||||
* address before being saved into the next available page of FLASH
|
||||
* of the current group.
|
||||
* Once the current group is completely full, we compact it and save
|
||||
* it into the other group, then erase the current group and switch
|
||||
* to that new group and set it as current.
|
||||
*
|
||||
* The FLASH endurance is about 1/10 ... 1/100 of an EEPROM
|
||||
* endurance, but EEPROM endurance is specified per byte, not
|
||||
* per page. We can't emulate EE endurance with FLASH for all
|
||||
* bytes, but we can emulate endurance for a given percent of
|
||||
* bytes.
|
||||
*/
|
||||
|
||||
//#define EE_EMU_DEBUG
|
||||
|
||||
#define EEPROMSize 4096
|
||||
#define PagesPerGroup 128
|
||||
#define GroupCount 2
|
||||
#define PageSize 256U
|
||||
|
||||
/* Flash storage */
|
||||
typedef struct FLASH_SECTOR {
|
||||
uint8_t page[PageSize];
|
||||
} FLASH_SECTOR_T;
|
||||
|
||||
#define PAGE_FILL \
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, \
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, \
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, \
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, \
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, \
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, \
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, \
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, \
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, \
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, \
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, \
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, \
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, \
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, \
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, \
|
||||
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
|
||||
|
||||
#define FLASH_INIT_FILL \
|
||||
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
||||
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
||||
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
||||
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
||||
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
||||
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
||||
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
||||
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
||||
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
||||
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
||||
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
||||
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
||||
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
||||
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
||||
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
||||
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
||||
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
||||
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
||||
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
||||
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
||||
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
||||
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
||||
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
||||
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
||||
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
||||
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
||||
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
||||
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
||||
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
||||
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
||||
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL, \
|
||||
PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL,PAGE_FILL
|
||||
|
||||
/* This is the FLASH area used to emulate a 2Kbyte EEPROM -- We need this buffer aligned
|
||||
to a 256 byte boundary. */
|
||||
static const uint8_t flashStorage[PagesPerGroup * GroupCount * PageSize] __attribute__ ((aligned (PageSize))) = { FLASH_INIT_FILL };
|
||||
|
||||
/* Get the address of an specific page */
|
||||
static const FLASH_SECTOR_T* getFlashStorage(int page) {
|
||||
return (const FLASH_SECTOR_T*)&flashStorage[page*PageSize];
|
||||
}
|
||||
|
||||
static uint8_t buffer[256] = {0}, // The RAM buffer to accumulate writes
|
||||
curPage = 0, // Current FLASH page inside the group
|
||||
curGroup = 0xFF; // Current FLASH group
|
||||
|
||||
#define DEBUG_OUT ENABLED(EE_EMU_DEBUG)
|
||||
#include "../../core/debug_out.h"
|
||||
|
||||
static void ee_Dump(const int page, const void *data) {
|
||||
|
||||
#ifdef EE_EMU_DEBUG
|
||||
|
||||
const uint8_t *c = (const uint8_t*) data;
|
||||
char buffer[80];
|
||||
|
||||
sprintf_P(buffer, PSTR("Page: %d (0x%04x)\n"), page, page);
|
||||
DEBUG_ECHO(buffer);
|
||||
|
||||
char* p = &buffer[0];
|
||||
for (int i = 0; i< PageSize; ++i) {
|
||||
if ((i & 0xF) == 0) p += sprintf_P(p, PSTR("%04x] "), i);
|
||||
|
||||
p += sprintf_P(p, PSTR(" %02x"), c[i]);
|
||||
if ((i & 0xF) == 0xF) {
|
||||
*p++ = '\n';
|
||||
*p = 0;
|
||||
DEBUG_ECHO(buffer);
|
||||
p = &buffer[0];
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
UNUSED(page);
|
||||
UNUSED(data);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Flash Writing Protection Key */
|
||||
#define FWP_KEY 0x5Au
|
||||
|
||||
#if SAM4S_SERIES
|
||||
#define EEFC_FCR_FCMD(value) \
|
||||
((EEFC_FCR_FCMD_Msk & ((value) << EEFC_FCR_FCMD_Pos)))
|
||||
#define EEFC_ERROR_FLAGS (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE | EEFC_FSR_FLERR)
|
||||
#else
|
||||
#define EEFC_ERROR_FLAGS (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Writes the contents of the specified page (no previous erase)
|
||||
* @param page (page #)
|
||||
* @param data (pointer to the data buffer)
|
||||
*/
|
||||
__attribute__ ((long_call, section (".ramfunc")))
|
||||
static bool ee_PageWrite(uint16_t page, const void *data) {
|
||||
|
||||
uint16_t i;
|
||||
uint32_t addrflash = uint32_t(getFlashStorage(page));
|
||||
|
||||
// Read the flash contents
|
||||
uint32_t pageContents[PageSize>>2];
|
||||
memcpy(pageContents, (void*)addrflash, PageSize);
|
||||
|
||||
// We ONLY want to toggle bits that have changed, and that have changed to 0.
|
||||
// SAM3X8E tends to destroy contiguous bits if reprogrammed without erasing, so
|
||||
// we try by all means to avoid this. That is why it says: "The Partial
|
||||
// Programming mode works only with 128-bit (or higher) boundaries. It cannot
|
||||
// be used with boundaries lower than 128 bits (8, 16 or 32-bit for example)."
|
||||
// All bits that did not change, set them to 1.
|
||||
for (i = 0; i <PageSize >> 2; i++)
|
||||
pageContents[i] = (((uint32_t*)data)[i]) | (~(pageContents[i] ^ ((uint32_t*)data)[i]));
|
||||
|
||||
DEBUG_ECHO_MSG("EEPROM PageWrite ", page);
|
||||
DEBUG_ECHOLNPGM(" in FLASH address ", (uint32_t)addrflash);
|
||||
DEBUG_ECHOLNPGM(" base address ", (uint32_t)getFlashStorage(0));
|
||||
DEBUG_FLUSH();
|
||||
|
||||
// Get the page relative to the start of the EFC controller, and the EFC controller to use
|
||||
Efc *efc;
|
||||
uint16_t fpage;
|
||||
if (addrflash >= IFLASH1_ADDR) {
|
||||
efc = EFC1;
|
||||
fpage = (addrflash - IFLASH1_ADDR) / IFLASH1_PAGE_SIZE;
|
||||
}
|
||||
else {
|
||||
efc = EFC0;
|
||||
fpage = (addrflash - IFLASH0_ADDR) / IFLASH0_PAGE_SIZE;
|
||||
}
|
||||
|
||||
// Get the page that must be unlocked, then locked
|
||||
uint16_t lpage = fpage & (~((IFLASH0_LOCK_REGION_SIZE / IFLASH0_PAGE_SIZE) - 1));
|
||||
|
||||
// Disable all interrupts
|
||||
__disable_irq();
|
||||
|
||||
// Get the FLASH wait states
|
||||
uint32_t orgWS = (efc->EEFC_FMR & EEFC_FMR_FWS_Msk) >> EEFC_FMR_FWS_Pos;
|
||||
|
||||
// Set wait states to 6 (SAM errata)
|
||||
efc->EEFC_FMR = (efc->EEFC_FMR & (~EEFC_FMR_FWS_Msk)) | EEFC_FMR_FWS(6);
|
||||
|
||||
// Unlock the flash page
|
||||
uint32_t status;
|
||||
efc->EEFC_FCR = EEFC_FCR_FKEY(FWP_KEY) | EEFC_FCR_FARG(lpage) | EEFC_FCR_FCMD(EFC_FCMD_CLB);
|
||||
while (((status = efc->EEFC_FSR) & EEFC_FSR_FRDY) != EEFC_FSR_FRDY) {
|
||||
// force compiler to not optimize this -- NOPs don't work!
|
||||
__asm__ __volatile__("");
|
||||
};
|
||||
|
||||
if ((status & EEFC_ERROR_FLAGS) != 0) {
|
||||
|
||||
// Restore original wait states
|
||||
efc->EEFC_FMR = (efc->EEFC_FMR & (~EEFC_FMR_FWS_Msk)) | EEFC_FMR_FWS(orgWS);
|
||||
|
||||
// Reenable interrupts
|
||||
__enable_irq();
|
||||
|
||||
DEBUG_ECHO_MSG("EEPROM Unlock failure for page ", page);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Write page and lock: Writing 8-bit and 16-bit data is not allowed and may lead to unpredictable data corruption.
|
||||
const uint32_t * aligned_src = (const uint32_t *) &pageContents[0]; /*data;*/
|
||||
uint32_t * p_aligned_dest = (uint32_t *) addrflash;
|
||||
for (i = 0; i < (IFLASH0_PAGE_SIZE / sizeof(uint32_t)); ++i) {
|
||||
*p_aligned_dest++ = *aligned_src++;
|
||||
}
|
||||
efc->EEFC_FCR = EEFC_FCR_FKEY(FWP_KEY) | EEFC_FCR_FARG(fpage) | EEFC_FCR_FCMD(EFC_FCMD_WPL);
|
||||
while (((status = efc->EEFC_FSR) & EEFC_FSR_FRDY) != EEFC_FSR_FRDY) {
|
||||
// force compiler to not optimize this -- NOPs don't work!
|
||||
__asm__ __volatile__("");
|
||||
};
|
||||
|
||||
if ((status & EEFC_ERROR_FLAGS) != 0) {
|
||||
|
||||
// Restore original wait states
|
||||
efc->EEFC_FMR = (efc->EEFC_FMR & (~EEFC_FMR_FWS_Msk)) | EEFC_FMR_FWS(orgWS);
|
||||
|
||||
// Reenable interrupts
|
||||
__enable_irq();
|
||||
|
||||
DEBUG_ECHO_MSG("EEPROM Write failure for page ", page);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Restore original wait states
|
||||
efc->EEFC_FMR = (efc->EEFC_FMR & (~EEFC_FMR_FWS_Msk)) | EEFC_FMR_FWS(orgWS);
|
||||
|
||||
// Reenable interrupts
|
||||
__enable_irq();
|
||||
|
||||
// Compare contents
|
||||
if (memcmp(getFlashStorage(page),data,PageSize)) {
|
||||
|
||||
#ifdef EE_EMU_DEBUG
|
||||
DEBUG_ECHO_MSG("EEPROM Verify Write failure for page ", page);
|
||||
|
||||
ee_Dump( page, (uint32_t *)addrflash);
|
||||
ee_Dump(-page, data);
|
||||
|
||||
// Calculate count of changed bits
|
||||
uint32_t *p1 = (uint32_t*)addrflash;
|
||||
uint32_t *p2 = (uint32_t*)data;
|
||||
int count = 0;
|
||||
for (i = 0; i < PageSize >> 2; i++) {
|
||||
if (p1[i] != p2[i]) {
|
||||
uint32_t delta = p1[i] ^ p2[i];
|
||||
while (delta) {
|
||||
if ((delta&1) != 0)
|
||||
count++;
|
||||
delta >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
DEBUG_ECHOLNPGM("--> Differing bits: ", count);
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Erases the contents of the specified page
|
||||
* @param page (page #)
|
||||
*/
|
||||
__attribute__ ((long_call, section (".ramfunc")))
|
||||
static bool ee_PageErase(uint16_t page) {
|
||||
|
||||
uint16_t i;
|
||||
uint32_t addrflash = uint32_t(getFlashStorage(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();
|
||||
|
||||
// Get the page relative to the start of the EFC controller, and the EFC controller to use
|
||||
Efc *efc;
|
||||
uint16_t fpage;
|
||||
if (addrflash >= IFLASH1_ADDR) {
|
||||
efc = EFC1;
|
||||
fpage = (addrflash - IFLASH1_ADDR) / IFLASH1_PAGE_SIZE;
|
||||
}
|
||||
else {
|
||||
efc = EFC0;
|
||||
fpage = (addrflash - IFLASH0_ADDR) / IFLASH0_PAGE_SIZE;
|
||||
}
|
||||
|
||||
// Get the page that must be unlocked, then locked
|
||||
uint16_t lpage = fpage & (~((IFLASH0_LOCK_REGION_SIZE / IFLASH0_PAGE_SIZE) - 1));
|
||||
|
||||
// Disable all interrupts
|
||||
__disable_irq();
|
||||
|
||||
// Get the FLASH wait states
|
||||
uint32_t orgWS = (efc->EEFC_FMR & EEFC_FMR_FWS_Msk) >> EEFC_FMR_FWS_Pos;
|
||||
|
||||
// Set wait states to 6 (SAM errata)
|
||||
efc->EEFC_FMR = (efc->EEFC_FMR & (~EEFC_FMR_FWS_Msk)) | EEFC_FMR_FWS(6);
|
||||
|
||||
// Unlock the flash page
|
||||
uint32_t status;
|
||||
efc->EEFC_FCR = EEFC_FCR_FKEY(FWP_KEY) | EEFC_FCR_FARG(lpage) | EEFC_FCR_FCMD(EFC_FCMD_CLB);
|
||||
while (((status = efc->EEFC_FSR) & EEFC_FSR_FRDY) != EEFC_FSR_FRDY) {
|
||||
// force compiler to not optimize this -- NOPs don't work!
|
||||
__asm__ __volatile__("");
|
||||
};
|
||||
if ((status & EEFC_ERROR_FLAGS) != 0) {
|
||||
|
||||
// Restore original wait states
|
||||
efc->EEFC_FMR = (efc->EEFC_FMR & (~EEFC_FMR_FWS_Msk)) | EEFC_FMR_FWS(orgWS);
|
||||
|
||||
// Reenable interrupts
|
||||
__enable_irq();
|
||||
|
||||
DEBUG_ECHO_MSG("EEPROM Unlock failure for page ",page);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Erase Write page and lock: Writing 8-bit and 16-bit data is not allowed and may lead to unpredictable data corruption.
|
||||
uint32_t * p_aligned_dest = (uint32_t *) addrflash;
|
||||
for (i = 0; i < (IFLASH0_PAGE_SIZE / sizeof(uint32_t)); ++i) {
|
||||
*p_aligned_dest++ = 0xFFFFFFFF;
|
||||
}
|
||||
efc->EEFC_FCR = EEFC_FCR_FKEY(FWP_KEY) | EEFC_FCR_FARG(fpage) | EEFC_FCR_FCMD(EFC_FCMD_EWPL);
|
||||
while (((status = efc->EEFC_FSR) & EEFC_FSR_FRDY) != EEFC_FSR_FRDY) {
|
||||
// force compiler to not optimize this -- NOPs don't work!
|
||||
__asm__ __volatile__("");
|
||||
};
|
||||
if ((status & EEFC_ERROR_FLAGS) != 0) {
|
||||
|
||||
// Restore original wait states
|
||||
efc->EEFC_FMR = (efc->EEFC_FMR & (~EEFC_FMR_FWS_Msk)) | EEFC_FMR_FWS(orgWS);
|
||||
|
||||
// Reenable interrupts
|
||||
__enable_irq();
|
||||
|
||||
DEBUG_ECHO_MSG("EEPROM Erase failure for page ",page);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Restore original wait states
|
||||
efc->EEFC_FMR = (efc->EEFC_FMR & (~EEFC_FMR_FWS_Msk)) | EEFC_FMR_FWS(orgWS);
|
||||
|
||||
// Reenable interrupts
|
||||
__enable_irq();
|
||||
|
||||
// Check erase
|
||||
uint32_t * aligned_src = (uint32_t *) addrflash;
|
||||
for (i = 0; i < PageSize >> 2; i++) {
|
||||
if (*aligned_src++ != 0xFFFFFFFF) {
|
||||
DEBUG_ECHO_MSG("EEPROM Verify Erase failure for page ",page);
|
||||
ee_Dump(page, (uint32_t *)addrflash);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint8_t ee_Read(uint32_t address, bool excludeRAMBuffer=false) {
|
||||
|
||||
uint32_t baddr;
|
||||
uint32_t blen;
|
||||
|
||||
// If we were requested an address outside of the emulated range, fail now
|
||||
if (address >= EEPROMSize)
|
||||
return false;
|
||||
|
||||
// Check that the value is not contained in the RAM buffer
|
||||
if (!excludeRAMBuffer) {
|
||||
uint16_t i = 0;
|
||||
while (i <= (PageSize - 4)) { /* (PageSize - 4) because otherwise, there is not enough room for data and headers */
|
||||
|
||||
// Get the address of the block
|
||||
baddr = buffer[i] | (buffer[i + 1] << 8);
|
||||
|
||||
// Get the length of the block
|
||||
blen = buffer[i + 2];
|
||||
|
||||
// If we reach the end of the list, break loop
|
||||
if (blen == 0xFF)
|
||||
break;
|
||||
|
||||
// Check if data is contained in this block
|
||||
if (address >= baddr &&
|
||||
address < (baddr + blen)) {
|
||||
|
||||
// Yes, it is contained. Return it!
|
||||
return buffer[i + 3 + address - baddr];
|
||||
}
|
||||
|
||||
// As blocks are always sorted, if the starting address of this block is higher
|
||||
// than the address we are looking for, break loop now - We wont find the value
|
||||
// associated to the address
|
||||
if (baddr > address)
|
||||
break;
|
||||
|
||||
// Jump to the next block
|
||||
i += 3 + blen;
|
||||
}
|
||||
}
|
||||
|
||||
// It is NOT on the RAM buffer. It could be stored in FLASH. We are
|
||||
// ensured on a given FLASH page, address contents are never repeated
|
||||
// but on different pages, there is no such warranty, so we must go
|
||||
// backwards from the last written FLASH page to the first one.
|
||||
for (int page = curPage - 1; page >= 0; --page) {
|
||||
|
||||
// Get a pointer to the flash page
|
||||
uint8_t *pflash = (uint8_t*)getFlashStorage(page + curGroup * PagesPerGroup);
|
||||
|
||||
uint16_t i = 0;
|
||||
while (i <= (PageSize - 4)) { /* (PageSize - 4) because otherwise, there is not enough room for data and headers */
|
||||
|
||||
// Get the address of the block
|
||||
baddr = pflash[i] | (pflash[i + 1] << 8);
|
||||
|
||||
// Get the length of the block
|
||||
blen = pflash[i + 2];
|
||||
|
||||
// If we reach the end of the list, break loop
|
||||
if (blen == 0xFF)
|
||||
break;
|
||||
|
||||
// Check if data is contained in this block
|
||||
if (address >= baddr && address < (baddr + blen))
|
||||
return pflash[i + 3 + address - baddr]; // Yes, it is contained. Return it!
|
||||
|
||||
// As blocks are always sorted, if the starting address of this block is higher
|
||||
// than the address we are looking for, break loop now - We wont find the value
|
||||
// associated to the address
|
||||
if (baddr > address) break;
|
||||
|
||||
// Jump to the next block
|
||||
i += 3 + blen;
|
||||
}
|
||||
}
|
||||
|
||||
// If reached here, value is not stored, so return its default value
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
static uint32_t ee_GetAddrRange(uint32_t address, bool excludeRAMBuffer=false) {
|
||||
uint32_t baddr,
|
||||
blen,
|
||||
nextAddr = 0xFFFF,
|
||||
nextRange = 0;
|
||||
|
||||
// Check that the value is not contained in the RAM buffer
|
||||
if (!excludeRAMBuffer) {
|
||||
uint16_t i = 0;
|
||||
while (i <= (PageSize - 4)) { /* (PageSize - 4) because otherwise, there is not enough room for data and headers */
|
||||
|
||||
// Get the address of the block
|
||||
baddr = buffer[i] | (buffer[i + 1] << 8);
|
||||
|
||||
// Get the length of the block
|
||||
blen = buffer[i + 2];
|
||||
|
||||
// If we reach the end of the list, break loop
|
||||
if (blen == 0xFF) break;
|
||||
|
||||
// Check if address and address + 1 is contained in this block
|
||||
if (address >= baddr && address < (baddr + blen))
|
||||
return address | ((blen - address + baddr) << 16); // Yes, it is contained. Return it!
|
||||
|
||||
// Otherwise, check if we can use it as a limit
|
||||
if (baddr > address && baddr < nextAddr) {
|
||||
nextAddr = baddr;
|
||||
nextRange = blen;
|
||||
}
|
||||
|
||||
// As blocks are always sorted, if the starting address of this block is higher
|
||||
// than the address we are looking for, break loop now - We wont find the value
|
||||
// associated to the address
|
||||
if (baddr > address) break;
|
||||
|
||||
// Jump to the next block
|
||||
i += 3 + blen;
|
||||
}
|
||||
}
|
||||
|
||||
// It is NOT on the RAM buffer. It could be stored in FLASH. We are
|
||||
// ensured on a given FLASH page, address contents are never repeated
|
||||
// but on different pages, there is no such warranty, so we must go
|
||||
// backwards from the last written FLASH page to the first one.
|
||||
for (int page = curPage - 1; page >= 0; --page) {
|
||||
|
||||
// Get a pointer to the flash page
|
||||
uint8_t *pflash = (uint8_t*)getFlashStorage(page + curGroup * PagesPerGroup);
|
||||
|
||||
uint16_t i = 0;
|
||||
while (i <= (PageSize - 4)) { /* (PageSize - 4) because otherwise, there is not enough room for data and headers */
|
||||
|
||||
// Get the address of the block
|
||||
baddr = pflash[i] | (pflash[i + 1] << 8);
|
||||
|
||||
// Get the length of the block
|
||||
blen = pflash[i + 2];
|
||||
|
||||
// If we reach the end of the list, break loop
|
||||
if (blen == 0xFF) break;
|
||||
|
||||
// Check if data is contained in this block
|
||||
if (address >= baddr && address < (baddr + blen))
|
||||
return address | ((blen - address + baddr) << 16); // Yes, it is contained. Return it!
|
||||
|
||||
// Otherwise, check if we can use it as a limit
|
||||
if (baddr > address && baddr < nextAddr) {
|
||||
nextAddr = baddr;
|
||||
nextRange = blen;
|
||||
}
|
||||
|
||||
// As blocks are always sorted, if the starting address of this block is higher
|
||||
// than the address we are looking for, break loop now - We wont find the value
|
||||
// associated to the address
|
||||
if (baddr > address) break;
|
||||
|
||||
// Jump to the next block
|
||||
i += 3 + blen;
|
||||
}
|
||||
}
|
||||
|
||||
// If reached here, we will return the next valid address
|
||||
return nextAddr | (nextRange << 16);
|
||||
}
|
||||
|
||||
static bool ee_IsPageClean(int page) {
|
||||
uint32_t *pflash = (uint32_t*) getFlashStorage(page);
|
||||
for (uint16_t i = 0; i < (PageSize >> 2); ++i)
|
||||
if (*pflash++ != 0xFFFFFFFF) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ee_Flush(uint32_t overrideAddress = 0xFFFFFFFF, uint8_t overrideData=0xFF) {
|
||||
|
||||
// Check if RAM buffer has something to be written
|
||||
bool isEmpty = true;
|
||||
uint32_t *p = (uint32_t*) &buffer[0];
|
||||
for (uint16_t j = 0; j < (PageSize >> 2); j++) {
|
||||
if (*p++ != 0xFFFFFFFF) {
|
||||
isEmpty = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If something has to be written, do so!
|
||||
if (!isEmpty) {
|
||||
|
||||
// Write the current ram buffer into FLASH
|
||||
ee_PageWrite(curPage + curGroup * PagesPerGroup, buffer);
|
||||
|
||||
// Clear the RAM buffer
|
||||
memset(buffer, 0xFF, sizeof(buffer));
|
||||
|
||||
// Increment the page to use the next time
|
||||
++curPage;
|
||||
}
|
||||
|
||||
// Did we reach the maximum count of available pages per group for storage ?
|
||||
if (curPage < PagesPerGroup) {
|
||||
|
||||
// Do we have an override address ?
|
||||
if (overrideAddress < EEPROMSize) {
|
||||
|
||||
// Yes, just store the value into the RAM buffer
|
||||
buffer[0] = overrideAddress & 0xFF;
|
||||
buffer[0 + 1] = (overrideAddress >> 8) & 0xFF;
|
||||
buffer[0 + 2] = 1;
|
||||
buffer[0 + 3] = overrideData;
|
||||
}
|
||||
|
||||
// Done!
|
||||
return true;
|
||||
}
|
||||
|
||||
// We have no space left on the current group - We must compact the values
|
||||
uint16_t i = 0;
|
||||
|
||||
// Compute the next group to use
|
||||
int curwPage = 0, curwGroup = curGroup + 1;
|
||||
if (curwGroup >= GroupCount) curwGroup = 0;
|
||||
|
||||
uint32_t rdAddr = 0;
|
||||
do {
|
||||
|
||||
// Get the next valid range
|
||||
uint32_t addrRange = ee_GetAddrRange(rdAddr, true);
|
||||
|
||||
// Make sure not to skip the override address, if specified
|
||||
int rdRange;
|
||||
if (overrideAddress < EEPROMSize &&
|
||||
rdAddr <= overrideAddress &&
|
||||
(addrRange & 0xFFFF) > overrideAddress) {
|
||||
|
||||
rdAddr = overrideAddress;
|
||||
rdRange = 1;
|
||||
}
|
||||
else {
|
||||
rdAddr = addrRange & 0xFFFF;
|
||||
rdRange = addrRange >> 16;
|
||||
}
|
||||
|
||||
// If no range, break loop
|
||||
if (rdRange == 0)
|
||||
break;
|
||||
|
||||
do {
|
||||
|
||||
// Get the value
|
||||
uint8_t rdValue = overrideAddress == rdAddr ? overrideData : ee_Read(rdAddr, true);
|
||||
|
||||
// Do not bother storing default values
|
||||
if (rdValue != 0xFF) {
|
||||
|
||||
// If we have room, add it to the buffer
|
||||
if (buffer[i + 2] == 0xFF) {
|
||||
|
||||
// Uninitialized buffer, just add it!
|
||||
buffer[i] = rdAddr & 0xFF;
|
||||
buffer[i + 1] = (rdAddr >> 8) & 0xFF;
|
||||
buffer[i + 2] = 1;
|
||||
buffer[i + 3] = rdValue;
|
||||
|
||||
}
|
||||
else {
|
||||
// Buffer already has contents. Check if we can extend it
|
||||
|
||||
// Get the address of the block
|
||||
uint32_t baddr = buffer[i] | (buffer[i + 1] << 8);
|
||||
|
||||
// Get the length of the block
|
||||
uint32_t blen = buffer[i + 2];
|
||||
|
||||
// Can we expand it ?
|
||||
if (rdAddr == (baddr + blen) &&
|
||||
i < (PageSize - 4) && /* This block has a chance to contain data AND */
|
||||
buffer[i + 2] < (PageSize - i - 3)) {/* There is room for this block to be expanded */
|
||||
|
||||
// Yes, do it
|
||||
++buffer[i + 2];
|
||||
|
||||
// And store the value
|
||||
buffer[i + 3 + rdAddr - baddr] = rdValue;
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
// No, we can't expand it - Skip the existing block
|
||||
i += 3 + blen;
|
||||
|
||||
// Can we create a new slot ?
|
||||
if (i > (PageSize - 4)) {
|
||||
|
||||
// Not enough space - Write the current buffer to FLASH
|
||||
ee_PageWrite(curwPage + curwGroup * PagesPerGroup, buffer);
|
||||
|
||||
// Advance write page (as we are compacting, should never overflow!)
|
||||
++curwPage;
|
||||
|
||||
// Clear RAM buffer
|
||||
memset(buffer, 0xFF, sizeof(buffer));
|
||||
|
||||
// Start fresh */
|
||||
i = 0;
|
||||
}
|
||||
|
||||
// Enough space, add the new block
|
||||
buffer[i] = rdAddr & 0xFF;
|
||||
buffer[i + 1] = (rdAddr >> 8) & 0xFF;
|
||||
buffer[i + 2] = 1;
|
||||
buffer[i + 3] = rdValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Go to the next address
|
||||
++rdAddr;
|
||||
|
||||
// Repeat for bytes of this range
|
||||
} while (--rdRange);
|
||||
|
||||
// Repeat until we run out of ranges
|
||||
} while (rdAddr < EEPROMSize);
|
||||
|
||||
// We must erase the previous group, in preparation for the next swap
|
||||
for (int page = 0; page < curPage; page++) {
|
||||
ee_PageErase(page + curGroup * PagesPerGroup);
|
||||
}
|
||||
|
||||
// Finally, Now the active group is the created new group
|
||||
curGroup = curwGroup;
|
||||
curPage = curwPage;
|
||||
|
||||
// Done!
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool ee_Write(uint32_t address, uint8_t data) {
|
||||
|
||||
// If we were requested an address outside of the emulated range, fail now
|
||||
if (address >= EEPROMSize) return false;
|
||||
|
||||
// Lets check if we have a block with that data previously defined. Block
|
||||
// start addresses are always sorted in ascending order
|
||||
uint16_t i = 0;
|
||||
while (i <= (PageSize - 4)) { /* (PageSize - 4) because otherwise, there is not enough room for data and headers */
|
||||
|
||||
// Get the address of the block
|
||||
uint32_t baddr = buffer[i] | (buffer[i + 1] << 8);
|
||||
|
||||
// Get the length of the block
|
||||
uint32_t blen = buffer[i + 2];
|
||||
|
||||
// If we reach the end of the list, break loop
|
||||
if (blen == 0xFF)
|
||||
break;
|
||||
|
||||
// Check if data is contained in this block
|
||||
if (address >= baddr &&
|
||||
address < (baddr + blen)) {
|
||||
|
||||
// Yes, it is contained. Just modify it
|
||||
buffer[i + 3 + address - baddr] = data;
|
||||
|
||||
// Done!
|
||||
return true;
|
||||
}
|
||||
|
||||
// Maybe we could add it to the front or to the back
|
||||
// of this block ?
|
||||
if ((address + 1) == baddr || address == (baddr + blen)) {
|
||||
|
||||
// Potentially, it could be done. But we must ensure there is room
|
||||
// so we can expand the block. Lets find how much free space remains
|
||||
uint32_t iend = i;
|
||||
do {
|
||||
uint32_t ln = buffer[iend + 2];
|
||||
if (ln == 0xFF) break;
|
||||
iend += 3 + ln;
|
||||
} while (iend <= (PageSize - 4)); /* (PageSize - 4) because otherwise, there is not enough room for data and headers */
|
||||
|
||||
// Here, inxt points to the first free address in the buffer. Do we have room ?
|
||||
if (iend < PageSize) {
|
||||
// Yes, at least a byte is free - We can expand the block
|
||||
|
||||
// Do we have to insert at the beginning ?
|
||||
if ((address + 1) == baddr) {
|
||||
|
||||
// Insert at the beginning
|
||||
|
||||
// Make room at the beginning for our byte
|
||||
memmove(&buffer[i + 3 + 1], &buffer[i + 3], iend - i - 3);
|
||||
|
||||
// Adjust the header and store the data
|
||||
buffer[i] = address & 0xFF;
|
||||
buffer[i + 1] = (address >> 8) & 0xFF;
|
||||
buffer[i + 2]++;
|
||||
buffer[i + 3] = data;
|
||||
|
||||
}
|
||||
else {
|
||||
|
||||
// Insert at the end - There is a very interesting thing that could happen here:
|
||||
// Maybe we could coalesce the next block with this block. Let's try to do it!
|
||||
uint16_t inext = i + 3 + blen;
|
||||
if (inext <= (PageSize - 4) &&
|
||||
(buffer[inext] | uint16_t(buffer[inext + 1] << 8)) == (baddr + blen + 1)) {
|
||||
// YES! ... we can coalesce blocks! . Do it!
|
||||
|
||||
// Adjust this block header to include the next one
|
||||
buffer[i + 2] += buffer[inext + 2] + 1;
|
||||
|
||||
// Store data at the right place
|
||||
buffer[i + 3 + blen] = data;
|
||||
|
||||
// Remove the next block header and append its data
|
||||
memmove(&buffer[inext + 1], &buffer[inext + 3], iend - inext - 3);
|
||||
|
||||
// Finally, as we have saved 2 bytes at the end, make sure to clean them
|
||||
buffer[iend - 2] = 0xFF;
|
||||
buffer[iend - 1] = 0xFF;
|
||||
|
||||
}
|
||||
else {
|
||||
// NO ... No coalescing possible yet
|
||||
|
||||
// Make room at the end for our byte
|
||||
memmove(&buffer[i + 3 + blen + 1], &buffer[i + 3 + blen], iend - i - 3 - blen);
|
||||
|
||||
// And add the data to the block
|
||||
buffer[i + 2]++;
|
||||
buffer[i + 3 + blen] = data;
|
||||
}
|
||||
}
|
||||
|
||||
// Done!
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// As blocks are always sorted, if the starting address of this block is higher
|
||||
// than the address we are looking for, break loop now - We wont find the value
|
||||
// associated to the address
|
||||
if (baddr > address) break;
|
||||
|
||||
// Jump to the next block
|
||||
i += 3 + blen;
|
||||
}
|
||||
|
||||
// Value is not stored AND we can't expand previous block to contain it. We must create a new block
|
||||
|
||||
// First, lets find how much free space remains
|
||||
uint32_t iend = i;
|
||||
while (iend <= (PageSize - 4)) { /* (PageSize - 4) because otherwise, there is not enough room for data and headers */
|
||||
uint32_t ln = buffer[iend + 2];
|
||||
if (ln == 0xFF) break;
|
||||
iend += 3 + ln;
|
||||
}
|
||||
|
||||
// If there is room for a new block, insert it at the proper place
|
||||
if (iend <= (PageSize - 4)) {
|
||||
|
||||
// We have room to create a new block. Do so --- But add
|
||||
// the block at the proper position, sorted by starting
|
||||
// address, so it will be possible to compact it with other blocks.
|
||||
|
||||
// Make space
|
||||
memmove(&buffer[i + 4], &buffer[i], iend - i);
|
||||
|
||||
// And add the block
|
||||
buffer[i] = address & 0xFF;
|
||||
buffer[i + 1] = (address >> 8) & 0xFF;
|
||||
buffer[i + 2] = 1;
|
||||
buffer[i + 3] = data;
|
||||
|
||||
// Done!
|
||||
return true;
|
||||
}
|
||||
|
||||
// Not enough room to store this information on this FLASH page - Perform a
|
||||
// flush and override the address with the specified contents
|
||||
return ee_Flush(address, data);
|
||||
}
|
||||
|
||||
static void ee_Init() {
|
||||
|
||||
// Just init once!
|
||||
if (curGroup != 0xFF) return;
|
||||
|
||||
// Clean up the SRAM buffer
|
||||
memset(buffer, 0xFF, sizeof(buffer));
|
||||
|
||||
// Now, we must find out the group where settings are stored
|
||||
for (curGroup = 0; curGroup < GroupCount; curGroup++)
|
||||
if (!ee_IsPageClean(curGroup * PagesPerGroup)) break;
|
||||
|
||||
// If all groups seem to be used, default to first group
|
||||
if (curGroup >= GroupCount) curGroup = 0;
|
||||
|
||||
DEBUG_ECHO_MSG("EEPROM Current Group: ",curGroup);
|
||||
DEBUG_FLUSH();
|
||||
|
||||
// Now, validate that all the other group pages are empty
|
||||
for (int grp = 0; grp < GroupCount; grp++) {
|
||||
if (grp == curGroup) continue;
|
||||
|
||||
for (int page = 0; page < PagesPerGroup; page++) {
|
||||
if (!ee_IsPageClean(grp * PagesPerGroup + page)) {
|
||||
DEBUG_ECHO_MSG("EEPROM Page ", page, " not clean on group ", grp);
|
||||
DEBUG_FLUSH();
|
||||
ee_PageErase(grp * PagesPerGroup + page);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, for the active group, determine the first unused page
|
||||
// and also validate that all the other ones are clean
|
||||
for (curPage = 0; curPage < PagesPerGroup; curPage++) {
|
||||
if (ee_IsPageClean(curGroup * PagesPerGroup + curPage)) {
|
||||
ee_Dump(curGroup * PagesPerGroup + curPage, getFlashStorage(curGroup * PagesPerGroup + curPage));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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_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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* PersistentStore -----------------------------------------------------------*/
|
||||
|
||||
#include "../shared/eeprom_api.h"
|
||||
|
||||
#ifndef MARLIN_EEPROM_SIZE
|
||||
#define MARLIN_EEPROM_SIZE 0x1000 // 4KB
|
||||
#endif
|
||||
size_t PersistentStore::capacity() { return MARLIN_EEPROM_SIZE; }
|
||||
bool PersistentStore::access_start() { ee_Init(); return true; }
|
||||
bool PersistentStore::access_finish() { ee_Flush(); return true; }
|
||||
|
||||
bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, uint16_t *crc) {
|
||||
uint16_t written = 0;
|
||||
while (size--) {
|
||||
uint8_t * const p = (uint8_t * const)pos;
|
||||
uint8_t v = *value;
|
||||
if (v != ee_Read(uint32_t(p))) { // EEPROM has only ~100,000 write cycles, so only write bytes that have changed!
|
||||
ee_Write(uint32_t(p), v);
|
||||
if (++written & 0x7F) delay(2); else safe_delay(2); // Avoid triggering watchdog during long EEPROM writes
|
||||
if (ee_Read(uint32_t(p)) != v) {
|
||||
SERIAL_ECHO_MSG(STR_ERR_EEPROM_WRITE);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
crc16(crc, &v, 1);
|
||||
pos++;
|
||||
value++;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PersistentStore::read_data(int &pos, uint8_t *value, size_t size, uint16_t *crc, const bool writing/*=true*/) {
|
||||
do {
|
||||
uint8_t c = ee_Read(uint32_t(pos));
|
||||
if (writing) *value = c;
|
||||
crc16(crc, &c, 1);
|
||||
pos++;
|
||||
value++;
|
||||
} while (--size);
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // FLASH_EEPROM_EMULATION
|
||||
#endif // ARDUINO_ARCH_SAM
|
|
@ -0,0 +1,75 @@
|
|||
/**
|
||||
* 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"
|
||||
|
||||
#if USE_WIRED_EEPROM
|
||||
|
||||
/**
|
||||
* PersistentStore for Arduino-style EEPROM interface
|
||||
* with simple implementations supplied by Marlin.
|
||||
*/
|
||||
|
||||
#include "../shared/eeprom_if.h"
|
||||
#include "../shared/eeprom_api.h"
|
||||
|
||||
#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--) {
|
||||
uint8_t * const p = (uint8_t * const)pos;
|
||||
uint8_t v = *value;
|
||||
if (v != eeprom_read_byte(p)) { // EEPROM has only ~100,000 write cycles, so only write bytes that have changed!
|
||||
eeprom_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*/) {
|
||||
do {
|
||||
uint8_t c = eeprom_read_byte((uint8_t*)pos);
|
||||
if (writing) *value = c;
|
||||
crc16(crc, &c, 1);
|
||||
pos++;
|
||||
value++;
|
||||
} while (--size);
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif // USE_WIRED_EEPROM
|
||||
#endif // ARDUINO_ARCH_SAM
|
|
@ -0,0 +1,79 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* 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"
|
||||
|
||||
// One ISR for all EXT-Interrupts
|
||||
void endstop_ISR() { endstops.update(); }
|
||||
|
||||
/**
|
||||
* Endstop interrupts for Due based targets.
|
||||
* On Due, all pins support external interrupt capability.
|
||||
*/
|
||||
|
||||
void setup_endstop_interrupts() {
|
||||
#define _ATTACH(P) attachInterrupt(digitalPinToInterrupt(P), endstop_ISR, CHANGE)
|
||||
TERN_(USE_X_MAX, _ATTACH(X_MAX_PIN));
|
||||
TERN_(USE_X_MIN, _ATTACH(X_MIN_PIN));
|
||||
TERN_(USE_Y_MAX, _ATTACH(Y_MAX_PIN));
|
||||
TERN_(USE_Y_MIN, _ATTACH(Y_MIN_PIN));
|
||||
TERN_(USE_Z_MAX, _ATTACH(Z_MAX_PIN));
|
||||
TERN_(USE_Z_MIN, _ATTACH(Z_MIN_PIN));
|
||||
TERN_(USE_X2_MAX, _ATTACH(X2_MAX_PIN));
|
||||
TERN_(USE_X2_MIN, _ATTACH(X2_MIN_PIN));
|
||||
TERN_(USE_Y2_MAX, _ATTACH(Y2_MAX_PIN));
|
||||
TERN_(USE_Y2_MIN, _ATTACH(Y2_MIN_PIN));
|
||||
TERN_(USE_Z2_MAX, _ATTACH(Z2_MAX_PIN));
|
||||
TERN_(USE_Z2_MIN, _ATTACH(Z2_MIN_PIN));
|
||||
TERN_(USE_Z3_MAX, _ATTACH(Z3_MAX_PIN));
|
||||
TERN_(USE_Z3_MIN, _ATTACH(Z3_MIN_PIN));
|
||||
TERN_(USE_Z4_MAX, _ATTACH(Z4_MAX_PIN));
|
||||
TERN_(USE_Z4_MIN, _ATTACH(Z4_MIN_PIN));
|
||||
TERN_(HAS_Z_MIN_PROBE_PIN, _ATTACH(Z_MIN_PROBE_PIN));
|
||||
TERN_(USE_I_MAX, _ATTACH(I_MAX_PIN));
|
||||
TERN_(USE_I_MIN, _ATTACH(I_MIN_PIN));
|
||||
TERN_(USE_J_MAX, _ATTACH(J_MAX_PIN));
|
||||
TERN_(USE_J_MIN, _ATTACH(J_MIN_PIN));
|
||||
TERN_(USE_K_MAX, _ATTACH(K_MAX_PIN));
|
||||
TERN_(USE_K_MIN, _ATTACH(K_MIN_PIN));
|
||||
TERN_(USE_U_MAX, _ATTACH(U_MAX_PIN));
|
||||
TERN_(USE_U_MIN, _ATTACH(U_MIN_PIN));
|
||||
TERN_(USE_V_MAX, _ATTACH(V_MAX_PIN));
|
||||
TERN_(USE_V_MIN, _ATTACH(V_MIN_PIN));
|
||||
TERN_(USE_W_MAX, _ATTACH(W_MAX_PIN));
|
||||
TERN_(USE_W_MIN, _ATTACH(W_MIN_PIN));
|
||||
}
|
|
@ -0,0 +1,565 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Fast I/O Routines for SAM3X8E
|
||||
* Use direct port manipulation to save scads of processor time.
|
||||
* Contributed by Triffid_Hunter and modified by Kliment, thinkyhead, Bob-the-Kuhn, et.al.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Description: Fast IO functions for Arduino Due and compatible (SAM3X8E)
|
||||
*
|
||||
* For ARDUINO_ARCH_SAM
|
||||
* Note the code here was specifically crafted by disassembling what GCC produces
|
||||
* out of it, so GCC is able to optimize it out as much as possible to the least
|
||||
* amount of instructions. Be very careful if you modify them, as "clean code"
|
||||
* leads to less efficient compiled code!!
|
||||
*/
|
||||
|
||||
#include <pins_arduino.h>
|
||||
|
||||
#include "../../inc/MarlinConfigPre.h"
|
||||
|
||||
/**
|
||||
* Utility functions
|
||||
*/
|
||||
|
||||
// Due has 12 PWMs assigned to logical pins 2-13.
|
||||
// 6, 7, 8 & 9 come from the PWM controller. The others come from the timers.
|
||||
#define PWM_PIN(P) WITHIN(P, 2, 13)
|
||||
|
||||
#ifndef MASK
|
||||
#define MASK(PIN) _BV(PIN)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Magic I/O routines
|
||||
*
|
||||
* Now you can simply SET_OUTPUT(STEP); WRITE(STEP, HIGH); WRITE(STEP, LOW);
|
||||
*
|
||||
* Why double up on these macros? see https://gcc.gnu.org/onlinedocs/cpp/Stringification.html
|
||||
*/
|
||||
|
||||
// Read a pin
|
||||
#define _READ(IO) bool(DIO ## IO ## _WPORT -> PIO_PDSR & MASK(DIO ## IO ## _PIN))
|
||||
|
||||
// Write to a pin
|
||||
#define _WRITE(IO,V) do { \
|
||||
volatile Pio* port = (DIO ## IO ## _WPORT); \
|
||||
const uint32_t mask = MASK(DIO ## IO ## _PIN); \
|
||||
if (V) port->PIO_SODR = mask; \
|
||||
else port->PIO_CODR = mask; \
|
||||
}while(0)
|
||||
|
||||
// Toggle a pin
|
||||
#define _TOGGLE(IO) _WRITE(IO, !READ(IO))
|
||||
|
||||
#if MB(PRINTRBOARD_G2)
|
||||
|
||||
#include "fastio/G2_pins.h"
|
||||
|
||||
// Set pin as input
|
||||
#define _SET_INPUT(IO) do{ \
|
||||
pmc_enable_periph_clk(G2_g_APinDescription[IO].ulPeripheralId); \
|
||||
PIO_Configure((DIO ## IO ## _WPORT), PIO_INPUT, MASK(DIO ## IO ## _PIN), 0); \
|
||||
}while(0)
|
||||
|
||||
// Set pin as output
|
||||
#define _SET_OUTPUT(IO) do{ \
|
||||
uint32_t mask = MASK(G2_g_APinDescription[IO].ulPeripheralId); \
|
||||
if ((PMC->PMC_PCSR0 & mask) != (mask)) PMC->PMC_PCER0 = mask; \
|
||||
volatile Pio* port = (DIO ## IO ## _WPORT); \
|
||||
mask = MASK(DIO ## IO ## _PIN); \
|
||||
if (_READ(IO)) port->PIO_SODR = mask; \
|
||||
else port->PIO_CODR = mask; \
|
||||
port->PIO_IDR = mask; \
|
||||
const uint32_t pin_config = G2_g_APinDescription[IO].ulPinConfiguration; \
|
||||
if (pin_config & PIO_PULLUP) port->PIO_PUER = mask; \
|
||||
else port->PIO_PUDR = mask; \
|
||||
if (pin_config & PIO_OPENDRAIN) port->PIO_MDER = mask; \
|
||||
else port->PIO_MDDR = mask; \
|
||||
port->PIO_PER = mask; \
|
||||
port->PIO_OER = mask; \
|
||||
g_pinStatus[IO] = (g_pinStatus[IO] & 0xF0) | PIN_STATUS_DIGITAL_OUTPUT; \
|
||||
}while(0)
|
||||
|
||||
/**
|
||||
* Set pin as output with comments
|
||||
* #define _SET_OUTPUT(IO) do{ \
|
||||
* uint32_t mask = MASK(G2_g_APinDescription[IO].ulPeripheralId); \
|
||||
* if ((PMC->PMC_PCSR0 & mask ) != (mask)) PMC->PMC_PCER0 = mask; \ // enable PIO clock if not already enabled
|
||||
*
|
||||
* volatile Pio* port = (DIO ## IO ## _WPORT); \
|
||||
* const uint32_t mask = MASK(DIO ## IO ## _PIN); \
|
||||
* if (_READ(IO)) port->PIO_SODR = mask; \ // set output to match input BEFORE setting direction or will glitch the output
|
||||
* else port->PIO_CODR = mask; \
|
||||
*
|
||||
* port->PIO_IDR = mask; \ // disable interrupt
|
||||
*
|
||||
* uint32_t pin_config = G2_g_APinDescription[IO].ulPinConfiguration; \
|
||||
* if (pin_config & PIO_PULLUP) pPio->PIO_PUER = mask; \ // enable pullup if necessary
|
||||
* else pPio->PIO_PUDR = mask; \
|
||||
*
|
||||
* if (pin_config & PIO_OPENDRAIN) port->PIO_MDER = mask; \ // Enable multi-drive if necessary
|
||||
* else port->PIO_MDDR = mask; \
|
||||
*
|
||||
* port->PIO_PER = mask; \
|
||||
* port->PIO_OER = mask; \ // set to output
|
||||
*
|
||||
* g_pinStatus[IO] = (g_pinStatus[IO] & 0xF0) | PIN_STATUS_DIGITAL_OUTPUT; \
|
||||
* }while(0)
|
||||
*/
|
||||
|
||||
#else
|
||||
|
||||
// Set pin as input
|
||||
#define _SET_INPUT(IO) do{ \
|
||||
pmc_enable_periph_clk(g_APinDescription[IO].ulPeripheralId); \
|
||||
PIO_Configure(digitalPinToPort(IO), PIO_INPUT, digitalPinToBitMask(IO), 0); \
|
||||
}while(0)
|
||||
|
||||
// Set pin as output
|
||||
#define _SET_OUTPUT(IO) do{ \
|
||||
pmc_enable_periph_clk(g_APinDescription[IO].ulPeripheralId); \
|
||||
PIO_Configure(digitalPinToPort(IO), _READ(IO) ? PIO_OUTPUT_1 : PIO_OUTPUT_0, digitalPinToBitMask(IO), g_APinDescription[IO].ulPinConfiguration); \
|
||||
g_pinStatus[IO] = (g_pinStatus[IO] & 0xF0) | PIN_STATUS_DIGITAL_OUTPUT; \
|
||||
}while(0)
|
||||
#endif
|
||||
|
||||
// Set pin as input with pullup mode
|
||||
#define _PULLUP(IO,V) pinMode(IO, (V) ? INPUT_PULLUP : INPUT)
|
||||
|
||||
// Read a pin (wrapper)
|
||||
#define READ(IO) _READ(IO)
|
||||
|
||||
// Write to a pin (wrapper)
|
||||
#define WRITE(IO,V) _WRITE(IO,V)
|
||||
|
||||
// Toggle a pin (wrapper)
|
||||
#define TOGGLE(IO) _TOGGLE(IO)
|
||||
|
||||
// Set pin as input (wrapper)
|
||||
#define SET_INPUT(IO) _SET_INPUT(IO)
|
||||
// Set pin as input with pullup (wrapper)
|
||||
#define SET_INPUT_PULLUP(IO) do{ _SET_INPUT(IO); _PULLUP(IO, HIGH); }while(0)
|
||||
// Set pin as input with pulldown (substitution)
|
||||
#define SET_INPUT_PULLDOWN SET_INPUT
|
||||
|
||||
// Set pin as output (wrapper) - reads the pin and sets the output to that value
|
||||
#define SET_OUTPUT(IO) _SET_OUTPUT(IO)
|
||||
// Set pin as PWM
|
||||
#define SET_PWM SET_OUTPUT
|
||||
|
||||
// Check if pin is an input
|
||||
#define IS_INPUT(IO) ((digitalPinToPort(IO)->PIO_OSR & digitalPinToBitMask(IO)) == 0)
|
||||
// Check if pin is an output
|
||||
#define IS_OUTPUT(IO) ((digitalPinToPort(IO)->PIO_OSR & digitalPinToBitMask(IO)) != 0)
|
||||
|
||||
// Shorthand
|
||||
#define OUT_WRITE(IO,V) do{ SET_OUTPUT(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!
|
||||
*/
|
||||
|
||||
// UART
|
||||
#define RXD 0
|
||||
#define TXD 1
|
||||
|
||||
// TWI (I2C)
|
||||
#define SCL 21
|
||||
#define SDA 20
|
||||
|
||||
/**
|
||||
* pins
|
||||
*/
|
||||
|
||||
#define DIO0_PIN 8
|
||||
#define DIO0_WPORT PIOA
|
||||
|
||||
#define DIO1_PIN 9
|
||||
#define DIO1_WPORT PIOA
|
||||
|
||||
#define DIO2_PIN 25
|
||||
#define DIO2_WPORT PIOB
|
||||
|
||||
#define DIO3_PIN 28
|
||||
#define DIO3_WPORT PIOC
|
||||
|
||||
#define DIO4_PIN 26
|
||||
#define DIO4_WPORT PIOC
|
||||
|
||||
#define DIO5_PIN 25
|
||||
#define DIO5_WPORT PIOC
|
||||
|
||||
#define DIO6_PIN 24
|
||||
#define DIO6_WPORT PIOC
|
||||
|
||||
#define DIO7_PIN 23
|
||||
#define DIO7_WPORT PIOC
|
||||
|
||||
#define DIO8_PIN 22
|
||||
#define DIO8_WPORT PIOC
|
||||
|
||||
#define DIO9_PIN 21
|
||||
#define DIO9_WPORT PIOC
|
||||
|
||||
#define DIO10_PIN 29
|
||||
#define DIO10_WPORT PIOC
|
||||
|
||||
#define DIO11_PIN 7
|
||||
#define DIO11_WPORT PIOD
|
||||
|
||||
#define DIO12_PIN 8
|
||||
#define DIO12_WPORT PIOD
|
||||
|
||||
#define DIO13_PIN 27
|
||||
#define DIO13_WPORT PIOB
|
||||
|
||||
#define DIO14_PIN 4
|
||||
#define DIO14_WPORT PIOD
|
||||
|
||||
#define DIO15_PIN 5
|
||||
#define DIO15_WPORT PIOD
|
||||
|
||||
#define DIO16_PIN 13
|
||||
#define DIO16_WPORT PIOA
|
||||
|
||||
#define DIO17_PIN 12
|
||||
#define DIO17_WPORT PIOA
|
||||
|
||||
#define DIO18_PIN 11
|
||||
#define DIO18_WPORT PIOA
|
||||
|
||||
#define DIO19_PIN 10
|
||||
#define DIO19_WPORT PIOA
|
||||
|
||||
#define DIO20_PIN 12
|
||||
#define DIO20_WPORT PIOB
|
||||
|
||||
#define DIO21_PIN 13
|
||||
#define DIO21_WPORT PIOB
|
||||
|
||||
#define DIO22_PIN 26
|
||||
#define DIO22_WPORT PIOB
|
||||
|
||||
#define DIO23_PIN 14
|
||||
#define DIO23_WPORT PIOA
|
||||
|
||||
#define DIO24_PIN 15
|
||||
#define DIO24_WPORT PIOA
|
||||
|
||||
#define DIO25_PIN 0
|
||||
#define DIO25_WPORT PIOD
|
||||
|
||||
#define DIO26_PIN 1
|
||||
#define DIO26_WPORT PIOD
|
||||
|
||||
#define DIO27_PIN 2
|
||||
#define DIO27_WPORT PIOD
|
||||
|
||||
#define DIO28_PIN 3
|
||||
#define DIO28_WPORT PIOD
|
||||
|
||||
#define DIO29_PIN 6
|
||||
#define DIO29_WPORT PIOD
|
||||
|
||||
#define DIO30_PIN 9
|
||||
#define DIO30_WPORT PIOD
|
||||
|
||||
#define DIO31_PIN 7
|
||||
#define DIO31_WPORT PIOA
|
||||
|
||||
#define DIO32_PIN 10
|
||||
#define DIO32_WPORT PIOD
|
||||
|
||||
#define DIO33_PIN 1
|
||||
#define DIO33_WPORT PIOC
|
||||
|
||||
#if !MB(PRINTRBOARD_G2) // normal DUE pin mapping
|
||||
|
||||
#define DIO34_PIN 2
|
||||
#define DIO34_WPORT PIOC
|
||||
|
||||
#define DIO35_PIN 3
|
||||
#define DIO35_WPORT PIOC
|
||||
|
||||
#define DIO36_PIN 4
|
||||
#define DIO36_WPORT PIOC
|
||||
|
||||
#define DIO37_PIN 5
|
||||
#define DIO37_WPORT PIOC
|
||||
|
||||
#define DIO38_PIN 6
|
||||
#define DIO38_WPORT PIOC
|
||||
|
||||
#define DIO39_PIN 7
|
||||
#define DIO39_WPORT PIOC
|
||||
|
||||
#define DIO40_PIN 8
|
||||
#define DIO40_WPORT PIOC
|
||||
|
||||
#define DIO41_PIN 9
|
||||
#define DIO41_WPORT PIOC
|
||||
|
||||
#endif // !PRINTRBOARD_G2
|
||||
|
||||
#define DIO42_PIN 19
|
||||
#define DIO42_WPORT PIOA
|
||||
|
||||
#define DIO43_PIN 20
|
||||
#define DIO43_WPORT PIOA
|
||||
|
||||
#define DIO44_PIN 19
|
||||
#define DIO44_WPORT PIOC
|
||||
|
||||
#define DIO45_PIN 18
|
||||
#define DIO45_WPORT PIOC
|
||||
|
||||
#define DIO46_PIN 17
|
||||
#define DIO46_WPORT PIOC
|
||||
|
||||
#define DIO47_PIN 16
|
||||
#define DIO47_WPORT PIOC
|
||||
|
||||
#define DIO48_PIN 15
|
||||
#define DIO48_WPORT PIOC
|
||||
|
||||
#define DIO49_PIN 14
|
||||
#define DIO49_WPORT PIOC
|
||||
|
||||
#define DIO50_PIN 13
|
||||
#define DIO50_WPORT PIOC
|
||||
|
||||
#define DIO51_PIN 12
|
||||
#define DIO51_WPORT PIOC
|
||||
|
||||
#define DIO52_PIN 21
|
||||
#define DIO52_WPORT PIOB
|
||||
|
||||
#define DIO53_PIN 14
|
||||
#define DIO53_WPORT PIOB
|
||||
|
||||
#define DIO54_PIN 16
|
||||
#define DIO54_WPORT PIOA
|
||||
|
||||
#define DIO55_PIN 24
|
||||
#define DIO55_WPORT PIOA
|
||||
|
||||
#define DIO56_PIN 23
|
||||
#define DIO56_WPORT PIOA
|
||||
|
||||
#define DIO57_PIN 22
|
||||
#define DIO57_WPORT PIOA
|
||||
|
||||
#define DIO58_PIN 6
|
||||
#define DIO58_WPORT PIOA
|
||||
|
||||
#define DIO59_PIN 4
|
||||
#define DIO59_WPORT PIOA
|
||||
|
||||
#define DIO60_PIN 3
|
||||
#define DIO60_WPORT PIOA
|
||||
|
||||
#define DIO61_PIN 2
|
||||
#define DIO61_WPORT PIOA
|
||||
|
||||
#define DIO62_PIN 17
|
||||
#define DIO62_WPORT PIOB
|
||||
|
||||
#define DIO63_PIN 18
|
||||
#define DIO63_WPORT PIOB
|
||||
|
||||
#define DIO64_PIN 19
|
||||
#define DIO64_WPORT PIOB
|
||||
|
||||
#define DIO65_PIN 20
|
||||
#define DIO65_WPORT PIOB
|
||||
|
||||
#define DIO66_PIN 15
|
||||
#define DIO66_WPORT PIOB
|
||||
|
||||
#define DIO67_PIN 16
|
||||
#define DIO67_WPORT PIOB
|
||||
|
||||
#define DIO68_PIN 1
|
||||
#define DIO68_WPORT PIOA
|
||||
|
||||
#define DIO69_PIN 0
|
||||
#define DIO69_WPORT PIOA
|
||||
|
||||
#define DIO70_PIN 17
|
||||
#define DIO70_WPORT PIOA
|
||||
|
||||
#define DIO71_PIN 18
|
||||
#define DIO71_WPORT PIOA
|
||||
|
||||
#define DIO72_PIN 30
|
||||
#define DIO72_WPORT PIOC
|
||||
|
||||
#define DIO73_PIN 21
|
||||
#define DIO73_WPORT PIOA
|
||||
|
||||
#define DIO74_PIN 25
|
||||
#define DIO74_WPORT PIOA
|
||||
|
||||
#define DIO75_PIN 26
|
||||
#define DIO75_WPORT PIOA
|
||||
|
||||
#define DIO76_PIN 27
|
||||
#define DIO76_WPORT PIOA
|
||||
|
||||
#define DIO77_PIN 28
|
||||
#define DIO77_WPORT PIOA
|
||||
|
||||
#define DIO78_PIN 23
|
||||
#define DIO78_WPORT PIOB
|
||||
|
||||
#define DIO79_PIN 17
|
||||
#define DIO79_WPORT PIOA
|
||||
|
||||
#define DIO80_PIN 12
|
||||
#define DIO80_WPORT PIOB
|
||||
|
||||
#define DIO81_PIN 8
|
||||
#define DIO81_WPORT PIOA
|
||||
|
||||
#define DIO82_PIN 11
|
||||
#define DIO82_WPORT PIOA
|
||||
|
||||
#define DIO83_PIN 13
|
||||
#define DIO83_WPORT PIOA
|
||||
|
||||
#define DIO84_PIN 4
|
||||
#define DIO84_WPORT PIOD
|
||||
|
||||
#define DIO85_PIN 11
|
||||
#define DIO85_WPORT PIOB
|
||||
|
||||
#define DIO86_PIN 21
|
||||
#define DIO86_WPORT PIOB
|
||||
|
||||
#define DIO87_PIN 29
|
||||
#define DIO87_WPORT PIOA
|
||||
|
||||
#define DIO88_PIN 15
|
||||
#define DIO88_WPORT PIOB
|
||||
|
||||
#define DIO89_PIN 14
|
||||
#define DIO89_WPORT PIOB
|
||||
|
||||
#define DIO90_PIN 1
|
||||
#define DIO90_WPORT PIOA
|
||||
|
||||
#define DIO91_PIN 15
|
||||
#define DIO91_WPORT PIOB
|
||||
|
||||
#ifdef ARDUINO_SAM_ARCHIM
|
||||
|
||||
#define DIO92_PIN 11
|
||||
#define DIO92_WPORT PIOC
|
||||
|
||||
#define DIO93_PIN 2
|
||||
#define DIO93_WPORT PIOB
|
||||
|
||||
#define DIO94_PIN 1
|
||||
#define DIO94_WPORT PIOB
|
||||
|
||||
#define DIO95_PIN 0
|
||||
#define DIO95_WPORT PIOB
|
||||
|
||||
#define DIO96_PIN 10
|
||||
#define DIO96_WPORT PIOC
|
||||
|
||||
#define DIO97_PIN 24
|
||||
#define DIO97_WPORT PIOB
|
||||
|
||||
#define DIO98_PIN 7
|
||||
#define DIO98_WPORT PIOB
|
||||
|
||||
#define DIO99_PIN 6
|
||||
#define DIO99_WPORT PIOB
|
||||
|
||||
#define DIO100_PIN 8
|
||||
#define DIO100_WPORT PIOB
|
||||
|
||||
#define DIO101_PIN 5
|
||||
#define DIO101_WPORT PIOB
|
||||
|
||||
#define DIO102_PIN 4
|
||||
#define DIO102_WPORT PIOB
|
||||
|
||||
#define DIO103_PIN 3
|
||||
#define DIO103_WPORT PIOB
|
||||
|
||||
#define DIO104_PIN 20
|
||||
#define DIO104_WPORT PIOC
|
||||
|
||||
#define DIO105_PIN 22
|
||||
#define DIO105_WPORT PIOB
|
||||
|
||||
#define DIO106_PIN 27
|
||||
#define DIO106_WPORT PIOC
|
||||
|
||||
#define DIO107_PIN 10
|
||||
#define DIO107_WPORT PIOB
|
||||
|
||||
#define DIO108_PIN 9
|
||||
#define DIO108_WPORT PIOB
|
||||
|
||||
#else // !ARDUINO_SAM_ARCHIM
|
||||
|
||||
#define DIO92_PIN 5
|
||||
#define DIO92_WPORT PIOA
|
||||
|
||||
#define DIO93_PIN 12
|
||||
#define DIO93_WPORT PIOB
|
||||
|
||||
#define DIO94_PIN 22
|
||||
#define DIO94_WPORT PIOB
|
||||
|
||||
#define DIO95_PIN 23
|
||||
#define DIO95_WPORT PIOB
|
||||
|
||||
#define DIO96_PIN 24
|
||||
#define DIO96_WPORT PIOB
|
||||
|
||||
#define DIO97_PIN 20
|
||||
#define DIO97_WPORT PIOC
|
||||
|
||||
#define DIO98_PIN 27
|
||||
#define DIO98_WPORT PIOC
|
||||
|
||||
#define DIO99_PIN 10
|
||||
#define DIO99_WPORT PIOC
|
||||
|
||||
#define DIO100_PIN 11
|
||||
#define DIO100_WPORT PIOC
|
||||
|
||||
#endif // !ARDUINO_SAM_ARCHIM
|
|
@ -0,0 +1,206 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* The PWM module is only used to generate interrupts at specified times. It
|
||||
* is NOT used to directly toggle pins. The ISR writes to the pin assigned to
|
||||
* that interrupt.
|
||||
*
|
||||
* All PWMs use the same repetition rate. The G2 needs about 10kHz min in order to
|
||||
* not have obvious ripple on the Vref signals.
|
||||
*
|
||||
* The data structures are setup to minimize the computation done by the ISR which
|
||||
* minimizes ISR execution time. Execution times are 0.8 to 1.1 microseconds.
|
||||
*
|
||||
* FIve PWM interrupt sources are used. Channel 0 sets the base period. All Vref
|
||||
* signals are set active when this counter overflows and resets to zero. The compare
|
||||
* values in channels 1-4 are set to give the desired duty cycle for that Vref pin.
|
||||
* When counter 0 matches the compare value then that channel generates an interrupt.
|
||||
* The ISR checks the source of the interrupt and sets the corresponding pin inactive.
|
||||
*
|
||||
* Some jitter in the Vref signal is OK so the interrupt priority is left at its default value.
|
||||
*/
|
||||
|
||||
#include "../../../inc/MarlinConfig.h"
|
||||
|
||||
#if MB(PRINTRBOARD_G2)
|
||||
|
||||
#include "G2_PWM.h"
|
||||
|
||||
#if PIN_EXISTS(MOTOR_CURRENT_PWM_X)
|
||||
#define G2_PWM_X 1
|
||||
#else
|
||||
#define G2_PWM_X 0
|
||||
#endif
|
||||
#if PIN_EXISTS(MOTOR_CURRENT_PWM_Y)
|
||||
#define G2_PWM_Y 1
|
||||
#else
|
||||
#define G2_PWM_Y 0
|
||||
#endif
|
||||
#if PIN_EXISTS(MOTOR_CURRENT_PWM_Z)
|
||||
#define G2_PWM_Z 1
|
||||
#else
|
||||
#define G2_PWM_Z 0
|
||||
#endif
|
||||
#if PIN_EXISTS(MOTOR_CURRENT_PWM_E)
|
||||
#define G2_PWM_E 1
|
||||
#else
|
||||
#define G2_PWM_E 0
|
||||
#endif
|
||||
#define G2_MASK_X(V) (G2_PWM_X * (V))
|
||||
#define G2_MASK_Y(V) (G2_PWM_Y * (V))
|
||||
#define G2_MASK_Z(V) (G2_PWM_Z * (V))
|
||||
#define G2_MASK_E(V) (G2_PWM_E * (V))
|
||||
|
||||
volatile uint32_t *SODR_A = &PIOA->PIO_SODR,
|
||||
*SODR_B = &PIOB->PIO_SODR,
|
||||
*CODR_A = &PIOA->PIO_CODR,
|
||||
*CODR_B = &PIOB->PIO_CODR;
|
||||
|
||||
PWM_map ISR_table[NUM_PWMS] = PWM_MAP_INIT;
|
||||
|
||||
void Stepper::digipot_init() {
|
||||
|
||||
#if PIN_EXISTS(MOTOR_CURRENT_PWM_X)
|
||||
OUT_WRITE(MOTOR_CURRENT_PWM_X_PIN, 0); // init pins
|
||||
#endif
|
||||
#if PIN_EXISTS(MOTOR_CURRENT_PWM_Y)
|
||||
OUT_WRITE(MOTOR_CURRENT_PWM_Y_PIN, 0);
|
||||
#endif
|
||||
#if G2_PWM_Z
|
||||
OUT_WRITE(MOTOR_CURRENT_PWM_Z_PIN, 0);
|
||||
#endif
|
||||
#if G2_PWM_E
|
||||
OUT_WRITE(MOTOR_CURRENT_PWM_E_PIN, 0);
|
||||
#endif
|
||||
|
||||
#define WPKEY (0x50574D << 8) // “PWM” in ASCII
|
||||
#define WPCMD_DIS_SW 0 // command to disable Write Protect SW
|
||||
#define WPRG_ALL (PWM_WPCR_WPRG0 | PWM_WPCR_WPRG1 | PWM_WPCR_WPRG2 | PWM_WPCR_WPRG3 | PWM_WPCR_WPRG4 | PWM_WPCR_WPRG5) // all Write Protect Groups
|
||||
|
||||
#define PWM_CLOCK_F F_CPU / 1000000UL // set clock to 1MHz
|
||||
|
||||
PMC->PMC_PCER1 = PMC_PCER1_PID36; // enable PWM controller clock (disabled on power up)
|
||||
|
||||
PWM->PWM_WPCR = WPKEY | WPRG_ALL | WPCMD_DIS_SW; // enable setting of all PWM registers
|
||||
PWM->PWM_CLK = PWM_CLOCK_F; // enable CLK_A and set it to 1MHz, leave CLK_B disabled
|
||||
PWM->PWM_CH_NUM[0].PWM_CMR = 0b1011; // set channel 0 to Clock A input & to left aligned
|
||||
if (G2_PWM_X) PWM->PWM_CH_NUM[1].PWM_CMR = 0b1011; // set channel 1 to Clock A input & to left aligned
|
||||
if (G2_PWM_Y) PWM->PWM_CH_NUM[2].PWM_CMR = 0b1011; // set channel 2 to Clock A input & to left aligned
|
||||
if (G2_PWM_Z) PWM->PWM_CH_NUM[3].PWM_CMR = 0b1011; // set channel 3 to Clock A input & to left aligned
|
||||
if (G2_PWM_E) PWM->PWM_CH_NUM[4].PWM_CMR = 0b1011; // set channel 4 to Clock A input & to left aligned
|
||||
|
||||
PWM->PWM_CH_NUM[0].PWM_CPRD = PWM_PERIOD_US; // set channel 0 Period
|
||||
|
||||
PWM->PWM_IER2 = PWM_IER1_CHID0; // generate interrupt when counter0 overflows
|
||||
PWM->PWM_IER2 = PWM_IER2_CMPM0
|
||||
| G2_MASK_X(PWM_IER2_CMPM1)
|
||||
| G2_MASK_Y(PWM_IER2_CMPM2)
|
||||
| G2_MASK_Z(PWM_IER2_CMPM3)
|
||||
| G2_MASK_E(PWM_IER2_CMPM4)
|
||||
; // generate interrupt on compare event
|
||||
|
||||
if (G2_PWM_X) PWM->PWM_CMP[1].PWM_CMPV = 0x010000000LL | G2_VREF_COUNT(G2_VREF(motor_current_setting[0])); // interrupt when counter0 == CMPV - used to set Motor 1 PWM inactive
|
||||
if (G2_PWM_Y) PWM->PWM_CMP[2].PWM_CMPV = 0x010000000LL | G2_VREF_COUNT(G2_VREF(motor_current_setting[0])); // interrupt when counter0 == CMPV - used to set Motor 2 PWM inactive
|
||||
if (G2_PWM_Z) PWM->PWM_CMP[3].PWM_CMPV = 0x010000000LL | G2_VREF_COUNT(G2_VREF(motor_current_setting[1])); // interrupt when counter0 == CMPV - used to set Motor 3 PWM inactive
|
||||
if (G2_PWM_E) PWM->PWM_CMP[4].PWM_CMPV = 0x010000000LL | G2_VREF_COUNT(G2_VREF(motor_current_setting[2])); // interrupt when counter0 == CMPV - used to set Motor 4 PWM inactive
|
||||
|
||||
if (G2_PWM_X) PWM->PWM_CMP[1].PWM_CMPM = 0x0001; // enable compare event
|
||||
if (G2_PWM_Y) PWM->PWM_CMP[2].PWM_CMPM = 0x0001; // enable compare event
|
||||
if (G2_PWM_Z) PWM->PWM_CMP[3].PWM_CMPM = 0x0001; // enable compare event
|
||||
if (G2_PWM_E) PWM->PWM_CMP[4].PWM_CMPM = 0x0001; // enable compare event
|
||||
|
||||
PWM->PWM_SCM = PWM_SCM_UPDM_MODE0 | PWM_SCM_SYNC0
|
||||
| G2_MASK_X(PWM_SCM_SYNC1)
|
||||
| G2_MASK_Y(PWM_SCM_SYNC2)
|
||||
| G2_MASK_Z(PWM_SCM_SYNC3)
|
||||
| G2_MASK_E(PWM_SCM_SYNC4)
|
||||
; // sync 1-4 with 0, use mode 0 for updates
|
||||
|
||||
PWM->PWM_ENA = PWM_ENA_CHID0
|
||||
| G2_MASK_X(PWM_ENA_CHID1)
|
||||
| G2_MASK_Y(PWM_ENA_CHID2)
|
||||
| G2_MASK_Z(PWM_ENA_CHID3)
|
||||
| G2_MASK_E(PWM_ENA_CHID4)
|
||||
; // enable channels used by G2
|
||||
|
||||
PWM->PWM_IER1 = PWM_IER1_CHID0
|
||||
| G2_MASK_X(PWM_IER1_CHID1)
|
||||
| G2_MASK_Y(PWM_IER1_CHID2)
|
||||
| G2_MASK_Z(PWM_IER1_CHID3)
|
||||
| G2_MASK_E(PWM_IER1_CHID4)
|
||||
; // enable interrupts for channels used by G2
|
||||
|
||||
NVIC_EnableIRQ(PWM_IRQn); // Enable interrupt handler
|
||||
NVIC_SetPriority(PWM_IRQn, NVIC_EncodePriority(0, 10, 0)); // normal priority for PWM module (can stand some jitter on the Vref signals)
|
||||
}
|
||||
|
||||
void Stepper::set_digipot_current(const uint8_t driver, const int16_t current) {
|
||||
|
||||
if (!(PWM->PWM_CH_NUM[0].PWM_CPRD == PWM_PERIOD_US)) digipot_init(); // Init PWM system if needed
|
||||
|
||||
switch (driver) {
|
||||
case 0:
|
||||
if (G2_PWM_X) PWM->PWM_CMP[1].PWM_CMPVUPD = 0x010000000LL | G2_VREF_COUNT(G2_VREF(current)); // update X & Y
|
||||
if (G2_PWM_Y) PWM->PWM_CMP[2].PWM_CMPVUPD = 0x010000000LL | G2_VREF_COUNT(G2_VREF(current));
|
||||
if (G2_PWM_X) PWM->PWM_CMP[1].PWM_CMPMUPD = 0x0001; // enable compare event
|
||||
if (G2_PWM_Y) PWM->PWM_CMP[2].PWM_CMPMUPD = 0x0001; // enable compare event
|
||||
if (G2_PWM_X || G2_PWM_Y) PWM->PWM_SCUC = PWM_SCUC_UPDULOCK; // tell the PWM controller to update the values on the next cycle
|
||||
break;
|
||||
case 1:
|
||||
if (G2_PWM_Z) {
|
||||
PWM->PWM_CMP[3].PWM_CMPVUPD = 0x010000000LL | G2_VREF_COUNT(G2_VREF(current)); // update Z
|
||||
PWM->PWM_CMP[3].PWM_CMPMUPD = 0x0001; // enable compare event
|
||||
PWM->PWM_SCUC = PWM_SCUC_UPDULOCK; // tell the PWM controller to update the values on the next cycle
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (G2_PWM_E) {
|
||||
PWM->PWM_CMP[4].PWM_CMPVUPD = 0x010000000LL | G2_VREF_COUNT(G2_VREF(current)); // update E
|
||||
PWM->PWM_CMP[4].PWM_CMPMUPD = 0x0001; // enable compare event
|
||||
PWM->PWM_SCUC = PWM_SCUC_UPDULOCK; // tell the PWM controller to update the values on the next cycle
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
volatile uint32_t PWM_ISR1_STATUS, PWM_ISR2_STATUS;
|
||||
|
||||
void PWM_Handler() {
|
||||
PWM_ISR1_STATUS = PWM->PWM_ISR1;
|
||||
PWM_ISR2_STATUS = PWM->PWM_ISR2;
|
||||
if (PWM_ISR1_STATUS & PWM_IER1_CHID0) { // CHAN_0 interrupt
|
||||
if (G2_PWM_X) *ISR_table[0].set_register = ISR_table[0].write_mask; // set X to active
|
||||
if (G2_PWM_Y) *ISR_table[1].set_register = ISR_table[1].write_mask; // set Y to active
|
||||
if (G2_PWM_Z) *ISR_table[2].set_register = ISR_table[2].write_mask; // set Z to active
|
||||
if (G2_PWM_E) *ISR_table[3].set_register = ISR_table[3].write_mask; // set E to active
|
||||
}
|
||||
else {
|
||||
if (G2_PWM_X && (PWM_ISR2_STATUS & PWM_IER2_CMPM1)) *ISR_table[0].clr_register = ISR_table[0].write_mask; // set X to inactive
|
||||
if (G2_PWM_Y && (PWM_ISR2_STATUS & PWM_IER2_CMPM2)) *ISR_table[1].clr_register = ISR_table[1].write_mask; // set Y to inactive
|
||||
if (G2_PWM_Z && (PWM_ISR2_STATUS & PWM_IER2_CMPM3)) *ISR_table[2].clr_register = ISR_table[2].write_mask; // set Z to inactive
|
||||
if (G2_PWM_E && (PWM_ISR2_STATUS & PWM_IER2_CMPM4)) *ISR_table[3].clr_register = ISR_table[3].write_mask; // set E to inactive
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
#endif // PRINTRBOARD_G2
|
|
@ -0,0 +1,77 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* This module is stripped down version of the LPC1768_PWM.h file from
|
||||
* PR #7500. It is hardwired for the PRINTRBOARD_G2 Motor Current needs.
|
||||
*/
|
||||
|
||||
#include "../../../inc/MarlinConfigPre.h"
|
||||
#include "../../../module/stepper.h"
|
||||
//C:\Users\bobku\Documents\GitHub\Marlin-Bob-2\Marlin\src\module\stepper.h
|
||||
//C:\Users\bobku\Documents\GitHub\Marlin-Bob-2\Marlin\src\HAL\HAL_DUE\G2_PWM.h
|
||||
|
||||
#define PWM_PERIOD_US 100 // base repetition rate in micro seconds
|
||||
|
||||
typedef struct { // holds the data needed by the ISR to control the Vref pin
|
||||
volatile uint32_t* set_register;
|
||||
volatile uint32_t* clr_register;
|
||||
uint32_t write_mask;
|
||||
} PWM_map;
|
||||
|
||||
#define G2_VREF(I) (uint32_t)(I * 5 * 0.15) // desired Vref * 1000 (scaled so don't loose accuracy in next step)
|
||||
|
||||
#define G2_VREF_COUNT(Q) (uint32_t)map(constrain(Q, 500, 3.3 * 1000), 0, 3.3 * 1000, 0, PWM_PERIOD_US) // under 500 the results are very non-linear
|
||||
|
||||
extern volatile uint32_t *SODR_A, *SODR_B, *CODR_A, *CODR_B;
|
||||
|
||||
#define _PIN(IO) (DIO ## IO ## _PIN)
|
||||
|
||||
#define PWM_MAP_INIT_ROW(IO,ZZ) { ZZ == 'A' ? SODR_A : SODR_B, ZZ == 'A' ? CODR_A : CODR_B, 1 << _PIN(IO) }
|
||||
|
||||
#define PWM_MAP_INIT { PWM_MAP_INIT_ROW(MOTOR_CURRENT_PWM_X_PIN, 'B'), \
|
||||
PWM_MAP_INIT_ROW(MOTOR_CURRENT_PWM_Y_PIN, 'B'), \
|
||||
PWM_MAP_INIT_ROW(MOTOR_CURRENT_PWM_Z_PIN, 'B'), \
|
||||
PWM_MAP_INIT_ROW(MOTOR_CURRENT_PWM_E_PIN, 'A'), \
|
||||
};
|
||||
|
||||
#define NUM_PWMS 4
|
||||
|
||||
extern PWM_map ISR_table[NUM_PWMS];
|
||||
|
||||
extern uint32_t motor_current_setting[3];
|
||||
|
||||
#define IR_BIT(p) (WITHIN(p, 0, 3) ? (p) : (p) + 4)
|
||||
#define COPY_ACTIVE_TABLE() do{ for (uint8_t i = 0; i < 6; ++i) work_table[i] = active_table[i]; }while(0)
|
||||
|
||||
#define PWM_MR0 19999 // base repetition rate minus one count - 20mS
|
||||
#define PWM_PR 24 // prescaler value - prescaler divide by 24 + 1 - 1 MHz output
|
||||
#define PWM_PCLKSEL0 0x00 // select clock source for prescaler - defaults to 25MHz on power up
|
||||
// 0: 25MHz, 1: 100MHz, 2: 50MHz, 3: 12.5MHZ to PWM1 prescaler
|
||||
#define MR0_MARGIN 200 // if channel value too close to MR0 the system locks up
|
||||
|
||||
extern bool PWM_table_swap; // flag to tell the ISR that the tables have been swapped
|
||||
|
||||
#define HAL_G2_PWM_ISR void PWM_Handler()
|
||||
|
||||
extern volatile uint32_t PWM_ISR1_STATUS, PWM_ISR2_STATUS;
|
|
@ -0,0 +1,277 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* This file contains the custom port/pin definitions for the PRINTRBOARD_G2
|
||||
* motherboard. This motherboard uses the SAM3X8C which is a subset of the
|
||||
* SAM3X8E used in the DUE board. It uses port/pin pairs that are not
|
||||
* available using the DUE definitions.
|
||||
*
|
||||
* The first part is a copy of the pin descriptions in the
|
||||
* "variants\arduino_due_x\variant.cpp" file but with pins 34-41 replaced by
|
||||
* the G2 pins.
|
||||
*
|
||||
* The second part is the FASTIO port/pin definitions.
|
||||
*
|
||||
* THESE PINS CAN ONLY BE ACCESSED VIA FASTIO COMMANDS.
|
||||
*/
|
||||
|
||||
/*
|
||||
Copyright (c) 2011 Arduino. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library 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 Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
typedef struct _G2_PinDescription {
|
||||
Pio* pPort;
|
||||
uint32_t ulPin;
|
||||
uint32_t ulPeripheralId;
|
||||
EPioType ulPinType;
|
||||
uint32_t ulPinConfiguration;
|
||||
uint32_t ulPinAttribute;
|
||||
EAnalogChannel ulAnalogChannel; /* Analog pin in the Arduino context (label on the board) */
|
||||
EAnalogChannel ulADCChannelNumber; /* ADC Channel number in the SAM device */
|
||||
EPWMChannel ulPWMChannel;
|
||||
ETCChannel ulTCChannel;
|
||||
} G2_PinDescription;
|
||||
|
||||
/**
|
||||
* This section is a copy of the pin descriptions in the "variants\arduino_due_x\variant.cpp" file
|
||||
* with pins 34-41 replaced by the G2 pins.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Pins descriptions
|
||||
*/
|
||||
const G2_PinDescription G2_g_APinDescription[] = {
|
||||
// 0 .. 53 - Digital pins
|
||||
// ----------------------
|
||||
// 0/1 - UART (Serial)
|
||||
{ PIOA, PIO_PA8A_URXD, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // URXD
|
||||
{ PIOA, PIO_PA9A_UTXD, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // UTXD
|
||||
|
||||
// 2
|
||||
{ PIOB, PIO_PB25B_TIOA0, ID_PIOB, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_TIMER), NO_ADC, NO_ADC, NOT_ON_PWM, TC0_CHA0 }, // TIOA0
|
||||
{ PIOC, PIO_PC28B_TIOA7, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_TIMER), NO_ADC, NO_ADC, NOT_ON_PWM, TC2_CHA7 }, // TIOA7
|
||||
{ PIOC, PIO_PC26B_TIOB6, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_TIMER), NO_ADC, NO_ADC, NOT_ON_PWM, TC2_CHB6 }, // TIOB6
|
||||
|
||||
// 5
|
||||
{ PIOC, PIO_PC25B_TIOA6, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_TIMER), NO_ADC, NO_ADC, NOT_ON_PWM, TC2_CHA6 }, // TIOA6
|
||||
{ PIOC, PIO_PC24B_PWML7, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), NO_ADC, NO_ADC, PWM_CH7, NOT_ON_TIMER }, // PWML7
|
||||
{ PIOC, PIO_PC23B_PWML6, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), NO_ADC, NO_ADC, PWM_CH6, NOT_ON_TIMER }, // PWML6
|
||||
{ PIOC, PIO_PC22B_PWML5, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), NO_ADC, NO_ADC, PWM_CH5, NOT_ON_TIMER }, // PWML5
|
||||
{ PIOC, PIO_PC21B_PWML4, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), NO_ADC, NO_ADC, PWM_CH4, NOT_ON_TIMER }, // PWML4
|
||||
// 10
|
||||
{ PIOC, PIO_PC29B_TIOB7, ID_PIOC, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_TIMER), NO_ADC, NO_ADC, NOT_ON_PWM, TC2_CHB7 }, // TIOB7
|
||||
{ PIOD, PIO_PD7B_TIOA8, ID_PIOD, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_TIMER), NO_ADC, NO_ADC, NOT_ON_PWM, TC2_CHA8 }, // TIOA8
|
||||
{ PIOD, PIO_PD8B_TIOB8, ID_PIOD, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_TIMER), NO_ADC, NO_ADC, NOT_ON_PWM, TC2_CHB8 }, // TIOB8
|
||||
|
||||
// 13 - AMBER LED
|
||||
{ PIOB, PIO_PB27B_TIOB0, ID_PIOB, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_TIMER), NO_ADC, NO_ADC, NOT_ON_PWM, TC0_CHB0 }, // TIOB0
|
||||
|
||||
// 14/15 - USART3 (Serial3)
|
||||
{ PIOD, PIO_PD4B_TXD3, ID_PIOD, PIO_PERIPH_B, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // TXD3
|
||||
{ PIOD, PIO_PD5B_RXD3, ID_PIOD, PIO_PERIPH_B, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // RXD3
|
||||
|
||||
// 16/17 - USART1 (Serial2)
|
||||
{ PIOA, PIO_PA13A_TXD1, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // TXD1
|
||||
{ PIOA, PIO_PA12A_RXD1, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // RXD1
|
||||
|
||||
// 18/19 - USART0 (Serial1)
|
||||
{ PIOA, PIO_PA11A_TXD0, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // TXD0
|
||||
{ PIOA, PIO_PA10A_RXD0, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // RXD0
|
||||
|
||||
// 20/21 - TWI1
|
||||
{ PIOB, PIO_PB12A_TWD1, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // TWD1 - SDA0
|
||||
{ PIOB, PIO_PB13A_TWCK1, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // TWCK1 - SCL0
|
||||
|
||||
// 22
|
||||
{ PIOB, PIO_PB26, ID_PIOB, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 22
|
||||
{ PIOA, PIO_PA14, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 23
|
||||
{ PIOA, PIO_PA15, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 24
|
||||
{ PIOD, PIO_PD0, ID_PIOD, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 25
|
||||
|
||||
// 26
|
||||
{ PIOD, PIO_PD1, ID_PIOD, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 26
|
||||
{ PIOD, PIO_PD2, ID_PIOD, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 27
|
||||
{ PIOD, PIO_PD3, ID_PIOD, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 28
|
||||
{ PIOD, PIO_PD6, ID_PIOD, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 29
|
||||
|
||||
// 30
|
||||
{ PIOD, PIO_PD9, ID_PIOD, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 30
|
||||
{ PIOA, PIO_PA7, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 31
|
||||
{ PIOD, PIO_PD10, ID_PIOD, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 32
|
||||
{ PIOC, PIO_PC1, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 33
|
||||
|
||||
// 34
|
||||
|
||||
// start of custom pins
|
||||
{ PIOA, PIO_PA29, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 34 Y_STEP_PIN
|
||||
{ PIOB, PIO_PB1, ID_PIOB, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 35 Y_DIR_PIN
|
||||
{ PIOB, PIO_PB0, ID_PIOB, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 36 Y_ENABLE_PIN
|
||||
{ PIOB, PIO_PB22, ID_PIOB, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 37 E0_ENABLE_PIN
|
||||
{ PIOB, PIO_PB11, ID_PIOB, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 38 E0_MS1_PIN
|
||||
{ PIOB, PIO_PB10, ID_PIOB, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 39 E0_MS3_PIN
|
||||
{ PIOA, PIO_PA5, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 40 HEATER_0_PIN
|
||||
{ PIOB, PIO_PB24, ID_PIOB, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 41 HEATER_BED_PIN
|
||||
// end of custom pins
|
||||
|
||||
// 42
|
||||
{ PIOA, PIO_PA19, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 42
|
||||
{ PIOA, PIO_PA20, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 43
|
||||
{ PIOC, PIO_PC19, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 44
|
||||
{ PIOC, PIO_PC18, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 45
|
||||
|
||||
// 46
|
||||
{ PIOC, PIO_PC17, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 46
|
||||
{ PIOC, PIO_PC16, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 47
|
||||
{ PIOC, PIO_PC15, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 48
|
||||
{ PIOC, PIO_PC14, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 49
|
||||
|
||||
// 50
|
||||
{ PIOC, PIO_PC13, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 50
|
||||
{ PIOC, PIO_PC12, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 51
|
||||
{ PIOB, PIO_PB21, ID_PIOB, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 52
|
||||
{ PIOB, PIO_PB14, ID_PIOB, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // PIN 53
|
||||
|
||||
// 54 .. 65 - Analog pins
|
||||
// ----------------------
|
||||
{ PIOA, PIO_PA16X1_AD7, ID_PIOA, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC0, ADC7, NOT_ON_PWM, NOT_ON_TIMER }, // AD0
|
||||
{ PIOA, PIO_PA24X1_AD6, ID_PIOA, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC1, ADC6, NOT_ON_PWM, NOT_ON_TIMER }, // AD1
|
||||
{ PIOA, PIO_PA23X1_AD5, ID_PIOA, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC2, ADC5, NOT_ON_PWM, NOT_ON_TIMER }, // AD2
|
||||
{ PIOA, PIO_PA22X1_AD4, ID_PIOA, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC3, ADC4, NOT_ON_PWM, NOT_ON_TIMER }, // AD3
|
||||
// 58
|
||||
{ PIOA, PIO_PA6X1_AD3, ID_PIOA, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC4, ADC3, NOT_ON_PWM, TC0_CHB2 }, // AD4
|
||||
{ PIOA, PIO_PA4X1_AD2, ID_PIOA, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC5, ADC2, NOT_ON_PWM, NOT_ON_TIMER }, // AD5
|
||||
{ PIOA, PIO_PA3X1_AD1, ID_PIOA, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC6, ADC1, NOT_ON_PWM, TC0_CHB1 }, // AD6
|
||||
{ PIOA, PIO_PA2X1_AD0, ID_PIOA, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC7, ADC0, NOT_ON_PWM, TC0_CHA1 }, // AD7
|
||||
// 62
|
||||
{ PIOB, PIO_PB17X1_AD10, ID_PIOB, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC8, ADC10, NOT_ON_PWM, NOT_ON_TIMER }, // AD8
|
||||
{ PIOB, PIO_PB18X1_AD11, ID_PIOB, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC9, ADC11, NOT_ON_PWM, NOT_ON_TIMER }, // AD9
|
||||
{ PIOB, PIO_PB19X1_AD12, ID_PIOB, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC10, ADC12, NOT_ON_PWM, NOT_ON_TIMER }, // AD10
|
||||
{ PIOB, PIO_PB20X1_AD13, ID_PIOB, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC11, ADC13, NOT_ON_PWM, NOT_ON_TIMER }, // AD11
|
||||
|
||||
// 66/67 - DAC0/DAC1
|
||||
{ PIOB, PIO_PB15X1_DAC0, ID_PIOB, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC12, DA0, NOT_ON_PWM, NOT_ON_TIMER }, // DAC0
|
||||
{ PIOB, PIO_PB16X1_DAC1, ID_PIOB, PIO_INPUT, PIO_DEFAULT, PIN_ATTR_ANALOG, ADC13, DA1, NOT_ON_PWM, NOT_ON_TIMER }, // DAC1
|
||||
|
||||
// 68/69 - CANRX0/CANTX0
|
||||
{ PIOA, PIO_PA1A_CANRX0, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, ADC14, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // CANRX
|
||||
{ PIOA, PIO_PA0A_CANTX0, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, ADC15, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // CANTX
|
||||
|
||||
// 70/71 - TWI0
|
||||
{ PIOA, PIO_PA17A_TWD0, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // TWD0 - SDA1
|
||||
{ PIOA, PIO_PA18A_TWCK0, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // TWCK0 - SCL1
|
||||
|
||||
// 72/73 - LEDs
|
||||
{ PIOC, PIO_PC30, ID_PIOC, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // LED AMBER RXL
|
||||
{ PIOA, PIO_PA21, ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // LED AMBER TXL
|
||||
|
||||
// 74/75/76 - SPI
|
||||
{ PIOA, PIO_PA25A_SPI0_MISO,ID_PIOA,PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // MISO
|
||||
{ PIOA, PIO_PA26A_SPI0_MOSI,ID_PIOA,PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // MOSI
|
||||
{ PIOA, PIO_PA27A_SPI0_SPCK,ID_PIOA,PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // SPCK
|
||||
|
||||
// 77 - SPI CS0
|
||||
{ PIOA, PIO_PA28A_SPI0_NPCS0,ID_PIOA,PIO_PERIPH_A,PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // NPCS0
|
||||
|
||||
// 78 - SPI CS3 (unconnected)
|
||||
{ PIOB, PIO_PB23B_SPI0_NPCS3,ID_PIOB,PIO_PERIPH_B,PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // NPCS3
|
||||
|
||||
// 79 .. 84 - "All pins" masks
|
||||
|
||||
// 79 - TWI0 all pins
|
||||
{ PIOA, PIO_PA17A_TWD0|PIO_PA18A_TWCK0, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_COMBO), NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER },
|
||||
// 80 - TWI1 all pins
|
||||
{ PIOB, PIO_PB12A_TWD1|PIO_PB13A_TWCK1, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_COMBO), NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER },
|
||||
// 81 - UART (Serial) all pins
|
||||
{ PIOA, PIO_PA8A_URXD|PIO_PA9A_UTXD, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_COMBO), NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER },
|
||||
// 82 - USART0 (Serial1) all pins
|
||||
{ PIOA, PIO_PA11A_TXD0|PIO_PA10A_RXD0, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_COMBO), NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER },
|
||||
// 83 - USART1 (Serial2) all pins
|
||||
{ PIOA, PIO_PA13A_TXD1|PIO_PA12A_RXD1, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_COMBO), NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER },
|
||||
// 84 - USART3 (Serial3) all pins
|
||||
{ PIOD, PIO_PD4B_TXD3|PIO_PD5B_RXD3, ID_PIOD, PIO_PERIPH_B, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_COMBO), NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER },
|
||||
|
||||
// 85 - USB
|
||||
{ PIOB, PIO_PB11A_UOTGID|PIO_PB10A_UOTGVBOF, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL,NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // ID - VBOF
|
||||
|
||||
// 86 - SPI CS2
|
||||
{ PIOB, PIO_PB21B_SPI0_NPCS2, ID_PIOB, PIO_PERIPH_B, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // NPCS2
|
||||
|
||||
// 87 - SPI CS1
|
||||
{ PIOA, PIO_PA29A_SPI0_NPCS1, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // NPCS1
|
||||
|
||||
// 88/89 - CANRX1/CANTX1 (same physical pin for 66/53)
|
||||
{ PIOB, PIO_PB15A_CANRX1, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // CANRX1
|
||||
{ PIOB, PIO_PB14A_CANTX1, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, PIN_ATTR_DIGITAL, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }, // CANTX1
|
||||
|
||||
// 90 .. 91 - "All CAN pins" masks
|
||||
// 90 - CAN0 all pins
|
||||
{ PIOA, PIO_PA1A_CANRX0|PIO_PA0A_CANTX0, ID_PIOA, PIO_PERIPH_A, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_COMBO), NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER },
|
||||
// 91 - CAN1 all pins
|
||||
{ PIOB, PIO_PB15A_CANRX1|PIO_PB14A_CANTX1, ID_PIOB, PIO_PERIPH_A, PIO_DEFAULT, (PIN_ATTR_DIGITAL|PIN_ATTR_COMBO), NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER },
|
||||
|
||||
// END
|
||||
{ nullptr, 0, 0, PIO_NOT_A_PIN, PIO_DEFAULT, 0, NO_ADC, NO_ADC, NOT_ON_PWM, NOT_ON_TIMER }
|
||||
};
|
||||
|
||||
// This section replaces the FASTIO definitions of pins 34-41
|
||||
|
||||
#define DIO34_PIN 29
|
||||
#define DIO34_WPORT PIOA // only available via FASTIO // 34 PA29 - Y_STEP_PIN
|
||||
|
||||
#define DIO35_PIN 1
|
||||
#define DIO35_WPORT PIOB // only available via FASTIO // 35 PAB1 - Y_DIR_PIN
|
||||
|
||||
#define DIO36_PIN 0
|
||||
#define DIO36_WPORT PIOB // only available via FASTIO // 36 PB0 - Y_ENABLE_PIN
|
||||
|
||||
#define DIO37_PIN 22
|
||||
#define DIO37_WPORT PIOB // only available via FASTIO // 37 PB22 - E0_ENABLE_PIN
|
||||
|
||||
#define DIO38_PIN 11
|
||||
#define DIO38_WPORT PIOB // only available via FASTIO // 38 PB11 - E0_MS1_PIN
|
||||
|
||||
#define DIO39_PIN 10
|
||||
#define DIO39_WPORT PIOB // only available via FASTIO // 39 PB10 - E0_MS3_PIN
|
||||
|
||||
#define DIO40_PIN 5
|
||||
#define DIO40_WPORT PIOA // only available via FASTIO // 40 PA5 - HEATER_0_PIN
|
||||
|
||||
#define DIO41_PIN 24
|
||||
#define DIO41_WPORT PIOB // only available via FASTIO // 41 PB24 - HEATER_BED_PIN
|
|
@ -0,0 +1,22 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
|
@ -0,0 +1,22 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
|
@ -0,0 +1,28 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#if USE_FALLBACK_EEPROM
|
||||
#define FLASH_EEPROM_EMULATION
|
||||
#elif ANY(I2C_EEPROM, SPI_EEPROM)
|
||||
#define USE_SHARED_EEPROM 1
|
||||
#endif
|
|
@ -0,0 +1,92 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Test Arduino Due specific configuration values for errors at compile-time.
|
||||
*/
|
||||
|
||||
#if HAS_SPI_TFT || HAS_FSMC_TFT
|
||||
#error "Sorry! TFT displays are not available for HAL/DUE."
|
||||
#endif
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* DUE selects hardware vs. software SPI depending on whether one of the hardware-controllable SDSS pins is in use.
|
||||
*
|
||||
* The hardware SPI controller doesn't allow software SPIs to control any shared pins.
|
||||
*
|
||||
* When DUE software SPI is used then Trinamic drivers must use the TMC softSPI.
|
||||
*
|
||||
* When DUE hardware SPI is used then a Trinamic driver can use either its hardware SPI or, if there are no shared
|
||||
* pins, its software SPI.
|
||||
*
|
||||
* Usually the hardware SPI pins are only available to the LCD. This makes the DUE hard SPI used at the same time
|
||||
* as the TMC2130 soft SPI the most common setup.
|
||||
*/
|
||||
#if HAS_MEDIA && HAS_DRIVER(TMC2130)
|
||||
#define _IS_HW_SPI(P) (defined(TMC_SPI_##P) && (TMC_SPI_##P == SD_MOSI_PIN || TMC_SPI_##P == SD_MISO_PIN || TMC_SPI_##P == SD_SCK_PIN))
|
||||
#if DISABLED(DUE_SOFTWARE_SPI) && ENABLED(TMC_USE_SW_SPI) && (_IS_HW_SPI(MOSI) || _IS_HW_SPI(MISO) || _IS_HW_SPI(SCK))
|
||||
#error "DUE hardware SPI is required but is incompatible with TMC2130 software SPI. Either disable TMC_USE_SW_SPI or use separate pins for the two SPIs."
|
||||
#endif
|
||||
#if ENABLED(DUE_SOFTWARE_SPI) && DISABLED(TMC_USE_SW_SPI)
|
||||
#error "DUE software SPI is required but is incompatible with TMC2130 hardware SPI. Enable TMC_USE_SW_SPI to fix."
|
||||
#endif
|
||||
#undef _IS_HW_SPI
|
||||
#endif
|
||||
|
||||
#if ENABLED(FAST_PWM_FAN) || SPINDLE_LASER_FREQUENCY
|
||||
#error "Features requiring Hardware PWM (FAST_PWM_FAN, SPINDLE_LASER_FREQUENCY) are not yet supported for HAL/DUE."
|
||||
#endif
|
||||
|
||||
#if HAS_TMC_SW_SERIAL
|
||||
#error "TMC220x Software Serial is not supported on the DUE platform."
|
||||
#endif
|
||||
|
||||
#if USING_PULLDOWNS
|
||||
#error "PULLDOWN pin mode is not available on DUE boards."
|
||||
#endif
|
|
@ -0,0 +1,186 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Support routines for Due
|
||||
*/
|
||||
|
||||
/**
|
||||
* Translation of routines & variables used by pinsDebug.h
|
||||
*/
|
||||
|
||||
#include "../shared/Marduino.h"
|
||||
|
||||
/**
|
||||
* Due/Marlin quirks
|
||||
*
|
||||
* a) determining the state of a pin
|
||||
* The Due/Arduino status definitions for the g_pinStatus[pin] array are:
|
||||
* #define PIN_STATUS_DIGITAL_INPUT_PULLUP (0x01)
|
||||
* #define PIN_STATUS_DIGITAL_INPUT (0x02)
|
||||
* #define PIN_STATUS_DIGITAL_OUTPUT (0x03)
|
||||
* #define PIN_STATUS_ANALOG (0x04)
|
||||
* #define PIN_STATUS_PWM (0x05)
|
||||
* #define PIN_STATUS_TIMER (0x06)
|
||||
*
|
||||
* These are only valid if the following Due/Arduino provided functions are used:
|
||||
* analogRead
|
||||
* analogWrite
|
||||
* digitalWrite
|
||||
* pinMode
|
||||
*
|
||||
* The FASTIO routines do not touch the g_pinStatus[pin] array.
|
||||
*
|
||||
* The net result is that both the g_pinStatus[pin] array and the PIO_OSR register
|
||||
* needs to be looked at when determining if a pin is an input or an output.
|
||||
*
|
||||
* b) Due has only pins 6, 7, 8 & 9 enabled for PWMs. FYI - they run at 1kHz
|
||||
*
|
||||
* c) NUM_DIGITAL_PINS does not include the analog pins
|
||||
*
|
||||
* d) Pins 0-78 are defined for Due but 78 has a comment of "unconnected!". 78 is
|
||||
* included just in case.
|
||||
*/
|
||||
|
||||
#define NUMBER_PINS_TOTAL PINS_COUNT
|
||||
|
||||
#define digitalRead_mod(p) extDigitalRead(p) // AVR digitalRead disabled PWM before it read the pin
|
||||
#define PRINT_ARRAY_NAME(x) do{ sprintf_P(buffer, PSTR("%-" STRINGIFY(MAX_NAME_LENGTH) "s"), pin_array[x].name); SERIAL_ECHO(buffer); }while(0)
|
||||
#define PRINT_PIN(p) do{ sprintf_P(buffer, PSTR("%02d"), p); SERIAL_ECHO(buffer); }while(0)
|
||||
#define PRINT_PIN_ANALOG(p) do{ sprintf_P(buffer, PSTR(" (A%2d) "), DIGITAL_PIN_TO_ANALOG_PIN(pin)); SERIAL_ECHO(buffer); }while(0)
|
||||
#define GET_ARRAY_PIN(p) pin_array[p].pin
|
||||
#define GET_ARRAY_IS_DIGITAL(p) pin_array[p].is_digital
|
||||
#define VALID_PIN(pin) (pin >= 0 && pin < int8_t(NUMBER_PINS_TOTAL))
|
||||
#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) && \
|
||||
((g_APinDescription[pin].ulPinAttribute & PIN_ATTR_PWM) == PIN_ATTR_PWM))
|
||||
#define MULTI_NAME_PAD 14 // space needed to be pretty if not first name assigned to a pin
|
||||
|
||||
bool GET_PINMODE(int8_t pin) { // 1: output, 0: input
|
||||
volatile Pio* port = g_APinDescription[pin].pPort;
|
||||
uint32_t mask = g_APinDescription[pin].ulPin;
|
||||
uint8_t pin_status = g_pinStatus[pin] & 0xF;
|
||||
return ( (pin_status == 0 && (port->PIO_OSR & mask))
|
||||
|| pin_status == PIN_STATUS_DIGITAL_OUTPUT
|
||||
|| pwm_status(pin));
|
||||
}
|
||||
|
||||
void pwm_details(int32_t pin) {
|
||||
if (pwm_status(pin)) {
|
||||
uint32_t chan = g_APinDescription[pin].ulPWMChannel;
|
||||
SERIAL_ECHOPGM("PWM = ", PWM_INTERFACE->PWM_CH_NUM[chan].PWM_CDTY);
|
||||
}
|
||||
}
|
||||
|
||||
void print_port(const pin_t) {}
|
||||
|
||||
/**
|
||||
* DUE Board pin | PORT | Label
|
||||
* ----------------+--------+-------
|
||||
* 0 | PA8 | "RX0"
|
||||
* 1 | PA9 | "TX0"
|
||||
* 2 TIOA0 | PB25 |
|
||||
* 3 TIOA7 | PC28 |
|
||||
* 4 NPCS1 | PA29 |
|
||||
* TIOB6 | PC26 |
|
||||
* 5 TIOA6 | PC25 |
|
||||
* 6 PWML7 | PC24 |
|
||||
* 7 PWML6 | PC23 |
|
||||
* 8 PWML5 | PC22 |
|
||||
* 9 PWML4 | PC21 |
|
||||
* 10 NPCS0 | PA28 |
|
||||
* TIOB7 | PC29 |
|
||||
* 11 TIOA8 | PD7 |
|
||||
* 12 TIOB8 | PD8 |
|
||||
* 13 TIOB0 | PB27 | LED AMBER "L"
|
||||
* 14 TXD3 | PD4 | "TX3"
|
||||
* 15 RXD3 | PD5 | "RX3"
|
||||
* 16 TXD1 | PA13 | "TX2"
|
||||
* 17 RXD1 | PA12 | "RX2"
|
||||
* 18 TXD0 | PA11 | "TX1"
|
||||
* 19 RXD0 | PA10 | "RX1"
|
||||
* 20 | PB12 | "SDA"
|
||||
* 21 | PB13 | "SCL"
|
||||
* 22 | PB26 |
|
||||
* 23 | PA14 |
|
||||
* 24 | PA15 |
|
||||
* 25 | PD0 |
|
||||
* 26 | PD1 |
|
||||
* 27 | PD2 |
|
||||
* 28 | PD3 |
|
||||
* 29 | PD6 |
|
||||
* 30 | PD9 |
|
||||
* 31 | PA7 |
|
||||
* 32 | PD10 |
|
||||
* 33 | PC1 |
|
||||
* 34 | PC2 |
|
||||
* 35 | PC3 |
|
||||
* 36 | PC4 |
|
||||
* 37 | PC5 |
|
||||
* 38 | PC6 |
|
||||
* 39 | PC7 |
|
||||
* 40 | PC8 |
|
||||
* 41 | PC9 |
|
||||
* 42 | PA19 |
|
||||
* 43 | PA20 |
|
||||
* 44 | PC19 |
|
||||
* 45 | PC18 |
|
||||
* 46 | PC17 |
|
||||
* 47 | PC16 |
|
||||
* 48 | PC15 |
|
||||
* 49 | PC14 |
|
||||
* 50 | PC13 |
|
||||
* 51 | PC12 |
|
||||
* 52 NPCS2 | PB21 |
|
||||
* 53 | PB14 |
|
||||
* 54 | PA16 | "A0"
|
||||
* 55 | PA24 | "A1"
|
||||
* 56 | PA23 | "A2"
|
||||
* 57 | PA22 | "A3"
|
||||
* 58 TIOB2 | PA6 | "A4"
|
||||
* 69 | PA4 | "A5"
|
||||
* 60 TIOB1 | PA3 | "A6"
|
||||
* 61 TIOA1 | PA2 | "A7"
|
||||
* 62 | PB17 | "A8"
|
||||
* 63 | PB18 | "A9"
|
||||
* 64 | PB19 | "A10"
|
||||
* 65 | PB20 | "A11"
|
||||
* 66 | PB15 | "DAC0"
|
||||
* 67 | PB16 | "DAC1"
|
||||
* 68 | PA1 | "CANRX"
|
||||
* 69 | PA0 | "CANTX"
|
||||
* 70 | PA17 | "SDA1"
|
||||
* 71 | PA18 | "SCL1"
|
||||
* 72 | PC30 | LED AMBER "RX"
|
||||
* 73 | PA21 | LED AMBER "TX"
|
||||
* 74 MISO | PA25 |
|
||||
* 75 MOSI | PA26 |
|
||||
* 76 SCLK | PA27 |
|
||||
* 77 NPCS0 | PA28 |
|
||||
* 78 NPCS3 | PB23 | unconnected!
|
||||
*
|
||||
* USB pin | PORT
|
||||
* ----------------+--------
|
||||
* ID | PB11
|
||||
* VBOF | PB10
|
||||
*/
|
|
@ -0,0 +1,64 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Define SPI Pins: SCK, MISO, MOSI, SS
|
||||
*
|
||||
* Available chip select pins for HW SPI are 4 10 52 77 87
|
||||
*/
|
||||
#if SDSS == 4 || SDSS == 10 || SDSS == 52 || SDSS == 77 || SDSS == 87
|
||||
#if SDSS == 4
|
||||
#define SPI_PIN 87
|
||||
#define SPI_CHAN 1
|
||||
#elif SDSS == 10
|
||||
#define SPI_PIN 77
|
||||
#define SPI_CHAN 0
|
||||
#elif SDSS == 52
|
||||
#define SPI_PIN 86
|
||||
#define SPI_CHAN 2
|
||||
#elif SDSS == 77
|
||||
#define SPI_PIN 77
|
||||
#define SPI_CHAN 0
|
||||
#else
|
||||
#define SPI_PIN 87
|
||||
#define SPI_CHAN 1
|
||||
#endif
|
||||
#define SD_SCK_PIN 76
|
||||
#define SD_MISO_PIN 74
|
||||
#define SD_MOSI_PIN 75
|
||||
#else
|
||||
// defaults
|
||||
#define DUE_SOFTWARE_SPI
|
||||
#ifndef SD_SCK_PIN
|
||||
#define SD_SCK_PIN 52
|
||||
#endif
|
||||
#ifndef SD_MISO_PIN
|
||||
#define SD_MISO_PIN 50
|
||||
#endif
|
||||
#ifndef SD_MOSI_PIN
|
||||
#define SD_MOSI_PIN 51
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* A.28, A.29, B.21, C.26, C.29 */
|
||||
#define SD_SS_PIN SDSS
|
|
@ -0,0 +1,139 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* HAL Timers for Arduino Due and compatible (SAM3X8E)
|
||||
*/
|
||||
|
||||
#ifdef ARDUINO_ARCH_SAM
|
||||
|
||||
// ------------------------
|
||||
// Includes
|
||||
// ------------------------
|
||||
#include "../../inc/MarlinConfig.h"
|
||||
#include "HAL.h"
|
||||
|
||||
// ------------------------
|
||||
// Local defines
|
||||
// ------------------------
|
||||
|
||||
#define NUM_HARDWARE_TIMERS 9
|
||||
|
||||
// ------------------------
|
||||
// Private Variables
|
||||
// ------------------------
|
||||
|
||||
const tTimerConfig timer_config[NUM_HARDWARE_TIMERS] = {
|
||||
{ TC0, 0, TC0_IRQn, 3}, // 0 - [servo timer5]
|
||||
{ TC0, 1, TC1_IRQn, 0}, // 1
|
||||
{ TC0, 2, TC2_IRQn, 2}, // 2 - stepper
|
||||
{ TC1, 0, TC3_IRQn, 0}, // 3 - stepper for BOARD_ARCHIM1
|
||||
{ TC1, 1, TC4_IRQn, 15}, // 4 - temperature
|
||||
{ TC1, 2, TC5_IRQn, 3}, // 5 - [servo timer3]
|
||||
{ TC2, 0, TC6_IRQn, 14}, // 6 - tone
|
||||
{ TC2, 1, TC7_IRQn, 0}, // 7
|
||||
{ TC2, 2, TC8_IRQn, 0}, // 8
|
||||
};
|
||||
|
||||
// ------------------------
|
||||
// Public functions
|
||||
// ------------------------
|
||||
|
||||
/*
|
||||
Timer_clock1: Prescaler 2 -> 42MHz
|
||||
Timer_clock2: Prescaler 8 -> 10.5MHz
|
||||
Timer_clock3: Prescaler 32 -> 2.625MHz
|
||||
Timer_clock4: Prescaler 128 -> 656.25kHz
|
||||
*/
|
||||
|
||||
void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
|
||||
Tc *tc = timer_config[timer_num].pTimerRegs;
|
||||
IRQn_Type irq = timer_config[timer_num].IRQ_Id;
|
||||
uint32_t channel = timer_config[timer_num].channel;
|
||||
|
||||
// Disable interrupt, just in case it was already enabled
|
||||
NVIC_DisableIRQ(irq);
|
||||
|
||||
// We NEED memory barriers to ensure Interrupts are actually disabled!
|
||||
// ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
|
||||
__DSB();
|
||||
__ISB();
|
||||
|
||||
// Disable timer interrupt
|
||||
tc->TC_CHANNEL[channel].TC_IDR = TC_IDR_CPCS;
|
||||
|
||||
// Stop timer, just in case, to be able to reconfigure it
|
||||
TC_Stop(tc, channel);
|
||||
|
||||
pmc_set_writeprotect(false);
|
||||
pmc_enable_periph_clk((uint32_t)irq);
|
||||
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
|
||||
| (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 / (HAL_TIMER_PRESCALER) / frequency);
|
||||
|
||||
// And start timer
|
||||
TC_Start(tc, channel);
|
||||
|
||||
// enable interrupt on RC compare
|
||||
tc->TC_CHANNEL[channel].TC_IER = TC_IER_CPCS;
|
||||
|
||||
// Finally, enable IRQ
|
||||
NVIC_EnableIRQ(irq);
|
||||
}
|
||||
|
||||
void HAL_timer_enable_interrupt(const uint8_t timer_num) {
|
||||
IRQn_Type irq = timer_config[timer_num].IRQ_Id;
|
||||
NVIC_EnableIRQ(irq);
|
||||
}
|
||||
|
||||
void HAL_timer_disable_interrupt(const uint8_t timer_num) {
|
||||
IRQn_Type irq = timer_config[timer_num].IRQ_Id;
|
||||
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();
|
||||
}
|
||||
|
||||
// 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) {
|
||||
IRQn_Type irq = timer_config[timer_num].IRQ_Id;
|
||||
return NVIC_GetEnabledIRQ(irq);
|
||||
}
|
||||
|
||||
#endif // ARDUINO_ARCH_SAM
|
|
@ -0,0 +1,130 @@
|
|||
/**
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* HAL Timers for Arduino Due and compatible (SAM3X8E)
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// ------------------------
|
||||
// Defines
|
||||
// ------------------------
|
||||
|
||||
#define FORCE_INLINE __attribute__((always_inline)) inline
|
||||
|
||||
typedef uint32_t hal_timer_t;
|
||||
#define HAL_TIMER_TYPE_MAX 0xFFFFFFFF
|
||||
|
||||
#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
|
||||
#endif
|
||||
#ifndef MF_TIMER_PULSE
|
||||
#define MF_TIMER_PULSE MF_TIMER_STEP
|
||||
#endif
|
||||
#ifndef MF_TIMER_TEMP
|
||||
#define MF_TIMER_TEMP 4 // Timer Index for Temperature
|
||||
#endif
|
||||
#ifndef MF_TIMER_TONE
|
||||
#define MF_TIMER_TONE 6 // index of timer to use for beeper tones
|
||||
#endif
|
||||
|
||||
#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 // frequency of pulse timer
|
||||
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
|
||||
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
|
||||
|
||||
#define ENABLE_STEPPER_DRIVER_INTERRUPT() HAL_timer_enable_interrupt(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)
|
||||
|
||||
#ifndef HAL_STEP_TIMER_ISR
|
||||
#define HAL_STEP_TIMER_ISR() void TC2_Handler()
|
||||
#endif
|
||||
#ifndef HAL_TEMP_TIMER_ISR
|
||||
#define HAL_TEMP_TIMER_ISR() void TC4_Handler()
|
||||
#endif
|
||||
#ifndef HAL_TONE_TIMER_ISR
|
||||
#define HAL_TONE_TIMER_ISR() void TC6_Handler()
|
||||
#endif
|
||||
|
||||
// ------------------------
|
||||
// Types
|
||||
// ------------------------
|
||||
|
||||
typedef struct {
|
||||
Tc *pTimerRegs;
|
||||
uint16_t channel;
|
||||
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) {
|
||||
const tTimerConfig * const pConfig = &timer_config[timer_num];
|
||||
pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_RC = compare;
|
||||
}
|
||||
|
||||
FORCE_INLINE static hal_timer_t HAL_timer_get_compare(const uint8_t timer_num) {
|
||||
const tTimerConfig * const pConfig = &timer_config[timer_num];
|
||||
return pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_RC;
|
||||
}
|
||||
|
||||
FORCE_INLINE static hal_timer_t HAL_timer_get_count(const uint8_t timer_num) {
|
||||
const tTimerConfig * const pConfig = &timer_config[timer_num];
|
||||
return pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_CV;
|
||||
}
|
||||
|
||||
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) {
|
||||
const tTimerConfig * const pConfig = &timer_config[timer_num];
|
||||
// Reading the status register clears the interrupt flag
|
||||
pConfig->pTimerRegs->TC_CHANNEL[pConfig->channel].TC_SR;
|
||||
}
|
||||
|
||||
#define HAL_timer_isr_epilogue(T) NOOP
|
|
@ -0,0 +1,19 @@
|
|||
#
|
||||
# Set upload_command
|
||||
#
|
||||
# Windows: bossac.exe
|
||||
# Other: leave unchanged
|
||||
#
|
||||
import pioutil
|
||||
if pioutil.is_pio_build():
|
||||
import platform
|
||||
current_OS = platform.system()
|
||||
|
||||
if current_OS == 'Windows':
|
||||
|
||||
Import("env")
|
||||
|
||||
# Use bossac.exe on Windows
|
||||
env.Replace(
|
||||
UPLOADCMD="bossac --info --unlock --write --verify --reset --erase -U false --boot $SOURCE"
|
||||
)
|
|
@ -0,0 +1,97 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief Arduino Due/X Board Definition.
|
||||
*
|
||||
* Copyright (c) 2011-2015 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
/**
|
||||
* Support and FAQ: visit <a href="https://www.atmel.com/design-support/">Atmel Support</a>
|
||||
*/
|
||||
|
||||
/**
|
||||
* \page arduino_due_x_opfreq "Arduino Due/X - Operating frequencies"
|
||||
* This page lists several definition related to the board operating frequency
|
||||
*
|
||||
* \section Definitions
|
||||
* - \ref BOARD_FREQ_*
|
||||
* - \ref BOARD_MCK
|
||||
*/
|
||||
|
||||
/*! Board oscillator settings */
|
||||
#define BOARD_FREQ_SLCK_XTAL (32768U)
|
||||
#define BOARD_FREQ_SLCK_BYPASS (32768U)
|
||||
#define BOARD_FREQ_MAINCK_XTAL (12000000U)
|
||||
#define BOARD_FREQ_MAINCK_BYPASS (12000000U)
|
||||
|
||||
/*! Master clock frequency */
|
||||
#define BOARD_MCK CHIP_FREQ_CPU_MAX
|
||||
#define BOARD_NO_32K_XTAL
|
||||
|
||||
/** board main clock xtal startup time */
|
||||
#define BOARD_OSC_STARTUP_US 15625
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
/**
|
||||
* \page arduino_due_x_board_info "Arduino Due/X - Board information"
|
||||
* This page lists several definition related to the board description.
|
||||
*
|
||||
*/
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* USB */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/*! USB OTG VBus On/Off: Bus Power Control Port. */
|
||||
#define PIN_UOTGHS_VBOF { PIO_PB10, PIOB, ID_PIOB, PIO_PERIPH_A, PIO_PULLUP }
|
||||
/*! USB OTG Identification: Mini Connector Identification Port. */
|
||||
#define PIN_UOTGHS_ID { PIO_PB11, PIOB, ID_PIOB, PIO_PERIPH_A, PIO_PULLUP }
|
||||
|
||||
/*! Multiplexed pin used for USB_ID: */
|
||||
#define USB_ID PIO_PB11_IDX
|
||||
#define USB_ID_GPIO (PIO_PB11_IDX)
|
||||
#define USB_ID_FLAGS (PIO_PERIPH_A | PIO_DEFAULT)
|
||||
/*! Multiplexed pin used for USB_VBOF: */
|
||||
#define USB_VBOF PIO_PB10_IDX
|
||||
#define USB_VBOF_GPIO (PIO_PB10_IDX)
|
||||
#define USB_VBOF_FLAGS (PIO_PERIPH_A | PIO_DEFAULT)
|
||||
/*! Active level of the USB_VBOF output pin. */
|
||||
#define USB_VBOF_ACTIVE_STATE LOW
|
||||
/* ------------------------------------------------------------------------ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,114 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief Memory access control configuration file.
|
||||
*
|
||||
* Copyright (c) 2012-2015 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Support and FAQ: visit <a href="https://www.atmel.com/design-support/">Atmel Support</a>
|
||||
*/
|
||||
|
||||
#ifndef _CONF_ACCESS_H_
|
||||
#define _CONF_ACCESS_H_
|
||||
|
||||
#include "compiler.h"
|
||||
#include "../../../inc/MarlinConfigPre.h"
|
||||
|
||||
/*! \name Activation of Logical Unit Numbers
|
||||
*/
|
||||
//! @{
|
||||
|
||||
#define LUN_0 ENABLE //!< SD/MMC Card over MCI Slot 0.
|
||||
#define LUN_1 DISABLE
|
||||
#define LUN_2 DISABLE
|
||||
#define LUN_3 DISABLE
|
||||
#define LUN_4 DISABLE
|
||||
#define LUN_5 DISABLE
|
||||
#define LUN_6 DISABLE
|
||||
#define LUN_7 DISABLE
|
||||
#define LUN_USB DISABLE
|
||||
//! @}
|
||||
|
||||
/*! \name LUN 0 Definitions
|
||||
*/
|
||||
//! @{
|
||||
#define SD_MMC_SPI_MEM LUN_0
|
||||
#define LUN_ID_SD_MMC_SPI_MEM LUN_ID_0
|
||||
#define LUN_0_INCLUDE "sd_mmc_spi_mem.h"
|
||||
#define Lun_0_test_unit_ready sd_mmc_spi_test_unit_ready
|
||||
#define Lun_0_read_capacity sd_mmc_spi_read_capacity
|
||||
#define Lun_0_unload sd_mmc_spi_unload
|
||||
#define Lun_0_wr_protect sd_mmc_spi_wr_protect
|
||||
#define Lun_0_removal sd_mmc_spi_removal
|
||||
#define Lun_0_usb_read_10 sd_mmc_spi_usb_read_10
|
||||
#define Lun_0_usb_write_10 sd_mmc_spi_usb_write_10
|
||||
#define LUN_0_NAME "\"SD/MMC Card\""
|
||||
//! @}
|
||||
|
||||
/*! \name Actions Associated with Memory Accesses
|
||||
*
|
||||
* Write here the action to associate with each memory access.
|
||||
*
|
||||
* \warning Be careful not to waste time in order not to disturb the functions.
|
||||
*/
|
||||
//! @{
|
||||
#define memory_start_read_action(nb_sectors)
|
||||
#define memory_stop_read_action()
|
||||
#define memory_start_write_action(nb_sectors)
|
||||
#define memory_stop_write_action()
|
||||
//! @}
|
||||
|
||||
/*! \name Activation of Interface Features
|
||||
*/
|
||||
//! @{
|
||||
#define ACCESS_USB true //!< MEM <-> USB interface.
|
||||
#define ACCESS_MEM_TO_RAM false //!< MEM <-> RAM interface.
|
||||
#define ACCESS_STREAM false //!< Streaming MEM <-> MEM interface.
|
||||
#define ACCESS_STREAM_RECORD false //!< Streaming MEM <-> MEM interface in record mode.
|
||||
#define ACCESS_MEM_TO_MEM false //!< MEM <-> MEM interface.
|
||||
#define ACCESS_CODEC false //!< Codec interface.
|
||||
//! @}
|
||||
|
||||
/*! \name Specific Options for Access Control
|
||||
*/
|
||||
//! @{
|
||||
#define GLOBAL_WR_PROTECT false //!< Management of a global write protection.
|
||||
//! @}
|
||||
|
||||
#endif // _CONF_ACCESS_H_
|
|
@ -0,0 +1,99 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief SAM3X clock configuration.
|
||||
*
|
||||
* Copyright (c) 2011-2015 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Support and FAQ: visit <a href="https://www.atmel.com/design-support/">Atmel Support</a>
|
||||
*/
|
||||
|
||||
#ifndef CONF_CLOCK_H_INCLUDED
|
||||
#define CONF_CLOCK_H_INCLUDED
|
||||
|
||||
// ===== System Clock (MCK) Source Options
|
||||
//#define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_SLCK_RC
|
||||
//#define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_SLCK_XTAL
|
||||
//#define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_SLCK_BYPASS
|
||||
//#define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_MAINCK_4M_RC
|
||||
//#define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_MAINCK_8M_RC
|
||||
//#define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_MAINCK_12M_RC
|
||||
//#define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_MAINCK_XTAL
|
||||
//#define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_MAINCK_BYPASS
|
||||
#define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_PLLACK
|
||||
//#define CONFIG_SYSCLK_SOURCE SYSCLK_SRC_UPLLCK
|
||||
|
||||
// ===== System Clock (MCK) Prescaler Options (Fmck = Fsys / (SYSCLK_PRES))
|
||||
//#define CONFIG_SYSCLK_PRES SYSCLK_PRES_1
|
||||
#define CONFIG_SYSCLK_PRES SYSCLK_PRES_2
|
||||
//#define CONFIG_SYSCLK_PRES SYSCLK_PRES_4
|
||||
//#define CONFIG_SYSCLK_PRES SYSCLK_PRES_8
|
||||
//#define CONFIG_SYSCLK_PRES SYSCLK_PRES_16
|
||||
//#define CONFIG_SYSCLK_PRES SYSCLK_PRES_32
|
||||
//#define CONFIG_SYSCLK_PRES SYSCLK_PRES_64
|
||||
//#define CONFIG_SYSCLK_PRES SYSCLK_PRES_3
|
||||
|
||||
// ===== PLL0 (A) Options (Fpll = (Fclk * PLL_mul) / PLL_div)
|
||||
// Use mul and div effective values here.
|
||||
#define CONFIG_PLL0_SOURCE PLL_SRC_MAINCK_XTAL
|
||||
#define CONFIG_PLL0_MUL 14
|
||||
#define CONFIG_PLL0_DIV 1
|
||||
|
||||
// ===== UPLL (UTMI) Hardware fixed at 480MHz.
|
||||
|
||||
// ===== USB Clock Source Options (Fusb = FpllX / USB_div)
|
||||
// Use div effective value here.
|
||||
//#define CONFIG_USBCLK_SOURCE USBCLK_SRC_PLL0
|
||||
#define CONFIG_USBCLK_SOURCE USBCLK_SRC_UPLL
|
||||
#define CONFIG_USBCLK_DIV 1
|
||||
|
||||
// ===== Target frequency (System clock)
|
||||
// - XTAL frequency: 12MHz
|
||||
// - System clock source: PLLA
|
||||
// - System clock prescaler: 2 (divided by 2)
|
||||
// - PLLA source: XTAL
|
||||
// - PLLA output: XTAL * 14 / 1
|
||||
// - System clock is: 12 * 14 / 1 /2 = 84MHz
|
||||
// ===== Target frequency (USB Clock)
|
||||
// - USB clock source: UPLL
|
||||
// - USB clock divider: 1 (not divided)
|
||||
// - UPLL frequency: 480MHz
|
||||
// - USB clock: 480 / 1 = 480MHz
|
||||
|
||||
#endif /* CONF_CLOCK_H_INCLUDED */
|
|
@ -0,0 +1,292 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief USB configuration file
|
||||
*
|
||||
* Copyright (c) 2011-2015 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Support and FAQ: visit <a href="https://www.atmel.com/design-support/">Atmel Support</a>
|
||||
*/
|
||||
|
||||
#ifndef _CONF_USB_H_
|
||||
#define _CONF_USB_H_
|
||||
|
||||
#undef UNUSED /* To avoid a macro clash as macros.h already defines it */
|
||||
#include "../../../inc/MarlinConfigPre.h"
|
||||
#include "compiler.h"
|
||||
|
||||
/**
|
||||
* USB Device Configuration
|
||||
* @{
|
||||
*/
|
||||
|
||||
//! Device definition (mandatory)
|
||||
#define USB_DEVICE_MAJOR_VERSION 1
|
||||
#define USB_DEVICE_MINOR_VERSION 0
|
||||
#define USB_DEVICE_POWER 100 // Consumption on Vbus line (mA)
|
||||
#define USB_DEVICE_ATTR \
|
||||
(USB_CONFIG_ATTR_SELF_POWERED)
|
||||
// (USB_CONFIG_ATTR_BUS_POWERED)
|
||||
// (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_SELF_POWERED)
|
||||
// (USB_CONFIG_ATTR_REMOTE_WAKEUP|USB_CONFIG_ATTR_BUS_POWERED)
|
||||
|
||||
/**
|
||||
* Device speeds support
|
||||
* Low speed not supported by CDC and MSC
|
||||
* @{
|
||||
*/
|
||||
|
||||
//! To define a Low speed device
|
||||
//#define USB_DEVICE_LOW_SPEED
|
||||
|
||||
//! To define a Full speed device
|
||||
//#define USB_DEVICE_FULL_SPEED
|
||||
|
||||
//! To authorize the High speed
|
||||
#ifndef USB_DEVICE_FULL_SPEED
|
||||
#if (UC3A3||UC3A4)
|
||||
#define USB_DEVICE_HS_SUPPORT
|
||||
#elif (SAM3XA||SAM3U)
|
||||
#define USB_DEVICE_HS_SUPPORT
|
||||
#endif
|
||||
#endif
|
||||
//@}
|
||||
|
||||
/**
|
||||
* USB Device Callbacks definitions (Optional)
|
||||
* @{
|
||||
*/
|
||||
#define UDC_VBUS_EVENT(b_vbus_high)
|
||||
#define UDC_SOF_EVENT()
|
||||
#define UDC_SUSPEND_EVENT()
|
||||
#define UDC_RESUME_EVENT()
|
||||
#define UDC_GET_EXTRA_STRING() usb_task_extra_string()
|
||||
#define USB_DEVICE_SPECIFIC_REQUEST() usb_task_other_requests()
|
||||
//@}
|
||||
|
||||
#if HAS_MEDIA
|
||||
/**
|
||||
* USB Device low level configuration
|
||||
* When only one interface is used, these configurations are defined by the class module.
|
||||
* For composite device, these configuration must be defined here
|
||||
* @{
|
||||
*/
|
||||
//! Control endpoint size
|
||||
#define USB_DEVICE_EP_CTRL_SIZE 64
|
||||
|
||||
//! Two interfaces for this device (CDC COM + CDC DATA + MSC)
|
||||
#define USB_DEVICE_NB_INTERFACE 3
|
||||
|
||||
//! 5 endpoints used by CDC and MSC interfaces
|
||||
#if SAM3U
|
||||
// (3 | USB_EP_DIR_IN) // CDC Notify endpoint
|
||||
// (6 | USB_EP_DIR_IN) // CDC TX
|
||||
// (5 | USB_EP_DIR_OUT) // CDC RX
|
||||
// (1 | USB_EP_DIR_IN) // MSC IN
|
||||
// (2 | USB_EP_DIR_OUT) // MSC OUT
|
||||
# define USB_DEVICE_MAX_EP 6
|
||||
# if defined(USB_DEVICE_HS_SUPPORT)
|
||||
// In HS mode, size of bulk endpoints are 512
|
||||
// If CDC and MSC endpoints all uses 2 banks, DPRAM is not enough: 4 bulk
|
||||
// endpoints requires 4K bytes. So reduce the number of banks of CDC bulk
|
||||
// endpoints to use less DPRAM. Keep MSC setting to keep MSC performance.
|
||||
# define UDD_BULK_NB_BANK(ep) ((ep == 5 || ep== 6) ? 1 : 2)
|
||||
#endif
|
||||
#else
|
||||
// (3 | USB_EP_DIR_IN) // CDC Notify endpoint
|
||||
// (4 | USB_EP_DIR_IN) // CDC TX
|
||||
// (5 | USB_EP_DIR_OUT) // CDC RX
|
||||
// (1 | USB_EP_DIR_IN) // MSC IN
|
||||
// (2 | USB_EP_DIR_OUT) // MSC OUT
|
||||
# define USB_DEVICE_MAX_EP 5
|
||||
# if SAM3XA && defined(USB_DEVICE_HS_SUPPORT)
|
||||
// In HS mode, size of bulk endpoints are 512
|
||||
// If CDC and MSC endpoints all uses 2 banks, DPRAM is not enough: 4 bulk
|
||||
// endpoints requires 4K bytes. So reduce the number of banks of CDC bulk
|
||||
// endpoints to use less DPRAM. Keep MSC setting to keep MSC performance.
|
||||
# define UDD_BULK_NB_BANK(ep) ((ep == 4 || ep== 5) ? 1 : 2)
|
||||
# endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//@}
|
||||
|
||||
//@}
|
||||
|
||||
/**
|
||||
* USB Interface Configuration
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* Configuration of CDC interface
|
||||
* @{
|
||||
*/
|
||||
|
||||
//! Define one USB communication ports
|
||||
#define UDI_CDC_PORT_NB 1
|
||||
|
||||
//! Interface callback definition
|
||||
#define UDI_CDC_ENABLE_EXT(port) usb_task_cdc_enable(port)
|
||||
#define UDI_CDC_DISABLE_EXT(port) usb_task_cdc_disable(port)
|
||||
#define UDI_CDC_RX_NOTIFY(port) usb_task_cdc_rx_notify(port)
|
||||
#define UDI_CDC_TX_EMPTY_NOTIFY(port)
|
||||
#define UDI_CDC_SET_CODING_EXT(port,cfg) usb_task_cdc_config(port,cfg)
|
||||
#define UDI_CDC_SET_DTR_EXT(port,set) usb_task_cdc_set_dtr(port,set)
|
||||
#define UDI_CDC_SET_RTS_EXT(port,set)
|
||||
|
||||
//! Define it when the transfer CDC Device to Host is a low rate (<512000 bauds)
|
||||
//! to reduce CDC buffers size
|
||||
//#define UDI_CDC_LOW_RATE
|
||||
|
||||
//! Default configuration of communication port
|
||||
#define UDI_CDC_DEFAULT_RATE 115200
|
||||
#define UDI_CDC_DEFAULT_STOPBITS CDC_STOP_BITS_1
|
||||
#define UDI_CDC_DEFAULT_PARITY CDC_PAR_NONE
|
||||
#define UDI_CDC_DEFAULT_DATABITS 8
|
||||
|
||||
//! Enable id string of interface to add an extra USB string
|
||||
#define UDI_CDC_IAD_STRING_ID 4
|
||||
|
||||
#if HAS_MEDIA
|
||||
/**
|
||||
* USB CDC low level configuration
|
||||
* In standalone these configurations are defined by the CDC module.
|
||||
* For composite device, these configuration must be defined here
|
||||
* @{
|
||||
*/
|
||||
//! Endpoint numbers definition
|
||||
#if SAM3U
|
||||
# define UDI_CDC_COMM_EP_0 (3 | USB_EP_DIR_IN) // Notify endpoint
|
||||
# define UDI_CDC_DATA_EP_IN_0 (6 | USB_EP_DIR_IN) // TX
|
||||
# define UDI_CDC_DATA_EP_OUT_0 (5 | USB_EP_DIR_OUT)// RX
|
||||
#else
|
||||
# define UDI_CDC_COMM_EP_0 (3 | USB_EP_DIR_IN) // Notify endpoint
|
||||
# define UDI_CDC_DATA_EP_IN_0 (4 | USB_EP_DIR_IN) // TX
|
||||
# define UDI_CDC_DATA_EP_OUT_0 (5 | USB_EP_DIR_OUT)// RX
|
||||
#endif
|
||||
|
||||
//! Interface numbers
|
||||
#define UDI_CDC_COMM_IFACE_NUMBER_0 0
|
||||
#define UDI_CDC_DATA_IFACE_NUMBER_0 1
|
||||
|
||||
//@}
|
||||
//@}
|
||||
|
||||
/**
|
||||
* Configuration of MSC interface
|
||||
* @{
|
||||
*/
|
||||
//! Vendor name and Product version of MSC interface
|
||||
#define UDI_MSC_GLOBAL_VENDOR_ID \
|
||||
'M', 'A', 'R', 'L', 'I', 'N', '3', 'D'
|
||||
#define UDI_MSC_GLOBAL_PRODUCT_VERSION \
|
||||
'1', '.', '0', '0'
|
||||
|
||||
//! Interface callback definition
|
||||
#define UDI_MSC_ENABLE_EXT() usb_task_msc_enable()
|
||||
#define UDI_MSC_DISABLE_EXT() usb_task_msc_disable()
|
||||
|
||||
//! Enable id string of interface to add an extra USB string
|
||||
#define UDI_MSC_STRING_ID 5
|
||||
|
||||
/**
|
||||
* USB MSC low level configuration
|
||||
* In standalone these configurations are defined by the MSC module.
|
||||
* For composite device, these configuration must be defined here
|
||||
* @{
|
||||
*/
|
||||
//! Endpoint numbers definition
|
||||
#define UDI_MSC_EP_IN (1 | USB_EP_DIR_IN)
|
||||
#define UDI_MSC_EP_OUT (2 | USB_EP_DIR_OUT)
|
||||
|
||||
//! Interface number
|
||||
#define UDI_MSC_IFACE_NUMBER 2
|
||||
//@}
|
||||
//@}
|
||||
|
||||
//@}
|
||||
|
||||
/**
|
||||
* Description of Composite Device
|
||||
* @{
|
||||
*/
|
||||
//! USB Interfaces descriptor structure
|
||||
#define UDI_COMPOSITE_DESC_T \
|
||||
usb_iad_desc_t udi_cdc_iad; \
|
||||
udi_cdc_comm_desc_t udi_cdc_comm; \
|
||||
udi_cdc_data_desc_t udi_cdc_data; \
|
||||
udi_msc_desc_t udi_msc
|
||||
|
||||
//! USB Interfaces descriptor value for Full Speed
|
||||
#define UDI_COMPOSITE_DESC_FS \
|
||||
.udi_cdc_iad = UDI_CDC_IAD_DESC_0, \
|
||||
.udi_cdc_comm = UDI_CDC_COMM_DESC_0, \
|
||||
.udi_cdc_data = UDI_CDC_DATA_DESC_0_FS, \
|
||||
.udi_msc = UDI_MSC_DESC_FS
|
||||
|
||||
//! USB Interfaces descriptor value for High Speed
|
||||
#define UDI_COMPOSITE_DESC_HS \
|
||||
.udi_cdc_iad = UDI_CDC_IAD_DESC_0, \
|
||||
.udi_cdc_comm = UDI_CDC_COMM_DESC_0, \
|
||||
.udi_cdc_data = UDI_CDC_DATA_DESC_0_HS, \
|
||||
.udi_msc = UDI_MSC_DESC_HS
|
||||
|
||||
//! USB Interface APIs
|
||||
#define UDI_COMPOSITE_API \
|
||||
&udi_api_cdc_comm, \
|
||||
&udi_api_cdc_data, \
|
||||
&udi_api_msc
|
||||
//@}
|
||||
|
||||
/**
|
||||
* USB Device Driver Configuration
|
||||
* @{
|
||||
*/
|
||||
//@}
|
||||
|
||||
//! The includes of classes and other headers must be done at the end of this file to avoid compile error
|
||||
#include "udi_cdc.h"
|
||||
#include "udi_msc.h"
|
||||
#else
|
||||
#include "udi_cdc_conf.h"
|
||||
#endif
|
||||
|
||||
#include "usb_task.h"
|
||||
|
||||
#endif // _CONF_USB_H_
|
|
@ -0,0 +1,619 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* \file
|
||||
*
|
||||
* \brief Abstraction layer for memory interfaces.
|
||||
*
|
||||
* This module contains the interfaces:
|
||||
* - MEM <-> USB;
|
||||
* - MEM <-> RAM;
|
||||
* - MEM <-> MEM.
|
||||
*
|
||||
* This module may be configured and expanded to support the following features:
|
||||
* - write-protected globals;
|
||||
* - password-protected data;
|
||||
* - specific features;
|
||||
* - etc.
|
||||
*
|
||||
* Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Support and FAQ: visit <a href="https://www.atmel.com/design-support/">Atmel Support</a>
|
||||
*/
|
||||
|
||||
#ifdef ARDUINO_ARCH_SAM
|
||||
|
||||
//_____ I N C L U D E S ____________________________________________________
|
||||
|
||||
#include "compiler.h"
|
||||
#include "preprocessor.h"
|
||||
#ifdef FREERTOS_USED
|
||||
#include "FreeRTOS.h"
|
||||
#include "semphr.h"
|
||||
#endif
|
||||
#include "ctrl_access.h"
|
||||
|
||||
//_____ D E F I N I T I O N S ______________________________________________
|
||||
|
||||
#ifdef FREERTOS_USED
|
||||
|
||||
/*! \name LUN Access Protection Macros
|
||||
*/
|
||||
//! @{
|
||||
|
||||
/*! \brief Locks accesses to LUNs.
|
||||
*
|
||||
* \return \c true if the access was successfully locked, else \c false.
|
||||
*/
|
||||
#define Ctrl_access_lock() ctrl_access_lock()
|
||||
|
||||
/*! \brief Unlocks accesses to LUNs.
|
||||
*/
|
||||
#define Ctrl_access_unlock() xSemaphoreGive(ctrl_access_semphr)
|
||||
|
||||
//! @}
|
||||
|
||||
//! Handle to the semaphore protecting accesses to LUNs.
|
||||
static xSemaphoreHandle ctrl_access_semphr = NULL;
|
||||
|
||||
#else
|
||||
|
||||
/*! \name LUN Access Protection Macros
|
||||
*/
|
||||
//! @{
|
||||
|
||||
/*! \brief Locks accesses to LUNs.
|
||||
*
|
||||
* \return \c true if the access was successfully locked, else \c false.
|
||||
*/
|
||||
#define Ctrl_access_lock() true
|
||||
|
||||
/*! \brief Unlocks accesses to LUNs.
|
||||
*/
|
||||
#define Ctrl_access_unlock()
|
||||
|
||||
//! @}
|
||||
|
||||
#endif // FREERTOS_USED
|
||||
|
||||
#if MAX_LUN
|
||||
|
||||
/*! \brief Initializes an entry of the LUN descriptor table.
|
||||
*
|
||||
* \param lun Logical Unit Number.
|
||||
*
|
||||
* \return LUN descriptor table entry initializer.
|
||||
*/
|
||||
#if ACCESS_USB == true && ACCESS_MEM_TO_RAM == true
|
||||
#define Lun_desc_entry(lun) \
|
||||
{\
|
||||
TPASTE3(Lun_, lun, _test_unit_ready),\
|
||||
TPASTE3(Lun_, lun, _read_capacity),\
|
||||
TPASTE3(Lun_, lun, _unload),\
|
||||
TPASTE3(Lun_, lun, _wr_protect),\
|
||||
TPASTE3(Lun_, lun, _removal),\
|
||||
TPASTE3(Lun_, lun, _usb_read_10),\
|
||||
TPASTE3(Lun_, lun, _usb_write_10),\
|
||||
TPASTE3(Lun_, lun, _mem_2_ram),\
|
||||
TPASTE3(Lun_, lun, _ram_2_mem),\
|
||||
TPASTE3(LUN_, lun, _NAME)\
|
||||
}
|
||||
#elif ACCESS_USB == true
|
||||
#define Lun_desc_entry(lun) \
|
||||
{\
|
||||
TPASTE3(Lun_, lun, _test_unit_ready),\
|
||||
TPASTE3(Lun_, lun, _read_capacity),\
|
||||
TPASTE3(Lun_, lun, _unload),\
|
||||
TPASTE3(Lun_, lun, _wr_protect),\
|
||||
TPASTE3(Lun_, lun, _removal),\
|
||||
TPASTE3(Lun_, lun, _usb_read_10),\
|
||||
TPASTE3(Lun_, lun, _usb_write_10),\
|
||||
TPASTE3(LUN_, lun, _NAME)\
|
||||
}
|
||||
#elif ACCESS_MEM_TO_RAM == true
|
||||
#define Lun_desc_entry(lun) \
|
||||
{\
|
||||
TPASTE3(Lun_, lun, _test_unit_ready),\
|
||||
TPASTE3(Lun_, lun, _read_capacity),\
|
||||
TPASTE3(Lun_, lun, _unload),\
|
||||
TPASTE3(Lun_, lun, _wr_protect),\
|
||||
TPASTE3(Lun_, lun, _removal),\
|
||||
TPASTE3(Lun_, lun, _mem_2_ram),\
|
||||
TPASTE3(Lun_, lun, _ram_2_mem),\
|
||||
TPASTE3(LUN_, lun, _NAME)\
|
||||
}
|
||||
#else
|
||||
#define Lun_desc_entry(lun) \
|
||||
{\
|
||||
TPASTE3(Lun_, lun, _test_unit_ready),\
|
||||
TPASTE3(Lun_, lun, _read_capacity),\
|
||||
TPASTE3(Lun_, lun, _unload),\
|
||||
TPASTE3(Lun_, lun, _wr_protect),\
|
||||
TPASTE3(Lun_, lun, _removal),\
|
||||
TPASTE3(LUN_, lun, _NAME)\
|
||||
}
|
||||
#endif
|
||||
|
||||
//! LUN descriptor table.
|
||||
static const struct
|
||||
{
|
||||
Ctrl_status (*test_unit_ready)(void);
|
||||
Ctrl_status (*read_capacity)(U32 *);
|
||||
bool (*unload)(bool);
|
||||
bool (*wr_protect)(void);
|
||||
bool (*removal)(void);
|
||||
#if ACCESS_USB == true
|
||||
Ctrl_status (*usb_read_10)(U32, U16);
|
||||
Ctrl_status (*usb_write_10)(U32, U16);
|
||||
#endif
|
||||
#if ACCESS_MEM_TO_RAM == true
|
||||
Ctrl_status (*mem_2_ram)(U32, void *);
|
||||
Ctrl_status (*ram_2_mem)(U32, const void *);
|
||||
#endif
|
||||
const char *name;
|
||||
} lun_desc[MAX_LUN] =
|
||||
{
|
||||
#if LUN_0 == ENABLE
|
||||
# ifndef Lun_0_unload
|
||||
# define Lun_0_unload NULL
|
||||
# endif
|
||||
Lun_desc_entry(0),
|
||||
#endif
|
||||
#if LUN_1 == ENABLE
|
||||
# ifndef Lun_1_unload
|
||||
# define Lun_1_unload NULL
|
||||
# endif
|
||||
Lun_desc_entry(1),
|
||||
#endif
|
||||
#if LUN_2 == ENABLE
|
||||
# ifndef Lun_2_unload
|
||||
# define Lun_2_unload NULL
|
||||
# endif
|
||||
Lun_desc_entry(2),
|
||||
#endif
|
||||
#if LUN_3 == ENABLE
|
||||
# ifndef Lun_3_unload
|
||||
# define Lun_3_unload NULL
|
||||
# endif
|
||||
Lun_desc_entry(3),
|
||||
#endif
|
||||
#if LUN_4 == ENABLE
|
||||
# ifndef Lun_4_unload
|
||||
# define Lun_4_unload NULL
|
||||
# endif
|
||||
Lun_desc_entry(4),
|
||||
#endif
|
||||
#if LUN_5 == ENABLE
|
||||
# ifndef Lun_5_unload
|
||||
# define Lun_5_unload NULL
|
||||
# endif
|
||||
Lun_desc_entry(5),
|
||||
#endif
|
||||
#if LUN_6 == ENABLE
|
||||
# ifndef Lun_6_unload
|
||||
# define Lun_6_unload NULL
|
||||
# endif
|
||||
Lun_desc_entry(6),
|
||||
#endif
|
||||
#if LUN_7 == ENABLE
|
||||
# ifndef Lun_7_unload
|
||||
# define Lun_7_unload NULL
|
||||
# endif
|
||||
Lun_desc_entry(7)
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#if GLOBAL_WR_PROTECT == true
|
||||
bool g_wr_protect;
|
||||
#endif
|
||||
|
||||
/*! \name Control Interface
|
||||
*/
|
||||
//! @{
|
||||
|
||||
#ifdef FREERTOS_USED
|
||||
|
||||
bool ctrl_access_init(void)
|
||||
{
|
||||
// If the handle to the protecting semaphore is not valid,
|
||||
if (!ctrl_access_semphr)
|
||||
{
|
||||
// try to create the semaphore.
|
||||
vSemaphoreCreateBinary(ctrl_access_semphr);
|
||||
|
||||
// If the semaphore could not be created, there is no backup solution.
|
||||
if (!ctrl_access_semphr) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*! \brief Locks accesses to LUNs.
|
||||
*
|
||||
* \return \c true if the access was successfully locked, else \c false.
|
||||
*/
|
||||
static bool ctrl_access_lock(void)
|
||||
{
|
||||
// If the semaphore could not be created, there is no backup solution.
|
||||
if (!ctrl_access_semphr) return false;
|
||||
|
||||
// Wait for the semaphore.
|
||||
while (!xSemaphoreTake(ctrl_access_semphr, portMAX_DELAY));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // FREERTOS_USED
|
||||
|
||||
U8 get_nb_lun(void)
|
||||
{
|
||||
#if MEM_USB == ENABLE
|
||||
# ifndef Lun_usb_get_lun
|
||||
# define Lun_usb_get_lun() host_get_lun()
|
||||
# endif
|
||||
U8 nb_lun;
|
||||
|
||||
if (!Ctrl_access_lock()) return MAX_LUN;
|
||||
|
||||
nb_lun = MAX_LUN + Lun_usb_get_lun();
|
||||
|
||||
Ctrl_access_unlock();
|
||||
|
||||
return nb_lun;
|
||||
#else
|
||||
return MAX_LUN;
|
||||
#endif
|
||||
}
|
||||
|
||||
U8 get_cur_lun(void)
|
||||
{
|
||||
return LUN_ID_0;
|
||||
}
|
||||
|
||||
Ctrl_status mem_test_unit_ready(U8 lun)
|
||||
{
|
||||
Ctrl_status status;
|
||||
|
||||
if (!Ctrl_access_lock()) return CTRL_FAIL;
|
||||
|
||||
status =
|
||||
#if MAX_LUN
|
||||
(lun < MAX_LUN) ? lun_desc[lun].test_unit_ready() :
|
||||
#endif
|
||||
#if LUN_USB == ENABLE
|
||||
Lun_usb_test_unit_ready(lun - LUN_ID_USB);
|
||||
#else
|
||||
CTRL_FAIL;
|
||||
#endif
|
||||
|
||||
Ctrl_access_unlock();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
Ctrl_status mem_read_capacity(U8 lun, U32 *u32_nb_sector)
|
||||
{
|
||||
Ctrl_status status;
|
||||
|
||||
if (!Ctrl_access_lock()) return CTRL_FAIL;
|
||||
|
||||
status =
|
||||
#if MAX_LUN
|
||||
(lun < MAX_LUN) ? lun_desc[lun].read_capacity(u32_nb_sector) :
|
||||
#endif
|
||||
#if LUN_USB == ENABLE
|
||||
Lun_usb_read_capacity(lun - LUN_ID_USB, u32_nb_sector);
|
||||
#else
|
||||
CTRL_FAIL;
|
||||
#endif
|
||||
|
||||
Ctrl_access_unlock();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
U8 mem_sector_size(U8 lun)
|
||||
{
|
||||
U8 sector_size;
|
||||
|
||||
if (!Ctrl_access_lock()) return 0;
|
||||
|
||||
sector_size =
|
||||
#if MAX_LUN
|
||||
(lun < MAX_LUN) ? 1 :
|
||||
#endif
|
||||
#if LUN_USB == ENABLE
|
||||
Lun_usb_read_sector_size(lun - LUN_ID_USB);
|
||||
#else
|
||||
0;
|
||||
#endif
|
||||
|
||||
Ctrl_access_unlock();
|
||||
|
||||
return sector_size;
|
||||
}
|
||||
|
||||
bool mem_unload(U8 lun, bool unload)
|
||||
{
|
||||
bool unloaded;
|
||||
#if !MAX_LUN || !defined(Lun_usb_unload)
|
||||
UNUSED(lun);
|
||||
#endif
|
||||
|
||||
if (!Ctrl_access_lock()) return false;
|
||||
|
||||
unloaded =
|
||||
#if MAX_LUN
|
||||
(lun < MAX_LUN) ?
|
||||
(lun_desc[lun].unload ?
|
||||
lun_desc[lun].unload(unload) : !unload) :
|
||||
#endif
|
||||
#if LUN_USB == ENABLE
|
||||
# if defined(Lun_usb_unload)
|
||||
Lun_usb_unload(lun - LUN_ID_USB, unload);
|
||||
# else
|
||||
!unload; /* Can not unload: load success, unload fail */
|
||||
# endif
|
||||
#else
|
||||
false; /* No mem, unload/load fail */
|
||||
#endif
|
||||
|
||||
Ctrl_access_unlock();
|
||||
|
||||
return unloaded;
|
||||
}
|
||||
|
||||
bool mem_wr_protect(U8 lun)
|
||||
{
|
||||
bool wr_protect;
|
||||
|
||||
if (!Ctrl_access_lock()) return true;
|
||||
|
||||
wr_protect =
|
||||
#if MAX_LUN
|
||||
(lun < MAX_LUN) ? lun_desc[lun].wr_protect() :
|
||||
#endif
|
||||
#if LUN_USB == ENABLE
|
||||
Lun_usb_wr_protect(lun - LUN_ID_USB);
|
||||
#else
|
||||
true;
|
||||
#endif
|
||||
|
||||
Ctrl_access_unlock();
|
||||
|
||||
return wr_protect;
|
||||
}
|
||||
|
||||
bool mem_removal(U8 lun)
|
||||
{
|
||||
bool removal;
|
||||
#if MAX_LUN==0
|
||||
UNUSED(lun);
|
||||
#endif
|
||||
|
||||
if (!Ctrl_access_lock()) return true;
|
||||
|
||||
removal =
|
||||
#if MAX_LUN
|
||||
(lun < MAX_LUN) ? lun_desc[lun].removal() :
|
||||
#endif
|
||||
#if LUN_USB == ENABLE
|
||||
Lun_usb_removal();
|
||||
#else
|
||||
true;
|
||||
#endif
|
||||
|
||||
Ctrl_access_unlock();
|
||||
|
||||
return removal;
|
||||
}
|
||||
|
||||
const char *mem_name(U8 lun)
|
||||
{
|
||||
#if MAX_LUN==0
|
||||
UNUSED(lun);
|
||||
#endif
|
||||
return
|
||||
#if MAX_LUN
|
||||
(lun < MAX_LUN) ? lun_desc[lun].name :
|
||||
#endif
|
||||
#if LUN_USB == ENABLE
|
||||
LUN_USB_NAME;
|
||||
#else
|
||||
NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
//! @}
|
||||
|
||||
#if ACCESS_USB == true
|
||||
|
||||
/*! \name MEM <-> USB Interface
|
||||
*/
|
||||
//! @{
|
||||
|
||||
Ctrl_status memory_2_usb(U8 lun, U32 addr, U16 nb_sector)
|
||||
{
|
||||
Ctrl_status status;
|
||||
|
||||
if (!Ctrl_access_lock()) return CTRL_FAIL;
|
||||
|
||||
memory_start_read_action(nb_sector);
|
||||
status =
|
||||
#if MAX_LUN
|
||||
(lun < MAX_LUN) ? lun_desc[lun].usb_read_10(addr, nb_sector) :
|
||||
#endif
|
||||
CTRL_FAIL;
|
||||
memory_stop_read_action();
|
||||
|
||||
Ctrl_access_unlock();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
Ctrl_status usb_2_memory(U8 lun, U32 addr, U16 nb_sector)
|
||||
{
|
||||
Ctrl_status status;
|
||||
|
||||
if (!Ctrl_access_lock()) return CTRL_FAIL;
|
||||
|
||||
memory_start_write_action(nb_sector);
|
||||
status =
|
||||
#if MAX_LUN
|
||||
(lun < MAX_LUN) ? lun_desc[lun].usb_write_10(addr, nb_sector) :
|
||||
#endif
|
||||
CTRL_FAIL;
|
||||
memory_stop_write_action();
|
||||
|
||||
Ctrl_access_unlock();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
//! @}
|
||||
|
||||
#endif // ACCESS_USB == true
|
||||
|
||||
#if ACCESS_MEM_TO_RAM == true
|
||||
|
||||
/*! \name MEM <-> RAM Interface
|
||||
*/
|
||||
//! @{
|
||||
|
||||
Ctrl_status memory_2_ram(U8 lun, U32 addr, void *ram)
|
||||
{
|
||||
Ctrl_status status;
|
||||
#if MAX_LUN==0
|
||||
UNUSED(lun);
|
||||
#endif
|
||||
|
||||
if (!Ctrl_access_lock()) return CTRL_FAIL;
|
||||
|
||||
memory_start_read_action(1);
|
||||
status =
|
||||
#if MAX_LUN
|
||||
(lun < MAX_LUN) ? lun_desc[lun].mem_2_ram(addr, ram) :
|
||||
#endif
|
||||
#if LUN_USB == ENABLE
|
||||
Lun_usb_mem_2_ram(addr, ram);
|
||||
#else
|
||||
CTRL_FAIL;
|
||||
#endif
|
||||
memory_stop_read_action();
|
||||
|
||||
Ctrl_access_unlock();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
Ctrl_status ram_2_memory(U8 lun, U32 addr, const void *ram)
|
||||
{
|
||||
Ctrl_status status;
|
||||
#if MAX_LUN==0
|
||||
UNUSED(lun);
|
||||
#endif
|
||||
|
||||
if (!Ctrl_access_lock()) return CTRL_FAIL;
|
||||
|
||||
memory_start_write_action(1);
|
||||
status =
|
||||
#if MAX_LUN
|
||||
(lun < MAX_LUN) ? lun_desc[lun].ram_2_mem(addr, ram) :
|
||||
#endif
|
||||
#if LUN_USB == ENABLE
|
||||
Lun_usb_ram_2_mem(addr, ram);
|
||||
#else
|
||||
CTRL_FAIL;
|
||||
#endif
|
||||
memory_stop_write_action();
|
||||
|
||||
Ctrl_access_unlock();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
//! @}
|
||||
|
||||
#endif // ACCESS_MEM_TO_RAM == true
|
||||
|
||||
#if ACCESS_STREAM == true
|
||||
|
||||
/*! \name Streaming MEM <-> MEM Interface
|
||||
*/
|
||||
//! @{
|
||||
|
||||
#if ACCESS_MEM_TO_MEM == true
|
||||
|
||||
#include "fat.h"
|
||||
|
||||
Ctrl_status stream_mem_to_mem(U8 src_lun, U32 src_addr, U8 dest_lun, U32 dest_addr, U16 nb_sector)
|
||||
{
|
||||
COMPILER_ALIGNED(4)
|
||||
static U8 sector_buf[FS_512B];
|
||||
Ctrl_status status = CTRL_GOOD;
|
||||
|
||||
while (nb_sector--)
|
||||
{
|
||||
if ((status = memory_2_ram(src_lun, src_addr++, sector_buf)) != CTRL_GOOD) break;
|
||||
if ((status = ram_2_memory(dest_lun, dest_addr++, sector_buf)) != CTRL_GOOD) break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#endif // ACCESS_MEM_TO_MEM == true
|
||||
|
||||
Ctrl_status stream_state(U8 id)
|
||||
{
|
||||
UNUSED(id);
|
||||
return CTRL_GOOD;
|
||||
}
|
||||
|
||||
U16 stream_stop(U8 id)
|
||||
{
|
||||
UNUSED(id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! @}
|
||||
|
||||
#endif // ACCESS_STREAM
|
||||
|
||||
#endif // ARDUINO_ARCH_SAM
|
|
@ -0,0 +1,393 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* \file
|
||||
*
|
||||
* \brief Abstraction layer for memory interfaces.
|
||||
*
|
||||
* This module contains the interfaces:
|
||||
* - MEM <-> USB;
|
||||
* - MEM <-> RAM;
|
||||
* - MEM <-> MEM.
|
||||
*
|
||||
* This module may be configured and expanded to support the following features:
|
||||
* - write-protected globals;
|
||||
* - password-protected data;
|
||||
* - specific features;
|
||||
* - etc.
|
||||
*
|
||||
* Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Support and FAQ: visit <a href="https://www.atmel.com/design-support/">Atmel Support</a>
|
||||
*/
|
||||
|
||||
#ifndef _CTRL_ACCESS_H_
|
||||
#define _CTRL_ACCESS_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \defgroup group_common_services_storage_ctrl_access Memory Control Access
|
||||
*
|
||||
* Common abstraction layer for memory interfaces. It provides interfaces between:
|
||||
* Memory and USB, Memory and RAM, Memory and Memory. Common API for XMEGA and UC3.
|
||||
*
|
||||
* \{
|
||||
*/
|
||||
|
||||
#include "compiler.h"
|
||||
#include "conf_access.h"
|
||||
|
||||
#ifndef SECTOR_SIZE
|
||||
#define SECTOR_SIZE 512
|
||||
#endif
|
||||
|
||||
//! Status returned by CTRL_ACCESS interfaces.
|
||||
typedef enum
|
||||
{
|
||||
CTRL_GOOD = PASS, //!< Success, memory ready.
|
||||
CTRL_FAIL = FAIL, //!< An error occurred.
|
||||
CTRL_NO_PRESENT = FAIL + 1, //!< Memory unplugged.
|
||||
CTRL_BUSY = FAIL + 2 //!< Memory not initialized or changed.
|
||||
} Ctrl_status;
|
||||
|
||||
// FYI: Each Logical Unit Number (LUN) corresponds to a memory.
|
||||
|
||||
// Check LUN defines.
|
||||
#ifndef LUN_0
|
||||
#error LUN_0 must be defined as ENABLE or DISABLE in conf_access.h
|
||||
#endif
|
||||
#ifndef LUN_1
|
||||
#error LUN_1 must be defined as ENABLE or DISABLE in conf_access.h
|
||||
#endif
|
||||
#ifndef LUN_2
|
||||
#error LUN_2 must be defined as ENABLE or DISABLE in conf_access.h
|
||||
#endif
|
||||
#ifndef LUN_3
|
||||
#error LUN_3 must be defined as ENABLE or DISABLE in conf_access.h
|
||||
#endif
|
||||
#ifndef LUN_4
|
||||
#error LUN_4 must be defined as ENABLE or DISABLE in conf_access.h
|
||||
#endif
|
||||
#ifndef LUN_5
|
||||
#error LUN_5 must be defined as ENABLE or DISABLE in conf_access.h
|
||||
#endif
|
||||
#ifndef LUN_6
|
||||
#error LUN_6 must be defined as ENABLE or DISABLE in conf_access.h
|
||||
#endif
|
||||
#ifndef LUN_7
|
||||
#error LUN_7 must be defined as ENABLE or DISABLE in conf_access.h
|
||||
#endif
|
||||
#ifndef LUN_USB
|
||||
#error LUN_USB must be defined as ENABLE or DISABLE in conf_access.h
|
||||
#endif
|
||||
|
||||
/*! \name LUN IDs
|
||||
*/
|
||||
//! @{
|
||||
#define LUN_ID_0 (0) //!< First static LUN.
|
||||
#define LUN_ID_1 (LUN_ID_0 + LUN_0)
|
||||
#define LUN_ID_2 (LUN_ID_1 + LUN_1)
|
||||
#define LUN_ID_3 (LUN_ID_2 + LUN_2)
|
||||
#define LUN_ID_4 (LUN_ID_3 + LUN_3)
|
||||
#define LUN_ID_5 (LUN_ID_4 + LUN_4)
|
||||
#define LUN_ID_6 (LUN_ID_5 + LUN_5)
|
||||
#define LUN_ID_7 (LUN_ID_6 + LUN_6)
|
||||
#define MAX_LUN (LUN_ID_7 + LUN_7) //!< Number of static LUNs.
|
||||
#define LUN_ID_USB (MAX_LUN) //!< First dynamic LUN (USB host mass storage).
|
||||
//! @}
|
||||
|
||||
// Include LUN header files.
|
||||
#if LUN_0 == ENABLE
|
||||
#include LUN_0_INCLUDE
|
||||
#endif
|
||||
#if LUN_1 == ENABLE
|
||||
#include LUN_1_INCLUDE
|
||||
#endif
|
||||
#if LUN_2 == ENABLE
|
||||
#include LUN_2_INCLUDE
|
||||
#endif
|
||||
#if LUN_3 == ENABLE
|
||||
#include LUN_3_INCLUDE
|
||||
#endif
|
||||
#if LUN_4 == ENABLE
|
||||
#include LUN_4_INCLUDE
|
||||
#endif
|
||||
#if LUN_5 == ENABLE
|
||||
#include LUN_5_INCLUDE
|
||||
#endif
|
||||
#if LUN_6 == ENABLE
|
||||
#include LUN_6_INCLUDE
|
||||
#endif
|
||||
#if LUN_7 == ENABLE
|
||||
#include LUN_7_INCLUDE
|
||||
#endif
|
||||
#if LUN_USB == ENABLE
|
||||
#include LUN_USB_INCLUDE
|
||||
#endif
|
||||
|
||||
// Check the configuration of write protection in conf_access.h.
|
||||
#ifndef GLOBAL_WR_PROTECT
|
||||
#error GLOBAL_WR_PROTECT must be defined as true or false in conf_access.h
|
||||
#endif
|
||||
|
||||
#if GLOBAL_WR_PROTECT == true
|
||||
|
||||
//! Write protect.
|
||||
extern bool g_wr_protect;
|
||||
|
||||
#endif
|
||||
|
||||
/*! \name Control Interface
|
||||
*/
|
||||
//! @{
|
||||
|
||||
#ifdef FREERTOS_USED
|
||||
|
||||
/*! \brief Initializes the LUN access locker.
|
||||
*
|
||||
* \return \c true if the locker was successfully initialized, else \c false.
|
||||
*/
|
||||
extern bool ctrl_access_init(void);
|
||||
|
||||
#endif // FREERTOS_USED
|
||||
|
||||
/*! \brief Returns the number of LUNs.
|
||||
*
|
||||
* \return Number of LUNs in the system.
|
||||
*/
|
||||
extern U8 get_nb_lun(void);
|
||||
|
||||
/*! \brief Returns the current LUN.
|
||||
*
|
||||
* \return Current LUN.
|
||||
*
|
||||
* \todo Implement.
|
||||
*/
|
||||
extern U8 get_cur_lun(void);
|
||||
|
||||
/*! \brief Tests the memory state and initializes the memory if required.
|
||||
*
|
||||
* The TEST UNIT READY SCSI primary command allows an application client to poll
|
||||
* a LUN until it is ready without having to allocate memory for returned data.
|
||||
*
|
||||
* This command may be used to check the media status of LUNs with removable
|
||||
* media.
|
||||
*
|
||||
* \param lun Logical Unit Number.
|
||||
*
|
||||
* \return Status.
|
||||
*/
|
||||
extern Ctrl_status mem_test_unit_ready(U8 lun);
|
||||
|
||||
/*! \brief Returns the address of the last valid sector (512 bytes) in the
|
||||
* memory.
|
||||
*
|
||||
* \param lun Logical Unit Number.
|
||||
* \param u32_nb_sector Pointer to the address of the last valid sector.
|
||||
*
|
||||
* \return Status.
|
||||
*/
|
||||
extern Ctrl_status mem_read_capacity(U8 lun, U32 *u32_nb_sector);
|
||||
|
||||
/*! \brief Returns the size of the physical sector.
|
||||
*
|
||||
* \param lun Logical Unit Number.
|
||||
*
|
||||
* \return Sector size (unit: 512 bytes).
|
||||
*/
|
||||
extern U8 mem_sector_size(U8 lun);
|
||||
|
||||
/*! \brief Unload/load the medium.
|
||||
*
|
||||
* \param lun Logical Unit Number.
|
||||
* \param unload \c true to unload the medium, \c false to load the medium.
|
||||
*
|
||||
* \return \c true if unload/load success, else \c false.
|
||||
*/
|
||||
extern bool mem_unload(U8 lun, bool unload);
|
||||
|
||||
/*! \brief Returns the write-protection state of the memory.
|
||||
*
|
||||
* \param lun Logical Unit Number.
|
||||
*
|
||||
* \return \c true if the memory is write-protected, else \c false.
|
||||
*
|
||||
* \note Only used by removable memories with hardware-specific write
|
||||
* protection.
|
||||
*/
|
||||
extern bool mem_wr_protect(U8 lun);
|
||||
|
||||
/*! \brief Tells whether the memory is removable.
|
||||
*
|
||||
* \param lun Logical Unit Number.
|
||||
*
|
||||
* \return \c true if the memory is removable, else \c false.
|
||||
*/
|
||||
extern bool mem_removal(U8 lun);
|
||||
|
||||
/*! \brief Returns a pointer to the LUN name.
|
||||
*
|
||||
* \param lun Logical Unit Number.
|
||||
*
|
||||
* \return Pointer to the LUN name string.
|
||||
*/
|
||||
extern const char *mem_name(U8 lun);
|
||||
|
||||
//! @}
|
||||
|
||||
#if ACCESS_USB == true
|
||||
|
||||
/*! \name MEM <-> USB Interface
|
||||
*/
|
||||
//! @{
|
||||
|
||||
/*! \brief Transfers data from the memory to USB.
|
||||
*
|
||||
* \param lun Logical Unit Number.
|
||||
* \param addr Address of first memory sector to read.
|
||||
* \param nb_sector Number of sectors to transfer.
|
||||
*
|
||||
* \return Status.
|
||||
*/
|
||||
extern Ctrl_status memory_2_usb(U8 lun, U32 addr, U16 nb_sector);
|
||||
|
||||
/*! \brief Transfers data from USB to the memory.
|
||||
*
|
||||
* \param lun Logical Unit Number.
|
||||
* \param addr Address of first memory sector to write.
|
||||
* \param nb_sector Number of sectors to transfer.
|
||||
*
|
||||
* \return Status.
|
||||
*/
|
||||
extern Ctrl_status usb_2_memory(U8 lun, U32 addr, U16 nb_sector);
|
||||
|
||||
//! @}
|
||||
|
||||
#endif // ACCESS_USB == true
|
||||
|
||||
#if ACCESS_MEM_TO_RAM == true
|
||||
|
||||
/*! \name MEM <-> RAM Interface
|
||||
*/
|
||||
//! @{
|
||||
|
||||
/*! \brief Copies 1 data sector from the memory to RAM.
|
||||
*
|
||||
* \param lun Logical Unit Number.
|
||||
* \param addr Address of first memory sector to read.
|
||||
* \param ram Pointer to RAM buffer to write.
|
||||
*
|
||||
* \return Status.
|
||||
*/
|
||||
extern Ctrl_status memory_2_ram(U8 lun, U32 addr, void *ram);
|
||||
|
||||
/*! \brief Copies 1 data sector from RAM to the memory.
|
||||
*
|
||||
* \param lun Logical Unit Number.
|
||||
* \param addr Address of first memory sector to write.
|
||||
* \param ram Pointer to RAM buffer to read.
|
||||
*
|
||||
* \return Status.
|
||||
*/
|
||||
extern Ctrl_status ram_2_memory(U8 lun, U32 addr, const void *ram);
|
||||
|
||||
//! @}
|
||||
|
||||
#endif // ACCESS_MEM_TO_RAM == true
|
||||
|
||||
#if ACCESS_STREAM == true
|
||||
|
||||
/*! \name Streaming MEM <-> MEM Interface
|
||||
*/
|
||||
//! @{
|
||||
|
||||
//! Erroneous streaming data transfer ID.
|
||||
#define ID_STREAM_ERR 0xFF
|
||||
|
||||
#if ACCESS_MEM_TO_MEM == true
|
||||
|
||||
/*! \brief Copies data from one memory to another.
|
||||
*
|
||||
* \param src_lun Source Logical Unit Number.
|
||||
* \param src_addr Source address of first memory sector to read.
|
||||
* \param dest_lun Destination Logical Unit Number.
|
||||
* \param dest_addr Destination address of first memory sector to write.
|
||||
* \param nb_sector Number of sectors to copy.
|
||||
*
|
||||
* \return Status.
|
||||
*/
|
||||
extern Ctrl_status stream_mem_to_mem(U8 src_lun, U32 src_addr, U8 dest_lun, U32 dest_addr, U16 nb_sector);
|
||||
|
||||
#endif // ACCESS_MEM_TO_MEM == true
|
||||
|
||||
/*! \brief Returns the state of a streaming data transfer.
|
||||
*
|
||||
* \param id Transfer ID.
|
||||
*
|
||||
* \return Status.
|
||||
*
|
||||
* \todo Implement.
|
||||
*/
|
||||
extern Ctrl_status stream_state(U8 id);
|
||||
|
||||
/*! \brief Stops a streaming data transfer.
|
||||
*
|
||||
* \param id Transfer ID.
|
||||
*
|
||||
* \return Number of remaining sectors.
|
||||
*
|
||||
* \todo Implement.
|
||||
*/
|
||||
extern U16 stream_stop(U8 id);
|
||||
|
||||
//! @}
|
||||
|
||||
#endif // ACCESS_STREAM == true
|
||||
|
||||
/**
|
||||
* \}
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // _CTRL_ACCESS_H_
|
|
@ -0,0 +1,264 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief Chip-specific generic clock management.
|
||||
*
|
||||
* Copyright (c) 2011-2015 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Support and FAQ: visit <a href="https://www.atmel.com/design-support/">Atmel Support</a>
|
||||
*/
|
||||
|
||||
#ifndef CHIP_GENCLK_H_INCLUDED
|
||||
#define CHIP_GENCLK_H_INCLUDED
|
||||
|
||||
#include <osc.h>
|
||||
#include <pll.h>
|
||||
|
||||
/// @cond 0
|
||||
/**INDENT-OFF**/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/**INDENT-ON**/
|
||||
/// @endcond
|
||||
|
||||
/**
|
||||
* \weakgroup genclk_group
|
||||
* @{
|
||||
*/
|
||||
|
||||
//! \name Programmable Clock Identifiers (PCK)
|
||||
//@{
|
||||
#define GENCLK_PCK_0 0 //!< PCK0 ID
|
||||
#define GENCLK_PCK_1 1 //!< PCK1 ID
|
||||
#define GENCLK_PCK_2 2 //!< PCK2 ID
|
||||
//@}
|
||||
|
||||
//! \name Programmable Clock Sources (PCK)
|
||||
//@{
|
||||
|
||||
enum genclk_source {
|
||||
GENCLK_PCK_SRC_SLCK_RC = 0, //!< Internal 32kHz RC oscillator as PCK source clock
|
||||
GENCLK_PCK_SRC_SLCK_XTAL = 1, //!< External 32kHz crystal oscillator as PCK source clock
|
||||
GENCLK_PCK_SRC_SLCK_BYPASS = 2, //!< External 32kHz bypass oscillator as PCK source clock
|
||||
GENCLK_PCK_SRC_MAINCK_4M_RC = 3, //!< Internal 4MHz RC oscillator as PCK source clock
|
||||
GENCLK_PCK_SRC_MAINCK_8M_RC = 4, //!< Internal 8MHz RC oscillator as PCK source clock
|
||||
GENCLK_PCK_SRC_MAINCK_12M_RC = 5, //!< Internal 12MHz RC oscillator as PCK source clock
|
||||
GENCLK_PCK_SRC_MAINCK_XTAL = 6, //!< External crystal oscillator as PCK source clock
|
||||
GENCLK_PCK_SRC_MAINCK_BYPASS = 7, //!< External bypass oscillator as PCK source clock
|
||||
GENCLK_PCK_SRC_PLLACK = 8, //!< Use PLLACK as PCK source clock
|
||||
GENCLK_PCK_SRC_PLLBCK = 9, //!< Use PLLBCK as PCK source clock
|
||||
GENCLK_PCK_SRC_MCK = 10, //!< Use Master Clk as PCK source clock
|
||||
};
|
||||
|
||||
//@}
|
||||
|
||||
//! \name Programmable Clock Prescalers (PCK)
|
||||
//@{
|
||||
|
||||
enum genclk_divider {
|
||||
GENCLK_PCK_PRES_1 = PMC_PCK_PRES_CLK_1, //!< Set PCK clock prescaler to 1
|
||||
GENCLK_PCK_PRES_2 = PMC_PCK_PRES_CLK_2, //!< Set PCK clock prescaler to 2
|
||||
GENCLK_PCK_PRES_4 = PMC_PCK_PRES_CLK_4, //!< Set PCK clock prescaler to 4
|
||||
GENCLK_PCK_PRES_8 = PMC_PCK_PRES_CLK_8, //!< Set PCK clock prescaler to 8
|
||||
GENCLK_PCK_PRES_16 = PMC_PCK_PRES_CLK_16, //!< Set PCK clock prescaler to 16
|
||||
GENCLK_PCK_PRES_32 = PMC_PCK_PRES_CLK_32, //!< Set PCK clock prescaler to 32
|
||||
GENCLK_PCK_PRES_64 = PMC_PCK_PRES_CLK_64, //!< Set PCK clock prescaler to 64
|
||||
};
|
||||
|
||||
//@}
|
||||
|
||||
struct genclk_config {
|
||||
uint32_t ctrl;
|
||||
};
|
||||
|
||||
static inline void genclk_config_defaults(struct genclk_config *p_cfg, uint32_t ul_id) {
|
||||
ul_id = ul_id;
|
||||
p_cfg->ctrl = 0;
|
||||
}
|
||||
|
||||
static inline void genclk_config_read(struct genclk_config *p_cfg, uint32_t ul_id) {
|
||||
p_cfg->ctrl = PMC->PMC_PCK[ul_id];
|
||||
}
|
||||
|
||||
static inline void genclk_config_write(const struct genclk_config *p_cfg, uint32_t ul_id) {
|
||||
PMC->PMC_PCK[ul_id] = p_cfg->ctrl;
|
||||
}
|
||||
|
||||
//! \name Programmable Clock Source and Prescaler configuration
|
||||
//@{
|
||||
|
||||
static inline void genclk_config_set_source(struct genclk_config *p_cfg, enum genclk_source e_src) {
|
||||
p_cfg->ctrl &= (~PMC_PCK_CSS_Msk);
|
||||
|
||||
switch (e_src) {
|
||||
case GENCLK_PCK_SRC_SLCK_RC:
|
||||
case GENCLK_PCK_SRC_SLCK_XTAL:
|
||||
case GENCLK_PCK_SRC_SLCK_BYPASS:
|
||||
p_cfg->ctrl |= (PMC_PCK_CSS_SLOW_CLK);
|
||||
break;
|
||||
|
||||
case GENCLK_PCK_SRC_MAINCK_4M_RC:
|
||||
case GENCLK_PCK_SRC_MAINCK_8M_RC:
|
||||
case GENCLK_PCK_SRC_MAINCK_12M_RC:
|
||||
case GENCLK_PCK_SRC_MAINCK_XTAL:
|
||||
case GENCLK_PCK_SRC_MAINCK_BYPASS:
|
||||
p_cfg->ctrl |= (PMC_PCK_CSS_MAIN_CLK);
|
||||
break;
|
||||
|
||||
case GENCLK_PCK_SRC_PLLACK:
|
||||
p_cfg->ctrl |= (PMC_PCK_CSS_PLLA_CLK);
|
||||
break;
|
||||
|
||||
case GENCLK_PCK_SRC_PLLBCK:
|
||||
p_cfg->ctrl |= (PMC_PCK_CSS_UPLL_CLK);
|
||||
break;
|
||||
|
||||
case GENCLK_PCK_SRC_MCK:
|
||||
p_cfg->ctrl |= (PMC_PCK_CSS_MCK);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void genclk_config_set_divider(struct genclk_config *p_cfg, uint32_t e_divider) {
|
||||
p_cfg->ctrl &= ~PMC_PCK_PRES_Msk;
|
||||
p_cfg->ctrl |= e_divider;
|
||||
}
|
||||
|
||||
//@}
|
||||
|
||||
static inline void genclk_enable(const struct genclk_config *p_cfg, uint32_t ul_id) {
|
||||
PMC->PMC_PCK[ul_id] = p_cfg->ctrl;
|
||||
pmc_enable_pck(ul_id);
|
||||
}
|
||||
|
||||
static inline void genclk_disable(uint32_t ul_id) {
|
||||
pmc_disable_pck(ul_id);
|
||||
}
|
||||
|
||||
static inline void genclk_enable_source(enum genclk_source e_src) {
|
||||
switch (e_src) {
|
||||
case GENCLK_PCK_SRC_SLCK_RC:
|
||||
if (!osc_is_ready(OSC_SLCK_32K_RC)) {
|
||||
osc_enable(OSC_SLCK_32K_RC);
|
||||
osc_wait_ready(OSC_SLCK_32K_RC);
|
||||
}
|
||||
break;
|
||||
|
||||
case GENCLK_PCK_SRC_SLCK_XTAL:
|
||||
if (!osc_is_ready(OSC_SLCK_32K_XTAL)) {
|
||||
osc_enable(OSC_SLCK_32K_XTAL);
|
||||
osc_wait_ready(OSC_SLCK_32K_XTAL);
|
||||
}
|
||||
break;
|
||||
|
||||
case GENCLK_PCK_SRC_SLCK_BYPASS:
|
||||
if (!osc_is_ready(OSC_SLCK_32K_BYPASS)) {
|
||||
osc_enable(OSC_SLCK_32K_BYPASS);
|
||||
osc_wait_ready(OSC_SLCK_32K_BYPASS);
|
||||
}
|
||||
break;
|
||||
|
||||
case GENCLK_PCK_SRC_MAINCK_4M_RC:
|
||||
if (!osc_is_ready(OSC_MAINCK_4M_RC)) {
|
||||
osc_enable(OSC_MAINCK_4M_RC);
|
||||
osc_wait_ready(OSC_MAINCK_4M_RC);
|
||||
}
|
||||
break;
|
||||
|
||||
case GENCLK_PCK_SRC_MAINCK_8M_RC:
|
||||
if (!osc_is_ready(OSC_MAINCK_8M_RC)) {
|
||||
osc_enable(OSC_MAINCK_8M_RC);
|
||||
osc_wait_ready(OSC_MAINCK_8M_RC);
|
||||
}
|
||||
break;
|
||||
|
||||
case GENCLK_PCK_SRC_MAINCK_12M_RC:
|
||||
if (!osc_is_ready(OSC_MAINCK_12M_RC)) {
|
||||
osc_enable(OSC_MAINCK_12M_RC);
|
||||
osc_wait_ready(OSC_MAINCK_12M_RC);
|
||||
}
|
||||
break;
|
||||
|
||||
case GENCLK_PCK_SRC_MAINCK_XTAL:
|
||||
if (!osc_is_ready(OSC_MAINCK_XTAL)) {
|
||||
osc_enable(OSC_MAINCK_XTAL);
|
||||
osc_wait_ready(OSC_MAINCK_XTAL);
|
||||
}
|
||||
break;
|
||||
|
||||
case GENCLK_PCK_SRC_MAINCK_BYPASS:
|
||||
if (!osc_is_ready(OSC_MAINCK_BYPASS)) {
|
||||
osc_enable(OSC_MAINCK_BYPASS);
|
||||
osc_wait_ready(OSC_MAINCK_BYPASS);
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef CONFIG_PLL0_SOURCE
|
||||
case GENCLK_PCK_SRC_PLLACK:
|
||||
pll_enable_config_defaults(0);
|
||||
break;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PLL1_SOURCE
|
||||
case GENCLK_PCK_SRC_PLLBCK:
|
||||
pll_enable_config_defaults(1);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case GENCLK_PCK_SRC_MCK:
|
||||
break;
|
||||
|
||||
default:
|
||||
Assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//! @}
|
||||
|
||||
/// @cond 0
|
||||
/**INDENT-OFF**/
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/**INDENT-ON**/
|
||||
/// @endcond
|
||||
|
||||
#endif /* CHIP_GENCLK_H_INCLUDED */
|
|
@ -0,0 +1,338 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief Preprocessor macro repeating utils.
|
||||
*
|
||||
* Copyright (c) 2010-2015 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Support and FAQ: visit <a href="https://www.atmel.com/design-support/">Atmel Support</a>
|
||||
*/
|
||||
|
||||
#ifndef _MREPEAT_H_
|
||||
#define _MREPEAT_H_
|
||||
|
||||
/**
|
||||
* \defgroup group_sam_utils_mrepeat Preprocessor - Macro Repeat
|
||||
*
|
||||
* \ingroup group_sam_utils
|
||||
*
|
||||
* \{
|
||||
*/
|
||||
|
||||
#include "preprocessor.h"
|
||||
|
||||
//! Maximal number of repetitions supported by MREPEAT.
|
||||
#define MREPEAT_LIMIT 256
|
||||
|
||||
/*! \brief Macro repeat.
|
||||
*
|
||||
* This macro represents a horizontal repetition construct.
|
||||
*
|
||||
* \param count The number of repetitious calls to macro. Valid values range from 0 to MREPEAT_LIMIT.
|
||||
* \param macro A binary operation of the form macro(n, data). This macro is expanded by MREPEAT with
|
||||
* the current repetition number and the auxiliary data argument.
|
||||
* \param data Auxiliary data passed to macro.
|
||||
*
|
||||
* \return <tt>macro(0, data) macro(1, data) ... macro(count - 1, data)</tt>
|
||||
*/
|
||||
#define MREPEAT(count, macro, data) TPASTE2(MREPEAT, count)(macro, data)
|
||||
|
||||
#define MREPEAT0( macro, data)
|
||||
#define MREPEAT1( macro, data) MREPEAT0( macro, data) macro( 0, data)
|
||||
#define MREPEAT2( macro, data) MREPEAT1( macro, data) macro( 1, data)
|
||||
#define MREPEAT3( macro, data) MREPEAT2( macro, data) macro( 2, data)
|
||||
#define MREPEAT4( macro, data) MREPEAT3( macro, data) macro( 3, data)
|
||||
#define MREPEAT5( macro, data) MREPEAT4( macro, data) macro( 4, data)
|
||||
#define MREPEAT6( macro, data) MREPEAT5( macro, data) macro( 5, data)
|
||||
#define MREPEAT7( macro, data) MREPEAT6( macro, data) macro( 6, data)
|
||||
#define MREPEAT8( macro, data) MREPEAT7( macro, data) macro( 7, data)
|
||||
#define MREPEAT9( macro, data) MREPEAT8( macro, data) macro( 8, data)
|
||||
#define MREPEAT10( macro, data) MREPEAT9( macro, data) macro( 9, data)
|
||||
#define MREPEAT11( macro, data) MREPEAT10( macro, data) macro( 10, data)
|
||||
#define MREPEAT12( macro, data) MREPEAT11( macro, data) macro( 11, data)
|
||||
#define MREPEAT13( macro, data) MREPEAT12( macro, data) macro( 12, data)
|
||||
#define MREPEAT14( macro, data) MREPEAT13( macro, data) macro( 13, data)
|
||||
#define MREPEAT15( macro, data) MREPEAT14( macro, data) macro( 14, data)
|
||||
#define MREPEAT16( macro, data) MREPEAT15( macro, data) macro( 15, data)
|
||||
#define MREPEAT17( macro, data) MREPEAT16( macro, data) macro( 16, data)
|
||||
#define MREPEAT18( macro, data) MREPEAT17( macro, data) macro( 17, data)
|
||||
#define MREPEAT19( macro, data) MREPEAT18( macro, data) macro( 18, data)
|
||||
#define MREPEAT20( macro, data) MREPEAT19( macro, data) macro( 19, data)
|
||||
#define MREPEAT21( macro, data) MREPEAT20( macro, data) macro( 20, data)
|
||||
#define MREPEAT22( macro, data) MREPEAT21( macro, data) macro( 21, data)
|
||||
#define MREPEAT23( macro, data) MREPEAT22( macro, data) macro( 22, data)
|
||||
#define MREPEAT24( macro, data) MREPEAT23( macro, data) macro( 23, data)
|
||||
#define MREPEAT25( macro, data) MREPEAT24( macro, data) macro( 24, data)
|
||||
#define MREPEAT26( macro, data) MREPEAT25( macro, data) macro( 25, data)
|
||||
#define MREPEAT27( macro, data) MREPEAT26( macro, data) macro( 26, data)
|
||||
#define MREPEAT28( macro, data) MREPEAT27( macro, data) macro( 27, data)
|
||||
#define MREPEAT29( macro, data) MREPEAT28( macro, data) macro( 28, data)
|
||||
#define MREPEAT30( macro, data) MREPEAT29( macro, data) macro( 29, data)
|
||||
#define MREPEAT31( macro, data) MREPEAT30( macro, data) macro( 30, data)
|
||||
#define MREPEAT32( macro, data) MREPEAT31( macro, data) macro( 31, data)
|
||||
#define MREPEAT33( macro, data) MREPEAT32( macro, data) macro( 32, data)
|
||||
#define MREPEAT34( macro, data) MREPEAT33( macro, data) macro( 33, data)
|
||||
#define MREPEAT35( macro, data) MREPEAT34( macro, data) macro( 34, data)
|
||||
#define MREPEAT36( macro, data) MREPEAT35( macro, data) macro( 35, data)
|
||||
#define MREPEAT37( macro, data) MREPEAT36( macro, data) macro( 36, data)
|
||||
#define MREPEAT38( macro, data) MREPEAT37( macro, data) macro( 37, data)
|
||||
#define MREPEAT39( macro, data) MREPEAT38( macro, data) macro( 38, data)
|
||||
#define MREPEAT40( macro, data) MREPEAT39( macro, data) macro( 39, data)
|
||||
#define MREPEAT41( macro, data) MREPEAT40( macro, data) macro( 40, data)
|
||||
#define MREPEAT42( macro, data) MREPEAT41( macro, data) macro( 41, data)
|
||||
#define MREPEAT43( macro, data) MREPEAT42( macro, data) macro( 42, data)
|
||||
#define MREPEAT44( macro, data) MREPEAT43( macro, data) macro( 43, data)
|
||||
#define MREPEAT45( macro, data) MREPEAT44( macro, data) macro( 44, data)
|
||||
#define MREPEAT46( macro, data) MREPEAT45( macro, data) macro( 45, data)
|
||||
#define MREPEAT47( macro, data) MREPEAT46( macro, data) macro( 46, data)
|
||||
#define MREPEAT48( macro, data) MREPEAT47( macro, data) macro( 47, data)
|
||||
#define MREPEAT49( macro, data) MREPEAT48( macro, data) macro( 48, data)
|
||||
#define MREPEAT50( macro, data) MREPEAT49( macro, data) macro( 49, data)
|
||||
#define MREPEAT51( macro, data) MREPEAT50( macro, data) macro( 50, data)
|
||||
#define MREPEAT52( macro, data) MREPEAT51( macro, data) macro( 51, data)
|
||||
#define MREPEAT53( macro, data) MREPEAT52( macro, data) macro( 52, data)
|
||||
#define MREPEAT54( macro, data) MREPEAT53( macro, data) macro( 53, data)
|
||||
#define MREPEAT55( macro, data) MREPEAT54( macro, data) macro( 54, data)
|
||||
#define MREPEAT56( macro, data) MREPEAT55( macro, data) macro( 55, data)
|
||||
#define MREPEAT57( macro, data) MREPEAT56( macro, data) macro( 56, data)
|
||||
#define MREPEAT58( macro, data) MREPEAT57( macro, data) macro( 57, data)
|
||||
#define MREPEAT59( macro, data) MREPEAT58( macro, data) macro( 58, data)
|
||||
#define MREPEAT60( macro, data) MREPEAT59( macro, data) macro( 59, data)
|
||||
#define MREPEAT61( macro, data) MREPEAT60( macro, data) macro( 60, data)
|
||||
#define MREPEAT62( macro, data) MREPEAT61( macro, data) macro( 61, data)
|
||||
#define MREPEAT63( macro, data) MREPEAT62( macro, data) macro( 62, data)
|
||||
#define MREPEAT64( macro, data) MREPEAT63( macro, data) macro( 63, data)
|
||||
#define MREPEAT65( macro, data) MREPEAT64( macro, data) macro( 64, data)
|
||||
#define MREPEAT66( macro, data) MREPEAT65( macro, data) macro( 65, data)
|
||||
#define MREPEAT67( macro, data) MREPEAT66( macro, data) macro( 66, data)
|
||||
#define MREPEAT68( macro, data) MREPEAT67( macro, data) macro( 67, data)
|
||||
#define MREPEAT69( macro, data) MREPEAT68( macro, data) macro( 68, data)
|
||||
#define MREPEAT70( macro, data) MREPEAT69( macro, data) macro( 69, data)
|
||||
#define MREPEAT71( macro, data) MREPEAT70( macro, data) macro( 70, data)
|
||||
#define MREPEAT72( macro, data) MREPEAT71( macro, data) macro( 71, data)
|
||||
#define MREPEAT73( macro, data) MREPEAT72( macro, data) macro( 72, data)
|
||||
#define MREPEAT74( macro, data) MREPEAT73( macro, data) macro( 73, data)
|
||||
#define MREPEAT75( macro, data) MREPEAT74( macro, data) macro( 74, data)
|
||||
#define MREPEAT76( macro, data) MREPEAT75( macro, data) macro( 75, data)
|
||||
#define MREPEAT77( macro, data) MREPEAT76( macro, data) macro( 76, data)
|
||||
#define MREPEAT78( macro, data) MREPEAT77( macro, data) macro( 77, data)
|
||||
#define MREPEAT79( macro, data) MREPEAT78( macro, data) macro( 78, data)
|
||||
#define MREPEAT80( macro, data) MREPEAT79( macro, data) macro( 79, data)
|
||||
#define MREPEAT81( macro, data) MREPEAT80( macro, data) macro( 80, data)
|
||||
#define MREPEAT82( macro, data) MREPEAT81( macro, data) macro( 81, data)
|
||||
#define MREPEAT83( macro, data) MREPEAT82( macro, data) macro( 82, data)
|
||||
#define MREPEAT84( macro, data) MREPEAT83( macro, data) macro( 83, data)
|
||||
#define MREPEAT85( macro, data) MREPEAT84( macro, data) macro( 84, data)
|
||||
#define MREPEAT86( macro, data) MREPEAT85( macro, data) macro( 85, data)
|
||||
#define MREPEAT87( macro, data) MREPEAT86( macro, data) macro( 86, data)
|
||||
#define MREPEAT88( macro, data) MREPEAT87( macro, data) macro( 87, data)
|
||||
#define MREPEAT89( macro, data) MREPEAT88( macro, data) macro( 88, data)
|
||||
#define MREPEAT90( macro, data) MREPEAT89( macro, data) macro( 89, data)
|
||||
#define MREPEAT91( macro, data) MREPEAT90( macro, data) macro( 90, data)
|
||||
#define MREPEAT92( macro, data) MREPEAT91( macro, data) macro( 91, data)
|
||||
#define MREPEAT93( macro, data) MREPEAT92( macro, data) macro( 92, data)
|
||||
#define MREPEAT94( macro, data) MREPEAT93( macro, data) macro( 93, data)
|
||||
#define MREPEAT95( macro, data) MREPEAT94( macro, data) macro( 94, data)
|
||||
#define MREPEAT96( macro, data) MREPEAT95( macro, data) macro( 95, data)
|
||||
#define MREPEAT97( macro, data) MREPEAT96( macro, data) macro( 96, data)
|
||||
#define MREPEAT98( macro, data) MREPEAT97( macro, data) macro( 97, data)
|
||||
#define MREPEAT99( macro, data) MREPEAT98( macro, data) macro( 98, data)
|
||||
#define MREPEAT100(macro, data) MREPEAT99( macro, data) macro( 99, data)
|
||||
#define MREPEAT101(macro, data) MREPEAT100(macro, data) macro(100, data)
|
||||
#define MREPEAT102(macro, data) MREPEAT101(macro, data) macro(101, data)
|
||||
#define MREPEAT103(macro, data) MREPEAT102(macro, data) macro(102, data)
|
||||
#define MREPEAT104(macro, data) MREPEAT103(macro, data) macro(103, data)
|
||||
#define MREPEAT105(macro, data) MREPEAT104(macro, data) macro(104, data)
|
||||
#define MREPEAT106(macro, data) MREPEAT105(macro, data) macro(105, data)
|
||||
#define MREPEAT107(macro, data) MREPEAT106(macro, data) macro(106, data)
|
||||
#define MREPEAT108(macro, data) MREPEAT107(macro, data) macro(107, data)
|
||||
#define MREPEAT109(macro, data) MREPEAT108(macro, data) macro(108, data)
|
||||
#define MREPEAT110(macro, data) MREPEAT109(macro, data) macro(109, data)
|
||||
#define MREPEAT111(macro, data) MREPEAT110(macro, data) macro(110, data)
|
||||
#define MREPEAT112(macro, data) MREPEAT111(macro, data) macro(111, data)
|
||||
#define MREPEAT113(macro, data) MREPEAT112(macro, data) macro(112, data)
|
||||
#define MREPEAT114(macro, data) MREPEAT113(macro, data) macro(113, data)
|
||||
#define MREPEAT115(macro, data) MREPEAT114(macro, data) macro(114, data)
|
||||
#define MREPEAT116(macro, data) MREPEAT115(macro, data) macro(115, data)
|
||||
#define MREPEAT117(macro, data) MREPEAT116(macro, data) macro(116, data)
|
||||
#define MREPEAT118(macro, data) MREPEAT117(macro, data) macro(117, data)
|
||||
#define MREPEAT119(macro, data) MREPEAT118(macro, data) macro(118, data)
|
||||
#define MREPEAT120(macro, data) MREPEAT119(macro, data) macro(119, data)
|
||||
#define MREPEAT121(macro, data) MREPEAT120(macro, data) macro(120, data)
|
||||
#define MREPEAT122(macro, data) MREPEAT121(macro, data) macro(121, data)
|
||||
#define MREPEAT123(macro, data) MREPEAT122(macro, data) macro(122, data)
|
||||
#define MREPEAT124(macro, data) MREPEAT123(macro, data) macro(123, data)
|
||||
#define MREPEAT125(macro, data) MREPEAT124(macro, data) macro(124, data)
|
||||
#define MREPEAT126(macro, data) MREPEAT125(macro, data) macro(125, data)
|
||||
#define MREPEAT127(macro, data) MREPEAT126(macro, data) macro(126, data)
|
||||
#define MREPEAT128(macro, data) MREPEAT127(macro, data) macro(127, data)
|
||||
#define MREPEAT129(macro, data) MREPEAT128(macro, data) macro(128, data)
|
||||
#define MREPEAT130(macro, data) MREPEAT129(macro, data) macro(129, data)
|
||||
#define MREPEAT131(macro, data) MREPEAT130(macro, data) macro(130, data)
|
||||
#define MREPEAT132(macro, data) MREPEAT131(macro, data) macro(131, data)
|
||||
#define MREPEAT133(macro, data) MREPEAT132(macro, data) macro(132, data)
|
||||
#define MREPEAT134(macro, data) MREPEAT133(macro, data) macro(133, data)
|
||||
#define MREPEAT135(macro, data) MREPEAT134(macro, data) macro(134, data)
|
||||
#define MREPEAT136(macro, data) MREPEAT135(macro, data) macro(135, data)
|
||||
#define MREPEAT137(macro, data) MREPEAT136(macro, data) macro(136, data)
|
||||
#define MREPEAT138(macro, data) MREPEAT137(macro, data) macro(137, data)
|
||||
#define MREPEAT139(macro, data) MREPEAT138(macro, data) macro(138, data)
|
||||
#define MREPEAT140(macro, data) MREPEAT139(macro, data) macro(139, data)
|
||||
#define MREPEAT141(macro, data) MREPEAT140(macro, data) macro(140, data)
|
||||
#define MREPEAT142(macro, data) MREPEAT141(macro, data) macro(141, data)
|
||||
#define MREPEAT143(macro, data) MREPEAT142(macro, data) macro(142, data)
|
||||
#define MREPEAT144(macro, data) MREPEAT143(macro, data) macro(143, data)
|
||||
#define MREPEAT145(macro, data) MREPEAT144(macro, data) macro(144, data)
|
||||
#define MREPEAT146(macro, data) MREPEAT145(macro, data) macro(145, data)
|
||||
#define MREPEAT147(macro, data) MREPEAT146(macro, data) macro(146, data)
|
||||
#define MREPEAT148(macro, data) MREPEAT147(macro, data) macro(147, data)
|
||||
#define MREPEAT149(macro, data) MREPEAT148(macro, data) macro(148, data)
|
||||
#define MREPEAT150(macro, data) MREPEAT149(macro, data) macro(149, data)
|
||||
#define MREPEAT151(macro, data) MREPEAT150(macro, data) macro(150, data)
|
||||
#define MREPEAT152(macro, data) MREPEAT151(macro, data) macro(151, data)
|
||||
#define MREPEAT153(macro, data) MREPEAT152(macro, data) macro(152, data)
|
||||
#define MREPEAT154(macro, data) MREPEAT153(macro, data) macro(153, data)
|
||||
#define MREPEAT155(macro, data) MREPEAT154(macro, data) macro(154, data)
|
||||
#define MREPEAT156(macro, data) MREPEAT155(macro, data) macro(155, data)
|
||||
#define MREPEAT157(macro, data) MREPEAT156(macro, data) macro(156, data)
|
||||
#define MREPEAT158(macro, data) MREPEAT157(macro, data) macro(157, data)
|
||||
#define MREPEAT159(macro, data) MREPEAT158(macro, data) macro(158, data)
|
||||
#define MREPEAT160(macro, data) MREPEAT159(macro, data) macro(159, data)
|
||||
#define MREPEAT161(macro, data) MREPEAT160(macro, data) macro(160, data)
|
||||
#define MREPEAT162(macro, data) MREPEAT161(macro, data) macro(161, data)
|
||||
#define MREPEAT163(macro, data) MREPEAT162(macro, data) macro(162, data)
|
||||
#define MREPEAT164(macro, data) MREPEAT163(macro, data) macro(163, data)
|
||||
#define MREPEAT165(macro, data) MREPEAT164(macro, data) macro(164, data)
|
||||
#define MREPEAT166(macro, data) MREPEAT165(macro, data) macro(165, data)
|
||||
#define MREPEAT167(macro, data) MREPEAT166(macro, data) macro(166, data)
|
||||
#define MREPEAT168(macro, data) MREPEAT167(macro, data) macro(167, data)
|
||||
#define MREPEAT169(macro, data) MREPEAT168(macro, data) macro(168, data)
|
||||
#define MREPEAT170(macro, data) MREPEAT169(macro, data) macro(169, data)
|
||||
#define MREPEAT171(macro, data) MREPEAT170(macro, data) macro(170, data)
|
||||
#define MREPEAT172(macro, data) MREPEAT171(macro, data) macro(171, data)
|
||||
#define MREPEAT173(macro, data) MREPEAT172(macro, data) macro(172, data)
|
||||
#define MREPEAT174(macro, data) MREPEAT173(macro, data) macro(173, data)
|
||||
#define MREPEAT175(macro, data) MREPEAT174(macro, data) macro(174, data)
|
||||
#define MREPEAT176(macro, data) MREPEAT175(macro, data) macro(175, data)
|
||||
#define MREPEAT177(macro, data) MREPEAT176(macro, data) macro(176, data)
|
||||
#define MREPEAT178(macro, data) MREPEAT177(macro, data) macro(177, data)
|
||||
#define MREPEAT179(macro, data) MREPEAT178(macro, data) macro(178, data)
|
||||
#define MREPEAT180(macro, data) MREPEAT179(macro, data) macro(179, data)
|
||||
#define MREPEAT181(macro, data) MREPEAT180(macro, data) macro(180, data)
|
||||
#define MREPEAT182(macro, data) MREPEAT181(macro, data) macro(181, data)
|
||||
#define MREPEAT183(macro, data) MREPEAT182(macro, data) macro(182, data)
|
||||
#define MREPEAT184(macro, data) MREPEAT183(macro, data) macro(183, data)
|
||||
#define MREPEAT185(macro, data) MREPEAT184(macro, data) macro(184, data)
|
||||
#define MREPEAT186(macro, data) MREPEAT185(macro, data) macro(185, data)
|
||||
#define MREPEAT187(macro, data) MREPEAT186(macro, data) macro(186, data)
|
||||
#define MREPEAT188(macro, data) MREPEAT187(macro, data) macro(187, data)
|
||||
#define MREPEAT189(macro, data) MREPEAT188(macro, data) macro(188, data)
|
||||
#define MREPEAT190(macro, data) MREPEAT189(macro, data) macro(189, data)
|
||||
#define MREPEAT191(macro, data) MREPEAT190(macro, data) macro(190, data)
|
||||
#define MREPEAT192(macro, data) MREPEAT191(macro, data) macro(191, data)
|
||||
#define MREPEAT193(macro, data) MREPEAT192(macro, data) macro(192, data)
|
||||
#define MREPEAT194(macro, data) MREPEAT193(macro, data) macro(193, data)
|
||||
#define MREPEAT195(macro, data) MREPEAT194(macro, data) macro(194, data)
|
||||
#define MREPEAT196(macro, data) MREPEAT195(macro, data) macro(195, data)
|
||||
#define MREPEAT197(macro, data) MREPEAT196(macro, data) macro(196, data)
|
||||
#define MREPEAT198(macro, data) MREPEAT197(macro, data) macro(197, data)
|
||||
#define MREPEAT199(macro, data) MREPEAT198(macro, data) macro(198, data)
|
||||
#define MREPEAT200(macro, data) MREPEAT199(macro, data) macro(199, data)
|
||||
#define MREPEAT201(macro, data) MREPEAT200(macro, data) macro(200, data)
|
||||
#define MREPEAT202(macro, data) MREPEAT201(macro, data) macro(201, data)
|
||||
#define MREPEAT203(macro, data) MREPEAT202(macro, data) macro(202, data)
|
||||
#define MREPEAT204(macro, data) MREPEAT203(macro, data) macro(203, data)
|
||||
#define MREPEAT205(macro, data) MREPEAT204(macro, data) macro(204, data)
|
||||
#define MREPEAT206(macro, data) MREPEAT205(macro, data) macro(205, data)
|
||||
#define MREPEAT207(macro, data) MREPEAT206(macro, data) macro(206, data)
|
||||
#define MREPEAT208(macro, data) MREPEAT207(macro, data) macro(207, data)
|
||||
#define MREPEAT209(macro, data) MREPEAT208(macro, data) macro(208, data)
|
||||
#define MREPEAT210(macro, data) MREPEAT209(macro, data) macro(209, data)
|
||||
#define MREPEAT211(macro, data) MREPEAT210(macro, data) macro(210, data)
|
||||
#define MREPEAT212(macro, data) MREPEAT211(macro, data) macro(211, data)
|
||||
#define MREPEAT213(macro, data) MREPEAT212(macro, data) macro(212, data)
|
||||
#define MREPEAT214(macro, data) MREPEAT213(macro, data) macro(213, data)
|
||||
#define MREPEAT215(macro, data) MREPEAT214(macro, data) macro(214, data)
|
||||
#define MREPEAT216(macro, data) MREPEAT215(macro, data) macro(215, data)
|
||||
#define MREPEAT217(macro, data) MREPEAT216(macro, data) macro(216, data)
|
||||
#define MREPEAT218(macro, data) MREPEAT217(macro, data) macro(217, data)
|
||||
#define MREPEAT219(macro, data) MREPEAT218(macro, data) macro(218, data)
|
||||
#define MREPEAT220(macro, data) MREPEAT219(macro, data) macro(219, data)
|
||||
#define MREPEAT221(macro, data) MREPEAT220(macro, data) macro(220, data)
|
||||
#define MREPEAT222(macro, data) MREPEAT221(macro, data) macro(221, data)
|
||||
#define MREPEAT223(macro, data) MREPEAT222(macro, data) macro(222, data)
|
||||
#define MREPEAT224(macro, data) MREPEAT223(macro, data) macro(223, data)
|
||||
#define MREPEAT225(macro, data) MREPEAT224(macro, data) macro(224, data)
|
||||
#define MREPEAT226(macro, data) MREPEAT225(macro, data) macro(225, data)
|
||||
#define MREPEAT227(macro, data) MREPEAT226(macro, data) macro(226, data)
|
||||
#define MREPEAT228(macro, data) MREPEAT227(macro, data) macro(227, data)
|
||||
#define MREPEAT229(macro, data) MREPEAT228(macro, data) macro(228, data)
|
||||
#define MREPEAT230(macro, data) MREPEAT229(macro, data) macro(229, data)
|
||||
#define MREPEAT231(macro, data) MREPEAT230(macro, data) macro(230, data)
|
||||
#define MREPEAT232(macro, data) MREPEAT231(macro, data) macro(231, data)
|
||||
#define MREPEAT233(macro, data) MREPEAT232(macro, data) macro(232, data)
|
||||
#define MREPEAT234(macro, data) MREPEAT233(macro, data) macro(233, data)
|
||||
#define MREPEAT235(macro, data) MREPEAT234(macro, data) macro(234, data)
|
||||
#define MREPEAT236(macro, data) MREPEAT235(macro, data) macro(235, data)
|
||||
#define MREPEAT237(macro, data) MREPEAT236(macro, data) macro(236, data)
|
||||
#define MREPEAT238(macro, data) MREPEAT237(macro, data) macro(237, data)
|
||||
#define MREPEAT239(macro, data) MREPEAT238(macro, data) macro(238, data)
|
||||
#define MREPEAT240(macro, data) MREPEAT239(macro, data) macro(239, data)
|
||||
#define MREPEAT241(macro, data) MREPEAT240(macro, data) macro(240, data)
|
||||
#define MREPEAT242(macro, data) MREPEAT241(macro, data) macro(241, data)
|
||||
#define MREPEAT243(macro, data) MREPEAT242(macro, data) macro(242, data)
|
||||
#define MREPEAT244(macro, data) MREPEAT243(macro, data) macro(243, data)
|
||||
#define MREPEAT245(macro, data) MREPEAT244(macro, data) macro(244, data)
|
||||
#define MREPEAT246(macro, data) MREPEAT245(macro, data) macro(245, data)
|
||||
#define MREPEAT247(macro, data) MREPEAT246(macro, data) macro(246, data)
|
||||
#define MREPEAT248(macro, data) MREPEAT247(macro, data) macro(247, data)
|
||||
#define MREPEAT249(macro, data) MREPEAT248(macro, data) macro(248, data)
|
||||
#define MREPEAT250(macro, data) MREPEAT249(macro, data) macro(249, data)
|
||||
#define MREPEAT251(macro, data) MREPEAT250(macro, data) macro(250, data)
|
||||
#define MREPEAT252(macro, data) MREPEAT251(macro, data) macro(251, data)
|
||||
#define MREPEAT253(macro, data) MREPEAT252(macro, data) macro(252, data)
|
||||
#define MREPEAT254(macro, data) MREPEAT253(macro, data) macro(253, data)
|
||||
#define MREPEAT255(macro, data) MREPEAT254(macro, data) macro(254, data)
|
||||
#define MREPEAT256(macro, data) MREPEAT255(macro, data) macro(255, data)
|
||||
|
||||
/**
|
||||
* \}
|
||||
*/
|
||||
|
||||
#endif // _MREPEAT_H_
|
|
@ -0,0 +1,254 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief Chip-specific oscillator management functions.
|
||||
*
|
||||
* Copyright (c) 2011-2015 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Support and FAQ: visit <a href="https://www.atmel.com/design-support/">Atmel Support</a>
|
||||
*/
|
||||
|
||||
#ifndef CHIP_OSC_H_INCLUDED
|
||||
#define CHIP_OSC_H_INCLUDED
|
||||
|
||||
#include "compiler.h"
|
||||
|
||||
/// @cond 0
|
||||
/**INDENT-OFF**/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/**INDENT-ON**/
|
||||
/// @endcond
|
||||
|
||||
/*
|
||||
* Below BOARD_XXX macros are related to the specific board, and
|
||||
* should be defined by the board code, otherwise default value are used.
|
||||
*/
|
||||
#ifndef BOARD_FREQ_SLCK_XTAL
|
||||
#warning The board slow clock xtal frequency has not been defined.
|
||||
#define BOARD_FREQ_SLCK_XTAL (32768UL)
|
||||
#endif
|
||||
|
||||
#ifndef BOARD_FREQ_SLCK_BYPASS
|
||||
#warning The board slow clock bypass frequency has not been defined.
|
||||
#define BOARD_FREQ_SLCK_BYPASS (32768UL)
|
||||
#endif
|
||||
|
||||
#ifndef BOARD_FREQ_MAINCK_XTAL
|
||||
#warning The board main clock xtal frequency has not been defined.
|
||||
#define BOARD_FREQ_MAINCK_XTAL (12000000UL)
|
||||
#endif
|
||||
|
||||
#ifndef BOARD_FREQ_MAINCK_BYPASS
|
||||
#warning The board main clock bypass frequency has not been defined.
|
||||
#define BOARD_FREQ_MAINCK_BYPASS (12000000UL)
|
||||
#endif
|
||||
|
||||
#ifndef BOARD_OSC_STARTUP_US
|
||||
#warning The board main clock xtal startup time has not been defined.
|
||||
#define BOARD_OSC_STARTUP_US (15625UL)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \weakgroup osc_group
|
||||
* @{
|
||||
*/
|
||||
|
||||
//! \name Oscillator identifiers
|
||||
//@{
|
||||
#define OSC_SLCK_32K_RC 0 //!< Internal 32kHz RC oscillator.
|
||||
#define OSC_SLCK_32K_XTAL 1 //!< External 32kHz crystal oscillator.
|
||||
#define OSC_SLCK_32K_BYPASS 2 //!< External 32kHz bypass oscillator.
|
||||
#define OSC_MAINCK_4M_RC 3 //!< Internal 4MHz RC oscillator.
|
||||
#define OSC_MAINCK_8M_RC 4 //!< Internal 8MHz RC oscillator.
|
||||
#define OSC_MAINCK_12M_RC 5 //!< Internal 12MHz RC oscillator.
|
||||
#define OSC_MAINCK_XTAL 6 //!< External crystal oscillator.
|
||||
#define OSC_MAINCK_BYPASS 7 //!< External bypass oscillator.
|
||||
//@}
|
||||
|
||||
//! \name Oscillator clock speed in hertz
|
||||
//@{
|
||||
#define OSC_SLCK_32K_RC_HZ CHIP_FREQ_SLCK_RC //!< Internal 32kHz RC oscillator.
|
||||
#define OSC_SLCK_32K_XTAL_HZ BOARD_FREQ_SLCK_XTAL //!< External 32kHz crystal oscillator.
|
||||
#define OSC_SLCK_32K_BYPASS_HZ BOARD_FREQ_SLCK_BYPASS //!< External 32kHz bypass oscillator.
|
||||
#define OSC_MAINCK_4M_RC_HZ CHIP_FREQ_MAINCK_RC_4MHZ //!< Internal 4MHz RC oscillator.
|
||||
#define OSC_MAINCK_8M_RC_HZ CHIP_FREQ_MAINCK_RC_8MHZ //!< Internal 8MHz RC oscillator.
|
||||
#define OSC_MAINCK_12M_RC_HZ CHIP_FREQ_MAINCK_RC_12MHZ //!< Internal 12MHz RC oscillator.
|
||||
#define OSC_MAINCK_XTAL_HZ BOARD_FREQ_MAINCK_XTAL //!< External crystal oscillator.
|
||||
#define OSC_MAINCK_BYPASS_HZ BOARD_FREQ_MAINCK_BYPASS //!< External bypass oscillator.
|
||||
//@}
|
||||
|
||||
static inline void osc_enable(uint32_t ul_id) {
|
||||
switch (ul_id) {
|
||||
case OSC_SLCK_32K_RC:
|
||||
break;
|
||||
|
||||
case OSC_SLCK_32K_XTAL:
|
||||
pmc_switch_sclk_to_32kxtal(PMC_OSC_XTAL);
|
||||
break;
|
||||
|
||||
case OSC_SLCK_32K_BYPASS:
|
||||
pmc_switch_sclk_to_32kxtal(PMC_OSC_BYPASS);
|
||||
break;
|
||||
|
||||
case OSC_MAINCK_4M_RC:
|
||||
pmc_switch_mainck_to_fastrc(CKGR_MOR_MOSCRCF_4_MHz);
|
||||
break;
|
||||
|
||||
case OSC_MAINCK_8M_RC:
|
||||
pmc_switch_mainck_to_fastrc(CKGR_MOR_MOSCRCF_8_MHz);
|
||||
break;
|
||||
|
||||
case OSC_MAINCK_12M_RC:
|
||||
pmc_switch_mainck_to_fastrc(CKGR_MOR_MOSCRCF_12_MHz);
|
||||
break;
|
||||
|
||||
case OSC_MAINCK_XTAL:
|
||||
pmc_switch_mainck_to_xtal(PMC_OSC_XTAL/*,
|
||||
pmc_us_to_moscxtst(BOARD_OSC_STARTUP_US,
|
||||
OSC_SLCK_32K_RC_HZ)*/);
|
||||
break;
|
||||
|
||||
case OSC_MAINCK_BYPASS:
|
||||
pmc_switch_mainck_to_xtal(PMC_OSC_BYPASS/*,
|
||||
pmc_us_to_moscxtst(BOARD_OSC_STARTUP_US,
|
||||
OSC_SLCK_32K_RC_HZ)*/);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void osc_disable(uint32_t ul_id) {
|
||||
switch (ul_id) {
|
||||
case OSC_SLCK_32K_RC:
|
||||
case OSC_SLCK_32K_XTAL:
|
||||
case OSC_SLCK_32K_BYPASS:
|
||||
break;
|
||||
|
||||
case OSC_MAINCK_4M_RC:
|
||||
case OSC_MAINCK_8M_RC:
|
||||
case OSC_MAINCK_12M_RC:
|
||||
pmc_osc_disable_fastrc();
|
||||
break;
|
||||
|
||||
case OSC_MAINCK_XTAL:
|
||||
pmc_osc_disable_xtal(PMC_OSC_XTAL);
|
||||
break;
|
||||
|
||||
case OSC_MAINCK_BYPASS:
|
||||
pmc_osc_disable_xtal(PMC_OSC_BYPASS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool osc_is_ready(uint32_t ul_id) {
|
||||
switch (ul_id) {
|
||||
case OSC_SLCK_32K_RC:
|
||||
return 1;
|
||||
|
||||
case OSC_SLCK_32K_XTAL:
|
||||
case OSC_SLCK_32K_BYPASS:
|
||||
return pmc_osc_is_ready_32kxtal();
|
||||
|
||||
case OSC_MAINCK_4M_RC:
|
||||
case OSC_MAINCK_8M_RC:
|
||||
case OSC_MAINCK_12M_RC:
|
||||
case OSC_MAINCK_XTAL:
|
||||
case OSC_MAINCK_BYPASS:
|
||||
return pmc_osc_is_ready_mainck();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline uint32_t osc_get_rate(uint32_t ul_id) {
|
||||
switch (ul_id) {
|
||||
case OSC_SLCK_32K_RC:
|
||||
return OSC_SLCK_32K_RC_HZ;
|
||||
|
||||
case OSC_SLCK_32K_XTAL:
|
||||
return BOARD_FREQ_SLCK_XTAL;
|
||||
|
||||
case OSC_SLCK_32K_BYPASS:
|
||||
return BOARD_FREQ_SLCK_BYPASS;
|
||||
|
||||
case OSC_MAINCK_4M_RC:
|
||||
return OSC_MAINCK_4M_RC_HZ;
|
||||
|
||||
case OSC_MAINCK_8M_RC:
|
||||
return OSC_MAINCK_8M_RC_HZ;
|
||||
|
||||
case OSC_MAINCK_12M_RC:
|
||||
return OSC_MAINCK_12M_RC_HZ;
|
||||
|
||||
case OSC_MAINCK_XTAL:
|
||||
return BOARD_FREQ_MAINCK_XTAL;
|
||||
|
||||
case OSC_MAINCK_BYPASS:
|
||||
return BOARD_FREQ_MAINCK_BYPASS;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Wait until the oscillator identified by \a id is ready
|
||||
*
|
||||
* This function will busy-wait for the oscillator identified by \a id
|
||||
* to become stable and ready to use as a clock source.
|
||||
*
|
||||
* \param id A number identifying the oscillator to wait for.
|
||||
*/
|
||||
static inline void osc_wait_ready(uint8_t id) {
|
||||
while (!osc_is_ready(id)) {
|
||||
/* Do nothing */
|
||||
}
|
||||
}
|
||||
|
||||
//! @}
|
||||
|
||||
/// @cond 0
|
||||
/**INDENT-OFF**/
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/**INDENT-ON**/
|
||||
/// @endcond
|
||||
|
||||
#endif /* CHIP_OSC_H_INCLUDED */
|
|
@ -0,0 +1,270 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief Chip-specific PLL definitions.
|
||||
*
|
||||
* Copyright (c) 2011-2015 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Support and FAQ: visit <a href="https://www.atmel.com/design-support/">Atmel Support</a>
|
||||
*/
|
||||
|
||||
#ifndef CHIP_PLL_H_INCLUDED
|
||||
#define CHIP_PLL_H_INCLUDED
|
||||
|
||||
#include "osc.h"
|
||||
|
||||
/// @cond 0
|
||||
/**INDENT-OFF**/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/**INDENT-ON**/
|
||||
/// @endcond
|
||||
|
||||
/**
|
||||
* \weakgroup pll_group
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define PLL_OUTPUT_MIN_HZ 84000000
|
||||
#define PLL_OUTPUT_MAX_HZ 192000000
|
||||
|
||||
#define PLL_INPUT_MIN_HZ 8000000
|
||||
#define PLL_INPUT_MAX_HZ 16000000
|
||||
|
||||
#define NR_PLLS 2
|
||||
#define PLLA_ID 0
|
||||
#define UPLL_ID 1 //!< USB UTMI PLL.
|
||||
|
||||
#define PLL_UPLL_HZ 480000000
|
||||
|
||||
#define PLL_COUNT 0x3FU
|
||||
|
||||
enum pll_source {
|
||||
PLL_SRC_MAINCK_4M_RC = OSC_MAINCK_4M_RC, //!< Internal 4MHz RC oscillator.
|
||||
PLL_SRC_MAINCK_8M_RC = OSC_MAINCK_8M_RC, //!< Internal 8MHz RC oscillator.
|
||||
PLL_SRC_MAINCK_12M_RC = OSC_MAINCK_12M_RC, //!< Internal 12MHz RC oscillator.
|
||||
PLL_SRC_MAINCK_XTAL = OSC_MAINCK_XTAL, //!< External crystal oscillator.
|
||||
PLL_SRC_MAINCK_BYPASS = OSC_MAINCK_BYPASS, //!< External bypass oscillator.
|
||||
PLL_NR_SOURCES, //!< Number of PLL sources.
|
||||
};
|
||||
|
||||
struct pll_config {
|
||||
uint32_t ctrl;
|
||||
};
|
||||
|
||||
#define pll_get_default_rate(pll_id) \
|
||||
((osc_get_rate(CONFIG_PLL##pll_id##_SOURCE) \
|
||||
* CONFIG_PLL##pll_id##_MUL) \
|
||||
/ CONFIG_PLL##pll_id##_DIV)
|
||||
|
||||
/* Force UTMI PLL parameters (Hardware defined) */
|
||||
#ifdef CONFIG_PLL1_SOURCE
|
||||
# undef CONFIG_PLL1_SOURCE
|
||||
#endif
|
||||
#ifdef CONFIG_PLL1_MUL
|
||||
# undef CONFIG_PLL1_MUL
|
||||
#endif
|
||||
#ifdef CONFIG_PLL1_DIV
|
||||
# undef CONFIG_PLL1_DIV
|
||||
#endif
|
||||
#define CONFIG_PLL1_SOURCE PLL_SRC_MAINCK_XTAL
|
||||
#define CONFIG_PLL1_MUL 0
|
||||
#define CONFIG_PLL1_DIV 0
|
||||
|
||||
/**
|
||||
* \note The SAM3X PLL hardware interprets mul as mul+1. For readability the hardware mul+1
|
||||
* is hidden in this implementation. Use mul as mul effective value.
|
||||
*/
|
||||
static inline void pll_config_init(struct pll_config *p_cfg,
|
||||
enum pll_source e_src, uint32_t ul_div, uint32_t ul_mul) {
|
||||
uint32_t vco_hz;
|
||||
|
||||
Assert(e_src < PLL_NR_SOURCES);
|
||||
|
||||
if (ul_div == 0 && ul_mul == 0) { /* Must only be true for UTMI PLL */
|
||||
p_cfg->ctrl = CKGR_UCKR_UPLLCOUNT(PLL_COUNT);
|
||||
}
|
||||
else { /* PLLA */
|
||||
/* Calculate internal VCO frequency */
|
||||
vco_hz = osc_get_rate(e_src) / ul_div;
|
||||
Assert(vco_hz >= PLL_INPUT_MIN_HZ);
|
||||
Assert(vco_hz <= PLL_INPUT_MAX_HZ);
|
||||
|
||||
vco_hz *= ul_mul;
|
||||
Assert(vco_hz >= PLL_OUTPUT_MIN_HZ);
|
||||
Assert(vco_hz <= PLL_OUTPUT_MAX_HZ);
|
||||
|
||||
/* PMC hardware will automatically make it mul+1 */
|
||||
p_cfg->ctrl = CKGR_PLLAR_MULA(ul_mul - 1) | CKGR_PLLAR_DIVA(ul_div) | CKGR_PLLAR_PLLACOUNT(PLL_COUNT);
|
||||
}
|
||||
}
|
||||
|
||||
#define pll_config_defaults(cfg, pll_id) \
|
||||
pll_config_init(cfg, \
|
||||
CONFIG_PLL##pll_id##_SOURCE, \
|
||||
CONFIG_PLL##pll_id##_DIV, \
|
||||
CONFIG_PLL##pll_id##_MUL)
|
||||
|
||||
static inline void pll_config_read(struct pll_config *p_cfg, uint32_t ul_pll_id) {
|
||||
Assert(ul_pll_id < NR_PLLS);
|
||||
p_cfg->ctrl = ul_pll_id == PLLA_ID ? PMC->CKGR_PLLAR : PMC->CKGR_UCKR;
|
||||
}
|
||||
|
||||
static inline void pll_config_write(const struct pll_config *p_cfg, uint32_t ul_pll_id) {
|
||||
Assert(ul_pll_id < NR_PLLS);
|
||||
|
||||
if (ul_pll_id == PLLA_ID) {
|
||||
pmc_disable_pllack(); // Always stop PLL first!
|
||||
PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | p_cfg->ctrl;
|
||||
}
|
||||
else
|
||||
PMC->CKGR_UCKR = p_cfg->ctrl;
|
||||
}
|
||||
|
||||
static inline void pll_enable(const struct pll_config *p_cfg, uint32_t ul_pll_id) {
|
||||
Assert(ul_pll_id < NR_PLLS);
|
||||
|
||||
if (ul_pll_id == PLLA_ID) {
|
||||
pmc_disable_pllack(); // Always stop PLL first!
|
||||
PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | p_cfg->ctrl;
|
||||
}
|
||||
else
|
||||
PMC->CKGR_UCKR = p_cfg->ctrl | CKGR_UCKR_UPLLEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* \note This will only disable the selected PLL, not the underlying oscillator (mainck).
|
||||
*/
|
||||
static inline void pll_disable(uint32_t ul_pll_id) {
|
||||
Assert(ul_pll_id < NR_PLLS);
|
||||
|
||||
if (ul_pll_id == PLLA_ID)
|
||||
pmc_disable_pllack();
|
||||
else
|
||||
PMC->CKGR_UCKR &= ~CKGR_UCKR_UPLLEN;
|
||||
}
|
||||
|
||||
static inline uint32_t pll_is_locked(uint32_t ul_pll_id) {
|
||||
Assert(ul_pll_id < NR_PLLS);
|
||||
|
||||
if (ul_pll_id == PLLA_ID)
|
||||
return pmc_is_locked_pllack();
|
||||
else
|
||||
return pmc_is_locked_upll();
|
||||
}
|
||||
|
||||
static inline void pll_enable_source(enum pll_source e_src) {
|
||||
switch (e_src) {
|
||||
case PLL_SRC_MAINCK_4M_RC:
|
||||
case PLL_SRC_MAINCK_8M_RC:
|
||||
case PLL_SRC_MAINCK_12M_RC:
|
||||
case PLL_SRC_MAINCK_XTAL:
|
||||
case PLL_SRC_MAINCK_BYPASS:
|
||||
osc_enable(e_src);
|
||||
osc_wait_ready(e_src);
|
||||
break;
|
||||
|
||||
default:
|
||||
Assert(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void pll_enable_config_defaults(unsigned int ul_pll_id) {
|
||||
struct pll_config pllcfg;
|
||||
|
||||
if (pll_is_locked(ul_pll_id)) return; // Pll already running
|
||||
|
||||
switch (ul_pll_id) {
|
||||
#ifdef CONFIG_PLL0_SOURCE
|
||||
case 0:
|
||||
pll_enable_source(CONFIG_PLL0_SOURCE);
|
||||
pll_config_init(&pllcfg,
|
||||
CONFIG_PLL0_SOURCE,
|
||||
CONFIG_PLL0_DIV,
|
||||
CONFIG_PLL0_MUL);
|
||||
break;
|
||||
#endif
|
||||
#ifdef CONFIG_PLL1_SOURCE
|
||||
case 1:
|
||||
pll_enable_source(CONFIG_PLL1_SOURCE);
|
||||
pll_config_init(&pllcfg,
|
||||
CONFIG_PLL1_SOURCE,
|
||||
CONFIG_PLL1_DIV,
|
||||
CONFIG_PLL1_MUL);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
Assert(false);
|
||||
break;
|
||||
}
|
||||
pll_enable(&pllcfg, ul_pll_id);
|
||||
while (!pll_is_locked(ul_pll_id));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Wait for PLL \a pll_id to become locked
|
||||
*
|
||||
* \todo Use a timeout to avoid waiting forever and hanging the system
|
||||
*
|
||||
* \param pll_id The ID of the PLL to wait for.
|
||||
*
|
||||
* \retval STATUS_OK The PLL is now locked.
|
||||
* \retval ERR_TIMEOUT Timed out waiting for PLL to become locked.
|
||||
*/
|
||||
static inline int pll_wait_for_lock(unsigned int pll_id) {
|
||||
Assert(pll_id < NR_PLLS);
|
||||
|
||||
while (!pll_is_locked(pll_id)) { /* Do nothing */ }
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! @}
|
||||
|
||||
/// @cond 0
|
||||
/**INDENT-OFF**/
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/**INDENT-ON**/
|
||||
/// @endcond
|
||||
|
||||
#endif /* CHIP_PLL_H_INCLUDED */
|
|
@ -0,0 +1,54 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief Preprocessor utils.
|
||||
*
|
||||
* Copyright (c) 2010-2015 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Support and FAQ: visit <a href="https://www.atmel.com/design-support/">Atmel Support</a>
|
||||
*/
|
||||
|
||||
#ifndef _PREPROCESSOR_H_
|
||||
#define _PREPROCESSOR_H_
|
||||
|
||||
#include "tpaste.h"
|
||||
#include "stringz.h"
|
||||
#include "mrepeat.h"
|
||||
|
||||
#endif // _PREPROCESSOR_H_
|
|
@ -0,0 +1,171 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief SCSI Block Commands
|
||||
*
|
||||
* This file contains definitions of some of the commands found in the
|
||||
* SCSI SBC-2 standard.
|
||||
*
|
||||
* Note that the SBC specification depends on several commands defined
|
||||
* by the SCSI Primary Commands (SPC) standard. Each version of the SBC
|
||||
* standard is meant to be used in conjunction with a specific version
|
||||
* of the SPC standard, as follows:
|
||||
* - SBC depends on SPC
|
||||
* - SBC-2 depends on SPC-3
|
||||
* - SBC-3 depends on SPC-4
|
||||
*
|
||||
* Copyright (c) 2014-2015 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
/*
|
||||
* Support and FAQ: visit <a href="https://www.atmel.com/design-support/">Atmel Support</a>
|
||||
*/
|
||||
#ifndef _SBC_PROTOCOL_H_
|
||||
#define _SBC_PROTOCOL_H_
|
||||
|
||||
/**
|
||||
* \ingroup usb_msc_protocol
|
||||
* \defgroup usb_sbc_protocol SCSI Block Commands protocol definitions
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
//! \name SCSI commands defined by SBC-2
|
||||
//@{
|
||||
#define SBC_FORMAT_UNIT 0x04
|
||||
#define SBC_READ6 0x08
|
||||
#define SBC_WRITE6 0x0A
|
||||
#define SBC_START_STOP_UNIT 0x1B
|
||||
#define SBC_READ_CAPACITY10 0x25
|
||||
#define SBC_READ10 0x28
|
||||
#define SBC_WRITE10 0x2A
|
||||
#define SBC_VERIFY10 0x2F
|
||||
//@}
|
||||
|
||||
//! \name SBC-2 Mode page definitions
|
||||
//@{
|
||||
|
||||
enum scsi_sbc_mode {
|
||||
SCSI_MS_MODE_RW_ERR_RECOV = 0x01, //!< Read-Write Error Recovery mode page
|
||||
SCSI_MS_MODE_FORMAT_DEVICE = 0x03, //!< Format Device mode page
|
||||
SCSI_MS_MODE_FLEXIBLE_DISK = 0x05, //!< Flexible Disk mode page
|
||||
SCSI_MS_MODE_CACHING = 0x08, //!< Caching mode page
|
||||
};
|
||||
|
||||
//! \name SBC-2 Device-Specific Parameter
|
||||
//@{
|
||||
#define SCSI_MS_SBC_WP 0x80 //!< Write Protected
|
||||
#define SCSI_MS_SBC_DPOFUA 0x10 //!< DPO and FUA supported
|
||||
//@}
|
||||
|
||||
/**
|
||||
* \brief SBC-2 Short LBA mode parameter block descriptor
|
||||
*/
|
||||
struct sbc_slba_block_desc {
|
||||
be32_t nr_blocks; //!< Number of Blocks
|
||||
be32_t block_len; //!< Block Length
|
||||
#define SBC_SLBA_BLOCK_LEN_MASK 0x00FFFFFFU //!< Mask reserved bits
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief SBC-2 Caching mode page
|
||||
*/
|
||||
struct sbc_caching_mode_page {
|
||||
uint8_t page_code;
|
||||
uint8_t page_length;
|
||||
uint8_t flags2;
|
||||
#define SBC_MP_CACHE_IC (1 << 7) //!< Initiator Control
|
||||
#define SBC_MP_CACHE_ABPF (1 << 6) //!< Abort Pre-Fetch
|
||||
#define SBC_MP_CACHE_CAP (1 << 5) //!< Catching Analysis Permitted
|
||||
#define SBC_MP_CACHE_DISC (1 << 4) //!< Discontinuity
|
||||
#define SBC_MP_CACHE_SIZE (1 << 3) //!< Size enable
|
||||
#define SBC_MP_CACHE_WCE (1 << 2) //!< Write back Cache Enable
|
||||
#define SBC_MP_CACHE_MF (1 << 1) //!< Multiplication Factor
|
||||
#define SBC_MP_CACHE_RCD (1 << 0) //!< Read Cache Disable
|
||||
uint8_t retention;
|
||||
be16_t dis_pf_transfer_len;
|
||||
be16_t min_prefetch;
|
||||
be16_t max_prefetch;
|
||||
be16_t max_prefetch_ceil;
|
||||
uint8_t flags12;
|
||||
#define SBC_MP_CACHE_FSW (1 << 7) //!< Force Sequential Write
|
||||
#define SBC_MP_CACHE_LBCSS (1 << 6) //!< Logical Blk Cache Seg Sz
|
||||
#define SBC_MP_CACHE_DRA (1 << 5) //!< Disable Read-Ahead
|
||||
#define SBC_MP_CACHE_NV_DIS (1 << 0) //!< Non-Volatile Cache Disable
|
||||
uint8_t nr_cache_segments;
|
||||
be16_t cache_segment_size;
|
||||
uint8_t reserved[4];
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief SBC-2 Read-Write Error Recovery mode page
|
||||
*/
|
||||
struct sbc_rdwr_error_recovery_mode_page {
|
||||
uint8_t page_code;
|
||||
uint8_t page_length;
|
||||
#define SPC_MP_RW_ERR_RECOV_PAGE_LENGTH 0x0A
|
||||
uint8_t flags1;
|
||||
#define SBC_MP_RW_ERR_RECOV_AWRE (1 << 7)
|
||||
#define SBC_MP_RW_ERR_RECOV_ARRE (1 << 6)
|
||||
#define SBC_MP_RW_ERR_RECOV_TB (1 << 5)
|
||||
#define SBC_MP_RW_ERR_RECOV_RC (1 << 4)
|
||||
#define SBC_MP_RW_ERR_RECOV_ERR (1 << 3)
|
||||
#define SBC_MP_RW_ERR_RECOV_PER (1 << 2)
|
||||
#define SBC_MP_RW_ERR_RECOV_DTE (1 << 1)
|
||||
#define SBC_MP_RW_ERR_RECOV_DCR (1 << 0)
|
||||
uint8_t read_retry_count;
|
||||
uint8_t correction_span;
|
||||
uint8_t head_offset_count;
|
||||
uint8_t data_strobe_offset_count;
|
||||
uint8_t flags2;
|
||||
uint8_t write_retry_count;
|
||||
uint8_t flags3;
|
||||
be16_t recovery_time_limit;
|
||||
};
|
||||
//@}
|
||||
|
||||
/**
|
||||
* \brief SBC-2 READ CAPACITY (10) parameter data
|
||||
*/
|
||||
struct sbc_read_capacity10_data {
|
||||
be32_t max_lba; //!< LBA of last logical block
|
||||
be32_t block_len; //!< Number of bytes in the last logical block
|
||||
};
|
||||
|
||||
//@}
|
||||
|
||||
#endif // _SBC_PROTOCOL_H_
|
|
@ -0,0 +1,142 @@
|
|||
/**
|
||||
* Interface from Atmel USB MSD to Marlin SD card
|
||||
*/
|
||||
|
||||
#ifdef ARDUINO_ARCH_SAM
|
||||
|
||||
#include "../../../inc/MarlinConfig.h"
|
||||
|
||||
#if HAS_MEDIA
|
||||
|
||||
#include "../../../sd/cardreader.h"
|
||||
extern "C" {
|
||||
#include "sd_mmc_spi_mem.h"
|
||||
}
|
||||
|
||||
#define SD_MMC_BLOCK_SIZE 512
|
||||
|
||||
void sd_mmc_spi_mem_init() {
|
||||
}
|
||||
|
||||
Ctrl_status sd_mmc_spi_test_unit_ready() {
|
||||
#ifdef DISABLE_DUE_SD_MMC
|
||||
return CTRL_NO_PRESENT;
|
||||
#endif
|
||||
if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.isMounted())
|
||||
return CTRL_NO_PRESENT;
|
||||
return CTRL_GOOD;
|
||||
}
|
||||
|
||||
// NOTE: This function is defined as returning the address of the last block
|
||||
// in the card, which is cardSize() - 1
|
||||
Ctrl_status sd_mmc_spi_read_capacity(uint32_t *nb_sector) {
|
||||
if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.isMounted())
|
||||
return CTRL_NO_PRESENT;
|
||||
*nb_sector = card.diskIODriver()->cardSize() - 1;
|
||||
return CTRL_GOOD;
|
||||
}
|
||||
|
||||
bool sd_mmc_spi_unload(bool) { return true; }
|
||||
|
||||
bool sd_mmc_spi_wr_protect() { return false; }
|
||||
|
||||
bool sd_mmc_spi_removal() {
|
||||
return (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.isMounted());
|
||||
}
|
||||
|
||||
#if ACCESS_USB == true
|
||||
/**
|
||||
* \name MEM <-> USB Interface
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "udi_msc.h"
|
||||
|
||||
COMPILER_WORD_ALIGNED
|
||||
uint8_t sector_buf[SD_MMC_BLOCK_SIZE];
|
||||
|
||||
// #define DEBUG_MMC
|
||||
|
||||
Ctrl_status sd_mmc_spi_usb_read_10(uint32_t addr, uint16_t nb_sector) {
|
||||
#ifdef DISABLE_DUE_SD_MMC
|
||||
return CTRL_NO_PRESENT;
|
||||
#endif
|
||||
if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.isMounted())
|
||||
return CTRL_NO_PRESENT;
|
||||
|
||||
#ifdef DEBUG_MMC
|
||||
{
|
||||
char buffer[80];
|
||||
sprintf_P(buffer, PSTR("SDRD: %d @ 0x%08x\n"), nb_sector, addr);
|
||||
PORT_REDIRECT(SERIAL_PORTMASK(0));
|
||||
SERIAL_ECHO(buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Start reading
|
||||
if (!card.diskIODriver()->readStart(addr))
|
||||
return CTRL_FAIL;
|
||||
|
||||
// For each specified sector
|
||||
while (nb_sector--) {
|
||||
|
||||
// Read a sector
|
||||
card.diskIODriver()->readData(sector_buf);
|
||||
|
||||
// RAM -> USB
|
||||
if (!udi_msc_trans_block(true, sector_buf, SD_MMC_BLOCK_SIZE, nullptr)) {
|
||||
card.diskIODriver()->readStop();
|
||||
return CTRL_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
// Stop reading
|
||||
card.diskIODriver()->readStop();
|
||||
|
||||
// Done
|
||||
return CTRL_GOOD;
|
||||
}
|
||||
|
||||
Ctrl_status sd_mmc_spi_usb_write_10(uint32_t addr, uint16_t nb_sector) {
|
||||
#ifdef DISABLE_DUE_SD_MMC
|
||||
return CTRL_NO_PRESENT;
|
||||
#endif
|
||||
if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.isMounted())
|
||||
return CTRL_NO_PRESENT;
|
||||
|
||||
#ifdef DEBUG_MMC
|
||||
{
|
||||
char buffer[80];
|
||||
sprintf_P(buffer, PSTR("SDWR: %d @ 0x%08x\n"), nb_sector, addr);
|
||||
PORT_REDIRECT(SERIAL_PORTMASK(0));
|
||||
SERIAL_ECHO(buffer);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!card.diskIODriver()->writeStart(addr, nb_sector))
|
||||
return CTRL_FAIL;
|
||||
|
||||
// For each specified sector
|
||||
while (nb_sector--) {
|
||||
|
||||
// USB -> RAM
|
||||
if (!udi_msc_trans_block(false, sector_buf, SD_MMC_BLOCK_SIZE, nullptr)) {
|
||||
card.diskIODriver()->writeStop();
|
||||
return CTRL_FAIL;
|
||||
}
|
||||
|
||||
// Write a sector
|
||||
card.diskIODriver()->writeData(sector_buf);
|
||||
}
|
||||
|
||||
// Stop writing
|
||||
card.diskIODriver()->writeStop();
|
||||
|
||||
// Done
|
||||
return CTRL_GOOD;
|
||||
}
|
||||
|
||||
#endif // ACCESS_USB == true
|
||||
|
||||
#endif // HAS_MEDIA
|
||||
#endif // ARDUINO_ARCH_SAM
|
|
@ -0,0 +1,172 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* \file
|
||||
*
|
||||
* \brief CTRL_ACCESS interface for SD/MMC card.
|
||||
*
|
||||
* Copyright (c) 2014-2015 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
******************************************************************************/
|
||||
/*
|
||||
* Support and FAQ: visit <a href="https://www.atmel.com/design-support/">Atmel Support</a>
|
||||
*/
|
||||
|
||||
#ifndef _SD_MMC_SPI_MEM_H_
|
||||
#define _SD_MMC_SPI_MEM_H_
|
||||
|
||||
/**
|
||||
* \defgroup group_avr32_components_memory_sd_mmc_sd_mmc_spi_mem SD/MMC SPI Memory
|
||||
*
|
||||
* \ingroup group_avr32_components_memory_sd_mmc_sd_mmc_spi
|
||||
*
|
||||
* \{
|
||||
*/
|
||||
|
||||
#include "conf_access.h"
|
||||
|
||||
#if SD_MMC_SPI_MEM == DISABLE
|
||||
#error sd_mmc_spi_mem.h is #included although SD_MMC_SPI_MEM is disabled
|
||||
#endif
|
||||
|
||||
#include "ctrl_access.h"
|
||||
|
||||
//_____ D E F I N I T I O N S ______________________________________________
|
||||
|
||||
#define SD_MMC_REMOVED 0
|
||||
#define SD_MMC_INSERTED 1
|
||||
#define SD_MMC_REMOVING 2
|
||||
|
||||
//---- CONTROL FUNCTIONS ----
|
||||
//!
|
||||
//! @brief This function initializes the hw/sw resources required to drive the SD_MMC_SPI.
|
||||
//!/
|
||||
extern void sd_mmc_spi_mem_init(void);
|
||||
|
||||
//!
|
||||
//! @brief This function tests the state of the SD_MMC memory and sends it to the Host.
|
||||
//! For a PC, this device is seen as a removable media
|
||||
//! Before indicating any modification of the status of the media (GOOD->NO_PRESENT or vice-versa),
|
||||
//! the function must return the BUSY data to make the PC accepting the change
|
||||
//!
|
||||
//! @return Ctrl_status
|
||||
//! Media is ready -> CTRL_GOOD
|
||||
//! Media not present -> CTRL_NO_PRESENT
|
||||
//! Media has changed -> CTRL_BUSY
|
||||
//!/
|
||||
extern Ctrl_status sd_mmc_spi_test_unit_ready(void);
|
||||
|
||||
//!
|
||||
//! @brief This function gives the address of the last valid sector.
|
||||
//!
|
||||
//! @param *nb_sector number of sector (sector = 512B). OUT
|
||||
//!
|
||||
//! @return Ctrl_status
|
||||
//! Media ready -> CTRL_GOOD
|
||||
//! Media not present -> CTRL_NO_PRESENT
|
||||
//!/
|
||||
extern Ctrl_status sd_mmc_spi_read_capacity(uint32_t *nb_sector);
|
||||
|
||||
/*! \brief Unload/Load the SD/MMC card selected
|
||||
*
|
||||
* The START STOP UNIT SCSI optional command allows an application client to
|
||||
* eject the removable medium on a LUN.
|
||||
*
|
||||
* \param unload \c true to unload the medium, \c false to load the medium.
|
||||
*
|
||||
* \return \c true if unload/load done success.
|
||||
*/
|
||||
extern bool sd_mmc_spi_unload(bool unload);
|
||||
|
||||
//!
|
||||
//! @brief This function returns the write protected status of the memory.
|
||||
//!
|
||||
//! Only used by memory removal with a HARDWARE SPECIFIC write protected detection
|
||||
//! ! The user must unplug the memory to change this write protected status,
|
||||
//! which cannot be for a SD_MMC.
|
||||
//!
|
||||
//! @return false -> the memory is not write-protected (always)
|
||||
//!/
|
||||
extern bool sd_mmc_spi_wr_protect(void);
|
||||
|
||||
//!
|
||||
//! @brief This function tells if the memory has been removed or not.
|
||||
//!
|
||||
//! @return false -> The memory isn't removed
|
||||
//!
|
||||
extern bool sd_mmc_spi_removal(void);
|
||||
|
||||
//---- ACCESS DATA FUNCTIONS ----
|
||||
|
||||
#if ACCESS_USB == true
|
||||
// Standard functions for open in read/write mode the device
|
||||
|
||||
//!
|
||||
//! @brief This function performs a read operation of n sectors from a given address on.
|
||||
//! (sector = 512B)
|
||||
//!
|
||||
//! DATA FLOW is: SD_MMC => USB
|
||||
//!
|
||||
//! @param addr Sector address to start the read from
|
||||
//! @param nb_sector Number of sectors to transfer
|
||||
//!
|
||||
//! @return Ctrl_status
|
||||
//! It is ready -> CTRL_GOOD
|
||||
//! A error occur -> CTRL_FAIL
|
||||
//!
|
||||
extern Ctrl_status sd_mmc_spi_usb_read_10(uint32_t addr, uint16_t nb_sector);
|
||||
|
||||
//! This function initializes the SD/MMC memory for a write operation
|
||||
//!
|
||||
//! DATA FLOW is: USB => SD_MMC
|
||||
//!
|
||||
//! (sector = 512B)
|
||||
//! @param addr Sector address to start write
|
||||
//! @param nb_sector Number of sectors to transfer
|
||||
//!
|
||||
//! @return Ctrl_status
|
||||
//! It is ready -> CTRL_GOOD
|
||||
//! An error occurs -> CTRL_FAIL
|
||||
//!
|
||||
extern Ctrl_status sd_mmc_spi_usb_write_10(uint32_t addr, uint16_t nb_sector);
|
||||
|
||||
#endif // #if ACCESS_USB == true
|
||||
|
||||
/**
|
||||
* \}
|
||||
*/
|
||||
|
||||
#endif // _SD_MMC_SPI_MEM_H_
|
|
@ -0,0 +1,330 @@
|
|||
/**
|
||||
* \file
|
||||
*
|
||||
* \brief SCSI Primary Commands
|
||||
*
|
||||
* This file contains definitions of some of the commands found in the
|
||||
* SPC-2 standard.
|
||||
*
|
||||
* Copyright (c) 2009-2015 Atmel Corporation. All rights reserved.
|
||||
*
|
||||
* \asf_license_start
|
||||
*
|
||||
* \page License
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of Atmel may not be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* 4. This software may only be redistributed and used in connection with an
|
||||
* Atmel microcontroller product.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* \asf_license_stop
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Support and FAQ: visit <a href="https://www.atmel.com/design-support/">Atmel Support</a>
|
||||
*/
|
||||
#ifndef _SPC_PROTOCOL_H_
|
||||
#define _SPC_PROTOCOL_H_
|
||||
|
||||
/**
|
||||
* \ingroup usb_msc_protocol
|
||||
* \defgroup usb_spc_protocol SCSI Primary Commands protocol definitions
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
//! \name SCSI commands defined by SPC-2
|
||||
//@{
|
||||
#define SPC_TEST_UNIT_READY 0x00
|
||||
#define SPC_REQUEST_SENSE 0x03
|
||||
#define SPC_INQUIRY 0x12
|
||||
#define SPC_MODE_SELECT6 0x15
|
||||
#define SPC_MODE_SENSE6 0x1A
|
||||
#define SPC_SEND_DIAGNOSTIC 0x1D
|
||||
#define SPC_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1E
|
||||
#define SPC_MODE_SENSE10 0x5A
|
||||
#define SPC_REPORT_LUNS 0xA0
|
||||
//@}
|
||||
|
||||
//! \brief May be set in byte 0 of the INQUIRY CDB
|
||||
//@{
|
||||
//! Enable Vital Product Data
|
||||
#define SCSI_INQ_REQ_EVPD 0x01
|
||||
//! Command Support Data specified by the PAGE OR OPERATION CODE field
|
||||
#define SCSI_INQ_REQ_CMDT 0x02
|
||||
//@}
|
||||
|
||||
COMPILER_PACK_SET(1)
|
||||
|
||||
/**
|
||||
* \brief SCSI Standard Inquiry data structure
|
||||
*/
|
||||
struct scsi_inquiry_data {
|
||||
uint8_t pq_pdt; //!< Peripheral Qual / Peripheral Dev Type
|
||||
#define SCSI_INQ_PQ_CONNECTED 0x00 //!< Peripheral connected
|
||||
#define SCSI_INQ_PQ_NOT_CONN 0x20 //!< Peripheral not connected
|
||||
#define SCSI_INQ_PQ_NOT_SUPP 0x60 //!< Peripheral not supported
|
||||
#define SCSI_INQ_DT_DIR_ACCESS 0x00 //!< Direct Access (SBC)
|
||||
#define SCSI_INQ_DT_SEQ_ACCESS 0x01 //!< Sequential Access
|
||||
#define SCSI_INQ_DT_PRINTER 0x02 //!< Printer
|
||||
#define SCSI_INQ_DT_PROCESSOR 0x03 //!< Processor device
|
||||
#define SCSI_INQ_DT_WRITE_ONCE 0x04 //!< Write-once device
|
||||
#define SCSI_INQ_DT_CD_DVD 0x05 //!< CD/DVD device
|
||||
#define SCSI_INQ_DT_OPTICAL 0x07 //!< Optical Memory
|
||||
#define SCSI_INQ_DT_MC 0x08 //!< Medium Changer
|
||||
#define SCSI_INQ_DT_ARRAY 0x0C //!< Storage Array Controller
|
||||
#define SCSI_INQ_DT_ENCLOSURE 0x0D //!< Enclosure Services
|
||||
#define SCSI_INQ_DT_RBC 0x0E //!< Simplified Direct Access
|
||||
#define SCSI_INQ_DT_OCRW 0x0F //!< Optical card reader/writer
|
||||
#define SCSI_INQ_DT_BCC 0x10 //!< Bridge Controller Commands
|
||||
#define SCSI_INQ_DT_OSD 0x11 //!< Object-based Storage
|
||||
#define SCSI_INQ_DT_NONE 0x1F //!< No Peripheral
|
||||
uint8_t flags1; //!< Flags (byte 1)
|
||||
#define SCSI_INQ_RMB 0x80 //!< Removable Medium
|
||||
uint8_t version; //!< Version
|
||||
#define SCSI_INQ_VER_NONE 0x00 //!< No standards conformance
|
||||
#define SCSI_INQ_VER_SPC 0x03 //!< SCSI Primary Commands (link to SBC)
|
||||
#define SCSI_INQ_VER_SPC2 0x04 //!< SCSI Primary Commands - 2 (link to SBC-2)
|
||||
#define SCSI_INQ_VER_SPC3 0x05 //!< SCSI Primary Commands - 3 (link to SBC-2)
|
||||
#define SCSI_INQ_VER_SPC4 0x06 //!< SCSI Primary Commands - 4 (link to SBC-3)
|
||||
uint8_t flags3; //!< Flags (byte 3)
|
||||
#define SCSI_INQ_NORMACA 0x20 //!< Normal ACA Supported
|
||||
#define SCSI_INQ_HISUP 0x10 //!< Hierarchal LUN addressing
|
||||
#define SCSI_INQ_RSP_SPC2 0x02 //!< SPC-2 / SPC-3 response format
|
||||
uint8_t addl_len; //!< Additional Length (n-4)
|
||||
#define SCSI_INQ_ADDL_LEN(tot) ((tot)-5) //!< Total length is \a tot
|
||||
uint8_t flags5; //!< Flags (byte 5)
|
||||
#define SCSI_INQ_SCCS 0x80
|
||||
uint8_t flags6; //!< Flags (byte 6)
|
||||
#define SCSI_INQ_BQUE 0x80
|
||||
#define SCSI_INQ_ENCSERV 0x40
|
||||
#define SCSI_INQ_MULTIP 0x10
|
||||
#define SCSI_INQ_MCHGR 0x08
|
||||
#define SCSI_INQ_ADDR16 0x01
|
||||
uint8_t flags7; //!< Flags (byte 7)
|
||||
#define SCSI_INQ_WBUS16 0x20
|
||||
#define SCSI_INQ_SYNC 0x10
|
||||
#define SCSI_INQ_LINKED 0x08
|
||||
#define SCSI_INQ_CMDQUE 0x02
|
||||
uint8_t vendor_id[8]; //!< T10 Vendor Identification
|
||||
uint8_t product_id[16]; //!< Product Identification
|
||||
uint8_t product_rev[4]; //!< Product Revision Level
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief SCSI Standard Request sense data structure
|
||||
*/
|
||||
struct scsi_request_sense_data {
|
||||
/* 1st byte: REQUEST SENSE response flags*/
|
||||
uint8_t valid_reponse_code;
|
||||
#define SCSI_SENSE_VALID 0x80 //!< Indicates the INFORMATION field contains valid information
|
||||
#define SCSI_SENSE_RESPONSE_CODE_MASK 0x7F
|
||||
#define SCSI_SENSE_CURRENT 0x70 //!< Response code 70h (current errors)
|
||||
#define SCSI_SENSE_DEFERRED 0x71
|
||||
|
||||
/* 2nd byte */
|
||||
uint8_t obsolete;
|
||||
|
||||
/* 3rd byte */
|
||||
uint8_t sense_flag_key;
|
||||
#define SCSI_SENSE_FILEMARK 0x80 //!< Indicates that the current command has read a filemark or setmark.
|
||||
#define SCSI_SENSE_EOM 0x40 //!< Indicates that an end-of-medium condition exists.
|
||||
#define SCSI_SENSE_ILI 0x20 //!< Indicates that the requested logical block length did not match the logical block length of the data on the medium.
|
||||
#define SCSI_SENSE_RESERVED 0x10 //!< Reserved
|
||||
#define SCSI_SENSE_KEY(x) (x&0x0F) //!< Sense Key
|
||||
|
||||
/* 4th to 7th bytes - INFORMATION field */
|
||||
uint8_t information[4];
|
||||
|
||||
/* 8th byte - ADDITIONAL SENSE LENGTH field */
|
||||
uint8_t AddSenseLen;
|
||||
#define SCSI_SENSE_ADDL_LEN(total_len) ((total_len) - 8)
|
||||
|
||||
/* 9th to 12th byte - COMMAND-SPECIFIC INFORMATION field */
|
||||
uint8_t CmdSpecINFO[4];
|
||||
|
||||
/* 13th byte - ADDITIONAL SENSE CODE field */
|
||||
uint8_t AddSenseCode;
|
||||
|
||||
/* 14th byte - ADDITIONAL SENSE CODE QUALIFIER field */
|
||||
uint8_t AddSnsCodeQlfr;
|
||||
|
||||
/* 15th byte - FIELD REPLACEABLE UNIT CODE field */
|
||||
uint8_t FldReplUnitCode;
|
||||
|
||||
/* 16th byte */
|
||||
uint8_t SenseKeySpec[3];
|
||||
#define SCSI_SENSE_SKSV 0x80 //!< Indicates the SENSE-KEY SPECIFIC field contains valid information
|
||||
};
|
||||
|
||||
COMPILER_PACK_RESET()
|
||||
|
||||
/* Vital Product Data page codes */
|
||||
enum scsi_vpd_page_code {
|
||||
SCSI_VPD_SUPPORTED_PAGES = 0x00,
|
||||
SCSI_VPD_UNIT_SERIAL_NUMBER = 0x80,
|
||||
SCSI_VPD_DEVICE_IDENTIFICATION = 0x83,
|
||||
};
|
||||
#define SCSI_VPD_HEADER_SIZE 4
|
||||
|
||||
/* Constants associated with the Device Identification VPD page */
|
||||
#define SCSI_VPD_ID_HEADER_SIZE 4
|
||||
|
||||
#define SCSI_VPD_CODE_SET_BINARY 1
|
||||
#define SCSI_VPD_CODE_SET_ASCII 2
|
||||
#define SCSI_VPD_CODE_SET_UTF8 3
|
||||
|
||||
#define SCSI_VPD_ID_TYPE_T10 1
|
||||
|
||||
/* Sense keys */
|
||||
enum scsi_sense_key {
|
||||
SCSI_SK_NO_SENSE = 0x0,
|
||||
SCSI_SK_RECOVERED_ERROR = 0x1,
|
||||
SCSI_SK_NOT_READY = 0x2,
|
||||
SCSI_SK_MEDIUM_ERROR = 0x3,
|
||||
SCSI_SK_HARDWARE_ERROR = 0x4,
|
||||
SCSI_SK_ILLEGAL_REQUEST = 0x5,
|
||||
SCSI_SK_UNIT_ATTENTION = 0x6,
|
||||
SCSI_SK_DATA_PROTECT = 0x7,
|
||||
SCSI_SK_BLANK_CHECK = 0x8,
|
||||
SCSI_SK_VENDOR_SPECIFIC = 0x9,
|
||||
SCSI_SK_COPY_ABORTED = 0xA,
|
||||
SCSI_SK_ABORTED_COMMAND = 0xB,
|
||||
SCSI_SK_VOLUME_OVERFLOW = 0xD,
|
||||
SCSI_SK_MISCOMPARE = 0xE,
|
||||
};
|
||||
|
||||
/* Additional Sense Code / Additional Sense Code Qualifier pairs */
|
||||
enum scsi_asc_ascq {
|
||||
SCSI_ASC_NO_ADDITIONAL_SENSE_INFO = 0x0000,
|
||||
SCSI_ASC_LU_NOT_READY_REBUILD_IN_PROGRESS = 0x0405,
|
||||
SCSI_ASC_WRITE_ERROR = 0x0C00,
|
||||
SCSI_ASC_UNRECOVERED_READ_ERROR = 0x1100,
|
||||
SCSI_ASC_INVALID_COMMAND_OPERATION_CODE = 0x2000,
|
||||
SCSI_ASC_INVALID_FIELD_IN_CDB = 0x2400,
|
||||
SCSI_ASC_WRITE_PROTECTED = 0x2700,
|
||||
SCSI_ASC_NOT_READY_TO_READY_CHANGE = 0x2800,
|
||||
SCSI_ASC_MEDIUM_NOT_PRESENT = 0x3A00,
|
||||
SCSI_ASC_INTERNAL_TARGET_FAILURE = 0x4400,
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief SPC-2 Mode parameter
|
||||
* This subclause describes the block descriptors and the pages
|
||||
* used with MODE SELECT and MODE SENSE commands
|
||||
* that are applicable to all SCSI devices.
|
||||
*/
|
||||
enum scsi_spc_mode {
|
||||
SCSI_MS_MODE_VENDOR_SPEC = 0x00,
|
||||
SCSI_MS_MODE_INFEXP = 0x1C, // Informational exceptions control page
|
||||
SCSI_MS_MODE_ALL = 0x3F,
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief SPC-2 Informational exceptions control page
|
||||
* See chapter 8.3.8
|
||||
*/
|
||||
struct spc_control_page_info_execpt {
|
||||
uint8_t page_code;
|
||||
uint8_t page_length;
|
||||
#define SPC_MP_INFEXP_PAGE_LENGTH 0x0A
|
||||
uint8_t flags1;
|
||||
#define SPC_MP_INFEXP_PERF (1<<7) //!< Initiator Control
|
||||
#define SPC_MP_INFEXP_EBF (1<<5) //!< Caching Analysis Permitted
|
||||
#define SPC_MP_INFEXP_EWASC (1<<4) //!< Discontinuity
|
||||
#define SPC_MP_INFEXP_DEXCPT (1<<3) //!< Size enable
|
||||
#define SPC_MP_INFEXP_TEST (1<<2) //!< Writeback Cache Enable
|
||||
#define SPC_MP_INFEXP_LOGERR (1<<0) //!< Log errors bit
|
||||
uint8_t mrie;
|
||||
#define SPC_MP_INFEXP_MRIE_NO_REPORT 0x00
|
||||
#define SPC_MP_INFEXP_MRIE_ASYNC_EVENT 0x01
|
||||
#define SPC_MP_INFEXP_MRIE_GEN_UNIT 0x02
|
||||
#define SPC_MP_INFEXP_MRIE_COND_RECOV_ERROR 0x03
|
||||
#define SPC_MP_INFEXP_MRIE_UNCOND_RECOV_ERROR 0x04
|
||||
#define SPC_MP_INFEXP_MRIE_NO_SENSE 0x05
|
||||
#define SPC_MP_INFEXP_MRIE_ONLY_REPORT 0x06
|
||||
be32_t interval_timer;
|
||||
be32_t report_count;
|
||||
};
|
||||
|
||||
enum scsi_spc_mode_sense_pc {
|
||||
SCSI_MS_SENSE_PC_CURRENT = 0,
|
||||
SCSI_MS_SENSE_PC_CHANGEABLE = 1,
|
||||
SCSI_MS_SENSE_PC_DEFAULT = 2,
|
||||
SCSI_MS_SENSE_PC_SAVED = 3,
|
||||
};
|
||||
|
||||
static inline bool scsi_mode_sense_dbd_is_set(const uint8_t * cdb) {
|
||||
return (cdb[1] >> 3) & 1;
|
||||
}
|
||||
|
||||
static inline uint8_t scsi_mode_sense_get_page_code(const uint8_t * cdb) {
|
||||
return cdb[2] & 0x3F;
|
||||
}
|
||||
|
||||
static inline uint8_t scsi_mode_sense_get_pc(const uint8_t * cdb) {
|
||||
return cdb[2] >> 6;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief SCSI Mode Parameter Header used by MODE SELECT(6) and MODE
|
||||
* SENSE(6)
|
||||
*/
|
||||
struct scsi_mode_param_header6 {
|
||||
uint8_t mode_data_length; //!< Number of bytes after this
|
||||
uint8_t medium_type; //!< Medium Type
|
||||
uint8_t device_specific_parameter; //!< Defined by command set
|
||||
uint8_t block_descriptor_length; //!< Length of block descriptors
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief SCSI Mode Parameter Header used by MODE SELECT(10) and MODE
|
||||
* SENSE(10)
|
||||
*/
|
||||
struct scsi_mode_param_header10 {
|
||||
be16_t mode_data_length; //!< Number of bytes after this
|
||||
uint8_t medium_type; //!< Medium Type
|
||||
uint8_t device_specific_parameter; //!< Defined by command set
|
||||
uint8_t flags4; //!< LONGLBA in bit 0
|
||||
uint8_t reserved;
|
||||
be16_t block_descriptor_length; //!< Length of block descriptors
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief SCSI Page_0 Mode Page header (SPF not set)
|
||||
*/
|
||||
struct scsi_mode_page_0_header {
|
||||
uint8_t page_code;
|
||||
#define SCSI_PAGE_CODE_PS (1 << 7) //!< Parameters Saveable
|
||||
#define SCSI_PAGE_CODE_SPF (1 << 6) //!< SubPage Format
|
||||
uint8_t page_length; //!< Number of bytes after this
|
||||
#define SCSI_MS_PAGE_LEN(total) ((total) - 2)
|
||||
};
|
||||
|
||||
//@}
|
||||
|
||||
#endif // SPC_PROTOCOL_H_
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue