Merge branch 'MK3' into 2091_2153_sheet_Mcode
This commit is contained in:
commit
20eef890a6
|
|
@ -0,0 +1,21 @@
|
|||
# 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": "*",
|
||||
}
|
||||
},
|
||||
}
|
||||
|
|
@ -12,3 +12,6 @@ indent_style = space
|
|||
indent_size = 4
|
||||
tab_width = 4
|
||||
max_line_length = 100
|
||||
|
||||
[lang/po/*.po]
|
||||
end_of_line = crlf
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
lang/po/*.po text eol=crlf diff=po
|
||||
lang/po/*.pot text diff=po
|
||||
|
|
@ -6,14 +6,17 @@ 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, ...]
|
||||
**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, ...]
|
||||
**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.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
---
|
||||
name: Community
|
||||
about: Related to "Community made" features
|
||||
title: "[Community made] <Enter comprehensive title>"
|
||||
labels: community_made
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
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.
|
||||
|
||||
**Which Community made feature do you want to address?**
|
||||
|
||||
**What is your request/question/suggestion?**
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
#!/bin/sh
|
||||
set -xe
|
||||
rm -rf build
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. \
|
||||
-DCMAKE_TOOLCHAIN_FILE="../cmake/AvrGcc.cmake" \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-G Ninja
|
||||
ninja ALL_FIRMWARE
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
#!/bin/sh
|
||||
set -xe
|
||||
rm -rf build
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. \
|
||||
-DCMAKE_TOOLCHAIN_FILE="../cmake/AvrGcc.cmake" \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-G Ninja
|
||||
|
||||
# ignore all failures in order to show as much output as possible
|
||||
ninja -k0 check_lang || true
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
#!/bin/sh
|
||||
set -xe
|
||||
rm -rf build
|
||||
mkdir build
|
||||
cd build
|
||||
cmake .. -G Ninja
|
||||
ninja tests
|
||||
ctest
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
#!/bin/sh
|
||||
set -xe
|
||||
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; }
|
||||
bash -x build.sh EN_FARM || { echo "1_75mm_MK3S-EINSy10a-E3Dv6full EN_FARM 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; }
|
||||
bash -x build.sh EN_FARM || { echo "1_75mm_MK3-EINSy10a-E3Dv6full EN_FARM 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
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
#!/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'
|
||||
}
|
||||
|
||||
echo "This PR will consume:" > "$MESSAGE"
|
||||
for TARGET in $@
|
||||
do
|
||||
base_bin=$(echo ${BASE_DIR}/build_gen/*/$TARGET)
|
||||
base_flash=$(avr_flash "$base_bin")
|
||||
base_ram=$(avr_ram "$base_bin")
|
||||
|
||||
pr_bin=$(echo ${PR_DIR}/build_gen/*/$TARGET)
|
||||
pr_flash=$(avr_flash "$pr_bin")
|
||||
pr_ram=$(avr_ram "$pr_bin")
|
||||
|
||||
flash_d=$(($pr_flash - $base_flash))
|
||||
ram_d=$(($pr_ram - $base_ram))
|
||||
|
||||
echo "- \`$TARGET\`: ${flash_d}b of flash, ${ram_d}b of ram" >> "$MESSAGE"
|
||||
done
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
name: pr-size
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ MK3, MK3_* ]
|
||||
|
||||
env:
|
||||
TARGETS: "MK3S-EINSy10a_ENGLISH MK3-EINSy10a_ENGLISH"
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
|
||||
# setup base required dependencies
|
||||
- name: Setup dependencies
|
||||
run: |
|
||||
sudo apt-get install cmake ninja-build python3-pyelftools python3-regex python3-polib
|
||||
|
||||
# build the PR branch
|
||||
- name: Checkout PR
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Setup build dependencies
|
||||
run: |
|
||||
./utils/bootstrap.py
|
||||
|
||||
- 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
|
||||
|
||||
# save pr-size for later use
|
||||
- name: Save pr-size from PR
|
||||
run: |
|
||||
cp -f ./.github/workflows/pr-size.sh build-pr
|
||||
|
||||
# build the base branch
|
||||
- name: Checkout base
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
clean: false
|
||||
ref: ${{ github.event.pull_request.base.ref }}
|
||||
|
||||
- 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
|
||||
|
||||
# extract/show build differences
|
||||
- name: Calculate binary changes
|
||||
run: |
|
||||
rm -rf build-changes
|
||||
./build-pr/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,54 +1,31 @@
|
|||
.settings
|
||||
.project
|
||||
.cproject
|
||||
Debug
|
||||
Firmware/Configuration_prusa.h
|
||||
Firmware/Doc
|
||||
/Firmware/.vs/Firmware/v14
|
||||
/Firmware/__vm
|
||||
/Firmware/Firmware.sln
|
||||
/Firmware/Firmware.vcxproj
|
||||
/Firmware/Firmware.vcxproj.filters
|
||||
/Firmware/Firmware - Shortcut.lnk
|
||||
/Firmware/variants/1_75mm_MK3-MMU-EINSy10a-E3Dv6full.h.bak
|
||||
/Firmware/Marlin_main.cpp~RF12cfae7.TMP
|
||||
/Firmware/variants/1_75mm_MK3-EINSy10a-E3Dv6full.h.bak
|
||||
/html
|
||||
/latex
|
||||
/Doxyfile
|
||||
/Firmware/builds/1_75mm_MK3-EINY04-E3Dv6full
|
||||
/Firmware/Configuration_prusa.h.bak
|
||||
/Firmware/Configuration_prusa_backup.h
|
||||
/Firmware/ultralcd_implementation_hitachi_HD44780.h.bak
|
||||
/Firmware/ultralcd.cpp.bak
|
||||
/Firmware/temperature.cpp.bak
|
||||
/Firmware/pins.h.bak
|
||||
/Firmware/Marlin_main.cpp.bak
|
||||
/Firmware/language_pl.h.bak
|
||||
/Firmware/language_it.h.bak
|
||||
/Firmware/language_es.h.bak
|
||||
/Firmware/language_en.h.bak
|
||||
/Firmware/language_de.h.bak
|
||||
/Firmware/language_cz.h.bak
|
||||
/Firmware/variants/1_75mm_MK2-MultiMaterial-RAMBo13a-E3Dv6full.h
|
||||
/Firmware/variants/1_75mm_MK2-MultiMaterial-RAMBo10a-E3Dv6full.h
|
||||
/Firmware/variants/1_75mm_MK2-EINY01-E3Dv6full.h.bak
|
||||
/Firmware/variants/1_75mm_MK1-RAMBo13a-E3Dv6full.h
|
||||
/Firmware/variants/1_75mm_MK1-RAMBo10a-E3Dv6full.h
|
||||
/lang/*.bin
|
||||
/lang/*.hex
|
||||
/lang/*.dat
|
||||
/lang/*.tmp
|
||||
/lang/*.out
|
||||
/lang/not_tran.txt
|
||||
/lang/not_used.txt
|
||||
/lang/progmem1.chr
|
||||
/lang/progmem1.lss
|
||||
/lang/progmem1.txt
|
||||
/lang/progmem1.var
|
||||
/lang/text.sym
|
||||
/lang/textaddr.txt
|
||||
# IDE data
|
||||
/.settings
|
||||
/.project
|
||||
/.cproject
|
||||
|
||||
# cmake
|
||||
/build/
|
||||
/build_gen/
|
||||
/.dependencies
|
||||
/compile_commands.json
|
||||
|
||||
# Temporary configuration
|
||||
/Firmware/Configuration_prusa.h
|
||||
|
||||
# Temporary language files
|
||||
/lang/po/*.mo
|
||||
/lang/tmp/
|
||||
/lang/Firmware-intl.hex
|
||||
/lang/Firmware-intl-en_*.hex
|
||||
/lang/*.map
|
||||
|
||||
# Temporary files and directories
|
||||
*[~#]
|
||||
*.tmp
|
||||
*.bak
|
||||
.DS_Store
|
||||
__pycache__
|
||||
|
||||
# Generated files
|
||||
/build-env/
|
||||
/Firmware/Firmware.vcxproj
|
||||
/Firmware/Configuration_prusa_bckp.h
|
||||
/Firmware/variants/printers.h
|
||||
/Firmware/Doc/
|
||||
|
|
|
|||
76
.travis.yml
76
.travis.yml
|
|
@ -1,35 +1,55 @@
|
|||
dist: trusty
|
||||
dist: focal
|
||||
language: minimal
|
||||
|
||||
cache:
|
||||
directories:
|
||||
# cmake project dependencies
|
||||
- .dependencies/
|
||||
# legacy PF-build dependencies
|
||||
- ./../PF-build-env/
|
||||
|
||||
before_install:
|
||||
- sudo apt-get install -y ninja-build
|
||||
# Arduino IDE adds a lot of noise caused by network traffic, trying to firewall it off
|
||||
# Prepare the dependencies for the old build environment
|
||||
- sudo apt-get install -y python3-polib python3-pyelftools python3-regex
|
||||
|
||||
# Undo whatever *GARBAGE* travis is doing with python and restore the system version
|
||||
- mkdir -p .dependencies/python3
|
||||
- ln -sf /usr/bin/python3 .dependencies/python3/python3
|
||||
- PATH=$PWD/.dependencies/python3:$PATH
|
||||
|
||||
# Bootstrap cmake/ninja for the new build environment
|
||||
- ./utils/bootstrap.py
|
||||
- PATH=$(./utils/bootstrap.py --print-dependency-directory "cmake")/bin:$PATH
|
||||
- PATH=$(./utils/bootstrap.py --print-dependency-directory "ninja"):$PATH
|
||||
|
||||
# Arduino IDE adds a lot of noise caused by network traffic, 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; }
|
||||
|
||||
jobs:
|
||||
include:
|
||||
# legacy build.sh environment
|
||||
- stage: legacy
|
||||
script: ./.github/travis/legacy-build.sh
|
||||
|
||||
# cmake-based build
|
||||
- stage: cmake
|
||||
script: ./.github/travis/cmake-build.sh
|
||||
|
||||
# cmake tests
|
||||
- stage: tests
|
||||
script: ./.github/travis/cmake-test.sh
|
||||
|
||||
# language checks
|
||||
- stage: lang
|
||||
script: ./.github/travis/cmake-lang.sh
|
||||
|
||||
stages:
|
||||
- cmake
|
||||
- lang
|
||||
- legacy
|
||||
- tests
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
[
|
||||
{
|
||||
"name": "avr-gcc",
|
||||
"toolchainFile": "${workspaceFolder}/cmake/AvrGcc.cmake",
|
||||
"cmakeSettings": {
|
||||
"CMAKE_MAKE_PROGRAM": "${workspaceFolder}/.dependencies/ninja-1.10.2/ninja",
|
||||
"CMAKE_BUILD_TYPE": "Release"
|
||||
}
|
||||
}
|
||||
]
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
buildType:
|
||||
default: debug
|
||||
choices:
|
||||
debug:
|
||||
short: Debug
|
||||
long: Emit debug information
|
||||
buildType: Debug
|
||||
release:
|
||||
short: Release
|
||||
long: Optimize generated code
|
||||
buildType: Release
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"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"
|
||||
}
|
||||
}
|
||||
535
CMakeLists.txt
535
CMakeLists.txt
|
|
@ -1,24 +1,519 @@
|
|||
cmake_minimum_required(VERSION 3.1)
|
||||
cmake_minimum_required(VERSION 3.19)
|
||||
include(cmake/Utilities.cmake)
|
||||
include(cmake/GetGitRevisionDescription.cmake)
|
||||
include(cmake/ReproducibleBuild.cmake)
|
||||
|
||||
set (CMAKE_CXX_STANDARD 11)
|
||||
set(PROJECT_VERSION_SUFFIX
|
||||
"<auto>"
|
||||
CACHE
|
||||
STRING
|
||||
"Full version suffix to be shown on the info screen in settings (e.g. full_version=4.0.3-BETA+1035.PR111.B4, suffix=-BETA+1035.PR111.B4). Defaults to '+<commit sha>.<dirty?>.<debug?>' if set to '<auto>'."
|
||||
)
|
||||
set(PROJECT_VERSION_SUFFIX_SHORT
|
||||
"<auto>"
|
||||
CACHE
|
||||
STRING
|
||||
"Short version suffix to be shown on splash screen. Defaults to '+<BUILD_NUMBER>' if set to '<auto>'."
|
||||
)
|
||||
set(BUILD_NUMBER
|
||||
""
|
||||
CACHE STRING "Build number of the firmware. Resolved automatically if not specified."
|
||||
)
|
||||
|
||||
project(cmake_test)
|
||||
include(cmake/ProjectVersion.cmake)
|
||||
resolve_version_variables()
|
||||
|
||||
# Prepare "Catch" library for other executables
|
||||
set(CATCH_INCLUDE_DIR Catch2)
|
||||
add_library(Catch INTERFACE)
|
||||
target_include_directories(Catch INTERFACE ${CATCH_INCLUDE_DIR})
|
||||
set(PROJECT_VERSION_FLAVOUR
|
||||
""
|
||||
CACHE STRING "Firmware flavour to build - DEBUG, DEVEL, APLHA, BETA or RC"
|
||||
)
|
||||
set(PROJECT_VERSION_FLAVOUR_REVISION
|
||||
""
|
||||
CACHE STRING "Firmware flavour version, e.g. 1 for RC1, etc"
|
||||
)
|
||||
|
||||
# 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)
|
||||
if(NOT PROJECT_VERSION_FLAVOUR STREQUAL "")
|
||||
set(PROJECT_VERSION "${PROJECT_VERSION}-${PROJECT_VERSION_FLAVOUR}")
|
||||
add_compile_definitions(FW_FLAVOR=${PROJECT_VERSION_FLAVOUR})
|
||||
if(NOT PROJECT_VERSION_FLAVOUR_REVISION STREQUAL "")
|
||||
set(PROJECT_VERSION "${PROJECT_VERSION}${PROJECT_VERSION_FLAVOUR_REVISION}")
|
||||
add_compile_definitions(FW_FLAVERSION=${PROJECT_VERSION_FLAVOUR_REVISION})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Inform user about the resolved settings
|
||||
message(STATUS "Project version: ${PROJECT_VERSION}")
|
||||
message(
|
||||
STATUS "Project version with short suffix: ${PROJECT_VERSION}${PROJECT_VERSION_SUFFIX_SHORT}"
|
||||
)
|
||||
|
||||
set(FN_PREFIX "FW${PROJECT_VERSION}${PROJECT_VERSION_SUFFIX_SHORT}")
|
||||
|
||||
# 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)
|
||||
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
|
||||
la10compat.cpp
|
||||
language.c
|
||||
lcd.cpp
|
||||
Marlin_main.cpp
|
||||
MarlinSerial.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
|
||||
Prusa_farm.cpp
|
||||
qr_solve.cpp
|
||||
rbuf.c
|
||||
Sd2Card.cpp
|
||||
SdBaseFile.cpp
|
||||
SdFatUtil.cpp
|
||||
SdFile.cpp
|
||||
SdVolume.cpp
|
||||
Servo.cpp
|
||||
sm4.c
|
||||
sound.cpp
|
||||
speed_lookuptable.cpp
|
||||
spi.c
|
||||
SpoolJoin.cpp
|
||||
stepper.cpp
|
||||
swi2c.c
|
||||
Tcodes.cpp
|
||||
temperature.cpp
|
||||
timer02.c
|
||||
Timer.cpp
|
||||
tmc2130.cpp
|
||||
tone04.c
|
||||
twi.cpp
|
||||
uart2.c
|
||||
ultralcd.cpp
|
||||
util.cpp
|
||||
vector_3.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)
|
||||
# TODO: get date from the last git commit to set as epoch
|
||||
set_source_epoch(0)
|
||||
|
||||
# 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
|
||||
)
|
||||
|
||||
target_compile_definitions(${variant_name} PRIVATE CMAKE_CONTROL)
|
||||
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")
|
||||
set(FW_HEX ${CMAKE_BINARY_DIR}/${FN_PREFIX}-${FW_EN}.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 ${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(LANG_HEX ${CMAKE_BINARY_DIR}/${FN_PREFIX}-${FW_LANG_FINAL}.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}
|
||||
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}/${FN_PREFIX}-${FW_LANG_FINAL}.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_OBJCOPY} -O binary ${FW_LANG_BASE} ${FW_LANG_FINAL}.bin
|
||||
COMMAND ${CMAKE_SOURCE_DIR}/lang/lang-patchsec.py ${FW_LANG_BASE} ${LANG_BIN}
|
||||
${FW_LANG_FINAL}.bin
|
||||
DEPENDS ${FW_LANG_BASE} ${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}
|
||||
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})
|
||||
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}")
|
||||
string(REPLACE "-E3Dv6full" "" DIR_NAME "${THIS_VAR}")
|
||||
string(REPLACE "1_75mm_" "" DIR_NAME "${DIR_NAME}")
|
||||
|
||||
# Generate a file in a subfolder so that we can organize things a little more neatly in VS code
|
||||
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})\nfw_add_variant(${THIS_VAR})"
|
||||
)
|
||||
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/build_gen/${DIR_NAME})
|
||||
endforeach(THIS_VAR IN LISTS FW_VARIANTS)
|
||||
endif()
|
||||
|
||||
#
|
||||
# Tests
|
||||
#
|
||||
if(NOT CMAKE_CROSSCOMPILING)
|
||||
enable_testing()
|
||||
add_subdirectory(tests)
|
||||
endif()
|
||||
|
|
|
|||
13287
Catch2/catch.hpp
13287
Catch2/catch.hpp
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,36 @@
|
|||
# Community made
|
||||
|
||||
## 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)
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
//! @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;
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
//! @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 */
|
||||
|
|
@ -1,10 +1,7 @@
|
|||
#include "Configuration.h"
|
||||
#include "Configuration_prusa.h"
|
||||
#include "Configuration_var.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;
|
||||
|
||||
uint16_t nPrinterType;
|
||||
PGM_P sPrinterName;
|
||||
|
|
@ -12,12 +12,21 @@ 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
|
||||
#define FW_VERSION "3.9.0"
|
||||
#define FW_COMMIT_NR 3175
|
||||
#define FW_MAJOR 3
|
||||
#define FW_MINOR 13
|
||||
#define FW_REVISION 0
|
||||
#define FW_FLAVOR ALPHA //uncomment if DEBUG, DEVEL, ALPHA, BETA or RC
|
||||
#define FW_FLAVERSION 1 //uncomment if FW_FLAVOR is defined and versioning is needed. Limited to max 8.
|
||||
#ifndef FW_FLAVOR
|
||||
#define FW_VERSION STR(FW_MAJOR) "." STR(FW_MINOR) "." STR(FW_REVISION)
|
||||
#else
|
||||
#define FW_VERSION STR(FW_MAJOR) "." STR(FW_MINOR) "." STR(FW_REVISION) "-" STR(FW_FLAVOR) "" STR(FW_FLAVERSION)
|
||||
#endif
|
||||
|
||||
#define FW_COMMIT_NR 6054
|
||||
|
||||
// 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
|
||||
|
|
@ -52,7 +61,14 @@ extern PGM_P sPrinterName;
|
|||
#undef DEBUG_BUILD
|
||||
#endif
|
||||
|
||||
#include "Configuration_prusa.h"
|
||||
#ifndef SOURCE_DATE_EPOCH
|
||||
#define SOURCE_DATE_EPOCH __DATE__
|
||||
#endif
|
||||
#ifndef SOURCE_TIME_EPOCH
|
||||
#define SOURCE_TIME_EPOCH __TIME__
|
||||
#endif
|
||||
|
||||
#include "Configuration_var.h"
|
||||
|
||||
#define FW_PRUSA3D_MAGIC "PRUSA3DFW"
|
||||
#define FW_PRUSA3D_MAGIC_LEN 10
|
||||
|
|
@ -67,9 +83,7 @@ extern PGM_P sPrinterName;
|
|||
// 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 "1.0.2"
|
||||
|
||||
#define STRING_VERSION_CONFIG_H __DATE__ " " __TIME__ // build date and time
|
||||
#define STRING_VERSION_CONFIG_H SOURCE_DATE_EPOCH " " SOURCE_TIME_EPOCH // 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.
|
||||
|
|
@ -262,7 +276,6 @@ 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:
|
||||
|
|
@ -413,18 +426,11 @@ 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)
|
||||
#define DEFAULT_ZJERK 0.4 // (mm/sec)
|
||||
#define DEFAULT_EJERK 2.5 // (mm/sec)
|
||||
#define DEFAULT_EJERK 4.5 // (mm/sec)
|
||||
|
||||
//===========================================================================
|
||||
//=============================Additional Features===========================
|
||||
|
|
@ -433,23 +439,14 @@ your extruder heater takes 2 minutes to hit the target on heating.
|
|||
// Custom M code points
|
||||
#define CUSTOM_M_CODES
|
||||
#ifdef CUSTOM_M_CODES
|
||||
#ifdef ENABLE_AUTO_BED_LEVELING
|
||||
#define CUSTOM_M_CODE_SET_Z_PROBE_OFFSET 851
|
||||
#define Z_PROBE_OFFSET_RANGE_MIN -15
|
||||
#define Z_PROBE_OFFSET_RANGE_MAX -5
|
||||
#endif
|
||||
#endif // ENABLE_AUTO_BED_LEVELING
|
||||
#endif // CUSTOM_M_CODES
|
||||
|
||||
|
||||
// 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
|
||||
|
|
@ -478,11 +475,6 @@ your extruder heater takes 2 minutes to hit the target on heating.
|
|||
// 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.
|
||||
|
|
@ -524,39 +516,14 @@ your extruder heater takes 2 minutes to hit the target on heating.
|
|||
|
||||
#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 50
|
||||
#define MIN_Z_FOR_UNLOAD 20
|
||||
#define MIN_Z_FOR_PREHEAT 10
|
||||
#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
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
#include "temperature.h"
|
||||
#include "ultralcd.h"
|
||||
#include "ConfigurationStore.h"
|
||||
#include "Configuration_prusa.h"
|
||||
#include "Configuration_var.h"
|
||||
|
||||
#ifdef MESH_BED_LEVELING
|
||||
#include "mesh_bed_leveling.h"
|
||||
|
|
@ -15,88 +15,23 @@
|
|||
#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: S=acceleration, T=retract acceleration\n%S M204 S%.2f T%.2f\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 (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"
|
||||
),
|
||||
|
|
@ -106,7 +41,7 @@ void Config_PrintSettings(uint8_t level)
|
|||
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_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,
|
||||
echomagic, echomagic, cs.acceleration, cs.retract_acceleration, cs.travel_acceleration,
|
||||
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
|
||||
|
|
@ -114,61 +49,68 @@ void Config_PrintSettings(uint8_t level)
|
|||
"%SSteps per unit:\n%S M92 X%.2f Y%.2f Z%.2f E%.2f\n"
|
||||
"%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: S=acceleration, T=retract acceleration\n%S M204 S%.2f T%.2f\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 (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_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_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,
|
||||
echomagic, echomagic, cs.acceleration, cs.retract_acceleration, cs.travel_acceleration,
|
||||
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 TEMP_MODEL
|
||||
temp_model_report_settings();
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -184,7 +126,7 @@ static_assert (false, "zprobe_zoffset was not initialized in printers in field t
|
|||
"0.0, if this is not acceptable, increment EEPROM_VERSION to force use default_conf");
|
||||
#endif
|
||||
|
||||
static_assert (sizeof(M500_conf) == 192, "sizeof(M500_conf) has changed, ensure that EEPROM_VERSION has been incremented, "
|
||||
static_assert (sizeof(M500_conf) == 209, "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.");
|
||||
|
|
@ -232,90 +174,100 @@ static const M500_conf default_conf PROGMEM =
|
|||
#else // TMC2130
|
||||
{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()
|
||||
{
|
||||
strcpy_P(cs.version, default_conf.version);
|
||||
eeprom_update_block(reinterpret_cast<uint8_t*>(&cs), reinterpret_cast<uint8_t*>(EEPROM_M500_base), sizeof(cs));
|
||||
#ifdef TEMP_MODEL
|
||||
temp_model_save_settings();
|
||||
#endif
|
||||
|
||||
SERIAL_ECHO_START;
|
||||
SERIAL_ECHOLNPGM("Settings Stored");
|
||||
}
|
||||
|
||||
|
||||
//! @brief Read M500 configuration
|
||||
//! @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.
|
||||
//! @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
|
||||
bool Config_RetrieveSettings()
|
||||
{
|
||||
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
|
||||
eeprom_read_block(reinterpret_cast<uint8_t*>(cs.version), reinterpret_cast<uint8_t*>(EEPROM_M500_base->version), sizeof(cs.version));
|
||||
// SERIAL_ECHOLN("Version: [" << ver << "] Stored version: [" << cs.version << "]");
|
||||
if (strncmp(ver,cs.version,3) == 0) // version number match
|
||||
if (strncmp_P(cs.version, default_conf.version, sizeof(EEPROM_VERSION)) == 0) // version number match
|
||||
{
|
||||
|
||||
EEPROM_readData(reinterpret_cast<uint8_t*>(EEPROM_M500_base), reinterpret_cast<uint8_t*>(&cs), sizeof(cs), "cs");
|
||||
|
||||
// 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));
|
||||
|
||||
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;
|
||||
// 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));
|
||||
|
||||
// Initialize the max_feedrate_silent and max_acceleration_units_per_sq_second_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_units_per_sq_second_silent, sizeof(EEPROM_M500_base->max_acceleration_units_per_sq_second_silent), default_conf.max_acceleration_units_per_sq_second_silent);
|
||||
|
||||
// load the CS to RAM
|
||||
eeprom_read_block(reinterpret_cast<uint8_t*>(&cs), reinterpret_cast<uint8_t*>(EEPROM_M500_base), sizeof(cs));
|
||||
calculate_extruder_multipliers();
|
||||
|
||||
//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;
|
||||
bool initialized = false;
|
||||
|
||||
for(uint8_t j = 0; j < sizeof(float); ++j)
|
||||
{
|
||||
if(0xff != reinterpret_cast<uint8_t*>(&(cs.max_feedrate_silent[i]))[j]) initialized = true;
|
||||
}
|
||||
if (!initialized) 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]));
|
||||
}
|
||||
}
|
||||
|
||||
#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;
|
||||
}
|
||||
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; }
|
||||
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]);
|
||||
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
|
||||
|
||||
reset_acceleration_rates();
|
||||
|
||||
// Call updatePID (similar to when we have processed M301)
|
||||
updatePID();
|
||||
// Call updatePID (similar to when we have processed M301)
|
||||
updatePID();
|
||||
#ifdef TEMP_MODEL
|
||||
temp_model_load_settings();
|
||||
#endif
|
||||
|
||||
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_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 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;
|
||||
}
|
||||
}
|
||||
#ifdef EEPROM_CHITCHAT
|
||||
Config_PrintSettings();
|
||||
#endif
|
||||
return previous_settings_retrieved;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
@ -323,19 +275,20 @@ 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 TEMP_MODEL
|
||||
temp_model_reset_settings();
|
||||
#endif
|
||||
|
||||
calculate_extruder_multipliers();
|
||||
calculate_extruder_multipliers();
|
||||
|
||||
SERIAL_ECHO_START;
|
||||
SERIAL_ECHOLNPGM("Hardcoded Default Settings Loaded");
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ typedef struct
|
|||
unsigned long minsegmenttime;
|
||||
float max_jerk[4]; //!< Jerk is a maximum immediate velocity change.
|
||||
float add_homing[3];
|
||||
float zprobe_zoffset;
|
||||
float zprobe_zoffset; //!< Only used with define ENABLE_AUTO_BED_LEVELING
|
||||
float Kp;
|
||||
float Ki;
|
||||
float Kd;
|
||||
|
|
@ -38,6 +38,13 @@ typedef struct
|
|||
float max_feedrate_silent[4]; //!< max speeds for silent mode
|
||||
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;
|
||||
|
|
@ -58,8 +65,4 @@ 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,16 +10,6 @@
|
|||
#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>
|
||||
|
|
@ -62,8 +52,19 @@
|
|||
// before setting a PWM value. (Does not work with software PWM for fan on Sanguinololu)
|
||||
#define FAN_KICKSTART_TIME 800
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
* bit 3 = free
|
||||
* bit 4 = free
|
||||
* bit 5 = free
|
||||
* bit 6 = free
|
||||
* bit 7 = free
|
||||
*/
|
||||
#define AUTO_REPORT
|
||||
|
||||
//===========================================================================
|
||||
//=============================Mechanical Settings===========================
|
||||
|
|
@ -152,7 +153,6 @@
|
|||
#define Z_HOME_RETRACT_MM 2
|
||||
//#define QUICK_HOME //if this is defined, if both x and y are to be homed, a diagonal move will be performed initially.
|
||||
|
||||
#define AXIS_RELATIVE_MODES {0, 0, 0, 0}
|
||||
#define MAX_STEP_FREQUENCY 40000 // Max step frequency for Ultimaker (5000 pps / half step). Toshiba steppers are 4x slower, but Prusa3D does not use those.
|
||||
//By default pololu step drivers require an active high signal. However, some high power drivers require an active low signal as step.
|
||||
#define INVERT_X_STEP_PIN 0
|
||||
|
|
@ -221,35 +221,29 @@
|
|||
* SD sorting uses static allocation (as set by SDSORT_LIMIT), allowing the
|
||||
* compiler to calculate the worst-case usage and throw an error if the SRAM
|
||||
* limit is exceeded.
|
||||
*
|
||||
* - SDSORT_USES_RAM provides faster sorting via a static directory buffer.
|
||||
* - SDSORT_USES_STACK does the same, but uses a local stack-based buffer.
|
||||
* - SDSORT_CACHE_NAMES will retain the sorted file listing in RAM. (Expensive!)
|
||||
* - SDSORT_DYNAMIC_RAM only uses RAM when the SD menu is visible. (Use with caution!)
|
||||
*/
|
||||
#define SDCARD_SORT_ALPHA //Alphabetical sorting of SD files menu
|
||||
|
||||
// SD Card Sorting options
|
||||
// In current firmware Prusa Firmware version,
|
||||
// SDSORT_CACHE_NAMES and SDSORT_DYNAMIC_RAM is not supported and must be set to 0.
|
||||
#ifdef SDCARD_SORT_ALPHA
|
||||
#define SD_SORT_TIME 0
|
||||
#define SD_SORT_ALPHA 1
|
||||
#define SD_SORT_NONE 2
|
||||
#define INSERTSORT
|
||||
// #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
|
||||
#define SDSORT_GCODE 0 // Allow turning sorting on/off with LCD and M34 g-code.
|
||||
#define SDSORT_USES_RAM 0 // Pre-allocate a static array for faster pre-sorting.
|
||||
#define SDSORT_USES_STACK 0 // Prefer the stack for pre-sorting to give back some SRAM. (Negated by next 2 options.)
|
||||
#define SDSORT_CACHE_NAMES 0 // Keep sorted items in RAM longer for speedy performance. Most expensive option.
|
||||
#define SDSORT_DYNAMIC_RAM 0 // Use dynamic allocation (within SD menus). Least expensive option. Set SDSORT_LIMIT before use!
|
||||
#endif
|
||||
|
||||
#if defined(SDCARD_SORT_ALPHA)
|
||||
#define HAS_FOLDER_SORTING (FOLDER_SORTING || SDSORT_GCODE)
|
||||
#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
|
||||
|
||||
|
|
@ -286,16 +280,17 @@
|
|||
#define LIN_ADVANCE
|
||||
|
||||
#ifdef LIN_ADVANCE
|
||||
#define LIN_ADVANCE_K 0 // Unit: mm compression per 1mm/s extruder speed
|
||||
//#define LA_NOCOMPAT // Disable Linear Advance 1.0 compatibility
|
||||
//#define LA_LIVE_K // Allow adjusting K in the Tune menu
|
||||
//#define LA_DEBUG // If enabled, this will generate debug information output over USB.
|
||||
//#define LA_DEBUG_LOGIC // @wavexx: setup logic channels for isr debugging
|
||||
#define LA_K_DEF 0 // Default K factor (Unit: mm compression per 1mm/s extruder speed)
|
||||
#define LA_K_MAX 10 // Maximum acceptable K factor (exclusive, see notes in planner.cpp:plan_buffer_line)
|
||||
#define LA_LA10_MIN LA_K_MAX // Lin. Advance 1.0 threshold value (inclusive)
|
||||
//#define LA_FLOWADJ // Adjust LA along with flow/M221 for uniform width
|
||||
//#define LA_NOCOMPAT // Disable Linear Advance 1.0 compatibility
|
||||
//#define LA_LIVE_K // Allow adjusting K in the Tune menu
|
||||
//#define LA_DEBUG // If enabled, this will generate debug information output over USB.
|
||||
//#define LA_DEBUG_LOGIC // @wavexx: setup logic channels for isr debugging
|
||||
#endif
|
||||
|
||||
// Arc interpretation settings:
|
||||
#define MM_PER_ARC_SEGMENT 1
|
||||
#define N_ARC_CORRECTION 25
|
||||
// Arc interpretation settings : Moved to the variant files.
|
||||
|
||||
const unsigned int dropsegments=5; //everything with less than this number of steps will be ignored as move and joined with the next movement
|
||||
|
||||
|
|
@ -325,6 +320,11 @@ const unsigned int dropsegments=5; //everything with less than this number of st
|
|||
// Control heater 0 and heater 1 in parallel.
|
||||
//#define HEATERS_PARALLEL
|
||||
|
||||
//LCD status clock interval timer to switch between
|
||||
// remaining print time
|
||||
// and time to change/pause/interaction
|
||||
#define CLOCK_INTERVAL_TIME 5
|
||||
|
||||
//===========================================================================
|
||||
//=============================Buffers ============================
|
||||
//===========================================================================
|
||||
|
|
@ -346,6 +346,62 @@ 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
|
||||
|
||||
/**
|
||||
* Advanced Pause for Filament Change
|
||||
* - Adds the G-code M600 Filament Change to initiate a filament change.
|
||||
* - This feature is required for the default FILAMENT_RUNOUT_SCRIPT.
|
||||
*
|
||||
* Requirements:
|
||||
* - For Filament Change parking enable and configure NOZZLE_PARK_FEATURE.
|
||||
* - For user interaction enable an LCD display, HOST_PROMPT_SUPPORT, or EMERGENCY_PARSER.
|
||||
*
|
||||
* Enable PARK_HEAD_ON_PAUSE to add the G-code M125 Pause and Park.
|
||||
*/
|
||||
|
||||
#define PAUSE_PARK_RETRACT_FEEDRATE 60 // (mm/s) Initial retract feedrate.
|
||||
#define PAUSE_PARK_RETRACT_LENGTH 2 // (mm) Initial retract.
|
||||
// This short retract is done immediately, before parking the nozzle.
|
||||
#define FILAMENT_CHANGE_UNLOAD_FEEDRATE 10 // (mm/s) Unload filament feedrate. This can be pretty fast.
|
||||
#define FILAMENT_CHANGE_UNLOAD_ACCEL 25 // (mm/s^2) Lower acceleration may allow a faster feedrate.
|
||||
#define FILAMENT_CHANGE_UNLOAD_LENGTH 100 // (mm) The length of filament for a complete unload.
|
||||
// For Bowden, the full length of the tube and nozzle.
|
||||
// For direct drive, the full length of the nozzle.
|
||||
// Set to 0 for manual unloading.
|
||||
#define FILAMENT_CHANGE_SLOW_LOAD_FEEDRATE 6 // (mm/s) Slow move when starting load.
|
||||
#define FILAMENT_CHANGE_SLOW_LOAD_LENGTH 0 // (mm) Slow length, to allow time to insert material.
|
||||
// 0 to disable start loading and skip to fast load only
|
||||
#define FILAMENT_CHANGE_FAST_LOAD_FEEDRATE 6 // (mm/s) Load filament feedrate. This can be pretty fast.
|
||||
#define FILAMENT_CHANGE_FAST_LOAD_ACCEL 25 // (mm/s^2) Lower acceleration may allow a faster feedrate.
|
||||
#define FILAMENT_CHANGE_FAST_LOAD_LENGTH 0 // (mm) Load length of filament, from extruder gear to nozzle.
|
||||
// For Bowden, the full length of the tube and nozzle.
|
||||
// For direct drive, the full length of the nozzle.
|
||||
//#define ADVANCED_PAUSE_CONTINUOUS_PURGE // Purge continuously up to the purge length until interrupted.
|
||||
#define ADVANCED_PAUSE_PURGE_FEEDRATE 3 // (mm/s) Extrude feedrate (after loading). Should be slower than load feedrate.
|
||||
#define ADVANCED_PAUSE_PURGE_LENGTH 50 // (mm) Length to extrude after loading.
|
||||
// Set to 0 for manual extrusion.
|
||||
// Filament can be extruded repeatedly from the Filament Change menu
|
||||
// until extrusion is consistent, and to purge old filament.
|
||||
#define ADVANCED_PAUSE_RESUME_PRIME 0 // (mm) Extra distance to prime nozzle after returning from park.
|
||||
//#define ADVANCED_PAUSE_FANS_PAUSE // Turn off print-cooling fans while the machine is paused.
|
||||
|
||||
// Filament Unload does a Retract, Delay, and Purge first:
|
||||
#define FILAMENT_UNLOAD_PURGE_RETRACT 13 // (mm) Unload initial retract length.
|
||||
#define FILAMENT_UNLOAD_PURGE_DELAY 5000 // (ms) Delay for the filament to cool after retract.
|
||||
#define FILAMENT_UNLOAD_PURGE_LENGTH 8 // (mm) An unretract is done, then this length is purged.
|
||||
#define FILAMENT_UNLOAD_PURGE_FEEDRATE 25 // (mm/s) feedrate to purge before unload
|
||||
|
||||
#define PAUSE_PARK_NOZZLE_TIMEOUT 45 // (seconds) Time limit before the nozzle is turned off for safety.
|
||||
#define FILAMENT_CHANGE_ALERT_BEEPS 10 // Number of alert beeps to play when a response is needed.
|
||||
#define PAUSE_PARK_NO_STEPPER_TIMEOUT // Enable for XYZ steppers to stay powered on during filament change.
|
||||
//#define FILAMENT_CHANGE_RESUME_ON_INSERT // Automatically continue / load filament when runout sensor is triggered again.
|
||||
//#define PAUSE_REHEAT_FAST_RESUME // Reduce number of waits by not prompting again post-timeout before continuing.
|
||||
|
||||
//#define PARK_HEAD_ON_PAUSE // Park the nozzle during pause and filament change.
|
||||
//#define HOME_BEFORE_FILAMENT_CHANGE // If needed, home before parking for filament change
|
||||
|
||||
//#define FILAMENT_LOAD_UNLOAD_GCODES // Add M701/M702 Load/Unload G-codes, plus Load/Unload in the LCD Prepare menu.
|
||||
//#define FILAMENT_UNLOAD_ALL_EXTRUDERS // Allow M702 to unload all extruders above a minimum target temp (as set by M302)
|
||||
|
||||
|
||||
// Firmware based and LCD controlled retract
|
||||
// M207 and M208 can be used to define parameters for the retraction.
|
||||
|
|
@ -374,6 +430,17 @@ const unsigned int dropsegments=5; //everything with less than this number of st
|
|||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Include capabilities in M115 output
|
||||
*/
|
||||
#define EXTENDED_CAPABILITIES_REPORT
|
||||
|
||||
/**
|
||||
* Enable M120/M121 G-code commands
|
||||
*
|
||||
*/
|
||||
//#define M120_M121_ENABLED //Be careful enabling and using these G-code commands.
|
||||
|
||||
//===========================================================================
|
||||
//============================= Define Defines ============================
|
||||
//===========================================================================
|
||||
|
|
@ -435,6 +502,10 @@ const unsigned int dropsegments=5; //everything with less than this number of st
|
|||
#undef BED_MINTEMP
|
||||
#undef BED_MAXTEMP
|
||||
#endif
|
||||
#if TEMP_SENSOR_AMBIENT == 0
|
||||
#undef AMBIENT_MINTEMP
|
||||
#undef AMBIENT_MAXTEMP
|
||||
#endif
|
||||
|
||||
|
||||
#endif //__CONFIGURATION_ADV_H
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
// 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
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
#include "Marlin.h"
|
||||
#include "Dcodes.h"
|
||||
//#include "Marlin.h"
|
||||
#include "Configuration.h"
|
||||
#include "language.h"
|
||||
#include "cmdqueue.h"
|
||||
#include <stdio.h>
|
||||
|
|
@ -22,31 +23,28 @@ void print_hex_byte(uint8_t val)
|
|||
print_hex_nibble(val & 15);
|
||||
}
|
||||
|
||||
void print_hex_word(uint16_t val)
|
||||
// debug range address type (fits all SRAM/PROGMEM/XFLASH memory ranges)
|
||||
#if defined(DEBUG_DCODE6) || defined(DEBUG_DCODES) || defined(XFLASH_DUMP)
|
||||
#include "xflash.h"
|
||||
#include "xflash_layout.h"
|
||||
|
||||
#define DADDR_SIZE 32
|
||||
typedef uint32_t daddr_t; // XFLASH requires 24 bits
|
||||
#else
|
||||
#define DADDR_SIZE 16
|
||||
typedef uint16_t daddr_t;
|
||||
#endif
|
||||
|
||||
void print_hex_word(daddr_t val)
|
||||
{
|
||||
print_hex_byte(val >> 8);
|
||||
print_hex_byte(val & 255);
|
||||
#if DADDR_SIZE > 16
|
||||
print_hex_byte((val >> 16) & 0xFF);
|
||||
#endif
|
||||
print_hex_byte((val >> 8) & 0xFF);
|
||||
print_hex_byte(val & 0xFF);
|
||||
}
|
||||
|
||||
void print_eeprom(uint16_t address, uint16_t count, uint8_t countperline = 16)
|
||||
{
|
||||
while (count)
|
||||
{
|
||||
print_hex_word(address);
|
||||
putchar(' ');
|
||||
uint8_t count_line = countperline;
|
||||
while (count && count_line)
|
||||
{
|
||||
putchar(' ');
|
||||
print_hex_byte(eeprom_read_byte((uint8_t*)address++));
|
||||
count_line--;
|
||||
count--;
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
|
||||
int parse_hex(char* hex, uint8_t* data, int count)
|
||||
int parse_hex(const char* hex, uint8_t* data, int count)
|
||||
{
|
||||
int parsed = 0;
|
||||
while (*hex)
|
||||
|
|
@ -70,12 +68,16 @@ int parse_hex(char* hex, uint8_t* data, int count)
|
|||
}
|
||||
|
||||
|
||||
void print_mem(uint32_t address, uint16_t count, uint8_t type, uint8_t countperline = 16)
|
||||
enum class dcode_mem_t:uint8_t { sram, eeprom, progmem, xflash };
|
||||
|
||||
void print_mem(daddr_t address, daddr_t count, dcode_mem_t type, uint8_t countperline = 16)
|
||||
{
|
||||
#if defined(DEBUG_DCODE6) || defined(DEBUG_DCODES) || defined(XFLASH_DUMP)
|
||||
if(type == dcode_mem_t::xflash)
|
||||
XFLASH_SPI_ENTER();
|
||||
#endif
|
||||
while (count)
|
||||
{
|
||||
if (type == 2)
|
||||
print_hex_nibble(address >> 16);
|
||||
print_hex_word(address);
|
||||
putchar(' ');
|
||||
uint8_t count_line = countperline;
|
||||
|
|
@ -84,75 +86,98 @@ void print_mem(uint32_t address, uint16_t count, uint8_t type, uint8_t countperl
|
|||
uint8_t data = 0;
|
||||
switch (type)
|
||||
{
|
||||
case 0: data = *((uint8_t*)address++); break;
|
||||
case 1: data = eeprom_read_byte((uint8_t*)address++); break;
|
||||
case 2: data = pgm_read_byte_far((uint8_t*)address++); break;
|
||||
case dcode_mem_t::sram: data = *((uint8_t*)address); break;
|
||||
case dcode_mem_t::eeprom: data = eeprom_read_byte((uint8_t*)address); break;
|
||||
case dcode_mem_t::progmem: break;
|
||||
#if defined(DEBUG_DCODE6) || defined(DEBUG_DCODES) || defined(XFLASH_DUMP)
|
||||
case dcode_mem_t::xflash: xflash_rd_data(address, &data, 1); break;
|
||||
#else
|
||||
case dcode_mem_t::xflash: break;
|
||||
#endif
|
||||
}
|
||||
++address;
|
||||
putchar(' ');
|
||||
print_hex_byte(data);
|
||||
count_line--;
|
||||
count--;
|
||||
|
||||
// sporadically call manage_heater, but only when interrupts are enabled (meaning
|
||||
// print_mem is called by D2). Don't do anything otherwise: we are inside a crash
|
||||
// handler where memory & stack needs to be preserved!
|
||||
if((SREG & (1 << SREG_I)) && !((uint16_t)count % 8192))
|
||||
manage_heater();
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_DCODE3
|
||||
// TODO: this only handles SRAM/EEPROM 16bit addresses
|
||||
void write_mem(uint16_t address, uint16_t count, const uint8_t* data, const dcode_mem_t type)
|
||||
{
|
||||
for (uint16_t i = 0; i < count; i++)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case dcode_mem_t::sram: *((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;
|
||||
}
|
||||
++address;
|
||||
}
|
||||
}
|
||||
|
||||
void dcode_core(daddr_t addr_start, const daddr_t addr_end, const dcode_mem_t type,
|
||||
uint8_t dcode, const char* type_desc)
|
||||
{
|
||||
KEEPALIVE_STATE(NOT_BUSY);
|
||||
DBG(_N("D%d - Read/Write %S\n"), dcode, type_desc);
|
||||
daddr_t count = -1; // RW the entire space by default
|
||||
if (code_seen('A'))
|
||||
addr_start = (strchr_pointer[1] == 'x')?strtol(strchr_pointer + 2, 0, 16):(int)code_value();
|
||||
if (code_seen('C'))
|
||||
count = code_value_long();
|
||||
if (addr_start > addr_end)
|
||||
addr_start = addr_end;
|
||||
if ((addr_start + count) > addr_end || (addr_start + count) < addr_start)
|
||||
count = addr_end - addr_start;
|
||||
if (code_seen('X'))
|
||||
{
|
||||
uint8_t data[16];
|
||||
count = parse_hex(strchr_pointer + 1, data, 16);
|
||||
write_mem(addr_start, count, data, type);
|
||||
#if DADDR_SIZE > 16
|
||||
DBG(_N("%lu bytes written to %S at address 0x%04lx\n"), count, type_desc, addr_start);
|
||||
#else
|
||||
DBG(_N("%u bytes written to %S at address 0x%08x\n"), count, type_desc, addr_start);
|
||||
#endif
|
||||
}
|
||||
print_mem(addr_start, count, type);
|
||||
}
|
||||
|
||||
#if defined DEBUG_DCODE3 || defined DEBUG_DCODES
|
||||
#define EEPROM_SIZE 0x1000
|
||||
/*!
|
||||
*
|
||||
### 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.
|
||||
|
||||
D3 [ A | C | X ]
|
||||
|
||||
- `A` - Address (0x0000-0x0fff)
|
||||
- `C` - Count (0x0001-0x1000)
|
||||
- `X` - Data
|
||||
*
|
||||
#### 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
|
||||
- The hex data needs to be lowercase
|
||||
|
||||
*/
|
||||
void dcode_3()
|
||||
{
|
||||
DBG(_N("D3 - Read/Write EEPROM\n"));
|
||||
uint16_t address = 0x0000; //default 0x0000
|
||||
uint16_t count = EEPROM_SIZE; //default 0x1000 (entire eeprom)
|
||||
if (code_seen('A')) // Address (0x0000-0x0fff)
|
||||
address = (strchr_pointer[1] == 'x')?strtol(strchr_pointer + 2, 0, 16):(int)code_value();
|
||||
if (code_seen('C')) // Count (0x0001-0x1000)
|
||||
count = (int)code_value();
|
||||
address &= 0x1fff;
|
||||
if (count > EEPROM_SIZE) count = EEPROM_SIZE;
|
||||
if ((address + count) > EEPROM_SIZE) count = EEPROM_SIZE - address;
|
||||
if (code_seen('X')) // Data
|
||||
{
|
||||
uint8_t data[16];
|
||||
count = parse_hex(strchr_pointer + 1, data, 16);
|
||||
if (count > 0)
|
||||
{
|
||||
for (uint16_t i = 0; i < count; i++)
|
||||
eeprom_write_byte((uint8_t*)(address + i), data[i]);
|
||||
printf_P(_N("%d bytes written to EEPROM at address 0x%04x"), count, address);
|
||||
putchar('\n');
|
||||
}
|
||||
else
|
||||
count = 0;
|
||||
}
|
||||
print_mem(address, count, 1);
|
||||
/* while (count)
|
||||
{
|
||||
print_hex_word(address);
|
||||
putchar(' ');
|
||||
uint8_t countperline = 16;
|
||||
while (count && countperline)
|
||||
{
|
||||
uint8_t data = eeprom_read_byte((uint8_t*)address++);
|
||||
putchar(' ');
|
||||
print_hex_byte(data);
|
||||
countperline--;
|
||||
count--;
|
||||
}
|
||||
putchar('\n');
|
||||
}*/
|
||||
dcode_core(0, EEPROM_SIZE, dcode_mem_t::eeprom, 3, _N("EEPROM"));
|
||||
}
|
||||
#endif //DEBUG_DCODE3
|
||||
|
||||
|
|
@ -166,20 +191,6 @@ void dcode_3()
|
|||
#include "bootapp.h"
|
||||
|
||||
#if 0
|
||||
#define FLASHSIZE 0x40000
|
||||
|
||||
#define RAMSIZE 0x2000
|
||||
#define boot_src_addr (*((uint32_t*)(RAMSIZE - 16)))
|
||||
#define boot_dst_addr (*((uint32_t*)(RAMSIZE - 12)))
|
||||
#define boot_copy_size (*((uint16_t*)(RAMSIZE - 8)))
|
||||
#define boot_reserved (*((uint8_t*)(RAMSIZE - 6)))
|
||||
#define boot_app_flags (*((uint8_t*)(RAMSIZE - 5)))
|
||||
#define boot_app_magic (*((uint32_t*)(RAMSIZE - 4)))
|
||||
#define BOOT_APP_FLG_ERASE 0x01
|
||||
#define BOOT_APP_FLG_COPY 0x02
|
||||
#define BOOT_APP_FLG_FLASH 0x04
|
||||
|
||||
extern uint8_t fsensor_log;
|
||||
extern float current_temperature_pinda;
|
||||
extern float axis_steps_per_unit[NUM_AXIS];
|
||||
|
||||
|
|
@ -198,7 +209,7 @@ extern float axis_steps_per_unit[NUM_AXIS];
|
|||
*/
|
||||
void dcode__1()
|
||||
{
|
||||
printf_P(PSTR("D-1 - Endless loop\n"));
|
||||
DBG(_N("D-1 - Endless loop\n"));
|
||||
// cli();
|
||||
while (1);
|
||||
}
|
||||
|
|
@ -206,13 +217,13 @@ void dcode__1()
|
|||
#ifdef DEBUG_DCODES
|
||||
|
||||
/*!
|
||||
*
|
||||
### D0 - Reset <a href="https://reprap.org/wiki/G-code#D0:_Reset">D0: Reset</a>
|
||||
|
||||
D0 [ B ]
|
||||
|
||||
- `B` - Bootloader
|
||||
*
|
||||
#### Usage
|
||||
|
||||
D0 [ B ]
|
||||
|
||||
#### Parameters
|
||||
- `B` - Bootloader
|
||||
*/
|
||||
void dcode_0()
|
||||
{
|
||||
|
|
@ -220,9 +231,7 @@ void dcode_0()
|
|||
LOG("D0 - Reset\n");
|
||||
if (code_seen('B')) //bootloader
|
||||
{
|
||||
cli();
|
||||
wdt_enable(WDTO_15MS);
|
||||
while(1);
|
||||
softReset();
|
||||
}
|
||||
else //reset
|
||||
{
|
||||
|
|
@ -246,77 +255,48 @@ void dcode_1()
|
|||
cli();
|
||||
for (int i = 0; i < 8192; i++)
|
||||
eeprom_write_byte((unsigned char*)i, (unsigned char)0xff);
|
||||
wdt_enable(WDTO_15MS);
|
||||
while(1);
|
||||
softReset();
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined DEBUG_DCODE2 || defined DEBUG_DCODES
|
||||
/*!
|
||||
*
|
||||
### D2 - Read/Write RAM <a href="https://reprap.org/wiki/G-code#D2:_Read.2FWrite_RAM">D3: Read/Write RAM</a>
|
||||
This command can be used without any additional parameters. It will read the entire RAM.
|
||||
|
||||
D3 [ A | C | X ]
|
||||
|
||||
- `A` - Address (0x0000-0x1fff)
|
||||
- `C` - Count (0x0001-0x2000)
|
||||
- `X` - Data
|
||||
*
|
||||
#### Usage
|
||||
|
||||
D2 [ A | C | X ]
|
||||
|
||||
#### Parameters
|
||||
- `A` - Address (x0000-x21ff)
|
||||
- `C` - Count (1-8704)
|
||||
- `X` - Data
|
||||
|
||||
#### Notes
|
||||
- The hex address needs to be lowercase without the 0 before the x
|
||||
- Count is decimal
|
||||
- The hex data needs to be lowercase
|
||||
|
||||
*/
|
||||
void dcode_2()
|
||||
{
|
||||
LOG("D2 - Read/Write RAM\n");
|
||||
uint16_t address = 0x0000; //default 0x0000
|
||||
uint16_t count = 0x2000; //default 0x2000 (entire ram)
|
||||
if (code_seen('A')) // Address (0x0000-0x1fff)
|
||||
address = (strchr_pointer[1] == 'x')?strtol(strchr_pointer + 2, 0, 16):(int)code_value();
|
||||
if (code_seen('C')) // Count (0x0001-0x2000)
|
||||
count = (int)code_value();
|
||||
address &= 0x1fff;
|
||||
if (count > 0x2000) count = 0x2000;
|
||||
if ((address + count) > 0x2000) count = 0x2000 - address;
|
||||
if (code_seen('X')) // Data
|
||||
{
|
||||
uint8_t data[16];
|
||||
count = parse_hex(strchr_pointer + 1, data, 16);
|
||||
if (count > 0)
|
||||
{
|
||||
for (uint16_t i = 0; i < count; i++)
|
||||
*((uint8_t*)(address + i)) = data[i];
|
||||
LOG("%d bytes written to RAM at address %04x", count, address);
|
||||
}
|
||||
else
|
||||
count = 0;
|
||||
}
|
||||
print_mem(address, count, 0);
|
||||
/* while (count)
|
||||
{
|
||||
print_hex_word(address);
|
||||
putchar(' ');
|
||||
uint8_t countperline = 16;
|
||||
while (count && countperline)
|
||||
{
|
||||
uint8_t data = *((uint8_t*)address++);
|
||||
putchar(' ');
|
||||
print_hex_byte(data);
|
||||
countperline--;
|
||||
count--;
|
||||
}
|
||||
putchar('\n');
|
||||
}*/
|
||||
dcode_core(RAMSTART, RAMEND+1, dcode_mem_t::sram, 2, _N("SRAM"));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_DCODES
|
||||
/*!
|
||||
*
|
||||
### D4 - Read/Write PIN <a href="https://reprap.org/wiki/G-code#D4:_Read.2FWrite_PIN">D4: Read/Write PIN</a>
|
||||
|
||||
### 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.
|
||||
|
||||
D4 [ P | F | V ]
|
||||
|
||||
- `P` - Pin (0-255)
|
||||
- `F` - Function in/out (0/1)
|
||||
- `V` - Value (0/1)
|
||||
*
|
||||
#### Usage
|
||||
|
||||
D4 [ P | F | V ]
|
||||
|
||||
#### Parameters
|
||||
- `P` - Pin (0-255)
|
||||
- `F` - Function in/out (0/1)
|
||||
- `V` - Value (0/1)
|
||||
*/
|
||||
void dcode_4()
|
||||
{
|
||||
|
|
@ -348,24 +328,30 @@ void dcode_4()
|
|||
}
|
||||
#endif //DEBUG_DCODES
|
||||
|
||||
#ifdef DEBUG_DCODE5
|
||||
#if defined DEBUG_DCODE5 || defined DEBUG_DCODES
|
||||
|
||||
/*!
|
||||
*
|
||||
### 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.
|
||||
|
||||
D3 [ A | C | X | E ]
|
||||
|
||||
- `A` - Address (0x00000-0x3ffff)
|
||||
- `C` - Count (0x0001-0x2000)
|
||||
- `X` - Data
|
||||
- `E` - Erase
|
||||
*
|
||||
*/
|
||||
#### 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
|
||||
- The hex data needs to be lowercase
|
||||
|
||||
*/
|
||||
void dcode_5()
|
||||
{
|
||||
printf_P(PSTR("D5 - Read/Write FLASH\n"));
|
||||
puts_P(PSTR("D5 - Read/Write FLASH"));
|
||||
uint32_t address = 0x0000; //default 0x0000
|
||||
uint16_t count = 0x0400; //default 0x0400 (1kb block)
|
||||
if (code_seen('A')) // Address (0x00000-0x3ffff)
|
||||
|
|
@ -402,8 +388,7 @@ void dcode_5()
|
|||
boot_dst_addr = (uint32_t)address;
|
||||
boot_src_addr = (uint32_t)(&data);
|
||||
bootapp_print_vars();
|
||||
wdt_enable(WDTO_15MS);
|
||||
while(1);
|
||||
softReset();
|
||||
}
|
||||
while (count)
|
||||
{
|
||||
|
|
@ -424,27 +409,36 @@ void dcode_5()
|
|||
}
|
||||
#endif //DEBUG_DCODE5
|
||||
|
||||
#ifdef DEBUG_DCODES
|
||||
|
||||
#if defined(XFLASH) && (defined DEBUG_DCODE6 || defined DEBUG_DCODES)
|
||||
/*!
|
||||
*
|
||||
### D6 - Read/Write external FLASH <a href="https://reprap.org/wiki/G-code#D6:_Read.2FWrite_external_FLASH">D6: Read/Write external Flash</a>
|
||||
|
||||
Reserved
|
||||
*
|
||||
*/
|
||||
This command can be used without any additional parameters. It will read the entire XFLASH.
|
||||
#### Usage
|
||||
|
||||
D6 [ A | C | X ]
|
||||
|
||||
#### Parameters
|
||||
- `A` - Address (x0000-x3ffff)
|
||||
- `C` - Count (1-262144)
|
||||
- `X` - Data
|
||||
|
||||
#### Notes
|
||||
- The hex address needs to be lowercase without the 0 before the x
|
||||
- Count is decimal
|
||||
- The hex data needs to be lowercase
|
||||
- Writing is currently not implemented
|
||||
*/
|
||||
void dcode_6()
|
||||
{
|
||||
LOG("D6 - Read/Write external FLASH\n");
|
||||
dcode_core(0x0, XFLASH_SIZE, dcode_mem_t::xflash, 6, _N("XFLASH"));
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_DCODES
|
||||
/*!
|
||||
*
|
||||
### D7 - Read/Write Bootloader <a href="https://reprap.org/wiki/G-code#D7:_Read.2FWrite_Bootloader">D7: Read/Write Bootloader</a>
|
||||
|
||||
Reserved
|
||||
*
|
||||
*/
|
||||
*/
|
||||
void dcode_7()
|
||||
{
|
||||
LOG("D7 - Read/Write Bootloader\n");
|
||||
|
|
@ -455,26 +449,25 @@ void dcode_7()
|
|||
boot_copy_size = (uint16_t)0xc00;
|
||||
boot_src_addr = (uint32_t)0x0003e400;
|
||||
boot_dst_addr = (uint32_t)0x0003f400;
|
||||
wdt_enable(WDTO_15MS);
|
||||
while(1);
|
||||
softReset();
|
||||
*/
|
||||
}
|
||||
|
||||
/*!
|
||||
*
|
||||
### D8 - Read/Write PINDA <a href="https://reprap.org/wiki/G-code#D8:_Read.2FWrite_PINDA">D8: Read/Write PINDA</a>
|
||||
|
||||
D8 [ ? | ! | P | Z ]
|
||||
|
||||
- `?` - Read PINDA temperature shift values
|
||||
- `!` - Reset PINDA temperature shift values to default
|
||||
- `P` - Pinda temperature [C]
|
||||
- `Z` - Z Offset [mm]
|
||||
*
|
||||
#### Usage
|
||||
|
||||
D8 [ ? | ! | P | Z ]
|
||||
|
||||
#### Parameters
|
||||
- `?` - Read PINDA temperature shift values
|
||||
- `!` - Reset PINDA temperature shift values to default
|
||||
- `P` - Pinda temperature [C]
|
||||
- `Z` - Z Offset [mm]
|
||||
*/
|
||||
void dcode_8()
|
||||
{
|
||||
printf_P(PSTR("D8 - Read/Write PINDA\n"));
|
||||
puts_P(PSTR("D8 - Read/Write PINDA"));
|
||||
uint8_t cal_status = calibration_status_pinda();
|
||||
float temp_pinda = current_temperature_pinda;
|
||||
float offset_z = temp_compensation_pinda_thermistor_offset(temp_pinda);
|
||||
|
|
@ -514,21 +507,21 @@ void dcode_8()
|
|||
}
|
||||
|
||||
/*!
|
||||
*
|
||||
### D9 - Read ADC <a href="https://reprap.org/wiki/G-code#D9:_Read.2FWrite_ADC">D9: Read ADC</a>
|
||||
|
||||
D9 [ I | V ]
|
||||
|
||||
- `I` - ADC channel index
|
||||
- `0` - Heater 0 temperature
|
||||
- `1` - Heater 1 temperature
|
||||
- `2` - Bed temperature
|
||||
- `3` - PINDA temperature
|
||||
- `4` - PWR voltage
|
||||
- `5` - Ambient temperature
|
||||
- `6` - BED voltage
|
||||
- `V` Value to be written as simulated
|
||||
*
|
||||
#### Usage
|
||||
|
||||
D9 [ I | V ]
|
||||
|
||||
#### Parameters
|
||||
- `I` - ADC channel index
|
||||
- `0` - Heater 0 temperature
|
||||
- `1` - Heater 1 temperature
|
||||
- `2` - Bed temperature
|
||||
- `3` - PINDA temperature
|
||||
- `4` - PWR voltage
|
||||
- `5` - Ambient temperature
|
||||
- `6` - BED voltage
|
||||
- `V` Value to be written as simulated
|
||||
*/
|
||||
const char* dcode_9_ADC_name(uint8_t i)
|
||||
{
|
||||
|
|
@ -545,26 +538,20 @@ const char* dcode_9_ADC_name(uint8_t i)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef AMBIENT_THERMISTOR
|
||||
extern int current_temperature_raw_ambient;
|
||||
#endif //AMBIENT_THERMISTOR
|
||||
|
||||
#ifdef VOLT_PWR_PIN
|
||||
extern int current_voltage_raw_pwr;
|
||||
#endif //VOLT_PWR_PIN
|
||||
|
||||
#ifdef VOLT_BED_PIN
|
||||
extern int current_voltage_raw_bed;
|
||||
#endif //VOLT_BED_PIN
|
||||
|
||||
uint16_t dcode_9_ADC_val(uint8_t i)
|
||||
{
|
||||
switch (i)
|
||||
{
|
||||
#ifdef SHOW_TEMP_ADC_VALUES
|
||||
case 0: return current_temperature_raw[0];
|
||||
#endif //SHOW_TEMP_ADC_VALUES
|
||||
case 1: return 0;
|
||||
#ifdef SHOW_TEMP_ADC_VALUES
|
||||
case 2: return current_temperature_bed_raw;
|
||||
#endif //SHOW_TEMP_ADC_VALUES
|
||||
#ifdef PINDA_THERMISTOR
|
||||
case 3: return current_temperature_raw_pinda;
|
||||
#endif //PINDA_THERMISTOR
|
||||
#ifdef VOLT_PWR_PIN
|
||||
case 4: return current_voltage_raw_pwr;
|
||||
#endif //VOLT_PWR_PIN
|
||||
|
|
@ -580,12 +567,13 @@ uint16_t dcode_9_ADC_val(uint8_t i)
|
|||
|
||||
void dcode_9()
|
||||
{
|
||||
printf_P(PSTR("D9 - Read/Write ADC\n"));
|
||||
puts_P(PSTR("D9 - Read/Write ADC"));
|
||||
if ((strchr_pointer[1+1] == '?') || (strchr_pointer[1+1] == 0))
|
||||
{
|
||||
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;
|
||||
|
|
@ -596,77 +584,189 @@ void dcode_9()
|
|||
if (code_seen('V')) // value to be written as simulated
|
||||
{
|
||||
adc_sim_mask |= (1 << index);
|
||||
adc_values[index] = (((int)code_value()) << 4);
|
||||
adc_values[index] = ((uint16_t)code_value_short() << 4);
|
||||
printf_P(PSTR("ADC%d=%4d\n"), index, adc_values[index] >> 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/*!
|
||||
*
|
||||
### D10 - Set XYZ calibration = OK <a href="https://reprap.org/wiki/G-code#D10:_Set_XYZ_calibration_.3D_OK">D10: Set XYZ calibration = OK</a>
|
||||
|
||||
*
|
||||
*/
|
||||
*/
|
||||
void dcode_10()
|
||||
{//Tell the printer that XYZ calibration went OK
|
||||
LOG("D10 - XYZ calibration = OK\n");
|
||||
calibration_status_store(CALIBRATION_STATUS_LIVE_ADJUST);
|
||||
calibration_status_set(CALIBRATION_STATUS_XYZ);
|
||||
}
|
||||
|
||||
/*!
|
||||
*
|
||||
### D12 - Time <a href="https://reprap.org/wiki/G-code#D12:_Time">D12: Time</a>
|
||||
|
||||
*
|
||||
*/
|
||||
Writes the current time in the log file.
|
||||
*/
|
||||
|
||||
void dcode_12()
|
||||
{//Time
|
||||
LOG("D12 - Time\n");
|
||||
|
||||
}
|
||||
|
||||
#ifdef HEATBED_ANALYSIS
|
||||
/*!
|
||||
### 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)
|
||||
- `G` - Points X (default 40)
|
||||
- `H` - Points Y (default 40)
|
||||
- `I` - Offset X (default 74)
|
||||
- `J` - Offset Y (default 34)
|
||||
*/
|
||||
void dcode_80()
|
||||
{
|
||||
float dimension_x = 40;
|
||||
float dimension_y = 40;
|
||||
int points_x = 40;
|
||||
int points_y = 40;
|
||||
float offset_x = 74;
|
||||
float offset_y = 33;
|
||||
|
||||
if (code_seen('E')) dimension_x = code_value();
|
||||
if (code_seen('F')) dimension_y = code_value();
|
||||
if (code_seen('G')) {points_x = code_value(); }
|
||||
if (code_seen('H')) {points_y = code_value(); }
|
||||
if (code_seen('I')) {offset_x = code_value(); }
|
||||
if (code_seen('J')) {offset_y = code_value(); }
|
||||
printf_P(PSTR("DIM X: %f\n"), dimension_x);
|
||||
printf_P(PSTR("DIM Y: %f\n"), dimension_y);
|
||||
printf_P(PSTR("POINTS X: %d\n"), points_x);
|
||||
printf_P(PSTR("POINTS Y: %d\n"), points_y);
|
||||
printf_P(PSTR("OFFSET X: %f\n"), offset_x);
|
||||
printf_P(PSTR("OFFSET Y: %f\n"), offset_y);
|
||||
bed_check(dimension_x,dimension_y,points_x,points_y,offset_x,offset_y);
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
### 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)
|
||||
- `G` - Points X (default 40)
|
||||
- `H` - Points Y (default 40)
|
||||
- `I` - Offset X (default 74)
|
||||
- `J` - Offset Y (default 34)
|
||||
*/
|
||||
void dcode_81()
|
||||
{
|
||||
float dimension_x = 40;
|
||||
float dimension_y = 40;
|
||||
int points_x = 40;
|
||||
int points_y = 40;
|
||||
float offset_x = 74;
|
||||
float offset_y = 33;
|
||||
|
||||
if (code_seen('E')) dimension_x = code_value();
|
||||
if (code_seen('F')) dimension_y = code_value();
|
||||
if (code_seen("G")) { strchr_pointer+=1; points_x = code_value(); }
|
||||
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
|
||||
|
||||
/*!
|
||||
### D106 - Print measured fan speed for different pwm values <a href="https://reprap.org/wiki/G-code#D106:_Print_measured_fan_speed_for_different_pwm_values">D106: Print measured fan speed for different pwm values</a>
|
||||
*/
|
||||
void dcode_106()
|
||||
{
|
||||
for (int i = 255; i > 0; i = i - 5) {
|
||||
fanSpeed = i;
|
||||
//delay_keep_alive(2000);
|
||||
for (int j = 0; j < 100; j++) {
|
||||
delay_keep_alive(100);
|
||||
}
|
||||
printf_P(_N("%d: %d\n"), i, fan_speed[1]);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TMC2130
|
||||
#include "planner.h"
|
||||
#include "tmc2130.h"
|
||||
extern void st_synchronize();
|
||||
/**
|
||||
* @brief D2130 Trinamic stepper controller
|
||||
* D2130<axis><command>[subcommand][value]
|
||||
* * Axis
|
||||
* * * 'X'
|
||||
* * * 'Y'
|
||||
* * * 'Z'
|
||||
* * * 'E'
|
||||
* * command
|
||||
* * * '0' current off
|
||||
* * * '1' current on
|
||||
* * * '+' single step
|
||||
* * * * value sereval steps
|
||||
* * * '-' dtto oposite direction
|
||||
* * * '?' read register
|
||||
* * * * "mres"
|
||||
* * * * "step"
|
||||
* * * * "mscnt"
|
||||
* * * * "mscuract"
|
||||
* * * * "wave"
|
||||
* * * '!' set register
|
||||
* * * * "mres"
|
||||
* * * * "step"
|
||||
* * * * "wave"
|
||||
* * * * *0, 180..250 meaning: off, 0.9..1.25, recommended value is 1.1
|
||||
* * * '@' home calibrate axis
|
||||
*
|
||||
* Example:
|
||||
* 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
|
||||
*/
|
||||
/*!
|
||||
### 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
|
||||
- `Y` - Y stepper driver
|
||||
- `Z` - Z stepper driver
|
||||
- `E` - Extruder stepper driver
|
||||
- Commands
|
||||
- `0` - Current off
|
||||
- `1` - Current on
|
||||
- `+` - Single step
|
||||
- `-` - Single step oposite direction
|
||||
- `NNN` - Value sereval steps
|
||||
- `?` - Read register
|
||||
- Subcommands for read register
|
||||
- `mres` - Micro step resolution. More information in datasheet '5.5.2 CHOPCONF – Chopper Configuration'
|
||||
- `step` - Step
|
||||
- `mscnt` - Microstep counter. More information in datasheet '5.5 Motor Driver Registers'
|
||||
- `mscuract` - Actual microstep current for motor. More information in datasheet '5.5 Motor Driver Registers'
|
||||
- `wave` - Microstep linearity compensation curve
|
||||
- `!` - Set register
|
||||
- Subcommands for set register
|
||||
- `mres` - Micro step resolution
|
||||
- `step` - Step
|
||||
- `wave` - Microstep linearity compensation curve
|
||||
- Values for set register
|
||||
- `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
|
||||
*
|
||||
*/
|
||||
void dcode_2130()
|
||||
{
|
||||
printf_P(PSTR("D2130 - TMC2130\n"));
|
||||
puts_P(PSTR("D2130 - TMC2130"));
|
||||
uint8_t axis = 0xff;
|
||||
switch (strchr_pointer[1+4])
|
||||
{
|
||||
|
|
@ -765,20 +865,19 @@ void dcode_2130()
|
|||
}
|
||||
#endif //TMC2130
|
||||
|
||||
#ifdef PAT9125
|
||||
#if defined(FILAMENT_SENSOR) && (FILAMENT_SENSOR_TYPE == FSENSOR_PAT9125)
|
||||
/*!
|
||||
*
|
||||
### D9125 - PAT9125 filament sensor <a href="https://reprap.org/wiki/G-code#D9:_Read.2FWrite_ADC">D9125: PAT9125 filament sensor</a>
|
||||
|
||||
D9125 [ ? | ! | R | X | Y | L ]
|
||||
|
||||
- `?` - Print values
|
||||
- `!` - Print values
|
||||
- `R` - Resolution. Not active in code
|
||||
- `X` - X values
|
||||
- `Y` - Y values
|
||||
- `L` - Activate filament sensor log
|
||||
*
|
||||
#### Usage
|
||||
|
||||
D9125 [ ? | ! | R | X | Y | L ]
|
||||
|
||||
#### Parameters
|
||||
- `?` - Print values
|
||||
- `!` - Print values
|
||||
- `R` - Resolution. Not active in code
|
||||
- `X` - X values
|
||||
- `Y` - Y values
|
||||
*/
|
||||
void dcode_9125()
|
||||
{
|
||||
|
|
@ -812,13 +911,102 @@ void dcode_9125()
|
|||
pat9125_y = (int)code_value();
|
||||
LOG("pat9125_y=%d\n", pat9125_y);
|
||||
}
|
||||
if (code_seen('L'))
|
||||
{
|
||||
fsensor_log = (int)code_value();
|
||||
LOG("fsensor_log=%d\n", fsensor_log);
|
||||
}
|
||||
}
|
||||
#endif //PAT9125
|
||||
|
||||
#endif //defined(FILAMENT_SENSOR) && (FILAMENT_SENSOR_TYPE == FSENSOR_PAT9125)
|
||||
|
||||
#endif //DEBUG_DCODES
|
||||
|
||||
#ifdef XFLASH_DUMP
|
||||
#include "xflash_dump.h"
|
||||
|
||||
void dcode_20()
|
||||
{
|
||||
if(code_seen('E'))
|
||||
xfdump_full_dump_and_reset();
|
||||
else
|
||||
{
|
||||
unsigned long ts = _millis();
|
||||
xfdump_dump();
|
||||
ts = _millis() - ts;
|
||||
DBG(_N("dump completed in %lums\n"), ts);
|
||||
}
|
||||
}
|
||||
|
||||
void dcode_21()
|
||||
{
|
||||
if(!xfdump_check_state())
|
||||
DBG(_N("no dump available\n"));
|
||||
else
|
||||
{
|
||||
KEEPALIVE_STATE(NOT_BUSY);
|
||||
DBG(_N("D21 - read crash dump\n"));
|
||||
print_mem(DUMP_OFFSET, sizeof(dump_t), dcode_mem_t::xflash);
|
||||
}
|
||||
}
|
||||
|
||||
void dcode_22()
|
||||
{
|
||||
if(!xfdump_check_state())
|
||||
DBG(_N("no dump available\n"));
|
||||
else
|
||||
{
|
||||
xfdump_reset();
|
||||
DBG(_N("dump cleared\n"));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef EMERGENCY_SERIAL_DUMP
|
||||
#include "asm.h"
|
||||
#include "xflash_dump.h"
|
||||
|
||||
bool emergency_serial_dump = false;
|
||||
|
||||
void dcode_23()
|
||||
{
|
||||
if(code_seen('E'))
|
||||
serial_dump_and_reset(dump_crash_reason::manual);
|
||||
else
|
||||
{
|
||||
emergency_serial_dump = !code_seen('R');
|
||||
SERIAL_ECHOPGM("serial dump ");
|
||||
SERIAL_ECHOLNRPGM(emergency_serial_dump? _N("enabled"): _N("disabled"));
|
||||
}
|
||||
}
|
||||
|
||||
void __attribute__((noinline)) serial_dump_and_reset(dump_crash_reason reason)
|
||||
{
|
||||
uint16_t sp;
|
||||
uint32_t pc;
|
||||
|
||||
// we're being called from a live state, so shut off interrupts ...
|
||||
cli();
|
||||
|
||||
// sample SP/PC
|
||||
sp = SP;
|
||||
pc = GETPC();
|
||||
|
||||
// extend WDT long enough to allow writing the entire stream
|
||||
wdt_enable(WDTO_8S);
|
||||
|
||||
// ... and heaters
|
||||
WRITE(FAN_PIN, HIGH);
|
||||
disable_heater();
|
||||
|
||||
// this function can also be called from within a corrupted state, so not use
|
||||
// printf family of functions that use the heap or grow the stack.
|
||||
SERIAL_ECHOLNPGM("D23 - emergency serial dump");
|
||||
SERIAL_ECHOPGM("error: ");
|
||||
MYSERIAL.print((uint8_t)reason, DEC);
|
||||
SERIAL_ECHOPGM(" 0x");
|
||||
MYSERIAL.print(pc, HEX);
|
||||
SERIAL_ECHOPGM(" 0x");
|
||||
MYSERIAL.println(sp, HEX);
|
||||
|
||||
print_mem(0, RAMEND+1, dcode_mem_t::sram);
|
||||
SERIAL_ECHOLNRPGM(MSG_OK);
|
||||
|
||||
// reset soon
|
||||
softReset();
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -2,27 +2,60 @@
|
|||
#define DCODES_H
|
||||
|
||||
extern void dcode__1(); //D-1 - Endless loop (to simulate deadlock)
|
||||
|
||||
extern void dcode_0(); //D0 - Reset
|
||||
extern void dcode_1(); //D1 - Clear EEPROM
|
||||
|
||||
#if defined DEBUG_DCODE2 || defined DEBUG_DCODES
|
||||
extern void dcode_2(); //D2 - Read/Write RAM
|
||||
#endif
|
||||
|
||||
#if defined DEBUG_DCODE3 || defined DEBUG_DCODES
|
||||
extern void dcode_3(); //D3 - Read/Write EEPROM
|
||||
#endif //DEBUG_DCODE3
|
||||
|
||||
extern void dcode_4(); //D4 - Read/Write PIN
|
||||
|
||||
#if defined DEBUG_DCODE5 || defined DEBUG_DCODES
|
||||
extern void dcode_5(); //D5 - Read/Write FLASH
|
||||
#endif //DEBUG_DCODE5
|
||||
|
||||
#if defined DEBUG_DCODE6 || defined DEBUG_DCODES
|
||||
extern void dcode_6(); //D6 - Read/Write external FLASH
|
||||
#endif
|
||||
|
||||
extern void dcode_7(); //D7 - Read/Write Bootloader
|
||||
extern void dcode_8(); //D8 - Read/Write PINDA
|
||||
extern void dcode_9(); //D9 - Read/Write ADC (Write=enable simulated, Read=disable simulated)
|
||||
|
||||
extern void dcode_10(); //D10 - XYZ calibration = OK
|
||||
extern void dcode_12(); //D12 - Log time. Writes the current time in the log file.
|
||||
|
||||
#ifdef XFLASH_DUMP
|
||||
extern void dcode_20(); //D20 - Generate an offline crash dump
|
||||
extern void dcode_21(); //D21 - Print crash dump to serial
|
||||
extern void dcode_22(); //D22 - Clear crash dump state
|
||||
#endif
|
||||
|
||||
#ifdef EMERGENCY_SERIAL_DUMP
|
||||
#include "xflash_dump.h"
|
||||
extern void dcode_23(); //D23 - Request/generate an online serial crash dump
|
||||
extern bool emergency_serial_dump; //emergency dump enabled flag
|
||||
extern void serial_dump_and_reset(dump_crash_reason);
|
||||
#endif
|
||||
|
||||
#ifdef HEATBED_ANALYSIS
|
||||
extern void dcode_80(); //D80 - Bed check. This command will log data to SD card file "mesh.txt".
|
||||
extern void dcode_81(); //D81 - Bed analysis. This command will log data to SD card file "wldsd.txt".
|
||||
#endif //HEATBED_ANALYSIS
|
||||
|
||||
extern void dcode_106(); //D106 - Print measured fan speed for different pwm values
|
||||
|
||||
#ifdef TMC2130
|
||||
extern void dcode_2130(); //D2130 - TMC2130
|
||||
extern void dcode_2130(); //D2130 - TMC2130
|
||||
#endif //TMC2130
|
||||
|
||||
#ifdef PAT9125
|
||||
extern void dcode_9125(); //D9125 - PAT9125
|
||||
#endif //PAT9125
|
||||
#if defined(FILAMENT_SENSOR) && (FILAMENT_SENSOR_TYPE == FSENSOR_PAT9125)
|
||||
extern void dcode_9125(); //D9125 - PAT9125
|
||||
#endif //defined(FILAMENT_SENSOR) && (FILAMENT_SENSOR_TYPE == FSENSOR_PAT9125)
|
||||
|
||||
|
||||
#endif //DCODES_H
|
||||
|
|
|
|||
|
|
@ -0,0 +1,531 @@
|
|||
#include <avr/pgmspace.h>
|
||||
#include <stdio.h>
|
||||
#include <util/atomic.h>
|
||||
|
||||
#include "Filament_sensor.h"
|
||||
#include "Timer.h"
|
||||
#include "cardreader.h"
|
||||
#include "eeprom.h"
|
||||
#include "menu.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((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((uint8_t *)EEPROM_FSENS_AUTOLOAD_ENABLED, state);
|
||||
}
|
||||
}
|
||||
|
||||
void Filament_sensor::setRunoutEnabled(bool state, bool updateEEPROM) {
|
||||
runoutEnabled = state;
|
||||
if (updateEEPROM) {
|
||||
eeprom_update_byte((uint8_t *)EEPROM_FSENS_RUNOUT_ENABLED, state);
|
||||
}
|
||||
}
|
||||
|
||||
void Filament_sensor::setActionOnError(SensorActionOnError state, bool updateEEPROM) {
|
||||
sensorActionOnError = state;
|
||||
if (updateEEPROM) {
|
||||
eeprom_update_byte((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
|
||||
|| IS_SD_PRINTING
|
||||
|| usb_timer.running()
|
||||
|| (lcd_commands_type == LcdCommands::Layer1Cal)
|
||||
|| eeprom_read_byte((uint8_t *)EEPROM_WIZARD_ACTIVE)
|
||||
)
|
||||
) {
|
||||
filAutoLoad();
|
||||
}
|
||||
}
|
||||
|
||||
void Filament_sensor::triggerFilamentRemoved() {
|
||||
// SERIAL_ECHOLNPGM("triggerFilamentRemoved");
|
||||
if (runoutEnabled
|
||||
&& (! MMU2::mmu2.Enabled() ) // quick and dirty hack to prevent spurious runouts just before the toolchange
|
||||
&& (eFilamentAction == FilamentAction::None)
|
||||
&& !saved_printing
|
||||
&& (
|
||||
moves_planned() != 0
|
||||
|| IS_SD_PRINTING
|
||||
|| usb_timer.running()
|
||||
|| (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::filAutoLoad() {
|
||||
eFilamentAction = FilamentAction::AutoLoad;
|
||||
if (target_temperature[0] >= EXTRUDE_MINTEMP) {
|
||||
bFilamentPreheatState = true;
|
||||
menu_submenu(mFilamentItemForce);
|
||||
} else {
|
||||
menu_submenu(lcd_generic_preheat_menu);
|
||||
lcd_timeoutToStatus.start();
|
||||
}
|
||||
}
|
||||
|
||||
void Filament_sensor::filRunout() {
|
||||
// SERIAL_ECHOLNPGM("filRunout");
|
||||
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((PSTR("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((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;
|
||||
}
|
||||
/// 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 <= raw && raw <= 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
|
||||
#error "I really think this code can't be enabled anymore because we are constantly checking this voltage."
|
||||
if((sensorRevision == SensorRevision::_Undef) && (raw > 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;
|
||||
}
|
||||
|
||||
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_unit[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((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((PSTR("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.running() || pollingTimer.expired(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)
|
||||
|
|
@ -0,0 +1,214 @@
|
|||
#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();
|
||||
|
||||
static void filAutoLoad();
|
||||
|
||||
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
|
||||
|
|
@ -4,7 +4,7 @@
|
|||
#ifndef MARLIN_H
|
||||
#define MARLIN_H
|
||||
|
||||
#define FORCE_INLINE __attribute__((always_inline)) inline
|
||||
#include "macros.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
|
|
@ -21,6 +21,7 @@
|
|||
#include "Configuration.h"
|
||||
#include "pins.h"
|
||||
#include "Timer.h"
|
||||
#include "mmu2.h"
|
||||
extern uint8_t mbl_z_probe_nr;
|
||||
|
||||
#ifndef AT90USB
|
||||
|
|
@ -79,9 +80,9 @@ extern FILE _uartout;
|
|||
#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)/*,MYSERIAL.write('\n')*/)
|
||||
#define SERIAL_PROTOCOLLNPGM(x) (serialprintPGM(PSTR(x)),MYSERIAL.println()/*write('\n')*/)
|
||||
#define SERIAL_PROTOCOLLNRPGM(x) (serialprintPGM((x)),MYSERIAL.println()/*write('\n')*/)
|
||||
#define SERIAL_PROTOCOLLN(x) (MYSERIAL.println(x))
|
||||
#define SERIAL_PROTOCOLLNPGM(x) (serialprintlnPGM(PSTR(x)))
|
||||
#define SERIAL_PROTOCOLLNRPGM(x) (serialprintlnPGM((x)))
|
||||
|
||||
|
||||
extern const char errormagic[] PROGMEM;
|
||||
|
|
@ -115,8 +116,10 @@ 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 get_command();
|
||||
void process_commands();
|
||||
void ramming();
|
||||
|
||||
|
|
@ -146,40 +149,39 @@ void manage_inactivity(bool ignore_stepper_queue=false);
|
|||
#if defined(Z_ENABLE_PIN) && Z_ENABLE_PIN > -1
|
||||
#if defined(Z_AXIS_ALWAYS_ON)
|
||||
#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; }
|
||||
#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 enable_z() WRITE(Z_ENABLE_PIN, Z_ENABLE_ON)
|
||||
#define disable_z() {}
|
||||
#define poweron_z() WRITE(Z_ENABLE_PIN, Z_ENABLE_ON)
|
||||
#define poweroff_z() {}
|
||||
#endif
|
||||
#else
|
||||
#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; }
|
||||
#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 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; }
|
||||
#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 enable_z() {}
|
||||
#define disable_z() {}
|
||||
#define poweron_z() {}
|
||||
#define poweroff_z() {}
|
||||
#endif
|
||||
|
||||
#ifdef PSU_Delta
|
||||
#ifndef PSU_Delta
|
||||
#define enable_z() poweron_z()
|
||||
#define disable_z() poweroff_z()
|
||||
#else
|
||||
void init_force_z();
|
||||
void check_force_z();
|
||||
#undef disable_z
|
||||
#define disable_z() disable_force_z()
|
||||
void disable_force_z();
|
||||
#undef enable_z
|
||||
#define enable_z() enable_force_z()
|
||||
void enable_force_z();
|
||||
void disable_force_z();
|
||||
#define enable_z() enable_force_z()
|
||||
#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); }
|
||||
|
|
@ -219,9 +221,6 @@ void manage_inactivity(bool ignore_stepper_queue=false);
|
|||
#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
|
||||
|
|
@ -235,130 +234,90 @@ void FlushSerialRequestResend();
|
|||
void ClearToSend();
|
||||
void update_currents();
|
||||
|
||||
void get_coordinates();
|
||||
void prepare_move();
|
||||
void kill(const char *full_screen_message = NULL, unsigned char id = 0);
|
||||
void Stop();
|
||||
void finishAndDisableSteppers();
|
||||
|
||||
bool IsStopped();
|
||||
|
||||
//put an ASCII command at the end of the current buffer.
|
||||
void enquecommand(const char *cmd, bool from_progmem = false);
|
||||
void UnconditionalStop(); // Stop heaters, motion and clear current print status
|
||||
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
|
||||
|
||||
//put an ASCII command at the end of the current buffer, read from flash
|
||||
#define enquecommand_P(cmd) enquecommand(cmd, true)
|
||||
|
||||
//put an ASCII command at the begin of the current buffer
|
||||
void enquecommand_front(const char *cmd, bool from_progmem = false);
|
||||
|
||||
//put an ASCII command at the begin of the current buffer, read from flash
|
||||
#define enquecommand_front_P(cmd) enquecommand_front(cmd, true)
|
||||
|
||||
void repeatcommand_front();
|
||||
|
||||
// Remove all lines from the command queue.
|
||||
void cmdqueue_reset();
|
||||
|
||||
void prepare_arc_move(char 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
|
||||
|
||||
#ifndef CRITICAL_SECTION_START
|
||||
#define CRITICAL_SECTION_START unsigned char _sreg = SREG; cli();
|
||||
#define CRITICAL_SECTION_END SREG = _sreg;
|
||||
#endif //CRITICAL_SECTION_START
|
||||
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;
|
||||
extern float homing_feedrate[];
|
||||
extern bool axis_relative_modes[];
|
||||
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 volumetric_multiplier[EXTRUDERS]; // reciprocal of cross-sectional area of filament (in square millimeters), stored this way to reduce computational burden in planner
|
||||
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 int fanSpeed;
|
||||
extern int8_t lcd_change_fil_state;
|
||||
extern uint8_t newFanSpeed;
|
||||
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();
|
||||
|
||||
#ifdef TMC2130
|
||||
void homeaxis(int axis, uint8_t cnt = 1, uint8_t* pstep = 0);
|
||||
void homeaxis(uint8_t axis, uint8_t cnt = 1, uint8_t* pstep = 0);
|
||||
#else
|
||||
void homeaxis(int axis, uint8_t cnt = 1);
|
||||
void homeaxis(uint8_t 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 uint8_t host_keepalive_interval;
|
||||
|
||||
extern unsigned long starttime;
|
||||
extern unsigned long stoptime;
|
||||
extern int bowden_length[4];
|
||||
extern bool is_usb_printing;
|
||||
extern ShortTimer usb_timer;
|
||||
extern bool processing_tcode;
|
||||
extern bool homing_flag;
|
||||
extern bool temp_cal_active;
|
||||
extern bool loading_flag;
|
||||
extern unsigned int usb_printing_counter;
|
||||
|
||||
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 uint8_t heating_status_counter;
|
||||
|
||||
extern bool fan_state[2];
|
||||
extern int fan_edge_counter[2];
|
||||
extern int fan_speed[2];
|
||||
|
||||
// Handling multiple extruders pins
|
||||
extern uint8_t active_extruder;
|
||||
// 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
|
||||
|
||||
//Long pause
|
||||
extern unsigned long pause_time;
|
||||
|
|
@ -366,13 +325,7 @@ extern unsigned long start_pause_print;
|
|||
extern unsigned long t_fan_rising_edge;
|
||||
|
||||
extern bool mesh_bed_leveling_flag;
|
||||
extern bool mesh_bed_run_from_menu;
|
||||
|
||||
extern bool sortAlpha;
|
||||
|
||||
extern char dir_names[3][9];
|
||||
|
||||
extern int8_t lcd_change_fil_state;
|
||||
// save/restore printing
|
||||
extern bool saved_printing;
|
||||
extern uint8_t saved_printing_type;
|
||||
|
|
@ -380,14 +333,17 @@ extern uint8_t saved_printing_type;
|
|||
#define PRINTING_TYPE_USB 1
|
||||
#define PRINTING_TYPE_NONE 2
|
||||
|
||||
//save/restore printing in case that mmu is not responding
|
||||
extern bool mmu_print_saved;
|
||||
extern float saved_extruder_temperature; //!< Active extruder temperature
|
||||
extern float saved_bed_temperature; //!< Bed temperature
|
||||
extern int saved_fan_speed; //!< Print fan speed
|
||||
|
||||
//estimated time to end of the print
|
||||
extern uint8_t print_percent_done_normal;
|
||||
extern uint16_t print_time_remaining_normal;
|
||||
extern uint8_t print_percent_done_silent;
|
||||
extern uint16_t print_time_remaining_normal;
|
||||
extern uint16_t print_time_remaining_silent;
|
||||
extern uint16_t print_time_to_change_normal;
|
||||
extern uint16_t print_time_to_change_silent;
|
||||
|
||||
#define PRINT_TIME_REMAINING_INIT 0xffff
|
||||
|
||||
|
|
@ -396,8 +352,9 @@ extern uint16_t gcode_in_progress;
|
|||
|
||||
extern LongTimer safetyTimer;
|
||||
|
||||
#define PRINT_PERCENT_DONE_INIT 0xff
|
||||
#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)
|
||||
#define PRINT_PERCENT_DONE_INIT 0xff
|
||||
|
||||
extern bool printer_active();
|
||||
|
||||
//! 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
|
||||
|
|
@ -406,7 +363,7 @@ extern LongTimer safetyTimer;
|
|||
//! 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 :)
|
||||
#define CHECK_FSENSOR ((IS_SD_PRINTING || is_usb_printing) && (mcode_in_progress != 600) && !saved_printing && e_active())
|
||||
bool check_fsensor();
|
||||
|
||||
extern void calculate_extruder_multipliers();
|
||||
|
||||
|
|
@ -426,7 +383,9 @@ 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);
|
||||
#if 0
|
||||
void show_fw_version_warnings();
|
||||
#endif
|
||||
uint8_t check_printer_version();
|
||||
|
||||
#ifdef PINDA_THERMISTOR
|
||||
|
|
@ -445,9 +404,8 @@ void setup_uvlo_interrupt();
|
|||
void setup_fan_interrupt();
|
||||
#endif
|
||||
|
||||
//extern void recover_machine_state_after_power_panic();
|
||||
extern void recover_machine_state_after_power_panic(bool bTiny);
|
||||
extern void restore_print_from_eeprom();
|
||||
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();
|
||||
|
|
@ -455,12 +413,12 @@ extern void print_physical_coordinates();
|
|||
extern void print_mesh_bed_leveling_table();
|
||||
|
||||
extern void stop_and_save_print_to_ram(float z_move, float e_move);
|
||||
void restore_extruder_temperature_from_ram();
|
||||
extern void restore_print_from_ram_and_continue(float e_move);
|
||||
extern void cancel_saved_printing();
|
||||
|
||||
|
||||
//estimated time to end of the print
|
||||
extern uint16_t print_time_remaining();
|
||||
extern uint8_t calc_percent_done();
|
||||
|
||||
|
||||
|
|
@ -483,6 +441,7 @@ 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;
|
||||
|
||||
|
|
@ -500,12 +459,13 @@ void force_high_power_mode(bool start_high_power_section);
|
|||
|
||||
bool gcode_M45(bool onlyZ, int8_t verbosity_level);
|
||||
void gcode_M114();
|
||||
void gcode_M701();
|
||||
#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);
|
||||
|
||||
#define UVLO !(PINE & (1<<4))
|
||||
|
||||
void proc_commands();
|
||||
|
||||
|
||||
void M600_load_filament();
|
||||
void M600_load_filament_movements();
|
||||
|
|
@ -513,6 +473,12 @@ void M600_wait_for_user(float HotendTempBckp);
|
|||
void M600_check_state(float nozzle_temp);
|
||||
void load_filament_final_feed();
|
||||
void marlin_wait_for_click();
|
||||
void raise_z_above(float target, bool plan=true);
|
||||
float raise_z(float delta);
|
||||
void raise_z_above(float target);
|
||||
|
||||
extern "C" void softReset();
|
||||
void stack_error();
|
||||
|
||||
extern uint32_t IP_address;
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ uint8_t selectedSerialPort = 0;
|
|||
// 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)
|
||||
|
||||
#if UART_PRESENT(SERIAL_PORT)
|
||||
#ifdef HAS_UART
|
||||
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,7 +97,6 @@ ISR(USART1_RX_vect)
|
|||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Public Methods //////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
@ -131,8 +130,6 @@ void MarlinSerial::begin(long baud)
|
|||
sbi(M_UCSRxB, M_TXENx);
|
||||
sbi(M_UCSRxB, M_RXCIEx);
|
||||
|
||||
#ifndef SNMM
|
||||
|
||||
if (selectedSerialPort == 1) { //set up also the second serial port
|
||||
if (useU2X) {
|
||||
UCSR1A = 1 << U2X1;
|
||||
|
|
@ -148,9 +145,8 @@ void MarlinSerial::begin(long baud)
|
|||
|
||||
sbi(UCSR1B, RXEN1);
|
||||
sbi(UCSR1B, TXEN1);
|
||||
sbi(UCSR1B, RXCIE1);
|
||||
sbi(UCSR1B, RXCIE1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void MarlinSerial::end()
|
||||
|
|
@ -159,11 +155,9 @@ 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
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -255,7 +249,7 @@ void MarlinSerial::print(double n, int digits)
|
|||
|
||||
void MarlinSerial::println(void)
|
||||
{
|
||||
print('\r');
|
||||
// print('\r');
|
||||
print('\n');
|
||||
}
|
||||
|
||||
|
|
@ -318,7 +312,7 @@ 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.
|
||||
unsigned long i = 0;
|
||||
uint8_t i = 0;
|
||||
|
||||
if (n == 0) {
|
||||
print('0');
|
||||
|
|
@ -359,7 +353,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)
|
||||
|
|
|
|||
|
|
@ -28,17 +28,19 @@
|
|||
#endif
|
||||
|
||||
// The presence of the UBRRH register is used to detect a UART.
|
||||
#define UART_PRESENT(port) ((port == 0 && (defined(UBRRH) || defined(UBRR0H))) || \
|
||||
(port == 1 && defined(UBRR1H)) || (port == 2 && defined(UBRR2H)) || \
|
||||
(port == 3 && defined(UBRR3H)))
|
||||
#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
|
||||
|
||||
// These are macros to build serial port register names for the selected SERIAL_PORT (C preprocessor
|
||||
// requires two levels of indirection to expand macro values properly)
|
||||
#define SERIAL_REGNAME(registerbase,number,suffix) SERIAL_REGNAME_INTERNAL(registerbase,number,suffix)
|
||||
#if SERIAL_PORT == 0 && (!defined(UBRR0H) || !defined(UDR0)) // use un-numbered registers if necessary
|
||||
#define SERIAL_REGNAME_INTERNAL(registerbase,number,suffix) registerbase##suffix
|
||||
#define SERIAL_REGNAME(registerbase,number,suffix) _REGNAME_SHORT(registerbase, suffix)
|
||||
#else
|
||||
#define SERIAL_REGNAME_INTERNAL(registerbase,number,suffix) registerbase##number##suffix
|
||||
#define SERIAL_REGNAME(registerbase,number,suffix) _REGNAME(registerbase, number, suffix)
|
||||
#endif
|
||||
|
||||
// Registers used by MarlinSerial class (these are expanded
|
||||
|
|
@ -82,7 +84,7 @@ struct ring_buffer
|
|||
int tail;
|
||||
};
|
||||
|
||||
#if UART_PRESENT(SERIAL_PORT)
|
||||
#ifdef HAS_UART
|
||||
extern ring_buffer rx_buffer;
|
||||
#endif
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,495 @@
|
|||
#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"
|
||||
|
||||
#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 (starttime != 0) {
|
||||
SERIAL_ECHO(_millis() / 1000 - starttime / 1000);
|
||||
}
|
||||
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() {
|
||||
|
||||
setTargetHotend(0);
|
||||
setTargetBed(0);
|
||||
|
||||
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 (isPrintPaused) {
|
||||
prusa_statistics_case0(14);
|
||||
}
|
||||
else if (IS_SD_PRINTING || loading_flag) {
|
||||
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 || loading_flag) {
|
||||
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(loading_flag)
|
||||
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((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((unsigned char *)EEPROM_FARM_MODE, farm_mode);
|
||||
SilentModeMenu = SILENT_MODE_OFF;
|
||||
eeprom_update_byte((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((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
|
||||
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
#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() {
|
||||
digitalWrite(chipSelectPin_, HIGH);
|
||||
WRITE(SDSS, 1);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void Sd2Card::chipSelectLow() {
|
||||
#ifndef SOFTWARE_SPI
|
||||
spiInit(spiRate_);
|
||||
#endif // SOFTWARE_SPI
|
||||
digitalWrite(chipSelectPin_, LOW);
|
||||
WRITE(SDSS, 0);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Erase a range of blocks.
|
||||
|
|
@ -283,26 +283,25 @@ 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, uint8_t chipSelectPin) {
|
||||
bool Sd2Card::init(uint8_t sckRateID) {
|
||||
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();
|
||||
pinMode(SPI_MISO_PIN, INPUT);
|
||||
pinMode(SPI_MOSI_PIN, OUTPUT);
|
||||
pinMode(SPI_SCK_PIN, OUTPUT);
|
||||
SET_OUTPUT(SDSS);
|
||||
SET_INPUT(MISO);
|
||||
SET_OUTPUT(MOSI);
|
||||
SET_OUTPUT(SCK);
|
||||
|
||||
#ifndef SOFTWARE_SPI
|
||||
// SS must be in output mode even it is not chip select
|
||||
pinMode(SS_PIN, OUTPUT);
|
||||
SET_OUTPUT(SS);
|
||||
// set SS high - may be chip select for another SPI device
|
||||
#if SET_SPI_SS_HIGH
|
||||
digitalWrite(SS_PIN, HIGH);
|
||||
WRITE(SS, 1);
|
||||
#endif // SET_SPI_SS_HIGH
|
||||
// set SCK rate for initialization commands
|
||||
spiRate_ = SPI_SD_INIT_RATE;
|
||||
|
|
@ -312,13 +311,16 @@ bool Sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin) {
|
|||
// 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,6 +769,9 @@ uint8_t Sd2Card::waitStartBlock(void) {
|
|||
|
||||
// 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).
|
||||
// https://flashair-developers.github.io/website/docs/tutorials/arduino/2.html
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** Perform Extention Read. */
|
||||
|
|
@ -774,7 +779,7 @@ uint8_t Sd2Card::readExt(uint32_t arg, uint8_t* dst, uint16_t count) {
|
|||
uint16_t i;
|
||||
|
||||
// send command and argument.
|
||||
if (cardCommand(CMD48, arg)) {
|
||||
if (cardCommand(CMD48, arg) && cardCommand(CMD17, arg)) { // CMD48 for W-03, CMD17 for W-04
|
||||
error(SD_CARD_ERROR_CMD48);
|
||||
goto fail;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,6 @@
|
|||
* \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
|
||||
|
|
@ -133,22 +132,7 @@ uint8_t const SD_CARD_TYPE_SDHC = 3;
|
|||
//------------------------------------------------------------------------------
|
||||
// SPI pin definitions - do not edit here - change in SdFatConfig.h
|
||||
//
|
||||
#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;
|
||||
#ifdef SOFTWARE_SPI
|
||||
/** SPI Master Out Slave In pin */
|
||||
uint8_t const SPI_MOSI_PIN = SOFT_SPI_MOSI_PIN;
|
||||
/** SPI Master In Slave Out pin */
|
||||
|
|
@ -176,17 +160,16 @@ class Sd2Card {
|
|||
/**
|
||||
* \return error code for last error. See Sd2Card.h for a list of error codes.
|
||||
*/
|
||||
int errorCode() const {return errorCode_;}
|
||||
uint8_t errorCode() const {return errorCode_;}
|
||||
/** \return error data for last error. */
|
||||
int errorData() const {return status_;}
|
||||
uint8_t errorData() const {return status_;}
|
||||
/**
|
||||
* Initialize an SD flash memory card with default clock rate and chip
|
||||
* select pin. See sd2Card::init(uint8_t sckRateID, uint8_t chipSelectPin).
|
||||
* select pin. See sd2Card::init(uint8_t sckRateID).
|
||||
*
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool init(uint8_t sckRateID = SPI_FULL_SPEED,
|
||||
uint8_t chipSelectPin = SD_CHIP_SELECT_PIN);
|
||||
bool init(uint8_t sckRateID = SPI_FULL_SPEED);
|
||||
bool readBlock(uint32_t block, uint8_t* dst);
|
||||
/**
|
||||
* Read a card's CID register. The CID contains card identification
|
||||
|
|
@ -232,7 +215,6 @@ class Sd2Card {
|
|||
|
||||
private:
|
||||
//----------------------------------------------------------------------------
|
||||
uint8_t chipSelectPin_;
|
||||
uint8_t errorCode_;
|
||||
uint8_t spiRate_;
|
||||
uint8_t status_;
|
||||
|
|
|
|||
|
|
@ -1,368 +0,0 @@
|
|||
/* 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
|
||||
|
||||
// Two Wire (aka I2C) ports
|
||||
uint8_t const SDA_PIN = 20; // D1
|
||||
uint8_t const SCL_PIN = 21; // D0
|
||||
|
||||
#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
|
||||
|
|
@ -530,9 +530,9 @@ bool SdBaseFile::mkdir(SdBaseFile* parent, const uint8_t dname[11]) {
|
|||
* \return The value one, true, is returned for success and
|
||||
* the value zero, false, is returned for failure.
|
||||
*/
|
||||
bool SdBaseFile::open(const char* path, uint8_t oflag) {
|
||||
return open(cwd_, path, oflag);
|
||||
}
|
||||
bool SdBaseFile::open(const char* path, uint8_t oflag) {
|
||||
return open(cwd_, path, oflag);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Open a file or directory by name.
|
||||
*
|
||||
|
|
@ -1015,7 +1015,7 @@ void SdBaseFile::printFatTime( uint16_t fatTime) {
|
|||
* the value zero, false, is returned for failure.
|
||||
*/
|
||||
bool SdBaseFile::printName() {
|
||||
char name[13];
|
||||
char name[FILENAME_LENGTH];
|
||||
if (!getFilename(name)) return false;
|
||||
MYSERIAL.print(name);
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -281,8 +281,10 @@ class SdBaseFile {
|
|||
static void printFatDate(uint16_t fatDate);
|
||||
static void printFatTime( uint16_t fatTime);
|
||||
bool printName();
|
||||
protected:
|
||||
int16_t read();
|
||||
int16_t read(void* buf, uint16_t nbyte);
|
||||
public:
|
||||
int8_t readDir(dir_t* dir, char* longFilename);
|
||||
static bool remove(SdBaseFile* dirFile, const char* path);
|
||||
bool remove();
|
||||
|
|
@ -321,7 +323,7 @@ class SdBaseFile {
|
|||
SdVolume* volume() const {return vol_;}
|
||||
int16_t write(const void* buf, uint16_t nbyte);
|
||||
//------------------------------------------------------------------------------
|
||||
private:
|
||||
protected:
|
||||
// allow SdFat to set cwd_
|
||||
friend class SdFat;
|
||||
// global pointer to cwd dir
|
||||
|
|
|
|||
|
|
@ -48,24 +48,16 @@ void SdFatUtil::set_stack_guard()
|
|||
{
|
||||
uint32_t *stack_guard;
|
||||
|
||||
stack_guard = (uint32_t*)&__bss_end;
|
||||
stack_guard = (uint32_t*)(&__bss_end + STACK_GUARD_MARGIN);
|
||||
*stack_guard = STACK_GUARD_TEST_VALUE;
|
||||
}
|
||||
|
||||
bool SdFatUtil::test_stack_integrity()
|
||||
{
|
||||
uint32_t* stack_guard = (uint32_t*)&__bss_end;
|
||||
uint32_t* stack_guard = (uint32_t*)(&__bss_end + STACK_GUARD_MARGIN);
|
||||
return (*stack_guard == STACK_GUARD_TEST_VALUE);
|
||||
}
|
||||
|
||||
uint32_t SdFatUtil::get_stack_guard_test_value()
|
||||
{
|
||||
uint32_t* stack_guard;
|
||||
uint32_t output;
|
||||
stack_guard = (uint32_t*)&__bss_end;
|
||||
output = *stack_guard;
|
||||
return(output);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** %Print a string in flash memory.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -41,11 +41,10 @@ namespace SdFatUtil {
|
|||
void SerialPrintln_P(PGM_P str);
|
||||
void set_stack_guard();
|
||||
bool test_stack_integrity();
|
||||
uint32_t get_stack_guard_test_value();
|
||||
}
|
||||
|
||||
using namespace SdFatUtil; // NOLINT
|
||||
#endif // #define SdFatUtil_h
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -30,6 +30,194 @@
|
|||
*/
|
||||
SdFile::SdFile(const char* path, uint8_t oflag) : SdBaseFile(path, oflag) {
|
||||
}
|
||||
|
||||
bool SdFile::openFilteredGcode(SdBaseFile* dirFile, const char* path){
|
||||
if( open(dirFile, path, O_READ) ){
|
||||
// compute the block to start with
|
||||
if( ! gfComputeNextFileBlock() )
|
||||
return false;
|
||||
gfReset();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool SdFile::seekSetFilteredGcode(uint32_t pos){
|
||||
if(! seekSet(pos) )return false;
|
||||
if(! gfComputeNextFileBlock() )return false;
|
||||
gfReset();
|
||||
return true;
|
||||
}
|
||||
|
||||
const uint8_t *SdFile::gfBlockBuffBegin() const {
|
||||
return vol_->cache()->data; // this is constant for the whole time, so it should be fast and sleek
|
||||
}
|
||||
|
||||
void SdFile::gfReset(){
|
||||
// reset cache read ptr to its begin
|
||||
gfReadPtr = gfBlockBuffBegin() + gfOffset;
|
||||
}
|
||||
|
||||
// think twice before allowing this to inline - manipulating 4B longs is costly
|
||||
// moreover - this function has its parameters in registers only, so no heavy stack usage besides the call/ret
|
||||
void __attribute__((noinline)) SdFile::gfUpdateCurrentPosition(uint16_t inc){
|
||||
curPosition_ += inc;
|
||||
}
|
||||
|
||||
#define find_endl(resultP, startP) \
|
||||
__asm__ __volatile__ ( \
|
||||
"cycle: \n" \
|
||||
"ld r22, Z+ \n" \
|
||||
"cpi r22, 0x0A \n" \
|
||||
"brne cycle \n" \
|
||||
: "=z" (resultP) /* result of the ASM code - in our case the Z register (R30:R31) */ \
|
||||
: "z" (startP) /* input of the ASM code - in our case the Z register as well (R30:R31) */ \
|
||||
: "r22" /* modifying register R22 - so that the compiler knows */ \
|
||||
)
|
||||
|
||||
// avoid calling the default heavy-weight read() for just one byte
|
||||
int16_t SdFile::readFilteredGcode(){
|
||||
if( ! gfEnsureBlock() ){
|
||||
goto eof_or_fail; // this is unfortunate :( ... other calls are using the cache and we can loose the data block of our gcode file
|
||||
}
|
||||
// assume, we have the 512B block cache filled and terminated with a '\n'
|
||||
{
|
||||
const uint8_t *start = gfReadPtr;
|
||||
|
||||
// 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.
|
||||
// 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.
|
||||
// And it does! Codesize dropped by 68B!
|
||||
const uint8_t *rdPtr = gfReadPtr;
|
||||
|
||||
// the same applies to gfXBegin, codesize dropped another 100B!
|
||||
const uint8_t *blockBuffBegin = gfBlockBuffBegin();
|
||||
|
||||
uint8_t consecutiveCommentLines = 0;
|
||||
while( *rdPtr == ';' ){
|
||||
for(;;){
|
||||
|
||||
//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,
|
||||
// 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!
|
||||
// This was the generated code:
|
||||
//FORCE_INLINE const uint8_t * find_endl(const uint8_t *p){
|
||||
// while( *(++p) != '\n' ); // skip until a newline is found
|
||||
// return p; }
|
||||
// 11c5e: movw r30, r18
|
||||
// 11c60: subi r18, 0xFF ; 255
|
||||
// 11c62: sbci r19, 0xFF ; 255
|
||||
// 11c64: ld r22, Z
|
||||
// 11c66: cpi r22, 0x0A ; 10
|
||||
// 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)
|
||||
// There is no other way than pure ASM!
|
||||
find_endl(rdPtr, rdPtr);
|
||||
|
||||
// found a newline, prepare the next block if block cache end reached
|
||||
if( rdPtr - blockBuffBegin > 512 ){
|
||||
// at the end of block cache, fill new data in
|
||||
gfUpdateCurrentPosition( rdPtr - start - 1 );
|
||||
if( ! gfComputeNextFileBlock() )goto eof_or_fail;
|
||||
if( ! gfEnsureBlock() )goto eof_or_fail; // fetch it into RAM
|
||||
rdPtr = start = blockBuffBegin;
|
||||
} else {
|
||||
if(consecutiveCommentLines >= 250){
|
||||
--rdPtr; // unget the already consumed newline
|
||||
goto emit_char;
|
||||
}
|
||||
// peek the next byte - we are inside the block at least at 511th index - still safe
|
||||
if( *rdPtr == ';' ){
|
||||
// consecutive comment
|
||||
++consecutiveCommentLines;
|
||||
} else {
|
||||
--rdPtr; // unget the already consumed newline
|
||||
goto emit_char;
|
||||
}
|
||||
break; // found the real end of the line even across many blocks
|
||||
}
|
||||
}
|
||||
}
|
||||
emit_char:
|
||||
{
|
||||
gfUpdateCurrentPosition( rdPtr - start + 1 );
|
||||
int16_t rv = *rdPtr++;
|
||||
|
||||
if( curPosition_ >= fileSize_ ){
|
||||
// past the end of file
|
||||
goto eof_or_fail;
|
||||
} else if( rdPtr - blockBuffBegin >= 512 ){
|
||||
// past the end of current bufferred block - prepare the next one...
|
||||
if( ! gfComputeNextFileBlock() )goto eof_or_fail;
|
||||
// don't need to force fetch the block here, it will get loaded on the next call
|
||||
rdPtr = blockBuffBegin;
|
||||
}
|
||||
|
||||
// save the current read ptr for the next run
|
||||
gfReadPtr = rdPtr;
|
||||
return rv;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
eof_or_fail:
|
||||
// make the rdptr point to a safe location - end of file
|
||||
gfReadPtr = gfBlockBuffBegin() + 512;
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool SdFile::gfEnsureBlock(){
|
||||
// this comparison is heavy-weight, especially when there is another one inside cacheRawBlock
|
||||
// but it is necessary to avoid computing of terminateOfs if not needed
|
||||
if( gfBlock != vol_->cacheBlockNumber_ ){
|
||||
if ( ! vol_->cacheRawBlock(gfBlock, SdVolume::CACHE_FOR_READ)){
|
||||
return false;
|
||||
}
|
||||
// terminate with a '\n'
|
||||
const uint32_t terminateOfs = fileSize_ - gfOffset;
|
||||
vol_->cache()->data[ terminateOfs < 512 ? terminateOfs : 512 ] = '\n';
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SdFile::gfComputeNextFileBlock() {
|
||||
// error if not open or write only
|
||||
if (!isOpen() || !(flags_ & O_READ)) return false;
|
||||
|
||||
gfOffset = curPosition_ & 0X1FF; // offset in block
|
||||
if (type_ == FAT_FILE_TYPE_ROOT_FIXED) {
|
||||
// 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);
|
||||
} else {
|
||||
uint8_t blockOfCluster = vol_->blockOfCluster(curPosition_);
|
||||
if (gfOffset == 0 && blockOfCluster == 0) {
|
||||
// start of new cluster
|
||||
if (curPosition_ == 0) {
|
||||
// use first cluster in file
|
||||
curCluster_ = firstCluster_;
|
||||
} else {
|
||||
// get next cluster from FAT
|
||||
if (!vol_->fatGet(curCluster_, &curCluster_)) return false;
|
||||
}
|
||||
}
|
||||
gfBlock = vol_->clusterStartBlock(curCluster_) + blockOfCluster;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/** Write data to an open file.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -34,7 +34,24 @@
|
|||
* \brief SdBaseFile with Print.
|
||||
*/
|
||||
class SdFile : public SdBaseFile/*, public Print*/ {
|
||||
public:
|
||||
// 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);
|
||||
public:
|
||||
SdFile() {}
|
||||
SdFile(const char* name, uint8_t oflag);
|
||||
#if ARDUINO >= 100
|
||||
|
|
@ -43,6 +60,9 @@ class SdFile : public SdBaseFile/*, public Print*/ {
|
|||
void write(uint8_t b);
|
||||
#endif
|
||||
|
||||
bool openFilteredGcode(SdBaseFile* dirFile, const char* path);
|
||||
int16_t readFilteredGcode();
|
||||
bool seekSetFilteredGcode(uint32_t pos);
|
||||
int16_t write(const void* buf, uint16_t nbyte);
|
||||
void write(const char* str);
|
||||
void write_P(PGM_P str);
|
||||
|
|
@ -51,4 +71,4 @@ class SdFile : public SdBaseFile/*, public Print*/ {
|
|||
#endif // SdFile_h
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@
|
|||
*/
|
||||
union cache_t {
|
||||
/** Used to access cached file data blocks. */
|
||||
uint8_t data[512];
|
||||
uint8_t data[512 + 1]; // abuse the last byte for saving '\n' - ugly optimization of read_filtered's inner skipping loop
|
||||
/** Used to access cached FAT16 entries. */
|
||||
uint16_t fat16[256];
|
||||
/** Used to access cached FAT32 entries. */
|
||||
|
|
@ -119,6 +119,7 @@ class SdVolume {
|
|||
bool dbgFat(uint32_t n, uint32_t* v) {return fatGet(n, v);}
|
||||
//------------------------------------------------------------------------------
|
||||
private:
|
||||
friend class SdFile;
|
||||
// Allow SdBaseFile access to SdVolume private data.
|
||||
friend class SdBaseFile;
|
||||
|
||||
|
|
@ -211,4 +212,4 @@ class SdVolume {
|
|||
#endif // ALLOW_DEPRECATED_FUNCTIONS
|
||||
};
|
||||
#endif // SdVolume
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -231,7 +231,7 @@ static void finISR(timer16_Sequence_t timer)
|
|||
#endif
|
||||
}
|
||||
|
||||
static boolean isTimerActive(timer16_Sequence_t timer)
|
||||
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++) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
#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_write_byte((uint8_t*)EEPROM_SPOOL_JOIN, (uint8_t)EEPROM::Enabled);
|
||||
} else {
|
||||
eeprom_write_byte((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 >= 4) currentMMUSlot = 0;
|
||||
else currentMMUSlot++;
|
||||
|
||||
SERIAL_ECHOPGM(" -> ");
|
||||
SERIAL_ECHOLN((int)currentMMUSlot);
|
||||
|
||||
return currentMMUSlot;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
/// @file
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include "eeprom.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
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
#include "Tcodes.h"
|
||||
#include "SpoolJoin.h"
|
||||
#include "Marlin.h"
|
||||
#include "language.h"
|
||||
#include "messages.h"
|
||||
#include "mmu2.h"
|
||||
#include "stepper.h"
|
||||
#include "ultralcd.h"
|
||||
#include <avr/pgmspace.h>
|
||||
#include <ctype.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.");
|
||||
}
|
||||
|
||||
struct SChooseFromMenu {
|
||||
uint8_t slot:7;
|
||||
uint8_t loadToNozzle:1;
|
||||
inline constexpr SChooseFromMenu(uint8_t slot, bool loadToNozzle):slot(slot), loadToNozzle(loadToNozzle){}
|
||||
inline constexpr SChooseFromMenu():slot(0), loadToNozzle(false) { }
|
||||
};
|
||||
|
||||
SChooseFromMenu TCodeChooseFromMenu() {
|
||||
if (MMU2::mmu2.Enabled()) {
|
||||
return SChooseFromMenu( choose_menu_P(_T(MSG_SELECT_FILAMENT), _T(MSG_FILAMENT)), true );
|
||||
} else {
|
||||
return SChooseFromMenu( choose_menu_P(_T(MSG_SELECT_EXTRUDER), _T(MSG_EXTRUDER)), false );
|
||||
}
|
||||
}
|
||||
|
||||
void TCodes(char *const strchr_pointer, 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'){
|
||||
// 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_EXTRUDER), _T(MSG_EXTRUDER)));
|
||||
}
|
||||
} 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 {
|
||||
SChooseFromMenu selectedSlot;
|
||||
if (strchr_pointer[index] == '?') {
|
||||
selectedSlot = TCodeChooseFromMenu();
|
||||
/*} else if (MMU2::mmu2.Enabled() && SpoolJoin::spooljoin.isSpoolJoinEnabled()) {
|
||||
// TODO: What if the next slot has no filament?
|
||||
selectedSlot.slot = SpoolJoin::spooljoin.nextSlot();*/
|
||||
} else {
|
||||
selectedSlot.slot = codeValue;
|
||||
}
|
||||
st_synchronize();
|
||||
|
||||
if (MMU2::mmu2.Enabled()) {
|
||||
if (selectedSlot.slot == 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(selectedSlot.slot);
|
||||
}
|
||||
#endif // defined(MMU_HAS_CUTTER) && defined(MMU_ALWAYS_CUT)
|
||||
if (selectedSlot.loadToNozzle){ // for single material usage with mmu
|
||||
MMU2::mmu2.load_filament_to_nozzle(selectedSlot.slot);
|
||||
} else {
|
||||
MMU2::mmu2.tool_change(selectedSlot.slot);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (selectedSlot.slot >= EXTRUDERS) {
|
||||
SERIAL_ECHO_START;
|
||||
SERIAL_ECHO('T');
|
||||
SERIAL_ECHOLN(selectedSlot.slot + '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_ECHO_START;
|
||||
SERIAL_ECHORPGM(_n("Active Extruder: ")); ////MSG_ACTIVE_EXTRUDER
|
||||
SERIAL_ECHOLN(active_extruder + '0'); // this is not changed in our FW at all, can be optimized away
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
/// @file
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
void TCodes(char * const strchr_pointer, uint8_t codeValue);
|
||||
|
|
@ -64,5 +64,24 @@ 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>;
|
||||
|
|
|
|||
|
|
@ -20,10 +20,12 @@ public:
|
|||
Timer();
|
||||
void start();
|
||||
void stop(){m_isRunning = false;}
|
||||
bool running(){return m_isRunning;}
|
||||
bool expired(T msPeriod);
|
||||
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
|
||||
protected:
|
||||
T started(){return m_started;}
|
||||
T started()const {return m_started;}
|
||||
private:
|
||||
bool m_isRunning;
|
||||
T m_started;
|
||||
|
|
|
|||
|
|
@ -1,95 +0,0 @@
|
|||
//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)
|
||||
{
|
||||
printf_P(PSTR("adc_init\n"));
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
#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,15 +1,8 @@
|
|||
//adc.h
|
||||
#ifndef _ADC_H
|
||||
#define _ADC_H
|
||||
#pragma once
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "config.h"
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif //defined(__cplusplus)
|
||||
|
||||
/*
|
||||
http://resnet.uoregon.edu/~gurney_j/jmpc/bitwise.html
|
||||
*/
|
||||
|
|
@ -22,24 +15,11 @@ http://resnet.uoregon.edu/~gurney_j/jmpc/bitwise.html
|
|||
# error "ADC_CHAN_MSK oes not match ADC_CHAN_CNT"
|
||||
#endif
|
||||
|
||||
extern uint8_t adc_state;
|
||||
extern uint8_t adc_count;
|
||||
extern uint16_t adc_values[ADC_CHAN_CNT];
|
||||
extern uint16_t adc_sim_mask;
|
||||
#define VOLT_DIV_REF 5 //[V]
|
||||
|
||||
extern volatile uint8_t adc_channel;
|
||||
extern volatile uint16_t adc_values[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
|
||||
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; }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
#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)
|
||||
{
|
||||
__uint24 ret;
|
||||
asm (
|
||||
"rcall .\n"
|
||||
"pop %A0\n"
|
||||
"pop %B0\n"
|
||||
"pop %C0\n"
|
||||
: "=&r" (ret)
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -1,10 +1,10 @@
|
|||
//backlight.cpp
|
||||
|
||||
#include "backlight.h"
|
||||
#include "macros.h"
|
||||
#include <avr/eeprom.h>
|
||||
#include <Arduino.h>
|
||||
#include "eeprom.h"
|
||||
#include "Marlin.h"
|
||||
#include "pins.h"
|
||||
#include "fastio.h"
|
||||
#include "Timer.h"
|
||||
|
|
@ -91,30 +91,22 @@ void backlight_init()
|
|||
backlightSupport = !READ(LCD_BL_PIN);
|
||||
if (!backlightSupport) return;
|
||||
|
||||
//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);
|
||||
|
||||
//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, 130);
|
||||
backlightLevel_LOW = eeprom_init_default_byte((uint8_t *)EEPROM_BACKLIGHT_LEVEL_LOW, 50);
|
||||
backlightTimer_period = eeprom_init_default_word((uint16_t *)EEPROM_BACKLIGHT_TIMEOUT, 10); // in seconds
|
||||
|
||||
SET_OUTPUT(LCD_BL_PIN);
|
||||
backlightTimer_reset();
|
||||
}
|
||||
|
||||
#else //LCD_BL_PIN
|
||||
|
||||
void force_bl_on(__attribute__((unused)) bool section_start) {}
|
||||
void force_bl_on(bool) {}
|
||||
void backlight_update() {}
|
||||
void backlight_init() {}
|
||||
void backlight_save() {}
|
||||
void backlight_wake(__attribute__((unused)) const uint8_t flashNo) {}
|
||||
void backlight_wake(const uint8_t) {}
|
||||
|
||||
#endif //LCD_BL_PIN
|
||||
#endif //LCD_BL_PIN
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@
|
|||
extern FILE _uartout;
|
||||
#define uartout (&_uartout)
|
||||
|
||||
extern void softReset();
|
||||
|
||||
void bootapp_print_vars(void)
|
||||
{
|
||||
fprintf_P(uartout, PSTR("boot_src_addr =0x%08lx\n"), boot_src_addr);
|
||||
|
|
@ -26,21 +28,11 @@ void bootapp_ram2flash(uint16_t rptr, uint16_t fptr, uint16_t size)
|
|||
boot_app_magic = BOOT_APP_MAGIC;
|
||||
boot_app_flags |= BOOT_APP_FLG_COPY;
|
||||
boot_app_flags |= BOOT_APP_FLG_ERASE;
|
||||
/* uint16_t ui; for (ui = 0; ui < size; ui++)
|
||||
{
|
||||
uint8_t uc = ram_array[ui+rptr];
|
||||
if (pgm_read_byte(ui+fptr) & uc != uc)
|
||||
{
|
||||
boot_app_flags |= BOOT_APP_FLG_ERASE;
|
||||
break;
|
||||
}
|
||||
}*/
|
||||
boot_copy_size = (uint16_t)size;
|
||||
boot_src_addr = (uint32_t)rptr;
|
||||
boot_dst_addr = (uint32_t)fptr;
|
||||
bootapp_print_vars();
|
||||
wdt_enable(WDTO_15MS);
|
||||
while(1);
|
||||
softReset();
|
||||
}
|
||||
|
||||
void bootapp_reboot_user0(uint8_t reserved)
|
||||
|
|
@ -50,6 +42,5 @@ void bootapp_reboot_user0(uint8_t reserved)
|
|||
boot_app_flags = BOOT_APP_FLG_USER0;
|
||||
boot_reserved = reserved;
|
||||
bootapp_print_vars();
|
||||
wdt_enable(WDTO_15MS);
|
||||
while(1);
|
||||
softReset();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@
|
|||
#define BOOTAPP_H
|
||||
|
||||
#include "config.h"
|
||||
#include <avr/io.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
|
||||
#define RAMSIZE 0x2000
|
||||
#define ram_array ((uint8_t*)(0))
|
||||
#define RAMSIZE (RAMEND+1-RAMSTART)
|
||||
#define boot_src_addr (*((uint32_t*)(RAMSIZE - 16)))
|
||||
#define boot_dst_addr (*((uint32_t*)(RAMSIZE - 12)))
|
||||
#define boot_copy_size (*((uint16_t*)(RAMSIZE - 8)))
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -1,66 +1,81 @@
|
|||
#ifndef CARDREADER_H
|
||||
#define CARDREADER_H
|
||||
|
||||
#define SDSUPPORT
|
||||
|
||||
#ifdef SDSUPPORT
|
||||
|
||||
#define MAX_DIR_DEPTH 10
|
||||
#define MAX_DIR_DEPTH 6
|
||||
|
||||
#include "SdFile.h"
|
||||
enum LsAction {LS_SerialPrint,LS_Count,LS_GetFilename};
|
||||
class CardReader
|
||||
{
|
||||
public:
|
||||
CardReader();
|
||||
|
||||
void initsd();
|
||||
enum LsAction : uint8_t
|
||||
{
|
||||
LS_SerialPrint,
|
||||
LS_Count,
|
||||
LS_GetFilename,
|
||||
};
|
||||
struct ls_param
|
||||
{
|
||||
bool LFN : 1;
|
||||
bool timestamp : 1;
|
||||
inline ls_param():LFN(0), timestamp(0) { }
|
||||
inline ls_param(bool LFN, bool timestamp):LFN(LFN), timestamp(timestamp) { }
|
||||
} __attribute__((packed));
|
||||
|
||||
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 openFile(const char* name,bool read,bool replace_current=true);
|
||||
void openFileWrite(const char* name);
|
||||
void openFileReadFilteredGcode(const char* name, bool replace_current = false);
|
||||
void openLogFile(const char* name);
|
||||
void removeFile(const char* name);
|
||||
void closefile(bool store_location=false);
|
||||
void release();
|
||||
void startFileprint();
|
||||
uint32_t getFileSize();
|
||||
void getStatus();
|
||||
void getStatus(bool arg_P);
|
||||
void printingHasFinished();
|
||||
|
||||
void getfilename(uint16_t nr, const char* const match=NULL);
|
||||
void getfilename_simple(uint32_t position, const char * const match = NULL);
|
||||
void getfilename_simple(uint16_t entry, 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);
|
||||
uint16_t getWorkDirDepth();
|
||||
uint8_t getWorkDirDepth();
|
||||
|
||||
|
||||
void ls();
|
||||
void chdir(const char * relpath);
|
||||
void ls(ls_param params);
|
||||
bool chdir(const char * relpath, bool doPresort);
|
||||
void updir();
|
||||
void setroot();
|
||||
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);
|
||||
#if SDSORT_GCODE
|
||||
FORCE_INLINE void setSortOn(bool b) { sort_alpha = b; presort(); }
|
||||
FORCE_INLINE void setSortFolders(int i) { sort_folders = i; presort(); }
|
||||
//FORCE_INLINE void setSortReverse(bool b) { sort_reverse = b; }
|
||||
#endif
|
||||
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(); }
|
||||
FORCE_INLINE bool eof() { return sdpos>=filesize ;};
|
||||
FORCE_INLINE int16_t get() { sdpos = file.curPosition();return (int16_t)file.read();};
|
||||
FORCE_INLINE void setIndex(long index) {sdpos = index;file.seekSet(index);};
|
||||
bool eof() { return sdpos>=filesize; }
|
||||
FORCE_INLINE int16_t getFilteredGcodeChar()
|
||||
{
|
||||
int16_t c = (int16_t)file.readFilteredGcode();
|
||||
sdpos = file.curPosition();
|
||||
return c;
|
||||
};
|
||||
void setIndex(long index) {sdpos = index;file.seekSetFilteredGcode(index);};
|
||||
FORCE_INLINE uint8_t percentDone(){if(!isFileOpen()) return 0; if(filesize) return sdpos/((filesize+99)/100); else return 0;};
|
||||
FORCE_INLINE char* getWorkDirName(){workDir.getFilename(filename);return filename;};
|
||||
FORCE_INLINE uint32_t get_sdpos() { if (!isFileOpen()) return 0; else return(sdpos); };
|
||||
|
|
@ -74,58 +89,27 @@ public:
|
|||
bool logging;
|
||||
bool sdprinting ;
|
||||
bool cardOK ;
|
||||
char filename[13];
|
||||
uint16_t modificationTime, modificationDate;
|
||||
uint32_t cluster, position;
|
||||
char filename[FILENAME_LENGTH];
|
||||
// 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;
|
||||
uint32_t /* cluster, */ position;
|
||||
char longFilename[LONG_FILENAME_LENGTH];
|
||||
bool filenameIsDir;
|
||||
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];
|
||||
private:
|
||||
SdFile root,*curDir,workDir,workDirParents[MAX_DIR_DEPTH];
|
||||
uint16_t workDirDepth;
|
||||
uint8_t workDirDepth;
|
||||
|
||||
// Sort files and folders alphabetically.
|
||||
#ifdef SDCARD_SORT_ALPHA
|
||||
uint16_t sort_count; // Count of sorted items in the current directory
|
||||
#if SDSORT_GCODE
|
||||
bool sort_alpha; // Flag to enable / disable the feature
|
||||
int sort_folders; // Flag to enable / disable folder sorting
|
||||
//bool sort_reverse; // Flag to enable / disable reverse sorting
|
||||
#endif
|
||||
|
||||
// By default the sort index is static
|
||||
#if SDSORT_DYNAMIC_RAM
|
||||
uint8_t *sort_order;
|
||||
#else
|
||||
uint8_t sort_order[SDSORT_LIMIT];
|
||||
#endif
|
||||
// Cache filenames to speed up SD menus.
|
||||
#if SDSORT_USES_RAM
|
||||
|
||||
// If using dynamic ram for names, allocate on the heap.
|
||||
#if SDSORT_CACHE_NAMES
|
||||
#if SDSORT_DYNAMIC_RAM
|
||||
char **sortshort, **sortnames;
|
||||
#else
|
||||
char sortshort[SDSORT_LIMIT][FILENAME_LENGTH];
|
||||
char sortnames[SDSORT_LIMIT][FILENAME_LENGTH];
|
||||
#endif
|
||||
#elif !SDSORT_USES_STACK
|
||||
char sortnames[SDSORT_LIMIT][FILENAME_LENGTH];
|
||||
uint16_t modification_time[SDSORT_LIMIT];
|
||||
uint16_t modification_date[SDSORT_LIMIT];
|
||||
#endif
|
||||
|
||||
// Folder sorting uses an isDir array when caching items.
|
||||
#if HAS_FOLDER_SORTING
|
||||
#if SDSORT_DYNAMIC_RAM
|
||||
uint8_t *isDir;
|
||||
#elif (SDSORT_CACHE_NAMES) || !(SDSORT_USES_STACK)
|
||||
uint8_t isDir[(SDSORT_LIMIT + 7) >> 3];
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif // SDSORT_USES_RAM
|
||||
uint16_t sort_entries[SDSORT_LIMIT];
|
||||
uint16_t lastSortedFilePosition;
|
||||
|
||||
#endif // SDCARD_SORT_ALPHA
|
||||
|
||||
|
|
@ -144,17 +128,13 @@ private:
|
|||
char filenames[SD_PROCEDURE_DEPTH][MAXPATHNAMELENGTH];
|
||||
uint32_t filesize;
|
||||
//int16_t n;
|
||||
unsigned long autostart_atmillis;
|
||||
ShortTimer 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.
|
||||
|
||||
LsAction lsAction; //stored for recursion.
|
||||
int16_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;
|
||||
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.
|
||||
|
||||
void diveSubfolder (const char *fileName, SdFile& dir);
|
||||
void lsDive(const char *prepend, SdFile parent, const char * const match=NULL);
|
||||
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());
|
||||
#ifdef SDCARD_SORT_ALPHA
|
||||
void flush_presort();
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
#include <util/atomic.h>
|
||||
#include "cmdqueue.h"
|
||||
#include "cardreader.h"
|
||||
#include "ultralcd.h"
|
||||
|
||||
extern bool Stopped;
|
||||
#include "Prusa_farm.h"
|
||||
|
||||
// Reserve BUFSIZE lines of length MAX_CMD_SIZE plus CMDBUFFER_RESERVE_FRONT.
|
||||
char cmdbuffer[BUFSIZE * (MAX_CMD_SIZE + 1) + CMDBUFFER_RESERVE_FRONT];
|
||||
|
|
@ -18,17 +18,16 @@ int buflen = 0;
|
|||
// Therefore don't remove the command from the queue in the loop() function.
|
||||
bool cmdbuffer_front_already_processed = false;
|
||||
|
||||
// Used for temporarely preventing accidental adding of Serial commands to the queue.
|
||||
// For now only check_file and the fancheck pause use this.
|
||||
bool cmdqueue_serial_disabled = false;
|
||||
|
||||
int serial_count = 0; //index of character read from serial line
|
||||
boolean comment_mode = false;
|
||||
bool comment_mode = false;
|
||||
char *strchr_pointer; // just a pointer to find chars in the command string like X, Y, Z, E, etc
|
||||
|
||||
unsigned long TimeSent = _millis();
|
||||
unsigned long TimeNow = _millis();
|
||||
|
||||
long gcode_N = 0;
|
||||
ShortTimer serialTimeoutTimer;
|
||||
long gcode_LastN = 0;
|
||||
long Stopped_gcode_LastN = 0;
|
||||
|
||||
uint32_t sdpos_atomic = 0;
|
||||
|
||||
|
||||
|
|
@ -91,14 +90,19 @@ bool cmdqueue_pop_front()
|
|||
|
||||
void cmdqueue_reset()
|
||||
{
|
||||
bufindr = 0;
|
||||
bufindw = 0;
|
||||
buflen = 0;
|
||||
while (buflen)
|
||||
{
|
||||
// printf_P(PSTR("dumping: \"%s\" of type %u\n"), cmdbuffer+bufindr+CMDHDRSIZE, CMDBUFFER_CURRENT_TYPE);
|
||||
ClearToSend();
|
||||
cmdqueue_pop_front();
|
||||
}
|
||||
bufindr = 0;
|
||||
bufindw = 0;
|
||||
|
||||
//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?
|
||||
|
|
@ -149,7 +153,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 cmdqueue_could_enqueue_back(size_t len_asked, bool atomic_update = false)
|
||||
static bool __attribute__((noinline)) cmdqueue_could_enqueue_back(size_t len_asked)
|
||||
{
|
||||
// MAX_CMD_SIZE has to accommodate the zero terminator.
|
||||
if (len_asked >= MAX_CMD_SIZE)
|
||||
|
|
@ -159,61 +163,29 @@ static bool cmdqueue_could_enqueue_back(size_t len_asked, bool atomic_update = f
|
|||
// Full buffer.
|
||||
return false;
|
||||
|
||||
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;
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -362,26 +334,10 @@ void repeatcommand_front()
|
|||
cmdbuffer_front_already_processed = true;
|
||||
}
|
||||
|
||||
bool is_buffer_empty()
|
||||
{
|
||||
if (buflen == 0) return true;
|
||||
else return false;
|
||||
}
|
||||
|
||||
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, true))
|
||||
if (! cmdqueue_could_enqueue_back(MAX_CMD_SIZE - 1))
|
||||
return;
|
||||
|
||||
if (MYSERIAL.available() == RX_BUFFER_SIZE - 1) { //compare number of chars buffered in rx buffer with rx buffer size
|
||||
|
|
@ -390,17 +346,11 @@ void get_command()
|
|||
}
|
||||
|
||||
// start of serial line processing loop
|
||||
while ((MYSERIAL.available() > 0 && !saved_printing) || (MYSERIAL.available() > 0 && isPrintPaused)) { //is print is saved (crash detection or filament detection), dont process data from serial line
|
||||
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();
|
||||
/* if (selectedSerialPort == 1)
|
||||
{
|
||||
selectedSerialPort = 0;
|
||||
MYSERIAL.write(serial_char); // for debuging serial line 2 in farm_mode
|
||||
selectedSerialPort = 1;
|
||||
} */ //RP - removed
|
||||
TimeSent = _millis();
|
||||
TimeNow = _millis();
|
||||
|
||||
serialTimeoutTimer.start();
|
||||
|
||||
if (serial_char < 0)
|
||||
// Ignore extended ASCII characters. These characters have no meaning in the G-code apart from the file names
|
||||
|
|
@ -416,22 +366,23 @@ void get_command()
|
|||
comment_mode = false; //for new command
|
||||
return;
|
||||
}
|
||||
cmdbuffer[bufindw+serial_count+CMDHDRSIZE] = 0; //terminate string
|
||||
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)
|
||||
|
||||
if(!comment_mode){
|
||||
|
||||
gcode_N = 0;
|
||||
long gcode_N = -1; // seen line number
|
||||
|
||||
// Line numbers must be first in buffer
|
||||
if (*cmd_head == 'N') {
|
||||
|
||||
if ((strstr(cmdbuffer+bufindw+CMDHDRSIZE, "PRUSA") == NULL) &&
|
||||
(cmdbuffer[bufindw+CMDHDRSIZE] == '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;
|
||||
|
||||
// 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.
|
||||
// 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.
|
||||
SERIAL_ERROR_START;
|
||||
SERIAL_ERRORRPGM(_n("Line Number is not Last Line Number+1, Last Line: "));////MSG_ERR_LINE_NO
|
||||
SERIAL_ERRORLN(gcode_LastN);
|
||||
|
|
@ -441,13 +392,13 @@ void get_command()
|
|||
return;
|
||||
}
|
||||
|
||||
if((strchr_pointer = strchr(cmdbuffer+bufindw+CMDHDRSIZE, '*')) != NULL)
|
||||
if((strchr_pointer = strchr(cmd_start, '*')) != NULL)
|
||||
{
|
||||
byte checksum = 0;
|
||||
char *p = cmdbuffer+bufindw+CMDHDRSIZE;
|
||||
char *p = cmd_head;
|
||||
while (p != strchr_pointer)
|
||||
checksum = checksum^(*p++);
|
||||
if (int(strtol(strchr_pointer+1, NULL, 10)) != int(checksum)) {
|
||||
if (code_value_short() != (int16_t)checksum) {
|
||||
SERIAL_ERROR_START;
|
||||
SERIAL_ERRORRPGM(_n("checksum mismatch, Last Line: "));////MSG_ERR_CHECKSUM_MISMATCH
|
||||
SERIAL_ERRORLN(gcode_LastN);
|
||||
|
|
@ -467,54 +418,80 @@ 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;
|
||||
}
|
||||
// if we don't receive 'N' but still see '*'
|
||||
if ((cmdbuffer[bufindw + CMDHDRSIZE] != 'N') && (cmdbuffer[bufindw + CMDHDRSIZE] != '$') && (strchr(cmdbuffer+bufindw+CMDHDRSIZE, '*') != NULL))
|
||||
else
|
||||
{
|
||||
// move cmd_start past all spaces
|
||||
while (*cmd_start == ' ') ++cmd_start;
|
||||
|
||||
SERIAL_ERROR_START;
|
||||
SERIAL_ERRORRPGM(_n("No Line Number with checksum, Last Line: "));////MSG_ERR_NO_LINENUMBER_WITH_CHECKSUM
|
||||
SERIAL_ERRORLN(gcode_LastN);
|
||||
FlushSerialRequestResend();
|
||||
// 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, 2);
|
||||
|
||||
// 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') && !(IS_SD_PRINTING))
|
||||
usb_timer.start();
|
||||
|
||||
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_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
|
||||
|
||||
//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.
|
||||
// Command is complete: store the current line into buffer, move to the next line.
|
||||
|
||||
// Store type of entry
|
||||
cmdbuffer[bufindw] = gcode_N ? CMDBUFFER_CURRENT_TYPE_USB_WITH_LINENR : CMDBUFFER_CURRENT_TYPE_USB;
|
||||
cmdbuffer[bufindw] = gcode_N >= 0 ? 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(cmdbuffer+bufindw+CMDHDRSIZE);
|
||||
SERIAL_ECHO(cmd_start);
|
||||
SERIAL_ECHOLNPGM("");
|
||||
#endif /* CMDBUFFER_DEBUG */
|
||||
bufindw += strlen(cmdbuffer+bufindw+CMDHDRSIZE) + (1 + CMDHDRSIZE);
|
||||
|
||||
// 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;
|
||||
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);
|
||||
|
|
@ -524,7 +501,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, true))
|
||||
if (MYSERIAL.available() == 0 || ! cmdqueue_could_enqueue_back(MAX_CMD_SIZE-1))
|
||||
return;
|
||||
} // end of "end of line" processing
|
||||
else {
|
||||
|
|
@ -534,26 +511,15 @@ void get_command()
|
|||
}
|
||||
} // end of serial line processing loop
|
||||
|
||||
if(farm_mode){
|
||||
TimeNow = _millis();
|
||||
if ( ((TimeNow - TimeSent) > 800) && (serial_count > 0) ) {
|
||||
cmdbuffer[bufindw+serial_count+CMDHDRSIZE] = 0;
|
||||
|
||||
bufindw += strlen(cmdbuffer+bufindw+CMDHDRSIZE) + (1 + CMDHDRSIZE);
|
||||
if (bufindw == sizeof(cmdbuffer))
|
||||
bufindw = 0;
|
||||
++ buflen;
|
||||
|
||||
serial_count = 0;
|
||||
|
||||
SERIAL_ECHOPGM("TIMEOUT:");
|
||||
//memset(cmdbuffer, 0 , sizeof(cmdbuffer));
|
||||
return;
|
||||
}
|
||||
if (serial_count > 0 && serialTimeoutTimer.expired(farm_mode ? 800 : 2000)) {
|
||||
comment_mode = false;
|
||||
serial_count = 0;
|
||||
SERIAL_ECHOLNPGM("RX timeout");
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef SDSUPPORT
|
||||
if(!card.sdprinting || serial_count!=0){
|
||||
if(!card.sdprinting || !card.isFileOpen() || serial_count!=0){
|
||||
// If there is a half filled buffer from serial line, wait until return before
|
||||
// continuing with the serial line.
|
||||
return;
|
||||
|
|
@ -575,15 +541,14 @@ void get_command()
|
|||
sd_count.value = 0;
|
||||
// Reads whole lines from the SD card. Never leaves a half-filled line in the cmdbuffer.
|
||||
while( !card.eof() && !stop_buffering) {
|
||||
int16_t n=card.get();
|
||||
int16_t n=card.getFilteredGcodeChar();
|
||||
char serial_char = (char)n;
|
||||
if(serial_char == '\n' ||
|
||||
serial_char == '\r' ||
|
||||
((serial_char == '#' || serial_char == ':') && comment_mode == false) ||
|
||||
serial_count >= (MAX_CMD_SIZE - 1) || n==-1)
|
||||
{
|
||||
if(card.eof()) break;
|
||||
|
||||
if( serial_char == '\n'
|
||||
|| serial_char == '\r'
|
||||
|| serial_char == '#'
|
||||
|| serial_count >= (MAX_CMD_SIZE - 1)
|
||||
|| n==-1
|
||||
){
|
||||
if(serial_char=='#')
|
||||
stop_buffering=true;
|
||||
|
||||
|
|
@ -592,14 +557,13 @@ 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 lenght of the already read empty lines and comments will be added
|
||||
// so that the length of the already read empty lines and comments will be added
|
||||
// to the following non-empty line.
|
||||
comment_mode = false;
|
||||
continue; //if 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
|
||||
// to be inside the active queue.
|
||||
sd_count.value = (card.get_sdpos()+1) - sdpos_atomic;
|
||||
sd_count.value = card.get_sdpos() - sdpos_atomic;
|
||||
cmdbuffer[bufindw] = CMDBUFFER_CURRENT_TYPE_SDCARD;
|
||||
cmdbuffer[bufindw+1] = sd_count.lohi.lo;
|
||||
cmdbuffer[bufindw+2] = sd_count.lohi.hi;
|
||||
|
|
@ -611,10 +575,10 @@ void get_command()
|
|||
// MYSERIAL.print(sd_count.value, DEC);
|
||||
// SERIAL_ECHOPGM(") ");
|
||||
// SERIAL_ECHOLN(cmdbuffer+bufindw+CMDHDRSIZE);
|
||||
// SERIAL_ECHOPGM("cmdbuffer:");
|
||||
// MYSERIAL.print(cmdbuffer);
|
||||
// SERIAL_ECHOPGM("buflen:");
|
||||
// MYSERIAL.print(buflen+1);
|
||||
// SERIAL_ECHOPGM("cmdbuffer:");
|
||||
// MYSERIAL.print(cmdbuffer);
|
||||
// SERIAL_ECHOPGM("buflen:");
|
||||
// MYSERIAL.print(buflen+1);
|
||||
sd_count.value = 0;
|
||||
|
||||
cli();
|
||||
|
|
@ -624,21 +588,24 @@ void get_command()
|
|||
// or a 115200 Bd serial line receive interrupt, which will not trigger faster than 12kHz.
|
||||
++ buflen;
|
||||
bufindw += len;
|
||||
sdpos_atomic = card.get_sdpos()+1;
|
||||
sdpos_atomic = card.get_sdpos();
|
||||
if (bufindw == sizeof(cmdbuffer))
|
||||
bufindw = 0;
|
||||
sei();
|
||||
|
||||
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, true))
|
||||
if (! cmdqueue_could_enqueue_back(MAX_CMD_SIZE-1))
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(serial_char == ';') comment_mode = true;
|
||||
else if(!comment_mode) cmdbuffer[bufindw+CMDHDRSIZE+serial_count++] = serial_char;
|
||||
// there are no comments coming from the filtered file
|
||||
cmdbuffer[bufindw+CMDHDRSIZE+serial_count++] = serial_char;
|
||||
}
|
||||
}
|
||||
if(card.eof())
|
||||
|
|
@ -649,6 +616,10 @@ 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];
|
||||
|
|
@ -666,10 +637,7 @@ void get_command()
|
|||
card.checkautostart(true);
|
||||
|
||||
if (farm_mode)
|
||||
{
|
||||
prusa_statistics(6);
|
||||
lcd_commands_type = LcdCommands::FarmModeConfirm;
|
||||
}
|
||||
prusa_statistics(6);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ extern char cmdbuffer[BUFSIZE * (MAX_CMD_SIZE + 1) + CMDBUFFER_RESERVE_FRONT];
|
|||
extern size_t bufindr;
|
||||
extern int buflen;
|
||||
extern bool cmdbuffer_front_already_processed;
|
||||
extern bool cmdqueue_serial_disabled;
|
||||
|
||||
// Type of a command, which is to be executed right now.
|
||||
#define CMDBUFFER_CURRENT_TYPE (cmdbuffer[bufindr])
|
||||
|
|
@ -48,15 +49,10 @@ extern bool cmdbuffer_front_already_processed;
|
|||
extern uint32_t sdpos_atomic;
|
||||
|
||||
extern int serial_count;
|
||||
extern boolean comment_mode;
|
||||
extern bool comment_mode;
|
||||
extern char *strchr_pointer;
|
||||
|
||||
extern unsigned long TimeSent;
|
||||
extern unsigned long TimeNow;
|
||||
|
||||
extern long gcode_N;
|
||||
extern long gcode_LastN;
|
||||
extern long Stopped_gcode_LastN;
|
||||
|
||||
extern bool cmdqueue_pop_front();
|
||||
extern void cmdqueue_reset();
|
||||
|
|
@ -65,30 +61,18 @@ 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();
|
||||
extern void enquecommand(const char *cmd, bool from_progmem);
|
||||
extern void enquecommand_front(const char *cmd, bool from_progmem);
|
||||
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 bool is_buffer_empty();
|
||||
extern void get_command();
|
||||
extern uint16_t cmdqueue_calc_sd_length();
|
||||
|
||||
// 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(const char *code) { return (strchr_pointer = strstr(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(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,13 +2,16 @@
|
|||
#define _CONFIG_H
|
||||
|
||||
|
||||
#include "Configuration_prusa.h"
|
||||
#include "Configuration_var.h"
|
||||
#include "pins.h"
|
||||
|
||||
#define IR_SENSOR_ANALOG (defined(VOLT_IR_PIN) && defined(IR_SENSOR))
|
||||
#if (defined(VOLT_IR_PIN) && defined(IR_SENSOR))
|
||||
// TODO: IR_SENSOR_ANALOG currently disabled as being incompatible with the new thermal regulation
|
||||
// # define IR_SENSOR_ANALOG
|
||||
#endif
|
||||
|
||||
//ADC configuration
|
||||
#if !IR_SENSOR_ANALOG
|
||||
#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)
|
||||
|
|
@ -18,10 +21,9 @@
|
|||
#define ADC_CHAN_CNT 8 //number of used channels)
|
||||
#endif //!IR_SENSOR_ANALOG
|
||||
#define ADC_OVRSAMPL 16 //oversampling multiplier
|
||||
#define ADC_CALLBACK adc_ready //callback function ()
|
||||
#define ADC_CALLBACK adc_callback //callback function ()
|
||||
|
||||
//SWI2C configuration
|
||||
#define SWI2C
|
||||
//#define SWI2C_SDA 20 //SDA on P3
|
||||
//#define SWI2C_SCL 21 //SCL on P3
|
||||
#define SWI2C_A8
|
||||
|
|
@ -29,12 +31,23 @@
|
|||
#define SWI2C_TMO 2048 //2048 cycles timeout
|
||||
|
||||
//PAT9125 configuration
|
||||
#define PAT9125_SWI2C
|
||||
#ifdef SWI2C_SCL
|
||||
#define PAT9125_SWI2C // software I2C mode
|
||||
#else
|
||||
#define PAT9125_I2C // hardware I2C mode
|
||||
#endif
|
||||
|
||||
#define PAT9125_I2C_ADDR 0x75 //ID=LO
|
||||
//#define PAT9125_I2C_ADDR 0x79 //ID=HI
|
||||
//#define PAT9125_I2C_ADDR 0x73 //ID=NC
|
||||
#define PAT9125_XRES 0
|
||||
#define PAT9125_YRES 240
|
||||
#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.
|
||||
|
||||
//SM4 configuration
|
||||
#define SM4_DEFDELAY 500 //default step delay [us]
|
||||
|
|
@ -46,19 +59,73 @@
|
|||
#define TMC2130_SPCR SPI_SPCR(TMC2130_SPI_RATE, 1, 1, 1, 0)
|
||||
#define TMC2130_SPSR SPI_SPSR(TMC2130_SPI_RATE)
|
||||
|
||||
//W25X20CL configuration
|
||||
//pinout:
|
||||
#define W25X20CL_PIN_CS 32
|
||||
//spi:
|
||||
#define W25X20CL_SPI_RATE 0 // fosc/4 = 4MHz
|
||||
#define W25X20CL_SPCR SPI_SPCR(W25X20CL_SPI_RATE, 1, 1, 1, 0)
|
||||
#define W25X20CL_SPSR SPI_SPSR(W25X20CL_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 0 // primary language only
|
||||
#define LANG_MODE 1 // sec. language support
|
||||
#endif
|
||||
|
||||
#define LANG_SIZE_RESERVED 0x3000 // reserved space for secondary language (12288 bytes)
|
||||
#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
|
||||
|
||||
#if (LANG_SIZE_RESERVED % 256)
|
||||
#error "LANG_SIZE_RESERVED should be a multiple of a page size"
|
||||
#endif
|
||||
|
||||
//Community language support
|
||||
#define COMMUNITY_LANG_GROUP 1
|
||||
|
||||
#if (COMMUNITY_LANG_GROUP == 1)
|
||||
#define COMMUNITY_LANG_GROUP1_NL // Community Dutch language
|
||||
#define COMMUNITY_LANG_GROUP1_RO // Community Romanian language
|
||||
#define COMMUNITY_LANG_GROUP1_HU // Community Hungarian language
|
||||
#define COMMUNITY_LANG_GROUP1_HR // Community Croatian language
|
||||
#define COMMUNITY_LANG_GROUP1_SK // Community Slovak language
|
||||
#define COMMUNITY_LANG_GROUP1_SV // Community Swedish language
|
||||
#define COMMUNITY_LANG_GROUP1_NO // Community Norwegian language
|
||||
//#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_QR // Community new language //..use this as a template and replace 'QR'
|
||||
#endif //COMMUNITY_LANG_GROUP 2
|
||||
|
||||
#if (COMMUNITY_LANG_GROUP >=1 )
|
||||
#define COMMUNITY_LANGUAGE_SUPPORT
|
||||
#endif
|
||||
|
||||
// Sanity checks for correct configuration of XFLASH_DUMP options
|
||||
#if defined(XFLASH_DUMP) && !defined(XFLASH)
|
||||
#error "XFLASH_DUMP requires XFLASH support"
|
||||
#endif
|
||||
#if (defined(MENU_DUMP) || defined(EMERGENCY_DUMP)) && !defined(XFLASH_DUMP)
|
||||
#error "MENU_DUMP and EMERGENCY_DUMP require XFLASH_DUMP"
|
||||
#endif
|
||||
|
||||
// Support for serial dumps is mutually exclusive with XFLASH_DUMP features
|
||||
#if defined(EMERGENCY_DUMP) && defined(EMERGENCY_SERIAL_DUMP)
|
||||
#error "EMERGENCY_DUMP and EMERGENCY_SERIAL_DUMP are mutually exclusive"
|
||||
#endif
|
||||
#if defined(MENU_DUMP) && defined(MENU_SERIAL_DUMP)
|
||||
#error "MENU_DUMP and MENU_SERIAL_DUMP are mutually exclusive"
|
||||
#endif
|
||||
|
||||
// Reduce internal duplication
|
||||
#if defined(EMERGENCY_DUMP) || defined(EMERGENCY_SERIAL_DUMP)
|
||||
#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
|
||||
|
|
|
|||
|
|
@ -1,292 +0,0 @@
|
|||
//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;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
//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
|
||||
|
|
@ -11,57 +11,22 @@
|
|||
|
||||
#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()
|
||||
{
|
||||
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_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_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);
|
||||
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_byte(&(EEPROM_Sheets_base->active_sheet)) == EEPROM_EMPTY_VALUE)
|
||||
{
|
||||
eeprom_update_byte(&(EEPROM_Sheets_base->active_sheet), 0);
|
||||
|
|
@ -71,28 +36,38 @@ void eeprom_init()
|
|||
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);
|
||||
|
||||
for (uint_least8_t a = 0; a < sizeof(Sheet::name); ++a){
|
||||
eeprom_write(&(EEPROM_Sheets_base->s[i].name[a]), sheetName.c[a]);
|
||||
}
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
|
||||
if(!eeprom_is_sheet_initialized(eeprom_read_byte(&(EEPROM_Sheets_base->active_sheet))))
|
||||
{
|
||||
eeprom_switch_to_next_sheet();
|
||||
}
|
||||
check_babystep();
|
||||
|
||||
#ifdef PINDA_TEMP_COMP
|
||||
eeprom_init_default_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((uint8_t*)EEPROM_BED_CORRECTION_VALID, 1);
|
||||
eeprom_update_byte((uint8_t*)EEPROM_BED_CORRECTION_LEFT, 0);
|
||||
eeprom_update_byte((uint8_t*)EEPROM_BED_CORRECTION_RIGHT, 0);
|
||||
eeprom_update_byte((uint8_t*)EEPROM_BED_CORRECTION_FRONT, 0);
|
||||
eeprom_update_byte((uint8_t*)EEPROM_BED_CORRECTION_REAR, 0);
|
||||
}
|
||||
|
||||
//! @brief Get default sheet name for index
|
||||
|
|
@ -103,10 +78,10 @@ void eeprom_init()
|
|||
//! | 1 | Smooth2 |
|
||||
//! | 2 | Textur1 |
|
||||
//! | 3 | Textur2 |
|
||||
//! | 4 | Custom1 |
|
||||
//! | 5 | Custom2 |
|
||||
//! | 6 | Custom3 |
|
||||
//! | 7 | Custom4 |
|
||||
//! | 4 | Satin |
|
||||
//! | 5 | NylonPA |
|
||||
//! | 6 | Custom1 |
|
||||
//! | 7 | Custom2 |
|
||||
//!
|
||||
//! @param[in] index
|
||||
//! @param[out] sheetName
|
||||
|
|
@ -122,42 +97,23 @@ 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"));
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy_P(sheetName.c, PSTR("Custom"));
|
||||
}
|
||||
|
||||
switch (index)
|
||||
if (index <4 || index >5)
|
||||
{
|
||||
case 0:
|
||||
sheetName.c[6] = '1';
|
||||
break;
|
||||
case 1:
|
||||
sheetName.c[6] = '2';
|
||||
break;
|
||||
case 2:
|
||||
sheetName.c[6] = '1';
|
||||
break;
|
||||
case 3:
|
||||
sheetName.c[6] = '2';
|
||||
break;
|
||||
case 4:
|
||||
sheetName.c[6] = '1';
|
||||
break;
|
||||
case 5:
|
||||
sheetName.c[6] = '2';
|
||||
break;
|
||||
case 6:
|
||||
sheetName.c[6] = '3';
|
||||
break;
|
||||
case 7:
|
||||
sheetName.c[6] = '4';
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
sheetName.c[6] = '0' + ((index % 2)+1);
|
||||
sheetName.c[7] = '\0';
|
||||
}
|
||||
|
||||
sheetName.c[7] = '\0';
|
||||
}
|
||||
|
||||
//! @brief Get next initialized sheet
|
||||
|
|
@ -185,3 +141,97 @@ void eeprom_switch_to_next_sheet()
|
|||
sheet = eeprom_next_initialized_sheet(sheet);
|
||||
if (sheet >= 0) eeprom_update_byte(&(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(dst++, pgm_read_byte(src++));
|
||||
}
|
||||
}
|
||||
|
||||
void eeprom_toggle(uint8_t *__p) {
|
||||
eeprom_write_byte(__p, !eeprom_read_byte(__p));
|
||||
}
|
||||
|
||||
void __attribute__((noinline)) eeprom_increment_byte(uint8_t *__p) {
|
||||
eeprom_write_byte(__p, eeprom_read_byte(__p) + 1);
|
||||
}
|
||||
|
||||
void __attribute__((noinline)) eeprom_increment_word(uint16_t *__p) {
|
||||
eeprom_write_word(__p, eeprom_read_word(__p) + 1);
|
||||
}
|
||||
|
||||
void __attribute__((noinline)) eeprom_increment_dword(uint32_t *__p) {
|
||||
eeprom_write_dword(__p, eeprom_read_dword(__p) + 1);
|
||||
}
|
||||
|
||||
|
||||
void __attribute__((noinline)) eeprom_add_byte(uint8_t *__p, uint8_t add) {
|
||||
eeprom_write_byte(__p, eeprom_read_byte(__p) + add);
|
||||
}
|
||||
|
||||
void __attribute__((noinline)) eeprom_add_word(uint16_t *__p, uint16_t add) {
|
||||
eeprom_write_word(__p, eeprom_read_word(__p) + add);
|
||||
}
|
||||
|
||||
void __attribute__((noinline)) eeprom_add_dword(uint32_t *__p, uint32_t add) {
|
||||
eeprom_write_dword(__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(__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(__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(__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(__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(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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,13 @@
|
|||
|
||||
/**
|
||||
* @file
|
||||
* @author 3d-gussner
|
||||
*/
|
||||
/** \ingroup eeprom_table */
|
||||
|
||||
//! _This is a EEPROM table of currently implemented in Prusa firmware (dynamically generated from doxygen)._
|
||||
|
||||
|
||||
#ifndef EEPROM_H
|
||||
#define EEPROM_H
|
||||
|
||||
|
|
@ -10,8 +20,8 @@ typedef struct
|
|||
{
|
||||
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]
|
||||
uint8_t pinda_temp; //!< 0 .. 254 [°C]
|
||||
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
|
||||
} Sheet;
|
||||
|
||||
typedef struct
|
||||
|
|
@ -26,9 +36,341 @@ typedef struct
|
|||
#ifdef __cplusplus
|
||||
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
|
||||
|
||||
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.
|
||||
- Octoprint does support D-codes
|
||||
- _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: 1.0.2
|
||||
|
||||
---------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|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_BABYSTEP_X | ??? | ff ffh 65535 | Babystep for X axis _unsued_ | ??? | D3 Ax0ffc C2
|
||||
| 0x0FFA 4090 | uint16 | EEPROM_BABYSTEP_Y | ??? | ff ffh 65535 | Babystep for Y axis _unsued_ | ^ | D3 Ax0ffa C2
|
||||
| 0x0FF8 4088 | uint16 | EEPROM_BABYSTEP_Z | ??? | ff ffh 65535 | Babystep for Z axis _lagacy_ | ^ | 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 Temp Model calibration | ^ | ^
|
||||
| ^ | ^ | ^ | f0h 240 | ^ __P__ | needs Z calibration | ^ | ^
|
||||
| ^ | ^ | ^ | fah 250 | ^ | needs XYZ calibration | ^ | ^
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | Unknown (legacy) | ^ | ^
|
||||
| 0x0FF5 4085 | uint16 | EEPROM_BABYSTEP_Z0 | ??? | ff ffh 65535 | Babystep for Z ??? | ??? | D3 Ax0ff5 C2
|
||||
| 0x0FF1 4081 | unint32 | EEPROM_FILAMENTUSED | ??? | 00 00 00 00h 0 __S/P__| Filament used in meters | ??? | D3 Ax0ff1 C4
|
||||
| 0x0FED 4077 | unint32 | EEPROM_TOTALTIME | ??? | 00 00 00 00h 0 __S/P__| Total print time | ??? | 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_FARM_NUMBER | 000-999 | ff ffh / 000 __P__ | Prusa farm number _only 0-9 are allowed: 000-999_ | LCD menu | 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 | uchar | EEPROM_PRINT_FLAG | ??? | ??? | _unsued_ | ??? | 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_ | ??? | D3 Ax0fae C8
|
||||
| ^ | ^ | ^ | ^ | 00 00 00 00h | ^ | ^ | ^
|
||||
| 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 | Power Panic flag: __inactive__ | ??? | D3 Ax0fa5 C1
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | Power Panic flag: __active__ | ^ | ^
|
||||
| ^ | ^ | ^ | 02h 2 | ^ | Power Panic flag: __???__ | ^ | ^
|
||||
| 0x0F9D 3997 | float | EEPROM_UVLO_CURRENT_POSITION | ??? | ffh 255 | Power Panic position | ??? | D3 Ax0f9d C8
|
||||
| 0x0F95 3989 | char | EEPROM_FILENAME | ??? | ffh 255 | Power Panic Filename | ??? | D3 Ax0f95 C8
|
||||
| 0x0F91 3985 | unint32 | EEPROM_FILE_POSITION | ??? | ff ff ff ffh | Power Panic File Position | ??? | D3 Ax0f91 C4
|
||||
| 0x0F8D 3981 | float | EEPROM_UVLO_CURRENT_POSITION_Z | ??? | ff ff ff ffh | Power Panic Z Position | ^ | D3 Ax0f8d C4
|
||||
| 0x0F8C 3980 | ??? | EEPROM_UVLO_UNUSED_001 | ??? | ffh 255 | Power Panic _unused_ | ^ | D3 Ax0f8c C1
|
||||
| 0x0F8B 3979 | uint8 | EEPROM_UVLO_TARGET_BED | ??? | ffh 255 | Power Panic Bed temperature | ^ | D3 Ax0f8b C1
|
||||
| 0x0F89 3977 | uint16 | EEPROM_UVLO_FEEDRATE | ??? | ff ffh 65535 | Power Panic Feedrate | ^ | D3 Ax0f89 C2
|
||||
| 0x0F88 3976 | uint8 | EEPROM_UVLO_FAN_SPEED | ??? | ffh 255 | Power Panic Fan speed | ^ | 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_UVLO_MESH_BED_LEVELING | ??? | ff ffh 65535 | Power Panic Mesh Bed Leveling | ??? | D3 Ax0f75 C18
|
||||
| 0x0F73 3955 | uint16 | EEPROM_UVLO_Z_MICROSTEPS | ??? | ff ffh 65535 | Power Panic Z microsteps | ??? | D3 Ax0f73 C2
|
||||
| 0x0F72 3954 | uint8 | EEPROM_UVLO_E_ABS | ??? | ffh 255 | Power Panic ??? position | ??? | D3 Ax0f72 C1
|
||||
| 0x0F6E 3950 | float | EEPROM_UVLO_CURRENT_POSITION_E | ??? | ff ff ff ffh | Power Panic E position | ??? | D3 Ax0f6e C4
|
||||
| 0x0F6C 3948 | uint16 | EEPROM_UVLO_SAVED_SEGMENT_IDX | all | ff ffh 65535 | Power Panic index of multi-segment move | ??? | 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__ | Crashes detected on y axis | ??? | 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__ | Crashes detected on x axis | ??? | D3 Ax0f66 C1
|
||||
| 0x0F65 3941 | uint8 | EEPROM_FERROR_COUNT | 00h-ffh 0-255| ffh 255 __S/P__ | Filament sensor error counter | ??? | D3 Ax0f65 C1
|
||||
| 0x0F64 3940 | uint8 | EEPROM_POWER_COUNT | 00h-ffh 0-255| ffh 255 __S/P__ | Power failure counter | ??? | 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 | ??? | D3 Ax0f05 C2
|
||||
| 0x0F03 3843 | uint16 | EEPROM_CRASH_COUNT_Y_TOT | 0000-fffe | ff ffh __S/P__ | Total crashes on y axis | ??? | D3 Ax0f03 C2
|
||||
| 0x0F01 3841 | uint16 | EEPROM_FERROR_COUNT_TOT | 0000-fffe | ff ffh __S/P__ | Total filament sensor errors | ??? | D3 Ax0f01 C2
|
||||
| 0x0EFF 3839 | uint16 | EEPROM_POWER_COUNT_TOT | 0000-fffe | ff ffh __S/P__ | Total power failures | ??? | 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 | ??? | ^
|
||||
| ^ | ^ | ^ | 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 2 | ^ | Sound mode: __silent__ | ^ | ^
|
||||
| ^ | ^ | ^ | 03h 3 | ^ | Sound mode: __assist__ | ^ | ^
|
||||
| 0x0ED6 3798 | bool | EEPROM_SPOOL_JOIN | 01h 1 | ffh 255 | MMU2/s autodeplete: __on__ | ??? | D3 Ax0ed6 C1
|
||||
| ^ | ^ | ^ | 00h 0 | ^ | MMU2/s autodeplete: __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__ | LCD menu | ^
|
||||
| 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 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 | Power panic saved start position all-axis | ??? | D3 Ax0d37 C16
|
||||
| ^ | ^ | ^ | ??? | ^ | Power panic saved start position e-axis | ^ | D3 Ax0d43 C4
|
||||
| ^ | ^ | ^ | ??? | ^ | Power panic saved start position z-axis | ^ | D3 Ax0d3f C4
|
||||
| ^ | ^ | ^ | ??? | ^ | Power panic saved start position y-axis | ^ | D3 Ax0d3b C4
|
||||
| ^ | ^ | ^ | ??? | ^ | Power panic saved start position 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 | 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_TEMP_MODEL_ENABLE | 00h 0 | ff/00 | Temp model deactivated | Temp model | D3 Ax0d02 C1
|
||||
| ^ | ^ | ^ | 01h 1 | ^ | Temp model activated | ^ | ^
|
||||
| 0x0CFE 3326 | float | EEPROM_TEMP_MODEL_P | ??? | ff ff ff ffh | Temp model power (W) | Temp model | D3 Ax0cfe C4
|
||||
| 0x0CFA 3322 | float | EEPROM_TEMP_MODEL_C | ??? | ff ff ff ffh | Temp model capacitance (J/K) | Temp model | D3 Ax0cfa C4
|
||||
| 0x0CBA 3258 |float[16]| EEPROM_TEMP_MODEL_R | ??? | ff ff ff ffh | Temp model resistance (K/W) | Temp model | D3 Ax0cba C64
|
||||
| 0x0CB6 3254 | float | EEPROM_TEMP_MODEL_Ta_corr | ??? | ff ff ff ffh | Temp model ambient temperature correction (K) | Temp model | D3 Ax0cb6 C4
|
||||
| 0x0CB2 3250 | float | EEPROM_TEMP_MODEL_W | ??? | ff ff ff ffh | Temp model warning threshold (K/s) | Temp model | D3 Ax0cb2 C4
|
||||
| 0x0CAE 3246 | float | EEPROM_TEMP_MODEL_E | ??? | ff ff ff ffh | Temp model error threshold (K/s) | Temp 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 | ^ | Temp model cal passed | ^ | ^
|
||||
| ^ | ^ | ^ | 10h 16 | ^ | Live Adjust set | ^ | ^
|
||||
| ^ | ^ | ^ | 20h 32 | ^ | Free bit | ^ | ^
|
||||
| ^ | ^ | ^ | 40h 64 | ^ | Free bit | ^ | ^
|
||||
| ^ | ^ | ^ | 80h 128 | ^ | Unknown | ^ | ^
|
||||
|
||||
|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
|
||||
#define EEPROM_EMPTY_VALUE16 0xFFFF
|
||||
#define EEPROM_EMPTY_VALUE32 0xFFFFFFFFl
|
||||
// The total size of the EEPROM is
|
||||
// 4096 for the Atmega2560
|
||||
#define EEPROM_TOP 4096
|
||||
|
|
@ -37,7 +379,7 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP
|
|||
#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 4087
|
||||
#define EEPROM_CALIBRATION_STATUS_V1 4087 // legacy, used up to v3.11
|
||||
#define EEPROM_BABYSTEP_Z0 4085
|
||||
#define EEPROM_FILAMENTUSED 4081
|
||||
// uint32_t
|
||||
|
|
@ -51,7 +393,8 @@ 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_FARM_NUMBER (EEPROM_FARM_MODE-3)
|
||||
#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.
|
||||
|
|
@ -63,32 +406,35 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP
|
|||
#define EEPROM_BED_CORRECTION_REAR (EEPROM_BED_CORRECTION_FRONT-1)
|
||||
#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_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_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_FREE_NR6_ (EEPROM_TEMP_CAL_ACTIVE - 2*4) //4 x int (used to be for bowden lengths for SNMM)
|
||||
#define EEPROM_CALIBRATION_STATUS_PINDA (_EEPROM_FREE_NR6_ - 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_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_TARGET_HOTEND (EEPROM_UVLO_CURRENT_POSITION_Z - 1)
|
||||
#define EEPROM_UVLO_TARGET_BED (EEPROM_UVLO_TARGET_HOTEND - 1)
|
||||
#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_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_Z_MICROSTEPS (EEPROM_UVLO_MESH_BED_LEVELING - 2)
|
||||
#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_UVLO_SAVED_SEGMENT_IDX (EEPROM_UVLO_CURRENT_POSITION_E - 2) //uint16_t
|
||||
|
||||
// Crash detection mode EEPROM setting
|
||||
#define EEPROM_CRASH_DET (EEPROM_UVLO_CURRENT_POSITION_E - 5) // float (orig EEPROM_UVLO_MESH_BED_LEVELING-12)
|
||||
#define EEPROM_FREE_NR4 (EEPROM_UVLO_SAVED_SEGMENT_IDX - 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)
|
||||
// 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)
|
||||
|
|
@ -97,7 +443,7 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP
|
|||
#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)
|
||||
#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.
|
||||
#define EEPROM_BELTSTATUS_X (EEPROM_WIZARD_ACTIVE - 2) // uint16
|
||||
#define EEPROM_BELTSTATUS_Y (EEPROM_BELTSTATUS_X - 2) // uint16
|
||||
|
||||
|
|
@ -118,7 +464,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
|
||||
|
|
@ -165,18 +511,16 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP
|
|||
#define EEPROM_EXTRUDER_MULTIPLIER_2 (EEPROM_EXTRUDER_MULTIPLIER_1 - 4) //float
|
||||
#define EEPROM_EXTRUDEMULTIPLY (EEPROM_EXTRUDER_MULTIPLIER_2 - 2) // uint16
|
||||
|
||||
//
|
||||
#define EEPROM_UVLO_TINY_CURRENT_POSITION_Z (EEPROM_EXTRUDEMULTIPLY-4) // float
|
||||
#define EEPROM_UVLO_TINY_Z_MICROSTEPS (EEPROM_UVLO_TINY_CURRENT_POSITION_Z-2) // uint16
|
||||
#define EEPROM_UVLO_TARGET_HOTEND (EEPROM_UVLO_TINY_CURRENT_POSITION_Z-2) // uint16
|
||||
|
||||
// Sound Mode
|
||||
//#define EEPROM_SOUND_MODE (EEPROM_EXTRUDEMULTIPLY-1) // uint8
|
||||
#define EEPROM_SOUND_MODE (EEPROM_UVLO_TINY_Z_MICROSTEPS-1) // uint8
|
||||
#define EEPROM_AUTO_DEPLETE (EEPROM_SOUND_MODE-1) //bool
|
||||
#define EEPROM_SOUND_MODE (EEPROM_UVLO_TARGET_HOTEND-1) // uint8
|
||||
#define EEPROM_SPOOL_JOIN (EEPROM_SOUND_MODE-1) //bool
|
||||
|
||||
#define EEPROM_FSENS_OQ_MEASS_ENABLED (EEPROM_AUTO_DEPLETE - 1) //bool
|
||||
#define EEPROM_FSENS_RUNOUT_ENABLED (EEPROM_SPOOL_JOIN - 1) //bool
|
||||
|
||||
#define EEPROM_MMU_FAIL_TOT (EEPROM_FSENS_OQ_MEASS_ENABLED - 2) //uint16_t
|
||||
#define EEPROM_MMU_FAIL_TOT (EEPROM_FSENS_RUNOUT_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
|
||||
|
|
@ -185,7 +529,7 @@ static_assert(sizeof(Sheets) == EEPROM_SHEETS_SIZEOF, "Sizeof(Sheets) is not EEP
|
|||
#define EEPROM_UVLO_MESH_BED_LEVELING_FULL (EEPROM_MMU_CUTTER_ENABLED - 12*12*2) //allow 12 calibration points for future expansion
|
||||
|
||||
#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_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
|
||||
|
||||
|
|
@ -204,8 +548,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_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_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_BACKLIGHT_LEVEL_HIGH (EEPROM_UVLO_FEEDMULTIPLY-1) // uint8
|
||||
#define EEPROM_BACKLIGHT_LEVEL_LOW (EEPROM_BACKLIGHT_LEVEL_HIGH-1) // uint8
|
||||
|
|
@ -214,8 +558,36 @@ static Sheets * const EEPROM_Sheets_base = (Sheets*)(EEPROM_SHEETS_BASE);
|
|||
|
||||
#define EEPROM_UVLO_LA_K (EEPROM_BACKLIGHT_TIMEOUT-4) // float
|
||||
|
||||
#define EEPROM_ALTFAN_OVERRIDE (EEPROM_UVLO_LA_K-1) //uint8
|
||||
#define EEPROM_EXPERIMENTAL_VISIBILITY (EEPROM_ALTFAN_OVERRIDE-1) //uint8
|
||||
#define EEPROM_PINDA_TEMP_COMPENSATION (EEPROM_EXPERIMENTAL_VISIBILITY-1) //uint8
|
||||
#define EEPROM_PRUSA_SN (EEPROM_PINDA_TEMP_COMPENSATION-20) //char[20]
|
||||
|
||||
#define EEPROM_UVLO_ACCELL (EEPROM_PRUSA_SN-4) // float
|
||||
#define EEPROM_UVLO_RETRACT_ACCELL (EEPROM_UVLO_ACCELL-4) // float
|
||||
#define EEPROM_UVLO_TRAVEL_ACCELL (EEPROM_UVLO_RETRACT_ACCELL-4) // float
|
||||
|
||||
#define EEPROM_JOB_ID (EEPROM_UVLO_TRAVEL_ACCELL-4) //uint32_t
|
||||
|
||||
#define EEPROM_ECOOL_ENABLE (EEPROM_JOB_ID-1) // uint8_t
|
||||
#define EEPROM_FW_CRASH_FLAG (EEPROM_ECOOL_ENABLE-1) // uint8_t
|
||||
|
||||
#define EEPROM_TEMP_MODEL_ENABLE (EEPROM_FW_CRASH_FLAG-1) // uint8_t
|
||||
#define EEPROM_TEMP_MODEL_P (EEPROM_TEMP_MODEL_ENABLE-4) // float
|
||||
#define EEPROM_TEMP_MODEL_C (EEPROM_TEMP_MODEL_P-4) // float
|
||||
#define EEPROM_TEMP_MODEL_R (EEPROM_TEMP_MODEL_C-4*16) // float[16]
|
||||
#define EEPROM_TEMP_MODEL_Ta_corr (EEPROM_TEMP_MODEL_R-4) // float
|
||||
#define EEPROM_TEMP_MODEL_W (EEPROM_TEMP_MODEL_Ta_corr-4) // float
|
||||
#define EEPROM_TEMP_MODEL_E (EEPROM_TEMP_MODEL_W-4) // float
|
||||
|
||||
#define EEPROM_FSENSOR_JAM_DETECTION (EEPROM_TEMP_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
|
||||
|
||||
//This is supposed to point to last item to allow EEPROM overrun check. Please update when adding new items.
|
||||
#define EEPROM_LAST_ITEM EEPROM_UVLO_LA_K
|
||||
#define EEPROM_LAST_ITEM EEPROM_CALIBRATION_STATUS_V2
|
||||
// !!!!!
|
||||
// !!!!! this is end of EEPROM section ... all updates MUST BE inserted before this mark !!!!!
|
||||
// !!!!!
|
||||
|
|
@ -231,11 +603,12 @@ static Sheets * const EEPROM_Sheets_base = (Sheets*)(EEPROM_SHEETS_BASE);
|
|||
#define EEPROM_FIRMWARE_VERSION_MAJOR FW_PRUSA3D_MAGIC_LEN
|
||||
// Magic string, indicating that the current or the previous firmware running was the Prusa3D firmware.
|
||||
#define EEPROM_FIRMWARE_PRUSA_MAGIC 0
|
||||
#define EEPROM_ECOOL_MAGIC_NUMBER 42
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include "ConfigurationStore.h"
|
||||
static_assert(EEPROM_FIRMWARE_VERSION_END < 20, "Firmware version EEPROM address conflicts with EEPROM_M500_base");
|
||||
static constexpr M500_conf * const EEPROM_M500_base = reinterpret_cast<M500_conf*>(20); //offset for storing settings using M500
|
||||
static M500_conf * const EEPROM_M500_base = reinterpret_cast<M500_conf*>(20); //offset for storing settings using M500
|
||||
static_assert(((sizeof(M500_conf) + 20) < EEPROM_LAST_ITEM), "M500_conf address space conflicts with previous items.");
|
||||
#endif
|
||||
|
||||
|
|
@ -247,7 +620,7 @@ enum
|
|||
|
||||
#ifdef __cplusplus
|
||||
void eeprom_init();
|
||||
bool eeprom_is_sheet_initialized(uint8_t sheet_num);
|
||||
void eeprom_adjust_bed_reset();
|
||||
struct SheetName
|
||||
{
|
||||
char c[sizeof(Sheet::name) + 1];
|
||||
|
|
@ -255,6 +628,26 @@ 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);
|
||||
#endif
|
||||
|
||||
#endif // EEPROM_H
|
||||
|
|
|
|||
|
|
@ -0,0 +1,317 @@
|
|||
// fan control and check
|
||||
#include "fancheck.h"
|
||||
#include "cardreader.h"
|
||||
#include "ultralcd.h"
|
||||
#include "sound.h"
|
||||
#include "messages.h"
|
||||
#include "temperature.h"
|
||||
#include "stepper.h"
|
||||
|
||||
#define FAN_CHECK_PERIOD 5000 //5s
|
||||
#define FAN_CHECK_DURATION 100 //100ms
|
||||
|
||||
#ifdef FANCHECK
|
||||
volatile uint8_t fan_check_error = EFCE_OK;
|
||||
#endif
|
||||
|
||||
#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 (IS_SD_PRINTING || usb_timer.running()) {
|
||||
// A print is ongoing, pause the print normally
|
||||
if(!isPrintPaused) {
|
||||
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
|
||||
}
|
||||
if (fans_check_enabled && (fan_check_error == EFCE_OK))
|
||||
{
|
||||
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)
|
||||
|
||||
#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((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() {
|
||||
#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
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
// 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))
|
||||
|
||||
#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();
|
||||
|
|
@ -7,15 +7,8 @@
|
|||
#define _FASTIO_ARDUINO_H
|
||||
|
||||
#include <avr/io.h>
|
||||
#include "macros.h"
|
||||
|
||||
/*
|
||||
utility functions
|
||||
*/
|
||||
|
||||
#ifndef MASK
|
||||
/// MASKING- returns \f$2^PIN\f$
|
||||
#define MASK(PIN) (1 << PIN)
|
||||
#endif
|
||||
|
||||
/*
|
||||
magic I/O routines
|
||||
|
|
@ -23,20 +16,20 @@
|
|||
*/
|
||||
|
||||
/// Read a pin
|
||||
#define _READ(IO) ((bool)(DIO ## IO ## _RPORT & MASK(DIO ## IO ## _PIN)))
|
||||
#define _READ(IO) ((bool)(DIO ## IO ## _RPORT & _BV(DIO ## IO ## _PIN)))
|
||||
/// write to a pin
|
||||
// On some boards pins > 0x100 are used. These are not converted to atomic actions. An critical section is needed.
|
||||
|
||||
#define _WRITE_NC(IO, v) do { if (v) {DIO ## IO ## _WPORT |= MASK(DIO ## IO ## _PIN); } else {DIO ## IO ## _WPORT &= ~MASK(DIO ## IO ## _PIN); }; } while (0)
|
||||
#define _WRITE_NC(IO, v) do { if (v) {DIO ## IO ## _WPORT |= _BV(DIO ## IO ## _PIN); } else {DIO ## IO ## _WPORT &= ~_BV(DIO ## IO ## _PIN); }; } while (0)
|
||||
|
||||
#define _WRITE_C(IO, v) do { if (v) { \
|
||||
CRITICAL_SECTION_START; \
|
||||
{DIO ## IO ## _WPORT |= MASK(DIO ## IO ## _PIN); }\
|
||||
{DIO ## IO ## _WPORT |= _BV(DIO ## IO ## _PIN); }\
|
||||
CRITICAL_SECTION_END; \
|
||||
}\
|
||||
else {\
|
||||
CRITICAL_SECTION_START; \
|
||||
{DIO ## IO ## _WPORT &= ~MASK(DIO ## IO ## _PIN); }\
|
||||
{DIO ## IO ## _WPORT &= ~_BV(DIO ## IO ## _PIN); }\
|
||||
CRITICAL_SECTION_END; \
|
||||
}\
|
||||
}\
|
||||
|
|
@ -45,20 +38,20 @@
|
|||
#define _WRITE(IO, v) do { if (&(DIO ## IO ## _RPORT) >= (uint8_t *)0x100) {_WRITE_C(IO, v); } else {_WRITE_NC(IO, v); }; } while (0)
|
||||
|
||||
/// toggle a pin
|
||||
#define _TOGGLE(IO) do {DIO ## IO ## _RPORT = MASK(DIO ## IO ## _PIN); } while (0)
|
||||
#define _TOGGLE(IO) do {DIO ## IO ## _RPORT = _BV(DIO ## IO ## _PIN); } while (0)
|
||||
|
||||
/// set pin as input
|
||||
#define _SET_INPUT(IO) do {DIO ## IO ## _DDR &= ~MASK(DIO ## IO ## _PIN); } while (0)
|
||||
#define _SET_INPUT(IO) do {DIO ## IO ## _DDR &= ~_BV(DIO ## IO ## _PIN); } while (0)
|
||||
/// set pin as output
|
||||
#define _SET_OUTPUT(IO) do {DIO ## IO ## _DDR |= MASK(DIO ## IO ## _PIN); } while (0)
|
||||
#define _SET_OUTPUT(IO) do {DIO ## IO ## _DDR |= _BV(DIO ## IO ## _PIN); } while (0)
|
||||
|
||||
/// check if pin is an input
|
||||
#define _GET_INPUT(IO) ((DIO ## IO ## _DDR & MASK(DIO ## IO ## _PIN)) == 0)
|
||||
#define _GET_INPUT(IO) ((DIO ## IO ## _DDR & _BV(DIO ## IO ## _PIN)) == 0)
|
||||
/// check if pin is an output
|
||||
#define _GET_OUTPUT(IO) ((DIO ## IO ## _DDR & MASK(DIO ## IO ## _PIN)) != 0)
|
||||
#define _GET_OUTPUT(IO) ((DIO ## IO ## _DDR & _BV(DIO ## IO ## _PIN)) != 0)
|
||||
|
||||
/// check if pin is an timer
|
||||
#define _GET_TIMER(IO) ((DIO ## IO ## _PWM)
|
||||
#define _GET_TIMER(IO) (DIO ## IO ## _PWM)
|
||||
|
||||
// why double up on these macros? see http://gcc.gnu.org/onlinedocs/cpp/Stringification.html
|
||||
|
||||
|
|
@ -938,10 +931,10 @@ pins
|
|||
#define TXD DIO1
|
||||
|
||||
// SPI
|
||||
#define SCK DIO52
|
||||
#define MISO DIO50
|
||||
#define MOSI DIO51
|
||||
#define SS DIO53
|
||||
#define SCK 52
|
||||
#define MISO 50
|
||||
#define MOSI 51
|
||||
#define SS 53
|
||||
|
||||
// TWI (I2C)
|
||||
#define SCL DIO21
|
||||
|
|
|
|||
|
|
@ -4,59 +4,70 @@
|
|||
//! @brief First layer (Z offset) calibration
|
||||
|
||||
#include "first_lay_cal.h"
|
||||
#include "Configuration_prusa.h"
|
||||
#include "Configuration_var.h"
|
||||
#include "language.h"
|
||||
#include "Marlin.h"
|
||||
#include "mmu.h"
|
||||
#include "cmdqueue.h"
|
||||
#include "mmu2.h"
|
||||
#include <avr/pgmspace.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,
|
||||
PSTR("M107"),
|
||||
PSTR("M190"),
|
||||
PSTR("M109"),
|
||||
PSTR("G28"),
|
||||
PSTR("G92 E0.0")
|
||||
};
|
||||
|
||||
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)
|
||||
//! @returns true if extra purge distance is needed in case of MMU prints (after a toolchange), otherwise false
|
||||
bool lay1cal_load_filament(char *cmd_buffer, uint8_t filament)
|
||||
{
|
||||
if (mmu_enabled)
|
||||
if (MMU2::mmu2.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);
|
||||
}
|
||||
|
||||
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(PSTR("M702"));
|
||||
}
|
||||
// perform a toolchange
|
||||
// sprintf_P(cmd_buffer, PSTR("T%d"), filament);
|
||||
// rewriting the trivial T<filament> g-code command saves 30B:
|
||||
cmd_buffer[0] = 'T';
|
||||
cmd_buffer[1] = filament + '0';
|
||||
cmd_buffer[2] = 0;
|
||||
|
||||
enquecommand(cmd_buffer);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//! @brief Print intro line
|
||||
void lay1cal_intro_line()
|
||||
//! @param extraPurgeNeeded false if the first MMU-related "G1 E29" have to be skipped because the nozzle is already full of filament
|
||||
void lay1cal_intro_line(bool extraPurgeNeeded)
|
||||
{
|
||||
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_3[] PROGMEM = "G1 X55.0 E29.0 F1073.0";
|
||||
static const char cmd_intro_mmu_4[] PROGMEM = "G1 X5.0 E29.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";
|
||||
|
|
@ -68,8 +79,10 @@ void lay1cal_intro_line()
|
|||
|
||||
static const char * const intro_mmu_cmd[] 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,
|
||||
cmd_intro_mmu_7,
|
||||
|
|
@ -80,9 +93,9 @@ void lay1cal_intro_line()
|
|||
cmd_intro_mmu_12,
|
||||
};
|
||||
|
||||
if (mmu_enabled)
|
||||
if (MMU2::mmu2.Enabled())
|
||||
{
|
||||
for (uint8_t i = 0; i < (sizeof(intro_mmu_cmd)/sizeof(intro_mmu_cmd[0])); ++i)
|
||||
for (uint8_t i = (extraPurgeNeeded ? 0 : 2); i < (sizeof(intro_mmu_cmd)/sizeof(intro_mmu_cmd[0])); ++i)
|
||||
{
|
||||
enquecommand_P(static_cast<char*>(pgm_read_ptr(&intro_mmu_cmd[i])));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@
|
|||
#include <stdint.h>
|
||||
|
||||
void lay1cal_wait_preheat();
|
||||
void lay1cal_load_filament(char *cmd_buffer, uint8_t filament);
|
||||
void lay1cal_intro_line();
|
||||
[[nodiscard]] bool lay1cal_load_filament(char *cmd_buffer, uint8_t filament);
|
||||
void lay1cal_intro_line(bool skipExtraPurge);
|
||||
void lay1cal_before_meander();
|
||||
void lay1cal_meander(char *cmd_buffer);
|
||||
void lay1cal_square(char *cmd_buffer, uint8_t i);
|
||||
|
|
|
|||
|
|
@ -1,679 +0,0 @@
|
|||
//! @file
|
||||
|
||||
#include "Marlin.h"
|
||||
|
||||
#include "fsensor.h"
|
||||
#include <avr/pgmspace.h>
|
||||
#include "pat9125.h"
|
||||
#include "stepper.h"
|
||||
#include "io_atmega2560.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 0.64F //!< filament sensor chunk length 0.64mm
|
||||
#define FSENSOR_ERR_MAX 17 //!< filament sensor maximum error count for runout detection
|
||||
//! @}
|
||||
|
||||
//! @name Optical quality measurement parameters
|
||||
//! @{
|
||||
#define FSENSOR_OQ_MAX_ES 6 //!< maximum error sum while loading (length ~64mm = 100chunks)
|
||||
#define FSENSOR_OQ_MAX_EM 2 //!< maximum error counter value while loading
|
||||
#define FSENSOR_OQ_MIN_YD 2 //!< minimum yd per chunk (applied to avg value)
|
||||
#define FSENSOR_OQ_MAX_YD 200 //!< maximum yd per chunk (applied to avg value)
|
||||
#define FSENSOR_OQ_MAX_PD 4 //!< maximum positive deviation (= yd_max/yd_avg)
|
||||
#define FSENSOR_OQ_MAX_ND 5 //!< maximum negative deviation (= yd_avg/yd_min)
|
||||
#define FSENSOR_OQ_MAX_SH 13 //!< 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
|
||||
|
||||
//uint8_t fsensor_int_pin = FSENSOR_INT_PIN;
|
||||
uint8_t fsensor_int_pin_old = 0;
|
||||
int16_t fsensor_chunk_len = 0;
|
||||
|
||||
//! 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;
|
||||
//! 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;
|
||||
//! last dy value from pat9125 sensor (used in ISR)
|
||||
int16_t fsensor_dy_old = 0;
|
||||
|
||||
//! log flag: 0=log disabled, 1=log enabled
|
||||
uint8_t fsensor_log = 1;
|
||||
|
||||
|
||||
//! @name filament autoload variables
|
||||
//! @{
|
||||
|
||||
//! autoload feature enabled
|
||||
bool fsensor_autoload_enabled = true;
|
||||
//! autoload watching enable/disable flag
|
||||
bool fsensor_watch_autoload = false;
|
||||
//
|
||||
uint16_t fsensor_autoload_y;
|
||||
//
|
||||
uint8_t fsensor_autoload_c;
|
||||
//
|
||||
uint32_t fsensor_autoload_last_millis;
|
||||
//
|
||||
uint8_t fsensor_autoload_sum;
|
||||
//! @}
|
||||
|
||||
|
||||
//! @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;
|
||||
//! @}
|
||||
|
||||
#if IR_SENSOR_ANALOG
|
||||
ClFsensorPCB oFsensorPCB;
|
||||
ClFsensorActionNA oFsensorActionNA;
|
||||
bool bIRsensorStateFlag=false;
|
||||
unsigned long nIRsensorLastTime;
|
||||
#endif //IR_SENSOR_ANALOG
|
||||
|
||||
void fsensor_stop_and_save_print(void)
|
||||
{
|
||||
printf_P(PSTR("fsensor_stop_and_save_print\n"));
|
||||
stop_and_save_print_to_ram(0, 0); //XYZE - no change
|
||||
}
|
||||
|
||||
void fsensor_restore_print_and_continue(void)
|
||||
{
|
||||
printf_P(PSTR("fsensor_restore_print_and_continue\n"));
|
||||
fsensor_err_cnt = 0;
|
||||
restore_print_from_ram_and_continue(0); //XYZ = orig, E - no change
|
||||
}
|
||||
|
||||
// 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)
|
||||
{
|
||||
printf_P(PSTR("fsensor_checkpoint_print\n"));
|
||||
stop_and_save_print_to_ram(0, 0);
|
||||
restore_print_from_ram_and_continue(0);
|
||||
}
|
||||
|
||||
void fsensor_init(void)
|
||||
{
|
||||
#ifdef PAT9125
|
||||
uint8_t pat9125 = pat9125_init();
|
||||
printf_P(PSTR("PAT9125_init:%hhu\n"), pat9125);
|
||||
#endif //PAT9125
|
||||
uint8_t fsensor = 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_chunk_len = (int16_t)(FSENSOR_CHUNK_LEN * cs.axis_steps_per_unit[E_AXIS]);
|
||||
|
||||
if (!pat9125)
|
||||
{
|
||||
fsensor = 0; //disable sensor
|
||||
fsensor_not_responding = true;
|
||||
}
|
||||
#endif //PAT9125
|
||||
#if 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);
|
||||
#endif //IR_SENSOR_ANALOG
|
||||
if (fsensor)
|
||||
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")));
|
||||
#if IR_SENSOR_ANALOG
|
||||
printf_P(PSTR(" (sensor board revision: %S)\n"),(oFsensorPCB==ClFsensorPCB::_Rev03b)?PSTR("03b or newer"):PSTR("03 or older"));
|
||||
#else //IR_SENSOR_ANALOG
|
||||
printf_P(PSTR("\n"));
|
||||
#endif //IR_SENSOR_ANALOG
|
||||
if (check_for_ir_sensor()) ir_sensor_detected = true;
|
||||
|
||||
}
|
||||
|
||||
bool fsensor_enable(bool bUpdateEEPROM)
|
||||
{
|
||||
#ifdef PAT9125
|
||||
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_err_cnt = 0;
|
||||
fsensor_dy_old = 0;
|
||||
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
|
||||
#if 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;
|
||||
#if 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\n"));
|
||||
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;
|
||||
fsensor_err_cnt = 0;
|
||||
}
|
||||
|
||||
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\n"));
|
||||
fsensor_autoload_sum = 0;
|
||||
fsensor_watch_autoload = false;
|
||||
fsensor_watch_runout = true;
|
||||
fsensor_err_cnt = 0;
|
||||
}
|
||||
#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;
|
||||
}
|
||||
|
||||
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;
|
||||
printf_P(PSTR("fsensor_oq_meassure_start\n"));
|
||||
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 = FSENSOR_OQ_MAX_YD;
|
||||
fsensor_oq_yd_max = 0;
|
||||
fsensor_oq_sh_sum = 0;
|
||||
pat9125_update();
|
||||
pat9125_y = 0;
|
||||
fsensor_watch_runout = false;
|
||||
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;
|
||||
fsensor_watch_runout = true;
|
||||
fsensor_err_cnt = 0;
|
||||
}
|
||||
|
||||
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;
|
||||
printf_P(_N("fsensor_oq_result\n"));
|
||||
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;
|
||||
}
|
||||
#ifdef PAT9125
|
||||
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;
|
||||
static bool _lock = false;
|
||||
if (_lock) return;
|
||||
_lock = true;
|
||||
int st_cnt = fsensor_st_cnt;
|
||||
fsensor_st_cnt = 0;
|
||||
sei();
|
||||
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
|
||||
if (st_cnt > 0) //positive movement
|
||||
{
|
||||
if (pat9125_y < 0)
|
||||
{
|
||||
if (fsensor_err_cnt)
|
||||
fsensor_err_cnt += 2;
|
||||
else
|
||||
fsensor_err_cnt++;
|
||||
}
|
||||
else if (pat9125_y > 0)
|
||||
{
|
||||
if (fsensor_err_cnt)
|
||||
fsensor_err_cnt--;
|
||||
}
|
||||
else //(pat9125_y == 0)
|
||||
if (((fsensor_dy_old <= 0) || (fsensor_err_cnt)) && (st_cnt > (fsensor_chunk_len >> 1)))
|
||||
fsensor_err_cnt++;
|
||||
if (fsensor_oq_meassure)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
else //negative movement
|
||||
{
|
||||
}
|
||||
}
|
||||
else
|
||||
{ //no movement
|
||||
}
|
||||
|
||||
#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
|
||||
|
||||
fsensor_dy_old = pat9125_y;
|
||||
pat9125_y = 0;
|
||||
|
||||
_lock = false;
|
||||
return;
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
#endif //PAT9125
|
||||
|
||||
void fsensor_st_block_chunk(int cnt)
|
||||
{
|
||||
if (!fsensor_enabled) return;
|
||||
fsensor_st_cnt += cnt;
|
||||
if (abs(fsensor_st_cnt) >= fsensor_chunk_len)
|
||||
{
|
||||
// !!! bit toggling (PINxn <- 1) (for PinChangeInterrupt) does not work for some MCU pins
|
||||
if (PIN_GET(FSENSOR_INT_PIN)) {PIN_VAL(FSENSOR_INT_PIN, LOW);}
|
||||
else {PIN_VAL(FSENSOR_INT_PIN, HIGH);}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! 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(){
|
||||
printf_P(PSTR("fsensor_update - M600\n"));
|
||||
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_enabled && fsensor_watch_runout && (fsensor_err_cnt > FSENSOR_ERR_MAX))
|
||||
{
|
||||
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;
|
||||
|
||||
fsensor_stop_and_save_print();
|
||||
|
||||
fsensor_err_cnt = 0;
|
||||
fsensor_oq_meassure_start(0);
|
||||
|
||||
enquecommand_front_P((PSTR("G1 E-3 F200")));
|
||||
process_commands();
|
||||
KEEPALIVE_STATE(IN_HANDLER);
|
||||
cmdqueue_pop_front();
|
||||
st_synchronize();
|
||||
|
||||
enquecommand_front_P((PSTR("G1 E3 F200")));
|
||||
process_commands();
|
||||
KEEPALIVE_STATE(IN_HANDLER);
|
||||
cmdqueue_pop_front();
|
||||
st_synchronize();
|
||||
|
||||
uint8_t err_cnt = fsensor_err_cnt;
|
||||
fsensor_oq_meassure_stop();
|
||||
|
||||
bool err = false;
|
||||
err |= (err_cnt > 1);
|
||||
|
||||
err |= (fsensor_oq_er_sum > 2);
|
||||
err |= (fsensor_oq_yd_sum < (4 * FSENSOR_OQ_MIN_YD));
|
||||
|
||||
fsensor_restore_print_and_continue();
|
||||
fsensor_autoload_enabled = autoload_enabled_tmp;
|
||||
fsensor_oq_meassure_enabled = oq_meassure_enabled_tmp;
|
||||
|
||||
if (!err)
|
||||
printf_P(PSTR("fsensor_err_cnt = 0\n"));
|
||||
else
|
||||
fsensor_enque_M600();
|
||||
}
|
||||
#else //PAT9125
|
||||
if (CHECK_FSENSOR && fsensor_enabled && ir_sensor_detected)
|
||||
{
|
||||
if(digitalRead(IR_SENSOR_PIN))
|
||||
{ // IR_SENSOR_PIN ~ H
|
||||
#if 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 ...
|
||||
if((oFsensorPCB==ClFsensorPCB::_Rev03b)&&((nADC*OVERSAMPLENR)>((int)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(oFsensorActionNA==ClFsensorActionNA::_Pause)
|
||||
lcd_pause_print();
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif //IR_SENSOR_ANALOG
|
||||
fsensor_checkpoint_print();
|
||||
fsensor_enque_M600();
|
||||
#if IR_SENSOR_ANALOG
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // IR_SENSOR_PIN ~ L
|
||||
bIRsensorStateFlag=false;
|
||||
#endif //IR_SENSOR_ANALOG
|
||||
}
|
||||
}
|
||||
#endif //PAT9125
|
||||
}
|
||||
|
||||
#if IR_SENSOR_ANALOG
|
||||
bool fsensor_IR_check()
|
||||
{
|
||||
uint16_t volt_IR_int;
|
||||
bool bCheckResult;
|
||||
|
||||
volt_IR_int=current_voltage_raw_IR;
|
||||
bCheckResult=(volt_IR_int<((int)IRsensor_Lmax_TRESHOLD))||(volt_IR_int>((int)IRsensor_Hmin_TRESHOLD));
|
||||
bCheckResult=bCheckResult&&(!((oFsensorPCB==ClFsensorPCB::_Rev03b)&&(volt_IR_int>((int)IRsensor_Hopen_TRESHOLD))));
|
||||
return(bCheckResult);
|
||||
}
|
||||
#endif //IR_SENSOR_ANALOG
|
||||
|
|
@ -1,98 +0,0 @@
|
|||
//! @file
|
||||
#ifndef FSENSOR_H
|
||||
#define FSENSOR_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "config.h"
|
||||
|
||||
|
||||
//! minimum meassured chunk length in steps
|
||||
extern int16_t fsensor_chunk_len;
|
||||
// enable/disable flag
|
||||
extern bool fsensor_enabled;
|
||||
// not responding flag
|
||||
extern bool fsensor_not_responding;
|
||||
//enable/disable quality meassurement
|
||||
extern bool fsensor_oq_meassure_enabled;
|
||||
|
||||
|
||||
//! @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);
|
||||
|
||||
//! @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);
|
||||
//! @}
|
||||
|
||||
//! @name optical quality measurement support
|
||||
//! @{
|
||||
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);
|
||||
|
||||
// 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)
|
||||
//! @}
|
||||
|
||||
|
||||
#if IR_SENSOR_ANALOG
|
||||
#define IR_SENSOR_STEADY 10 // [ms]
|
||||
|
||||
enum class ClFsensorPCB:uint_least8_t
|
||||
{
|
||||
_Old=0,
|
||||
_Rev03b=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 bool fsensor_IR_check();
|
||||
#endif //IR_SENSOR_ANALOG
|
||||
|
||||
#endif //FSENSOR_H
|
||||
|
|
@ -1,180 +1,182 @@
|
|||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include "io_atmega2560.h"
|
||||
|
||||
// All this is about silencing the heat bed, as it behaves like a loudspeaker.
|
||||
// Basically, we want the PWM heating switched at 30Hz (or so) which is a well ballanced
|
||||
// frequency for both power supply units (i.e. both PSUs are reasonably silent).
|
||||
// The only trouble is the rising or falling edge of bed heating - that creates an audible click.
|
||||
// This audible click may be suppressed by making the rising or falling edge NOT sharp.
|
||||
// Of course, making non-sharp edges in digital technology is not easy, but there is a solution.
|
||||
// It is possible to do a fast PWM sequence with duty starting from 0 to 255.
|
||||
// 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
|
||||
// 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
|
||||
// So the automaton runs atop of inner 8 (or 16) cycles.
|
||||
// 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,
|
||||
// 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.
|
||||
// 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,
|
||||
// we don't have to clock 62kHz, but we can increase the CLK prescaler for these states to 8 (or even 64).
|
||||
// That shall result in the ISR not being called that much resulting in regained performance
|
||||
// Theoretically this is relatively easy, however one must be very carefull handling the AVR's timer
|
||||
// control registers correctly, especially setting them in a correct order.
|
||||
// Some registers are double buffered, some changes are applied in next cycles etc.
|
||||
// The biggest problem was with the CLK prescaler itself - this circuit is shared among almost all timers,
|
||||
// we don't want to reset the prescaler counted value when transiting among automaton states.
|
||||
// Resetting the prescaler would make the PWM more precise, right now there are temporal segments
|
||||
// of variable period ranging from 0 to 7 62kHz ticks - that's logical, the timer must "sync"
|
||||
// to the new slower CLK after setting the slower prescaler value.
|
||||
// In our application, this isn't any significant problem and may be ignored.
|
||||
// Doing changes in timer's registers non-correctly results in artefacts on the output pin
|
||||
// - 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.
|
||||
// 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!
|
||||
|
||||
///! Definition off finite automaton states
|
||||
enum class States : uint8_t {
|
||||
ZERO_START = 0,///< entry point of the automaton - reads the soft_pwm_bed value for the next whole PWM cycle
|
||||
ZERO, ///< steady 0 (OFF), no change for the whole period
|
||||
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_TO_FALL, ///< metastate allowing the timer change its state atomically without artefacts on the output pin
|
||||
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
|
||||
};
|
||||
|
||||
///! Inner states of the finite automaton
|
||||
static States state = States::ZERO_START;
|
||||
|
||||
///! Fast PWM counter is used in the RISE and FALL states (62.5kHz)
|
||||
static uint8_t slowCounter = 0;
|
||||
///! Slow PWM counter is used in the ZERO and ONE states (62.5kHz/8 or 64)
|
||||
static uint8_t fastCounter = 0;
|
||||
///! PWM counter for the whole cycle - a cache for soft_pwm_bed
|
||||
static uint8_t pwm = 0;
|
||||
|
||||
///! The slow PWM duty for the next 30Hz cycle
|
||||
///! Set in the whole firmware at various places
|
||||
extern unsigned char soft_pwm_bed;
|
||||
|
||||
/// fastMax - how many fast PWM steps to do in RISE and FALL states
|
||||
/// 16 is a good compromise between silenced bed ("smooth" edges)
|
||||
/// and not burning the switching MOSFET
|
||||
static const uint8_t fastMax = 16;
|
||||
|
||||
/// Scaler 16->256 for fast PWM
|
||||
static const uint8_t fastShift = 4;
|
||||
|
||||
/// Increment slow PWM counter by slowInc every ZERO or ONE state
|
||||
/// This allows for fine-tuning the basic PWM switching frequency
|
||||
/// A possible further optimization - use a 64 prescaler (instead of 8)
|
||||
/// 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
|
||||
static const uint8_t slowInc = 1;
|
||||
|
||||
ISR(TIMER0_OVF_vect) // timer compare interrupt service routine
|
||||
{
|
||||
switch(state){
|
||||
case States::ZERO_START:
|
||||
pwm = soft_pwm_bed << 1;// expecting soft_pwm_bed to be 7bit!
|
||||
if( pwm != 0 ){
|
||||
state = States::ZERO; // do nothing, let it tick once again after the 30Hz period
|
||||
}
|
||||
break;
|
||||
case States::ZERO: // end of state ZERO - we'll either stay in ZERO or change to RISE
|
||||
// In any case update our cache of pwm value for the next whole cycle from soft_pwm_bed
|
||||
slowCounter += slowInc; // this does software timer_clk/256 or less (depends on slowInc)
|
||||
if( slowCounter > pwm ){
|
||||
return;
|
||||
} // otherwise moving towards RISE
|
||||
state = States::ZERO_TO_RISE; // and finalize the change in a transitional state RISE0
|
||||
break;
|
||||
// even though it may look like the ZERO state may be glued together with the ZERO_TO_RISE, don't do it
|
||||
// the timer must tick once more in order to get rid of occasional output pin toggles.
|
||||
case States::ZERO_TO_RISE: // special state for handling transition between prescalers and switching inverted->non-inverted fast-PWM without toggling the output pin.
|
||||
// It must be done in consequent steps, otherwise the pin will get flipped up and down during one PWM cycle.
|
||||
// Also beware of the correct sequence of the following timer control registers initialization - it really matters!
|
||||
state = States::RISE; // prepare for standard RISE cycles
|
||||
fastCounter = fastMax - 1;// we'll do 16-1 cycles of RISE
|
||||
TCNT0 = 255; // force overflow on the next clock cycle
|
||||
TCCR0B = (1 << CS00); // change prescaler to 1, i.e. 62.5kHz
|
||||
TCCR0A &= ~(1 << COM0B0); // Clear OC0B on Compare Match, set OC0B at BOTTOM (non-inverting mode)
|
||||
break;
|
||||
case States::RISE:
|
||||
OCR0B = (fastMax - fastCounter) << fastShift;
|
||||
if( fastCounter ){
|
||||
--fastCounter;
|
||||
} else { // end of RISE cycles, changing into state ONE
|
||||
state = States::RISE_TO_ONE;
|
||||
OCR0B = 255; // full duty
|
||||
TCNT0 = 254; // make the timer overflow in the next cycle
|
||||
// @@TODO these constants are still subject to investigation
|
||||
}
|
||||
break;
|
||||
case States::RISE_TO_ONE:
|
||||
state = States::ONE;
|
||||
OCR0B = 255; // full duty
|
||||
TCNT0 = 255; // make the timer overflow in the next cycle
|
||||
TCCR0B = (1 << CS01); // change prescaler to 8, i.e. 7.8kHz
|
||||
break;
|
||||
case States::ONE: // state ONE - we'll either stay in ONE or change to FALL
|
||||
OCR0B = 255;
|
||||
slowCounter += slowInc; // this does software timer_clk/256 or less
|
||||
if( slowCounter < pwm ){
|
||||
return;
|
||||
}
|
||||
if( (soft_pwm_bed << 1) >= (255 - slowInc - 1) ){ //@@TODO simplify & explain
|
||||
// if slowInc==2, soft_pwm == 251 will be the first to do short drops to zero. 252 will keep full heating
|
||||
return; // want full duty for the next ONE cycle again - so keep on heating and just wait for the next timer ovf
|
||||
}
|
||||
// otherwise moving towards FALL
|
||||
// @@TODO it looks like ONE_TO_FALL isn't necessary, there are no artefacts at all
|
||||
state = States::ONE;//_TO_FALL;
|
||||
// TCCR0B = (1 << CS00); // change prescaler to 1, i.e. 62.5kHz
|
||||
// break;
|
||||
// case States::ONE_TO_FALL:
|
||||
// OCR0B = 255; // zero duty
|
||||
state=States::FALL;
|
||||
fastCounter = fastMax - 1;// we'll do 16-1 cycles of RISE
|
||||
TCNT0 = 255; // force overflow on the next clock cycle
|
||||
TCCR0B = (1 << CS00); // change prescaler to 1, i.e. 62.5kHz
|
||||
// must switch to inverting mode already here, because it takes a whole PWM cycle and it would make a "1" at the end of this pwm cycle
|
||||
// COM0B1 remains set both in inverting and non-inverting mode
|
||||
TCCR0A |= (1 << COM0B0); // inverting mode
|
||||
break;
|
||||
case States::FALL:
|
||||
OCR0B = (fastMax - fastCounter) << fastShift; // this is the same as in RISE, because now we are setting the zero part of duty due to inverting mode
|
||||
//TCCR0A |= (1 << COM0B0); // already set in ONE_TO_FALL
|
||||
if( fastCounter ){
|
||||
--fastCounter;
|
||||
} else { // end of FALL cycles, changing into state ZERO
|
||||
state = States::FALL_TO_ZERO;
|
||||
TCNT0 = 128; //@@TODO again - need to wait long enough to propagate the timer state changes
|
||||
OCR0B = 255;
|
||||
}
|
||||
break;
|
||||
case States::FALL_TO_ZERO:
|
||||
state = States::ZERO_START; // go to read new soft_pwm_bed value for the next cycle
|
||||
TCNT0 = 128;
|
||||
OCR0B = 255;
|
||||
TCCR0B = (1 << CS01); // change prescaler to 8, i.e. 7.8kHz
|
||||
break;
|
||||
}
|
||||
}
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
|
||||
// All this is about silencing the heat bed, as it behaves like a loudspeaker.
|
||||
// Basically, we want the PWM heating switched at 30Hz (or so) which is a well ballanced
|
||||
// frequency for both power supply units (i.e. both PSUs are reasonably silent).
|
||||
// The only trouble is the rising or falling edge of bed heating - that creates an audible click.
|
||||
// This audible click may be suppressed by making the rising or falling edge NOT sharp.
|
||||
// Of course, making non-sharp edges in digital technology is not easy, but there is a solution.
|
||||
// It is possible to do a fast PWM sequence with duty starting from 0 to 255.
|
||||
// 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
|
||||
// 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
|
||||
// So the automaton runs atop of inner 8 (or 16) cycles.
|
||||
// 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,
|
||||
// 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.
|
||||
// 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,
|
||||
// we don't have to clock 62kHz, but we can increase the CLK prescaler for these states to 8 (or even 64).
|
||||
// That shall result in the ISR not being called that much resulting in regained performance
|
||||
// Theoretically this is relatively easy, however one must be very carefull handling the AVR's timer
|
||||
// control registers correctly, especially setting them in a correct order.
|
||||
// Some registers are double buffered, some changes are applied in next cycles etc.
|
||||
// The biggest problem was with the CLK prescaler itself - this circuit is shared among almost all timers,
|
||||
// we don't want to reset the prescaler counted value when transiting among automaton states.
|
||||
// Resetting the prescaler would make the PWM more precise, right now there are temporal segments
|
||||
// of variable period ranging from 0 to 7 62kHz ticks - that's logical, the timer must "sync"
|
||||
// to the new slower CLK after setting the slower prescaler value.
|
||||
// In our application, this isn't any significant problem and may be ignored.
|
||||
// Doing changes in timer's registers non-correctly results in artefacts on the output pin
|
||||
// - 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.
|
||||
// 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!
|
||||
|
||||
// 2020-01-29 update: we are introducing a new option to the automaton that will allow us to force the output state
|
||||
// to either full ON or OFF. This is so that interference during the MBL probing is minimal.
|
||||
// To accomplish this goal we use bedPWMDisabled. It is only supposed to be used for brief periods of time as to
|
||||
// not make the bed temperature too unstable. Also, careful consideration should be used when using this
|
||||
// option as leaving this enabled will also keep the bed output in the state it stopped in.
|
||||
|
||||
///! Definition off finite automaton states
|
||||
enum class States : uint8_t {
|
||||
ZERO_START = 0,///< entry point of the automaton - reads the soft_pwm_bed value for the next whole PWM cycle
|
||||
ZERO, ///< steady 0 (OFF), no change for the whole period
|
||||
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
|
||||
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
|
||||
};
|
||||
|
||||
///! Inner states of the finite automaton
|
||||
static States state = States::ZERO_START;
|
||||
|
||||
bool bedPWMDisabled = 0;
|
||||
|
||||
///! Fast PWM counter is used in the RISE and FALL states (62.5kHz)
|
||||
static uint8_t slowCounter = 0;
|
||||
///! Slow PWM counter is used in the ZERO and ONE states (62.5kHz/8 or 64)
|
||||
static uint8_t fastCounter = 0;
|
||||
///! PWM counter for the whole cycle - a cache for soft_pwm_bed
|
||||
static uint8_t pwm = 0;
|
||||
|
||||
///! The slow PWM duty for the next 30Hz cycle
|
||||
///! Set in the whole firmware at various places
|
||||
extern unsigned char soft_pwm_bed;
|
||||
|
||||
/// fastMax - how many fast PWM steps to do in RISE and FALL states
|
||||
/// 16 is a good compromise between silenced bed ("smooth" edges)
|
||||
/// and not burning the switching MOSFET
|
||||
static const uint8_t fastMax = 16;
|
||||
|
||||
/// Scaler 16->256 for fast PWM
|
||||
static const uint8_t fastShift = 4;
|
||||
|
||||
/// Increment slow PWM counter by slowInc every ZERO or ONE state
|
||||
/// This allows for fine-tuning the basic PWM switching frequency
|
||||
/// A possible further optimization - use a 64 prescaler (instead of 8)
|
||||
/// 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
|
||||
static const uint8_t slowInc = 1;
|
||||
|
||||
ISR(TIMER0_OVF_vect) // timer compare interrupt service routine
|
||||
{
|
||||
switch(state){
|
||||
case States::ZERO_START:
|
||||
if (bedPWMDisabled) return; // stay in the OFF state and do not change the output pin
|
||||
pwm = soft_pwm_bed << 1;// expecting soft_pwm_bed to be 7bit!
|
||||
if( pwm != 0 ){
|
||||
state = States::ZERO; // do nothing, let it tick once again after the 30Hz period
|
||||
}
|
||||
break;
|
||||
case States::ZERO: // end of state ZERO - we'll either stay in ZERO or change to RISE
|
||||
// In any case update our cache of pwm value for the next whole cycle from soft_pwm_bed
|
||||
slowCounter += slowInc; // this does software timer_clk/256 or less (depends on slowInc)
|
||||
if( slowCounter > pwm ){
|
||||
return;
|
||||
} // otherwise moving towards RISE
|
||||
state = States::ZERO_TO_RISE; // and finalize the change in a transitional state RISE0
|
||||
break;
|
||||
// even though it may look like the ZERO state may be glued together with the ZERO_TO_RISE, don't do it
|
||||
// the timer must tick once more in order to get rid of occasional output pin toggles.
|
||||
case States::ZERO_TO_RISE: // special state for handling transition between prescalers and switching inverted->non-inverted fast-PWM without toggling the output pin.
|
||||
// It must be done in consequent steps, otherwise the pin will get flipped up and down during one PWM cycle.
|
||||
// Also beware of the correct sequence of the following timer control registers initialization - it really matters!
|
||||
state = States::RISE; // prepare for standard RISE cycles
|
||||
fastCounter = fastMax - 1;// we'll do 16-1 cycles of RISE
|
||||
TCNT0 = 255; // force overflow on the next clock cycle
|
||||
TCCR0B = (1 << CS00); // change prescaler to 1, i.e. 62.5kHz
|
||||
TCCR0A &= ~(1 << COM0B0); // Clear OC0B on Compare Match, set OC0B at BOTTOM (non-inverting mode)
|
||||
break;
|
||||
case States::RISE:
|
||||
OCR0B = (fastMax - fastCounter) << fastShift;
|
||||
if( fastCounter ){
|
||||
--fastCounter;
|
||||
} else { // end of RISE cycles, changing into state ONE
|
||||
state = States::RISE_TO_ONE;
|
||||
OCR0B = 255; // full duty
|
||||
TCNT0 = 254; // make the timer overflow in the next cycle
|
||||
// @@TODO these constants are still subject to investigation
|
||||
}
|
||||
break;
|
||||
case States::RISE_TO_ONE:
|
||||
state = States::ONE;
|
||||
OCR0B = 255; // full duty
|
||||
TCNT0 = 255; // make the timer overflow in the next cycle
|
||||
TCCR0B = (1 << CS01); // change prescaler to 8, i.e. 7.8kHz
|
||||
break;
|
||||
case States::ONE: // state ONE - we'll either stay in ONE or change to FALL
|
||||
OCR0B = 255;
|
||||
if (bedPWMDisabled) return; // stay in the ON state and do not change the output pin
|
||||
slowCounter += slowInc; // this does software timer_clk/256 or less
|
||||
if( slowCounter < pwm ){
|
||||
return;
|
||||
}
|
||||
if( (soft_pwm_bed << 1) >= (255 - slowInc - 1) ){ //@@TODO simplify & explain
|
||||
// if slowInc==2, soft_pwm == 251 will be the first to do short drops to zero. 252 will keep full heating
|
||||
return; // want full duty for the next ONE cycle again - so keep on heating and just wait for the next timer ovf
|
||||
}
|
||||
// otherwise moving towards FALL
|
||||
state=States::FALL;
|
||||
fastCounter = fastMax - 1;// we'll do 16-1 cycles of RISE
|
||||
TCNT0 = 255; // force overflow on the next clock cycle
|
||||
TCCR0B = (1 << CS00); // change prescaler to 1, i.e. 62.5kHz
|
||||
// must switch to inverting mode already here, because it takes a whole PWM cycle and it would make a "1" at the end of this pwm cycle
|
||||
// COM0B1 remains set both in inverting and non-inverting mode
|
||||
TCCR0A |= (1 << COM0B0); // inverting mode
|
||||
break;
|
||||
case States::FALL:
|
||||
OCR0B = (fastMax - fastCounter) << fastShift; // this is the same as in RISE, because now we are setting the zero part of duty due to inverting mode
|
||||
//TCCR0A |= (1 << COM0B0); // already set in ONE_TO_FALL
|
||||
if( fastCounter ){
|
||||
--fastCounter;
|
||||
} else { // end of FALL cycles, changing into state ZERO
|
||||
state = States::FALL_TO_ZERO;
|
||||
TCNT0 = 128; //@@TODO again - need to wait long enough to propagate the timer state changes
|
||||
OCR0B = 255;
|
||||
}
|
||||
break;
|
||||
case States::FALL_TO_ZERO:
|
||||
state = States::ZERO_START; // go to read new soft_pwm_bed value for the next cycle
|
||||
TCNT0 = 128;
|
||||
OCR0B = 255;
|
||||
TCCR0B = (1 << CS01); // change prescaler to 8, i.e. 7.8kHz
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,374 +0,0 @@
|
|||
//io_atmega2560.h
|
||||
#ifndef _IO_ATMEGA2560
|
||||
#define _IO_ATMEGA2560
|
||||
|
||||
|
||||
#define __PIN_P0 PINE
|
||||
#define __PIN_P1 PINE
|
||||
#define __PIN_P2 PINE
|
||||
#define __PIN_P3 PINE
|
||||
#define __PIN_P4 PING
|
||||
#define __PIN_P5 PINE
|
||||
#define __PIN_P6 PINH
|
||||
#define __PIN_P7 PINH
|
||||
#define __PIN_P8 PINH
|
||||
#define __PIN_P9 PINH
|
||||
#define __PIN_P10 PINB
|
||||
#define __PIN_P11 PINB
|
||||
#define __PIN_P12 PINB
|
||||
#define __PIN_P13 PINB
|
||||
#define __PIN_P14 PINJ
|
||||
#define __PIN_P15 PINJ
|
||||
#define __PIN_P16 PINH
|
||||
#define __PIN_P17 PINH
|
||||
#define __PIN_P18 PIND
|
||||
#define __PIN_P19 PIND
|
||||
#define __PIN_P20 PIND
|
||||
#define __PIN_P21 PIND
|
||||
#define __PIN_P22 PINA
|
||||
#define __PIN_P23 PINA
|
||||
#define __PIN_P24 PINA
|
||||
#define __PIN_P25 PINA
|
||||
#define __PIN_P26 PINA
|
||||
#define __PIN_P27 PINA
|
||||
#define __PIN_P28 PINA
|
||||
#define __PIN_P29 PINA
|
||||
#define __PIN_P30 PINC
|
||||
#define __PIN_P31 PINC
|
||||
#define __PIN_P32 PINC
|
||||
#define __PIN_P33 PINC
|
||||
#define __PIN_P34 PINC
|
||||
#define __PIN_P35 PINC
|
||||
#define __PIN_P36 PINC
|
||||
#define __PIN_P37 PINC
|
||||
#define __PIN_P38 PIND
|
||||
#define __PIN_P39 PING
|
||||
#define __PIN_P40 PING
|
||||
#define __PIN_P41 PING
|
||||
#define __PIN_P42 PINL
|
||||
#define __PIN_P43 PINL
|
||||
#define __PIN_P44 PINL
|
||||
#define __PIN_P45 PINL
|
||||
#define __PIN_P46 PINL
|
||||
#define __PIN_P47 PINL
|
||||
#define __PIN_P48 PINL
|
||||
#define __PIN_P49 PINL
|
||||
#define __PIN_P50 PINB
|
||||
#define __PIN_P51 PINB
|
||||
#define __PIN_P52 PINB
|
||||
#define __PIN_P53 PINB
|
||||
#define __PIN_P54 PINF
|
||||
#define __PIN_P55 PINF
|
||||
#define __PIN_P56 PINF
|
||||
#define __PIN_P57 PINF
|
||||
#define __PIN_P58 PINF
|
||||
#define __PIN_P59 PINF
|
||||
#define __PIN_P60 PINF
|
||||
#define __PIN_P61 PINF
|
||||
#define __PIN_P62 PINK
|
||||
#define __PIN_P63 PINK
|
||||
#define __PIN_P64 PINK
|
||||
#define __PIN_P65 PINK
|
||||
#define __PIN_P66 PINK
|
||||
#define __PIN_P67 PINK
|
||||
#define __PIN_P68 PINK
|
||||
#define __PIN_P69 PINK
|
||||
#define __PIN_P70 PING
|
||||
#define __PIN_P71 PING
|
||||
#define __PIN_P72 PINJ
|
||||
#define __PIN_P73 PINJ
|
||||
#define __PIN_P74 PINJ
|
||||
#define __PIN_P75 PINJ
|
||||
#define __PIN_P76 PINJ
|
||||
#define __PIN_P77 PINJ
|
||||
#define __PIN_P78 PINE
|
||||
#define __PIN_P79 PINE
|
||||
#define __PIN_P80 PINE
|
||||
#define __PIN_P81 PIND
|
||||
#define __PIN_P82 PIND
|
||||
#define __PIN_P83 PIND
|
||||
#define __PIN_P84 PINH
|
||||
#define __PIN_P85 PINH
|
||||
|
||||
#define __PORT_P0 PORTE
|
||||
#define __PORT_P1 PORTE
|
||||
#define __PORT_P2 PORTE
|
||||
#define __PORT_P3 PORTE
|
||||
#define __PORT_P4 PORTG
|
||||
#define __PORT_P5 PORTE
|
||||
#define __PORT_P6 PORTH
|
||||
#define __PORT_P7 PORTH
|
||||
#define __PORT_P8 PORTH
|
||||
#define __PORT_P9 PORTH
|
||||
#define __PORT_P10 PORTB
|
||||
#define __PORT_P11 PORTB
|
||||
#define __PORT_P12 PORTB
|
||||
#define __PORT_P13 PORTB
|
||||
#define __PORT_P14 PORTJ
|
||||
#define __PORT_P15 PORTJ
|
||||
#define __PORT_P16 PORTH
|
||||
#define __PORT_P17 PORTH
|
||||
#define __PORT_P18 PORTD
|
||||
#define __PORT_P19 PORTD
|
||||
#define __PORT_P20 PORTD
|
||||
#define __PORT_P21 PORTD
|
||||
#define __PORT_P22 PORTA
|
||||
#define __PORT_P23 PORTA
|
||||
#define __PORT_P24 PORTA
|
||||
#define __PORT_P25 PORTA
|
||||
#define __PORT_P26 PORTA
|
||||
#define __PORT_P27 PORTA
|
||||
#define __PORT_P28 PORTA
|
||||
#define __PORT_P29 PORTA
|
||||
#define __PORT_P30 PORTC
|
||||
#define __PORT_P31 PORTC
|
||||
#define __PORT_P32 PORTC
|
||||
#define __PORT_P33 PORTC
|
||||
#define __PORT_P34 PORTC
|
||||
#define __PORT_P35 PORTC
|
||||
#define __PORT_P36 PORTC
|
||||
#define __PORT_P37 PORTC
|
||||
#define __PORT_P38 PORTD
|
||||
#define __PORT_P39 PORTG
|
||||
#define __PORT_P40 PORTG
|
||||
#define __PORT_P41 PORTG
|
||||
#define __PORT_P42 PORTL
|
||||
#define __PORT_P43 PORTL
|
||||
#define __PORT_P44 PORTL
|
||||
#define __PORT_P45 PORTL
|
||||
#define __PORT_P46 PORTL
|
||||
#define __PORT_P47 PORTL
|
||||
#define __PORT_P48 PORTL
|
||||
#define __PORT_P49 PORTL
|
||||
#define __PORT_P50 PORTB
|
||||
#define __PORT_P51 PORTB
|
||||
#define __PORT_P52 PORTB
|
||||
#define __PORT_P53 PORTB
|
||||
#define __PORT_P54 PORTF
|
||||
#define __PORT_P55 PORTF
|
||||
#define __PORT_P56 PORTF
|
||||
#define __PORT_P57 PORTF
|
||||
#define __PORT_P58 PORTF
|
||||
#define __PORT_P59 PORTF
|
||||
#define __PORT_P60 PORTF
|
||||
#define __PORT_P61 PORTF
|
||||
#define __PORT_P62 PORTK
|
||||
#define __PORT_P63 PORTK
|
||||
#define __PORT_P64 PORTK
|
||||
#define __PORT_P65 PORTK
|
||||
#define __PORT_P66 PORTK
|
||||
#define __PORT_P67 PORTK
|
||||
#define __PORT_P68 PORTK
|
||||
#define __PORT_P69 PORTK
|
||||
#define __PORT_P70 PORTG
|
||||
#define __PORT_P71 PORTG
|
||||
#define __PORT_P72 PORTJ
|
||||
#define __PORT_P73 PORTJ
|
||||
#define __PORT_P74 PORTJ
|
||||
#define __PORT_P75 PORTJ
|
||||
#define __PORT_P76 PORTJ
|
||||
#define __PORT_P77 PORTJ
|
||||
#define __PORT_P78 PORTE
|
||||
#define __PORT_P79 PORTE
|
||||
#define __PORT_P80 PORTE
|
||||
#define __PORT_P81 PORTD
|
||||
#define __PORT_P82 PORTD
|
||||
#define __PORT_P83 PORTD
|
||||
#define __PORT_P84 PORTH
|
||||
#define __PORT_P85 PORTH
|
||||
|
||||
#define __DDR_P0 DDRE
|
||||
#define __DDR_P1 DDRE
|
||||
#define __DDR_P2 DDRE
|
||||
#define __DDR_P3 DDRE
|
||||
#define __DDR_P4 DDRG
|
||||
#define __DDR_P5 DDRE
|
||||
#define __DDR_P6 DDRH
|
||||
#define __DDR_P7 DDRH
|
||||
#define __DDR_P8 DDRH
|
||||
#define __DDR_P9 DDRH
|
||||
#define __DDR_P10 DDRB
|
||||
#define __DDR_P11 DDRB
|
||||
#define __DDR_P12 DDRB
|
||||
#define __DDR_P13 DDRB
|
||||
#define __DDR_P14 DDRJ
|
||||
#define __DDR_P15 DDRJ
|
||||
#define __DDR_P16 DDRH
|
||||
#define __DDR_P17 DDRH
|
||||
#define __DDR_P18 DDRD
|
||||
#define __DDR_P19 DDRD
|
||||
#define __DDR_P20 DDRD
|
||||
#define __DDR_P21 DDRD
|
||||
#define __DDR_P22 DDRA
|
||||
#define __DDR_P23 DDRA
|
||||
#define __DDR_P24 DDRA
|
||||
#define __DDR_P25 DDRA
|
||||
#define __DDR_P26 DDRA
|
||||
#define __DDR_P27 DDRA
|
||||
#define __DDR_P28 DDRA
|
||||
#define __DDR_P29 DDRA
|
||||
#define __DDR_P30 DDRC
|
||||
#define __DDR_P31 DDRC
|
||||
#define __DDR_P32 DDRC
|
||||
#define __DDR_P33 DDRC
|
||||
#define __DDR_P34 DDRC
|
||||
#define __DDR_P35 DDRC
|
||||
#define __DDR_P36 DDRC
|
||||
#define __DDR_P37 DDRC
|
||||
#define __DDR_P38 DDRD
|
||||
#define __DDR_P39 DDRG
|
||||
#define __DDR_P40 DDRG
|
||||
#define __DDR_P41 DDRG
|
||||
#define __DDR_P42 DDRL
|
||||
#define __DDR_P43 DDRL
|
||||
#define __DDR_P44 DDRL
|
||||
#define __DDR_P45 DDRL
|
||||
#define __DDR_P46 DDRL
|
||||
#define __DDR_P47 DDRL
|
||||
#define __DDR_P48 DDRL
|
||||
#define __DDR_P49 DDRL
|
||||
#define __DDR_P50 DDRB
|
||||
#define __DDR_P51 DDRB
|
||||
#define __DDR_P52 DDRB
|
||||
#define __DDR_P53 DDRB
|
||||
#define __DDR_P54 DDRF
|
||||
#define __DDR_P55 DDRF
|
||||
#define __DDR_P56 DDRF
|
||||
#define __DDR_P57 DDRF
|
||||
#define __DDR_P58 DDRF
|
||||
#define __DDR_P59 DDRF
|
||||
#define __DDR_P60 DDRF
|
||||
#define __DDR_P61 DDRF
|
||||
#define __DDR_P62 DDRK
|
||||
#define __DDR_P63 DDRK
|
||||
#define __DDR_P64 DDRK
|
||||
#define __DDR_P65 DDRK
|
||||
#define __DDR_P66 DDRK
|
||||
#define __DDR_P67 DDRK
|
||||
#define __DDR_P68 DDRK
|
||||
#define __DDR_P69 DDRK
|
||||
#define __DDR_P70 DDRG
|
||||
#define __DDR_P71 DDRG
|
||||
#define __DDR_P72 DDRJ
|
||||
#define __DDR_P73 DDRJ
|
||||
#define __DDR_P74 DDRJ
|
||||
#define __DDR_P75 DDRJ
|
||||
#define __DDR_P76 DDRJ
|
||||
#define __DDR_P77 DDRJ
|
||||
#define __DDR_P78 DDRE
|
||||
#define __DDR_P79 DDRE
|
||||
#define __DDR_P80 DDRE
|
||||
#define __DDR_P81 DDRD
|
||||
#define __DDR_P82 DDRD
|
||||
#define __DDR_P83 DDRD
|
||||
#define __DDR_P84 DDRH
|
||||
#define __DDR_P85 DDRH
|
||||
|
||||
#define __BIT_P0 0
|
||||
#define __BIT_P1 1
|
||||
#define __BIT_P2 4
|
||||
#define __BIT_P3 5
|
||||
#define __BIT_P4 5
|
||||
#define __BIT_P5 3
|
||||
#define __BIT_P6 3
|
||||
#define __BIT_P7 4
|
||||
#define __BIT_P8 5
|
||||
#define __BIT_P9 6
|
||||
#define __BIT_P10 4
|
||||
#define __BIT_P11 5
|
||||
#define __BIT_P12 6
|
||||
#define __BIT_P13 7
|
||||
#define __BIT_P14 1
|
||||
#define __BIT_P15 0
|
||||
#define __BIT_P16 0
|
||||
#define __BIT_P17 1
|
||||
#define __BIT_P18 3
|
||||
#define __BIT_P19 2
|
||||
#define __BIT_P20 1
|
||||
#define __BIT_P21 0
|
||||
#define __BIT_P22 0
|
||||
#define __BIT_P23 1
|
||||
#define __BIT_P24 2
|
||||
#define __BIT_P25 3
|
||||
#define __BIT_P26 4
|
||||
#define __BIT_P27 5
|
||||
#define __BIT_P28 6
|
||||
#define __BIT_P29 7
|
||||
#define __BIT_P30 7
|
||||
#define __BIT_P31 6
|
||||
#define __BIT_P32 5
|
||||
#define __BIT_P33 4
|
||||
#define __BIT_P34 3
|
||||
#define __BIT_P35 2
|
||||
#define __BIT_P36 1
|
||||
#define __BIT_P37 0
|
||||
#define __BIT_P38 7
|
||||
#define __BIT_P39 2
|
||||
#define __BIT_P40 1
|
||||
#define __BIT_P41 0
|
||||
#define __BIT_P42 7
|
||||
#define __BIT_P43 6
|
||||
#define __BIT_P44 5
|
||||
#define __BIT_P45 4
|
||||
#define __BIT_P46 3
|
||||
#define __BIT_P47 2
|
||||
#define __BIT_P48 1
|
||||
#define __BIT_P49 0
|
||||
#define __BIT_P50 3
|
||||
#define __BIT_P51 2
|
||||
#define __BIT_P52 1
|
||||
#define __BIT_P53 0
|
||||
#define __BIT_P54 0
|
||||
#define __BIT_P55 1
|
||||
#define __BIT_P56 2
|
||||
#define __BIT_P57 3
|
||||
#define __BIT_P58 4
|
||||
#define __BIT_P59 5
|
||||
#define __BIT_P60 6
|
||||
#define __BIT_P61 7
|
||||
#define __BIT_P62 0
|
||||
#define __BIT_P63 1
|
||||
#define __BIT_P64 2
|
||||
#define __BIT_P65 3
|
||||
#define __BIT_P66 4
|
||||
#define __BIT_P67 5
|
||||
#define __BIT_P68 6
|
||||
#define __BIT_P69 7
|
||||
#define __BIT_P70 4
|
||||
#define __BIT_P71 3
|
||||
#define __BIT_P72 2
|
||||
#define __BIT_P73 3
|
||||
#define __BIT_P74 7
|
||||
#define __BIT_P75 4
|
||||
#define __BIT_P76 5
|
||||
#define __BIT_P77 6
|
||||
#define __BIT_P78 2
|
||||
#define __BIT_P79 6
|
||||
#define __BIT_P80 7
|
||||
#define __BIT_P81 4
|
||||
#define __BIT_P82 5
|
||||
#define __BIT_P83 6
|
||||
#define __BIT_P84 2
|
||||
#define __BIT_P85 7
|
||||
|
||||
#define __BIT(pin) __BIT_P##pin
|
||||
#define __MSK(pin) (1 << __BIT(pin))
|
||||
|
||||
#define __PIN(pin) __PIN_P##pin
|
||||
#define __PORT(pin) __PORT_P##pin
|
||||
#define __DDR(pin) __DDR_P##pin
|
||||
|
||||
#define PIN(pin) __PIN(pin)
|
||||
#define PORT(pin) __PORT(pin)
|
||||
#define DDR(pin) __DDR(pin)
|
||||
|
||||
#define PIN_INP(pin) DDR(pin) &= ~__MSK(pin)
|
||||
#define PIN_OUT(pin) DDR(pin) |= __MSK(pin)
|
||||
#define PIN_CLR(pin) PORT(pin) &= ~__MSK(pin)
|
||||
#define PIN_SET(pin) PORT(pin) |= __MSK(pin)
|
||||
#define PIN_VAL(pin, val) if (val) PIN_SET(pin); else PIN_CLR(pin);
|
||||
#define PIN_GET(pin) (PIN(pin) & __MSK(pin))
|
||||
#define PIN_INQ(pin) (PORT(pin) & __MSK(pin))
|
||||
|
||||
|
||||
#endif //_IO_ATMEGA2560
|
||||
|
|
@ -1,14 +1,26 @@
|
|||
#include "la10compat.h"
|
||||
#include "Marlin.h"
|
||||
#include <float.h>
|
||||
|
||||
|
||||
static LA10C_MODE la10c_mode = LA10C_UNKNOWN;
|
||||
static LA10C_MODE la10c_mode = LA10C_UNKNOWN; // Current LA compatibility mode
|
||||
static float la10c_orig_jerk = 0; // Unadjusted/saved e-jerk
|
||||
|
||||
|
||||
LA10C_MODE la10c_mode_get()
|
||||
{
|
||||
return la10c_mode;
|
||||
}
|
||||
|
||||
|
||||
void la10c_mode_change(LA10C_MODE mode)
|
||||
{
|
||||
if(mode == la10c_mode) return;
|
||||
|
||||
// always restore to the last unadjusted E-jerk value
|
||||
if(la10c_orig_jerk)
|
||||
cs.max_jerk[E_AXIS] = la10c_orig_jerk;
|
||||
|
||||
SERIAL_ECHOPGM("LA10C: Linear Advance mode: ");
|
||||
switch(mode)
|
||||
{
|
||||
|
|
@ -17,14 +29,19 @@ void la10c_mode_change(LA10C_MODE mode)
|
|||
case LA10C_LA10: SERIAL_ECHOLNPGM("1.0"); break;
|
||||
}
|
||||
la10c_mode = mode;
|
||||
|
||||
// adjust the E-jerk if needed
|
||||
cs.max_jerk[E_AXIS] = la10c_jerk(cs.max_jerk[E_AXIS]);
|
||||
}
|
||||
|
||||
|
||||
// Approximate a LA10 value to a LA15 equivalent.
|
||||
static float la10c_convert(float k)
|
||||
{
|
||||
float new_K = k * 0.004 - 0.06;
|
||||
return (new_K < 0? 0: new_K);
|
||||
float new_K = k * 0.002 - 0.01;
|
||||
return new_K < 0? 0:
|
||||
new_K > (LA_K_MAX - FLT_EPSILON)? (LA_K_MAX - FLT_EPSILON):
|
||||
new_K;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -38,11 +55,37 @@ float la10c_value(float k)
|
|||
else if(k < 0)
|
||||
return -1;
|
||||
|
||||
la10c_mode_change(k < 10? LA10C_LA15: LA10C_LA10);
|
||||
la10c_mode_change(k < LA_LA10_MIN? LA10C_LA15: LA10C_LA10);
|
||||
}
|
||||
|
||||
if(la10c_mode == LA10C_LA15)
|
||||
return (k >= 0 && k < 10? k: -1);
|
||||
return (k >= 0 && k < LA_K_MAX? k: -1);
|
||||
else
|
||||
return (k >= 0? la10c_convert(k): -1);
|
||||
}
|
||||
|
||||
|
||||
float la10c_jerk(float j)
|
||||
{
|
||||
la10c_orig_jerk = j;
|
||||
|
||||
if(la10c_mode != LA10C_LA10)
|
||||
return 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_units_per_sq_second_normal[E_AXIS] < 2000)
|
||||
return j;
|
||||
|
||||
// bring low E-jerk values into equivalent LA 1.5 values by
|
||||
// flattening the response in the (0.3-4.5) range using a piecewise
|
||||
// function. Is it truly worth to preserve the difference between
|
||||
// 1.5/2.5 E-jerk for LA1.0? Probably not, but we try nonetheless.
|
||||
j = j < 0.3? j * 11.5:
|
||||
j < 4.5? j * 0.25 + 3.375:
|
||||
j;
|
||||
|
||||
SERIAL_ECHOPGM("LA10C: Adjusted E-Jerk: ");
|
||||
SERIAL_ECHOLN(j);
|
||||
return j;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,9 @@
|
|||
// compatbility mode is active the K factor is converted to a LA15
|
||||
// equivalent (that is, the return value is always a LA15 value).
|
||||
//
|
||||
// E-jerk<2 is also bumped in LA10 mode to restore the the printing speed
|
||||
// to values comparable to existing settings.
|
||||
//
|
||||
// Once the interpretation mode has been set it is kept until the mode
|
||||
// is explicitly reset. This is done to handle transparent fallback for
|
||||
// old firmware revisions in combination with the following gcode
|
||||
|
|
@ -31,9 +34,13 @@ enum __attribute__((packed)) LA10C_MODE
|
|||
LA10C_LA10 = 2
|
||||
};
|
||||
|
||||
// Explicitly set/reset the interpretation mode for la10c_value()
|
||||
// Explicitly set/get/reset the interpretation mode for la10c_value()
|
||||
void la10c_mode_change(LA10C_MODE mode);
|
||||
LA10C_MODE la10c_mode_get();
|
||||
static inline void la10c_reset() { la10c_mode_change(LA10C_UNKNOWN); }
|
||||
|
||||
// Return a LA15 K value according to the supplied value and mode
|
||||
float la10c_value(float k);
|
||||
|
||||
// Return an updated LA15 E-jerk value according to the current mode
|
||||
float la10c_jerk(float j);
|
||||
|
|
|
|||
|
|
@ -1,15 +1,17 @@
|
|||
//language.c
|
||||
#include "language.h"
|
||||
#include <avr/pgmspace.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/eeprom.h>
|
||||
#include "bootapp.h"
|
||||
|
||||
#include "Configuration.h"
|
||||
#include "pins.h"
|
||||
|
||||
#ifdef W25X20CL
|
||||
#include "w25x20cl.h"
|
||||
#endif //W25X20CL
|
||||
#ifdef XFLASH
|
||||
#include "xflash.h"
|
||||
#include "xflash_layout.h"
|
||||
#endif //XFLASH
|
||||
|
||||
// Currently active language selection.
|
||||
uint8_t lang_selected = 0;
|
||||
|
|
@ -17,17 +19,17 @@ uint8_t lang_selected = 0;
|
|||
|
||||
#if (LANG_MODE == 0) //primary language only
|
||||
|
||||
uint8_t lang_select(__attribute__((unused)) uint8_t lang) { return 0; }
|
||||
uint8_t lang_select(_UNUSED uint8_t lang) { return 0; }
|
||||
uint8_t lang_get_count() { return 1; }
|
||||
uint16_t lang_get_code(__attribute__((unused)) uint8_t lang) { return LANG_CODE_EN; }
|
||||
const char* lang_get_name_by_code(__attribute__((unused)) uint16_t code) { return _n("English"); }
|
||||
uint16_t lang_get_code(_UNUSED uint8_t lang) { return LANG_CODE_EN; }
|
||||
const char* lang_get_name_by_code(_UNUSED uint16_t code) { return _n("English"); }
|
||||
void lang_reset(void) { }
|
||||
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] PROGMEM_I2 = "_SEC_LANG";
|
||||
const char _SEC_LANG[LANG_SIZE_RESERVED] __attribute__((aligned(SPM_PAGESIZE))) PROGMEM_I2 = "_SEC_LANG";
|
||||
|
||||
//primary language signature
|
||||
const uint32_t _PRI_LANG_SIGNATURE[1] __attribute__((section(".progmem0"))) = {0xffffffff};
|
||||
|
|
@ -40,7 +42,7 @@ const char* lang_get_translation(const char* s)
|
|||
if (lang_selected == 0) return s + 2; //primary language selected, return orig. str.
|
||||
if (lang_table == 0) return s + 2; //sec. lang table not found, return orig. str.
|
||||
uint16_t ui = pgm_read_word(((uint16_t*)s)); //read string id
|
||||
if (ui == 0xffff) return s + 2; //translation not found, return orig. str.
|
||||
if (ui == 0xffff) return s + 2; //id not assigned, return orig. str.
|
||||
ui = pgm_read_word(((uint16_t*)(((char*)lang_table + 16 + ui*2)))); //read relative offset
|
||||
if (pgm_read_byte(((uint8_t*)((char*)lang_table + ui))) == 0) //read first character
|
||||
return s + 2;//zero length string == not translated, return orig. str.
|
||||
|
|
@ -54,7 +56,7 @@ uint8_t lang_select(uint8_t lang)
|
|||
lang_table = 0;
|
||||
lang_selected = lang;
|
||||
}
|
||||
#ifdef W25X20CL
|
||||
#ifdef XFLASH
|
||||
if (lang_get_code(lang) == lang_get_code(LANG_ID_SEC)) lang = LANG_ID_SEC;
|
||||
if (lang == LANG_ID_SEC) //current secondary language
|
||||
{
|
||||
|
|
@ -68,7 +70,7 @@ uint8_t lang_select(uint8_t lang)
|
|||
}
|
||||
}
|
||||
}
|
||||
#else //W25X20CL
|
||||
#else //XFLASH
|
||||
if (lang == LANG_ID_SEC)
|
||||
{
|
||||
uint16_t table = _SEC_LANG_TABLE;
|
||||
|
|
@ -82,7 +84,7 @@ uint8_t lang_select(uint8_t lang)
|
|||
}
|
||||
}
|
||||
}
|
||||
#endif //W25X20CL
|
||||
#endif //XFLASH
|
||||
if (lang_selected == lang)
|
||||
{
|
||||
eeprom_update_byte((unsigned char*)EEPROM_LANG, lang_selected);
|
||||
|
|
@ -107,19 +109,19 @@ uint8_t lang_get_count()
|
|||
{
|
||||
if (pgm_read_dword(((uint32_t*)(_PRI_LANG_SIGNATURE))) == 0xffffffff)
|
||||
return 1; //signature not set - only primary language will be available
|
||||
#ifdef W25X20CL
|
||||
W25X20CL_SPI_ENTER();
|
||||
#ifdef XFLASH
|
||||
XFLASH_SPI_ENTER();
|
||||
uint8_t count = 2; //count = 1+n (primary + secondary + all in xflash)
|
||||
uint32_t addr = 0x00000; //start of xflash
|
||||
uint32_t addr = LANG_OFFSET;
|
||||
lang_table_header_t header; //table header structure
|
||||
while (1)
|
||||
{
|
||||
w25x20cl_rd_data(addr, (uint8_t*)&header, sizeof(lang_table_header_t)); //read table header from xflash
|
||||
xflash_rd_data(addr, (uint8_t*)&header, sizeof(lang_table_header_t)); //read table header from xflash
|
||||
if (header.magic != LANG_MAGIC) break; //break if magic not valid
|
||||
addr += header.size; //calc address of next table
|
||||
count++; //inc counter
|
||||
}
|
||||
#else //W25X20CL
|
||||
#else //XFLASH
|
||||
uint16_t table = _SEC_LANG_TABLE;
|
||||
uint8_t count = 1; //count = 1 (primary)
|
||||
while (pgm_read_dword(((uint32_t*)table)) == LANG_MAGIC) //magic valid
|
||||
|
|
@ -127,14 +129,14 @@ uint8_t lang_get_count()
|
|||
table += pgm_read_word((uint16_t*)(table + 4));
|
||||
count++;
|
||||
}
|
||||
#endif //W25X20CL
|
||||
#endif //XFLASH
|
||||
return count;
|
||||
}
|
||||
|
||||
uint8_t lang_get_header(uint8_t lang, lang_table_header_t* header, uint32_t* offset)
|
||||
{
|
||||
if (lang == LANG_ID_PRI) return 0; //primary lang not supported for this function
|
||||
#ifdef W25X20CL
|
||||
#ifdef XFLASH
|
||||
if (lang == LANG_ID_SEC)
|
||||
{
|
||||
uint16_t ui = _SEC_LANG_TABLE; //table pointer
|
||||
|
|
@ -142,18 +144,18 @@ uint8_t lang_get_header(uint8_t lang, lang_table_header_t* header, uint32_t* off
|
|||
if (offset) *offset = ui;
|
||||
return (header->magic == LANG_MAGIC)?1:0; //return 1 if magic valid
|
||||
}
|
||||
W25X20CL_SPI_ENTER();
|
||||
uint32_t addr = 0x00000; //start of xflash
|
||||
XFLASH_SPI_ENTER();
|
||||
uint32_t addr = LANG_OFFSET;
|
||||
lang--;
|
||||
while (1)
|
||||
{
|
||||
w25x20cl_rd_data(addr, (uint8_t*)(header), sizeof(lang_table_header_t)); //read table header from xflash
|
||||
xflash_rd_data(addr, (uint8_t*)(header), sizeof(lang_table_header_t)); //read table header from xflash
|
||||
if (header->magic != LANG_MAGIC) break; //break if not valid
|
||||
if (offset) *offset = addr;
|
||||
if (--lang == 0) return 1;
|
||||
addr += header->size; //calc address of next table
|
||||
}
|
||||
#else //W25X20CL
|
||||
#else //XFLASH
|
||||
if (lang == LANG_ID_SEC)
|
||||
{
|
||||
uint16_t ui = _SEC_LANG_TABLE; //table pointer
|
||||
|
|
@ -161,32 +163,32 @@ uint8_t lang_get_header(uint8_t lang, lang_table_header_t* header, uint32_t* off
|
|||
if (offset) *offset = ui;
|
||||
return (header->magic == LANG_MAGIC)?1:0; //return 1 if magic valid
|
||||
}
|
||||
#endif //W25X20CL
|
||||
#endif //XFLASH
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t lang_get_code(uint8_t lang)
|
||||
{
|
||||
if (lang == LANG_ID_PRI) return LANG_CODE_EN; //primary lang = EN
|
||||
#ifdef W25X20CL
|
||||
#ifdef XFLASH
|
||||
if (lang == LANG_ID_SEC)
|
||||
{
|
||||
uint16_t ui = _SEC_LANG_TABLE; //table pointer
|
||||
if (pgm_read_dword(((uint32_t*)(ui + 0))) != LANG_MAGIC) return LANG_CODE_XX; //magic not valid
|
||||
return pgm_read_word(((uint32_t*)(ui + 10))); //return lang code from progmem
|
||||
}
|
||||
W25X20CL_SPI_ENTER();
|
||||
uint32_t addr = 0x00000; //start of xflash
|
||||
XFLASH_SPI_ENTER();
|
||||
uint32_t addr = LANG_OFFSET;
|
||||
lang_table_header_t header; //table header structure
|
||||
lang--;
|
||||
while (1)
|
||||
{
|
||||
w25x20cl_rd_data(addr, (uint8_t*)&header, sizeof(lang_table_header_t)); //read table header from xflash
|
||||
xflash_rd_data(addr, (uint8_t*)&header, sizeof(lang_table_header_t)); //read table header from xflash
|
||||
if (header.magic != LANG_MAGIC) break; //break if not valid
|
||||
if (--lang == 0) return header.code;
|
||||
addr += header.size; //calc address of next table
|
||||
}
|
||||
#else //W25X20CL
|
||||
#else //XFLASH
|
||||
uint16_t table = _SEC_LANG_TABLE;
|
||||
uint8_t count = 1; //count = 1 (primary)
|
||||
while (pgm_read_dword((uint32_t*)table) == LANG_MAGIC) //magic valid
|
||||
|
|
@ -195,7 +197,7 @@ uint16_t lang_get_code(uint8_t lang)
|
|||
table += pgm_read_word((uint16_t*)(table + 4));
|
||||
count++;
|
||||
}
|
||||
#endif //W25X20CL
|
||||
#endif //XFLASH
|
||||
return LANG_CODE_XX;
|
||||
}
|
||||
|
||||
|
|
@ -210,6 +212,46 @@ const char* lang_get_name_by_code(uint16_t code)
|
|||
case LANG_CODE_FR: return _n("Francais");
|
||||
case LANG_CODE_IT: return _n("Italiano");
|
||||
case LANG_CODE_PL: return _n("Polski");
|
||||
#ifdef COMMUNITY_LANGUAGE_SUPPORT //Community language support
|
||||
#ifdef COMMUNITY_LANG_GROUP1_NL
|
||||
case LANG_CODE_NL: return _n("Nederlands"); //community Dutch contribution
|
||||
#endif // COMMUNITY_LANG_GROUP1_NL
|
||||
#ifdef COMMUNITY_LANG_GROUP1_SV
|
||||
case LANG_CODE_SV: return _n("Svenska"); //community Swedish contribution
|
||||
#endif // COMMUNITY_LANG_GROUP1_SV
|
||||
#ifdef COMMUNITY_LANG_GROUP1_NO
|
||||
case LANG_CODE_NO: return _n("Norsk"); //community Swedish contribution
|
||||
#endif // COMMUNITY_LANG_GROUP1_NO
|
||||
#ifdef COMMUNITY_LANG_GROUP1_DA
|
||||
case LANG_CODE_DA: return _n("Dansk"); //community Danish contribution
|
||||
#endif // COMMUNITY_LANG_GROUP1_DA
|
||||
#ifdef COMMUNITY_LANG_GROUP1_SK
|
||||
case LANG_CODE_SK: return _n("Slovencina"); //community Slovak contribution
|
||||
#endif // COMMUNITY_LANG_GROUP1_SK
|
||||
#ifdef COMMUNITY_LANG_GROUP1_SL
|
||||
case LANG_CODE_SL: return _n("Slovenscina"); //community Slovanian contribution
|
||||
#endif // COMMUNITY_LANG_GROUP1_SL
|
||||
#ifdef COMMUNITY_LANG_GROUP1_HU
|
||||
case LANG_CODE_HU: return _n("Magyar"); //community Hungarian contribution
|
||||
#endif // COMMUNITY_LANG_GROUP1_HU
|
||||
#ifdef COMMUNITY_LANG_GROUP1_LB
|
||||
case LANG_CODE_LB: return _n("Letzebuergesch"); //community Luxembourgish contribution
|
||||
#endif // COMMUNITY_LANG_GROUP1_LB
|
||||
#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
|
||||
case LANG_CODE_LT: return _n("Lietuviu"); //community Lithuanian contribution
|
||||
#endif // COMMUNITY_LANG_GROUP2_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
|
||||
// case LANG_CODE_QR: return _n("New language"); //community contribution
|
||||
//#endif // COMMUNITY_LANG_GROUP1_QR
|
||||
#endif // COMMUNITY_LANGUAGE_SUPPORT
|
||||
}
|
||||
return _n("??");
|
||||
}
|
||||
|
|
@ -268,5 +310,5 @@ void lang_boot_update_start(uint8_t lang)
|
|||
{
|
||||
uint8_t cnt = lang_get_count();
|
||||
if ((lang < 2) || (lang > cnt)) return; //only languages from xflash can be selected
|
||||
bootapp_reboot_user0(lang << 4);
|
||||
bootapp_reboot_user0(lang << 3);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,8 +5,11 @@
|
|||
|
||||
|
||||
#include "config.h"
|
||||
#include "macros.h"
|
||||
#include <inttypes.h>
|
||||
//#include <stdio.h>
|
||||
#ifdef DEBUG_SEC_LANG
|
||||
#include <stdio.h>
|
||||
#endif //DEBUG_SEC_LANG
|
||||
|
||||
#define PROTOCOL_VERSION "1.0"
|
||||
|
||||
|
|
@ -18,19 +21,15 @@
|
|||
#define MACHINE_UUID "00000000-0000-0000-0000-000000000000"
|
||||
#endif
|
||||
|
||||
#define MSG_FW_VERSION "Firmware"
|
||||
|
||||
#define STRINGIFY_(n) #n
|
||||
#define STRINGIFY(n) STRINGIFY_(n)
|
||||
|
||||
#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
|
||||
#define _i(s) _I(s)
|
||||
#define _T(s) s
|
||||
#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
|
||||
#else //(LANG_MODE == 0)
|
||||
// section .loc_sec (originaly .progmem0) will be used for localized translated strings
|
||||
#define PROGMEM_I2 __attribute__((section(".loc_sec")))
|
||||
|
|
@ -42,9 +41,12 @@
|
|||
#define ISTR(s) "\xff\xff" s
|
||||
#define _i(s) lang_get_translation(_I(s))
|
||||
#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)
|
||||
#define _n(s) _N(s) // declare and return untranslated string
|
||||
#define _R(s) (s) // return reference to translatable string (for warning suppression)
|
||||
|
||||
/** @brief lang_table_header_t structure - (size= 16byte) */
|
||||
typedef struct
|
||||
|
|
@ -96,6 +98,45 @@ typedef struct
|
|||
#define LANG_CODE_FR 0x6672 //!<'fr'
|
||||
#define LANG_CODE_IT 0x6974 //!<'it'
|
||||
#define LANG_CODE_PL 0x706c //!<'pl'
|
||||
#ifdef COMMUNITY_LANGUAGE_SUPPORT //Community language support
|
||||
#ifdef COMMUNITY_LANG_GROUP1_NL
|
||||
#define LANG_CODE_NL 0x6e6c //!<'nl'
|
||||
#endif // COMMUNITY_LANG_GROUP1_NL
|
||||
#ifdef COMMUNITY_LANG_GROUP1_SV
|
||||
#define LANG_CODE_SV 0x7376 //!<'sv'
|
||||
#endif // COMMUNITY_LANG_GROUP1_SV
|
||||
#ifdef COMMUNITY_LANG_GROUP1_NO
|
||||
#define LANG_CODE_NO 0x6E6F //!<'no'
|
||||
#endif // COMMUNITY_LANG_GROUP1_NO
|
||||
#ifdef COMMUNITY_LANG_GROUP1_DA
|
||||
#define LANG_CODE_DA 0x6461 //!<'da'
|
||||
#endif // COMMUNITY_LANG_GROUP1_DA
|
||||
#ifdef COMMUNITY_LANG_GROUP1_SL
|
||||
#define LANG_CODE_SL 0x736C //!<'sl'
|
||||
#endif // COMMUNITY_LANG_GROUP1_SL
|
||||
#ifdef COMMUNITY_LANG_GROUP1_HU
|
||||
#define LANG_CODE_HU 0x6875 //!<'hu'
|
||||
#endif // COMMUNITY_LANG_GROUP1_HU
|
||||
#ifdef COMMUNITY_LANG_GROUP1_LB
|
||||
#define LANG_CODE_LB 0x6C62 //!<'lb'
|
||||
#endif // COMMUNITY_LANG_GROUP1_LB
|
||||
#ifdef COMMUNITY_LANG_GROUP1_HR
|
||||
#define LANG_CODE_HR 0x6872 //!<'hr'
|
||||
#endif // COMMUNITY_LANG_GROUP1_HR
|
||||
#ifdef COMMUNITY_LANG_GROUP2_LT
|
||||
#define LANG_CODE_LT 0x6C74 //!<'lt'
|
||||
#endif // COMMUNITY_LANG_GROUP2_LT
|
||||
#ifdef COMMUNITY_LANG_GROUP1_SK
|
||||
#define LANG_CODE_SK 0x736b //!<'sk'
|
||||
#endif // COMMUNITY_LANG_GROUP1_SK
|
||||
#ifdef COMMUNITY_LANG_GROUP1_RO
|
||||
#define LANG_CODE_RO 0x726F //!<'ro'
|
||||
#endif // COMMUNITY_LANG_GROUP1_RO
|
||||
//Use the 3 lines below as a template and replace 'QR', '0X7172' and 'qr'
|
||||
//#ifdef COMMUNITY_LANG_GROUP1_QR
|
||||
//#define LANG_CODE_QR 0x7172 //!<'qr'
|
||||
//#endif // COMMUNITY_LANG_GROUP1_QR
|
||||
#endif // COMMUNITY_LANGUAGE_SUPPORT
|
||||
///@}
|
||||
|
||||
#if defined(__cplusplus)
|
||||
|
|
@ -108,9 +149,7 @@ extern uint8_t lang_selected;
|
|||
#if (LANG_MODE != 0)
|
||||
extern const char _SEC_LANG[LANG_SIZE_RESERVED];
|
||||
extern const char* lang_get_translation(const char* s);
|
||||
/** @def _SEC_LANG_TABLE
|
||||
* @brief Align table to start of 256 byte page */
|
||||
#define _SEC_LANG_TABLE ((((uint16_t)&_SEC_LANG) + 0x00ff) & 0xff00)
|
||||
#define _SEC_LANG_TABLE ((uint16_t)&_SEC_LANG)
|
||||
#endif //(LANG_MODE != 0)
|
||||
|
||||
/** @brief selects language, eeprom is updated in case of success */
|
||||
|
|
|
|||
166
Firmware/lcd.cpp
166
Firmware/lcd.cpp
|
|
@ -66,6 +66,8 @@
|
|||
#define LCD_RS_FLAG 0x01
|
||||
#define LCD_HALF_FLAG 0x02
|
||||
|
||||
constexpr uint8_t row_offsets[] PROGMEM = { 0x00, 0x40, 0x14, 0x54 };
|
||||
|
||||
FILE _lcdout; // = {0}; Global variable is always zero initialized, no need to explicitly state that.
|
||||
|
||||
uint8_t lcd_displayfunction = 0;
|
||||
|
|
@ -329,13 +331,30 @@ void lcd_no_autoscroll(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
/// @brief set the current LCD row
|
||||
/// @param row LCD row number, ranges from 0 to LCD_HEIGHT - 1
|
||||
static void FORCE_INLINE lcd_set_current_row(uint8_t row)
|
||||
{
|
||||
lcd_currline = min(row, LCD_HEIGHT - 1);
|
||||
}
|
||||
|
||||
/// @brief Calculate the LCD row offset
|
||||
/// @param row LCD row number, ranges from 0 to LCD_HEIGHT - 1
|
||||
/// @return row offset which the LCD register understands
|
||||
static uint8_t __attribute__((noinline)) lcd_get_row_offset(uint8_t row)
|
||||
{
|
||||
return pgm_read_byte(row_offsets + min(row, LCD_HEIGHT - 1));
|
||||
}
|
||||
|
||||
void lcd_set_cursor(uint8_t col, uint8_t row)
|
||||
{
|
||||
int row_offsets[] = { 0x00, 0x40, 0x14, 0x54 };
|
||||
if (row >= LCD_HEIGHT)
|
||||
row = LCD_HEIGHT - 1; // we count rows starting w/0
|
||||
lcd_currline = row;
|
||||
lcd_command(LCD_SETDDRAMADDR | (col + row_offsets[row]));
|
||||
lcd_set_current_row(row);
|
||||
lcd_command(LCD_SETDDRAMADDR | (col + lcd_get_row_offset(lcd_currline)));
|
||||
}
|
||||
|
||||
void lcd_set_cursor_column(uint8_t col)
|
||||
{
|
||||
lcd_command(LCD_SETDDRAMADDR | (col + lcd_get_row_offset(lcd_currline)));
|
||||
}
|
||||
|
||||
// Allows us to fill the first 8 CGRAM locations
|
||||
|
|
@ -344,7 +363,7 @@ void lcd_createChar_P(uint8_t location, const uint8_t* charmap)
|
|||
{
|
||||
location &= 0x7; // we only have 8 locations 0-7
|
||||
lcd_command(LCD_SETCGRAMADDR | (location << 3));
|
||||
for (int i=0; i<8; i++)
|
||||
for (uint8_t i = 0; i < 8; i++)
|
||||
lcd_send(pgm_read_byte(&charmap[i]), HIGH);
|
||||
}
|
||||
|
||||
|
|
@ -486,11 +505,17 @@ void lcd_escape_write(uint8_t chr)
|
|||
#endif //VT100
|
||||
|
||||
|
||||
int lcd_putc(int c)
|
||||
int lcd_putc(char c)
|
||||
{
|
||||
return fputc(c, lcdout);
|
||||
}
|
||||
|
||||
int lcd_putc_at(uint8_t c, uint8_t r, char ch)
|
||||
{
|
||||
lcd_set_cursor(c, r);
|
||||
return fputc(ch, lcdout);
|
||||
}
|
||||
|
||||
int lcd_puts_P(const char* str)
|
||||
{
|
||||
return fputs_P(str, lcdout);
|
||||
|
|
@ -522,6 +547,26 @@ void lcd_print(const char* s)
|
|||
while (*s) lcd_write(*(s++));
|
||||
}
|
||||
|
||||
char lcd_print_pad(const char* s, uint8_t len)
|
||||
{
|
||||
while (len && *s) {
|
||||
lcd_write(*(s++));
|
||||
--len;
|
||||
}
|
||||
lcd_space(len);
|
||||
return *s;
|
||||
}
|
||||
|
||||
uint8_t lcd_print_pad_P(const char* s, uint8_t len)
|
||||
{
|
||||
while (len && pgm_read_byte(s)) {
|
||||
lcd_write(pgm_read_byte(s++));
|
||||
--len;
|
||||
}
|
||||
lcd_space(len);
|
||||
return len;
|
||||
}
|
||||
|
||||
void lcd_print(char c, int base)
|
||||
{
|
||||
lcd_print((long) c, base);
|
||||
|
|
@ -567,16 +612,10 @@ void lcd_print(unsigned long n, int base)
|
|||
lcd_printNumber(n, base);
|
||||
}
|
||||
|
||||
void lcd_print(double n, int digits)
|
||||
{
|
||||
lcd_printFloat(n, digits);
|
||||
}
|
||||
|
||||
|
||||
void lcd_printNumber(unsigned long n, uint8_t base)
|
||||
{
|
||||
unsigned char buf[8 * sizeof(long)]; // Assumes 8-bit chars.
|
||||
unsigned long i = 0;
|
||||
uint8_t i = 0;
|
||||
if (n == 0)
|
||||
{
|
||||
lcd_print('0');
|
||||
|
|
@ -591,37 +630,6 @@ void lcd_printNumber(unsigned long n, uint8_t base)
|
|||
lcd_print((char) (buf[i - 1] < 10 ? '0' + buf[i - 1] : 'A' + buf[i - 1] - 10));
|
||||
}
|
||||
|
||||
void lcd_printFloat(double number, uint8_t digits)
|
||||
{
|
||||
// Handle negative numbers
|
||||
if (number < 0.0)
|
||||
{
|
||||
lcd_print('-');
|
||||
number = -number;
|
||||
}
|
||||
// Round correctly so that print(1.999, 2) prints as "2.00"
|
||||
double rounding = 0.5;
|
||||
for (uint8_t i=0; i<digits; ++i)
|
||||
rounding /= 10.0;
|
||||
number += rounding;
|
||||
// Extract the integer part of the number and print it
|
||||
unsigned long int_part = (unsigned long)number;
|
||||
double remainder = number - (double)int_part;
|
||||
lcd_print(int_part);
|
||||
// Print the decimal point, but only if there are digits beyond
|
||||
if (digits > 0)
|
||||
lcd_print('.');
|
||||
// Extract digits from the remainder one at a time
|
||||
while (digits-- > 0)
|
||||
{
|
||||
remainder *= 10.0;
|
||||
int toPrint = int(remainder);
|
||||
lcd_print(toPrint);
|
||||
remainder -= toPrint;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint8_t lcd_draw_update = 2;
|
||||
int32_t lcd_encoder = 0;
|
||||
uint8_t lcd_encoder_bits = 0;
|
||||
|
|
@ -632,14 +640,11 @@ uint8_t lcd_button_pressed = 0;
|
|||
uint8_t lcd_update_enabled = 1;
|
||||
|
||||
uint32_t lcd_next_update_millis = 0;
|
||||
uint8_t lcd_status_update_delay = 0;
|
||||
|
||||
|
||||
|
||||
lcd_longpress_func_t lcd_longpress_func = 0;
|
||||
|
||||
lcd_charsetup_func_t lcd_charsetup_func = 0;
|
||||
|
||||
lcd_lcdupdate_func_t lcd_lcdupdate_func = 0;
|
||||
|
||||
static ShortTimer buttonBlanking;
|
||||
|
|
@ -698,6 +703,7 @@ void lcd_update(uint8_t lcdDrawUpdateOverride)
|
|||
|
||||
void lcd_update_enable(uint8_t enabled)
|
||||
{
|
||||
// printf_P(PSTR("lcd_update_enable(%u -> %u)\n"), lcd_update_enabled, enabled);
|
||||
if (lcd_update_enabled != enabled)
|
||||
{
|
||||
lcd_update_enabled = enabled;
|
||||
|
|
@ -712,8 +718,6 @@ void lcd_update_enable(uint8_t enabled)
|
|||
lcd_next_update_millis = _millis() - 1;
|
||||
// Full update.
|
||||
lcd_clear();
|
||||
if (lcd_charsetup_func)
|
||||
lcd_charsetup_func();
|
||||
lcd_update(2);
|
||||
} else
|
||||
{
|
||||
|
|
@ -722,6 +726,10 @@ void lcd_update_enable(uint8_t enabled)
|
|||
}
|
||||
}
|
||||
|
||||
bool lcd_longpress_trigger = 0;
|
||||
|
||||
// WARNING: this function is called from the temperature ISR.
|
||||
// Only update flags, but do not perform any menu/lcd operation!
|
||||
void lcd_buttons_update(void)
|
||||
{
|
||||
static uint8_t lcd_long_press_active = 0;
|
||||
|
|
@ -731,7 +739,6 @@ void lcd_buttons_update(void)
|
|||
|
||||
if (READ(BTN_ENC) == 0)
|
||||
{ //button is pressed
|
||||
lcd_timeoutToStatus.start();
|
||||
if (!buttonBlanking.running() || buttonBlanking.expired(BUTTON_BLANKING_TIME)) {
|
||||
buttonBlanking.start();
|
||||
safetyTimer.start();
|
||||
|
|
@ -743,9 +750,7 @@ void lcd_buttons_update(void)
|
|||
else if (longPressTimer.expired(LONG_PRESS_TIME))
|
||||
{
|
||||
lcd_long_press_active = 1;
|
||||
//long press is not possible in modal mode
|
||||
if (lcd_longpress_func && lcd_update_enabled)
|
||||
lcd_longpress_func();
|
||||
lcd_longpress_trigger = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -916,28 +921,6 @@ const uint8_t lcd_chardata_clock[8] PROGMEM = {
|
|||
B00000,
|
||||
B00000}; //thanks Sonny Mounicou
|
||||
|
||||
const uint8_t lcd_chardata_arrup[8] PROGMEM = {
|
||||
B00100,
|
||||
B01110,
|
||||
B11111,
|
||||
B00000,
|
||||
B00000,
|
||||
B00000,
|
||||
B00000,
|
||||
B00000};
|
||||
|
||||
const uint8_t lcd_chardata_arrdown[8] PROGMEM = {
|
||||
B00000,
|
||||
B00000,
|
||||
B00000,
|
||||
B00000,
|
||||
B00000,
|
||||
B10001,
|
||||
B01010,
|
||||
B00100};
|
||||
|
||||
|
||||
|
||||
void lcd_set_custom_characters(void)
|
||||
{
|
||||
lcd_createChar_P(LCD_STR_BEDTEMP[0], lcd_chardata_bedTemp);
|
||||
|
|
@ -948,28 +931,6 @@ void lcd_set_custom_characters(void)
|
|||
lcd_createChar_P(LCD_STR_FOLDER[0], lcd_chardata_folder);
|
||||
lcd_createChar_P(LCD_STR_FEEDRATE[0], lcd_chardata_feedrate);
|
||||
lcd_createChar_P(LCD_STR_CLOCK[0], lcd_chardata_clock);
|
||||
//lcd_createChar_P(LCD_STR_ARROW_UP[0], lcd_chardata_arrup);
|
||||
//lcd_createChar_P(LCD_STR_ARROW_DOWN[0], lcd_chardata_arrdown);
|
||||
}
|
||||
|
||||
void lcd_set_custom_characters_arrows(void)
|
||||
{
|
||||
lcd_createChar_P(1, lcd_chardata_arrdown);
|
||||
}
|
||||
|
||||
const uint8_t lcd_chardata_progress[8] PROGMEM = {
|
||||
B11111,
|
||||
B11111,
|
||||
B11111,
|
||||
B11111,
|
||||
B11111,
|
||||
B11111,
|
||||
B11111,
|
||||
B11111};
|
||||
|
||||
void lcd_set_custom_characters_progress(void)
|
||||
{
|
||||
lcd_createChar_P(1, lcd_chardata_progress);
|
||||
}
|
||||
|
||||
const uint8_t lcd_chardata_arr2down[8] PROGMEM = {
|
||||
|
|
@ -993,12 +954,7 @@ const uint8_t lcd_chardata_confirm[8] PROGMEM = {
|
|||
|
||||
void lcd_set_custom_characters_nextpage(void)
|
||||
{
|
||||
lcd_createChar_P(1, lcd_chardata_arr2down);
|
||||
lcd_createChar_P(2, lcd_chardata_confirm);
|
||||
}
|
||||
|
||||
void lcd_set_custom_characters_degree(void)
|
||||
{
|
||||
lcd_createChar_P(1, lcd_chardata_degree);
|
||||
lcd_createChar_P(LCD_STR_ARROW_2_DOWN[0], lcd_chardata_arr2down);
|
||||
lcd_createChar_P(LCD_STR_CONFIRM[0], lcd_chardata_confirm);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -37,26 +37,38 @@ extern void lcd_no_autoscroll(void);*/
|
|||
|
||||
extern void lcd_set_cursor(uint8_t col, uint8_t row);
|
||||
|
||||
/// @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_createChar_P(uint8_t, const uint8_t*);
|
||||
|
||||
|
||||
extern int lcd_putc(int c);
|
||||
// char c is non-standard, however it saves 1B on stack
|
||||
extern int lcd_putc(char c);
|
||||
extern int lcd_putc_at(uint8_t c, uint8_t r, char ch);
|
||||
|
||||
extern int lcd_puts_P(const char* str);
|
||||
extern int lcd_puts_at_P(uint8_t c, uint8_t r, const char* str);
|
||||
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 char 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"
|
||||
|
|
@ -104,11 +116,8 @@ 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 lcd_charsetup_func_t lcd_charsetup_func;
|
||||
extern bool lcd_longpress_trigger;
|
||||
|
||||
extern lcd_lcdupdate_func_t lcd_lcdupdate_func;
|
||||
|
||||
|
|
@ -187,29 +196,28 @@ private:
|
|||
|
||||
|
||||
//Custom characters defined in the first 8 characters of the LCD
|
||||
#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
|
||||
#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_ARROW_2_DOWN "\x06"
|
||||
#define LCD_STR_CLOCK "\x07"
|
||||
#define LCD_STR_CONFIRM "\x07"
|
||||
#define LCD_STR_ARROW_RIGHT "\x7E" //from the default character set
|
||||
#define LCD_STR_SOLID_BLOCK "\xFF" //from the default character set
|
||||
|
||||
extern void lcd_set_custom_characters(void);
|
||||
extern void lcd_set_custom_characters_arrows(void);
|
||||
extern void lcd_set_custom_characters_progress(void);
|
||||
extern void lcd_set_custom_characters_nextpage(void);
|
||||
extern void lcd_set_custom_characters_degree(void);
|
||||
|
||||
//! @brief Consume click event
|
||||
//! @brief Consume click and longpress event
|
||||
inline void lcd_consume_click()
|
||||
{
|
||||
lcd_button_pressed = 0;
|
||||
lcd_buttons &= 0xff^EN_C;
|
||||
lcd_longpress_trigger = 0;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,93 @@
|
|||
#ifndef MACROS_H
|
||||
#define MACROS_H
|
||||
|
||||
#include <avr/interrupt.h> //for cli() and sei()
|
||||
|
||||
#define FORCE_INLINE __attribute__((always_inline)) inline
|
||||
#define _UNUSED __attribute__((unused))
|
||||
|
||||
#ifndef CRITICAL_SECTION_START
|
||||
#define CRITICAL_SECTION_START unsigned char _sreg = SREG; cli();
|
||||
#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)
|
||||
|
||||
// Macros for bit masks
|
||||
#undef _BV
|
||||
#define _BV(n) (1<<(n))
|
||||
#define TEST(n,b) (!!((n)&_BV(b)))
|
||||
#define SET_BIT_TO(N,B,TF) do{ if (TF) SBI(N,B); else CBI(N,B); }while(0)
|
||||
|
||||
#ifndef SBI
|
||||
#define SBI(A,B) (A |= (1 << (B)))
|
||||
#endif
|
||||
|
||||
#ifndef CBI
|
||||
#define CBI(A,B) (A &= ~(1 << (B)))
|
||||
#endif
|
||||
|
||||
#define TBI(N,B) (N ^= _BV(B))
|
||||
|
||||
|
||||
// Macros to chain up to 12 conditions
|
||||
#define _DO_1(W,C,A) (_##W##_1(A))
|
||||
#define _DO_2(W,C,A,B) (_##W##_1(A) C _##W##_1(B))
|
||||
#define _DO_3(W,C,A,V...) (_##W##_1(A) C _DO_2(W,C,V))
|
||||
#define _DO_4(W,C,A,V...) (_##W##_1(A) C _DO_3(W,C,V))
|
||||
#define _DO_5(W,C,A,V...) (_##W##_1(A) C _DO_4(W,C,V))
|
||||
#define _DO_6(W,C,A,V...) (_##W##_1(A) C _DO_5(W,C,V))
|
||||
#define _DO_7(W,C,A,V...) (_##W##_1(A) C _DO_6(W,C,V))
|
||||
#define _DO_8(W,C,A,V...) (_##W##_1(A) C _DO_7(W,C,V))
|
||||
#define _DO_9(W,C,A,V...) (_##W##_1(A) C _DO_8(W,C,V))
|
||||
#define _DO_10(W,C,A,V...) (_##W##_1(A) C _DO_9(W,C,V))
|
||||
#define _DO_11(W,C,A,V...) (_##W##_1(A) C _DO_10(W,C,V))
|
||||
#define _DO_12(W,C,A,V...) (_##W##_1(A) C _DO_11(W,C,V))
|
||||
#define __DO_N(W,C,N,V...) _DO_##N(W,C,V)
|
||||
#define _DO_N(W,C,N,V...) __DO_N(W,C,N,V)
|
||||
#define DO(W,C,V...) _DO_N(W,C,NUM_ARGS(V),V)
|
||||
|
||||
// Macros to support option testing
|
||||
#define _CAT(a,V...) a##V
|
||||
#define CAT(a,V...) _CAT(a,V)
|
||||
|
||||
#define _ISENA_ ~,1
|
||||
#define _ISENA_1 ~,1
|
||||
#define _ISENA_0x1 ~,1
|
||||
#define _ISENA_true ~,1
|
||||
#define _ISENA(V...) IS_PROBE(V)
|
||||
|
||||
#define _ENA_1(O) _ISENA(CAT(_IS,CAT(ENA_, O)))
|
||||
#define _DIS_1(O) NOT(_ENA_1(O))
|
||||
#define ENABLED(V...) DO(ENA,&&,V)
|
||||
#define DISABLED(V...) DO(DIS,&&,V)
|
||||
|
||||
#define TERN(O,A,B) _TERN(_ENA_1(O),B,A) // OPTION converted to '0' or '1'
|
||||
#define TERN0(O,A) _TERN(_ENA_1(O),0,A) // OPTION converted to A or '0'
|
||||
#define TERN1(O,A) _TERN(_ENA_1(O),1,A) // OPTION converted to A or '1'
|
||||
#define TERN_(O,A) _TERN(_ENA_1(O),,A) // OPTION converted to A or '<nul>'
|
||||
#define _TERN(E,V...) __TERN(_CAT(T_,E),V) // Prepend 'T_' to get 'T_0' or 'T_1'
|
||||
#define __TERN(T,V...) ___TERN(_CAT(_NO,T),V) // Prepend '_NO' to get '_NOT_0' or '_NOT_1'
|
||||
#define ___TERN(P,V...) THIRD(P,V) // If first argument has a comma, A. Else B.
|
||||
|
||||
|
||||
// Use NUM_ARGS(__VA_ARGS__) to get the number of variadic arguments
|
||||
#define _NUM_ARGS(_,Z,Y,X,W,V,U,T,S,R,Q,P,O,N,M,L,K,J,I,H,G,F,E,D,C,B,A,OUT,...) OUT
|
||||
#define NUM_ARGS(V...) _NUM_ARGS(0,V,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0)
|
||||
|
||||
//
|
||||
// Primitives supporting precompiler REPEAT
|
||||
//
|
||||
#define FIRST(a,...) a
|
||||
#define SECOND(a,b,...) b
|
||||
#define THIRD(a,b,c,...) c
|
||||
|
||||
#define IS_PROBE(V...) SECOND(V, 0) // Get the second item passed, or 0
|
||||
#define NOT(x) IS_PROBE(_CAT(_NOT_, x)) // NOT('0') gets '1'. Anything else gets '0'.
|
||||
|
||||
#endif //MACROS_H
|
||||
|
|
@ -8,13 +8,12 @@
|
|||
#include "lcd.h"
|
||||
#include "Configuration.h"
|
||||
#include "Marlin.h"
|
||||
#include "cmdqueue.h"
|
||||
#include "ultralcd.h"
|
||||
#include "language.h"
|
||||
#include "static_assert.h"
|
||||
#include "sound.h"
|
||||
|
||||
extern int32_t lcd_encoder;
|
||||
|
||||
#define MENU_DEPTH_MAX 7
|
||||
|
||||
static menu_record_t menu_stack[MENU_DEPTH_MAX];
|
||||
|
|
@ -25,7 +24,7 @@ uint8_t menu_data[MENU_DATA_SIZE];
|
|||
#endif
|
||||
|
||||
uint8_t menu_depth = 0;
|
||||
uint8_t menu_block_entering_on_serious_errors = SERIOUS_ERR_NONE;
|
||||
uint8_t menu_block_mask = MENU_BLOCK_NONE;
|
||||
uint8_t menu_line = 0;
|
||||
uint8_t menu_item = 0;
|
||||
uint8_t menu_row = 0;
|
||||
|
|
@ -33,32 +32,35 @@ uint8_t menu_top = 0;
|
|||
|
||||
uint8_t menu_clicked = 0;
|
||||
|
||||
uint8_t menu_entering = 0;
|
||||
uint8_t menu_leaving = 0;
|
||||
|
||||
menu_func_t menu_menu = 0;
|
||||
|
||||
static_assert(sizeof(menu_data)>= sizeof(menu_data_edit_t),"menu_data_edit_t doesn't fit into menu_data");
|
||||
|
||||
void menu_data_reset(void)
|
||||
{
|
||||
// Resets the global shared C union.
|
||||
// This ensures, that the menu entered will find out, that it shall initialize itself.
|
||||
memset(&menu_data, 0, sizeof(menu_data));
|
||||
}
|
||||
|
||||
void menu_goto(menu_func_t menu, const uint32_t encoder, const bool feedback, bool reset_menu_state)
|
||||
{
|
||||
asm("cli");
|
||||
CRITICAL_SECTION_START;
|
||||
if (menu_menu != menu)
|
||||
{
|
||||
menu_menu = menu;
|
||||
lcd_encoder = encoder;
|
||||
asm("sei");
|
||||
menu_top = 0; //reset menu view. Needed if menu_back() is called from deep inside a menu, such as Support
|
||||
CRITICAL_SECTION_END;
|
||||
if (reset_menu_state)
|
||||
{
|
||||
// Resets the global shared C union.
|
||||
// This ensures, that the menu entered will find out, that it shall initialize itself.
|
||||
memset(&menu_data, 0, sizeof(menu_data));
|
||||
}
|
||||
menu_data_reset();
|
||||
|
||||
if (feedback) lcd_quick_feedback();
|
||||
}
|
||||
else
|
||||
asm("sei");
|
||||
CRITICAL_SECTION_END;
|
||||
}
|
||||
|
||||
void menu_start(void)
|
||||
|
|
@ -148,32 +150,10 @@ void menu_submenu_no_reset(menu_func_t submenu)
|
|||
|
||||
uint8_t menu_item_ret(void)
|
||||
{
|
||||
lcd_beeper_quick_feedback();
|
||||
lcd_draw_update = 2;
|
||||
lcd_button_pressed = false;
|
||||
lcd_quick_feedback();
|
||||
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)?'>':' ';
|
||||
}
|
||||
|
|
@ -181,7 +161,9 @@ static char menu_selection_mark(){
|
|||
static void menu_draw_item_puts_P(char type_char, const char* str)
|
||||
{
|
||||
lcd_set_cursor(0, menu_row);
|
||||
lcd_printf_P(PSTR("%c%-18.18S%c"), menu_selection_mark(), str, type_char);
|
||||
lcd_putc(menu_selection_mark());
|
||||
lcd_print_pad_P(str, LCD_WIDTH - 2);
|
||||
lcd_putc(type_char);
|
||||
}
|
||||
|
||||
static void menu_draw_toggle_puts_P(const char* str, const char* toggle, const uint8_t settings)
|
||||
|
|
@ -191,13 +173,22 @@ static void menu_draw_toggle_puts_P(const char* str, const char* toggle, const u
|
|||
//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
|
||||
//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]:' ';
|
||||
uint8_t is_progmem = settings & 0x02;
|
||||
const char eol = (toggle == NULL) ? LCD_STR_ARROW_RIGHT[0] : ' ';
|
||||
if (toggle == NULL) toggle = _T(MSG_NA);
|
||||
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);
|
||||
uint8_t len = 4 + (is_progmem ? strlen_P(toggle) : strlen(toggle));
|
||||
if (!(settings & 0x04)) lcd_set_cursor(0, menu_row);
|
||||
fputs(lineStr, lcdout);
|
||||
lcd_putc((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);
|
||||
}
|
||||
|
||||
//! @brief Format sheet name
|
||||
|
|
@ -233,7 +224,9 @@ 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_printf_P(PSTR("%c%-18.18s%c"), menu_selection_mark(), buffer.c, type_char);
|
||||
lcd_putc(menu_selection_mark());
|
||||
lcd_print_pad(buffer.c, LCD_WIDTH - 2);
|
||||
lcd_putc(type_char);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -242,27 +235,20 @@ 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_printf_P(PSTR("%c%-18.18s%c"), menu_selection_mark(), buffer.c, type_char);
|
||||
lcd_putc(menu_selection_mark());
|
||||
lcd_print_pad(buffer.c, LCD_WIDTH - 2);
|
||||
lcd_putc(type_char);
|
||||
}
|
||||
|
||||
static void menu_draw_item_puts_P(char type_char, const char* str, char num)
|
||||
{
|
||||
lcd_set_cursor(0, menu_row);
|
||||
lcd_printf_P(PSTR("%c%-.16S "), menu_selection_mark(), str);
|
||||
lcd_putc(num);
|
||||
lcd_set_cursor(19, menu_row);
|
||||
lcd_putc(type_char);
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
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++;
|
||||
|
|
@ -310,7 +296,7 @@ uint8_t menu_item_submenu_E(const Sheet &sheet, menu_func_t submenu)
|
|||
return 0;
|
||||
}
|
||||
|
||||
uint8_t 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)
|
||||
{
|
||||
|
|
@ -344,6 +330,10 @@ uint8_t menu_item_back_P(const char* str)
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool __attribute__((noinline)) menu_item_leave(){
|
||||
return ((menu_item == menu_line) && menu_clicked && (lcd_encoder == menu_item)) || menu_leaving;
|
||||
}
|
||||
|
||||
uint8_t menu_item_function_P(const char* str, menu_func_t func)
|
||||
{
|
||||
if (menu_item == menu_line)
|
||||
|
|
@ -445,13 +435,21 @@ 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)
|
||||
{
|
||||
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);
|
||||
// The LCD row position is controlled externally. We may only modify the column here
|
||||
lcd_putc(chr);
|
||||
uint8_t len = lcd_print_pad_P(str, LCD_WIDTH - 1);
|
||||
lcd_set_cursor_column((LCD_WIDTH - 1) - len + 1);
|
||||
lcd_putc(':');
|
||||
|
||||
// The value is right adjusted, set the cursor then render the value
|
||||
if (val < 10) { // 1 digit
|
||||
lcd_set_cursor_column(LCD_WIDTH - 1);
|
||||
} else if (val < 100) { // 2 digits
|
||||
lcd_set_cursor_column(LCD_WIDTH - 2);
|
||||
} else { // 3 digits
|
||||
lcd_set_cursor_column(LCD_WIDTH - 3);
|
||||
}
|
||||
lcd_print(val);
|
||||
}
|
||||
|
||||
template<>
|
||||
|
|
@ -506,7 +504,7 @@ static void _menu_edit_P(void)
|
|||
if (lcd_draw_update)
|
||||
{
|
||||
if (lcd_encoder < _md->minEditValue) lcd_encoder = _md->minEditValue;
|
||||
if (lcd_encoder > _md->maxEditValue) lcd_encoder = _md->maxEditValue;
|
||||
else if (lcd_encoder > _md->maxEditValue) lcd_encoder = _md->maxEditValue;
|
||||
lcd_set_cursor(0, 1);
|
||||
menu_draw_P<T>(' ', _md->editLabel, (int)lcd_encoder);
|
||||
}
|
||||
|
|
@ -546,4 +544,34 @@ uint8_t menu_item_edit_P(const char* str, T pval, int16_t min_val, int16_t max_v
|
|||
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);
|
||||
|
||||
#undef _menu_data
|
||||
static uint8_t progressbar_block_count = 0;
|
||||
static uint16_t progressbar_total = 0;
|
||||
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);
|
||||
}
|
||||
|
||||
void menu_progressbar_update(uint16_t newVal)
|
||||
{
|
||||
uint8_t newCnt = (newVal * LCD_WIDTH) / progressbar_total;
|
||||
if (newCnt > LCD_WIDTH)
|
||||
newCnt = LCD_WIDTH;
|
||||
while (newCnt > progressbar_block_count)
|
||||
{
|
||||
lcd_print(LCD_STR_SOLID_BLOCK[0]);
|
||||
progressbar_block_count++;
|
||||
}
|
||||
}
|
||||
|
||||
void menu_progressbar_finish(void)
|
||||
{
|
||||
progressbar_total = 1;
|
||||
menu_progressbar_update(1);
|
||||
_delay(300);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,26 +29,26 @@ extern uint8_t menu_data[MENU_DATA_SIZE];
|
|||
|
||||
extern uint8_t menu_depth;
|
||||
|
||||
//! definition of serious errors possibly blocking the main menu
|
||||
//! definition of reasons blocking the main menu
|
||||
//! Use them as bit mask, so that the code may set various errors at the same time
|
||||
enum ESeriousErrors {
|
||||
SERIOUS_ERR_NONE = 0,
|
||||
SERIOUS_ERR_MINTEMP_HEATER = 0x01,
|
||||
SERIOUS_ERR_MINTEMP_BED = 0x02
|
||||
MENU_BLOCK_NONE = 0,
|
||||
MENU_BLOCK_THERMAL_ERROR = 0x01,
|
||||
#ifdef TEMP_MODEL
|
||||
MENU_BLOCK_TEMP_MODEL_AUTOTUNE = 0x02,
|
||||
#endif
|
||||
}; // and possibly others in the future.
|
||||
|
||||
//! 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;
|
||||
//! 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;
|
||||
|
||||
//! a pair of macros for manipulating the serious errors
|
||||
//! a pair of macros for manipulating menu entry
|
||||
//! a c++ class would have been better
|
||||
#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
|
||||
#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) != 0
|
||||
|
||||
extern uint8_t menu_line;
|
||||
extern uint8_t menu_item;
|
||||
|
|
@ -56,16 +56,13 @@ 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_entering;
|
||||
extern uint8_t menu_leaving;
|
||||
|
||||
//function pointer to the currently active menu
|
||||
extern menu_func_t menu_menu;
|
||||
|
||||
|
||||
extern void menu_data_reset(void);
|
||||
|
||||
extern void menu_goto(menu_func_t menu, const uint32_t encoder, const bool feedback, bool reset_menu_state);
|
||||
|
||||
|
|
@ -112,7 +109,8 @@ extern uint8_t menu_item_function_E(const Sheet &sheet, menu_func_t func);
|
|||
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 == menu_line) && menu_clicked && (lcd_encoder == menu_item)) || menu_leaving){ func } } while (0)
|
||||
#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 { if (menu_item_function_P(str, func)) return; } while (0)
|
||||
extern uint8_t menu_item_function_P(const char* str, menu_func_t func);
|
||||
|
|
@ -150,5 +148,8 @@ extern void menu_format_sheet_E(const Sheet &sheet_E, SheetFormatBuffer &buffer)
|
|||
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);
|
||||
extern void menu_progressbar_finish(void);
|
||||
|
||||
#endif //_MENU_H
|
||||
|
|
|
|||
|
|
@ -1,16 +1,19 @@
|
|||
#include "Marlin.h"
|
||||
#include "Configuration.h"
|
||||
#include "ConfigurationStore.h"
|
||||
#include "util.h"
|
||||
#include "language.h"
|
||||
#include "mesh_bed_calibration.h"
|
||||
#include "mesh_bed_leveling.h"
|
||||
#include "stepper.h"
|
||||
#include "ultralcd.h"
|
||||
#include "temperature.h"
|
||||
|
||||
#ifdef TMC2130
|
||||
#include "tmc2130.h"
|
||||
#endif //TMC2130
|
||||
|
||||
#define DBG(args...) printf_P(args)
|
||||
|
||||
uint8_t world2machine_correction_mode;
|
||||
float world2machine_rotation_and_skew[2][2];
|
||||
float world2machine_rotation_and_skew_inv[2][2];
|
||||
|
|
@ -368,7 +371,9 @@ BedSkewOffsetDetectionResultType calculate_machine_skew_and_offset_LS(
|
|||
BedSkewOffsetDetectionResultType result = BED_SKEW_OFFSET_DETECTION_PERFECT;
|
||||
{
|
||||
angleDiff = fabs(a2 - a1);
|
||||
eeprom_update_float((float*)(EEPROM_XYZ_CAL_SKEW), angleDiff); //storing xyz cal. skew to be able to show in support menu later
|
||||
/// XY skew and Y-bed skew
|
||||
DBG(_n("Measured skews: %f %f\n"), degrees(a2 - a1), degrees(a2));
|
||||
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 :
|
||||
|
|
@ -414,9 +419,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 = 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);
|
||||
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);
|
||||
#ifdef SUPPORT_VERBOSITY
|
||||
if (verbosity_level >= 10) {
|
||||
SERIAL_ECHOPGM("point #");
|
||||
|
|
@ -430,15 +435,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 (sqrt(errX) > BED_CALIBRATION_POINT_OFFSET_MAX_1ST_ROW_X ||
|
||||
(w != 0.f && sqrt(errY) > BED_CALIBRATION_POINT_OFFSET_MAX_1ST_ROW_Y)) {
|
||||
if (errX > BED_CALIBRATION_POINT_OFFSET_MAX_1ST_ROW_X ||
|
||||
(w != 0.f && 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 (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");
|
||||
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");
|
||||
}
|
||||
#endif // SUPPORT_VERBOSITY
|
||||
}
|
||||
|
|
@ -473,9 +478,9 @@ BedSkewOffsetDetectionResultType calculate_machine_skew_and_offset_LS(
|
|||
SERIAL_ECHOPGM("error: ");
|
||||
MYSERIAL.print(err);
|
||||
SERIAL_ECHOPGM(", error X: ");
|
||||
MYSERIAL.print(sqrt(errX));
|
||||
MYSERIAL.print(errX);
|
||||
SERIAL_ECHOPGM(", error Y: ");
|
||||
MYSERIAL.print(sqrt(errY));
|
||||
MYSERIAL.print(errY);
|
||||
SERIAL_ECHOLNPGM("");
|
||||
SERIAL_ECHOLNPGM("");
|
||||
}
|
||||
|
|
@ -641,7 +646,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(sqrt(sqr(measured_pts[i * 2] - x) + sqr(measured_pts[i * 2 + 1] - y)));
|
||||
MYSERIAL.print( hypot(measured_pts[i * 2] - x, measured_pts[i * 2 + 1] - y) );
|
||||
SERIAL_ECHOLNPGM("");
|
||||
}
|
||||
if (verbosity_level >= 20) {
|
||||
|
|
@ -806,7 +811,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 = sqrt(vec_x[0] * vec_x[0] + vec_x[1] * vec_x[1]);
|
||||
float l = hypot(vec_x[0], vec_x[1]);
|
||||
if (l < 0.9 || l > 1.1)
|
||||
{
|
||||
#if 0
|
||||
|
|
@ -817,7 +822,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 = sqrt(vec_y[0] * vec_y[0] + vec_y[1] * vec_y[1]);
|
||||
l = hypot(vec_y[0], vec_y[1]);
|
||||
if (l < 0.9 || l > 1.1)
|
||||
{
|
||||
#if 0
|
||||
|
|
@ -828,7 +833,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 = sqrt(cntr[0] * cntr[0] + cntr[1] * cntr[1]);
|
||||
l = hypot(cntr[0], cntr[1]);
|
||||
if (l > 15.f)
|
||||
{
|
||||
#if 0
|
||||
|
|
@ -907,19 +912,19 @@ 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, active_extruder);
|
||||
plan_buffer_line(x, y, z, current_position[E_AXIS], fr);
|
||||
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, active_extruder);
|
||||
plan_buffer_line(x, y, current_position[Z_AXIS], current_position[E_AXIS], fr);
|
||||
st_synchronize();
|
||||
}
|
||||
|
||||
static inline void go_to_current(float fr)
|
||||
{
|
||||
plan_buffer_line_curposXYZE(fr, active_extruder);
|
||||
plan_buffer_line_curposXYZE(fr);
|
||||
st_synchronize();
|
||||
}
|
||||
|
||||
|
|
@ -928,7 +933,7 @@ static inline void update_current_position_xyz()
|
|||
current_position[X_AXIS] = st_get_position_mm(X_AXIS);
|
||||
current_position[Y_AXIS] = st_get_position_mm(Y_AXIS);
|
||||
current_position[Z_AXIS] = st_get_position_mm(Z_AXIS);
|
||||
plan_set_position(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS], current_position[E_AXIS]);
|
||||
plan_set_position_curposXYZE();
|
||||
}
|
||||
|
||||
static inline void update_current_position_z()
|
||||
|
|
@ -939,13 +944,14 @@ static inline void update_current_position_z()
|
|||
|
||||
// At the current position, find the Z stop.
|
||||
|
||||
inline bool find_bed_induction_sensor_point_z(float minimum_z, uint8_t n_iter, int
|
||||
bool find_bed_induction_sensor_point_z(float minimum_z, uint8_t n_iter, int
|
||||
#ifdef SUPPORT_VERBOSITY
|
||||
verbosity_level
|
||||
#endif //SUPPORT_VERBOSITY
|
||||
)
|
||||
{
|
||||
bool high_deviation_occured = false;
|
||||
bedPWMDisabled = 1;
|
||||
#ifdef TMC2130
|
||||
FORCE_HIGH_POWER_START;
|
||||
#endif
|
||||
|
|
@ -969,7 +975,7 @@ inline bool find_bed_induction_sensor_point_z(float minimum_z, uint8_t n_iter, i
|
|||
goto error;
|
||||
}
|
||||
#ifdef TMC2130
|
||||
if (READ(Z_TMC2130_DIAG) != 0)
|
||||
if (!READ(Z_TMC2130_DIAG))
|
||||
{
|
||||
//printf_P(PSTR("crash detected 1, current_pos[Z]: %f \n"), current_position[Z_AXIS]);
|
||||
goto error; //crash Z detected
|
||||
|
|
@ -988,10 +994,9 @@ inline bool find_bed_induction_sensor_point_z(float minimum_z, uint8_t n_iter, i
|
|||
// we have to let the planner know where we are right now as it is not where we said to go.
|
||||
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 (abs(current_position[Z_AXIS] - z_bckp) < 0.025) {
|
||||
if (fabs(current_position[Z_AXIS] - z_bckp) < 0.025) {
|
||||
//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);
|
||||
raise_z(0.5);
|
||||
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.
|
||||
|
|
@ -1006,7 +1011,7 @@ inline bool find_bed_induction_sensor_point_z(float minimum_z, uint8_t n_iter, i
|
|||
goto error;
|
||||
}
|
||||
#ifdef TMC2130
|
||||
if (READ(Z_TMC2130_DIAG) != 0) {
|
||||
if (!READ(Z_TMC2130_DIAG)) {
|
||||
//printf_P(PSTR("crash detected 2, current_pos[Z]: %f \n"), current_position[Z_AXIS]);
|
||||
goto error; //crash Z detected
|
||||
}
|
||||
|
|
@ -1014,7 +1019,7 @@ inline bool find_bed_induction_sensor_point_z(float minimum_z, uint8_t n_iter, i
|
|||
// SERIAL_ECHOPGM("Bed find_bed_induction_sensor_point_z low, height: ");
|
||||
// MYSERIAL.print(current_position[Z_AXIS], 5);
|
||||
// SERIAL_ECHOLNPGM("");
|
||||
float dz = i?abs(current_position[Z_AXIS] - (z / i)):0;
|
||||
float dz = i?fabs(current_position[Z_AXIS] - (z / i)):0;
|
||||
z += current_position[Z_AXIS];
|
||||
//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);
|
||||
|
|
@ -1044,6 +1049,7 @@ inline bool find_bed_induction_sensor_point_z(float minimum_z, uint8_t n_iter, i
|
|||
#ifdef TMC2130
|
||||
FORCE_HIGH_POWER_END;
|
||||
#endif
|
||||
bedPWMDisabled = 0;
|
||||
return true;
|
||||
|
||||
error:
|
||||
|
|
@ -1053,11 +1059,12 @@ error:
|
|||
#ifdef TMC2130
|
||||
FORCE_HIGH_POWER_END;
|
||||
#endif
|
||||
bedPWMDisabled = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef NEW_XYZCAL
|
||||
extern bool xyzcal_find_bed_induction_sensor_point_xy();
|
||||
BedSkewOffsetDetectionResultType xyzcal_find_bed_induction_sensor_point_xy();
|
||||
#endif //NEW_XYZCAL
|
||||
// Search around the current_position[X,Y],
|
||||
// look for the induction sensor response.
|
||||
|
|
@ -1073,7 +1080,7 @@ extern bool xyzcal_find_bed_induction_sensor_point_xy();
|
|||
#endif //HEATBED_V2
|
||||
|
||||
#ifdef HEATBED_V2
|
||||
inline bool find_bed_induction_sensor_point_xy(int
|
||||
BedSkewOffsetDetectionResultType find_bed_induction_sensor_point_xy(int
|
||||
#if !defined (NEW_XYZCAL) && defined (SUPPORT_VERBOSITY)
|
||||
verbosity_level
|
||||
#endif
|
||||
|
|
@ -1129,7 +1136,7 @@ inline bool find_bed_induction_sensor_point_xy(int
|
|||
|
||||
// go_xyz(current_position[X_AXIS], current_position[Y_AXIS], MESH_HOME_Z_SEARCH, homing_feedrate[Z_AXIS]/60);
|
||||
go_xyz(x0, y0, current_position[Z_AXIS], feedrate);
|
||||
// Continously lower the Z axis.
|
||||
// Continuously lower the Z axis.
|
||||
endstops_hit_on_purpose();
|
||||
enable_z_endstop(true);
|
||||
bool direction = false;
|
||||
|
|
@ -1327,7 +1334,7 @@ inline bool find_bed_induction_sensor_point_xy(int
|
|||
#endif //NEW_XYZCAL
|
||||
}
|
||||
#else //HEATBED_V2
|
||||
inline bool find_bed_induction_sensor_point_xy(int verbosity_level)
|
||||
BedSkewOffsetDetectionResultType find_bed_induction_sensor_point_xy(int verbosity_level)
|
||||
{
|
||||
#ifdef NEW_XYZCAL
|
||||
return xyzcal_find_bed_induction_sensor_point_xy();
|
||||
|
|
@ -1376,7 +1383,7 @@ inline bool find_bed_induction_sensor_point_xy(int verbosity_level)
|
|||
|
||||
// go_xyz(current_position[X_AXIS], current_position[Y_AXIS], MESH_HOME_Z_SEARCH, homing_feedrate[Z_AXIS]/60);
|
||||
go_xyz(x0, y0, current_position[Z_AXIS], feedrate);
|
||||
// Continously lower the Z axis.
|
||||
// Continuously lower the Z axis.
|
||||
endstops_hit_on_purpose();
|
||||
enable_z_endstop(true);
|
||||
while (current_position[Z_AXIS] > -10.f) {
|
||||
|
|
@ -1523,7 +1530,9 @@ inline bool find_bed_induction_sensor_point_xy(int verbosity_level)
|
|||
}
|
||||
|
||||
enable_z_endstop(false);
|
||||
return found;
|
||||
if (found)
|
||||
return BED_SKEW_OFFSET_DETECTION_POINT_FOUND;
|
||||
return BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND;
|
||||
#endif //NEW_XYZCAL
|
||||
}
|
||||
|
||||
|
|
@ -1570,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 = sqrt(vx*vx+vy*vy);
|
||||
float l = hypot(vx, vy);
|
||||
float t;
|
||||
if (destination[X_AXIS] < X_MIN_POS) {
|
||||
// Exiting the bed at xmin.
|
||||
|
|
@ -2222,25 +2231,26 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
|
|||
}
|
||||
#endif // SUPPORT_VERBOSITY
|
||||
#ifdef MESH_BED_CALIBRATION_SHOW_LCD
|
||||
uint8_t next_line;
|
||||
lcd_display_message_fullscreen_P(_T(MSG_FIND_BED_OFFSET_AND_SKEW_LINE1), next_line);
|
||||
if (next_line > 3)
|
||||
next_line = 3;
|
||||
lcd_display_message_fullscreen_P(_T(MSG_FIND_BED_OFFSET_AND_SKEW_LINE1));
|
||||
#endif /* MESH_BED_CALIBRATION_SHOW_LCD */
|
||||
|
||||
// Collect the rear 2x3 points.
|
||||
current_position[Z_AXIS] = MESH_HOME_Z_SEARCH + FIND_BED_INDUCTION_SENSOR_POINT_Z_STEP * iteration * 0.3;
|
||||
for (int k = 0; k < 4; ++k) {
|
||||
// Don't let the manage_inactivity() function remove power from the motors.
|
||||
refresh_cmd_timeout();
|
||||
|
||||
/// 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) {
|
||||
bool retry = false;
|
||||
for (int k = 0; k < 4; ++k) {
|
||||
// Don't let the manage_inactivity() function remove power from the motors.
|
||||
refresh_cmd_timeout();
|
||||
#ifdef MESH_BED_CALIBRATION_SHOW_LCD
|
||||
lcd_set_cursor(0, next_line);
|
||||
lcd_print(k + 1);
|
||||
lcd_puts_P(_T(MSG_FIND_BED_OFFSET_AND_SKEW_LINE2));
|
||||
lcd_set_cursor(0, 3);
|
||||
lcd_printf_P(PSTR("%d/4"),(k+1));
|
||||
|
||||
if (iteration > 0) {
|
||||
lcd_puts_at_P(0, next_line + 1, _i("Iteration "));////MSG_FIND_BED_OFFSET_AND_SKEW_ITERATION c=20
|
||||
lcd_print(int(iteration + 1));
|
||||
lcd_printf_P(PSTR(" %S %d/1"),_T(MSG_ITERATION),int(iteration + 1));
|
||||
}
|
||||
#endif /* MESH_BED_CALIBRATION_SHOW_LCD */
|
||||
float *pt = pts + k * 2;
|
||||
|
|
@ -2267,7 +2277,7 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
|
|||
/*}
|
||||
else {
|
||||
// if first iteration failed, count corrected point coordinates as initial
|
||||
// Use the coorrected coordinate, which is a result of find_bed_offset_and_skew().
|
||||
// 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];
|
||||
|
|
@ -2296,8 +2306,19 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
|
|||
if (verbosity_level >= 10)
|
||||
delay_keep_alive(3000);
|
||||
#endif // SUPPORT_VERBOSITY
|
||||
if (!find_bed_induction_sensor_point_xy(verbosity_level))
|
||||
return BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND;
|
||||
|
||||
BedSkewOffsetDetectionResultType result;
|
||||
result = find_bed_induction_sensor_point_xy(verbosity_level);
|
||||
switch(result){
|
||||
case BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND:
|
||||
return BED_SKEW_OFFSET_DETECTION_POINT_NOT_FOUND;
|
||||
case BED_SKEW_OFFSET_DETECTION_POINT_SCAN_FAILED:
|
||||
retry = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
#ifndef NEW_XYZCAL
|
||||
#ifndef HEATBED_V2
|
||||
|
||||
|
|
@ -2371,8 +2392,12 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
|
|||
delay_keep_alive(3000);
|
||||
}
|
||||
#endif // SUPPORT_VERBOSITY
|
||||
}
|
||||
delay_keep_alive(0); //manage_heater, reset watchdog, manage inactivity
|
||||
}
|
||||
if (!retry)
|
||||
break;
|
||||
}
|
||||
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) {
|
||||
|
|
@ -2382,7 +2407,7 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
|
|||
// Don't let the manage_inactivity() function remove power from the motors.
|
||||
refresh_cmd_timeout();
|
||||
// Go to the measurement point.
|
||||
// Use the coorrected coordinate, which is a result of find_bed_offset_and_skew().
|
||||
// Use the corrected coordinate, which is a result of find_bed_offset_and_skew().
|
||||
current_position[X_AXIS] = pts[mesh_point * 2];
|
||||
current_position[Y_AXIS] = pts[mesh_point * 2 + 1];
|
||||
go_to_current(homing_feedrate[X_AXIS] / 60);
|
||||
|
|
@ -2402,6 +2427,7 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t 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.
|
||||
|
|
@ -2415,16 +2441,16 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
|
|||
#ifdef SUPPORT_VERBOSITY
|
||||
if (verbosity_level >= 10) {
|
||||
// Length of the vec_x
|
||||
float l = sqrt(vec_x[0] * vec_x[0] + vec_x[1] * vec_x[1]);
|
||||
float l = hypot(vec_x[0], vec_x[1]);
|
||||
SERIAL_ECHOLNPGM("X vector length:");
|
||||
MYSERIAL.println(l);
|
||||
|
||||
// Length of the vec_y
|
||||
l = sqrt(vec_y[0] * vec_y[0] + vec_y[1] * vec_y[1]);
|
||||
l = hypot(vec_y[0], vec_y[1]);
|
||||
SERIAL_ECHOLNPGM("Y vector length:");
|
||||
MYSERIAL.println(l);
|
||||
// Zero point correction
|
||||
l = sqrt(cntr[0] * cntr[0] + cntr[1] * cntr[1]);
|
||||
l = hypot(cntr[0], cntr[1]);
|
||||
SERIAL_ECHOLNPGM("Zero point correction:");
|
||||
MYSERIAL.println(l);
|
||||
|
||||
|
|
@ -2446,7 +2472,7 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
|
|||
// Don't let the manage_inactivity() function remove power from the motors.
|
||||
refresh_cmd_timeout();
|
||||
// Go to the measurement point.
|
||||
// Use the coorrected coordinate, which is a result of find_bed_offset_and_skew().
|
||||
// Use the corrected coordinate, which is a result of find_bed_offset_and_skew().
|
||||
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;
|
||||
|
|
@ -2458,9 +2484,12 @@ BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level
|
|||
}
|
||||
#endif // SUPPORT_VERBOSITY
|
||||
return result;
|
||||
}
|
||||
if (result == BED_SKEW_OFFSET_DETECTION_FITTING_FAILED && too_far_mask == 2) return result; //if fitting failed and front center point is out of reach, terminate calibration and inform user
|
||||
iteration++;
|
||||
}
|
||||
if (result == BED_SKEW_OFFSET_DETECTION_FITTING_FAILED && too_far_mask == 2){
|
||||
DBG(_n("Fitting failed => calibration failed.\n"));
|
||||
return result; //if fitting failed and front center point is out of reach, terminate calibration and inform user
|
||||
}
|
||||
iteration++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
@ -2499,10 +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
|
||||
uint8_t next_line;
|
||||
lcd_display_message_fullscreen_P(_i("Improving bed calibration point"), next_line);////MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1 c=60
|
||||
if (next_line > 3)
|
||||
next_line = 3;
|
||||
lcd_display_message_fullscreen_P(_i("Improving bed calibration point"));////MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE1 c=20 r=4
|
||||
#endif /* MESH_BED_CALIBRATION_SHOW_LCD */
|
||||
|
||||
// Collect a matrix of 9x9 points.
|
||||
|
|
@ -2512,9 +2538,8 @@ BedSkewOffsetDetectionResultType improve_bed_offset_and_skew(int8_t method, int8
|
|||
refresh_cmd_timeout();
|
||||
// Print the decrasing ID of the measurement point.
|
||||
#ifdef MESH_BED_CALIBRATION_SHOW_LCD
|
||||
lcd_set_cursor(0, next_line);
|
||||
lcd_print(mesh_point+1);
|
||||
lcd_puts_P(_T(MSG_FIND_BED_OFFSET_AND_SKEW_LINE2));////MSG_IMPROVE_BED_OFFSET_AND_SKEW_LINE2 c=14
|
||||
lcd_set_cursor(0, 3);
|
||||
lcd_printf_P(PSTR("%d/4"),mesh_point+1);
|
||||
#endif /* MESH_BED_CALIBRATION_SHOW_LCD */
|
||||
|
||||
// Move up.
|
||||
|
|
@ -2767,10 +2792,7 @@ canceled:
|
|||
bool sample_z() {
|
||||
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););
|
||||
|
||||
raise_z(150);
|
||||
lcd_show_fullscreen_message_and_wait_P(_T(MSG_PLACE_STEEL_SHEET));
|
||||
|
||||
// Sample Z heights for the mesh bed leveling.
|
||||
|
|
@ -2812,14 +2834,9 @@ bool sample_mesh_and_store_reference()
|
|||
refresh_cmd_timeout();
|
||||
|
||||
#ifdef MESH_BED_CALIBRATION_SHOW_LCD
|
||||
uint8_t next_line;
|
||||
lcd_display_message_fullscreen_P(_T(MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE1), next_line);
|
||||
if (next_line > 3)
|
||||
next_line = 3;
|
||||
lcd_display_message_fullscreen_P(_T(MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE1));
|
||||
// display "point xx of yy"
|
||||
lcd_set_cursor(0, next_line);
|
||||
lcd_print(1);
|
||||
lcd_puts_P(_T(MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2));
|
||||
lcd_puts_at_P(0,3,_n("1/9"));
|
||||
#endif /* MESH_BED_CALIBRATION_SHOW_LCD */
|
||||
|
||||
// Sample Z heights for the mesh bed leveling.
|
||||
|
|
@ -2832,12 +2849,12 @@ bool sample_mesh_and_store_reference()
|
|||
current_position[Y_AXIS] = BED_Y0;
|
||||
world2machine_clamp(current_position[X_AXIS], current_position[Y_AXIS]);
|
||||
go_to_current(homing_feedrate[X_AXIS]/60);
|
||||
memcpy(destination, current_position, sizeof(destination));
|
||||
set_destination_to_current();
|
||||
enable_endstops(true);
|
||||
homeaxis(Z_AXIS);
|
||||
|
||||
#ifdef TMC2130
|
||||
if (!axis_known_position[Z_AXIS] && (READ(Z_TMC2130_DIAG) != 0)) //Z crash
|
||||
if (!axis_known_position[Z_AXIS] && (!READ(Z_TMC2130_DIAG))) //Z crash
|
||||
{
|
||||
kill(_T(MSG_BED_LEVELING_FAILED_POINT_LOW));
|
||||
return false;
|
||||
|
|
@ -2852,14 +2869,15 @@ bool sample_mesh_and_store_reference()
|
|||
}
|
||||
mbl.set_z(0, 0, current_position[Z_AXIS]);
|
||||
}
|
||||
for (int8_t mesh_point = 1; mesh_point != MESH_MEAS_NUM_X_POINTS * MESH_MEAS_NUM_Y_POINTS; ++ mesh_point) {
|
||||
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) {
|
||||
// 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);
|
||||
int8_t ix = mesh_point % MESH_MEAS_NUM_X_POINTS;
|
||||
int8_t iy = mesh_point / MESH_MEAS_NUM_X_POINTS;
|
||||
uint8_t ix = mesh_point % MESH_MEAS_NUM_X_POINTS;
|
||||
uint8_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, MESH_MEAS_NUM_X_POINTS);
|
||||
current_position[Y_AXIS] = BED_Y(iy, MESH_MEAS_NUM_Y_POINTS);
|
||||
|
|
@ -2867,9 +2885,8 @@ bool sample_mesh_and_store_reference()
|
|||
go_to_current(homing_feedrate[X_AXIS]/60);
|
||||
#ifdef MESH_BED_CALIBRATION_SHOW_LCD
|
||||
// display "point xx of yy"
|
||||
lcd_set_cursor(0, next_line);
|
||||
lcd_print(mesh_point+1);
|
||||
lcd_puts_P(_T(MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2));
|
||||
lcd_set_cursor(0, 3);
|
||||
lcd_printf_P(PSTR("%d/9"),mesh_point+1);
|
||||
#endif /* MESH_BED_CALIBRATION_SHOW_LCD */
|
||||
if (!find_bed_induction_sensor_point_z()) //Z crash or deviation > 50um
|
||||
{
|
||||
|
|
@ -3012,13 +3029,11 @@ bool scan_bed_induction_points(int8_t verbosity_level)
|
|||
// To replace loading of the babystep correction.
|
||||
static void shift_z(float delta)
|
||||
{
|
||||
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);
|
||||
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);
|
||||
st_synchronize();
|
||||
plan_set_z_position(current_position[Z_AXIS]);
|
||||
}
|
||||
|
||||
#define BABYSTEP_LOADZ_BY_PLANNER
|
||||
|
||||
// Number of baby steps applied
|
||||
static int babystepLoadZ = 0;
|
||||
|
||||
|
|
@ -3026,7 +3041,7 @@ void babystep_load()
|
|||
{
|
||||
babystepLoadZ = 0;
|
||||
// Apply Z height correction aka baby stepping before mesh bed leveling gets activated.
|
||||
if (calibration_status() < CALIBRATION_STATUS_LIVE_ADJUST)
|
||||
if (calibration_status_get(CALIBRATION_STATUS_LIVE_ADJUST))
|
||||
{
|
||||
check_babystep(); //checking if babystep is in allowed range, otherwise setting babystep to 0
|
||||
|
||||
|
|
@ -3049,20 +3064,12 @@ void babystep_load()
|
|||
void babystep_apply()
|
||||
{
|
||||
babystep_load();
|
||||
#ifdef BABYSTEP_LOADZ_BY_PLANNER
|
||||
shift_z(- float(babystepLoadZ) / float(cs.axis_steps_per_unit[Z_AXIS]));
|
||||
#else
|
||||
babystepsTodoZadd(babystepLoadZ);
|
||||
#endif /* BABYSTEP_LOADZ_BY_PLANNER */
|
||||
}
|
||||
|
||||
void babystep_undo()
|
||||
{
|
||||
#ifdef BABYSTEP_LOADZ_BY_PLANNER
|
||||
shift_z(float(babystepLoadZ) / float(cs.axis_steps_per_unit[Z_AXIS]));
|
||||
#else
|
||||
babystepsTodoZsubtract(babystepLoadZ);
|
||||
#endif /* BABYSTEP_LOADZ_BY_PLANNER */
|
||||
babystepLoadZ = 0;
|
||||
}
|
||||
|
||||
|
|
@ -3117,17 +3124,9 @@ void mbl_mode_init() {
|
|||
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
|
||||
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);
|
||||
}
|
||||
eeprom_init_default_byte((uint8_t*)EEPROM_MBL_MAGNET_ELIMINATION, 1);
|
||||
eeprom_init_default_byte((uint8_t*)EEPROM_MBL_POINTS_NR, 3);
|
||||
mbl_z_probe_nr = eeprom_init_default_byte((uint8_t*)EEPROM_MBL_PROBE_NR, 3);
|
||||
}
|
||||
|
||||
//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 )
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#ifndef MESH_BED_CALIBRATION_H
|
||||
#define MESH_BED_CALIBRATION_H
|
||||
#pragma once
|
||||
|
||||
#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
|
||||
|
|
@ -128,16 +129,15 @@ inline bool world2machine_clamp(float &x, float &y)
|
|||
if (tmpx < X_MIN_POS) {
|
||||
tmpx = X_MIN_POS;
|
||||
clamped = true;
|
||||
}
|
||||
if (tmpy < Y_MIN_POS) {
|
||||
tmpy = Y_MIN_POS;
|
||||
clamped = true;
|
||||
}
|
||||
if (tmpx > X_MAX_POS) {
|
||||
} else if (tmpx > X_MAX_POS) {
|
||||
tmpx = X_MAX_POS;
|
||||
clamped = true;
|
||||
}
|
||||
if (tmpy > Y_MAX_POS) {
|
||||
|
||||
if (tmpy < Y_MIN_POS) {
|
||||
tmpy = Y_MIN_POS;
|
||||
clamped = true;
|
||||
} else if (tmpy > Y_MAX_POS) {
|
||||
tmpy = Y_MAX_POS;
|
||||
clamped = true;
|
||||
}
|
||||
|
|
@ -145,11 +145,6 @@ inline bool world2machine_clamp(float &x, float &y)
|
|||
machine2world(tmpx, tmpy, x, y);
|
||||
return clamped;
|
||||
}
|
||||
|
||||
extern bool find_bed_induction_sensor_point_z(float minimum_z = -10.f, uint8_t n_iter = 3, int verbosity_level = 0);
|
||||
extern bool find_bed_induction_sensor_point_xy(int verbosity_level = 0);
|
||||
extern void go_home_with_z_lift();
|
||||
|
||||
/**
|
||||
* @brief Bed skew and offest detection result
|
||||
*
|
||||
|
|
@ -159,8 +154,10 @@ extern void go_home_with_z_lift();
|
|||
|
||||
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.
|
||||
|
|
@ -168,6 +165,10 @@ enum BedSkewOffsetDetectionResultType {
|
|||
BED_SKEW_OFFSET_DETECTION_SKEW_EXTREME = 2 //!< Extremely skewed.
|
||||
};
|
||||
|
||||
bool find_bed_induction_sensor_point_z(float minimum_z = -10.f, uint8_t n_iter = 3, int verbosity_level = 0);
|
||||
BedSkewOffsetDetectionResultType find_bed_induction_sensor_point_xy(int verbosity_level = 0);
|
||||
void go_home_with_z_lift();
|
||||
|
||||
extern BedSkewOffsetDetectionResultType find_bed_offset_and_skew(int8_t verbosity_level, uint8_t &too_far_mask);
|
||||
#ifndef NEW_XYZCAL
|
||||
extern BedSkewOffsetDetectionResultType improve_bed_offset_and_skew(int8_t method, int8_t verbosity_level, uint8_t &too_far_mask);
|
||||
|
|
@ -213,4 +214,3 @@ extern void mbl_settings_init();
|
|||
|
||||
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);
|
||||
#endif /* MESH_BED_CALIBRATION_H */
|
||||
|
|
|
|||
|
|
@ -10,9 +10,7 @@ mesh_bed_leveling::mesh_bed_leveling() { reset(); }
|
|||
|
||||
void mesh_bed_leveling::reset() {
|
||||
active = 0;
|
||||
for (int y = 0; y < MESH_NUM_Y_POINTS; y++)
|
||||
for (int x = 0; x < MESH_NUM_X_POINTS; x++)
|
||||
z_values[y][x] = 0;
|
||||
memset(z_values, 0, sizeof(float) * MESH_NUM_X_POINTS * MESH_NUM_Y_POINTS);
|
||||
}
|
||||
|
||||
static inline bool vec_undef(const float v[2])
|
||||
|
|
|
|||
|
|
@ -24,12 +24,7 @@ public:
|
|||
static float get_x(int i) { return float(MESH_MIN_X) + float(MESH_X_DIST) * float(i); }
|
||||
static float get_y(int i) { return float(MESH_MIN_Y) + float(MESH_Y_DIST) * float(i); }
|
||||
|
||||
// Measurement point for the Z probe.
|
||||
// If use_default=true, then the default positions for a correctly built printer are used.
|
||||
// Otherwise a correction matrix is pulled from the EEPROM if available.
|
||||
static void get_meas_xy(int ix, int iy, float &x, float &y, bool use_default);
|
||||
|
||||
void set_z(int ix, int iy, float z) { z_values[iy][ix] = z; }
|
||||
void set_z(uint8_t ix, uint8_t iy, float z) { z_values[iy][ix] = z; }
|
||||
|
||||
int select_x_index(float x) {
|
||||
int i = 1;
|
||||
|
|
|
|||
|
|
@ -1,173 +0,0 @@
|
|||
//messages.c
|
||||
#include "language.h"
|
||||
|
||||
//this is because we need include Configuration_prusa.h (CUSTOM_MENDEL_NAME)
|
||||
#define bool char
|
||||
#define true 1
|
||||
#define false 0
|
||||
#include "Configuration_prusa.h"
|
||||
|
||||
//internationalized messages
|
||||
const char MSG_AUTO_HOME[] PROGMEM_I1 = ISTR("Auto home"); ////
|
||||
const char MSG_BABYSTEP_Z[] PROGMEM_I1 = ISTR("Live adjust Z"); //// c=18
|
||||
const char MSG_BABYSTEP_Z_NOT_SET[] PROGMEM_I1 = ISTR("Distance between tip of the nozzle and the bed surface has not been set yet. Please follow the manual, chapter First steps, section First layer calibration."); ////c=20 r=12
|
||||
const char MSG_BED[] PROGMEM_I1 = ISTR("Bed"); ////
|
||||
const char MSG_BED_DONE[] PROGMEM_I1 = ISTR("Bed done"); ////
|
||||
const char MSG_BED_HEATING[] PROGMEM_I1 = ISTR("Bed Heating"); ////
|
||||
const char MSG_BED_LEVELING_FAILED_POINT_LOW[] PROGMEM_I1 = ISTR("Bed leveling failed. Sensor didnt trigger. Debris on nozzle? Waiting for reset."); ////c=20 r=4
|
||||
const char MSG_BED_SKEW_OFFSET_DETECTION_FITTING_FAILED[] PROGMEM_I1 = ISTR("XYZ calibration failed. Please consult the manual."); ////c=20 r=8
|
||||
const char MSG_CALIBRATE_Z_AUTO[] PROGMEM_I1 = ISTR("Calibrating Z"); ////c=20 r=2
|
||||
const char MSG_CARD_MENU[] PROGMEM_I1 = ISTR("Print from SD"); ////
|
||||
const char MSG_CONFIRM_NOZZLE_CLEAN[] PROGMEM_I1 = ISTR("Please clean the nozzle for calibration. Click when done."); ////c=20 r=8
|
||||
const char MSG_COOLDOWN[] PROGMEM_I1 = ISTR("Cooldown"); ////
|
||||
const char MSG_CRASH_DETECTED[] PROGMEM_I1 = ISTR("Crash detected."); ////c=20 r=1
|
||||
const char MSG_CRASHDETECT[] PROGMEM_I1 = ISTR("Crash det."); ////
|
||||
const char MSG_ERROR[] PROGMEM_I1 = ISTR("ERROR:"); ////
|
||||
const char MSG_EXTRUDER[] PROGMEM_I1 = ISTR("Extruder"); ////c=17 r=1
|
||||
const char MSG_FILAMENT[] PROGMEM_I1 = ISTR("Filament"); ////c=17 r=1
|
||||
const char MSG_FAN_SPEED[] PROGMEM_I1 = ISTR("Fan speed"); ////c=14
|
||||
const char MSG_FILAMENT_CLEAN[] PROGMEM_I1 = ISTR("Filament extruding & with correct color?"); ////c=20 r=2
|
||||
const char MSG_FILAMENT_LOADING_T0[] PROGMEM_I1 = ISTR("Insert filament into extruder 1. Click when done."); ////c=20 r=4
|
||||
const char MSG_FILAMENT_LOADING_T1[] PROGMEM_I1 = ISTR("Insert filament into extruder 2. Click when done."); ////c=20 r=4
|
||||
const char MSG_FILAMENT_LOADING_T2[] PROGMEM_I1 = ISTR("Insert filament into extruder 3. Click when done."); ////c=20 r=4
|
||||
const char MSG_FILAMENT_LOADING_T3[] PROGMEM_I1 = ISTR("Insert filament into extruder 4. Click when done."); ////c=20 r=4
|
||||
const char MSG_FILAMENTCHANGE[] PROGMEM_I1 = ISTR("Change filament"); ////
|
||||
const char MSG_FIND_BED_OFFSET_AND_SKEW_LINE1[] PROGMEM_I1 = ISTR("Searching bed calibration point"); ////c=60
|
||||
const char MSG_FIND_BED_OFFSET_AND_SKEW_LINE2[] PROGMEM_I1 = ISTR(" of 4"); ////c=14
|
||||
const char MSG_FINISHING_MOVEMENTS[] PROGMEM_I1 = ISTR("Finishing movements"); ////c=20 r=1
|
||||
const char MSG_FOLLOW_CALIBRATION_FLOW[] PROGMEM_I1 = ISTR("Printer has not been calibrated yet. Please follow the manual, chapter First steps, section Calibration flow."); ////c=20 r=8
|
||||
const char MSG_FOLLOW_Z_CALIBRATION_FLOW[] PROGMEM_I1 = ISTR("There is still a need to make Z calibration. Please follow the manual, chapter First steps, section Calibration flow."); ////c=20 r=8
|
||||
const char MSG_FSENSOR_AUTOLOAD[] PROGMEM_I1 = ISTR("F. autoload"); ////c=17 r=1
|
||||
const char MSG_FSENSOR[] PROGMEM_I1 = ISTR("Fil. sensor"); ////
|
||||
const char MSG_HEATING[] PROGMEM_I1 = ISTR("Heating"); ////
|
||||
const char MSG_HEATING_COMPLETE[] PROGMEM_I1 = ISTR("Heating done."); ////c=20
|
||||
const char MSG_HOMEYZ[] PROGMEM_I1 = ISTR("Calibrate Z"); ////
|
||||
const char MSG_CHOOSE_EXTRUDER[] PROGMEM_I1 = ISTR("Choose extruder:"); ////c=20 r=1
|
||||
const char MSG_CHOOSE_FILAMENT[] PROGMEM_I1 = ISTR("Choose filament:"); ////c=20 r=1
|
||||
const char MSG_LOAD_FILAMENT[] PROGMEM_I1 = ISTR("Load filament"); //// Number 1 to 5 is added behind text e.g. "Load filament 1" c=16
|
||||
const char MSG_LOADING_FILAMENT[] PROGMEM_I1 = ISTR("Loading filament"); ////c=20
|
||||
const char MSG_EJECT_FILAMENT[] PROGMEM_I1 = ISTR("Eject filament"); //// Number 1 to 5 is added behind text e.g. "Eject filament 1" c=16
|
||||
const char MSG_CUT_FILAMENT[] PROGMEM_I1 = ISTR("Cut filament"); //// Number 1 to 5 is added behind text e.g. "Cut filament 1" c=16
|
||||
const char MSG_M117_V2_CALIBRATION[] PROGMEM_I1 = ISTR("M117 First layer cal."); ////c=25 r=1
|
||||
const char MSG_MAIN[] PROGMEM_I1 = ISTR("Main"); ////
|
||||
const char MSG_BACK[] PROGMEM_I1 = ISTR("Back"); ////
|
||||
const char MSG_SHEET[] PROGMEM_I1 = ISTR("Sheet"); ////c=10
|
||||
const char MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE1[] PROGMEM_I1 = ISTR("Measuring reference height of calibration point"); ////c=60
|
||||
const char MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2[] PROGMEM_I1 = ISTR(" of 9"); ////c=14
|
||||
const char MSG_MENU_CALIBRATION[] PROGMEM_I1 = ISTR("Calibration"); ////
|
||||
const char MSG_NO[] PROGMEM_I1 = ISTR("No"); ////
|
||||
const char MSG_NOZZLE[] PROGMEM_I1 = ISTR("Nozzle"); ////
|
||||
const char MSG_PAPER[] PROGMEM_I1 = ISTR("Place a sheet of paper under the nozzle during the calibration of first 4 points. If the nozzle catches the paper, power off the printer immediately."); ////c=20 r=8
|
||||
const char MSG_PLACE_STEEL_SHEET[] PROGMEM_I1 = ISTR("Please place steel sheet on heatbed."); ////c=20 r=4
|
||||
const char MSG_PLEASE_WAIT[] PROGMEM_I1 = ISTR("Please wait"); ////c=20
|
||||
const char MSG_PREHEAT_NOZZLE[] PROGMEM_I1 = ISTR("Preheat the nozzle!"); ////c=20
|
||||
const char MSG_PRESS_TO_UNLOAD[] PROGMEM_I1 = ISTR("Please press the knob to unload filament"); ////c=20 r=4
|
||||
const char MSG_PRINT_ABORTED[] PROGMEM_I1 = ISTR("Print aborted"); ////c=20
|
||||
const char MSG_PULL_OUT_FILAMENT[] PROGMEM_I1 = ISTR("Please pull out filament immediately"); ////c=20 r=4
|
||||
const char MSG_RECOVER_PRINT[] PROGMEM_I1 = ISTR("Blackout occurred. Recover print?"); ////c=20 r=2
|
||||
const char MSG_REFRESH[] PROGMEM_I1 = ISTR("\xF8" "Refresh"); ////
|
||||
const char MSG_RESUMING_PRINT[] PROGMEM_I1 = ISTR("Resuming print"); ////
|
||||
const char MSG_REMOVE_STEEL_SHEET[] PROGMEM_I1 = ISTR("Please remove steel sheet from heatbed."); ////c=20 r=4
|
||||
const char MSG_SELFTEST_COOLING_FAN[] PROGMEM_I1 = ISTR("Front print fan?"); ////c=20
|
||||
const char MSG_SELFTEST_EXTRUDER_FAN[] PROGMEM_I1 = ISTR("Left hotend fan?"); ////c=20
|
||||
const char MSG_SELFTEST_FAILED[] PROGMEM_I1 = ISTR("Selftest failed "); ////c=20
|
||||
const char MSG_SELFTEST_FAN[] PROGMEM_I1 = ISTR("Fan test"); ////c=20
|
||||
const char MSG_SELFTEST_FAN_NO[] PROGMEM_I1 = ISTR("Not spinning"); ////c=19
|
||||
const char MSG_SELFTEST_FAN_YES[] PROGMEM_I1 = ISTR("Spinning"); ////c=19
|
||||
const char MSG_SELFTEST_CHECK_BED[] PROGMEM_I1 = ISTR("Checking bed "); ////c=20
|
||||
const char MSG_SELFTEST_CHECK_FSENSOR[] PROGMEM_I1 = ISTR("Checking sensors "); ////c=20
|
||||
const char MSG_SELFTEST_MOTOR[] PROGMEM_I1 = ISTR("Motor"); ////
|
||||
const char MSG_SELFTEST_FILAMENT_SENSOR[] PROGMEM_I1 = ISTR("Filament sensor"); ////c=17
|
||||
const char MSG_SELFTEST_WIRINGERROR[] PROGMEM_I1 = ISTR("Wiring error"); ////
|
||||
const char MSG_SETTINGS[] PROGMEM_I1 = ISTR("Settings"); ////
|
||||
const char MSG_HW_SETUP[] PROGMEM_I1 = ISTR("HW Setup"); ////
|
||||
const char MSG_MODE[] PROGMEM_I1 = ISTR("Mode"); ////
|
||||
const char MSG_HIGH_POWER[] PROGMEM_I1 = ISTR("High power"); ////
|
||||
const char MSG_AUTO_POWER[] PROGMEM_I1 = ISTR("Auto power"); ////
|
||||
const char MSG_SILENT[] PROGMEM_I1 = ISTR("Silent"); ////
|
||||
const char MSG_NORMAL[] PROGMEM_I1 = ISTR("Normal"); ////
|
||||
const char MSG_STEALTH[] PROGMEM_I1 = ISTR("Stealth"); ////
|
||||
const char MSG_STEEL_SHEET_CHECK[] PROGMEM_I1 = ISTR("Is steel sheet on heatbed?"); ////c=20 r=2
|
||||
const char MSG_STOP_PRINT[] PROGMEM_I1 = ISTR("Stop print"); ////
|
||||
const char MSG_STOPPED[] PROGMEM_I1 = ISTR("STOPPED. "); ////
|
||||
const char MSG_TEMP_CALIBRATION[] PROGMEM_I1 = ISTR("Temp. cal."); ////c=12 r=1
|
||||
const char MSG_TEMP_CALIBRATION_DONE[] PROGMEM_I1 = ISTR("Temperature calibration is finished and active. Temp. calibration can be disabled in menu Settings->Temp. cal."); ////c=20 r=12
|
||||
const char MSG_UNLOAD_FILAMENT[] PROGMEM_I1 = ISTR("Unload filament"); ////c=17
|
||||
const char MSG_UNLOADING_FILAMENT[] PROGMEM_I1 = ISTR("Unloading filament"); ////c=20 r=1
|
||||
const char MSG_WATCH[] PROGMEM_I1 = ISTR("Info screen"); ////
|
||||
const char MSG_WIZARD_CALIBRATION_FAILED[] PROGMEM_I1 = ISTR("Please check our handbook and fix the problem. Then resume the Wizard by rebooting the printer."); ////c=20 r=8
|
||||
const char MSG_WIZARD_DONE[] PROGMEM_I1 = ISTR("All is done. Happy printing!"); ////c=20 r=8
|
||||
const char MSG_WIZARD_HEATING[] PROGMEM_I1 = ISTR("Preheating nozzle. Please wait."); ////c=20 r=3
|
||||
const char MSG_WIZARD_QUIT[] PROGMEM_I1 = ISTR("You can always resume the Wizard from Calibration -> Wizard."); ////c=20 r=8
|
||||
const char MSG_YES[] PROGMEM_I1 = ISTR("Yes"); ////
|
||||
const char MSG_V2_CALIBRATION[] PROGMEM_I1 = ISTR("First layer cal."); ////c=17 r=1
|
||||
const char WELCOME_MSG[] PROGMEM_I1 = ISTR(CUSTOM_MENDEL_NAME " OK."); ////c=20
|
||||
const char MSG_OFF[] PROGMEM_I1 = ISTR("Off"); ////
|
||||
const char MSG_ON[] PROGMEM_I1 = ISTR("On"); ////
|
||||
const char MSG_NA[] PROGMEM_I1 = ISTR("N/A"); ////
|
||||
const char MSG_AUTO_DEPLETE[] PROGMEM_I1 = ISTR("SpoolJoin"); ////
|
||||
const char MSG_CUTTER[] PROGMEM_I1 = ISTR("Cutter"); ////
|
||||
const char MSG_NONE[] PROGMEM_I1 = ISTR("None"); ////
|
||||
const char MSG_WARN[] PROGMEM_I1 = ISTR("Warn"); ////
|
||||
const char MSG_STRICT[] PROGMEM_I1 = ISTR("Strict"); ////
|
||||
const char MSG_MODEL[] PROGMEM_I1 = ISTR("Model"); ////
|
||||
const char MSG_FIRMWARE[] PROGMEM_I1 = ISTR("Firmware"); ////
|
||||
const char MSG_GCODE[] PROGMEM_I1 = ISTR("Gcode"); ////
|
||||
const char MSG_NOZZLE_DIAMETER[] PROGMEM_I1 = ISTR("Nozzle d."); ////
|
||||
const char MSG_MMU_MODE[] PROGMEM_I1 = ISTR("MMU Mode"); ////
|
||||
const char MSG_SD_CARD[] PROGMEM_I1 = ISTR("SD card"); ////
|
||||
const char MSG_TOSHIBA_FLASH_AIR_COMPATIBILITY[] PROGMEM_I1 = ISTR("FlashAir"); ////
|
||||
const char MSG_SORT[] PROGMEM_I1 = ISTR("Sort"); ////
|
||||
const char MSG_SORT_TIME[] PROGMEM_I1 = ISTR("Time"); ////
|
||||
const char MSG_SORT_ALPHA[] PROGMEM_I1 = ISTR("Alphabet"); ////
|
||||
const char MSG_RPI_PORT[] PROGMEM_I1 = ISTR("RPi port"); ////
|
||||
const char MSG_SOUND[] PROGMEM_I1 = ISTR("Sound"); ////
|
||||
const char MSG_SOUND_LOUD[] PROGMEM_I1 = ISTR("Loud"); ////
|
||||
const char MSG_SOUND_ONCE[] PROGMEM_I1 = ISTR("Once"); ////
|
||||
const char MSG_SOUND_BLIND[] PROGMEM_I1 = ISTR("Assist"); ////
|
||||
const char MSG_MESH[] PROGMEM_I1 = ISTR("Mesh"); ////
|
||||
const char MSG_Z_PROBE_NR[] PROGMEM_I1 = ISTR("Z-probe nr."); ////
|
||||
const char MSG_MAGNETS_COMP[] PROGMEM_I1 = ISTR("Magnets comp."); ////
|
||||
const char MSG_FS_ACTION[] PROGMEM_I1 = ISTR("FS Action"); ////
|
||||
const char MSG_FS_CONTINUE[] PROGMEM_I1 = ISTR("Cont."); ////
|
||||
const char MSG_FS_PAUSE[] PROGMEM_I1 = ISTR("Pause"); ////
|
||||
const char MSG_BRIGHTNESS[] PROGMEM_I1 = ISTR("Brightness"); ////
|
||||
const char MSG_BL_HIGH[] PROGMEM_I1 = ISTR("Level Bright"); ////
|
||||
const char MSG_BL_LOW[] PROGMEM_I1 = ISTR("Level Dimmed"); ////
|
||||
const char MSG_TIMEOUT[] PROGMEM_I1 = ISTR("Timeout"); ////
|
||||
const char MSG_BRIGHT[] PROGMEM_I1 = ISTR("Bright"); ////
|
||||
const char MSG_DIM[] PROGMEM_I1 = ISTR("Dim"); ////
|
||||
const char MSG_AUTO[] PROGMEM_I1 = ISTR("Auto"); ////
|
||||
|
||||
//not internationalized messages
|
||||
const char MSG_SD_WORKDIR_FAIL[] PROGMEM_N1 = "workDir open failed"; ////
|
||||
const char MSG_BROWNOUT_RESET[] PROGMEM_N1 = " Brown out Reset"; ////
|
||||
const char MSG_EXTERNAL_RESET[] PROGMEM_N1 = " External Reset"; ////
|
||||
const char MSG_FILE_SAVED[] PROGMEM_N1 = "Done saving file."; ////
|
||||
const char MSG_POSITION_UNKNOWN[] PROGMEM_N1 = "Home X/Y before Z"; ////
|
||||
const char MSG_SOFTWARE_RESET[] PROGMEM_N1 = " Software Reset"; ////
|
||||
const char MSG_UNKNOWN_COMMAND[] PROGMEM_N1 = "Unknown command: \""; ////
|
||||
const char MSG_WATCHDOG_RESET[] PROGMEM_N1 = " Watchdog Reset"; ////
|
||||
const char MSG_Z_MAX[] PROGMEM_N1 = "z_max: "; ////
|
||||
const char MSG_Z_MIN[] PROGMEM_N1 = "z_min: "; ////
|
||||
const char MSG_ZPROBE_OUT[] PROGMEM_N1 = "Z probe out. bed"; ////
|
||||
const char MSG_ZPROBE_ZOFFSET[] PROGMEM_N1 = "Z Offset"; ////
|
||||
const char MSG_TMC_OVERTEMP[] PROGMEM_N1 = "TMC DRIVER OVERTEMP"; ////
|
||||
const char MSG_Enqueing[] PROGMEM_N1 = "enqueing \""; ////
|
||||
const char MSG_ENDSTOPS_HIT[] PROGMEM_N1 = "endstops hit: "; ////
|
||||
const char MSG_SD_ERR_WRITE_TO_FILE[] PROGMEM_N1 = "error writing to file"; ////
|
||||
const char MSG_OK[] PROGMEM_N1 = "ok"; ////
|
||||
const char MSG_SD_OPEN_FILE_FAIL[] PROGMEM_N1 = "open failed, File: "; ////
|
||||
const char MSG_ENDSTOP_OPEN[] PROGMEM_N1 = "open"; ////
|
||||
const char MSG_POWERUP[] PROGMEM_N1 = "PowerUp"; ////
|
||||
const char MSG_ERR_STOPPED[] PROGMEM_N1 = "Printer stopped due to errors. Fix the error and use M999 to restart. (Temperature is reset. Set it after restarting)"; ////
|
||||
const char MSG_ENDSTOP_HIT[] PROGMEM_N1 = "TRIGGERED"; ////
|
||||
const char MSG_OCTOPRINT_PAUSED[] PROGMEM_N1 = "// action:paused"; ////
|
||||
const char MSG_OCTOPRINT_RESUMED[] PROGMEM_N1 = "// action:resumed"; ////
|
||||
const char MSG_OCTOPRINT_CANCEL[] PROGMEM_N1 = "// action:cancel"; ////
|
||||
const char MSG_FANCHECK_EXTRUDER[] PROGMEM_N1 = "Err: EXTR. FAN ERROR"; ////c=20
|
||||
const char MSG_FANCHECK_PRINT[] PROGMEM_N1 = "Err: PRINT FAN ERROR"; ////c=20
|
||||
const char MSG_M112_KILL[] PROGMEM_N1 = "M112 called. Emergency Stop."; ////c=20
|
||||
#ifdef LA_LIVE_K
|
||||
const char MSG_ADVANCE_K[] PROGMEM_N1 = "Advance K:"; ////c=13
|
||||
#endif
|
||||
|
|
@ -0,0 +1,230 @@
|
|||
//messages.c
|
||||
#include "language.h"
|
||||
|
||||
//this is because we need CUSTOM_MENDEL_NAME
|
||||
#include "Configuration_var.h"
|
||||
|
||||
//internationalized messages
|
||||
const char MSG_ALWAYS[] PROGMEM_I1 = ISTR("Always"); ////MSG_ALWAYS c=6
|
||||
const char MSG_AUTO_HOME[] PROGMEM_I1 = ISTR("Auto home"); ////MSG_AUTO_HOME c=18
|
||||
const char MSG_BABYSTEP_Z[] PROGMEM_I1 = ISTR("Live adjust Z"); ////MSG_BABYSTEP_Z c=18
|
||||
const char MSG_BABYSTEP_Z_NOT_SET[] PROGMEM_I1 = ISTR("Distance between tip of the nozzle and the bed surface has not been set yet. Please follow the manual, chapter First steps, section First layer calibration."); ////MSG_BABYSTEP_Z_NOT_SET c=20 r=12
|
||||
const char MSG_BED[] PROGMEM_I1 = ISTR("Bed"); ////MSG_BED c=13
|
||||
const char MSG_BED_DONE[] PROGMEM_I1 = ISTR("Bed done"); ////MSG_BED_DONE c=20
|
||||
const char MSG_BED_HEATING[] PROGMEM_I1 = ISTR("Bed Heating"); ////MSG_BED_HEATING c=20
|
||||
const char MSG_BED_LEVELING_FAILED_POINT_LOW[] PROGMEM_I1 = ISTR("Bed leveling failed. Sensor didn't trigger. Debris on nozzle? Waiting for reset."); ////MSG_BED_LEVELING_FAILED_POINT_LOW c=20 r=6
|
||||
const char MSG_BED_SKEW_OFFSET_DETECTION_FITTING_FAILED[] PROGMEM_I1 = ISTR("XYZ calibration failed. Please consult the manual."); ////MSG_BED_SKEW_OFFSET_DETECTION_FITTING_FAILED c=20 r=8
|
||||
const char MSG_BELT_STATUS[] PROGMEM_I1 = ISTR("Belt status");////MSG_BELT_STATUS c=18
|
||||
const char MSG_CANCEL[] PROGMEM_I1 = ISTR(">Cancel");////MSG_CANCEL c=10
|
||||
const char MSG_CALIBRATE_Z_AUTO[] PROGMEM_I1 = ISTR("Calibrating Z"); ////MSG_CALIBRATE_Z_AUTO c=20 r=2
|
||||
const char MSG_CARD_MENU[] PROGMEM_I1 = ISTR("Print from SD"); ////MSG_CARD_MENU c=18
|
||||
const char MSG_CHECKING_X[] PROGMEM_I1 = ISTR("Checking X axis"); ////MSG_CHECKING_X c=20
|
||||
const char MSG_CHECKING_Y[] PROGMEM_I1 = ISTR("Checking Y axis"); ////MSG_CHECKING_Y c=20
|
||||
const char MSG_COMMUNITY_MADE[] PROGMEM_I1 = ISTR("Community made"); ////MSG_COMMUNITY_MADE c=18
|
||||
const char MSG_CONFIRM_NOZZLE_CLEAN[] PROGMEM_I1 = ISTR("Please clean the nozzle for calibration. Click when done."); ////MSG_CONFIRM_NOZZLE_CLEAN c=20 r=8
|
||||
const char MSG_COOLDOWN[] PROGMEM_I1 = ISTR("Cooldown"); ////MSG_COOLDOWN c=18
|
||||
const char MSG_CRASH[] PROGMEM_I1 = ISTR("Crash"); ////MSG_CRASH c=7
|
||||
const char MSG_CRASH_DETECTED[] PROGMEM_I1 = ISTR("Crash detected."); ////MSG_CRASH_DETECTED c=20
|
||||
const char MSG_CRASHDETECT[] PROGMEM_I1 = ISTR("Crash det."); ////MSG_CRASHDETECT c=13
|
||||
const char MSG_ERROR[] PROGMEM_I1 = ISTR("ERROR:"); ////MSG_ERROR c=10
|
||||
const char MSG_EXTRUDER[] PROGMEM_I1 = ISTR("Extruder"); ////MSG_EXTRUDER c=17
|
||||
const char MSG_FANS_CHECK[] PROGMEM_I1 = ISTR("Fans check"); ////MSG_FANS_CHECK c=13
|
||||
const char MSG_FIL_RUNOUTS[] PROGMEM_I1 = ISTR("Fil. runouts"); ////MSG_FIL_RUNOUTS c=15
|
||||
const char MSG_FILAMENT[] PROGMEM_I1 = ISTR("Filament"); ////MSG_FILAMENT c=17
|
||||
const char MSG_FAN_SPEED[] PROGMEM_I1 = ISTR("Fan speed"); ////MSG_FAN_SPEED c=14
|
||||
const char MSG_HOTEND_FAN_SPEED[] PROGMEM_I1 = ISTR("Hotend fan:");////MSG_HOTEND_FAN_SPEED c=15
|
||||
const char MSG_PRINT_FAN_SPEED[] PROGMEM_I1 = ISTR("Print fan:"); ////MSG_PRINT_FAN_SPEED c=15
|
||||
const char MSG_FILAMENT_CLEAN[] PROGMEM_I1 = ISTR("Filament extruding & with correct color?"); ////MSG_FILAMENT_CLEAN c=20 r=2
|
||||
const char MSG_FILAMENT_LOADED[] PROGMEM_I1 = ISTR("Is filament loaded?"); ////MSG_FILAMENT_LOADED c=20 r=2
|
||||
const char MSG_FILAMENTCHANGE[] PROGMEM_I1 = ISTR("Change filament"); ////MSG_FILAMENTCHANGE c=18
|
||||
const char MSG_FIND_BED_OFFSET_AND_SKEW_LINE1[] PROGMEM_I1 = ISTR("Searching bed calibration point"); ////MSG_FIND_BED_OFFSET_AND_SKEW_LINE1 c=20 r=3
|
||||
const char MSG_FINISHING_MOVEMENTS[] PROGMEM_I1 = ISTR("Finishing movements"); ////MSG_FINISHING_MOVEMENTS c=20
|
||||
const char MSG_FOLLOW_CALIBRATION_FLOW[] PROGMEM_I1 = ISTR("Printer has not been calibrated yet. Please follow the manual, chapter First steps, section Calibration flow."); ////MSG_FOLLOW_CALIBRATION_FLOW c=20 r=8
|
||||
const char MSG_FOLLOW_Z_CALIBRATION_FLOW[] PROGMEM_I1 = ISTR("There is still a need to make Z calibration. Please follow the manual, chapter First steps, section Calibration flow."); ////MSG_FOLLOW_Z_CALIBRATION_FLOW c=20 r=9
|
||||
const char MSG_FSENSOR_RUNOUT[] PROGMEM_I1 = ISTR("F. runout"); ////MSG_FSENSOR_RUNOUT c=13
|
||||
const char MSG_FSENSOR_AUTOLOAD[] PROGMEM_I1 = ISTR("F. autoload"); ////MSG_FSENSOR_AUTOLOAD c=13
|
||||
const char MSG_FSENSOR_JAM_DETECTION[] PROGMEM_I1 = ISTR("F. jam detect"); ////MSG_FSENSOR_JAM_DETECTION c=13
|
||||
const char MSG_FSENSOR[] PROGMEM_I1 = ISTR("Fil. sensor"); ////MSG_FSENSOR c=12
|
||||
const char MSG_HEATING[] PROGMEM_I1 = ISTR("Heating"); ////MSG_HEATING c=20
|
||||
const char MSG_HEATING_COMPLETE[] PROGMEM_I1 = ISTR("Heating done."); ////MSG_HEATING_COMPLETE c=20
|
||||
const char MSG_HOMEYZ[] PROGMEM_I1 = ISTR("Calibrate Z"); ////MSG_HOMEYZ c=18
|
||||
const char MSG_ITERATION[] PROGMEM_I1 = ISTR("Iteration"); ////MSG_ITERATION c=12
|
||||
const char MSG_SELECT_EXTRUDER[] PROGMEM_I1 = ISTR("Select extruder:"); ////MSG_SELECT_EXTRUDER c=20
|
||||
const char MSG_SELECT_FILAMENT[] PROGMEM_I1 = ISTR("Select filament:"); ////MSG_SELECT_FILAMENT c=20
|
||||
const char MSG_LAST_PRINT[] PROGMEM_I1 = ISTR("Last print"); ////MSG_LAST_PRINT c=18
|
||||
const char MSG_LAST_PRINT_FAILURES[] PROGMEM_I1 = ISTR("Last print failures"); ////MSG_LAST_PRINT_FAILURES c=20
|
||||
const char MSG_LOAD_FILAMENT[] PROGMEM_I1 = ISTR("Load filament"); ////MSG_LOAD_FILAMENT c=17
|
||||
const char MSG_LOADING_TEST[] PROGMEM_I1 = ISTR("Loading Test"); ////MSG_LOADING_TEST c=18
|
||||
const char MSG_LOADING_FILAMENT[] PROGMEM_I1 = ISTR("Loading filament"); ////MSG_LOADING_FILAMENT c=20
|
||||
const char MSG_TESTING_FILAMENT[] PROGMEM_I1 = ISTR("Testing filament"); ////MSG_TESTING_FILAMENT c=20
|
||||
const char MSG_EJECT_FILAMENT[] PROGMEM_I1 = ISTR("Eject filament"); ////MSG_EJECT_FILAMENT c=17
|
||||
const char MSG_CUT_FILAMENT[] PROGMEM_I1 = ISTR("Cut filament"); ////MSG_CUT_FILAMENT c=17
|
||||
const char MSG_MAIN[] PROGMEM_I1 = ISTR("Main"); ////MSG_MAIN c=18
|
||||
const char MSG_BACK[] PROGMEM_I1 = ISTR("Back"); ////MSG_BACK c=18
|
||||
const char MSG_SHEET[] PROGMEM_I1 = ISTR("Sheet"); ////MSG_SHEET c=10
|
||||
const char MSG_STEEL_SHEETS[] PROGMEM_I1 = ISTR("Steel sheets"); ////MSG_STEEL_SHEETS c=18
|
||||
const char MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE1[] PROGMEM_I1 = ISTR("Measuring reference height of calibration point"); ////MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE1 c=20 r=3
|
||||
const char MSG_CALIBRATION[] PROGMEM_I1 = ISTR("Calibration"); ////MSG_CALIBRATION c=18
|
||||
const char MSG_MMU_FAILS[] PROGMEM_I1 = ISTR("MMU fails"); ////MSG_MMU_FAILS c=15
|
||||
const char MSG_MMU_LOAD_FAILS[] PROGMEM_I1 = ISTR("MMU load fails"); ////MSG_MMU_LOAD_FAILS c=15
|
||||
const char MSG_MMU_POWER_FAILS[] PROGMEM_I1 = ISTR("MMU power fails"); ////MSG_MMU_POWER_FAILS c=15
|
||||
const char MSG_NO[] PROGMEM_I1 = ISTR("No"); ////MSG_NO c=4
|
||||
const char MSG_NOZZLE[] PROGMEM_I1 = ISTR("Nozzle"); ////MSG_NOZZLE c=10
|
||||
const char MSG_PAPER[] PROGMEM_I1 = ISTR("Place a sheet of paper under the nozzle during the calibration of first 4 points. If the nozzle catches the paper, power off the printer immediately."); ////MSG_PAPER c=20 r=10
|
||||
const char MSG_PAUSE_PRINT[] PROGMEM_I1 = ISTR("Pause print");////MSG_PAUSE_PRINT c=18
|
||||
const char MSG_PLACE_STEEL_SHEET[] PROGMEM_I1 = ISTR("Please place steel sheet on heatbed."); ////MSG_PLACE_STEEL_SHEET c=20 r=5
|
||||
const char MSG_PLEASE_WAIT[] PROGMEM_I1 = ISTR("Please wait"); ////MSG_PLEASE_WAIT c=20
|
||||
const char MSG_POWER_FAILURES[] PROGMEM_I1 = ISTR("Power failures"); ////MSG_POWER_FAILURES c=15
|
||||
const char MSG_PREHEAT_NOZZLE[] PROGMEM_I1 = ISTR("Preheat the nozzle!"); ////MSG_PREHEAT_NOZZLE c=20
|
||||
const char MSG_PRESS_TO_UNLOAD[] PROGMEM_I1 = ISTR("Please press the knob to unload filament"); ////MSG_PRESS_TO_UNLOAD c=20 r=4
|
||||
const char MSG_PRINT_ABORTED[] PROGMEM_I1 = ISTR("Print aborted"); ////MSG_PRINT_ABORTED c=20
|
||||
const char MSG_PULL_OUT_FILAMENT[] PROGMEM_I1 = ISTR("Please pull out filament immediately"); ////MSG_PULL_OUT_FILAMENT c=20 r=4
|
||||
const char MSG_RECOVER_PRINT[] PROGMEM_I1 = ISTR("Blackout occurred. Recover print?"); ////MSG_RECOVER_PRINT c=20 r=2
|
||||
const char MSG_REFRESH[] PROGMEM_I1 = ISTR("\x04Refresh"); ////MSG_REFRESH c=18
|
||||
const char MSG_REMOVE_STEEL_SHEET[] PROGMEM_I1 = ISTR("Please remove steel sheet from heatbed."); ////MSG_REMOVE_STEEL_SHEET c=20 r=4
|
||||
const char MSG_RESET[] PROGMEM_I1 = ISTR("Reset"); ////MSG_RESET c=14
|
||||
const char MSG_RESUME_PRINT[] PROGMEM_I1 = ISTR("Resume print"); ////MSG_RESUME_PRINT c=18
|
||||
const char MSG_RESUMING_PRINT[] PROGMEM_I1 = ISTR("Resuming print"); ////MSG_RESUMING_PRINT c=20
|
||||
const char MSG_SELFTEST_PART_FAN[] PROGMEM_I1 = ISTR("Front print fan?"); ////MSG_SELFTEST_PART_FAN c=20
|
||||
const char MSG_SELFTEST_HOTEND_FAN[] PROGMEM_I1 = ISTR("Left hotend fan?"); ////MSG_SELFTEST_HOTEND_FAN c=20
|
||||
const char MSG_SELFTEST_FAILED[] PROGMEM_I1 = ISTR("Selftest failed"); ////MSG_SELFTEST_FAILED c=20
|
||||
const char MSG_SELFTEST_FAN[] PROGMEM_I1 = ISTR("Fan test"); ////MSG_SELFTEST_FAN c=20
|
||||
const char MSG_SELFTEST_FAN_NO[] PROGMEM_I1 = ISTR("Not spinning"); ////MSG_SELFTEST_FAN_NO c=19
|
||||
const char MSG_SELFTEST_FAN_YES[] PROGMEM_I1 = ISTR("Spinning"); ////MSG_SELFTEST_FAN_YES c=19
|
||||
const char MSG_SELFTEST_CHECK_BED[] PROGMEM_I1 = ISTR("Checking bed"); ////MSG_SELFTEST_CHECK_BED c=20
|
||||
const char MSG_SELFTEST_CHECK_FSENSOR[] PROGMEM_I1 = ISTR("Checking sensors"); ////MSG_SELFTEST_CHECK_FSENSOR c=20
|
||||
const char MSG_SELFTEST_MOTOR[] PROGMEM_I1 = ISTR("Motor"); ////MSG_SELFTEST_MOTOR c=18
|
||||
const char MSG_SELFTEST_FILAMENT_SENSOR[] PROGMEM_I1 = ISTR("Filament sensor"); ////MSG_SELFTEST_FILAMENT_SENSOR c=17
|
||||
const char MSG_SELFTEST_WIRINGERROR[] PROGMEM_I1 = ISTR("Wiring error"); ////MSG_SELFTEST_WIRINGERROR c=18
|
||||
const char MSG_SETTINGS[] PROGMEM_I1 = ISTR("Settings"); ////MSG_SETTINGS c=18
|
||||
const char MSG_SELECT_LANGUAGE[] PROGMEM_I1 = ISTR("Select language"); ////MSG_SELECT_LANGUAGE c=18
|
||||
const char MSG_SORTING_FILES[] PROGMEM_I1 = ISTR("Sorting files"); ////MSG_SORTING_FILES c=20
|
||||
const char MSG_TOTAL[] PROGMEM_I1 = ISTR("Total"); ////MSG_TOTAL c=6
|
||||
const char MSG_MATERIAL_CHANGES[] PROGMEM_I1 = ISTR("Material changes"); ////MSG_MATERIAL_CHANGES c=18
|
||||
const char MSG_TOTAL_FAILURES[] PROGMEM_I1 = ISTR("Total failures"); ////MSG_TOTAL_FAILURES c=20
|
||||
const char MSG_HW_SETUP[] PROGMEM_I1 = ISTR("HW Setup"); ////MSG_HW_SETUP c=18
|
||||
const char MSG_MODE[] PROGMEM_I1 = ISTR("Mode"); ////MSG_MODE c=6
|
||||
const char MSG_HIGH_POWER[] PROGMEM_I1 = ISTR("High power"); ////MSG_HIGH_POWER c=10
|
||||
const char MSG_AUTO_POWER[] PROGMEM_I1 = ISTR("Auto power"); ////MSG_AUTO_POWER c=10
|
||||
const char MSG_SILENT[] PROGMEM_I1 = ISTR("Silent"); ////MSG_SILENT c=7
|
||||
const char MSG_NORMAL[] PROGMEM_I1 = ISTR("Normal"); ////MSG_NORMAL c=7
|
||||
const char MSG_STEALTH[] PROGMEM_I1 = ISTR("Stealth"); ////MSG_STEALTH c=7
|
||||
const char MSG_STEEL_SHEET_CHECK[] PROGMEM_I1 = ISTR("Is steel sheet on heatbed?"); ////MSG_STEEL_SHEET_CHECK c=20 r=2
|
||||
const char MSG_STOP_PRINT[] PROGMEM_I1 = ISTR("Stop print"); ////MSG_STOP_PRINT c=18
|
||||
const char MSG_STOPPED[] PROGMEM_I1 = ISTR("STOPPED."); ////MSG_STOPPED c=20
|
||||
const char MSG_PINDA_CALIBRATION[] PROGMEM_I1 = ISTR("PINDA cal."); ////MSG_PINDA_CALIBRATION c=13
|
||||
const char MSG_PINDA_CALIBRATION_DONE[] PROGMEM_I1 = ISTR("PINDA calibration is finished and active. It can be disabled in menu Settings->PINDA cal."); ////MSG_PINDA_CALIBRATION_DONE c=20 r=8
|
||||
const char MSG_UNLOAD_FILAMENT[] PROGMEM_I1 = ISTR("Unload filament"); ////MSG_UNLOAD_FILAMENT c=16
|
||||
const char MSG_UNLOADING_FILAMENT[] PROGMEM_I1 = ISTR("Unloading filament"); ////MSG_UNLOADING_FILAMENT c=20
|
||||
const char MSG_INFO_SCREEN[] PROGMEM_I1 = ISTR("Info screen"); ////MSG_INFO_SCREEN c=18
|
||||
const char MSG_WIZARD_CALIBRATION_FAILED[] PROGMEM_I1 = ISTR("Please check our handbook and fix the problem. Then resume the Wizard by rebooting the printer."); ////MSG_WIZARD_CALIBRATION_FAILED c=20 r=8
|
||||
const char MSG_WIZARD_DONE[] PROGMEM_I1 = ISTR("All is done. Happy printing!"); ////MSG_WIZARD_DONE c=20 r=3
|
||||
const char MSG_WIZARD_HEATING[] PROGMEM_I1 = ISTR("Preheating nozzle. Please wait."); ////MSG_WIZARD_HEATING c=20 r=3
|
||||
const char MSG_WIZARD_QUIT[] PROGMEM_I1 = ISTR("You can always resume the Wizard from Calibration -> Wizard."); ////MSG_WIZARD_QUIT c=20 r=8
|
||||
const char MSG_WIZARD_WELCOME[] PROGMEM_I1 = ISTR("Hi, I am your Original Prusa i3 printer. Would you like me to guide you through the setup process?"); ////MSG_WIZARD_WELCOME c=20 r=7
|
||||
const char MSG_WIZARD_WELCOME_SHIPPING[] PROGMEM_I1 = ISTR("Hi, I am your Original Prusa i3 printer. I will guide you through a short setup process, in which the Z-axis will be calibrated. Then, you will be ready to print."); ////MSG_WIZARD_WELCOME_SHIPPING c=20 r=12
|
||||
const char MSG_YES[] PROGMEM_I1 = ISTR("Yes"); ////MSG_YES c=4
|
||||
const char MSG_V2_CALIBRATION[] PROGMEM_I1 = ISTR("First layer cal."); ////MSG_V2_CALIBRATION c=18
|
||||
const char MSG_OFF[] PROGMEM_I1 = ISTR("Off"); ////MSG_OFF c=3
|
||||
const char MSG_ON[] PROGMEM_I1 = ISTR("On"); ////MSG_ON c=3
|
||||
const char MSG_NA[] PROGMEM_I1 = ISTR("N/A"); ////MSG_NA c=3
|
||||
const char MSG_CUTTER[] PROGMEM_I1 = ISTR("Cutter"); ////MSG_CUTTER c=9
|
||||
const char MSG_NONE[] PROGMEM_I1 = ISTR("None"); ////MSG_NONE c=8
|
||||
const char MSG_WARN[] PROGMEM_I1 = ISTR("Warn"); ////MSG_WARN c=8
|
||||
const char MSG_STRICT[] PROGMEM_I1 = ISTR("Strict"); ////MSG_STRICT c=8
|
||||
const char MSG_MODEL[] PROGMEM_I1 = ISTR("Model"); ////MSG_MODEL c=8
|
||||
const char MSG_GCODE_DIFF_PRINTER_CONTINUE[] PROGMEM_I1 = ISTR("G-code sliced for a different printer type. Continue?"); ////MSG_GCODE_DIFF_PRINTER_CONTINUE c=20 r=3
|
||||
const char MSG_GCODE_DIFF_PRINTER_CANCELLED[] PROGMEM_I1 =ISTR("G-code sliced for a different printer type. Please re-slice the model again. Print cancelled."); ////MSG_GCODE_DIFF_PRINTER_CANCELLED c=20 r=8
|
||||
const char MSG_GCODE_NEWER_FIRMWARE_CONTINUE[] PROGMEM_I1 = ISTR("G-code sliced for a newer firmware. Continue?"); ////MSG_GCODE_NEWER_FIRMWARE_CONTINUE c=20 r=3
|
||||
const char MSG_GCODE_NEWER_FIRMWARE_CANCELLED[] PROGMEM_I1 = ISTR("G-code sliced for a newer firmware. Please update the firmware. Print cancelled."); ////MSG_GCODE_NEWER_FIRMWARE_CANCELLED c=20 r=8
|
||||
const char MSG_GCODE_DIFF_CONTINUE[] PROGMEM_I1 = ISTR("G-code sliced for a different level. Continue?"); ////MSG_GCODE_DIFF_CONTINUE c=20 r=3
|
||||
const char MSG_GCODE_DIFF_CANCELLED[] PROGMEM_I1 = ISTR("G-code sliced for a different level. Please re-slice the model again. Print cancelled."); ////MSG_GCODE_DIFF_CANCELLED c=20 r=8
|
||||
const char MSG_NOZZLE_DIFFERS_CONTINUE[] PROGMEM_I1 = ISTR("Nozzle diameter differs from the G-code. Continue?"); ////MSG_NOZZLE_DIFFERS_CONTINUE c=20 r=3
|
||||
const char MSG_NOZZLE_DIFFERS_CANCELLED[] PROGMEM_I1 = ISTR("Nozzle diameter differs from the G-code. Please check the value in settings. Print cancelled."); ////MSG_NOZZLE_DIFFERS_CANCELLED c=20 r=9
|
||||
const char MSG_NOZZLE_DIAMETER[] PROGMEM_I1 = ISTR("Nozzle d."); ////MSG_NOZZLE_DIAMETER c=10
|
||||
const char MSG_MMU_MODE[] PROGMEM_I1 = ISTR("MMU Mode"); ////MSG_MMU_MODE c=8
|
||||
const char MSG_SD_CARD[] PROGMEM_I1 = ISTR("SD card"); ////MSG_SD_CARD c=8
|
||||
const char MSG_SORT[] PROGMEM_I1 = ISTR("Sort"); ////MSG_SORT c=7
|
||||
const char MSG_SORT_TIME[] PROGMEM_I1 = ISTR("Time"); ////MSG_SORT_TIME c=8
|
||||
const char MSG_SORT_ALPHA[] PROGMEM_I1 = ISTR("Alphabet"); ////MSG_SORT_ALPHA c=8
|
||||
const char MSG_RPI_PORT[] PROGMEM_I1 = ISTR("RPi port"); ////MSG_RPI_PORT c=13
|
||||
const char MSG_SOUND[] PROGMEM_I1 = ISTR("Sound"); ////MSG_SOUND c=9
|
||||
const char MSG_SOUND_LOUD[] PROGMEM_I1 = ISTR("Loud"); ////MSG_SOUND_LOUD c=7
|
||||
const char MSG_SOUND_ONCE[] PROGMEM_I1 = ISTR("Once"); ////MSG_SOUND_ONCE c=7
|
||||
const char MSG_SOUND_BLIND[] PROGMEM_I1 = ISTR("Assist"); ////MSG_SOUND_BLIND c=7
|
||||
const char MSG_MESH[] PROGMEM_I1 = ISTR("Mesh"); ////MSG_MESH c=12
|
||||
const char MSG_MESH_BED_LEVELING[] PROGMEM_I1 = ISTR("Mesh Bed Leveling"); ////MSG_MESH_BED_LEVELING c=18
|
||||
const char MSG_Z_PROBE_NR[] PROGMEM_I1 = ISTR("Z-probe nr."); ////MSG_Z_PROBE_NR c=14
|
||||
const char MSG_MAGNETS_COMP[] PROGMEM_I1 = ISTR("Magnets comp."); ////MSG_MAGNETS_COMP c=13
|
||||
const char MSG_FS_ACTION[] PROGMEM_I1 = ISTR("FS Action"); ////MSG_FS_ACTION c=10
|
||||
const char MSG_CONTINUE_SHORT[] PROGMEM_I1 = ISTR("Cont."); ////MSG_CONTINUE_SHORT c=5
|
||||
const char MSG_PAUSE[] PROGMEM_I1 = ISTR("Pause"); ////MSG_PAUSE c=5
|
||||
const char MSG_BRIGHTNESS[] PROGMEM_I1 = ISTR("Brightness"); ////MSG_BRIGHTNESS c=18
|
||||
const char MSG_BL_HIGH[] PROGMEM_I1 = ISTR("Level Bright"); ////MSG_BL_HIGH c=12
|
||||
const char MSG_BL_LOW[] PROGMEM_I1 = ISTR("Level Dimmed"); ////MSG_BL_LOW c=12
|
||||
const char MSG_TIMEOUT[] PROGMEM_I1 = ISTR("Timeout"); ////MSG_TIMEOUT c=12
|
||||
const char MSG_BRIGHT[] PROGMEM_I1 = ISTR("Bright"); ////MSG_BRIGHT c=6
|
||||
const char MSG_DIM[] PROGMEM_I1 = ISTR("Dim"); ////MSG_DIM c=6
|
||||
const char MSG_AUTO[] PROGMEM_I1 = ISTR("Auto"); ////MSG_AUTO c=6
|
||||
#if (FILAMENT_SENSOR_TYPE == FSENSOR_IR_ANALOG)
|
||||
// Beware - the space at the beginning is necessary since it is reused in LCD menu items which are to be with a space
|
||||
const char MSG_IR_04_OR_NEWER[] PROGMEM_I1 = ISTR(" 0.4 or newer");////MSG_IR_04_OR_NEWER c=18
|
||||
const char MSG_IR_03_OR_OLDER[] PROGMEM_I1 = ISTR(" 0.3 or older");////MSG_IR_03_OR_OLDER c=18
|
||||
const char MSG_IR_UNKNOWN[] PROGMEM_I1 = ISTR("unknown state");////MSG_IR_UNKNOWN c=18
|
||||
#endif
|
||||
extern const char MSG_PAUSED_THERMAL_ERROR[] PROGMEM_I1 = ISTR("PAUSED THERMAL ERROR");////MSG_PAUSED_THERMAL_ERROR c=20
|
||||
#ifdef TEMP_MODEL
|
||||
extern const char MSG_THERMAL_ANOMALY[] PROGMEM_I1 = ISTR("THERMAL ANOMALY");////MSG_THERMAL_ANOMALY c=20
|
||||
extern const char MSG_TM_NOT_CAL[] PROGMEM_I1 = ISTR("Thermal model not calibrated yet.");////MSG_TM_NOT_CAL c=20 r=4
|
||||
extern const char MSG_TM_ACK_ERROR[] PROGMEM_I1 = ISTR("Clear TM error");////MSG_TM_ACK_ERROR c=18
|
||||
#endif
|
||||
extern const char MSG_LOAD_ALL[] PROGMEM_I1 = ISTR("Load All"); ////MSG_LOAD_ALL c=18
|
||||
extern const char MSG_NOZZLE_CNG_MENU [] PROGMEM_I1 = ISTR("Nozzle change");////MSG_NOZZLE_CNG_MENU c=18
|
||||
extern const char MSG_NOZZLE_CNG_READ_HELP [] PROGMEM_I1 = ISTR("For a Nozzle change please read\nprusa.io/nozzle-mk3s");////MSG_NOZZLE_CNG_READ_HELP c=20 r=4
|
||||
extern const char MSG_NOZZLE_CNG_CHANGED [] PROGMEM_I1 = ISTR("Hotend at 280C! Nozzle changed and tightened to specs?");////MSG_NOZZLE_CNG_CHANGED c=20 r=6
|
||||
|
||||
//not internationalized messages
|
||||
#if 0
|
||||
const char MSG_FW_VERSION_BETA[] PROGMEM_N1 = "You are using a BETA firmware version! It is in a development state! Use this version with CAUTION as it may DAMAGE the printer!"; ////MSG_FW_VERSION_BETA c=20 r=8
|
||||
#endif
|
||||
const char MSG_SPOOL_JOIN[] PROGMEM_N1 = "SpoolJoin"; ////MSG_SPOOL_JOIN c=13
|
||||
const char MSG_FIRMWARE[] PROGMEM_N1 = "Firmware"; ////MSG_FIRMWARE c=8
|
||||
const char MSG_TOSHIBA_FLASH_AIR_COMPATIBILITY[] PROGMEM_N1 = "FlashAir"; ////MSG_TOSHIBA_FLASH_AIR_COMPATIBILITY c=8
|
||||
const char MSG_PINDA[] PROGMEM_N1 = "PINDA"; ////MSG_PINDA c=5
|
||||
const char MSG_WELCOME[] PROGMEM_N1 = WELCOME_MSG;
|
||||
const char MSG_SD_WORKDIR_FAIL[] PROGMEM_N1 = "workDir open failed"; ////
|
||||
const char MSG_BROWNOUT_RESET[] PROGMEM_N1 = " Brown out Reset"; ////
|
||||
const char MSG_EXTERNAL_RESET[] PROGMEM_N1 = " External Reset"; ////
|
||||
const char MSG_FILE_SAVED[] PROGMEM_N1 = "Done saving file."; ////
|
||||
const char MSG_POSITION_UNKNOWN[] PROGMEM_N1 = "Home X/Y before Z"; ////
|
||||
const char MSG_SOFTWARE_RESET[] PROGMEM_N1 = " Software Reset"; ////
|
||||
const char MSG_UNKNOWN_COMMAND[] PROGMEM_N1 = "Unknown command: \""; ////
|
||||
const char MSG_WATCHDOG_RESET[] PROGMEM_N1 = " Watchdog Reset"; ////
|
||||
const char MSG_Z_MAX[] PROGMEM_N1 = "z_max: "; ////
|
||||
const char MSG_Z_MIN[] PROGMEM_N1 = "z_min: "; ////
|
||||
const char MSG_ZPROBE_OUT[] PROGMEM_N1 = "Z probe out. bed"; ////
|
||||
#ifdef ENABLE_AUTO_BED_LEVELING
|
||||
const char MSG_ZPROBE_ZOFFSET[] PROGMEM_N1 = "Z Offset"; ////
|
||||
#endif
|
||||
const char MSG_TMC_OVERTEMP[] PROGMEM_N1 = "TMC DRIVER OVERTEMP"; ////
|
||||
const char MSG_Enqueing[] PROGMEM_N1 = "enqueing \""; ////
|
||||
const char MSG_ENDSTOPS_HIT[] PROGMEM_N1 = "endstops hit: "; ////
|
||||
const char MSG_SD_ERR_WRITE_TO_FILE[] PROGMEM_N1 = "error writing to file"; ////
|
||||
const char MSG_OK[] PROGMEM_N1 = "ok"; ////
|
||||
const char MSG_SD_OPEN_FILE_FAIL[] PROGMEM_N1 = "open failed, File: "; ////
|
||||
const char MSG_ENDSTOP_OPEN[] PROGMEM_N1 = "open"; ////
|
||||
const char MSG_POWERUP[] PROGMEM_N1 = "PowerUp"; ////
|
||||
const char MSG_ERR_STOPPED[] PROGMEM_N1 = "Printer stopped due to errors. Supervision required."; ////
|
||||
const char MSG_ENDSTOP_HIT[] PROGMEM_N1 = "TRIGGERED"; ////
|
||||
const char MSG_OCTOPRINT_ASK_PAUSE[] PROGMEM_N1 = "// action:pause"; ////
|
||||
const char MSG_OCTOPRINT_PAUSED[] PROGMEM_N1 = "// action:paused"; ////
|
||||
const char MSG_OCTOPRINT_ASK_RESUME[] PROGMEM_N1 = "// action:resume"; ////
|
||||
const char MSG_OCTOPRINT_RESUMED[] PROGMEM_N1 = "// action:resumed"; ////
|
||||
const char MSG_OCTOPRINT_CANCEL[] PROGMEM_N1 = "// action:cancel"; ////
|
||||
const char MSG_FANCHECK_HOTEND[] PROGMEM_N1 = "Err:HOTEND FAN ERROR"; ////c=20
|
||||
const char MSG_FANCHECK_PRINT[] PROGMEM_N1 = "Err:PRINT FAN ERROR"; ////c=20
|
||||
const char MSG_M112_KILL[] PROGMEM_N1 = "M112 called. Emergency Stop."; ////c=20
|
||||
const char MSG_ADVANCE_K[] PROGMEM_N1 = "Advance K:"; ////c=13
|
||||
const char MSG_POWERPANIC_DETECTED[] PROGMEM_N1 = "POWER PANIC DETECTED"; ////c=20
|
||||
const char MSG_LCD_STATUS_CHANGED[] PROGMEM_N1 = "LCD status changed";
|
||||
const char MSG_UNKNOWN_CODE[] PROGMEM_N1 = "Unknown %c code: %s\n";
|
||||
|
|
@ -7,8 +7,11 @@
|
|||
extern "C" {
|
||||
#endif //defined(__cplusplus)
|
||||
|
||||
#define WELCOME_MSG (CUSTOM_MENDEL_NAME " OK.")
|
||||
|
||||
// LCD Menu Messages
|
||||
//internationalized messages
|
||||
extern const char MSG_ALWAYS[];
|
||||
extern const char MSG_AUTO_HOME[];
|
||||
extern const char MSG_BABYSTEP_Z[];
|
||||
extern const char MSG_BABYSTEP_Z_NOT_SET[];
|
||||
|
|
@ -17,48 +20,66 @@ extern const char MSG_BED_DONE[];
|
|||
extern const char MSG_BED_HEATING[];
|
||||
extern const char MSG_BED_LEVELING_FAILED_POINT_LOW[];
|
||||
extern const char MSG_BED_SKEW_OFFSET_DETECTION_FITTING_FAILED[];
|
||||
extern const char MSG_BELT_STATUS[];
|
||||
extern const char MSG_CANCEL[];
|
||||
extern const char MSG_CALIBRATE_Z_AUTO[];
|
||||
extern const char MSG_CARD_MENU[];
|
||||
extern const char MSG_CHECKING_X[];
|
||||
extern const char MSG_CHECKING_Y[];
|
||||
extern const char MSG_COMMUNITY_MADE[];
|
||||
extern const char MSG_CONFIRM_NOZZLE_CLEAN[];
|
||||
extern const char MSG_COOLDOWN[];
|
||||
extern const char MSG_CRASH[];
|
||||
extern const char MSG_CRASH_DETECTED[];
|
||||
extern const char MSG_CRASHDETECT[];
|
||||
extern const char MSG_ERROR[];
|
||||
extern const char MSG_EXTRUDER[];
|
||||
extern const char MSG_FANS_CHECK[];
|
||||
extern const char MSG_FIL_RUNOUTS[];
|
||||
extern const char MSG_FILAMENT[];
|
||||
extern const char MSG_FAN_SPEED[];
|
||||
extern const char MSG_HOTEND_FAN_SPEED[];
|
||||
extern const char MSG_PRINT_FAN_SPEED[];
|
||||
extern const char MSG_FILAMENT_CLEAN[];
|
||||
extern const char MSG_FILAMENT_LOADING_T0[];
|
||||
extern const char MSG_FILAMENT_LOADING_T1[];
|
||||
extern const char MSG_FILAMENT_LOADING_T2[];
|
||||
extern const char MSG_FILAMENT_LOADING_T3[];
|
||||
extern const char MSG_FILAMENT_LOADED[];
|
||||
extern const char MSG_FILAMENTCHANGE[];
|
||||
extern const char MSG_FIND_BED_OFFSET_AND_SKEW_LINE1[];
|
||||
extern const char MSG_FIND_BED_OFFSET_AND_SKEW_LINE2[];
|
||||
extern const char MSG_FINISHING_MOVEMENTS[];
|
||||
extern const char MSG_FOLLOW_CALIBRATION_FLOW[];
|
||||
extern const char MSG_FOLLOW_Z_CALIBRATION_FLOW[];
|
||||
extern const char MSG_FSENSOR_RUNOUT[];
|
||||
extern const char MSG_FSENSOR_AUTOLOAD[];
|
||||
extern const char MSG_FSENSOR_JAM_DETECTION[];
|
||||
extern const char MSG_FSENSOR[];
|
||||
extern const char MSG_HEATING[];
|
||||
extern const char MSG_HEATING_COMPLETE[];
|
||||
extern const char MSG_HOMEYZ[];
|
||||
extern const char MSG_CHOOSE_EXTRUDER[];
|
||||
extern const char MSG_CHOOSE_FILAMENT[];
|
||||
extern const char MSG_ITERATION[];
|
||||
extern const char MSG_SELECT_EXTRUDER[];
|
||||
extern const char MSG_SELECT_FILAMENT[];
|
||||
extern const char MSG_LAST_PRINT[];
|
||||
extern const char MSG_LAST_PRINT_FAILURES[];
|
||||
extern const char MSG_LOAD_FILAMENT[];
|
||||
extern const char MSG_LOADING_TEST[];
|
||||
extern const char MSG_LOADING_FILAMENT[];
|
||||
extern const char MSG_TESTING_FILAMENT[];
|
||||
extern const char MSG_M117_V2_CALIBRATION[];
|
||||
extern const char MSG_MAIN[];
|
||||
extern const char MSG_BACK[];
|
||||
extern const char MSG_SHEET[];
|
||||
extern const char MSG_STEEL_SHEETS[];
|
||||
extern const char MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE1[];
|
||||
extern const char MSG_MEASURE_BED_REFERENCE_HEIGHT_LINE2[];
|
||||
extern const char MSG_MENU_CALIBRATION[];
|
||||
extern const char MSG_CALIBRATION[];
|
||||
extern const char MSG_MMU_FAILS[];
|
||||
extern const char MSG_MMU_LOAD_FAILS[];
|
||||
extern const char MSG_MMU_POWER_FAILS[];
|
||||
extern const char MSG_NO[];
|
||||
extern const char MSG_NOZZLE[];
|
||||
extern const char MSG_PAPER[];
|
||||
extern const char MSG_PAUSE_PRINT[];
|
||||
extern const char MSG_PLACE_STEEL_SHEET[];
|
||||
extern const char MSG_PLEASE_WAIT[];
|
||||
extern const char MSG_POWER_FAILURES[];
|
||||
extern const char MSG_PREHEAT_NOZZLE[];
|
||||
extern const char MSG_PRESS_TO_UNLOAD[];
|
||||
extern const char MSG_PRINT_ABORTED[];
|
||||
|
|
@ -66,10 +87,11 @@ extern const char MSG_PULL_OUT_FILAMENT[];
|
|||
extern const char MSG_RECOVER_PRINT[];
|
||||
extern const char MSG_REFRESH[];
|
||||
extern const char MSG_REMOVE_STEEL_SHEET[];
|
||||
extern const char MSG_RESET[];
|
||||
extern const char MSG_RESUME_PRINT[];
|
||||
extern const char MSG_RESUMING_PRINT[];
|
||||
extern const char MSG_SD_WORKDIR_FAIL[];
|
||||
extern const char MSG_SELFTEST_COOLING_FAN[];
|
||||
extern const char MSG_SELFTEST_EXTRUDER_FAN[];
|
||||
extern const char MSG_SELFTEST_PART_FAN[];
|
||||
extern const char MSG_SELFTEST_HOTEND_FAN[];
|
||||
extern const char MSG_SELFTEST_FAILED[];
|
||||
extern const char MSG_SELFTEST_FAN[];
|
||||
extern const char MSG_SELFTEST_FAN_NO[];
|
||||
|
|
@ -80,6 +102,11 @@ extern const char MSG_SELFTEST_MOTOR[];
|
|||
extern const char MSG_SELFTEST_FILAMENT_SENSOR[];
|
||||
extern const char MSG_SELFTEST_WIRINGERROR[];
|
||||
extern const char MSG_SETTINGS[];
|
||||
extern const char MSG_SELECT_LANGUAGE[];
|
||||
extern const char MSG_SORTING_FILES[];
|
||||
extern const char MSG_TOTAL[];
|
||||
extern const char MSG_MATERIAL_CHANGES[];
|
||||
extern const char MSG_TOTAL_FAILURES[];
|
||||
extern const char MSG_HW_SETUP[];
|
||||
extern const char MSG_MODE[];
|
||||
extern const char MSG_HIGH_POWER[];
|
||||
|
|
@ -90,33 +117,38 @@ extern const char MSG_STEALTH[];
|
|||
extern const char MSG_STEEL_SHEET_CHECK[];
|
||||
extern const char MSG_STOP_PRINT[];
|
||||
extern const char MSG_STOPPED[];
|
||||
extern const char MSG_TEMP_CALIBRATION[];
|
||||
extern const char MSG_TEMP_CALIBRATION_DONE[];
|
||||
extern const char MSG_PINDA_CALIBRATION[];
|
||||
extern const char MSG_PINDA_CALIBRATION_DONE[];
|
||||
extern const char MSG_UNLOAD_FILAMENT[];
|
||||
extern const char MSG_UNLOADING_FILAMENT[];
|
||||
extern const char MSG_WATCH[];
|
||||
extern const char MSG_INFO_SCREEN[];
|
||||
extern const char MSG_WIZARD_CALIBRATION_FAILED[];
|
||||
extern const char MSG_WIZARD_DONE[];
|
||||
extern const char MSG_WIZARD_HEATING[];
|
||||
extern const char MSG_WIZARD_QUIT[];
|
||||
extern const char MSG_WIZARD_WELCOME[];
|
||||
extern const char MSG_WIZARD_WELCOME_SHIPPING[];
|
||||
extern const char MSG_YES[];
|
||||
extern const char MSG_V2_CALIBRATION[];
|
||||
extern const char WELCOME_MSG[];
|
||||
extern const char MSG_OFF[];
|
||||
extern const char MSG_ON[];
|
||||
extern const char MSG_NA[];
|
||||
extern const char MSG_AUTO_DEPLETE[];
|
||||
extern const char MSG_CUTTER[];
|
||||
extern const char MSG_NONE[];
|
||||
extern const char MSG_WARN[];
|
||||
extern const char MSG_STRICT[];
|
||||
extern const char MSG_MODEL[];
|
||||
extern const char MSG_FIRMWARE[];
|
||||
extern const char MSG_GCODE[];
|
||||
extern const char MSG_GCODE_DIFF_PRINTER_CONTINUE[];
|
||||
extern const char MSG_GCODE_DIFF_PRINTER_CANCELLED[];
|
||||
extern const char MSG_GCODE_NEWER_FIRMWARE_CONTINUE[];
|
||||
extern const char MSG_GCODE_NEWER_FIRMWARE_CANCELLED[];
|
||||
extern const char MSG_GCODE_DIFF_CONTINUE[];
|
||||
extern const char MSG_GCODE_DIFF_CANCELLED[];
|
||||
extern const char MSG_NOZZLE_DIFFERS_CONTINUE[];
|
||||
extern const char MSG_NOZZLE_DIFFERS_CANCELLED[];
|
||||
extern const char MSG_NOZZLE_DIAMETER[];
|
||||
extern const char MSG_MMU_MODE[];
|
||||
extern const char MSG_SD_CARD[];
|
||||
extern const char MSG_TOSHIBA_FLASH_AIR_COMPATIBILITY[];
|
||||
extern const char MSG_SORT[];
|
||||
extern const char MSG_SORT_TIME[];
|
||||
extern const char MSG_SORT_ALPHA[];
|
||||
|
|
@ -126,11 +158,12 @@ extern const char MSG_SOUND_LOUD[];
|
|||
extern const char MSG_SOUND_ONCE[];
|
||||
extern const char MSG_SOUND_BLIND[];
|
||||
extern const char MSG_MESH[];
|
||||
extern const char MSG_MESH_BED_LEVELING[];
|
||||
extern const char MSG_Z_PROBE_NR[];
|
||||
extern const char MSG_MAGNETS_COMP[];
|
||||
extern const char MSG_FS_ACTION[];
|
||||
extern const char MSG_FS_CONTINUE[];
|
||||
extern const char MSG_FS_PAUSE[];
|
||||
extern const char MSG_CONTINUE_SHORT[];
|
||||
extern const char MSG_PAUSE[];
|
||||
extern const char MSG_BRIGHTNESS[];
|
||||
extern const char MSG_BL_HIGH[];
|
||||
extern const char MSG_BL_LOW[];
|
||||
|
|
@ -138,8 +171,32 @@ extern const char MSG_TIMEOUT[];
|
|||
extern const char MSG_BRIGHT[];
|
||||
extern const char MSG_DIM[];
|
||||
extern const char MSG_AUTO[];
|
||||
#if (FILAMENT_SENSOR_TYPE == FSENSOR_IR_ANALOG)
|
||||
extern const char MSG_IR_04_OR_NEWER[];
|
||||
extern const char MSG_IR_03_OR_OLDER[];
|
||||
extern const char MSG_IR_UNKNOWN[];
|
||||
#endif
|
||||
extern const char MSG_PAUSED_THERMAL_ERROR[];
|
||||
#ifdef TEMP_MODEL
|
||||
extern const char MSG_THERMAL_ANOMALY[];
|
||||
extern const char MSG_TM_NOT_CAL[];
|
||||
extern const char MSG_TM_ACK_ERROR[];
|
||||
#endif
|
||||
extern const char MSG_LOAD_ALL[];
|
||||
extern const char MSG_NOZZLE_CNG_MENU [];
|
||||
extern const char MSG_NOZZLE_CNG_READ_HELP [];
|
||||
extern const char MSG_NOZZLE_CNG_CHANGED [];
|
||||
|
||||
//not internationalized messages
|
||||
#if 0
|
||||
extern const char MSG_FW_VERSION_BETA[];
|
||||
#endif
|
||||
extern const char MSG_SPOOL_JOIN[];
|
||||
extern const char MSG_FIRMWARE[];
|
||||
extern const char MSG_TOSHIBA_FLASH_AIR_COMPATIBILITY[];
|
||||
extern const char MSG_PINDA[];
|
||||
extern const char MSG_WELCOME[];
|
||||
extern const char MSG_SD_WORKDIR_FAIL[];
|
||||
extern const char MSG_BROWNOUT_RESET[];
|
||||
extern const char MSG_EXTERNAL_RESET[];
|
||||
extern const char MSG_FILE_SAVED[];
|
||||
|
|
@ -150,7 +207,9 @@ extern const char MSG_WATCHDOG_RESET[];
|
|||
extern const char MSG_Z_MAX[];
|
||||
extern const char MSG_Z_MIN[];
|
||||
extern const char MSG_ZPROBE_OUT[];
|
||||
#ifdef ENABLE_AUTO_BED_LEVELING
|
||||
extern const char MSG_ZPROBE_ZOFFSET[];
|
||||
#endif
|
||||
extern const char MSG_TMC_OVERTEMP[];
|
||||
extern const char MSG_Enqueing[];
|
||||
extern const char MSG_ENDSTOPS_HIT[];
|
||||
|
|
@ -163,13 +222,18 @@ extern const char MSG_ERR_STOPPED[];
|
|||
extern const char MSG_ENDSTOP_HIT[];
|
||||
extern const char MSG_EJECT_FILAMENT[];
|
||||
extern const char MSG_CUT_FILAMENT[];
|
||||
extern const char MSG_OCTOPRINT_ASK_PAUSE[];
|
||||
extern const char MSG_OCTOPRINT_PAUSED[];
|
||||
extern const char MSG_OCTOPRINT_ASK_RESUME[];
|
||||
extern const char MSG_OCTOPRINT_RESUMED[];
|
||||
extern const char MSG_OCTOPRINT_CANCEL[];
|
||||
extern const char MSG_FANCHECK_EXTRUDER[];
|
||||
extern const char MSG_FANCHECK_HOTEND[];
|
||||
extern const char MSG_FANCHECK_PRINT[];
|
||||
extern const char MSG_M112_KILL[];
|
||||
extern const char MSG_ADVANCE_K[];
|
||||
extern const char MSG_POWERPANIC_DETECTED[];
|
||||
extern const char MSG_LCD_STATUS_CHANGED[];
|
||||
extern const char MSG_UNKNOWN_CODE[];
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
|
|
|
|||
1606
Firmware/mmu.cpp
1606
Firmware/mmu.cpp
File diff suppressed because it is too large
Load Diff
142
Firmware/mmu.h
142
Firmware/mmu.h
|
|
@ -1,142 +0,0 @@
|
|||
//! @file
|
||||
|
||||
#ifndef MMU_H
|
||||
#define MMU_H
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
|
||||
extern bool mmu_enabled;
|
||||
extern bool mmu_fil_loaded;
|
||||
|
||||
extern uint8_t mmu_extruder;
|
||||
|
||||
extern uint8_t tmp_extruder;
|
||||
|
||||
extern int8_t mmu_finda;
|
||||
extern uint32_t mmu_last_finda_response;
|
||||
extern bool ir_sensor_detected;
|
||||
|
||||
extern int16_t mmu_version;
|
||||
extern int16_t mmu_buildnr;
|
||||
|
||||
extern uint16_t mmu_power_failures;
|
||||
|
||||
#define MMU_FILAMENT_UNKNOWN 255
|
||||
|
||||
#define MMU_NO_MOVE 0
|
||||
#define MMU_UNLOAD_MOVE 1
|
||||
#define MMU_LOAD_MOVE 2
|
||||
#define MMU_TCODE_MOVE 3
|
||||
|
||||
#define MMU_LOAD_FEEDRATE 19.02f //mm/s
|
||||
#define MMU_LOAD_TIME_MS 2000 //should be fine tuned to load time for shortest allowed PTFE tubing and maximum loading speed
|
||||
|
||||
enum class MmuCmd : uint_least8_t
|
||||
{
|
||||
None,
|
||||
T0,
|
||||
T1,
|
||||
T2,
|
||||
T3,
|
||||
T4,
|
||||
L0,
|
||||
L1,
|
||||
L2,
|
||||
L3,
|
||||
L4,
|
||||
C0,
|
||||
U0,
|
||||
E0,
|
||||
E1,
|
||||
E2,
|
||||
E3,
|
||||
E4,
|
||||
K0,
|
||||
K1,
|
||||
K2,
|
||||
K3,
|
||||
K4,
|
||||
R0,
|
||||
S3,
|
||||
W0, //!< Wait and signal load error
|
||||
};
|
||||
|
||||
inline MmuCmd operator+ (MmuCmd cmd, uint8_t filament)
|
||||
{
|
||||
return static_cast<MmuCmd>(static_cast<uint8_t>(cmd) + filament );
|
||||
}
|
||||
|
||||
inline uint8_t operator- (MmuCmd cmda, MmuCmd cmdb)
|
||||
{
|
||||
return (static_cast<uint8_t>(cmda) - static_cast<uint8_t>(cmdb));
|
||||
}
|
||||
|
||||
extern int mmu_puts_P(const char* str);
|
||||
|
||||
extern int mmu_printf_P(const char* format, ...);
|
||||
|
||||
extern int8_t mmu_rx_ok(void);
|
||||
|
||||
extern bool check_for_ir_sensor();
|
||||
|
||||
extern void mmu_init(void);
|
||||
|
||||
extern void mmu_loop(void);
|
||||
|
||||
|
||||
extern void mmu_reset(void);
|
||||
|
||||
extern int8_t mmu_set_filament_type(uint8_t extruder, uint8_t filament);
|
||||
|
||||
extern void mmu_command(MmuCmd cmd);
|
||||
|
||||
extern bool mmu_get_response(uint8_t move = 0);
|
||||
|
||||
extern void manage_response(bool move_axes, bool turn_off_nozzle, uint8_t move = MMU_NO_MOVE);
|
||||
|
||||
extern void mmu_load_to_nozzle();
|
||||
|
||||
extern void mmu_M600_load_filament(bool automatic, float nozzle_temp);
|
||||
extern void mmu_M600_wait_and_beep();
|
||||
|
||||
extern void extr_mov(float shift, float feed_rate);
|
||||
extern void change_extr(int extr);
|
||||
extern int get_ext_nr();
|
||||
extern void display_loading();
|
||||
extern void extr_adj(uint8_t extruder);
|
||||
extern void extr_unload();
|
||||
|
||||
extern void extr_adj_0();
|
||||
extern void extr_adj_1();
|
||||
extern void extr_adj_2();
|
||||
extern void extr_adj_3();
|
||||
extern void extr_adj_4();
|
||||
extern void load_all();
|
||||
extern void extr_change_0();
|
||||
extern void extr_change_1();
|
||||
extern void extr_change_2();
|
||||
extern void extr_change_3();
|
||||
#ifdef SNMM
|
||||
extern void extr_unload_all();
|
||||
extern void extr_unload_used();
|
||||
#endif //SNMM
|
||||
extern void extr_unload_0();
|
||||
extern void extr_unload_1();
|
||||
extern void extr_unload_2();
|
||||
extern void extr_unload_3();
|
||||
extern void extr_unload_4();
|
||||
|
||||
extern bool mmu_check_version();
|
||||
extern void mmu_show_warning();
|
||||
extern void lcd_mmu_load_to_nozzle(uint8_t filament_nr);
|
||||
extern void mmu_eject_filament(uint8_t filament, bool recover);
|
||||
#ifdef MMU_HAS_CUTTER
|
||||
extern void mmu_cut_filament(uint8_t filament_nr);
|
||||
#endif //MMU_HAS_CUTTER
|
||||
extern void mmu_continue_loading(bool blocking);
|
||||
extern void mmu_filament_ramming();
|
||||
extern void mmu_wait_for_heater_blocking();
|
||||
extern void mmu_load_step(bool synchronize = true);
|
||||
|
||||
#endif //MMU_H
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,318 @@
|
|||
/// @file
|
||||
#pragma once
|
||||
|
||||
#include "mmu2_state.h"
|
||||
#include "mmu2_marlin.h"
|
||||
|
||||
#ifdef __AVR__
|
||||
#include "mmu2_protocol_logic.h"
|
||||
typedef float feedRate_t;
|
||||
|
||||
#else
|
||||
|
||||
#include "protocol_logic.h"
|
||||
#include "../../Marlin/src/core/macros.h"
|
||||
#include "../../Marlin/src/core/types.h"
|
||||
#include <atomic>
|
||||
#endif
|
||||
|
||||
struct E_Step;
|
||||
|
||||
namespace MMU2 {
|
||||
|
||||
// general MMU setup for MK3
|
||||
enum : uint8_t {
|
||||
FILAMENT_UNKNOWN = 0xffU
|
||||
};
|
||||
|
||||
struct Version {
|
||||
uint8_t major, minor, build;
|
||||
};
|
||||
|
||||
/// Top-level interface between Logic and Marlin.
|
||||
/// Intentionally named MMU2 to be (almost) a drop-in replacement for the previous implementation.
|
||||
/// Most of the public methods share the original naming convention as well.
|
||||
class MMU2 {
|
||||
public:
|
||||
MMU2();
|
||||
|
||||
/// Powers ON the MMU, then initializes the UART and protocol logic
|
||||
void Start();
|
||||
|
||||
/// Stops the protocol logic, closes the UART, powers OFF the MMU
|
||||
void Stop();
|
||||
|
||||
inline xState State() const { return state; }
|
||||
|
||||
inline bool Enabled() const { return State() == xState::Active; }
|
||||
|
||||
/// Different levels of resetting the MMU
|
||||
enum ResetForm : uint8_t {
|
||||
Software = 0, ///< sends a X0 command into the MMU, the MMU will watchdog-reset itself
|
||||
ResetPin = 1, ///< trigger the reset pin of the MMU
|
||||
CutThePower = 2 ///< power off and power on (that includes +5V and +24V power lines)
|
||||
};
|
||||
|
||||
/// Saved print state on error.
|
||||
enum SavedState : uint8_t {
|
||||
None = 0, // No state saved.
|
||||
ParkExtruder = 1, // The extruder was parked.
|
||||
Cooldown = 2, // The extruder was allowed to cool.
|
||||
CooldownPending = 4,
|
||||
};
|
||||
|
||||
/// Source of operation error
|
||||
enum ErrorSource : uint8_t {
|
||||
ErrorSourcePrinter = 0,
|
||||
ErrorSourceMMU = 1,
|
||||
ErrorSourceNone = 0xFF,
|
||||
};
|
||||
|
||||
/// Perform a reset of the MMU
|
||||
/// @param level physical form of the reset
|
||||
void Reset(ResetForm level);
|
||||
|
||||
/// Power off the MMU (cut the power)
|
||||
void PowerOff();
|
||||
|
||||
/// Power on the MMU
|
||||
void PowerOn();
|
||||
|
||||
/// Read from a MMU register (See gcode M707)
|
||||
/// @param address Address of register in hexidecimal
|
||||
/// @returns true upon success
|
||||
bool ReadRegister(uint8_t address);
|
||||
|
||||
/// Write from a MMU register (See gcode M708)
|
||||
/// @param address Address of register in hexidecimal
|
||||
/// @param data Data to write to register
|
||||
/// @returns true upon success
|
||||
bool WriteRegister(uint8_t address, uint16_t data);
|
||||
|
||||
/// The main loop of MMU processing.
|
||||
/// Doesn't loop (block) inside, performs just one step of logic state machines.
|
||||
/// Also, internally it prevents recursive entries.
|
||||
void mmu_loop();
|
||||
|
||||
/// The main MMU command - select a different slot
|
||||
/// @param slot of the slot to be selected
|
||||
/// @returns false if the operation cannot be performed (Stopped)
|
||||
bool tool_change(uint8_t slot);
|
||||
|
||||
/// Handling of special Tx, Tc, T? commands
|
||||
bool tool_change(char code, uint8_t slot);
|
||||
|
||||
/// Unload of filament in collaboration with the MMU.
|
||||
/// That includes rotating the printer's extruder in order to release filament.
|
||||
/// @returns false if the operation cannot be performed (Stopped or cold extruder)
|
||||
bool unload();
|
||||
|
||||
/// Load (insert) filament just into the MMU (not into printer's nozzle)
|
||||
/// @returns false if the operation cannot be performed (Stopped)
|
||||
bool load_filament(uint8_t slot);
|
||||
|
||||
/// Load (push) filament from the MMU into the printer's nozzle
|
||||
/// @returns false if the operation cannot be performed (Stopped or cold extruder)
|
||||
bool load_filament_to_nozzle(uint8_t slot);
|
||||
|
||||
/// Move MMU's selector aside and push the selected filament forward.
|
||||
/// Usable for improving filament's tip or pulling the remaining piece of filament out completely.
|
||||
bool eject_filament(uint8_t slot, bool enableFullScreenMsg = true);
|
||||
|
||||
/// Issue a Cut command into the MMU
|
||||
/// Requires unloaded filament from the printer (obviously)
|
||||
/// @returns false if the operation cannot be performed (Stopped)
|
||||
bool cut_filament(uint8_t slot, bool enableFullScreenMsg = true);
|
||||
|
||||
/// Issue a planned request for statistics data from MMU
|
||||
void get_statistics();
|
||||
|
||||
/// Issue a Try-Load command
|
||||
/// It behaves very similarly like a ToolChange, but it doesn't load the filament
|
||||
/// all the way down to the nozzle. The sole purpose of this operation
|
||||
/// is to check, that the filament will be ready for printing.
|
||||
/// @param slot index of slot to be tested
|
||||
/// @returns true
|
||||
bool loading_test(uint8_t slot);
|
||||
|
||||
/// @returns the active filament slot index (0-4) or 0xff in case of no active tool
|
||||
uint8_t get_current_tool() const;
|
||||
|
||||
/// @returns The filament slot index (0 to 4) that will be loaded next, 0xff in case of no active tool change
|
||||
uint8_t get_tool_change_tool() const;
|
||||
|
||||
bool set_filament_type(uint8_t slot, uint8_t type);
|
||||
|
||||
/// Issue a "button" click into the MMU - to be used from Error screens of the MMU
|
||||
/// to select one of the 3 possible options to resolve the issue
|
||||
void Button(uint8_t index);
|
||||
|
||||
/// Issue an explicit "homing" command into the MMU
|
||||
void Home(uint8_t mode);
|
||||
|
||||
/// @returns current state of FINDA (true=filament present, false=filament not present)
|
||||
inline bool FindaDetectsFilament() const { return logic.FindaPressed(); }
|
||||
|
||||
inline uint16_t TotalFailStatistics() const { return logic.FailStatistics(); }
|
||||
|
||||
/// @returns Current error code
|
||||
inline ErrorCode MMUCurrentErrorCode() const { return logic.Error(); }
|
||||
|
||||
/// @returns Last error source
|
||||
inline ErrorSource MMULastErrorSource() const { return lastErrorSource; }
|
||||
|
||||
/// @returns the version of the connected MMU FW.
|
||||
/// In the future we'll return the trully detected FW version
|
||||
Version GetMMUFWVersion() const {
|
||||
if (State() == xState::Active) {
|
||||
return { logic.MmuFwVersionMajor(), logic.MmuFwVersionMinor(), logic.MmuFwVersionRevision() };
|
||||
} else {
|
||||
return { 0, 0, 0 };
|
||||
}
|
||||
}
|
||||
|
||||
// Helper variable to monitor knob in MMU error screen in blocking functions e.g. manage_response
|
||||
bool is_mmu_error_monitor_active;
|
||||
|
||||
/// Method to read-only mmu_print_saved
|
||||
inline bool MMU_PRINT_SAVED() const { return mmu_print_saved != SavedState::None; }
|
||||
|
||||
/// Automagically "press" a Retry button if we have any retry attempts left
|
||||
/// @param ec ErrorCode enum value
|
||||
/// @returns true if auto-retry is ongoing, false when retry is unavailable or retry attempts are all used up
|
||||
bool RetryIfPossible(uint16_t ec);
|
||||
|
||||
/// @return count for toolchange in current print
|
||||
inline uint16_t ToolChangeCounter() const { return toolchange_counter; };
|
||||
|
||||
/// Set toolchange counter to zero
|
||||
inline void ClearToolChangeCounter() { toolchange_counter = 0; };
|
||||
|
||||
inline uint16_t TMCFailures() const { return tmcFailures; }
|
||||
inline void IncrementTMCFailures() { ++tmcFailures; }
|
||||
inline void ClearTMCFailures() { tmcFailures = 0; }
|
||||
|
||||
private:
|
||||
/// Perform software self-reset of the MMU (sends an X0 command)
|
||||
void ResetX0();
|
||||
|
||||
/// Trigger reset pin of the MMU
|
||||
void TriggerResetPin();
|
||||
|
||||
/// Perform power cycle of the MMU (cold boot)
|
||||
/// Please note this is a blocking operation (sleeps for some time inside while doing the power cycle)
|
||||
void PowerCycle();
|
||||
|
||||
/// Stop the communication, but keep the MMU powered on (for scenarios with incorrect FW version)
|
||||
void StopKeepPowered();
|
||||
|
||||
/// Along with the mmu_loop method, this loops until a response from the MMU is received and acts upon.
|
||||
/// In case of an error, it parks the print head and turns off nozzle heating
|
||||
/// @returns false if the command could not have been completed (MMU interrupted)
|
||||
[[nodiscard]] bool manage_response(const bool move_axes, const bool turn_off_nozzle);
|
||||
|
||||
/// The inner private implementation of mmu_loop()
|
||||
/// which is NOT (!!!) recursion-guarded. Use caution - but we do need it during waiting for hotend resume to keep comms alive!
|
||||
/// @param reportErrors true if Errors should raise MMU Error screen, false otherwise
|
||||
void mmu_loop_inner(bool reportErrors);
|
||||
|
||||
/// Performs one step of the protocol logic state machine
|
||||
/// and reports progress and errors if needed to attached ExtUIs.
|
||||
/// Updates the global state of MMU (Active/Connecting/Stopped) at runtime, see @ref State
|
||||
/// @param reportErrors true if Errors should raise MMU Error screen, false otherwise
|
||||
StepStatus LogicStep(bool reportErrors);
|
||||
|
||||
void filament_ramming();
|
||||
void execute_extruder_sequence(const E_Step *sequence, uint8_t steps);
|
||||
void execute_load_to_nozzle_sequence();
|
||||
|
||||
/// Reports an error into attached ExtUIs
|
||||
/// @param ec error code, see ErrorCode
|
||||
/// @param res reporter error source, is either Printer (0) or MMU (1)
|
||||
void ReportError(ErrorCode ec, ErrorSource res);
|
||||
|
||||
/// Reports progress of operations into attached ExtUIs
|
||||
/// @param pc progress code, see ProgressCode
|
||||
void ReportProgress(ProgressCode pc);
|
||||
|
||||
/// Responds to a change of MMU's progress
|
||||
/// - plans additional steps, e.g. starts the E-motor after fsensor trigger
|
||||
void OnMMUProgressMsg(ProgressCode pc);
|
||||
/// Progress code changed - act accordingly
|
||||
void OnMMUProgressMsgChanged(ProgressCode pc);
|
||||
/// Repeated calls when progress code remains the same
|
||||
void OnMMUProgressMsgSame(ProgressCode pc);
|
||||
|
||||
/// @brief Save hotend temperature and set flag to cooldown hotend after 60 minutes
|
||||
/// @param turn_off_nozzle if true, the hotend temperature will be set to 0degC after 60 minutes
|
||||
void SaveHotendTemp(bool turn_off_nozzle);
|
||||
|
||||
/// Save print and park the print head
|
||||
void SaveAndPark(bool move_axes);
|
||||
|
||||
/// Resume hotend temperature, if it was cooled. Safe to call if we aren't saved.
|
||||
void ResumeHotendTemp();
|
||||
|
||||
/// Resume position, if the extruder was parked. Safe to all if state was not saved.
|
||||
void ResumeUnpark();
|
||||
|
||||
/// Check for any button/user input coming from the printer's UI
|
||||
void CheckUserInput();
|
||||
|
||||
/// @brief Check whether to trigger a FINDA runout. If triggered this function will call M600 AUTO
|
||||
/// if SpoolJoin is enabled, otherwise M600 is called without AUTO which will prompt the user
|
||||
/// for the next filament slot to use
|
||||
void CheckFINDARunout();
|
||||
|
||||
/// Entry check of all external commands.
|
||||
/// It can wait until the MMU becomes ready.
|
||||
/// Optionally, it can also emit/display an error screen and the user can decide what to do next.
|
||||
/// @returns false if the MMU is not ready to perform the command (for whatever reason)
|
||||
bool WaitForMMUReady();
|
||||
|
||||
/// After MMU completes a tool-change command
|
||||
/// the printer will push the filament by a constant distance. If the Fsensor untriggers
|
||||
/// at any moment the test fails. Else the test passes, and the E-motor retracts the
|
||||
/// filament back to its original position.
|
||||
/// @returns false if test fails, true otherwise
|
||||
bool VerifyFilamentEnteredPTFE();
|
||||
|
||||
/// Common processing of pushing filament into the extruder - shared by tool_change, load_to_nozzle and probably others
|
||||
void ToolChangeCommon(uint8_t slot);
|
||||
bool ToolChangeCommonOnce(uint8_t slot);
|
||||
|
||||
void HelpUnloadToFinda();
|
||||
|
||||
ProtocolLogic logic; ///< implementation of the protocol logic layer
|
||||
uint8_t extruder; ///< currently active slot in the MMU ... somewhat... not sure where to get it from yet
|
||||
uint8_t tool_change_extruder; ///< only used for UI purposes
|
||||
|
||||
pos3d resume_position;
|
||||
int16_t resume_hotend_temp;
|
||||
|
||||
ProgressCode lastProgressCode = ProgressCode::OK;
|
||||
ErrorCode lastErrorCode = ErrorCode::MMU_NOT_RESPONDING;
|
||||
ErrorSource lastErrorSource = ErrorSource::ErrorSourceNone;
|
||||
Buttons lastButton = Buttons::NoButton;
|
||||
|
||||
StepStatus logicStepLastStatus;
|
||||
|
||||
enum xState state;
|
||||
|
||||
uint8_t mmu_print_saved;
|
||||
bool loadFilamentStarted;
|
||||
bool unloadFilamentStarted;
|
||||
|
||||
friend struct LoadingToNozzleRAII;
|
||||
/// true in case we are doing the LoadToNozzle operation - that means the filament shall be loaded all the way down to the nozzle
|
||||
/// unlike the mid-print ToolChange commands, which only load the first ~30mm and then the G-code takes over.
|
||||
bool loadingToNozzle;
|
||||
uint16_t toolchange_counter;
|
||||
uint16_t tmcFailures;
|
||||
};
|
||||
|
||||
/// following Marlin's way of doing stuff - one and only instance of MMU implementation in the code base
|
||||
/// + avoiding buggy singletons on the AVR platform
|
||||
extern MMU2 mmu2;
|
||||
|
||||
} // namespace MMU2
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
// Helper macros to parse the operations from Btns()
|
||||
#define BUTTON_OP_RIGHT(X) ( ( X & 0xF0 ) >> 4 )
|
||||
#define BUTTON_OP_MIDDLE(X) ( X & 0x0F )
|
||||
|
||||
namespace MMU2 {
|
||||
|
||||
/// Will be mapped onto dialog button responses in the FW
|
||||
/// Those responses have their unique+translated texts as well
|
||||
enum class ButtonOperations : uint8_t {
|
||||
NoOperation = 0,
|
||||
Retry = 1,
|
||||
Continue = 2,
|
||||
RestartMMU = 3,
|
||||
Unload = 4,
|
||||
StopPrint = 5,
|
||||
DisableMMU = 6,
|
||||
};
|
||||
|
||||
/// Button codes + extended actions performed on the printer's side
|
||||
enum Buttons : uint8_t {
|
||||
Right = 0,
|
||||
Middle,
|
||||
Left,
|
||||
|
||||
// performed on the printer's side
|
||||
RestartMMU,
|
||||
StopPrint,
|
||||
DisableMMU,
|
||||
|
||||
NoButton = 0xff // shall be kept last
|
||||
};
|
||||
|
||||
|
||||
} // namespace MMU2
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue