Compare commits
2 Commits
MK3
...
MK3_3.11.1
| Author | SHA1 | Date |
|---|---|---|
|
|
700d241e8e | |
|
|
9ac1523126 |
|
|
@ -1,21 +0,0 @@
|
|||
# If a statement is wrapped to more than one line, than dangle the closing
|
||||
# parenthesis on it's own line.
|
||||
dangle_parens = True
|
||||
dangle_align = 'child'
|
||||
|
||||
# If true, the parsers may infer whether or not an argument list is sortable
|
||||
# (without annotation).
|
||||
autosort = True
|
||||
|
||||
# How wide to allow formatted cmake files
|
||||
line_width = 100
|
||||
|
||||
additional_commands = {
|
||||
"target_sources": {
|
||||
"kwargs": {
|
||||
"PUBLIC": "*",
|
||||
"PRIVATE": "*",
|
||||
"INTERFACE": "*",
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
@ -1,2 +1 @@
|
|||
lang/po/*.po text eol=crlf diff=po
|
||||
lang/po/*.pot text diff=po
|
||||
lang/po/*.po text eol=crlf
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: "[BUG]<Enter comprehensive title>"
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
<!--
|
||||
Please, before you create a new bug report, please make sure you searched in open and closed issues and couldn't find anything that matches.
|
||||
-->
|
||||
**Printer type** - [e.g. MK3S, MK3, MK2.5S, MK2.5, MK2S, MK2]
|
||||
**Printer firmware version** - [e.g. 3.8.1, 3.8.1-RC1, ...]
|
||||
|
||||
**MMU upgrade** - [e.g. MMU2S, MMU2, MMU1]
|
||||
**MMU upgrade firmware version** - [e.g. 1.0.6, 1.0.6-RC2, ...]
|
||||
|
||||
**SD card or USB/Octoprint**
|
||||
Please let us know if you print via SD card or USB/Octoprint
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Please describe steps to reproduce the behavior.
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**G-code**
|
||||
Please attach a G-code. This will make it easier for us to replicate the error.
|
||||
|
||||
**Video**
|
||||
Please attach a video. It usually helps to solve the problem.
|
||||
|
|
@ -1,96 +0,0 @@
|
|||
name: Bug report
|
||||
description: File a bug report
|
||||
title: '[BUG] '
|
||||
labels:
|
||||
- bug
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Before you create a new bug report, please check if an issue with it already exists (either open or closed) by using the search bar on the issues page. If it does, comment there. Even if it's closed, we can reopen it based on your comment.
|
||||
- type: dropdown
|
||||
id: printer_model
|
||||
attributes:
|
||||
label: Printer model
|
||||
description: Enter the printer model(s) where you encountered the issue
|
||||
options:
|
||||
- MK3S/+
|
||||
- MK3
|
||||
- MK2.5S
|
||||
- MK2.5
|
||||
validations:
|
||||
required: true
|
||||
- type: dropdown
|
||||
id: mmu_model
|
||||
attributes:
|
||||
label: MMU model
|
||||
description: Enter the MMU model(s) where you encountered the issue
|
||||
multiple: false
|
||||
options:
|
||||
- No-MMU
|
||||
- MMU3
|
||||
- MMU2S
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: firmware_version
|
||||
attributes:
|
||||
label: Firmware versions
|
||||
description: |
|
||||
If you're using a custom firmware (not downloaded from Prusa), please note that!
|
||||
placeholder: '3.14.0, 3.12.0-RC1, 3.14.0 and 3.0.2...'
|
||||
validations:
|
||||
required: true
|
||||
- type: input
|
||||
id: optional_upgrades
|
||||
attributes:
|
||||
label: Upgrades and modifications
|
||||
description: 'If your printer has upgrades or was modified, please note that! If not, please write None or leave blank.'
|
||||
placeholder: |
|
||||
None, custom extruder/hotend (which), different frame, ...
|
||||
- type: dropdown
|
||||
id: printing_from
|
||||
attributes:
|
||||
label: Printing from...
|
||||
multiple: false
|
||||
options:
|
||||
- SD Card
|
||||
- PrusaLink
|
||||
- PrusaConnect
|
||||
- OctoPrint
|
||||
- Other host software
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Describe the bug
|
||||
description: Write a concise description of the bug.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: reproduction
|
||||
attributes:
|
||||
label: How to reproduce
|
||||
description: |
|
||||
If you are able to reproduce the issue - meaning that you can trigger it yourself by following certain steps - please describe the step-by-step process in as much detail as possible!
|
||||
- type: textarea
|
||||
id: expected_behavior
|
||||
attributes:
|
||||
label: Expected behavior
|
||||
description: |
|
||||
If the printer did something unexpected, or if the procedure is missing a step that would resolve the issue, please provide a step-by-step process of how it should behave.
|
||||
- type: textarea
|
||||
id: files
|
||||
attributes:
|
||||
label: Files
|
||||
description: |
|
||||
Provide at least one of these (ideally as many as you can) to help developers track down the bug.
|
||||
*To upload files, compress them into a .zip file and drag them to the text area to upload.* Images and videos can be uploaded directly.
|
||||
|
||||
- **gcode** file
|
||||
- **3mf project** which includes the model and printer settings
|
||||
- **video** or **photos** of the issue happening
|
||||
|
||||
**Crash dump: Do not share the file publicly**, as the crash dump contains a raw snapshot of the printer's memory and may include unencrypted sensitive information.
|
||||
Please send the crash dump file to Prusa by emailing it to reports@prusa3d.com and referencing this issue. In reply to the email, you will be automatically assigned a reference code to be mentioned in the issue. Sharing this file is important and helps us investigate the bug.
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
name: Community
|
||||
description: Related to "Community made" features
|
||||
title: '[Community made] '
|
||||
labels:
|
||||
- community_made
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: >
|
||||
Prusa Research will NOT follow up these issues!
|
||||
The maintainers of the "Community made" feature should/will react.
|
||||
|
||||
Please, before you create a new "Community made" ticket, please make sure you searched in open and closed issues and couldn't find anything that matches.
|
||||
- type: textarea
|
||||
id: which_community
|
||||
attributes:
|
||||
label: Which Community made feature do you want to address?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: What_about_community
|
||||
attributes:
|
||||
label: What is your request/question/suggestion?
|
||||
validations:
|
||||
required: true
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
contact_links:
|
||||
- name: Do you need Support?
|
||||
url: https://help.prusa3d.com/article/customer-support_2287
|
||||
about: If you are not sure whether what you are reporting is a bug, please contact our support team first. We are providing full 24/7 customer support.
|
||||
- name: Knowledge Base
|
||||
url: https://help.prusa3d.com/
|
||||
about: We have a comprehensive help documentation that could be helpful for troubleshooting.
|
||||
- name: Prusa Forum
|
||||
url: https://forum.prusa3d.com/
|
||||
about: Please get in touch on our Prusa Forum! (Not an official support channel)
|
||||
blank_issues_enabled: false
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
name: Enhancement
|
||||
about: Suggest an idea for this project
|
||||
title: " [ENHANCEMENT]<Enter comprehensive title>"
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
Please, before you create a new feature request, please make sure you searched in open and closed issues and couldn't find anything that matches.
|
||||
|
||||
Enter what type of printer or upgrade the enhancement applies to.
|
||||
**Printer type** - [e.g. MK3S, MK3, MK2.5S, MK2.5, MK2S, MK2]
|
||||
**MMU Upgrade** - [e.g. MMU2S, MMU2, MMU1]
|
||||
|
||||
**Is your enhancement related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
name: Enhancement
|
||||
description: Suggest an improvement of the existing functionality
|
||||
title: '[ENHANCEMENT] '
|
||||
labels:
|
||||
- enhancement
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Before you create a new enhancement, please check if an issue with it already exists (either open or closed) by using the search bar on the issues page.
|
||||
- type: checkboxes
|
||||
id: printer_model
|
||||
attributes:
|
||||
label: Printer model
|
||||
description: Select the printer model(s) where you would like this enhancement
|
||||
options:
|
||||
- label: MK3S/+
|
||||
- label: MK3
|
||||
- label: MK2.5S
|
||||
- label: MK2.5
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Describe the enhancement
|
||||
description: How would this enhancement improve your experience? Do you have a specific use case where this enhancemnet is especially needed?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: expected_functionality
|
||||
attributes:
|
||||
label: Expected functionality
|
||||
description: |
|
||||
Describe the way the enhancement would change existing functionality. You can also describe it in a step-by-step basis if applicable.
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: "[FEATURE REQUEST]<Enter comprehensive title>"
|
||||
labels: feature request
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
Please, before you create a new feature request, please make sure you searched in open and closed issues and couldn't find anything that matches.
|
||||
|
||||
If it makes sense, enter what type of printer or upgrade the feature request applies to.
|
||||
**Printer type** - [e.g. MK3S, MK3, MK2.5S, MK2.5, MK2S, MK2]
|
||||
**MMU Upgrade** - [e.g. MMU2S, MMU2, MMU1]
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
|
@ -1,35 +0,0 @@
|
|||
name: Feature request
|
||||
description: Suggest new functionality
|
||||
title: '[FEATURE REQUEST] '
|
||||
labels:
|
||||
- feature request
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Before you create a new feature request, please check if an issue with it already exists (either open or closed) by using the search bar on the issues page.
|
||||
- type: checkboxes
|
||||
id: printer_model
|
||||
attributes:
|
||||
label: Printer model
|
||||
description: Select the printer model(s) where you would like this feature
|
||||
options:
|
||||
- label: MK3S/+
|
||||
- label: MK3
|
||||
- label: MK2.5S
|
||||
- label: MK2.5
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: description
|
||||
attributes:
|
||||
label: Describe the feature
|
||||
description: How would this feature improve the printer? Are there specific use cases where this would be beneficial? Describe how you would use it.
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
id: expected_functionality
|
||||
attributes:
|
||||
label: Expected functionality
|
||||
description: |
|
||||
Describe the way the feature would work. You can also describe it in a step-by-step basis if applicable.
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
---
|
||||
name: Question
|
||||
about: What do you want to know?
|
||||
title: "[QUESTION]<Enter comprehensive title>"
|
||||
labels: question
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
Please, before you create a new question, please make sure you searched in open and closed issues and couldn't find anything that matches.
|
||||
|
||||
**What is your question?**
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
name: Question
|
||||
description: Ask a firmware specific question
|
||||
title: '[QUESTION] '
|
||||
labels:
|
||||
- question
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
Before you create a new question, please check if an issue with it already exists (either open or closed) by using the search bar on the issues page.
|
||||
- type: textarea
|
||||
id: question
|
||||
attributes:
|
||||
label: Question
|
||||
validations:
|
||||
required: true
|
||||
|
|
@ -1,178 +0,0 @@
|
|||
name: ci-build
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- '*'
|
||||
push:
|
||||
branches: [ MK3, MK3_* ]
|
||||
tags:
|
||||
- 'v*'
|
||||
- 't*'
|
||||
- 'c*'
|
||||
|
||||
env:
|
||||
GH_ANNOTATIONS: 1
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
# setup base required dependencies
|
||||
- name: Setup dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install cmake ninja-build python3-pyelftools python3-regex python3-polib
|
||||
|
||||
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
|
||||
- name: Checkout ${{ github.event.pull_request.head.ref }}
|
||||
uses: actions/checkout@v4
|
||||
if: ${{ github.event.pull_request }}
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
submodules: true
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Checkout ${{ github.event.ref }}
|
||||
uses: actions/checkout@v4
|
||||
if: ${{ !github.event.pull_request }}
|
||||
with:
|
||||
ref: ${{ github.event.ref }}
|
||||
submodules: true
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cache Dependencies
|
||||
uses: actions/cache@v4
|
||||
id: cache-pkgs
|
||||
with:
|
||||
path: ".dependencies"
|
||||
key: "build-deps-1_0_0-linux"
|
||||
|
||||
- name: Setup build dependencies
|
||||
run: |
|
||||
./utils/bootstrap.py
|
||||
|
||||
- name: Cache permissions
|
||||
run: sudo chmod -R 744 .dependencies
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -DCMAKE_TOOLCHAIN_FILE="../cmake/AvrGcc.cmake" -DCMAKE_BUILD_TYPE=Release -G Ninja
|
||||
ninja
|
||||
|
||||
- name: Upload artifacts
|
||||
if: ${{ !github.event.pull_request }}
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Firmware
|
||||
path: build/*.hex
|
||||
|
||||
- name: RELEASE THE KRAKEN
|
||||
if: startsWith(github.ref, 'refs/tags/v') || startsWith(github.ref, 'refs/tags/t') || startsWith(github.ref, 'refs/tags/c')
|
||||
uses: "marvinpinto/action-automatic-releases@latest"
|
||||
with:
|
||||
repo_token: "${{ secrets.GITHUB_TOKEN }}"
|
||||
automatic_release_tag: ${{ github.ref_name }}
|
||||
draft: true
|
||||
files: |
|
||||
${{ github.workspace }}/build/release/*.hex
|
||||
${{ github.workspace }}/build/release/*.zip
|
||||
|
||||
check-lang:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
# setup base required dependencies
|
||||
- name: Setup dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install gcc-11 g++11 lcov cmake ninja-build python3-pyelftools python3-regex python3-polib
|
||||
|
||||
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
|
||||
- name: Checkout ${{ github.event.pull_request.head.ref }}
|
||||
uses: actions/checkout@v4
|
||||
if: ${{ github.event.pull_request }}
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
submodules: true
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Checkout ${{ github.event.ref }}
|
||||
uses: actions/checkout@v4
|
||||
if: ${{ !github.event.pull_request }}
|
||||
with:
|
||||
ref: ${{ github.event.ref }}
|
||||
submodules: true
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cache Dependencies
|
||||
uses: actions/cache@v4
|
||||
id: cache-pkgs
|
||||
with:
|
||||
path: ".dependencies"
|
||||
key: "build-deps-1_0_0-linux"
|
||||
|
||||
- name: Setup build dependencies
|
||||
run: |
|
||||
./utils/bootstrap.py
|
||||
|
||||
- name: Cache permissions
|
||||
run: sudo chmod -R 744 .dependencies
|
||||
|
||||
- name: Run check
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -G Ninja -DCMAKE_TOOLCHAIN_FILE="../cmake/AvrGcc.cmake" -DCMAKE_BUILD_TYPE=Release -G Ninja
|
||||
ninja check_lang
|
||||
|
||||
tests:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
# setup base required dependencies
|
||||
- name: Setup dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install gcc-11 g++11 lcov cmake ninja-build python3-pyelftools python3-regex python3-polib
|
||||
|
||||
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
|
||||
- name: Checkout ${{ github.event.pull_request.head.ref }}
|
||||
uses: actions/checkout@v4
|
||||
if: ${{ github.event.pull_request }}
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
submodules: true
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Checkout ${{ github.event.ref }}
|
||||
uses: actions/checkout@v4
|
||||
if: ${{ !github.event.pull_request }}
|
||||
with:
|
||||
ref: ${{ github.event.ref }}
|
||||
submodules: true
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Cache Dependencies
|
||||
uses: actions/cache@v4
|
||||
id: cache-pkgs
|
||||
with:
|
||||
path: ".dependencies"
|
||||
key: "build-deps-1_0_0-linux"
|
||||
|
||||
- name: Setup build dependencies
|
||||
run: |
|
||||
./utils/bootstrap.py
|
||||
|
||||
- name: Cache permissions
|
||||
run: sudo chmod -R 744 .dependencies
|
||||
|
||||
- name: Run check
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -G Ninja
|
||||
ninja test_run_all
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
#!/bin/sh
|
||||
MESSAGE=$1
|
||||
BASE_DIR=$2
|
||||
PR_DIR=$3
|
||||
shift 3
|
||||
|
||||
# this assumes we're running from the repository root
|
||||
AVR_SIZE=$(echo .dependencies/avr-gcc-*/bin/avr-size)
|
||||
test -x "$AVR_SIZE" || exit 2
|
||||
|
||||
avr_size()
|
||||
{
|
||||
"$AVR_SIZE" --mcu=atmega2560 -C "$@"
|
||||
}
|
||||
|
||||
avr_flash()
|
||||
{
|
||||
avr_size "$@" | sed -ne 's/^Program: *\([0-9]\+\).*/\1/p'
|
||||
}
|
||||
|
||||
avr_ram()
|
||||
{
|
||||
avr_size "$@" | sed -ne 's/^Data: *\([0-9]\+\).*/\1/p'
|
||||
}
|
||||
|
||||
cat <<EOF > "$MESSAGE"
|
||||
All values in bytes. Δ Delta to base
|
||||
|
||||
| Target| ΔFlash | ΔSRAM | Used Flash | Used SRAM | Free Flash | Free SRAM |
|
||||
| ------| ------ | ----- | -----------| --------- | ---------- | --------- |
|
||||
EOF
|
||||
|
||||
einsy_max_upload_size=$(grep "prusa_einsy_rambo.upload.maximum_size" .dependencies/prusa3dboards-*/boards.txt | cut -d "=" -f2)
|
||||
einsy_max_upload_data_size=8192
|
||||
|
||||
for TARGET in $@
|
||||
do
|
||||
# strip the multilang prefix
|
||||
variant=${TARGET%_MULTILANG}
|
||||
|
||||
base_bin=$(echo ${BASE_DIR}/build_gen/$variant/${variant}_lang_base)
|
||||
base_flash=$(avr_flash "$base_bin")
|
||||
base_ram=$(avr_ram "$base_bin")
|
||||
|
||||
pr_bin=$(echo ${PR_DIR}/build_gen/$variant/${variant}_lang_base)
|
||||
pr_flash=$(avr_flash "$pr_bin")
|
||||
pr_ram=$(avr_ram "$pr_bin")
|
||||
|
||||
flash_d=$(($pr_flash - $base_flash))
|
||||
ram_d=$(($pr_ram - $base_ram))
|
||||
|
||||
flash_free=$(($einsy_max_upload_size - $pr_flash))
|
||||
ram_free=$(($einsy_max_upload_data_size - $pr_ram))
|
||||
|
||||
echo "| \`$TARGET\` | $flash_d | $ram_d | $pr_flash | $pr_ram | $flash_free | $ram_free |" >> "$MESSAGE"
|
||||
done
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
name: pr-size
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
branches: [ MK3, MK3_* ]
|
||||
|
||||
env:
|
||||
TARGETS: "MK3S_MULTILANG MK3_MULTILANG"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
|
||||
# setup base required dependencies
|
||||
- name: Setup dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install cmake ninja-build python3-pyelftools python3-regex python3-polib
|
||||
|
||||
# build the base branch
|
||||
- name: Checkout base
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Cache Dependencies
|
||||
uses: actions/cache@v4
|
||||
id: cache-pkgs
|
||||
with:
|
||||
path: ".dependencies"
|
||||
key: "build-deps-1_0_0-linux"
|
||||
|
||||
- name: Setup build dependencies
|
||||
run: |
|
||||
./utils/bootstrap.py
|
||||
|
||||
- name: Cache permissions
|
||||
run: sudo chmod -R 744 .dependencies
|
||||
|
||||
- name: Build base
|
||||
run: |
|
||||
rm -rf build-base
|
||||
mkdir build-base
|
||||
cd build-base
|
||||
cmake .. -DCMAKE_TOOLCHAIN_FILE="../cmake/AvrGcc.cmake" -DCMAKE_BUILD_TYPE=Release -G Ninja
|
||||
ninja $TARGETS
|
||||
|
||||
# save pr-size for later use
|
||||
- name: Save base data
|
||||
run: |
|
||||
cp -f ./.github/workflows/pr-size.sh build-base
|
||||
|
||||
# build the PR branch
|
||||
- name: Checkout PR
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
clean: false
|
||||
ref: ${{ github.event.pull_request.head.sha }}
|
||||
|
||||
- name: Build PR
|
||||
run: |
|
||||
rm -rf build-pr
|
||||
mkdir build-pr
|
||||
cd build-pr
|
||||
cmake .. -DCMAKE_TOOLCHAIN_FILE="../cmake/AvrGcc.cmake" -DCMAKE_BUILD_TYPE=Release -G Ninja
|
||||
ninja $TARGETS
|
||||
|
||||
# extract/show build differences
|
||||
- name: Calculate binary changes
|
||||
run: |
|
||||
rm -rf build-changes
|
||||
./build-base/pr-size.sh build-changes build-base build-pr $TARGETS
|
||||
|
||||
- name: Add PR Comment
|
||||
uses: mshick/add-pr-comment@v2
|
||||
with:
|
||||
message-path: build-changes
|
||||
|
|
@ -1,30 +0,0 @@
|
|||
name: Mark stale issues
|
||||
|
||||
on:
|
||||
schedule:
|
||||
# 1:30 AM on MON/THU
|
||||
- cron: "30 1 * * 1,2,3,4"
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/stale@v9
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
# Don't ever mark PRs as stale.
|
||||
days-before-pr-stale: -1
|
||||
stale-issue-message: 'Thank you for your contribution to our project. This issue has not received any updates for 60 days and may be considered "stale." If this issue is still important to you, please add an update within the next 7 days to keep it open. Administrators can manually reopen the issue if necessary.'
|
||||
close-issue-message: 'This issue has been closed due to lack of recent activity. Please consider opening a new one if needed.'
|
||||
# Don't act on things assigned to a milestone or assigned to someone.
|
||||
exempt-all-milestones: true
|
||||
exempt-all-assignees: true
|
||||
enable-statistics: true
|
||||
# Disable this and change the operations per run back to 30 when this goes live.
|
||||
debug-only: false
|
||||
operations-per-run: 200
|
||||
stale-issue-label: 'stale-issue'
|
||||
stale-pr-label: 'stale-pr'
|
||||
ascending: true
|
||||
|
|
@ -1,14 +1,3 @@
|
|||
# IDE data
|
||||
/.settings
|
||||
/.project
|
||||
/.cproject
|
||||
|
||||
# cmake
|
||||
/build/
|
||||
/build_gen/
|
||||
/.dependencies
|
||||
/compile_commands.json
|
||||
|
||||
# Temporary configuration
|
||||
/Firmware/Configuration_prusa.h
|
||||
|
||||
|
|
@ -17,7 +6,6 @@
|
|||
/lang/tmp/
|
||||
/lang/Firmware-intl.hex
|
||||
/lang/Firmware-intl-en_*.hex
|
||||
/lang/*.map
|
||||
|
||||
# Temporary files and directories
|
||||
*[~#]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
dist: focal
|
||||
before_install:
|
||||
- sudo apt-get install -y ninja-build python3-polib python3-pyelftools
|
||||
# Arduino IDE adds a lot of noise caused by network traffic, trying to firewall it off
|
||||
- sudo iptables -P INPUT DROP
|
||||
- sudo iptables -P FORWARD DROP
|
||||
- sudo iptables -P OUTPUT ACCEPT
|
||||
- sudo iptables -A INPUT -i lo -j ACCEPT
|
||||
- sudo iptables -A OUTPUT -o lo -j ACCEPT
|
||||
- sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
|
||||
script:
|
||||
- bash -x test.sh
|
||||
- cp Firmware/variants/1_75mm_MK3S-EINSy10a-E3Dv6full.h Firmware/Configuration_prusa.h
|
||||
- bash -x build.sh || { echo "1_75mm_MK3S-EINSy10a-E3Dv6full variant failed" && false; }
|
||||
- rm Firmware/Configuration_prusa.h
|
||||
- cp Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h Firmware/Configuration_prusa.h
|
||||
- bash -x build.sh || { echo "1_75mm_MK3-EINSy10a-E3Dv6full variant failed" && false; }
|
||||
- rm Firmware/Configuration_prusa.h
|
||||
- cp Firmware/variants/1_75mm_MK25S-RAMBo13a-E3Dv6full.h Firmware/Configuration_prusa.h
|
||||
- bash -x build.sh || { echo "1_75mm_MK25S-RAMBo13a-E3Dv6full variant failed" && false; }
|
||||
- rm Firmware/Configuration_prusa.h
|
||||
- cp Firmware/variants/1_75mm_MK25S-RAMBo10a-E3Dv6full.h Firmware/Configuration_prusa.h
|
||||
- bash -x build.sh || { echo "1_75mm_MK25S-RAMBo10a-E3Dv6full variant failed" && false; }
|
||||
- rm Firmware/Configuration_prusa.h
|
||||
- cp Firmware/variants/1_75mm_MK25-RAMBo13a-E3Dv6full.h Firmware/Configuration_prusa.h
|
||||
- bash -x build.sh || { echo "1_75mm_MK25-RAMBo13a-E3Dv6full variant failed" && false; }
|
||||
- rm Firmware/Configuration_prusa.h
|
||||
- cp Firmware/variants/1_75mm_MK25-RAMBo10a-E3Dv6full.h Firmware/Configuration_prusa.h
|
||||
- bash -x build.sh || { echo "1_75mm_MK25-RAMBo10a-E3Dv6full variant failed" && false; }
|
||||
- rm Firmware/Configuration_prusa.h
|
||||
- cp Firmware/variants/1_75mm_MK2-RAMBo13a-E3Dv6full.h Firmware/Configuration_prusa.h
|
||||
- bash -x build.sh || { echo "1_75mm_MK2-RAMBo13a-E3Dv6full variant failed" && false; }
|
||||
- rm Firmware/Configuration_prusa.h
|
||||
- cp Firmware/variants/1_75mm_MK2-RAMBo10a-E3Dv6full.h Firmware/Configuration_prusa.h
|
||||
- bash -x build.sh || { echo "1_75mm_MK2-RAMBo10a-E3Dv6full variant failed" && false; }
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
[
|
||||
{
|
||||
"name": "avr-gcc",
|
||||
"toolchainFile": "${workspaceFolder}/cmake/AvrGcc.cmake",
|
||||
"cmakeSettings": {
|
||||
"CMAKE_MAKE_PROGRAM": "${workspaceFolder}/.dependencies/ninja-1.12.1/ninja",
|
||||
"CMAKE_BUILD_TYPE": "Release"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
buildType:
|
||||
default: debug
|
||||
choices:
|
||||
debug:
|
||||
short: Debug
|
||||
long: Emit debug information
|
||||
buildType: Debug
|
||||
release:
|
||||
short: Release
|
||||
long: Optimize generated code
|
||||
buildType: Release
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
{
|
||||
"cmake.configureOnOpen": true,
|
||||
"cmake.copyCompileCommands": "${workspaceFolder}/compile_commands.json",
|
||||
"cmake.cmakePath": "${workspaceFolder}/.dependencies/cmake-3.22.5/bin/cmake",
|
||||
"cmake.generator": "Ninja",
|
||||
"files.insertFinalNewline": true,
|
||||
"files.associations": {
|
||||
"xlocale": "cpp"
|
||||
}
|
||||
}
|
||||
682
CMakeLists.txt
682
CMakeLists.txt
|
|
@ -1,658 +1,24 @@
|
|||
cmake_minimum_required(VERSION 3.19)
|
||||
include(cmake/Utilities.cmake)
|
||||
include(cmake/GetGitRevisionDescription.cmake)
|
||||
include(cmake/ReproducibleBuild.cmake)
|
||||
include(cmake/ProjectVersion.cmake)
|
||||
resolve_version_variables()
|
||||
|
||||
OPTION(ENFORCE_VERSION_MATCH "Enforce checking that configuration.h matches any parsed git tags" OFF)
|
||||
OPTION(NO_TAG_IS_FATAL "If tag parsing fails, issue a fatal error" OFF)
|
||||
|
||||
set(PROJECT_VERSION_HASH
|
||||
"<auto>"
|
||||
CACHE
|
||||
STRING
|
||||
"Version suffix to be appended to the final filename (<ver+PROJECT_VERSION_HASH>). Overrides git hash if set."
|
||||
)
|
||||
if(PROJECT_VERSION_HASH STREQUAL "<auto>")
|
||||
set(PROJECT_VERSION_HASH "${FW_COMMIT_HASH}")
|
||||
endif()
|
||||
set(PROJECT_VERSION_FULL
|
||||
"<auto>"
|
||||
CACHE
|
||||
STRING
|
||||
"Full version string to be shown on the info screen in settings. Overrides git version if set."
|
||||
)
|
||||
if(PROJECT_VERSION_FULL STREQUAL "<auto>")
|
||||
set(PROJECT_VERSION_FULL "${FW_COMMIT_DSC}")
|
||||
endif()
|
||||
set(PROJECT_REPOSITORY
|
||||
"Unknown"
|
||||
CACHE STRING "Repository string to be shown on the info screen in settings."
|
||||
)
|
||||
|
||||
set(CUSTOM_COMPILE_OPTIONS
|
||||
""
|
||||
CACHE STRING "Allows adding custom C/C++ flags"
|
||||
)
|
||||
|
||||
#set(FN_VERSION_SUFFIX "FW${PROJECT_VERSION}+${PROJECT_VERSION_HASH}")
|
||||
set(FN_VERSION_SUFFIX "FW_${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_REV}")
|
||||
if(PROJECT_VERSION_FLV AND PROJECT_VERSION_FLV_VER)
|
||||
set (FN_VERSION_SUFFIX "${FN_VERSION_SUFFIX}-${PROJECT_VERSION_FLV}${PROJECT_VERSION_FLV_VER}")
|
||||
endif()
|
||||
set(FN_VERSION_DEBUG_SUFFIX "${FN_VERSION_SUFFIX}+${PROJECT_VERSION_COMMIT}")
|
||||
|
||||
# Inform user about the resolved settings from Configuration.h
|
||||
message(STATUS "Project version (Configuration.h): ${PROJECT_VERSION}")
|
||||
#message(STATUS "Project version major............: ${PROJECT_VERSION_MAJOR}") #For debuging
|
||||
#message(STATUS "Project version minor............: ${PROJECT_VERSION_MINOR}") #For debuging
|
||||
#message(STATUS "Project version revision.........: ${PROJECT_VERSION_REV}") #For debuging
|
||||
#message(STATUS "Project version flavor...........: ${PROJECT_VERSION_FLV}") #For debuging
|
||||
#message(STATUS "Project version fla-revison......: ${PROJECT_VERSION_FLV_VER}") #For debuging
|
||||
#message(STATUS "Project version commit number....: ${PROJECT_VERSION_COMMIT}") #For debuging
|
||||
message(STATUS "Filename suffix..................: ${FN_VERSION_SUFFIX}")
|
||||
message(STATUS "Filename debug suffix ...........: ${FN_VERSION_DEBUG_SUFFIX}")
|
||||
#message(STATUS "Host OS .........................: ${CMAKE_HOST_SYSTEM_NAME}")
|
||||
# testing
|
||||
# SET(FW_COMMIT_DSC "v3.13.0-1234")
|
||||
|
||||
if(NOT "${PROJECT_VERSION_HASH}" STREQUAL "UNKNOWN" AND NOT "${FW_COMMIT_DSC}" MATCHES ".+NOTFOUND.+") # else -> no commit hash is known... likely no git.
|
||||
string(REGEX MATCH "[v|t|c]([0-9]+)\.([0-9]+)\.([0-9]+)-?(${DEV_TAG_REGEX})?([0-9]+)?-([0-9]+)" TAG_VERSION "${FW_COMMIT_DSC}")
|
||||
|
||||
if (CMAKE_MATCH_4) # Do we have a build type?
|
||||
decode_flavor_code(PROJECT_VER_TAG_FLV "${CMAKE_MATCH_4}" "${CMAKE_MATCH_5}")
|
||||
else()
|
||||
# No dev status found, it must be a final tag.
|
||||
decode_flavor_code(PROJECT_VER_TAG_FLV "RELEASED" "0")
|
||||
endif()
|
||||
|
||||
if(ENFORCE_VERSION_MATCH)
|
||||
if(NOT ${CMAKE_MATCH_1} STREQUAL ${PROJECT_VERSION_MAJOR})
|
||||
message(FATAL_ERROR "Major version of current tag disagrees with Configuration.h ${CMAKE_MATCH_1}!=${PROJECT_VERSION_MAJOR}")
|
||||
endif()
|
||||
|
||||
if(NOT ${CMAKE_MATCH_2} STREQUAL ${PROJECT_VERSION_MINOR})
|
||||
message(FATAL_ERROR "Minor version of current tag disagrees with Configuration.h ${CMAKE_MATCH_2}!=${PROJECT_VERSION_MINOR}")
|
||||
endif()
|
||||
|
||||
if(NOT ${CMAKE_MATCH_3} STREQUAL ${PROJECT_VERSION_REV})
|
||||
message(FATAL_ERROR "Rev version of current tag disagrees with Configuration.h ${CMAKE_MATCH_3}!=${PROJECT_VERSION_REV}")
|
||||
endif()
|
||||
|
||||
if(NOT ${PROJECT_VER_TAG_FLV} STREQUAL ${PROJECT_VERSION_TWEAK})
|
||||
message(FATAL_ERROR "Dev status of current tag disagrees with Configuration.h ${PROJECT_VER_TAG_FLV}!=${PROJECT_VERSION_TWEAK}")
|
||||
endif()
|
||||
# Note - we don't check the commit counter, that'd be too much of a headache. Maybe it
|
||||
# should be an error only on a tagged build?
|
||||
MESSAGE(STATUS "Configuration.h and tag match: OK (${PROJECT_VERSION}/${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}.${PROJECT_VER_TAG_FLV})")
|
||||
else()
|
||||
MESSAGE(STATUS "Configuration.h and tag (not enforced): (${PROJECT_VERSION}/${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}.${PROJECT_VER_TAG_FLV})")
|
||||
endif()
|
||||
|
||||
MESSAGE(STATUS "Commit Nr: Configuration.h: ${PROJECT_VERSION_COMMIT} Tag: ${CMAKE_MATCH_6}")
|
||||
MESSAGE(STATUS "These tag values will override Configuration.h")
|
||||
SET(PROJECT_VERSION ${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}.${PROJECT_VER_TAG_FLV})
|
||||
SET(PROJECT_VERSION_COMMIT ${CMAKE_MATCH_6})
|
||||
|
||||
git_get_repository(PROJECT_REPOSITORY)
|
||||
else(GIT_FOUND)
|
||||
if (NO_TAG_IS_FATAL)
|
||||
MESSAGE(FATAL_ERROR "Git was not found or an error occurred parsing the tag. This is a fatal error according to the settings.")
|
||||
else()
|
||||
MESSAGE(STATUS "Git was not found or an error occurred parsing the tag. Falling back to Configuration.h values (${PROJECT_VERSION}).")
|
||||
endif()
|
||||
set(FW_COMMIT_HASH ${FW_COMMIT_HASH_UNKNOWN}) # Clear it, the code expects a binary...
|
||||
set(PROJECT_VERSION_TIMESTAMP "0")
|
||||
endif()
|
||||
|
||||
if(CMAKE_MATCH_1 AND CMAKE_MATCH_2)
|
||||
set(FN_VERSION_SUFFIX "FW_${CMAKE_MATCH_1}.${CMAKE_MATCH_2}.${CMAKE_MATCH_3}")
|
||||
endif()
|
||||
if(CMAKE_MATCH_4 AND CMAKE_MATCH_5)
|
||||
set (FN_VERSION_SUFFIX "${FN_VERSION_SUFFIX}-${CMAKE_MATCH_4}${CMAKE_MATCH_5}")
|
||||
endif()
|
||||
if(CMAKE_MATCH_6 AND PROJECT_VERSION_HASH)
|
||||
set(FN_VERSION_DEBUG_SUFFIX "${FN_VERSION_SUFFIX}+${CMAKE_MATCH_6}_${PROJECT_VERSION_HASH}")
|
||||
endif()
|
||||
# Inform user about the resolved settings from github
|
||||
message(STATUS "Project version git..............: ${PROJECT_VERSION}")
|
||||
message(STATUS "Project version git hash.........: ${PROJECT_VERSION_HASH}")
|
||||
message(STATUS "Project version git description..: ${PROJECT_VERSION_FULL}")
|
||||
#message(STATUS "Project version git major........: ${CMAKE_MATCH_1}") #For debuging
|
||||
#message(STATUS "Project version git minor........: ${CMAKE_MATCH_2}") #For debuging
|
||||
#message(STATUS "Project version git revision.....: ${CMAKE_MATCH_3}") #For debuging
|
||||
#message(STATUS "Project version git flavor.......: ${CMAKE_MATCH_4}") #For debuging
|
||||
#message(STATUS "Project version git fla-revison..: ${CMAKE_MATCH_5}") #For debuging
|
||||
#message(STATUS "Project version git commit number: ${CMAKE_MATCH_6}") #For debuging
|
||||
message(STATUS "Filename suffix .................: ${FN_VERSION_SUFFIX}")
|
||||
message(STATUS "Filename debug suffix ...........: ${FN_VERSION_DEBUG_SUFFIX}")
|
||||
|
||||
# Language configuration
|
||||
set(MAIN_LANGUAGES
|
||||
cs de es fr it pl
|
||||
CACHE STRING "The list of 'main' languages to be included, in the correct order"
|
||||
)
|
||||
set(COMMUNITY_LANGUAGES
|
||||
nl
|
||||
ro
|
||||
hu
|
||||
hr
|
||||
sk
|
||||
sv
|
||||
no
|
||||
CACHE STRING "The list of community languages to be included, in the correct order"
|
||||
)
|
||||
set(SELECTED_LANGUAGES ${MAIN_LANGUAGES} ${COMMUNITY_LANGUAGES})
|
||||
|
||||
get_dependency_directory(prusa3dboards PRUSA_BOARDS_DIR)
|
||||
project(Prusa-Firmware VERSION ${PROJECT_VERSION})
|
||||
add_subdirectory(lib)
|
||||
|
||||
# Get LANG_MAX_SIZE from sources
|
||||
file(STRINGS ${CMAKE_CURRENT_SOURCE_DIR}/Firmware/config.h MAX_SIZE_LINE
|
||||
REGEX "^#define \+LANG_SIZE_RESERVED \+"
|
||||
)
|
||||
string(REGEX MATCH "0x[0-9]+" MAX_SIZE_HEX "${MAX_SIZE_LINE}")
|
||||
math(EXPR LANG_MAX_SIZE "${MAX_SIZE_HEX}" OUTPUT_FORMAT DECIMAL)
|
||||
message("Language maximum size (from config.h): ${LANG_MAX_SIZE} bytes")
|
||||
|
||||
# Ditto, this in xflash_layout.h but needs invocation of the preprocessor... :-/
|
||||
set(LANG_BIN_MAX 249856)
|
||||
|
||||
# Check GCC Version
|
||||
get_recommended_gcc_version(RECOMMENDED_TOOLCHAIN_VERSION)
|
||||
if(CMAKE_CROSSCOMPILING AND NOT CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL
|
||||
${RECOMMENDED_TOOLCHAIN_VERSION}
|
||||
)
|
||||
message(WARNING "Recommended AVR toolchain is ${RECOMMENDED_TOOLCHAIN_VERSION}"
|
||||
", but you have ${CMAKE_CXX_COMPILER_VERSION}"
|
||||
)
|
||||
|
||||
elseif(NOT CMAKE_CROSSCOMPILING AND NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
message(
|
||||
WARNING
|
||||
"Recommended compiler for host tools and unittests is GCC, you have ${CMAKE_CXX_COMPILER_ID}."
|
||||
)
|
||||
endif()
|
||||
|
||||
# append custom C/C++ flags
|
||||
if(CUSTOM_COMPILE_OPTIONS)
|
||||
string(REPLACE " " ";" CUSTOM_COMPILE_OPTIONS "${CUSTOM_COMPILE_OPTIONS}")
|
||||
add_compile_options(${CUSTOM_COMPILE_OPTIONS})
|
||||
endif()
|
||||
|
||||
#
|
||||
# Global Compiler & Linker Configuration
|
||||
#
|
||||
|
||||
# enable warnings
|
||||
add_compile_options(-Wall -Wextra -Wno-expansion-to-defined -Wsign-compare)
|
||||
|
||||
# default standards for all targets
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
# support _DEBUG macro (some code uses to recognize debug builds)
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
add_compile_definitions(_DEBUG)
|
||||
endif()
|
||||
|
||||
#
|
||||
# Firmware - get file lists.
|
||||
#
|
||||
set(FW_SOURCES
|
||||
adc.cpp
|
||||
backlight.cpp
|
||||
BlinkM.cpp
|
||||
bootapp.c
|
||||
cardreader.cpp
|
||||
cmdqueue.cpp
|
||||
Configuration.cpp
|
||||
ConfigurationStore.cpp
|
||||
Dcodes.cpp
|
||||
eeprom.cpp
|
||||
fancheck.cpp
|
||||
Filament_sensor.cpp
|
||||
first_lay_cal.cpp
|
||||
heatbed_pwm.cpp
|
||||
host.cpp
|
||||
la10compat.cpp
|
||||
language.c
|
||||
lcd.cpp
|
||||
Marlin_main.cpp
|
||||
MarlinSerial.cpp
|
||||
meatpack.cpp
|
||||
menu.cpp
|
||||
mesh_bed_calibration.cpp
|
||||
mesh_bed_leveling.cpp
|
||||
messages.cpp
|
||||
mmu2.cpp
|
||||
mmu2_crc.cpp
|
||||
mmu2_error_converter.cpp
|
||||
mmu2_fsensor.cpp
|
||||
mmu2_log.cpp
|
||||
mmu2_marlin1.cpp
|
||||
mmu2_power.cpp
|
||||
mmu2_progress_converter.cpp
|
||||
mmu2_protocol.cpp
|
||||
mmu2_protocol_logic.cpp
|
||||
mmu2_reporting.cpp
|
||||
mmu2_serial.cpp
|
||||
motion_control.cpp
|
||||
optiboot_xflash.cpp
|
||||
pat9125.cpp
|
||||
planner.cpp
|
||||
power_panic.cpp
|
||||
printer_state.cpp
|
||||
Prusa_farm.cpp
|
||||
rbuf.c
|
||||
Sd2Card.cpp
|
||||
SdBaseFile.cpp
|
||||
SdFatUtil.cpp
|
||||
SdFile.cpp
|
||||
SdVolume.cpp
|
||||
sm4.cpp
|
||||
sound.cpp
|
||||
speed_lookuptable.cpp
|
||||
spi.c
|
||||
SpoolJoin.cpp
|
||||
stepper.cpp
|
||||
stopwatch.cpp
|
||||
strtod.c
|
||||
swi2c.c
|
||||
Tcodes.cpp
|
||||
temperature.cpp
|
||||
timer02.c
|
||||
Timer.cpp
|
||||
tmc2130.cpp
|
||||
tone04.c
|
||||
twi.cpp
|
||||
uart2.cpp
|
||||
ultralcd.cpp
|
||||
util.cpp
|
||||
xflash.c
|
||||
xflash_dump.cpp
|
||||
xyzcal.cpp
|
||||
)
|
||||
list(TRANSFORM FW_SOURCES PREPEND ${CMAKE_CURRENT_SOURCE_DIR}/Firmware/)
|
||||
|
||||
set(AVR_SOURCES
|
||||
wiring_digital.c
|
||||
WInterrupts.c
|
||||
wiring_pulse.c
|
||||
hooks.c
|
||||
wiring.c
|
||||
wiring_analog.c
|
||||
wiring_shift.c
|
||||
CDC.cpp
|
||||
PluggableUSB.cpp
|
||||
HardwareSerial.cpp
|
||||
HardwareSerial0.cpp
|
||||
HardwareSerial1.cpp
|
||||
HardwareSerial3.cpp
|
||||
IPAddress.cpp
|
||||
HardwareSerial2.cpp
|
||||
Print.cpp
|
||||
Stream.cpp
|
||||
Tone.cpp
|
||||
USBCore.cpp
|
||||
WMath.cpp
|
||||
WString.cpp
|
||||
abi.cpp
|
||||
main.cpp
|
||||
)
|
||||
list(TRANSFORM AVR_SOURCES PREPEND ${PRUSA_BOARDS_DIR}/cores/prusa_einsy_rambo/)
|
||||
|
||||
#
|
||||
# Target configuration
|
||||
#
|
||||
if(CMAKE_CROSSCOMPILING)
|
||||
set_source_epoch(${PROJECT_VERSION_TIMESTAMP})
|
||||
|
||||
# default optimization flags
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "-Og -g")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-Os -g -DNDEBUG")
|
||||
set(CMAKE_C_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG})
|
||||
set(CMAKE_C_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELEASE})
|
||||
|
||||
# mcu and target-related settings
|
||||
add_compile_options(
|
||||
-mmcu=atmega2560 -DF_CPU=16000000L -DARDUINO=10819 -DARDUINO_AVR_PRUSA_EINSY_RAMBO
|
||||
-DARDUINO_ARCH_AVR
|
||||
)
|
||||
add_link_options(-mmcu=atmega2560 -Wl,-u,vfprintf -lprintf_flt -lm)
|
||||
|
||||
# disable some C++ language features
|
||||
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fno-threadsafe-statics>)
|
||||
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fno-rtti>)
|
||||
|
||||
# disable exceptions
|
||||
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fno-exceptions>)
|
||||
add_compile_options($<$<COMPILE_LANGUAGE:CXX>:-fno-unwind-tables>)
|
||||
|
||||
# split and gc sections
|
||||
add_compile_options(-ffunction-sections -fdata-sections)
|
||||
add_link_options(-ffunction-sections -fdata-sections -Wl,--gc-sections)
|
||||
|
||||
# LTO (with custom options)
|
||||
add_compile_options(-flto -fno-fat-lto-objects)
|
||||
add_link_options(-flto)
|
||||
|
||||
# Create this target before we apply the GC options
|
||||
add_library(avr_core STATIC ${AVR_SOURCES})
|
||||
set_reproducible_target(avr_core)
|
||||
target_include_directories(
|
||||
avr_core PRIVATE ${PRUSA_BOARDS_DIR}/cores/prusa_einsy_rambo/
|
||||
${PRUSA_BOARDS_DIR}/variants/prusa_einsy_rambo/
|
||||
)
|
||||
endif()
|
||||
|
||||
# Meta targets to build absolutely everything
|
||||
add_custom_target(ALL_FIRMWARE)
|
||||
add_custom_target(ALL_ENGLISH)
|
||||
add_custom_target(ALL_MULTILANG)
|
||||
add_dependencies(ALL_FIRMWARE ALL_ENGLISH ALL_MULTILANG)
|
||||
set_target_properties(ALL_MULTILANG PROPERTIES EXCLUDE_FROM_ALL FALSE)
|
||||
|
||||
function(add_base_binary variant_name)
|
||||
add_executable(${variant_name} ${FW_SOURCES} ${FW_HEADERS} ${VARIANT_CFG_DST})
|
||||
set_target_properties(${variant_name} PROPERTIES EXCLUDE_FROM_ALL TRUE)
|
||||
set_reproducible_target(${variant_name})
|
||||
|
||||
target_include_directories(
|
||||
${variant_name}
|
||||
PRIVATE ${PRUSA_BOARDS_DIR}/cores/prusa_einsy_rambo/
|
||||
${PRUSA_BOARDS_DIR}/variants/prusa_einsy_rambo/ ${CMAKE_SOURCE_DIR}/Firmware
|
||||
)
|
||||
|
||||
target_link_libraries(${variant_name} avr_core)
|
||||
|
||||
# configure linker script
|
||||
set(LINKER_SCRIPT ${PRUSA_BOARDS_DIR}/ldscripts/avr6.xn)
|
||||
target_link_options(${variant_name} PUBLIC -Wl,-T,${LINKER_SCRIPT})
|
||||
|
||||
# limit the text section to 248K (256K - 8k reserved for the bootloader)
|
||||
target_link_options(${variant_name} PUBLIC -Wl,--defsym=__TEXT_REGION_LENGTH__=248K)
|
||||
|
||||
# produce ASM listing. Note we also specify the .map as a byproduct so it gets cleaned because
|
||||
# link_options doesn't have a "generated outputs" feature.
|
||||
add_custom_command(
|
||||
TARGET ${variant_name}
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_OBJDUMP} --prefix ${CMAKE_SOURCE_DIR} -CSd ${variant_name} > ${variant_name}.asm
|
||||
BYPRODUCTS ${variant_name}.asm ${variant_name}.map
|
||||
)
|
||||
|
||||
# inform about the firmware's size in terminal
|
||||
add_custom_command(
|
||||
TARGET ${variant_name}
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_COMMAND} -E echo_append "${variant_name} "
|
||||
COMMAND ${CMAKE_SIZE_UTIL} -C --mcu=atmega2560 ${variant_name}
|
||||
)
|
||||
report_size(${variant_name})
|
||||
|
||||
# generate linker map file
|
||||
target_link_options(
|
||||
${variant_name} PUBLIC -Wl,-Map=${CMAKE_CURRENT_BINARY_DIR}/${variant_name}.map
|
||||
)
|
||||
decode_tweak_version(PROJECT_VERSION_FLV PROJECT_VERSION_FLV_VER)
|
||||
target_compile_definitions(
|
||||
${variant_name}
|
||||
PRIVATE CMAKE_CONTROL FW_REPOSITORY="${PROJECT_REPOSITORY}"
|
||||
FW_COMMIT_HASH="${FW_COMMIT_HASH}"
|
||||
FW_COMMIT_HASH_LENGTH=${FW_COMMIT_HASH_LENGTH}
|
||||
FW_MAJOR=${PROJECT_VERSION_MAJOR}
|
||||
FW_MINOR=${PROJECT_VERSION_MINOR}
|
||||
FW_REVISION=${PROJECT_VERSION_REV}
|
||||
FW_COMMITNR=${PROJECT_VERSION_COMMIT}
|
||||
)
|
||||
if(NOT PROJECT_VERSION_FLV STREQUAL "RELEASED")
|
||||
target_compile_definitions(
|
||||
${variant_name}
|
||||
PRIVATE
|
||||
FW_FLAVERSION=${PROJECT_VERSION_FLV_VER}
|
||||
FW_FLAVOR=${PROJECT_VERSION_FLV}
|
||||
)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(fw_add_variant variant_name)
|
||||
set(variant_header "variants/${variant_name}.h")
|
||||
string(REPLACE "1_75mm_" "" variant_name "${variant_name}")
|
||||
string(REPLACE "-E3Dv6full" "" variant_name "${variant_name}")
|
||||
|
||||
# Single-language build
|
||||
set(FW_EN "${variant_name}_ENGLISH")
|
||||
#MK3S_MK3S+_FW_3.13.2-RC1_ENGLISH.hex
|
||||
set(hex_variant_name "${variant_name}")
|
||||
if(hex_variant_name STRGREATER_EQUAL "MK3S")
|
||||
string(REPLACE "MK3S" "MK3S_MK3S+" hex_variant_name ${hex_variant_name})
|
||||
endif()
|
||||
set(FW_HEX "${CMAKE_BINARY_DIR}/${hex_variant_name}_${FN_VERSION_SUFFIX}_ENGLISH.hex")
|
||||
#message(STATUS "Hex filename: ${FW_HEX}")
|
||||
|
||||
add_base_binary(${FW_EN})
|
||||
target_compile_definitions(${FW_EN} PUBLIC LANG_MODE=0 FW_VARIANT="${variant_header}")
|
||||
add_custom_command(
|
||||
TARGET ${FW_EN}
|
||||
POST_BUILD
|
||||
COMMAND ${CMAKE_OBJCOPY} -O ihex ${FW_EN} ${FW_EN}.hex
|
||||
COMMAND ${CMAKE_COMMAND} -E create_hardlink ${FW_EN}.hex ${FW_HEX}
|
||||
BYPRODUCTS ${FW_EN}.hex ${FW_HEX}
|
||||
COMMENT "Generating ${FW_EN}.hex"
|
||||
)
|
||||
add_dependencies(ALL_ENGLISH ${FW_EN})
|
||||
|
||||
# Multi-language build/s
|
||||
set(FW_LANG_BASE "${variant_name}_lang_base")
|
||||
set(FW_LANG_PATCH "${variant_name}_lang_patch")
|
||||
add_base_binary(${FW_LANG_BASE})
|
||||
target_compile_definitions(${FW_LANG_BASE} PUBLIC LANG_MODE=1 FW_VARIANT="${variant_header}")
|
||||
|
||||
# Construct language map
|
||||
set(LANG_TMP_DIR lang)
|
||||
set(LANG_MAP ${LANG_TMP_DIR}/${variant_name}_lang.map)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${LANG_MAP}
|
||||
COMMAND ${CMAKE_OBJCOPY} -O binary ${FW_LANG_BASE} ${FW_LANG_PATCH}.bin
|
||||
COMMAND "${Python3_EXECUTABLE}" ${CMAKE_SOURCE_DIR}/lang/lang-map.py ${FW_LANG_BASE} ${FW_LANG_PATCH}.bin > ${LANG_MAP}
|
||||
COMMAND ${CMAKE_OBJCOPY} -I binary -O ihex ${FW_LANG_PATCH}.bin ${FW_LANG_PATCH}.hex
|
||||
DEPENDS ${FW_LANG_BASE}
|
||||
BYPRODUCTS ${FW_LANG_PATCH}.bin ${FW_LANG_PATCH}.hex
|
||||
COMMENT "Generating ${variant_name} language map"
|
||||
)
|
||||
|
||||
# Base targets for language checks
|
||||
add_custom_target(check_lang_${variant_name})
|
||||
add_dependencies(check_lang check_lang_${variant_name})
|
||||
|
||||
# Build language catalogs
|
||||
set(LANG_BINS "")
|
||||
foreach(LANG IN LISTS SELECTED_LANGUAGES)
|
||||
set(LANG_BIN ${LANG_TMP_DIR}/${variant_name}_${LANG}.bin)
|
||||
set(PO_FILE "${CMAKE_SOURCE_DIR}/lang/po/Firmware_${LANG}.po")
|
||||
|
||||
# Full language checks
|
||||
add_custom_target(
|
||||
check_lang_${variant_name}_${LANG}
|
||||
COMMENT "Checking ${variant_name} language ${LANG}"
|
||||
COMMAND "${Python3_EXECUTABLE}" ${CMAKE_SOURCE_DIR}/lang/lang-check.py --map ${LANG_MAP} ${PO_FILE}
|
||||
DEPENDS ${LANG_MAP} ${PO_FILE}
|
||||
USES_TERMINAL
|
||||
)
|
||||
add_dependencies(check_lang_${variant_name} check_lang_${variant_name}_${LANG})
|
||||
add_dependencies(check_lang_${LANG} check_lang_${variant_name}_${LANG})
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${LANG_BIN}
|
||||
# Check po file for errors _only_
|
||||
COMMAND "${Python3_EXECUTABLE}" ${CMAKE_SOURCE_DIR}/lang/lang-check.py --errors-only --map ${LANG_MAP} ${PO_FILE}
|
||||
# Build the catalog
|
||||
COMMAND "${Python3_EXECUTABLE}" ${CMAKE_SOURCE_DIR}/lang/lang-build.py ${LANG_MAP} ${PO_FILE} ${LANG_BIN}
|
||||
# Check bin size
|
||||
COMMAND ${CMAKE_COMMAND} -DLANG_MAX_SIZE=${LANG_MAX_SIZE} -DLANG_FILE=${LANG_BIN} -P
|
||||
${PROJECT_CMAKE_DIR}/Check_lang_size.cmake
|
||||
DEPENDS ${LANG_MAP} ${PO_FILE}
|
||||
COMMENT "Generating ${variant_name}_${LANG}.bin"
|
||||
)
|
||||
list(APPEND LANG_BINS ${LANG_BIN})
|
||||
endforeach()
|
||||
|
||||
string(FIND ${variant_name} "MK3" HAS_XFLASH)
|
||||
if(${HAS_XFLASH} GREATER_EQUAL 0)
|
||||
# X-Flash based build (catalogs appended to patched binary)
|
||||
set(FW_LANG_FINAL "${variant_name}_MULTILANG")
|
||||
set(hex_variant_name "${variant_name}")
|
||||
#MK3S_MK3S+_FW_3.13.2-RC1+7651_deadbeef_MULTILANG.hex
|
||||
if(hex_variant_name STRGREATER_EQUAL "MK3S")
|
||||
string(REPLACE "MK3S" "MK3S_MK3S+" hex_variant_name ${hex_variant_name})
|
||||
endif()
|
||||
set(LANG_HEX ${CMAKE_BINARY_DIR}/${hex_variant_name}_${FN_VERSION_SUFFIX}_MULTILANG.hex)
|
||||
set(LANG_DEBUG_HEX ${CMAKE_BINARY_DIR}/${hex_variant_name}_${FN_VERSION_DEBUG_SUFFIX}_MULTILANG.hex)
|
||||
#message(STATUS "Hex filename .....: ${LANG_HEX}")
|
||||
#message(STATUS "Hex debug filename: ${LANG_DEBUG_HEX}")
|
||||
set(LANG_CATBIN ${LANG_TMP_DIR}/${variant_name}_cat.bin)
|
||||
set(LANG_CATHEX ${LANG_TMP_DIR}/${variant_name}_cat.hex)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${LANG_CATBIN}
|
||||
COMMAND ${CMAKE_COMMAND} -E cat ${LANG_BINS} > ${LANG_CATBIN}
|
||||
DEPENDS ${LANG_BINS}
|
||||
COMMENT "Merging language catalogs"
|
||||
)
|
||||
#[[
|
||||
#add_custom_command(OUTPUT ${LANG_FINAL_BIN}
|
||||
# COMMAND ${CMAKE_COMMAND} -DLANG_MAX_SIZE=${LANG_BIN_MAX} -DLANG_FILE=${LANG_FINAL_BIN}
|
||||
# -P ${PROJECT_CMAKE_DIR}/Check_final_lang_bin_size.cmake
|
||||
# APPEND)
|
||||
#]]
|
||||
add_custom_command(
|
||||
OUTPUT ${LANG_CATHEX}
|
||||
COMMAND ${CMAKE_OBJCOPY} -I binary -O ihex ${LANG_CATBIN} ${LANG_CATHEX}
|
||||
DEPENDS ${LANG_CATBIN}
|
||||
COMMENT "Generating Hex for language data"
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ${FW_LANG_FINAL}.hex
|
||||
COMMAND ${CMAKE_COMMAND} -E cat ${FW_LANG_PATCH}.hex ${LANG_CATHEX} > ${FW_LANG_FINAL}.hex
|
||||
COMMAND ${CMAKE_COMMAND} -E create_hardlink ${FW_LANG_FINAL}.hex ${LANG_HEX}
|
||||
BYPRODUCTS ${LANG_HEX}
|
||||
COMMAND ${CMAKE_COMMAND} -E create_hardlink ${FW_LANG_FINAL}.hex ${LANG_DEBUG_HEX}
|
||||
BYPRODUCTS ${LANG_DEBUG_HEX}
|
||||
COMMAND ${CMAKE_COMMAND} -E create_hardlink ${FW_LANG_FINAL}.hex ${CMAKE_BINARY_DIR}/release/${hex_variant_name}_${FN_VERSION_SUFFIX}_MULTILANG.hex
|
||||
BYPRODUCTS ${CMAKE_BINARY_DIR}/release/${hex_variant_name}_${FN_VERSION_SUFFIX}_MULTILANG.hex
|
||||
DEPENDS ${FW_LANG_PATCH}.hex ${LANG_CATHEX}
|
||||
COMMENT "Generating final ${FW_LANG_FINAL}.hex"
|
||||
)
|
||||
|
||||
add_custom_target(${FW_LANG_FINAL} DEPENDS ${FW_LANG_FINAL}.hex)
|
||||
add_dependencies(ALL_MULTILANG ${FW_LANG_FINAL})
|
||||
else()
|
||||
set(ALL_VARIANT_HEXES "")
|
||||
# Non-xflash, e.g. MK2.5
|
||||
foreach(LANG IN LISTS SELECTED_LANGUAGES)
|
||||
set(FW_LANG_FINAL ${variant_name}_en-${LANG})
|
||||
set(LANG_HEX ${CMAKE_BINARY_DIR}/${variant_name}_${FN_VERSION_SUFFIX}_en-${LANG}.hex)
|
||||
set(LANG_DEBUG_HEX ${CMAKE_BINARY_DIR}/${variant_name}_${FN_VERSION_DEBUG_SUFFIX}_en-${LANG}.hex)
|
||||
set(LANG_BIN ${LANG_TMP_DIR}/${variant_name}_${LANG}.bin)
|
||||
|
||||
# Patched binary with pre-baked secondary language
|
||||
add_custom_command(
|
||||
OUTPUT ${FW_LANG_FINAL}.bin
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${FW_LANG_PATCH}.bin ${FW_LANG_FINAL}.bin
|
||||
COMMAND "${Python3_EXECUTABLE}" ${CMAKE_SOURCE_DIR}/lang/lang-patchsec.py ${FW_LANG_BASE} ${LANG_BIN}
|
||||
${FW_LANG_FINAL}.bin
|
||||
DEPENDS ${FW_LANG_BASE} ${FW_LANG_PATCH}.bin ${LANG_BIN}
|
||||
COMMENT "Generating ${FW_LANG_FINAL}.bin"
|
||||
)
|
||||
|
||||
# Final hex files
|
||||
add_custom_command(
|
||||
OUTPUT ${FW_LANG_FINAL}.hex
|
||||
COMMAND ${CMAKE_OBJCOPY} -I binary -O ihex ${FW_LANG_FINAL}.bin ${FW_LANG_FINAL}.hex
|
||||
COMMAND ${CMAKE_COMMAND} -E create_hardlink ${FW_LANG_FINAL}.hex ${LANG_HEX}
|
||||
BYPRODUCTS ${LANG_HEX}
|
||||
COMMAND ${CMAKE_COMMAND} -E create_hardlink ${FW_LANG_FINAL}.hex ${LANG_DEBUG_HEX}
|
||||
BYPRODUCTS ${LANG_DEBUG_HEX}
|
||||
DEPENDS ${FW_LANG_FINAL}.bin
|
||||
COMMENT "Creating ${FW_LANG_FINAL}.hex"
|
||||
)
|
||||
|
||||
add_custom_target(${FW_LANG_FINAL} DEPENDS ${FW_LANG_FINAL}.hex)
|
||||
list(APPEND ALL_VARIANT_HEXES ${FW_LANG_FINAL})
|
||||
endforeach()
|
||||
add_custom_target("${variant_name}-All-Languages" DEPENDS ${ALL_VARIANT_HEXES})
|
||||
if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux")
|
||||
add_custom_command(TARGET "${variant_name}-All-Languages"
|
||||
POST_BUILD
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||
COMMAND ${CMAKE_COMMAND} -E make_directory "release"
|
||||
COMMAND ${CMAKE_COMMAND} -E tar "cfv" "release/${variant_name}_${FN_VERSION_SUFFIX}.zip" --format=zip ${variant_name}_${FN_VERSION_SUFFIX}_en*.hex
|
||||
BYPRODUCTS "${CMAKE_BINARY_DIR}/release/${variant_name}_${FN_VERSION_SUFFIX}.zip"
|
||||
)
|
||||
endif()
|
||||
add_dependencies(ALL_MULTILANG "${variant_name}-All-Languages")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
if(CMAKE_CROSSCOMPILING)
|
||||
|
||||
# Main target for language checks
|
||||
add_custom_target(check_lang)
|
||||
foreach(LANG IN LISTS SELECTED_LANGUAGES)
|
||||
add_custom_target(check_lang_${LANG})
|
||||
add_dependencies(check_lang check_lang_${LANG})
|
||||
endforeach()
|
||||
|
||||
# build a list of all supported variants
|
||||
file(
|
||||
GLOB ALL_VARIANTS
|
||||
RELATIVE ${PROJECT_SOURCE_DIR}/Firmware/variants
|
||||
${PROJECT_SOURCE_DIR}/Firmware/variants/*.h
|
||||
)
|
||||
list(TRANSFORM ALL_VARIANTS REPLACE "\.h$" "")
|
||||
set(FW_VARIANTS
|
||||
${ALL_VARIANTS}
|
||||
CACHE STRING "Firmware variants to be built"
|
||||
)
|
||||
|
||||
foreach(THIS_VAR IN LISTS FW_VARIANTS)
|
||||
if(NOT ${THIS_VAR} IN_LIST ALL_VARIANTS)
|
||||
message(FATAL_ERROR "Variant ${THIS_VAR} does not exist")
|
||||
endif()
|
||||
|
||||
message("Variant added: ${THIS_VAR}")
|
||||
|
||||
# Generate a file in a subfolder so that we can organize things a little more neatly in VS code
|
||||
set(DIR_NAME ${THIS_VAR})
|
||||
file(MAKE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/build_gen/${DIR_NAME})
|
||||
file(WRITE ${CMAKE_CURRENT_SOURCE_DIR}/build_gen/${DIR_NAME}/CMakeLists.txt
|
||||
"project(${DIR_NAME} VERSION ${PROJECT_VERSION})\nfw_add_variant(${THIS_VAR})"
|
||||
)
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/build_gen/${DIR_NAME})
|
||||
endforeach(THIS_VAR IN LISTS FW_VARIANTS)
|
||||
endif()
|
||||
|
||||
SET(REVO_FW_ZIP_NAME "E3D_REVO_FW_MK3_MK3S_MK3S+_${FN_VERSION_SUFFIX}.zip")
|
||||
|
||||
if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux")
|
||||
add_custom_command(TARGET ALL_MULTILANG
|
||||
POST_BUILD
|
||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/release
|
||||
BYPRODUCTS ${CMAKE_BINARY_DIR}/release/${REVO_FW_ZIP_NAME}
|
||||
COMMAND ${CMAKE_COMMAND} -E tar "cfv" "${REVO_FW_ZIP_NAME}" --format=zip *E3DREVO*.hex
|
||||
COMMAND ${CMAKE_COMMAND} -E rm *E3DREVO*.hex
|
||||
)
|
||||
endif()
|
||||
|
||||
#
|
||||
# Tests
|
||||
#
|
||||
if(NOT CMAKE_CROSSCOMPILING)
|
||||
enable_testing()
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
|
||||
set (CMAKE_CXX_STANDARD 11)
|
||||
|
||||
project(cmake_test)
|
||||
|
||||
# Prepare "Catch" library for other executables
|
||||
set(CATCH_INCLUDE_DIR Catch2)
|
||||
add_library(Catch INTERFACE)
|
||||
target_include_directories(Catch INTERFACE ${CATCH_INCLUDE_DIR})
|
||||
|
||||
# Make test executable
|
||||
set(TEST_SOURCES
|
||||
Tests/tests.cpp
|
||||
Tests/Example_test.cpp
|
||||
Tests/Timer_test.cpp
|
||||
Tests/AutoDeplete_test.cpp
|
||||
Tests/PrusaStatistics_test.cpp
|
||||
Firmware/Timer.cpp
|
||||
Firmware/AutoDeplete.cpp
|
||||
)
|
||||
add_executable(tests ${TEST_SOURCES})
|
||||
target_include_directories(tests PRIVATE Tests)
|
||||
target_link_libraries(tests Catch)
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,65 +0,0 @@
|
|||
# Community made
|
||||
Community made features aren't fully supported by Prusa and the owners are responsible to maintain them.
|
||||
In case the feature isn't maintained OR causes issues Prusa will deactivate these.
|
||||
## Prusa-Firmware build
|
||||
- `PF-build.sh`
|
||||
- Maintainers: **@3d-gussner**
|
||||
- Co-maintainers:
|
||||
- Contributors: **@mkbel**, **@ropaha**, **@deliopoulos**, **@DRracer**, **wavexx**, **@leptun**, **@andrewluebke**, **@kuhnmarek**
|
||||
- [X] **Active** since February 2019
|
||||
- [X] **Maintained** since January 2019
|
||||
|
||||
### How-to use PF-build.sh
|
||||
Start `./PF-build.sh` and follow the instructions
|
||||
|
||||
Help `./PF-build.sh -h`
|
||||
|
||||
# MK404 Simulator
|
||||
|
||||
## MK404-build.sh
|
||||
**MK404 is a community 3d printer simulator created by @vintagepc**
|
||||
Please checkout and support his github repository [MK404](https://github.com/vintagepc/MK404) and the [MK404 Wiki](https://github.com/vintagepc/MK404/wiki)
|
||||
|
||||
At this moment the `MK404-build.sh` script is only supported on Linux
|
||||
- `MK404-build.sh`
|
||||
- Maintainers: **@3d-gussner**
|
||||
- Co-maintainers:
|
||||
- Contributors:
|
||||
- [X] **Active** since August 2021
|
||||
- [X] **Maintained** since August 2021
|
||||
|
||||
### How-to use MK404-build.sh
|
||||
After compiling with `PF-build.sh` you get the option to start the `MK404` simulator with the fresh compiled firmware. (Linux only at this moment)
|
||||
|
||||
Help `./MK404-build.sh -h`
|
||||
|
||||
# Translations
|
||||
- see [/lang/Community_made_translations.md](https://github.com/prusa3d/Prusa-Firmware/blob/MK3/lang/Community_made_translations.md)
|
||||
|
||||
# Arc interpolation features
|
||||
**Arc interpolation features by @FormerLurker**
|
||||
Please read more about it [here](https://github.com/prusa3d/Prusa-Firmware/pull/2657) and [here](https://github.com/FormerLurker/ArcWelderPlugin)
|
||||
|
||||
- Maintainers: **@FormerLurker**
|
||||
- Co-maintainers:
|
||||
- Contributors:
|
||||
- [X] **Active** since January 2023
|
||||
- [X] **Maintained** since May 2020
|
||||
|
||||
# MeatPack
|
||||
**MeatPack by @scottmudge**
|
||||
Please read more about it [here](https://github.com/prusa3d/Prusa-Firmware/pull/2955), [here](https://github.com/prusa3d/Prusa-Firmware/pull/4067) and [here](https://github.com/scottmudge/OctoPrint-MeatPack/)
|
||||
|
||||
- Maintainers: **@scottmudge**
|
||||
- Co-maintainers:
|
||||
- Contributors:
|
||||
- [X] **Active** since April 2023
|
||||
- [X] **Maintained** since January 2021
|
||||
|
||||
# E3D Revo
|
||||
**The E3D REVO support is a community effort thanks to these Contributors, E3D and others.**
|
||||
- Maintainers: **E3D**
|
||||
- Co-maintainers:
|
||||
- Contributors: @alexiri @kromeninja @ulab @JWvP @snafu1282 @matthiazzz @sdh2 @jdrozdz @peschkaj @MarcelTh @zuidwijk @davejhilton @WhiterRice @NightSkySK @D-an-W
|
||||
- [X] **Active** since June 2023
|
||||
- [X] **Maintained** since April 2023
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
//! @file
|
||||
//! @author: Marek Bel
|
||||
//! @date Jan 3, 2019
|
||||
|
||||
#include "AutoDeplete.h"
|
||||
#include "assert.h"
|
||||
|
||||
//! @brief bit field marking depleted filaments
|
||||
//!
|
||||
//! binary 1 marks filament as depleted
|
||||
//! Zero initialized value means, that no filament is depleted.
|
||||
static uint8_t depleted;
|
||||
static const uint8_t filamentCount = 5;
|
||||
|
||||
//! @return binary 1 for all filaments
|
||||
//! @par fCount number of filaments
|
||||
static constexpr uint8_t allDepleted(uint8_t fCount)
|
||||
{
|
||||
return fCount == 1 ? 1 : ((1 << (fCount - 1)) | allDepleted(fCount - 1));
|
||||
}
|
||||
|
||||
//! @brief Is filament available for printing?
|
||||
//! @par filament Filament number to be checked
|
||||
//! @retval true Filament is available for printing.
|
||||
//! @retval false Filament is not available for printing.
|
||||
static bool loaded(uint8_t filament)
|
||||
{
|
||||
if (depleted & (1 << filament)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
//! @brief Mark filament as not available for printing.
|
||||
//! @par filament filament to be marked
|
||||
void ad_markDepleted(uint8_t filament)
|
||||
{
|
||||
assert(filament < filamentCount);
|
||||
if (filament < filamentCount)
|
||||
{
|
||||
depleted |= 1 << filament;
|
||||
}
|
||||
}
|
||||
|
||||
//! @brief Mark filament as available for printing.
|
||||
//! @par filament filament to be marked
|
||||
void ad_markLoaded(uint8_t filament)
|
||||
{
|
||||
assert(filament < filamentCount);
|
||||
if (filament < filamentCount)
|
||||
{
|
||||
depleted &= ~(1 << filament);
|
||||
}
|
||||
}
|
||||
|
||||
//! @brief Get alternative filament, which is not depleted
|
||||
//! @par filament filament
|
||||
//! @return Filament, if it is depleted, returns next available,
|
||||
//! if all filaments are depleted, returns filament function parameter.
|
||||
uint8_t ad_getAlternative(uint8_t filament)
|
||||
{
|
||||
assert(filament < filamentCount);
|
||||
for (uint8_t i = 0; i<filamentCount; ++i)
|
||||
{
|
||||
uint8_t nextFilament = (filament + i) % filamentCount;
|
||||
if (loaded(nextFilament)) return nextFilament;
|
||||
}
|
||||
return filament;
|
||||
}
|
||||
|
||||
//! @brief Are all filaments depleted?
|
||||
//! @retval true All filaments are depleted.
|
||||
//! @retval false All filaments are not depleted.
|
||||
bool ad_allDepleted()
|
||||
{
|
||||
if (allDepleted(filamentCount) == depleted)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
//! @file
|
||||
//! @author: Marek Bel
|
||||
//! @brief Filament auto deplete engine for multi-material prints with MMUv2 (Now marketed as SpoolJoin)
|
||||
//!
|
||||
//! Interface for marking MMUv2 filaments as depleted and getting alternative filament for printing.
|
||||
|
||||
#ifndef AUTODEPLETE_H
|
||||
#define AUTODEPLETE_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void ad_markDepleted(uint8_t filament);
|
||||
void ad_markLoaded(uint8_t filament);
|
||||
uint8_t ad_getAlternative(uint8_t filament);
|
||||
bool ad_allDepleted();
|
||||
|
||||
#endif /* AUTODEPLETE_H */
|
||||
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
void SendColors(byte red, byte grn, byte blu)
|
||||
{
|
||||
Wire.begin();
|
||||
Wire.begin();
|
||||
Wire.beginTransmission(0x09);
|
||||
Wire.write('o'); //to disable ongoing script, only needs to be used once
|
||||
Wire.write('n');
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
#include "Configuration.h"
|
||||
#include "Configuration_var.h"
|
||||
#include "Configuration_prusa.h"
|
||||
|
||||
const uint16_t _nPrinterType PROGMEM=PRINTER_TYPE;
|
||||
const char _sPrinterName[] PROGMEM=PRINTER_NAME;
|
||||
const uint16_t _nPrinterMmuType PROGMEM=PRINTER_MMU_TYPE;
|
||||
const char _sPrinterMmuName[] PROGMEM=PRINTER_MMU_NAME;
|
||||
|
||||
static_assert(TEMP_HYSTERESIS > 0, "TEMP_HYSTERESIS must be greater than 0");
|
||||
uint16_t nPrinterType;
|
||||
PGM_P sPrinterName;
|
||||
|
|
@ -1,61 +1,69 @@
|
|||
#ifndef CONFIGURATION_H
|
||||
#define CONFIGURATION_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "boards.h"
|
||||
|
||||
#define STR_HELPER(x) #x
|
||||
#define STR(x) STR_HELPER(x)
|
||||
#define _CONCAT(x,y) x##y
|
||||
#define CONCAT(x,y) _CONCAT(x,y)
|
||||
|
||||
//-//
|
||||
#include <avr/pgmspace.h>
|
||||
extern const uint16_t _nPrinterType;
|
||||
extern const char _sPrinterName[] PROGMEM;
|
||||
extern const uint16_t _nPrinterMmuType;
|
||||
extern const char _sPrinterMmuName[] PROGMEM;
|
||||
extern uint16_t nPrinterType;
|
||||
extern PGM_P sPrinterName;
|
||||
|
||||
// Firmware version.
|
||||
// NOTE: These are ONLY used if you are not building via cmake and/or not in a git repository.
|
||||
// Otherwise the repository information takes precedence.
|
||||
#ifndef CMAKE_CONTROL
|
||||
// Firmware version
|
||||
#define FW_MAJOR 3
|
||||
#define FW_MINOR 14
|
||||
#define FW_MINOR 11
|
||||
#define FW_REVISION 1
|
||||
#define FW_COMMITNR 8225
|
||||
#define FW_FLAVOR RC //uncomment if DEV, ALPHA, BETA or RC
|
||||
#define FW_FLAVERSION 1 //uncomment if FW_FLAVOR is defined and versioning is needed. Limited to max 8.
|
||||
#endif
|
||||
|
||||
#define FW_FLAVOR RC //uncomment if DEBUG, DEVEL, APLHA, BETA or RC
|
||||
#define FW_FLAVERSION 1 //uncomment if FW_FLAVOR is defined and versioning is needed.
|
||||
#ifndef FW_FLAVOR
|
||||
#define FW_TWEAK (FIRMWARE_REVISION_RELEASED)
|
||||
#define FW_VERSION STR(FW_MAJOR) "." STR(FW_MINOR) "." STR(FW_REVISION)
|
||||
#define FW_VERSION_FULL STR(FW_MAJOR) "." STR(FW_MINOR) "." STR(FW_REVISION) "-" STR(FW_COMMITNR)
|
||||
#else
|
||||
// Construct the TWEAK value as it is expected from the enum.
|
||||
#define FW_TWEAK (CONCAT(FIRMWARE_REVISION_,FW_FLAVOR) + FW_FLAVERSION)
|
||||
#define FW_VERSION STR(FW_MAJOR) "." STR(FW_MINOR) "." STR(FW_REVISION) "-" STR(FW_FLAVOR) "" STR(FW_FLAVERSION)
|
||||
#define FW_VERSION_FULL STR(FW_MAJOR) "." STR(FW_MINOR) "." STR(FW_REVISION) "-" STR(FW_FLAVOR) "" STR(FW_FLAVERSION) "+" STR(FW_COMMITNR)
|
||||
#endif
|
||||
|
||||
// The full version string and repository source are set via cmake
|
||||
#ifndef CMAKE_CONTROL
|
||||
#define FW_COMMIT_HASH_LENGTH 1
|
||||
#define FW_COMMIT_HASH "0"
|
||||
#define FW_COMMIT_NR 4987
|
||||
|
||||
// FW_VERSION_UNKNOWN means this is an unofficial build.
|
||||
// The firmware should only be checked into github with this symbol.
|
||||
#define FW_DEV_VERSION FW_VERSION_UNKNOWN
|
||||
#define FW_REPOSITORY "Unknown"
|
||||
#endif
|
||||
#define FW_VERSION_FULL FW_VERSION "-" STR(FW_COMMIT_NR)
|
||||
|
||||
// G-code language level
|
||||
#define GCODE_LEVEL 1
|
||||
|
||||
#ifndef SOURCE_DATE_EPOCH
|
||||
#define SOURCE_DATE_EPOCH __DATE__
|
||||
#endif
|
||||
#ifndef SOURCE_TIME_EPOCH
|
||||
#define SOURCE_TIME_EPOCH __TIME__
|
||||
// Debug version has debugging enabled (the symbol DEBUG_BUILD is set).
|
||||
// The debug build may be a bit slower than the non-debug build, therefore the debug build should
|
||||
// not be shipped to a customer.
|
||||
#define FW_VERSION_DEBUG 6
|
||||
// This is a development build. A development build is either built from an unofficial git repository,
|
||||
// or from an unofficial branch, or it does not have a label set. Only the build server should set this build type.
|
||||
#define FW_VERSION_DEVEL 5
|
||||
// This is an alpha release. Only the build server should set this build type.
|
||||
#define FW_VERSION_ALPHA 4
|
||||
// This is a beta release. Only the build server should set this build type.
|
||||
#define FW_VERSION_BETA 3
|
||||
// This is a release candidate build. Only the build server should set this build type.
|
||||
#define FW_VERSION_RC 2
|
||||
// This is a final release. Only the build server should set this build type.
|
||||
#define FW_VERSION_GOLD 1
|
||||
// This is an unofficial build. The firmware should only be checked into github with this symbol,
|
||||
// the build server shall never produce builds with this build type.
|
||||
#define FW_VERSION_UNKNOWN 0
|
||||
|
||||
#if FW_DEV_VERSION == FW_VERSION_DEBUG
|
||||
#define DEBUG_BUILD
|
||||
#else
|
||||
#undef DEBUG_BUILD
|
||||
#endif
|
||||
|
||||
#include "Configuration_var.h"
|
||||
#include "Configuration_prusa.h"
|
||||
|
||||
#define FW_PRUSA3D_MAGIC "PRUSA3DFW"
|
||||
#define FW_PRUSA3D_MAGIC_LEN 10
|
||||
|
|
@ -70,8 +78,10 @@ extern const char _sPrinterMmuName[] PROGMEM;
|
|||
// startup. Implementation of an idea by Prof Braino to inform user that any changes made to this
|
||||
// build by the user have been successfully uploaded into firmware.
|
||||
|
||||
#define STRING_VERSION_CONFIG_H SOURCE_DATE_EPOCH " " SOURCE_TIME_EPOCH // build date and time
|
||||
#define STRING_CONFIG_H_AUTHOR FW_REPOSITORY // Who made the changes.
|
||||
//#define STRING_VERSION "1.0.2"
|
||||
|
||||
#define STRING_VERSION_CONFIG_H __DATE__ " " __TIME__ // build date and time
|
||||
#define STRING_CONFIG_H_AUTHOR "(none, default config)" // Who made the changes.
|
||||
|
||||
// SERIAL_PORT selects which serial port should be used for communication with the host.
|
||||
// This allows the connection of wireless adapters (for instance) to non-default port pins.
|
||||
|
|
@ -81,9 +91,6 @@ extern const char _sPrinterMmuName[] PROGMEM;
|
|||
// This determines the communication speed of the printer
|
||||
#define BAUDRATE 115200
|
||||
|
||||
// Enable g-code compression (see https://github.com/scottmudge/OctoPrint-MeatPack)
|
||||
#define ENABLE_MEATPACK
|
||||
|
||||
// This enables the serial port associated to the Bluetooth interface
|
||||
//#define BTENABLED // Enable BT interface on AT90USB devices
|
||||
|
||||
|
|
@ -122,6 +129,13 @@ extern const char _sPrinterMmuName[] PROGMEM;
|
|||
#define TEMP_HYSTERESIS 5 // (degC) range of +/- temperatures considered "close" to the target one
|
||||
#define TEMP_WINDOW 1 // (degC) Window around target to start the residency timer x degC early.
|
||||
|
||||
|
||||
|
||||
// If your bed has low resistance e.g. .6 ohm and throws the fuse you can duty cycle it to reduce the
|
||||
// average current. The value should be an integer and the heat bed will be turned on for 1 interval of
|
||||
// HEATER_BED_DUTY_CYCLE_DIVIDER intervals.
|
||||
//#define HEATER_BED_DUTY_CYCLE_DIVIDER 4
|
||||
|
||||
// If you want the M105 heater power reported in watts, define the BED_WATTS, and (shared for all extruders) EXTRUDER_WATTS
|
||||
//#define EXTRUDER_WATTS (12.0*12.0/6.7) // P=I^2/R
|
||||
//#define BED_WATTS (12.0*12.0/1.1) // P=I^2/R
|
||||
|
|
@ -141,7 +155,7 @@ extern const char _sPrinterMmuName[] PROGMEM;
|
|||
|
||||
// If you are using a pre-configured hotend then you can use one of the value sets by uncommenting it
|
||||
// Ultimaker
|
||||
|
||||
|
||||
|
||||
// MakerGear
|
||||
// #define DEFAULT_Kp 7.0
|
||||
|
|
@ -177,15 +191,15 @@ The issue: If a thermistor come off, it will read a lower temperature than actua
|
|||
The system will turn the heater on forever, burning up the filament and anything
|
||||
else around.
|
||||
|
||||
After the temperature reaches the target for the first time, this feature will
|
||||
start measuring for how long the current temperature stays below the target
|
||||
After the temperature reaches the target for the first time, this feature will
|
||||
start measuring for how long the current temperature stays below the target
|
||||
minus _HYSTERESIS (set_temperature - THERMAL_RUNAWAY_PROTECTION_HYSTERESIS).
|
||||
|
||||
If it stays longer than _PERIOD, it means the thermistor temperature
|
||||
cannot catch up with the target, so something *may be* wrong. Then, to be on the
|
||||
safe side, the system will he halt.
|
||||
|
||||
Bear in mind the count down will just start AFTER the first time the
|
||||
Bear in mind the count down will just start AFTER the first time the
|
||||
thermistor temperature is over the target, so you will have no problem if
|
||||
your extruder heater takes 2 minutes to hit the target on heating.
|
||||
|
||||
|
|
@ -259,6 +273,7 @@ your extruder heater takes 2 minutes to hit the target on heating.
|
|||
#define DISABLE_Y 0
|
||||
#define DISABLE_Z 0
|
||||
#define DISABLE_E 0// For all extruders
|
||||
#define DISABLE_INACTIVE_EXTRUDER 1 //disable only inactive extruders and keep active extruder enabled
|
||||
|
||||
|
||||
// ENDSTOP SETTINGS:
|
||||
|
|
@ -277,13 +292,131 @@ your extruder heater takes 2 minutes to hit the target on heating.
|
|||
|
||||
|
||||
#define X_MAX_LENGTH (X_MAX_POS - X_MIN_POS)
|
||||
#define Y_MAX_LENGTH (Y_MAX_POS - Y_MIN_POS)
|
||||
#define Y_MAX_LENGTH (Y_MAX_POS - Y_MIN_POS)
|
||||
#define Z_MAX_LENGTH (Z_MAX_POS - Z_MIN_POS)
|
||||
|
||||
#define Z_HEIGHT_HIDE_LIVE_ADJUST_MENU 2.0f
|
||||
|
||||
#define HOME_Z_SEARCH_THRESHOLD 0.15f // Threshold of the Z height in calibration
|
||||
|
||||
//============================= Bed Auto Leveling ===========================
|
||||
|
||||
//#define ENABLE_AUTO_BED_LEVELING // Delete the comment to enable (remove // at the start of the line)
|
||||
#define Z_PROBE_REPEATABILITY_TEST // If not commented out, Z-Probe Repeatability test will be included if Auto Bed Leveling is Enabled.
|
||||
|
||||
#ifdef ENABLE_AUTO_BED_LEVELING
|
||||
|
||||
// There are 2 different ways to pick the X and Y locations to probe:
|
||||
|
||||
// - "grid" mode
|
||||
// Probe every point in a rectangular grid
|
||||
// You must specify the rectangle, and the density of sample points
|
||||
// This mode is preferred because there are more measurements.
|
||||
// It used to be called ACCURATE_BED_LEVELING but "grid" is more descriptive
|
||||
|
||||
// - "3-point" mode
|
||||
// Probe 3 arbitrary points on the bed (that aren't colinear)
|
||||
// You must specify the X & Y coordinates of all 3 points
|
||||
|
||||
#define AUTO_BED_LEVELING_GRID
|
||||
// with AUTO_BED_LEVELING_GRID, the bed is sampled in a
|
||||
// AUTO_BED_LEVELING_GRID_POINTSxAUTO_BED_LEVELING_GRID_POINTS grid
|
||||
// and least squares solution is calculated
|
||||
// Note: this feature occupies 10'206 byte
|
||||
#ifdef AUTO_BED_LEVELING_GRID
|
||||
|
||||
// set the rectangle in which to probe
|
||||
#define LEFT_PROBE_BED_POSITION 15
|
||||
#define RIGHT_PROBE_BED_POSITION 170
|
||||
#define BACK_PROBE_BED_POSITION 180
|
||||
#define FRONT_PROBE_BED_POSITION 20
|
||||
|
||||
// set the number of grid points per dimension
|
||||
// I wouldn't see a reason to go above 3 (=9 probing points on the bed)
|
||||
#define AUTO_BED_LEVELING_GRID_POINTS 2
|
||||
|
||||
|
||||
#else // not AUTO_BED_LEVELING_GRID
|
||||
// with no grid, just probe 3 arbitrary points. A simple cross-product
|
||||
// is used to esimate the plane of the print bed
|
||||
|
||||
#define ABL_PROBE_PT_1_X 15
|
||||
#define ABL_PROBE_PT_1_Y 180
|
||||
#define ABL_PROBE_PT_2_X 15
|
||||
#define ABL_PROBE_PT_2_Y 20
|
||||
#define ABL_PROBE_PT_3_X 170
|
||||
#define ABL_PROBE_PT_3_Y 20
|
||||
|
||||
#endif // AUTO_BED_LEVELING_GRID
|
||||
|
||||
|
||||
// these are the offsets to the probe relative to the extruder tip (Hotend - Probe)
|
||||
// X and Y offsets must be integers
|
||||
#define X_PROBE_OFFSET_FROM_EXTRUDER -25
|
||||
#define Y_PROBE_OFFSET_FROM_EXTRUDER -29
|
||||
#define Z_PROBE_OFFSET_FROM_EXTRUDER -12.35
|
||||
|
||||
#define Z_RAISE_BEFORE_HOMING 5 // (in mm) Raise Z before homing (G28) for Probe Clearance.
|
||||
// Be sure you have this distance over your Z_MAX_POS in case
|
||||
|
||||
#define XY_TRAVEL_SPEED 8000 // X and Y axis travel speed between probes, in mm/min
|
||||
|
||||
#define Z_RAISE_BEFORE_PROBING 15 //How much the extruder will be raised before traveling to the first probing point.
|
||||
#define Z_RAISE_BETWEEN_PROBINGS 5 //How much the extruder will be raised when traveling from between next probing points
|
||||
|
||||
//#define Z_PROBE_SLED // turn on if you have a z-probe mounted on a sled like those designed by Charles Bell
|
||||
//#define SLED_DOCKING_OFFSET 5 // the extra distance the X axis must travel to pickup the sled. 0 should be fine but you can push it further if you'd like.
|
||||
|
||||
//If defined, the Probe servo will be turned on only during movement and then turned off to avoid jerk
|
||||
//The value is the delay to turn the servo off after powered on - depends on the servo speed; 300ms is good value, but you can try lower it.
|
||||
// You MUST HAVE the SERVO_ENDSTOPS defined to use here a value higher than zero otherwise your code will not compile.
|
||||
|
||||
// #define PROBE_SERVO_DEACTIVATION_DELAY 300
|
||||
|
||||
|
||||
//If you have enabled the Bed Auto Leveling and are using the same Z Probe for Z Homing,
|
||||
//it is highly recommended you let this Z_SAFE_HOMING enabled!
|
||||
|
||||
//#define Z_SAFE_HOMING // This feature is meant to avoid Z homing with probe outside the bed area.
|
||||
// When defined, it will:
|
||||
// - Allow Z homing only after X and Y homing AND stepper drivers still enabled
|
||||
// - If stepper drivers timeout, it will need X and Y homing again before Z homing
|
||||
// - Position the probe in a defined XY point before Z Homing when homing all axis (G28)
|
||||
// - Block Z homing only when the probe is outside bed area.
|
||||
|
||||
#ifdef Z_SAFE_HOMING
|
||||
|
||||
#define Z_SAFE_HOMING_X_POINT (X_MAX_LENGTH/2) // X point for Z homing when homing all axis (G28)
|
||||
#define Z_SAFE_HOMING_Y_POINT (Y_MAX_LENGTH/2) // Y point for Z homing when homing all axis (G28)
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef AUTO_BED_LEVELING_GRID // Check if Probe_Offset * Grid Points is greater than Probing Range
|
||||
#if X_PROBE_OFFSET_FROM_EXTRUDER < 0
|
||||
#if (-(X_PROBE_OFFSET_FROM_EXTRUDER * AUTO_BED_LEVELING_GRID_POINTS) >= (RIGHT_PROBE_BED_POSITION - LEFT_PROBE_BED_POSITION))
|
||||
#error "The X axis probing range is not enough to fit all the points defined in AUTO_BED_LEVELING_GRID_POINTS"
|
||||
#endif
|
||||
#else
|
||||
#if ((X_PROBE_OFFSET_FROM_EXTRUDER * AUTO_BED_LEVELING_GRID_POINTS) >= (RIGHT_PROBE_BED_POSITION - LEFT_PROBE_BED_POSITION))
|
||||
#error "The X axis probing range is not enough to fit all the points defined in AUTO_BED_LEVELING_GRID_POINTS"
|
||||
#endif
|
||||
#endif
|
||||
#if Y_PROBE_OFFSET_FROM_EXTRUDER < 0
|
||||
#if (-(Y_PROBE_OFFSET_FROM_EXTRUDER * AUTO_BED_LEVELING_GRID_POINTS) >= (BACK_PROBE_BED_POSITION - FRONT_PROBE_BED_POSITION))
|
||||
#error "The Y axis probing range is not enough to fit all the points defined in AUTO_BED_LEVELING_GRID_POINTS"
|
||||
#endif
|
||||
#else
|
||||
#if ((Y_PROBE_OFFSET_FROM_EXTRUDER * AUTO_BED_LEVELING_GRID_POINTS) >= (BACK_PROBE_BED_POSITION - FRONT_PROBE_BED_POSITION))
|
||||
#error "The Y axis probing range is not enough to fit all the points defined in AUTO_BED_LEVELING_GRID_POINTS"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#endif // ENABLE_AUTO_BED_LEVELING
|
||||
|
||||
|
||||
// The position of the homing switches
|
||||
//#define MANUAL_HOME_POSITIONS // If defined, MANUAL_*_HOME_POS below will be used
|
||||
//#define BED_CENTER_AT_0_0 // If defined, the center of the bed is at (X=0, Y=0)
|
||||
|
|
@ -291,6 +424,13 @@ your extruder heater takes 2 minutes to hit the target on heating.
|
|||
//Manual homing switch locations:
|
||||
// For deltabots this means top and center of the Cartesian print volume.
|
||||
|
||||
|
||||
// Offset of the extruders (uncomment if using more than one and relying on firmware to position when changing).
|
||||
// The offset has to be X=0, Y=0 for the extruder 0 hotend (default extruder).
|
||||
// For the other hotends it is their distance from the extruder 0 hotend.
|
||||
// #define EXTRUDER_OFFSET_X {0.0, 20.00} // (in mm) for each extruder, offset of the hotend on the X axis
|
||||
// #define EXTRUDER_OFFSET_Y {0.0, 5.00} // (in mm) for each extruder, offset of the hotend on the Y axis
|
||||
|
||||
// The speed change that does not require acceleration (i.e. the software might assume it can be done instantaneously)
|
||||
#define DEFAULT_XJERK 10 // (mm/sec)
|
||||
#define DEFAULT_YJERK 10 // (mm/sec)
|
||||
|
|
@ -301,6 +441,26 @@ your extruder heater takes 2 minutes to hit the target on heating.
|
|||
//=============================Additional Features===========================
|
||||
//===========================================================================
|
||||
|
||||
// Custom M code points
|
||||
#define CUSTOM_M_CODES
|
||||
#ifdef CUSTOM_M_CODES
|
||||
#define CUSTOM_M_CODE_SET_Z_PROBE_OFFSET 851
|
||||
#define Z_PROBE_OFFSET_RANGE_MIN -15
|
||||
#define Z_PROBE_OFFSET_RANGE_MAX -5
|
||||
#endif
|
||||
|
||||
|
||||
// EEPROM
|
||||
// The microcontroller can store settings in the EEPROM, e.g. max velocity...
|
||||
// M500 - stores parameters in EEPROM
|
||||
// M501 - reads parameters from EEPROM (if you need reset them after you changed them temporarily).
|
||||
// M502 - reverts to the default "factory settings". You still need to store them in EEPROM afterwards if you want to.
|
||||
//define this to enable EEPROM support
|
||||
//#define EEPROM_SETTINGS
|
||||
//to disable EEPROM Serial responses and decrease program space by ~1700 byte: comment this out:
|
||||
// please keep turned on if you can.
|
||||
//#define EEPROM_CHITCHAT
|
||||
|
||||
// Host Keepalive
|
||||
//
|
||||
// When enabled Marlin will send a busy status message to the host
|
||||
|
|
@ -324,15 +484,16 @@ your extruder heater takes 2 minutes to hit the target on heating.
|
|||
#define SDSUPPORT
|
||||
#define LCD_WIDTH 20
|
||||
#define LCD_HEIGHT 4
|
||||
#define LCD_BACKLIGHT_LEVEL_HIGH 130
|
||||
#define LCD_BACKLIGHT_LEVEL_LOW 50
|
||||
#define LCD_BACKLIGHT_FORCE_ON 30
|
||||
#define LCD_BACKLIGHT_TIMEOUT 15
|
||||
|
||||
|
||||
// Increase the FAN pwm frequency. Removes the PWM noise but increases heating in the FET/Arduino
|
||||
//#define FAST_PWM_FAN
|
||||
|
||||
// Temperature status LEDs that display the hotend and bet temperature.
|
||||
// If all hotends and bed temperature and temperature setpoint are < 54C then the BLUE led is on.
|
||||
// Otherwise the RED led is on. There is 1C hysteresis.
|
||||
//#define TEMP_STAT_LEDS
|
||||
|
||||
// Use software PWM to drive the fan, as for the heaters. This uses a very low frequency
|
||||
// which is not ass annoying as with the hardware PWM. On the other hand, if this frequency
|
||||
// is too low, you should also increment SOFT_PWM_SCALE.
|
||||
|
|
@ -358,16 +519,56 @@ your extruder heater takes 2 minutes to hit the target on heating.
|
|||
//define BlinkM/CyzRgb Support
|
||||
//#define BLINKM
|
||||
|
||||
/*********************************************************************\
|
||||
* R/C SERVO support
|
||||
* Sponsored by TrinityLabs, Reworked by codexmas
|
||||
**********************************************************************/
|
||||
|
||||
// Number of servos
|
||||
//
|
||||
// If you select a configuration below, this will receive a default value and does not need to be set manually
|
||||
// set it manually if you have more servos than extruders and wish to manually control some
|
||||
// leaving it undefined or defining as 0 will disable the servo subsystem
|
||||
// If unsure, leave commented / disabled
|
||||
//
|
||||
//#define NUM_SERVOS 3 // Servo index starts with 0 for M280 command
|
||||
|
||||
#define DEFAULT_NOMINAL_FILAMENT_DIA 1.75 //Enter the diameter (in mm) of the filament generally used (3.0 mm or 1.75 mm). Used by the volumetric extrusion.
|
||||
|
||||
// Calibration status of the machine, to be stored into the EEPROM,
|
||||
// (unsigned char*)EEPROM_CALIBRATION_STATUS
|
||||
enum CalibrationStatus
|
||||
{
|
||||
// Freshly assembled, needs to peform a self-test and the XYZ calibration.
|
||||
CALIBRATION_STATUS_ASSEMBLED = 255,
|
||||
|
||||
// For the wizard: self test has been performed, now the XYZ calibration is needed.
|
||||
CALIBRATION_STATUS_XYZ_CALIBRATION = 250,
|
||||
|
||||
// For the wizard: factory assembled, needs to run Z calibration.
|
||||
CALIBRATION_STATUS_Z_CALIBRATION = 240,
|
||||
|
||||
// The XYZ calibration has been performed, now it remains to run the V2Calibration.gcode.
|
||||
CALIBRATION_STATUS_LIVE_ADJUST = 230,
|
||||
|
||||
// Calibrated, ready to print.
|
||||
CALIBRATION_STATUS_CALIBRATED = 1,
|
||||
|
||||
// Legacy: resetted by issuing a G86 G-code.
|
||||
// This value can only be expected after an upgrade from the initial MK2 firmware releases.
|
||||
// Currently the G86 sets the calibration status to
|
||||
CALIBRATION_STATUS_UNKNOWN = 0,
|
||||
};
|
||||
|
||||
// Try to maintain a minimum distance from the bed even when Z is
|
||||
// unknown when doing the following operations
|
||||
#define MIN_Z_FOR_LOAD 35 // lcd filament loading or autoload (values for load and unload have been unified to prevent movement between unload & load operations!)
|
||||
#define MIN_Z_FOR_UNLOAD 35 // lcd filament unloading
|
||||
#define MIN_Z_FOR_LOAD 50 // lcd filament loading or autoload
|
||||
#define MIN_Z_FOR_UNLOAD 50 // lcd filament unloading
|
||||
#define MIN_Z_FOR_SWAP 27 // filament change (including M600)
|
||||
#define MIN_Z_FOR_PREHEAT 10 // lcd preheat
|
||||
|
||||
#include "Configuration_adv.h"
|
||||
#include "thermistortables.h"
|
||||
|
||||
|
||||
#endif //__CONFIGURATION_H
|
||||
|
|
|
|||
|
|
@ -3,41 +3,111 @@
|
|||
#include "Marlin.h"
|
||||
#include "planner.h"
|
||||
#include "temperature.h"
|
||||
#include "ultralcd.h"
|
||||
#include "ConfigurationStore.h"
|
||||
#include "Configuration_var.h"
|
||||
#include "Configuration_prusa.h"
|
||||
|
||||
#ifdef MESH_BED_LEVELING
|
||||
#include "mesh_bed_leveling.h"
|
||||
#endif
|
||||
|
||||
#ifdef TMC2130
|
||||
#include "tmc2130.h"
|
||||
#endif
|
||||
|
||||
|
||||
M500_conf cs;
|
||||
|
||||
//! @brief Write data to EEPROM
|
||||
//! @param pos destination in EEPROM, 0 is start
|
||||
//! @param value value to be written
|
||||
//! @param size size of type pointed by value
|
||||
//! @param name name of variable written, used only for debug input if DEBUG_EEPROM_WRITE defined
|
||||
//! @retval true success
|
||||
//! @retval false failed
|
||||
#ifdef DEBUG_EEPROM_WRITE
|
||||
static bool EEPROM_writeData(uint8_t* pos, uint8_t* value, uint8_t size, const char* name)
|
||||
#else //DEBUG_EEPROM_WRITE
|
||||
static bool EEPROM_writeData(uint8_t* pos, uint8_t* value, uint8_t size, const char*)
|
||||
#endif //DEBUG_EEPROM_WRITE
|
||||
{
|
||||
#ifdef DEBUG_EEPROM_WRITE
|
||||
printf_P(PSTR("EEPROM_WRITE_VAR addr=0x%04x size=0x%02hhx name=%s\n"), pos, size, name);
|
||||
#endif //DEBUG_EEPROM_WRITE
|
||||
while (size--)
|
||||
{
|
||||
|
||||
eeprom_update_byte(pos, *value);
|
||||
if (eeprom_read_byte(pos) != *value) {
|
||||
SERIAL_ECHOLNPGM("EEPROM Error");
|
||||
return false;
|
||||
}
|
||||
|
||||
pos++;
|
||||
value++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_EEPROM_READ
|
||||
static void EEPROM_readData(uint8_t* pos, uint8_t* value, uint8_t size, const char* name)
|
||||
#else //DEBUG_EEPROM_READ
|
||||
static void EEPROM_readData(uint8_t* pos, uint8_t* value, uint8_t size, const char*)
|
||||
#endif //DEBUG_EEPROM_READ
|
||||
{
|
||||
#ifdef DEBUG_EEPROM_READ
|
||||
printf_P(PSTR("EEPROM_READ_VAR addr=0x%04x size=0x%02hhx name=%s\n"), pos, size, name);
|
||||
#endif //DEBUG_EEPROM_READ
|
||||
while(size--)
|
||||
{
|
||||
*value = eeprom_read_byte(pos);
|
||||
pos++;
|
||||
value++;
|
||||
}
|
||||
}
|
||||
|
||||
#define EEPROM_VERSION "V2"
|
||||
|
||||
#ifdef EEPROM_SETTINGS
|
||||
void Config_StoreSettings()
|
||||
{
|
||||
strcpy(cs.version,"000"); //!< invalidate data first @TODO use erase to save one erase cycle
|
||||
|
||||
if (EEPROM_writeData(reinterpret_cast<uint8_t*>(EEPROM_M500_base),reinterpret_cast<uint8_t*>(&cs),sizeof(cs),0), "cs, invalid version")
|
||||
{
|
||||
strcpy(cs.version,EEPROM_VERSION); //!< validate data if write succeed
|
||||
EEPROM_writeData(reinterpret_cast<uint8_t*>(EEPROM_M500_base->version), reinterpret_cast<uint8_t*>(cs.version), sizeof(cs.version), "cs.version valid");
|
||||
}
|
||||
|
||||
SERIAL_ECHO_START;
|
||||
SERIAL_ECHOLNPGM("Settings Stored");
|
||||
}
|
||||
#endif //EEPROM_SETTINGS
|
||||
|
||||
|
||||
#ifndef DISABLE_M503
|
||||
void Config_PrintSettings(uint8_t level)
|
||||
{ // Always have this function, even with EEPROM_SETTINGS disabled, the current values will be shown
|
||||
#ifdef TMC2130
|
||||
printf_P(PSTR(
|
||||
"%SSteps per unit:\n%S M92 X%.2f Y%.2f Z%.2f E%.2f\n"
|
||||
printf_P(PSTR(
|
||||
"%SSteps per unit:\n%S M92 X%.2f Y%.2f Z%.2f E%.2f\n"
|
||||
"%SUStep resolution: \n%S M350 X%d Y%d Z%d E%d\n"
|
||||
"%SMaximum feedrates - normal (mm/s):\n%S M203 X%.2f Y%.2f Z%.2f E%.2f\n"
|
||||
"%SMaximum feedrates - stealth (mm/s):\n%S M203 X%.2f Y%.2f Z%.2f E%.2f\n"
|
||||
"%SMaximum acceleration - normal (mm/s2):\n%S M201 X%lu Y%lu Z%lu E%lu\n"
|
||||
"%SMaximum acceleration - stealth (mm/s2):\n%S M201 X%lu Y%lu Z%lu E%lu\n"
|
||||
"%SAcceleration: P=print, R=retract, T=travel\n%S M204 P%.2f R%.2f T%.2f\n"
|
||||
"%SAdvanced variables: S=Min feedrate (mm/s), T=Min travel feedrate (mm/s), B=minimum segment time (us), X=maximum XY jerk (mm/s), Z=maximum Z jerk (mm/s), E=maximum E jerk (mm/s)\n%S M205 S%.2f T%.2f B%lu X%.2f Y%.2f Z%.2f E%.2f\n"
|
||||
"%SAdvanced variables: S=Min feedrate (mm/s), T=Min travel feedrate (mm/s), B=minimum segment time (ms), X=maximum XY jerk (mm/s), Z=maximum Z jerk (mm/s), E=maximum E jerk (mm/s)\n%S M205 S%.2f T%.2f B%.2f X%.2f Y%.2f Z%.2f E%.2f\n"
|
||||
"%SHome offset (mm):\n%S M206 X%.2f Y%.2f Z%.2f\n"
|
||||
),
|
||||
echomagic, echomagic, cs.axis_steps_per_mm[X_AXIS], cs.axis_steps_per_mm[Y_AXIS], cs.axis_steps_per_mm[Z_AXIS], cs.axis_steps_per_mm[E_AXIS],
|
||||
echomagic, echomagic, cs.axis_steps_per_unit[X_AXIS], cs.axis_steps_per_unit[Y_AXIS], cs.axis_steps_per_unit[Z_AXIS], cs.axis_steps_per_unit[E_AXIS],
|
||||
echomagic, echomagic, cs.axis_ustep_resolution[X_AXIS], cs.axis_ustep_resolution[Y_AXIS], cs.axis_ustep_resolution[Z_AXIS], cs.axis_ustep_resolution[E_AXIS],
|
||||
echomagic, echomagic, cs.max_feedrate_normal[X_AXIS], cs.max_feedrate_normal[Y_AXIS], cs.max_feedrate_normal[Z_AXIS], cs.max_feedrate_normal[E_AXIS],
|
||||
echomagic, echomagic, cs.max_feedrate_silent[X_AXIS], cs.max_feedrate_silent[Y_AXIS], cs.max_feedrate_silent[Z_AXIS], cs.max_feedrate_silent[E_AXIS],
|
||||
echomagic, echomagic, cs.max_acceleration_mm_per_s2_normal[X_AXIS], cs.max_acceleration_mm_per_s2_normal[Y_AXIS], cs.max_acceleration_mm_per_s2_normal[Z_AXIS], cs.max_acceleration_mm_per_s2_normal[E_AXIS],
|
||||
echomagic, echomagic, cs.max_acceleration_mm_per_s2_silent[X_AXIS], cs.max_acceleration_mm_per_s2_silent[Y_AXIS], cs.max_acceleration_mm_per_s2_silent[Z_AXIS], cs.max_acceleration_mm_per_s2_silent[E_AXIS],
|
||||
echomagic, echomagic, cs.max_acceleration_units_per_sq_second_normal[X_AXIS], cs.max_acceleration_units_per_sq_second_normal[Y_AXIS], cs.max_acceleration_units_per_sq_second_normal[Z_AXIS], cs.max_acceleration_units_per_sq_second_normal[E_AXIS],
|
||||
echomagic, echomagic, cs.max_acceleration_units_per_sq_second_silent[X_AXIS], cs.max_acceleration_units_per_sq_second_silent[Y_AXIS], cs.max_acceleration_units_per_sq_second_silent[Z_AXIS], cs.max_acceleration_units_per_sq_second_silent[E_AXIS],
|
||||
echomagic, echomagic, cs.acceleration, cs.retract_acceleration, cs.travel_acceleration,
|
||||
echomagic, echomagic, cs.minimumfeedrate, cs.mintravelfeedrate, cs.min_segment_time_us, cs.max_jerk[X_AXIS], cs.max_jerk[Y_AXIS], cs.max_jerk[Z_AXIS], cs.max_jerk[E_AXIS],
|
||||
echomagic, echomagic, cs.minimumfeedrate, cs.mintravelfeedrate, cs.minsegmenttime, cs.max_jerk[X_AXIS], cs.max_jerk[Y_AXIS], cs.max_jerk[Z_AXIS], cs.max_jerk[E_AXIS],
|
||||
echomagic, echomagic, cs.add_homing[X_AXIS], cs.add_homing[Y_AXIS], cs.add_homing[Z_AXIS]
|
||||
#else //TMC2130
|
||||
printf_P(PSTR(
|
||||
|
|
@ -45,70 +115,60 @@ void Config_PrintSettings(uint8_t level)
|
|||
"%SMaximum feedrates (mm/s):\n%S M203 X%.2f Y%.2f Z%.2f E%.2f\n"
|
||||
"%SMaximum acceleration (mm/s2):\n%S M201 X%lu Y%lu Z%lu E%lu\n"
|
||||
"%SAcceleration: P=print, R=retract, T=travel\n%S M204 P%.2f R%.2f T%.2f\n"
|
||||
"%SAdvanced variables: S=Min feedrate (mm/s), T=Min travel feedrate (mm/s), B=minimum segment time (us), X=maximum XY jerk (mm/s), Z=maximum Z jerk (mm/s), E=maximum E jerk (mm/s)\n%S M205 S%.2f T%.2f B%lu X%.2f Y%.2f Z%.2f E%.2f\n"
|
||||
"%SAdvanced variables: S=Min feedrate (mm/s), T=Min travel feedrate (mm/s), B=minimum segment time (ms), X=maximum XY jerk (mm/s), Z=maximum Z jerk (mm/s), E=maximum E jerk (mm/s)\n%S M205 S%.2f T%.2f B%.2f X%.2f Y%.2f Z%.2f E%.2f\n"
|
||||
"%SHome offset (mm):\n%S M206 X%.2f Y%.2f Z%.2f\n"
|
||||
),
|
||||
echomagic, echomagic, cs.axis_steps_per_mm[X_AXIS], cs.axis_steps_per_mm[Y_AXIS], cs.axis_steps_per_mm[Z_AXIS], cs.axis_steps_per_mm[E_AXIS],
|
||||
echomagic, echomagic, cs.axis_steps_per_unit[X_AXIS], cs.axis_steps_per_unit[Y_AXIS], cs.axis_steps_per_unit[Z_AXIS], cs.axis_steps_per_unit[E_AXIS],
|
||||
echomagic, echomagic, max_feedrate[X_AXIS], max_feedrate[Y_AXIS], max_feedrate[Z_AXIS], max_feedrate[E_AXIS],
|
||||
echomagic, echomagic, max_acceleration_mm_per_s2[X_AXIS], max_acceleration_mm_per_s2[Y_AXIS], max_acceleration_mm_per_s2[Z_AXIS], max_acceleration_mm_per_s2[E_AXIS],
|
||||
echomagic, echomagic, max_acceleration_units_per_sq_second[X_AXIS], max_acceleration_units_per_sq_second[Y_AXIS], max_acceleration_units_per_sq_second[Z_AXIS], max_acceleration_units_per_sq_second[E_AXIS],
|
||||
echomagic, echomagic, cs.acceleration, cs.retract_acceleration, cs.travel_acceleration,
|
||||
echomagic, echomagic, cs.minimumfeedrate, cs.mintravelfeedrate, cs.min_segment_time_us, cs.max_jerk[X_AXIS], cs.max_jerk[Y_AXIS], cs.max_jerk[Z_AXIS], cs.max_jerk[E_AXIS],
|
||||
echomagic, echomagic, cs.minimumfeedrate, cs.mintravelfeedrate, cs.minsegmenttime, cs.max_jerk[X_AXIS], cs.max_jerk[Y_AXIS], cs.max_jerk[Z_AXIS], cs.max_jerk[E_AXIS],
|
||||
echomagic, echomagic, cs.add_homing[X_AXIS], cs.add_homing[Y_AXIS], cs.add_homing[Z_AXIS]
|
||||
#endif //TMC2130
|
||||
);
|
||||
);
|
||||
#ifdef PIDTEMP
|
||||
printf_P(PSTR("%SPID settings:\n%S M301 P%.2f I%.2f D%.2f\n"),
|
||||
echomagic, echomagic, cs.Kp, unscalePID_i(cs.Ki), unscalePID_d(cs.Kd));
|
||||
printf_P(PSTR("%SPID settings:\n%S M301 P%.2f I%.2f D%.2f\n"),
|
||||
echomagic, echomagic, cs.Kp, unscalePID_i(cs.Ki), unscalePID_d(cs.Kd));
|
||||
#endif
|
||||
#ifdef PIDTEMPBED
|
||||
printf_P(PSTR("%SPID heatbed settings:\n%S M304 P%.2f I%.2f D%.2f\n"),
|
||||
echomagic, echomagic, cs.bedKp, unscalePID_i(cs.bedKi), unscalePID_d(cs.bedKd));
|
||||
printf_P(PSTR("%SPID heatbed settings:\n%S M304 P%.2f I%.2f D%.2f\n"),
|
||||
echomagic, echomagic, cs.bedKp, unscalePID_i(cs.bedKi), unscalePID_d(cs.bedKd));
|
||||
#endif
|
||||
#ifdef FWRETRACT
|
||||
printf_P(PSTR(
|
||||
"%SRetract: S=Length (mm) F:Speed (mm/m) Z: ZLift (mm)\n%S M207 S%.2f F%.2f Z%.2f\n"
|
||||
"%SRecover: S=Extra length (mm) F:Speed (mm/m)\n%S M208 S%.2f F%.2f\n"
|
||||
"%SAuto-Retract: S=0 to disable, 1 to interpret extrude-only moves as retracts or recoveries\n%S M209 S%d\n"
|
||||
),
|
||||
echomagic, echomagic, cs.retract_length, cs.retract_feedrate*60, cs.retract_zlift,
|
||||
echomagic, echomagic, cs.retract_recover_length, cs.retract_recover_feedrate*60,
|
||||
echomagic, echomagic, (cs.autoretract_enabled ? 1 : 0)
|
||||
);
|
||||
printf_P(PSTR(
|
||||
"%SRetract: S=Length (mm) F:Speed (mm/m) Z: ZLift (mm)\n%S M207 S%.2f F%.2f Z%.2f\n"
|
||||
"%SRecover: S=Extra length (mm) F:Speed (mm/m)\n%S M208 S%.2f F%.2f\n"
|
||||
"%SAuto-Retract: S=0 to disable, 1 to interpret extrude-only moves as retracts or recoveries\n%S M209 S%d\n"
|
||||
),
|
||||
echomagic, echomagic, cs.retract_length, cs.retract_feedrate*60, cs.retract_zlift,
|
||||
echomagic, echomagic, cs.retract_recover_length, cs.retract_recover_feedrate*60,
|
||||
echomagic, echomagic, (cs.autoretract_enabled ? 1 : 0)
|
||||
);
|
||||
#if EXTRUDERS > 1
|
||||
printf_P(PSTR("%SMulti-extruder settings:\n%S Swap retract length (mm): %.2f\n%S Swap rec. addl. length (mm): %.2f\n"),
|
||||
echomagic, echomagic, retract_length_swap, echomagic, retract_recover_length_swap);
|
||||
printf_P(PSTR("%SMulti-extruder settings:\n%S Swap retract length (mm): %.2f\n%S Swap rec. addl. length (mm): %.2f\n"),
|
||||
echomagic, echomagic, retract_length_swap, echomagic, retract_recover_length_swap);
|
||||
#endif
|
||||
if (cs.volumetric_enabled) {
|
||||
printf_P(PSTR("%SFilament settings:\n%S M200 D%.2f\n"),
|
||||
echomagic, echomagic, cs.filament_size[0]);
|
||||
if (cs.volumetric_enabled) {
|
||||
printf_P(PSTR("%SFilament settings:\n%S M200 D%.2f\n"),
|
||||
echomagic, echomagic, cs.filament_size[0]);
|
||||
#if EXTRUDERS > 1
|
||||
printf_P(PSTR("%S M200 T1 D%.2f\n"),
|
||||
echomagic, echomagic, cs.filament_size[1]);
|
||||
printf_P(PSTR("%S M200 T1 D%.2f\n"),
|
||||
echomagic, echomagic, cs.filament_size[1]);
|
||||
#if EXTRUDERS > 2
|
||||
printf_P(PSTR("%S M200 T1 D%.2f\n"),
|
||||
echomagic, echomagic, cs.filament_size[2]);
|
||||
printf_P(PSTR("%S M200 T1 D%.2f\n"),
|
||||
echomagic, echomagic, cs.filament_size[2]);
|
||||
#endif
|
||||
#endif
|
||||
} else {
|
||||
printf_P(PSTR("%SFilament settings: Disabled\n"), echomagic);
|
||||
}
|
||||
#endif
|
||||
if (level >= 10) {
|
||||
if (level >= 10) {
|
||||
#ifdef LIN_ADVANCE
|
||||
printf_P(PSTR("%SLinear advance settings:%S M900 K%.2f\n"),
|
||||
printf_P(PSTR("%SLinear advance settings:%S M900 K%.2f\n"),
|
||||
echomagic, echomagic, extruder_advance_K);
|
||||
#endif //LIN_ADVANCE
|
||||
}
|
||||
// Arc Interpolation Settings
|
||||
printf_P(PSTR(
|
||||
"%SArc Settings: P:Max length(mm) S:Min length (mm) N:Corrections R:Min segments F:Segments/sec.\n%S M214 P%.2f S%.2f N%d R%d F%d\n"),
|
||||
echomagic, echomagic, cs.mm_per_arc_segment, cs.min_mm_per_arc_segment, cs.n_arc_correction, cs.min_arc_segments, cs.arc_segments_per_sec);
|
||||
#ifdef THERMAL_MODEL
|
||||
thermal_model_report_settings();
|
||||
#endif
|
||||
printf_P(PSTR(
|
||||
"%SStatistics:\n%S M78 S%lu T%lu\n"),
|
||||
echomagic, echomagic, eeprom_read_dword((uint32_t *)EEPROM_FILAMENTUSED), eeprom_read_dword((uint32_t *)EEPROM_TOTALTIME));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -117,10 +177,14 @@ void Config_PrintSettings(uint8_t level)
|
|||
|
||||
static_assert (EXTRUDERS == 1, "ConfigurationStore M500_conf not implemented for more extruders, fix filament_size array size.");
|
||||
static_assert (NUM_AXIS == 4, "ConfigurationStore M500_conf not implemented for more axis."
|
||||
"Fix axis_steps_per_mm max_feedrate_normal max_acceleration_mm_per_s2_normal max_jerk max_feedrate_silent"
|
||||
" max_acceleration_mm_per_s2_silent array size.");
|
||||
"Fix axis_steps_per_unit max_feedrate_normal max_acceleration_units_per_sq_second_normal max_jerk max_feedrate_silent"
|
||||
" max_acceleration_units_per_sq_second_silent array size.");
|
||||
#ifdef ENABLE_AUTO_BED_LEVELING
|
||||
static_assert (false, "zprobe_zoffset was not initialized in printers in field to -(Z_PROBE_OFFSET_FROM_EXTRUDER), so it contains"
|
||||
"0.0, if this is not acceptable, increment EEPROM_VERSION to force use default_conf");
|
||||
#endif
|
||||
|
||||
static_assert (sizeof(M500_conf) == 209, "sizeof(M500_conf) has changed, ensure that EEPROM_VERSION has been incremented, "
|
||||
static_assert (sizeof(M500_conf) == 196, "sizeof(M500_conf) has changed, ensure that EEPROM_VERSION has been incremented, "
|
||||
"or if you added members in the end of struct, ensure that historically uninitialized values will be initialized."
|
||||
"If this is caused by change to more then 8bit processor, decide whether make this struct packed to save EEPROM,"
|
||||
"leave as it is to keep fast code, or reorder struct members to pack more tightly.");
|
||||
|
|
@ -169,98 +233,101 @@ static const M500_conf default_conf PROGMEM =
|
|||
{16,16,16,16},
|
||||
#endif
|
||||
DEFAULT_TRAVEL_ACCELERATION,
|
||||
DEFAULT_MM_PER_ARC_SEGMENT,
|
||||
DEFAULT_MIN_MM_PER_ARC_SEGMENT,
|
||||
DEFAULT_N_ARC_CORRECTION,
|
||||
DEFAULT_MIN_ARC_SEGMENTS,
|
||||
DEFAULT_ARC_SEGMENTS_PER_SEC
|
||||
};
|
||||
|
||||
|
||||
void Config_StoreSettings()
|
||||
static bool is_uninitialized(void* addr, uint8_t len)
|
||||
{
|
||||
strcpy_P(cs.version, default_conf.version);
|
||||
eeprom_update_block_notify(reinterpret_cast<uint8_t*>(&cs), reinterpret_cast<uint8_t*>(EEPROM_M500_base), sizeof(cs));
|
||||
#ifdef THERMAL_MODEL
|
||||
thermal_model_save_settings();
|
||||
#endif
|
||||
|
||||
SERIAL_ECHO_START;
|
||||
SERIAL_ECHOLNPGM("Settings Stored");
|
||||
while(len--)
|
||||
{
|
||||
if(reinterpret_cast<uint8_t*>(addr)[len] != 0xff)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//! @brief Read M500 configuration
|
||||
//! @retval true Succeeded. Stored settings retrieved or default settings retrieved in case EEPROM cs was empty.
|
||||
//! @retval false Failed. Default settings has been retrieved, because of version mismatch
|
||||
//! @retval true Succeeded. Stored settings retrieved or default settings retrieved in case EEPROM has been erased.
|
||||
//! @retval false Failed. Default settings has been retrieved, because of older version or corrupted data.
|
||||
bool Config_RetrieveSettings()
|
||||
{
|
||||
eeprom_read_block(reinterpret_cast<uint8_t*>(cs.version), reinterpret_cast<uint8_t*>(EEPROM_M500_base->version), sizeof(cs.version));
|
||||
bool previous_settings_retrieved = true;
|
||||
char ver[4]=EEPROM_VERSION;
|
||||
EEPROM_readData(reinterpret_cast<uint8_t*>(EEPROM_M500_base->version), reinterpret_cast<uint8_t*>(cs.version), sizeof(cs.version), "cs.version"); //read stored version
|
||||
// SERIAL_ECHOLN("Version: [" << ver << "] Stored version: [" << cs.version << "]");
|
||||
if (strncmp_P(cs.version, default_conf.version, sizeof(EEPROM_VERSION)) == 0) // version number match
|
||||
if (strncmp(ver,cs.version,3) == 0) // version number match
|
||||
{
|
||||
// Initialize arc interpolation settings in eeprom if they are not already
|
||||
eeprom_init_default_float(&EEPROM_M500_base->mm_per_arc_segment, pgm_read_float(&default_conf.mm_per_arc_segment));
|
||||
eeprom_init_default_float(&EEPROM_M500_base->min_mm_per_arc_segment, pgm_read_float(&default_conf.min_mm_per_arc_segment));
|
||||
eeprom_init_default_byte(&EEPROM_M500_base->n_arc_correction, pgm_read_byte(&default_conf.n_arc_correction));
|
||||
eeprom_init_default_word(&EEPROM_M500_base->min_arc_segments, pgm_read_word(&default_conf.min_arc_segments));
|
||||
eeprom_init_default_word(&EEPROM_M500_base->arc_segments_per_sec, pgm_read_word(&default_conf.arc_segments_per_sec));
|
||||
|
||||
// Initialize the travel_acceleration in eeprom if not already
|
||||
eeprom_init_default_float(&EEPROM_M500_base->travel_acceleration, pgm_read_float(&default_conf.travel_acceleration));
|
||||
EEPROM_readData(reinterpret_cast<uint8_t*>(EEPROM_M500_base), reinterpret_cast<uint8_t*>(&cs), sizeof(cs), "cs");
|
||||
|
||||
// Initialize the max_feedrate_silent and max_acceleration_mm_per_s2_silent in eeprom if not already
|
||||
eeprom_init_default_block(&EEPROM_M500_base->max_feedrate_silent, sizeof(EEPROM_M500_base->max_feedrate_silent), default_conf.max_feedrate_silent);
|
||||
eeprom_init_default_block(&EEPROM_M500_base->max_acceleration_mm_per_s2_silent, sizeof(EEPROM_M500_base->max_acceleration_mm_per_s2_silent), default_conf.max_acceleration_mm_per_s2_silent);
|
||||
|
||||
#ifdef TMC2130
|
||||
eeprom_init_default_block(&EEPROM_M500_base->axis_ustep_resolution, sizeof(EEPROM_M500_base->axis_ustep_resolution), default_conf.axis_ustep_resolution);
|
||||
#endif // TMC2130
|
||||
|
||||
// load the CS to RAM
|
||||
eeprom_read_block(reinterpret_cast<uint8_t*>(&cs), reinterpret_cast<uint8_t*>(EEPROM_M500_base), sizeof(cs));
|
||||
|
||||
if (cs.max_jerk[X_AXIS] > DEFAULT_XJERK) cs.max_jerk[X_AXIS] = DEFAULT_XJERK;
|
||||
if (cs.max_jerk[Y_AXIS] > DEFAULT_YJERK) cs.max_jerk[Y_AXIS] = DEFAULT_YJERK;
|
||||
calculate_extruder_multipliers();
|
||||
|
||||
#ifdef TMC2130
|
||||
for (uint8_t j = X_AXIS; j <= Y_AXIS; j++)
|
||||
{
|
||||
if (cs.max_feedrate_normal[j] > NORMAL_MAX_FEEDRATE_XY)
|
||||
cs.max_feedrate_normal[j] = NORMAL_MAX_FEEDRATE_XY;
|
||||
if (cs.max_feedrate_silent[j] > SILENT_MAX_FEEDRATE_XY)
|
||||
cs.max_feedrate_silent[j] = SILENT_MAX_FEEDRATE_XY;
|
||||
if (cs.max_acceleration_mm_per_s2_normal[j] > NORMAL_MAX_ACCEL_XY)
|
||||
cs.max_acceleration_mm_per_s2_normal[j] = NORMAL_MAX_ACCEL_XY;
|
||||
if (cs.max_acceleration_mm_per_s2_silent[j] > SILENT_MAX_ACCEL_XY)
|
||||
cs.max_acceleration_mm_per_s2_silent[j] = SILENT_MAX_ACCEL_XY;
|
||||
}
|
||||
//if max_feedrate_silent and max_acceleration_units_per_sq_second_silent were never stored to eeprom, use default values:
|
||||
for (uint8_t i = 0; i < (sizeof(cs.max_feedrate_silent)/sizeof(cs.max_feedrate_silent[0])); ++i)
|
||||
{
|
||||
const uint32_t erased = 0xffffffff;
|
||||
if (is_uninitialized(&(cs.max_feedrate_silent[i]), sizeof(float))) {
|
||||
memcpy_P(&cs.max_feedrate_silent[i],&default_conf.max_feedrate_silent[i], sizeof(cs.max_feedrate_silent[i]));
|
||||
}
|
||||
if (erased == cs.max_acceleration_units_per_sq_second_silent[i]) {
|
||||
memcpy_P(&cs.max_acceleration_units_per_sq_second_silent[i],&default_conf.max_acceleration_units_per_sq_second_silent[i],sizeof(cs.max_acceleration_units_per_sq_second_silent[i]));
|
||||
}
|
||||
}
|
||||
|
||||
tmc2130_set_res(X_AXIS, cs.axis_ustep_resolution[X_AXIS]);
|
||||
tmc2130_set_res(Y_AXIS, cs.axis_ustep_resolution[Y_AXIS]);
|
||||
tmc2130_set_res(Z_AXIS, cs.axis_ustep_resolution[Z_AXIS]);
|
||||
tmc2130_set_res(E_AXIS, cs.axis_ustep_resolution[E_AXIS]);
|
||||
#ifdef TMC2130
|
||||
for (uint8_t j = X_AXIS; j <= Y_AXIS; j++)
|
||||
{
|
||||
if (cs.max_feedrate_normal[j] > NORMAL_MAX_FEEDRATE_XY)
|
||||
cs.max_feedrate_normal[j] = NORMAL_MAX_FEEDRATE_XY;
|
||||
if (cs.max_feedrate_silent[j] > SILENT_MAX_FEEDRATE_XY)
|
||||
cs.max_feedrate_silent[j] = SILENT_MAX_FEEDRATE_XY;
|
||||
if (cs.max_acceleration_units_per_sq_second_normal[j] > NORMAL_MAX_ACCEL_XY)
|
||||
cs.max_acceleration_units_per_sq_second_normal[j] = NORMAL_MAX_ACCEL_XY;
|
||||
if (cs.max_acceleration_units_per_sq_second_silent[j] > SILENT_MAX_ACCEL_XY)
|
||||
cs.max_acceleration_units_per_sq_second_silent[j] = SILENT_MAX_ACCEL_XY;
|
||||
}
|
||||
|
||||
if(cs.axis_ustep_resolution[X_AXIS] == 0xff){ cs.axis_ustep_resolution[X_AXIS] = TMC2130_USTEPS_XY; }
|
||||
if(cs.axis_ustep_resolution[Y_AXIS] == 0xff){ cs.axis_ustep_resolution[Y_AXIS] = TMC2130_USTEPS_XY; }
|
||||
if(cs.axis_ustep_resolution[Z_AXIS] == 0xff){ cs.axis_ustep_resolution[Z_AXIS] = TMC2130_USTEPS_Z; }
|
||||
if(cs.axis_ustep_resolution[E_AXIS] == 0xff){ cs.axis_ustep_resolution[E_AXIS] = TMC2130_USTEPS_E; }
|
||||
|
||||
tmc2130_set_res(X_AXIS, cs.axis_ustep_resolution[X_AXIS]);
|
||||
tmc2130_set_res(Y_AXIS, cs.axis_ustep_resolution[Y_AXIS]);
|
||||
tmc2130_set_res(Z_AXIS, cs.axis_ustep_resolution[Z_AXIS]);
|
||||
tmc2130_set_res(E_AXIS, cs.axis_ustep_resolution[E_AXIS]);
|
||||
#endif //TMC2130
|
||||
|
||||
if(is_uninitialized(&cs.travel_acceleration, sizeof(cs.travel_acceleration)))
|
||||
cs.travel_acceleration = cs.acceleration;
|
||||
|
||||
reset_acceleration_rates();
|
||||
|
||||
// Call updatePID (similar to when we have processed M301)
|
||||
updatePID();
|
||||
#ifdef THERMAL_MODEL
|
||||
thermal_model_load_settings();
|
||||
#endif
|
||||
|
||||
// Call updatePID (similar to when we have processed M301)
|
||||
updatePID();
|
||||
SERIAL_ECHO_START;
|
||||
SERIAL_ECHOLNPGM("Stored settings retrieved");
|
||||
}
|
||||
else
|
||||
{
|
||||
Config_ResetDefault();
|
||||
//Return false to inform user that eeprom version was changed and firmware is using default hardcoded settings now.
|
||||
//In case that storing to eeprom was not used yet, do not inform user that hardcoded settings are used.
|
||||
if (eeprom_is_initialized_block(EEPROM_M500_base->version, sizeof(EEPROM_M500_base->version))) {
|
||||
return false;
|
||||
}
|
||||
//Return false to inform user that eeprom version was changed and firmware is using default hardcoded settings now.
|
||||
//In case that storing to eeprom was not used yet, do not inform user that hardcoded settings are used.
|
||||
if (eeprom_read_byte(reinterpret_cast<uint8_t*>(&(EEPROM_M500_base->version[0]))) != 0xFF ||
|
||||
eeprom_read_byte(reinterpret_cast<uint8_t*>(&(EEPROM_M500_base->version[1]))) != 0xFF ||
|
||||
eeprom_read_byte(reinterpret_cast<uint8_t*>(&(EEPROM_M500_base->version[2]))) != 0xFF)
|
||||
{
|
||||
previous_settings_retrieved = false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
#ifdef EEPROM_CHITCHAT
|
||||
Config_PrintSettings();
|
||||
#endif
|
||||
return previous_settings_retrieved;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -268,20 +335,19 @@ void Config_ResetDefault()
|
|||
{
|
||||
memcpy_P(&cs,&default_conf, sizeof(cs));
|
||||
|
||||
// steps per sq second need to be updated to agree with the units per sq second
|
||||
// steps per sq second need to be updated to agree with the units per sq second
|
||||
reset_acceleration_rates();
|
||||
|
||||
|
||||
#ifdef PIDTEMP
|
||||
updatePID();
|
||||
#ifdef PID_ADD_EXTRUSION_RATE
|
||||
Kc = DEFAULT_Kc; //this is not stored by Config_StoreSettings
|
||||
#endif//PID_ADD_EXTRUSION_RATE
|
||||
#endif//PIDTEMP
|
||||
#ifdef THERMAL_MODEL
|
||||
thermal_model_reset_settings();
|
||||
#endif
|
||||
|
||||
calculate_extruder_multipliers();
|
||||
calculate_extruder_multipliers();
|
||||
|
||||
SERIAL_ECHO_START;
|
||||
SERIAL_ECHOLNPGM("Hardcoded Default Settings Loaded");
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,17 +9,17 @@
|
|||
typedef struct
|
||||
{
|
||||
char version[4];
|
||||
float axis_steps_per_mm[4];
|
||||
float axis_steps_per_unit[4];
|
||||
float max_feedrate_normal[4];
|
||||
uint32_t max_acceleration_mm_per_s2_normal[4];
|
||||
unsigned long max_acceleration_units_per_sq_second_normal[4];
|
||||
float acceleration; //!< Normal acceleration mm/s^2 THIS IS THE DEFAULT ACCELERATION for all moves. M204 SXXXX
|
||||
float retract_acceleration; //!< mm/s^2 filament pull-pack and push-forward while standing still in the other axis M204 TXXXX
|
||||
float minimumfeedrate;
|
||||
float mintravelfeedrate;
|
||||
uint32_t min_segment_time_us; //!< (µs) M205 B
|
||||
unsigned long minsegmenttime;
|
||||
float max_jerk[4]; //!< Jerk is a maximum immediate velocity change.
|
||||
float add_homing[3];
|
||||
float zprobe_zoffset; //!< unused
|
||||
float zprobe_zoffset;
|
||||
float Kp;
|
||||
float Ki;
|
||||
float Kd;
|
||||
|
|
@ -36,15 +36,9 @@ typedef struct
|
|||
bool volumetric_enabled;
|
||||
float filament_size[1]; //!< cross-sectional area of filament (in millimeters), typically around 1.75 or 2.85, 0 disables the volumetric calculations for the extruder.
|
||||
float max_feedrate_silent[4]; //!< max speeds for silent mode
|
||||
uint32_t max_acceleration_mm_per_s2_silent[4];
|
||||
unsigned long max_acceleration_units_per_sq_second_silent[4];
|
||||
unsigned char axis_ustep_resolution[4];
|
||||
float travel_acceleration; //!< travel acceleration mm/s^2
|
||||
// Arc Interpolation Settings, configurable via M214
|
||||
float mm_per_arc_segment;
|
||||
float min_mm_per_arc_segment;
|
||||
uint8_t n_arc_correction; // If equal to zero, this is disabled
|
||||
uint16_t min_arc_segments; // If equal to zero, this is disabled
|
||||
uint16_t arc_segments_per_sec; // If equal to zero, this is disabled
|
||||
} M500_conf;
|
||||
|
||||
extern M500_conf cs;
|
||||
|
|
@ -65,4 +59,8 @@ FORCE_INLINE void Config_StoreSettings() {}
|
|||
FORCE_INLINE void Config_RetrieveSettings() { Config_ResetDefault(); Config_PrintSettings(); }
|
||||
#endif
|
||||
|
||||
inline uint8_t calibration_status() { return eeprom_read_byte((uint8_t*)EEPROM_CALIBRATION_STATUS); }
|
||||
inline void calibration_status_store(uint8_t status) { eeprom_update_byte((uint8_t*)EEPROM_CALIBRATION_STATUS, status); }
|
||||
inline bool calibration_status_pinda() { return eeprom_read_byte((uint8_t*)EEPROM_CALIBRATION_STATUS_PINDA); }
|
||||
|
||||
#endif//CONFIG_STORE_H
|
||||
|
|
|
|||
|
|
@ -10,6 +10,16 @@
|
|||
#endif
|
||||
#define BED_CHECK_INTERVAL 5000 //ms between checks in bang-bang control
|
||||
|
||||
#ifdef PIDTEMP
|
||||
// this adds an experimental additional term to the heating power, proportional to the extrusion speed.
|
||||
// if Kc is chosen well, the additional required power due to increased melting should be compensated.
|
||||
#define PID_ADD_EXTRUSION_RATE
|
||||
#ifdef PID_ADD_EXTRUSION_RATE
|
||||
#define DEFAULT_Kc (1) //heating power=Kc*(e_speed)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
//automatic temperature: The hot end target temperature is calculated by all the buffered lines of gcode.
|
||||
//The maximum buffered steps/sec of the extruder motor are called "se".
|
||||
//You enter the autotemp mode by a M109 S<mintemp> B<maxtemp> F<factor>
|
||||
|
|
@ -54,7 +64,7 @@
|
|||
|
||||
/**
|
||||
* Auto-report all at once with M155 S<seconds> C[bitmask] with single timer
|
||||
*
|
||||
*
|
||||
* bit 0 = Auto-report temperatures
|
||||
* bit 1 = Auto-report fans
|
||||
* bit 2 = Auto-report position
|
||||
|
|
@ -66,12 +76,6 @@
|
|||
*/
|
||||
#define AUTO_REPORT
|
||||
|
||||
// Keepalive period which is restarted with M79
|
||||
#define M79_TIMEOUT 30 * 1000 // ms
|
||||
|
||||
// A timer which is restarted everytime a G-command is added to the command queue.
|
||||
#define USB_TIMER_TIMEOUT 10 * 1000 // ms
|
||||
|
||||
//===========================================================================
|
||||
//=============================Mechanical Settings===========================
|
||||
//===========================================================================
|
||||
|
|
@ -125,6 +129,34 @@
|
|||
#endif //End auto min/max positions
|
||||
//END AUTOSET LOCATIONS OF LIMIT SWITCHES -ZP
|
||||
|
||||
|
||||
// A single Z stepper driver is usually used to drive 2 stepper motors.
|
||||
// Uncomment this define to utilize a separate stepper driver for each Z axis motor.
|
||||
// Only a few motherboards support this, like RAMPS, which have dual extruder support (the 2nd, often unused, extruder driver is used
|
||||
// to control the 2nd Z axis stepper motor). The pins are currently only defined for a RAMPS motherboards.
|
||||
// On a RAMPS (or other 5 driver) motherboard, using this feature will limit you to using 1 extruder.
|
||||
//#define Z_DUAL_STEPPER_DRIVERS
|
||||
|
||||
#ifdef Z_DUAL_STEPPER_DRIVERS
|
||||
#undef EXTRUDERS
|
||||
#define EXTRUDERS 1
|
||||
#endif
|
||||
|
||||
// Same again but for Y Axis.
|
||||
//#define Y_DUAL_STEPPER_DRIVERS
|
||||
|
||||
// Define if the two Y drives need to rotate in opposite directions
|
||||
#define INVERT_Y2_VS_Y_DIR 1
|
||||
|
||||
#ifdef Y_DUAL_STEPPER_DRIVERS
|
||||
#undef EXTRUDERS
|
||||
#define EXTRUDERS 1
|
||||
#endif
|
||||
|
||||
#if defined (Z_DUAL_STEPPER_DRIVERS) && defined (Y_DUAL_STEPPER_DRIVERS)
|
||||
#error "You cannot have dual drivers for both Y and Z"
|
||||
#endif
|
||||
|
||||
//homing hits the endstop, then retracts by this distance, before it tries to slowly bump again:
|
||||
#define X_HOME_RETRACT_MM 5
|
||||
#define Y_HOME_RETRACT_MM 5
|
||||
|
|
@ -201,27 +233,23 @@
|
|||
* limit is exceeded.
|
||||
*/
|
||||
#define SDCARD_SORT_ALPHA //Alphabetical sorting of SD files menu
|
||||
|
||||
|
||||
// SD Card Sorting options
|
||||
#ifdef SDCARD_SORT_ALPHA
|
||||
#define SD_SORT_TIME 0
|
||||
#define SD_SORT_ALPHA 1
|
||||
#define SD_SORT_NONE 2
|
||||
#define INSERTSORT
|
||||
// #define SHELLSORT
|
||||
// #define SORTING_DUMP
|
||||
// #define SORTING_SPEEDTEST
|
||||
|
||||
|
||||
#define SDSORT_LIMIT 100 // Maximum number of sorted items (10-256).
|
||||
#define FOLDER_SORTING -1 // -1=above 0=none 1=below
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(SDCARD_SORT_ALPHA)
|
||||
#define HAS_FOLDER_SORTING (FOLDER_SORTING)
|
||||
#endif
|
||||
|
||||
// Enabe this option to get a pretty message whenever the endstop gets hit (as in the position at which the endstop got triggered)
|
||||
//#define VERBOSE_CHECK_HIT_ENDSTOPS
|
||||
|
||||
// Enable the option to stop SD printing when hitting and endstops, needs to be enabled from the LCD menu when this option is enabled.
|
||||
//#define ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED
|
||||
|
||||
|
|
@ -268,7 +296,9 @@
|
|||
//#define LA_DEBUG_LOGIC // @wavexx: setup logic channels for isr debugging
|
||||
#endif
|
||||
|
||||
// Arc interpretation settings : Moved to the variant files.
|
||||
// Arc interpretation settings:
|
||||
#define MM_PER_ARC_SEGMENT 1
|
||||
#define N_ARC_CORRECTION 25
|
||||
|
||||
const unsigned int dropsegments=5; //everything with less than this number of steps will be ignored as move and joined with the next movement
|
||||
|
||||
|
|
@ -324,11 +354,6 @@ const unsigned int dropsegments=5; //everything with less than this number of st
|
|||
// 2nd and 3rd byte (LSB first) contains a 16bit length of a command including its preceding comments.
|
||||
#define CMDHDRSIZE 3
|
||||
|
||||
#define FILAMENT_CHANGE_UNLOAD_FEEDRATE 10.f // (mm/s) Unload filament feedrate. This can be pretty fast.
|
||||
#define FILAMENT_UNLOAD_FAST_RETRACT_FEEDRATE 86.67f // (mm/s) Unload fast retract feedrate.
|
||||
#define FILAMENT_UNLOAD_SLOW_RETRACT_FEEDRATE 16.67f // (mm/s) Unload slow retract feedrate.
|
||||
#define FILAMENT_UNLOAD_FAST_RETRACT_LENGTH 45.f // (mm) Unload fast retract length.
|
||||
#define FILAMENT_UNLOAD_SLOW_RETRACT_LENGTH 35.f // (mm) Unload slow retract length.
|
||||
|
||||
// Firmware based and LCD controlled retract
|
||||
// M207 and M208 can be used to define parameters for the retraction.
|
||||
|
|
@ -364,7 +389,7 @@ const unsigned int dropsegments=5; //everything with less than this number of st
|
|||
|
||||
/**
|
||||
* Enable M120/M121 G-code commands
|
||||
*
|
||||
*
|
||||
*/
|
||||
//#define M120_M121_ENABLED //Be careful enabling and using these G-code commands.
|
||||
|
||||
|
|
@ -380,6 +405,14 @@ const unsigned int dropsegments=5; //everything with less than this number of st
|
|||
#define THERMISTORHEATER_0 TEMP_SENSOR_0
|
||||
#define HEATER_0_USES_THERMISTOR
|
||||
#endif
|
||||
#if TEMP_SENSOR_1 > 0
|
||||
#define THERMISTORHEATER_1 TEMP_SENSOR_1
|
||||
#define HEATER_1_USES_THERMISTOR
|
||||
#endif
|
||||
#if TEMP_SENSOR_2 > 0
|
||||
#define THERMISTORHEATER_2 TEMP_SENSOR_2
|
||||
#define HEATER_2_USES_THERMISTOR
|
||||
#endif
|
||||
#if TEMP_SENSOR_BED > 0
|
||||
#define THERMISTORBED TEMP_SENSOR_BED
|
||||
#define BED_USES_THERMISTOR
|
||||
|
|
@ -393,6 +426,12 @@ const unsigned int dropsegments=5; //everything with less than this number of st
|
|||
#if TEMP_SENSOR_0 == -1
|
||||
#define HEATER_0_USES_AD595
|
||||
#endif
|
||||
#if TEMP_SENSOR_1 == -1
|
||||
#define HEATER_1_USES_AD595
|
||||
#endif
|
||||
#if TEMP_SENSOR_2 == -1
|
||||
#define HEATER_2_USES_AD595
|
||||
#endif
|
||||
#if TEMP_SENSOR_BED == -1
|
||||
#define BED_USES_AD595
|
||||
#endif
|
||||
|
|
@ -403,6 +442,14 @@ const unsigned int dropsegments=5; //everything with less than this number of st
|
|||
#undef HEATER_0_MINTEMP
|
||||
#undef HEATER_0_MAXTEMP
|
||||
#endif
|
||||
#if TEMP_SENSOR_1 == 0
|
||||
#undef HEATER_1_MINTEMP
|
||||
#undef HEATER_1_MAXTEMP
|
||||
#endif
|
||||
#if TEMP_SENSOR_2 == 0
|
||||
#undef HEATER_2_MINTEMP
|
||||
#undef HEATER_2_MAXTEMP
|
||||
#endif
|
||||
#if TEMP_SENSOR_BED == 0
|
||||
#undef BED_MINTEMP
|
||||
#undef BED_MAXTEMP
|
||||
|
|
|
|||
|
|
@ -1,10 +0,0 @@
|
|||
// Include the printer's variant configuration header
|
||||
#pragma once
|
||||
|
||||
// This is set by the cmake build to be able to take control of
|
||||
// the variant header without breaking existing build mechanisms.
|
||||
#ifndef CMAKE_CONTROL
|
||||
#include "Configuration_prusa.h"
|
||||
#else
|
||||
#include FW_VARIANT
|
||||
#endif
|
||||
|
|
@ -3,7 +3,6 @@
|
|||
#include "Configuration.h"
|
||||
#include "language.h"
|
||||
#include "cmdqueue.h"
|
||||
#include "util.h"
|
||||
#include <stdio.h>
|
||||
#include <avr/pgmspace.h>
|
||||
|
||||
|
|
@ -45,7 +44,7 @@ void print_hex_word(daddr_t val)
|
|||
print_hex_byte(val & 0xFF);
|
||||
}
|
||||
|
||||
int parse_hex(const char* hex, uint8_t* data, int count)
|
||||
int parse_hex(char* hex, uint8_t* data, int count)
|
||||
{
|
||||
int parsed = 0;
|
||||
while (*hex)
|
||||
|
|
@ -120,7 +119,7 @@ void write_mem(uint16_t address, uint16_t count, const uint8_t* data, const dcod
|
|||
switch (type)
|
||||
{
|
||||
case dcode_mem_t::sram: *((uint8_t*)address) = data[i]; break;
|
||||
case dcode_mem_t::eeprom: eeprom_write_byte_notify((uint8_t*)address, data[i]); break;
|
||||
case dcode_mem_t::eeprom: eeprom_write_byte((uint8_t*)address, data[i]); break;
|
||||
case dcode_mem_t::progmem: break;
|
||||
case dcode_mem_t::xflash: break;
|
||||
}
|
||||
|
|
@ -162,19 +161,19 @@ void dcode_core(daddr_t addr_start, const daddr_t addr_end, const dcode_mem_t ty
|
|||
### D3 - Read/Write EEPROM <a href="https://reprap.org/wiki/G-code#D3:_Read.2FWrite_EEPROM">D3: Read/Write EEPROM</a>
|
||||
This command can be used without any additional parameters. It will read the entire eeprom.
|
||||
#### Usage
|
||||
|
||||
|
||||
D3 [ A | C | X ]
|
||||
|
||||
|
||||
#### Parameters
|
||||
- `A` - Address (x0000-x0fff)
|
||||
- `C` - Count (1-4096)
|
||||
- `X` - Data (hex)
|
||||
|
||||
|
||||
#### Notes
|
||||
- The hex address needs to be lowercase without the 0 before the x
|
||||
- Count is decimal
|
||||
- Count is decimal
|
||||
- The hex data needs to be lowercase
|
||||
|
||||
|
||||
*/
|
||||
void dcode_3()
|
||||
{
|
||||
|
|
@ -191,14 +190,21 @@ void dcode_3()
|
|||
#include <avr/wdt.h>
|
||||
#include "bootapp.h"
|
||||
|
||||
#if 0
|
||||
extern float current_temperature_pinda;
|
||||
extern float axis_steps_per_unit[NUM_AXIS];
|
||||
|
||||
|
||||
#define LOG(args...) printf(args)
|
||||
#endif //0
|
||||
#define LOG(args...)
|
||||
|
||||
/*!
|
||||
*
|
||||
### D-1 - Endless Loop <a href="https://reprap.org/wiki/G-code#G28:_Move_to_Origin_.28Home.29">D-1: Endless Loop</a>
|
||||
|
||||
|
||||
D-1
|
||||
|
||||
|
||||
*
|
||||
*/
|
||||
void dcode__1()
|
||||
|
|
@ -213,9 +219,9 @@ void dcode__1()
|
|||
/*!
|
||||
### D0 - Reset <a href="https://reprap.org/wiki/G-code#D0:_Reset">D0: Reset</a>
|
||||
#### Usage
|
||||
|
||||
|
||||
D0 [ B ]
|
||||
|
||||
|
||||
#### Parameters
|
||||
- `B` - Bootloader
|
||||
*/
|
||||
|
|
@ -238,9 +244,9 @@ void dcode_0()
|
|||
/*!
|
||||
*
|
||||
### D1 - Clear EEPROM and RESET <a href="https://reprap.org/wiki/G-code#D1:_Clear_EEPROM_and_RESET">D1: Clear EEPROM and RESET</a>
|
||||
|
||||
|
||||
D1
|
||||
|
||||
|
||||
*
|
||||
*/
|
||||
void dcode_1()
|
||||
|
|
@ -248,7 +254,7 @@ void dcode_1()
|
|||
LOG("D1 - Clear EEPROM and RESET\n");
|
||||
cli();
|
||||
for (int i = 0; i < 8192; i++)
|
||||
eeprom_write_byte_notify((unsigned char*)i, (unsigned char)0xff);
|
||||
eeprom_write_byte((unsigned char*)i, (unsigned char)0xff);
|
||||
softReset();
|
||||
}
|
||||
#endif
|
||||
|
|
@ -280,13 +286,13 @@ void dcode_2()
|
|||
|
||||
#ifdef DEBUG_DCODES
|
||||
/*!
|
||||
|
||||
|
||||
### D4 - Read/Write PIN <a href="https://reprap.org/wiki/G-code#D4:_Read.2FWrite_PIN">D4: Read/Write PIN</a>
|
||||
To read the digital value of a pin you need only to define the pin number.
|
||||
#### Usage
|
||||
|
||||
|
||||
D4 [ P | F | V ]
|
||||
|
||||
|
||||
#### Parameters
|
||||
- `P` - Pin (0-255)
|
||||
- `F` - Function in/out (0/1)
|
||||
|
|
@ -328,19 +334,20 @@ void dcode_4()
|
|||
### D5 - Read/Write FLASH <a href="https://reprap.org/wiki/G-code#D5:_Read.2FWrite_FLASH">D5: Read/Write Flash</a>
|
||||
This command can be used without any additional parameters. It will read the 1kb FLASH.
|
||||
#### Usage
|
||||
|
||||
|
||||
D5 [ A | C | X | E ]
|
||||
|
||||
|
||||
#### Parameters
|
||||
- `A` - Address (x00000-x3ffff)
|
||||
- `C` - Count (1-8192)
|
||||
- `X` - Data (hex)
|
||||
- `E` - Erase
|
||||
|
||||
|
||||
#### Notes
|
||||
- The hex address needs to be lowercase without the 0 before the x
|
||||
- Count is decimal
|
||||
- Count is decimal
|
||||
- The hex data needs to be lowercase
|
||||
|
||||
*/
|
||||
void dcode_5()
|
||||
{
|
||||
|
|
@ -449,9 +456,9 @@ void dcode_7()
|
|||
/*!
|
||||
### D8 - Read/Write PINDA <a href="https://reprap.org/wiki/G-code#D8:_Read.2FWrite_PINDA">D8: Read/Write PINDA</a>
|
||||
#### Usage
|
||||
|
||||
|
||||
D8 [ ? | ! | P | Z ]
|
||||
|
||||
|
||||
#### Parameters
|
||||
- `?` - Read PINDA temperature shift values
|
||||
- `!` - Reset PINDA temperature shift values to default
|
||||
|
|
@ -471,7 +478,7 @@ void dcode_8()
|
|||
{
|
||||
uint16_t offs = 0;
|
||||
if (i > 0) offs = eeprom_read_word(((uint16_t*)EEPROM_PROBE_TEMP_SHIFT) + (i - 1));
|
||||
float foffs = ((float)offs) / cs.axis_steps_per_mm[Z_AXIS];
|
||||
float foffs = ((float)offs) / cs.axis_steps_per_unit[Z_AXIS];
|
||||
offs = 1000 * foffs;
|
||||
printf_P(PSTR("temp_pinda=%dC temp_shift=%dum\n"), 35 + i * 5, offs);
|
||||
}
|
||||
|
|
@ -479,12 +486,12 @@ void dcode_8()
|
|||
else if (strchr_pointer[1+1] == '!')
|
||||
{
|
||||
cal_status = 1;
|
||||
eeprom_write_byte_notify((uint8_t*)EEPROM_CALIBRATION_STATUS_PINDA, cal_status);
|
||||
eeprom_write_word_notify(((uint16_t*)EEPROM_PROBE_TEMP_SHIFT) + 0, 8); //40C - 20um - 8usteps
|
||||
eeprom_write_word_notify(((uint16_t*)EEPROM_PROBE_TEMP_SHIFT) + 1, 24); //45C - 60um - 24usteps
|
||||
eeprom_write_word_notify(((uint16_t*)EEPROM_PROBE_TEMP_SHIFT) + 2, 48); //50C - 120um - 48usteps
|
||||
eeprom_write_word_notify(((uint16_t*)EEPROM_PROBE_TEMP_SHIFT) + 3, 80); //55C - 200um - 80usteps
|
||||
eeprom_write_word_notify(((uint16_t*)EEPROM_PROBE_TEMP_SHIFT) + 4, 120); //60C - 300um - 120usteps
|
||||
eeprom_write_byte((uint8_t*)EEPROM_CALIBRATION_STATUS_PINDA, cal_status);
|
||||
eeprom_write_word(((uint16_t*)EEPROM_PROBE_TEMP_SHIFT) + 0, 8); //40C - 20um - 8usteps
|
||||
eeprom_write_word(((uint16_t*)EEPROM_PROBE_TEMP_SHIFT) + 1, 24); //45C - 60um - 24usteps
|
||||
eeprom_write_word(((uint16_t*)EEPROM_PROBE_TEMP_SHIFT) + 2, 48); //50C - 120um - 48usteps
|
||||
eeprom_write_word(((uint16_t*)EEPROM_PROBE_TEMP_SHIFT) + 3, 80); //55C - 200um - 80usteps
|
||||
eeprom_write_word(((uint16_t*)EEPROM_PROBE_TEMP_SHIFT) + 4, 120); //60C - 300um - 120usteps
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -502,11 +509,11 @@ void dcode_8()
|
|||
/*!
|
||||
### D9 - Read ADC <a href="https://reprap.org/wiki/G-code#D9:_Read.2FWrite_ADC">D9: Read ADC</a>
|
||||
#### Usage
|
||||
|
||||
|
||||
D9 [ I | V ]
|
||||
|
||||
|
||||
#### Parameters
|
||||
- `I` - ADC channel index
|
||||
- `I` - ADC channel index
|
||||
- `0` - Heater 0 temperature
|
||||
- `1` - Heater 1 temperature
|
||||
- `2` - Bed temperature
|
||||
|
|
@ -566,7 +573,6 @@ void dcode_9()
|
|||
for (uint8_t i = 0; i < ADC_CHAN_CNT; i++)
|
||||
printf_P(PSTR("\tADC%d=%4d\t(%S)\n"), i, dcode_9_ADC_val(i) >> 4, dcode_9_ADC_name(i));
|
||||
}
|
||||
#if 0
|
||||
else
|
||||
{
|
||||
uint8_t index = 0xff;
|
||||
|
|
@ -577,12 +583,11 @@ void dcode_9()
|
|||
if (code_seen('V')) // value to be written as simulated
|
||||
{
|
||||
adc_sim_mask |= (1 << index);
|
||||
adc_values[index] = ((uint16_t)code_value_short() << 4);
|
||||
adc_values[index] = (((int)code_value()) << 4);
|
||||
printf_P(PSTR("ADC%d=%4d\n"), index, adc_values[index] >> 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -591,7 +596,7 @@ void dcode_9()
|
|||
void dcode_10()
|
||||
{//Tell the printer that XYZ calibration went OK
|
||||
LOG("D10 - XYZ calibration = OK\n");
|
||||
calibration_status_set(CALIBRATION_STATUS_XYZ);
|
||||
calibration_status_store(CALIBRATION_STATUS_LIVE_ADJUST);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -610,9 +615,9 @@ void dcode_12()
|
|||
### D80 - Bed check <a href="https://reprap.org/wiki/G-code#D80:_Bed_check">D80: Bed check</a>
|
||||
This command will log data to SD card file "mesh.txt".
|
||||
#### Usage
|
||||
|
||||
|
||||
D80 [ E | F | G | H | I | J ]
|
||||
|
||||
|
||||
#### Parameters
|
||||
- `E` - Dimension X (default 40)
|
||||
- `F` - Dimention Y (default 40)
|
||||
|
|
@ -650,9 +655,9 @@ void dcode_80()
|
|||
### D81 - Bed analysis <a href="https://reprap.org/wiki/G-code#D81:_Bed_analysis">D80: Bed analysis</a>
|
||||
This command will log data to SD card file "wldsd.txt".
|
||||
#### Usage
|
||||
|
||||
|
||||
D81 [ E | F | G | H | I | J ]
|
||||
|
||||
|
||||
#### Parameters
|
||||
- `E` - Dimension X (default 40)
|
||||
- `F` - Dimention Y (default 40)
|
||||
|
|
@ -676,9 +681,9 @@ void dcode_81()
|
|||
if (code_seen("H")) { strchr_pointer+=1; points_y = code_value(); }
|
||||
if (code_seen("I")) { strchr_pointer+=1; offset_x = code_value(); }
|
||||
if (code_seen("J")) { strchr_pointer+=1; offset_y = code_value(); }
|
||||
|
||||
|
||||
bed_analysis(dimension_x,dimension_y,points_x,points_y,offset_x,offset_y);
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif //HEATBED_ANALYSIS
|
||||
|
|
@ -705,11 +710,11 @@ extern void st_synchronize();
|
|||
/*!
|
||||
### D2130 - Trinamic stepper controller <a href="https://reprap.org/wiki/G-code#D2130:_Trinamic_stepper_controller">D2130: Trinamic stepper controller</a>
|
||||
@todo Please review by owner of the code. RepRap Wiki Gcode needs to be updated after review of owner as well.
|
||||
|
||||
|
||||
#### Usage
|
||||
|
||||
|
||||
D2130 [ Axis | Command | Subcommand | Value ]
|
||||
|
||||
|
||||
#### Parameters
|
||||
- Axis
|
||||
- `X` - X stepper driver
|
||||
|
|
@ -738,21 +743,21 @@ extern void st_synchronize();
|
|||
- `0, 180 --> 250` - Off
|
||||
- `0.9 --> 1.25` - Valid values (recommended is 1.1)
|
||||
- `@` - Home calibrate axis
|
||||
|
||||
|
||||
Examples:
|
||||
|
||||
|
||||
D2130E?wave
|
||||
|
||||
|
||||
Print extruder microstep linearity compensation curve
|
||||
|
||||
|
||||
D2130E!wave0
|
||||
|
||||
|
||||
Disable extruder linearity compensation curve, (sine curve is used)
|
||||
|
||||
|
||||
D2130E!wave220
|
||||
|
||||
|
||||
(sin(x))^1.1 extruder microstep compensation curve used
|
||||
|
||||
|
||||
Notes:
|
||||
For more information see https://www.trinamic.com/fileadmin/assets/Products/ICs_Documents/TMC2130_datasheet.pdf
|
||||
*
|
||||
|
|
@ -815,7 +820,7 @@ void dcode_2130()
|
|||
}
|
||||
else if (strcmp(strchr_pointer + 7, "wave") == 0)
|
||||
{
|
||||
tmc2130_get_wave(axis, 0);
|
||||
tmc2130_get_wave(axis, 0, stdout);
|
||||
}
|
||||
}
|
||||
else if (strchr_pointer[1+5] == '!')
|
||||
|
|
@ -836,9 +841,9 @@ void dcode_2130()
|
|||
uint16_t res_new = tmc2130_mres2usteps(mres);
|
||||
tmc2130_set_res(axis, res_new);
|
||||
if (res_new > res)
|
||||
cs.axis_steps_per_mm[axis] *= (res_new / res);
|
||||
cs.axis_steps_per_unit[axis] *= (res_new / res);
|
||||
else
|
||||
cs.axis_steps_per_mm[axis] /= (res / res_new);
|
||||
cs.axis_steps_per_unit[axis] /= (res / res_new);
|
||||
}
|
||||
}
|
||||
else if (strncmp(strchr_pointer + 7, "wave", 4) == 0)
|
||||
|
|
@ -858,19 +863,20 @@ void dcode_2130()
|
|||
}
|
||||
#endif //TMC2130
|
||||
|
||||
#if defined(FILAMENT_SENSOR) && (FILAMENT_SENSOR_TYPE == FSENSOR_PAT9125)
|
||||
#ifdef PAT9125
|
||||
/*!
|
||||
### D9125 - PAT9125 filament sensor <a href="https://reprap.org/wiki/G-code#D9:_Read.2FWrite_ADC">D9125: PAT9125 filament sensor</a>
|
||||
#### Usage
|
||||
|
||||
|
||||
D9125 [ ? | ! | R | X | Y | L ]
|
||||
|
||||
|
||||
#### Parameters
|
||||
- `?` - Print values
|
||||
- `!` - Print values
|
||||
- `R` - Resolution. Not active in code
|
||||
- `X` - X values
|
||||
- `Y` - Y values
|
||||
- `L` - Activate filament sensor log
|
||||
*/
|
||||
void dcode_9125()
|
||||
{
|
||||
|
|
@ -904,8 +910,15 @@ void dcode_9125()
|
|||
pat9125_y = (int)code_value();
|
||||
LOG("pat9125_y=%d\n", pat9125_y);
|
||||
}
|
||||
#ifdef DEBUG_FSENSOR_LOG
|
||||
if (code_seen('L'))
|
||||
{
|
||||
fsensor_log = (int)code_value();
|
||||
LOG("fsensor_log=%d\n", fsensor_log);
|
||||
}
|
||||
#endif //DEBUG_FSENSOR_LOG
|
||||
}
|
||||
#endif //defined(FILAMENT_SENSOR) && (FILAMENT_SENSOR_TYPE == FSENSOR_PAT9125)
|
||||
#endif //PAT9125
|
||||
|
||||
#endif //DEBUG_DCODES
|
||||
|
||||
|
|
@ -977,7 +990,7 @@ void __attribute__((noinline)) serial_dump_and_reset(dump_crash_reason reason)
|
|||
|
||||
// sample SP/PC
|
||||
sp = SP;
|
||||
pc = GETPC();
|
||||
GETPC(&pc);
|
||||
|
||||
// extend WDT long enough to allow writing the entire stream
|
||||
wdt_enable(WDTO_8S);
|
||||
|
|
|
|||
|
|
@ -53,9 +53,9 @@ extern void dcode_81(); //D81 - Bed analysis. This command will log data to SD c
|
|||
extern void dcode_2130(); //D2130 - TMC2130
|
||||
#endif //TMC2130
|
||||
|
||||
#if defined(FILAMENT_SENSOR) && (FILAMENT_SENSOR_TYPE == FSENSOR_PAT9125)
|
||||
#ifdef PAT9125
|
||||
extern void dcode_9125(); //D9125 - PAT9125
|
||||
#endif //defined(FILAMENT_SENSOR) && (FILAMENT_SENSOR_TYPE == FSENSOR_PAT9125)
|
||||
#endif //PAT9125
|
||||
|
||||
|
||||
#endif //DCODES_H
|
||||
|
|
|
|||
|
|
@ -1,509 +0,0 @@
|
|||
#include <avr/pgmspace.h>
|
||||
#include <stdio.h>
|
||||
#include <util/atomic.h>
|
||||
|
||||
#include "Filament_sensor.h"
|
||||
#include "Timer.h"
|
||||
#include "eeprom.h"
|
||||
#include "language.h"
|
||||
#include "menu.h"
|
||||
#include "messages.h"
|
||||
#include "mmu2.h"
|
||||
#include "planner.h"
|
||||
#include "temperature.h"
|
||||
#include "ultralcd.h"
|
||||
|
||||
#ifdef FILAMENT_SENSOR
|
||||
FSensorBlockRunout::FSensorBlockRunout() {
|
||||
fsensor.setRunoutEnabled(false); //suppress filament runouts while loading filament.
|
||||
fsensor.setAutoLoadEnabled(false); //suppress filament autoloads while loading filament.
|
||||
#if (FILAMENT_SENSOR_TYPE == FSENSOR_PAT9125)
|
||||
fsensor.setJamDetectionEnabled(false); //suppress filament jam detection while loading filament.
|
||||
#endif //(FILAMENT_SENSOR_TYPE == FSENSOR_PAT9125)
|
||||
// SERIAL_ECHOLNPGM("FSBlockRunout");
|
||||
}
|
||||
|
||||
FSensorBlockRunout::~FSensorBlockRunout() {
|
||||
fsensor.settings_init(); // restore filament runout state.
|
||||
// SERIAL_ECHOLNPGM("FSUnBlockRunout");
|
||||
}
|
||||
|
||||
# if FILAMENT_SENSOR_TYPE == FSENSOR_IR
|
||||
IR_sensor fsensor;
|
||||
# elif FILAMENT_SENSOR_TYPE == FSENSOR_IR_ANALOG
|
||||
IR_sensor_analog fsensor;
|
||||
# elif FILAMENT_SENSOR_TYPE == FSENSOR_PAT9125
|
||||
PAT9125_sensor fsensor;
|
||||
# endif
|
||||
|
||||
#else // FILAMENT_SENSOR
|
||||
FSensorBlockRunout::FSensorBlockRunout() { }
|
||||
FSensorBlockRunout::~FSensorBlockRunout() { }
|
||||
#endif // FILAMENT_SENSOR
|
||||
|
||||
void Filament_sensor::setEnabled(bool enabled) {
|
||||
eeprom_update_byte_notify((uint8_t *)EEPROM_FSENSOR, enabled);
|
||||
if (enabled) {
|
||||
fsensor.init();
|
||||
} else {
|
||||
fsensor.deinit();
|
||||
}
|
||||
}
|
||||
|
||||
void Filament_sensor::setAutoLoadEnabled(bool state, bool updateEEPROM) {
|
||||
autoLoadEnabled = state;
|
||||
if (updateEEPROM) {
|
||||
eeprom_update_byte_notify((uint8_t *)EEPROM_FSENS_AUTOLOAD_ENABLED, state);
|
||||
}
|
||||
}
|
||||
|
||||
void Filament_sensor::setRunoutEnabled(bool state, bool updateEEPROM) {
|
||||
runoutEnabled = state;
|
||||
if (updateEEPROM) {
|
||||
eeprom_update_byte_notify((uint8_t *)EEPROM_FSENS_RUNOUT_ENABLED, state);
|
||||
}
|
||||
}
|
||||
|
||||
void Filament_sensor::setActionOnError(SensorActionOnError state, bool updateEEPROM) {
|
||||
sensorActionOnError = state;
|
||||
if (updateEEPROM) {
|
||||
eeprom_update_byte_notify((uint8_t *)EEPROM_FSENSOR_ACTION_NA, (uint8_t)state);
|
||||
}
|
||||
}
|
||||
|
||||
void Filament_sensor::settings_init_common() {
|
||||
bool enabled = eeprom_read_byte((uint8_t *)EEPROM_FSENSOR);
|
||||
if ((state != State::disabled) != enabled) {
|
||||
state = enabled ? State::initializing : State::disabled;
|
||||
}
|
||||
|
||||
autoLoadEnabled = eeprom_read_byte((uint8_t *)EEPROM_FSENS_AUTOLOAD_ENABLED);
|
||||
runoutEnabled = eeprom_read_byte((uint8_t *)EEPROM_FSENS_RUNOUT_ENABLED);
|
||||
sensorActionOnError = (SensorActionOnError)eeprom_read_byte((uint8_t *)EEPROM_FSENSOR_ACTION_NA);
|
||||
if (sensorActionOnError == SensorActionOnError::_Undef) {
|
||||
sensorActionOnError = SensorActionOnError::_Continue;
|
||||
}
|
||||
}
|
||||
|
||||
bool Filament_sensor::checkFilamentEvents() {
|
||||
if (state != State::ready)
|
||||
return false;
|
||||
if (eventBlankingTimer.running() && !eventBlankingTimer.expired(100)) { // event blanking for 100ms
|
||||
return false;
|
||||
}
|
||||
|
||||
bool newFilamentPresent = fsensor.getFilamentPresent();
|
||||
if (oldFilamentPresent != newFilamentPresent) {
|
||||
oldFilamentPresent = newFilamentPresent;
|
||||
eventBlankingTimer.start();
|
||||
if (newFilamentPresent) { // filament insertion
|
||||
// puts_P(PSTR("filament inserted"));
|
||||
triggerFilamentInserted();
|
||||
postponedLoadEvent = true;
|
||||
} else { // filament removal
|
||||
// puts_P(PSTR("filament removed"));
|
||||
triggerFilamentRemoved();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Filament_sensor::triggerFilamentInserted() {
|
||||
if (autoLoadEnabled
|
||||
&& (eFilamentAction == FilamentAction::None)
|
||||
&& !(
|
||||
MMU2::mmu2.Enabled() // quick and dirty hack to prevent spurious runouts while the MMU is in charge
|
||||
|| moves_planned() != 0
|
||||
|| printJobOngoing()
|
||||
|| (lcd_commands_type == LcdCommands::Layer1Cal)
|
||||
|| eeprom_read_byte((uint8_t *)EEPROM_WIZARD_ACTIVE)
|
||||
)
|
||||
) {
|
||||
menu_submenu(lcd_AutoLoadFilament, true);
|
||||
}
|
||||
}
|
||||
|
||||
void Filament_sensor::triggerFilamentRemoved() {
|
||||
// SERIAL_ECHOLNPGM("triggerFilamentRemoved");
|
||||
if (runoutEnabled
|
||||
&& (eFilamentAction == FilamentAction::None)
|
||||
&& (
|
||||
moves_planned() != 0
|
||||
|| printJobOngoing()
|
||||
)
|
||||
&& !(
|
||||
saved_printing
|
||||
|| MMU2::mmu2.Enabled() // quick and dirty hack to prevent spurious runouts just before the toolchange
|
||||
|| (lcd_commands_type == LcdCommands::Layer1Cal)
|
||||
|| eeprom_read_byte((uint8_t *)EEPROM_WIZARD_ACTIVE)
|
||||
)
|
||||
){
|
||||
// SERIAL_ECHOPGM("runoutEnabled="); SERIAL_ECHOLN((int)runoutEnabled);
|
||||
// SERIAL_ECHOPGM("eFilamentAction="); SERIAL_ECHOLN((int)eFilamentAction);
|
||||
// SERIAL_ECHOPGM("saved_printing="); SERIAL_ECHOLN((int)saved_printing);
|
||||
filRunout();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Filament_sensor::filRunout() {
|
||||
// SERIAL_ECHOLNPGM("filRunout");
|
||||
sendHostNotification_P(MSG_FILAMENT_RUNOUT_DETECTED);
|
||||
runoutEnabled = false;
|
||||
autoLoadEnabled = false;
|
||||
stop_and_save_print_to_ram(0, 0);
|
||||
restore_print_from_ram_and_continue(0);
|
||||
eeprom_increment_byte((uint8_t *)EEPROM_FERROR_COUNT);
|
||||
eeprom_increment_word((uint16_t *)EEPROM_FERROR_COUNT_TOT);
|
||||
enquecommand_front_P(MSG_M600);
|
||||
}
|
||||
|
||||
void Filament_sensor::triggerError() {
|
||||
state = State::error;
|
||||
|
||||
/// some message, idk
|
||||
; //
|
||||
}
|
||||
|
||||
#if (FILAMENT_SENSOR_TYPE == FSENSOR_IR) || (FILAMENT_SENSOR_TYPE == FSENSOR_IR_ANALOG)
|
||||
void IR_sensor::init() {
|
||||
if (state == State::error) {
|
||||
fsensor.deinit(); // deinit first if there was an error.
|
||||
}
|
||||
// puts_P(PSTR("fsensor::init()"));
|
||||
SET_INPUT(IR_SENSOR_PIN); // input mode
|
||||
WRITE(IR_SENSOR_PIN, 1); // pullup
|
||||
settings_init(); // also sets the state to State::initializing
|
||||
}
|
||||
|
||||
void IR_sensor::deinit() {
|
||||
// puts_P(PSTR("fsensor::deinit()"));
|
||||
SET_INPUT(IR_SENSOR_PIN); // input mode
|
||||
WRITE(IR_SENSOR_PIN, 0); // no pullup
|
||||
state = State::disabled;
|
||||
}
|
||||
|
||||
bool IR_sensor::update() {
|
||||
switch (state) {
|
||||
case State::initializing:
|
||||
state = State::ready; // the IR sensor gets ready instantly as it's just a gpio read operation.
|
||||
// initialize the current filament state so that we don't create a switching event right after the sensor is ready.
|
||||
oldFilamentPresent = fsensor.getFilamentPresent();
|
||||
[[fallthrough]];
|
||||
case State::ready: {
|
||||
postponedLoadEvent = false;
|
||||
return checkFilamentEvents();
|
||||
} break;
|
||||
case State::disabled:
|
||||
case State::error:
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifdef FSENSOR_PROBING
|
||||
bool IR_sensor::probeOtherType() { return pat9125_probe(); }
|
||||
#endif
|
||||
|
||||
void IR_sensor::settings_init() { Filament_sensor::settings_init_common(); }
|
||||
|
||||
#if (FILAMENT_SENSOR_TYPE == FSENSOR_IR_ANALOG)
|
||||
void IR_sensor_analog::init() {
|
||||
IR_sensor::init();
|
||||
IR_sensor::settings_init();
|
||||
sensorRevision = (SensorRevision)eeprom_read_byte((uint8_t *)EEPROM_FSENSOR_PCB);
|
||||
}
|
||||
|
||||
bool IR_sensor_analog::update() {
|
||||
bool event = IR_sensor::update();
|
||||
if (state == State::ready) {
|
||||
if (getVoltReady()) {
|
||||
clearVoltReady();
|
||||
uint16_t volt = getVoltRaw();
|
||||
// printf_P(PSTR("newVoltRaw:%u\n"), volt / OVERSAMPLENR);
|
||||
|
||||
// detect min-max, some long term sliding window for filtration may be added
|
||||
// avoiding floating point operations, thus computing in raw
|
||||
if (volt > maxVolt) {
|
||||
maxVolt = volt;
|
||||
} else if (volt < minVolt) {
|
||||
minVolt = volt;
|
||||
}
|
||||
//! The trouble is, I can hold the filament in the hole in such a way, that it creates the exact voltage
|
||||
//! to be detected as the new fsensor
|
||||
//! We can either fake it by extending the detection window to a looooong time
|
||||
//! or do some other countermeasures
|
||||
|
||||
//! what we want to detect:
|
||||
//! if minvolt gets below ~0.3V, it means there is an old fsensor
|
||||
//! if maxvolt gets above 4.6V, it means we either have an old fsensor or broken cables/fsensor
|
||||
//! So I'm waiting for a situation, when minVolt gets to range <0, 1.5> and maxVolt gets into range <3.0, 5>
|
||||
//! If and only if minVolt is in range <0.3, 1.5> and maxVolt is in range <3.0, 4.6>, I'm considering a situation with the new fsensor
|
||||
if (minVolt >= IRsensor_Ldiode_TRESHOLD && minVolt <= IRsensor_Lmax_TRESHOLD && maxVolt >= IRsensor_Hmin_TRESHOLD &&
|
||||
maxVolt <= IRsensor_Hopen_TRESHOLD) {
|
||||
IR_ANALOG_Check(SensorRevision::_Old, SensorRevision::_Rev04);
|
||||
}
|
||||
//! If and only if minVolt is in range <0.0, 0.3> and maxVolt is in range <4.6, 5.0V>, I'm considering a situation with the old fsensor
|
||||
//! Note, we are not relying on one voltage here - getting just +5V can mean an old fsensor or a broken new sensor - that's why
|
||||
//! we need to have both voltages detected correctly to allow switching back to the old fsensor.
|
||||
else if (minVolt < IRsensor_Ldiode_TRESHOLD && maxVolt > IRsensor_Hopen_TRESHOLD && maxVolt <= IRsensor_VMax_TRESHOLD) {
|
||||
IR_ANALOG_Check(SensorRevision::_Rev04, SensorRevision::_Old);
|
||||
}
|
||||
|
||||
if (!checkVoltage(volt)) {
|
||||
triggerError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
; //
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
void IR_sensor_analog::voltUpdate(uint16_t raw) { // to be called from the ADC ISR when a cycle is finished
|
||||
voltRaw = raw;
|
||||
voltReady = true;
|
||||
}
|
||||
|
||||
uint16_t IR_sensor_analog::getVoltRaw() {
|
||||
uint16_t ret;
|
||||
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { ret = voltRaw; }
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char *IR_sensor_analog::getIRVersionText() {
|
||||
switch (sensorRevision) {
|
||||
case SensorRevision::_Old:
|
||||
return _T(MSG_IR_03_OR_OLDER);
|
||||
case SensorRevision::_Rev04:
|
||||
return _T(MSG_IR_04_OR_NEWER);
|
||||
default:
|
||||
return _T(MSG_IR_UNKNOWN);
|
||||
}
|
||||
}
|
||||
|
||||
void IR_sensor_analog::setSensorRevision(SensorRevision rev, bool updateEEPROM) {
|
||||
sensorRevision = rev;
|
||||
if (updateEEPROM) {
|
||||
eeprom_update_byte_notify((uint8_t *)EEPROM_FSENSOR_PCB, (uint8_t)rev);
|
||||
}
|
||||
}
|
||||
|
||||
bool IR_sensor_analog::checkVoltage(uint16_t raw) {
|
||||
if (IRsensor_Lmax_TRESHOLD <= raw && raw <= IRsensor_Hmin_TRESHOLD) {
|
||||
/// If the voltage is in forbidden range, the fsensor is ok, but the lever is mounted improperly.
|
||||
/// Or the user is so creative so that he can hold a piece of fillament in the hole in such a genius way,
|
||||
/// that the IR fsensor reading is within 1.5 and 3V ... this would have been highly unusual
|
||||
/// and would have been considered more like a sabotage than normal printer operation
|
||||
if (voltageErrorCnt++ > 4) {
|
||||
puts_P(PSTR("fsensor in forbidden range 1.5-3V - check sensor"));
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
voltageErrorCnt = 0;
|
||||
}
|
||||
if (sensorRevision == SensorRevision::_Rev04) {
|
||||
/// newer IR sensor cannot normally produce 4.6-5V, this is considered a failure/bad mount
|
||||
if (IRsensor_Hopen_TRESHOLD <= raw && raw <= IRsensor_VMax_TRESHOLD) {
|
||||
puts_P(PSTR("fsensor v0.4 in fault range 4.6-5V - unconnected"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// otherwise the IR fsensor is considered working correctly
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IR_sensor_analog::getVoltReady() const {
|
||||
bool ret;
|
||||
ATOMIC_BLOCK(ATOMIC_RESTORESTATE){ ret = voltReady; }
|
||||
return ret;
|
||||
}
|
||||
|
||||
void IR_sensor_analog::clearVoltReady(){
|
||||
ATOMIC_BLOCK(ATOMIC_RESTORESTATE){ voltReady = false; }
|
||||
}
|
||||
|
||||
void IR_sensor_analog::IR_ANALOG_Check(SensorRevision isVersion, SensorRevision switchTo) {
|
||||
bool bTemp = (!CHECK_ALL_HEATERS);
|
||||
bTemp = bTemp && (menu_menu == lcd_status_screen);
|
||||
bTemp = bTemp && ((sensorRevision == isVersion) || (sensorRevision == SensorRevision::_Undef));
|
||||
bTemp = bTemp && (state == State::ready);
|
||||
if (bTemp) {
|
||||
nFSCheckCount++;
|
||||
if (nFSCheckCount > FS_CHECK_COUNT) {
|
||||
nFSCheckCount = 0; // not necessary
|
||||
setSensorRevision(switchTo, true);
|
||||
printf_IRSensorAnalogBoardChange();
|
||||
switch (switchTo) {
|
||||
case SensorRevision::_Old:
|
||||
lcd_setstatuspgm(_T(MSG_IR_03_OR_OLDER));
|
||||
break;
|
||||
case SensorRevision::_Rev04:
|
||||
lcd_setstatuspgm(_T(MSG_IR_04_OR_NEWER));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
nFSCheckCount = 0;
|
||||
}
|
||||
}
|
||||
#endif //(FILAMENT_SENSOR_TYPE == FSENSOR_IR_ANALOG)
|
||||
#endif //(FILAMENT_SENSOR_TYPE == FSENSOR_IR) || (FILAMENT_SENSOR_TYPE == FSENSOR_IR_ANALOG)
|
||||
|
||||
#if (FILAMENT_SENSOR_TYPE == FSENSOR_PAT9125)
|
||||
void PAT9125_sensor::init() {
|
||||
if (state == State::error) {
|
||||
deinit(); // deinit first if there was an error.
|
||||
}
|
||||
// puts_P(PSTR("fsensor::init()"));
|
||||
|
||||
settings_init(); // also sets the state to State::initializing
|
||||
|
||||
calcChunkSteps(cs.axis_steps_per_mm[E_AXIS]); // for jam detection
|
||||
|
||||
if (!pat9125_init()) {
|
||||
deinit();
|
||||
triggerError();
|
||||
; //
|
||||
}
|
||||
#ifdef IR_SENSOR_PIN
|
||||
else if (!READ(IR_SENSOR_PIN)) {
|
||||
; // MK3 fw on MK3S printer
|
||||
}
|
||||
#endif // IR_SENSOR_PIN
|
||||
}
|
||||
|
||||
void PAT9125_sensor::deinit() {
|
||||
// puts_P(PSTR("fsensor::deinit()"));
|
||||
; //
|
||||
state = State::disabled;
|
||||
filter = 0;
|
||||
}
|
||||
|
||||
bool PAT9125_sensor::update() {
|
||||
switch (state) {
|
||||
case State::initializing:
|
||||
if (!updatePAT9125()) {
|
||||
break; // still not stable. Stay in the initialization state.
|
||||
}
|
||||
oldFilamentPresent =
|
||||
getFilamentPresent(); // initialize the current filament state so that we don't create a switching event right after the sensor is ready.
|
||||
oldPos = pat9125_y;
|
||||
state = State::ready;
|
||||
break;
|
||||
case State::ready: {
|
||||
updatePAT9125();
|
||||
postponedLoadEvent = false;
|
||||
bool event = checkFilamentEvents();
|
||||
|
||||
; //
|
||||
|
||||
return event;
|
||||
} break;
|
||||
case State::disabled:
|
||||
case State::error:
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef FSENSOR_PROBING
|
||||
bool PAT9125_sensor::probeOtherType() {
|
||||
SET_INPUT(IR_SENSOR_PIN); // input mode
|
||||
WRITE(IR_SENSOR_PIN, 1); // pullup
|
||||
_delay_us(100); // wait for the pullup to pull the line high (might be needed, not really sure. The internal pullups are quite weak and there might be a
|
||||
// long wire attached).
|
||||
bool fsensorDetected = !READ(IR_SENSOR_PIN);
|
||||
WRITE(IR_SENSOR_PIN, 0); // no pullup
|
||||
return fsensorDetected;
|
||||
}
|
||||
#endif
|
||||
|
||||
void PAT9125_sensor::setJamDetectionEnabled(bool state, bool updateEEPROM) {
|
||||
jamDetection = state;
|
||||
oldPos = pat9125_y;
|
||||
resetStepCount();
|
||||
jamErrCnt = 0;
|
||||
if (updateEEPROM) {
|
||||
eeprom_update_byte_notify((uint8_t *)EEPROM_FSENSOR_JAM_DETECTION, state);
|
||||
}
|
||||
}
|
||||
|
||||
void PAT9125_sensor::settings_init() {
|
||||
// puts_P(PSTR("settings_init"));
|
||||
Filament_sensor::settings_init_common();
|
||||
setJamDetectionEnabled(eeprom_read_byte((uint8_t *)EEPROM_FSENSOR_JAM_DETECTION));
|
||||
}
|
||||
|
||||
int16_t PAT9125_sensor::getStepCount() {
|
||||
int16_t ret;
|
||||
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { ret = stepCount; }
|
||||
return ret;
|
||||
}
|
||||
|
||||
void PAT9125_sensor::resetStepCount() {
|
||||
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { stepCount = 0; }
|
||||
}
|
||||
|
||||
void PAT9125_sensor::filJam() {
|
||||
runoutEnabled = false;
|
||||
autoLoadEnabled = false;
|
||||
jamDetection = false;
|
||||
stop_and_save_print_to_ram(0, 0);
|
||||
restore_print_from_ram_and_continue(0);
|
||||
eeprom_increment_byte((uint8_t *)EEPROM_FERROR_COUNT);
|
||||
eeprom_increment_word((uint16_t *)EEPROM_FERROR_COUNT_TOT);
|
||||
enquecommand_front_P(MSG_M600);
|
||||
}
|
||||
|
||||
bool PAT9125_sensor::updatePAT9125() {
|
||||
if (jamDetection) {
|
||||
int16_t _stepCount = getStepCount();
|
||||
if (abs(_stepCount) >= chunkSteps) { // end of chunk. Check distance
|
||||
resetStepCount();
|
||||
if (!pat9125_update()) { // get up to date data. reinit on error.
|
||||
init(); // try to reinit.
|
||||
}
|
||||
bool fsDir = (pat9125_y - oldPos) > 0;
|
||||
bool stDir = _stepCount > 0;
|
||||
if (fsDir != stDir) {
|
||||
jamErrCnt++;
|
||||
} else if (jamErrCnt) {
|
||||
jamErrCnt--;
|
||||
}
|
||||
oldPos = pat9125_y;
|
||||
}
|
||||
if (jamErrCnt > 10) {
|
||||
jamErrCnt = 0;
|
||||
filJam();
|
||||
}
|
||||
}
|
||||
|
||||
if (pollingTimer.expired_cont(pollingPeriod)) {
|
||||
pollingTimer.start();
|
||||
if (!pat9125_update()) {
|
||||
init(); // try to reinit.
|
||||
}
|
||||
|
||||
bool present = (pat9125_s < 17) || (pat9125_s >= 17 && pat9125_b >= 50);
|
||||
if (present != filterFilPresent) {
|
||||
filter++;
|
||||
} else if (filter) {
|
||||
filter--;
|
||||
}
|
||||
if (filter >= filterCnt) {
|
||||
filter = 0;
|
||||
filterFilPresent = present;
|
||||
}
|
||||
}
|
||||
return (filter == 0); // return stability
|
||||
}
|
||||
#endif // #if (FILAMENT_SENSOR_TYPE == FSENSOR_PAT9125)
|
||||
|
|
@ -1,212 +0,0 @@
|
|||
#pragma once
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "cmdqueue.h"
|
||||
#include "pins.h"
|
||||
#include "fastio.h"
|
||||
#include "adc.h"
|
||||
#include "pat9125.h"
|
||||
|
||||
#define FSENSOR_IR 1
|
||||
#define FSENSOR_IR_ANALOG 2
|
||||
#define FSENSOR_PAT9125 3
|
||||
|
||||
/// Can be used to block printer's filament sensor handling - to avoid errorneous injecting of M600
|
||||
/// while doing a toolchange with the MMU
|
||||
/// In case of "no filament sensor" these methods default to an empty implementation
|
||||
class FSensorBlockRunout {
|
||||
public:
|
||||
FSensorBlockRunout();
|
||||
~FSensorBlockRunout();
|
||||
};
|
||||
|
||||
/// Base class Filament sensor
|
||||
///
|
||||
/// Ideally, there could have been a nice class hierarchy of filament sensor types with common functionality
|
||||
/// extracted into this base class.
|
||||
/// But:
|
||||
/// - virtual methods take more space
|
||||
/// - we don't need to switch among different filament sensors at runtime
|
||||
/// Therefore the class hierarchy carefully avoids using virtual methods and doesn't look too fancy.
|
||||
#ifdef FILAMENT_SENSOR
|
||||
class Filament_sensor {
|
||||
public:
|
||||
enum class State : uint8_t {
|
||||
disabled = 0,
|
||||
initializing,
|
||||
ready,
|
||||
error,
|
||||
};
|
||||
|
||||
enum class SensorActionOnError : uint8_t {
|
||||
_Continue = 0,
|
||||
_Pause = 1,
|
||||
_Undef = EEPROM_EMPTY_VALUE
|
||||
};
|
||||
|
||||
static void setEnabled(bool enabled);
|
||||
|
||||
void setAutoLoadEnabled(bool state, bool updateEEPROM = false);
|
||||
bool getAutoLoadEnabled() const { return autoLoadEnabled; }
|
||||
|
||||
void setRunoutEnabled(bool state, bool updateEEPROM = false);
|
||||
bool getRunoutEnabled() const { return runoutEnabled; }
|
||||
|
||||
void setActionOnError(SensorActionOnError state, bool updateEEPROM = false);
|
||||
SensorActionOnError getActionOnError() const { return sensorActionOnError; }
|
||||
|
||||
bool getFilamentLoadEvent() const { return postponedLoadEvent; }
|
||||
|
||||
bool isError() const { return state == State::error; }
|
||||
bool isReady() const { return state == State::ready; }
|
||||
bool isEnabled() const { return state != State::disabled; }
|
||||
|
||||
protected:
|
||||
void settings_init_common();
|
||||
|
||||
bool checkFilamentEvents();
|
||||
|
||||
void triggerFilamentInserted();
|
||||
|
||||
void triggerFilamentRemoved();
|
||||
|
||||
void filRunout();
|
||||
|
||||
void triggerError();
|
||||
|
||||
State state;
|
||||
bool autoLoadEnabled;
|
||||
bool runoutEnabled;
|
||||
bool oldFilamentPresent; //for creating filament presence switching events.
|
||||
bool postponedLoadEvent; //this event lasts exactly one update cycle. It is long enough to be able to do polling for load event.
|
||||
ShortTimer eventBlankingTimer;
|
||||
SensorActionOnError sensorActionOnError;
|
||||
};
|
||||
|
||||
#if (FILAMENT_SENSOR_TYPE == FSENSOR_IR) || (FILAMENT_SENSOR_TYPE == FSENSOR_IR_ANALOG)
|
||||
class IR_sensor: public Filament_sensor {
|
||||
public:
|
||||
void init();
|
||||
void deinit();
|
||||
bool update();
|
||||
bool getFilamentPresent() const { return !READ(IR_SENSOR_PIN); }
|
||||
#ifdef FSENSOR_PROBING
|
||||
static bool probeOtherType(); //checks if the wrong fsensor type is detected.
|
||||
#endif
|
||||
void settings_init();
|
||||
};
|
||||
|
||||
#if (FILAMENT_SENSOR_TYPE == FSENSOR_IR_ANALOG)
|
||||
constexpr static uint16_t Voltage2Raw(float V) {
|
||||
return (V * 1023 * OVERSAMPLENR / VOLT_DIV_REF ) + 0.5F;
|
||||
}
|
||||
constexpr static float Raw2Voltage(uint16_t raw) {
|
||||
return VOLT_DIV_REF * (raw / (1023.F * OVERSAMPLENR));
|
||||
}
|
||||
|
||||
class IR_sensor_analog: public IR_sensor {
|
||||
public:
|
||||
void init();
|
||||
bool update();
|
||||
void voltUpdate(uint16_t raw);
|
||||
|
||||
uint16_t __attribute__((noinline)) getVoltRaw();
|
||||
|
||||
enum class SensorRevision : uint8_t {
|
||||
_Old = 0,
|
||||
_Rev04 = 1,
|
||||
_Undef = EEPROM_EMPTY_VALUE
|
||||
};
|
||||
|
||||
SensorRevision getSensorRevision() const { return sensorRevision; }
|
||||
|
||||
const char* __attribute__((noinline)) getIRVersionText();
|
||||
|
||||
void setSensorRevision(SensorRevision rev, bool updateEEPROM = false);
|
||||
|
||||
constexpr static uint16_t IRsensor_Ldiode_TRESHOLD = Voltage2Raw(0.3F); // ~0.3V, raw value=982
|
||||
constexpr static uint16_t IRsensor_Lmax_TRESHOLD = Voltage2Raw(1.5F); // ~1.5V (0.3*Vcc), raw value=4910
|
||||
constexpr static uint16_t IRsensor_Hmin_TRESHOLD = Voltage2Raw(3.0F); // ~3.0V (0.6*Vcc), raw value=9821
|
||||
constexpr static uint16_t IRsensor_Hopen_TRESHOLD = Voltage2Raw(4.6F); // ~4.6V (N.C. @ Ru~20-50k, Rd'=56k, Ru'=10k), raw value=15059
|
||||
constexpr static uint16_t IRsensor_VMax_TRESHOLD = Voltage2Raw(5.F); // ~5V, raw value=16368
|
||||
|
||||
private:
|
||||
SensorRevision sensorRevision;
|
||||
|
||||
bool voltReady; // set by the adc ISR, therefore avoid accessing the variable directly but use getVoltReady()
|
||||
bool getVoltReady()const;
|
||||
void clearVoltReady();
|
||||
|
||||
uint16_t voltRaw; // set by the adc ISR, therefore avoid accessing the variable directly but use getVoltRaw()
|
||||
bool checkVoltage(uint16_t raw);
|
||||
|
||||
uint16_t minVolt = Voltage2Raw(6.F);
|
||||
uint16_t maxVolt = 0;
|
||||
uint16_t nFSCheckCount;
|
||||
uint8_t voltageErrorCnt;
|
||||
|
||||
static constexpr uint16_t FS_CHECK_COUNT = 4;
|
||||
/// Switching mechanism of the fsensor type.
|
||||
/// Called from 2 spots which have a very similar behavior
|
||||
/// 1: SensorRevision::_Old -> SensorRevision::_Rev04 and print _i("FS v0.4 or newer")
|
||||
/// 2: SensorRevision::_Rev04 -> sensorRevision=SensorRevision::_Old and print _i("FS v0.3 or older")
|
||||
void IR_ANALOG_Check(SensorRevision isVersion, SensorRevision switchTo);
|
||||
};
|
||||
#endif //(FILAMENT_SENSOR_TYPE == FSENSOR_IR_ANALOG)
|
||||
#endif //(FILAMENT_SENSOR_TYPE == FSENSOR_IR) || (FILAMENT_SENSOR_TYPE == FSENSOR_IR_ANALOG)
|
||||
|
||||
#if (FILAMENT_SENSOR_TYPE == FSENSOR_PAT9125)
|
||||
class PAT9125_sensor: public Filament_sensor {
|
||||
public:
|
||||
void init();
|
||||
void deinit();
|
||||
bool update();
|
||||
bool getFilamentPresent() const { return filterFilPresent; }
|
||||
#ifdef FSENSOR_PROBING
|
||||
bool probeOtherType(); //checks if the wrong fsensor type is detected.
|
||||
#endif
|
||||
|
||||
void setJamDetectionEnabled(bool state, bool updateEEPROM = false);
|
||||
bool getJamDetectionEnabled() const { return jamDetection; }
|
||||
|
||||
void stStep(bool rev) { //from stepper isr
|
||||
stepCount += rev ? -1 : 1;
|
||||
}
|
||||
|
||||
void settings_init();
|
||||
private:
|
||||
static constexpr uint16_t pollingPeriod = 10; //[ms]
|
||||
static constexpr uint8_t filterCnt = 5; //how many checks need to be done in order to determine the filament presence precisely.
|
||||
ShortTimer pollingTimer;
|
||||
uint8_t filter;
|
||||
uint8_t filterFilPresent;
|
||||
|
||||
bool jamDetection;
|
||||
int16_t oldPos;
|
||||
int16_t stepCount;
|
||||
int16_t chunkSteps;
|
||||
uint8_t jamErrCnt;
|
||||
|
||||
constexpr void calcChunkSteps(float u) {
|
||||
chunkSteps = (int16_t)(1.25 * u); //[mm]
|
||||
}
|
||||
|
||||
int16_t getStepCount();
|
||||
|
||||
void resetStepCount();
|
||||
|
||||
void filJam();
|
||||
|
||||
bool updatePAT9125();
|
||||
};
|
||||
#endif //(FILAMENT_SENSOR_TYPE == FSENSOR_PAT9125)
|
||||
|
||||
#if FILAMENT_SENSOR_TYPE == FSENSOR_IR
|
||||
extern IR_sensor fsensor;
|
||||
#elif FILAMENT_SENSOR_TYPE == FSENSOR_IR_ANALOG
|
||||
extern IR_sensor_analog fsensor;
|
||||
#elif FILAMENT_SENSOR_TYPE == FSENSOR_PAT9125
|
||||
extern PAT9125_sensor fsensor;
|
||||
#endif
|
||||
|
||||
#endif //FILAMENT_SENSOR
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
{0x3E, {0x0F, 0xA8, 0xAF, 0x00, }, 'H'}, // index=0x80, utf8='🄷'
|
||||
{0x00, {0x69, 0x96, 0x00, 0x00, }, '\xdf'}, // index=0x81, utf8='°'
|
||||
{0x60, {0x25, 0x55, 0x58, 0x87, }, 'h'}, // index=0x82, utf8='🌡'
|
||||
{0x04, {0x27, 0xF2, 0xE0, 0x00, }, '^'}, // index=0x83, utf8='⬏'
|
||||
{0x34, {0x03, 0xCC, 0x19, 0x60, }, '\xf3'}, // index=0x84, utf8='🔃'
|
||||
{0x3C, {0x0E, 0xF8, 0x8F, 0x00, }, '\xdb'}, // index=0x85, utf8='🗀'
|
||||
{0x08, {0x02, 0x94, 0x92, 0x00, }, '>'}, // index=0x86, utf8='»'
|
||||
{0x1C, {0x07, 0x9A, 0x87, 0x00, }, '\xe5'}, // index=0x87, utf8='🕑'
|
||||
{0x24, {0x00, 0x85, 0x28, 0x52, }, '\x7e'}, // index=0x88, utf8='⏬'
|
||||
{0x06, {0x00, 0x1B, 0xE4, 0x00, }, '\x7e'}, // index=0x89, utf8='✔'
|
||||
{0x78, {0x12, 0x70, 0x78, 0x70, }, 'a'}, // index=0x8A, utf8='á'
|
||||
{0xF8, {0x12, 0x78, 0x8F, 0x88, }, 'A'}, // index=0x8B, utf8='Á'
|
||||
{0x78, {0x42, 0x70, 0x78, 0x70, }, 'a'}, // index=0x8C, utf8='à'
|
||||
{0x78, {0x25, 0x70, 0x78, 0x70, }, 'a'}, // index=0x8D, utf8='â'
|
||||
{0xF8, {0x50, 0x78, 0x8F, 0x88, }, '\xd1'}, // index=0x8E, utf8='Ä'
|
||||
{0xF0, {0x25, 0x27, 0x07, 0x87, }, 'a'}, // index=0x8F, utf8='å'
|
||||
{0xF0, {0x25, 0x27, 0x8F, 0x88, }, 'A'}, // index=0x90, utf8='Å'
|
||||
{0x2C, {0x0D, 0x27, 0xAA, 0x50, }, '\xd1'}, // index=0x91, utf8='æ'
|
||||
{0xBC, {0x07, 0x07, 0x87, 0x11, }, 'a'}, // index=0x92, utf8='ą'
|
||||
{0xBE, {0x78, 0x8F, 0x88, 0x11, }, 'A'}, // index=0x93, utf8='Ą'
|
||||
{0x78, {0x52, 0x70, 0x78, 0x70, }, 'a'}, // index=0x94, utf8='ă'
|
||||
{0xF8, {0x52, 0x78, 0x8F, 0x88, }, 'A'}, // index=0x95, utf8='Ă'
|
||||
{0x20, {0x12, 0x78, 0x88, 0x70, }, 'c'}, // index=0x96, utf8='ć'
|
||||
{0x20, {0x52, 0x78, 0x88, 0x70, }, 'c'}, // index=0x97, utf8='č'
|
||||
{0x48, {0x52, 0x78, 0x88, 0x87, }, 'C'}, // index=0x98, utf8='Č'
|
||||
{0x03, {0x11, 0x17, 0x99, 0x70, }, 'd'}, // index=0x99, utf8='ď'
|
||||
{0x18, {0x12, 0x78, 0xF8, 0x70, }, 'e'}, // index=0x9A, utf8='é'
|
||||
{0x44, {0x12, 0xF8, 0xF8, 0xF0, }, 'E'}, // index=0x9B, utf8='É'
|
||||
{0x18, {0x42, 0x78, 0xF8, 0x70, }, 'e'}, // index=0x9C, utf8='è'
|
||||
{0x18, {0x25, 0x78, 0xF8, 0x70, }, 'e'}, // index=0x9D, utf8='ê'
|
||||
{0x18, {0x52, 0x78, 0xF8, 0x70, }, 'e'}, // index=0x9E, utf8='ě'
|
||||
{0x18, {0x50, 0x78, 0xF8, 0x70, }, 'e'}, // index=0x9F, utf8='ë'
|
||||
{0x0C, {0x07, 0x8F, 0x87, 0x23, }, 'e'}, // index=0xA0, utf8='ę'
|
||||
{0xA2, {0x0F, 0x8F, 0x8F, 0x11, }, 'E'}, // index=0xA1, utf8='Ę'
|
||||
{0x00, {0x12, 0x06, 0x22, 0x70, }, 'i'}, // index=0xA2, utf8='í'
|
||||
{0x00, {0x12, 0x07, 0x22, 0x27, }, 'I'}, // index=0xA3, utf8='Í'
|
||||
{0x00, {0x25, 0x06, 0x22, 0x70, }, 'i'}, // index=0xA4, utf8='î'
|
||||
{0x00, {0x25, 0x07, 0x22, 0x27, }, 'I'}, // index=0xA5, utf8='Î'
|
||||
{0x00, {0x12, 0x06, 0x22, 0x27, }, 'l'}, // index=0xA6, utf8='ĺ'
|
||||
{0x02, {0x62, 0x36, 0xA2, 0x70, }, 'l'}, // index=0xA7, utf8='ł'
|
||||
{0x40, {0x45, 0x6C, 0x44, 0x70, }, 'L'}, // index=0xA8, utf8='Ł'
|
||||
{0x03, {0x62, 0x22, 0x22, 0x70, }, 'l'}, // index=0xA9, utf8='ľ'
|
||||
{0x43, {0x88, 0x88, 0x88, 0xF0, }, 'L'}, // index=0xAA, utf8='Ľ'
|
||||
{0x78, {0x12, 0xBC, 0x88, 0x80, }, 'n'}, // index=0xAB, utf8='ń'
|
||||
{0x78, {0x52, 0xBC, 0x88, 0x80, }, 'n'}, // index=0xAC, utf8='ň'
|
||||
{0x38, {0x12, 0x78, 0x88, 0x70, }, 'o'}, // index=0xAD, utf8='ó'
|
||||
{0x78, {0x12, 0x78, 0x88, 0x87, }, 'O'}, // index=0xAE, utf8='Ó'
|
||||
{0x38, {0x42, 0x78, 0x88, 0x70, }, 'o'}, // index=0xAF, utf8='ò'
|
||||
{0x38, {0x25, 0x78, 0x88, 0x70, }, 'o'}, // index=0xB0, utf8='ô'
|
||||
{0x3A, {0x00, 0x79, 0xAC, 0x78, }, 'o'}, // index=0xB1, utf8='ø'
|
||||
{0x3D, {0x07, 0x9A, 0xAC, 0x78, }, 'o'}, // index=0xB2, utf8='Ø'
|
||||
{0x78, {0x50, 0x78, 0x88, 0x87, }, '\xef'}, // index=0xB3, utf8='Ö'
|
||||
{0x39, {0x49, 0x78, 0x88, 0x70, }, 'o'}, // index=0xB4, utf8='ő'
|
||||
{0x08, {0x52, 0xBC, 0x88, 0x80, }, 'r'}, // index=0xB5, utf8='ř'
|
||||
{0x98, {0x52, 0xF8, 0x8F, 0x98, }, 'R'}, // index=0xB6, utf8='Ř'
|
||||
{0x20, {0x12, 0x78, 0x70, 0xF0, }, 's'}, // index=0xB7, utf8='ś'
|
||||
{0x48, {0x12, 0x78, 0x63, 0x87, }, 'S'}, // index=0xB8, utf8='Ś'
|
||||
{0x20, {0x52, 0x78, 0x70, 0xF0, }, 's'}, // index=0xB9, utf8='š'
|
||||
{0x48, {0x52, 0x78, 0x63, 0x87, }, 'S'}, // index=0xBA, utf8='Š'
|
||||
{0x10, {0x07, 0x87, 0x0F, 0x24, }, 's'}, // index=0xBB, utf8='ș'
|
||||
{0x12, {0x78, 0x63, 0x87, 0x24, }, 'S'}, // index=0xBC, utf8='Ș'
|
||||
{0x60, {0x69, 0x9A, 0x98, 0x8B, }, '\xe2'}, // index=0xBD, utf8='ß'
|
||||
{0x23, {0x04, 0xE4, 0x44, 0x30, }, 't'}, // index=0xBE, utf8='ť'
|
||||
{0x10, {0x4E, 0x44, 0x43, 0x24, }, 't'}, // index=0xBF, utf8='ț'
|
||||
{0x7C, {0x12, 0x88, 0x89, 0x60, }, 'u'}, // index=0xC0, utf8='ú'
|
||||
{0x3C, {0x50, 0x88, 0x88, 0x70, }, 'U'}, // index=0xC1, utf8='Ü'
|
||||
{0x78, {0x25, 0x28, 0x89, 0x60, }, 'u'}, // index=0xC2, utf8='ů'
|
||||
{0x79, {0x49, 0x08, 0x89, 0x60, }, 'u'}, // index=0xC3, utf8='ű'
|
||||
{0x3C, {0x12, 0x88, 0x70, 0x70, }, 'y'}, // index=0xC4, utf8='ý'
|
||||
{0x0C, {0x12, 0x88, 0x52, 0x22, }, 'Y'}, // index=0xC5, utf8='Ý'
|
||||
{0x44, {0x12, 0xF1, 0x24, 0xF0, }, 'z'}, // index=0xC6, utf8='ź'
|
||||
{0x44, {0x52, 0xF1, 0x24, 0xF0, }, 'z'}, // index=0xC7, utf8='ž'
|
||||
{0x8C, {0x52, 0xF0, 0x36, 0x8F, }, 'Z'}, // index=0xC8, utf8='Ž'
|
||||
{0x44, {0x20, 0xF1, 0x24, 0xF0, }, 'z'}, // index=0xC9, utf8='ż'
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
#include "Configuration.h"
|
||||
#include "pins.h"
|
||||
#include "Timer.h"
|
||||
#include "printer_state.h"
|
||||
extern uint8_t mbl_z_probe_nr;
|
||||
|
||||
#ifndef AT90USB
|
||||
#define HardwareSerial_h // trick to disable the standard HWserial
|
||||
|
|
@ -63,13 +63,25 @@
|
|||
#define MYSERIAL MSerial
|
||||
#endif
|
||||
|
||||
#include "lcd.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
extern FILE _uartout;
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define uartout (&_uartout)
|
||||
|
||||
#define SERIAL_PROTOCOL(x) (MYSERIAL.print(x))
|
||||
#define SERIAL_PROTOCOL_F(x,y) (MYSERIAL.print(x,y))
|
||||
#define SERIAL_PROTOCOLPGM(x) (serialprintPGM(PSTR(x)))
|
||||
#define SERIAL_PROTOCOLRPGM(x) (serialprintPGM((x)))
|
||||
#define SERIAL_PROTOCOLLN(x) (MYSERIAL.println(x))
|
||||
#define SERIAL_PROTOCOLLNPGM(x) (serialprintlnPGM(PSTR(x)))
|
||||
#define SERIAL_PROTOCOLLNRPGM(x) (serialprintlnPGM((x)))
|
||||
#define SERIAL_PROTOCOLLN(x) (MYSERIAL.println(x)/*,MYSERIAL.write('\n')*/)
|
||||
#define SERIAL_PROTOCOLLNPGM(x) (serialprintPGM(PSTR(x)),MYSERIAL.println()/*write('\n')*/)
|
||||
#define SERIAL_PROTOCOLLNRPGM(x) (serialprintPGM((x)),MYSERIAL.println()/*write('\n')*/)
|
||||
|
||||
|
||||
extern const char errormagic[] PROGMEM;
|
||||
|
|
@ -103,9 +115,6 @@ void serial_echopair_P(const char *s_P, unsigned long v);
|
|||
// I'd rather skip a few CPU ticks than 5.5KB (!!) of FLASH
|
||||
void serialprintPGM(const char *str);
|
||||
|
||||
//The "ln" variant of the function above.
|
||||
void serialprintlnPGM(const char *str);
|
||||
|
||||
bool is_buffer_empty();
|
||||
void process_commands();
|
||||
void ramming();
|
||||
|
|
@ -121,20 +130,35 @@ void manage_inactivity(bool ignore_stepper_queue=false);
|
|||
#endif
|
||||
|
||||
#if defined(Y_ENABLE_PIN) && Y_ENABLE_PIN > -1
|
||||
#define enable_y() WRITE(Y_ENABLE_PIN, Y_ENABLE_ON)
|
||||
#define disable_y() { WRITE(Y_ENABLE_PIN,!Y_ENABLE_ON); axis_known_position[Y_AXIS] = false; }
|
||||
#ifdef Y_DUAL_STEPPER_DRIVERS
|
||||
#define enable_y() { WRITE(Y_ENABLE_PIN, Y_ENABLE_ON); WRITE(Y2_ENABLE_PIN, Y_ENABLE_ON); }
|
||||
#define disable_y() { WRITE(Y_ENABLE_PIN,!Y_ENABLE_ON); WRITE(Y2_ENABLE_PIN, !Y_ENABLE_ON); axis_known_position[Y_AXIS] = false; }
|
||||
#else
|
||||
#define enable_y() WRITE(Y_ENABLE_PIN, Y_ENABLE_ON)
|
||||
#define disable_y() { WRITE(Y_ENABLE_PIN,!Y_ENABLE_ON); axis_known_position[Y_AXIS] = false; }
|
||||
#endif
|
||||
#else
|
||||
#define enable_y() ;
|
||||
#define disable_y() ;
|
||||
#endif
|
||||
|
||||
#if defined(Z_ENABLE_PIN) && Z_ENABLE_PIN > -1
|
||||
#if defined(Z_ENABLE_PIN) && Z_ENABLE_PIN > -1
|
||||
#if defined(Z_AXIS_ALWAYS_ON)
|
||||
#ifdef Z_DUAL_STEPPER_DRIVERS
|
||||
#define poweron_z() { WRITE(Z_ENABLE_PIN, Z_ENABLE_ON); WRITE(Z2_ENABLE_PIN, Z_ENABLE_ON); }
|
||||
#define poweroff_z() { WRITE(Z_ENABLE_PIN,!Z_ENABLE_ON); WRITE(Z2_ENABLE_PIN,!Z_ENABLE_ON); axis_known_position[Z_AXIS] = false; }
|
||||
#else
|
||||
#define poweron_z() WRITE(Z_ENABLE_PIN, Z_ENABLE_ON)
|
||||
#define poweroff_z() {}
|
||||
#endif
|
||||
#else
|
||||
#ifdef Z_DUAL_STEPPER_DRIVERS
|
||||
#define poweron_z() { WRITE(Z_ENABLE_PIN, Z_ENABLE_ON); WRITE(Z2_ENABLE_PIN, Z_ENABLE_ON); }
|
||||
#define poweroff_z() { WRITE(Z_ENABLE_PIN,!Z_ENABLE_ON); WRITE(Z2_ENABLE_PIN,!Z_ENABLE_ON); axis_known_position[Z_AXIS] = false; }
|
||||
#else
|
||||
#define poweron_z() WRITE(Z_ENABLE_PIN, Z_ENABLE_ON)
|
||||
#define poweroff_z() { WRITE(Z_ENABLE_PIN,!Z_ENABLE_ON); axis_known_position[Z_AXIS] = false; }
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
#define poweron_z() {}
|
||||
|
|
@ -145,7 +169,6 @@ void manage_inactivity(bool ignore_stepper_queue=false);
|
|||
#define enable_z() poweron_z()
|
||||
#define disable_z() poweroff_z()
|
||||
#else
|
||||
extern bool bEnableForce_z; // Used by ultralcd stealth toggle
|
||||
void init_force_z();
|
||||
void check_force_z();
|
||||
void enable_force_z();
|
||||
|
|
@ -154,6 +177,21 @@ void manage_inactivity(bool ignore_stepper_queue=false);
|
|||
#define disable_z() disable_force_z()
|
||||
#endif // PSU_Delta
|
||||
|
||||
|
||||
//#if defined(Z_ENABLE_PIN) && Z_ENABLE_PIN > -1
|
||||
//#ifdef Z_DUAL_STEPPER_DRIVERS
|
||||
//#define enable_z() { WRITE(Z_ENABLE_PIN, Z_ENABLE_ON); WRITE(Z2_ENABLE_PIN, Z_ENABLE_ON); }
|
||||
//#define disable_z() { WRITE(Z_ENABLE_PIN,!Z_ENABLE_ON); WRITE(Z2_ENABLE_PIN,!Z_ENABLE_ON); axis_known_position[Z_AXIS] = false; }
|
||||
//#else
|
||||
//#define enable_z() WRITE(Z_ENABLE_PIN, Z_ENABLE_ON)
|
||||
//#define disable_z() { WRITE(Z_ENABLE_PIN,!Z_ENABLE_ON); axis_known_position[Z_AXIS] = false; }
|
||||
//#endif
|
||||
//#else
|
||||
//#define enable_z() ;
|
||||
//#define disable_z() ;
|
||||
//#endif
|
||||
|
||||
|
||||
#if defined(E0_ENABLE_PIN) && (E0_ENABLE_PIN > -1)
|
||||
#define enable_e0() WRITE(E0_ENABLE_PIN, E_ENABLE_ON)
|
||||
#define disable_e0() WRITE(E0_ENABLE_PIN,!E_ENABLE_ON)
|
||||
|
|
@ -162,6 +200,26 @@ void manage_inactivity(bool ignore_stepper_queue=false);
|
|||
#define disable_e0() /* nothing */
|
||||
#endif
|
||||
|
||||
#if (EXTRUDERS > 1) && defined(E1_ENABLE_PIN) && (E1_ENABLE_PIN > -1)
|
||||
#define enable_e1() WRITE(E1_ENABLE_PIN, E_ENABLE_ON)
|
||||
#define disable_e1() WRITE(E1_ENABLE_PIN,!E_ENABLE_ON)
|
||||
#else
|
||||
#define enable_e1() /* nothing */
|
||||
#define disable_e1() /* nothing */
|
||||
#endif
|
||||
|
||||
#if (EXTRUDERS > 2) && defined(E2_ENABLE_PIN) && (E2_ENABLE_PIN > -1)
|
||||
#define enable_e2() WRITE(E2_ENABLE_PIN, E_ENABLE_ON)
|
||||
#define disable_e2() WRITE(E2_ENABLE_PIN,!E_ENABLE_ON)
|
||||
#else
|
||||
#define enable_e2() /* nothing */
|
||||
#define disable_e2() /* nothing */
|
||||
#endif
|
||||
|
||||
|
||||
#define FARM_FILAMENT_COLOR_NONE 99;
|
||||
|
||||
|
||||
enum AxisEnum {X_AXIS=0, Y_AXIS=1, Z_AXIS=2, E_AXIS=3, X_HEAD=4, Y_HEAD=5};
|
||||
#define X_AXIS_MASK 1
|
||||
#define Y_AXIS_MASK 2
|
||||
|
|
@ -175,14 +233,14 @@ void FlushSerialRequestResend();
|
|||
void ClearToSend();
|
||||
void update_currents();
|
||||
|
||||
void kill(const char *full_screen_message = NULL);
|
||||
void get_coordinates();
|
||||
void prepare_move();
|
||||
void kill(const char *full_screen_message = NULL, unsigned char id = 0);
|
||||
void finishAndDisableSteppers();
|
||||
|
||||
void UnconditionalStop(); // Stop heaters, motion and clear current print status
|
||||
void ConditionalStop(); // Similar to UnconditionalStop, but doesn't disable heaters
|
||||
void ThermalStop(bool allow_pause = false); // Emergency stop used by overtemp functions which allows
|
||||
// recovery (with pause=true)
|
||||
bool IsStopped(); // Returns true if the print has been stopped
|
||||
void UnconditionalStop(); // Stop heaters, motion and clear current print status
|
||||
void Stop(); // Emergency stop used by overtemp functions which allows recovery
|
||||
bool IsStopped(); // Returns true if the print has been stopped
|
||||
|
||||
//put an ASCII command at the end of the current buffer, read from flash
|
||||
#define enquecommand_P(cmd) enquecommand(cmd, true)
|
||||
|
|
@ -190,92 +248,119 @@ bool IsStopped(); // Returns true if the print has bee
|
|||
//put an ASCII command at the begin of the current buffer, read from flash
|
||||
#define enquecommand_front_P(cmd) enquecommand_front(cmd, true)
|
||||
|
||||
void prepare_arc_move(bool isclockwise);
|
||||
void clamp_to_software_endstops(float target[3]);
|
||||
void refresh_cmd_timeout(void);
|
||||
|
||||
// Timer counter, incremented by the 1ms Arduino timer.
|
||||
// The standard Arduino timer() function returns this value atomically
|
||||
// by disabling / enabling interrupts. This is costly, if the interrupts are known
|
||||
// to be disabled.
|
||||
#ifdef SYSTEM_TIMER_2
|
||||
extern volatile unsigned long timer2_millis;
|
||||
#else //SYSTEM_TIMER_2
|
||||
extern volatile unsigned long timer0_millis;
|
||||
#endif //SYSTEM_TIMER_2
|
||||
|
||||
// An unsynchronized equivalent to a standard Arduino _millis() function.
|
||||
// To be used inside an interrupt routine.
|
||||
|
||||
FORCE_INLINE unsigned long millis_nc() {
|
||||
#ifdef SYSTEM_TIMER_2
|
||||
return timer2_millis;
|
||||
#else //SYSTEM_TIMER_2
|
||||
return timer0_millis;
|
||||
#endif //SYSTEM_TIMER_2
|
||||
}
|
||||
|
||||
#ifdef FAST_PWM_FAN
|
||||
void setPwmFrequency(uint8_t pin, int val);
|
||||
#endif
|
||||
|
||||
enum class HeatingStatus : uint8_t
|
||||
{
|
||||
NO_HEATING = 0,
|
||||
EXTRUDER_HEATING = 1,
|
||||
EXTRUDER_HEATING_COMPLETE = 2,
|
||||
BED_HEATING = 3,
|
||||
BED_HEATING_COMPLETE = 4,
|
||||
};
|
||||
|
||||
extern HeatingStatus heating_status;
|
||||
|
||||
extern bool fans_check_enabled;
|
||||
constexpr float homing_feedrate[] = HOMING_FEEDRATE;
|
||||
extern float homing_feedrate[];
|
||||
extern uint8_t axis_relative_modes;
|
||||
extern float feedrate;
|
||||
extern int feedmultiply;
|
||||
extern int extrudemultiply; // Sets extrude multiply factor (in percent) for all extruders
|
||||
extern int extruder_multiply[EXTRUDERS]; // sets extrude multiply factor (in percent) for each extruder individually
|
||||
extern float extruder_multiplier[EXTRUDERS]; // reciprocal of cross-sectional area of filament (in square millimeters), stored this way to reduce computational burden in planner
|
||||
extern float current_position[NUM_AXIS] ;
|
||||
extern float destination[NUM_AXIS] ;
|
||||
extern float min_pos[3];
|
||||
extern float max_pos[3];
|
||||
extern bool axis_known_position[3];
|
||||
extern uint8_t fanSpeed; //!< Print fan speed, ranges from 0 to 255
|
||||
extern int fanSpeed;
|
||||
extern uint8_t newFanSpeed;
|
||||
extern int8_t lcd_change_fil_state;
|
||||
extern float default_retraction;
|
||||
|
||||
void get_coordinates();
|
||||
void prepare_move(uint16_t start_segment_idx = 0);
|
||||
void prepare_arc_move(bool isclockwise, uint16_t start_segment_idx = 0);
|
||||
uint16_t restore_interrupted_gcode();
|
||||
|
||||
///@brief Helper function to reduce code size, cheaper to call function than to inline division
|
||||
///@param feedrate_mm_min feedrate with unit mm per minute
|
||||
///@returns feedrate with unit mm per second
|
||||
float __attribute__((noinline)) get_feedrate_mm_s(const float feedrate_mm_min);
|
||||
|
||||
#ifdef TMC2130
|
||||
void check_Z_crash(void);
|
||||
void homeaxis(uint8_t axis, uint8_t cnt = 1, uint8_t* pstep = 0);
|
||||
void homeaxis(int axis, uint8_t cnt = 1, uint8_t* pstep = 0);
|
||||
#else
|
||||
void homeaxis(uint8_t axis, uint8_t cnt = 1);
|
||||
void homeaxis(int axis, uint8_t cnt = 1);
|
||||
#endif //TMC2130
|
||||
|
||||
|
||||
#ifdef FAN_SOFT_PWM
|
||||
extern unsigned char fanSpeedSoftPwm;
|
||||
#endif
|
||||
|
||||
#ifdef FWRETRACT
|
||||
extern bool retracted[EXTRUDERS];
|
||||
extern float retract_length_swap;
|
||||
extern float retract_recover_length_swap;
|
||||
#endif
|
||||
|
||||
extern ShortTimer usb_timer;
|
||||
extern bool processing_tcode;
|
||||
|
||||
extern uint8_t host_keepalive_interval;
|
||||
|
||||
extern unsigned long starttime;
|
||||
extern unsigned long stoptime;
|
||||
extern int bowden_length[4];
|
||||
extern bool is_usb_printing;
|
||||
extern bool homing_flag;
|
||||
extern uint32_t total_filament_used; // mm/100 or 10um
|
||||
extern bool loading_flag;
|
||||
extern unsigned int usb_printing_counter;
|
||||
|
||||
/// @brief Save print statistics to EEPROM
|
||||
void save_statistics();
|
||||
extern unsigned long kicktime;
|
||||
|
||||
extern unsigned long total_filament_used;
|
||||
void save_statistics(unsigned long _total_filament_used, unsigned long _total_print_time);
|
||||
extern unsigned int heating_status;
|
||||
extern unsigned int status_number;
|
||||
extern unsigned int heating_status_counter;
|
||||
extern char snmm_filaments_used;
|
||||
extern unsigned long PingTime;
|
||||
extern unsigned long NcTime;
|
||||
extern bool no_response;
|
||||
extern uint8_t important_status;
|
||||
extern uint8_t saved_filament_type;
|
||||
|
||||
extern bool fan_state[2];
|
||||
extern int fan_edge_counter[2];
|
||||
extern int fan_speed[2];
|
||||
|
||||
// Active extruder becomes a #define to make the whole firmware compilable.
|
||||
// We may even remove the references to it wherever possible in the future
|
||||
#define active_extruder 0
|
||||
// Handling multiple extruders pins
|
||||
extern uint8_t active_extruder;
|
||||
|
||||
//Long pause
|
||||
extern unsigned long pause_time;
|
||||
extern unsigned long start_pause_print;
|
||||
extern unsigned long t_fan_rising_edge;
|
||||
|
||||
extern bool mesh_bed_leveling_flag;
|
||||
extern bool did_pause_print;
|
||||
extern bool mesh_bed_run_from_menu;
|
||||
|
||||
// save/restore printing
|
||||
extern bool saved_printing;
|
||||
extern uint32_t saved_sdpos;
|
||||
extern uint8_t saved_printing_type;
|
||||
#define PRINTING_TYPE_SD 0
|
||||
#define PRINTING_TYPE_USB 1
|
||||
#define PRINTING_TYPE_NONE 2
|
||||
|
||||
extern uint16_t saved_extruder_temperature; //!< Active extruder temperature
|
||||
extern uint8_t saved_bed_temperature; //!< Bed temperature
|
||||
extern bool saved_extruder_relative_mode;
|
||||
extern uint8_t saved_fan_speed; //!< Print fan speed, ranges from 0 to 255
|
||||
extern float saved_pos[NUM_AXIS];
|
||||
extern uint16_t saved_feedrate2;
|
||||
//save/restore printing in case that mmu is not responding
|
||||
extern bool mmu_print_saved;
|
||||
|
||||
//estimated time to end of the print
|
||||
extern uint8_t print_percent_done_normal;
|
||||
|
|
@ -287,25 +372,13 @@ extern uint16_t print_time_to_change_silent;
|
|||
|
||||
#define PRINT_TIME_REMAINING_INIT 0xffff
|
||||
|
||||
extern uint16_t mcode_in_progress;
|
||||
extern uint16_t gcode_in_progress;
|
||||
|
||||
extern LongTimer safetyTimer;
|
||||
|
||||
#define PRINT_PERCENT_DONE_INIT 0xff
|
||||
|
||||
// Returns true if there is a print running. It does not matter if
|
||||
// the print is paused, that still counts as a "running" print.
|
||||
bool printJobOngoing();
|
||||
|
||||
// Make debug_printer_states available everywhere
|
||||
#ifdef DEBUG_PRINTER_STATES
|
||||
void debug_printer_states();
|
||||
#endif //DEBUG_PRINTER_STATES
|
||||
|
||||
// Printing is paused according to SD or host indicators
|
||||
bool printingIsPaused();
|
||||
|
||||
bool printer_active();
|
||||
|
||||
bool printer_recovering();
|
||||
#define PRINTER_ACTIVE (IS_SD_PRINTING || is_usb_printing || isPrintPaused || (custom_message_type == CustomMsg::TempCal) || saved_printing || (lcd_commands_type == LcdCommands::Layer1Cal) || mmu_print_saved || homing_flag || mesh_bed_leveling_flag)
|
||||
|
||||
//! Beware - mcode_in_progress is set as soon as the command gets really processed,
|
||||
//! which is not the same as posting the M600 command into the command queue
|
||||
|
|
@ -314,26 +387,11 @@ bool printer_recovering();
|
|||
//! Instead, the fsensor uses another state variable :( , which is set to true, when the M600 command is enqued
|
||||
//! and is reset to false when the fsensor returns into its filament runout finished handler
|
||||
//! I'd normally change this macro, but who knows what would happen in the MMU :)
|
||||
bool check_fsensor();
|
||||
|
||||
//! Condition where Babystepping is allowed:
|
||||
//! 1) Not allowed during Homing (printer busy)
|
||||
//! 2) Not allowed during Mesh Bed Leveling (printer busy)
|
||||
//! 3) Not allowed when a print job is paused
|
||||
//! 4) Allowed if:
|
||||
//! - First Layer Calibration is running (the event when heaters are turned off is used to dismiss the menu)
|
||||
//! - A print job is running
|
||||
//! - If the printer is idle with not planned moves
|
||||
bool babystep_allowed();
|
||||
|
||||
//! Same as babystep_allowed() but additionally adds a requirement
|
||||
//! where the Z-axis position must be less than 2.0mm (only allowed
|
||||
//! during the first couple of layers)
|
||||
bool babystep_allowed_strict();
|
||||
#define CHECK_FSENSOR ((IS_SD_PRINTING || is_usb_printing) && (mcode_in_progress != 600) && !saved_printing && e_active())
|
||||
|
||||
extern void calculate_extruder_multipliers();
|
||||
|
||||
// Similar to the default Arduino delay function,
|
||||
// Similar to the default Arduino delay function,
|
||||
// but it keeps the background tasks running.
|
||||
extern void delay_keep_alive(unsigned int ms);
|
||||
|
||||
|
|
@ -349,6 +407,7 @@ void bed_analysis(float x_dimension, float y_dimension, int x_points_num, int y_
|
|||
void bed_check(float x_dimension, float y_dimension, int x_points_num, int y_points_num, float shift_x, float shift_y);
|
||||
#endif //HEATBED_ANALYSIS
|
||||
float temp_comp_interpolation(float temperature);
|
||||
void show_fw_version_warnings();
|
||||
uint8_t check_printer_version();
|
||||
|
||||
#ifdef PINDA_THERMISTOR
|
||||
|
|
@ -358,33 +417,27 @@ float temp_compensation_pinda_thermistor_offset(float temperature_pinda);
|
|||
void serialecho_temperatures();
|
||||
bool check_commands();
|
||||
|
||||
void uvlo_();
|
||||
void uvlo_tiny();
|
||||
void recover_print(uint8_t automatic);
|
||||
void setup_uvlo_interrupt();
|
||||
|
||||
#if defined(TACH_1) && TACH_1 >-1
|
||||
void setup_fan_interrupt();
|
||||
#endif
|
||||
|
||||
extern bool recover_machine_state_after_power_panic();
|
||||
extern void restore_print_from_eeprom(bool mbl_was_active);
|
||||
extern void position_menu();
|
||||
|
||||
extern void print_world_coordinates();
|
||||
extern void print_physical_coordinates();
|
||||
extern void print_mesh_bed_leveling_table();
|
||||
|
||||
void save_print_file_state();
|
||||
void restore_print_file_state();
|
||||
void save_planner_global_state();
|
||||
void refresh_print_state_in_ram();
|
||||
|
||||
/// Updates the feedrate multiplier when a print is saved such that
|
||||
/// it is not overwritten when the print is later resumed
|
||||
void refresh_saved_feedrate_multiplier_in_ram();
|
||||
void clear_print_state_in_ram();
|
||||
extern void stop_and_save_print_to_ram(float z_move, float e_move);
|
||||
void restore_file_from_sd();
|
||||
void restore_extruder_temperature_from_ram();
|
||||
extern void restore_print_from_ram_and_continue(float e_move);
|
||||
extern void cancel_saved_printing();
|
||||
|
||||
// Define some coordinates outside the clamp limits (making them invalid past the parsing stage) so
|
||||
// that they can be used later for various logical checks
|
||||
#define X_COORD_INVALID (X_MIN_POS-1)
|
||||
#define SAVED_START_POSITION_UNSET X_COORD_INVALID
|
||||
extern float saved_start_position[NUM_AXIS];
|
||||
extern uint16_t saved_segment_idx;
|
||||
extern bool isPartialBackupAvailable;
|
||||
|
||||
|
||||
//estimated time to end of the print
|
||||
extern uint8_t calc_percent_done();
|
||||
|
|
@ -396,7 +449,7 @@ extern uint8_t calc_percent_done();
|
|||
/*enum MarlinBusyState {
|
||||
NOT_BUSY, // Not in a handler
|
||||
IN_HANDLER, // Processing a GCode
|
||||
IN_PROCESS, // Known to be blocking command input
|
||||
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)
|
||||
};*/
|
||||
|
|
@ -409,7 +462,6 @@ extern uint8_t calc_percent_done();
|
|||
|
||||
#define KEEPALIVE_STATE(n) do { busy_state = n;} while (0)
|
||||
extern void host_keepalive();
|
||||
extern void host_autoreport();
|
||||
//extern MarlinBusyState busy_state;
|
||||
extern int8_t busy_state;
|
||||
|
||||
|
|
@ -420,7 +472,6 @@ extern int8_t busy_state;
|
|||
#define FORCE_HIGH_POWER_END force_high_power_mode(false)
|
||||
|
||||
void force_high_power_mode(bool start_high_power_section);
|
||||
void change_power_mode_live(uint8_t mode);
|
||||
|
||||
#endif //TMC2130
|
||||
|
||||
|
|
@ -431,22 +482,25 @@ void gcode_M114();
|
|||
#if (defined(FANCHECK) && (((defined(TACH_0) && (TACH_0 >-1)) || (defined(TACH_1) && (TACH_1 > -1)))))
|
||||
void gcode_M123();
|
||||
#endif //FANCHECK and TACH_0 and TACH_1
|
||||
void gcode_M701(float fastLoadLength, uint8_t mmuSlotIndex);
|
||||
void gcode_M701();
|
||||
|
||||
#define UVLO !(PINE & (1<<4))
|
||||
|
||||
void proc_commands();
|
||||
|
||||
void M600_load_filament(const char* filament_name);
|
||||
void M600_load_filament_movements(const char* filament_name);
|
||||
void M600_wait_for_user();
|
||||
bool M600_check_state_and_repeat(const char* filament_name);
|
||||
|
||||
void M600_load_filament();
|
||||
void M600_load_filament_movements();
|
||||
void M600_wait_for_user(float HotendTempBckp);
|
||||
void M600_check_state(float nozzle_temp);
|
||||
void load_filament_final_feed();
|
||||
void marlin_wait_for_click();
|
||||
float raise_z(float delta);
|
||||
void raise_z_above(float target);
|
||||
void raise_z_above(float target, bool plan=true);
|
||||
|
||||
extern "C" void softReset();
|
||||
void stack_error();
|
||||
void pullup_error(bool fromTempISR);
|
||||
|
||||
extern uint32_t IP_address;
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
|
||||
Modified 23 November 2006 by David A. Mellis
|
||||
Modified 28 September 2010 by Mark Sproul
|
||||
*/
|
||||
|
|
@ -26,11 +26,11 @@
|
|||
uint8_t selectedSerialPort = 0;
|
||||
|
||||
#ifndef AT90USB
|
||||
// this next line disables the entire HardwareSerial.cpp,
|
||||
// this next line disables the entire HardwareSerial.cpp,
|
||||
// this is so I can support Attiny series and any other chip without a UART
|
||||
#if defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) || defined(UBRR2H) || defined(UBRR3H)
|
||||
|
||||
#ifdef HAS_UART
|
||||
#if UART_PRESENT(SERIAL_PORT)
|
||||
ring_buffer rx_buffer = { { 0 }, 0, 0 };
|
||||
#endif
|
||||
|
||||
|
|
@ -75,7 +75,7 @@ ISR(M_USARTx_RX_vect)
|
|||
#endif //DEBUG_DUMP_TO_2ND_SERIAL
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef SNMM
|
||||
ISR(USART1_RX_vect)
|
||||
{
|
||||
// Test for a framing error.
|
||||
|
|
@ -97,6 +97,7 @@ ISR(USART1_RX_vect)
|
|||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Public Methods //////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -129,8 +130,10 @@ void MarlinSerial::begin(long baud)
|
|||
sbi(M_UCSRxB, M_RXENx);
|
||||
sbi(M_UCSRxB, M_TXENx);
|
||||
sbi(M_UCSRxB, M_RXCIEx);
|
||||
|
||||
#ifndef SNMM
|
||||
|
||||
if (selectedSerialPort == 1) { //set up also the second serial port
|
||||
if (selectedSerialPort == 1) { //set up also the second serial port
|
||||
if (useU2X) {
|
||||
UCSR1A = 1 << U2X1;
|
||||
baud_setting = (F_CPU / 4 / baud - 1) / 2;
|
||||
|
|
@ -142,11 +145,12 @@ void MarlinSerial::begin(long baud)
|
|||
// assign the baud_setting, a.k.a. ubbr (USART Baud Rate Register)
|
||||
UBRR1H = baud_setting >> 8;
|
||||
UBRR1L = baud_setting;
|
||||
|
||||
|
||||
sbi(UCSR1B, RXEN1);
|
||||
sbi(UCSR1B, TXEN1);
|
||||
sbi(UCSR1B, RXCIE1);
|
||||
sbi(UCSR1B, RXCIE1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void MarlinSerial::end()
|
||||
|
|
@ -155,9 +159,11 @@ void MarlinSerial::end()
|
|||
cbi(M_UCSRxB, M_TXENx);
|
||||
cbi(M_UCSRxB, M_RXCIEx);
|
||||
|
||||
#ifndef SNMM
|
||||
cbi(UCSR1B, RXEN1);
|
||||
cbi(UCSR1B, TXEN1);
|
||||
cbi(UCSR1B, RXCIE1);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -250,7 +256,7 @@ void MarlinSerial::print(double n, int digits)
|
|||
void MarlinSerial::println(void)
|
||||
{
|
||||
// print('\r');
|
||||
print('\n');
|
||||
print('\n');
|
||||
}
|
||||
|
||||
/*void MarlinSerial::println(const String &s)
|
||||
|
|
@ -311,13 +317,13 @@ void MarlinSerial::println(double n, int digits)
|
|||
|
||||
void MarlinSerial::printNumber(unsigned long n, uint8_t base)
|
||||
{
|
||||
unsigned char buf[8 * sizeof(long)]; // Assumes 8-bit chars.
|
||||
uint8_t i = 0;
|
||||
unsigned char buf[8 * sizeof(long)]; // Assumes 8-bit chars.
|
||||
unsigned long i = 0;
|
||||
|
||||
if (n == 0) {
|
||||
print('0');
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
while (n > 0) {
|
||||
buf[i++] = n % base;
|
||||
|
|
@ -330,8 +336,8 @@ void MarlinSerial::printNumber(unsigned long n, uint8_t base)
|
|||
'A' + buf[i - 1] - 10));
|
||||
}
|
||||
|
||||
void MarlinSerial::printFloat(double number, uint8_t digits)
|
||||
{
|
||||
void MarlinSerial::printFloat(double number, uint8_t digits)
|
||||
{
|
||||
// Handle negative numbers
|
||||
if (number < 0.0)
|
||||
{
|
||||
|
|
@ -343,7 +349,7 @@ void MarlinSerial::printFloat(double number, uint8_t digits)
|
|||
double rounding = 0.5;
|
||||
for (uint8_t i=0; i<digits; ++i)
|
||||
rounding /= 10.0;
|
||||
|
||||
|
||||
number += rounding;
|
||||
|
||||
// Extract the integer part of the number and print it
|
||||
|
|
@ -353,7 +359,7 @@ void MarlinSerial::printFloat(double number, uint8_t digits)
|
|||
|
||||
// Print the decimal point, but only if there are digits beyond
|
||||
if (digits > 0)
|
||||
print('.');
|
||||
print('.');
|
||||
|
||||
// Extract digits from the remainder one at a time
|
||||
while (digits-- > 0)
|
||||
|
|
@ -361,8 +367,8 @@ void MarlinSerial::printFloat(double number, uint8_t digits)
|
|||
remainder *= 10.0;
|
||||
int toPrint = int(remainder);
|
||||
print(toPrint);
|
||||
remainder -= toPrint;
|
||||
}
|
||||
remainder -= toPrint;
|
||||
}
|
||||
}
|
||||
// Preinstantiate Objects //////////////////////////////////////////////////////
|
||||
|
||||
|
|
|
|||
|
|
@ -23,35 +23,33 @@
|
|||
#define MarlinSerial_h
|
||||
#include "Marlin.h"
|
||||
|
||||
#if !defined(SERIAL_PORT)
|
||||
#if !defined(SERIAL_PORT)
|
||||
#define SERIAL_PORT 0
|
||||
#endif
|
||||
|
||||
// The presence of the UBRRH register is used to detect a UART.
|
||||
#if ((SERIAL_PORT == 0 && (defined(UBRRH) || defined(UBRR0H))) || \
|
||||
(SERIAL_PORT == 1 && defined(UBRR1H)) || \
|
||||
(SERIAL_PORT == 2 && defined(UBRR2H)) || \
|
||||
(SERIAL_PORT == 3 && defined(UBRR3H)))
|
||||
#define HAS_UART
|
||||
#endif
|
||||
|
||||
#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(registerbase,number,suffix) _REGNAME_SHORT(registerbase, suffix)
|
||||
#define SERIAL_REGNAME_INTERNAL(registerbase,number,suffix) registerbase##suffix
|
||||
#else
|
||||
#define SERIAL_REGNAME(registerbase,number,suffix) _REGNAME(registerbase, number, suffix)
|
||||
#define SERIAL_REGNAME_INTERNAL(registerbase,number,suffix) registerbase##number##suffix
|
||||
#endif
|
||||
|
||||
// Registers used by MarlinSerial class (these are expanded
|
||||
// Registers used by MarlinSerial class (these are 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_RXCIEx SERIAL_REGNAME(RXCIE,SERIAL_PORT,)
|
||||
#define M_UDREx SERIAL_REGNAME(UDRE,SERIAL_PORT,)
|
||||
#define M_UDRx SERIAL_REGNAME(UDR,SERIAL_PORT,)
|
||||
#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_RXCIEx SERIAL_REGNAME(RXCIE,SERIAL_PORT,)
|
||||
#define M_UDREx SERIAL_REGNAME(UDRE,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,)
|
||||
|
|
@ -84,7 +82,7 @@ struct ring_buffer
|
|||
int tail;
|
||||
};
|
||||
|
||||
#ifdef HAS_UART
|
||||
#if UART_PRESENT(SERIAL_PORT)
|
||||
extern ring_buffer rx_buffer;
|
||||
#endif
|
||||
|
||||
|
|
@ -97,7 +95,7 @@ class MarlinSerial //: public Stream
|
|||
static int peek(void);
|
||||
static int read(void);
|
||||
static void flush(void);
|
||||
|
||||
|
||||
static /*FORCE_INLINE*/ int available(void)
|
||||
{
|
||||
return (unsigned int)(RX_BUFFER_SIZE + rx_buffer.head - rx_buffer.tail) % RX_BUFFER_SIZE;
|
||||
|
|
@ -124,7 +122,7 @@ class MarlinSerial //: public Stream
|
|||
UDR1 = c;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void checkRx(void)
|
||||
{
|
||||
if (selectedSerialPort == 0) {
|
||||
|
|
@ -177,15 +175,15 @@ class MarlinSerial //: public Stream
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private:
|
||||
static void printNumber(unsigned long, uint8_t);
|
||||
static void printFloat(double, uint8_t);
|
||||
|
||||
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
static /*FORCE_INLINE*/ void write(const char *str)
|
||||
{
|
||||
while (*str)
|
||||
|
|
@ -205,7 +203,7 @@ class MarlinSerial //: public Stream
|
|||
write(s[i]);
|
||||
}
|
||||
}*/
|
||||
|
||||
|
||||
static FORCE_INLINE void print(const char *str)
|
||||
{
|
||||
write(str);
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,496 +0,0 @@
|
|||
#include "Prusa_farm.h"
|
||||
#include "macros.h"
|
||||
#include "Marlin.h"
|
||||
#include "cmdqueue.h"
|
||||
#include "temperature.h"
|
||||
#include "cardreader.h"
|
||||
#include "util.h"
|
||||
#include "ultralcd.h"
|
||||
#include "Filament_sensor.h"
|
||||
#include "language.h"
|
||||
#include "lcd.h"
|
||||
#include "stopwatch.h"
|
||||
|
||||
#ifdef PRUSA_FARM
|
||||
uint8_t farm_mode = 0;
|
||||
|
||||
static ShortTimer NcTime;
|
||||
static uint8_t farm_timer = 8;
|
||||
static uint8_t status_number = 0;
|
||||
static bool no_response = false;
|
||||
#ifdef PRUSA_M28
|
||||
#define CHUNK_SIZE 64 // bytes
|
||||
#define SAFETY_MARGIN 1
|
||||
bool prusa_sd_card_upload = false;
|
||||
char chunk[CHUNK_SIZE+SAFETY_MARGIN];
|
||||
#endif
|
||||
|
||||
|
||||
static void prusa_statistics_err(char c);
|
||||
static void prusa_stat_printerstatus(uint8_t _status);
|
||||
static void prusa_stat_farm_number();
|
||||
static void prusa_stat_diameter();
|
||||
static void prusa_stat_temperatures();
|
||||
static void prusa_stat_printinfo();
|
||||
static void lcd_send_status();
|
||||
#ifdef FARM_CONNECT_MESSAGE
|
||||
static void proc_commands();
|
||||
static void lcd_connect_printer();
|
||||
#endif //FARM_CONNECT_MESSAGE
|
||||
#ifdef PRUSA_M28
|
||||
static void trace();
|
||||
#endif
|
||||
|
||||
|
||||
static void prusa_statistics_err(char c) {
|
||||
SERIAL_ECHOPGM("{[ERR:");
|
||||
SERIAL_ECHO(c);
|
||||
SERIAL_ECHO(']');
|
||||
prusa_stat_farm_number();
|
||||
}
|
||||
|
||||
static void prusa_statistics_case0(uint8_t statnr) {
|
||||
SERIAL_ECHO('{');
|
||||
prusa_stat_printerstatus(statnr);
|
||||
prusa_stat_farm_number();
|
||||
prusa_stat_printinfo();
|
||||
}
|
||||
|
||||
static void prusa_stat_printerstatus(uint8_t _status) {
|
||||
SERIAL_ECHOPGM("[PRN:");
|
||||
SERIAL_ECHO(_status);
|
||||
SERIAL_ECHO(']');
|
||||
}
|
||||
|
||||
static void prusa_stat_farm_number() {
|
||||
SERIAL_ECHOPGM("[PFN:0]");
|
||||
}
|
||||
|
||||
static void prusa_stat_diameter() {
|
||||
SERIAL_ECHOPGM("[DIA:");
|
||||
SERIAL_ECHO(eeprom_read_word((uint16_t*)EEPROM_NOZZLE_DIAMETER_uM));
|
||||
SERIAL_ECHO(']');
|
||||
}
|
||||
|
||||
static void prusa_stat_temperatures() {
|
||||
SERIAL_ECHOPGM("[ST0:");
|
||||
SERIAL_ECHO(target_temperature[0]);
|
||||
SERIAL_ECHOPGM("][STB:");
|
||||
SERIAL_ECHO(target_temperature_bed);
|
||||
SERIAL_ECHOPGM("][AT0:");
|
||||
SERIAL_ECHO(current_temperature[0]);
|
||||
SERIAL_ECHOPGM("][ATB:");
|
||||
SERIAL_ECHO(current_temperature_bed);
|
||||
SERIAL_ECHO(']');
|
||||
}
|
||||
|
||||
static void prusa_stat_printinfo() {
|
||||
SERIAL_ECHOPGM("[TFU:");
|
||||
SERIAL_ECHO(total_filament_used);
|
||||
SERIAL_ECHOPGM("][PCD:");
|
||||
SERIAL_ECHO((int)card.percentDone());
|
||||
SERIAL_ECHOPGM("][FEM:");
|
||||
SERIAL_ECHO(feedmultiply);
|
||||
SERIAL_ECHOPGM("][FNM:");
|
||||
SERIAL_ECHO(card.longFilename[0] ? card.longFilename : card.filename);
|
||||
SERIAL_ECHOPGM("][TIM:");
|
||||
if (print_job_timer.isRunning()) {
|
||||
SERIAL_ECHO(print_job_timer.duration());
|
||||
}
|
||||
else {
|
||||
SERIAL_ECHO(0);
|
||||
}
|
||||
SERIAL_ECHOPGM("][FWR:");
|
||||
SERIAL_ECHORPGM(FW_VERSION_STR_P());
|
||||
SERIAL_ECHO(']');
|
||||
prusa_stat_diameter();
|
||||
}
|
||||
|
||||
static void lcd_send_status() {
|
||||
if (farm_mode && no_response && (NcTime.expired(NC_TIME * 1000))) {
|
||||
//send important status messages periodicaly
|
||||
prusa_statistics(8);
|
||||
NcTime.start();
|
||||
#ifdef FARM_CONNECT_MESSAGE
|
||||
lcd_connect_printer();
|
||||
#endif //FARM_CONNECT_MESSAGE
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef FARM_CONNECT_MESSAGE
|
||||
static void proc_commands() {
|
||||
if (buflen) {
|
||||
process_commands();
|
||||
if (!cmdbuffer_front_already_processed)
|
||||
cmdqueue_pop_front();
|
||||
cmdbuffer_front_already_processed = false;
|
||||
}
|
||||
}
|
||||
|
||||
static void lcd_connect_printer() {
|
||||
lcd_update_enable(false);
|
||||
lcd_clear();
|
||||
|
||||
int i = 0;
|
||||
int t = 0;
|
||||
lcd_puts_at_P(0, 0, PSTR("Connect printer to"));
|
||||
lcd_puts_at_P(0, 1, PSTR("monitoring or hold"));
|
||||
lcd_puts_at_P(0, 2, PSTR("the knob to continue"));
|
||||
while (no_response) {
|
||||
i++;
|
||||
t++;
|
||||
delay_keep_alive(100);
|
||||
proc_commands();
|
||||
if (t == 10) {
|
||||
prusa_statistics(8);
|
||||
t = 0;
|
||||
}
|
||||
if (READ(BTN_ENC)) { //if button is not pressed
|
||||
i = 0;
|
||||
lcd_puts_at_P(0, 3, PSTR(" "));
|
||||
}
|
||||
if (i != 0)
|
||||
lcd_putc_at((i * 20) / (NC_BUTTON_LONG_PRESS * 10), 3, LCD_STR_SOLID_BLOCK[0]);
|
||||
if (i == NC_BUTTON_LONG_PRESS * 10)
|
||||
no_response = false;
|
||||
}
|
||||
lcd_update_enable(true);
|
||||
lcd_update(2);
|
||||
}
|
||||
#endif //FARM_CONNECT_MESSAGE
|
||||
|
||||
#ifdef PRUSA_M28
|
||||
static void trace() {
|
||||
Sound_MakeCustom(25,440,true);
|
||||
}
|
||||
|
||||
void serial_read_stream() {
|
||||
disable_heater();
|
||||
|
||||
lcd_clear();
|
||||
lcd_puts_P(PSTR(" Upload in progress"));
|
||||
|
||||
// first wait for how many bytes we will receive
|
||||
uint32_t bytesToReceive;
|
||||
|
||||
// receive the four bytes
|
||||
char bytesToReceiveBuffer[4];
|
||||
for (int i=0; i<4; i++) {
|
||||
int data;
|
||||
while ((data = MYSERIAL.read()) == -1) {};
|
||||
bytesToReceiveBuffer[i] = data;
|
||||
|
||||
}
|
||||
|
||||
// make it a uint32
|
||||
memcpy(&bytesToReceive, &bytesToReceiveBuffer, 4);
|
||||
|
||||
// we're ready, notify the sender
|
||||
MYSERIAL.write('+');
|
||||
|
||||
// lock in the routine
|
||||
uint32_t receivedBytes = 0;
|
||||
while (prusa_sd_card_upload) {
|
||||
int i;
|
||||
for (i=0; i<CHUNK_SIZE; i++) {
|
||||
int data;
|
||||
|
||||
// check if we're not done
|
||||
if (receivedBytes == bytesToReceive) {
|
||||
break;
|
||||
}
|
||||
|
||||
// read the next byte
|
||||
while ((data = MYSERIAL.read()) == -1) {};
|
||||
receivedBytes++;
|
||||
|
||||
// save it to the chunk
|
||||
chunk[i] = data;
|
||||
}
|
||||
|
||||
// write the chunk to SD
|
||||
card.write_command_no_newline(&chunk[0]);
|
||||
|
||||
// notify the sender we're ready for more data
|
||||
MYSERIAL.write('+');
|
||||
|
||||
// for safety
|
||||
manage_heater();
|
||||
|
||||
// check if we're done
|
||||
if(receivedBytes == bytesToReceive) {
|
||||
trace(); // beep
|
||||
card.closefile();
|
||||
prusa_sd_card_upload = false;
|
||||
SERIAL_PROTOCOLLNRPGM(MSG_FILE_SAVED);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif //PRUSA_M28
|
||||
|
||||
|
||||
void prusa_statistics(uint8_t _message) {
|
||||
const uint8_t _fil_nr = 0;
|
||||
if (!farm_mode)
|
||||
return;
|
||||
|
||||
switch (_message) {
|
||||
case 0: // default message
|
||||
if (busy_state == PAUSED_FOR_USER) {
|
||||
prusa_statistics_case0(15);
|
||||
}
|
||||
else if (printingIsPaused()) {
|
||||
prusa_statistics_case0(14);
|
||||
}
|
||||
else if (IS_SD_PRINTING || (eFilamentAction != FilamentAction::None)) {
|
||||
prusa_statistics_case0(4);
|
||||
}
|
||||
else {
|
||||
SERIAL_ECHO('{');
|
||||
prusa_stat_printerstatus(1);
|
||||
prusa_stat_farm_number();
|
||||
prusa_stat_diameter();
|
||||
status_number = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: // 1 heating
|
||||
SERIAL_ECHO('{');
|
||||
prusa_stat_printerstatus(2);
|
||||
prusa_stat_farm_number();
|
||||
status_number = 2;
|
||||
farm_timer = 1;
|
||||
break;
|
||||
|
||||
case 2: // heating done
|
||||
SERIAL_ECHO('{');
|
||||
prusa_stat_printerstatus(3);
|
||||
prusa_stat_farm_number();
|
||||
SERIAL_ECHOLN('}');
|
||||
status_number = 3;
|
||||
farm_timer = 1;
|
||||
|
||||
if (IS_SD_PRINTING || (eFilamentAction != FilamentAction::None)) {
|
||||
SERIAL_ECHO('{');
|
||||
prusa_stat_printerstatus(4);
|
||||
prusa_stat_farm_number();
|
||||
status_number = 4;
|
||||
}
|
||||
else {
|
||||
SERIAL_ECHO('{');
|
||||
prusa_stat_printerstatus(3);
|
||||
prusa_stat_farm_number();
|
||||
status_number = 3;
|
||||
}
|
||||
farm_timer = 1;
|
||||
break;
|
||||
|
||||
case 3: // filament change
|
||||
// must do a return here to prevent doing SERIAL_ECHOLN("}") at the very end of this function
|
||||
// saved a considerable amount of FLASH
|
||||
return;
|
||||
break;
|
||||
case 4: // print succesfull
|
||||
SERIAL_ECHOPGM("{[RES:1][FIL:");
|
||||
MYSERIAL.print(int(_fil_nr));
|
||||
SERIAL_ECHO(']');
|
||||
prusa_stat_printerstatus(status_number);
|
||||
prusa_stat_farm_number();
|
||||
farm_timer = 2;
|
||||
break;
|
||||
case 5: // print not succesfull
|
||||
SERIAL_ECHOPGM("{[RES:0][FIL:");
|
||||
MYSERIAL.print(int(_fil_nr));
|
||||
SERIAL_ECHO(']');
|
||||
prusa_stat_printerstatus(status_number);
|
||||
prusa_stat_farm_number();
|
||||
farm_timer = 2;
|
||||
break;
|
||||
case 6: // print done
|
||||
SERIAL_ECHOPGM("{[PRN:8]");
|
||||
prusa_stat_farm_number();
|
||||
status_number = 8;
|
||||
farm_timer = 2;
|
||||
break;
|
||||
case 7: // print done - stopped
|
||||
SERIAL_ECHOPGM("{[PRN:9]");
|
||||
prusa_stat_farm_number();
|
||||
status_number = 9;
|
||||
farm_timer = 2;
|
||||
break;
|
||||
case 8: // printer started
|
||||
SERIAL_ECHOPGM("{[PRN:0]");
|
||||
prusa_stat_farm_number();
|
||||
status_number = 0;
|
||||
farm_timer = 2;
|
||||
break;
|
||||
case 20: // echo farm no
|
||||
SERIAL_ECHO('{');
|
||||
prusa_stat_printerstatus(status_number);
|
||||
prusa_stat_farm_number();
|
||||
farm_timer = 4;
|
||||
break;
|
||||
case 21: // temperatures
|
||||
SERIAL_ECHO('{');
|
||||
prusa_stat_temperatures();
|
||||
prusa_stat_farm_number();
|
||||
prusa_stat_printerstatus(status_number);
|
||||
break;
|
||||
case 22: // waiting for filament change
|
||||
SERIAL_ECHOPGM("{[PRN:5]");
|
||||
prusa_stat_farm_number();
|
||||
status_number = 5;
|
||||
break;
|
||||
|
||||
case 90: // Error - Thermal Runaway
|
||||
prusa_statistics_err('1');
|
||||
break;
|
||||
case 91: // Error - Thermal Runaway Preheat
|
||||
prusa_statistics_err('2');
|
||||
break;
|
||||
case 92: // Error - Min temp
|
||||
prusa_statistics_err('3');
|
||||
break;
|
||||
case 93: // Error - Max temp
|
||||
prusa_statistics_err('4');
|
||||
break;
|
||||
|
||||
case 99: // heartbeat
|
||||
SERIAL_ECHOPGM("{[PRN:99]");
|
||||
prusa_stat_temperatures();
|
||||
prusa_stat_farm_number();
|
||||
break;
|
||||
}
|
||||
SERIAL_ECHOLN('}');
|
||||
}
|
||||
|
||||
void prusa_statistics_update_from_status_screen() {
|
||||
if (farm_mode) {
|
||||
farm_timer--;
|
||||
if (farm_timer < 1) {
|
||||
farm_timer = 10;
|
||||
prusa_statistics(0);
|
||||
}
|
||||
switch (farm_timer) {
|
||||
case 8:
|
||||
prusa_statistics(21);
|
||||
if(eFilamentAction != FilamentAction::None)
|
||||
prusa_statistics(22);
|
||||
break;
|
||||
case 5:
|
||||
if (IS_SD_PRINTING)
|
||||
prusa_statistics(20);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void prusa_statistics_update_from_lcd_update() {
|
||||
lcd_send_status();
|
||||
}
|
||||
|
||||
void farm_mode_init() {
|
||||
farm_mode = eeprom_init_default_byte((uint8_t*)EEPROM_FARM_MODE, 0);
|
||||
if (farm_mode) {
|
||||
no_response = true; //we need confirmation by recieving PRUSA thx
|
||||
prusa_statistics(8);
|
||||
#ifdef HAS_SECOND_SERIAL_PORT
|
||||
selectedSerialPort = 1;
|
||||
#endif //HAS_SECOND_SERIAL_PORT
|
||||
MYSERIAL.begin(BAUDRATE);
|
||||
#ifdef FILAMENT_SENSOR
|
||||
//to be converted to Filament_sensor.h...
|
||||
//disabled filament autoload (PFW360)
|
||||
fsensor.setAutoLoadEnabled(false);
|
||||
#endif //FILAMENT_SENSOR
|
||||
// ~ FanCheck -> on
|
||||
eeprom_update_byte_notify((uint8_t*)EEPROM_FAN_CHECK_ENABLED, true);
|
||||
}
|
||||
}
|
||||
|
||||
bool farm_prusa_code_seen() {
|
||||
if (!farm_mode)
|
||||
return false;
|
||||
|
||||
if (code_seen_P(PSTR("PRN"))) { // PRUSA PRN
|
||||
printf_P(_N("%u"), status_number);
|
||||
}
|
||||
else if (code_seen_P(PSTR("thx"))) { // PRUSA thx
|
||||
no_response = false;
|
||||
}
|
||||
#ifdef PRUSA_M28
|
||||
else if (code_seen_P(PSTR("M28"))) { // PRUSA M28
|
||||
trace();
|
||||
prusa_sd_card_upload = true;
|
||||
card.openFileWrite(strchr_pointer+4);
|
||||
}
|
||||
#endif //PRUSA_M28
|
||||
else if (code_seen_P(PSTR("fv"))) { // PRUSA fv
|
||||
// get file version
|
||||
#ifdef SDSUPPORT
|
||||
card.openFileReadFilteredGcode(strchr_pointer + 3, true);
|
||||
while (true) {
|
||||
uint16_t readByte = card.getFilteredGcodeChar();
|
||||
MYSERIAL.write(readByte);
|
||||
if (readByte == '\n') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
card.closefile();
|
||||
#endif // SDSUPPORT
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void farm_gcode_g98() {
|
||||
farm_mode = 1;
|
||||
eeprom_update_byte_notify((unsigned char *)EEPROM_FARM_MODE, farm_mode);
|
||||
SilentModeMenu = SILENT_MODE_OFF;
|
||||
eeprom_update_byte_notify((unsigned char *)EEPROM_SILENT, SilentModeMenu);
|
||||
fCheckModeInit(); // alternatively invoke printer reset
|
||||
}
|
||||
|
||||
void farm_gcode_g99() {
|
||||
farm_disable();
|
||||
lcd_update(2);
|
||||
fCheckModeInit(); // alternatively invoke printer reset
|
||||
}
|
||||
|
||||
void farm_disable() {
|
||||
farm_mode = false;
|
||||
eeprom_update_byte_notify((uint8_t*)EEPROM_FARM_MODE, farm_mode);
|
||||
}
|
||||
|
||||
#else //PRUSA_FARM
|
||||
|
||||
void prusa_statistics(_UNUSED uint8_t message) {
|
||||
}
|
||||
|
||||
void prusa_statistics_update_from_status_screen() {
|
||||
}
|
||||
|
||||
void prusa_statistics_update_from_lcd_update() {
|
||||
}
|
||||
|
||||
void farm_mode_init() {
|
||||
}
|
||||
|
||||
bool farm_prusa_code_seen() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void farm_gcode_g98() {
|
||||
}
|
||||
|
||||
void farm_gcode_g99() {
|
||||
}
|
||||
|
||||
void farm_disable() {
|
||||
}
|
||||
|
||||
#endif //PRUSA_FARM
|
||||
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "config.h"
|
||||
|
||||
#define FARM_PREHEAT_HOTEND_TEMP 250
|
||||
#define FARM_PREHEAT_HPB_TEMP 80
|
||||
|
||||
#define FARM_DEFAULT_SAFETYTIMER_TIME_ms (45*60*1000ul)
|
||||
#define NC_TIME 10 //time in s for periodic important status messages sending which needs reponse from monitoring
|
||||
#define NC_BUTTON_LONG_PRESS 15 //time in s
|
||||
|
||||
//#define FARM_CONNECT_MESSAGE
|
||||
|
||||
#ifdef PRUSA_FARM
|
||||
extern uint8_t farm_mode;
|
||||
#else
|
||||
#define farm_mode 0
|
||||
#endif
|
||||
|
||||
#ifdef PRUSA_M28
|
||||
extern bool prusa_sd_card_upload;
|
||||
extern void serial_read_stream();
|
||||
#endif
|
||||
extern void prusa_statistics(uint8_t _message);
|
||||
extern void prusa_statistics_update_from_status_screen();
|
||||
extern void prusa_statistics_update_from_lcd_update();
|
||||
extern void farm_mode_init();
|
||||
extern bool farm_prusa_code_seen();
|
||||
extern void farm_gcode_g98();
|
||||
extern void farm_gcode_g99();
|
||||
extern void farm_disable();
|
||||
|
|
@ -205,14 +205,14 @@ uint32_t Sd2Card::cardSize() {
|
|||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void Sd2Card::chipSelectHigh() {
|
||||
WRITE(SDSS, 1);
|
||||
digitalWrite(chipSelectPin_, HIGH);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void Sd2Card::chipSelectLow() {
|
||||
#ifndef SOFTWARE_SPI
|
||||
spiInit(spiRate_);
|
||||
#endif // SOFTWARE_SPI
|
||||
WRITE(SDSS, 0);
|
||||
digitalWrite(chipSelectPin_, LOW);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Erase a range of blocks.
|
||||
|
|
@ -283,25 +283,26 @@ bool Sd2Card::eraseSingleBlockEnable() {
|
|||
* the value zero, false, is returned for failure. The reason for failure
|
||||
* can be determined by calling errorCode() and errorData().
|
||||
*/
|
||||
bool Sd2Card::init(uint8_t sckRateID) {
|
||||
bool Sd2Card::init(uint8_t sckRateID, uint8_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;
|
||||
|
||||
// set pin modes
|
||||
pinMode(chipSelectPin_, OUTPUT);
|
||||
chipSelectHigh();
|
||||
SET_OUTPUT(SDSS);
|
||||
SET_INPUT(MISO);
|
||||
SET_OUTPUT(MOSI);
|
||||
SET_OUTPUT(SCK);
|
||||
pinMode(SPI_MISO_PIN, INPUT);
|
||||
pinMode(SPI_MOSI_PIN, OUTPUT);
|
||||
pinMode(SPI_SCK_PIN, OUTPUT);
|
||||
|
||||
#ifndef SOFTWARE_SPI
|
||||
// SS must be in output mode even it is not chip select
|
||||
SET_OUTPUT(SS);
|
||||
pinMode(SS_PIN, OUTPUT);
|
||||
// set SS high - may be chip select for another SPI device
|
||||
#if SET_SPI_SS_HIGH
|
||||
WRITE(SS, 1);
|
||||
digitalWrite(SS_PIN, HIGH);
|
||||
#endif // SET_SPI_SS_HIGH
|
||||
// set SCK rate for initialization commands
|
||||
spiRate_ = SPI_SD_INIT_RATE;
|
||||
|
|
@ -311,16 +312,13 @@ bool Sd2Card::init(uint8_t sckRateID) {
|
|||
// must supply min of 74 clock cycles with CS high.
|
||||
for (uint8_t i = 0; i < 10; i++) spiSend(0XFF);
|
||||
|
||||
WRITE(MISO, 1); // temporarily enable the MISO line pullup
|
||||
// command to go idle in SPI mode
|
||||
while ((status_ = cardCommand(CMD0, 0)) != R1_IDLE_STATE) {
|
||||
if (((uint16_t)_millis() - t0) > SD_INIT_TIMEOUT) {
|
||||
WRITE(MISO, 0); // disable the MISO line pullup
|
||||
error(SD_CARD_ERROR_CMD0);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
WRITE(MISO, 0); // disable the MISO line pullup
|
||||
|
||||
// send 0xFF until 0xFF received to give card some clock cycles
|
||||
t0 = (uint16_t)_millis();
|
||||
|
|
@ -767,7 +765,7 @@ uint8_t Sd2Card::waitStartBlock(void) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// Toshiba FlashAir support, copied from
|
||||
// Toshiba FlashAir support, copied from
|
||||
// https://flashair-developers.com/en/documents/tutorials/arduino/
|
||||
// However, the official website was closed in September 2019.
|
||||
// There is an archived website (written in Japanese).
|
||||
|
|
@ -783,7 +781,7 @@ uint8_t Sd2Card::readExt(uint32_t arg, uint8_t* dst, uint16_t count) {
|
|||
error(SD_CARD_ERROR_CMD48);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
// wait for start block token.
|
||||
if (!waitStartBlock()) {
|
||||
goto fail;
|
||||
|
|
@ -793,7 +791,7 @@ uint8_t Sd2Card::readExt(uint32_t arg, uint8_t* dst, uint16_t count) {
|
|||
for (i = 0; i < count; ++i) {
|
||||
dst[i] = spiRec();
|
||||
}
|
||||
|
||||
|
||||
// skip dummy bytes and 16-bit crc.
|
||||
for (; i < 514; ++i) {
|
||||
spiRec();
|
||||
|
|
@ -815,19 +813,19 @@ uint8_t Sd2Card::readExt(uint32_t arg, uint8_t* dst, uint16_t count) {
|
|||
* \return The value one, true, is returned for success and
|
||||
* the value zero, false, is returned for failure.
|
||||
*/
|
||||
uint8_t Sd2Card::readExtMemory(uint8_t mio, uint8_t func,
|
||||
uint8_t Sd2Card::readExtMemory(uint8_t mio, uint8_t func,
|
||||
uint32_t addr, uint16_t count, uint8_t* dst) {
|
||||
uint32_t offset = addr & 0x1FF;
|
||||
if (offset + count > 512) count = 512 - offset;
|
||||
|
||||
|
||||
if (count == 0) return true;
|
||||
|
||||
uint32_t arg =
|
||||
(((uint32_t)mio & 0x1) << 31) |
|
||||
|
||||
uint32_t arg =
|
||||
(((uint32_t)mio & 0x1) << 31) |
|
||||
(mio ? (((uint32_t)func & 0x7) << 28) : (((uint32_t)func & 0xF) << 27)) |
|
||||
((addr & 0x1FFFF) << 9) |
|
||||
((count - 1) & 0x1FF);
|
||||
|
||||
|
||||
return readExt(arg, dst, count);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
* \brief Sd2Card class for V2 SD/SDHC cards
|
||||
*/
|
||||
#include "SdFatConfig.h"
|
||||
#include "Sd2PinMap.h"
|
||||
#include "SdInfo.h"
|
||||
//------------------------------------------------------------------------------
|
||||
// SPI speed is F_CPU/2^(1 + index), 0 <= index <= 6
|
||||
|
|
@ -132,7 +133,22 @@ uint8_t const SD_CARD_TYPE_SDHC = 3;
|
|||
//------------------------------------------------------------------------------
|
||||
// SPI pin definitions - do not edit here - change in SdFatConfig.h
|
||||
//
|
||||
#ifdef SOFTWARE_SPI
|
||||
#ifndef SOFTWARE_SPI
|
||||
// hardware pin defs
|
||||
/** The default chip select pin for the SD card is SS. */
|
||||
uint8_t const SD_CHIP_SELECT_PIN = SS_PIN;
|
||||
// The following three pins must not be redefined for hardware SPI.
|
||||
/** SPI Master Out Slave In pin */
|
||||
uint8_t const SPI_MOSI_PIN = MOSI_PIN;
|
||||
/** SPI Master In Slave Out pin */
|
||||
uint8_t const SPI_MISO_PIN = MISO_PIN;
|
||||
/** SPI Clock pin */
|
||||
uint8_t const SPI_SCK_PIN = SCK_PIN;
|
||||
|
||||
#else // SOFTWARE_SPI
|
||||
|
||||
/** SPI chip select pin */
|
||||
uint8_t const SD_CHIP_SELECT_PIN = SOFT_SPI_CS_PIN;
|
||||
/** SPI Master Out Slave In pin */
|
||||
uint8_t const SPI_MOSI_PIN = SOFT_SPI_MOSI_PIN;
|
||||
/** SPI Master In Slave Out pin */
|
||||
|
|
@ -160,21 +176,22 @@ class Sd2Card {
|
|||
/**
|
||||
* \return error code for last error. See Sd2Card.h for a list of error codes.
|
||||
*/
|
||||
uint8_t errorCode() const {return errorCode_;}
|
||||
int errorCode() const {return errorCode_;}
|
||||
/** \return error data for last error. */
|
||||
uint8_t errorData() const {return status_;}
|
||||
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).
|
||||
* 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);
|
||||
bool init(uint8_t sckRateID = SPI_FULL_SPEED,
|
||||
uint8_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.
|
||||
* number and Manufacturing date.
|
||||
*
|
||||
* \param[out] cid pointer to area for returned data.
|
||||
*
|
||||
|
|
@ -215,6 +232,7 @@ class Sd2Card {
|
|||
|
||||
private:
|
||||
//----------------------------------------------------------------------------
|
||||
uint8_t chipSelectPin_;
|
||||
uint8_t errorCode_;
|
||||
uint8_t spiRate_;
|
||||
uint8_t status_;
|
||||
|
|
@ -243,4 +261,4 @@ class Sd2Card {
|
|||
#endif // Sd2Card_h
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
@ -0,0 +1,364 @@
|
|||
/* Arduino SdFat Library
|
||||
* Copyright (C) 2010 by William Greiman
|
||||
*
|
||||
* This file is part of the Arduino SdFat Library
|
||||
*
|
||||
* This Library 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 Library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with the Arduino SdFat Library. If not, see
|
||||
* <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
// Warning this file was generated by a program.
|
||||
#include "Marlin.h"
|
||||
#ifdef SDSUPPORT
|
||||
|
||||
#ifndef Sd2PinMap_h
|
||||
#define Sd2PinMap_h
|
||||
#include <avr/io.h>
|
||||
//------------------------------------------------------------------------------
|
||||
/** struct for mapping digital pins */
|
||||
struct pin_map_t {
|
||||
volatile uint8_t* ddr;
|
||||
volatile uint8_t* pin;
|
||||
volatile uint8_t* port;
|
||||
uint8_t bit;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
#if defined(__AVR_ATmega1280__)\
|
||||
|| defined(__AVR_ATmega2560__)
|
||||
// Mega
|
||||
|
||||
#undef MOSI_PIN
|
||||
#undef MISO_PIN
|
||||
// SPI port
|
||||
uint8_t const SS_PIN = 53; // B0
|
||||
uint8_t const MOSI_PIN = 51; // B2
|
||||
uint8_t const MISO_PIN = 50; // B3
|
||||
uint8_t const SCK_PIN = 52; // B1
|
||||
|
||||
static const pin_map_t digitalPinMap[] = {
|
||||
{&DDRE, &PINE, &PORTE, 0}, // E0 0
|
||||
{&DDRE, &PINE, &PORTE, 1}, // E1 1
|
||||
{&DDRE, &PINE, &PORTE, 4}, // E4 2
|
||||
{&DDRE, &PINE, &PORTE, 5}, // E5 3
|
||||
{&DDRG, &PING, &PORTG, 5}, // G5 4
|
||||
{&DDRE, &PINE, &PORTE, 3}, // E3 5
|
||||
{&DDRH, &PINH, &PORTH, 3}, // H3 6
|
||||
{&DDRH, &PINH, &PORTH, 4}, // H4 7
|
||||
{&DDRH, &PINH, &PORTH, 5}, // H5 8
|
||||
{&DDRH, &PINH, &PORTH, 6}, // H6 9
|
||||
{&DDRB, &PINB, &PORTB, 4}, // B4 10
|
||||
{&DDRB, &PINB, &PORTB, 5}, // B5 11
|
||||
{&DDRB, &PINB, &PORTB, 6}, // B6 12
|
||||
{&DDRB, &PINB, &PORTB, 7}, // B7 13
|
||||
{&DDRJ, &PINJ, &PORTJ, 1}, // J1 14
|
||||
{&DDRJ, &PINJ, &PORTJ, 0}, // J0 15
|
||||
{&DDRH, &PINH, &PORTH, 1}, // H1 16
|
||||
{&DDRH, &PINH, &PORTH, 0}, // H0 17
|
||||
{&DDRD, &PIND, &PORTD, 3}, // D3 18
|
||||
{&DDRD, &PIND, &PORTD, 2}, // D2 19
|
||||
{&DDRD, &PIND, &PORTD, 1}, // D1 20
|
||||
{&DDRD, &PIND, &PORTD, 0}, // D0 21
|
||||
{&DDRA, &PINA, &PORTA, 0}, // A0 22
|
||||
{&DDRA, &PINA, &PORTA, 1}, // A1 23
|
||||
{&DDRA, &PINA, &PORTA, 2}, // A2 24
|
||||
{&DDRA, &PINA, &PORTA, 3}, // A3 25
|
||||
{&DDRA, &PINA, &PORTA, 4}, // A4 26
|
||||
{&DDRA, &PINA, &PORTA, 5}, // A5 27
|
||||
{&DDRA, &PINA, &PORTA, 6}, // A6 28
|
||||
{&DDRA, &PINA, &PORTA, 7}, // A7 29
|
||||
{&DDRC, &PINC, &PORTC, 7}, // C7 30
|
||||
{&DDRC, &PINC, &PORTC, 6}, // C6 31
|
||||
{&DDRC, &PINC, &PORTC, 5}, // C5 32
|
||||
{&DDRC, &PINC, &PORTC, 4}, // C4 33
|
||||
{&DDRC, &PINC, &PORTC, 3}, // C3 34
|
||||
{&DDRC, &PINC, &PORTC, 2}, // C2 35
|
||||
{&DDRC, &PINC, &PORTC, 1}, // C1 36
|
||||
{&DDRC, &PINC, &PORTC, 0}, // C0 37
|
||||
{&DDRD, &PIND, &PORTD, 7}, // D7 38
|
||||
{&DDRG, &PING, &PORTG, 2}, // G2 39
|
||||
{&DDRG, &PING, &PORTG, 1}, // G1 40
|
||||
{&DDRG, &PING, &PORTG, 0}, // G0 41
|
||||
{&DDRL, &PINL, &PORTL, 7}, // L7 42
|
||||
{&DDRL, &PINL, &PORTL, 6}, // L6 43
|
||||
{&DDRL, &PINL, &PORTL, 5}, // L5 44
|
||||
{&DDRL, &PINL, &PORTL, 4}, // L4 45
|
||||
{&DDRL, &PINL, &PORTL, 3}, // L3 46
|
||||
{&DDRL, &PINL, &PORTL, 2}, // L2 47
|
||||
{&DDRL, &PINL, &PORTL, 1}, // L1 48
|
||||
{&DDRL, &PINL, &PORTL, 0}, // L0 49
|
||||
{&DDRB, &PINB, &PORTB, 3}, // B3 50
|
||||
{&DDRB, &PINB, &PORTB, 2}, // B2 51
|
||||
{&DDRB, &PINB, &PORTB, 1}, // B1 52
|
||||
{&DDRB, &PINB, &PORTB, 0}, // B0 53
|
||||
{&DDRF, &PINF, &PORTF, 0}, // F0 54
|
||||
{&DDRF, &PINF, &PORTF, 1}, // F1 55
|
||||
{&DDRF, &PINF, &PORTF, 2}, // F2 56
|
||||
{&DDRF, &PINF, &PORTF, 3}, // F3 57
|
||||
{&DDRF, &PINF, &PORTF, 4}, // F4 58
|
||||
{&DDRF, &PINF, &PORTF, 5}, // F5 59
|
||||
{&DDRF, &PINF, &PORTF, 6}, // F6 60
|
||||
{&DDRF, &PINF, &PORTF, 7}, // F7 61
|
||||
{&DDRK, &PINK, &PORTK, 0}, // K0 62
|
||||
{&DDRK, &PINK, &PORTK, 1}, // K1 63
|
||||
{&DDRK, &PINK, &PORTK, 2}, // K2 64
|
||||
{&DDRK, &PINK, &PORTK, 3}, // K3 65
|
||||
{&DDRK, &PINK, &PORTK, 4}, // K4 66
|
||||
{&DDRK, &PINK, &PORTK, 5}, // K5 67
|
||||
{&DDRK, &PINK, &PORTK, 6}, // K6 68
|
||||
{&DDRK, &PINK, &PORTK, 7} // K7 69
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
#elif defined(__AVR_ATmega644P__)\
|
||||
|| defined(__AVR_ATmega644__)\
|
||||
|| defined(__AVR_ATmega1284P__)
|
||||
// Sanguino
|
||||
|
||||
// Two Wire (aka I2C) ports
|
||||
uint8_t const SDA_PIN = 17; // C1
|
||||
uint8_t const SCL_PIN = 18; // C2
|
||||
|
||||
// SPI port
|
||||
uint8_t const SS_PIN = 4; // B4
|
||||
uint8_t const MOSI_PIN = 5; // B5
|
||||
uint8_t const MISO_PIN = 6; // B6
|
||||
uint8_t const SCK_PIN = 7; // B7
|
||||
|
||||
static const pin_map_t digitalPinMap[] = {
|
||||
{&DDRB, &PINB, &PORTB, 0}, // B0 0
|
||||
{&DDRB, &PINB, &PORTB, 1}, // B1 1
|
||||
{&DDRB, &PINB, &PORTB, 2}, // B2 2
|
||||
{&DDRB, &PINB, &PORTB, 3}, // B3 3
|
||||
{&DDRB, &PINB, &PORTB, 4}, // B4 4
|
||||
{&DDRB, &PINB, &PORTB, 5}, // B5 5
|
||||
{&DDRB, &PINB, &PORTB, 6}, // B6 6
|
||||
{&DDRB, &PINB, &PORTB, 7}, // B7 7
|
||||
{&DDRD, &PIND, &PORTD, 0}, // D0 8
|
||||
{&DDRD, &PIND, &PORTD, 1}, // D1 9
|
||||
{&DDRD, &PIND, &PORTD, 2}, // D2 10
|
||||
{&DDRD, &PIND, &PORTD, 3}, // D3 11
|
||||
{&DDRD, &PIND, &PORTD, 4}, // D4 12
|
||||
{&DDRD, &PIND, &PORTD, 5}, // D5 13
|
||||
{&DDRD, &PIND, &PORTD, 6}, // D6 14
|
||||
{&DDRD, &PIND, &PORTD, 7}, // D7 15
|
||||
{&DDRC, &PINC, &PORTC, 0}, // C0 16
|
||||
{&DDRC, &PINC, &PORTC, 1}, // C1 17
|
||||
{&DDRC, &PINC, &PORTC, 2}, // C2 18
|
||||
{&DDRC, &PINC, &PORTC, 3}, // C3 19
|
||||
{&DDRC, &PINC, &PORTC, 4}, // C4 20
|
||||
{&DDRC, &PINC, &PORTC, 5}, // C5 21
|
||||
{&DDRC, &PINC, &PORTC, 6}, // C6 22
|
||||
{&DDRC, &PINC, &PORTC, 7}, // C7 23
|
||||
{&DDRA, &PINA, &PORTA, 7}, // A7 24
|
||||
{&DDRA, &PINA, &PORTA, 6}, // A6 25
|
||||
{&DDRA, &PINA, &PORTA, 5}, // A5 26
|
||||
{&DDRA, &PINA, &PORTA, 4}, // A4 27
|
||||
{&DDRA, &PINA, &PORTA, 3}, // A3 28
|
||||
{&DDRA, &PINA, &PORTA, 2}, // A2 29
|
||||
{&DDRA, &PINA, &PORTA, 1}, // A1 30
|
||||
{&DDRA, &PINA, &PORTA, 0} // A0 31
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
#elif defined(__AVR_ATmega32U4__)
|
||||
// Teensy 2.0
|
||||
|
||||
// Two Wire (aka I2C) ports
|
||||
uint8_t const SDA_PIN = 6; // D1
|
||||
uint8_t const SCL_PIN = 5; // D0
|
||||
|
||||
// SPI port
|
||||
uint8_t const SS_PIN = 0; // B0
|
||||
uint8_t const MOSI_PIN = 2; // B2
|
||||
uint8_t const MISO_PIN = 3; // B3
|
||||
uint8_t const SCK_PIN = 1; // B1
|
||||
|
||||
static const pin_map_t digitalPinMap[] = {
|
||||
{&DDRB, &PINB, &PORTB, 0}, // B0 0
|
||||
{&DDRB, &PINB, &PORTB, 1}, // B1 1
|
||||
{&DDRB, &PINB, &PORTB, 2}, // B2 2
|
||||
{&DDRB, &PINB, &PORTB, 3}, // B3 3
|
||||
{&DDRB, &PINB, &PORTB, 7}, // B7 4
|
||||
{&DDRD, &PIND, &PORTD, 0}, // D0 5
|
||||
{&DDRD, &PIND, &PORTD, 1}, // D1 6
|
||||
{&DDRD, &PIND, &PORTD, 2}, // D2 7
|
||||
{&DDRD, &PIND, &PORTD, 3}, // D3 8
|
||||
{&DDRC, &PINC, &PORTC, 6}, // C6 9
|
||||
{&DDRC, &PINC, &PORTC, 7}, // C7 10
|
||||
{&DDRD, &PIND, &PORTD, 6}, // D6 11
|
||||
{&DDRD, &PIND, &PORTD, 7}, // D7 12
|
||||
{&DDRB, &PINB, &PORTB, 4}, // B4 13
|
||||
{&DDRB, &PINB, &PORTB, 5}, // B5 14
|
||||
{&DDRB, &PINB, &PORTB, 6}, // B6 15
|
||||
{&DDRF, &PINF, &PORTF, 7}, // F7 16
|
||||
{&DDRF, &PINF, &PORTF, 6}, // F6 17
|
||||
{&DDRF, &PINF, &PORTF, 5}, // F5 18
|
||||
{&DDRF, &PINF, &PORTF, 4}, // F4 19
|
||||
{&DDRF, &PINF, &PORTF, 1}, // F1 20
|
||||
{&DDRF, &PINF, &PORTF, 0}, // F0 21
|
||||
{&DDRD, &PIND, &PORTD, 4}, // D4 22
|
||||
{&DDRD, &PIND, &PORTD, 5}, // D5 23
|
||||
{&DDRE, &PINE, &PORTE, 6} // E6 24
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
#elif defined(__AVR_AT90USB646__)\
|
||||
|| defined(__AVR_AT90USB1286__)
|
||||
// Teensy++ 1.0 & 2.0
|
||||
|
||||
// Two Wire (aka I2C) ports
|
||||
uint8_t const SDA_PIN = 1; // D1
|
||||
uint8_t const SCL_PIN = 0; // D0
|
||||
|
||||
// SPI port
|
||||
uint8_t const SS_PIN = 20; // B0
|
||||
uint8_t const MOSI_PIN = 22; // B2
|
||||
uint8_t const MISO_PIN = 23; // B3
|
||||
uint8_t const SCK_PIN = 21; // B1
|
||||
|
||||
static const pin_map_t digitalPinMap[] = {
|
||||
{&DDRD, &PIND, &PORTD, 0}, // D0 0
|
||||
{&DDRD, &PIND, &PORTD, 1}, // D1 1
|
||||
{&DDRD, &PIND, &PORTD, 2}, // D2 2
|
||||
{&DDRD, &PIND, &PORTD, 3}, // D3 3
|
||||
{&DDRD, &PIND, &PORTD, 4}, // D4 4
|
||||
{&DDRD, &PIND, &PORTD, 5}, // D5 5
|
||||
{&DDRD, &PIND, &PORTD, 6}, // D6 6
|
||||
{&DDRD, &PIND, &PORTD, 7}, // D7 7
|
||||
{&DDRE, &PINE, &PORTE, 0}, // E0 8
|
||||
{&DDRE, &PINE, &PORTE, 1}, // E1 9
|
||||
{&DDRC, &PINC, &PORTC, 0}, // C0 10
|
||||
{&DDRC, &PINC, &PORTC, 1}, // C1 11
|
||||
{&DDRC, &PINC, &PORTC, 2}, // C2 12
|
||||
{&DDRC, &PINC, &PORTC, 3}, // C3 13
|
||||
{&DDRC, &PINC, &PORTC, 4}, // C4 14
|
||||
{&DDRC, &PINC, &PORTC, 5}, // C5 15
|
||||
{&DDRC, &PINC, &PORTC, 6}, // C6 16
|
||||
{&DDRC, &PINC, &PORTC, 7}, // C7 17
|
||||
{&DDRE, &PINE, &PORTE, 6}, // E6 18
|
||||
{&DDRE, &PINE, &PORTE, 7}, // E7 19
|
||||
{&DDRB, &PINB, &PORTB, 0}, // B0 20
|
||||
{&DDRB, &PINB, &PORTB, 1}, // B1 21
|
||||
{&DDRB, &PINB, &PORTB, 2}, // B2 22
|
||||
{&DDRB, &PINB, &PORTB, 3}, // B3 23
|
||||
{&DDRB, &PINB, &PORTB, 4}, // B4 24
|
||||
{&DDRB, &PINB, &PORTB, 5}, // B5 25
|
||||
{&DDRB, &PINB, &PORTB, 6}, // B6 26
|
||||
{&DDRB, &PINB, &PORTB, 7}, // B7 27
|
||||
{&DDRA, &PINA, &PORTA, 0}, // A0 28
|
||||
{&DDRA, &PINA, &PORTA, 1}, // A1 29
|
||||
{&DDRA, &PINA, &PORTA, 2}, // A2 30
|
||||
{&DDRA, &PINA, &PORTA, 3}, // A3 31
|
||||
{&DDRA, &PINA, &PORTA, 4}, // A4 32
|
||||
{&DDRA, &PINA, &PORTA, 5}, // A5 33
|
||||
{&DDRA, &PINA, &PORTA, 6}, // A6 34
|
||||
{&DDRA, &PINA, &PORTA, 7}, // A7 35
|
||||
{&DDRE, &PINE, &PORTE, 4}, // E4 36
|
||||
{&DDRE, &PINE, &PORTE, 5}, // E5 37
|
||||
{&DDRF, &PINF, &PORTF, 0}, // F0 38
|
||||
{&DDRF, &PINF, &PORTF, 1}, // F1 39
|
||||
{&DDRF, &PINF, &PORTF, 2}, // F2 40
|
||||
{&DDRF, &PINF, &PORTF, 3}, // F3 41
|
||||
{&DDRF, &PINF, &PORTF, 4}, // F4 42
|
||||
{&DDRF, &PINF, &PORTF, 5}, // F5 43
|
||||
{&DDRF, &PINF, &PORTF, 6}, // F6 44
|
||||
{&DDRF, &PINF, &PORTF, 7} // F7 45
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
#elif defined(__AVR_ATmega168__)\
|
||||
||defined(__AVR_ATmega168P__)\
|
||||
||defined(__AVR_ATmega328P__)
|
||||
// 168 and 328 Arduinos
|
||||
|
||||
// Two Wire (aka I2C) ports
|
||||
uint8_t const SDA_PIN = 18; // C4
|
||||
uint8_t const SCL_PIN = 19; // C5
|
||||
|
||||
// SPI port
|
||||
uint8_t const SS_PIN = 10; // B2
|
||||
uint8_t const MOSI_PIN = 11; // B3
|
||||
uint8_t const MISO_PIN = 12; // B4
|
||||
uint8_t const SCK_PIN = 13; // B5
|
||||
|
||||
static const pin_map_t digitalPinMap[] = {
|
||||
{&DDRD, &PIND, &PORTD, 0}, // D0 0
|
||||
{&DDRD, &PIND, &PORTD, 1}, // D1 1
|
||||
{&DDRD, &PIND, &PORTD, 2}, // D2 2
|
||||
{&DDRD, &PIND, &PORTD, 3}, // D3 3
|
||||
{&DDRD, &PIND, &PORTD, 4}, // D4 4
|
||||
{&DDRD, &PIND, &PORTD, 5}, // D5 5
|
||||
{&DDRD, &PIND, &PORTD, 6}, // D6 6
|
||||
{&DDRD, &PIND, &PORTD, 7}, // D7 7
|
||||
{&DDRB, &PINB, &PORTB, 0}, // B0 8
|
||||
{&DDRB, &PINB, &PORTB, 1}, // B1 9
|
||||
{&DDRB, &PINB, &PORTB, 2}, // B2 10
|
||||
{&DDRB, &PINB, &PORTB, 3}, // B3 11
|
||||
{&DDRB, &PINB, &PORTB, 4}, // B4 12
|
||||
{&DDRB, &PINB, &PORTB, 5}, // B5 13
|
||||
{&DDRC, &PINC, &PORTC, 0}, // C0 14
|
||||
{&DDRC, &PINC, &PORTC, 1}, // C1 15
|
||||
{&DDRC, &PINC, &PORTC, 2}, // C2 16
|
||||
{&DDRC, &PINC, &PORTC, 3}, // C3 17
|
||||
{&DDRC, &PINC, &PORTC, 4}, // C4 18
|
||||
{&DDRC, &PINC, &PORTC, 5} // C5 19
|
||||
};
|
||||
#else // defined(__AVR_ATmega1280__)
|
||||
#error unknown chip
|
||||
#endif // defined(__AVR_ATmega1280__)
|
||||
//------------------------------------------------------------------------------
|
||||
static const uint8_t digitalPinCount = sizeof(digitalPinMap)/sizeof(pin_map_t);
|
||||
|
||||
uint8_t badPinNumber(void)
|
||||
__attribute__((error("Pin number is too large or not a constant")));
|
||||
|
||||
static inline __attribute__((always_inline))
|
||||
bool getPinMode(uint8_t pin) {
|
||||
if (__builtin_constant_p(pin) && pin < digitalPinCount) {
|
||||
return (*digitalPinMap[pin].ddr >> digitalPinMap[pin].bit) & 1;
|
||||
} else {
|
||||
return badPinNumber();
|
||||
}
|
||||
}
|
||||
static inline __attribute__((always_inline))
|
||||
void setPinMode(uint8_t pin, uint8_t mode) {
|
||||
if (__builtin_constant_p(pin) && pin < digitalPinCount) {
|
||||
if (mode) {
|
||||
*digitalPinMap[pin].ddr |= 1 << digitalPinMap[pin].bit;
|
||||
} else {
|
||||
*digitalPinMap[pin].ddr &= ~(1 << digitalPinMap[pin].bit);
|
||||
}
|
||||
} else {
|
||||
badPinNumber();
|
||||
}
|
||||
}
|
||||
static inline __attribute__((always_inline))
|
||||
bool fastDigitalRead(uint8_t pin) {
|
||||
if (__builtin_constant_p(pin) && pin < digitalPinCount) {
|
||||
return (*digitalPinMap[pin].pin >> digitalPinMap[pin].bit) & 1;
|
||||
} else {
|
||||
return badPinNumber();
|
||||
}
|
||||
}
|
||||
static inline __attribute__((always_inline))
|
||||
void fastDigitalWrite(uint8_t pin, uint8_t value) {
|
||||
if (__builtin_constant_p(pin) && pin < digitalPinCount) {
|
||||
if (value) {
|
||||
*digitalPinMap[pin].port |= 1 << digitalPinMap[pin].bit;
|
||||
} else {
|
||||
*digitalPinMap[pin].port &= ~(1 << digitalPinMap[pin].bit);
|
||||
}
|
||||
} else {
|
||||
badPinNumber();
|
||||
}
|
||||
}
|
||||
#endif // Sd2PinMap_h
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -1015,7 +1015,7 @@ void SdBaseFile::printFatTime( uint16_t fatTime) {
|
|||
* the value zero, false, is returned for failure.
|
||||
*/
|
||||
bool SdBaseFile::printName() {
|
||||
char name[FILENAME_LENGTH];
|
||||
char name[13];
|
||||
if (!getFilename(name)) return false;
|
||||
MYSERIAL.print(name);
|
||||
return true;
|
||||
|
|
@ -1115,7 +1115,7 @@ int8_t SdBaseFile::readDir(dir_t* dir, char* longFilename) {
|
|||
int16_t n;
|
||||
// if not a directory file or miss-positioned return an error
|
||||
if (!isDir() || (0X1F & curPosition_)) return -1;
|
||||
|
||||
|
||||
//If we have a longFilename buffer, mark it as invalid. If we find a long filename it will be filled automaticly.
|
||||
if (longFilename != NULL)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -281,7 +281,7 @@ class SdBaseFile {
|
|||
static void printFatDate(uint16_t fatDate);
|
||||
static void printFatTime( uint16_t fatTime);
|
||||
bool printName();
|
||||
protected:
|
||||
protected:
|
||||
int16_t read();
|
||||
int16_t read(void* buf, uint16_t nbyte);
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -468,29 +468,29 @@ uint32_t const FAT32MASK = 0X0FFFFFFF;
|
|||
* \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
|
||||
*
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* 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
|
||||
* 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 {
|
||||
|
|
@ -548,7 +548,7 @@ struct directoryEntry {
|
|||
*
|
||||
* 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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ int SdFatUtil::FreeRam() {
|
|||
#endif // __arm
|
||||
|
||||
void SdFatUtil::set_stack_guard()
|
||||
{
|
||||
{
|
||||
uint32_t *stack_guard;
|
||||
|
||||
stack_guard = (uint32_t*)(&__bss_end + STACK_GUARD_MARGIN);
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ int16_t SdFile::readFilteredGcode(){
|
|||
|
||||
// It may seem unreasonable to copy the variable into a local one and copy it back at the end of this method,
|
||||
// but there is an important point of view: the compiler is unsure whether it can optimize the reads/writes
|
||||
// to gfReadPtr within this method, because it is a class member variable.
|
||||
// to gfReadPtr within this method, because it is a class member variable.
|
||||
// The compiler cannot see, if omitting read/write won't have any incorrect side-effects to the rest of the whole FW.
|
||||
// So this trick explicitly states, that rdPtr is a local variable limited to the scope of this method,
|
||||
// therefore the compiler can omit read/write to it (keep it in registers!) as it sees fit.
|
||||
|
|
@ -96,7 +96,7 @@ int16_t SdFile::readFilteredGcode(){
|
|||
|
||||
// the same applies to gfXBegin, codesize dropped another 100B!
|
||||
const uint8_t *blockBuffBegin = gfBlockBuffBegin();
|
||||
|
||||
|
||||
uint8_t consecutiveCommentLines = 0;
|
||||
while( *rdPtr == ';' ){
|
||||
for(;;){
|
||||
|
|
@ -104,8 +104,8 @@ int16_t SdFile::readFilteredGcode(){
|
|||
//while( *(++gfReadPtr) != '\n' ); // skip until a newline is found - suboptimal code!
|
||||
// Wondering, why this "nice while cycle" is done in such a weird way using a separate find_endl() function?
|
||||
// Have a look at the ASM code GCC produced!
|
||||
|
||||
// At first - a separate find_endl() makes the compiler understand,
|
||||
|
||||
// At first - a separate find_endl() makes the compiler understand,
|
||||
// that I don't need to store gfReadPtr every time, I'm only interested in the final address where the '\n' was found
|
||||
// - the cycle can run on CPU registers only without touching memory besides reading the character being compared.
|
||||
// Not only makes the code run considerably faster, but is also 40B shorter!
|
||||
|
|
@ -118,7 +118,7 @@ int16_t SdFile::readFilteredGcode(){
|
|||
// 11c62: sbci r19, 0xFF ; 255
|
||||
// 11c64: ld r22, Z
|
||||
// 11c66: cpi r22, 0x0A ; 10
|
||||
// 11c68: brne .-12 ; 0x11c5e <get_command()+0x524>
|
||||
// 11c68: brne .-12 ; 0x11c5e <get_command()+0x524>
|
||||
|
||||
// Still, even that was suboptimal as the compiler seems not to understand the usage of ld r22, Z+ (the plus is important)
|
||||
// aka automatic increment of the Z register (R30:R31 pair)
|
||||
|
|
@ -153,7 +153,7 @@ emit_char:
|
|||
{
|
||||
gfUpdateCurrentPosition( rdPtr - start + 1 );
|
||||
int16_t rv = *rdPtr++;
|
||||
|
||||
|
||||
if( curPosition_ >= fileSize_ ){
|
||||
// past the end of file
|
||||
goto eof_or_fail;
|
||||
|
|
@ -200,7 +200,7 @@ bool SdFile::gfComputeNextFileBlock() {
|
|||
// SHR by 9 means skip the last byte and shift just 3 bytes by 1
|
||||
// -> should be 8 instructions... and not the horrible loop shifting 4 bytes at once
|
||||
// still need to get some work on this
|
||||
gfBlock = vol_->rootDirStart() + (curPosition_ >> 9);
|
||||
gfBlock = vol_->rootDirStart() + (curPosition_ >> 9);
|
||||
} else {
|
||||
uint8_t blockOfCluster = vol_->blockOfCluster(curPosition_);
|
||||
if (gfOffset == 0 && blockOfCluster == 0) {
|
||||
|
|
|
|||
|
|
@ -35,19 +35,19 @@
|
|||
*/
|
||||
class SdFile : public SdBaseFile/*, public Print*/ {
|
||||
// GCode filtering vars and methods - due to optimization reasons not wrapped in a separate class
|
||||
|
||||
|
||||
// beware - this read ptr is manipulated inside just 2 methods - readFilteredGcode and gfReset
|
||||
// If you even want to call gfReset from readFilteredGcode, you must make sure
|
||||
// to update gfReadPtr inside readFilteredGcode from a local copy (see explanation of this trick in readFilteredGcode)
|
||||
const uint8_t *gfReadPtr;
|
||||
|
||||
|
||||
uint32_t gfBlock; // remember the current file block to be kept in cache - due to reuse of the memory, the block may fall out a must be read back
|
||||
uint16_t gfOffset;
|
||||
|
||||
const uint8_t *gfBlockBuffBegin()const;
|
||||
|
||||
|
||||
void gfReset();
|
||||
|
||||
|
||||
bool gfEnsureBlock();
|
||||
bool gfComputeNextFileBlock();
|
||||
void gfUpdateCurrentPosition(uint16_t inc);
|
||||
|
|
@ -59,7 +59,7 @@ public:
|
|||
#else
|
||||
void write(uint8_t b);
|
||||
#endif
|
||||
|
||||
|
||||
bool openFilteredGcode(SdBaseFile* dirFile, const char* path);
|
||||
int16_t readFilteredGcode();
|
||||
bool seekSetFilteredGcode(uint32_t pos);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,344 @@
|
|||
/*
|
||||
Servo.cpp - Interrupt driven Servo library for Arduino using 16 bit timers- Version 2
|
||||
Copyright (c) 2009 Michael Margolis. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
A servo is activated by creating an instance of the Servo class passing the desired pin to the attach() method.
|
||||
The servos are pulsed in the background using the value most recently written using the write() method
|
||||
|
||||
Note that analogWrite of PWM on pins associated with the timer are disabled when the first servo is attached.
|
||||
Timers are seized as needed in groups of 12 servos - 24 servos use two timers, 48 servos will use four.
|
||||
|
||||
The methods are:
|
||||
|
||||
Servo - Class for manipulating servo motors connected to Arduino pins.
|
||||
|
||||
attach(pin ) - Attaches a servo motor to an i/o pin.
|
||||
attach(pin, min, max ) - Attaches to a pin setting min and max values in microseconds
|
||||
default min is 544, max is 2400
|
||||
|
||||
write() - Sets the servo angle in degrees. (invalid angle that is valid as pulse in microseconds is treated as microseconds)
|
||||
writeMicroseconds() - Sets the servo pulse width in microseconds
|
||||
read() - Gets the last written servo pulse width as an angle between 0 and 180.
|
||||
readMicroseconds() - Gets the last written servo pulse width in microseconds. (was read_us() in first release)
|
||||
attached() - Returns true if there is a servo attached.
|
||||
detach() - Stops an attached servos from pulsing its i/o pin.
|
||||
|
||||
*/
|
||||
#include "Configuration.h"
|
||||
|
||||
#ifdef NUM_SERVOS
|
||||
#include <avr/interrupt.h>
|
||||
#include <Arduino.h>
|
||||
|
||||
#include "Servo.h"
|
||||
|
||||
#define usToTicks(_us) (( clockCyclesPerMicrosecond()* _us) / 8) // converts microseconds to tick (assumes prescale of 8) // 12 Aug 2009
|
||||
#define ticksToUs(_ticks) (( (unsigned)_ticks * 8)/ clockCyclesPerMicrosecond() ) // converts from ticks back to microseconds
|
||||
|
||||
|
||||
#define TRIM_DURATION 2 // compensation ticks to trim adjust for digitalWrite delays // 12 August 2009
|
||||
|
||||
//#define NBR_TIMERS (MAX_SERVOS / SERVOS_PER_TIMER)
|
||||
|
||||
static servo_t servos[MAX_SERVOS]; // static array of servo structures
|
||||
static volatile int8_t Channel[_Nbr_16timers ]; // counter for the servo being pulsed for each timer (or -1 if refresh interval)
|
||||
|
||||
uint8_t ServoCount = 0; // the total number of attached servos
|
||||
|
||||
|
||||
// convenience macros
|
||||
#define SERVO_INDEX_TO_TIMER(_servo_nbr) ((timer16_Sequence_t)(_servo_nbr / SERVOS_PER_TIMER)) // returns the timer controlling this servo
|
||||
#define SERVO_INDEX_TO_CHANNEL(_servo_nbr) (_servo_nbr % SERVOS_PER_TIMER) // returns the index of the servo on this timer
|
||||
#define SERVO_INDEX(_timer,_channel) ((_timer*SERVOS_PER_TIMER) + _channel) // macro to access servo index by timer and channel
|
||||
#define SERVO(_timer,_channel) (servos[SERVO_INDEX(_timer,_channel)]) // macro to access servo class by timer and channel
|
||||
|
||||
#define SERVO_MIN() (MIN_PULSE_WIDTH - this->min * 4) // minimum value in uS for this servo
|
||||
#define SERVO_MAX() (MAX_PULSE_WIDTH - this->max * 4) // maximum value in uS for this servo
|
||||
|
||||
/************ static functions common to all instances ***********************/
|
||||
|
||||
static inline void handle_interrupts(timer16_Sequence_t timer, volatile uint16_t *TCNTn, volatile uint16_t* OCRnA)
|
||||
{
|
||||
if( Channel[timer] < 0 )
|
||||
*TCNTn = 0; // channel set to -1 indicated that refresh interval completed so reset the timer
|
||||
else{
|
||||
if( SERVO_INDEX(timer,Channel[timer]) < ServoCount && SERVO(timer,Channel[timer]).Pin.isActive == true )
|
||||
digitalWrite( SERVO(timer,Channel[timer]).Pin.nbr,LOW); // pulse this channel low if activated
|
||||
}
|
||||
|
||||
Channel[timer]++; // increment to the next channel
|
||||
if( SERVO_INDEX(timer,Channel[timer]) < ServoCount && Channel[timer] < SERVOS_PER_TIMER) {
|
||||
*OCRnA = *TCNTn + SERVO(timer,Channel[timer]).ticks;
|
||||
if(SERVO(timer,Channel[timer]).Pin.isActive == true) // check if activated
|
||||
digitalWrite( SERVO(timer,Channel[timer]).Pin.nbr,HIGH); // its an active channel so pulse it high
|
||||
}
|
||||
else {
|
||||
// finished all channels so wait for the refresh period to expire before starting over
|
||||
if( ((unsigned)*TCNTn) + 4 < usToTicks(REFRESH_INTERVAL) ) // allow a few ticks to ensure the next OCR1A not missed
|
||||
*OCRnA = (unsigned int)usToTicks(REFRESH_INTERVAL);
|
||||
else
|
||||
*OCRnA = *TCNTn + 4; // at least REFRESH_INTERVAL has elapsed
|
||||
Channel[timer] = -1; // this will get incremented at the end of the refresh period to start again at the first channel
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef WIRING // Wiring pre-defines signal handlers so don't define any if compiling for the Wiring platform
|
||||
// Interrupt handlers for Arduino
|
||||
#if defined(_useTimer1)
|
||||
SIGNAL (TIMER1_COMPA_vect)
|
||||
{
|
||||
handle_interrupts(_timer1, &TCNT1, &OCR1A);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(_useTimer3)
|
||||
SIGNAL (TIMER3_COMPA_vect)
|
||||
{
|
||||
handle_interrupts(_timer3, &TCNT3, &OCR3A);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(_useTimer4)
|
||||
SIGNAL (TIMER4_COMPA_vect)
|
||||
{
|
||||
handle_interrupts(_timer4, &TCNT4, &OCR4A);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(_useTimer5)
|
||||
SIGNAL (TIMER5_COMPA_vect)
|
||||
{
|
||||
handle_interrupts(_timer5, &TCNT5, &OCR5A);
|
||||
}
|
||||
#endif
|
||||
|
||||
#elif defined WIRING
|
||||
// Interrupt handlers for Wiring
|
||||
#if defined(_useTimer1)
|
||||
void Timer1Service()
|
||||
{
|
||||
handle_interrupts(_timer1, &TCNT1, &OCR1A);
|
||||
}
|
||||
#endif
|
||||
#if defined(_useTimer3)
|
||||
void Timer3Service()
|
||||
{
|
||||
handle_interrupts(_timer3, &TCNT3, &OCR3A);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
static void initISR(timer16_Sequence_t timer)
|
||||
{
|
||||
#if defined (_useTimer1)
|
||||
if(timer == _timer1) {
|
||||
TCCR1A = 0; // normal counting mode
|
||||
TCCR1B = _BV(CS11); // set prescaler of 8
|
||||
TCNT1 = 0; // clear the timer count
|
||||
#if defined(__AVR_ATmega8__)|| defined(__AVR_ATmega128__)
|
||||
TIFR |= _BV(OCF1A); // clear any pending interrupts;
|
||||
TIMSK |= _BV(OCIE1A) ; // enable the output compare interrupt
|
||||
#else
|
||||
// here if not ATmega8 or ATmega128
|
||||
TIFR1 |= _BV(OCF1A); // clear any pending interrupts;
|
||||
TIMSK1 |= _BV(OCIE1A) ; // enable the output compare interrupt
|
||||
#endif
|
||||
#if defined(WIRING)
|
||||
timerAttach(TIMER1OUTCOMPAREA_INT, Timer1Service);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined (_useTimer3)
|
||||
if(timer == _timer3) {
|
||||
TCCR3A = 0; // normal counting mode
|
||||
TCCR3B = _BV(CS31); // set prescaler of 8
|
||||
TCNT3 = 0; // clear the timer count
|
||||
#if defined(__AVR_ATmega128__)
|
||||
TIFR |= _BV(OCF3A); // clear any pending interrupts;
|
||||
ETIMSK |= _BV(OCIE3A); // enable the output compare interrupt
|
||||
#else
|
||||
TIFR3 = _BV(OCF3A); // clear any pending interrupts;
|
||||
TIMSK3 = _BV(OCIE3A) ; // enable the output compare interrupt
|
||||
#endif
|
||||
#if defined(WIRING)
|
||||
timerAttach(TIMER3OUTCOMPAREA_INT, Timer3Service); // for Wiring platform only
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined (_useTimer4)
|
||||
if(timer == _timer4) {
|
||||
TCCR4A = 0; // normal counting mode
|
||||
TCCR4B = _BV(CS41); // set prescaler of 8
|
||||
TCNT4 = 0; // clear the timer count
|
||||
TIFR4 = _BV(OCF4A); // clear any pending interrupts;
|
||||
TIMSK4 = _BV(OCIE4A) ; // enable the output compare interrupt
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined (_useTimer5)
|
||||
if(timer == _timer5) {
|
||||
TCCR5A = 0; // normal counting mode
|
||||
TCCR5B = _BV(CS51); // set prescaler of 8
|
||||
TCNT5 = 0; // clear the timer count
|
||||
TIFR5 = _BV(OCF5A); // clear any pending interrupts;
|
||||
TIMSK5 = _BV(OCIE5A) ; // enable the output compare interrupt
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void finISR(timer16_Sequence_t timer)
|
||||
{
|
||||
//disable use of the given timer
|
||||
#if defined WIRING // Wiring
|
||||
if(timer == _timer1) {
|
||||
#if defined(__AVR_ATmega1281__)||defined(__AVR_ATmega2561__)
|
||||
TIMSK1 &= ~_BV(OCIE1A) ; // disable timer 1 output compare interrupt
|
||||
#else
|
||||
TIMSK &= ~_BV(OCIE1A) ; // disable timer 1 output compare interrupt
|
||||
#endif
|
||||
timerDetach(TIMER1OUTCOMPAREA_INT);
|
||||
}
|
||||
else if(timer == _timer3) {
|
||||
#if defined(__AVR_ATmega1281__)||defined(__AVR_ATmega2561__)
|
||||
TIMSK3 &= ~_BV(OCIE3A); // disable the timer3 output compare A interrupt
|
||||
#else
|
||||
ETIMSK &= ~_BV(OCIE3A); // disable the timer3 output compare A interrupt
|
||||
#endif
|
||||
timerDetach(TIMER3OUTCOMPAREA_INT);
|
||||
}
|
||||
#else
|
||||
//For arduino - in future: call here to a currently undefined function to reset the timer
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool isTimerActive(timer16_Sequence_t timer)
|
||||
{
|
||||
// returns true if any servo is active on this timer
|
||||
for(uint8_t channel=0; channel < SERVOS_PER_TIMER; channel++) {
|
||||
if(SERVO(timer,channel).Pin.isActive == true)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/****************** end of static functions ******************************/
|
||||
|
||||
Servo::Servo()
|
||||
{
|
||||
if( ServoCount < MAX_SERVOS) {
|
||||
this->servoIndex = ServoCount++; // assign a servo index to this instance
|
||||
servos[this->servoIndex].ticks = usToTicks(DEFAULT_PULSE_WIDTH); // store default values - 12 Aug 2009
|
||||
}
|
||||
else
|
||||
this->servoIndex = INVALID_SERVO ; // too many servos
|
||||
}
|
||||
|
||||
uint8_t Servo::attach(int pin)
|
||||
{
|
||||
return this->attach(pin, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);
|
||||
}
|
||||
|
||||
uint8_t Servo::attach(int pin, int min, int max)
|
||||
{
|
||||
if(this->servoIndex < MAX_SERVOS ) {
|
||||
#if defined (ENABLE_AUTO_BED_LEVELING) && (PROBE_SERVO_DEACTIVATION_DELAY > 0)
|
||||
if (pin > 0) this->pin = pin; else pin = this->pin;
|
||||
#endif
|
||||
pinMode( pin, OUTPUT) ; // set servo pin to output
|
||||
servos[this->servoIndex].Pin.nbr = pin;
|
||||
// todo min/max check: abs(min - MIN_PULSE_WIDTH) /4 < 128
|
||||
this->min = (MIN_PULSE_WIDTH - min)/4; //resolution of min/max is 4 uS
|
||||
this->max = (MAX_PULSE_WIDTH - max)/4;
|
||||
// initialize the timer if it has not already been initialized
|
||||
timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(servoIndex);
|
||||
if(isTimerActive(timer) == false)
|
||||
initISR(timer);
|
||||
servos[this->servoIndex].Pin.isActive = true; // this must be set after the check for isTimerActive
|
||||
}
|
||||
return this->servoIndex ;
|
||||
}
|
||||
|
||||
void Servo::detach()
|
||||
{
|
||||
servos[this->servoIndex].Pin.isActive = false;
|
||||
timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(servoIndex);
|
||||
if(isTimerActive(timer) == false) {
|
||||
finISR(timer);
|
||||
}
|
||||
}
|
||||
|
||||
void Servo::write(int value)
|
||||
{
|
||||
if(value < MIN_PULSE_WIDTH)
|
||||
{ // treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds)
|
||||
if(value < 0) value = 0;
|
||||
if(value > 180) value = 180;
|
||||
value = map(value, 0, 180, SERVO_MIN(), SERVO_MAX());
|
||||
}
|
||||
this->writeMicroseconds(value);
|
||||
}
|
||||
|
||||
void Servo::writeMicroseconds(int value)
|
||||
{
|
||||
// calculate and store the values for the given channel
|
||||
byte channel = this->servoIndex;
|
||||
if( (channel < MAX_SERVOS) ) // ensure channel is valid
|
||||
{
|
||||
if( value < SERVO_MIN() ) // ensure pulse width is valid
|
||||
value = SERVO_MIN();
|
||||
else if( value > SERVO_MAX() )
|
||||
value = SERVO_MAX();
|
||||
|
||||
value = value - TRIM_DURATION;
|
||||
value = usToTicks(value); // convert to ticks after compensating for interrupt overhead - 12 Aug 2009
|
||||
|
||||
uint8_t oldSREG = SREG;
|
||||
cli();
|
||||
servos[channel].ticks = value;
|
||||
SREG = oldSREG;
|
||||
}
|
||||
}
|
||||
|
||||
int Servo::read() // return the value as degrees
|
||||
{
|
||||
return map( this->readMicroseconds()+1, SERVO_MIN(), SERVO_MAX(), 0, 180);
|
||||
}
|
||||
|
||||
int Servo::readMicroseconds()
|
||||
{
|
||||
unsigned int pulsewidth;
|
||||
if( this->servoIndex != INVALID_SERVO )
|
||||
pulsewidth = ticksToUs(servos[this->servoIndex].ticks) + TRIM_DURATION ; // 12 aug 2009
|
||||
else
|
||||
pulsewidth = 0;
|
||||
|
||||
return pulsewidth;
|
||||
}
|
||||
|
||||
bool Servo::attached()
|
||||
{
|
||||
return servos[this->servoIndex].Pin.isActive ;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
Servo.h - Interrupt driven Servo library for Arduino using 16 bit timers- Version 2
|
||||
Copyright (c) 2009 Michael Margolis. All right reserved.
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
A servo is activated by creating an instance of the Servo class passing the desired pin to the attach() method.
|
||||
The servos are pulsed in the background using the value most recently written using the write() method
|
||||
|
||||
Note that analogWrite of PWM on pins associated with the timer are disabled when the first servo is attached.
|
||||
Timers are seized as needed in groups of 12 servos - 24 servos use two timers, 48 servos will use four.
|
||||
The sequence used to seize timers is defined in timers.h
|
||||
|
||||
The methods are:
|
||||
|
||||
Servo - Class for manipulating servo motors connected to Arduino pins.
|
||||
|
||||
attach(pin ) - Attaches a servo motor to an i/o pin.
|
||||
attach(pin, min, max ) - Attaches to a pin setting min and max values in microseconds
|
||||
default min is 544, max is 2400
|
||||
|
||||
write() - Sets the servo angle in degrees. (invalid angle that is valid as pulse in microseconds is treated as microseconds)
|
||||
writeMicroseconds() - Sets the servo pulse width in microseconds
|
||||
read() - Gets the last written servo pulse width as an angle between 0 and 180.
|
||||
readMicroseconds() - Gets the last written servo pulse width in microseconds. (was read_us() in first release)
|
||||
attached() - Returns true if there is a servo attached.
|
||||
detach() - Stops an attached servos from pulsing its i/o pin.
|
||||
*/
|
||||
|
||||
#ifndef Servo_h
|
||||
#define Servo_h
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
/*
|
||||
* Defines for 16 bit timers used with Servo library
|
||||
*
|
||||
* If _useTimerX is defined then TimerX is a 16 bit timer on the current board
|
||||
* timer16_Sequence_t enumerates the sequence that the timers should be allocated
|
||||
* _Nbr_16timers indicates how many 16 bit timers are available.
|
||||
*
|
||||
*/
|
||||
|
||||
// Say which 16 bit timers can be used and in what order
|
||||
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
|
||||
#define _useTimer5
|
||||
//#define _useTimer1
|
||||
#define _useTimer3
|
||||
#define _useTimer4
|
||||
//typedef enum { _timer5, _timer1, _timer3, _timer4, _Nbr_16timers } timer16_Sequence_t ;
|
||||
typedef enum { _timer5, _timer3, _timer4, _Nbr_16timers } timer16_Sequence_t ;
|
||||
|
||||
#elif defined(__AVR_ATmega32U4__)
|
||||
//#define _useTimer1
|
||||
#define _useTimer3
|
||||
//typedef enum { _timer1, _Nbr_16timers } timer16_Sequence_t ;
|
||||
typedef enum { _timer3, _Nbr_16timers } timer16_Sequence_t ;
|
||||
|
||||
#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
|
||||
#define _useTimer3
|
||||
//#define _useTimer1
|
||||
//typedef enum { _timer3, _timer1, _Nbr_16timers } timer16_Sequence_t ;
|
||||
typedef enum { _timer3, _Nbr_16timers } timer16_Sequence_t ;
|
||||
|
||||
#elif defined(__AVR_ATmega128__) ||defined(__AVR_ATmega1281__) || defined(__AVR_ATmega1284P__) ||defined(__AVR_ATmega2561__)
|
||||
#define _useTimer3
|
||||
//#define _useTimer1
|
||||
//typedef enum { _timer3, _timer1, _Nbr_16timers } timer16_Sequence_t ;
|
||||
typedef enum { _timer3, _Nbr_16timers } timer16_Sequence_t ;
|
||||
|
||||
#else // everything else
|
||||
//#define _useTimer1
|
||||
//typedef enum { _timer1, _Nbr_16timers } timer16_Sequence_t ;
|
||||
typedef enum { _Nbr_16timers } timer16_Sequence_t ;
|
||||
#endif
|
||||
|
||||
#define Servo_VERSION 2 // software version of this library
|
||||
|
||||
#define MIN_PULSE_WIDTH 544 // the shortest pulse sent to a servo
|
||||
#define MAX_PULSE_WIDTH 2400 // the longest pulse sent to a servo
|
||||
#define DEFAULT_PULSE_WIDTH 1500 // default pulse width when servo is attached
|
||||
#define REFRESH_INTERVAL 20000 // minimum time to refresh servos in microseconds
|
||||
|
||||
#define SERVOS_PER_TIMER 12 // the maximum number of servos controlled by one timer
|
||||
#define MAX_SERVOS (_Nbr_16timers * SERVOS_PER_TIMER)
|
||||
|
||||
#define INVALID_SERVO 255 // flag indicating an invalid servo index
|
||||
|
||||
typedef struct {
|
||||
uint8_t nbr :6 ; // a pin number from 0 to 63
|
||||
uint8_t isActive :1 ; // true if this channel is enabled, pin not pulsed if false
|
||||
} ServoPin_t ;
|
||||
|
||||
typedef struct {
|
||||
ServoPin_t Pin;
|
||||
unsigned int ticks;
|
||||
} servo_t;
|
||||
|
||||
class Servo
|
||||
{
|
||||
public:
|
||||
Servo();
|
||||
uint8_t attach(int pin); // attach the given pin to the next free channel, sets pinMode, returns channel number or 0 if failure
|
||||
uint8_t attach(int pin, int min, int max); // as above but also sets min and max values for writes.
|
||||
void detach();
|
||||
void write(int value); // if value is < 200 it is treated as an angle, otherwise as pulse width in microseconds
|
||||
void writeMicroseconds(int value); // Write pulse width in microseconds
|
||||
int read(); // returns current pulse width as an angle between 0 and 180 degrees
|
||||
int readMicroseconds(); // returns current pulse width in microseconds for this servo (was read_us() in first release)
|
||||
bool attached(); // return true if this servo is attached, otherwise false
|
||||
#if defined (ENABLE_AUTO_BED_LEVELING) && (PROBE_SERVO_DEACTIVATION_DELAY > 0)
|
||||
int pin; // store the hardware pin of the servo
|
||||
#endif
|
||||
private:
|
||||
uint8_t servoIndex; // index into the channel data for this servo
|
||||
int8_t min; // minimum is this value times 4 added to MIN_PULSE_WIDTH
|
||||
int8_t max; // maximum is this value times 4 added to MAX_PULSE_WIDTH
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
#include "SpoolJoin.h"
|
||||
#include "Marlin.h"
|
||||
#include "eeprom.h"
|
||||
#include "messages.h"
|
||||
#include "language.h"
|
||||
|
||||
namespace SpoolJoin {
|
||||
|
||||
SpoolJoin spooljoin;
|
||||
|
||||
SpoolJoin::SpoolJoin()
|
||||
: currentMMUSlot(0)
|
||||
{
|
||||
}
|
||||
|
||||
void SpoolJoin::initSpoolJoinStatus()
|
||||
{
|
||||
// Useful information to see during bootup
|
||||
SERIAL_ECHOPGM("SpoolJoin is ");
|
||||
uint8_t status = eeprom_init_default_byte((uint8_t*)EEPROM_SPOOL_JOIN, (uint8_t)EEPROM::Disabled);
|
||||
if (status == (uint8_t)EEPROM::Enabled)
|
||||
{
|
||||
SERIAL_ECHOLNRPGM(_O(MSG_ON));
|
||||
} else {
|
||||
SERIAL_ECHOLNRPGM(_O(MSG_OFF));
|
||||
}
|
||||
}
|
||||
|
||||
void SpoolJoin::toggleSpoolJoin()
|
||||
{
|
||||
if (eeprom_read_byte((uint8_t*)EEPROM_SPOOL_JOIN) == (uint8_t)EEPROM::Disabled)
|
||||
{
|
||||
eeprom_update_byte_notify((uint8_t*)EEPROM_SPOOL_JOIN, (uint8_t)EEPROM::Enabled);
|
||||
} else {
|
||||
eeprom_update_byte_notify((uint8_t*)EEPROM_SPOOL_JOIN, (uint8_t)EEPROM::Disabled);
|
||||
}
|
||||
}
|
||||
|
||||
bool SpoolJoin::isSpoolJoinEnabled()
|
||||
{
|
||||
if(eeprom_read_byte((uint8_t*)EEPROM_SPOOL_JOIN) == (uint8_t)EEPROM::Enabled) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void SpoolJoin::setSlot(uint8_t slot)
|
||||
{
|
||||
currentMMUSlot = slot;
|
||||
}
|
||||
|
||||
uint8_t SpoolJoin::nextSlot()
|
||||
{
|
||||
SERIAL_ECHOPGM("SpoolJoin: ");
|
||||
SERIAL_ECHO((int)currentMMUSlot);
|
||||
|
||||
if (currentMMUSlot >= MMU_FILAMENT_COUNT-1) currentMMUSlot = 0;
|
||||
else currentMMUSlot++;
|
||||
|
||||
SERIAL_ECHOPGM(" -> ");
|
||||
SERIAL_ECHOLN((int)currentMMUSlot);
|
||||
|
||||
return currentMMUSlot;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
/// @file
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
// See documentation here: https://help.prusa3d.com/article/spooljoin-mmu2s_134252
|
||||
|
||||
namespace SpoolJoin {
|
||||
|
||||
class SpoolJoin {
|
||||
public:
|
||||
SpoolJoin();
|
||||
|
||||
enum class EEPROM : uint8_t {
|
||||
Unknown, ///< SpoolJoin is unknown while printer is booting up
|
||||
Enabled, ///< SpoolJoin is enabled in EEPROM
|
||||
Disabled, ///< SpoolJoin is disabled in EEPROM
|
||||
Empty = 0xFF ///< EEPROM has not been set before and all bits are 1 (0xFF) - either a new printer or user erased the memory
|
||||
};
|
||||
|
||||
/// @brief Called when EEPROM is ready to be read
|
||||
void initSpoolJoinStatus();
|
||||
|
||||
/// @brief Toggle SpoolJoin
|
||||
static void toggleSpoolJoin();
|
||||
|
||||
/// @brief Check if SpoolJoin is enabled
|
||||
/// @returns true if enabled, false if disabled
|
||||
bool isSpoolJoinEnabled();
|
||||
|
||||
/// @brief Update the saved MMU slot number so SpoolJoin can determine the next slot to use
|
||||
/// @param slot number of the slot to set
|
||||
void setSlot(uint8_t slot);
|
||||
|
||||
/// @brief Fetch the next slot number should count from 0 to 4.
|
||||
/// When filament slot 4 is depleted, the next slot should be 0.
|
||||
/// @returns the next slot, ranges from 0 to 4
|
||||
uint8_t nextSlot();
|
||||
|
||||
private:
|
||||
/// @brief Currently used slot, ranges from 0 to 4
|
||||
uint8_t currentMMUSlot;
|
||||
};
|
||||
|
||||
extern SpoolJoin spooljoin;
|
||||
|
||||
} // namespace SpoolJoin
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
#include "Tcodes.h"
|
||||
#include "SpoolJoin.h"
|
||||
#include "Marlin.h"
|
||||
#include "language.h"
|
||||
#include "messages.h"
|
||||
#include "mmu2.h"
|
||||
#include "ultralcd.h"
|
||||
#include <avr/pgmspace.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static const char duplicate_Tcode_ignored[] PROGMEM = "Duplicate T-code ignored.";
|
||||
|
||||
inline bool IsInvalidTCode(char *const s, uint8_t i) {
|
||||
return ((s[i] < '0' || s[i] > '4') && s[i] != '?' && s[i] != 'x' && s[i] != 'c');
|
||||
}
|
||||
|
||||
inline void TCodeInvalid() {
|
||||
SERIAL_ECHOLNPGM("Invalid T code.");
|
||||
}
|
||||
|
||||
void TCodes(char *const strchr_pointer, const uint8_t codeValue) {
|
||||
uint8_t index = 1;
|
||||
for ( /*nothing*/ ; strchr_pointer[index] == ' ' || strchr_pointer[index] == '\t'; index++)
|
||||
;
|
||||
|
||||
strchr_pointer[index] = tolower(strchr_pointer[index]);
|
||||
|
||||
if (IsInvalidTCode(strchr_pointer, index)){
|
||||
TCodeInvalid();
|
||||
} else if (strchr_pointer[index] == 'x' || strchr_pointer[index] == '?'){
|
||||
// load to extruder gears; if mmu is not present do nothing
|
||||
if (MMU2::mmu2.Enabled()) {
|
||||
MMU2::mmu2.tool_change(strchr_pointer[index], choose_menu_P(_T(MSG_SELECT_FILAMENT), MSG_FILAMENT));
|
||||
}
|
||||
} else if (strchr_pointer[index] == 'c'){
|
||||
// load from extruder gears to nozzle (nozzle should be preheated)
|
||||
if (MMU2::mmu2.Enabled()) {
|
||||
MMU2::mmu2.tool_change(strchr_pointer[index], MMU2::mmu2.get_current_tool());
|
||||
}
|
||||
} else { // Process T0 ... T4
|
||||
if (MMU2::mmu2.Enabled()) {
|
||||
if (codeValue == MMU2::mmu2.get_current_tool()){
|
||||
// don't execute the same T-code twice in a row
|
||||
puts_P(duplicate_Tcode_ignored);
|
||||
} else {
|
||||
#if defined(MMU_HAS_CUTTER) && defined(MMU_ALWAYS_CUT)
|
||||
if (EEPROM_MMU_CUTTER_ENABLED_always == eeprom_read_byte((uint8_t *)EEPROM_MMU_CUTTER_ENABLED)) {
|
||||
MMU2::mmu2.cut_filament(codeValue);
|
||||
}
|
||||
#endif // defined(MMU_HAS_CUTTER) && defined(MMU_ALWAYS_CUT)
|
||||
MMU2::mmu2.tool_change(codeValue);
|
||||
}
|
||||
} else {
|
||||
SERIAL_ECHO_START;
|
||||
if (codeValue >= EXTRUDERS) {
|
||||
SERIAL_ECHO('T');
|
||||
SERIAL_ECHOLN(codeValue + '0');
|
||||
SERIAL_ECHOLNRPGM(_n("Invalid extruder")); ////MSG_INVALID_EXTRUDER
|
||||
} else {
|
||||
// @@TODO if (code_seen('F')) {
|
||||
// next_feedrate = code_value();
|
||||
// if (next_feedrate > 0.0) {
|
||||
// feedrate = next_feedrate;
|
||||
// }
|
||||
// }
|
||||
SERIAL_ECHORPGM(_n("Active Extruder: 0")); ////MSG_ACTIVE_EXTRUDER
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
/// @file
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
void TCodes(char * const strchr_pointer, const uint8_t codeValue);
|
||||
|
|
@ -6,6 +6,17 @@
|
|||
#include "Timer.h"
|
||||
#include "system_timer.h"
|
||||
|
||||
/**
|
||||
* @brief construct Timer
|
||||
*
|
||||
* It is guaranteed, that construction is equivalent with zeroing all members.
|
||||
* This property can be exploited in menu_data.
|
||||
*/
|
||||
template<typename T>
|
||||
Timer<T>::Timer() : m_isRunning(false), m_started()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Start timer
|
||||
*/
|
||||
|
|
@ -53,24 +64,5 @@ bool Timer<T>::expired(T msPeriod)
|
|||
return expired;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Ticks since the timer was started
|
||||
*
|
||||
* This function returns 0 if the timer is not started. Otherwise, it returns
|
||||
* the time in milliseconds since the timer was started.
|
||||
* This function is expected to handle wrap around of time register well.
|
||||
* The maximum elapsed time is dictated by the template type
|
||||
*/
|
||||
template<typename T>
|
||||
T Timer<T>::elapsed() {
|
||||
return m_isRunning ? (_millis() - m_started) : 0;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool Timer<T>::expired_cont(T msPeriod)
|
||||
{
|
||||
return !m_isRunning || expired(msPeriod);
|
||||
}
|
||||
|
||||
template class Timer<unsigned long>;
|
||||
template class Timer<unsigned short>;
|
||||
|
|
|
|||
|
|
@ -17,16 +17,11 @@ template <class T>
|
|||
class Timer
|
||||
{
|
||||
public:
|
||||
inline constexpr Timer()
|
||||
: m_isRunning(false)
|
||||
, m_started(0) {};
|
||||
|
||||
Timer();
|
||||
void start();
|
||||
void stop(){m_isRunning = false;}
|
||||
bool running()const {return m_isRunning;}
|
||||
bool expired(T msPeriod); // returns true only once after expiration, then stops running
|
||||
T elapsed(); // returns the time in milliseconds since the timer was started or 0 otherwise
|
||||
bool expired_cont(T msPeriod); // return true when continuosly when expired / not running
|
||||
bool expired(T msPeriod);
|
||||
protected:
|
||||
T started()const {return m_started;}
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,95 @@
|
|||
//adc.c
|
||||
|
||||
#include "adc.h"
|
||||
#include <stdio.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include "pins.h"
|
||||
|
||||
uint8_t adc_state;
|
||||
uint8_t adc_count;
|
||||
uint16_t adc_values[ADC_CHAN_CNT];
|
||||
uint16_t adc_sim_mask;
|
||||
|
||||
|
||||
#ifdef ADC_CALLBACK
|
||||
extern void ADC_CALLBACK(void);
|
||||
#endif //ADC_CALLBACK
|
||||
|
||||
|
||||
void adc_init(void)
|
||||
{
|
||||
puts_P(PSTR("adc_init"));
|
||||
adc_sim_mask = 0x00;
|
||||
ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0);
|
||||
ADMUX |= (1 << REFS0);
|
||||
ADCSRA |= (1 << ADEN);
|
||||
// ADCSRA |= (1 << ADIF) | (1 << ADSC);
|
||||
DIDR0 = ((ADC_CHAN_MSK & ADC_DIDR_MSK) & 0xff);
|
||||
DIDR2 = ((ADC_CHAN_MSK & ADC_DIDR_MSK) >> 8);
|
||||
adc_reset();
|
||||
// adc_sim_mask = 0b0101;
|
||||
// adc_sim_mask = 0b100101;
|
||||
// adc_values[0] = 1023 * 16;
|
||||
// adc_values[2] = 1023 * 16;
|
||||
// adc_values[5] = 1002 * 16;
|
||||
}
|
||||
|
||||
void adc_reset(void)
|
||||
{
|
||||
adc_state = 0;
|
||||
adc_count = 0;
|
||||
uint8_t i; for (i = 0; i < ADC_CHAN_CNT; i++)
|
||||
if ((adc_sim_mask & (1 << i)) == 0)
|
||||
adc_values[i] = 0;
|
||||
}
|
||||
|
||||
void adc_setmux(uint8_t ch)
|
||||
{
|
||||
ch &= 0x0f;
|
||||
if (ch & 0x08) ADCSRB |= (1 << MUX5);
|
||||
else ADCSRB &= ~(1 << MUX5);
|
||||
ADMUX = (ADMUX & ~(0x07)) | (ch & 0x07);
|
||||
}
|
||||
|
||||
uint8_t adc_chan(uint8_t index)
|
||||
{
|
||||
uint8_t chan = 0;
|
||||
uint16_t mask = 1;
|
||||
while (mask)
|
||||
{
|
||||
if ((mask & ADC_CHAN_MSK) && (index-- == 0)) break;
|
||||
mask <<= 1;
|
||||
chan++;
|
||||
}
|
||||
return chan;
|
||||
}
|
||||
|
||||
void adc_cycle(void)
|
||||
{
|
||||
if (adc_state & 0x80)
|
||||
{
|
||||
uint8_t index = adc_state & 0x0f;
|
||||
if ((adc_sim_mask & (1 << index)) == 0)
|
||||
adc_values[index] += ADC;
|
||||
if (++index >= ADC_CHAN_CNT)
|
||||
{
|
||||
index = 0;
|
||||
adc_count++;
|
||||
if (adc_count >= ADC_OVRSAMPL)
|
||||
{
|
||||
#ifdef ADC_CALLBACK
|
||||
ADC_CALLBACK();
|
||||
#endif //ADC_CALLBACK
|
||||
adc_reset();
|
||||
}
|
||||
}
|
||||
adc_setmux(adc_chan(index));
|
||||
adc_state = index;
|
||||
}
|
||||
else
|
||||
{
|
||||
ADCSRA |= (1 << ADSC); //start conversion
|
||||
adc_state |= 0x80;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
#include "adc.h"
|
||||
#include <stdio.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <string.h>
|
||||
#include "pins.h"
|
||||
|
||||
static uint8_t adc_count; //used for oversampling
|
||||
static uint8_t adc_channel_idx; //bitmask index
|
||||
volatile uint8_t adc_channel; //regular index
|
||||
volatile uint16_t adc_values[ADC_CHAN_CNT];
|
||||
|
||||
static void adc_reset();
|
||||
static void adc_setmux(uint8_t ch);
|
||||
|
||||
void adc_init()
|
||||
{
|
||||
puts_P(PSTR("adc_init"));
|
||||
DIDR0 = ((ADC_CHAN_MSK & ADC_DIDR_MSK) & 0xff); //disable digital inputs PORTF
|
||||
DIDR2 = ((ADC_CHAN_MSK & ADC_DIDR_MSK) >> 8); //disable digital inputs PORTK
|
||||
ADMUX |= (1 << REFS0); //use AVCC as reference
|
||||
|
||||
//enable ADC, set prescaler/128, enable interrupt
|
||||
ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0) | (1 << ADIF) | (1 << ADIE);
|
||||
}
|
||||
|
||||
static void adc_reset()
|
||||
{
|
||||
static const uint8_t first_channel_idx = 0;
|
||||
static_assert((1 << first_channel_idx) & ADC_CHAN_MSK);
|
||||
|
||||
ADCSRA &= ~(1 << ADSC); //stop conversion just in case
|
||||
adc_count = 0;
|
||||
adc_channel = 0;
|
||||
adc_channel_idx = first_channel_idx;
|
||||
adc_setmux(adc_channel_idx);
|
||||
memset((void*)adc_values, 0, sizeof(adc_values));
|
||||
}
|
||||
|
||||
static void adc_setmux(uint8_t ch)
|
||||
{
|
||||
ch &= 0x0f;
|
||||
if (ch & 0x08) ADCSRB |= (1 << MUX5);
|
||||
else ADCSRB &= ~(1 << MUX5);
|
||||
ADMUX = (ADMUX & ~(0x07)) | (ch & 0x07);
|
||||
}
|
||||
|
||||
void adc_start_cycle() {
|
||||
adc_reset();
|
||||
ADCSRA |= (1 << ADSC); //start conversion
|
||||
}
|
||||
|
||||
#ifdef ADC_CALLBACK
|
||||
extern void ADC_CALLBACK();
|
||||
#endif //ADC_CALLBACK
|
||||
|
||||
ISR(ADC_vect)
|
||||
{
|
||||
adc_values[adc_channel] += ADC;
|
||||
if (++adc_count == ADC_OVRSAMPL)
|
||||
{
|
||||
// go to the next channel
|
||||
if (++adc_channel == ADC_CHAN_CNT) {
|
||||
#ifdef ADC_CALLBACK
|
||||
ADC_CALLBACK();
|
||||
#endif
|
||||
return; // do not start the next measurement since there are no channels remaining
|
||||
}
|
||||
|
||||
// find the next channel
|
||||
while (++adc_channel_idx) {
|
||||
if (ADC_CHAN_MSK & (1 << adc_channel_idx)) {
|
||||
adc_setmux(adc_channel_idx);
|
||||
adc_count = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
ADCSRA |= (1 << ADSC); //start conversion
|
||||
}
|
||||
|
|
@ -1,8 +1,15 @@
|
|||
#pragma once
|
||||
//adc.h
|
||||
#ifndef _ADC_H
|
||||
#define _ADC_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "config.h"
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif //defined(__cplusplus)
|
||||
|
||||
/*
|
||||
http://resnet.uoregon.edu/~gurney_j/jmpc/bitwise.html
|
||||
*/
|
||||
|
|
@ -15,11 +22,24 @@ http://resnet.uoregon.edu/~gurney_j/jmpc/bitwise.html
|
|||
# error "ADC_CHAN_MSK oes not match ADC_CHAN_CNT"
|
||||
#endif
|
||||
|
||||
#define VOLT_DIV_REF 5 //[V]
|
||||
extern uint8_t adc_state;
|
||||
extern uint8_t adc_count;
|
||||
extern uint16_t adc_values[ADC_CHAN_CNT];
|
||||
extern uint16_t adc_sim_mask;
|
||||
|
||||
extern volatile uint8_t adc_channel;
|
||||
extern volatile uint16_t adc_values[ADC_CHAN_CNT];
|
||||
|
||||
extern void adc_init();
|
||||
extern void adc_start_cycle(); //should be called from an atomic context only
|
||||
static inline bool adc_cycle_done() { return adc_channel >= ADC_CHAN_CNT; }
|
||||
extern void adc_init(void);
|
||||
|
||||
extern void adc_reset(void);
|
||||
|
||||
extern void adc_setmux(uint8_t ch);
|
||||
|
||||
extern uint8_t adc_chan(uint8_t index);
|
||||
|
||||
extern void adc_cycle(void);
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif //defined(__cplusplus)
|
||||
#endif //_ADC_H
|
||||
|
|
|
|||
|
|
@ -1,21 +1,24 @@
|
|||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include "macros.h"
|
||||
|
||||
#ifdef __AVR_ATmega2560__
|
||||
|
||||
// return the current PC (on AVRs with 22bit PC)
|
||||
FORCE_INLINE __uint24 GETPC(void)
|
||||
static inline void GETPC(uint32_t* v)
|
||||
{
|
||||
__uint24 ret;
|
||||
asm (
|
||||
uint8_t a, b, c;
|
||||
asm
|
||||
(
|
||||
"rcall .\n"
|
||||
"pop %A0\n"
|
||||
"pop %B0\n"
|
||||
"pop %C0\n"
|
||||
: "=&r" (ret)
|
||||
"pop %2\n"
|
||||
"pop %1\n"
|
||||
"pop %0\n"
|
||||
: "=r" (a), "=r" (b), "=r" (c)
|
||||
);
|
||||
return ret;
|
||||
((uint8_t*)v)[0] = a;
|
||||
((uint8_t*)v)[1] = b;
|
||||
((uint8_t*)v)[2] = c;
|
||||
((uint8_t*)v)[3] = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
//backlight.cpp
|
||||
#include <Arduino.h>
|
||||
#include <avr/eeprom.h>
|
||||
|
||||
#include "backlight.h"
|
||||
#include "eeprom.h"
|
||||
#include "fastio.h"
|
||||
#include "macros.h"
|
||||
#include <avr/eeprom.h>
|
||||
#include <Arduino.h>
|
||||
#include "eeprom.h"
|
||||
#include "pins.h"
|
||||
#include "system_timer.h"
|
||||
#include "fastio.h"
|
||||
#include "Timer.h"
|
||||
|
||||
#ifdef LCD_BL_PIN
|
||||
|
|
@ -14,10 +14,10 @@
|
|||
#define BL_FLASH_DELAY_MS 25
|
||||
|
||||
bool backlightSupport = 0; //only if it's true will any of the settings be visible to the user
|
||||
uint8_t backlightLevel_HIGH = 0;
|
||||
uint8_t backlightLevel_LOW = 0;
|
||||
int16_t backlightLevel_HIGH = 0;
|
||||
int16_t backlightLevel_LOW = 0;
|
||||
uint8_t backlightMode = BACKLIGHT_MODE_BRIGHT;
|
||||
int16_t backlightTimer_period = LCD_BACKLIGHT_TIMEOUT;
|
||||
int16_t backlightTimer_period = 10;
|
||||
LongTimer backlightTimer;
|
||||
|
||||
static void backlightTimer_reset() //used for resetting the timer and waking the display. Triggered on user interactions.
|
||||
|
|
@ -32,7 +32,7 @@ void force_bl_on(bool section_start)
|
|||
if (section_start)
|
||||
{
|
||||
backlightMode = BACKLIGHT_MODE_BRIGHT;
|
||||
if (backlightLevel_HIGH < LCD_BACKLIGHT_FORCE_ON) backlightLevel_HIGH = LCD_BACKLIGHT_FORCE_ON;
|
||||
if (backlightLevel_HIGH < 30) backlightLevel_HIGH = 30;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -45,7 +45,7 @@ void force_bl_on(bool section_start)
|
|||
void backlight_wake(const uint8_t flashNo)
|
||||
{
|
||||
if (!backlightSupport) return;
|
||||
|
||||
|
||||
if (flashNo)
|
||||
{
|
||||
uint8_t backlightMode_bck = backlightMode;
|
||||
|
|
@ -62,16 +62,16 @@ void backlight_wake(const uint8_t flashNo)
|
|||
|
||||
void backlight_save() //saves all backlight data to eeprom.
|
||||
{
|
||||
eeprom_update_byte_notify((uint8_t *)EEPROM_BACKLIGHT_LEVEL_HIGH, backlightLevel_HIGH);
|
||||
eeprom_update_byte_notify((uint8_t *)EEPROM_BACKLIGHT_LEVEL_LOW, backlightLevel_LOW);
|
||||
eeprom_update_byte_notify((uint8_t *)EEPROM_BACKLIGHT_MODE, backlightMode);
|
||||
eeprom_update_word_notify((uint16_t *)EEPROM_BACKLIGHT_TIMEOUT, backlightTimer_period);
|
||||
eeprom_update_byte((uint8_t *)EEPROM_BACKLIGHT_LEVEL_HIGH, (uint8_t)backlightLevel_HIGH);
|
||||
eeprom_update_byte((uint8_t *)EEPROM_BACKLIGHT_LEVEL_LOW, (uint8_t)backlightLevel_LOW);
|
||||
eeprom_update_byte((uint8_t *)EEPROM_BACKLIGHT_MODE, backlightMode);
|
||||
eeprom_update_word((uint16_t *)EEPROM_BACKLIGHT_TIMEOUT, backlightTimer_period);
|
||||
}
|
||||
|
||||
void backlight_update()
|
||||
{
|
||||
if (!backlightSupport) return;
|
||||
|
||||
|
||||
if (backlightMode == BACKLIGHT_MODE_AUTO)
|
||||
{
|
||||
if (backlightTimer.expired((uint32_t)backlightTimer_period * 1000ul)) analogWrite(LCD_BL_PIN, backlightLevel_LOW);
|
||||
|
|
@ -91,12 +91,20 @@ void backlight_init()
|
|||
backlightSupport = !READ(LCD_BL_PIN);
|
||||
if (!backlightSupport) return;
|
||||
|
||||
//initialize backlight
|
||||
backlightMode = eeprom_init_default_byte((uint8_t *)EEPROM_BACKLIGHT_MODE, BACKLIGHT_MODE_AUTO);
|
||||
backlightLevel_HIGH = eeprom_init_default_byte((uint8_t *)EEPROM_BACKLIGHT_LEVEL_HIGH, LCD_BACKLIGHT_LEVEL_HIGH);
|
||||
backlightLevel_LOW = eeprom_init_default_byte((uint8_t *)EEPROM_BACKLIGHT_LEVEL_LOW, LCD_BACKLIGHT_LEVEL_LOW);
|
||||
backlightTimer_period = eeprom_init_default_word((uint16_t *)EEPROM_BACKLIGHT_TIMEOUT, LCD_BACKLIGHT_TIMEOUT); // in seconds
|
||||
|
||||
//initialize backlight
|
||||
backlightMode = eeprom_read_byte((uint8_t *)EEPROM_BACKLIGHT_MODE);
|
||||
if (backlightMode == 0xFF) //set default values
|
||||
{
|
||||
backlightMode = BACKLIGHT_MODE_AUTO;
|
||||
backlightLevel_HIGH = 130;
|
||||
backlightLevel_LOW = 50;
|
||||
backlightTimer_period = 10; //in seconds
|
||||
backlight_save();
|
||||
}
|
||||
backlightLevel_HIGH = eeprom_read_byte((uint8_t *)EEPROM_BACKLIGHT_LEVEL_HIGH);
|
||||
backlightLevel_LOW = eeprom_read_byte((uint8_t *)EEPROM_BACKLIGHT_LEVEL_LOW);
|
||||
backlightTimer_period = eeprom_read_word((uint16_t *)EEPROM_BACKLIGHT_TIMEOUT);
|
||||
|
||||
SET_OUTPUT(LCD_BL_PIN);
|
||||
backlightTimer_reset();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
#define _BACKLIGHT_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "Marlin.h"
|
||||
#include "pins.h"
|
||||
|
||||
enum Backlight_Mode
|
||||
{
|
||||
|
|
@ -11,8 +13,8 @@ enum Backlight_Mode
|
|||
BACKLIGHT_MODE_AUTO = 2,
|
||||
};
|
||||
|
||||
extern uint8_t backlightLevel_HIGH;
|
||||
extern uint8_t backlightLevel_LOW;
|
||||
extern int16_t backlightLevel_HIGH;
|
||||
extern int16_t backlightLevel_LOW;
|
||||
extern uint8_t backlightMode;
|
||||
extern bool backlightSupport;
|
||||
extern int16_t backlightTimer_period;
|
||||
|
|
|
|||
|
|
@ -6,17 +6,19 @@
|
|||
|
||||
|
||||
#include <stdio.h>
|
||||
extern FILE _uartout;
|
||||
#define uartout (&_uartout)
|
||||
|
||||
extern void softReset();
|
||||
|
||||
void bootapp_print_vars(void)
|
||||
{
|
||||
printf_P(PSTR("boot_src_addr =0x%08lx\n"), boot_src_addr);
|
||||
printf_P(PSTR("boot_dst_addr =0x%08lx\n"), boot_dst_addr);
|
||||
printf_P(PSTR("boot_copy_size =0x%04x\n"), boot_copy_size);
|
||||
printf_P(PSTR("boot_reserved =0x%02x\n"), boot_reserved);
|
||||
printf_P(PSTR("boot_app_flags =0x%02x\n"), boot_app_flags);
|
||||
printf_P(PSTR("boot_app_magic =0x%08lx\n"), boot_app_magic);
|
||||
fprintf_P(uartout, PSTR("boot_src_addr =0x%08lx\n"), boot_src_addr);
|
||||
fprintf_P(uartout, PSTR("boot_dst_addr =0x%08lx\n"), boot_dst_addr);
|
||||
fprintf_P(uartout, PSTR("boot_copy_size =0x%04x\n"), boot_copy_size);
|
||||
fprintf_P(uartout, PSTR("boot_reserved =0x%02x\n"), boot_reserved);
|
||||
fprintf_P(uartout, PSTR("boot_app_flags =0x%02x\n"), boot_app_flags);
|
||||
fprintf_P(uartout, PSTR("boot_app_magic =0x%08lx\n"), boot_app_magic);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -24,11 +26,12 @@ void bootapp_ram2flash(uint16_t rptr, uint16_t fptr, uint16_t size)
|
|||
{
|
||||
cli();
|
||||
boot_app_magic = BOOT_APP_MAGIC;
|
||||
boot_app_flags |= BOOT_APP_FLG_COPY | BOOT_APP_FLG_ERASE;
|
||||
boot_app_flags |= BOOT_APP_FLG_COPY;
|
||||
boot_app_flags |= BOOT_APP_FLG_ERASE;
|
||||
boot_copy_size = (uint16_t)size;
|
||||
boot_src_addr = (uint32_t)rptr;
|
||||
boot_dst_addr = (uint32_t)fptr;
|
||||
// bootapp_print_vars();
|
||||
bootapp_print_vars();
|
||||
softReset();
|
||||
}
|
||||
|
||||
|
|
@ -37,8 +40,7 @@ void bootapp_reboot_user0(uint8_t reserved)
|
|||
cli();
|
||||
boot_app_magic = BOOT_APP_MAGIC;
|
||||
boot_app_flags = BOOT_APP_FLG_USER0;
|
||||
boot_copy_size = 0;
|
||||
boot_reserved = reserved;
|
||||
// bootapp_print_vars();
|
||||
bootapp_print_vars();
|
||||
softReset();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,10 +17,11 @@
|
|||
#define BOOT_APP_FLG_ERASE 0x01
|
||||
#define BOOT_APP_FLG_COPY 0x02
|
||||
#define BOOT_APP_FLG_FLASH 0x04
|
||||
#define BOOT_APP_FLG_RUN 0x08
|
||||
|
||||
#define BOOT_APP_FLG_USER0 0x80
|
||||
|
||||
#define BOOT_APP_MAGIC 0x55aa55aaUL
|
||||
#define BOOT_APP_MAGIC 0x55aa55aa
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
|
|
|
|||
|
|
@ -2,13 +2,11 @@
|
|||
#include "cmdqueue.h"
|
||||
#include "cardreader.h"
|
||||
#include "ultralcd.h"
|
||||
#include "conv2str.h"
|
||||
#include "menu.h"
|
||||
#include "stepper.h"
|
||||
#include "temperature.h"
|
||||
#include "language.h"
|
||||
#include "Prusa_farm.h"
|
||||
#include "power_panic.h"
|
||||
#include "stopwatch.h"
|
||||
|
||||
#ifdef SDSUPPORT
|
||||
|
||||
|
|
@ -24,31 +22,33 @@ CardReader::CardReader()
|
|||
filesize = 0;
|
||||
sdpos = 0;
|
||||
sdprinting = false;
|
||||
mounted = false;
|
||||
cardOK = false;
|
||||
saving = false;
|
||||
logging = false;
|
||||
autostart_atmillis=0;
|
||||
workDirDepth = 0;
|
||||
file_subcall_ctr=0;
|
||||
memset(workDirParents, 0, sizeof(workDirParents));
|
||||
presort_flag = false;
|
||||
|
||||
autostart_stilltocheck=true; //the SD start is delayed, because otherwise the serial cannot answer fast enough to make contact with the host software.
|
||||
lastnr=0;
|
||||
//power to SD reader
|
||||
#if SDPOWER > -1
|
||||
SET_OUTPUT(SDPOWER);
|
||||
SET_OUTPUT(SDPOWER);
|
||||
WRITE(SDPOWER,HIGH);
|
||||
#endif //SDPOWER
|
||||
|
||||
autostart_atmillis.start(); // reset timer
|
||||
|
||||
autostart_atmillis=_millis()+5000;
|
||||
}
|
||||
|
||||
char *createFilename(char *buffer,const dir_t &p) //buffer>12characters
|
||||
{
|
||||
char *pos=buffer;
|
||||
for (uint8_t i = 0; i < 11; i++)
|
||||
for (uint8_t i = 0; i < 11; i++)
|
||||
{
|
||||
if (p.name[i] == ' ')continue;
|
||||
if (i == 8)
|
||||
if (i == 8)
|
||||
{
|
||||
*pos++='.';
|
||||
}
|
||||
|
|
@ -74,7 +74,7 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m
|
|||
_incrementer() {recursionCnt++;}
|
||||
~_incrementer() {recursionCnt--;}
|
||||
} recursionCntIncrementer;
|
||||
|
||||
|
||||
dir_t p;
|
||||
uint8_t cnt = 0;
|
||||
// Read the next entry from a directory
|
||||
|
|
@ -103,10 +103,10 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m
|
|||
// Serial.print(path);
|
||||
// Get a new directory object using the full path
|
||||
// and dive recursively into it.
|
||||
|
||||
|
||||
if (lsParams.LFN)
|
||||
printf_P(PSTR("DIR_ENTER: %s \"%s\"\n"), path, longFilename[0] ? longFilename : lfilename);
|
||||
|
||||
|
||||
SdFile dir;
|
||||
if (!dir.open(parent, lfilename, O_READ)) {
|
||||
//SERIAL_ECHO_START();
|
||||
|
|
@ -115,7 +115,7 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m
|
|||
}
|
||||
lsDive(path, dir, NULL, lsAction, lsParams);
|
||||
// close() is done automatically by destructor of SdFile
|
||||
|
||||
|
||||
if (lsParams.LFN)
|
||||
puts_P(PSTR("DIR_EXIT"));
|
||||
}
|
||||
|
|
@ -126,15 +126,15 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m
|
|||
case LS_Count:
|
||||
nrFiles++;
|
||||
break;
|
||||
|
||||
|
||||
case LS_SerialPrint:
|
||||
createFilename(filename, p);
|
||||
SERIAL_PROTOCOL(prepend);
|
||||
SERIAL_PROTOCOL(filename);
|
||||
|
||||
|
||||
MYSERIAL.write(' ');
|
||||
SERIAL_PROTOCOL(p.fileSize);
|
||||
|
||||
|
||||
if (lsParams.timestamp)
|
||||
{
|
||||
crmodDate = p.lastWriteDate;
|
||||
|
|
@ -145,14 +145,14 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m
|
|||
}
|
||||
printf_P(PSTR(" %#lx"), ((uint32_t)crmodDate << 16) | crmodTime);
|
||||
}
|
||||
|
||||
|
||||
if (lsParams.LFN)
|
||||
printf_P(PSTR(" \"%s\""), LONGEST_FILENAME);
|
||||
|
||||
|
||||
SERIAL_PROTOCOLLN();
|
||||
manage_heater();
|
||||
break;
|
||||
|
||||
|
||||
case LS_GetFilename:
|
||||
//SERIAL_ECHOPGM("File: ");
|
||||
createFilename(filename, p);
|
||||
|
|
@ -198,19 +198,26 @@ void CardReader::ls(ls_param params)
|
|||
}
|
||||
|
||||
|
||||
void CardReader::mount(bool doPresort/* = true*/)
|
||||
void CardReader::initsd(bool doPresort/* = true*/)
|
||||
{
|
||||
mounted = false;
|
||||
cardOK = false;
|
||||
if(root.isOpen())
|
||||
root.close();
|
||||
#ifdef SDSLOW
|
||||
if (!card.init(SPI_HALF_SPEED)
|
||||
if (!card.init(SPI_HALF_SPEED,SDSS)
|
||||
#if defined(LCD_SDSS) && (LCD_SDSS != SDSS)
|
||||
&& !card.init(SPI_HALF_SPEED,LCD_SDSS)
|
||||
#endif
|
||||
)
|
||||
#else
|
||||
if (!card.init(SPI_FULL_SPEED)
|
||||
if (!card.init(SPI_FULL_SPEED,SDSS)
|
||||
#if defined(LCD_SDSS) && (LCD_SDSS != SDSS)
|
||||
&& !card.init(SPI_FULL_SPEED,LCD_SDSS)
|
||||
#endif
|
||||
)
|
||||
#endif
|
||||
{
|
||||
//if (!card.init(SPI_HALF_SPEED,SDSS))
|
||||
SERIAL_ECHO_START;
|
||||
SERIAL_ECHOLNRPGM(_n("SD init fail"));////MSG_SD_INIT_FAIL
|
||||
}
|
||||
|
|
@ -219,28 +226,40 @@ void CardReader::mount(bool doPresort/* = true*/)
|
|||
SERIAL_ERROR_START;
|
||||
SERIAL_ERRORLNRPGM(_n("volume.init failed"));////MSG_SD_VOL_INIT_FAIL
|
||||
}
|
||||
else if (!root.openRoot(&volume))
|
||||
else if (!root.openRoot(&volume))
|
||||
{
|
||||
SERIAL_ERROR_START;
|
||||
SERIAL_ERRORLNRPGM(_n("openRoot failed"));////MSG_SD_OPENROOT_FAIL
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
mounted = true;
|
||||
cardOK = true;
|
||||
SERIAL_ECHO_START;
|
||||
SERIAL_ECHOLNRPGM(_n("SD card ok"));////MSG_SD_CARD_OK
|
||||
}
|
||||
workDir=root;
|
||||
curDir=&root;
|
||||
workDirDepth = 0;
|
||||
|
||||
if (mounted)
|
||||
#ifdef SDCARD_SORT_ALPHA
|
||||
if (doPresort)
|
||||
presort();
|
||||
#endif
|
||||
|
||||
/*
|
||||
if(!workDir.openRoot(&volume))
|
||||
{
|
||||
cdroot(doPresort);
|
||||
SERIAL_ECHOLNPGM(MSG_SD_WORKDIR_FAIL);
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
void __attribute__((noinline)) CardReader::cdroot(bool doPresort)
|
||||
void CardReader::setroot(bool doPresort)
|
||||
{
|
||||
workDir=root;
|
||||
workDirDepth = 0;
|
||||
|
||||
curDir=&workDir;
|
||||
#ifdef SDCARD_SORT_ALPHA
|
||||
if (doPresort)
|
||||
|
|
@ -252,17 +271,17 @@ void __attribute__((noinline)) CardReader::cdroot(bool doPresort)
|
|||
void CardReader::release()
|
||||
{
|
||||
sdprinting = false;
|
||||
mounted = false;
|
||||
cardOK = false;
|
||||
SERIAL_ECHO_START;
|
||||
SERIAL_ECHOLNRPGM(_n("SD card released"));////MSG_SD_CARD_RELEASED
|
||||
}
|
||||
|
||||
void CardReader::startFileprint()
|
||||
{
|
||||
if(mounted)
|
||||
if(cardOK)
|
||||
{
|
||||
sdprinting = true;
|
||||
SetPrinterState(PrinterState::IsSDPrinting); //set printer state to hide LCD menu
|
||||
Stopped = false;
|
||||
#ifdef SDCARD_SORT_ALPHA
|
||||
//flush_presort();
|
||||
#endif
|
||||
|
|
@ -276,11 +295,11 @@ void CardReader::openLogFile(const char* name)
|
|||
}
|
||||
|
||||
void CardReader::getDirName(char* name, uint8_t level)
|
||||
{
|
||||
{
|
||||
workDirParents[level].getFilename(name);
|
||||
}
|
||||
|
||||
uint8_t CardReader::getWorkDirDepth() {
|
||||
uint16_t CardReader::getWorkDirDepth() {
|
||||
return workDirDepth;
|
||||
}
|
||||
|
||||
|
|
@ -291,10 +310,10 @@ void CardReader::getAbsFilename(char *t)
|
|||
for(uint8_t i=0;i<workDirDepth;i++)
|
||||
{
|
||||
workDirParents[i].getFilename(t); //SDBaseFile.getfilename!
|
||||
while(*t!=0 && cnt< MAXPATHNAMELENGTH)
|
||||
while(*t!=0 && cnt< MAXPATHNAMELENGTH)
|
||||
{t++;cnt++;} //crawl counter forward.
|
||||
}
|
||||
if(cnt < MAXPATHNAMELENGTH - FILENAME_LENGTH)
|
||||
if(cnt<MAXPATHNAMELENGTH-13)
|
||||
file.getFilename(t);
|
||||
else
|
||||
t[0]=0;
|
||||
|
|
@ -334,7 +353,7 @@ bool CardReader::diveSubfolder (const char *&fileName)
|
|||
const char *dirname_start, *dirname_end;
|
||||
if (fileName[0] == '/') // absolute path
|
||||
{
|
||||
cdroot(false);
|
||||
setroot(false);
|
||||
dirname_start = fileName + 1;
|
||||
while (*dirname_start)
|
||||
{
|
||||
|
|
@ -384,27 +403,27 @@ static const char ofSDPrinting[] PROGMEM = "SD-PRINTING";
|
|||
static const char ofWritingToFile[] PROGMEM = "Writing to file: ";
|
||||
|
||||
void CardReader::openFileReadFilteredGcode(const char* name, bool replace_current/* = false*/){
|
||||
if(!mounted)
|
||||
if(!cardOK)
|
||||
return;
|
||||
|
||||
|
||||
if(file.isOpen()){ //replacing current file by new file, or subfile call
|
||||
if(!replace_current){
|
||||
if((int)file_subcall_ctr>(int)SD_PROCEDURE_DEPTH-1){
|
||||
// SERIAL_ERROR_START;
|
||||
// SERIAL_ERRORPGM("trying to call sub-gcode files with too many levels. MAX level is:");
|
||||
// SERIAL_ERRORLN(SD_PROCEDURE_DEPTH);
|
||||
kill(ofKill);
|
||||
kill(ofKill, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SERIAL_ECHO_START;
|
||||
SERIAL_ECHORPGM(ofSubroutineCallTgt);
|
||||
SERIAL_ECHO(name);
|
||||
SERIAL_ECHORPGM(ofParent);
|
||||
|
||||
|
||||
//store current filename and position
|
||||
getAbsFilename(filenames[file_subcall_ctr]);
|
||||
|
||||
|
||||
SERIAL_ECHO(filenames[file_subcall_ctr]);
|
||||
SERIAL_ECHORPGM(ofPos);
|
||||
SERIAL_ECHOLN(sdpos);
|
||||
|
|
@ -423,11 +442,11 @@ void CardReader::openFileReadFilteredGcode(const char* name, bool replace_curren
|
|||
SERIAL_ECHOLN(name);
|
||||
}
|
||||
sdprinting = false;
|
||||
|
||||
|
||||
const char *fname=name;
|
||||
if (!diveSubfolder(fname))
|
||||
return;
|
||||
|
||||
|
||||
if (file.openFilteredGcode(curDir, fname)) {
|
||||
getfilename(0, fname);
|
||||
filesize = file.fileSize();
|
||||
|
|
@ -436,7 +455,7 @@ void CardReader::openFileReadFilteredGcode(const char* name, bool replace_curren
|
|||
SERIAL_PROTOCOLRPGM(ofSize);////MSG_SD_SIZE
|
||||
SERIAL_PROTOCOLLN(filesize);
|
||||
sdpos = 0;
|
||||
|
||||
|
||||
SERIAL_PROTOCOLLNRPGM(ofFileSelected);////MSG_SD_FILE_SELECTED
|
||||
lcd_setstatuspgm(ofFileSelected);
|
||||
scrollstuff = 0;
|
||||
|
|
@ -449,7 +468,7 @@ void CardReader::openFileReadFilteredGcode(const char* name, bool replace_curren
|
|||
|
||||
void CardReader::openFileWrite(const char* name)
|
||||
{
|
||||
if(!mounted)
|
||||
if(!cardOK)
|
||||
return;
|
||||
if(file.isOpen()){ //replacing current file by new file, or subfile call
|
||||
#if 0
|
||||
|
|
@ -460,18 +479,18 @@ void CardReader::openFileWrite(const char* name)
|
|||
// SERIAL_ERROR_START;
|
||||
// SERIAL_ERRORPGM("trying to call sub-gcode files with too many levels. MAX level is:");
|
||||
// SERIAL_ERRORLN(SD_PROCEDURE_DEPTH);
|
||||
kill(ofKill);
|
||||
kill(ofKill, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
SERIAL_ECHO_START;
|
||||
SERIAL_ECHORPGM(ofSubroutineCallTgt);
|
||||
SERIAL_ECHO(name);
|
||||
SERIAL_ECHORPGM(ofParent);
|
||||
|
||||
|
||||
//store current filename and position
|
||||
getAbsFilename(filenames[file_subcall_ctr]);
|
||||
|
||||
|
||||
SERIAL_ECHO(filenames[file_subcall_ctr]);
|
||||
SERIAL_ECHORPGM(ofPos);
|
||||
SERIAL_ECHOLN(sdpos);
|
||||
|
|
@ -488,11 +507,11 @@ void CardReader::openFileWrite(const char* name)
|
|||
SERIAL_ECHOLN(name);
|
||||
}
|
||||
sdprinting = false;
|
||||
|
||||
|
||||
const char *fname=name;
|
||||
if (!diveSubfolder(fname))
|
||||
return;
|
||||
|
||||
|
||||
//write
|
||||
if (!file.open(curDir, fname, O_CREAT | O_APPEND | O_WRITE | O_TRUNC)){
|
||||
SERIAL_PROTOCOLRPGM(MSG_SD_OPEN_FILE_FAIL);
|
||||
|
|
@ -504,7 +523,7 @@ void CardReader::openFileWrite(const char* name)
|
|||
SERIAL_PROTOCOLRPGM(ofWritingToFile);////MSG_SD_WRITE_TO_FILE
|
||||
printAbsFilenameFast();
|
||||
SERIAL_PROTOCOLLN();
|
||||
|
||||
|
||||
SERIAL_PROTOCOLLNRPGM(ofFileSelected);////MSG_SD_FILE_SELECTED
|
||||
lcd_setstatuspgm(ofFileSelected);
|
||||
scrollstuff = 0;
|
||||
|
|
@ -513,7 +532,7 @@ void CardReader::openFileWrite(const char* name)
|
|||
|
||||
void CardReader::removeFile(const char* name)
|
||||
{
|
||||
if(!mounted) return;
|
||||
if(!cardOK) return;
|
||||
file.close();
|
||||
sdprinting = false;
|
||||
|
||||
|
|
@ -521,7 +540,7 @@ void CardReader::removeFile(const char* name)
|
|||
if (!diveSubfolder(fname))
|
||||
return;
|
||||
|
||||
if (file.remove(curDir, fname))
|
||||
if (file.remove(curDir, fname))
|
||||
{
|
||||
SERIAL_PROTOCOLPGM("File deleted:");
|
||||
SERIAL_PROTOCOLLN(fname);
|
||||
|
|
@ -536,7 +555,7 @@ void CardReader::removeFile(const char* name)
|
|||
SERIAL_PROTOCOL(fname);
|
||||
SERIAL_PROTOCOLLN('.');
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
uint32_t CardReader::getFileSize()
|
||||
|
|
@ -546,9 +565,9 @@ uint32_t CardReader::getFileSize()
|
|||
|
||||
void CardReader::getStatus(bool arg_P)
|
||||
{
|
||||
if (printingIsPaused())
|
||||
if (isPrintPaused)
|
||||
{
|
||||
if (saved_printing && (saved_printing_type == PowerPanic::PRINT_TYPE_SD))
|
||||
if (saved_printing && (saved_printing_type == PRINTING_TYPE_SD))
|
||||
SERIAL_PROTOCOLLNPGM("SD print paused");
|
||||
else
|
||||
SERIAL_PROTOCOLLNPGM("Print saved");
|
||||
|
|
@ -562,15 +581,15 @@ void CardReader::getStatus(bool arg_P)
|
|||
}
|
||||
else
|
||||
SERIAL_PROTOCOLLN(LONGEST_FILENAME);
|
||||
|
||||
|
||||
SERIAL_PROTOCOLRPGM(_N("SD printing byte "));////MSG_SD_PRINTING_BYTE
|
||||
SERIAL_PROTOCOL(sdpos);
|
||||
SERIAL_PROTOCOL('/');
|
||||
SERIAL_PROTOCOLLN(filesize);
|
||||
uint16_t time = print_job_timer.duration() / 60;
|
||||
SERIAL_PROTOCOL((int)(time / 60));
|
||||
uint16_t time = ( _millis() - starttime ) / 60000U;
|
||||
SERIAL_PROTOCOL(itostr2(time/60));
|
||||
SERIAL_PROTOCOL(':');
|
||||
SERIAL_PROTOCOLLN((int)(time % 60));
|
||||
SERIAL_PROTOCOLLN(itostr2(time%60));
|
||||
}
|
||||
else
|
||||
SERIAL_PROTOCOLLNPGM("Not SD printing");
|
||||
|
|
@ -603,24 +622,21 @@ void CardReader::write_command_no_newline(char *buf)
|
|||
|
||||
void CardReader::checkautostart(bool force)
|
||||
{
|
||||
// The SD start is delayed because otherwise the serial cannot answer
|
||||
// fast enough to make contact with the host software.
|
||||
static bool autostart_stilltocheck = true;
|
||||
if(!force)
|
||||
{
|
||||
if(!autostart_stilltocheck)
|
||||
return;
|
||||
if(autostart_atmillis.expired(5000))
|
||||
if(autostart_atmillis<_millis())
|
||||
return;
|
||||
}
|
||||
autostart_stilltocheck = false;
|
||||
if(!mounted)
|
||||
autostart_stilltocheck=false;
|
||||
if(!cardOK)
|
||||
{
|
||||
mount();
|
||||
if(!mounted) //fail
|
||||
initsd();
|
||||
if(!cardOK) //fail
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
char autoname[30];
|
||||
sprintf_P(autoname, PSTR("auto%i.g"), lastnr);
|
||||
for(int8_t i=0;i<(int8_t)strlen(autoname);i++)
|
||||
|
|
@ -628,9 +644,9 @@ void CardReader::checkautostart(bool force)
|
|||
dir_t p;
|
||||
|
||||
root.rewind();
|
||||
|
||||
|
||||
bool found=false;
|
||||
while (root.readDir(p, NULL) > 0)
|
||||
while (root.readDir(p, NULL) > 0)
|
||||
{
|
||||
for(int8_t i=0;i<(int8_t)strlen((char*)p.name);i++)
|
||||
p.name[i]=tolower(p.name[i]);
|
||||
|
|
@ -640,10 +656,12 @@ void CardReader::checkautostart(bool force)
|
|||
if(p.name[9]!='~') //skip safety copies
|
||||
if(strncmp((char*)p.name,autoname,5)==0)
|
||||
{
|
||||
char cmd[30];
|
||||
// M23: Select SD file
|
||||
enquecommandf_P(MSG_M23, autoname);
|
||||
sprintf_P(cmd, PSTR("M23 %s"), autoname);
|
||||
enquecommand(cmd);
|
||||
// M24: Start/resume SD print
|
||||
enquecommand_P(MSG_M24);
|
||||
enquecommand_P(PSTR("M24"));
|
||||
found=true;
|
||||
}
|
||||
}
|
||||
|
|
@ -657,17 +675,17 @@ void CardReader::closefile(bool store_location)
|
|||
{
|
||||
file.sync();
|
||||
file.close();
|
||||
saving = false;
|
||||
saving = false;
|
||||
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.
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
void CardReader::getfilename(uint16_t nr, const char * const match/*=NULL*/)
|
||||
|
|
@ -676,14 +694,14 @@ void CardReader::getfilename(uint16_t nr, const char * const match/*=NULL*/)
|
|||
nrFiles=nr;
|
||||
curDir->rewind();
|
||||
lsDive("",*curDir,match, LS_GetFilename);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void CardReader::getfilename_simple(uint16_t entry, const char * const match/*=NULL*/)
|
||||
void CardReader::getfilename_simple(uint32_t position, const char * const match/*=NULL*/)
|
||||
{
|
||||
curDir = &workDir;
|
||||
nrFiles = 0;
|
||||
curDir->seekSet((uint32_t)entry << 5);
|
||||
curDir->seekSet(position);
|
||||
lsDive("", *curDir, match, LS_GetFilename);
|
||||
}
|
||||
|
||||
|
|
@ -709,10 +727,10 @@ bool CardReader::chdir(const char * relpath, bool doPresort)
|
|||
{
|
||||
SdFile newfile;
|
||||
SdFile *parent=&root;
|
||||
|
||||
|
||||
if(workDir.isOpen())
|
||||
parent=&workDir;
|
||||
|
||||
|
||||
if(!newfile.open(*parent,relpath, O_READ) || ((workDirDepth + 1) >= MAX_DIR_DEPTH))
|
||||
{
|
||||
SERIAL_ECHO_START;
|
||||
|
|
@ -726,7 +744,7 @@ bool CardReader::chdir(const char * relpath, bool doPresort)
|
|||
puts(relpath);
|
||||
|
||||
if (workDirDepth < MAX_DIR_DEPTH) {
|
||||
for (uint8_t d = ++workDirDepth; d--;)
|
||||
for (int d = ++workDirDepth; d--;)
|
||||
workDirParents[d+1] = workDirParents[d];
|
||||
workDirParents[0]=*parent;
|
||||
}
|
||||
|
|
@ -748,7 +766,7 @@ void CardReader::updir()
|
|||
{
|
||||
--workDirDepth;
|
||||
workDir = workDirParents[0];
|
||||
for (uint8_t d = 0; d < workDirDepth; d++)
|
||||
for (unsigned int d = 0; d < workDirDepth; d++)
|
||||
{
|
||||
workDirParents[d] = workDirParents[d+1];
|
||||
}
|
||||
|
|
@ -765,17 +783,9 @@ void CardReader::updir()
|
|||
*/
|
||||
void CardReader::getfilename_sorted(const uint16_t nr, uint8_t sdSort) {
|
||||
if (nr < sort_count)
|
||||
getfilename_simple(sort_entries[(sdSort == SD_SORT_ALPHA) ? (sort_count - nr - 1) : nr]);
|
||||
getfilename_simple(sort_positions[(sdSort == SD_SORT_ALPHA) ? (sort_count - nr - 1) : nr]);
|
||||
else
|
||||
getfilename_afterMaxSorting(nr);
|
||||
}
|
||||
|
||||
void CardReader::getfilename_afterMaxSorting(uint16_t entry, const char * const match/*=NULL*/)
|
||||
{
|
||||
curDir = &workDir;
|
||||
nrFiles = entry - sort_count + 1;
|
||||
curDir->seekSet(lastSortedFilePosition << 5);
|
||||
lsDive("", *curDir, match, LS_GetFilename);
|
||||
getfilename(nr);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -787,120 +797,136 @@ void CardReader::getfilename_afterMaxSorting(uint16_t entry, const char * const
|
|||
* - Most RAM: Buffer the directory and return filenames from RAM
|
||||
*/
|
||||
void CardReader::presort() {
|
||||
// Throw away old sort index
|
||||
flush_presort();
|
||||
|
||||
if (IS_SD_INSERTED == false) return; //sorting is not used in farm mode
|
||||
if (farm_mode || IS_SD_INSERTED == false) return; //sorting is not used in farm mode
|
||||
uint8_t sdSort = eeprom_read_byte((uint8_t*)EEPROM_SD_SORT);
|
||||
|
||||
if (sdSort == SD_SORT_NONE) return; //sd sort is turned off
|
||||
|
||||
KEEPALIVE_STATE(IN_HANDLER);
|
||||
|
||||
// Throw away old sort index
|
||||
flush_presort();
|
||||
|
||||
// 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) {
|
||||
if ((sdSort != SD_SORT_NONE) && !farm_mode) {
|
||||
lcd_show_fullscreen_message_and_wait_P(_T(MSG_FILE_CNT));
|
||||
}
|
||||
lcd_show_fullscreen_message_and_wait_P(_i("Some files will not be sorted. Max. No. of files in 1 folder for sorting is 100."));////MSG_FILE_CNT c=20 r=6
|
||||
fileCnt = SDSORT_LIMIT;
|
||||
}
|
||||
|
||||
sort_count = fileCnt;
|
||||
// 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];
|
||||
uint16_t crmod_time_bckp;
|
||||
uint16_t crmod_date_bckp;
|
||||
|
||||
// Init sort order.
|
||||
for (uint16_t i = 0; i < fileCnt; i++) {
|
||||
if (!IS_SD_INSERTED) return;
|
||||
manage_heater();
|
||||
if (i == 0)
|
||||
getfilename(0);
|
||||
else
|
||||
getfilename_next(position);
|
||||
sort_entries[i] = position >> 5;
|
||||
}
|
||||
#if HAS_FOLDER_SORTING
|
||||
uint16_t dirCnt = 0;
|
||||
#endif
|
||||
|
||||
if ((fileCnt > 1) && (sdSort != SD_SORT_NONE) && !farm_mode) {
|
||||
if (fileCnt > 1) {
|
||||
// Init sort order.
|
||||
uint8_t sort_order[fileCnt];
|
||||
for (uint16_t i = 0; i < fileCnt; i++) {
|
||||
if (!IS_SD_INSERTED) return;
|
||||
manage_heater();
|
||||
if (i == 0)
|
||||
getfilename(0);
|
||||
else
|
||||
getfilename_next(position);
|
||||
sort_order[i] = i;
|
||||
sort_positions[i] = position;
|
||||
#if HAS_FOLDER_SORTING
|
||||
if (filenameIsDir) dirCnt++;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef SORTING_SPEEDTEST
|
||||
LongTimer sortingSpeedtestTimer;
|
||||
sortingSpeedtestTimer.start();
|
||||
#endif //SORTING_SPEEDTEST
|
||||
lastSortedFilePosition = position >> 5;
|
||||
|
||||
// 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];
|
||||
uint16_t crmod_time_bckp;
|
||||
uint16_t crmod_date_bckp;
|
||||
|
||||
#ifdef INSERTSORT
|
||||
#ifdef QUICKSORT
|
||||
quicksort(0, fileCnt - 1);
|
||||
#elif defined(SHELLSORT)
|
||||
|
||||
#define _SORT_CMP_NODIR() (strcasecmp(name1, name2) < 0) //true if lowercase(name1) < lowercase(name2)
|
||||
#define _SORT_CMP_TIME_NODIR() (((crmod_date_bckp == crmodDate) && (crmod_time_bckp > crmodTime)) || (crmod_date_bckp > crmodDate))
|
||||
#define _SORT_CMP_TIME_NODIR() (((crmod_date_bckp == crmodDate) && (crmod_time_bckp < crmodTime)) || (crmod_date_bckp < crmodDate))
|
||||
|
||||
#if HAS_FOLDER_SORTING
|
||||
#define _SORT_CMP_DIR(fs) ((dir1 == filenameIsDir) ? _SORT_CMP_NODIR() : (fs < 0 ? dir1 : !dir1))
|
||||
#define _SORT_CMP_TIME_DIR(fs) ((dir1 == filenameIsDir) ? _SORT_CMP_TIME_NODIR() : (fs < 0 ? dir1 : !dir1))
|
||||
#endif
|
||||
|
||||
uint16_t counter = 0;
|
||||
menu_progressbar_init(fileCnt * fileCnt / 2, _T(MSG_SORTING_FILES));
|
||||
|
||||
for (uint16_t i = 1; i < fileCnt; ++i){
|
||||
// if (!IS_SD_INSERTED) return;
|
||||
menu_progressbar_update(counter);
|
||||
counter += i;
|
||||
|
||||
/// pop the position
|
||||
const uint16_t o1 = sort_entries[i];
|
||||
getfilename_simple(o1);
|
||||
strcpy(name1, LONGEST_FILENAME); // save (or getfilename below will trounce it)
|
||||
crmod_date_bckp = crmodDate;
|
||||
crmod_time_bckp = crmodTime;
|
||||
#if HAS_FOLDER_SORTING
|
||||
bool dir1 = filenameIsDir;
|
||||
#endif
|
||||
|
||||
/// find proper place
|
||||
uint16_t j = i;
|
||||
for (; j > 0; --j){
|
||||
if (!IS_SD_INSERTED) return;
|
||||
|
||||
#ifdef SORTING_DUMP
|
||||
for (uint16_t z = 0; z < fileCnt; z++){
|
||||
printf_P(PSTR("%2u "), sort_entries[z]);
|
||||
}
|
||||
MYSERIAL.println();
|
||||
#endif
|
||||
|
||||
manage_heater();
|
||||
const uint16_t o2 = sort_entries[j - 1];
|
||||
|
||||
getfilename_simple(o2);
|
||||
char *name2 = LONGEST_FILENAME; // use the string in-place
|
||||
|
||||
// Sort the current pair according to settings.
|
||||
if (
|
||||
#if HAS_FOLDER_SORTING
|
||||
(sdSort == SD_SORT_TIME && _SORT_CMP_TIME_DIR(FOLDER_SORTING)) || (sdSort == SD_SORT_ALPHA && !_SORT_CMP_DIR(FOLDER_SORTING))
|
||||
#else
|
||||
(sdSort == SD_SORT_TIME && _SORT_CMP_TIME_NODIR()) || (sdSort == SD_SORT_ALPHA && !_SORT_CMP_NODIR())
|
||||
#endif
|
||||
)
|
||||
{
|
||||
break;
|
||||
} else {
|
||||
#ifdef SORTING_DUMP
|
||||
puts_P(PSTR("shift"));
|
||||
#endif
|
||||
sort_entries[j] = o2;
|
||||
}
|
||||
}
|
||||
/// place the position
|
||||
sort_entries[j] = o1;
|
||||
}
|
||||
for (uint8_t runs = 0; runs < 2; runs++)
|
||||
{
|
||||
//run=0: sorts all files and moves folders to the beginning
|
||||
//run=1: assumes all folders are at the beginning of the list and sorts them
|
||||
uint16_t sortCountFiles = 0;
|
||||
if (runs == 0)
|
||||
{
|
||||
sortCountFiles = fileCnt;
|
||||
}
|
||||
#if HAS_FOLDER_SORTING
|
||||
else
|
||||
{
|
||||
sortCountFiles = dirCnt;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint16_t counter = 0;
|
||||
uint16_t total = 0;
|
||||
for (uint16_t i = sortCountFiles/2; i > 0; i /= 2) total += sortCountFiles - i; //total runs for progress bar
|
||||
menu_progressbar_init(
|
||||
total, (runs == 0)
|
||||
? _i("Sorting files") ////MSG_SORTING_FILES c=20
|
||||
: _i("Sorting folders")); ////MSG_SORTING_FOLDERS c=20
|
||||
|
||||
for (uint16_t gap = sortCountFiles/2; gap > 0; gap /= 2)
|
||||
{
|
||||
for (uint16_t i = gap; i < sortCountFiles; i++)
|
||||
{
|
||||
if (!IS_SD_INSERTED) return;
|
||||
|
||||
menu_progressbar_update(counter);
|
||||
counter++;
|
||||
|
||||
manage_heater();
|
||||
uint8_t orderBckp = sort_order[i];
|
||||
getfilename_simple(sort_positions[orderBckp]);
|
||||
strcpy(name1, LONGEST_FILENAME); // save (or getfilename below will trounce it)
|
||||
crmod_date_bckp = crmodDate;
|
||||
crmod_time_bckp = crmodTime;
|
||||
#if HAS_FOLDER_SORTING
|
||||
bool dir1 = filenameIsDir;
|
||||
#endif
|
||||
|
||||
uint16_t j = i;
|
||||
getfilename_simple(sort_positions[sort_order[j - gap]]);
|
||||
char *name2 = LONGEST_FILENAME; // use the string in-place
|
||||
#if HAS_FOLDER_SORTING
|
||||
while (j >= gap && ((sdSort == SD_SORT_TIME)?_SORT_CMP_TIME_DIR(FOLDER_SORTING):_SORT_CMP_DIR(FOLDER_SORTING)))
|
||||
#else
|
||||
while (j >= gap && ((sdSort == SD_SORT_TIME)?_SORT_CMP_TIME_NODIR():_SORT_CMP_NODIR()))
|
||||
#endif
|
||||
{
|
||||
sort_order[j] = sort_order[j - gap];
|
||||
j -= gap;
|
||||
#ifdef SORTING_DUMP
|
||||
for (uint16_t z = 0; z < sortCountFiles; z++)
|
||||
{
|
||||
printf_P(PSTR("%2u "), sort_order[z]);
|
||||
}
|
||||
printf_P(PSTR("i%2d j%2d gap%2d orderBckp%2d\n"), i, j, gap, orderBckp);
|
||||
#endif
|
||||
if (j < gap) break;
|
||||
getfilename_simple(sort_positions[sort_order[j - gap]]);
|
||||
name2 = LONGEST_FILENAME; // use the string in-place
|
||||
}
|
||||
sort_order[j] = orderBckp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else //Bubble Sort
|
||||
|
||||
|
|
@ -913,7 +939,7 @@ void CardReader::presort() {
|
|||
#endif
|
||||
|
||||
uint16_t counter = 0;
|
||||
menu_progressbar_init(0.5*(fileCnt - 1)*(fileCnt), _T(MSG_SORTING_FILES));
|
||||
menu_progressbar_init(0.5*(fileCnt - 1)*(fileCnt), _i("Sorting files"));
|
||||
|
||||
for (uint16_t i = fileCnt; --i;) {
|
||||
if (!IS_SD_INSERTED) return;
|
||||
|
|
@ -927,22 +953,22 @@ void CardReader::presort() {
|
|||
#ifdef SORTING_DUMP
|
||||
for (uint16_t z = 0; z < fileCnt; z++)
|
||||
{
|
||||
printf_P(PSTR("%2u "), sort_entries[z]);
|
||||
printf_P(PSTR("%2u "), sort_order[z]);
|
||||
}
|
||||
MYSERIAL.println();
|
||||
#endif
|
||||
manage_heater();
|
||||
const uint16_t o1 = sort_entries[j], o2 = sort_entries[j + 1];
|
||||
const uint16_t o1 = sort_order[j], o2 = sort_order[j + 1];
|
||||
|
||||
counter++;
|
||||
getfilename_simple(o1);
|
||||
getfilename_simple(sort_positions[o1]);
|
||||
strcpy(name1, LONGEST_FILENAME); // save (or getfilename below will trounce it)
|
||||
crmod_date_bckp = crmodDate;
|
||||
crmod_time_bckp = crmodTime;
|
||||
#if HAS_FOLDER_SORTING
|
||||
bool dir1 = filenameIsDir;
|
||||
#endif
|
||||
getfilename_simple(o2);
|
||||
getfilename_simple(sort_positions[o2]);
|
||||
char *name2 = LONGEST_FILENAME; // use the string in-place
|
||||
|
||||
// Sort the current pair according to settings.
|
||||
|
|
@ -957,9 +983,9 @@ void CardReader::presort() {
|
|||
#ifdef SORTING_DUMP
|
||||
puts_P(PSTR("swap"));
|
||||
#endif
|
||||
|
||||
sort_entries[j] = o2;
|
||||
sort_entries[j + 1] = o1;
|
||||
|
||||
sort_order[j] = o2;
|
||||
sort_order[j + 1] = o1;
|
||||
didSwap = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -967,26 +993,52 @@ void CardReader::presort() {
|
|||
} //end of bubble sort loop
|
||||
#endif
|
||||
|
||||
#ifdef SORTING_SPEEDTEST
|
||||
printf_P(PSTR("sortingSpeedtestTimer:%lu\n"), sortingSpeedtestTimer.elapsed());
|
||||
#endif //SORTING_SPEEDTEST
|
||||
|
||||
#ifdef SORTING_DUMP
|
||||
for (uint16_t z = 0; z < fileCnt; z++)
|
||||
printf_P(PSTR("%2u "), sort_entries[z]);
|
||||
printf_P(PSTR("%2u "), sort_order[z]);
|
||||
SERIAL_PROTOCOLLN();
|
||||
#endif
|
||||
|
||||
uint8_t sort_order_reverse_index[fileCnt];
|
||||
for (uint8_t i = 0; i < fileCnt; i++)
|
||||
sort_order_reverse_index[sort_order[i]] = i;
|
||||
for (uint8_t i = 0; i < fileCnt; i++)
|
||||
{
|
||||
if (sort_order_reverse_index[i] != i)
|
||||
{
|
||||
uint32_t el = sort_positions[i];
|
||||
uint8_t idx = sort_order_reverse_index[i];
|
||||
while (idx != i)
|
||||
{
|
||||
uint32_t el1 = sort_positions[idx];
|
||||
uint8_t idx1 = sort_order_reverse_index[idx];
|
||||
sort_order_reverse_index[idx] = idx;
|
||||
sort_positions[idx] = el;
|
||||
idx = idx1;
|
||||
el = el1;
|
||||
}
|
||||
sort_order_reverse_index[idx] = idx;
|
||||
sort_positions[idx] = el;
|
||||
}
|
||||
}
|
||||
menu_progressbar_finish();
|
||||
}
|
||||
else {
|
||||
getfilename(0);
|
||||
sort_positions[0] = position;
|
||||
}
|
||||
|
||||
sort_count = fileCnt;
|
||||
}
|
||||
|
||||
lcd_update(2);
|
||||
KEEPALIVE_STATE(NOT_BUSY);
|
||||
}
|
||||
|
||||
void CardReader::flush_presort() {
|
||||
sort_count = 0;
|
||||
lastSortedFilePosition = 0;
|
||||
if (sort_count > 0) {
|
||||
sort_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SDCARD_SORT_ALPHA
|
||||
|
|
@ -996,10 +1048,9 @@ void CardReader::flush_presort() {
|
|||
void CardReader::printingHasFinished()
|
||||
{
|
||||
st_synchronize();
|
||||
file.close();
|
||||
|
||||
if(file_subcall_ctr>0) //heading up to a parent file that called current as a procedure.
|
||||
{
|
||||
file.close();
|
||||
file_subcall_ctr--;
|
||||
openFileReadFilteredGcode(filenames[file_subcall_ctr],true);
|
||||
setIndex(filespos[file_subcall_ctr]);
|
||||
|
|
@ -1007,8 +1058,9 @@ void CardReader::printingHasFinished()
|
|||
}
|
||||
else
|
||||
{
|
||||
quickStop();
|
||||
file.close();
|
||||
sdprinting = false;
|
||||
SetPrinterState(PrinterState::SDPrintingFinished); //set printer state to show LCD menu after finished SD print
|
||||
if(SD_FINISHED_STEPPERRELEASE)
|
||||
{
|
||||
finishAndDisableSteppers();
|
||||
|
|
@ -1027,17 +1079,4 @@ bool CardReader::ToshibaFlashAir_GetIP(uint8_t *ip)
|
|||
return card.readExtMemory(1, 1, 0x400+0x150, 4, ip);
|
||||
}
|
||||
|
||||
//Used for Reprint action
|
||||
bool CardReader::FileExists(const char* filename)
|
||||
{
|
||||
bool exists = false;
|
||||
|
||||
if (file.open(curDir, filename, O_READ))
|
||||
{
|
||||
exists = true;
|
||||
file.close();
|
||||
}
|
||||
return exists;
|
||||
}
|
||||
|
||||
#endif //SDSUPPORT
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ class CardReader
|
|||
{
|
||||
public:
|
||||
CardReader();
|
||||
|
||||
|
||||
enum LsAction : uint8_t
|
||||
{
|
||||
LS_SerialPrint,
|
||||
|
|
@ -26,14 +26,14 @@ public:
|
|||
inline ls_param():LFN(0), timestamp(0) { }
|
||||
inline ls_param(bool LFN, bool timestamp):LFN(LFN), timestamp(timestamp) { }
|
||||
} __attribute__((packed));
|
||||
|
||||
void mount(bool doPresort = true);
|
||||
|
||||
void initsd(bool doPresort = true);
|
||||
void write_command(char *buf);
|
||||
void write_command_no_newline(char *buf);
|
||||
//files auto[0-9].g on the sd card are performed in a row
|
||||
//this is to delay autostart and hence the initialisaiton of the sd card to some seconds after the normal init, so the device is available quick after a reset
|
||||
|
||||
void checkautostart(bool x);
|
||||
void checkautostart(bool x);
|
||||
void openFileWrite(const char* name);
|
||||
void openFileReadFilteredGcode(const char* name, bool replace_current = false);
|
||||
void openLogFile(const char* name);
|
||||
|
|
@ -46,24 +46,28 @@ public:
|
|||
void printingHasFinished();
|
||||
|
||||
void getfilename(uint16_t nr, const char* const match=NULL);
|
||||
void getfilename_simple(uint16_t entry, const char * const match = NULL);
|
||||
void getfilename_simple(uint32_t position, const char * const match = NULL);
|
||||
void getfilename_next(uint32_t position, const char * const match = NULL);
|
||||
uint16_t getnrfilenames();
|
||||
|
||||
|
||||
void getAbsFilename(char *t);
|
||||
void printAbsFilenameFast();
|
||||
void getDirName(char* name, uint8_t level);
|
||||
uint8_t getWorkDirDepth();
|
||||
uint16_t getWorkDirDepth();
|
||||
|
||||
|
||||
void ls(ls_param params);
|
||||
bool chdir(const char * relpath, bool doPresort);
|
||||
void updir();
|
||||
void cdroot(bool doPresort);
|
||||
void setroot(bool doPresort);
|
||||
|
||||
#ifdef SDCARD_SORT_ALPHA
|
||||
void presort();
|
||||
#ifdef SDSORT_QUICKSORT
|
||||
void swap(uint8_t left, uint8_t right);
|
||||
void quicksort(uint8_t left, uint8_t right);
|
||||
#endif //SDSORT_QUICKSORT
|
||||
void getfilename_sorted(const uint16_t nr, uint8_t sdSort);
|
||||
void getfilename_afterMaxSorting(uint16_t entry, const char * const match = NULL);
|
||||
#endif
|
||||
|
||||
FORCE_INLINE bool isFileOpen() { return file.isOpen(); }
|
||||
|
|
@ -83,15 +87,12 @@ public:
|
|||
void ToshibaFlashAir_enable(bool enable) { card.setFlashAirCompatible(enable); }
|
||||
bool ToshibaFlashAir_GetIP(uint8_t *ip);
|
||||
|
||||
//Reprint
|
||||
bool FileExists(const char* filename);
|
||||
|
||||
public:
|
||||
bool saving;
|
||||
bool logging;
|
||||
bool sdprinting;
|
||||
bool mounted;
|
||||
char filename[FILENAME_LENGTH];
|
||||
bool sdprinting ;
|
||||
bool cardOK ;
|
||||
char filename[13];
|
||||
// There are scenarios when simple modification time is not enough (on MS Windows)
|
||||
// Therefore these timestamps hold the most recent one of creation/modification date/times
|
||||
uint16_t crmodTime, crmodDate;
|
||||
|
|
@ -101,17 +102,16 @@ public:
|
|||
int lastnr; //last number of the autostart;
|
||||
#ifdef SDCARD_SORT_ALPHA
|
||||
bool presort_flag;
|
||||
#endif // SDCARD_SORT_ALPHA
|
||||
char dir_names[MAX_DIR_DEPTH][9];
|
||||
#endif // SDCARD_SORT_ALPHA
|
||||
private:
|
||||
SdFile root,*curDir,workDir,workDirParents[MAX_DIR_DEPTH];
|
||||
uint8_t workDirDepth;
|
||||
uint16_t workDirDepth;
|
||||
|
||||
// Sort files and folders alphabetically.
|
||||
#ifdef SDCARD_SORT_ALPHA
|
||||
uint16_t sort_count; // Count of sorted items in the current directory
|
||||
uint16_t sort_entries[SDSORT_LIMIT];
|
||||
uint16_t lastSortedFilePosition;
|
||||
uint32_t sort_positions[SDSORT_LIMIT];
|
||||
|
||||
#endif // SDCARD_SORT_ALPHA
|
||||
|
||||
|
|
@ -130,10 +130,13 @@ private:
|
|||
char filenames[SD_PROCEDURE_DEPTH][MAXPATHNAMELENGTH];
|
||||
uint32_t filesize;
|
||||
//int16_t n;
|
||||
ShortTimer autostart_atmillis;
|
||||
unsigned long autostart_atmillis;
|
||||
uint32_t sdpos ;
|
||||
|
||||
bool autostart_stilltocheck; //the sd start is delayed, because otherwise the serial cannot answer fast enought to make contact with the hostsoftware.
|
||||
|
||||
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;
|
||||
|
||||
bool diveSubfolder (const char *&fileName);
|
||||
void lsDive(const char *prepend, SdFile parent, const char * const match=NULL, LsAction lsAction = LS_GetFilename, ls_param lsParams = ls_param());
|
||||
|
|
@ -146,7 +149,7 @@ extern CardReader card;
|
|||
#define IS_SD_PRINTING (card.sdprinting)
|
||||
|
||||
#if (SDCARDDETECT > -1)
|
||||
# ifdef SDCARDDETECTINVERTED
|
||||
# ifdef SDCARDDETECTINVERTED
|
||||
# define IS_SD_INSERTED (READ(SDCARDDETECT)!=0)
|
||||
# else
|
||||
# define IS_SD_INSERTED (READ(SDCARDDETECT)==0)
|
||||
|
|
|
|||
|
|
@ -1,14 +1,6 @@
|
|||
#include <stdarg.h>
|
||||
#include <util/atomic.h>
|
||||
#include "cmdqueue.h"
|
||||
#include "cardreader.h"
|
||||
#include "ultralcd.h"
|
||||
#include "Prusa_farm.h"
|
||||
#include "meatpack.h"
|
||||
#include "messages.h"
|
||||
#include "language.h"
|
||||
#include "stopwatch.h"
|
||||
#include "power_panic.h"
|
||||
|
||||
// Reserve BUFSIZE lines of length MAX_CMD_SIZE plus CMDBUFFER_RESERVE_FRONT.
|
||||
char cmdbuffer[BUFSIZE * (MAX_CMD_SIZE + 1) + CMDBUFFER_RESERVE_FRONT];
|
||||
|
|
@ -33,7 +25,11 @@ bool comment_mode = false;
|
|||
char *strchr_pointer; // just a pointer to find chars in the command string like X, Y, Z, E, etc
|
||||
|
||||
ShortTimer serialTimeoutTimer;
|
||||
|
||||
long gcode_N = 0;
|
||||
long gcode_LastN = 0;
|
||||
long Stopped_gcode_LastN = 0;
|
||||
|
||||
uint32_t sdpos_atomic = 0;
|
||||
|
||||
|
||||
|
|
@ -98,7 +94,7 @@ void cmdqueue_reset()
|
|||
{
|
||||
while (buflen)
|
||||
{
|
||||
// printf_P(PSTR("dumping: \"%s\" of type %u\n"), cmdbuffer+bufindr+CMDHDRSIZE, CMDBUFFER_CURRENT_TYPE);
|
||||
// printf_P(PSTR("dumping: \"%s\" of type %hu\n"), cmdbuffer+bufindr+CMDHDRSIZE, CMDBUFFER_CURRENT_TYPE);
|
||||
ClearToSend();
|
||||
cmdqueue_pop_front();
|
||||
}
|
||||
|
|
@ -108,7 +104,7 @@ void cmdqueue_reset()
|
|||
//commands are removed from command queue after process_command() function is finished
|
||||
//reseting command queue and enqueing new commands during some (usually long running) command processing would cause that new commands are immediately removed from queue (or damaged)
|
||||
//this will ensure that all new commands which are enqueued after cmdqueue reset, will be always executed
|
||||
cmdbuffer_front_already_processed = true;
|
||||
cmdbuffer_front_already_processed = true;
|
||||
}
|
||||
|
||||
// How long a string could be pushed to the front of the command queue?
|
||||
|
|
@ -159,7 +155,7 @@ static bool cmdqueue_could_enqueue_front(size_t len_asked)
|
|||
// len_asked does not contain the zero terminator size.
|
||||
// This function may update bufindw, therefore for the power panic to work, this function must be called
|
||||
// with the interrupts disabled!
|
||||
static bool __attribute__((noinline)) cmdqueue_could_enqueue_back(size_t len_asked)
|
||||
static bool cmdqueue_could_enqueue_back(size_t len_asked, bool atomic_update = false)
|
||||
{
|
||||
// MAX_CMD_SIZE has to accommodate the zero terminator.
|
||||
if (len_asked >= MAX_CMD_SIZE)
|
||||
|
|
@ -169,29 +165,61 @@ static bool __attribute__((noinline)) cmdqueue_could_enqueue_back(size_t len_ask
|
|||
// Full buffer.
|
||||
return false;
|
||||
|
||||
// If there is some data stored starting at bufindw, len_asked is certainly smaller than
|
||||
// the allocated data buffer. Try to reserve a new buffer and to move the already received
|
||||
// serial data.
|
||||
// How much memory to reserve for the commands pushed to the front?
|
||||
// End of the queue, when pushing to the end.
|
||||
size_t endw = bufindw + len_asked + (1 + CMDHDRSIZE);
|
||||
if (bufindw < bufindr)
|
||||
// Simple case. There is a contiguous space between the write buffer and the read buffer.
|
||||
return endw + CMDBUFFER_RESERVE_FRONT <= bufindr;
|
||||
// Otherwise the free space is split between the start and end.
|
||||
if (// Could one fit to the end, including the reserve?
|
||||
endw + CMDBUFFER_RESERVE_FRONT <= sizeof(cmdbuffer) ||
|
||||
// Could one fit to the end, and the reserve to the start?
|
||||
(endw <= sizeof(cmdbuffer) && CMDBUFFER_RESERVE_FRONT <= bufindr))
|
||||
return true;
|
||||
// Could one fit both to the start?
|
||||
if (len_asked + (1 + CMDHDRSIZE) + CMDBUFFER_RESERVE_FRONT <= bufindr) {
|
||||
// Mark the rest of the buffer as used.
|
||||
memset(cmdbuffer+bufindw, 0, sizeof(cmdbuffer)-bufindw);
|
||||
// and point to the start.
|
||||
// Be careful! The bufindw needs to be changed atomically for the power panic & filament panic to work.
|
||||
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) { bufindw = 0; }
|
||||
return true;
|
||||
if (serial_count > 0) {
|
||||
// If there is some data stored starting at bufindw, len_asked is certainly smaller than
|
||||
// the allocated data buffer. Try to reserve a new buffer and to move the already received
|
||||
// serial data.
|
||||
// How much memory to reserve for the commands pushed to the front?
|
||||
// End of the queue, when pushing to the end.
|
||||
size_t endw = bufindw + len_asked + (1 + CMDHDRSIZE);
|
||||
if (bufindw < bufindr)
|
||||
// Simple case. There is a contiguous space between the write buffer and the read buffer.
|
||||
return endw + CMDBUFFER_RESERVE_FRONT <= bufindr;
|
||||
// Otherwise the free space is split between the start and end.
|
||||
if (// Could one fit to the end, including the reserve?
|
||||
endw + CMDBUFFER_RESERVE_FRONT <= sizeof(cmdbuffer) ||
|
||||
// Could one fit to the end, and the reserve to the start?
|
||||
(endw <= sizeof(cmdbuffer) && CMDBUFFER_RESERVE_FRONT <= bufindr))
|
||||
return true;
|
||||
// Could one fit both to the start?
|
||||
if (len_asked + (1 + CMDHDRSIZE) + CMDBUFFER_RESERVE_FRONT <= bufindr) {
|
||||
// Mark the rest of the buffer as used.
|
||||
memset(cmdbuffer+bufindw, 0, sizeof(cmdbuffer)-bufindw);
|
||||
// and point to the start.
|
||||
// Be careful! The bufindw needs to be changed atomically for the power panic & filament panic to work.
|
||||
if (atomic_update)
|
||||
cli();
|
||||
bufindw = 0;
|
||||
if (atomic_update)
|
||||
sei();
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
// How much memory to reserve for the commands pushed to the front?
|
||||
// End of the queue, when pushing to the end.
|
||||
size_t endw = bufindw + len_asked + (1 + CMDHDRSIZE);
|
||||
if (bufindw < bufindr)
|
||||
// Simple case. There is a contiguous space between the write buffer and the read buffer.
|
||||
return endw + CMDBUFFER_RESERVE_FRONT <= bufindr;
|
||||
// Otherwise the free space is split between the start and end.
|
||||
if (// Could one fit to the end, including the reserve?
|
||||
endw + CMDBUFFER_RESERVE_FRONT <= sizeof(cmdbuffer) ||
|
||||
// Could one fit to the end, and the reserve to the start?
|
||||
(endw <= sizeof(cmdbuffer) && CMDBUFFER_RESERVE_FRONT <= bufindr))
|
||||
return true;
|
||||
// Could one fit both to the start?
|
||||
if (len_asked + (1 + CMDHDRSIZE) + CMDBUFFER_RESERVE_FRONT <= bufindr) {
|
||||
// Mark the rest of the buffer as used.
|
||||
memset(cmdbuffer+bufindw, 0, sizeof(cmdbuffer)-bufindw);
|
||||
// and point to the start.
|
||||
// Be careful! The bufindw needs to be changed atomically for the power panic & filament panic to work.
|
||||
if (atomic_update)
|
||||
cli();
|
||||
bufindw = 0;
|
||||
if (atomic_update)
|
||||
sei();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -254,22 +282,6 @@ void cmdqueue_dump_to_serial()
|
|||
}
|
||||
#endif /* CMDBUFFER_DEBUG */
|
||||
|
||||
static const char bufferFull[] PROGMEM = "\" failed: Buffer full!";
|
||||
static const char enqueingFront[] PROGMEM = "Enqueing to the front: \"";
|
||||
|
||||
|
||||
void enquecommandf_P(const char *fmt, ...)
|
||||
{
|
||||
// MAX_CMD_SIZE is 96, but for formatting
|
||||
// string we usually don't need more than 30 bytes
|
||||
char cmd_buffer[30];
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vsnprintf_P(cmd_buffer, sizeof(cmd_buffer), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
enquecommand(cmd_buffer, false);
|
||||
}
|
||||
//adds an command to the main command buffer
|
||||
//thats really done in a non-safe way.
|
||||
//needs overworking someday
|
||||
|
|
@ -305,7 +317,7 @@ void enquecommand(const char *cmd, bool from_progmem)
|
|||
SERIAL_PROTOCOLRPGM(cmd);
|
||||
else
|
||||
SERIAL_ECHO(cmd);
|
||||
SERIAL_ECHOLNRPGM(bufferFull);
|
||||
SERIAL_ECHOLNPGM("\" failed: Buffer full!");
|
||||
#ifdef CMDBUFFER_DEBUG
|
||||
cmdqueue_dump_to_serial();
|
||||
#endif /* CMDBUFFER_DEBUG */
|
||||
|
|
@ -329,7 +341,7 @@ void enquecommand_front(const char *cmd, bool from_progmem)
|
|||
strcpy(cmdbuffer + bufindr + CMDHDRSIZE, cmd);
|
||||
++ buflen;
|
||||
SERIAL_ECHO_START;
|
||||
SERIAL_ECHORPGM(enqueingFront);
|
||||
SERIAL_ECHOPGM("Enqueing to the front: \"");
|
||||
SERIAL_ECHO(cmdbuffer + bufindr + CMDHDRSIZE);
|
||||
SERIAL_ECHOLNPGM("\"");
|
||||
#ifdef CMDBUFFER_DEBUG
|
||||
|
|
@ -337,12 +349,12 @@ void enquecommand_front(const char *cmd, bool from_progmem)
|
|||
#endif /* CMDBUFFER_DEBUG */
|
||||
} else {
|
||||
SERIAL_ERROR_START;
|
||||
SERIAL_ECHORPGM(enqueingFront);
|
||||
SERIAL_ECHOPGM("Enqueing to the front: \"");
|
||||
if (from_progmem)
|
||||
SERIAL_PROTOCOLRPGM(cmd);
|
||||
else
|
||||
SERIAL_ECHO(cmd);
|
||||
SERIAL_ECHOLNRPGM(bufferFull);
|
||||
SERIAL_ECHOLNPGM("\" failed: Buffer full!");
|
||||
#ifdef CMDBUFFER_DEBUG
|
||||
cmdqueue_dump_to_serial();
|
||||
#endif /* CMDBUFFER_DEBUG */
|
||||
|
|
@ -354,12 +366,22 @@ void enquecommand_front(const char *cmd, bool from_progmem)
|
|||
void repeatcommand_front()
|
||||
{
|
||||
cmdbuffer_front_already_processed = true;
|
||||
}
|
||||
|
||||
void proc_commands() {
|
||||
if (buflen)
|
||||
{
|
||||
process_commands();
|
||||
if (!cmdbuffer_front_already_processed)
|
||||
cmdqueue_pop_front();
|
||||
cmdbuffer_front_already_processed = false;
|
||||
}
|
||||
}
|
||||
|
||||
void get_command()
|
||||
{
|
||||
// Test and reserve space for the new command string.
|
||||
if (! cmdqueue_could_enqueue_back(MAX_CMD_SIZE - 1))
|
||||
if (! cmdqueue_could_enqueue_back(MAX_CMD_SIZE - 1, true))
|
||||
return;
|
||||
|
||||
if (MYSERIAL.available() == RX_BUFFER_SIZE - 1) { //compare number of chars buffered in rx buffer with rx buffer size
|
||||
|
|
@ -368,24 +390,16 @@ void get_command()
|
|||
}
|
||||
|
||||
// start of serial line processing loop
|
||||
while (((MYSERIAL.available() > 0 && !saved_printing) || (MYSERIAL.available() > 0 && printingIsPaused())) && !cmdqueue_serial_disabled) { //is print is saved (crash detection or filament detection), dont process data from serial line
|
||||
|
||||
#ifdef ENABLE_MEATPACK
|
||||
// MeatPack Changes
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
const int rec = MYSERIAL.read();
|
||||
if (rec < 0) continue;
|
||||
|
||||
mp_handle_rx_char((uint8_t)rec);
|
||||
char c_res[2] = {0, 0};
|
||||
const uint8_t char_count = mp_get_result_char(c_res);
|
||||
// Note -- Paired bracket in preproc switch below
|
||||
for (uint8_t i = 0; i < char_count; ++i) { char serial_char = c_res[i];
|
||||
#else
|
||||
while (((MYSERIAL.available() > 0 && !saved_printing) || (MYSERIAL.available() > 0 && isPrintPaused)) && !cmdqueue_serial_disabled) { //is print is saved (crash detection or filament detection), dont process data from serial line
|
||||
|
||||
char serial_char = MYSERIAL.read();
|
||||
#endif
|
||||
|
||||
serialTimeoutTimer.start();
|
||||
/* if (selectedSerialPort == 1)
|
||||
{
|
||||
selectedSerialPort = 0;
|
||||
MYSERIAL.write(serial_char); // for debuging serial line 2 in farm_mode
|
||||
selectedSerialPort = 1;
|
||||
} */ //RP - removed
|
||||
serialTimeoutTimer.start();
|
||||
|
||||
if (serial_char < 0)
|
||||
// Ignore extended ASCII characters. These characters have no meaning in the G-code apart from the file names
|
||||
|
|
@ -401,23 +415,22 @@ void get_command()
|
|||
comment_mode = false; //for new command
|
||||
return;
|
||||
}
|
||||
cmdbuffer[bufindw+serial_count+CMDHDRSIZE] = 0; // terminate string
|
||||
char* cmd_head = cmdbuffer+bufindw+CMDHDRSIZE; // current command pointer
|
||||
char* cmd_start = cmd_head; // pointer past the line number (if any)
|
||||
|
||||
cmdbuffer[bufindw+serial_count+CMDHDRSIZE] = 0; //terminate string
|
||||
if(!comment_mode){
|
||||
long gcode_N = -1; // seen line number
|
||||
|
||||
gcode_N = 0;
|
||||
|
||||
// Line numbers must be first in buffer
|
||||
if (*cmd_head == 'N') {
|
||||
|
||||
// Line number met: decode the number, then move cmd_start past all spaces.
|
||||
gcode_N = (strtol(cmd_head+1, &cmd_start, 10));
|
||||
while (*cmd_start == ' ') ++cmd_start;
|
||||
if ((strstr(cmdbuffer+bufindw+CMDHDRSIZE, "PRUSA") == NULL) &&
|
||||
(cmdbuffer[bufindw+CMDHDRSIZE] == 'N')) {
|
||||
|
||||
// Test whether the successive lines are stamped with an increasing line number ID.
|
||||
if(gcode_N != gcode_LastN+1 && strncmp_P(cmd_start, PSTR("M110"), 4)) {
|
||||
// Line numbers not sent in succession and M110 not seen.
|
||||
// Line number met. When sending a G-code over a serial line, each line may be stamped with its index,
|
||||
// and Marlin tests, whether the successive lines are stamped with an increasing line number ID
|
||||
gcode_N = (strtol(cmdbuffer+bufindw+CMDHDRSIZE+1, NULL, 10));
|
||||
if(gcode_N != gcode_LastN+1 && (strstr_P(cmdbuffer+bufindw+CMDHDRSIZE, PSTR("M110")) == NULL) ) {
|
||||
// M110 - set current line number.
|
||||
// Line numbers not sent in succession.
|
||||
SERIAL_ERROR_START;
|
||||
SERIAL_ERRORRPGM(_n("Line Number is not Last Line Number+1, Last Line: "));////MSG_ERR_LINE_NO
|
||||
SERIAL_ERRORLN(gcode_LastN);
|
||||
|
|
@ -427,13 +440,13 @@ void get_command()
|
|||
return;
|
||||
}
|
||||
|
||||
if((strchr_pointer = strchr(cmd_start, '*')) != NULL)
|
||||
if((strchr_pointer = strchr(cmdbuffer+bufindw+CMDHDRSIZE, '*')) != NULL)
|
||||
{
|
||||
byte checksum = 0;
|
||||
char *p = cmd_head;
|
||||
char *p = cmdbuffer+bufindw+CMDHDRSIZE;
|
||||
while (p != strchr_pointer)
|
||||
checksum = checksum^(*p++);
|
||||
if (code_value_short() != (int16_t)checksum) {
|
||||
if (int(strtol(strchr_pointer+1, NULL, 10)) != int(checksum)) {
|
||||
SERIAL_ERROR_START;
|
||||
SERIAL_ERRORRPGM(_n("checksum mismatch, Last Line: "));////MSG_ERR_CHECKSUM_MISMATCH
|
||||
SERIAL_ERRORLN(gcode_LastN);
|
||||
|
|
@ -453,82 +466,54 @@ void get_command()
|
|||
serial_count = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Don't parse N again with code_seen('N')
|
||||
cmdbuffer[bufindw + CMDHDRSIZE] = '$';
|
||||
//if no errors, continue parsing
|
||||
gcode_LastN = gcode_N;
|
||||
}
|
||||
else
|
||||
// if we don't receive 'N' but still see '*'
|
||||
if ((cmdbuffer[bufindw + CMDHDRSIZE] != 'N') && (cmdbuffer[bufindw + CMDHDRSIZE] != '$') && (strchr(cmdbuffer+bufindw+CMDHDRSIZE, '*') != NULL))
|
||||
{
|
||||
// move cmd_start past all spaces
|
||||
while (*cmd_start == ' ') ++cmd_start;
|
||||
|
||||
// if we didn't receive 'N' but still see '*'
|
||||
if (strchr(cmd_start, '*') != NULL)
|
||||
{
|
||||
SERIAL_ERROR_START;
|
||||
SERIAL_ERRORRPGM(_n("No Line Number with checksum, Last Line: "));////MSG_ERR_NO_LINENUMBER_WITH_CHECKSUM
|
||||
SERIAL_ERRORLN(gcode_LastN);
|
||||
FlushSerialRequestResend();
|
||||
serial_count = 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle KILL early, even when Stopped
|
||||
if(strcmp_P(cmd_start, PSTR("M112")) == 0)
|
||||
kill(MSG_M112_KILL);
|
||||
|
||||
// Bypass Stopped for some commands
|
||||
bool allow_when_stopped = false;
|
||||
if(strncmp_P(cmd_start, PSTR("M310"), 4) == 0)
|
||||
allow_when_stopped = true;
|
||||
|
||||
// Handle the USB timer
|
||||
if ((*cmd_start == 'G') && (GetPrinterState() != PrinterState::IsSDPrinting)) {
|
||||
usb_timer.start();
|
||||
SetPrinterState(PrinterState::IsHostPrinting); //set printer state busy printing to hide LCD menu while USB printing
|
||||
eeprom_update_byte_notify((uint8_t*)EEPROM_UVLO, PowerPanic::NO_PENDING_RECOVERY);
|
||||
}
|
||||
if (allow_when_stopped == false && Stopped == true) {
|
||||
// Stopped can be set either during error states (thermal error: cannot continue), or
|
||||
// when a printer-initiated action is processed. In such case the printer will send to
|
||||
// the host an action, but cannot know if the action has been processed while new
|
||||
// commands are being sent. In this situation we just drop the command while issuing
|
||||
// periodic "busy" messages in the main loop. Since we're not incrementing the received
|
||||
// line number, a request for resend will happen (if necessary), ensuring we don't skip
|
||||
// commands whenever Stopped is cleared and processing resumes.
|
||||
SERIAL_ERROR_START;
|
||||
SERIAL_ERRORRPGM(_n("No Line Number with checksum, Last Line: "));////MSG_ERR_NO_LINENUMBER_WITH_CHECKSUM
|
||||
SERIAL_ERRORLN(gcode_LastN);
|
||||
FlushSerialRequestResend();
|
||||
serial_count = 0;
|
||||
return;
|
||||
}
|
||||
if ((strchr_pointer = strchr(cmdbuffer+bufindw+CMDHDRSIZE, 'G')) != NULL) {
|
||||
if (! IS_SD_PRINTING) {
|
||||
usb_printing_counter = 10;
|
||||
is_usb_printing = true;
|
||||
}
|
||||
if (Stopped == true) {
|
||||
int gcode = strtol(strchr_pointer+1, NULL, 10);
|
||||
if (gcode >= 0 && gcode <= 3) {
|
||||
SERIAL_ERRORLNRPGM(MSG_ERR_STOPPED);
|
||||
LCD_MESSAGERPGM(_T(MSG_STOPPED));
|
||||
}
|
||||
}
|
||||
} // end of 'G' command
|
||||
|
||||
// Command is complete: store the current line into buffer, move to the next line.
|
||||
|
||||
//If command was e-stop process now
|
||||
if(strcmp(cmdbuffer+bufindw+CMDHDRSIZE, "M112") == 0)
|
||||
kill(MSG_M112_KILL, 2);
|
||||
|
||||
// Store the current line into buffer, move to the next line.
|
||||
// Store type of entry
|
||||
cmdbuffer[bufindw] = gcode_N >= 0 ? CMDBUFFER_CURRENT_TYPE_USB_WITH_LINENR : CMDBUFFER_CURRENT_TYPE_USB;
|
||||
|
||||
cmdbuffer[bufindw] = gcode_N ? CMDBUFFER_CURRENT_TYPE_USB_WITH_LINENR : CMDBUFFER_CURRENT_TYPE_USB;
|
||||
#ifdef CMDBUFFER_DEBUG
|
||||
SERIAL_ECHO_START;
|
||||
SERIAL_ECHOPGM("Storing a command line to buffer: ");
|
||||
SERIAL_ECHO(cmd_start);
|
||||
SERIAL_ECHO(cmdbuffer+bufindw+CMDHDRSIZE);
|
||||
SERIAL_ECHOLNPGM("");
|
||||
#endif /* CMDBUFFER_DEBUG */
|
||||
|
||||
// Store the command itself (without line number or checksum)
|
||||
size_t cmd_len;
|
||||
if (cmd_head == cmd_start)
|
||||
cmd_len = strlen(cmd_start) + 1;
|
||||
else {
|
||||
// strip the line number
|
||||
cmd_len = 0;
|
||||
do { cmd_head[cmd_len] = cmd_start[cmd_len]; }
|
||||
while (cmd_head[cmd_len++]);
|
||||
}
|
||||
bufindw += cmd_len + CMDHDRSIZE;
|
||||
bufindw += strlen(cmdbuffer+bufindw+CMDHDRSIZE) + (1 + CMDHDRSIZE);
|
||||
if (bufindw == sizeof(cmdbuffer))
|
||||
bufindw = 0;
|
||||
++ buflen;
|
||||
|
||||
// Update the processed gcode line
|
||||
if (gcode_N >= 0)
|
||||
gcode_LastN = gcode_N;
|
||||
|
||||
#ifdef CMDBUFFER_DEBUG
|
||||
SERIAL_ECHOPGM("Number of commands in the buffer: ");
|
||||
SERIAL_ECHO(buflen);
|
||||
|
|
@ -538,7 +523,7 @@ void get_command()
|
|||
serial_count = 0; //clear buffer
|
||||
// Don't call cmdqueue_could_enqueue_back if there are no characters waiting
|
||||
// in the queue, as this function will reserve the memory.
|
||||
if (MYSERIAL.available() == 0 || ! cmdqueue_could_enqueue_back(MAX_CMD_SIZE-1))
|
||||
if (MYSERIAL.available() == 0 || ! cmdqueue_could_enqueue_back(MAX_CMD_SIZE-1, true))
|
||||
return;
|
||||
} // end of "end of line" processing
|
||||
else {
|
||||
|
|
@ -546,9 +531,6 @@ void get_command()
|
|||
if(serial_char == ';') comment_mode = true;
|
||||
if(!comment_mode) cmdbuffer[bufindw+CMDHDRSIZE+serial_count++] = serial_char;
|
||||
}
|
||||
#ifdef ENABLE_MEATPACK
|
||||
}
|
||||
#endif
|
||||
} // end of serial line processing loop
|
||||
|
||||
if (serial_count > 0 && serialTimeoutTimer.expired(farm_mode ? 800 : 2000)) {
|
||||
|
|
@ -559,7 +541,7 @@ void get_command()
|
|||
}
|
||||
|
||||
#ifdef SDSUPPORT
|
||||
if(!card.sdprinting || !card.isFileOpen() || serial_count!=0){
|
||||
if(!card.sdprinting || serial_count!=0){
|
||||
// If there is a half filled buffer from serial line, wait until return before
|
||||
// continuing with the serial line.
|
||||
return;
|
||||
|
|
@ -585,7 +567,7 @@ void get_command()
|
|||
char serial_char = (char)n;
|
||||
if( serial_char == '\n'
|
||||
|| serial_char == '\r'
|
||||
|| serial_char == '#'
|
||||
|| ((serial_char == '#' || serial_char == ':') )
|
||||
|| serial_count >= (MAX_CMD_SIZE - 1)
|
||||
|| n==-1
|
||||
){
|
||||
|
|
@ -596,9 +578,9 @@ void get_command()
|
|||
{
|
||||
// This is either an empty line, or a line with just a comment.
|
||||
// Continue to the following line, and continue accumulating the number of bytes
|
||||
// read from the sdcard into sd_count,
|
||||
// so that the length of the already read empty lines and comments will be added
|
||||
// to the following non-empty line.
|
||||
// read from the sdcard into sd_count,
|
||||
// so that the lenght of the already read empty lines and comments will be added
|
||||
// to the following non-empty line.
|
||||
return; // prevent cycling indefinitely - let manage_heaters do their job
|
||||
}
|
||||
// The new command buffer could be updated non-atomically, because it is not yet considered
|
||||
|
|
@ -635,11 +617,11 @@ void get_command()
|
|||
|
||||
comment_mode = false; //for new command
|
||||
serial_count = 0; //clear buffer
|
||||
|
||||
|
||||
if(card.eof()) break;
|
||||
|
||||
// The following line will reserve buffer space if available.
|
||||
if (! cmdqueue_could_enqueue_back(MAX_CMD_SIZE-1))
|
||||
if (! cmdqueue_could_enqueue_back(MAX_CMD_SIZE-1, true))
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
|
@ -656,28 +638,27 @@ void get_command()
|
|||
// cleared by printingHasFinished after peforming all remaining moves.
|
||||
if(!cmdqueue_calc_sd_length())
|
||||
{
|
||||
// queue is complete, but before we process EOF commands prevent
|
||||
// re-entry by disabling SD processing from any st_synchronize call
|
||||
card.closefile();
|
||||
|
||||
SERIAL_PROTOCOLLNRPGM(_n("Done printing file"));////MSG_FILE_PRINTED
|
||||
stoptime=_millis();
|
||||
char time[30];
|
||||
uint32_t t = print_job_timer.duration() / 60;
|
||||
unsigned long t=(stoptime-starttime-pause_time)/1000;
|
||||
pause_time = 0;
|
||||
int hours, minutes;
|
||||
minutes = t % 60;
|
||||
hours = t / 60;
|
||||
save_statistics();
|
||||
minutes=(t/60)%60;
|
||||
hours=t/60/60;
|
||||
save_statistics(total_filament_used, t);
|
||||
sprintf_P(time, PSTR("%i hours %i minutes"),hours, minutes);
|
||||
SERIAL_ECHO_START;
|
||||
SERIAL_ECHOLN(time);
|
||||
#ifndef SHOW_FILENAME_AFTER_FINISH
|
||||
lcd_setstatus(time);
|
||||
#endif //SHOW_FILENAME_AFTER_FINISH
|
||||
card.printingHasFinished();
|
||||
card.checkautostart(true);
|
||||
|
||||
if (farm_mode)
|
||||
prusa_statistics(6);
|
||||
{
|
||||
prusa_statistics(6);
|
||||
lcd_commands_type = LcdCommands::FarmModeConfirm;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,11 +2,13 @@
|
|||
#define CMDQUEUE_H
|
||||
|
||||
#include "Marlin.h"
|
||||
#include "language.h"
|
||||
|
||||
|
||||
// String circular buffer. Commands may be pushed to the buffer from both sides:
|
||||
// Chained commands will be pushed to the front, interactive (from LCD menu)
|
||||
// Chained commands will be pushed to the front, interactive (from LCD menu)
|
||||
// and printing commands (from serial line or from SD card) are pushed to the tail.
|
||||
// First character of each entry indicates the type of the entry:
|
||||
// First character of each entry indicates the type of the entry:
|
||||
#define CMDBUFFER_CURRENT_TYPE_UNKNOWN 0
|
||||
// Command in cmdbuffer was sent over USB.
|
||||
#define CMDBUFFER_CURRENT_TYPE_USB 1
|
||||
|
|
@ -16,8 +18,8 @@
|
|||
#define CMDBUFFER_CURRENT_TYPE_UI 3
|
||||
// Command in cmdbuffer was generated by another G-code.
|
||||
#define CMDBUFFER_CURRENT_TYPE_CHAINED 4
|
||||
// Command has been processed and its SD card length has been possibly pushed
|
||||
// to the planner queue, but not yet removed from the cmdqueue.
|
||||
// Command has been processed and its SD card length has been possibly pushed
|
||||
// to the planner queue, but not yet removed from the cmdqueue.
|
||||
// This is a temporary state to reduce stepper interrupt locking time.
|
||||
#define CMDBUFFER_CURRENT_TYPE_TO_BE_REMOVED 5
|
||||
//Command in cmdbuffer was sent over USB and contains line number
|
||||
|
|
@ -50,7 +52,9 @@ extern int serial_count;
|
|||
extern bool comment_mode;
|
||||
extern char *strchr_pointer;
|
||||
|
||||
extern long gcode_N;
|
||||
extern long gcode_LastN;
|
||||
extern long Stopped_gcode_LastN;
|
||||
|
||||
extern bool cmdqueue_pop_front();
|
||||
extern void cmdqueue_reset();
|
||||
|
|
@ -59,31 +63,29 @@ extern void cmdqueue_dump_to_serial_single_line(int nr, const char *p);
|
|||
extern void cmdqueue_dump_to_serial();
|
||||
#endif /* CMDBUFFER_DEBUG */
|
||||
extern bool cmd_buffer_empty();
|
||||
|
||||
/// @brief Variant of enquecommand which accepts a format string
|
||||
/// @param fmt a format string residing in PROGMEM
|
||||
void enquecommandf_P(const char *fmt, ...);
|
||||
extern void enquecommand(const char *cmd, bool from_progmem = false);
|
||||
extern void enquecommand_front(const char *cmd, bool from_progmem = false);
|
||||
extern void repeatcommand_front();
|
||||
extern void get_command();
|
||||
extern uint16_t cmdqueue_calc_sd_length();
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
extern double strtod_noE(const char* nptr, char** endptr);
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
// Return True if a character was found
|
||||
static inline bool code_seen(char code) { return (strchr_pointer = strchr(CMDBUFFER_CURRENT_STRING, code)) != NULL; }
|
||||
static inline bool code_seen_P(const char *code_PROGMEM) { return (strchr_pointer = strstr_P(CMDBUFFER_CURRENT_STRING, code_PROGMEM)) != NULL; }
|
||||
static inline float code_value() { return strtod_noE(strchr_pointer+1, NULL);}
|
||||
static inline float code_value() { return strtod(strchr_pointer+1, NULL);}
|
||||
static inline long code_value_long() { return strtol(strchr_pointer+1, NULL, 10); }
|
||||
static inline int16_t code_value_short() { return int16_t(strtol(strchr_pointer+1, NULL, 10)); };
|
||||
static inline uint8_t code_value_uint8() { return uint8_t(strtol(strchr_pointer+1, NULL, 10)); };
|
||||
|
||||
static inline float code_value_float()
|
||||
{
|
||||
char* e = strchr(strchr_pointer, 'E');
|
||||
if (!e) return strtod(strchr_pointer + 1, NULL);
|
||||
*e = 0;
|
||||
float ret = strtod(strchr_pointer + 1, NULL);
|
||||
*e = 'E';
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
#endif //CMDQUEUE_H
|
||||
|
|
|
|||
|
|
@ -2,22 +2,25 @@
|
|||
#define _CONFIG_H
|
||||
|
||||
|
||||
#include "Configuration_var.h"
|
||||
#include "Configuration_prusa.h"
|
||||
#include "pins.h"
|
||||
|
||||
#if (defined(VOLT_IR_PIN) && defined(IR_SENSOR))
|
||||
# define IR_SENSOR_ANALOG
|
||||
#endif
|
||||
|
||||
//ADC configuration
|
||||
#if defined(FILAMENT_SENSOR) && (FILAMENT_SENSOR_TYPE == FSENSOR_IR_ANALOG)
|
||||
#define ADC_CHAN_MSK 0b0000001101011111 //used AD channels bit mask (0,1,2,3,4,6,8,9)
|
||||
#define ADC_DIDR_MSK 0b0000001001011111 //AD channels DIDR mask (1 ~ disabled digital input)
|
||||
#define ADC_CHAN_CNT 8 //number of used channels)
|
||||
#else
|
||||
#ifndef IR_SENSOR_ANALOG
|
||||
#define ADC_CHAN_MSK 0b0000001001011111 //used AD channels bit mask (0,1,2,3,4,6,9)
|
||||
#define ADC_DIDR_MSK 0b0000001001011111 //AD channels DIDR mask (1 ~ disabled digital input)
|
||||
#define ADC_CHAN_CNT 7 //number of used channels)
|
||||
#endif
|
||||
#else //!IR_SENSOR_ANALOG
|
||||
#define ADC_CHAN_MSK 0b0000001101011111 //used AD channels bit mask (0,1,2,3,4,6,8,9)
|
||||
#define ADC_DIDR_MSK 0b0000001001011111 //AD channels DIDR mask (1 ~ disabled digital input)
|
||||
#define ADC_CHAN_CNT 8 //number of used channels)
|
||||
#endif //!IR_SENSOR_ANALOG
|
||||
#define ADC_OVRSAMPL 16 //oversampling multiplier
|
||||
#define ADC_CALLBACK adc_callback //callback function ()
|
||||
#define ADC_CALLBACK adc_ready //callback function ()
|
||||
|
||||
//SWI2C configuration
|
||||
//#define SWI2C_SDA 20 //SDA on P3
|
||||
|
|
@ -27,6 +30,7 @@
|
|||
#define SWI2C_TMO 2048 //2048 cycles timeout
|
||||
|
||||
//PAT9125 configuration
|
||||
//#define PAT9125_SWSPI // software SPI mode (incomplete)
|
||||
#ifdef SWI2C_SCL
|
||||
#define PAT9125_SWI2C // software I2C mode
|
||||
#else
|
||||
|
|
@ -38,12 +42,7 @@
|
|||
//#define PAT9125_I2C_ADDR 0x73 //ID=NC
|
||||
#define PAT9125_XRES 0
|
||||
#define PAT9125_YRES 240 // maximum resolution (5*X cpi)
|
||||
#define PAT9125_YRES_MM (5*PAT9125_YRES/25.4) // counts per mm
|
||||
#define PAT9125_INVERT_X 0 //1 means flipped
|
||||
#define PAT9125_INVERT_Y 1 //1 means flipped
|
||||
#define PAT9125_SWAP_XY 0 //X is Y and Y is X
|
||||
#define PAT9125_12B_RES 1 //8bit or 12bit signed motion data
|
||||
#define PAT9125_NEW_INIT 1 //set to 1 to use the magic sequence provided by pixart.
|
||||
#define PAT9124_YRES_MM (5*PAT9125_YRES/25.4) // counts per mm
|
||||
|
||||
//SM4 configuration
|
||||
#define SM4_DEFDELAY 500 //default step delay [us]
|
||||
|
|
@ -55,17 +54,11 @@
|
|||
#define TMC2130_SPCR SPI_SPCR(TMC2130_SPI_RATE, 1, 1, 1, 0)
|
||||
#define TMC2130_SPSR SPI_SPSR(TMC2130_SPI_RATE)
|
||||
|
||||
// This is set by the cmake build to be able to take control of
|
||||
// the language flag, without breaking existing build mechanisms.
|
||||
#ifndef CMAKE_CONTROL
|
||||
//LANG - Multi-language support
|
||||
//#define LANG_MODE 0 // primary language only
|
||||
#define LANG_MODE 1 // sec. language support
|
||||
#endif
|
||||
|
||||
#define LANG_SIZE_RESERVED 0x3500 // reserved space for secondary language (13568 bytes).
|
||||
// 0x3D00 Maximum 15616 bytes as it depends on xflash_layout.h
|
||||
// 16 Languages max. per group including stock
|
||||
#define LANG_SIZE_RESERVED 0x3000 // reserved space for secondary language (12288 bytes). Maximum 32768 bytes
|
||||
|
||||
#if (LANG_SIZE_RESERVED % 256)
|
||||
#error "LANG_SIZE_RESERVED should be a multiple of a page size"
|
||||
|
|
@ -85,12 +78,9 @@
|
|||
//#define COMMUNITY_LANG_GROUP1_DA // Community Danish language
|
||||
//#define COMMUNITY_LANG_GROUP1_SL // Community Slovanian language
|
||||
//#define COMMUNITY_LANG_GROUP1_LB // Community Luxembourgish language
|
||||
#endif //COMMUNITY_LANG_GROUP 1
|
||||
|
||||
#if (COMMUNITY_LANG_GROUP == 2)
|
||||
#define COMMUNITY_LANG_GROUP2_LT // Community Lithuanian language
|
||||
//#define COMMUNITY_LANG_GROUP1_LT // Community Lithuanian language
|
||||
//#define COMMUNITY_LANG_GROUP1_QR // Community new language //..use this as a template and replace 'QR'
|
||||
#endif //COMMUNITY_LANG_GROUP 2
|
||||
#endif
|
||||
|
||||
#if (COMMUNITY_LANG_GROUP >=1 )
|
||||
#define COMMUNITY_LANGUAGE_SUPPORT
|
||||
|
|
@ -117,11 +107,4 @@
|
|||
#define EMERGENCY_HANDLERS
|
||||
#endif
|
||||
|
||||
//FARM_MODE
|
||||
#if ( LANG_MODE == 0 ) && defined(XFLASH) //Save resources on EINSY and disable FARM_MODE on multi-language version
|
||||
#define PRUSA_FARM
|
||||
#endif //PRUSA_FARM only in english on EINSYs
|
||||
#ifndef XFLASH //enable FARM_MODE on miniRAMBo boards
|
||||
#define PRUSA_FARM
|
||||
#endif
|
||||
#endif //_CONFIG_H
|
||||
|
|
|
|||
|
|
@ -0,0 +1,292 @@
|
|||
//conv2str.cpp - Float conversion utilities
|
||||
|
||||
#include "conv2str.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
|
||||
// convert float to string with +123.4 format
|
||||
char conv[8];
|
||||
|
||||
char *ftostr3(const float &x)
|
||||
{
|
||||
return itostr3((int)x);
|
||||
}
|
||||
|
||||
char *itostr2(const uint8_t &x)
|
||||
{
|
||||
//sprintf(conv,"%5.1f",x);
|
||||
int xx = x;
|
||||
conv[0] = (xx / 10) % 10 + '0';
|
||||
conv[1] = (xx) % 10 + '0';
|
||||
conv[2] = 0;
|
||||
return conv;
|
||||
}
|
||||
|
||||
// Convert float to string with 123.4 format, dropping sign
|
||||
char *ftostr31(const float &x)
|
||||
{
|
||||
int xx = x * 10;
|
||||
conv[0] = (xx >= 0) ? '+' : '-';
|
||||
xx = abs(xx);
|
||||
conv[1] = (xx / 1000) % 10 + '0';
|
||||
conv[2] = (xx / 100) % 10 + '0';
|
||||
conv[3] = (xx / 10) % 10 + '0';
|
||||
conv[4] = '.';
|
||||
conv[5] = (xx) % 10 + '0';
|
||||
conv[6] = 0;
|
||||
return conv;
|
||||
}
|
||||
|
||||
// Convert float to string with 123.4 format
|
||||
char *ftostr31ns(const float &x)
|
||||
{
|
||||
int xx = x * 10;
|
||||
//conv[0]=(xx>=0)?'+':'-';
|
||||
xx = abs(xx);
|
||||
conv[0] = (xx / 1000) % 10 + '0';
|
||||
conv[1] = (xx / 100) % 10 + '0';
|
||||
conv[2] = (xx / 10) % 10 + '0';
|
||||
conv[3] = '.';
|
||||
conv[4] = (xx) % 10 + '0';
|
||||
conv[5] = 0;
|
||||
return conv;
|
||||
}
|
||||
|
||||
char *ftostr32(const float &x)
|
||||
{
|
||||
long xx = x * 100;
|
||||
if (xx >= 0)
|
||||
conv[0] = (xx / 10000) % 10 + '0';
|
||||
else
|
||||
conv[0] = '-';
|
||||
xx = abs(xx);
|
||||
conv[1] = (xx / 1000) % 10 + '0';
|
||||
conv[2] = (xx / 100) % 10 + '0';
|
||||
conv[3] = '.';
|
||||
conv[4] = (xx / 10) % 10 + '0';
|
||||
conv[5] = (xx) % 10 + '0';
|
||||
conv[6] = 0;
|
||||
return conv;
|
||||
}
|
||||
|
||||
//// Convert float to rj string with 123.45 format
|
||||
char *ftostr32ns(const float &x) {
|
||||
long xx = abs(x);
|
||||
conv[0] = xx >= 10000 ? (xx / 10000) % 10 + '0' : ' ';
|
||||
conv[1] = xx >= 1000 ? (xx / 1000) % 10 + '0' : ' ';
|
||||
conv[2] = xx >= 100 ? (xx / 100) % 10 + '0' : '0';
|
||||
conv[3] = '.';
|
||||
conv[4] = (xx / 10) % 10 + '0';
|
||||
conv[5] = xx % 10 + '0';
|
||||
return conv;
|
||||
}
|
||||
|
||||
|
||||
// Convert float to string with 1.234 format
|
||||
char *ftostr43(const float &x, uint8_t offset)
|
||||
{
|
||||
const size_t maxOffset = sizeof(conv)/sizeof(conv[0]) - 6;
|
||||
if (offset>maxOffset) offset = maxOffset;
|
||||
long xx = x * 1000;
|
||||
if (xx >= 0)
|
||||
conv[offset] = (xx / 1000) % 10 + '0';
|
||||
else
|
||||
conv[offset] = '-';
|
||||
xx = abs(xx);
|
||||
conv[offset + 1] = '.';
|
||||
conv[offset + 2] = (xx / 100) % 10 + '0';
|
||||
conv[offset + 3] = (xx / 10) % 10 + '0';
|
||||
conv[offset + 4] = (xx) % 10 + '0';
|
||||
conv[offset + 5] = 0;
|
||||
return conv;
|
||||
}
|
||||
|
||||
//Float to string with 1.23 format
|
||||
char *ftostr12ns(const float &x)
|
||||
{
|
||||
long xx = x * 100;
|
||||
|
||||
xx = abs(xx);
|
||||
conv[0] = (xx / 100) % 10 + '0';
|
||||
conv[1] = '.';
|
||||
conv[2] = (xx / 10) % 10 + '0';
|
||||
conv[3] = (xx) % 10 + '0';
|
||||
conv[4] = 0;
|
||||
return conv;
|
||||
}
|
||||
|
||||
//Float to string with 1.234 format
|
||||
char *ftostr13ns(const float &x)
|
||||
{
|
||||
long xx = x * 1000;
|
||||
if (xx >= 0)
|
||||
conv[0] = ' ';
|
||||
else
|
||||
conv[0] = '-';
|
||||
xx = abs(xx);
|
||||
conv[1] = (xx / 1000) % 10 + '0';
|
||||
conv[2] = '.';
|
||||
conv[3] = (xx / 100) % 10 + '0';
|
||||
conv[4] = (xx / 10) % 10 + '0';
|
||||
conv[5] = (xx) % 10 + '0';
|
||||
conv[6] = 0;
|
||||
return conv;
|
||||
}
|
||||
|
||||
// convert float to space-padded string with -_23.4_ format
|
||||
char *ftostr32sp(const float &x) {
|
||||
long xx = abs(x * 100);
|
||||
uint8_t dig;
|
||||
|
||||
if (x < 0) { // negative val = -_0
|
||||
conv[0] = '-';
|
||||
dig = (xx / 1000) % 10;
|
||||
conv[1] = dig ? '0' + dig : ' ';
|
||||
}
|
||||
else { // positive val = __0
|
||||
dig = (xx / 10000) % 10;
|
||||
if (dig) {
|
||||
conv[0] = '0' + dig;
|
||||
conv[1] = '0' + (xx / 1000) % 10;
|
||||
}
|
||||
else {
|
||||
conv[0] = ' ';
|
||||
dig = (xx / 1000) % 10;
|
||||
conv[1] = dig ? '0' + dig : ' ';
|
||||
}
|
||||
}
|
||||
|
||||
conv[2] = '0' + (xx / 100) % 10; // lsd always
|
||||
|
||||
dig = xx % 10;
|
||||
if (dig) { // 2 decimal places
|
||||
conv[5] = '0' + dig;
|
||||
conv[4] = '0' + (xx / 10) % 10;
|
||||
conv[3] = '.';
|
||||
}
|
||||
else { // 1 or 0 decimal place
|
||||
dig = (xx / 10) % 10;
|
||||
if (dig) {
|
||||
conv[4] = '0' + dig;
|
||||
conv[3] = '.';
|
||||
}
|
||||
else {
|
||||
conv[3] = conv[4] = ' ';
|
||||
}
|
||||
conv[5] = ' ';
|
||||
}
|
||||
conv[6] = '\0';
|
||||
return conv;
|
||||
}
|
||||
|
||||
char *itostr31(const int &xx)
|
||||
{
|
||||
conv[0] = (xx >= 0) ? '+' : '-';
|
||||
conv[1] = (xx / 1000) % 10 + '0';
|
||||
conv[2] = (xx / 100) % 10 + '0';
|
||||
conv[3] = (xx / 10) % 10 + '0';
|
||||
conv[4] = '.';
|
||||
conv[5] = (xx) % 10 + '0';
|
||||
conv[6] = 0;
|
||||
return conv;
|
||||
}
|
||||
|
||||
// Convert int to rj string with 123 or -12 format
|
||||
char *itostr3(const int &x)
|
||||
{
|
||||
int xx = x;
|
||||
if (xx < 0) {
|
||||
conv[0] = '-';
|
||||
xx = -xx;
|
||||
} else if (xx >= 100)
|
||||
conv[0] = (xx / 100) % 10 + '0';
|
||||
else
|
||||
conv[0] = ' ';
|
||||
if (xx >= 10)
|
||||
conv[1] = (xx / 10) % 10 + '0';
|
||||
else
|
||||
conv[1] = ' ';
|
||||
conv[2] = (xx) % 10 + '0';
|
||||
conv[3] = 0;
|
||||
return conv;
|
||||
}
|
||||
|
||||
// Convert int to lj string with 123 format
|
||||
char *itostr3left(const int &xx)
|
||||
{
|
||||
if (xx >= 100)
|
||||
{
|
||||
conv[0] = (xx / 100) % 10 + '0';
|
||||
conv[1] = (xx / 10) % 10 + '0';
|
||||
conv[2] = (xx) % 10 + '0';
|
||||
conv[3] = 0;
|
||||
}
|
||||
else if (xx >= 10)
|
||||
{
|
||||
conv[0] = (xx / 10) % 10 + '0';
|
||||
conv[1] = (xx) % 10 + '0';
|
||||
conv[2] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
conv[0] = (xx) % 10 + '0';
|
||||
conv[1] = 0;
|
||||
}
|
||||
return conv;
|
||||
}
|
||||
|
||||
// Convert int to rj string with 1234 format
|
||||
char *itostr4(const int &xx) {
|
||||
conv[0] = xx >= 1000 ? (xx / 1000) % 10 + '0' : ' ';
|
||||
conv[1] = xx >= 100 ? (xx / 100) % 10 + '0' : ' ';
|
||||
conv[2] = xx >= 10 ? (xx / 10) % 10 + '0' : ' ';
|
||||
conv[3] = xx % 10 + '0';
|
||||
conv[4] = 0;
|
||||
return conv;
|
||||
}
|
||||
|
||||
// Convert float to rj string with 12345 format
|
||||
char *ftostr5(const float &x) {
|
||||
long xx = abs(x);
|
||||
conv[0] = xx >= 10000 ? (xx / 10000) % 10 + '0' : ' ';
|
||||
conv[1] = xx >= 1000 ? (xx / 1000) % 10 + '0' : ' ';
|
||||
conv[2] = xx >= 100 ? (xx / 100) % 10 + '0' : ' ';
|
||||
conv[3] = xx >= 10 ? (xx / 10) % 10 + '0' : ' ';
|
||||
conv[4] = xx % 10 + '0';
|
||||
conv[5] = 0;
|
||||
return conv;
|
||||
}
|
||||
|
||||
// Convert float to string with +1234.5 format
|
||||
char *ftostr51(const float &x)
|
||||
{
|
||||
long xx = x * 10;
|
||||
conv[0] = (xx >= 0) ? '+' : '-';
|
||||
xx = abs(xx);
|
||||
conv[1] = (xx / 10000) % 10 + '0';
|
||||
conv[2] = (xx / 1000) % 10 + '0';
|
||||
conv[3] = (xx / 100) % 10 + '0';
|
||||
conv[4] = (xx / 10) % 10 + '0';
|
||||
conv[5] = '.';
|
||||
conv[6] = (xx) % 10 + '0';
|
||||
conv[7] = 0;
|
||||
return conv;
|
||||
}
|
||||
|
||||
// Convert float to string with +123.45 format
|
||||
char *ftostr52(const float &x)
|
||||
{
|
||||
long xx = x * 100;
|
||||
conv[0] = (xx >= 0) ? '+' : '-';
|
||||
xx = abs(xx);
|
||||
conv[1] = (xx / 10000) % 10 + '0';
|
||||
conv[2] = (xx / 1000) % 10 + '0';
|
||||
conv[3] = (xx / 100) % 10 + '0';
|
||||
conv[4] = '.';
|
||||
conv[5] = (xx / 10) % 10 + '0';
|
||||
conv[6] = (xx) % 10 + '0';
|
||||
conv[7] = 0;
|
||||
return conv;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
//conv2str.h - Float conversion utilities
|
||||
#ifndef _CONV2STR_H
|
||||
#define _CONV2STR_H
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
|
||||
char *itostr2(const uint8_t &x);
|
||||
char *itostr31(const int &xx);
|
||||
char *itostr3(const int &xx);
|
||||
char *itostr3left(const int &xx);
|
||||
char *itostr4(const int &xx);
|
||||
|
||||
char *ftostr3(const float &x);
|
||||
char *ftostr31ns(const float &x); // float to string without sign character
|
||||
char *ftostr31(const float &x);
|
||||
char *ftostr32(const float &x);
|
||||
char *ftostr32ns(const float &x);
|
||||
char *ftostr43(const float &x, uint8_t offset = 0);
|
||||
char *ftostr12ns(const float &x);
|
||||
char *ftostr13ns(const float &x);
|
||||
char *ftostr32sp(const float &x); // remove zero-padding from ftostr32
|
||||
char *ftostr5(const float &x);
|
||||
char *ftostr51(const float &x);
|
||||
char *ftostr52(const float &x);
|
||||
|
||||
|
||||
#endif //_CONV2STR_H
|
||||
|
|
@ -8,69 +8,98 @@
|
|||
#include <avr/eeprom.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
#include "language.h"
|
||||
|
||||
#if 0
|
||||
template <typename T>
|
||||
static T eeprom_read(T *address);
|
||||
|
||||
template<>
|
||||
char eeprom_read<char>(char *address)
|
||||
{
|
||||
return eeprom_read_byte(reinterpret_cast<uint8_t*>(address));
|
||||
}
|
||||
#endif
|
||||
|
||||
template <typename T>
|
||||
static void eeprom_write(T *address, T value);
|
||||
|
||||
template<>
|
||||
void eeprom_write<char>(char *addres, char value)
|
||||
{
|
||||
eeprom_write_byte(reinterpret_cast<uint8_t*>(addres), static_cast<uint8_t>(value));
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
static bool eeprom_is_uninitialized(T *address);
|
||||
|
||||
template <>
|
||||
bool eeprom_is_uninitialized<char>(char *address)
|
||||
{
|
||||
return (0xff == eeprom_read_byte(reinterpret_cast<uint8_t*>(address)));
|
||||
}
|
||||
|
||||
bool eeprom_is_sheet_initialized(uint8_t sheet_num)
|
||||
{
|
||||
return (0xffff != eeprom_read_word(reinterpret_cast<uint16_t*>(&(EEPROM_Sheets_base->
|
||||
s[sheet_num].z_offset))));
|
||||
}
|
||||
|
||||
void eeprom_init()
|
||||
{
|
||||
eeprom_init_default_byte((uint8_t*)EEPROM_POWER_COUNT, 0);
|
||||
eeprom_init_default_byte((uint8_t*)EEPROM_CRASH_COUNT_X, 0);
|
||||
eeprom_init_default_byte((uint8_t*)EEPROM_CRASH_COUNT_Y, 0);
|
||||
eeprom_init_default_byte((uint8_t*)EEPROM_FERROR_COUNT, 0);
|
||||
eeprom_init_default_word((uint16_t*)EEPROM_POWER_COUNT_TOT, 0);
|
||||
eeprom_init_default_word((uint16_t*)EEPROM_CRASH_COUNT_X_TOT, 0);
|
||||
eeprom_init_default_word((uint16_t*)EEPROM_CRASH_COUNT_Y_TOT, 0);
|
||||
eeprom_init_default_word((uint16_t*)EEPROM_FERROR_COUNT_TOT, 0);
|
||||
if (eeprom_read_byte((uint8_t*)EEPROM_POWER_COUNT) == 0xff) eeprom_write_byte((uint8_t*)EEPROM_POWER_COUNT, 0);
|
||||
if (eeprom_read_byte((uint8_t*)EEPROM_CRASH_COUNT_X) == 0xff) eeprom_write_byte((uint8_t*)EEPROM_CRASH_COUNT_X, 0);
|
||||
if (eeprom_read_byte((uint8_t*)EEPROM_CRASH_COUNT_Y) == 0xff) eeprom_write_byte((uint8_t*)EEPROM_CRASH_COUNT_Y, 0);
|
||||
if (eeprom_read_byte((uint8_t*)EEPROM_FERROR_COUNT) == 0xff) eeprom_write_byte((uint8_t*)EEPROM_FERROR_COUNT, 0);
|
||||
if (eeprom_read_word((uint16_t*)EEPROM_POWER_COUNT_TOT) == 0xffff) eeprom_write_word((uint16_t*)EEPROM_POWER_COUNT_TOT, 0);
|
||||
if (eeprom_read_word((uint16_t*)EEPROM_CRASH_COUNT_X_TOT) == 0xffff) eeprom_write_word((uint16_t*)EEPROM_CRASH_COUNT_X_TOT, 0);
|
||||
if (eeprom_read_word((uint16_t*)EEPROM_CRASH_COUNT_Y_TOT) == 0xffff) eeprom_write_word((uint16_t*)EEPROM_CRASH_COUNT_Y_TOT, 0);
|
||||
if (eeprom_read_word((uint16_t*)EEPROM_FERROR_COUNT_TOT) == 0xffff) eeprom_write_word((uint16_t*)EEPROM_FERROR_COUNT_TOT, 0);
|
||||
|
||||
eeprom_init_default_word((uint16_t*)EEPROM_MMU_FAIL_TOT, 0);
|
||||
eeprom_init_default_word((uint16_t*)EEPROM_MMU_LOAD_FAIL_TOT, 0);
|
||||
eeprom_init_default_byte((uint8_t*)EEPROM_MMU_FAIL, 0);
|
||||
eeprom_init_default_byte((uint8_t*)EEPROM_MMU_LOAD_FAIL, 0);
|
||||
eeprom_init_default_dword((uint32_t*)EEPROM_MMU_MATERIAL_CHANGES, 0);
|
||||
if (eeprom_read_word((uint16_t*)EEPROM_MMU_FAIL_TOT) == 0xffff) eeprom_update_word((uint16_t *)EEPROM_MMU_FAIL_TOT, 0);
|
||||
if (eeprom_read_word((uint16_t*)EEPROM_MMU_LOAD_FAIL_TOT) == 0xffff) eeprom_update_word((uint16_t *)EEPROM_MMU_LOAD_FAIL_TOT, 0);
|
||||
if (eeprom_read_byte((uint8_t*)EEPROM_MMU_FAIL) == 0xff) eeprom_update_byte((uint8_t *)EEPROM_MMU_FAIL, 0);
|
||||
if (eeprom_read_byte((uint8_t*)EEPROM_MMU_LOAD_FAIL) == 0xff) eeprom_update_byte((uint8_t *)EEPROM_MMU_LOAD_FAIL, 0);
|
||||
if (eeprom_read_byte(&(EEPROM_Sheets_base->active_sheet)) == EEPROM_EMPTY_VALUE)
|
||||
{
|
||||
eeprom_update_byte_notify(&(EEPROM_Sheets_base->active_sheet), 0);
|
||||
eeprom_update_byte(&(EEPROM_Sheets_base->active_sheet), 0);
|
||||
// When upgrading from version older version (before multiple sheets were implemented in v3.8.0)
|
||||
// Sheet 1 uses the previous Live adjust Z (@EEPROM_BABYSTEP_Z)
|
||||
int last_babystep = eeprom_read_word((uint16_t *)EEPROM_BABYSTEP_Z);
|
||||
eeprom_update_word(reinterpret_cast<uint16_t *>(&(EEPROM_Sheets_base->s[0].z_offset)), last_babystep);
|
||||
}
|
||||
|
||||
for (uint_least8_t i = 0; i < (sizeof(Sheets::s)/sizeof(Sheets::s[0])); ++i)
|
||||
{
|
||||
bool is_uninitialized = true;
|
||||
for (uint_least8_t j = 0; j < (sizeof(Sheet::name)/sizeof(Sheet::name[0])); ++j)
|
||||
{
|
||||
if (!eeprom_is_uninitialized(&(EEPROM_Sheets_base->s[i].name[j]))) is_uninitialized = false;
|
||||
}
|
||||
if(is_uninitialized)
|
||||
{
|
||||
SheetName sheetName;
|
||||
eeprom_default_sheet_name(i,sheetName);
|
||||
|
||||
// initialize the sheet names in eeprom
|
||||
for (uint_least8_t i = 0; i < (sizeof(Sheets::s)/sizeof(Sheets::s[0])); i++) {
|
||||
SheetName sheetName;
|
||||
eeprom_default_sheet_name(i, sheetName);
|
||||
eeprom_init_default_block(EEPROM_Sheets_base->s[i].name, (sizeof(Sheet::name)/sizeof(Sheet::name[0])), sheetName.c);
|
||||
for (uint_least8_t a = 0; a < sizeof(Sheet::name); ++a){
|
||||
eeprom_write(&(EEPROM_Sheets_base->s[i].name[a]), sheetName.c[a]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(!eeprom_is_sheet_initialized(eeprom_read_byte(&(EEPROM_Sheets_base->active_sheet))))
|
||||
{
|
||||
eeprom_switch_to_next_sheet();
|
||||
}
|
||||
check_babystep();
|
||||
|
||||
// initialize custom mendel name in eeprom
|
||||
if (eeprom_read_byte((uint8_t*)EEPROM_CUSTOM_MENDEL_NAME) == EEPROM_EMPTY_VALUE) {
|
||||
//SERIAL_ECHOLN("Init Custom Mendel Name");
|
||||
eeprom_update_block_notify(CUSTOM_MENDEL_NAME, (uint8_t*)EEPROM_CUSTOM_MENDEL_NAME, sizeof(CUSTOM_MENDEL_NAME));
|
||||
} //else SERIAL_ECHOLN("Found Custom Mendel Name");
|
||||
|
||||
#ifdef PINDA_TEMP_COMP
|
||||
eeprom_init_default_byte((uint8_t*)EEPROM_PINDA_TEMP_COMPENSATION, 0);
|
||||
if (eeprom_read_byte((uint8_t*)EEPROM_PINDA_TEMP_COMPENSATION) == 0xff) eeprom_update_byte((uint8_t *)EEPROM_PINDA_TEMP_COMPENSATION, 0);
|
||||
#endif //PINDA_TEMP_COMP
|
||||
|
||||
eeprom_init_default_dword((uint32_t*)EEPROM_JOB_ID, 0);
|
||||
eeprom_init_default_dword((uint32_t*)EEPROM_TOTALTIME, 0);
|
||||
eeprom_init_default_dword((uint32_t*)EEPROM_FILAMENTUSED, 0);
|
||||
eeprom_init_default_byte((uint8_t*)EEPROM_MMU_CUTTER_ENABLED, 0);
|
||||
|
||||
eeprom_init_default_byte((uint8_t*)EEPROM_HEAT_BED_ON_LOAD_FILAMENT, 1);
|
||||
|
||||
}
|
||||
|
||||
void eeprom_adjust_bed_reset() {
|
||||
eeprom_update_byte_notify((uint8_t*)EEPROM_BED_CORRECTION_VALID, 1);
|
||||
eeprom_update_byte_notify((uint8_t*)EEPROM_BED_CORRECTION_LEFT, 0);
|
||||
eeprom_update_byte_notify((uint8_t*)EEPROM_BED_CORRECTION_RIGHT, 0);
|
||||
eeprom_update_byte_notify((uint8_t*)EEPROM_BED_CORRECTION_FRONT, 0);
|
||||
eeprom_update_byte_notify((uint8_t*)EEPROM_BED_CORRECTION_REAR, 0);
|
||||
if (eeprom_read_dword((uint32_t*)EEPROM_JOB_ID) == EEPROM_EMPTY_VALUE32)
|
||||
eeprom_update_dword((uint32_t*)EEPROM_JOB_ID, 0);
|
||||
}
|
||||
|
||||
//! @brief Get default sheet name for index
|
||||
|
|
@ -81,8 +110,8 @@ void eeprom_adjust_bed_reset() {
|
|||
//! | 1 | Smooth2 |
|
||||
//! | 2 | Textur1 |
|
||||
//! | 3 | Textur2 |
|
||||
//! | 4 | Satin |
|
||||
//! | 5 | NylonPA |
|
||||
//! | 4 | Satin 1 |
|
||||
//! | 5 | Satin 2 |
|
||||
//! | 6 | Custom1 |
|
||||
//! | 7 | Custom2 |
|
||||
//!
|
||||
|
|
@ -100,23 +129,17 @@ void eeprom_default_sheet_name(uint8_t index, SheetName &sheetName)
|
|||
{
|
||||
strcpy_P(sheetName.c, PSTR("Textur"));
|
||||
}
|
||||
else if (index < 5)
|
||||
{
|
||||
strcpy_P(sheetName.c, PSTR("Satin "));
|
||||
}
|
||||
else if (index < 6)
|
||||
{
|
||||
strcpy_P(sheetName.c, PSTR("NylonPA"));
|
||||
strcpy_P(sheetName.c, PSTR("Satin "));
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy_P(sheetName.c, PSTR("Custom"));
|
||||
}
|
||||
if (index <4 || index >5)
|
||||
{
|
||||
sheetName.c[6] = '0' + ((index % 2)+1);
|
||||
sheetName.c[7] = '\0';
|
||||
}
|
||||
|
||||
sheetName.c[6] = '0' + ((index % 2)+1);
|
||||
sheetName.c[7] = '\0';
|
||||
}
|
||||
|
||||
//! @brief Get next initialized sheet
|
||||
|
|
@ -137,267 +160,10 @@ int8_t eeprom_next_initialized_sheet(int8_t sheet)
|
|||
return -1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_EEPROM_CHANGES
|
||||
static void eeprom_byte_notify(uint8_t *dst, uint8_t previous_value, uint8_t value, bool write) {
|
||||
printf_P(PSTR("EEPROMChng b %s %u %d -> %d\n"), write ? "write":"", dst , previous_value, value);
|
||||
}
|
||||
|
||||
static void eeprom_word_notify(uint16_t *dst, uint16_t previous_value, uint16_t value, bool write) {
|
||||
printf_P(PSTR("EEPROMChng w %s %u %u -> %u\n"), write ? "write":"", dst , previous_value, value);
|
||||
}
|
||||
|
||||
static void eeprom_dword_notify(uint32_t *dst, uint32_t previous_value, uint32_t value, bool write) {
|
||||
printf_P(PSTR("EEPROMChng d %s %u %x -> %x\n"), write ? "write":"", reinterpret_cast<const uint16_t>(dst) , previous_value, value);
|
||||
}
|
||||
|
||||
static void eeprom_float_notify(float *dst, float previous_value, float value, bool write) {
|
||||
printf_P(PSTR("EEPROMChng f %s %u %f -> %f\n"), write ? "write":"", reinterpret_cast<const uint16_t>(dst) , previous_value, value);
|
||||
}
|
||||
|
||||
static void eeprom_block_notify(void *dst, const uint8_t *previous_values, const uint8_t *values, size_t size, bool write) {
|
||||
for(size_t i = 0; i < size; ++i){
|
||||
if (previous_values[i] != values[i] || write) {
|
||||
printf_P(PSTR("EEPROMChng bl %s %u %x -> %x\n"), write ? "write":"", reinterpret_cast<const uint16_t>(dst) + i, previous_values[i], values[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif //DEBUG_EEPROM_CHANGES
|
||||
|
||||
#ifndef DEBUG_EEPROM_CHANGES
|
||||
void eeprom_write_byte_notify(uint8_t *dst, uint8_t value){
|
||||
#else
|
||||
void eeprom_write_byte_notify(uint8_t *dst, uint8_t value, bool active){
|
||||
if (active) {
|
||||
uint8_t previous_value = eeprom_read_byte(dst);
|
||||
eeprom_byte_notify(dst, previous_value, value, true);
|
||||
}
|
||||
#endif //DEBUG_EEPROM_CHANGES
|
||||
eeprom_write_byte(dst, value);
|
||||
}
|
||||
|
||||
#ifndef DEBUG_EEPROM_CHANGES
|
||||
void eeprom_update_byte_notify(uint8_t *dst, uint8_t value){
|
||||
#else
|
||||
void eeprom_update_byte_notify(uint8_t *dst, uint8_t value, bool active){
|
||||
|
||||
if (active) {
|
||||
uint8_t previous_value = eeprom_read_byte(dst);
|
||||
if (previous_value != value) {
|
||||
eeprom_byte_notify(dst, previous_value, value, false);
|
||||
}
|
||||
}
|
||||
#endif //DEBUG_EEPROM_CHANGES
|
||||
eeprom_update_byte(dst, value);
|
||||
}
|
||||
|
||||
#ifndef DEBUG_EEPROM_CHANGES
|
||||
void eeprom_write_word_notify(uint16_t *dst, uint16_t value){
|
||||
#else
|
||||
void eeprom_write_word_notify(uint16_t *dst, uint16_t value, bool active){
|
||||
if (active) {
|
||||
uint16_t previous_value = eeprom_read_word(dst);
|
||||
eeprom_word_notify(dst, previous_value, value, true);
|
||||
}
|
||||
#endif //DEBUG_EEPROM_CHANGES
|
||||
eeprom_write_word(dst, value);
|
||||
}
|
||||
|
||||
#ifndef DEBUG_EEPROM_CHANGES
|
||||
void eeprom_update_word_notify(uint16_t *dst, uint16_t value){
|
||||
#else
|
||||
void eeprom_update_word_notify(uint16_t *dst, uint16_t value, bool active){
|
||||
if (active) {
|
||||
uint16_t previous_value = eeprom_read_word(dst);
|
||||
if (previous_value != value) {
|
||||
eeprom_word_notify(dst, previous_value, value, false);
|
||||
}
|
||||
}
|
||||
#endif //DEBUG_EEPROM_CHANGES
|
||||
eeprom_update_word(dst, value);
|
||||
}
|
||||
|
||||
#ifndef DEBUG_EEPROM_CHANGES
|
||||
void eeprom_write_dword_notify(uint32_t *dst, uint32_t value){
|
||||
#else
|
||||
void eeprom_write_dword_notify(uint32_t *dst, uint32_t value, bool active){
|
||||
if (active) {
|
||||
uint32_t previous_value = eeprom_read_dword(dst);
|
||||
eeprom_dword_notify(dst, previous_value, value, true);
|
||||
}
|
||||
#endif //DEBUG_EEPROM_CHANGES
|
||||
eeprom_write_dword(dst, value);
|
||||
}
|
||||
|
||||
#ifndef DEBUG_EEPROM_CHANGES
|
||||
void eeprom_update_dword_notify(uint32_t *dst, uint32_t value){
|
||||
#else
|
||||
void eeprom_update_dword_notify(uint32_t *dst, uint32_t value, bool active){
|
||||
if (active) {
|
||||
uint32_t previous_value = eeprom_read_dword(dst);
|
||||
if (previous_value != value) {
|
||||
eeprom_dword_notify(dst, previous_value, value, false);
|
||||
}
|
||||
}
|
||||
#endif //DEBUG_EEPROM_CHANGES
|
||||
eeprom_update_dword(dst, value);
|
||||
}
|
||||
|
||||
#ifndef DEBUG_EEPROM_CHANGES
|
||||
void eeprom_write_float_notify(float *dst, float value){
|
||||
#else
|
||||
void eeprom_write_float_notify(float *dst, float value, bool active){
|
||||
if (active) {
|
||||
float previous_value = eeprom_read_float(dst);
|
||||
eeprom_float_notify(dst, previous_value, value, true);
|
||||
}
|
||||
#endif //DEBUG_EEPROM_CHANGES
|
||||
eeprom_write_float(dst, value);
|
||||
}
|
||||
|
||||
#ifndef DEBUG_EEPROM_CHANGES
|
||||
void eeprom_update_float_notify(float *dst, float value){
|
||||
#else
|
||||
void eeprom_update_float_notify(float *dst, float value, bool active){
|
||||
if (active) {
|
||||
float previous_value = eeprom_read_float(dst);
|
||||
if (previous_value != value) {
|
||||
eeprom_float_notify(dst, previous_value, value, false);
|
||||
}
|
||||
}
|
||||
#endif //DEBUG_EEPROM_CHANGES
|
||||
eeprom_update_float(dst, value);
|
||||
}
|
||||
|
||||
#ifndef DEBUG_EEPROM_CHANGES
|
||||
void eeprom_write_block_notify(const void *__src, void *__dst, size_t __n){
|
||||
eeprom_write_block(__src, __dst, __n);
|
||||
#else
|
||||
void eeprom_write_block_notify(const void *__src, void *__dst, size_t __n, bool active){
|
||||
if (active) {
|
||||
uint8_t previous_values[__n];
|
||||
uint8_t new_values[__n];
|
||||
eeprom_read_block(previous_values, __dst, __n);
|
||||
eeprom_write_block(__src, __dst, __n);
|
||||
eeprom_read_block(new_values, __dst, __n);
|
||||
eeprom_block_notify(__dst, previous_values, new_values, __n, true);
|
||||
}
|
||||
#endif //DEBUG_EEPROM_CHANGES
|
||||
}
|
||||
|
||||
#ifndef DEBUG_EEPROM_CHANGES
|
||||
void eeprom_update_block_notify(const void *__src, void *__dst, size_t __n){
|
||||
eeprom_update_block(__src, __dst, __n);
|
||||
#else
|
||||
void eeprom_update_block_notify(const void *__src, void *__dst, size_t __n, bool active){
|
||||
if (active) {
|
||||
uint8_t previous_values[__n];
|
||||
uint8_t new_values[__n];
|
||||
eeprom_read_block(previous_values, __dst, __n);
|
||||
eeprom_update_block(__src, __dst, __n);
|
||||
eeprom_read_block(new_values, __dst, __n);
|
||||
eeprom_block_notify(__dst, previous_values, new_values, __n, false);
|
||||
}
|
||||
#endif //DEBUG_EEPROM_CHANGES
|
||||
}
|
||||
|
||||
void eeprom_switch_to_next_sheet()
|
||||
{
|
||||
int8_t sheet = eeprom_read_byte(&(EEPROM_Sheets_base->active_sheet));
|
||||
|
||||
sheet = eeprom_next_initialized_sheet(sheet);
|
||||
if (sheet >= 0) eeprom_update_byte_notify(&(EEPROM_Sheets_base->active_sheet), sheet);
|
||||
}
|
||||
|
||||
bool __attribute__((noinline)) eeprom_is_sheet_initialized(uint8_t sheet_num) {
|
||||
return (eeprom_read_word(reinterpret_cast<uint16_t*>(&(EEPROM_Sheets_base->s[sheet_num].z_offset))) != EEPROM_EMPTY_VALUE16);
|
||||
}
|
||||
|
||||
|
||||
bool __attribute__((noinline)) eeprom_is_initialized_block(const void *__p, size_t __n) {
|
||||
const uint8_t *p = (const uint8_t*)__p;
|
||||
while (__n--) {
|
||||
if (eeprom_read_byte(p++) != EEPROM_EMPTY_VALUE)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void eeprom_update_block_P(const void *__src, void *__dst, size_t __n) {
|
||||
const uint8_t *src = (const uint8_t*)__src;
|
||||
uint8_t *dst = (uint8_t*)__dst;
|
||||
while (__n--) {
|
||||
eeprom_update_byte_notify(dst++, pgm_read_byte(src++));
|
||||
}
|
||||
}
|
||||
|
||||
void eeprom_toggle(uint8_t *__p) {
|
||||
eeprom_write_byte_notify(__p, !eeprom_read_byte(__p));
|
||||
}
|
||||
|
||||
void __attribute__((noinline)) eeprom_increment_byte(uint8_t *__p) {
|
||||
eeprom_write_byte_notify(__p, eeprom_read_byte(__p) + 1);
|
||||
}
|
||||
|
||||
void __attribute__((noinline)) eeprom_increment_word(uint16_t *__p) {
|
||||
eeprom_write_word_notify(__p, eeprom_read_word(__p) + 1);
|
||||
}
|
||||
|
||||
void __attribute__((noinline)) eeprom_increment_dword(uint32_t *__p) {
|
||||
eeprom_write_dword_notify(__p, eeprom_read_dword(__p) + 1);
|
||||
}
|
||||
|
||||
|
||||
void __attribute__((noinline)) eeprom_add_byte(uint8_t *__p, uint8_t add) {
|
||||
eeprom_write_byte_notify(__p, eeprom_read_byte(__p) + add);
|
||||
}
|
||||
|
||||
void __attribute__((noinline)) eeprom_add_word(uint16_t *__p, uint16_t add) {
|
||||
eeprom_write_word_notify(__p, eeprom_read_word(__p) + add);
|
||||
}
|
||||
|
||||
void __attribute__((noinline)) eeprom_add_dword(uint32_t *__p, uint32_t add) {
|
||||
eeprom_write_dword_notify(__p, eeprom_read_dword(__p) + add);
|
||||
}
|
||||
|
||||
|
||||
uint8_t __attribute__((noinline)) eeprom_init_default_byte(uint8_t *__p, uint8_t def) {
|
||||
uint8_t val = eeprom_read_byte(__p);
|
||||
if (val == EEPROM_EMPTY_VALUE) {
|
||||
eeprom_write_byte_notify(__p, def);
|
||||
return def;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
uint16_t __attribute__((noinline)) eeprom_init_default_word(uint16_t *__p, uint16_t def) {
|
||||
uint16_t val = eeprom_read_word(__p);
|
||||
if (val == EEPROM_EMPTY_VALUE16) {
|
||||
eeprom_write_word_notify(__p, def);
|
||||
return def;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
uint32_t __attribute__((noinline)) eeprom_init_default_dword(uint32_t *__p, uint32_t def) {
|
||||
uint32_t val = eeprom_read_dword(__p);
|
||||
if (val == EEPROM_EMPTY_VALUE32) {
|
||||
eeprom_write_dword_notify(__p, def);
|
||||
return def;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
void __attribute__((noinline)) eeprom_init_default_float(float *__p, float def) {
|
||||
if (eeprom_read_dword((uint32_t*)__p) == EEPROM_EMPTY_VALUE32)
|
||||
eeprom_write_float_notify(__p, def);
|
||||
}
|
||||
|
||||
void __attribute__((noinline)) eeprom_init_default_block(void *__p, size_t __n, const void *def) {
|
||||
if (!eeprom_is_initialized_block(__p, __n))
|
||||
eeprom_update_block_notify(def, __p, __n);
|
||||
}
|
||||
|
||||
void __attribute__((noinline)) eeprom_init_default_block_P(void *__p, size_t __n, const void *def) {
|
||||
if (!eeprom_is_initialized_block(__p, __n))
|
||||
eeprom_update_block_P(def, __p, __n);
|
||||
if (sheet >= 0) eeprom_update_byte(&(EEPROM_Sheets_base->active_sheet), sheet);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
* @author 3d-gussner
|
||||
*/
|
||||
/** \ingroup eeprom_table */
|
||||
|
||||
|
||||
//! _This is a EEPROM table of currently implemented in Prusa firmware (dynamically generated from doxygen)._
|
||||
|
||||
|
||||
|
|
@ -12,27 +12,16 @@
|
|||
#define EEPROM_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "Configuration_var.h"
|
||||
|
||||
// Custom Mendel Name
|
||||
#ifndef CUSTOM_MENDEL_NAME
|
||||
#define CUSTOM_MENDEL_NAME "Prusa i3"
|
||||
#endif
|
||||
|
||||
#define MAX_CUSTOM_MENDEL_NAME_LENGTH 17
|
||||
|
||||
|
||||
// Sheets
|
||||
#define MAX_SHEETS 8
|
||||
#define MAX_SHEET_NAME_LENGTH 7
|
||||
|
||||
typedef struct
|
||||
{
|
||||
unsigned char name[MAX_SHEET_NAME_LENGTH]; //!< Can be null terminated, doesn't need to be null terminated
|
||||
char name[MAX_SHEET_NAME_LENGTH]; //!< Can be null terminated, doesn't need to be null terminated
|
||||
int16_t z_offset; //!< Z_BABYSTEP_MIN .. Z_BABYSTEP_MAX = Z_BABYSTEP_MIN*2/1000 [mm] .. Z_BABYSTEP_MAX*2/1000 [mm]
|
||||
uint8_t bed_temp; //!< 0 .. 254 [°C] NOTE: currently only written-to and never used
|
||||
uint8_t pinda_temp; //!< 0 .. 254 [°C] NOTE: currently only written-to and never used
|
||||
uint8_t bed_temp; //!< 0 .. 254 [°C]
|
||||
uint8_t pinda_temp; //!< 0 .. 254 [°C]
|
||||
} Sheet;
|
||||
|
||||
typedef struct
|
||||
|
|
@ -48,29 +37,29 @@ typedef struct
|
|||
static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEPROM_SHEETS_SIZEOF.");
|
||||
#endif
|
||||
/** @defgroup eeprom_table EEPROM Table
|
||||
*
|
||||
|
||||
*
|
||||
|
||||
---------------------------------------------------------------------------------
|
||||
EEPROM 8-bit Empty value = 0xFFh 255
|
||||
|
||||
|
||||
EEPROM 16-bit Empty value = 0xFFFFh 65535
|
||||
|
||||
|
||||
_Italic = unused or default_
|
||||
|
||||
|
||||
__Bold = Status__
|
||||
|
||||
In Default/FactoryReset column the
|
||||
|
||||
- __L__ Language
|
||||
- __S__ Statistics
|
||||
- __P__ Shipping prep
|
||||
- __M__ Service/Maintenance prep
|
||||
- __S/P__ Statistics and Shipping prep
|
||||
|
||||
|
||||
In Default/FactoryReset column the
|
||||
|
||||
- __L__ Language
|
||||
- __S__ Statistics
|
||||
- __P__ Shipping prep
|
||||
- __M__ Service/Maintenance prep
|
||||
- __S/P__ Statistics and Shipping prep
|
||||
|
||||
will overwrite existing values to 0 or default.
|
||||
A FactoryReset All Data will overwrite the whole EEPROM with ffh and some values will be initialized automatically,
|
||||
others need a reset / reboot.
|
||||
|
||||
|
||||
---------------------------------------------------------------------------------
|
||||
How can you use the debug codes?
|
||||
- Serial terminal like Putty.
|
||||
|
|
@ -78,355 +67,282 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP
|
|||
- _Pronterface_ does __not__ support D-codes
|
||||
|
||||
### !!! D-codes are case sensitive so please don't use upper case A,C or X in the address you want to read !!!
|
||||
|
||||
|
||||
#### Useful tools/links:
|
||||
To convert hex to ascii https://www.rapidtables.com/convert/number/hex-to-ascii.html
|
||||
|
||||
To convert hex to dec https://www.rapidtables.com/convert/number/hex-to-decimal.html
|
||||
|
||||
Version: 3.14.1
|
||||
|
||||
To convert hex to ascii https://www.rapidtables.com/convert/number/hex-to-ascii.html
|
||||
|
||||
To convert hex to dec https://www.rapidtables.com/convert/number/hex-to-decimal.html
|
||||
|
||||
Version: 1.0.1
|
||||
|
||||
---------------------------------------------------------------------------------
|
||||
|
||||
|
||||
| Address begin | Bit/Type | Name | Valid values | Default/FactoryReset | Description | Gcode/Function| Debug code
|
||||
| :-- | :-- | :-- | :--: | :--: | :-- | :--: | :--:
|
||||
| 0x0FFFh 4095 | uchar | EEPROM_SILENT | 00h 0 | ffh 255 | TMC Stealth mode: __off__ / miniRambo Power mode | LCD menu | D3 Ax0fff C1
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | TMC Stealth mode: __on__ / miniRambo Silent mode | ^ | ^
|
||||
| ^ | ^ | ^ | 02h 2 | ^ | miniRambo Auto mode | ^ | ^
|
||||
| 0x0FFEh 4094 | uchar | EEPROM_LANG | 00h 0 | ffh 255 __L__ | English / LANG_ID_PRI | LCD menu | D3 Ax0ffe C1
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | Other language LANG_ID_SEC | ^ | ^
|
||||
| 0x0FFCh 4092 | uint16 | EEPROM_BABYSTEP_X | ??? | ff ffh 65535 | Babystep for X axis _unsued_ | ??? | D3 Ax0ffc C2
|
||||
| 0x0FFAh 4090 | uint16 | EEPROM_BABYSTEP_Y | ??? | ff ffh 65535 | Babystep for Y axis _unsued_ | ^ | D3 Ax0ffa C2
|
||||
| 0x0FF8h 4088 | uint16 | EEPROM_BABYSTEP_Z | ??? | ff ffh 65535 | Babystep for Z axis _lagacy_ | ^ | D3 Ax0ff8 C2
|
||||
| ^ | ^ | ^ | ^ | ^ | multiple values stored now in EEPROM_Sheets_base | ^ | ^
|
||||
| 0x0FF7h 4087 | uint8 | EEPROM_CALIBRATION_STATUS | ffh 255 | ffh 255 | Assembled _default_ | ??? | D3 Ax0ff7 C1
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | Calibrated | ^ | ^
|
||||
| ^ | ^ | ^ | e6h 230 | ^ | needs Live Z adjustment | ^ | ^
|
||||
| ^ | ^ | ^ | f0h 240 | ^ __P__ | needs Z calibration | ^ | ^
|
||||
| ^ | ^ | ^ | fah 250 | ^ | needs XYZ calibration | ^ | ^
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | Unknown | ^ | ^
|
||||
| 0x0FF5h 4085 | uint16 | EEPROM_BABYSTEP_Z0 | ??? | ff ffh 65535 | Babystep for Z ??? | ??? | D3 Ax0ff5 C2
|
||||
| 0x0FF1h 4081 | uint32 | EEPROM_FILAMENTUSED | ??? | 00 00 00 00h 0 __S/P__| Filament used in meters | ??? | D3 Ax0ff1 C4
|
||||
| 0x0FEDh 4077 | uint32 | EEPROM_TOTALTIME | ??? | 00 00 00 00h 0 __S/P__| Total print time | ??? | D3 Ax0fed C4
|
||||
| 0x0FE5h 4069 | float | EEPROM_BED_CALIBRATION_CENTER | ??? | ff ff ff ffh | ??? | ??? | D3 Ax0fe5 C8
|
||||
| 0x0FDDh 4061 | float | EEPROM_BED_CALIBRATION_VEC_X | ??? | ff ff ff ffh | ??? | ??? | D3 Ax0fdd C8
|
||||
| 0x0FD5h 4053 | float | EEPROM_BED_CALIBRATION_VEC_Y | ??? | ff ff ff ffh | ??? | ??? | D3 Ax0fd5 C8
|
||||
| 0x0FC5h 4037 | int16 | EEPROM_BED_CALIBRATION_Z_JITTER | ??? | ff ffh 65535 | ??? | ??? | D3 Ax0fc5 C16
|
||||
| 0x0FC4h 4036 | bool | EEPROM_FARM_MODE | 00h 0 | ffh 255 __P__ | Prusa farm mode: __off__ | G99 | D3 Ax0fc4 C1
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | Prusa farm mode: __on__ | G98 | ^
|
||||
| 0x0FC3h 4035 | free | _EEPROM_FREE_NR1_ | ??? | ffh 255 | _Free EEPROM space_ | _free space_ | D3 Ax0fc3 C1
|
||||
| 0x0FC1h 4033 | ??? | EEPROM_FARM_NUMBER | 000-999 | ff ffh / 000 __P__ | Prusa farm number _only 0-9 are allowed: 000-999_ | LCD menu | D3 Ax0fc1 C2
|
||||
| 0x0FC0h 4032 | bool | EEPROM_BED_CORRECTION_VALID | 00h 0 | 00h 0 | Bed correction invalid | ??? | D3 Ax0fc0 C1
|
||||
| ^ | ^ | ^ | ffh 255 | | Bed correction valid | ??? | ^
|
||||
| 0x0FBFh 4031 | char | EEPROM_BED_CORRECTION_LEFT | 00h ffh | 00h 0 | Bed manual correction left | LCD menu | D3 Ax0fbf C1
|
||||
| ^ | ^ | ^ | ^ | ^ | At this moment limited to +-100um | G80 Lxxx | ^
|
||||
| 0x0FBEh 4030 | char | EEPROM_BED_CORRECTION_RIGHT | 00h ffh | 00h 0 | Bed manual correction right | LCD menu | D3 Ax0fbe C1
|
||||
| ^ | ^ | ^ | ^ | ^ | At this moment limited to +-100um | G80 Rxxx | ^
|
||||
| 0x0FBDh 4029 | char | EEPROM_BED_CORRECTION_FRONT | 00h ffh | 00h 0 | Bed manual correction front | LCD menu | D3 Ax0fbd C1
|
||||
| ^ | ^ | ^ | ^ | ^ | At this moment limited to +-100um | G80 Fxxx | ^
|
||||
| 0x0FBCh 4028 | char | EEPROM_BED_CORRECTION_BACK | 00h ffh | 00h 0 | Bed manual correction back | LCD menu | D3 Ax0fbc C1
|
||||
| ^ | ^ | ^ | ^ | ^ | At this moment limited to +-100um | G80 Bxxx | ^
|
||||
| 0x0FBBh 4027 | bool | EEPROM_TOSHIBA_FLASH_AIR_COMPATIBLITY | 00h 0 | ffh 255 | Toshiba Air: __off__ | LCD menu | D3 Ax0fbb C1
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | Toshiba Air: __on__ | ^ | ^
|
||||
| 0x0FBAh 4026 | uchar | EEPROM_PRINT_FLAG | ??? | ??? | _unsued_ | ??? | D3 Ax0fba C1
|
||||
| 0x0FB0h 4016 | int16 | EEPROM_PROBE_TEMP_SHIFT | ??? | ??? | ??? | ??? | D3 Ax0fb0 C10
|
||||
| 0x0FAFh 4015 | bool | EEPROM_TEMP_CAL_ACTIVE | 00h 0 | 00h 0 | PINDA Temp cal.: __inactive__ | LCD menu | D3 Ax0faf C1
|
||||
| ^ | ^ | ^ | ffh 255 | ^ | PINDA Temp cal.: __active__ | ^ | ^
|
||||
| 0x0FA7h 4007 | uint32 | EEPROM_BOWDEN_LENGTH | ??? | ff 00 00 00h | Bowden length | ??? | D3 Ax0fae C8
|
||||
| ^ | ^ | ^ | ^ | 00 00 00 00h | ^ | ^ | ^
|
||||
| 0x0FA6h 4006 | uint8 | EEPROM_CALIBRATION_STATUS_PINDA | 00h 0 | ffh 255 | PINDA Temp: __not calibrated__ | ??? | D3 Ax0fa6 C1
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | PINDA Temp: __calibrated__ | ^ | ^
|
||||
| 0x0FA5h 4005 | uint8 | EEPROM_UVLO | 00h 0 | ffh 255 | Power Panic flag: __inactive__ | ??? | D3 Ax0fa5 C1
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | Power Panic flag: __active__ | ^ | ^
|
||||
| ^ | ^ | ^ | 02h 2 | ^ | Power Panic flag: __???__ | ^ | ^
|
||||
| 0x0F9Dh 3997 | float | EEPROM_UVLO_CURRENT_POSITION | ??? | ffh 255 | Power Panic position | ??? | D3 Ax0f9d C8
|
||||
| 0x0F95h 3989 | char | EEPROM_FILENAME | ??? | ffh 255 | Power Panic Filename | ??? | D3 Ax0f95 C8
|
||||
| 0x0F91h 3985 | uint32 | EEPROM_FILE_POSITION | ??? | ff ff ff ffh | Power Panic File Position | ??? | D3 Ax0f91 C4
|
||||
| 0x0F8Dh 3981 | float | EEPROM_UVLO_CURRENT_POSITION_Z | ??? | ff ff ff ffh | Power Panic Z Position | ^ | D3 Ax0f8d C4
|
||||
| 0x0F8Ch 3980 | ??? | EEPROM_UVLO_UNUSED_001 | ??? | ffh 255 | Power Panic _unused_ | ^ | D3 Ax0f8c C1
|
||||
| 0x0F8Bh 3979 | uint8 | EEPROM_UVLO_TARGET_BED | ??? | ffh 255 | Power Panic Bed temperature | ^ | D3 Ax0f8b C1
|
||||
| 0x0F89h 3977 | uint16 | EEPROM_UVLO_FEEDRATE | ??? | ff ffh 65535 | Power Panic Feedrate | ^ | D3 Ax0f89 C2
|
||||
| 0x0F88h 3976 | uint8 | EEPROM_UVLO_FAN_SPEED | ??? | ffh 255 | Power Panic Fan speed | ^ | D3 Ax0f88 C1
|
||||
| 0x0F87h 3975 | uint8 | EEPROM_FAN_CHECK_ENABLED | 00h 0 | ??? | Fan Check __disabled__ | LCD menu | D3 Ax0f87 C1
|
||||
| ^ | ^ | ^ | 01h 1 | ffh 255 | Fan Check __enabled__ | ^ | ^
|
||||
| 0x0F75h 3957 | uint16 | EEPROM_UVLO_MESH_BED_LEVELING | ??? | ff ffh 65535 | Power Panic Mesh Bed Leveling | ??? | D3 Ax0f75 C18
|
||||
| 0x0F73h 3955 | uint16 | EEPROM_UVLO_Z_MICROSTEPS | ??? | ff ffh 65535 | Power Panic Z microsteps | ??? | D3 Ax0f73 C2
|
||||
| 0x0F72h 3954 | uint8 | EEPROM_UVLO_E_ABS | ??? | ffh 255 | Power Panic ??? position | ??? | D3 Ax0f72 C1
|
||||
| 0x0F6Eh 3950 | foat | EEPROM_UVLO_CURRENT_POSITION_E | ??? | ff ff ff ffh | Power Panic E position | ??? | D3 Ax0f6e C4
|
||||
| 0x0F6Dh 3949 | ??? | _EEPROM_FREE_NR2_ | ??? | ffh 255 | _Free EEPROM space_ | _free space_ | D3 Ax0f6d C1
|
||||
| 0x0F6Ch 3948 | ??? | _EEPROM_FREE_NR3_ | ??? | ffh 255 | _Free EEPROM space_ | _free space_ | D3 Ax0f6c C1
|
||||
| 0x0F6Bh 3947 | ??? | _EEPROM_FREE_NR4_ | ??? | ffh 255 | _Free EEPROM space_ | _free space_ | D3 Ax0f6b C1
|
||||
| 0x0F6Ah 3946 | ??? | _EEPROM_FREE_NR5_ | ??? | ffh 255 | _Free EEPROM space_ | _free space_ | D3 Ax0f6a C1
|
||||
| 0x0F69h 3945 | uint8 | EEPROM_CRASH_DET | ffh 255 | ffh 255 | Crash detection: __enabled__ | LCD menu | D3 Ax0f69 C1
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | Crash detection: __disabled__ | LCD menu | ^
|
||||
| 0x0F68h 3944 | uint8 | EEPROM_CRASH_COUNT_Y | 00h-ffh 0-255 | ffh 255 __S/P__ | Crashes detected on y axis | ??? | D3 Ax0f68 C1
|
||||
| 0x0F67h 3943 | uint8 | EEPROM_FSENSOR | 01h 1 | ffh 255 __P__ | Filament sensor: __enabled__ | LCD menu | D3 Ax0f67 C1
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | Filament sensor: __disabled__ | LCD menu | ^
|
||||
| 0x0F65h 3942 | uint8 | EEPROM_CRASH_COUNT_X | 00h-ffh 0-255 | ffh 255 __S/P__ | Crashes detected on x axis | ??? | D3 Ax0f66 C1
|
||||
| 0x0F65h 3941 | uint8 | EEPROM_FERROR_COUNT | 00h-ffh 0-255 | ffh 255 __S/P__ | Filament sensor error counter | ??? | D3 Ax0f65 C1
|
||||
| 0x0F64h 3940 | uint8 | EEPROM_POWER_COUNT | 00h-ffh 0-255 | ffh 255 __S/P__ | Power failure counter | ??? | D3 Ax0f64 C1
|
||||
| 0x0F60h 3936 | float | EEPROM_XYZ_CAL_SKEW | ??? | ff ff ff ffh | XYZ skew value | ??? | D3 Ax0f60 C4
|
||||
| 0x0F5Fh 3935 | uint8 | EEPROM_WIZARD_ACTIVE | 01h 1 | 01h 1 __P__ | Wizard __active__ | ??? | D3 Ax0f5f C1
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | Wizard __inactive__ | ^ | ^
|
||||
| ^ | ^ | ^ | 02h 2 | 02h 2 __M__ | Wizard active - Z cal after shipping/service prep | ^ | ^
|
||||
| 0x0F5Dh 3933 | uint16 | EEPROM_BELTSTATUS_X | ??? | ff ffh | X Beltstatus | ??? | D3 Ax0f5d C2
|
||||
| 0x0F5Bh 3931 | uint16 | EEPROM_BELTSTATUS_Y | ??? | ff ffh | Y Beltstatus | ??? | D3 Ax0f5b C2
|
||||
| 0x0F5Ah 3930 | uint8 | EEPROM_DIR_DEPTH | 00h-ffh 0-255 | ffh 255 | Directory depth | ??? | D3 Ax0f5a C1
|
||||
| 0x0F0Ah 3850 | uint8 | EEPROM_DIRS | ??? | ffh 255 | Directories ??? | ??? | D3 Ax0f0a C80
|
||||
| 0x0F09h 3849 | uint8 | EEPROM_SD_SORT | 00h 0 | ffh 255 | SD card sort by: __time__ | LCD menu | D3 Ax0f09 C1
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | SD card sort by: __alphabet__ | LCD menu | ^
|
||||
| ^ | ^ | ^ | 02h 1 | ^ | SD card: __not sorted__ | LCD menu | ^
|
||||
| 0x0F08h 3848 | uint8 | EEPROM_SECOND_SERIAL_ACTIVE | 00h 0 | ffh 255 | RPi Port: __disabled__ | LCD menu | D3 Ax0f08 C1
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | RPi Port: __enabled__ | LCD menu | ^
|
||||
| 0x0F07h 3847 | uint8 | EEPROM_FSENS_AUTOLOAD_ENABLED | 01h 1 | ffh 255 __P__ | Filament autoload: __enabled__ | LCD menu | D3 Ax0f07 C1
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | Filament autoload: __disabled__ | LCD menu | ^
|
||||
| 0x0F05h 3845 | uint16 | EEPROM_CRASH_COUNT_X_TOT | 0000-fffe | ff ffh __S/P__ | Total crashes on x axis | ??? | D3 Ax0f05 C2
|
||||
| 0x0F03h 3843 | uint16 | EEPROM_CRASH_COUNT_Y_TOT | 0000-fffe | ff ffh __S/P__ | Total crashes on y axis | ??? | D3 Ax0f03 C2
|
||||
| 0x0F01h 3841 | uint16 | EEPROM_FERROR_COUNT_TOT | 0000-fffe | ff ffh __S/P__ | Total filament sensor errors | ??? | D3 Ax0f01 C2
|
||||
| 0x0EFFh 3839 | uint16 | EEPROM_POWER_COUNT_TOT | 0000-fffe | ff ffh __S/P__ | Total power failures | ??? | D3 Ax0eff C2
|
||||
| 0x0EFEh 3838 | uint8 | EEPROM_TMC2130_HOME_X_ORIGIN | ??? | ffh 255 | ??? | ??? | D3 Ax0efe C1
|
||||
| 0x0EFDh 3837 | uint8 | EEPROM MC2130_HOME_X_BSTEPS | ??? | ffh 255 | ??? | ??? | D3 Ax0efd C1
|
||||
| 0x0EFCh 3836 | uint8 | EEPROM_TMC2130_HOME_X_FSTEPS | ??? | ffh 255 | ??? | ??? | D3 Ax0efc C1
|
||||
| 0x0EFBh 3835 | uint8 | EEPROM_TMC2130_HOME_Y_ORIGIN | ??? | ffh 255 | ??? | ??? | D3 Ax0efb C1
|
||||
| 0x0EFAh 3834 | uint8 | EEPROM_TMC2130_HOME_Y_BSTEPS | ??? | ffh 255 | ??? | ??? | D3 Ax0efa C1
|
||||
| 0x0EF9h 3833 | uint8 | EEPROM_TMC2130_HOME_Y_FSTEPS | ??? | ffh 255 | ??? | ??? | D3 Ax0ef9 C1
|
||||
| 0x0EF8h 3832 | uint8 | EEPROM_TMC2130_HOME_ENABLED | ??? | ffh 255 | ??? | ??? | D3 Ax0ef8 C1
|
||||
| 0x0EF7h 3831 | uint8 | EEPROM_TMC2130_WAVE_X_FAC | ??? | ffh 255 | ??? | ??? | D3 Ax0ef7 C1
|
||||
| 0x0EF6h 3830 | uint8 | EEPROM_TMC2130_WAVE_Y_FAC | ??? | ffh 255 | ??? | ??? | D3 Ax0ef6 C1
|
||||
| 0x0EF5h 3829 | uint8 | EEPROM_TMC2130_WAVE_Z_FAC | ??? | ffh 255 | ??? | ??? | D3 Ax0ef5 C1
|
||||
| 0x0EF4h 3828 | uint8 | EEPROM_TMC2130_WAVE_E_FAC | ??? | ffh 255 | ??? | ??? | D3 Ax0ef4 C1
|
||||
| 0x0EF3h 3827 | uint8 | EEPROM_TMC2130_X_MRES | ??? | ffh 255 | ??? | ??? | D3 Ax0ef3 C1
|
||||
| 0x0EF2h 3826 | uint8 | EEPROM_TMC2130_Y_MRES | ??? | ffh 255 | ??? | ??? | D3 Ax0ef2 C1
|
||||
| 0x0EF1h 3825 | uint8 | EEPROM_TMC2130_Z_MRES | ??? | ffh 255 | ??? | ??? | D3 Ax0ef1 C1
|
||||
| 0x0EF0h 3824 | uint8 | EEPROM_TMC2130_E_MRES | ??? | ffh 255 | ??? | ??? | D3 Ax0ef0 C1
|
||||
| 0x0EEE 3822 | uint16 | EEPROM_PRINTER_TYPE | ??? | ff ffh 65535 | Printer Type | ??? | D3 Ax0eee C2
|
||||
| ^ | ^ | ^ | 64 00h 100 | ^ | PRINTER_MK1 | ??? | ^
|
||||
| ^ | ^ | ^ | c8 00h 200 | ^ | PRINTER_MK2 | ??? | ^
|
||||
| ^ | ^ | ^ | c9 00h 201 | ^ | PRINTER_MK2 with MMU1 | ??? | ^
|
||||
| ^ | ^ | ^ | ca 00h 202 | ^ | PRINTER_MK2S | ??? | ^
|
||||
| ^ | ^ | ^ | cb 00h 203 | ^ | PRINTER_MK2S with MMU1 | ??? | ^
|
||||
| ^ | ^ | ^ | fa 00h 250 | ^ | PRINTER_MK2.5 | ??? | ^
|
||||
| ^ | ^ | ^ | 1a 4fh 20250 | ^ | PRINTER_MK2.5 with MMU2 | ??? | ^
|
||||
| ^ | ^ | ^ | fc 00h 252 | ^ | PRINTER_MK2.5S | ??? | ^
|
||||
| ^ | ^ | ^ | 1c 4fh 20252 | ^ | PRINTER_MK2.5S with MMU2S | ??? | ^
|
||||
| ^ | ^ | ^ | 2c 01h 300 | ^ | PRINTER_MK3 | ??? | ^
|
||||
| ^ | ^ | ^ | 4c 4fh 20300 | ^ | PRINTER_MK3 with MMU2 | ??? | ^
|
||||
| ^ | ^ | ^ | 2e 01h 302 | ^ | PRINTER_MK3S | ??? | ^
|
||||
| ^ | ^ | ^ | 4e 4fh 20302 | ^ | PRINTER_MK3S with MMU2S | ??? | ^
|
||||
| 0x0EEC 3820 | uint16 | EEPROM_BOARD_TYPE | ??? | ff ffh 65535 | Board Type | ??? | D3 Ax0eec C2
|
||||
| ^ | ^ | ^ | c8 00h 200 | ^ | BOARD_RAMBO_MINI_1_0 | ??? | ^
|
||||
| ^ | ^ | ^ | cb 00h 203 | ^ | BOARD_RAMBO_MINI_1_3 | ??? | ^
|
||||
| ^ | ^ | ^ | 36 01h 310 | ^ | BOARD_EINSY_1_0a | ??? | ^
|
||||
| 0x0EE8 3816 | float | EEPROM_EXTRUDER_MULTIPLIER_0 | ??? | ff ff ff ffh | Power panic Extruder 0 multiplier | ??? | D3 Ax0ee8 C4
|
||||
| 0x0EE4 3812 | float | EEPROM_EXTRUDER_MULTIPLIER_1 | ??? | ff ff ff ffh | Power panic Extruder 1 multiplier | ??? | D3 Ax0ee4 C4
|
||||
| 0x0EE0 3808 | float | EEPROM_EXTRUDER_MULTIPLIER_2 | ??? | ff ff ff ffh | Power panic Extruder 2 multiplier | ??? | D3 Ax0ee0 C4
|
||||
| 0x0EDE 3806 | uint16 | EEPROM_EXTRUDEMULTIPLY | ??? | ff ffh 65535 | Power panic Extruder multiplier | ??? | D3 Ax0ede C2
|
||||
| 0x0EDA 3802 | float | EEPROM_UVLO_TINY_CURRENT_POSITION_Z | ??? | ff ff ff ffh | Power panic Z position | ??? | D3 Ax0eda C4
|
||||
| 0x0ED8 3800 | uint16 | EEPROM_UVLO_TARGET_HOTEND | ??? | ff ffh 65535 | Power panic target Hotend temperature | ??? | D3 Ax0ed8 C2
|
||||
| 0x0ED7 3799 | uint8 | EEPROM_SOUND_MODE | 00h 0 | ffh 255 | Sound mode: __loud__ | ??? | D3 Ax0ed7 C1
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | Sound mode: __once__ | ^ | ^
|
||||
| ^ | ^ | ^ | 02h 1 | ^ | Sound mode: __silent__ | ^ | ^
|
||||
| ^ | ^ | ^ | 03h 1 | ^ | Sound mode: __assist__ | ^ | ^
|
||||
| 0x0ED6 3798 | bool | EEPROM_AUTO_DEPLETE | 01h 1 | ffh 255 | MMU2/s autodeplete: __on__ | ??? | D3 Ax0ed6 C1
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | MMU2/s autodeplete: __off__ | ^ | ^
|
||||
| 0x0ED5 3797 | bool | EEPROM_FSENS_OQ_MEASS_ENABLED | ??? | ffh 255 | PAT1925 ??? | ??? | D3 Ax0ed5 C1
|
||||
| ^ | ^ | ^ | ??? | ^ | PAT1925 ??? | ^ | ^
|
||||
| 0x0ED3 3795 | uint16 | EEPROM_MMU_FAIL_TOT | ??? | ff ffh 65535 __S/P__ | MMU2/s total failures | ??? | D3 Ax0ed3 C2
|
||||
| 0x0ED2 3794 | uint8 | EEPROM_MMU_FAIL | ??? | ffh 255 __S/P__ | MMU2/s fails during print | ??? | D3 Ax0ed2 C1
|
||||
| 0x0ED0 3792 | uint16 | EEPROM_MMU_LOAD_FAIL_TOT | ??? | ff ffh 65535 __S/P__ | MMU2/s total load failures | ??? | D3 Ax0ed0 C2
|
||||
| 0x0ECF 3791 | uint8 | EEPROM_MMU_LOAD_FAIL | ??? | ffh 255 __S/P__ | MMU2/s load failures during print | ??? | D3 Ax0ecf C1
|
||||
| 0x0ECE 3790 | uint8 | EEPROM_MMU_CUTTER_ENABLED | 00h 0 | ffh 255 | MMU2/s cutter: __disabled__ | LCD menu | D3 Ax0ece C1
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | MMU2/s cutter: __enabled__ | ^ | ^
|
||||
| ^ | ^ | ^ | 02h 2 | ^ | MMU2/s cutter: __always__ | ^ | ^
|
||||
| 0x0DAE 3502 | uint16 | EEPROM_UVLO_MESH_BED_LEVELING_FULL | ??? | ff ffh 65535 | Power panic Mesh bed leveling points | ??? | D3 Ax0dae C288
|
||||
| 0x0DAD 3501 | uint8 | EEPROM_MBL_TYPE | ??? | ffh 255 | Mesh bed leveling precision _unused atm_ | ??? | D3 Ax0dad C1
|
||||
| 0x0DAC 3500 | bool | EEPROM_MBL_MAGNET_ELIMINATION | 01h 1 | ffh 255 | Mesh bed leveling does: __ignores__ magnets | LCD menu | D3 Ax0dac C1
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | Mesh bed leveling does: __NOT ignores__ magnets | ^ | ^
|
||||
| 0x0DAB 3499 | uint8 | EEPROM_MBL_POINTS_NR | 03h 3 | ffh 255 | Mesh bed leveling points: __3x3__ | LCD menu | D3 Ax0dab C1
|
||||
| ^ | ^ | ^ | 07h 7 | ^ | Mesh bed leveling points: __7x7__ | ^ | ^
|
||||
| 0x0DAA 3498 | uint8 | EEPROM_MBL_PROBE_NR | 03h 3 | ffh 255 | MBL times measurements for each point: __3__ | LCD menu | D3 Ax0daa C1
|
||||
| ^ | ^ | ^ | 05h 5 | ^ | MBL times measurements for each point: __5__ | ^ | ^
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | MBL times measurements for each point: __1__ | ^ | ^
|
||||
| 0x0DA9 3497 | uint8 | EEPROM_MMU_STEALTH | 01h 1 | ffh 255 | MMU2/s Silent mode: __on__ | ??? | D3 Ax0da9 C1
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | MMU2/s Silent mode: __off__ | ^ | ^
|
||||
| 0x0DA8 3496 | uint8 | EEPROM_CHECK_MODE | 01h 1 | ffh 255 | Check mode for nozzle is: __warn__ | LCD menu | D3 Ax0da8 C1
|
||||
| ^ | ^ | ^ | 02h 0 | ^ | Check mode for nozzle is: __strict__ | ^ | ^
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | Check mode for nozzle is: __none__ | ^ | ^
|
||||
| 0x0DA7 3495 | uint8 | EEPROM_NOZZLE_DIAMETER | 28h 40 | ffh 255 | Nozzle diameter is: __40 or 0.40mm__ | LCD menu | D3 Ax0da7 C1
|
||||
| ^ | ^ | ^ | 3ch 60 | ^ | Nozzle diameter is: __60 or 0.60mm__ | ^ | ^
|
||||
| ^ | ^ | ^ | 3ch 80 | ^ | Nozzle diameter is: __80 or 0.80mm__ | ^ | ^
|
||||
| ^ | ^ | ^ | 19h 25 | ^ | Nozzle diameter is: __25 or 0.25mm__ | ^ | ^
|
||||
| 0x0DA5 3493 | uint16 | EEPROM_NOZZLE_DIAMETER_uM | 9001h | ff ffh 65535 | Nozzle diameter is: __400um__ | LCD menu | D3 Ax0da5 C2
|
||||
| ^ | ^ | ^ | 5802h | ^ | Nozzle diameter is: __600um__ | ^ | ^
|
||||
| ^ | ^ | ^ | 2003h | ^ | Nozzle diameter is: __800um__ | ^ | ^
|
||||
| ^ | ^ | ^ | fa00h | ^ | Nozzle diameter is: __250um__ | ^ | ^
|
||||
| 0x0DA4 3492 | uint8 | EEPROM_CHECK_MODEL | 01h 1 | ffh 255 | Check mode for printer model is: __warn__ | LCD menu | D3 Ax0da4 C1
|
||||
| ^ | ^ | ^ | 02h 0 | ^ | Check mode for printer model is: __strict__ | ^ | ^
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | Check mode for printer model is: __none__ | ^ | ^
|
||||
| 0x0DA3 3491 | uint8 | EEPROM_CHECK_VERSION | 01h 1 | ffh 255 | Check mode for firmware is: __warn__ | LCD menu | D3 Ax0da3 C1
|
||||
| ^ | ^ | ^ | 02h 0 | ^ | Check mode for firmware is: __strict__ | ^ | ^
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | Check mode for firmware is: __none__ | ^ | ^
|
||||
| 0x0DA2 3490 | uint8 | EEPROM_CHECK_GCODE | 01h 1 | ffh 255 | Check mode for gcode is: __warn__ _unused atm_ | LCD menu | D3 Ax0da2 C1
|
||||
| ^ | ^ | ^ | 02h 0 | ^ | Check mode for gcode is: __strict__ _unused atm_ | ^ | ^
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | Check mode for gcode is: __none__ _unused atm_ | ^ | ^
|
||||
| 0x0D49 3401 | uint16 | EEPROM_SHEETS_BASE | ??? | ffh 255 | ??? | LCD menu | D3 Ax0d49 C89
|
||||
| 0x0D49 3401 | char | _1st Sheet block_ | 536d6f6f746831| ffffffffffffff | 1st sheet - Name: _Smooth1_ | ^ | D3 Ax0d49 C7
|
||||
| 0x0D50 3408 | uint16 | ^ | 00 00h 0 | ff ffh 65535 | 1st sheet - Z offset | ^ | D3 Ax0d50 C2
|
||||
| 0x0D52 3410 | uint8 | ^ | 00h 0 | ffh 255 | 1st sheet - bed temp | ^ | D3 Ax0d52 C1
|
||||
| 0x0D53 3411 | uint8 | ^ | 00h 0 | ffh 255 | 1st sheet - PINDA temp | ^ | D3 Ax0d53 C1
|
||||
| 0x0D54 3412 | char | _2nd Sheet block_ | 536d6f6f746832| ffffffffffffff | 2nd sheet - Name: _Smooth2_ | ^ | D3 Ax0d54 C7
|
||||
| 0x0D5B 3419 | uint16 | ^ | 00 00h 0 | ff ffh 65535 | 2nd sheet - Z offset | ^ | D3 Ax0d5b C2
|
||||
| 0x0D5D 3421 | uint8 | ^ | 00h 0 | ffh 255 | 2nd sheet - bed temp | ^ | D3 Ax0d5d C1
|
||||
| 0x0D5E 3422 | uint8 | ^ | 00h 0 | ffh 255 | 2nd sheet - PINDA temp | ^ | D3 Ax0d5e C1
|
||||
| 0x0D5F 3423 | char | _3rd Sheet block_ | 54657874757231| ffffffffffffff | 3rd sheet - Name: _Textur1_ | ^ | D3 Ax0d5f C7
|
||||
| 0x0D66 3430 | uint16 | ^ | 00 00h 0 | ff ffh 65535 | 3rd sheet - Z offset | ^ | D3 Ax0d66 C2
|
||||
| 0x0D68 3432 | uint8 | ^ | 00h 0 | ffh 255 | 3rd sheet - bed temp | ^ | D3 Ax0d68 C1
|
||||
| 0x0D69 3433 | uint8 | ^ | 00h 0 | ffh 255 | 3rd sheet - PINDA temp | ^ | D3 Ax0d69 C1
|
||||
| 0x0D6A 3434 | char | _4th Sheet block_ | 54657874757232| ffffffffffffff | 4th sheet - Name: _Textur2_ | ^ | D3 Ax0d6a C7
|
||||
| 0x0D71 3441 | uint16 | ^ | 00 00h 0 | ff ffh 65535 | 4th sheet - Z offset | ^ | D3 Ax0d71 C2
|
||||
| 0x0D73 3443 | uint8 | ^ | 00h 0 | ffh 255 | 4th sheet - bed temp | ^ | D3 Ax0d73 C1
|
||||
| 0x0D74 3444 | uint8 | ^ | 00h 0 | ffh 255 | 4th sheet - PINDA temp | ^ | D3 Ax0d74 C1
|
||||
| 0x0D75 3445 | char | _5th Sheet block_ | 536174696e2031| ffffffffffffff | 5th sheet - Name: _Satin 1_ | ^ | D3 Ax0d75 C7
|
||||
| 0x0D7C 3452 | uint16 | ^ | 00 00h 0 | ff ffh 65535 | 5th sheet - Z offset | ^ | D3 Ax0d7c C2
|
||||
| 0x0D7E 3454 | uint8 | ^ | 00h 0 | ffh 255 | 5th sheet - bed temp | ^ | D3 Ax0d7e C1
|
||||
| 0x0D7F 3455 | uint8 | ^ | 00h 0 | ffh 255 | 5th sheet - PINDA temp | ^ | D3 Ax0d7f C1
|
||||
| 0x0D80 3456 | char | _6th Sheet block_ | 536174696e2032| ffffffffffffff | 6th sheet - Name: _Satin 2_ | ^ | D3 Ax0d80 C7
|
||||
| 0x0D87 3463 | uint16 | ^ | 00 00h 0 | ff ffh 65535 | 6th sheet - Z offset | ^ | D3 Ax0d87 C2
|
||||
| 0x0D89 3465 | uint8 | ^ | 00h 0 | ffh 255 | 6th sheet - bed temp | ^ | D3 Ax0d89 C1
|
||||
| 0x0D8A 3466 | uint8 | ^ | 00h 0 | ffh 255 | 6th sheet - PINDA temp | ^ | D3 Ax0d8a C1
|
||||
| 0x0D8B 3467 | char | _7th Sheet block_ | 437573746f6d31| ffffffffffffff | 7th sheet - Name: _Custom1_ | ^ | D3 Ax0d8b C7
|
||||
| 0x0D92 3474 | uint16 | ^ | 00 00h 0 | ff ffh 65535 | 7th sheet - Z offset | ^ | D3 Ax0d92 C2
|
||||
| 0x0D94 3476 | uint8 | ^ | 00h 0 | ffh 255 | 7th sheet - bed temp | ^ | D3 Ax0d94 C1
|
||||
| 0x0D95 3477 | uint8 | ^ | 00h 0 | ffh 255 | 7th sheet - PINDA temp | ^ | D3 Ax0d95 C1
|
||||
| 0x0D96 3478 | char | _8th Sheet block_ | 437573746f6d32| ffffffffffffff | 8th sheet - Name: _Custom2_ | ^ | D3 Ax0d96 C7
|
||||
| 0x0D9D 3485 | uint16 | ^ | 00 00h 0 | ff ffh 65535 | 8th sheet - Z offset | ^ | D3 Ax0d9d C2
|
||||
| 0x0D9F 3487 | uint8 | ^ | 00h 0 | ffh 255 | 8th sheet - bed temp | ^ | D3 Ax0d9f C1
|
||||
| 0x0DA0 3488 | uint8 | ^ | 00h 0 | ffh 255 | 8th sheet - PINDA temp | ^ | D3 Ax0da0 C1
|
||||
| 0x0DA1 3489 | uint8 | ??? | 00h 0 | ffh 255 | ??? | ??? | D3 Ax0da1 C1
|
||||
| 0x0D48 3400 | uint8 | EEPROM_FSENSOR_PCB | ffh 255 | ffh 255 | Filament Sensor type IR unknown | LCD Support | D3 Ax0d48 C1
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | Filament Sensor type IR 0.3 or older | ^ | ^
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | Filament Sensor type IR 0.4 or newer | ^ | ^
|
||||
| 0x0D47 3399 | uint8 | EEPROM_FSENSOR_ACTION_NA | 00h 0 | ffh 255 | Filament Sensor action: __Continue__ | LCD menu | D3 Ax0d47 C1
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | Filament Sensor action: __Pause__ | ^ | ^
|
||||
| 0x0D37 3383 | float | EEPROM_UVLO_SAVED_TARGET | ??? | ff ff ff ffh | Power panic saved target all-axis | ??? | D3 Ax0d37 C16
|
||||
| ^ | ^ | ^ | ??? | ^ | Power panic saved target e-axis | ^ | D3 Ax0d43 C4
|
||||
| ^ | ^ | ^ | ??? | ^ | Power panic saved target z-axis | ^ | D3 Ax0d3f C4
|
||||
| ^ | ^ | ^ | ??? | ^ | Power panic saved target y-axis | ^ | D3 Ax0d3b C4
|
||||
| ^ | ^ | ^ | ??? | ^ | Power panic saved target x-axis | ^ | D3 Ax0d37 C4
|
||||
| 0x0D35 3381 | uint16 | EEPROM_UVLO_FEEDMULTIPLY | ??? | ff ffh 65355 | Power panic saved feed multiplier | ??? | D3 Ax0d35 C2
|
||||
| 0x0D34 3380 | uint8 | EEPROM_BACKLIGHT_LEVEL_HIGH | 00h - ffh | 82h 130 | LCD backlight bright: __128__ Dim value to 255 | LCD menu | D3 Ax0d34 C1
|
||||
| 0x0D33 3379 | uint8 | EEPROM_BACKLIGHT_LEVEL_LOW | 00h - ffh | 32h 50 | LCD backlight dim: __50__ 0 to Bright value | LCD menu | D3 Ax0d33 C1
|
||||
| 0x0D32 3378 | uint8 | EEPROM_BACKLIGHT_MODE | 02h 2 | ffh 255 | LCD backlight mode: __Auto__ | LCD menu | D3 Ax0d32 C1
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | LCD backlight mode: __Bright__ | ^ | ^
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | LCD backlight mode: __Dim__ | ^ | ^
|
||||
| 0x0D30 3376 | uint16 | EEPROM_BACKLIGHT_TIMEOUT | 01 00 - ff ff | 0a 00h 65535 | LCD backlight timeout: __10__ seconds | LCD menu | D3 Ax0d30 C2
|
||||
| 0x0D2C 3372 | float | EEPROM_UVLO_LA_K | ??? | ff ff ff ffh | Power panic saved Linear Advanced K value | ??? | D3 Ax0d2c C4
|
||||
| 0x0D2B 3371 | uint8 | EEPROM_ALTFAN_OVERRIDE | ffh 255 | ffh 255 | ALTFAN override unknown state | LCD menu | D3 Ax0d2b C1
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | ALTFAN override deactivated | ^ | ^
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | ALTFAN override activated | ^ | ^
|
||||
| 0x0D2A 3370 | uint8 | EEPROM_EXPERIMENTAL_VISIBILITY | ffh 255 | ffh 255 | Experimental menu visibility unknown state | LCD menu | D3 Ax0d2a C1
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | Experimental menu visibility hidden | ^ | ^
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | Experimental menu visibility visible | ^ | ^
|
||||
| 0x0D29 3369 | uint8 | EEPROM_PINDA_TEMP_COMPENSATION | ffh 255 | ffh 255 | PINDA temp compensation unknown state | LCD menu | D3 Ax0d29 C1
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | PINDA has no temp compensation PINDA v1/2 | ^ | ^
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | PINDA has temp compensation aka SuperPINDA | ^ | ^
|
||||
| 0x0D15 3349 | char[20] | EEPROM_PRUSA_SN | SN[19] == 0 | ffffffffffffffff... | PRUSA Serial number string | PRUSA SN | D3 Ax0d15 C20
|
||||
| 0x0D11 3345 | float | EEPROM_UVLO_ACCELL | ??? | ff ff ff ffh | Power panic saved normal acceleration | ??? | D3 Ax0d11 C4
|
||||
| 0x0D0D 3341 | float | EEPROM_UVLO_RETRACT_ACCELL | ??? | ff ff ff ffh | Power panic saved retract acceleration | ??? | D3 Ax0d0d C4
|
||||
| 0x0D09 3337 | float | EEPROM_UVLO_TRAVEL_ACCELL | ??? | ff ff ff ffh | Power panic saved travel acceleration | ??? | D3 Ax0d09 C4
|
||||
| 0x0D05 3333 | uint32_t | EEPROM_JOB_ID | ??? | 00 00 00 00h | Job ID used by host software | D3 only | D3 Ax0d05 C4
|
||||
| 0x0D04 3332 | uint8_t | EEPROM_ECOOL_ENABLE | ffh 255 | ^ | Disable extruder motor scaling for non-farm print | LCD menu | D3 Ax0d04 C1
|
||||
| ^ | ^ | ^ | 2ah 42 | ^ | Enable extruder motor scaling for non-farm print | ^ | D3 Ax0d04 C1
|
||||
| 0x0D03 3321 | uint8_t | EEPROM_FW_CRASH_FLAG | ffh 255 | ffh 255 | Last FW crash reason (dump_crash_reason) | D21/D22 | D3 Ax0d03 C1
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | manual | ^ | ^
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | stack_error | ^ | ^
|
||||
| ^ | ^ | ^ | 02h 2 | ^ | watchdog | ^ | ^
|
||||
| ^ | ^ | ^ | 03h 3 | ^ | bad_isr | ^ | ^
|
||||
| ^ | ^ | ^ | 04h 4 | ^ | bad_pullup_temp_isr | ^ | ^
|
||||
| ^ | ^ | ^ | 05h 5 | ^ | bad_pullup_step_isr | ^ | ^
|
||||
|
||||
|
||||
|Address begin|Bit/Type | Name | Valid values | Default/FactoryReset | Description |Gcode/Function| Debug code
|
||||
| :-- | :-- | :-- | :--: | :--: | :-- | :--: | :--:
|
||||
| 0x0FFF 4095 | uchar | EEPROM_SILENT | 00h 0 | ffh 255 | TMC Stealth mode: __off__ / miniRambo Power mode | LCD menu | D3 Ax0fff C1
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | TMC Stealth mode: __on__ / miniRambo Silent mode | ^ | ^
|
||||
| ^ | ^ | ^ | 02h 2 | ^ | miniRambo Auto mode | ^ | ^
|
||||
| 0x0FFE 4094 | uchar | EEPROM_LANG | 00h 0 | ffh 255 __L__ | English / LANG_ID_PRI | LCD menu | D3 Ax0ffe C1
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | Other language LANG_ID_SEC | ^ | ^
|
||||
| 0x0FFC 4092 | uint16 | _EEPROM_FREE_NR10_ | ??? | ff ffh 65535 | _Free EEPROM space_ | _free space_ | D3 Ax0ffc C2
|
||||
| 0x0FFA 4090 | uint16 | _EEPROM_FREE_NR11_ | ??? | ff ffh 65535 | _Free EEPROM space_ | _free space_ | D3 Ax0ffa C2
|
||||
| 0x0FF8 4088 | uint16 | EEPROM_BABYSTEP_Z | ??? | ff ffh 65535 | Babystep for Z axis _legacy_ | ??? | D3 Ax0ff8 C2
|
||||
| ^ | ^ | ^ | ^ | ^ | multiple values stored now in EEPROM_Sheets_base | ^ | ^
|
||||
| 0x0FF7 4087 | uint8 | EEPROM_CALIBRATION_STATUS_V1 | ffh 255 | ffh 255 | Calibration status (<v3.12) | ??? | D3 Ax0ff7 C1
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | Calibrated | ^ | ^
|
||||
| ^ | ^ | ^ | e6h 230 | ^ | needs Live Z adjustment | ^ | ^
|
||||
| ^ | ^ | ^ | ebh 235 | ^ | needs Thermal Model calibration | ^ | ^
|
||||
| ^ | ^ | ^ | f0h 240 | ^ __P__ | needs Z calibration | ^ | ^
|
||||
| ^ | ^ | ^ | fah 250 | ^ | needs XYZ calibration | ^ | ^
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | Unknown (legacy) | ^ | ^
|
||||
| 0x0FF5 4085 | uint16 | _EEPROM_FREE_NR12_ | ??? | ff ffh 65535 | _Free EEPROM space_ | _free space_ | D3 Ax0ff5 C2
|
||||
| 0x0FF1 4081 | uint32 | EEPROM_FILAMENTUSED | ??? | 00 00 00 00h 0 __S/P__| Filament used in centimeters | ??? | D3 Ax0ff1 C4
|
||||
| 0x0FED 4077 | uint32 | EEPROM_TOTALTIME | ??? | 00 00 00 00h 0 __S/P__| Total print time in minutes | ??? | D3 Ax0fed C4
|
||||
| 0x0FE5 4069 | float | EEPROM_BED_CALIBRATION_CENTER | ??? | ff ff ff ffh | ??? | ??? | D3 Ax0fe5 C8
|
||||
| 0x0FDD 4061 | float | EEPROM_BED_CALIBRATION_VEC_X | ??? | ff ff ff ffh | ??? | ??? | D3 Ax0fdd C8
|
||||
| 0x0FD5 4053 | float | EEPROM_BED_CALIBRATION_VEC_Y | ??? | ff ff ff ffh | ??? | ??? | D3 Ax0fd5 C8
|
||||
| 0x0FC5 4037 | int16 | EEPROM_BED_CALIBRATION_Z_JITTER | ??? | ff ffh 65535 | ??? | ??? | D3 Ax0fc5 C16
|
||||
| 0x0FC4 4036 | bool | EEPROM_FARM_MODE | 00h 0 | ffh 255 __P__ | Prusa farm mode: __off__ | G99 | D3 Ax0fc4 C1
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | Prusa farm mode: __on__ | G98 | ^
|
||||
| 0x0FC3 4035 | free | _EEPROM_FREE_NR1_ | ??? | ffh 255 | _Free EEPROM space_ | _free space_ | D3 Ax0fc3 C1
|
||||
| 0x0FC1 4033 | ??? | _EEPROM_FREE_NR2_ | ??? | ff ffh 65535 | _Free EEPROM space_ | _free space_ | D3 Ax0fc1 C2
|
||||
| 0x0FC0 4032 | bool | EEPROM_BED_CORRECTION_VALID | 00h 0 | 00h 0 | Bed correction: __invalid__ | ??? | D3 Ax0fc0 C1
|
||||
| ^ | ^ | ^ | ffh 255 | ^ | Bed correction: __valid__ | ??? | ^
|
||||
| 0x0FBF 4031 | char | EEPROM_BED_CORRECTION_LEFT | 00h ffh | 00h 0 | Bed manual correction left | LCD menu | D3 Ax0fbf C1
|
||||
| ^ | ^ | ^ | ^ | ^ | At this moment limited to +-100um | G80 Lxxx | ^
|
||||
| 0x0FBE 4030 | char | EEPROM_BED_CORRECTION_RIGHT | 00h ffh | 00h 0 | Bed manual correction right | LCD menu | D3 Ax0fbe C1
|
||||
| ^ | ^ | ^ | ^ | ^ | At this moment limited to +-100um | G80 Rxxx | ^
|
||||
| 0x0FBD 4029 | char | EEPROM_BED_CORRECTION_FRONT | 00h ffh | 00h 0 | Bed manual correction front | LCD menu | D3 Ax0fbd C1
|
||||
| ^ | ^ | ^ | ^ | ^ | At this moment limited to +-100um | G80 Fxxx | ^
|
||||
| 0x0FBC 4028 | char | EEPROM_BED_CORRECTION_BACK | 00h ffh | 00h 0 | Bed manual correction back | LCD menu | D3 Ax0fbc C1
|
||||
| ^ | ^ | ^ | ^ | ^ | At this moment limited to +-100um | G80 Bxxx | ^
|
||||
| 0x0FBB 4027 | bool | EEPROM_TOSHIBA_FLASH_AIR_COMPATIBLITY | 00h 0 | ffh 255 | Toshiba Air: __off__ | LCD menu | D3 Ax0fbb C1
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | Toshiba Air: __on__ | ^ | ^
|
||||
| 0x0FBA 4026 | uint8 | _EEPROM_FREE_NR3_ | ??? | ??? | _Free EEPROM space_ | _free space_ | D3 Ax0fba C1
|
||||
| 0x0FB0 4016 | int16 | EEPROM_PROBE_TEMP_SHIFT | ??? | ??? | ??? | ??? | D3 Ax0fb0 C10
|
||||
| 0x0FAF 4015 | bool | EEPROM_TEMP_CAL_ACTIVE | 00h 0 | 00h 0 | PINDA Temp cal.: __inactive__ | LCD menu | D3 Ax0faf C1
|
||||
| ^ | ^ | ^ | ffh 255 | ^ | PINDA Temp cal.: __active__ | ^ | ^
|
||||
| 0x0FA7 4007 | ??? | _EEPROM_FREE_NR6_ | ??? | ffh 255 | _Free EEPROM space_ | _free space_ | D3 Ax0fae C8
|
||||
| 0x0FA6 4006 | uint8 | EEPROM_CALIBRATION_STATUS_PINDA | 00h 0 | ffh 255 | PINDA Temp: __not calibrated__ | ??? | D3 Ax0fa6 C1
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | PINDA Temp: __calibrated__ | ^ | ^
|
||||
| 0x0FA5 4005 | uint8 | EEPROM_UVLO | 00h 0 | ffh 255 | No print job recovery is pending | Power panic | D3 Ax0fa5 C1
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | Print job recovery is pending | ^ | ^
|
||||
| ^ | ^ | ^ | 02h 2 | ^ | Print job recovery retry is pending | ^ | ^
|
||||
| 0x0F9D 3997 | float | EEPROM_UVLO_CURRENT_POSITION | ??? | ffh 255 | Saved machine position (X and Y axis) | Power Panic | D3 Ax0f9d C8
|
||||
| ^ | ^ | ^ | ??? | ^ | Y-axis | ^ | D3 Ax0fa1 C4
|
||||
| ^ | ^ | ^ | ??? | ^ | X-axis | ^ | D3 Ax0f9d C4
|
||||
| 0x0F95 3989 | char[8] | EEPROM_FILENAME | ??? | ffh 255 | SD print SFN without extension | Power Panic | D3 Ax0f95 C8
|
||||
| 0x0F91 3985 | uint32 | EEPROM_FILE_POSITION | ??? | ff ff ff ffh | SD: file position, USB/Serial: last line number | Power Panic | D3 Ax0f91 C4
|
||||
| 0x0F8D 3981 | float | EEPROM_UVLO_CURRENT_POSITION_Z | ??? | ff ff ff ffh | Saved machine position (Z axis) without MBL applied| Power Panic | D3 Ax0f8d C4
|
||||
| 0x0F8C 3980 | uint8 | EEPROM_UVLO_PRINT_TYPE | 00h 0 | ffh 255 | print type: SD | Power Panic | D3 Ax0f8c C1
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | print type: USB / Serial | ^ | ^
|
||||
| ^ | ^ | ^ | 02h 2 | ^ | print type: None | ^ | ^
|
||||
| 0x0F8B 3979 | uint8 | EEPROM_UVLO_TARGET_BED | ??? | ffh 255 | Saved bed target temperature | Power Panic | D3 Ax0f8b C1
|
||||
| 0x0F89 3977 | uint16 | EEPROM_UVLO_FEEDRATE | ??? | ff ffh 65535 | Saved Feedrate | Power Panic | D3 Ax0f89 C2
|
||||
| 0x0F88 3976 | uint8 | EEPROM_UVLO_FAN_SPEED | ??? | ffh 255 | Saved Fan speed | Power Panic | D3 Ax0f88 C1
|
||||
| 0x0F87 3975 | uint8 | EEPROM_FAN_CHECK_ENABLED | 00h 0 | ??? | Fan Check __disabled__ | LCD menu | D3 Ax0f87 C1
|
||||
| ^ | ^ | ^ | 01h 1 | ffh 255 | Fan Check __enabled__ | ^ | ^
|
||||
| 0x0F75 3957 | uint16 | _EEPROM_FREE_NR7_ | ??? | ff ffh 65535 | _Free EEPROM space_ | _free space_ | D3 Ax0f75 C18
|
||||
| 0x0F73 3955 | uint16 | _EEPROM_FREE_NR8_ | ??? | ff ffh 65535 | _Free EEPROM space_ | _free space_ | D3 Ax0f73 C2
|
||||
| 0x0F72 3954 | uint8 | EEPROM_UVLO_E_ABS | ??? | ffh 0 | E axis was in relative mode (M83) | Power Panic | D3 Ax0f72 C1
|
||||
| 0x0F72 3954 | uint8 | ^ | ??? | ffh 1 | E axis was in absolute mode (M82) | Power Panic | ^
|
||||
| 0x0F6E 3950 | float | EEPROM_UVLO_CURRENT_POSITION_E | ??? | ff ff ff ffh | Saved machine position (E axis) | Power Panic | D3 Ax0f6e C4
|
||||
| 0x0F6C 3948 | uint16 | EEPROM_UVLO_SAVED_SEGMENT_IDX | all | ff ffh 65535 | Saved index of multi-segment move | Power Panic | D3 Ax0f6c C2
|
||||
| 0x0F6B 3947 | ??? | _EEPROM_FREE_NR4_ | ??? | ffh 255 | _Free EEPROM space_ | _free space_ | D3 Ax0f6b C1
|
||||
| 0x0F6A 3946 | ??? | _EEPROM_FREE_NR5_ | ??? | ffh 255 | _Free EEPROM space_ | _free space_ | D3 Ax0f6a C1
|
||||
| 0x0F69 3945 | uint8 | EEPROM_CRASH_DET | ffh 255 | ffh 255 | Crash detection: __enabled__ | LCD menu | D3 Ax0f69 C1
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | Crash detection: __disabled__ | LCD menu | ^
|
||||
| 0x0F68 3944 | uint8 | EEPROM_CRASH_COUNT_Y | 00h-ffh 0-255| ffh 255 __S/P__ | Crash detection counter Y (last print) | Statistics | D3 Ax0f68 C1
|
||||
| 0x0F67 3943 | uint8 | EEPROM_FSENSOR | 01h 1 | ffh 255 __P__ | Filament sensor: __enabled__ | LCD menu | D3 Ax0f67 C1
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | Filament sensor: __disabled__ | LCD menu | ^
|
||||
| 0x0F65 3942 | uint8 | EEPROM_CRASH_COUNT_X | 00h-ffh 0-255| ffh 255 __S/P__ | Crash detection counter X (last print) | Statistics | D3 Ax0f66 C1
|
||||
| 0x0F65 3941 | uint8 | EEPROM_FERROR_COUNT | 00h-ffh 0-255| ffh 255 __S/P__ | Filament runout/error counter (last print) | Statistics | D3 Ax0f65 C1
|
||||
| 0x0F64 3940 | uint8 | EEPROM_POWER_COUNT | 00h-ffh 0-255| ffh 255 __S/P__ | Power loss errors (last print) | Statistics | D3 Ax0f64 C1
|
||||
| 0x0F60 3936 | float | EEPROM_XYZ_CAL_SKEW | ??? | ff ff ff ffh | XYZ skew value | ??? | D3 Ax0f60 C4
|
||||
| 0x0F5F 3935 | uint8 | EEPROM_WIZARD_ACTIVE | 01h 1 | 01h 1 __P__ | Wizard __active__ | ??? | D3 Ax0f5f C1
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | Wizard __inactive__ | ^ | ^
|
||||
| ^ | ^ | ^ | 02h 2 | 02h 2 __M__ | Wizard active - Z cal after shipping/service prep | ^ | ^
|
||||
| 0x0F5D 3933 | uint16 | EEPROM_BELTSTATUS_X | ??? | ff ffh | X Beltstatus | ??? | D3 Ax0f5d C2
|
||||
| 0x0F5B 3931 | uint16 | EEPROM_BELTSTATUS_Y | ??? | ff ffh | Y Beltstatus | ??? | D3 Ax0f5b C2
|
||||
| 0x0F5A 3930 | uint8 | EEPROM_DIR_DEPTH | 00h-ffh 0-255| ffh 255 | Directory depth | ??? | D3 Ax0f5a C1
|
||||
| 0x0F0A 3850 | uint8 | EEPROM_DIRS | ??? | ffh 255 | Directories ??? | ??? | D3 Ax0f0a C80
|
||||
| 0x0F09 3849 | uint8 | EEPROM_SD_SORT | 00h 0 | ffh 255 | SD card sort by: __time__ | LCD menu | D3 Ax0f09 C1
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | SD card sort by: __alphabet__ | LCD menu | ^
|
||||
| ^ | ^ | ^ | 02h 2 | ^ | SD card: __not sorted__ | LCD menu | ^
|
||||
| 0x0F08 3848 | uint8 | EEPROM_SECOND_SERIAL_ACTIVE | 00h 0 | ffh 255 | RPi Port: __disabled__ | LCD menu | D3 Ax0f08 C1
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | RPi Port: __enabled__ | LCD menu | ^
|
||||
| 0x0F07 3847 | uint8 | EEPROM_FSENS_AUTOLOAD_ENABLED | 01h 1 | ffh 255 __P__ | Filament autoload: __enabled__ | LCD menu | D3 Ax0f07 C1
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | Filament autoload: __disabled__ | LCD menu | ^
|
||||
| 0x0F05 3845 | uint16 | EEPROM_CRASH_COUNT_X_TOT | 0000-fffe | ff ffh __S/P__ | Total crashes on x axis | Statistics | D3 Ax0f05 C2
|
||||
| 0x0F03 3843 | uint16 | EEPROM_CRASH_COUNT_Y_TOT | 0000-fffe | ff ffh __S/P__ | Total crashes on y axis | Statistics | D3 Ax0f03 C2
|
||||
| 0x0F01 3841 | uint16 | EEPROM_FERROR_COUNT_TOT | 0000-fffe | ff ffh __S/P__ | Total filament sensor errors | Statistics | D3 Ax0f01 C2
|
||||
| 0x0EFF 3839 | uint16 | EEPROM_POWER_COUNT_TOT | 0000-fffe | ff ffh __S/P__ | Total power failures | Statistics | D3 Ax0eff C2
|
||||
| 0x0EFE 3838 | uint8 | EEPROM_TMC2130_HOME_X_ORIGIN | ??? | ffh 255 | ??? | ??? | D3 Ax0efe C1
|
||||
| 0x0EFD 3837 | uint8 | EEPROM_TMC2130_HOME_X_BSTEPS | ??? | ffh 255 | ??? | ??? | D3 Ax0efd C1
|
||||
| 0x0EFC 3836 | uint8 | EEPROM_TMC2130_HOME_X_FSTEPS | ??? | ffh 255 | ??? | ??? | D3 Ax0efc C1
|
||||
| 0x0EFB 3835 | uint8 | EEPROM_TMC2130_HOME_Y_ORIGIN | ??? | ffh 255 | ??? | ??? | D3 Ax0efb C1
|
||||
| 0x0EFA 3834 | uint8 | EEPROM_TMC2130_HOME_Y_BSTEPS | ??? | ffh 255 | ??? | ??? | D3 Ax0efa C1
|
||||
| 0x0EF9 3833 | uint8 | EEPROM_TMC2130_HOME_Y_FSTEPS | ??? | ffh 255 | ??? | ??? | D3 Ax0ef9 C1
|
||||
| 0x0EF8 3832 | uint8 | EEPROM_TMC2130_HOME_ENABLED | ??? | ffh 255 | ??? | ??? | D3 Ax0ef8 C1
|
||||
| 0x0EF7 3831 | uint8 | EEPROM_TMC2130_WAVE_X_FAC | ??? | ffh 255 | ??? | ??? | D3 Ax0ef7 C1
|
||||
| 0x0EF6 3830 | uint8 | EEPROM_TMC2130_WAVE_Y_FAC | ??? | ffh 255 | ??? | ??? | D3 Ax0ef6 C1
|
||||
| 0x0EF5 3829 | uint8 | EEPROM_TMC2130_WAVE_Z_FAC | ??? | ffh 255 | ??? | ??? | D3 Ax0ef5 C1
|
||||
| 0x0EF4 3828 | uint8 | EEPROM_TMC2130_WAVE_E_FAC | ??? | ffh 255 | ??? | ??? | D3 Ax0ef4 C1
|
||||
| 0x0EF3 3827 | uint8 | EEPROM_TMC2130_X_MRES | ??? | ffh 255 | ??? | ??? | D3 Ax0ef3 C1
|
||||
| 0x0EF2 3826 | uint8 | EEPROM_TMC2130_Y_MRES | ??? | ffh 255 | ??? | ??? | D3 Ax0ef2 C1
|
||||
| 0x0EF1 3825 | uint8 | EEPROM_TMC2130_Z_MRES | ??? | ffh 255 | ??? | ??? | D3 Ax0ef1 C1
|
||||
| 0x0EF0 3824 | uint8 | EEPROM_TMC2130_E_MRES | ??? | ffh 255 | ??? | ??? | D3 Ax0ef0 C1
|
||||
| 0x0EEE 3822 | uint16 | EEPROM_PRINTER_TYPE | ??? | ff ffh 65535 | Printer Type | ??? | D3 Ax0eee C2
|
||||
| ^ | ^ | ^ | 64 00h 100 | ^ | PRINTER_MK1 | ??? | ^
|
||||
| ^ | ^ | ^ | c8 00h 200 | ^ | PRINTER_MK2 | ??? | ^
|
||||
| ^ | ^ | ^ | c9 00h 201 | ^ | PRINTER_MK2 with MMU1 | ??? | ^
|
||||
| ^ | ^ | ^ | ca 00h 202 | ^ | PRINTER_MK2S | ??? | ^
|
||||
| ^ | ^ | ^ | cb 00h 203 | ^ | PRINTER_MK2S with MMU1 | ??? | ^
|
||||
| ^ | ^ | ^ | fa 00h 250 | ^ | PRINTER_MK2.5 | ??? | ^
|
||||
| ^ | ^ | ^ | 1a 4fh 20250 | ^ | PRINTER_MK2.5 with MMU2 | ??? | ^
|
||||
| ^ | ^ | ^ | fc 00h 252 | ^ | PRINTER_MK2.5S | ??? | ^
|
||||
| ^ | ^ | ^ | 1c 4fh 20252 | ^ | PRINTER_MK2.5S with MMU2S | ??? | ^
|
||||
| ^ | ^ | ^ | 2c 01h 300 | ^ | PRINTER_MK3 | ??? | ^
|
||||
| ^ | ^ | ^ | 4c 4fh 20300 | ^ | PRINTER_MK3 with MMU2 | ??? | ^
|
||||
| ^ | ^ | ^ | 5c 76h 30300 | ^ | PRINTER_MK3 with MMU3 | ??? | ^
|
||||
| ^ | ^ | ^ | 2e 01h 302 | ^ | PRINTER_MK3S | ??? | ^
|
||||
| ^ | ^ | ^ | 4e 4fh 20302 | ^ | PRINTER_MK3S with MMU2S | ??? | ^
|
||||
| ^ | ^ | ^ | 5e 76h 30302 | ^ | PRINTER_MK3S with MMU3 | ??? | ^
|
||||
| 0x0EEC 3820 | uint16 | EEPROM_BOARD_TYPE | ??? | ff ffh 65535 | Board Type | ??? | D3 Ax0eec C2
|
||||
| ^ | ^ | ^ | c8 00h 200 | ^ | BOARD_RAMBO_MINI_1_0 | ??? | ^
|
||||
| ^ | ^ | ^ | cb 00h 203 | ^ | BOARD_RAMBO_MINI_1_3 | ??? | ^
|
||||
| ^ | ^ | ^ | 36 01h 310 | ^ | BOARD_EINSY_1_0a | ??? | ^
|
||||
| 0x0EE8 3816 | float | EEPROM_EXTRUDER_MULTIPLIER_0 | ??? | ff ff ff ffh | Extruder 0 multiplier | Power Panic | D3 Ax0ee8 C4
|
||||
| 0x0EE4 3812 | float | EEPROM_EXTRUDER_MULTIPLIER_1 | ??? | ff ff ff ffh | Extruder 1 multiplier | Power Panic | D3 Ax0ee4 C4
|
||||
| 0x0EE0 3808 | float | EEPROM_EXTRUDER_MULTIPLIER_2 | ??? | ff ff ff ffh | Extruder 2 multiplier | Power Panic | D3 Ax0ee0 C4
|
||||
| 0x0EDE 3806 | uint16 | EEPROM_EXTRUDEMULTIPLY | ??? | ff ffh 65535 | Extruder multiplier | Power Panic | D3 Ax0ede C2
|
||||
| 0x0EDA 3802 | float | EEPROM_UVLO_TINY_CURRENT_POSITION_Z | ??? | ff ff ff ffh | Saved Z-axis position when recovering print failed| Power Panic | D3 Ax0eda C4
|
||||
| 0x0ED8 3800 | uint16 | EEPROM_UVLO_TARGET_HOTEND | ??? | ff ffh 65535 | Saved hotend target temperature | Power Panic | D3 Ax0ed8 C2
|
||||
| 0x0ED7 3799 | uint8 | EEPROM_SOUND_MODE | 00h 0 | ffh 255 | Sound mode: __loud__ | ??? | D3 Ax0ed7 C1
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | Sound mode: __once__ | ^ | ^
|
||||
| ^ | ^ | ^ | 02h 2 | ^ | Sound mode: __silent__ | ^ | ^
|
||||
| ^ | ^ | ^ | 03h 3 | ^ | Sound mode: __assist__ | ^ | ^
|
||||
| 0x0ED6 3798 | bool | EEPROM_SPOOL_JOIN | 01h 1 | ffh 255 | SpoolJoin: __on__ | MMU | D3 Ax0ed6 C1
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | SpoolJoin: __off__ | ^ | ^
|
||||
| 0x0ED5 3797 | bool | EEPROM_FSENS_RUNOUT_ENABLED | 01h 1 | ffh 255 __P__ | Filament runout: __enabled__ | LCD menu | D3 Ax0ed5 C1
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | Filament runout: __disabled__ | ^ | ^
|
||||
| 0x0ED3 3795 | uint16 | EEPROM_MMU_FAIL_TOT | ??? | ff ffh 65535 __S/P__ | MMU total failures | LCD menu | D3 Ax0ed3 C2
|
||||
| 0x0ED2 3794 | uint8 | EEPROM_MMU_FAIL | ??? | ffh 255 __S/P__ | MMU fails during print | LCD menu | D3 Ax0ed2 C1
|
||||
| 0x0ED0 3792 | uint16 | EEPROM_MMU_LOAD_FAIL_TOT | ??? | ff ffh 65535 __S/P__ | MMU total load failures | LCD menu | D3 Ax0ed0 C2
|
||||
| 0x0ECF 3791 | uint8 | EEPROM_MMU_LOAD_FAIL | ??? | ffh 255 __S/P__ | MMU load failures during print | LCD menu | D3 Ax0ecf C1
|
||||
| 0x0ECE 3790 | uint8 | EEPROM_MMU_CUTTER_ENABLED | 00h 0 | ffh 255 | MMU cutter: __disabled__ | LCD menu | D3 Ax0ece C1
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | MMU cutter: __enabled__ | ^ | ^
|
||||
| ^ | ^ | ^ | 02h 2 | ^ | MMU cutter: __always__ | ^ | ^
|
||||
| 0x0DAE 3502 | uint16 | EEPROM_UVLO_MESH_BED_LEVELING_FULL | ??? | ff ffh 65535 | Saved MBL points | Power Panic | D3 Ax0dae C288
|
||||
| 0x0DAD 3501 | uint8 | _EEPROM_FREE_NR9_ | ??? | ffh 255 | _Free EEPROM space_ | _free space_ | D3 Ax0dad C1
|
||||
| 0x0DAC 3500 | bool | EEPROM_MBL_MAGNET_ELIMINATION | 01h 1 | ffh 255 | Mesh bed leveling does: __ignores__ magnets | LCD menu | D3 Ax0dac C1
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | Mesh bed leveling does: __NOT ignores__ magnets | ^ | ^
|
||||
| 0x0DAB 3499 | uint8 | EEPROM_MBL_POINTS_NR | 03h 3 | ffh 255 | Mesh bed leveling points: __3x3__ | LCD menu | D3 Ax0dab C1
|
||||
| ^ | ^ | ^ | 07h 7 | ^ | Mesh bed leveling points: __7x7__ | ^ | ^
|
||||
| 0x0DAA 3498 | uint8 | EEPROM_MBL_PROBE_NR | 03h 3 | ffh 255 | MBL times measurements for each point: __3__ | LCD menu | D3 Ax0daa C1
|
||||
| ^ | ^ | ^ | 05h 5 | ^ | MBL times measurements for each point: __5__ | ^ | ^
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | MBL times measurements for each point: __1__ | ^ | ^
|
||||
| 0x0DA9 3497 | uint8 | EEPROM_MMU_STEALTH | 01h 1 | ffh 255 | MMU Silent mode: __on__ | LCD menu | D3 Ax0da9 C1
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | MMU Silent mode: __off__ | ^ | ^
|
||||
| 0x0DA8 3496 | uint8 | EEPROM_CHECK_MODE | 01h 1 | ffh 255 | Check mode for nozzle is: __warn__ | LCD menu | D3 Ax0da8 C1
|
||||
| ^ | ^ | ^ | 02h 2 | ^ | Check mode for nozzle is: __strict__ | ^ | ^
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | Check mode for nozzle is: __none__ | ^ | ^
|
||||
| 0x0DA7 3495 | uint8 | EEPROM_NOZZLE_DIAMETER | 28h 40 | ffh 255 | Nozzle diameter is: __40 or 0.40mm__ | LCD menu | D3 Ax0da7 C1
|
||||
| ^ | ^ | ^ | 3ch 60 | ^ | Nozzle diameter is: __60 or 0.60mm__ | ^ | ^
|
||||
| ^ | ^ | ^ | 3ch 80 | ^ | Nozzle diameter is: __80 or 0.80mm__ | ^ | ^
|
||||
| ^ | ^ | ^ | 19h 25 | ^ | Nozzle diameter is: __25 or 0.25mm__ | ^ | ^
|
||||
| 0x0DA5 3493 | uint16 | EEPROM_NOZZLE_DIAMETER_uM | 9001h | ff ffh 65535 | Nozzle diameter is: __400um__ | LCD menu | D3 Ax0da5 C2
|
||||
| ^ | ^ | ^ | 5802h | ^ | Nozzle diameter is: __600um__ | ^ | ^
|
||||
| ^ | ^ | ^ | 2003h | ^ | Nozzle diameter is: __800um__ | ^ | ^
|
||||
| ^ | ^ | ^ | fa00h | ^ | Nozzle diameter is: __250um__ | ^ | ^
|
||||
| 0x0DA4 3492 | uint8 | EEPROM_CHECK_MODEL | 01h 1 | ffh 255 | Check mode for printer model is: __warn__ | LCD menu | D3 Ax0da4 C1
|
||||
| ^ | ^ | ^ | 02h 2 | ^ | Check mode for printer model is: __strict__ | ^ | ^
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | Check mode for printer model is: __none__ | ^ | ^
|
||||
| 0x0DA3 3491 | uint8 | EEPROM_CHECK_VERSION | 01h 1 | ffh 255 | Check mode for firmware is: __warn__ | LCD menu | D3 Ax0da3 C1
|
||||
| ^ | ^ | ^ | 02h 2 | ^ | Check mode for firmware is: __strict__ | ^ | ^
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | Check mode for firmware is: __none__ | ^ | ^
|
||||
| 0x0DA2 3490 | uint8 | EEPROM_CHECK_GCODE | 01h 1 | ffh 255 | Check mode for gcode is: __warn__ _unused atm_ | LCD menu | D3 Ax0da2 C1
|
||||
| ^ | ^ | ^ | 02h 2 | ^ | Check mode for gcode is: __strict__ _unused atm_ | ^ | ^
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | Check mode for gcode is: __none__ _unused atm_ | ^ | ^
|
||||
| 0x0D49 3401 | uint16 | EEPROM_SHEETS_BASE | ??? | ffh 255 | ??? | LCD menu | D3 Ax0d49 C89
|
||||
| 0x0D49 3401 | char | _1st Sheet block_ |536d6f6f746831| ffffffffffffff | 1st sheet - Name: _Smooth1_ | ^ | D3 Ax0d49 C7
|
||||
| 0x0D50 3408 | uint16 | ^ | 00 00h 0 | ff ffh 65535 | 1st sheet - Z offset | ^ | D3 Ax0d50 C2
|
||||
| 0x0D52 3410 | uint8 | ^ | 00h 0 | ffh 255 | 1st sheet - bed temp | ^ | D3 Ax0d52 C1
|
||||
| 0x0D53 3411 | uint8 | ^ | 00h 0 | ffh 255 | 1st sheet - PINDA temp | ^ | D3 Ax0d53 C1
|
||||
| 0x0D54 3412 | char | _2nd Sheet block_ |536d6f6f746832| ffffffffffffff | 2nd sheet - Name: _Smooth2_ | ^ | D3 Ax0d54 C7
|
||||
| 0x0D5B 3419 | uint16 | ^ | 00 00h 0 | ff ffh 65535 | 2nd sheet - Z offset | ^ | D3 Ax0d5b C2
|
||||
| 0x0D5D 3421 | uint8 | ^ | 00h 0 | ffh 255 | 2nd sheet - bed temp | ^ | D3 Ax0d5d C1
|
||||
| 0x0D5E 3422 | uint8 | ^ | 00h 0 | ffh 255 | 2nd sheet - PINDA temp | ^ | D3 Ax0d5e C1
|
||||
| 0x0D5F 3423 | char | _3rd Sheet block_ |54657874757231| ffffffffffffff | 3rd sheet - Name: _Textur1_ | ^ | D3 Ax0d5f C7
|
||||
| 0x0D66 3430 | uint16 | ^ | 00 00h 0 | ff ffh 65535 | 3rd sheet - Z offset | ^ | D3 Ax0d66 C2
|
||||
| 0x0D68 3432 | uint8 | ^ | 00h 0 | ffh 255 | 3rd sheet - bed temp | ^ | D3 Ax0d68 C1
|
||||
| 0x0D69 3433 | uint8 | ^ | 00h 0 | ffh 255 | 3rd sheet - PINDA temp | ^ | D3 Ax0d69 C1
|
||||
| 0x0D6A 3434 | char | _4th Sheet block_ |54657874757232| ffffffffffffff | 4th sheet - Name: _Textur2_ | ^ | D3 Ax0d6a C7
|
||||
| 0x0D71 3441 | uint16 | ^ | 00 00h 0 | ff ffh 65535 | 4th sheet - Z offset | ^ | D3 Ax0d71 C2
|
||||
| 0x0D73 3443 | uint8 | ^ | 00h 0 | ffh 255 | 4th sheet - bed temp | ^ | D3 Ax0d73 C1
|
||||
| 0x0D74 3444 | uint8 | ^ | 00h 0 | ffh 255 | 4th sheet - PINDA temp | ^ | D3 Ax0d74 C1
|
||||
| 0x0D75 3445 | char | _5th Sheet block_ |536174696e2020| ffffffffffffff | 5th sheet - Name: _Satin _ | ^ | D3 Ax0d75 C7
|
||||
| 0x0D7C 3452 | uint16 | ^ | 00 00h 0 | ff ffh 65535 | 5th sheet - Z offset | ^ | D3 Ax0d7c C2
|
||||
| 0x0D7E 3454 | uint8 | ^ | 00h 0 | ffh 255 | 5th sheet - bed temp | ^ | D3 Ax0d7e C1
|
||||
| 0x0D7F 3455 | uint8 | ^ | 00h 0 | ffh 255 | 5th sheet - PINDA temp | ^ | D3 Ax0d7f C1
|
||||
| 0x0D80 3456 | char | _6th Sheet block_ |4e796c6f6e5041| ffffffffffffff | 6th sheet - Name: _NylonPA_ | ^ | D3 Ax0d80 C7
|
||||
| 0x0D87 3463 | uint16 | ^ | 00 00h 0 | ff ffh 65535 | 6th sheet - Z offset | ^ | D3 Ax0d87 C2
|
||||
| 0x0D89 3465 | uint8 | ^ | 00h 0 | ffh 255 | 6th sheet - bed temp | ^ | D3 Ax0d89 C1
|
||||
| 0x0D8A 3466 | uint8 | ^ | 00h 0 | ffh 255 | 6th sheet - PINDA temp | ^ | D3 Ax0d8a C1
|
||||
| 0x0D8B 3467 | char | _7th Sheet block_ |437573746f6d31| ffffffffffffff | 7th sheet - Name: _Custom1_ | ^ | D3 Ax0d8b C7
|
||||
| 0x0D92 3474 | uint16 | ^ | 00 00h 0 | ff ffh 65535 | 7th sheet - Z offset | ^ | D3 Ax0d92 C2
|
||||
| 0x0D94 3476 | uint8 | ^ | 00h 0 | ffh 255 | 7th sheet - bed temp | ^ | D3 Ax0d94 C1
|
||||
| 0x0D95 3477 | uint8 | ^ | 00h 0 | ffh 255 | 7th sheet - PINDA temp | ^ | D3 Ax0d95 C1
|
||||
| 0x0D96 3478 | char | _8th Sheet block_ |437573746f6d32| ffffffffffffff | 8th sheet - Name: _Custom2_ | ^ | D3 Ax0d96 C7
|
||||
| 0x0D9D 3485 | uint16 | ^ | 00 00h 0 | ff ffh 65535 | 8th sheet - Z offset | ^ | D3 Ax0d9d C2
|
||||
| 0x0D9F 3487 | uint8 | ^ | 00h 0 | ffh 255 | 8th sheet - bed temp | ^ | D3 Ax0d9f C1
|
||||
| 0x0DA0 3488 | uint8 | ^ | 00h 0 | ffh 255 | 8th sheet - PINDA temp | ^ | D3 Ax0da0 C1
|
||||
| 0x0DA1 3489 | uint8 | active_sheet | 00h 0 | ffh 255 | Active sheet index | ^ | D3 Ax0da1 C1
|
||||
| 0x0D48 3400 | uint8 | EEPROM_FSENSOR_PCB | ffh 255 | ffh 255 | Filament Sensor type IR unknown | LCD Support | D3 Ax0d48 C1
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | Filament Sensor type IR 0.3 or older | ^ | ^
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | Filament Sensor type IR 0.4 or newer | ^ | ^
|
||||
| 0x0D47 3399 | uint8 | EEPROM_FSENSOR_ACTION_NA | 00h 0 | ffh 255 | Filament Sensor action: __Continue__ | LCD menu | D3 Ax0d47 C1
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | Filament Sensor action: __Pause__ | ^ | ^
|
||||
| 0x0D37 3383 | float | EEPROM_UVLO_SAVED_START_POSITION | ??? | ff ff ff ffh | Saved start position all-axis | Power Panic | D3 Ax0d37 C16
|
||||
| ^ | ^ | ^ | ??? | ^ | E-axis | ^ | D3 Ax0d43 C4
|
||||
| ^ | ^ | ^ | ??? | ^ | Z-axis | ^ | D3 Ax0d3f C4
|
||||
| ^ | ^ | ^ | ??? | ^ | Y-axis | ^ | D3 Ax0d3b C4
|
||||
| ^ | ^ | ^ | ??? | ^ | X-axis | ^ | D3 Ax0d37 C4
|
||||
| 0x0D35 3381 | uint16 | EEPROM_UVLO_FEEDMULTIPLY | ??? | ff ffh 65355 | Saved feed multiplier | Power Panic | D3 Ax0d35 C2
|
||||
| 0x0D34 3380 | uint8 | EEPROM_BACKLIGHT_LEVEL_HIGH | 00h - ffh | 82h 130 | LCD backlight bright: __128__ Dim value to 255 | LCD menu | D3 Ax0d34 C1
|
||||
| 0x0D33 3379 | uint8 | EEPROM_BACKLIGHT_LEVEL_LOW | 00h - ffh | 32h 50 | LCD backlight dim: __50__ 0 to Bright value | LCD menu | D3 Ax0d33 C1
|
||||
| 0x0D32 3378 | uint8 | EEPROM_BACKLIGHT_MODE | 02h 2 | ffh 255 | LCD backlight mode: __Auto__ | LCD menu | D3 Ax0d32 C1
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | LCD backlight mode: __Bright__ | ^ | ^
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | LCD backlight mode: __Dim__ | ^ | ^
|
||||
| 0x0D30 3376 | uint16 | EEPROM_BACKLIGHT_TIMEOUT | 01 00 - ff ff| 0a 00h 65535 | LCD backlight timeout: __10__ seconds | LCD menu | D3 Ax0d30 C2
|
||||
| 0x0D2C 3372 | float | EEPROM_UVLO_LA_K | ??? | ff ff ff ffh | Saved Linear Advanced K value | Power Panic | D3 Ax0d2c C4
|
||||
| 0x0D2B 3371 | uint8 | EEPROM_ALTFAN_OVERRIDE | ffh 255 | ffh 255 | ALTFAN override unknown state | LCD menu | D3 Ax0d2b C1
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | ALTFAN override deactivated | ^ | ^
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | ALTFAN override activated | ^ | ^
|
||||
| 0x0D2A 3370 | uint8 | EEPROM_EXPERIMENTAL_VISIBILITY | ffh 255 | ffh 255 | Experimental menu visibility unknown state | LCD menu | D3 Ax0d2a C1
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | Experimental menu visibility hidden | ^ | ^
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | Experimental menu visibility visible | ^ | ^
|
||||
| 0x0D29 3369 | uint8 | EEPROM_PINDA_TEMP_COMPENSATION | ffh 255 | ffh 255 | PINDA temp compensation unknown state | LCD menu | D3 Ax0d29 C1
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | PINDA has no temp compensation PINDA v1/2 | ^ | ^
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | PINDA has temp compensation aka SuperPINDA | ^ | ^
|
||||
| 0x0D15 3349 | char[20]| EEPROM_PRUSA_SN | SN[19] == 0 | ffffffffffffffff... | PRUSA Serial number string | PRUSA SN | D3 Ax0d15 C20
|
||||
| 0x0D11 3345 | float | EEPROM_UVLO_ACCELL | ??? | ff ff ff ffh | Saved print acceleration | Power Panic | D3 Ax0d11 C4
|
||||
| 0x0D0D 3341 | float | EEPROM_UVLO_RETRACT_ACCELL | ??? | ff ff ff ffh | Saved retract acceleration | Power Panic | D3 Ax0d0d C4
|
||||
| 0x0D09 3337 | float | EEPROM_UVLO_TRAVEL_ACCELL | ??? | ff ff ff ffh | Saved travel acceleration | Power Panic | D3 Ax0d09 C4
|
||||
| 0x0D05 3333 | unint32 | EEPROM_JOB_ID | ??? | 00 00 00 00h | Job ID used by host software | D3 only | D3 Ax0d05 C4
|
||||
| 0x0D04 3332 | uint8 | EEPROM_ECOOL_ENABLE | ffh 255 | ^ | Disable extruder motor scaling for non-farm print | LCD menu | D3 Ax0d04 C1
|
||||
| ^ | ^ | ^ | 2ah 42 | ^ | Enable extruder motor scaling for non-farm print | ^ | D3 Ax0d04 C1
|
||||
| 0x0D03 3331 | uint8 | EEPROM_FW_CRASH_FLAG | ffh 255 | ffh 255 | Last FW crash reason (dump_crash_reason) | D21/D22 | D3 Ax0d03 C1
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | manual | ^ | ^
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | stack_error | ^ | ^
|
||||
| ^ | ^ | ^ | 02h 2 | ^ | watchdog | ^ | ^
|
||||
| ^ | ^ | ^ | 03h 3 | ^ | bad_isr | ^ | ^
|
||||
| ^ | ^ | ^ | 04h 4 | ^ | bad_pullup_temp_isr | ^ | ^
|
||||
| ^ | ^ | ^ | 05h 5 | ^ | bad_pullup_step_isr | ^ | ^
|
||||
| 0x0D02 3330 | uint8 | EEPROM_THERMAL_MODEL_ENABLE | 00h 0 | ff/00 | Thermal Model deactivated | Thermal Model| D3 Ax0d02 C1
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | Thermal Model activated | ^ | ^
|
||||
| 0x0CFE 3326 | float | EEPROM_THERMAL_MODEL_P | ??? | ff ff ff ffh | Thermal Model power (W) | Thermal Model| D3 Ax0cfe C4
|
||||
| 0x0CFA 3322 | float | EEPROM_THERMAL_MODEL_C | ??? | ff ff ff ffh | Thermal Model capacitance (J/K) | Thermal Model| D3 Ax0cfa C4
|
||||
| 0x0CBA 3258 |float[16]| EEPROM_THERMAL_MODEL_R | ??? | ff ff ff ffh | Thermal Model resistance (K/W) | Thermal Model| D3 Ax0cba C64
|
||||
| 0x0CB6 3254 | float | EEPROM_THERMAL_MODEL_Ta_corr | ??? | ff ff ff ffh | Thermal Model ambient temperature correction (K) | Thermal Model| D3 Ax0cb6 C4
|
||||
| 0x0CB2 3250 | float | EEPROM_THERMAL_MODEL_W | ??? | ff ff ff ffh | Thermal Model warning threshold (K/s) | Thermal Model| D3 Ax0cb2 C4
|
||||
| 0x0CAE 3246 | float | EEPROM_THERMAL_MODEL_E | ??? | ff ff ff ffh | Thermal Model error threshold (K/s) | Thermal Model| D3 Ax0cae C4
|
||||
| 0x0CAD 3245 | uint8 | EEPROM_FSENSOR_JAM_DETECTION | 01h 1 | ff/01 | fsensor pat9125 jam detection feature | LCD menu | D3 Ax0cad C1
|
||||
| 0x0CAC 3244 | uint8 | EEPROM_MMU_ENABLED | 00h 0 | ff/00 | MMU enabled | LCD menu | D3 Ax0cac C1
|
||||
| 0x0CA8 3240 | uint32 | EEPROM_MMU_MATERIAL_CHANGES | ??? | ff ff ff ffh | MMU toolchange counter over printers lifetime | LCD statistic| D3 Ax0ca8 C4
|
||||
| 0x0CA7 3239 | uint8 | EEPROM_HEAT_BED_ON_LOAD_FILAMENT | ffh 255 | ffh 255 | Heat bed on load filament unknown state | LCD menu | D3 Ax0ca7 C1
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | Do not heat bed on load filament | ^ | ^
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | Heat bed on load filament | ^ | ^
|
||||
| 0x0CA6 3238 | uint8 | EEPROM_CALIBRATION_STATUS_V2 | ffh 255 | ffh 255 | Calibration status (>=v3.12) | ??? | D3 Ax0ca6 C1
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | Selftest passed | ^ | ^
|
||||
| ^ | ^ | ^ | 02h 2 | ^ | XYZ cal passed | ^ | ^
|
||||
| ^ | ^ | ^ | 04h 4 | ^ | Z cal passed | ^ | ^
|
||||
| ^ | ^ | ^ | 08h 8 | ^ | Thermal Model cal passed | ^ | ^
|
||||
| ^ | ^ | ^ | 10h 16 | ^ | Live Adjust set | ^ | ^
|
||||
| ^ | ^ | ^ | 20h 32 | ^ | Free bit | ^ | ^
|
||||
| ^ | ^ | ^ | 40h 64 | ^ | Free bit | ^ | ^
|
||||
| ^ | ^ | ^ | 80h 128 | ^ | Unknown | ^ | ^
|
||||
| 0x0CA2 3234 | float | EEPROM_THERMAL_MODEL_U | ??? | ff ff ff ffh | Thermal Model linear temp coefficient (W/K/W) | Thermal Model| D3 Ax0ca2 C4
|
||||
| 0x0C9E 3230 | float | EEPROM_THERMAL_MODEL_V | ??? | ff ff ff ffh | Thermal Model linear temp intercept (W/W) | Thermal Model| D3 Ax0c9e C4
|
||||
| 0x0C9A 3226 | float | EEPROM_THERMAL_MODEL_D | ??? | ff ff ff ffh | Thermal Model sim. 1st order IIR filter factor | Thermal Model| D3 Ax0c9a C4
|
||||
| 0x0C98 3224 | uint16 | EEPROM_THERMAL_MODEL_L | 0-2160 | ff ffh | Thermal Model sim. response lag (ms) | Thermal Model| D3 Ax0c98 C2
|
||||
| 0x0C97 3223 | uint8 | EEPROM_THERMAL_MODEL_VER | 0-255 | ffh | Thermal Model Version | Thermal Model| D3 Ax0c97 C1
|
||||
| 0x0C95 3221 | PGM_P | EEPROM_KILL_MESSAGE | 0-65535 | ff ffh | Kill message PGM pointer | kill() | D3 Ax0c95 C2
|
||||
| 0x0C94 3220 | uint8 | EEPROM_KILL_PENDING_FLAG | 42h, ffh | ffh | Kill pending flag (0x42 magic value) | kill() | D3 Ax0c94 C1
|
||||
| 0x0C91 3217 | char[3] | EEPROM_FILENAME_EXTENSION | ??? | ffffffffh | DOS 8.3 filename extension | Power Panic | D3 Ax0c91 C1
|
||||
| 0x0C80 3200 | char[17]| EEPROM_CUSTOM_MENDEL_NAME | Prusa i3 MK3S| ffffffffffffffffff... | Custom Printer Name | | D3 Ax0c80 C17
|
||||
| 0x0C7F 3199 | bool | EEPROM_UVLO_Z_LIFTED | 00h 0 | 00h | Power Panic Z axis NOT lifted | Power Panic | D3 Ax0c7f C1
|
||||
| ^ | ^ | ^ | 01h 1 | 01h | Power Panic Z axis lifted | ^ | ^
|
||||
| 0x0C7d 3197 | uint16 | EEPROM_UVLO_EXTRUDE_MINTEMP | 0-305 | afh 175 | Power Panic Extrude mintemp | Power Panic | D3 Ax0c7d C2
|
||||
| 0x0C6D 3181 | uint32 | EEPROM_UVLO_ACCELL_MM_S2_NORMAL | ??? | ff ff ff ffh | Power Panic acceleration mm per s2 normal | Power Panic | D3 Ax0c6d C16
|
||||
| ^ | ^ | ^ | ??? | ^ | E-axis | ^ | D3 Ax0c79 C4
|
||||
| ^ | ^ | ^ | ??? | ^ | Z-axis | ^ | D3 Ax0c75 C4
|
||||
| ^ | ^ | ^ | ??? | ^ | Y-axis | ^ | D3 Ax0c71 C4
|
||||
| ^ | ^ | ^ | ??? | ^ | X-axis | ^ | D3 Ax0c6d C4
|
||||
| 0x0C5D 3165 | uint32 | EEPROM_UVLO_ACCELL_MM_S2_SILENT | ??? | ff ff ff ffh | Power Panic acceleration mm per s2 silent | Power Panic | D3 Ax0c5d C16
|
||||
| ^ | ^ | ^ | ??? | ^ | E-axis | ^ | D3 Ax0c69 C4
|
||||
| ^ | ^ | ^ | ??? | ^ | Z-axis | ^ | D3 Ax0c65 C4
|
||||
| ^ | ^ | ^ | ??? | ^ | Y-axis | ^ | D3 Ax0c61 C4
|
||||
| ^ | ^ | ^ | ??? | ^ | X-axis | ^ | D3 Ax0c5d C4
|
||||
| 0x0C4D 3149 | float | EEPROM_UVLO_MAX_FEEDRATE_NORMAL | ??? | ff ff ff ffh | Power Panic max feedrate normal | Power Panic | D3 Ax0c4d C16
|
||||
| ^ | ^ | ^ | ??? | ^ | E-axis | ^ | D3 Ax0d59 C4
|
||||
| ^ | ^ | ^ | ??? | ^ | Z-axis | ^ | D3 Ax0d55 C4
|
||||
| ^ | ^ | ^ | ??? | ^ | Y-axis | ^ | D3 Ax0d51 C4
|
||||
| ^ | ^ | ^ | ??? | ^ | X-axis | ^ | D3 Ax0c4d C4
|
||||
| 0x0C3D 3133 | float | EEPROM_UVLO_MAX_FEEDRATE_SILENT | ??? | ff ff ff ffh | Power Panic max feedrate silent | Power Panic | D3 Ax0c3d C16
|
||||
| ^ | ^ | ^ | ??? | ^ | E-axis | ^ | D3 Ax0d49 C4
|
||||
| ^ | ^ | ^ | ??? | ^ | Z-axis | ^ | D3 Ax0d45 C4
|
||||
| ^ | ^ | ^ | ??? | ^ | Y-axis | ^ | D3 Ax0d41 C4
|
||||
| ^ | ^ | ^ | ??? | ^ | X-axis | ^ | D3 Ax0c3d C4
|
||||
| 0x0C39 3129 | float | EEPROM_UVLO_MIN_FEEDRATE | ??? | ff ff ff ffh | Power Panic min feedrate | Power Panic | D3 Ax0c39 C4
|
||||
| 0x0C35 3125 | float | EEPROM_UVLO_MIN_TRAVEL_FEEDRATE | ??? | ff ff ff ffh | Power Panic min travel feedrate | Power Panic | D3 Ax0c35 C4
|
||||
| 0x0C31 3121 | uint32 | EEPROM_UVLO_MIN_SEGMENT_TIME_US | ??? | ff ff ff ffh | Power Panic min segment time us | Power Panic | D3 Ax0c31 C4
|
||||
| 0x0C21 3105 | float | EEPROM_UVLO_MAX_JERK | ??? | ff ff ff ffh | Power Panic max jerk | Power Panic | D3 Ax0c21 C16
|
||||
| ^ | ^ | ^ | ??? | ^ | E-axis | ^ | D3 Ax0d2d C4
|
||||
| ^ | ^ | ^ | ??? | ^ | Z-axis | ^ | D3 Ax0d29 C4
|
||||
| ^ | ^ | ^ | ??? | ^ | Y-axis | ^ | D3 Ax0d25 C4
|
||||
| ^ | ^ | ^ | ??? | ^ | X-axis | ^ | D3 Ax0c21 C4
|
||||
| 0x0C11 3089 | uint8 | EEPROM_CHECK_FILAMENT | 01h 1 | ffh 255 | Check mode for filament is: __warn__ | LCD menu | D3 Ax0c11 C1
|
||||
| ^ | ^ | ^ | 02h 2 | ^ | Check mode for filament is: __strict__ | ^ | ^
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | Check mode for filament is: __none__ | ^ | ^
|
||||
|
||||
|
||||
|Address begin|Bit/Type | Name | Valid values | Default/FactoryReset | Description |Gcode/Function| Debug code
|
||||
| :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--:
|
||||
| 0x0012 18 | uint16 | EEPROM_FIRMWARE_VERSION_END | ??? | ff ffh 65535 | ??? | ??? | D3 Ax0012 C2
|
||||
| 0x0010 16 | uint16 | EEPROM_FIRMWARE_VERSION_FLAVOR | ??? | ff ffh 65535 | ??? | ??? | D3 Ax0010 C2
|
||||
| 0x000E 14 | uint16 | EEPROM_FIRMWARE_VERSION_REVISION | ??? | ff ffh 65535 | Firmware version revision number DEV/ALPHA/BETA/RC| ??? | D3 Ax000e C2
|
||||
| 0x000C 12 | uint16 | EEPROM_FIRMWARE_VERSION_MINOR | ??? | ff ffh 65535 | Firmware version minor number | ??? | D3 Ax000c C2
|
||||
| 0x000A 10 | uint16 | EEPROM_FIRMWARE_VERSION_MAJOR | ??? | ff ffh 65535 | Firmware version major number | ??? | D3 Ax000a C2
|
||||
| 0x0000 0 | char | FW_PRUSA3D_MAGIC | ??? | ffffffffffffffffffff | __`PRUSA3DFW`__ | ??? | D3 Ax0000 C10
|
||||
| Address begin | Bit/Type | Name | Valid values | Default/FactoryReset | Description | Gcode/Function| Debug code
|
||||
| :--: | :--: | :--: | :--: | :--: | :--: | :--: | :--:
|
||||
| 0x0012 18 | uint16 | EEPROM_FIRMWARE_VERSION_END | ??? | ff ffh 65535 | ??? | ??? | D3 Ax0012 C2
|
||||
| 0x0010 16 | uint16 | EEPROM_FIRMWARE_VERSION_FLAVOR | ??? | ff ffh 65535 | ??? | ??? | D3 Ax0010 C2
|
||||
| 0x000E 14 | uint16 | EEPROM_FIRMWARE_VERSION_REVISION | ??? | ff ffh 65535 | Firmware version revision number DEV/ALPHA/BETA/RC| ??? | D3 Ax000e C2
|
||||
| 0x000C 12 | uint16 | EEPROM_FIRMWARE_VERSION_MINOR | ??? | ff ffh 65535 | Firmware version minor number | ??? | D3 Ax000c C2
|
||||
| 0x000A 10 | uint16 | EEPROM_FIRMWARE_VERSION_MAJOR | ??? | ff ffh 65535 | Firmware version major number | ??? | D3 Ax000a C2
|
||||
| 0x0000 0 | char | FW_PRUSA3D_MAGIC | ??? | ffffffffffffffffffff | __`PRUSA3DFW`__ | ??? | D3 Ax0000 C10
|
||||
*/
|
||||
|
||||
#define EEPROM_EMPTY_VALUE 0xFF
|
||||
|
|
@ -437,11 +353,11 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP
|
|||
#define EEPROM_TOP 4096
|
||||
#define EEPROM_SILENT 4095
|
||||
#define EEPROM_LANG 4094
|
||||
#define _EEPROM_FREE_NR10_ 4092 // uint16_t
|
||||
#define _EEPROM_FREE_NR11_ 4090 // uint16_t
|
||||
#define EEPROM_BABYSTEP_X 4092 //unused
|
||||
#define EEPROM_BABYSTEP_Y 4090 //unused
|
||||
#define EEPROM_BABYSTEP_Z 4088 //legacy, multiple values stored now in EEPROM_Sheets_base
|
||||
#define EEPROM_CALIBRATION_STATUS_V1 4087 // legacy, used up to v3.11
|
||||
#define _EEPROM_FREE_NR12_ (EEPROM_CALIBRATION_STATUS_V1 - 2) // uint16_t
|
||||
#define EEPROM_CALIBRATION_STATUS 4087
|
||||
#define EEPROM_BABYSTEP_Z0 4085
|
||||
#define EEPROM_FILAMENTUSED 4081
|
||||
// uint32_t
|
||||
#define EEPROM_TOTALTIME 4077
|
||||
|
|
@ -454,53 +370,55 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP
|
|||
// The offsets are saved as 16bit signed int, scaled to tenths of microns.
|
||||
#define EEPROM_BED_CALIBRATION_Z_JITTER (EEPROM_BED_CALIBRATION_VEC_Y-2*8)
|
||||
#define EEPROM_FARM_MODE (EEPROM_BED_CALIBRATION_Z_JITTER-1)
|
||||
#define EEPROM_FREE_NR1 (EEPROM_FARM_MODE-1) // uint8_t
|
||||
#define _EEPROM_FREE_NR2_ (EEPROM_FREE_NR1 - 2) // int16_t
|
||||
#define EEPROM_FREE_NR1 (EEPROM_FARM_MODE-1)
|
||||
#define EEPROM_FARM_NUMBER (EEPROM_FREE_NR1-2)
|
||||
|
||||
// Correction of the bed leveling, in micrometers.
|
||||
// Maximum 50 micrometers allowed.
|
||||
// Bed correction is valid if set to 1. If set to zero or 255, the successive 4 bytes are invalid.
|
||||
#define EEPROM_BED_CORRECTION_VALID (_EEPROM_FREE_NR2_ - 1)
|
||||
#define EEPROM_BED_CORRECTION_VALID (EEPROM_FARM_NUMBER-1)
|
||||
#define EEPROM_BED_CORRECTION_LEFT (EEPROM_BED_CORRECTION_VALID-1)
|
||||
#define EEPROM_BED_CORRECTION_RIGHT (EEPROM_BED_CORRECTION_LEFT-1)
|
||||
#define EEPROM_BED_CORRECTION_FRONT (EEPROM_BED_CORRECTION_RIGHT-1)
|
||||
#define EEPROM_BED_CORRECTION_REAR (EEPROM_BED_CORRECTION_FRONT-1)
|
||||
#define EEPROM_TOSHIBA_FLASH_AIR_COMPATIBLITY (EEPROM_BED_CORRECTION_REAR-1) // bool
|
||||
|
||||
#define _EEPROM_FREE_NR3_ (EEPROM_TOSHIBA_FLASH_AIR_COMPATIBLITY - 1) // uint8_t
|
||||
|
||||
#define EEPROM_PROBE_TEMP_SHIFT (_EEPROM_FREE_NR3_ - 2*5) //5 x int for storing pinda probe temp shift relative to 50 C; unit: motor steps
|
||||
#define EEPROM_TOSHIBA_FLASH_AIR_COMPATIBLITY (EEPROM_BED_CORRECTION_REAR-1)
|
||||
#define EEPROM_PRINT_FLAG (EEPROM_TOSHIBA_FLASH_AIR_COMPATIBLITY-1)
|
||||
#define EEPROM_PROBE_TEMP_SHIFT (EEPROM_PRINT_FLAG - 2*5) //5 x int for storing pinda probe temp shift relative to 50 C; unit: motor steps
|
||||
#define EEPROM_TEMP_CAL_ACTIVE (EEPROM_PROBE_TEMP_SHIFT - 1)
|
||||
#define _EEPROM_FREE_NR6_ (EEPROM_TEMP_CAL_ACTIVE - 2*4) //4 x int
|
||||
#define EEPROM_CALIBRATION_STATUS_PINDA (_EEPROM_FREE_NR6_ - 1) //0 - not calibrated; 1 - calibrated
|
||||
#define EEPROM_BOWDEN_LENGTH (EEPROM_TEMP_CAL_ACTIVE - 2*4) //4 x int for bowden lengths for multimaterial
|
||||
#define EEPROM_CALIBRATION_STATUS_PINDA (EEPROM_BOWDEN_LENGTH - 1) //0 - not calibrated; 1 - calibrated
|
||||
#define EEPROM_UVLO (EEPROM_CALIBRATION_STATUS_PINDA - 1) //1 - uvlo during print
|
||||
#define EEPROM_UVLO_CURRENT_POSITION (EEPROM_UVLO-2*4) // 2 x float for current_position in X and Y axes
|
||||
#define EEPROM_FILENAME (EEPROM_UVLO_CURRENT_POSITION - 8) //8chars to store filename without extension
|
||||
#define EEPROM_FILE_POSITION (EEPROM_FILENAME - 4) //32 bit for uint32_t file position
|
||||
#define EEPROM_UVLO_CURRENT_POSITION_Z (EEPROM_FILE_POSITION - 4) //float for current position in Z
|
||||
#define EEPROM_UVLO_UNUSED_001 (EEPROM_UVLO_CURRENT_POSITION_Z - 1) // uint8_t (unused)
|
||||
#define EEPROM_UVLO_TARGET_BED (EEPROM_UVLO_UNUSED_001 - 1)
|
||||
#define EEPROM_UVLO_FEEDRATE (EEPROM_UVLO_TARGET_BED - 2) //uint16_t
|
||||
#define EEPROM_UVLO_FAN_SPEED (EEPROM_UVLO_FEEDRATE - 1)
|
||||
#define EEPROM_FAN_CHECK_ENABLED (EEPROM_UVLO_FAN_SPEED - 1)
|
||||
#define EEPROM_UVLO_MESH_BED_LEVELING (EEPROM_FAN_CHECK_ENABLED - 9*2)
|
||||
|
||||
#define EEPROM_UVLO (EEPROM_CALIBRATION_STATUS_PINDA - 1) // uint8_t
|
||||
#define EEPROM_UVLO_CURRENT_POSITION (EEPROM_UVLO-2*4) // 2 x float for current_position in X and Y axes
|
||||
#define EEPROM_FILENAME (EEPROM_UVLO_CURRENT_POSITION - 8) //8chars to store filename without extension
|
||||
#define EEPROM_FILE_POSITION (EEPROM_FILENAME - 4) //32 bit for uint32_t file position
|
||||
#define EEPROM_UVLO_CURRENT_POSITION_Z (EEPROM_FILE_POSITION - 4) //float for current position in Z
|
||||
#define EEPROM_UVLO_PRINT_TYPE (EEPROM_UVLO_CURRENT_POSITION_Z - 1) // uint8_t
|
||||
#define EEPROM_UVLO_TARGET_BED (EEPROM_UVLO_PRINT_TYPE - 1)
|
||||
#define EEPROM_UVLO_FEEDRATE (EEPROM_UVLO_TARGET_BED - 2) //uint16_t
|
||||
#define EEPROM_UVLO_FAN_SPEED (EEPROM_UVLO_FEEDRATE - 1)
|
||||
#define EEPROM_FAN_CHECK_ENABLED (EEPROM_UVLO_FAN_SPEED - 1)
|
||||
#define EEPROM_UVLO_Z_MICROSTEPS (EEPROM_UVLO_MESH_BED_LEVELING - 2) // uint16_t (could be removed)
|
||||
#define EEPROM_UVLO_E_ABS (EEPROM_UVLO_Z_MICROSTEPS - 1)
|
||||
#define EEPROM_UVLO_CURRENT_POSITION_E (EEPROM_UVLO_E_ABS - 4) //float for current position in E
|
||||
|
||||
#define _EEPROM_FREE_NR7_ (EEPROM_FAN_CHECK_ENABLED - 9*2) // 9 x uint16_t
|
||||
#define _EEPROM_FREE_NR8_ (_EEPROM_FREE_NR7_ - 2) // uint16_t
|
||||
|
||||
#define EEPROM_UVLO_E_ABS (_EEPROM_FREE_NR8_ - 1) // uint8_t
|
||||
#define EEPROM_UVLO_CURRENT_POSITION_E (EEPROM_UVLO_E_ABS - 4) // float
|
||||
#define EEPROM_UVLO_SAVED_SEGMENT_IDX (EEPROM_UVLO_CURRENT_POSITION_E - 2) //uint16_t
|
||||
|
||||
#define EEPROM_FREE_NR4 (EEPROM_UVLO_SAVED_SEGMENT_IDX - 1) // uint8_t
|
||||
#define EEPROM_FREE_NR5 (EEPROM_FREE_NR4 - 1) // uint8_t
|
||||
|
||||
#define EEPROM_CRASH_DET (EEPROM_FREE_NR5 - 1) // uint8_t
|
||||
#define EEPROM_CRASH_COUNT_Y (EEPROM_CRASH_DET - 1) // uint8_t
|
||||
#define EEPROM_FSENSOR (EEPROM_CRASH_COUNT_Y - 1) // uint8_t
|
||||
#define EEPROM_CRASH_COUNT_X (EEPROM_FSENSOR - 1) // uint8_t
|
||||
#define EEPROM_FERROR_COUNT (EEPROM_CRASH_COUNT_X - 1) // uint8_t
|
||||
#define EEPROM_POWER_COUNT (EEPROM_FERROR_COUNT - 1) // uint8_t
|
||||
#define EEPROM_FREE_NR2 (EEPROM_UVLO_CURRENT_POSITION_E - 1) // FREE EEPROM SPACE
|
||||
#define EEPROM_FREE_NR3 (EEPROM_FREE_NR2 - 1) // FREE EEPROM SPACE
|
||||
#define EEPROM_FREE_NR4 (EEPROM_FREE_NR3 - 1) // FREE EEPROM SPACE
|
||||
#define EEPROM_FREE_NR5 (EEPROM_FREE_NR4 - 1) // FREE EEPROM SPACE
|
||||
// Crash detection mode EEPROM setting
|
||||
#define EEPROM_CRASH_DET (EEPROM_FREE_NR5 - 1) // uint8 (orig EEPROM_UVLO_MESH_BED_LEVELING-12)
|
||||
// Crash detection counter Y (last print)
|
||||
#define EEPROM_CRASH_COUNT_Y (EEPROM_CRASH_DET - 1) // uint8 (orig EEPROM_UVLO_MESH_BED_LEVELING-15)
|
||||
// Filament sensor on/off EEPROM setting
|
||||
#define EEPROM_FSENSOR (EEPROM_CRASH_COUNT_Y - 1) // uint8 (orig EEPROM_UVLO_MESH_BED_LEVELING-14)
|
||||
// Crash detection counter X (last print)
|
||||
#define EEPROM_CRASH_COUNT_X (EEPROM_FSENSOR - 1) // uint8 (orig EEPROM_UVLO_MESH_BED_LEVELING-15)
|
||||
// Filament runout/error coutner (last print)
|
||||
#define EEPROM_FERROR_COUNT (EEPROM_CRASH_COUNT_X - 1) // uint8 (orig EEPROM_UVLO_MESH_BED_LEVELING-16)
|
||||
// Power loss errors (last print)
|
||||
#define EEPROM_POWER_COUNT (EEPROM_FERROR_COUNT - 1) // uint8 (orig EEPROM_UVLO_MESH_BED_LEVELING-17)
|
||||
|
||||
#define EEPROM_XYZ_CAL_SKEW (EEPROM_POWER_COUNT - 4) // float for skew backup
|
||||
#define EEPROM_WIZARD_ACTIVE (EEPROM_XYZ_CAL_SKEW - 1) // 0: wizard not active, 1: wizard active, 2: wizard active without yes/no = forced calibrate Z after shipping/service prep.
|
||||
|
|
@ -524,7 +442,7 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP
|
|||
#define EEPROM_POWER_COUNT_TOT (EEPROM_FERROR_COUNT_TOT - 2) // uint16
|
||||
|
||||
////////////////////////////////////////
|
||||
// TMC2130 Accurate sensorless homing
|
||||
// TMC2130 Accurate sensorless homing
|
||||
|
||||
// X-axis home origin (stepper phase in microsteps, 0..63 for 16ustep resolution)
|
||||
#define EEPROM_TMC2130_HOME_X_ORIGIN (EEPROM_POWER_COUNT_TOT - 1) // uint8
|
||||
|
|
@ -576,25 +494,24 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP
|
|||
|
||||
// Sound Mode
|
||||
#define EEPROM_SOUND_MODE (EEPROM_UVLO_TARGET_HOTEND-1) // uint8
|
||||
#define EEPROM_SPOOL_JOIN (EEPROM_SOUND_MODE-1) //bool
|
||||
#define EEPROM_AUTO_DEPLETE (EEPROM_SOUND_MODE-1) //bool
|
||||
|
||||
#define EEPROM_FSENS_RUNOUT_ENABLED (EEPROM_SPOOL_JOIN - 1) //bool
|
||||
#define EEPROM_FSENS_OQ_MEASS_ENABLED (EEPROM_AUTO_DEPLETE - 1) //bool
|
||||
|
||||
#define EEPROM_MMU_FAIL_TOT (EEPROM_FSENS_RUNOUT_ENABLED - 2) //uint16_t
|
||||
#define EEPROM_MMU_FAIL_TOT (EEPROM_FSENS_OQ_MEASS_ENABLED - 2) //uint16_t
|
||||
#define EEPROM_MMU_FAIL (EEPROM_MMU_FAIL_TOT - 1) //uint8_t
|
||||
|
||||
#define EEPROM_MMU_LOAD_FAIL_TOT (EEPROM_MMU_FAIL - 2) // uint16_t
|
||||
#define EEPROM_MMU_LOAD_FAIL (EEPROM_MMU_LOAD_FAIL_TOT - 1) // uint8_t
|
||||
#define EEPROM_MMU_CUTTER_ENABLED (EEPROM_MMU_LOAD_FAIL - 1) // bool
|
||||
#define EEPROM_MMU_LOAD_FAIL_TOT (EEPROM_MMU_FAIL - 2) //uint16_t
|
||||
#define EEPROM_MMU_LOAD_FAIL (EEPROM_MMU_LOAD_FAIL_TOT - 1) //uint8_t
|
||||
#define EEPROM_MMU_CUTTER_ENABLED (EEPROM_MMU_LOAD_FAIL - 1)
|
||||
#define EEPROM_UVLO_MESH_BED_LEVELING_FULL (EEPROM_MMU_CUTTER_ENABLED - 12*12*2) //allow 12 calibration points for future expansion
|
||||
|
||||
#define _EEPROM_FREE_NR9_ (EEPROM_UVLO_MESH_BED_LEVELING_FULL-1) // uint8_t
|
||||
|
||||
#define EEPROM_MBL_MAGNET_ELIMINATION (_EEPROM_FREE_NR9_ - 1)
|
||||
#define EEPROM_MBL_TYPE (EEPROM_UVLO_MESH_BED_LEVELING_FULL-1) //uint8_t for mesh bed leveling precision
|
||||
#define EEPROM_MBL_MAGNET_ELIMINATION (EEPROM_MBL_TYPE -1)
|
||||
#define EEPROM_MBL_POINTS_NR (EEPROM_MBL_MAGNET_ELIMINATION -1) //uint8_t number of points in one exis for mesh bed leveling
|
||||
#define EEPROM_MBL_PROBE_NR (EEPROM_MBL_POINTS_NR-1) //number of measurements for each point
|
||||
|
||||
#define EEPROM_MMU_STEALTH (EEPROM_MBL_PROBE_NR-1) // bool
|
||||
#define EEPROM_MMU_STEALTH (EEPROM_MBL_PROBE_NR-1)
|
||||
|
||||
#define EEPROM_CHECK_MODE (EEPROM_MMU_STEALTH-1) // uint8
|
||||
#define EEPROM_NOZZLE_DIAMETER (EEPROM_CHECK_MODE-1) // uint8
|
||||
|
|
@ -609,8 +526,8 @@ static Sheets * const EEPROM_Sheets_base = (Sheets*)(EEPROM_SHEETS_BASE);
|
|||
#define EEPROM_FSENSOR_PCB (EEPROM_SHEETS_BASE-1) // uint8
|
||||
#define EEPROM_FSENSOR_ACTION_NA (EEPROM_FSENSOR_PCB-1) // uint8
|
||||
|
||||
#define EEPROM_UVLO_SAVED_START_POSITION (EEPROM_FSENSOR_ACTION_NA - 4*4) // 4 x float for saved start position for all axes
|
||||
#define EEPROM_UVLO_FEEDMULTIPLY (EEPROM_UVLO_SAVED_START_POSITION - 2) // uint16_t for feedmultiply
|
||||
#define EEPROM_UVLO_SAVED_TARGET (EEPROM_FSENSOR_ACTION_NA - 4*4) // 4 x float for saved target for all axes
|
||||
#define EEPROM_UVLO_FEEDMULTIPLY (EEPROM_UVLO_SAVED_TARGET - 2) // uint16_t for feedmultiply
|
||||
|
||||
#define EEPROM_BACKLIGHT_LEVEL_HIGH (EEPROM_UVLO_FEEDMULTIPLY-1) // uint8
|
||||
#define EEPROM_BACKLIGHT_LEVEL_LOW (EEPROM_BACKLIGHT_LEVEL_HIGH-1) // uint8
|
||||
|
|
@ -633,43 +550,8 @@ static Sheets * const EEPROM_Sheets_base = (Sheets*)(EEPROM_SHEETS_BASE);
|
|||
#define EEPROM_ECOOL_ENABLE (EEPROM_JOB_ID-1) // uint8_t
|
||||
#define EEPROM_FW_CRASH_FLAG (EEPROM_ECOOL_ENABLE-1) // uint8_t
|
||||
|
||||
#define EEPROM_THERMAL_MODEL_ENABLE (EEPROM_FW_CRASH_FLAG-1) // uint8_t
|
||||
#define EEPROM_THERMAL_MODEL_P (EEPROM_THERMAL_MODEL_ENABLE-4) // float
|
||||
#define EEPROM_THERMAL_MODEL_C (EEPROM_THERMAL_MODEL_P-4) // float
|
||||
#define EEPROM_THERMAL_MODEL_R (EEPROM_THERMAL_MODEL_C-4*16) // float[16]
|
||||
#define EEPROM_THERMAL_MODEL_Ta_corr (EEPROM_THERMAL_MODEL_R-4) // float
|
||||
#define EEPROM_THERMAL_MODEL_W (EEPROM_THERMAL_MODEL_Ta_corr-4) // float
|
||||
#define EEPROM_THERMAL_MODEL_E (EEPROM_THERMAL_MODEL_W-4) // float
|
||||
|
||||
#define EEPROM_FSENSOR_JAM_DETECTION (EEPROM_THERMAL_MODEL_E-1) // uint8_t
|
||||
#define EEPROM_MMU_ENABLED (EEPROM_FSENSOR_JAM_DETECTION-1) // uint8_t
|
||||
#define EEPROM_MMU_MATERIAL_CHANGES (EEPROM_MMU_ENABLED-4) // uint32_t
|
||||
#define EEPROM_HEAT_BED_ON_LOAD_FILAMENT (EEPROM_MMU_MATERIAL_CHANGES-1) //uint8
|
||||
#define EEPROM_CALIBRATION_STATUS_V2 (EEPROM_HEAT_BED_ON_LOAD_FILAMENT-1) //uint8
|
||||
|
||||
#define EEPROM_THERMAL_MODEL_U (EEPROM_CALIBRATION_STATUS_V2-4) //float
|
||||
#define EEPROM_THERMAL_MODEL_V (EEPROM_THERMAL_MODEL_U-4) //float
|
||||
#define EEPROM_THERMAL_MODEL_D (EEPROM_THERMAL_MODEL_V-4) //float
|
||||
#define EEPROM_THERMAL_MODEL_L (EEPROM_THERMAL_MODEL_D-2) //uint16_t
|
||||
#define EEPROM_THERMAL_MODEL_VER (EEPROM_THERMAL_MODEL_L-1) //uint8_t
|
||||
|
||||
#define EEPROM_KILL_MESSAGE (EEPROM_THERMAL_MODEL_VER-2) //PGM_P
|
||||
#define EEPROM_KILL_PENDING_FLAG (EEPROM_KILL_MESSAGE-1) //uint8
|
||||
#define EEPROM_FILENAME_EXTENSION (EEPROM_KILL_PENDING_FLAG - 3) // 3 x char
|
||||
#define EEPROM_CUSTOM_MENDEL_NAME (EEPROM_FILENAME_EXTENSION-17) //char[17]
|
||||
#define EEPROM_UVLO_Z_LIFTED (EEPROM_CUSTOM_MENDEL_NAME-1) //bool
|
||||
#define EEPROM_UVLO_EXTRUDE_MINTEMP (EEPROM_UVLO_Z_LIFTED-2) //uint16_t
|
||||
#define EEPROM_UVLO_ACCELL_MM_S2_NORMAL (EEPROM_UVLO_EXTRUDE_MINTEMP-4*4) // 4 x float
|
||||
#define EEPROM_UVLO_ACCELL_MM_S2_SILENT (EEPROM_UVLO_ACCELL_MM_S2_NORMAL-4*4) // 4 x uint32_t
|
||||
#define EEPROM_UVLO_MAX_FEEDRATE_NORMAL (EEPROM_UVLO_ACCELL_MM_S2_SILENT-4*4) // 4 x uint32_t
|
||||
#define EEPROM_UVLO_MAX_FEEDRATE_SILENT (EEPROM_UVLO_MAX_FEEDRATE_NORMAL-4*4) // 4 x float
|
||||
#define EEPROM_UVLO_MIN_FEEDRATE (EEPROM_UVLO_MAX_FEEDRATE_SILENT-4) //float
|
||||
#define EEPROM_UVLO_MIN_TRAVEL_FEEDRATE (EEPROM_UVLO_MIN_FEEDRATE-4) //float
|
||||
#define EEPROM_UVLO_MIN_SEGMENT_TIME_US (EEPROM_UVLO_MIN_TRAVEL_FEEDRATE-4) //uint32_t
|
||||
#define EEPROM_UVLO_MAX_JERK (EEPROM_UVLO_MIN_SEGMENT_TIME_US-4*4) // 4 x float
|
||||
#define EEPROM_CHECK_FILAMENT (EEPROM_UVLO_MAX_JERK-1) // uint8_t
|
||||
//This is supposed to point to last item to allow EEPROM overrun check. Please update when adding new items.
|
||||
#define EEPROM_LAST_ITEM EEPROM_CHECK_FILAMENT
|
||||
#define EEPROM_LAST_ITEM EEPROM_FW_CRASH_FLAG
|
||||
// !!!!!
|
||||
// !!!!! this is end of EEPROM section ... all updates MUST BE inserted before this mark !!!!!
|
||||
// !!!!!
|
||||
|
|
@ -702,7 +584,7 @@ enum
|
|||
|
||||
#ifdef __cplusplus
|
||||
void eeprom_init();
|
||||
void eeprom_adjust_bed_reset();
|
||||
bool eeprom_is_sheet_initialized(uint8_t sheet_num);
|
||||
struct SheetName
|
||||
{
|
||||
char c[sizeof(Sheet::name) + 1];
|
||||
|
|
@ -710,50 +592,6 @@ struct SheetName
|
|||
void eeprom_default_sheet_name(uint8_t index, SheetName &sheetName);
|
||||
int8_t eeprom_next_initialized_sheet(int8_t sheet);
|
||||
void eeprom_switch_to_next_sheet();
|
||||
bool eeprom_is_sheet_initialized(uint8_t sheet_num);
|
||||
|
||||
bool eeprom_is_initialized_block(const void *__p, size_t __n);
|
||||
void eeprom_update_block_P(const void *__src, void *__dst, size_t __n);
|
||||
void eeprom_toggle(uint8_t *__p);
|
||||
|
||||
void eeprom_increment_byte(uint8_t *__p);
|
||||
void eeprom_increment_word(uint16_t *__p);
|
||||
void eeprom_increment_dword(uint32_t *__p);
|
||||
|
||||
void eeprom_add_byte(uint8_t *__p, uint8_t add);
|
||||
void eeprom_add_word(uint16_t *__p, uint16_t add);
|
||||
void eeprom_add_dword(uint32_t *__p, uint32_t add);
|
||||
|
||||
uint8_t eeprom_init_default_byte(uint8_t *__p, uint8_t def);
|
||||
uint16_t eeprom_init_default_word(uint16_t *__p, uint16_t def);
|
||||
uint32_t eeprom_init_default_dword(uint32_t *__p, uint32_t def);
|
||||
void eeprom_init_default_float(float *__p, float def);
|
||||
void eeprom_init_default_block(void *__p, size_t __n, const void *def);
|
||||
void eeprom_init_default_block_P(void *__p, size_t __n, const void *def);
|
||||
/// Updates eeprom byte and notifies the changed eeprom address (just the address!) onto the serial line
|
||||
#ifndef DEBUG_EEPROM_CHANGES
|
||||
void eeprom_write_byte_notify(uint8_t *dst, uint8_t value);
|
||||
void eeprom_update_byte_notify(uint8_t *dst, uint8_t value);
|
||||
void eeprom_write_word_notify(uint16_t *dst, uint16_t value);
|
||||
void eeprom_update_word_notify(uint16_t *dst, uint16_t value);
|
||||
void eeprom_write_dword_notify(uint32_t *dst, uint32_t value);
|
||||
void eeprom_update_dword_notify(uint32_t *dst, uint32_t value);
|
||||
void eeprom_write_float_notify(float *dst, float value);
|
||||
void eeprom_update_float_notify(float *dst, float value);
|
||||
void eeprom_write_block_notify(const void *__src, void *__dst , size_t __size);
|
||||
void eeprom_update_block_notify(const void *__src, void *__dst, size_t __size);
|
||||
#else
|
||||
void eeprom_write_byte_notify(uint8_t *dst, uint8_t value, bool active = true);
|
||||
void eeprom_update_byte_notify(uint8_t *dst, uint8_t value, bool active = true);
|
||||
void eeprom_write_word_notify(uint16_t *dst, uint16_t value, bool active = true);
|
||||
void eeprom_update_word_notify(uint16_t *dst, uint16_t value, bool active = true);
|
||||
void eeprom_write_dword_notify(uint32_t *dst, uint32_t value, bool active = true);
|
||||
void eeprom_update_dword_notify(uint32_t *dst, uint32_t value, bool active = true);
|
||||
void eeprom_write_float_notify(float *dst, float value, bool active = true);
|
||||
void eeprom_update_float_notify(float *dst, float value, bool active = true);
|
||||
void eeprom_write_block_notify(const void *__src, void *__dst , size_t __size, bool active = true);
|
||||
void eeprom_update_block_notify(const void *__src, void *__dst, size_t __size , bool active = true);
|
||||
#endif //DEBUG_EEPROM_CHANGES
|
||||
#endif
|
||||
|
||||
#endif // EEPROM_H
|
||||
|
|
|
|||
|
|
@ -1,362 +0,0 @@
|
|||
// fan control and check
|
||||
#include "fancheck.h"
|
||||
#include "ultralcd.h"
|
||||
#include "sound.h"
|
||||
#include "messages.h"
|
||||
#include "temperature.h"
|
||||
#include "stepper.h"
|
||||
#include "stopwatch.h"
|
||||
|
||||
#define FAN_CHECK_PERIOD 5000 //5s
|
||||
#define FAN_CHECK_DURATION 100 //100ms
|
||||
|
||||
//Macro for print fan speed
|
||||
#define FAN_PULSE_WIDTH_LIMIT ((fanSpeed > 100) ? 3 : 4) //time in ms
|
||||
|
||||
#ifdef FANCHECK
|
||||
volatile uint8_t fan_check_error = EFCE_OK;
|
||||
#endif
|
||||
|
||||
#if (defined(FANCHECK) && defined(TACH_1) && (TACH_1 >-1))
|
||||
static uint32_t t_fan_rising_edge;
|
||||
#endif // #if (defined(FANCHECK) && defined(TACH_1) && (TACH_1 >-1))
|
||||
|
||||
#if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1)
|
||||
#ifdef EXTRUDER_ALTFAN_DETECT
|
||||
static struct
|
||||
{
|
||||
uint8_t isAltfan : 1;
|
||||
uint8_t altfanOverride : 1;
|
||||
} altfanStatus;
|
||||
#endif //EXTRUDER_ALTFAN_DETECT
|
||||
|
||||
unsigned long extruder_autofan_last_check = _millis();
|
||||
bool fan_measuring = false;
|
||||
static uint8_t fanState = 0;
|
||||
#endif
|
||||
|
||||
#if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1)
|
||||
#if defined(FAN_PIN) && FAN_PIN > -1
|
||||
#if EXTRUDER_0_AUTO_FAN_PIN == FAN_PIN
|
||||
#error "You cannot set EXTRUDER_0_AUTO_FAN_PIN equal to FAN_PIN"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void setExtruderAutoFanState(uint8_t state)
|
||||
{
|
||||
//If bit 1 is set (0x02), then the hotend fan speed won't be adjusted according to temperature. Useful for forcing
|
||||
//the fan to either On or Off during certain tests/errors.
|
||||
|
||||
fanState = state;
|
||||
newFanSpeed = 0;
|
||||
if (fanState & 0x01)
|
||||
{
|
||||
#ifdef EXTRUDER_ALTFAN_DETECT
|
||||
if (altfanStatus.isAltfan && !altfanStatus.altfanOverride) newFanSpeed = EXTRUDER_ALTFAN_SPEED_SILENT;
|
||||
else newFanSpeed = EXTRUDER_AUTO_FAN_SPEED;
|
||||
#else //EXTRUDER_ALTFAN_DETECT
|
||||
newFanSpeed = EXTRUDER_AUTO_FAN_SPEED;
|
||||
#endif //EXTRUDER_ALTFAN_DETECT
|
||||
}
|
||||
timer4_set_fan0(newFanSpeed);
|
||||
}
|
||||
|
||||
#if (defined(FANCHECK) && (((defined(TACH_0) && (TACH_0 >-1)) || (defined(TACH_1) && (TACH_1 > -1)))))
|
||||
|
||||
void countFanSpeed()
|
||||
{
|
||||
//SERIAL_ECHOPGM("edge counter 1:"); MYSERIAL.println(fan_edge_counter[1]);
|
||||
fan_speed[0] = (fan_edge_counter[0] * (float(250) / (_millis() - extruder_autofan_last_check)));
|
||||
fan_speed[1] = (fan_edge_counter[1] * (float(250) / (_millis() - extruder_autofan_last_check)));
|
||||
/*SERIAL_ECHOPGM("time interval: "); MYSERIAL.println(_millis() - extruder_autofan_last_check);
|
||||
SERIAL_ECHOPGM("hotend fan speed:"); MYSERIAL.print(fan_speed[0]); SERIAL_ECHOPGM("; edge counter:"); MYSERIAL.println(fan_edge_counter[0]);
|
||||
SERIAL_ECHOPGM("print fan speed:"); MYSERIAL.print(fan_speed[1]); SERIAL_ECHOPGM("; edge counter:"); MYSERIAL.println(fan_edge_counter[1]);
|
||||
SERIAL_ECHOLNPGM(" ");*/
|
||||
fan_edge_counter[0] = 0;
|
||||
fan_edge_counter[1] = 0;
|
||||
}
|
||||
|
||||
//! Prints serialMsg to serial port, displays lcdMsg onto the LCD and beeps.
|
||||
//! Extracted from fanSpeedError to save some space.
|
||||
//! @param serialMsg pointer into PROGMEM, this text will be printed to the serial port
|
||||
//! @param lcdMsg pointer into PROGMEM, this text will be printed onto the LCD
|
||||
static void fanSpeedErrorBeep(const char *serialMsg, const char *lcdMsg){
|
||||
SERIAL_ECHOLNRPGM(serialMsg);
|
||||
if (get_message_level() == 0) {
|
||||
Sound_MakeCustom(200,0,true);
|
||||
LCD_ALERTMESSAGERPGM(lcdMsg);
|
||||
}
|
||||
}
|
||||
|
||||
void fanSpeedError(unsigned char _fan) {
|
||||
if (fan_check_error == EFCE_REPORTED) return;
|
||||
fan_check_error = EFCE_REPORTED;
|
||||
|
||||
if (printJobOngoing()) {
|
||||
// A print is ongoing, pause the print normally
|
||||
if(!printingIsPaused()) {
|
||||
if (usb_timer.running())
|
||||
lcd_pause_usb_print();
|
||||
else
|
||||
lcd_pause_print();
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Nothing is going on, but still turn off heaters and report the error
|
||||
setTargetHotend(0);
|
||||
heating_status = HeatingStatus::NO_HEATING;
|
||||
}
|
||||
switch (_fan) {
|
||||
case 0: // extracting the same code from case 0 and case 1 into a function saves 72B
|
||||
fanSpeedErrorBeep(PSTR("Hotend fan speed is lower than expected"), MSG_FANCHECK_HOTEND);
|
||||
break;
|
||||
case 1:
|
||||
fanSpeedErrorBeep(PSTR("Print fan speed is lower than expected"), MSG_FANCHECK_PRINT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void checkFanSpeed()
|
||||
{
|
||||
uint8_t max_fan_errors[2];
|
||||
#ifdef FAN_SOFT_PWM
|
||||
max_fan_errors[1] = 3; // 15 seconds (Print fan)
|
||||
max_fan_errors[0] = 2; // 10 seconds (Hotend fan)
|
||||
#else //FAN_SOFT_PWM
|
||||
max_fan_errors[1] = 15; // 15 seconds (Print fan)
|
||||
max_fan_errors[0] = 5; // 5 seconds (Hotend fan)
|
||||
#endif //FAN_SOFT_PWM
|
||||
|
||||
if(fans_check_enabled)
|
||||
fans_check_enabled = (eeprom_read_byte((uint8_t*)EEPROM_FAN_CHECK_ENABLED) > 0);
|
||||
static uint8_t fan_speed_errors[2] = { 0,0 };
|
||||
#if (defined(FANCHECK) && defined(TACH_0) && (TACH_0 >-1))
|
||||
if ((fan_speed[0] < 20) && (current_temperature[0] > EXTRUDER_AUTO_FAN_TEMPERATURE)){ fan_speed_errors[0]++;}
|
||||
else fan_speed_errors[0] = 0;
|
||||
#endif
|
||||
#if (defined(FANCHECK) && defined(TACH_1) && (TACH_1 >-1))
|
||||
if ((fan_speed[1] < 5) && ((blocks_queued() ? block_buffer[block_buffer_tail].fan_speed : fanSpeed) > MIN_PRINT_FAN_SPEED)) fan_speed_errors[1]++;
|
||||
else fan_speed_errors[1] = 0;
|
||||
#endif
|
||||
|
||||
// drop the fan_check_error flag when both fans are ok
|
||||
if( fan_speed_errors[0] == 0 && fan_speed_errors[1] == 0 && fan_check_error == EFCE_REPORTED){
|
||||
// we may even send some info to the LCD from here
|
||||
fan_check_error = EFCE_FIXED;
|
||||
}
|
||||
if ((fan_check_error == EFCE_FIXED) && !printer_active()){
|
||||
fan_check_error = EFCE_OK; //if the issue is fixed while the printer is doing nothing, reenable processing immediately.
|
||||
lcd_reset_alert_level(); //for another fan speed error
|
||||
lcd_setstatuspgm(MSG_WELCOME); // Reset the status line message to visually show the error is gone
|
||||
}
|
||||
if (fans_check_enabled && (fan_check_error != EFCE_REPORTED))
|
||||
{
|
||||
for (uint8_t fan = 0; fan < 2; fan++)
|
||||
{
|
||||
if (fan_speed_errors[fan] > max_fan_errors[fan])
|
||||
{
|
||||
fan_speed_errors[fan] = 0;
|
||||
fanSpeedError(fan);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif //(defined(TACH_0) && TACH_0 >-1) || (defined(TACH_1) && TACH_1 > -1)
|
||||
|
||||
#if (defined(FANCHECK) && defined(TACH_1) && (TACH_1 >-1))
|
||||
void setup_fan_interrupt() {
|
||||
//INT7
|
||||
DDRE &= ~(1 << 7); //input pin
|
||||
PORTE &= ~(1 << 7); //no internal pull-up
|
||||
|
||||
//start with sensing rising edge
|
||||
EICRB &= ~(1 << 6);
|
||||
EICRB |= (1 << 7);
|
||||
|
||||
//enable INT7 interrupt
|
||||
EIMSK |= (1 << 7);
|
||||
}
|
||||
|
||||
// The fan interrupt is triggered at maximum 325Hz (may be a bit more due to component tollerances),
|
||||
// and it takes 4.24 us to process (the interrupt invocation overhead not taken into account).
|
||||
ISR(INT7_vect) {
|
||||
//measuring speed now works for fanSpeed > 18 (approximately), which is sufficient because MIN_PRINT_FAN_SPEED is higher
|
||||
#ifdef FAN_SOFT_PWM
|
||||
if (!fan_measuring || (fanSpeedSoftPwm < MIN_PRINT_FAN_SPEED)) return;
|
||||
#else //FAN_SOFT_PWM
|
||||
if (fanSpeed < MIN_PRINT_FAN_SPEED) return;
|
||||
#endif //FAN_SOFT_PWM
|
||||
|
||||
if ((1 << 6) & EICRB) { //interrupt was triggered by rising edge
|
||||
t_fan_rising_edge = millis_nc();
|
||||
}
|
||||
else { //interrupt was triggered by falling edge
|
||||
if ((millis_nc() - t_fan_rising_edge) >= FAN_PULSE_WIDTH_LIMIT) {//this pulse was from sensor and not from pwm
|
||||
fan_edge_counter[1] += 2; //we are currently counting all edges so lets count two edges for one pulse
|
||||
}
|
||||
}
|
||||
EICRB ^= (1 << 6); //change edge
|
||||
}
|
||||
#endif //(defined(FANCHECK) && defined(TACH_1) && (TACH_1 >-1))
|
||||
|
||||
#ifdef EXTRUDER_ALTFAN_DETECT
|
||||
ISR(INT6_vect) {
|
||||
fan_edge_counter[0]++;
|
||||
}
|
||||
|
||||
bool extruder_altfan_detect()
|
||||
{
|
||||
// override isAltFan setting for detection
|
||||
altfanStatus.isAltfan = 0;
|
||||
|
||||
// During initialisation, use the EEPROM value
|
||||
altfanStatus.altfanOverride = eeprom_init_default_byte((uint8_t*)EEPROM_ALTFAN_OVERRIDE, 0);
|
||||
setExtruderAutoFanState(3);
|
||||
|
||||
SET_INPUT(TACH_0);
|
||||
CRITICAL_SECTION_START;
|
||||
EICRB &= ~(1 << ISC61);
|
||||
EICRB |= (1 << ISC60);
|
||||
EIMSK |= (1 << INT6);
|
||||
fan_edge_counter[0] = 0;
|
||||
CRITICAL_SECTION_END;
|
||||
extruder_autofan_last_check = _millis();
|
||||
|
||||
_delay(1000);
|
||||
|
||||
EIMSK &= ~(1 << INT6);
|
||||
|
||||
countFanSpeed();
|
||||
|
||||
// restore fan state
|
||||
altfanStatus.isAltfan = fan_speed[0] > 100;
|
||||
setExtruderAutoFanState(1);
|
||||
|
||||
return altfanStatus.isAltfan;
|
||||
}
|
||||
|
||||
void altfanOverride_toggle()
|
||||
{
|
||||
altfanStatus.altfanOverride = !altfanStatus.altfanOverride;
|
||||
eeprom_update_byte_notify((uint8_t *)EEPROM_ALTFAN_OVERRIDE, altfanStatus.altfanOverride);
|
||||
}
|
||||
|
||||
bool altfanOverride_get()
|
||||
{
|
||||
return altfanStatus.altfanOverride;
|
||||
}
|
||||
|
||||
#endif //EXTRUDER_ALTFAN_DETECT
|
||||
|
||||
void checkExtruderAutoFans()
|
||||
{
|
||||
#if defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1
|
||||
if (!(fanState & 0x02))
|
||||
{
|
||||
fanState &= ~1;
|
||||
fanState |= current_temperature[0] > EXTRUDER_AUTO_FAN_TEMPERATURE;
|
||||
fanState |= get_temp_error();
|
||||
}
|
||||
setExtruderAutoFanState(fanState);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif // any extruder auto fan pins set
|
||||
|
||||
#if (defined(FANCHECK) && defined(TACH_0) && (TACH_0 > -1))
|
||||
void readFanTach() {
|
||||
static bool fan_state[2];
|
||||
#ifdef FAN_SOFT_PWM
|
||||
if (READ(TACH_0) != fan_state[0]) {
|
||||
if(fan_measuring) fan_edge_counter[0] ++;
|
||||
fan_state[0] = !fan_state[0];
|
||||
}
|
||||
#else //FAN_SOFT_PWM
|
||||
if (READ(TACH_0) != fan_state[0]) {
|
||||
fan_edge_counter[0] ++;
|
||||
fan_state[0] = !fan_state[0];
|
||||
}
|
||||
#endif
|
||||
//if (READ(TACH_1) != fan_state[1]) {
|
||||
// fan_edge_counter[1] ++;
|
||||
// fan_state[1] = !fan_state[1];
|
||||
//}
|
||||
}
|
||||
#endif //TACH_0
|
||||
|
||||
void checkFans()
|
||||
{
|
||||
#ifndef DEBUG_DISABLE_FANCHECK
|
||||
#if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1)
|
||||
|
||||
#ifdef FAN_SOFT_PWM
|
||||
#ifdef FANCHECK
|
||||
if ((_millis() - extruder_autofan_last_check > FAN_CHECK_PERIOD) && (!fan_measuring)) {
|
||||
extruder_autofan_last_check = _millis();
|
||||
fanSpeedBckp = fanSpeedSoftPwm;
|
||||
|
||||
if (fanSpeedSoftPwm >= MIN_PRINT_FAN_SPEED) { //if we are in rage where we are doing fan check, set full PWM range for a short time to measure fan RPM by reading tacho signal without modulation by PWM signal
|
||||
// printf_P(PSTR("fanSpeedSoftPwm 1: %d\n"), fanSpeedSoftPwm);
|
||||
fanSpeedSoftPwm = 255;
|
||||
}
|
||||
fan_measuring = true;
|
||||
}
|
||||
if ((_millis() - extruder_autofan_last_check > FAN_CHECK_DURATION) && (fan_measuring)) {
|
||||
countFanSpeed();
|
||||
checkFanSpeed();
|
||||
//printf_P(PSTR("fanSpeedSoftPwm 1: %d\n"), fanSpeedSoftPwm);
|
||||
fanSpeedSoftPwm = fanSpeedBckp;
|
||||
//printf_P(PSTR("fan PWM: %d; extr fanSpeed measured: %d; print fan speed measured: %d \n"), fanSpeedBckp, fan_speed[0], fan_speed[1]);
|
||||
extruder_autofan_last_check = _millis();
|
||||
fan_measuring = false;
|
||||
}
|
||||
#endif //FANCHECK
|
||||
checkExtruderAutoFans();
|
||||
#else //FAN_SOFT_PWM
|
||||
if(_millis() - extruder_autofan_last_check > 1000) // only need to check fan state very infrequently
|
||||
{
|
||||
#if (defined(FANCHECK) && ((defined(TACH_0) && (TACH_0 >-1)) || (defined(TACH_1) && (TACH_1 > -1))))
|
||||
countFanSpeed();
|
||||
checkFanSpeed();
|
||||
#endif //(defined(TACH_0) && TACH_0 >-1) || (defined(TACH_1) && TACH_1 > -1)
|
||||
checkExtruderAutoFans();
|
||||
extruder_autofan_last_check = _millis();
|
||||
}
|
||||
#endif //FAN_SOFT_PWM
|
||||
|
||||
#endif
|
||||
#endif //DEBUG_DISABLE_FANCHECK
|
||||
}
|
||||
|
||||
void resetFanCheck() {
|
||||
fan_measuring = false;
|
||||
extruder_autofan_last_check = _millis();
|
||||
}
|
||||
|
||||
|
||||
void hotendFanSetFullSpeed()
|
||||
{
|
||||
#ifdef EXTRUDER_ALTFAN_DETECT
|
||||
altfanStatus.altfanOverride = 1; //full speed
|
||||
#endif //EXTRUDER_ALTFAN_DETECT
|
||||
resetFanCheck();
|
||||
setExtruderAutoFanState(3);
|
||||
SET_OUTPUT(FAN_PIN);
|
||||
#ifdef FAN_SOFT_PWM
|
||||
fanSpeedSoftPwm = 255;
|
||||
#else //FAN_SOFT_PWM
|
||||
analogWrite(FAN_PIN, 255);
|
||||
#endif //FAN_SOFT_PWM
|
||||
fanSpeed = 255;
|
||||
}
|
||||
|
||||
void hotendDefaultAutoFanState()
|
||||
{
|
||||
#if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1)
|
||||
#ifdef EXTRUDER_ALTFAN_DETECT
|
||||
altfanStatus.altfanOverride = eeprom_read_byte((uint8_t*)EEPROM_ALTFAN_OVERRIDE);
|
||||
#endif
|
||||
resetFanCheck();
|
||||
setExtruderAutoFanState(1);
|
||||
#endif
|
||||
}
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
// fan control and check
|
||||
#pragma once
|
||||
|
||||
#include "Configuration.h"
|
||||
#include "config.h"
|
||||
|
||||
#if (defined(FANCHECK) && defined(TACH_0) && (TACH_0 > -1))
|
||||
enum {
|
||||
EFCE_OK = 0, //!< normal operation, both fans are ok
|
||||
EFCE_FIXED, //!< previous fan error was fixed
|
||||
EFCE_REPORTED //!< fan error detected and reported to LCD and serial
|
||||
};
|
||||
extern volatile uint8_t fan_check_error;
|
||||
|
||||
void readFanTach();
|
||||
#endif //(defined(TACH_0))
|
||||
|
||||
#if (defined(FANCHECK) && defined(TACH_1) && (TACH_1 >-1))
|
||||
void setup_fan_interrupt();
|
||||
#endif // (defined(FANCHECK) && defined(TACH_1) && (TACH_1 >-1))
|
||||
|
||||
#ifdef EXTRUDER_ALTFAN_DETECT
|
||||
extern bool extruder_altfan_detect();
|
||||
extern void altfanOverride_toggle();
|
||||
extern bool altfanOverride_get();
|
||||
#endif //EXTRUDER_ALTFAN_DETECT
|
||||
|
||||
#if (defined(EXTRUDER_0_AUTO_FAN_PIN) && EXTRUDER_0_AUTO_FAN_PIN > -1)
|
||||
#ifdef FAN_SOFT_PWM
|
||||
extern bool fan_measuring;
|
||||
#endif //FAN_SOFT_PWM
|
||||
|
||||
extern unsigned long extruder_autofan_last_check;
|
||||
void setExtruderAutoFanState(uint8_t state);
|
||||
void checkExtruderAutoFans();
|
||||
#endif
|
||||
|
||||
void checkFans();
|
||||
void resetFanCheck(); // resets the fan measuring state
|
||||
|
||||
void hotendFanSetFullSpeed();
|
||||
void hotendDefaultAutoFanState();
|
||||
|
|
@ -62,7 +62,7 @@
|
|||
/// Write to a pin wrapper, non critical.
|
||||
/// This macro is cheaper than WRITE(IO,v) on ports H,I,J,K,L, as _WRITE_C disables / enables interrupts
|
||||
/// and stores the old CPU flags on the stack.
|
||||
/// This macro should only be called, where it cannot be interrupted.
|
||||
/// This macro should only be called, where it cannot be interrupted.
|
||||
#define WRITE_NC(IO, v) _WRITE_NC(IO, v)
|
||||
|
||||
/// toggle a pin wrapper
|
||||
|
|
@ -931,10 +931,10 @@ pins
|
|||
#define TXD DIO1
|
||||
|
||||
// SPI
|
||||
#define SCK 52
|
||||
#define MISO 50
|
||||
#define MOSI 51
|
||||
#define SS 53
|
||||
#define SCK DIO52
|
||||
#define MISO DIO50
|
||||
#define MOSI DIO51
|
||||
#define SS DIO53
|
||||
|
||||
// TWI (I2C)
|
||||
#define SCL DIO21
|
||||
|
|
@ -2067,7 +2067,7 @@ pins
|
|||
pins
|
||||
*/
|
||||
|
||||
//#define AT90USBxx_TEENSYPP_ASSIGNMENTS // Use Teensy++ 2.0 assignments
|
||||
//#define AT90USBxx_TEENSYPP_ASSIGNMENTS // Use Teensy++ 2.0 assignments
|
||||
#ifndef AT90USBxx_TEENSYPP_ASSIGNMENTS // Use traditional Marlin pin assignments
|
||||
|
||||
#define DIO0_PIN PINA0
|
||||
|
|
@ -2707,8 +2707,8 @@ pins
|
|||
|
||||
/*
|
||||
|
||||
AT90USB 51 50 49 48 47 46 45 44 10 11 12 13 14 15 16 17 35 36 37 38 39 40 41 42 25 26 27 28 29 30 31 32 33 34 43 09 18 19 01 02 61 60 59 58 57 56 55 54
|
||||
Port A0 A1 A2 A3 A4 A5 A6 A7 B0 B1 B2 B3 B4 B5 B6 B7 C0 C1 C2 C3 C4 C5 C6 C7 D0 D1 D2 D3 D4 D5 D6 D7 E0 E1 E2 E3 E4 E5 E6 E7 F0 F1 F2 F3 F4 F5 F6 F7
|
||||
AT90USB 51 50 49 48 47 46 45 44 10 11 12 13 14 15 16 17 35 36 37 38 39 40 41 42 25 26 27 28 29 30 31 32 33 34 43 09 18 19 01 02 61 60 59 58 57 56 55 54
|
||||
Port A0 A1 A2 A3 A4 A5 A6 A7 B0 B1 B2 B3 B4 B5 B6 B7 C0 C1 C2 C3 C4 C5 C6 C7 D0 D1 D2 D3 D4 D5 D6 D7 E0 E1 E2 E3 E4 E5 E6 E7 F0 F1 F2 F3 F4 F5 F6 F7
|
||||
Marlin 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
|
||||
Teensy 28 29 30 31 32 33 34 35 20 21 22 23 24 25 26 27 10 11 12 13 14 15 16 17 00 01 02 03 04 05 06 07 08 09(46*47)36 37 18 19 38 39 40 41 42 43 44 45
|
||||
The pins 46 and 47 are not supported by Teensyduino, but are supported below.
|
||||
|
|
|
|||
|
|
@ -4,13 +4,127 @@
|
|||
//! @brief First layer (Z offset) calibration
|
||||
|
||||
#include "first_lay_cal.h"
|
||||
#include "Configuration_var.h"
|
||||
#include "Configuration_prusa.h"
|
||||
#include "language.h"
|
||||
#include "Marlin.h"
|
||||
#include "messages.h"
|
||||
#include "cmdqueue.h"
|
||||
#include "mmu2.h"
|
||||
#include "mmu.h"
|
||||
#include <avr/pgmspace.h>
|
||||
#include <math.h>
|
||||
|
||||
//! @brief Wait for preheat
|
||||
void lay1cal_wait_preheat()
|
||||
{
|
||||
static const char cmd_preheat_0[] PROGMEM = "M107";
|
||||
static const char cmd_preheat_1[] PROGMEM = "M190";
|
||||
static const char cmd_preheat_2[] PROGMEM = "M109";
|
||||
static const char cmd_preheat_4[] PROGMEM = "G28";
|
||||
static const char cmd_preheat_5[] PROGMEM = "G92 E0.0";
|
||||
|
||||
const char * const preheat_cmd[] =
|
||||
{
|
||||
cmd_preheat_0,
|
||||
cmd_preheat_1,
|
||||
cmd_preheat_2,
|
||||
_T(MSG_M117_V2_CALIBRATION),
|
||||
cmd_preheat_4,
|
||||
cmd_preheat_5,
|
||||
};
|
||||
|
||||
for (uint8_t i = 0; i < (sizeof(preheat_cmd)/sizeof(preheat_cmd[0])); ++i)
|
||||
{
|
||||
enquecommand_P(preheat_cmd[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//! @brief Load filament
|
||||
//! @param cmd_buffer character buffer needed to format gcodes
|
||||
//! @param filament filament to use (applies for MMU only)
|
||||
void lay1cal_load_filament(char *cmd_buffer, uint8_t filament)
|
||||
{
|
||||
if (mmu_enabled)
|
||||
{
|
||||
enquecommand_P(PSTR("M83"));
|
||||
enquecommand_P(PSTR("G1 Y-3.0 F1000.0"));
|
||||
enquecommand_P(PSTR("G1 Z0.4 F1000.0"));
|
||||
sprintf_P(cmd_buffer, PSTR("T%d"), filament);
|
||||
enquecommand(cmd_buffer);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//! @brief Print intro line
|
||||
void lay1cal_intro_line()
|
||||
{
|
||||
static const char cmd_intro_mmu_3[] PROGMEM = "G1 X55.0 E32.0 F1073.0";
|
||||
static const char cmd_intro_mmu_4[] PROGMEM = "G1 X5.0 E32.0 F1800.0";
|
||||
static const char cmd_intro_mmu_5[] PROGMEM = "G1 X55.0 E8.0 F2000.0";
|
||||
static const char cmd_intro_mmu_6[] PROGMEM = "G1 Z0.3 F1000.0";
|
||||
static const char cmd_intro_mmu_7[] PROGMEM = "G92 E0.0";
|
||||
static const char cmd_intro_mmu_8[] PROGMEM = "G1 X240.0 E25.0 F2200.0";
|
||||
static const char cmd_intro_mmu_9[] PROGMEM = "G1 Y-2.0 F1000.0";
|
||||
static const char cmd_intro_mmu_10[] PROGMEM = "G1 X55.0 E25 F1400.0";
|
||||
static const char cmd_intro_mmu_11[] PROGMEM = "G1 Z0.20 F1000.0";
|
||||
static const char cmd_intro_mmu_12[] PROGMEM = "G1 X5.0 E4.0 F1000.0";
|
||||
|
||||
static const char * const intro_mmu_cmd[] PROGMEM =
|
||||
{
|
||||
cmd_intro_mmu_3,
|
||||
cmd_intro_mmu_4,
|
||||
cmd_intro_mmu_5,
|
||||
cmd_intro_mmu_6,
|
||||
cmd_intro_mmu_7,
|
||||
cmd_intro_mmu_8,
|
||||
cmd_intro_mmu_9,
|
||||
cmd_intro_mmu_10,
|
||||
cmd_intro_mmu_11,
|
||||
cmd_intro_mmu_12,
|
||||
};
|
||||
|
||||
if (mmu_enabled)
|
||||
{
|
||||
for (uint8_t i = 0; i < (sizeof(intro_mmu_cmd)/sizeof(intro_mmu_cmd[0])); ++i)
|
||||
{
|
||||
enquecommand_P(static_cast<char*>(pgm_read_ptr(&intro_mmu_cmd[i])));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
enquecommand_P(PSTR("G1 X60.0 E9.0 F1000.0"));
|
||||
enquecommand_P(PSTR("G1 X100.0 E12.5 F1000.0"));
|
||||
}
|
||||
}
|
||||
|
||||
//! @brief Setup for printing meander
|
||||
void lay1cal_before_meander()
|
||||
{
|
||||
static const char cmd_pre_meander_0[] PROGMEM = "G92 E0.0";
|
||||
static const char cmd_pre_meander_1[] PROGMEM = "G21"; //set units to millimeters TODO unsupported command
|
||||
static const char cmd_pre_meander_2[] PROGMEM = "G90"; //use absolute coordinates
|
||||
static const char cmd_pre_meander_3[] PROGMEM = "M83"; //use relative distances for extrusion TODO: duplicate
|
||||
static const char cmd_pre_meander_4[] PROGMEM = "G1 E-1.50000 F2100.00000";
|
||||
static const char cmd_pre_meander_5[] PROGMEM = "G1 Z5 F7200.000";
|
||||
static const char cmd_pre_meander_6[] PROGMEM = "M204 S1000"; //set acceleration
|
||||
static const char cmd_pre_meander_7[] PROGMEM = "G1 F4000";
|
||||
|
||||
static const char * const cmd_pre_meander[] PROGMEM =
|
||||
{
|
||||
cmd_pre_meander_0,
|
||||
cmd_pre_meander_1,
|
||||
cmd_pre_meander_2,
|
||||
cmd_pre_meander_3,
|
||||
cmd_pre_meander_4,
|
||||
cmd_pre_meander_5,
|
||||
cmd_pre_meander_6,
|
||||
cmd_pre_meander_7,
|
||||
};
|
||||
|
||||
for (uint8_t i = 0; i < (sizeof(cmd_pre_meander)/sizeof(cmd_pre_meander[0])); ++i)
|
||||
{
|
||||
enquecommand_P(static_cast<char*>(pgm_read_ptr(&cmd_pre_meander[i])));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! @brief Count extrude length
|
||||
//!
|
||||
|
|
@ -18,247 +132,83 @@
|
|||
//! @param extrusion_width extrusion width in mm
|
||||
//! @param extrusion_length extrusion length in mm
|
||||
//! @return filament length in mm which needs to be extruded to form line
|
||||
static constexpr float __attribute__((noinline)) count_e(float layer_height, float extrusion_width, float extrusion_length, float filament_diameter=1.75f)
|
||||
static constexpr float count_e(float layer_height, float extrusion_width, float extrusion_length)
|
||||
{
|
||||
return (extrusion_length * ((M_PI * pow(layer_height, 2)) / 4 + layer_height * (extrusion_width - layer_height))) / ((M_PI * pow(filament_diameter, 2)) / 4);
|
||||
return (extrusion_length * layer_height * extrusion_width / (M_PI * pow(1.75, 2) / 4));
|
||||
}
|
||||
|
||||
//! @brief Extrusion spacing
|
||||
//!
|
||||
//! @param layer_height layer height in mm
|
||||
//! @param extrusion_width extrusion width in mm
|
||||
//! @return filament length in mm which needs to be extruded to form line
|
||||
static constexpr float spacing(float layer_height, float extrusion_width, float overlap_factor=1.f)
|
||||
{
|
||||
return extrusion_width - layer_height * (overlap_factor - M_PI/4);
|
||||
}
|
||||
|
||||
// Common code extracted into one function to reduce code size
|
||||
static void lay1cal_common_enqueue_loop(const char * const * cmd_sequence, const uint8_t steps) {
|
||||
for (uint8_t i = 0; i < steps; ++i)
|
||||
{
|
||||
void * const pgm_ptr = pgm_read_ptr(cmd_sequence + i);
|
||||
|
||||
// M702 is currently only used with MMU enabled
|
||||
if (pgm_ptr == MSG_M702 && !MMU2::mmu2.Enabled()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
enquecommand_P(static_cast<char*>(pgm_ptr));
|
||||
}
|
||||
}
|
||||
|
||||
static const char extrude_fmt_X[] PROGMEM = "G1X%.4fE%.4f";
|
||||
static const char extrude_fmt_Y[] PROGMEM = "G1Y%.4fE%.4f";
|
||||
static const char zero_extrusion[] PROGMEM = "G92E0";
|
||||
static const char feedrate_F1080[] PROGMEM = "G1F1080";
|
||||
#ifndef NEW_FIRST_LAYER_CAL
|
||||
static constexpr int8_t invert = 1;
|
||||
static constexpr float short_length = 20;
|
||||
static constexpr float square_width = short_length;
|
||||
#else
|
||||
static constexpr int8_t invert = -1;
|
||||
static constexpr float short_length = 13.2812; //max_pos[1]/2 / meander * 2
|
||||
static constexpr float square_width = short_length*2;
|
||||
#endif //NEW_FIRST_LAYER_CAL
|
||||
static constexpr float long_length = 150;
|
||||
|
||||
//! @brief Wait for preheat
|
||||
void lay1cal_wait_preheat()
|
||||
{
|
||||
static const char preheat_cmd_2[] PROGMEM = "M190";
|
||||
static const char preheat_cmd_3[] PROGMEM = "M109";
|
||||
static const char preheat_cmd_4[] PROGMEM = "G28";
|
||||
|
||||
static const char * const preheat_cmd[] PROGMEM =
|
||||
{
|
||||
MSG_M107,
|
||||
preheat_cmd_2,
|
||||
preheat_cmd_3,
|
||||
preheat_cmd_4,
|
||||
zero_extrusion
|
||||
};
|
||||
|
||||
lay1cal_common_enqueue_loop(preheat_cmd, sizeof(preheat_cmd)/sizeof(preheat_cmd[0]));
|
||||
}
|
||||
|
||||
//! @brief Load filament
|
||||
//! @param cmd_buffer character buffer needed to format gcodes
|
||||
//! @param filament filament to use (applies for MMU only)
|
||||
//! @returns true if extra purge distance is needed in case of MMU prints (after a toolchange), otherwise false
|
||||
bool lay1cal_load_filament(uint8_t filament)
|
||||
{
|
||||
if (MMU2::mmu2.Enabled())
|
||||
{
|
||||
enquecommand_P(MSG_M83);
|
||||
enquecommand_P(PSTR("G1Y-3F1000"));
|
||||
enquecommand_P(PSTR("G1Z0.4"));
|
||||
|
||||
uint8_t currentTool = MMU2::mmu2.get_current_tool();
|
||||
if(currentTool == filament ){
|
||||
// already have the correct tool loaded - do nothing
|
||||
return false;
|
||||
} else if( currentTool != (uint8_t)MMU2::FILAMENT_UNKNOWN){
|
||||
// some other slot is loaded, perform an unload first
|
||||
enquecommand_P(MSG_M702);
|
||||
}
|
||||
// perform a toolchange
|
||||
enquecommandf_P(PSTR("T%d"), filament);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//! @brief Print intro line
|
||||
//! @param extraPurgeNeeded false if the first MMU-related "G1 E29" have to be skipped because the nozzle is already full of filament
|
||||
//! @param layer_height the height of the calibration layer
|
||||
//! @param extrusion_width the width of the extrusion layer
|
||||
void lay1cal_intro_line(bool extraPurgeNeeded, float layer_height, float extrusion_width)
|
||||
{
|
||||
static const char cmd_intro_mmu_3[] PROGMEM = "G1X55E29F1073";
|
||||
static const char cmd_intro_mmu_4[] PROGMEM = "G1X5E29F1800";
|
||||
static const char cmd_intro_mmu_5[] PROGMEM = "G1X55E8F2000";
|
||||
static const char cmd_intro_mmu_6[] PROGMEM = "G1Z0.3F1000";
|
||||
static const char cmd_intro_mmu_8[] PROGMEM = "G1X240E25F2200";
|
||||
static const char cmd_intro_mmu_9[] PROGMEM = "G1Y-2F1000";
|
||||
static const char cmd_intro_mmu_10[] PROGMEM = "G1X202.5E8F1400";
|
||||
static const char cmd_intro_mmu_11[] PROGMEM = "G1Z0.2";
|
||||
static const char * const cmd_intro_mmu[] PROGMEM =
|
||||
{
|
||||
// first 2 items are only relevant if filament was not loaded - i.e. extraPurgeNeeded == true
|
||||
cmd_intro_mmu_3,
|
||||
cmd_intro_mmu_4,
|
||||
cmd_intro_mmu_5,
|
||||
cmd_intro_mmu_6,
|
||||
zero_extrusion,
|
||||
cmd_intro_mmu_8,
|
||||
cmd_intro_mmu_9,
|
||||
cmd_intro_mmu_10,
|
||||
cmd_intro_mmu_11,
|
||||
};
|
||||
|
||||
if (MMU2::mmu2.Enabled())
|
||||
{
|
||||
for (uint8_t i = (extraPurgeNeeded ? 0 : 2); i < (sizeof(cmd_intro_mmu)/sizeof(cmd_intro_mmu[0])); ++i)
|
||||
{
|
||||
enquecommand_P(static_cast<char*>(pgm_read_ptr(&cmd_intro_mmu[i])));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
enquecommand_P(feedrate_F1080); //fixed velocity for the intro line
|
||||
enquecommandf_P(extrude_fmt_X, 60.f, count_e(layer_height, extrusion_width * 4.f, 60));
|
||||
enquecommandf_P(extrude_fmt_X, 202.5f, count_e(layer_height, extrusion_width * 8.f, 142.5));
|
||||
}
|
||||
}
|
||||
|
||||
//! @brief Setup for printing meander
|
||||
void lay1cal_before_meander()
|
||||
{
|
||||
#ifndef NEW_FIRST_LAYER_CAL
|
||||
static const char cmd_pre_meander_4[] PROGMEM = "G1E-1.5F2100";
|
||||
static const char cmd_pre_meander_5[] PROGMEM = "G1Z5F7200";
|
||||
#endif //NEW_FIRST_LAYER_CAL
|
||||
static const char cmd_pre_meander_6[] PROGMEM = "M204S1000"; //set acceleration
|
||||
|
||||
static const char * const cmd_pre_meander[] PROGMEM =
|
||||
{
|
||||
zero_extrusion,
|
||||
MSG_G90,
|
||||
MSG_M83, // use relative distances for extrusion
|
||||
#ifndef NEW_FIRST_LAYER_CAL
|
||||
cmd_pre_meander_4,
|
||||
cmd_pre_meander_5,
|
||||
#endif //NEW_FIRST_LAYER_CAL
|
||||
cmd_pre_meander_6,
|
||||
};
|
||||
|
||||
lay1cal_common_enqueue_loop(cmd_pre_meander, (sizeof(cmd_pre_meander)/sizeof(cmd_pre_meander[0])));
|
||||
}
|
||||
|
||||
//! @brief Print meander start
|
||||
void lay1cal_meander_start(float layer_height, float extrusion_width)
|
||||
{
|
||||
#ifndef NEW_FIRST_LAYER_CAL
|
||||
enquecommand_P(PSTR("G1X50Y155"));
|
||||
#endif //_NEW_FIRST_LAYER_CAL
|
||||
static const char fmt1[] PROGMEM = "G1Z%.2f";
|
||||
enquecommandf_P(fmt1, layer_height);
|
||||
enquecommand_P(feedrate_F1080);
|
||||
enquecommand_P(MSG_G91); //enable relative XYZ
|
||||
#ifdef NEW_FIRST_LAYER_CAL
|
||||
enquecommandf_P(extrude_fmt_Y, short_length, count_e(layer_height, extrusion_width, short_length));
|
||||
enquecommandf_P(extrude_fmt_X, long_length*invert, count_e(layer_height, extrusion_width, long_length));
|
||||
enquecommandf_P(extrude_fmt_Y, -short_length*invert, count_e(layer_height, extrusion_width, short_length));
|
||||
#else
|
||||
enquecommandf_P(extrude_fmt_X, 25.f*invert, count_e(layer_height, extrusion_width * 4.f, 25));
|
||||
enquecommandf_P(extrude_fmt_X, 25.f*invert, count_e(layer_height, extrusion_width * 2.f, 25));
|
||||
enquecommandf_P(extrude_fmt_X, 100.f*invert, count_e(layer_height, extrusion_width, 100));
|
||||
enquecommandf_P(extrude_fmt_Y, -20.f*invert, count_e(layer_height, extrusion_width, 20));
|
||||
#endif //_NEW_FIRST_LAYER_CAL
|
||||
}
|
||||
static const float width = 0.4; //!< line width
|
||||
static const float length = 20 - width; //!< line length
|
||||
static const float height = 0.2; //!< layer height TODO This is wrong, as current Z height is 0.15 mm
|
||||
static const float extr = count_e(height, width, length); //!< E axis movement needed to print line
|
||||
|
||||
//! @brief Print meander
|
||||
//! @param cmd_buffer character buffer needed to format gcodes
|
||||
void lay1cal_meander(float layer_height, float extrusion_width)
|
||||
void lay1cal_meander(char *cmd_buffer)
|
||||
{
|
||||
const float long_extrusion = count_e(layer_height, extrusion_width, long_length);
|
||||
const float short_extrusion = count_e(layer_height, extrusion_width, short_length);
|
||||
static const char cmd_meander_0[] PROGMEM = "G1 X50 Y155";
|
||||
static const char cmd_meander_1[] PROGMEM = "G1 Z0.150 F7200.000";
|
||||
static const char cmd_meander_2[] PROGMEM = "G1 F1080";
|
||||
static const char cmd_meander_3[] PROGMEM = "G1 X75 Y155 E2.5";
|
||||
static const char cmd_meander_4[] PROGMEM = "G1 X100 Y155 E2";
|
||||
static const char cmd_meander_5[] PROGMEM = "G1 X200 Y155 E2.62773";
|
||||
static const char cmd_meander_6[] PROGMEM = "G1 X200 Y135 E0.66174";
|
||||
static const char cmd_meander_7[] PROGMEM = "G1 X50 Y135 E3.62773";
|
||||
static const char cmd_meander_8[] PROGMEM = "G1 X50 Y115 E0.49386";
|
||||
static const char cmd_meander_9[] PROGMEM = "G1 X200 Y115 E3.62773";
|
||||
static const char cmd_meander_10[] PROGMEM = "G1 X200 Y95 E0.49386";
|
||||
static const char cmd_meander_11[] PROGMEM = "G1 X50 Y95 E3.62773";
|
||||
static const char cmd_meander_12[] PROGMEM = "G1 X50 Y75 E0.49386";
|
||||
static const char cmd_meander_13[] PROGMEM = "G1 X200 Y75 E3.62773";
|
||||
static const char cmd_meander_14[] PROGMEM = "G1 X200 Y55 E0.49386";
|
||||
static const char cmd_meander_15[] PROGMEM = "G1 X50 Y55 E3.62773";
|
||||
|
||||
for(int8_t i = 0, xdir = -invert; i <= 4; i++, xdir = -xdir)
|
||||
static const char * const cmd_meander[] PROGMEM =
|
||||
{
|
||||
enquecommandf_P(extrude_fmt_X, xdir * long_length, long_extrusion);
|
||||
enquecommandf_P(extrude_fmt_Y, invert * -short_length, short_extrusion);
|
||||
}
|
||||
#ifdef NEW_FIRST_LAYER_CAL
|
||||
constexpr float mid_length = 0.5f * long_length - 0.5f * square_width;
|
||||
const float mid_extrusion = count_e(layer_height, extrusion_width, mid_length);
|
||||
enquecommandf_P(extrude_fmt_X, -mid_length, mid_extrusion); //~Middle of bed X125
|
||||
enquecommandf_P(extrude_fmt_Y, short_length, short_extrusion); //~Middle of bed Y105
|
||||
#endif //NEW_FIRST_LAYER_CAL
|
||||
cmd_meander_0,
|
||||
cmd_meander_1,
|
||||
cmd_meander_2,
|
||||
cmd_meander_3,
|
||||
cmd_meander_4,
|
||||
cmd_meander_5,
|
||||
cmd_meander_6,
|
||||
cmd_meander_7,
|
||||
cmd_meander_8,
|
||||
cmd_meander_9,
|
||||
cmd_meander_10,
|
||||
cmd_meander_11,
|
||||
cmd_meander_12,
|
||||
cmd_meander_13,
|
||||
cmd_meander_14,
|
||||
cmd_meander_15,
|
||||
};
|
||||
|
||||
for (uint8_t i = 0; i < (sizeof(cmd_meander)/sizeof(cmd_meander[0])); ++i)
|
||||
{
|
||||
enquecommand_P(static_cast<char*>(pgm_read_ptr(&cmd_meander[i])));
|
||||
}
|
||||
sprintf_P(cmd_buffer, PSTR("G1 X50 Y35 E%-.3f"), extr);
|
||||
enquecommand(cmd_buffer);
|
||||
}
|
||||
|
||||
//! @brief Print square
|
||||
//!
|
||||
//! This function enqueues 4 lines of the square, so it needs to be called multiple times
|
||||
//! This function needs to be called 16 times for i from 0 to 15.
|
||||
//!
|
||||
//! @param cmd_buffer character buffer needed to format gcodes
|
||||
void lay1cal_square(float layer_height, float extrusion_width)
|
||||
//! @param i iteration
|
||||
void lay1cal_square(char *cmd_buffer, uint8_t i)
|
||||
{
|
||||
const float Y_spacing = spacing(layer_height, extrusion_width);
|
||||
const float long_extrusion = count_e(layer_height, extrusion_width, square_width);
|
||||
const float short_extrusion = count_e(layer_height, extrusion_width, Y_spacing);
|
||||
const float extr_short_segment = count_e(height, width, width);
|
||||
|
||||
for (uint8_t i = 0; i < 4; i++)
|
||||
{
|
||||
enquecommandf_P(extrude_fmt_X, square_width*invert, long_extrusion);
|
||||
enquecommandf_P(extrude_fmt_Y, -Y_spacing*invert, short_extrusion);
|
||||
enquecommandf_P(extrude_fmt_X, -square_width*invert, long_extrusion);
|
||||
enquecommandf_P(extrude_fmt_Y, -Y_spacing*invert, short_extrusion);
|
||||
}
|
||||
}
|
||||
|
||||
void lay1cal_finish()
|
||||
{
|
||||
static const char cmd_cal_finish_3[] PROGMEM = "G1E-0.075F2100"; // Retract
|
||||
static const char cmd_cal_finish_4[] PROGMEM = "M140S0"; // Turn off bed heater
|
||||
static const char cmd_cal_finish_5[] PROGMEM = "G1Z10F1300"; // Lift Z
|
||||
static const char cmd_cal_finish_6[] PROGMEM = "G1X10Y180F4000"; // Go to parking position
|
||||
static const char cmd_cal_finish_8[] PROGMEM = "M104S0"; // Turn off hotend heater
|
||||
|
||||
static const char * const cmd_cal_finish[] PROGMEM =
|
||||
{
|
||||
MSG_G90, // Set to Absolute Positioning
|
||||
MSG_M107, // Turn off printer fan
|
||||
cmd_cal_finish_3, // Retract
|
||||
cmd_cal_finish_4, // Turn off bed heater
|
||||
cmd_cal_finish_5, // Lift Z
|
||||
cmd_cal_finish_6, // Go to parking position
|
||||
MSG_M702, // Unload filament (MMU only)
|
||||
cmd_cal_finish_8, // Turn off hotend heater
|
||||
MSG_M84 // Disable stepper motors
|
||||
};
|
||||
|
||||
lay1cal_common_enqueue_loop(cmd_cal_finish, (sizeof(cmd_cal_finish)/sizeof(cmd_cal_finish[0])));
|
||||
static const char fmt1[] PROGMEM = "G1 X%d Y%-.2f E%-.3f";
|
||||
static const char fmt2[] PROGMEM = "G1 Y%-.2f E%-.3f";
|
||||
sprintf_P(cmd_buffer, fmt1, 70, (35 - i*width * 2), extr);
|
||||
enquecommand(cmd_buffer);
|
||||
sprintf_P(cmd_buffer, fmt2, (35 - (2 * i + 1)*width), extr_short_segment);
|
||||
enquecommand(cmd_buffer);
|
||||
sprintf_P(cmd_buffer, fmt1, 50, (35 - (2 * i + 1)*width), extr);
|
||||
enquecommand(cmd_buffer);
|
||||
sprintf_P(cmd_buffer, fmt2, (35 - (i + 1)*width * 2), extr_short_segment);
|
||||
enquecommand(cmd_buffer);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,12 +7,10 @@
|
|||
#include <stdint.h>
|
||||
|
||||
void lay1cal_wait_preheat();
|
||||
[[nodiscard]] bool lay1cal_load_filament(uint8_t filament);
|
||||
void lay1cal_intro_line(bool skipExtraPurge, float layer_height, float extrusion_width);
|
||||
void lay1cal_load_filament(char *cmd_buffer, uint8_t filament);
|
||||
void lay1cal_intro_line();
|
||||
void lay1cal_before_meander();
|
||||
void lay1cal_meander_start(float layer_height, float extrusion_width);
|
||||
void lay1cal_meander(float layer_height, float extrusion_width);
|
||||
void lay1cal_square(float layer_height, float extrusion_width);
|
||||
void lay1cal_finish();
|
||||
void lay1cal_meander(char *cmd_buffer);
|
||||
void lay1cal_square(char *cmd_buffer, uint8_t i);
|
||||
|
||||
#endif /* FIRMWARE_FIRST_LAY_CAL_H_ */
|
||||
|
|
|
|||
|
|
@ -0,0 +1,789 @@
|
|||
//! @file
|
||||
|
||||
#include "Marlin.h"
|
||||
|
||||
#include "fsensor.h"
|
||||
#include <avr/pgmspace.h>
|
||||
#include "pat9125.h"
|
||||
#include "stepper.h"
|
||||
#include "cmdqueue.h"
|
||||
#include "ultralcd.h"
|
||||
#include "mmu.h"
|
||||
#include "cardreader.h"
|
||||
|
||||
#include "adc.h"
|
||||
#include "temperature.h"
|
||||
#include "config.h"
|
||||
|
||||
//! @name Basic parameters
|
||||
//! @{
|
||||
#define FSENSOR_CHUNK_LEN 1.25 //!< filament sensor chunk length (mm)
|
||||
#define FSENSOR_ERR_MAX 4 //!< filament sensor maximum error/chunk count for runout detection
|
||||
|
||||
#define FSENSOR_SOFTERR_CMAX 3 //!< number of contiguous soft failures before a triggering a runout
|
||||
#define FSENSOR_SOFTERR_DELTA 30000 //!< maximum interval (ms) to consider soft failures contiguous
|
||||
//! @}
|
||||
|
||||
//! @name Optical quality measurement parameters
|
||||
//! @{
|
||||
#define FSENSOR_OQ_MAX_ES 2 //!< maximum sum of error blocks during filament recheck
|
||||
#define FSENSOR_OQ_MIN_YD 2 //!< minimum yd sum during filament check (counts per inch)
|
||||
#define FSENSOR_OQ_MIN_BR 80 //!< minimum brightness value
|
||||
#define FSENSOR_OQ_MAX_SH 10 //!< maximum shutter value
|
||||
//! @}
|
||||
|
||||
const char ERRMSG_PAT9125_NOT_RESP[] PROGMEM = "PAT9125 not responding (%d)!\n";
|
||||
|
||||
// PJ7 can not be used (does not have PinChangeInterrupt possibility)
|
||||
#define FSENSOR_INT_PIN 75 //!< filament sensor interrupt pin PJ4
|
||||
#define FSENSOR_INT_PIN_MASK 0x10 //!< filament sensor interrupt pin mask (bit4)
|
||||
#define FSENSOR_INT_PIN_PIN_REG PINJ // PIN register @ PJ4
|
||||
#define FSENSOR_INT_PIN_VECT PCINT1_vect // PinChange ISR @ PJ4
|
||||
#define FSENSOR_INT_PIN_PCMSK_REG PCMSK1 // PinChangeMaskRegister @ PJ4
|
||||
#define FSENSOR_INT_PIN_PCMSK_BIT PCINT13 // PinChange Interrupt / PinChange Enable Mask @ PJ4
|
||||
#define FSENSOR_INT_PIN_PCICR_BIT PCIE1 // PinChange Interrupt Enable / Flag @ PJ4
|
||||
|
||||
//! enabled = initialized and sampled every chunk event
|
||||
bool fsensor_enabled = true;
|
||||
//! runout watching is done in fsensor_update (called from main loop)
|
||||
bool fsensor_watch_runout = true;
|
||||
//! not responding - is set if any communication error occurred during initialization or readout
|
||||
bool fsensor_not_responding = false;
|
||||
|
||||
#ifdef PAT9125
|
||||
uint8_t fsensor_int_pin_old = 0;
|
||||
//! optical checking "chunk lenght" (already in steps)
|
||||
int16_t fsensor_chunk_len = 0;
|
||||
//! enable/disable quality meassurement
|
||||
bool fsensor_oq_meassure_enabled = false;
|
||||
//! number of errors, updated in ISR
|
||||
uint8_t fsensor_err_cnt = 0;
|
||||
//! variable for accumulating step count (updated callbacks from stepper and ISR)
|
||||
int16_t fsensor_st_cnt = 0;
|
||||
//! count of total sensor "soft" failures (filament status checks)
|
||||
uint8_t fsensor_softfail = 0;
|
||||
//! timestamp of last soft failure
|
||||
unsigned long fsensor_softfail_last = 0;
|
||||
//! count of soft failures within the configured time
|
||||
uint8_t fsensor_softfail_ccnt = 0;
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_FSENSOR_LOG
|
||||
//! log flag: 0=log disabled, 1=log enabled
|
||||
uint8_t fsensor_log = 1;
|
||||
#endif //DEBUG_FSENSOR_LOG
|
||||
|
||||
|
||||
//! @name filament autoload variables
|
||||
//! @{
|
||||
|
||||
//! autoload feature enabled
|
||||
bool fsensor_autoload_enabled = true;
|
||||
//! autoload watching enable/disable flag
|
||||
bool fsensor_watch_autoload = false;
|
||||
|
||||
#ifdef PAT9125
|
||||
//
|
||||
uint16_t fsensor_autoload_y;
|
||||
//
|
||||
uint8_t fsensor_autoload_c;
|
||||
//
|
||||
uint32_t fsensor_autoload_last_millis;
|
||||
//
|
||||
uint8_t fsensor_autoload_sum;
|
||||
//! @}
|
||||
#endif
|
||||
|
||||
|
||||
//! @name filament optical quality measurement variables
|
||||
//! @{
|
||||
|
||||
//! Measurement enable/disable flag
|
||||
bool fsensor_oq_meassure = false;
|
||||
//! skip-chunk counter, for accurate measurement is necessary to skip first chunk...
|
||||
uint8_t fsensor_oq_skipchunk;
|
||||
//! number of samples from start of measurement
|
||||
uint8_t fsensor_oq_samples;
|
||||
//! sum of steps in positive direction movements
|
||||
uint16_t fsensor_oq_st_sum;
|
||||
//! sum of deltas in positive direction movements
|
||||
uint16_t fsensor_oq_yd_sum;
|
||||
//! sum of errors during measurement
|
||||
uint16_t fsensor_oq_er_sum;
|
||||
//! max error counter value during measurement
|
||||
uint8_t fsensor_oq_er_max;
|
||||
//! minimum delta value
|
||||
int16_t fsensor_oq_yd_min;
|
||||
//! maximum delta value
|
||||
int16_t fsensor_oq_yd_max;
|
||||
//! sum of shutter value
|
||||
uint16_t fsensor_oq_sh_sum;
|
||||
//! @}
|
||||
|
||||
#ifdef IR_SENSOR_ANALOG
|
||||
ClFsensorPCB oFsensorPCB;
|
||||
ClFsensorActionNA oFsensorActionNA;
|
||||
bool bIRsensorStateFlag=false;
|
||||
unsigned long nIRsensorLastTime;
|
||||
#endif //IR_SENSOR_ANALOG
|
||||
|
||||
void fsensor_stop_and_save_print(void)
|
||||
{
|
||||
puts_P(PSTR("fsensor_stop_and_save_print"));
|
||||
stop_and_save_print_to_ram(0, 0);
|
||||
fsensor_watch_runout = false;
|
||||
}
|
||||
|
||||
#ifdef PAT9125
|
||||
// Reset all internal counters to zero, including stepper callbacks
|
||||
void fsensor_reset_err_cnt()
|
||||
{
|
||||
fsensor_err_cnt = 0;
|
||||
pat9125_y = 0;
|
||||
st_reset_fsensor();
|
||||
}
|
||||
|
||||
void fsensor_set_axis_steps_per_unit(float u)
|
||||
{
|
||||
fsensor_chunk_len = (int16_t)(FSENSOR_CHUNK_LEN * u);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void fsensor_restore_print_and_continue(void)
|
||||
{
|
||||
puts_P(PSTR("fsensor_restore_print_and_continue"));
|
||||
fsensor_watch_runout = true;
|
||||
#ifdef PAT9125
|
||||
fsensor_reset_err_cnt();
|
||||
#endif
|
||||
restore_print_from_ram_and_continue(0);
|
||||
}
|
||||
|
||||
// fsensor_checkpoint_print cuts the current print job at the current position,
|
||||
// allowing new instructions to be inserted in the middle
|
||||
void fsensor_checkpoint_print(void)
|
||||
{
|
||||
puts_P(PSTR("fsensor_checkpoint_print"));
|
||||
stop_and_save_print_to_ram(0, 0);
|
||||
restore_print_from_ram_and_continue(0);
|
||||
}
|
||||
|
||||
#ifdef IR_SENSOR_ANALOG
|
||||
const char* FsensorIRVersionText()
|
||||
{
|
||||
switch(oFsensorPCB)
|
||||
{
|
||||
case ClFsensorPCB::_Old:
|
||||
return _T(MSG_IR_03_OR_OLDER);
|
||||
case ClFsensorPCB::_Rev04:
|
||||
return _T(MSG_IR_04_OR_NEWER);
|
||||
default:
|
||||
return _T(MSG_IR_UNKNOWN);
|
||||
}
|
||||
}
|
||||
#endif //IR_SENSOR_ANALOG
|
||||
|
||||
void fsensor_init(void)
|
||||
{
|
||||
#ifdef PAT9125
|
||||
uint8_t pat9125 = pat9125_init();
|
||||
printf_P(PSTR("PAT9125_init:%hhu\n"), pat9125);
|
||||
#endif //PAT9125
|
||||
uint8_t fsensor_enabled = eeprom_read_byte((uint8_t*)EEPROM_FSENSOR);
|
||||
fsensor_autoload_enabled=eeprom_read_byte((uint8_t*)EEPROM_FSENS_AUTOLOAD_ENABLED);
|
||||
fsensor_not_responding = false;
|
||||
#ifdef PAT9125
|
||||
uint8_t oq_meassure_enabled = eeprom_read_byte((uint8_t*)EEPROM_FSENS_OQ_MEASS_ENABLED);
|
||||
fsensor_oq_meassure_enabled = (oq_meassure_enabled == 1)?true:false;
|
||||
fsensor_set_axis_steps_per_unit(cs.axis_steps_per_unit[E_AXIS]);
|
||||
|
||||
if (!pat9125){
|
||||
fsensor_enabled = 0; //disable sensor
|
||||
fsensor_not_responding = true;
|
||||
}
|
||||
#endif //PAT9125
|
||||
#ifdef IR_SENSOR_ANALOG
|
||||
bIRsensorStateFlag=false;
|
||||
oFsensorPCB = (ClFsensorPCB)eeprom_read_byte((uint8_t*)EEPROM_FSENSOR_PCB);
|
||||
oFsensorActionNA = (ClFsensorActionNA)eeprom_read_byte((uint8_t*)EEPROM_FSENSOR_ACTION_NA);
|
||||
|
||||
// If the fsensor is not responding even at the start of the printer,
|
||||
// set this flag accordingly to show N/A in Settings->Filament sensor.
|
||||
// This is even valid for both fsensor board revisions (0.3 or older and 0.4).
|
||||
// Must be done after reading what type of fsensor board we have
|
||||
fsensor_not_responding = ! fsensor_IR_check();
|
||||
#endif //IR_SENSOR_ANALOG
|
||||
if (fsensor_enabled){
|
||||
fsensor_enable(false); // (in this case) EEPROM update is not necessary
|
||||
} else {
|
||||
fsensor_disable(false); // (in this case) EEPROM update is not necessary
|
||||
}
|
||||
printf_P(PSTR("FSensor %S"), (fsensor_enabled?PSTR("ENABLED"):PSTR("DISABLED")));
|
||||
#ifdef IR_SENSOR_ANALOG
|
||||
printf_P(PSTR(" (sensor board revision:%S)\n"), FsensorIRVersionText());
|
||||
#else //IR_SENSOR_ANALOG
|
||||
MYSERIAL.println();
|
||||
#endif //IR_SENSOR_ANALOG
|
||||
if (check_for_ir_sensor()){
|
||||
ir_sensor_detected = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool fsensor_enable(bool bUpdateEEPROM)
|
||||
{
|
||||
#ifdef PAT9125
|
||||
(void)bUpdateEEPROM; // silence unused warning in this variant
|
||||
|
||||
if (mmu_enabled == false) { //filament sensor is pat9125, enable only if it is working
|
||||
uint8_t pat9125 = pat9125_init();
|
||||
printf_P(PSTR("PAT9125_init:%hhu\n"), pat9125);
|
||||
if (pat9125)
|
||||
fsensor_not_responding = false;
|
||||
else
|
||||
fsensor_not_responding = true;
|
||||
fsensor_enabled = pat9125 ? true : false;
|
||||
fsensor_watch_runout = true;
|
||||
fsensor_oq_meassure = false;
|
||||
fsensor_reset_err_cnt();
|
||||
eeprom_update_byte((uint8_t*)EEPROM_FSENSOR, fsensor_enabled ? 0x01 : 0x00);
|
||||
FSensorStateMenu = fsensor_enabled ? 1 : 0;
|
||||
}
|
||||
else //filament sensor is FINDA, always enable
|
||||
{
|
||||
fsensor_enabled = true;
|
||||
eeprom_update_byte((uint8_t*)EEPROM_FSENSOR, 0x01);
|
||||
FSensorStateMenu = 1;
|
||||
}
|
||||
#else // PAT9125
|
||||
#ifdef IR_SENSOR_ANALOG
|
||||
if(!fsensor_IR_check())
|
||||
{
|
||||
bUpdateEEPROM=true;
|
||||
fsensor_enabled=false;
|
||||
fsensor_not_responding=true;
|
||||
FSensorStateMenu=0;
|
||||
}
|
||||
else {
|
||||
#endif //IR_SENSOR_ANALOG
|
||||
fsensor_enabled=true;
|
||||
fsensor_not_responding=false;
|
||||
FSensorStateMenu=1;
|
||||
#ifdef IR_SENSOR_ANALOG
|
||||
}
|
||||
#endif //IR_SENSOR_ANALOG
|
||||
if(bUpdateEEPROM)
|
||||
eeprom_update_byte((uint8_t*)EEPROM_FSENSOR, FSensorStateMenu);
|
||||
#endif //PAT9125
|
||||
return fsensor_enabled;
|
||||
}
|
||||
|
||||
void fsensor_disable(bool bUpdateEEPROM)
|
||||
{
|
||||
fsensor_enabled = false;
|
||||
FSensorStateMenu = 0;
|
||||
if(bUpdateEEPROM)
|
||||
eeprom_update_byte((uint8_t*)EEPROM_FSENSOR, 0x00);
|
||||
}
|
||||
|
||||
void fsensor_autoload_set(bool State)
|
||||
{
|
||||
#ifdef PAT9125
|
||||
if (!State) fsensor_autoload_check_stop();
|
||||
#endif //PAT9125
|
||||
fsensor_autoload_enabled = State;
|
||||
eeprom_update_byte((unsigned char *)EEPROM_FSENS_AUTOLOAD_ENABLED, fsensor_autoload_enabled);
|
||||
}
|
||||
|
||||
void pciSetup(byte pin)
|
||||
{
|
||||
// !!! "digitalPinTo?????bit()" does not provide the correct results for some MCU pins
|
||||
*digitalPinToPCMSK(pin) |= bit (digitalPinToPCMSKbit(pin)); // enable pin
|
||||
PCIFR |= bit (digitalPinToPCICRbit(pin)); // clear any outstanding interrupt
|
||||
PCICR |= bit (digitalPinToPCICRbit(pin)); // enable interrupt for the group
|
||||
}
|
||||
|
||||
#ifdef PAT9125
|
||||
void fsensor_autoload_check_start(void)
|
||||
{
|
||||
// puts_P(_N("fsensor_autoload_check_start\n"));
|
||||
if (!fsensor_enabled) return;
|
||||
if (!fsensor_autoload_enabled) return;
|
||||
if (fsensor_watch_autoload) return;
|
||||
if (!pat9125_update()) //update sensor
|
||||
{
|
||||
fsensor_disable();
|
||||
fsensor_not_responding = true;
|
||||
fsensor_watch_autoload = false;
|
||||
printf_P(ERRMSG_PAT9125_NOT_RESP, 3);
|
||||
return;
|
||||
}
|
||||
puts_P(_N("fsensor_autoload_check_start - autoload ENABLED"));
|
||||
fsensor_autoload_y = pat9125_y; //save current y value
|
||||
fsensor_autoload_c = 0; //reset number of changes counter
|
||||
fsensor_autoload_sum = 0;
|
||||
fsensor_autoload_last_millis = _millis();
|
||||
fsensor_watch_runout = false;
|
||||
fsensor_watch_autoload = true;
|
||||
}
|
||||
|
||||
|
||||
void fsensor_autoload_check_stop(void)
|
||||
{
|
||||
// puts_P(_N("fsensor_autoload_check_stop\n"));
|
||||
if (!fsensor_enabled) return;
|
||||
// puts_P(_N("fsensor_autoload_check_stop 1\n"));
|
||||
if (!fsensor_autoload_enabled) return;
|
||||
// puts_P(_N("fsensor_autoload_check_stop 2\n"));
|
||||
if (!fsensor_watch_autoload) return;
|
||||
puts_P(_N("fsensor_autoload_check_stop - autoload DISABLED"));
|
||||
fsensor_autoload_sum = 0;
|
||||
fsensor_watch_autoload = false;
|
||||
fsensor_watch_runout = true;
|
||||
fsensor_reset_err_cnt();
|
||||
}
|
||||
#endif //PAT9125
|
||||
|
||||
bool fsensor_check_autoload(void)
|
||||
{
|
||||
if (!fsensor_enabled) return false;
|
||||
if (!fsensor_autoload_enabled) return false;
|
||||
if (ir_sensor_detected) {
|
||||
if (digitalRead(IR_SENSOR_PIN) == 1) {
|
||||
fsensor_watch_autoload = true;
|
||||
}
|
||||
else if (fsensor_watch_autoload == true) {
|
||||
fsensor_watch_autoload = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#ifdef PAT9125
|
||||
if (!fsensor_watch_autoload)
|
||||
{
|
||||
fsensor_autoload_check_start();
|
||||
return false;
|
||||
}
|
||||
#if 0
|
||||
uint8_t fsensor_autoload_c_old = fsensor_autoload_c;
|
||||
#endif
|
||||
if ((_millis() - fsensor_autoload_last_millis) < 25) return false;
|
||||
fsensor_autoload_last_millis = _millis();
|
||||
if (!pat9125_update_y()) //update sensor
|
||||
{
|
||||
fsensor_disable();
|
||||
fsensor_not_responding = true;
|
||||
printf_P(ERRMSG_PAT9125_NOT_RESP, 2);
|
||||
return false;
|
||||
}
|
||||
int16_t dy = pat9125_y - fsensor_autoload_y;
|
||||
if (dy) //? dy value is nonzero
|
||||
{
|
||||
if (dy > 0) //? delta-y value is positive (inserting)
|
||||
{
|
||||
fsensor_autoload_sum += dy;
|
||||
fsensor_autoload_c += 3; //increment change counter by 3
|
||||
}
|
||||
else if (fsensor_autoload_c > 1)
|
||||
fsensor_autoload_c -= 2; //decrement change counter by 2
|
||||
fsensor_autoload_y = pat9125_y; //save current value
|
||||
}
|
||||
else if (fsensor_autoload_c > 0)
|
||||
fsensor_autoload_c--;
|
||||
if (fsensor_autoload_c == 0) fsensor_autoload_sum = 0;
|
||||
#if 0
|
||||
puts_P(_N("fsensor_check_autoload\n"));
|
||||
if (fsensor_autoload_c != fsensor_autoload_c_old)
|
||||
printf_P(PSTR("fsensor_check_autoload dy=%d c=%d sum=%d\n"), dy, fsensor_autoload_c, fsensor_autoload_sum);
|
||||
#endif
|
||||
// if ((fsensor_autoload_c >= 15) && (fsensor_autoload_sum > 30))
|
||||
if ((fsensor_autoload_c >= 12) && (fsensor_autoload_sum > 20))
|
||||
{
|
||||
// puts_P(_N("fsensor_check_autoload = true !!!\n"));
|
||||
return true;
|
||||
}
|
||||
#endif //PAT9125
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef PAT9125
|
||||
void fsensor_oq_meassure_set(bool State)
|
||||
{
|
||||
fsensor_oq_meassure_enabled = State;
|
||||
eeprom_update_byte((unsigned char *)EEPROM_FSENS_OQ_MEASS_ENABLED, fsensor_oq_meassure_enabled);
|
||||
}
|
||||
|
||||
void fsensor_oq_meassure_start(uint8_t skip)
|
||||
{
|
||||
if (!fsensor_enabled) return;
|
||||
if (!fsensor_oq_meassure_enabled) return;
|
||||
puts_P(PSTR("fsensor_oq_meassure_start"));
|
||||
fsensor_oq_skipchunk = skip;
|
||||
fsensor_oq_samples = 0;
|
||||
fsensor_oq_st_sum = 0;
|
||||
fsensor_oq_yd_sum = 0;
|
||||
fsensor_oq_er_sum = 0;
|
||||
fsensor_oq_er_max = 0;
|
||||
fsensor_oq_yd_min = INT16_MAX;
|
||||
fsensor_oq_yd_max = 0;
|
||||
fsensor_oq_sh_sum = 0;
|
||||
pat9125_update();
|
||||
pat9125_y = 0;
|
||||
fsensor_oq_meassure = true;
|
||||
}
|
||||
|
||||
void fsensor_oq_meassure_stop(void)
|
||||
{
|
||||
if (!fsensor_enabled) return;
|
||||
if (!fsensor_oq_meassure_enabled) return;
|
||||
printf_P(PSTR("fsensor_oq_meassure_stop, %hhu samples\n"), fsensor_oq_samples);
|
||||
printf_P(_N(" st_sum=%u yd_sum=%u er_sum=%u er_max=%hhu\n"), fsensor_oq_st_sum, fsensor_oq_yd_sum, fsensor_oq_er_sum, fsensor_oq_er_max);
|
||||
printf_P(_N(" yd_min=%u yd_max=%u yd_avg=%u sh_avg=%u\n"), fsensor_oq_yd_min, fsensor_oq_yd_max, (uint16_t)((uint32_t)fsensor_oq_yd_sum * fsensor_chunk_len / fsensor_oq_st_sum), (uint16_t)(fsensor_oq_sh_sum / fsensor_oq_samples));
|
||||
fsensor_oq_meassure = false;
|
||||
}
|
||||
|
||||
#ifdef FSENSOR_QUALITY
|
||||
const char _OK[] PROGMEM = "OK";
|
||||
const char _NG[] PROGMEM = "NG!";
|
||||
|
||||
bool fsensor_oq_result(void)
|
||||
{
|
||||
if (!fsensor_enabled) return true;
|
||||
if (!fsensor_oq_meassure_enabled) return true;
|
||||
puts_P(_N("fsensor_oq_result"));
|
||||
bool res_er_sum = (fsensor_oq_er_sum <= FSENSOR_OQ_MAX_ES);
|
||||
printf_P(_N(" er_sum = %u %S\n"), fsensor_oq_er_sum, (res_er_sum?_OK:_NG));
|
||||
bool res_er_max = (fsensor_oq_er_max <= FSENSOR_OQ_MAX_EM);
|
||||
printf_P(_N(" er_max = %hhu %S\n"), fsensor_oq_er_max, (res_er_max?_OK:_NG));
|
||||
uint8_t yd_avg = ((uint32_t)fsensor_oq_yd_sum * fsensor_chunk_len / fsensor_oq_st_sum);
|
||||
bool res_yd_avg = (yd_avg >= FSENSOR_OQ_MIN_YD) && (yd_avg <= FSENSOR_OQ_MAX_YD);
|
||||
printf_P(_N(" yd_avg = %hhu %S\n"), yd_avg, (res_yd_avg?_OK:_NG));
|
||||
bool res_yd_max = (fsensor_oq_yd_max <= (yd_avg * FSENSOR_OQ_MAX_PD));
|
||||
printf_P(_N(" yd_max = %u %S\n"), fsensor_oq_yd_max, (res_yd_max?_OK:_NG));
|
||||
bool res_yd_min = (fsensor_oq_yd_min >= (yd_avg / FSENSOR_OQ_MAX_ND));
|
||||
printf_P(_N(" yd_min = %u %S\n"), fsensor_oq_yd_min, (res_yd_min?_OK:_NG));
|
||||
|
||||
uint16_t yd_dev = (fsensor_oq_yd_max - yd_avg) + (yd_avg - fsensor_oq_yd_min);
|
||||
printf_P(_N(" yd_dev = %u\n"), yd_dev);
|
||||
|
||||
uint16_t yd_qua = 10 * yd_avg / (yd_dev + 1);
|
||||
printf_P(_N(" yd_qua = %u %S\n"), yd_qua, ((yd_qua >= 8)?_OK:_NG));
|
||||
|
||||
uint8_t sh_avg = (fsensor_oq_sh_sum / fsensor_oq_samples);
|
||||
bool res_sh_avg = (sh_avg <= FSENSOR_OQ_MAX_SH);
|
||||
if (yd_qua >= 8) res_sh_avg = true;
|
||||
|
||||
printf_P(_N(" sh_avg = %hhu %S\n"), sh_avg, (res_sh_avg?_OK:_NG));
|
||||
bool res = res_er_sum && res_er_max && res_yd_avg && res_yd_max && res_yd_min && res_sh_avg;
|
||||
printf_P(_N("fsensor_oq_result %S\n"), (res?_OK:_NG));
|
||||
return res;
|
||||
}
|
||||
#endif //FSENSOR_QUALITY
|
||||
|
||||
FORCE_INLINE static void fsensor_isr(int st_cnt)
|
||||
{
|
||||
uint8_t old_err_cnt = fsensor_err_cnt;
|
||||
uint8_t pat9125_res = fsensor_oq_meassure?pat9125_update():pat9125_update_y();
|
||||
if (!pat9125_res)
|
||||
{
|
||||
fsensor_disable();
|
||||
fsensor_not_responding = true;
|
||||
printf_P(ERRMSG_PAT9125_NOT_RESP, 1);
|
||||
}
|
||||
|
||||
if (st_cnt != 0)
|
||||
{
|
||||
// movement was planned, check for sensor movement
|
||||
int8_t st_dir = st_cnt >= 0;
|
||||
int8_t pat9125_dir = pat9125_y >= 0;
|
||||
|
||||
if (pat9125_y == 0)
|
||||
{
|
||||
if (st_dir)
|
||||
{
|
||||
// no movement detected: we might be within a blind sensor range,
|
||||
// update the frame and shutter parameters we didn't earlier
|
||||
if (!fsensor_oq_meassure)
|
||||
pat9125_update_bs();
|
||||
|
||||
// increment the error count only if underexposed: filament likely missing
|
||||
if ((pat9125_b < FSENSOR_OQ_MIN_BR) && (pat9125_s > FSENSOR_OQ_MAX_SH))
|
||||
{
|
||||
// check for a dark frame (<30% avg brightness) with long exposure
|
||||
++fsensor_err_cnt;
|
||||
}
|
||||
else
|
||||
{
|
||||
// good frame, filament likely present
|
||||
if(fsensor_err_cnt) --fsensor_err_cnt;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (pat9125_dir != st_dir)
|
||||
{
|
||||
// detected direction opposite of motor movement
|
||||
if (st_dir) ++fsensor_err_cnt;
|
||||
}
|
||||
else if (pat9125_dir == st_dir)
|
||||
{
|
||||
// direction agreeing with planned movement
|
||||
if (fsensor_err_cnt) --fsensor_err_cnt;
|
||||
}
|
||||
|
||||
if (st_dir && fsensor_oq_meassure)
|
||||
{
|
||||
// extruding with quality assessment
|
||||
if (fsensor_oq_skipchunk)
|
||||
{
|
||||
fsensor_oq_skipchunk--;
|
||||
fsensor_err_cnt = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (st_cnt == fsensor_chunk_len)
|
||||
{
|
||||
if (pat9125_y > 0) if (fsensor_oq_yd_min > pat9125_y) fsensor_oq_yd_min = (fsensor_oq_yd_min + pat9125_y) / 2;
|
||||
if (pat9125_y >= 0) if (fsensor_oq_yd_max < pat9125_y) fsensor_oq_yd_max = (fsensor_oq_yd_max + pat9125_y) / 2;
|
||||
}
|
||||
fsensor_oq_samples++;
|
||||
fsensor_oq_st_sum += st_cnt;
|
||||
if (pat9125_y > 0) fsensor_oq_yd_sum += pat9125_y;
|
||||
if (fsensor_err_cnt > old_err_cnt)
|
||||
fsensor_oq_er_sum += (fsensor_err_cnt - old_err_cnt);
|
||||
if (fsensor_oq_er_max < fsensor_err_cnt)
|
||||
fsensor_oq_er_max = fsensor_err_cnt;
|
||||
fsensor_oq_sh_sum += pat9125_s;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_FSENSOR_LOG
|
||||
if (fsensor_log)
|
||||
{
|
||||
printf_P(_N("FSENSOR cnt=%d dy=%d err=%hhu %S\n"), st_cnt, pat9125_y, fsensor_err_cnt, (fsensor_err_cnt > old_err_cnt)?_N("NG!"):_N("OK"));
|
||||
if (fsensor_oq_meassure) printf_P(_N("FSENSOR st_sum=%u yd_sum=%u er_sum=%u er_max=%hhu yd_max=%u\n"), fsensor_oq_st_sum, fsensor_oq_yd_sum, fsensor_oq_er_sum, fsensor_oq_er_max, fsensor_oq_yd_max);
|
||||
}
|
||||
#endif //DEBUG_FSENSOR_LOG
|
||||
|
||||
pat9125_y = 0;
|
||||
}
|
||||
|
||||
ISR(FSENSOR_INT_PIN_VECT)
|
||||
{
|
||||
if (mmu_enabled || ir_sensor_detected) return;
|
||||
if (!((fsensor_int_pin_old ^ FSENSOR_INT_PIN_PIN_REG) & FSENSOR_INT_PIN_MASK)) return;
|
||||
fsensor_int_pin_old = FSENSOR_INT_PIN_PIN_REG;
|
||||
|
||||
// prevent isr re-entry
|
||||
static bool _lock = false;
|
||||
if (!_lock)
|
||||
{
|
||||
// fetch fsensor_st_cnt atomically
|
||||
int st_cnt = fsensor_st_cnt;
|
||||
fsensor_st_cnt = 0;
|
||||
|
||||
_lock = true;
|
||||
sei();
|
||||
fsensor_isr(st_cnt);
|
||||
cli();
|
||||
_lock = false;
|
||||
}
|
||||
}
|
||||
|
||||
void fsensor_setup_interrupt(void)
|
||||
{
|
||||
|
||||
pinMode(FSENSOR_INT_PIN, OUTPUT);
|
||||
digitalWrite(FSENSOR_INT_PIN, LOW);
|
||||
fsensor_int_pin_old = 0;
|
||||
|
||||
//pciSetup(FSENSOR_INT_PIN);
|
||||
// !!! "pciSetup()" does not provide the correct results for some MCU pins
|
||||
// so interrupt registers settings:
|
||||
FSENSOR_INT_PIN_PCMSK_REG |= bit(FSENSOR_INT_PIN_PCMSK_BIT); // enable corresponding PinChangeInterrupt (individual pin)
|
||||
PCIFR |= bit(FSENSOR_INT_PIN_PCICR_BIT); // clear previous occasional interrupt (set of pins)
|
||||
PCICR |= bit(FSENSOR_INT_PIN_PCICR_BIT); // enable corresponding PinChangeInterrupt (set of pins)
|
||||
}
|
||||
|
||||
void fsensor_st_block_chunk(int cnt)
|
||||
{
|
||||
if (!fsensor_enabled) return;
|
||||
fsensor_st_cnt += cnt;
|
||||
|
||||
// !!! bit toggling (PINxn <- 1) (for PinChangeInterrupt) does not work for some MCU pins
|
||||
WRITE(FSENSOR_INT_PIN, !READ(FSENSOR_INT_PIN));
|
||||
}
|
||||
#endif //PAT9125
|
||||
|
||||
|
||||
//! Common code for enqueing M600 and supplemental codes into the command queue.
|
||||
//! Used both for the IR sensor and the PAT9125
|
||||
void fsensor_enque_M600(){
|
||||
puts_P(PSTR("fsensor_update - M600"));
|
||||
eeprom_update_byte((uint8_t*)EEPROM_FERROR_COUNT, eeprom_read_byte((uint8_t*)EEPROM_FERROR_COUNT) + 1);
|
||||
eeprom_update_word((uint16_t*)EEPROM_FERROR_COUNT_TOT, eeprom_read_word((uint16_t*)EEPROM_FERROR_COUNT_TOT) + 1);
|
||||
enquecommand_front_P((PSTR("M600")));
|
||||
}
|
||||
|
||||
//! @brief filament sensor update (perform M600 on filament runout)
|
||||
//!
|
||||
//! Works only if filament sensor is enabled.
|
||||
//! When the filament sensor error count is larger then FSENSOR_ERR_MAX, pauses print, tries to move filament back and forth.
|
||||
//! If there is still no plausible signal from filament sensor plans M600 (Filament change).
|
||||
void fsensor_update(void)
|
||||
{
|
||||
#ifdef PAT9125
|
||||
if (fsensor_watch_runout && (fsensor_err_cnt > FSENSOR_ERR_MAX))
|
||||
{
|
||||
fsensor_stop_and_save_print();
|
||||
KEEPALIVE_STATE(IN_HANDLER);
|
||||
|
||||
bool autoload_enabled_tmp = fsensor_autoload_enabled;
|
||||
fsensor_autoload_enabled = false;
|
||||
bool oq_meassure_enabled_tmp = fsensor_oq_meassure_enabled;
|
||||
fsensor_oq_meassure_enabled = true;
|
||||
|
||||
// move the nozzle away while checking the filament
|
||||
current_position[Z_AXIS] += 0.8;
|
||||
if(current_position[Z_AXIS] > Z_MAX_POS) current_position[Z_AXIS] = Z_MAX_POS;
|
||||
plan_buffer_line_curposXYZE(max_feedrate[Z_AXIS]);
|
||||
st_synchronize();
|
||||
|
||||
// check the filament in isolation
|
||||
fsensor_reset_err_cnt();
|
||||
fsensor_oq_meassure_start(0);
|
||||
float e_tmp = current_position[E_AXIS];
|
||||
current_position[E_AXIS] -= 3;
|
||||
plan_buffer_line_curposXYZE(250/60);
|
||||
current_position[E_AXIS] = e_tmp;
|
||||
plan_buffer_line_curposXYZE(200/60);
|
||||
st_synchronize();
|
||||
fsensor_oq_meassure_stop();
|
||||
|
||||
bool err = false;
|
||||
err |= (fsensor_err_cnt > 0); // final error count is non-zero
|
||||
err |= (fsensor_oq_er_sum > FSENSOR_OQ_MAX_ES); // total error count is above limit
|
||||
err |= (fsensor_oq_yd_sum < FSENSOR_OQ_MIN_YD); // total measured distance is below limit
|
||||
|
||||
fsensor_restore_print_and_continue();
|
||||
fsensor_autoload_enabled = autoload_enabled_tmp;
|
||||
fsensor_oq_meassure_enabled = oq_meassure_enabled_tmp;
|
||||
unsigned long now = _millis();
|
||||
if (!err && (now - fsensor_softfail_last) > FSENSOR_SOFTERR_DELTA)
|
||||
fsensor_softfail_ccnt = 0;
|
||||
if (!err && fsensor_softfail_ccnt <= FSENSOR_SOFTERR_CMAX)
|
||||
{
|
||||
puts_P(PSTR("fsensor_err_cnt = 0"));
|
||||
++fsensor_softfail;
|
||||
++fsensor_softfail_ccnt;
|
||||
fsensor_softfail_last = now;
|
||||
}
|
||||
else
|
||||
{
|
||||
fsensor_softfail_ccnt = 0;
|
||||
fsensor_softfail_last = 0;
|
||||
fsensor_enque_M600();
|
||||
}
|
||||
}
|
||||
#else //PAT9125
|
||||
if (CHECK_FSENSOR && ir_sensor_detected)
|
||||
{
|
||||
if(digitalRead(IR_SENSOR_PIN))
|
||||
{ // IR_SENSOR_PIN ~ H
|
||||
#ifdef IR_SENSOR_ANALOG
|
||||
if(!bIRsensorStateFlag)
|
||||
{
|
||||
bIRsensorStateFlag=true;
|
||||
nIRsensorLastTime=_millis();
|
||||
}
|
||||
else
|
||||
{
|
||||
if((_millis()-nIRsensorLastTime)>IR_SENSOR_STEADY)
|
||||
{
|
||||
uint8_t nMUX1,nMUX2;
|
||||
uint16_t nADC;
|
||||
bIRsensorStateFlag=false;
|
||||
// sequence for direct data reading from AD converter
|
||||
DISABLE_TEMPERATURE_INTERRUPT();
|
||||
nMUX1=ADMUX; // ADMUX saving
|
||||
nMUX2=ADCSRB;
|
||||
adc_setmux(VOLT_IR_PIN);
|
||||
ADCSRA|=(1<<ADSC); // first conversion after ADMUX change discarded (preventively)
|
||||
while(ADCSRA&(1<<ADSC))
|
||||
;
|
||||
ADCSRA|=(1<<ADSC); // second conversion used
|
||||
while(ADCSRA&(1<<ADSC))
|
||||
;
|
||||
nADC=ADC;
|
||||
ADMUX=nMUX1; // ADMUX restoring
|
||||
ADCSRB=nMUX2;
|
||||
ENABLE_TEMPERATURE_INTERRUPT();
|
||||
// end of sequence for ...
|
||||
// Detection of correct function of fsensor v04 - it must NOT read >4.6V
|
||||
// If it does, it means a disconnected cables or faulty board
|
||||
if( (oFsensorPCB == ClFsensorPCB::_Rev04) && ( (nADC*OVERSAMPLENR) > IRsensor_Hopen_TRESHOLD ) )
|
||||
{
|
||||
fsensor_disable();
|
||||
fsensor_not_responding = true;
|
||||
printf_P(PSTR("IR sensor not responding (%d)!\n"),1);
|
||||
if((ClFsensorActionNA)eeprom_read_byte((uint8_t*)EEPROM_FSENSOR_ACTION_NA)==ClFsensorActionNA::_Pause)
|
||||
|
||||
// if we are printing and FS action is set to "Pause", force pause the print
|
||||
if(oFsensorActionNA==ClFsensorActionNA::_Pause)
|
||||
lcd_pause_print();
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif //IR_SENSOR_ANALOG
|
||||
fsensor_checkpoint_print();
|
||||
fsensor_enque_M600();
|
||||
#ifdef IR_SENSOR_ANALOG
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // IR_SENSOR_PIN ~ L
|
||||
bIRsensorStateFlag=false;
|
||||
#endif //IR_SENSOR_ANALOG
|
||||
}
|
||||
}
|
||||
#endif //PAT9125
|
||||
}
|
||||
|
||||
#ifdef IR_SENSOR_ANALOG
|
||||
/// This is called only upon start of the printer or when switching the fsensor ON in the menu
|
||||
/// We cannot do temporal window checks here (aka the voltage has been in some range for a period of time)
|
||||
bool fsensor_IR_check(){
|
||||
if( IRsensor_Lmax_TRESHOLD <= current_voltage_raw_IR && current_voltage_raw_IR <= IRsensor_Hmin_TRESHOLD ){
|
||||
/// If the voltage is in forbidden range, the fsensor is ok, but the lever is mounted improperly.
|
||||
/// Or the user is so creative so that he can hold a piece of fillament in the hole in such a genius way,
|
||||
/// that the IR fsensor reading is within 1.5 and 3V ... this would have been highly unusual
|
||||
/// and would have been considered more like a sabotage than normal printer operation
|
||||
puts_P(PSTR("fsensor in forbidden range 1.5-3V - check sensor"));
|
||||
return false;
|
||||
}
|
||||
if( oFsensorPCB == ClFsensorPCB::_Rev04 ){
|
||||
/// newer IR sensor cannot normally produce 4.6-5V, this is considered a failure/bad mount
|
||||
if( IRsensor_Hopen_TRESHOLD <= current_voltage_raw_IR && current_voltage_raw_IR <= IRsensor_VMax_TRESHOLD ){
|
||||
puts_P(PSTR("fsensor v0.4 in fault range 4.6-5V - unconnected"));
|
||||
return false;
|
||||
}
|
||||
/// newer IR sensor cannot normally produce 0-0.3V, this is considered a failure
|
||||
#if 0 //Disabled as it has to be decided if we gonna use this or not.
|
||||
if( IRsensor_Hopen_TRESHOLD <= current_voltage_raw_IR && current_voltage_raw_IR <= IRsensor_VMax_TRESHOLD ){
|
||||
puts_P(PSTR("fsensor v0.4 in fault range 0.0-0.3V - wrong IR sensor"));
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/// If IR sensor is "uknown state" and filament is not loaded > 1.5V return false
|
||||
#if 0
|
||||
if( (oFsensorPCB == ClFsensorPCB::_Undef) && ( current_voltage_raw_IR > IRsensor_Lmax_TRESHOLD ) ){
|
||||
puts_P(PSTR("Unknown IR sensor version and no filament loaded detected."));
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
// otherwise the IR fsensor is considered working correctly
|
||||
return true;
|
||||
}
|
||||
#endif //IR_SENSOR_ANALOG
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
//! @file
|
||||
#ifndef FSENSOR_H
|
||||
#define FSENSOR_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "config.h"
|
||||
|
||||
|
||||
// enable/disable flag
|
||||
extern bool fsensor_enabled;
|
||||
// not responding flag
|
||||
extern bool fsensor_not_responding;
|
||||
#ifdef PAT9125
|
||||
// optical checking "chunk lenght" (already in steps)
|
||||
extern int16_t fsensor_chunk_len;
|
||||
// count of soft failures
|
||||
extern uint8_t fsensor_softfail;
|
||||
#endif
|
||||
|
||||
//! @name save restore printing
|
||||
//! @{
|
||||
extern void fsensor_stop_and_save_print(void);
|
||||
//! restore print - restore position and heatup to original temperature
|
||||
extern void fsensor_restore_print_and_continue(void);
|
||||
//! split the current gcode stream to insert new instructions
|
||||
extern void fsensor_checkpoint_print(void);
|
||||
//! @}
|
||||
|
||||
//! initialize
|
||||
extern void fsensor_init(void);
|
||||
|
||||
#ifdef PAT9125
|
||||
//! update axis resolution
|
||||
extern void fsensor_set_axis_steps_per_unit(float u);
|
||||
#endif
|
||||
|
||||
//! @name enable/disable
|
||||
//! @{
|
||||
extern bool fsensor_enable(bool bUpdateEEPROM=true);
|
||||
extern void fsensor_disable(bool bUpdateEEPROM=true);
|
||||
//! @}
|
||||
|
||||
//autoload feature enabled
|
||||
extern bool fsensor_autoload_enabled;
|
||||
extern void fsensor_autoload_set(bool State);
|
||||
|
||||
extern void fsensor_update(void);
|
||||
#ifdef PAT9125
|
||||
//! setup pin-change interrupt
|
||||
extern void fsensor_setup_interrupt(void);
|
||||
|
||||
//! @name autoload support
|
||||
//! @{
|
||||
|
||||
extern void fsensor_autoload_check_start(void);
|
||||
extern void fsensor_autoload_check_stop(void);
|
||||
#endif //PAT9125
|
||||
extern bool fsensor_check_autoload(void);
|
||||
//! @}
|
||||
|
||||
#ifdef PAT9125
|
||||
//! @name optical quality measurement support
|
||||
//! @{
|
||||
extern bool fsensor_oq_meassure_enabled;
|
||||
extern void fsensor_oq_meassure_set(bool State);
|
||||
extern void fsensor_oq_meassure_start(uint8_t skip);
|
||||
extern void fsensor_oq_meassure_stop(void);
|
||||
extern bool fsensor_oq_result(void);
|
||||
//! @}
|
||||
|
||||
//! @name callbacks from stepper
|
||||
//! @{
|
||||
extern void fsensor_st_block_chunk(int cnt);
|
||||
|
||||
// debugging
|
||||
extern uint8_t fsensor_log;
|
||||
|
||||
// There's really nothing to do in block_begin: the stepper ISR likely has
|
||||
// called us already at the end of the last block, making this integration
|
||||
// redundant. LA1.5 might not always do that during a coasting move, so attempt
|
||||
// to drain fsensor_st_cnt anyway at the beginning of the new block.
|
||||
#define fsensor_st_block_begin(rev) fsensor_st_block_chunk(0)
|
||||
//! @}
|
||||
#endif //PAT9125
|
||||
|
||||
#define VOLT_DIV_REF 5
|
||||
|
||||
#ifdef IR_SENSOR_ANALOG
|
||||
#define IR_SENSOR_STEADY 10 // [ms]
|
||||
|
||||
enum class ClFsensorPCB:uint_least8_t
|
||||
{
|
||||
_Old=0,
|
||||
_Rev04=1,
|
||||
_Undef=EEPROM_EMPTY_VALUE
|
||||
};
|
||||
|
||||
enum class ClFsensorActionNA:uint_least8_t
|
||||
{
|
||||
_Continue=0,
|
||||
_Pause=1,
|
||||
_Undef=EEPROM_EMPTY_VALUE
|
||||
};
|
||||
|
||||
extern ClFsensorPCB oFsensorPCB;
|
||||
extern ClFsensorActionNA oFsensorActionNA;
|
||||
extern const char* FsensorIRVersionText();
|
||||
|
||||
extern bool fsensor_IR_check();
|
||||
constexpr uint16_t Voltage2Raw(float V){
|
||||
return ( V * 1023 * OVERSAMPLENR / VOLT_DIV_REF ) + 0.5F;
|
||||
}
|
||||
constexpr float Raw2Voltage(uint16_t raw){
|
||||
return VOLT_DIV_REF*(raw / (1023.F * OVERSAMPLENR) );
|
||||
}
|
||||
constexpr uint16_t IRsensor_Ldiode_TRESHOLD = Voltage2Raw(0.3F); // ~0.3V, raw value=982
|
||||
constexpr uint16_t IRsensor_Lmax_TRESHOLD = Voltage2Raw(1.5F); // ~1.5V (0.3*Vcc), raw value=4910
|
||||
constexpr uint16_t IRsensor_Hmin_TRESHOLD = Voltage2Raw(3.0F); // ~3.0V (0.6*Vcc), raw value=9821
|
||||
constexpr uint16_t IRsensor_Hopen_TRESHOLD = Voltage2Raw(4.6F); // ~4.6V (N.C. @ Ru~20-50k, Rd'=56k, Ru'=10k), raw value=15059
|
||||
constexpr uint16_t IRsensor_VMax_TRESHOLD = Voltage2Raw(5.F); // ~5V, raw value=16368
|
||||
|
||||
#endif //IR_SENSOR_ANALOG
|
||||
|
||||
#endif //FSENSOR_H
|
||||
|
|
@ -11,7 +11,7 @@
|
|||
// Doing this at higher frequency than the bed "loudspeaker" can handle makes the click barely audible.
|
||||
// Technically:
|
||||
// timer0 is set to fast PWM mode at 62.5kHz (timer0 is linked to the bed heating pin) (zero prescaler)
|
||||
// To keep the bed switching at 30Hz - we don't want the PWM running at 62kHz all the time
|
||||
// To keep the bed switching at 30Hz - we don't want the PWM running at 62kHz all the time
|
||||
// since it would burn the heatbed's MOSFET:
|
||||
// 16MHz/256 levels of PWM duty gives us 62.5kHz
|
||||
// 62.5kHz/256 gives ~244Hz, that is still too fast - 244/8 gives ~30Hz, that's what we need
|
||||
|
|
@ -19,9 +19,9 @@
|
|||
// The finite automaton is running in the ISR(TIMER0_OVF_vect)
|
||||
|
||||
// 2019-08-14 update: the original algorithm worked very well, however there were 2 regressions:
|
||||
// 1. 62kHz ISR requires considerable amount of processing power,
|
||||
// 1. 62kHz ISR requires considerable amount of processing power,
|
||||
// USB transfer speed dropped by 20%, which was most notable when doing short G-code segments.
|
||||
// 2. Some users reported TLed PSU started clicking when running at 120V/60Hz.
|
||||
// 2. Some users reported TLed PSU started clicking when running at 120V/60Hz.
|
||||
// This looks like the original algorithm didn't maintain base PWM 30Hz, but only 15Hz
|
||||
// To address both issues, there is an improved approach based on the idea of leveraging
|
||||
// different CLK prescalers in some automaton states - i.e. when holding LOW or HIGH on the output pin,
|
||||
|
|
@ -40,7 +40,7 @@
|
|||
// - it can toggle unnoticed, which will result in bed clicking again.
|
||||
// That's why there are special transition states ZERO_TO_RISE and ONE_TO_FALL, which enable the
|
||||
// counter change its operation atomically and without artefacts on the output pin.
|
||||
// The resulting signal on the output pin was checked with an osciloscope.
|
||||
// The resulting signal on the output pin was checked with an osciloscope.
|
||||
// If there are any change requirements in the future, the signal must be checked with an osciloscope again,
|
||||
// ad-hoc changes may completely screw things up!
|
||||
|
||||
|
|
@ -57,7 +57,7 @@ enum class States : uint8_t {
|
|||
ZERO_TO_RISE, ///< metastate allowing the timer change its state atomically without artefacts on the output pin
|
||||
RISE, ///< 16 fast PWM cycles with increasing duty up to steady ON
|
||||
RISE_TO_ONE, ///< metastate allowing the timer change its state atomically without artefacts on the output pin
|
||||
ONE, ///< steady 1 (ON), no change for the whole period
|
||||
ONE, ///< steady 1 (ON), no change for the whole period
|
||||
FALL, ///< 16 fast PWM cycles with decreasing duty down to steady OFF
|
||||
FALL_TO_ZERO ///< metastate allowing the timer change its state atomically without artefacts on the output pin
|
||||
};
|
||||
|
|
@ -92,7 +92,7 @@ static const uint8_t fastShift = 4;
|
|||
/// increment slowCounter by 1
|
||||
/// but use less bits of soft PWM - something like soft_pwm_bed >> 2
|
||||
/// that may further reduce the CPU cycles required by the bed heating automaton
|
||||
/// Due to the nature of bed heating the reduced PID precision may not be a major issue, however doing 8x less ISR(timer0_ovf) may significantly improve the performance
|
||||
/// Due to the nature of bed heating the reduced PID precision may not be a major issue, however doing 8x less ISR(timer0_ovf) may significantly improve the performance
|
||||
static const uint8_t slowInc = 1;
|
||||
|
||||
ISR(TIMER0_OVF_vect) // timer compare interrupt service routine
|
||||
|
|
@ -177,6 +177,6 @@ ISR(TIMER0_OVF_vect) // timer compare interrupt service routine
|
|||
TCNT0 = 128;
|
||||
OCR0B = 255;
|
||||
TCCR0B = (1 << CS01); // change prescaler to 8, i.e. 7.8kHz
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,32 +0,0 @@
|
|||
#include <string.h>
|
||||
#include "Configuration_adv.h"
|
||||
#include "host.h"
|
||||
#include "Timer.h"
|
||||
|
||||
static LongTimer M79_timer;
|
||||
static char host_status_screen_name[3];
|
||||
|
||||
void SetHostStatusScreenName(const char * name) {
|
||||
strncpy(host_status_screen_name, name, 2);
|
||||
host_status_screen_name[2] = '\0';
|
||||
}
|
||||
|
||||
char * GetHostStatusScreenName() {
|
||||
return host_status_screen_name;
|
||||
}
|
||||
|
||||
void ResetHostStatusScreenName() {
|
||||
memset(host_status_screen_name, 0, sizeof(host_status_screen_name));
|
||||
}
|
||||
|
||||
void M79_timer_restart() {
|
||||
M79_timer.start();
|
||||
}
|
||||
|
||||
bool M79_timer_get_status() {
|
||||
return M79_timer.running();
|
||||
}
|
||||
|
||||
void M79_timer_update_status() {
|
||||
M79_timer.expired(M79_TIMEOUT);
|
||||
}
|
||||
|
|
@ -1,22 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
/// Assigns host name with up to two characters which will be shown on
|
||||
/// the UI when printing. The function forces the third byte to be null delimiter.
|
||||
void SetHostStatusScreenName(const char * name);
|
||||
|
||||
/// Returns a pointer to the host name
|
||||
char * GetHostStatusScreenName();
|
||||
|
||||
/// Reset the memory to NULL when the host name should not be used
|
||||
void ResetHostStatusScreenName();
|
||||
|
||||
/// Restart the M79 timer
|
||||
void M79_timer_restart();
|
||||
|
||||
/// Get the current M79 timer status
|
||||
/// @returns true if running, false otherwise
|
||||
bool M79_timer_get_status();
|
||||
|
||||
/// Checks if the timer period has expired. If the timer
|
||||
/// has expired, the timer is stopped
|
||||
void M79_timer_update_status();
|
||||
|
|
@ -74,7 +74,7 @@ float la10c_jerk(float j)
|
|||
|
||||
// check for a compatible range of values prior to convert (be sure that
|
||||
// a higher E-jerk would still be compatible wrt the E accell range)
|
||||
if(j < 4.5 && cs.max_acceleration_mm_per_s2_normal[E_AXIS] < 2000)
|
||||
if(j < 4.5 && cs.max_acceleration_units_per_sq_second_normal[E_AXIS] < 2000)
|
||||
return j;
|
||||
|
||||
// bring low E-jerk values into equivalent LA 1.5 values by
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
//language.c
|
||||
#include "language.h"
|
||||
#include <avr/pgmspace.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/eeprom.h>
|
||||
#include "bootapp.h"
|
||||
|
||||
|
|
@ -29,7 +28,7 @@ uint8_t lang_is_selected(void) { return 1; }
|
|||
#else //(LANG_MODE == 0) //secondary languages in progmem or xflash
|
||||
|
||||
//reserved xx kbytes for secondary language table
|
||||
const char _SEC_LANG[LANG_SIZE_RESERVED] __attribute__((aligned(SPM_PAGESIZE))) PROGMEM_I2 = "_SEC_LANG";
|
||||
const char __attribute__((aligned(256))) _SEC_LANG[LANG_SIZE_RESERVED] PROGMEM_I2 = "_SEC_LANG";
|
||||
|
||||
//primary language signature
|
||||
const uint32_t _PRI_LANG_SIGNATURE[1] __attribute__((section(".progmem0"))) = {0xffffffff};
|
||||
|
|
@ -240,15 +239,15 @@ const char* lang_get_name_by_code(uint16_t code)
|
|||
#ifdef COMMUNITY_LANG_GROUP1_HR
|
||||
case LANG_CODE_HR: return _n("Hrvatski"); //community Croatian contribution
|
||||
#endif // COMMUNITY_LANG_GROUP1_HR
|
||||
#ifdef COMMUNITY_LANG_GROUP2_LT
|
||||
#ifdef COMMUNITY_LANG_GROUP1_LT
|
||||
case LANG_CODE_LT: return _n("Lietuviu"); //community Lithuanian contribution
|
||||
#endif // COMMUNITY_LANG_GROUP2_LT
|
||||
#endif // COMMUNITY_LANG_GROUP1_LT
|
||||
#ifdef COMMUNITY_LANG_GROUP1_RO
|
||||
case LANG_CODE_RO: return _n("Romana"); //community Romanian contribution
|
||||
#endif // COMMUNITY_LANG_GROUP1_RO
|
||||
|
||||
//Use the 3 lines below as a template and replace 'QR' and 'New language'
|
||||
//#ifdef COMMUNITY_LANG_GROUP1_QR
|
||||
//#ifdef COMMUNITY_LANG_GROUP1_QR
|
||||
// case LANG_CODE_QR: return _n("New language"); //community contribution
|
||||
//#endif // COMMUNITY_LANG_GROUP1_QR
|
||||
#endif // COMMUNITY_LANGUAGE_SUPPORT
|
||||
|
|
@ -276,7 +275,7 @@ const char* lang_get_sec_lang_str_by_id(uint16_t id)
|
|||
return ui + pgm_read_word(((uint16_t*)(ui + 16 + id * 2))); //read relative offset and return calculated pointer
|
||||
}
|
||||
|
||||
uint16_t lang_print_sec_lang()
|
||||
uint16_t lang_print_sec_lang(FILE* out)
|
||||
{
|
||||
printf_P(_n("&_SEC_LANG = 0x%04x\n"), &_SEC_LANG);
|
||||
printf_P(_n("sizeof(_SEC_LANG) = 0x%04x\n"), sizeof(_SEC_LANG));
|
||||
|
|
@ -298,7 +297,7 @@ uint16_t lang_print_sec_lang()
|
|||
puts_P(_n(" strings:\n"));
|
||||
uint16_t ui = _SEC_LANG_TABLE; //table pointer
|
||||
for (ui = 0; ui < _lt_count; ui++)
|
||||
printf_P(_n(" %3d %S\n"), ui, lang_get_sec_lang_str_by_id(ui));
|
||||
fprintf_P(out, _n(" %3d %S\n"), ui, lang_get_sec_lang_str_by_id(ui));
|
||||
return _lt_count;
|
||||
}
|
||||
#endif //DEBUG_SEC_LANG
|
||||
|
|
|
|||
|
|
@ -13,15 +13,23 @@
|
|||
|
||||
#define PROTOCOL_VERSION "1.0"
|
||||
|
||||
#ifndef CUSTOM_MENDEL_NAME
|
||||
#define MACHINE_NAME "Mendel"
|
||||
#endif
|
||||
|
||||
#ifndef MACHINE_UUID
|
||||
#define MACHINE_UUID "00000000-0000-0000-0000-000000000000"
|
||||
#endif
|
||||
|
||||
#if (LANG_MODE == 0) //primary language only
|
||||
#define PROGMEM_I2 __attribute__((section(".progmem0")))
|
||||
#define PROGMEM_I1 __attribute__((section(".progmem1")))
|
||||
#define PROGMEM_N1 __attribute__((section(".progmem2")))
|
||||
#define _I(s) (__extension__({static const char __c[] PROGMEM_I1 = s; &__c[0];}))
|
||||
#define ISTR(s) (s) // declare a translatable string
|
||||
#define _i(s) _I(s) // declare a translatable string and return the translated form
|
||||
#define _T(s) (s) // return translated string from reference
|
||||
#define _O(s) (s) // return original (untranslated) string from reference
|
||||
#define ISTR(s) s
|
||||
#define _i(s) _I(s)
|
||||
#define _T(s) s
|
||||
#define _O(s) s
|
||||
#else //(LANG_MODE == 0)
|
||||
// section .loc_sec (originaly .progmem0) will be used for localized translated strings
|
||||
#define PROGMEM_I2 __attribute__((section(".loc_sec")))
|
||||
|
|
@ -35,15 +43,13 @@
|
|||
#define _T(s) lang_get_translation(s)
|
||||
#define _O(s) (s + 2)
|
||||
#endif //(LANG_MODE == 0)
|
||||
|
||||
#define _N(s) (__extension__({static const char __c[] PROGMEM_N1 = s; &__c[0];}))
|
||||
#define _n(s) _N(s) // declare and return untranslated string
|
||||
#define _R(s) (s) // return reference to translatable string (for warning suppression)
|
||||
#define _n(s) _N(s)
|
||||
|
||||
/** @brief lang_table_header_t structure - (size= 16byte) */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t magic; //+0
|
||||
uint32_t magic; //+0
|
||||
uint16_t size; //+4
|
||||
uint16_t count; //+6
|
||||
uint16_t checksum; //+8
|
||||
|
|
@ -115,9 +121,9 @@ typedef struct
|
|||
#ifdef COMMUNITY_LANG_GROUP1_HR
|
||||
#define LANG_CODE_HR 0x6872 //!<'hr'
|
||||
#endif // COMMUNITY_LANG_GROUP1_HR
|
||||
#ifdef COMMUNITY_LANG_GROUP2_LT
|
||||
#ifdef COMMUNITY_LANG_GROUP1_LT
|
||||
#define LANG_CODE_LT 0x6C74 //!<'lt'
|
||||
#endif // COMMUNITY_LANG_GROUP2_LT
|
||||
#endif // COMMUNITY_LANG_GROUP1_LT
|
||||
#ifdef COMMUNITY_LANG_GROUP1_SK
|
||||
#define LANG_CODE_SK 0x736b //!<'sk'
|
||||
#endif // COMMUNITY_LANG_GROUP1_SK
|
||||
|
|
@ -163,7 +169,7 @@ extern uint8_t lang_is_selected(void);
|
|||
|
||||
#ifdef DEBUG_SEC_LANG
|
||||
extern const char* lang_get_sec_lang_str_by_id(uint16_t id);
|
||||
extern uint16_t lang_print_sec_lang();
|
||||
extern uint16_t lang_print_sec_lang(FILE* out);
|
||||
#endif //DEBUG_SEC_LANG
|
||||
|
||||
extern void lang_boot_update_start(uint8_t lang);
|
||||
|
|
|
|||
837
Firmware/lcd.cpp
837
Firmware/lcd.cpp
File diff suppressed because it is too large
Load Diff
127
Firmware/lcd.h
127
Firmware/lcd.h
|
|
@ -22,11 +22,20 @@ extern void lcd_clear(void);
|
|||
|
||||
extern void lcd_home(void);
|
||||
|
||||
extern void lcd_set_cursor(uint8_t col, uint8_t row);
|
||||
/*extern void lcd_no_display(void);
|
||||
extern void lcd_display(void);
|
||||
extern void lcd_no_blink(void);
|
||||
extern void lcd_blink(void);
|
||||
extern void lcd_no_cursor(void);
|
||||
extern void lcd_cursor(void);
|
||||
extern void lcd_scrollDisplayLeft(void);
|
||||
extern void lcd_scrollDisplayRight(void);
|
||||
extern void lcd_leftToRight(void);
|
||||
extern void lcd_rightToLeft(void);
|
||||
extern void lcd_autoscroll(void);
|
||||
extern void lcd_no_autoscroll(void);*/
|
||||
|
||||
/// @brief Change the cursor column position while preserving the current row position
|
||||
/// @param col column number, ranges from 0 to LCD_WIDTH - 1
|
||||
void lcd_set_cursor_column(uint8_t col);
|
||||
extern void lcd_set_cursor(uint8_t col, uint8_t row);
|
||||
|
||||
extern void lcd_createChar_P(uint8_t, const uint8_t*);
|
||||
|
||||
|
|
@ -41,21 +50,29 @@ extern int lcd_printf_P(const char* format, ...);
|
|||
extern void lcd_space(uint8_t n);
|
||||
|
||||
extern void lcd_printNumber(unsigned long n, uint8_t base);
|
||||
extern void lcd_printFloat(double number, uint8_t digits);
|
||||
|
||||
extern void lcd_print(const char*);
|
||||
extern uint8_t lcd_print_pad(const char* s, uint8_t len);
|
||||
|
||||
/// @brief print a string from PROGMEM with left-adjusted padding
|
||||
/// @param s string from PROGMEM.
|
||||
/// @param len maximum number of characters to print, including padding. Ranges from 0 to LCD_WIDTH.
|
||||
/// @return number of padded bytes. 0 means there was no padding.
|
||||
uint8_t lcd_print_pad_P(const char* s, uint8_t len);
|
||||
extern void lcd_print(char, int = 0);
|
||||
extern void lcd_print(unsigned char, int = 0);
|
||||
extern void lcd_print(int, int = 10);
|
||||
extern void lcd_print(unsigned int, int = 10);
|
||||
extern void lcd_print(long, int = 10);
|
||||
extern void lcd_print(unsigned long, int = 10);
|
||||
extern void lcd_print(double, int = 2);
|
||||
|
||||
//! @brief Clear screen
|
||||
#define ESC_2J "\x1b[2J"
|
||||
//! @brief Show cursor
|
||||
#define ESC_25h "\x1b[?25h"
|
||||
//! @brief Hide cursor
|
||||
#define ESC_25l "\x1b[?25l"
|
||||
//! @brief Set cursor to
|
||||
//! @param c column
|
||||
//! @param r row
|
||||
#define ESC_H(c,r) "\x1b["#r";"#c"H"
|
||||
|
||||
|
||||
|
||||
#define LCD_UPDATE_INTERVAL 100
|
||||
#define LCD_TIMEOUT_TO_STATUS 30000ul //!< Generic timeout to status screen in ms, when no user action.
|
||||
|
|
@ -72,9 +89,17 @@ typedef void (*lcd_lcdupdate_func_t)(void);
|
|||
//Set to none-zero when the LCD needs to draw, decreased after every draw. Set to 2 in LCD routines so the LCD gets at least 1 full redraw (first redraw is partial)
|
||||
extern uint8_t lcd_draw_update;
|
||||
|
||||
extern int16_t lcd_encoder;
|
||||
extern int32_t lcd_encoder;
|
||||
|
||||
extern uint8_t lcd_click_trigger;
|
||||
extern uint8_t lcd_encoder_bits;
|
||||
|
||||
// lcd_encoder_diff is updated from interrupt context and added to lcd_encoder every LCD update
|
||||
extern int8_t lcd_encoder_diff;
|
||||
|
||||
//the last checked lcd_buttons in a bit array.
|
||||
extern uint8_t lcd_buttons;
|
||||
|
||||
extern uint8_t lcd_button_pressed;
|
||||
|
||||
extern uint8_t lcd_update_enabled;
|
||||
|
||||
|
|
@ -82,9 +107,13 @@ extern LongTimer lcd_timeoutToStatus;
|
|||
|
||||
extern uint32_t lcd_next_update_millis;
|
||||
|
||||
extern uint8_t lcd_status_update_delay;
|
||||
|
||||
extern lcd_longpress_func_t lcd_longpress_func;
|
||||
extern bool lcd_longpress_trigger;
|
||||
|
||||
extern lcd_charsetup_func_t lcd_charsetup_func;
|
||||
|
||||
extern lcd_lcdupdate_func_t lcd_lcdupdate_func;
|
||||
|
||||
|
||||
|
|
@ -96,10 +125,6 @@ extern void lcd_beeper_quick_feedback(void);
|
|||
//Cause an LCD refresh, and give the user visual or audible feedback that something has happened
|
||||
extern void lcd_quick_feedback(void);
|
||||
|
||||
/// @brief Check whether knob is rotated or clicked and update relevant
|
||||
///variables. Flags are set by lcd_buttons_update in ISR context.
|
||||
extern void lcd_knob_update();
|
||||
|
||||
extern void lcd_update(uint8_t lcdDrawUpdateOverride);
|
||||
|
||||
extern void lcd_update_enable(uint8_t enabled);
|
||||
|
|
@ -111,25 +136,38 @@ extern void lcd_buttons_update(void);
|
|||
//! When constructed (on stack), original state state of lcd_update_enabled is stored
|
||||
//! and LCD updates are disabled.
|
||||
//! When destroyed (gone out of scope), original state of LCD update is restored.
|
||||
//! Do not call lcd_update_enable() to prevent calling lcd_update() in sensitive code.
|
||||
//! in certain scenarios it will cause recursion e.g. in the menus.
|
||||
//! It has zero overhead compared to storing bool saved = lcd_update_enabled
|
||||
//! and calling lcd_update_enable(false) and lcd_update_enable(saved).
|
||||
class LcdUpdateDisabler
|
||||
{
|
||||
public:
|
||||
LcdUpdateDisabler(): m_updateEnabled(lcd_update_enabled)
|
||||
{
|
||||
lcd_update_enabled = false;
|
||||
lcd_update_enable(false);
|
||||
}
|
||||
~LcdUpdateDisabler()
|
||||
{
|
||||
lcd_update_enabled = m_updateEnabled;
|
||||
lcd_update_enable(m_updateEnabled);
|
||||
}
|
||||
|
||||
private:
|
||||
bool m_updateEnabled;
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////
|
||||
// Setup button and encode mappings for each panel (into 'lcd_buttons' variable
|
||||
//
|
||||
// This is just to map common functions (across different panels) onto the same
|
||||
// macro name. The mapping is independent of whether the button is directly connected or
|
||||
// via a shift/i2c register.
|
||||
|
||||
#define BLEN_B 1
|
||||
#define BLEN_A 0
|
||||
#define EN_B (1<<BLEN_B) // The two encoder pins are connected through BTN_EN1 and BTN_EN2
|
||||
#define EN_A (1<<BLEN_A)
|
||||
#define BLEN_C 2
|
||||
#define EN_C (1<<BLEN_C)
|
||||
|
||||
//! @brief Was button clicked?
|
||||
//!
|
||||
|
|
@ -140,32 +178,41 @@ private:
|
|||
//!
|
||||
//! @retval 0 button was not clicked
|
||||
//! @retval 1 button was clicked
|
||||
#define LCD_CLICKED (lcd_click_trigger)
|
||||
#define LCD_CLICKED (lcd_buttons&EN_C)
|
||||
|
||||
////////////////////////
|
||||
// Setup Rotary Encoder Bit Values (for two pin encoders to indicate movement)
|
||||
// These values are independent of which pins are used for EN_A and EN_B indications
|
||||
// The rotary encoder part is also independent to the chipset used for the LCD
|
||||
#define encrot0 0
|
||||
#define encrot1 2
|
||||
#define encrot2 3
|
||||
#define encrot3 1
|
||||
|
||||
////////////////////////////////////
|
||||
|
||||
//Custom characters defined in the first 8 characters of the LCD
|
||||
#define LCD_STR_ARROW_RIGHT "\x7E" //from the default character set
|
||||
#define LCD_STR_ARROW_LEFT "\x7F" //from the default character set
|
||||
#define LCD_STR_BEDTEMP "\x80"
|
||||
#define LCD_STR_DEGREE "\x81"
|
||||
#define LCD_STR_THERMOMETER "\x82"
|
||||
#define LCD_STR_UPLEVEL "\x83"
|
||||
#define LCD_STR_REFRESH "\x84"
|
||||
#define LCD_STR_FOLDER "\x85"
|
||||
#define LCD_STR_FEEDRATE "\x86"
|
||||
#define LCD_STR_CLOCK "\x87"
|
||||
#define LCD_STR_ARROW_2_DOWN "\x88"
|
||||
#define LCD_STR_CONFIRM "\x89"
|
||||
#define LCD_STR_SOLID_BLOCK "\xFF" //from the default character set
|
||||
#define LCD_STR_BEDTEMP "\x00"
|
||||
#define LCD_STR_DEGREE "\x01"
|
||||
#define LCD_STR_THERMOMETER "\x02"
|
||||
#define LCD_STR_UPLEVEL "\x03"
|
||||
#define LCD_STR_REFRESH "\x04"
|
||||
#define LCD_STR_FOLDER "\x05"
|
||||
#define LCD_STR_FEEDRATE "\x06"
|
||||
#define LCD_STR_CLOCK "\x07"
|
||||
#define LCD_STR_ARROW_UP "\x0B"
|
||||
#define LCD_STR_ARROW_DOWN "\x01"
|
||||
#define LCD_STR_ARROW_RIGHT "\x7E" //from the default character set
|
||||
|
||||
extern void lcd_frame_start();
|
||||
extern void lcd_set_custom_characters(void);
|
||||
extern void lcd_set_custom_characters_arrows(void);
|
||||
extern void lcd_set_custom_characters_nextpage(void);
|
||||
extern void lcd_set_custom_characters_degree(void);
|
||||
|
||||
//! @brief Consume click and longpress event
|
||||
//! @brief Consume click event
|
||||
inline void lcd_consume_click()
|
||||
{
|
||||
lcd_click_trigger = 0;
|
||||
lcd_longpress_trigger = 0;
|
||||
lcd_button_pressed = 0;
|
||||
lcd_buttons &= 0xff^EN_C;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -11,9 +11,6 @@
|
|||
#define CRITICAL_SECTION_END SREG = _sreg;
|
||||
#endif //CRITICAL_SECTION_START
|
||||
|
||||
#define _REGNAME(registerbase,number,suffix) registerbase##number##suffix
|
||||
#define _REGNAME_SHORT(registerbase,suffix) registerbase##suffix
|
||||
|
||||
// Macros to make a string from a macro
|
||||
#define STRINGIFY_(M) #M
|
||||
#define STRINGIFY(M) STRINGIFY_(M)
|
||||
|
|
|
|||
|
|
@ -1,379 +0,0 @@
|
|||
/*
|
||||
* MeatPack G-Code Compression
|
||||
*
|
||||
* Algorithm & Implementation: Scott Mudge - mail@scottmudge.com
|
||||
* Date: Dec. 2020
|
||||
*/
|
||||
|
||||
#include "meatpack.h"
|
||||
|
||||
#ifdef ENABLE_MEATPACK
|
||||
|
||||
#include "language.h"
|
||||
#include "Marlin.h"
|
||||
|
||||
//#define MP_DEBUG
|
||||
|
||||
// Utility definitions
|
||||
#define MeatPack_CommandByte 0b11111111
|
||||
#define MeatPack_NextPackedFirst 0b00000001
|
||||
#define MeatPack_NextPackedSecond 0b00000010
|
||||
|
||||
#define MeatPack_SpaceCharIdx 11U
|
||||
#define MeatPack_SpaceCharReplace 'E'
|
||||
|
||||
#define MeatPack_ProtocolVersion "PV01"
|
||||
|
||||
/*
|
||||
|
||||
Character Frequencies from ~30 MB of comment-stripped gcode:
|
||||
|
||||
'1' -> 4451136
|
||||
'0' -> 4253577
|
||||
' ' -> 3053297
|
||||
'.' -> 3035310
|
||||
'2' -> 1523296
|
||||
'8' -> 1366812
|
||||
'4' -> 1353273
|
||||
'9' -> 1352147
|
||||
'3' -> 1262929
|
||||
'5' -> 1189871
|
||||
'6' -> 1127900
|
||||
'7' -> 1112908
|
||||
'\n' -> 1087683
|
||||
'G' -> 1075806
|
||||
'X' -> 975742
|
||||
'E' -> 965275
|
||||
'Y' -> 965274
|
||||
'F' -> 99416
|
||||
'-' -> 90242
|
||||
'Z' -> 34109
|
||||
'M' -> 11879
|
||||
'S' -> 9910
|
||||
|
||||
If spaces are omitted, we add 'E'
|
||||
|
||||
*/
|
||||
|
||||
// Note:
|
||||
// I've tried both a switch/case method and a lookup table. The disassembly is exactly the same after compilation, byte-to-byte.
|
||||
// Thus, performance is identical.
|
||||
#define USE_LOOKUP_TABLE
|
||||
|
||||
// State variables
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
enum MeatPack_ConfigStateFlags {
|
||||
MPConfig_None = 0,
|
||||
MPConfig_Active = (1 << 0),
|
||||
MPConfig_NoSpaces = (1 << 1)
|
||||
};
|
||||
|
||||
uint8_t mp_config = MPConfig_None; // Configuration state
|
||||
uint8_t mp_cmd_active = 0; // Is a command is pending
|
||||
uint8_t mp_char_buf = 0; // Buffers a character if dealing with out-of-sequence pairs
|
||||
uint8_t mp_cmd_count = 0; // Counts how many command bytes are received (need 2)
|
||||
uint8_t mp_full_char_queue = 0; // Counts how many full-width characters are to be received
|
||||
uint8_t mp_char_out_buf[2]; // Output buffer for caching up to 2 characters
|
||||
uint8_t mp_char_out_count = 0; // Stores number of characters to be read out.
|
||||
|
||||
|
||||
#ifdef USE_LOOKUP_TABLE
|
||||
// The 15 most-common characters used in G-code, ~90-95% of all g-code uses these characters
|
||||
// NOT storing this with PROGMEM, given how frequently this table will be accessed.
|
||||
uint8_t MeatPackLookupTbl[16] = {
|
||||
'0', // 0000
|
||||
'1', // 0001
|
||||
'2', // 0010
|
||||
'3', // 0011
|
||||
'4', // 0100
|
||||
'5', // 0101
|
||||
'6', // 0110
|
||||
'7', // 0111
|
||||
'8', // 1000
|
||||
'9', // 1001
|
||||
'.', // 1010
|
||||
' ', // 1011
|
||||
'\n', // 1100
|
||||
'G', // 1101
|
||||
'X', // 1110
|
||||
'\0' // never used, 0b1111 is used to indicate next 8-bits is a full character
|
||||
};
|
||||
#else
|
||||
inline uint8_t get_char(const uint8_t in) {
|
||||
switch (in) {
|
||||
case 0b0000:
|
||||
return '0';
|
||||
break;
|
||||
case 0b0001:
|
||||
return '1';
|
||||
break;
|
||||
case 0b0010:
|
||||
return '2';
|
||||
break;
|
||||
case 0b0011:
|
||||
return '3';
|
||||
break;
|
||||
case 0b0100:
|
||||
return '4';
|
||||
break;
|
||||
case 0b0101:
|
||||
return '5';
|
||||
break;
|
||||
case 0b0110:
|
||||
return '6';
|
||||
break;
|
||||
case 0b0111:
|
||||
return '7';
|
||||
break;
|
||||
case 0b1000:
|
||||
return '8';
|
||||
break;
|
||||
case 0b1001:
|
||||
return '9';
|
||||
break;
|
||||
case 0b1010:
|
||||
return '.';
|
||||
break;
|
||||
case 0b1011:
|
||||
return (mp_config & MPConfig_NoSpaces) ? MeatPack_SpaceCharReplace : ' ';
|
||||
break;
|
||||
case 0b1100:
|
||||
return '\n';
|
||||
break;
|
||||
case 0b1101:
|
||||
return 'G';
|
||||
break;
|
||||
case 0b1110:
|
||||
return 'X';
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
// #DEBUGGING
|
||||
#ifdef MP_DEBUG
|
||||
uint32_t mp_chars_decoded = 0;
|
||||
#endif
|
||||
|
||||
void FORCE_INLINE mp_handle_output_char(const uint8_t c) {
|
||||
mp_char_out_buf[mp_char_out_count++] = c;
|
||||
|
||||
#ifdef MP_DEBUG
|
||||
if (mp_chars_decoded < 4096) {
|
||||
++mp_chars_decoded;
|
||||
SERIAL_ECHOPGM("RB: ");
|
||||
MYSERIAL.print((char)c);
|
||||
SERIAL_ECHOLNPGM("");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Storing
|
||||
// packed = ((low & 0xF) << 4) | (high & 0xF);
|
||||
|
||||
// Unpacking
|
||||
// low = (packed >> 4) & 0xF;
|
||||
// high = (packed & 0xF);
|
||||
|
||||
//==========================================================================
|
||||
uint8_t FORCE_INLINE mp_unpack_chars(const uint8_t pk, uint8_t* __restrict const chars_out) {
|
||||
uint8_t out = 0;
|
||||
|
||||
#ifdef USE_LOOKUP_TABLE
|
||||
// If lower 4 bytes is 0b1111, the higher 4 are unused, and next char is full.
|
||||
if ((pk & MeatPack_FirstNotPacked) == MeatPack_FirstNotPacked) out |= MeatPack_NextPackedFirst;
|
||||
else chars_out[0] = MeatPackLookupTbl[(pk & 0xF)]; // Assign lower char
|
||||
|
||||
// Check if upper 4 bytes is 0b1111... if so, we don't need the second char.
|
||||
if ((pk & MeatPack_SecondNotPacked) == MeatPack_SecondNotPacked) out |= MeatPack_NextPackedSecond;
|
||||
else chars_out[1] = MeatPackLookupTbl[((pk >> 4) & 0xf)]; // Assign upper char
|
||||
#else
|
||||
// If lower 4 bytes is 0b1111, the higher 4 are unused, and next char is full.
|
||||
if ((pk & MeatPack_FirstNotPacked) == MeatPack_FirstNotPacked) out |= MeatPack_NextPackedFirst;
|
||||
else chars_out[0] = get_char(pk & 0xF); // Assign lower char
|
||||
|
||||
// Check if upper 4 bytes is 0b1111... if so, we don't need the second char.
|
||||
if ((pk & MeatPack_SecondNotPacked) == MeatPack_SecondNotPacked) out |= MeatPack_NextPackedSecond;
|
||||
else chars_out[1] = get_char((pk >> 4) & 0xf); // Assign upper char
|
||||
#endif
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void FORCE_INLINE mp_reset_state() {
|
||||
mp_char_out_count = 0;
|
||||
mp_cmd_active = MPCommand_None;
|
||||
mp_config = MPConfig_None;
|
||||
mp_char_buf = 0;
|
||||
mp_cmd_count = 0;
|
||||
mp_cmd_active = 0;
|
||||
mp_full_char_queue = 0;
|
||||
|
||||
#ifdef MP_DEBUG
|
||||
mp_chars_decoded = 0;
|
||||
SERIAL_ECHOLNPGM("MP Reset");
|
||||
#endif
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
void FORCE_INLINE mp_handle_rx_char_inner(const uint8_t c) {
|
||||
|
||||
// Packing enabled, handle character and re-arrange them appropriately.
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
if (mp_config & MPConfig_Active) {
|
||||
if (mp_full_char_queue > 0) {
|
||||
mp_handle_output_char(c);
|
||||
if (mp_char_buf > 0) {
|
||||
mp_handle_output_char(mp_char_buf);
|
||||
mp_char_buf = 0;
|
||||
}
|
||||
--mp_full_char_queue;
|
||||
}
|
||||
else {
|
||||
uint8_t buf[2] = { 0,0 };
|
||||
const uint8_t res = mp_unpack_chars(c, buf);
|
||||
|
||||
if (res & MeatPack_NextPackedFirst) {
|
||||
++mp_full_char_queue;
|
||||
if (res & MeatPack_NextPackedSecond) ++mp_full_char_queue;
|
||||
else mp_char_buf = buf[1];
|
||||
}
|
||||
else {
|
||||
mp_handle_output_char(buf[0]);
|
||||
if (buf[0] != '\n') {
|
||||
if (res & MeatPack_NextPackedSecond) ++mp_full_char_queue;
|
||||
else mp_handle_output_char(buf[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else // Packing not enabled, just copy character to output
|
||||
mp_handle_output_char(c);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
void FORCE_INLINE mp_echo_config_state() {
|
||||
SERIAL_ECHOPGM(" [MP] "); // Add space at idx 0 just in case first character is dropped due to timing/sync issues.
|
||||
|
||||
// NOTE: if any configuration vars are added below, the outgoing sync text for host plugin
|
||||
// should not contain the "PV' substring, as this is used to indicate protocol version
|
||||
SERIAL_ECHOPGM(MeatPack_ProtocolVersion);
|
||||
|
||||
// Echo current state
|
||||
if (mp_config & MPConfig_Active)
|
||||
SERIAL_ECHOPGM(" ON");
|
||||
else
|
||||
SERIAL_ECHOPGM(" OFF");
|
||||
|
||||
if (mp_config & MPConfig_NoSpaces)
|
||||
SERIAL_ECHOPGM(" NSP"); // [N]o [SP]aces
|
||||
else
|
||||
SERIAL_ECHOPGM(" ESP"); // [E]nabled [SP]aces
|
||||
|
||||
SERIAL_ECHOLNPGM("");
|
||||
|
||||
// Validate config vars
|
||||
#ifdef USE_LOOKUP_TABLE
|
||||
if (mp_config & MPConfig_NoSpaces)
|
||||
MeatPackLookupTbl[MeatPack_SpaceCharIdx] = (uint8_t)(MeatPack_SpaceCharReplace);
|
||||
else
|
||||
MeatPackLookupTbl[MeatPack_SpaceCharIdx] = ' ';
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
void FORCE_INLINE mp_handle_cmd(const MeatPack_Command c) {
|
||||
switch (c) {
|
||||
case MPCommand_EnablePacking: {
|
||||
mp_config |= MPConfig_Active;
|
||||
#ifdef MP_DEBUG
|
||||
SERIAL_ECHOLNPGM("[MPDBG] ENABL REC");
|
||||
#endif
|
||||
} break;
|
||||
case MPCommand_DisablePacking: {
|
||||
mp_config &= ~(MPConfig_Active);
|
||||
#ifdef MP_DEBUG
|
||||
SERIAL_ECHOLNPGM("[MPDBG] DISBL REC");
|
||||
#endif
|
||||
} break;
|
||||
case MPCommand_ResetAll: {
|
||||
mp_reset_state();
|
||||
#ifdef MP_DEBUG
|
||||
SERIAL_ECHOLNPGM("[MPDBG] RESET REC");
|
||||
#endif
|
||||
} break;
|
||||
case MPCommand_EnableNoSpaces: {
|
||||
mp_config |= MPConfig_NoSpaces;
|
||||
#ifdef MP_DEBUG
|
||||
SERIAL_ECHOLNPGM("[MPDBG] ENABL NSP");
|
||||
#endif
|
||||
} break;
|
||||
case MPCommand_DisableNoSpaces: {
|
||||
mp_config &= ~(MPConfig_NoSpaces);
|
||||
#ifdef MP_DEBUG
|
||||
SERIAL_ECHOLNPGM("[MPDBG] DISBL NSP");
|
||||
#endif
|
||||
} break;
|
||||
default: {
|
||||
#ifdef MP_DEBUG
|
||||
SERIAL_ECHOLN("[MPDBG] UNK CMD REC");
|
||||
#endif
|
||||
}
|
||||
case MPCommand_QueryConfig:
|
||||
break;
|
||||
}
|
||||
|
||||
mp_echo_config_state();
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
void mp_handle_rx_char(const uint8_t c) {
|
||||
|
||||
// Check for commit complete
|
||||
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
if (c == (uint8_t)(MeatPack_CommandByte)) {
|
||||
if (mp_cmd_count > 0) {
|
||||
mp_cmd_active = 1;
|
||||
mp_cmd_count = 0;
|
||||
}
|
||||
else
|
||||
++mp_cmd_count;
|
||||
return;
|
||||
}
|
||||
|
||||
if (mp_cmd_active > 0) {
|
||||
mp_handle_cmd((MeatPack_Command)c);
|
||||
mp_cmd_active = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (mp_cmd_count > 0) {
|
||||
mp_handle_rx_char_inner((uint8_t)(MeatPack_CommandByte));
|
||||
mp_cmd_count = 0;
|
||||
}
|
||||
|
||||
mp_handle_rx_char_inner(c);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
uint8_t mp_get_result_char(char* const __restrict out) {
|
||||
if (mp_char_out_count > 0) {
|
||||
const uint8_t res = mp_char_out_count;
|
||||
for (uint8_t i = 0; i < mp_char_out_count; ++i)
|
||||
out[i] = (char)mp_char_out_buf[i];
|
||||
mp_char_out_count = 0;
|
||||
return res;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void mp_trigger_cmd(const MeatPack_Command cmd)
|
||||
{
|
||||
mp_handle_cmd(cmd);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
/*
|
||||
* MeatPack G-Code Compression
|
||||
*
|
||||
* Algorithm & Implementation: Scott Mudge - mail@scottmudge.com
|
||||
* Date: Dec. 2020
|
||||
*
|
||||
* Specifically optimized for 3D printing G-Code, this is a zero-cost data compression method
|
||||
* which packs ~180-190% more data into the same amount of bytes going to the CNC controller.
|
||||
* As a majority of G-Code can be represented by a restricted alphabet, I performed histogram
|
||||
* analysis on a wide variety of 3D printing gcode samples, and found ~93% of all gcode could
|
||||
* be represented by the same 15-character alphabet.
|
||||
*
|
||||
* This allowed me to design a system of packing 2 8-bit characters into a single byte, assuming
|
||||
* they fall within this limited 15-character alphabet. Using a 4-bit lookup table, these 8-bit
|
||||
* characters can be represented by a 4-bit index.
|
||||
*
|
||||
* Combined with some logic to allow commingling of full-width characters outside of this 15-
|
||||
* character alphabet (at the cost of an extra 8-bits per full-width character), and by stripping
|
||||
* out unnecessary comments, the end result is gcode which is roughly half the original size.
|
||||
*
|
||||
* Why did I do this? I noticed micro-stuttering and other data-bottleneck issues while printing
|
||||
* objects with high curvature, especially at high speeds. There is also the issue of the limited
|
||||
* baud rate provided by Prusa's Atmega2560-based boards, over the USB serial connection. So soft-
|
||||
* ware like OctoPrint would also suffer this same micro-stuttering and poor print quality issue.
|
||||
*
|
||||
*/
|
||||
#include <stdint.h>
|
||||
#include "Configuration.h"
|
||||
|
||||
#ifndef MEATPACK_H_
|
||||
#define MEATPACK_H_
|
||||
|
||||
#ifdef ENABLE_MEATPACK
|
||||
|
||||
#define MeatPack_SecondNotPacked 0b11110000
|
||||
#define MeatPack_FirstNotPacked 0b00001111
|
||||
|
||||
// These are commands sent to MeatPack to control its behavior.
|
||||
// They are sent by first sending 2x MeatPack_CommandByte (0xFF) in sequence,
|
||||
// followed by one of the command bytes below.
|
||||
// Provided that 0xFF is an exceedingly rare character that is virtually never
|
||||
// present in g-code naturally, it is safe to assume 2 in sequence should never
|
||||
// happen naturally, and so it is used as a signal here.
|
||||
//
|
||||
// 0xFF *IS* used in "packed" g-code (used to denote that the next 2 characters are
|
||||
// full-width), however 2 in a row will never occur, as the next 2 bytes will always
|
||||
// some non-0xFF character.
|
||||
enum MeatPack_Command {
|
||||
MPCommand_None = 0U,
|
||||
// MPCommand_TogglePacking = 253U, -- Unused, byte 253 can be re-used later.
|
||||
MPCommand_EnablePacking = 251U,
|
||||
MPCommand_DisablePacking = 250U,
|
||||
MPCommand_ResetAll = 249U,
|
||||
MPCommand_QueryConfig = 248U,
|
||||
MPCommand_EnableNoSpaces = 247U,
|
||||
MPCommand_DisableNoSpaces = 246U
|
||||
};
|
||||
|
||||
// Pass in a character rx'd by SD card or serial. Automatically parses command/ctrl sequences,
|
||||
// and will control state internally.
|
||||
extern void mp_handle_rx_char(const uint8_t c);
|
||||
|
||||
// After passing in rx'd char using above method, call this to get characters out. Can return
|
||||
// from 0 to 2 characters at once.
|
||||
// @param out [in] Output pointer for unpacked/processed data.
|
||||
// @return Number of characters returned. Range from 0 to 2.
|
||||
extern uint8_t mp_get_result_char(char* const __restrict out);
|
||||
#endif
|
||||
|
||||
#endif // MEATPACK_H_
|
||||
|
|
@ -24,7 +24,7 @@ uint8_t menu_data[MENU_DATA_SIZE];
|
|||
#endif
|
||||
|
||||
uint8_t menu_depth = 0;
|
||||
uint8_t menu_block_mask = MENU_BLOCK_NONE;
|
||||
uint8_t menu_block_entering_on_serious_errors = SERIOUS_ERR_NONE;
|
||||
uint8_t menu_line = 0;
|
||||
uint8_t menu_item = 0;
|
||||
uint8_t menu_row = 0;
|
||||
|
|
@ -45,7 +45,7 @@ void menu_data_reset(void)
|
|||
memset(&menu_data, 0, sizeof(menu_data));
|
||||
}
|
||||
|
||||
void menu_goto(menu_func_t menu, const int16_t encoder, bool reset_menu_state, const bool feedback)
|
||||
void menu_goto(menu_func_t menu, const uint32_t encoder, const bool feedback, bool reset_menu_state)
|
||||
{
|
||||
CRITICAL_SECTION_START;
|
||||
if (menu_menu != menu)
|
||||
|
|
@ -53,10 +53,11 @@ void menu_goto(menu_func_t menu, const int16_t encoder, bool reset_menu_state, c
|
|||
menu_menu = menu;
|
||||
lcd_encoder = encoder;
|
||||
menu_top = 0; //reset menu view. Needed if menu_back() is called from deep inside a menu, such as Support
|
||||
lcd_draw_update = 2; // Full LCD re-draw
|
||||
CRITICAL_SECTION_END;
|
||||
if (feedback) lcd_beeper_quick_feedback();
|
||||
if (reset_menu_state) menu_data_reset();
|
||||
if (reset_menu_state)
|
||||
menu_data_reset();
|
||||
|
||||
if (feedback) lcd_quick_feedback();
|
||||
}
|
||||
else
|
||||
CRITICAL_SECTION_END;
|
||||
|
|
@ -64,6 +65,7 @@ void menu_goto(menu_func_t menu, const int16_t encoder, bool reset_menu_state, c
|
|||
|
||||
void menu_start(void)
|
||||
{
|
||||
if (lcd_encoder > 0x8000) lcd_encoder = 0;
|
||||
if (lcd_encoder < 0)
|
||||
{
|
||||
lcd_encoder = 0;
|
||||
|
|
@ -72,16 +74,11 @@ void menu_start(void)
|
|||
if (lcd_encoder < menu_top)
|
||||
menu_top = lcd_encoder;
|
||||
menu_line = menu_top;
|
||||
menu_clicked = lcd_clicked(); // Consume click event
|
||||
menu_clicked = LCD_CLICKED;
|
||||
}
|
||||
|
||||
void menu_end(void)
|
||||
{
|
||||
if (menu_row >= LCD_HEIGHT)
|
||||
{
|
||||
// Early abort if the menu was clicked. The current menu might have changed because of the click event
|
||||
return;
|
||||
}
|
||||
if (lcd_encoder >= menu_item)
|
||||
{
|
||||
lcd_encoder = menu_item - 1;
|
||||
|
|
@ -90,6 +87,7 @@ void menu_end(void)
|
|||
if (((uint8_t)lcd_encoder) >= menu_top + LCD_HEIGHT)
|
||||
{
|
||||
menu_top = lcd_encoder - LCD_HEIGHT + 1;
|
||||
lcd_draw_update = 1;
|
||||
menu_line = menu_top - 1;
|
||||
menu_row = -1;
|
||||
}
|
||||
|
|
@ -98,7 +96,7 @@ void menu_end(void)
|
|||
void menu_back(uint8_t nLevel)
|
||||
{
|
||||
menu_depth = ((menu_depth > nLevel) ? (menu_depth - nLevel) : 0);
|
||||
menu_goto(menu_stack[menu_depth].menu, menu_stack[menu_depth].position, true);
|
||||
menu_goto(menu_stack[menu_depth].menu, menu_stack[menu_depth].position, true, true);
|
||||
}
|
||||
|
||||
void menu_back(void)
|
||||
|
|
@ -110,8 +108,8 @@ void menu_back_no_reset(void)
|
|||
{
|
||||
if (menu_depth > 0)
|
||||
{
|
||||
menu_depth--;
|
||||
menu_goto(menu_stack[menu_depth].menu, menu_stack[menu_depth].position, false);
|
||||
menu_depth--;
|
||||
menu_goto(menu_stack[menu_depth].menu, menu_stack[menu_depth].position, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -121,46 +119,71 @@ void menu_back_if_clicked(void)
|
|||
menu_back();
|
||||
}
|
||||
|
||||
void menu_submenu(menu_func_t submenu, const bool feedback)
|
||||
void menu_back_if_clicked_fb(void)
|
||||
{
|
||||
if (lcd_clicked())
|
||||
{
|
||||
lcd_quick_feedback();
|
||||
menu_back();
|
||||
}
|
||||
}
|
||||
|
||||
void menu_submenu(menu_func_t submenu)
|
||||
{
|
||||
if (menu_depth < MENU_DEPTH_MAX)
|
||||
{
|
||||
menu_stack[menu_depth].menu = menu_menu;
|
||||
menu_stack[menu_depth++].position = lcd_encoder;
|
||||
menu_goto(submenu, 0, true, feedback);
|
||||
menu_goto(submenu, 0, true, true);
|
||||
}
|
||||
}
|
||||
|
||||
void menu_submenu_no_reset(menu_func_t submenu, const bool feedback)
|
||||
void menu_submenu_no_reset(menu_func_t submenu)
|
||||
{
|
||||
if (menu_depth < MENU_DEPTH_MAX)
|
||||
{
|
||||
menu_stack[menu_depth].menu = menu_menu;
|
||||
menu_stack[menu_depth++].position = lcd_encoder;
|
||||
menu_goto(submenu, 0, false, feedback);
|
||||
menu_goto(submenu, 0, true, false);
|
||||
}
|
||||
}
|
||||
|
||||
void menu_item_ret(void)
|
||||
uint8_t menu_item_ret(void)
|
||||
{
|
||||
lcd_beeper_quick_feedback();
|
||||
lcd_draw_update = 2;
|
||||
menu_item++;
|
||||
|
||||
//prevent the rest of the menu items from rendering or getting clicked
|
||||
menu_row = LCD_HEIGHT; // early exit from the MENU_BEGIN() for loop at the end of the current cycle
|
||||
menu_line = 0; // prevent subsequent menu items from rendering at all in the current MENU_BEGIN() for loop cycle
|
||||
menu_clicked = 0; // prevent subsequent items from being able to be clicked in case the current menu or position was changed by the clicked menu item
|
||||
lcd_button_pressed = false;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
int menu_draw_item_printf_P(char type_char, const char* format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int ret = 0;
|
||||
lcd_set_cursor(0, menu_row);
|
||||
if (lcd_encoder == menu_item)
|
||||
lcd_print('>');
|
||||
else
|
||||
lcd_print(' ');
|
||||
int cnt = vfprintf_P(lcdout, format, args);
|
||||
for (int i = cnt; i < 18; i++)
|
||||
lcd_print(' ');
|
||||
lcd_print(type_char);
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
*/
|
||||
|
||||
static char menu_selection_mark(){
|
||||
return (lcd_encoder == menu_item)?'>':' ';
|
||||
}
|
||||
|
||||
static void menu_draw_item_puts_P(char type_char, const char* str)
|
||||
{
|
||||
lcd_putc_at(0, menu_row, menu_selection_mark());
|
||||
lcd_print_pad_P(str, LCD_WIDTH - 2);
|
||||
lcd_putc(type_char);
|
||||
lcd_set_cursor(0, menu_row);
|
||||
lcd_printf_P(PSTR("%c%-18.18S%c"), menu_selection_mark(), str, type_char);
|
||||
}
|
||||
|
||||
static void menu_draw_toggle_puts_P(const char* str, const char* toggle, const uint8_t settings)
|
||||
|
|
@ -169,21 +192,14 @@ static void menu_draw_toggle_puts_P(const char* str, const char* toggle, const u
|
|||
//xxxxxcba
|
||||
//a = selection mark. If it's set(1), then '>' will be used as the first character on the line. Else leave blank
|
||||
//b = toggle string is from progmem
|
||||
uint8_t is_progmem = settings & 0x02;
|
||||
const char eol = (toggle == NULL) ? LCD_STR_ARROW_RIGHT[0] : ' ';
|
||||
//c = do not set cursor at all. Must be handled externally.
|
||||
char lineStr[LCD_WIDTH + 1];
|
||||
const char eol = (toggle == NULL)?LCD_STR_ARROW_RIGHT[0]:' ';
|
||||
if (toggle == NULL) toggle = _T(MSG_NA);
|
||||
uint8_t len = 4 + (is_progmem ? strlen_P(toggle) : strlen(toggle));
|
||||
lcd_putc_at(0, menu_row, (settings & 0x01) ? '>' : ' ');
|
||||
lcd_print_pad_P(str, LCD_WIDTH - len);
|
||||
lcd_putc('[');
|
||||
if (is_progmem)
|
||||
{
|
||||
lcd_puts_P(toggle);
|
||||
} else {
|
||||
lcd_print(toggle);
|
||||
}
|
||||
lcd_putc(']');
|
||||
lcd_putc(eol);
|
||||
sprintf_P(lineStr, PSTR("%c%-18.18S"), (settings & 0x01)?'>':' ', str);
|
||||
sprintf_P(lineStr + LCD_WIDTH - ((settings & 0x02)?strlen_P(toggle):strlen(toggle)) - 3, (settings & 0x02)?PSTR("[%S]%c"):PSTR("[%s]%c"), toggle, eol);
|
||||
if (!(settings & 0x04)) lcd_set_cursor(0, menu_row);
|
||||
fputs(lineStr, lcdout);
|
||||
}
|
||||
|
||||
//! @brief Format sheet name
|
||||
|
|
@ -216,32 +232,38 @@ void menu_format_sheet_select_E(const Sheet &sheet_E, SheetFormatBuffer &buffer)
|
|||
|
||||
static void menu_draw_item_select_sheet_E(char type_char, const Sheet &sheet)
|
||||
{
|
||||
lcd_set_cursor(0, menu_row);
|
||||
SheetFormatBuffer buffer;
|
||||
menu_format_sheet_select_E(sheet, buffer);
|
||||
lcd_putc_at(0, menu_row, menu_selection_mark());
|
||||
lcd_print_pad(buffer.c, LCD_WIDTH - 2);
|
||||
lcd_putc(type_char);
|
||||
lcd_printf_P(PSTR("%c%-18.18s%c"), menu_selection_mark(), buffer.c, type_char);
|
||||
}
|
||||
|
||||
|
||||
static void menu_draw_item_puts_E(char type_char, const Sheet &sheet)
|
||||
{
|
||||
lcd_set_cursor(0, menu_row);
|
||||
SheetFormatBuffer buffer;
|
||||
menu_format_sheet_E(sheet, buffer);
|
||||
lcd_putc_at(0, menu_row, menu_selection_mark());
|
||||
lcd_print_pad(buffer.c, LCD_WIDTH - 2);
|
||||
lcd_putc(type_char);
|
||||
lcd_printf_P(PSTR("%c%-18.18s%c"), menu_selection_mark(), buffer.c, type_char);
|
||||
}
|
||||
|
||||
static void menu_draw_item_puts_P(char type_char, const char* str, char num)
|
||||
{
|
||||
const uint8_t max_strlen = LCD_WIDTH - 3;
|
||||
lcd_putc_at(0, menu_row, menu_selection_mark());
|
||||
uint8_t len = lcd_print_pad_P(str, max_strlen);
|
||||
lcd_putc_at((max_strlen - len) + 2, menu_row, num);
|
||||
lcd_putc_at(LCD_WIDTH - 1, menu_row, type_char);
|
||||
lcd_set_cursor(0, menu_row);
|
||||
lcd_printf_P(PSTR("%c%-.16S "), menu_selection_mark(), str);
|
||||
lcd_putc(num);
|
||||
lcd_putc_at(19, menu_row, type_char);
|
||||
}
|
||||
|
||||
/*
|
||||
int menu_draw_item_puts_P_int16(char type_char, const char* str, int16_t val, )
|
||||
{
|
||||
lcd_set_cursor(0, menu_row);
|
||||
int cnt = lcd_printf_P(PSTR("%c%-18S%c"), (lcd_encoder == menu_item)?'>':' ', str, type_char);
|
||||
return cnt;
|
||||
}
|
||||
*/
|
||||
|
||||
void menu_item_dummy(void)
|
||||
{
|
||||
menu_item++;
|
||||
|
|
@ -253,16 +275,13 @@ uint8_t menu_item_text_P(const char* str)
|
|||
{
|
||||
if (lcd_draw_update) menu_draw_item_puts_P(' ', str);
|
||||
if (menu_clicked && (lcd_encoder == menu_item))
|
||||
{
|
||||
menu_item_ret();
|
||||
return 1;
|
||||
}
|
||||
return menu_item_ret();
|
||||
}
|
||||
menu_item++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void menu_item_submenu_P(const char* str, menu_func_t submenu)
|
||||
uint8_t menu_item_submenu_P(const char* str, menu_func_t submenu)
|
||||
{
|
||||
if (menu_item == menu_line)
|
||||
{
|
||||
|
|
@ -270,14 +289,14 @@ void menu_item_submenu_P(const char* str, menu_func_t submenu)
|
|||
if (menu_clicked && (lcd_encoder == menu_item))
|
||||
{
|
||||
menu_submenu(submenu);
|
||||
menu_item_ret();
|
||||
return;
|
||||
return menu_item_ret();
|
||||
}
|
||||
}
|
||||
menu_item++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void menu_item_submenu_E(const Sheet &sheet, menu_func_t submenu)
|
||||
uint8_t menu_item_submenu_E(const Sheet &sheet, menu_func_t submenu)
|
||||
{
|
||||
if (menu_item == menu_line)
|
||||
{
|
||||
|
|
@ -285,31 +304,33 @@ void menu_item_submenu_E(const Sheet &sheet, menu_func_t submenu)
|
|||
if (menu_clicked && (lcd_encoder == menu_item))
|
||||
{
|
||||
menu_submenu(submenu);
|
||||
menu_item_ret();
|
||||
return;
|
||||
return menu_item_ret();
|
||||
}
|
||||
}
|
||||
menu_item++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void __attribute__((noinline)) menu_item_function_E(const Sheet &sheet, menu_func_t func)
|
||||
uint8_t __attribute__((noinline)) menu_item_function_E(const Sheet &sheet, menu_func_t func)
|
||||
{
|
||||
if (menu_item == menu_line)
|
||||
{
|
||||
if (lcd_draw_update) menu_draw_item_select_sheet_E(' ', sheet);
|
||||
if (menu_clicked && (lcd_encoder == menu_item))
|
||||
{
|
||||
menu_clicked = false;
|
||||
lcd_consume_click();
|
||||
lcd_update_enabled = 0;
|
||||
if (func) func();
|
||||
lcd_update_enabled = 1;
|
||||
menu_item_ret();
|
||||
return;
|
||||
return menu_item_ret();
|
||||
}
|
||||
}
|
||||
menu_item++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void menu_item_back_P(const char* str)
|
||||
uint8_t menu_item_back_P(const char* str)
|
||||
{
|
||||
if (menu_item == menu_line)
|
||||
{
|
||||
|
|
@ -317,32 +338,34 @@ void menu_item_back_P(const char* str)
|
|||
if (menu_clicked && (lcd_encoder == menu_item))
|
||||
{
|
||||
menu_back();
|
||||
menu_item_ret();
|
||||
return;
|
||||
return menu_item_ret();
|
||||
}
|
||||
}
|
||||
menu_item++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool __attribute__((noinline)) menu_item_leave(){
|
||||
return ((menu_item == menu_line) && menu_clicked && (lcd_encoder == menu_item)) || menu_leaving;
|
||||
}
|
||||
|
||||
void menu_item_function_P(const char* str, menu_func_t func)
|
||||
uint8_t menu_item_function_P(const char* str, menu_func_t func)
|
||||
{
|
||||
if (menu_item == menu_line)
|
||||
{
|
||||
if (lcd_draw_update) menu_draw_item_puts_P(' ', str);
|
||||
if (menu_clicked && (lcd_encoder == menu_item))
|
||||
{
|
||||
menu_clicked = false;
|
||||
lcd_consume_click();
|
||||
lcd_update_enabled = 0;
|
||||
if (func) func();
|
||||
lcd_update_enabled = 1;
|
||||
menu_item_ret();
|
||||
return;
|
||||
return menu_item_ret();
|
||||
}
|
||||
}
|
||||
menu_item++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
//! @brief Menu item function taking single parameter
|
||||
|
|
@ -354,24 +377,26 @@ void menu_item_function_P(const char* str, menu_func_t func)
|
|||
//! @param fn_par value to be passed to function
|
||||
//! @retval 0
|
||||
//! @retval 1 Item was clicked
|
||||
void menu_item_function_P(const char* str, char number, void (*func)(uint8_t), uint8_t fn_par)
|
||||
uint8_t menu_item_function_P(const char* str, char number, void (*func)(uint8_t), uint8_t fn_par)
|
||||
{
|
||||
if (menu_item == menu_line)
|
||||
{
|
||||
if (lcd_draw_update) menu_draw_item_puts_P(' ', str, number);
|
||||
if (menu_clicked && (lcd_encoder == menu_item))
|
||||
{
|
||||
menu_clicked = false;
|
||||
lcd_consume_click();
|
||||
lcd_update_enabled = 0;
|
||||
if (func) func(fn_par);
|
||||
lcd_update_enabled = 1;
|
||||
menu_item_ret();
|
||||
return;
|
||||
return menu_item_ret();
|
||||
}
|
||||
}
|
||||
menu_item++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void menu_item_toggle_P(const char* str, const char* toggle, menu_func_t func, const uint8_t settings)
|
||||
uint8_t menu_item_toggle_P(const char* str, const char* toggle, menu_func_t func, const uint8_t settings)
|
||||
{
|
||||
if (menu_item == menu_line)
|
||||
{
|
||||
|
|
@ -381,21 +406,24 @@ void menu_item_toggle_P(const char* str, const char* toggle, menu_func_t func, c
|
|||
if (toggle == NULL) // print N/A warning message
|
||||
{
|
||||
menu_submenu(func);
|
||||
return menu_item_ret();
|
||||
}
|
||||
else // do the actual toggling
|
||||
{
|
||||
menu_clicked = false;
|
||||
lcd_consume_click();
|
||||
lcd_update_enabled = 0;
|
||||
if (func) func();
|
||||
lcd_update_enabled = 1;
|
||||
return menu_item_ret();
|
||||
}
|
||||
menu_item_ret();
|
||||
return;
|
||||
}
|
||||
}
|
||||
menu_item++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void menu_item_gcode_P(const char* str, const char* str_gcode)
|
||||
uint8_t menu_item_gcode_P(const char* str, const char* str_gcode)
|
||||
{
|
||||
if (menu_item == menu_line)
|
||||
{
|
||||
|
|
@ -403,54 +431,69 @@ void menu_item_gcode_P(const char* str, const char* str_gcode)
|
|||
if (menu_clicked && (lcd_encoder == menu_item))
|
||||
{
|
||||
if (str_gcode) enquecommand_P(str_gcode);
|
||||
menu_item_ret();
|
||||
return;
|
||||
return menu_item_ret();
|
||||
}
|
||||
}
|
||||
menu_item++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char menu_fmt_int3[] PROGMEM = "%c%.15S:%s%3d";
|
||||
|
||||
const char menu_fmt_float31[] PROGMEM = "%-12.12S%+8.1f";
|
||||
|
||||
const char menu_fmt_float13[] PROGMEM = "%c%-13.13S%+5.3f";
|
||||
|
||||
/// @brief Draw the label and value for a menu edit item
|
||||
/// @param chr 1 byte character
|
||||
/// @param str String residing in program memory (PROGMEM)
|
||||
/// @param val value to render, ranges from -999 to 9999
|
||||
static void menu_draw_P(const char chr, const char* str, const int16_t val)
|
||||
template<typename T>
|
||||
static void menu_draw_P(char chr, const char* str, int16_t val);
|
||||
|
||||
template<>
|
||||
void menu_draw_P<int16_t*>(char chr, const char* str, int16_t val)
|
||||
{
|
||||
lcd_putc(chr);
|
||||
lcd_puts_P(str);
|
||||
lcd_putc(':');
|
||||
int text_len = strlen_P(str);
|
||||
if (text_len > 15) text_len = 15;
|
||||
char spaces[LCD_WIDTH + 1] = {0};
|
||||
memset(spaces,' ', LCD_WIDTH);
|
||||
if (val <= -100) spaces[15 - text_len - 1] = 0;
|
||||
else spaces[15 - text_len] = 0;
|
||||
lcd_printf_P(menu_fmt_int3, chr, str, spaces, val);
|
||||
}
|
||||
|
||||
// Padding to compensate variable string length
|
||||
const uint8_t len = strlen_P(str);
|
||||
lcd_space((LCD_WIDTH - 4) - (2 + len));
|
||||
|
||||
// Right adjusted value
|
||||
lcd_printf_P(PSTR("%4d"), val);
|
||||
template<>
|
||||
void menu_draw_P<uint8_t*>(char chr, const char* str, int16_t val)
|
||||
{
|
||||
menu_data_edit_t* _md = (menu_data_edit_t*)&(menu_data[0]);
|
||||
float factor = 1.0f + static_cast<float>(val) / 1000.0f;
|
||||
if (val <= _md->minEditValue)
|
||||
{
|
||||
menu_draw_toggle_puts_P(str, _T(MSG_OFF), 0x04 | 0x02 | (chr=='>'));
|
||||
}
|
||||
else
|
||||
{
|
||||
lcd_printf_P(menu_fmt_float13, chr, str, factor);
|
||||
}
|
||||
}
|
||||
|
||||
//! @brief Draw up to 10 chars of text and a float number in format from +0.0 to +12345.0. The increased range is necessary
|
||||
//! for displaying large values of extruder positions, which caused text overflow in the previous implementation.
|
||||
//!
|
||||
//!
|
||||
//! @param str string label to print
|
||||
//! @param val value to print aligned to the right side of the display
|
||||
//!
|
||||
//! @param val value to print aligned to the right side of the display
|
||||
//!
|
||||
//! Implementation comments:
|
||||
//! The text needs to come with a colon ":", this function does not append it anymore.
|
||||
//! That resulted in a much shorter implementation (234628B -> 234476B)
|
||||
//! There are similar functions around which may be shortened in a similar way
|
||||
void menu_draw_float31(const char* str, float val)
|
||||
{
|
||||
lcd_printf_P(menu_fmt_float31, str, val);
|
||||
lcd_printf_P(menu_fmt_float31, str, val);
|
||||
}
|
||||
|
||||
//! @brief Draw up to 14 chars of text and a float number in format +1.234
|
||||
//!
|
||||
//!
|
||||
//! @param str string label to print
|
||||
//! @param val value to print aligned to the right side of the display
|
||||
//!
|
||||
//! @param val value to print aligned to the right side of the display
|
||||
//!
|
||||
//! Implementation comments:
|
||||
//! This function uses similar optimization principles as menu_draw_float31
|
||||
//! (i.e. str must include a ':' at its end)
|
||||
|
|
@ -461,66 +504,53 @@ void menu_draw_float13(const char* str, float val)
|
|||
lcd_printf_P(menu_fmt_float13, ' ', str, val);
|
||||
}
|
||||
|
||||
static void _menu_edit_P()
|
||||
template <typename T>
|
||||
static void _menu_edit_P(void)
|
||||
{
|
||||
menu_data_edit_t* _md = (menu_data_edit_t*)&(menu_data[0]);
|
||||
if (lcd_draw_update)
|
||||
{
|
||||
// handle initial value jumping
|
||||
if (_md->minJumpValue && lcd_encoder) {
|
||||
if (lcd_encoder > 0 && _md->currentValue == _md->minEditValue) {
|
||||
_md->currentValue = _md->minJumpValue;
|
||||
lcd_encoder = 0;
|
||||
}
|
||||
// disable after first use and/or if the initial value is not minEditValue
|
||||
_md->minJumpValue = 0;
|
||||
}
|
||||
_md->currentValue += lcd_encoder;
|
||||
lcd_encoder = 0; // Consume knob rotation event
|
||||
// Constrain the value in case it's outside the allowed limits
|
||||
_md->currentValue = constrain(_md->currentValue, _md->minEditValue, _md->maxEditValue);
|
||||
if (lcd_encoder < _md->minEditValue) lcd_encoder = _md->minEditValue;
|
||||
if (lcd_encoder > _md->maxEditValue) lcd_encoder = _md->maxEditValue;
|
||||
lcd_set_cursor(0, 1);
|
||||
menu_draw_P(' ', _md->editLabel, _md->currentValue);
|
||||
menu_draw_P<T>(' ', _md->editLabel, (int)lcd_encoder);
|
||||
}
|
||||
if (lcd_clicked())
|
||||
if (LCD_CLICKED)
|
||||
{
|
||||
if (_md->editValueBits == 8)
|
||||
*((uint8_t*)(_md->editValuePtr)) = _md->currentValue;
|
||||
else
|
||||
*((int16_t*)(_md->editValuePtr)) = _md->currentValue;
|
||||
*((T)(_md->editValue)) = lcd_encoder;
|
||||
menu_back_no_reset();
|
||||
}
|
||||
}
|
||||
|
||||
void menu_item_edit_P(const char* str, void* pval, uint8_t pbits, int16_t min_val, int16_t max_val, int16_t jmp_val)
|
||||
template <typename T>
|
||||
uint8_t menu_item_edit_P(const char* str, T pval, int16_t min_val, int16_t max_val)
|
||||
{
|
||||
menu_data_edit_t* _md = (menu_data_edit_t*)&(menu_data[0]);
|
||||
if (menu_item == menu_line)
|
||||
{
|
||||
int16_t cur_val = (pbits == 8 ? *((uint8_t*)pval) : *((int16_t*)pval));
|
||||
|
||||
if (lcd_draw_update)
|
||||
if (lcd_draw_update)
|
||||
{
|
||||
lcd_set_cursor(0, menu_row);
|
||||
menu_draw_P(menu_selection_mark(), str, cur_val);
|
||||
menu_draw_P<T>(menu_selection_mark(), str, *pval);
|
||||
}
|
||||
if (menu_clicked && (lcd_encoder == menu_item))
|
||||
{
|
||||
menu_submenu_no_reset(_menu_edit_P);
|
||||
menu_submenu_no_reset(_menu_edit_P<T>);
|
||||
_md->editLabel = str;
|
||||
_md->editValuePtr = pval;
|
||||
_md->editValueBits = pbits;
|
||||
_md->currentValue = cur_val;
|
||||
_md->editValue = pval;
|
||||
_md->minEditValue = min_val;
|
||||
_md->maxEditValue = max_val;
|
||||
_md->minJumpValue = jmp_val;
|
||||
menu_item_ret();
|
||||
return;
|
||||
lcd_encoder = *pval;
|
||||
return menu_item_ret();
|
||||
}
|
||||
}
|
||||
menu_item++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
template uint8_t menu_item_edit_P<int16_t*>(const char* str, int16_t *pval, int16_t min_val, int16_t max_val);
|
||||
template uint8_t menu_item_edit_P<uint8_t*>(const char* str, uint8_t *pval, int16_t min_val, int16_t max_val);
|
||||
|
||||
static uint8_t progressbar_block_count = 0;
|
||||
static uint16_t progressbar_total = 0;
|
||||
void menu_progressbar_init(uint16_t total, const char* title)
|
||||
|
|
@ -528,10 +558,9 @@ void menu_progressbar_init(uint16_t total, const char* title)
|
|||
lcd_clear();
|
||||
progressbar_block_count = 0;
|
||||
progressbar_total = total;
|
||||
|
||||
|
||||
lcd_set_cursor(0, 1);
|
||||
lcd_print_pad_P(title, LCD_WIDTH);
|
||||
lcd_set_cursor(0, 2);
|
||||
lcd_printf_P(PSTR("%-20.20S\n"), title);
|
||||
}
|
||||
|
||||
void menu_progressbar_update(uint16_t newVal)
|
||||
|
|
@ -541,7 +570,7 @@ void menu_progressbar_update(uint16_t newVal)
|
|||
newCnt = LCD_WIDTH;
|
||||
while (newCnt > progressbar_block_count)
|
||||
{
|
||||
lcd_print(LCD_STR_SOLID_BLOCK[0]);
|
||||
lcd_print('\xFF');
|
||||
progressbar_block_count++;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
//Function pointer to menu functions.
|
||||
typedef void (*menu_func_t)(void);
|
||||
|
||||
typedef struct
|
||||
typedef struct
|
||||
{
|
||||
menu_func_t menu;
|
||||
int8_t position;
|
||||
|
|
@ -20,40 +20,35 @@ typedef struct
|
|||
{
|
||||
//Variables used when editing values.
|
||||
const char* editLabel;
|
||||
uint8_t editValueBits; // 8 or 16
|
||||
void* editValuePtr;
|
||||
int16_t currentValue;
|
||||
int16_t minEditValue;
|
||||
int16_t maxEditValue;
|
||||
int16_t minJumpValue;
|
||||
void* editValue;
|
||||
int32_t minEditValue;
|
||||
int32_t maxEditValue;
|
||||
} menu_data_edit_t;
|
||||
|
||||
extern uint8_t menu_data[MENU_DATA_SIZE];
|
||||
|
||||
extern uint8_t menu_depth;
|
||||
|
||||
//! definition of reasons blocking the main menu
|
||||
//! definition of serious errors possibly blocking the main menu
|
||||
//! Use them as bit mask, so that the code may set various errors at the same time
|
||||
enum ESeriousErrors {
|
||||
MENU_BLOCK_NONE = 0,
|
||||
MENU_BLOCK_THERMAL_ERROR = 0x01,
|
||||
#ifdef THERMAL_MODEL
|
||||
MENU_BLOCK_THERMAL_MODEL_AUTOTUNE = 0x02,
|
||||
#endif
|
||||
MENU_BLOCK_STATUS_SCREEN_M0 = 0x04,
|
||||
SERIOUS_ERR_NONE = 0,
|
||||
SERIOUS_ERR_MINTEMP_HEATER = 0x01,
|
||||
SERIOUS_ERR_MINTEMP_BED = 0x02
|
||||
}; // and possibly others in the future.
|
||||
|
||||
//! this is a flag for disabling entering the main menu and longpress. If this is set to anything !=
|
||||
//! 0, the only the main status screen will be shown on the LCD and the user will be prevented from
|
||||
//! entering the menu.
|
||||
extern uint8_t menu_block_mask;
|
||||
//! this is a flag for disabling entering the main menu. If this is set
|
||||
//! to anything != 0, the only the main status screen will be shown on the
|
||||
//! LCD and the user will be prevented from entering the menu.
|
||||
//! Now used only to block doing anything with the printer when there is
|
||||
//! the infamous MINTEMP error (SERIOUS_ERR_MINTEMP).
|
||||
extern uint8_t menu_block_entering_on_serious_errors;
|
||||
|
||||
//! a pair of macros for manipulating menu entry
|
||||
//! a pair of macros for manipulating the serious errors
|
||||
//! a c++ class would have been better
|
||||
#define menu_set_block(x) menu_block_mask |= x;
|
||||
#define menu_unset_block(x) menu_block_mask &= ~x;
|
||||
#define menu_is_blocked(x) (menu_block_mask & x)
|
||||
#define menu_is_any_block() (menu_block_mask != MENU_BLOCK_NONE)
|
||||
#define menu_set_serious_error(x) menu_block_entering_on_serious_errors |= x;
|
||||
#define menu_unset_serious_error(x) menu_block_entering_on_serious_errors &= ~x;
|
||||
#define menu_is_serious_error(x) (menu_block_entering_on_serious_errors & x) != 0
|
||||
|
||||
extern uint8_t menu_line;
|
||||
extern uint8_t menu_item;
|
||||
|
|
@ -61,7 +56,9 @@ extern uint8_t menu_row;
|
|||
|
||||
//scroll offset in the current menu
|
||||
extern uint8_t menu_top;
|
||||
|
||||
extern uint8_t menu_clicked;
|
||||
|
||||
extern uint8_t menu_leaving;
|
||||
|
||||
//function pointer to the currently active menu
|
||||
|
|
@ -69,7 +66,7 @@ extern menu_func_t menu_menu;
|
|||
|
||||
extern void menu_data_reset(void);
|
||||
|
||||
extern void menu_goto(menu_func_t menu, const int16_t encoder, bool reset_menu_state, const bool feedback=false);
|
||||
extern void menu_goto(menu_func_t menu, const uint32_t encoder, const bool feedback, bool reset_menu_state);
|
||||
|
||||
#define MENU_BEGIN() menu_start(); for(menu_row = 0; menu_row < LCD_HEIGHT; menu_row++, menu_line++) { menu_item = 0;
|
||||
void menu_start(void);
|
||||
|
|
@ -83,10 +80,12 @@ extern void menu_back(uint8_t nLevel);
|
|||
|
||||
extern void menu_back_if_clicked(void);
|
||||
|
||||
extern void menu_submenu(menu_func_t submenu, const bool feedback=false);
|
||||
extern void menu_submenu_no_reset(menu_func_t submenu, const bool feedback=false);
|
||||
extern void menu_back_if_clicked_fb(void);
|
||||
|
||||
extern void menu_item_ret(void);
|
||||
extern void menu_submenu(menu_func_t submenu);
|
||||
extern void menu_submenu_no_reset(menu_func_t submenu);
|
||||
|
||||
extern uint8_t menu_item_ret(void);
|
||||
|
||||
//extern int menu_draw_item_printf_P(char type_char, const char* format, ...);
|
||||
|
||||
|
|
@ -96,37 +95,37 @@ extern void menu_item_ret(void);
|
|||
#define MENU_ITEM_DUMMY() menu_item_dummy()
|
||||
extern void menu_item_dummy(void);
|
||||
|
||||
#define MENU_ITEM_TEXT_P(str) do { menu_item_text_P(str); } while (0)
|
||||
#define MENU_ITEM_TEXT_P(str) do { if (menu_item_text_P(str)) return; } while (0)
|
||||
extern uint8_t menu_item_text_P(const char* str);
|
||||
|
||||
#define MENU_ITEM_SUBMENU_P(str, submenu) do { menu_item_submenu_P(str, submenu); } while (0)
|
||||
extern void menu_item_submenu_P(const char* str, menu_func_t submenu);
|
||||
#define MENU_ITEM_SUBMENU_P(str, submenu) do { if (menu_item_submenu_P(str, submenu)) return; } while (0)
|
||||
extern uint8_t menu_item_submenu_P(const char* str, menu_func_t submenu);
|
||||
|
||||
#define MENU_ITEM_SUBMENU_E(sheet, submenu) do { menu_item_submenu_E(sheet, submenu); } while (0)
|
||||
extern void menu_item_submenu_E(const Sheet &sheet, menu_func_t submenu);
|
||||
#define MENU_ITEM_SUBMENU_E(sheet, submenu) do { if (menu_item_submenu_E(sheet, submenu)) return; } while (0)
|
||||
extern uint8_t menu_item_submenu_E(const Sheet &sheet, menu_func_t submenu);
|
||||
|
||||
#define MENU_ITEM_FUNCTION_E(sheet, submenu) do { menu_item_function_E(sheet, submenu); } while (0)
|
||||
extern void menu_item_function_E(const Sheet &sheet, menu_func_t func);
|
||||
#define MENU_ITEM_FUNCTION_E(sheet, submenu) do { if (menu_item_function_E(sheet, submenu)) return; } while (0)
|
||||
extern uint8_t menu_item_function_E(const Sheet &sheet, menu_func_t func);
|
||||
|
||||
#define MENU_ITEM_BACK_P(str) do { menu_item_back_P(str); } while (0)
|
||||
extern void menu_item_back_P(const char* str);
|
||||
#define MENU_ITEM_BACK_P(str) do { if (menu_item_back_P(str)) return; } while (0)
|
||||
extern uint8_t menu_item_back_P(const char* str);
|
||||
|
||||
// leaving menu - this condition must be immediately before MENU_ITEM_BACK_P
|
||||
#define ON_MENU_LEAVE(func) do { if (menu_item_leave()){ func } } while (0)
|
||||
extern bool menu_item_leave();
|
||||
|
||||
#define MENU_ITEM_FUNCTION_P(str, func) do { menu_item_function_P(str, func); } while (0)
|
||||
extern void menu_item_function_P(const char* str, menu_func_t func);
|
||||
#define MENU_ITEM_FUNCTION_P(str, func) do { if (menu_item_function_P(str, func)) return; } while (0)
|
||||
extern uint8_t menu_item_function_P(const char* str, menu_func_t func);
|
||||
|
||||
#define MENU_ITEM_FUNCTION_NR_P(str, number, func, fn_par) do { menu_item_function_P(str, number, func, fn_par); } while (0)
|
||||
extern void menu_item_function_P(const char* str, char number, void (*func)(uint8_t), uint8_t fn_par);
|
||||
#define MENU_ITEM_FUNCTION_NR_P(str, number, func, fn_par) do { if (menu_item_function_P(str, number, func, fn_par)) return; } while (0)
|
||||
extern uint8_t menu_item_function_P(const char* str, char number, void (*func)(uint8_t), uint8_t fn_par);
|
||||
|
||||
#define MENU_ITEM_TOGGLE_P(str, toggle, func) do { menu_item_toggle_P(str, toggle, func, 0x02); } while (0)
|
||||
#define MENU_ITEM_TOGGLE(str, toggle, func) do { menu_item_toggle_P(str, toggle, func, 0x00); } while (0)
|
||||
extern void menu_item_toggle_P(const char* str, const char* toggle, menu_func_t func, const uint8_t settings);
|
||||
#define MENU_ITEM_TOGGLE_P(str, toggle, func) do { if (menu_item_toggle_P(str, toggle, func, 0x02)) return; } while (0)
|
||||
#define MENU_ITEM_TOGGLE(str, toggle, func) do { if (menu_item_toggle_P(str, toggle, func, 0x00)) return; } while (0)
|
||||
extern uint8_t menu_item_toggle_P(const char* str, const char* toggle, menu_func_t func, const uint8_t settings);
|
||||
|
||||
#define MENU_ITEM_GCODE_P(str, str_gcode) do { menu_item_gcode_P(str, str_gcode); } while (0)
|
||||
extern void menu_item_gcode_P(const char* str, const char* str_gcode);
|
||||
#define MENU_ITEM_GCODE_P(str, str_gcode) do { if (menu_item_gcode_P(str, str_gcode)) return; } while (0)
|
||||
extern uint8_t menu_item_gcode_P(const char* str, const char* str_gcode);
|
||||
|
||||
|
||||
extern const char menu_fmt_int3[];
|
||||
|
|
@ -145,9 +144,11 @@ struct SheetFormatBuffer
|
|||
|
||||
extern void menu_format_sheet_E(const Sheet &sheet_E, SheetFormatBuffer &buffer);
|
||||
|
||||
#define MENU_ITEM_EDIT_int3_P(str, pval, minval, maxval) do { menu_item_edit_P(str, pval, sizeof(*pval)*8, minval, maxval, 0); } while (0)
|
||||
#define MENU_ITEM_EDIT_int3_jmp_P(str, pval, minval, maxval, jmpval) do { menu_item_edit_P(str, pval, sizeof(*pval)*8, minval, maxval, jmpval); } while (0)
|
||||
extern void menu_item_edit_P(const char* str, void* pval, uint8_t pbits, int16_t min_val, int16_t max_val, int16_t jmp_val);
|
||||
|
||||
#define MENU_ITEM_EDIT_int3_P(str, pval, minval, maxval) do { if (menu_item_edit_P(str, pval, minval, maxval)) return; } while (0)
|
||||
//#define MENU_ITEM_EDIT_int3_P(str, pval, minval, maxval) MENU_ITEM_EDIT(int3, str, pval, minval, maxval)
|
||||
template <typename T>
|
||||
extern uint8_t menu_item_edit_P(const char* str, T pval, int16_t min_val, int16_t max_val);
|
||||
|
||||
extern void menu_progressbar_init(uint16_t total, const char* title);
|
||||
extern void menu_progressbar_update(uint16_t newVal);
|
||||
|
|
|
|||
|
|
@ -1,8 +1,6 @@
|
|||
#include "Configuration.h"
|
||||
#include "ConfigurationStore.h"
|
||||
#include "util.h"
|
||||
#include "language.h"
|
||||
#include "lcd.h"
|
||||
#include "mesh_bed_calibration.h"
|
||||
#include "mesh_bed_leveling.h"
|
||||
#include "stepper.h"
|
||||
|
|
@ -263,26 +261,26 @@ BedSkewOffsetDetectionResultType calculate_machine_skew_and_offset_LS(
|
|||
for (uint8_t i = 0; i < npts; ++i) {
|
||||
// First for the residuum in the x axis:
|
||||
if (r != 1 && c != 1) {
|
||||
float a =
|
||||
float a =
|
||||
(r == 0) ? 1.f :
|
||||
((r == 2) ? (-s1 * measured_pts[2 * i]) :
|
||||
(-c2 * measured_pts[2 * i + 1]));
|
||||
float b =
|
||||
float b =
|
||||
(c == 0) ? 1.f :
|
||||
((c == 2) ? (-s1 * measured_pts[2 * i]) :
|
||||
(-c2 * measured_pts[2 * i + 1]));
|
||||
float w = point_weight_x(i, measured_pts[2 * i + 1]);
|
||||
acc += a * b * w;
|
||||
}
|
||||
// Second for the residuum in the y axis.
|
||||
// Second for the residuum in the y axis.
|
||||
// The first row of the points have a low weight, because their position may not be known
|
||||
// with a sufficient accuracy.
|
||||
if (r != 0 && c != 0) {
|
||||
float a =
|
||||
float a =
|
||||
(r == 1) ? 1.f :
|
||||
((r == 2) ? ( c1 * measured_pts[2 * i]) :
|
||||
(-s2 * measured_pts[2 * i + 1]));
|
||||
float b =
|
||||
float b =
|
||||
(c == 1) ? 1.f :
|
||||
((c == 2) ? ( c1 * measured_pts[2 * i]) :
|
||||
(-s2 * measured_pts[2 * i + 1]));
|
||||
|
|
@ -296,7 +294,7 @@ BedSkewOffsetDetectionResultType calculate_machine_skew_and_offset_LS(
|
|||
acc = 0.f;
|
||||
for (uint8_t i = 0; i < npts; ++i) {
|
||||
{
|
||||
float j =
|
||||
float j =
|
||||
(r == 0) ? 1.f :
|
||||
((r == 1) ? 0.f :
|
||||
((r == 2) ? (-s1 * measured_pts[2 * i]) :
|
||||
|
|
@ -306,7 +304,7 @@ BedSkewOffsetDetectionResultType calculate_machine_skew_and_offset_LS(
|
|||
acc += j * fx * w;
|
||||
}
|
||||
{
|
||||
float j =
|
||||
float j =
|
||||
(r == 0) ? 0.f :
|
||||
((r == 1) ? 1.f :
|
||||
((r == 2) ? ( c1 * measured_pts[2 * i]) :
|
||||
|
|
@ -374,7 +372,7 @@ BedSkewOffsetDetectionResultType calculate_machine_skew_and_offset_LS(
|
|||
angleDiff = fabs(a2 - a1);
|
||||
/// XY skew and Y-bed skew
|
||||
DBG(_n("Measured skews: %f %f\n"), degrees(a2 - a1), degrees(a2));
|
||||
eeprom_update_float_notify((float *)(EEPROM_XYZ_CAL_SKEW), angleDiff); //storing xyz cal. skew to be able to show in support menu later
|
||||
eeprom_update_float((float *)(EEPROM_XYZ_CAL_SKEW), angleDiff); //storing xyz cal. skew to be able to show in support menu later
|
||||
if (angleDiff > bed_skew_angle_mild)
|
||||
result = (angleDiff > bed_skew_angle_extreme) ?
|
||||
BED_SKEW_OFFSET_DETECTION_SKEW_EXTREME :
|
||||
|
|
@ -420,9 +418,9 @@ BedSkewOffsetDetectionResultType calculate_machine_skew_and_offset_LS(
|
|||
for (uint8_t i = 0; i < npts; ++i) {
|
||||
float x = vec_x[0] * measured_pts[i * 2] + vec_y[0] * measured_pts[i * 2 + 1] + cntr[0];
|
||||
float y = vec_x[1] * measured_pts[i * 2] + vec_y[1] * measured_pts[i * 2 + 1] + cntr[1];
|
||||
float errX = pgm_read_float(true_pts + i * 2) - x;
|
||||
float errY = pgm_read_float(true_pts + i * 2 + 1) - y;
|
||||
float err = hypot(errX, errY);
|
||||
float errX = sqr(pgm_read_float(true_pts + i * 2) - x);
|
||||
float errY = sqr(pgm_read_float(true_pts + i * 2 + 1) - y);
|
||||
float err = sqrt(errX + errY);
|
||||
#ifdef SUPPORT_VERBOSITY
|
||||
if (verbosity_level >= 10) {
|
||||
SERIAL_ECHOPGM("point #");
|
||||
|
|
@ -436,15 +434,15 @@ BedSkewOffsetDetectionResultType calculate_machine_skew_and_offset_LS(
|
|||
if(verbosity_level >= 20) SERIAL_ECHOPGM("Point on first row");
|
||||
#endif // SUPPORT_VERBOSITY
|
||||
float w = point_weight_y(i, measured_pts[2 * i + 1]);
|
||||
if (errX > BED_CALIBRATION_POINT_OFFSET_MAX_1ST_ROW_X ||
|
||||
(w != 0.f && errY > BED_CALIBRATION_POINT_OFFSET_MAX_1ST_ROW_Y)) {
|
||||
if (sqrt(errX) > BED_CALIBRATION_POINT_OFFSET_MAX_1ST_ROW_X ||
|
||||
(w != 0.f && sqrt(errY) > BED_CALIBRATION_POINT_OFFSET_MAX_1ST_ROW_Y)) {
|
||||
result = BED_SKEW_OFFSET_DETECTION_FITTING_FAILED;
|
||||
#ifdef SUPPORT_VERBOSITY
|
||||
if (verbosity_level >= 20) {
|
||||
SERIAL_ECHOPGM(", weigth Y: ");
|
||||
MYSERIAL.print(w);
|
||||
if (errX > BED_CALIBRATION_POINT_OFFSET_MAX_1ST_ROW_X) SERIAL_ECHOPGM(", error X > max. error X");
|
||||
if (w != 0.f && errY > BED_CALIBRATION_POINT_OFFSET_MAX_1ST_ROW_Y) SERIAL_ECHOPGM(", error Y > max. error Y");
|
||||
if (sqrt(errX) > BED_CALIBRATION_POINT_OFFSET_MAX_1ST_ROW_X) SERIAL_ECHOPGM(", error X > max. error X");
|
||||
if (w != 0.f && sqrt(errY) > BED_CALIBRATION_POINT_OFFSET_MAX_1ST_ROW_Y) SERIAL_ECHOPGM(", error Y > max. error Y");
|
||||
}
|
||||
#endif // SUPPORT_VERBOSITY
|
||||
}
|
||||
|
|
@ -456,7 +454,7 @@ BedSkewOffsetDetectionResultType calculate_machine_skew_and_offset_LS(
|
|||
if (err > BED_CALIBRATION_POINT_OFFSET_MAX_EUCLIDIAN) {
|
||||
result = BED_SKEW_OFFSET_DETECTION_FITTING_FAILED;
|
||||
#ifdef SUPPORT_VERBOSITY
|
||||
if(verbosity_level >= 20) SERIAL_ECHOPGM(", error > max. error euclidian");
|
||||
if(verbosity_level >= 20) SERIAL_ECHOPGM(", error > max. error euclidian");
|
||||
#endif // SUPPORT_VERBOSITY
|
||||
}
|
||||
}
|
||||
|
|
@ -479,9 +477,9 @@ BedSkewOffsetDetectionResultType calculate_machine_skew_and_offset_LS(
|
|||
SERIAL_ECHOPGM("error: ");
|
||||
MYSERIAL.print(err);
|
||||
SERIAL_ECHOPGM(", error X: ");
|
||||
MYSERIAL.print(errX);
|
||||
MYSERIAL.print(sqrt(errX));
|
||||
SERIAL_ECHOPGM(", error Y: ");
|
||||
MYSERIAL.print(errY);
|
||||
MYSERIAL.print(sqrt(errY));
|
||||
SERIAL_ECHOLNPGM("");
|
||||
SERIAL_ECHOLNPGM("");
|
||||
}
|
||||
|
|
@ -500,6 +498,19 @@ BedSkewOffsetDetectionResultType calculate_machine_skew_and_offset_LS(
|
|||
}
|
||||
#endif // SUPPORT_VERBOSITY
|
||||
|
||||
#if 0
|
||||
if (result == BED_SKEW_OFFSET_DETECTION_PERFECT && fabs(a1) < bed_skew_angle_mild && fabs(a2) < bed_skew_angle_mild) {
|
||||
#ifdef SUPPORT_VERBOSITY
|
||||
if (verbosity_level > 0)
|
||||
SERIAL_ECHOLNPGM("Very little skew detected. Disabling skew correction.");
|
||||
#endif // SUPPORT_VERBOSITY
|
||||
// Just disable the skew correction.
|
||||
vec_x[0] = MACHINE_AXIS_SCALE_X;
|
||||
vec_x[1] = 0.f;
|
||||
vec_y[0] = 0.f;
|
||||
vec_y[1] = MACHINE_AXIS_SCALE_Y;
|
||||
}
|
||||
#else
|
||||
if (result == BED_SKEW_OFFSET_DETECTION_PERFECT) {
|
||||
#ifdef SUPPORT_VERBOSITY
|
||||
if (verbosity_level > 0)
|
||||
|
|
@ -571,6 +582,7 @@ BedSkewOffsetDetectionResultType calculate_machine_skew_and_offset_LS(
|
|||
}
|
||||
#endif // SUPPORT_VERBOSITY
|
||||
}
|
||||
#endif
|
||||
|
||||
// Invert the transformation matrix made of vec_x, vec_y and cntr.
|
||||
{
|
||||
|
|
@ -633,7 +645,7 @@ BedSkewOffsetDetectionResultType calculate_machine_skew_and_offset_LS(
|
|||
SERIAL_ECHOPGM(", ");
|
||||
MYSERIAL.print(pgm_read_float(true_pts + i * 2 + 1), 5);
|
||||
SERIAL_ECHOPGM("), error: ");
|
||||
MYSERIAL.print( hypot(measured_pts[i * 2] - x, measured_pts[i * 2 + 1] - y) );
|
||||
MYSERIAL.print(sqrt(sqr(measured_pts[i * 2] - x) + sqr(measured_pts[i * 2 + 1] - y)));
|
||||
SERIAL_ECHOLNPGM("");
|
||||
}
|
||||
if (verbosity_level >= 20) {
|
||||
|
|
@ -656,27 +668,27 @@ BedSkewOffsetDetectionResultType calculate_machine_skew_and_offset_LS(
|
|||
*/
|
||||
void reset_bed_offset_and_skew()
|
||||
{
|
||||
eeprom_update_dword_notify((uint32_t*)(EEPROM_BED_CALIBRATION_CENTER+0), 0x0FFFFFFFF);
|
||||
eeprom_update_dword_notify((uint32_t*)(EEPROM_BED_CALIBRATION_CENTER+4), 0x0FFFFFFFF);
|
||||
eeprom_update_dword_notify((uint32_t*)(EEPROM_BED_CALIBRATION_VEC_X +0), 0x0FFFFFFFF);
|
||||
eeprom_update_dword_notify((uint32_t*)(EEPROM_BED_CALIBRATION_VEC_X +4), 0x0FFFFFFFF);
|
||||
eeprom_update_dword_notify((uint32_t*)(EEPROM_BED_CALIBRATION_VEC_Y +0), 0x0FFFFFFFF);
|
||||
eeprom_update_dword_notify((uint32_t*)(EEPROM_BED_CALIBRATION_VEC_Y +4), 0x0FFFFFFFF);
|
||||
eeprom_update_dword((uint32_t*)(EEPROM_BED_CALIBRATION_CENTER+0), 0x0FFFFFFFF);
|
||||
eeprom_update_dword((uint32_t*)(EEPROM_BED_CALIBRATION_CENTER+4), 0x0FFFFFFFF);
|
||||
eeprom_update_dword((uint32_t*)(EEPROM_BED_CALIBRATION_VEC_X +0), 0x0FFFFFFFF);
|
||||
eeprom_update_dword((uint32_t*)(EEPROM_BED_CALIBRATION_VEC_X +4), 0x0FFFFFFFF);
|
||||
eeprom_update_dword((uint32_t*)(EEPROM_BED_CALIBRATION_VEC_Y +0), 0x0FFFFFFFF);
|
||||
eeprom_update_dword((uint32_t*)(EEPROM_BED_CALIBRATION_VEC_Y +4), 0x0FFFFFFFF);
|
||||
|
||||
// Reset the 8 16bit offsets.
|
||||
for (int8_t i = 0; i < 4; ++ i)
|
||||
eeprom_update_dword_notify((uint32_t*)(EEPROM_BED_CALIBRATION_Z_JITTER+i*4), 0x0FFFFFFFF);
|
||||
eeprom_update_dword((uint32_t*)(EEPROM_BED_CALIBRATION_Z_JITTER+i*4), 0x0FFFFFFFF);
|
||||
}
|
||||
|
||||
bool is_bed_z_jitter_data_valid()
|
||||
// offsets of the Z heiths of the calibration points from the first point are saved as 16bit signed int, scaled to tenths of microns
|
||||
// if at least one 16bit integer has different value then -1 (0x0FFFF), data are considered valid and function returns true, otherwise it returns false
|
||||
{
|
||||
{
|
||||
bool data_valid = false;
|
||||
for (int8_t i = 0; i < 8; ++i) {
|
||||
if (eeprom_read_word((uint16_t*)(EEPROM_BED_CALIBRATION_Z_JITTER + i * 2)) != 0x0FFFF)
|
||||
return true;
|
||||
if (eeprom_read_word((uint16_t*)(EEPROM_BED_CALIBRATION_Z_JITTER + i * 2)) != 0x0FFFF) data_valid = true;
|
||||
}
|
||||
return false;
|
||||
return data_valid;
|
||||
}
|
||||
|
||||
static void world2machine_update(const float vec_x[2], const float vec_y[2], const float cntr[2])
|
||||
|
|
@ -763,7 +775,7 @@ void world2machine_revert_to_uncorrected()
|
|||
static inline bool vec_undef(const float v[2])
|
||||
{
|
||||
const uint32_t *vx = (const uint32_t*)v;
|
||||
return vx[0] == 0xFFFFFFFF || vx[1] == 0xFFFFFFFF;
|
||||
return vx[0] == 0x0FFFFFFFF || vx[1] == 0x0FFFFFFFF;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -780,9 +792,12 @@ static inline bool vec_undef(const float v[2])
|
|||
*/
|
||||
void world2machine_read_valid(float vec_x[2], float vec_y[2], float cntr[2])
|
||||
{
|
||||
eeprom_read_block(&vec_x[0], (float*)(EEPROM_BED_CALIBRATION_VEC_X), 8);
|
||||
eeprom_read_block(&vec_y[0], (float*)(EEPROM_BED_CALIBRATION_VEC_Y), 8);
|
||||
eeprom_read_block(&cntr[0], (float*)(EEPROM_BED_CALIBRATION_CENTER), 8);
|
||||
vec_x[0] = eeprom_read_float((float*)(EEPROM_BED_CALIBRATION_VEC_X +0));
|
||||
vec_x[1] = eeprom_read_float((float*)(EEPROM_BED_CALIBRATION_VEC_X +4));
|
||||
vec_y[0] = eeprom_read_float((float*)(EEPROM_BED_CALIBRATION_VEC_Y +0));
|
||||
vec_y[1] = eeprom_read_float((float*)(EEPROM_BED_CALIBRATION_VEC_Y +4));
|
||||
cntr[0] = eeprom_read_float((float*)(EEPROM_BED_CALIBRATION_CENTER+0));
|
||||
cntr[1] = eeprom_read_float((float*)(EEPROM_BED_CALIBRATION_CENTER+4));
|
||||
|
||||
bool reset = false;
|
||||
if (vec_undef(cntr) || vec_undef(vec_x) || vec_undef(vec_y))
|
||||
|
|
@ -795,7 +810,7 @@ void world2machine_read_valid(float vec_x[2], float vec_y[2], float cntr[2])
|
|||
else
|
||||
{
|
||||
// Length of the vec_x shall be close to unity.
|
||||
float l = hypot(vec_x[0], vec_x[1]);
|
||||
float l = sqrt(vec_x[0] * vec_x[0] + vec_x[1] * vec_x[1]);
|
||||
if (l < 0.9 || l > 1.1)
|
||||
{
|
||||
#if 0
|
||||
|
|
@ -806,7 +821,7 @@ void world2machine_read_valid(float vec_x[2], float vec_y[2], float cntr[2])
|
|||
reset = true;
|
||||
}
|
||||
// Length of the vec_y shall be close to unity.
|
||||
l = hypot(vec_y[0], vec_y[1]);
|
||||
l = sqrt(vec_y[0] * vec_y[0] + vec_y[1] * vec_y[1]);
|
||||
if (l < 0.9 || l > 1.1)
|
||||
{
|
||||
#if 0
|
||||
|
|
@ -817,7 +832,7 @@ void world2machine_read_valid(float vec_x[2], float vec_y[2], float cntr[2])
|
|||
reset = true;
|
||||
}
|
||||
// Correction of the zero point shall be reasonably small.
|
||||
l = hypot(cntr[0], cntr[1]);
|
||||
l = sqrt(cntr[0] * cntr[0] + cntr[1] * cntr[1]);
|
||||
if (l > 15.f)
|
||||
{
|
||||
#if 0
|
||||
|
|
@ -896,13 +911,13 @@ void world2machine_update_current()
|
|||
|
||||
static inline void go_xyz(float x, float y, float z, float fr)
|
||||
{
|
||||
plan_buffer_line(x, y, z, current_position[E_AXIS], fr);
|
||||
plan_buffer_line(x, y, z, current_position[E_AXIS], fr, active_extruder);
|
||||
st_synchronize();
|
||||
}
|
||||
|
||||
static inline void go_xy(float x, float y, float fr)
|
||||
{
|
||||
plan_buffer_line(x, y, current_position[Z_AXIS], current_position[E_AXIS], fr);
|
||||
plan_buffer_line(x, y, current_position[Z_AXIS], current_position[E_AXIS], fr, active_extruder);
|
||||
st_synchronize();
|
||||
}
|
||||
|
||||
|
|
@ -934,15 +949,10 @@ bool find_bed_induction_sensor_point_z(float minimum_z, uint8_t n_iter, int
|
|||
#endif //SUPPORT_VERBOSITY
|
||||
)
|
||||
{
|
||||
bool high_deviation_occured = false;
|
||||
bool high_deviation_occured = false;
|
||||
bedPWMDisabled = 1;
|
||||
#ifdef TMC2130
|
||||
bool bHighPowerForced = false;
|
||||
if (tmc2130_mode == TMC2130_MODE_SILENT)
|
||||
{
|
||||
FORCE_HIGH_POWER_START;
|
||||
bHighPowerForced = true;
|
||||
}
|
||||
FORCE_HIGH_POWER_START;
|
||||
#endif
|
||||
//printf_P(PSTR("Min. Z: %f\n"), minimum_z);
|
||||
#ifdef SUPPORT_VERBOSITY
|
||||
|
|
@ -964,7 +974,7 @@ bool find_bed_induction_sensor_point_z(float minimum_z, uint8_t n_iter, int
|
|||
goto error;
|
||||
}
|
||||
#ifdef TMC2130
|
||||
if (!READ(Z_TMC2130_DIAG))
|
||||
if (READ(Z_TMC2130_DIAG) != 0)
|
||||
{
|
||||
//printf_P(PSTR("crash detected 1, current_pos[Z]: %f \n"), current_position[Z_AXIS]);
|
||||
goto error; //crash Z detected
|
||||
|
|
@ -972,7 +982,7 @@ bool find_bed_induction_sensor_point_z(float minimum_z, uint8_t n_iter, int
|
|||
#endif //TMC2130
|
||||
for (uint8_t i = 0; i < n_iter; ++ i)
|
||||
{
|
||||
|
||||
|
||||
current_position[Z_AXIS] += high_deviation_occured ? 0.5 : 0.2;
|
||||
float z_bckp = current_position[Z_AXIS];
|
||||
go_to_current(homing_feedrate[Z_AXIS]/60);
|
||||
|
|
@ -984,8 +994,9 @@ bool find_bed_induction_sensor_point_z(float minimum_z, uint8_t n_iter, int
|
|||
update_current_position_z();
|
||||
//printf_P(PSTR("Zs: %f, Z: %f, delta Z: %f"), z_bckp, current_position[Z_AXIS], (z_bckp - current_position[Z_AXIS]));
|
||||
if (fabs(current_position[Z_AXIS] - z_bckp) < 0.025) {
|
||||
//printf_P(PSTR("PINDA triggered immediately, move Z higher and repeat measurement\n"));
|
||||
raise_z(0.5);
|
||||
//printf_P(PSTR("PINDA triggered immediately, move Z higher and repeat measurement\n"));
|
||||
current_position[Z_AXIS] += 0.5;
|
||||
go_to_current(homing_feedrate[Z_AXIS]/60);
|
||||
current_position[Z_AXIS] = minimum_z;
|
||||
go_to_current(homing_feedrate[Z_AXIS]/(4*60));
|
||||
// we have to let the planner know where we are right now as it is not where we said to go.
|
||||
|
|
@ -1000,7 +1011,7 @@ bool find_bed_induction_sensor_point_z(float minimum_z, uint8_t n_iter, int
|
|||
goto error;
|
||||
}
|
||||
#ifdef TMC2130
|
||||
if (!READ(Z_TMC2130_DIAG)) {
|
||||
if (READ(Z_TMC2130_DIAG) != 0) {
|
||||
//printf_P(PSTR("crash detected 2, current_pos[Z]: %f \n"), current_position[Z_AXIS]);
|
||||
goto error; //crash Z detected
|
||||
}
|
||||
|
|
@ -1013,12 +1024,12 @@ bool find_bed_induction_sensor_point_z(float minimum_z, uint8_t n_iter, int
|
|||
//printf_P(PSTR("Z[%d] = %d, dz=%d\n"), i, (int)(current_position[Z_AXIS] * 1000), (int)(dz * 1000));
|
||||
//printf_P(PSTR("Z- measurement deviation from avg value %f um\n"), dz);
|
||||
if (dz > 0.05) { //deviation > 50um
|
||||
if (high_deviation_occured == false) { //first occurence may be caused in some cases by mechanic resonance probably especially if printer is placed on unstable surface
|
||||
if (high_deviation_occured == false) { //first occurence may be caused in some cases by mechanic resonance probably especially if printer is placed on unstable surface
|
||||
//printf_P(PSTR("high dev. first occurence\n"));
|
||||
delay_keep_alive(500); //damping
|
||||
//start measurement from the begining, but this time with higher movements in Z axis which should help to reduce mechanical resonance
|
||||
high_deviation_occured = true;
|
||||
i = -1;
|
||||
i = -1;
|
||||
z = 0;
|
||||
}
|
||||
else {
|
||||
|
|
@ -1036,7 +1047,7 @@ bool find_bed_induction_sensor_point_z(float minimum_z, uint8_t n_iter, int
|
|||
enable_z_endstop(endstop_z_enabled);
|
||||
// SERIAL_ECHOLNPGM("find_bed_induction_sensor_point_z 3");
|
||||
#ifdef TMC2130
|
||||
if (bHighPowerForced) FORCE_HIGH_POWER_END;
|
||||
FORCE_HIGH_POWER_END;
|
||||
#endif
|
||||
bedPWMDisabled = 0;
|
||||
return true;
|
||||
|
|
@ -1046,7 +1057,7 @@ error:
|
|||
enable_endstops(endstops_enabled);
|
||||
enable_z_endstop(endstop_z_enabled);
|
||||
#ifdef TMC2130
|
||||
if (bHighPowerForced) FORCE_HIGH_POWER_END;
|
||||
FORCE_HIGH_POWER_END;
|
||||
#endif
|
||||
bedPWMDisabled = 0;
|
||||
return false;
|
||||
|
|
@ -1186,6 +1197,8 @@ BedSkewOffsetDetectionResultType find_bed_induction_sensor_point_xy(int
|
|||
MYSERIAL.println(current_position[Z_AXIS]);
|
||||
}
|
||||
#endif //SUPPORT_VERBOSITY
|
||||
//lcd_show_fullscreen_message_and_wait_P(PSTR("First hit"));
|
||||
//lcd_update_enable(true);
|
||||
|
||||
float init_x_position = current_position[X_AXIS];
|
||||
float init_y_position = current_position[Y_AXIS];
|
||||
|
|
@ -1193,7 +1206,7 @@ BedSkewOffsetDetectionResultType find_bed_induction_sensor_point_xy(int
|
|||
// we have to let the planner know where we are right now as it is not where we said to go.
|
||||
update_current_position_xyz();
|
||||
enable_z_endstop(false);
|
||||
|
||||
|
||||
for (int8_t iter = 0; iter < 2; ++iter) {
|
||||
/*SERIAL_ECHOPGM("iter: ");
|
||||
MYSERIAL.println(iter);
|
||||
|
|
@ -1212,7 +1225,7 @@ BedSkewOffsetDetectionResultType find_bed_induction_sensor_point_xy(int
|
|||
invert_z_endstop(true);
|
||||
for (int iteration = 0; iteration < 8; iteration++) {
|
||||
|
||||
found = false;
|
||||
found = false;
|
||||
enable_z_endstop(true);
|
||||
go_xy(init_x_position + 16.0f, current_position[Y_AXIS], feedrate / 5);
|
||||
update_current_position_xyz();
|
||||
|
|
@ -1238,7 +1251,7 @@ BedSkewOffsetDetectionResultType find_bed_induction_sensor_point_xy(int
|
|||
current_position[X_AXIS] = 0.5f * (a + b);
|
||||
go_xy(current_position[X_AXIS], init_y_position, feedrate / 5);
|
||||
found = true;
|
||||
|
||||
|
||||
// Search in the Y direction along a cross.
|
||||
found = false;
|
||||
enable_z_endstop(true);
|
||||
|
|
@ -1314,7 +1327,7 @@ BedSkewOffsetDetectionResultType find_bed_induction_sensor_point_xy(int
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
enable_z_endstop(false);
|
||||
invert_z_endstop(false);
|
||||
return found;
|
||||
|
|
@ -1566,7 +1579,7 @@ inline bool improve_bed_induction_sensor_point()
|
|||
// Trim the vector from center_old_[x,y] to destination[x,y] by the bed dimensions.
|
||||
float vx = destination[X_AXIS] - center_old_x;
|
||||
float vy = destination[Y_AXIS] - center_old_y;
|
||||
float l = hypot(vx, vy);
|
||||
float l = sqrt(vx*vx+vy*vy);
|
||||
float t;
|
||||
if (destination[X_AXIS] < X_MIN_POS) {
|
||||
// Exiting the bed at xmin.
|
||||
|
|
@ -1802,7 +1815,7 @@ canceled:
|
|||
#define IMPROVE_BED_INDUCTION_SENSOR_POINT3_SEARCH_RADIUS (8.f)
|
||||
#define IMPROVE_BED_INDUCTION_SENSOR_POINT3_SEARCH_STEP_FINE_Y (0.1f)
|
||||
inline bool improve_bed_induction_sensor_point3(int verbosity_level)
|
||||
{
|
||||
{
|
||||
float center_old_x = current_position[X_AXIS];
|
||||
float center_old_y = current_position[Y_AXIS];
|
||||
float a, b;
|
||||
|
|
@ -2166,18 +2179,8 @@ inline void scan_bed_induction_sensor_point()
|
|||
|
||||
#define MESH_BED_CALIBRATION_SHOW_LCD
|
||||
|
||||
float __attribute__((noinline)) BED_X(const uint8_t col)
|
||||
{
|
||||
return ((float)col * x_mesh_density + BED_X0);
|
||||
}
|
||||
|
||||
float __attribute__((noinline)) BED_Y(const uint8_t row)
|
||||
{
|
||||
return ((float)row * y_mesh_density + BED_Y0);
|
||||
}
|
||||
|
||||
BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level, uint8_t &too_far_mask)
|
||||
{
|
||||
{
|
||||
// Don't let the manage_inactivity() function remove power from the motors.
|
||||
refresh_cmd_timeout();
|
||||
|
||||
|
|
@ -2188,13 +2191,13 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
|
|||
float *vec_y = vec_x + 2;
|
||||
float *cntr = vec_y + 2;
|
||||
memset(pts, 0, sizeof(float) * 7 * 7);
|
||||
uint8_t iteration = 0;
|
||||
uint8_t iteration = 0;
|
||||
BedSkewOffsetDetectionResultType result;
|
||||
|
||||
// SERIAL_ECHOLNPGM("find_bed_offset_and_skew verbosity level: ");
|
||||
// SERIAL_ECHO(int(verbosity_level));
|
||||
// SERIAL_ECHOPGM("");
|
||||
|
||||
|
||||
#ifdef NEW_XYZCAL
|
||||
{
|
||||
#else //NEW_XYZCAL
|
||||
|
|
@ -2206,7 +2209,7 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
|
|||
#ifdef SUPPORT_VERBOSITY
|
||||
if (verbosity_level >= 20) {
|
||||
SERIAL_ECHOLNPGM("Vectors: ");
|
||||
|
||||
|
||||
SERIAL_ECHOPGM("vec_x[0]:");
|
||||
MYSERIAL.print(vec_x[0], 5);
|
||||
SERIAL_ECHOLNPGM("");
|
||||
|
|
@ -2237,7 +2240,7 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
|
|||
/// Retry point scanning if a point with bad data appears.
|
||||
/// Bad data could be cause by "cold" sensor.
|
||||
/// This behavior vanishes after few point scans so retry will help.
|
||||
for (uint8_t retries = 0; retries <= 1; ++retries) {
|
||||
for (int retries = 0; retries <= 1; ++retries) {
|
||||
bool retry = false;
|
||||
for (int k = 0; k < 4; ++k) {
|
||||
// Don't let the manage_inactivity() function remove power from the motors.
|
||||
|
|
@ -2275,7 +2278,7 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
|
|||
else {
|
||||
// if first iteration failed, count corrected point coordinates as initial
|
||||
// Use the corrected coordinate, which is a result of find_bed_offset_and_skew().
|
||||
|
||||
|
||||
current_position[X_AXIS] = vec_x[0] * pgm_read_float(bed_ref_points_4 + k * 2) + vec_y[0] * pgm_read_float(bed_ref_points_4 + k * 2 + 1) + cntr[0];
|
||||
current_position[Y_AXIS] = vec_x[1] * pgm_read_float(bed_ref_points_4 + k * 2) + vec_y[1] * pgm_read_float(bed_ref_points_4 + k * 2 + 1) + cntr[1];
|
||||
|
||||
|
|
@ -2318,7 +2321,7 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
|
|||
|
||||
#ifndef NEW_XYZCAL
|
||||
#ifndef HEATBED_V2
|
||||
|
||||
|
||||
if (k == 0 || k == 1) {
|
||||
// Improve the position of the 1st row sensor points by a zig-zag movement.
|
||||
find_bed_induction_sensor_point_z();
|
||||
|
|
@ -2357,11 +2360,11 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
|
|||
pt[0] += (current_position[X_AXIS]/(iteration + 1)); //count average
|
||||
pt[1] = (pt[1] * iteration) / (iteration + 1);
|
||||
pt[1] += (current_position[Y_AXIS] / (iteration + 1));
|
||||
|
||||
|
||||
|
||||
|
||||
//pt[0] += current_position[X_AXIS];
|
||||
//if(iteration > 0) pt[0] = pt[0] / 2;
|
||||
|
||||
|
||||
//pt[1] += current_position[Y_AXIS];
|
||||
//if (iteration > 0) pt[1] = pt[1] / 2;
|
||||
|
||||
|
|
@ -2395,7 +2398,7 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
|
|||
}
|
||||
DBG(_n("All 4 calibration points found.\n"));
|
||||
delay_keep_alive(0); //manage_heater, reset watchdog, manage inactivity
|
||||
|
||||
|
||||
#ifdef SUPPORT_VERBOSITY
|
||||
if (verbosity_level >= 20) {
|
||||
// Test the positions. Are the positions reproducible? Now the calibration is active in the planner.
|
||||
|
|
@ -2422,29 +2425,32 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
|
|||
}
|
||||
result = calculate_machine_skew_and_offset_LS(pts, 4, bed_ref_points_4, vec_x, vec_y, cntr, verbosity_level);
|
||||
delay_keep_alive(0); //manage_heater, reset watchdog, manage inactivity
|
||||
|
||||
|
||||
if (result >= 0) {
|
||||
DBG(_n("Calibration success.\n"));
|
||||
world2machine_update(vec_x, vec_y, cntr);
|
||||
|
||||
#if 1
|
||||
// Fearlessly store the calibration values into the eeprom.
|
||||
eeprom_update_block_notify(&cntr[0], (float*)(EEPROM_BED_CALIBRATION_CENTER), 8);
|
||||
eeprom_update_block_notify(&vec_x[0], (float*)(EEPROM_BED_CALIBRATION_VEC_X), 8);
|
||||
eeprom_update_block_notify(&vec_y[0], (float*)(EEPROM_BED_CALIBRATION_VEC_Y), 8);
|
||||
|
||||
eeprom_update_float((float*)(EEPROM_BED_CALIBRATION_CENTER + 0), cntr[0]);
|
||||
eeprom_update_float((float*)(EEPROM_BED_CALIBRATION_CENTER + 4), cntr[1]);
|
||||
eeprom_update_float((float*)(EEPROM_BED_CALIBRATION_VEC_X + 0), vec_x[0]);
|
||||
eeprom_update_float((float*)(EEPROM_BED_CALIBRATION_VEC_X + 4), vec_x[1]);
|
||||
eeprom_update_float((float*)(EEPROM_BED_CALIBRATION_VEC_Y + 0), vec_y[0]);
|
||||
eeprom_update_float((float*)(EEPROM_BED_CALIBRATION_VEC_Y + 4), vec_y[1]);
|
||||
#endif
|
||||
#ifdef SUPPORT_VERBOSITY
|
||||
if (verbosity_level >= 10) {
|
||||
// Length of the vec_x
|
||||
float l = hypot(vec_x[0], vec_x[1]);
|
||||
float l = sqrt(vec_x[0] * vec_x[0] + vec_x[1] * vec_x[1]);
|
||||
SERIAL_ECHOLNPGM("X vector length:");
|
||||
MYSERIAL.println(l);
|
||||
|
||||
// Length of the vec_y
|
||||
l = hypot(vec_y[0], vec_y[1]);
|
||||
l = sqrt(vec_y[0] * vec_y[0] + vec_y[1] * vec_y[1]);
|
||||
SERIAL_ECHOLNPGM("Y vector length:");
|
||||
MYSERIAL.println(l);
|
||||
// Zero point correction
|
||||
l = hypot(cntr[0], cntr[1]);
|
||||
l = sqrt(cntr[0] * cntr[0] + cntr[1] * cntr[1]);
|
||||
SERIAL_ECHOLNPGM("Zero point correction:");
|
||||
MYSERIAL.println(l);
|
||||
|
||||
|
|
@ -2470,8 +2476,8 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
|
|||
uint8_t ix = mesh_point % MESH_MEAS_NUM_X_POINTS; // from 0 to MESH_NUM_X_POINTS - 1
|
||||
uint8_t iy = mesh_point / MESH_MEAS_NUM_X_POINTS;
|
||||
if (iy & 1) ix = (MESH_MEAS_NUM_X_POINTS - 1) - ix;
|
||||
current_position[X_AXIS] = BED_X(ix * 3);
|
||||
current_position[Y_AXIS] = BED_Y(iy * 3);
|
||||
current_position[X_AXIS] = BED_X(ix, MESH_MEAS_NUM_X_POINTS);
|
||||
current_position[Y_AXIS] = BED_Y(iy, MESH_MEAS_NUM_Y_POINTS);
|
||||
go_to_current(homing_feedrate[X_AXIS] / 60);
|
||||
delay_keep_alive(3000);
|
||||
}
|
||||
|
|
@ -2485,7 +2491,7 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
|
|||
}
|
||||
iteration++;
|
||||
}
|
||||
return result;
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifndef NEW_XYZCAL
|
||||
|
|
@ -2522,7 +2528,7 @@ BedSkewOffsetDetectionResultType improve_bed_offset_and_skew(int8_t method, int8
|
|||
bool endstop_z_enabled = enable_z_endstop(false);
|
||||
|
||||
#ifdef MESH_BED_CALIBRATION_SHOW_LCD
|
||||
lcd_display_message_fullscreen_P(_T(MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1));
|
||||
lcd_display_message_fullscreen_P(_i("Improving bed calibration point"));////MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1 c=60
|
||||
#endif /* MESH_BED_CALIBRATION_SHOW_LCD */
|
||||
|
||||
// Collect a matrix of 9x9 points.
|
||||
|
|
@ -2714,11 +2720,15 @@ BedSkewOffsetDetectionResultType improve_bed_offset_and_skew(int8_t method, int8
|
|||
}
|
||||
|
||||
world2machine_update(vec_x, vec_y, cntr);
|
||||
|
||||
#if 1
|
||||
// Fearlessly store the calibration values into the eeprom.
|
||||
eeprom_update_block_notify(&cntr[0], (float*)(EEPROM_BED_CALIBRATION_CENTER), 8);
|
||||
eeprom_update_block_notify(&vec_x[0], (float*)(EEPROM_BED_CALIBRATION_VEC_X), 8);
|
||||
eeprom_update_block_notify(&vec_y[0], (float*)(EEPROM_BED_CALIBRATION_VEC_Y), 8);
|
||||
eeprom_update_float((float*)(EEPROM_BED_CALIBRATION_CENTER+0), cntr [0]);
|
||||
eeprom_update_float((float*)(EEPROM_BED_CALIBRATION_CENTER+4), cntr [1]);
|
||||
eeprom_update_float((float*)(EEPROM_BED_CALIBRATION_VEC_X +0), vec_x[0]);
|
||||
eeprom_update_float((float*)(EEPROM_BED_CALIBRATION_VEC_X +4), vec_x[1]);
|
||||
eeprom_update_float((float*)(EEPROM_BED_CALIBRATION_VEC_Y +0), vec_y[0]);
|
||||
eeprom_update_float((float*)(EEPROM_BED_CALIBRATION_VEC_Y +4), vec_y[1]);
|
||||
#endif
|
||||
|
||||
// Correct the current_position to match the transformed coordinate system after world2machine_rotation_and_skew and world2machine_shift were set.
|
||||
world2machine_update_current();
|
||||
|
|
@ -2780,22 +2790,19 @@ canceled:
|
|||
#endif //NEW_XYZCAL
|
||||
|
||||
bool sample_z() {
|
||||
bool sampled = true;
|
||||
// make some space for the sheet
|
||||
// Avoid calling raise_z(), because a false triggering stallguard may prevent the Z from moving.
|
||||
// The extruder then may ram the sheet hard if not going down from some ~150mm height
|
||||
current_position[Z_AXIS] = 0.F;
|
||||
destination[Z_AXIS] = 150.F;
|
||||
plan_buffer_line_destinationXYZE(homing_feedrate[Z_AXIS] / 60);
|
||||
bool sampled = true;
|
||||
//make space
|
||||
current_position[Z_AXIS] += 150;
|
||||
go_to_current(homing_feedrate[Z_AXIS] / 60);
|
||||
//plan_buffer_line_curposXYZE(feedrate, active_extruder););
|
||||
|
||||
lcd_show_fullscreen_message_and_wait_P(_T(MSG_PLACE_STEEL_SHEET));
|
||||
lcd_show_fullscreen_message_and_wait_P(_T(MSG_PLACE_STEEL_SHEET));
|
||||
|
||||
// Sample Z heights for the mesh bed leveling.
|
||||
// In addition, store the results into an eeprom, to be used later for verification of the bed leveling process.
|
||||
if (!sample_mesh_and_store_reference())
|
||||
sampled = false;
|
||||
// Sample Z heights for the mesh bed leveling.
|
||||
// In addition, store the results into an eeprom, to be used later for verification of the bed leveling process.
|
||||
if (!sample_mesh_and_store_reference()) sampled = false;
|
||||
|
||||
return sampled;
|
||||
return sampled;
|
||||
}
|
||||
|
||||
void go_home_with_z_lift()
|
||||
|
|
@ -2805,16 +2812,16 @@ void go_home_with_z_lift()
|
|||
// Go home.
|
||||
// First move up to a safe height.
|
||||
current_position[Z_AXIS] = MESH_HOME_Z_SEARCH;
|
||||
go_to_current(homing_feedrate[Z_AXIS] / 60);
|
||||
go_to_current(homing_feedrate[Z_AXIS]/60);
|
||||
// Second move to XY [0, 0].
|
||||
current_position[X_AXIS] = X_MIN_POS + 0.2;
|
||||
current_position[Y_AXIS] = Y_MIN_POS + 0.2;
|
||||
current_position[X_AXIS] = X_MIN_POS+0.2;
|
||||
current_position[Y_AXIS] = Y_MIN_POS+0.2;
|
||||
// Clamp to the physical coordinates.
|
||||
world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]);
|
||||
go_to_current((3 * homing_feedrate[X_AXIS]) / 60);
|
||||
go_to_current(homing_feedrate[X_AXIS]/20);
|
||||
// Third move up to a safe height.
|
||||
current_position[Z_AXIS] = Z_MIN_POS;
|
||||
go_to_current(homing_feedrate[Z_AXIS] / 60);
|
||||
go_to_current(homing_feedrate[Z_AXIS]/60);
|
||||
}
|
||||
|
||||
// Sample the 9 points of the bed and store them into the EEPROM as a reference.
|
||||
|
|
@ -2823,10 +2830,6 @@ void go_home_with_z_lift()
|
|||
// Returns false if the reference values are more than 3mm far away.
|
||||
bool sample_mesh_and_store_reference()
|
||||
{
|
||||
bool result = false;
|
||||
#ifdef TMC2130
|
||||
tmc2130_home_enter(Z_AXIS_MASK);
|
||||
#endif
|
||||
bool endstops_enabled = enable_endstops(false);
|
||||
bool endstop_z_enabled = enable_z_endstop(false);
|
||||
|
||||
|
|
@ -2842,40 +2845,44 @@ bool sample_mesh_and_store_reference()
|
|||
// Sample Z heights for the mesh bed leveling.
|
||||
// In addition, store the results into an eeprom, to be used later for verification of the bed leveling process.
|
||||
{
|
||||
// Lower Z to the mesh search height with stall detection
|
||||
enable_endstops(true);
|
||||
// The first point defines the reference.
|
||||
current_position[Z_AXIS] = MESH_HOME_Z_SEARCH;
|
||||
go_to_current(homing_feedrate[Z_AXIS]/60);
|
||||
#ifdef TMC2130
|
||||
check_Z_crash();
|
||||
#endif
|
||||
enable_endstops(false);
|
||||
|
||||
// Move XY to first point
|
||||
current_position[X_AXIS] = BED_X0;
|
||||
current_position[Y_AXIS] = BED_Y0;
|
||||
world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]);
|
||||
go_to_current(homing_feedrate[X_AXIS]/60);
|
||||
set_destination_to_current();
|
||||
memcpy(destination, current_position, sizeof(destination));
|
||||
enable_endstops(true);
|
||||
homeaxis(Z_AXIS);
|
||||
|
||||
#ifdef TMC2130
|
||||
if (!axis_known_position[Z_AXIS] && (READ(Z_TMC2130_DIAG) != 0)) //Z crash
|
||||
{
|
||||
kill(_T(MSG_BED_LEVELING_FAILED_POINT_LOW));
|
||||
return false;
|
||||
}
|
||||
#endif //TMC2130
|
||||
|
||||
enable_endstops(false);
|
||||
if (!find_bed_induction_sensor_point_z()) //Z crash or deviation > 50um
|
||||
{
|
||||
kill(_T(MSG_BED_LEVELING_FAILED_POINT_LOW));
|
||||
return false;
|
||||
}
|
||||
mbl.set_z(0, 0, current_position[Z_AXIS]);
|
||||
}
|
||||
static_assert(MESH_MEAS_NUM_X_POINTS * MESH_MEAS_NUM_Y_POINTS <= 255, "overflow.....");
|
||||
for (uint8_t mesh_point = 1; mesh_point != MESH_MEAS_NUM_X_POINTS * MESH_MEAS_NUM_Y_POINTS; ++ mesh_point) {
|
||||
for (int8_t mesh_point = 1; mesh_point != MESH_MEAS_NUM_X_POINTS * MESH_MEAS_NUM_Y_POINTS; ++ mesh_point) {
|
||||
// Don't let the manage_inactivity() function remove power from the motors.
|
||||
refresh_cmd_timeout();
|
||||
// Print the decrasing ID of the measurement point.
|
||||
current_position[Z_AXIS] = MESH_HOME_Z_SEARCH;
|
||||
go_to_current(homing_feedrate[Z_AXIS]/60);
|
||||
uint8_t ix = mesh_point % MESH_MEAS_NUM_X_POINTS;
|
||||
uint8_t iy = mesh_point / MESH_MEAS_NUM_X_POINTS;
|
||||
int8_t ix = mesh_point % MESH_MEAS_NUM_X_POINTS;
|
||||
int8_t iy = mesh_point / MESH_MEAS_NUM_X_POINTS;
|
||||
if (iy & 1) ix = (MESH_MEAS_NUM_X_POINTS - 1) - ix; // Zig zag
|
||||
current_position[X_AXIS] = BED_X(ix * 3);
|
||||
current_position[Y_AXIS] = BED_Y(iy * 3);
|
||||
current_position[X_AXIS] = BED_X(ix, MESH_MEAS_NUM_X_POINTS);
|
||||
current_position[Y_AXIS] = BED_Y(iy, MESH_MEAS_NUM_Y_POINTS);
|
||||
world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]);
|
||||
go_to_current(homing_feedrate[X_AXIS]/60);
|
||||
#ifdef MESH_BED_CALIBRATION_SHOW_LCD
|
||||
|
|
@ -2886,9 +2893,10 @@ bool sample_mesh_and_store_reference()
|
|||
if (!find_bed_induction_sensor_point_z()) //Z crash or deviation > 50um
|
||||
{
|
||||
kill(_T(MSG_BED_LEVELING_FAILED_POINT_LOW));
|
||||
return false;
|
||||
}
|
||||
// Get cords of measuring point
|
||||
|
||||
|
||||
mbl.set_z(ix, iy, current_position[Z_AXIS]);
|
||||
}
|
||||
{
|
||||
|
|
@ -2904,7 +2912,7 @@ bool sample_mesh_and_store_reference()
|
|||
// The span of the Z offsets is extreme. Give up.
|
||||
// Homing failed on some of the points.
|
||||
SERIAL_PROTOCOLLNPGM("Exreme span of the Z values!");
|
||||
goto end;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2919,7 +2927,7 @@ bool sample_mesh_and_store_reference()
|
|||
continue;
|
||||
float dif = mbl.z_values[j][i] - mbl.z_values[0][0];
|
||||
int16_t dif_quantized = int16_t(floor(dif * 100.f + 0.5f));
|
||||
eeprom_update_word_notify((uint16_t*)addr, *reinterpret_cast<uint16_t*>(&dif_quantized));
|
||||
eeprom_update_word((uint16_t*)addr, *reinterpret_cast<uint16_t*>(&dif_quantized));
|
||||
#if 0
|
||||
{
|
||||
uint16_t z_offset_u = eeprom_read_word((uint16_t*)addr);
|
||||
|
|
@ -2940,18 +2948,14 @@ bool sample_mesh_and_store_reference()
|
|||
}
|
||||
}
|
||||
|
||||
mbl.reset();
|
||||
mbl.upsample_3x3();
|
||||
mbl.active = true;
|
||||
|
||||
go_home_with_z_lift();
|
||||
|
||||
result = true;
|
||||
end:
|
||||
enable_endstops(endstops_enabled);
|
||||
enable_z_endstop(endstop_z_enabled);
|
||||
#ifdef TMC2130
|
||||
tmc2130_home_exit();
|
||||
#endif
|
||||
return result;
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifndef NEW_XYZCAL
|
||||
|
|
@ -2997,8 +3001,8 @@ bool scan_bed_induction_points(int8_t verbosity_level)
|
|||
uint8_t ix = mesh_point % MESH_MEAS_NUM_X_POINTS; // from 0 to MESH_NUM_X_POINTS - 1
|
||||
uint8_t iy = mesh_point / MESH_MEAS_NUM_X_POINTS;
|
||||
if (iy & 1) ix = (MESH_MEAS_NUM_X_POINTS - 1) - ix;
|
||||
float bedX = BED_X(ix * 3);
|
||||
float bedY = BED_Y(iy * 3);
|
||||
float bedX = BED_X(ix, MESH_MEAS_NUM_X_POINTS);
|
||||
float bedY = BED_Y(iy, MESH_MEAS_NUM_Y_POINTS);
|
||||
current_position[X_AXIS] = vec_x[0] * bedX + vec_y[0] * bedY + cntr[0];
|
||||
current_position[Y_AXIS] = vec_x[1] * bedX + vec_y[1] * bedY + cntr[1];
|
||||
// The calibration points are very close to the min Y.
|
||||
|
|
@ -3027,12 +3031,9 @@ bool scan_bed_induction_points(int8_t verbosity_level)
|
|||
// To replace loading of the babystep correction.
|
||||
static void shift_z(float delta)
|
||||
{
|
||||
const float curpos_z = current_position[Z_AXIS];
|
||||
current_position[Z_AXIS] -= delta;
|
||||
plan_buffer_line_curposXYZE(homing_feedrate[Z_AXIS] / 60);
|
||||
plan_buffer_line(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS] - delta, current_position[E_AXIS], homing_feedrate[Z_AXIS]/40, active_extruder);
|
||||
st_synchronize();
|
||||
current_position[Z_AXIS] = curpos_z;
|
||||
plan_set_z_position(curpos_z);
|
||||
plan_set_z_position(current_position[Z_AXIS]);
|
||||
}
|
||||
|
||||
// Number of baby steps applied
|
||||
|
|
@ -3042,21 +3043,21 @@ void babystep_load()
|
|||
{
|
||||
babystepLoadZ = 0;
|
||||
// Apply Z height correction aka baby stepping before mesh bed leveling gets activated.
|
||||
if (calibration_status_get(CALIBRATION_STATUS_LIVE_ADJUST))
|
||||
if (calibration_status() < CALIBRATION_STATUS_LIVE_ADJUST)
|
||||
{
|
||||
check_babystep(); //checking if babystep is in allowed range, otherwise setting babystep to 0
|
||||
|
||||
|
||||
// End of G80: Apply the baby stepping value.
|
||||
babystepLoadZ = eeprom_read_word(reinterpret_cast<uint16_t *>(&(EEPROM_Sheets_base->
|
||||
s[(eeprom_read_byte(&(EEPROM_Sheets_base->active_sheet)))].z_offset)));
|
||||
|
||||
|
||||
#if 0
|
||||
SERIAL_ECHO("Z baby step: ");
|
||||
SERIAL_ECHO(babystepLoadZ);
|
||||
SERIAL_ECHO(", current Z: ");
|
||||
SERIAL_ECHO(current_position[Z_AXIS]);
|
||||
SERIAL_ECHO("correction: ");
|
||||
SERIAL_ECHO(float(babystepLoadZ) / float(axis_steps_per_mm[Z_AXIS]));
|
||||
SERIAL_ECHO(float(babystepLoadZ) / float(axis_steps_per_unit[Z_AXIS]));
|
||||
SERIAL_ECHOLN("");
|
||||
#endif
|
||||
}
|
||||
|
|
@ -3065,52 +3066,90 @@ void babystep_load()
|
|||
void babystep_apply()
|
||||
{
|
||||
babystep_load();
|
||||
shift_z(- float(babystepLoadZ) / float(cs.axis_steps_per_mm[Z_AXIS]));
|
||||
shift_z(- float(babystepLoadZ) / float(cs.axis_steps_per_unit[Z_AXIS]));
|
||||
}
|
||||
|
||||
void babystep_undo()
|
||||
{
|
||||
shift_z(float(babystepLoadZ) / float(cs.axis_steps_per_mm[Z_AXIS]));
|
||||
shift_z(float(babystepLoadZ) / float(cs.axis_steps_per_unit[Z_AXIS]));
|
||||
babystepLoadZ = 0;
|
||||
}
|
||||
|
||||
void babystep_reset()
|
||||
{
|
||||
babystepLoadZ = 0;
|
||||
babystepLoadZ = 0;
|
||||
}
|
||||
|
||||
void count_xyz_details(float (&distanceMin)[2]) {
|
||||
float cntr[2];
|
||||
float vec_x[2];
|
||||
float vec_y[2];
|
||||
eeprom_read_block(&cntr[0], (float*)(EEPROM_BED_CALIBRATION_CENTER), 8);
|
||||
eeprom_read_block(&vec_x[0], (float*)(EEPROM_BED_CALIBRATION_VEC_X), 8);
|
||||
eeprom_read_block(&vec_y[0], (float*)(EEPROM_BED_CALIBRATION_VEC_Y), 8);
|
||||
|
||||
float cntr[2] = {
|
||||
eeprom_read_float((float*)(EEPROM_BED_CALIBRATION_CENTER + 0)),
|
||||
eeprom_read_float((float*)(EEPROM_BED_CALIBRATION_CENTER + 4))
|
||||
};
|
||||
float vec_x[2] = {
|
||||
eeprom_read_float((float*)(EEPROM_BED_CALIBRATION_VEC_X + 0)),
|
||||
eeprom_read_float((float*)(EEPROM_BED_CALIBRATION_VEC_X + 4))
|
||||
};
|
||||
float vec_y[2] = {
|
||||
eeprom_read_float((float*)(EEPROM_BED_CALIBRATION_VEC_Y + 0)),
|
||||
eeprom_read_float((float*)(EEPROM_BED_CALIBRATION_VEC_Y + 4))
|
||||
};
|
||||
#if 0
|
||||
a2 = -1 * asin(vec_y[0] / MACHINE_AXIS_SCALE_Y);
|
||||
a1 = asin(vec_x[1] / MACHINE_AXIS_SCALE_X);
|
||||
angleDiff = fabs(a2 - a1);
|
||||
#endif
|
||||
for (uint8_t mesh_point = 0; mesh_point < 2; ++mesh_point) {
|
||||
float y = vec_x[1] * pgm_read_float(bed_ref_points_4 + mesh_point * 2) + vec_y[1] * pgm_read_float(bed_ref_points_4 + mesh_point * 2 + 1) + cntr[1];
|
||||
distanceMin[mesh_point] = (y - Y_MIN_POS_CALIBRATION_POINT_OUT_OF_REACH);
|
||||
}
|
||||
}
|
||||
/*
|
||||
e_MBL_TYPE e_mbl_type = e_MBL_OPTIMAL;
|
||||
|
||||
void mbl_mode_set() {
|
||||
switch (e_mbl_type) {
|
||||
case e_MBL_OPTIMAL: e_mbl_type = e_MBL_PREC; break;
|
||||
case e_MBL_PREC: e_mbl_type = e_MBL_FAST; break;
|
||||
case e_MBL_FAST: e_mbl_type = e_MBL_OPTIMAL; break;
|
||||
default: e_mbl_type = e_MBL_OPTIMAL; break;
|
||||
}
|
||||
eeprom_update_byte((uint8_t*)EEPROM_MBL_TYPE,(uint8_t)e_mbl_type);
|
||||
}
|
||||
|
||||
void mbl_mode_init() {
|
||||
uint8_t mbl_type = eeprom_read_byte((uint8_t*)EEPROM_MBL_TYPE);
|
||||
if (mbl_type == 0xFF) e_mbl_type = e_MBL_OPTIMAL;
|
||||
else e_mbl_type = mbl_type;
|
||||
}
|
||||
*/
|
||||
|
||||
void mbl_settings_init() {
|
||||
//3x3 mesh; 3 Z-probes on each point, magnet elimination on
|
||||
//magnet elimination: use aaproximate Z-coordinate instead of measured values for points which are near magnets
|
||||
eeprom_init_default_byte((uint8_t*)EEPROM_MBL_MAGNET_ELIMINATION, 1);
|
||||
eeprom_init_default_byte((uint8_t*)EEPROM_MBL_POINTS_NR, 3);
|
||||
eeprom_init_default_byte((uint8_t*)EEPROM_MBL_PROBE_NR, 3);
|
||||
if (eeprom_read_byte((uint8_t*)EEPROM_MBL_MAGNET_ELIMINATION) == 0xFF) {
|
||||
eeprom_update_byte((uint8_t*)EEPROM_MBL_MAGNET_ELIMINATION, 1);
|
||||
}
|
||||
if (eeprom_read_byte((uint8_t*)EEPROM_MBL_POINTS_NR) == 0xFF) {
|
||||
eeprom_update_byte((uint8_t*)EEPROM_MBL_POINTS_NR, 3);
|
||||
}
|
||||
mbl_z_probe_nr = eeprom_read_byte((uint8_t*)EEPROM_MBL_PROBE_NR);
|
||||
if (mbl_z_probe_nr == 0xFF) {
|
||||
mbl_z_probe_nr = 3;
|
||||
eeprom_update_byte((uint8_t*)EEPROM_MBL_PROBE_NR, mbl_z_probe_nr);
|
||||
}
|
||||
}
|
||||
|
||||
//parameter ix: index of mesh bed leveling point in X-axis (for meas_points == 7 is valid range from 0 to 6; for meas_points == 3 is valid range from 0 to 2 )
|
||||
//parameter iy: index of mesh bed leveling point in Y-axis (for meas_points == 7 is valid range from 0 to 6; for meas_points == 3 is valid range from 0 to 2 )
|
||||
//parameter ix: index of mesh bed leveling point in X-axis (for meas_points == 7 is valid range from 0 to 6; for meas_points == 3 is valid range from 0 to 2 )
|
||||
//parameter iy: index of mesh bed leveling point in Y-axis (for meas_points == 7 is valid range from 0 to 6; for meas_points == 3 is valid range from 0 to 2 )
|
||||
//parameter meas_points: number of mesh bed leveling points in one axis; currently designed and tested for values 3 and 7
|
||||
//parameter zigzag: false if ix is considered 0 on left side of bed and ix rises with rising X coordinate; true if ix is considered 0 on the right side of heatbed for odd iy values (zig zag mesh bed leveling movements)
|
||||
//function returns true if point is considered valid (typicaly in safe distance from magnet or another object which inflences PINDA measurements)
|
||||
bool mbl_point_measurement_valid(uint8_t ix, uint8_t iy) {
|
||||
bool mbl_point_measurement_valid(uint8_t ix, uint8_t iy, uint8_t meas_points, bool zigzag) {
|
||||
//"human readable" heatbed plan
|
||||
//magnet proximity influence Z coordinate measurements significantly (40 - 100 um)
|
||||
//0 - measurement point is above magnet and Z coordinate can be influenced negatively
|
||||
//1 - we should be in safe distance from magnets, measurement should be accurate
|
||||
if ((ix >= MESH_NUM_X_POINTS) || (iy >= MESH_NUM_Y_POINTS))
|
||||
return false;
|
||||
if ((ix >= meas_points) || (iy >= meas_points)) return false;
|
||||
|
||||
uint8_t valid_points_mask[7] = {
|
||||
//[X_MAX,Y_MAX]
|
||||
|
|
@ -3124,26 +3163,36 @@ bool mbl_point_measurement_valid(uint8_t ix, uint8_t iy) {
|
|||
0b1111111,//0
|
||||
//[0,0]
|
||||
};
|
||||
return (valid_points_mask[6 - iy] & (1 << (6 - ix)));
|
||||
if (meas_points == 3) {
|
||||
ix *= 3;
|
||||
iy *= 3;
|
||||
}
|
||||
if (zigzag) {
|
||||
if ((iy % 2) == 0) return (valid_points_mask[6 - iy] & (1 << (6 - ix)));
|
||||
else return (valid_points_mask[6 - iy] & (1 << ix));
|
||||
}
|
||||
else {
|
||||
return (valid_points_mask[6 - iy] & (1 << (6 - ix)));
|
||||
}
|
||||
}
|
||||
|
||||
void mbl_single_point_interpolation(uint8_t x, uint8_t y) {
|
||||
void mbl_single_point_interpolation(uint8_t x, uint8_t y, uint8_t meas_points) {
|
||||
//printf_P(PSTR("x = %d; y = %d \n"), x, y);
|
||||
uint8_t count = 0;
|
||||
float z = 0;
|
||||
if (mbl_point_measurement_valid(x, y + 1)) { z += mbl.z_values[y + 1][x]; /*printf_P(PSTR("x; y+1: Z = %f \n"), mbl.z_values[y + 1][x]);*/ count++; }
|
||||
if (mbl_point_measurement_valid(x, y - 1)) { z += mbl.z_values[y - 1][x]; /*printf_P(PSTR("x; y-1: Z = %f \n"), mbl.z_values[y - 1][x]);*/ count++; }
|
||||
if (mbl_point_measurement_valid(x + 1, y)) { z += mbl.z_values[y][x + 1]; /*printf_P(PSTR("x+1; y: Z = %f \n"), mbl.z_values[y][x + 1]);*/ count++; }
|
||||
if (mbl_point_measurement_valid(x - 1, y)) { z += mbl.z_values[y][x - 1]; /*printf_P(PSTR("x-1; y: Z = %f \n"), mbl.z_values[y][x - 1]);*/ count++; }
|
||||
if (mbl_point_measurement_valid(x, y + 1, meas_points, false)) { z += mbl.z_values[y + 1][x]; /*printf_P(PSTR("x; y+1: Z = %f \n"), mbl.z_values[y + 1][x]);*/ count++; }
|
||||
if (mbl_point_measurement_valid(x, y - 1, meas_points, false)) { z += mbl.z_values[y - 1][x]; /*printf_P(PSTR("x; y-1: Z = %f \n"), mbl.z_values[y - 1][x]);*/ count++; }
|
||||
if (mbl_point_measurement_valid(x + 1, y, meas_points, false)) { z += mbl.z_values[y][x + 1]; /*printf_P(PSTR("x+1; y: Z = %f \n"), mbl.z_values[y][x + 1]);*/ count++; }
|
||||
if (mbl_point_measurement_valid(x - 1, y, meas_points, false)) { z += mbl.z_values[y][x - 1]; /*printf_P(PSTR("x-1; y: Z = %f \n"), mbl.z_values[y][x - 1]);*/ count++; }
|
||||
if(count != 0) mbl.z_values[y][x] = z / count; //if we have at least one valid point in surrounding area use average value, otherwise use inaccurately measured Z-coordinate
|
||||
//printf_P(PSTR("result: Z = %f \n\n"), mbl.z_values[y][x]);
|
||||
}
|
||||
|
||||
void mbl_magnet_elimination() {
|
||||
for (uint8_t y = 0; y < MESH_NUM_Y_POINTS; y++) {
|
||||
for (uint8_t x = 0; x < MESH_NUM_X_POINTS; x++) {
|
||||
if (!mbl_point_measurement_valid(x, y)) {
|
||||
mbl_single_point_interpolation(x, y);
|
||||
void mbl_interpolation(uint8_t meas_points) {
|
||||
for (uint8_t x = 0; x < meas_points; x++) {
|
||||
for (uint8_t y = 0; y < meas_points; y++) {
|
||||
if (!mbl_point_measurement_valid(x, y, meas_points, false)) {
|
||||
mbl_single_point_interpolation(x, y, meas_points);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <avr/pgmspace.h>
|
||||
#include "Marlin.h"
|
||||
|
||||
#define BED_ZERO_REF_X (- 22.f + X_PROBE_OFFSET_FROM_EXTRUDER) // -22 + 23 = 1
|
||||
#define BED_ZERO_REF_Y (- 0.6f + Y_PROBE_OFFSET_FROM_EXTRUDER + 4.f) // -0.6 + 5 + 4 = 8.4
|
||||
|
|
@ -21,8 +21,8 @@
|
|||
|
||||
#endif //not HEATBED_V2
|
||||
|
||||
constexpr float x_mesh_density = (BED_Xn - BED_X0) / (MESH_NUM_X_POINTS - 1);
|
||||
constexpr float y_mesh_density = (BED_Yn - BED_Y0) / (MESH_NUM_Y_POINTS - 1);
|
||||
#define BED_X(i, n) ((float)i * (BED_Xn - BED_X0) / (n - 1) + BED_X0)
|
||||
#define BED_Y(i, n) ((float)i * (BED_Yn - BED_Y0) / (n - 1) + BED_Y0)
|
||||
|
||||
// Exact positions of the print head above the bed reference points, in the world coordinates.
|
||||
// The world coordinates match the machine coordinates only in case, when the machine
|
||||
|
|
@ -129,15 +129,16 @@ inline bool world2machine_clamp(float &x, float &y)
|
|||
if (tmpx < X_MIN_POS) {
|
||||
tmpx = X_MIN_POS;
|
||||
clamped = true;
|
||||
} else if (tmpx > X_MAX_POS) {
|
||||
tmpx = X_MAX_POS;
|
||||
clamped = true;
|
||||
}
|
||||
|
||||
if (tmpy < Y_MIN_POS) {
|
||||
tmpy = Y_MIN_POS;
|
||||
clamped = true;
|
||||
} else if (tmpy > Y_MAX_POS) {
|
||||
}
|
||||
if (tmpx > X_MAX_POS) {
|
||||
tmpx = X_MAX_POS;
|
||||
clamped = true;
|
||||
}
|
||||
if (tmpy > Y_MAX_POS) {
|
||||
tmpy = Y_MAX_POS;
|
||||
clamped = true;
|
||||
}
|
||||
|
|
@ -145,17 +146,6 @@ inline bool world2machine_clamp(float &x, float &y)
|
|||
machine2world(tmpx, tmpy, x, y);
|
||||
return clamped;
|
||||
}
|
||||
|
||||
/// @brief For a given column on the mesh calculate the bed X coordinate
|
||||
/// @param col column index on mesh
|
||||
/// @return Bed X coordinate
|
||||
float BED_X(const uint8_t col);
|
||||
|
||||
/// @brief For a given row on the mesh calculate the bed Y coordinate
|
||||
/// @param row row index on mesh
|
||||
/// @return Bed Y coordinate
|
||||
float BED_Y(const uint8_t row);
|
||||
|
||||
/**
|
||||
* @brief Bed skew and offest detection result
|
||||
*
|
||||
|
|
@ -163,13 +153,13 @@ float BED_Y(const uint8_t row);
|
|||
* Negative: failed
|
||||
*/
|
||||
|
||||
enum BedSkewOffsetDetectionResultType : int8_t {
|
||||
enum BedSkewOffsetDetectionResultType {
|
||||
// Detection failed, some point was not found.
|
||||
BED_SKEW_OFFSET_DETECTION_POINT_FOUND = 0, //!< Point found
|
||||
BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND = -1, //!< Point not found.
|
||||
BED_SKEW_OFFSET_DETECTION_FITTING_FAILED = -2, //!< Fitting failed
|
||||
BED_SKEW_OFFSET_DETECTION_POINT_SCAN_FAILED = -3, //!< Point scan failed, try again
|
||||
|
||||
|
||||
// Detection finished with success.
|
||||
BED_SKEW_OFFSET_DETECTION_PERFECT = 0, //!< Perfect.
|
||||
BED_SKEW_OFFSET_DETECTION_SKEW_MILD = 1, //!< Mildly skewed.
|
||||
|
|
@ -195,7 +185,7 @@ extern bool is_bed_z_jitter_data_valid();
|
|||
// Useful for visualizing the behavior of the bed induction detector.
|
||||
extern bool scan_bed_induction_points(int8_t verbosity_level);
|
||||
|
||||
// Load Z babystep value from the EEPROM into babystepLoadZ,
|
||||
// Load Z babystep value from the EEPROM into babystepLoadZ,
|
||||
// but don't apply it through the planner. This is useful on wake up
|
||||
// after power panic, when it is expected, that the baby step has been already applied.
|
||||
extern void babystep_load();
|
||||
|
|
@ -212,7 +202,16 @@ extern void babystep_reset();
|
|||
|
||||
extern void count_xyz_details(float (&distanceMin)[2]);
|
||||
extern bool sample_z();
|
||||
|
||||
/*
|
||||
typedef enum
|
||||
{
|
||||
e_MBL_FAST, e_MBL_OPTIMAL, e_MBL_PREC
|
||||
} e_MBL_TYPE;
|
||||
*/
|
||||
//extern e_MBL_TYPE e_mbl_type;
|
||||
//extern void mbl_mode_set();
|
||||
//extern void mbl_mode_init();
|
||||
extern void mbl_settings_init();
|
||||
extern bool mbl_point_measurement_valid(uint8_t ix, uint8_t iy);
|
||||
extern void mbl_magnet_elimination();
|
||||
|
||||
extern bool mbl_point_measurement_valid(uint8_t ix, uint8_t iy, uint8_t meas_points, bool zigzag);
|
||||
extern void mbl_interpolation(uint8_t meas_points);
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue