This commit is contained in:
dfriedrich 2019-03-21 10:43:51 -03:00
commit 60ece440f6
553 changed files with 361616 additions and 0 deletions

20
.gitattributes vendored Normal file
View File

@ -0,0 +1,20 @@
# 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

46
.github/code_of_conduct.md vendored Normal file
View File

@ -0,0 +1,46 @@
# 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.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at [marlinfirmware@github.com](mailto:marlinfirmware@github.com). All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## 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/

144
.github/contributing.md vendored Normal file
View File

@ -0,0 +1,144 @@
# 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 to [marlinfirmware@github.com](mailto:marlinfirmware@github.com).
## 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 RepRap forum](http://forums.reprap.org/list.php?415)
* [MarlinFirmware on Facebook](https://www.facebook.com/groups/1049718498464482/)
If chat is more your speed, you can join the MarlinFirmware Slack team:
* Join the Marlin Slack Team
* To obtain group access, please [send a request](http://www.thinkyhead.com/contact/9) to @thinkyhead.
* Even though Slack is a chat service, sometimes it takes several hours 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. 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.md), the information it asks for helps us resolve issues faster.
> **Note:** Regressions can happen. If you find a **Closed** issue that seems like your issue, go ahead and open a new issue and include a link to the original issue in the body of your new one. All you need to create a link is the issue number, preceded by #. For example, #8888.
#### How Do I Submit A (Good) Bug Report?
Bugs are tracked as [GitHub issues](https://guides.github.com/features/issues/). Use the New Issue button to create an issue and provide the following information by filling in [the template](issue_template.md).
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](#before-submitting-a-suggestion) as you might find out that you don't need to create one. When you are creating an enhancement suggestion, please [include as many details as possible](#how-do-i-submit-a-good-enhancement-suggestion). Fill in [the template](issue_template.md), including the steps that you imagine you would take if the feature you're requesting existed.
#### Before Submitting a Feature Request
* **Check the [Marlin website](http://marlinfw.org/)** for tips — you might discover that the feature is already included. Most importantly, check if you're using [the latest version of Marlin](https://github.com/MarlinFirmware/Marlin/releases) and if you can get the desired behavior by changing [Marlin's config settings](http://marlinfw.org/docs/configuration/configuration.html).
* **Perform a [cursory search](https://github.com/MarlinFirmware/Marlin/issues?q=is%3Aissue)** to see if the enhancement has already been suggested. If it has, add a comment to the existing issue instead of opening a new one.
#### How Do I Submit A (Good) Feature Request?
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-1.1.x` and/or `bugfix-2.0.x`) and never to release branches (e.g., `1.1.x`). If this is your first Pull Request, please read our [Guide to Pull Requests](http://marlinfw.org/docs/development/getting_started_pull_requests.html) and Github's [Pull Request](https://help.github.com/articles/creating-a-pull-request/) documentation.
* Fill in [the required template](pull_request_template.md).
* 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](http://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](http://marlinfw.org/docs/development/coding_standards.html) posted on our website. Failure to follow these guidelines will delay evaluation and acceptance of Pull Requests.
### Documentation
* Guidelines for documentation are still under development. In-general, be clear, concise, and to-the-point.

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

@ -0,0 +1,31 @@
<!--
Have you read Marlin's Code of Conduct? By filing an Issue, you are expected to comply with it, including treating everyone with respect: https://github.com/MarlinFirmware/Marlin/blob/1.1.x/.github/code_of_conduct.md
Do you want to ask a question? Are you looking for support? Please don't post here. Instead please use the Marlin Firmware forum at http://forums.reprap.org/list.php?415 or the Marlin Facebook Group https://www.facebook.com/groups/1049718498464482/.
Before filing an issue be sure to test the 1.1 and/or 2.0 "bugfix" branches to see whether the issue is already addressed.
-->
### Description
<!-- Description of the bug or requested feature -->
### Steps to Reproduce
<!-- If this is a Bug Report, please describe the steps needed to reproduce the issue -->
1. [First Step]
2. [Second Step]
3. [and so on...]
**Expected behavior:** [What you expect to happen]
**Actual behavior:** [What actually happens]
#### Additional Information
* Include a ZIP file containing your `Configuration.h` and `Configuration_adv.h` files.
* Provide pictures or links to videos that clearly demonstrate the issue.
* See [How Can I Contribute](https://github.com/MarlinFirmware/Marlin/blob/1.1.x/.github/contributing.md#how-can-i-contribute) for additional guidelines.

19
.github/pull_request_template.md vendored Normal file
View File

@ -0,0 +1,19 @@
### Requirements
* Filling out this template is required. Pull Requests without a clear description may be closed at the maintainers' discretion.
### Description
<!--
We must be able to understand your proposed change from this description. If we can't understand what the code will do from this description, the Pull Request may be closed at the maintainers' discretion. Keep in mind that the maintainer reviewing this PR may not be familiar with or have worked with the code recently, so please walk us through the concepts.
-->
### Benefits
<!-- What does this fix or improve? -->
### Related Issues
<!-- Whether this fixes a bug or fulfills a feature request, please list any related Issues here. -->

149
.gitignore vendored Normal file
View File

@ -0,0 +1,149 @@
#
# Marlin 3D Printer Firmware
# Copyright (C) 2017 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
#
# Based on Sprinter and grbl.
# Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# Our automatic versioning scheme generates the following file
# NEVER put it in the repository
_Version.h
#
# OS
#
applet/
*.DS_Store
#
# Misc
#
*~
*.orig
*.rej
*.bak
*.idea
*.s
*.i
*.ii
*.swp
tags
#
# C++
#
# Compiled 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
#
# 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
lib/readme.txt
#Visual Studio
*.sln
*.vcxproj
*.vcxproj.user
*.vcxproj.filters
Release/
Debug/
__vm/
.vs/
vc-fileutils.settings
#Visual Studio Code
.vscode
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/*.db
#cmake
CMakeLists.txt
Marlin/CMakeLists.txt
CMakeListsPrivate.txt
#CLion
cmake-build-*

389
.travis.yml Normal file
View File

@ -0,0 +1,389 @@
dist: trusty
sudo: true
#
language: c
#
notifications:
email: false
#
before_install:
#
# Fetch the tag information for the current branch
- git fetch origin --tags
#
# Publish the buildroot script folder
- chmod +x ${TRAVIS_BUILD_DIR}/buildroot/bin/*
- export PATH=${TRAVIS_BUILD_DIR}/buildroot/bin/:${PATH}
#
# Start fb X server
- "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_1.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :1 -ac -screen 0 1280x1024x16"
- sleep 3
- export DISPLAY=:1.0
#
install:
#
# Install arduino 1.8.5
- wget http://downloads-02.arduino.cc/arduino-1.8.5-linux64.tar.xz
- tar xf arduino-1.8.5-linux64.tar.xz
- sudo mv arduino-1.8.5 /usr/local/share/arduino
- ln -s /usr/local/share/arduino/arduino ${TRAVIS_BUILD_DIR}/buildroot/bin/arduino
#
# Install: LiquidCrystal_I2C library
- git clone https://github.com/kiyoshigawa/LiquidCrystal_I2C.git
- mv LiquidCrystal_I2C/LiquidCrystal_I2C /usr/local/share/arduino/libraries/LiquidCrystal_I2C
#
# Install: LiquidTWI2 library
- git clone https://github.com/lincomatic/LiquidTWI2.git
- sudo mv LiquidTWI2 /usr/local/share/arduino/libraries/LiquidTWI2
#
# Install: Monochrome Graphics Library for LCDs and OLEDs
- git clone https://github.com/olikraus/U8glib_Arduino.git
- sudo mv U8glib_Arduino /usr/local/share/arduino/libraries/U8glib
#
# Install: L6470 Stepper Motor Driver library
# - git clone https://github.com/ameyer/Arduino-L6470.git
# - sudo mv Arduino-L6470/L6470 /usr/local/share/arduino/libraries/L6470
#
# Install: TMC26X Stepper Motor Controller library
# - git clone https://github.com/trinamic/TMC26XStepper.git
# - sudo mv TMC26XStepper /usr/local/share/arduino/libraries/TMC26XStepper
#
# Install: TMC2130 Stepper Motor Controller library
- git clone https://github.com/teemuatlut/TMC2130Stepper.git
- sudo mv TMC2130Stepper /usr/local/share/arduino/libraries/TMC2130Stepper
#
# Install: TMC2208 Stepper Motor Controller library
- git clone https://github.com/teemuatlut/TMC2208Stepper.git
- sudo mv TMC2208Stepper /usr/local/share/arduino/libraries/TMC2208Stepper
#
# Install: Adafruit Neopixel library
- git clone https://github.com/adafruit/Adafruit_NeoPixel.git
- sudo mv Adafruit_NeoPixel /usr/local/share/arduino/libraries/Adafruit_NeoPixel
#
before_script:
#
# Change current working directory to the build dir
- cd ${TRAVIS_BUILD_DIR}
#
# Generate custom version include
- generate_version_header_for_marlin ${TRAVIS_BUILD_DIR}/Marlin
- cat ${TRAVIS_BUILD_DIR}/Marlin/_Version.h
#
script:
#
# Backup Configuration.h, Configuration_adv.h, and pins_RAMPS.h
#
- cp Marlin/Configuration.h Marlin/Configuration.h.backup
- cp Marlin/Configuration_adv.h Marlin/Configuration_adv.h.backup
- cp Marlin/pins_RAMPS.h Marlin/pins_RAMPS.h.backup
#
# Build with the default configurations
#
- build_marlin
#
# Test 2 extruders (one MAX6675) and heated bed on basic RAMPS 1.4
# Test a "Fix Mounted" Probe with Safe Homing, some arc options,
# linear bed leveling, M48, leveling debug, and firmware retraction.
#
- opt_set MOTHERBOARD BOARD_RAMPS_14_EEB
- opt_set EXTRUDERS 2
- opt_set TEMP_SENSOR_0 -2
- opt_set TEMP_SENSOR_1 1
- opt_set TEMP_SENSOR_BED 1
- opt_set POWER_SUPPLY 1
- opt_enable PIDTEMPBED FIX_MOUNTED_PROBE Z_SAFE_HOMING
- opt_enable REPRAP_DISCOUNT_SMART_CONTROLLER SDSUPPORT EEPROM_SETTINGS PINS_DEBUGGING
- opt_enable BLINKM PCA9632 RGB_LED NEOPIXEL_LED AUTO_POWER_CONTROL NOZZLE_PARK_FEATURE FILAMENT_RUNOUT_SENSOR
- opt_enable AUTO_BED_LEVELING_LINEAR Z_MIN_PROBE_REPEATABILITY_TEST DEBUG_LEVELING_FEATURE SKEW_CORRECTION SKEW_CORRECTION_FOR_Z SKEW_CORRECTION_GCODE
- opt_enable_adv ARC_P_CIRCLES ADVANCED_PAUSE_FEATURE CNC_WORKSPACE_PLANES CNC_COORDINATE_SYSTEMS POWER_LOSS_RECOVERY POWER_LOSS_PIN POWER_LOSS_STATE
- opt_enable_adv FWRETRACT MAX7219_DEBUG LED_CONTROL_MENU CASE_LIGHT_ENABLE CASE_LIGHT_USE_NEOPIXEL CODEPENDENT_XY_HOMING
- opt_set GRID_MAX_POINTS_X 16
- opt_set_adv FANMUX0_PIN 53
- build_marlin
#
# Test a probeless build of AUTO_BED_LEVELING_UBL, with lots of extruders
#
- restore_configs
- opt_set MOTHERBOARD BOARD_AZTEEG_X3_PRO
- opt_set EXTRUDERS 5
- opt_set TEMP_SENSOR_1 1
- opt_set TEMP_SENSOR_2 5
- opt_set TEMP_SENSOR_3 20
- opt_set TEMP_SENSOR_4 999
- opt_set TEMP_SENSOR_BED 1
- opt_enable AUTO_BED_LEVELING_UBL RESTORE_LEVELING_AFTER_G28 DEBUG_LEVELING_FEATURE G26_MESH_EDITING ENABLE_LEVELING_FADE_HEIGHT SKEW_CORRECTION
- opt_enable EEPROM_SETTINGS EEPROM_CHITCHAT REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER
- opt_enable_adv CUSTOM_USER_MENUS I2C_POSITION_ENCODERS BABYSTEPPING BABYSTEP_XY LIN_ADVANCE NANODLP_Z_SYNC QUICK_HOME JUNCTION_DEVIATION MAX7219_DEBUG
- opt_set_adv MAX7219_ROTATE 270
- build_marlin
#
# Add a Sled Z Probe, use UBL Cartesian moves, use Japanese language
#
- opt_enable Z_PROBE_SLED SKEW_CORRECTION SKEW_CORRECTION_FOR_Z SKEW_CORRECTION_GCODE S_CURVE_ACCELERATION
- opt_set LCD_LANGUAGE kana_utf8
- opt_disable SEGMENT_LEVELED_MOVES
- opt_enable_adv BABYSTEP_ZPROBE_OFFSET DOUBLECLICK_FOR_Z_BABYSTEPPING
- build_marlin
#
# Test a Servo Probe
# ...with AUTO_BED_LEVELING_3POINT, DEBUG_LEVELING_FEATURE, EEPROM_SETTINGS, EEPROM_CHITCHAT, EXTENDED_CAPABILITIES_REPORT, and AUTO_REPORT_TEMPERATURES
#
- restore_configs
- opt_enable NUM_SERVOS Z_PROBE_SERVO_NR Z_SERVO_ANGLES DEACTIVATE_SERVOS_AFTER_MOVE
- opt_set NUM_SERVOS 1
- opt_enable AUTO_BED_LEVELING_3POINT DEBUG_LEVELING_FEATURE EEPROM_SETTINGS EEPROM_CHITCHAT
- opt_enable_adv NO_VOLUMETRICS EXTENDED_CAPABILITIES_REPORT AUTO_REPORT_TEMPERATURES AUTOTEMP G38_PROBE_TARGET
- build_marlin
#
# Test MESH_BED_LEVELING feature, with LCD
#
- restore_configs
- opt_enable MESH_BED_LEVELING G26_MESH_EDITING MESH_G28_REST_ORIGIN LCD_BED_LEVELING ULTIMAKERCONTROLLER
- build_marlin
#
# Test MINIRAMBO for PWM_MOTOR_CURRENT
# PROBE_MANUALLY feature, with LCD support,
# ULTIMAKERCONTROLLER, FILAMENT_LCD_DISPLAY, FILAMENT_WIDTH_SENSOR,
# PRINTCOUNTER, NOZZLE_PARK_FEATURE, NOZZLE_CLEAN_FEATURE, PCA9632,
# Z_DUAL_ENDSTOPS, BEZIER_CURVE_SUPPORT, EXPERIMENTAL_I2CBUS,
# ADVANCED_PAUSE_FEATURE, ADVANCED_PAUSE_CONTINUOUS_PURGE, PARK_HEAD_ON_PAUSE, LCD_INFO_MENU, M114_DETAIL
# EEPROM_SETTINGS, EEPROM_CHITCHAT, M100_FREE_MEMORY_WATCHER,
# INCH_MODE_SUPPORT, TEMPERATURE_UNITS_SUPPORT
#
- restore_configs
- opt_set MOTHERBOARD BOARD_MINIRAMBO
- opt_enable PROBE_MANUALLY AUTO_BED_LEVELING_BILINEAR G26_MESH_EDITING LCD_BED_LEVELING ULTIMAKERCONTROLLER
- opt_enable EEPROM_SETTINGS EEPROM_CHITCHAT M100_FREE_MEMORY_WATCHER M100_FREE_MEMORY_DUMPER M100_FREE_MEMORY_CORRUPTOR INCH_MODE_SUPPORT TEMPERATURE_UNITS_SUPPORT
- opt_enable ULTIMAKERCONTROLLER SDSUPPORT
- opt_enable PRINTCOUNTER NOZZLE_PARK_FEATURE NOZZLE_CLEAN_FEATURE PCA9632
- opt_enable_adv BEZIER_CURVE_SUPPORT EXPERIMENTAL_I2CBUS
- opt_enable_adv ADVANCED_PAUSE_FEATURE ADVANCED_PAUSE_CONTINUOUS_PURGE FILAMENT_LOAD_UNLOAD_GCODES PARK_HEAD_ON_PAUSE LCD_INFO_MENU M114_DETAIL
- opt_set_adv PWM_MOTOR_CURRENT {1300,1300,1250}
- opt_set_adv I2C_SLAVE_ADDRESS 63
- build_marlin
#
# Mixing Extruder with 5 steppers, Cyrillic
#
- restore_configs
- opt_set MOTHERBOARD BOARD_AZTEEG_X3_PRO
- opt_enable MIXING_EXTRUDER CR10_STOCKDISPLAY
- opt_set MIXING_STEPPERS 5
- opt_set LCD_LANGUAGE ru
- build_marlin
#
# Test DUAL_X_CARRIAGE
#
- restore_configs
- opt_set MOTHERBOARD BOARD_RUMBA
- opt_set EXTRUDERS 2
- opt_set TEMP_SENSOR_1 1
- opt_enable USE_XMAX_PLUG
- opt_enable_adv DUAL_X_CARRIAGE
- build_marlin
#
# Test SPEAKER with BOARD_BQ_ZUM_MEGA_3D and BQ_LCD_SMART_CONTROLLER
#
#- restore_configs
#- opt_set MOTHERBOARD BOARD_BQ_ZUM_MEGA_3D
#- opt_set LCD_FEEDBACK_FREQUENCY_DURATION_MS 10
#- opt_set LCD_FEEDBACK_FREQUENCY_HZ 100
#- opt_enable BQ_LCD_SMART_CONTROLLER SPEAKER
#
# Test SWITCHING_EXTRUDER
#
- restore_configs
- opt_set MOTHERBOARD BOARD_RUMBA
- opt_set EXTRUDERS 2
- opt_enable NUM_SERVOS
- opt_set NUM_SERVOS 1
- opt_enable SWITCHING_EXTRUDER ULTIMAKERCONTROLLER
- build_marlin
#
# Enable COREXY
#
#- restore_configs
#- opt_enable COREXY
#- build_marlin
#
# Test many less common options
#
- restore_configs
- opt_enable COREYX
- opt_set_adv FAN_MIN_PWM 50
- opt_set_adv FAN_KICKSTART_TIME 100
- opt_set_adv XY_FREQUENCY_LIMIT 15
- opt_enable_adv SHOW_TEMP_ADC_VALUES HOME_Y_BEFORE_X EMERGENCY_PARSER FAN_KICKSTART_TIME
- opt_enable_adv ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED ADVANCED_OK
- opt_enable_adv VOLUMETRIC_DEFAULT_ON NO_WORKSPACE_OFFSETS ACTION_ON_KILL
- opt_enable_adv EXTRA_FAN_SPEED FWERETRACT Z_DUAL_STEPPER_DRIVERS Z_DUAL_ENDSTOPS
- opt_enable_adv MENU_ADDAUTOSTART SDCARD_SORT_ALPHA
- opt_enable REPRAP_DISCOUNT_SMART_CONTROLLER BABYSTEPPING DAC_MOTOR_CURRENT_DEFAULT
- opt_enable FILAMENT_LCD_DISPLAY FILAMENT_WIDTH_SENSOR
- opt_enable ENDSTOP_INTERRUPTS_FEATURE FAN_SOFT_PWM SDSUPPORT
- opt_enable USE_XMAX_PLUG
- build_marlin
#
######## Other Standard LCD/Panels ##############
#
# ULTRA_LCD
#
#- restore_configs
#- opt_enable ULTRA_LCD
#- build_marlin
#
# DOGLCD
#
#- restore_configs
#- opt_enable DOGLCD
#- build_marlin
#
# MAKRPANEL
# Needs to use Melzi and Sanguino hardware
#
#- restore_configs
#- opt_enable MAKRPANEL
#- build_marlin
#
# REPRAP_DISCOUNT_SMART_CONTROLLER, SDSUPPORT, BABYSTEPPING, RIGIDBOARD_V2, and DAC_MOTOR_CURRENT_DEFAULT
#
#- restore_configs
#- opt_set MOTHERBOARD BOARD_RIGIDBOARD_V2
#- opt_enable REPRAP_DISCOUNT_SMART_CONTROLLER SDSUPPORT BABYSTEPPING DAC_MOTOR_CURRENT_DEFAULT
#- build_marlin
# #
# G3D_PANEL with SDCARD_SORT_ALPHA and STATUS_MESSAGE_SCROLLING
#
#- restore_configs
#- opt_enable G3D_PANEL SDSUPPORT
#- opt_enable_adv SDCARD_SORT_ALPHA STATUS_MESSAGE_SCROLLING SCROLL_LONG_FILENAMES
#- opt_set_adv SDSORT_GCODE true
#- opt_set_adv SDSORT_USES_RAM true
#- opt_set_adv SDSORT_USES_STACK true
#- opt_set_adv SDSORT_CACHE_NAMES true
#- build_marlin
#
# REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER with LIGHTWEIGHT_UI
#
- restore_configs
- opt_enable REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER SDSUPPORT
- opt_enable_adv SDCARD_SORT_ALPHA STATUS_MESSAGE_SCROLLING SCROLL_LONG_FILENAMES LIGHTWEIGHT_UI
- opt_set_adv SDSORT_GCODE true
- opt_set_adv SDSORT_USES_RAM true
- opt_set_adv SDSORT_USES_STACK true
- opt_set_adv SDSORT_CACHE_NAMES true
- build_marlin
#
# REPRAPWORLD_KEYPAD
#
# Cant find configuration details to get it to compile
#- restore_configs
#- opt_enable ULTRA_LCD REPRAPWORLD_KEYPAD REPRAPWORLD_KEYPAD_MOVE_STEP
#- build_marlin
#
# RA_CONTROL_PANEL
#
#- restore_configs
#- opt_enable RA_CONTROL_PANEL PINS_DEBUGGING
#- build_marlin
#
######## I2C LCD/PANELS ##############
#
# !!!ATTENTION!!!
# Most I2C configurations are failing at the moment because they require
# a different Liquid Crystal library "LiquidTWI2".
#
# LCD_SAINSMART_I2C_1602
#
#- restore_configs
#- opt_enable LCD_SAINSMART_I2C_1602
#- build_marlin
#
# LCD_I2C_PANELOLU2
#
#- restore_configs
#- opt_enable LCD_I2C_PANELOLU2
#- build_marlin
#
# LCD_I2C_VIKI
#
#- restore_configs
#- opt_enable LCD_I2C_VIKI
#- build_marlin
#
# LCM1602
#
#- restore_configs
#- opt_enable LCM1602
#- build_marlin
#
# Language files test with REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER
#
#- restore_configs
#- opt_enable REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER SDSUPPORT
#- for lang in an bg ca zh_CN zh_TW cz da de el el-gr en es eu fi fr gl hr it jp-kana nl pl pt pt-br ru sk tr uk test; do opt_set LCD_LANGUAGE $lang; echo "compile with language $lang ..."; build_marlin
#
#- restore_configs
#- opt_enable REPRAP_DISCOUNT_SMART_CONTROLLER SDSUPPORT
#- for lang in an bg ca zh_CN zh_TW cz da de el el-gr en es eu fi fr gl hr it jp-kana nl pl pt pt-br ru sk tr uk test; do opt_set LCD_LANGUAGE $lang; echo "compile with language $lang ..."; build_marlin
#
#
######## Example Configurations ##############
#
# BQ Hephestos 2
#- restore_configs
#- use_example_configs Hephestos_2
#- build_marlin
#
# Delta Config (generic) + ABL bilinear + PROBE_MANUALLY
- use_example_configs delta/generic
- opt_enable REPRAP_DISCOUNT_SMART_CONTROLLER DELTA_CALIBRATION_MENU AUTO_BED_LEVELING_BILINEAR PROBE_MANUALLY
- build_marlin
#
# Delta Config (generic) + UBL + ALLEN_KEY + OLED_PANEL_TINYBOY2 + EEPROM_SETTINGS
#
- use_example_configs delta/generic
- opt_enable AUTO_BED_LEVELING_UBL RESTORE_LEVELING_AFTER_G28 Z_PROBE_ALLEN_KEY EEPROM_SETTINGS EEPROM_CHITCHAT
- opt_enable OLED_PANEL_TINYBOY2 MESH_EDIT_GFX_OVERLAY
- build_marlin
#
# Delta Config (FLSUN AC because it's complex)
#
- use_example_configs delta/FLSUN/auto_calibrate
- build_marlin
#
# Makibox Config need to check board type for Teensy++ 2.0
#
#- use_example_configs makibox
#- build_marlin
#
# SCARA with TMC2130
#
- use_example_configs SCARA
- opt_enable AUTO_BED_LEVELING_BILINEAR FIX_MOUNTED_PROBE USE_ZMIN_PLUG EEPROM_SETTINGS EEPROM_CHITCHAT ULTIMAKERCONTROLLER
- opt_set X_DRIVER_TYPE TMC2130
- opt_set Y_DRIVER_TYPE TMC2130
- opt_set Z_DRIVER_TYPE TMC2130
- opt_set E0_DRIVER_TYPE TMC2130
- opt_enable_adv MONITOR_DRIVER_STATUS STEALTHCHOP HYBRID_THRESHOLD SENSORLESS_HOMING
- build_marlin
#
# TMC2208 Config
#
- restore_configs
- opt_set X_DRIVER_TYPE TMC2208
- opt_set Y_DRIVER_TYPE TMC2208
- opt_set Z_DRIVER_TYPE TMC2208
- opt_set E0_DRIVER_TYPE TMC2208
- opt_enable_adv MONITOR_DRIVER_STATUS STEALTHCHOP HYBRID_THRESHOLD TMC_DEBUG
- build_marlin
#
# tvrrug Config need to check board type for sanguino atmega644p
#
#- use_example_configs tvrrug/Round2
#- build_marlin
#
#
######## Board Types #############
#
# To be added in nightly test branch
#

677
LICENSE Normal file
View File

@ -0,0 +1,677 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://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 <http://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
<http://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
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

27
Marlin/Conditionals.h Normal file
View File

@ -0,0 +1,27 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* Conditionals.h
* OBSOLETE: Replaced by Conditionals_LCD.h and Conditionals_post.h
*/
#error "Old configurations? Please delete all #include lines from Configuration.h and Configuration_adv.h."

528
Marlin/Conditionals_LCD.h Normal file
View File

@ -0,0 +1,528 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* Conditionals_LCD.h
* Conditionals that need to be set before Configuration_adv.h or pins.h
*/
#ifndef CONDITIONALS_LCD_H // Get the LCD defines which are needed first
#define CONDITIONALS_LCD_H
#define LCD_HAS_DIRECTIONAL_BUTTONS (BUTTON_EXISTS(UP) || BUTTON_EXISTS(DWN) || BUTTON_EXISTS(LFT) || BUTTON_EXISTS(RT))
#if ENABLED(CARTESIO_UI)
#define DOGLCD
#define ULTIPANEL
#define DEFAULT_LCD_CONTRAST 90
#define LCD_CONTRAST_MIN 60
#define LCD_CONTRAST_MAX 140
#elif ENABLED(MAKRPANEL)
#define U8GLIB_ST7565_64128N
#elif ENABLED(ZONESTAR_LCD)
#define REPRAPWORLD_KEYPAD
#define REPRAPWORLD_KEYPAD_MOVE_STEP 10.0
#define ADC_KEYPAD
#define ADC_KEY_NUM 8
#define ULTIPANEL
// this helps to implement ADC_KEYPAD menus
#define ENCODER_PULSES_PER_STEP 1
#define ENCODER_STEPS_PER_MENU_ITEM 1
#define ENCODER_FEEDRATE_DEADZONE 2
#define REVERSE_MENU_DIRECTION
#elif ENABLED(ANET_FULL_GRAPHICS_LCD)
#define REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER
#elif ENABLED(BQ_LCD_SMART_CONTROLLER)
#define REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER
#elif ENABLED(miniVIKI) || ENABLED(VIKI2) || ENABLED(ELB_FULL_GRAPHIC_CONTROLLER)
#define ULTRA_LCD //general LCD support, also 16x2
#define DOGLCD // Support for SPI LCD 128x64 (Controller ST7565R graphic Display Family)
#define ULTIMAKERCONTROLLER //as available from the Ultimaker online store.
#if ENABLED(miniVIKI)
#define LCD_CONTRAST_MIN 75
#define LCD_CONTRAST_MAX 115
#define DEFAULT_LCD_CONTRAST 95
#define U8GLIB_ST7565_64128N
#elif ENABLED(VIKI2)
#define LCD_CONTRAST_MIN 0
#define LCD_CONTRAST_MAX 255
#define DEFAULT_LCD_CONTRAST 140
#define U8GLIB_ST7565_64128N
#elif ENABLED(ELB_FULL_GRAPHIC_CONTROLLER)
#define LCD_CONTRAST_MIN 90
#define LCD_CONTRAST_MAX 130
#define DEFAULT_LCD_CONTRAST 110
#define U8GLIB_LM6059_AF
#define SD_DETECT_INVERTED
#endif
#elif ENABLED(OLED_PANEL_TINYBOY2)
#define U8GLIB_SSD1306
#define ULTIPANEL
#define REVERSE_ENCODER_DIRECTION
#define REVERSE_MENU_DIRECTION
#elif ENABLED(RA_CONTROL_PANEL)
#define LCD_I2C_TYPE_PCA8574
#define LCD_I2C_ADDRESS 0x27 // I2C Address of the port expander
#define ULTIPANEL
#elif ENABLED(REPRAPWORLD_GRAPHICAL_LCD)
#define DOGLCD
#define U8GLIB_ST7920
#define ULTIPANEL
#elif ENABLED(CR10_STOCKDISPLAY)
#define REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER
#ifndef ST7920_DELAY_1
#define ST7920_DELAY_1 DELAY_NS(125)
#endif
#ifndef ST7920_DELAY_2
#define ST7920_DELAY_2 DELAY_NS(125)
#endif
#ifndef ST7920_DELAY_3
#define ST7920_DELAY_3 DELAY_NS(125)
#endif
#elif ENABLED(MKS_12864OLED)
#define REPRAP_DISCOUNT_SMART_CONTROLLER
#define U8GLIB_SH1106
#elif ENABLED(MKS_12864OLED_SSD1306)
#define REPRAP_DISCOUNT_SMART_CONTROLLER
#define U8GLIB_SSD1306
#elif ENABLED(MKS_MINI_12864)
#define MINIPANEL
#endif
#if ENABLED(MAKRPANEL) || ENABLED(MINIPANEL)
#define DOGLCD
#define ULTIPANEL
#define DEFAULT_LCD_CONTRAST 17
#endif
#if ENABLED(ULTI_CONTROLLER)
#define U8GLIB_SSD1309
#define REVERSE_ENCODER_DIRECTION
#define LCD_RESET_PIN LCD_PINS_D6 // This controller need a reset pin
#define LCD_CONTRAST_MIN 0
#define LCD_CONTRAST_MAX 254
#define DEFAULT_LCD_CONTRAST 127
#define ENCODER_PULSES_PER_STEP 2
#define ENCODER_STEPS_PER_MENU_ITEM 2
#endif
// Generic support for SSD1306 / SSD1309 / SH1106 OLED based LCDs.
#if ENABLED(U8GLIB_SSD1306) || ENABLED(U8GLIB_SSD1309) || ENABLED(U8GLIB_SH1106)
#define ULTRA_LCD //general LCD support, also 16x2
#define DOGLCD // Support for I2C LCD 128x64 (Controller SSD1306 / SSD1309 / SH1106 graphic Display Family)
#endif
#if ENABLED(PANEL_ONE) || ENABLED(U8GLIB_SH1106)
#define ULTIMAKERCONTROLLER
#elif ENABLED(MAKEBOARD_MINI_2_LINE_DISPLAY_1602)
#define REPRAP_DISCOUNT_SMART_CONTROLLER
#define LCD_WIDTH 16
#define LCD_HEIGHT 2
#endif
#if ENABLED(REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER) || ENABLED(LCD_FOR_MELZI) || ENABLED(SILVER_GATE_GLCD_CONTROLLER)
#define DOGLCD
#define U8GLIB_ST7920
#define REPRAP_DISCOUNT_SMART_CONTROLLER
#endif
#if ENABLED(ULTIMAKERCONTROLLER) \
|| ENABLED(REPRAP_DISCOUNT_SMART_CONTROLLER) \
|| ENABLED(G3D_PANEL) \
|| ENABLED(RIGIDBOT_PANEL) \
|| ENABLED(ULTI_CONTROLLER)
#define ULTIPANEL
#endif
#if ENABLED(REPRAPWORLD_KEYPAD)
#define NEWPANEL
#if ENABLED(ULTIPANEL) && !defined(REPRAPWORLD_KEYPAD_MOVE_STEP)
#define REPRAPWORLD_KEYPAD_MOVE_STEP 1.0
#endif
#endif
/**
* I2C PANELS
*/
#if ENABLED(LCD_SAINSMART_I2C_1602) || ENABLED(LCD_SAINSMART_I2C_2004)
#define LCD_I2C_TYPE_PCF8575
#define LCD_I2C_ADDRESS 0x27 // I2C Address of the port expander
#define ULTRA_LCD
#if ENABLED(LCD_SAINSMART_I2C_2004)
#define LCD_WIDTH 20
#define LCD_HEIGHT 4
#endif
#elif ENABLED(LCD_I2C_PANELOLU2)
// PANELOLU2 LCD with status LEDs, separate encoder and click inputs
#define LCD_I2C_TYPE_MCP23017
#define LCD_I2C_ADDRESS 0x20 // I2C Address of the port expander
#define LCD_USE_I2C_BUZZER // Enable buzzer on LCD (optional)
#define ULTIPANEL
#elif ENABLED(LCD_I2C_VIKI)
/**
* Panucatt VIKI LCD with status LEDs, integrated click & L/R/U/P buttons, separate encoder inputs
*
* This uses the LiquidTWI2 library v1.2.3 or later ( https://github.com/lincomatic/LiquidTWI2 )
* Make sure the LiquidTWI2 directory is placed in the Arduino or Sketchbook libraries subdirectory.
* Note: The pause/stop/resume LCD button pin should be connected to the Arduino
* BTN_ENC pin (or set BTN_ENC to -1 if not used)
*/
#define LCD_I2C_TYPE_MCP23017
#define LCD_I2C_ADDRESS 0x20 // I2C Address of the port expander
#define LCD_USE_I2C_BUZZER // Enable buzzer on LCD (requires LiquidTWI2 v1.2.3 or later)
#define ULTIPANEL
#define ENCODER_FEEDRATE_DEADZONE 4
#define STD_ENCODER_PULSES_PER_STEP 1
#define STD_ENCODER_STEPS_PER_MENU_ITEM 2
#elif ENABLED(G3D_PANEL)
#define STD_ENCODER_PULSES_PER_STEP 2
#define STD_ENCODER_STEPS_PER_MENU_ITEM 1
#elif ENABLED(miniVIKI) || ENABLED(VIKI2) \
|| ENABLED(ELB_FULL_GRAPHIC_CONTROLLER) \
|| ENABLED(OLED_PANEL_TINYBOY2) \
|| ENABLED(BQ_LCD_SMART_CONTROLLER) \
|| ENABLED(LCD_I2C_PANELOLU2) \
|| ENABLED(REPRAP_DISCOUNT_SMART_CONTROLLER)
#define STD_ENCODER_PULSES_PER_STEP 4
#define STD_ENCODER_STEPS_PER_MENU_ITEM 1
#endif
#ifndef STD_ENCODER_PULSES_PER_STEP
#define STD_ENCODER_PULSES_PER_STEP 5
#endif
#ifndef STD_ENCODER_STEPS_PER_MENU_ITEM
#define STD_ENCODER_STEPS_PER_MENU_ITEM 1
#endif
#ifndef ENCODER_PULSES_PER_STEP
#define ENCODER_PULSES_PER_STEP STD_ENCODER_PULSES_PER_STEP
#endif
#ifndef ENCODER_STEPS_PER_MENU_ITEM
#define ENCODER_STEPS_PER_MENU_ITEM STD_ENCODER_STEPS_PER_MENU_ITEM
#endif
#ifndef ENCODER_FEEDRATE_DEADZONE
#define ENCODER_FEEDRATE_DEADZONE 6
#endif
// Shift register panels
// ---------------------
// 2 wire Non-latching LCD SR from:
// https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/schematics#!shiftregister-connection
#if ENABLED(SAV_3DLCD)
#define SR_LCD_2W_NL // Non latching 2 wire shift register
#define ULTIPANEL
#endif
#if ENABLED(DOGLCD) // Change number of lines to match the DOG graphic display
#ifndef LCD_WIDTH
#ifdef LCD_WIDTH_OVERRIDE
#define LCD_WIDTH LCD_WIDTH_OVERRIDE
#else
#define LCD_WIDTH 22
#endif
#endif
#ifndef LCD_HEIGHT
#define LCD_HEIGHT 5
#endif
#endif
#if ENABLED(NO_LCD_MENUS)
#undef ULTIPANEL
#endif
#if ENABLED(ULTIPANEL)
#define NEWPANEL // Disable this if you actually have no click-encoder panel
#define ULTRA_LCD
#ifndef LCD_WIDTH
#define LCD_WIDTH 20
#endif
#ifndef LCD_HEIGHT
#define LCD_HEIGHT 4
#endif
#elif ENABLED(ULTRA_LCD) // no panel but just LCD
#ifndef LCD_WIDTH
#define LCD_WIDTH 16
#endif
#ifndef LCD_HEIGHT
#define LCD_HEIGHT 2
#endif
#endif
#if ENABLED(DOGLCD)
/* Custom characters defined in font dogm_font_data_Marlin_symbols.h / Marlin_symbols.fon */
// \x00 intentionally skipped to avoid problems in strings
#define LCD_STR_REFRESH "\x01"
#define LCD_STR_FOLDER "\x02"
#define LCD_STR_ARROW_RIGHT "\x03"
#define LCD_STR_UPLEVEL "\x04"
#define LCD_STR_CLOCK "\x05"
#define LCD_STR_FEEDRATE "\x06"
#define LCD_STR_BEDTEMP "\x07"
#define LCD_STR_THERMOMETER "\x08"
#define LCD_STR_DEGREE "\x09"
#define LCD_STR_SPECIAL_MAX '\x09'
// Maximum here is 0x1F because 0x20 is ' ' (space) and the normal charsets begin.
// Better stay below 0x10 because DISPLAY_CHARSET_HD44780_WESTERN begins here.
// Symbol characters
#define LCD_STR_FILAM_DIA "\xf8"
#define LCD_STR_FILAM_MUL "\xa4"
#else
// Custom characters defined in the first 8 characters of the LCD
#define LCD_BEDTEMP_CHAR 0x00 // Print only as a char. This will have 'unexpected' results when used in a string!
#define LCD_DEGREE_CHAR 0x01
#define LCD_STR_THERMOMETER "\x02" // Still used with string concatenation
#define LCD_UPLEVEL_CHAR 0x03
#define LCD_STR_REFRESH "\x04"
#define LCD_STR_FOLDER "\x05"
#define LCD_FEEDRATE_CHAR 0x06
#define LCD_CLOCK_CHAR 0x07
#define LCD_STR_ARROW_RIGHT ">" /* from the default character set */
#endif
/**
* Default LCD contrast for dogm-like LCD displays
*/
#if ENABLED(DOGLCD)
#define HAS_LCD_CONTRAST ( \
ENABLED(MAKRPANEL) \
|| ENABLED(CARTESIO_UI) \
|| ENABLED(VIKI2) \
|| ENABLED(miniVIKI) \
|| ENABLED(ELB_FULL_GRAPHIC_CONTROLLER) \
)
#if HAS_LCD_CONTRAST
#ifndef LCD_CONTRAST_MIN
#define LCD_CONTRAST_MIN 0
#endif
#ifndef LCD_CONTRAST_MAX
#define LCD_CONTRAST_MAX 63
#endif
#ifndef DEFAULT_LCD_CONTRAST
#define DEFAULT_LCD_CONTRAST 32
#endif
#endif
#endif
// Boot screens
#if DISABLED(ULTRA_LCD)
#undef SHOW_BOOTSCREEN
#elif !defined(BOOTSCREEN_TIMEOUT)
#define BOOTSCREEN_TIMEOUT 2500
#endif
#define HAS_DEBUG_MENU (ENABLED(ULTIPANEL) && ENABLED(LCD_PROGRESS_BAR_TEST))
/**
* Extruders have some combination of stepper motors and hotends
* so we separate these concepts into the defines:
*
* EXTRUDERS - Number of Selectable Tools
* HOTENDS - Number of hotends, whether connected or separate
* E_STEPPERS - Number of actual E stepper motors
* E_MANUAL - Number of E steppers for LCD move options
*
*/
#if ENABLED(SWITCHING_EXTRUDER) // One stepper for every two EXTRUDERS
#if EXTRUDERS > 4
#define E_STEPPERS 3
#elif EXTRUDERS > 2
#define E_STEPPERS 2
#else
#define E_STEPPERS 1
#endif
#if DISABLED(SWITCHING_NOZZLE)
#define HOTENDS E_STEPPERS
#endif
#define E_MANUAL EXTRUDERS
#elif ENABLED(MIXING_EXTRUDER)
#define E_STEPPERS MIXING_STEPPERS
#define E_MANUAL 1
#else
#define E_STEPPERS EXTRUDERS
#define E_MANUAL EXTRUDERS
#endif
// No inactive extruders with MK2_MULTIPLEXER or SWITCHING_NOZZLE
#if ENABLED(MK2_MULTIPLEXER) || ENABLED(SWITCHING_NOZZLE)
#undef DISABLE_INACTIVE_EXTRUDER
#endif
// MK2 Multiplexer forces SINGLENOZZLE
#if ENABLED(MK2_MULTIPLEXER)
#define SINGLENOZZLE
#endif
#if ENABLED(SINGLENOZZLE) || ENABLED(MIXING_EXTRUDER) // One hotend, one thermistor, no XY offset
#undef HOTENDS
#define HOTENDS 1
#undef TEMP_SENSOR_1_AS_REDUNDANT
#undef HOTEND_OFFSET_X
#undef HOTEND_OFFSET_Y
#endif
#ifndef HOTENDS
#define HOTENDS EXTRUDERS
#endif
#define DO_SWITCH_EXTRUDER (ENABLED(SWITCHING_EXTRUDER) && (DISABLED(SWITCHING_NOZZLE) || SWITCHING_EXTRUDER_SERVO_NR != SWITCHING_NOZZLE_SERVO_NR))
/**
* DISTINCT_E_FACTORS affects how some E factors are accessed
*/
#if ENABLED(DISTINCT_E_FACTORS) && E_STEPPERS > 1
#define XYZE_N (XYZ + E_STEPPERS)
#if ENABLED(HANGPRINTER)
#define NUM_AXIS_N (ABCD + E_STEPPERS)
#else
#define NUM_AXIS_N (XYZ + E_STEPPERS)
#endif
#define E_AXIS_N (E_AXIS + extruder)
#else
#undef DISTINCT_E_FACTORS
#define XYZE_N XYZE
#if ENABLED(HANGPRINTER)
#define NUM_AXIS_N ABCDE
#else
#define NUM_AXIS_N XYZE
#endif
#define E_AXIS_N E_AXIS
#endif
/**
* The BLTouch Probe emulates a servo probe
* and uses "special" angles for its state.
*/
#if ENABLED(BLTOUCH)
#ifndef Z_PROBE_SERVO_NR
#define Z_PROBE_SERVO_NR 0
#endif
#ifndef NUM_SERVOS
#define NUM_SERVOS (Z_PROBE_SERVO_NR + 1)
#endif
#undef DEACTIVATE_SERVOS_AFTER_MOVE
#if NUM_SERVOS == 1
#undef SERVO_DELAY
#define SERVO_DELAY { 50 }
#endif
#ifndef BLTOUCH_DELAY
#define BLTOUCH_DELAY 375
#endif
#undef Z_SERVO_ANGLES
#define Z_SERVO_ANGLES { BLTOUCH_DEPLOY, BLTOUCH_STOW }
#define BLTOUCH_DEPLOY 10
#define BLTOUCH_STOW 90
#define BLTOUCH_SELFTEST 120
#define BLTOUCH_RESET 160
#define _TEST_BLTOUCH(P) (READ(P##_PIN) != P##_ENDSTOP_INVERTING)
// Always disable probe pin inverting for BLTouch
#undef Z_MIN_PROBE_ENDSTOP_INVERTING
#define Z_MIN_PROBE_ENDSTOP_INVERTING false
#if ENABLED(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN)
#undef Z_MIN_ENDSTOP_INVERTING
#define Z_MIN_ENDSTOP_INVERTING Z_MIN_PROBE_ENDSTOP_INVERTING
#define TEST_BLTOUCH() _TEST_BLTOUCH(Z_MIN)
#else
#define TEST_BLTOUCH() _TEST_BLTOUCH(Z_MIN_PROBE)
#endif
#endif
/**
* Set a flag for a servo probe
*/
#define HAS_Z_SERVO_PROBE (defined(Z_PROBE_SERVO_NR) && Z_PROBE_SERVO_NR >= 0)
/**
* Set flags for enabled probes
*/
#define HAS_BED_PROBE (ENABLED(FIX_MOUNTED_PROBE) || ENABLED(Z_PROBE_ALLEN_KEY) || HAS_Z_SERVO_PROBE || ENABLED(Z_PROBE_SLED) || ENABLED(SOLENOID_PROBE))
#define PROBE_SELECTED (HAS_BED_PROBE || ENABLED(PROBE_MANUALLY) || ENABLED(MESH_BED_LEVELING))
#if !HAS_BED_PROBE
// Clear probe pin settings when no probe is selected
#undef Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN
#undef Z_MIN_PROBE_ENDSTOP
#elif ENABLED(Z_PROBE_ALLEN_KEY)
// Extra test for Allen Key Probe
#define PROBE_IS_TRIGGERED_WHEN_STOWED_TEST
#endif
#define HOMING_Z_WITH_PROBE (HAS_BED_PROBE && Z_HOME_DIR < 0 && ENABLED(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN))
#define HAS_SOFTWARE_ENDSTOPS (ENABLED(MIN_SOFTWARE_ENDSTOPS) || ENABLED(MAX_SOFTWARE_ENDSTOPS))
#define HAS_RESUME_CONTINUE (ENABLED(NEWPANEL) || ENABLED(EMERGENCY_PARSER))
#define HAS_COLOR_LEDS (ENABLED(BLINKM) || ENABLED(RGB_LED) || ENABLED(RGBW_LED) || ENABLED(PCA9632) || ENABLED(NEOPIXEL_LED))
#define USE_MARLINSERIAL !(defined(__AVR__) && defined(USBCON))
#endif // CONDITIONALS_LCD_H

1417
Marlin/Conditionals_post.h Normal file

File diff suppressed because it is too large Load Diff

1927
Marlin/Configuration.h Normal file

File diff suppressed because it is too large Load Diff

1654
Marlin/Configuration_adv.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,920 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* Marlin Firmware -- G26 - Mesh Validation Tool
*/
#include "MarlinConfig.h"
#if ENABLED(G26_MESH_VALIDATION)
#include "Marlin.h"
#include "planner.h"
#include "stepper.h"
#include "temperature.h"
#include "ultralcd.h"
#include "parser.h"
#include "serial.h"
#include "bitmap_flags.h"
#if ENABLED(MESH_BED_LEVELING)
#include "mesh_bed_leveling.h"
#elif ENABLED(AUTO_BED_LEVELING_UBL)
#include "ubl.h"
#endif
#define EXTRUSION_MULTIPLIER 1.0
#define RETRACTION_MULTIPLIER 1.0
#define PRIME_LENGTH 10.0
#define OOZE_AMOUNT 0.3
#define INTERSECTION_CIRCLE_RADIUS 5
#define CROSSHAIRS_SIZE 3
#if CROSSHAIRS_SIZE >= INTERSECTION_CIRCLE_RADIUS
#error "CROSSHAIRS_SIZE must be less than INTERSECTION_CIRCLE_RADIUS."
#endif
#define G26_OK false
#define G26_ERR true
/**
* G26 Mesh Validation Tool
*
* G26 is a Mesh Validation Tool intended to provide support for the Marlin Unified Bed Leveling System.
* In order to fully utilize and benefit from the Marlin Unified Bed Leveling System an accurate Mesh must
* be defined. G29 is designed to allow the user to quickly validate the correctness of her Mesh. It will
* first heat the bed and nozzle. It will then print lines and circles along the Mesh Cell boundaries and
* the intersections of those lines (respectively).
*
* This action allows the user to immediately see where the Mesh is properly defined and where it needs to
* be edited. The command will generate the Mesh lines closest to the nozzle's starting position. Alternatively
* the user can specify the X and Y position of interest with command parameters. This allows the user to
* focus on a particular area of the Mesh where attention is needed.
*
* B # Bed Set the Bed Temperature. If not specified, a default of 60 C. will be assumed.
*
* C Current When searching for Mesh Intersection points to draw, use the current nozzle location
* as the base for any distance comparison.
*
* D Disable Disable the Unified Bed Leveling System. In the normal case the user is invoking this
* command to see how well a Mesh as been adjusted to match a print surface. In order to do
* this the Unified Bed Leveling System is turned on by the G26 command. The D parameter
* alters the command's normal behaviour and disables the Unified Bed Leveling System even if
* it is on.
*
* H # Hotend Set the Nozzle Temperature. If not specified, a default of 205 C. will be assumed.
*
* F # Filament Used to specify the diameter of the filament being used. If not specified
* 1.75mm filament is assumed. If you are not getting acceptable results by using the
* 'correct' numbers, you can scale this number up or down a little bit to change the amount
* of filament that is being extruded during the printing of the various lines on the bed.
*
* K Keep-On Keep the heaters turned on at the end of the command.
*
* L # Layer Layer height. (Height of nozzle above bed) If not specified .20mm will be used.
*
* O # Ooooze How much your nozzle will Ooooze filament while getting in position to print. This
* is over kill, but using this parameter will let you get the very first 'circle' perfect
* so you have a trophy to peel off of the bed and hang up to show how perfectly you have your
* Mesh calibrated. If not specified, a filament length of .3mm is assumed.
*
* P # Prime Prime the nozzle with specified length of filament. If this parameter is not
* given, no prime action will take place. If the parameter specifies an amount, that much
* will be purged before continuing. If no amount is specified the command will start
* purging filament until the user provides an LCD Click and then it will continue with
* printing the Mesh. You can carefully remove the spent filament with a needle nose
* pliers while holding the LCD Click wheel in a depressed state. If you do not have
* an LCD, you must specify a value if you use P.
*
* Q # Multiplier Retraction Multiplier. Normally not needed. Retraction defaults to 1.0mm and
* un-retraction is at 1.2mm These numbers will be scaled by the specified amount
*
* R # Repeat Prints the number of patterns given as a parameter, starting at the current location.
* If a parameter isn't given, every point will be printed unless G26 is interrupted.
* This works the same way that the UBL G29 P4 R parameter works.
*
* NOTE: If you do not have an LCD, you -must- specify R. This is to ensure that you are
* aware that there's some risk associated with printing without the ability to abort in
* cases where mesh point Z value may be inaccurate. As above, if you do not include a
* parameter, every point will be printed.
*
* S # Nozzle Used to control the size of nozzle diameter. If not specified, a .4mm nozzle is assumed.
*
* U # Random Randomize the order that the circles are drawn on the bed. The search for the closest
* undrawn cicle is still done. But the distance to the location for each circle has a
* random number of the size specified added to it. Specifying S50 will give an interesting
* deviation from the normal behaviour on a 10 x 10 Mesh.
*
* X # X Coord. Specify the starting location of the drawing activity.
*
* Y # Y Coord. Specify the starting location of the drawing activity.
*/
// External references
extern Planner planner;
// Private functions
static uint16_t circle_flags[16], horizontal_mesh_line_flags[16], vertical_mesh_line_flags[16];
float g26_e_axis_feedrate = 0.025,
random_deviation = 0.0;
static bool g26_retracted = false; // Track the retracted state of the nozzle so mismatched
// retracts/recovers won't result in a bad state.
static float g26_extrusion_multiplier,
g26_retraction_multiplier,
g26_layer_height,
g26_prime_length,
g26_x_pos, g26_y_pos;
static int16_t g26_bed_temp,
g26_hotend_temp;
static int8_t g26_prime_flag;
#if ENABLED(ULTIPANEL)
/**
* If the LCD is clicked, cancel, wait for release, return true
*/
bool user_canceled() {
if (!is_lcd_clicked()) return false; // Return if the button isn't pressed
lcd_setstatusPGM(PSTR("Mesh Validation Stopped."), 99);
#if ENABLED(ULTIPANEL)
lcd_quick_feedback(true);
#endif
wait_for_release();
return true;
}
bool exit_from_g26() {
lcd_setstatusPGM(PSTR("Leaving G26"), -1);
wait_for_release();
return G26_ERR;
}
#endif
void G26_line_to_destination(const float &feed_rate) {
const float save_feedrate = feedrate_mm_s;
feedrate_mm_s = feed_rate;
prepare_move_to_destination(); // will ultimately call ubl.line_to_destination_cartesian or ubl.prepare_linear_move_to for UBL_SEGMENTED
feedrate_mm_s = save_feedrate;
}
void move_to(const float &rx, const float &ry, const float &z, const float &e_delta) {
float feed_value;
static float last_z = -999.99;
bool has_xy_component = (rx != current_position[X_AXIS] || ry != current_position[Y_AXIS]); // Check if X or Y is involved in the movement.
if (z != last_z) {
last_z = z;
feed_value = planner.max_feedrate_mm_s[Z_AXIS]/(3.0); // Base the feed rate off of the configured Z_AXIS feed rate
destination[X_AXIS] = current_position[X_AXIS];
destination[Y_AXIS] = current_position[Y_AXIS];
destination[Z_AXIS] = z; // We know the last_z==z or we wouldn't be in this block of code.
destination[E_CART] = current_position[E_CART];
G26_line_to_destination(feed_value);
set_destination_from_current();
}
// Check if X or Y is involved in the movement.
// Yes: a 'normal' movement. No: a retract() or recover()
feed_value = has_xy_component ? PLANNER_XY_FEEDRATE() / 10.0 : planner.max_feedrate_mm_s[E_AXIS] / 1.5;
if (g26_debug_flag) SERIAL_ECHOLNPAIR("in move_to() feed_value for XY:", feed_value);
destination[X_AXIS] = rx;
destination[Y_AXIS] = ry;
destination[E_CART] += e_delta;
G26_line_to_destination(feed_value);
set_destination_from_current();
}
FORCE_INLINE void move_to(const float where[XYZE], const float &de) { move_to(where[X_AXIS], where[Y_AXIS], where[Z_AXIS], de); }
void retract_filament(const float where[XYZE]) {
if (!g26_retracted) { // Only retract if we are not already retracted!
g26_retracted = true;
move_to(where, -1.0 * g26_retraction_multiplier);
}
}
void recover_filament(const float where[XYZE]) {
if (g26_retracted) { // Only un-retract if we are retracted.
move_to(where, 1.2 * g26_retraction_multiplier);
g26_retracted = false;
}
}
/**
* Prime the nozzle if needed. Return true on error.
*/
inline bool prime_nozzle() {
#if ENABLED(ULTIPANEL)
float Total_Prime = 0.0;
if (g26_prime_flag == -1) { // The user wants to control how much filament gets purged
lcd_external_control = true;
lcd_setstatusPGM(PSTR("User-Controlled Prime"), 99);
lcd_chirp();
set_destination_from_current();
recover_filament(destination); // Make sure G26 doesn't think the filament is retracted().
while (!is_lcd_clicked()) {
lcd_chirp();
destination[E_CART] += 0.25;
#ifdef PREVENT_LENGTHY_EXTRUDE
Total_Prime += 0.25;
if (Total_Prime >= EXTRUDE_MAXLENGTH) return G26_ERR;
#endif
G26_line_to_destination(planner.max_feedrate_mm_s[E_AXIS] / 15.0);
set_destination_from_current();
planner.synchronize(); // Without this synchronize, the purge is more consistent,
// but because the planner has a buffer, we won't be able
// to stop as quickly. So we put up with the less smooth
// action to give the user a more responsive 'Stop'.
SERIAL_FLUSH(); // Prevent host M105 buffer overrun.
}
wait_for_release();
lcd_setstatusPGM(PSTR("Done Priming"), 99);
lcd_quick_feedback(true);
lcd_external_control = false;
}
else
#endif
{
#if ENABLED(ULTRA_LCD)
lcd_setstatusPGM(PSTR("Fixed Length Prime."), 99);
lcd_quick_feedback(true);
#endif
set_destination_from_current();
destination[E_CART] += g26_prime_length;
G26_line_to_destination(planner.max_feedrate_mm_s[E_AXIS] / 15.0);
set_destination_from_current();
retract_filament(destination);
}
return G26_OK;
}
mesh_index_pair find_closest_circle_to_print(const float &X, const float &Y) {
float closest = 99999.99;
mesh_index_pair return_val;
return_val.x_index = return_val.y_index = -1;
for (uint8_t i = 0; i < GRID_MAX_POINTS_X; i++) {
for (uint8_t j = 0; j < GRID_MAX_POINTS_Y; j++) {
if (!is_bitmap_set(circle_flags, i, j)) {
const float mx = _GET_MESH_X(i), // We found a circle that needs to be printed
my = _GET_MESH_Y(j);
// Get the distance to this intersection
float f = HYPOT(X - mx, Y - my);
// It is possible that we are being called with the values
// to let us find the closest circle to the start position.
// But if this is not the case, add a small weighting to the
// distance calculation to help it choose a better place to continue.
f += HYPOT(g26_x_pos - mx, g26_y_pos - my) / 15.0;
// Add in the specified amount of Random Noise to our search
if (random_deviation > 1.0)
f += random(0.0, random_deviation);
if (f < closest) {
closest = f; // We found a closer location that is still
return_val.x_index = i; // un-printed --- save the data for it
return_val.y_index = j;
return_val.distance = closest;
}
}
}
}
bitmap_set(circle_flags, return_val.x_index, return_val.y_index); // Mark this location as done.
return return_val;
}
/**
* print_line_from_here_to_there() takes two cartesian coordinates and draws a line from one
* to the other. But there are really three sets of coordinates involved. The first coordinate
* is the present location of the nozzle. We don't necessarily want to print from this location.
* We first need to move the nozzle to the start of line segment where we want to print. Once
* there, we can use the two coordinates supplied to draw the line.
*
* Note: Although we assume the first set of coordinates is the start of the line and the second
* set of coordinates is the end of the line, it does not always work out that way. This function
* optimizes the movement to minimize the travel distance before it can start printing. This saves
* a lot of time and eliminates a lot of nonsensical movement of the nozzle. However, it does
* cause a lot of very little short retracement of th nozzle when it draws the very first line
* segment of a 'circle'. The time this requires is very short and is easily saved by the other
* cases where the optimization comes into play.
*/
void print_line_from_here_to_there(const float &sx, const float &sy, const float &sz, const float &ex, const float &ey, const float &ez) {
const float dx_s = current_position[X_AXIS] - sx, // find our distance from the start of the actual line segment
dy_s = current_position[Y_AXIS] - sy,
dist_start = HYPOT2(dx_s, dy_s), // We don't need to do a sqrt(), we can compare the distance^2
// to save computation time
dx_e = current_position[X_AXIS] - ex, // find our distance from the end of the actual line segment
dy_e = current_position[Y_AXIS] - ey,
dist_end = HYPOT2(dx_e, dy_e),
line_length = HYPOT(ex - sx, ey - sy);
// If the end point of the line is closer to the nozzle, flip the direction,
// moving from the end to the start. On very small lines the optimization isn't worth it.
if (dist_end < dist_start && (INTERSECTION_CIRCLE_RADIUS) < ABS(line_length))
return print_line_from_here_to_there(ex, ey, ez, sx, sy, sz);
// Decide whether to retract & bump
if (dist_start > 2.0) {
retract_filament(destination);
//todo: parameterize the bump height with a define
move_to(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS] + 0.500, 0.0); // Z bump to minimize scraping
move_to(sx, sy, sz + 0.500, 0.0); // Get to the starting point with no extrusion while bumped
}
move_to(sx, sy, sz, 0.0); // Get to the starting point with no extrusion / un-Z bump
const float e_pos_delta = line_length * g26_e_axis_feedrate * g26_extrusion_multiplier;
recover_filament(destination);
move_to(ex, ey, ez, e_pos_delta); // Get to the ending point with an appropriate amount of extrusion
}
inline bool look_for_lines_to_connect() {
float sx, sy, ex, ey;
for (uint8_t i = 0; i < GRID_MAX_POINTS_X; i++) {
for (uint8_t j = 0; j < GRID_MAX_POINTS_Y; j++) {
#if ENABLED(ULTIPANEL)
if (user_canceled()) return true; // Check if the user wants to stop the Mesh Validation
#endif
if (i < GRID_MAX_POINTS_X) { // We can't connect to anything to the right than GRID_MAX_POINTS_X.
// This is already a half circle because we are at the edge of the bed.
if (is_bitmap_set(circle_flags, i, j) && is_bitmap_set(circle_flags, i + 1, j)) { // check if we can do a line to the left
if (!is_bitmap_set(horizontal_mesh_line_flags, i, j)) {
//
// We found two circles that need a horizontal line to connect them
// Print it!
//
sx = _GET_MESH_X( i ) + (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)); // right edge
ex = _GET_MESH_X(i + 1) - (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)); // left edge
sx = constrain(sx, X_MIN_POS + 1, X_MAX_POS - 1);
sy = ey = constrain(_GET_MESH_Y(j), Y_MIN_POS + 1, Y_MAX_POS - 1);
ex = constrain(ex, X_MIN_POS + 1, X_MAX_POS - 1);
if (position_is_reachable(sx, sy) && position_is_reachable(ex, ey)) {
if (g26_debug_flag) {
SERIAL_ECHOPAIR(" Connecting with horizontal line (sx=", sx);
SERIAL_ECHOPAIR(", sy=", sy);
SERIAL_ECHOPAIR(") -> (ex=", ex);
SERIAL_ECHOPAIR(", ey=", ey);
SERIAL_CHAR(')');
SERIAL_EOL();
//debug_current_and_destination(PSTR("Connecting horizontal line."));
}
print_line_from_here_to_there(sx, sy, g26_layer_height, ex, ey, g26_layer_height);
}
bitmap_set(horizontal_mesh_line_flags, i, j); // Mark it as done so we don't do it again, even if we skipped it
}
}
if (j < GRID_MAX_POINTS_Y) { // We can't connect to anything further back than GRID_MAX_POINTS_Y.
// This is already a half circle because we are at the edge of the bed.
if (is_bitmap_set(circle_flags, i, j) && is_bitmap_set(circle_flags, i, j + 1)) { // check if we can do a line straight down
if (!is_bitmap_set( vertical_mesh_line_flags, i, j)) {
//
// We found two circles that need a vertical line to connect them
// Print it!
//
sy = _GET_MESH_Y( j ) + (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)); // top edge
ey = _GET_MESH_Y(j + 1) - (INTERSECTION_CIRCLE_RADIUS - (CROSSHAIRS_SIZE)); // bottom edge
sx = ex = constrain(_GET_MESH_X(i), X_MIN_POS + 1, X_MAX_POS - 1);
sy = constrain(sy, Y_MIN_POS + 1, Y_MAX_POS - 1);
ey = constrain(ey, Y_MIN_POS + 1, Y_MAX_POS - 1);
if (position_is_reachable(sx, sy) && position_is_reachable(ex, ey)) {
if (g26_debug_flag) {
SERIAL_ECHOPAIR(" Connecting with vertical line (sx=", sx);
SERIAL_ECHOPAIR(", sy=", sy);
SERIAL_ECHOPAIR(") -> (ex=", ex);
SERIAL_ECHOPAIR(", ey=", ey);
SERIAL_CHAR(')');
SERIAL_EOL();
#if ENABLED(AUTO_BED_LEVELING_UBL)
debug_current_and_destination(PSTR("Connecting vertical line."));
#endif
}
print_line_from_here_to_there(sx, sy, g26_layer_height, ex, ey, g26_layer_height);
}
bitmap_set(vertical_mesh_line_flags, i, j); // Mark it as done so we don't do it again, even if skipped
}
}
}
}
}
}
return false;
}
/**
* Turn on the bed and nozzle heat and
* wait for them to get up to temperature.
*/
inline bool turn_on_heaters() {
millis_t next = millis() + 5000UL;
#if HAS_HEATED_BED
#if ENABLED(ULTRA_LCD)
if (g26_bed_temp > 25) {
lcd_setstatusPGM(PSTR("G26 Heating Bed."), 99);
lcd_quick_feedback(true);
#if ENABLED(ULTIPANEL)
lcd_external_control = true;
#endif
#endif
thermalManager.setTargetBed(g26_bed_temp);
while (ABS(thermalManager.degBed() - g26_bed_temp) > 3) {
#if ENABLED(ULTIPANEL)
if (is_lcd_clicked()) return exit_from_g26();
#endif
if (ELAPSED(millis(), next)) {
next = millis() + 5000UL;
thermalManager.print_heaterstates();
SERIAL_EOL();
}
idle();
SERIAL_FLUSH(); // Prevent host M105 buffer overrun.
}
#if ENABLED(ULTRA_LCD)
}
lcd_setstatusPGM(PSTR("G26 Heating Nozzle."), 99);
lcd_quick_feedback(true);
#endif
#endif
// Start heating the nozzle and wait for it to reach temperature.
thermalManager.setTargetHotend(g26_hotend_temp, 0);
while (ABS(thermalManager.degHotend(0) - g26_hotend_temp) > 3) {
#if ENABLED(ULTIPANEL)
if (is_lcd_clicked()) return exit_from_g26();
#endif
if (ELAPSED(millis(), next)) {
next = millis() + 5000UL;
thermalManager.print_heaterstates();
SERIAL_EOL();
}
idle();
SERIAL_FLUSH(); // Prevent host M105 buffer overrun.
}
#if ENABLED(ULTRA_LCD)
lcd_reset_status();
lcd_quick_feedback(true);
#endif
return G26_OK;
}
float valid_trig_angle(float d) {
while (d > 360.0) d -= 360.0;
while (d < 0.0) d += 360.0;
return d;
}
/**
* G26: Mesh Validation Pattern generation.
*
* Used to interactively edit the mesh by placing the
* nozzle in a problem area and doing a G29 P4 R command.
*
* Parameters:
*
* B Bed Temperature
* C Continue from the Closest mesh point
* D Disable leveling before starting
* F Filament diameter
* H Hotend Temperature
* K Keep heaters on when completed
* L Layer Height
* O Ooze extrusion length
* P Prime length
* Q Retraction multiplier
* R Repetitions (number of grid points)
* S Nozzle Size (diameter) in mm
* U Random deviation (50 if no value given)
* X X position
* Y Y position
*/
void gcode_G26() {
SERIAL_ECHOLNPGM("G26 command started. Waiting for heater(s).");
// Don't allow Mesh Validation without homing first,
// or if the parameter parsing did not go OK, abort
if (axis_unhomed_error()) return;
g26_extrusion_multiplier = EXTRUSION_MULTIPLIER;
g26_retraction_multiplier = RETRACTION_MULTIPLIER;
g26_layer_height = MESH_TEST_LAYER_HEIGHT;
g26_prime_length = PRIME_LENGTH;
g26_bed_temp = MESH_TEST_BED_TEMP;
g26_hotend_temp = MESH_TEST_HOTEND_TEMP;
g26_prime_flag = 0;
float g26_nozzle = MESH_TEST_NOZZLE_SIZE,
g26_filament_diameter = DEFAULT_NOMINAL_FILAMENT_DIA,
g26_ooze_amount = parser.linearval('O', OOZE_AMOUNT);
bool g26_continue_with_closest = parser.boolval('C'),
g26_keep_heaters_on = parser.boolval('K');
if (parser.seenval('B')) {
g26_bed_temp = parser.value_celsius();
if (g26_bed_temp && !WITHIN(g26_bed_temp, 40, 140)) {
SERIAL_PROTOCOLLNPGM("?Specified bed temperature not plausible (40-140C).");
return;
}
}
if (parser.seenval('L')) {
g26_layer_height = parser.value_linear_units();
if (!WITHIN(g26_layer_height, 0.0, 2.0)) {
SERIAL_PROTOCOLLNPGM("?Specified layer height not plausible.");
return;
}
}
if (parser.seen('Q')) {
if (parser.has_value()) {
g26_retraction_multiplier = parser.value_float();
if (!WITHIN(g26_retraction_multiplier, 0.05, 15.0)) {
SERIAL_PROTOCOLLNPGM("?Specified Retraction Multiplier not plausible.");
return;
}
}
else {
SERIAL_PROTOCOLLNPGM("?Retraction Multiplier must be specified.");
return;
}
}
if (parser.seenval('S')) {
g26_nozzle = parser.value_float();
if (!WITHIN(g26_nozzle, 0.1, 1.0)) {
SERIAL_PROTOCOLLNPGM("?Specified nozzle size not plausible.");
return;
}
}
if (parser.seen('P')) {
if (!parser.has_value()) {
#if ENABLED(ULTIPANEL)
g26_prime_flag = -1;
#else
SERIAL_PROTOCOLLNPGM("?Prime length must be specified when not using an LCD.");
return;
#endif
}
else {
g26_prime_flag++;
g26_prime_length = parser.value_linear_units();
if (!WITHIN(g26_prime_length, 0.0, 25.0)) {
SERIAL_PROTOCOLLNPGM("?Specified prime length not plausible.");
return;
}
}
}
if (parser.seenval('F')) {
g26_filament_diameter = parser.value_linear_units();
if (!WITHIN(g26_filament_diameter, 1.0, 4.0)) {
SERIAL_PROTOCOLLNPGM("?Specified filament size not plausible.");
return;
}
}
g26_extrusion_multiplier *= sq(1.75) / sq(g26_filament_diameter); // If we aren't using 1.75mm filament, we need to
// scale up or down the length needed to get the
// same volume of filament
g26_extrusion_multiplier *= g26_filament_diameter * sq(g26_nozzle) / sq(0.3); // Scale up by nozzle size
if (parser.seenval('H')) {
g26_hotend_temp = parser.value_celsius();
if (!WITHIN(g26_hotend_temp, 165, 280)) {
SERIAL_PROTOCOLLNPGM("?Specified nozzle temperature not plausible.");
return;
}
}
if (parser.seen('U')) {
randomSeed(millis());
// This setting will persist for the next G26
random_deviation = parser.has_value() ? parser.value_float() : 50.0;
}
int16_t g26_repeats;
#if ENABLED(ULTIPANEL)
g26_repeats = parser.intval('R', GRID_MAX_POINTS + 1);
#else
if (!parser.seen('R')) {
SERIAL_PROTOCOLLNPGM("?(R)epeat must be specified when not using an LCD.");
return;
}
else
g26_repeats = parser.has_value() ? parser.value_int() : GRID_MAX_POINTS + 1;
#endif
if (g26_repeats < 1) {
SERIAL_PROTOCOLLNPGM("?(R)epeat value not plausible; must be at least 1.");
return;
}
g26_x_pos = parser.seenval('X') ? RAW_X_POSITION(parser.value_linear_units()) : current_position[X_AXIS];
g26_y_pos = parser.seenval('Y') ? RAW_Y_POSITION(parser.value_linear_units()) : current_position[Y_AXIS];
if (!position_is_reachable(g26_x_pos, g26_y_pos)) {
SERIAL_PROTOCOLLNPGM("?Specified X,Y coordinate out of bounds.");
return;
}
/**
* Wait until all parameters are verified before altering the state!
*/
set_bed_leveling_enabled(!parser.seen('D'));
if (current_position[Z_AXIS] < Z_CLEARANCE_BETWEEN_PROBES) {
do_blocking_move_to_z(Z_CLEARANCE_BETWEEN_PROBES);
set_current_from_destination();
}
if (turn_on_heaters() != G26_OK) goto LEAVE;
current_position[E_CART] = 0.0;
sync_plan_position_e();
if (g26_prime_flag && prime_nozzle() != G26_OK) goto LEAVE;
/**
* Bed is preheated
*
* Nozzle is at temperature
*
* Filament is primed!
*
* It's "Show Time" !!!
*/
ZERO(circle_flags);
ZERO(horizontal_mesh_line_flags);
ZERO(vertical_mesh_line_flags);
// Move nozzle to the specified height for the first layer
set_destination_from_current();
destination[Z_AXIS] = g26_layer_height;
move_to(destination, 0.0);
move_to(destination, g26_ooze_amount);
#if ENABLED(ULTIPANEL)
lcd_external_control = true;
#endif
//debug_current_and_destination(PSTR("Starting G26 Mesh Validation Pattern."));
#if DISABLED(ARC_SUPPORT)
/**
* Pre-generate radius offset values at 30 degree intervals to reduce CPU load.
*/
#define A_INT 30
#define _ANGS (360 / A_INT)
#define A_CNT (_ANGS / 2)
#define _IND(A) ((A + _ANGS * 8) % _ANGS)
#define _COS(A) (trig_table[_IND(A) % A_CNT] * (_IND(A) >= A_CNT ? -1 : 1))
#define _SIN(A) (-_COS((A + A_CNT / 2) % _ANGS))
#if A_CNT & 1
#error "A_CNT must be a positive value. Please change A_INT."
#endif
float trig_table[A_CNT];
for (uint8_t i = 0; i < A_CNT; i++)
trig_table[i] = INTERSECTION_CIRCLE_RADIUS * cos(RADIANS(i * A_INT));
#endif // !ARC_SUPPORT
mesh_index_pair location;
do {
location = g26_continue_with_closest
? find_closest_circle_to_print(current_position[X_AXIS], current_position[Y_AXIS])
: find_closest_circle_to_print(g26_x_pos, g26_y_pos); // Find the closest Mesh Intersection to where we are now.
if (location.x_index >= 0 && location.y_index >= 0) {
const float circle_x = _GET_MESH_X(location.x_index),
circle_y = _GET_MESH_Y(location.y_index);
// If this mesh location is outside the printable_radius, skip it.
if (!position_is_reachable(circle_x, circle_y)) continue;
// Determine where to start and end the circle,
// which is always drawn counter-clockwise.
const uint8_t xi = location.x_index, yi = location.y_index;
const bool f = yi == 0, r = xi >= GRID_MAX_POINTS_X - 1, b = yi >= GRID_MAX_POINTS_Y - 1;
#if ENABLED(ARC_SUPPORT)
#define ARC_LENGTH(quarters) (INTERSECTION_CIRCLE_RADIUS * M_PI * (quarters) / 2)
float sx = circle_x + INTERSECTION_CIRCLE_RADIUS, // default to full circle
ex = circle_x + INTERSECTION_CIRCLE_RADIUS,
sy = circle_y, ey = circle_y,
arc_length = ARC_LENGTH(4);
// Figure out where to start and end the arc - we always print counterclockwise
if (xi == 0) { // left edge
sx = f ? circle_x + INTERSECTION_CIRCLE_RADIUS : circle_x;
ex = b ? circle_x + INTERSECTION_CIRCLE_RADIUS : circle_x;
sy = f ? circle_y : circle_y - INTERSECTION_CIRCLE_RADIUS;
ey = b ? circle_y : circle_y + INTERSECTION_CIRCLE_RADIUS;
arc_length = (f || b) ? ARC_LENGTH(1) : ARC_LENGTH(2);
}
else if (r) { // right edge
sx = b ? circle_x - INTERSECTION_CIRCLE_RADIUS : circle_x;
ex = f ? circle_x - INTERSECTION_CIRCLE_RADIUS : circle_x;
sy = b ? circle_y : circle_y + INTERSECTION_CIRCLE_RADIUS;
ey = f ? circle_y : circle_y - INTERSECTION_CIRCLE_RADIUS;
arc_length = (f || b) ? ARC_LENGTH(1) : ARC_LENGTH(2);
}
else if (f) {
sx = circle_x + INTERSECTION_CIRCLE_RADIUS;
ex = circle_x - INTERSECTION_CIRCLE_RADIUS;
sy = ey = circle_y;
arc_length = ARC_LENGTH(2);
}
else if (b) {
sx = circle_x - INTERSECTION_CIRCLE_RADIUS;
ex = circle_x + INTERSECTION_CIRCLE_RADIUS;
sy = ey = circle_y;
arc_length = ARC_LENGTH(2);
}
const float arc_offset[2] = {
circle_x - sx,
circle_y - sy
};
const float dx_s = current_position[X_AXIS] - sx, // find our distance from the start of the actual circle
dy_s = current_position[Y_AXIS] - sy,
dist_start = HYPOT2(dx_s, dy_s);
const float endpoint[XYZE] = {
ex, ey,
g26_layer_height,
current_position[E_CART] + (arc_length * g26_e_axis_feedrate * g26_extrusion_multiplier)
};
if (dist_start > 2.0) {
retract_filament(destination);
//todo: parameterize the bump height with a define
move_to(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS] + 0.500, 0.0); // Z bump to minimize scraping
move_to(sx, sy, g26_layer_height + 0.500, 0.0); // Get to the starting point with no extrusion while bumped
}
move_to(sx, sy, g26_layer_height, 0.0); // Get to the starting point with no extrusion / un-Z bump
recover_filament(destination);
const float save_feedrate = feedrate_mm_s;
feedrate_mm_s = PLANNER_XY_FEEDRATE() / 10.0;
plan_arc(endpoint, arc_offset, false); // Draw a counter-clockwise arc
feedrate_mm_s = save_feedrate;
set_destination_from_current();
#if ENABLED(ULTIPANEL)
if (user_canceled()) goto LEAVE; // Check if the user wants to stop the Mesh Validation
#endif
#else // !ARC_SUPPORT
int8_t start_ind = -2, end_ind = 9; // Assume a full circle (from 5:00 to 5:00)
if (xi == 0) { // Left edge? Just right half.
start_ind = f ? 0 : -3; // 03:00 to 12:00 for front-left
end_ind = b ? 0 : 2; // 06:00 to 03:00 for back-left
}
else if (r) { // Right edge? Just left half.
start_ind = b ? 6 : 3; // 12:00 to 09:00 for front-right
end_ind = f ? 5 : 8; // 09:00 to 06:00 for back-right
}
else if (f) { // Front edge? Just back half.
start_ind = 0; // 03:00
end_ind = 5; // 09:00
}
else if (b) { // Back edge? Just front half.
start_ind = 6; // 09:00
end_ind = 11; // 03:00
}
for (int8_t ind = start_ind; ind <= end_ind; ind++) {
#if ENABLED(ULTIPANEL)
if (user_canceled()) goto LEAVE; // Check if the user wants to stop the Mesh Validation
#endif
float rx = circle_x + _COS(ind), // For speed, these are now a lookup table entry
ry = circle_y + _SIN(ind),
xe = circle_x + _COS(ind + 1),
ye = circle_y + _SIN(ind + 1);
#if IS_KINEMATIC
// Check to make sure this segment is entirely on the bed, skip if not.
if (!position_is_reachable(rx, ry) || !position_is_reachable(xe, ye)) continue;
#else // not, we need to skip
rx = constrain(rx, X_MIN_POS + 1, X_MAX_POS - 1); // This keeps us from bumping the endstops
ry = constrain(ry, Y_MIN_POS + 1, Y_MAX_POS - 1);
xe = constrain(xe, X_MIN_POS + 1, X_MAX_POS - 1);
ye = constrain(ye, Y_MIN_POS + 1, Y_MAX_POS - 1);
#endif
print_line_from_here_to_there(rx, ry, g26_layer_height, xe, ye, g26_layer_height);
SERIAL_FLUSH(); // Prevent host M105 buffer overrun.
}
#endif // !ARC_SUPPORT
if (look_for_lines_to_connect()) goto LEAVE;
}
SERIAL_FLUSH(); // Prevent host M105 buffer overrun.
} while (--g26_repeats && location.x_index >= 0 && location.y_index >= 0);
LEAVE:
lcd_setstatusPGM(PSTR("Leaving G26"), -1);
retract_filament(destination);
destination[Z_AXIS] = Z_CLEARANCE_BETWEEN_PROBES;
//debug_current_and_destination(PSTR("ready to do Z-Raise."));
move_to(destination, 0); // Raise the nozzle
//debug_current_and_destination(PSTR("done doing Z-Raise."));
destination[X_AXIS] = g26_x_pos; // Move back to the starting position
destination[Y_AXIS] = g26_y_pos;
//destination[Z_AXIS] = Z_CLEARANCE_BETWEEN_PROBES; // Keep the nozzle where it is
move_to(destination, 0); // Move back to the starting position
//debug_current_and_destination(PSTR("done doing X/Y move."));
#if ENABLED(ULTIPANEL)
lcd_external_control = false; // Give back control of the LCD Panel!
#endif
if (!g26_keep_heaters_on) {
#if HAS_HEATED_BED
thermalManager.setTargetBed(0);
#endif
thermalManager.setTargetHotend(0, 0);
}
}
#endif // G26_MESH_VALIDATION

337
Marlin/HAL.h Normal file
View File

@ -0,0 +1,337 @@
/* **************************************************************************
Marlin 3D Printer Firmware
Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
Copyright (c) 2016 Bob Cousins bobcousins42@googlemail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
****************************************************************************/
/**
* Description: HAL for __AVR__
*/
#ifndef _HAL_AVR_H_
#define _HAL_AVR_H_
// --------------------------------------------------------------------------
// Includes
// --------------------------------------------------------------------------
#include "fastio.h"
#include <stdint.h>
#include <Arduino.h>
#include <util/delay.h>
#include <avr/eeprom.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include <avr/io.h>
// --------------------------------------------------------------------------
// Defines
// --------------------------------------------------------------------------
//#define analogInputToDigitalPin(IO) IO
// Bracket code that shouldn't be interrupted
#ifndef CRITICAL_SECTION_START
#define CRITICAL_SECTION_START unsigned char _sreg = SREG; cli()
#define CRITICAL_SECTION_END SREG = _sreg
#endif
#define ISRS_ENABLED() TEST(SREG, SREG_I)
#define ENABLE_ISRS() sei()
#define DISABLE_ISRS() cli()
// --------------------------------------------------------------------------
// Types
// --------------------------------------------------------------------------
typedef uint16_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX 0xFFFF
typedef int8_t pin_t;
#define HAL_SERVO_LIB Servo
// --------------------------------------------------------------------------
// Public Variables
// --------------------------------------------------------------------------
//extern uint8_t MCUSR;
// --------------------------------------------------------------------------
// Public functions
// --------------------------------------------------------------------------
//void cli(void);
//void _delay_ms(const int delay);
inline void HAL_clear_reset_source(void) { MCUSR = 0; }
inline uint8_t HAL_get_reset_source(void) { return MCUSR; }
// eeprom
//void eeprom_write_byte(unsigned char *pos, unsigned char value);
//unsigned char eeprom_read_byte(unsigned char *pos);
// timers
#define HAL_TIMER_RATE ((F_CPU) / 8) // i.e., 2MHz or 2.5MHz
#define STEP_TIMER_NUM 1
#define TEMP_TIMER_NUM 0
#define PULSE_TIMER_NUM STEP_TIMER_NUM
#define TEMP_TIMER_FREQUENCY ((F_CPU) / 64.0 / 256.0)
#define STEPPER_TIMER_RATE HAL_TIMER_RATE
#define STEPPER_TIMER_PRESCALE 8
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // Cannot be of type double
#define PULSE_TIMER_RATE STEPPER_TIMER_RATE // frequency of pulse timer
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define ENABLE_STEPPER_DRIVER_INTERRUPT() SBI(TIMSK1, OCIE1A)
#define DISABLE_STEPPER_DRIVER_INTERRUPT() CBI(TIMSK1, OCIE1A)
#define STEPPER_ISR_ENABLED() TEST(TIMSK1, OCIE1A)
#define ENABLE_TEMPERATURE_INTERRUPT() SBI(TIMSK0, OCIE0B)
#define DISABLE_TEMPERATURE_INTERRUPT() CBI(TIMSK0, OCIE0B)
#define TEMPERATURE_ISR_ENABLED() TEST(TIMSK0, OCIE0B)
FORCE_INLINE void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
UNUSED(frequency);
switch (timer_num) {
case STEP_TIMER_NUM:
// waveform generation = 0100 = CTC
SET_WGM(1, CTC_OCRnA);
// output mode = 00 (disconnected)
SET_COMA(1, NORMAL);
// Set the timer pre-scaler
// Generally we use a divider of 8, resulting in a 2MHz timer
// frequency on a 16MHz MCU. If you are going to change this, be
// sure to regenerate speed_lookuptable.h with
// create_speed_lookuptable.py
SET_CS(1, PRESCALER_8); // CS 2 = 1/8 prescaler
// Init Stepper ISR to 122 Hz for quick starting
// (F_CPU) / (STEPPER_TIMER_PRESCALE) / frequency
OCR1A = 0x4000;
TCNT1 = 0;
break;
case TEMP_TIMER_NUM:
// Use timer0 for temperature measurement
// Interleave temperature interrupt with millies interrupt
OCR0B = 128;
break;
}
}
#define TIMER_OCR_1 OCR1A
#define TIMER_COUNTER_1 TCNT1
#define TIMER_OCR_0 OCR0A
#define TIMER_COUNTER_0 TCNT0
#define _CAT(a, ...) a ## __VA_ARGS__
#define HAL_timer_set_compare(timer, compare) (_CAT(TIMER_OCR_, timer) = compare)
#define HAL_timer_get_compare(timer) _CAT(TIMER_OCR_, timer)
#define HAL_timer_get_count(timer) _CAT(TIMER_COUNTER_, timer)
/**
* On AVR there is no hardware prioritization and preemption of
* interrupts, so this emulates it. The UART has first priority
* (otherwise, characters will be lost due to UART overflow).
* Then: Stepper, Endstops, Temperature, and -finally- all others.
*/
#define HAL_timer_isr_prologue(TIMER_NUM)
#define HAL_timer_isr_epilogue(TIMER_NUM)
/* 18 cycles maximum latency */
#define HAL_STEP_TIMER_ISR \
extern "C" void TIMER1_COMPA_vect (void) __attribute__ ((signal, naked, used, externally_visible)); \
extern "C" void TIMER1_COMPA_vect_bottom (void) asm ("TIMER1_COMPA_vect_bottom") __attribute__ ((used, externally_visible, noinline)); \
void TIMER1_COMPA_vect (void) { \
__asm__ __volatile__ ( \
A("push r16") /* 2 Save R16 */ \
A("in r16, __SREG__") /* 1 Get SREG */ \
A("push r16") /* 2 Save SREG into stack */ \
A("lds r16, %[timsk0]") /* 2 Load into R0 the Temperature timer Interrupt mask register */ \
A("push r16") /* 2 Save TIMSK0 into the stack */ \
A("andi r16,~%[msk0]") /* 1 Disable the temperature ISR */ \
A("sts %[timsk0], r16") /* 2 And set the new value */ \
A("lds r16, %[timsk1]") /* 2 Load into R0 the stepper timer Interrupt mask register [TIMSK1] */ \
A("andi r16,~%[msk1]") /* 1 Disable the stepper ISR */ \
A("sts %[timsk1], r16") /* 2 And set the new value */ \
A("push r16") /* 2 Save TIMSK1 into stack */ \
A("in r16, 0x3B") /* 1 Get RAMPZ register */ \
A("push r16") /* 2 Save RAMPZ into stack */ \
A("in r16, 0x3C") /* 1 Get EIND register */ \
A("push r0") /* C runtime can modify all the following registers without restoring them */ \
A("push r1") \
A("push r18") \
A("push r19") \
A("push r20") \
A("push r21") \
A("push r22") \
A("push r23") \
A("push r24") \
A("push r25") \
A("push r26") \
A("push r27") \
A("push r30") \
A("push r31") \
A("clr r1") /* C runtime expects this register to be 0 */ \
A("call TIMER1_COMPA_vect_bottom") /* Call the bottom handler - No inlining allowed, otherwise registers used are not saved */ \
A("pop r31") \
A("pop r30") \
A("pop r27") \
A("pop r26") \
A("pop r25") \
A("pop r24") \
A("pop r23") \
A("pop r22") \
A("pop r21") \
A("pop r20") \
A("pop r19") \
A("pop r18") \
A("pop r1") \
A("pop r0") \
A("out 0x3C, r16") /* 1 Restore EIND register */ \
A("pop r16") /* 2 Get the original RAMPZ register value */ \
A("out 0x3B, r16") /* 1 Restore RAMPZ register to its original value */ \
A("pop r16") /* 2 Get the original TIMSK1 value but with stepper ISR disabled */ \
A("ori r16,%[msk1]") /* 1 Reenable the stepper ISR */ \
A("cli") /* 1 Disable global interrupts - Reenabling Stepper ISR can reenter amd temperature can reenter, and we want that, if it happens, after this ISR has ended */ \
A("sts %[timsk1], r16") /* 2 And restore the old value - This reenables the stepper ISR */ \
A("pop r16") /* 2 Get the temperature timer Interrupt mask register [TIMSK0] */ \
A("sts %[timsk0], r16") /* 2 And restore the old value - This reenables the temperature ISR */ \
A("pop r16") /* 2 Get the old SREG value */ \
A("out __SREG__, r16") /* 1 And restore the SREG value */ \
A("pop r16") /* 2 Restore R16 value */ \
A("reti") /* 4 Return from interrupt */ \
: \
: [timsk0] "i" ((uint16_t)&TIMSK0), \
[timsk1] "i" ((uint16_t)&TIMSK1), \
[msk0] "M" ((uint8_t)(1<<OCIE0B)),\
[msk1] "M" ((uint8_t)(1<<OCIE1A)) \
: \
); \
} \
void TIMER1_COMPA_vect_bottom(void)
/* 14 cycles maximum latency */
#define HAL_TEMP_TIMER_ISR \
extern "C" void TIMER0_COMPB_vect (void) __attribute__ ((signal, naked, used, externally_visible)); \
extern "C" void TIMER0_COMPB_vect_bottom(void) asm ("TIMER0_COMPB_vect_bottom") __attribute__ ((used, externally_visible, noinline)); \
void TIMER0_COMPB_vect (void) { \
__asm__ __volatile__ ( \
A("push r16") /* 2 Save R16 */ \
A("in r16, __SREG__") /* 1 Get SREG */ \
A("push r16") /* 2 Save SREG into stack */ \
A("lds r16, %[timsk0]") /* 2 Load into R0 the Temperature timer Interrupt mask register */ \
A("andi r16,~%[msk0]") /* 1 Disable the temperature ISR */ \
A("sts %[timsk0], r16") /* 2 And set the new value */ \
A("sei") /* 1 Enable global interrupts - It is safe, as the temperature ISR is disabled, so we cannot reenter it */ \
A("push r16") /* 2 Save TIMSK0 into stack */ \
A("in r16, 0x3B") /* 1 Get RAMPZ register */ \
A("push r16") /* 2 Save RAMPZ into stack */ \
A("in r16, 0x3C") /* 1 Get EIND register */ \
A("push r0") /* C runtime can modify all the following registers without restoring them */ \
A("push r1") \
A("push r18") \
A("push r19") \
A("push r20") \
A("push r21") \
A("push r22") \
A("push r23") \
A("push r24") \
A("push r25") \
A("push r26") \
A("push r27") \
A("push r30") \
A("push r31") \
A("clr r1") /* C runtime expects this register to be 0 */ \
A("call TIMER0_COMPB_vect_bottom") /* Call the bottom handler - No inlining allowed, otherwise registers used are not saved */ \
A("pop r31") \
A("pop r30") \
A("pop r27") \
A("pop r26") \
A("pop r25") \
A("pop r24") \
A("pop r23") \
A("pop r22") \
A("pop r21") \
A("pop r20") \
A("pop r19") \
A("pop r18") \
A("pop r1") \
A("pop r0") \
A("out 0x3C, r16") /* 1 Restore EIND register */ \
A("pop r16") /* 2 Get the original RAMPZ register value */ \
A("out 0x3B, r16") /* 1 Restore RAMPZ register to its original value */ \
A("pop r16") /* 2 Get the original TIMSK0 value but with temperature ISR disabled */ \
A("ori r16,%[msk0]") /* 1 Enable temperature ISR */ \
A("cli") /* 1 Disable global interrupts - We must do this, as we will reenable the temperature ISR, and we don't want to reenter this handler until the current one is done */ \
A("sts %[timsk0], r16") /* 2 And restore the old value */ \
A("pop r16") /* 2 Get the old SREG */ \
A("out __SREG__, r16") /* 1 And restore the SREG value */ \
A("pop r16") /* 2 Restore R16 */ \
A("reti") /* 4 Return from interrupt */ \
: \
: [timsk0] "i"((uint16_t)&TIMSK0), \
[msk0] "M" ((uint8_t)(1<<OCIE0B)) \
: \
); \
} \
void TIMER0_COMPB_vect_bottom(void)
// ADC
#ifdef DIDR2
#define HAL_ANALOG_SELECT(pin) do{ if (pin < 8) SBI(DIDR0, pin); else SBI(DIDR2, pin & 0x07); }while(0)
#else
#define HAL_ANALOG_SELECT(pin) do{ SBI(DIDR0, pin); }while(0)
#endif
inline void HAL_adc_init(void) {
ADCSRA = _BV(ADEN) | _BV(ADSC) | _BV(ADIF) | 0x07;
DIDR0 = 0;
#ifdef DIDR2
DIDR2 = 0;
#endif
}
#define SET_ADMUX_ADCSRA(pin) ADMUX = _BV(REFS0) | (pin & 0x07); SBI(ADCSRA, ADSC)
#ifdef MUX5
#define HAL_START_ADC(pin) if (pin > 7) ADCSRB = _BV(MUX5); else ADCSRB = 0; SET_ADMUX_ADCSRA(pin)
#else
#define HAL_START_ADC(pin) ADCSRB = 0; SET_ADMUX_ADCSRA(pin)
#endif
#define HAL_READ_ADC() ADC
#define HAL_ADC_READY() !TEST(ADCSRA, ADSC)
#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
#endif // _HAL_AVR_H_

File diff suppressed because it is too large Load Diff

342
Marlin/I2CPositionEncoder.h Normal file
View File

@ -0,0 +1,342 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016, 2017 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef I2CPOSENC_H
#define I2CPOSENC_H
#include "MarlinConfig.h"
#if ENABLED(I2C_POSITION_ENCODERS)
#include "enum.h"
#include "macros.h"
#include "types.h"
#include <Wire.h>
//=========== Advanced / Less-Common Encoder Configuration Settings ==========
#define I2CPE_EC_THRESH_PROPORTIONAL // if enabled adjusts the error correction threshold
// proportional to the current speed of the axis allows
// for very small error margin at low speeds without
// stuttering due to reading latency at high speeds
#define I2CPE_DEBUG // enable encoder-related debug serial echos
#define I2CPE_REBOOT_TIME 5000 // time we wait for an encoder module to reboot
// after changing address.
#define I2CPE_MAG_SIG_GOOD 0
#define I2CPE_MAG_SIG_MID 1
#define I2CPE_MAG_SIG_BAD 2
#define I2CPE_MAG_SIG_NF 255
#define I2CPE_REQ_REPORT 0
#define I2CPE_RESET_COUNT 1
#define I2CPE_SET_ADDR 2
#define I2CPE_SET_REPORT_MODE 3
#define I2CPE_CLEAR_EEPROM 4
#define I2CPE_LED_PAR_MODE 10
#define I2CPE_LED_PAR_BRT 11
#define I2CPE_LED_PAR_RATE 14
#define I2CPE_REPORT_DISTANCE 0
#define I2CPE_REPORT_STRENGTH 1
#define I2CPE_REPORT_VERSION 2
// Default I2C addresses
#define I2CPE_PRESET_ADDR_X 30
#define I2CPE_PRESET_ADDR_Y 31
#define I2CPE_PRESET_ADDR_Z 32
#define I2CPE_PRESET_ADDR_E 33
#define I2CPE_DEF_AXIS X_AXIS
#define I2CPE_DEF_ADDR I2CPE_PRESET_ADDR_X
// Error event counter; tracks how many times there is an error exceeding a certain threshold
#define I2CPE_ERR_CNT_THRESH 3.00
#define I2CPE_ERR_CNT_DEBOUNCE_MS 2000
#if ENABLED(I2CPE_ERR_ROLLING_AVERAGE)
#define I2CPE_ERR_ARRAY_SIZE 32
#define I2CPE_ERR_PRST_ARRAY_SIZE 10
#endif
// Error Correction Methods
#define I2CPE_ECM_NONE 0
#define I2CPE_ECM_MICROSTEP 1
#define I2CPE_ECM_PLANNER 2
#define I2CPE_ECM_STALLDETECT 3
// Encoder types
#define I2CPE_ENC_TYPE_ROTARY 0
#define I2CPE_ENC_TYPE_LINEAR 1
// Parser
#define I2CPE_PARSE_ERR 1
#define I2CPE_PARSE_OK 0
#define LOOP_PE(VAR) LOOP_L_N(VAR, I2CPE_ENCODER_CNT)
#define CHECK_IDX() do{ if (!WITHIN(idx, 0, I2CPE_ENCODER_CNT - 1)) return; }while(0)
typedef union {
volatile int32_t val = 0;
uint8_t bval[4];
} i2cLong;
class I2CPositionEncoder {
private:
AxisEnum encoderAxis = I2CPE_DEF_AXIS;
uint8_t i2cAddress = I2CPE_DEF_ADDR,
ecMethod = I2CPE_DEF_EC_METHOD,
type = I2CPE_DEF_TYPE,
H = I2CPE_MAG_SIG_NF; // Magnetic field strength
int encoderTicksPerUnit = I2CPE_DEF_ENC_TICKS_UNIT,
stepperTicks = I2CPE_DEF_TICKS_REV,
errorCount = 0,
errorPrev = 0;
float ecThreshold = I2CPE_DEF_EC_THRESH;
bool homed = false,
trusted = false,
initialised = false,
active = false,
invert = false,
ec = true;
int32_t zeroOffset = 0,
lastPosition = 0,
position;
millis_t lastPositionTime = 0,
nextErrorCountTime = 0,
lastErrorTime;
#if ENABLED(I2CPE_ERR_ROLLING_AVERAGE)
uint8_t errIdx = 0, errPrstIdx = 0;
int err[I2CPE_ERR_ARRAY_SIZE] = { 0 },
errPrst[I2CPE_ERR_PRST_ARRAY_SIZE] = { 0 };
#endif
public:
void init(const uint8_t address, const AxisEnum axis);
void reset();
void update();
void set_homed();
int32_t get_raw_count();
FORCE_INLINE float mm_from_count(const int32_t count) {
switch (type) {
default: return -1;
case I2CPE_ENC_TYPE_LINEAR:
return count / encoderTicksPerUnit;
case I2CPE_ENC_TYPE_ROTARY:
return (count * stepperTicks) / (encoderTicksPerUnit * planner.axis_steps_per_mm[encoderAxis]);
}
}
FORCE_INLINE float get_position_mm() { return mm_from_count(get_position()); }
FORCE_INLINE int32_t get_position() { return get_raw_count() - zeroOffset; }
int32_t get_axis_error_steps(const bool report);
float get_axis_error_mm(const bool report);
void calibrate_steps_mm(const uint8_t iter);
bool passes_test(const bool report);
bool test_axis(void);
FORCE_INLINE int get_error_count(void) { return errorCount; }
FORCE_INLINE void set_error_count(const int newCount) { errorCount = newCount; }
FORCE_INLINE uint8_t get_address() { return i2cAddress; }
FORCE_INLINE void set_address(const uint8_t addr) { i2cAddress = addr; }
FORCE_INLINE bool get_active(void) { return active; }
FORCE_INLINE void set_active(const bool a) { active = a; }
FORCE_INLINE void set_inverted(const bool i) { invert = i; }
FORCE_INLINE AxisEnum get_axis() { return encoderAxis; }
FORCE_INLINE bool get_ec_enabled() { return ec; }
FORCE_INLINE void set_ec_enabled(const bool enabled) { ec = enabled; }
FORCE_INLINE uint8_t get_ec_method() { return ecMethod; }
FORCE_INLINE void set_ec_method(const byte method) { ecMethod = method; }
FORCE_INLINE float get_ec_threshold() { return ecThreshold; }
FORCE_INLINE void set_ec_threshold(const float newThreshold) { ecThreshold = newThreshold; }
FORCE_INLINE int get_encoder_ticks_mm() {
switch (type) {
default: return 0;
case I2CPE_ENC_TYPE_LINEAR:
return encoderTicksPerUnit;
case I2CPE_ENC_TYPE_ROTARY:
return (int)((encoderTicksPerUnit / stepperTicks) * planner.axis_steps_per_mm[encoderAxis]);
}
}
FORCE_INLINE int get_ticks_unit() { return encoderTicksPerUnit; }
FORCE_INLINE void set_ticks_unit(const int ticks) { encoderTicksPerUnit = ticks; }
FORCE_INLINE uint8_t get_type() { return type; }
FORCE_INLINE void set_type(const byte newType) { type = newType; }
FORCE_INLINE int get_stepper_ticks() { return stepperTicks; }
FORCE_INLINE void set_stepper_ticks(const int ticks) { stepperTicks = ticks; }
};
class I2CPositionEncodersMgr {
private:
static bool I2CPE_anyaxis;
static uint8_t I2CPE_addr, I2CPE_idx;
public:
static void init(void);
// consider only updating one endoder per call / tick if encoders become too time intensive
static void update(void) { LOOP_PE(i) encoders[i].update(); }
static void homed(const AxisEnum axis) {
LOOP_PE(i)
if (encoders[i].get_axis() == axis) encoders[i].set_homed();
}
static void report_position(const int8_t idx, const bool units, const bool noOffset);
static void report_status(const int8_t idx) {
CHECK_IDX();
SERIAL_ECHOPAIR("Encoder ",idx);
SERIAL_ECHOPGM(": ");
encoders[idx].get_raw_count();
encoders[idx].passes_test(true);
}
static void report_error(const int8_t idx) {
CHECK_IDX();
encoders[idx].get_axis_error_steps(true);
}
static void test_axis(const int8_t idx) {
CHECK_IDX();
encoders[idx].test_axis();
}
static void calibrate_steps_mm(const int8_t idx, const int iterations) {
CHECK_IDX();
encoders[idx].calibrate_steps_mm(iterations);
}
static void change_module_address(const uint8_t oldaddr, const uint8_t newaddr);
static void report_module_firmware(const uint8_t address);
static void report_error_count(const int8_t idx, const AxisEnum axis) {
CHECK_IDX();
SERIAL_ECHOPAIR("Error count on ", axis_codes[axis]);
SERIAL_ECHOLNPAIR(" axis is ", encoders[idx].get_error_count());
}
static void reset_error_count(const int8_t idx, const AxisEnum axis) {
CHECK_IDX();
encoders[idx].set_error_count(0);
SERIAL_ECHOPAIR("Error count on ", axis_codes[axis]);
SERIAL_ECHOLNPGM(" axis has been reset.");
}
static void enable_ec(const int8_t idx, const bool enabled, const AxisEnum axis) {
CHECK_IDX();
encoders[idx].set_ec_enabled(enabled);
SERIAL_ECHOPAIR("Error correction on ", axis_codes[axis]);
SERIAL_ECHOPGM(" axis is ");
serialprintPGM(encoders[idx].get_ec_enabled() ? PSTR("en") : PSTR("dis"));
SERIAL_ECHOLNPGM("abled.");
}
static void set_ec_threshold(const int8_t idx, const float newThreshold, const AxisEnum axis) {
CHECK_IDX();
encoders[idx].set_ec_threshold(newThreshold);
SERIAL_ECHOPAIR("Error correct threshold for ", axis_codes[axis]);
SERIAL_ECHOPAIR_F(" axis set to ", newThreshold);
SERIAL_ECHOLNPGM("mm.");
}
static void get_ec_threshold(const int8_t idx, const AxisEnum axis) {
CHECK_IDX();
const float threshold = encoders[idx].get_ec_threshold();
SERIAL_ECHOPAIR("Error correct threshold for ", axis_codes[axis]);
SERIAL_ECHOPAIR_F(" axis is ", threshold);
SERIAL_ECHOLNPGM("mm.");
}
static int8_t idx_from_axis(const AxisEnum axis) {
LOOP_PE(i)
if (encoders[i].get_axis() == axis) return i;
return -1;
}
static int8_t idx_from_addr(const uint8_t addr) {
LOOP_PE(i)
if (encoders[i].get_address() == addr) return i;
return -1;
}
static int8_t parse();
static void M860();
static void M861();
static void M862();
static void M863();
static void M864();
static void M865();
static void M866();
static void M867();
static void M868();
static void M869();
static I2CPositionEncoder encoders[I2CPE_ENCODER_CNT];
};
extern I2CPositionEncodersMgr I2CPEM;
FORCE_INLINE static void gcode_M860() { I2CPEM.M860(); }
FORCE_INLINE static void gcode_M861() { I2CPEM.M861(); }
FORCE_INLINE static void gcode_M862() { I2CPEM.M862(); }
FORCE_INLINE static void gcode_M863() { I2CPEM.M863(); }
FORCE_INLINE static void gcode_M864() { I2CPEM.M864(); }
FORCE_INLINE static void gcode_M865() { I2CPEM.M865(); }
FORCE_INLINE static void gcode_M866() { I2CPEM.M866(); }
FORCE_INLINE static void gcode_M867() { I2CPEM.M867(); }
FORCE_INLINE static void gcode_M868() { I2CPEM.M868(); }
FORCE_INLINE static void gcode_M869() { I2CPEM.M869(); }
#endif //I2C_POSITION_ENCODERS
#endif //I2CPOSENC_H

View File

@ -0,0 +1,332 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* M100 Free Memory Watcher
*
* This code watches the free memory block between the bottom of the heap and the top of the stack.
* This memory block is initialized and watched via the M100 command.
*
* M100 I Initializes the free memory block and prints vitals statistics about the area
*
* M100 F Identifies how much of the free memory block remains free and unused. It also
* detects and reports any corruption within the free memory block that may have
* happened due to errant firmware.
*
* M100 D Does a hex display of the free memory block along with a flag for any errant
* data that does not match the expected value.
*
* M100 C x Corrupts x locations within the free memory block. This is useful to check the
* correctness of the M100 F and M100 D commands.
*
* Also, there are two support functions that can be called from a developer's C code.
*
* uint16_t check_for_free_memory_corruption(const char * const ptr);
* void M100_dump_routine(const char * const title, const char *start, const char *end);
*
* Initial version by Roxy-3D
*/
#include "MarlinConfig.h"
#if ENABLED(M100_FREE_MEMORY_WATCHER)
#define M100_FREE_MEMORY_DUMPER // Enable for the `M100 D` Dump sub-command
#define M100_FREE_MEMORY_CORRUPTOR // Enable for the `M100 C` Corrupt sub-command
#include "Marlin.h"
#include "parser.h"
#include "hex_print_routines.h"
#define TEST_BYTE ((char) 0xE5)
extern char* __brkval;
extern size_t __heap_start, __heap_end, __flp;
extern char __bss_end;
//
// Utility functions
//
#define END_OF_HEAP() (__brkval ? __brkval : &__bss_end)
int check_for_free_memory_corruption(const char * const title);
// Location of a variable on its stack frame. Returns a value above
// the stack (once the function returns to the caller).
char* top_of_stack() {
char x;
return &x + 1; // x is pulled on return;
}
// Count the number of test bytes at the specified location.
int16_t count_test_bytes(const char * const ptr) {
for (uint16_t i = 0; i < 32000; i++)
if (((char) ptr[i]) != TEST_BYTE)
return i - 1;
return -1;
}
//
// M100 sub-commands
//
#if ENABLED(M100_FREE_MEMORY_DUMPER)
/**
* M100 D
* Dump the free memory block from __brkval to the stack pointer.
* malloc() eats memory from the start of the block and the stack grows
* up from the bottom of the block. Solid test bytes indicate nothing has
* used that memory yet. There should not be anything but test bytes within
* the block. If so, it may indicate memory corruption due to a bad pointer.
* Unexpected bytes are flagged in the right column.
*/
void dump_free_memory(const char *ptr, const char *sp) {
//
// Start and end the dump on a nice 16 byte boundary
// (even though the values are not 16-byte aligned).
//
ptr = (char *)((uint16_t)ptr & 0xFFF0); // Align to 16-byte boundary
sp = (char *)((uint16_t)sp | 0x000F); // Align sp to the 15th byte (at or above sp)
// Dump command main loop
while (ptr < sp) {
print_hex_word((uint16_t)ptr); // Print the address
SERIAL_CHAR(':');
for (uint8_t i = 0; i < 16; i++) { // and 16 data bytes
if (i == 8) SERIAL_CHAR('-');
print_hex_byte(ptr[i]);
SERIAL_CHAR(' ');
}
safe_delay(25);
SERIAL_CHAR('|'); // Point out non test bytes
for (uint8_t i = 0; i < 16; i++) {
char ccc = (char)ptr[i]; // cast to char before automatically casting to char on assignment, in case the compiler is broken
if (&ptr[i] >= (const char*)command_queue && &ptr[i] < (const char*)(command_queue + sizeof(command_queue))) { // Print out ASCII in the command buffer area
if (!WITHIN(ccc, ' ', 0x7E)) ccc = ' ';
}
else { // If not in the command buffer area, flag bytes that don't match the test byte
ccc = (ccc == TEST_BYTE) ? ' ' : '?';
}
SERIAL_CHAR(ccc);
}
SERIAL_EOL();
ptr += 16;
safe_delay(25);
idle();
}
}
void M100_dump_routine(const char * const title, const char *start, const char *end) {
SERIAL_ECHOLN(title);
//
// Round the start and end locations to produce full lines of output
//
start = (char*)((uint16_t) start & 0xFFF0);
end = (char*)((uint16_t) end | 0x000F);
dump_free_memory(start, end);
}
#endif // M100_FREE_MEMORY_DUMPER
/**
* M100 F
* Return the number of free bytes in the memory pool,
* with other vital statistics defining the pool.
*/
void free_memory_pool_report(char * const ptr, const int16_t size) {
int16_t max_cnt = -1, block_cnt = 0;
char *max_addr = NULL;
// Find the longest block of test bytes in the buffer
for (int16_t i = 0; i < size; i++) {
char *addr = ptr + i;
if (*addr == TEST_BYTE) {
const int16_t j = count_test_bytes(addr);
if (j > 8) {
SERIAL_ECHOPAIR("Found ", j);
SERIAL_ECHOLNPAIR(" bytes free at ", hex_address(addr));
if (j > max_cnt) {
max_cnt = j;
max_addr = addr;
}
i += j;
block_cnt++;
}
}
}
if (block_cnt > 1) {
SERIAL_ECHOLNPGM("\nMemory Corruption detected in free memory area.");
SERIAL_ECHOPAIR("\nLargest free block is ", max_cnt);
SERIAL_ECHOLNPAIR(" bytes at ", hex_address(max_addr));
}
SERIAL_ECHOLNPAIR("check_for_free_memory_corruption() = ", check_for_free_memory_corruption("M100 F "));
}
#if ENABLED(M100_FREE_MEMORY_CORRUPTOR)
/**
* M100 C<num>
* Corrupt <num> locations in the free memory pool and report the corrupt addresses.
* This is useful to check the correctness of the M100 D and the M100 F commands.
*/
void corrupt_free_memory(char *ptr, const uint16_t size) {
ptr += 8;
const uint16_t near_top = top_of_stack() - ptr - 250, // -250 to avoid interrupt activity that's altered the stack.
j = near_top / (size + 1);
SERIAL_ECHOLNPGM("Corrupting free memory block.\n");
for (uint16_t i = 1; i <= size; i++) {
char * const addr = ptr + i * j;
*addr = i;
SERIAL_ECHOPAIR("\nCorrupting address: ", hex_address(addr));
}
SERIAL_EOL();
}
#endif // M100_FREE_MEMORY_CORRUPTOR
/**
* M100 I
* Init memory for the M100 tests. (Automatically applied on the first M100.)
*/
void init_free_memory(char *ptr, int16_t size) {
SERIAL_ECHOLNPGM("Initializing free memory block.\n\n");
size -= 250; // -250 to avoid interrupt activity that's altered the stack.
if (size < 0) {
SERIAL_ECHOLNPGM("Unable to initialize.\n");
return;
}
ptr += 8; // move a few bytes away from the heap just because we don't want
// to be altering memory that close to it.
memset(ptr, TEST_BYTE, size);
SERIAL_ECHO(size);
SERIAL_ECHOLNPGM(" bytes of memory initialized.\n");
for (int16_t i = 0; i < size; i++) {
if (ptr[i] != TEST_BYTE) {
SERIAL_ECHOPAIR("? address : ", hex_address(ptr + i));
SERIAL_ECHOLNPAIR("=", hex_byte(ptr[i]));
SERIAL_EOL();
}
}
}
/**
* M100: Free Memory Check
*/
void gcode_M100() {
SERIAL_ECHOPAIR("\n__brkval : ", hex_address(__brkval));
SERIAL_ECHOPAIR("\n__bss_end : ", hex_address(&__bss_end));
char *ptr = END_OF_HEAP(), *sp = top_of_stack();
SERIAL_ECHOPAIR("\nstart of free space : ", hex_address(ptr));
SERIAL_ECHOLNPAIR("\nStack Pointer : ", hex_address(sp));
// Always init on the first invocation of M100
static bool m100_not_initialized = true;
if (m100_not_initialized || parser.seen('I')) {
m100_not_initialized = false;
init_free_memory(ptr, sp - ptr);
}
#if ENABLED(M100_FREE_MEMORY_DUMPER)
if (parser.seen('D'))
return dump_free_memory(ptr, sp);
#endif
if (parser.seen('F'))
return free_memory_pool_report(ptr, sp - ptr);
#if ENABLED(M100_FREE_MEMORY_CORRUPTOR)
if (parser.seen('C'))
return corrupt_free_memory(ptr, parser.value_int());
#endif
}
int check_for_free_memory_corruption(const char * const title) {
SERIAL_ECHO(title);
char *ptr = END_OF_HEAP(), *sp = top_of_stack();
int n = sp - ptr;
SERIAL_ECHOPAIR("\nfmc() n=", n);
SERIAL_ECHOPAIR("\n&__brkval: ", hex_address(&__brkval));
SERIAL_ECHOPAIR("=", hex_address(__brkval));
SERIAL_ECHOPAIR("\n__bss_end: ", hex_address(&__bss_end));
SERIAL_ECHOPAIR(" sp=", hex_address(sp));
if (sp < ptr) {
SERIAL_ECHOPGM(" sp < Heap ");
// SET_INPUT_PULLUP(63); // if the developer has a switch wired up to their controller board
// safe_delay(5); // this code can be enabled to pause the display as soon as the
// while ( READ(63)) // malfunction is detected. It is currently defaulting to a switch
// idle(); // being on pin-63 which is unassigend and available on most controller
// safe_delay(20); // boards.
// while ( !READ(63))
// idle();
safe_delay(20);
#ifdef M100_FREE_MEMORY_DUMPER
M100_dump_routine(" Memory corruption detected with sp<Heap\n", (char*)0x1B80, (char*)0x21FF);
#endif
}
// Scan through the range looking for the biggest block of 0xE5's we can find
int block_cnt = 0;
for (int i = 0; i < n; i++) {
if (ptr[i] == TEST_BYTE) {
int16_t j = count_test_bytes(ptr + i);
if (j > 8) {
// SERIAL_ECHOPAIR("Found ", j);
// SERIAL_ECHOLNPAIR(" bytes free at ", hex_address(ptr + i));
i += j;
block_cnt++;
SERIAL_ECHOPAIR(" (", block_cnt);
SERIAL_ECHOPAIR(") found=", j);
SERIAL_ECHOPGM(" ");
}
}
}
SERIAL_ECHOPAIR(" block_found=", block_cnt);
if (block_cnt != 1 || __brkval != 0x0000)
SERIAL_ECHOLNPGM("\nMemory Corruption detected in free memory area.");
if (block_cnt == 0) // Make sure the special case of no free blocks shows up as an
block_cnt = -1; // error to the calling code!
SERIAL_ECHOPGM(" return=");
if (block_cnt == 1) {
SERIAL_CHAR('0'); // if the block_cnt is 1, nothing has broken up the free memory
SERIAL_EOL(); // area and it is appropriate to say 'no corruption'.
return 0;
}
SERIAL_ECHOLNPGM("true");
return block_cnt;
}
#endif // M100_FREE_MEMORY_WATCHER

686
Marlin/Makefile Normal file
View File

@ -0,0 +1,686 @@
# Marlin Firmware Arduino Project Makefile
#
# Makefile Based on:
# Arduino 0011 Makefile
# Arduino adaptation by mellis, eighthave, oli.keller
# Marlin adaption by Daid
#
# This has been tested with Arduino 0022.
#
# This makefile allows you to build sketches from the command line
# without the Arduino environment (or Java).
#
# Detailed instructions for using the makefile:
#
# 1. Modify the line containing "ARDUINO_INSTALL_DIR" to point to the directory that
# contains the Arduino installation (for example, under Mac OS X, this
# might be /Applications/Arduino.app/Contents/Resources/Java).
#
# 2. Modify the line containing "UPLOAD_PORT" to refer to the filename
# representing the USB or serial connection to your Arduino board
# (e.g. UPLOAD_PORT = /dev/tty.USB0). If the exact name of this file
# changes, you can use * as a wild card (e.g. UPLOAD_PORT = /dev/tty.usb*).
#
# 3. Set the line containing "MCU" to match your board's processor.
# Older one's are atmega8 based, newer ones like Arduino Mini, Bluetooth
# or Diecimila have the atmega168. If you're using a LilyPad Arduino,
# change F_CPU to 8000000. If you are using Gen7 electronics, you
# probably need to use 20000000. Either way, you must regenerate
# the speed lookup table with create_speed_lookuptable.py.
#
# 4. Type "make" and press enter to compile/verify your program.
#
# 5. Type "make upload", reset your Arduino board, and press enter to
# upload your program to the Arduino board.
#
# Note that all settings at the top of this file can be overriden from
# the command line with, for example, "make HARDWARE_MOTHERBOARD=71"
#
# To compile for RAMPS (atmega2560) with Arduino 1.6.9 at root/arduino you would use...
#
# make ARDUINO_VERSION=10609 AVR_TOOLS_PATH=/root/arduino/hardware/tools/avr/bin/ \
# HARDWARE_MOTHERBOARD=33 ARDUINO_INSTALL_DIR=/root/arduino
#
# To compile and upload simply add "upload" to the end of the line...
#
# make ARDUINO_VERSION=10609 AVR_TOOLS_PATH=/root/arduino/hardware/tools/avr/bin/ \
# HARDWARE_MOTHERBOARD=33 ARDUINO_INSTALL_DIR=/root/arduino upload
#
# If uploading doesn't work try adding the parameter "AVRDUDE_PROGRAMMER=wiring" or
# start upload manually (using stk500) like so:
#
# avrdude -C /root/arduino/hardware/tools/avr/etc/avrdude.conf -v -p m2560 -c stk500 \
# -U flash:w:applet/Marlin.hex:i -P /dev/ttyUSB0
#
# Or, try disconnecting USB to power down and then reconnecting before running avrdude.
#
# This defines the board to compile for (see boards.h for your board's ID)
HARDWARE_MOTHERBOARD ?= 11
# Arduino source install directory, and version number
# On most linuxes this will be /usr/share/arduino
ARDUINO_INSTALL_DIR ?= ${HOME}/Arduino
ARDUINO_VERSION ?= 106
# You can optionally set a path to the avr-gcc tools. Requires a trailing slash. (ex: /usr/local/avr-gcc/bin)
AVR_TOOLS_PATH ?=
#Programmer configuration
UPLOAD_RATE ?= 57600
AVRDUDE_PROGRAMMER ?= arduino
# on most linuxes this will be /dev/ttyACM0 or /dev/ttyACM1
UPLOAD_PORT ?= /dev/ttyUSB0
#Directory used to build files in, contains all the build files, from object files to the final hex file
#on linux it is best to put an absolute path like /home/username/tmp .
BUILD_DIR ?= applet
# This defines whether Liquid_TWI2 support will be built
LIQUID_TWI2 ?= 0
# this defines if Wire is needed
WIRE ?= 0
# this defines if U8GLIB is needed (may require RELOC_WORKAROUND)
U8GLIB ?= 1
# this defines whether to add a workaround for the avr-gcc relocation bug
# https://www.stix.id.au/wiki/AVR_relocation_truncations_workaround
RELOC_WORKAROUND ?= 1
############################################################################
# Below here nothing should be changed...
# Here the Arduino variant is selected by the board type
# HARDWARE_VARIANT = "arduino", "Sanguino", "Gen7", ...
# MCU = "atmega1280", "Mega2560", "atmega2560", "atmega644p", ...
ifeq ($(HARDWARE_MOTHERBOARD),0)
# No motherboard selected
#
# RAMPS 1.3 / 1.4 - ATmega1280, ATmega2560
#
# MEGA/RAMPS up to 1.2
else ifeq ($(HARDWARE_MOTHERBOARD),3)
# RAMPS 1.3 (Power outputs: Hotend, Fan, Bed)
else ifeq ($(HARDWARE_MOTHERBOARD),33)
# RAMPS 1.3 (Power outputs: Hotend0, Hotend1, Bed)
else ifeq ($(HARDWARE_MOTHERBOARD),34)
# RAMPS 1.3 (Power outputs: Hotend, Fan0, Fan1)
else ifeq ($(HARDWARE_MOTHERBOARD),35)
# RAMPS 1.3 (Power outputs: Hotend0, Hotend1, Fan)
else ifeq ($(HARDWARE_MOTHERBOARD),36)
# RAMPS 1.3 (Power outputs: Spindle, Controller Fan)
else ifeq ($(HARDWARE_MOTHERBOARD),38)
# RAMPS 1.4 (Power outputs: Hotend, Fan, Bed)
else ifeq ($(HARDWARE_MOTHERBOARD),43)
# RAMPS 1.4 (Power outputs: Hotend0, Hotend1, Bed)
else ifeq ($(HARDWARE_MOTHERBOARD),44)
# RAMPS 1.4 (Power outputs: Hotend, Fan0, Fan1)
else ifeq ($(HARDWARE_MOTHERBOARD),45)
# RAMPS 1.4 (Power outputs: Hotend0, Hotend1, Fan)
else ifeq ($(HARDWARE_MOTHERBOARD),46)
# RAMPS 1.4 (Power outputs: Spindle, Controller Fan)
else ifeq ($(HARDWARE_MOTHERBOARD),48)
# RAMPS Plus 3DYMY (Power outputs: Hotend, Fan, Bed)
else ifeq ($(HARDWARE_MOTHERBOARD),143)
# RAMPS Plus 3DYMY (Power outputs: Hotend0, Hotend1, Bed)
else ifeq ($(HARDWARE_MOTHERBOARD),144)
# RAMPS Plus 3DYMY (Power outputs: Hotend, Fan0, Fan1)
else ifeq ($(HARDWARE_MOTHERBOARD),145)
# RAMPS Plus 3DYMY (Power outputs: Hotend0, Hotend1, Fan)
else ifeq ($(HARDWARE_MOTHERBOARD),146)
# RAMPS Plus 3DYMY (Power outputs: Spindle, Controller Fan)
else ifeq ($(HARDWARE_MOTHERBOARD),148)
#
# RAMPS Derivatives - ATmega1280, ATmega2560
#
# 3Drag Controller
else ifeq ($(HARDWARE_MOTHERBOARD),77)
# Velleman K8200 Controller (derived from 3Drag Controller)
else ifeq ($(HARDWARE_MOTHERBOARD),78)
# Velleman K8400 Controller (derived from 3Drag Controller)
else ifeq ($(HARDWARE_MOTHERBOARD),79)
# 2PrintBeta BAM&DICE with STK drivers
else ifeq ($(HARDWARE_MOTHERBOARD),401)
# 2PrintBeta BAM&DICE Due with STK drivers
else ifeq ($(HARDWARE_MOTHERBOARD),402)
# MKS BASE v1.0
else ifeq ($(HARDWARE_MOTHERBOARD),40)
# MKS v1.5 with Allegro A4982 stepper drivers
else ifeq ($(HARDWARE_MOTHERBOARD),405)
# MKS BASE 1.0 with Heroic HR4982 stepper drivers
else ifeq ($(HARDWARE_MOTHERBOARD),41)
# MKS GEN v1.3 or 1.4
else ifeq ($(HARDWARE_MOTHERBOARD),47)
# MKS GEN L
else ifeq ($(HARDWARE_MOTHERBOARD),53)
# zrib V2.0 control board (Chinese knock off RAMPS replica)
else ifeq ($(HARDWARE_MOTHERBOARD),504)
# Felix 2.0+ Electronics Board (RAMPS like)
else ifeq ($(HARDWARE_MOTHERBOARD),37)
# Invent-A-Part RigidBoard
else ifeq ($(HARDWARE_MOTHERBOARD),42)
# Invent-A-Part RigidBoard V2
else ifeq ($(HARDWARE_MOTHERBOARD),52)
# Sainsmart 2-in-1 board
else ifeq ($(HARDWARE_MOTHERBOARD),49)
# Ultimaker
else ifeq ($(HARDWARE_MOTHERBOARD),7)
# Ultimaker (Older electronics. Pre 1.5.4. This is rare)
else ifeq ($(HARDWARE_MOTHERBOARD),71)
MCU ?= atmega1280
# Azteeg X3
else ifeq ($(HARDWARE_MOTHERBOARD),67)
# Azteeg X3 Pro
else ifeq ($(HARDWARE_MOTHERBOARD),68)
# Ultimainboard 2.x (Uses TEMP_SENSOR 20)
else ifeq ($(HARDWARE_MOTHERBOARD),72)
# Rumba
else ifeq ($(HARDWARE_MOTHERBOARD),80)
# bq ZUM Mega 3D
else ifeq ($(HARDWARE_MOTHERBOARD),503)
# MakeBoard Mini v2.1.2 is a control board sold by MicroMake
else ifeq ($(HARDWARE_MOTHERBOARD),431)
# TriGorilla Anycubic version 1.3 based on RAMPS EFB
else ifeq ($(HARDWARE_MOTHERBOARD),343)
# TriGorilla Anycubic version 1.4 based on RAMPS EFB
else ifeq ($(HARDWARE_MOTHERBOARD),443)
# Creality: Ender-4, CR-8
else ifeq ($(HARDWARE_MOTHERBOARD),243)
#
# Other ATmega1280, ATmega2560
#
# Cartesio CN Controls V11
else ifeq ($(HARDWARE_MOTHERBOARD),111)
# Cartesio CN Controls V12
else ifeq ($(HARDWARE_MOTHERBOARD),112)
# Cheaptronic v1.0
else ifeq ($(HARDWARE_MOTHERBOARD),2)
# Cheaptronic v2.0
else ifeq ($(HARDWARE_MOTHERBOARD),21)
# Makerbot Mightyboard Revision E
else ifeq ($(HARDWARE_MOTHERBOARD),200)
# Megatronics
else ifeq ($(HARDWARE_MOTHERBOARD),70)
# Megatronics v2.0
else ifeq ($(HARDWARE_MOTHERBOARD),701)
# Megatronics v3.0
else ifeq ($(HARDWARE_MOTHERBOARD),703)
# Megatronics v3.1
else ifeq ($(HARDWARE_MOTHERBOARD),704)
# Rambo
else ifeq ($(HARDWARE_MOTHERBOARD),301)
# Mini-Rambo
else ifeq ($(HARDWARE_MOTHERBOARD),302)
# Mini-Rambo 1.0a
else ifeq ($(HARDWARE_MOTHERBOARD),303)
# Einsy Rambo
else ifeq ($(HARDWARE_MOTHERBOARD),304)
# Einsy Retro
else ifeq ($(HARDWARE_MOTHERBOARD),305)
# Elefu Ra Board (v3)
else ifeq ($(HARDWARE_MOTHERBOARD),21)
# Leapfrog
else ifeq ($(HARDWARE_MOTHERBOARD),999)
# Mega controller
else ifeq ($(HARDWARE_MOTHERBOARD),310)
# abee Scoovo X9H
else ifeq ($(HARDWARE_MOTHERBOARD),321)
# Geeetech GT2560 Rev. A
else ifeq ($(HARDWARE_MOTHERBOARD),74)
# Geeetech GT2560 Rev. A+ (with auto level probe)
else ifeq ($(HARDWARE_MOTHERBOARD),75)
#
# ATmega1281, ATmega2561
#
else ifeq ($(HARDWARE_MOTHERBOARD),702)
MCU ?= atmega1281
else ifeq ($(HARDWARE_MOTHERBOARD),25)
MCU ?= atmega1281
#
# Sanguinololu and Derivatives - ATmega644P, ATmega1284P
#
# Sanguinololu < 1.2
else ifeq ($(HARDWARE_MOTHERBOARD),6)
HARDWARE_VARIANT ?= Sanguino
MCU ?= atmega644p
# Sanguinololu 1.2 and above
else ifeq ($(HARDWARE_MOTHERBOARD),62)
HARDWARE_VARIANT ?= Sanguino
MCU ?= atmega644p
# Melzi
else ifeq ($(HARDWARE_MOTHERBOARD),63)
HARDWARE_VARIANT ?= Sanguino
MCU ?= atmega644p
# Melzi with ATmega1284 (MaKr3d version)
else ifeq ($(HARDWARE_MOTHERBOARD),66)
HARDWARE_VARIANT ?= Sanguino
MCU ?= atmega1284p
# Melzi Creality3D board (for CR-10 etc)
else ifeq ($(HARDWARE_MOTHERBOARD),89)
HARDWARE_VARIANT ?= Sanguino
MCU ?= atmega1284p
# Melzi Malyan M150 board
else ifeq ($(HARDWARE_MOTHERBOARD),92)
HARDWARE_VARIANT ?= Sanguino
MCU ?= atmega1284p
# Tronxy X5S
else ifeq ($(HARDWARE_MOTHERBOARD),505)
HARDWARE_VARIANT ?= Sanguino
MCU ?= atmega1284p
# STB V1.1
else ifeq ($(HARDWARE_MOTHERBOARD),64)
HARDWARE_VARIANT ?= Sanguino
MCU ?= atmega1284p
# Azteeg X1
else ifeq ($(HARDWARE_MOTHERBOARD),65)
HARDWARE_VARIANT ?= Sanguino
MCU ?= atmega1284p
# Anet 1.0 (Melzi clone)
else ifeq ($(HARDWARE_MOTHERBOARD),69)
HARDWARE_VARIANT ?= Sanguino
MCU ?= atmega1284p
#
# Other ATmega644P, ATmega644, ATmega1284P
#
# Gen3 Monolithic Electronics
else ifeq ($(HARDWARE_MOTHERBOARD),22)
HARDWARE_VARIANT ?= Sanguino
MCU ?= atmega644p
# Gen3+
else ifeq ($(HARDWARE_MOTHERBOARD),9)
HARDWARE_VARIANT ?= Sanguino
MCU ?= atmega644p
# Gen6
else ifeq ($(HARDWARE_MOTHERBOARD),5)
HARDWARE_VARIANT ?= Gen6
MCU ?= atmega644p
# Gen6 deluxe
else ifeq ($(HARDWARE_MOTHERBOARD),51)
HARDWARE_VARIANT ?= Gen6
MCU ?= atmega644p
# Gen7 custom (Alfons3 Version)
else ifeq ($(HARDWARE_MOTHERBOARD),10)
HARDWARE_VARIANT ?= Gen7
MCU ?= atmega644
F_CPU ?= 20000000
# Gen7 v1.1, v1.2
else ifeq ($(HARDWARE_MOTHERBOARD),11)
HARDWARE_VARIANT ?= Gen7
MCU ?= atmega644p
F_CPU ?= 20000000
# Gen7 v1.3
else ifeq ($(HARDWARE_MOTHERBOARD),12)
HARDWARE_VARIANT ?= Gen7
MCU ?= atmega644p
F_CPU ?= 20000000
# Gen7 v1.4
else ifeq ($(HARDWARE_MOTHERBOARD),13)
HARDWARE_VARIANT ?= Gen7
MCU ?= atmega1284p
F_CPU ?= 20000000
# Alpha OMCA board
else ifeq ($(HARDWARE_MOTHERBOARD),90)
HARDWARE_VARIANT ?= SanguinoA
MCU ?= atmega644
# Final OMCA board
else ifeq ($(HARDWARE_MOTHERBOARD),91)
HARDWARE_VARIANT ?= Sanguino
MCU ?= atmega644p
# Sethi 3D_1
else ifeq ($(HARDWARE_MOTHERBOARD),20)
HARDWARE_VARIANT ?= Sanguino
MCU ?= atmega644p
#
# Teensyduino - AT90USB1286, AT90USB1286P
#
# Teensylu
else ifeq ($(HARDWARE_MOTHERBOARD),8)
HARDWARE_VARIANT ?= Teensy
MCU ?= at90usb1286
# Printrboard (AT90USB1286)
else ifeq ($(HARDWARE_MOTHERBOARD),81)
HARDWARE_VARIANT ?= Teensy
MCU ?= at90usb1286
# Printrboard Revision F (AT90USB1286)
else ifeq ($(HARDWARE_MOTHERBOARD),811)
HARDWARE_VARIANT ?= Teensy
MCU ?= at90usb1286
# Brainwave (AT90USB646)
else ifeq ($(HARDWARE_MOTHERBOARD),82)
HARDWARE_VARIANT ?= Teensy
MCU ?= at90usb646
# Brainwave Pro (AT90USB1286)
else ifeq ($(HARDWARE_MOTHERBOARD),83)
HARDWARE_VARIANT ?= Teensy
MCU ?= at90usb1286
# SAV Mk-I (AT90USB1286)
else ifeq ($(HARDWARE_MOTHERBOARD),84)
HARDWARE_VARIANT ?= Teensy
MCU ?= at90usb1286
# Teensy++2.0 (AT90USB1286) - CLI compile: HARDWARE_MOTHERBOARD=84 make
else ifeq ($(HARDWARE_MOTHERBOARD),85)
HARDWARE_VARIANT ?= Teensy
MCU ?= at90usb1286
# 5DPrint D8 Driver Board
else ifeq ($(HARDWARE_MOTHERBOARD),88)
HARDWARE_VARIANT ?= Teensy
MCU ?= at90usb1286
endif
# Be sure to regenerate speed_lookuptable.h with create_speed_lookuptable.py
# if you are setting this to something other than 16MHz
# Set to 16Mhz if not yet set.
F_CPU ?= 16000000
# Set to arduino, ATmega2560 if not yet set.
HARDWARE_VARIANT ?= arduino
MCU ?= atmega2560
# Arduino contained the main source code for the Arduino
# Libraries, the "hardware variant" are for boards
# that derives from that, and their source are present in
# the main Marlin source directory
TARGET = $(notdir $(CURDIR))
# VPATH tells make to look into these directory for source files,
# there is no need to specify explicit pathnames as long as the
# directory is added here
VPATH = .
VPATH += $(BUILD_DIR)
VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/cores/arduino
VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/libraries/SPI
VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/libraries/SPI/src
VPATH += $(ARDUINO_INSTALL_DIR)/libraries/LiquidCrystal/src
ifeq ($(LIQUID_TWI2), 1)
VPATH += $(ARDUINO_INSTALL_DIR)/libraries/Wire
VPATH += $(ARDUINO_INSTALL_DIR)/libraries/Wire/utility
VPATH += $(ARDUINO_INSTALL_DIR)/libraries/LiquidTWI2
endif
ifeq ($(WIRE), 1)
VPATH += $(ARDUINO_INSTALL_DIR)/libraries/Wire
VPATH += $(ARDUINO_INSTALL_DIR)/libraries/Wire/utility
endif
ifeq ($(NEOPIXEL), 1)
VPATH += $(ARDUINO_INSTALL_DIR)/libraries/Adafruit_NeoPixel
endif
ifeq ($(U8GLIB), 1)
VPATH += $(ARDUINO_INSTALL_DIR)/libraries/U8glib
VPATH += $(ARDUINO_INSTALL_DIR)/libraries/U8glib/utility
endif
ifeq ($(HARDWARE_VARIANT), arduino)
HARDWARE_SUB_VARIANT ?= mega
VPATH += $(ARDUINO_INSTALL_DIR)/hardware/arduino/avr/variants/$(HARDWARE_SUB_VARIANT)
else
ifeq ($(HARDWARE_VARIANT), Sanguino)
VPATH += $(HARDWARE_DIR)/marlin/avr/variants/sanguino
else
HARDWARE_SUB_VARIANT ?= standard
VPATH += $(HARDWARE_DIR)/$(HARDWARE_VARIANT)/variants/$(HARDWARE_SUB_VARIANT)
endif
endif
SRC = wiring.c \
wiring_analog.c wiring_digital.c \
wiring_pulse.c \
wiring_shift.c WInterrupts.c hooks.c
ifeq ($(HARDWARE_VARIANT), Teensy)
SRC = wiring.c
VPATH += $(ARDUINO_INSTALL_DIR)/hardware/teensy/cores/teensy
endif
CXXSRC = WMath.cpp WString.cpp Print.cpp SPI.cpp Tone.cpp
CXXSRC += $(wildcard *.cpp)
ifeq ($(NEOPIXEL), 1)
CXXSRC += Adafruit_NeoPixel.cpp
endif
ifeq ($(LIQUID_TWI2), 0)
CXXSRC += LiquidCrystal.cpp
else
SRC += twi.c
CXXSRC += Wire.cpp LiquidTWI2.cpp
endif
ifeq ($(WIRE), 1)
SRC += twi.c
CXXSRC += Wire.cpp
endif
ifeq ($(U8GLIB), 1)
SRC += u8g_ll_api.c u8g_bitmap.c u8g_clip.c u8g_com_null.c u8g_delay.c u8g_page.c u8g_pb.c u8g_pb16h1.c u8g_rect.c u8g_state.c u8g_font.c u8g_font_data.c
endif
ifeq ($(RELOC_WORKAROUND), 1)
LD_PREFIX=-nodefaultlibs
LD_SUFFIX=-lm -lgcc -lc -lgcc -L$(ARDUINO_INSTALL_DIR)/hardware/tools/avr/avr/lib/avr6 -l$(MCU)
endif
#Check for Arduino 1.0.0 or higher and use the correct source files for that version
ifeq ($(shell [ $(ARDUINO_VERSION) -ge 100 ] && echo true), true)
CXXSRC += main.cpp
else
SRC += pins_arduino.c main.c
endif
FORMAT = ihex
# Name of this Makefile (used for "make depend").
MAKEFILE = Makefile
# Debugging format.
# Native formats for AVR-GCC's -g are stabs [default], or dwarf-2.
# AVR (extended) COFF requires stabs, plus an avr-objcopy run.
DEBUG = stabs
OPT = s
DEFINES ?=
# Program settings
CC = $(AVR_TOOLS_PATH)avr-gcc
CXX = $(AVR_TOOLS_PATH)avr-g++
OBJCOPY = $(AVR_TOOLS_PATH)avr-objcopy
OBJDUMP = $(AVR_TOOLS_PATH)avr-objdump
AR = $(AVR_TOOLS_PATH)avr-ar
SIZE = $(AVR_TOOLS_PATH)avr-size
NM = $(AVR_TOOLS_PATH)avr-nm
AVRDUDE = avrdude
REMOVE = rm -f
MV = mv -f
# Place -D or -U options here
CDEFS = -DF_CPU=$(F_CPU) ${addprefix -D , $(DEFINES)}
CXXDEFS = $(CDEFS)
ifeq ($(HARDWARE_VARIANT), Teensy)
CDEFS += -DUSB_SERIAL
SRC += usb.c pins_teensy.c
CXXSRC += usb_api.cpp
endif
# Add all the source directories as include directories too
CINCS = ${addprefix -I ,${VPATH}}
CXXINCS = ${addprefix -I ,${VPATH}}
# Compiler flag to set the C/CPP Standard level.
CSTANDARD = -std=gnu99
CXXSTANDARD = -std=gnu++11
CDEBUG = -g$(DEBUG)
CWARN = -Wall -Wstrict-prototypes
CTUNING = -w -fsigned-char -funsigned-bitfields -fpack-struct \
-fshort-enums -ffunction-sections -fdata-sections -flto \
-DARDUINO=$(ARDUINO_VERSION)
ifneq ($(HARDWARE_MOTHERBOARD),)
CTUNING += -DMOTHERBOARD=${HARDWARE_MOTHERBOARD}
endif
#CEXTRA = -Wa,-adhlns=$(<:.c=.lst)
CEXTRA = -fno-use-cxa-atexit -fno-threadsafe-statics
CFLAGS := $(CDEBUG) $(CDEFS) $(CINCS) -O$(OPT) $(CWARN) $(CEXTRA) $(CTUNING) $(CSTANDARD)
CXXFLAGS := $(CDEFS) $(CINCS) -O$(OPT) -Wall $(CEXTRA) $(CTUNING) $(CXXSTANDARD)
#ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
LDFLAGS = -lm
# Programming support using avrdude. Settings and variables.
AVRDUDE_PORT = $(UPLOAD_PORT)
AVRDUDE_WRITE_FLASH = -Uflash:w:$(BUILD_DIR)/$(TARGET).hex:i
ifeq ($(shell uname -s), Linux)
AVRDUDE_CONF = /etc/avrdude/avrdude.conf
else
AVRDUDE_CONF = $(ARDUINO_INSTALL_DIR)/hardware/tools/avr/etc/avrdude.conf
endif
AVRDUDE_FLAGS = -D -C$(AVRDUDE_CONF) \
-p$(MCU) -P$(AVRDUDE_PORT) -c$(AVRDUDE_PROGRAMMER) \
-b$(UPLOAD_RATE)
# Define all object files.
OBJ = ${patsubst %.c, $(BUILD_DIR)/%.o, ${SRC}}
OBJ += ${patsubst %.cpp, $(BUILD_DIR)/%.o, ${CXXSRC}}
OBJ += ${patsubst %.S, $(BUILD_DIR)/%.o, ${ASRC}}
# Define all listing files.
LST = $(ASRC:.S=.lst) $(CXXSRC:.cpp=.lst) $(SRC:.c=.lst)
# Combine all necessary flags and optional flags.
# Add target processor to flags.
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS)
ALL_CXXFLAGS = -mmcu=$(MCU) $(CXXFLAGS)
ALL_ASFLAGS = -mmcu=$(MCU) -x assembler-with-cpp $(ASFLAGS)
# set V=1 (eg, "make V=1") to print the full commands etc.
ifneq ($V,1)
Pecho=@echo
P=@
else
Pecho=@:
P=
endif
# Default target.
all: sizeafter
build: $(BUILD_DIR) elf hex
# Creates the object directory
$(BUILD_DIR):
$P mkdir -p $(BUILD_DIR)
elf: $(BUILD_DIR)/$(TARGET).elf
hex: $(BUILD_DIR)/$(TARGET).hex
eep: $(BUILD_DIR)/$(TARGET).eep
lss: $(BUILD_DIR)/$(TARGET).lss
sym: $(BUILD_DIR)/$(TARGET).sym
# Program the device.
# Do not try to reset an Arduino if it's not one
upload: $(BUILD_DIR)/$(TARGET).hex
ifeq (${AVRDUDE_PROGRAMMER}, arduino)
stty hup < $(UPLOAD_PORT); true
endif
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH)
ifeq (${AVRDUDE_PROGRAMMER}, arduino)
stty -hup < $(UPLOAD_PORT); true
endif
# Display size of file.
HEXSIZE = $(SIZE) --target=$(FORMAT) $(BUILD_DIR)/$(TARGET).hex
ELFSIZE = $(SIZE) --mcu=$(MCU) -C $(BUILD_DIR)/$(TARGET).elf; \
$(SIZE) $(BUILD_DIR)/$(TARGET).elf
sizebefore:
$P if [ -f $(BUILD_DIR)/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_BEFORE); $(HEXSIZE); echo; fi
sizeafter: build
$P if [ -f $(BUILD_DIR)/$(TARGET).elf ]; then echo; echo $(MSG_SIZE_AFTER); $(ELFSIZE); echo; fi
# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
COFFCONVERT=$(OBJCOPY) --debugging \
--change-section-address .data-0x800000 \
--change-section-address .bss-0x800000 \
--change-section-address .noinit-0x800000 \
--change-section-address .eeprom-0x810000
coff: $(BUILD_DIR)/$(TARGET).elf
$(COFFCONVERT) -O coff-avr $(BUILD_DIR)/$(TARGET).elf $(TARGET).cof
extcoff: $(TARGET).elf
$(COFFCONVERT) -O coff-ext-avr $(BUILD_DIR)/$(TARGET).elf $(TARGET).cof
.SUFFIXES: .elf .hex .eep .lss .sym
.PRECIOUS: .o
.elf.hex:
$(Pecho) " COPY $@"
$P $(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
.elf.eep:
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 -O $(FORMAT) $< $@
# Create extended listing file from ELF output file.
.elf.lss:
$(OBJDUMP) -h -S $< > $@
# Create a symbol table from ELF output file.
.elf.sym:
$(NM) -n $< > $@
# Link: create ELF output file from library.
$(BUILD_DIR)/$(TARGET).elf: $(OBJ) Configuration.h
$(Pecho) " CXX $@"
$P $(CC) $(LD_PREFIX) $(ALL_CXXFLAGS) -Wl,--gc-sections,--relax -o $@ -L. $(OBJ) $(LDFLAGS) $(LD_SUFFIX)
$(BUILD_DIR)/%.o: %.c Configuration.h Configuration_adv.h $(MAKEFILE)
$(Pecho) " CC $<"
$P $(CC) -MMD -c $(ALL_CFLAGS) $< -o $@
$(BUILD_DIR)/%.o: $(BUILD_DIR)/%.cpp Configuration.h Configuration_adv.h $(MAKEFILE)
$(Pecho) " CXX $<"
$P $(CXX) -MMD -c $(ALL_CXXFLAGS) $< -o $@
$(BUILD_DIR)/%.o: %.cpp Configuration.h Configuration_adv.h $(MAKEFILE)
$(Pecho) " CXX $<"
$P $(CXX) -MMD -c $(ALL_CXXFLAGS) $< -o $@
# Target: clean project.
clean:
$(Pecho) " RM $(BUILD_DIR)/*"
$P $(REMOVE) $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).eep $(BUILD_DIR)/$(TARGET).cof $(BUILD_DIR)/$(TARGET).elf \
$(BUILD_DIR)/$(TARGET).map $(BUILD_DIR)/$(TARGET).sym $(BUILD_DIR)/$(TARGET).lss $(BUILD_DIR)/$(TARGET).cpp \
$(OBJ) $(LST) $(SRC:.c=.s) $(SRC:.c=.d) $(CXXSRC:.cpp=.s) $(CXXSRC:.cpp=.d)
$(Pecho) " RMDIR $(BUILD_DIR)/"
$P rm -rf $(BUILD_DIR)
.PHONY: all build elf hex eep lss sym program coff extcoff clean depend sizebefore sizeafter
# Automaticaly include the dependency files created by gcc
-include ${wildcard $(BUILD_DIR)/*.d}

647
Marlin/Marlin.h Normal file
View File

@ -0,0 +1,647 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef MARLIN_H
#define MARLIN_H
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <util/delay.h>
#include <avr/eeprom.h>
#include <avr/interrupt.h>
#include "MarlinConfig.h"
#ifdef DEBUG_GCODE_PARSER
#include "parser.h"
#endif
#include "enum.h"
#include "types.h"
#include "fastio.h"
#include "utility.h"
#include "serial.h"
void idle(
#if ENABLED(ADVANCED_PAUSE_FEATURE)
bool no_stepper_sleep = false // pass true to keep steppers from disabling on timeout
#endif
);
void manage_inactivity(const bool ignore_stepper_queue=false);
extern const char axis_codes[XYZE];
#if ENABLED(DUAL_X_CARRIAGE) || ENABLED(DUAL_NOZZLE_DUPLICATION_MODE)
extern bool extruder_duplication_enabled;
#endif
#if HAS_X2_ENABLE
#define enable_X() do{ X_ENABLE_WRITE( X_ENABLE_ON); X2_ENABLE_WRITE( X_ENABLE_ON); }while(0)
#define disable_X() do{ X_ENABLE_WRITE(!X_ENABLE_ON); X2_ENABLE_WRITE(!X_ENABLE_ON); CBI(axis_known_position, X_AXIS); }while(0)
#elif HAS_X_ENABLE
#define enable_X() X_ENABLE_WRITE( X_ENABLE_ON)
#define disable_X() do{ X_ENABLE_WRITE(!X_ENABLE_ON); CBI(axis_known_position, X_AXIS); }while(0)
#else
#define enable_X() NOOP
#define disable_X() NOOP
#endif
#if HAS_Y2_ENABLE
#define enable_Y() do{ Y_ENABLE_WRITE( Y_ENABLE_ON); Y2_ENABLE_WRITE(Y_ENABLE_ON); }while(0)
#define disable_Y() do{ Y_ENABLE_WRITE(!Y_ENABLE_ON); Y2_ENABLE_WRITE(!Y_ENABLE_ON); CBI(axis_known_position, Y_AXIS); }while(0)
#elif HAS_Y_ENABLE
#define enable_Y() Y_ENABLE_WRITE( Y_ENABLE_ON)
#define disable_Y() do{ Y_ENABLE_WRITE(!Y_ENABLE_ON); CBI(axis_known_position, Y_AXIS); }while(0)
#else
#define enable_Y() NOOP
#define disable_Y() NOOP
#endif
#if HAS_Z2_ENABLE
#define enable_Z() do{ Z_ENABLE_WRITE( Z_ENABLE_ON); Z2_ENABLE_WRITE(Z_ENABLE_ON); }while(0)
#define disable_Z() do{ Z_ENABLE_WRITE(!Z_ENABLE_ON); Z2_ENABLE_WRITE(!Z_ENABLE_ON); CBI(axis_known_position, Z_AXIS); }while(0)
#elif HAS_Z_ENABLE
#define enable_Z() Z_ENABLE_WRITE( Z_ENABLE_ON)
#define disable_Z() do{ Z_ENABLE_WRITE(!Z_ENABLE_ON); CBI(axis_known_position, Z_AXIS); }while(0)
#else
#define enable_Z() NOOP
#define disable_Z() NOOP
#endif
#if ENABLED(MIXING_EXTRUDER)
/**
* Mixing steppers synchronize their enable (and direction) together
*/
#if MIXING_STEPPERS > 4
#define enable_E0() { E0_ENABLE_WRITE( E_ENABLE_ON); E1_ENABLE_WRITE( E_ENABLE_ON); E2_ENABLE_WRITE( E_ENABLE_ON); E3_ENABLE_WRITE( E_ENABLE_ON); E4_ENABLE_WRITE( E_ENABLE_ON); }
#define disable_E0() { E0_ENABLE_WRITE(!E_ENABLE_ON); E1_ENABLE_WRITE(!E_ENABLE_ON); E2_ENABLE_WRITE(!E_ENABLE_ON); E3_ENABLE_WRITE(!E_ENABLE_ON); E4_ENABLE_WRITE(!E_ENABLE_ON); }
#elif MIXING_STEPPERS > 3
#define enable_E0() { E0_ENABLE_WRITE( E_ENABLE_ON); E1_ENABLE_WRITE( E_ENABLE_ON); E2_ENABLE_WRITE( E_ENABLE_ON); E3_ENABLE_WRITE( E_ENABLE_ON); }
#define disable_E0() { E0_ENABLE_WRITE(!E_ENABLE_ON); E1_ENABLE_WRITE(!E_ENABLE_ON); E2_ENABLE_WRITE(!E_ENABLE_ON); E3_ENABLE_WRITE(!E_ENABLE_ON); }
#elif MIXING_STEPPERS > 2
#define enable_E0() { E0_ENABLE_WRITE( E_ENABLE_ON); E1_ENABLE_WRITE( E_ENABLE_ON); E2_ENABLE_WRITE( E_ENABLE_ON); }
#define disable_E0() { E0_ENABLE_WRITE(!E_ENABLE_ON); E1_ENABLE_WRITE(!E_ENABLE_ON); E2_ENABLE_WRITE(!E_ENABLE_ON); }
#else
#define enable_E0() { E0_ENABLE_WRITE( E_ENABLE_ON); E1_ENABLE_WRITE( E_ENABLE_ON); }
#define disable_E0() { E0_ENABLE_WRITE(!E_ENABLE_ON); E1_ENABLE_WRITE(!E_ENABLE_ON); }
#endif
#define enable_E1() NOOP
#define disable_E1() NOOP
#define enable_E2() NOOP
#define disable_E2() NOOP
#define enable_E3() NOOP
#define disable_E3() NOOP
#define enable_E4() NOOP
#define disable_E4() NOOP
#else // !MIXING_EXTRUDER
#if HAS_E0_ENABLE
#define enable_E0() E0_ENABLE_WRITE( E_ENABLE_ON)
#define disable_E0() E0_ENABLE_WRITE(!E_ENABLE_ON)
#else
#define enable_E0() NOOP
#define disable_E0() NOOP
#endif
#if E_STEPPERS > 1 && HAS_E1_ENABLE
#define enable_E1() E1_ENABLE_WRITE( E_ENABLE_ON)
#define disable_E1() E1_ENABLE_WRITE(!E_ENABLE_ON)
#else
#define enable_E1() NOOP
#define disable_E1() NOOP
#endif
#if E_STEPPERS > 2 && HAS_E2_ENABLE
#define enable_E2() E2_ENABLE_WRITE( E_ENABLE_ON)
#define disable_E2() E2_ENABLE_WRITE(!E_ENABLE_ON)
#else
#define enable_E2() NOOP
#define disable_E2() NOOP
#endif
#if E_STEPPERS > 3 && HAS_E3_ENABLE
#define enable_E3() E3_ENABLE_WRITE( E_ENABLE_ON)
#define disable_E3() E3_ENABLE_WRITE(!E_ENABLE_ON)
#else
#define enable_E3() NOOP
#define disable_E3() NOOP
#endif
#if E_STEPPERS > 4 && HAS_E4_ENABLE
#define enable_E4() E4_ENABLE_WRITE( E_ENABLE_ON)
#define disable_E4() E4_ENABLE_WRITE(!E_ENABLE_ON)
#else
#define enable_E4() NOOP
#define disable_E4() NOOP
#endif
#endif // !MIXING_EXTRUDER
#if ENABLED(HANGPRINTER)
#define enable_A() enable_X()
#define enable_B() enable_Y()
#define enable_C() enable_Z()
#define __D_ENABLE(p) E##p##_ENABLE_WRITE(E_ENABLE_ON)
#define _D_ENABLE(p) __D_ENABLE(p)
#define enable_D() _D_ENABLE(EXTRUDERS)
// Don't allow any axes to be disabled
#undef disable_X
#undef disable_Y
#undef disable_Z
#define disable_X() NOOP
#define disable_Y() NOOP
#define disable_Z() NOOP
#if EXTRUDERS >= 1
#undef disable_E1
#define disable_E1() NOOP
#if EXTRUDERS >= 2
#undef disable_E2
#define disable_E2() NOOP
#if EXTRUDERS >= 3
#undef disable_E3
#define disable_E3() NOOP
#if EXTRUDERS >= 4
#undef disable_E4
#define disable_E4() NOOP
#endif // EXTRUDERS >= 4
#endif // EXTRUDERS >= 3
#endif // EXTRUDERS >= 2
#endif // EXTRUDERS >= 1
#endif // HANGPRINTER
#if ENABLED(G38_PROBE_TARGET)
extern bool G38_move, // flag to tell the interrupt handler that a G38 command is being run
G38_endstop_hit; // flag from the interrupt handler to indicate if the endstop went active
#endif
void enable_all_steppers();
void disable_e_stepper(const uint8_t e);
void disable_e_steppers();
void disable_all_steppers();
void sync_plan_position();
void sync_plan_position_e();
#if IS_KINEMATIC
void sync_plan_position_kinematic();
#define SYNC_PLAN_POSITION_KINEMATIC() sync_plan_position_kinematic()
#else
#define SYNC_PLAN_POSITION_KINEMATIC() sync_plan_position()
#endif
void flush_and_request_resend();
void ok_to_send();
void kill(const char*);
void quickstop_stepper();
extern uint8_t marlin_debug_flags;
#define DEBUGGING(F) (marlin_debug_flags & (DEBUG_## F))
extern bool Running;
inline bool IsRunning() { return Running; }
inline bool IsStopped() { return !Running; }
bool enqueue_and_echo_command(const char* cmd); // Add a single command to the end of the buffer. Return false on failure.
void enqueue_and_echo_commands_P(const char * const cmd); // Set one or more commands to be prioritized over the next Serial/SD command.
void clear_command_queue();
#if ENABLED(M100_FREE_MEMORY_WATCHER) || ENABLED(POWER_LOSS_RECOVERY)
extern char command_queue[BUFSIZE][MAX_CMD_SIZE];
#endif
#define HAS_LCD_QUEUE_NOW (ENABLED(MALYAN_LCD) || (ENABLED(ULTIPANEL) && (ENABLED(AUTO_BED_LEVELING_UBL) || ENABLED(PID_AUTOTUNE_MENU) || ENABLED(ADVANCED_PAUSE_FEATURE))))
#define HAS_QUEUE_NOW (ENABLED(SDSUPPORT) || HAS_LCD_QUEUE_NOW)
#if HAS_QUEUE_NOW
// Return only when commands are actually enqueued
void enqueue_and_echo_command_now(const char* cmd);
#if HAS_LCD_QUEUE_NOW
void enqueue_and_echo_commands_now_P(const char * const cmd);
#endif
#endif
extern millis_t previous_move_ms;
inline void reset_stepper_timeout() { previous_move_ms = millis(); }
/**
* Feedrate scaling and conversion
*/
extern float feedrate_mm_s;
extern int16_t feedrate_percentage;
#define MMS_SCALED(MM_S) ((MM_S)*feedrate_percentage*0.01f)
extern bool axis_relative_modes[XYZE];
extern uint8_t axis_homed, axis_known_position;
constexpr uint8_t xyz_bits = _BV(X_AXIS) | _BV(Y_AXIS) | _BV(Z_AXIS);
FORCE_INLINE bool all_axes_homed() { return (axis_homed & xyz_bits) == xyz_bits; }
FORCE_INLINE bool all_axes_known() { return (axis_known_position & xyz_bits) == xyz_bits; }
extern volatile bool wait_for_heatup;
#if HAS_RESUME_CONTINUE
extern volatile bool wait_for_user;
#endif
#if HAS_AUTO_REPORTING || ENABLED(HOST_KEEPALIVE_FEATURE)
extern bool suspend_auto_report;
#endif
extern float current_position[XYZE], destination[XYZE];
/**
* Workspace offsets
*/
#if HAS_WORKSPACE_OFFSET
#if HAS_HOME_OFFSET
extern float home_offset[XYZ];
#endif
#if HAS_POSITION_SHIFT
extern float position_shift[XYZ];
#endif
#if HAS_HOME_OFFSET && HAS_POSITION_SHIFT
extern float workspace_offset[XYZ];
#define WORKSPACE_OFFSET(AXIS) workspace_offset[AXIS]
#elif HAS_HOME_OFFSET
#define WORKSPACE_OFFSET(AXIS) home_offset[AXIS]
#elif HAS_POSITION_SHIFT
#define WORKSPACE_OFFSET(AXIS) position_shift[AXIS]
#endif
#define NATIVE_TO_LOGICAL(POS, AXIS) ((POS) + WORKSPACE_OFFSET(AXIS))
#define LOGICAL_TO_NATIVE(POS, AXIS) ((POS) - WORKSPACE_OFFSET(AXIS))
#else
#define NATIVE_TO_LOGICAL(POS, AXIS) (POS)
#define LOGICAL_TO_NATIVE(POS, AXIS) (POS)
#endif
#define LOGICAL_X_POSITION(POS) NATIVE_TO_LOGICAL(POS, X_AXIS)
#define LOGICAL_Y_POSITION(POS) NATIVE_TO_LOGICAL(POS, Y_AXIS)
#define LOGICAL_Z_POSITION(POS) NATIVE_TO_LOGICAL(POS, Z_AXIS)
#define RAW_X_POSITION(POS) LOGICAL_TO_NATIVE(POS, X_AXIS)
#define RAW_Y_POSITION(POS) LOGICAL_TO_NATIVE(POS, Y_AXIS)
#define RAW_Z_POSITION(POS) LOGICAL_TO_NATIVE(POS, Z_AXIS)
// Hotend Offsets
#if HOTENDS > 1
extern float hotend_offset[XYZ][HOTENDS];
#endif
// Software Endstops
extern float soft_endstop_min[XYZ], soft_endstop_max[XYZ];
#if HAS_SOFTWARE_ENDSTOPS
extern bool soft_endstops_enabled;
void clamp_to_software_endstops(float target[XYZ]);
#else
#define soft_endstops_enabled false
#define clamp_to_software_endstops(x) NOOP
#endif
#if HAS_WORKSPACE_OFFSET || ENABLED(DUAL_X_CARRIAGE)
void update_software_endstops(const AxisEnum axis);
#endif
#define MAX_COORDINATE_SYSTEMS 9
#if ENABLED(CNC_COORDINATE_SYSTEMS)
extern float coordinate_system[MAX_COORDINATE_SYSTEMS][XYZ];
bool select_coordinate_system(const int8_t _new);
#endif
void tool_change(const uint8_t tmp_extruder, const float fr_mm_s=0.0, bool no_move=false);
void home_all_axes();
void report_current_position();
#if IS_KINEMATIC
#if ENABLED(HANGPRINTER)
extern float line_lengths[ABCD];
#else
extern float delta[ABC];
#endif
void inverse_kinematics(const float raw[XYZ]);
#endif
#if ENABLED(DELTA)
extern float delta_height,
delta_endstop_adj[ABC],
delta_radius,
delta_tower_angle_trim[ABC],
delta_tower[ABC][2],
delta_diagonal_rod,
delta_calibration_radius,
delta_diagonal_rod_2_tower[ABC],
delta_segments_per_second,
delta_clip_start_height;
void recalc_delta_settings();
float delta_safe_distance_from_top();
// Macro to obtain the Z position of an individual tower
#define DELTA_Z(V,T) V[Z_AXIS] + SQRT( \
delta_diagonal_rod_2_tower[T] - HYPOT2( \
delta_tower[T][X_AXIS] - V[X_AXIS], \
delta_tower[T][Y_AXIS] - V[Y_AXIS] \
) \
)
#define DELTA_IK(V) do { \
delta[A_AXIS] = DELTA_Z(V, A_AXIS); \
delta[B_AXIS] = DELTA_Z(V, B_AXIS); \
delta[C_AXIS] = DELTA_Z(V, C_AXIS); \
}while(0)
#elif ENABLED(HANGPRINTER)
// Don't collect anchor positions in array because there are no A_x, D_x or D_y
extern float anchor_A_y,
anchor_A_z,
anchor_B_x,
anchor_B_y,
anchor_B_z,
anchor_C_x,
anchor_C_y,
anchor_C_z,
anchor_D_z,
delta_segments_per_second,
line_lengths_origin[ABCD];
void recalc_hangprinter_settings();
#define HANGPRINTER_IK(V) do { \
line_lengths[A_AXIS] = SQRT(sq(anchor_A_z - V[Z_AXIS]) \
+ sq(anchor_A_y - V[Y_AXIS]) \
+ sq( V[X_AXIS])); \
line_lengths[B_AXIS] = SQRT(sq(anchor_B_z - V[Z_AXIS]) \
+ sq(anchor_B_y - V[Y_AXIS]) \
+ sq(anchor_B_x - V[X_AXIS])); \
line_lengths[C_AXIS] = SQRT(sq(anchor_C_z - V[Z_AXIS]) \
+ sq(anchor_C_y - V[Y_AXIS]) \
+ sq(anchor_C_x - V[X_AXIS])); \
line_lengths[D_AXIS] = SQRT(sq( V[X_AXIS]) \
+ sq( V[Y_AXIS]) \
+ sq(anchor_D_z - V[Z_AXIS])); \
}while(0)
// Inverse kinematics at origin
#define HANGPRINTER_IK_ORIGIN(LL) do { \
LL[A_AXIS] = SQRT(sq(anchor_A_z) \
+ sq(anchor_A_y)); \
LL[B_AXIS] = SQRT(sq(anchor_B_z) \
+ sq(anchor_B_y) \
+ sq(anchor_B_x)); \
LL[C_AXIS] = SQRT(sq(anchor_C_z) \
+ sq(anchor_C_y) \
+ sq(anchor_C_x)); \
LL[D_AXIS] = anchor_D_z; \
}while(0)
#elif IS_SCARA
void forward_kinematics_SCARA(const float &a, const float &b);
#endif
#if ENABLED(G26_MESH_VALIDATION)
extern bool g26_debug_flag;
#elif ENABLED(AUTO_BED_LEVELING_UBL)
constexpr bool g26_debug_flag = false;
#endif
#if ENABLED(AUTO_BED_LEVELING_BILINEAR)
#define _GET_MESH_X(I) (bilinear_start[X_AXIS] + (I) * bilinear_grid_spacing[X_AXIS])
#define _GET_MESH_Y(J) (bilinear_start[Y_AXIS] + (J) * bilinear_grid_spacing[Y_AXIS])
#elif ENABLED(AUTO_BED_LEVELING_UBL)
#define _GET_MESH_X(I) ubl.mesh_index_to_xpos(I)
#define _GET_MESH_Y(J) ubl.mesh_index_to_ypos(J)
#elif ENABLED(MESH_BED_LEVELING)
#define _GET_MESH_X(I) mbl.index_to_xpos[I]
#define _GET_MESH_Y(J) mbl.index_to_ypos[J]
#endif
#if ENABLED(AUTO_BED_LEVELING_BILINEAR)
extern int bilinear_grid_spacing[2], bilinear_start[2];
extern float bilinear_grid_factor[2],
z_values[GRID_MAX_POINTS_X][GRID_MAX_POINTS_Y];
float bilinear_z_offset(const float raw[XYZ]);
#endif
#if ENABLED(AUTO_BED_LEVELING_BILINEAR) || ENABLED(MESH_BED_LEVELING)
typedef float (*element_2d_fn)(const uint8_t, const uint8_t);
void print_2d_array(const uint8_t sx, const uint8_t sy, const uint8_t precision, const element_2d_fn fn);
#endif
#if HAS_LEVELING
bool leveling_is_valid();
void set_bed_leveling_enabled(const bool enable=true);
void reset_bed_level();
#endif
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
void set_z_fade_height(const float zfh, const bool do_report=true);
#endif
#if HAS_BED_PROBE
extern float zprobe_zoffset;
bool set_probe_deployed(const bool deploy);
#ifdef Z_AFTER_PROBING
void move_z_after_probing();
#endif
enum ProbePtRaise : unsigned char {
PROBE_PT_NONE, // No raise or stow after run_z_probe
PROBE_PT_STOW, // Do a complete stow after run_z_probe
PROBE_PT_RAISE, // Raise to "between" clearance after run_z_probe
PROBE_PT_BIG_RAISE // Raise to big clearance after run_z_probe
};
float probe_pt(const float &rx, const float &ry, const ProbePtRaise raise_after=PROBE_PT_NONE, const uint8_t verbose_level=0, const bool probe_relative=true);
#define DEPLOY_PROBE() set_probe_deployed(true)
#define STOW_PROBE() set_probe_deployed(false)
#else
#define DEPLOY_PROBE()
#define STOW_PROBE()
#endif
#if ENABLED(HOST_KEEPALIVE_FEATURE)
extern MarlinBusyState busy_state;
#define KEEPALIVE_STATE(n) do{ busy_state = n; }while(0)
#else
#define KEEPALIVE_STATE(n) NOOP
#endif
#if FAN_COUNT > 0
extern int16_t fanSpeeds[FAN_COUNT];
#if ENABLED(EXTRA_FAN_SPEED)
extern int16_t old_fanSpeeds[FAN_COUNT],
new_fanSpeeds[FAN_COUNT];
#endif
#if ENABLED(PROBING_FANS_OFF)
extern bool fans_paused;
extern int16_t paused_fanSpeeds[FAN_COUNT];
#endif
#endif
#if ENABLED(USE_CONTROLLER_FAN)
extern int controllerFanSpeed;
#endif
#if ENABLED(BARICUDA)
extern uint8_t baricuda_valve_pressure, baricuda_e_to_p_pressure;
#endif
#if ENABLED(FILAMENT_WIDTH_SENSOR)
extern bool filament_sensor; // Flag that filament sensor readings should control extrusion
extern float filament_width_nominal, // Theoretical filament diameter i.e., 3.00 or 1.75
filament_width_meas; // Measured filament diameter
extern uint8_t meas_delay_cm; // Delay distance
extern int8_t measurement_delay[MAX_MEASUREMENT_DELAY + 1], // Ring buffer to delay measurement
filwidth_delay_index[2]; // Ring buffer indexes. Used by planner, temperature, and main code
#endif
#if ENABLED(ADVANCED_PAUSE_FEATURE)
extern int8_t did_pause_print;
extern AdvancedPauseMenuResponse advanced_pause_menu_response;
extern float filament_change_unload_length[EXTRUDERS],
filament_change_load_length[EXTRUDERS];
#endif
#if HAS_POWER_SWITCH
extern bool powersupply_on;
#define PSU_PIN_ON() do{ OUT_WRITE(PS_ON_PIN, PS_ON_AWAKE); powersupply_on = true; }while(0)
#define PSU_PIN_OFF() do{ OUT_WRITE(PS_ON_PIN, PS_ON_ASLEEP); powersupply_on = false; }while(0)
#endif
// Handling multiple extruders pins
extern uint8_t active_extruder;
#if ENABLED(MIXING_EXTRUDER)
extern float mixing_factor[MIXING_STEPPERS];
#endif
inline void set_current_from_destination() { COPY(current_position, destination); }
inline void set_destination_from_current() { COPY(destination, current_position); }
void prepare_move_to_destination();
/**
* Blocking movement and shorthand functions
*/
void do_blocking_move_to(const float rx, const float ry, const float rz, const float &fr_mm_s=0);
void do_blocking_move_to_x(const float &rx, const float &fr_mm_s=0);
void do_blocking_move_to_z(const float &rz, const float &fr_mm_s=0);
void do_blocking_move_to_xy(const float &rx, const float &ry, const float &fr_mm_s=0);
#if ENABLED(ARC_SUPPORT)
void plan_arc(const float(&cart)[XYZE], const float(&offset)[2], const bool clockwise);
#endif
#define HAS_AXIS_UNHOMED_ERR ( \
ENABLED(Z_PROBE_ALLEN_KEY) \
|| ENABLED(Z_PROBE_SLED) \
|| HAS_PROBING_PROCEDURE \
|| HOTENDS > 1 \
|| ENABLED(NOZZLE_CLEAN_FEATURE) \
|| ENABLED(NOZZLE_PARK_FEATURE) \
|| (ENABLED(ADVANCED_PAUSE_FEATURE) && ENABLED(HOME_BEFORE_FILAMENT_CHANGE)) \
|| HAS_M206_COMMAND \
) || ENABLED(NO_MOTION_BEFORE_HOMING)
#if HAS_AXIS_UNHOMED_ERR
bool axis_unhomed_error(const bool x=true, const bool y=true, const bool z=true);
#endif
/**
* position_is_reachable family of functions
*/
#if IS_KINEMATIC // (DELTA or SCARA)
#if IS_SCARA
extern const float L1, L2;
#endif
// Return true if the given point is within the printable area
inline bool position_is_reachable(const float &rx, const float &ry, const float inset=0) {
#if ENABLED(DELTA)
return HYPOT2(rx, ry) <= sq(DELTA_PRINTABLE_RADIUS - inset);
#elif ENABLED(HANGPRINTER)
// TODO: This is over simplified. Hangprinter's build volume is _not_ cylindrical.
return HYPOT2(rx, ry) <= sq(HANGPRINTER_PRINTABLE_RADIUS - inset);
#elif IS_SCARA
const float R2 = HYPOT2(rx - SCARA_OFFSET_X, ry - SCARA_OFFSET_Y);
return (
R2 <= sq(L1 + L2) - inset
#if MIDDLE_DEAD_ZONE_R > 0
&& R2 >= sq(float(MIDDLE_DEAD_ZONE_R))
#endif
);
#endif
}
#if HAS_BED_PROBE
// Return true if the both nozzle and the probe can reach the given point.
// Note: This won't work on SCARA since the probe offset rotates with the arm.
inline bool position_is_reachable_by_probe(const float &rx, const float &ry) {
return position_is_reachable(rx - (X_PROBE_OFFSET_FROM_EXTRUDER), ry - (Y_PROBE_OFFSET_FROM_EXTRUDER))
&& position_is_reachable(rx, ry, ABS(MIN_PROBE_EDGE));
}
#endif
#else // CARTESIAN
// Return true if the given position is within the machine bounds.
inline bool position_is_reachable(const float &rx, const float &ry) {
// Add 0.001 margin to deal with float imprecision
return WITHIN(rx, X_MIN_POS - 0.001f, X_MAX_POS + 0.001f)
&& WITHIN(ry, Y_MIN_POS - 0.001f, Y_MAX_POS + 0.001f);
}
#if HAS_BED_PROBE
/**
* Return whether the given position is within the bed, and whether the nozzle
* can reach the position required to put the probe at the given position.
*
* Example: For a probe offset of -10,+10, then for the probe to reach 0,0 the
* nozzle must be be able to reach +10,-10.
*/
inline bool position_is_reachable_by_probe(const float &rx, const float &ry) {
return position_is_reachable(rx - (X_PROBE_OFFSET_FROM_EXTRUDER), ry - (Y_PROBE_OFFSET_FROM_EXTRUDER))
&& WITHIN(rx, MIN_PROBE_X - 0.001f, MAX_PROBE_X + 0.001f)
&& WITHIN(ry, MIN_PROBE_Y - 0.001f, MAX_PROBE_Y + 0.001f);
}
#endif
#endif // CARTESIAN
#if !HAS_BED_PROBE
FORCE_INLINE bool position_is_reachable_by_probe(const float &rx, const float &ry) { return position_is_reachable(rx, ry); }
#endif
#endif // MARLIN_H

53
Marlin/Marlin.ino Normal file
View File

@ -0,0 +1,53 @@
/*
================================================================================
Marlin Firmware
(c) 2011-2018 MarlinFirmware
Portions of Marlin are (c) by their respective authors.
All code complies with GPLv2 and/or GPLv3
================================================================================
Greetings! Thank you for choosing Marlin as your 3D printer firmware.
To configure Marlin you must edit Configuration.h and Configuration_adv.h
located in the root 'Marlin' folder. Check the example_configurations folder 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
- http://marlinfw.org/
The official Marlin Firmware website contains the most up-to-date
documentation. Contributions are always welcome!
Configuration
- https://www.youtube.com/watch?v=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
- http://marlinfw.org/docs/configuration/configuration.html
Marlin's configuration options are explained in more detail here.
Getting Help
- http://forums.reprap.org/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
- http://marlinfw.org/docs/development/contributing.html
If you'd like to contribute to Marlin, read this first!
- http://marlinfw.org/docs/development/coding_standards.html
Before submitting code get to know the Coding Standards.
*/

48
Marlin/MarlinConfig.h Normal file
View File

@ -0,0 +1,48 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef MARLIN_CONFIG_H
#define MARLIN_CONFIG_H
#include "boards.h"
#include "macros.h"
#include "Version.h"
#include "Configuration.h"
#include "Conditionals_LCD.h"
#include "drivers.h"
#include "Configuration_adv.h"
#if USE_MARLINSERIAL
#define HardwareSerial_h // trick to disable the standard HWserial
#endif
#include "types.h"
#include "HAL.h"
#include "pins.h"
#include "Conditionals_post.h"
#include "SanityCheck.h"
#include "enum.h"
#include "language.h"
#include "utility.h"
#include "serial.h"
#endif // MARLIN_CONFIG_H

57
Marlin/MarlinSPI.h Normal file
View File

@ -0,0 +1,57 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef __MARLIN_SPI_H__
#define __MARLIN_SPI_H__
#include <stdint.h>
#include "softspi.h"
template<uint8_t MisoPin, uint8_t MosiPin, uint8_t SckPin>
class SPI {
static SoftSPI<MisoPin, MosiPin, SckPin> softSPI;
public:
FORCE_INLINE static void init() { softSPI.begin(); }
FORCE_INLINE static void send(uint8_t data) { softSPI.send(data); }
FORCE_INLINE static uint8_t receive() { return softSPI.receive(); }
};
// Hardware SPI
template<>
class SPI<MISO_PIN, MOSI_PIN, SCK_PIN> {
public:
FORCE_INLINE static void init() {
OUT_WRITE(SCK_PIN, LOW);
OUT_WRITE(MOSI_PIN, HIGH);
SET_INPUT(MISO_PIN);
WRITE(MISO_PIN, HIGH);
}
FORCE_INLINE static uint8_t receive() {
SPDR = 0;
while (!TEST(SPSR, SPIF)) { /* nada */ }
return SPDR;
}
};
#endif // __MARLIN_SPI_H__

740
Marlin/MarlinSerial.cpp Normal file
View File

@ -0,0 +1,740 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* 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)
*/
// Disable HardwareSerial.cpp to support chips without a UART (Attiny, etc.)
#include "MarlinConfig.h"
#if USE_MARLINSERIAL && (defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) || defined(UBRR2H) || defined(UBRR3H))
#include "MarlinSerial.h"
#include "Marlin.h"
struct ring_buffer_r {
unsigned char buffer[RX_BUFFER_SIZE];
volatile ring_buffer_pos_t head, tail;
};
#if TX_BUFFER_SIZE > 0
struct ring_buffer_t {
unsigned char buffer[TX_BUFFER_SIZE];
volatile uint8_t head, tail;
};
#endif
#if UART_PRESENT(SERIAL_PORT)
ring_buffer_r rx_buffer = { { 0 }, 0, 0 };
#if TX_BUFFER_SIZE > 0
ring_buffer_t tx_buffer = { { 0 }, 0, 0 };
#endif
static bool _written;
#endif
#if ENABLED(SERIAL_XON_XOFF)
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
constexpr uint8_t XON_CHAR = 17, XOFF_CHAR = 19;
uint8_t xon_xoff_state = XON_XOFF_CHAR_SENT | XON_CHAR;
#endif
#if ENABLED(SERIAL_STATS_DROPPED_RX)
uint8_t rx_dropped_bytes = 0;
#endif
#if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
uint8_t rx_buffer_overruns = 0;
#endif
#if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
uint8_t rx_framing_errors = 0;
#endif
#if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
ring_buffer_pos_t rx_max_enqueued = 0;
#endif
// A SW memory barrier, to ensure GCC does not overoptimize loops
#define sw_barrier() asm volatile("": : :"memory");
#if ENABLED(EMERGENCY_PARSER)
#include "emergency_parser.h"
#endif
// "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!
FORCE_INLINE ring_buffer_pos_t atomic_read_rx_head() {
#if RX_BUFFER_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;
#endif
}
#if RX_BUFFER_SIZE > 256
static volatile bool rx_tail_value_not_stable = false;
static volatile uint16_t rx_tail_value_backup = 0;
#endif
// 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 -
FORCE_INLINE void atomic_set_rx_tail(ring_buffer_pos_t value) {
#if RX_BUFFER_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;
#endif
}
// 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 -
FORCE_INLINE ring_buffer_pos_t atomic_read_rx_tail() {
#if RX_BUFFER_SIZE > 256
// If the true index is being modified, return the backup value
if (rx_tail_value_not_stable) return rx_tail_value_backup;
#endif
// The true index is stable, return it
return rx_buffer.tail;
}
// (called with RX interrupts disabled)
FORCE_INLINE void store_rxd_char() {
// 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)(RX_BUFFER_SIZE - 1);
// This must read the M_UCSRxA register before reading the received byte to detect error causes
#if ENABLED(SERIAL_STATS_DROPPED_RX)
if (TEST(M_UCSRxA, M_DORx) && !++rx_dropped_bytes) --rx_dropped_bytes;
#endif
#if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
if (TEST(M_UCSRxA, M_DORx) && !++rx_buffer_overruns) --rx_buffer_overruns;
#endif
#if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
if (TEST(M_UCSRxA, M_FEx) && !++rx_framing_errors) --rx_framing_errors;
#endif
// Read the character from the USART
uint8_t c = M_UDRx;
#if ENABLED(EMERGENCY_PARSER)
emergency_parser.update(c);
#endif
// 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;
}
#if ENABLED(SERIAL_STATS_DROPPED_RX)
else if (!++rx_dropped_bytes) --rx_dropped_bytes;
#endif
#if ENABLED(SERIAL_STATS_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)(RX_BUFFER_SIZE - 1);
// Keep track of the maximum count of enqueued bytes
NOLESS(rx_max_enqueued, rx_count);
#endif
#if ENABLED(SERIAL_XON_XOFF)
// 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)(RX_BUFFER_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 >= (RX_BUFFER_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 (!TEST(M_UCSRxA, M_UDREx)) {
if (TEST(M_UCSRxA,M_RXCx)) {
// 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)(RX_BUFFER_SIZE - 1);
// Read the character from the USART
c = M_UDRx;
#if ENABLED(EMERGENCY_PARSER)
emergency_parser.update(c);
#endif
// 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;
}
#if ENABLED(SERIAL_STATS_DROPPED_RX)
else if (!++rx_dropped_bytes) --rx_dropped_bytes;
#endif
}
sw_barrier();
}
M_UDRx = 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
SBI(M_UCSRxA, M_TXCx);
// 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 (!TEST(M_UCSRxA, M_UDREx)) {
if (TEST(M_UCSRxA,M_RXCx)) {
// 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)(RX_BUFFER_SIZE - 1);
// Read the character from the USART
c = M_UDRx;
#if ENABLED(EMERGENCY_PARSER)
emergency_parser.update(c);
#endif
// 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;
}
#if ENABLED(SERIAL_STATS_DROPPED_RX)
else if (!++rx_dropped_bytes) --rx_dropped_bytes;
#endif
}
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!
}
}
#endif // SERIAL_XON_XOFF
// Store the new head value - The main loop will retry until the value is stable
rx_buffer.head = h;
}
#if TX_BUFFER_SIZE > 0
// (called with TX irqs disabled)
FORCE_INLINE void _tx_udr_empty_irq(void) {
// Read positions
uint8_t t = tx_buffer.tail;
const uint8_t h = tx_buffer.head;
#if ENABLED(SERIAL_XON_XOFF)
// If an XON char is pending to be sent, do it now
if (xon_xoff_state == XON_CHAR) {
// Send the character
M_UDRx = 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
SBI(M_UCSRxA, M_TXCx);
// 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) CBI(M_UCSRxB, M_UDRIEx); // (Non-atomic, could be reenabled by the main program, but eventually this will succeed)
return;
}
#endif
// 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) {
CBI(M_UCSRxB, M_UDRIEx); // (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) & (TX_BUFFER_SIZE - 1);
M_UDRx = 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/
SBI(M_UCSRxA, M_TXCx);
// Disable interrupts if there is nothing to transmit following this byte
if (h == t) CBI(M_UCSRxB, M_UDRIEx); // (Non-atomic, could be reenabled by the main program, but eventually this will succeed)
}
#ifdef M_USARTx_UDRE_vect
ISR(M_USARTx_UDRE_vect) { _tx_udr_empty_irq(); }
#endif
#endif // TX_BUFFER_SIZE
#ifdef M_USARTx_RX_vect
ISR(M_USARTx_RX_vect) { store_rxd_char(); }
#endif
// Public Methods
void MarlinSerial::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
if (useU2X) {
M_UCSRxA = _BV(M_U2Xx);
baud_setting = (F_CPU / 4 / baud - 1) / 2;
}
else {
M_UCSRxA = 0;
baud_setting = (F_CPU / 8 / baud - 1) / 2;
}
// assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register)
M_UBRRxH = baud_setting >> 8;
M_UBRRxL = baud_setting;
SBI(M_UCSRxB, M_RXENx);
SBI(M_UCSRxB, M_TXENx);
SBI(M_UCSRxB, M_RXCIEx);
#if TX_BUFFER_SIZE > 0
CBI(M_UCSRxB, M_UDRIEx);
#endif
_written = false;
}
void MarlinSerial::end() {
CBI(M_UCSRxB, M_RXENx);
CBI(M_UCSRxB, M_TXENx);
CBI(M_UCSRxB, M_RXCIEx);
CBI(M_UCSRxB, M_UDRIEx);
}
int MarlinSerial::peek(void) {
const ring_buffer_pos_t h = atomic_read_rx_head(), t = rx_buffer.tail;
return h == t ? -1 : rx_buffer.buffer[t];
}
int MarlinSerial::read(void) {
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) & (RX_BUFFER_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 ENABLED(SERIAL_XON_XOFF)
// 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)(RX_BUFFER_SIZE - 1);
if (rx_count < (RX_BUFFER_SIZE) / 10) {
#if TX_BUFFER_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
SBI(M_UCSRxB, M_UDRIEx);
#else
// If not using TX interrupts, we must send the XON char now
xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
while (!TEST(M_UCSRxA, M_UDREx)) sw_barrier();
M_UDRx = XON_CHAR;
#endif
}
}
#endif
return v;
}
ring_buffer_pos_t MarlinSerial::available(void) {
const ring_buffer_pos_t h = atomic_read_rx_head(), t = rx_buffer.tail;
return (ring_buffer_pos_t)(RX_BUFFER_SIZE + h - t) & (RX_BUFFER_SIZE - 1);
}
void MarlinSerial::flush(void) {
// 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 ENABLED(SERIAL_XON_XOFF)
// If the XOFF char was sent, or about to be sent...
if ((xon_xoff_state & XON_XOFF_CHAR_MASK) == XOFF_CHAR) {
#if TX_BUFFER_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.
SBI(M_UCSRxB, M_UDRIEx);
#else
// If not using TX interrupts, we must send the XON char now
xon_xoff_state = XON_CHAR | XON_XOFF_CHAR_SENT;
while (!TEST(M_UCSRxA, M_UDREx)) sw_barrier();
M_UDRx = XON_CHAR;
#endif
}
#endif
}
#if TX_BUFFER_SIZE > 0
void MarlinSerial::write(const uint8_t c) {
_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 (!TEST(M_UCSRxB, M_UDRIEx) && TEST(M_UCSRxA, M_UDREx)) {
M_UDRx = 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
SBI(M_UCSRxA, M_TXCx);
return;
}
const uint8_t i = (tx_buffer.head + 1) & (TX_BUFFER_SIZE - 1);
// If global interrupts are disabled (as the result of being called from an ISR)...
if (!ISRS_ENABLED()) {
// 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 (TEST(M_UCSRxA, M_UDREx)) _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
SBI(M_UCSRxB, M_UDRIEx);
}
void MarlinSerial::flushTX(void) {
// 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 (!ISRS_ENABLED()) {
// Wait until everything was transmitted - We must do polling, as interrupts are disabled
while (tx_buffer.head != tx_buffer.tail || !TEST(M_UCSRxA, M_TXCx)) {
// If there is more space, send an extra character
if (TEST(M_UCSRxA, M_UDREx))
_tx_udr_empty_irq();
sw_barrier();
}
}
else {
// Wait until everything was transmitted
while (tx_buffer.head != tx_buffer.tail || !TEST(M_UCSRxA, M_TXCx)) sw_barrier();
}
// At this point nothing is queued anymore (DRIE is disabled) and
// the hardware finished transmission (TXC is set).
}
#else // TX_BUFFER_SIZE == 0
void MarlinSerial::write(const uint8_t c) {
_written = true;
while (!TEST(M_UCSRxA, M_UDREx)) sw_barrier();
M_UDRx = c;
}
void MarlinSerial::flushTX(void) {
// 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 (!TEST(M_UCSRxA, M_TXCx)) sw_barrier();
// At this point nothing is queued anymore (DRIE is disabled) and
// the hardware finished transmission (TXC is set).
}
#endif // TX_BUFFER_SIZE == 0
/**
* Imports from print.h
*/
void MarlinSerial::print(char c, int base) {
print((long)c, base);
}
void MarlinSerial::print(unsigned char b, int base) {
print((unsigned long)b, base);
}
void MarlinSerial::print(int n, int base) {
print((long)n, base);
}
void MarlinSerial::print(unsigned int n, int base) {
print((unsigned long)n, base);
}
void MarlinSerial::print(long n, int base) {
if (base == 0) write(n);
else if (base == 10) {
if (n < 0) { print('-'); n = -n; }
printNumber(n, 10);
}
else
printNumber(n, base);
}
void MarlinSerial::print(unsigned long n, int base) {
if (base == 0) write(n);
else printNumber(n, base);
}
void MarlinSerial::print(double n, int digits) {
printFloat(n, digits);
}
void MarlinSerial::println(void) {
print('\r');
print('\n');
}
void MarlinSerial::println(const String& s) {
print(s);
println();
}
void MarlinSerial::println(const char c[]) {
print(c);
println();
}
void MarlinSerial::println(char c, int base) {
print(c, base);
println();
}
void MarlinSerial::println(unsigned char b, int base) {
print(b, base);
println();
}
void MarlinSerial::println(int n, int base) {
print(n, base);
println();
}
void MarlinSerial::println(unsigned int n, int base) {
print(n, base);
println();
}
void MarlinSerial::println(long n, int base) {
print(n, base);
println();
}
void MarlinSerial::println(unsigned long n, int base) {
print(n, base);
println();
}
void MarlinSerial::println(double n, int digits) {
print(n, digits);
println();
}
// Private Methods
void MarlinSerial::printNumber(unsigned long n, uint8_t base) {
if (n) {
unsigned char buf[8 * sizeof(long)]; // Enough space for base 2
int8_t i = 0;
while (n) {
buf[i++] = n % base;
n /= base;
}
while (i--)
print((char)(buf[i] + (buf[i] < 10 ? '0' : 'A' - 10)));
}
else
print('0');
}
void MarlinSerial::printFloat(double number, uint8_t digits) {
// Handle negative numbers
if (number < 0.0) {
print('-');
number = -number;
}
// Round correctly so that print(1.999, 2) prints as "2.00"
double rounding = 0.5;
for (uint8_t i = 0; i < digits; ++i)
rounding *= 0.1;
number += rounding;
// Extract the integer part of the number and print it
unsigned long int_part = (unsigned long)number;
double remainder = number - (double)int_part;
print(int_part);
// Print the decimal point, but only if there are digits beyond
if (digits) {
print('.');
// Extract digits from the remainder one at a time
while (digits--) {
remainder *= 10.0;
int toPrint = int(remainder);
print(toPrint);
remainder -= toPrint;
}
}
}
// Preinstantiate
MarlinSerial customizedSerial;
#endif // USE_MARLINSERIAL && (UBRRH || UBRR0H || UBRR1H || UBRR2H || UBRR3H)
// For AT90USB targets use the UART for BT interfacing
#if !USE_MARLINSERIAL && ENABLED(BLUETOOTH)
HardwareSerial bluetoothSerial;
#endif

184
Marlin/MarlinSerial.h Normal file
View File

@ -0,0 +1,184 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* 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)
*/
#ifndef _MARLINSERIAL_H_
#define _MARLINSERIAL_H_
#include "MarlinConfig.h"
#ifndef SERIAL_PORT
#define SERIAL_PORT 0
#endif
// 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_INTERNAL(registerbase,number,suffix)
#if SERIAL_PORT == 0 && (!defined(UBRR0H) || !defined(UDR0)) // use un-numbered registers if necessary
#define SERIAL_REGNAME_INTERNAL(registerbase,number,suffix) registerbase##suffix
#else
#define SERIAL_REGNAME_INTERNAL(registerbase,number,suffix) registerbase##number##suffix
#endif
// Registers used by MarlinSerial class (expanded depending on selected serial port)
#define M_UCSRxA SERIAL_REGNAME(UCSR,SERIAL_PORT,A) // defines M_UCSRxA to be UCSRnA where n is the serial port number
#define M_UCSRxB SERIAL_REGNAME(UCSR,SERIAL_PORT,B)
#define M_RXENx SERIAL_REGNAME(RXEN,SERIAL_PORT,)
#define M_TXENx SERIAL_REGNAME(TXEN,SERIAL_PORT,)
#define M_TXCx SERIAL_REGNAME(TXC,SERIAL_PORT,)
#define M_RXCIEx SERIAL_REGNAME(RXCIE,SERIAL_PORT,)
#define M_UDREx SERIAL_REGNAME(UDRE,SERIAL_PORT,)
#define M_FEx SERIAL_REGNAME(FE,SERIAL_PORT,)
#define M_DORx SERIAL_REGNAME(DOR,SERIAL_PORT,)
#define M_UPEx SERIAL_REGNAME(UPE,SERIAL_PORT,)
#define M_UDRIEx SERIAL_REGNAME(UDRIE,SERIAL_PORT,)
#define M_UDRx SERIAL_REGNAME(UDR,SERIAL_PORT,)
#define M_UBRRxH SERIAL_REGNAME(UBRR,SERIAL_PORT,H)
#define M_UBRRxL SERIAL_REGNAME(UBRR,SERIAL_PORT,L)
#define M_RXCx SERIAL_REGNAME(RXC,SERIAL_PORT,)
#define M_USARTx_RX_vect SERIAL_REGNAME(USART,SERIAL_PORT,_RX_vect)
#define M_U2Xx SERIAL_REGNAME(U2X,SERIAL_PORT,)
#define M_USARTx_UDRE_vect SERIAL_REGNAME(USART,SERIAL_PORT,_UDRE_vect)
#define DEC 10
#define HEX 16
#define OCT 8
#define BIN 2
#define BYTE 0
// Define constants and variables for buffering serial data.
// Use only 0 or powers of 2 greater than 1
// : [0, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, ...]
#ifndef RX_BUFFER_SIZE
#define RX_BUFFER_SIZE 128
#endif
// 256 is the max TX buffer limit due to uint8_t head and tail.
#ifndef TX_BUFFER_SIZE
#define TX_BUFFER_SIZE 32
#endif
#if USE_MARLINSERIAL
#if RX_BUFFER_SIZE > 256
typedef uint16_t ring_buffer_pos_t;
#else
typedef uint8_t ring_buffer_pos_t;
#endif
#if ENABLED(SERIAL_STATS_DROPPED_RX)
extern uint8_t rx_dropped_bytes;
#endif
#if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
extern uint8_t rx_buffer_overruns;
#endif
#if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
extern uint8_t rx_framing_errors;
#endif
#if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
extern ring_buffer_pos_t rx_max_enqueued;
#endif
class MarlinSerial {
public:
MarlinSerial() {};
static void begin(const long);
static void end();
static int peek(void);
static int read(void);
static void flush(void);
static ring_buffer_pos_t available(void);
static void write(const uint8_t c);
static void flushTX(void);
#if ENABLED(SERIAL_STATS_DROPPED_RX)
FORCE_INLINE static uint32_t dropped() { return rx_dropped_bytes; }
#endif
#if ENABLED(SERIAL_STATS_RX_BUFFER_OVERRUNS)
FORCE_INLINE static uint32_t buffer_overruns() { return rx_buffer_overruns; }
#endif
#if ENABLED(SERIAL_STATS_RX_FRAMING_ERRORS)
FORCE_INLINE static uint32_t framing_errors() { return rx_framing_errors; }
#endif
#if ENABLED(SERIAL_STATS_MAX_RX_QUEUED)
FORCE_INLINE static ring_buffer_pos_t rxMaxEnqueued() { return rx_max_enqueued; }
#endif
FORCE_INLINE static void write(const char* str) { while (*str) write(*str++); }
FORCE_INLINE static void write(const uint8_t* buffer, size_t size) { while (size--) write(*buffer++); }
FORCE_INLINE static void print(const String& s) { for (int i = 0; i < (int)s.length(); i++) write(s[i]); }
FORCE_INLINE static void print(const char* str) { write(str); }
static void print(char, int = BYTE);
static void print(unsigned char, int = BYTE);
static void print(int, int = DEC);
static void print(unsigned int, int = DEC);
static void print(long, int = DEC);
static void print(unsigned long, int = DEC);
static void print(double, int = 2);
static void println(const String& s);
static void println(const char[]);
static void println(char, int = BYTE);
static void println(unsigned char, int = BYTE);
static void println(int, int = DEC);
static void println(unsigned int, int = DEC);
static void println(long, int = DEC);
static void println(unsigned long, int = DEC);
static void println(double, int = 2);
static void println(void);
operator bool() { return true; }
private:
static void printNumber(unsigned long, const uint8_t);
static void printFloat(double, uint8_t);
};
extern MarlinSerial customizedSerial;
#endif // USE_MARLINSERIAL
// Use the UART for Bluetooth in AT90USB configurations
#if !USE_MARLINSERIAL && ENABLED(BLUETOOTH)
extern HardwareSerial bluetoothSerial;
#endif
#endif // _MARLINSERIAL_H_

15377
Marlin/Marlin_main.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,593 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* This module is off by default, but can be enabled to facilitate the display of
* extra debug information during code development.
*
* Just connect up 5V and GND to give it power, then connect up the pins assigned
* in Configuration_adv.h. For example, on the Re-ARM you could use:
*
* #define MAX7219_CLK_PIN 77
* #define MAX7219_DIN_PIN 78
* #define MAX7219_LOAD_PIN 79
*
* send() is called automatically at startup, and then there are a number of
* support functions available to control the LEDs in the 8x8 grid.
*/
#include "MarlinConfig.h"
#if ENABLED(MAX7219_DEBUG)
#define MAX7219_ERRORS // Disable to save 406 bytes of Program Memory
#include "Max7219_Debug_LEDs.h"
#include "planner.h"
#include "stepper.h"
#include "Marlin.h"
#include "delay.h"
Max7219 max7219;
uint8_t Max7219::led_line[MAX7219_LINES]; // = { 0 };
#define LINE_REG(Q) (max7219_reg_digit0 + ((Q) & 0x7))
#if _ROT == 0 || _ROT == 270
#define _LED_BIT(Q) (7 - ((Q) & 0x7))
#define _LED_UNIT(Q) ((Q) & ~0x7)
#else
#define _LED_BIT(Q) ((Q) & 0x7)
#define _LED_UNIT(Q) ((MAX7219_NUMBER_UNITS - 1 - ((Q) >> 3)) << 3)
#endif
#if _ROT < 180
#define _LED_IND(P,Q) (_LED_UNIT(P) + (Q))
#else
#define _LED_IND(P,Q) (_LED_UNIT(P) + (7 - ((Q) & 0x7)))
#endif
#if _ROT == 0 || _ROT == 180
#define LED_IND(X,Y) _LED_IND(X,Y)
#define LED_BIT(X,Y) _LED_BIT(X)
#elif _ROT == 90 || _ROT == 270
#define LED_IND(X,Y) _LED_IND(Y,X)
#define LED_BIT(X,Y) _LED_BIT(Y)
#endif
#define XOR_7219(X,Y) do{ led_line[LED_IND(X,Y)] ^= _BV(LED_BIT(X,Y)); }while(0)
#define SET_7219(X,Y) do{ led_line[LED_IND(X,Y)] |= _BV(LED_BIT(X,Y)); }while(0)
#define CLR_7219(X,Y) do{ led_line[LED_IND(X,Y)] &= ~_BV(LED_BIT(X,Y)); }while(0)
#define BIT_7219(X,Y) TEST(led_line[LED_IND(X,Y)], LED_BIT(X,Y))
#ifdef CPU_32_BIT
#define SIG_DELAY() DELAY_US(1) // Approximate a 1µs delay on 32-bit ARM
#undef CRITICAL_SECTION_START
#undef CRITICAL_SECTION_END
#define CRITICAL_SECTION_START NOOP
#define CRITICAL_SECTION_END NOOP
#else
#define SIG_DELAY() DELAY_NS(188) // Delay for 0.1875µs (16MHz AVR) or 0.15µs (20MHz AVR)
#endif
void Max7219::error(const char * const func, const int32_t v1, const int32_t v2/*=-1*/) {
#if ENABLED(MAX7219_ERRORS)
SERIAL_ECHOPGM("??? Max7219::");
serialprintPGM(func);
SERIAL_CHAR('(');
SERIAL_ECHO(v1);
if (v2 > 0) SERIAL_ECHOPAIR(", ", v2);
SERIAL_CHAR(')');
SERIAL_EOL();
#else
UNUSED(func); UNUSED(v1); UNUSED(v2);
#endif
}
/**
* Flip the lowest n_bytes of the supplied bits:
* flipped(x, 1) flips the low 8 bits of x.
* flipped(x, 2) flips the low 16 bits of x.
* flipped(x, 3) flips the low 24 bits of x.
* flipped(x, 4) flips the low 32 bits of x.
*/
inline uint32_t flipped(const uint32_t bits, const uint8_t n_bytes) {
uint32_t mask = 1, outbits = 0;
for (uint8_t b = 0; b < n_bytes * 8; b++) {
outbits <<= 1;
if (bits & mask) outbits |= 1;
mask <<= 1;
}
return outbits;
}
void Max7219::noop() {
CRITICAL_SECTION_START;
SIG_DELAY();
WRITE(MAX7219_DIN_PIN, LOW);
for (uint8_t i = 16; i--;) {
SIG_DELAY();
WRITE(MAX7219_CLK_PIN, LOW);
SIG_DELAY();
SIG_DELAY();
WRITE(MAX7219_CLK_PIN, HIGH);
SIG_DELAY();
}
CRITICAL_SECTION_END;
}
void Max7219::putbyte(uint8_t data) {
CRITICAL_SECTION_START;
for (uint8_t i = 8; i--;) {
SIG_DELAY();
WRITE(MAX7219_CLK_PIN, LOW); // tick
SIG_DELAY();
WRITE(MAX7219_DIN_PIN, (data & 0x80) ? HIGH : LOW); // send 1 or 0 based on data bit
SIG_DELAY();
WRITE(MAX7219_CLK_PIN, HIGH); // tock
SIG_DELAY();
data <<= 1;
}
CRITICAL_SECTION_END;
}
void Max7219::pulse_load() {
SIG_DELAY();
WRITE(MAX7219_LOAD_PIN, LOW); // tell the chip to load the data
SIG_DELAY();
WRITE(MAX7219_LOAD_PIN, HIGH);
SIG_DELAY();
}
void Max7219::send(const uint8_t reg, const uint8_t data) {
SIG_DELAY();
CRITICAL_SECTION_START;
SIG_DELAY();
putbyte(reg); // specify register
SIG_DELAY();
putbyte(data); // put data
CRITICAL_SECTION_END;
}
// Send out a single native row of bits to all units
void Max7219::refresh_line(const uint8_t line) {
for (uint8_t u = MAX7219_NUMBER_UNITS; u--;)
send(LINE_REG(line), led_line[(u << 3) | (line & 0x7)]);
pulse_load();
}
// Send out a single native row of bits to just one unit
void Max7219::refresh_unit_line(const uint8_t line) {
for (uint8_t u = MAX7219_NUMBER_UNITS; u--;)
if (u == (line >> 3)) send(LINE_REG(line), led_line[line]); else noop();
pulse_load();
}
void Max7219::set(const uint8_t line, const uint8_t bits) {
led_line[line] = bits;
refresh_line(line);
}
#if ENABLED(MAX7219_NUMERIC)
// Draw an integer with optional leading zeros and optional decimal point
void Max7219::print(const uint8_t start, int16_t value, uint8_t size, const bool leadzero=false, bool dec=false) {
constexpr uint8_t led_numeral[10] = { 0x7E, 0x60, 0x6D, 0x79, 0x63, 0x5B, 0x5F, 0x70, 0x7F, 0x7A },
led_decimal = 0x80, led_minus = 0x01;
bool blank = false, neg = value < 0;
if (neg) value *= -1;
while (size--) {
const bool minus = neg && blank;
if (minus) neg = false;
send(
max7219_reg_digit0 + start + size,
minus ? led_minus : blank ? 0x00 : led_numeral[value % 10] | (dec ? led_decimal : 0x00)
);
pulse_load(); // tell the chips to load the clocked out data
value /= 10;
if (!value && !leadzero) blank = true;
dec = false;
}
}
// Draw a float with a decimal point and optional digits
void Max7219::print(const uint8_t start, const float value, const uint8_t pre_size, const uint8_t post_size, const bool leadzero=false) {
if (pre_size) print(start, value, pre_size, leadzero, !!post_size);
if (post_size) {
const int16_t after = ABS(value) * (10 ^ post_size);
print(start + pre_size, after, post_size, true);
}
}
#endif // MAX7219_NUMERIC
// Modify a single LED bit and send the changed line
void Max7219::led_set(const uint8_t x, const uint8_t y, const bool on) {
if (x > MAX7219_X_LEDS - 1 || y > MAX7219_Y_LEDS - 1) return error(PSTR("led_set"), x, y);
if (BIT_7219(x, y) == on) return;
XOR_7219(x, y);
refresh_line(LED_IND(x, y));
}
void Max7219::led_on(const uint8_t x, const uint8_t y) {
if (x > MAX7219_X_LEDS - 1 || y > MAX7219_Y_LEDS - 1) return error(PSTR("led_on"), x, y);
led_set(x, y, true);
}
void Max7219::led_off(const uint8_t x, const uint8_t y) {
if (x > MAX7219_X_LEDS - 1 || y > MAX7219_Y_LEDS - 1) return error(PSTR("led_off"), x, y);
led_set(x, y, false);
}
void Max7219::led_toggle(const uint8_t x, const uint8_t y) {
if (x > MAX7219_X_LEDS - 1 || y > MAX7219_Y_LEDS - 1) return error(PSTR("led_toggle"), x, y);
led_set(x, y, !BIT_7219(x, y));
}
void Max7219::send_row(const uint8_t row) {
#if _ROT == 0 || _ROT == 180
refresh_line(LED_IND(0, row));
#else
UNUSED(row);
refresh();
#endif
}
void Max7219::send_column(const uint8_t col) {
#if _ROT == 90 || _ROT == 270
refresh_line(LED_IND(col, 0));
#else
UNUSED(col);
refresh();
#endif
}
void Max7219::clear() {
ZERO(led_line);
refresh();
}
void Max7219::fill() {
memset(led_line, 0xFF, sizeof(led_line));
refresh();
}
void Max7219::clear_row(const uint8_t row) {
if (row >= MAX7219_Y_LEDS) return error(PSTR("clear_row"), row);
for (uint8_t x = 0; x < MAX7219_X_LEDS; x++) CLR_7219(x, row);
send_row(row);
}
void Max7219::clear_column(const uint8_t col) {
if (col >= MAX7219_X_LEDS) return error(PSTR("set_column"), col);
for (uint8_t y = 0; y < MAX7219_Y_LEDS; y++) CLR_7219(col, y);
send_column(col);
}
/**
* Plot the low order bits of val to the specified row of the matrix.
* With 4 Max7219 units in the chain, it's possible to set 32 bits at once with
* one call to the function (if rotated 90° or 180°).
*/
void Max7219::set_row(const uint8_t row, const uint32_t val) {
if (row >= MAX7219_Y_LEDS) return error(PSTR("set_row"), row);
uint32_t mask = _BV32(MAX7219_X_LEDS - 1);
for (uint8_t x = 0; x < MAX7219_X_LEDS; x++) {
if (val & mask) SET_7219(x, row); else CLR_7219(x, row);
mask >>= 1;
}
send_row(row);
}
/**
* Plot the low order bits of val to the specified column of the matrix.
* With 4 Max7219 units in the chain, it's possible to set 32 bits at once with
* one call to the function (if rotated 90° or 180°).
*/
void Max7219::set_column(const uint8_t col, const uint32_t val) {
if (col >= MAX7219_X_LEDS) return error(PSTR("set_column"), col);
uint32_t mask = _BV32(MAX7219_Y_LEDS - 1);
for (uint8_t y = 0; y < MAX7219_Y_LEDS; y++) {
if (val & mask) SET_7219(col, y); else CLR_7219(col, y);
mask >>= 1;
}
send_column(col);
}
void Max7219::set_rows_16bits(const uint8_t y, uint32_t val) {
#if MAX7219_X_LEDS == 8
if (y > MAX7219_Y_LEDS - 2) return error(PSTR("set_rows_16bits"), y, val);
set_row(y + 1, val); val >>= 8;
set_row(y + 0, val);
#else // at least 16 bits on each row
if (y > MAX7219_Y_LEDS - 1) return error(PSTR("set_rows_16bits"), y, val);
set_row(y, val);
#endif
}
void Max7219::set_rows_32bits(const uint8_t y, uint32_t val) {
#if MAX7219_X_LEDS == 8
if (y > MAX7219_Y_LEDS - 4) return error(PSTR("set_rows_32bits"), y, val);
set_row(y + 3, val); val >>= 8;
set_row(y + 2, val); val >>= 8;
set_row(y + 1, val); val >>= 8;
set_row(y + 0, val);
#elif MAX7219_X_LEDS == 16
if (y > MAX7219_Y_LEDS - 2) return error(PSTR("set_rows_32bits"), y, val);
set_row(y + 1, val); val >>= 16;
set_row(y + 0, val);
#else // at least 24 bits on each row. In the 3 matrix case, just display the low 24 bits
if (y > MAX7219_Y_LEDS - 1) return error(PSTR("set_rows_32bits"), y, val);
set_row(y, val);
#endif
}
void Max7219::set_columns_16bits(const uint8_t x, uint32_t val) {
#if MAX7219_Y_LEDS == 8
if (x > MAX7219_X_LEDS - 2) return error(PSTR("set_columns_16bits"), x, val);
set_column(x + 0, val); val >>= 8;
set_column(x + 1, val);
#else // at least 16 bits in each column
if (x > MAX7219_X_LEDS - 1) return error(PSTR("set_columns_16bits"), x, val);
set_column(x, val);
#endif
}
void Max7219::set_columns_32bits(const uint8_t x, uint32_t val) {
#if MAX7219_Y_LEDS == 8
if (x > MAX7219_X_LEDS - 4) return error(PSTR("set_rows_32bits"), x, val);
set_column(x + 3, val); val >>= 8;
set_column(x + 2, val); val >>= 8;
set_column(x + 1, val); val >>= 8;
set_column(x + 0, val);
#elif MAX7219_Y_LEDS == 16
if (x > MAX7219_X_LEDS - 2) return error(PSTR("set_rows_32bits"), x, val);
set_column(x + 1, val); val >>= 16;
set_column(x + 0, val);
#else // at least 24 bits on each row. In the 3 matrix case, just display the low 24 bits
if (x > MAX7219_X_LEDS - 1) return error(PSTR("set_rows_32bits"), x, val);
set_column(x, val);
#endif
}
// Initialize the Max7219
void Max7219::register_setup() {
for (uint8_t i = 0; i < MAX7219_NUMBER_UNITS; i++)
send(max7219_reg_scanLimit, 0x07);
pulse_load(); // tell the chips to load the clocked out data
for (uint8_t i = 0; i < MAX7219_NUMBER_UNITS; i++)
send(max7219_reg_decodeMode, 0x00); // using an led matrix (not digits)
pulse_load(); // tell the chips to load the clocked out data
for (uint8_t i = 0; i < MAX7219_NUMBER_UNITS; i++)
send(max7219_reg_shutdown, 0x01); // not in shutdown mode
pulse_load(); // tell the chips to load the clocked out data
for (uint8_t i = 0; i < MAX7219_NUMBER_UNITS; i++)
send(max7219_reg_displayTest, 0x00); // no display test
pulse_load(); // tell the chips to load the clocked out data
for (uint8_t i = 0; i < MAX7219_NUMBER_UNITS; i++)
send(max7219_reg_intensity, 0x01 & 0x0F); // the first 0x0F is the value you can set
// range: 0x00 to 0x0F
pulse_load(); // tell the chips to load the clocked out data
}
#ifdef MAX7219_INIT_TEST
#if MAX7219_INIT_TEST == 2
void Max7219::spiral(const bool on, const uint16_t del) {
constexpr int8_t way[] = { 1, 0, 0, 1, -1, 0, 0, -1 };
int8_t px = 0, py = 0, dir = 0;
for (uint8_t i = MAX7219_X_LEDS * MAX7219_Y_LEDS; i--;) {
led_set(px, py, on);
delay(del);
const int8_t x = px + way[dir], y = py + way[dir + 1];
if (!WITHIN(x, 0, MAX7219_X_LEDS-1) || !WITHIN(y, 0, MAX7219_Y_LEDS-1) || BIT_7219(x, y) == on) dir = (dir + 2) & 0x7;
px += way[dir]; py += way[dir + 1];
}
}
#else
void Max7219::sweep(const int8_t dir, const uint16_t ms, const bool on) {
uint8_t x = dir > 0 ? 0 : MAX7219_X_LEDS-1;
for (uint8_t i = MAX7219_X_LEDS; i--; x += dir) {
set_column(x, on ? 0xFFFFFFFF : 0x00000000);
delay(ms);
}
}
#endif
#endif // MAX7219_INIT_TEST
void Max7219::init() {
SET_OUTPUT(MAX7219_DIN_PIN);
SET_OUTPUT(MAX7219_CLK_PIN);
OUT_WRITE(MAX7219_LOAD_PIN, HIGH);
delay(1);
register_setup();
for (uint8_t i = 0; i <= 7; i++) { // Empty registers to turn all LEDs off
led_line[i] = 0x00;
send(max7219_reg_digit0 + i, 0);
pulse_load(); // tell the chips to load the clocked out data
}
#ifdef MAX7219_INIT_TEST
#if MAX7219_INIT_TEST == 2
spiral(true, 8);
delay(150);
spiral(false, 8);
#else
// Do an aesthetically-pleasing pattern to fully test the Max7219 module and LEDs.
// Light up and turn off columns, both forward and backward.
sweep(1, 20, true);
sweep(1, 20, false);
delay(150);
sweep(-1, 20, true);
sweep(-1, 20, false);
#endif
#endif
}
/**
* This code demonstrates some simple debugging using a single 8x8 LED Matrix. If your feature could
* benefit from matrix display, add its code here. Very little processing is required, so the 7219 is
* ideal for debugging when realtime feedback is important but serial output can't be used.
*/
// Apply changes to update a marker
void Max7219::mark16(const uint8_t y, const uint8_t v1, const uint8_t v2) {
#if MAX7219_X_LEDS == 8
#if MAX7219_Y_LEDS == 8
led_off(v1 & 0x7, y + (v1 >= 8));
led_on(v2 & 0x7, y + (v2 >= 8));
#else
led_off(y, v1 & 0xF); // At least 16 LEDs down. Use a single column.
led_on(y, v2 & 0xF);
#endif
#else
led_off(v1 & 0xF, y); // At least 16 LEDs across. Use a single row.
led_on(v2 & 0xF, y);
#endif
}
// Apply changes to update a tail-to-head range
void Max7219::range16(const uint8_t y, const uint8_t ot, const uint8_t nt, const uint8_t oh, const uint8_t nh) {
#if MAX7219_X_LEDS == 8
#if MAX7219_Y_LEDS == 8
if (ot != nt) for (uint8_t n = ot & 0xF; n != (nt & 0xF) && n != (nh & 0xF); n = (n + 1) & 0xF)
led_off(n & 0x7, y + (n >= 8));
if (oh != nh) for (uint8_t n = (oh + 1) & 0xF; n != ((nh + 1) & 0xF); n = (n + 1) & 0xF)
led_on(n & 0x7, y + (n >= 8));
#else // The Max7219 Y-Axis has at least 16 LED's. So use a single column
if (ot != nt) for (uint8_t n = ot & 0xF; n != (nt & 0xF) && n != (nh & 0xF); n = (n + 1) & 0xF)
led_off(y, n & 0xF);
if (oh != nh) for (uint8_t n = (oh + 1) & 0xF; n != ((nh + 1) & 0xF); n = (n + 1) & 0xF)
led_on(y, n & 0xF);
#endif
#else // LED matrix has at least 16 LED's on the X-Axis. Use single line of LED's
if (ot != nt) for (uint8_t n = ot & 0xF; n != (nt & 0xF) && n != (nh & 0xF); n = (n + 1) & 0xF)
led_off(n & 0xF, y);
if (oh != nh) for (uint8_t n = (oh + 1) & 0xF; n != ((nh + 1) & 0xF); n = (n + 1) & 0xF)
led_on(n & 0xF, y);
#endif
}
// Apply changes to update a quantity
void Max7219::quantity16(const uint8_t y, const uint8_t ov, const uint8_t nv) {
for (uint8_t i = MIN(nv, ov); i < MAX(nv, ov); i++)
#if MAX7219_X_LEDS == 8
#if MAX7219_Y_LEDS == 8
led_set(i >> 1, y + (i & 1), nv >= ov); // single 8x8 LED matrix. Use two lines to get 16 LED's
#else
led_set(y, i, nv >= ov); // The Max7219 Y-Axis has at least 16 LED's. So use a single column
#endif
#else
led_set(i, y, nv >= ov); // LED matrix has at least 16 LED's on the X-Axis. Use single line of LED's
#endif
}
void Max7219::idle_tasks() {
#define MAX7219_USE_HEAD (defined(MAX7219_DEBUG_PLANNER_HEAD) || defined(MAX7219_DEBUG_PLANNER_QUEUE))
#define MAX7219_USE_TAIL (defined(MAX7219_DEBUG_PLANNER_TAIL) || defined(MAX7219_DEBUG_PLANNER_QUEUE))
#if MAX7219_USE_HEAD || MAX7219_USE_TAIL
CRITICAL_SECTION_START;
#if MAX7219_USE_HEAD
const uint8_t head = planner.block_buffer_head;
#endif
#if MAX7219_USE_TAIL
const uint8_t tail = planner.block_buffer_tail;
#endif
CRITICAL_SECTION_END;
#endif
#if ENABLED(MAX7219_DEBUG_PRINTER_ALIVE)
static uint8_t refresh_cnt; // = 0
constexpr uint16_t refresh_limit = 5;
static millis_t next_blink = 0;
const millis_t ms = millis();
const bool do_blink = ELAPSED(ms, next_blink);
#else
static uint16_t refresh_cnt; // = 0
constexpr bool do_blink = true;
constexpr uint16_t refresh_limit = 50000;
#endif
// Some Max7219 units are vulnerable to electrical noise, especially
// with long wires next to high current wires. If the display becomes
// corrupted, this will fix it within a couple seconds.
if (do_blink && ++refresh_cnt >= refresh_limit) {
refresh_cnt = 0;
register_setup();
}
#if ENABLED(MAX7219_DEBUG_PRINTER_ALIVE)
if (do_blink) {
led_toggle(MAX7219_X_LEDS - 1, MAX7219_Y_LEDS - 1);
next_blink = ms + 1000;
}
#endif
#if defined(MAX7219_DEBUG_PLANNER_HEAD) && defined(MAX7219_DEBUG_PLANNER_TAIL) && MAX7219_DEBUG_PLANNER_HEAD == MAX7219_DEBUG_PLANNER_TAIL
static int16_t last_head_cnt = 0xF, last_tail_cnt = 0xF;
if (last_head_cnt != head || last_tail_cnt != tail) {
range16(MAX7219_DEBUG_PLANNER_HEAD, last_tail_cnt, tail, last_head_cnt, head);
last_head_cnt = head;
last_tail_cnt = tail;
}
#else
#ifdef MAX7219_DEBUG_PLANNER_HEAD
static int16_t last_head_cnt = 0x1;
if (last_head_cnt != head) {
mark16(MAX7219_DEBUG_PLANNER_HEAD, last_head_cnt, head);
last_head_cnt = head;
}
#endif
#ifdef MAX7219_DEBUG_PLANNER_TAIL
static int16_t last_tail_cnt = 0x1;
if (last_tail_cnt != tail) {
mark16(MAX7219_DEBUG_PLANNER_TAIL, last_tail_cnt, tail);
last_tail_cnt = tail;
}
#endif
#endif
#ifdef MAX7219_DEBUG_PLANNER_QUEUE
static int16_t last_depth = 0;
const int16_t current_depth = (head - tail + BLOCK_BUFFER_SIZE) & (BLOCK_BUFFER_SIZE - 1) & 0xF;
if (current_depth != last_depth) {
quantity16(MAX7219_DEBUG_PLANNER_QUEUE, last_depth, current_depth);
last_depth = current_depth;
}
#endif
}
#endif // MAX7219_DEBUG

154
Marlin/Max7219_Debug_LEDs.h Normal file
View File

@ -0,0 +1,154 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* This module is off by default, but can be enabled to facilitate the display of
* extra debug information during code development.
*
* Just connect up 5V and GND to give it power, then connect up the pins assigned
* in Configuration_adv.h. For example, on the Re-ARM you could use:
*
* #define MAX7219_CLK_PIN 77
* #define MAX7219_DIN_PIN 78
* #define MAX7219_LOAD_PIN 79
*
* max7219.init() is called automatically at startup, and then there are a number of
* support functions available to control the LEDs in the 8x8 grid.
*
* If you are using the Max7219 matrix for firmware debug purposes in time sensitive
* areas of the code, please be aware that the orientation (rotation) of the display can
* affect the speed. The Max7219 can update a single column fairly fast. It is much
* faster to do a Max7219_Set_Column() with a rotation of 90 or 270 degrees than to do
* a Max7219_Set_Row(). The opposite is true for rotations of 0 or 180 degrees.
*/
#pragma once
#ifndef MAX7219_ROTATE
#define MAX7219_ROTATE 0
#endif
#define _ROT ((MAX7219_ROTATE + 360) % 360)
#define MAX7219_LINES (8 * (MAX7219_NUMBER_UNITS))
#if _ROT == 0 || _ROT == 180
#define MAX7219_Y_LEDS 8
#define MAX7219_X_LEDS MAX7219_LINES
#elif _ROT == 90 || _ROT == 270
#define MAX7219_X_LEDS 8
#define MAX7219_Y_LEDS MAX7219_LINES
#else
#error "MAX7219_ROTATE must be a multiple of +/- 90°."
#endif
//
// MAX7219 registers
//
#define max7219_reg_noop 0x00
#define max7219_reg_digit0 0x01
#define max7219_reg_digit1 0x02
#define max7219_reg_digit2 0x03
#define max7219_reg_digit3 0x04
#define max7219_reg_digit4 0x05
#define max7219_reg_digit5 0x06
#define max7219_reg_digit6 0x07
#define max7219_reg_digit7 0x08
#define max7219_reg_decodeMode 0x09
#define max7219_reg_intensity 0x0A
#define max7219_reg_scanLimit 0x0B
#define max7219_reg_shutdown 0x0C
#define max7219_reg_displayTest 0x0F
class Max7219 {
public:
static uint8_t led_line[MAX7219_LINES];
Max7219() { }
static void init();
static void register_setup();
static void putbyte(uint8_t data);
static void pulse_load();
// Set a single register (e.g., a whole native row)
static void send(const uint8_t reg, const uint8_t data);
// Refresh all units
inline static void refresh() { for (uint8_t i = 0; i < 8; i++) refresh_line(i); }
// Update a single native line on all units
static void refresh_line(const uint8_t line);
// Update a single native line on just one unit
static void refresh_unit_line(const uint8_t line);
// Set a single LED by XY coordinate
static void led_set(const uint8_t x, const uint8_t y, const bool on);
static void led_on(const uint8_t x, const uint8_t y);
static void led_off(const uint8_t x, const uint8_t y);
static void led_toggle(const uint8_t x, const uint8_t y);
// Set all LEDs in a single column
static void set_column(const uint8_t col, const uint32_t val);
static void clear_column(const uint8_t col);
// Set all LEDs in a single row
static void set_row(const uint8_t row, const uint32_t val);
static void clear_row(const uint8_t row);
// 16 and 32 bit versions of Row and Column functions
// Multiple rows and columns will be used to display the value if
// the array of matrix LED's is too narrow to accomplish the goal
static void set_rows_16bits(const uint8_t y, uint32_t val);
static void set_rows_32bits(const uint8_t y, uint32_t val);
static void set_columns_16bits(const uint8_t x, uint32_t val);
static void set_columns_32bits(const uint8_t x, uint32_t val);
// Quickly clear the whole matrix
static void clear();
// Quickly fill the whole matrix
static void fill();
// Apply custom code to update the matrix
static void idle_tasks();
private:
static void error(const char * const func, const int32_t v1, const int32_t v2=-1);
static void noop();
static void set(const uint8_t line, const uint8_t bits);
static void send_row(const uint8_t row);
static void send_column(const uint8_t col);
static void mark16(const uint8_t y, const uint8_t v1, const uint8_t v2);
static void range16(const uint8_t y, const uint8_t ot, const uint8_t nt, const uint8_t oh, const uint8_t nh);
static void quantity16(const uint8_t y, const uint8_t ov, const uint8_t nv);
#ifdef MAX7219_INIT_TEST
#if MAX7219_INIT_TEST == 2
static void spiral(const bool on, const uint16_t del);
#else
static void sweep(const int8_t dir, const uint16_t ms, const bool on);
#endif
#endif
};
extern Max7219 max7219;

1705
Marlin/SanityCheck.h Normal file

File diff suppressed because it is too large Load Diff

716
Marlin/Sd2Card.cpp Normal file
View File

@ -0,0 +1,716 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* Arduino Sd2Card Library
* Copyright (C) 2009 by William Greiman
*
* This file is part of the Arduino Sd2Card Library
*/
#include "MarlinConfig.h"
#if ENABLED(SDSUPPORT)
#include "Sd2Card.h"
#if ENABLED(USE_WATCHDOG)
#include "watchdog.h"
#endif
#if DISABLED(SOFTWARE_SPI)
// functions for 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]
*/
static void spiInit(uint8_t spiRate) {
// See avr processor documentation
SPCR = _BV(SPE) | _BV(MSTR) | (spiRate >> 1);
SPSR = spiRate & 1 || spiRate == 6 ? 0 : _BV(SPI2X);
}
/** SPI receive a byte */
static uint8_t spiRec() {
SPDR = 0xFF;
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
return SPDR;
}
/** SPI read data - only one call so force inline */
static inline __attribute__((always_inline))
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 */
static void spiSend(uint8_t b) {
SPDR = b;
while (!TEST(SPSR, SPIF)) { /* Intentionally left empty */ }
}
/** SPI send block - only one call so force inline */
static inline __attribute__((always_inline))
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 */ }
}
//------------------------------------------------------------------------------
#else // SOFTWARE_SPI
//------------------------------------------------------------------------------
/** nop to tune soft SPI timing */
#define nop asm volatile ("nop\n\t")
/** Soft SPI receive byte */
static uint8_t spiRec() {
uint8_t data = 0;
// no interrupts during byte receive - about 8 us
cli();
// output pin high - like sending 0xFF
WRITE(SPI_MOSI_PIN, HIGH);
for (uint8_t i = 0; i < 8; i++) {
WRITE(SPI_SCK_PIN, HIGH);
// adjust so SCK is nice
nop;
nop;
data <<= 1;
if (READ(SPI_MISO_PIN)) data |= 1;
WRITE(SPI_SCK_PIN, LOW);
}
// enable interrupts
sei();
return data;
}
/** Soft SPI read data */
static void spiRead(uint8_t* buf, uint16_t nbyte) {
for (uint16_t i = 0; i < nbyte; i++)
buf[i] = spiRec();
}
/** Soft SPI send byte */
static void spiSend(uint8_t data) {
// no interrupts during byte send - about 8 us
cli();
for (uint8_t i = 0; i < 8; i++) {
WRITE(SPI_SCK_PIN, LOW);
WRITE(SPI_MOSI_PIN, data & 0x80);
data <<= 1;
WRITE(SPI_SCK_PIN, HIGH);
}
// hold SCK high for a few ns
nop;
nop;
nop;
nop;
WRITE(SPI_SCK_PIN, LOW);
// enable interrupts
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
// send command and return error code. Return zero for OK
uint8_t Sd2Card::cardCommand(uint8_t cmd, uint32_t arg) {
// select card
chipSelectLow();
// wait up to 300 ms if busy
waitNotBusy(300);
// send command
spiSend(cmd | 0x40);
// send argument
for (int8_t s = 24; s >= 0; s -= 8) spiSend(arg >> s);
// send CRC
uint8_t crc = 0xFF;
if (cmd == CMD0) crc = 0x95; // correct crc for CMD0 with arg 0
if (cmd == CMD8) crc = 0x87; // correct crc for CMD8 with arg 0x1AA
spiSend(crc);
// skip stuff byte for stop read
if (cmd == CMD12) spiRec();
// wait for response
for (uint8_t i = 0; ((status_ = spiRec()) & 0x80) && i != 0xFF; i++) { /* Intentionally left empty */ }
return status_;
}
/**
* Determine the size of an SD flash memory card.
*
* \return The number of 512 byte data blocks in the card
* or zero if an error occurs.
*/
uint32_t Sd2Card::cardSize() {
csd_t csd;
if (!readCSD(&csd)) return 0;
if (csd.v1.csd_ver == 0) {
uint8_t read_bl_len = csd.v1.read_bl_len;
uint16_t c_size = (csd.v1.c_size_high << 10)
| (csd.v1.c_size_mid << 2) | csd.v1.c_size_low;
uint8_t c_size_mult = (csd.v1.c_size_mult_high << 1)
| csd.v1.c_size_mult_low;
return (uint32_t)(c_size + 1) << (c_size_mult + read_bl_len - 7);
}
else if (csd.v2.csd_ver == 1) {
uint32_t c_size = ((uint32_t)csd.v2.c_size_high << 16)
| (csd.v2.c_size_mid << 8) | csd.v2.c_size_low;
return (c_size + 1) << 10;
}
else {
error(SD_CARD_ERROR_BAD_CSD);
return 0;
}
}
void Sd2Card::chipSelectHigh() {
digitalWrite(chipSelectPin_, HIGH);
}
void Sd2Card::chipSelectLow() {
#if DISABLED(SOFTWARE_SPI)
spiInit(spiRate_);
#endif // SOFTWARE_SPI
digitalWrite(chipSelectPin_, LOW);
}
/**
* Erase a range of blocks.
*
* \param[in] firstBlock The address of the first block in the range.
* \param[in] lastBlock The address of the last block in the range.
*
* \note This function requests the SD card to do a flash erase for a
* range of blocks. The data on the card after an erase operation is
* either 0 or 1, depends on the card vendor. The card must support
* single block erase.
*
* \return true for success, false for failure.
*/
bool Sd2Card::erase(uint32_t firstBlock, uint32_t lastBlock) {
csd_t csd;
if (!readCSD(&csd)) goto FAIL;
// check for single block erase
if (!csd.v1.erase_blk_en) {
// erase size mask
uint8_t m = (csd.v1.sector_size_high << 1) | csd.v1.sector_size_low;
if ((firstBlock & m) != 0 || ((lastBlock + 1) & m) != 0) {
// error card can't erase specified area
error(SD_CARD_ERROR_ERASE_SINGLE_BLOCK);
goto FAIL;
}
}
if (type_ != SD_CARD_TYPE_SDHC) {
firstBlock <<= 9;
lastBlock <<= 9;
}
if (cardCommand(CMD32, firstBlock)
|| cardCommand(CMD33, lastBlock)
|| cardCommand(CMD38, 0)) {
error(SD_CARD_ERROR_ERASE);
goto FAIL;
}
if (!waitNotBusy(SD_ERASE_TIMEOUT)) {
error(SD_CARD_ERROR_ERASE_TIMEOUT);
goto FAIL;
}
chipSelectHigh();
return true;
FAIL:
chipSelectHigh();
return false;
}
/**
* Determine if card supports single block erase.
*
* \return true if single block erase is supported.
* false if single block erase is not supported.
*/
bool Sd2Card::eraseSingleBlockEnable() {
csd_t csd;
return readCSD(&csd) ? csd.v1.erase_blk_en : false;
}
/**
* Initialize an SD flash memory card.
*
* \param[in] sckRateID SPI clock rate selector. See setSckRate().
* \param[in] chipSelectPin SD chip select pin number.
*
* \return true for success, false for failure.
* The reason for failure can be determined by calling errorCode() and errorData().
*/
bool Sd2Card::init(uint8_t sckRateID, pin_t chipSelectPin) {
errorCode_ = type_ = 0;
chipSelectPin_ = chipSelectPin;
// 16-bit init start time allows over a minute
uint16_t t0 = (uint16_t)millis();
uint32_t arg;
// If init takes more than 4s it could trigger
// watchdog leading to a reboot loop.
#if ENABLED(USE_WATCHDOG)
watchdog_reset();
#endif
// set pin modes
pinMode(chipSelectPin_, OUTPUT);
chipSelectHigh();
SET_INPUT(SPI_MISO_PIN);
SET_OUTPUT(SPI_MOSI_PIN);
SET_OUTPUT(SPI_SCK_PIN);
#if DISABLED(SOFTWARE_SPI)
// SS must be in output mode even it is not chip select
SET_OUTPUT(SS_PIN);
// set SS high - may be chip select for another SPI device
#if SET_SPI_SS_HIGH
WRITE(SS_PIN, HIGH);
#endif // SET_SPI_SS_HIGH
// set SCK rate for initialization commands
spiRate_ = SPI_SD_INIT_RATE;
spiInit(spiRate_);
#endif // SOFTWARE_SPI
// must supply min of 74 clock cycles with CS high.
for (uint8_t i = 0; i < 10; i++) spiSend(0xFF);
// command to go idle in SPI mode
while ((status_ = cardCommand(CMD0, 0)) != R1_IDLE_STATE) {
if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) {
error(SD_CARD_ERROR_CMD0);
goto FAIL;
}
}
// check SD version
if ((cardCommand(CMD8, 0x1AA) & R1_ILLEGAL_COMMAND)) {
type(SD_CARD_TYPE_SD1);
}
else {
// only need last byte of r7 response
for (uint8_t i = 0; i < 4; i++) status_ = spiRec();
if (status_ != 0xAA) {
error(SD_CARD_ERROR_CMD8);
goto FAIL;
}
type(SD_CARD_TYPE_SD2);
}
// initialize card and send host supports SDHC if SD2
arg = type() == SD_CARD_TYPE_SD2 ? 0x40000000 : 0;
while ((status_ = cardAcmd(ACMD41, arg)) != R1_READY_STATE) {
// check for timeout
if (((uint16_t)millis() - t0) > SD_INIT_TIMEOUT) {
error(SD_CARD_ERROR_ACMD41);
goto FAIL;
}
}
// if SD2 read OCR register to check for SDHC card
if (type() == SD_CARD_TYPE_SD2) {
if (cardCommand(CMD58, 0)) {
error(SD_CARD_ERROR_CMD58);
goto FAIL;
}
if ((spiRec() & 0xC0) == 0xC0) type(SD_CARD_TYPE_SDHC);
// discard rest of ocr - contains allowed voltage range
for (uint8_t i = 0; i < 3; i++) spiRec();
}
chipSelectHigh();
#if DISABLED(SOFTWARE_SPI)
return setSckRate(sckRateID);
#else // SOFTWARE_SPI
UNUSED(sckRateID);
return true;
#endif // SOFTWARE_SPI
FAIL:
chipSelectHigh();
return false;
}
/**
* Read a 512 byte block from an SD card.
*
* \param[in] blockNumber Logical block to be read.
* \param[out] dst Pointer to the location that will receive the data.
* \return true for success, false for failure.
*/
bool Sd2Card::readBlock(uint32_t blockNumber, uint8_t* dst) {
// use address if not SDHC card
if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;
#if ENABLED(SD_CHECK_AND_RETRY)
uint8_t retryCnt = 3;
for (;;) {
if (cardCommand(CMD17, blockNumber))
error(SD_CARD_ERROR_CMD17);
else if (readData(dst, 512))
return true;
chipSelectHigh();
if (!--retryCnt) break;
cardCommand(CMD12, 0); // Try sending a stop command, ignore the result.
errorCode_ = 0;
}
return false;
#else
if (cardCommand(CMD17, blockNumber)) {
error(SD_CARD_ERROR_CMD17);
chipSelectHigh();
return false;
}
else
return readData(dst, 512);
#endif
}
/**
* Read one data block in a multiple block read sequence
*
* \param[in] dst Pointer to the location for the data to be read.
*
* \return true for success, false for failure.
*/
bool Sd2Card::readData(uint8_t* dst) {
chipSelectLow();
return readData(dst, 512);
}
#if ENABLED(SD_CHECK_AND_RETRY)
static const uint16_t crctab[] PROGMEM = {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
};
static uint16_t CRC_CCITT(const uint8_t* data, size_t n) {
uint16_t crc = 0;
for (size_t i = 0; i < n; i++) {
crc = pgm_read_word(&crctab[(crc >> 8 ^ data[i]) & 0xFF]) ^ (crc << 8);
}
return crc;
}
#endif // SD_CHECK_AND_RETRY
bool Sd2Card::readData(uint8_t* dst, uint16_t count) {
// wait for start block token
uint16_t t0 = millis();
while ((status_ = spiRec()) == 0XFF) {
if (((uint16_t)millis() - t0) > SD_READ_TIMEOUT) {
error(SD_CARD_ERROR_READ_TIMEOUT);
goto FAIL;
}
}
if (status_ != DATA_START_BLOCK) {
error(SD_CARD_ERROR_READ);
goto FAIL;
}
// transfer data
spiRead(dst, count);
#if ENABLED(SD_CHECK_AND_RETRY)
{
uint16_t calcCrc = CRC_CCITT(dst, count);
uint16_t recvCrc = spiRec() << 8;
recvCrc |= spiRec();
if (calcCrc != recvCrc) {
error(SD_CARD_ERROR_CRC);
goto FAIL;
}
}
#else
// discard CRC
spiRec();
spiRec();
#endif
chipSelectHigh();
// Send an additional dummy byte, required by Toshiba Flash Air SD Card
spiSend(0XFF);
return true;
FAIL:
chipSelectHigh();
// Send an additional dummy byte, required by Toshiba Flash Air SD Card
spiSend(0XFF);
return false;
}
/** read CID or CSR register */
bool Sd2Card::readRegister(uint8_t cmd, void* buf) {
uint8_t* dst = reinterpret_cast<uint8_t*>(buf);
if (cardCommand(cmd, 0)) {
error(SD_CARD_ERROR_READ_REG);
chipSelectHigh();
return false;
}
return readData(dst, 16);
}
/**
* Start a read multiple blocks sequence.
*
* \param[in] blockNumber Address of first block in sequence.
*
* \note This function is used with readData() and readStop() for optimized
* multiple block reads. SPI chipSelect must be low for the entire sequence.
*
* \return true for success, false for failure.
*/
bool Sd2Card::readStart(uint32_t blockNumber) {
if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;
if (cardCommand(CMD18, blockNumber)) {
error(SD_CARD_ERROR_CMD18);
chipSelectHigh();
return false;
}
chipSelectHigh();
return true;
}
/**
* End a read multiple blocks sequence.
*
* \return true for success, false for failure.
*/
bool Sd2Card::readStop() {
chipSelectLow();
if (cardCommand(CMD12, 0)) {
error(SD_CARD_ERROR_CMD12);
chipSelectHigh();
return false;
}
chipSelectHigh();
return true;
}
/**
* Set the SPI clock rate.
*
* \param[in] sckRateID A value in the range [0, 6].
*
* The SPI clock will be set to F_CPU/pow(2, 1 + sckRateID). The maximum
* SPI rate is F_CPU/2 for \a sckRateID = 0 and the minimum rate is F_CPU/128
* for \a scsRateID = 6.
*
* \return The value one, true, is returned for success and the value zero,
* false, is returned for an invalid value of \a sckRateID.
*/
bool Sd2Card::setSckRate(uint8_t sckRateID) {
if (sckRateID > 6) {
error(SD_CARD_ERROR_SCK_RATE);
return false;
}
spiRate_ = sckRateID;
return true;
}
// wait for card to go not busy
bool Sd2Card::waitNotBusy(uint16_t timeoutMillis) {
uint16_t t0 = millis();
while (spiRec() != 0XFF)
if (((uint16_t)millis() - t0) >= timeoutMillis) return false;
return true;
}
/**
* Writes a 512 byte block to an SD card.
*
* \param[in] blockNumber Logical block to be written.
* \param[in] src Pointer to the location of the data to be written.
* \return true for success, false for failure.
*/
bool Sd2Card::writeBlock(uint32_t blockNumber, const uint8_t* src) {
// use address if not SDHC card
if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;
if (cardCommand(CMD24, blockNumber)) {
error(SD_CARD_ERROR_CMD24);
goto FAIL;
}
if (!writeData(DATA_START_BLOCK, src)) goto FAIL;
// wait for flash programming to complete
if (!waitNotBusy(SD_WRITE_TIMEOUT)) {
error(SD_CARD_ERROR_WRITE_TIMEOUT);
goto FAIL;
}
// response is r2 so get and check two bytes for nonzero
if (cardCommand(CMD13, 0) || spiRec()) {
error(SD_CARD_ERROR_WRITE_PROGRAMMING);
goto FAIL;
}
chipSelectHigh();
return true;
FAIL:
chipSelectHigh();
return false;
}
/**
* Write one data block in a multiple block write sequence
* \param[in] src Pointer to the location of the data to be written.
* \return true for success, false for failure.
*/
bool Sd2Card::writeData(const uint8_t* src) {
chipSelectLow();
// wait for previous write to finish
if (!waitNotBusy(SD_WRITE_TIMEOUT) || !writeData(WRITE_MULTIPLE_TOKEN, src)) {
error(SD_CARD_ERROR_WRITE_MULTIPLE);
chipSelectHigh();
return false;
}
chipSelectHigh();
return true;
}
// send one block of data for write block or write multiple blocks
bool Sd2Card::writeData(uint8_t token, const uint8_t* src) {
spiSendBlock(token, src);
spiSend(0xFF); // dummy crc
spiSend(0xFF); // dummy crc
status_ = spiRec();
if ((status_ & DATA_RES_MASK) != DATA_RES_ACCEPTED) {
error(SD_CARD_ERROR_WRITE);
chipSelectHigh();
return false;
}
return true;
}
/**
* Start a write multiple blocks sequence.
*
* \param[in] blockNumber Address of first block in sequence.
* \param[in] eraseCount The number of blocks to be pre-erased.
*
* \note This function is used with writeData() and writeStop()
* for optimized multiple block writes.
*
* \return true for success, false for failure.
*/
bool Sd2Card::writeStart(uint32_t blockNumber, uint32_t eraseCount) {
// send pre-erase count
if (cardAcmd(ACMD23, eraseCount)) {
error(SD_CARD_ERROR_ACMD23);
goto FAIL;
}
// use address if not SDHC card
if (type() != SD_CARD_TYPE_SDHC) blockNumber <<= 9;
if (cardCommand(CMD25, blockNumber)) {
error(SD_CARD_ERROR_CMD25);
goto FAIL;
}
chipSelectHigh();
return true;
FAIL:
chipSelectHigh();
return false;
}
/**
* End a write multiple blocks sequence.
*
* \return true for success, false for failure.
*/
bool Sd2Card::writeStop() {
chipSelectLow();
if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto FAIL;
spiSend(STOP_TRAN_TOKEN);
if (!waitNotBusy(SD_WRITE_TIMEOUT)) goto FAIL;
chipSelectHigh();
return true;
FAIL:
error(SD_CARD_ERROR_STOP_TRAN);
chipSelectHigh();
return false;
}
#endif // SDSUPPORT

204
Marlin/Sd2Card.h Normal file
View File

@ -0,0 +1,204 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* \file
* \brief Sd2Card class for V2 SD/SDHC cards
*/
/**
* Arduino Sd2Card Library
* Copyright (C) 2009 by William Greiman
*
* This file is part of the Arduino Sd2Card Library
*/
#ifndef _SD2CARD_H_
#define _SD2CARD_H_
#include "SdFatConfig.h"
#include "SdInfo.h"
// SPI speed is F_CPU/2^(1 + index), 0 <= index <= 6
uint8_t const SPI_FULL_SPEED = 0, // Set SCK to max rate of F_CPU/2. See Sd2Card::setSckRate().
SPI_HALF_SPEED = 1, // Set SCK rate to F_CPU/4. See Sd2Card::setSckRate().
SPI_QUARTER_SPEED = 2, // Set SCK rate to F_CPU/8. See Sd2Card::setSckRate().
SPI_EIGHTH_SPEED = 3, // Set SCK rate to F_CPU/16. See Sd2Card::setSckRate().
SPI_SIXTEENTH_SPEED = 4; // Set SCK rate to F_CPU/32. See Sd2Card::setSckRate().
uint16_t const SD_INIT_TIMEOUT = 2000, // init timeout ms
SD_ERASE_TIMEOUT = 10000, // erase timeout ms
SD_READ_TIMEOUT = 300, // read timeout ms
SD_WRITE_TIMEOUT = 600; // write time out ms
// SD card errors
uint8_t const SD_CARD_ERROR_CMD0 = 0X1, // timeout error for command CMD0 (initialize card in SPI mode)
SD_CARD_ERROR_CMD8 = 0X2, // CMD8 was not accepted - not a valid SD card
SD_CARD_ERROR_CMD12 = 0X3, // card returned an error response for CMD12 (write stop)
SD_CARD_ERROR_CMD17 = 0X4, // card returned an error response for CMD17 (read block)
SD_CARD_ERROR_CMD18 = 0X5, // card returned an error response for CMD18 (read multiple block)
SD_CARD_ERROR_CMD24 = 0X6, // card returned an error response for CMD24 (write block)
SD_CARD_ERROR_CMD25 = 0X7, // WRITE_MULTIPLE_BLOCKS command failed
SD_CARD_ERROR_CMD58 = 0X8, // card returned an error response for CMD58 (read OCR)
SD_CARD_ERROR_ACMD23 = 0X9, // SET_WR_BLK_ERASE_COUNT failed
SD_CARD_ERROR_ACMD41 = 0XA, // ACMD41 initialization process timeout
SD_CARD_ERROR_BAD_CSD = 0XB, // card returned a bad CSR version field
SD_CARD_ERROR_ERASE = 0XC, // erase block group command failed
SD_CARD_ERROR_ERASE_SINGLE_BLOCK = 0XD, // card not capable of single block erase
SD_CARD_ERROR_ERASE_TIMEOUT = 0XE, // Erase sequence timed out
SD_CARD_ERROR_READ = 0XF, // card returned an error token instead of read data
SD_CARD_ERROR_READ_REG = 0x10, // read CID or CSD failed
SD_CARD_ERROR_READ_TIMEOUT = 0x11, // timeout while waiting for start of read data
SD_CARD_ERROR_STOP_TRAN = 0x12, // card did not accept STOP_TRAN_TOKEN
SD_CARD_ERROR_WRITE = 0x13, // card returned an error token as a response to a write operation
SD_CARD_ERROR_WRITE_BLOCK_ZERO = 0x14, // REMOVE - not used ... attempt to write protected block zero
SD_CARD_ERROR_WRITE_MULTIPLE = 0x15, // card did not go ready for a multiple block write
SD_CARD_ERROR_WRITE_PROGRAMMING = 0x16, // card returned an error to a CMD13 status check after a write
SD_CARD_ERROR_WRITE_TIMEOUT = 0x17, // timeout occurred during write programming
SD_CARD_ERROR_SCK_RATE = 0x18, // incorrect rate selected
SD_CARD_ERROR_INIT_NOT_CALLED = 0x19, // init() not called
SD_CARD_ERROR_CRC = 0x20; // crc check error
// card types
uint8_t const SD_CARD_TYPE_SD1 = 1, // Standard capacity V1 SD card
SD_CARD_TYPE_SD2 = 2, // Standard capacity V2 SD card
SD_CARD_TYPE_SDHC = 3; // High Capacity SD card
/**
* define SOFTWARE_SPI to use bit-bang SPI
*/
#if MEGA_SOFT_SPI
#define SOFTWARE_SPI
#elif USE_SOFTWARE_SPI
#define SOFTWARE_SPI
#endif
// SPI pin definitions - do not edit here - change in SdFatConfig.h
#if DISABLED(SOFTWARE_SPI)
// hardware pin defs
#define SD_CHIP_SELECT_PIN SS_PIN // The default chip select pin for the SD card is SS.
// The following three pins must not be redefined for hardware SPI.
#define SPI_MOSI_PIN MOSI_PIN // SPI Master Out Slave In pin
#define SPI_MISO_PIN MISO_PIN // SPI Master In Slave Out pin
#define SPI_SCK_PIN SCK_PIN // SPI Clock pin
#else // SOFTWARE_SPI
#define SD_CHIP_SELECT_PIN SOFT_SPI_CS_PIN // SPI chip select pin
#define SPI_MOSI_PIN SOFT_SPI_MOSI_PIN // SPI Master Out Slave In pin
#define SPI_MISO_PIN SOFT_SPI_MISO_PIN // SPI Master In Slave Out pin
#define SPI_SCK_PIN SOFT_SPI_SCK_PIN // SPI Clock pin
#endif // SOFTWARE_SPI
/**
* \class Sd2Card
* \brief Raw access to SD and SDHC flash memory cards.
*/
class Sd2Card {
public:
Sd2Card() : errorCode_(SD_CARD_ERROR_INIT_NOT_CALLED), type_(0) {}
uint32_t cardSize();
bool erase(uint32_t firstBlock, uint32_t lastBlock);
bool eraseSingleBlockEnable();
/**
* Set SD error code.
* \param[in] code value for error code.
*/
void error(uint8_t code) {errorCode_ = code;}
/**
* \return error code for last error. See Sd2Card.h for a list of error codes.
*/
int errorCode() const {return errorCode_;}
/** \return error data for last error. */
int errorData() const {return status_;}
/**
* Initialize an SD flash memory card with default clock rate and chip
* select pin. See sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin).
*
* \return true for success or false for failure.
*/
bool init(uint8_t sckRateID = SPI_FULL_SPEED,
pin_t chipSelectPin = SD_CHIP_SELECT_PIN);
bool readBlock(uint32_t block, uint8_t* dst);
/**
* Read a card's CID register. The CID contains card identification
* information such as Manufacturer ID, Product name, Product serial
* number and Manufacturing date.
*
* \param[out] cid pointer to area for returned data.
*
* \return true for success or false for failure.
*/
bool readCID(cid_t* cid) { return readRegister(CMD10, cid); }
/**
* Read a card's CSD register. The CSD contains Card-Specific Data that
* provides information regarding access to the card's contents.
*
* \param[out] csd pointer to area for returned data.
*
* \return true for success or false for failure.
*/
bool readCSD(csd_t* csd) { return readRegister(CMD9, csd); }
bool readData(uint8_t* dst);
bool readStart(uint32_t blockNumber);
bool readStop();
bool setSckRate(uint8_t sckRateID);
/**
* Return the card type: SD V1, SD V2 or SDHC
* \return 0 - SD V1, 1 - SD V2, or 3 - SDHC.
*/
int type() const {return type_;}
bool writeBlock(uint32_t blockNumber, const uint8_t* src);
bool writeData(const uint8_t* src);
bool writeStart(uint32_t blockNumber, uint32_t eraseCount);
bool writeStop();
private:
uint8_t chipSelectPin_,
errorCode_,
spiRate_,
status_,
type_;
// private functions
uint8_t cardAcmd(uint8_t cmd, uint32_t arg) {
cardCommand(CMD55, 0);
return cardCommand(cmd, arg);
}
uint8_t cardCommand(uint8_t cmd, uint32_t arg);
bool readData(uint8_t* dst, uint16_t count);
bool readRegister(uint8_t cmd, void* buf);
void chipSelectHigh();
void chipSelectLow();
void type(uint8_t value) { type_ = value; }
bool waitNotBusy(uint16_t timeoutMillis);
bool writeData(uint8_t token, const uint8_t* src);
};
#endif // _SD2CARD_H_

1728
Marlin/SdBaseFile.cpp Normal file

File diff suppressed because it is too large Load Diff

390
Marlin/SdBaseFile.h Normal file
View File

@ -0,0 +1,390 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* \file
* \brief SdBaseFile class
*/
/**
* Arduino SdFat Library
* Copyright (C) 2009 by William Greiman
*
* This file is part of the Arduino Sd2Card Library
*/
#ifndef _SDBASEFILE_H_
#define _SDBASEFILE_H_
#include "SdFatConfig.h"
#include "SdVolume.h"
#include <stdint.h>
/**
* \struct filepos_t
* \brief internal type for istream
* do not use in user apps
*/
struct filepos_t {
uint32_t position; // stream byte position
uint32_t cluster; // cluster of position
filepos_t() : position(0), cluster(0) {}
};
// use the gnu style oflag in open()
uint8_t const O_READ = 0x01, // open() oflag for reading
O_RDONLY = O_READ, // open() oflag - same as O_IN
O_WRITE = 0x02, // open() oflag for write
O_WRONLY = O_WRITE, // open() oflag - same as O_WRITE
O_RDWR = (O_READ | O_WRITE), // open() oflag for reading and writing
O_ACCMODE = (O_READ | O_WRITE), // open() oflag mask for access modes
O_APPEND = 0x04, // The file offset shall be set to the end of the file prior to each write.
O_SYNC = 0x08, // Synchronous writes - call sync() after each write
O_TRUNC = 0x10, // Truncate the file to zero length
O_AT_END = 0x20, // Set the initial position at the end of the file
O_CREAT = 0x40, // Create the file if nonexistent
O_EXCL = 0x80; // If O_CREAT and O_EXCL are set, open() shall fail if the file exists
// SdBaseFile class static and const definitions
// flags for ls()
uint8_t const LS_DATE = 1, // ls() flag to print modify date
LS_SIZE = 2, // ls() flag to print file size
LS_R = 4; // ls() flag for recursive list of subdirectories
// flags for timestamp
uint8_t const T_ACCESS = 1, // Set the file's last access date
T_CREATE = 2, // Set the file's creation date and time
T_WRITE = 4; // Set the file's write date and time
// values for type_
uint8_t const FAT_FILE_TYPE_CLOSED = 0, // This file has not been opened.
FAT_FILE_TYPE_NORMAL = 1, // A normal file
FAT_FILE_TYPE_ROOT_FIXED = 2, // A FAT12 or FAT16 root directory
FAT_FILE_TYPE_ROOT32 = 3, // A FAT32 root directory
FAT_FILE_TYPE_SUBDIR = 4, // A subdirectory file
FAT_FILE_TYPE_MIN_DIR = FAT_FILE_TYPE_ROOT_FIXED; // Test value for directory type
/**
* date field for FAT directory entry
* \param[in] year [1980,2107]
* \param[in] month [1,12]
* \param[in] day [1,31]
*
* \return Packed date for dir_t entry.
*/
static inline uint16_t FAT_DATE(uint16_t year, uint8_t month, uint8_t day) { return (year - 1980) << 9 | month << 5 | day; }
/**
* year part of FAT directory date field
* \param[in] fatDate Date in packed dir format.
*
* \return Extracted year [1980,2107]
*/
static inline uint16_t FAT_YEAR(uint16_t fatDate) { return 1980 + (fatDate >> 9); }
/**
* month part of FAT directory date field
* \param[in] fatDate Date in packed dir format.
*
* \return Extracted month [1,12]
*/
static inline uint8_t FAT_MONTH(uint16_t fatDate) { return (fatDate >> 5) & 0XF; }
/**
* day part of FAT directory date field
* \param[in] fatDate Date in packed dir format.
*
* \return Extracted day [1,31]
*/
static inline uint8_t FAT_DAY(uint16_t fatDate) { return fatDate & 0x1F; }
/**
* time field for FAT directory entry
* \param[in] hour [0,23]
* \param[in] minute [0,59]
* \param[in] second [0,59]
*
* \return Packed time for dir_t entry.
*/
static inline uint16_t FAT_TIME(uint8_t hour, uint8_t minute, uint8_t second) { return hour << 11 | minute << 5 | second >> 1; }
/**
* hour part of FAT directory time field
* \param[in] fatTime Time in packed dir format.
*
* \return Extracted hour [0,23]
*/
static inline uint8_t FAT_HOUR(uint16_t fatTime) { return fatTime >> 11; }
/**
* minute part of FAT directory time field
* \param[in] fatTime Time in packed dir format.
*
* \return Extracted minute [0,59]
*/
static inline uint8_t FAT_MINUTE(uint16_t fatTime) { return (fatTime >> 5) & 0x3F; }
/**
* second part of FAT directory time field
* Note second/2 is stored in packed time.
*
* \param[in] fatTime Time in packed dir format.
*
* \return Extracted second [0,58]
*/
static inline uint8_t FAT_SECOND(uint16_t fatTime) { return 2 * (fatTime & 0x1F); }
// Default date for file timestamps is 1 Jan 2000
uint16_t const FAT_DEFAULT_DATE = ((2000 - 1980) << 9) | (1 << 5) | 1;
// Default time for file timestamp is 1 am
uint16_t const FAT_DEFAULT_TIME = (1 << 11);
/**
* \class SdBaseFile
* \brief Base class for SdFile with Print and C++ streams.
*/
class SdBaseFile {
public:
SdBaseFile() : writeError(false), type_(FAT_FILE_TYPE_CLOSED) {}
SdBaseFile(const char* path, uint8_t oflag);
~SdBaseFile() { if (isOpen()) close(); }
/**
* writeError is set to true if an error occurs during a write().
* Set writeError to false before calling print() and/or write() and check
* for true after calls to print() and/or write().
*/
bool writeError;
// helpers for stream classes
/**
* get position for streams
* \param[out] pos struct to receive position
*/
void getpos(filepos_t* pos);
/**
* set position for streams
* \param[out] pos struct with value for new position
*/
void setpos(filepos_t* pos);
bool close();
bool contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock);
bool createContiguous(SdBaseFile* dirFile,
const char* path, uint32_t size);
/**
* \return The current cluster number for a file or directory.
*/
uint32_t curCluster() const { return curCluster_; }
/**
* \return The current position for a file or directory.
*/
uint32_t curPosition() const { return curPosition_; }
/**
* \return Current working directory
*/
static SdBaseFile* cwd() { return cwd_; }
/**
* Set the date/time callback function
*
* \param[in] dateTime The user's call back function. The callback
* function is of the form:
*
* \code
* void dateTime(uint16_t* date, uint16_t* time) {
* uint16_t year;
* uint8_t month, day, hour, minute, second;
*
* // User gets date and time from GPS or real-time clock here
*
* // return date using FAT_DATE macro to format fields
* *date = FAT_DATE(year, month, day);
*
* // return time using FAT_TIME macro to format fields
* *time = FAT_TIME(hour, minute, second);
* }
* \endcode
*
* Sets the function that is called when a file is created or when
* a file's directory entry is modified by sync(). All timestamps,
* access, creation, and modify, are set when a file is created.
* sync() maintains the last access date and last modify date/time.
*
* See the timestamp() function.
*/
static void dateTimeCallback(
void (*dateTime)(uint16_t* date, uint16_t* time)) {
dateTime_ = dateTime;
}
/**
* Cancel the date/time callback function.
*/
static void dateTimeCallbackCancel() { dateTime_ = 0; }
bool dirEntry(dir_t* dir);
static void dirName(const dir_t& dir, char* name);
bool exists(const char* name);
int16_t fgets(char* str, int16_t num, char* delim = 0);
/**
* \return The total number of bytes in a file or directory.
*/
uint32_t fileSize() const { return fileSize_; }
/**
* \return The first cluster number for a file or directory.
*/
uint32_t firstCluster() const { return firstCluster_; }
/**
* \return True if this is a directory else false.
*/
bool isDir() const { return type_ >= FAT_FILE_TYPE_MIN_DIR; }
/**
* \return True if this is a normal file else false.
*/
bool isFile() const { return type_ == FAT_FILE_TYPE_NORMAL; }
/**
* \return True if this is an open file/directory else false.
*/
bool isOpen() const { return type_ != FAT_FILE_TYPE_CLOSED; }
/**
* \return True if this is a subdirectory else false.
*/
bool isSubDir() const { return type_ == FAT_FILE_TYPE_SUBDIR; }
/**
* \return True if this is the root directory.
*/
bool isRoot() const { return type_ == FAT_FILE_TYPE_ROOT_FIXED || type_ == FAT_FILE_TYPE_ROOT32; }
bool getFilename(char * const name);
void ls(uint8_t flags = 0, uint8_t indent = 0);
bool mkdir(SdBaseFile* dir, const char* path, bool pFlag = true);
bool open(SdBaseFile* dirFile, uint16_t index, uint8_t oflag);
bool open(SdBaseFile* dirFile, const char* path, uint8_t oflag);
bool open(const char* path, uint8_t oflag = O_READ);
bool openNext(SdBaseFile* dirFile, uint8_t oflag);
bool openRoot(SdVolume* vol);
int peek();
static void printFatDate(uint16_t fatDate);
static void printFatTime(uint16_t fatTime);
bool printName();
int16_t read();
int16_t read(void* buf, uint16_t nbyte);
int8_t readDir(dir_t* dir, char* longFilename);
static bool remove(SdBaseFile* dirFile, const char* path);
bool remove();
/**
* Set the file's current position to zero.
*/
void rewind() { seekSet(0); }
bool rename(SdBaseFile* dirFile, const char* newPath);
bool rmdir();
bool rmRfStar();
/**
* Set the files position to current position + \a pos. See seekSet().
* \param[in] offset The new position in bytes from the current position.
* \return true for success or false for failure.
*/
bool seekCur(const int32_t offset) { return seekSet(curPosition_ + offset); }
/**
* Set the files position to end-of-file + \a offset. See seekSet().
* \param[in] offset The new position in bytes from end-of-file.
* \return true for success or false for failure.
*/
bool seekEnd(const int32_t offset = 0) { return seekSet(fileSize_ + offset); }
bool seekSet(const uint32_t pos);
bool sync();
bool timestamp(SdBaseFile* file);
bool timestamp(uint8_t flag, uint16_t year, uint8_t month, uint8_t day,
uint8_t hour, uint8_t minute, uint8_t second);
/**
* Type of file. Use isFile() or isDir() instead of type() if possible.
*
* \return The file or directory type.
*/
uint8_t type() const { return type_; }
bool truncate(uint32_t size);
/**
* \return SdVolume that contains this file.
*/
SdVolume* volume() const { return vol_; }
int16_t write(const void* buf, uint16_t nbyte);
private:
friend class SdFat; // allow SdFat to set cwd_
static SdBaseFile* cwd_; // global pointer to cwd dir
// data time callback function
static void (*dateTime_)(uint16_t* date, uint16_t* time);
// bits defined in flags_
static uint8_t const F_OFLAG = (O_ACCMODE | O_APPEND | O_SYNC), // should be 0x0F
F_FILE_DIR_DIRTY = 0x80; // sync of directory entry required
// private data
uint8_t flags_; // See above for definition of flags_ bits
uint8_t fstate_; // error and eof indicator
uint8_t type_; // type of file see above for values
uint32_t curCluster_; // cluster for current file position
uint32_t curPosition_; // current file position in bytes from beginning
uint32_t dirBlock_; // block for this files directory entry
uint8_t dirIndex_; // index of directory entry in dirBlock
uint32_t fileSize_; // file size in bytes
uint32_t firstCluster_; // first cluster of file
SdVolume* vol_; // volume where file is located
/**
* EXPERIMENTAL - Don't use!
*/
//bool openParent(SdBaseFile* dir);
// private functions
bool addCluster();
bool addDirCluster();
dir_t* cacheDirEntry(uint8_t action);
int8_t lsPrintNext(uint8_t flags, uint8_t indent);
static bool make83Name(const char* str, uint8_t* name, const char** ptr);
bool mkdir(SdBaseFile* parent, const uint8_t dname[11]);
bool open(SdBaseFile* dirFile, const uint8_t dname[11], uint8_t oflag);
bool openCachedEntry(uint8_t cacheIndex, uint8_t oflags);
dir_t* readDirCache();
};
#endif // _SDBASEFILE_H_

116
Marlin/SdFatConfig.h Normal file
View File

@ -0,0 +1,116 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* SdFatConfig.h
* Arduino SdFat Library
* Copyright (C) 2009 by William Greiman
*
* This file is part of the Arduino Sd2Card Library
*/
#ifndef _SDFATCONFIG_H_
#define _SDFATCONFIG_H_
#include "MarlinConfig.h"
/**
* To use multiple SD cards set USE_MULTIPLE_CARDS nonzero.
*
* Using multiple cards costs 400 - 500 bytes of flash.
*
* Each card requires about 550 bytes of SRAM so use of a Mega is recommended.
*/
#define USE_MULTIPLE_CARDS 0
/**
* Call flush for endl if ENDL_CALLS_FLUSH is nonzero
*
* The standard for iostreams is to call flush. This is very costly for
* SdFat. Each call to flush causes 2048 bytes of I/O to the SD.
*
* SdFat has a single 512 byte buffer for SD I/O so it must write the current
* data block to the SD, read the directory block from the SD, update the
* directory entry, write the directory block to the SD and read the data
* block back into the buffer.
*
* The SD flash memory controller is not designed for this many rewrites
* so performance may be reduced by more than a factor of 100.
*
* If ENDL_CALLS_FLUSH is zero, you must call flush and/or close to force
* all data to be written to the SD.
*/
#define ENDL_CALLS_FLUSH 0
/**
* Allow FAT12 volumes if FAT12_SUPPORT is nonzero.
* FAT12 has not been well tested.
*/
#define FAT12_SUPPORT 0
/**
* SPI init rate for SD initialization commands. Must be 5 (F_CPU/64)
* or 6 (F_CPU/128).
*/
#define SPI_SD_INIT_RATE 5
/**
* Set the SS pin high for hardware SPI. If SS is chip select for another SPI
* device this will disable that device during the SD init phase.
*/
#define SET_SPI_SS_HIGH 1
/**
* Define MEGA_SOFT_SPI nonzero to use software SPI on Mega Arduinos.
* Pins used are SS 10, MOSI 11, MISO 12, and SCK 13.
*
* MEGA_SOFT_SPI allows an unmodified Adafruit GPS Shield to be used
* on Mega Arduinos. Software SPI works well with GPS Shield V1.1
* but many SD cards will fail with GPS Shield V1.0.
*/
#define MEGA_SOFT_SPI 0
// Set USE_SOFTWARE_SPI nonzero to ALWAYS use Software SPI.
#define USE_SOFTWARE_SPI 0
// Define software SPI pins so Mega can use unmodified 168/328 shields
#define SOFT_SPI_CS_PIN 10 // Software SPI chip select pin for the SD
#define SOFT_SPI_MOSI_PIN 11 // Software SPI Master Out Slave In pin
#define SOFT_SPI_MISO_PIN 12 // Software SPI Master In Slave Out pin
#define SOFT_SPI_SCK_PIN 13 // Software SPI Clock pin
/**
* The __cxa_pure_virtual function is an error handler that is invoked when
* a pure virtual function is called.
*/
#define USE_CXA_PURE_VIRTUAL 1
/**
* Defines for 8.3 and long (vfat) filenames
*/
#define FILENAME_LENGTH 13 // Number of UTF-16 characters per entry
// Total bytes needed to store a single long filename
#define LONG_FILENAME_LENGTH (FILENAME_LENGTH * MAX_VFAT_ENTRIES + 1)
#endif // _SDFATCONFIG_H_

615
Marlin/SdFatStructs.h Normal file
View File

@ -0,0 +1,615 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* \file
* \brief FAT file structures
*/
/**
* Arduino SdFat Library
* Copyright (C) 2009 by William Greiman
*
* This file is part of the Arduino Sd2Card Library
*/
#ifndef SDFATSTRUCTS_H
#define SDFATSTRUCTS_H
#define PACKED __attribute__((__packed__))
/**
* mostly from Microsoft document fatgen103.doc
* http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx
*/
uint8_t const BOOTSIG0 = 0x55, // Value for byte 510 of boot block or MBR
BOOTSIG1 = 0xAA, // Value for byte 511 of boot block or MBR
EXTENDED_BOOT_SIG = 0x29; // Value for bootSignature field int FAT/FAT32 boot sector
/**
* \struct partitionTable
* \brief MBR partition table entry
*
* A partition table entry for a MBR formatted storage device.
* The MBR partition table has four entries.
*/
struct partitionTable {
/**
* Boot Indicator . Indicates whether the volume is the active
* partition. Legal values include: 0x00. Do not use for booting.
* 0x80 Active partition.
*/
uint8_t boot;
/**
* Head part of Cylinder-head-sector address of the first block in
* the partition. Legal values are 0-255. Only used in old PC BIOS.
*/
uint8_t beginHead;
/**
* Sector part of Cylinder-head-sector address of the first block in
* the partition. Legal values are 1-63. Only used in old PC BIOS.
*/
unsigned beginSector : 6;
/** High bits cylinder for first block in partition. */
unsigned beginCylinderHigh : 2;
/**
* Combine beginCylinderLow with beginCylinderHigh. Legal values
* are 0-1023. Only used in old PC BIOS.
*/
uint8_t beginCylinderLow;
/**
* Partition type. See defines that begin with PART_TYPE_ for
* some Microsoft partition types.
*/
uint8_t type;
/**
* head part of cylinder-head-sector address of the last sector in the
* partition. Legal values are 0-255. Only used in old PC BIOS.
*/
uint8_t endHead;
/**
* Sector part of cylinder-head-sector address of the last sector in
* the partition. Legal values are 1-63. Only used in old PC BIOS.
*/
unsigned endSector : 6;
/** High bits of end cylinder */
unsigned endCylinderHigh : 2;
/**
* Combine endCylinderLow with endCylinderHigh. Legal values
* are 0-1023. Only used in old PC BIOS.
*/
uint8_t endCylinderLow;
uint32_t firstSector; // Logical block address of the first block in the partition.
uint32_t totalSectors; // Length of the partition, in blocks.
} PACKED;
typedef struct partitionTable part_t; // Type name for partitionTable
/**
* \struct masterBootRecord
*
* \brief Master Boot Record
*
* The first block of a storage device that is formatted with a MBR.
*/
struct masterBootRecord {
uint8_t codeArea[440]; // Code Area for master boot program.
uint32_t diskSignature; // Optional Windows NT disk signature. May contain boot code.
uint16_t usuallyZero; // Usually zero but may be more boot code.
part_t part[4]; // Partition tables.
uint8_t mbrSig0; // First MBR signature byte. Must be 0x55
uint8_t mbrSig1; // Second MBR signature byte. Must be 0xAA
} PACKED;
/** Type name for masterBootRecord */
typedef struct masterBootRecord mbr_t;
/**
* \struct fat_boot
*
* \brief Boot sector for a FAT12/FAT16 volume.
*
*/
struct fat_boot {
/**
* The first three bytes of the boot sector must be valid,
* executable x 86-based CPU instructions. This includes a
* jump instruction that skips the next nonexecutable bytes.
*/
uint8_t jump[3];
/**
* This is typically a string of characters that identifies
* the operating system that formatted the volume.
*/
char oemId[8];
/**
* The size of a hardware sector. Valid decimal values for this
* field are 512, 1024, 2048, and 4096. For most disks used in
* the United States, the value of this field is 512.
*/
uint16_t bytesPerSector;
/**
* Number of sectors per allocation unit. This value must be a
* power of 2 that is greater than 0. The legal values are
* 1, 2, 4, 8, 16, 32, 64, and 128. 128 should be avoided.
*/
uint8_t sectorsPerCluster;
/**
* The number of sectors preceding the start of the first FAT,
* including the boot sector. The value of this field is always 1.
*/
uint16_t reservedSectorCount;
/**
* The number of copies of the FAT on the volume.
* The value of this field is always 2.
*/
uint8_t fatCount;
/**
* For FAT12 and FAT16 volumes, this field contains the count of
* 32-byte directory entries in the root directory. For FAT32 volumes,
* this field must be set to 0. For FAT12 and FAT16 volumes, this
* value should always specify a count that when multiplied by 32
* results in a multiple of bytesPerSector. FAT16 volumes should
* use the value 512.
*/
uint16_t rootDirEntryCount;
/**
* This field is the old 16-bit total count of sectors on the volume.
* This count includes the count of all sectors in all four regions
* of the volume. This field can be 0; if it is 0, then totalSectors32
* must be nonzero. For FAT32 volumes, this field must be 0. For
* FAT12 and FAT16 volumes, this field contains the sector count, and
* totalSectors32 is 0 if the total sector count fits
* (is less than 0x10000).
*/
uint16_t totalSectors16;
/**
* This dates back to the old MS-DOS 1.x media determination and is
* no longer usually used for anything. 0xF8 is the standard value
* for fixed (nonremovable) media. For removable media, 0xF0 is
* frequently used. Legal values are 0xF0 or 0xF8-0xFF.
*/
uint8_t mediaType;
/**
* Count of sectors occupied by one FAT on FAT12/FAT16 volumes.
* On FAT32 volumes this field must be 0, and sectorsPerFat32
* contains the FAT size count.
*/
uint16_t sectorsPerFat16;
uint16_t sectorsPerTrack; // Sectors per track for interrupt 0x13. Not used otherwise.
uint16_t headCount; // Number of heads for interrupt 0x13. Not used otherwise.
/**
* Count of hidden sectors preceding the partition that contains this
* FAT volume. This field is generally only relevant for media
* visible on interrupt 0x13.
*/
uint32_t hidddenSectors;
/**
* This field is the new 32-bit total count of sectors on the volume.
* This count includes the count of all sectors in all four regions
* of the volume. This field can be 0; if it is 0, then
* totalSectors16 must be nonzero.
*/
uint32_t totalSectors32;
/**
* Related to the BIOS physical drive number. Floppy drives are
* identified as 0x00 and physical hard disks are identified as
* 0x80, regardless of the number of physical disk drives.
* Typically, this value is set prior to issuing an INT 13h BIOS
* call to specify the device to access. The value is only
* relevant if the device is a boot device.
*/
uint8_t driveNumber;
uint8_t reserved1; // used by Windows NT - should be zero for FAT
uint8_t bootSignature; // 0x29 if next three fields are valid
/**
* A random serial number created when formatting a disk,
* which helps to distinguish between disks.
* Usually generated by combining date and time.
*/
uint32_t volumeSerialNumber;
/**
* A field once used to store the volume label. The volume label
* is now stored as a special file in the root directory.
*/
char volumeLabel[11];
/**
* A field with a value of either FAT, FAT12 or FAT16,
* depending on the disk format.
*/
char fileSystemType[8];
uint8_t bootCode[448]; // X86 boot code
uint8_t bootSectorSig0; // must be 0x55
uint8_t bootSectorSig1; // must be 0xAA
} PACKED;
typedef struct fat_boot fat_boot_t; // Type name for FAT Boot Sector
/**
* \struct fat32_boot
*
* \brief Boot sector for a FAT32 volume.
*/
struct fat32_boot {
/**
* The first three bytes of the boot sector must be valid,
* executable x 86-based CPU instructions. This includes a
* jump instruction that skips the next nonexecutable bytes.
*/
uint8_t jump[3];
/**
* This is typically a string of characters that identifies
* the operating system that formatted the volume.
*/
char oemId[8];
/**
* The size of a hardware sector. Valid decimal values for this
* field are 512, 1024, 2048, and 4096. For most disks used in
* the United States, the value of this field is 512.
*/
uint16_t bytesPerSector;
/**
* Number of sectors per allocation unit. This value must be a
* power of 2 that is greater than 0. The legal values are
* 1, 2, 4, 8, 16, 32, 64, and 128. 128 should be avoided.
*/
uint8_t sectorsPerCluster;
/**
* The number of sectors preceding the start of the first FAT,
* including the boot sector. Must not be zero
*/
uint16_t reservedSectorCount;
/**
* The number of copies of the FAT on the volume.
* The value of this field is always 2.
*/
uint8_t fatCount;
/**
* FAT12/FAT16 only. For FAT32 volumes, this field must be set to 0.
*/
uint16_t rootDirEntryCount;
/**
* For FAT32 volumes, this field must be 0.
*/
uint16_t totalSectors16;
/**
* This dates back to the old MS-DOS 1.x media determination and is
* no longer usually used for anything. 0xF8 is the standard value
* for fixed (nonremovable) media. For removable media, 0xF0 is
* frequently used. Legal values are 0xF0 or 0xF8-0xFF.
*/
uint8_t mediaType;
/**
* On FAT32 volumes this field must be 0, and sectorsPerFat32
* contains the FAT size count.
*/
uint16_t sectorsPerFat16;
uint16_t sectorsPerTrack; // Sectors per track for interrupt 0x13. Not used otherwise.
uint16_t headCount; // Number of heads for interrupt 0x13. Not used otherwise.
/**
* Count of hidden sectors preceding the partition that contains this
* FAT volume. This field is generally only relevant for media
* visible on interrupt 0x13.
*/
uint32_t hidddenSectors;
/**
* Contains the total number of sectors in the FAT32 volume.
*/
uint32_t totalSectors32;
/**
* Count of sectors occupied by one FAT on FAT32 volumes.
*/
uint32_t sectorsPerFat32;
/**
* This field is only defined for FAT32 media and does not exist on
* FAT12 and FAT16 media.
* Bits 0-3 -- Zero-based number of active FAT.
* Only valid if mirroring is disabled.
* Bits 4-6 -- Reserved.
* Bit 7 -- 0 means the FAT is mirrored at runtime into all FATs.
* -- 1 means only one FAT is active; it is the one referenced
* in bits 0-3.
* Bits 8-15 -- Reserved.
*/
uint16_t fat32Flags;
/**
* FAT32 version. High byte is major revision number.
* Low byte is minor revision number. Only 0.0 define.
*/
uint16_t fat32Version;
/**
* Cluster number of the first cluster of the root directory for FAT32.
* This usually 2 but not required to be 2.
*/
uint32_t fat32RootCluster;
/**
* Sector number of FSINFO structure in the reserved area of the
* FAT32 volume. Usually 1.
*/
uint16_t fat32FSInfo;
/**
* If nonzero, indicates the sector number in the reserved area
* of the volume of a copy of the boot record. Usually 6.
* No value other than 6 is recommended.
*/
uint16_t fat32BackBootBlock;
/**
* Reserved for future expansion. Code that formats FAT32 volumes
* should always set all of the bytes of this field to 0.
*/
uint8_t fat32Reserved[12];
/**
* Related to the BIOS physical drive number. Floppy drives are
* identified as 0x00 and physical hard disks are identified as
* 0x80, regardless of the number of physical disk drives.
* Typically, this value is set prior to issuing an INT 13h BIOS
* call to specify the device to access. The value is only
* relevant if the device is a boot device.
*/
uint8_t driveNumber;
uint8_t reserved1; // Used by Windows NT - should be zero for FAT
uint8_t bootSignature; // 0x29 if next three fields are valid
/**
* A random serial number created when formatting a disk,
* which helps to distinguish between disks.
* Usually generated by combining date and time.
*/
uint32_t volumeSerialNumber;
/**
* A field once used to store the volume label. The volume label
* is now stored as a special file in the root directory.
*/
char volumeLabel[11];
/**
* A text field with a value of FAT32.
*/
char fileSystemType[8];
uint8_t bootCode[420]; // X86 boot code
uint8_t bootSectorSig0; // must be 0x55
uint8_t bootSectorSig1; // must be 0xAA
} PACKED;
typedef struct fat32_boot fat32_boot_t; // Type name for FAT32 Boot Sector
uint32_t const FSINFO_LEAD_SIG = 0x41615252, // 'AaRR' Lead signature for a FSINFO sector
FSINFO_STRUCT_SIG = 0x61417272; // 'aArr' Struct signature for a FSINFO sector
/**
* \struct fat32_fsinfo
*
* \brief FSINFO sector for a FAT32 volume.
*
*/
struct fat32_fsinfo {
uint32_t leadSignature; // must be 0x52, 0x52, 0x61, 0x41 'RRaA'
uint8_t reserved1[480]; // must be zero
uint32_t structSignature; // must be 0x72, 0x72, 0x41, 0x61 'rrAa'
/**
* Contains the last known free cluster count on the volume.
* If the value is 0xFFFFFFFF, then the free count is unknown
* and must be computed. Any other value can be used, but is
* not necessarily correct. It should be range checked at least
* to make sure it is <= volume cluster count.
*/
uint32_t freeCount;
/**
* This is a hint for the FAT driver. It indicates the cluster
* number at which the driver should start looking for free clusters.
* If the value is 0xFFFFFFFF, then there is no hint and the driver
* should start looking at cluster 2.
*/
uint32_t nextFree;
uint8_t reserved2[12]; // must be zero
uint8_t tailSignature[4]; // must be 0x00, 0x00, 0x55, 0xAA
} PACKED;
typedef struct fat32_fsinfo fat32_fsinfo_t; // Type name for FAT32 FSINFO Sector
// End Of Chain values for FAT entries
uint16_t const FAT12EOC = 0xFFF, // FAT12 end of chain value used by Microsoft.
FAT12EOC_MIN = 0xFF8, // Minimum value for FAT12 EOC. Use to test for EOC.
FAT16EOC = 0xFFFF, // FAT16 end of chain value used by Microsoft.
FAT16EOC_MIN = 0xFFF8; // Minimum value for FAT16 EOC. Use to test for EOC.
uint32_t const FAT32EOC = 0x0FFFFFFF, // FAT32 end of chain value used by Microsoft.
FAT32EOC_MIN = 0x0FFFFFF8, // Minimum value for FAT32 EOC. Use to test for EOC.
FAT32MASK = 0x0FFFFFFF; // Mask a for FAT32 entry. Entries are 28 bits.
/**
* \struct directoryEntry
* \brief FAT short directory entry
*
* Short means short 8.3 name, not the entry size.
*
* Date Format. A FAT directory entry date stamp is a 16-bit field that is
* basically a date relative to the MS-DOS epoch of 01/01/1980. Here is the
* format (bit 0 is the LSB of the 16-bit word, bit 15 is the MSB of the
* 16-bit word):
*
* Bits 9-15: Count of years from 1980, valid value range 0-127
* inclusive (1980-2107).
*
* Bits 5-8: Month of year, 1 = January, valid value range 1-12 inclusive.
*
* Bits 0-4: Day of month, valid value range 1-31 inclusive.
*
* Time Format. A FAT directory entry time stamp is a 16-bit field that has
* a granularity of 2 seconds. Here is the format (bit 0 is the LSB of the
* 16-bit word, bit 15 is the MSB of the 16-bit word).
*
* Bits 11-15: Hours, valid value range 0-23 inclusive.
*
* Bits 5-10: Minutes, valid value range 0-59 inclusive.
*
* Bits 0-4: 2-second count, valid value range 0-29 inclusive (0 - 58 seconds).
*
* The valid time range is from Midnight 00:00:00 to 23:59:58.
*/
struct directoryEntry {
/**
* Short 8.3 name.
*
* The first eight bytes contain the file name with blank fill.
* The last three bytes contain the file extension with blank fill.
*/
uint8_t name[11];
/**
* Entry attributes.
*
* The upper two bits of the attribute byte are reserved and should
* always be set to 0 when a file is created and never modified or
* looked at after that. See defines that begin with DIR_ATT_.
*/
uint8_t attributes;
/**
* Reserved for use by Windows NT. Set value to 0 when a file is
* created and never modify or look at it after that.
*/
uint8_t reservedNT;
/**
* The granularity of the seconds part of creationTime is 2 seconds
* so this field is a count of tenths of a second and it's valid
* value range is 0-199 inclusive. (WHG note - seems to be hundredths)
*/
uint8_t creationTimeTenths;
uint16_t creationTime; // Time file was created.
uint16_t creationDate; // Date file was created.
/**
* Last access date. Note that there is no last access time, only
* a date. This is the date of last read or write. In the case of
* a write, this should be set to the same date as lastWriteDate.
*/
uint16_t lastAccessDate;
/**
* High word of this entry's first cluster number (always 0 for a
* FAT12 or FAT16 volume).
*/
uint16_t firstClusterHigh;
uint16_t lastWriteTime; // Time of last write. File creation is considered a write.
uint16_t lastWriteDate; // Date of last write. File creation is considered a write.
uint16_t firstClusterLow; // Low word of this entry's first cluster number.
uint32_t fileSize; // 32-bit unsigned holding this file's size in bytes.
} PACKED;
/**
* \struct directoryVFATEntry
* \brief VFAT long filename directory entry
*
* directoryVFATEntries are found in the same list as normal directoryEntry.
* But have the attribute field set to DIR_ATT_LONG_NAME.
*
* Long filenames are saved in multiple directoryVFATEntries.
* Each entry containing 13 UTF-16 characters.
*/
struct directoryVFATEntry {
/**
* Sequence number. Consists of 2 parts:
* bit 6: indicates first long filename block for the next file
* bit 0-4: the position of this long filename block (first block is 1)
*/
uint8_t sequenceNumber;
uint16_t name1[5]; // First set of UTF-16 characters
uint8_t attributes; // attributes (at the same location as in directoryEntry), always 0x0F
uint8_t reservedNT; // Reserved for use by Windows NT. Always 0.
uint8_t checksum; // Checksum of the short 8.3 filename, can be used to checked if the file system as modified by a not-long-filename aware implementation.
uint16_t name2[6]; // Second set of UTF-16 characters
uint16_t firstClusterLow; // firstClusterLow is always zero for longFilenames
uint16_t name3[2]; // Third set of UTF-16 characters
} PACKED;
// Definitions for directory entries
//
typedef struct directoryEntry dir_t; // Type name for directoryEntry
typedef struct directoryVFATEntry vfat_t; // Type name for directoryVFATEntry
uint8_t const DIR_NAME_0xE5 = 0x05, // escape for name[0] = 0xE5
DIR_NAME_DELETED = 0xE5, // name[0] value for entry that is free after being "deleted"
DIR_NAME_FREE = 0x00, // name[0] value for entry that is free and no allocated entries follow
DIR_ATT_READ_ONLY = 0x01, // file is read-only
DIR_ATT_HIDDEN = 0x02, // File should hidden in directory listings
DIR_ATT_SYSTEM = 0x04, // Entry is for a system file
DIR_ATT_VOLUME_ID = 0x08, // Directory entry contains the volume label
DIR_ATT_DIRECTORY = 0x10, // Entry is for a directory
DIR_ATT_ARCHIVE = 0x20, // Old DOS archive bit for backup support
DIR_ATT_LONG_NAME = 0x0F, // Test value for long name entry. Test is (d->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME.
DIR_ATT_LONG_NAME_MASK = 0x3F, // Test mask for long name entry
DIR_ATT_DEFINED_BITS = 0x3F; // defined attribute bits
/**
* Directory entry is part of a long name
* \param[in] dir Pointer to a directory entry.
*
* \return true if the entry is for part of a long name else false.
*/
static inline uint8_t DIR_IS_LONG_NAME(const dir_t* dir) {
return (dir->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME;
}
/** Mask for file/subdirectory tests */
uint8_t const DIR_ATT_FILE_TYPE_MASK = (DIR_ATT_VOLUME_ID | DIR_ATT_DIRECTORY);
/**
* Directory entry is for a file
* \param[in] dir Pointer to a directory entry.
*
* \return true if the entry is for a normal file else false.
*/
static inline uint8_t DIR_IS_FILE(const dir_t* dir) {
return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == 0;
}
/**
* Directory entry is for a subdirectory
* \param[in] dir Pointer to a directory entry.
*
* \return true if the entry is for a subdirectory else false.
*/
static inline uint8_t DIR_IS_SUBDIR(const dir_t* dir) {
return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == DIR_ATT_DIRECTORY;
}
/**
* Directory entry is for a file or subdirectory
* \param[in] dir Pointer to a directory entry.
*
* \return true if the entry is for a normal file or subdirectory else false.
*/
static inline uint8_t DIR_IS_FILE_OR_SUBDIR(const dir_t* dir) {
return (dir->attributes & DIR_ATT_VOLUME_ID) == 0;
}
#endif // SDFATSTRUCTS_H

91
Marlin/SdFatUtil.cpp Normal file
View File

@ -0,0 +1,91 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* Arduino SdFat Library
* Copyright (C) 2008 by William Greiman
*
* This file is part of the Arduino Sd2Card Library
*/
#include "MarlinConfig.h"
#if ENABLED(SDSUPPORT)
#include "SdFatUtil.h"
#include "serial.h"
/**
* Amount of free RAM
* \return The number of free bytes.
*/
#ifdef __arm__
extern "C" char* sbrk(int incr);
int SdFatUtil::FreeRam() {
char top;
return &top - reinterpret_cast<char*>(sbrk(0));
}
#else // __arm__
extern char* __brkval;
extern char __bss_end;
/**
* Amount of free RAM
* \return The number of free bytes.
*/
int SdFatUtil::FreeRam() {
char top;
return __brkval ? &top - __brkval : &top - &__bss_end;
}
#endif // __arm
/**
* %Print a string in flash memory.
*
* \param[in] pr Print object for output.
* \param[in] str Pointer to string stored in flash memory.
*/
void SdFatUtil::print_P(PGM_P str) {
for (uint8_t c; (c = pgm_read_byte(str)); str++) SERIAL_CHAR(c);
}
/**
* %Print a string in flash memory followed by a CR/LF.
*
* \param[in] pr Print object for output.
* \param[in] str Pointer to string stored in flash memory.
*/
void SdFatUtil::println_P(PGM_P str) { print_P(str); SERIAL_EOL(); }
/**
* %Print a string in flash memory to Serial.
*
* \param[in] str Pointer to string stored in flash memory.
*/
void SdFatUtil::SerialPrint_P(PGM_P str) { print_P(str); }
/**
* %Print a string in flash memory to Serial followed by a CR/LF.
*
* \param[in] str Pointer to string stored in flash memory.
*/
void SdFatUtil::SerialPrintln_P(PGM_P str) { println_P(str); }
#endif // SDSUPPORT

51
Marlin/SdFatUtil.h Normal file
View File

@ -0,0 +1,51 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* Arduino SdFat Library
* Copyright (C) 2008 by William Greiman
*
* This file is part of the Arduino Sd2Card Library
*/
#ifndef _SDFATUTIL_H_
#define _SDFATUTIL_H_
/**
* \file
* \brief Useful utility functions.
*/
/** Store and print a string in flash memory.*/
#define PgmPrint(x) SerialPrint_P(PSTR(x))
/** Store and print a string in flash memory followed by a CR/LF.*/
#define PgmPrintln(x) SerialPrintln_P(PSTR(x))
namespace SdFatUtil {
int FreeRam();
void print_P(PGM_P str);
void println_P(PGM_P str);
void SerialPrint_P(PGM_P str);
void SerialPrintln_P(PGM_P str);
}
using namespace SdFatUtil; // NOLINT
#endif // _SDFATUTIL_H_

100
Marlin/SdFile.cpp Normal file
View File

@ -0,0 +1,100 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* Arduino SdFat Library
* Copyright (C) 2009 by William Greiman
*
* This file is part of the Arduino Sd2Card Library
*/
#include "MarlinConfig.h"
#if ENABLED(SDSUPPORT)
#include "SdFile.h"
/**
* Create a file object and open it in the current working directory.
*
* \param[in] path A path with a valid 8.3 DOS name for a file to be opened.
*
* \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive
* OR of open flags. see SdBaseFile::open(SdBaseFile*, const char*, uint8_t).
*/
SdFile::SdFile(const char* path, uint8_t oflag) : SdBaseFile(path, oflag) { }
/**
* Write data to an open file.
*
* \note Data is moved to the cache but may not be written to the
* storage device until sync() is called.
*
* \param[in] buf Pointer to the location of the data to be written.
*
* \param[in] nbyte Number of bytes to write.
*
* \return For success write() returns the number of bytes written, always
* \a nbyte. If an error occurs, write() returns -1. Possible errors
* include write() is called before a file has been opened, write is called
* for a read-only file, device is full, a corrupt file system or an I/O error.
*
*/
int16_t SdFile::write(const void* buf, uint16_t nbyte) { return SdBaseFile::write(buf, nbyte); }
/**
* Write a byte to a file. Required by the Arduino Print class.
* \param[in] b the byte to be written.
* Use writeError to check for errors.
*/
#if ARDUINO >= 100
size_t SdFile::write(uint8_t b) { return SdBaseFile::write(&b, 1); }
#else
void SdFile::write(uint8_t b) { SdBaseFile::write(&b, 1); }
#endif
/**
* Write a string to a file. Used by the Arduino Print class.
* \param[in] str Pointer to the string.
* Use writeError to check for errors.
*/
void SdFile::write(const char* str) { SdBaseFile::write(str, strlen(str)); }
/**
* Write a PROGMEM string to a file.
* \param[in] str Pointer to the PROGMEM string.
* Use writeError to check for errors.
*/
void SdFile::write_P(PGM_P str) {
for (uint8_t c; (c = pgm_read_byte(str)); str++) write(c);
}
/**
* Write a PROGMEM string followed by CR/LF to a file.
* \param[in] str Pointer to the PROGMEM string.
* Use writeError to check for errors.
*/
void SdFile::writeln_P(PGM_P str) {
write_P(str);
write_P(PSTR("\r\n"));
}
#endif // SDSUPPORT

60
Marlin/SdFile.h Normal file
View File

@ -0,0 +1,60 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* \file
* \brief SdFile class
*/
/**
* Arduino SdFat Library
* Copyright (C) 2009 by William Greiman
*
* This file is part of the Arduino Sd2Card Library
*/
#ifndef _SDFILE_H_
#define _SDFILE_H_
#include "SdBaseFile.h"
#include <Print.h>
/**
* \class SdFile
* \brief SdBaseFile with Print.
*/
class SdFile : public SdBaseFile, public Print {
public:
SdFile() {}
SdFile(const char* name, uint8_t oflag);
#if ARDUINO >= 100
size_t write(uint8_t b);
#else
void write(uint8_t b);
#endif
int16_t write(const void* buf, uint16_t nbyte);
void write(const char* str);
void write_P(PGM_P str);
void writeln_P(PGM_P str);
};
#endif // _SDFILE_H_

267
Marlin/SdInfo.h Normal file
View File

@ -0,0 +1,267 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* Arduino Sd2Card Library
* Copyright (C) 2009 by William Greiman
*
* This file is part of the Arduino Sd2Card Library
*/
#ifndef _SDINFO_H_
#define _SDINFO_H_
#include <stdint.h>
// Based on the document:
//
// SD Specifications
// Part 1
// Physical Layer
// Simplified Specification
// Version 3.01
// May 18, 2010
//
// http://www.sdcard.org/developers/tech/sdcard/pls/simplified_specs
// SD card commands
uint8_t const CMD0 = 0x00, // GO_IDLE_STATE - init card in spi mode if CS low
CMD8 = 0x08, // SEND_IF_COND - verify SD Memory Card interface operating condition
CMD9 = 0x09, // SEND_CSD - read the Card Specific Data (CSD register)
CMD10 = 0x0A, // SEND_CID - read the card identification information (CID register)
CMD12 = 0x0C, // STOP_TRANSMISSION - end multiple block read sequence
CMD13 = 0x0D, // SEND_STATUS - read the card status register
CMD17 = 0x11, // READ_SINGLE_BLOCK - read a single data block from the card
CMD18 = 0x12, // READ_MULTIPLE_BLOCK - read a multiple data blocks from the card
CMD24 = 0x18, // WRITE_BLOCK - write a single data block to the card
CMD25 = 0x19, // WRITE_MULTIPLE_BLOCK - write blocks of data until a STOP_TRANSMISSION
CMD32 = 0x20, // ERASE_WR_BLK_START - sets the address of the first block to be erased
CMD33 = 0x21, // ERASE_WR_BLK_END - sets the address of the last block of the continuous range to be erased*/
CMD38 = 0x26, // ERASE - erase all previously selected blocks */
CMD55 = 0x37, // APP_CMD - escape for application specific command */
CMD58 = 0x3A, // READ_OCR - read the OCR register of a card */
ACMD23 = 0x17, // SET_WR_BLK_ERASE_COUNT - Set the number of write blocks to be pre-erased before writing */
ACMD41 = 0x29; // SD_SEND_OP_COMD - Sends host capacity support information and activates the card's initialization process */
/** status for card in the ready state */
uint8_t const R1_READY_STATE = 0x00;
/** status for card in the idle state */
uint8_t const R1_IDLE_STATE = 0x01;
/** status bit for illegal command */
uint8_t const R1_ILLEGAL_COMMAND = 0x04;
/** start data token for read or write single block*/
uint8_t const DATA_START_BLOCK = 0xFE;
/** stop token for write multiple blocks*/
uint8_t const STOP_TRAN_TOKEN = 0xFD;
/** start data token for write multiple blocks*/
uint8_t const WRITE_MULTIPLE_TOKEN = 0xFC;
/** mask for data response tokens after a write block operation */
uint8_t const DATA_RES_MASK = 0x1F;
/** write data accepted token */
uint8_t const DATA_RES_ACCEPTED = 0x05;
/** Card IDentification (CID) register */
typedef struct CID {
// byte 0
/** Manufacturer ID */
unsigned char mid;
// byte 1-2
/** OEM/Application ID */
char oid[2];
// byte 3-7
/** Product name */
char pnm[5];
// byte 8
/** Product revision least significant digit */
unsigned char prv_m : 4;
/** Product revision most significant digit */
unsigned char prv_n : 4;
// byte 9-12
/** Product serial number */
uint32_t psn;
// byte 13
/** Manufacturing date year low digit */
unsigned char mdt_year_high : 4;
/** not used */
unsigned char reserved : 4;
// byte 14
/** Manufacturing date month */
unsigned char mdt_month : 4;
/** Manufacturing date year low digit */
unsigned char mdt_year_low : 4;
// byte 15
/** not used always 1 */
unsigned char always1 : 1;
/** CRC7 checksum */
unsigned char crc : 7;
} cid_t;
/** CSD for version 1.00 cards */
typedef struct CSDV1 {
// byte 0
unsigned char reserved1 : 6;
unsigned char csd_ver : 2;
// byte 1
unsigned char taac;
// byte 2
unsigned char nsac;
// byte 3
unsigned char tran_speed;
// byte 4
unsigned char ccc_high;
// byte 5
unsigned char read_bl_len : 4;
unsigned char ccc_low : 4;
// byte 6
unsigned char c_size_high : 2;
unsigned char reserved2 : 2;
unsigned char dsr_imp : 1;
unsigned char read_blk_misalign : 1;
unsigned char write_blk_misalign : 1;
unsigned char read_bl_partial : 1;
// byte 7
unsigned char c_size_mid;
// byte 8
unsigned char vdd_r_curr_max : 3;
unsigned char vdd_r_curr_min : 3;
unsigned char c_size_low : 2;
// byte 9
unsigned char c_size_mult_high : 2;
unsigned char vdd_w_cur_max : 3;
unsigned char vdd_w_curr_min : 3;
// byte 10
unsigned char sector_size_high : 6;
unsigned char erase_blk_en : 1;
unsigned char c_size_mult_low : 1;
// byte 11
unsigned char wp_grp_size : 7;
unsigned char sector_size_low : 1;
// byte 12
unsigned char write_bl_len_high : 2;
unsigned char r2w_factor : 3;
unsigned char reserved3 : 2;
unsigned char wp_grp_enable : 1;
// byte 13
unsigned char reserved4 : 5;
unsigned char write_partial : 1;
unsigned char write_bl_len_low : 2;
// byte 14
unsigned char reserved5: 2;
unsigned char file_format : 2;
unsigned char tmp_write_protect : 1;
unsigned char perm_write_protect : 1;
unsigned char copy : 1;
/** Indicates the file format on the card */
unsigned char file_format_grp : 1;
// byte 15
unsigned char always1 : 1;
unsigned char crc : 7;
} csd1_t;
/** CSD for version 2.00 cards */
typedef struct CSDV2 {
// byte 0
unsigned char reserved1 : 6;
unsigned char csd_ver : 2;
// byte 1
/** fixed to 0x0E */
unsigned char taac;
// byte 2
/** fixed to 0 */
unsigned char nsac;
// byte 3
unsigned char tran_speed;
// byte 4
unsigned char ccc_high;
// byte 5
/** This field is fixed to 9h, which indicates READ_BL_LEN=512 Byte */
unsigned char read_bl_len : 4;
unsigned char ccc_low : 4;
// byte 6
/** not used */
unsigned char reserved2 : 4;
unsigned char dsr_imp : 1;
/** fixed to 0 */
unsigned char read_blk_misalign : 1;
/** fixed to 0 */
unsigned char write_blk_misalign : 1;
/** fixed to 0 - no partial read */
unsigned char read_bl_partial : 1;
// byte 7
/** not used */
unsigned char reserved3 : 2;
/** high part of card size */
unsigned char c_size_high : 6;
// byte 8
/** middle part of card size */
unsigned char c_size_mid;
// byte 9
/** low part of card size */
unsigned char c_size_low;
// byte 10
/** sector size is fixed at 64 KB */
unsigned char sector_size_high : 6;
/** fixed to 1 - erase single is supported */
unsigned char erase_blk_en : 1;
/** not used */
unsigned char reserved4 : 1;
// byte 11
unsigned char wp_grp_size : 7;
/** sector size is fixed at 64 KB */
unsigned char sector_size_low : 1;
// byte 12
/** write_bl_len fixed for 512 byte blocks */
unsigned char write_bl_len_high : 2;
/** fixed value of 2 */
unsigned char r2w_factor : 3;
/** not used */
unsigned char reserved5 : 2;
/** fixed value of 0 - no write protect groups */
unsigned char wp_grp_enable : 1;
// byte 13
unsigned char reserved6 : 5;
/** always zero - no partial block read*/
unsigned char write_partial : 1;
/** write_bl_len fixed for 512 byte blocks */
unsigned char write_bl_len_low : 2;
// byte 14
unsigned char reserved7: 2;
/** Do not use always 0 */
unsigned char file_format : 2;
unsigned char tmp_write_protect : 1;
unsigned char perm_write_protect : 1;
unsigned char copy : 1;
/** Do not use always 0 */
unsigned char file_format_grp : 1;
// byte 15
/** not used always 1 */
unsigned char always1 : 1;
/** checksum */
unsigned char crc : 7;
} csd2_t;
/** union of old and new style CSD register */
union csd_t {
csd1_t v1;
csd2_t v2;
};
#endif // _SDINFO_H_

384
Marlin/SdVolume.cpp Normal file
View File

@ -0,0 +1,384 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* Arduino SdFat Library
* Copyright (C) 2009 by William Greiman
*
* This file is part of the Arduino Sd2Card Library
*/
#include "MarlinConfig.h"
#if ENABLED(SDSUPPORT)
#include "SdVolume.h"
#if !USE_MULTIPLE_CARDS
// raw block cache
uint32_t SdVolume::cacheBlockNumber_; // current block number
cache_t SdVolume::cacheBuffer_; // 512 byte cache for Sd2Card
Sd2Card* SdVolume::sdCard_; // pointer to SD card object
bool SdVolume::cacheDirty_; // cacheFlush() will write block if true
uint32_t SdVolume::cacheMirrorBlock_; // mirror block for second FAT
#endif // USE_MULTIPLE_CARDS
// find a contiguous group of clusters
bool SdVolume::allocContiguous(uint32_t count, uint32_t* curCluster) {
// start of group
uint32_t bgnCluster;
// end of group
uint32_t endCluster;
// last cluster of FAT
uint32_t fatEnd = clusterCount_ + 1;
// flag to save place to start next search
bool setStart;
// set search start cluster
if (*curCluster) {
// try to make file contiguous
bgnCluster = *curCluster + 1;
// don't save new start location
setStart = false;
}
else {
// start at likely place for free cluster
bgnCluster = allocSearchStart_;
// save next search start if one cluster
setStart = count == 1;
}
// end of group
endCluster = bgnCluster;
// search the FAT for free clusters
for (uint32_t n = 0;; n++, endCluster++) {
// can't find space checked all clusters
if (n >= clusterCount_) return false;
// past end - start from beginning of FAT
if (endCluster > fatEnd) {
bgnCluster = endCluster = 2;
}
uint32_t f;
if (!fatGet(endCluster, &f)) return false;
if (f != 0) {
// cluster in use try next cluster as bgnCluster
bgnCluster = endCluster + 1;
}
else if ((endCluster - bgnCluster + 1) == count) {
// done - found space
break;
}
}
// mark end of chain
if (!fatPutEOC(endCluster)) return false;
// link clusters
while (endCluster > bgnCluster) {
if (!fatPut(endCluster - 1, endCluster)) return false;
endCluster--;
}
if (*curCluster != 0) {
// connect chains
if (!fatPut(*curCluster, bgnCluster)) return false;
}
// return first cluster number to caller
*curCluster = bgnCluster;
// remember possible next free cluster
if (setStart) allocSearchStart_ = bgnCluster + 1;
return true;
}
bool SdVolume::cacheFlush() {
if (cacheDirty_) {
if (!sdCard_->writeBlock(cacheBlockNumber_, cacheBuffer_.data))
return false;
// mirror FAT tables
if (cacheMirrorBlock_) {
if (!sdCard_->writeBlock(cacheMirrorBlock_, cacheBuffer_.data))
return false;
cacheMirrorBlock_ = 0;
}
cacheDirty_ = 0;
}
return true;
}
bool SdVolume::cacheRawBlock(uint32_t blockNumber, bool dirty) {
if (cacheBlockNumber_ != blockNumber) {
if (!cacheFlush()) return false;
if (!sdCard_->readBlock(blockNumber, cacheBuffer_.data)) return false;
cacheBlockNumber_ = blockNumber;
}
if (dirty) cacheDirty_ = true;
return true;
}
// return the size in bytes of a cluster chain
bool SdVolume::chainSize(uint32_t cluster, uint32_t* size) {
uint32_t s = 0;
do {
if (!fatGet(cluster, &cluster)) return false;
s += 512UL << clusterSizeShift_;
} while (!isEOC(cluster));
*size = s;
return true;
}
// Fetch a FAT entry
bool SdVolume::fatGet(uint32_t cluster, uint32_t* value) {
uint32_t lba;
if (cluster > (clusterCount_ + 1)) return false;
if (FAT12_SUPPORT && fatType_ == 12) {
uint16_t index = cluster;
index += index >> 1;
lba = fatStartBlock_ + (index >> 9);
if (!cacheRawBlock(lba, CACHE_FOR_READ)) return false;
index &= 0x1FF;
uint16_t tmp = cacheBuffer_.data[index];
index++;
if (index == 512) {
if (!cacheRawBlock(lba + 1, CACHE_FOR_READ)) return false;
index = 0;
}
tmp |= cacheBuffer_.data[index] << 8;
*value = cluster & 1 ? tmp >> 4 : tmp & 0xFFF;
return true;
}
if (fatType_ == 16)
lba = fatStartBlock_ + (cluster >> 8);
else if (fatType_ == 32)
lba = fatStartBlock_ + (cluster >> 7);
else
return false;
if (lba != cacheBlockNumber_ && !cacheRawBlock(lba, CACHE_FOR_READ))
return false;
*value = (fatType_ == 16) ? cacheBuffer_.fat16[cluster & 0xFF] : (cacheBuffer_.fat32[cluster & 0x7F] & FAT32MASK);
return true;
}
// Store a FAT entry
bool SdVolume::fatPut(uint32_t cluster, uint32_t value) {
uint32_t lba;
// error if reserved cluster
if (cluster < 2) return false;
// error if not in FAT
if (cluster > (clusterCount_ + 1)) return false;
if (FAT12_SUPPORT && fatType_ == 12) {
uint16_t index = cluster;
index += index >> 1;
lba = fatStartBlock_ + (index >> 9);
if (!cacheRawBlock(lba, CACHE_FOR_WRITE)) return false;
// mirror second FAT
if (fatCount_ > 1) cacheMirrorBlock_ = lba + blocksPerFat_;
index &= 0x1FF;
uint8_t tmp = value;
if (cluster & 1) {
tmp = (cacheBuffer_.data[index] & 0xF) | tmp << 4;
}
cacheBuffer_.data[index] = tmp;
index++;
if (index == 512) {
lba++;
index = 0;
if (!cacheRawBlock(lba, CACHE_FOR_WRITE)) return false;
// mirror second FAT
if (fatCount_ > 1) cacheMirrorBlock_ = lba + blocksPerFat_;
}
tmp = value >> 4;
if (!(cluster & 1)) {
tmp = ((cacheBuffer_.data[index] & 0xF0)) | tmp >> 4;
}
cacheBuffer_.data[index] = tmp;
return true;
}
if (fatType_ == 16)
lba = fatStartBlock_ + (cluster >> 8);
else if (fatType_ == 32)
lba = fatStartBlock_ + (cluster >> 7);
else
return false;
if (!cacheRawBlock(lba, CACHE_FOR_WRITE)) return false;
// store entry
if (fatType_ == 16)
cacheBuffer_.fat16[cluster & 0xFF] = value;
else
cacheBuffer_.fat32[cluster & 0x7F] = value;
// mirror second FAT
if (fatCount_ > 1) cacheMirrorBlock_ = lba + blocksPerFat_;
return true;
}
// free a cluster chain
bool SdVolume::freeChain(uint32_t cluster) {
// clear free cluster location
allocSearchStart_ = 2;
do {
uint32_t next;
if (!fatGet(cluster, &next)) return false;
// free cluster
if (!fatPut(cluster, 0)) return false;
cluster = next;
} while (!isEOC(cluster));
return true;
}
/** Volume free space in clusters.
*
* \return Count of free clusters for success or -1 if an error occurs.
*/
int32_t SdVolume::freeClusterCount() {
uint32_t free = 0;
uint16_t n;
uint32_t todo = clusterCount_ + 2;
if (fatType_ == 16)
n = 256;
else if (fatType_ == 32)
n = 128;
else // put FAT12 here
return -1;
for (uint32_t lba = fatStartBlock_; todo; todo -= n, lba++) {
if (!cacheRawBlock(lba, CACHE_FOR_READ)) return -1;
NOMORE(n, todo);
if (fatType_ == 16) {
for (uint16_t i = 0; i < n; i++)
if (cacheBuffer_.fat16[i] == 0) free++;
}
else {
for (uint16_t i = 0; i < n; i++)
if (cacheBuffer_.fat32[i] == 0) free++;
}
}
return free;
}
/** Initialize a FAT volume.
*
* \param[in] dev The SD card where the volume is located.
*
* \param[in] part The partition to be used. Legal values for \a part are
* 1-4 to use the corresponding partition on a device formatted with
* a MBR, Master Boot Record, or zero if the device is formatted as
* a super floppy with the FAT boot sector in block zero.
*
* \return true for success, false for failure.
* Reasons for failure include not finding a valid partition, not finding a valid
* FAT file system in the specified partition or an I/O error.
*/
bool SdVolume::init(Sd2Card* dev, uint8_t part) {
uint32_t totalBlocks, volumeStartBlock = 0;
fat32_boot_t* fbs;
sdCard_ = dev;
fatType_ = 0;
allocSearchStart_ = 2;
cacheDirty_ = 0; // cacheFlush() will write block if true
cacheMirrorBlock_ = 0;
cacheBlockNumber_ = 0xFFFFFFFF;
// if part == 0 assume super floppy with FAT boot sector in block zero
// if part > 0 assume mbr volume with partition table
if (part) {
if (part > 4) return false;
if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) return false;
part_t* p = &cacheBuffer_.mbr.part[part - 1];
if ((p->boot & 0x7F) != 0 || p->totalSectors < 100 || p->firstSector == 0)
return false; // not a valid partition
volumeStartBlock = p->firstSector;
}
if (!cacheRawBlock(volumeStartBlock, CACHE_FOR_READ)) return false;
fbs = &cacheBuffer_.fbs32;
if (fbs->bytesPerSector != 512 ||
fbs->fatCount == 0 ||
fbs->reservedSectorCount == 0 ||
fbs->sectorsPerCluster == 0) {
// not valid FAT volume
return false;
}
fatCount_ = fbs->fatCount;
blocksPerCluster_ = fbs->sectorsPerCluster;
// determine shift that is same as multiply by blocksPerCluster_
clusterSizeShift_ = 0;
while (blocksPerCluster_ != _BV(clusterSizeShift_)) {
// error if not power of 2
if (clusterSizeShift_++ > 7) return false;
}
blocksPerFat_ = fbs->sectorsPerFat16 ?
fbs->sectorsPerFat16 : fbs->sectorsPerFat32;
fatStartBlock_ = volumeStartBlock + fbs->reservedSectorCount;
// count for FAT16 zero for FAT32
rootDirEntryCount_ = fbs->rootDirEntryCount;
// directory start for FAT16 dataStart for FAT32
rootDirStart_ = fatStartBlock_ + fbs->fatCount * blocksPerFat_;
// data start for FAT16 and FAT32
dataStartBlock_ = rootDirStart_ + ((32 * fbs->rootDirEntryCount + 511) / 512);
// total blocks for FAT16 or FAT32
totalBlocks = fbs->totalSectors16 ?
fbs->totalSectors16 : fbs->totalSectors32;
// total data blocks
clusterCount_ = totalBlocks - (dataStartBlock_ - volumeStartBlock);
// divide by cluster size to get cluster count
clusterCount_ >>= clusterSizeShift_;
// FAT type is determined by cluster count
if (clusterCount_ < 4085) {
fatType_ = 12;
if (!FAT12_SUPPORT) return false;
}
else if (clusterCount_ < 65525)
fatType_ = 16;
else {
rootDirStart_ = fbs->fat32RootCluster;
fatType_ = 32;
}
return true;
}
#endif // SDSUPPORT

211
Marlin/SdVolume.h Normal file
View File

@ -0,0 +1,211 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* \file
* \brief SdVolume class
*/
/**
* Arduino SdFat Library
* Copyright (C) 2009 by William Greiman
*
* This file is part of the Arduino Sd2Card Library
*/
#ifndef _SDVOLUME_H_
#define _SDVOLUME_H_
#include "SdFatConfig.h"
#include "Sd2Card.h"
#include "SdFatStructs.h"
//==============================================================================
// SdVolume class
/**
* \brief Cache for an SD data block
*/
union cache_t {
uint8_t data[512]; // Used to access cached file data blocks.
uint16_t fat16[256]; // Used to access cached FAT16 entries.
uint32_t fat32[128]; // Used to access cached FAT32 entries.
dir_t dir[16]; // Used to access cached directory entries.
mbr_t mbr; // Used to access a cached Master Boot Record.
fat_boot_t fbs; // Used to access to a cached FAT boot sector.
fat32_boot_t fbs32; // Used to access to a cached FAT32 boot sector.
fat32_fsinfo_t fsinfo; // Used to access to a cached FAT32 FSINFO sector.
};
/**
* \class SdVolume
* \brief Access FAT16 and FAT32 volumes on SD and SDHC cards.
*/
class SdVolume {
public:
// Create an instance of SdVolume
SdVolume() : fatType_(0) {}
/**
* Clear the cache and returns a pointer to the cache. Used by the WaveRP
* recorder to do raw write to the SD card. Not for normal apps.
* \return A pointer to the cache buffer or zero if an error occurs.
*/
cache_t* cacheClear() {
if (!cacheFlush()) return 0;
cacheBlockNumber_ = 0xFFFFFFFF;
return &cacheBuffer_;
}
/**
* Initialize a FAT volume. Try partition one first then try super
* floppy format.
*
* \param[in] dev The Sd2Card where the volume is located.
*
* \return true for success, false for failure.
* Reasons for failure include not finding a valid partition, not finding
* a valid FAT file system or an I/O error.
*/
bool init(Sd2Card* dev) { return init(dev, 1) ? true : init(dev, 0); }
bool init(Sd2Card* dev, uint8_t part);
// inline functions that return volume info
uint8_t blocksPerCluster() const { return blocksPerCluster_; } //> \return The volume's cluster size in blocks.
uint32_t blocksPerFat() const { return blocksPerFat_; } //> \return The number of blocks in one FAT.
uint32_t clusterCount() const { return clusterCount_; } //> \return The total number of clusters in the volume.
uint8_t clusterSizeShift() const { return clusterSizeShift_; } //> \return The shift count required to multiply by blocksPerCluster.
uint32_t dataStartBlock() const { return dataStartBlock_; } //> \return The logical block number for the start of file data.
uint8_t fatCount() const { return fatCount_; } //> \return The number of FAT structures on the volume.
uint32_t fatStartBlock() const { return fatStartBlock_; } //> \return The logical block number for the start of the first FAT.
uint8_t fatType() const { return fatType_; } //> \return The FAT type of the volume. Values are 12, 16 or 32.
int32_t freeClusterCount();
uint32_t rootDirEntryCount() const { return rootDirEntryCount_; } /** \return The number of entries in the root directory for FAT16 volumes. */
/**
* \return The logical block number for the start of the root directory
* on FAT16 volumes or the first cluster number on FAT32 volumes.
*/
uint32_t rootDirStart() const { return rootDirStart_; }
/**
* Sd2Card object for this volume
* \return pointer to Sd2Card object.
*/
Sd2Card* sdCard() { return sdCard_; }
/**
* Debug access to FAT table
*
* \param[in] n cluster number.
* \param[out] v value of entry
* \return true for success or false for failure
*/
bool dbgFat(uint32_t n, uint32_t* v) { return fatGet(n, v); }
private:
// Allow SdBaseFile access to SdVolume private data.
friend class SdBaseFile;
// value for dirty argument in cacheRawBlock to indicate read from cache
static bool const CACHE_FOR_READ = false;
// value for dirty argument in cacheRawBlock to indicate write to cache
static bool const CACHE_FOR_WRITE = true;
#if USE_MULTIPLE_CARDS
cache_t cacheBuffer_; // 512 byte cache for device blocks
uint32_t cacheBlockNumber_; // Logical number of block in the cache
Sd2Card* sdCard_; // Sd2Card object for cache
bool cacheDirty_; // cacheFlush() will write block if true
uint32_t cacheMirrorBlock_; // block number for mirror FAT
#else
static cache_t cacheBuffer_; // 512 byte cache for device blocks
static uint32_t cacheBlockNumber_; // Logical number of block in the cache
static Sd2Card* sdCard_; // Sd2Card object for cache
static bool cacheDirty_; // cacheFlush() will write block if true
static uint32_t cacheMirrorBlock_; // block number for mirror FAT
#endif
uint32_t allocSearchStart_; // start cluster for alloc search
uint8_t blocksPerCluster_; // cluster size in blocks
uint32_t blocksPerFat_; // FAT size in blocks
uint32_t clusterCount_; // clusters in one FAT
uint8_t clusterSizeShift_; // shift to convert cluster count to block count
uint32_t dataStartBlock_; // first data block number
uint8_t fatCount_; // number of FATs on volume
uint32_t fatStartBlock_; // start block for first FAT
uint8_t fatType_; // volume type (12, 16, OR 32)
uint16_t rootDirEntryCount_; // number of entries in FAT16 root dir
uint32_t rootDirStart_; // root start block for FAT16, cluster for FAT32
bool allocContiguous(uint32_t count, uint32_t* curCluster);
uint8_t blockOfCluster(uint32_t position) const { return (position >> 9) & (blocksPerCluster_ - 1); }
uint32_t clusterStartBlock(uint32_t cluster) const { return dataStartBlock_ + ((cluster - 2) << clusterSizeShift_); }
uint32_t blockNumber(uint32_t cluster, uint32_t position) const { return clusterStartBlock(cluster) + blockOfCluster(position); }
cache_t* cache() { return &cacheBuffer_; }
uint32_t cacheBlockNumber() const { return cacheBlockNumber_; }
#if USE_MULTIPLE_CARDS
bool cacheFlush();
bool cacheRawBlock(uint32_t blockNumber, bool dirty);
#else
static bool cacheFlush();
static bool cacheRawBlock(uint32_t blockNumber, bool dirty);
#endif
// used by SdBaseFile write to assign cache to SD location
void cacheSetBlockNumber(uint32_t blockNumber, bool dirty) {
cacheDirty_ = dirty;
cacheBlockNumber_ = blockNumber;
}
void cacheSetDirty() { cacheDirty_ |= CACHE_FOR_WRITE; }
bool chainSize(uint32_t beginCluster, uint32_t* size);
bool fatGet(uint32_t cluster, uint32_t* value);
bool fatPut(uint32_t cluster, uint32_t value);
bool fatPutEOC(uint32_t cluster) { return fatPut(cluster, 0x0FFFFFFF); }
bool freeChain(uint32_t cluster);
bool isEOC(uint32_t cluster) const {
if (FAT12_SUPPORT && fatType_ == 12) return cluster >= FAT12EOC_MIN;
if (fatType_ == 16) return cluster >= FAT16EOC_MIN;
return cluster >= FAT32EOC_MIN;
}
bool readBlock(uint32_t block, uint8_t* dst) { return sdCard_->readBlock(block, dst); }
bool writeBlock(uint32_t block, const uint8_t* dst) { return sdCard_->writeBlock(block, dst); }
// Deprecated functions
#if ALLOW_DEPRECATED_FUNCTIONS
public:
/**
* \deprecated Use: bool SdVolume::init(Sd2Card* dev);
* \param[in] dev The SD card where the volume is located.
* \return true for success or false for failure.
*/
bool init(Sd2Card& dev) { return init(&dev); }
/**
* \deprecated Use: bool SdVolume::init(Sd2Card* dev, uint8_t vol);
* \param[in] dev The SD card where the volume is located.
* \param[in] part The partition to be used.
* \return true for success or false for failure.
*/
bool init(Sd2Card& dev, uint8_t part) { return init(&dev, part); }
#endif // ALLOW_DEPRECATED_FUNCTIONS
};
#endif // _SDVOLUME_H_

94
Marlin/Version.h Normal file
View File

@ -0,0 +1,94 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* This file is the standard Marlin version identifier file, all fields can be
* overriden by the ones defined on _Version.h by using the Configuration.h
* directive USE_AUTOMATIC_VERSIONING.
*/
#if ENABLED(USE_AUTOMATIC_VERSIONING)
#include "_Version.h"
#else
/**
* Marlin release version identifier
*/
#define SHORT_BUILD_VERSION "1.1.9"
/**
* 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 " (Github)"
/**
* 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 "2018-08-01"
/**
* Required minimum Configuration.h and Configuration_adv.h file versions.
*
* You must increment this version number for every significant change such as,
* but not limited to: ADD, DELETE RENAME OR REPURPOSE any directive/option on
* the configuration files.
*/
#define REQUIRED_CONFIGURATION_H_VERSION 010109
#define REQUIRED_CONFIGURATION_ADV_H_VERSION 010109
/**
* The protocol for communication to the host. Protocol indicates communication
* standards such as the use of ASCII, "echo:" and "error:" line prefixes, etc.
* (Other behaviors are given by the firmware version and capabilities report.)
*/
#define PROTOCOL_VERSION "1.0"
/**
* Defines a generic printer name to be output to the LCD after booting Marlin.
*/
#define MACHINE_NAME "3D Printer"
/**
* 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 "https://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 "http://marlinfw.org"
#endif // USE_AUTOMATIC_VERSIONING

38
Marlin/bitmap_flags.h Normal file
View File

@ -0,0 +1,38 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016, 2017 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _BITMAP_FLAGS_H_
#define _BITMAP_FLAGS_H_
#include "macros.h"
/**
* These support functions allow the use of large bit arrays of flags that take very
* little RAM. Currently they are limited to being 16x16 in size. Changing the declaration
* to unsigned long will allow us to go to 32x32 if higher resolution meshes are needed
* in the future.
*/
FORCE_INLINE void bitmap_clear(uint16_t bits[16], const uint8_t x, const uint8_t y) { CBI(bits[y], x); }
FORCE_INLINE void bitmap_set(uint16_t bits[16], const uint8_t x, const uint8_t y) { SBI(bits[y], x); }
FORCE_INLINE bool is_bitmap_set(uint16_t bits[16], const uint8_t x, const uint8_t y) { return TEST(bits[y], x); }
#endif // _BITMAP_FLAGS_H_

46
Marlin/blinkm.cpp Normal file
View File

@ -0,0 +1,46 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* blinkm.cpp - Control a BlinkM over i2c
*/
#include "MarlinConfig.h"
#if ENABLED(BLINKM)
#include "blinkm.h"
#include "leds.h"
#include <Wire.h>
void blinkm_set_led_color(const LEDColor &color) {
Wire.begin();
Wire.beginTransmission(0x09);
Wire.write('o'); //to disable ongoing script, only needs to be used once
Wire.write('n');
Wire.write(color.r);
Wire.write(color.g);
Wire.write(color.b);
Wire.endTransmission();
}
#endif // BLINKM

35
Marlin/blinkm.h Normal file
View File

@ -0,0 +1,35 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* blinkm.h - Control a BlinkM over i2c
*/
#ifndef _BLINKM_H_
#define _BLINKM_H_
struct LEDColor;
typedef LEDColor LEDColor;
void blinkm_set_led_color(const LEDColor &color);
#endif // _BLINKM_H_

161
Marlin/boards.h Normal file
View File

@ -0,0 +1,161 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef BOARDS_H
#define BOARDS_H
#define BOARD_UNKNOWN -1
//
// RAMPS 1.3 / 1.4 - ATmega1280, ATmega2560
//
#define BOARD_RAMPS_OLD 3 // MEGA/RAMPS up to 1.2
#define BOARD_RAMPS_13_EFB 33 // RAMPS 1.3 (Power outputs: Hotend, Fan, Bed)
#define BOARD_RAMPS_13_EEB 34 // RAMPS 1.3 (Power outputs: Hotend0, Hotend1, Bed)
#define BOARD_RAMPS_13_EFF 35 // RAMPS 1.3 (Power outputs: Hotend, Fan0, Fan1)
#define BOARD_RAMPS_13_EEF 36 // RAMPS 1.3 (Power outputs: Hotend0, Hotend1, Fan)
#define BOARD_RAMPS_13_SF 38 // RAMPS 1.3 (Power outputs: Spindle, Controller Fan)
#define BOARD_RAMPS_14_EFB 43 // RAMPS 1.4 (Power outputs: Hotend, Fan, Bed)
#define BOARD_RAMPS_14_EEB 44 // RAMPS 1.4 (Power outputs: Hotend0, Hotend1, Bed)
#define BOARD_RAMPS_14_EFF 45 // RAMPS 1.4 (Power outputs: Hotend, Fan0, Fan1)
#define BOARD_RAMPS_14_EEF 46 // RAMPS 1.4 (Power outputs: Hotend0, Hotend1, Fan)
#define BOARD_RAMPS_14_SF 48 // RAMPS 1.4 (Power outputs: Spindle, Controller Fan)
#define BOARD_RAMPS_PLUS_EFB 143 // RAMPS Plus 3DYMY (Power outputs: Hotend, Fan, Bed)
#define BOARD_RAMPS_PLUS_EEB 144 // RAMPS Plus 3DYMY (Power outputs: Hotend0, Hotend1, Bed)
#define BOARD_RAMPS_PLUS_EFF 145 // RAMPS Plus 3DYMY (Power outputs: Hotend, Fan0, Fan1)
#define BOARD_RAMPS_PLUS_EEF 146 // RAMPS Plus 3DYMY (Power outputs: Hotend0, Hotend1, Fan)
#define BOARD_RAMPS_PLUS_SF 148 // RAMPS Plus 3DYMY (Power outputs: Spindle, Controller Fan)
//
// RAMPS Derivatives - ATmega1280, ATmega2560
//
#define BOARD_3DRAG 77 // 3Drag Controller
#define BOARD_K8200 78 // Velleman K8200 Controller (derived from 3Drag Controller)
#define BOARD_K8400 79 // Velleman K8400 Controller (derived from 3Drag Controller)
#define BOARD_BAM_DICE 401 // 2PrintBeta BAM&DICE with STK drivers
#define BOARD_BAM_DICE_DUE 402 // 2PrintBeta BAM&DICE Due with STK drivers
#define BOARD_MKS_BASE 40 // MKS BASE v1.0
#define BOARD_MKS_BASE_15 405 // MKS v1.5 with Allegro A4982 stepper drivers
#define BOARD_MKS_BASE_HEROIC 41 // MKS BASE 1.0 with Heroic HR4982 stepper drivers
#define BOARD_MKS_GEN_13 47 // MKS GEN v1.3 or 1.4
#define BOARD_MKS_GEN_L 53 // MKS GEN L
#define BOARD_ZRIB_V20 504 // zrib V2.0 control board (Chinese knock off RAMPS replica)
#define BOARD_FELIX2 37 // Felix 2.0+ Electronics Board (RAMPS like)
#define BOARD_RIGIDBOARD 42 // Invent-A-Part RigidBoard
#define BOARD_RIGIDBOARD_V2 52 // Invent-A-Part RigidBoard V2
#define BOARD_SAINSMART_2IN1 49 // Sainsmart 2-in-1 board
#define BOARD_ULTIMAKER 7 // Ultimaker
#define BOARD_ULTIMAKER_OLD 71 // Ultimaker (Older electronics. Pre 1.5.4. This is rare)
#define BOARD_AZTEEG_X3 67 // Azteeg X3
#define BOARD_AZTEEG_X3_PRO 68 // Azteeg X3 Pro
#define BOARD_ULTIMAIN_2 72 // Ultimainboard 2.x (Uses TEMP_SENSOR 20)
#define BOARD_RUMBA 80 // Rumba
#define BOARD_BQ_ZUM_MEGA_3D 503 // bq ZUM Mega 3D
#define BOARD_MAKEBOARD_MINI 431 // MakeBoard Mini v2.1.2 is a control board sold by MicroMake
#define BOARD_TRIGORILLA_13 343 // TriGorilla Anycubic version 1.3 based on RAMPS EFB
#define BOARD_TRIGORILLA_14 443 // TriGorilla Anycubic version 1.4 based on RAMPS EFB
#define BOARD_RAMPS_ENDER_4 243 // Creality: Ender-4, CR-8
//
// Other ATmega1280, ATmega2560
//
#define BOARD_CNCONTROLS_11 111 // Cartesio CN Controls V11
#define BOARD_CNCONTROLS_12 112 // Cartesio CN Controls V12
#define BOARD_CHEAPTRONIC 2 // Cheaptronic v1.0
#define BOARD_CHEAPTRONIC_V2 21 // Cheaptronic v2.0
#define BOARD_MIGHTYBOARD_REVE 200 // Makerbot Mightyboard Revision E
#define BOARD_MEGATRONICS 70 // Megatronics
#define BOARD_MEGATRONICS_2 701 // Megatronics v2.0
#define BOARD_MEGATRONICS_3 703 // Megatronics v3.0
#define BOARD_MEGATRONICS_31 704 // Megatronics v3.1
#define BOARD_RAMBO 301 // Rambo
#define BOARD_MINIRAMBO 302 // Mini-Rambo
#define BOARD_MINIRAMBO_10A 303 // Mini-Rambo 1.0a
#define BOARD_EINSY_RAMBO 304 // Einsy Rambo
#define BOARD_EINSY_RETRO 305 // Einsy Retro
#define BOARD_ELEFU_3 21 // Elefu Ra Board (v3)
#define BOARD_LEAPFROG 999 // Leapfrog
#define BOARD_MEGACONTROLLER 310 // Mega controller
#define BOARD_SCOOVO_X9H 321 // abee Scoovo X9H
#define BOARD_GT2560_REV_A 74 // Geeetech GT2560 Rev. A
#define BOARD_GT2560_REV_A_PLUS 75 // Geeetech GT2560 Rev. A+ (with auto level probe)
//
// ATmega1281, ATmega2561
//
#define BOARD_MINITRONICS 702 // Minitronics v1.0/1.1
#define BOARD_SILVER_GATE 25 // Silvergate v1.0
//
// Sanguinololu and Derivatives - ATmega644P, ATmega1284P
//
#define BOARD_SANGUINOLOLU_11 6 // Sanguinololu < 1.2
#define BOARD_SANGUINOLOLU_12 62 // Sanguinololu 1.2 and above
#define BOARD_MELZI 63 // Melzi
#define BOARD_MELZI_MAKR3D 66 // Melzi with ATmega1284 (MaKr3d version)
#define BOARD_MELZI_CREALITY 89 // Melzi Creality3D board (for CR-10 etc)
#define BOARD_MELZI_MALYAN 92 // Melzi Malyan M150 board
#define BOARD_MELZI_TRONXY 505 // Tronxy X5S
#define BOARD_STB_11 64 // STB V1.1
#define BOARD_AZTEEG_X1 65 // Azteeg X1
#define BOARD_ANET_10 69 // Anet 1.0 (Melzi clone)
//
// Other ATmega644P, ATmega644, ATmega1284P
//
#define BOARD_GEN3_MONOLITHIC 22 // Gen3 Monolithic Electronics
#define BOARD_GEN3_PLUS 9 // Gen3+
#define BOARD_GEN6 5 // Gen6
#define BOARD_GEN6_DELUXE 51 // Gen6 deluxe
#define BOARD_GEN7_CUSTOM 10 // Gen7 custom (Alfons3 Version) "https://github.com/Alfons3/Generation_7_Electronics"
#define BOARD_GEN7_12 11 // Gen7 v1.1, v1.2
#define BOARD_GEN7_13 12 // Gen7 v1.3
#define BOARD_GEN7_14 13 // Gen7 v1.4
#define BOARD_OMCA_A 90 // Alpha OMCA board
#define BOARD_OMCA 91 // Final OMCA board
#define BOARD_SETHI 20 // Sethi 3D_1
//
// Teensyduino - AT90USB1286, AT90USB1286P
//
#define BOARD_TEENSYLU 8 // Teensylu
#define BOARD_PRINTRBOARD 81 // Printrboard (AT90USB1286)
#define BOARD_PRINTRBOARD_REVF 811 // Printrboard Revision F (AT90USB1286)
#define BOARD_BRAINWAVE 82 // Brainwave (AT90USB646)
#define BOARD_BRAINWAVE_PRO 85 // Brainwave Pro (AT90USB1286)
#define BOARD_SAV_MKI 83 // SAV Mk-I (AT90USB1286)
#define BOARD_TEENSY2 84 // Teensy++2.0 (AT90USB1286) - CLI compile: HARDWARE_MOTHERBOARD=84 make
#define BOARD_5DPRINT 88 // 5DPrint D8 Driver Board
#define MB(board) (defined(BOARD_##board) && MOTHERBOARD==BOARD_##board)
#endif // __BOARDS_H

146
Marlin/buzzer.h Normal file
View File

@ -0,0 +1,146 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef __BUZZER_H__
#define __BUZZER_H__
#include "types.h"
#include "fastio.h"
#include "circularqueue.h"
#include "temperature.h"
#include "MarlinConfig.h"
#define TONE_QUEUE_LENGTH 4
/**
* @brief Tone structure
* @details Simple abstraction of a tone based on a duration and a frequency.
*/
struct tone_t {
uint16_t duration;
uint16_t frequency;
};
/**
* @brief Buzzer class
*/
class Buzzer {
private:
struct state_t {
tone_t tone;
uint32_t endtime;
} state;
protected:
CircularQueue<tone_t, TONE_QUEUE_LENGTH> buffer;
/**
* @brief Inverts the sate of a digital PIN
* @details This will invert the current state of an digital IO pin.
*/
void invert() {
TOGGLE(BEEPER_PIN);
}
/**
* @brief Turn off a digital PIN
* @details Alias of digitalWrite(PIN, LOW) using FastIO
*/
void off() {
WRITE(BEEPER_PIN, LOW);
}
/**
* @brief Turn on a digital PIN
* @details Alias of digitalWrite(PIN, HIGH) using FastIO
*/
void on() {
WRITE(BEEPER_PIN, HIGH);
}
/**
* @brief Resets the state of the class
* @details Brings the class state to a known one.
*/
void reset() {
this->off();
this->state.endtime = 0;
}
public:
/**
* @brief Class constructor
*/
Buzzer() {
SET_OUTPUT(BEEPER_PIN);
this->reset();
}
/**
* @brief Add a tone to the queue
* @details Adds a tone_t structure to the ring buffer, will block IO if the
* queue is full waiting for one slot to get available.
*
* @param duration Duration of the tone in milliseconds
* @param frequency Frequency of the tone in hertz
*/
void tone(const uint16_t &duration, const uint16_t &frequency=0) {
while (buffer.isFull()) {
this->tick();
thermalManager.manage_heater();
}
tone_t tone = { duration, frequency };
this->buffer.enqueue(tone);
}
/**
* @brief Loop function
* @details This function should be called at loop, it will take care of
* playing the tones in the queue.
*/
virtual void tick() {
const millis_t now = millis();
if (!this->state.endtime) {
if (this->buffer.isEmpty()) return;
this->state.tone = this->buffer.dequeue();
this->state.endtime = now + this->state.tone.duration;
if (this->state.tone.frequency > 0) {
#if ENABLED(SPEAKER)
CRITICAL_SECTION_START;
::tone(BEEPER_PIN, this->state.tone.frequency, this->state.tone.duration);
CRITICAL_SECTION_END;
#else
this->on();
#endif
}
}
else if (ELAPSED(now, this->state.endtime)) this->reset();
}
};
extern Buzzer buzzer;
#endif

987
Marlin/cardreader.cpp Normal file
View File

@ -0,0 +1,987 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "MarlinConfig.h"
#if ENABLED(SDSUPPORT)
#include "cardreader.h"
#include "ultralcd.h"
#include "stepper.h"
#include "language.h"
#include "printcounter.h"
#if ENABLED(POWER_LOSS_RECOVERY)
#include "power_loss_recovery.h"
#endif
CardReader::CardReader() {
#if ENABLED(SDCARD_SORT_ALPHA)
sort_count = 0;
#if ENABLED(SDSORT_GCODE)
sort_alpha = true;
sort_folders = FOLDER_SORTING;
//sort_reverse = false;
#endif
#endif
sdprinting = cardOK = saving = logging = false;
filesize = 0;
sdpos = 0;
file_subcall_ctr = 0;
workDirDepth = 0;
ZERO(workDirParents);
// Disable autostart until card is initialized
autostart_index = -1;
//power to SD reader
#if SDPOWER > -1
OUT_WRITE(SDPOWER, HIGH);
#endif
}
char *createFilename(char *buffer, const dir_t &p) { //buffer > 12characters
char *pos = buffer;
for (uint8_t i = 0; i < 11; i++) {
if (p.name[i] == ' ') continue;
if (i == 8) *pos++ = '.';
*pos++ = p.name[i];
}
*pos++ = 0;
return buffer;
}
/**
* Dive into a folder and recurse depth-first to perform a pre-set operation lsAction:
* LS_Count - Add +1 to nrFiles for every file within the parent
* LS_GetFilename - Get the filename of the file indexed by nrFile_index
* LS_SerialPrint - Print the full path and size of each file to serial output
*/
uint16_t nrFile_index;
void CardReader::lsDive(const char *prepend, SdFile parent, const char * const match/*=NULL*/) {
dir_t p;
uint8_t cnt = 0;
// Read the next entry from a directory
while (parent.readDir(&p, longFilename) > 0) {
// If the entry is a directory and the action is LS_SerialPrint
if (DIR_IS_SUBDIR(&p) && lsAction != LS_Count && lsAction != LS_GetFilename) {
// Get the short name for the item, which we know is a folder
char dosFilename[FILENAME_LENGTH];
createFilename(dosFilename, p);
// Allocate enough stack space for the full path to a folder, trailing slash, and nul
const bool prepend_is_empty = (!prepend || prepend[0] == '\0');
const int len = (prepend_is_empty ? 1 : strlen(prepend)) + strlen(dosFilename) + 1 + 1;
char path[len];
// Append the FOLDERNAME12/ to the passed string.
// It contains the full path to the "parent" argument.
// We now have the full path to the item in this folder.
strcpy(path, prepend_is_empty ? "/" : prepend); // root slash if prepend is empty
strcat(path, dosFilename); // FILENAME_LENGTH-1 characters maximum
strcat(path, "/"); // 1 character
// Serial.print(path);
// Get a new directory object using the full path
// and dive recursively into it.
SdFile dir;
if (!dir.open(&parent, dosFilename, O_READ)) {
if (lsAction == LS_SerialPrint) {
SERIAL_ECHO_START();
SERIAL_ECHOPGM(MSG_SD_CANT_OPEN_SUBDIR);
SERIAL_ECHOLN(dosFilename);
}
}
lsDive(path, dir);
// close() is done automatically by destructor of SdFile
}
else {
uint8_t pn0 = p.name[0];
if (pn0 == DIR_NAME_FREE) break;
if (pn0 == DIR_NAME_DELETED || pn0 == '.') continue;
if (longFilename[0] == '.') continue;
if (!DIR_IS_FILE_OR_SUBDIR(&p) || (p.attributes & DIR_ATT_HIDDEN)) continue;
filenameIsDir = DIR_IS_SUBDIR(&p);
if (!filenameIsDir && (p.name[8] != 'G' || p.name[9] == '~')) continue;
switch (lsAction) { // 1 based file count
case LS_Count:
nrFiles++;
break;
case LS_SerialPrint:
createFilename(filename, p);
if (prepend) SERIAL_PROTOCOL(prepend);
SERIAL_PROTOCOL(filename);
SERIAL_PROTOCOLCHAR(' ');
SERIAL_PROTOCOLLN(p.fileSize);
break;
case LS_GetFilename:
createFilename(filename, p);
if (match != NULL) {
if (strcasecmp(match, filename) == 0) return;
}
else if (cnt == nrFile_index) return; // 0 based index
cnt++;
break;
}
}
} // while readDir
}
void CardReader::ls() {
lsAction = LS_SerialPrint;
root.rewind();
lsDive(NULL, root);
}
#if ENABLED(LONG_FILENAME_HOST_SUPPORT)
/**
* Get a long pretty path based on a DOS 8.3 path
*/
void CardReader::printLongPath(char *path) {
lsAction = LS_GetFilename;
int i, pathLen = strlen(path);
// SERIAL_ECHOPGM("Full Path: "); SERIAL_ECHOLN(path);
// Zero out slashes to make segments
for (i = 0; i < pathLen; i++) if (path[i] == '/') path[i] = '\0';
SdFile diveDir = root; // start from the root for segment 1
for (i = 0; i < pathLen;) {
if (path[i] == '\0') i++; // move past a single nul
char *segment = &path[i]; // The segment after most slashes
// If a segment is empty (extra-slash) then exit
if (!*segment) break;
// Go to the next segment
while (path[++i]) { }
// SERIAL_ECHOPGM("Looking for segment: "); SERIAL_ECHOLN(segment);
// Find the item, setting the long filename
diveDir.rewind();
lsDive(NULL, diveDir, segment);
// Print /LongNamePart to serial output
SERIAL_PROTOCOLCHAR('/');
SERIAL_PROTOCOL(longFilename[0] ? longFilename : "???");
// If the filename was printed then that's it
if (!filenameIsDir) break;
// SERIAL_ECHOPGM("Opening dir: "); SERIAL_ECHOLN(segment);
// Open the sub-item as the new dive parent
SdFile dir;
if (!dir.open(&diveDir, segment, O_READ)) {
SERIAL_EOL();
SERIAL_ECHO_START();
SERIAL_ECHOPGM(MSG_SD_CANT_OPEN_SUBDIR);
SERIAL_ECHO(segment);
break;
}
diveDir.close();
diveDir = dir;
} // while i<pathLen
SERIAL_EOL();
}
#endif // LONG_FILENAME_HOST_SUPPORT
/**
* Echo the DOS 8.3 filename (and long filename, if any)
*/
void CardReader::printFilename() {
if (file.isOpen()) {
char dosFilename[FILENAME_LENGTH];
file.getFilename(dosFilename);
SERIAL_ECHO(dosFilename);
#if ENABLED(LONG_FILENAME_HOST_SUPPORT)
getfilename(0, dosFilename);
if (longFilename[0]) {
SERIAL_ECHO(' ');
SERIAL_ECHO(longFilename);
}
#endif
}
else
SERIAL_ECHOPGM("(no file)");
SERIAL_EOL();
}
void CardReader::initsd() {
cardOK = false;
if (root.isOpen()) root.close();
#ifndef SPI_SPEED
#define SPI_SPEED SPI_FULL_SPEED
#endif
if (!sd2card.init(SPI_SPEED, SDSS)
#if defined(LCD_SDSS) && (LCD_SDSS != SDSS)
&& !sd2card.init(SPI_SPEED, LCD_SDSS)
#endif
) {
//if (!sd2card.init(SPI_HALF_SPEED,SDSS))
SERIAL_ECHO_START();
SERIAL_ECHOLNPGM(MSG_SD_INIT_FAIL);
}
else if (!volume.init(&sd2card)) {
SERIAL_ERROR_START();
SERIAL_ERRORLNPGM(MSG_SD_VOL_INIT_FAIL);
}
else if (!root.openRoot(&volume)) {
SERIAL_ERROR_START();
SERIAL_ERRORLNPGM(MSG_SD_OPENROOT_FAIL);
}
else {
cardOK = true;
SERIAL_ECHO_START();
SERIAL_ECHOLNPGM(MSG_SD_CARD_OK);
}
setroot();
}
void CardReader::release() {
sdprinting = false;
cardOK = false;
}
void CardReader::openAndPrintFile(const char *name) {
char cmd[4 + strlen(name) + 1]; // Room for "M23 ", filename, and null
sprintf_P(cmd, PSTR("M23 %s"), name);
for (char *c = &cmd[4]; *c; c++) *c = tolower(*c);
enqueue_and_echo_command_now(cmd);
enqueue_and_echo_commands_P(PSTR("M24"));
}
void CardReader::startFileprint() {
if (cardOK) {
sdprinting = true;
#if SD_RESORT
flush_presort();
#endif
}
}
void CardReader::stopSDPrint(
#if SD_RESORT
const bool re_sort/*=false*/
#endif
) {
#if ENABLED(ADVANCED_PAUSE_FEATURE)
did_pause_print = 0;
#endif
sdprinting = false;
if (isFileOpen()) file.close();
#if SD_RESORT
if (re_sort) presort();
#endif
}
void CardReader::openLogFile(char * const path) {
logging = true;
openFile(path, false);
}
void appendAtom(SdFile &file, char *& dst, uint8_t &cnt) {
file.getFilename(dst);
while (*dst && cnt < MAXPATHNAMELENGTH) { dst++; cnt++; }
if (cnt < MAXPATHNAMELENGTH) { *dst = '/'; dst++; cnt++; }
}
void CardReader::getAbsFilename(char *t) {
*t++ = '/'; // Root folder
uint8_t cnt = 1;
for (uint8_t i = 0; i < workDirDepth; i++) // Loop to current work dir
appendAtom(workDirParents[i], t, cnt);
if (cnt < MAXPATHNAMELENGTH - (FILENAME_LENGTH)) {
appendAtom(file, t, cnt);
--t;
}
*t = '\0';
}
void CardReader::openFile(char * const path, const bool read, const bool subcall/*=false*/) {
if (!cardOK) return;
uint8_t doing = 0;
if (isFileOpen()) { // Replacing current file or doing a subroutine
if (subcall) {
if (file_subcall_ctr > SD_PROCEDURE_DEPTH - 1) {
SERIAL_ERROR_START();
SERIAL_ERRORPGM("trying to call sub-gcode files with too many levels. MAX level is:");
SERIAL_ERRORLN((int)SD_PROCEDURE_DEPTH);
kill(PSTR(MSG_KILLED));
return;
}
// Store current filename (based on workDirParents) and position
getAbsFilename(proc_filenames[file_subcall_ctr]);
filespos[file_subcall_ctr] = sdpos;
SERIAL_ECHO_START();
SERIAL_ECHOPAIR("SUBROUTINE CALL target:\"", path);
SERIAL_ECHOPAIR("\" parent:\"", proc_filenames[file_subcall_ctr]);
SERIAL_ECHOLNPAIR("\" pos", sdpos);
file_subcall_ctr++;
}
else
doing = 1;
}
else if (subcall) { // Returning from a subcall?
SERIAL_ECHO_START();
SERIAL_ECHOLNPGM("END SUBROUTINE");
}
else { // Opening fresh file
doing = 2;
file_subcall_ctr = 0; // Reset procedure depth in case user cancels print while in procedure
}
if (doing) {
SERIAL_ECHO_START();
SERIAL_ECHOPGM("Now ");
serialprintPGM(doing == 1 ? PSTR("doing") : PSTR("fresh"));
SERIAL_ECHOLNPAIR(" file: ", path);
}
stopSDPrint();
SdFile *curDir;
const char * const fname = diveToFile(curDir, path, false);
if (!fname) return;
if (read) {
if (file.open(curDir, fname, O_READ)) {
filesize = file.fileSize();
sdpos = 0;
SERIAL_PROTOCOLPAIR(MSG_SD_FILE_OPENED, fname);
SERIAL_PROTOCOLLNPAIR(MSG_SD_SIZE, filesize);
SERIAL_PROTOCOLLNPGM(MSG_SD_FILE_SELECTED);
getfilename(0, fname);
lcd_setstatus(longFilename[0] ? longFilename : fname);
//if (longFilename[0]) {
// SERIAL_PROTOCOLPAIR(MSG_SD_FILE_LONG_NAME, longFilename);
//}
}
else {
SERIAL_PROTOCOLPAIR(MSG_SD_OPEN_FILE_FAIL, fname);
SERIAL_PROTOCOLCHAR('.');
SERIAL_EOL();
}
}
else { //write
if (!file.open(curDir, fname, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)) {
SERIAL_PROTOCOLPAIR(MSG_SD_OPEN_FILE_FAIL, fname);
SERIAL_PROTOCOLCHAR('.');
SERIAL_EOL();
}
else {
saving = true;
SERIAL_PROTOCOLLNPAIR(MSG_SD_WRITE_TO_FILE, path);
lcd_setstatus(fname);
}
}
}
void CardReader::removeFile(const char * const name) {
if (!cardOK) return;
stopSDPrint();
SdFile *curDir;
const char * const fname = diveToFile(curDir, name, false);
if (!fname) return;
if (file.remove(curDir, fname)) {
SERIAL_PROTOCOLPGM("File deleted:");
SERIAL_PROTOCOLLN(fname);
sdpos = 0;
#if ENABLED(SDCARD_SORT_ALPHA)
presort();
#endif
}
else {
SERIAL_PROTOCOLPGM("Deletion failed, File: ");
SERIAL_PROTOCOL(fname);
SERIAL_PROTOCOLCHAR('.');
}
}
void CardReader::getStatus() {
if (cardOK && sdprinting) {
SERIAL_PROTOCOLPGM(MSG_SD_PRINTING_BYTE);
SERIAL_PROTOCOL(sdpos);
SERIAL_PROTOCOLCHAR('/');
SERIAL_PROTOCOLLN(filesize);
}
else
SERIAL_PROTOCOLLNPGM(MSG_SD_NOT_PRINTING);
}
void CardReader::write_command(char *buf) {
char* begin = buf;
char* npos = NULL;
char* end = buf + strlen(buf) - 1;
file.writeError = false;
if ((npos = strchr(buf, 'N')) != NULL) {
begin = strchr(npos, ' ') + 1;
end = strchr(npos, '*') - 1;
}
end[1] = '\r';
end[2] = '\n';
end[3] = '\0';
file.write(begin);
if (file.writeError) {
SERIAL_ERROR_START();
SERIAL_ERRORLNPGM(MSG_SD_ERR_WRITE_TO_FILE);
}
}
//
// Run the next autostart file. Called:
// - On boot after successful card init
// - After finishing the previous autostart file
// - From the LCD command to run the autostart file
//
void CardReader::checkautostart() {
if (autostart_index < 0 || sdprinting) return;
if (!cardOK) initsd();
if (cardOK
#if ENABLED(POWER_LOSS_RECOVERY)
&& !jobRecoverFileExists() // Don't run auto#.g when a resume file exists
#endif
) {
char autoname[10];
sprintf_P(autoname, PSTR("auto%i.g"), int(autostart_index));
dir_t p;
root.rewind();
while (root.readDir(&p, NULL) > 0) {
for (int8_t i = (int8_t)strlen((char*)p.name); i--;) p.name[i] = tolower(p.name[i]);
if (p.name[9] != '~' && strncmp((char*)p.name, autoname, 5) == 0) {
openAndPrintFile(autoname);
autostart_index++;
return;
}
}
}
autostart_index = -1;
}
void CardReader::beginautostart() {
autostart_index = 0;
setroot();
}
void CardReader::closefile(const bool store_location) {
file.sync();
file.close();
saving = logging = false;
if (store_location) {
//future: store printer state, filename and position for continuing a stopped print
// so one can unplug the printer and continue printing the next day.
}
}
/**
* Get the name of a file in the current directory by index
* with optional name to match.
*/
void CardReader::getfilename(uint16_t nr, const char * const match/*=NULL*/) {
#if ENABLED(SDSORT_CACHE_NAMES)
if (match != NULL) {
while (nr < sort_count) {
if (strcasecmp(match, sortshort[nr]) == 0) break;
nr++;
}
}
if (nr < sort_count) {
strcpy(filename, sortshort[nr]);
strcpy(longFilename, sortnames[nr]);
filenameIsDir = TEST(isDir[nr>>3], nr & 0x07);
return;
}
#endif // SDSORT_CACHE_NAMES
lsAction = LS_GetFilename;
nrFile_index = nr;
workDir.rewind();
lsDive(NULL, workDir, match);
}
uint16_t CardReader::getnrfilenames() {
lsAction = LS_Count;
nrFiles = 0;
workDir.rewind();
lsDive(NULL, workDir);
//SERIAL_ECHOLN(nrFiles);
return nrFiles;
}
/**
* Dive to the given file path, with optional echo.
* On exit set curDir and return the name part of the path.
* A NULL result indicates an unrecoverable error.
*/
const char* CardReader::diveToFile(SdFile*& curDir, const char * const path, const bool echo) {
SdFile myDir;
if (path[0] != '/') { curDir = &workDir; return path; }
curDir = &root;
const char *dirname_start = &path[1];
while (dirname_start) {
char * const dirname_end = strchr(dirname_start, '/');
if (dirname_end <= dirname_start) break;
const uint8_t len = dirname_end - dirname_start;
char dosSubdirname[len + 1];
strncpy(dosSubdirname, dirname_start, len);
dosSubdirname[len] = 0;
if (echo) SERIAL_ECHOLN(dosSubdirname);
if (!myDir.open(curDir, dosSubdirname, O_READ)) {
SERIAL_PROTOCOLPAIR(MSG_SD_OPEN_FILE_FAIL, dosSubdirname);
SERIAL_PROTOCOLCHAR('.');
SERIAL_EOL();
return NULL;
}
curDir = &myDir;
dirname_start = dirname_end + 1;
}
return dirname_start;
}
void CardReader::chdir(const char * relpath) {
SdFile newDir;
SdFile *parent = workDir.isOpen() ? &workDir : &root;
if (newDir.open(parent, relpath, O_READ)) {
workDir = newDir;
if (workDirDepth < MAX_DIR_DEPTH)
workDirParents[workDirDepth++] = workDir;
#if ENABLED(SDCARD_SORT_ALPHA)
presort();
#endif
}
else {
SERIAL_ECHO_START();
SERIAL_ECHOPGM(MSG_SD_CANT_ENTER_SUBDIR);
SERIAL_ECHOLN(relpath);
}
}
int8_t CardReader::updir() {
if (workDirDepth > 0) { // At least 1 dir has been saved
workDir = --workDirDepth ? workDirParents[workDirDepth - 1] : root; // Use parent, or root if none
#if ENABLED(SDCARD_SORT_ALPHA)
presort();
#endif
}
return workDirDepth;
}
void CardReader::setroot() {
/*if (!workDir.openRoot(&volume)) {
SERIAL_ECHOLNPGM(MSG_SD_WORKDIR_FAIL);
}*/
workDir = root;
#if ENABLED(SDCARD_SORT_ALPHA)
presort();
#endif
}
#if ENABLED(SDCARD_SORT_ALPHA)
/**
* Get the name of a file in the current directory by sort-index
*/
void CardReader::getfilename_sorted(const uint16_t nr) {
getfilename(
#if ENABLED(SDSORT_GCODE)
sort_alpha &&
#endif
(nr < sort_count) ? sort_order[nr] : nr
);
}
/**
* Read all the files and produce a sort key
*
* We can do this in 3 ways...
* - Minimal RAM: Read two filenames at a time sorting along...
* - Some RAM: Buffer the directory just for this sort
* - Most RAM: Buffer the directory and return filenames from RAM
*/
void CardReader::presort() {
// Throw away old sort index
flush_presort();
// Sorting may be turned off
#if ENABLED(SDSORT_GCODE)
if (!sort_alpha) return;
#endif
// If there are files, sort up to the limit
uint16_t fileCnt = getnrfilenames();
if (fileCnt > 0) {
// Never sort more than the max allowed
// If you use folders to organize, 20 may be enough
if (fileCnt > SDSORT_LIMIT) fileCnt = SDSORT_LIMIT;
// Sort order is always needed. May be static or dynamic.
#if ENABLED(SDSORT_DYNAMIC_RAM)
sort_order = new uint8_t[fileCnt];
#endif
// Use RAM to store the entire directory during pre-sort.
// SDSORT_LIMIT should be set to prevent over-allocation.
#if ENABLED(SDSORT_USES_RAM)
// If using dynamic ram for names, allocate on the heap.
#if ENABLED(SDSORT_CACHE_NAMES)
#if ENABLED(SDSORT_DYNAMIC_RAM)
sortshort = new char*[fileCnt];
sortnames = new char*[fileCnt];
#endif
#elif ENABLED(SDSORT_USES_STACK)
char sortnames[fileCnt][SORTED_LONGNAME_MAXLEN];
#endif
// Folder sorting needs 1 bit per entry for flags.
#if HAS_FOLDER_SORTING
#if ENABLED(SDSORT_DYNAMIC_RAM)
isDir = new uint8_t[(fileCnt + 7) >> 3];
#elif ENABLED(SDSORT_USES_STACK)
uint8_t isDir[(fileCnt + 7) >> 3];
#endif
#endif
#else // !SDSORT_USES_RAM
// By default re-read the names from SD for every compare
// retaining only two filenames at a time. This is very
// slow but is safest and uses minimal RAM.
char name1[LONG_FILENAME_LENGTH + 1];
#endif
if (fileCnt > 1) {
// Init sort order.
for (uint16_t i = 0; i < fileCnt; i++) {
sort_order[i] = i;
// If using RAM then read all filenames now.
#if ENABLED(SDSORT_USES_RAM)
getfilename(i);
#if ENABLED(SDSORT_DYNAMIC_RAM)
// Use dynamic method to copy long filename
sortnames[i] = strdup(longest_filename());
#if ENABLED(SDSORT_CACHE_NAMES)
// When caching also store the short name, since
// we're replacing the getfilename() behavior.
sortshort[i] = strdup(filename);
#endif
#else
// Copy filenames into the static array
#if SORTED_LONGNAME_MAXLEN != LONG_FILENAME_LENGTH
strncpy(sortnames[i], longest_filename(), SORTED_LONGNAME_MAXLEN);
sortnames[i][SORTED_LONGNAME_MAXLEN - 1] = '\0';
#else
strncpy(sortnames[i], longest_filename(), SORTED_LONGNAME_MAXLEN);
#endif
#if ENABLED(SDSORT_CACHE_NAMES)
strcpy(sortshort[i], filename);
#endif
#endif
// char out[30];
// sprintf_P(out, PSTR("---- %i %s %s"), i, filenameIsDir ? "D" : " ", sortnames[i]);
// SERIAL_ECHOLN(out);
#if HAS_FOLDER_SORTING
const uint16_t bit = i & 0x07, ind = i >> 3;
if (bit == 0) isDir[ind] = 0x00;
if (filenameIsDir) isDir[ind] |= _BV(bit);
#endif
#endif
}
// Bubble Sort
for (uint16_t i = fileCnt; --i;) {
bool didSwap = false;
for (uint16_t j = 0; j < i; ++j) {
const uint16_t o1 = sort_order[j], o2 = sort_order[j + 1];
// Compare names from the array or just the two buffered names
#if ENABLED(SDSORT_USES_RAM)
#define _SORT_CMP_NODIR() (strcasecmp(sortnames[o1], sortnames[o2]) > 0)
#else
#define _SORT_CMP_NODIR() (strcasecmp(name1, name2) > 0)
#endif
#if HAS_FOLDER_SORTING
#if ENABLED(SDSORT_USES_RAM)
// Folder sorting needs an index and bit to test for folder-ness.
const uint8_t ind1 = o1 >> 3, bit1 = o1 & 0x07,
ind2 = o2 >> 3, bit2 = o2 & 0x07;
#define _SORT_CMP_DIR(fs) \
(((isDir[ind1] & _BV(bit1)) != 0) == ((isDir[ind2] & _BV(bit2)) != 0) \
? _SORT_CMP_NODIR() \
: (isDir[fs > 0 ? ind1 : ind2] & (fs > 0 ? _BV(bit1) : _BV(bit2))) != 0)
#else
#define _SORT_CMP_DIR(fs) ((dir1 == filenameIsDir) ? _SORT_CMP_NODIR() : (fs > 0 ? dir1 : !dir1))
#endif
#endif
// The most economical method reads names as-needed
// throughout the loop. Slow if there are many.
#if DISABLED(SDSORT_USES_RAM)
getfilename(o1);
strcpy(name1, longest_filename()); // save (or getfilename below will trounce it)
#if HAS_FOLDER_SORTING
bool dir1 = filenameIsDir;
#endif
getfilename(o2);
char *name2 = longest_filename(); // use the string in-place
#endif // !SDSORT_USES_RAM
// Sort the current pair according to settings.
if (
#if HAS_FOLDER_SORTING
#if ENABLED(SDSORT_GCODE)
sort_folders ? _SORT_CMP_DIR(sort_folders) : _SORT_CMP_NODIR()
#else
_SORT_CMP_DIR(FOLDER_SORTING)
#endif
#else
_SORT_CMP_NODIR()
#endif
) {
sort_order[j] = o2;
sort_order[j + 1] = o1;
didSwap = true;
}
}
if (!didSwap) break;
}
// Using RAM but not keeping names around
#if ENABLED(SDSORT_USES_RAM) && DISABLED(SDSORT_CACHE_NAMES)
#if ENABLED(SDSORT_DYNAMIC_RAM)
for (uint16_t i = 0; i < fileCnt; ++i) free(sortnames[i]);
#if HAS_FOLDER_SORTING
free(isDir);
#endif
#endif
#endif
}
else {
sort_order[0] = 0;
#if ENABLED(SDSORT_USES_RAM) && ENABLED(SDSORT_CACHE_NAMES)
getfilename(0);
#if ENABLED(SDSORT_DYNAMIC_RAM)
sortnames = new char*[1];
sortnames[0] = strdup(longest_filename()); // malloc
#if ENABLED(SDSORT_CACHE_NAMES)
sortshort = new char*[1];
sortshort[0] = strdup(filename); // malloc
#endif
isDir = new uint8_t[1];
#else
#if SORTED_LONGNAME_MAXLEN != LONG_FILENAME_LENGTH
strncpy(sortnames[0], longest_filename(), SORTED_LONGNAME_MAXLEN);
sortnames[0][SORTED_LONGNAME_MAXLEN - 1] = '\0';
#else
strncpy(sortnames[0], longest_filename(), SORTED_LONGNAME_MAXLEN);
#endif
#if ENABLED(SDSORT_CACHE_NAMES)
strcpy(sortshort[0], filename);
#endif
#endif
isDir[0] = filenameIsDir ? 0x01 : 0x00;
#endif
}
sort_count = fileCnt;
}
}
void CardReader::flush_presort() {
if (sort_count > 0) {
#if ENABLED(SDSORT_DYNAMIC_RAM)
delete sort_order;
#if ENABLED(SDSORT_CACHE_NAMES)
for (uint8_t i = 0; i < sort_count; ++i) {
free(sortshort[i]); // strdup
free(sortnames[i]); // strdup
}
delete sortshort;
delete sortnames;
#endif
#endif
sort_count = 0;
}
}
#endif // SDCARD_SORT_ALPHA
uint16_t CardReader::get_num_Files() {
return
#if ENABLED(SDCARD_SORT_ALPHA) && SDSORT_USES_RAM && SDSORT_CACHE_NAMES
nrFiles // no need to access the SD card for filenames
#else
getnrfilenames()
#endif
;
}
void CardReader::printingHasFinished() {
planner.synchronize();
file.close();
if (file_subcall_ctr > 0) { // Heading up to a parent file that called current as a procedure.
file_subcall_ctr--;
openFile(proc_filenames[file_subcall_ctr], true, true);
setIndex(filespos[file_subcall_ctr]);
startFileprint();
}
else {
sdprinting = false;
#if ENABLED(POWER_LOSS_RECOVERY)
removeJobRecoveryFile();
#endif
#if ENABLED(SD_FINISHED_STEPPERRELEASE) && defined(SD_FINISHED_RELEASECOMMAND)
planner.finish_and_disable();
#endif
print_job_timer.stop();
if (print_job_timer.duration() > 60)
enqueue_and_echo_commands_P(PSTR("M31"));
#if ENABLED(SDCARD_SORT_ALPHA)
presort();
#endif
#if ENABLED(ULTRA_LCD) && ENABLED(LCD_SET_PROGRESS_MANUALLY)
progress_bar_percent = 0;
#endif
#if ENABLED(SD_REPRINT_LAST_SELECTED_FILE)
lcd_reselect_last_file();
#endif
}
}
#if ENABLED(AUTO_REPORT_SD_STATUS)
uint8_t CardReader::auto_report_sd_interval = 0;
millis_t CardReader::next_sd_report_ms;
void CardReader::auto_report_sd_status() {
millis_t current_ms = millis();
if (auto_report_sd_interval && ELAPSED(current_ms, next_sd_report_ms)) {
next_sd_report_ms = current_ms + 1000UL * auto_report_sd_interval;
getStatus();
}
}
#endif // AUTO_REPORT_SD_STATUS
#if ENABLED(POWER_LOSS_RECOVERY)
char job_recovery_file_name[4] = "bin";
void CardReader::openJobRecoveryFile(const bool read) {
if (!cardOK) return;
if (jobRecoveryFile.isOpen()) return;
if (!jobRecoveryFile.open(&root, job_recovery_file_name, read ? O_READ : O_CREAT | O_WRITE | O_TRUNC | O_SYNC)) {
SERIAL_PROTOCOLPAIR(MSG_SD_OPEN_FILE_FAIL, job_recovery_file_name);
SERIAL_PROTOCOLCHAR('.');
SERIAL_EOL();
}
else if (!read)
SERIAL_PROTOCOLLNPAIR(MSG_SD_WRITE_TO_FILE, job_recovery_file_name);
}
void CardReader::closeJobRecoveryFile() { jobRecoveryFile.close(); }
bool CardReader::jobRecoverFileExists() {
const bool exists = jobRecoveryFile.open(&root, job_recovery_file_name, O_READ);
if (exists) jobRecoveryFile.close();
return exists;
}
int16_t CardReader::saveJobRecoveryInfo() {
jobRecoveryFile.seekSet(0);
const int16_t ret = jobRecoveryFile.write(&job_recovery_info, sizeof(job_recovery_info));
#if ENABLED(DEBUG_POWER_LOSS_RECOVERY)
if (ret == -1) SERIAL_PROTOCOLLNPGM("Power-loss file write failed.");
#endif
return ret;
}
int16_t CardReader::loadJobRecoveryInfo() {
return jobRecoveryFile.read(&job_recovery_info, sizeof(job_recovery_info));
}
void CardReader::removeJobRecoveryFile() {
job_recovery_info.valid_head = job_recovery_info.valid_foot = job_recovery_commands_count = 0;
if (jobRecoverFileExists()) {
closefile();
removeFile(job_recovery_file_name);
#if ENABLED(DEBUG_POWER_LOSS_RECOVERY)
SERIAL_PROTOCOLPGM("Power-loss file delete");
serialprintPGM(jobRecoverFileExists() ? PSTR(" failed.\n") : PSTR("d.\n"));
#endif
}
}
#endif // POWER_LOSS_RECOVERY
#endif // SDSUPPORT

230
Marlin/cardreader.h Normal file
View File

@ -0,0 +1,230 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _CARDREADER_H_
#define _CARDREADER_H_
#include "MarlinConfig.h"
#if ENABLED(SDSUPPORT)
#define SD_RESORT ENABLED(SDCARD_SORT_ALPHA) && ENABLED(SDSORT_DYNAMIC_RAM)
#define MAX_DIR_DEPTH 10 // Maximum folder depth
#include "SdFile.h"
class CardReader {
public:
CardReader();
void initsd();
void write_command(char *buf);
void beginautostart();
void checkautostart();
void openFile(char * const path, const bool read, const bool subcall=false);
void openLogFile(char * const path);
void removeFile(const char * const name);
void closefile(const bool store_location=false);
void release();
void openAndPrintFile(const char *name);
void startFileprint();
void stopSDPrint(
#if SD_RESORT
const bool re_sort=false
#endif
);
void getStatus();
void printingHasFinished();
void printFilename();
#if ENABLED(LONG_FILENAME_HOST_SUPPORT)
void printLongPath(char *path);
#endif
void getfilename(uint16_t nr, const char* const match=NULL);
uint16_t getnrfilenames();
void getAbsFilename(char *t);
void ls();
void chdir(const char *relpath);
int8_t updir();
void setroot();
const char* diveToFile(SdFile*& curDir, const char * const path, const bool echo);
uint16_t get_num_Files();
#if ENABLED(SDCARD_SORT_ALPHA)
void presort();
void getfilename_sorted(const uint16_t nr);
#if ENABLED(SDSORT_GCODE)
FORCE_INLINE void setSortOn(bool b) { sort_alpha = b; presort(); }
FORCE_INLINE void setSortFolders(int i) { sort_folders = i; presort(); }
//FORCE_INLINE void setSortReverse(bool b) { sort_reverse = b; }
#endif
#endif
#if ENABLED(POWER_LOSS_RECOVERY)
void openJobRecoveryFile(const bool read);
void closeJobRecoveryFile();
bool jobRecoverFileExists();
int16_t saveJobRecoveryInfo();
int16_t loadJobRecoveryInfo();
void removeJobRecoveryFile();
#endif
FORCE_INLINE void pauseSDPrint() { sdprinting = false; }
FORCE_INLINE bool isFileOpen() { return file.isOpen(); }
FORCE_INLINE bool eof() { return sdpos >= filesize; }
FORCE_INLINE int16_t get() { sdpos = file.curPosition(); return (int16_t)file.read(); }
FORCE_INLINE void setIndex(const uint32_t index) { sdpos = index; file.seekSet(index); }
FORCE_INLINE uint32_t getIndex() { return sdpos; }
FORCE_INLINE uint8_t percentDone() { return (isFileOpen() && filesize) ? sdpos / ((filesize + 99) / 100) : 0; }
FORCE_INLINE char* getWorkDirName() { workDir.getFilename(filename); return filename; }
#if ENABLED(AUTO_REPORT_SD_STATUS)
void auto_report_sd_status(void);
FORCE_INLINE void set_auto_report_interval(uint8_t v) {
NOMORE(v, 60);
auto_report_sd_interval = v;
next_sd_report_ms = millis() + 1000UL * v;
}
#endif
FORCE_INLINE char* longest_filename() { return longFilename[0] ? longFilename : filename; }
public:
bool saving, logging, sdprinting, cardOK, filenameIsDir;
char filename[FILENAME_LENGTH], longFilename[LONG_FILENAME_LENGTH];
int8_t autostart_index;
private:
SdFile root, workDir, workDirParents[MAX_DIR_DEPTH];
uint8_t workDirDepth;
// Sort files and folders alphabetically.
#if ENABLED(SDCARD_SORT_ALPHA)
uint16_t sort_count; // Count of sorted items in the current directory
#if ENABLED(SDSORT_GCODE)
bool sort_alpha; // Flag to enable / disable the feature
int sort_folders; // Flag to enable / disable folder sorting
//bool sort_reverse; // Flag to enable / disable reverse sorting
#endif
// By default the sort index is static
#if ENABLED(SDSORT_DYNAMIC_RAM)
uint8_t *sort_order;
#else
uint8_t sort_order[SDSORT_LIMIT];
#endif
#if ENABLED(SDSORT_USES_RAM) && ENABLED(SDSORT_CACHE_NAMES) && DISABLED(SDSORT_DYNAMIC_RAM)
#define SORTED_LONGNAME_MAXLEN ((SDSORT_CACHE_VFATS) * (FILENAME_LENGTH) + 1)
#else
#define SORTED_LONGNAME_MAXLEN LONG_FILENAME_LENGTH
#endif
// Cache filenames to speed up SD menus.
#if ENABLED(SDSORT_USES_RAM)
// If using dynamic ram for names, allocate on the heap.
#if ENABLED(SDSORT_CACHE_NAMES)
#if ENABLED(SDSORT_DYNAMIC_RAM)
char **sortshort, **sortnames;
#else
char sortshort[SDSORT_LIMIT][FILENAME_LENGTH];
char sortnames[SDSORT_LIMIT][SORTED_LONGNAME_MAXLEN];
#endif
#elif DISABLED(SDSORT_USES_STACK)
char sortnames[SDSORT_LIMIT][SORTED_LONGNAME_MAXLEN];
#endif
// Folder sorting uses an isDir array when caching items.
#if HAS_FOLDER_SORTING
#if ENABLED(SDSORT_DYNAMIC_RAM)
uint8_t *isDir;
#elif ENABLED(SDSORT_CACHE_NAMES) || DISABLED(SDSORT_USES_STACK)
uint8_t isDir[(SDSORT_LIMIT+7)>>3];
#endif
#endif
#endif // SDSORT_USES_RAM
#endif // SDCARD_SORT_ALPHA
Sd2Card sd2card;
SdVolume volume;
SdFile file;
#if ENABLED(POWER_LOSS_RECOVERY)
SdFile jobRecoveryFile;
#endif
#define SD_PROCEDURE_DEPTH 1
#define MAXPATHNAMELENGTH (FILENAME_LENGTH*MAX_DIR_DEPTH + MAX_DIR_DEPTH + 1)
uint8_t file_subcall_ctr;
uint32_t filespos[SD_PROCEDURE_DEPTH];
char proc_filenames[SD_PROCEDURE_DEPTH][MAXPATHNAMELENGTH];
uint32_t filesize, sdpos;
LsAction lsAction; //stored for recursion.
uint16_t nrFiles; //counter for the files in the current directory and recycled as position counter for getting the nrFiles'th name in the directory.
char* diveDirName;
void lsDive(const char *prepend, SdFile parent, const char * const match=NULL);
#if ENABLED(SDCARD_SORT_ALPHA)
void flush_presort();
#endif
#if ENABLED(AUTO_REPORT_SD_STATUS)
static uint8_t auto_report_sd_interval;
static millis_t next_sd_report_ms;
#endif
};
#if PIN_EXISTS(SD_DETECT)
#if ENABLED(SD_DETECT_INVERTED)
#define IS_SD_INSERTED (READ(SD_DETECT_PIN) == HIGH)
#else
#define IS_SD_INSERTED (READ(SD_DETECT_PIN) == LOW)
#endif
#else
// No card detect line? Assume the card is inserted.
#define IS_SD_INSERTED true
#endif
extern CardReader card;
#endif // SDSUPPORT
#if ENABLED(SDSUPPORT)
#define IS_SD_PRINTING (card.sdprinting)
#define IS_SD_FILE_OPEN (card.isFileOpen())
#else
#define IS_SD_PRINTING (false)
#define IS_SD_FILE_OPEN (false)
#endif
#endif // _CARDREADER_H_

145
Marlin/circularqueue.h Normal file
View File

@ -0,0 +1,145 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef __CIRCULARQUEUE_H__
#define __CIRCULARQUEUE_H__
#include <Arduino.h>
/**
* @brief Circular Queue class
* @details Implementation of the classic ring buffer data structure
*/
template<typename T, uint8_t N>
class CircularQueue {
private:
/**
* @brief Buffer structure
* @details This structure consolidates all the overhead required to handle
* a circular queue such as the pointers and the buffer vector.
*/
struct buffer_t {
uint8_t head;
uint8_t tail;
uint8_t count;
uint8_t size;
T queue[N];
} buffer;
public:
/**
* @brief Class constructor
* @details This class requires two template parameters, T defines the type
* of item this queue will handle and N defines the maximum number of
* items that can be stored on the queue.
*/
CircularQueue<T, N>() {
this->buffer.size = N;
this->buffer.count = this->buffer.head = this->buffer.tail = 0;
}
/**
* @brief Removes and returns a item from the queue
* @details Removes the oldest item on the queue, pointed to by the
* buffer_t head field. The item is returned to the caller.
* @return type T item
*/
T dequeue() {
if (this->isEmpty()) return T();
uint8_t index = this->buffer.head;
--this->buffer.count;
if (++this->buffer.head == this->buffer.size)
this->buffer.head = 0;
return this->buffer.queue[index];
}
/**
* @brief Adds an item to the queue
* @details Adds an item to the queue on the location pointed by the buffer_t
* tail variable. Returns false if no queue space is available.
* @param item Item to be added to the queue
* @return true if the operation was successful
*/
bool enqueue(T const &item) {
if (this->isFull()) return false;
this->buffer.queue[this->buffer.tail] = item;
++this->buffer.count;
if (++this->buffer.tail == this->buffer.size)
this->buffer.tail = 0;
return true;
}
/**
* @brief Checks if the queue has no items
* @details Returns true if there are no items on the queue, false otherwise.
* @return true if queue is empty
*/
bool isEmpty() {
return this->buffer.count == 0;
}
/**
* @brief Checks if the queue is full
* @details Returns true if the queue is full, false otherwise.
* @return true if queue is full
*/
bool isFull() {
return this->buffer.count == this->buffer.size;
}
/**
* @brief Gets the queue size
* @details Returns the maximum number of items a queue can have.
* @return the queue size
*/
uint8_t size() {
return this->buffer.size;
}
/**
* @brief Gets the next item from the queue without removing it
* @details Returns the next item in the queue without removing it
* or updating the pointers.
* @return first item in the queue
*/
T peek() {
return this->buffer.queue[this->buffer.head];
}
/**
* @brief Gets the number of items on the queue
* @details Returns the current number of items stored on the queue.
* @return number of items in the queue
*/
uint8_t count() {
return this->buffer.count;
}
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,101 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef CONFIGURATION_STORE_H
#define CONFIGURATION_STORE_H
#include "MarlinConfig.h"
class MarlinSettings {
public:
MarlinSettings() { }
static uint16_t datasize();
static void reset();
static bool save(); // Return 'true' if data was saved
FORCE_INLINE static bool init_eeprom() {
reset();
#if ENABLED(EEPROM_SETTINGS)
const bool success = save();
#if ENABLED(EEPROM_CHITCHAT)
if (success) report();
#endif
return success;
#else
return true;
#endif
}
#if ENABLED(EEPROM_SETTINGS)
static bool load(); // Return 'true' if data was loaded ok
static bool validate(); // Return 'true' if EEPROM data is ok
#if ENABLED(AUTO_BED_LEVELING_UBL) // Eventually make these available if any leveling system
// That can store is enabled
static uint16_t meshes_start_index();
FORCE_INLINE static uint16_t meshes_end_index() { return meshes_end; }
static uint16_t calc_num_meshes();
static int mesh_slot_offset(const int8_t slot);
static void store_mesh(const int8_t slot);
static void load_mesh(const int8_t slot, void * const into=NULL);
//static void delete_mesh(); // necessary if we have a MAT
//static void defrag_meshes(); // "
#endif
#else
FORCE_INLINE
static bool load() { reset(); report(); return true; }
#endif
#if DISABLED(DISABLE_M503)
static void report(const bool forReplay=false);
#else
FORCE_INLINE
static void report(const bool forReplay=false) { UNUSED(forReplay); }
#endif
private:
static void postprocess();
#if ENABLED(EEPROM_SETTINGS)
static bool eeprom_error, validating;
#if ENABLED(AUTO_BED_LEVELING_UBL) // Eventually make these available if any leveling system
// That can store is enabled
static constexpr uint16_t meshes_end = E2END - 128; // 128 is a placeholder for the size of the MAT; the MAT will always
// live at the very end of the eeprom
#endif
static bool _load();
static void write_data(int &pos, const uint8_t *value, uint16_t size, uint16_t *crc);
static void read_data(int &pos, uint8_t *value, uint16_t size, uint16_t *crc, const bool force=false);
static bool size_error(const uint16_t size);
#endif
};
extern MarlinSettings settings;
#endif // CONFIGURATION_STORE_H

153
Marlin/dac_mcp4728.cpp Normal file
View File

@ -0,0 +1,153 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* mcp4728.cpp - Arduino library for MicroChip MCP4728 I2C D/A converter
*
* For implementation details, please take a look at the datasheet:
* http://ww1.microchip.com/downloads/en/DeviceDoc/22187a.pdf
*
* For discussion and feedback, please go to:
* http://arduino.cc/forum/index.php/topic,51842.0.html
*/
#include "MarlinConfig.h"
#if ENABLED(DAC_STEPPER_CURRENT)
#include "dac_mcp4728.h"
#include "enum.h"
uint16_t mcp4728_values[XYZE];
/**
* Begin I2C, get current values (input register and eeprom) of mcp4728
*/
void mcp4728_init() {
Wire.begin();
Wire.requestFrom(int(DAC_DEV_ADDRESS), 24);
while (Wire.available()) {
char deviceID = Wire.read(),
hiByte = Wire.read(),
loByte = Wire.read();
if (!(deviceID & 0x08))
mcp4728_values[(deviceID & 0x30) >> 4] = word((hiByte & 0x0F), loByte);
}
}
/**
* Write input resister value to specified channel using fastwrite method.
* Channel : 0-3, Values : 0-4095
*/
uint8_t mcp4728_analogWrite(uint8_t channel, uint16_t value) {
mcp4728_values[channel] = value;
return mcp4728_fastWrite();
}
/**
* Write all input resistor values to EEPROM using SequencialWrite method.
* This will update both input register and EEPROM value
* This will also write current Vref, PowerDown, Gain settings to EEPROM
*/
uint8_t mcp4728_eepromWrite() {
Wire.beginTransmission(DAC_DEV_ADDRESS);
Wire.write(SEQWRITE);
LOOP_XYZE(i) {
Wire.write(DAC_STEPPER_VREF << 7 | DAC_STEPPER_GAIN << 4 | highByte(mcp4728_values[i]));
Wire.write(lowByte(mcp4728_values[i]));
}
return Wire.endTransmission();
}
/**
* Write Voltage reference setting to all input regiters
*/
uint8_t mcp4728_setVref_all(uint8_t value) {
Wire.beginTransmission(DAC_DEV_ADDRESS);
Wire.write(VREFWRITE | (value ? 0x0F : 0x00));
return Wire.endTransmission();
}
/**
* Write Gain setting to all input regiters
*/
uint8_t mcp4728_setGain_all(uint8_t value) {
Wire.beginTransmission(DAC_DEV_ADDRESS);
Wire.write(GAINWRITE | (value ? 0x0F : 0x00));
return Wire.endTransmission();
}
/**
* Return Input Register value
*/
uint16_t mcp4728_getValue(uint8_t channel) { return mcp4728_values[channel]; }
/**
* Steph: Might be useful in the future
* Return Vout
*
uint16_t mcp4728_getVout(uint8_t channel) {
uint32_t vref = 2048,
vOut = (vref * mcp4728_values[channel] * (_DAC_STEPPER_GAIN + 1)) / 4096;
if (vOut > defaultVDD) vOut = defaultVDD;
return vOut;
}
*/
/**
* Returns DAC values as a 0-100 percentage of drive strength
*/
uint8_t mcp4728_getDrvPct(uint8_t channel) { return uint8_t(100.0 * mcp4728_values[channel] / (DAC_STEPPER_MAX) + 0.5); }
/**
* Receives all Drive strengths as 0-100 percent values, updates
* DAC Values array and calls fastwrite to update the DAC.
*/
void mcp4728_setDrvPct(uint8_t pct[XYZE]) {
LOOP_XYZE(i) mcp4728_values[i] = 0.01 * pct[i] * (DAC_STEPPER_MAX);
mcp4728_fastWrite();
}
/**
* FastWrite input register values - All DAC ouput update. refer to DATASHEET 5.6.1
* DAC Input and PowerDown bits update.
* No EEPROM update
*/
uint8_t mcp4728_fastWrite() {
Wire.beginTransmission(DAC_DEV_ADDRESS);
LOOP_XYZE(i) {
Wire.write(highByte(mcp4728_values[i]));
Wire.write(lowByte(mcp4728_values[i]));
}
return Wire.endTransmission();
}
/**
* Common function for simple general commands
*/
uint8_t mcp4728_simpleCommand(byte simpleCommand) {
Wire.beginTransmission(GENERALCALL);
Wire.write(simpleCommand);
return Wire.endTransmission();
}
#endif // DAC_STEPPER_CURRENT

66
Marlin/dac_mcp4728.h Normal file
View File

@ -0,0 +1,66 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* Arduino library for MicroChip MCP4728 I2C D/A converter.
*/
#ifndef DAC_MCP4728_H
#define DAC_MCP4728_H
#include "MarlinConfig.h"
#if ENABLED(DAC_STEPPER_CURRENT)
#include "Wire.h"
#define defaultVDD DAC_STEPPER_MAX //was 5000 but differs with internal Vref
#define BASE_ADDR 0x60
#define RESET 0B00000110
#define WAKE 0B00001001
#define UPDATE 0B00001000
#define MULTIWRITE 0B01000000
#define SINGLEWRITE 0B01011000
#define SEQWRITE 0B01010000
#define VREFWRITE 0B10000000
#define GAINWRITE 0B11000000
#define POWERDOWNWRITE 0B10100000
#define GENERALCALL 0B00000000
#define GAINWRITE 0B11000000
// This is taken from the original lib, makes it easy to edit if needed
// DAC_OR_ADDRESS defined in pins_BOARD.h file
#define DAC_DEV_ADDRESS (BASE_ADDR | DAC_OR_ADDRESS)
void mcp4728_init();
uint8_t mcp4728_analogWrite(uint8_t channel, uint16_t value);
uint8_t mcp4728_eepromWrite();
uint8_t mcp4728_setVref_all(uint8_t value);
uint8_t mcp4728_setGain_all(uint8_t value);
uint16_t mcp4728_getValue(uint8_t channel);
uint8_t mcp4728_fastWrite();
uint8_t mcp4728_simpleCommand(byte simpleCommand);
uint8_t mcp4728_getDrvPct(uint8_t channel);
void mcp4728_setDrvPct(uint8_t pct[XYZE]);
#endif
#endif // DAC_MCP4728_H

77
Marlin/delay.h Normal file
View File

@ -0,0 +1,77 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* AVR busy wait delay Cycles routines:
*
* DELAY_CYCLES(count): Delay execution in cycles
* DELAY_NS(count): Delay execution in nanoseconds
* DELAY_US(count): Delay execution in microseconds
*/
#ifndef MARLIN_DELAY_H
#define MARLIN_DELAY_H
#define nop() __asm__ __volatile__("nop;\n\t":::)
FORCE_INLINE static void __delay_4cycles(uint8_t cy) {
__asm__ __volatile__(
L("1")
A("dec %[cnt]")
A("nop")
A("brne 1b")
: [cnt] "+r"(cy) // output: +r means input+output
: // input:
: "cc" // clobbers:
);
}
/* ---------------- Delay in cycles */
FORCE_INLINE static void DELAY_CYCLES(uint16_t x) {
if (__builtin_constant_p(x)) {
#define MAXNOPS 4
if (x <= (MAXNOPS)) {
switch (x) { case 4: nop(); case 3: nop(); case 2: nop(); case 1: nop(); }
}
else {
const uint32_t rem = (x) % (MAXNOPS);
switch (rem) { case 3: nop(); case 2: nop(); case 1: nop(); }
if ((x = (x) / (MAXNOPS)))
__delay_4cycles(x); // if need more then 4 nop loop is more optimal
}
#undef MAXNOPS
}
else
__delay_4cycles(x / 4);
}
#undef nop
/* ---------------- Delay in nanoseconds */
#define DELAY_NS(x) DELAY_CYCLES( (x) * (F_CPU/1000000L) / 1000L )
/* ---------------- Delay in microseconds */
#define DELAY_US(x) DELAY_CYCLES( (x) * (F_CPU/1000000L) )
#endif // MARLIN_DELAY_H

106
Marlin/digipot_mcp4018.cpp Normal file
View File

@ -0,0 +1,106 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "MarlinConfig.h"
#if ENABLED(DIGIPOT_I2C) && ENABLED(DIGIPOT_MCP4018)
#include "enum.h"
#include "Stream.h"
#include "utility/twi.h"
#include <SlowSoftI2CMaster.h> //https://github.com/stawel/SlowSoftI2CMaster
// Settings for the I2C based DIGIPOT (MCP4018) based on WT150
#define DIGIPOT_I2C_ADDRESS 0x2F
#define DIGIPOT_A4988_Rsx 0.250
#define DIGIPOT_A4988_Vrefmax 1.666
#define DIGIPOT_A4988_MAX_VALUE 127
#define DIGIPOT_A4988_Itripmax(Vref) ((Vref)/(8.0*DIGIPOT_A4988_Rsx))
#define DIGIPOT_A4988_FACTOR ((DIGIPOT_A4988_MAX_VALUE)/DIGIPOT_A4988_Itripmax(DIGIPOT_A4988_Vrefmax))
#define DIGIPOT_A4988_MAX_CURRENT 2.0
static byte current_to_wiper(const float current) {
const int16_t value = ceil(float(DIGIPOT_A4988_FACTOR) * current);
return byte(constrain(value, 0, DIGIPOT_A4988_MAX_VALUE));
}
const uint8_t sda_pins[DIGIPOT_I2C_NUM_CHANNELS] = {
DIGIPOTS_I2C_SDA_X
#if DIGIPOT_I2C_NUM_CHANNELS > 1
, DIGIPOTS_I2C_SDA_Y
#if DIGIPOT_I2C_NUM_CHANNELS > 2
, DIGIPOTS_I2C_SDA_Z
#if DIGIPOT_I2C_NUM_CHANNELS > 3
, DIGIPOTS_I2C_SDA_E0
#if DIGIPOT_I2C_NUM_CHANNELS > 4
, DIGIPOTS_I2C_SDA_E1
#endif
#endif
#endif
#endif
};
static SlowSoftI2CMaster pots[DIGIPOT_I2C_NUM_CHANNELS] = {
SlowSoftI2CMaster { sda_pins[X_AXIS], DIGIPOTS_I2C_SCL }
#if DIGIPOT_I2C_NUM_CHANNELS > 1
, SlowSoftI2CMaster { sda_pins[Y_AXIS], DIGIPOTS_I2C_SCL }
#if DIGIPOT_I2C_NUM_CHANNELS > 2
, SlowSoftI2CMaster { sda_pins[Z_AXIS], DIGIPOTS_I2C_SCL }
#if DIGIPOT_I2C_NUM_CHANNELS > 3
, SlowSoftI2CMaster { sda_pins[E_AXIS], DIGIPOTS_I2C_SCL }
#if DIGIPOT_I2C_NUM_CHANNELS > 4
, SlowSoftI2CMaster { sda_pins[E_AXIS + 1], DIGIPOTS_I2C_SCL }
#endif
#endif
#endif
#endif
};
static void i2c_send(const uint8_t channel, const byte v) {
if (WITHIN(channel, 0, DIGIPOT_I2C_NUM_CHANNELS - 1)) {
pots[channel].i2c_start(((DIGIPOT_I2C_ADDRESS) << 1) | I2C_WRITE);
pots[channel].i2c_write(v);
pots[channel].i2c_stop();
}
}
// This is for the MCP4018 I2C based digipot
void digipot_i2c_set_current(uint8_t channel, float current) {
i2c_send(channel, current_to_wiper(MIN(MAX(current, 0), float(DIGIPOT_A4988_MAX_CURRENT))));
}
void digipot_i2c_init() {
static const float digipot_motor_current[] PROGMEM = DIGIPOT_I2C_MOTOR_CURRENTS;
for (uint8_t i = 0; i < DIGIPOT_I2C_NUM_CHANNELS; i++)
pots[i].i2c_init();
// setup initial currents as defined in Configuration_adv.h
for (uint8_t i = 0; i < COUNT(digipot_motor_current); i++)
digipot_i2c_set_current(i, pgm_read_float(&digipot_motor_current[i]));
}
#endif // DIGIPOT_I2C && DIGIPOT_MCP4018

View File

@ -0,0 +1,79 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "MarlinConfig.h"
#if ENABLED(DIGIPOT_I2C) && DISABLED(DIGIPOT_MCP4018)
#include "Stream.h"
#include "utility/twi.h"
#include "Wire.h"
// Settings for the I2C based DIGIPOT (MCP4451) on Azteeg X3 Pro
#if MB(5DPRINT)
#define DIGIPOT_I2C_FACTOR 117.96
#define DIGIPOT_I2C_MAX_CURRENT 1.736
#else
#define DIGIPOT_I2C_FACTOR 106.7
#define DIGIPOT_I2C_MAX_CURRENT 2.5
#endif
static byte current_to_wiper(const float current) {
return byte(CEIL(float((DIGIPOT_I2C_FACTOR * current))));
}
static void i2c_send(const byte addr, const byte a, const byte b) {
Wire.beginTransmission(addr);
Wire.write(a);
Wire.write(b);
Wire.endTransmission();
}
// This is for the MCP4451 I2C based digipot
void digipot_i2c_set_current(uint8_t channel, float current) {
current = MIN((float) MAX(current, 0), DIGIPOT_I2C_MAX_CURRENT);
// these addresses are specific to Azteeg X3 Pro, can be set to others,
// In this case first digipot is at address A0=0, A1= 0, second one is at A0=0, A1= 1
byte addr = 0x2C; // channel 0-3
if (channel >= 4) {
addr = 0x2E; // channel 4-7
channel -= 4;
}
// Initial setup
i2c_send(addr, 0x40, 0xFF);
i2c_send(addr, 0xA0, 0xFF);
// Set actual wiper value
byte addresses[4] = { 0x00, 0x10, 0x60, 0x70 };
i2c_send(addr, addresses[channel], current_to_wiper(current));
}
void digipot_i2c_init() {
static const float digipot_motor_current[] PROGMEM = DIGIPOT_I2C_MOTOR_CURRENTS;
Wire.begin();
// setup initial currents as defined in Configuration_adv.h
for (uint8_t i = 0; i < COUNT(digipot_motor_current); i++)
digipot_i2c_set_current(i, pgm_read_float(&digipot_motor_current[i]));
}
#endif // DIGIPOT_I2C

1192
Marlin/dogm_bitmaps.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,180 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
Fontname: -Misc-Fixed-Medium-R-Normal--9-90-75-75-C-60-ISO10646-1
Copyright: Public domain font. Share and enjoy.
Capital A Height: 6, '1' Height: 6
Calculated Max Values w= 6 h= 9 x= 2 y= 7 dx= 6 dy= 0 ascent= 7 len= 9
Font Bounding box w= 6 h= 9 x= 0 y=-2
Calculated Min Values x= 0 y=-2 dx= 0 dy= 0
Pure Font ascent = 6 descent=-2
X Font ascent = 6 descent=-2
Max Font ascent = 7 descent=-2
*/
#include <U8glib.h>
const u8g_fntpgm_uint8_t u8g_font_6x9[2300] U8G_SECTION(".progmem.u8g_font_6x9") = {
0, 6, 9, 0, 254, 6, 1, 137, 2, 254, 32, 255, 254, 7, 254, 6,
254, 0, 0, 0, 6, 0, 7, 1, 6, 6, 6, 2, 0, 128, 128, 128,
128, 0, 128, 3, 3, 3, 6, 1, 3, 160, 160, 160, 5, 7, 7, 6,
0, 255, 80, 80, 248, 80, 248, 80, 80, 5, 9, 9, 6, 0, 254, 32,
112, 168, 160, 112, 40, 168, 112, 32, 6, 8, 8, 6, 0, 255, 64, 168,
72, 16, 32, 72, 84, 8, 5, 7, 7, 6, 0, 255, 96, 144, 144, 96,
152, 144, 104, 1, 3, 3, 6, 2, 3, 128, 128, 128, 2, 7, 7, 6,
2, 255, 64, 128, 128, 128, 128, 128, 64, 2, 7, 7, 6, 2, 255, 128,
64, 64, 64, 64, 64, 128, 5, 5, 5, 6, 0, 0, 136, 80, 248, 80,
136, 5, 5, 5, 6, 0, 0, 32, 32, 248, 32, 32, 2, 4, 4, 6,
2, 254, 192, 64, 64, 128, 5, 1, 1, 6, 0, 2, 248, 2, 2, 2,
6, 2, 0, 192, 192, 4, 6, 6, 6, 1, 0, 16, 16, 32, 64, 128,
128, 4, 6, 6, 6, 1, 0, 96, 144, 144, 144, 144, 96, 3, 6, 6,
6, 1, 0, 64, 192, 64, 64, 64, 224, 4, 6, 6, 6, 1, 0, 96,
144, 16, 32, 64, 240, 4, 6, 6, 6, 1, 0, 240, 32, 96, 16, 16,
224, 5, 6, 6, 6, 0, 0, 16, 48, 80, 144, 248, 16, 4, 6, 6,
6, 1, 0, 240, 128, 224, 16, 16, 224, 4, 6, 6, 6, 1, 0, 96,
128, 224, 144, 144, 96, 4, 6, 6, 6, 1, 0, 240, 16, 16, 32, 64,
64, 4, 6, 6, 6, 1, 0, 96, 144, 96, 144, 144, 96, 4, 6, 6,
6, 1, 0, 96, 144, 144, 112, 16, 96, 2, 5, 5, 6, 2, 0, 192,
192, 0, 192, 192, 2, 7, 7, 6, 2, 254, 192, 192, 0, 192, 64, 64,
128, 5, 5, 5, 6, 0, 0, 24, 96, 128, 96, 24, 5, 3, 3, 6,
0, 1, 248, 0, 248, 5, 5, 5, 6, 0, 0, 192, 48, 8, 48, 192,
4, 7, 7, 6, 1, 0, 96, 144, 16, 96, 64, 0, 64, 5, 6, 6,
6, 0, 0, 112, 144, 168, 176, 128, 112, 5, 6, 6, 6, 0, 0, 32,
80, 136, 248, 136, 136, 5, 6, 6, 6, 0, 0, 240, 136, 240, 136, 136,
240, 4, 6, 6, 6, 1, 0, 96, 144, 128, 128, 144, 96, 4, 6, 6,
6, 1, 0, 224, 144, 144, 144, 144, 224, 4, 6, 6, 6, 1, 0, 240,
128, 224, 128, 128, 240, 4, 6, 6, 6, 1, 0, 240, 128, 224, 128, 128,
128, 4, 6, 6, 6, 1, 0, 96, 144, 128, 176, 144, 96, 4, 6, 6,
6, 1, 0, 144, 144, 240, 144, 144, 144, 3, 6, 6, 6, 1, 0, 224,
64, 64, 64, 64, 224, 5, 6, 6, 6, 0, 0, 56, 16, 16, 16, 144,
96, 4, 6, 6, 6, 1, 0, 144, 160, 192, 160, 144, 144, 4, 6, 6,
6, 1, 0, 128, 128, 128, 128, 128, 240, 5, 6, 6, 6, 0, 0, 136,
216, 168, 168, 136, 136, 4, 6, 6, 6, 1, 0, 144, 208, 176, 144, 144,
144, 5, 6, 6, 6, 0, 0, 112, 136, 136, 136, 136, 112, 4, 6, 6,
6, 1, 0, 224, 144, 144, 224, 128, 128, 4, 7, 7, 6, 1, 255, 96,
144, 144, 208, 176, 96, 16, 4, 6, 6, 6, 1, 0, 224, 144, 144, 224,
144, 144, 4, 6, 6, 6, 1, 0, 96, 144, 64, 32, 144, 96, 5, 6,
6, 6, 0, 0, 248, 32, 32, 32, 32, 32, 4, 6, 6, 6, 1, 0,
144, 144, 144, 144, 144, 96, 4, 6, 6, 6, 1, 0, 144, 144, 144, 240,
96, 96, 5, 6, 6, 6, 0, 0, 136, 136, 168, 168, 216, 136, 5, 6,
6, 6, 0, 0, 136, 80, 32, 32, 80, 136, 5, 6, 6, 6, 0, 0,
136, 136, 80, 32, 32, 32, 4, 6, 6, 6, 1, 0, 240, 16, 32, 64,
128, 240, 3, 6, 6, 6, 1, 0, 224, 128, 128, 128, 128, 224, 4, 6,
6, 6, 1, 0, 128, 128, 64, 32, 16, 16, 3, 6, 6, 6, 1, 0,
224, 32, 32, 32, 32, 224, 5, 3, 3, 6, 0, 3, 32, 80, 136, 5,
1, 1, 6, 0, 254, 248, 2, 2, 2, 6, 2, 4, 128, 64, 4, 4,
4, 6, 1, 0, 112, 144, 144, 112, 4, 6, 6, 6, 1, 0, 128, 128,
224, 144, 144, 224, 4, 4, 4, 6, 1, 0, 112, 128, 128, 112, 4, 6,
6, 6, 1, 0, 16, 16, 112, 144, 144, 112, 4, 4, 4, 6, 1, 0,
96, 176, 192, 112, 4, 6, 6, 6, 1, 0, 32, 80, 64, 224, 64, 64,
4, 6, 6, 6, 1, 254, 96, 144, 144, 112, 16, 96, 4, 6, 6, 6,
1, 0, 128, 128, 224, 144, 144, 144, 3, 6, 6, 6, 1, 0, 64, 0,
192, 64, 64, 224, 3, 8, 8, 6, 1, 254, 32, 0, 96, 32, 32, 32,
160, 64, 4, 6, 6, 6, 1, 0, 128, 128, 160, 192, 160, 144, 3, 6,
6, 6, 1, 0, 192, 64, 64, 64, 64, 224, 5, 4, 4, 6, 0, 0,
208, 168, 168, 136, 4, 4, 4, 6, 1, 0, 224, 144, 144, 144, 4, 4,
4, 6, 1, 0, 96, 144, 144, 96, 4, 6, 6, 6, 1, 254, 224, 144,
144, 224, 128, 128, 4, 6, 6, 6, 1, 254, 112, 144, 144, 112, 16, 16,
4, 4, 4, 6, 1, 0, 160, 208, 128, 128, 4, 4, 4, 6, 1, 0,
112, 192, 48, 224, 4, 6, 6, 6, 1, 0, 64, 64, 224, 64, 80, 32,
4, 4, 4, 6, 1, 0, 144, 144, 144, 112, 4, 4, 4, 6, 1, 0,
144, 144, 96, 96, 5, 4, 4, 6, 0, 0, 136, 168, 168, 80, 4, 4,
4, 6, 1, 0, 144, 96, 96, 144, 4, 6, 6, 6, 1, 254, 144, 144,
144, 112, 144, 96, 4, 4, 4, 6, 1, 0, 240, 32, 64, 240, 3, 7,
7, 6, 1, 0, 32, 64, 64, 128, 64, 64, 32, 1, 7, 7, 6, 2,
255, 128, 128, 128, 128, 128, 128, 128, 3, 7, 7, 6, 1, 0, 128, 64,
64, 32, 64, 64, 128, 4, 2, 2, 6, 1, 3, 80, 160, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0,
0, 6, 0, 7, 1, 6, 6, 6, 2, 0, 128, 0, 128, 128, 128, 128,
4, 6, 6, 6, 1, 255, 32, 112, 160, 160, 112, 32, 5, 7, 7, 6,
0, 255, 48, 72, 64, 240, 64, 64, 248, 5, 5, 5, 6, 0, 0, 168,
80, 136, 80, 168, 5, 6, 6, 6, 0, 0, 136, 80, 248, 32, 248, 32,
1, 7, 7, 6, 2, 255, 128, 128, 128, 0, 128, 128, 128, 4, 7, 7,
6, 1, 255, 112, 128, 96, 144, 96, 16, 224, 3, 1, 1, 6, 1, 5,
160, 6, 7, 7, 6, 0, 0, 120, 132, 148, 164, 148, 132, 120, 3, 5,
5, 6, 1, 1, 96, 160, 96, 0, 224, 5, 5, 5, 6, 0, 0, 40,
80, 160, 80, 40, 4, 3, 3, 6, 1, 0, 240, 16, 16, 4, 1, 1,
6, 1, 2, 240, 6, 7, 7, 6, 0, 0, 120, 132, 180, 164, 164, 132,
120, 4, 1, 1, 6, 1, 5, 240, 4, 3, 3, 6, 1, 2, 96, 144,
96, 5, 7, 7, 6, 0, 255, 32, 32, 248, 32, 32, 0, 248, 3, 5,
5, 6, 1, 1, 64, 160, 32, 64, 224, 3, 5, 5, 6, 1, 1, 192,
32, 64, 32, 192, 2, 2, 2, 6, 2, 4, 64, 128, 4, 5, 5, 6,
1, 255, 144, 144, 176, 208, 128, 5, 6, 6, 6, 0, 0, 120, 232, 232,
104, 40, 40, 1, 1, 1, 6, 2, 2, 128, 2, 2, 2, 6, 2, 254,
64, 128, 3, 5, 5, 6, 1, 1, 64, 192, 64, 64, 224, 3, 5, 5,
6, 1, 1, 64, 160, 64, 0, 224, 5, 5, 5, 6, 0, 0, 160, 80,
40, 80, 160, 5, 8, 8, 6, 0, 255, 64, 192, 64, 80, 112, 48, 120,
16, 5, 8, 8, 6, 0, 255, 64, 192, 64, 80, 104, 8, 16, 56, 5,
8, 8, 6, 0, 255, 192, 32, 64, 48, 240, 48, 120, 16, 4, 7, 7,
6, 1, 0, 32, 0, 32, 96, 128, 144, 96, 5, 7, 7, 6, 0, 0,
64, 32, 32, 80, 112, 136, 136, 5, 7, 7, 6, 0, 0, 16, 32, 32,
80, 112, 136, 136, 5, 7, 7, 6, 0, 0, 32, 80, 32, 80, 112, 136,
136, 5, 7, 7, 6, 0, 0, 40, 80, 32, 80, 112, 136, 136, 5, 7,
7, 6, 0, 0, 80, 0, 32, 80, 112, 136, 136, 5, 7, 7, 6, 0,
0, 32, 80, 32, 80, 112, 136, 136, 5, 6, 6, 6, 0, 0, 120, 160,
240, 160, 160, 184, 4, 8, 8, 6, 1, 254, 96, 144, 128, 128, 144, 96,
32, 64, 4, 7, 7, 6, 1, 0, 64, 32, 240, 128, 224, 128, 240, 4,
7, 7, 6, 1, 0, 32, 64, 240, 128, 224, 128, 240, 4, 7, 7, 6,
1, 0, 32, 80, 240, 128, 224, 128, 240, 4, 7, 7, 6, 1, 0, 80,
0, 240, 128, 224, 128, 240, 3, 7, 7, 6, 1, 0, 128, 64, 224, 64,
64, 64, 224, 3, 7, 7, 6, 1, 0, 32, 64, 224, 64, 64, 64, 224,
3, 7, 7, 6, 1, 0, 64, 160, 224, 64, 64, 64, 224, 3, 7, 7,
6, 1, 0, 160, 0, 224, 64, 64, 64, 224, 5, 6, 6, 6, 0, 0,
112, 72, 232, 72, 72, 112, 4, 7, 7, 6, 1, 0, 80, 160, 144, 208,
176, 144, 144, 4, 7, 7, 6, 1, 0, 64, 32, 96, 144, 144, 144, 96,
4, 7, 7, 6, 1, 0, 32, 64, 96, 144, 144, 144, 96, 4, 7, 7,
6, 1, 0, 32, 80, 96, 144, 144, 144, 96, 4, 7, 7, 6, 1, 0,
80, 160, 96, 144, 144, 144, 96, 4, 7, 7, 6, 1, 0, 80, 0, 96,
144, 144, 144, 96, 5, 5, 5, 6, 0, 0, 136, 80, 32, 80, 136, 4,
8, 8, 6, 1, 255, 16, 112, 176, 176, 208, 208, 224, 128, 4, 7, 7,
6, 1, 0, 64, 32, 144, 144, 144, 144, 96, 4, 7, 7, 6, 1, 0,
32, 64, 144, 144, 144, 144, 96, 4, 7, 7, 6, 1, 0, 32, 80, 144,
144, 144, 144, 96, 4, 7, 7, 6, 1, 0, 80, 0, 144, 144, 144, 144,
96, 5, 7, 7, 6, 0, 0, 16, 32, 136, 80, 32, 32, 32, 4, 6,
6, 6, 1, 0, 128, 224, 144, 144, 224, 128, 4, 6, 6, 6, 1, 0,
96, 144, 160, 160, 144, 160, 4, 7, 7, 6, 1, 0, 64, 32, 0, 112,
144, 144, 112, 4, 7, 7, 6, 1, 0, 32, 64, 0, 112, 144, 144, 112,
4, 7, 7, 6, 1, 0, 32, 80, 0, 112, 144, 144, 112, 4, 7, 7,
6, 1, 0, 80, 160, 0, 112, 144, 144, 112, 4, 6, 6, 6, 1, 0,
80, 0, 112, 144, 144, 112, 4, 7, 7, 6, 1, 0, 32, 80, 32, 112,
144, 144, 112, 5, 4, 4, 6, 0, 0, 112, 168, 176, 120, 4, 6, 6,
6, 1, 254, 112, 128, 128, 112, 32, 64, 4, 7, 7, 6, 1, 0, 64,
32, 0, 96, 176, 192, 112, 4, 7, 7, 6, 1, 0, 32, 64, 0, 96,
176, 192, 112, 4, 7, 7, 6, 1, 0, 32, 80, 0, 96, 176, 192, 112,
4, 6, 6, 6, 1, 0, 80, 0, 96, 176, 192, 112, 3, 7, 7, 6,
1, 0, 128, 64, 0, 192, 64, 64, 224, 3, 7, 7, 6, 1, 0, 32,
64, 0, 192, 64, 64, 224, 3, 7, 7, 6, 1, 0, 64, 160, 0, 192,
64, 64, 224, 3, 6, 6, 6, 1, 0, 160, 0, 192, 64, 64, 224, 4,
7, 7, 6, 1, 0, 48, 96, 16, 112, 144, 144, 96, 4, 7, 7, 6,
1, 0, 80, 160, 0, 224, 144, 144, 144, 4, 7, 7, 6, 1, 0, 64,
32, 0, 96, 144, 144, 96, 4, 7, 7, 6, 1, 0, 32, 64, 0, 96,
144, 144, 96, 4, 7, 7, 6, 1, 0, 32, 80, 0, 96, 144, 144, 96,
4, 7, 7, 6, 1, 0, 80, 160, 0, 96, 144, 144, 96, 4, 6, 6,
6, 1, 0, 80, 0, 96, 144, 144, 96, 5, 5, 5, 6, 0, 0, 32,
0, 248, 0, 32, 4, 4, 4, 6, 1, 0, 112, 176, 208, 224, 4, 7,
7, 6, 1, 0, 64, 32, 0, 144, 144, 144, 112, 4, 7, 7, 6, 1,
0, 32, 64, 0, 144, 144, 144, 112, 4, 7, 7, 6, 1, 0, 32, 80,
0, 144, 144, 144, 112, 4, 6, 6, 6, 1, 0, 80, 0, 144, 144, 144,
112, 4, 9, 9, 6, 1, 254, 32, 64, 0, 144, 144, 144, 112, 144, 96,
4, 8, 8, 6, 1, 254, 128, 128, 224, 144, 144, 224, 128, 128, 4, 8,
8, 6, 1, 254, 80, 0, 144, 144, 144, 112, 144, 96
};

View File

@ -0,0 +1,194 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
Fontname: HD44780_C v1.2
Copyright: A. Hardtung, public domain
Capital A Height: 7, '1' Height: 7
Calculated Max Values w= 5 h= 8 x= 2 y= 7 dx= 6 dy= 0 ascent= 8 len= 8
Font Bounding box w= 6 h= 9 x= 0 y=-2
Calculated Min Values x= 0 y=-1 dx= 0 dy= 0
Pure Font ascent = 7 descent=-1
X Font ascent = 7 descent=-1
Max Font ascent = 8 descent=-1
*/
#include <U8glib.h>
const u8g_fntpgm_uint8_t HD44780_C_5x7[2522] U8G_SECTION(".progmem.HD44780_C_5x7") = {
0, 6, 9, 0, 254, 7, 1, 145, 3, 34, 32, 255, 255, 8, 255, 7,
255, 0, 0, 0, 6, 0, 0, 1, 7, 7, 6, 2, 0, 128, 128, 128,
128, 128, 0, 128, 3, 2, 2, 6, 1, 5, 160, 160, 5, 7, 7, 6,
0, 0, 80, 80, 248, 80, 248, 80, 80, 5, 7, 7, 6, 0, 0, 32,
120, 160, 112, 40, 240, 32, 5, 7, 7, 6, 0, 0, 192, 200, 16, 32,
64, 152, 24, 5, 7, 7, 6, 0, 0, 96, 144, 160, 64, 168, 144, 104,
2, 3, 3, 6, 1, 4, 192, 64, 128, 3, 7, 7, 6, 1, 0, 32,
64, 128, 128, 128, 64, 32, 3, 7, 7, 6, 1, 0, 128, 64, 32, 32,
32, 64, 128, 5, 5, 5, 6, 0, 1, 32, 168, 112, 168, 32, 5, 5,
5, 6, 0, 1, 32, 32, 248, 32, 32, 2, 3, 3, 6, 2, 255, 192,
64, 128, 5, 1, 1, 6, 0, 3, 248, 2, 2, 2, 6, 2, 0, 192,
192, 5, 5, 5, 6, 0, 1, 8, 16, 32, 64, 128, 5, 7, 7, 6,
0, 0, 112, 136, 152, 168, 200, 136, 112, 3, 7, 7, 6, 1, 0, 64,
192, 64, 64, 64, 64, 224, 5, 7, 7, 6, 0, 0, 112, 136, 8, 112,
128, 128, 248, 5, 7, 7, 6, 0, 0, 248, 16, 32, 16, 8, 8, 240,
5, 7, 7, 6, 0, 0, 16, 48, 80, 144, 248, 16, 16, 5, 7, 7,
6, 0, 0, 248, 128, 240, 8, 8, 136, 112, 5, 7, 7, 6, 0, 0,
48, 64, 128, 240, 136, 136, 112, 5, 7, 7, 6, 0, 0, 248, 8, 16,
32, 32, 32, 32, 5, 7, 7, 6, 0, 0, 112, 136, 136, 112, 136, 136,
112, 5, 7, 7, 6, 0, 0, 112, 136, 136, 120, 8, 16, 96, 2, 5,
5, 6, 2, 0, 192, 192, 0, 192, 192, 2, 6, 6, 6, 2, 255, 192,
192, 0, 192, 64, 128, 4, 7, 7, 6, 0, 0, 16, 32, 64, 128, 64,
32, 16, 5, 3, 3, 6, 0, 2, 248, 0, 248, 4, 7, 7, 6, 1,
0, 128, 64, 32, 16, 32, 64, 128, 5, 7, 7, 6, 0, 0, 112, 136,
8, 16, 32, 0, 32, 5, 6, 6, 6, 0, 0, 112, 136, 8, 104, 168,
112, 5, 7, 7, 6, 0, 0, 112, 136, 136, 248, 136, 136, 136, 5, 7,
7, 6, 0, 0, 240, 136, 136, 240, 136, 136, 240, 5, 7, 7, 6, 0,
0, 112, 136, 128, 128, 128, 136, 112, 5, 7, 7, 6, 0, 0, 224, 144,
136, 136, 136, 144, 224, 5, 7, 7, 6, 0, 0, 248, 128, 128, 240, 128,
128, 248, 5, 7, 7, 6, 0, 0, 248, 128, 128, 240, 128, 128, 128, 5,
7, 7, 6, 0, 0, 112, 136, 128, 184, 136, 136, 112, 5, 7, 7, 6,
0, 0, 136, 136, 136, 248, 136, 136, 136, 1, 7, 7, 6, 2, 0, 128,
128, 128, 128, 128, 128, 128, 5, 7, 7, 6, 0, 0, 56, 16, 16, 16,
16, 144, 96, 5, 7, 7, 6, 0, 0, 136, 144, 160, 192, 160, 144, 136,
5, 7, 7, 6, 0, 0, 128, 128, 128, 128, 128, 128, 248, 5, 7, 7,
6, 0, 0, 136, 216, 168, 136, 136, 136, 136, 5, 7, 7, 6, 0, 0,
136, 136, 200, 168, 152, 136, 136, 5, 7, 7, 6, 0, 0, 112, 136, 136,
136, 136, 136, 112, 5, 7, 7, 6, 0, 0, 240, 136, 136, 240, 128, 128,
128, 5, 7, 7, 6, 0, 0, 112, 136, 136, 136, 168, 144, 104, 5, 7,
7, 6, 0, 0, 240, 136, 136, 240, 160, 144, 136, 5, 7, 7, 6, 0,
0, 120, 128, 128, 112, 8, 8, 240, 5, 7, 7, 6, 0, 0, 248, 32,
32, 32, 32, 32, 32, 5, 7, 7, 6, 0, 0, 136, 136, 136, 136, 136,
136, 112, 5, 7, 7, 6, 0, 0, 136, 136, 136, 136, 136, 80, 32, 5,
7, 7, 6, 0, 0, 136, 136, 136, 136, 136, 168, 80, 5, 7, 7, 6,
0, 0, 136, 136, 80, 32, 80, 136, 136, 5, 7, 7, 6, 0, 0, 136,
136, 136, 80, 32, 32, 32, 5, 7, 7, 6, 0, 0, 248, 8, 16, 32,
64, 128, 248, 3, 7, 7, 6, 1, 0, 224, 128, 128, 128, 128, 128, 224,
5, 7, 7, 6, 0, 0, 32, 112, 160, 160, 168, 112, 32, 3, 7, 7,
6, 1, 0, 224, 32, 32, 32, 32, 32, 224, 5, 3, 3, 6, 0, 4,
32, 80, 136, 5, 1, 1, 6, 0, 0, 248, 2, 2, 2, 6, 2, 5,
128, 64, 5, 5, 5, 6, 0, 0, 112, 8, 120, 136, 120, 5, 7, 7,
6, 0, 0, 128, 128, 176, 200, 136, 136, 240, 5, 5, 5, 6, 0, 0,
112, 128, 128, 136, 112, 5, 7, 7, 6, 0, 0, 8, 8, 104, 152, 136,
136, 120, 5, 5, 5, 6, 0, 0, 112, 136, 248, 128, 112, 5, 7, 7,
6, 0, 0, 48, 72, 224, 64, 64, 64, 64, 5, 6, 6, 6, 0, 255,
112, 136, 136, 120, 8, 112, 5, 7, 7, 6, 0, 0, 128, 128, 176, 200,
136, 136, 136, 1, 7, 7, 6, 2, 0, 128, 0, 128, 128, 128, 128, 128,
3, 8, 8, 6, 1, 255, 32, 0, 32, 32, 32, 32, 160, 64, 4, 7,
7, 6, 0, 0, 128, 128, 144, 160, 192, 160, 144, 3, 7, 7, 6, 1,
0, 192, 64, 64, 64, 64, 64, 224, 5, 5, 5, 6, 0, 0, 208, 168,
168, 168, 168, 5, 5, 5, 6, 0, 0, 176, 200, 136, 136, 136, 5, 5,
5, 6, 0, 0, 112, 136, 136, 136, 112, 5, 6, 6, 6, 0, 255, 240,
136, 136, 240, 128, 128, 5, 6, 6, 6, 0, 255, 120, 136, 136, 120, 8,
8, 5, 5, 5, 6, 0, 0, 176, 200, 128, 128, 128, 5, 5, 5, 6,
0, 0, 112, 128, 112, 8, 240, 5, 7, 7, 6, 0, 0, 64, 64, 224,
64, 64, 72, 48, 5, 5, 5, 6, 0, 0, 136, 136, 136, 152, 104, 5,
5, 5, 6, 0, 0, 136, 136, 136, 80, 32, 5, 5, 5, 6, 0, 0,
136, 136, 168, 168, 80, 5, 5, 5, 6, 0, 0, 136, 80, 32, 80, 136,
5, 6, 6, 6, 0, 255, 136, 136, 136, 120, 8, 112, 5, 5, 5, 6,
0, 0, 248, 16, 32, 64, 248, 5, 5, 5, 6, 0, 2, 184, 168, 168,
168, 184, 5, 5, 5, 6, 0, 2, 184, 136, 184, 160, 184, 5, 5, 5,
6, 0, 2, 184, 160, 184, 136, 184, 5, 6, 6, 6, 0, 1, 8, 40,
72, 248, 64, 32, 5, 5, 5, 6, 0, 0, 56, 112, 224, 136, 240, 0,
0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0,
0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0,
6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0,
0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0,
0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0,
6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0,
0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0,
0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0,
6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0,
0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0,
0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0,
6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 5,
7, 7, 6, 0, 0, 248, 136, 128, 240, 136, 136, 240, 5, 7, 7, 6,
0, 0, 248, 136, 128, 128, 128, 128, 128, 5, 7, 7, 6, 0, 0, 80,
0, 248, 128, 240, 128, 248, 5, 7, 7, 6, 0, 0, 168, 168, 168, 112,
168, 168, 168, 5, 7, 7, 6, 0, 0, 240, 8, 8, 112, 8, 8, 240,
5, 7, 7, 6, 0, 0, 136, 136, 152, 168, 200, 136, 136, 5, 8, 8,
6, 0, 0, 80, 32, 136, 152, 168, 168, 200, 136, 5, 7, 7, 6, 0,
0, 120, 40, 40, 40, 40, 168, 72, 5, 7, 7, 6, 0, 0, 248, 136,
136, 136, 136, 136, 136, 5, 7, 7, 6, 0, 0, 136, 136, 136, 80, 32,
64, 128, 5, 7, 7, 6, 0, 0, 32, 112, 168, 168, 168, 112, 32, 5,
7, 7, 6, 0, 0, 136, 136, 136, 120, 8, 8, 8, 5, 7, 7, 6,
0, 0, 168, 168, 168, 168, 168, 168, 248, 5, 7, 7, 6, 0, 0, 192,
64, 64, 112, 72, 72, 112, 5, 7, 7, 6, 0, 0, 136, 136, 136, 200,
168, 168, 200, 5, 7, 7, 6, 0, 0, 112, 136, 8, 56, 8, 136, 112,
5, 7, 7, 6, 0, 0, 144, 168, 168, 232, 168, 168, 144, 5, 7, 7,
6, 0, 0, 120, 136, 136, 120, 40, 72, 136, 5, 7, 7, 6, 0, 0,
24, 96, 128, 240, 136, 136, 112, 4, 5, 5, 6, 0, 0, 224, 144, 224,
144, 224, 5, 5, 5, 6, 0, 0, 248, 136, 128, 128, 128, 5, 7, 7,
6, 0, 0, 80, 0, 112, 136, 248, 128, 112, 5, 5, 5, 6, 0, 0,
168, 168, 112, 168, 168, 5, 5, 5, 6, 0, 0, 240, 8, 48, 8, 240,
5, 5, 5, 6, 0, 0, 136, 152, 168, 200, 136, 5, 7, 7, 6, 0,
0, 80, 32, 136, 152, 168, 200, 136, 4, 5, 5, 6, 0, 0, 144, 160,
192, 160, 144, 5, 5, 5, 6, 0, 0, 248, 40, 40, 168, 72, 5, 5,
5, 6, 0, 0, 136, 216, 168, 136, 136, 5, 5, 5, 6, 0, 0, 136,
136, 248, 136, 136, 5, 5, 5, 6, 0, 0, 248, 136, 136, 136, 136, 5,
5, 5, 6, 0, 0, 248, 32, 32, 32, 32, 5, 5, 5, 6, 0, 0,
136, 136, 120, 8, 8, 5, 5, 5, 6, 0, 0, 168, 168, 168, 168, 248,
5, 5, 5, 6, 0, 0, 192, 64, 112, 72, 112, 5, 5, 5, 6, 0,
0, 136, 136, 200, 168, 200, 4, 5, 5, 6, 0, 0, 128, 128, 224, 144,
224, 5, 5, 5, 6, 0, 0, 112, 136, 56, 136, 112, 5, 5, 5, 6,
0, 0, 144, 168, 232, 168, 144, 5, 5, 5, 6, 0, 0, 120, 136, 120,
40, 72, 5, 5, 5, 6, 0, 1, 32, 72, 144, 72, 32, 5, 5, 5,
6, 0, 1, 32, 144, 72, 144, 32, 5, 3, 3, 6, 0, 0, 72, 144,
216, 5, 3, 3, 6, 0, 4, 216, 72, 144, 5, 7, 7, 6, 0, 0,
144, 208, 176, 144, 56, 40, 56, 5, 7, 7, 6, 0, 0, 32, 0, 32,
64, 128, 136, 112, 5, 7, 7, 6, 0, 0, 24, 32, 32, 112, 32, 32,
192, 5, 7, 7, 6, 0, 0, 32, 80, 64, 240, 64, 64, 120, 1, 2,
2, 6, 2, 0, 128, 128, 1, 4, 4, 6, 2, 0, 128, 128, 128, 128,
3, 5, 5, 6, 1, 0, 160, 160, 160, 0, 224, 3, 5, 5, 6, 1,
0, 160, 160, 160, 0, 160, 5, 7, 7, 6, 0, 0, 160, 0, 232, 16,
32, 64, 128, 5, 5, 5, 6, 0, 1, 216, 112, 32, 112, 216, 5, 7,
7, 6, 0, 0, 160, 64, 168, 16, 32, 64, 128, 3, 6, 6, 6, 1,
1, 224, 64, 64, 64, 64, 224, 5, 6, 6, 6, 0, 1, 248, 80, 80,
80, 80, 248, 5, 7, 7, 6, 0, 0, 32, 112, 168, 32, 32, 32, 32,
5, 7, 7, 6, 0, 0, 32, 32, 32, 32, 168, 112, 32, 5, 7, 7,
6, 0, 0, 128, 144, 176, 248, 176, 144, 128, 5, 7, 7, 6, 0, 0,
8, 72, 104, 248, 104, 72, 8, 5, 7, 7, 6, 0, 0, 128, 136, 168,
248, 168, 136, 128, 5, 7, 7, 6, 0, 0, 128, 224, 136, 16, 32, 64,
128, 2, 2, 2, 6, 2, 2, 192, 192, 5, 8, 8, 6, 0, 255, 120,
40, 40, 40, 72, 136, 248, 136, 5, 8, 8, 6, 0, 255, 136, 136, 136,
136, 136, 136, 248, 8, 5, 8, 8, 6, 0, 255, 168, 168, 168, 168, 168,
168, 248, 8, 5, 6, 6, 6, 0, 255, 120, 40, 72, 136, 248, 136, 5,
7, 7, 6, 0, 255, 32, 32, 112, 168, 168, 112, 32, 5, 6, 6, 6,
0, 255, 136, 136, 136, 136, 248, 8, 5, 6, 6, 6, 0, 255, 168, 168,
168, 168, 248, 8, 2, 2, 2, 6, 2, 6, 64, 128, 3, 1, 1, 6,
1, 7, 160, 5, 2, 2, 6, 0, 6, 72, 176, 5, 8, 8, 6, 0,
0, 16, 32, 0, 112, 136, 248, 128, 112, 5, 6, 6, 6, 0, 255, 112,
128, 136, 112, 32, 96, 3, 7, 7, 6, 1, 0, 160, 0, 160, 160, 160,
32, 192, 5, 6, 6, 6, 0, 1, 32, 112, 112, 112, 248, 32, 5, 5,
5, 6, 0, 1, 80, 0, 136, 0, 80, 5, 5, 5, 6, 0, 1, 112,
136, 136, 136, 112, 5, 7, 7, 6, 0, 0, 136, 144, 168, 88, 184, 8,
8, 5, 7, 7, 6, 0, 0, 136, 144, 184, 72, 184, 8, 56, 5, 7,
7, 6, 0, 0, 136, 144, 184, 72, 152, 32, 56, 5, 8, 8, 6, 0,
0, 192, 64, 192, 72, 216, 56, 8, 8, 5, 7, 7, 6, 0, 0, 136,
248, 136, 248, 136, 248, 136, 4, 5, 5, 6, 0, 2, 192, 0, 48, 0,
96, 5, 8, 8, 6, 0, 0, 64, 160, 224, 168, 8, 40, 120, 32, 5,
8, 8, 6, 0, 0, 64, 112, 64, 120, 64, 112, 64, 224, 5, 8, 8,
6, 0, 0, 32, 112, 32, 248, 32, 112, 32, 112, 5, 7, 7, 6, 0,
0, 104, 0, 232, 0, 104, 16, 56, 5, 8, 8, 6, 0, 0, 16, 112,
16, 240, 16, 112, 16, 56, 5, 7, 7, 6, 0, 1, 32, 112, 32, 248,
32, 112, 32, 5, 8, 8, 6, 0, 0, 16, 144, 80, 48, 80, 144, 16,
56, 5, 8, 8, 6, 0, 0, 48, 72, 32, 80, 80, 32, 144, 96, 5,
7, 7, 6, 0, 0, 120, 168, 168, 120, 40, 40, 40, 5, 8, 8, 6,
0, 0, 248, 248, 248, 248, 248, 248, 248, 248
};

View File

@ -0,0 +1,192 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
Fontname: HD44780_J
Copyright: A. Hardtung, public domain
Capital A Height: 7, '1' Height: 7
Calculated Max Values w= 6 h=10 x= 2 y= 5 dx= 6 dy= 0 ascent= 8 len= 8
Font Bounding box w= 6 h= 9 x= 0 y=-2
Calculated Min Values x= 0 y=-2 dx= 0 dy= 0
Pure Font ascent = 7 descent=-1
X Font ascent = 7 descent=-1
Max Font ascent = 8 descent=-2
*/
#include <U8glib.h>
const u8g_fntpgm_uint8_t HD44780_J_5x7[2492] U8G_SECTION(".progmem.HD44780_J_5x7") = {
0, 6, 9, 0, 254, 7, 1, 145, 3, 34, 32, 255, 255, 8, 254, 7,
255, 0, 0, 0, 6, 0, 0, 1, 7, 7, 6, 2, 0, 128, 128, 128,
128, 128, 0, 128, 3, 2, 2, 6, 1, 5, 160, 160, 5, 7, 7, 6,
0, 0, 80, 80, 248, 80, 248, 80, 80, 5, 7, 7, 6, 0, 0, 32,
120, 160, 112, 40, 240, 32, 5, 7, 7, 6, 0, 0, 192, 200, 16, 32,
64, 152, 24, 5, 7, 7, 6, 0, 0, 96, 144, 160, 64, 168, 144, 104,
2, 3, 3, 6, 1, 4, 192, 64, 128, 3, 7, 7, 6, 1, 0, 32,
64, 128, 128, 128, 64, 32, 3, 7, 7, 6, 1, 0, 128, 64, 32, 32,
32, 64, 128, 5, 5, 5, 6, 0, 1, 32, 168, 112, 168, 32, 5, 5,
5, 6, 0, 1, 32, 32, 248, 32, 32, 2, 3, 3, 6, 2, 255, 192,
64, 128, 5, 1, 1, 6, 0, 3, 248, 2, 2, 2, 6, 2, 0, 192,
192, 5, 5, 5, 6, 0, 1, 8, 16, 32, 64, 128, 5, 7, 7, 6,
0, 0, 112, 136, 152, 168, 200, 136, 112, 3, 7, 7, 6, 1, 0, 64,
192, 64, 64, 64, 64, 224, 5, 7, 7, 6, 0, 0, 112, 136, 8, 112,
128, 128, 248, 5, 7, 7, 6, 0, 0, 248, 16, 32, 16, 8, 8, 240,
5, 7, 7, 6, 0, 0, 16, 48, 80, 144, 248, 16, 16, 5, 7, 7,
6, 0, 0, 248, 128, 240, 8, 8, 136, 112, 5, 7, 7, 6, 0, 0,
48, 64, 128, 240, 136, 136, 112, 5, 7, 7, 6, 0, 0, 248, 8, 16,
32, 32, 32, 32, 5, 7, 7, 6, 0, 0, 112, 136, 136, 112, 136, 136,
112, 5, 7, 7, 6, 0, 0, 112, 136, 136, 120, 8, 16, 96, 2, 5,
5, 6, 2, 0, 192, 192, 0, 192, 192, 2, 6, 6, 6, 2, 255, 192,
192, 0, 192, 64, 128, 4, 7, 7, 6, 0, 0, 16, 32, 64, 128, 64,
32, 16, 5, 3, 3, 6, 0, 2, 248, 0, 248, 4, 7, 7, 6, 1,
0, 128, 64, 32, 16, 32, 64, 128, 5, 7, 7, 6, 0, 0, 112, 136,
8, 16, 32, 0, 32, 5, 6, 6, 6, 0, 0, 112, 136, 8, 104, 168,
112, 5, 7, 7, 6, 0, 0, 112, 136, 136, 248, 136, 136, 136, 5, 7,
7, 6, 0, 0, 240, 136, 136, 240, 136, 136, 240, 5, 7, 7, 6, 0,
0, 112, 136, 128, 128, 128, 136, 112, 5, 7, 7, 6, 0, 0, 224, 144,
136, 136, 136, 144, 224, 5, 7, 7, 6, 0, 0, 248, 128, 128, 240, 128,
128, 248, 5, 7, 7, 6, 0, 0, 248, 128, 128, 240, 128, 128, 128, 5,
7, 7, 6, 0, 0, 112, 136, 128, 184, 136, 136, 112, 5, 7, 7, 6,
0, 0, 136, 136, 136, 248, 136, 136, 136, 1, 7, 7, 6, 2, 0, 128,
128, 128, 128, 128, 128, 128, 5, 7, 7, 6, 0, 0, 56, 16, 16, 16,
16, 144, 96, 5, 7, 7, 6, 0, 0, 136, 144, 160, 192, 160, 144, 136,
5, 7, 7, 6, 0, 0, 128, 128, 128, 128, 128, 128, 248, 5, 7, 7,
6, 0, 0, 136, 216, 168, 136, 136, 136, 136, 5, 7, 7, 6, 0, 0,
136, 136, 200, 168, 152, 136, 136, 5, 7, 7, 6, 0, 0, 112, 136, 136,
136, 136, 136, 112, 5, 7, 7, 6, 0, 0, 240, 136, 136, 240, 128, 128,
128, 5, 7, 7, 6, 0, 0, 112, 136, 136, 136, 168, 144, 104, 5, 7,
7, 6, 0, 0, 240, 136, 136, 240, 160, 144, 136, 5, 7, 7, 6, 0,
0, 120, 128, 128, 112, 8, 8, 240, 5, 7, 7, 6, 0, 0, 248, 32,
32, 32, 32, 32, 32, 5, 7, 7, 6, 0, 0, 136, 136, 136, 136, 136,
136, 112, 5, 7, 7, 6, 0, 0, 136, 136, 136, 136, 136, 80, 32, 5,
7, 7, 6, 0, 0, 136, 136, 136, 136, 136, 168, 80, 5, 7, 7, 6,
0, 0, 136, 136, 80, 32, 80, 136, 136, 5, 7, 7, 6, 0, 0, 136,
136, 136, 80, 32, 32, 32, 5, 7, 7, 6, 0, 0, 248, 8, 16, 32,
64, 128, 248, 3, 7, 7, 6, 1, 0, 224, 128, 128, 128, 128, 128, 224,
5, 7, 7, 6, 0, 0, 136, 80, 248, 32, 248, 32, 32, 3, 7, 7,
6, 1, 0, 224, 32, 32, 32, 32, 32, 224, 5, 3, 3, 6, 0, 4,
32, 80, 136, 5, 1, 1, 6, 0, 0, 248, 2, 2, 2, 6, 2, 5,
128, 64, 5, 5, 5, 6, 0, 0, 112, 8, 120, 136, 120, 5, 7, 7,
6, 0, 0, 128, 128, 176, 200, 136, 136, 240, 5, 5, 5, 6, 0, 0,
112, 128, 128, 136, 112, 5, 7, 7, 6, 0, 0, 8, 8, 104, 152, 136,
136, 120, 5, 5, 5, 6, 0, 0, 112, 136, 248, 128, 112, 5, 7, 7,
6, 0, 0, 48, 72, 224, 64, 64, 64, 64, 5, 6, 6, 6, 0, 255,
112, 136, 136, 120, 8, 112, 5, 7, 7, 6, 0, 0, 128, 128, 176, 200,
136, 136, 136, 1, 7, 7, 6, 2, 0, 128, 0, 128, 128, 128, 128, 128,
3, 8, 8, 6, 1, 255, 32, 0, 32, 32, 32, 32, 160, 64, 4, 7,
7, 6, 0, 0, 128, 128, 144, 160, 192, 160, 144, 3, 7, 7, 6, 1,
0, 192, 64, 64, 64, 64, 64, 224, 5, 5, 5, 6, 0, 0, 208, 168,
168, 168, 168, 5, 5, 5, 6, 0, 0, 176, 200, 136, 136, 136, 5, 5,
5, 6, 0, 0, 112, 136, 136, 136, 112, 5, 6, 6, 6, 0, 255, 240,
136, 136, 240, 128, 128, 5, 6, 6, 6, 0, 255, 120, 136, 136, 120, 8,
8, 5, 5, 5, 6, 0, 0, 176, 200, 128, 128, 128, 5, 5, 5, 6,
0, 0, 112, 128, 112, 8, 240, 5, 7, 7, 6, 0, 0, 64, 64, 224,
64, 64, 72, 48, 5, 5, 5, 6, 0, 0, 136, 136, 136, 152, 104, 5,
5, 5, 6, 0, 0, 136, 136, 136, 80, 32, 5, 5, 5, 6, 0, 0,
136, 136, 168, 168, 80, 5, 5, 5, 6, 0, 0, 136, 80, 32, 80, 136,
5, 6, 6, 6, 0, 255, 136, 136, 136, 120, 8, 112, 5, 5, 5, 6,
0, 0, 248, 16, 32, 64, 248, 3, 7, 7, 6, 1, 0, 32, 64, 64,
128, 64, 64, 32, 1, 7, 7, 6, 2, 0, 128, 128, 128, 128, 128, 128,
128, 3, 7, 7, 6, 1, 0, 128, 64, 64, 32, 64, 64, 128, 5, 5,
5, 6, 0, 1, 32, 16, 248, 16, 32, 5, 5, 5, 6, 0, 1, 32,
64, 248, 64, 32, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0,
0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6,
0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0,
0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0,
0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6,
0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0,
0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0,
0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6,
0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0,
0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0,
0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6,
0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0,
0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 3, 3, 3, 6, 0, 0,
224, 160, 224, 3, 4, 4, 6, 2, 3, 224, 128, 128, 128, 3, 4, 4,
6, 0, 0, 32, 32, 32, 224, 3, 3, 3, 6, 0, 0, 128, 64, 32,
2, 2, 2, 6, 1, 2, 192, 192, 5, 6, 6, 6, 0, 0, 248, 8,
248, 8, 16, 32, 5, 5, 5, 6, 0, 0, 248, 8, 48, 32, 64, 4,
5, 5, 6, 0, 0, 16, 32, 96, 160, 32, 5, 5, 5, 6, 0, 0,
32, 248, 136, 8, 48, 5, 4, 4, 6, 0, 0, 248, 32, 32, 248, 5,
5, 5, 6, 0, 0, 16, 248, 48, 80, 144, 5, 5, 5, 6, 0, 0,
64, 248, 72, 80, 64, 5, 4, 4, 6, 0, 0, 112, 16, 16, 248, 4,
5, 5, 6, 0, 0, 240, 16, 240, 16, 240, 5, 4, 4, 6, 0, 0,
168, 168, 8, 48, 5, 1, 1, 6, 0, 3, 248, 5, 7, 7, 6, 0,
0, 248, 8, 40, 48, 32, 32, 64, 5, 7, 7, 6, 0, 0, 8, 16,
32, 96, 160, 32, 32, 5, 7, 7, 6, 0, 0, 32, 248, 136, 136, 8,
16, 32, 5, 6, 6, 6, 0, 0, 248, 32, 32, 32, 32, 248, 5, 7,
7, 6, 0, 0, 16, 248, 16, 48, 80, 144, 16, 5, 7, 7, 6, 0,
0, 64, 248, 72, 72, 72, 72, 144, 5, 7, 7, 6, 0, 0, 32, 248,
32, 248, 32, 32, 32, 5, 6, 6, 6, 0, 0, 120, 72, 136, 8, 16,
96, 5, 7, 7, 6, 0, 0, 64, 120, 144, 16, 16, 16, 32, 5, 6,
6, 6, 0, 0, 248, 8, 8, 8, 8, 248, 5, 7, 7, 6, 0, 0,
80, 248, 80, 80, 16, 32, 64, 5, 6, 6, 6, 0, 0, 192, 8, 200,
8, 16, 224, 5, 6, 6, 6, 0, 0, 248, 8, 16, 32, 80, 136, 5,
7, 7, 6, 0, 0, 64, 248, 72, 80, 64, 64, 56, 5, 6, 6, 6,
0, 0, 136, 136, 72, 8, 16, 96, 5, 6, 6, 6, 0, 0, 120, 72,
168, 24, 16, 96, 5, 7, 7, 6, 0, 0, 16, 224, 32, 248, 32, 32,
64, 5, 6, 6, 6, 0, 0, 168, 168, 168, 8, 16, 32, 5, 7, 7,
6, 0, 0, 112, 0, 248, 32, 32, 32, 64, 3, 7, 7, 6, 1, 0,
128, 128, 128, 192, 160, 128, 128, 5, 7, 7, 6, 0, 0, 32, 32, 248,
32, 32, 64, 128, 5, 6, 6, 6, 0, 0, 112, 0, 0, 0, 0, 248,
5, 6, 6, 6, 0, 0, 248, 8, 80, 32, 80, 128, 5, 7, 7, 6,
0, 0, 32, 248, 16, 32, 112, 168, 32, 3, 7, 7, 6, 1, 0, 32,
32, 32, 32, 32, 64, 128, 5, 6, 6, 6, 0, 0, 32, 16, 136, 136,
136, 136, 5, 7, 7, 6, 0, 0, 128, 128, 248, 128, 128, 128, 120, 5,
6, 6, 6, 0, 0, 248, 8, 8, 8, 16, 96, 5, 5, 5, 6, 0,
1, 64, 160, 16, 8, 8, 5, 7, 7, 6, 0, 0, 32, 248, 32, 32,
168, 168, 32, 5, 6, 6, 6, 0, 0, 248, 8, 8, 80, 32, 16, 4,
6, 6, 6, 1, 0, 224, 0, 224, 0, 224, 16, 5, 6, 6, 6, 0,
0, 32, 64, 128, 136, 248, 8, 5, 6, 6, 6, 0, 0, 8, 8, 80,
32, 80, 128, 5, 6, 6, 6, 0, 0, 248, 64, 248, 64, 64, 56, 5,
7, 7, 6, 0, 0, 64, 64, 248, 72, 80, 64, 64, 5, 7, 7, 6,
0, 0, 112, 16, 16, 16, 16, 16, 248, 5, 6, 6, 6, 0, 0, 248,
8, 248, 8, 8, 248, 5, 7, 7, 6, 0, 0, 112, 0, 248, 8, 8,
16, 32, 4, 7, 7, 6, 0, 0, 144, 144, 144, 144, 16, 32, 64, 5,
6, 6, 6, 0, 0, 32, 160, 160, 168, 168, 176, 5, 7, 7, 6, 0,
0, 128, 128, 128, 136, 144, 160, 192, 5, 6, 6, 6, 0, 0, 248, 136,
136, 136, 136, 248, 5, 6, 6, 6, 0, 0, 248, 136, 136, 8, 16, 32,
5, 6, 6, 6, 0, 0, 192, 0, 8, 8, 16, 224, 4, 3, 3, 6,
0, 4, 32, 144, 64, 3, 3, 3, 6, 0, 4, 224, 160, 224, 5, 5,
5, 6, 0, 1, 72, 168, 144, 144, 104, 5, 7, 7, 6, 0, 0, 80,
0, 112, 8, 120, 136, 120, 4, 8, 8, 6, 1, 255, 96, 144, 144, 224,
144, 144, 224, 128, 5, 5, 5, 6, 0, 0, 112, 128, 96, 136, 112, 5,
6, 6, 6, 0, 255, 136, 136, 152, 232, 136, 128, 5, 5, 5, 6, 0,
0, 120, 160, 144, 136, 112, 5, 7, 7, 6, 0, 254, 48, 72, 136, 136,
240, 128, 128, 5, 8, 8, 6, 0, 254, 120, 136, 136, 136, 120, 8, 8,
112, 5, 5, 5, 6, 0, 1, 56, 32, 32, 160, 64, 4, 3, 3, 6,
0, 3, 16, 208, 16, 4, 8, 8, 6, 0, 255, 16, 0, 48, 16, 16,
16, 144, 96, 3, 3, 3, 6, 0, 4, 160, 64, 160, 5, 7, 7, 6,
0, 0, 32, 112, 160, 160, 168, 112, 32, 5, 7, 7, 6, 0, 0, 64,
64, 224, 64, 224, 64, 120, 5, 7, 7, 6, 0, 0, 112, 0, 176, 200,
136, 136, 136, 5, 7, 7, 6, 0, 0, 80, 0, 112, 136, 136, 136, 112,
5, 7, 7, 6, 0, 255, 176, 200, 136, 136, 240, 128, 128, 5, 7, 7,
6, 0, 255, 104, 152, 136, 136, 120, 8, 8, 5, 6, 6, 6, 0, 0,
112, 136, 248, 136, 136, 112, 5, 3, 3, 6, 0, 2, 88, 168, 208, 5,
5, 5, 6, 0, 0, 112, 136, 136, 80, 216, 5, 7, 7, 6, 0, 0,
80, 0, 136, 136, 136, 152, 104, 5, 7, 7, 6, 0, 0, 248, 128, 64,
32, 64, 128, 248, 5, 5, 5, 6, 0, 0, 248, 80, 80, 80, 152, 5,
7, 7, 6, 0, 0, 248, 0, 136, 80, 32, 80, 136, 5, 7, 7, 6,
0, 255, 136, 136, 136, 136, 120, 8, 112, 5, 6, 6, 6, 0, 0, 8,
240, 32, 248, 32, 32, 5, 5, 5, 6, 0, 0, 248, 64, 120, 72, 136,
5, 5, 5, 6, 0, 0, 248, 168, 248, 136, 136, 5, 5, 5, 6, 0,
1, 32, 0, 248, 0, 32, 0, 0, 0, 6, 0, 0, 6, 10, 10, 6,
0, 254, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252
};

View File

@ -0,0 +1,226 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
Fontname: HD44780_W
Copyright: A.Hardtung, public domain
Capital A Height: 7, '1' Height: 7
Calculated Max Values w= 5 h= 9 x= 2 y= 5 dx= 6 dy= 0 ascent= 8 len= 9
Font Bounding box w= 6 h= 9 x= 0 y=-2
Calculated Min Values x= 0 y=-1 dx= 0 dy= 0
Pure Font ascent = 7 descent=-1
X Font ascent = 7 descent=-1
Max Font ascent = 8 descent=-1
*/
#include <U8glib.h>
const u8g_fntpgm_uint8_t HD44780_W_5x7[3034] U8G_SECTION(".progmem.HD44780_W_5x7") = {
0, 6, 9, 0, 254, 7, 2, 79, 3, 222, 16, 255, 255, 8, 255, 7,
255, 4, 7, 7, 6, 0, 0, 16, 48, 112, 240, 112, 48, 16, 4, 7,
7, 6, 1, 0, 128, 192, 224, 240, 224, 192, 128, 5, 3, 3, 6, 0,
4, 216, 72, 144, 5, 3, 3, 6, 0, 4, 216, 144, 72, 5, 7, 7,
6, 0, 0, 32, 112, 248, 0, 32, 112, 248, 5, 7, 7, 6, 0, 0,
248, 112, 32, 0, 248, 112, 32, 5, 5, 5, 6, 0, 1, 112, 248, 248,
248, 112, 5, 7, 7, 6, 0, 0, 8, 8, 40, 72, 248, 64, 32, 5,
7, 7, 6, 0, 0, 32, 112, 168, 32, 32, 32, 32, 5, 7, 7, 6,
0, 0, 32, 32, 32, 32, 168, 112, 32, 5, 5, 5, 6, 0, 1, 32,
64, 248, 64, 32, 5, 5, 5, 6, 0, 1, 32, 16, 248, 16, 32, 5,
7, 7, 6, 0, 0, 16, 32, 64, 32, 16, 0, 248, 5, 7, 7, 6,
0, 0, 64, 32, 16, 32, 64, 0, 248, 5, 5, 5, 6, 0, 1, 32,
32, 112, 112, 248, 5, 5, 5, 6, 0, 0, 248, 112, 112, 32, 32, 0,
0, 0, 6, 0, 0, 1, 7, 7, 6, 2, 0, 128, 128, 128, 128, 128,
0, 128, 3, 2, 2, 6, 1, 5, 160, 160, 5, 7, 7, 6, 0, 0,
80, 80, 248, 80, 248, 80, 80, 5, 7, 7, 6, 0, 0, 32, 120, 160,
112, 40, 240, 32, 5, 7, 7, 6, 0, 0, 192, 200, 16, 32, 64, 152,
24, 5, 7, 7, 6, 0, 0, 96, 144, 160, 64, 168, 144, 104, 2, 3,
3, 6, 1, 4, 192, 64, 128, 3, 7, 7, 6, 1, 0, 32, 64, 128,
128, 128, 64, 32, 3, 7, 7, 6, 1, 0, 128, 64, 32, 32, 32, 64,
128, 5, 5, 5, 6, 0, 1, 32, 168, 112, 168, 32, 5, 5, 5, 6,
0, 1, 32, 32, 248, 32, 32, 2, 3, 3, 6, 2, 255, 192, 64, 128,
5, 1, 1, 6, 0, 3, 248, 2, 2, 2, 6, 2, 0, 192, 192, 5,
5, 5, 6, 0, 1, 8, 16, 32, 64, 128, 5, 7, 7, 6, 0, 0,
112, 136, 152, 168, 200, 136, 112, 3, 7, 7, 6, 1, 0, 64, 192, 64,
64, 64, 64, 224, 5, 7, 7, 6, 0, 0, 112, 136, 8, 112, 128, 128,
248, 5, 7, 7, 6, 0, 0, 248, 16, 32, 16, 8, 8, 240, 5, 7,
7, 6, 0, 0, 16, 48, 80, 144, 248, 16, 16, 5, 7, 7, 6, 0,
0, 248, 128, 240, 8, 8, 136, 112, 5, 7, 7, 6, 0, 0, 48, 64,
128, 240, 136, 136, 112, 5, 7, 7, 6, 0, 0, 248, 8, 16, 32, 32,
32, 32, 5, 7, 7, 6, 0, 0, 112, 136, 136, 112, 136, 136, 112, 5,
7, 7, 6, 0, 0, 112, 136, 136, 120, 8, 16, 96, 2, 5, 5, 6,
2, 0, 192, 192, 0, 192, 192, 2, 6, 6, 6, 2, 255, 192, 192, 0,
192, 64, 128, 4, 7, 7, 6, 0, 0, 16, 32, 64, 128, 64, 32, 16,
5, 3, 3, 6, 0, 2, 248, 0, 248, 4, 7, 7, 6, 1, 0, 128,
64, 32, 16, 32, 64, 128, 5, 7, 7, 6, 0, 0, 112, 136, 8, 16,
32, 0, 32, 5, 6, 6, 6, 0, 0, 112, 136, 8, 104, 168, 112, 5,
7, 7, 6, 0, 0, 112, 136, 136, 248, 136, 136, 136, 5, 7, 7, 6,
0, 0, 240, 136, 136, 240, 136, 136, 240, 5, 7, 7, 6, 0, 0, 112,
136, 128, 128, 128, 136, 112, 5, 7, 7, 6, 0, 0, 224, 144, 136, 136,
136, 144, 224, 5, 7, 7, 6, 0, 0, 248, 128, 128, 240, 128, 128, 248,
5, 7, 7, 6, 0, 0, 248, 128, 128, 240, 128, 128, 128, 5, 7, 7,
6, 0, 0, 112, 136, 128, 184, 136, 136, 112, 5, 7, 7, 6, 0, 0,
136, 136, 136, 248, 136, 136, 136, 1, 7, 7, 6, 2, 0, 128, 128, 128,
128, 128, 128, 128, 5, 7, 7, 6, 0, 0, 56, 16, 16, 16, 16, 144,
96, 5, 7, 7, 6, 0, 0, 136, 144, 160, 192, 160, 144, 136, 5, 7,
7, 6, 0, 0, 128, 128, 128, 128, 128, 128, 248, 5, 7, 7, 6, 0,
0, 136, 216, 168, 136, 136, 136, 136, 5, 7, 7, 6, 0, 0, 136, 136,
200, 168, 152, 136, 136, 5, 7, 7, 6, 0, 0, 112, 136, 136, 136, 136,
136, 112, 5, 7, 7, 6, 0, 0, 240, 136, 136, 240, 128, 128, 128, 5,
7, 7, 6, 0, 0, 112, 136, 136, 136, 168, 144, 104, 5, 7, 7, 6,
0, 0, 240, 136, 136, 240, 160, 144, 136, 5, 7, 7, 6, 0, 0, 120,
128, 128, 112, 8, 8, 240, 5, 7, 7, 6, 0, 0, 248, 32, 32, 32,
32, 32, 32, 5, 7, 7, 6, 0, 0, 136, 136, 136, 136, 136, 136, 112,
5, 7, 7, 6, 0, 0, 136, 136, 136, 136, 136, 80, 32, 5, 7, 7,
6, 0, 0, 136, 136, 136, 136, 136, 168, 80, 5, 7, 7, 6, 0, 0,
136, 136, 80, 32, 80, 136, 136, 5, 7, 7, 6, 0, 0, 136, 136, 136,
80, 32, 32, 32, 5, 7, 7, 6, 0, 0, 248, 8, 16, 32, 64, 128,
248, 3, 7, 7, 6, 1, 0, 224, 128, 128, 128, 128, 128, 224, 5, 5,
5, 6, 0, 1, 128, 64, 32, 16, 8, 3, 7, 7, 6, 1, 0, 224,
32, 32, 32, 32, 32, 224, 5, 3, 3, 6, 0, 4, 32, 80, 136, 5,
1, 1, 6, 0, 0, 248, 2, 2, 2, 6, 2, 5, 128, 64, 5, 5,
5, 6, 0, 0, 112, 8, 120, 136, 120, 5, 7, 7, 6, 0, 0, 128,
128, 176, 200, 136, 136, 240, 5, 5, 5, 6, 0, 0, 112, 128, 128, 136,
112, 5, 7, 7, 6, 0, 0, 8, 8, 104, 152, 136, 136, 120, 5, 5,
5, 6, 0, 0, 112, 136, 248, 128, 112, 5, 7, 7, 6, 0, 0, 48,
72, 224, 64, 64, 64, 64, 5, 6, 6, 6, 0, 255, 112, 136, 136, 120,
8, 112, 5, 7, 7, 6, 0, 0, 128, 128, 176, 200, 136, 136, 136, 1,
7, 7, 6, 2, 0, 128, 0, 128, 128, 128, 128, 128, 3, 8, 8, 6,
1, 255, 32, 0, 32, 32, 32, 32, 160, 64, 4, 7, 7, 6, 0, 0,
128, 128, 144, 160, 192, 160, 144, 3, 7, 7, 6, 1, 0, 192, 64, 64,
64, 64, 64, 224, 5, 5, 5, 6, 0, 0, 208, 168, 168, 168, 168, 5,
5, 5, 6, 0, 0, 176, 200, 136, 136, 136, 5, 5, 5, 6, 0, 0,
112, 136, 136, 136, 112, 5, 6, 6, 6, 0, 255, 240, 136, 136, 240, 128,
128, 5, 6, 6, 6, 0, 255, 120, 136, 136, 120, 8, 8, 5, 5, 5,
6, 0, 0, 176, 200, 128, 128, 128, 5, 5, 5, 6, 0, 0, 112, 128,
112, 8, 240, 5, 7, 7, 6, 0, 0, 64, 64, 224, 64, 64, 72, 48,
5, 5, 5, 6, 0, 0, 136, 136, 136, 152, 104, 5, 5, 5, 6, 0,
0, 136, 136, 136, 80, 32, 5, 5, 5, 6, 0, 0, 136, 136, 168, 168,
80, 5, 5, 5, 6, 0, 0, 136, 80, 32, 80, 136, 5, 6, 6, 6,
0, 255, 136, 136, 136, 120, 8, 112, 5, 5, 5, 6, 0, 0, 248, 16,
32, 64, 248, 3, 7, 7, 6, 1, 0, 32, 64, 64, 128, 64, 64, 32,
1, 7, 7, 6, 2, 0, 128, 128, 128, 128, 128, 128, 128, 3, 7, 7,
6, 1, 0, 128, 64, 64, 32, 64, 64, 128, 5, 6, 6, 6, 0, 1,
8, 40, 72, 248, 64, 32, 5, 7, 7, 6, 0, 0, 32, 80, 136, 136,
136, 136, 248, 5, 7, 7, 6, 0, 0, 248, 136, 128, 240, 136, 136, 240,
5, 8, 8, 6, 0, 255, 120, 40, 40, 40, 72, 136, 248, 136, 5, 7,
7, 6, 0, 0, 168, 168, 168, 112, 168, 168, 168, 5, 7, 7, 6, 0,
0, 240, 8, 8, 112, 8, 8, 240, 5, 7, 7, 6, 0, 0, 136, 136,
152, 168, 200, 136, 136, 5, 8, 8, 6, 0, 0, 80, 32, 136, 152, 168,
168, 200, 136, 5, 7, 7, 6, 0, 0, 120, 40, 40, 40, 40, 168, 72,
5, 7, 7, 6, 0, 0, 248, 136, 136, 136, 136, 136, 136, 5, 7, 7,
6, 0, 0, 136, 136, 136, 80, 32, 64, 128, 5, 8, 8, 6, 0, 255,
136, 136, 136, 136, 136, 136, 248, 8, 5, 7, 7, 6, 0, 0, 136, 136,
136, 120, 8, 8, 8, 5, 7, 7, 6, 0, 0, 168, 168, 168, 168, 168,
168, 248, 5, 8, 8, 6, 0, 255, 168, 168, 168, 168, 168, 168, 248, 8,
5, 7, 7, 6, 0, 0, 192, 64, 64, 112, 72, 72, 112, 5, 7, 7,
6, 0, 0, 136, 136, 136, 200, 168, 168, 200, 5, 7, 7, 6, 0, 0,
112, 136, 40, 80, 8, 136, 112, 5, 5, 5, 6, 0, 0, 64, 160, 144,
144, 104, 5, 7, 7, 6, 0, 0, 32, 48, 40, 40, 32, 224, 224, 5,
7, 7, 6, 0, 0, 248, 136, 128, 128, 128, 128, 128, 5, 5, 5, 6,
0, 0, 248, 80, 80, 80, 152, 5, 7, 7, 6, 0, 0, 248, 128, 64,
32, 64, 128, 248, 5, 5, 5, 6, 0, 0, 120, 144, 144, 144, 96, 5,
7, 7, 6, 0, 0, 48, 40, 56, 40, 200, 216, 24, 5, 6, 6, 6,
0, 0, 8, 112, 160, 32, 32, 16, 5, 6, 6, 6, 0, 1, 32, 112,
112, 112, 248, 32, 5, 7, 7, 6, 0, 0, 112, 136, 136, 248, 136, 136,
112, 5, 5, 5, 6, 0, 0, 112, 136, 136, 80, 216, 5, 7, 7, 6,
0, 0, 48, 72, 32, 80, 136, 136, 112, 5, 3, 3, 6, 0, 2, 88,
168, 208, 5, 6, 6, 6, 0, 0, 80, 248, 248, 248, 112, 32, 5, 5,
5, 6, 0, 0, 112, 128, 96, 136, 112, 5, 7, 7, 6, 0, 0, 112,
136, 136, 136, 136, 136, 136, 5, 7, 7, 6, 0, 0, 216, 216, 216, 216,
216, 216, 216, 1, 7, 7, 6, 2, 0, 128, 0, 128, 128, 128, 128, 128,
5, 7, 7, 6, 0, 0, 32, 112, 160, 160, 168, 112, 32, 5, 7, 7,
6, 0, 0, 48, 64, 64, 224, 64, 80, 168, 5, 5, 5, 6, 0, 0,
136, 112, 80, 112, 136, 5, 7, 7, 6, 0, 0, 136, 80, 248, 32, 248,
32, 32, 1, 7, 7, 6, 2, 0, 128, 128, 128, 0, 128, 128, 128, 5,
8, 8, 6, 0, 0, 48, 72, 32, 80, 80, 32, 144, 96, 5, 7, 7,
6, 0, 0, 24, 32, 32, 112, 32, 32, 192, 5, 7, 7, 6, 0, 0,
248, 136, 184, 184, 184, 136, 248, 5, 7, 7, 6, 0, 0, 112, 8, 120,
136, 120, 0, 248, 5, 5, 5, 6, 0, 1, 40, 80, 160, 80, 40, 5,
7, 7, 6, 0, 0, 144, 168, 168, 232, 168, 168, 144, 5, 7, 7, 6,
0, 0, 120, 136, 136, 120, 40, 72, 136, 5, 7, 7, 6, 0, 0, 248,
136, 168, 136, 152, 168, 248, 2, 3, 3, 6, 2, 4, 64, 128, 192, 4,
5, 5, 6, 0, 3, 96, 144, 144, 144, 96, 5, 7, 7, 6, 0, 0,
32, 32, 248, 32, 32, 0, 248, 4, 5, 5, 6, 0, 3, 96, 144, 32,
64, 240, 3, 5, 5, 6, 0, 3, 224, 32, 224, 32, 224, 5, 8, 8,
6, 0, 0, 224, 144, 224, 128, 144, 184, 144, 24, 5, 8, 8, 6, 0,
255, 136, 136, 136, 136, 152, 232, 128, 128, 5, 7, 7, 6, 0, 0, 120,
152, 152, 120, 24, 24, 24, 2, 2, 2, 6, 2, 2, 192, 192, 5, 5,
5, 6, 0, 0, 80, 136, 168, 168, 80, 3, 5, 5, 6, 0, 3, 64,
192, 64, 64, 224, 5, 7, 7, 6, 0, 0, 112, 136, 136, 136, 112, 0,
248, 5, 5, 5, 6, 0, 1, 160, 80, 40, 80, 160, 5, 7, 7, 6,
0, 0, 136, 144, 168, 88, 184, 8, 8, 5, 7, 7, 6, 0, 0, 136,
144, 184, 72, 152, 32, 56, 5, 8, 8, 6, 0, 0, 192, 64, 192, 72,
216, 56, 8, 8, 5, 7, 7, 6, 0, 0, 32, 0, 32, 64, 128, 136,
112, 5, 8, 8, 6, 0, 0, 64, 32, 32, 80, 136, 248, 136, 136, 5,
8, 8, 6, 0, 0, 16, 32, 32, 80, 136, 248, 136, 136, 5, 8, 8,
6, 0, 0, 32, 80, 0, 112, 136, 248, 136, 136, 5, 8, 8, 6, 0,
0, 104, 144, 0, 112, 136, 248, 136, 136, 5, 8, 8, 6, 0, 0, 80,
0, 32, 80, 136, 248, 136, 136, 5, 8, 8, 6, 0, 0, 32, 80, 32,
112, 136, 248, 136, 136, 5, 7, 7, 6, 0, 0, 56, 96, 160, 184, 224,
160, 184, 5, 8, 8, 6, 0, 255, 112, 136, 128, 128, 136, 112, 32, 96,
5, 8, 8, 6, 0, 0, 64, 32, 0, 248, 128, 240, 128, 248, 5, 8,
8, 6, 0, 0, 8, 16, 0, 248, 128, 240, 128, 248, 5, 8, 8, 6,
0, 0, 32, 80, 0, 248, 128, 240, 128, 248, 5, 7, 7, 6, 0, 0,
80, 0, 248, 128, 240, 128, 248, 3, 8, 8, 6, 1, 0, 128, 64, 0,
224, 64, 64, 64, 224, 3, 8, 8, 6, 1, 0, 32, 64, 0, 224, 64,
64, 64, 224, 3, 8, 8, 6, 1, 0, 64, 160, 0, 224, 64, 64, 64,
224, 3, 7, 7, 6, 1, 0, 160, 0, 224, 64, 64, 64, 224, 5, 7,
7, 6, 0, 0, 112, 72, 72, 232, 72, 72, 112, 5, 8, 8, 6, 0,
0, 104, 144, 0, 136, 200, 168, 152, 136, 5, 8, 8, 6, 0, 0, 64,
32, 112, 136, 136, 136, 136, 112, 5, 8, 8, 6, 0, 0, 16, 32, 112,
136, 136, 136, 136, 112, 5, 8, 8, 6, 0, 0, 32, 80, 0, 112, 136,
136, 136, 112, 5, 8, 8, 6, 0, 0, 104, 144, 0, 112, 136, 136, 136,
112, 5, 8, 8, 6, 0, 0, 80, 0, 112, 136, 136, 136, 136, 112, 5,
5, 5, 6, 0, 1, 136, 80, 32, 80, 136, 5, 7, 7, 6, 0, 0,
112, 32, 112, 168, 112, 32, 112, 5, 8, 8, 6, 0, 0, 64, 32, 136,
136, 136, 136, 136, 112, 5, 8, 8, 6, 0, 0, 16, 32, 136, 136, 136,
136, 136, 112, 5, 8, 8, 6, 0, 0, 32, 80, 0, 136, 136, 136, 136,
112, 5, 8, 8, 6, 0, 0, 80, 0, 136, 136, 136, 136, 136, 112, 5,
8, 8, 6, 0, 0, 16, 32, 136, 80, 32, 32, 32, 32, 5, 8, 8,
6, 0, 0, 192, 64, 112, 72, 72, 112, 64, 224, 5, 7, 7, 6, 0,
0, 48, 72, 72, 112, 72, 72, 176, 5, 8, 8, 6, 0, 0, 64, 32,
0, 112, 8, 120, 136, 120, 5, 8, 8, 6, 0, 0, 16, 32, 0, 112,
8, 120, 136, 120, 5, 8, 8, 6, 0, 0, 32, 80, 0, 112, 8, 120,
136, 120, 5, 8, 8, 6, 0, 0, 104, 144, 0, 112, 8, 120, 136, 120,
5, 7, 7, 6, 0, 0, 80, 0, 112, 8, 120, 136, 120, 5, 8, 8,
6, 0, 0, 32, 80, 32, 112, 8, 120, 136, 120, 5, 6, 6, 6, 0,
0, 208, 40, 120, 160, 168, 80, 5, 6, 6, 6, 0, 255, 112, 128, 136,
112, 32, 96, 5, 8, 8, 6, 0, 0, 64, 32, 0, 112, 136, 248, 128,
112, 5, 8, 8, 6, 0, 0, 16, 32, 0, 112, 136, 248, 128, 112, 5,
8, 8, 6, 0, 0, 32, 80, 0, 112, 136, 248, 128, 112, 5, 7, 7,
6, 0, 0, 80, 0, 112, 136, 248, 128, 112, 3, 8, 8, 6, 1, 0,
128, 64, 0, 64, 192, 64, 64, 224, 3, 8, 8, 6, 1, 0, 32, 64,
0, 64, 192, 64, 64, 224, 3, 8, 8, 6, 1, 0, 64, 160, 0, 64,
192, 64, 64, 224, 3, 7, 7, 6, 1, 0, 160, 0, 64, 192, 64, 64,
224, 5, 7, 7, 6, 0, 0, 160, 64, 160, 16, 120, 136, 112, 5, 8,
8, 6, 0, 0, 104, 144, 0, 176, 200, 136, 136, 136, 5, 8, 8, 6,
0, 0, 64, 32, 0, 112, 136, 136, 136, 112, 5, 8, 8, 6, 0, 0,
16, 32, 0, 112, 136, 136, 136, 112, 5, 8, 8, 6, 0, 0, 32, 80,
0, 112, 136, 136, 136, 112, 5, 8, 8, 6, 0, 0, 104, 144, 0, 112,
136, 136, 136, 112, 5, 7, 7, 6, 0, 0, 80, 0, 112, 136, 136, 136,
112, 5, 5, 5, 6, 0, 1, 32, 0, 248, 0, 32, 5, 7, 7, 6,
0, 0, 16, 32, 112, 168, 112, 32, 64, 5, 8, 8, 6, 0, 0, 64,
32, 0, 136, 136, 136, 152, 104, 5, 8, 8, 6, 0, 0, 16, 32, 0,
136, 136, 136, 152, 104, 5, 8, 8, 6, 0, 0, 32, 80, 0, 136, 136,
136, 152, 104, 5, 7, 7, 6, 0, 0, 80, 0, 136, 136, 136, 152, 104,
5, 9, 9, 6, 0, 255, 16, 32, 0, 136, 136, 136, 248, 8, 112, 4,
7, 7, 6, 1, 0, 192, 64, 96, 80, 96, 64, 224, 5, 8, 8, 6,
0, 255, 80, 0, 136, 136, 136, 248, 8, 112
};

View File

@ -0,0 +1,286 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
Fontname: ISO10646-1
Copyright: A.Hardtung, public domain
Capital A Height: 7, '1' Height: 7
Calculated Max Values w= 5 h= 9 x= 2 y= 7 dx= 6 dy= 0 ascent= 8 len= 9
Font Bounding box w= 6 h= 9 x= 0 y=-2
Calculated Min Values x= 0 y=-1 dx= 0 dy= 0
Pure Font ascent = 7 descent=-1
X Font ascent = 7 descent=-1
Max Font ascent = 8 descent=-1
*/
#include <U8glib.h>
#if defined(__AVR__) && ENABLED(NOT_EXTENDED_ISO10646_1_5X7)
//
// Reduced font (only symbols 32 - 127) - About 1400 bytes smaller
//
const u8g_fntpgm_uint8_t ISO10646_1_5x7[] U8G_SECTION(".progmem.ISO10646_1_5x7") = {
0,6,9,0,254,7,1,146,3,33,32,127,255,7,255,7,
255,0,0,0,6,0,0,1,7,7,6,2,0,128,128,128,
128,128,0,128,3,2,2,6,1,5,160,160,5,7,7,6,
0,0,80,80,248,80,248,80,80,5,7,7,6,0,0,32,
120,160,112,40,240,32,5,7,7,6,0,0,192,200,16,32,
64,152,24,5,7,7,6,0,0,96,144,160,64,168,144,104,
2,3,3,6,1,4,192,64,128,3,7,7,6,1,0,32,
64,128,128,128,64,32,3,7,7,6,1,0,128,64,32,32,
32,64,128,5,5,5,6,0,1,32,168,112,168,32,5,5,
5,6,0,1,32,32,248,32,32,2,3,3,6,2,255,192,
64,128,5,1,1,6,0,3,248,2,2,2,6,2,0,192,
192,5,5,5,6,0,1,8,16,32,64,128,5,7,7,6,
0,0,112,136,136,136,136,136,112,3,7,7,6,1,0,64,
192,64,64,64,64,224,5,7,7,6,0,0,112,136,8,112,
128,128,248,5,7,7,6,0,0,248,16,32,16,8,8,240,
5,7,7,6,0,0,16,48,80,144,248,16,16,5,7,7,
6,0,0,248,128,240,8,8,136,112,5,7,7,6,0,0,
112,128,128,240,136,136,112,5,7,7,6,0,0,248,8,16,
32,32,32,32,5,7,7,6,0,0,112,136,136,112,136,136,
112,5,7,7,6,0,0,112,136,136,120,8,8,112,2,5,
5,6,2,0,192,192,0,192,192,2,6,6,6,2,255,192,
192,0,192,64,128,4,7,7,6,0,0,16,32,64,128,64,
32,16,5,3,3,6,0,2,248,0,248,4,7,7,6,1,
0,128,64,32,16,32,64,128,5,7,7,6,0,0,112,136,
8,16,32,0,32,5,7,7,6,0,0,112,136,8,104,168,
168,112,5,7,7,6,0,0,112,136,136,248,136,136,136,5,
7,7,6,0,0,240,136,136,240,136,136,240,5,7,7,6,
0,0,112,136,128,128,128,136,112,5,7,7,6,0,0,240,
136,136,136,136,136,240,5,7,7,6,0,0,248,128,128,240,
128,128,248,5,7,7,6,0,0,248,128,128,240,128,128,128,
5,7,7,6,0,0,112,136,128,184,136,136,112,5,7,7,
6,0,0,136,136,136,248,136,136,136,1,7,7,6,2,0,
128,128,128,128,128,128,128,5,7,7,6,0,0,56,16,16,
16,16,144,96,5,7,7,6,0,0,136,144,160,192,160,144,
136,5,7,7,6,0,0,128,128,128,128,128,128,248,5,7,
7,6,0,0,136,216,168,136,136,136,136,5,7,7,6,0,
0,136,136,200,168,152,136,136,5,7,7,6,0,0,112,136,
136,136,136,136,112,5,7,7,6,0,0,240,136,136,240,128,
128,128,5,7,7,6,0,0,112,136,136,136,168,144,104,5,
7,7,6,0,0,240,136,136,240,160,144,136,5,7,7,6,
0,0,120,128,128,112,8,8,240,5,7,7,6,0,0,248,
32,32,32,32,32,32,5,7,7,6,0,0,136,136,136,136,
136,136,112,5,7,7,6,0,0,136,136,136,136,136,80,32,
5,7,7,6,0,0,136,136,136,136,136,168,80,5,7,7,
6,0,0,136,136,80,32,80,136,136,5,7,7,6,0,0,
136,136,136,80,32,32,32,5,7,7,6,0,0,248,8,16,
32,64,128,248,3,7,7,6,1,0,224,128,128,128,128,128,
224,5,5,5,6,0,1,128,64,32,16,8,3,7,7,6,
1,0,224,32,32,32,32,32,224,5,3,3,6,0,4,32,
80,136,5,1,1,6,0,0,248,2,2,2,6,2,5,128,
64,5,5,5,6,0,0,112,8,120,136,120,5,7,7,6,
0,0,128,128,176,200,136,136,240,5,5,5,6,0,0,112,
128,128,136,112,5,7,7,6,0,0,8,8,104,152,136,136,
120,5,5,5,6,0,0,112,136,248,128,112,5,7,7,6,
0,0,48,72,224,64,64,64,64,5,6,6,6,0,255,112,
136,136,120,8,112,5,7,7,6,0,0,128,128,176,200,136,
136,136,1,7,7,6,2,0,128,0,128,128,128,128,128,3,
8,8,6,1,255,32,0,32,32,32,32,160,64,4,7,7,
6,0,0,128,128,144,160,192,160,144,3,7,7,6,1,0,
192,64,64,64,64,64,224,5,5,5,6,0,0,208,168,168,
168,168,5,5,5,6,0,0,176,200,136,136,136,5,5,5,
6,0,0,112,136,136,136,112,5,6,6,6,0,255,240,136,
136,240,128,128,5,6,6,6,0,255,120,136,136,120,8,8,
5,5,5,6,0,0,176,200,128,128,128,5,5,5,6,0,
0,112,128,112,8,240,4,7,7,6,0,0,64,64,224,64,
64,64,48,5,5,5,6,0,0,136,136,136,152,104,5,5,
5,6,0,0,136,136,136,80,32,5,5,5,6,0,0,136,
136,168,168,80,5,5,5,6,0,0,136,80,32,80,136,5,
6,6,6,0,255,136,136,136,120,8,112,5,5,5,6,0,
0,248,16,32,64,248,3,7,7,6,1,0,32,64,64,128,
64,64,32,1,7,7,6,2,0,128,128,128,128,128,128,128,
3,7,7,6,1,0,128,64,64,32,64,64,128,5,2,2,
6,0,2,104,144,0,0,0,6,0,0};
#else
//
// Extended (original) font (symbols 32 - 255)
//
const u8g_fntpgm_uint8_t ISO10646_1_5x7[] U8G_SECTION(".progmem.ISO10646_1_5x7") = {
0, 6, 9, 0, 254, 7, 1, 146, 3, 33, 32, 255, 255, 8, 255, 7,
255, 0, 0, 0, 6, 0, 0, 1, 7, 7, 6, 2, 0, 128, 128, 128,
128, 128, 0, 128, 3, 2, 2, 6, 1, 5, 160, 160, 5, 7, 7, 6,
0, 0, 80, 80, 248, 80, 248, 80, 80, 5, 7, 7, 6, 0, 0, 32,
120, 160, 112, 40, 240, 32, 5, 7, 7, 6, 0, 0, 192, 200, 16, 32,
64, 152, 24, 5, 7, 7, 6, 0, 0, 96, 144, 160, 64, 168, 144, 104,
2, 3, 3, 6, 1, 4, 192, 64, 128, 3, 7, 7, 6, 1, 0, 32,
64, 128, 128, 128, 64, 32, 3, 7, 7, 6, 1, 0, 128, 64, 32, 32,
32, 64, 128, 5, 5, 5, 6, 0, 1, 32, 168, 112, 168, 32, 5, 5,
5, 6, 0, 1, 32, 32, 248, 32, 32, 2, 3, 3, 6, 2, 255, 192,
64, 128, 5, 1, 1, 6, 0, 3, 248, 2, 2, 2, 6, 2, 0, 192,
192, 5, 5, 5, 6, 0, 1, 8, 16, 32, 64, 128, 5, 7, 7, 6,
0, 0, 112, 136, 136, 136, 136, 136, 112, 3, 7, 7, 6, 1, 0, 64,
192, 64, 64, 64, 64, 224, 5, 7, 7, 6, 0, 0, 112, 136, 8, 112,
128, 128, 248, 5, 7, 7, 6, 0, 0, 248, 16, 32, 16, 8, 8, 240,
5, 7, 7, 6, 0, 0, 16, 48, 80, 144, 248, 16, 16, 5, 7, 7,
6, 0, 0, 248, 128, 240, 8, 8, 136, 112, 5, 7, 7, 6, 0, 0,
112, 128, 128, 240, 136, 136, 112, 5, 7, 7, 6, 0, 0, 248, 8, 16,
32, 32, 32, 32, 5, 7, 7, 6, 0, 0, 112, 136, 136, 112, 136, 136,
112, 5, 7, 7, 6, 0, 0, 112, 136, 136, 120, 8, 8, 112, 2, 5,
5, 6, 2, 0, 192, 192, 0, 192, 192, 2, 6, 6, 6, 2, 255, 192,
192, 0, 192, 64, 128, 4, 7, 7, 6, 0, 0, 16, 32, 64, 128, 64,
32, 16, 5, 3, 3, 6, 0, 2, 248, 0, 248, 4, 7, 7, 6, 1,
0, 128, 64, 32, 16, 32, 64, 128, 5, 7, 7, 6, 0, 0, 112, 136,
8, 16, 32, 0, 32, 5, 7, 7, 6, 0, 0, 112, 136, 8, 104, 168,
168, 112, 5, 7, 7, 6, 0, 0, 112, 136, 136, 248, 136, 136, 136, 5,
7, 7, 6, 0, 0, 240, 136, 136, 240, 136, 136, 240, 5, 7, 7, 6,
0, 0, 112, 136, 128, 128, 128, 136, 112, 5, 7, 7, 6, 0, 0, 240,
136, 136, 136, 136, 136, 240, 5, 7, 7, 6, 0, 0, 248, 128, 128, 240,
128, 128, 248, 5, 7, 7, 6, 0, 0, 248, 128, 128, 240, 128, 128, 128,
5, 7, 7, 6, 0, 0, 112, 136, 128, 184, 136, 136, 112, 5, 7, 7,
6, 0, 0, 136, 136, 136, 248, 136, 136, 136, 1, 7, 7, 6, 2, 0,
128, 128, 128, 128, 128, 128, 128, 5, 7, 7, 6, 0, 0, 56, 16, 16,
16, 16, 144, 96, 5, 7, 7, 6, 0, 0, 136, 144, 160, 192, 160, 144,
136, 5, 7, 7, 6, 0, 0, 128, 128, 128, 128, 128, 128, 248, 5, 7,
7, 6, 0, 0, 136, 216, 168, 136, 136, 136, 136, 5, 7, 7, 6, 0,
0, 136, 136, 200, 168, 152, 136, 136, 5, 7, 7, 6, 0, 0, 112, 136,
136, 136, 136, 136, 112, 5, 7, 7, 6, 0, 0, 240, 136, 136, 240, 128,
128, 128, 5, 7, 7, 6, 0, 0, 112, 136, 136, 136, 168, 144, 104, 5,
7, 7, 6, 0, 0, 240, 136, 136, 240, 160, 144, 136, 5, 7, 7, 6,
0, 0, 120, 128, 128, 112, 8, 8, 240, 5, 7, 7, 6, 0, 0, 248,
32, 32, 32, 32, 32, 32, 5, 7, 7, 6, 0, 0, 136, 136, 136, 136,
136, 136, 112, 5, 7, 7, 6, 0, 0, 136, 136, 136, 136, 136, 80, 32,
5, 7, 7, 6, 0, 0, 136, 136, 136, 136, 136, 168, 80, 5, 7, 7,
6, 0, 0, 136, 136, 80, 32, 80, 136, 136, 5, 7, 7, 6, 0, 0,
136, 136, 136, 80, 32, 32, 32, 5, 7, 7, 6, 0, 0, 248, 8, 16,
32, 64, 128, 248, 3, 7, 7, 6, 1, 0, 224, 128, 128, 128, 128, 128,
224, 5, 5, 5, 6, 0, 1, 128, 64, 32, 16, 8, 3, 7, 7, 6,
1, 0, 224, 32, 32, 32, 32, 32, 224, 5, 3, 3, 6, 0, 4, 32,
80, 136, 5, 1, 1, 6, 0, 0, 248, 2, 2, 2, 6, 2, 5, 128,
64, 5, 5, 5, 6, 0, 0, 112, 8, 120, 136, 120, 5, 7, 7, 6,
0, 0, 128, 128, 176, 200, 136, 136, 240, 5, 5, 5, 6, 0, 0, 112,
128, 128, 136, 112, 5, 7, 7, 6, 0, 0, 8, 8, 104, 152, 136, 136,
120, 5, 5, 5, 6, 0, 0, 112, 136, 248, 128, 112, 5, 7, 7, 6,
0, 0, 48, 72, 224, 64, 64, 64, 64, 5, 6, 6, 6, 0, 255, 112,
136, 136, 120, 8, 112, 5, 7, 7, 6, 0, 0, 128, 128, 176, 200, 136,
136, 136, 1, 7, 7, 6, 2, 0, 128, 0, 128, 128, 128, 128, 128, 3,
8, 8, 6, 1, 255, 32, 0, 32, 32, 32, 32, 160, 64, 4, 7, 7,
6, 0, 0, 128, 128, 144, 160, 192, 160, 144, 3, 7, 7, 6, 1, 0,
192, 64, 64, 64, 64, 64, 224, 5, 5, 5, 6, 0, 0, 208, 168, 168,
168, 168, 5, 5, 5, 6, 0, 0, 176, 200, 136, 136, 136, 5, 5, 5,
6, 0, 0, 112, 136, 136, 136, 112, 5, 6, 6, 6, 0, 255, 240, 136,
136, 240, 128, 128, 5, 6, 6, 6, 0, 255, 120, 136, 136, 120, 8, 8,
5, 5, 5, 6, 0, 0, 176, 200, 128, 128, 128, 5, 5, 5, 6, 0,
0, 112, 128, 112, 8, 240, 4, 7, 7, 6, 0, 0, 64, 64, 224, 64,
64, 64, 48, 5, 5, 5, 6, 0, 0, 136, 136, 136, 152, 104, 5, 5,
5, 6, 0, 0, 136, 136, 136, 80, 32, 5, 5, 5, 6, 0, 0, 136,
136, 168, 168, 80, 5, 5, 5, 6, 0, 0, 136, 80, 32, 80, 136, 5,
6, 6, 6, 0, 255, 136, 136, 136, 120, 8, 112, 5, 5, 5, 6, 0,
0, 248, 16, 32, 64, 248, 3, 7, 7, 6, 1, 0, 32, 64, 64, 128,
64, 64, 32, 1, 7, 7, 6, 2, 0, 128, 128, 128, 128, 128, 128, 128,
3, 7, 7, 6, 1, 0, 128, 64, 64, 32, 64, 64, 128, 5, 2, 2,
6, 0, 2, 104, 144, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0,
0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0,
6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0,
0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0,
0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0,
6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0,
0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0,
0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0,
6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0,
0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0,
0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0,
6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0,
0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0,
0, 1, 7, 7, 6, 2, 0, 128, 0, 128, 128, 128, 128, 128, 5, 7,
7, 6, 0, 0, 32, 112, 168, 160, 168, 112, 32, 5, 7, 7, 6, 0,
0, 48, 64, 64, 224, 64, 80, 168, 5, 5, 5, 6, 0, 0, 136, 112,
80, 112, 136, 5, 7, 7, 6, 0, 0, 136, 80, 32, 248, 32, 248, 32,
1, 7, 7, 6, 2, 0, 128, 128, 128, 0, 128, 128, 128, 5, 8, 8,
6, 0, 0, 48, 72, 32, 80, 80, 32, 144, 96, 3, 1, 1, 6, 1,
7, 160, 5, 7, 7, 6, 0, 0, 248, 136, 184, 184, 184, 136, 248, 5,
7, 7, 6, 0, 1, 112, 8, 120, 136, 120, 0, 248, 5, 5, 5, 6,
0, 1, 40, 80, 160, 80, 40, 5, 3, 3, 6, 0, 1, 248, 8, 8,
2, 2, 2, 6, 2, 6, 64, 128, 5, 7, 7, 6, 0, 0, 248, 136,
168, 136, 152, 168, 248, 5, 1, 1, 6, 0, 6, 248, 4, 4, 4, 6,
0, 3, 96, 144, 144, 96, 5, 7, 7, 6, 0, 0, 32, 32, 248, 32,
32, 0, 248, 4, 5, 5, 6, 0, 3, 96, 144, 32, 64, 240, 3, 5,
5, 6, 0, 3, 224, 32, 224, 32, 224, 2, 2, 2, 6, 2, 6, 64,
128, 5, 8, 8, 6, 0, 255, 136, 136, 136, 136, 152, 232, 128, 128, 5,
7, 7, 6, 0, 0, 120, 152, 152, 120, 24, 24, 24, 2, 2, 2, 6,
2, 2, 192, 192, 2, 2, 2, 6, 2, 255, 64, 128, 3, 5, 5, 6,
0, 3, 64, 192, 64, 64, 224, 5, 7, 7, 6, 0, 1, 112, 136, 136,
136, 112, 0, 248, 5, 5, 5, 6, 0, 1, 160, 80, 40, 80, 160, 5,
7, 7, 6, 0, 0, 136, 144, 168, 88, 184, 8, 8, 5, 7, 7, 6,
0, 0, 136, 144, 184, 72, 152, 32, 56, 5, 8, 8, 6, 0, 0, 192,
64, 192, 72, 216, 56, 8, 8, 5, 7, 7, 6, 0, 0, 32, 0, 32,
64, 128, 136, 112, 5, 8, 8, 6, 0, 0, 64, 32, 0, 112, 136, 248,
136, 136, 5, 8, 8, 6, 0, 0, 16, 32, 0, 112, 136, 248, 136, 136,
5, 8, 8, 6, 0, 0, 32, 80, 0, 112, 136, 248, 136, 136, 5, 8,
8, 6, 0, 0, 104, 144, 0, 112, 136, 248, 136, 136, 5, 8, 8, 6,
0, 0, 80, 0, 112, 136, 136, 248, 136, 136, 5, 8, 8, 6, 0, 0,
32, 80, 32, 112, 136, 248, 136, 136, 5, 7, 7, 6, 0, 0, 56, 96,
160, 184, 224, 160, 184, 5, 8, 8, 6, 0, 255, 112, 136, 128, 128, 136,
112, 32, 96, 5, 8, 8, 6, 0, 0, 64, 32, 0, 248, 128, 240, 128,
248, 5, 8, 8, 6, 0, 0, 8, 16, 0, 248, 128, 240, 128, 248, 5,
8, 8, 6, 0, 0, 32, 80, 0, 248, 128, 240, 128, 248, 5, 7, 7,
6, 0, 0, 80, 0, 248, 128, 240, 128, 248, 3, 8, 8, 6, 1, 0,
128, 64, 0, 224, 64, 64, 64, 224, 3, 8, 8, 6, 1, 0, 32, 64,
0, 224, 64, 64, 64, 224, 3, 8, 8, 6, 1, 0, 64, 160, 0, 224,
64, 64, 64, 224, 3, 7, 7, 6, 1, 0, 160, 0, 224, 64, 64, 64,
224, 5, 7, 7, 6, 0, 0, 112, 72, 72, 232, 72, 72, 112, 5, 8,
8, 6, 0, 0, 104, 144, 0, 136, 200, 168, 152, 136, 5, 8, 8, 6,
0, 0, 64, 32, 112, 136, 136, 136, 136, 112, 5, 8, 8, 6, 0, 0,
16, 32, 112, 136, 136, 136, 136, 112, 5, 8, 8, 6, 0, 0, 32, 80,
0, 112, 136, 136, 136, 112, 5, 8, 8, 6, 0, 0, 104, 144, 0, 112,
136, 136, 136, 112, 5, 8, 8, 6, 0, 0, 80, 0, 112, 136, 136, 136,
136, 112, 5, 5, 5, 6, 0, 1, 136, 80, 32, 80, 136, 5, 8, 8,
6, 0, 255, 16, 112, 168, 168, 168, 168, 112, 64, 5, 8, 8, 6, 0,
0, 64, 32, 136, 136, 136, 136, 136, 112, 5, 8, 8, 6, 0, 0, 16,
32, 136, 136, 136, 136, 136, 112, 5, 8, 8, 6, 0, 0, 32, 80, 0,
136, 136, 136, 136, 112, 5, 8, 8, 6, 0, 0, 80, 0, 136, 136, 136,
136, 136, 112, 5, 8, 8, 6, 0, 0, 16, 32, 136, 80, 32, 32, 32,
32, 5, 9, 9, 6, 0, 255, 192, 64, 112, 72, 72, 112, 64, 64, 224,
4, 8, 8, 6, 1, 255, 96, 144, 144, 160, 144, 144, 224, 128, 5, 8,
8, 6, 0, 0, 64, 32, 0, 112, 8, 120, 136, 120, 5, 8, 8, 6,
0, 0, 16, 32, 0, 112, 8, 120, 136, 120, 5, 8, 8, 6, 0, 0,
32, 80, 0, 112, 8, 120, 136, 120, 5, 8, 8, 6, 0, 0, 104, 144,
0, 112, 8, 120, 136, 120, 5, 7, 7, 6, 0, 0, 80, 0, 112, 8,
120, 136, 120, 5, 8, 8, 6, 0, 0, 32, 80, 32, 112, 8, 120, 136,
120, 5, 6, 6, 6, 0, 0, 208, 40, 120, 160, 168, 80, 5, 6, 6,
6, 0, 255, 112, 128, 136, 112, 32, 96, 5, 8, 8, 6, 0, 0, 64,
32, 0, 112, 136, 248, 128, 112, 5, 8, 8, 6, 0, 0, 16, 32, 0,
112, 136, 248, 128, 112, 5, 8, 8, 6, 0, 0, 32, 80, 0, 112, 136,
248, 128, 112, 5, 7, 7, 6, 0, 0, 80, 0, 112, 136, 248, 128, 112,
3, 8, 8, 6, 1, 0, 128, 64, 0, 64, 192, 64, 64, 224, 3, 8,
8, 6, 1, 0, 32, 64, 0, 64, 192, 64, 64, 224, 3, 8, 8, 6,
1, 0, 64, 160, 0, 64, 192, 64, 64, 224, 3, 7, 7, 6, 1, 0,
160, 0, 64, 192, 64, 64, 224, 5, 7, 7, 6, 0, 0, 160, 64, 160,
16, 120, 136, 112, 5, 8, 8, 6, 0, 0, 104, 144, 0, 176, 200, 136,
136, 136, 5, 8, 8, 6, 0, 0, 64, 32, 0, 112, 136, 136, 136, 112,
5, 8, 8, 6, 0, 0, 16, 32, 0, 112, 136, 136, 136, 112, 5, 8,
8, 6, 0, 0, 32, 80, 0, 112, 136, 136, 136, 112, 5, 8, 8, 6,
0, 0, 104, 144, 0, 112, 136, 136, 136, 112, 5, 7, 7, 6, 0, 0,
80, 0, 112, 136, 136, 136, 112, 5, 5, 5, 6, 0, 1, 32, 0, 248,
0, 32, 5, 7, 7, 6, 0, 255, 16, 112, 168, 168, 168, 112, 64, 5,
8, 8, 6, 0, 0, 64, 32, 0, 136, 136, 136, 152, 104, 5, 8, 8,
6, 0, 0, 16, 32, 0, 136, 136, 136, 152, 104, 5, 8, 8, 6, 0,
0, 32, 80, 0, 136, 136, 136, 152, 104, 5, 7, 7, 6, 0, 0, 80,
0, 136, 136, 136, 152, 104, 5, 9, 9, 6, 0, 255, 16, 32, 0, 136,
136, 136, 248, 8, 112, 4, 7, 7, 6, 1, 255, 192, 64, 96, 80, 96,
64, 224, 5, 8, 8, 6, 0, 255, 80, 0, 136, 136, 136, 120, 8, 112
};
#endif

View File

@ -0,0 +1,184 @@
/*
Fontname: ISO10646-1-PL
Copyright: A.Hardtung, public domain
Capital A Height: 7, '1' Height: 7
Calculated Max Values w= 5 h= 9 x= 2 y= 7 dx= 6 dy= 0 ascent= 8 len= 9
Font Bounding box w= 6 h= 9 x= 0 y=-2
Calculated Min Values x= 0 y=-2 dx= 0 dy= 0
Pure Font ascent = 7 descent=-1
X Font ascent = 7 descent=-1
Max Font ascent = 8 descent=-2
*/
#include <U8glib.h>
const u8g_fntpgm_uint8_t ISO10646_1_PL_5x7[2732] U8G_FONT_SECTION(".progmem.ISO10646_1_PL_5x7") = {
0,6,9,0,254,7,1,146,3,33,32,255,255,8,254,7,
255,0,0,0,6,0,0,1,7,7,6,2,0,128,128,128,
128,128,0,128,3,2,2,6,1,5,160,160,5,7,7,6,
0,0,80,80,248,80,248,80,80,5,7,7,6,0,0,32,
120,160,112,40,240,32,5,7,7,6,0,0,192,200,16,32,
64,152,24,5,7,7,6,0,0,96,144,160,64,168,144,104,
2,3,3,6,1,4,192,64,128,3,7,7,6,1,0,32,
64,128,128,128,64,32,3,7,7,6,1,0,128,64,32,32,
32,64,128,5,5,5,6,0,1,32,168,112,168,32,5,5,
5,6,0,1,32,32,248,32,32,2,3,3,6,2,255,192,
64,128,5,1,1,6,0,3,248,2,2,2,6,2,0,192,
192,5,5,5,6,0,1,8,16,32,64,128,5,7,7,6,
0,0,112,136,136,136,136,136,112,3,7,7,6,1,0,64,
192,64,64,64,64,224,5,7,7,6,0,0,112,136,8,112,
128,128,248,5,7,7,6,0,0,248,16,32,16,8,8,240,
5,7,7,6,0,0,16,48,80,144,248,16,16,5,7,7,
6,0,0,248,128,240,8,8,136,112,5,7,7,6,0,0,
112,128,128,240,136,136,112,5,7,7,6,0,0,248,8,16,
32,32,32,32,5,7,7,6,0,0,112,136,136,112,136,136,
112,5,7,7,6,0,0,112,136,136,120,8,8,112,2,5,
5,6,2,0,192,192,0,192,192,2,6,6,6,2,255,192,
192,0,192,64,128,4,7,7,6,0,0,16,32,64,128,64,
32,16,5,3,3,6,0,2,248,0,248,4,7,7,6,1,
0,128,64,32,16,32,64,128,5,7,7,6,0,0,112,136,
8,16,32,0,32,5,7,7,6,0,0,112,136,8,104,168,
168,112,5,7,7,6,0,0,112,136,136,248,136,136,136,5,
7,7,6,0,0,240,136,136,240,136,136,240,5,7,7,6,
0,0,112,136,128,128,128,136,112,5,7,7,6,0,0,240,
136,136,136,136,136,240,5,7,7,6,0,0,248,128,128,240,
128,128,248,5,7,7,6,0,0,248,128,128,240,128,128,128,
5,7,7,6,0,0,112,136,128,184,136,136,112,5,7,7,
6,0,0,136,136,136,248,136,136,136,1,7,7,6,2,0,
128,128,128,128,128,128,128,5,7,7,6,0,0,56,16,16,
16,16,144,96,5,7,7,6,0,0,136,144,160,192,160,144,
136,5,7,7,6,0,0,128,128,128,128,128,128,248,5,7,
7,6,0,0,136,216,168,136,136,136,136,5,7,7,6,0,
0,136,136,200,168,152,136,136,5,7,7,6,0,0,112,136,
136,136,136,136,112,5,7,7,6,0,0,240,136,136,240,128,
128,128,5,7,7,6,0,0,112,136,136,136,168,144,104,5,
7,7,6,0,0,240,136,136,240,160,144,136,5,7,7,6,
0,0,120,128,128,112,8,8,240,5,7,7,6,0,0,248,
32,32,32,32,32,32,5,7,7,6,0,0,136,136,136,136,
136,136,112,5,7,7,6,0,0,136,136,136,136,136,80,32,
5,7,7,6,0,0,136,136,136,136,136,168,80,5,7,7,
6,0,0,136,136,80,32,80,136,136,5,7,7,6,0,0,
136,136,136,80,32,32,32,5,7,7,6,0,0,248,8,16,
32,64,128,248,3,7,7,6,1,0,224,128,128,128,128,128,
224,5,5,5,6,0,1,128,64,32,16,8,3,7,7,6,
1,0,224,32,32,32,32,32,224,5,3,3,6,0,4,32,
80,136,5,1,1,6,0,0,248,2,2,2,6,2,5,128,
64,5,5,5,6,0,0,112,8,120,136,120,5,7,7,6,
0,0,128,128,176,200,136,136,240,5,5,5,6,0,0,112,
128,128,136,112,5,7,7,6,0,0,8,8,104,152,136,136,
120,5,5,5,6,0,0,112,136,248,128,112,5,7,7,6,
0,0,48,72,224,64,64,64,64,5,6,6,6,0,255,112,
136,136,120,8,112,5,7,7,6,0,0,128,128,176,200,136,
136,136,1,7,7,6,2,0,128,0,128,128,128,128,128,3,
8,8,6,1,255,32,0,32,32,32,32,160,64,4,7,7,
6,0,0,128,128,144,160,192,160,144,3,7,7,6,1,0,
192,64,64,64,64,64,224,5,5,5,6,0,0,208,168,168,
168,168,5,5,5,6,0,0,176,200,136,136,136,5,5,5,
6,0,0,112,136,136,136,112,5,6,6,6,0,255,240,136,
136,240,128,128,5,6,6,6,0,255,120,136,136,120,8,8,
5,5,5,6,0,0,176,200,128,128,128,5,5,5,6,0,
0,112,128,112,8,240,4,7,7,6,0,0,64,64,224,64,
64,64,48,5,5,5,6,0,0,136,136,136,152,104,5,5,
5,6,0,0,136,136,136,80,32,5,5,5,6,0,0,136,
136,168,168,80,5,5,5,6,0,0,136,80,32,80,136,5,
6,6,6,0,255,136,136,136,120,8,112,5,5,5,6,0,
0,248,16,32,64,248,3,7,7,6,1,0,32,64,64,128,
64,64,32,1,7,7,6,2,0,128,128,128,128,128,128,128,
3,7,7,6,1,0,128,64,64,32,64,64,128,5,2,2,
6,0,2,104,144,0,0,0,6,0,0,5,9,9,6,0,
254,112,136,136,248,136,136,136,16,32,5,7,7,6,0,254,
112,8,120,136,120,16,32,5,8,8,6,0,0,16,32,112,
136,128,128,136,112,5,7,7,6,0,0,16,32,112,128,128,
136,112,5,9,9,6,0,254,248,128,128,240,128,128,248,8,
16,5,7,7,6,0,254,112,136,248,128,112,16,32,5,7,
7,6,0,0,128,144,160,192,128,128,248,5,7,7,6,0,
0,96,40,48,96,160,32,112,5,8,8,6,0,0,16,168,
136,200,168,152,136,136,5,8,8,6,0,0,8,16,0,176,
200,136,136,136,5,8,8,6,0,0,16,32,112,136,136,136,
136,112,5,8,8,6,0,0,16,32,0,112,136,136,136,112,
5,8,8,6,0,0,16,120,128,128,112,8,8,240,5,8,
8,6,0,0,16,32,0,112,128,112,8,240,5,8,8,6,
0,0,32,248,8,16,32,64,128,248,5,8,8,6,0,0,
16,32,0,248,16,32,64,248,5,7,7,6,0,0,248,8,
16,248,64,128,248,5,8,8,6,0,0,48,48,0,248,16,
32,64,248,0,0,0,6,0,0,0,0,0,6,0,0,0,
0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,0,
0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,
6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,
0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,0,
0,0,0,0,6,0,0,0,0,0,6,0,0,1,7,7,
6,2,0,128,0,128,128,128,128,128,5,7,7,6,0,0,
32,112,168,160,168,112,32,5,7,7,6,0,0,48,64,64,
224,64,80,168,5,5,5,6,0,0,136,112,80,112,136,5,
7,7,6,0,0,136,80,32,248,32,248,32,1,7,7,6,
2,0,128,128,128,0,128,128,128,5,8,8,6,0,0,48,
72,32,80,80,32,144,96,3,1,1,6,1,7,160,5,7,
7,6,0,0,248,136,184,184,184,136,248,5,7,7,6,0,
1,112,8,120,136,120,0,248,5,5,5,6,0,1,40,80,
160,80,40,5,3,3,6,0,1,248,8,8,2,2,2,6,
2,6,64,128,5,7,7,6,0,0,248,136,168,136,152,168,
248,5,1,1,6,0,6,248,4,4,4,6,0,3,96,144,
144,96,5,7,7,6,0,0,32,32,248,32,32,0,248,4,
5,5,6,0,3,96,144,32,64,240,3,5,5,6,0,3,
224,32,224,32,224,2,2,2,6,2,6,64,128,5,8,8,
6,0,255,136,136,136,136,152,232,128,128,5,7,7,6,0,
0,120,152,152,120,24,24,24,2,2,2,6,2,2,192,192,
2,2,2,6,2,255,64,128,3,5,5,6,0,3,64,192,
64,64,224,5,7,7,6,0,1,112,136,136,136,112,0,248,
5,5,5,6,0,1,160,80,40,80,160,5,7,7,6,0,
0,136,144,168,88,184,8,8,5,7,7,6,0,0,136,144,
184,72,152,32,56,5,8,8,6,0,0,192,64,192,72,216,
56,8,8,5,7,7,6,0,0,32,0,32,64,128,136,112,
5,8,8,6,0,0,64,32,0,112,136,248,136,136,5,8,
8,6,0,0,16,32,0,112,136,248,136,136,5,8,8,6,
0,0,32,80,0,112,136,248,136,136,5,8,8,6,0,0,
104,144,0,112,136,248,136,136,5,8,8,6,0,0,80,0,
112,136,136,248,136,136,5,8,8,6,0,0,32,80,32,112,
136,248,136,136,5,7,7,6,0,0,56,96,160,184,224,160,
184,5,8,8,6,0,255,112,136,128,128,136,112,32,96,5,
8,8,6,0,0,64,32,0,248,128,240,128,248,5,8,8,
6,0,0,8,16,0,248,128,240,128,248,5,8,8,6,0,
0,32,80,0,248,128,240,128,248,5,7,7,6,0,0,80,
0,248,128,240,128,248,3,8,8,6,1,0,128,64,0,224,
64,64,64,224,3,8,8,6,1,0,32,64,0,224,64,64,
64,224,3,8,8,6,1,0,64,160,0,224,64,64,64,224,
3,7,7,6,1,0,160,0,224,64,64,64,224,5,7,7,
6,0,0,112,72,72,232,72,72,112,5,8,8,6,0,0,
104,144,0,136,200,168,152,136,5,8,8,6,0,0,64,32,
112,136,136,136,136,112,5,8,8,6,0,0,16,32,112,136,
136,136,136,112,5,8,8,6,0,0,32,80,0,112,136,136,
136,112,5,8,8,6,0,0,104,144,0,112,136,136,136,112,
5,8,8,6,0,0,80,0,112,136,136,136,136,112,5,5,
5,6,0,1,136,80,32,80,136,5,8,8,6,0,255,16,
112,168,168,168,168,112,64,5,8,8,6,0,0,64,32,136,
136,136,136,136,112,5,8,8,6,0,0,16,32,136,136,136,
136,136,112,5,8,8,6,0,0,32,80,0,136,136,136,136,
112,5,8,8,6,0,0,80,0,136,136,136,136,136,112,5,
8,8,6,0,0,16,32,136,80,32,32,32,32,5,9,9,
6,0,255,192,64,112,72,72,112,64,64,224,4,8,8,6,
1,255,96,144,144,160,144,144,224,128,5,8,8,6,0,0,
64,32,0,112,8,120,136,120,5,8,8,6,0,0,16,32,
0,112,8,120,136,120,5,8,8,6,0,0,32,80,0,112,
8,120,136,120,5,8,8,6,0,0,104,144,0,112,8,120,
136,120,5,7,7,6,0,0,80,0,112,8,120,136,120,5,
8,8,6,0,0,32,80,32,112,8,120,136,120,5,6,6,
6,0,0,208,40,120,160,168,80,5,6,6,6,0,255,112,
128,136,112,32,96,5,8,8,6,0,0,64,32,0,112,136,
248,128,112,5,8,8,6,0,0,16,32,0,112,136,248,128,
112,5,8,8,6,0,0,32,80,0,112,136,248,128,112,5,
7,7,6,0,0,80,0,112,136,248,128,112,3,8,8,6,
1,0,128,64,0,64,192,64,64,224,3,8,8,6,1,0,
32,64,0,64,192,64,64,224,3,8,8,6,1,0,64,160,
0,64,192,64,64,224,3,7,7,6,1,0,160,0,64,192,
64,64,224,5,7,7,6,0,0,160,64,160,16,120,136,112,
5,8,8,6,0,0,104,144,0,176,200,136,136,136,5,8,
8,6,0,0,64,32,0,112,136,136,136,112,5,8,8,6,
0,0,16,32,0,112,136,136,136,112,5,8,8,6,0,0,
32,80,0,112,136,136,136,112,5,8,8,6,0,0,104,144,
0,112,136,136,136,112,5,7,7,6,0,0,80,0,112,136,
136,136,112,5,5,5,6,0,1,32,0,248,0,32,5,7,
7,6,0,255,16,112,168,168,168,112,64,5,8,8,6,0,
0,64,32,0,136,136,136,152,104,5,8,8,6,0,0,16,
32,0,136,136,136,152,104,5,8,8,6,0,0,32,80,0,
136,136,136,152,104,5,7,7,6,0,0,80,0,136,136,136,
152,104,5,9,9,6,0,255,16,32,0,136,136,136,248,8,
112,4,7,7,6,1,255,192,64,96,80,96,64,224,5,8,
8,6,0,255,80,0,136,136,136,120,8,112};

View File

@ -0,0 +1,197 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
Fontname: ISO10646-1-tr
Copyright: public domain
Capital A Height: 7, '1' Height: 7
Calculated Max Values w= 5 h= 9 x= 2 y= 7 dx= 6 dy= 0 ascent= 8 len= 9
Font Bounding box w= 6 h= 9 x= 0 y=-2
Calculated Min Values x= 0 y=-1 dx= 0 dy= 0
Pure Font ascent = 7 descent=-1
X Font ascent = 7 descent=-1
Max Font ascent = 8 descent=-1
*/
#include <U8glib.h>
const u8g_fntpgm_uint8_t ISO10646_TR[2591] U8G_SECTION(".progmem.ISO10646_TR") = {
0,6,9,0,254,7,1,146,3,33,32,255,255,8,255,7,
255,0,0,0,6,0,0,1,7,7,6,2,0,128,128,128,
128,128,0,128,3,2,2,6,1,5,160,160,5,7,7,6,
0,0,80,80,248,80,248,80,80,5,7,7,6,0,0,32,
120,160,112,40,240,32,5,7,7,6,0,0,192,200,16,32,
64,152,24,5,7,7,6,0,0,96,144,160,64,168,144,104,
2,3,3,6,1,4,192,64,128,3,7,7,6,1,0,32,
64,128,128,128,64,32,3,7,7,6,1,0,128,64,32,32,
32,64,128,5,5,5,6,0,1,32,168,112,168,32,5,5,
5,6,0,1,32,32,248,32,32,2,3,3,6,2,255,192,
64,128,5,1,1,6,0,3,248,2,2,2,6,2,0,192,
192,5,5,5,6,0,1,8,16,32,64,128,5,7,7,6,
0,0,112,136,136,136,136,136,112,3,7,7,6,1,0,64,
192,64,64,64,64,224,5,7,7,6,0,0,112,136,8,112,
128,128,248,5,7,7,6,0,0,248,16,32,16,8,8,240,
5,7,7,6,0,0,16,48,80,144,248,16,16,5,7,7,
6,0,0,248,128,240,8,8,136,112,5,7,7,6,0,0,
112,128,128,240,136,136,112,5,7,7,6,0,0,248,8,16,
32,32,32,32,5,7,7,6,0,0,112,136,136,112,136,136,
112,5,7,7,6,0,0,112,136,136,120,8,8,112,2,5,
5,6,2,0,192,192,0,192,192,2,6,6,6,2,255,192,
192,0,192,64,128,4,7,7,6,0,0,16,32,64,128,64,
32,16,5,3,3,6,0,2,248,0,248,4,7,7,6,1,
0,128,64,32,16,32,64,128,5,7,7,6,0,0,112,136,
8,16,32,0,32,5,7,7,6,0,0,112,136,8,104,168,
168,112,5,7,7,6,0,0,112,136,136,248,136,136,136,5,
7,7,6,0,0,240,136,136,240,136,136,240,5,7,7,6,
0,0,112,136,128,128,128,136,112,5,7,7,6,0,0,240,
136,136,136,136,136,240,5,7,7,6,0,0,248,128,128,240,
128,128,248,5,7,7,6,0,0,248,128,128,240,128,128,128,
5,7,7,6,0,0,112,136,128,184,136,136,112,5,7,7,
6,0,0,136,136,136,248,136,136,136,1,7,7,6,2,0,
128,128,128,128,128,128,128,5,7,7,6,0,0,56,16,16,
16,16,144,96,5,7,7,6,0,0,136,144,160,192,160,144,
136,5,7,7,6,0,0,128,128,128,128,128,128,248,5,7,
7,6,0,0,136,216,168,136,136,136,136,5,7,7,6,0,
0,136,136,200,168,152,136,136,5,7,7,6,0,0,112,136,
136,136,136,136,112,5,7,7,6,0,0,240,136,136,240,128,
128,128,5,7,7,6,0,0,112,136,136,136,168,144,104,5,
7,7,6,0,0,240,136,136,240,160,144,136,5,7,7,6,
0,0,120,128,128,112,8,8,240,5,7,7,6,0,0,248,
32,32,32,32,32,32,5,7,7,6,0,0,136,136,136,136,
136,136,112,5,7,7,6,0,0,136,136,136,136,136,80,32,
5,7,7,6,0,0,136,136,136,136,136,168,80,5,7,7,
6,0,0,136,136,80,32,80,136,136,5,7,7,6,0,0,
136,136,136,80,32,32,32,5,7,7,6,0,0,248,8,16,
32,64,128,248,3,7,7,6,1,0,224,128,128,128,128,128,
224,5,5,5,6,0,1,128,64,32,16,8,3,7,7,6,
1,0,224,32,32,32,32,32,224,5,3,3,6,0,4,32,
80,136,5,1,1,6,0,0,248,2,2,2,6,2,5,128,
64,5,5,5,6,0,0,112,8,120,136,120,5,7,7,6,
0,0,128,128,176,200,136,136,240,5,5,5,6,0,0,112,
128,128,136,112,5,7,7,6,0,0,8,8,104,152,136,136,
120,5,5,5,6,0,0,112,136,248,128,112,5,7,7,6,
0,0,48,72,224,64,64,64,64,5,6,6,6,0,255,112,
136,136,120,8,112,5,7,7,6,0,0,128,128,176,200,136,
136,136,1,7,7,6,2,0,128,0,128,128,128,128,128,3,
8,8,6,1,255,32,0,32,32,32,32,160,64,4,7,7,
6,0,0,128,128,144,160,192,160,144,3,7,7,6,1,0,
192,64,64,64,64,64,224,5,5,5,6,0,0,208,168,168,
168,168,5,5,5,6,0,0,176,200,136,136,136,5,5,5,
6,0,0,112,136,136,136,112,5,6,6,6,0,255,240,136,
136,240,128,128,5,6,6,6,0,255,120,136,136,120,8,8,
5,5,5,6,0,0,176,200,128,128,128,5,5,5,6,0,
0,112,128,112,8,240,4,7,7,6,0,0,64,64,224,64,
64,64,48,5,5,5,6,0,0,136,136,136,152,104,5,5,
5,6,0,0,136,136,136,80,32,5,5,5,6,0,0,136,
136,168,168,80,5,5,5,6,0,0,136,80,32,80,136,5,
6,6,6,0,255,136,136,136,120,8,112,5,5,5,6,0,
0,248,16,32,64,248,3,7,7,6,1,0,32,64,64,128,
64,64,32,1,7,7,6,2,0,128,128,128,128,128,128,128,
3,7,7,6,1,0,128,64,64,32,64,64,128,5,2,2,
6,0,2,104,144,0,0,0,6,0,0,0,0,0,6,0,
0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,
6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,
0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,0,
0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,
6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,
0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,0,
0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,
6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,
0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,0,
0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,
6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,
0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,0,
0,1,7,7,6,2,0,128,0,128,128,128,128,128,5,7,
7,6,0,0,32,112,168,160,168,112,32,5,7,7,6,0,
0,48,64,64,224,64,80,168,5,5,5,6,0,0,136,112,
80,112,136,5,7,7,6,0,0,136,80,32,248,32,248,32,
1,7,7,6,2,0,128,128,128,0,128,128,128,5,8,8,
6,0,0,48,72,32,80,80,32,144,96,3,1,1,6,1,
7,160,5,7,7,6,0,0,248,136,184,184,184,136,248,5,
7,7,6,0,1,112,8,120,136,120,0,248,5,5,5,6,
0,1,40,80,160,80,40,5,3,3,6,0,1,248,8,8,
2,2,2,6,2,6,64,128,5,7,7,6,0,0,248,136,
168,136,152,168,248,5,1,1,6,0,6,248,4,4,4,6,
0,3,96,144,144,96,5,7,7,6,0,0,32,32,248,32,
32,0,248,4,5,5,6,0,3,96,144,32,64,240,3,5,
5,6,0,3,224,32,224,32,224,2,2,2,6,2,6,64,
128,5,8,8,6,0,255,136,136,136,136,152,232,128,128,5,
7,7,6,0,0,120,152,152,120,24,24,24,2,2,2,6,
2,2,192,192,2,2,2,6,2,255,64,128,3,5,5,6,
0,3,64,192,64,64,224,5,7,7,6,0,1,112,136,136,
136,112,0,248,5,5,5,6,0,1,160,80,40,80,160,5,
7,7,6,0,0,136,144,168,88,184,8,8,5,7,7,6,
0,0,136,144,184,72,152,32,56,5,8,8,6,0,0,192,
64,192,72,216,56,8,8,5,7,7,6,0,0,32,0,32,
64,128,136,112,5,8,8,6,0,0,64,32,0,112,136,248,
136,136,5,8,8,6,0,0,16,32,0,112,136,248,136,136,
5,8,8,6,0,0,32,80,0,112,136,248,136,136,5,8,
8,6,0,0,104,144,0,112,136,248,136,136,5,8,8,6,
0,0,80,0,112,136,136,248,136,136,5,8,8,6,0,0,
32,80,32,112,136,248,136,136,5,7,7,6,0,0,56,96,
160,184,224,160,184,5,8,8,6,0,255,112,136,128,128,136,
112,32,96,5,8,8,6,0,0,64,32,0,248,128,240,128,
248,5,8,8,6,0,0,8,16,0,248,128,240,128,248,5,
8,8,6,0,0,32,80,0,248,128,240,128,248,5,7,7,
6,0,0,80,0,248,128,240,128,248,3,8,8,6,1,0,
128,64,0,224,64,64,64,224,3,8,8,6,1,0,32,64,
0,224,64,64,64,224,3,8,8,6,1,0,64,160,0,224,
64,64,64,224,3,7,7,6,1,0,160,0,224,64,64,64,
224,5,9,9,6,0,255,80,32,112,136,128,184,136,136,112,
5,8,8,6,0,0,104,144,0,136,200,168,152,136,5,8,
8,6,0,0,64,32,112,136,136,136,136,112,5,8,8,6,
0,0,16,32,112,136,136,136,136,112,5,8,8,6,0,0,
32,80,0,112,136,136,136,112,5,8,8,6,0,0,104,144,
0,112,136,136,136,112,5,8,8,6,0,0,80,0,112,136,
136,136,136,112,5,5,5,6,0,1,136,80,32,80,136,5,
8,8,6,0,255,16,112,168,168,168,168,112,64,5,8,8,
6,0,0,64,32,136,136,136,136,136,112,5,8,8,6,0,
0,16,32,136,136,136,136,136,112,5,8,8,6,0,0,32,
80,0,136,136,136,136,112,5,8,8,6,0,0,80,0,136,
136,136,136,136,112,1,7,7,6,2,0,128,0,128,128,128,
128,128,5,9,9,6,0,255,120,128,128,112,8,8,240,32,
96,4,8,8,6,1,255,96,144,144,160,144,144,224,128,5,
8,8,6,0,0,64,32,0,112,8,120,136,120,5,8,8,
6,0,0,16,32,0,112,8,120,136,120,5,8,8,6,0,
0,32,80,0,112,8,120,136,120,5,8,8,6,0,0,104,
144,0,112,8,120,136,120,5,7,7,6,0,0,80,0,112,
8,120,136,120,5,8,8,6,0,0,32,80,32,112,8,120,
136,120,5,6,6,6,0,0,208,40,120,160,168,80,5,7,
7,6,0,255,112,128,128,136,112,32,96,5,8,8,6,0,
0,64,32,0,112,136,248,128,112,5,8,8,6,0,0,16,
32,0,112,136,248,128,112,5,8,8,6,0,0,32,80,0,
112,136,248,128,112,5,7,7,6,0,0,80,0,112,136,248,
128,112,3,8,8,6,1,0,128,64,0,64,192,64,64,224,
3,8,8,6,1,0,32,64,0,64,192,64,64,224,3,8,
8,6,1,0,64,160,0,64,192,64,64,224,3,7,7,6,
1,0,160,0,64,192,64,64,224,5,8,8,6,0,255,80,
32,112,136,136,120,8,112,5,8,8,6,0,0,104,144,0,
176,200,136,136,136,5,8,8,6,0,0,64,32,0,112,136,
136,136,112,5,8,8,6,0,0,16,32,0,112,136,136,136,
112,5,8,8,6,0,0,32,80,0,112,136,136,136,112,5,
8,8,6,0,0,104,144,0,112,136,136,136,112,5,7,7,
6,0,0,80,0,112,136,136,136,112,5,5,5,6,0,1,
32,0,248,0,32,5,7,7,6,0,255,16,112,168,168,168,
112,64,5,8,8,6,0,0,64,32,0,136,136,136,152,104,
5,8,8,6,0,0,16,32,0,136,136,136,152,104,5,8,
8,6,0,0,32,80,0,136,136,136,152,104,5,7,7,6,
0,0,80,0,136,136,136,152,104,1,5,5,6,2,0,128,
128,128,128,128,5,7,7,6,0,255,112,128,112,8,240,32,
96,5,8,8,6,0,255,80,0,136,136,136,120,8,112};

View File

@ -0,0 +1,196 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
Fontname: ISO10646_5_Cyrillic
Copyright: A. Hardtung, public domain
Capital A Height: 7, '1' Height: 7
Calculated Max Values w= 5 h= 9 x= 2 y= 5 dx= 6 dy= 0 ascent= 8 len= 9
Font Bounding box w= 6 h= 9 x= 0 y=-2
Calculated Min Values x= 0 y=-1 dx= 0 dy= 0
Pure Font ascent = 7 descent=-1
X Font ascent = 7 descent=-1
Max Font ascent = 8 descent=-1
*/
#include <U8glib.h>
const u8g_fntpgm_uint8_t ISO10646_5_Cyrillic_5x7[2560] U8G_SECTION(".progmem.ISO10646_5_Cyrillic_5x7") = {
0, 6, 9, 0, 254, 7, 1, 145, 3, 32, 32, 255, 255, 8, 255, 7,
255, 0, 0, 0, 6, 0, 0, 1, 7, 7, 6, 2, 0, 128, 128, 128,
128, 128, 0, 128, 3, 2, 2, 6, 1, 5, 160, 160, 5, 7, 7, 6,
0, 0, 80, 80, 248, 80, 248, 80, 80, 5, 7, 7, 6, 0, 0, 32,
120, 160, 112, 40, 240, 32, 5, 7, 7, 6, 0, 0, 192, 200, 16, 32,
64, 152, 24, 5, 7, 7, 6, 0, 0, 96, 144, 160, 64, 168, 144, 104,
2, 3, 3, 6, 1, 4, 192, 64, 128, 3, 7, 7, 6, 1, 0, 32,
64, 128, 128, 128, 64, 32, 3, 7, 7, 6, 1, 0, 128, 64, 32, 32,
32, 64, 128, 5, 5, 5, 6, 0, 1, 32, 168, 112, 168, 32, 5, 5,
5, 6, 0, 1, 32, 32, 248, 32, 32, 2, 3, 3, 6, 2, 255, 192,
64, 128, 5, 1, 1, 6, 0, 3, 248, 2, 2, 2, 6, 2, 0, 192,
192, 5, 5, 5, 6, 0, 1, 8, 16, 32, 64, 128, 5, 7, 7, 6,
0, 0, 112, 136, 152, 168, 200, 136, 112, 3, 7, 7, 6, 1, 0, 64,
192, 64, 64, 64, 64, 224, 5, 7, 7, 6, 0, 0, 112, 136, 8, 112,
128, 128, 248, 5, 7, 7, 6, 0, 0, 248, 16, 32, 16, 8, 8, 240,
5, 7, 7, 6, 0, 0, 16, 48, 80, 144, 248, 16, 16, 5, 7, 7,
6, 0, 0, 248, 128, 240, 8, 8, 136, 112, 5, 7, 7, 6, 0, 0,
48, 64, 128, 240, 136, 136, 112, 5, 7, 7, 6, 0, 0, 248, 8, 16,
32, 32, 32, 32, 5, 7, 7, 6, 0, 0, 112, 136, 136, 112, 136, 136,
112, 5, 7, 7, 6, 0, 0, 112, 136, 136, 120, 8, 16, 96, 2, 5,
5, 6, 2, 0, 192, 192, 0, 192, 192, 2, 6, 6, 6, 2, 255, 192,
192, 0, 192, 64, 128, 4, 7, 7, 6, 0, 0, 16, 32, 64, 128, 64,
32, 16, 5, 3, 3, 6, 0, 2, 248, 0, 248, 4, 7, 7, 6, 1,
0, 128, 64, 32, 16, 32, 64, 128, 5, 7, 7, 6, 0, 0, 112, 136,
8, 16, 32, 0, 32, 5, 6, 6, 6, 0, 0, 112, 136, 8, 104, 168,
112, 5, 7, 7, 6, 0, 0, 112, 136, 136, 248, 136, 136, 136, 5, 7,
7, 6, 0, 0, 240, 136, 136, 240, 136, 136, 240, 5, 7, 7, 6, 0,
0, 112, 136, 128, 128, 128, 136, 112, 5, 7, 7, 6, 0, 0, 224, 144,
136, 136, 136, 144, 224, 5, 7, 7, 6, 0, 0, 248, 128, 128, 240, 128,
128, 248, 5, 7, 7, 6, 0, 0, 248, 128, 128, 240, 128, 128, 128, 5,
7, 7, 6, 0, 0, 112, 136, 128, 184, 136, 136, 112, 5, 7, 7, 6,
0, 0, 136, 136, 136, 248, 136, 136, 136, 1, 7, 7, 6, 2, 0, 128,
128, 128, 128, 128, 128, 128, 5, 7, 7, 6, 0, 0, 56, 16, 16, 16,
16, 144, 96, 5, 7, 7, 6, 0, 0, 136, 144, 160, 192, 160, 144, 136,
5, 7, 7, 6, 0, 0, 128, 128, 128, 128, 128, 128, 248, 5, 7, 7,
6, 0, 0, 136, 216, 168, 136, 136, 136, 136, 5, 7, 7, 6, 0, 0,
136, 136, 200, 168, 152, 136, 136, 5, 7, 7, 6, 0, 0, 112, 136, 136,
136, 136, 136, 112, 5, 7, 7, 6, 0, 0, 240, 136, 136, 240, 128, 128,
128, 5, 7, 7, 6, 0, 0, 112, 136, 136, 136, 168, 144, 104, 5, 7,
7, 6, 0, 0, 240, 136, 136, 240, 160, 144, 136, 5, 7, 7, 6, 0,
0, 120, 128, 128, 112, 8, 8, 240, 5, 7, 7, 6, 0, 0, 248, 32,
32, 32, 32, 32, 32, 5, 7, 7, 6, 0, 0, 136, 136, 136, 136, 136,
136, 112, 5, 7, 7, 6, 0, 0, 136, 136, 136, 136, 136, 80, 32, 5,
7, 7, 6, 0, 0, 136, 136, 136, 136, 136, 168, 80, 5, 7, 7, 6,
0, 0, 136, 136, 80, 32, 80, 136, 136, 5, 7, 7, 6, 0, 0, 136,
136, 136, 80, 32, 32, 32, 5, 7, 7, 6, 0, 0, 248, 8, 16, 32,
64, 128, 248, 3, 7, 7, 6, 1, 0, 224, 128, 128, 128, 128, 128, 224,
5, 5, 5, 6, 0, 1, 128, 64, 32, 16, 8, 3, 7, 7, 6, 1,
0, 224, 32, 32, 32, 32, 32, 224, 5, 3, 3, 6, 0, 4, 32, 80,
136, 5, 1, 1, 6, 0, 0, 248, 2, 2, 2, 6, 2, 5, 128, 64,
5, 5, 5, 6, 0, 0, 112, 8, 120, 136, 120, 5, 7, 7, 6, 0,
0, 128, 128, 176, 200, 136, 136, 240, 5, 5, 5, 6, 0, 0, 112, 128,
128, 136, 112, 5, 7, 7, 6, 0, 0, 8, 8, 104, 152, 136, 136, 120,
5, 5, 5, 6, 0, 0, 112, 136, 248, 128, 112, 5, 7, 7, 6, 0,
0, 48, 72, 224, 64, 64, 64, 64, 5, 6, 6, 6, 0, 255, 112, 136,
136, 120, 8, 112, 5, 7, 7, 6, 0, 0, 128, 128, 176, 200, 136, 136,
136, 1, 7, 7, 6, 2, 0, 128, 0, 128, 128, 128, 128, 128, 3, 8,
8, 6, 1, 255, 32, 0, 32, 32, 32, 32, 160, 64, 4, 7, 7, 6,
0, 0, 128, 128, 144, 160, 192, 160, 144, 3, 7, 7, 6, 1, 0, 192,
64, 64, 64, 64, 64, 224, 5, 5, 5, 6, 0, 0, 208, 168, 168, 168,
168, 5, 5, 5, 6, 0, 0, 176, 200, 136, 136, 136, 5, 5, 5, 6,
0, 0, 112, 136, 136, 136, 112, 5, 6, 6, 6, 0, 255, 240, 136, 136,
240, 128, 128, 5, 6, 6, 6, 0, 255, 120, 136, 136, 120, 8, 8, 5,
5, 5, 6, 0, 0, 176, 200, 128, 128, 128, 5, 5, 5, 6, 0, 0,
112, 128, 112, 8, 240, 5, 7, 7, 6, 0, 0, 64, 64, 224, 64, 64,
72, 48, 5, 5, 5, 6, 0, 0, 136, 136, 136, 152, 104, 5, 5, 5,
6, 0, 0, 136, 136, 136, 80, 32, 5, 5, 5, 6, 0, 0, 136, 136,
168, 168, 80, 5, 5, 5, 6, 0, 0, 136, 80, 32, 80, 136, 5, 6,
6, 6, 0, 255, 136, 136, 136, 120, 8, 112, 5, 5, 5, 6, 0, 0,
248, 16, 32, 64, 248, 3, 7, 7, 6, 1, 0, 32, 64, 64, 128, 64,
64, 32, 1, 7, 7, 6, 2, 0, 128, 128, 128, 128, 128, 128, 128, 3,
7, 7, 6, 1, 0, 128, 64, 64, 32, 64, 64, 128, 5, 2, 2, 6,
0, 3, 104, 144, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0,
0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6,
0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0,
0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0,
0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6,
0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0,
0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0,
0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6,
0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0,
0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0,
0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6,
0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0,
0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 5, 8, 8, 6, 0, 0,
64, 248, 128, 128, 240, 128, 128, 248, 5, 8, 8, 6, 0, 0, 80, 248,
128, 128, 240, 128, 128, 248, 5, 7, 7, 6, 0, 0, 224, 64, 64, 112,
72, 72, 112, 5, 8, 8, 6, 0, 0, 16, 32, 248, 136, 128, 128, 128,
128, 5, 7, 7, 6, 0, 0, 48, 72, 128, 224, 128, 72, 48, 5, 7,
7, 6, 0, 0, 112, 136, 128, 112, 8, 136, 112, 3, 7, 7, 6, 1,
0, 224, 64, 64, 64, 64, 64, 224, 3, 8, 8, 6, 1, 0, 160, 0,
224, 64, 64, 64, 64, 224, 5, 7, 7, 6, 0, 0, 56, 16, 16, 16,
16, 144, 96, 5, 7, 7, 6, 0, 0, 160, 160, 160, 184, 168, 168, 184,
5, 7, 7, 6, 0, 0, 160, 160, 160, 248, 168, 168, 184, 4, 7, 7,
6, 0, 0, 224, 64, 112, 80, 80, 80, 80, 5, 8, 8, 6, 0, 0,
16, 32, 136, 144, 160, 224, 144, 136, 5, 8, 8, 6, 0, 0, 64, 32,
136, 152, 168, 200, 136, 136, 5, 9, 9, 6, 0, 255, 80, 32, 136, 136,
136, 80, 32, 32, 32, 5, 8, 8, 6, 0, 255, 136, 136, 136, 136, 136,
136, 248, 32, 5, 7, 7, 6, 0, 0, 112, 136, 136, 248, 136, 136, 136,
5, 7, 7, 6, 0, 0, 248, 128, 128, 240, 136, 136, 240, 5, 7, 7,
6, 0, 0, 240, 136, 136, 240, 136, 136, 240, 5, 7, 7, 6, 0, 0,
248, 136, 128, 128, 128, 128, 128, 5, 8, 8, 6, 0, 255, 120, 40, 40,
40, 72, 136, 248, 136, 5, 7, 7, 6, 0, 0, 248, 128, 128, 240, 128,
128, 248, 5, 7, 7, 6, 0, 0, 168, 168, 168, 112, 168, 168, 168, 5,
7, 7, 6, 0, 0, 240, 8, 8, 112, 8, 8, 240, 5, 7, 7, 6,
0, 0, 136, 136, 152, 168, 200, 136, 136, 5, 8, 8, 6, 0, 0, 80,
32, 136, 152, 168, 168, 200, 136, 5, 7, 7, 6, 0, 0, 136, 144, 160,
192, 160, 144, 136, 5, 7, 7, 6, 0, 0, 120, 40, 40, 40, 40, 168,
72, 5, 7, 7, 6, 0, 0, 136, 216, 168, 136, 136, 136, 136, 5, 7,
7, 6, 0, 0, 136, 136, 136, 248, 136, 136, 136, 5, 7, 7, 6, 0,
0, 112, 136, 136, 136, 136, 136, 112, 5, 7, 7, 6, 0, 0, 248, 136,
136, 136, 136, 136, 136, 5, 7, 7, 6, 0, 0, 240, 136, 136, 240, 128,
128, 128, 5, 7, 7, 6, 0, 0, 112, 136, 128, 128, 128, 136, 112, 5,
7, 7, 6, 0, 0, 248, 32, 32, 32, 32, 32, 32, 5, 7, 7, 6,
0, 0, 136, 136, 136, 80, 32, 64, 128, 5, 7, 7, 6, 0, 0, 32,
112, 168, 168, 168, 112, 32, 5, 7, 7, 6, 0, 0, 136, 136, 80, 32,
80, 136, 136, 5, 8, 8, 6, 0, 255, 136, 136, 136, 136, 136, 136, 248,
8, 5, 7, 7, 6, 0, 0, 136, 136, 136, 152, 104, 8, 8, 5, 7,
7, 6, 0, 0, 168, 168, 168, 168, 168, 168, 248, 5, 8, 8, 6, 0,
255, 168, 168, 168, 168, 168, 168, 248, 8, 5, 7, 7, 6, 0, 0, 192,
64, 64, 112, 72, 72, 112, 5, 7, 7, 6, 0, 0, 136, 136, 136, 200,
168, 168, 200, 5, 7, 7, 6, 0, 0, 128, 128, 128, 240, 136, 136, 240,
5, 7, 7, 6, 0, 0, 112, 136, 8, 56, 8, 136, 112, 5, 7, 7,
6, 0, 0, 144, 168, 168, 232, 168, 168, 144, 5, 7, 7, 6, 0, 0,
120, 136, 136, 120, 40, 72, 136, 5, 5, 5, 6, 0, 0, 112, 8, 120,
136, 120, 5, 7, 7, 6, 0, 0, 24, 96, 128, 240, 136, 136, 112, 4,
5, 5, 6, 0, 0, 224, 144, 224, 144, 224, 5, 5, 5, 6, 0, 0,
248, 136, 128, 128, 128, 5, 6, 6, 6, 0, 255, 120, 40, 72, 136, 248,
136, 5, 5, 5, 6, 0, 0, 112, 136, 248, 128, 112, 5, 5, 5, 6,
0, 0, 168, 168, 112, 168, 168, 5, 5, 5, 6, 0, 0, 240, 8, 48,
8, 240, 5, 5, 5, 6, 0, 0, 136, 152, 168, 200, 136, 5, 7, 7,
6, 0, 0, 80, 32, 136, 152, 168, 200, 136, 4, 5, 5, 6, 0, 0,
144, 160, 192, 160, 144, 5, 5, 5, 6, 0, 0, 248, 40, 40, 168, 72,
5, 5, 5, 6, 0, 0, 136, 216, 168, 136, 136, 5, 5, 5, 6, 0,
0, 136, 136, 248, 136, 136, 5, 5, 5, 6, 0, 0, 112, 136, 136, 136,
112, 5, 5, 5, 6, 0, 0, 248, 136, 136, 136, 136, 5, 6, 6, 6,
0, 255, 240, 136, 136, 240, 128, 128, 5, 5, 5, 6, 0, 0, 112, 128,
128, 136, 112, 5, 5, 5, 6, 0, 0, 248, 32, 32, 32, 32, 5, 6,
6, 6, 0, 255, 136, 136, 136, 120, 8, 112, 5, 6, 6, 6, 0, 0,
32, 112, 168, 168, 112, 32, 5, 5, 5, 6, 0, 0, 136, 80, 32, 80,
136, 5, 6, 6, 6, 0, 255, 136, 136, 136, 136, 248, 8, 5, 5, 5,
6, 0, 0, 136, 136, 248, 8, 8, 5, 5, 5, 6, 0, 0, 168, 168,
168, 168, 248, 5, 6, 6, 6, 0, 255, 168, 168, 168, 168, 248, 8, 5,
5, 5, 6, 0, 0, 192, 64, 112, 72, 112, 5, 5, 5, 6, 0, 0,
136, 136, 200, 168, 200, 3, 5, 5, 6, 1, 0, 128, 128, 192, 160, 192,
5, 5, 5, 6, 0, 0, 112, 136, 56, 136, 112, 5, 5, 5, 6, 0,
0, 144, 168, 232, 168, 144, 5, 5, 5, 6, 0, 0, 120, 136, 120, 40,
72, 5, 8, 8, 6, 0, 0, 64, 32, 0, 112, 136, 248, 128, 112, 5,
7, 7, 6, 0, 0, 80, 0, 112, 136, 248, 128, 112, 5, 9, 9, 6,
0, 255, 64, 224, 64, 64, 120, 72, 72, 72, 16, 5, 8, 8, 6, 0,
0, 16, 32, 0, 248, 136, 128, 128, 128, 5, 5, 5, 6, 0, 0, 112,
136, 96, 136, 112, 5, 5, 5, 6, 0, 0, 112, 128, 112, 8, 240, 1,
7, 7, 6, 2, 0, 128, 0, 128, 128, 128, 128, 128, 3, 7, 7, 6,
1, 0, 160, 0, 64, 64, 64, 64, 64, 3, 8, 8, 6, 1, 255, 32,
0, 32, 32, 32, 32, 160, 64, 5, 5, 5, 6, 0, 0, 160, 160, 184,
168, 184, 5, 5, 5, 6, 0, 0, 160, 160, 248, 168, 184, 5, 6, 6,
6, 0, 0, 64, 224, 64, 120, 72, 72, 4, 8, 8, 6, 0, 0, 16,
32, 0, 144, 160, 192, 160, 144, 5, 8, 8, 6, 0, 0, 64, 32, 0,
136, 152, 168, 200, 136, 5, 9, 9, 6, 0, 255, 80, 32, 0, 136, 136,
136, 120, 8, 112, 5, 6, 6, 6, 0, 255, 136, 136, 136, 136, 248, 32
};

View File

@ -0,0 +1,293 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
Fontname: ISO10646_CN
Copyright: A. Hardtung, public domain
Capital A Height: 7, '1' Height: 7
Calculated Max Values w=11 h=11 x= 2 y=10 dx=12 dy= 0 ascent=10 len=22
Font Bounding box w=12 h=11 x= 0 y=-2
Calculated Min Values x= 0 y=-1 dx= 0 dy= 0
Pure Font ascent = 7 descent=-1
X Font ascent = 7 descent=-1
Max Font ascent =10 descent=-1
*/
#include <U8glib.h>
const u8g_fntpgm_uint8_t ISO10646_CN[4105] U8G_SECTION(".progmem.ISO10646_CN") = {
0, 12, 11, 0, 254, 7, 1, 146, 3, 33, 32, 255, 255, 10, 255, 7,
255, 0, 0, 0, 6, 0, 10, 1, 7, 7, 6, 2, 0, 128, 128, 128,
128, 128, 0, 128, 3, 2, 2, 6, 1, 5, 160, 160, 5, 7, 7, 6,
0, 0, 80, 80, 248, 80, 248, 80, 80, 5, 7, 7, 6, 0, 0, 32,
120, 160, 112, 40, 240, 32, 5, 7, 7, 6, 0, 0, 192, 200, 16, 32,
64, 152, 24, 5, 7, 7, 6, 0, 0, 96, 144, 160, 64, 168, 144, 104,
2, 3, 3, 6, 1, 4, 192, 64, 128, 3, 7, 7, 6, 1, 0, 32,
64, 128, 128, 128, 64, 32, 3, 7, 7, 6, 1, 0, 128, 64, 32, 32,
32, 64, 128, 5, 5, 5, 6, 0, 1, 32, 168, 112, 168, 32, 5, 5,
5, 6, 0, 1, 32, 32, 248, 32, 32, 2, 3, 3, 6, 2, 255, 192,
64, 128, 5, 1, 1, 6, 0, 3, 248, 2, 2, 2, 6, 2, 0, 192,
192, 5, 5, 5, 6, 0, 1, 8, 16, 32, 64, 128, 5, 7, 7, 6,
0, 0, 112, 136, 152, 168, 200, 136, 112, 3, 7, 7, 6, 1, 0, 64,
192, 64, 64, 64, 64, 224, 5, 7, 7, 6, 0, 0, 112, 136, 8, 112,
128, 128, 248, 5, 7, 7, 6, 0, 0, 248, 16, 32, 16, 8, 8, 240,
5, 7, 7, 6, 0, 0, 16, 48, 80, 144, 248, 16, 16, 5, 7, 7,
6, 0, 0, 248, 128, 240, 8, 8, 136, 112, 5, 7, 7, 6, 0, 0,
112, 128, 128, 240, 136, 136, 112, 5, 7, 7, 6, 0, 0, 248, 8, 16,
32, 32, 32, 32, 5, 7, 7, 6, 0, 0, 112, 136, 136, 112, 136, 136,
112, 5, 7, 7, 6, 0, 0, 112, 136, 136, 120, 8, 8, 112, 2, 5,
5, 6, 2, 0, 192, 192, 0, 192, 192, 2, 6, 6, 6, 2, 255, 192,
192, 0, 192, 64, 128, 4, 7, 7, 6, 0, 0, 16, 32, 64, 128, 64,
32, 16, 5, 3, 3, 6, 0, 2, 248, 0, 248, 4, 7, 7, 6, 0,
0, 128, 64, 32, 16, 32, 64, 128, 5, 7, 7, 6, 0, 0, 112, 136,
8, 16, 32, 0, 32, 5, 7, 7, 6, 0, 0, 112, 136, 8, 104, 168,
168, 112, 5, 7, 7, 6, 0, 0, 112, 136, 136, 248, 136, 136, 136, 5,
7, 7, 6, 0, 0, 240, 136, 136, 240, 136, 136, 240, 5, 7, 7, 6,
0, 0, 112, 136, 128, 128, 128, 136, 112, 5, 7, 7, 6, 0, 0, 240,
136, 136, 136, 136, 136, 240, 5, 7, 7, 6, 0, 0, 248, 128, 128, 240,
128, 128, 248, 5, 7, 7, 6, 0, 0, 248, 128, 128, 240, 128, 128, 128,
5, 7, 7, 6, 0, 0, 112, 136, 128, 184, 136, 136, 112, 5, 7, 7,
6, 0, 0, 136, 136, 136, 248, 136, 136, 136, 1, 7, 7, 6, 2, 0,
128, 128, 128, 128, 128, 128, 128, 5, 7, 7, 6, 0, 0, 56, 16, 16,
16, 16, 144, 96, 5, 7, 7, 6, 0, 0, 136, 144, 160, 192, 160, 144,
136, 5, 7, 7, 6, 0, 0, 128, 128, 128, 128, 128, 128, 248, 5, 7,
7, 6, 0, 0, 136, 216, 168, 136, 136, 136, 136, 5, 7, 7, 6, 0,
0, 136, 136, 200, 168, 152, 136, 136, 5, 7, 7, 6, 0, 0, 112, 136,
136, 136, 136, 136, 112, 5, 7, 7, 6, 0, 0, 240, 136, 136, 240, 128,
128, 128, 5, 7, 7, 6, 0, 0, 112, 136, 136, 136, 168, 144, 104, 5,
7, 7, 6, 0, 0, 240, 136, 136, 240, 160, 144, 136, 5, 7, 7, 6,
0, 0, 120, 128, 128, 112, 8, 8, 240, 5, 7, 7, 6, 0, 0, 248,
32, 32, 32, 32, 32, 32, 5, 7, 7, 6, 0, 0, 136, 136, 136, 136,
136, 136, 112, 5, 7, 7, 6, 0, 0, 136, 136, 136, 136, 136, 80, 32,
5, 7, 7, 6, 0, 0, 136, 136, 136, 136, 136, 168, 80, 5, 7, 7,
6, 0, 0, 136, 136, 80, 32, 80, 136, 136, 5, 7, 7, 6, 0, 0,
136, 136, 136, 80, 32, 32, 32, 5, 7, 7, 6, 0, 0, 248, 8, 16,
32, 64, 128, 248, 3, 7, 7, 6, 0, 0, 224, 128, 128, 128, 128, 128,
224, 5, 5, 5, 6, 0, 1, 128, 64, 32, 16, 8, 3, 7, 7, 6,
0, 0, 224, 32, 32, 32, 32, 32, 224, 5, 3, 3, 6, 0, 4, 32,
80, 136, 5, 1, 1, 6, 0, 0, 248, 2, 2, 2, 6, 2, 5, 128,
64, 5, 5, 5, 6, 0, 0, 112, 8, 120, 136, 120, 5, 7, 7, 6,
0, 0, 128, 128, 176, 200, 136, 136, 240, 5, 5, 5, 6, 0, 0, 112,
128, 128, 136, 112, 5, 7, 7, 6, 0, 0, 8, 8, 104, 152, 136, 136,
120, 5, 5, 5, 6, 0, 0, 112, 136, 248, 128, 112, 5, 7, 7, 6,
0, 0, 48, 72, 224, 64, 64, 64, 64, 5, 6, 6, 6, 0, 255, 112,
136, 136, 120, 8, 112, 5, 7, 7, 6, 0, 0, 128, 128, 176, 200, 136,
136, 136, 1, 7, 7, 6, 2, 0, 128, 0, 128, 128, 128, 128, 128, 3,
8, 8, 6, 1, 255, 32, 0, 32, 32, 32, 32, 160, 64, 4, 7, 7,
6, 1, 0, 128, 128, 144, 160, 192, 160, 144, 3, 7, 7, 6, 1, 0,
192, 64, 64, 64, 64, 64, 224, 5, 5, 5, 6, 0, 0, 208, 168, 168,
168, 168, 5, 5, 5, 6, 0, 0, 176, 200, 136, 136, 136, 5, 5, 5,
6, 0, 0, 112, 136, 136, 136, 112, 5, 6, 6, 6, 0, 255, 240, 136,
136, 240, 128, 128, 5, 6, 6, 6, 0, 255, 120, 136, 136, 120, 8, 8,
5, 5, 5, 6, 0, 0, 176, 200, 128, 128, 128, 5, 5, 5, 6, 0,
0, 112, 128, 112, 8, 240, 4, 7, 7, 6, 0, 0, 64, 64, 224, 64,
64, 64, 48, 5, 5, 5, 6, 0, 0, 136, 136, 136, 152, 104, 5, 5,
5, 6, 0, 0, 136, 136, 136, 80, 32, 5, 5, 5, 6, 0, 0, 136,
136, 168, 168, 80, 5, 5, 5, 6, 0, 0, 136, 80, 32, 80, 136, 5,
6, 6, 6, 0, 255, 136, 136, 136, 120, 8, 112, 5, 5, 5, 6, 0,
0, 248, 16, 32, 64, 248, 3, 7, 7, 6, 1, 0, 32, 64, 64, 128,
64, 64, 32, 1, 7, 7, 6, 2, 0, 128, 128, 128, 128, 128, 128, 128,
3, 7, 7, 6, 1, 0, 128, 64, 64, 32, 64, 64, 128, 5, 2, 2,
6, 0, 3, 104, 144, 0, 0, 0, 6, 0, 10, 0, 0, 0, 12, 0,
10, 0, 0, 0, 12, 0, 10, 0, 0, 0, 12, 0, 10, 0, 0, 0,
12, 0, 10, 0, 0, 0, 12, 0, 10, 0, 0, 0, 12, 0, 10, 0,
0, 0, 12, 0, 10, 0, 0, 0, 12, 0, 10, 0, 0, 0, 12, 0,
10, 0, 0, 0, 12, 0, 10, 0, 0, 0, 12, 0, 10, 0, 0, 0,
12, 0, 10, 0, 0, 0, 12, 0, 10, 0, 0, 0, 12, 0, 10, 0,
0, 0, 12, 0, 10, 0, 0, 0, 12, 0, 10, 0, 0, 0, 12, 0,
10, 0, 0, 0, 12, 0, 10, 0, 0, 0, 12, 0, 10, 0, 0, 0,
12, 0, 10, 0, 0, 0, 12, 0, 10, 0, 0, 0, 12, 0, 10, 0,
0, 0, 12, 0, 10, 0, 0, 0, 12, 0, 10, 0, 0, 0, 12, 0,
10, 0, 0, 0, 12, 0, 10, 0, 0, 0, 12, 0, 10, 0, 0, 0,
12, 0, 10, 0, 0, 0, 12, 0, 10, 11, 11, 22, 12, 0, 255, 255,
224, 2, 0, 2, 0, 4, 0, 13, 0, 20, 128, 36, 64, 196, 32, 4,
0, 4, 0, 4, 0, 11, 11, 22, 12, 0, 255, 249, 0, 138, 0, 171,
224, 172, 64, 170, 64, 170, 64, 170, 64, 170, 128, 33, 0, 82, 128, 140,
96, 11, 11, 22, 12, 0, 255, 36, 0, 36, 0, 63, 128, 68, 0, 132,
0, 4, 0, 255, 224, 10, 0, 17, 0, 32, 128, 192, 96, 11, 11, 22,
12, 0, 255, 36, 0, 36, 0, 63, 192, 68, 0, 4, 0, 255, 224, 9,
0, 9, 0, 17, 32, 33, 32, 64, 224, 11, 11, 22, 12, 0, 255, 32,
0, 61, 224, 81, 32, 145, 32, 17, 32, 255, 32, 17, 32, 41, 32, 37,
224, 69, 32, 128, 0, 11, 11, 22, 12, 0, 255, 32, 128, 127, 192, 8,
64, 255, 224, 17, 0, 32, 128, 95, 64, 128, 32, 63, 128, 0, 0, 127,
192, 11, 11, 22, 12, 0, 255, 34, 64, 71, 224, 148, 128, 228, 128, 47,
224, 68, 128, 244, 128, 7, 224, 52, 128, 196, 128, 7, 224, 11, 11, 22,
12, 0, 255, 4, 128, 143, 224, 73, 0, 25, 0, 47, 192, 9, 0, 9,
0, 47, 192, 73, 0, 137, 0, 15, 224, 11, 11, 22, 12, 0, 255, 16,
0, 63, 128, 81, 0, 14, 0, 49, 128, 192, 96, 63, 128, 36, 128, 63,
128, 36, 128, 63, 128, 11, 11, 22, 12, 0, 255, 34, 128, 250, 64, 7,
224, 250, 128, 138, 128, 138, 128, 250, 128, 34, 128, 178, 128, 170, 160, 100,
224, 11, 11, 22, 12, 0, 255, 34, 32, 71, 64, 146, 128, 239, 224, 34,
0, 71, 192, 236, 64, 7, 192, 52, 64, 199, 192, 4, 64, 11, 11, 22,
12, 0, 255, 8, 0, 15, 192, 8, 0, 8, 0, 255, 224, 8, 0, 14,
0, 9, 128, 8, 64, 8, 0, 8, 0, 10, 11, 22, 12, 0, 255, 255,
128, 0, 128, 0, 128, 128, 128, 128, 128, 255, 128, 128, 0, 128, 0, 128,
64, 128, 64, 127, 192, 11, 11, 22, 12, 0, 255, 71, 192, 65, 0, 239,
224, 65, 0, 69, 0, 105, 96, 201, 32, 77, 96, 73, 32, 79, 224, 200,
32, 11, 11, 22, 12, 0, 255, 8, 0, 4, 0, 4, 0, 10, 0, 10,
0, 10, 0, 17, 0, 17, 0, 32, 128, 64, 64, 128, 32, 11, 11, 22,
12, 0, 255, 34, 64, 34, 0, 247, 224, 34, 0, 35, 224, 53, 32, 229,
32, 37, 64, 40, 128, 41, 64, 114, 32, 11, 10, 20, 12, 0, 0, 68,
64, 68, 64, 68, 64, 127, 192, 4, 0, 4, 0, 132, 32, 132, 32, 132,
32, 255, 224, 11, 11, 22, 12, 0, 255, 4, 0, 0, 0, 127, 192, 4,
0, 4, 0, 4, 0, 127, 192, 4, 0, 4, 0, 4, 0, 255, 224, 11,
11, 22, 12, 0, 255, 255, 224, 17, 0, 1, 192, 254, 0, 72, 128, 37,
0, 4, 0, 255, 224, 21, 0, 36, 128, 196, 96, 11, 11, 22, 12, 0,
255, 17, 0, 127, 192, 68, 64, 127, 192, 68, 64, 127, 192, 4, 0, 255,
224, 4, 0, 4, 0, 4, 0, 9, 11, 22, 12, 0, 255, 16, 0, 255,
128, 128, 128, 128, 128, 255, 128, 128, 128, 128, 128, 255, 128, 128, 128, 128,
128, 255, 128, 11, 11, 22, 12, 0, 255, 113, 0, 1, 0, 3, 224, 249,
32, 33, 32, 65, 32, 81, 32, 137, 32, 250, 32, 2, 32, 4, 192, 11,
11, 22, 12, 0, 255, 127, 192, 17, 0, 17, 0, 17, 0, 17, 0, 255,
224, 17, 0, 17, 0, 33, 0, 33, 0, 65, 0, 11, 11, 22, 12, 0,
255, 33, 0, 34, 0, 244, 64, 87, 224, 80, 32, 87, 192, 148, 64, 84,
64, 36, 64, 87, 192, 148, 64, 11, 11, 22, 12, 0, 255, 17, 0, 10,
0, 127, 192, 4, 0, 4, 0, 255, 224, 4, 0, 10, 0, 17, 0, 32,
128, 192, 96, 10, 11, 22, 12, 0, 255, 95, 192, 0, 64, 132, 64, 132,
64, 191, 64, 132, 64, 140, 64, 148, 64, 164, 64, 140, 64, 129, 192, 11,
11, 22, 12, 0, 255, 36, 0, 39, 192, 36, 0, 36, 0, 255, 224, 0,
0, 20, 64, 36, 128, 71, 0, 12, 0, 112, 0, 11, 11, 22, 12, 0,
255, 36, 128, 4, 128, 15, 192, 228, 128, 36, 128, 63, 224, 36, 128, 36,
128, 40, 128, 80, 0, 143, 224, 11, 11, 22, 12, 0, 255, 8, 0, 8,
0, 255, 128, 136, 128, 136, 128, 255, 128, 136, 128, 136, 128, 255, 160, 136,
32, 7, 224, 11, 11, 22, 12, 0, 255, 39, 128, 36, 128, 244, 128, 36,
128, 116, 128, 108, 128, 164, 128, 36, 128, 36, 160, 40, 160, 48, 96, 10,
11, 22, 12, 0, 255, 255, 192, 128, 64, 128, 64, 158, 64, 146, 64, 146,
64, 158, 64, 128, 64, 128, 64, 255, 192, 128, 64, 11, 11, 22, 12, 0,
255, 127, 192, 68, 0, 95, 192, 80, 64, 95, 192, 80, 64, 95, 192, 66,
0, 74, 128, 82, 64, 166, 32, 11, 11, 22, 12, 0, 255, 4, 0, 7,
224, 4, 0, 127, 192, 64, 64, 64, 64, 64, 64, 127, 192, 0, 0, 82,
64, 137, 32, 11, 11, 22, 12, 0, 255, 71, 128, 36, 128, 4, 128, 4,
128, 232, 96, 32, 0, 47, 192, 36, 64, 34, 128, 49, 0, 38, 192, 11,
11, 22, 12, 0, 255, 127, 192, 74, 64, 127, 192, 4, 0, 255, 224, 4,
0, 63, 128, 32, 128, 36, 128, 36, 128, 255, 224, 11, 11, 22, 12, 0,
255, 34, 0, 79, 224, 72, 32, 79, 224, 200, 0, 79, 224, 74, 160, 90,
160, 111, 224, 74, 160, 72, 96, 11, 11, 22, 12, 0, 255, 243, 192, 36,
64, 42, 128, 241, 0, 34, 128, 101, 224, 114, 32, 165, 64, 32, 128, 35,
0, 44, 0, 11, 11, 22, 12, 0, 255, 4, 0, 255, 224, 128, 32, 0,
0, 255, 224, 4, 0, 36, 0, 39, 192, 36, 0, 84, 0, 143, 224, 11,
11, 22, 12, 0, 255, 115, 224, 16, 128, 81, 0, 35, 224, 250, 32, 42,
160, 34, 160, 34, 160, 32, 128, 33, 64, 98, 32, 11, 11, 22, 12, 0,
255, 34, 0, 247, 128, 34, 128, 54, 128, 226, 160, 37, 160, 36, 96, 104,
32, 0, 0, 82, 64, 137, 32, 11, 11, 22, 12, 0, 255, 115, 192, 66,
0, 66, 0, 123, 224, 74, 64, 74, 64, 122, 64, 74, 64, 66, 64, 68,
64, 136, 64, 11, 11, 22, 12, 0, 255, 8, 0, 255, 224, 8, 0, 31,
192, 48, 64, 95, 192, 144, 64, 31, 192, 16, 64, 16, 64, 16, 192, 11,
11, 22, 12, 0, 255, 2, 0, 127, 224, 66, 0, 66, 0, 95, 192, 66,
0, 71, 0, 74, 128, 82, 64, 98, 32, 130, 0, 11, 11, 22, 12, 0,
255, 243, 192, 150, 64, 145, 128, 166, 96, 161, 0, 151, 192, 145, 0, 149,
0, 231, 224, 129, 0, 129, 0, 11, 11, 22, 12, 0, 255, 15, 128, 136,
128, 79, 128, 8, 128, 143, 128, 64, 0, 31, 192, 53, 64, 85, 64, 149,
64, 63, 224, 11, 11, 22, 12, 0, 255, 39, 224, 32, 128, 248, 128, 32,
128, 32, 128, 56, 128, 224, 128, 32, 128, 32, 128, 32, 128, 97, 128, 11,
11, 22, 12, 0, 255, 31, 224, 145, 0, 87, 192, 20, 64, 23, 192, 148,
64, 87, 192, 17, 0, 85, 64, 153, 32, 35, 0, 11, 11, 22, 12, 0,
255, 32, 128, 39, 224, 242, 64, 33, 128, 34, 64, 52, 32, 226, 64, 34,
64, 34, 64, 34, 64, 100, 64, 11, 11, 22, 12, 0, 255, 65, 0, 65,
0, 79, 224, 233, 32, 73, 32, 73, 32, 111, 224, 201, 32, 73, 32, 73,
32, 207, 224, 11, 11, 22, 12, 0, 255, 33, 0, 241, 0, 79, 224, 169,
32, 249, 32, 47, 224, 57, 32, 233, 32, 41, 32, 47, 224, 40, 32, 11,
11, 22, 12, 0, 255, 143, 224, 73, 32, 9, 32, 203, 160, 73, 32, 79,
224, 72, 32, 75, 160, 74, 160, 107, 160, 80, 224, 11, 11, 22, 12, 0,
255, 127, 192, 4, 0, 68, 64, 36, 64, 36, 128, 4, 0, 255, 224, 4,
0, 4, 0, 4, 0, 4, 0, 11, 11, 22, 12, 0, 255, 130, 0, 66,
0, 31, 224, 194, 0, 95, 192, 82, 64, 95, 192, 71, 0, 74, 128, 82,
64, 191, 224, 11, 11, 22, 12, 0, 255, 4, 0, 127, 224, 72, 128, 127,
224, 72, 128, 79, 128, 64, 0, 95, 192, 72, 64, 71, 128, 152, 96, 11,
11, 22, 12, 0, 255, 1, 0, 239, 224, 161, 0, 164, 64, 175, 224, 164,
64, 175, 224, 169, 32, 233, 32, 2, 128, 12, 96, 11, 11, 22, 12, 0,
255, 20, 192, 246, 160, 188, 96, 167, 128, 168, 128, 191, 224, 169, 32, 239,
224, 9, 32, 15, 224, 9, 32, 11, 11, 22, 12, 0, 255, 127, 128, 64,
128, 66, 128, 98, 128, 84, 128, 72, 128, 72, 128, 84, 160, 98, 160, 64,
96, 128, 32, 11, 11, 22, 12, 0, 255, 4, 0, 127, 224, 64, 32, 127,
224, 64, 0, 125, 224, 84, 32, 76, 160, 84, 96, 100, 160, 141, 96, 11,
11, 22, 12, 0, 255, 130, 0, 95, 224, 4, 0, 8, 64, 159, 224, 64,
32, 10, 128, 10, 128, 74, 160, 146, 160, 34, 96, 11, 11, 22, 12, 0,
255, 65, 0, 79, 224, 232, 32, 66, 128, 68, 64, 104, 32, 199, 192, 65,
0, 65, 0, 65, 0, 207, 224, 11, 11, 22, 12, 0, 255, 80, 32, 125,
32, 145, 32, 255, 32, 17, 32, 125, 32, 85, 32, 85, 32, 84, 32, 92,
32, 16, 224, 11, 11, 22, 12, 0, 255, 63, 128, 32, 128, 63, 128, 32,
128, 255, 224, 72, 0, 123, 192, 73, 64, 121, 64, 72, 128, 251, 96, 11,
11, 22, 12, 0, 255, 4, 0, 4, 0, 4, 0, 36, 128, 36, 64, 68,
64, 68, 32, 132, 32, 4, 0, 4, 0, 28, 0, 11, 11, 22, 12, 0,
255, 4, 0, 4, 0, 4, 0, 255, 224, 4, 0, 10, 0, 10, 0, 17,
0, 17, 0, 32, 128, 192, 96, 9, 10, 20, 10, 0, 0, 136, 128, 73,
0, 8, 0, 255, 128, 0, 128, 0, 128, 127, 128, 0, 128, 0, 128, 255,
128, 11, 11, 22, 12, 0, 255, 33, 0, 18, 0, 255, 224, 0, 0, 120,
128, 74, 128, 122, 128, 74, 128, 122, 128, 72, 128, 89, 128, 11, 11, 22,
12, 0, 255, 39, 192, 0, 0, 0, 0, 239, 224, 33, 0, 34, 0, 36,
64, 47, 224, 32, 32, 80, 0, 143, 224, 11, 11, 22, 12, 0, 255, 32,
128, 39, 0, 249, 0, 33, 192, 119, 0, 33, 0, 249, 224, 39, 0, 113,
32, 169, 32, 32, 224, 11, 11, 22, 12, 0, 255, 16, 64, 16, 64, 253,
224, 16, 64, 56, 192, 53, 64, 82, 64, 148, 64, 16, 64, 16, 64, 16,
192, 11, 11, 22, 12, 0, 255, 0, 64, 248, 64, 11, 224, 8, 64, 136,
64, 82, 64, 81, 64, 33, 64, 80, 64, 72, 64, 137, 192, 10, 11, 22,
12, 0, 255, 132, 0, 132, 64, 132, 128, 245, 0, 134, 0, 132, 0, 132,
0, 148, 0, 164, 64, 196, 64, 131, 192, 11, 11, 22, 12, 0, 255, 17,
32, 125, 0, 17, 0, 255, 224, 41, 0, 253, 64, 73, 64, 124, 128, 8,
160, 253, 96, 10, 32, 11, 11, 22, 12, 0, 255, 23, 192, 36, 64, 36,
64, 103, 192, 161, 0, 47, 224, 33, 0, 35, 128, 37, 64, 41, 32, 33,
0, 11, 11, 22, 12, 0, 255, 8, 0, 255, 224, 16, 0, 39, 192, 32,
128, 97, 0, 175, 224, 33, 0, 33, 0, 33, 0, 35, 0, 11, 11, 22,
12, 0, 255, 36, 0, 47, 224, 180, 0, 164, 128, 164, 160, 170, 192, 42,
128, 40, 128, 41, 64, 50, 64, 36, 32, 11, 11, 22, 12, 0, 255, 127,
224, 128, 0, 63, 192, 32, 64, 63, 192, 16, 0, 31, 192, 16, 64, 40,
128, 71, 0, 56, 224, 11, 11, 22, 12, 0, 255, 127, 224, 64, 0, 64,
0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 64, 0, 128,
0, 11, 11, 22, 12, 0, 255, 255, 224, 4, 0, 127, 192, 68, 64, 127,
192, 68, 64, 127, 192, 68, 0, 36, 0, 24, 0, 231, 224, 11, 11, 22,
12, 0, 255, 17, 224, 253, 0, 69, 0, 41, 224, 253, 64, 17, 64, 125,
64, 17, 64, 85, 64, 146, 64, 52, 64, 11, 11, 22, 12, 0, 255, 33,
0, 95, 224, 64, 0, 207, 192, 64, 0, 79, 192, 64, 0, 79, 192, 72,
64, 79, 192, 72, 64, 11, 11, 22, 12, 0, 255, 4, 0, 127, 192, 64,
64, 127, 192, 64, 64, 127, 192, 64, 64, 127, 192, 4, 64, 82, 32, 191,
160, 11, 11, 22, 12, 0, 255, 127, 192, 68, 64, 127, 192, 68, 64, 127,
192, 4, 0, 27, 0, 224, 224, 17, 0, 17, 0, 97, 0, 11, 11, 22,
12, 0, 255, 255, 224, 4, 0, 8, 0, 127, 224, 73, 32, 79, 32, 73,
32, 79, 32, 73, 32, 73, 32, 127, 224, 11, 11, 22, 12, 0, 255, 253,
224, 86, 64, 121, 64, 56, 128, 85, 64, 146, 32, 255, 224, 4, 0, 39,
192, 36, 0, 255, 224, 11, 11, 22, 12, 0, 255, 251, 128, 82, 0, 123,
224, 18, 64, 250, 64, 20, 64, 63, 128, 32, 128, 63, 128, 32, 128, 63,
128, 11, 11, 22, 12, 0, 255, 31, 224, 32, 0, 39, 192, 100, 64, 167,
192, 32, 0, 47, 224, 40, 32, 39, 192, 33, 0, 35, 0, 11, 11, 22,
12, 0, 255, 243, 224, 130, 32, 130, 32, 250, 32, 130, 32, 130, 32, 138,
32, 178, 32, 194, 224, 2, 0, 2, 0, 11, 11, 22, 12, 0, 255, 36,
128, 70, 160, 149, 192, 228, 128, 39, 224, 68, 128, 245, 192, 6, 160, 52,
128, 196, 128, 7, 224, 11, 11, 22, 12, 0, 255, 39, 192, 65, 0, 135,
224, 224, 32, 34, 128, 69, 128, 242, 128, 15, 224, 48, 128, 193, 64, 2,
32, 11, 11, 22, 12, 0, 255, 2, 0, 2, 0, 34, 0, 35, 192, 34,
0, 34, 0, 34, 0, 34, 0, 34, 0, 34, 0, 255, 224, 9, 11, 22,
12, 0, 255, 8, 0, 8, 0, 255, 128, 136, 128, 136, 128, 136, 128, 255,
128, 136, 128, 136, 128, 136, 128, 255, 128, 11, 11, 22, 12, 0, 255, 33,
0, 83, 160, 65, 0, 247, 224, 81, 0, 83, 192, 86, 64, 83, 192, 90,
64, 83, 192, 66, 64, 11, 11, 22, 12, 0, 255, 127, 192, 4, 0, 4,
0, 4, 0, 255, 224, 10, 0, 10, 0, 18, 0, 34, 32, 66, 32, 129,
224, 11, 11, 22, 12, 0, 255, 17, 0, 33, 0, 47, 224, 97, 0, 163,
128, 35, 128, 37, 64, 37, 64, 41, 32, 33, 0, 33, 0, 11, 11, 22,
12, 0, 255, 247, 224, 148, 32, 244, 32, 151, 224, 148, 128, 244, 128, 151,
224, 148, 128, 244, 160, 150, 96, 4, 32, 11, 11, 22, 12, 0, 255, 123,
224, 148, 128, 4, 0, 127, 192, 4, 0, 255, 224, 1, 0, 255, 224, 33,
0, 17, 0, 7, 0, 11, 11, 22, 12, 0, 255, 33, 0, 71, 192, 145,
0, 47, 224, 96, 128, 175, 224, 32, 128, 36, 128, 34, 128, 32, 128, 35,
128, 11, 11, 22, 12, 0, 255, 39, 192, 36, 64, 247, 192, 46, 224, 42,
160, 62, 224, 225, 0, 47, 224, 35, 128, 37, 64, 105, 32, 11, 11, 22,
12, 0, 255, 20, 0, 39, 224, 42, 0, 98, 0, 163, 192, 34, 0, 34,
0, 35, 224, 34, 0, 34, 0, 34, 0
};

View File

@ -0,0 +1,192 @@
/*
Fontname: ISO10646_CZ
Copyright: A. Hardtung, public domain
Modified for Czech accents by Petr Zahradnik, http://www.zahradniksebavi.cz
Capital A Height: 7, '1' Height: 7
Calculated Max Values w= 6 h= 9 x= 2 y= 7 dx= 6 dy= 0 ascent= 8 len= 9
Font Bounding box w= 6 h= 9 x= 0 y=-2
Calculated Min Values x= 0 y=-1 dx= 0 dy= 0
Pure Font ascent = 7 descent=-1
X Font ascent = 7 descent=-1
Max Font ascent = 8 descent=-1
*/
#include <U8glib.h>
const u8g_fntpgm_uint8_t ISO10646_CZ[2832] U8G_SECTION(".progmem.ISO10646_CZ") = {
0,6,9,0,254,7,1,146,3,33,32,255,255,8,255,7,
255,0,0,0,6,0,0,1,7,7,6,2,0,128,128,128,
128,128,0,128,3,2,2,6,1,5,160,160,5,7,7,6,
0,0,80,80,248,80,248,80,80,5,7,7,6,0,0,32,
120,160,112,40,240,32,5,7,7,6,0,0,192,200,16,32,
64,152,24,5,7,7,6,0,0,96,144,160,64,168,144,104,
2,3,3,6,1,4,192,64,128,3,7,7,6,1,0,32,
64,128,128,128,64,32,3,7,7,6,1,0,128,64,32,32,
32,64,128,5,5,5,6,0,1,32,168,112,168,32,5,5,
5,6,0,1,32,32,248,32,32,2,3,3,6,2,255,192,
64,128,5,1,1,6,0,3,248,2,2,2,6,2,0,192,
192,5,5,5,6,0,1,8,16,32,64,128,5,7,7,6,
0,0,112,136,136,136,136,136,112,3,7,7,6,1,0,64,
192,64,64,64,64,224,5,7,7,6,0,0,112,136,8,112,
128,128,248,5,7,7,6,0,0,248,16,32,16,8,8,240,
5,7,7,6,0,0,16,48,80,144,248,16,16,5,7,7,
6,0,0,248,128,240,8,8,136,112,5,7,7,6,0,0,
112,128,128,240,136,136,112,5,7,7,6,0,0,248,8,16,
32,32,32,32,5,7,7,6,0,0,112,136,136,112,136,136,
112,5,7,7,6,0,0,112,136,136,120,8,8,112,2,5,
5,6,2,0,192,192,0,192,192,2,6,6,6,2,255,192,
192,0,192,64,128,4,7,7,6,0,0,16,32,64,128,64,
32,16,5,3,3,6,0,2,248,0,248,4,7,7,6,1,
0,128,64,32,16,32,64,128,5,7,7,6,0,0,112,136,
8,16,32,0,32,5,7,7,6,0,0,112,136,8,104,168,
168,112,5,7,7,6,0,0,112,136,136,248,136,136,136,5,
7,7,6,0,0,240,136,136,240,136,136,240,5,7,7,6,
0,0,112,136,128,128,128,136,112,5,7,7,6,0,0,240,
136,136,136,136,136,240,5,7,7,6,0,0,248,128,128,240,
128,128,248,5,7,7,6,0,0,248,128,128,240,128,128,128,
5,7,7,6,0,0,112,136,128,184,136,136,112,5,7,7,
6,0,0,136,136,136,248,136,136,136,1,7,7,6,2,0,
128,128,128,128,128,128,128,5,7,7,6,0,0,56,16,16,
16,16,144,96,5,7,7,6,0,0,136,144,160,192,160,144,
136,5,7,7,6,0,0,128,128,128,128,128,128,248,5,7,
7,6,0,0,136,216,168,136,136,136,136,5,7,7,6,0,
0,136,136,200,168,152,136,136,5,7,7,6,0,0,112,136,
136,136,136,136,112,5,7,7,6,0,0,240,136,136,240,128,
128,128,5,7,7,6,0,0,112,136,136,136,168,144,104,5,
7,7,6,0,0,240,136,136,240,160,144,136,5,7,7,6,
0,0,120,128,128,112,8,8,240,5,7,7,6,0,0,248,
32,32,32,32,32,32,5,7,7,6,0,0,136,136,136,136,
136,136,112,5,7,7,6,0,0,136,136,136,136,136,80,32,
5,7,7,6,0,0,136,136,136,136,136,168,80,5,7,7,
6,0,0,136,136,80,32,80,136,136,5,7,7,6,0,0,
136,136,136,80,32,32,32,5,7,7,6,0,0,248,8,16,
32,64,128,248,3,7,7,6,1,0,224,128,128,128,128,128,
224,5,5,5,6,0,1,128,64,32,16,8,3,7,7,6,
1,0,224,32,32,32,32,32,224,5,3,3,6,0,4,32,
80,136,5,1,1,6,0,0,248,2,2,2,6,2,5,128,
64,5,5,5,6,0,0,112,8,120,136,120,5,7,7,6,
0,0,128,128,176,200,136,136,240,5,5,5,6,0,0,112,
128,128,136,112,5,7,7,6,0,0,8,8,104,152,136,136,
120,5,5,5,6,0,0,112,136,248,128,112,5,7,7,6,
0,0,48,72,224,64,64,64,64,5,6,6,6,0,255,112,
136,136,120,8,112,5,7,7,6,0,0,128,128,176,200,136,
136,136,1,7,7,6,2,0,128,0,128,128,128,128,128,3,
8,8,6,1,255,32,0,32,32,32,32,160,64,4,7,7,
6,0,0,128,128,144,160,192,160,144,3,7,7,6,1,0,
192,64,64,64,64,64,224,5,5,5,6,0,0,208,168,168,
168,168,5,5,5,6,0,0,176,200,136,136,136,5,5,5,
6,0,0,112,136,136,136,112,5,6,6,6,0,255,240,136,
136,240,128,128,5,6,6,6,0,255,120,136,136,120,8,8,
5,5,5,6,0,0,176,200,128,128,128,5,5,5,6,0,
0,112,128,112,8,240,4,7,7,6,0,0,64,64,224,64,
64,64,48,5,5,5,6,0,0,136,136,136,152,104,5,5,
5,6,0,0,136,136,136,80,32,5,5,5,6,0,0,136,
136,168,168,80,5,5,5,6,0,0,136,80,32,80,136,5,
6,6,6,0,255,136,136,136,120,8,112,5,5,5,6,0,
0,248,16,32,64,248,3,7,7,6,1,0,32,64,64,128,
64,64,32,1,7,7,6,2,0,128,128,128,128,128,128,128,
3,7,7,6,1,0,128,64,64,32,64,64,128,5,2,2,
6,0,2,104,144,0,0,0,6,0,0,5,8,8,6,0,
0,16,32,112,136,136,248,136,136,5,8,8,6,0,0,8,
16,248,128,128,240,128,248,3,8,8,6,1,0,32,64,224,
64,64,64,64,224,5,8,8,6,0,0,16,32,112,136,136,
136,136,112,5,8,8,6,0,0,16,32,136,136,136,136,136,
112,5,8,8,6,0,0,16,32,136,136,80,32,32,32,5,
8,8,6,0,0,16,32,0,112,8,120,136,120,5,8,8,
6,0,0,16,32,0,112,136,248,128,112,2,8,8,6,2,
0,64,128,0,128,128,128,128,128,5,8,8,6,0,0,16,
32,0,112,136,136,136,112,5,8,8,6,0,0,16,32,0,
136,136,136,152,104,5,9,9,6,0,255,16,32,0,136,136,
136,120,8,112,5,8,8,6,0,0,80,32,112,136,128,128,
136,112,5,8,8,6,0,0,80,32,0,112,128,128,136,112,
5,8,8,6,0,0,80,32,240,136,136,136,136,240,6,8,
8,6,0,0,4,20,24,112,144,144,144,112,5,8,8,6,
0,0,80,32,248,128,128,240,128,248,5,8,8,6,0,0,
80,32,0,112,136,248,128,112,5,8,8,6,0,0,80,32,
136,200,168,152,136,136,5,8,8,6,0,0,80,32,0,176,
200,136,136,136,5,8,8,6,0,0,80,32,240,136,240,160,
144,136,5,8,8,6,0,0,80,32,0,176,200,128,128,128,
5,8,8,6,0,0,80,32,120,128,128,112,8,240,5,8,
8,6,0,0,80,32,0,112,128,112,8,240,5,8,8,6,
0,0,80,32,248,32,32,32,32,32,6,8,8,6,0,0,
4,68,72,224,64,64,64,48,5,8,8,6,0,0,32,80,
168,136,136,136,136,112,5,8,8,6,0,0,32,80,32,136,
136,136,152,104,5,8,8,6,0,0,80,32,248,8,48,64,
128,248,5,8,8,6,0,0,80,32,0,248,16,32,64,248,
0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,
0,0,1,7,7,6,2,0,128,0,128,128,128,128,128,5,
7,7,6,0,0,32,112,168,160,168,112,32,5,7,7,6,
0,0,48,64,64,224,64,80,168,5,5,5,6,0,0,136,
112,80,112,136,5,7,7,6,0,0,136,80,32,248,32,248,
32,1,7,7,6,2,0,128,128,128,0,128,128,128,5,8,
8,6,0,0,48,72,32,80,80,32,144,96,3,1,1,6,
1,7,160,5,7,7,6,0,0,248,136,184,184,184,136,248,
5,7,7,6,0,1,112,8,120,136,120,0,248,5,5,5,
6,0,1,40,80,160,80,40,5,3,3,6,0,1,248,8,
8,2,2,2,6,2,6,64,128,5,7,7,6,0,0,248,
136,168,136,152,168,248,5,1,1,6,0,6,248,4,4,4,
6,0,3,96,144,144,96,5,7,7,6,0,0,32,32,248,
32,32,0,248,4,5,5,6,0,3,96,144,32,64,240,3,
5,5,6,0,3,224,32,224,32,224,2,2,2,6,2,6,
64,128,5,8,8,6,0,255,136,136,136,136,152,232,128,128,
5,7,7,6,0,0,120,152,152,120,24,24,24,2,2,2,
6,2,2,192,192,2,2,2,6,2,255,64,128,3,5,5,
6,0,3,64,192,64,64,224,5,7,7,6,0,1,112,136,
136,136,112,0,248,5,5,5,6,0,1,160,80,40,80,160,
5,7,7,6,0,0,136,144,168,88,184,8,8,5,7,7,
6,0,0,136,144,184,72,152,32,56,5,8,8,6,0,0,
192,64,192,72,216,56,8,8,5,7,7,6,0,0,32,0,
32,64,128,136,112,5,8,8,6,0,0,64,32,0,112,136,
248,136,136,5,8,8,6,0,0,16,32,0,112,136,248,136,
136,5,8,8,6,0,0,32,80,0,112,136,248,136,136,5,
8,8,6,0,0,104,144,0,112,136,248,136,136,5,8,8,
6,0,0,80,0,112,136,136,248,136,136,5,8,8,6,0,
0,32,80,32,112,136,248,136,136,5,7,7,6,0,0,56,
96,160,184,224,160,184,5,8,8,6,0,255,112,136,128,128,
136,112,32,96,5,8,8,6,0,0,64,32,0,248,128,240,
128,248,5,8,8,6,0,0,8,16,0,248,128,240,128,248,
5,8,8,6,0,0,32,80,0,248,128,240,128,248,5,7,
7,6,0,0,80,0,248,128,240,128,248,3,8,8,6,1,
0,128,64,0,224,64,64,64,224,3,8,8,6,1,0,32,
64,0,224,64,64,64,224,3,8,8,6,1,0,64,160,0,
224,64,64,64,224,3,7,7,6,1,0,160,0,224,64,64,
64,224,5,9,9,6,0,255,80,32,112,136,128,184,136,136,
112,5,8,8,6,0,0,104,144,0,136,200,168,152,136,5,
8,8,6,0,0,64,32,112,136,136,136,136,112,5,8,8,
6,0,0,16,32,112,136,136,136,136,112,5,8,8,6,0,
0,32,80,0,112,136,136,136,112,5,8,8,6,0,0,104,
144,0,112,136,136,136,112,5,8,8,6,0,0,80,0,112,
136,136,136,136,112,5,5,5,6,0,1,136,80,32,80,136,
5,8,8,6,0,255,16,112,168,168,168,168,112,64,5,8,
8,6,0,0,64,32,136,136,136,136,136,112,5,8,8,6,
0,0,16,32,136,136,136,136,136,112,5,8,8,6,0,0,
32,80,0,136,136,136,136,112,5,8,8,6,0,0,80,0,
136,136,136,136,136,112,1,7,7,6,2,0,128,0,128,128,
128,128,128,5,9,9,6,0,255,120,128,128,112,8,8,240,
32,96,4,8,8,6,1,255,96,144,144,160,144,144,224,128,
5,8,8,6,0,0,64,32,0,112,8,120,136,120,5,8,
8,6,0,0,16,32,0,112,8,120,136,120,5,8,8,6,
0,0,32,80,0,112,8,120,136,120,5,8,8,6,0,0,
104,144,0,112,8,120,136,120,5,7,7,6,0,0,80,0,
112,8,120,136,120,5,8,8,6,0,0,32,80,32,112,8,
120,136,120,5,6,6,6,0,0,208,40,120,160,168,80,5,
7,7,6,0,255,112,128,128,136,112,32,96,5,8,8,6,
0,0,64,32,0,112,136,248,128,112,5,8,8,6,0,0,
16,32,0,112,136,248,128,112,5,8,8,6,0,0,32,80,
0,112,136,248,128,112,5,7,7,6,0,0,80,0,112,136,
248,128,112,3,8,8,6,1,0,128,64,0,64,192,64,64,
224,3,8,8,6,1,0,32,64,0,64,192,64,64,224,3,
8,8,6,1,0,64,160,0,64,192,64,64,224,3,7,7,
6,1,0,160,0,64,192,64,64,224,5,8,8,6,0,255,
80,32,112,136,136,120,8,112,5,8,8,6,0,0,104,144,
0,176,200,136,136,136,5,8,8,6,0,0,64,32,0,112,
136,136,136,112,5,8,8,6,0,0,16,32,0,112,136,136,
136,112,5,8,8,6,0,0,32,80,0,112,136,136,136,112,
5,8,8,6,0,0,104,144,0,112,136,136,136,112,5,7,
7,6,0,0,80,0,112,136,136,136,112,5,5,5,6,0,
1,32,0,248,0,32,5,7,7,6,0,255,16,112,168,168,
168,112,64,5,8,8,6,0,0,64,32,0,136,136,136,152,
104,5,8,8,6,0,0,16,32,0,136,136,136,152,104,5,
8,8,6,0,0,32,80,0,136,136,136,152,104,5,7,7,
6,0,0,80,0,136,136,136,152,104,1,5,5,6,2,0,
128,128,128,128,128,5,7,7,6,0,255,112,128,112,8,240,
32,96,5,8,8,6,0,255,80,0,136,136,136,120,8,112
};

View File

@ -0,0 +1,205 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
Fontname: ISO10646_4_Greek
Copyright: A. Hardtung, public domain
Capital A Height: 7, '1' Height: 7
Calculated Max Values w= 5 h= 9 x= 2 y= 6 dx= 6 dy= 0 ascent= 8 len= 9
Font Bounding box w= 6 h= 9 x= 0 y=-2
Calculated Min Values x= 0 y=-1 dx= 0 dy= 0
Pure Font ascent = 7 descent=-1
X Font ascent = 7 descent=-1
Max Font ascent = 8 descent=-1
*/
#include <U8glib.h>
const u8g_fntpgm_uint8_t ISO10646_Greek_5x7[2715] U8G_SECTION(".progmem.ISO10646_Greek_5x7") = {
0,6,9,0,254,7,1,145,3,32,32,255,255,8,255,7,
255,0,0,0,6,0,0,1,7,7,6,2,0,128,128,128,
128,128,0,128,3,2,2,6,1,5,160,160,5,7,7,6,
0,0,80,80,248,80,248,80,80,5,7,7,6,0,0,32,
120,160,112,40,240,32,5,7,7,6,0,0,192,200,16,32,
64,152,24,5,7,7,6,0,0,96,144,160,64,168,144,104,
2,3,3,6,1,4,192,64,128,3,7,7,6,1,0,32,
64,128,128,128,64,32,3,7,7,6,1,0,128,64,32,32,
32,64,128,5,5,5,6,0,1,32,168,112,168,32,5,5,
5,6,0,1,32,32,248,32,32,2,3,3,6,2,255,192,
64,128,5,1,1,6,0,3,248,2,2,2,6,2,0,192,
192,5,5,5,6,0,1,8,16,32,64,128,5,7,7,6,
0,0,112,136,152,168,200,136,112,3,7,7,6,1,0,64,
192,64,64,64,64,224,5,7,7,6,0,0,112,136,8,112,
128,128,248,5,7,7,6,0,0,248,16,32,16,8,8,240,
5,7,7,6,0,0,16,48,80,144,248,16,16,5,7,7,
6,0,0,248,128,240,8,8,136,112,5,7,7,6,0,0,
48,64,128,240,136,136,112,5,7,7,6,0,0,248,8,16,
32,32,32,32,5,7,7,6,0,0,112,136,136,112,136,136,
112,5,7,7,6,0,0,112,136,136,120,8,16,96,2,5,
5,6,2,0,192,192,0,192,192,2,6,6,6,2,255,192,
192,0,192,64,128,4,7,7,6,0,0,16,32,64,128,64,
32,16,5,3,3,6,0,2,248,0,248,4,7,7,6,1,
0,128,64,32,16,32,64,128,5,7,7,6,0,0,112,136,
8,16,32,0,32,5,6,6,6,0,0,112,136,8,104,168,
112,5,7,7,6,0,0,112,136,136,248,136,136,136,5,7,
7,6,0,0,240,136,136,240,136,136,240,5,7,7,6,0,
0,112,136,128,128,128,136,112,5,7,7,6,0,0,224,144,
136,136,136,144,224,5,7,7,6,0,0,248,128,128,240,128,
128,248,5,7,7,6,0,0,248,128,128,240,128,128,128,5,
7,7,6,0,0,112,136,128,184,136,136,112,5,7,7,6,
0,0,136,136,136,248,136,136,136,1,7,7,6,2,0,128,
128,128,128,128,128,128,5,7,7,6,0,0,56,16,16,16,
16,144,96,5,7,7,6,0,0,136,144,160,192,160,144,136,
5,7,7,6,0,0,128,128,128,128,128,128,248,5,7,7,
6,0,0,136,216,168,136,136,136,136,5,7,7,6,0,0,
136,136,200,168,152,136,136,5,7,7,6,0,0,112,136,136,
136,136,136,112,5,7,7,6,0,0,240,136,136,240,128,128,
128,5,7,7,6,0,0,112,136,136,136,168,144,104,5,7,
7,6,0,0,240,136,136,240,160,144,136,5,7,7,6,0,
0,120,128,128,112,8,8,240,5,7,7,6,0,0,248,32,
32,32,32,32,32,5,7,7,6,0,0,136,136,136,136,136,
136,112,5,7,7,6,0,0,136,136,136,136,136,80,32,5,
7,7,6,0,0,136,136,136,136,136,168,80,5,7,7,6,
0,0,136,136,80,32,80,136,136,5,7,7,6,0,0,136,
136,136,80,32,32,32,5,7,7,6,0,0,248,8,16,32,
64,128,248,3,7,7,6,1,0,224,128,128,128,128,128,224,
5,5,5,6,0,1,128,64,32,16,8,3,7,7,6,1,
0,224,32,32,32,32,32,224,5,3,3,6,0,4,32,80,
136,5,1,1,6,0,0,248,2,2,2,6,2,5,128,64,
5,5,5,6,0,0,112,8,120,136,120,5,7,7,6,0,
0,128,128,176,200,136,136,240,5,5,5,6,0,0,112,128,
128,136,112,5,7,7,6,0,0,8,8,104,152,136,136,120,
5,5,5,6,0,0,112,136,248,128,112,5,7,7,6,0,
0,48,72,224,64,64,64,64,5,6,6,6,0,255,112,136,
136,120,8,112,5,7,7,6,0,0,128,128,176,200,136,136,
136,1,7,7,6,2,0,128,0,128,128,128,128,128,3,8,
8,6,1,255,32,0,32,32,32,32,160,64,4,7,7,6,
0,0,128,128,144,160,192,160,144,3,7,7,6,1,0,192,
64,64,64,64,64,224,5,5,5,6,0,0,208,168,168,168,
168,5,5,5,6,0,0,176,200,136,136,136,5,5,5,6,
0,0,112,136,136,136,112,5,6,6,6,0,255,240,136,136,
240,128,128,5,6,6,6,0,255,120,136,136,120,8,8,5,
5,5,6,0,0,176,200,128,128,128,5,5,5,6,0,0,
112,128,112,8,240,5,7,7,6,0,0,64,64,224,64,64,
72,48,5,5,5,6,0,0,136,136,136,152,104,5,5,5,
6,0,0,136,136,136,80,32,5,5,5,6,0,0,136,136,
168,168,80,5,5,5,6,0,0,136,80,32,80,136,5,6,
6,6,0,255,136,136,136,120,8,112,5,5,5,6,0,0,
248,16,32,64,248,3,7,7,6,1,0,32,64,64,128,64,
64,32,1,7,7,6,2,0,128,128,128,128,128,128,128,3,
7,7,6,1,0,128,64,64,32,64,64,128,5,2,2,6,
0,3,104,144,0,0,0,6,0,0,0,0,0,6,0,0,
0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,
0,0,2,2,2,6,1,6,64,128,3,3,3,6,1,5,
32,64,160,5,8,8,6,0,0,64,160,80,80,136,248,136,
136,2,2,2,6,1,2,192,192,5,8,8,6,0,0,64,
128,248,128,240,128,128,248,5,8,8,6,0,0,64,128,136,
136,248,136,136,136,4,8,8,6,0,0,64,128,112,32,32,
32,32,112,0,0,0,6,0,0,5,8,8,6,0,0,64,
128,112,136,136,136,136,112,0,0,0,6,0,0,5,8,8,
6,0,0,64,128,8,136,112,32,32,32,5,8,8,6,0,
0,64,128,112,136,136,136,80,216,3,8,8,6,1,0,32,
64,160,0,64,64,64,32,5,7,7,6,0,0,32,80,136,
136,248,136,136,5,7,7,6,0,0,240,72,72,112,72,72,
240,5,7,7,6,0,0,248,128,128,128,128,128,128,5,6,
6,6,0,0,32,80,80,136,136,248,5,7,7,6,0,0,
248,128,128,240,128,128,248,5,7,7,6,0,0,248,8,16,
32,64,128,248,5,7,7,6,0,0,136,136,136,248,136,136,
136,5,7,7,6,0,0,112,136,136,168,136,136,112,3,7,
7,6,1,0,224,64,64,64,64,64,224,5,7,7,6,0,
0,136,144,160,192,160,144,136,5,7,7,6,0,0,32,80,
136,136,136,136,136,5,7,7,6,0,0,136,216,168,168,136,
136,136,5,7,7,6,0,0,136,200,200,168,152,152,136,5,
7,7,6,0,0,248,0,0,112,0,0,248,5,7,7,6,
0,0,112,136,136,136,136,136,112,5,7,7,6,0,0,248,
80,80,80,80,80,80,5,7,7,6,0,0,240,136,136,240,
128,128,128,0,0,0,6,0,0,5,7,7,6,0,0,248,
128,64,32,64,128,248,5,7,7,6,0,0,248,32,32,32,
32,32,32,5,7,7,6,0,0,136,136,80,32,32,32,32,
5,7,7,6,0,0,112,32,112,168,112,32,112,5,7,7,
6,0,0,136,136,80,32,80,136,136,5,7,7,6,0,0,
168,168,168,168,112,32,32,5,6,6,6,0,0,112,136,136,
80,80,216,3,8,8,6,1,0,160,0,224,64,64,64,64,
224,5,8,8,6,0,0,80,0,136,136,136,80,32,32,5,
8,8,6,0,0,32,64,8,104,152,144,144,104,5,8,8,
6,0,0,32,64,0,112,136,224,136,112,5,9,9,6,0,
255,32,64,0,112,136,136,136,136,8,2,8,8,6,1,0,
64,128,0,128,128,128,128,64,5,8,8,6,0,0,16,32,
80,0,136,136,136,112,5,6,6,6,0,0,8,104,152,144,
144,104,4,6,6,6,0,255,96,144,240,144,224,128,5,6,
6,6,0,255,136,72,80,32,32,64,5,6,6,6,0,0,
48,64,112,136,136,112,5,5,5,6,0,0,112,136,224,136,
112,5,8,8,6,0,255,128,112,64,128,128,112,8,112,5,
6,6,6,0,255,184,200,136,136,136,8,5,5,5,6,0,
0,112,136,248,136,112,3,5,5,6,1,0,128,128,128,128,
96,4,5,5,6,0,0,144,160,192,160,144,5,6,6,6,
0,0,64,32,32,80,80,136,5,6,6,6,0,255,136,136,
136,216,168,128,5,5,5,6,0,0,136,136,80,96,32,5,
9,9,6,0,255,128,224,128,112,32,64,240,8,112,5,5,
5,6,0,0,112,136,136,136,112,5,5,5,6,0,0,248,
80,80,80,80,5,6,6,6,0,255,112,136,136,200,176,128,
5,7,7,6,0,255,48,64,128,64,48,8,112,5,5,5,
6,0,0,104,144,144,144,96,4,5,5,6,0,0,240,64,
64,64,48,5,5,5,6,0,0,136,136,144,144,224,5,7,
7,6,0,255,32,168,168,168,112,32,32,5,6,6,6,0,
255,136,80,32,32,80,136,5,6,6,6,0,255,168,168,168,
168,112,32,5,5,5,6,0,0,80,136,136,168,112,4,7,
7,6,0,0,160,0,64,64,64,64,48,5,7,7,6,0,
0,80,0,136,136,144,144,224,4,8,8,6,0,0,32,64,
0,96,144,144,144,96,5,8,8,6,0,0,32,64,0,136,
136,144,144,96,5,8,8,6,0,0,32,64,0,80,136,136,
168,112,5,7,7,6,0,255,144,160,192,160,144,136,16,5,
8,8,6,0,0,96,144,160,128,240,136,136,112,5,7,7,
6,0,0,112,80,56,144,144,144,96,5,6,6,6,0,0,
152,80,32,32,32,32,5,8,8,6,0,0,64,128,152,80,
32,32,32,32,5,8,8,6,0,0,80,0,152,80,32,32,
32,32,5,7,7,6,0,255,48,168,168,168,168,112,32,5,
5,5,6,0,0,248,80,80,80,88,5,6,6,6,0,255,
136,80,112,80,136,16,5,7,7,6,0,255,112,136,136,136,
112,32,112,5,6,6,6,0,255,112,136,136,112,32,112,5,
6,6,6,0,0,112,136,128,112,32,112,5,7,7,6,0,
255,8,8,112,128,112,16,96,5,6,6,6,0,0,248,128,
128,240,128,128,4,5,5,6,0,0,240,128,224,128,128,5,
6,6,6,0,0,248,0,0,112,0,248,4,5,5,6,0,
0,64,128,240,16,32,5,7,7,6,0,0,224,80,40,40,
8,8,16,5,7,7,6,0,0,192,32,80,40,8,8,8,
5,7,7,6,0,255,168,168,168,168,88,8,112,5,6,6,
6,0,255,168,168,168,88,8,112,5,6,6,6,0,0,104,
136,136,120,8,8,5,6,6,6,0,255,104,136,136,120,8,
8,4,8,8,6,0,255,128,224,144,144,144,144,32,192,5,
5,5,6,0,0,104,144,112,16,224,5,6,6,6,0,0,
96,144,16,96,136,112,4,6,6,6,0,0,96,144,16,96,
128,112,5,6,6,6,0,0,136,80,32,80,136,248,5,5,
5,6,0,0,136,80,32,80,112,5,6,6,6,0,0,120,
128,240,136,136,112,4,5,5,6,0,0,240,128,224,144,96,
3,6,6,6,1,0,64,224,64,64,64,64,3,6,6,6,
1,255,64,224,64,64,64,128,5,5,5,6,0,0,136,80,
112,80,136,5,6,6,6,0,255,112,136,136,240,128,112,4,
5,5,6,0,0,112,128,128,128,112,2,8,8,6,1,255,
64,0,192,64,64,64,64,128,5,7,7,6,0,0,112,136,
136,248,136,136,112,4,5,5,6,0,0,112,128,224,128,112,
4,5,5,6,0,0,224,16,112,16,224,5,7,7,6,0,
0,128,240,136,136,136,240,128,4,7,7,6,0,255,128,224,
144,144,144,224,128,5,6,6,6,0,0,112,136,128,128,136,
112,5,6,6,6,0,0,136,216,168,136,136,136,5,6,6,
6,0,255,136,216,168,136,136,128,5,8,8,6,0,255,112,
136,136,136,112,64,224,64,5,6,6,6,0,0,112,136,8,
8,136,112,5,6,6,6,0,0,112,136,160,128,136,112,5,
6,6,6,0,0,112,136,40,8,136,112};

View File

@ -0,0 +1,192 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
Fontname: ISO10646_Kana
Copyright: A. Hardtung, public domain
Capital A Height: 7, '1' Height: 7
Calculated Max Values w= 5 h= 8 x= 2 y= 5 dx= 6 dy= 0 ascent= 8 len= 8
Font Bounding box w= 6 h= 9 x= 0 y=-2
Calculated Min Values x= 0 y=-1 dx= 0 dy= 0
Pure Font ascent = 7 descent=-1
X Font ascent = 7 descent=-1
Max Font ascent = 8 descent=-1
*/
#include <U8glib.h>
const u8g_fntpgm_uint8_t ISO10646_Kana_5x7[2482] U8G_SECTION(".progmem.ISO10646_Kana_5x7") = {
0, 6, 9, 0, 254, 7, 1, 145, 3, 32, 32, 255, 255, 8, 255, 7,
255, 0, 0, 0, 6, 0, 0, 1, 7, 7, 6, 2, 0, 128, 128, 128,
128, 128, 0, 128, 3, 2, 2, 6, 1, 5, 160, 160, 5, 7, 7, 6,
0, 0, 80, 80, 248, 80, 248, 80, 80, 5, 7, 7, 6, 0, 0, 32,
120, 160, 112, 40, 240, 32, 5, 7, 7, 6, 0, 0, 192, 200, 16, 32,
64, 152, 24, 5, 7, 7, 6, 0, 0, 96, 144, 160, 64, 168, 144, 104,
2, 3, 3, 6, 1, 4, 192, 64, 128, 3, 7, 7, 6, 1, 0, 32,
64, 128, 128, 128, 64, 32, 3, 7, 7, 6, 1, 0, 128, 64, 32, 32,
32, 64, 128, 5, 5, 5, 6, 0, 1, 32, 168, 112, 168, 32, 5, 5,
5, 6, 0, 1, 32, 32, 248, 32, 32, 2, 3, 3, 6, 2, 255, 192,
64, 128, 5, 1, 1, 6, 0, 3, 248, 2, 2, 2, 6, 2, 0, 192,
192, 5, 5, 5, 6, 0, 1, 8, 16, 32, 64, 128, 5, 7, 7, 6,
0, 0, 112, 136, 152, 168, 200, 136, 112, 3, 7, 7, 6, 1, 0, 64,
192, 64, 64, 64, 64, 224, 5, 7, 7, 6, 0, 0, 112, 136, 8, 112,
128, 128, 248, 5, 7, 7, 6, 0, 0, 248, 16, 32, 16, 8, 8, 240,
5, 7, 7, 6, 0, 0, 16, 48, 80, 144, 248, 16, 16, 5, 7, 7,
6, 0, 0, 248, 128, 240, 8, 8, 136, 112, 5, 7, 7, 6, 0, 0,
48, 64, 128, 240, 136, 136, 112, 5, 7, 7, 6, 0, 0, 248, 8, 16,
32, 32, 32, 32, 5, 7, 7, 6, 0, 0, 112, 136, 136, 112, 136, 136,
112, 5, 7, 7, 6, 0, 0, 112, 136, 136, 120, 8, 16, 96, 2, 5,
5, 6, 2, 0, 192, 192, 0, 192, 192, 2, 6, 6, 6, 2, 255, 192,
192, 0, 192, 64, 128, 4, 7, 7, 6, 0, 0, 16, 32, 64, 128, 64,
32, 16, 5, 3, 3, 6, 0, 2, 248, 0, 248, 4, 7, 7, 6, 1,
0, 128, 64, 32, 16, 32, 64, 128, 5, 7, 7, 6, 0, 0, 112, 136,
8, 16, 32, 0, 32, 5, 6, 6, 6, 0, 0, 112, 136, 8, 104, 168,
112, 5, 7, 7, 6, 0, 0, 112, 136, 136, 248, 136, 136, 136, 5, 7,
7, 6, 0, 0, 240, 136, 136, 240, 136, 136, 240, 5, 7, 7, 6, 0,
0, 112, 136, 128, 128, 128, 136, 112, 5, 7, 7, 6, 0, 0, 224, 144,
136, 136, 136, 144, 224, 5, 7, 7, 6, 0, 0, 248, 128, 128, 240, 128,
128, 248, 5, 7, 7, 6, 0, 0, 248, 128, 128, 240, 128, 128, 128, 5,
7, 7, 6, 0, 0, 112, 136, 128, 184, 136, 136, 112, 5, 7, 7, 6,
0, 0, 136, 136, 136, 248, 136, 136, 136, 1, 7, 7, 6, 2, 0, 128,
128, 128, 128, 128, 128, 128, 5, 7, 7, 6, 0, 0, 56, 16, 16, 16,
16, 144, 96, 5, 7, 7, 6, 0, 0, 136, 144, 160, 192, 160, 144, 136,
5, 7, 7, 6, 0, 0, 128, 128, 128, 128, 128, 128, 248, 5, 7, 7,
6, 0, 0, 136, 216, 168, 136, 136, 136, 136, 5, 7, 7, 6, 0, 0,
136, 136, 200, 168, 152, 136, 136, 5, 7, 7, 6, 0, 0, 112, 136, 136,
136, 136, 136, 112, 5, 7, 7, 6, 0, 0, 240, 136, 136, 240, 128, 128,
128, 5, 7, 7, 6, 0, 0, 112, 136, 136, 136, 168, 144, 104, 5, 7,
7, 6, 0, 0, 240, 136, 136, 240, 160, 144, 136, 5, 7, 7, 6, 0,
0, 120, 128, 128, 112, 8, 8, 240, 5, 7, 7, 6, 0, 0, 248, 32,
32, 32, 32, 32, 32, 5, 7, 7, 6, 0, 0, 136, 136, 136, 136, 136,
136, 112, 5, 7, 7, 6, 0, 0, 136, 136, 136, 136, 136, 80, 32, 5,
7, 7, 6, 0, 0, 136, 136, 136, 136, 136, 168, 80, 5, 7, 7, 6,
0, 0, 136, 136, 80, 32, 80, 136, 136, 5, 7, 7, 6, 0, 0, 136,
136, 136, 80, 32, 32, 32, 5, 7, 7, 6, 0, 0, 248, 8, 16, 32,
64, 128, 248, 3, 7, 7, 6, 1, 0, 224, 128, 128, 128, 128, 128, 224,
5, 5, 5, 6, 0, 1, 128, 64, 32, 16, 8, 3, 7, 7, 6, 1,
0, 224, 32, 32, 32, 32, 32, 224, 5, 3, 3, 6, 0, 4, 32, 80,
136, 5, 1, 1, 6, 0, 0, 248, 2, 2, 2, 6, 2, 5, 128, 64,
5, 5, 5, 6, 0, 0, 112, 8, 120, 136, 120, 5, 7, 7, 6, 0,
0, 128, 128, 176, 200, 136, 136, 240, 5, 5, 5, 6, 0, 0, 112, 128,
128, 136, 112, 5, 7, 7, 6, 0, 0, 8, 8, 104, 152, 136, 136, 120,
5, 5, 5, 6, 0, 0, 112, 136, 248, 128, 112, 5, 7, 7, 6, 0,
0, 48, 72, 224, 64, 64, 64, 64, 5, 6, 6, 6, 0, 255, 112, 136,
136, 120, 8, 112, 5, 7, 7, 6, 0, 0, 128, 128, 176, 200, 136, 136,
136, 1, 7, 7, 6, 2, 0, 128, 0, 128, 128, 128, 128, 128, 3, 8,
8, 6, 1, 255, 32, 0, 32, 32, 32, 32, 160, 64, 4, 7, 7, 6,
0, 0, 128, 128, 144, 160, 192, 160, 144, 3, 7, 7, 6, 1, 0, 192,
64, 64, 64, 64, 64, 224, 5, 5, 5, 6, 0, 0, 208, 168, 168, 168,
168, 5, 5, 5, 6, 0, 0, 176, 200, 136, 136, 136, 5, 5, 5, 6,
0, 0, 112, 136, 136, 136, 112, 5, 6, 6, 6, 0, 255, 240, 136, 136,
240, 128, 128, 5, 6, 6, 6, 0, 255, 120, 136, 136, 120, 8, 8, 5,
5, 5, 6, 0, 0, 176, 200, 128, 128, 128, 5, 5, 5, 6, 0, 0,
112, 128, 112, 8, 240, 5, 7, 7, 6, 0, 0, 64, 64, 224, 64, 64,
72, 48, 5, 5, 5, 6, 0, 0, 136, 136, 136, 152, 104, 5, 5, 5,
6, 0, 0, 136, 136, 136, 80, 32, 5, 5, 5, 6, 0, 0, 136, 136,
168, 168, 80, 5, 5, 5, 6, 0, 0, 136, 80, 32, 80, 136, 5, 6,
6, 6, 0, 255, 136, 136, 136, 120, 8, 112, 5, 5, 5, 6, 0, 0,
248, 16, 32, 64, 248, 3, 7, 7, 6, 1, 0, 32, 64, 64, 128, 64,
64, 32, 1, 7, 7, 6, 2, 0, 128, 128, 128, 128, 128, 128, 128, 3,
7, 7, 6, 1, 0, 128, 64, 64, 32, 64, 64, 128, 5, 2, 2, 6,
0, 3, 104, 144, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0,
0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6,
0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0,
0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0,
0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6,
0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0,
0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0,
0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6,
0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0,
0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0,
0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6,
0, 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 0, 0,
0, 6, 0, 0, 0, 0, 0, 6, 0, 0, 5, 3, 3, 6, 0, 1,
248, 0, 248, 4, 4, 4, 6, 0, 0, 240, 16, 96, 64, 5, 6, 6,
6, 0, 0, 248, 8, 40, 48, 32, 64, 3, 4, 4, 6, 1, 0, 32,
64, 192, 64, 4, 6, 6, 6, 0, 0, 16, 32, 96, 160, 32, 32, 4,
4, 4, 6, 0, 0, 32, 240, 144, 32, 5, 6, 6, 6, 0, 0, 32,
248, 136, 8, 16, 32, 3, 4, 4, 6, 1, 0, 224, 64, 64, 224, 5,
5, 5, 6, 0, 0, 248, 32, 32, 32, 248, 4, 4, 4, 6, 0, 0,
32, 240, 96, 160, 5, 6, 6, 6, 0, 0, 16, 248, 48, 80, 144, 16,
5, 6, 6, 6, 0, 0, 64, 248, 72, 72, 72, 144, 5, 8, 8, 6,
0, 0, 40, 0, 64, 248, 72, 72, 72, 144, 5, 6, 6, 6, 0, 0,
32, 248, 32, 248, 32, 32, 5, 8, 8, 6, 0, 0, 40, 0, 32, 248,
32, 248, 32, 32, 4, 5, 5, 6, 0, 0, 112, 144, 16, 32, 192, 5,
7, 7, 6, 0, 0, 40, 0, 112, 144, 16, 32, 192, 5, 6, 6, 6,
0, 0, 64, 120, 144, 16, 16, 32, 5, 8, 8, 6, 0, 0, 40, 0,
64, 120, 144, 16, 16, 32, 5, 5, 5, 6, 0, 0, 248, 8, 8, 8,
248, 5, 7, 7, 6, 0, 0, 40, 0, 248, 8, 8, 8, 248, 5, 6,
6, 6, 0, 0, 80, 248, 80, 16, 32, 64, 5, 8, 8, 6, 0, 0,
40, 0, 80, 248, 80, 16, 32, 64, 5, 5, 5, 6, 0, 0, 192, 8,
200, 16, 224, 5, 7, 7, 6, 0, 0, 40, 0, 192, 8, 200, 16, 224,
5, 5, 5, 6, 0, 0, 248, 16, 32, 80, 136, 5, 7, 7, 6, 0,
0, 40, 0, 248, 16, 32, 80, 136, 5, 6, 6, 6, 0, 0, 64, 248,
72, 80, 64, 56, 5, 8, 8, 6, 0, 0, 40, 0, 64, 248, 72, 80,
64, 56, 5, 5, 5, 6, 0, 0, 136, 136, 72, 16, 96, 5, 7, 7,
6, 0, 0, 40, 0, 136, 136, 72, 16, 96, 5, 5, 5, 6, 0, 0,
120, 72, 168, 16, 96, 5, 7, 7, 6, 0, 0, 40, 0, 120, 72, 168,
16, 96, 5, 6, 6, 6, 0, 0, 16, 224, 32, 248, 32, 64, 5, 8,
8, 6, 0, 0, 40, 0, 16, 224, 32, 248, 32, 64, 5, 4, 4, 6,
0, 0, 168, 168, 8, 48, 5, 5, 5, 6, 0, 0, 168, 168, 8, 16,
32, 5, 7, 7, 6, 0, 0, 40, 0, 168, 168, 8, 16, 32, 5, 6,
6, 6, 0, 0, 112, 0, 248, 32, 32, 64, 5, 8, 8, 6, 0, 0,
40, 0, 112, 0, 248, 32, 32, 64, 3, 6, 6, 6, 1, 0, 128, 128,
192, 160, 128, 128, 4, 8, 8, 6, 1, 0, 80, 0, 128, 128, 192, 160,
128, 128, 5, 6, 6, 6, 0, 0, 32, 248, 32, 32, 64, 128, 5, 5,
5, 6, 0, 0, 112, 0, 0, 0, 248, 5, 5, 5, 6, 0, 0, 248,
8, 80, 32, 208, 5, 6, 6, 6, 0, 0, 32, 248, 16, 32, 112, 168,
3, 6, 6, 6, 1, 0, 32, 32, 32, 32, 64, 128, 5, 5, 5, 6,
0, 0, 16, 136, 136, 136, 136, 5, 7, 7, 6, 0, 0, 40, 0, 16,
136, 136, 136, 136, 5, 8, 8, 6, 0, 0, 24, 24, 0, 16, 136, 136,
136, 136, 5, 6, 6, 6, 0, 0, 128, 128, 248, 128, 128, 120, 5, 7,
7, 6, 0, 0, 40, 128, 128, 248, 128, 128, 120, 5, 7, 7, 6, 0,
0, 24, 152, 128, 248, 128, 128, 120, 5, 5, 5, 6, 0, 0, 248, 8,
8, 16, 96, 5, 7, 7, 6, 0, 0, 40, 0, 248, 8, 8, 16, 96,
5, 8, 8, 6, 0, 0, 24, 24, 0, 248, 8, 8, 16, 96, 5, 4,
4, 6, 0, 1, 64, 160, 16, 8, 5, 6, 6, 6, 0, 1, 40, 0,
64, 160, 16, 8, 5, 6, 6, 6, 0, 1, 24, 24, 64, 160, 16, 8,
5, 6, 6, 6, 0, 0, 32, 248, 32, 168, 168, 32, 5, 8, 8, 6,
0, 0, 40, 0, 32, 248, 32, 168, 168, 32, 5, 8, 8, 6, 0, 0,
24, 24, 32, 248, 32, 168, 168, 32, 5, 5, 5, 6, 0, 0, 248, 8,
80, 32, 16, 4, 5, 5, 6, 1, 0, 224, 0, 224, 0, 240, 5, 5,
5, 6, 0, 0, 32, 64, 136, 248, 8, 5, 5, 5, 6, 0, 0, 8,
40, 16, 40, 192, 5, 5, 5, 6, 0, 0, 248, 64, 248, 64, 56, 5,
4, 4, 6, 0, 0, 64, 248, 80, 64, 5, 6, 6, 6, 0, 0, 64,
248, 72, 80, 64, 64, 4, 4, 4, 6, 0, 0, 96, 32, 32, 240, 5,
5, 5, 6, 0, 0, 112, 16, 16, 16, 248, 4, 5, 5, 6, 0, 0,
240, 16, 240, 16, 240, 5, 5, 5, 6, 0, 0, 248, 8, 248, 8, 248,
5, 6, 6, 6, 0, 0, 112, 0, 248, 8, 16, 32, 4, 6, 6, 6,
0, 0, 144, 144, 144, 144, 16, 32, 5, 5, 5, 6, 0, 0, 32, 160,
168, 168, 176, 4, 5, 5, 6, 0, 0, 128, 128, 144, 160, 192, 5, 5,
5, 6, 0, 0, 248, 136, 136, 136, 248, 4, 4, 4, 6, 0, 0, 240,
144, 16, 32, 5, 5, 5, 6, 0, 0, 248, 136, 8, 16, 32, 5, 6,
6, 6, 0, 0, 16, 248, 80, 80, 248, 16, 5, 5, 5, 6, 0, 0,
248, 8, 48, 32, 248, 5, 5, 5, 6, 0, 0, 248, 8, 248, 8, 48,
5, 5, 5, 6, 0, 0, 192, 8, 8, 16, 224, 5, 8, 8, 6, 0,
0, 40, 0, 32, 248, 136, 8, 16, 32, 4, 4, 4, 6, 0, 0, 64,
240, 80, 160, 4, 4, 4, 6, 0, 0, 64, 240, 32, 64, 5, 7, 7,
6, 0, 0, 40, 0, 248, 136, 8, 16, 96, 5, 8, 8, 6, 0, 0,
40, 0, 16, 248, 80, 80, 248, 16, 5, 7, 7, 6, 0, 0, 40, 0,
248, 8, 48, 32, 248, 5, 7, 7, 6, 0, 0, 40, 0, 248, 8, 248,
8, 48, 2, 2, 2, 6, 2, 2, 192, 192, 5, 1, 1, 6, 0, 2,
248, 5, 4, 4, 6, 0, 1, 128, 96, 16, 8, 5, 5, 5, 6, 0,
1, 40, 128, 96, 16, 8, 5, 6, 6, 6, 0, 0, 248, 8, 8, 8,
8, 8
};

View File

@ -0,0 +1,151 @@
/*
Fontname: ISO10646_SK
Copyright: A. Hardtung, modified by Roman Moravcik
Capital A Height: 7, '1' Height: 7
Calculated Max Values w= 6 h= 9 x= 2 y= 7 dx= 6 dy= 0 ascent= 8 len= 9
Font Bounding box w= 6 h= 9 x= 0 y=-2
Calculated Min Values x= 0 y=-1 dx= 0 dy= 0
Pure Font ascent = 7 descent=-1
X Font ascent = 7 descent=-1
Max Font ascent = 8 descent=-1
*/
#include <U8glib.h>
const u8g_fntpgm_uint8_t ISO10646_SK[2203] U8G_SECTION(".progmem.ISO10646_SK") = {
0,6,9,0,254,7,1,146,3,33,32,255,255,8,255,7,
255,0,0,0,6,0,0,1,7,7,6,2,0,128,128,128,
128,128,0,128,3,2,2,6,1,5,160,160,5,7,7,6,
0,0,80,80,248,80,248,80,80,5,7,7,6,0,0,32,
120,160,112,40,240,32,5,7,7,6,0,0,192,200,16,32,
64,152,24,5,7,7,6,0,0,96,144,160,64,168,144,104,
2,3,3,6,1,4,192,64,128,3,7,7,6,1,0,32,
64,128,128,128,64,32,3,7,7,6,1,0,128,64,32,32,
32,64,128,5,5,5,6,0,1,32,168,112,168,32,5,5,
5,6,0,1,32,32,248,32,32,2,3,3,6,2,255,192,
64,128,5,1,1,6,0,3,248,2,2,2,6,2,0,192,
192,5,5,5,6,0,1,8,16,32,64,128,5,7,7,6,
0,0,112,136,136,136,136,136,112,3,7,7,6,1,0,64,
192,64,64,64,64,224,5,7,7,6,0,0,112,136,8,112,
128,128,248,5,7,7,6,0,0,248,16,32,16,8,8,240,
5,7,7,6,0,0,16,48,80,144,248,16,16,5,7,7,
6,0,0,248,128,240,8,8,136,112,5,7,7,6,0,0,
112,128,128,240,136,136,112,5,7,7,6,0,0,248,8,16,
32,32,32,32,5,7,7,6,0,0,112,136,136,112,136,136,
112,5,7,7,6,0,0,112,136,136,120,8,8,112,2,5,
5,6,2,0,192,192,0,192,192,2,6,6,6,2,255,192,
192,0,192,64,128,4,7,7,6,0,0,16,32,64,128,64,
32,16,5,3,3,6,0,2,248,0,248,4,7,7,6,1,
0,128,64,32,16,32,64,128,5,7,7,6,0,0,112,136,
8,16,32,0,32,5,7,7,6,0,0,112,136,8,104,168,
168,112,5,7,7,6,0,0,112,136,136,248,136,136,136,5,
7,7,6,0,0,240,136,136,240,136,136,240,5,7,7,6,
0,0,112,136,128,128,128,136,112,5,7,7,6,0,0,240,
136,136,136,136,136,240,5,7,7,6,0,0,248,128,128,240,
128,128,248,5,7,7,6,0,0,248,128,128,240,128,128,128,
5,7,7,6,0,0,112,136,128,184,136,136,112,5,7,7,
6,0,0,136,136,136,248,136,136,136,1,7,7,6,2,0,
128,128,128,128,128,128,128,5,7,7,6,0,0,56,16,16,
16,16,144,96,5,7,7,6,0,0,136,144,160,192,160,144,
136,5,7,7,6,0,0,128,128,128,128,128,128,248,5,7,
7,6,0,0,136,216,168,136,136,136,136,5,7,7,6,0,
0,136,136,200,168,152,136,136,5,7,7,6,0,0,112,136,
136,136,136,136,112,5,7,7,6,0,0,240,136,136,240,128,
128,128,5,7,7,6,0,0,112,136,136,136,168,144,104,5,
7,7,6,0,0,240,136,136,240,160,144,136,5,7,7,6,
0,0,120,128,128,112,8,8,240,5,7,7,6,0,0,248,
32,32,32,32,32,32,5,7,7,6,0,0,136,136,136,136,
136,136,112,5,7,7,6,0,0,136,136,136,136,136,80,32,
5,7,7,6,0,0,136,136,136,136,136,168,80,5,7,7,
6,0,0,136,136,80,32,80,136,136,5,7,7,6,0,0,
136,136,136,80,32,32,32,5,7,7,6,0,0,248,8,16,
32,64,128,248,3,7,7,6,1,0,224,128,128,128,128,128,
224,5,5,5,6,0,1,128,64,32,16,8,3,7,7,6,
1,0,224,32,32,32,32,32,224,5,3,3,6,0,4,32,
80,136,5,1,1,6,0,0,248,2,2,2,6,2,5,128,
64,5,5,5,6,0,0,112,8,120,136,120,5,7,7,6,
0,0,128,128,176,200,136,136,240,5,5,5,6,0,0,112,
128,128,136,112,5,7,7,6,0,0,8,8,104,152,136,136,
120,5,5,5,6,0,0,112,136,248,128,112,5,7,7,6,
0,0,48,72,224,64,64,64,64,5,6,6,6,0,255,112,
136,136,120,8,112,5,7,7,6,0,0,128,128,176,200,136,
136,136,1,7,7,6,2,0,128,0,128,128,128,128,128,3,
8,8,6,1,255,32,0,32,32,32,32,160,64,4,7,7,
6,0,0,128,128,144,160,192,160,144,3,7,7,6,1,0,
192,64,64,64,64,64,224,5,5,5,6,0,0,208,168,168,
168,168,5,5,5,6,0,0,176,200,136,136,136,5,5,5,
6,0,0,112,136,136,136,112,5,6,6,6,0,255,240,136,
136,240,128,128,5,6,6,6,0,255,120,136,136,120,8,8,
5,5,5,6,0,0,176,200,128,128,128,5,5,5,6,0,
0,112,128,112,8,240,4,7,7,6,0,0,64,64,224,64,
64,64,48,5,5,5,6,0,0,136,136,136,152,104,5,5,
5,6,0,0,136,136,136,80,32,5,5,5,6,0,0,136,
136,168,168,80,5,5,5,6,0,0,136,80,32,80,136,5,
6,6,6,0,255,136,136,136,120,8,112,5,5,5,6,0,
0,248,16,32,64,248,3,7,7,6,1,0,32,64,64,128,
64,64,32,1,7,7,6,2,0,128,128,128,128,128,128,128,
3,7,7,6,1,0,128,64,64,32,64,64,128,5,2,2,
6,0,2,104,144,0,0,0,6,0,0,5,8,8,6,0,
0,16,32,112,136,136,248,136,136,5,8,8,6,0,0,80,
0,112,136,136,248,136,136,5,8,8,6,0,0,8,16,248,
128,128,240,128,248,3,8,8,6,1,0,32,64,224,64,64,
64,64,224,5,8,8,6,0,0,16,32,112,136,136,136,136,
112,5,8,8,6,0,0,32,80,112,136,136,136,136,112,5,
8,8,6,0,0,16,32,136,136,136,136,136,112,5,8,8,
6,0,0,16,32,136,136,80,32,32,32,5,8,8,6,0,
0,16,32,0,112,8,120,136,120,5,7,7,6,0,0,80,
0,112,8,120,136,120,5,8,8,6,0,0,16,32,0,112,
136,248,128,112,2,8,8,6,2,0,64,128,0,128,128,128,
128,128,5,8,8,6,0,0,16,32,0,112,136,136,136,112,
5,8,8,6,0,0,32,80,0,112,136,136,136,112,5,8,
8,6,0,0,16,32,0,136,136,136,152,104,5,9,9,6,
0,255,16,32,0,136,136,136,120,8,112,5,8,8,6,0,
0,80,32,112,136,128,128,136,112,5,8,8,6,0,0,80,
32,0,112,128,128,136,112,5,8,8,6,0,0,80,32,240,
136,136,136,136,240,6,8,8,6,0,0,4,20,24,112,144,
144,144,112,5,8,8,6,0,0,16,32,128,128,128,128,128,
248,3,8,8,6,1,0,32,64,0,192,64,64,64,224,5,
8,8,6,0,0,16,144,160,128,128,128,128,248,5,8,8,
6,1,0,8,200,80,64,64,64,64,224,5,8,8,6,0,
0,80,32,136,200,168,152,136,136,5,8,8,6,0,0,80,
32,0,176,200,136,136,136,5,8,8,6,0,0,16,32,240,
136,240,160,144,136,5,8,8,6,0,0,16,32,0,176,200,
128,128,128,5,8,8,6,0,0,80,32,120,128,128,112,8,
240,5,8,8,6,0,0,80,32,0,112,128,112,8,240,5,
8,8,6,0,0,80,32,248,32,32,32,32,32,6,8,8,
6,0,0,4,68,72,224,64,64,64,48,5,8,8,6,0,
0,80,32,248,8,48,64,128,248,5,8,8,6,0,0,80,
32,0,248,16,32,64,248,0,0,0,6,0,0,0,0,0,
6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,
0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,0,
0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,
6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,
0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,0,
0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,
6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,
0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,0,
0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,
6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,
0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,0,
0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,
6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,
0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,0,
0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,
6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,
0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,0,
0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,
6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,
0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,0,
0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,
6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,
0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,0,
0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,
6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,
0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,0,
0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,
6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,
0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,0,
0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,
6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,
0,0,6,0,0,0,0,0,6,0,0,0,0,0,6,0,
0,0,0,0,6,0,0,0,0,0,6,0,0,0,0,0,
6,0,0,0,0,0,6,0,0,0,0,0,6,0,0,0,
0,0,6,0,0,0,0,0,6,0,0};

View File

@ -0,0 +1,45 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
Fontname: Marlin_symbols
Copyright: Created with Fony 1.4.7
Capital A Height: 0, '1' Height: 0
Calculated Max Values w= 5 h=10 x= 0 y= 3 dx= 6 dy= 0 ascent= 8 len=10
Font Bounding box w= 6 h= 9 x= 0 y=-2
Calculated Min Values x= 0 y=-2 dx= 0 dy= 0
Pure Font ascent = 0 descent= 0
X Font ascent = 0 descent= 0
Max Font ascent = 8 descent=-2
*/
#include <U8glib.h>
const u8g_fntpgm_uint8_t Marlin_symbols[140] U8G_SECTION(".progmem.Marlin_symbols") = {
0, 6, 9, 0, 254, 0, 0, 0, 0, 0, 1, 9, 0, 8, 254, 0,
0, 5, 8, 8, 6, 0, 0, 64, 240, 200, 136, 136, 152, 120, 16, 5,
8, 8, 6, 0, 0, 192, 248, 136, 136, 136, 136, 136, 248, 5, 5, 5,
6, 0, 1, 32, 48, 248, 48, 32, 5, 8, 8, 6, 0, 0, 32, 112,
248, 32, 32, 32, 32, 224, 5, 9, 9, 6, 0, 255, 32, 112, 168, 168,
184, 136, 136, 112, 32, 5, 9, 9, 6, 0, 255, 224, 128, 192, 176, 168,
40, 48, 40, 40, 5, 9, 9, 6, 0, 255, 248, 168, 136, 136, 136, 136,
136, 168, 248, 5, 10, 10, 6, 0, 254, 32, 80, 80, 80, 80, 136, 168,
168, 136, 112, 3, 3, 3, 6, 0, 3, 64, 160, 64
};

73
Marlin/drivers.h Normal file
View File

@ -0,0 +1,73 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _DRIVERS_H_
#define _DRIVERS_H_
#include "MarlinConfig.h"
#define A4988 0x001
#define DRV8825 0x002
#define LV8729 0x003
#define L6470 0x104
#define TB6560 0x005
#define TB6600 0x006
#define TMC2100 0x007
#define TMC2130 0x108
#define TMC2130_STANDALONE 0x008
#define TMC2208 0x109
#define TMC2208_STANDALONE 0x009
#define TMC26X 0x10A
#define TMC26X_STANDALONE 0x00A
#define TMC2660 0x10B
#define TMC2660_STANDALONE 0x00B
#define _AXIS_DRIVER_TYPE(A,T) ( defined(A##_DRIVER_TYPE) && (A##_DRIVER_TYPE == T) )
#define AXIS_DRIVER_TYPE_X(T) _AXIS_DRIVER_TYPE(X,T)
#define AXIS_DRIVER_TYPE_Y(T) _AXIS_DRIVER_TYPE(Y,T)
#define AXIS_DRIVER_TYPE_Z(T) _AXIS_DRIVER_TYPE(Z,T)
#define AXIS_DRIVER_TYPE_X2(T) (ENABLED(X_DUAL_STEPPER_DRIVERS) || ENABLED(DUAL_X_CARRIAGE)) && _AXIS_DRIVER_TYPE(X2,T)
#define AXIS_DRIVER_TYPE_Y2(T) (ENABLED(Y_DUAL_STEPPER_DRIVERS) && _AXIS_DRIVER_TYPE(Y2,T))
#define AXIS_DRIVER_TYPE_Z2(T) (ENABLED(Z_DUAL_STEPPER_DRIVERS) && _AXIS_DRIVER_TYPE(Z2,T))
#define AXIS_DRIVER_TYPE_E0(T) (E_STEPPERS > 0 && _AXIS_DRIVER_TYPE(E0,T))
#define AXIS_DRIVER_TYPE_E1(T) (E_STEPPERS > 1 && _AXIS_DRIVER_TYPE(E1,T))
#define AXIS_DRIVER_TYPE_E2(T) (E_STEPPERS > 2 && _AXIS_DRIVER_TYPE(E2,T))
#define AXIS_DRIVER_TYPE_E3(T) (E_STEPPERS > 3 && _AXIS_DRIVER_TYPE(E3,T))
#define AXIS_DRIVER_TYPE_E4(T) (E_STEPPERS > 4 && _AXIS_DRIVER_TYPE(E4,T))
#define AXIS_DRIVER_TYPE(A,T) AXIS_DRIVER_TYPE_##A(T)
#define HAS_DRIVER(T) (AXIS_DRIVER_TYPE_X(T) || AXIS_DRIVER_TYPE_X2(T) || \
AXIS_DRIVER_TYPE_Y(T) || AXIS_DRIVER_TYPE_Y2(T) || \
AXIS_DRIVER_TYPE_Z(T) || AXIS_DRIVER_TYPE_Z2(T) || \
AXIS_DRIVER_TYPE_E0(T) || AXIS_DRIVER_TYPE_E1(T) || \
AXIS_DRIVER_TYPE_E2(T) || AXIS_DRIVER_TYPE_E3(T) || \
AXIS_DRIVER_TYPE_E4(T) )
// Test for supported TMC drivers that require advanced configuration
// Does not match standalone configurations
#define HAS_TRINAMIC (HAS_DRIVER(TMC2130) || HAS_DRIVER(TMC2208))
#define AXIS_IS_TMC(A) ( AXIS_DRIVER_TYPE_##A(TMC2130) || \
AXIS_DRIVER_TYPE_##A(TMC2208) )
#endif // _DRIVERS_H_

170
Marlin/duration_t.h Normal file
View File

@ -0,0 +1,170 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef __DURATION_T__
#define __DURATION_T__
#include <stdio.h>
#include <inttypes.h>
struct duration_t {
/**
* @brief Duration is stored in seconds
*/
uint32_t value;
/**
* @brief Constructor
*/
duration_t()
: duration_t(0) {};
/**
* @brief Constructor
*
* @param seconds The number of seconds
*/
duration_t(uint32_t const &seconds) {
this->value = seconds;
}
/**
* @brief Equality comparison
* @details Overloads the equality comparison operator
*
* @param value The number of seconds to compare to
* @return True if both durations are equal
*/
bool operator==(const uint32_t &value) const {
return (this->value == value);
}
/**
* @brief Inequality comparison
* @details Overloads the inequality comparison operator
*
* @param value The number of seconds to compare to
* @return False if both durations are equal
*/
bool operator!=(const uint32_t &value) const {
return ! this->operator==(value);
}
/**
* @brief Formats the duration as years
* @return The number of years
*/
inline uint8_t year() const {
return this->day() / 365;
}
/**
* @brief Formats the duration as days
* @return The number of days
*/
inline uint16_t day() const {
return this->hour() / 24;
}
/**
* @brief Formats the duration as hours
* @return The number of hours
*/
inline uint32_t hour() const {
return this->minute() / 60;
}
/**
* @brief Formats the duration as minutes
* @return The number of minutes
*/
inline uint32_t minute() const {
return this->second() / 60;
}
/**
* @brief Formats the duration as seconds
* @return The number of seconds
*/
inline uint32_t second() const {
return this->value;
}
/**
* @brief Formats the duration as a string
* @details String will be formated using a "full" representation of duration
*
* @param buffer The array pointed to must be able to accommodate 21 bytes
*
* Output examples:
* 123456789012345678901 (strlen)
* 135y 364d 23h 59m 59s
* 364d 23h 59m 59s
* 23h 59m 59s
* 59m 59s
* 59s
*/
void toString(char *buffer) const {
int y = this->year(),
d = this->day() % 365,
h = this->hour() % 24,
m = this->minute() % 60,
s = this->second() % 60;
if (y) sprintf_P(buffer, PSTR("%iy %id %ih %im %is"), y, d, h, m, s);
else if (d) sprintf_P(buffer, PSTR("%id %ih %im %is"), d, h, m, s);
else if (h) sprintf_P(buffer, PSTR("%ih %im %is"), h, m, s);
else if (m) sprintf_P(buffer, PSTR("%im %is"), m, s);
else sprintf_P(buffer, PSTR("%is"), s);
}
/**
* @brief Formats the duration as a string
* @details String will be formated using a "digital" representation of duration
*
* @param buffer The array pointed to must be able to accommodate 10 bytes
*
* Output examples:
* 123456789 (strlen)
* 99:59
* 11d 12:33
*/
uint8_t toDigital(char *buffer, bool with_days=false) const {
uint16_t h = uint16_t(this->hour()),
m = uint16_t(this->minute() % 60UL);
if (with_days) {
uint16_t d = this->day();
sprintf_P(buffer, PSTR("%ud %02u:%02u"), d, h % 24, m);
return d >= 10 ? 9 : 8;
}
else if (h < 100) {
sprintf_P(buffer, PSTR("%02u:%02u"), h, m);
return 5;
}
else {
sprintf_P(buffer, PSTR("%u:%02u"), h, m);
return 6;
}
}
};
#endif // __DURATION_T__

View File

@ -0,0 +1,40 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* emergency_parser.cpp - Intercept special commands directly in the serial stream
*/
#include "MarlinConfig.h"
#if ENABLED(EMERGENCY_PARSER)
#include "emergency_parser.h"
// Static data members
bool EmergencyParser::killed_by_M112; // = false
EmergencyParser::State EmergencyParser::state; // = EP_RESET
// Global instance
EmergencyParser emergency_parser;
#endif // EMERGENCY_PARSER

144
Marlin/emergency_parser.h Normal file
View File

@ -0,0 +1,144 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* emergency_parser.h - Intercept special commands directly in the serial stream
*/
#ifndef _EMERGENCY_PARSER_H_
#define _EMERGENCY_PARSER_H_
// External references
extern volatile bool wait_for_user, wait_for_heatup;
void quickstop_stepper();
class EmergencyParser {
public:
// Currently looking for: M108, M112, M410
enum State : char {
EP_RESET,
EP_N,
EP_M,
EP_M1,
EP_M10,
EP_M108,
EP_M11,
EP_M112,
EP_M4,
EP_M41,
EP_M410,
EP_IGNORE // to '\n'
};
static bool killed_by_M112;
static State state;
EmergencyParser() {}
__attribute__((always_inline)) inline
static void update(const uint8_t c) {
switch (state) {
case EP_RESET:
switch (c) {
case ' ': break;
case 'N': state = EP_N; break;
case 'M': state = EP_M; break;
default: state = EP_IGNORE;
}
break;
case EP_N:
switch (c) {
case '0': case '1': case '2':
case '3': case '4': case '5':
case '6': case '7': case '8':
case '9': case '-': case ' ': break;
case 'M': state = EP_M; break;
default: state = EP_IGNORE;
}
break;
case EP_M:
switch (c) {
case ' ': break;
case '1': state = EP_M1; break;
case '4': state = EP_M4; break;
default: state = EP_IGNORE;
}
break;
case EP_M1:
switch (c) {
case '0': state = EP_M10; break;
case '1': state = EP_M11; break;
default: state = EP_IGNORE;
}
break;
case EP_M10:
state = (c == '8') ? EP_M108 : EP_IGNORE;
break;
case EP_M11:
state = (c == '2') ? EP_M112 : EP_IGNORE;
break;
case EP_M4:
state = (c == '1') ? EP_M41 : EP_IGNORE;
break;
case EP_M41:
state = (c == '0') ? EP_M410 : EP_IGNORE;
break;
case EP_IGNORE:
if (c == '\n') state = EP_RESET;
break;
default:
if (c == '\n') {
switch (state) {
case EP_M108:
wait_for_user = wait_for_heatup = false;
break;
case EP_M112:
killed_by_M112 = true;
break;
case EP_M410:
quickstop_stepper();
break;
default:
break;
}
state = EP_RESET;
}
}
}
};
extern EmergencyParser emergency_parser;
#endif // _EMERGENCY_PARSER_H_

239
Marlin/endstop_interrupts.h Normal file
View File

@ -0,0 +1,239 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* 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)
*/
#ifndef _ENDSTOP_INTERRUPTS_H_
#define _ENDSTOP_INTERRUPTS_H_
#include "macros.h"
// One ISR for all EXT-Interrupts
void endstop_ISR(void) { 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 (D13, D14).
* 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)
#undef digitalPinToPCICR
#define digitalPinToPCICR(p) ( WITHIN(p, 10, 15) || \
WITHIN(p, 50, 53) || \
WITHIN(p, 62, 69) ? &PCICR : (uint8_t*)0 )
#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 : \
(uint8_t *)0 )
#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 )
#endif
// Install Pin change interrupt for a pin. Can be called multiple times.
void pciSetup(const int8_t 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) { endstop_ISR(); }
#endif
#ifdef PCINT2_vect
ISR(PCINT2_vect) { endstop_ISR(); }
#endif
#ifdef PCINT3_vect
ISR(PCINT3_vect) { endstop_ISR(); }
#endif
void setup_endstop_interrupts( void ) {
#if HAS_X_MAX
#if digitalPinToInterrupt(X_MAX_PIN) != NOT_AN_INTERRUPT // if pin has an external interrupt
attachInterrupt(digitalPinToInterrupt(X_MAX_PIN), endstop_ISR, CHANGE); // assign it
#else
// Not all used endstop/probe -pins can raise interrupts. Please deactivate ENDSTOP_INTERRUPTS or change the pin configuration!
static_assert(digitalPinToPCICR(X_MAX_PIN) != NULL, "X_MAX_PIN is not interrupt-capable"); // if pin has no pin change interrupt - error
pciSetup(X_MAX_PIN); // assign it
#endif
#endif
#if HAS_X_MIN
#if digitalPinToInterrupt(X_MIN_PIN) != NOT_AN_INTERRUPT
attachInterrupt(digitalPinToInterrupt(X_MIN_PIN), endstop_ISR, CHANGE);
#else
// Not all used endstop/probe -pins can raise interrupts. Please deactivate ENDSTOP_INTERRUPTS or change the pin configuration!
static_assert(digitalPinToPCICR(X_MIN_PIN) != NULL, "X_MIN_PIN is not interrupt-capable");
pciSetup(X_MIN_PIN);
#endif
#endif
#if HAS_Y_MAX
#if digitalPinToInterrupt(Y_MAX_PIN) != NOT_AN_INTERRUPT
attachInterrupt(digitalPinToInterrupt(Y_MAX_PIN), endstop_ISR, CHANGE);
#else
// Not all used endstop/probe -pins can raise interrupts. Please deactivate ENDSTOP_INTERRUPTS or change the pin configuration!
static_assert(digitalPinToPCICR(Y_MAX_PIN) != NULL, "Y_MAX_PIN is not interrupt-capable");
pciSetup(Y_MAX_PIN);
#endif
#endif
#if HAS_Y_MIN
#if digitalPinToInterrupt(Y_MIN_PIN) != NOT_AN_INTERRUPT
attachInterrupt(digitalPinToInterrupt(Y_MIN_PIN), endstop_ISR, CHANGE);
#else
// Not all used endstop/probe -pins can raise interrupts. Please deactivate ENDSTOP_INTERRUPTS or change the pin configuration!
static_assert(digitalPinToPCICR(Y_MIN_PIN) != NULL, "Y_MIN_PIN is not interrupt-capable");
pciSetup(Y_MIN_PIN);
#endif
#endif
#if HAS_Z_MAX
#if digitalPinToInterrupt(Z_MAX_PIN) != NOT_AN_INTERRUPT
attachInterrupt(digitalPinToInterrupt(Z_MAX_PIN), endstop_ISR, CHANGE);
#else
// Not all used endstop/probe -pins can raise interrupts. Please deactivate ENDSTOP_INTERRUPTS or change the pin configuration!
static_assert(digitalPinToPCICR(Z_MAX_PIN) != NULL, "Z_MAX_PIN is not interrupt-capable");
pciSetup(Z_MAX_PIN);
#endif
#endif
#if HAS_Z_MIN
#if digitalPinToInterrupt(Z_MIN_PIN) != NOT_AN_INTERRUPT
attachInterrupt(digitalPinToInterrupt(Z_MIN_PIN), endstop_ISR, CHANGE);
#else
// Not all used endstop/probe -pins can raise interrupts. Please deactivate ENDSTOP_INTERRUPTS or change the pin configuration!
static_assert(digitalPinToPCICR(Z_MIN_PIN) != NULL, "Z_MIN_PIN is not interrupt-capable");
pciSetup(Z_MIN_PIN);
#endif
#endif
#if HAS_X2_MAX
#if (digitalPinToInterrupt(X2_MAX_PIN) != NOT_AN_INTERRUPT)
attachInterrupt(digitalPinToInterrupt(X2_MAX_PIN), endstop_ISR, CHANGE);
#else
// Not all used endstop/probe -pins can raise interrupts. Please deactivate ENDSTOP_INTERRUPTS or change the pin configuration!
static_assert(digitalPinToPCICR(X2_MAX_PIN) != NULL, "X2_MAX_PIN is not interrupt-capable");
pciSetup(X2_MAX_PIN);
#endif
#endif
#if HAS_X2_MIN
#if (digitalPinToInterrupt(X2_MIN_PIN) != NOT_AN_INTERRUPT)
attachInterrupt(digitalPinToInterrupt(X2_MIN_PIN), endstop_ISR, CHANGE);
#else
// Not all used endstop/probe -pins can raise interrupts. Please deactivate ENDSTOP_INTERRUPTS or change the pin configuration!
static_assert(digitalPinToPCICR(X2_MIN_PIN) != NULL, "X2_MIN_PIN is not interrupt-capable");
pciSetup(X2_MIN_PIN);
#endif
#endif
#if HAS_Y2_MAX
#if (digitalPinToInterrupt(Y2_MAX_PIN) != NOT_AN_INTERRUPT)
attachInterrupt(digitalPinToInterrupt(Y2_MAX_PIN), endstop_ISR, CHANGE);
#else
// Not all used endstop/probe -pins can raise interrupts. Please deactivate ENDSTOP_INTERRUPTS or change the pin configuration!
static_assert(digitalPinToPCICR(Y2_MAX_PIN) != NULL, "Y2_MAX_PIN is not interrupt-capable");
pciSetup(Y2_MAX_PIN);
#endif
#endif
#if HAS_Y2_MIN
#if (digitalPinToInterrupt(Y2_MIN_PIN) != NOT_AN_INTERRUPT)
attachInterrupt(digitalPinToInterrupt(Y2_MIN_PIN), endstop_ISR, CHANGE);
#else
// Not all used endstop/probe -pins can raise interrupts. Please deactivate ENDSTOP_INTERRUPTS or change the pin configuration!
static_assert(digitalPinToPCICR(Y2_MIN_PIN) != NULL, "Y2_MIN_PIN is not interrupt-capable");
pciSetup(Y2_MIN_PIN);
#endif
#endif
#if HAS_Z2_MAX
#if digitalPinToInterrupt(Z2_MAX_PIN) != NOT_AN_INTERRUPT
attachInterrupt(digitalPinToInterrupt(Z2_MAX_PIN), endstop_ISR, CHANGE);
#else
// Not all used endstop/probe -pins can raise interrupts. Please deactivate ENDSTOP_INTERRUPTS or change the pin configuration!
static_assert(digitalPinToPCICR(Z2_MAX_PIN) != NULL, "Z2_MAX_PIN is not interrupt-capable");
pciSetup(Z2_MAX_PIN);
#endif
#endif
#if HAS_Z2_MIN
#if digitalPinToInterrupt(Z2_MIN_PIN) != NOT_AN_INTERRUPT
attachInterrupt(digitalPinToInterrupt(Z2_MIN_PIN), endstop_ISR, CHANGE);
#else
// Not all used endstop/probe -pins can raise interrupts. Please deactivate ENDSTOP_INTERRUPTS or change the pin configuration!
static_assert(digitalPinToPCICR(Z2_MIN_PIN) != NULL, "Z2_MIN_PIN is not interrupt-capable");
pciSetup(Z2_MIN_PIN);
#endif
#endif
#if HAS_Z_MIN_PROBE_PIN
#if digitalPinToInterrupt(Z_MIN_PROBE_PIN) != NOT_AN_INTERRUPT
attachInterrupt(digitalPinToInterrupt(Z_MIN_PROBE_PIN), endstop_ISR, CHANGE);
#else
// Not all used endstop/probe -pins can raise interrupts. Please deactivate ENDSTOP_INTERRUPTS or change the pin configuration!
static_assert(digitalPinToPCICR(Z_MIN_PROBE_PIN) != NULL, "Z_MIN_PROBE_PIN is not interrupt-capable");
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.
}
#endif // _ENDSTOP_INTERRUPTS_H_

774
Marlin/endstops.cpp Normal file
View File

@ -0,0 +1,774 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* endstops.cpp - A singleton object to manage endstops
*/
#include "Marlin.h"
#include "cardreader.h"
#include "endstops.h"
#include "temperature.h"
#include "stepper.h"
#include "ultralcd.h"
#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
#include "endstop_interrupts.h"
#endif
Endstops endstops;
// public:
bool Endstops::enabled, Endstops::enabled_globally; // Initialized by settings.load()
volatile uint8_t Endstops::hit_state;
Endstops::esbits_t Endstops::live_state = 0;
#if ENABLED(ENDSTOP_NOISE_FILTER)
Endstops::esbits_t Endstops::validated_live_state;
uint8_t Endstops::endstop_poll_count;
#endif
#if HAS_BED_PROBE
volatile bool Endstops::z_probe_enabled = false;
#endif
// Initialized by settings.load()
#if ENABLED(X_DUAL_ENDSTOPS)
float Endstops::x_endstop_adj;
#endif
#if ENABLED(Y_DUAL_ENDSTOPS)
float Endstops::y_endstop_adj;
#endif
#if ENABLED(Z_DUAL_ENDSTOPS)
float Endstops::z_endstop_adj;
#endif
/**
* Class and Instance Methods
*/
void Endstops::init() {
#if HAS_X_MIN
#if ENABLED(ENDSTOPPULLUP_XMIN)
SET_INPUT_PULLUP(X_MIN_PIN);
#else
SET_INPUT(X_MIN_PIN);
#endif
#endif
#if HAS_X2_MIN
#if ENABLED(ENDSTOPPULLUP_XMIN)
SET_INPUT_PULLUP(X2_MIN_PIN);
#else
SET_INPUT(X2_MIN_PIN);
#endif
#endif
#if HAS_Y_MIN
#if ENABLED(ENDSTOPPULLUP_YMIN)
SET_INPUT_PULLUP(Y_MIN_PIN);
#else
SET_INPUT(Y_MIN_PIN);
#endif
#endif
#if HAS_Y2_MIN
#if ENABLED(ENDSTOPPULLUP_YMIN)
SET_INPUT_PULLUP(Y2_MIN_PIN);
#else
SET_INPUT(Y2_MIN_PIN);
#endif
#endif
#if HAS_Z_MIN
#if ENABLED(ENDSTOPPULLUP_ZMIN)
SET_INPUT_PULLUP(Z_MIN_PIN);
#else
SET_INPUT(Z_MIN_PIN);
#endif
#endif
#if HAS_Z2_MIN
#if ENABLED(ENDSTOPPULLUP_ZMIN)
SET_INPUT_PULLUP(Z2_MIN_PIN);
#else
SET_INPUT(Z2_MIN_PIN);
#endif
#endif
#if HAS_X_MAX
#if ENABLED(ENDSTOPPULLUP_XMAX)
SET_INPUT_PULLUP(X_MAX_PIN);
#else
SET_INPUT(X_MAX_PIN);
#endif
#endif
#if HAS_X2_MAX
#if ENABLED(ENDSTOPPULLUP_XMAX)
SET_INPUT_PULLUP(X2_MAX_PIN);
#else
SET_INPUT(X2_MAX_PIN);
#endif
#endif
#if HAS_Y_MAX
#if ENABLED(ENDSTOPPULLUP_YMAX)
SET_INPUT_PULLUP(Y_MAX_PIN);
#else
SET_INPUT(Y_MAX_PIN);
#endif
#endif
#if HAS_Y2_MAX
#if ENABLED(ENDSTOPPULLUP_YMAX)
SET_INPUT_PULLUP(Y2_MAX_PIN);
#else
SET_INPUT(Y2_MAX_PIN);
#endif
#endif
#if HAS_Z_MAX
#if ENABLED(ENDSTOPPULLUP_ZMAX)
SET_INPUT_PULLUP(Z_MAX_PIN);
#else
SET_INPUT(Z_MAX_PIN);
#endif
#endif
#if HAS_Z2_MAX
#if ENABLED(ENDSTOPPULLUP_ZMAX)
SET_INPUT_PULLUP(Z2_MAX_PIN);
#else
SET_INPUT(Z2_MAX_PIN);
#endif
#endif
#if ENABLED(Z_MIN_PROBE_ENDSTOP)
#if ENABLED(ENDSTOPPULLUP_ZMIN_PROBE)
SET_INPUT_PULLUP(Z_MIN_PROBE_PIN);
#else
SET_INPUT(Z_MIN_PROBE_PIN);
#endif
#endif
#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
setup_endstop_interrupts();
#endif
// Enable endstops
enable_globally(
#if ENABLED(ENDSTOPS_ALWAYS_ON_DEFAULT)
true
#else
false
#endif
);
} // Endstops::init
// Called at ~1KHz from Temperature ISR: Poll endstop state if required
void Endstops::poll() {
#if ENABLED(PINS_DEBUGGING)
run_monitor(); // report changes in endstop status
#endif
#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE) && ENABLED(ENDSTOP_NOISE_FILTER)
if (endstop_poll_count) update();
#elif DISABLED(ENDSTOP_INTERRUPTS_FEATURE) || ENABLED(ENDSTOP_NOISE_FILTER)
update();
#endif
}
void Endstops::enable_globally(const bool onoff) {
enabled_globally = enabled = onoff;
#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
update();
#endif
}
// Enable / disable endstop checking
void Endstops::enable(const bool onoff) {
enabled = onoff;
#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
update();
#endif
}
// Disable / Enable endstops based on ENSTOPS_ONLY_FOR_HOMING and global enable
void Endstops::not_homing() {
enabled = enabled_globally;
#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
update();
#endif
}
#if ENABLED(VALIDATE_HOMING_ENDSTOPS)
// If the last move failed to trigger an endstop, call kill
void Endstops::validate_homing_move() {
if (trigger_state()) hit_on_purpose();
else kill(PSTR(MSG_ERR_HOMING_FAILED));
}
#endif
// Enable / disable endstop z-probe checking
#if HAS_BED_PROBE
void Endstops::enable_z_probe(const bool onoff) {
z_probe_enabled = onoff;
#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
update();
#endif
}
#endif
#if ENABLED(PINS_DEBUGGING)
void Endstops::run_monitor() {
if (!monitor_flag) return;
static uint8_t monitor_count = 16; // offset this check from the others
monitor_count += _BV(1); // 15 Hz
monitor_count &= 0x7F;
if (!monitor_count) monitor(); // report changes in endstop status
}
#endif
void Endstops::event_handler() {
static uint8_t prev_hit_state; // = 0
if (hit_state && hit_state != prev_hit_state) {
#if ENABLED(ULTRA_LCD)
char chrX = ' ', chrY = ' ', chrZ = ' ', chrP = ' ';
#define _SET_STOP_CHAR(A,C) (chr## A = C)
#else
#define _SET_STOP_CHAR(A,C) ;
#endif
#define _ENDSTOP_HIT_ECHO(A,C) do{ \
SERIAL_ECHOPAIR(" " STRINGIFY(A) ":", planner.triggered_position_mm(_AXIS(A))); \
_SET_STOP_CHAR(A,C); }while(0)
#define _ENDSTOP_HIT_TEST(A,C) \
if (TEST(hit_state, A ##_MIN) || TEST(hit_state, A ##_MAX)) \
_ENDSTOP_HIT_ECHO(A,C)
#define ENDSTOP_HIT_TEST_X() _ENDSTOP_HIT_TEST(X,'X')
#define ENDSTOP_HIT_TEST_Y() _ENDSTOP_HIT_TEST(Y,'Y')
#define ENDSTOP_HIT_TEST_Z() _ENDSTOP_HIT_TEST(Z,'Z')
SERIAL_ECHO_START();
SERIAL_ECHOPGM(MSG_ENDSTOPS_HIT);
ENDSTOP_HIT_TEST_X();
ENDSTOP_HIT_TEST_Y();
ENDSTOP_HIT_TEST_Z();
#if ENABLED(Z_MIN_PROBE_ENDSTOP)
#define P_AXIS Z_AXIS
if (TEST(hit_state, Z_MIN_PROBE)) _ENDSTOP_HIT_ECHO(P, 'P');
#endif
SERIAL_EOL();
#if ENABLED(ULTRA_LCD)
lcd_status_printf_P(0, PSTR(MSG_LCD_ENDSTOPS " %c %c %c %c"), chrX, chrY, chrZ, chrP);
#endif
#if ENABLED(ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED) && ENABLED(SDSUPPORT)
if (planner.abort_on_endstop_hit) {
card.sdprinting = false;
card.closefile();
quickstop_stepper();
thermalManager.disable_all_heaters(); // switch off all heaters.
}
#endif
}
prev_hit_state = hit_state;
} // Endstops::report_state
static void print_es_state(const bool is_hit, const char * const label=NULL) {
if (label) serialprintPGM(label);
SERIAL_PROTOCOLPGM(": ");
serialprintPGM(is_hit ? PSTR(MSG_ENDSTOP_HIT) : PSTR(MSG_ENDSTOP_OPEN));
SERIAL_EOL();
}
void _O2 Endstops::M119() {
SERIAL_PROTOCOLLNPGM(MSG_M119_REPORT);
#define ES_REPORT(S) print_es_state(READ(S##_PIN) != S##_ENDSTOP_INVERTING, PSTR(MSG_##S))
#if HAS_X_MIN
ES_REPORT(X_MIN);
#endif
#if HAS_X2_MIN
ES_REPORT(X2_MIN);
#endif
#if HAS_X_MAX
ES_REPORT(X_MAX);
#endif
#if HAS_X2_MAX
ES_REPORT(X2_MAX);
#endif
#if HAS_Y_MIN
ES_REPORT(Y_MIN);
#endif
#if HAS_Y2_MIN
ES_REPORT(Y2_MIN);
#endif
#if HAS_Y_MAX
ES_REPORT(Y_MAX);
#endif
#if HAS_Y2_MAX
ES_REPORT(Y2_MAX);
#endif
#if HAS_Z_MIN
ES_REPORT(Z_MIN);
#endif
#if HAS_Z2_MIN
ES_REPORT(Z2_MIN);
#endif
#if HAS_Z_MAX
ES_REPORT(Z_MAX);
#endif
#if HAS_Z2_MAX
ES_REPORT(Z2_MAX);
#endif
#if ENABLED(Z_MIN_PROBE_ENDSTOP)
print_es_state(READ(Z_MIN_PROBE_PIN) != Z_MIN_PROBE_ENDSTOP_INVERTING, PSTR(MSG_Z_PROBE));
#endif
#if ENABLED(FILAMENT_RUNOUT_SENSOR)
#if NUM_RUNOUT_SENSORS == 1
print_es_state(READ(FIL_RUNOUT_PIN) != FIL_RUNOUT_INVERTING, PSTR(MSG_FILAMENT_RUNOUT_SENSOR));
#else
for (uint8_t i = 1; i <= NUM_RUNOUT_SENSORS; i++) {
pin_t pin;
switch (i) {
default: continue;
case 1: pin = FIL_RUNOUT_PIN; break;
case 2: pin = FIL_RUNOUT2_PIN; break;
#if NUM_RUNOUT_SENSORS > 2
case 3: pin = FIL_RUNOUT3_PIN; break;
#if NUM_RUNOUT_SENSORS > 3
case 4: pin = FIL_RUNOUT4_PIN; break;
#if NUM_RUNOUT_SENSORS > 4
case 5: pin = FIL_RUNOUT5_PIN; break;
#endif
#endif
#endif
}
SERIAL_PROTOCOLPGM(MSG_FILAMENT_RUNOUT_SENSOR);
if (i > 1) { SERIAL_CHAR(' '); SERIAL_CHAR('0' + i); }
print_es_state(digitalRead(pin) != FIL_RUNOUT_INVERTING);
}
#endif
#endif
} // Endstops::M119
// The following routines are called from an ISR context. It could be the temperature ISR, the
// endstop ISR or the Stepper ISR.
#define _ENDSTOP(AXIS, MINMAX) AXIS ##_## MINMAX
#define _ENDSTOP_PIN(AXIS, MINMAX) AXIS ##_## MINMAX ##_PIN
#define _ENDSTOP_INVERTING(AXIS, MINMAX) AXIS ##_## MINMAX ##_ENDSTOP_INVERTING
// Check endstops - Could be called from Temperature ISR!
void Endstops::update() {
#if DISABLED(ENDSTOP_NOISE_FILTER)
if (!abort_enabled()) return;
#endif
#define UPDATE_ENDSTOP_BIT(AXIS, MINMAX) SET_BIT_TO(live_state, _ENDSTOP(AXIS, MINMAX), (READ(_ENDSTOP_PIN(AXIS, MINMAX)) != _ENDSTOP_INVERTING(AXIS, MINMAX)))
#define COPY_LIVE_STATE(SRC_BIT, DST_BIT) SET_BIT_TO(live_state, DST_BIT, TEST(live_state, SRC_BIT))
#if ENABLED(G38_PROBE_TARGET) && PIN_EXISTS(Z_MIN_PROBE) && !(CORE_IS_XY || CORE_IS_XZ)
// If G38 command is active check Z_MIN_PROBE for ALL movement
if (G38_move) UPDATE_ENDSTOP_BIT(Z, MIN_PROBE);
#endif
// With Dual X, endstops are only checked in the homing direction for the active extruder
#if ENABLED(DUAL_X_CARRIAGE)
#define E0_ACTIVE stepper.movement_extruder() == 0
#define X_MIN_TEST ((X_HOME_DIR < 0 && E0_ACTIVE) || (X2_HOME_DIR < 0 && !E0_ACTIVE))
#define X_MAX_TEST ((X_HOME_DIR > 0 && E0_ACTIVE) || (X2_HOME_DIR > 0 && !E0_ACTIVE))
#else
#define X_MIN_TEST true
#define X_MAX_TEST true
#endif
// Use HEAD for core axes, AXIS for others
#if CORE_IS_XY || CORE_IS_XZ
#define X_AXIS_HEAD X_HEAD
#else
#define X_AXIS_HEAD X_AXIS
#endif
#if CORE_IS_XY || CORE_IS_YZ
#define Y_AXIS_HEAD Y_HEAD
#else
#define Y_AXIS_HEAD Y_AXIS
#endif
#if CORE_IS_XZ || CORE_IS_YZ
#define Z_AXIS_HEAD Z_HEAD
#else
#define Z_AXIS_HEAD Z_AXIS
#endif
/**
* Check and update endstops
*/
#if HAS_X_MIN
#if ENABLED(X_DUAL_ENDSTOPS)
UPDATE_ENDSTOP_BIT(X, MIN);
#if HAS_X2_MIN
UPDATE_ENDSTOP_BIT(X2, MIN);
#else
COPY_LIVE_STATE(X_MIN, X2_MIN);
#endif
#else
UPDATE_ENDSTOP_BIT(X, MIN);
#endif
#endif
#if HAS_X_MAX
#if ENABLED(X_DUAL_ENDSTOPS)
UPDATE_ENDSTOP_BIT(X, MAX);
#if HAS_X2_MAX
UPDATE_ENDSTOP_BIT(X2, MAX);
#else
COPY_LIVE_STATE(X_MAX, X2_MAX);
#endif
#else
UPDATE_ENDSTOP_BIT(X, MAX);
#endif
#endif
#if HAS_Y_MIN
#if ENABLED(Y_DUAL_ENDSTOPS)
UPDATE_ENDSTOP_BIT(Y, MIN);
#if HAS_Y2_MIN
UPDATE_ENDSTOP_BIT(Y2, MIN);
#else
COPY_LIVE_STATE(Y_MIN, Y2_MIN);
#endif
#else
UPDATE_ENDSTOP_BIT(Y, MIN);
#endif
#endif
#if HAS_Y_MAX
#if ENABLED(Y_DUAL_ENDSTOPS)
UPDATE_ENDSTOP_BIT(Y, MAX);
#if HAS_Y2_MAX
UPDATE_ENDSTOP_BIT(Y2, MAX);
#else
COPY_LIVE_STATE(Y_MAX, Y2_MAX);
#endif
#else
UPDATE_ENDSTOP_BIT(Y, MAX);
#endif
#endif
#if HAS_Z_MIN
#if ENABLED(Z_DUAL_ENDSTOPS)
UPDATE_ENDSTOP_BIT(Z, MIN);
#if HAS_Z2_MIN
UPDATE_ENDSTOP_BIT(Z2, MIN);
#else
COPY_LIVE_STATE(Z_MIN, Z2_MIN);
#endif
#elif ENABLED(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN)
UPDATE_ENDSTOP_BIT(Z, MIN);
#elif Z_HOME_DIR < 0
UPDATE_ENDSTOP_BIT(Z, MIN);
#endif
#endif
// When closing the gap check the enabled probe
#if ENABLED(Z_MIN_PROBE_ENDSTOP)
UPDATE_ENDSTOP_BIT(Z, MIN_PROBE);
#endif
#if HAS_Z_MAX
// Check both Z dual endstops
#if ENABLED(Z_DUAL_ENDSTOPS)
UPDATE_ENDSTOP_BIT(Z, MAX);
#if HAS_Z2_MAX
UPDATE_ENDSTOP_BIT(Z2, MAX);
#else
COPY_LIVE_STATE(Z_MAX, Z2_MAX);
#endif
#elif DISABLED(Z_MIN_PROBE_ENDSTOP) || Z_MAX_PIN != Z_MIN_PROBE_PIN
// If this pin isn't the bed probe it's the Z endstop
UPDATE_ENDSTOP_BIT(Z, MAX);
#endif
#endif
#if ENABLED(ENDSTOP_NOISE_FILTER)
/**
* Filtering out noise on endstops requires a delayed decision. Let's assume, due to noise,
* that 50% of endstop signal samples are good and 50% are bad (assuming normal distribution
* of random noise). Then the first sample has a 50% chance to be good or bad. The 2nd sample
* also has a 50% chance to be good or bad. The chances of 2 samples both being bad becomes
* 50% of 50%, or 25%. That was the previous implementation of Marlin endstop handling. It
* reduces chances of bad readings in half, at the cost of 1 extra sample period, but chances
* still exist. The only way to reduce them further is to increase the number of samples.
* To reduce the chance to 1% (1/128th) requires 7 samples (adding 7ms of delay).
*/
static esbits_t old_live_state;
if (old_live_state != live_state) {
endstop_poll_count = 7;
old_live_state = live_state;
}
else if (endstop_poll_count && !--endstop_poll_count)
validated_live_state = live_state;
if (!abort_enabled()) return;
#endif
// Test the current status of an endstop
#define TEST_ENDSTOP(ENDSTOP) (TEST(state(), ENDSTOP))
// Record endstop was hit
#define _ENDSTOP_HIT(AXIS, MINMAX) SBI(hit_state, _ENDSTOP(AXIS, MINMAX))
// Call the endstop triggered routine for single endstops
#define PROCESS_ENDSTOP(AXIS,MINMAX) do { \
if (TEST_ENDSTOP(_ENDSTOP(AXIS, MINMAX))) { \
_ENDSTOP_HIT(AXIS, MINMAX); \
planner.endstop_triggered(_AXIS(AXIS)); \
} \
}while(0)
// Call the endstop triggered routine for dual endstops
#define PROCESS_DUAL_ENDSTOP(AXIS1, AXIS2, MINMAX) do { \
const byte dual_hit = TEST_ENDSTOP(_ENDSTOP(AXIS1, MINMAX)) | (TEST_ENDSTOP(_ENDSTOP(AXIS2, MINMAX)) << 1); \
if (dual_hit) { \
_ENDSTOP_HIT(AXIS1, MINMAX); \
/* if not performing home or if both endstops were trigged during homing... */ \
if (!stepper.homing_dual_axis || dual_hit == 0b11) \
planner.endstop_triggered(_AXIS(AXIS1)); \
} \
}while(0)
#if ENABLED(G38_PROBE_TARGET) && PIN_EXISTS(Z_MIN_PROBE) && !(CORE_IS_XY || CORE_IS_XZ)
// If G38 command is active check Z_MIN_PROBE for ALL movement
if (G38_move) {
if (TEST_ENDSTOP(_ENDSTOP(Z, MIN_PROBE))) {
if (stepper.axis_is_moving(X_AXIS)) { _ENDSTOP_HIT(X, MIN); planner.endstop_triggered(X_AXIS); }
else if (stepper.axis_is_moving(Y_AXIS)) { _ENDSTOP_HIT(Y, MIN); planner.endstop_triggered(Y_AXIS); }
else if (stepper.axis_is_moving(Z_AXIS)) { _ENDSTOP_HIT(Z, MIN); planner.endstop_triggered(Z_AXIS); }
G38_endstop_hit = true;
}
}
#endif
// Now, we must signal, after validation, if an endstop limit is pressed or not
if (stepper.axis_is_moving(X_AXIS)) {
if (stepper.motor_direction(X_AXIS_HEAD)) { // -direction
#if HAS_X_MIN
#if ENABLED(X_DUAL_ENDSTOPS)
PROCESS_DUAL_ENDSTOP(X, X2, MIN);
#else
if (X_MIN_TEST) PROCESS_ENDSTOP(X, MIN);
#endif
#endif
}
else { // +direction
#if HAS_X_MAX
#if ENABLED(X_DUAL_ENDSTOPS)
PROCESS_DUAL_ENDSTOP(X, X2, MAX);
#else
if (X_MAX_TEST) PROCESS_ENDSTOP(X, MAX);
#endif
#endif
}
}
if (stepper.axis_is_moving(Y_AXIS)) {
if (stepper.motor_direction(Y_AXIS_HEAD)) { // -direction
#if HAS_Y_MIN
#if ENABLED(Y_DUAL_ENDSTOPS)
PROCESS_DUAL_ENDSTOP(Y, Y2, MIN);
#else
PROCESS_ENDSTOP(Y, MIN);
#endif
#endif
}
else { // +direction
#if HAS_Y_MAX
#if ENABLED(Y_DUAL_ENDSTOPS)
PROCESS_DUAL_ENDSTOP(Y, Y2, MAX);
#else
PROCESS_ENDSTOP(Y, MAX);
#endif
#endif
}
}
if (stepper.axis_is_moving(Z_AXIS)) {
if (stepper.motor_direction(Z_AXIS_HEAD)) { // Z -direction. Gantry down, bed up.
#if HAS_Z_MIN
#if ENABLED(Z_DUAL_ENDSTOPS)
PROCESS_DUAL_ENDSTOP(Z, Z2, MIN);
#else
#if ENABLED(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN)
if (z_probe_enabled) PROCESS_ENDSTOP(Z, MIN);
#elif ENABLED(Z_MIN_PROBE_ENDSTOP)
if (!z_probe_enabled) PROCESS_ENDSTOP(Z, MIN);
#else
PROCESS_ENDSTOP(Z, MIN);
#endif
#endif
#endif
// When closing the gap check the enabled probe
#if ENABLED(Z_MIN_PROBE_ENDSTOP)
if (z_probe_enabled) PROCESS_ENDSTOP(Z, MIN_PROBE);
#endif
}
else { // Z +direction. Gantry up, bed down.
#if HAS_Z_MAX
#if ENABLED(Z_DUAL_ENDSTOPS)
PROCESS_DUAL_ENDSTOP(Z, Z2, MAX);
#elif DISABLED(Z_MIN_PROBE_ENDSTOP) || Z_MAX_PIN != Z_MIN_PROBE_PIN
// If this pin is not hijacked for the bed probe
// then it belongs to the Z endstop
PROCESS_ENDSTOP(Z, MAX);
#endif
#endif
}
}
} // Endstops::update()
#if ENABLED(PINS_DEBUGGING)
bool Endstops::monitor_flag = false;
/**
* monitors endstops & Z probe for changes
*
* If a change is detected then the LED is toggled and
* a message is sent out the serial port
*
* Yes, we could miss a rapid back & forth change but
* that won't matter because this is all manual.
*
*/
void Endstops::monitor() {
static uint16_t old_live_state_local = 0;
static uint8_t local_LED_status = 0;
uint16_t live_state_local = 0;
#if HAS_X_MIN
if (READ(X_MIN_PIN)) SBI(live_state_local, X_MIN);
#endif
#if HAS_X_MAX
if (READ(X_MAX_PIN)) SBI(live_state_local, X_MAX);
#endif
#if HAS_Y_MIN
if (READ(Y_MIN_PIN)) SBI(live_state_local, Y_MIN);
#endif
#if HAS_Y_MAX
if (READ(Y_MAX_PIN)) SBI(live_state_local, Y_MAX);
#endif
#if HAS_Z_MIN
if (READ(Z_MIN_PIN)) SBI(live_state_local, Z_MIN);
#endif
#if HAS_Z_MAX
if (READ(Z_MAX_PIN)) SBI(live_state_local, Z_MAX);
#endif
#if HAS_Z_MIN_PROBE_PIN
if (READ(Z_MIN_PROBE_PIN)) SBI(live_state_local, Z_MIN_PROBE);
#endif
#if HAS_X2_MIN
if (READ(X2_MIN_PIN)) SBI(live_state_local, X2_MIN);
#endif
#if HAS_X2_MAX
if (READ(X2_MAX_PIN)) SBI(live_state_local, X2_MAX);
#endif
#if HAS_Y2_MIN
if (READ(Y2_MIN_PIN)) SBI(live_state_local, Y2_MIN);
#endif
#if HAS_Y2_MAX
if (READ(Y2_MAX_PIN)) SBI(live_state_local, Y2_MAX);
#endif
#if HAS_Z2_MIN
if (READ(Z2_MIN_PIN)) SBI(live_state_local, Z2_MIN);
#endif
#if HAS_Z2_MAX
if (READ(Z2_MAX_PIN)) SBI(live_state_local, Z2_MAX);
#endif
uint16_t endstop_change = live_state_local ^ old_live_state_local;
if (endstop_change) {
#if HAS_X_MIN
if (TEST(endstop_change, X_MIN)) SERIAL_PROTOCOLPAIR(" X_MIN:", TEST(live_state_local, X_MIN));
#endif
#if HAS_X_MAX
if (TEST(endstop_change, X_MAX)) SERIAL_PROTOCOLPAIR(" X_MAX:", TEST(live_state_local, X_MAX));
#endif
#if HAS_Y_MIN
if (TEST(endstop_change, Y_MIN)) SERIAL_PROTOCOLPAIR(" Y_MIN:", TEST(live_state_local, Y_MIN));
#endif
#if HAS_Y_MAX
if (TEST(endstop_change, Y_MAX)) SERIAL_PROTOCOLPAIR(" Y_MAX:", TEST(live_state_local, Y_MAX));
#endif
#if HAS_Z_MIN
if (TEST(endstop_change, Z_MIN)) SERIAL_PROTOCOLPAIR(" Z_MIN:", TEST(live_state_local, Z_MIN));
#endif
#if HAS_Z_MAX
if (TEST(endstop_change, Z_MAX)) SERIAL_PROTOCOLPAIR(" Z_MAX:", TEST(live_state_local, Z_MAX));
#endif
#if HAS_Z_MIN_PROBE_PIN
if (TEST(endstop_change, Z_MIN_PROBE)) SERIAL_PROTOCOLPAIR(" PROBE:", TEST(live_state_local, Z_MIN_PROBE));
#endif
#if HAS_X2_MIN
if (TEST(endstop_change, X2_MIN)) SERIAL_PROTOCOLPAIR(" X2_MIN:", TEST(live_state_local, X2_MIN));
#endif
#if HAS_X2_MAX
if (TEST(endstop_change, X2_MAX)) SERIAL_PROTOCOLPAIR(" X2_MAX:", TEST(live_state_local, X2_MAX));
#endif
#if HAS_Y2_MIN
if (TEST(endstop_change, Y2_MIN)) SERIAL_PROTOCOLPAIR(" Y2_MIN:", TEST(live_state_local, Y2_MIN));
#endif
#if HAS_Y2_MAX
if (TEST(endstop_change, Y2_MAX)) SERIAL_PROTOCOLPAIR(" Y2_MAX:", TEST(live_state_local, Y2_MAX));
#endif
#if HAS_Z2_MIN
if (TEST(endstop_change, Z2_MIN)) SERIAL_PROTOCOLPAIR(" Z2_MIN:", TEST(live_state_local, Z2_MIN));
#endif
#if HAS_Z2_MAX
if (TEST(endstop_change, Z2_MAX)) SERIAL_PROTOCOLPAIR(" Z2_MAX:", TEST(live_state_local, Z2_MAX));
#endif
SERIAL_PROTOCOLPGM("\n\n");
analogWrite(LED_PIN, local_LED_status);
local_LED_status ^= 255;
old_live_state_local = live_state_local;
}
}
#endif // PINS_DEBUGGING

174
Marlin/endstops.h Normal file
View File

@ -0,0 +1,174 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/**
* endstops.h - manages endstops
*/
#ifndef __ENDSTOPS_H__
#define __ENDSTOPS_H__
#include "MarlinConfig.h"
#define VALIDATE_HOMING_ENDSTOPS
enum EndstopEnum : char {
X_MIN,
Y_MIN,
Z_MIN,
Z_MIN_PROBE,
X_MAX,
Y_MAX,
Z_MAX,
X2_MIN,
X2_MAX,
Y2_MIN,
Y2_MAX,
Z2_MIN,
Z2_MAX
};
class Endstops {
public:
static bool enabled, enabled_globally;
#if ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS)
typedef uint16_t esbits_t;
#if ENABLED(X_DUAL_ENDSTOPS)
static float x_endstop_adj;
#endif
#if ENABLED(Y_DUAL_ENDSTOPS)
static float y_endstop_adj;
#endif
#if ENABLED(Z_DUAL_ENDSTOPS)
static float z_endstop_adj;
#endif
#else
typedef uint8_t esbits_t;
#endif
private:
static esbits_t live_state;
static volatile uint8_t hit_state; // Use X_MIN, Y_MIN, Z_MIN and Z_MIN_PROBE as BIT index
#if ENABLED(ENDSTOP_NOISE_FILTER)
static esbits_t validated_live_state;
static uint8_t endstop_poll_count; // Countdown from threshold for polling
#endif
public:
Endstops() {};
/**
* Initialize the endstop pins
*/
static void init();
/**
* Are endstops or the probe set to abort the move?
*/
FORCE_INLINE static bool abort_enabled() {
return (enabled
#if HAS_BED_PROBE
|| z_probe_enabled
#endif
);
}
/**
* Periodic call to poll endstops if required. Called from temperature ISR
*/
static void poll();
/**
* Update endstops bits from the pins. Apply filtering to get a verified state.
* If abort_enabled() and moving towards a triggered switch, abort the current move.
* Called from ISR contexts.
*/
static void update();
/**
* Get Endstop hit state.
*/
FORCE_INLINE static uint8_t trigger_state() { return hit_state; }
/**
* Get current endstops state
*/
FORCE_INLINE static esbits_t state() {
return
#if ENABLED(ENDSTOP_NOISE_FILTER)
validated_live_state
#else
live_state
#endif
;
}
/**
* Report endstop hits to serial. Called from loop().
*/
static void event_handler();
/**
* Report endstop positions in response to M119
*/
static void M119();
// Enable / disable endstop checking globally
static void enable_globally(const bool onoff=true);
// Enable / disable endstop checking
static void enable(const bool onoff=true);
// Disable / Enable endstops based on ENSTOPS_ONLY_FOR_HOMING and global enable
static void not_homing();
#if ENABLED(VALIDATE_HOMING_ENDSTOPS)
// If the last move failed to trigger an endstop, call kill
static void validate_homing_move();
#else
FORCE_INLINE static void validate_homing_move() { hit_on_purpose(); }
#endif
// Clear endstops (i.e., they were hit intentionally) to suppress the report
FORCE_INLINE static void hit_on_purpose() { hit_state = 0; }
// Enable / disable endstop z-probe checking
#if HAS_BED_PROBE
static volatile bool z_probe_enabled;
static void enable_z_probe(const bool onoff=true);
#endif
// Debugging of endstops
#if ENABLED(PINS_DEBUGGING)
static bool monitor_flag;
static void monitor();
static void run_monitor();
#endif
};
extern Endstops endstops;
#endif // __ENDSTOPS_H__

175
Marlin/enum.h Normal file
View File

@ -0,0 +1,175 @@
/**
* Marlin 3D Printer Firmware
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* Based on Sprinter and grbl.
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef __ENUM_H__
#define __ENUM_H__
#include "MarlinConfig.h"
/**
* Axis indices as enumerated constants
*
* - X_AXIS, Y_AXIS, and Z_AXIS should be used for axes in Cartesian space
* - A_AXIS, B_AXIS, and C_AXIS should be used for Steppers, corresponding to XYZ on Cartesians
* - X_HEAD, Y_HEAD, and Z_HEAD should be used for Steppers on Core kinematics
*/
enum AxisEnum : unsigned char {
X_AXIS = 0,
A_AXIS = 0,
Y_AXIS = 1,
B_AXIS = 1,
Z_AXIS = 2,
C_AXIS = 2,
E_CART = 3,
#if ENABLED(HANGPRINTER) // Hangprinter order: A_AXIS, B_AXIS, C_AXIS, D_AXIS, E_AXIS
D_AXIS = 3,
E_AXIS = 4,
#else
E_AXIS = 3,
#endif
X_HEAD, Y_HEAD, Z_HEAD,
ALL_AXES = 0xFE,
NO_AXIS = 0xFF
};
#define LOOP_S_LE_N(VAR, S, N) for (uint8_t VAR=S; VAR<=N; VAR++)
#define LOOP_S_L_N(VAR, S, N) for (uint8_t VAR=S; VAR<N; VAR++)
#define LOOP_LE_N(VAR, N) LOOP_S_LE_N(VAR, 0, N)
#define LOOP_L_N(VAR, N) LOOP_S_L_N(VAR, 0, N)
#define LOOP_NA(VAR) LOOP_L_N(VAR, NUM_AXIS)
#define LOOP_XYZ(VAR) LOOP_S_LE_N(VAR, X_AXIS, Z_AXIS)
#define LOOP_XYZE(VAR) LOOP_S_LE_N(VAR, X_AXIS, E_CART)
#define LOOP_XYZE_N(VAR) LOOP_S_L_N(VAR, X_AXIS, XYZE_N)
#define LOOP_MOV_AXIS(VAR) LOOP_S_L_N(VAR, A_AXIS, MOV_AXIS)
#define LOOP_NUM_AXIS(VAR) LOOP_S_L_N(VAR, A_AXIS, NUM_AXIS)
#define LOOP_NUM_AXIS_N(VAR) LOOP_S_L_N(VAR, A_AXIS, NUM_AXIS_N)
typedef enum {
LINEARUNIT_MM,
LINEARUNIT_INCH
} LinearUnit;
typedef enum {
TEMPUNIT_C,
TEMPUNIT_K,
TEMPUNIT_F
} TempUnit;
/**
* Debug flags
* Not yet widely applied
*/
enum DebugFlags : unsigned char {
DEBUG_NONE = 0,
DEBUG_ECHO = _BV(0), ///< Echo commands in order as they are processed
DEBUG_INFO = _BV(1), ///< Print messages for code that has debug output
DEBUG_ERRORS = _BV(2), ///< Not implemented
DEBUG_DRYRUN = _BV(3), ///< Ignore temperature setting and E movement commands
DEBUG_COMMUNICATION = _BV(4), ///< Not implemented
DEBUG_LEVELING = _BV(5), ///< Print detailed output for homing and leveling
DEBUG_MESH_ADJUST = _BV(6), ///< UBL bed leveling
DEBUG_ALL = 0xFF
};
#if ENABLED(ADVANCED_PAUSE_FEATURE)
enum AdvancedPauseMenuResponse : char {
ADVANCED_PAUSE_RESPONSE_WAIT_FOR,
ADVANCED_PAUSE_RESPONSE_EXTRUDE_MORE,
ADVANCED_PAUSE_RESPONSE_RESUME_PRINT
};
#if ENABLED(ULTIPANEL)
enum AdvancedPauseMessage : char {
ADVANCED_PAUSE_MESSAGE_INIT,
ADVANCED_PAUSE_MESSAGE_UNLOAD,
ADVANCED_PAUSE_MESSAGE_INSERT,
ADVANCED_PAUSE_MESSAGE_LOAD,
ADVANCED_PAUSE_MESSAGE_PURGE,
#if ENABLED(ADVANCED_PAUSE_CONTINUOUS_PURGE)
ADVANCED_PAUSE_MESSAGE_CONTINUOUS_PURGE,
#endif
ADVANCED_PAUSE_MESSAGE_OPTION,
ADVANCED_PAUSE_MESSAGE_RESUME,
ADVANCED_PAUSE_MESSAGE_STATUS,
ADVANCED_PAUSE_MESSAGE_CLICK_TO_HEAT_NOZZLE,
ADVANCED_PAUSE_MESSAGE_WAIT_FOR_NOZZLES_TO_HEAT
};
#endif
enum AdvancedPauseMode : char {
ADVANCED_PAUSE_MODE_PAUSE_PRINT,
ADVANCED_PAUSE_MODE_LOAD_FILAMENT,
ADVANCED_PAUSE_MODE_UNLOAD_FILAMENT
};
#endif
/**
* States for managing Marlin and host communication
* Marlin sends messages if blocked or busy
*/
#if ENABLED(HOST_KEEPALIVE_FEATURE)
enum MarlinBusyState : char {
NOT_BUSY, // Not in a handler
IN_HANDLER, // Processing a GCode
IN_PROCESS, // Known to be blocking command input (as in G29)
PAUSED_FOR_USER, // Blocking pending any input
PAUSED_FOR_INPUT // Blocking pending text input (concept)
};
#endif
/**
* SD Card
*/
enum LsAction : char { LS_SerialPrint, LS_Count, LS_GetFilename };
/**
* Ultra LCD
*/
enum LCDViewAction : char {
LCDVIEW_NONE,
LCDVIEW_REDRAW_NOW,
LCDVIEW_CALL_REDRAW_NEXT,
LCDVIEW_CLEAR_CALL_REDRAW,
LCDVIEW_CALL_NO_REDRAW
};
/**
* Dual X Carriage modes. A Dual Nozzle can also do duplication.
*/
#if ENABLED(DUAL_X_CARRIAGE) || ENABLED(DUAL_NOZZLE_DUPLICATION_MODE)
enum DualXMode : char {
DXC_FULL_CONTROL_MODE, // DUAL_X_CARRIAGE only
DXC_AUTO_PARK_MODE, // DUAL_X_CARRIAGE only
DXC_DUPLICATION_MODE
};
#endif
/**
* Workspace planes only apply to G2/G3 moves
* (and "canned cycles" - not a current feature)
*/
#if ENABLED(CNC_WORKSPACE_PLANES)
enum WorkspacePlane : char { PLANE_XY, PLANE_ZX, PLANE_YZ };
#endif
#endif // __ENUM_H__

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

View File

@ -0,0 +1,15 @@
This is an example configuration for the CL-260 Ultimaker 2 clone.
Change Z_MAX_POS to 300 for the CL-260MAX.
(The printer is available on AliExpress; be aware that this is not a beginner's
printer -- it needs tweaking and some parts replaced before being decent.)
The printer comes with a quite old Marlin, the sources are available here:
http://www.thingiverse.com/thing:1635830/ and I recommend replacing them.
The setting "works" for my printer and the extruder using my calibration value.
You might want to tweak some settings, e.g enable EEPROM, increase default Z speed, adjust homing speeds,...
Have fun!
--
tobi

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

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

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

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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,29 @@
# Example Configuration for BQ [Hephestos 2](http://www.bq.com/uk/hephestos-2)
Based on the original configuration file shipped with the heavily modified Marlin fork by BQ.
The forked firmware and configuration files can be found at the [BQ Github repository](https://github.com/bq/Marlin).
NOTE: The look and feel of the LCD menu will change dramatically when using the original Marlin firmware.
## Changelog
* 2018/05/30 - Configuration updated to the latest Marlin version (43a55a9af).
ABL Bilinear 5x5 is active by default.
* 2017/07/06 - Configuration updated to the latest Marlin version and added support for the
official BQ heated bed upgrade kit.
* 2016/12/13 - Configuration updated to the latest Marlin version.
* 2016/07/13 - Configuration updated to the latest Marlin version.
* 2016/06/21 - Disabled heated bed related options, activated software endstops and SD printing now
disables the heater when finishes printing.
* 2016/03/21 - Activated 4-point auto leveling by default and updated miscellaneous z-probe values.
* 2016/03/01 - The first release of Marlin's configuration file for the
BQ Hephestos 2 3D printer.
## Support
This configuration should work easily with the stock Hephestos 2, nevertheless if you encounter any
issues you may contact me on [Github](https://github.com/jbrazio), [Twitter](https://twitter.com/jbrazio) or by mail.

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