diff --git a/.clang-format b/.clang-format index c1ea667913..2ac6d89793 100644 --- a/.clang-format +++ b/.clang-format @@ -75,6 +75,7 @@ IncludeCategories: - Regex: '.*' Priority: 1 IncludeIsMainRegex: '(Test)?$' +InsertBraces: true IndentCaseLabels: false IndentPPDirectives: BeforeHash IndentWidth: 4 diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 5aeac8ea77..3a3b2c8bdc 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -9,7 +9,7 @@ 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** - [MINI] +**Printer type** - [MINI, MK4, XL] **Printer firmware version** - [e.g. 4.0.5, ...] @@ -33,7 +33,9 @@ Please, before you create a new bug report, please make sure you searched in ope Please attach the G-code you had trouble with. This will make it easier for us to replicate the error. **Crash dump file** - Please attach the crash dump file. This will make it easier for us to investigate the bug. + Please send the crash dump file to Prusa by emailing it to reports@prusa3d.com. Sharing this file is important and helps us investigate the bug. + + Do not share the file publicly, as the crash dump contains a raw snapshot of the printer's memory and may include unencrypted sensitive information. **Video** Please attach a video. It usually helps to solve the problem. diff --git a/CMakeLists.txt b/CMakeLists.txt index 9c20fad4a9..6ffd92edc5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,7 +3,6 @@ include(ExternalProject) include(cmake/Utilities.cmake) include(cmake/GetGitRevisionDescription.cmake) include(cmake/ProjectVersion.cmake) -include(cmake/CheckRemotes.cmake) include(cmake/Littlefs.cmake) include(cmake/Options.cmake) diff --git a/CMakePresets.json b/CMakePresets.json index dfb89aeae6..3e98640b89 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -274,6 +274,1710 @@ } } }, + { + "name": "mini-en-cs_debug_boot", + "generator": "Ninja", + "binaryDir": "build-vscode-buddy", + "cacheVariables": { + "CMAKE_MAKE_PROGRAM": { + "type": "FILEPATH", + "value": "${sourceDir}/.dependencies/ninja-1.10.2/ninja" + }, + "CMAKE_EXPORT_COMPILE_COMMANDS": { + "type": "STRING", + "value": "ON" + }, + "PRINTER": { + "type": "STRING", + "value": "MINI" + }, + "BOARD": { + "type": "STRING", + "value": "" + }, + "BOARD_VERSION": { + "type": "STRING", + "value": "" + }, + "PRESET_COMPILE_OPTIONS": { + "type": "STRING", + "value": "" + }, + "DEVELOPMENT_ITEMS_ENABLED": { + "type": "BOOL", + "value": "YES" + }, + "TRANSLATIONS_LIST": { + "type": "STRING", + "value": "cs" + }, + "BOOTLOADER": { + "type": "STRING", + "value": "YES" + }, + "GENERATE_BBF": { + "type": "BOOL", + "value": "TRUE" + }, + "GENERATE_DFU": { + "type": "BOOL", + "value": "OFF" + }, + "SIGNING_KEY": { + "type": "FILEPATH", + "value": "" + }, + "CMAKE_TOOLCHAIN_FILE": { + "type": "FILEPATH", + "value": "${sourceDir}/cmake/GccArmNoneEabi.cmake" + }, + "CMAKE_BUILD_TYPE": { + "type": "STRING", + "value": "Debug" + }, + "PROJECT_VERSION_SUFFIX": { + "type": "STRING", + "value": "" + }, + "PROJECT_VERSION_SUFFIX_SHORT": { + "type": "STRING", + "value": "" + } + } + }, + { + "name": "mini-en-cs_debug_noboot", + "generator": "Ninja", + "binaryDir": "build-vscode-buddy", + "cacheVariables": { + "CMAKE_MAKE_PROGRAM": { + "type": "FILEPATH", + "value": "${sourceDir}/.dependencies/ninja-1.10.2/ninja" + }, + "CMAKE_EXPORT_COMPILE_COMMANDS": { + "type": "STRING", + "value": "ON" + }, + "PRINTER": { + "type": "STRING", + "value": "MINI" + }, + "BOARD": { + "type": "STRING", + "value": "" + }, + "BOARD_VERSION": { + "type": "STRING", + "value": "" + }, + "PRESET_COMPILE_OPTIONS": { + "type": "STRING", + "value": "" + }, + "DEVELOPMENT_ITEMS_ENABLED": { + "type": "BOOL", + "value": "YES" + }, + "TRANSLATIONS_LIST": { + "type": "STRING", + "value": "cs" + }, + "BOOTLOADER": { + "type": "STRING", + "value": "NO" + }, + "GENERATE_BBF": { + "type": "BOOL", + "value": "FALSE" + }, + "GENERATE_DFU": { + "type": "BOOL", + "value": "OFF" + }, + "SIGNING_KEY": { + "type": "FILEPATH", + "value": "" + }, + "CMAKE_TOOLCHAIN_FILE": { + "type": "FILEPATH", + "value": "${sourceDir}/cmake/GccArmNoneEabi.cmake" + }, + "CMAKE_BUILD_TYPE": { + "type": "STRING", + "value": "Debug" + }, + "PROJECT_VERSION_SUFFIX": { + "type": "STRING", + "value": "" + }, + "PROJECT_VERSION_SUFFIX_SHORT": { + "type": "STRING", + "value": "" + } + } + }, + { + "name": "mini-en-cs_release_boot", + "generator": "Ninja", + "binaryDir": "build-vscode-buddy", + "cacheVariables": { + "CMAKE_MAKE_PROGRAM": { + "type": "FILEPATH", + "value": "${sourceDir}/.dependencies/ninja-1.10.2/ninja" + }, + "CMAKE_EXPORT_COMPILE_COMMANDS": { + "type": "STRING", + "value": "ON" + }, + "PRINTER": { + "type": "STRING", + "value": "MINI" + }, + "BOARD": { + "type": "STRING", + "value": "" + }, + "BOARD_VERSION": { + "type": "STRING", + "value": "" + }, + "PRESET_COMPILE_OPTIONS": { + "type": "STRING", + "value": "" + }, + "DEVELOPMENT_ITEMS_ENABLED": { + "type": "BOOL", + "value": "YES" + }, + "TRANSLATIONS_LIST": { + "type": "STRING", + "value": "cs" + }, + "BOOTLOADER": { + "type": "STRING", + "value": "YES" + }, + "GENERATE_BBF": { + "type": "BOOL", + "value": "TRUE" + }, + "GENERATE_DFU": { + "type": "BOOL", + "value": "OFF" + }, + "SIGNING_KEY": { + "type": "FILEPATH", + "value": "" + }, + "CMAKE_TOOLCHAIN_FILE": { + "type": "FILEPATH", + "value": "${sourceDir}/cmake/GccArmNoneEabi.cmake" + }, + "CMAKE_BUILD_TYPE": { + "type": "STRING", + "value": "Release" + }, + "PROJECT_VERSION_SUFFIX": { + "type": "STRING", + "value": "" + }, + "PROJECT_VERSION_SUFFIX_SHORT": { + "type": "STRING", + "value": "" + } + } + }, + { + "name": "mini-en-cs_release_noboot", + "generator": "Ninja", + "binaryDir": "build-vscode-buddy", + "cacheVariables": { + "CMAKE_MAKE_PROGRAM": { + "type": "FILEPATH", + "value": "${sourceDir}/.dependencies/ninja-1.10.2/ninja" + }, + "CMAKE_EXPORT_COMPILE_COMMANDS": { + "type": "STRING", + "value": "ON" + }, + "PRINTER": { + "type": "STRING", + "value": "MINI" + }, + "BOARD": { + "type": "STRING", + "value": "" + }, + "BOARD_VERSION": { + "type": "STRING", + "value": "" + }, + "PRESET_COMPILE_OPTIONS": { + "type": "STRING", + "value": "" + }, + "DEVELOPMENT_ITEMS_ENABLED": { + "type": "BOOL", + "value": "YES" + }, + "TRANSLATIONS_LIST": { + "type": "STRING", + "value": "cs" + }, + "BOOTLOADER": { + "type": "STRING", + "value": "NO" + }, + "GENERATE_BBF": { + "type": "BOOL", + "value": "FALSE" + }, + "GENERATE_DFU": { + "type": "BOOL", + "value": "OFF" + }, + "SIGNING_KEY": { + "type": "FILEPATH", + "value": "" + }, + "CMAKE_TOOLCHAIN_FILE": { + "type": "FILEPATH", + "value": "${sourceDir}/cmake/GccArmNoneEabi.cmake" + }, + "CMAKE_BUILD_TYPE": { + "type": "STRING", + "value": "Release" + }, + "PROJECT_VERSION_SUFFIX": { + "type": "STRING", + "value": "" + }, + "PROJECT_VERSION_SUFFIX_SHORT": { + "type": "STRING", + "value": "" + } + } + }, + { + "name": "mini-en-de_debug_boot", + "generator": "Ninja", + "binaryDir": "build-vscode-buddy", + "cacheVariables": { + "CMAKE_MAKE_PROGRAM": { + "type": "FILEPATH", + "value": "${sourceDir}/.dependencies/ninja-1.10.2/ninja" + }, + "CMAKE_EXPORT_COMPILE_COMMANDS": { + "type": "STRING", + "value": "ON" + }, + "PRINTER": { + "type": "STRING", + "value": "MINI" + }, + "BOARD": { + "type": "STRING", + "value": "" + }, + "BOARD_VERSION": { + "type": "STRING", + "value": "" + }, + "PRESET_COMPILE_OPTIONS": { + "type": "STRING", + "value": "" + }, + "DEVELOPMENT_ITEMS_ENABLED": { + "type": "BOOL", + "value": "YES" + }, + "TRANSLATIONS_LIST": { + "type": "STRING", + "value": "de" + }, + "BOOTLOADER": { + "type": "STRING", + "value": "YES" + }, + "GENERATE_BBF": { + "type": "BOOL", + "value": "TRUE" + }, + "GENERATE_DFU": { + "type": "BOOL", + "value": "OFF" + }, + "SIGNING_KEY": { + "type": "FILEPATH", + "value": "" + }, + "CMAKE_TOOLCHAIN_FILE": { + "type": "FILEPATH", + "value": "${sourceDir}/cmake/GccArmNoneEabi.cmake" + }, + "CMAKE_BUILD_TYPE": { + "type": "STRING", + "value": "Debug" + }, + "PROJECT_VERSION_SUFFIX": { + "type": "STRING", + "value": "" + }, + "PROJECT_VERSION_SUFFIX_SHORT": { + "type": "STRING", + "value": "" + } + } + }, + { + "name": "mini-en-de_debug_noboot", + "generator": "Ninja", + "binaryDir": "build-vscode-buddy", + "cacheVariables": { + "CMAKE_MAKE_PROGRAM": { + "type": "FILEPATH", + "value": "${sourceDir}/.dependencies/ninja-1.10.2/ninja" + }, + "CMAKE_EXPORT_COMPILE_COMMANDS": { + "type": "STRING", + "value": "ON" + }, + "PRINTER": { + "type": "STRING", + "value": "MINI" + }, + "BOARD": { + "type": "STRING", + "value": "" + }, + "BOARD_VERSION": { + "type": "STRING", + "value": "" + }, + "PRESET_COMPILE_OPTIONS": { + "type": "STRING", + "value": "" + }, + "DEVELOPMENT_ITEMS_ENABLED": { + "type": "BOOL", + "value": "YES" + }, + "TRANSLATIONS_LIST": { + "type": "STRING", + "value": "de" + }, + "BOOTLOADER": { + "type": "STRING", + "value": "NO" + }, + "GENERATE_BBF": { + "type": "BOOL", + "value": "FALSE" + }, + "GENERATE_DFU": { + "type": "BOOL", + "value": "OFF" + }, + "SIGNING_KEY": { + "type": "FILEPATH", + "value": "" + }, + "CMAKE_TOOLCHAIN_FILE": { + "type": "FILEPATH", + "value": "${sourceDir}/cmake/GccArmNoneEabi.cmake" + }, + "CMAKE_BUILD_TYPE": { + "type": "STRING", + "value": "Debug" + }, + "PROJECT_VERSION_SUFFIX": { + "type": "STRING", + "value": "" + }, + "PROJECT_VERSION_SUFFIX_SHORT": { + "type": "STRING", + "value": "" + } + } + }, + { + "name": "mini-en-de_release_boot", + "generator": "Ninja", + "binaryDir": "build-vscode-buddy", + "cacheVariables": { + "CMAKE_MAKE_PROGRAM": { + "type": "FILEPATH", + "value": "${sourceDir}/.dependencies/ninja-1.10.2/ninja" + }, + "CMAKE_EXPORT_COMPILE_COMMANDS": { + "type": "STRING", + "value": "ON" + }, + "PRINTER": { + "type": "STRING", + "value": "MINI" + }, + "BOARD": { + "type": "STRING", + "value": "" + }, + "BOARD_VERSION": { + "type": "STRING", + "value": "" + }, + "PRESET_COMPILE_OPTIONS": { + "type": "STRING", + "value": "" + }, + "DEVELOPMENT_ITEMS_ENABLED": { + "type": "BOOL", + "value": "YES" + }, + "TRANSLATIONS_LIST": { + "type": "STRING", + "value": "de" + }, + "BOOTLOADER": { + "type": "STRING", + "value": "YES" + }, + "GENERATE_BBF": { + "type": "BOOL", + "value": "TRUE" + }, + "GENERATE_DFU": { + "type": "BOOL", + "value": "OFF" + }, + "SIGNING_KEY": { + "type": "FILEPATH", + "value": "" + }, + "CMAKE_TOOLCHAIN_FILE": { + "type": "FILEPATH", + "value": "${sourceDir}/cmake/GccArmNoneEabi.cmake" + }, + "CMAKE_BUILD_TYPE": { + "type": "STRING", + "value": "Release" + }, + "PROJECT_VERSION_SUFFIX": { + "type": "STRING", + "value": "" + }, + "PROJECT_VERSION_SUFFIX_SHORT": { + "type": "STRING", + "value": "" + } + } + }, + { + "name": "mini-en-de_release_noboot", + "generator": "Ninja", + "binaryDir": "build-vscode-buddy", + "cacheVariables": { + "CMAKE_MAKE_PROGRAM": { + "type": "FILEPATH", + "value": "${sourceDir}/.dependencies/ninja-1.10.2/ninja" + }, + "CMAKE_EXPORT_COMPILE_COMMANDS": { + "type": "STRING", + "value": "ON" + }, + "PRINTER": { + "type": "STRING", + "value": "MINI" + }, + "BOARD": { + "type": "STRING", + "value": "" + }, + "BOARD_VERSION": { + "type": "STRING", + "value": "" + }, + "PRESET_COMPILE_OPTIONS": { + "type": "STRING", + "value": "" + }, + "DEVELOPMENT_ITEMS_ENABLED": { + "type": "BOOL", + "value": "YES" + }, + "TRANSLATIONS_LIST": { + "type": "STRING", + "value": "de" + }, + "BOOTLOADER": { + "type": "STRING", + "value": "NO" + }, + "GENERATE_BBF": { + "type": "BOOL", + "value": "FALSE" + }, + "GENERATE_DFU": { + "type": "BOOL", + "value": "OFF" + }, + "SIGNING_KEY": { + "type": "FILEPATH", + "value": "" + }, + "CMAKE_TOOLCHAIN_FILE": { + "type": "FILEPATH", + "value": "${sourceDir}/cmake/GccArmNoneEabi.cmake" + }, + "CMAKE_BUILD_TYPE": { + "type": "STRING", + "value": "Release" + }, + "PROJECT_VERSION_SUFFIX": { + "type": "STRING", + "value": "" + }, + "PROJECT_VERSION_SUFFIX_SHORT": { + "type": "STRING", + "value": "" + } + } + }, + { + "name": "mini-en-es_debug_boot", + "generator": "Ninja", + "binaryDir": "build-vscode-buddy", + "cacheVariables": { + "CMAKE_MAKE_PROGRAM": { + "type": "FILEPATH", + "value": "${sourceDir}/.dependencies/ninja-1.10.2/ninja" + }, + "CMAKE_EXPORT_COMPILE_COMMANDS": { + "type": "STRING", + "value": "ON" + }, + "PRINTER": { + "type": "STRING", + "value": "MINI" + }, + "BOARD": { + "type": "STRING", + "value": "" + }, + "BOARD_VERSION": { + "type": "STRING", + "value": "" + }, + "PRESET_COMPILE_OPTIONS": { + "type": "STRING", + "value": "" + }, + "DEVELOPMENT_ITEMS_ENABLED": { + "type": "BOOL", + "value": "YES" + }, + "TRANSLATIONS_LIST": { + "type": "STRING", + "value": "es" + }, + "BOOTLOADER": { + "type": "STRING", + "value": "YES" + }, + "GENERATE_BBF": { + "type": "BOOL", + "value": "TRUE" + }, + "GENERATE_DFU": { + "type": "BOOL", + "value": "OFF" + }, + "SIGNING_KEY": { + "type": "FILEPATH", + "value": "" + }, + "CMAKE_TOOLCHAIN_FILE": { + "type": "FILEPATH", + "value": "${sourceDir}/cmake/GccArmNoneEabi.cmake" + }, + "CMAKE_BUILD_TYPE": { + "type": "STRING", + "value": "Debug" + }, + "PROJECT_VERSION_SUFFIX": { + "type": "STRING", + "value": "" + }, + "PROJECT_VERSION_SUFFIX_SHORT": { + "type": "STRING", + "value": "" + } + } + }, + { + "name": "mini-en-es_debug_noboot", + "generator": "Ninja", + "binaryDir": "build-vscode-buddy", + "cacheVariables": { + "CMAKE_MAKE_PROGRAM": { + "type": "FILEPATH", + "value": "${sourceDir}/.dependencies/ninja-1.10.2/ninja" + }, + "CMAKE_EXPORT_COMPILE_COMMANDS": { + "type": "STRING", + "value": "ON" + }, + "PRINTER": { + "type": "STRING", + "value": "MINI" + }, + "BOARD": { + "type": "STRING", + "value": "" + }, + "BOARD_VERSION": { + "type": "STRING", + "value": "" + }, + "PRESET_COMPILE_OPTIONS": { + "type": "STRING", + "value": "" + }, + "DEVELOPMENT_ITEMS_ENABLED": { + "type": "BOOL", + "value": "YES" + }, + "TRANSLATIONS_LIST": { + "type": "STRING", + "value": "es" + }, + "BOOTLOADER": { + "type": "STRING", + "value": "NO" + }, + "GENERATE_BBF": { + "type": "BOOL", + "value": "FALSE" + }, + "GENERATE_DFU": { + "type": "BOOL", + "value": "OFF" + }, + "SIGNING_KEY": { + "type": "FILEPATH", + "value": "" + }, + "CMAKE_TOOLCHAIN_FILE": { + "type": "FILEPATH", + "value": "${sourceDir}/cmake/GccArmNoneEabi.cmake" + }, + "CMAKE_BUILD_TYPE": { + "type": "STRING", + "value": "Debug" + }, + "PROJECT_VERSION_SUFFIX": { + "type": "STRING", + "value": "" + }, + "PROJECT_VERSION_SUFFIX_SHORT": { + "type": "STRING", + "value": "" + } + } + }, + { + "name": "mini-en-es_release_boot", + "generator": "Ninja", + "binaryDir": "build-vscode-buddy", + "cacheVariables": { + "CMAKE_MAKE_PROGRAM": { + "type": "FILEPATH", + "value": "${sourceDir}/.dependencies/ninja-1.10.2/ninja" + }, + "CMAKE_EXPORT_COMPILE_COMMANDS": { + "type": "STRING", + "value": "ON" + }, + "PRINTER": { + "type": "STRING", + "value": "MINI" + }, + "BOARD": { + "type": "STRING", + "value": "" + }, + "BOARD_VERSION": { + "type": "STRING", + "value": "" + }, + "PRESET_COMPILE_OPTIONS": { + "type": "STRING", + "value": "" + }, + "DEVELOPMENT_ITEMS_ENABLED": { + "type": "BOOL", + "value": "YES" + }, + "TRANSLATIONS_LIST": { + "type": "STRING", + "value": "es" + }, + "BOOTLOADER": { + "type": "STRING", + "value": "YES" + }, + "GENERATE_BBF": { + "type": "BOOL", + "value": "TRUE" + }, + "GENERATE_DFU": { + "type": "BOOL", + "value": "OFF" + }, + "SIGNING_KEY": { + "type": "FILEPATH", + "value": "" + }, + "CMAKE_TOOLCHAIN_FILE": { + "type": "FILEPATH", + "value": "${sourceDir}/cmake/GccArmNoneEabi.cmake" + }, + "CMAKE_BUILD_TYPE": { + "type": "STRING", + "value": "Release" + }, + "PROJECT_VERSION_SUFFIX": { + "type": "STRING", + "value": "" + }, + "PROJECT_VERSION_SUFFIX_SHORT": { + "type": "STRING", + "value": "" + } + } + }, + { + "name": "mini-en-es_release_noboot", + "generator": "Ninja", + "binaryDir": "build-vscode-buddy", + "cacheVariables": { + "CMAKE_MAKE_PROGRAM": { + "type": "FILEPATH", + "value": "${sourceDir}/.dependencies/ninja-1.10.2/ninja" + }, + "CMAKE_EXPORT_COMPILE_COMMANDS": { + "type": "STRING", + "value": "ON" + }, + "PRINTER": { + "type": "STRING", + "value": "MINI" + }, + "BOARD": { + "type": "STRING", + "value": "" + }, + "BOARD_VERSION": { + "type": "STRING", + "value": "" + }, + "PRESET_COMPILE_OPTIONS": { + "type": "STRING", + "value": "" + }, + "DEVELOPMENT_ITEMS_ENABLED": { + "type": "BOOL", + "value": "YES" + }, + "TRANSLATIONS_LIST": { + "type": "STRING", + "value": "es" + }, + "BOOTLOADER": { + "type": "STRING", + "value": "NO" + }, + "GENERATE_BBF": { + "type": "BOOL", + "value": "FALSE" + }, + "GENERATE_DFU": { + "type": "BOOL", + "value": "OFF" + }, + "SIGNING_KEY": { + "type": "FILEPATH", + "value": "" + }, + "CMAKE_TOOLCHAIN_FILE": { + "type": "FILEPATH", + "value": "${sourceDir}/cmake/GccArmNoneEabi.cmake" + }, + "CMAKE_BUILD_TYPE": { + "type": "STRING", + "value": "Release" + }, + "PROJECT_VERSION_SUFFIX": { + "type": "STRING", + "value": "" + }, + "PROJECT_VERSION_SUFFIX_SHORT": { + "type": "STRING", + "value": "" + } + } + }, + { + "name": "mini-en-fr_debug_boot", + "generator": "Ninja", + "binaryDir": "build-vscode-buddy", + "cacheVariables": { + "CMAKE_MAKE_PROGRAM": { + "type": "FILEPATH", + "value": "${sourceDir}/.dependencies/ninja-1.10.2/ninja" + }, + "CMAKE_EXPORT_COMPILE_COMMANDS": { + "type": "STRING", + "value": "ON" + }, + "PRINTER": { + "type": "STRING", + "value": "MINI" + }, + "BOARD": { + "type": "STRING", + "value": "" + }, + "BOARD_VERSION": { + "type": "STRING", + "value": "" + }, + "PRESET_COMPILE_OPTIONS": { + "type": "STRING", + "value": "" + }, + "DEVELOPMENT_ITEMS_ENABLED": { + "type": "BOOL", + "value": "YES" + }, + "TRANSLATIONS_LIST": { + "type": "STRING", + "value": "fr" + }, + "BOOTLOADER": { + "type": "STRING", + "value": "YES" + }, + "GENERATE_BBF": { + "type": "BOOL", + "value": "TRUE" + }, + "GENERATE_DFU": { + "type": "BOOL", + "value": "OFF" + }, + "SIGNING_KEY": { + "type": "FILEPATH", + "value": "" + }, + "CMAKE_TOOLCHAIN_FILE": { + "type": "FILEPATH", + "value": "${sourceDir}/cmake/GccArmNoneEabi.cmake" + }, + "CMAKE_BUILD_TYPE": { + "type": "STRING", + "value": "Debug" + }, + "PROJECT_VERSION_SUFFIX": { + "type": "STRING", + "value": "" + }, + "PROJECT_VERSION_SUFFIX_SHORT": { + "type": "STRING", + "value": "" + } + } + }, + { + "name": "mini-en-fr_debug_noboot", + "generator": "Ninja", + "binaryDir": "build-vscode-buddy", + "cacheVariables": { + "CMAKE_MAKE_PROGRAM": { + "type": "FILEPATH", + "value": "${sourceDir}/.dependencies/ninja-1.10.2/ninja" + }, + "CMAKE_EXPORT_COMPILE_COMMANDS": { + "type": "STRING", + "value": "ON" + }, + "PRINTER": { + "type": "STRING", + "value": "MINI" + }, + "BOARD": { + "type": "STRING", + "value": "" + }, + "BOARD_VERSION": { + "type": "STRING", + "value": "" + }, + "PRESET_COMPILE_OPTIONS": { + "type": "STRING", + "value": "" + }, + "DEVELOPMENT_ITEMS_ENABLED": { + "type": "BOOL", + "value": "YES" + }, + "TRANSLATIONS_LIST": { + "type": "STRING", + "value": "fr" + }, + "BOOTLOADER": { + "type": "STRING", + "value": "NO" + }, + "GENERATE_BBF": { + "type": "BOOL", + "value": "FALSE" + }, + "GENERATE_DFU": { + "type": "BOOL", + "value": "OFF" + }, + "SIGNING_KEY": { + "type": "FILEPATH", + "value": "" + }, + "CMAKE_TOOLCHAIN_FILE": { + "type": "FILEPATH", + "value": "${sourceDir}/cmake/GccArmNoneEabi.cmake" + }, + "CMAKE_BUILD_TYPE": { + "type": "STRING", + "value": "Debug" + }, + "PROJECT_VERSION_SUFFIX": { + "type": "STRING", + "value": "" + }, + "PROJECT_VERSION_SUFFIX_SHORT": { + "type": "STRING", + "value": "" + } + } + }, + { + "name": "mini-en-fr_release_boot", + "generator": "Ninja", + "binaryDir": "build-vscode-buddy", + "cacheVariables": { + "CMAKE_MAKE_PROGRAM": { + "type": "FILEPATH", + "value": "${sourceDir}/.dependencies/ninja-1.10.2/ninja" + }, + "CMAKE_EXPORT_COMPILE_COMMANDS": { + "type": "STRING", + "value": "ON" + }, + "PRINTER": { + "type": "STRING", + "value": "MINI" + }, + "BOARD": { + "type": "STRING", + "value": "" + }, + "BOARD_VERSION": { + "type": "STRING", + "value": "" + }, + "PRESET_COMPILE_OPTIONS": { + "type": "STRING", + "value": "" + }, + "DEVELOPMENT_ITEMS_ENABLED": { + "type": "BOOL", + "value": "YES" + }, + "TRANSLATIONS_LIST": { + "type": "STRING", + "value": "fr" + }, + "BOOTLOADER": { + "type": "STRING", + "value": "YES" + }, + "GENERATE_BBF": { + "type": "BOOL", + "value": "TRUE" + }, + "GENERATE_DFU": { + "type": "BOOL", + "value": "OFF" + }, + "SIGNING_KEY": { + "type": "FILEPATH", + "value": "" + }, + "CMAKE_TOOLCHAIN_FILE": { + "type": "FILEPATH", + "value": "${sourceDir}/cmake/GccArmNoneEabi.cmake" + }, + "CMAKE_BUILD_TYPE": { + "type": "STRING", + "value": "Release" + }, + "PROJECT_VERSION_SUFFIX": { + "type": "STRING", + "value": "" + }, + "PROJECT_VERSION_SUFFIX_SHORT": { + "type": "STRING", + "value": "" + } + } + }, + { + "name": "mini-en-fr_release_noboot", + "generator": "Ninja", + "binaryDir": "build-vscode-buddy", + "cacheVariables": { + "CMAKE_MAKE_PROGRAM": { + "type": "FILEPATH", + "value": "${sourceDir}/.dependencies/ninja-1.10.2/ninja" + }, + "CMAKE_EXPORT_COMPILE_COMMANDS": { + "type": "STRING", + "value": "ON" + }, + "PRINTER": { + "type": "STRING", + "value": "MINI" + }, + "BOARD": { + "type": "STRING", + "value": "" + }, + "BOARD_VERSION": { + "type": "STRING", + "value": "" + }, + "PRESET_COMPILE_OPTIONS": { + "type": "STRING", + "value": "" + }, + "DEVELOPMENT_ITEMS_ENABLED": { + "type": "BOOL", + "value": "YES" + }, + "TRANSLATIONS_LIST": { + "type": "STRING", + "value": "fr" + }, + "BOOTLOADER": { + "type": "STRING", + "value": "NO" + }, + "GENERATE_BBF": { + "type": "BOOL", + "value": "FALSE" + }, + "GENERATE_DFU": { + "type": "BOOL", + "value": "OFF" + }, + "SIGNING_KEY": { + "type": "FILEPATH", + "value": "" + }, + "CMAKE_TOOLCHAIN_FILE": { + "type": "FILEPATH", + "value": "${sourceDir}/cmake/GccArmNoneEabi.cmake" + }, + "CMAKE_BUILD_TYPE": { + "type": "STRING", + "value": "Release" + }, + "PROJECT_VERSION_SUFFIX": { + "type": "STRING", + "value": "" + }, + "PROJECT_VERSION_SUFFIX_SHORT": { + "type": "STRING", + "value": "" + } + } + }, + { + "name": "mini-en-it_debug_boot", + "generator": "Ninja", + "binaryDir": "build-vscode-buddy", + "cacheVariables": { + "CMAKE_MAKE_PROGRAM": { + "type": "FILEPATH", + "value": "${sourceDir}/.dependencies/ninja-1.10.2/ninja" + }, + "CMAKE_EXPORT_COMPILE_COMMANDS": { + "type": "STRING", + "value": "ON" + }, + "PRINTER": { + "type": "STRING", + "value": "MINI" + }, + "BOARD": { + "type": "STRING", + "value": "" + }, + "BOARD_VERSION": { + "type": "STRING", + "value": "" + }, + "PRESET_COMPILE_OPTIONS": { + "type": "STRING", + "value": "" + }, + "DEVELOPMENT_ITEMS_ENABLED": { + "type": "BOOL", + "value": "YES" + }, + "TRANSLATIONS_LIST": { + "type": "STRING", + "value": "it" + }, + "BOOTLOADER": { + "type": "STRING", + "value": "YES" + }, + "GENERATE_BBF": { + "type": "BOOL", + "value": "TRUE" + }, + "GENERATE_DFU": { + "type": "BOOL", + "value": "OFF" + }, + "SIGNING_KEY": { + "type": "FILEPATH", + "value": "" + }, + "CMAKE_TOOLCHAIN_FILE": { + "type": "FILEPATH", + "value": "${sourceDir}/cmake/GccArmNoneEabi.cmake" + }, + "CMAKE_BUILD_TYPE": { + "type": "STRING", + "value": "Debug" + }, + "PROJECT_VERSION_SUFFIX": { + "type": "STRING", + "value": "" + }, + "PROJECT_VERSION_SUFFIX_SHORT": { + "type": "STRING", + "value": "" + } + } + }, + { + "name": "mini-en-it_debug_noboot", + "generator": "Ninja", + "binaryDir": "build-vscode-buddy", + "cacheVariables": { + "CMAKE_MAKE_PROGRAM": { + "type": "FILEPATH", + "value": "${sourceDir}/.dependencies/ninja-1.10.2/ninja" + }, + "CMAKE_EXPORT_COMPILE_COMMANDS": { + "type": "STRING", + "value": "ON" + }, + "PRINTER": { + "type": "STRING", + "value": "MINI" + }, + "BOARD": { + "type": "STRING", + "value": "" + }, + "BOARD_VERSION": { + "type": "STRING", + "value": "" + }, + "PRESET_COMPILE_OPTIONS": { + "type": "STRING", + "value": "" + }, + "DEVELOPMENT_ITEMS_ENABLED": { + "type": "BOOL", + "value": "YES" + }, + "TRANSLATIONS_LIST": { + "type": "STRING", + "value": "it" + }, + "BOOTLOADER": { + "type": "STRING", + "value": "NO" + }, + "GENERATE_BBF": { + "type": "BOOL", + "value": "FALSE" + }, + "GENERATE_DFU": { + "type": "BOOL", + "value": "OFF" + }, + "SIGNING_KEY": { + "type": "FILEPATH", + "value": "" + }, + "CMAKE_TOOLCHAIN_FILE": { + "type": "FILEPATH", + "value": "${sourceDir}/cmake/GccArmNoneEabi.cmake" + }, + "CMAKE_BUILD_TYPE": { + "type": "STRING", + "value": "Debug" + }, + "PROJECT_VERSION_SUFFIX": { + "type": "STRING", + "value": "" + }, + "PROJECT_VERSION_SUFFIX_SHORT": { + "type": "STRING", + "value": "" + } + } + }, + { + "name": "mini-en-it_release_boot", + "generator": "Ninja", + "binaryDir": "build-vscode-buddy", + "cacheVariables": { + "CMAKE_MAKE_PROGRAM": { + "type": "FILEPATH", + "value": "${sourceDir}/.dependencies/ninja-1.10.2/ninja" + }, + "CMAKE_EXPORT_COMPILE_COMMANDS": { + "type": "STRING", + "value": "ON" + }, + "PRINTER": { + "type": "STRING", + "value": "MINI" + }, + "BOARD": { + "type": "STRING", + "value": "" + }, + "BOARD_VERSION": { + "type": "STRING", + "value": "" + }, + "PRESET_COMPILE_OPTIONS": { + "type": "STRING", + "value": "" + }, + "DEVELOPMENT_ITEMS_ENABLED": { + "type": "BOOL", + "value": "YES" + }, + "TRANSLATIONS_LIST": { + "type": "STRING", + "value": "it" + }, + "BOOTLOADER": { + "type": "STRING", + "value": "YES" + }, + "GENERATE_BBF": { + "type": "BOOL", + "value": "TRUE" + }, + "GENERATE_DFU": { + "type": "BOOL", + "value": "OFF" + }, + "SIGNING_KEY": { + "type": "FILEPATH", + "value": "" + }, + "CMAKE_TOOLCHAIN_FILE": { + "type": "FILEPATH", + "value": "${sourceDir}/cmake/GccArmNoneEabi.cmake" + }, + "CMAKE_BUILD_TYPE": { + "type": "STRING", + "value": "Release" + }, + "PROJECT_VERSION_SUFFIX": { + "type": "STRING", + "value": "" + }, + "PROJECT_VERSION_SUFFIX_SHORT": { + "type": "STRING", + "value": "" + } + } + }, + { + "name": "mini-en-it_release_noboot", + "generator": "Ninja", + "binaryDir": "build-vscode-buddy", + "cacheVariables": { + "CMAKE_MAKE_PROGRAM": { + "type": "FILEPATH", + "value": "${sourceDir}/.dependencies/ninja-1.10.2/ninja" + }, + "CMAKE_EXPORT_COMPILE_COMMANDS": { + "type": "STRING", + "value": "ON" + }, + "PRINTER": { + "type": "STRING", + "value": "MINI" + }, + "BOARD": { + "type": "STRING", + "value": "" + }, + "BOARD_VERSION": { + "type": "STRING", + "value": "" + }, + "PRESET_COMPILE_OPTIONS": { + "type": "STRING", + "value": "" + }, + "DEVELOPMENT_ITEMS_ENABLED": { + "type": "BOOL", + "value": "YES" + }, + "TRANSLATIONS_LIST": { + "type": "STRING", + "value": "it" + }, + "BOOTLOADER": { + "type": "STRING", + "value": "NO" + }, + "GENERATE_BBF": { + "type": "BOOL", + "value": "FALSE" + }, + "GENERATE_DFU": { + "type": "BOOL", + "value": "OFF" + }, + "SIGNING_KEY": { + "type": "FILEPATH", + "value": "" + }, + "CMAKE_TOOLCHAIN_FILE": { + "type": "FILEPATH", + "value": "${sourceDir}/cmake/GccArmNoneEabi.cmake" + }, + "CMAKE_BUILD_TYPE": { + "type": "STRING", + "value": "Release" + }, + "PROJECT_VERSION_SUFFIX": { + "type": "STRING", + "value": "" + }, + "PROJECT_VERSION_SUFFIX_SHORT": { + "type": "STRING", + "value": "" + } + } + }, + { + "name": "mini-en-pl_debug_boot", + "generator": "Ninja", + "binaryDir": "build-vscode-buddy", + "cacheVariables": { + "CMAKE_MAKE_PROGRAM": { + "type": "FILEPATH", + "value": "${sourceDir}/.dependencies/ninja-1.10.2/ninja" + }, + "CMAKE_EXPORT_COMPILE_COMMANDS": { + "type": "STRING", + "value": "ON" + }, + "PRINTER": { + "type": "STRING", + "value": "MINI" + }, + "BOARD": { + "type": "STRING", + "value": "" + }, + "BOARD_VERSION": { + "type": "STRING", + "value": "" + }, + "PRESET_COMPILE_OPTIONS": { + "type": "STRING", + "value": "" + }, + "DEVELOPMENT_ITEMS_ENABLED": { + "type": "BOOL", + "value": "YES" + }, + "TRANSLATIONS_LIST": { + "type": "STRING", + "value": "pl" + }, + "BOOTLOADER": { + "type": "STRING", + "value": "YES" + }, + "GENERATE_BBF": { + "type": "BOOL", + "value": "TRUE" + }, + "GENERATE_DFU": { + "type": "BOOL", + "value": "OFF" + }, + "SIGNING_KEY": { + "type": "FILEPATH", + "value": "" + }, + "CMAKE_TOOLCHAIN_FILE": { + "type": "FILEPATH", + "value": "${sourceDir}/cmake/GccArmNoneEabi.cmake" + }, + "CMAKE_BUILD_TYPE": { + "type": "STRING", + "value": "Debug" + }, + "PROJECT_VERSION_SUFFIX": { + "type": "STRING", + "value": "" + }, + "PROJECT_VERSION_SUFFIX_SHORT": { + "type": "STRING", + "value": "" + } + } + }, + { + "name": "mini-en-pl_debug_noboot", + "generator": "Ninja", + "binaryDir": "build-vscode-buddy", + "cacheVariables": { + "CMAKE_MAKE_PROGRAM": { + "type": "FILEPATH", + "value": "${sourceDir}/.dependencies/ninja-1.10.2/ninja" + }, + "CMAKE_EXPORT_COMPILE_COMMANDS": { + "type": "STRING", + "value": "ON" + }, + "PRINTER": { + "type": "STRING", + "value": "MINI" + }, + "BOARD": { + "type": "STRING", + "value": "" + }, + "BOARD_VERSION": { + "type": "STRING", + "value": "" + }, + "PRESET_COMPILE_OPTIONS": { + "type": "STRING", + "value": "" + }, + "DEVELOPMENT_ITEMS_ENABLED": { + "type": "BOOL", + "value": "YES" + }, + "TRANSLATIONS_LIST": { + "type": "STRING", + "value": "pl" + }, + "BOOTLOADER": { + "type": "STRING", + "value": "NO" + }, + "GENERATE_BBF": { + "type": "BOOL", + "value": "FALSE" + }, + "GENERATE_DFU": { + "type": "BOOL", + "value": "OFF" + }, + "SIGNING_KEY": { + "type": "FILEPATH", + "value": "" + }, + "CMAKE_TOOLCHAIN_FILE": { + "type": "FILEPATH", + "value": "${sourceDir}/cmake/GccArmNoneEabi.cmake" + }, + "CMAKE_BUILD_TYPE": { + "type": "STRING", + "value": "Debug" + }, + "PROJECT_VERSION_SUFFIX": { + "type": "STRING", + "value": "" + }, + "PROJECT_VERSION_SUFFIX_SHORT": { + "type": "STRING", + "value": "" + } + } + }, + { + "name": "mini-en-pl_release_boot", + "generator": "Ninja", + "binaryDir": "build-vscode-buddy", + "cacheVariables": { + "CMAKE_MAKE_PROGRAM": { + "type": "FILEPATH", + "value": "${sourceDir}/.dependencies/ninja-1.10.2/ninja" + }, + "CMAKE_EXPORT_COMPILE_COMMANDS": { + "type": "STRING", + "value": "ON" + }, + "PRINTER": { + "type": "STRING", + "value": "MINI" + }, + "BOARD": { + "type": "STRING", + "value": "" + }, + "BOARD_VERSION": { + "type": "STRING", + "value": "" + }, + "PRESET_COMPILE_OPTIONS": { + "type": "STRING", + "value": "" + }, + "DEVELOPMENT_ITEMS_ENABLED": { + "type": "BOOL", + "value": "YES" + }, + "TRANSLATIONS_LIST": { + "type": "STRING", + "value": "pl" + }, + "BOOTLOADER": { + "type": "STRING", + "value": "YES" + }, + "GENERATE_BBF": { + "type": "BOOL", + "value": "TRUE" + }, + "GENERATE_DFU": { + "type": "BOOL", + "value": "OFF" + }, + "SIGNING_KEY": { + "type": "FILEPATH", + "value": "" + }, + "CMAKE_TOOLCHAIN_FILE": { + "type": "FILEPATH", + "value": "${sourceDir}/cmake/GccArmNoneEabi.cmake" + }, + "CMAKE_BUILD_TYPE": { + "type": "STRING", + "value": "Release" + }, + "PROJECT_VERSION_SUFFIX": { + "type": "STRING", + "value": "" + }, + "PROJECT_VERSION_SUFFIX_SHORT": { + "type": "STRING", + "value": "" + } + } + }, + { + "name": "mini-en-pl_release_noboot", + "generator": "Ninja", + "binaryDir": "build-vscode-buddy", + "cacheVariables": { + "CMAKE_MAKE_PROGRAM": { + "type": "FILEPATH", + "value": "${sourceDir}/.dependencies/ninja-1.10.2/ninja" + }, + "CMAKE_EXPORT_COMPILE_COMMANDS": { + "type": "STRING", + "value": "ON" + }, + "PRINTER": { + "type": "STRING", + "value": "MINI" + }, + "BOARD": { + "type": "STRING", + "value": "" + }, + "BOARD_VERSION": { + "type": "STRING", + "value": "" + }, + "PRESET_COMPILE_OPTIONS": { + "type": "STRING", + "value": "" + }, + "DEVELOPMENT_ITEMS_ENABLED": { + "type": "BOOL", + "value": "YES" + }, + "TRANSLATIONS_LIST": { + "type": "STRING", + "value": "pl" + }, + "BOOTLOADER": { + "type": "STRING", + "value": "NO" + }, + "GENERATE_BBF": { + "type": "BOOL", + "value": "FALSE" + }, + "GENERATE_DFU": { + "type": "BOOL", + "value": "OFF" + }, + "SIGNING_KEY": { + "type": "FILEPATH", + "value": "" + }, + "CMAKE_TOOLCHAIN_FILE": { + "type": "FILEPATH", + "value": "${sourceDir}/cmake/GccArmNoneEabi.cmake" + }, + "CMAKE_BUILD_TYPE": { + "type": "STRING", + "value": "Release" + }, + "PROJECT_VERSION_SUFFIX": { + "type": "STRING", + "value": "" + }, + "PROJECT_VERSION_SUFFIX_SHORT": { + "type": "STRING", + "value": "" + } + } + }, { "name": "mk4_debug_boot", "generator": "Ninja", diff --git a/ProjectOptions.cmake b/ProjectOptions.cmake index 8f3cfc7ab0..1d0c02c917 100644 --- a/ProjectOptions.cmake +++ b/ProjectOptions.cmake @@ -90,6 +90,11 @@ set(TRANSLATIONS_ENABLED "" CACHE STRING "Enable languages (NO == English only)" ) +set(TRANSLATIONS_LIST + "" + CACHE STRING "List of languages to enable" + ) + set(TOUCH_ENABLED "" CACHE STRING "Enable touch (valid values are ${TOUCH_ENABLED_VALID_OPTS})." @@ -263,7 +268,8 @@ set(PRINTERS_WITH_TOOLCHANGER "XL") set(PRINTERS_WITH_SIDE_FSENSOR "XL") set(PRINTERS_WITH_EMBEDDED_ESP32 "XL") set(PRINTERS_WITH_SIDE_LEDS "XL" "iX") -set(PRINTERS_WITH_TRANSLATIONS "MK4" "MK3.5" "XL") +set(PRINTERS_WITH_TRANSLATIONS "MK4" "MK3.5" "XL" "MINI") +set(PRINTERS_WITH_EXTFLASH_TRANSLATIONS "MINI") set(PRINTERS_WITH_LOVE_BOARD "MK4" "iX") set(PRINTERS_WITH_MMU2 "MK4" "MK3.5") @@ -284,12 +290,48 @@ set(BOARDS_WITH_ACCELEROMETER "XBUDDY" "DWARF") if(${TRANSLATIONS_ENABLED} STREQUAL "") if(${PRINTER} IN_LIST PRINTERS_WITH_TRANSLATIONS) set(TRANSLATIONS_ENABLED YES) + if(${PRINTER} IN_LIST PRINTERS_WITH_EXTFLASH_TRANSLATIONS) + set(TRANSLATIONS_IN_EXTFLASH YES) + else() + set(TRANSLATIONS_IN_EXTFLASH NO) + endif() + define_boolean_option(TRANSLATIONS_IN_EXTFLASH ${TRANSLATIONS_IN_EXTFLASH}) else() set(TRANSLATIONS_ENABLED NO) endif() + endif() define_boolean_option(HAS_TRANSLATIONS ${TRANSLATIONS_ENABLED}) +# Set language options +set(LANGUAGES_AVAILABLE CS DE ES FR IT PL) +if("${TRANSLATIONS_LIST}" STREQUAL "") + if(PRINTER STREQUAL "MINI" + OR (CMAKE_BUILD_TYPE STREQUAL "Debug" AND (NOT ${TRANSLATIONS_IN_EXTFLASH})) + ) + # Do not include translations to some build - Mini has explicitly listed translations - Debug + # builds has translations disabled (due to FLASH space reasons), unless translations are in + # extflash than its fine + else() + # include all translations + foreach(LANG ${LANGUAGES_AVAILABLE}) + define_boolean_option("ENABLE_TRANSLATION_${LANG}" yes) + endforeach() + endif() +else() + set(TRANSLATIONS_LIST_FOREACH ${TRANSLATIONS_LIST}) + foreach(LANG ${TRANSLATIONS_LIST_FOREACH}) + string(TOUPPER ${LANG} LANG) + define_boolean_option(ENABLE_TRANSLATION_${LANG} yes) + endforeach() +endif() + +foreach(LANG ${LANGUAGES_AVAILABLE}) + if(NOT DEFINED "ENABLE_TRANSLATION_${LANG}") + define_boolean_option("ENABLE_TRANSLATION_${LANG}" no) + endif() +endforeach() + if(${TOUCH_ENABLED} STREQUAL "") if(${PRINTER} MATCHES "^(iX)$") set(TOUCH_ENABLED NO) diff --git a/README.md b/README.md index aebbc55c43..6198040515 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,12 @@ # Buddy -[![Build Status]()](https://holly.prusa3d.com/job/Prusa-Firmware-Buddy-Private/job/Multibranch/job/private/) -[![Build Status]()](https://holly.prusa3d.com/job/Prusa-Firmware-Buddy-Private/job/Multibranch/job/master/) -[![Build Status]()](https://holly.prusa3d.com/job/Prusa-Firmware-Buddy-Private/job/Auto-Pull-Master/) -[![Build Status]()](https://holly.prusa3d.com/job/Prusa-Firmware-Buddy-Private/job/Merge-Master-To-Private/) +[![GitHub release](https://img.shields.io/github/release/prusa3d/Prusa-Firmware-Buddy.svg)](https://github.com/prusa3d/Prusa-Firmware-Buddy/releases) +[![Build Status](https://holly.prusa3d.com/buildStatus/icon?job=Prusa-Firmware-Buddy%2FMultibranch%2Fmaster)](https://holly.prusa3d.com/job/Prusa-Firmware-Buddy/job/Multibranch/job/master/) This repository includes source code and firmware releases for the Original Prusa 3D printers based on the 32-bit ARM microcontrollers. The currently supported models are: -- Original Prusa MINI +- Original Prusa MINI/MINI+ +- Original Prusa MK3.9 - Original Prusa MK4 - Original Prusa XL @@ -61,15 +60,9 @@ The build process of this project is driven by CMake and `build.py` is just a hi - [Eclipse, STM32CubeIDE](doc/editor/stm32cubeide.md) - [Other LSP-based IDEs (Atom, Sublime Text, ...)](doc/editor/lsp-based-ides.md) -#### Formatting +#### Contributing -All the source code in this repository is automatically formatted: - -- C/C++ files using [clang-format](https://clang.llvm.org/docs/ClangFormat.html), -- Python files using [yapf](https://github.com/google/yapf), -- and CMake files using [cmake-format](https://github.com/cheshirekow/cmake_format). - -If you want to contribute, make sure to install [pre-commit](https://pre-commit.com) and then run `pre-commit install` within the repository. This makes sure that all your future commits will be formatted appropriately. Our build server automatically rejects improperly formatted pull requests. +If you want to contribute to the codebase, please read the [Contribution Guidelines](doc/contributing.md). #### XL and Puppies diff --git a/cmake/CheckRemotes.cmake b/cmake/CheckRemotes.cmake deleted file mode 100644 index 8a6b396787..0000000000 --- a/cmake/CheckRemotes.cmake +++ /dev/null @@ -1,47 +0,0 @@ -find_package(Git QUIET) - -if(NOT GIT_FOUND) - message(STATUS "Not Git Executable found. Skipping check for dangerous Git remotes.") - return() -endif() - -function(check_git_repo_for_dangerous_remotes repo_dir) - execute_process( - COMMAND "${GIT_EXECUTABLE}" remote - WORKING_DIRECTORY "${repo_dir}" - RESULT_VARIABLE res - OUTPUT_VARIABLE lst - ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE - ) - - if(NOT res STREQUAL "0") - message(WARNING "Failed to check dangerousness of your Git remotes!") - return() - endif() - - string(REPLACE "\n" ";" lst ${lst}) - foreach(item ${lst}) - execute_process( - COMMAND "${GIT_EXECUTABLE}" remote get-url --push ${item} - WORKING_DIRECTORY "${repo_dir}" - RESULT_VARIABLE res - OUTPUT_VARIABLE url - ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE - ) - - if(NOT res STREQUAL 0) - message(WARNING "Failed to check dangerousness of remote '${item}'!") - endif() - - if(url MATCHES "Prusa\-Firmware\-Buddy.git" OR url MATCHES "Marlin.git") - message( - FATAL_ERROR - "Oh, your remote '${item}' appears to have its push URL set to a public repository! Let me say, that this is a bad, bad idea! You are \"one push\" away from mistakenly publishing private things. Please remove this remote or set its push url to some nonsense (see below).\n git -C \"${repo_dir}\" remote set-url --push ${item} DISABLED\n" - ) - endif() - - endforeach() -endfunction() - -check_git_repo_for_dangerous_remotes("${CMAKE_SOURCE_DIR}") -check_git_repo_for_dangerous_remotes("${CMAKE_SOURCE_DIR}/lib/Marlin") diff --git a/doc/contributing.md b/doc/contributing.md new file mode 100644 index 0000000000..56850ee770 --- /dev/null +++ b/doc/contributing.md @@ -0,0 +1,64 @@ +# Contribution Guidelines + +## Git + +### Merging: Use rebase whenever possible + +The goal is to have a simple and linear git history. +It is not always possible; for example when merging master into private. +In such cases, it is ok to use git-merge. + +### Commit: Atomicity + +A commit should be a single complete unit of work. +Every commit should be buildable and follow the rules in this document. + +### Commit: Message + +- Commit message comprises a subject and a body (separated by an empty line). +- Commit message is written in English. +- Subject uses the imperative mood. +- Subject starts with a capital letter and does not end with a period. +- When a commit is relevant to some subset/module of the project (most of the time), use it as a prefix of the subject as follows: + ``` + metrics: Add support for syslog + ``` + or + ``` + gui: Add touch support + ``` +- Write the module in lowercase +- Limit the subject to 72 letters. +- Wrap the body to 72 letters per line. +- Put an issue tracker reference (BFW-xxxx) at the end of the body if you have one. Do not put it in the subject line. + +## Formatting & Code Organization + +### Formatting + +All the source code in this repository is automatically formatted: + +- C/C++ files using [clang-format](https://clang.llvm.org/docs/ClangFormat.html), +- Python files using [yapf](https://github.com/google/yapf), +- and CMake files using [cmake-format](https://github.com/cheshirekow/cmake_format). + +If you want to contribute, make sure to install [pre-commit](https://pre-commit.com) and then run `pre-commit install` within the repository. This makes sure that all your future commits will be formatted appropriately. Our build server automatically rejects improperly formatted pull requests. + +### Files: Include Guards +Use the `#pragma once` as a file guard. +Do not use the `#ifdef FILE_X`, `#define FILE_X`, `#endif` pattern. + +### Files: Author & Copyright + +Do not add file headers with author/creation time/copyright, etc. +Those data are already stored in the commit, and we don't want to duplicate them. + +This does not apply to 3rd party code in our repository. + +### Code Style: C/C++ Naming Conventions + +- Types & Classes are in `PascalCase`. +- Global constants in `SCREAMING_CASE` +- Variables (local, class, etc), class-level constants, `enum class` items, methods and namespaces are in `snake_case`. +- File names are in `snake_case.cpp` (even if the only thing the file contains is a class named in `PascalCase`). +- Types never end with a `'_t'`. diff --git a/doc/prusa_printer_settings.ini b/doc/prusa_printer_settings.ini index 6717ec16d1..538ca1c4b9 100644 --- a/doc/prusa_printer_settings.ini +++ b/doc/prusa_printer_settings.ini @@ -51,4 +51,4 @@ psk=SuperSecretWifiPassword hostname = buddy-a.connect.prusa3d.com token = 1234567890 port = 443 -tls = yes +tls = true diff --git a/include/marlin/Configuration_MINI.h b/include/marlin/Configuration_MINI.h index 1a2f9fb184..72c8bb729b 100644 --- a/include/marlin/Configuration_MINI.h +++ b/include/marlin/Configuration_MINI.h @@ -397,7 +397,7 @@ // Above this temperature the heater will be switched off. // This can protect components from overheating, but NOT from shorts and failures. // (Use MINTEMP for thermistor short/failure protection.) -#define HEATER_0_MAXTEMP 290 +#define HEATER_0_MAXTEMP 295 #define HEATER_1_MAXTEMP 275 #define HEATER_2_MAXTEMP 275 #define HEATER_3_MAXTEMP 275 @@ -565,7 +565,7 @@ //! implemented only for Cartesian kinematics #define MOVE_BACK_BEFORE_HOMING #if ENABLED(MOVE_BACK_BEFORE_HOMING) - #define MOVE_BACK_BEFORE_HOMING_DISTANCE 10.0f + #define MOVE_BACK_BEFORE_HOMING_DISTANCE 1.92f #endif // Specify here all the endstop connectors that are connected to any endstop or probe. diff --git a/include/marlin/Configuration_MINI_adv.h b/include/marlin/Configuration_MINI_adv.h index 138ce40210..ecff740497 100644 --- a/include/marlin/Configuration_MINI_adv.h +++ b/include/marlin/Configuration_MINI_adv.h @@ -482,8 +482,8 @@ #define HOMING_MAX_ATTEMPTS 10 // Homing hits each endstop, retracts by these distances, then does a slower bump. -#define X_HOME_BUMP_MM 10 -#define Y_HOME_BUMP_MM 10 +#define X_HOME_BUMP_MM 0 +#define Y_HOME_BUMP_MM 0 #define Z_HOME_BUMP_MM 2 #define HOMING_BUMP_DIVISOR \ { 1, 1, 4 } // Re-Bump Speed Divisor (Divides the Homing Feedrate) @@ -1745,7 +1745,7 @@ #define POWER_PANIC_MAX_BED_DIFF 10 // Maximum bed temperature (C) difference for auto-recovery // seconds to wait on hold before auto-restarting during short power failures - #define POWER_PANIC_HOLD_RST_S 5 + #define POWER_PANIC_HOLD_RST_MS 5000 // TODO: Suboptimal values #define POWER_PANIC_X_CURRENT 350 // (mA) RMS current for parking diff --git a/include/marlin/Configuration_MK3.5_adv.h b/include/marlin/Configuration_MK3.5_adv.h index 4280c869c1..e29aeffb42 100644 --- a/include/marlin/Configuration_MK3.5_adv.h +++ b/include/marlin/Configuration_MK3.5_adv.h @@ -1753,7 +1753,7 @@ #define POWER_PANIC_MAX_BED_DIFF 10 // Maximum bed temperature (C) difference for auto-recovery // seconds to wait on hold before auto-restarting during short power failures - #define POWER_PANIC_HOLD_RST_S 5 + #define POWER_PANIC_HOLD_RST_MS 5000 #define POWER_PANIC_X_CURRENT 350 // (mA) RMS current for parking #define POWER_PANIC_X_FEEDRATE 200 // (mm/s, running at POWER_PANIC_X_CURRENT) diff --git a/include/marlin/Configuration_MK4_adv.h b/include/marlin/Configuration_MK4_adv.h index 7183add87b..db42729c97 100644 --- a/include/marlin/Configuration_MK4_adv.h +++ b/include/marlin/Configuration_MK4_adv.h @@ -1765,7 +1765,7 @@ #define POWER_PANIC_MAX_BED_DIFF 10 // Maximum bed temperature (C) difference for auto-recovery // seconds to wait on hold before auto-restarting during short power failures - #define POWER_PANIC_HOLD_RST_S 5 + #define POWER_PANIC_HOLD_RST_MS 5000 // TODO: currently arbitrary, needs to include optimal feedrates too #define POWER_PANIC_X_CURRENT 350 // (mA) RMS current for parking diff --git a/include/marlin/Configuration_XL_adv.h b/include/marlin/Configuration_XL_adv.h index 4f0671a2b1..bb434d8766 100644 --- a/include/marlin/Configuration_XL_adv.h +++ b/include/marlin/Configuration_XL_adv.h @@ -1751,8 +1751,8 @@ #define POWER_PANIC_Z_LIFT_CYCLES 4 // 4xFullStep cycles = ~0.64mm #define POWER_PANIC_MAX_BED_DIFF 10 // Maximum bed temperature (C) difference for auto-recovery - // seconds to wait on hold before auto-restarting during short power failures - #define POWER_PANIC_HOLD_RST_S 5 + // milliseconds to wait on hold before auto-restarting during short power failures + #define POWER_PANIC_HOLD_RST_MS 5000 // TODO: Suboptimal values #define POWER_PANIC_X_CURRENT 350 // (mA) RMS current for parking diff --git a/lib/Arduino_Core_Buddy/cores/arduino/SPI.cpp b/lib/Arduino_Core_Buddy/cores/arduino/SPI.cpp index b8cecd5ee2..304c3e1682 100644 --- a/lib/Arduino_Core_Buddy/cores/arduino/SPI.cpp +++ b/lib/Arduino_Core_Buddy/cores/arduino/SPI.cpp @@ -19,8 +19,9 @@ typedef enum { spi_status_e _spi_transfer(uint8_t *tx_buffer, uint8_t *rx_buffer, uint16_t len, uint32_t Timeout) { if (HAL_SPI_Initialized) { HAL_StatusTypeDef ret = HAL_SPI_TransmitReceive(&SPI_HANDLE_FOR(tmc), tx_buffer, rx_buffer, len, Timeout); - if (ret == HAL_TIMEOUT) + if (ret == HAL_TIMEOUT) { return SPI_TIMEOUT; + } return SPI_OK; } return SPI_ERROR; @@ -77,16 +78,18 @@ uint16_t SPIClass::transfer16(uint16_t _data, SPITransferMode _mode) { } uint8_t SPIClass::dmaTransfer(uint8_t *transmitBuf, uint8_t *receiveBuf, uint16_t length) { - if (!HAL_SPI_Initialized) + if (!HAL_SPI_Initialized) { return SPI_NOT_INITIALIZED; + } auto status = HAL_SPI_TransmitReceive(&SPI_HANDLE_FOR(tmc), transmitBuf, receiveBuf, length, SPI_TRANSFER_TIMEOUT); return hal_status_to_retval(status); } uint8_t SPIClass::dmaSend(uint8_t *buf, uint16_t length) { - if (!HAL_SPI_Initialized) + if (!HAL_SPI_Initialized) { return SPI_NOT_INITIALIZED; + } auto status = HAL_SPI_Transmit(&SPI_HANDLE_FOR(tmc), buf, length, SPI_TRANSFER_TIMEOUT); return hal_status_to_retval(status); diff --git a/lib/Arduino_Core_Buddy/cores/arduino/USBSerial.cpp b/lib/Arduino_Core_Buddy/cores/arduino/USBSerial.cpp index 6a0fa82dbc..2e2e745d38 100644 --- a/lib/Arduino_Core_Buddy/cores/arduino/USBSerial.cpp +++ b/lib/Arduino_Core_Buddy/cores/arduino/USBSerial.cpp @@ -17,36 +17,41 @@ void USBSerial::setIsWriteOnly(bool writeOnly) { } int USBSerial::available(void) { - if (!enabled || isWriteOnly) + if (!enabled || isWriteOnly) { return 0; + } return tud_cdc_available(); } int USBSerial::peek(void) { - if (!enabled || isWriteOnly) + if (!enabled || isWriteOnly) { return 0; + } return tud_cdc_peek(0); } int USBSerial::read(void) { - if (!enabled || isWriteOnly) + if (!enabled || isWriteOnly) { return 0; + } return tud_cdc_read_char(); } size_t USBSerial::readBytes(char *buffer, size_t length) { - if (!enabled || isWriteOnly) + if (!enabled || isWriteOnly) { return 0; + } return tud_cdc_read(buffer, length); } void USBSerial::flush(void) { - if (enabled) + if (enabled) { tud_cdc_write_flush(); + } if (!lineBufferHook || !lineBufferUsed) { return; @@ -66,6 +71,11 @@ void USBSerial::LineBufferAppend(char character) { } size_t USBSerial::write(uint8_t ch) { + // its not possible to write to USB-CDC from ISR, so skip the write alltogether + if (xPortIsInsideInterrupt()) { + return 0; + } + if (enabled) { while (tud_cdc_write_char(ch) != 1) { // TX is full, yield to lower-priority (which usb is part of) threads until ready @@ -74,8 +84,9 @@ size_t USBSerial::write(uint8_t ch) { } LineBufferAppend(ch); - if (ch == '\n') + if (ch == '\n') { flush(); + } return 1; } @@ -83,8 +94,9 @@ size_t USBSerial::write(uint8_t ch) { static void cdc_write_sync(const uint8_t *buffer, size_t size) { for (;;) { size_t done = tud_cdc_write(buffer, size); - if (done == size) + if (done == size) { break; + } // TX was full, yield to lower-priority (which usb is part of) threads until ready buffer += done; @@ -94,6 +106,11 @@ static void cdc_write_sync(const uint8_t *buffer, size_t size) { } size_t USBSerial::write(const uint8_t *buffer, size_t size) { + // its not possible to write to USB-CDC from ISR, so skip the write alltogether + if (xPortIsInsideInterrupt()) { + return 0; + } + size_t beg = 0; size_t end = 0; diff --git a/lib/Arduino_Core_Buddy/cores/arduino/wiring_time.c b/lib/Arduino_Core_Buddy/cores/arduino/wiring_time.c index fb370cfb7f..47f9b00982 100644 --- a/lib/Arduino_Core_Buddy/cores/arduino/wiring_time.c +++ b/lib/Arduino_Core_Buddy/cores/arduino/wiring_time.c @@ -17,10 +17,11 @@ static inline int is_interrupt(void) { } void delay(uint32_t ms) { - if (!is_interrupt()) + if (!is_interrupt()) { osDelay(ms); - else + } else { abort(); // TODO: add support for delay from IRQ + } } void delayMicroseconds(uint32_t usec) { diff --git a/lib/Marlin/Marlin/src/feature/input_shaper/input_shaper.cpp b/lib/Marlin/Marlin/src/feature/input_shaper/input_shaper.cpp index efd8def29d..a09a823435 100644 --- a/lib/Marlin/Marlin/src/feature/input_shaper/input_shaper.cpp +++ b/lib/Marlin/Marlin/src/feature/input_shaper/input_shaper.cpp @@ -29,8 +29,9 @@ input_shaper_pulses_t InputShaper::logical_axis_pulses[3]; static void init_input_shaper_pulses(const float a[], const float t[], const int num_pulses, input_shaper_pulses_t *is_pulses) { double sum_a = 0.; - for (int i = 0; i < num_pulses; ++i) + for (int i = 0; i < num_pulses; ++i) { sum_a += a[i]; + } // Reverse pulses vs their traditional definition const double inv_sum_a = 1. / sum_a; @@ -40,21 +41,24 @@ static void init_input_shaper_pulses(const float a[], const float t[], const int } double time_shift = 0.; - for (int i = 0; i < num_pulses; ++i) + for (int i = 0; i < num_pulses; ++i) { time_shift += is_pulses->pulses[i].a * is_pulses->pulses[i].t; + } // Shift pulses around mid-point. - for (int i = 0; i < num_pulses; ++i) + for (int i = 0; i < num_pulses; ++i) { is_pulses->pulses[i].t -= time_shift; + } is_pulses->num_pulses = num_pulses; } input_shaper::Shaper input_shaper::get(const float damping_ratio, const float shaper_freq, const float vibration_reduction, const input_shaper::Type type) { - if (shaper_freq <= 0.f) + if (shaper_freq <= 0.f) { bsod("Zero or negative frequency of input shaper."); - else if (damping_ratio >= 1.f) + } else if (damping_ratio >= 1.f) { bsod("Damping ration must always be less than 1."); + } switch (type) { case Type::zv: { @@ -233,14 +237,16 @@ void input_shaper_step_generator_init(const move_t &move, input_shaper_step_gene bsod("Unsupported axis"); } #else - if (axis == X_AXIS || axis == Y_AXIS || axis == Z_AXIS) + if (axis == X_AXIS || axis == Y_AXIS || axis == Z_AXIS) { is_state->m_axis_shaper[0].m_pulses = &InputShaper::logical_axis_pulses[axis]; - else + } else { bsod("Unsupported axis"); + } #endif - for (const logical_axis_input_shaper_t &axis_shaper : is_state->m_axis_shaper) + for (const logical_axis_input_shaper_t &axis_shaper : is_state->m_axis_shaper) { move.reference_cnt += axis_shaper.m_pulses->num_pulses; + } input_shaper_state_init(*is_state, move, axis); input_shaper_step_generator_update(step_generator); @@ -253,8 +259,9 @@ void input_shaper_state_init(input_shaper_state_t &is_state, const move_t &move, is_state.print_time = move.print_time; #ifdef COREXY - for (uint8_t logical_axis = X_AXIS; logical_axis <= Y_AXIS; ++logical_axis) + for (uint8_t logical_axis = X_AXIS; logical_axis <= Y_AXIS; ++logical_axis) { is_state.m_axis_shaper[logical_axis].init(move, logical_axis); + } #else is_state.m_axis_shaper[0].init(move, axis); #endif @@ -300,8 +307,9 @@ bool logical_axis_input_shaper_t::update(const input_shaper_state_t &axis_is) { if (!axis_is.is_crossing_zero_velocity) { const move_t *curr_move = m_move[curr_idx]; const move_t *next_move = this->load_next_move_segment(curr_idx); - if (next_move == nullptr) + if (next_move == nullptr) { return false; + } weighted_velocity_discontinuity += (get_move_start_v(*next_move, m_axis) - get_move_end_v(*curr_move, m_axis)) * m_pulses->pulses[curr_idx].a; } @@ -321,10 +329,11 @@ bool logical_axis_input_shaper_t::update(const input_shaper_state_t &axis_is) { // After applying the input shape filter, the velocity during the acceleration or deceleration phase doesn't equal the velocity of the input move segment at the same time. // Because of that also, the position will not equal, so during the acceleration or deceleration phase, we cannot compute start_pos just from the input move segment. // We can compute start_pos from the input move segment (without accumulated error) just for the cruise phase where velocity is constant. - if (std::abs(half_accel) <= EPSILON) + if (std::abs(half_accel) <= EPSILON) { m_start_pos = get_move_start_pos(*first_move, m_axis) + start_v * move_t; - else + } else { m_start_pos += (m_start_v + m_half_accel * move_elapsed_time) * move_elapsed_time; + } m_start_v = start_v + 2. * half_accel * move_t; m_half_accel = half_accel; @@ -335,12 +344,14 @@ bool logical_axis_input_shaper_t::update(const input_shaper_state_t &axis_is) { m_half_accel = this->calc_half_accel(); // Change small velocities to zero as prevention for numeric issues. - if (std::abs(m_start_v) <= INPUT_SHAPER_VELOCITY_EPSILON) + if (std::abs(m_start_v) <= INPUT_SHAPER_VELOCITY_EPSILON) { m_start_v = 0.; + } // Change small accelerations to zero as prevention for numeric issues. - if (std::abs(m_half_accel) <= INPUT_SHAPER_ACCELERATION_EPSILON) + if (std::abs(m_half_accel) <= INPUT_SHAPER_ACCELERATION_EPSILON) { m_half_accel = 0.; + } } m_print_time = nearest_next_change; @@ -359,26 +370,30 @@ static bool input_shaper_state_update(input_shaper_state_t &is_state, const int bool x_updated = false; bool y_updated = false; if (is_state.is_crossing_zero_velocity || is_state.nearest_next_change == is_state.m_axis_shaper[0].get_nearest_next_change()) { - if (!is_state.m_axis_shaper[0].update(is_state)) + if (!is_state.m_axis_shaper[0].update(is_state)) { return false; - else + } else { x_updated = true; + } } if (is_state.is_crossing_zero_velocity || is_state.nearest_next_change == is_state.m_axis_shaper[1].get_nearest_next_change()) { - if (!is_state.m_axis_shaper[1].update(is_state)) + if (!is_state.m_axis_shaper[1].update(is_state)) { return false; - else + } else { y_updated = true; + } } #else - if (!is_state.m_axis_shaper[0].update(is_state)) + if (!is_state.m_axis_shaper[0].update(is_state)) { return false; + } #endif - if (is_state.is_crossing_zero_velocity) + if (is_state.is_crossing_zero_velocity) { is_state.is_crossing_zero_velocity = false; + } #ifdef COREXY double x_start_v = is_state.m_axis_shaper[0].m_start_v; @@ -411,12 +426,14 @@ static bool input_shaper_state_update(input_shaper_state_t &is_state, const int } // Change small velocities to zero as prevention for numeric issues. - if (std::abs(is_state.start_v) <= INPUT_SHAPER_VELOCITY_EPSILON) + if (std::abs(is_state.start_v) <= INPUT_SHAPER_VELOCITY_EPSILON) { is_state.start_v = 0.; + } // Change small accelerations to zero as prevention for numeric issues. - if (std::abs(is_state.half_accel) <= INPUT_SHAPER_ACCELERATION_EPSILON) + if (std::abs(is_state.half_accel) <= INPUT_SHAPER_ACCELERATION_EPSILON) { is_state.half_accel = 0.; + } is_state.step_dir = input_shaper_state_step_dir(is_state); is_state.print_time = is_state.nearest_next_change; @@ -441,8 +458,9 @@ static bool input_shaper_state_update(input_shaper_state_t &is_state, const int const double zero_velocity_crossing_time_absolute = is_state.start_v / (-2. * is_state.half_accel) + is_state.print_time; if (zero_velocity_crossing_time_absolute < (is_state.nearest_next_change - EPSILON)) { - for (logical_axis_input_shaper_t &axis_shaper : is_state.m_axis_shaper) + for (logical_axis_input_shaper_t &axis_shaper : is_state.m_axis_shaper) { axis_shaper.set_nearest_next_change(zero_velocity_crossing_time_absolute); + } is_state.nearest_next_change = zero_velocity_crossing_time_absolute; is_state.is_crossing_zero_velocity = true; @@ -539,8 +557,9 @@ uint8_t logical_axis_input_shaper_t::calc_nearest_next_change_idx() const { double logical_axis_input_shaper_t::calc_half_accel() const { double half_accel = 0.; - for (uint8_t idx = 0; idx < m_pulses->num_pulses; ++idx) + for (uint8_t idx = 0; idx < m_pulses->num_pulses; ++idx) { half_accel += m_pulses->pulses[idx].a * get_move_half_accel(*m_move[idx], m_axis); + } return half_accel; } @@ -550,8 +569,9 @@ void logical_axis_input_shaper_t::set_nearest_next_change(const double new_neare const move_t *logical_axis_input_shaper_t::load_next_move_segment(const uint8_t m_idx) { const move_t *next_move = PreciseStepping::move_segment_queue_next_move(*m_move[m_idx]); - if (next_move == nullptr) + if (next_move == nullptr) { return nullptr; + } --m_move[m_idx]->reference_cnt; ++next_move->reference_cnt; diff --git a/lib/Marlin/Marlin/src/feature/precise_stepping/internal.hpp b/lib/Marlin/Marlin/src/feature/precise_stepping/internal.hpp index 5c101a4d52..d3529c2da1 100644 --- a/lib/Marlin/Marlin/src/feature/precise_stepping/internal.hpp +++ b/lib/Marlin/Marlin/src/feature/precise_stepping/internal.hpp @@ -52,15 +52,17 @@ FORCE_INLINE float fast_sqrt(float in) { // Step_dir determines which solution of the quadratic equation we will choose. FORCE_INLINE float calc_time_for_distance(const float start_velocity, const float acceleration, const float distance, const bool step_dir) { if (acceleration == 0.f) { - if (start_velocity != 0.f) + if (start_velocity != 0.f) { return distance / start_velocity; - else + } else { return std::numeric_limits::infinity(); + } } else if (const float sqr = 2.f * acceleration * distance + SQR(start_velocity); sqr >= 0.f) { - if (step_dir) + if (step_dir) { return (fast_sqrt(sqr) - start_velocity) / acceleration; - else + } else { return (-fast_sqrt(sqr) - start_velocity) / acceleration; + } } else if (sqr < 0.f && sqr >= -EPSILON_FLOAT) { return -(start_velocity / acceleration); } else { diff --git a/lib/Marlin/Marlin/src/feature/precise_stepping/precise_stepping.cpp b/lib/Marlin/Marlin/src/feature/precise_stepping/precise_stepping.cpp index 24bd53a32d..f5545dd5b2 100644 --- a/lib/Marlin/Marlin/src/feature/precise_stepping/precise_stepping.cpp +++ b/lib/Marlin/Marlin/src/feature/precise_stepping/precise_stepping.cpp @@ -150,8 +150,9 @@ FORCE_INLINE xyze_double_t calc_axes_r_from_block(const block_t &block) { axes_r[i] = 0.; } else { axes_r[i] = double(block.msteps[i]) * millimeters_inv * double(Planner::mm_per_mstep[i]); - if (block.direction_bits & _BV(i)) + if (block.direction_bits & _BV(i)) { axes_r[i] *= -1.; + } } } @@ -170,10 +171,11 @@ FORCE_INLINE double calc_distance_required_to_reach_cruise_velocity(const double // Clamp distances close to zero or negative. FORCE_INLINE double calc_distance_required_to_reach_cruise_velocity_clamped(const double start_v, const double cruise_v, const double accel) { - if (const double dist_out = calc_distance_required_to_reach_cruise_velocity(start_v, cruise_v, accel); dist_out < EPSILON_DISTANCE) + if (const double dist_out = calc_distance_required_to_reach_cruise_velocity(start_v, cruise_v, accel); dist_out < EPSILON_DISTANCE) { return 0.; - else + } else { return dist_out; + } } // It assumes that there is no move segment with cruise velocity. @@ -187,12 +189,13 @@ FORCE_INLINE double calc_distance_in_which_we_start_decelerating(const double st // Clamp distances close to zero or negative to zero and distances close to "dist" to "dist". FORCE_INLINE double calc_distance_in_which_we_start_decelerating_clamped(const double start_v, const double end_v, const double accel, const double dist) { - if (const double dist_out = calc_distance_in_which_we_start_decelerating(start_v, end_v, accel, dist); dist_out <= EPSILON_DISTANCE) + if (const double dist_out = calc_distance_in_which_we_start_decelerating(start_v, end_v, accel, dist); dist_out <= EPSILON_DISTANCE) { return 0.; - else if (dist_out > dist - EPSILON_DISTANCE) + } else if (dist_out > dist - EPSILON_DISTANCE) { return dist; - else + } else { return dist_out; + } } bool append_move_segments_to_queue(const block_t &block) { @@ -218,8 +221,9 @@ bool append_move_segments_to_queue(const block_t &block) { cruise_v = calc_velocity_after_acceleration(start_v, accel, accel_dist); } - if (uint8_t move_blocks_required = (accel_dist != 0.) + (decel_dist != 0.) + (cruise_dist != 0.); PreciseStepping::move_segment_queue_free_slots() < (move_blocks_required + MOVE_SEGMENT_QUEUE_MIN_FREE_SLOTS)) + if (uint8_t move_blocks_required = (accel_dist != 0.) + (decel_dist != 0.) + (cruise_dist != 0.); PreciseStepping::move_segment_queue_free_slots() < (move_blocks_required + MOVE_SEGMENT_QUEUE_MIN_FREE_SLOTS)) { return false; + } const PreciseSteppingFlag_t old_ps_flags = PreciseStepping::flags; const MoveFlag_t active_axis = get_active_axis_flags_from_block(block); @@ -246,8 +250,9 @@ bool append_move_segments_to_queue(const block_t &block) { | (uint16_t(block.direction_bits & 0x0F) << MOVE_FLAG_DIR_SHIFT) | active_axis | (uint32_t(old_ps_flags) << MOVE_FLAG_RESET_POSITION_SHIFT); - if (!append_move_segment_to_queue(accel_t, start_v, half_accel, print_time, axes_r, start_pos, flags)) + if (!append_move_segment_to_queue(accel_t, start_v, half_accel, print_time, axes_r, start_pos, flags)) { bsod("Acceleration move segment wasn't append into the queue."); + } print_time += accel_t; start_pos = calc_end_position(start_pos, axes_r, accel_dist); @@ -261,8 +266,9 @@ bool append_move_segments_to_queue(const block_t &block) { | (uint16_t(block.direction_bits & 0x0F) << MOVE_FLAG_DIR_SHIFT) | active_axis | ((accel_dist != 0.) ? 0x00 : (uint32_t(old_ps_flags) << MOVE_FLAG_RESET_POSITION_SHIFT)); - if (!append_move_segment_to_queue(cruise_t, cruise_v, 0., print_time, axes_r, start_pos, flags)) + if (!append_move_segment_to_queue(cruise_t, cruise_v, 0., print_time, axes_r, start_pos, flags)) { bsod("Cruise move segment wasn't append into the queue."); + } print_time += cruise_t; start_pos = calc_end_position(start_pos, axes_r, cruise_dist); @@ -276,8 +282,9 @@ bool append_move_segments_to_queue(const block_t &block) { | (uint16_t(block.direction_bits & 0x0F) << MOVE_FLAG_DIR_SHIFT) | active_axis | ((accel_dist != 0. || cruise_dist != 0.) ? 0x00 : (uint32_t(old_ps_flags) << MOVE_FLAG_RESET_POSITION_SHIFT)); - if (!append_move_segment_to_queue(decel_t, cruise_v, -half_accel, print_time, axes_r, start_pos, flags)) + if (!append_move_segment_to_queue(decel_t, cruise_v, -half_accel, print_time, axes_r, start_pos, flags)) { bsod("Deceleration move segment wasn't append into the queue."); + } print_time += decel_t; } @@ -295,12 +302,13 @@ FORCE_INLINE float calc_time_for_distance(const classic_step_generator_t &step_g FORCE_INLINE float get_move_axis_r(const move_t &move, const int axis) { #ifdef COREXY - if (axis == A_AXIS) + if (axis == A_AXIS) { return float(move.axes_r[X_AXIS]) + float(move.axes_r[Y_AXIS]); - else if (axis == B_AXIS) + } else if (axis == B_AXIS) { return float(move.axes_r[X_AXIS]) - float(move.axes_r[Y_AXIS]); - else + } else { return float(move.axes_r[axis]); + } #else return float(move.axes_r[axis]); #endif @@ -321,17 +329,19 @@ FORCE_INLINE void classic_step_generator_update(classic_step_generator_t &step_g #ifdef COREXY // TODO @hejllukas: It can be moved into get_move_start_pos(). - if (axis == A_AXIS) + if (axis == A_AXIS) { step_generator.start_pos = float(current_move.start_pos.x) + float(current_move.start_pos.y); - else if (axis == B_AXIS) + } else if (axis == B_AXIS) { step_generator.start_pos = float(current_move.start_pos.x) - float(current_move.start_pos.y); - else + } else { step_generator.start_pos = float(current_move.start_pos[step_generator.axis]); + } - if (axis == A_AXIS || axis == B_AXIS) + if (axis == A_AXIS || axis == B_AXIS) { step_generator.step_dir = step_generator.start_v >= 0.; // TODO @hejllukas: It can be done cheaply without the comparison of start_v. - else + } else { step_generator.step_dir = get_move_step_dir(*step_generator.current_move, step_generator.axis); + } #else step_generator.start_pos = float(current_move.start_pos[step_generator.axis]); step_generator.step_dir = get_move_step_dir(*step_generator.current_move, step_generator.axis); @@ -368,8 +378,9 @@ step_event_info_t classic_step_generator_next_step_event(classic_step_generator_ next_step_event.time = next_move->print_time; // Reset position in steps (current_distance) based on the difference in the position. - if (next_move->flags & (MOVE_FLAG_RESET_POSITION_X << step_generator.axis)) + if (next_move->flags & (MOVE_FLAG_RESET_POSITION_X << step_generator.axis)) { classic_step_generator_reset_position(step_generator, step_generator_state, *next_move); + } // The move segment is fully processed, and in the queue is another unprocessed move segment. // So we decrement reference count of the current move segment and increment reference count of next move segment. @@ -443,8 +454,12 @@ bool generate_next_step_event(step_event_i32_t &step_event, step_generator_state assert(step_event.flags); // ensure flags are non-zero // The timer ticks mustn't be negative in any case. Because if it is negative, there is an issue in the code. - if (step_event.time_ticks < 0) + if (step_event.time_ticks < 0) { +#ifndef NDEBUG bsod("Negative step time: %d, flags: %d", step_event.time_ticks, step_event.flags); +#endif + step_event.time_ticks = 0; + } if (step_state.left_insert_start_of_move_segment) { step_event.flags |= STEP_EVENT_FLAG_BEGINNING_OF_MOVE_SEGMENT; @@ -560,8 +575,9 @@ uint16_t PreciseStepping::process_one_step_event_from_queue() { if (const move_t *current_move = get_current_move_segment(); current_move->flags & MOVE_FLAG_LAST_MOVE_SEGMENT_OF_BLOCK) { // discard the current block if this move is also the last move segment of a block block_t *current_block = Planner::get_current_processed_block(); - if (current_block->flag.sync_position) + if (current_block->flag.sync_position) { Stepper::_set_position(current_block->position); + } Planner::discard_current_block(); Stepper::count_position_last_block = Stepper::count_position; } @@ -625,10 +641,11 @@ uint16_t PreciseStepping::process_one_step_event_from_queue() { E_STEP_RESET(); } - if (step_event_u16_t *next_step_event = get_current_step_event(); next_step_event != nullptr) + if (step_event_u16_t *next_step_event = get_current_step_event(); next_step_event != nullptr) { ticks_to_next_isr = next_step_event->time_ticks; - else if ((step_flags & STEP_EVENT_END_OF_MOTION) == false) + } else if ((step_flags & STEP_EVENT_END_OF_MOTION) == false) { ++step_ev_miss; + } } else { // The step event queue drained or ended Stepper::axis_did_move = 0; @@ -650,8 +667,9 @@ void PreciseStepping::step_isr() { #ifdef ISR_DEADLINE_TRACKING // in addition to checking for forward misses, check for past ones static uint32_t scheduled_ts = 0; - if (scheduled_ts && ticks_us() > scheduled_ts + min_reserve * 2) + if (scheduled_ts && ticks_us() > scheduled_ts + min_reserve * 2) { ++step_dl_miss; + } #endif uint16_t time_increment = 0; @@ -677,13 +695,15 @@ void PreciseStepping::step_isr() { // Compute the number of ticks for the next ISR. time_increment += ticks_to_next_step_event; - if (ticks_to_next_step_event > min_delay || steps >= max_steps) + if (ticks_to_next_step_event > min_delay || steps >= max_steps) { break; + } // the next step is too close for a new isr but still within margin, // spin-wait for accurate delivery - if (left_ticks_to_next_step_event) + if (left_ticks_to_next_step_event) { delay_us_precise(left_ticks_to_next_step_event); + } } uint32_t compare = __HAL_TIM_GET_COMPARE(&TimerHandle[STEP_TIMER_NUM].handle, TIM_CHANNEL_1); @@ -781,15 +801,17 @@ bool PreciseStepping::is_waiting_before_delivering() { } else if (Planner::nonbusy_movesplanned() >= 3 || (ticks_ms() - waiting_before_delivering_start_time) >= Planner::delay_before_delivering) { Planner::delay_before_delivering = 0; waiting_before_delivering_start_time = 0; - } else + } else { return true; + } } if (const uint8_t waiting_for_discard = Planner::movesplanned_processed(); waiting_for_discard >= (BLOCK_BUFFER_SIZE / 2)) { // In case the block queue contains plenty of short blocks waiting for discarding and step generators are unable to produce new // step events, we have to ensure that the next block can be processed (or the empty move segment can be placed into the queue). - if (PreciseStepping::get_nearest_step_event_status() == STEP_EVENT_INFO_STATUS_GENERATED_INVALID) + if (PreciseStepping::get_nearest_step_event_status() == STEP_EVENT_INFO_STATUS_GENERATED_INVALID) { return false; + } return true; } @@ -798,15 +820,17 @@ bool PreciseStepping::is_waiting_before_delivering() { } void PreciseStepping::process_queue_of_blocks() { - if (is_waiting_before_delivering()) + if (is_waiting_before_delivering()) { return; + } // When the ending move segment is on the bottom of the queue (then Planner::total_print_time // contains the value bigger then MAX_PRINT_TIME) we're waiting for motion to halt and reset. if (PreciseStepping::total_print_time >= MAX_PRINT_TIME) { // ensure all motion has stopped - if (has_blocks_queued()) + if (has_blocks_queued()) { return; + } // we can now reset to a halt reset_from_halt(true); @@ -833,8 +857,9 @@ void PreciseStepping::process_queue_of_blocks() { // the counters should be manipulated directly otherwise assert(PreciseStepping::total_print_time != 0.); - if (!append_block_discarding_move()) + if (!append_block_discarding_move()) { return; + } // To avoid accumulating E-axis into very big numbers that are causing numerical issues, we reset // the E-axis position with every SYNC block. @@ -842,8 +867,9 @@ void PreciseStepping::process_queue_of_blocks() { // @hejllukas: If we sometimes implement reset for input shaper and decide to synchronize total_start_pos // with the Planner position, we should introduce something like SYNC move segment and replace // append_block_discarding_move() with that. That should simplify the resetting mechanism. - if (current_block->is_sync() && current_block->position.e == 0) + if (current_block->is_sync() && current_block->position.e == 0) { PreciseStepping::flags |= PRECISE_STEPPING_FLAG_RESET_POSITION_E; + } // pass-through SYNC blocks, they will be processed in the ISR Planner::discard_current_unprocessed_block(); @@ -860,12 +886,14 @@ void PreciseStepping::process_queue_of_blocks() { if (PreciseStepping::total_print_time == 0.) { // we're restarting from zero, prepend a beginning move - if (!append_beginning_empty_move()) + if (!append_beginning_empty_move()) { return; + } } - if (append_move_segments_to_queue(*current_block)) + if (append_move_segments_to_queue(*current_block)) { Planner::discard_current_unprocessed_block(); + } } void PreciseStepping::loop() { @@ -893,8 +921,9 @@ void PreciseStepping::loop() { } void PreciseStepping::move_isr() { - if (stop_pending) + if (stop_pending) { return; + } StepGeneratorStatus status = process_one_move_segment_from_queue(); if (status == STEP_GENERATOR_STATUS_OK) { @@ -955,8 +984,9 @@ FORCE_INLINE split_step_event_t split_buffered_step(const step_generator_state_t split_step_event.empty_step_event_cnt = (step_generator_state.buffered_step.time_ticks - 1) / STEP_TIMER_MAX_TICKS_LIMIT; split_step_event.last_step_event_time_ticks = step_generator_state.buffered_step.time_ticks - split_step_event.empty_step_event_cnt * STEP_TIMER_MAX_TICKS_LIMIT; - if (split_step_event.empty_step_event_cnt > STEP_EVENT_QUEUE_SIZE) + if (split_step_event.empty_step_event_cnt > STEP_EVENT_QUEUE_SIZE) { bsod("Step event time exceeds the size of the step event queue."); + } // We left only the direction and the active axes flags because other flags have to be present only in the last step event. split_step_event.empty_step_event_flags = step_generator_state.buffered_step.flags & (STEP_EVENT_FLAG_DIR_MASK | STEP_EVENT_FLAG_AXIS_ACTIVE_MASK); @@ -1009,11 +1039,13 @@ StepGeneratorStatus PreciseStepping::process_one_move_segment_from_queue() { // ensure there is space free for flushing the buffered step split_step_event_t split_step_event; if (step_generator_state.buffered_step.flags) { - if (next_step_event == nullptr) + if (next_step_event == nullptr) { return STEP_GENERATOR_STATUS_FULL_STEP_EVENT_QUEUE; + } split_step_event = split_buffered_step(step_generator_state); - if (split_step_event.empty_step_event_cnt && split_step_event.empty_step_event_cnt + 1 > step_event_queue_free_slots()) + if (split_step_event.empty_step_event_cnt && split_step_event.empty_step_event_cnt + 1 > step_event_queue_free_slots()) { return STEP_GENERATOR_STATUS_FULL_STEP_EVENT_QUEUE; + } } step_event_i32_t new_step_event; @@ -1063,12 +1095,14 @@ StepGeneratorStatus PreciseStepping::process_one_move_segment_from_queue() { if (step_generator_state.buffered_step.flags) { uint16_t next_step_event_queue_head; step_event_u16_t *next_step_event = PreciseStepping::get_next_free_step_event(next_step_event_queue_head); - if (next_step_event == nullptr) + if (next_step_event == nullptr) { return STEP_GENERATOR_STATUS_FULL_STEP_EVENT_QUEUE; + } split_step_event_t split_step_event = split_buffered_step(step_generator_state); - if (split_step_event.empty_step_event_cnt && split_step_event.empty_step_event_cnt + 1 > step_event_queue_free_slots()) + if (split_step_event.empty_step_event_cnt && split_step_event.empty_step_event_cnt + 1 > step_event_queue_free_slots()) { return STEP_GENERATOR_STATUS_FULL_STEP_EVENT_QUEUE; + } append_split_step_event(split_step_event, next_step_event, next_step_event_queue_head); step_generator_state.buffered_step.flags = 0; @@ -1076,8 +1110,9 @@ StepGeneratorStatus PreciseStepping::process_one_move_segment_from_queue() { // Place discarding step events (just empty step events) into the step event queue if there are // still remaining step events that have to be marked to free already processed move segments. - while (step_generator_state.left_insert_start_of_move_segment > 0 && append_move_discarding_step_event(step_generator_state)) + while (step_generator_state.left_insert_start_of_move_segment > 0 && append_move_discarding_step_event(step_generator_state)) { --step_generator_state.left_insert_start_of_move_segment; + } assert(step_generator_state.left_insert_start_of_move_segment >= 0); @@ -1106,10 +1141,11 @@ void PreciseStepping::update_maximum_lookback_time() { LOOP_XYZ(i) { if (physical_axis_step_generator_types & (INPUT_SHAPER_STEP_GENERATOR_X << i)) { #ifdef COREXY - if ((physical_axis_step_generator_types & INPUT_SHAPER_STEP_GENERATOR_X) || (physical_axis_step_generator_types & INPUT_SHAPER_STEP_GENERATOR_Y)) + if ((physical_axis_step_generator_types & INPUT_SHAPER_STEP_GENERATOR_X) || (physical_axis_step_generator_types & INPUT_SHAPER_STEP_GENERATOR_Y)) { max_lookback_time = std::max(max_lookback_time, std::max(-InputShaper::logical_axis_pulses[X_AXIS].pulses[0].t, -InputShaper::logical_axis_pulses[Y_AXIS].pulses[0].t)); - else + } else { max_lookback_time = std::max(max_lookback_time, -InputShaper::logical_axis_pulses[i].pulses[0].t); + } #else max_lookback_time = std::max(max_lookback_time, -InputShaper::logical_axis_pulses[i].pulses[0].t); #endif @@ -1124,8 +1160,9 @@ void PreciseStepping::update_maximum_lookback_time() { void PreciseStepping::step_generator_state_init(const move_t &move) { assert(is_beginning_empty_move(move)); - if (max_lookback_time > move.move_t) + if (max_lookback_time > move.move_t) { bsod("Max lookback time exceeds the length of the beginning empty move segment."); + } step_generator_state.flags = 0; step_generator_state.previous_step_time = 0.; @@ -1134,8 +1171,9 @@ void PreciseStepping::step_generator_state_init(const move_t &move) { step_generator_state.left_insert_start_of_move_segment = 0; // Reset step events and index - for (step_index_t i = 0; i != step_generator_state.step_event_index.size(); ++i) + for (step_index_t i = 0; i != step_generator_state.step_event_index.size(); ++i) { step_generator_state.step_event_index[i] = i; + } for (step_event_info_t &step_event_info : step_generator_state.step_events) { step_event_info.time = 0.; @@ -1195,6 +1233,7 @@ void PreciseStepping::reset_queues() { stop_pending = false; ENABLE_MOVE_INTERRUPT(); - if (was_enabled) + if (was_enabled) { stepper.wake_up(); + } } diff --git a/lib/Marlin/Marlin/src/feature/precise_stepping/precise_stepping.hpp b/lib/Marlin/Marlin/src/feature/precise_stepping/precise_stepping.hpp index 42b7b4fffc..461a35a150 100644 --- a/lib/Marlin/Marlin/src/feature/precise_stepping/precise_stepping.hpp +++ b/lib/Marlin/Marlin/src/feature/precise_stepping/precise_stepping.hpp @@ -145,24 +145,27 @@ class PreciseStepping { // Returns the current move segment, nullptr if the queue is empty. FORCE_INLINE static move_t *get_current_move_segment() { - if (has_move_segments_queued()) + if (has_move_segments_queued()) { return &move_segment_queue.data[move_segment_queue.tail]; + } return nullptr; } // Returns the current move segment that isn't processed by PreciseStepping::process_queue_of_move_segments(), nullptr if the queue is empty. FORCE_INLINE static move_t *get_current_unprocessed_move_segment() { - if (has_unprocessed_move_segments_queued()) + if (has_unprocessed_move_segments_queued()) { return &move_segment_queue.data[move_segment_queue.unprocessed]; + } return nullptr; } // Returns the last move segment inside the queue (at the bottom of the queue), nullptr if the queue is empty. FORCE_INLINE static move_t *get_last_move_segment() { - if (has_move_segments_queued()) + if (has_move_segments_queued()) { return &move_segment_queue.data[move_segment_queue_prev_index(move_segment_queue.head)]; + } return nullptr; } @@ -170,8 +173,9 @@ class PreciseStepping { // Returns the first head move segment, nullptr if the queue is full. // Also, it returns the next move segment queue head index (passed by reference). FORCE_INLINE static move_t *get_next_free_move_segment(uint8_t &next_move_segment_queue_head) { - if (is_move_segment_queue_full()) + if (is_move_segment_queue_full()) { return nullptr; + } // Return the first available move segment. next_move_segment_queue_head = move_segment_queue_next_index(move_segment_queue.head); @@ -215,8 +219,9 @@ class PreciseStepping { // Returns the current step event, nullptr if the queue is empty. static step_event_u16_t *get_current_step_event() { - if (has_step_events_queued()) + if (has_step_events_queued()) { return &step_event_queue.data[step_event_queue.tail]; + } return nullptr; } @@ -224,8 +229,9 @@ class PreciseStepping { // Returns the first head step event, nullptr if the queue is full. // Also, it returns the next step event queue head index (passed by reference). FORCE_INLINE static step_event_u16_t *get_next_free_step_event(uint16_t &next_step_event_queue_head) { - if (is_step_event_queue_full()) + if (is_step_event_queue_full()) { return nullptr; + } // Return the first available step event. next_step_event_queue_head = step_event_queue_next_index(step_event_queue.head); @@ -234,8 +240,9 @@ class PreciseStepping { // Discard the current step event. FORCE_INLINE static void discard_current_step_event() { - if (has_step_events_queued()) + if (has_step_events_queued()) { step_event_queue.tail = step_event_queue_next_index(step_event_queue.tail); + } } FORCE_INLINE static void step_generator_state_clear() { @@ -250,10 +257,11 @@ class PreciseStepping { assert(move_idx >= 0 && move_idx < MOVE_SEGMENT_QUEUE_SIZE); // move_idx out of bounds of the move queue. assert(move_idx != move_segment_queue.head); // Input move segment is out of the move queue. - if (uint8_t next_move_idx = move_segment_queue_next_index(uint8_t(move_idx)); next_move_idx == move_segment_queue.head) + if (uint8_t next_move_idx = move_segment_queue_next_index(uint8_t(move_idx)); next_move_idx == move_segment_queue.head) { return nullptr; - else + } else { return &PreciseStepping::move_segment_queue.data[next_move_idx]; + } } FORCE_INLINE static StepEventInfoStatus get_nearest_step_event_status() { diff --git a/lib/Marlin/Marlin/src/feature/pressure_advance/pressure_advance.cpp b/lib/Marlin/Marlin/src/feature/pressure_advance/pressure_advance.cpp index 3e6a1d6907..4cdf136323 100644 --- a/lib/Marlin/Marlin/src/feature/pressure_advance/pressure_advance.cpp +++ b/lib/Marlin/Marlin/src/feature/pressure_advance/pressure_advance.cpp @@ -37,8 +37,9 @@ FORCE_INLINE void pressure_advance_precalculate_parameters(pressure_advance_step state.start_v = float(get_move_start_v(current_move, step_generator.axis)); state.half_accel = float(get_move_half_accel(current_move, step_generator.axis)); - if (is_pressure_advance_active(current_move)) + if (is_pressure_advance_active(current_move)) { state.start_v += (2.f * state.half_accel * params.pressure_advance_value); + } } else { state.start_v = 0.f; state.half_accel = 0.f; @@ -58,8 +59,9 @@ FORCE_INLINE float calc_distance_for_time_with_pressure_advance_move(const press } pressure_advance_window_filter_t create_normalized_bartlett_window_filter(const uint16_t filter_length) { - if (filter_length > PRESSURE_ADVANCE_MAX_FILTER_LENGTH) + if (filter_length > PRESSURE_ADVANCE_MAX_FILTER_LENGTH) { fatal_error("Filter length is above maximum.", "create_normalized_bartlett_window_filter"); + } pressure_advance_window_filter_t filter; if (filter_length > 1) { @@ -79,14 +81,16 @@ pressure_advance_window_filter_t create_normalized_bartlett_window_filter(const } pressure_advance_window_filter_t create_simple_window_filter(const uint16_t filter_length) { - if (filter_length > PRESSURE_ADVANCE_MAX_FILTER_LENGTH) + if (filter_length > PRESSURE_ADVANCE_MAX_FILTER_LENGTH) { bsod("Filter length is above maximum."); + } pressure_advance_window_filter_t filter; if (filter_length > 1) { filter.length = filter_length; - for (int idx = 0; idx < filter_length; ++idx) + for (int idx = 0; idx < filter_length; ++idx) { filter.window[idx] = 0.f; + } int idx = (filter_length - 1) / 2; filter.window[idx] = 1.f; @@ -168,16 +172,19 @@ void pressure_advance_state_init(pressure_advance_step_generator_t &step_generat FORCE_INLINE float pressure_advance_apply_filter(pressure_advance_state_t &state, const pressure_advance_params_t ¶ms) { assert(params.filter.length == state.buffer.length); - if (state.buffer.same_samples_cnt >= params.filter.length) + if (state.buffer.same_samples_cnt >= params.filter.length) { return state.start_pos; + } float filtered_value = 0.; const uint16_t index_diff = (params.filter.length - state.buffer.start_idx); - for (int window_idx = 0; window_idx < index_diff; ++window_idx) + for (int window_idx = 0; window_idx < index_diff; ++window_idx) { filtered_value += params.filter.window[window_idx] * state.buffer.data[state.buffer.start_idx + window_idx]; + } - for (int window_idx = index_diff; window_idx < params.filter.length; ++window_idx) + for (int window_idx = index_diff; window_idx < params.filter.length; ++window_idx) { filtered_value += params.filter.window[window_idx] * state.buffer.data[window_idx - index_diff]; + } return filtered_value; } @@ -185,10 +192,11 @@ FORCE_INLINE float pressure_advance_apply_filter(pressure_advance_state_t &state // Based on whether the extruder is active, update the counter for the same samples in the buffer, which is used // for skipping most of the pressure advance computation for move segments without the active extruder. FORCE_INLINE void pressure_advance_update_same_samples_count(pressure_advance_state_t &state) { - if (const bool is_e_active = is_active_e_axis(*state.current_move); !is_e_active && state.buffer.same_samples_cnt < state.buffer.length) + if (const bool is_e_active = is_active_e_axis(*state.current_move); !is_e_active && state.buffer.same_samples_cnt < state.buffer.length) { ++state.buffer.same_samples_cnt; - else if (is_e_active && state.buffer.same_samples_cnt > 0) + } else if (is_e_active && state.buffer.same_samples_cnt > 0) { state.buffer.same_samples_cnt = 0; + } } // Returns true when we were able to get the next sample, false if the buffer wasn't filled up, @@ -233,8 +241,9 @@ FORCE_INLINE bool pressure_advance_sample_next(pressure_advance_state_t &state, } FORCE_INLINE float pressure_advance_get_next_position(pressure_advance_state_t &state, const pressure_advance_params_t ¶ms) { - if (!pressure_advance_sample_next(state, params)) + if (!pressure_advance_sample_next(state, params)) { return std::numeric_limits::infinity(); + } return pressure_advance_apply_filter(state, params); } @@ -278,8 +287,9 @@ double calc_time_for_distance_pressure_advance(const float distance, pressure_ad const double next_step_negative = float(step_generator_state.current_distance[axis] - 1) * Planner::mm_per_step[axis] + distance; // When state.position_has_to_be_in_range is true, then have to be next_step_positive or next_step_negative // inside the interval (state.prev_position, state.next_position). - if (state.position_has_to_be_in_range) + if (state.position_has_to_be_in_range) { assert((!state.step_dir || (state.prev_position <= next_step_negative && next_step_negative <= state.next_position)) && (state.step_dir || (state.prev_position >= next_step_positive && next_step_positive >= state.next_position))); + } } #endif @@ -348,17 +358,19 @@ void pressure_advance_reset_position(pressure_advance_step_generator_t &step_gen const float axis_diff = float(axis_diff_steps) * Planner::mm_per_step[axis]; // We have ensured that there is at least a number of samples equal to the buffer size. So, the whole buffer is filled with sampled positions. - for (uint32_t buffer_idx = 0; buffer_idx < step_generator.pa_state->buffer.length; ++buffer_idx) + for (uint32_t buffer_idx = 0; buffer_idx < step_generator.pa_state->buffer.length; ++buffer_idx) { step_generator.pa_state->buffer.data[buffer_idx] += axis_diff; + } // Because this function is called when the next step position isn't within the interval (prev_position, next_position), // we don't have to care about numeric issues. We have to only ensure that when prev_position and next_position are equal, // then after resetting, they will also equal. float new_next_position = pressure_advance_apply_filter(*step_generator.pa_state, PressureAdvance::pressure_advance_params); - if (step_generator.pa_state->prev_position == step_generator.pa_state->next_position) + if (step_generator.pa_state->prev_position == step_generator.pa_state->next_position) { step_generator.pa_state->prev_position = new_next_position; - else + } else { step_generator.pa_state->prev_position += axis_diff; + } step_generator.pa_state->next_position = new_next_position; @@ -402,14 +414,16 @@ step_event_info_t pressure_advance_step_generator_next_step_event(pressure_advan // We have to update start_post before we reset the pressure advance position because // we are using it during the resetting position. - if (is_pressure_advance_active(*next_move)) + if (is_pressure_advance_active(*next_move)) { step_generator.pa_state->start_pos = float(get_move_start_pos(*next_move, step_generator.axis)) + float(get_move_start_v(*next_move, step_generator.axis)) * PressureAdvance::pressure_advance_params.pressure_advance_value; - else + } else { step_generator.pa_state->start_pos = float(get_move_start_pos(*next_move, step_generator.axis)); + } // Apply reset of position on the pressure advance data structure and adjust position in steps (current_distance). - if (next_move->flags & (MOVE_FLAG_RESET_POSITION_X << step_generator.axis)) + if (next_move->flags & (MOVE_FLAG_RESET_POSITION_X << step_generator.axis)) { pressure_advance_reset_position(step_generator, step_generator_state, *next_move); + } --step_generator.pa_state->current_move->reference_cnt; step_generator.pa_state->current_move = next_move; diff --git a/lib/Marlin/Marlin/src/feature/pressure_advance/pressure_advance_config.cpp b/lib/Marlin/Marlin/src/feature/pressure_advance/pressure_advance_config.cpp index e9a1dc73be..ceb3d79e16 100644 --- a/lib/Marlin/Marlin/src/feature/pressure_advance/pressure_advance_config.cpp +++ b/lib/Marlin/Marlin/src/feature/pressure_advance/pressure_advance_config.cpp @@ -22,10 +22,11 @@ void set_axis_e_config(const Config &config) { // set step generator e_axis_config = config; - if (config.pressure_advance > 0.f) + if (config.pressure_advance > 0.f) { PreciseStepping::physical_axis_step_generator_types |= PRESSURE_ADVANCE_STEP_GENERATOR_E; - else + } else { PreciseStepping::physical_axis_step_generator_types &= ~PRESSURE_ADVANCE_STEP_GENERATOR_E; + } PreciseStepping::update_maximum_lookback_time(); } diff --git a/lib/Marlin/Marlin/src/feature/prusa/MMU2/mmu2.cpp b/lib/Marlin/Marlin/src/feature/prusa/MMU2/mmu2.cpp index 6cbee5d0bf..22f2d09db7 100644 --- a/lib/Marlin/Marlin/src/feature/prusa/MMU2/mmu2.cpp +++ b/lib/Marlin/Marlin/src/feature/prusa/MMU2/mmu2.cpp @@ -295,13 +295,16 @@ void MMU2::mmu_loop() { state = 1; - if (cmd == 0) + if (cmd == 0) { ready = true; + } - if (!finda && finda_runout_valid) + if (!finda && finda_runout_valid) { filament_runout(); - } else if (ELAPSED(millis(), last_request + MMU_P0_TIMEOUT)) // Resend request after timeout (3s) + } + } else if (ELAPSED(millis(), last_request + MMU_P0_TIMEOUT)) { // Resend request after timeout (3s) state = 1; + } break; @@ -354,19 +357,23 @@ bool MMU2::rx_str_P(const char *str) { uint8_t len = strlen_P(str); - if (i < len) + if (i < len) { return false; + } str += len; while (len--) { char c0 = pgm_read_byte(str--), c1 = rx_buffer[i--]; - if (c0 == c1) + if (c0 == c1) { continue; - if (c0 == '\r' && c1 == '\n') + } + if (c0 == '\r' && c1 == '\n') { continue; // match cr as lf - if (c0 == '\n' && c1 == '\r') + } + if (c0 == '\n' && c1 == '\r') { continue; // match lf as cr + } return false; } return true; @@ -378,8 +385,9 @@ bool MMU2::rx_str_P(const char *str) { void MMU2::tx_str_P(const char *str) { clear_rx_buffer(); uint8_t len = strlen_P(str); - for (uint8_t i = 0; i < len; i++) + for (uint8_t i = 0; i < len; i++) { mmuSerial.write(pgm_read_byte(str++)); + } rx_buffer[0] = '\0'; last_request = millis(); } @@ -390,8 +398,9 @@ void MMU2::tx_str_P(const char *str) { void MMU2::tx_printf_P(const char *format, int argument = -1) { clear_rx_buffer(); uint8_t len = sprintf_P(tx_buffer, format, argument); - for (uint8_t i = 0; i < len; i++) + for (uint8_t i = 0; i < len; i++) { mmuSerial.write(tx_buffer[i]); + } rx_buffer[0] = '\0'; last_request = millis(); } @@ -402,8 +411,9 @@ void MMU2::tx_printf_P(const char *format, int argument = -1) { void MMU2::tx_printf_P(const char *format, int argument1, int argument2) { clear_rx_buffer(); uint8_t len = sprintf_P(tx_buffer, format, argument1, argument2); - for (uint8_t i = 0; i < len; i++) + for (uint8_t i = 0; i < len; i++) { mmuSerial.write(tx_buffer[i]); + } rx_buffer[0] = '\0'; last_request = millis(); } @@ -412,8 +422,9 @@ void MMU2::tx_printf_P(const char *format, int argument1, int argument2) { * Empty the rx buffer */ void MMU2::clear_rx_buffer() { - while (mmuSerial.available()) + while (mmuSerial.available()) { mmuSerial.read(); + } rx_buffer[0] = '\0'; } @@ -443,8 +454,9 @@ void MMU2::check_version() { */ void MMU2::tool_change(uint8_t index) { - if (!enabled) + if (!enabled) { return; + } set_runout_valid(false); @@ -483,8 +495,9 @@ void MMU2::tool_change(uint8_t index) { */ void MMU2::tool_change(const char *special) { - if (!enabled) + if (!enabled) { return; + } #if ENABLED(MMU2_MENUS) @@ -493,8 +506,9 @@ void MMU2::tool_change(const char *special) { switch (*special) { case '?': { uint8_t index = mmu2_choose_filament(); - while (!thermalManager.wait_for_hotend(active_extruder, false)) + while (!thermalManager.wait_for_hotend(active_extruder, false)) { safe_delay(100); + } load_filament_to_nozzle(index); } break; @@ -513,8 +527,9 @@ void MMU2::tool_change(const char *special) { } break; case 'c': { - while (!thermalManager.wait_for_hotend(active_extruder, false)) + while (!thermalManager.wait_for_hotend(active_extruder, false)) { safe_delay(100); + } execute_extruder_sequence((const E_Step *)load_to_nozzle_sequence, COUNT(load_to_nozzle_sequence)); } break; } @@ -528,8 +543,9 @@ void MMU2::tool_change(const char *special) { * Set next command */ void MMU2::command(const uint8_t mmu_cmd) { - if (!enabled) + if (!enabled) { return; + } cmd = mmu_cmd; ready = false; } @@ -538,13 +554,15 @@ void MMU2::command(const uint8_t mmu_cmd) { * Wait for response from MMU */ bool MMU2::get_response() { - while (cmd != MMU_CMD_NONE) + while (cmd != MMU_CMD_NONE) { idle(true); + } while (!ready) { idle(true); - if (state != 3) + if (state != 3) { break; + } } const bool ret = ready; @@ -582,11 +600,13 @@ void MMU2::manage_response(const bool move_axes, const bool turn_off_nozzle) { resume_hotend_temp = thermalManager.degTargetHotend(active_extruder); resume_position = current_position; - if (move_axes && all_axes_homed()) + if (move_axes && all_axes_homed()) { nozzle.park(2, park_point /*= NOZZLE_PARK_POINT*/); + } - if (turn_off_nozzle) + if (turn_off_nozzle) { thermalManager.setTargetHotend(0, active_extruder); + } LCD_MESSAGEPGM(MSG_MMU2_NOT_RESPONDING); BUZZ(100, 659); @@ -603,8 +623,9 @@ void MMU2::manage_response(const bool move_axes, const bool turn_off_nozzle) { LCD_MESSAGEPGM(MSG_HEATING); BUZZ(200, 40); - while (!thermalManager.wait_for_hotend(active_extruder, false)) + while (!thermalManager.wait_for_hotend(active_extruder, false)) { safe_delay(1000); + } } if (move_axes && all_axes_homed()) { @@ -627,8 +648,9 @@ void MMU2::manage_response(const bool move_axes, const bool turn_off_nozzle) { } void MMU2::set_filament_type(uint8_t index, uint8_t filamentType) { - if (!enabled) + if (!enabled) { return; + } cmd_arg = filamentType; command(MMU_CMD_F0 + index); @@ -645,8 +667,9 @@ void MMU2::filament_runout() { // Load filament into MMU2 void MMU2::load_filament(uint8_t index) { - if (!enabled) + if (!enabled) { return; + } command(MMU_CMD_L0 + index); manage_response(false, false); BUZZ(200, 404); @@ -659,8 +682,9 @@ void MMU2::load_filament(uint8_t index) { */ bool MMU2::load_filament_to_nozzle(uint8_t index) { - if (!enabled) + if (!enabled) { return false; + } if (thermalManager.tooColdToExtrude(active_extruder)) { BUZZ(200, 404); @@ -691,15 +715,17 @@ bool MMU2::load_filament_to_nozzle(uint8_t index) { * filament to nozzle. */ void MMU2::load_to_nozzle() { - if (!enabled) + if (!enabled) { return; + } execute_extruder_sequence((const E_Step *)load_to_nozzle_sequence, COUNT(load_to_nozzle_sequence)); } bool MMU2::eject_filament(uint8_t index, bool recover) { - if (!enabled) + if (!enabled) { return false; + } if (thermalManager.tooColdToExtrude(active_extruder)) { BUZZ(200, 404); @@ -726,8 +752,9 @@ bool MMU2::eject_filament(uint8_t index, bool recover) { #if ENABLED(EXTENSIBLE_UI) ExtUI::onUserConfirmRequired_P(PSTR("MMU2 Eject Recover")); #endif - while (wait_for_user) + while (wait_for_user) { idle(true); + } BUZZ(200, 404); BUZZ(200, 404); @@ -756,8 +783,9 @@ bool MMU2::eject_filament(uint8_t index, bool recover) { */ bool MMU2::unload() { - if (!enabled) + if (!enabled) { return false; + } if (thermalManager.tooColdToExtrude(active_extruder)) { BUZZ(200, 404); diff --git a/lib/Marlin/Marlin/src/feature/prusa/MMU2/mmu2.h b/lib/Marlin/Marlin/src/feature/prusa/MMU2/mmu2.h index 4def80da55..a620f58e57 100644 --- a/lib/Marlin/Marlin/src/feature/prusa/MMU2/mmu2.h +++ b/lib/Marlin/Marlin/src/feature/prusa/MMU2/mmu2.h @@ -84,8 +84,9 @@ class MMU2 { static inline void set_runout_valid(const bool valid) { finda_runout_valid = valid; #if HAS_FILAMENT_SENSOR - if (valid) + if (valid) { runout.reset(); + } #endif } }; diff --git a/lib/Marlin/Marlin/src/feature/prusa/MMU2/mmu2_mk4.cpp b/lib/Marlin/Marlin/src/feature/prusa/MMU2/mmu2_mk4.cpp index 9759ff3809..d30b94586f 100644 --- a/lib/Marlin/Marlin/src/feature/prusa/MMU2/mmu2_mk4.cpp +++ b/lib/Marlin/Marlin/src/feature/prusa/MMU2/mmu2_mk4.cpp @@ -46,8 +46,9 @@ class Timer { // returns true only once after expiration, then stops running bool expired(T msPeriod) { - if (!m_isRunning) + if (!m_isRunning) { return false; + } bool expired = false; const T now = millis(); if (m_started <= m_started + msPeriod) { @@ -59,8 +60,9 @@ class Timer { expired = true; } } - if (expired) + if (expired) { m_isRunning = false; + } return expired; } @@ -225,8 +227,9 @@ void MMU2::PowerOn() { } bool MMU2::ReadRegister(uint8_t address) { - if (!WaitForMMUReady()) + if (!WaitForMMUReady()) { return false; + } do { logic.ReadRegister(address); // we may signal the accepted/rejected status of the response as return value of this function } while (!manage_response(false, false)); @@ -237,8 +240,9 @@ bool MMU2::ReadRegister(uint8_t address) { } bool __attribute__((noinline)) MMU2::WriteRegister(uint8_t address, uint16_t data) { - if (!WaitForMMUReady()) + if (!WaitForMMUReady()) { return false; + } // special cases - intercept requests of registers which influence the printer's behaviour too + perform the change even on the printer's side switch (address) { @@ -264,8 +268,9 @@ void MMU2::mmu_loop() { // Atomic compare_exchange would have been the most appropriate solution here, but this gets called only in Marlin's task, // so thread safety should be kept static bool avoidRecursion = false; - if (avoidRecursion) + if (avoidRecursion) { return; + } avoidRecursion = true; mmu_loop_inner(true); @@ -373,8 +378,9 @@ bool MMU2::RetryIfPossible(ErrorCode ec) { bool MMU2::VerifyFilamentEnteredPTFE() { planner_synchronize(); - if (WhereIsFilament() != FilamentState::AT_FSENSOR) + if (WhereIsFilament() != FilamentState::AT_FSENSOR) { return false; + } // MMU has finished its load, push the filament further by some defined constant length // If the filament sensor reads 0 at any moment, then report FAILURE @@ -439,8 +445,9 @@ bool MMU2::ToolChangeCommonOnce(uint8_t slot) { planner_synchronize(); logic.ToolChange(slot); // let the MMU pull the filament out and push a new one in - if (manage_response(true, true)) + if (manage_response(true, true)) { break; + } // otherwise: failed to perform the command - unload first and then let it run again IncrementMMUFails(); @@ -485,8 +492,9 @@ void MMU2::ToolChangeCommon(uint8_t slot) { } bool MMU2::tool_change(uint8_t slot) { - if (!WaitForMMUReady()) + if (!WaitForMMUReady()) { return false; + } if (slot != extruder) { if (/*FindaDetectsFilament()*/ @@ -507,8 +515,9 @@ bool MMU2::tool_change(uint8_t slot) { } bool MMU2::tool_change_full(uint8_t slot) { - if (!WaitForMMUReady()) + if (!WaitForMMUReady()) { return false; + } if (slot != extruder) { planner_synchronize(); @@ -545,8 +554,9 @@ bool MMU2::tool_change_full(uint8_t slot) { ///- Tx Same as T?, except nozzle doesn't have to be preheated. Tc must be placed after extruder nozzle is preheated to finish filament load. ///- Tc Load to nozzle after filament was prepared by Tx and extruder nozzle is already heated. bool MMU2::tool_change(char code, uint8_t slot) { - if (!WaitForMMUReady()) + if (!WaitForMMUReady()) { return false; + } FSensorBlockRunout blockRunout; BlockEStallDetection blockEStallDetection; @@ -585,8 +595,9 @@ uint8_t MMU2::get_tool_change_tool() const { } bool MMU2::set_filament_type(uint8_t /*slot*/, uint8_t /*type*/) { - if (!WaitForMMUReady()) + if (!WaitForMMUReady()) { return false; + } // @@TODO - this is not supported in the new MMU yet // slot = slot; // @@TODO @@ -612,8 +623,9 @@ void MMU2::UnloadInner() { for (;;) { Disable_E0(); logic.UnloadFilament(); - if (manage_response(false, true)) + if (manage_response(false, true)) { break; + } IncrementMMUFails(); } MakeSound(Confirm); @@ -624,8 +636,9 @@ void MMU2::UnloadInner() { } bool MMU2::unload() { - if (!WaitForMMUReady()) + if (!WaitForMMUReady()) { return false; + } WaitForHotendTargetTempBeep(); @@ -641,15 +654,17 @@ void MMU2::CutFilamentInner(uint8_t slot) { for (;;) { Disable_E0(); logic.CutFilament(slot); - if (manage_response(false, true)) + if (manage_response(false, true)) { break; + } IncrementMMUFails(); } } bool MMU2::cut_filament(uint8_t slot, bool enableFullScreenMsg /*= true*/) { - if (!WaitForMMUReady()) + if (!WaitForMMUReady()) { return false; + } if (enableFullScreenMsg) { FullScreenMsgCut(slot); @@ -686,8 +701,9 @@ bool MMU2::loading_test(uint8_t slot) { } bool MMU2::load_filament(uint8_t slot) { - if (!WaitForMMUReady()) + if (!WaitForMMUReady()) { return false; + } FullScreenMsgLoad(slot); { @@ -695,8 +711,9 @@ bool MMU2::load_filament(uint8_t slot) { for (;;) { Disable_E0(); logic.LoadFilament(slot); - if (manage_response(false, false)) + if (manage_response(false, false)) { break; + } IncrementMMUFails(); } MakeSound(SoundType::Confirm); @@ -706,8 +723,9 @@ bool MMU2::load_filament(uint8_t slot) { } bool MMU2::load_filament_to_nozzle(uint8_t slot) { - if (!WaitForMMUReady()) + if (!WaitForMMUReady()) { return false; + } WaitForHotendTargetTempBeep(); @@ -733,8 +751,9 @@ bool MMU2::load_filament_to_nozzle(uint8_t slot) { } bool MMU2::eject_filament(uint8_t slot, bool enableFullScreenMsg /* = true */) { - if (!WaitForMMUReady()) + if (!WaitForMMUReady()) { return false; + } if (enableFullScreenMsg) { FullScreenMsgEject(slot); @@ -748,8 +767,9 @@ bool MMU2::eject_filament(uint8_t slot, bool enableFullScreenMsg /* = true */) { for (;;) { Disable_E0(); logic.EjectFilament(slot); - if (manage_response(false, true)) + if (manage_response(false, true)) { break; + } IncrementMMUFails(); } extruder = MMU2_NO_TOOL; @@ -770,8 +790,9 @@ void MMU2::Home(uint8_t mode) { } void MMU2::SaveHotendTemp(bool turn_off_nozzle) { - if (mmu_print_saved & SavedState::Cooldown) + if (mmu_print_saved & SavedState::Cooldown) { return; + } if (turn_off_nozzle && !(mmu_print_saved & SavedState::CooldownPending)) { Disable_E0(); diff --git a/lib/Marlin/Marlin/src/feature/prusa/MMU2/protocol_logic.cpp b/lib/Marlin/Marlin/src/feature/prusa/MMU2/protocol_logic.cpp index 9c6f81aa7e..61faa079c1 100644 --- a/lib/Marlin/Marlin/src/feature/prusa/MMU2/protocol_logic.cpp +++ b/lib/Marlin/Marlin/src/feature/prusa/MMU2/protocol_logic.cpp @@ -280,8 +280,9 @@ StepStatus ProtocolLogic::ScopeStep() { } } else { // we are expecting a message - if (auto expmsg = ExpectingMessage(); expmsg != MessageReady) // this whole statement takes 12B + if (auto expmsg = ExpectingMessage(); expmsg != MessageReady) { // this whole statement takes 12B return expmsg; + } // process message switch (currentScope) { @@ -725,8 +726,9 @@ void ProtocolLogic::FormatLastResponseMsgAndClearLRB(char *dst) { for (uint8_t i = 0; i < lrb; ++i) { uint8_t b = lastReceivedBytes[i]; // Check for printable character, including space - if (b < 32 || b > 127) + if (b < 32 || b > 127) { b = '.'; + } *dst++ = b; } *dst = 0; // terminate properly @@ -740,8 +742,9 @@ void ProtocolLogic::LogRequestMsg(const uint8_t *txbuff, uint8_t size) { for (uint8_t i = 0; i < size; ++i) { uint8_t b = txbuff[i]; // Check for printable character, including space - if (b < 32 || b > 127) + if (b < 32 || b > 127) { b = '.'; + } tmp[i + 1] = b; } tmp[size + 1] = 0; @@ -850,8 +853,9 @@ StepStatus ProtocolLogic::Step() { } uint8_t ProtocolLogic::CommandInProgress() const { - if (currentScope != Scope::Command) + if (currentScope != Scope::Command) { return 0; + } return (uint8_t)ReqMsg().code; } diff --git a/lib/Marlin/Marlin/src/feature/prusa/crash_recovery.cpp b/lib/Marlin/Marlin/src/feature/prusa/crash_recovery.cpp index 0173329fd0..4cc11ae169 100644 --- a/lib/Marlin/Marlin/src/feature/prusa/crash_recovery.cpp +++ b/lib/Marlin/Marlin/src/feature/prusa/crash_recovery.cpp @@ -136,8 +136,9 @@ void Crash_s::resume_movement() { } void Crash_s::restore_state() { - if (inhibit_flags & INHIBIT_PARTIAL_REPLAY) + if (inhibit_flags & INHIBIT_PARTIAL_REPLAY) { segments_finished = 0; + } if (inhibit_flags & INHIBIT_XYZ_REPOSITIONING) { // also reset internal crash locations to current_position @@ -245,25 +246,29 @@ void Crash_s::set_state(state_t new_state) { case RECOVERY: // TODO: the following checks are too broad (should check for existing state) - if (state != PRINTING && state != TRIGGERED_ISR && state != TRIGGERED_TOOLFALL && state != TRIGGERED_AC_FAULT) + if (state != PRINTING && state != TRIGGERED_ISR && state != TRIGGERED_TOOLFALL && state != TRIGGERED_AC_FAULT) { bsod("invalid recovery transition"); + } resume_movement(); break; case REPLAY: - if (state != RECOVERY) + if (state != RECOVERY) { bsod("invalid replay transition"); + } activate(); restore_state(); break; case PRINTING: - if (state != RECOVERY && state != REPEAT_WAIT && state != IDLE && state != REPLAY) + if (state != RECOVERY && state != REPEAT_WAIT && state != IDLE && state != REPLAY) { bsod("invalid printing transition"); + } homefail_z = false; reset_repeated_crash(); - if (state != REPLAY) + if (state != REPLAY) { activate(); + } break; } @@ -303,8 +308,9 @@ void Crash_s::update_machine() { } void Crash_s::enable(bool state) { - if (state == enabled) + if (state == enabled) { return; + } enabled = state; config_store().crash_enabled.set(state); update_machine(); @@ -325,8 +331,9 @@ void Crash_s::reset_crash_counter() { } void Crash_s::send_reports() { - if (axis_hit != X_AXIS && axis_hit != Y_AXIS) + if (axis_hit != X_AXIS && axis_hit != Y_AXIS) { return; + } float speed = -1; if (axis_hit == X_AXIS) { @@ -384,13 +391,15 @@ uint32_t Crash_s::clean_history() { } void Crash_s::reset_history() { - for (auto &t : crash_timestamps) + for (auto &t : crash_timestamps) { t = std::nullopt; + } } void Crash_s::count_crash() { - if (axis_hit == X_AXIS || axis_hit == Y_AXIS) + if (axis_hit == X_AXIS || axis_hit == Y_AXIS) { ++counter_crash.pos[axis_hit]; + } uint32_t valid = clean_history(); if (valid == crash_timestamps.size()) { @@ -464,8 +473,9 @@ void Crash_s::end_sensorless_homing_per_axis(const AxisEnum axis, const bool ena #if HAS_DRIVER(TMC2130) void Crash_s::set_filter(bool on) { - if (filter == on) + if (filter == on) { return; + } filter = on; config_store().crash_filter.set(on); update_machine(); diff --git a/lib/Marlin/Marlin/src/feature/prusa/measure_axis.cpp b/lib/Marlin/Marlin/src/feature/prusa/measure_axis.cpp index e9ec78bdb0..d6417f9dbb 100644 --- a/lib/Marlin/Marlin/src/feature/prusa/measure_axis.cpp +++ b/lib/Marlin/Marlin/src/feature/prusa/measure_axis.cpp @@ -45,8 +45,9 @@ Measure_axis::Measure_axis(bool measure_x, bool measure_y, xy_bool_t invert_dir, return; } - if (raise_z < 0) + if (raise_z < 0) { raise_z = Z_HOMING_HEIGHT; + } if (fr_mm_s <= 0) { fr.x = homing_feedrate(X_AXIS); @@ -125,18 +126,22 @@ void Measure_axis::sensorless_enable(AxisEnum axis) { break; #if X_SENSORLESS case X_AXIS: - if (sensitivity.has_value()) + if (sensitivity.has_value()) { stepperX.stall_sensitivity(sensitivity.value().x); - if (max_period.has_value()) + } + if (max_period.has_value()) { stepperX.stall_max_period(max_period.value().x); + } break; #endif #if Y_SENSORLESS case Y_AXIS: - if (sensitivity.has_value()) + if (sensitivity.has_value()) { stepperY.stall_sensitivity(sensitivity.value().y); - if (max_period.has_value()) + } + if (max_period.has_value()) { stepperX.stall_max_period(max_period.value().y); + } break; #endif } @@ -312,8 +317,9 @@ void Measure_axis::state_finish() { #endif break; case QUICK_HOME_XY: - if (do_x && do_y) + if (do_x && do_y) { quick_home_finish(); + } break; case MEASURE_X: save_length(X_AXIS); @@ -339,8 +345,9 @@ void Measure_axis::loop() { case FINISH: break; default: - if (!Planner::busy()) + if (!Planner::busy()) { state_next(); + } break; } } diff --git a/lib/Marlin/Marlin/src/feature/prusa/measure_axis.h b/lib/Marlin/Marlin/src/feature/prusa/measure_axis.h index af21d27a41..ba68552d0b 100644 --- a/lib/Marlin/Marlin/src/feature/prusa/measure_axis.h +++ b/lib/Marlin/Marlin/src/feature/prusa/measure_axis.h @@ -82,8 +82,9 @@ class Measure_axis { // switches to the next state void state_next() { - if (state_ >= last_) + if (state_ >= last_) { return; + } state_change(state_t(state_ + 1)); } diff --git a/lib/Marlin/Marlin/src/feature/prusa/restore_z.cpp b/lib/Marlin/Marlin/src/feature/prusa/restore_z.cpp index 5dca75d78a..d1d94a7382 100644 --- a/lib/Marlin/Marlin/src/feature/prusa/restore_z.cpp +++ b/lib/Marlin/Marlin/src/feature/prusa/restore_z.cpp @@ -20,8 +20,9 @@ static bool is_requested() { * of print. */ void restore_z::restore() { - if (!is_requested()) + if (!is_requested()) { return; + } current_position[Z_AXIS] = config_store().restore_z_after_boot.get().current_position_z; planner.set_position_mm(current_position); if (TEST(config_store().restore_z_after_boot.get().axis_known_position, Z_AXIS)) { diff --git a/lib/Marlin/Marlin/src/gcode/calibrate/G80.cpp b/lib/Marlin/Marlin/src/gcode/calibrate/G80.cpp index ce5207c48d..c3c7dcc5dd 100644 --- a/lib/Marlin/Marlin/src/gcode/calibrate/G80.cpp +++ b/lib/Marlin/Marlin/src/gcode/calibrate/G80.cpp @@ -65,6 +65,14 @@ void GcodeSuite::G80() { run_gcode("M109 S%.0f T%i", print_temp, target_extruder); // deretraction run_gcode("G1 E2 F2400"); + + + // If running in MK3 compatibility mode, we need to move z axis down to print bed. + // When running G80 in MK3 we moved the nozzle to the printbed after MBL. + // We don't do that now and the newer slicer adds G1 instruction to move the nozzle down. + if (gcode.compatibility_mode == CompatibilityMode::MK3) { + run_gcode("G1 Z0.15"); // 0.15 is value of Z_MIN_POS https://github.com/prusa3d/Prusa-Firmware/blob/MK3/Firmware/variants/MK3S.h#L67 + } } #endif diff --git a/lib/Marlin/Marlin/src/gcode/calibrate/M958.cpp b/lib/Marlin/Marlin/src/gcode/calibrate/M958.cpp index 57f80e2da0..18bc6a1108 100644 --- a/lib/Marlin/Marlin/src/gcode/calibrate/M958.cpp +++ b/lib/Marlin/Marlin/src/gcode/calibrate/M958.cpp @@ -263,8 +263,9 @@ static void enqueue_step(int step_us, bool dir, StepEventFlag_t axis_flags) { step_event_u16_t *step_event = PreciseStepping::get_next_free_step_event(next_queue_head); step_event->time_ticks = step_us; step_event->flags = axis_flags; - if (dir) + if (dir) { step_event->flags ^= STEP_EVENT_FLAG_DIR_MASK; + } PreciseStepping::step_event_queue.head = next_queue_head; CRITICAL_SECTION_END; } @@ -692,8 +693,9 @@ void GcodeSuite::M958() { MicrostepRestorer microstepRestorer; const StepEventFlag_t axis_flag = setup_axis(); // modifies mres as a side-effect const float step_len = get_step_len(axis_flag, microstepRestorer.saved_mres()); - if (isnan(step_len)) + if (isnan(step_len)) { return; + } const bool klipper_mode = parser.seen('K'); @@ -741,8 +743,9 @@ static void naive_zv_tune(StepEventFlag_t axis_flag, float start_frequency, floa for (float frequency_requested = start_frequency; frequency_requested <= end_frequency + epsilon; frequency_requested += frequency_increment) { FrequencyGain3dError frequencyGain3dError = vibrate_measure(axis_flag, false, frequency_requested, acceleration_requested, step_len, cycles, calibrate_accelerometer); - if (frequencyGain3dError.error) + if (frequencyGain3dError.error) { return; + } FrequencyGain frequencyGain = { frequencyGain3dError.frequencyGain3D.frequency, frequencyGain3dError.frequencyGain3D.gain[logicalAxis] }; calibrate_accelerometer = false; if (frequencyGain.gain > maxFrequencyGain.gain) { @@ -983,8 +986,9 @@ static input_shaper::AxisConfig find_best_shaper(const Fl_Spectrum &psd, const A }; for (input_shaper::Type shaper_type = first_type + 1; shaper_type <= input_shaper::Type::last; ++shaper_type) { - if (shaper_type == input_shaper::Type::null) + if (shaper_type == input_shaper::Type::null) { continue; + } Shaper_result shaper = fit_shaper(shaper_type, psd, progress_percent, final_action, default_config); if (shaper.score * 1.2f < best_shaper.result.score @@ -1027,8 +1031,9 @@ static void klipper_tune(const bool subtract_excitation, const StepEventFlag_t a bool calibrate_accelerometer = true; for (float frequency_requested = start_frequency; frequency_requested <= end_frequency + epsilon; frequency_requested += frequency_increment) { FrequencyGain3dError frequencyGain3dError = vibrate_measure(axis_flag, true, frequency_requested, acceleration_requested, step_len, cycles, calibrate_accelerometer); - if (frequencyGain3dError.error) + if (frequencyGain3dError.error) { return; + } calibrate_accelerometer = false; if (subtract_excitation) { frequencyGain3dError.frequencyGain3D.gain[logicalAxis] = max(frequencyGain3dError.frequencyGain3D.gain[logicalAxis] - 1.f, 0.f); @@ -1076,8 +1081,9 @@ void GcodeSuite::M959() { MicrostepRestorer microstepRestorer; StepEventFlag_t axis_flag = setup_axis(); // modifies mres as a side-effect const float step_len = get_step_len(axis_flag, microstepRestorer.saved_mres()); - if (isnan(step_len)) + if (isnan(step_len)) { return; + } const bool seen_m = parser.seen('M'); diff --git a/lib/Marlin/Marlin/src/gcode/feature/input_shaper/M593.cpp b/lib/Marlin/Marlin/src/gcode/feature/input_shaper/M593.cpp index 6ae836529e..5d568f0ad4 100644 --- a/lib/Marlin/Marlin/src/gcode/feature/input_shaper/M593.cpp +++ b/lib/Marlin/Marlin/src/gcode/feature/input_shaper/M593.cpp @@ -165,50 +165,56 @@ void GcodeSuite::M593() { if (parser.seen('D')) { const float dr = parser.value_float(); - if (WITHIN(dr, 0., 1.)) + if (WITHIN(dr, 0., 1.)) { params.axis.damping_ratio = dr; - else + } else { SERIAL_ECHO_MSG("?Damping ratio (D) value out of range (0-1)"); + } } if (parser.seen('F')) { const float f = parser.value_float(); - if (f >= 0) + if (f >= 0) { params.axis.frequency = f; - else + } else { SERIAL_ECHO_MSG("?Frequency (X) must be greater or equal to 0"); + } } if (parser.seen('T')) { const int t = parser.value_int(); - if (WITHIN(t, 0, (int)input_shaper::Type::last)) + if (WITHIN(t, 0, (int)input_shaper::Type::last)) { params.axis.type = static_cast(t); - else + } else { SERIAL_ECHO_MSG("?Invalid type of input shaper (T)"); + } } if (parser.seen('R')) { const float vr = parser.value_float(); - if (vr > 0) + if (vr > 0) { params.axis.vibration_reduction = vr; - else + } else { SERIAL_ECHO_MSG("?Vibration reduction (X) must be greater than 0"); + } } if (parser.seen('A')) { const float a = parser.value_float(); - if (a < 0) + if (a < 0) { params.weight_adjust.frequency_delta = a; - else + } else { SERIAL_ECHO_MSG("?Weight adjust frequency delta (A) must be lesser than 0"); + } } if (parser.seen('M')) { const float m = parser.value_float(); - if (m >= 0) + if (m >= 0) { params.weight_adjust.mass_limit = m; - else + } else { SERIAL_ECHO_MSG("?Weight adjust mass limit (M) must be greater or equal to 0"); + } } input_shaper::M593_internal(params); diff --git a/lib/Marlin/Marlin/src/gcode/feature/input_shaper/M74.cpp b/lib/Marlin/Marlin/src/gcode/feature/input_shaper/M74.cpp index 47ed4b519d..2dc8a3bf7a 100644 --- a/lib/Marlin/Marlin/src/gcode/feature/input_shaper/M74.cpp +++ b/lib/Marlin/Marlin/src/gcode/feature/input_shaper/M74.cpp @@ -48,10 +48,10 @@ void GcodeSuite::M74() { if (parser.seen('W')) { const float m = parser.value_float(); - if (m > 0) { + if (m >= 0.f) { params.mass = m; } else { - SERIAL_ECHO_MSG("?Mass (W) must be greater than 0"); + SERIAL_ECHO_MSG("?Mass (W) must be greater or equal 0"); } } diff --git a/lib/Marlin/Marlin/src/gcode/feature/pressure_advance/M572.cpp b/lib/Marlin/Marlin/src/gcode/feature/pressure_advance/M572.cpp index b430007173..7ed0339d6f 100644 --- a/lib/Marlin/Marlin/src/gcode/feature/pressure_advance/M572.cpp +++ b/lib/Marlin/Marlin/src/gcode/feature/pressure_advance/M572.cpp @@ -50,18 +50,20 @@ void GcodeSuite::M572() { if (seen_s) { const float s = parser.value_float(); - if (WITHIN(s, 0.f, 10.f)) + if (WITHIN(s, 0.f, 10.f)) { pressure_advance = s; - else + } else { SERIAL_ECHO_MSG("?Pressure advance (S) value out of range (0-10)"); + } } if (seen_w) { const float w = parser.value_float(); - if (WITHIN(w, 0.f, 0.2f)) + if (WITHIN(w, 0.f, 0.2f)) { smooth_time = w; - else + } else { SERIAL_ECHO_MSG("?Pressure advance smooth time (W) value out of range (0-0.2)"); + } } M572_internal(pressure_advance, smooth_time); diff --git a/lib/Marlin/Marlin/src/gcode/feature/prusa/MMU2/M403.cpp b/lib/Marlin/Marlin/src/gcode/feature/prusa/MMU2/M403.cpp index 12d85ec7d7..af24be78d4 100644 --- a/lib/Marlin/Marlin/src/gcode/feature/prusa/MMU2/M403.cpp +++ b/lib/Marlin/Marlin/src/gcode/feature/prusa/MMU2/M403.cpp @@ -40,10 +40,11 @@ void GcodeSuite::M403() { int8_t index = parser.intval('E', -1), type = parser.intval('F', -1); - if (WITHIN(index, 0, 4) && WITHIN(type, 0, 2)) + if (WITHIN(index, 0, 4) && WITHIN(type, 0, 2)) { MMU2::mmu2.set_filament_type(index, type); - else + } else { SERIAL_ECHO_MSG("M403 - bad arguments."); + } } #endif // PRUSA_MMU2 diff --git a/lib/Marlin/Marlin/src/gcode/gcode.cpp b/lib/Marlin/Marlin/src/gcode/gcode.cpp index 43d0a26ea2..8f10bbd960 100644 --- a/lib/Marlin/Marlin/src/gcode/gcode.cpp +++ b/lib/Marlin/Marlin/src/gcode/gcode.cpp @@ -801,6 +801,8 @@ void GcodeSuite::process_parsed_command(const bool no_ok/*=false*/) { case 602: M602(); break; // M602: Unpark & UnPause print case 603: M603(); break; // M603: Configure Filament Change #endif + + case 604: M604(); break; // M604: Abort (serial) print #if HAS_DUPLICATION_MODE case 605: M605(); break; // M605: Set Dual X Carriage movement mode diff --git a/lib/Marlin/Marlin/src/gcode/gcode.h b/lib/Marlin/Marlin/src/gcode/gcode.h index e3b9f1c700..ab52664744 100644 --- a/lib/Marlin/Marlin/src/gcode/gcode.h +++ b/lib/Marlin/Marlin/src/gcode/gcode.h @@ -228,6 +228,7 @@ * M601 - Pause and park print-head in marlin's defined position. (Requires ADVANCED_PAUSE_FEATURE) * M602 - Unpark print-head parked with M601 called before and unpause print process. (Requires ADVANCED_PAUSE_FEATURE) * M603 - Configure filament change: "M603 T U L". (Requires ADVANCED_PAUSE_FEATURE) + * M604 - Abort (serial) print * M605 - Set Dual X-Carriage movement mode: "M605 S [X] [R]". (Requires DUAL_X_CARRIAGE) * M665 - Set delta configurations: "M665 H L R S B X Y Z (Requires DELTA) * M666 - Set/get offsets for delta (Requires DELTA) or dual endstops (Requires [XYZ]_DUAL_ENDSTOPS). @@ -899,6 +900,7 @@ class GcodeSuite { static void M602(); static void M603(); #endif + static void M604(); #if HAS_DUPLICATION_MODE static void M605(); diff --git a/lib/Marlin/Marlin/src/gcode/lcd/M73_PE.cpp b/lib/Marlin/Marlin/src/gcode/lcd/M73_PE.cpp index defb5e1926..b52f431374 100644 --- a/lib/Marlin/Marlin/src/gcode/lcd/M73_PE.cpp +++ b/lib/Marlin/Marlin/src/gcode/lcd/M73_PE.cpp @@ -6,112 +6,120 @@ #include "M73_PE.h" #include "../Marlin/src/libs/stopwatch.h" +#include "marlin_vars.hpp" extern Stopwatch print_job_timer; - ClProgressData oProgressData; - -void ClValidityValue::mInit(void) -{ -//nTime=0; -bIsUsed=false; +void ClValidityValue::mInit(void) { + // nTime=0; + bIsUsed = false; } -void ClValidityValue::mSetValue(uint32_t nN,uint32_t nNow) -{ -nValue=nN; -nTime=nNow; -bIsUsed=true; +void ClValidityValue::mSetValue(uint32_t nN, uint32_t nNow) { + nValue = nN; + nTime = nNow; + bIsUsed = true; } -uint32_t ClValidityValue::mGetValue(void) -{ -return(nValue); +uint32_t ClValidityValue::mGetValue(void) { + return (nValue); } -bool ClValidityValue::mIsActual(uint32_t nNow) -{ -return(mIsActual(nNow,PROGRESS_DATA_VALIDITY_PERIOD)); +bool ClValidityValue::mIsActual(uint32_t nNow) { + return (mIsActual(nNow, PROGRESS_DATA_VALIDITY_PERIOD)); } -bool ClValidityValue::mIsActual(uint32_t nNow,uint16_t nPeriod) -{ -//return((nTime+nPeriod)>=nNow); -return(mIsUsed()&&((nTime+nPeriod)>=nNow)); +bool ClValidityValue::mIsActual(uint32_t nNow, uint16_t nPeriod) { + // return((nTime+nPeriod)>=nNow); + return (mIsUsed() && ((nTime + nPeriod) >= nNow)); } -bool ClValidityValue::mIsUsed(void) -{ -//return(nTime>0); -return(bIsUsed); +bool ClValidityValue::mIsUsed(void) { + // return(nTime>0); + return (bIsUsed); } - -void ClValidityValueSec::mFormatSeconds(char *sStr,uint16_t nFeedrate) -{ -uint8_t nDay,nHour,nMin; -uint32_t nRest; - -nRest=(nValue*100)/nFeedrate; -nDay=nRest/(60*60*24); -nRest=nRest%(60*60*24); -nHour=nRest/(60*60); -nRest=nRest%(60*60); -nMin=nRest/60; -if(nDay>0) - sprintf_P(sStr,PSTR("%dd %dh"),nDay,nHour); -else if(nHour>0) - sprintf_P(sStr,PSTR("%dh %dm"),nHour,nMin); - else sprintf_P(sStr,PSTR("%dm"),nMin); +void ClValidityValueSec::mFormatSeconds(char *sStr, uint16_t nFeedrate) { + uint8_t nDay, nHour, nMin; + uint32_t nRest; + + nRest = (nValue * 100) / nFeedrate; + nDay = nRest / (60 * 60 * 24); + nRest = nRest % (60 * 60 * 24); + nHour = nRest / (60 * 60); + nRest = nRest % (60 * 60); + nMin = nRest / 60; + if (nDay > 0) { + sprintf_P(sStr, PSTR("%dd %dh"), nDay, nHour); + } else if (nHour > 0) { + sprintf_P(sStr, PSTR("%dh %dm"), nHour, nMin); + } else { + sprintf_P(sStr, PSTR("%dm"), nMin); + } } - -void ClProgressData::mInit(void) -{ -oPercentDirectControl.mInit(); -oPercentDone.mInit(); -oTime2End.mInit(); -oTime2Pause.mInit(); +void ClProgressData::mInit(void) { + oPercentDirectControl.mInit(); + oPercentDone.mInit(); + oTime2End.mInit(); + oTime2Pause.mInit(); } #if ENABLED(M73_PRUSA) -void GcodeSuite::M73_PE() -{ -std::optional P = std::nullopt; -std::optional R = std::nullopt; -std::optional T = std::nullopt; -if (parser.seen('P')) P = parser.value_byte(); -if (parser.seen('R')) R = parser.value_ulong()*60; -if (parser.seen('T')) T = parser.value_ulong()*60; - -M73_PE_no_parser(P, R, T); +void GcodeSuite::M73_PE() { + std::optional P = std::nullopt; + std::optional R = std::nullopt; + std::optional T = std::nullopt; + if (parser.seen('P')) { + P = parser.value_byte(); + } + if (parser.seen('R')) { + R = parser.value_ulong() * 60; + } + if (parser.seen('T')) { + T = parser.value_ulong() * 60; + } + + M73_PE_no_parser(P, R, T); } -void M73_PE_no_parser(std::optional P, std::optional R, std::optional T) -{ -uint32_t nTimeNow; -uint8_t nValue; - -//ui.set_progress_time(...); -nTimeNow=print_job_timer.duration(); // !!! [s] -if(P) - { - nValue=*P; - if(R) - { - oProgressData.oPercentDone.mSetValue((uint32_t)nValue,nTimeNow); - oProgressData.oTime2End.mSetValue(*R,nTimeNow); // [min] -> [s] - } - else { - oProgressData.oPercentDirectControl.mSetValue((uint32_t)nValue,nTimeNow); - } - } - -if(T) - { - oProgressData.oTime2Pause.mSetValue(*T,nTimeNow); // [min] -> [s] - } +void M73_PE_no_parser(std::optional P, std::optional R, std::optional T) { + uint32_t nTimeNow; + uint8_t nValue; + + // ui.set_progress_time(...); + nTimeNow = print_job_timer.duration(); // !!! [s] + if (P) { + nValue = *P; + if (R) { + oProgressData.oPercentDone.mSetValue((uint32_t)nValue, nTimeNow); + oProgressData.oTime2End.mSetValue(*R, nTimeNow); // [min] -> [s] + } else { + oProgressData.oPercentDirectControl.mSetValue((uint32_t)nValue, nTimeNow); + } + } + + if (T) { + oProgressData.oTime2Pause.mSetValue(*T, nTimeNow); // [min] -> [s] + } + + // Print progress report. Do not remove as third party tools might depend on this + if (!P && !R && !T) { + SERIAL_ECHO_START(); + SERIAL_ECHOLNPAIR(" M73 Progress: ", marlin_vars()->sd_percent_done, "%;"); + const uint32_t time_to_end = marlin_vars_t().time_to_end; + if (time_to_end != marlin_server::TIME_TO_END_INVALID) { + SERIAL_ECHOPAIR(" Time left: ", time_to_end / 60, "m;"); + SERIAL_EOL(); + } + const uint32_t time_to_pause = oProgressData.oTime2Pause.mGetValue(); + if (time_to_pause != marlin_server::TIME_TO_END_INVALID) { + const int print_speed = marlin_vars()->print_speed; + SERIAL_ECHOPAIR(" Change: ", print_speed > 0 ? ((time_to_pause * 100) / print_speed) / 60 : 0, "m;"); + SERIAL_EOL(); + } + } } #endif diff --git a/lib/Marlin/Marlin/src/gcode/lcd/M73_PE.h b/lib/Marlin/Marlin/src/gcode/lcd/M73_PE.h index 580826d4df..c54a711662 100644 --- a/lib/Marlin/Marlin/src/gcode/lcd/M73_PE.h +++ b/lib/Marlin/Marlin/src/gcode/lcd/M73_PE.h @@ -8,49 +8,43 @@ #if PRINTER_IS_PRUSA_XL // XL needs more time for initial 5 tool preheat/cleanup and MBL - #define PROGRESS_DATA_VALIDITY_PERIOD (60*10) // [s] ~ 10min + #define PROGRESS_DATA_VALIDITY_PERIOD (60 * 10) // [s] ~ 10min #else - #define PROGRESS_DATA_VALIDITY_PERIOD (60*5) // [s] ~ 5min + #define PROGRESS_DATA_VALIDITY_PERIOD (60 * 5) // [s] ~ 5min #endif -class ClValidityValue -{ +class ClValidityValue { protected: -uint32_t nValue; -uint32_t nTime=0; // [s] -bool bIsUsed=false; + uint32_t nValue; + uint32_t nTime = 0; // [s] + bool bIsUsed = false; public: -void mSetValue(uint32_t nN,uint32_t nNow); -uint32_t mGetValue(void); -void mInit(void); -bool mIsActual(uint32_t nNow); -bool mIsActual(uint32_t nNow,uint16_t nPeriod); -bool mIsUsed(void); -//void mFormatSeconds(char *sStr,uint16_t nFeedrate); + void mSetValue(uint32_t nN, uint32_t nNow); + uint32_t mGetValue(void); + void mInit(void); + bool mIsActual(uint32_t nNow); + bool mIsActual(uint32_t nNow, uint16_t nPeriod); + bool mIsUsed(void); + // void mFormatSeconds(char *sStr,uint16_t nFeedrate); }; - -class ClValidityValueSec : public ClValidityValue -{ +class ClValidityValueSec : public ClValidityValue { public: -void mFormatSeconds(char *sStr,uint16_t nFeedrate); + void mFormatSeconds(char *sStr, uint16_t nFeedrate); }; - -class ClProgressData -{ +class ClProgressData { public: -ClValidityValue oPercentDirectControl; -ClValidityValue oPercentDone; -ClValidityValueSec oTime2End; -ClValidityValueSec oTime2Pause; + ClValidityValue oPercentDirectControl; + ClValidityValue oPercentDone; + ClValidityValueSec oTime2End; + ClValidityValueSec oTime2Pause; public: -void mInit(void); + void mInit(void); }; - extern ClProgressData oProgressData; void M73_PE_no_parser(std::optional P = std::nullopt, std::optional R = std::nullopt, std::optional T = std::nullopt); diff --git a/lib/Marlin/Marlin/src/gcode/queue.cpp b/lib/Marlin/Marlin/src/gcode/queue.cpp index de098417d9..410a4b7522 100644 --- a/lib/Marlin/Marlin/src/gcode/queue.cpp +++ b/lib/Marlin/Marlin/src/gcode/queue.cpp @@ -72,6 +72,7 @@ char GCodeQueue::command_buffer[BUFSIZE][MAX_CMD_SIZE]; uint32_t GCodeQueue::sdpos = GCodeQueue::SDPOS_INVALID; uint32_t GCodeQueue::sdpos_buffer[BUFSIZE]; +bool GCodeQueue::pause_serial_commands = false; /* * The port that the command was received on @@ -611,7 +612,8 @@ void GCodeQueue::get_serial_commands() { */ void GCodeQueue::get_available_commands() { - get_serial_commands(); + if (!pause_serial_commands) + get_serial_commands(); #if ENABLED(SDSUPPORT) get_sdcard_commands(); diff --git a/lib/Marlin/Marlin/src/gcode/queue.h b/lib/Marlin/Marlin/src/gcode/queue.h index e77de75fa6..c1ac02b905 100644 --- a/lib/Marlin/Marlin/src/gcode/queue.h +++ b/lib/Marlin/Marlin/src/gcode/queue.h @@ -59,6 +59,9 @@ class GCodeQueue { static uint32_t sdpos; // Position in file for the latest instruction static uint32_t sdpos_buffer[BUFSIZE]; // Ring buffer of positions (synced with command_buffer) + /// True pauses processing of serial commands. + static bool pause_serial_commands; + // Return the file position of the _current_ instruction static uint32_t get_current_sdpos() { return length ? sdpos_buffer[index_r] : sdpos; diff --git a/lib/Marlin/Marlin/src/module/prusa/accelerometer_remote.cpp b/lib/Marlin/Marlin/src/module/prusa/accelerometer_remote.cpp index f3d505c425..a63567fca1 100644 --- a/lib/Marlin/Marlin/src/module/prusa/accelerometer_remote.cpp +++ b/lib/Marlin/Marlin/src/module/prusa/accelerometer_remote.cpp @@ -67,8 +67,9 @@ PrusaAccelerometer::~PrusaAccelerometer() { case Error::corrupted_sample_overrun: case Error::corrupted_transmission_error: { buddy::puppies::Dwarf *dwarf = prusa_toolchanger.get_marlin_picked_tool(); - if (!dwarf) + if (!dwarf) { return; + } if (!dwarf->set_accelerometer(false)) { SERIAL_ERROR_MSG("Failed to disable accelerometer, communication error"); } diff --git a/lib/Marlin/Marlin/src/module/prusa/homing_cart.cpp b/lib/Marlin/Marlin/src/module/prusa/homing_cart.cpp index d6a4f37366..765f55017f 100644 --- a/lib/Marlin/Marlin/src/module/prusa/homing_cart.cpp +++ b/lib/Marlin/Marlin/src/module/prusa/homing_cart.cpp @@ -69,8 +69,9 @@ static int calibrated_offset_mscnt(const AxisEnum axis, const int mscnt, bool &c float calibrated_home_offset(const AxisEnum axis) { bool calibrated; const int cal = get_calibrated_home(axis, calibrated); - if (!calibrated) + if (!calibrated) { return 0; + } const constexpr float steps_per_unit[] = DEFAULT_AXIS_STEPS_PER_UNIT; switch (axis) { @@ -110,8 +111,9 @@ static int32_t home_and_get_calibration_offset(AxisEnum axis, int axis_home_dir, } calibration_offset = calibrated_offset_mscnt(axis, mscnt, calibrated); - if (!calibrated) + if (!calibrated) { calibration_offset = 0; + } SERIAL_ECHO_START(); SERIAL_ECHOPAIR(" homing probe offset: ", probe_offset); diff --git a/lib/Marlin/Marlin/src/module/prusa/homing_corexy.cpp b/lib/Marlin/Marlin/src/module/prusa/homing_corexy.cpp index d5d9af6f51..55a49783ff 100644 --- a/lib/Marlin/Marlin/src/module/prusa/homing_corexy.cpp +++ b/lib/Marlin/Marlin/src/module/prusa/homing_corexy.cpp @@ -91,8 +91,9 @@ static int16_t phase_backoff_steps(const AxisEnum axis) { int16_t phaseCurrent = stepper_axis(axis).MSCNT(); // The TMC µsteps(phase) count of the current position int16_t phaseDelta = (0 - phaseCurrent) * stepperBackoutDir; - if (phaseDelta < 0) + if (phaseDelta < 0) { phaseDelta += 1024; + } return int16_t(phaseDelta / phase_per_ustep(axis)) * effectorBackoutDir; } @@ -216,8 +217,9 @@ static measure_phase_cycles_ret measure_phase_cycles(int32_t &c_dist_a, int32_t m_dist[slot].a = -m_dist[slot].a; if (ABS(m_dist[slot].a - m_dist[slot2].a) < XY_HOMING_ORIGIN_BUMPS_MAX_ERR - && ABS(m_dist[slot].b - m_dist[slot2].b) < XY_HOMING_ORIGIN_BUMPS_MAX_ERR) + && ABS(m_dist[slot].b - m_dist[slot2].b) < XY_HOMING_ORIGIN_BUMPS_MAX_ERR) { break; + } } if (retry == XY_HOMING_ORIGIN_MAX_RETRIES) { ui.status_printf_P(0, "Precise refinement failed"); // User is most likely to get this version of ERR_MECHANICAL_PRECISE_REFINEMENT_FAILED @@ -233,8 +235,9 @@ static measure_phase_cycles_ret measure_phase_cycles(int32_t &c_dist_a, int32_t c_dist_a = (d + c_steps_a) / (2 * c_steps_a); int32_t d_y = d - (m_steps[0].b + m_steps[1].b); int32_t d_y2 = abs(d_y) + c_steps_b; - if (d_y < 0) + if (d_y < 0) { d_y2 = -d_y2; + } c_dist_b = d_y2 / (2 * c_steps_b); if (DEBUGGING(LEVELING)) { @@ -257,8 +260,9 @@ static bool wait_for_standstill(uint8_t axis_mask, millis_t max_delay = 150) { } } } - if (stst) + if (stst) { return true; + } if (millis() > timeout || planner.draining()) { return false; } @@ -298,8 +302,9 @@ bool refine_corexy_origin() { // sanity checks wait_for_standstill(_BV(A_AXIS) | _BV(B_AXIS)); if (!phase_aligned(A_AXIS) || !phase_aligned(B_AXIS)) { - if (planner.draining()) + if (planner.draining()) { return true; + } SERIAL_ECHOLN("phase alignment failed"); SERIAL_ECHOLNPAIR("phase A:", stepperX.MSCNT(), " B:", stepperY.MSCNT()); diff --git a/lib/Marlin/Marlin/src/module/prusa/homing_modus.cpp b/lib/Marlin/Marlin/src/module/prusa/homing_modus.cpp index 13df66d0bb..407092b7b6 100644 --- a/lib/Marlin/Marlin/src/module/prusa/homing_modus.cpp +++ b/lib/Marlin/Marlin/src/module/prusa/homing_modus.cpp @@ -7,10 +7,12 @@ /// @return -512 .. +512 int to_calibrated(const int calibrated, const int value) { const int diff = calibrated - value; - if (std::abs(diff) <= 512) + if (std::abs(diff) <= 512) { return diff; - if (diff < 0) + } + if (diff < 0) { return 1024 + diff; + } return diff - 1024; } diff --git a/lib/Marlin/Marlin/src/module/prusa/homing_utils.cpp b/lib/Marlin/Marlin/src/module/prusa/homing_utils.cpp index 8d938c3aa6..c0e3f74061 100644 --- a/lib/Marlin/Marlin/src/module/prusa/homing_utils.cpp +++ b/lib/Marlin/Marlin/src/module/prusa/homing_utils.cpp @@ -29,24 +29,27 @@ static workspace_xyz_t disable_workspace(bool do_x, bool do_y, bool do_z) { changed = true; } - if (changed) + if (changed) { sync_plan_position(); + } return res; } #endif // HAS_WORKSPACE_OFFSET bool disable_modifiers_if(bool condition, bool do_z) { - if (!condition) + if (!condition) { return false; + } bool leveling_was_active = false; #if HAS_LEVELING #if ENABLED(RESTORE_LEVELING_AFTER_G28) leveling_was_active = planner.leveling_active; #else - if (!do_z) + if (!do_z) { leveling_was_active = planner.leveling_active; + } #endif set_bed_leveling_enabled(false); #endif @@ -61,16 +64,18 @@ bool disable_modifiers_if(bool condition, bool do_z) { } void enable_modifiers_if(bool condition, bool restore_leveling) { - if (!condition) + if (!condition) { return; + } #if ENABLED(SKEW_CORRECTION) skew(current_position); #endif #if HAS_LEVELING - if (restore_leveling) + if (restore_leveling) { set_bed_leveling_enabled(true); + } #endif sync_plan_position(); } @@ -78,8 +83,9 @@ void enable_modifiers_if(bool condition, bool restore_leveling) { Motion_Parameters reset_acceleration_if(bool condition) { Motion_Parameters mp; mp.save(); - if (!condition) + if (!condition) { return mp; + } mp.reset(); @@ -96,8 +102,9 @@ Motion_Parameters reset_acceleration_if(bool condition) { } void restore_acceleration_if(bool condition, Motion_Parameters &mp) { - if (!condition) + if (!condition) { return; + } restore_feedrate_and_scaling(); mp.load(); @@ -106,8 +113,9 @@ void restore_acceleration_if(bool condition, Motion_Parameters &mp) { el_current_xyz_t reset_current_if(bool condition) { el_current_xyz_t curr = { stepperX.rms_current(), stepperY.rms_current(), stepperZ.rms_current() }; - if (!condition) + if (!condition) { return curr; + } stepperX.rms_current(get_default_rms_current_ma_x()); stepperY.rms_current(get_default_rms_current_ma_y()); @@ -116,8 +124,9 @@ el_current_xyz_t reset_current_if(bool condition) { } void restore_current_if(bool condition, el_current_xyz_t current) { - if (!condition) + if (!condition) { return; + } stepperX.rms_current(current.x); stepperY.rms_current(current.y); diff --git a/lib/Marlin/Marlin/src/module/prusa/spool_join.cpp b/lib/Marlin/Marlin/src/module/prusa/spool_join.cpp index c7b7d7b761..3aa26fcf42 100644 --- a/lib/Marlin/Marlin/src/module/prusa/spool_join.cpp +++ b/lib/Marlin/Marlin/src/module/prusa/spool_join.cpp @@ -39,8 +39,9 @@ void SpoolJoin::reset() { } bool SpoolJoin::add_join(uint8_t spool_1, uint8_t spool_2) { - if (num_joins >= joins.size() || !is_tool_enabled(spool_1) || !is_tool_enabled(spool_2) || spool_1 == spool_2) + if (num_joins >= joins.size() || !is_tool_enabled(spool_1) || !is_tool_enabled(spool_2) || spool_1 == spool_2) { return false; + } // join will be added at the end of existing joins, so when for example // 0 will join with 1, and we want to join0 with 2, actual join created will be 1 -> 2, @@ -58,8 +59,9 @@ bool SpoolJoin::add_join(uint8_t spool_1, uint8_t spool_2) { } // check again that we are not joining spool with itself - spool_1 might have changed above - if (spool_1 == spool_2) + if (spool_1 == spool_2) { return false; + } for (auto &join : joins) { if (join.spool_2 == spool_2) { @@ -170,8 +172,9 @@ uint8_t SpoolJoin::get_first_spool_1_from_chain(uint8_t spool_2) const { std::optional SpoolJoin::get_spool_2(uint8_t tool) const { for (size_t i = 0; i < num_joins; i++) { - if (joins[i].spool_1 == tool) + if (joins[i].spool_1 == tool) { return joins[i].spool_2; + } } return std::nullopt; diff --git a/lib/Marlin/Marlin/src/module/prusa/tool_mapper.cpp b/lib/Marlin/Marlin/src/module/prusa/tool_mapper.cpp index c3ba133e38..47861729bb 100644 --- a/lib/Marlin/Marlin/src/module/prusa/tool_mapper.cpp +++ b/lib/Marlin/Marlin/src/module/prusa/tool_mapper.cpp @@ -59,10 +59,11 @@ void ToolMapper::set_enable(bool enable) { } uint8_t ToolMapper::to_physical(uint8_t logical, bool ignore_enabled) const { - if ((ignore_enabled || enabled) && logical < std::size(gcode_to_physical)) + if ((ignore_enabled || enabled) && logical < std::size(gcode_to_physical)) { return gcode_to_physical[logical]; - else + } else { return logical; // no maping + } } uint8_t ToolMapper::to_gcode(uint8_t physical) const { diff --git a/lib/Marlin/Marlin/src/module/prusa/toolchanger.cpp b/lib/Marlin/Marlin/src/module/prusa/toolchanger.cpp index 8cc7d5de89..f36f412fa0 100644 --- a/lib/Marlin/Marlin/src/module/prusa/toolchanger.cpp +++ b/lib/Marlin/Marlin/src/module/prusa/toolchanger.cpp @@ -197,8 +197,9 @@ void tool_change(const uint8_t new_tool, } // if we don't know position of all axes, do not return to current position - if (return_type == tool_return_t::to_current && !all_axes_known()) + if (return_type == tool_return_t::to_current && !all_axes_known()) { return_type = tool_return_t::no_return; + } // Change tool, ignore return as Marlin doesn't care bool ret [[maybe_unused]] = prusa_toolchanger.tool_change(new_tool, return_type, return_position, z_lift, z_return); @@ -301,8 +302,9 @@ bool PrusaToolChanger::tool_change(const uint8_t new_tool, tool_return_t return_ z_raise += tool_offset_diff.z; } - if (z_raise > 0) + if (z_raise > 0) { z_shift(z_raise); + } // Home X and Y if needed if (!ensure_safe_move()) { @@ -353,8 +355,9 @@ bool PrusaToolChanger::tool_change(const uint8_t new_tool, tool_return_t return_ } if (return_type == tool_return_t::purge_and_to_destination) { - if (!purge_tool(*new_dwarf)) + if (!purge_tool(*new_dwarf)) { return false; + } } } @@ -508,10 +511,12 @@ bool PrusaToolChanger::purge_tool(Dwarf &dwarf) { // restore fan speed Fans::print(tool_nr).setPWM(thermalManager.fan_speed[tool_nr]); - if (!park(dwarf)) + if (!park(dwarf)) { return false; - if (!pickup(dwarf)) + } + if (!pickup(dwarf)) { return false; + } return true; } @@ -570,8 +575,9 @@ void PrusaToolChanger::loop(bool printing, bool paused) { // Update the currently applied offset when idling (so that a manual swap is reflected), but // _not_ during print where toolchange() is in charge to do the heavy lifting if (!printing) { - if (active_extruder != MARLIN_NO_TOOL_PICKED) + if (active_extruder != MARLIN_NO_TOOL_PICKED) { hotend_currently_applied_offset = hotend_offset[active_extruder]; + } } } diff --git a/lib/Marlin/Marlin/src/module/temperature.cpp b/lib/Marlin/Marlin/src/module/temperature.cpp index e27907de65..2159b9c39d 100644 --- a/lib/Marlin/Marlin/src/module/temperature.cpp +++ b/lib/Marlin/Marlin/src/module/temperature.cpp @@ -884,7 +884,7 @@ void Temperature::max_temp_error(const heater_ind_t heater) { #if HAS_TEMP_HEATBREAK //we have multiple heartbreak thermistors and they have always the highest ID if(heater >= H_HEATBREAK_E0){ - _temp_error(heater, PSTR(MSG_T_MINTEMP), GET_TEXT(MSG_ERR_MAXTEMP_HEATBREAK)); + _temp_error(heater, PSTR(MSG_T_MAXTEMP), GET_TEXT(MSG_ERR_MAXTEMP_HEATBREAK)); } #endif _temp_error(heater, PSTR(MSG_T_MAXTEMP), GET_TEXT(MSG_ERR_MAXTEMP)); diff --git a/lib/Marlin/Marlin/src/module/temperature.h b/lib/Marlin/Marlin/src/module/temperature.h index cb15de645f..45814c512f 100644 --- a/lib/Marlin/Marlin/src/module/temperature.h +++ b/lib/Marlin/Marlin/src/module/temperature.h @@ -934,9 +934,9 @@ class Temperature { last_e_position = 0; #endif #if ENABLED(PRUSA_TOOLCHANGER) - // Set all dwarfs with PID parameters of the first hotend + // Set PID parameters to all dwarves HOTEND_LOOP() { - buddy::puppies::dwarfs[e].set_pid(Temperature::temp_hotend[0].pid.Kp, Temperature::temp_hotend[0].pid.Ki, Temperature::temp_hotend[0].pid.Kd); + buddy::puppies::dwarfs[e].set_pid(Temperature::temp_hotend[e].pid.Kp, Temperature::temp_hotend[e].pid.Ki, Temperature::temp_hotend[e].pid.Kd); } #endif /*HAS_DWARF()*/ } diff --git a/lib/Prusa-Error-Codes/.gitrepo b/lib/Prusa-Error-Codes/.gitrepo index 59657fe659..2aaa56c826 100644 --- a/lib/Prusa-Error-Codes/.gitrepo +++ b/lib/Prusa-Error-Codes/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = git@github.com:prusa3d/Prusa-Error-Codes.git branch = master - commit = 95837d125fd5bbc1ab98b628b21a6f0c809f6bdb - parent = 76ed1e965faf4d237df6e95683b2acc236ede19e + commit = 14b01d0fe3d55bb895d27515ceb747939ae01396 + parent = 56082083aaf9c1aa12bd6045727252ed2d3723f1 method = merge cmdver = 0.4.6 diff --git a/lib/Prusa-Error-Codes/12_MINI/error-codes.yaml b/lib/Prusa-Error-Codes/12_MINI/error-codes.yaml index a7eb499b36..55a543a172 100644 --- a/lib/Prusa-Error-Codes/12_MINI/error-codes.yaml +++ b/lib/Prusa-Error-Codes/12_MINI/error-codes.yaml @@ -75,6 +75,11 @@ Errors: text: "Check the heatbreak thermistor wiring for possible damage." id: "HEATBREAK_MAXTEMP_ERR" approved: true +- code: "12213" + title: "MCU MAXTEMP ERROR" + text: "MCU in %s is overheated." + id: "MCU_MAXTEMP_ERR" + approved: false # XX250-XX257 reserved - code: "12301" title: "HOMING ERROR Z" diff --git a/lib/Prusa-Error-Codes/13_MK4/error-codes.yaml b/lib/Prusa-Error-Codes/13_MK4/error-codes.yaml index 4dbbfbbff4..1042adab73 100644 --- a/lib/Prusa-Error-Codes/13_MK4/error-codes.yaml +++ b/lib/Prusa-Error-Codes/13_MK4/error-codes.yaml @@ -98,6 +98,12 @@ Errors: id: "HEATBREAK_MAXTEMP_ERR" approved: true +- code: "13213" + title: "MCU MAXTEMP ERROR" + text: "MCU in %s is overheated." + id: "MCU_MAXTEMP_ERR" + approved: false + # XX250-XX257 reserved # ELECTRICAL xx3xx diff --git a/lib/Prusa-Error-Codes/16_iX/error-codes.yaml b/lib/Prusa-Error-Codes/16_iX/error-codes.yaml index 56b6fffb48..28efde660d 100644 --- a/lib/Prusa-Error-Codes/16_iX/error-codes.yaml +++ b/lib/Prusa-Error-Codes/16_iX/error-codes.yaml @@ -81,6 +81,11 @@ Errors: text: "Check the heatbreak thermistor wiring for possible damage." id: "HEATBREAK_MAXTEMP_ERR" approved: true +- code: "16213" + title: "MCU MAXTEMP ERROR" + text: "MCU in %s is overheated." + id: "MCU_MAXTEMP_ERR" + approved: false - code: "16250" title: "MODULAR BED ERROR" text: "Heatbed tile no. %d:\nDamaged tile or wiring.\nFollow online guide to diagnose." diff --git a/lib/Prusa-Error-Codes/17_XL/error-codes.yaml b/lib/Prusa-Error-Codes/17_XL/error-codes.yaml index 0333f020b9..b511fd9cc3 100644 --- a/lib/Prusa-Error-Codes/17_XL/error-codes.yaml +++ b/lib/Prusa-Error-Codes/17_XL/error-codes.yaml @@ -94,6 +94,11 @@ Errors: text: "Check the heatbreak thermistor wiring for possible damage." id: "HEATBREAK_MAXTEMP_ERR" approved: true +- code: "17213" + title: "MCU MAXTEMP ERROR" + text: "MCU in %s is overheated." + id: "MCU_MAXTEMP_ERR" + approved: false - code: "17250" title: "MODULAR BED ERROR" text: "Heatbed tile no. %d:\nDamaged tile or wiring.\nFollow online guide to diagnose." diff --git a/lib/Prusa-Error-Codes/20_MK3.5/error-codes.yaml b/lib/Prusa-Error-Codes/20_MK3.5/error-codes.yaml index 76bcc609f0..387bbd8428 100644 --- a/lib/Prusa-Error-Codes/20_MK3.5/error-codes.yaml +++ b/lib/Prusa-Error-Codes/20_MK3.5/error-codes.yaml @@ -74,6 +74,11 @@ Errors: text: "Check the heatbreak thermistor wiring for possible damage." id: "HEATBREAK_MAXTEMP_ERR" approved: true +- code: "20213" + title: "MCU MAXTEMP ERROR" + text: "MCU in %s is overheated." + id: "MCU_MAXTEMP_ERR" + approved: false # XX250-XX257 reserved - code: "20301" title: "HOMING ERROR Z" diff --git a/lib/WUI/espif.cpp b/lib/WUI/espif.cpp index 34d5d67d70..98b0e5e30c 100644 --- a/lib/WUI/espif.cpp +++ b/lib/WUI/espif.cpp @@ -98,10 +98,10 @@ enum MessageType { #if PRINTER_IS_PRUSA_XL // ESP32 FW version -static const uint32_t SUPPORTED_FW_VERSION = 10; +static constexpr uint8_t SUPPORTED_FW_VERSION = 10; #else // ESP8266 FW version -static const uint32_t SUPPORTED_FW_VERSION = 10; +static constexpr uint8_t SUPPORTED_FW_VERSION = 10; #endif // NIC state @@ -386,7 +386,7 @@ static void process_mac(uint8_t *data, struct netif *netif) { ESPIFOperatingMode old = ESPIF_WAIT_INIT; if (esp_operating_mode.compare_exchange_strong(old, ESPIF_NEED_AP)) { - uint16_t version = fw_version.load(); + const uint8_t version = fw_version.load(); if (version != SUPPORTED_FW_VERSION) { log_warning(ESPIF, "Firmware version mismatch: %d != %d", version, SUPPORTED_FW_VERSION); esp_operating_mode = ESPIF_WRONG_FW; diff --git a/lib/WUI/ethernetif.c b/lib/WUI/ethernetif.c index 82bbf05fb3..fc87ca5683 100644 --- a/lib/WUI/ethernetif.c +++ b/lib/WUI/ethernetif.c @@ -325,8 +325,9 @@ static struct pbuf *low_level_input(struct netif *netif) { uint32_t i = 0; /* get received frame */ - if (HAL_ETH_GetReceivedFrame_IT(&heth) != HAL_OK) + if (HAL_ETH_GetReceivedFrame_IT(&heth) != HAL_OK) { return NULL; + } /* Obtain the size of the packet and put it into the "len" variable. */ len = heth.RxFrameInfos.length; diff --git a/lib/WUI/link_content/basic_gets.cpp b/lib/WUI/link_content/basic_gets.cpp index 4049a1f1c3..b0870e7627 100644 --- a/lib/WUI/link_content/basic_gets.cpp +++ b/lib/WUI/link_content/basic_gets.cpp @@ -185,7 +185,7 @@ JsonResult get_printer(size_t resume_point, JsonOutput &output) { JsonResult get_version(size_t resume_point, JsonOutput &output) { char hostname[ETH_HOSTNAME_LEN + 1]; netdev_get_hostname(netdev_get_active_id(), hostname, sizeof hostname); - auto nozzle_diameter = config_store().get_nozzle_diameter(0); + float nozzle_diameter = config_store().get_nozzle_diameter(0); // Keep the indentation of the JSON in here! // clang-format off @@ -210,7 +210,7 @@ JsonResult get_version(size_t resume_point, JsonOutput &output) { JsonResult get_info(size_t resume_point, JsonOutput &output) { char hostname[ETH_HOSTNAME_LEN + 1]; netdev_get_hostname(netdev_get_active_id(), hostname, sizeof hostname); - auto nozzle_diameter = config_store().get_nozzle_diameter(0); + float nozzle_diameter = config_store().get_nozzle_diameter(0); auto mmu2_enabled = #if HAS_MMU2() config_store().mmu2_enabled.get(); diff --git a/lib/WUI/nhttp/gcode_preview.cpp b/lib/WUI/nhttp/gcode_preview.cpp index 2689bc90ff..de4d20a63b 100644 --- a/lib/WUI/nhttp/gcode_preview.cpp +++ b/lib/WUI/nhttp/gcode_preview.cpp @@ -73,8 +73,9 @@ Step GCodePreview::step(string_view, bool, uint8_t *buffer, size_t buffer_size) written += http::render_chunk(handling, buffer, buffer_size, [&](uint8_t *buffer_, size_t buffer_size_) { int got = 0; for (size_t i = 0; i < buffer_size_; i++) { - if (gcode.get()->stream_getc(*reinterpret_cast(&buffer_[i])) != IGcodeReader::Result_t::RESULT_OK) + if (gcode.get()->stream_getc(*reinterpret_cast(&buffer_[i])) != IGcodeReader::Result_t::RESULT_OK) { break; + } ++got; } if (got > 0) { diff --git a/lib/WUI/nhttp/gcode_upload.cpp b/lib/WUI/nhttp/gcode_upload.cpp index 3c123f1b39..dd11143bcd 100644 --- a/lib/WUI/nhttp/gcode_upload.cpp +++ b/lib/WUI/nhttp/gcode_upload.cpp @@ -6,6 +6,7 @@ #include "../../src/common/filename_type.hpp" #include "../wui_api.h" +#include #include #include @@ -234,8 +235,9 @@ namespace { // teoretically could fail not on the first // folder and we would then leave some previous // folder in place ,but this is improbable... - if (errno != EEXIST) + if (errno != EEXIST) { return make_tuple(Status::InternalServerError, "Failed to create a folder"); + } } return make_tuple(Status::Ok, nullptr); } @@ -243,8 +245,9 @@ namespace { UploadHooks::Result make_dirs(string_view path) { size_t pos = path.find('/'); while (pos != path.npos) { - if (auto error = make_dir(path.substr(0, pos)); std::get<0>(error) != Status::Ok) + if (auto error = make_dir(path.substr(0, pos)); std::get<0>(error) != Status::Ok) { return error; + } pos = path.find('/', pos + 1); } @@ -281,32 +284,44 @@ namespace { return error; } - FILE *attempt = fopen(fn, "r"); - if (attempt) { - fclose(attempt); - if (overwrite) { - int result = remove(fn); - if (result == -1) { - remove(src); - switch (errno) { - case EBUSY: - return make_tuple(Status::Conflict, "File is busy"); - default: - return make_tuple(Status::InternalServerError, "Unknown error"); - } - } - } else { + struct stat st = {}; + int stat_result = stat_retry(fn, &st); + if (stat_result == 0 && S_ISREG(st.st_mode) && overwrite) { + int result = remove(fn); + if (result == -1) { remove(src); - return make_tuple(Status::Conflict, "File already exists"); + switch (errno) { + case EBUSY: + return make_tuple(Status::Conflict, "File is busy"); + case EISDIR: + // Shouldn't happen due to st_mode already checked? + return make_tuple(Status::Conflict, "Is a directory or ongoing transfer"); + default: + return make_tuple(Status::InternalServerError, "Unknown error"); + } } + } else if (stat_result == 0 && S_ISDIR(st.st_mode) && overwrite) { + return make_tuple(Status::Conflict, "Is a directory or ongoing transfer"); + } else if (stat_result == 0) { + remove(src); + return make_tuple(Status::Conflict, "File already exists"); } int result = rename(src, fn); if (result != 0) { + // Backup errno before calling other things + int old_errno = errno; remove(src); // No check - no way to handle errors anyway. - // we already checked for existence of the file, so we guess - // it is weird file name/forbidden chars that contain (422 Unprocessable Entity). - return make_tuple(Status::UnprocessableEntity, "Filename contains invalid characters"); + switch (old_errno) { + case EISDIR: + return make_tuple(Status::Conflict, "Is a directory or ongoing transfer"); + case ENOTDIR: + return make_tuple(Status::NotFound, "Destination directory does not exist"); + default: + // we already checked for existence of the file, so we guess + // it is weird file name/forbidden chars that contain (422 Unprocessable Entity). + return make_tuple(Status::UnprocessableEntity, "Filename contains invalid characters"); + } } else { return f(fn); } @@ -425,8 +440,9 @@ UploadHooks::Result GcodeUpload::check_filename(const char *filename) const { if (overwrite) { char filepath[FILE_NAME_BUFFER_LEN]; auto error = prepend_usb_path(filename, filepath, sizeof(filepath)); - if (std::get<0>(error) != Status::Ok) + if (std::get<0>(error) != Status::Ok) { return error; + } if (wui_is_file_being_printed(filepath)) { return make_tuple(Status::Conflict, "File is busy"); @@ -491,8 +507,9 @@ Step GcodeUpload::step(string_view input, const size_t read, PutParams &putParam static_cast(input); auto filename_error = check_filename(filename); - if (std::get<0>(filename_error) != Status::Ok) + if (std::get<0>(filename_error) != Status::Ok) { return { read, 0, StatusPage(std::get<0>(filename_error), StatusPage::CloseHandling::ErrorClose, json_errors, nullopt, std::get<1>(filename_error)) }; + } assert(put_transfer.f == nullptr); // No other transfer is happening at the moment. put_transfer.f = move(tmp_upload_file); diff --git a/lib/WUI/nhttp/headers.cpp b/lib/WUI/nhttp/headers.cpp index 92c07c8d91..2ec8f26270 100644 --- a/lib/WUI/nhttp/headers.cpp +++ b/lib/WUI/nhttp/headers.cpp @@ -40,7 +40,7 @@ namespace { { Status::UnprocessableEntity, "Unprocessable Entity" }, { Status::TooManyRequests, "Too Many Requests" }, { Status::RequestHeaderFieldsTooLarge, "Request Header Fields Too Large" }, - { Status::InternalServerError, "Infernal Server Error" }, + { Status::InternalServerError, "Internal Server Error" }, { Status::NotImplemented, "Not Implemented" }, { Status::ServiceTemporarilyUnavailable, "Service Temporarily Unavailable" }, { Status::GatewayTimeout, "Gateway Timeout" }, diff --git a/lib/WUI/nhttp/multipart_parser.c b/lib/WUI/nhttp/multipart_parser.c index 3f9474f1cf..abefc8610d 100644 --- a/lib/WUI/nhttp/multipart_parser.c +++ b/lib/WUI/nhttp/multipart_parser.c @@ -188,8 +188,9 @@ size_t multipart_parser_execute(multipart_parser *p, const char *buf, size_t len multipart_log("invalid character in header name"); return i; } - if (is_last) + if (is_last) { EMIT_DATA_CB(header_field, buf + mark, (i - mark) + 1); + } break; case s_headers_almost_done: @@ -218,8 +219,9 @@ size_t multipart_parser_execute(multipart_parser *p, const char *buf, size_t len p->state = s_header_value_almost_done; break; } - if (is_last) + if (is_last) { EMIT_DATA_CB(header_value, buf + mark, (i - mark) + 1); + } break; case s_header_value_almost_done: @@ -246,8 +248,9 @@ size_t multipart_parser_execute(multipart_parser *p, const char *buf, size_t len p->lookbehind[0] = CR; break; } - if (is_last) + if (is_last) { EMIT_DATA_CB(part_data, buf + mark, (i - mark) + 1); + } break; case s_part_data_almost_boundary: diff --git a/lib/WUI/nhttp/req_parser.cpp b/lib/WUI/nhttp/req_parser.cpp index 67ab2e2b2a..f1dc33aa66 100644 --- a/lib/WUI/nhttp/req_parser.cpp +++ b/lib/WUI/nhttp/req_parser.cpp @@ -111,7 +111,8 @@ ExecutionControl RequestParser::event(Event event) { error_code = Status::RequestHeaderFieldsTooLarge; return ExecutionControl::Continue; } - case Names::Nonce: { + case Names::Nonce: + case Names::NonceUnquoted: { if (!holds_alternative(auth_status)) { auth_status = DigestAuthParams {}; } @@ -126,7 +127,8 @@ ExecutionControl RequestParser::event(Event event) { digest_params.recieved_nonce += static_cast(value); return ExecutionControl::Continue; } - case Names::Response: { + case Names::Response: + case Names::ResponseUnquoted: { if (!holds_alternative(auth_status)) { auth_status = DigestAuthParams {}; } @@ -306,14 +308,13 @@ bool RequestParser::nonce_valid(uint64_t nonce_to_check) const { uint32_t random = static_cast(nonce_to_check >> 32); uint32_t time = nonce_to_check & 0xffffffff; uint32_t age = ticks_s() - time; - // Make valid period for POST and PUT longer, to avoid infinit uploading - // loops if nonce get stale for upload request. - uint32_t max_valid_age = has_body(method) ? http::extended_valid_nonce_period : http::valid_nonce_period; + // sanity check if (nonce_random != 0) { // really valid? - if (random == nonce_random && age < max_valid_age) + if (random == nonce_random && age < http::valid_nonce_period) { return true; + } } return false; } @@ -322,10 +323,11 @@ uint64_t RequestParser::new_nonce() const { } std::optional> RequestParser::authenticated_status(const ApiKeyAuthParams ¶ms) const { - if (holds_alternative(params) and get(params)) + if (holds_alternative(params) and get(params)) { return std::nullopt; - else + } else { return UnauthenticatedStatusPage(*this, ApiKeyAuth {}); + } } std::optional> RequestParser::authenticated_status(const DigestAuthParams ¶ms) const { if (nonce_random == 0) { @@ -404,13 +406,15 @@ bool RequestParser::check_digest_auth(uint64_t nonce_to_use) const { for (size_t i = 0; i < MD5_SIZE; i++) { uint8_t to_compare {}; - if (i < 8) + if (i < 8) { to_compare = (digest_params->recieved_response[1] << i * 8) >> 56; - else + } else { to_compare = (digest_params->recieved_response[0] << (i - 8) * 8) >> 56; + } - if (to_compare != hash[i]) + if (to_compare != hash[i]) { return false; + } } return true; } diff --git a/lib/WUI/nhttp/status_renderer.cpp b/lib/WUI/nhttp/status_renderer.cpp index 43e3b06404..2c95f2aba3 100644 --- a/lib/WUI/nhttp/status_renderer.cpp +++ b/lib/WUI/nhttp/status_renderer.cpp @@ -42,11 +42,11 @@ json::JsonResult StatusRenderer::renderState(size_t resume_point, json::JsonOutp JSON_FIELD_INT("time_printing", marlin_vars()->print_duration); JSON_OBJ_END JSON_COMMA; } - JSON_FIELD_OBJ("storage"); - JSON_FIELD_STR("path", "/usb/") JSON_COMMA; - JSON_FIELD_STR("name", "usb") JSON_COMMA; - JSON_FIELD_BOOL("read_only", false); - JSON_OBJ_END JSON_COMMA; + JSON_FIELD_OBJ("storage"); + JSON_FIELD_STR("path", "/usb/") JSON_COMMA; + JSON_FIELD_STR("name", "usb") JSON_COMMA; + JSON_FIELD_BOOL("read_only", false); + JSON_OBJ_END JSON_COMMA; if (state.transfer_id.has_value()) { JSON_FIELD_OBJ("transfer"); JSON_FIELD_INT_G(transfer_status.has_value(), "id", transfer_status->id) JSON_COMMA; diff --git a/lib/WUI/wui_api.cpp b/lib/WUI/wui_api.cpp index 2c77a35de6..3498bf2183 100644 --- a/lib/WUI/wui_api.cpp +++ b/lib/WUI/wui_api.cpp @@ -268,7 +268,7 @@ StartPrintResult wui_start_print(char *filename, bool autostart_if_able) { if (autostart_if_able) { if (printer_can_print) { - print_begin(filename, true); + print_begin(filename, marlin_server::PreviewSkipIfAble::all); return marlin_client::is_print_started() ? StartPrintResult::PrintStarted : StartPrintResult::Failed; } else { return StartPrintResult::Failed; @@ -278,7 +278,7 @@ StartPrintResult wui_start_print(char *filename, bool autostart_if_able) { // marlin. If it couldn't print/initialte the preview, it would just do // nothing anyway. if (printer_can_print) { - print_begin(filename, false); + print_begin(filename); } // We were not asked to print. Showing the preview is "best effort", // but not reported to the user. diff --git a/src/bootloader/bootloader_update.cpp b/src/bootloader/bootloader_update.cpp index 53136b7735..aea4492d6e 100644 --- a/src/bootloader/bootloader_update.cpp +++ b/src/bootloader/bootloader_update.cpp @@ -168,8 +168,9 @@ static void copy_bootloader_to_flash(FILE *bootloader_bin, ProgressCallback prog auto buffer_size = bootloader_sector_get_size(0); auto buffer_mem = std::make_unique(buffer_size); - if (buffer_mem.get() == nullptr) + if (buffer_mem.get() == nullptr) { bsod("Not enough memory"); + } auto buffer = std::span(buffer_mem.get(), buffer_size); for (unsigned sector = 0; sector < buddy::bootloader::bootloader_sector_count; sector++) { diff --git a/src/buddy/fatfs.cpp b/src/buddy/fatfs.cpp index 7a8570c443..e6ea0af2c3 100644 --- a/src/buddy/fatfs.cpp +++ b/src/buddy/fatfs.cpp @@ -36,8 +36,9 @@ FRESULT fatfs_test_contiguous_file( *cont = 0; fr = f_rewind(fp); /* Validates and prepares the file */ - if (fr != FR_OK) + if (fr != FR_OK) { return fr; + } #if FF_MAX_SS == FF_MIN_SS clsz = (DWORD)fp->obj.fs->csize * FF_MAX_SS; /* Cluster size */ @@ -50,15 +51,18 @@ FRESULT fatfs_test_contiguous_file( while (fsz) { step = (fsz >= clsz) ? clsz : (DWORD)fsz; fr = f_lseek(fp, f_tell(fp) + step); /* Advances file pointer a cluster */ - if (fr != FR_OK) + if (fr != FR_OK) { return fr; - if (clst + 1 != fp->clust) + } + if (clst + 1 != fp->clust) { break; /* Is not the cluster next to previous one? */ + } clst = fp->clust; fsz -= step; /* Get current cluster for next test */ } - if (fsz == 0) + if (fsz == 0) { *cont = 1; /* All done without fail? */ + } } else { *cont = 1; /* A 0-sized file is continuous by definition. */ } diff --git a/src/buddy/littlefs_internal.cpp b/src/buddy/littlefs_internal.cpp index 37c1bd73fc..f1766ccf9e 100644 --- a/src/buddy/littlefs_internal.cpp +++ b/src/buddy/littlefs_internal.cpp @@ -77,8 +77,9 @@ static int read([[maybe_unused]] const struct lfs_config *c, lfs_block_t block, w25x_rd_data(addr, static_cast(buffer), size); - if (w25x_fetch_error() != 0) + if (w25x_fetch_error() != 0) { return LFS_ERR_IO; + } return 0; } @@ -93,8 +94,9 @@ static int prog([[maybe_unused]] const struct lfs_config *c, lfs_block_t block, w25x_program(addr, (uint8_t *)buffer, size); - if (w25x_fetch_error() != 0) + if (w25x_fetch_error() != 0) { return LFS_ERR_IO; + } return 0; } @@ -107,8 +109,9 @@ static int erase([[maybe_unused]] const struct lfs_config *c, lfs_block_t block) w25x_sector_erase(addr); - if (w25x_fetch_error() != 0) + if (w25x_fetch_error() != 0) { return LFS_ERR_IO; + } return 0; } diff --git a/src/buddy/main.cpp b/src/buddy/main.cpp index d1c63af03a..982c4164b7 100644 --- a/src/buddy/main.cpp +++ b/src/buddy/main.cpp @@ -229,8 +229,9 @@ extern "C" void main_cpp(void) { SPI_INIT(flash); // initialize SPI flash w25x_spi_assign(&SPI_HANDLE_FOR(flash)); - if (!w25x_init()) + if (!w25x_init()) { bsod("failed to initialize ext flash"); + } /* * If we have BSOD or red screen we want to have as small boot process as we can. @@ -669,8 +670,9 @@ static void enable_dfu_entry() { // this has to be checked after having // 1) initialized access to the backup domain // 2) having initialized related clocks (SystemClock_Config) - if (sys_dfu_requested()) + if (sys_dfu_requested()) { sys_dfu_boot_enter(); + } #endif } diff --git a/src/buddy/usb_device.cpp b/src/buddy/usb_device.cpp index 8bfb2b2902..dfc74d3474 100644 --- a/src/buddy/usb_device.cpp +++ b/src/buddy/usb_device.cpp @@ -233,8 +233,9 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, [[maybe_unused]] uint16_ // note: Dthe 0xEE index string is a Microsoft OS 1.0 Descriptors. // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors - if (!(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0]))) + if (!(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0]))) { return NULL; + } const char *str = string_desc_arr[index]; #if PRINTER_IS_PRUSA_MK4 @@ -245,8 +246,9 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, [[maybe_unused]] uint16_ // cap at max char chr_count = strlen(str); - if (chr_count > 31) + if (chr_count > 31) { chr_count = 31; + } // convert ASCII string into UTF-16 for (uint8_t i = 0; i < chr_count; i++) { diff --git a/src/buddy/usb_device_msc.cpp b/src/buddy/usb_device_msc.cpp index ff6142af51..df28ce2db9 100644 --- a/src/buddy/usb_device_msc.cpp +++ b/src/buddy/usb_device_msc.cpp @@ -52,12 +52,14 @@ int32_t tud_msc_write10_cb([[maybe_unused]] uint8_t lun, uint32_t lba, uint32_t if (offset == 0) { // we are at the beginning of the block, so lets clear it first - if (lfs->erase(lfs, lba) != 0) + if (lfs->erase(lfs, lba) != 0) { goto cleanup_and_return; + } } - if (lfs->prog(lfs, lba, offset, buffer, bufsize) != 0) + if (lfs->prog(lfs, lba, offset, buffer, bufsize) != 0) { goto cleanup_and_return; + } retval = bufsize; cleanup_and_return: @@ -148,8 +150,9 @@ int32_t tud_msc_scsi_cb(uint8_t lun, uint8_t const scsi_cmd[16], void *buffer, u } // return resplen must not larger than bufsize - if (resplen > bufsize) + if (resplen > bufsize) { resplen = bufsize; + } if (response && (resplen > 0)) { if (in_xfer) { diff --git a/src/buddy/usb_host.cpp b/src/buddy/usb_host.cpp index cee703089c..dfe2e01198 100644 --- a/src/buddy/usb_host.cpp +++ b/src/buddy/usb_host.cpp @@ -76,8 +76,9 @@ void USBH_UserProcess([[maybe_unused]] USBH_HandleTypeDef *phost, uint8_t id) { #ifdef USBH_MSC_READAHEAD usbh_msc_readahead.enable(USBHFatFS.pdrv); #endif - } else + } else { media_set_error(media_error_MOUNT); + } } else { phost->stealth_reset = false; } diff --git a/src/buddy/usbh_diskio.cpp b/src/buddy/usbh_diskio.cpp index d54e44a9f6..ff98640008 100644 --- a/src/buddy/usbh_diskio.cpp +++ b/src/buddy/usbh_diskio.cpp @@ -68,8 +68,9 @@ static USBH_StatusTypeDef USBH_exec(UsbhMscRequest::UsbhMscRequestOperation oper }; UsbhMscRequest *request_ptr = &request; - if (xQueueSend(request_queue, &request_ptr, USBH_MSC_RW_MAX_DELAY) != pdPASS) + if (xQueueSend(request_queue, &request_ptr, USBH_MSC_RW_MAX_DELAY) != pdPASS) { return USBH_FAIL; + } xSemaphoreTake(semaphore, portMAX_DELAY); @@ -92,8 +93,9 @@ USBH_StatusTypeDef usbh_msc_submit_request(UsbhMscRequest *request) { break; } #endif - if (xQueueSend(request_queue, &request, portMAX_DELAY) != pdPASS) + if (xQueueSend(request_queue, &request, portMAX_DELAY) != pdPASS) { return USBH_FAIL; + } return USBH_OK; } @@ -255,15 +257,17 @@ DRESULT USBH_read(BYTE lun, BYTE *buff, DWORD sector, UINT count) { // from the least significant bit (0 means it needs to be loaded) uint32_t mask = ~0u << count; for (unsigned i = 0; i < count; ++i) { - if (usbh_msc_readahead.get(lun, sector + i, buff + i * UsbhMscRequest::SECTOR_SIZE)) + if (usbh_msc_readahead.get(lun, sector + i, buff + i * UsbhMscRequest::SECTOR_SIZE)) { mask |= 1 << i; + } } if (mask != ~0u << count) { // some sectors in the cache while (mask != ~0u) { int i = std::countr_one(mask); result = USBH_read_ii(lun, buff + i * UsbhMscRequest::SECTOR_SIZE, sector + i, 1); - if (result != RES_OK) + if (result != RES_OK) { return result; + } mask |= 1 << i; } } else { // no cache match => read whole buffer at once @@ -398,8 +402,9 @@ DRESULT USBH_ioctl(BYTE lun, BYTE cmd, void *buff) { #ifdef USBH_MSC_READAHEAD bool UsbhMscReadahead::get(UsbhMscRequest::LunNbr lun_nbr, UsbhMscRequest::SectorNbr sector_nbr, uint8_t *data) { - if (this->lun_nbr != lun_nbr) + if (this->lun_nbr != lun_nbr) { return false; + } bool found = false; { @@ -433,15 +438,17 @@ bool UsbhMscReadahead::get(UsbhMscRequest::LunNbr lun_nbr, UsbhMscRequest::Secto // typical fatfs read requests are 1kb so it's a good idea to preload 2 sectors void UsbhMscReadahead::notify_read(UsbhMscRequest::LunNbr lun_nbr, UsbhMscRequest::SectorNbr sector_nbr) { Lock lock(mutex); - if (this->lun_nbr != lun_nbr) + if (this->lun_nbr != lun_nbr) { return; + } static_assert(size >= 2); // find the oldest and second oldest slots auto it = begin(cache); auto first = it++; auto second = it++; - if (*second < *first) + if (*second < *first) { std::swap(first, second); + } for (; it != end(cache); ++it) { if (*it < *first) { @@ -495,8 +502,9 @@ void UsbhMscReadahead::disable() { void UsbhMscReadahead::invalidate(UsbhMscRequest::LunNbr lun_nbr, UsbhMscRequest::SectorNbr sector_nbr, size_t count) { Lock lock(mutex); - if (this->lun_nbr != lun_nbr) + if (this->lun_nbr != lun_nbr) { return; + } for (auto &e : cache) { if (e.sector_nbr >= sector_nbr && e.sector_nbr < sector_nbr + count) { Lock lock2(e.mutex); @@ -510,8 +518,9 @@ bool UsbhMscReadahead::preload() { { Lock lock(mutex); - if (this->lun_nbr == INVALID_LUN_NBR) + if (this->lun_nbr == INVALID_LUN_NBR) { return false; + } entry = std::find_if(begin(cache), end(cache), [](const auto &e) { return e.preloaded == false && e.sector_nbr != INVALID_SECTOR_NBR; diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 8a61beb21b..6f6fb6004e 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -66,7 +66,6 @@ if(BOARD MATCHES ".*BUDDY") sys.cpp sys_time.cpp tasks.cpp - time_tools.cpp tools_mapping.cpp trinamic.cpp uartrxbuff.cpp diff --git a/src/common/ConstexprQuickSort.hpp b/src/common/ConstexprQuickSort.hpp index c8bc7882a6..356181acde 100644 --- a/src/common/ConstexprQuickSort.hpp +++ b/src/common/ConstexprQuickSort.hpp @@ -23,8 +23,9 @@ constexpr InputIt find_if_not(InputIt first, InputIt last, UnaryPredicate q) { template constexpr ForwardIt partition(ForwardIt first, ForwardIt last, UnaryPredicate p) { first = find_if_not(first, last, p); - if (first == last) + if (first == last) { return first; + } for (ForwardIt i = std::next(first); i != last; ++i) { if (p(*i)) { @@ -38,8 +39,9 @@ constexpr ForwardIt partition(ForwardIt first, ForwardIt last, UnaryPredicate p) template > constexpr void quick_sort(RAIt first, RAIt last, Compare cmp = Compare {}) { auto const N = std::distance(first, last); - if (N <= 1) + if (N <= 1) { return; + } auto const pivot = *std::next(first, N / 2); auto const middle1 = partition(first, last, [=](auto const &elem) { return cmp(elem, pivot); diff --git a/src/common/MindaRedscreen.cpp b/src/common/MindaRedscreen.cpp index d5f888aa84..c025ae0283 100644 --- a/src/common/MindaRedscreen.cpp +++ b/src/common/MindaRedscreen.cpp @@ -177,7 +177,8 @@ void mbl_error(uint16_t moves, uint16_t points) { // cannot use jogwheel_signals (disabled interrupt) while (1) { wdt_iwdg_refresh(); - if (!jogwheel.GetJogwheelButtonPinState()) + if (!jogwheel.GetJogwheelButtonPinState()) { sys_reset(); // button press + } } } diff --git a/src/common/PCA9557.hpp b/src/common/PCA9557.hpp index 2df185a47b..ef7d77189c 100644 --- a/src/common/PCA9557.hpp +++ b/src/common/PCA9557.hpp @@ -66,10 +66,11 @@ class PCA9557OutputPin { , init_state(init_state) {} void configure() const { - if (init_state == Pin::State::low) + if (init_state == Pin::State::low) { device.output_reset(pin); - else + } else { device.output_set(pin); + } device.configure_as_output(pin); } diff --git a/src/common/PersistentStorage.cpp b/src/common/PersistentStorage.cpp index 4eaa155ab5..4c744063b5 100644 --- a/src/common/PersistentStorage.cpp +++ b/src/common/PersistentStorage.cpp @@ -56,30 +56,34 @@ static void readHomeSamples(HomeSample (&homeSamples)[PersistentStorage::homeSam } static IndexRun getNextHomeSampleIndexRun(uint_fast8_t axis) { - if (axis >= axisCount) + if (axis >= axisCount) { return { 0, 0, true }; + } HomeSample homeSamplesRead[PersistentStorage::homeSamplesCount]; readHomeSamples(homeSamplesRead, axis); /// return first invalid sample, assume run 0. for (uint_fast8_t i = 0; i < PersistentStorage::homeSamplesCount; ++i) { - if (!isValid(homeSamplesRead[i])) + if (!isValid(homeSamplesRead[i])) { return { i, 0, false }; + } } /// return position to rewrite - first sample of previous run if (0 == homeSamplesRead[0].run) { // run 0. already started for (uint_fast8_t i = 1; i < PersistentStorage::homeSamplesCount; ++i) { - if (1 == homeSamplesRead[i].run) + if (1 == homeSamplesRead[i].run) { return { i, 0, false }; // return position of first sample from previous run + } } // run 0. finished, start 1. run return { 0, 1, false }; } else { // run 1. already started for (uint_fast8_t i = 1; i < PersistentStorage::homeSamplesCount; ++i) { - if (0 == homeSamplesRead[i].run) + if (0 == homeSamplesRead[i].run) { return { i, 1, false }; // return position of first sample from previous run + } } // run 1. finished, start 0. run return { 0, 0, false }; @@ -88,8 +92,9 @@ static IndexRun getNextHomeSampleIndexRun(uint_fast8_t axis) { void PersistentStorage::pushHomeSample(uint16_t mscnt, uint8_t board_temp, uint8_t axis) { const IndexRun indexRun = getNextHomeSampleIndexRun(axis); - if (indexRun.error) + if (indexRun.error) { return; + } HomeSample homeSample; homeSample.run = indexRun.run; diff --git a/src/common/Pin.cpp b/src/common/Pin.cpp index cabf42bbb2..b01c4a0aa5 100644 --- a/src/common/Pin.cpp +++ b/src/common/Pin.cpp @@ -49,8 +49,9 @@ void InterruptPin::configure() const { InputPin::configure(); if (!isIRQEnabled()) { HAL_NVIC_SetPriority(getIRQn(), m_priority.preemptPriority, m_priority.subPriority); - if (m_startEnabled) + if (m_startEnabled) { enableIRQ(); + } } else { #if MCU_IS_STM32F4() uint32_t priorityGroup = HAL_NVIC_GetPriorityGrouping(); diff --git a/src/common/SteelSheets.cpp b/src/common/SteelSheets.cpp index 67c0a2056a..4da959f91c 100644 --- a/src/common/SteelSheets.cpp +++ b/src/common/SteelSheets.cpp @@ -25,8 +25,9 @@ bool SteelSheets::IsSheetCalibrated(uint32_t index) { return !nearlyEqual(sheet.z_offset, config_store_ns::z_offset_uncalibrated, 0.001f); } bool SteelSheets::SelectSheet(uint32_t index) { - if (index >= config_store_ns::sheets_num) + if (index >= config_store_ns::sheets_num) { return false; + } uint8_t index_ui8 = index; config_store().active_sheet.set(index_ui8); @@ -38,13 +39,15 @@ bool SteelSheets::SelectSheet(uint32_t index) { return true; } bool SteelSheets::ResetSheet(uint32_t index) { - if (index >= config_store_ns::sheets_num) + if (index >= config_store_ns::sheets_num) { return false; + } uint8_t active = activeSheetIndex(); setSheetOffset(index, config_store_ns::z_offset_uncalibrated); - if (active == index) + if (active == index) { NextSheet(); + } return true; } uint32_t SteelSheets::activeSheetIndex() { @@ -53,31 +56,36 @@ uint32_t SteelSheets::activeSheetIndex() { uint32_t SteelSheets::NumOfCalibrated() { uint32_t count = 1; for (size_t i = 1; i < config_store_ns::sheets_num; ++i) { - if (IsSheetCalibrated(i)) + if (IsSheetCalibrated(i)) { ++count; + } } return count; } uint32_t SteelSheets::ActiveSheetName(char *buffer, uint32_t length) { - if (!buffer || !length) + if (!buffer || !length) { return 0; + } uint8_t index = activeSheetIndex(); return SheetName(index, buffer, length); } uint32_t SteelSheets::SheetName(uint32_t index, char *buffer, uint32_t length) { - if (index >= config_store_ns::sheets_num || !buffer || !length) + if (index >= config_store_ns::sheets_num || !buffer || !length) { return 0; + } uint32_t l = length < static_cast(MAX_SHEET_NAME_LENGTH) ? length : static_cast(MAX_SHEET_NAME_LENGTH); auto sheet = getSheet(index); memcpy(buffer, sheet.name, l); - while (l > 0 && !buffer[l - 1]) + while (l > 0 && !buffer[l - 1]) { --l; + } return l; } uint32_t SteelSheets::RenameSheet(uint32_t index, const char *buffer, uint32_t length) { - if (index >= config_store_ns::sheets_num || !buffer || !length) + if (index >= config_store_ns::sheets_num || !buffer || !length) { return false; + } auto sheet = getSheet(index); uint32_t l = length < static_cast(MAX_SHEET_NAME_LENGTH) ? length : static_cast(MAX_SHEET_NAME_LENGTH); @@ -97,8 +105,9 @@ void SteelSheets::updateMarlin(float offset) { marlin_client::set_z_offset(offset); } void SteelSheets::SetZOffset(float offset) { - if (!std::isfinite(offset)) + if (!std::isfinite(offset)) { offset = 0.F; + } offset = std::clamp(offset, zOffsetMin, zOffsetMax); uint8_t index = activeSheetIndex(); diff --git a/src/common/adc.cpp b/src/common/adc.cpp index b2a7e2d378..0c68d843cd 100644 --- a/src/common/adc.cpp +++ b/src/common/adc.cpp @@ -29,18 +29,20 @@ AdcMultiplexer // NOTE: This ISR is currently only enabled during AdcMultiplexer channel switching, // and kept disabled most of the time. See AdcMultiplexer::switch_channel. extern "C" void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc) { - if (hadc == &PowerHWIDAndTempMux.adc_handle()) + if (hadc == &PowerHWIDAndTempMux.adc_handle()) { PowerHWIDAndTempMux.conv_isr(); - else if (hadc == &SFSAndTempMux.adc_handle()) + } else if (hadc == &SFSAndTempMux.adc_handle()) { SFSAndTempMux.conv_isr(); + } } #endif int32_t AdcGet::getMCUTemp() { // there is division somewhere in formula below, so avoid division by zero in case vref is not measured properly (for example in simulator) - if (AdcGet::vref() == 0) + if (AdcGet::vref() == 0) { return 0; + } // Use LL calculation with factory calibration values ///@note ADC bit resolution shouldn't matter as it cancels out, but we use 12b on all platforms. return __LL_ADC_CALC_TEMPERATURE(__LL_ADC_CALC_VREFANALOG_VOLTAGE(AdcGet::vref(), LL_ADC_RESOLUTION_12B), AdcGet::mcuTemperature(), LL_ADC_RESOLUTION_12B); diff --git a/src/common/adc.hpp b/src/common/adc.hpp index 4b99517185..50278e7f1c 100644 --- a/src/common/adc.hpp +++ b/src/common/adc.hpp @@ -330,8 +330,9 @@ class AdcMultiplexer { } void conv_isr() { - if ((adcDma.handle.DMA_Handle->Instance->CR & DMA_SxCR_EN) != RESET) + if ((adcDma.handle.DMA_Handle->Instance->CR & DMA_SxCR_EN) != RESET) { return; // not disabled yet, we'll get another interrupt + } // update current values one last time update_X(); @@ -374,10 +375,11 @@ class AdcMultiplexer { [[nodiscard]] uint16_t get_channel(uint8_t index) { // update current values - if (index == (current_channel + channel_X_off)) + if (index == (current_channel + channel_X_off)) { update_X(); - else if (index == (current_channel + channel_Y_off)) + } else if (index == (current_channel + channel_Y_off)) { update_Y(); + } return m_data[index]; } @@ -434,8 +436,9 @@ inline uint16_t nozzle() { // increase oversampling for values lower than 50 degrees Celsius to reduce noise if (raw_temp > raw_adc_value_at_50_degreas_celsius) { // handle an empty buffer - if (nozzle_ring_buff.GetSize() == 0) + if (nozzle_ring_buff.GetSize() == 0) { return adcDma1.reset_value; + } // decimate to match the behavior of get_and_shift_channel() auto raw_temp_avg = nozzle_ring_buff.GetSum() / nozzle_ring_buff.GetSize(); @@ -448,10 +451,11 @@ inline uint16_t nozzle() { inline void sampleNozzle() { // the ring buffer is kept at full resolution auto raw_temp = adcDma1.get_channel(AdcChannel::hotend_T); - if (raw_temp == adcDma1.reset_value) + if (raw_temp == adcDma1.reset_value) { nozzle_ring_buff.PopLast(); - else + } else { nozzle_ring_buff.Put(raw_temp); + } } inline uint16_t bed() { return adcDma1.get_and_shift_channel(AdcChannel::heatbed_T); } diff --git a/src/common/advanced_power.cpp b/src/common/advanced_power.cpp index 8232972207..87e3c019e6 100644 --- a/src/common/advanced_power.cpp +++ b/src/common/advanced_power.cpp @@ -62,8 +62,9 @@ float AdvancedPower::GetInputCurrent() const { #if !(BOARD_IS_DWARF) void AdvancedPower::Update() { - if (!isInitialized) + if (!isInitialized) { return; + } #if BOARD_IS_XBUDDY if (HeaterOvercurentFaultDetected()) { fatal_error(ErrCode::ERR_ELECTRO_NOZZLE_OVERCURRENT); diff --git a/src/common/algorithm_scale.hpp b/src/common/algorithm_scale.hpp index 96cb4b79ff..1dd77f69e2 100644 --- a/src/common/algorithm_scale.hpp +++ b/src/common/algorithm_scale.hpp @@ -23,10 +23,12 @@ */ template T constexpr scale(T num, T min, T max, T scaled_min, T scaled_max) { - if (scaled_min == scaled_max) + if (scaled_min == scaled_max) { return scaled_min; - if (min == max) + } + if (min == max) { return scaled_max; + } if (min > max) { std::swap(min, max); diff --git a/src/common/app_metrics.cpp b/src/common/app_metrics.cpp index fd48004d9d..58c8880dbf 100644 --- a/src/common/app_metrics.cpp +++ b/src/common/app_metrics.cpp @@ -330,9 +330,13 @@ void buddy::metrics::RecordPrintFilename() { #if BOARD_IS_XLBUDDY void buddy::metrics::record_dwarf_internal_temperatures() { - // Dwarf board temperature for sensor screen + // Dwarf board and MCU temperature for sensor screen buddy::puppies::Dwarf &dwarf = prusa_toolchanger.getActiveToolOrFirst(); - static metric_t metric_dwarfMCUTemperature = METRIC("dwarf_board_temp", METRIC_VALUE_INTEGER, 1001, METRIC_HANDLER_ENABLE_ALL); + + static metric_t metric_dwarfBoardTemperature = METRIC("dwarf_board_temp", METRIC_VALUE_INTEGER, 1001, METRIC_HANDLER_ENABLE_ALL); + metric_record_integer(&metric_dwarfBoardTemperature, dwarf.get_board_temperature()); + + static metric_t metric_dwarfMCUTemperature = METRIC("dwarf_mcu_temp", METRIC_VALUE_INTEGER, 1001, METRIC_HANDLER_ENABLE_ALL); metric_record_integer(&metric_dwarfMCUTemperature, dwarf.get_mcu_temperature()); // All MCU temperatures diff --git a/src/common/appmain.cpp b/src/common/appmain.cpp index 67b7a9ece7..395179e47c 100644 --- a/src/common/appmain.cpp +++ b/src/common/appmain.cpp @@ -87,8 +87,9 @@ extern osThreadId webServerTaskHandle; // Webserver thread(used for fast boot mo #endif // BUDDY_ENABLE_ETHERNET void app_marlin_serial_output_write_hook(const uint8_t *buffer, int size) { - while (size && (buffer[size - 1] == '\n' || buffer[size - 1] == '\r')) + while (size && (buffer[size - 1] == '\n' || buffer[size - 1] == '\r')) { size--; + } log_severity_t severity = LOG_SEVERITY_INFO; bool MMU = false; if (size == 2 && memcmp("ok", buffer, 2) == 0) { @@ -276,8 +277,9 @@ static void filament_sensor_irq() { // widen the type to match the main sensor data type and translate the undefined value FSensor::value_type fs_raw_value = AdcGet::side_filament_sensor(adc_channel_mapping[remapped]); - if (fs_raw_value == AdcGet::undefined_value) + if (fs_raw_value == AdcGet::undefined_value) { fs_raw_value = FSensor::undefined_value; + } side_fs_process_sample(fs_raw_value, dwarf.get_dwarf_nr() - 1); } cnt_filament_sensor_update = 0; diff --git a/src/common/base64_stream_decoder.cpp b/src/common/base64_stream_decoder.cpp index 1ccb95fb03..b76f999289 100644 --- a/src/common/base64_stream_decoder.cpp +++ b/src/common/base64_stream_decoder.cpp @@ -28,8 +28,9 @@ const uint8_t Base64StreamDecoder::base64_inverse[256] = { int Base64StreamDecoder::ConsumeChar(char c, uint8_t *out) { // pozor na konec zaznamu - special handling uint8_t ic = (c != '=') ? find64(static_cast(c)) : 0; - if (ic == 0xff) + if (ic == 0xff) { return -1; // neplatny vstupni znak + } switch (state) { case States::AwaitingFirst: diff --git a/src/common/circle_buffer.hpp b/src/common/circle_buffer.hpp index 984e9211f9..2f8bc24634 100644 --- a/src/common/circle_buffer.hpp +++ b/src/common/circle_buffer.hpp @@ -234,8 +234,9 @@ bool CircleBuffer::push_back_DontRewrite(T elem) { template bool CircleBuffer::ConsumeFirst(T &elem) { - if (IsEmpty()) + if (IsEmpty()) { return false; + } elem = GetFirstIfAble(); incrementIndex(begin_pos); return true; @@ -243,8 +244,9 @@ bool CircleBuffer::ConsumeFirst(T &elem) { template bool CircleBuffer::ConsumeLast(T &elem) { - if (IsEmpty()) + if (IsEmpty()) { return false; + } elem = GetLastIfAble(); decrementIndex(end_pos); return true; diff --git a/src/common/client_fsm_types.h b/src/common/client_fsm_types.h index 576e3b9157..c58d76bd1f 100644 --- a/src/common/client_fsm_types.h +++ b/src/common/client_fsm_types.h @@ -72,7 +72,10 @@ enum class WarningType : uint32_t { HeatBreakThermistorFail, NozzleDoesNotHaveRoundSection, NotDownloaded, - _last = NotDownloaded + BuddyMCUMaxTemp, + DwarfMCUMaxTemp, + ModBedMCUMaxTemp, + _last = ModBedMCUMaxTemp }; // Open dialog has a parameter because I need to set a caption of change filament dialog (load / unload / change). diff --git a/src/common/client_response.hpp b/src/common/client_response.hpp index f5bea3b433..1d973fa160 100644 --- a/src/common/client_response.hpp +++ b/src/common/client_response.hpp @@ -274,7 +274,7 @@ enum class PhasesSelftest : uint16_t { ToolOffsets_wait_user_install_pin, ToolOffsets_wait_stable_temp, ToolOffsets_wait_calibrate, - ToolOffsets_wait_final_park, + ToolOffsets_wait_move_away, ToolOffsets_wait_user_remove_pin, _last_Tool_Offsets = ToolOffsets_wait_user_remove_pin, @@ -635,8 +635,9 @@ class ClientResponses { static uint8_t GetIndex(T phase, Response response) { const PhaseResponses &cmds = getResponsesInPhase(phase); for (size_t i = 0; i < MAX_RESPONSES; ++i) { - if (cmds[i] == response) + if (cmds[i] == response) { return i; + } } return -1; } @@ -644,8 +645,9 @@ class ClientResponses { // get response from PhaseResponses by index template static const Response &GetResponse(const T phase, const uint8_t index) { - if (index >= MAX_RESPONSES) + if (index >= MAX_RESPONSES) { return ResponseNone; + } const PhaseResponses &cmds = getResponsesInPhase(phase); return cmds[index]; } @@ -666,8 +668,9 @@ class ClientResponses { template static uint32_t Encode(T phase, Response response) { uint8_t clicked_index = GetIndex(phase, response); - if (clicked_index >= MAX_RESPONSES) + if (clicked_index >= MAX_RESPONSES) { return -1; // this phase does not have response with this index + } return ((static_cast(phase)) << RESPONSE_BITS) + uint32_t(clicked_index); } }; @@ -841,52 +844,66 @@ static constexpr bool SelftestPartContainsPhase(SelftestParts part, PhasesSelfte static constexpr SelftestParts SelftestGetPartFromPhase(PhasesSelftest ph) { for (size_t i = 0; i < size_t(SelftestParts::_none); ++i) { - if (SelftestPartContainsPhase(SelftestParts(i), ph)) + if (SelftestPartContainsPhase(SelftestParts(i), ph)) { return SelftestParts(i); + } } - if (SelftestPartContainsPhase(SelftestParts::WizardPrologue, ph)) + if (SelftestPartContainsPhase(SelftestParts::WizardPrologue, ph)) { return SelftestParts::WizardPrologue; + } - if (SelftestPartContainsPhase(SelftestParts::Fans, ph)) + if (SelftestPartContainsPhase(SelftestParts::Fans, ph)) { return SelftestParts::Fans; + } #if HAS_LOADCELL() - if (SelftestPartContainsPhase(SelftestParts::Loadcell, ph)) + if (SelftestPartContainsPhase(SelftestParts::Loadcell, ph)) { return SelftestParts::Loadcell; + } #endif #if FILAMENT_SENSOR_IS_ADC() - if (SelftestPartContainsPhase(SelftestParts::FSensor, ph)) + if (SelftestPartContainsPhase(SelftestParts::FSensor, ph)) { return SelftestParts::FSensor; + } #endif #if PRINTER_IS_PRUSA_MK4 - if (SelftestPartContainsPhase(SelftestParts::GearsCalib, ph)) + if (SelftestPartContainsPhase(SelftestParts::GearsCalib, ph)) { return SelftestParts::GearsCalib; + } #endif - if (SelftestPartContainsPhase(SelftestParts::Axis, ph)) + if (SelftestPartContainsPhase(SelftestParts::Axis, ph)) { return SelftestParts::Axis; + } - if (SelftestPartContainsPhase(SelftestParts::Heaters, ph)) + if (SelftestPartContainsPhase(SelftestParts::Heaters, ph)) { return SelftestParts::Heaters; + } - if (SelftestPartContainsPhase(SelftestParts::SpecifyHotEnd, ph)) + if (SelftestPartContainsPhase(SelftestParts::SpecifyHotEnd, ph)) { return SelftestParts::SpecifyHotEnd; + } - if (SelftestPartContainsPhase(SelftestParts::CalibZ, ph)) + if (SelftestPartContainsPhase(SelftestParts::CalibZ, ph)) { return SelftestParts::CalibZ; + } - if (SelftestPartContainsPhase(SelftestParts::WizardEpilogue_ok, ph)) + if (SelftestPartContainsPhase(SelftestParts::WizardEpilogue_ok, ph)) { return SelftestParts::WizardEpilogue_ok; + } - if (SelftestPartContainsPhase(SelftestParts::WizardEpilogue_nok, ph)) + if (SelftestPartContainsPhase(SelftestParts::WizardEpilogue_nok, ph)) { return SelftestParts::WizardEpilogue_nok; + } - if (SelftestPartContainsPhase(SelftestParts::Result, ph)) + if (SelftestPartContainsPhase(SelftestParts::Result, ph)) { return SelftestParts::Result; + } #if BOARD_IS_XLBUDDY - if (SelftestPartContainsPhase(SelftestParts::Dock, ph)) + if (SelftestPartContainsPhase(SelftestParts::Dock, ph)) { return SelftestParts::Dock; + } #endif return SelftestParts::_none; @@ -900,8 +917,9 @@ static constexpr bool ESPPartContainsPhase(ESPParts part, PhasesESP ph) { static constexpr ESPParts ESPGetPartFromPhase(PhasesESP ph) { for (size_t i = 0; i < size_t(ESPParts::_none); ++i) { - if (ESPPartContainsPhase(ESPParts(i), ph)) + if (ESPPartContainsPhase(ESPParts(i), ph)) { return ESPParts(i); + } } return ESPParts::_none; } @@ -926,18 +944,22 @@ enum class FSM_action { */ template FSM_action IsFSM_action_needed(std::optional current, std::optional should_be) { - if (!current && !should_be) + if (!current && !should_be) { return FSM_action::no_action; + } - if (!current && should_be) + if (!current && should_be) { return FSM_action::create; + } - if (current && !should_be) + if (current && !should_be) { return FSM_action::destroy; + } // current && should_be - if (*current == *should_be) + if (*current == *should_be) { return FSM_action::no_action; + } return FSM_action::change; } diff --git a/src/common/crash_dump/crash_dump_distribute.cpp b/src/common/crash_dump/crash_dump_distribute.cpp index d756abe128..77629321de 100644 --- a/src/common/crash_dump/crash_dump_distribute.cpp +++ b/src/common/crash_dump/crash_dump_distribute.cpp @@ -53,6 +53,10 @@ void create_url_string(std::array &url_buff, std::array disable crash dumps. + return false; + } http::SocketConnectionFactory conn_factory(server, port, socket_timeout_s); http::HttpClient http(conn_factory); diff --git a/src/common/crash_dump/crash_dump_distribute.hpp b/src/common/crash_dump/crash_dump_distribute.hpp index 173c690f1f..08ad7a5c77 100644 --- a/src/common/crash_dump/crash_dump_distribute.hpp +++ b/src/common/crash_dump/crash_dump_distribute.hpp @@ -6,9 +6,7 @@ namespace crash_dump { -// inline constexpr const char *server { "crashdump.dragomirecky.com" }; -// inline constexpr uint16_t port { 80 }; -inline constexpr const char *server { "94.142.234.223" }; // temporary server +inline constexpr const char *server { "" }; // Empty -> disabled inline constexpr uint16_t port { 8888 }; // temporary port inline constexpr size_t url_buff_size { 128 }; diff --git a/src/common/crash_dump/dump.cpp b/src/common/crash_dump/dump.cpp index 2a3f8ba6b6..a229a2c18f 100644 --- a/src/common/crash_dump/dump.cpp +++ b/src/common/crash_dump/dump.cpp @@ -80,8 +80,9 @@ enum { static bool dump_read_header(info_t &dumpinfo) { w25x_rd_data(dump_header_addr, (uint8_t *)(&dumpinfo), sizeof(dumpinfo)); - if (w25x_fetch_error()) + if (w25x_fetch_error()) { return false; + } return true; } @@ -104,8 +105,9 @@ bool dump_is_displayed() { } size_t dump_get_size() { - if (!dump_is_valid()) + if (!dump_is_valid()) { return 0; + } info_t dumpinfo; dump_read_header(dumpinfo); return dumpinfo.dump_size; @@ -161,8 +163,9 @@ bool save_dump_to_usb(const char *fn) { uint32_t bw_total = 0; info_t dump_info; - if (!dump_read_header(dump_info)) + if (!dump_read_header(dump_info)) { return false; + } fd = fopen(fn, "w"); if (fd != NULL) { @@ -223,24 +226,27 @@ void save_message(MsgType type, uint16_t error_code, const char *error, const ch bool message_is_valid() { uint32_t magic; w25x_rd_data(reinterpret_cast(&dumpmessage_flash->message_magic_nr), reinterpret_cast(&magic), sizeof(message_t::message_magic_nr)); - if (w25x_fetch_error()) + if (w25x_fetch_error()) { return false; + } return magic == MESSAGE_DUMP_MAGIC_NR; } MsgType message_get_type() { uint8_t type; w25x_rd_data(reinterpret_cast(&dumpmessage_flash->type), &type, sizeof(message_t::type)); - if (w25x_fetch_error()) + if (w25x_fetch_error()) { return MsgType::EMPTY; // Behave as invalid message + } return MsgType(type); } bool message_is_displayed() { uint8_t not_displayed; w25x_rd_data(reinterpret_cast(&dumpmessage_flash->not_displayed), ¬_displayed, sizeof(message_t::not_displayed)); - if (w25x_fetch_error()) + if (w25x_fetch_error()) { return false; + } return !not_displayed; } @@ -261,13 +267,16 @@ bool load_message(char *msg_dst, size_t msg_dst_size, char *tit_dst, size_t tit_ w25x_rd_data(reinterpret_cast(&dumpmessage_flash->msg), (uint8_t *)(msg_dst), msg_max_size); } - if (title_max_size) + if (title_max_size) { tit_dst[title_max_size - 1] = '\0'; - if (msg_max_size) + } + if (msg_max_size) { msg_dst[msg_max_size - 1] = '\0'; + } - if (w25x_fetch_error()) + if (w25x_fetch_error()) { return false; + } return true; } @@ -277,8 +286,9 @@ uint16_t load_message_error_code() { reinterpret_cast(&dumpmessage_flash->error_code), reinterpret_cast(&error_code), sizeof(message_t::error_code)); - if (w25x_fetch_error()) + if (w25x_fetch_error()) { return ftrstd::to_underlying(ErrCode::ERR_UNDEF); + } return error_code; } @@ -355,14 +365,16 @@ void CrashCatcher_DumpStart([[maybe_unused]] const CrashCatcherInfo *pInfo) { void CrashCatcher_DumpMemory(const void *pvMemory, CrashCatcherElementSizes element_size, size_t elementCount) { if (element_size == CRASH_CATCHER_BYTE) { - if (crash_dump::dump_size + elementCount > crash_dump::dump_max_data_size) + if (crash_dump::dump_size + elementCount > crash_dump::dump_max_data_size) { crash_dump::dump_failed(); + } w25x_program(crash_dump::dump_data_addr + crash_dump::dump_size, (uint8_t *)pvMemory, elementCount); crash_dump::dump_size += elementCount; } else if (element_size == CRASH_CATCHER_WORD) { - if (crash_dump::dump_size + elementCount * sizeof(uint32_t) > crash_dump::dump_max_data_size) + if (crash_dump::dump_size + elementCount * sizeof(uint32_t) > crash_dump::dump_max_data_size) { crash_dump::dump_failed(); + } const uint32_t *ptr = reinterpret_cast(pvMemory); while (elementCount) { @@ -375,8 +387,9 @@ void CrashCatcher_DumpMemory(const void *pvMemory, CrashCatcherElementSizes elem crash_dump::dump_failed(); } - if (w25x_fetch_error()) + if (w25x_fetch_error()) { crash_dump::dump_failed(); + } } CrashCatcherReturnCodes CrashCatcher_DumpEnd(void) { @@ -387,8 +400,9 @@ CrashCatcherReturnCodes CrashCatcher_DumpEnd(void) { .dump_size = crash_dump::dump_size, }; w25x_program(crash_dump::dump_header_addr, (uint8_t *)&dump_info, sizeof(dump_info)); - if (w25x_fetch_error()) + if (w25x_fetch_error()) { crash_dump::dump_failed(); + } // All done, now restart and display BSOD HAL_NVIC_SystemReset(); diff --git a/src/common/disable_interrupts.h b/src/common/disable_interrupts.h index 07d80fa68c..163ff73596 100644 --- a/src/common/disable_interrupts.h +++ b/src/common/disable_interrupts.h @@ -69,8 +69,9 @@ class DisableInterrupts { public: DisableInterrupts(bool disableNow = true) : m_primask(__get_PRIMASK()) { - if (disableNow) + if (disableNow) { disable(); + } } ~DisableInterrupts() { diff --git a/src/common/fanctl/local/c_fan_ctl.cpp b/src/common/fanctl/local/c_fan_ctl.cpp index 7577fec03a..384217427b 100644 --- a/src/common/fanctl/local/c_fan_ctl.cpp +++ b/src/common/fanctl/local/c_fan_ctl.cpp @@ -36,8 +36,9 @@ CFanCtlPWM::CFanCtlPWM(const OutputPin &pinOut, uint8_t pwm_min, uint8_t pwm_max int8_t CFanCtlPWM::tick() { int8_t pwm_on = cnt - pha; // calculate on time (number of ticks after 0-1 pwm transition) - if (pwm_on >= val) + if (pwm_on >= val) { pwm_on -= max_value; + } bool o = (cnt >= pha) && (cnt < (pha + val)); if (++cnt >= max_value) { cnt = 0; @@ -47,11 +48,13 @@ int8_t CFanCtlPWM::tick() { pha_max = max_value - val; // calculate maximum phase if ((val > 1) && (val <= pha_thr)) { uint8_t steps = max_value / val; // calculate number of steps - if (steps < 3) + if (steps < 3) { steps = 3; // limit steps >= 3 + } pha_stp = pha_max / steps; // calculate step - enable phase shifting - } else + } else { pha_stp = 0; // set step to zero - disable phase shifting + } } #if 1 else if (pha_stp) // pha_stp != 0 means phase shifting enabled @@ -89,10 +92,12 @@ int8_t CFanCtlPWM::tick() { } void CFanCtlPWM::set_PWM(uint8_t new_pwm) { - if (new_pwm > max_value) + if (new_pwm > max_value) { new_pwm = max_value; - if (new_pwm && (new_pwm < min_value)) + } + if (new_pwm && (new_pwm < min_value)) { new_pwm = min_value; + } pwm = new_pwm; } @@ -126,12 +131,14 @@ CFanCtlTach::CFanCtlTach(const InputPin &inputPin) bool CFanCtlTach::tick(int8_t pwm_on) { bool tach = static_cast(m_pin.read()); // sample tach input pin bool edge = ((tach ^ input_state) && (pwm_on >= 2)); // detect edge inside pwm pulse, ignore first two sub-periods after 0-1 pwm transition - if (edge) + if (edge) { edges++; + } input_state = tach; // store current tach input state if (++tick_count >= ticks_per_second) { - if (pwm_sum) + if (pwm_sum) { edges = (edges * ticks_per_second) / pwm_sum; // add lost edges + } rpm = (rpm + (45 * edges)) >> 2; // calculate and filter rpm original formula // rpm = (rpm + 3 * ((60 * edges) >> 2)) >> 2; // take original rpm add 3 times new rpm - new rpm= 60*freq; @@ -140,8 +147,9 @@ bool CFanCtlTach::tick(int8_t pwm_on) { tick_count = 0; // reset tick counter pwm_sum = 0; // reset pwm_sum m_value_ready = true; // set value ready = measure done - } else if (pwm_on >= 0) + } else if (pwm_on >= 0) { pwm_sum++; // inc pwm sum if pwm enabled + } return edge; } @@ -178,20 +186,22 @@ void CFanCtl::tick() { m_State = starting; m_Edges = 0; m_Ticks = 0; - } else + } else { m_pwm.set_PWM(0); + } break; case starting: - if (m_PWMValue == 0) + if (m_PWMValue == 0) { m_State = idle; - else { + } else { m_Ticks++; if (m_Ticks > FANCTL_START_TIMEOUT && m_skip_tacho != skip_tacho_t::yes) { m_State = error_starting; } else { m_pwm.set_PWM(m_pwm.get_max_PWM()); - if (edge) + if (edge) { m_Edges++; + } if (m_Edges >= FANCTL_START_EDGES) { m_State = rpm_stabilization; m_Ticks = 0; @@ -204,10 +214,11 @@ void CFanCtl::tick() { m_State = idle; } else { m_pwm.set_PWM(m_PWMValue); - if (m_Ticks < FANCTL_RPM_DELAY) + if (m_Ticks < FANCTL_RPM_DELAY) { m_Ticks++; - else + } else { m_State = running; + } } break; case running: @@ -215,17 +226,19 @@ void CFanCtl::tick() { m_State = idle; } else { m_pwm.set_PWM(m_PWMValue); - if (!getRPMIsOk() && m_skip_tacho != skip_tacho_t::yes) + if (!getRPMIsOk() && m_skip_tacho != skip_tacho_t::yes) { m_State = error_running; + } } break; default: // error state - if (m_PWMValue == 0) + if (m_PWMValue == 0) { m_State = idle; - else { + } else { m_pwm.set_PWM(m_PWMValue); - if (getRPMIsOk()) + if (getRPMIsOk()) { m_State = running; + } } break; } @@ -240,22 +253,25 @@ uint16_t CFanCtl::unscalePWM(uint8_t pwm) const { } bool CFanCtl::setPWM(uint8_t pwm) { - if (selftest_mode) + if (selftest_mode) { return false; + } m_PWMValue = scalePWM(pwm); return true; } bool CFanCtl::SelftestSetPWM(uint8_t pwm) { - if (!selftest_mode) + if (!selftest_mode) { return false; + } m_PWMValue = scalePWM(pwm); return true; } bool CFanCtl::setPhaseShiftMode(uint8_t psm) { - if (selftest_mode) + if (selftest_mode) { return false; + } m_pwm.set_PhaseShiftMode((CFanCtlPWM::PhaseShiftMode)psm); return true; } @@ -267,29 +283,33 @@ void CFanCtl::safeState() { } bool CFanCtl::getRPMIsOk() { - if (m_PWMValue && (getActualRPM() < m_MinRPM)) + if (m_PWMValue && (getActualRPM() < m_MinRPM)) { return false; + } return true; } void CFanCtl::EnterSelftestMode() { - if (selftest_mode) + if (selftest_mode) { return; + } selftest_mode = true; selftest_initial_pwm = getPWM(); } void CFanCtl::ExitSelftestMode() { - if (!selftest_mode) + if (!selftest_mode) { return; + } selftest_mode = false; uint8_t pwm_to_restore; - if (isAutoFan()) + if (isAutoFan()) { // if this is autofan, turn fan off and let marlin turn it back on in case it is needed pwm_to_restore = 0; - else + } else { pwm_to_restore = selftest_initial_pwm; + } setPWM(pwm_to_restore); } diff --git a/src/common/fanctl/on_puppy/c_fan_ctl.cpp b/src/common/fanctl/on_puppy/c_fan_ctl.cpp index f192ad22b9..b0685e587c 100644 --- a/src/common/fanctl/on_puppy/c_fan_ctl.cpp +++ b/src/common/fanctl/on_puppy/c_fan_ctl.cpp @@ -16,16 +16,18 @@ void CFanCtl::reset_fan() { } bool CFanCtl::setPWM(uint16_t pwm) { - if (selftest_active) + if (selftest_active) { return false; + } buddy::puppies::dwarfs[dwarf_nr].set_fan(fan_nr, pwm); return true; } bool CFanCtl::SelftestSetPWM(uint8_t pwm) { - if (!selftest_active) + if (!selftest_active) { return false; + } buddy::puppies::dwarfs[dwarf_nr].set_fan(fan_nr, pwm); return true; diff --git a/src/common/filament.hpp b/src/common/filament.hpp index 05b5165037..1f8dcf6982 100644 --- a/src/common/filament.hpp +++ b/src/common/filament.hpp @@ -31,6 +31,50 @@ enum class Type : uint8_t { _last = PA }; +struct ColorIndex { + const char *name; + uint32_t color; +}; + +enum class ColorName : uint32_t { + NONE = 0, + BLACK, + BLUE, + GREEN, + BROWN, + PURPLE, + GRAY, + TERRACOTTA, + SILVER, + GOLD, + RED, + PINK, + ORANGE, + TRANSPARENT, + YELLOW, + WHITE, + _last = WHITE +}; + +const ColorIndex colortable[size_t(filament::ColorName::_last) + 1] = { + { "NONE", 0 }, + { "BLACK", 0x000000 }, + { "BLUE", 0x0000FF }, + { "GREEN", 0x00FF00 }, + { "BROWN", 0x800000 }, + { "PURPLE", 0x800080 }, + { "GRAY", 0x999999 }, + { "TERRACOTTA", 0xB87F6A }, + { "SILVER", 0xC0C0C0 }, + { "GOLD", 0xD4AF37 }, + { "RED", 0xFF0000 }, + { "PINK", 0xFF007F }, + { "ORANGE", 0xFF8000 }, + { "TRANSPARENT", 0xF0F0F0 }, + { "YELLOW", 0xFFFF00 }, + { "WHITE", 0xFFFFFF } +}; + constexpr Type default_type = Type::PLA; constexpr float cold_nozzle = 50.f; constexpr float cold_bed = 45.f; @@ -53,6 +97,17 @@ struct Colour { return red << 16 | green << 8 | blue; } + static Colour from_string(char *name) { + // first name is not valid ("---") + size_t name_len = strlen(name); + for (size_t i = size_t(ColorName::NONE) + 1; i <= size_t(ColorName::_last); ++i) { + if ((strlen(colortable[i].name) == name_len) && (!strncmp(name, colortable[i].name, name_len))) { + return from_int(colortable[i].color); + } + } + return from_int(atoi(name)); + } + static Colour from_int(int value) { return Colour { .red = static_cast((value >> 16) & 0xFF), diff --git a/src/common/filament_sensor.cpp b/src/common/filament_sensor.cpp index 15b426a312..6f79bd8298 100644 --- a/src/common/filament_sensor.cpp +++ b/src/common/filament_sensor.cpp @@ -51,10 +51,11 @@ fsensor_t FSensor::WaitInitialized() { void FSensor::init() { bool enabled = FSensorEEPROM::Get(); // can globally disable all sensors, but some sensors might need another enable - if (enabled) + if (enabled) { enable(); - else + } else { disable(); + } } /*---------------------------------------------------------------------------*/ @@ -71,10 +72,12 @@ IFSensor::event IFSensor::GenerateEvent() { } const bool had_filament = fsensor_t::HasFilament == previous_state; - if (has_filament == had_filament) + if (has_filament == had_filament) { return has_filament ? event::HasFilament : event::NoFilament; + } /// state has changed - if (has_filament) + if (has_filament) { return event::EdgeFilamentInserted; // has && !had + } return event::EdgeFilamentRemoved; //! has && had } diff --git a/src/common/filament_sensor_photoelectric.cpp b/src/common/filament_sensor_photoelectric.cpp index 42974a56dd..a3f44308b3 100644 --- a/src/common/filament_sensor_photoelectric.cpp +++ b/src/common/filament_sensor_photoelectric.cpp @@ -67,8 +67,9 @@ void FSensorPhotoElectric::record_state() { // without filter fs_meas_cycle1 could set FS_NO_SENSOR (in case filament just runout) void FSensorPhotoElectric::set_state(fsensor_t st) { CriticalSection C; - if (last_state == st) + if (last_state == st) { state = st; + } last_state = st; } diff --git a/src/common/filament_sensors_handler.cpp b/src/common/filament_sensors_handler.cpp index be1ed7e2ee..41d805e5c1 100644 --- a/src/common/filament_sensors_handler.cpp +++ b/src/common/filament_sensors_handler.cpp @@ -156,13 +156,15 @@ bool FilamentSensors::run_sensors_cycle() { HOTEND_LOOP() { if (IFSensor *s = GetExtruderFSensor(e); s != nullptr) { s->Cycle(); - if (s->Get() == fsensor_t::NotInitialized) + if (s->Get() == fsensor_t::NotInitialized) { any_not_intitialized = true; + } } if (IFSensor *s = GetSideFSensor(e); s != nullptr) { s->Cycle(); - if (s->Get() == fsensor_t::NotInitialized) + if (s->Get() == fsensor_t::NotInitialized) { any_not_intitialized = true; + } } } return any_not_intitialized; @@ -219,12 +221,14 @@ void FilamentSensors::Cycle() { opt_event_m600 = evaluateM600(*events.secondary_runout); } } else { - if (events.autoload) + if (events.autoload) { opt_event_autoload = evaluateAutoload(*events.autoload); + } } - if (isEvLocked()) + if (isEvLocked()) { return; + } // gcode is injected outside critical section, so critical section is as short as possible // also injection of GCode inside critical section might not work diff --git a/src/common/filters/median_filter.hpp b/src/common/filters/median_filter.hpp index 586225b75a..db5b62e0fa 100644 --- a/src/common/filters/median_filter.hpp +++ b/src/common/filters/median_filter.hpp @@ -17,16 +17,20 @@ class MedianFilter { static constexpr uint32_t median_3_i32(const int32_t *nums) { // Compare each three number to find middle number if (nums[0] > nums[1]) { - if (nums[1] > nums[2]) + if (nums[1] > nums[2]) { return 1; - if (nums[0] > nums[2]) + } + if (nums[0] > nums[2]) { return 2; + } return 0; } else { - if (nums[0] > nums[2]) + if (nums[0] > nums[2]) { return 0; - if (nums[1] > nums[2]) + } + if (nums[1] > nums[2]) { return 2; + } return 1; } } diff --git a/src/common/footer_def.hpp b/src/common/footer_def.hpp index 27e0b1573f..7046a553c7 100644 --- a/src/common/footer_def.hpp +++ b/src/common/footer_def.hpp @@ -97,9 +97,9 @@ inline constexpr auto disabled_items { std::to_array({ Item::input_shaper_x, Item::input_shaper_y, Item::f_s_value, +#endif +#if not HAS_SIDE_FSENSOR() Item::f_sensor_side, -#elif not HAS_SIDE_FSENSOR() - Item::f_sensor_side, #endif }) }; @@ -270,12 +270,15 @@ static_assert(sizeof(ItemDrawCnf) <= 4, "invalid ctor - constexpr ItemDrawCnf(ui // 4B var, better pass by value constexpr bool operator==(ItemDrawCnf lhs, ItemDrawCnf rhs) { - if (lhs.type != rhs.type) + if (lhs.type != rhs.type) { return false; - if (lhs.zero != rhs.zero) + } + if (lhs.zero != rhs.zero) { return false; - if (lhs.center_n_and_fewer != rhs.center_n_and_fewer) + } + if (lhs.center_n_and_fewer != rhs.center_n_and_fewer) { return false; + } return true; } diff --git a/src/common/footer_eeprom.cpp b/src/common/footer_eeprom.cpp index e2723b19dc..3e264aa9a3 100644 --- a/src/common/footer_eeprom.cpp +++ b/src/common/footer_eeprom.cpp @@ -7,6 +7,7 @@ #include "footer_eeprom.hpp" #include #include +#include namespace footer::eeprom { @@ -56,8 +57,9 @@ ItemDrawCnf load_item_draw_cnf() { } changed_t set(ItemDrawCnf cnf) { - if (get_draw_cnf_ref() == cnf) + if (get_draw_cnf_ref() == cnf) { return changed_t::no; + } config_store().footer_draw_type.set(static_cast(cnf)); get_draw_cnf_ref() = cnf; return changed_t::yes; @@ -93,6 +95,95 @@ uint8_t get_center_n_and_fewer() { return get_draw_cnf_ref().center_n_and_fewer; } +#if PRINTER_IS_PRUSA_MINI || PRINTER_IS_PRUSA_XL +Record decode_from_old_eeprom_v22(uint32_t encoded) { + // Only valid for XL and MINI + + static constexpr size_t min_bit_size { config_store_ns::old_eeprom::v22::value_bit_size }; + uint32_t mask = (uint32_t(1) << (min_bit_size)) - 1; + footer::Record ret = { {} }; + + // version >= v11 has trailing ones + encoded >>= config_store_ns::old_eeprom::v22::count_of_trailing_ones; + + for (size_t i = 0; i < config_store_ns::old_eeprom::v22::count; ++i) { + uint32_t decoded = encoded & mask; + if (decoded >= ftrstd::to_underlying(config_store_ns::old_eeprom::v22::FooterItems::_count)) { + return footer::default_items; // data corrupted, return default setting + } + + auto previous_item = static_cast(decoded); + switch (previous_item) { // easiest way to ensure there's no mistake is the most boring one - a switch case + case config_store_ns::old_eeprom::v22::FooterItems::Nozzle: + ret[i] = footer::Item::nozzle; + break; + case config_store_ns::old_eeprom::v22::FooterItems::Bed: + ret[i] = footer::Item::bed; + break; + case config_store_ns::old_eeprom::v22::FooterItems::Filament: + ret[i] = footer::Item::filament; + break; + case config_store_ns::old_eeprom::v22::FooterItems::FSValue: + ret[i] = footer::Item::f_s_value; + break; + case config_store_ns::old_eeprom::v22::FooterItems::FSensor: + ret[i] = footer::Item::f_sensor; + break; + case config_store_ns::old_eeprom::v22::FooterItems::Speed: + ret[i] = footer::Item::speed; + break; + case config_store_ns::old_eeprom::v22::FooterItems::AxisX: + ret[i] = footer::Item::axis_x; + break; + case config_store_ns::old_eeprom::v22::FooterItems::AxisY: + ret[i] = footer::Item::axis_y; + break; + case config_store_ns::old_eeprom::v22::FooterItems::AxisZ: + ret[i] = footer::Item::axis_z; + break; + case config_store_ns::old_eeprom::v22::FooterItems::ZHeight: + ret[i] = footer::Item::z_height; + break; + case config_store_ns::old_eeprom::v22::FooterItems::PrintFan: + ret[i] = footer::Item::print_fan; + break; + case config_store_ns::old_eeprom::v22::FooterItems::HeatbreakFan: + ret[i] = footer::Item::heatbreak_fan; + break; + case config_store_ns::old_eeprom::v22::FooterItems::Heatbreak: + ret[i] = footer::Item::heatbreak_temp; + break; + #if PRINTER_IS_PRUSA_MINI + case config_store_ns::old_eeprom::v22::FooterItems::LiveZ: + ret[i] = footer::Item::live_z; + break; + case config_store_ns::old_eeprom::v22::FooterItems::Sheets: + ret[i] = footer::Item::sheets; + break; + #endif + #if PRINTER_IS_PRUSA_XL + case config_store_ns::old_eeprom::v22::FooterItems::CurrentTool: + ret[i] = footer::Item::current_tool; + break; + case config_store_ns::old_eeprom::v22::FooterItems::AllNozzles: + ret[i] = footer::Item::all_nozzles; + break; + case config_store_ns::old_eeprom::v22::FooterItems::FSensorSide: + ret[i] = footer::Item::f_sensor_side; + break; + #endif + case config_store_ns::old_eeprom::v22::FooterItems::None: + case config_store_ns::old_eeprom::v22::FooterItems::_count: + default: // better to set the footer as missing than anything else in case of a random value + ret[i] = footer::Item::none; + break; + } + encoded >>= min_bit_size; + } + return ret; +} +#endif + /// This is just a check to make it harder to corrupt eeprom static_assert(ftrstd::to_underlying(Item::none) == 0 && ftrstd::to_underlying(Item::nozzle) == 1 diff --git a/src/common/footer_eeprom.hpp b/src/common/footer_eeprom.hpp index 665a4b8b35..e98d989a10 100644 --- a/src/common/footer_eeprom.hpp +++ b/src/common/footer_eeprom.hpp @@ -8,6 +8,7 @@ #pragma once #include "footer_def.hpp" #include "changed.hpp" +#include namespace footer::eeprom { /** @@ -72,4 +73,8 @@ draw_zero_t get_item_draw_zero(); */ uint8_t get_center_n_and_fewer(); +#if PRINTER_IS_PRUSA_MINI || PRINTER_IS_PRUSA_XL +Record decode_from_old_eeprom_v22(uint32_t encoded); +#endif + } // namespace footer::eeprom diff --git a/src/common/fsm_preheat_type.hpp b/src/common/fsm_preheat_type.hpp index 8dc5d58b41..f1ce6ae0db 100644 --- a/src/common/fsm_preheat_type.hpp +++ b/src/common/fsm_preheat_type.hpp @@ -53,12 +53,15 @@ class PreheatData { static constexpr RetAndCool_t GetRetAndCool(uint8_t data) { const bool has_ret = GetReturnOption(data); const bool has_cool = GetCooldownOption(data); - if (has_ret && has_cool) + if (has_ret && has_cool) { return RetAndCool_t::Both; - if (has_ret) + } + if (has_ret) { return RetAndCool_t::Return; - if (has_cool) + } + if (has_cool) { return RetAndCool_t::Cooldown; + } return RetAndCool_t::Neither; } static constexpr PreheatMode GetMode(uint8_t data) { diff --git a/src/common/gcode/gcode_buffer.cpp b/src/common/gcode/gcode_buffer.cpp index 3ce8783cd6..d621952171 100644 --- a/src/common/gcode/gcode_buffer.cpp +++ b/src/common/gcode/gcode_buffer.cpp @@ -37,8 +37,9 @@ bool GcodeBuffer::String::skip_gcode(const char *gcode_str) { for (auto it = begin;; ++it, ++gcode_str) { if (*gcode_str == '\0') { // We matched for example M2, but actual gcode number contiunues (for example M22) => don't match in that case - if (*it >= '0' && *it <= '9') + if (*it >= '0' && *it <= '9') { return false; + } begin = it; skip_ws(); return true; diff --git a/src/common/gcode/gcode_info.cpp b/src/common/gcode/gcode_info.cpp index 3ba3916ec3..e8bc108431 100644 --- a/src/common/gcode/gcode_info.cpp +++ b/src/common/gcode/gcode_info.cpp @@ -103,6 +103,7 @@ bool GCodeInfo::start_load(AnyGcodeFormatReader &file_reader) { return true; } else { + error_str_ = N_("Failed to open file"); start_load_result_ = StartLoadResult::Failed; return false; } @@ -112,6 +113,16 @@ void GCodeInfo::end_load(AnyGcodeFormatReader &file_reader) { file_reader.close(); } +bool GCodeInfo::check_still_valid() { + if (!transfers::is_valid_file_or_transfer(GetGcodeFilepath())) { + error_str_ = N_("File removed or transfer aborted"); + is_printable_ = false; + return false; + } + + return !has_error(); +} + bool GCodeInfo::check_valid_for_print(AnyGcodeFormatReader &file_reader) { assert(file_reader.is_open()); auto &reader = *file_reader.get(); @@ -149,6 +160,9 @@ void GCodeInfo::load(AnyGcodeFormatReader &file_reader) { has_preview_thumbnail_ = hasThumbnail(*file_reader.get(), GuiDefaults::PreviewThumbnailRect.Size()); has_progress_thumbnail_ = hasThumbnail(*file_reader.get(), GuiDefaults::ProgressThumbnailRect.Size()); + if (!has_progress_thumbnail_) { + has_progress_thumbnail_ = hasThumbnail(*file_reader.get(), { GuiDefaults::OldSlicerProgressImgWidth, GuiDefaults::ProgressThumbnailRect.Height() }); + } // scan info G-codes and comments PreviewInit(*file_reader.get()); @@ -185,8 +199,9 @@ uint32_t GCodeInfo::getPrinterModelCode() const { void GCodeInfo::EvaluateToolsValid() { EXTRUDER_LOOP() { // e == gcode_tool // do not check this nozzle if not used in print - if (!per_extruder_info[e].used()) + if (!per_extruder_info[e].used()) { continue; + } auto physical_tool = tools_mapping::to_physical_tool(e); if (physical_tool == tools_mapping::no_tool) { @@ -205,8 +220,8 @@ void GCodeInfo::EvaluateToolsValid() { if (per_extruder_info[e].nozzle_diameter.has_value()) { auto do_nozzle_check = [&](uint8_t hotend) { assert(hotend < HOTENDS); - float nozzle_diameter_distance = per_extruder_info[e].nozzle_diameter.value() - config_store().get_nozzle_diameter(hotend); - if (nozzle_diameter_distance > 0.001f || nozzle_diameter_distance < -0.001f) { + float nozzle_diameter_distance = std::abs(per_extruder_info[e].nozzle_diameter.value() - config_store().get_nozzle_diameter(hotend)); + if (nozzle_diameter_distance > 0.001f) { valid_printer_settings.wrong_nozzle_diameter.fail(); } }; @@ -333,8 +348,9 @@ void GCodeInfo::parse_m862(GcodeBuffer::String cmd) { { // format is M862.x, so remove dot char dot = cmd.pop_front(); - if (dot != '.') + if (dot != '.') { return; + } } char subcode = cmd.pop_front(); @@ -391,23 +407,28 @@ void GCodeInfo::parse_m862(GcodeBuffer::String cmd) { case '6': auto compare = [](GcodeBuffer::String &a, const char *b) { for (char *c = a.begin;; ++c, ++b) { - if (c == a.end || *b == '\0') + if (c == a.end || *b == '\0') { return c == a.end && *b == '\0'; - if (toupper(*c) != toupper(*b)) + } + if (toupper(*c) != toupper(*b)) { return false; + } } return *b == '\0'; }; auto find = [&](GcodeBuffer::String feature) { - for (auto &f : PrusaGcodeSuite::m862_6SupportedFeatures) - if (compare(feature, f)) + for (auto &f : PrusaGcodeSuite::m862_6SupportedFeatures) { + if (compare(feature, f)) { return true; + } + } return false; }; auto feature = cmd.get_string(); feature.trim(); - if (!find(feature)) + if (!find(feature)) { valid_printer_settings.add_unsupported_feature(feature.begin, feature.end - feature.begin); + } break; } } @@ -449,7 +470,12 @@ void GCodeInfo::parse_gcode(GcodeBuffer::String cmd, uint32_t &gcode_counter) { if (!is_up_to_date(cmd.c_str())) { valid_printer_settings.outdated_firmware.fail(); - strncpy(valid_printer_settings.latest_fw_version, cmd.c_str(), min(sizeof(valid_printer_settings.latest_fw_version), cmd.len())); + strlcpy(valid_printer_settings.latest_fw_version, cmd.c_str(), min(sizeof(valid_printer_settings.latest_fw_version), cmd.len())); + // Cut the string at the comment start + char *comment_start = strchr(valid_printer_settings.latest_fw_version, ';'); + if (comment_start) { + *comment_start = '\0'; + } } } } @@ -533,12 +559,23 @@ void GCodeInfo::parse_comment(GcodeBuffer::String comment) { valid_printer_settings.wrong_printer_model.fail(); } } +#if EXTRUDERS > 1 + else if (name == gcode_info::filament_wipe_tower_g) { + // load amount of material used filament for wipe tower + float temp; + sscanf(val.c_str(), "%f", &temp); + filament_wipe_tower_g = temp; + } +#endif } } void GCodeInfo::PreviewInit(IGcodeReader &reader) { valid_printer_settings = ValidPrinterSettings(); // reset to valid state per_extruder_info = {}; // Reset extruder info +#if EXTRUDERS > 1 + filament_wipe_tower_g = std::nullopt; +#endif GcodeBuffer buffer; diff --git a/src/common/gcode/gcode_info.hpp b/src/common/gcode/gcode_info.hpp index f56dca6cfe..0f6fd67ff0 100644 --- a/src/common/gcode/gcode_info.hpp +++ b/src/common/gcode/gcode_info.hpp @@ -23,6 +23,9 @@ inline constexpr const char *filament_type = "filament_type"; inline constexpr const char *extruder_colour = "extruder_colour"; inline constexpr const char *filament_mm = "filament used [mm]"; inline constexpr const char *filament_g = "filament used [g]"; +#if EXTRUDERS > 1 +inline constexpr const char *filament_wipe_tower_g = "total filament used for wipe tower [g]"; +#endif inline constexpr const char *printer = "printer_model"; inline constexpr const char *m862 = "M862"; inline constexpr const char *m115 = "M115"; @@ -136,7 +139,6 @@ class GCodeInfo { unsigned build_number = 0; }; - GcodeFwVersion gcode_fw_version; char latest_fw_version[sizeof("99.99.99-alpha99+999999")]; /** @@ -167,6 +169,9 @@ class GCodeInfo { std::atomic error_str_ = nullptr; ///< If there is an error, this variable can be used to report the error string time_buff printing_time; ///< Stores string representation of printing time left +#if EXTRUDERS > 1 + std::optional filament_wipe_tower_g = { std::nullopt }; ///< Grams of filament used for wipe tower +#endif bool has_preview_thumbnail_; ///< True if gcode has preview thumbnail bool has_progress_thumbnail_; ///< True if gcode has progress thumbnail bool filament_described; ///< Filament info was found in gcode's comments @@ -191,6 +196,9 @@ class GCodeInfo { const std::optional &get_bed_preheat_temp() const { return bed_preheat_temp; } ///< Get info about bed preheat temperature const std::optional &get_bed_preheat_area() const { return bed_preheat_area; } ///< Get info about G-preheat area inline const std::optional &get_hotend_preheat_temp() const { return hotend_preheat_temp; } +#if EXTRUDERS > 1 + std::optional get_filament_wipe_tower_g() const { return filament_wipe_tower_g; } ///< filament used for wipe tower +#endif /** * @brief Check if gcode is sliced with singletool profile. @@ -254,7 +262,15 @@ class GCodeInfo { void end_load(AnyGcodeFormatReader &file_reader); /** - * @brief Check if file is ready for print. + * @brief Checks if the file still exists and can be potentially printed. + * Softer version of check_valid_for_print, performs more basic checks. + * Does not set \c is_printable to true on success, you gotta \c check_valid_for_print for that. + * @return false on failure, sets \c is_printable to false and updates \c error_str + */ + bool check_still_valid(); + + /** + * @brief Check if file is ready for print. Updates \c is_printable and \c error_str. * @param file_reader gcode file reader, it cannot be accessed by other threads at the same time */ bool check_valid_for_print(AnyGcodeFormatReader &file_reader); diff --git a/src/common/gcode/gcode_reader.cpp b/src/common/gcode/gcode_reader.cpp index c816266503..56baa1193d 100644 --- a/src/common/gcode/gcode_reader.cpp +++ b/src/common/gcode/gcode_reader.cpp @@ -97,7 +97,7 @@ void IGcodeReader::update_validity(transfers::Transfer::Path &filename) { return arg; } else if constexpr (std::is_same_v) { - set_error(N_("File read error")); + set_error(arg.msg ?: N_("File read error")); // State saying "nothing available" return PartialFile::State(); @@ -118,11 +118,13 @@ bool IGcodeReader::check_file_starts_with_BGCODE_magic() const { static constexpr int magicSize = bgcode::core::MAGIC.size(); char check_buffer[magicSize]; - if (!fread(check_buffer, magicSize, 1, file)) + if (!fread(check_buffer, magicSize, 1, file)) { return false; + } - if (memcmp(check_buffer, bgcode::core::MAGIC.data(), magicSize)) + if (memcmp(check_buffer, bgcode::core::MAGIC.data(), magicSize)) { return false; + } return true; } @@ -167,8 +169,9 @@ bool PlainGcodeReader::stream_thumbnail_start(uint16_t expected_width, uint16_t PlainGcodeReader::Result_t PlainGcodeReader::stream_getc_impl(char &out) { int iout = fgetc(file); - if (iout == EOF) + if (iout == EOF) { return Result_t::RESULT_EOF; + } out = iout; return Result_t::RESULT_OK; } @@ -181,20 +184,23 @@ IGcodeReader::Result_t PlainGcodeReader::stream_get_line(GcodeBuffer &buffer) { while (true) { // get raw line, then decide if to output it or not auto res = IGcodeReader::stream_get_line(buffer); - if (res != Result_t::RESULT_OK) + if (res != Result_t::RESULT_OK) { return res; + } // detect if line is metadata (it starts with ;) buffer.line.skip_ws(); - if (buffer.line.is_empty()) + if (buffer.line.is_empty()) { continue; + } const bool is_metadata = (buffer.line.front() == ';'); // metadata are encoded as comment, this will also pass actual comments that are not medatata, but there is no other way to differentiate between those const bool is_gcode = !is_metadata; bool output = true; if (output_type == output_type_t::metadata) { - if (is_gcode) + if (is_gcode) { ++gcodes_in_metadata; + } // if we are reading metadata, read first x gcodes, that signals that metadata ends, and after that is done, seek to the end of file and continue streaming there // because that is where next interesting metadata is @@ -210,8 +216,9 @@ IGcodeReader::Result_t PlainGcodeReader::stream_get_line(GcodeBuffer &buffer) { } else { return Result_t::RESULT_ERROR; } - if (output) + if (output) { return Result_t::RESULT_OK; + } } return Result_t::RESULT_EOF; } @@ -219,16 +226,19 @@ IGcodeReader::Result_t PlainGcodeReader::stream_get_line(GcodeBuffer &buffer) { IGcodeReader::Result_t PlainGcodeReader::stream_getc_thumbnail_impl(char &out) { long pos = ftell(file); while (true) { - if (thumbnail_size == 0) + if (thumbnail_size == 0) { return Result_t::RESULT_EOF; + } if (!range_valid(pos, pos + 1)) { return Result_t::RESULT_OUT_OF_RANGE; } int c = fgetc(file); - if (feof(file)) + if (feof(file)) { return Result_t::RESULT_EOF; - if (ferror(file) && errno == EAGAIN) + } + if (ferror(file) && errno == EAGAIN) { return Result_t::RESULT_ERROR; + } pos++; // skip non-base64 characters @@ -327,8 +337,9 @@ bool PlainGcodeReader::IsBeginThumbnail(GcodeBuffer &buffer, uint16_t expected_w IGcodeReader::FileVerificationResult PlainGcodeReader::verify_file(FileVerificationLevel level, std::span crc_calc_buffer) const { // If plain gcode starts with bgcode magic, that means it's most like a binary gcode -> it's not a valid plain gcode - if (check_file_starts_with_BGCODE_magic()) + if (check_file_starts_with_BGCODE_magic()) { return { .error_str = N_("The file seems to be a binary gcode with a wrong suffix.") }; + } // Plain GCode does not have CRC checking (void)crc_calc_buffer; @@ -385,8 +396,9 @@ IGcodeReader::Result_t PrusaPackGcodeReader::read_block_header(BlockHeader &bloc } // now check if also block content is in valid range - if (!range_valid(block_start, block_start + block_header.get_size() + block_content_size(file_header, block_header))) + if (!range_valid(block_start, block_start + block_header.get_size() + block_content_size(file_header, block_header))) { return Result_t::RESULT_OUT_OF_RANGE; + } return Result_t::RESULT_OK; } @@ -399,8 +411,9 @@ std::optional PrusaPackGcodeReader::iterate_blocks(std::function PrusaPackGcodeReader::iterate_blocks(std::function 0 - we are starting from arbitrary offset, find nearest block from cache - if (!read_and_check_header()) + if (!read_and_check_header()) { return false; // need to check file header somewhere + } // pick nearest restore block from restore info stream_restore_info_rec_t *restore_block = get_restore_block_for_offset(offset); - if (restore_block == nullptr) + if (restore_block == nullptr) { return false; + } - if (fseek(file, restore_block->block_file_pos, SEEK_SET) != 0) + if (fseek(file, restore_block->block_file_pos, SEEK_SET) != 0) { return false; + } - if (auto res = read_block_header(start_block); res != Result_t::RESULT_OK) + if (auto res = read_block_header(start_block); res != Result_t::RESULT_OK) { return false; + } block_throwaway_bytes = offset - restore_block->block_start_offset; block_decompressed_offset = restore_block->block_start_offset; @@ -510,22 +530,25 @@ bool PrusaPackGcodeReader::stream_gcode_start(uint32_t offset) { stream.reset(); stream.current_block_header = std::move(start_block); - if (fread(&stream.encoding, 1, sizeof(stream.encoding), file) != sizeof(stream.encoding)) + if (fread(&stream.encoding, 1, sizeof(stream.encoding), file) != sizeof(stream.encoding)) { return false; + } stream.uncompressed_offset = block_decompressed_offset; stream.block_remaining_bytes_compressed = ((bgcode::core::ECompressionType)stream.current_block_header.compression == bgcode::core::ECompressionType::None) ? stream.current_block_header.uncompressed_size : stream.current_block_header.compressed_size; stream.multiblock = true; - if (!init_decompression()) + if (!init_decompression()) { return false; + } stream_restore_info.fill(stream_restore_info_rec_t()); store_restore_block(); while (block_throwaway_bytes--) { char c; - if (stream_getc(c) != IGcodeReader::Result_t::RESULT_OK) + if (stream_getc(c) != IGcodeReader::Result_t::RESULT_OK) { return false; + } } return true; @@ -533,21 +556,25 @@ bool PrusaPackGcodeReader::stream_gcode_start(uint32_t offset) { PlainGcodeReader::Result_t PrusaPackGcodeReader::switch_to_next_block() { // go to next block - if (bgcode::core::skip_block(*file, file_header, stream.current_block_header) != bgcode::core::EResult::Success) + if (bgcode::core::skip_block(*file, file_header, stream.current_block_header) != bgcode::core::EResult::Success) { return Result_t::RESULT_ERROR; + } // read next block BlockHeader new_block; - if (auto res = read_block_header(new_block); res != Result_t::RESULT_OK) + if (auto res = read_block_header(new_block); res != Result_t::RESULT_OK) { return res; + } // read encoding uint16_t encoding; - if (fread(&encoding, 1, sizeof(encoding), file) != sizeof(encoding)) + if (fread(&encoding, 1, sizeof(encoding), file) != sizeof(encoding)) { return Result_t::RESULT_ERROR; + } - if (stream.encoding != encoding || stream.current_block_header.type != new_block.type || stream.current_block_header.compression != new_block.compression) + if (stream.encoding != encoding || stream.current_block_header.type != new_block.type || stream.current_block_header.compression != new_block.compression) { return Result_t::RESULT_ERROR; + } // update stream stream.current_block_header = new_block; @@ -572,17 +599,19 @@ IGcodeReader::Result_t PrusaPackGcodeReader::stream_getc_file(char &out) { if (stream.block_remaining_bytes_compressed == 0) { if (stream.multiblock) { auto res = switch_to_next_block(); - if (res != Result_t::RESULT_OK) + if (res != Result_t::RESULT_OK) { return res; + } } else { return Result_t::RESULT_EOF; } } stream.block_remaining_bytes_compressed--; // assume 1 byte was read, it might return EOF/ERROR, but at this point it doesn't matter as stream is done anyway int iout = fgetc(file); - if (iout == EOF) + if (iout == EOF) { // if fgetc returned EOF, there is something wrong, because that means EOF was found in the middle of block return Result_t::RESULT_ERROR; + } out = iout; return Result_t::RESULT_OK; } @@ -590,8 +619,9 @@ IGcodeReader::Result_t PrusaPackGcodeReader::stream_getc_file(char &out) { IGcodeReader::Result_t PrusaPackGcodeReader::stream_current_block_read(char *buffer, size_t size) { auto read_res = fread(buffer, 1, size, file); stream.block_remaining_bytes_compressed -= size; - if (read_res != size) + if (read_res != size) { return IGcodeReader::Result_t::RESULT_ERROR; + } return IGcodeReader::Result_t::RESULT_OK; } @@ -641,16 +671,18 @@ IGcodeReader::Result_t PrusaPackGcodeReader::stream_getc_decompressed_heatshrink } if (stream.multiblock) { auto res = switch_to_next_block(); - if (res != Result_t::RESULT_OK) + if (res != Result_t::RESULT_OK) { return res; + } } else { return Result_t::RESULT_EOF; } } auto sink_res = heatshrink_sink_data(); - if (sink_res != Result_t::RESULT_OK) + if (sink_res != Result_t::RESULT_OK) { return sink_res; + } } } } @@ -667,8 +699,9 @@ IGcodeReader::Result_t PrusaPackGcodeReader::stream_getc_decode_meatpacked(char // no character, uncompress next character char mp_char; auto res = (this->*ptr_stream_getc_decompressed)(mp_char); - if (res != Result_t::RESULT_OK) + if (res != Result_t::RESULT_OK) { return res; + } stream.meatpack.handle_rx_char(mp_char); } @@ -710,12 +743,14 @@ bool PrusaPackGcodeReader::stream_thumbnail_start(uint16_t expected_width, uint1 } bgcode::core::ThumbnailParams thumb_header; - if (thumb_header.read(*file) != bgcode::core::EResult::Success) + if (thumb_header.read(*file) != bgcode::core::EResult::Success) { return IterateResult_t::Continue; + } // format not valid - if (thumbnail_format_to_type(static_cast(thumb_header.format)) != expected_type) + if (thumbnail_format_to_type(static_cast(thumb_header.format)) != expected_type) { return IterateResult_t::Continue; + } if (expected_height == thumb_header.height && expected_width == thumb_header.width) { return IterateResult_t::Return; @@ -741,8 +776,9 @@ PrusaPackGcodeReader::Result_t PrusaPackGcodeReader::stream_get_block(char *out_ size = 0; while (size != orig_size) { auto res = stream_getc(*(out_data++)); - if (res != IGcodeReader::Result_t::RESULT_OK) + if (res != IGcodeReader::Result_t::RESULT_OK) { return res; + } ++size; } return Result_t::RESULT_OK; @@ -804,8 +840,9 @@ uint32_t PrusaPackGcodeReader::get_gcode_stream_size() { IGcodeReader::FileVerificationResult PrusaPackGcodeReader::verify_file(FileVerificationLevel level, std::span crc_calc_buffer) const { // Every binary gcode has to start a magic sequence - if (!check_file_starts_with_BGCODE_magic()) + if (!check_file_starts_with_BGCODE_magic()) { return { .error_str = N_("The file is not a valid bgcode file.") }; + } // Further checks are for FileVerificationLevel::full if (int(level) < int(FileVerificationLevel::full)) { @@ -816,8 +853,9 @@ IGcodeReader::FileVerificationResult PrusaPackGcodeReader::verify_file(FileVerif { // todo: this doesn't respect file validity rewind(file); - if (bgcode::core::is_valid_binary_gcode(*file, true, crc_calc_buffer.data(), crc_calc_buffer.size()) != bgcode::core::EResult::Success) + if (bgcode::core::is_valid_binary_gcode(*file, true, crc_calc_buffer.data(), crc_calc_buffer.size()) != bgcode::core::EResult::Success) { return { .error_str = N_("The file is not a valid bgcode file.") }; + } } return { .is_ok = true }; @@ -869,8 +907,9 @@ bool PrusaPackGcodeReader::valid_for_print() { // all metadata has to be preset at that point, because they are before gcode block auto res = iterate_blocks([](BlockHeader &block_header) { // check if correct type, if so, return this block - if ((bgcode::core::EBlockType)block_header.type == bgcode::core::EBlockType::GCode) + if ((bgcode::core::EBlockType)block_header.type == bgcode::core::EBlockType::GCode) { return IterateResult_t::Return; + } return IterateResult_t::Continue; }); @@ -929,8 +968,9 @@ IGcodeReader *AnyGcodeFormatReader::open(const char *filename) { storage.emplace(*file, info); ptr = &std::get(storage); - if (is_partial) + if (is_partial) { ptr->update_validity(path); + } return ptr; @@ -938,8 +978,9 @@ IGcodeReader *AnyGcodeFormatReader::open(const char *filename) { storage.emplace(*file, info); ptr = &std::get(storage); - if (is_partial) + if (is_partial) { ptr->update_validity(path); + } return ptr; } @@ -965,7 +1006,8 @@ void PrusaPackGcodeReader::stream_t::reset() { } PrusaPackGcodeReader::stream_t::~stream_t() { - if (hs_decoder) + if (hs_decoder) { heatshrink_decoder_free(hs_decoder); + } hs_decoder = nullptr; } diff --git a/src/common/gcode/gcode_reader.hpp b/src/common/gcode/gcode_reader.hpp index 2cd9d61be2..fabda5c473 100644 --- a/src/common/gcode/gcode_reader.hpp +++ b/src/common/gcode/gcode_reader.hpp @@ -223,8 +223,8 @@ class PlainGcodeReader : public IGcodeReader { }; // Size of header that have to be valid before we start printing - // One big file was observed to have header with size of 302KB, so this adds some headroom - static constexpr const size_t header_metadata_size = 400 * 1024; + // One big file was observed to have header with size of 428 kB, so this adds some headroom + static constexpr const size_t header_metadata_size = 512 * 1024; // when reading metadata and we encounter this number of gcodes, skip to end of file to search further static constexpr const uint32_t stop_metadata_after_gcodes_num = 1; diff --git a/src/common/gcode/meatpack.cpp b/src/common/gcode/meatpack.cpp index 0e929b4d71..5e9f00e579 100644 --- a/src/common/gcode/meatpack.cpp +++ b/src/common/gcode/meatpack.cpp @@ -73,17 +73,17 @@ uint8_t MeatPack::unpack_chars(const uint8_t pk, uint8_t *__restrict const chars uint8_t out = 0; // If lower nybble is 1111, the higher nybble is unused, and next char is full. - if ((pk & kFirstNotPacked) == kFirstNotPacked) + if ((pk & kFirstNotPacked) == kFirstNotPacked) { out = kFirstCharIsLiteral; - else { + } else { const uint8_t chr = pk & 0x0F; chars_out[0] = meatPackLookupTable[chr]; // Set the first char } // Check if upper nybble is 1111... if so, we don't need the second char. - if ((pk & kSecondNotPacked) == kSecondNotPacked) + if ((pk & kSecondNotPacked) == kSecondNotPacked) { out |= kSecondCharIsLiteral; - else { + } else { const uint8_t chr = (pk >> 4) & 0x0F; chars_out[1] = meatPackLookupTable[chr]; // Set the second char } @@ -102,17 +102,19 @@ void MeatPack::handle_rx_char_inner(const uint8_t c) { const uint8_t res = unpack_chars(c, buf); // Decode the byte into one or two characters. if (res & kFirstCharIsLiteral) { // The 1st character couldn't be packed. ++full_char_count; // So the next stream byte is a full character. - if (res & kSecondCharIsLiteral) + if (res & kSecondCharIsLiteral) { ++full_char_count; // The 2nd character couldn't be packed. Another stream byte is a full character. - else + } else { second_char = buf[1]; // Retain the unpacked second character. + } } else { handle_output_char(buf[0]); // Send the unpacked first character out. if (buf[0] != '\n') { // After a newline the next char won't be set - if (res & kSecondCharIsLiteral) + if (res & kSecondCharIsLiteral) { ++full_char_count; // The 2nd character couldn't be packed. The next stream byte is a full character. - else + } else { handle_output_char(buf[1]); // Send the unpacked second character out. + } } } } else { @@ -123,8 +125,9 @@ void MeatPack::handle_rx_char_inner(const uint8_t c) { } --full_char_count; // One literal character was consumed } - } else // Packing not enabled, just copy character to output + } else { // Packing not enabled, just copy character to output handle_output_char(c); + } } /** @@ -181,8 +184,9 @@ void MeatPack::handle_rx_char(const uint8_t c) { if (cmd_count) { // In fact, two in a row? cmd_is_next = true; // Then a MeatPack command follows cmd_count = 0; - } else + } else { ++cmd_count; // cmd_count = 1 // One command byte received so far... + } return; } @@ -205,15 +209,17 @@ uint8_t MeatPack::get_result_chars(char *const __restrict out) { if (char_out_count) { res = char_out_count; char_out_count = 0; - for (uint8_t i = 0; i < res; ++i) + for (uint8_t i = 0; i < res; ++i) { out[i] = (char)char_out_buf[i]; + } } return res; } char MeatPack::get_result_char() { - if (char_out_count == 0) + if (char_out_count == 0) { return 0; + } --char_out_count; auto res = char_out_buf[0]; char_out_buf[0] = char_out_buf[1]; diff --git a/src/common/heap.cpp b/src/common/heap.cpp index c2ee2b70d4..4d5e294d76 100644 --- a/src/common/heap.cpp +++ b/src/common/heap.cpp @@ -94,15 +94,17 @@ static int malloc_lock_counter = 0; void __malloc_lock([[maybe_unused]] struct _reent *r) { UBaseType_t interrupt_status; ENTER_CRITICAL_SECTION(interrupt_status); - if (malloc_lock_counter == 0) + if (malloc_lock_counter == 0) { malloc_saved_interrupt_status = interrupt_status; + } malloc_lock_counter += 1; }; void __malloc_unlock([[maybe_unused]] struct _reent *r) { malloc_lock_counter -= 1; - if (malloc_lock_counter == 0) + if (malloc_lock_counter == 0) { EXIT_CRITICAL_SECTION(malloc_saved_interrupt_status); + } }; uint32_t mem_is_heap_allocated(const void *ptr) { diff --git a/src/common/http/socket.cpp b/src/common/http/socket.cpp index 4b40843da4..b8950c7287 100644 --- a/src/common/http/socket.cpp +++ b/src/common/http/socket.cpp @@ -111,15 +111,17 @@ std::optional socket_con::connection(const char *host, uint16_t port) { } } - if (!connected) + if (!connected) { return Error::Connect; - else + } else { return std::nullopt; + } } std::variant socket_con::tx(const uint8_t *send_buffer, size_t data_len) { - if (!connected) + if (!connected) { return Error::InternalError; + } size_t bytes_sent = 0; @@ -140,8 +142,9 @@ std::variant socket_con::tx(const uint8_t *send_buffer, size_t da } std::variant socket_con::rx(uint8_t *read_buffer, size_t buffer_len, bool nonblock) { - if (!connected) + if (!connected) { return Error::InternalError; + } size_t bytes_received = 0; diff --git a/src/common/http/types.h b/src/common/http/types.h index f577659371..155d9d3bb5 100644 --- a/src/common/http/types.h +++ b/src/common/http/types.h @@ -149,11 +149,12 @@ static const size_t MAX_URL_LEN = 168; using Url = std::array; // # of seconds after which nonce becomes stale for digest authentication -// the extended version is used for requests with body, so that PrusaLink -// hopefully never gets stale nonce for request uploading a gcode, which -// can cause an infinit upload loop, if the browser does not read errors -// before sending the whole body. -static const uint32_t valid_nonce_period = 5; -static const uint32_t extended_valid_nonce_period = 8; +// The value of 300 has been chosen as it's the default value used in the Apache +// web server, see: +// https://httpd.apache.org/docs/2.4/mod/mod_auth_digest.html#authdigestnoncelifetime +// +// This value use to be much lower but would cause issues with Safari-based browser +// See https://github.com/prusa3d/Prusa-Firmware-Buddy/issues/3287 +static const uint32_t valid_nonce_period = 300; } // namespace http diff --git a/src/common/http/url_decode.cpp b/src/common/http/url_decode.cpp index 9dba9f2985..1f5c564111 100644 --- a/src/common/http/url_decode.cpp +++ b/src/common/http/url_decode.cpp @@ -2,8 +2,9 @@ namespace http { bool url_decode(std::string_view url, char *decoded_url, size_t decoded_url_len) { - if (decoded_url_len == 0) + if (decoded_url_len == 0) { return false; + } size_t out_index = 0; for (size_t i = 0; i < url.size(); i++) { @@ -12,13 +13,15 @@ bool url_decode(std::string_view url, char *decoded_url, size_t decoded_url_len) decoded_url[out_index] = ' '; break; case '%': { - if (decoded_url_len < i + 3) + if (decoded_url_len < i + 3) { return false; + } int ascii_value; auto curr_iter = url.begin() + i; auto result = std::from_chars(curr_iter + 1, curr_iter + 3, ascii_value, 16); - if (result.ec != std::errc {}) + if (result.ec != std::errc {}) { return false; + } decoded_url[out_index] = static_cast(ascii_value); i = i + 2; diff --git a/src/common/hwio_XLBuddy.cpp b/src/common/hwio_XLBuddy.cpp index 26efcfee19..8f741b75a8 100644 --- a/src/common/hwio_XLBuddy.cpp +++ b/src/common/hwio_XLBuddy.cpp @@ -175,8 +175,9 @@ int hwio_pwm_get_cnt(void) // number of pwm outputs static constexpr int hwio_pwm_get_max(int i_pwm) // pwm output maximum value { - if (!is_pwm_id_valid(i_pwm)) + if (!is_pwm_id_valid(i_pwm)) { return -1; + } return _pwm_max[i_pwm]; } @@ -184,12 +185,14 @@ static constexpr int hwio_pwm_get_max(int i_pwm) // pwm output maximum value // affects multiple channels void hwio_pwm_set_period_us(int i_pwm, int T_us) // set pwm resolution { - if (!is_pwm_id_valid(i_pwm)) + if (!is_pwm_id_valid(i_pwm)) { return; + } int *ptr_period_us = _pwm_period_us[i_pwm]; - if (T_us == *ptr_period_us) + if (T_us == *ptr_period_us) { return; + } int prescaler = T_us * (int32_t)TIM_BASE_CLK_MHZ / (_pwm_max[i_pwm] + 1) - 1; hwio_pwm_set_prescaler(i_pwm, prescaler); @@ -198,14 +201,16 @@ void hwio_pwm_set_period_us(int i_pwm, int T_us) // set pwm resolution } int hwio_pwm_get_period_us(int i_pwm) { - if (!is_pwm_id_valid(i_pwm)) + if (!is_pwm_id_valid(i_pwm)) { return -1; + } return *_pwm_period_us[i_pwm]; } void hwio_pwm_set_prescaler(int i_pwm, int prescaler) { - if (hwio_pwm_get_prescaler(i_pwm) == prescaler) + if (hwio_pwm_get_prescaler(i_pwm) == prescaler) { return; + } TIM_HandleTypeDef *htim = _pwm_get_htim(i_pwm); @@ -225,8 +230,9 @@ void hwio_pwm_set_prescaler(int i_pwm, int prescaler) { } int hwio_pwm_get_prescaler(int i_pwm) { - if (!is_pwm_id_valid(i_pwm)) + if (!is_pwm_id_valid(i_pwm)) { return -1; + } TIM_HandleTypeDef *htim = _pwm_get_htim(i_pwm); return htim->Init.Prescaler; } @@ -247,8 +253,9 @@ void hwio_pwm_set_prescaler_exp2(int i_pwm, int exp) { // reading value set by hwio_pwm_set_prescaler_exp2 int hwio_pwm_get_prescaler_log2(int i_pwm) { - if (!is_pwm_id_valid(i_pwm)) + if (!is_pwm_id_valid(i_pwm)) { return -1; + } uint32_t prescaler = hwio_pwm_get_prescaler(i_pwm) + 1; int index = 0; @@ -261,22 +268,25 @@ int hwio_pwm_get_prescaler_log2(int i_pwm) { } uint32_t _pwm_get_chan(int i_pwm) { - if (!is_pwm_id_valid(i_pwm)) + if (!is_pwm_id_valid(i_pwm)) { return -1; + } return _pwm_chan[i_pwm]; } TIM_HandleTypeDef *_pwm_get_htim(int i_pwm) { - if (!is_pwm_id_valid(i_pwm)) + if (!is_pwm_id_valid(i_pwm)) { i_pwm = 0; + } return _pwm_p_htim[i_pwm]; } void hwio_pwm_set_val(int i_pwm, uint32_t val) // write pwm output and update _pwm_analogWrite_val { - if (!is_pwm_id_valid(i_pwm)) + if (!is_pwm_id_valid(i_pwm)) { return; + } uint32_t chan = _pwm_get_chan(i_pwm); TIM_HandleTypeDef *htim = _pwm_get_htim(i_pwm); @@ -308,26 +318,29 @@ void __pwm_set_val(TIM_HandleTypeDef *htim, uint32_t pchan, int val) // write pw { if (htim->Init.Period) { TIM_OC_InitTypeDef sConfigOC = sConfigOC_default; - if (val) + if (val) { sConfigOC.Pulse = val; - else { + } else { sConfigOC.Pulse = htim->Init.Period; - if (sConfigOC.OCPolarity == TIM_OCPOLARITY_HIGH) + if (sConfigOC.OCPolarity == TIM_OCPOLARITY_HIGH) { sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW; - else + } else { sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; + } } if (HAL_TIM_PWM_ConfigChannel(htim, &sConfigOC, pchan) != HAL_OK) { Error_Handler(); } HAL_TIM_PWM_Start(htim, pchan); - } else + } else { HAL_TIM_PWM_Stop(htim, pchan); + } } void _hwio_pwm_analogWrite_set_val(int i_pwm, int val) { - if (!is_pwm_id_valid(i_pwm)) + if (!is_pwm_id_valid(i_pwm)) { return; + } if (_pwm_analogWrite_val[i_pwm] != val) { const int32_t pwm_max = hwio_pwm_get_max(i_pwm); @@ -345,8 +358,9 @@ int hwio_fan_get_cnt(void) // number of fans void hwio_fan_set_pwm(int i_fan, int val) { i_fan += _FAN_ID_MIN; - if ((i_fan >= _FAN_ID_MIN) && (i_fan <= _FAN_ID_MAX)) + if ((i_fan >= _FAN_ID_MIN) && (i_fan <= _FAN_ID_MAX)) { _hwio_pwm_analogWrite_set_val(i_fan, val); + } } //-------------------------------------- @@ -368,10 +382,12 @@ float hwio_beeper_get_vol(void) { } void hwio_beeper_set_vol(float vol) { - if (vol < 0) + if (vol < 0) { vol *= -1; - if (vol > 1) + } + if (vol > 1) { vol = 1; + } hwio_beeper_vol = vol; } @@ -379,16 +395,19 @@ void hwio_beeper_tone(float frq, uint32_t del) { uint32_t per; uint32_t pul; if (frq && del && hwio_beeper_vol) { - if (frq < 0) + if (frq < 0) { frq *= -1; - if (frq > 100000) + } + if (frq > 100000) { frq = 100000; + } per = (uint32_t)(1'000.0F / frq); pul = (uint32_t)(del / per); hwio_beeper_pulses = pul; hwio_beeper_period = per; - } else + } else { hwio_beeper_pulses = 0; + } } void hwio_beeper_tone2(float frq, uint32_t del, float vol) { @@ -607,8 +626,9 @@ uint32_t analogRead(uint32_t ulPin) { default: hwio_arduino_error(HWIO_ERR_UNDEF_ANA_RD, ulPin); // error: undefined pin analog read } - } else + } else { hwio_arduino_error(HWIO_ERR_UNINI_ANA_RD, ulPin); // error: uninitialized analog read + } return 0; } diff --git a/src/common/hwio_buddy_2209_02.cpp b/src/common/hwio_buddy_2209_02.cpp index fe8dc75689..dcd2f368d0 100644 --- a/src/common/hwio_buddy_2209_02.cpp +++ b/src/common/hwio_buddy_2209_02.cpp @@ -179,8 +179,9 @@ int hwio_pwm_get_cnt(void) // number of pwm outputs static constexpr int hwio_pwm_get_max(int i_pwm) // pwm output maximum value { - if (!is_pwm_id_valid(i_pwm)) + if (!is_pwm_id_valid(i_pwm)) { return -1; + } return _pwm_max[i_pwm]; } @@ -188,12 +189,14 @@ static constexpr int hwio_pwm_get_max(int i_pwm) // pwm output maximum value // affects multiple channels void hwio_pwm_set_period_us(int i_pwm, int T_us) // set pwm resolution { - if (!is_pwm_id_valid(i_pwm)) + if (!is_pwm_id_valid(i_pwm)) { return; + } int *ptr_period_us = _pwm_period_us[i_pwm]; - if (T_us == *ptr_period_us) + if (T_us == *ptr_period_us) { return; + } int prescaler = T_us * (int32_t)TIM_BASE_CLK_MHZ / (_pwm_max[i_pwm] + 1) - 1; hwio_pwm_set_prescaler(i_pwm, prescaler); @@ -202,14 +205,16 @@ void hwio_pwm_set_period_us(int i_pwm, int T_us) // set pwm resolution } int hwio_pwm_get_period_us(int i_pwm) { - if (!is_pwm_id_valid(i_pwm)) + if (!is_pwm_id_valid(i_pwm)) { return -1; + } return *_pwm_period_us[i_pwm]; } void hwio_pwm_set_prescaler(int i_pwm, int prescaler) { - if (hwio_pwm_get_prescaler(i_pwm) == prescaler) + if (hwio_pwm_get_prescaler(i_pwm) == prescaler) { return; + } TIM_HandleTypeDef *htim = _pwm_get_htim(i_pwm); @@ -229,8 +234,9 @@ void hwio_pwm_set_prescaler(int i_pwm, int prescaler) { } int hwio_pwm_get_prescaler(int i_pwm) { - if (!is_pwm_id_valid(i_pwm)) + if (!is_pwm_id_valid(i_pwm)) { return -1; + } TIM_HandleTypeDef *htim = _pwm_get_htim(i_pwm); return htim->Init.Prescaler; } @@ -251,8 +257,9 @@ void hwio_pwm_set_prescaler_exp2(int i_pwm, int exp) { // reading value set by hwio_pwm_set_prescaler_exp2 int hwio_pwm_get_prescaler_log2(int i_pwm) { - if (!is_pwm_id_valid(i_pwm)) + if (!is_pwm_id_valid(i_pwm)) { return -1; + } uint32_t prescaler = hwio_pwm_get_prescaler(i_pwm) + 1; int index = 0; @@ -265,22 +272,25 @@ int hwio_pwm_get_prescaler_log2(int i_pwm) { } uint32_t _pwm_get_chan(int i_pwm) { - if (!is_pwm_id_valid(i_pwm)) + if (!is_pwm_id_valid(i_pwm)) { return -1; + } return _pwm_chan[i_pwm]; } TIM_HandleTypeDef *_pwm_get_htim(int i_pwm) { - if (!is_pwm_id_valid(i_pwm)) + if (!is_pwm_id_valid(i_pwm)) { i_pwm = 0; + } return _pwm_p_htim[i_pwm]; } void hwio_pwm_set_val(int i_pwm, uint32_t val) // write pwm output and update _pwm_analogWrite_val { - if (!is_pwm_id_valid(i_pwm)) + if (!is_pwm_id_valid(i_pwm)) { return; + } uint32_t chan = _pwm_get_chan(i_pwm); TIM_HandleTypeDef *htim = _pwm_get_htim(i_pwm); @@ -312,14 +322,15 @@ void __pwm_set_val(TIM_HandleTypeDef *htim, uint32_t pchan, int val) // write pw { if (htim->Init.Period) { TIM_OC_InitTypeDef sConfigOC = sConfigOC_default; - if (val) + if (val) { sConfigOC.Pulse = val; - else { + } else { sConfigOC.Pulse = htim->Init.Period; - if (sConfigOC.OCPolarity == TIM_OCPOLARITY_HIGH) + if (sConfigOC.OCPolarity == TIM_OCPOLARITY_HIGH) { sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW; - else + } else { sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH; + } } if (HAL_TIM_PWM_Stop(htim, pchan) != HAL_OK) { Error_Handler(); @@ -338,8 +349,9 @@ void __pwm_set_val(TIM_HandleTypeDef *htim, uint32_t pchan, int val) // write pw } void _hwio_pwm_analogWrite_set_val(int i_pwm, int val) { - if (!is_pwm_id_valid(i_pwm)) + if (!is_pwm_id_valid(i_pwm)) { return; + } switch (i_pwm) { case HWIO_PWM_HEATER_0: @@ -366,8 +378,9 @@ int hwio_fan_get_cnt(void) // number of fans void hwio_fan_set_pwm(int i_fan, int val) { i_fan += _FAN_ID_MIN; - if ((i_fan >= _FAN_ID_MIN) && (i_fan <= _FAN_ID_MAX)) + if ((i_fan >= _FAN_ID_MIN) && (i_fan <= _FAN_ID_MAX)) { _hwio_pwm_analogWrite_set_val(i_fan, val); + } } //-------------------------------------- @@ -389,10 +402,12 @@ float hwio_beeper_get_vol(void) { } void hwio_beeper_set_vol(float vol) { - if (vol < 0) + if (vol < 0) { vol *= -1; - if (vol > 1) + } + if (vol > 1) { vol = 1; + } hwio_beeper_vol = vol; } @@ -416,8 +431,9 @@ void hwio_beeper_set_pwm(uint32_t per, uint32_t pul) { sConfigOC.OCFastMode = TIM_OCFAST_DISABLE; HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1); HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1); - } else + } else { HAL_TIM_PWM_Stop(&htim2, TIM_CHANNEL_1); + } } #else void hwio_beeper_set_pwm([[maybe_unused]] uint32_t per, [[maybe_unused]] uint32_t pul) {} // Without display, there is no beeper to beep. @@ -427,10 +443,12 @@ void hwio_beeper_tone(float frq, uint32_t del) { uint32_t per; uint32_t pul; if (frq && del && hwio_beeper_vol) { - if (frq < 0) + if (frq < 0) { frq *= -1; - if (frq > 100000) + } + if (frq > 100000) { frq = 100000; + } #if HAS_BEEPER_WITHOUT_PWM per = (uint32_t)(1'000.0F / frq); pul = (uint32_t)(del / per); @@ -442,8 +460,9 @@ void hwio_beeper_tone(float frq, uint32_t del) { hwio_beeper_set_pwm(per, pul); hwio_beeper_del = del; #endif - } else + } else { hwio_beeper_notone(); + } } void hwio_beeper_tone2(float frq, uint32_t del, float vol) { @@ -461,8 +480,9 @@ void hwio_beeper_notone(void) { void hwio_update_1ms(void) { #if !HAS_BEEPER_WITHOUT_PWM - if ((hwio_beeper_del) && ((--hwio_beeper_del) == 0)) + if ((hwio_beeper_del) && ((--hwio_beeper_del) == 0)) { hwio_beeper_set_pwm(0, 0); + } #elif HAS_GUI() && !(_DEBUG) static uint32_t skips = 0; if (skips < hwio_beeper_period - 1) { @@ -672,8 +692,9 @@ uint32_t analogRead(uint32_t ulPin) { default: hwio_arduino_error(HWIO_ERR_UNDEF_ANA_RD, ulPin); // error: undefined pin analog read } - } else + } else { hwio_arduino_error(HWIO_ERR_UNINI_ANA_RD, ulPin); // error: uninitialized analog read + } return 0; } @@ -699,8 +720,9 @@ void analogWrite(uint32_t ulPin, uint32_t ulValue) { default: hwio_arduino_error(HWIO_ERR_UNDEF_ANA_WR, ulPin); // error: undefined pin analog write } - } else + } else { hwio_arduino_error(HWIO_ERR_UNINI_ANA_WR, ulPin); // error: uninitialized analog write + } } void pinMode([[maybe_unused]] uint32_t ulPin, [[maybe_unused]] uint32_t ulMode) { diff --git a/src/common/hwio_pindef_check.cpp b/src/common/hwio_pindef_check.cpp index fcae6d21f6..a8295cba83 100644 --- a/src/common/hwio_pindef_check.cpp +++ b/src/common/hwio_pindef_check.cpp @@ -17,10 +17,13 @@ constexpr PinChecker pinsToCheck[] = { }; constexpr bool has_duplicates(const PinChecker (&array)[std::size(pinsToCheck)]) { - for (size_t i = 1; i < std::size(array); i++) - for (size_t j = 0; j < i; j++) - if ((array[i].getPort() == array[j].getPort()) && (array[i].getPin() == array[j].getPin())) + for (size_t i = 1; i < std::size(array); i++) { + for (size_t j = 0; j < i; j++) { + if ((array[i].getPort() == array[j].getPort()) && (array[i].getPin() == array[j].getPin())) { return true; + } + } + } return false; } diff --git a/src/common/hx717.cpp b/src/common/hx717.cpp index 168bf82c9f..08fcd6b5a0 100644 --- a/src/common/hx717.cpp +++ b/src/common/hx717.cpp @@ -66,8 +66,9 @@ int32_t HX717::ReadValue(Channel nextChannel, uint32_t readyTimestamp) { static constexpr int32_t loopCycles = 2; static constexpr int32_t disableEnableIrqCycles = 2; - if (!IsValueReady()) + if (!IsValueReady()) { goto reset; + } // Disable the IRQ before it starts to trigger due to the data read hx717Dout.disableIRQ(); @@ -111,8 +112,9 @@ int32_t HX717::ReadValue(Channel nextChannel, uint32_t readyTimestamp) { } // extend 2's complement to 32bits - if (result >= 0x800000) + if (result >= 0x800000) { result |= 0xFF000000; + } if (IsValueReady() || result < -0x7FFFFF || result > 0x7FFFFF) { // DOUT should automatically switch off after a correct readout. If that happens, and/or if diff --git a/src/common/hx717mux.cpp b/src/common/hx717mux.cpp index 0032dc497b..d6ca6a946f 100644 --- a/src/common/hx717mux.cpp +++ b/src/common/hx717mux.cpp @@ -31,10 +31,11 @@ void HX717Mux::handler() { // Configure the channel for the next read sample_counter = (sample_counter + 1) % sample_switch_count; HX717::Channel next_channel; - if (!(loadcell.IsHighPrecisionEnabled()) && !sample_counter) + if (!(loadcell.IsHighPrecisionEnabled()) && !sample_counter) { next_channel = hx717.CHANNEL_B_GAIN_8; // fs - else + } else { next_channel = hx717.CHANNEL_A_GAIN_128; // loadcell + } int32_t raw_value; @@ -80,8 +81,9 @@ void HX717Mux::handler() { // always forward the sample to the correct subsystem if (current_channel == hx717.CHANNEL_A_GAIN_128) { - if (!std::isnan(sample_interval)) + if (!std::isnan(sample_interval)) { loadcell.analysis.SetSamplingIntervalMs(sample_interval); + } loadcell.ProcessSample(raw_value, sample_timestamp); } else { fs_process_sample(raw_value, 0); diff --git a/src/common/i2c.cpp b/src/common/i2c.cpp index 7db070da3e..012c184c57 100644 --- a/src/common/i2c.cpp +++ b/src/common/i2c.cpp @@ -226,13 +226,15 @@ class [[nodiscard]] MoveIsrDisabler { public: MoveIsrDisabler() { old_move_isr_state = MOVE_ISR_ENABLED(); - if (old_move_isr_state) + if (old_move_isr_state) { DISABLE_MOVE_INTERRUPT(); + } } ~MoveIsrDisabler() { - if (old_move_isr_state) + if (old_move_isr_state) { ENABLE_MOVE_INTERRUPT(); + } } }; @@ -247,8 +249,9 @@ Result Transmit(I2C_HandleTypeDef &hi2c, uint16_t DevAddress, uint8_t *pData, ui result = HAL_I2C_Master_Transmit(&hi2c, DevAddress, pData, Size, Timeout); } res = process_result(hi2c, result); - if (result != HAL_BUSY) + if (result != HAL_BUSY) { break; + } } return res; @@ -266,8 +269,9 @@ Result Receive(I2C_HandleTypeDef &hi2c, uint16_t DevAddress, uint8_t *pData, uin result = HAL_I2C_Master_Receive(&hi2c, DevAddress, pData, Size, Timeout); } res = process_result(hi2c, result); - if (result != HAL_BUSY) + if (result != HAL_BUSY) { break; + } } return res; @@ -284,8 +288,9 @@ static Result Mem_Write(I2C_HandleTypeDef &hi2c, uint16_t DevAddress, uint16_t M result = HAL_I2C_Mem_Write(&hi2c, DevAddress, MemAddress, MemAddSize, pData, Size, Timeout); } res = process_result(hi2c, result); - if (res == Result::ok) + if (res == Result::ok) { break; + } } return res; @@ -310,8 +315,9 @@ Result Mem_Write_16bit_Addr(I2C_HandleTypeDef &hi2c, uint16_t DevAddress, uint16 result = HAL_I2C_Mem_Read(&hi2c, DevAddress, MemAddress, MemAddSize, pData, Size, Timeout); } res = process_result(hi2c, result); - if (res != Result::ok) + if (res != Result::ok) { break; + } } return res; diff --git a/src/common/lang.cpp b/src/common/lang.cpp index 0b989c7d9c..35a66a62a7 100644 --- a/src/common/lang.cpp +++ b/src/common/lang.cpp @@ -26,9 +26,11 @@ static const size_t LANG_ITEMS = sizeof(lang_list) / sizeof(lang_list[0]); /// inner function (language-table item finding) static const lang_t *get_lang_item(lang_code_t lang_code) { - for (uint32_t i = 1; i < LANG_ITEMS; i++) // ie. skip first item in language-table - if (lang_code == lang_list[i].lang_code) + for (uint32_t i = 1; i < LANG_ITEMS; i++) { // ie. skip first item in language-table + if (lang_code == lang_list[i].lang_code) { return (&lang_list[i]); + } + } return (&lang_list[0]); } diff --git a/src/common/loadcell.cpp b/src/common/loadcell.cpp index 145f055390..c275e3271c 100644 --- a/src/common/loadcell.cpp +++ b/src/common/loadcell.cpp @@ -47,24 +47,29 @@ Loadcell::Loadcell() void Loadcell::WaitBarrier(uint32_t ticks_us) { // the first sample we're waiting for needs to be valid - while (!planner.draining() && undefinedCnt) + while (!planner.draining() && undefinedCnt) { idle(true, true); + } // now wait until the requested timestamp - while (!planner.draining() && ticks_diff(loadcell.GetLastSampleTimeUs(), ticks_us) < 0) + while (!planner.draining() && ticks_diff(loadcell.GetLastSampleTimeUs(), ticks_us) < 0) { idle(true, true); + } } float Loadcell::Tare(TareMode mode) { // ensure high-precision mode is enabled when taring - if (!highPrecision) + if (!highPrecision) { bsod("high precision not enabled during tare"); + } - if (tareCount != 0) + if (tareCount != 0) { bsod("loadcell tare already requested"); + } - if (endstops.is_z_probe_enabled() && (endstop || xy_endstop)) + if (endstops.is_z_probe_enabled() && (endstop || xy_endstop)) { fatal_error("LOADCELL", "Tare under load"); + } tareMode = mode; @@ -76,8 +81,9 @@ float Loadcell::Tare(TareMode mode) { tareCount = requestedTareCount; // wait until we have all the samples that were requested - while (!planner.draining() && tareCount != 0) + while (!planner.draining() && tareCount != 0) { idle(true, true); + } if (!planner.draining()) { if (tareMode == TareMode::Continuous) { @@ -157,8 +163,9 @@ void Loadcell::ProcessSample(int32_t loadcellRaw, uint32_t time_us) { this->undefinedCnt = 0; } else { // undefined value, use forward-fill only for short bursts - if (++this->undefinedCnt > UNDEFINED_SAMPLE_MAX_CNT) + if (++this->undefinedCnt > UNDEFINED_SAMPLE_MAX_CNT) { fatal_error(ErrCode::ERR_SYSTEM_LOADCELL_TIMEOUT); + } } // handle filters only in high precision mode @@ -321,11 +328,13 @@ Loadcell::HighPrecisionEnabler::HighPrecisionEnabler(Loadcell &lcell, bool enable) : m_lcell(lcell) , m_enable(enable) { - if (m_enable) + if (m_enable) { m_lcell.EnableHighPrecision(); + } } Loadcell::HighPrecisionEnabler::~HighPrecisionEnabler() { - if (m_enable) + if (m_enable) { m_lcell.DisableHighPrecision(); + } } diff --git a/src/common/loadcell.hpp b/src/common/loadcell.hpp index b563b430a1..08b3717983 100644 --- a/src/common/loadcell.hpp +++ b/src/common/loadcell.hpp @@ -232,8 +232,9 @@ class Loadcell { static_assert(NZEROS == 4, "This code works only for NZEROS == 4"); static_assert(NPOLES == 4, "This code works only for NPOLES == 4"); static_assert(A[0] == 1, "This code works only A[0] == 1"); - if (samples < SETTLING_TIME) + if (samples < SETTLING_TIME) { ++samples; + } xv[0] = xv[1]; xv[1] = xv[2]; diff --git a/src/common/marlin_client.cpp b/src/common/marlin_client.cpp index 897bf007b0..9565f14b86 100644 --- a/src/common/marlin_client.cpp +++ b/src/common/marlin_client.cpp @@ -78,9 +78,11 @@ void init() { marlin_client_t *client = 0; TaskDeps::wait(TaskDeps::Tasks::marlin_client); osSemaphoreWait(server_semaphore, osWaitForever); - for (client_id = 0; client_id < MARLIN_MAX_CLIENTS; client_id++) - if (marlin_client_task[client_id] == 0) + for (client_id = 0; client_id < MARLIN_MAX_CLIENTS; client_id++) { + if (marlin_client_task[client_id] == 0) { break; + } + } if (client_id < MARLIN_MAX_CLIENTS) { client = clients + client_id; memset(client, 0, sizeof(marlin_client_t)); @@ -112,30 +114,36 @@ void loop() { marlin_client_t *client; osMessageQId queue; osThreadId taskHandle = osThreadGetId(); - for (client_id = 0; client_id < MARLIN_MAX_CLIENTS; client_id++) - if (taskHandle == marlin_client_task[client_id]) + for (client_id = 0; client_id < MARLIN_MAX_CLIENTS; client_id++) { + if (taskHandle == marlin_client_task[client_id]) { break; - if (client_id >= MARLIN_MAX_CLIENTS) + } + } + if (client_id >= MARLIN_MAX_CLIENTS) { return; + } client = clients + client_id; - if ((queue = marlin_client_queue[client_id]) != 0) + if ((queue = marlin_client_queue[client_id]) != 0) { while ((ose = osMessageGet(queue, 0)).status == osEventMessage) { if (client->flags & MARLIN_CFLG_LOWHIGH) { msg |= ((variant8_t)ose.value.v << 32); // store high dword _process_client_message(client, msg); // call handler variant8_done(&pmsg); count++; - } else + } else { msg = ose.value.v; // store low dword + } client->flags ^= MARLIN_CFLG_LOWHIGH; // flip flag } + } client->last_count = count; } int get_id() { marlin_client_t *client = _client_ptr(); - if (client) + if (client) { return client->id; + } return 0; } @@ -198,8 +206,9 @@ bool is_processing() { void _send_request_to_server_and_wait_with_callback(const char *request, void (*cb)()) { marlin_client_t *client = _client_ptr(); - if (client == 0) + if (client == 0) { return; + } uint8_t retries_left = max_retries; do { @@ -236,8 +245,9 @@ void set_event_notify(uint64_t notify_events, void (*cb)()) { marlin_server::Cmd get_command() { marlin_client_t *client = _client_ptr(); - if (client) + if (client) { return marlin_server::Cmd(client->command); + } return Cmd::NONE; } @@ -278,8 +288,9 @@ int event(Event evt_id) { int ret = 0; marlin_client_t *client = _client_ptr(); uint64_t msk = (uint64_t)1 << ftrstd::to_underlying(evt_id); - if (client) + if (client) { ret = (client->events & msk) ? 1 : 0; + } return ret; } @@ -303,8 +314,9 @@ int error(uint8_t err_id) { int ret = 0; marlin_client_t *client = _client_ptr(); uint64_t msk = (uint64_t)1 << err_id; - if (client) + if (client) { ret = (client->errors & msk) ? 1 : 0; + } return ret; } @@ -397,13 +409,17 @@ void test_abort() { } #endif -void print_start(const char *filename, bool skip_preview) { +void print_start(const char *filename, marlin_server::PreviewSkipIfAble skip_preview) { char request[MARLIN_MAX_REQUEST]; - const int len = snprintf(request, sizeof(request), "!%c%c%s", ftrstd::to_underlying(Msg::PrintStart), skip_preview ? '1' : '0', filename); - if (len < 0) + assert(skip_preview < marlin_server::PreviewSkipIfAble::_count); + static_assert(ftrstd::to_underlying(marlin_server::PreviewSkipIfAble::_count) < ('9' - '0'), "Too many skip preview options."); + const int len = snprintf(request, sizeof(request), "!%c%c%s", ftrstd::to_underlying(Msg::PrintStart), '0' + ftrstd::to_underlying(skip_preview), filename); + if (len < 0) { bsod("Error formatting request."); - if ((size_t)len >= sizeof(request)) + } + if ((size_t)len >= sizeof(request)) { bsod("Request too long."); + } _send_request_to_server_and_wait(request); } @@ -556,10 +572,12 @@ static void _send_request_to_server(uint8_t client_id, const char *request) { if (osMessageAvailableSpace(queue) >= static_cast(len + 1)) // check available space { osMessagePut(queue, '0' + client_id, osWaitForever); // one character client id - for (i = 0; i < len; i++) // loop over every characters + for (i = 0; i < len; i++) { // loop over every characters osMessagePut(queue, request[i], osWaitForever); // - if ((i > 0) && (request[i - 1] != '\n')) // automatically terminate with '\n' + } + if ((i > 0) && (request[i - 1] != '\n')) { // automatically terminate with '\n' osMessagePut(queue, '\n', osWaitForever); + } ret = 1; } else { osSemaphoreRelease(server_semaphore); // unlock @@ -578,8 +596,9 @@ static uint32_t _wait_ack_from_server_with_callback(uint8_t client_id, void (*cb while ((clients[client_id].events & make_mask(Event::Acknowledge)) == 0 && (clients[client_id].events & make_mask(Event::NotAcknowledge)) == 0) { loop(); if (clients[client_id].last_count == 0) { - if (cb) + if (cb) { cb(); + } osDelay(10); } } @@ -622,8 +641,9 @@ static void _process_client_message(marlin_client_t *client, variant8_t msg) { client->ack = variant8_get_ui32(msg); break; case Event::FSM: - if (client->fsm_cb) + if (client->fsm_cb) { client->fsm_cb(variant8_get_ui32(msg), variant8_get_usr16(msg)); + } break; case Event::Message: { variant8_t *pvar = &msg; @@ -636,8 +656,9 @@ static void _process_client_message(marlin_client_t *client, variant8_t msg) { break; } case Event::Warning: - if (client->warning_cb) + if (client->warning_cb) { client->warning_cb(static_cast(variant8_get_i32(msg))); + } break; case Event::Startup: if (client->startup_cb) { @@ -666,7 +687,7 @@ static void _process_client_message(marlin_client_t *client, variant8_t msg) { assert(false); } #ifdef DBG_EVT_MSK - if (DBG_EVT_MSK & ((uint64_t)1 << id)) + if (DBG_EVT_MSK & ((uint64_t)1 << id)) { switch (id) { // Event Event::MeshUpdate - ui32 is float z, ui16 low byte is x index, high byte y index case Event::MeshUpdate: { @@ -695,6 +716,7 @@ static void _process_client_message(marlin_client_t *client, variant8_t msg) { DBG_EVT("CL%c: EVT %s", '0' + client->id, marlin_events_get_name(id)); break; } + } #endif // DBG_EVT_MSK } } @@ -703,9 +725,11 @@ static void _process_client_message(marlin_client_t *client, variant8_t msg) { static marlin_client_t *_client_ptr() { osThreadId taskHandle = osThreadGetId(); int client_id; - for (client_id = 0; client_id < MARLIN_MAX_CLIENTS; client_id++) - if (taskHandle == marlin_client_task[client_id]) + for (client_id = 0; client_id < MARLIN_MAX_CLIENTS; client_id++) { + if (taskHandle == marlin_client_task[client_id]) { return clients + client_id; + } + } return 0; } diff --git a/src/common/marlin_client.hpp b/src/common/marlin_client.hpp index ea323fecc9..6041b746b6 100644 --- a/src/common/marlin_client.hpp +++ b/src/common/marlin_client.hpp @@ -140,7 +140,7 @@ void test_start(const uint64_t test_mask); void test_abort(); #endif -void print_start(const char *filename, bool skip_preview); +void print_start(const char *filename, marlin_server::PreviewSkipIfAble skip_preview); // Should only be called after calling marlin_print_start with skip_preview = true // to see if it really started. Calling it after a call to marlin_print_start with @@ -186,8 +186,9 @@ void encoded_response(uint32_t enc_phase_and_response); template bool FSM_response(T phase, Response response) { uint32_t encoded = ClientResponses::Encode(phase, response); - if (encoded == uint32_t(-1)) + if (encoded == uint32_t(-1)) { return false; + } encoded_response(encoded); return true; diff --git a/src/common/marlin_errors.cpp b/src/common/marlin_errors.cpp index 4132c2ef89..ba0587af2b 100644 --- a/src/common/marlin_errors.cpp +++ b/src/common/marlin_errors.cpp @@ -11,7 +11,8 @@ const char *__err_name[] = { // returns error name (dbg) const char *marlin_errors_get_name(uint8_t err_id) { - if (err_id <= MARLIN_ERR_MAX) + if (err_id <= MARLIN_ERR_MAX) { return __err_name[err_id]; + } return ""; } diff --git a/src/common/marlin_events.cpp b/src/common/marlin_events.cpp index 605460e1b3..298932eea5 100644 --- a/src/common/marlin_events.cpp +++ b/src/common/marlin_events.cpp @@ -43,8 +43,9 @@ static_assert(std::size(__evt_name) == ftrstd::to_underlying(Event::_count), "In // returns event name (dbg) const char *marlin_events_get_name(Event evt_id) { - if (evt_id <= Event::_last) + if (evt_id <= Event::_last) { return __evt_name[ftrstd::to_underlying(evt_id)]; + } return ""; } diff --git a/src/common/marlin_events.h b/src/common/marlin_events.h index 07dc874745..a24c10fbcc 100644 --- a/src/common/marlin_events.h +++ b/src/common/marlin_events.h @@ -74,4 +74,18 @@ enum class Cmd : uint32_t { const char *marlin_events_get_name(Event evt_id); +/** + * @brief Parameter to start printing. + * Tells whether to skip parts of preview when printing is started. + * @warning The order matters. Element skips its screen and all screens with lower number. + */ +enum class PreviewSkipIfAble : uint8_t { + no = 0, ///< Show all + preview, ///< Skip preview thumbnail + tool_mapping, ///< Skip preview thumbnail and toolmapping + _count, + _last = _count - 1, + all = _last, ///< Skip all +}; + } // namespace marlin_server diff --git a/src/common/marlin_print_preview.cpp b/src/common/marlin_print_preview.cpp index 83cdb60405..1d90ab8a60 100644 --- a/src/common/marlin_print_preview.cpp +++ b/src/common/marlin_print_preview.cpp @@ -166,8 +166,8 @@ auto PrintPreview::check_tools_mapping_validity(const ToolMapper &mapper, const return true; } - float nozzle_diameter_distance = gcode.get_extruder_info(gcode_tool).nozzle_diameter.value() - get_nozzle_diameter(physical_extruder); - if (nozzle_diameter_distance > 0.001f || nozzle_diameter_distance < -0.001f) { + float nozzle_diameter_distance = std::abs(static_cast(gcode.get_extruder_info(gcode_tool).nozzle_diameter.value()) - static_cast(get_nozzle_diameter(physical_extruder))); + if (nozzle_diameter_distance > 0.001f) { return false; } @@ -221,8 +221,9 @@ bool PrintPreview::check_extruder_need_filament_load(uint8_t physical_extruder, return false; // if this physical_extruder is not printing, no need to check its filament } - if (!GCodeInfo::getInstance().get_extruder_info(gcode_extruder).used()) + if (!GCodeInfo::getInstance().get_extruder_info(gcode_extruder).used()) { return false; + } // when tool doesn't have filament, it needs load return !FSensors_instance().ToolHasFilament(physical_extruder); @@ -239,11 +240,13 @@ bool PrintPreview::check_correct_filament_type(uint8_t physical_extruder, uint8_ } const auto &extruder_info = GCodeInfo::getInstance().get_extruder_info(gcode_extruder); - if (!extruder_info.used()) + if (!extruder_info.used()) { return true; // when tool not used in print, return OK filament type + } - if (!extruder_info.filament_name.has_value()) + if (!extruder_info.filament_name.has_value()) { return true; // filament type unspecified, return tool OK + } const auto loaded_filament_type = config_store().get_filament_type(physical_extruder); const auto loaded_filament_desc = filament::get_description(loaded_filament_type); @@ -295,8 +298,9 @@ static void queue_filament_load_gcodes() { } // skip for tools that already have filament - if (!check_extruder_need_filament_load_tools_mapping(e)) + if (!check_extruder_need_filament_load_tools_mapping(e)) { continue; + } // pass filament type from gcode, so that user doesn't have to select filament type const char *filament_name = GCodeInfo::getInstance().get_extruder_info(gcode_extruder).filament_name.has_value() @@ -373,13 +377,15 @@ void PrintPreview::tools_mapping_cleanup(bool leaving_to_print) { } PrintPreview::Result PrintPreview::Loop() { - if (GetState() == State::inactive) + if (GetState() == State::inactive) { return Result::Inactive; + } - uint32_t time = ticks_ms(); - if ((time - last_run) < max_run_period_ms) + const uint32_t curr_ms = ticks_ms(); + if (ticks_diff(curr_ms, last_run) < max_run_period_ms) { return stateToResult(); - last_run = time; + } + last_run = curr_ms; const Response response = GetResponse(); auto &gcode_info = GCodeInfo::getInstance(); @@ -391,8 +397,12 @@ PrintPreview::Result PrintPreview::Loop() { case State::init: osSignalSet(prefetch_thread_id, PREFETCH_SIGNAL_GCODE_INFO_INIT); + + // Reset print progress to 0. Need to be at this point because Connect is already starting to snitch the info. + marlin_server::enqueue_gcode_printf("M73 P0 R%i Q0 S%i", marlin_server::TIME_TO_END_INVALID, marlin_server::TIME_TO_END_INVALID); + ChangeState(State::loading); - if (skip_if_able) { + if (skip_if_able > marlin_server::PreviewSkipIfAble::no) { // if skip print confirmation was requested, mark the print as started immediately. // If not, it will be started later when user clicks print return Result::MarkStarted; @@ -421,14 +431,11 @@ PrintPreview::Result PrintPreview::Loop() { case State::loading: if (gcode_info.start_load_result() == GCodeInfo::StartLoadResult::None) { break; + } - } else if (gcode_info.has_error()) { + if (gcode_info.has_error()) { ChangeState(State::file_error_wait_user); break; - - } else if (gcode_info.start_load_result() == GCodeInfo::StartLoadResult::Failed) { - ChangeState(State::inactive); - return Result::Abort; } if (!gcode_info.can_be_printed()) { @@ -437,7 +444,7 @@ PrintPreview::Result PrintPreview::Loop() { } if (gcode_info.is_loaded()) { - ChangeState(skip_if_able ? stateFromSelftestCheck() : State::preview_wait_user); + ChangeState((skip_if_able > marlin_server::PreviewSkipIfAble::no) ? stateFromSelftestCheck() : State::preview_wait_user); } break; @@ -448,7 +455,7 @@ PrintPreview::Result PrintPreview::Loop() { case Response::Print: case Response::PRINT: ChangeState(stateFromSelftestCheck()); - if (!skip_if_able) { + if (skip_if_able == marlin_server::PreviewSkipIfAble::no) { // If print wasn't maked as started immediately, mark it now return Result::MarkStarted; } @@ -461,6 +468,19 @@ PrintPreview::Result PrintPreview::Loop() { default: break; } + + // Periodically kindly ask the prefetch thread to check if the file is still valid and update GCodeInfo::has_error + if (ticks_diff(curr_ms, last_still_valid_check_ms) > 1000) { + last_still_valid_check_ms = curr_ms; + osSignalSet(prefetch_thread_id, PREFETCH_SIGNAL_CHECK); + } + + // Still check for file validity - file could be downloaded enough for the info to show, + // but the transfer might fail and we want to prevent the user from start the print then + if (gcode_info.has_error()) { + ChangeState(State::file_error_wait_user); + break; + } break; case State::unfinished_selftest_wait_user: @@ -625,7 +645,7 @@ PrintPreview::Result PrintPreview::Loop() { case State::checks_done: if (tools_mapping::is_tool_mapping_possible()) { #if ENABLED(PRUSA_SPOOL_JOIN) && ENABLED(PRUSA_TOOL_MAPPING) - if (skip_if_able && PrintPreview::check_tools_mapping_validity(tool_mapper, spool_join, gcode_info).all_ok()) { + if ((skip_if_able >= marlin_server::PreviewSkipIfAble::tool_mapping) && PrintPreview::check_tools_mapping_validity(tool_mapper, spool_join, gcode_info).all_ok()) { // we can skip tools mapping if there is not warning/error in global tools mapping ChangeState(State::done); break; @@ -694,7 +714,7 @@ void PrintPreview::Init() { } IPrintPreview::State PrintPreview::stateFromSelftestCheck() { -#if (!DEVELOPER_MODE() && PRINTER_IS_PRUSA_XL) +#if (!DEVELOPER_MODE() && (PRINTER_IS_PRUSA_XL || PRINTER_IS_PRUSA_MK4)) const bool show_warning = !selftest_warning_selftest_finished(); #else const bool show_warning = false; diff --git a/src/common/marlin_print_preview.hpp b/src/common/marlin_print_preview.hpp index 8078b010c3..a0c15736ca 100644 --- a/src/common/marlin_print_preview.hpp +++ b/src/common/marlin_print_preview.hpp @@ -7,6 +7,7 @@ #include "client_response.hpp" #include #include +#include #include /** @@ -65,7 +66,7 @@ class IPrintPreview { class PrintPreview : public IPrintPreview { - static constexpr uint32_t max_run_period_ms = 50; + static constexpr int32_t max_run_period_ms = 50; uint32_t new_firmware_open_ms { 0 }; static constexpr uint32_t new_firmware_timeout_ms { 30000 }; // three seconds public: @@ -98,9 +99,14 @@ class PrintPreview : public IPrintPreview { void Init(); - inline void set_skip_if_able(bool set) { + /** + * @brief Configure whether to skip parts of preview when printing is started. + * @param set skip these parts + */ + inline void set_skip_if_able(marlin_server::PreviewSkipIfAble set) { skip_if_able = set; } + /** * @brief Checks whether the given physical extruder has corrent filament type for the print. Parametrized with getter to be callable without global tool_mapper/spool_join being in a valid state * @@ -133,8 +139,9 @@ class PrintPreview : public IPrintPreview { private: uint32_t last_run = 0; + uint32_t last_still_valid_check_ms = 0; - bool skip_if_able = false; + marlin_server::PreviewSkipIfAble skip_if_able = marlin_server::PreviewSkipIfAble::no; ///< Whether to skip parts of preview when printing is started PrintPreview() = default; PrintPreview(const PrintPreview &) = delete; diff --git a/src/common/marlin_server.cpp b/src/common/marlin_server.cpp index 34fc68189b..1242adb7ec 100644 --- a/src/common/marlin_server.cpp +++ b/src/common/marlin_server.cpp @@ -9,6 +9,7 @@ #include #include +#include "adc.hpp" #include "marlin_events.h" #include "marlin_print_preview.hpp" #include "app.h" @@ -18,6 +19,7 @@ #include "timing.h" #include "cmsis_os.h" #include "log.h" +#include #include "../Marlin/src/lcd/extensible_ui/ui_api.h" #include "../Marlin/src/gcode/queue.h" @@ -71,8 +73,18 @@ #include