[
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\ngithub: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]\npatreon: # Replace with a single Patreon username\nopen_collective: # Replace with a single Open Collective username\nko_fi: coco33 # Replace with a single Ko-fi username\ntidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel\ncommunity_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry\nliberapay: # Replace with a single Liberapay username\nissuehunt: # Replace with a single IssueHunt username\nlfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry\npolar: # Replace with a single Polar username\nbuy_me_a_coffee: # Replace with a single Buy Me a Coffee username\nthanks_dev: # Replace with a single thanks.dev username\ncustom:\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help me improve\ntitle: \"[Bug]\"\nlabels: ''\nassignees: Phil1988\n\n---\n\n**Describe the bug**\nA clear and concise description of what the bug is.\n\n**Expected behavior**\nIf not self self-explanatory, add a clear and concise description of what you expected to happen.\n\n**To Reproduce**\nSteps to reproduce the behavior:\n1. Go to '...'\n2. Click on '....'\n3. Scroll down to '....'\n4. See error\n\n**Screenshots or picture**\nIf applicable, add screenshots to help explain your problem.\n\n**Console output**\nIf applicable, add the debug console output here (here is a [how to](https://github.com/Phil1988/FreeDi/wiki/Bugs!))\n\n**Base (please complete the following information):**\n - Printer model: [eg. X-Plus 3]\n - X3seriesLCD firmware version: [e.g. v1.00 stable]\n - Source: [eg. self configured or FreeDi image]\n - Mainboard: [eg. stock Mainboard X-4 / other]\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: \"[Feature request]\"\nlabels: ''\nassignees: ''\n\n---\n\n**Is your feature request related to a problem? Please describe.**\nA clear and concise description of what the problem is.\n\n**Describe the feature you'd like**\nA clear and concise description of what you want to happen.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/getting-help.md",
    "content": "---\nname: Getting help\nabout: Describe this issue template's purpose here.\ntitle: \"[Help]\"\nlabels: ''\nassignees: ''\n\n---\n\nIf you are facing issues (especially during the first installation), please share important information to let me understand your current status.\n\nThis may include...\n\n**How did you install it?** (Did you use the full image? Did it on your own? ...)\n**What have you done?** (describe exactly please. step by step)\n**What kind of messages/responses/feedback did you get?** (command line responses, error messages in the Screen/on Mainsail etc.)\nAnd sometimes a **printer.cfg** is handy, which can be included here as renamed to *.txt or zipped.\n\nIn general: \n**Anything you think is helpful for me to understand your problem and how you got there :)**\n"
  },
  {
    "path": "FreeDiLCD/LICENSE",
    "content": "                             Copyright (c) 2024, \n                     https://github.com/Phil1988 [C0co]. \n                             All rights reserved.\n\n                           Custom License Agreement\n                         Version 1.0, September 2024\n\n1. Permission and Usage\n\n   You are hereby granted permission to use, copy, and distribute unmodified\n    copies of this software, subject to the following conditions:\n\n   - Commercial use of the software is prohibited without prior written\n   permission from the original author. To request permission, please \n   contact the author via their GitHub profile.\n   - For the purpose of this license, \"commercial use\" refers to any use \n   of the software in a manner that is intended for or directed toward \n   commercial advantage or monetary compensation.\n   - You may not modify, merge, or publish derivative works based on this \n   software without prior written permission from the original author.\n   - Any redistribution of this software, with or without modification, \n   must include a clear and visible acknowledgment of the original author \n   in the documentation and/or other materials provided with the distribution.\n   - Redistribution of this software under different licensing terms is not \n   permitted without prior written permission from the original author.\n   - If you modify the source code, you must notify the original author of \n   the changes made and provide feedback through GitHub.\n\n2. Attribution\n\n   When redistributing the software, you must retain the following:\n   \n   - The original author's name and copyright notice must be included in all \n   copies or substantial portions of the software.\n   - Clear acknowledgment must be given to the original author(s) in any \n   documentation or software release notes.\n\n3. No Warranty\n\n   This software is provided \"as-is,\" without any express or implied warranties.\n   In no event shall the author be held liable for any damages arising from the \n   use of the software, including but not limited to direct, indirect, \n   incidental, special, exemplary, or consequential damages.\n\n4. No Patent Rights\n\n   No patent rights are granted under this license. You may not use this software \n   to apply for any patent or related intellectual property rights.\n\n5. Limitation of Liability\n\n   In no event shall the author be liable for any claims, damages, or other \n   liabilities, whether in an action of contract, tort, or otherwise, arising \n   from, out of, or in connection with the software or the use or other \n   dealings in the software.\n\n6. Indemnification\n\n   You agree to indemnify and hold the author harmless from and against any and \n   all claims, losses, damages, liabilities, costs, and expenses, including \n   attorneys' fees, arising out of or related to your use or distribution of \n   the software.\n\n7. Reverse Engineering and Decompilation\n\n   You may not reverse engineer, decompile, or disassemble the software, except \n   to the extent that such activity is expressly permitted by applicable law.\n\n8. Security Vulnerabilities\n\n   Users are encouraged to report any security vulnerabilities or issues found \n   in the software to the author via GitHub for assessment and remediation.\n\n9. Termination\n\n   Any violation of the terms of this license will result in the immediate \n   termination of the rights granted herein.\n\n10. Global Applicability\n\n   This license is intended to be globally applicable, subject to the laws and \n   regulations of the relevant jurisdictions.\n\n11. Severability\n\n   If any provision of this License is held to be unenforceable or invalid, \n   such provision will be modified to the extent necessary to make it enforceable \n   and valid, and the remaining provisions will remain in effect.\n\n12. Governing Law\n\n   This License shall be governed by and construed in accordance with the laws \n   of germany, without regard to its conflict of law principles.\n\nBy using, modifying, or distributing the software, you acknowledge that you have \nread, understood, and agreed to be bound by these terms.\n\n\n            Author: https://github.com/Phil1988 [C0co]\n                    Date: September 1, 2024\n\n\n"
  },
  {
    "path": "FreeDiLCD/freedi_update.sh",
    "content": "#!/bin/bash\n\n# to delete '\\r' signs use\n# sed -i 's/\\r$//' freedi_update.sh\n# Set variables\n\necho \"Starting the FreeDi update process...\"\n\nSERVICE=\"FreeDi.service\"\n\n# ── Directory layout ─────────────────────────────────────────────────────────────\nSCRIPT_DIR=\"$( cd -- \"$( dirname \"${BASH_SOURCE[0]}\" )\" >/dev/null 2>&1 && pwd -P )\"  # /home/<user>/FreeDi/FreeDiLCD\nFREEDI_DIR=\"$( dirname \"${SCRIPT_DIR}\" )\"                                        # /home/<user>/FreeDi\nUSER_HOME_DIR=\"$( dirname \"${FREEDI_DIR}\" )\"                                     # /home/<user>\nUSER_NAME=\"$( basename \"${USER_HOME_DIR}\" )\"                                          # The last path component is the user name -> <user>\nUSER_GROUP=\"$( id -gn \"${USER_NAME}\" )\"                                               # The group name of the user\n\n\nFREEDI_LCD_DIR=\"${FREEDI_DIR}/FreeDiLCD\"\nREPO_MODULE_DIR=\"${FREEDI_DIR}/klipper_module\"\nLCD_FIRMWARE_DIR=\"${FREEDI_DIR}/screen_firmwares\"\n\nKLIPPER_DIR=\"${USER_HOME_DIR}/klipper\"\nKLIPPER_EXTRAS_DIR=\"${KLIPPER_DIR}/klippy/extras\"\n\n# Set python path to klipper env\nKLIPPER_ENV=\"${USER_HOME_DIR}/klippy-env\"                                               # klipper virtual environment\nKLIPPER_VENV_PYTHON_BIN=\"$KLIPPER_ENV/bin/python\"                                       # klipper python binary\n\n\n# -------- FreeDi repository ( $FREEDI_DIR ) ---------------------------\nPULLABLE_FILES_FREEDI=(\n    # example: \"FreeDiLCD/always_pull_from_remote.py\"\n    \"FreeDiLCD/freedi_update.sh\"\n)\n\nBLOCKED_FILES_FREEDI=(\n    # example: \"FreeDiLCD/never_pull_from_remote.py\"\n)\n\n# -------- Klipper repository ( $KLIPPER_DIR ) ------------------------------\n# Basically files that doesnt exist in upstream klipper (thus not in $KLIPPER_EXTRAS_DIR)\nPULLABLE_FILES_KLIPPER=(\n    # example: \"klippy/extras/freedi_custom_modified_file.py\"\n    \"klippy/extras/freedi.py\"\n    \"klippy/extras/auto_z_offset.py\"\n)\n\nBLOCKED_FILES_KLIPPER=(\n    # example: \"klippy/extras/freedi_custom_modified_file.py\"\n    #\"klippy/extras/hall_filament_width_sensor.py\"\n\n    # test showed this error/issue when trying to update klipper:\n    # Updating 08a1c9f12..61c0c8d2e\n    # From https://github.com/Klipper3d/klipper\n    # * branch 61c0c8d2ef40340781835dd53fb04cc7a454e37a -> FETCH_HEAD\n    # error: Your local changes to the following files would be overwritten by merge:\n    # klippy/extras/hall_filament_width_sensor.py\n    # Please commit your changes or stash them before you merge.\n)\n\n\n\n# ----- colour definitions -----\nYLW='\\033[1;33m'   # bold yellow\nRED='\\033[1;31m'   # bold red\nRST='\\033[0m'      # reset\n\n\n\n\n############ legacyFreeDi 1.XX -> 2.00 Update ############\n\nPRINTER_DATA_DIR=\"${USER_HOME_DIR}/printer_data\"\nPRINTER_CONFIG_DIR=\"${PRINTER_DATA_DIR}/config\"\nPRINTER_CFG=\"${PRINTER_CONFIG_DIR}/printer.cfg\"\nFREEDI_CFG_SRC=\"${FREEDI_DIR}/config_section/generic/freedi.cfg\"\nFREEDI_CFG_DST=\"${PRINTER_CONFIG_DIR}/freedi.cfg\"\n\n\n\n### Make sure the repo is complete\n# 1) Detect and fix a partial clone ( --filter=blob:none )\nif [ \"$(git config --get remote.origin.partialclonefilter)\" = \"blob:none\" ]; then\n    echo \"Partial clone detected – fetching all blobs ...\"\n    # switch the repo to a normal clone\n    git config --unset-all remote.origin.partialclonefilter\n    git config --unset-all remote.origin.promisor\n    # fetch (download) everything that is still missing\n    git fetch --no-filter --prune --tags --progress\nfi\n\n# 2) Detect and disable sparse-checkout\nif git config --bool core.sparseCheckout | grep -q true; then\n    echo \"Sparse-checkout is active – disabling ...\"\n    git sparse-checkout disable\nfi\n\n\n### Installing and update the new introduced freedi.cfg\n# 1. Copy freedi.cfg into the Klipper config directory\nif install -m 644 -T \"${FREEDI_CFG_SRC}\" \"${FREEDI_CFG_DST}\"; then\n    # Ensure proper ownership in case the script is executed as root\n    chown \"${USER_NAME}:${USER_GROUP}\" \"${FREEDI_CFG_DST}\"\n    echo \"freedi.cfg copied and ownership set to ${USER_NAME}:${USER_GROUP}.\"\nelse\n    echo \"Error: failed to copy freedi.cfg.\" >&2\nfi\n\n# 2. Comment out the legacy [freedi] section in printer.cfg\nif grep -q '^\\[freedi\\]$' \"${PRINTER_CFG}\"; then\n    sed -i '\n        /^\\[freedi\\]$/,/^\\[/{         # range: from [freedi] up to next \"[\" line\n            /^\\[freedi\\]$/  s/^/#/    # comment the [freedi] header\n            /^\\[/          b          # if line starts with [, skip further cmds\n            s/^/#/                     # otherwise: comment the line\n        }\n    ' \"${PRINTER_CFG}\"\n\n    echo \"Legacy [freedi] section commented out.\"\nfi\n\n# 3. Insert include statement where the former [freedi] section started\nif ! grep -q \"^\\[include freedi.cfg\\]\" \"${PRINTER_CFG}\"; then\n    # Find the line number of the (now commented) [freedi] header\n    FREEDI_LINE=$(grep -n -m1 '^[#]*\\[freedi\\]' \"${PRINTER_CFG}\" | cut -d':' -f1)\n    if [[ -n \"${FREEDI_LINE}\" ]]; then\n        # Insert the include line directly above that header\n        sed -i \"${FREEDI_LINE}i [include freedi.cfg]\\n\" \"${PRINTER_CFG}\"\n        echo \"Include statement inserted near the original [freedi] section.\"\n    else\n        echo \"Warning: could not locate the commented [freedi] section; include line not added.\" >&2\n    fi\nelse\n    echo \"Include statement already present in printer.cfg.\"\nfi\n\n\n\n# Activate the Klipper virtual environment and install required Python packages\necho \"Activating Klipper virtual environment and installing Python packages...\"\n\nif [ ! -d \"$KLIPPER_ENV\" ]; then\n\techo \"Klippy env doesn't exist so I can't continue installation...\"\n\texit 1\nfi\n\nPYTHON_V=$($KLIPPER_VENV_PYTHON_BIN -c 'import sys; print(\".\".join(map(str, sys.version_info[:3])))')\necho \"Klipper environment python version: $PYTHON_V\"\n\n# Arrange Python requirements from requirements.txt\necho \"Arranging Python requirements...\"\n\"${KLIPPER_ENV}/bin/pip\" install --upgrade pip \n\"${KLIPPER_ENV}/bin/pip\" install -r \"${FREEDI_DIR}/requirements.txt\"\nif [ $? -ne 0 ]; then\n    echo \"Failed to install Python requirements.\"\n    exit 1\nfi\necho \"Python requirements installed from requirements.txt.\"\n\n\n\n###### Installing klipper modules ######\n\n# Create a symbolic links for needed modules to the Klipper extras directory\nFREEDI_MODULES=(\n    \"freedi.py\"\n    \"qidi_auto_z_offset/auto_z_offset.py\"\n    #\"reverse_homing.py\"\n    #\"hall_filament_width_sensor.py\"\n)\n\nfor MODULE_PATH in \"${FREEDI_MODULES[@]}\"; do\n    MODULE_NAME=$(basename \"${MODULE_PATH}\")\n\n    echo \"Creating a symbolic link for ${MODULE_NAME} from ${REPO_MODULE_DIR}/${MODULE_PATH} to ${KLIPPER_EXTRAS_DIR} …\"\n    if ln -sf \"${REPO_MODULE_DIR}/${MODULE_PATH}\" \"${KLIPPER_EXTRAS_DIR}/${MODULE_NAME}\"; then\n        # Ensure the symlink belongs to the regular user, not root\n        chown -h \"${USER_NAME}:${USER_GROUP}\" \"${KLIPPER_EXTRAS_DIR}/${MODULE_NAME}\"\n        echo \"Successfully installed ${MODULE_NAME} to ${KLIPPER_EXTRAS_DIR}.\"\n    else\n        echo \"Error: failed to create a symbolic link for ${MODULE_NAME}.\" >&2\n        exit 1\n    fi\ndone\n\n\n############ Git housekeeping to prevent dirty repos and setting the correct logic (updateable or not) ############\n\n\n\n\n# Check if the script is run inside a Git repository\nif [ ! -d \"${FREEDI_DIR}/.git\" ]; then\n    echo \"Error: Not a git repository. Please initialize the repository first.\"\nfi\n\n# Ensure if the Klipper extras directory exists\nif [ ! -d \"$KLIPPER_EXTRAS_DIR\" ]; then\n    echo \"Error: Klipper extras directory not found at $KLIPPER_EXTRAS_DIR.\"\n    echo \"Make sure Klipper is installed correctly.\"\nfi\n\n\n# Wrapper to execute commands as the target user when running as root\n# Especially useful for Git operations\nrun_as_user() {\n    if [ \"$(id -u)\" -eq 0 ]; then\n        sudo -u \"$USER_NAME\" -- \"$@\"\n    else\n        \"$@\"\n    fi\n}\n\n# Helper: keep repo clean for a given list of files\n# • pullable → assume-unchanged\n# • blocked  → skip-worktree\n# • detects & clears an already recorded change (typechange, content, …)\n# • runs Git as $USER_NAME even when script is executed as root\nclean_repo() {\n    local repo=\"$1\"\n    local mode=\"$2\"\n    shift 2\n    local files=(\"$@\")\n\n    # Determine the .git directory and build absolute path to info/exclude\n    local git_dir\n    git_dir=\"$(run_as_user git -C \"$repo\" rev-parse --git-dir)\"\n    # <-- changed: use absolute path for exclude file\n    local exclude_file=\"${repo}/${git_dir}/info/exclude\"\n    echo \"Exclude file resolved to: $exclude_file\"\n\n    # Ensure the exclude file exists\n    run_as_user mkdir -p \"$(dirname \"$exclude_file\")\"\n    run_as_user touch \"$exclude_file\"\n\n    for f in \"${files[@]}\"; do\n        local full_path=\"${repo}/${f}\"\n        local st\n        st=\"$(run_as_user git -C \"$repo\" status --porcelain -- \"$f\")\"\n\n        # Warn if file/symlink is missing in working tree\n        if [ ! -e \"$full_path\" ]; then\n            echo -e \"${YLW}Notice: ${f} does not exist in working tree – index/ignore rules are still applied.${RST}\"\n        fi\n\n        # ------------------------------------------------------------------\n        # CASE 1 : tracked file or type-change\n        # ------------------------------------------------------------------\n        if run_as_user git -C \"$repo\" ls-files --error-unmatch \"$f\" >/dev/null 2>&1 \\\n           || [[ $st =~ ^.?T ]]; then\n\n            # Check if this file has changes already\n            local dirty_pre=false\n            if [ -n \"$st\" ]; then\n                echo -e \"${YLW}Detected changes for ${f} in index / working tree (causes dirty repo).${RST}\"\n                dirty_pre=true\n            fi\n\n            if [[ \"$mode\" == \"pullable\" ]]; then\n                if run_as_user git -C \"$repo\" update-index --assume-unchanged -- \"$f\"; then\n                    echo -e \"Git will now ignore local changes to ${f} (assume-unchanged).\"\n                else\n                    echo -e \"${RED}Warning: git update-index failed for ${f} – file NOT marked.${RST}\"\n                fi\n            else\n                if run_as_user git -C \"$repo\" update-index --skip-worktree -- \"$f\"; then\n                    echo -e \"Git will keep your local version of ${f} (skip-worktree).\"\n                else\n                    echo -e \"${RED}Warning: git update-index failed for ${f} – file NOT marked.${RST}\"\n                fi\n            fi\n\n            # If it was dirty, refresh index to clear existing change\n            if [ \"$dirty_pre\" = true ]; then\n                echo -e \"${YLW}Cleaning index / working tree for ${f}...${RST}\"\n                run_as_user git -C \"$repo\" update-index --really-refresh -q -- \"$f\"\n                if run_as_user git -C \"$repo\" status --porcelain -- \"$f\" | grep -q .; then\n                    echo -e \"${RED}Index still reports changes for ${f}!${RST}\"\n                else\n                    echo -e \"${YLW}Index cleaned for ${f}.${RST}\"\n                fi\n            fi\n\n        # ------------------------------------------------------------------\n        # CASE 2 : untracked file → add to info/exclude\n        # ------------------------------------------------------------------\n        else\n            if ! grep -Fxq \"$f\" \"$exclude_file\"; then\n                if printf '%s\\n' \"$f\" | run_as_user tee -a \"$exclude_file\" >/dev/null; then\n                    echo -e \"Added ${f} to $(basename \"$exclude_file\") (untracked→exclude).\"\n                else\n                    echo -e \"${RED}Warning: failed to write ${f} to $(basename \"$exclude_file\").${RST}\"\n                fi\n            else\n                echo -e \"${f} already listed in $(basename \"$exclude_file\") – skipping.\"\n            fi\n        fi\n    done\n}\n\n\n\n\n# Run git cleaning - Apply the definitions above\nclean_repo \"$FREEDI_DIR\" pullable \"${PULLABLE_FILES_FREEDI[@]}\"\nclean_repo \"$FREEDI_DIR\" blocked  \"${BLOCKED_FILES_FREEDI[@]}\"\n\nclean_repo \"$KLIPPER_DIR\"     pullable \"${PULLABLE_FILES_KLIPPER[@]}\"\nclean_repo \"$KLIPPER_DIR\"     blocked  \"${BLOCKED_FILES_KLIPPER[@]}\"\n\n\n\n\n############ Update finished: Restart klipper and FreeDi.service ############\n\n# Restart Klipper to load the new modules\necho \"Restarting Klipper service...\"\nsudo systemctl restart klipper\n"
  },
  {
    "path": "FreeDiLCD/start.py",
    "content": "import os\nimport sys\nimport subprocess\n\ndef run_and_delete_bash_script(file_name):\n    file_name = os.path.join(os.path.dirname(__file__), file_name)\n    if not os.path.exists(file_name):\n        return\n    \n    try:\n        result = subprocess.run([\"bash\", file_name], capture_output=True, text=True, check=True)\n        print(\"Script Output:\\n\", result.stdout)\n        os.remove(file_name)\n        print(f\"File '{file_name}' has been deleted.\")\n    except subprocess.CalledProcessError as e:\n        print(\"Error occurred:\\n\", e.stderr)\n    except FileNotFoundError:\n        print(f\"File '{file_name}' not found. Nothing to delete.\")\n\n# Run the update script\nfile_name = \"freedi_update.sh\"\nrun_and_delete_bash_script(file_name)\n\nimport psutil\n\n# Import the main function from main.py\nfrom main import main as main_function  \n\ndef is_instance_running(script_name):\n    \"\"\"Check if another instance of the script is running.\"\"\"\n    current_pid = os.getpid()\n    script_name = os.path.abspath(script_name)  # Ensure absolute path for comparison\n\n    matching_processes = []\n\n    for proc in psutil.process_iter(['pid', 'cmdline']):\n        try:\n            cmdline = proc.info['cmdline']\n            if cmdline:\n                # Check if the script name matches and it's not the current process\n                if proc.info['pid'] != current_pid and script_name in cmdline:\n                    matching_processes.append(proc.info)\n        except (psutil.NoSuchProcess, psutil.AccessDenied):\n            pass\n\n    return len(matching_processes) > 0\n\nif __name__ == \"__main__\":\n\n    # Ensure the script name matches explicitly\n    script_name = os.path.abspath(__file__)\n    if is_instance_running(script_name):\n        print(f\"Another instance of {script_name} is already running.\")\n        sys.exit(1)\n\n    main_function()  # Call the main function from main.py\n"
  },
  {
    "path": "LICENSE",
    "content": "                             Copyright (c) 2024, \n                     https://github.com/Phil1988 [C0co]. \n                             All rights reserved.\n\n                           Custom License Agreement\n                         Version 1.0, September 2024\n\n1. Permission and Usage\n\n   You are hereby granted permission to use, copy, and distribute unmodified\n    copies of this software, subject to the following conditions:\n\n   - Commercial use of the software is prohibited without prior written\n   permission from the original author. To request permission, please \n   contact the author via their GitHub profile.\n   - For the purpose of this license, \"commercial use\" refers to any use \n   of the software in a manner that is intended for or directed toward \n   commercial advantage or monetary compensation.\n   - You may not modify, merge, or publish derivative works based on this \n   software without prior written permission from the original author.\n   - Any redistribution of this software, with or without modification, \n   must include a clear and visible acknowledgment of the original author \n   in the documentation and/or other materials provided with the distribution.\n   - Redistribution of this software under different licensing terms is not \n   permitted without prior written permission from the original author.\n   - If you modify the source code, you must notify the original author of \n   the changes made and provide feedback through GitHub.\n\n2. Attribution\n\n   When redistributing the software, you must retain the following:\n   \n   - The original author's name and copyright notice must be included in all \n   copies or substantial portions of the software.\n   - Clear acknowledgment must be given to the original author(s) in any \n   documentation or software release notes.\n\n3. No Warranty\n\n   This software is provided \"as-is,\" without any express or implied warranties.\n   In no event shall the author be held liable for any damages arising from the \n   use of the software, including but not limited to direct, indirect, \n   incidental, special, exemplary, or consequential damages.\n\n4. No Patent Rights\n\n   No patent rights are granted under this license. You may not use this software \n   to apply for any patent or related intellectual property rights.\n\n5. Limitation of Liability\n\n   In no event shall the author be liable for any claims, damages, or other \n   liabilities, whether in an action of contract, tort, or otherwise, arising \n   from, out of, or in connection with the software or the use or other \n   dealings in the software.\n\n6. Indemnification\n\n   You agree to indemnify and hold the author harmless from and against any and \n   all claims, losses, damages, liabilities, costs, and expenses, including \n   attorneys' fees, arising out of or related to your use or distribution of \n   the software.\n\n7. Reverse Engineering and Decompilation\n\n   You may not reverse engineer, decompile, or disassemble the software, except \n   to the extent that such activity is expressly permitted by applicable law.\n\n8. Security Vulnerabilities\n\n   Users are encouraged to report any security vulnerabilities or issues found \n   in the software to the author via GitHub for assessment and remediation.\n\n9. Termination\n\n   Any violation of the terms of this license will result in the immediate \n   termination of the rights granted herein.\n\n10. Global Applicability\n\n   This license is intended to be globally applicable, subject to the laws and \n   regulations of the relevant jurisdictions.\n\n11. Severability\n\n   If any provision of this License is held to be unenforceable or invalid, \n   such provision will be modified to the extent necessary to make it enforceable \n   and valid, and the remaining provisions will remain in effect.\n\n12. Governing Law\n\n   This License shall be governed by and construed in accordance with the laws \n   of germany, without regard to its conflict of law principles.\n\nBy using, modifying, or distributing the software, you acknowledge that you have \nread, understood, and agreed to be bound by these terms.\n\n\n            Author: https://github.com/Phil1988 [C0co]\n                    Date: September 1, 2024\n\n\n"
  },
  {
    "path": "README.md",
    "content": "# FreeDi\n**Open Mainline Klipper for QIDI Printers**\n\nTransform your QIDI printer with FreeDi - built on open Armbian OS, official Klipper, custom display firmware, and cutting-edge features. Stay current, stay secure, unlock your printer's full potential.\n\n<p align=\"center\">\n  <img src=\"https://github.com/user-attachments/assets/745a7b53-ab59-433f-a441-291efb53926c\" alt=\"unlock\">\n</p>\n\n---\n\n## 🚀 Quick Start\n\nReady to upgrade? Head to the 📖 **[Installation Guide](https://github.com/Phil1988/FreeDi/wiki/Introduction)** and follow the step-by-step instructions.\n\n**Version 2.xx** → [Installation Guide](https://github.com/Phil1988/FreeDi/wiki/Introduction)  \n**Version 1.xx** → [Legacy Installation Guide](https://github.com/Phil1988/FreeDi/wiki/Installation-guide) | [Video Tutorial](https://www.youtube.com/watch?v=_ZmSTJBWUus)\n\n---\n\n## 💡 What Is FreeDi?\n\nFreeDi is a complete firmware ecosystem for QIDI printers that replaces the outdated stock system with modern, open-source components:\n\n- **Open Foundation**: Armbian OS + official mainline Klipper (unmodified)\n- **Custom Display**: Lightning-fast LCD firmware built for production use\n- **Seamless Integration**: Optimized communication layer between Klipper and display\n- **Latest Software**: Klipper 0.13.0+, Moonraker 0.9.3+, Mainsail 2.14+, KIAUH support\n- **OTA Updates**: Update everything in ~4 minutes - no USB drives, no hassle\n\n### Why Users Switch to FreeDi\n\n- **Full Klipper Ecosystem Access**: Use modern plugins like Cartographer, Beacon, Shake&Tune, Spoolman without compatibility issues\n- **More Storage**: ~2.6GB free space vs. stock's ~500MB - never run out of room for gcode files\n- **Security Compliant**: Passes security tests that stock firmware fails - critical for professional environments\n- **Actually Updated**: Stock systems run OS and Klipper versions up to 4 years old with no update path\n- **No More Stock Bugs**: Eliminate nozzle crashes, bed slamming, missing thumbnails, and \"SYSTEM STARTS ABNORMALLY\" errors\n\n<p align=\"center\">\n  <img src=\"https://github.com/user-attachments/assets/a98c5b18-c3e9-48b0-a21b-7799c58e283e\" alt=\"animated_menu\" width=\"45%\">\n  <img src=\"https://github.com/Phil1988/FreeDi/blob/master/animation.gif\" alt=\"animated_menu\" width=\"45%\">\n</p>\n\n<p align=\"center\">\n  <img src=\"https://github.com/user-attachments/assets/ede5aa17-d846-4368-9d28-f3c54d67b8fa\" alt=\"thumbnails\" width=\"45%\">\n  <img src=\"https://github.com/user-attachments/assets/e8a632de-2093-47ba-9bf1-003bb99845d6\" alt=\"thumbnails\" width=\"45%\">\n</p>\n\n---\n\n## 🖨️ Supported Printers\n\n- QIDI X-Max 3\n- QIDI X-Plus 3\n- QIDI X-Smart 3\n- QIDI Q1 Pro\n- QIDI Plus 4\n\n---\n\n## ❤️ Support This Project\n\nIf FreeDi has improved your printing experience, consider supporting development:\n\n[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/B0B4V3TJ6)\n\nYou can also help by giving this repo a ⭐, sharing it with other QIDI users, providing feedback, or contributing improvements!\n\n---\n\n## 🛠️ Contributing\n\nFreeDi thrives on community input. Have ideas, feature requests, or improvements? Open an issue or submit a pull request. Help spread the word so every QIDI user can make an informed choice about their firmware.\n\n---\n\n## ⚠️ Important Information\n\n**This is a hobby project - use at your own risk.** I've tested extensively (1,000+ LCD flashes), but I can't cover every scenario. Please report issues on GitHub, not to QIDI support - modifications may void your warranty. You can always revert to stock using QIDI's recovery image and official .tft firmware.\n\n**Regarding Sharing & Attribution**: Please don't copy or redistribute parts of this project without permission. In the past, modified/incorrect versions of my guides caused confusion and extra support work. Feel free to **share the project with proper credit** - the more users benefit, the better! I welcome contributions submitted directly here so we can maintain accuracy and make this the go-to resource for QIDI improvements. Thank you for respecting this and building a supportive community.\n\n---\n\n**Together, let's unlock the full potential of your printer!** 🎉\n\nFor complete documentation, visit the [FreeDi Wiki](https://github.com/Phil1988/FreeDi/wiki).\n"
  },
  {
    "path": "config_section/Plus4/macros.cfg",
    "content": "#####################################################################\n# Specific Plus4 macros\n#####################################################################\n#Danger Zone Y 318 -323\n[gcode_macro SET_PRINT_STATS_INFO]\nrename_existing: BASE_SET_PRINT_STATS_INFO_BASE\ngcode:\n    # To prevent the chamber heater to blow hot air directly onto the left side of the print bed \n    {% if (printer.toolhead.position.z) > 260 %}\n        M141 S0\n    {% endif %}\n    #TIMELAPSE_TAKE_FRAME\n    BASE_SET_PRINT_STATS_INFO_BASE {rawparams}\n    CHAMBER_TEMP_CONTROLLER\n\n# Safety macro that gets frequently called by SET_PRINT_STATS_INFO to prevent too high chamber temperatures\n[gcode_macro CHAMBER_TEMP_CONTROLLER]\ngcode:\n    {% set chamber_target_temp = printer['heater_generic chamber'].target %}\n    {% set chamber_temp = printer['heater_generic chamber'].temperature %}\n    {% if chamber_temp > printer.configfile.settings['heater_generic chamber'].max_temp %}\n        M106 P3 S255\n    {% else %}\n        {% if chamber_target_temp > 0 %}\n            # Allow for 3C of \"grace\" before we start ramping the exhaust fan speed\n            # This prevents the macro from fighting with the chamber heater PID algorithm\n            {% set difference = chamber_temp - (chamber_target_temp + 3) %}\n            {% if difference > 0 %}\n                {% set filterfan_speed = ([(difference * 50), 255] | min) | int %}\n                M106 P3 S{filterfan_speed}\n            {% else %}\n                M106 P3 S0\n            {% endif %}\n        {% endif %}\n    {% endif %}\n\n    \n[gcode_macro ENABLE_ALL_SENSOR]\ngcode:\n    ENABLE_FILAMENT_WIDTH_SENSOR\n    RESET_FILAMENT_WIDTH_SENSOR\n    query_filament_width\n    SET_FILAMENT_SENSOR SENSOR=filament_tangle_sensor ENABLE=1\n\n\n[gcode_macro DISABLE_ALL_SENSOR]\ngcode:\n    SET_FILAMENT_SENSOR SENSOR=filament_tangle_sensor ENABLE=0\n    DISABLE_FILAMENT_WIDTH_SENSOR\n\n\n\n[gcode_macro SCREWS_TILT_CALCULATE]\nrename_existing: BASE_SCREWS_TILT_CALCULATE_BASE\ngcode:\n    { action_respond_info(\"starting screw rotation calculation...\") }\n    M141 S0             # disable chamber heater (see https://github.com/qidi-community/Plus4-Wiki/tree/main/content/chamber-heater-issue)\n    BASE_SCREWS_TILT_CALCULATE_BASE\n\n\n[gcode_macro HOME_IF_NEEDED]\ndescription: Homes X and Y if needed\ngcode:\n    {% if \"y\" not in printer.toolhead.homed_axes %}\n        G28 Y\n    {% endif %}\n    {% if \"x\" not in printer.toolhead.homed_axes %}\n        G28 X\n    {% endif %}\n    {% if \"z\" not in printer.toolhead.homed_axes %}\n        G28 Z\n    {% endif %}\n\n\n[gcode_macro CUT_FILAMENT]\ndescription: Cuts the filament\ngcode:\n    HOME_IF_NEEDED\n    \n    {% if printer.gcode_move.position.y < 20 %}\n      G1 Y40 F9000\n    {% endif %}\n    {% if printer.gcode_move.position.y > 300 %}\n      G1 Y300 F9000\n    {% endif %}\n    G1 X305 Y40 F9000\n    G1 Y20 F9000\n    G1 Y5 F3000\n    G4 P500\n    G1 Y20 F9000\n    G1 Y5 F3000\n    G4 P500\n    G1 Y20 F9000\n\n\n[gcode_macro GO_TO_POOP_SHOOT]\ndescription: Move toolhead to poop shoot\ngcode:\n    HOME_IF_NEEDED\n\n    G90\n    {% if printer.gcode_move.position.y > 300 %}\n      G1 Y300 F9000\n    {% endif %}\n\n    G1 X95 Y312 F12000\n    G1 Y316 F600\n    G1 Y320 F9000\n    G1 Y324 F600\n\n\n[gcode_macro LEAVE_POOP_SHOOT]\ndescription: Primes the nozzle with fresh filament before load/unload/print start\ngcode:\n    HOME_IF_NEEDED\n\n    {% if printer.gcode_move.position.y > 323 %}\n      G1 X95 F1200\n      G1 Y300 F1200\n    {% else %}\n        {% if printer.gcode_move.position.y < 318  %}\n            G1 X95 Y300 F1200\n        {% else %}\n            {% if (printer.gcode_move.position.x < 83 or printer.gcode_move.position.x > 106 or \n                    (printer.gcode_move.position.x >= 93 and printer.gcode_move.position.x <= 97)) %}\n                G1 Y300 F1200\n                G1 X95    \n            {% else %}\n               M118 Warning: Nozzle in dangerous position!        \n            {% endif %}\n        {% endif %}\n    {% endif %}\n\n\n[gcode_macro _SILICON_WIPE]\ndescription: Wipe on the silicon pad with custom min and max coordinates and margin\ngcode:\n    G90\n    {% if (printer.gcode_move.position.y) > 300 %}\n      G1 Y300 F600      \n    {% endif %}\n\n    G1 X95 F12000\n    G1 Y314 F9000\n    G1 Y324 F600\n\n    ; Wipe movements in X direction\n    G1 X58 F12000\n    G1 X78 F12000\n    G1 Y324\n    G1 X58 F12000\n    G1 X78 F12000\n    G1 Y323.5\n    G1 X58 F12000\n    G1 X78 F12000\n    G1 Y323\n    G1 X58 F12000\n    G1 X78 F12000\n    G1 Y322.5\n    G1 X58 F12000\n    G1 X78 F12000\n    G1 Y322\n    G1 X58 F12000\n    G1 X75 F12000\n    G1 Y321.5\n\n    ; Wipe movements in circles\n    G2 I0.8 J0.8 F600\n    G2 I0.8 J0.8 F600\n    G2 I0.8 J0.8 F600\n\n    G1 Y324 F600\n    G1 X95 F12000\n\n\n[gcode_macro _PEI_WIPE]\ndescription: Wipe on the PEI pad\ngcode:\n    # Input values for the minimum and maximum coordinates of the pad\n    {% set pad_min_coordinate_x = 111 %}\n    {% set pad_max_coordinate_x = 136 %}\n    {% set pad_min_coordinate_y = 317 %}\n    {% set pad_max_coordinate_y = 325 %}\n    {% set margin = 1.0 %} # margin from the edge of the pad\n    {% set repetitions = 3 %}\n\n    # Arc parameters and radius to keep full arc inside limits\n    {% set arc_i = 0.5 %}\n    {% set arc_j = 0.5 %}\n    {% set arc_r = ((arc_i|float)**2 + (arc_j|float)**2) ** 0.5 %}\n\n    G90 # absolute positioning\n    {% if (printer.gcode_move.position.y) < 300 %}\n      G1 Y300 F9000\n    {% endif %}\n\n    G1 X108 F9000\n\n    # Compute safe max/min positions (account for margin and arc radius)\n    {% set X_max_position = pad_max_coordinate_x - margin - arc_r %}\n    {% set Y_max_position = pad_max_coordinate_y - margin - arc_r %}\n    {% set X_min_position = pad_min_coordinate_x + margin + arc_r %}\n    {% set Y_min_position = pad_min_coordinate_y + margin + arc_r %}\n\n    # Calculate random end positions within the defined safe boundaries (0.05 mm steps)\n    {% set random_x_steps = ((X_max_position - X_min_position) * 20) | int %}\n    {% if random_x_steps < 1 %}{% set random_x_steps = 1 %}{% endif %}\n    {% set random_x = (range(0, random_x_steps) | random) / 20.0 %}\n    {% set X_move_position = X_min_position + random_x %}\n\n    {% set random_y_steps = ((Y_max_position - Y_min_position) * 20) | int %}\n    {% if random_y_steps < 1 %}{% set random_y_steps = 1 %}{% endif %}\n    {% set random_y = (range(0, random_y_steps) | random) / 20.0 %}\n    {% set Y_move_position = Y_min_position + random_y %}\n\n    # Calculate a random starting Y position within the safe range (0.1 mm steps)\n    {% set random_start_y_steps = ((Y_max_position - Y_min_position) * 10) | int %}\n    {% if random_start_y_steps < 1 %}{% set random_start_y_steps = 1 %}{% endif %}\n    {% set random_start_y = (range(0, random_start_y_steps) | random) / 10.0 + Y_min_position %}\n\n    # Move the print head to the random starting Y position\n    G1 Y{random_start_y} F500\n\n    # Wiping movements in X direction\n    {% for move in range(repetitions|int) %}\n        G1 X{X_max_position} F400\n        G1 X{X_move_position} F400\n    {% endfor %}\n\n    # Wiping movements in Y direction\n    {% for move in range(repetitions|int) %}\n        G1 Y{Y_move_position} F400\n        G1 Y{Y_max_position} F400\n    {% endfor %}\n\n    G1 X{X_move_position} Y{Y_move_position} F300\n\n    # Circular wiping movements (kept inside safe area by arc radius)\n    {% for move in range(repetitions|int) %}\n        G2 I{arc_i} J{arc_j} F500\n    {% endfor %}\n\n    # Rectangular wiping movements\n    {% for move in range(repetitions|int) %}\n        G1 Y{Y_max_position} F400\n        G1 X{X_max_position} F400\n        G1 Y{Y_move_position} F400\n        G1 X{X_move_position} F400\n    {% endfor %}\n\n\n[gcode_macro PRIME_NOZZLE]\ndescription: Primes the nozzle with fresh filament before load/unload/print start\ngcode:\n    {% set hotend_target_temp = params.HOTEND_TARGET_TEMP|default(220)|int %}\n    M106 S0\n    M104 S{hotend_target_temp}\n\n    HOME_IF_NEEDED\n\n    TEMPERATURE_WAIT SENSOR=extruder MINIMUM={hotend_target_temp-50}\n    GO_TO_POOP_SHOOT\n\n    M109 S{hotend_target_temp}\n\n    G92 E0\n    G1 E5 F50\n    G1 E50 F200\n    G92 E0\n    G1 E-0.8 F200\n    G4 P300\n\n   \n    M104 S{([hotend_target_temp-80, 150]|min)} \n    M106 S255\n    G4 P4000\n    \n    _PEI_WIPE\n    TEMPERATURE_WAIT SENSOR=extruder MAXIMUM={([hotend_target_temp-80, 150]|min)}\n    _SILICON_WIPE\n    GO_TO_POOP_SHOOT \n    M106 S0\n    LEAVE_POOP_SHOOT\n\n\n[gcode_macro M603]\ndescription: Unload filament with cutting filament\ngcode:\n    {% set hotend_target_temp = params.S|default(220)|int %}\n    {% set accel = printer.toolhead.max_accel|int %}\n    \n\tM104 S{hotend_target_temp}\n    \n    HOME_IF_NEEDED\n    M204 S10000\n    CUT_FILAMENT\n    \n    M106 S0\n    M400\n    M204 S{accel}\n    M118 Unload finished\n\n\n[gcode_macro M604]\ndescription: Load filament with priming nozzle\ngcode:\n    {% set hotend_target_temp = params.S|default(250)|int %}\n    {% set accel = printer.toolhead.max_accel|int %}\n    \n    M104 S{hotend_target_temp}\n\n    HOME_IF_NEEDED\n    M204 S10000\n    PRIME_NOZZLE hotend_target_temp={hotend_target_temp}\n\n    M106 S0\n    M400\n    M204 S{accel}\n    M118 Load finished\n\n\n#####################################################################\n# Homing modification\n#####################################################################\n[gcode_macro G28]\nrename_existing: G28.1\ngcode:\n    {% set reduced_current_x = 0.55 %}\n    {% set reduced_current_y = 0.45 %}\n    {% set home_all = ('X' in rawparams.upper() and 'Y' in rawparams.upper() and 'Z' in rawparams.upper()) or \n                      ('X' not in rawparams.upper() and 'Y' not in rawparams.upper() and 'Z' not in rawparams.upper()) %}\n    {% set home_current_x = printer.configfile.settings['tmc2240 stepper_x'].run_current * reduced_current_x %}\n    {% set home_current_y = printer.configfile.settings['tmc2240 stepper_y'].run_current * reduced_current_y %}\n\n    {% set init_XY_move = 30 %}\n    #{% set y_init_move = 5 %}\n    {% set z_clearance = 2 %}\n\n    {% set home_all_final_position_x = printer.toolhead.axis_maximum.x / 2 %}\n    {% set home_all_final_position_y = printer.toolhead.axis_maximum.y - 40 %}\n    {% set home_all_final_position_z = 20 %}\n\n\n    {% if 'x' not in printer.toolhead.homed_axes %}\n      {% set X_axis_was_homed = false %}                                                                           ; Set Z_axis_was_homed to false if Z is not homed\n    {% endif %}\n    {% if 'y' not in printer.toolhead.homed_axes %}\n      {% set Y_axis_was_homed = false %}                                                                           ; Set Z_axis_was_homed to false if Z is not homed\n    {% endif %}\n            \n    # If homing should at least move X or Y axis\n    {% if home_all or 'X' in rawparams.upper() or 'Y' in rawparams.upper() %}     \n        # Check if Z is homed\n        {% if 'z' in printer.toolhead.homed_axes %}\n            {% set Z_axis_was_homed = true %}                                                                       ; Set Z_axis_was_homed to true if Z is already homed\n            G91                                                                                                     ; Use relative positioning\n            G1 Z2 F600                                                                                              ; Move bed down\n            G90                                                                                                     ; Use absolute positioning\n        {% else %}\n            {% set Z_axis_was_homed = false %}                                                                      ; Set Z_axis_was_homed to false if Z is not homed\n            G90\n            SET_KINEMATIC_POSITION Z=0                                                                              ; To allow bed move down\n            G1 Z{z_clearance}                                                                                       ; Move bed down\n            {% if X_axis_was_homed == false %}\n              SET_KINEMATIC_POSITION SET_HOMED= CLEAR_HOMED=X                                                       ; Set X to be unhomed\n            {% endif %}\n            {% if Y_axis_was_homed == false %}\n              SET_KINEMATIC_POSITION SET_HOMED= CLEAR_HOMED=Y                                                       ; Set Y to be unhomed\n            {% endif %}            \n        {% endif %}\n    {% endif %}\n\n    {% if home_all or 'X' in rawparams.upper() or 'Y' in rawparams.upper() %} \n        FORCE_MOVE STEPPER=stepper_x DISTANCE={init_XY_move} VELOCITY=40                                            ; Move X a little before homing\n        SET_KINEMATIC_POSITION X={printer.toolhead.position.x + (init_XY_move/2)}                                   ; Compensate the FORCE_MOVE position \n        SET_KINEMATIC_POSITION Y={printer.toolhead.position.y + (init_XY_move/2)}                                   ; Compensate the FORCE_MOVE position\n        {% if X_axis_was_homed == false %}\n          SET_KINEMATIC_POSITION SET_HOMED= CLEAR_HOMED=X                                                           ; Set X to be unhomed\n        {% endif %}\n        {% if Y_axis_was_homed == false %}\n          SET_KINEMATIC_POSITION SET_HOMED= CLEAR_HOMED=Y                                                           ; Set Y to be unhomed\n        {% endif %} \n    {% endif %}\n\n    # Home Y\n    {% if home_all or 'Y' in rawparams.upper() %}\n        SET_TMC_CURRENT STEPPER=stepper_x CURRENT={home_current_x}                                                  ; Lower motor current\n        SET_TMC_CURRENT STEPPER=stepper_y CURRENT={home_current_y}                                                  ; Lower motor current\n        G28.1 Y                                                                                                     ; Home Y\n        SET_TMC_CURRENT STEPPER=stepper_x CURRENT={printer.configfile.settings['tmc2240 stepper_x'].run_current}    ; Set motor current to the previous value\n        SET_TMC_CURRENT STEPPER=stepper_y CURRENT={printer.configfile.settings['tmc2240 stepper_y'].run_current}    ; Set motor current to the previous value\n        G1 Y10 F1200                                                                                                ; Move Y-axis slightly\n    {% endif %}\n    \n    # Home X\n    {% if home_all or 'X' in rawparams.upper() %}        \n        SET_TMC_CURRENT STEPPER=stepper_x CURRENT={home_current_x}                                                  ; Lower motor current\n        SET_TMC_CURRENT STEPPER=stepper_y CURRENT={home_current_x}                                                  ; Lower motor current\n        G28.1 X                                                                                                     ; Home X\n        SET_TMC_CURRENT STEPPER=stepper_x CURRENT={printer.configfile.settings['tmc2240 stepper_x'].run_current}    ; Set motor current to the previous value\n        SET_TMC_CURRENT STEPPER=stepper_y CURRENT={printer.configfile.settings['tmc2240 stepper_y'].run_current}    ; Set motor current to the previous value\n        G1 X10 F1200                                                                                                ; Move X-axis slightly\n    {% endif %}\n\n    # Raise the bed again if only X or only Y axes were homed\n    {% if not (home_all or 'Z' in rawparams.upper()) %}\n        {% if Z_axis_was_homed %}\n            G91                                                                                                     ; Use relative positioning\n            G1 Z-2 F600                                                                                             ; Raise the bed back again\n            G90                                                                                                     ; Use absolute positioning\n        {% else %}\n            G1 Z0.1                                                                                                 ; Raise the bed back again\n            SET_STEPPER_ENABLE STEPPER=stepper_z enable=0                                                           ; Disable Z to prevent collisions\n            SET_STEPPER_ENABLE STEPPER=stepper_z1 enable=0                                                          ; Disable Z to prevent collisions\n            SET_KINEMATIC_POSITION SET_HOMED= CLEAR_HOMED=Z                                                         ; Set Z to be unhomed\n        {% endif %}\n    {% endif %}\n\n    # Home Z\n    {% if home_all or 'Z' in rawparams.upper() %}\n        G1 X{printer.toolhead.axis_maximum.x / 2} Y{printer.toolhead.axis_maximum.x / 2} F12000 \n        G28.1 Z                                                                                                     ; Home Z\n        G90                                                                                                         ; Set absolute positioning\n        G1 Z{home_all_final_position_z} F600                                                                        ; Move bed down\n    {% endif %}\n\n    # Move to the final position if all axes were homed\n    {% if home_all %}\n        G90                                                                                                         ; Set absolute positioning\n        G1 X{home_all_final_position_x} Y{home_all_final_position_y} Z{home_all_final_position_z} F7800             ; Move to the rear center\n    {% endif %}\n\n\n# Unconditional stop\n[gcode_macro M0]\ngcode:\n    PAUSE\n\n\n# Pause SD print\n[gcode_macro M25]\nrename_existing: M9925\ngcode:\n    PAUSE\n\n\n########################################\n# Basic Macros\n########################################\n# Flag macro to use STATIC_MESH usage instead of KAMP (needed make this function work from printjob selection on the LCD)\n[gcode_macro NEXT_PRINT_STATIC_MESH]\ndescription: Forces the NEXT print to use 'STATIC_MESH' instead of KAMP.\ngcode:\n    {% if \"STATIC_MESH\" in printer.bed_mesh.profiles %}\n        SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=force_static_mesh VALUE=True\n        {action_respond_info(\"The NEXT print will use 'STATIC_MESH'.\")}\n        M118 The NEXT print will use the STATIC_MESH.\n    {% else %}\n        {action_respond_info(\"WARNING: No mesh named 'STATIC_MESH' found. Please save one first (BED_MESH_PROFILE SAVE=STATIC_MESH).\")}\n        M118 WARNING: No mesh named STATIC_MESH found. Please save one first (BED_MESH_PROFILE SAVE=STATIC_MESH).\n    {% endif %}\n\n\n[gcode_macro PRINT_START]\n# Use PRINT_START for the slicer starting script\ndescription: Start printing\nvariable_force_static_mesh: False                                                                                 ; Set to True to force a static mesh instead of KAMP\ngcode:\n    {% set bed_target_temp = params.BED|int %}\n    {% set hotend_target_temp = params.HOTEND|int %}\n    {% set chamber_target_temp = params.CHAMBER|default(0)|int %}\n    {% set bed_center_x = printer.configfile.config[\"stepper_x\"][\"position_max\"]|float / 2 %}\n    {% set bed_center_y = printer.configfile.config[\"stepper_y\"][\"position_max\"]|float / 2 %}\n\n    {% set start_position_x = printer.toolhead.axis_maximum.x / 2 %}\n    {% set start_position_y = printer.toolhead.axis_maximum.y - 40 %}\n    {% set start_position_z = 10 %}\n\n    CLEAR_PAUSE                                                                                                    ; Clear existing pause states\n    BED_MESH_CLEAR                                                                                                 ; Clear previous adaptive mesh\n\n    {% set KAMP_deactivated = printer[\"gcode_macro PRINT_START\"].force_static_mesh %}                              ; Check if KAMP is deactivated for this print\n    SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=force_static_mesh VALUE=False                                    ; Auto-reset the variable immediately for the next print after this one\n\n    SET_TEMPERATURE_FAN_TARGET TEMPERATURE_FAN=Mainboard_fan TARGET=1                                              ; Decrease the mainboard target temp to fully turn the fan on\n    \n    M140 S{bed_target_temp}\n    M141 S{chamber_target_temp}\n    G28\n\n    {% if chamber_target_temp > 0 %}                                                                               ; Accelerate chamber heating by using the bed as additional heater    \n        G0 X{bed_center_x} Y{bed_center_y} Z3 F780                                                                 ; Move print bed to perfect postion to help chamber heating\n        M106 P2 S185                                                                                               ; Turn sidefan on to use bed heat and mix air\n        M106 P0 S128                                                                                               ; Turn part cooling fan on to help air mixing\n        TEMPERATURE_WAIT SENSOR=\"heater_generic chamber\" MINIMUM={chamber_target_temp - 5}                         ; Wait for chamber to heat up\n        M106 P2 S0                                                                                                 ; Turn off sidefan\n        M106 P0 S0                                                                                                 ; Turn off part cooling fan                                      \n    {% endif %}\n\n    {% if bed_target_temp !=0 %}\n      TEMPERATURE_WAIT SENSOR=heater_bed MINIMUM={bed_target_temp * 0.95} MAXIMUM={bed_target_temp * 1.05}\n    {% endif %}\n\n    M191 S{chamber_target_temp}                                                                                    ; Set and wait for chamber temperature\n    M190 S{bed_target_temp}                                                                                        ; Set and wait for bed temperature \n    G90                                                                                                            ; Set absolute positioning\n    G1 X{start_position_x} Y{start_position_y} Z{start_position_z} F7800                                           ; Move to start position\n    G28 Z                                                                                                          ; Home Z again for to compensate bed expansion  \n    \n    {% if KAMP_deactivated %}\n        {% if \"STATIC_MESH\" in printer.bed_mesh.profiles %}                                                        ; Check if the spicific STATIC_MESH exists\n            M118  Loading 'STATIC_MESH' instead of KAMP.\n            BED_MESH_PROFILE LOAD=STATIC_MESH\n        {% else %}                                                                                                 ; Fallback to KAMP if STATIC_MESH not found\n            M118 ERROR: 'STATIC_MESH' not found! Using fallback: KAMP Adaptive Mesh.\n            BED_MESH_CLEAR                                                                                         ; Clear previous adaptive mesh\n            BED_MESH_CALIBRATE PROFILE=adaptive ADAPTIVE=1                                                         ; Start adaptive meshing\n        {% endif %}\n    {% else %}                                                                                                     ; Standard operation\n        {% if printer.toolhead.homed_axes|length < 3 %}\n            G28\n        {% endif %}\n        BED_MESH_CLEAR                                                                                             ; Clear previous adaptive mesh\n        BED_MESH_CALIBRATE PROFILE=adaptive ADAPTIVE=1                                                             ; Start adaptive meshing\n    {% endif %}\n\n    PRIME_NOZZLE hotend_target_temp={hotend_target_temp}\n    M109 S{hotend_target_temp}                                                                                     ; Set and wait for hotend temperature \n\n\n[gcode_macro PRINT_END]\ngcode:\n    {% set max_x = printer.configfile.config[\"stepper_x\"][\"position_max\"]|float %}\n    {% set max_y = printer.configfile.config[\"stepper_y\"][\"position_max\"]|float %}\n    {% set max_z = printer.configfile.config[\"stepper_z\"][\"position_max\"]|float %}\n    {% set current_extruder_temp = printer.extruder.temperature|float %}\n    {% set min_extrusion_temp = printer.configfile.config[\"extruder\"][\"min_extrude_temp\"]|float %}\n    {% set z_clearance = 50 %}\n\n    {% if (printer.toolhead.position.z + z_clearance) < max_z %}\n        {% set z_hop = 2  %}\n    {% else %}\n        {% set z_hop = 0 %}\n    {% endif %}\n\n    M106 P0 S0                                                                                                      ; Turn off part cooling fan\n    M106 P2 S0                                                                                                      ; Turn off side fan\n    M106 P3 S0                                                                                                      ; Turn off activated charcoal fan\n\n    M104 S0                                                                                                         ; Turn off hotend\n    M140 S0                                                                                                         ; Turn off heated bed\n    M141 S0                                                                                                         ; Turn off heated chamber\n\n    G91                                                                                                             ; Relative positioning\n    {% if current_extruder_temp >= min_extrusion_temp + 5 %}                                                        ; Check if the hotend is hot enough to perform a retraction (with a small gap)  \n        G0 E-4.0 F300                                                                                               ; Retract filament\n    {% endif %}\n    G0 Z{z_hop} F3600                                                                                               ; Move bed down a bit\n    G90                                                                                                             ; Absolute positioning\n    G0 X{max_x/2} Y{max_y-40} F20000                                                                                ; Move nozzle to remove stringing\n    _Z_CLEARANCE DISTANCE={z_clearance}                                                                             ; Lower bed\n    M400                                                                                                            ; Wait for buffer to clear\n    G92 E0                                                                                                          ; Zero the extruder\n\n    M220 S100                                                                                                       ; Set feedrate (speed percentage) back to 100%\n    M221 S100                                                                                                       ; Set flow percentage back to 100%\n\n    SET_IDLE_TIMEOUT TIMEOUT={printer.configfile.settings.idle_timeout.timeout}                                     ; Set timeout back to configured value\n    CLEAR_PAUSE                                                                                                     ; Ensure pause state is cleared if applicable\n\n    M84                                                                                                             ; Disable steppers\n    SET_TEMPERATURE_FAN_TARGET TEMPERATURE_FAN=Mainboard_fan TARGET=45                                              ; Reset the mainboard fan temp\n    BEEP I=2 DUR=500                                                                                                ; Alert at the end of the print (if sound is enabled)\n\n\n[gcode_macro PAUSE]\nrename_existing: BASE_PAUSE\ngcode:\n    {% set z_hop = params.Z|default(30)|int %}                                                                     ; Z hop amount\n    \n    {% if printer['pause_resume'].is_paused|int == 0 %}     \n        SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=zhop VALUE={z_hop}                                                ; Set Z hop variable for reference in resume macro\n        SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=etemp VALUE={printer['extruder'].target}                          ; Set hotend temperature variable for reference in resume macro\n        SAVE_GCODE_STATE NAME=PAUSE                                                                                ; Save current position for resume\n        BASE_PAUSE                                                                                                 ; Pause print\n        {% if (printer.gcode_move.position.z + z_hop) < printer.toolhead.axis_maximum.z %}                         ; Check that Z hop doesn't exceed Z max\n            G91                                                                                                    ; Use Relative positioning\n            G1 Z{z_hop} F600                                                                                       ; Raise Z up by Z hop amount\n        {% else %}\n            SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=zhop VALUE=0                                                  ; Set Z hop to 0 if exceeds max\n        {% endif %}\n        SAVE_GCODE_STATE NAME=PAUSEPARK2\n        G90                                                                                                        ; Absolute positioning\n        G1 X{printer.toolhead.axis_maximum.x/2} Y{printer.toolhead.axis_maximum.y-40} F6000                        ; Park toolhead  at rear center\n        SAVE_GCODE_STATE NAME=PAUSEPARK                                                                            ; Save parked position in case toolhead is moved during the pause (otherwise the return zhop can error)\n        M104 S0                                                                                                    ; Turn off hotend\n        SET_IDLE_TIMEOUT TIMEOUT=43200                                                                             ; Set timeout to 12 hours\n        SET_STEPPER_ENABLE STEPPER=extruder ENABLE=0                                                               ; Disable extruder stepper\n    {% endif %}\n\n\n[gcode_macro RESUME]\nrename_existing: BASE_RESUME\nvariable_zhop: 0\nvariable_etemp: 0\ngcode:\n    {% set extrusion_length = params.E|default(2.5)|int %}                                                                        ; Hotend prime amount (in mm)\n\n    {% if printer['pause_resume'].is_paused|int == 1 %}\n        {% if \"z\" not in printer.toolhead.homed_axes %}                                                            ; check if z position is lost\n            {action_raise_error(\"ERROR: Z-axixs lost its position (Idle-Timeout)! Resume not possible - Print should be aborted.\")}\n        {% endif %}\n        \n        SET_IDLE_TIMEOUT TIMEOUT={printer.configfile.settings.idle_timeout.timeout}                                ; Set idle timeout back to configured value\n\n        # If X/Y position lost: Give Z-clearance for homing X/Y that will be done by PRIME_NOZZLE                                                                                     \n        {% if \"x\" not in printer.toolhead.homed_axes or \"y\" not in printer.toolhead.homed_axes %}                  ; If X/Y position is lost, but z is still OK\n            G91                                                                                                    ; Relative positioning\n            G1 Z5 F600                                                                                             ; 5mm clearance for safe X/Y-Homing\n            G90                                                                                                    ; Absolute positioning\n        {% endif %}\n\n        PRIME_NOZZLE HOTEND_TARGET_TEMP={etemp}                                                                    ; Prime nozzle with last used hotend temperature\n\n        M109 S{etemp}                                                                                              ; Wait for hotend to heat up\n\n        RESTORE_GCODE_STATE NAME=PAUSEPARK2 MOVE=1 MOVE_SPEED=150                                                  ; Return to position after Z-hop (safely above the part)       \n        RESTORE_GCODE_STATE NAME=PAUSE MOVE=1 MOVE_SPEED=10                                                        ; Restore position\n        BASE_RESUME                                                                                                ; Absolute positioning\n    {% endif %}\n\n\n[gcode_macro CANCEL_PRINT]\nrename_existing: BASE_CANCEL_PRINT\ngcode:\n    {% set max_z = printer.configfile.config[\"stepper_z\"][\"position_max\"]|float %}\n    {% if (printer.toolhead.position.z + 12) < max_z %}\n        {% set z_hop = 2  %}\n    {% else %}\n        {% set z_hop = 0 %}\n    {% endif %}\n\n    G91                                                                                                            ; Relative positioning\n    G1 Z{z_hop} F600                                                                                               ; Do a tiny z-hop\n    G90                                                                                                            ; Absolute positioning\n\n    G1 X{printer.toolhead.axis_maximum.x/2} Y{printer.toolhead.axis_maximum.y-40} F12000\n    CLEAR_PAUSE\n    SDCARD_RESET_FILE\n\n    PRINT_END\n    BASE_CANCEL_PRINT\n\n\n[gcode_macro _Z_CLEARANCE]\ndescription: Lower the bed to give some clearance\nvariable_default_distance: 40.0\ngcode:\n    {% set current_z_height = printer.toolhead.position.z %}\n    {% set max_z_height = printer.toolhead.axis_maximum.z %}\n    {% set distance = params.DISTANCE|default(variable_default_distance)|float %}\n    {% set target_z_height = current_z_height + distance %}\n\n    {% set min_z_param = params.MIN_Z|default(None) %}\n    {% if min_z_param is not none %}\n        {% set min_z = min_z_param|float %}\n        {% if target_z_height < min_z %}\n            {% set target_z_height = min_z %}\n        {% endif %}\n    {% endif %}\n\n    G90                                                                                                            ; Absolute positioning\n    G1 Z{ [target_z_height, max_z_height]|min }\n\n\n########################################\n#  Filament Macros\n########################################\n[gcode_macro UNLOAD_FILAMENT]\ndescription: Unloads filament from toolhead\ngcode:\n  {% set EXTRUDER_TEMP = params.TEMP|default(230)|int %}\n  {% set CURRENT_TEMP = printer.extruder.temperature|int %}\n  {% if CURRENT_TEMP < EXTRUDER_TEMP %}\n    M104 S{EXTRUDER_TEMP}                                                                                          ; heat up the hotend\n  {% endif %}\n   \n  GO_TO_POOP_SHOOT                                                                                                 ; go to poop shoot\n\n  {% if CURRENT_TEMP < EXTRUDER_TEMP %}\n    M109 S{EXTRUDER_TEMP}                                                                                          ; heat up the hotend\n  {% endif %}  \n  SET_STEPPER_ENABLE STEPPER=extruder ENABLE=1                                                                     ; enable extruder stepper   \n  M83                                                                                                              ; set extruder to relative mode\n  G1 E5 F150                                                                                                       ; extrude a small amount to elimate soften the filament\n  G1 E-8 F1800                                                                                                     ; quickly retract a small amount to elimate stringing\n  G4 P200                                                                                                          ; pause for a short amount of time\n  G1 E-50 F300                                                                                                     ; retract slowly the rest of the way\n  M104 S0                                                                                                          ; turn off hotend\n  LEAVE_POOP_SHOOT                                                                                                 ; leave poop shoot\n  M400                                                                                                             ; wait for moves to finish\n  M118 Unload Complete!\n\n\n[gcode_macro LOAD_FILAMENT]\ndescription: Loads filament to toolhead\ngcode:\n  {% set EXTRUDER_TEMP = params.TEMP|default(230)|int %}\n  {% set CURRENT_TEMP = printer.extruder.temperature|int %}\n  {% if CURRENT_TEMP < EXTRUDER_TEMP %}\n    M104 S{EXTRUDER_TEMP}                                                                                          ; heat up the hotend\n  {% endif %}\n   \n  GO_TO_POOP_SHOOT                                                                                                 ; go to poop shoot\n  \n  {% if CURRENT_TEMP < EXTRUDER_TEMP %}\n    M109 S{EXTRUDER_TEMP}                                                                                          ; heat up the hotend\n  {% endif %}  \n  SET_STEPPER_ENABLE STEPPER=extruder ENABLE=1                                                                     ; enable extruder stepper \n  M83                                                                                                              ; set extruder to relative mode\n  G1 E5 F120                                                                                                       ; feed filament\n  G1 E5 F300                                                                                                       ; feed filament\n  G1 E40 F600                                                                                                      ; feed filament\n  G1 E15 F300                                                                                                      ; feed filament\n  G1 E15 F120                                                                                                      ; feed filament\n  G4 P200                                                                                                          ; pause for a short amount of time\n  G1 E10 F90                                                                                                       ; feed filament\n  M104 S0                                                                                                          ; turn off hotend\n  LEAVE_POOP_SHOOT                                                                                                 ; leave poop shoot\n  M400                                                                                                             ; wait for moves to finish\n  M118 Load Complete!\n\n\n# Filament runout sensor enable/disable\n[gcode_macro M8029]\ngcode:\n     {% if params.D is defined %}\n       {% if (params.D|int)==1 %} \n        SET_FILAMENT_SENSOR SENSOR=filament_tangle_sensor ENABLE=1\n       {% endif %}\n       {% if (params.D|int)==0 %} \n        SET_FILAMENT_SENSOR SENSOR=filament_tangle_sensor ENABLE=0\n       {% endif %}\n     {% endif %}\n\n\n########################################\n# Fan Macros\n########################################\n# Set Fan Speed macro\n# Mainly name castings for nicer web interface names and display functionality\n[gcode_macro M106]\nrename_existing: M106.1\ngcode:\n    {% if params.P is defined %}\n      {% if params.S is defined %}\n        {% set speed = 0.003921*params.S|int %}\n        {% if (params.P|int) == 0 %}\n          M106.1 S{params.S|int}\n        {% elif (params.P|int) == 2 %}\n          SET_FAN_SPEED FAN=sidefan SPEED={speed}\n        {% elif (params.P|int) == 3 %}\n          SET_FAN_SPEED FAN=filterfan SPEED={speed}\n        {% else %}\n          SET_FAN_SPEED FAN=fan{params.P|int} SPEED={speed}\n        {% endif %}\n      {% else %}\n        {% if (params.P|int) == 0 %}\n          M106.1 S255\n        {% elif (params.P|int) == 2 %}\n          SET_FAN_SPEED FAN=sidefan SPEED=1\n        {% elif (params.P|int) == 3 %}\n          SET_FAN_SPEED FAN=filterfan SPEED=1\n        {% else %}\n          SET_FAN_SPEED FAN=fan{params.P|int} SPEED=1\n        {% endif %}\n      {% endif %}\n    {% endif %} \n\n    {% if params.T is defined %}\n      {% if (params.T|int) == -2 %}\n        {% if params.S is defined %}\n          {% set speed = 0.003921*params.S|int %}\n          SET_FAN_SPEED FAN=filterfan SPEED={speed}\n        {% else %}\n          SET_FAN_SPEED FAN=filterfan SPEED=1\n        {% endif %}\n      {% endif %}\n    {% endif %}\n\n    {% if params.P is undefined %}\n      {% if params.T is undefined %}\n        {% if params.S is defined %}\n          M106.1 S{params.S|int}\n        {% else %}\n          M106.1 S255\n        {% endif %}\n      {% endif %}\n    {% endif %}\n\n[gcode_macro M107]\nrename_existing: M107.1\ngcode:  \n    M106.1 S0\n\n\n########################################\n# Temperature Macros\n########################################\n# Wait for Hotend Temperature\n[gcode_macro M109]\nrename_existing: M109.1\ngcode:\n    #Parameters\n    {% set s = params.S|float %}\n\n    M104 {% for p in params %}{'%s%s' % (p, params[p])}{% endfor %}                                              ; Set hotend temp\n    {% if s != 0 %}\n        TEMPERATURE_WAIT SENSOR=extruder MINIMUM={s} MAXIMUM={s+1}                                               ; Wait for hotend temp (within 1 degree)\n    {% endif %}\n\n\n# PID autotune\n[gcode_macro M303]\ngcode:\n    {% if params.E is defined %}\n     {% if params.S is defined %}\n        {% if (params.E|int)==-1 %} \n         PID_CALIBRATE HEATER=heater_bed TARGET={params.S|int}\n        {% endif %}\n        {% if (params.E|int)==0 %}\n         PID_CALIBRATE HEATER=extruder TARGET={params.S|int}\n        {% endif %}\n     {% endif %}\n  {% endif %}\n\n\n# Set chamber temperature\n[gcode_macro M141]\ngcode:\n    {% if printer[\"heater_generic chamber\"] is defined %}\n        {% set chamber_target_temp = params.S|float %}\n        SET_HEATER_TEMPERATURE HEATER=chamber TARGET={([chamber_target_temp, 65]|min)}\n    {% endif %}\n\n\n# Set wait chamber temperature\n[gcode_macro M191]\ngcode:\n    #Parameters\n    {% set chamber_target_temp = params.S|float %}\n\n    {% if chamber_target_temp == 0 %}\n        M118 Chamber heater off\n    {% else %}\n        M141 S{chamber_target_temp}\n        TEMPERATURE_WAIT SENSOR=\"heater_generic chamber\" MINIMUM={([chamber_target_temp, 65]|min)-2} MAXIMUM={chamber_target_temp + 5}  \n        M118 Chamber at target temperature\n    {% endif %}\n\n\n########################################\n# Sound Macros\n########################################\n[gcode_macro BEEP]\ngcode:\n    # Parameters\n    {% set i = params.I|default(1)|int %}                                                                        ; Iterations (number of times to beep).\n    {% set dur = params.DUR|default(100)|int %}                                                                  ; Duration/wait of each beep in ms. Default 100ms.\n\n    {% if printer[\"output_pin sound\"].value|int == 1 %}\n        {% for iteration in range(i|int) %}\n            SET_PIN PIN=buzzer VALUE=1\n            G4 P{dur}\n            SET_PIN PIN=buzzer VALUE=0\n            G4 P{dur}\n        {% endfor %}\n    {% endif %}\n\n\n[gcode_macro beep_on]\ngcode:\n    SET_PIN PIN=buzzer VALUE=1\n\n\n[gcode_macro beep_off]\ngcode:\n    SET_PIN PIN=buzzer VALUE=0\n\n\n########################################\n# Z-height Macros\n########################################\n# Bed Leveling (Unified)\n[gcode_macro G29]\nvariable_k:1\ngcode:\n    {% set temp = printer[\"heater_generic chamber\"].target %}\n      M141 S0\n    {% if temp > 0 %}\n      G4 P15000\n    {% endif %}\n\n    {% if k|int==1 %}\n        BED_MESH_CLEAR                                                                                           ; Clear levelling data\n        BED_MESH_CALIBRATE ADAPTIVE=1 ADAPTIVE_MARGIN=5                                                          ; Start adaptive meshing\n    {% endif %}   \n    M141 S{temp}\n\n\n# Babystep\n[gcode_macro M290]\ngcode:\n   SET_GCODE_OFFSET Z_ADJUST={params.Z}\n\n\n########################################\n# Tuning Macros\n########################################\n[gcode_macro SHAPER_CALIBRATE]\nrename_existing: RESHAPER_CALIBRATE\ngcode:\n    RESHAPER_CALIBRATE FREQ_START=30 FREQ_END=130\n\n\n# Linear Advance Factor\n[gcode_macro M900]\ngcode:\n    {% if params.K is defined %} \n          SET_PRESSURE_ADVANCE ADVANCE={params.K}\n    {% endif %}  \n    {% if params.T is defined %}    \n       SET_PRESSURE_ADVANCE SMOOTH_TIME={params.T}\n    {% endif %} \n\n\n# Set Starting Acceleration\n[gcode_macro M204]\nrename_existing: M99204\ngcode:\n    {% if params.S is defined %}\n        {% set s = params.S|float %}\n    {% endif %}\n    {% if params.P is defined %}\n    {% if params.T is defined %}\n        {% set s = [params.P|float ,params.T|float] | min %}\n    {% endif %}\n    {% endif %}\n\n    SET_VELOCITY_LIMIT ACCEL={s}\n    SET_VELOCITY_LIMIT ACCEL_TO_DECEL={s/2}\n\n\n# Bed leveling\n# For more information, see https://www.klipper3d.org/Manual_Level.html#adjusting-bed-leveling-screws-using-the-bed-probe\n[gcode_macro LEVEL_BED]\ndescription: \"Measure bed and calculate screw adjustments for manual bed leveling\"\ngcode:\n    G28                                                                                                         ; Home all\n    SCREWS_TILT_CALCULATE                                                                                       ; Perform measurements and output screw adjustments\n\n\n# Automatic rough Bed Leveling by ramming the bed to the bottom\n[gcode_macro AUTO_LEVEL_BED]\ngcode:\n    {% set Z_max = printer.toolhead.axis_maximum.z %}\n    G28    \n    G1 Z{Z_max-30} F600\n    SET_TMC_CURRENT STEPPER=stepper_z CURRENT={printer.configfile.settings['tmc2209 stepper_z'].run_current * 0.5 }\n    SET_TMC_CURRENT STEPPER=stepper_z1 CURRENT={printer.configfile.settings['tmc2209 stepper_z1'].run_current * 0.5 }\n    G1 Z{Z_max} F600\n    SET_KINEMATIC_POSITION Z=0\n    G1 Z10 F600\n    G1 Z0 F600\n    G1 Z15 F600\n    SET_TMC_CURRENT STEPPER=stepper_z CURRENT={printer.configfile.settings['tmc2209 stepper_z'].run_current}\n    SET_TMC_CURRENT STEPPER=stepper_z1 CURRENT={printer.configfile.settings['tmc2209 stepper_z1'].run_current}\n    G28\n\n\n# Probe Calibration\n# For more information, see https://www.klipper3d.org/Probe_Calibrate.html\n[gcode_macro CALIBRATE_Z_OFFSET]\ndescription: \"Calibrate the Z offset using the probe\"\ngcode:\n    {% set max_x = printer.configfile.config[\"stepper_x\"][\"position_max\"]|float %}\n    {% set max_y = printer.configfile.config[\"stepper_y\"][\"position_max\"]|float %}\n\n    G28                                                                                                         ; Home all\n    G0 Z10                                                                                                      ; Increase z clearance\n    G0 X{max_x/2} Y{max_y-40} F6000                                                                             ; Move to bed center \n    PROBE_CALIBRATE                                                                                             ; Perform a probe calibration\n\n\n# Nozzle PID tuning\n# For more information, see https://www.klipper3d.org/Config_checks.html#calibrate-pid-settings\n[gcode_macro NOZZLE_PID_TUNE]\ndescription: \"Perform PID tuning for the nozzle heater\"\ngcode:\n    PID_CALIBRATE HEATER=extruder TARGET=220                                                                    ; PID tune the nozzle\n\n\n# Bed PID tuning\n# For more information, see https://www.klipper3d.org/Config_checks.html#calibrate-pid-settings\n[gcode_macro BED_PID_TUNE]\ndescription: \"Perform PID tuning for the bed heater\"\ngcode:\n    PID_CALIBRATE HEATER=heater_bed TARGET=80                                                                   ; PID tune the bed\n\n\n########################################\n# Macros for display functionallity\n########################################\n[gcode_macro INPUT_SHAPING_CALIBRATE]\ndescription: \"Perform Input Shaping calibration and save the results to printer.cfg\"\ngcode:\n    SHAPER_CALIBRATE                                                                                            ; Step 1: Perform the Input Shaping calibration\n    PAUSE                                                                                                       ; Step 2: Pause to allow the calibration to complete\n    SAVE_CONFIG                                                                                                 ; Step 3: Save the configuration to printer.cfg\n    RESTART                                                                                                     ; Step 4: Restart the firmware to apply the new settings\n\n\n"
  },
  {
    "path": "config_section/Plus4/printer.cfg",
    "content": "# Plus4 config created by Phil1988(github)/coco.33(discord) on 04.05.2025\n# For more information check out my wiki: https://github.com/Phil1988/FreeDi/wiki\n\n\n#####################################################################\n# Kinematics\n#####################################################################\n[printer]\nkinematics:corexy\nmax_velocity: 600\nmax_accel: 20000\nmax_z_velocity: 20\nmax_z_accel: 500\nsquare_corner_velocity: 8\n\n\n#####################################################################\n# Motherboard and periphery\n#####################################################################\n[temperature_sensor Mainboard_RK3328]\nsensor_type: temperature_host\nmin_temp: 10\nmax_temp: 100\n\n[mcu]\nserial: /dev/ttyS0\nrestart_method: command\nbaud: 500000\n\n[temperature_sensor Mainboard_STM32F402]\nsensor_type: temperature_mcu\nsensor_mcu: mcu\n\n[mcu Toolhead]\nserial: /dev/ttyS2\nrestart_method: command\nbaud: 500000\n\n[temperature_sensor Toolhead_STM32F103XE]\nsensor_type: temperature_mcu\nsensor_mcu: Toolhead\nmin_temp: 0\nmax_temp: 100\n\n\n#####################################################################\n# Features\n#####################################################################\n# For saving GCODE files\n[virtual_sdcard]\npath: ~/printer_data/gcodes\non_error_gcode: CANCEL_PRINT\n\n# For enabling pause/resume\n[pause_resume]\n\n# Activating exclude objects feature\n[display_status]\n[exclude_object]\n\n# Expanding idle timeout\n[idle_timeout]\ntimeout: 5400   ; 90min timeout\n\n# Activating GCODE arc feature\n[gcode_arcs]\nresolution: 1.0\n\n# Allowing free move (can be dangerous!)\n[force_move]\nenable_force_move: True\n\n# Activating responses\n[respond]\ndefault_type: echo\n\n\n#####################################################################\n# FreeDi\n#####################################################################\n[include freedi.cfg] \n\n\n#####################################################################\n# Macros\n#####################################################################\n[include macros.cfg]\n\n\n#####################################################################\n# Input shaping\n#####################################################################\n[resonance_tester]\naccel_chip: adxl345\nprobe_points:\n    150, 150, 10\naccel_per_hz: 75\nsweeping_period: 0\nmax_smoothing: 0.5\n    \n[adxl345]\ncs_pin: Toolhead:PA4\nspi_software_sclk_pin: Toolhead:PA5\nspi_software_mosi_pin: Toolhead:PA7\nspi_software_miso_pin: Toolhead:PA6\naxes_map: -x, z, -y\n\n[input_shaper]\nshaper_type_x: mzv\nshaper_freq_x: 57.6\nshaper_type_y: mzv\nshaper_freq_y: 46.6\n\n\n#####################################################################\n# Hotend\n#####################################################################\n[extruder]\nstep_pin: Toolhead:PB9\ndir_pin: Toolhead:PB8\nenable_pin: !Toolhead:PC15\nrotation_distance: 53.7\ngear_ratio: 1517:170\nmicrosteps: 16\nfull_steps_per_rotation: 200\nnozzle_diameter: 0.400\nfilament_diameter: 1.75\nmin_temp: 0\nmax_temp: 360\nmin_extrude_temp: 170\nsmooth_time: 0.000001\nstep_pulse_duration: 0.000002\n\nheater_pin: Toolhead:PB3\nsensor_type: MAX6675\nsensor_pin: Toolhead:PB12\nmax_power: 1.0\ncontrol: pid  \npid_Kp: 33.879\npid_Ki: 6.453\npid_Kd: 44.467\n\nspi_speed: 100000\nspi_software_sclk_pin: Toolhead:PB13\nspi_software_mosi_pin: Toolhead:PA11\nspi_software_miso_pin: Toolhead:PB14\n\npressure_advance: 0.032\npressure_advance_smooth_time: 0.03\nmax_extrude_cross_section:500\ninstantaneous_corner_velocity: 10.000\nmax_extrude_only_distance: 1000.0\nmax_extrude_only_velocity: 5000\nmax_extrude_only_accel: 5000\n\n[verify_heater extruder]\nmax_error: 120\ncheck_gain_time:20\nhysteresis: 5\nheating_gain: 1\n\n\n#####################################################################\n# Heated bed\n#####################################################################\n[heater_bed]\nheater_pin: PB10\nsensor_type: NTC 100K MGB18-104F39050L32\nsensor_pin: PA0\nmax_power: 1.0\ncontrol: pid\npid_kp: 70.638\npid_ki: 0.671\npid_kd: 1859.554\nmin_temp: -50\nmax_temp: 125\npwm_cycle_time: 0.02 # for 50Hz line power \n#pwm_cycle_time: 0.016 # for 60Hz line power\n\n[verify_heater heater_bed]\nmax_error: 200\ncheck_gain_time: 360\nhysteresis: 5\nheating_gain: 1\n\n\n#####################################################################\n# Bed mesh\n#####################################################################\n[bed_mesh]\nspeed: 150               \nhorizontal_move_z: 2.6   \nmesh_min: 25,10\nmesh_max: 295,295   \nprobe_count: 9,9     \nalgorithm: bicubic\nbicubic_tension: 0.3\nmesh_pps: 4, 4\n\n\n#####################################################################\n# Probe\n#####################################################################\n#!# Pay attention to this section and compare it with your stock backup config\n[probe]\npin: ^!Toolhead:PA10\nx_offset: 25\ny_offset: 1.3\nz_offset: 1.00             #!# change this to 0 if you get a \"Probe triggered prior to movement\" - Error\nspeed: 5\nsamples: 2\nsamples_result: average\nsample_retract_dist: 0.7\nsamples_tolerance: 0.08\nsamples_tolerance_retries: 3\n\n# Check this for documentation https://github.com/frap129/qidi_auto_z_offset\n# Add AUTO_Z_LOAD_OFFSET to your PRINT_START macro to load the value every time you start a print. \n# If you make adujstments to the offset by micro-stepping durring a print, you can save that with AUTO_Z_SAVE_GCODE_OFFSET and SAVE_CONFIG\n\n[auto_z_offset]\npin: PC1\n# Adjust this z_offset value for a good first layer: \n# decrease if lines are squished (eg -0.2 -> -0.25)\n# increase if lines are thin/not sticking (-0.2 -> -0.15)\nz_offset: -0.2 \ncalibrated_z_offset: -1.00\nspeed: 13\nprobe_accel: 50\nsamples: 5\nsamples_result: median\nsamples_tolerance: 0.013\nsamples_tolerance_retries: 5\noffset_samples: 3\nprepare_gcode:\n   G90\n   G0 Z3\n   G91\n   SET_PIN PIN=bed_sensor VALUE=0\n   M204 S10000\n   {% set i = 6 %}\n   {% for iteration in range(i|int) %}\n       G1 Z5 F1200\n       G1 Z-5 F1200\n   {% endfor %}\n   G1 Z3\n   G90\n   SET_PIN PIN=bed_sensor VALUE=1\n\n[output_pin bed_sensor]\npin: !PA14\npwm: false\nshutdown_value:0\nvalue:0\n\n#####################################################################\n# Heated chamber\n#####################################################################\n[temperature_sensor chamber_sensor]\nsensor_type: NTC 100K MGB18-104F39050L32\nsensor_pin: PA1\n\n\n[heater_generic chamber]\nheater_pin: PC8\n#!# Caution!\n#set max_power to 0.4 for 110V\n#set max_power to 0.7 for 220V\n#set max_power to 1.0 if you are using a quality aftermarket SSR with a heat sink\nmax_power: 0.4                #!# Pay attention to this value and compare it with your stock backup config and with caution (read the comments)\n#sensor_type: NTC 100K MGB18-104F39050L32\n#sensor_pin: PA1\nsensor_type: temperature_combined\nsensor_list: temperature_sensor Toolhead_STM32F103XE, temperature_sensor Toolhead_STM32F103XE, temperature_sensor Toolhead_STM32F103XE, temperature_sensor chamber_sensor\ncombination_method: mean\nmaximum_deviation: 70\ncontrol: pid\npid_Kp: 63.418 \npid_Ki: 1.342 \npid_Kd: 749.125\nmin_temp: -100\nmax_temp: 75\n\n[verify_heater chamber]\nmax_error: 400\ncheck_gain_time: 600\nhysteresis: 5\nheating_gain: 2\n\n[temperature_sensor Chamber_Heater]\nsensor_type: NTC 100K MGB18-104F39050L32\nsensor_pin: PC2\nmin_temp: -100\nmax_temp: 140\n\n\n########################################\n# Filament sensors\n########################################\n[filament_switch_sensor filament_tangle_sensor]\nswitch_pin: PC3\npause_on_runout: True\nrunout_gcode:\n            M118 Filament tangled!\nevent_delay: 3.0\npause_delay: 0.5\n\n[hall_filament_width_sensor]\nadc1: Toolhead:PA2\nadc2: Toolhead:PA3\ncal_dia1: 1.50\ncal_dia2: 2.0\nraw_dia1: 14206\nraw_dia2: 15278\ndefault_nominal_filament_diameter: 1.75\nmax_difference: 0.00\nmeasurement_delay: 50\nenable: True\nenable_flow_compensation: False\nmeasurement_interval: 3\nlogging: False\nmin_diameter: 1.00\nuse_current_dia_while_delay: False\npause_on_runout: True\nrunout_gcode:\n            M118 Filament run out!\nevent_delay: 3.0\npause_delay: 0.5\n\n\n#####################################################################\n# Fans\n#####################################################################\n## Part cooling fan \n# [fan_generic partfan]\n# pin: Toolhead:PA8\n# max_power: 1.0\n# cycle_time: 0.0100\n# hardware_pwm: false\n# kick_start_time: 0.200\n# off_below: 0.08\n# shutdown_speed: 0\n[fan]\npin: Toolhead:PA8\nmax_power: 1.0\ncycle_time: 0.0100\nhardware_pwm: false\nkick_start_time: 0.200\noff_below: 0.08\nshutdown_speed: 0.0\n\n## Big side radial turbo fan\n[fan_generic sidefan]\npin: PA8\nmax_power: 1.0\ncycle_time: 0.0100\nhardware_pwm: false\nkick_start_time: 0.250\noff_below: 0.3\nshutdown_speed: 0\n\n## Activated charcoal blowing fan\n[fan_generic filterfan]\npin: PC9\nmax_power: 1.0\ncycle_time: 0.0100\nhardware_pwm: false\nkick_start_time: 0.200\noff_below: 0.3\nshutdown_speed: 0\n\n## Chamber heater fan\n[heater_fan chamber_heater_fan]\npin: PA4\nmax_power: 1.0\nshutdown_speed: 0\nkick_start_time: 0.5\nheater: chamber\nfan_speed: 1.0\noff_below: 0\nheater_temp: 40 \n\n## Cold end and toolhead housing fans\n[heater_fan hotend_fan]\npin: Toolhead:PB5\nmax_power: 1.0\nshutdown_speed: 1.0\nkick_start_time: 0.5\nheater: extruder\nheater_temp: 50.0\nfan_speed: 1.0\noff_below: 0\n\n# Toolhead cooling fan\n[heater_fan hotend_fan2]\npin:Toolhead: PB4\nmax_power: 1.0\nshutdown_speed: 1.0\nkick_start_time: 0.5\nheater: extruder\nheater_temp: 50.0\nfan_speed: 1.0\noff_below: 0\n\n# Toolhead cooling fan\n[heater_fan hotend_fan3]\npin:Toolhead: PB10\nmax_power: 1.0\nshutdown_speed: 1.0\nkick_start_time: 0.5\nheater: extruder\nheater_temp: 50.0\nfan_speed: 1.0\noff_below: 0\n\n#!# Delete the next section if your stock backup config doesnt have it\n## Controllable Mainboard cooling fan\n[temperature_fan Mainboard_fan]\nsensor_type: temperature_host \npin: PC4\nmax_power: 1.0  \ncycle_time: 0.01\nsensor_type: temperature_combined\nsensor_list: temperature_sensor Mainboard_RK3328, temperature_sensor Mainboard_STM32F402\ncombination_method: max                                           # use the maximum reading of the sensors\nmaximum_deviation: 999.9                                          # we don't care about the difference in temperature\nshutdown_speed: 0.0\nkick_start_time: 0.4\noff_below: 0.19\nmin_temp: 0\nmax_temp: 85.0 \ntarget_temp: 42.0\nmin_speed: 0\nmax_speed: 1.0\ncontrol: pid\npid_deriv_time: 2.0\npid_Kp: 5.0\npid_Ki: 2.5\npid_Kd: 3.5\n\n\n#####################################################################\n# Light\n#####################################################################\n## caselight LEDs\n[output_pin caselight]\npin: PC7\npwm: true\ncycle_time: 0.0100\nshutdown_value:0\nvalue:1\n\n\n#####################################################################\n# Buzzer\n#####################################################################\n## Buzzer\n[output_pin buzzer]\npin: PA2\npwm: false\nshutdown_value:0\nvalue:0\n\n[output_pin sound]\npin: Toolhead:PA1\nvalue:0\n\n\n#####################################################################\n# Power outage shutdown\n#####################################################################\n[output_pin pwc]\npin: PA3\npwm: False\nvalue: 1\nshutdown_value: 1\n\n\n#####################################################################\n# Drives\n#####################################################################\n[stepper_x]\nstep_pin: PB4\ndir_pin: !PB3\nenable_pin: !PB5\nmicrosteps: 32\nrotation_distance: 38.82\nfull_steps_per_rotation: 200 \nendstop_pin: tmc2240_stepper_x:virtual_endstop\nposition_min: -1.5\nposition_endstop: -1.5\nposition_max: 307\nhoming_speed: 55\nhoming_retract_dist:0\nhoming_positive_dir:False\nstep_pulse_duration:0.0000001\n\n[stepper_y]\nstep_pin: PC14\ndir_pin: !PC13\nenable_pin: !PC15\nmicrosteps: 32\nrotation_distance: 38.82\nfull_steps_per_rotation:200  \nendstop_pin: tmc2240_stepper_y:virtual_endstop\nposition_min: -2\nposition_endstop: -2\nposition_max: 325\nhoming_speed: 55\nhoming_retract_dist: 0\nhoming_positive_dir: False\nstep_pulse_duration: 0.0000001\n\n[stepper_z]\nstep_pin: PB1\ndir_pin: PB6\nenable_pin: !PB0\nmicrosteps: 16\nrotation_distance: 4\nfull_steps_per_rotation: 200\nendstop_pin: probe:z_virtual_endstop\nposition_max:285\nposition_min: -4\nhoming_speed: 13\nhoming_retract_dist: 8.0\nsecond_homing_speed: 5\nhoming_positive_dir: False\nstep_pulse_duration: 0.000002\n\n[stepper_z1]\nstep_pin: PC10\ndir_pin: PA15\nenable_pin: !PC11\nmicrosteps: 16\nrotation_distance: 4\nfull_steps_per_rotation: 200\nstep_pulse_duration: 0.000002\n\n#####################################################################\n# Steppers configuration\n#####################################################################\n[tmc2209 extruder]\nuart_pin: Toolhead:PC13\ninterpolate: False\nrun_current: 0.714             #!# Pay attention to this value and compare it with your stock backup config\nstealthchop_threshold: 0\nsense_resistor: 0.075\n\n[tmc2240 stepper_x]\ncs_pin: PD2\nspi_software_sclk_pin: PA5\nspi_software_mosi_pin: PA7\nspi_software_miso_pin: PA6\nspi_speed: 200000\nrun_current: 1.07               #!# Pay attention to this value and compare it with your stock backup config\ninterpolate: False\nstealthchop_threshold: 0\ndiag0_pin: !PB8\ndriver_SGT: 1\nrref: 12000\n\n[tmc2240 stepper_y]\ncs_pin: PB9\nspi_software_sclk_pin: PA5\nspi_software_mosi_pin: PA7\nspi_software_miso_pin: PA6\nspi_speed: 200000\nrun_current: 1.07              #!# Pay attention to this value and compare it with your stock backup config\ninterpolate: False\nstealthchop_threshold: 0\ndiag0_pin: !PC0\ndriver_SGT:1\nrref: 12000\n\n[tmc2209 stepper_z]\nuart_pin: PB7\nrun_current: 1.07              #!# Pay attention to this value and compare it with your stock backup config\ninterpolate: False\nstealthchop_threshold: 9999999999\ndiag_pin: ^PA13\nsense_resistor: 0.075\n\n\n[tmc2209 stepper_z1]\nuart_pin: PC5\nrun_current: 1.07              #!# Pay attention to this value and compare it with your stock backup config\ninterpolate: False\nstealthchop_threshold: 9999999999\ndiag_pin: ^PC12\nsense_resistor: 0.075\n\n#####################################################################\n# Bed tilt adjust\n#####################################################################\n[z_tilt]\nz_positions:\n    -17.5,138.5\n    335.7,138.5\n\npoints:\n    0,138.5\n    255,138.5\n\nspeed: 150\nhorizontal_move_z: 10\nretries: 5\nretry_tolerance: 0.013\n\n#####################################################################\n# Screws tilt adjust\n#####################################################################\n[screws_tilt_adjust] \nhorizontal_move_z: 5\nscrew_thread: CW-M4\nspeed: 300\n\nscrew1:0,20\nscrew1_name: Front left\nscrew2: 260,20\nscrew2_name: Front right\nscrew3: 260,280\nscrew3_name: Back right\nscrew4: 0,280\nscrew4_name: Back left\n\n"
  },
  {
    "path": "config_section/Q1_Pro/macros.cfg",
    "content": "#####################################################################\n# Specific Q1 Pro macros\n#####################################################################\n\n[gcode_macro SET_PRINT_STATS_INFO]\nrename_existing: BASE_SET_PRINT_STATS_INFO_BASE\ngcode:\n    TIMELAPSE_TAKE_FRAME\n    BASE_SET_PRINT_STATS_INFO_BASE {rawparams}\n    CHAMBER_TEMP_CONTROLLER\n\n\n# Safety macro that gets frequently called by SET_PRINT_STATS_INFO to prevent too high chamber temperatures\n[gcode_macro CHAMBER_TEMP_CONTROLLER]\ngcode:\n    {% set chamber_target_temp = printer['heater_generic chamber'].target %}\n    {% set chamber_temp = printer['heater_generic chamber'].temperature %}\n    {% if chamber_temp > printer.configfile.settings['heater_generic chamber'].max_temp %}\n        M106 P3 S255\n    {% else %}\n        {% if chamber_target_temp > 0 %}\n            # Allow for 3C of \"grace\" before we start ramping the exhaust fan speed\n            # This prevents the macro from fighting with the chamber heater PID algorithm\n            {% set difference = chamber_temp - (chamber_target_temp + 3) %}\n            {% if difference > 0 %}\n                {% set filterfan_speed = ([(difference * 50), 255] | min) | int %}\n                M106 P3 S{filterfan_speed}\n            {% else %}\n                M106 P3 S0\n            {% endif %}\n        {% endif %}\n    {% endif %}\n\n\n\n[gcode_macro CHAMBER_TEMP_CONTROLLER]\ngcode:\n    {% set chamber_cfg = printer.configfile.settings['heater_generic chamber'] %}\n    {% set chamber_target_temp = printer['heater_generic chamber'].target %}\n    {% set chamber_temp = printer['heater_generic chamber'].temperature %}\n    {% set min_filterfan = (255 * 0.40) | int %}  # ~35 % Mindestdrehzahl\n    \n    {% if chamber_temp > chamber_cfg.max_temp %}\n        M106 P3 S255\n    {% elif chamber_target_temp > 0 %}\n        {% set difference = chamber_temp - (chamber_target_temp + 3) %}\n        {% set raw_speed = ([(difference * 50), 255] | min) | int %}\n        {% set filterfan_speed = [raw_speed, min_filterfan] | max %}\n        M106 P3 S{filterfan_speed}\n    {% else %}\n        M106 P3 S0\n    {% endif %}\n\n\n\n[gcode_macro HOME_IF_NEEDED]\ndescription: Homes X and Y if needed\ngcode:\n    {% if \"y\" not in printer.toolhead.homed_axes %}\n        G28 Y\n    {% endif %}\n    {% if \"x\" not in printer.toolhead.homed_axes %}\n        G28 X\n    {% endif %}\n    {% if \"z\" not in printer.toolhead.homed_axes %}\n        G28 Z\n    {% endif %}\n\n\n[gcode_macro _SET_ACCEL]\ngcode:\n    {% set printer_config = printer.configfile.settings['printer'] %}\n    {% set set_acceleration = params.ACCEL|default(printer_config.max_accel)|float %}\n    SET_VELOCITY_LIMIT ACCEL={set_acceleration}\n\n\n[gcode_macro _FELT_WIPE]\ndescription: Wipe on the felt pad\ngcode:\n    G90                                                                                                            ; Absolute positioning\n\n    ; Input values for the minimum and maximum coordinates of the pad\n    {% set pad_min_coordinate_x = 60 %}\n    {% set pad_max_coordinate_x = 88 %}\n    {% set pad_min_coordinate_y = 250 %}\n    {% set pad_max_coordinate_y = 254 %}\n    {% set margin = 1 %} ; margin from the edge of the pad\n    {% set repetitions = 3 %} \n\n    ; Calculate wipe area (with margin)\n    {% set x_start = pad_min_coordinate_x + margin %}\n    {% set x_end   = pad_max_coordinate_x - margin %}\n    {% set y_start = pad_min_coordinate_y + margin %}\n    {% set y_end   = pad_max_coordinate_y - margin %}\n\n    ; First X wiping (Y stays constant, X moves back and forth)\n    {% set random_y_start = (range(0, (y_end - y_start) * 20) | random) / 20 + y_start %} ; Calculate a random starting Y position within the allowed range\n    G1 Y{random_y_start} F1500    ; Move to random Y position\n    G1 X{x_start} F1500           ; Move to X start position\n    {% for move in range(repetitions|int) %}\n        G1 X{x_end} F500\n        G1 X{x_start} F500\n    {% endfor %}\n\n    ; Y wiping (X stays constant, Y moves back and forth)\n    {% set random_x_start = (range(0, (x_end - x_start) * 20) | random) / 20 + x_start %} ; Calculate a random starting X position within the allowed range\n    G1 X{random_x_start} F1500    ; Move to random X position\n    G1 Y{y_start} F1500           ; Move to Y start position\n    {% for move in range(repetitions|int) %}\n        G1 Y{y_end} F500\n        G1 Y{y_start} F500\n    {% endfor %}    \n\n    ; Additional X wiping (Y stays constant, X moves back and forth)\n    {% set random_y_start_2 = (range(0, (y_end - y_start) * 20) | random) / 20 + y_start %} ; Calculate a random starting Y position within the allowed range\n    G1 Y{random_y_start_2} F1500    ; Move to random Y position again\n    G1 X{x_start} F1500           ; Move to X start position\n    {% for move in range(repetitions|int) %}\n        G1 X{x_end} F500\n        G1 X{x_start} F500\n    {% endfor %}\n\n\n[gcode_macro GO_TO_POOP_BUCKET]\ndescription: Move toolhead to poop bucket\ngcode:\n    {% set curr_x = printer.toolhead.position.x %}\n    {% set curr_y = printer.toolhead.position.y %}\n    {% if (curr_y != 240) or (curr_x != 97) %}\n        _Z_CLEARANCE DISTANCE=0 MIN_Z=40                                                                               ; Make sure to have enough clearance\n        G90                                                                                                            ; Absolute positioning\n        {% if printer.gcode_move.position.y > 240 %}\n            G1 Y240 F9000\n        {% endif %}\n        G1 X97 Y240 F9000\n        _SET_ACCEL ACCEL=100                                                                                           ; Reduce acceleration to 100mm/s^2\n        G1 Y254 F1500                                                                                                  ; gently press against wiper arm\n        _SET_ACCEL                                                                                                     ; Reset acceleration\n    {% endif %}\n\n\n[gcode_macro LEAVE_POOP_BUCKET]\ndescription: Leaving the poop bucket\ngcode:\n    {% set curr_x = printer.toolhead.position.x %}\n    {% set curr_y = printer.toolhead.position.y %}\n    {% if (curr_y >= 240) and (curr_x >= 59) and (curr_x <= 98) %}\n        G90                                                                                                         ; Absolute positioning\n        _SET_ACCEL ACCEL=500\n        G1 Y254 F2000\n        G1 X70 F5000\n        _SET_ACCEL ACCEL=100\n        G1 Y240 F1500                                                                                               ; gently leave the wiper arm\n        _SET_ACCEL                                                                                                  ; reset accel\n    {% endif %}\n\n[gcode_macro _BUCKET_CUT]\ndescription: Cut off the extruded filament on the nozzle\ngcode:\n    {% set i = 6 %}\n    {% for iteration in range(i|int) %}\n        G1 X85 F2000\n        G1 X97 F2000\n    {% endfor %}\n\n\n[gcode_macro PRIME_NOZZLE]\ndescription: Primes the nozzle with fresh filament before load/unload/print start\ngcode:\n    {% set hotend_target_temp = params.HOTEND_TARGET_TEMP|default(220)|int %}\n    \n    M106 S0\n    M104 S{hotend_target_temp}\n\n    HOME_IF_NEEDED\n\n    TEMPERATURE_WAIT SENSOR=extruder MINIMUM={hotend_target_temp-50}\n    GO_TO_POOP_BUCKET\n\n    M109 S{hotend_target_temp}\n\n    G92 E0\n    G1 E5 F50\n    G1 E50 F200\n    G92 E0\n    G1 E-0.8 F200\n    G4 P300\n\n   \n    M104 S{([hotend_target_temp-80, 150]|min)} \n    M106 S255\n    G4 P5000\n\n    _FELT_WIPE\n    TEMPERATURE_WAIT SENSOR=extruder MAXIMUM={([hotend_target_temp-80, 150]|min)}\n    M106 S0\n\n    _BUCKET_CUT\n    LEAVE_POOP_BUCKET\n\n\n#####################################################################\n# Homing modification\n#####################################################################\n[gcode_macro G28]\nrename_existing: G28.1\ngcode:\n    {% set reduced_current_x = 0.55 %}\n    {% set reduced_current_y = 0.45 %}\n    {% set home_all = ('X' in rawparams.upper() and 'Y' in rawparams.upper() and 'Z' in rawparams.upper()) or \n                      ('X' not in rawparams.upper() and 'Y' not in rawparams.upper() and 'Z' not in rawparams.upper()) %}\n    {% set home_current_x = printer.configfile.settings['tmc2240 stepper_x'].run_current * reduced_current_x %}\n    {% set home_current_y = printer.configfile.settings['tmc2240 stepper_y'].run_current * reduced_current_y %}\n\n    {% set init_XY_move = 30 %}\n    #{% set y_init_move = 5 %}\n    {% set z_clearance = 2 %}\n\n    {% set home_all_final_position_x = printer.toolhead.axis_maximum.x / 2 %}\n    {% set home_all_final_position_y = printer.toolhead.axis_maximum.y - 40 %}\n    {% set home_all_final_position_z = 20 %}\n\n\n    {% if 'x' not in printer.toolhead.homed_axes %}\n      {% set X_axis_was_homed = false %}                                                                           ; Set Z_axis_was_homed to false if Z is not homed\n    {% endif %}\n    {% if 'y' not in printer.toolhead.homed_axes %}\n      {% set Y_axis_was_homed = false %}                                                                           ; Set Z_axis_was_homed to false if Z is not homed\n    {% endif %}\n            \n    # If homing should at least move X or Y axis\n    {% if home_all or 'X' in rawparams.upper() or 'Y' in rawparams.upper() %}     \n        # Check if Z is homed\n        {% if 'z' in printer.toolhead.homed_axes %}\n            {% set Z_axis_was_homed = true %}                                                                       ; Set Z_axis_was_homed to true if Z is already homed\n            G91                                                                                                     ; Use relative positioning\n            G1 Z2 F600                                                                                              ; Move bed down\n            G90                                                                                                     ; Use absolute positioning\n        {% else %}\n            {% set Z_axis_was_homed = false %}                                                                      ; Set Z_axis_was_homed to false if Z is not homed\n            G90\n            SET_KINEMATIC_POSITION Z=0                                                                              ; To allow bed move down\n            G1 Z{z_clearance}                                                                                       ; Move bed down\n            {% if X_axis_was_homed == false %}\n              SET_KINEMATIC_POSITION SET_HOMED= CLEAR_HOMED=X                                                       ; Set X to be unhomed\n            {% endif %}\n            {% if Y_axis_was_homed == false %}\n              SET_KINEMATIC_POSITION SET_HOMED= CLEAR_HOMED=Y                                                       ; Set Y to be unhomed\n            {% endif %}            \n        {% endif %}\n    {% endif %}\n\n    {% if home_all or 'X' in rawparams.upper() or 'Y' in rawparams.upper() %} \n        FORCE_MOVE STEPPER=stepper_x DISTANCE={init_XY_move} VELOCITY=40                                            ; Move X a little before homing\n        SET_KINEMATIC_POSITION X={printer.toolhead.position.x + (init_XY_move/2)}                                   ; Compensate the FORCE_MOVE position \n        SET_KINEMATIC_POSITION Y={printer.toolhead.position.y + (init_XY_move/2)}                                   ; Compensate the FORCE_MOVE position\n        {% if X_axis_was_homed == false %}\n          SET_KINEMATIC_POSITION SET_HOMED= CLEAR_HOMED=X                                                           ; Set X to be unhomed\n        {% endif %}\n        {% if Y_axis_was_homed == false %}\n          SET_KINEMATIC_POSITION SET_HOMED= CLEAR_HOMED=Y                                                           ; Set Y to be unhomed\n        {% endif %} \n    {% endif %}\n\n    # Home Y\n    {% if home_all or 'Y' in rawparams.upper() %}\n        SET_TMC_CURRENT STEPPER=stepper_x CURRENT={home_current_x}                                                  ; Lower motor current\n        SET_TMC_CURRENT STEPPER=stepper_y CURRENT={home_current_y}                                                  ; Lower motor current\n        G28.1 Y                                                                                                     ; Home Y\n        SET_TMC_CURRENT STEPPER=stepper_x CURRENT={printer.configfile.settings['tmc2240 stepper_x'].run_current}    ; Set motor current to the previous value\n        SET_TMC_CURRENT STEPPER=stepper_y CURRENT={printer.configfile.settings['tmc2240 stepper_y'].run_current}    ; Set motor current to the previous value\n        G1 Y10 F1200                                                                                                ; Move Y-axis slightly\n    {% endif %}\n    \n    # Home X\n    {% if home_all or 'X' in rawparams.upper() %}        \n        SET_TMC_CURRENT STEPPER=stepper_x CURRENT={home_current_x}                                                  ; Lower motor current\n        SET_TMC_CURRENT STEPPER=stepper_y CURRENT={home_current_x}                                                  ; Lower motor current\n        G28.1 X                                                                                                     ; Home X\n        SET_TMC_CURRENT STEPPER=stepper_x CURRENT={printer.configfile.settings['tmc2240 stepper_x'].run_current}    ; Set motor current to the previous value\n        SET_TMC_CURRENT STEPPER=stepper_y CURRENT={printer.configfile.settings['tmc2240 stepper_y'].run_current}    ; Set motor current to the previous value\n        G1 X10 F1200                                                                                                ; Move X-axis slightly\n    {% endif %}\n\n    # Raise the bed again if only X or only Y axes were homed\n    {% if not (home_all or 'Z' in rawparams.upper()) %}\n        {% if Z_axis_was_homed %}\n            G91                                                                                                     ; Use relative positioning\n            G1 Z-2 F600                                                                                             ; Raise the bed back again\n            G90                                                                                                     ; Use absolute positioning\n        {% else %}\n            G1 Z0.1                                                                                                 ; Raise the bed back again\n            SET_STEPPER_ENABLE STEPPER=stepper_z enable=0                                                           ; Disable Z to prevent collisions\n            SET_STEPPER_ENABLE STEPPER=stepper_z1 enable=0                                                          ; Disable Z to prevent collisions\n            SET_KINEMATIC_POSITION SET_HOMED= CLEAR_HOMED=Z                                                         ; Set Z to be unhomed\n        {% endif %}\n    {% endif %}\n\n    # Home Z\n    {% if home_all or 'Z' in rawparams.upper() %}\n        G1 X{printer.toolhead.axis_maximum.x / 2} Y{printer.toolhead.axis_maximum.x / 2} F12000 \n        G28.1 Z                                                                                                     ; Home Z\n        G90                                                                                                         ; Set absolute positioning\n        G1 Z{home_all_final_position_z} F600                                                                        ; Move bed down\n    {% endif %}\n\n    # Move to the final position if all axes were homed\n    {% if home_all %}\n        G90                                                                                                         ; Set absolute positioning\n        G1 X{home_all_final_position_x} Y{home_all_final_position_y} Z{home_all_final_position_z} F7800             ; Move to the rear center\n    {% endif %}\n    \n\n# Unconditional stop\n[gcode_macro M0]\ngcode:\n    PAUSE\n\n\n# Pause SD print\n[gcode_macro M25]\nrename_existing: M9925\ngcode:\n    PAUSE\n\n\n########################################\n# Basic Macros\n########################################\n# Flag macro to use STATIC_MESH usage instead of KAMP (needed make this function work from printjob selection on the LCD)\n[gcode_macro NEXT_PRINT_STATIC_MESH]\ndescription: Forces the NEXT print to use 'STATIC_MESH' instead of KAMP.\ngcode:\n    {% if \"STATIC_MESH\" in printer.bed_mesh.profiles %}\n        SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=force_static_mesh VALUE=True\n        {action_respond_info(\"The NEXT print will use 'STATIC_MESH'.\")}\n        M118 The NEXT print will use the STATIC_MESH.\n    {% else %}\n        {action_respond_info(\"WARNING: No mesh named 'STATIC_MESH' found. Please save one first (BED_MESH_PROFILE SAVE=STATIC_MESH).\")}\n        M118 WARNING: No mesh named STATIC_MESH found. Please save one first (BED_MESH_PROFILE SAVE=STATIC_MESH).\n    {% endif %}\n\n\n[gcode_macro PRINT_START]\n# Use PRINT_START for the slicer starting script\ndescription: Start printing\nvariable_force_static_mesh: False                                                                                 ; Set to True to force a static mesh instead of KAMP\ngcode:\n    {% set bed_target_temp = params.BED|int %}\n    {% set hotend_target_temp = params.HOTEND|int %}\n    {% set chamber_target_temp = params.CHAMBER|default(0)|int %}\n    {% set bed_center_x = printer.configfile.config[\"stepper_x\"][\"position_max\"]|float / 2 %}\n    {% set bed_center_y = printer.configfile.config[\"stepper_y\"][\"position_max\"]|float / 2 %}\n\n    {% set start_position_x = printer.toolhead.axis_maximum.x / 2 %}\n    {% set start_position_y = printer.toolhead.axis_maximum.y - 40 %}\n    {% set start_position_z = 10 %}\n\n    CLEAR_PAUSE                                                                                                    ; Clear existing pause states\n    BED_MESH_CLEAR                                                                                                 ; Clear previous adaptive mesh\n\n    {% set KAMP_deactivated = printer[\"gcode_macro PRINT_START\"].force_static_mesh %}                              ; Check if KAMP is deactivated for this print\n    SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=force_static_mesh VALUE=False                                    ; Auto-reset the variable immediately for the next print after this one\n\n    SET_TEMPERATURE_FAN_TARGET TEMPERATURE_FAN=Mainboard_fan TARGET=1                                              ; Decrease the mainboard target temp to fully turn the fan on\n    \n    M140 S{bed_target_temp}\n    M141 S{chamber_target_temp}\n    G28\n\n    {% if chamber_target_temp > 0 %}                                                                               ; Accelerate chamber heating by using the bed as additional heater    \n        G0 X{bed_center_x} Y{bed_center_y} Z3 F780                                                                 ; Move print bed to perfect postion to help chamber heating\n        M106 P2 S185                                                                                               ; Turn sidefan on to use bed heat and mix air\n        M106 P0 S128                                                                                               ; Turn part cooling fan on to help air mixing\n        TEMPERATURE_WAIT SENSOR=\"heater_generic chamber\" MINIMUM={chamber_target_temp - 5}                         ; Wait for chamber to heat up\n        M106 P2 S0                                                                                                 ; Turn off sidefan\n        M106 P0 S0                                                                                                 ; Turn off part cooling fan                                      \n    {% endif %}\n\n    {% if bed_target_temp !=0 %}\n      TEMPERATURE_WAIT SENSOR=heater_bed MINIMUM={bed_target_temp * 0.95} MAXIMUM={bed_target_temp * 1.05}\n    {% endif %}\n\n    M191 S{chamber_target_temp}                                                                                    ; Set and wait for chamber temperature\n    M190 S{bed_target_temp}                                                                                        ; Set and wait for bed temperature \n    G90                                                                                                            ; Set absolute positioning\n    G1 X{start_position_x} Y{start_position_y} Z{start_position_z} F7800                                           ; Move to start position\n    G28 Z                                                                                                          ; Home Z again for to compensate bed expansion  \n\n    {% if KAMP_deactivated %}\n        {% if \"STATIC_MESH\" in printer.bed_mesh.profiles %}                                                        ; Check if the spicific STATIC_MESH exists\n            M118  Loading 'STATIC_MESH' instead of KAMP.\n            BED_MESH_PROFILE LOAD=STATIC_MESH\n        {% else %}                                                                                                 ; Fallback to KAMP if STATIC_MESH not found\n            M118 ERROR: 'STATIC_MESH' not found! Using fallback: KAMP Adaptive Mesh.\n            BED_MESH_CLEAR                                                                                         ; Clear previous adaptive mesh\n            BED_MESH_CALIBRATE PROFILE=adaptive ADAPTIVE=1                                                         ; Start adaptive meshing\n        {% endif %}\n    {% else %}                                                                                                     ; Standard operation\n        {% if printer.toolhead.homed_axes|length < 3 %}\n            G28\n        {% endif %}\n        BED_MESH_CLEAR                                                                                             ; Clear previous adaptive mesh\n        BED_MESH_CALIBRATE PROFILE=adaptive ADAPTIVE=1                                                             ; Start adaptive meshing\n    {% endif %}\n\n    PRIME_NOZZLE hotend_target_temp={hotend_target_temp}\n    M109 S{hotend_target_temp}                                                                                     ; Set and wait for hotend temperature \n\n\n[gcode_macro PRINT_END]\ngcode:\n    {% set max_x = printer.configfile.config[\"stepper_x\"][\"position_max\"]|float %}\n    {% set max_y = printer.configfile.config[\"stepper_y\"][\"position_max\"]|float %}\n    {% set max_z = printer.configfile.config[\"stepper_z\"][\"position_max\"]|float %}\n        {% set current_extruder_temp = printer.extruder.temperature|float %}\n    {% set min_extrusion_temp = printer.configfile.config[\"extruder\"][\"min_extrude_temp\"]|float %}\n    {% set z_clearance = 50 %}\n\n    {% if (printer.toolhead.position.z + z_clearance) < max_z %}\n        {% set z_hop = 2  %}\n    {% else %}\n        {% set z_hop = 0 %}\n    {% endif %}\n\n    M106 P0 S0                                                                                                      ; Turn off part cooling fan\n    M106 P2 S0                                                                                                      ; Turn off side fan\n    M106 P3 S0                                                                                                      ; Turn off activated charcoal fan\n\n    M104 S0                                                                                                         ; Turn off hotend\n    M140 S0                                                                                                         ; Turn off heated bed\n    M141 S0                                                                                                         ; Turn off heated chamber\n\n    G91                                                                                                             ; Relative positioning\n    {% if current_extruder_temp >= min_extrusion_temp + 5 %}                                                        ; Check if the hotend is hot enough to perform a retraction (with a small gap)  \n        G0 E-4.0 F300                                                                                               ; Retract filament\n    {% endif %}\n    G0 Z{z_hop} F3600                                                                                               ; Move bed down a bit\n    G90                                                                                                             ; Absolute positioning\n    G0 X{max_x/2} Y{max_y-40} F20000                                                                                ; Move nozzle to remove stringing\n    _Z_CLEARANCE DISTANCE={z_clearance}                                                                             ; Lower bed\n    M400                                                                                                            ; Wait for buffer to clear\n    G92 E0                                                                                                          ; Zero the extruder\n\n    M220 S100                                                                                                       ; Set feedrate (speed percentage) back to 100%\n    M221 S100                                                                                                       ; Set flow percentage back to 100%\n\n    SET_IDLE_TIMEOUT TIMEOUT={printer.configfile.settings.idle_timeout.timeout}                                     ; Set timeout back to configured value\n    CLEAR_PAUSE                                                                                                     ; Ensure pause state is cleared if applicable\n\n    M84                                                                                                             ; Disable steppers\n    SET_TEMPERATURE_FAN_TARGET TEMPERATURE_FAN=Mainboard_fan TARGET=45                                              ; Disable steppers\n    BEEP I=2 DUR=500                                                                                                ; Alert at the end of the print (if sound is enabled)\n\n\n[gcode_macro PAUSE]\nrename_existing: BASE_PAUSE\ngcode:\n    {% set z_hop = params.Z|default(30)|int %}                                                                     ; Z hop amount\n    \n    {% if printer['pause_resume'].is_paused|int == 0 %}     \n        SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=zhop VALUE={z_hop}                                                ; Set Z hop variable for reference in resume macro\n        SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=etemp VALUE={printer['extruder'].target}                          ; Set hotend temperature variable for reference in resume macro\n        SAVE_GCODE_STATE NAME=PAUSE                                                                                ; Save current position for resume\n        BASE_PAUSE                                                                                                 ; Pause print\n        {% if (printer.gcode_move.position.z + z_hop) < printer.toolhead.axis_maximum.z %}                         ; Check that Z hop doesn't exceed Z max\n            G91                                                                                                    ; Use Relative positioning\n            G1 Z{z_hop} F600                                                                                       ; Raise Z up by Z hop amount\n        {% else %}\n            SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=zhop VALUE=0                                                  ; Set Z hop to 0 if exceeds max\n        {% endif %}\n        SAVE_GCODE_STATE NAME=PAUSEPARK2\n        G90                                                                                                        ; Absolute positioning\n        GO_TO_POOP_BUCKET                                                                                          ; Move toolhead to poop bucket\n        SAVE_GCODE_STATE NAME=PAUSEPARK                                                                            ; Save parked position in case toolhead is moved during the pause (otherwise the return zhop can error)\n        M104 S0                                                                                                    ; Turn off hotend\n        SET_IDLE_TIMEOUT TIMEOUT=43200                                                                             ; Set timeout to 12 hours\n        SET_STEPPER_ENABLE STEPPER=extruder enable=0                                                               ; Disable extruder stepper\n    {% endif %}\n\n\n[gcode_macro RESUME]\nrename_existing: BASE_RESUME\nvariable_zhop: 0\nvariable_etemp: 0\ngcode:\n\n    {% if printer['pause_resume'].is_paused|int == 1 %}\n        \n        {% if \"z\" not in printer.toolhead.homed_axes %}                                                            ; check if z position is lost\n            {action_raise_error(\"ERROR: Z-axixs lost its position (Idle-Timeout)! Resume not possible - Print should be aborted.\")}\n        {% endif %}\n        \n        SET_IDLE_TIMEOUT TIMEOUT={printer.configfile.settings.idle_timeout.timeout}                                ; Set idle timeout back to configured value\n\n        # If X/Y position lost: Give Z-clearance for homing X/Y that will be done by PRIME_NOZZLE                                                                                     \n        {% if \"x\" not in printer.toolhead.homed_axes or \"y\" not in printer.toolhead.homed_axes %}                  ; If X/Y position is lost, but z is still OK\n            G91                                                                                                    ; Relative positioning\n            G1 Z5 F600                                                                                             ; 5mm clearance for safe X/Y-Homing\n            G90                                                                                                    ; Absolute positioning\n        {% endif %}\n        \n        PRIME_NOZZLE HOTEND_TARGET_TEMP={etemp}                                                                    ; Prime nozzle with last used hotend temperature\n\n        M109 S{etemp}                                                                                              ; Wait for hotend to heat up\n\n        RESTORE_GCODE_STATE NAME=PAUSEPARK2 MOVE=1 MOVE_SPEED=150                                                  ; Return to position after Z-hop (safely above the part)       \n        RESTORE_GCODE_STATE NAME=PAUSE MOVE=1 MOVE_SPEED=10                                                        ; Restore position\n        BASE_RESUME                                                                                                ; Resume print                                                                         ; Resume print\n    {% endif %}\n\n\n\n\n[gcode_macro CANCEL_PRINT]\nrename_existing: BASE_CANCEL_PRINT\ngcode:\n\n    {% set max_z = printer.configfile.config[\"stepper_z\"][\"position_max\"]|float %}\n    {% if (printer.toolhead.position.z + 12) < max_z %}\n        {% set z_hop = 2  %}\n    {% else %}\n        {% set z_hop = 0 %}\n    {% endif %}\n\n    G91                                                                                                            ; Relative positioning\n    G1 Z{z_hop} F600                                                                                               ; Do a tiny z-hop\n    G90                                                                                                            ; Absolute positioning\n\n    G1 X{printer.toolhead.axis_maximum.x/2} Y{printer.toolhead.axis_maximum.y-40} F12000\n    CLEAR_PAUSE\n    SDCARD_RESET_FILE\n\n    PRINT_END\n    BASE_CANCEL_PRINT\n\n\n[gcode_macro _Z_CLEARANCE]\ndescription: Lower the bed to give some clearance\nvariable_default_distance: 40.0\ngcode:\n    {% set current_z_height = printer.toolhead.position.z %}\n    {% set max_z_height = printer.toolhead.axis_maximum.z %}\n    {% set distance = params.DISTANCE|default(variable_default_distance)|float %}\n    {% set target_z_height = current_z_height + distance %}\n\n    {% set min_z_param = params.MIN_Z|default(None) %}\n    {% if min_z_param is not none %}\n        {% set min_z = min_z_param|float %}\n        {% if target_z_height < min_z %}\n            {% set target_z_height = min_z %}\n        {% endif %}\n    {% endif %}\n\n    G90                                                                                                            ; Absolute positioning\n    G1 Z{ [target_z_height, max_z_height]|min }\n\n\n\n########################################\n#  Filament Macros\n########################################\n[gcode_macro UNLOAD_FILAMENT]\ndescription: Unloads filament from toolhead\ngcode:\n  {% set EXTRUDER_TEMP = params.TEMP|default(230)|int %}\n  {% set CURRENT_TEMP = printer.extruder.temperature|int %}\n   \n  GO_TO_POOP_BUCKET                                                                                                ; go to poop bucket\n\n  {% if CURRENT_TEMP < EXTRUDER_TEMP %}\n    M104 S{EXTRUDER_TEMP}                                                                                          ; heat up the hotend\n  {% endif %}\n\n  {% if CURRENT_TEMP < EXTRUDER_TEMP %}\n    M109 S{EXTRUDER_TEMP}                                                                                          ; heat up the hotend\n  {% endif %}  \n  SET_STEPPER_ENABLE STEPPER=extruder ENABLE=1                                                                     ; enable extruder stepper \n  M83                                                                                                              ; set extruder to relative mode\n  G1 E5 F150                                                                                                       ; extrude a small amount to elimate soften the filament\n  G1 E-8 F1800                                                                                                     ; quickly retract a small amount to elimate stringing\n  G4 P200                                                                                                          ; pause for a short amount of time\n  G1 E-50 F300                                                                                                     ; retract slowly the rest of the way\n  M104 S0                                                                                                          ; turn off hotend and wait for cooldown before leaving\n  LEAVE_POOP_BUCKET                                                                                                ; leave poop bucket\n  M400                                                                                                             ; wait for moves to finish\n  M118 Unload Complete!\n\n\n[gcode_macro LOAD_FILAMENT]\ndescription: Loads filament to toolhead\ngcode:\n  {% set EXTRUDER_TEMP = params.TEMP|default(230)|int %}\n  {% set CURRENT_TEMP = printer.extruder.temperature|int %}\n   \n  GO_TO_POOP_BUCKET                                                                                                ; go to poop bucket\n\n  {% if CURRENT_TEMP < EXTRUDER_TEMP %}\n    M104 S{EXTRUDER_TEMP}                                                                                          ; heat up the hotend\n  {% endif %}\n\n  {% if CURRENT_TEMP < EXTRUDER_TEMP %}\n    M109 S{EXTRUDER_TEMP}                                                                                          ; heat up the hotend\n  {% endif %}  \n  SET_STEPPER_ENABLE STEPPER=extruder ENABLE=1                                                                     ; enable extruder stepper \n  M107                                                                                                             ; turn off fan\n  M83                                                                                                              ; set extruder to relative mode\n  G1 E5 F120                                                                                                       ; feed filament\n  G1 E5 F300                                                                                                       ; feed filament\n  G1 E40 F600                                                                                                      ; feed filament\n  G1 E15 F500                                                                                                      ; feed filament\n  G1 E15 F120                                                                                                      ; feed filament\n  G4 P200                                                                                                          ; pause for a short amount of time\n  G1 E10 F90                                                                                                       ; feed filament\n  G4 P3000                                                                                                         ; wait a bit to finish oozing\n  {% if printer.pause_resume.is_paused %}\n        LEAVE_POOP_BUCKET                                                                                          ; leave poop bucket\n        M118 Filament Loaded - Resuming Print...                                                                   ; print message\n        RESUME                                                                                                     ; resume print\n  {% else %}\n        M104 S0                                                                                                    ; turn off hotend\n        M106 S255                                                                                                  ; turn on fan\n        TEMPERATURE_WAIT SENSOR=extruder MAXIMUM=80                                                                ; wait for hotend to cool\n        LEAVE_POOP_BUCKET                                                                                          ; leave poop bucket\n        M400                                                                                                       ; wait for moves to finish\n        M107                                                                                                       ; turn off fan\n        M118 Load Complete!                                                                                        ; print message\n  {% endif %}\n\n\n\n\n# Filament runout sensor enable/disable\n[gcode_macro M8029]\ngcode:\n     {% if params.D is defined %}\n       {% if (params.D|int)==1 %} \n        SET_FILAMENT_SENSOR SENSOR=filament_tangle_sensor ENABLE=1\n       {% endif %}\n       {% if (params.D|int)==0 %} \n        SET_FILAMENT_SENSOR SENSOR=filament_tangle_sensor ENABLE=0\n       {% endif %}\n     {% endif %}\n\n\n########################################\n# Fan Macros\n########################################\n# Set Fan Speed macro\n# Mainly name castings for nicer web interface names and display functionality\n[gcode_macro M106]\nrename_existing: M106.1\ngcode:\n    {% if params.P is defined %}\n      {% if params.S is defined %}\n        {% set speed = 0.003921*params.S|int %}\n        {% if (params.P|int) == 0 %}\n          M106.1 S{params.S|int}\n        {% elif (params.P|int) == 2 %}\n          SET_FAN_SPEED FAN=sidefan SPEED={speed}\n        {% elif (params.P|int) == 3 %}\n          SET_FAN_SPEED FAN=filterfan SPEED={speed}\n        {% else %}\n          SET_FAN_SPEED FAN=fan{params.P|int} SPEED={speed}\n        {% endif %}\n      {% else %}\n        {% if (params.P|int) == 0 %}\n          M106.1 S255\n        {% elif (params.P|int) == 2 %}\n          SET_FAN_SPEED FAN=sidefan SPEED=1\n        {% elif (params.P|int) == 3 %}\n          SET_FAN_SPEED FAN=filterfan SPEED=1\n        {% else %}\n          SET_FAN_SPEED FAN=fan{params.P|int} SPEED=1\n        {% endif %}\n      {% endif %}\n    {% endif %} \n\n    {% if params.T is defined %}\n      {% if (params.T|int) == -2 %}\n        {% if params.S is defined %}\n          {% set speed = 0.003921*params.S|int %}\n          SET_FAN_SPEED FAN=filterfan SPEED={speed}\n        {% else %}\n          SET_FAN_SPEED FAN=filterfan SPEED=1\n        {% endif %}\n      {% endif %}\n    {% endif %}\n\n    {% if params.P is undefined %}\n      {% if params.T is undefined %}\n        {% if params.S is defined %}\n          M106.1 S{params.S|int}\n        {% else %}\n          M106.1 S255\n        {% endif %}\n      {% endif %}\n    {% endif %}\n\n[gcode_macro M107]\nrename_existing: M107.1\ngcode:  \n    M106.1 S0\n\n\n########################################\n# Temperature Macros\n########################################\n# Wait for Hotend Temperature\n[gcode_macro M109]\nrename_existing: M109.1\ngcode:\n    #Parameters\n    {% set s = params.S|float %}\n\n    M104 {% for p in params %}{'%s%s' % (p, params[p])}{% endfor %}                                              ; Set hotend temp\n    {% if s != 0 %}\n        TEMPERATURE_WAIT SENSOR=extruder MINIMUM={s} MAXIMUM={s+1}                                               ; Wait for hotend temp (within 1 degree)\n    {% endif %}\n\n\n# PID autotune\n[gcode_macro M303]\ngcode:\n    {% if params.E is defined %}\n     {% if params.S is defined %}\n        {% if (params.E|int)==-1 %} \n         PID_CALIBRATE HEATER=heater_bed TARGET={params.S|int}\n        {% endif %}\n        {% if (params.E|int)==0 %}\n         PID_CALIBRATE HEATER=extruder TARGET={params.S|int}\n        {% endif %}\n     {% endif %}\n  {% endif %}\n\n\n# Set chamber temperature\n[gcode_macro M141]\ngcode:\n    {% if printer[\"heater_generic chamber\"] is defined %}\n        {% set chamber_target_temp = params.S|float %}\n        SET_HEATER_TEMPERATURE HEATER=chamber TARGET={([chamber_target_temp, 65]|min)}\n    {% endif %}\n\n\n# Set wait chamber temperature\n[gcode_macro M191]\ngcode:\n    {% set chamber_target_temp = params.S|float %}\n\n    {% if chamber_target_temp == 0 %}\n        M118 Chamber heater off\n    {% else %}\n        M141 S{chamber_target_temp}\n        TEMPERATURE_WAIT SENSOR=\"heater_generic chamber\" MINIMUM={([chamber_target_temp, 65]|min)-2} MAXIMUM={chamber_target_temp + 5}  \n        M118 Chamber at target temperature\n    {% endif %}\n\n\n########################################\n# Sound Macros\n########################################\n[gcode_macro BEEP]\ngcode:\n    # Parameters\n    {% set i = params.I|default(1)|int %}                                                                        ; Iterations (number of times to beep).\n    {% set dur = params.DUR|default(100)|int %}                                                                  ; Duration/wait of each beep in ms. Default 100ms.\n\n    {% if printer[\"output_pin sound\"].value|int == 1 %}\n        {% for iteration in range(i|int) %}\n            SET_PIN PIN=buzzer VALUE=1\n            G4 P{dur}\n            SET_PIN PIN=buzzer VALUE=0\n            G4 P{dur}\n        {% endfor %}\n    {% endif %}\n\n\n[gcode_macro beep_on]\ngcode:\n    SET_PIN PIN=buzzer VALUE=1\n\n\n[gcode_macro beep_off]\ngcode:\n    SET_PIN PIN=buzzer VALUE=0\n\n\n########################################\n# Z-height Macros\n########################################\n# Bed Leveling (Unified)\n[gcode_macro G29]\nvariable_k:1\ngcode:\n    {% set temp = printer[\"heater_generic chamber\"].target %}\n      M141 S0\n    {% if temp > 0 %}\n      G4 P15000\n    {% endif %}\n\n    {% if k|int==1 %}\n        BED_MESH_CLEAR                                                                                           ; Clear levelling data\n        BED_MESH_CALIBRATE ADAPTIVE=1 ADAPTIVE_MARGIN=5                                                          ; Start adaptive meshing\n    {% endif %}   \n    M141 S{temp} \n\n\n# Babystep\n[gcode_macro M290]\ngcode:\n   SET_GCODE_OFFSET Z_ADJUST={params.Z}\n\n\n########################################\n# Tuning Macros\n########################################\n[gcode_macro SHAPER_CALIBRATE]\nrename_existing: RESHAPER_CALIBRATE\ngcode:\n    RESHAPER_CALIBRATE FREQ_START=30 FREQ_END=130\n\n\n# Linear Advance Factor\n[gcode_macro M900]\ngcode:\n    {% if params.K is defined %} \n          SET_PRESSURE_ADVANCE ADVANCE={params.K}\n    {% endif %}  \n    {% if params.T is defined %}    \n       SET_PRESSURE_ADVANCE SMOOTH_TIME={params.T}\n    {% endif %} \n\n\n# Set Starting Acceleration\n[gcode_macro M204]\nrename_existing: M99204\ngcode:\n    {% if params.S is defined %}\n        {% set s = params.S|float %}\n    {% endif %}\n    {% if params.P is defined %}\n    {% if params.T is defined %}\n        {% set s = [params.P|float ,params.T|float] | min %}\n    {% endif %}\n    {% endif %}\n\n    SET_VELOCITY_LIMIT ACCEL={s}\n    SET_VELOCITY_LIMIT ACCEL_TO_DECEL={s/2}\n\n\n# Bed leveling\n# For more information, see https://www.klipper3d.org/Manual_Level.html#adjusting-bed-leveling-screws-using-the-bed-probe\n[gcode_macro LEVEL_BED]\ndescription: \"Measure bed and calculate screw adjustments for manual bed leveling\"\ngcode:\n    G28                                                                                                         ; Home all\n    SCREWS_TILT_CALCULATE                                                                                       ; Perform measurements and output screw adjustments\n\n\n# Automatic rough Bed Leveling by ramming the bed to the bottom\n[gcode_macro AUTO_LEVEL_BED]\ngcode:\n    {% set Z_max = printer.toolhead.axis_maximum.z %}\n    G28    \n    G1 Z{Z_max-30} F600\n    SET_TMC_CURRENT STEPPER=stepper_z CURRENT={printer.configfile.settings['tmc2209 stepper_z'].run_current * 0.5 }\n    SET_TMC_CURRENT STEPPER=stepper_z1 CURRENT={printer.configfile.settings['tmc2209 stepper_z1'].run_current * 0.5 }\n    G1 Z{Z_max} F600\n    SET_KINEMATIC_POSITION Z=0\n    G1 Z10 F600\n    G1 Z0 F600\n    G1 Z15 F600\n    SET_TMC_CURRENT STEPPER=stepper_z CURRENT={printer.configfile.settings['tmc2209 stepper_z'].run_current}\n    SET_TMC_CURRENT STEPPER=stepper_z1 CURRENT={printer.configfile.settings['tmc2209 stepper_z1'].run_current}\n    G28\n\n\n\n# Probe Calibration\n# For more information, see https://www.klipper3d.org/Probe_Calibrate.html\n[gcode_macro CALIBRATE_Z_OFFSET]\ndescription: \"Calibrate the Z offset using the probe\"\ngcode:\n    {% set max_x = printer.configfile.config[\"stepper_x\"][\"position_max\"]|float %}\n    {% set max_y = printer.configfile.config[\"stepper_y\"][\"position_max\"]|float %}\n\n    G28                                                                                                         ; Home all\n    G0 Z10                                                                                                      ; Increase z clearance\n    G0 X{max_x/2} Y{max_y-40} F6000                                                                             ; Move to bed center \n    PROBE_CALIBRATE                                                                                             ; Perform a probe calibration\n\n\n# Nozzle PID tuning\n# For more information, see https://www.klipper3d.org/Config_checks.html#calibrate-pid-settings\n[gcode_macro NOZZLE_PID_TUNE]\ndescription: \"Perform PID tuning for the nozzle heater\"\ngcode:\n    PID_CALIBRATE HEATER=extruder TARGET=220                                                                    ; PID tune the nozzle\n\n\n# Bed PID tuning\n# For more information, see https://www.klipper3d.org/Config_checks.html#calibrate-pid-settings\n[gcode_macro BED_PID_TUNE]\ndescription: \"Perform PID tuning for the bed heater\"\ngcode:\n    PID_CALIBRATE HEATER=heater_bed TARGET=80                                                                   ; PID tune the bed\n\n\n########################################\n# Macros for display functionallity\n########################################\n[gcode_macro INPUT_SHAPING_CALIBRATE]\ndescription: \"Perform Input Shaping calibration and save the results to printer.cfg\"\ngcode:\n    SHAPER_CALIBRATE                                                                                            ; Step 1: Perform the Input Shaping calibration\n    PAUSE                                                                                                       ; Step 2: Pause to allow the calibration to complete\n    SAVE_CONFIG                                                                                                 ; Step 3: Save the configuration to printer.cfg\n    RESTART                                                                                                     ; Step 4: Restart the firmware to apply the new settings\n\n"
  },
  {
    "path": "config_section/Q1_Pro/printer.cfg",
    "content": "# Q1 Pro config created by Phil1988(github)/coco.33(discord) on 11.05.2025\n# For more information check out my wiki: https://github.com/Phil1988/FreeDi/wiki\n\n\n#####################################################################\n# Kinematics\n#####################################################################\n[printer]\nkinematics:corexy\nmax_velocity: 600\nmax_accel: 20000\nmax_z_velocity: 10\nmax_z_accel: 500\nsquare_corner_velocity: 8\n\n\n#####################################################################\n# Motherboard and periphery\n#####################################################################\n[temperature_sensor Mainboard_RK3328]\nsensor_type: temperature_host\nmin_temp: 10\nmax_temp: 100\n\n[mcu]\nserial: /dev/ttyS0\nrestart_method: command\nbaud: 500000\n\n[temperature_sensor Mainboard_STM32F402]\nsensor_type: temperature_mcu\nsensor_mcu: mcu\n\n[mcu Toolhead]\nserial: /dev/ttyS2\nrestart_method: command\nbaud: 500000\n\n[temperature_sensor Toolhead_RP2040]\nsensor_type: temperature_mcu\nsensor_mcu: Toolhead\nmin_temp: 0\nmax_temp: 100\n\n\n#####################################################################\n# Features\n#####################################################################\n# For saving GCODE files\n[virtual_sdcard]\npath: ~/printer_data/gcodes\non_error_gcode: CANCEL_PRINT\n\n# For enabling pause/resume\n[pause_resume]\n\n# Activating exclude objects feature\n[display_status]\n[exclude_object]\n\n\n# Expanding idle timeout\n[idle_timeout]\ntimeout: 5400   ; 90min timeout\n\n# Activating GCODE arc feature\n[gcode_arcs]\nresolution: 1.0\n\n# Allowing free move (can be dangerous!)\n[force_move]\nenable_force_move: True\n\n# Activating responses\n[respond]\ndefault_type: echo\n\n#####################################################################\n# FreeDi\n#####################################################################\n[include freedi.cfg] \n\n\n#####################################################################\n# Macros\n#####################################################################\n[include macros.cfg]\n\n\n#####################################################################\n# Input shaping\n#####################################################################\n[resonance_tester]\naccel_chip: adxl345\nprobe_points:\n    120, 120, 10\naccel_per_hz: 75\nsweeping_period: 0\nmax_smoothing: 0.5\n    \n[adxl345]\ncs_pin: Toolhead:gpio13\nspi_software_sclk_pin: Toolhead:gpio14\nspi_software_mosi_pin: Toolhead:gpio15\nspi_software_miso_pin: Toolhead:gpio12\naxes_map: -x, z, -y\n\n\n\n[input_shaper]\nshaper_type_x: mzv\nshaper_freq_x: 53.6\nshaper_type_y: mzv\nshaper_freq_y: 50.8\n\n\n\n#####################################################################\n# Hotend\n#####################################################################\n[extruder]\nstep_pin: Toolhead:gpio5\ndir_pin: Toolhead:gpio4\nenable_pin: !Toolhead:gpio10\nrotation_distance: 53.7\ngear_ratio: 1517:170\nmicrosteps: 16\nfull_steps_per_rotation: 200\nnozzle_diameter: 0.400\nfilament_diameter: 1.75\nmin_temp: 0\nmax_temp: 360\nmin_extrude_temp: 170\nsmooth_time: 0.000001\nstep_pulse_duration:0.000002\n\nheater_pin: Toolhead:gpio24\nsensor_type:MAX6675\nsensor_pin: Toolhead:gpio17\nmax_power: 1.0\ncontrol: pid  \npid_Kp: 24.737\npid_Ki: 10.994\npid_Kd: 13.915\n\nspi_speed: 100000\nspi_software_sclk_pin: Toolhead:gpio18\nspi_software_mosi_pin: Toolhead:gpio19\nspi_software_miso_pin: Toolhead:gpio16\n\npressure_advance: 0.032\npressure_advance_smooth_time: 0.03\nmax_extrude_cross_section:500\ninstantaneous_corner_velocity: 10.000\nmax_extrude_only_distance: 500.0\nmax_extrude_only_velocity: 5000\nmax_extrude_only_accel: 2000\n\n[verify_heater extruder]\nmax_error: 120\ncheck_gain_time: 20\nhysteresis: 5\nheating_gain: 1\n\n\n#####################################################################\n# Heated bed\n#####################################################################\n[heater_bed]\nheater_pin: PB10\nsensor_type: NTC 100K MGB18-104F39050L32\nsensor_pin: PA0\nmax_power: 1.0\ncontrol: pid\npid_kp: 64.431\npid_ki: 2.845\npid_kd: 364.839\nmin_temp: -50\nmax_temp: 125\npwm_cycle_time: 0.02 # for 50Hz line power \n#pwm_cycle_time: 0.016 # for 60Hz line power\n\n[verify_heater heater_bed]\nmax_error: 200\ncheck_gain_time: 360\nhysteresis: 5\nheating_gain: 1\n\n\n#####################################################################\n# Bed mesh\n#####################################################################\n[bed_mesh]\nspeed: 150               \nhorizontal_move_z: 3.5   \nmesh_min: 20,15\nmesh_max: 230,230    \nprobe_count: 8,8   \nalgorithm:bicubic\nbicubic_tension:0.2\nmesh_pps: 4, 4\n\n\n#####################################################################\n# Probe\n#####################################################################\n#!# Pay attention to this section and compare it with your stock backup config\n[probe]\npin: !Toolhead:gpio21\nx_offset: 17.6\ny_offset: 4.4\nz_offset: 1.0             #!# change this to 0 if you get a \"Probe triggered prior to movement\" - Error\nspeed: 5\nsamples: 2\nsamples_result: average\nsample_retract_dist: 0.7\nsamples_tolerance: 0.08\nsamples_tolerance_retries: 3\n\n\n# Check this for documentation https://github.com/frap129/qidi_auto_z_offset\n# Add AUTO_Z_LOAD_OFFSET to your PRINT_START macro to load the value every time you start a print. \n# If you make adujstments to the offset by micro-stepping durring a print, you can save that with AUTO_Z_SAVE_GCODE_OFFSET and SAVE_CONFIG\n[auto_z_offset]\npin: PC1\n# Adjust this z_offset value for a good first layer: \n# decrease if lines are squished (eg -0.2 -> -0.25)\n# increase if lines are thin/not sticking (-0.2 -> -0.15)\nz_offset: -0.07\ncalibrated_z_offset: -1.00\nspeed: 13\nprobe_accel: 50\nsamples: 5\nsamples_result: median\nsamples_tolerance: 0.013\nsamples_tolerance_retries: 5\noffset_samples: 3\nprepare_gcode:\n   G90\n   G0 Z3\n   G91\n   SET_PIN PIN=bed_sensor VALUE=0\n   M204 S10000\n   {% set i = 6 %}\n   {% for iteration in range(i|int) %}\n       G1 Z5 F1200\n       G1 Z-5 F1200\n   {% endfor %}\n   G1 Z3\n   G90\n   SET_PIN PIN=bed_sensor VALUE=1\n\n[output_pin bed_sensor]\npin: !PA14\npwm: false\nshutdown_value:0\nvalue:0\n\n#####################################################################\n# Heated chamber\n#####################################################################\n[heater_generic chamber]\nheater_pin: PC8\nmax_power:1.0\nsensor_type: NTC 100K MGB18-104F39050L32\nsensor_pin: PA1\ncontrol: pid\npid_Kp: 63.418\npid_Ki: 1.342\npid_Kd: 749.125\nmin_temp: -100\nmax_temp: 62\n\n[verify_heater chamber]\nmax_error: 400\ncheck_gain_time: 600\nhysteresis: 5\nheating_gain: 1\n\n\n########################################\n# Filament sensors\n########################################\n[filament_switch_sensor filament_tangle_sensor]\nswitch_pin: PC3\npause_on_runout: True\nrunout_gcode:\n            M118 Filament tangled!\nevent_delay: 3.0\npause_delay: 0.5\n\n[hall_filament_width_sensor]\nadc1: Toolhead:gpio27\nadc2: Toolhead:gpio28\ncal_dia1: 1.50\ncal_dia2: 2.0\nraw_dia1: 14206\nraw_dia2: 15278\ndefault_nominal_filament_diameter: 1.75\nmax_difference: 0.00\nmeasurement_delay: 50\nenable: True\nenable_flow_compensation: False\nmeasurement_interval: 3\nlogging: False\nmin_diameter: 1.00\nuse_current_dia_while_delay: False\npause_on_runout: True\nrunout_gcode:\n            M118 Filament run out\nevent_delay: 3.0\npause_delay: 0.5\n\n\n#####################################################################\n# Fans\n#####################################################################\n## Part cooling fan \n# [fan_generic partfan]\n# pin: Toolhead:gpio2\n# max_power: 1.0\n# cycle_time: 0.0100\n# hardware_pwm: false\n# kick_start_time: 0.200\n# off_below: 0.08\n# shutdown_speed: 0\n[fan]\npin: Toolhead:gpio2\nmax_power: 1.0\ncycle_time: 0.0100\nhardware_pwm: false\nkick_start_time: 0.200\noff_below: 0.08\nshutdown_speed: 0.0\n\n## Big side radial turbo fan\n[fan_generic sidefan]\npin: PA8\nmax_power: 1.0\ncycle_time: 0.0100\nhardware_pwm: false\nkick_start_time: 0.250\noff_below: 0.3\nshutdown_speed: 0\n\n## Activated charcoal blowing fan\n[fan_generic filterfan]\npin: PC9\nmax_power: 1.0\ncycle_time: 0.0100\nhardware_pwm: false\nkick_start_time: 0.200\noff_below: 0.3\nshutdown_speed: 0\n\n## Chamber heater fan\n[heater_fan chamber_heater_fan]\npin: PA4\nmax_power: 1.0\nshutdown_speed: 0\nkick_start_time: 0.5\nheater: chamber\nfan_speed: 1.0\noff_below: 0\nheater_temp: 35\n\n## Cold end and toolhead housing fans\n[heater_fan hotend_fan]\npin: Toolhead:gpio25\nmax_power: 1.0\nshutdown_speed: 1.0\nkick_start_time: 0.5\nheater: extruder\nheater_temp: 50.0\nfan_speed: 1.0\noff_below: 0\n\n#!# Delete the next section if your stock backup config doesnt have it\n# Toolhead cooling fan\n[heater_fan hotend_fan2]\npin: Toolhead:gpio11\nmax_power: 1.0\nshutdown_speed: 1.0\nkick_start_time: 0.5\nheater: extruder\nheater_temp: 50.0\nfan_speed: 1.0\noff_below: 0\n\n#!# Delete the next section if your stock backup config doesnt have it\n## Controllable Mainboard cooling fan\n[temperature_fan Mainboard_fan]\nsensor_type: temperature_host \npin: PC4        \nmax_power: 1.0  \ncycle_time: 0.01\nsensor_type: temperature_combined\nsensor_list: temperature_sensor Mainboard_RK3328, temperature_sensor Mainboard_STM32F402\ncombination_method: max                                           # use the maximum reading of the sensors\nmaximum_deviation: 999.9                                          # we don't care about the difference in temperature\nshutdown_speed: 0.0\nkick_start_time: 0.4\noff_below: 0.19\nmin_temp: 0\nmax_temp: 85.0  \ntarget_temp: 42.0\nmin_speed: 0\nmax_speed: 1.0\ncontrol: pid\npid_deriv_time: 2.0\npid_Kp: 2.0\npid_Ki: 5.0\npid_Kd: 0.5\n\n\n#####################################################################\n# Light\n#####################################################################\n## caselight LEDs\n[output_pin caselight]\npin: PC7\npwm: true\ncycle_time: 0.0100\nshutdown_value:0\nvalue:1\n\n\n#####################################################################\n# Buzzer\n#####################################################################\n## Buzzer\n[output_pin buzzer]\npin: PA2\npwm: false\nshutdown_value:0\nvalue:0\n\n[output_pin sound]\npin: PA13\nvalue:0\n\n\n#####################################################################\n# Power outage shutdown\n#####################################################################\n[output_pin pwc]\npin: PA3\npwm: False\nvalue: 1\nshutdown_value: 1\n\n\n#####################################################################\n# Drives\n#####################################################################\n[stepper_x]\nstep_pin: PB4\ndir_pin: !PB3\nenable_pin: !PB5\nmicrosteps: 32\nrotation_distance: 39.88\nfull_steps_per_rotation: 200\nendstop_pin: tmc2240_stepper_x:virtual_endstop\nposition_min: -5.5\nposition_endstop: -5.5\nposition_max: 245\nhoming_speed: 50\nhoming_retract_dist:0\nhoming_positive_dir: False\nstep_pulse_duration:0.0000001\n\n[stepper_y]\nstep_pin: PC14\ndir_pin: !PC13\nenable_pin: !PC15\nmicrosteps: 32\nrotation_distance: 39.88\nfull_steps_per_rotation:200 \nendstop_pin: tmc2240_stepper_y:virtual_endstop\nposition_min: -4.5\nposition_endstop: -4.5\nposition_max: 258\nhoming_speed: 50\nhoming_retract_dist:0\nhoming_positive_dir: False\nstep_pulse_duration:0.0000001\n\n[stepper_z]\nstep_pin: PC10\ndir_pin: PA15\nenable_pin: !PC11\nmicrosteps: 16\nrotation_distance: 4\nfull_steps_per_rotation: 200\nendstop_pin: probe:z_virtual_endstop\nposition_max: 248\nposition_min: -4\nhoming_speed: 8\nhoming_retract_dist: 8.0\nsecond_homing_speed: 5\nhoming_positive_dir: False\nstep_pulse_duration: 0.0000001\n\n[stepper_z1]\nstep_pin: PB1\ndir_pin: PB6\nenable_pin: !PB0\nmicrosteps: 16\nrotation_distance: 4\nfull_steps_per_rotation: 200\nstep_pulse_duration: 0.0000001\n\n\n#####################################################################\n# Steppers configuration\n#####################################################################\n[tmc2209 extruder]\nuart_pin: Toolhead:gpio6\ninterpolate: False\nrun_current: 0.714             #!# Pay attention to this value and compare it with your stock backup config\nstealthchop_threshold: 0\nsense_resistor: 0.075\n\n[tmc2240 stepper_x]\ncs_pin: PD2\nspi_software_sclk_pin: PA5\nspi_software_mosi_pin: PA7\nspi_software_miso_pin: PA6\nspi_speed: 200000\nrun_current: 1.07               #!# Pay attention to this value and compare it with your stock backup config\ninterpolate: True\nstealthchop_threshold: 0\ndiag0_pin: !PB8\ndriver_SGT: 1\nrref: 12000\n\n[tmc2240 stepper_y]\ncs_pin: PB9\nspi_software_sclk_pin: PA5\nspi_software_mosi_pin: PA7\nspi_software_miso_pin: PA6\nspi_speed: 200000\nrun_current: 1.07              #!# Pay attention to this value and compare it with your stock backup config\ninterpolate: True\nstealthchop_threshold: 0\ndiag0_pin: !PC0\ndriver_SGT: 1\nrref: 12000\n\n[tmc2209 stepper_z]\nuart_pin: PC5\nrun_current: 0.6               #!# Pay attention to this value and compare it with your stock backup config\ninterpolate: False\nstealthchop_threshold: 9999999999\n\n[tmc2209 stepper_z1]\nuart_pin: PB7\nrun_current: 0.6               #!# Pay attention to this value and compare it with your stock backup config\ninterpolate: False\nstealthchop_threshold: 9999999999\n\n#####################################################################\n# Bed tilt adjust\n#####################################################################\n[z_tilt]\nz_positions:\n    -59,125\n    307.5,125\n\npoints:\n    0,125\n    215,125\n\nspeed: 150\nhorizontal_move_z: 5\nretries: 2\nretry_tolerance: 0.05\n\n#####################################################################\n# Screws tilt adjust\n#####################################################################\n[screws_tilt_adjust] \nhorizontal_move_z: 5\nscrew_thread: CW-M4\nspeed: 300\n\nscrew1:10,10\nscrew1_name: Front left\nscrew2: 220,10\nscrew2_name: Front right\nscrew3: 125,230\nscrew3_name: Back center\n"
  },
  {
    "path": "config_section/X-Max3/macros.cfg",
    "content": "#####################################################################\n# Advanced CHAMBER_TEMP_CONTROLLER\n#####################################################################\n\n[gcode_macro SET_PRINT_STATS_INFO]\nrename_existing: BASE_SET_PRINT_STATS_INFO_BASE\ngcode:\n    #TIMELAPSE_TAKE_FRAME\n    BASE_SET_PRINT_STATS_INFO_BASE {rawparams}\n    CHAMBER_TEMP_CONTROLLER\n\n# Safety macro that gets frequently called by SET_PRINT_STATS_INFO to prevent too high chamber temperatures\n[gcode_macro CHAMBER_TEMP_CONTROLLER]\ngcode:\n    {% set chamber_target_temp = printer['heater_generic chamber'].target %}\n    {% set chamber_temp = printer['heater_generic chamber'].temperature %}\n    {% if chamber_temp > printer.configfile.settings['heater_generic chamber'].max_temp %}\n        M106 P3 S255\n    {% else %}\n        {% if chamber_target_temp > 0 %}\n            # Allow for 3C of \"grace\" before we start ramping the exhaust fan speed\n            # This prevents the macro from fighting with the chamber heater PID algorithm\n            {% set difference = chamber_temp - (chamber_target_temp + 3) %}\n            {% if difference > 0 %}\n                {% set filterfan_speed = ([(difference * 50), 255] | min) | int %}\n                M106 P3 S{filterfan_speed}\n            {% else %}\n                M106 P3 S0\n            {% endif %}\n        {% endif %}\n    {% endif %}\n    \n    \n#####################################################################\n# Homing modification\n#####################################################################\n[gcode_macro G28]\nrename_existing: G28.1\ngcode:\n    {% set reduced_current_x = 0.6 %}\n    {% set reduced_current_y = 0.7 %}\n    {% set home_all = ('X' in rawparams.upper() and 'Y' in rawparams.upper() and 'Z' in rawparams.upper()) or \n                      ('X' not in rawparams.upper() and 'Y' not in rawparams.upper() and 'Z' not in rawparams.upper()) %}\n    {% set home_current_x = printer.configfile.settings['tmc2209 stepper_x'].run_current * reduced_current_x %}\n    {% set home_current_y = printer.configfile.settings['tmc2209 stepper_y'].run_current * reduced_current_y %}\n\n    {% set init_XY_move = 30 %}\n    #{% set y_init_move = 5 %}\n    {% set z_clearance = 2 %}\n\n    {% set home_all_final_position_x = printer.toolhead.axis_maximum.x / 2 %}\n    {% set home_all_final_position_y = printer.toolhead.axis_maximum.y - 40 %}\n    {% set home_all_final_position_z = 10 %}\n\n    # If homing should at least move X or Y axis\n    {% if home_all or 'X' in rawparams.upper() or 'Y' in rawparams.upper() %}     \n        # Check if Z is homed\n        {% if 'z' in printer.toolhead.homed_axes %}\n            {% set Z_axis_was_homed = true %}                                                                       ; Set Z_axis_was_homed to true if Z is already homed\n            G91                                                                                                     ; Use relative positioning\n            G1 Z2 F600                                                                                              ; Move bed down\n            G90                                                                                                     ; Use absolute positioning\n        {% else %}\n            {% set Z_axis_was_homed = false %}                                                                      ; Set Z_axis_was_homed to false if Z is not homed\n            FORCE_MOVE STEPPER=stepper_z DISTANCE={z_clearance} VELOCITY=10                                         ; Move bed down\n        {% endif %}\n    {% endif %}\n\n    {% if home_all or 'X' in rawparams.upper() or 'Y' in rawparams.upper() %} \n        G91                                                                                                         ; Use relative positioning\n        FORCE_MOVE STEPPER=stepper_x DISTANCE={init_XY_move} VELOCITY=40                                            ; Move X a little before homing\n        SET_KINEMATIC_POSITION X={printer.toolhead.position.x + (init_XY_move/2)}                                   ; Compensate the FORCE_MOVE position \n        SET_KINEMATIC_POSITION Y={printer.toolhead.position.y + (init_XY_move/2)}                                   ; Compensate the FORCE_MOVE position \n        G90                                                                                                         ; Use absolute positioning\n    {% endif %}\n\n    # Home Y\n    {% if home_all or 'Y' in rawparams.upper() %}\n        SET_TMC_CURRENT STEPPER=stepper_x CURRENT={home_current_y}                                                  ; Lower motor current\n        SET_TMC_CURRENT STEPPER=stepper_y CURRENT={home_current_y}                                                  ; Lower motor current\n        G28.1 Y                                                                                                     ; Home Y\n        SET_TMC_CURRENT STEPPER=stepper_x CURRENT={printer.configfile.settings['tmc2209 stepper_x'].run_current}    ; Set motor current to the previous value\n        SET_TMC_CURRENT STEPPER=stepper_y CURRENT={printer.configfile.settings['tmc2209 stepper_y'].run_current}    ; Set motor current to the previous value\n        G1 Y10 F1200                                                                                                ; Move Y-axis slightly\n    {% endif %}\n    \n    # Home X\n    {% if home_all or 'X' in rawparams.upper() %}        \n        SET_TMC_CURRENT STEPPER=stepper_x CURRENT={home_current_x}                                                  ; Lower motor current\n        SET_TMC_CURRENT STEPPER=stepper_y CURRENT={home_current_x}                                                  ; Lower motor current\n        G28.1 X                                                                                                     ; Home X\n        SET_TMC_CURRENT STEPPER=stepper_x CURRENT={printer.configfile.settings['tmc2209 stepper_x'].run_current}    ; Set motor current to the previous value\n        SET_TMC_CURRENT STEPPER=stepper_y CURRENT={printer.configfile.settings['tmc2209 stepper_y'].run_current}    ; Set motor current to the previous value\n        G1 X10 F1200                                                                                                ; Move X-axis slightly\n    {% endif %}\n\n    # Raise the bed again if only X or only Y axes were homed\n    {% if not (home_all or 'Z' in rawparams.upper()) %}\n        {% if Z_axis_was_homed %}\n            G91                                                                                                     ; Use relative positioning\n            G1 Z-2 F600                                                                                             ; Raise the bed back again\n            G90                                                                                                     ; Use absolute positioning\n        {% else %}\n            FORCE_MOVE STEPPER=stepper_z DISTANCE=-{z_clearance} VELOCITY=10                                        ; Raise the bed back again\n        {% endif %}\n    {% endif %}\n\n    # Home Z\n    {% if home_all or 'Z' in rawparams.upper() %}\n        G28.1 Z                                                                                                     ; Home Z\n        G90                                                                                                         ; Set absolute positioning\n        G1 Z{home_all_final_position_z}                                                                             ; Move bed down\n    {% endif %}\n\n    # Move to the final position if all axes were homed\n    {% if home_all %}\n        G90                                                                                                         ; Set absolute positioning\n        G1 X{home_all_final_position_x} Y{home_all_final_position_y} Z{home_all_final_position_z} F7800             ; Move to the rear center\n    {% endif %}\n\n\n# Unconditional stop\n[gcode_macro M0]\ngcode:\n    PAUSE\n\n\n# Pause SD print\n[gcode_macro M25]\nrename_existing: M9925\ngcode:\n    PAUSE\n\n\n########################################\n# Basic Macros\n########################################\n# Flag macro to use STATIC_MESH usage instead of KAMP (needed make this function work from printjob selection on the LCD)\n[gcode_macro NEXT_PRINT_STATIC_MESH]\ndescription: Forces the NEXT print to use 'STATIC_MESH' instead of KAMP.\ngcode:\n    {% if \"STATIC_MESH\" in printer.bed_mesh.profiles %}\n        SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=force_static_mesh VALUE=True\n        {action_respond_info(\"The NEXT print will use 'STATIC_MESH'.\")}\n        M118 The NEXT print will use the STATIC_MESH.\n    {% else %}\n        {action_respond_info(\"WARNING: No mesh named 'STATIC_MESH' found. Please save one first (BED_MESH_PROFILE SAVE=STATIC_MESH).\")}\n        M118 WARNING: No mesh named STATIC_MESH found. Please save one first (BED_MESH_PROFILE SAVE=STATIC_MESH).\n    {% endif %}\n\n# PRINT_START Macro for use in Slicer start G-code\n[gcode_macro PRINT_START]\n# Use PRINT_START for the slicer starting script\ndescription: Start printing\nvariable_force_static_mesh: False                                                                                 ; Set to True to force a static mesh instead of KAMP\ngcode:\n    {% set bed_target_temp = params.BED|default(0)|int %}\n    {% set hotend_target_temp = params.HOTEND|default(0)|int %}\n    {% set chamber_target_temp = params.CHAMBER|default(0)|int %}\n\n    {% set in_advanced_mode = (bed_target_temp > 0) or (hotend_target_temp > 0) or (chamber_target_temp > 0) %}\n\n    CLEAR_PAUSE                                                                                                     ; Clear existing pause states\n    BED_MESH_CLEAR                                                                                                  ; Clear previous adaptive mesh\n    SET_TEMPERATURE_FAN_TARGET TEMPERATURE_FAN=Mainboard_fan TARGET=1                                               ; Decrease the mainboard target temp to fully turn the fan on\n\n    {% set KAMP_deactivated = printer[\"gcode_macro PRINT_START\"].force_static_mesh %}                               ; Check if KAMP is deactivated for this print\n    SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=force_static_mesh VALUE=False                                     ; Auto-reset the variable immediately for the next print after this one \n\n    {% if in_advanced_mode %}\n        {% set bed_center_x = printer.configfile.config[\"stepper_x\"][\"position_max\"]|float / 2 %}\n        {% set bed_center_y = printer.configfile.config[\"stepper_y\"][\"position_max\"]|float / 2 %}\n\n        {% set start_position_x = printer.toolhead.axis_maximum.x / 2 %}\n        {% set start_position_y = printer.toolhead.axis_maximum.y - 40 %}\n        {% set start_position_z = 10 %}\n\n        M140 S{bed_target_temp}                                                                                      ; Set bed temperature\n        M141 S{chamber_target_temp}                                                                                  ; Set chamber temperature\n        G28                                                                                                          ; Home all axes\n\n        {% if chamber_target_temp > 0 %}                                                                             ; Accelerate chamber heating by using the bed as additional heater    \n            G0 X{bed_center_x} Y{bed_center_y} Z3 F780                                                               ; Move print bed to perfect postion to help chamber heating\n            M106 P2 S185                                                                                             ; Turn sidefan on to use bed heat and mix air\n            M106 P0 S128                                                                                             ; Turn part cooling fan on to help air mixing\n            TEMPERATURE_WAIT SENSOR=\"heater_generic chamber\" MINIMUM={chamber_target_temp - 5}                       ; Wait for chamber to heat up\n            M106 P2 S0                                                                                               ; Turn off sidefan\n            M106 P0 S0                                                                                               ; Turn off part cooling fan                                                                      \n        {% endif %}\n\n        M191 S{chamber_target_temp}                                                                                  ; Set and wait for chamber temperature\n        M190 S{bed_target_temp}                                                                                      ; Set and wait for bed temperature  \n        G90                                                                                                          ; Set absolute positioning\n        G1 X{start_position_x} Y{start_position_y} Z{start_position_z} F7800                                        ; Move to start position\n        G28 Z                                                                                                        ; Home Z again for to compensate bed expansion     \n\n\n        {% if KAMP_deactivated %}\n            {% if \"STATIC_MESH\" in printer.bed_mesh.profiles %}                                                          ; Check if the spicific STATIC_MESH exists\n                M118  Loading 'STATIC_MESH' instead of KAMP.\n                BED_MESH_PROFILE LOAD=STATIC_MESH\n            {% else %}                                                                                                   ; Fallback to KAMP if STATIC_MESH not found\n                M118 ERROR: 'STATIC_MESH' not found! Using fallback: KAMP Adaptive Mesh.\n                BED_MESH_CLEAR                                                                                           ; Clear previous adaptive mesh\n                BED_MESH_CALIBRATE PROFILE=adaptive ADAPTIVE=1                                                           ; Start adaptive meshing\n            {% endif %}\n        {% else %}                                                                                                       ; Standard operation\n            {% if printer.toolhead.homed_axes|length < 3 %}\n                G28\n            {% endif %}\n            BED_MESH_CLEAR                                                                                               ; Clear previous adaptive mesh\n            BED_MESH_CALIBRATE PROFILE=adaptive ADAPTIVE=1                                                               ; Start adaptive meshing\n        {% endif %}\n\n       M109 S{hotend_target_temp}                                                                                  ; Set and wait for hotend temperature \n    {% endif %}\n\n\n[gcode_macro PRINT_END]\ngcode:\n    {% set max_x = printer.configfile.config[\"stepper_x\"][\"position_max\"]|float %}\n    {% set max_y = printer.configfile.config[\"stepper_y\"][\"position_max\"]|float %}\n    {% set max_z = printer.configfile.config[\"stepper_z\"][\"position_max\"]|float %}\n        {% set current_extruder_temp = printer.extruder.temperature|float %}\n    {% set min_extrusion_temp = printer.configfile.config[\"extruder\"][\"min_extrude_temp\"]|float %}\n    {% set z_clearance = 50 %}\n    {% set z_hop = 2  %}\n\n    {% if (printer.toolhead.position.z + z_clearance) < max_z %}\n        {% set z_hop = 2  %}\n    {% else %}\n        {% set z_hop = 0 %}\n    {% endif %}\n\n    M106 P0 S0                                                                                                      ; Turn off part cooling fan\n    M106 P2 S0                                                                                                      ; Turn off side fan\n    M106 P3 S0                                                                                                      ; Turn off activated charcoal fan\n\n    M104 S0                                                                                                         ; Turn off hotend\n    M140 S0                                                                                                         ; Turn off heated bed\n    M141 S0                                                                                                         ; Turn off heated chamber\n\n    G91                                                                                                             ; Relative positioning\n    {% if current_extruder_temp >= min_extrusion_temp + 5 %}                                                        ; Check if the hotend is hot enough to perform a retraction (with a small gap)  \n        G0 E-4.0 F300                                                                                               ; Retract filament\n    {% endif %}\n    G0 Z{z_hop} F3600                                                                                               ; Move bed down a bit\n    G90                                                                                                             ; Absolute positioning\n    G0 X{max_x/2} Y{max_y-40} F20000                                                                                ; Move nozzle to remove stringing\n    _Z_CLEARANCE DISTANCE={z_clearance}                                                                             ; Lower bed\n    M400                                                                                                            ; Wait for buffer to clear\n    G92 E0                                                                                                          ; Zero the extruder\n\n    M220 S100                                                                                                       ; Set feedrate (speed percentage) back to 100%\n    M221 S100                                                                                                       ; Set flow percentage back to 100%\n\n    SET_IDLE_TIMEOUT TIMEOUT={printer.configfile.settings.idle_timeout.timeout}                                     ; Set timeout back to configured value\n    CLEAR_PAUSE                                                                                                     ; Ensure pause state is cleared if applicable\n\n    M84                                                                                                             ; Disable steppers\n    SET_TEMPERATURE_FAN_TARGET TEMPERATURE_FAN=Mainboard_fan TARGET=45                                              ; Reset the mainboard fan temp\n    BEEP I=2 DUR=500                                                                                                ; Alert at the end of the print (if sound is enabled)\n\n\n[gcode_macro PAUSE]\nrename_existing: BASE_PAUSE\ngcode:\n    {% set z_hop = params.Z|default(30)|int %}                                                                     ; Z hop amount\n    \n    {% if printer['pause_resume'].is_paused|int == 0 %}     \n        SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=zhop VALUE={z_hop}                                                ; Set Z hop variable for reference in resume macro\n        SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=etemp VALUE={printer['extruder'].target}                          ; Set hotend temperature variable for reference in resume macro\n        SAVE_GCODE_STATE NAME=PAUSE                                                                                ; Save current position for resume\n        BASE_PAUSE                                                                                                 ; Pause print\n        {% if (printer.gcode_move.position.z + z_hop) < printer.toolhead.axis_maximum.z %}                         ; Check that Z hop doesn't exceed Z max\n            G91                                                                                                    ; Use Relative positioning\n            G1 Z{z_hop} F600                                                                                       ; Raise Z up by Z hop amount\n        {% else %}\n            SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=zhop VALUE=0                                                  ; Set Z hop to 0 if exceeds max\n        {% endif %}\n        SAVE_GCODE_STATE NAME=PAUSEPARK2\n        G90                                                                                                        ; Absolute positioning\n        G1 X{printer.toolhead.axis_maximum.x/2} Y{printer.toolhead.axis_maximum.y-40} F6000                        ; Park toolhead  at rear center\n        SAVE_GCODE_STATE NAME=PAUSEPARK                                                                            ; Save parked position in case toolhead is moved during the pause (otherwise the return zhop can error)\n        M104 S0                                                                                                    ; Turn off hotend\n        SET_IDLE_TIMEOUT TIMEOUT=43200                                                                             ; Set timeout to 12 hours\n        SET_STEPPER_ENABLE STEPPER=extruder enable=0                                                               ; Disable extruder stepper\n    {% endif %}\n\n\n[gcode_macro RESUME]\nrename_existing: BASE_RESUME\nvariable_zhop: 0\nvariable_etemp: 0\ngcode:\n    {% set extrusion_length = params.E|default(2.5)|int %}                                                                        ; Hotend prime amount (in mm)\n\n    {% if printer['pause_resume'].is_paused|int == 1 %}\n        {% if \"z\" not in printer.toolhead.homed_axes %}                                                            ; check if z position is lost\n            {action_raise_error(\"ERROR: Z-axixs lost its position (Idle-Timeout)! Resume not possible - Print should be aborted.\")}\n        {% endif %}\n        \n        SET_IDLE_TIMEOUT TIMEOUT={printer.configfile.settings.idle_timeout.timeout}                                ; Set idle timeout back to configured value\n\n        # If X/Y position lost: Give Z-clearance for homing X/Y that will be done by PRIME_NOZZLE                                                                                     \n        {% if \"x\" not in printer.toolhead.homed_axes or \"y\" not in printer.toolhead.homed_axes %}                  ; If X/Y position is lost, but z is still OK\n            G91                                                                                                    ; Relative positioning\n            G1 Z5 F600                                                                                             ; 5mm clearance for safe X/Y-Homing\n            G90                                                                                                    ; Absolute positioning\n        {% endif %}\n\n\n        {% if etemp > 0 %}\n            M109 S{etemp|int}                                                                                      ; Wait for hotend to heat up\n        {% endif %}\n        RESTORE_GCODE_STATE NAME=PAUSEPARK MOVE=1 MOVE_SPEED=150                                                   ; Restore back to parked position in case toolhead was moved during pause (otherwise the return zhop can error)  \n        G91                                                                                                        ; Relative positioning\n        M83                                                                                                        ; Relative extruder positioning\n        {% if printer[printer.toolhead.extruder].temperature >= printer.configfile.settings.extruder.min_extrude_temp %}\n            G1  E{extrusion_length} F900                                                                                          ; Prime nozzle\n        {% endif %}  \n        RESTORE_GCODE_STATE NAME=PAUSEPARK2 MOVE=1 MOVE_SPEED=150                           \n        RESTORE_GCODE_STATE NAME=PAUSE MOVE=1 MOVE_SPEED=10                                                        ; Restore position\n        BASE_RESUME                                                                                                ; Resume print\n        G90                                                                                                        ; Absolute positioning\n    {% endif %}\n\n\n[gcode_macro CANCEL_PRINT]\nrename_existing: BASE_CANCEL_PRINT\ngcode:\n\n    {% set max_z = printer.configfile.config[\"stepper_z\"][\"position_max\"]|float %}\n    {% if (printer.toolhead.position.z + 12) < max_z %}\n        {% set z_hop = 2  %}\n    {% else %}\n        {% set z_hop = 0 %}\n    {% endif %}\n\n    G91                                                                                                            ; Relative positioning\n    G1 Z{z_hop} F600                                                                                               ; Do a tiny z-hop\n    G90                                                                                                            ; Absolute positioning\n\n    G1 X{printer.toolhead.axis_maximum.x/2} Y{printer.toolhead.axis_maximum.y-40} F12000\n    CLEAR_PAUSE\n    SDCARD_RESET_FILE\n\n    PRINT_END\n    BASE_CANCEL_PRINT\n\n\n[gcode_macro _Z_CLEARANCE]\ndescription: Lower the bed to give some clearance\nvariable_default_distance: 40.0\ngcode:\n    {% set current_z_height = printer.toolhead.position.z %}\n    {% set max_z_height = printer.toolhead.axis_maximum.z %}\n    {% set distance = params.DISTANCE|default(variable_default_distance)|float %}\n    {% set target_z_height = current_z_height + distance %}\n\n    {% set min_z_param = params.MIN_Z|default(None) %}\n    {% if min_z_param is not none %}\n        {% set min_z = min_z_param|float %}\n        {% if target_z_height < min_z %}\n            {% set target_z_height = min_z %}\n        {% endif %}\n    {% endif %}\n\n    G90                                                                                                            ; Absolute positioning\n    G1 Z{ [target_z_height, max_z_height]|min }\n\n\n########################################\n#  Filament Macros\n########################################\n[gcode_macro UNLOAD_FILAMENT]\ndescription: Unloads filament from toolhead\ngcode:\n  {% set EXTRUDER_TEMP = params.TEMP|default(230)|int %}\n  {% set CURRENT_TEMP = printer.extruder.temperature|int %}\n  {% if CURRENT_TEMP < EXTRUDER_TEMP %}\n    M109 S{EXTRUDER_TEMP}                                                                                          ; heat up the hotend\n  {% endif %}  \n  SET_STEPPER_ENABLE STEPPER=extruder ENABLE=1                                                                     ; enable extruder stepper \n  M83                                                                                                              ; set extruder to relative mode\n  G1 E5 F150                                                                                                       ; extrude a small amount to elimate soften the filament\n  G1 E-8 F1800                                                                                                     ; quickly retract a small amount to elimate stringing\n  G4 P200                                                                                                          ; pause for a short amount of time\n  G1 E-50 F300                                                                                                     ; retract slowly the rest of the way\n  M104 S0                                                                                                          ; turn off hotend\n  M400                                                                                                             ; wait for moves to finish\n  M118 Unload Complete!\n\n\n[gcode_macro LOAD_FILAMENT]\ndescription: Loads filament to toolhead\ngcode:\n  {% set EXTRUDER_TEMP = params.TEMP|default(230)|int %}\n  {% set CURRENT_TEMP = printer.extruder.temperature|int %}\n  {% if CURRENT_TEMP < EXTRUDER_TEMP %}\n    M109 S{EXTRUDER_TEMP}                                                                                          ; heat up the hotend\n  {% endif %}\n  SET_STEPPER_ENABLE STEPPER=extruder ENABLE=1                                                                     ; enable extruder stepper \n  M83                                                                                                              ; set extruder to relative mode\n  G1 E5 F120                                                                                                       ; feed filament\n  G1 E5 F300                                                                                                       ; feed filament\n  G1 E40 F600                                                                                                      ; feed filament\n  G1 E15 F300                                                                                                      ; feed filament\n  G1 E15 F120                                                                                                      ; feed filament\n  G4 P200                                                                                                          ; pause for a short amount of time\n  G1 E10 F90                                                                                                       ; feed filament\n  M104 S0                                                                                                          ; turn off hotend\n  M400                                                                                                             ; wait for moves to finish\n  M118 Load Complete!\n\n\n# Filament runout sensor enable/disable\n[gcode_macro M8029]\ngcode:\n     {% if params.D is defined %}\n       {% if (params.D|int)==1 %} \n        SET_FILAMENT_SENSOR SENSOR=filament ENABLE=1\n       {% endif %}\n       {% if (params.D|int)==0 %} \n        SET_FILAMENT_SENSOR SENSOR=filament ENABLE=0\n       {% endif %}\n     {% endif %}\n\n\n########################################\n# Fan Macros\n########################################\n# Set Fan Speed macro\n# Mainly name castings for nicer web interface names and display functionality\n[gcode_macro M106]\nrename_existing: M106.1\ngcode:\n    {% if params.P is defined %}\n      {% if params.S is defined %}\n        {% set speed = 0.003921*params.S|int %}\n        {% if (params.P|int) == 0 %}\n          M106.1 S{params.S|int}\n        {% elif (params.P|int) == 2 %}\n          SET_FAN_SPEED FAN=sidefan SPEED={speed}\n        {% elif (params.P|int) == 3 %}\n          SET_FAN_SPEED FAN=filterfan SPEED={speed}\n        {% else %}\n          SET_FAN_SPEED FAN=fan{params.P|int} SPEED={speed}\n        {% endif %}\n      {% else %}\n        {% if (params.P|int) == 0 %}\n          M106.1 S255\n        {% elif (params.P|int) == 2 %}\n          SET_FAN_SPEED FAN=sidefan SPEED=1\n        {% elif (params.P|int) == 3 %}\n          SET_FAN_SPEED FAN=filterfan SPEED=1\n        {% else %}\n          SET_FAN_SPEED FAN=fan{params.P|int} SPEED=1\n        {% endif %}\n      {% endif %}\n    {% endif %} \n\n    {% if params.T is defined %}\n      {% if (params.T|int) == -2 %}\n        {% if params.S is defined %}\n          {% set speed = 0.003921*params.S|int %}\n          SET_FAN_SPEED FAN=filterfan SPEED={speed}\n        {% else %}\n          SET_FAN_SPEED FAN=filterfan SPEED=1\n        {% endif %}\n      {% endif %}\n    {% endif %}\n\n    {% if params.P is undefined %}\n      {% if params.T is undefined %}\n        {% if params.S is defined %}\n          M106.1 S{params.S|int}\n        {% else %}\n          M106.1 S255\n        {% endif %}\n      {% endif %}\n    {% endif %}\n\n[gcode_macro M107]\nrename_existing: M107.1\ngcode:  \n    M106.1 S0\n\n\n########################################\n# Temperature Macros\n########################################\n# Wait for Hotend Temperature\n[gcode_macro M109]\nrename_existing: M109.1\ngcode:\n    #Parameters\n    {% set s = params.S|float %}\n\n    M104 {% for p in params %}{'%s%s' % (p, params[p])}{% endfor %}                                              ; Set hotend temp\n    {% if s != 0 %}\n        TEMPERATURE_WAIT SENSOR=extruder MINIMUM={s} MAXIMUM={s+1}                                               ; Wait for hotend temp (within 1 degree)\n    {% endif %}\n\n\n# PID autotune\n[gcode_macro M303]\ngcode:\n    {% if params.E is defined %}\n     {% if params.S is defined %}\n        {% if (params.E|int)==-1 %} \n         PID_CALIBRATE HEATER=heater_bed TARGET={params.S|int}\n        {% endif %}\n        {% if (params.E|int)==0 %}\n         PID_CALIBRATE HEATER=extruder TARGET={params.S|int}\n        {% endif %}\n     {% endif %}\n  {% endif %}\n\n\n# Set chamber temperature\n[gcode_macro M141]\ngcode:\n    {% if printer[\"heater_generic chamber\"] is defined %}\n        {% set chamber_target_temp = params.S|float %}\n        SET_HEATER_TEMPERATURE HEATER=chamber TARGET={([chamber_target_temp, 65]|min)}\n    {% endif %}\n\n\n# Set wait chamber temperature\n[gcode_macro M191]\ngcode:\n    #Parameters\n    {% set chamber_target_temp = params.S|float %}\n\n    {% if chamber_target_temp == 0 %}\n        M118 Chamber heater off\n    {% else %}\n        M141 S{chamber_target_temp}\n        TEMPERATURE_WAIT SENSOR=\"heater_generic chamber\" MINIMUM={([chamber_target_temp, 60]|min)-2} MAXIMUM={chamber_target_temp + 5}  \n        M118 Chamber at target temperature\n    {% endif %}\n\n\n########################################\n# Sound Macros\n########################################\n[gcode_macro BEEP]\ngcode:\n    {% set i = params.I|default(1)|int %}                                                                        ; Iterations (number of times to beep).\n    {% set dur = params.DUR|default(100)|int %}                                                                  ; Duration/wait of each beep in ms. Default 100ms.\n\n    {% if printer[\"output_pin sound\"].value|int == 1 %}\n        {% for iteration in range(i|int) %}\n            SET_PIN PIN=buzzer VALUE=1\n            G4 P{dur}\n            SET_PIN PIN=buzzer VALUE=0\n            G4 P{dur}\n        {% endfor %}\n    {% endif %}\n\n\n[gcode_macro beep_on]\ngcode:\n    SET_PIN PIN=buzzer VALUE=1\n\n\n[gcode_macro beep_off]\ngcode:\n    SET_PIN PIN=buzzer VALUE=0\n\n\n########################################\n# Z-height Macros\n########################################\n# Bed Leveling (Unified)\n[gcode_macro G29]\nvariable_k:1\ngcode:\n    {% if k|int==1 %}\n        BED_MESH_CLEAR                                                                                           ; Clear levelling data\n        BED_MESH_CALIBRATE ADAPTIVE=1 ADAPTIVE_MARGIN=5                                                          ; Start adaptive meshing\n    {% endif %}   \n\n\n# Babystep\n[gcode_macro M290]\ngcode:\n   SET_GCODE_OFFSET Z_ADJUST={params.Z}\n\n\n########################################\n# Tuning Macros\n########################################\n[gcode_macro SHAPER_CALIBRATE]\nrename_existing: RESHAPER_CALIBRATE\ngcode:\n    RESHAPER_CALIBRATE FREQ_START=30 FREQ_END=130\n\n\n# Linear Advance Factor\n[gcode_macro M900]\ngcode:\n    {% if params.K is defined %} \n          SET_PRESSURE_ADVANCE ADVANCE={params.K}\n    {% endif %}  \n    {% if params.T is defined %}    \n       SET_PRESSURE_ADVANCE SMOOTH_TIME={params.T}\n    {% endif %} \n\n\n# Set Starting Acceleration\n[gcode_macro M204]\nrename_existing: M99204\ngcode:\n    {% if params.S is defined %}\n        {% set s = params.S|float %}\n    {% endif %}\n    {% if params.P is defined %}\n    {% if params.T is defined %}\n        {% set s = [params.P|float ,params.T|float] | min %}\n    {% endif %}\n    {% endif %}\n\n    SET_VELOCITY_LIMIT ACCEL={s}\n    SET_VELOCITY_LIMIT ACCEL_TO_DECEL={s/2}\n\n\n# Bed leveling\n# For more information, see https://www.klipper3d.org/Manual_Level.html#adjusting-bed-leveling-screws-using-the-bed-probe\n[gcode_macro LEVEL_BED]\ndescription: \"Measure bed and calculate screw adjustments for manual bed leveling\"\ngcode:\n    G28                                                                                                         ; Home all\n    SCREWS_TILT_CALCULATE                                                                                       ; Perform measurements and output screw adjustments\n\n\n# Probe Calibration\n# For more information, see https://www.klipper3d.org/Probe_Calibrate.html\n[gcode_macro CALIBRATE_Z_OFFSET]\ndescription: \"Calibrate the Z offset using the probe\"\ngcode:\n    {% set max_x = printer.configfile.config[\"stepper_x\"][\"position_max\"]|float %}\n    {% set max_y = printer.configfile.config[\"stepper_y\"][\"position_max\"]|float %}\n\n    G28                                                                                                         ; Home all\n    G0 Z10                                                                                                      ; Increase z clearance\n    G0 X{max_x/2} Y{max_y-40} F6000                                                                             ; Move to bed center \n    PROBE_CALIBRATE                                                                                             ; Perform a probe calibration\n\n\n# Nozzle PID tuning\n# For more information, see https://www.klipper3d.org/Config_checks.html#calibrate-pid-settings\n[gcode_macro NOZZLE_PID_TUNE]\ndescription: \"Perform PID tuning for the nozzle heater\"\ngcode:\n    PID_CALIBRATE HEATER=extruder TARGET=220                                                                    ; PID tune the nozzle\n\n\n# Bed PID tuning\n# For more information, see https://www.klipper3d.org/Config_checks.html#calibrate-pid-settings\n[gcode_macro BED_PID_TUNE]\ndescription: \"Perform PID tuning for the bed heater\"\ngcode:\n    PID_CALIBRATE HEATER=heater_bed TARGET=80                                                                   ; PID tune the bed\n\n\n########################################\n# Macros for display functionallity\n########################################\n[gcode_macro INPUT_SHAPING_CALIBRATE]\ndescription: \"Perform Input Shaping calibration and save the results to printer.cfg\"\ngcode:\n    SHAPER_CALIBRATE                                                                                            ; Step 1: Perform the Input Shaping calibration\n    PAUSE                                                                                                       ; Step 2: Pause to allow the calibration to complete\n    SAVE_CONFIG                                                                                                 ; Step 3: Save the configuration to printer.cfg\n    RESTART                                                                                                     ; Step 4: Restart the firmware to apply the new settings\n\n"
  },
  {
    "path": "config_section/X-Max3/printer.cfg",
    "content": "# X-Max3 config created by Phil1988(github)/coco.33(discord) on 20.12.2024\n# For more information check out my wiki: https://github.com/Phil1988/FreeDi/wiki\n\n\n#####################################################################\n# Kinematics\n#####################################################################\n[printer]\nkinematics:corexy\nmax_velocity: 600\nmax_accel: 20000\nmax_z_velocity: 20\nmax_z_accel: 500\nsquare_corner_velocity: 8\n\n\n#####################################################################\n# Motherboard and periphery\n#####################################################################\n[temperature_sensor Mainboard_RK3328]\nsensor_type: temperature_host\nmin_temp: 10\nmax_temp: 100\n\n[mcu]\nserial: /dev/ttyS0\nrestart_method: command\nbaud: 500000\n\n[temperature_sensor Mainboard_STM32F402]\nsensor_type: temperature_mcu\nsensor_mcu: mcu\n\n[mcu Toolhead]\nserial: /dev/serial/by-id/usb-Klipper_rp2040_C5DA4D951E145858-if00\n\n[temperature_sensor Toolhead_RP2040]\nsensor_type: temperature_mcu\nsensor_mcu: Toolhead\nmin_temp: 0\nmax_temp: 100\n\n\n#####################################################################\n# Features\n#####################################################################\n# For saving GCODE files\n[virtual_sdcard]\npath: ~/printer_data/gcodes\non_error_gcode: CANCEL_PRINT\n\n# For enabling pause/resume\n[pause_resume]\n\n# Activating exclude objects feature\n[display_status]\n[exclude_object]\n\n# Expanding idle timeout\n[idle_timeout]\ntimeout: 5400   ; 90min timeout\n\n# Activating GCODE arc feature\n[gcode_arcs]\nresolution: 1.0\n\n# Allowing free move (can be dangerous!)\n[force_move]\nenable_force_move: True\n\n# Activating responses\n[respond]\ndefault_type: echo\n\n\n#####################################################################\n# FreeDi\n#####################################################################\n[include freedi.cfg] \n\n\n#####################################################################\n# Macros\n#####################################################################\n[include macros.cfg]\n\n\n#####################################################################\n# Input shaping\n#####################################################################\n[resonance_tester]\naccel_chip:adxl345\nprobe_points:\n    160, 160, 10\naccel_per_hz: 75\nsweeping_period: 0\nmax_smoothing: 0.5\n    \n[adxl345]\ncs_pin: Toolhead:gpio13\nspi_software_sclk_pin: Toolhead:gpio14\nspi_software_mosi_pin: Toolhead:gpio15\nspi_software_miso_pin: Toolhead:gpio12\naxes_map: -x, z, -y\n\n[input_shaper]\nshaper_type_x: mzv\nshaper_freq_x: 57.6\nshaper_type_y: mzv\nshaper_freq_y: 46.6\n\n\n#####################################################################\n# Hotend\n#####################################################################\n[extruder]\nstep_pin: Toolhead:gpio5\ndir_pin: Toolhead:gpio4\nenable_pin: !Toolhead:gpio10\nrotation_distance: 53.5\ngear_ratio: 1628:170\nmicrosteps: 16\nfull_steps_per_rotation: 200\nnozzle_diameter: 0.400\nfilament_diameter: 1.75\nmin_temp: 0\nmax_temp: 360\nmin_extrude_temp: 170\nsmooth_time: 0.000001\nstep_pulse_duration:0.000002\n\nheater_pin: Toolhead:gpio0\nsensor_type:MAX6675\nsensor_pin: Toolhead:gpio17\nmax_power: 1.0\ncontrol: pid  \npid_Kp: 24.737\npid_Ki: 10.994\npid_Kd: 13.915\n\nspi_speed: 100000\nspi_software_sclk_pin: Toolhead:gpio18\nspi_software_mosi_pin: Toolhead:gpio19\nspi_software_miso_pin: Toolhead:gpio16\n\npressure_advance: 0.032\npressure_advance_smooth_time: 0.03\nmax_extrude_cross_section:500\ninstantaneous_corner_velocity: 10.000\nmax_extrude_only_distance: 500.0\nmax_extrude_only_velocity: 5000\nmax_extrude_only_accel: 2000\n\n[verify_heater extruder]\nmax_error: 120\ncheck_gain_time: 20\nhysteresis: 5\nheating_gain: 1\n\n\n#####################################################################\n# Heated bed\n#####################################################################\n[heater_bed]\nheater_pin: PC8\nsensor_type: NTC 100K MGB18-104F39050L32\nsensor_pin: PA0\nmax_power: 1.0\ncontrol: pid\npid_kp: 64.431\npid_ki: 2.845\npid_kd: 364.839\nmin_temp: -50\nmax_temp: 125\npwm_cycle_time: 0.02 # for 50Hz line power \n#pwm_cycle_time: 0.016 # for 60Hz line power\n\n[verify_heater heater_bed]\nmax_error: 200\ncheck_gain_time: 360\nhysteresis: 5\nheating_gain: 1\n\n\n#####################################################################\n# Bed mesh\n#####################################################################\n[bed_mesh]\nspeed: 150               \nhorizontal_move_z: 3.0\nmesh_min: 28,8        \nmesh_max: 315,310     \nprobe_count: 9,9     \nalgorithm: bicubic\nbicubic_tension: 0.2\nmesh_pps: 4, 4\n\n\n#####################################################################\n# Probe\n#####################################################################\n#!# Pay attention to this section and compare it with your stock backup config\n[probe]\npin: ^!Toolhead:gpio21\nx_offset: 28\ny_offset: 4.4\nz_offset: 1.549             #!# change this to 0 if you get a \"Probe triggered prior to movement\" - Error\nspeed: 5\nsamples: 2\nsamples_result: average\nsample_retract_dist: 1.1\nsamples_tolerance: 0.08\nsamples_tolerance_retries: 3\n\n#!# This is for users of the first batches x-series with a BLtouch. Please uncomment if you have one\n#!# Pay attention to this section and compare it with your stock backup config\n#[bltouch]\n#sensor_pin: ^Toolhead:gpio21\n#control_pin: Toolhead:gpio11\n#stow_on_each_sample: False\n#x_offset: 28\n#y_offset: 4.4\n#z_offset: 0.0\n#speed: 5\n#samples: 2\n#samples_result: average\n#sample_retract_dist: 3.0\n#samples_tolerance: 0.08\n#samples_tolerance_retries:3\n\n\n#####################################################################\n# Heated chamber\n#####################################################################\n[heater_generic chamber]\nheater_pin: PB10\nmax_power:1.0\nsensor_type:NTC 100K MGB18-104F39050L32\nsensor_pin: PA1\ncontrol: watermark\nmax_delta: 0.5\nmin_temp:-100\nmax_temp:70\n\n[verify_heater chamber]\nmax_error: 300\ncheck_gain_time:480\nhysteresis: 5\nheating_gain: 1\n\n\n########################################\n# Filament runout sensor\n########################################\n[filament_switch_sensor filament]\nswitch_pin: !PC1\npause_on_runout: True\nrunout_gcode:\n            M118 Filament run out!\nevent_delay: 3.0\npause_delay: 0.5\n\n\n#####################################################################\n# Fans\n#####################################################################\n## Part cooling fan \n# [fan_generic partfan]\n# pin: Toolhead:gpio2\n# max_power: 1.0\n# cycle_time: 0.0100\n# hardware_pwm: false\n# kick_start_time: 0.200\n# off_below: 0.08\n# shutdown_speed: 0\n[fan]\npin: Toolhead:gpio2\nmax_power: 1.0\ncycle_time: 0.0100\nhardware_pwm: false\nkick_start_time: 0.200\noff_below: 0.08\nshutdown_speed: 0.0\n\n## Big side radial turbo fan\n[fan_generic sidefan]\npin: PA8\nmax_power: 1.0\ncycle_time: 0.0100\nhardware_pwm: false\nkick_start_time: 0.250\noff_below: 0.3\nshutdown_speed: 0\n\n## Activated charcoal blowing fan\n[fan_generic filterfan]\npin: PC9\nmax_power: 1.0\ncycle_time: 0.0100\nhardware_pwm: false\nkick_start_time: 0.200\noff_below: 0.3\nshutdown_speed: 0\n\n## Cold end and toolhead housing fans\n[heater_fan hotend_fan]\npin: Toolhead:gpio1\nmax_power: 1.0\nshutdown_speed:1.0\nkick_start_time: 0.5\nheater: extruder\nheater_temp: 50.0\nfan_speed: 1.0\noff_below: 0\n\n#!# Delete the next section if your stock backup config doesnt have it\n# Toolhead cooling fan\n[heater_fan hotend_fan2]\npin: Toolhead:gpio20\nmax_power: 1.0\nkick_start_time: 0.5\nheater: extruder\nheater_temp: 50.0\nfan_speed: 1.0\noff_below: 0\n\n#!# Delete the next section if your stock backup config doesnt have it\n## Controllable Mainboard cooling fan\n[temperature_fan Mainboard_fan]\nsensor_type: temperature_host \npin: PC4        \nmax_power: 1.0  \ncycle_time: 0.01\nsensor_type: temperature_combined\nsensor_list: temperature_sensor Mainboard_RK3328, temperature_sensor Mainboard_STM32F402\ncombination_method: max                                           # use the maximum reading of the sensors\nmaximum_deviation: 999.9                                          # we don't care about the difference in temperature\nshutdown_speed: 0.0\nkick_start_time: 0.4\noff_below: 0.19\nmin_temp: 0\nmax_temp: 85.0  \ntarget_temp: 42.0\nmin_speed: 0\nmax_speed: 1.0\ncontrol: pid\npid_deriv_time: 2.0\npid_Kp: 2.0\npid_Ki: 5.0\npid_Kd: 0.5\n\n\n#####################################################################\n# Light\n#####################################################################\n## caselight LEDs\n[output_pin caselight]\npin: PC7\npwm: true\ncycle_time: 0.0100\nshutdown_value:0\nvalue:1\n\n\n#####################################################################\n# Buzzer\n#####################################################################\n## Buzzer\n[output_pin buzzer]\npin: PA2\npwm: false\nshutdown_value:0\nvalue:0\n\n[output_pin sound]\npin: PA13\nvalue:0\n\n\n#####################################################################\n# Power outage shutdown\n#####################################################################\n[output_pin pwc]\npin: PA3\npwm: False\nvalue: 1\nshutdown_value: 1\n\n\n#####################################################################\n# Drives\n#####################################################################\n[stepper_x]\nstep_pin: PB4\ndir_pin: PB3\nenable_pin: !PB5\nmicrosteps: 16\nrotation_distance: 39.94\nfull_steps_per_rotation: 200 \nendstop_pin: tmc2209_stepper_x:virtual_endstop\nposition_min: -5\nposition_endstop: -5\nposition_max: 328\nhoming_speed: 40\nhoming_retract_dist: 0\nhoming_positive_dir: False\nstep_pulse_duration: 0.000002\n\n[stepper_y]\nstep_pin: PC14\ndir_pin: PC13\nenable_pin: !PC15\nmicrosteps: 16\nrotation_distance: 39.96\nfull_steps_per_rotation: 200  \nendstop_pin: tmc2209_stepper_y:virtual_endstop\nposition_min: -7.5\nposition_endstop: -7.5\nposition_max: 326\nhoming_speed: 40\nhoming_retract_dist: 0\nhoming_positive_dir: False\nstep_pulse_duration: 0.000002\n\n[stepper_z]\nstep_pin: PC10\ndir_pin: PA15\nenable_pin: !PC11\nmicrosteps: 16\nrotation_distance: 8\nfull_steps_per_rotation: 200\nendstop_pin: probe:z_virtual_endstop\nposition_max: 322\nposition_min: -2\nhoming_speed: 10\nhoming_retract_dist: 8.0\nsecond_homing_speed: 5\nhoming_positive_dir: false\nstep_pulse_duration: 0.000002\n\n\n#####################################################################\n# Steppers configuration\n#####################################################################\n[tmc2209 extruder]\nuart_pin: Toolhead:gpio6\ninterpolate: True\nrun_current: 0.714             #!# Pay attention to this value and compare it with your stock backup config\nstealthchop_threshold: 0\n\n[tmc2209 stepper_x]\nuart_pin: PD2\nrun_current: 1.07               #!# Pay attention to this value and compare it with your stock backup config\ninterpolate: True\nstealthchop_threshold: 0\ndiag_pin: ^PB8\ndriver_SGTHRS: 85\n\n[tmc2209 stepper_y]\nuart_pin: PB9\nrun_current: 1.07              #!# Pay attention to this value and compare it with your stock backup config\ninterpolate: True\nstealthchop_threshold: 0\ndiag_pin: ^PC0\ndriver_SGTHRS: 85\n\n[tmc2209 stepper_z]\nuart_pin: PC5\nrun_current: 0.95              #!# Pay attention to this value and compare it with your stock backup config\ninterpolate: True\nstealthchop_threshold: 1200\n\n#####################################################################\n# Screws tilt adjust\n#####################################################################\n[screws_tilt_adjust] \nhorizontal_move_z: 5\nscrew_thread: CCW-M4\nspeed: 300\n\nscrew1: 8,32\nscrew1_name: front left screw\nscrew2: 264,32\nscrew2_name: front right screw\nscrew3: 264,286\nscrew3_name: rear right screw\nscrew4: 8,286\nscrew4_name: rear left screw\n"
  },
  {
    "path": "config_section/X-Plus3/macros.cfg",
    "content": "#####################################################################\n# Advanced CHAMBER_TEMP_CONTROLLER\n#####################################################################\n\n[gcode_macro SET_PRINT_STATS_INFO]\nrename_existing: BASE_SET_PRINT_STATS_INFO_BASE\ngcode:\n    #TIMELAPSE_TAKE_FRAME\n    BASE_SET_PRINT_STATS_INFO_BASE {rawparams}\n    CHAMBER_TEMP_CONTROLLER\n\n# Safety macro that gets frequently called by SET_PRINT_STATS_INFO to prevent too high chamber temperatures\n[gcode_macro CHAMBER_TEMP_CONTROLLER]\ngcode:\n    {% set chamber_target_temp = printer['heater_generic chamber'].target %}\n    {% set chamber_temp = printer['heater_generic chamber'].temperature %}\n    {% if chamber_temp > printer.configfile.settings['heater_generic chamber'].max_temp %}\n        M106 P3 S255\n    {% else %}\n        {% if chamber_target_temp > 0 %}\n            # Allow for 3C of \"grace\" before we start ramping the exhaust fan speed\n            # This prevents the macro from fighting with the chamber heater PID algorithm\n            {% set difference = chamber_temp - (chamber_target_temp + 3) %}\n            {% if difference > 0 %}\n                {% set filterfan_speed = ([(difference * 50), 255] | min) | int %}\n                M106 P3 S{filterfan_speed}\n            {% else %}\n                M106 P3 S0\n            {% endif %}\n        {% endif %}\n    {% endif %}\n    \n\n#####################################################################\n# Homing modification\n#####################################################################\n[gcode_macro G28]\nrename_existing: G28.1\ngcode:\n    {% set reduced_current_x = 0.6 %}\n    {% set reduced_current_y = 0.7 %}\n    {% set home_all = ('X' in rawparams.upper() and 'Y' in rawparams.upper() and 'Z' in rawparams.upper()) or \n                      ('X' not in rawparams.upper() and 'Y' not in rawparams.upper() and 'Z' not in rawparams.upper()) %}\n    {% set home_current_x = printer.configfile.settings['tmc2209 stepper_x'].run_current * reduced_current_x %}\n    {% set home_current_y = printer.configfile.settings['tmc2209 stepper_y'].run_current * reduced_current_y %}\n\n    {% set init_XY_move = 30 %}\n    #{% set y_init_move = 5 %}\n    {% set z_clearance = 2 %}\n\n    {% set home_all_final_position_x = printer.toolhead.axis_maximum.x / 2 %}\n    {% set home_all_final_position_y = printer.toolhead.axis_maximum.y - 40 %}\n    {% set home_all_final_position_z = 10 %}\n\n    # If homing should at least move X or Y axis\n    {% if home_all or 'X' in rawparams.upper() or 'Y' in rawparams.upper() %}     \n        # Check if Z is homed\n        {% if 'z' in printer.toolhead.homed_axes %}\n            {% set Z_axis_was_homed = true %}                                                                       ; Set Z_axis_was_homed to true if Z is already homed\n            G91                                                                                                     ; Use relative positioning\n            G1 Z2 F600                                                                                              ; Move bed down\n            G90                                                                                                     ; Use absolute positioning\n        {% else %}\n            {% set Z_axis_was_homed = false %}                                                                      ; Set Z_axis_was_homed to false if Z is not homed\n            FORCE_MOVE STEPPER=stepper_z DISTANCE={z_clearance} VELOCITY=10                                         ; Move bed down\n        {% endif %}\n    {% endif %}\n\n    {% if home_all or 'X' in rawparams.upper() or 'Y' in rawparams.upper() %} \n        G91                                                                                                         ; Use relative positioning\n        FORCE_MOVE STEPPER=stepper_x DISTANCE={init_XY_move} VELOCITY=40                                            ; Move X a little before homing\n        SET_KINEMATIC_POSITION X={printer.toolhead.position.x + (init_XY_move/2)}                                   ; Compensate the FORCE_MOVE position \n        SET_KINEMATIC_POSITION Y={printer.toolhead.position.y + (init_XY_move/2)}                                   ; Compensate the FORCE_MOVE position \n        G90                                                                                                         ; Use absolute positioning\n    {% endif %}\n\n    # Home Y\n    {% if home_all or 'Y' in rawparams.upper() %}\n        SET_TMC_CURRENT STEPPER=stepper_x CURRENT={home_current_y}                                                  ; Lower motor current\n        SET_TMC_CURRENT STEPPER=stepper_y CURRENT={home_current_y}                                                  ; Lower motor current\n        G28.1 Y                                                                                                     ; Home Y\n        SET_TMC_CURRENT STEPPER=stepper_x CURRENT={printer.configfile.settings['tmc2209 stepper_x'].run_current}    ; Set motor current to the previous value\n        SET_TMC_CURRENT STEPPER=stepper_y CURRENT={printer.configfile.settings['tmc2209 stepper_y'].run_current}    ; Set motor current to the previous value\n        G1 Y10 F1200                                                                                                ; Move Y-axis slightly\n    {% endif %}\n    \n    # Home X\n    {% if home_all or 'X' in rawparams.upper() %}        \n        SET_TMC_CURRENT STEPPER=stepper_x CURRENT={home_current_x}                                                  ; Lower motor current\n        SET_TMC_CURRENT STEPPER=stepper_y CURRENT={home_current_x}                                                  ; Lower motor current\n        G28.1 X                                                                                                     ; Home X\n        SET_TMC_CURRENT STEPPER=stepper_x CURRENT={printer.configfile.settings['tmc2209 stepper_x'].run_current}    ; Set motor current to the previous value\n        SET_TMC_CURRENT STEPPER=stepper_y CURRENT={printer.configfile.settings['tmc2209 stepper_y'].run_current}    ; Set motor current to the previous value\n        G1 X10 F1200                                                                                                ; Move X-axis slightly\n    {% endif %}\n\n    # Raise the bed again if only X or only Y axes were homed\n    {% if not (home_all or 'Z' in rawparams.upper()) %}\n        {% if Z_axis_was_homed %}\n            G91                                                                                                     ; Use relative positioning\n            G1 Z-2 F600                                                                                             ; Raise the bed back again\n            G90                                                                                                     ; Use absolute positioning\n        {% else %}\n            FORCE_MOVE STEPPER=stepper_z DISTANCE=-{z_clearance} VELOCITY=10                                        ; Raise the bed back again\n        {% endif %}\n    {% endif %}\n\n    # Home Z\n    {% if home_all or 'Z' in rawparams.upper() %}\n        G28.1 Z                                                                                                     ; Home Z\n        G90                                                                                                         ; Set absolute positioning\n        G1 Z{home_all_final_position_z}                                                                             ; Move bed down\n    {% endif %}\n\n    # Move to the final position if all axes were homed\n    {% if home_all %}\n        G90                                                                                                         ; Set absolute positioning\n        G1 X{home_all_final_position_x} Y{home_all_final_position_y} Z{home_all_final_position_z} F7800             ; Move to the rear center\n    {% endif %}\n\n\n# Unconditional stop\n[gcode_macro M0]\ngcode:\n    PAUSE\n\n\n# Pause SD print\n[gcode_macro M25]\nrename_existing: M9925\ngcode:\n    PAUSE\n\n\n########################################\n# Basic Macros\n########################################\n# Flag macro to use STATIC_MESH usage instead of KAMP (needed make this function work from printjob selection on the LCD)\n[gcode_macro NEXT_PRINT_STATIC_MESH]\ndescription: Forces the NEXT print to use 'STATIC_MESH' instead of KAMP.\ngcode:\n    {% if \"STATIC_MESH\" in printer.bed_mesh.profiles %}\n        SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=force_static_mesh VALUE=True\n        {action_respond_info(\"The NEXT print will use 'STATIC_MESH'.\")}\n        M118 The NEXT print will use the STATIC_MESH.\n    {% else %}\n        {action_respond_info(\"WARNING: No mesh named 'STATIC_MESH' found. Please save one first (BED_MESH_PROFILE SAVE=STATIC_MESH).\")}\n        M118 WARNING: No mesh named STATIC_MESH found. Please save one first (BED_MESH_PROFILE SAVE=STATIC_MESH).\n    {% endif %}\n\n\n[gcode_macro PRINT_START]\n# Use PRINT_START for the slicer starting script\ndescription: Start printing\nvariable_force_static_mesh: False                                                                                 ; Set to True to force a static mesh instead of KAMP\ngcode:\n    {% set bed_target_temp = params.BED|default(0)|int %}\n    {% set hotend_target_temp = params.HOTEND|default(0)|int %}\n    {% set chamber_target_temp = params.CHAMBER|default(0)|int %}\n\n    CLEAR_PAUSE                                                                                                    ; Clear existing pause states\n    BED_MESH_CLEAR                                                                                                 ; Clear previous adaptive mesh\n    SET_TEMPERATURE_FAN_TARGET TEMPERATURE_FAN=Mainboard_fan TARGET=1                                              ; Decrease the mainboard target temp to fully turn the fan on\n\n    {% set KAMP_deactivated = printer[\"gcode_macro PRINT_START\"].force_static_mesh %}                              ; Check if KAMP is deactivated for this print\n    SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=force_static_mesh VALUE=False                                    ; Auto-reset the variable immediately for the next print after this one\n\n\n    # Check if advanced mode (any parameter was passed)\n    {% if bed_target_temp > 0 or hotend_target_temp > 0 or chamber_target_temp > 0 %}\n        {% set bed_center_x = printer.configfile.config[\"stepper_x\"][\"position_max\"]|float / 2 %}\n        {% set bed_center_y = printer.configfile.config[\"stepper_y\"][\"position_max\"]|float / 2 %}\n\n        {% set start_position_x = printer.toolhead.axis_maximum.x / 2 %}\n        {% set start_position_y = printer.toolhead.axis_maximum.y - 40 %}\n        {% set start_position_z = 10 %}\n\n        M140 S{bed_target_temp}                                                                                    ; Set bed temperature\n        M141 S{chamber_target_temp}                                                                                ; Set chamber temperature\n        G28                                                                                                        ; Home all axes\n\n        {% if chamber_target_temp > 0 %}                                                                           ; Accelerate chamber heating by using the bed as additional heater    \n            G0 X{bed_center_x} Y{bed_center_y} Z3 F780                                                             ; Move print bed to perfect postion to help chamber heating\n            M106 P2 S185                                                                                           ; Turn sidefan on to use bed heat and mix air\n            M106 P0 S128                                                                                           ; Turn part cooling fan on to help air mixing\n            TEMPERATURE_WAIT SENSOR=\"heater_generic chamber\" MINIMUM={chamber_target_temp - 5}                     ; Wait for chamber to heat up\n            M106 P2 S0                                                                                             ; Turn off sidefan\n            M106 P0 S0                                                                                             ; Turn off part cooling fan                                      \n        {% endif %}\n\n        M191 S{chamber_target_temp}                                                                                ; Set and wait for chamber temperature\n        M190 S{bed_target_temp}                                                                                    ; Set and wait for bed temperature  \n        G90                                                                                                        ; Set absolute positioning\n        G1 X{start_position_x} Y{start_position_y} Z{start_position_z} F7800                                       ; Move to start position\n        G28 Z                                                                                                      ; Home Z again for to compensate bed expansion    \n    {% endif %}\n\n    {% if KAMP_deactivated %}\n        {% if \"STATIC_MESH\" in printer.bed_mesh.profiles %}                                                        ; Check if the spicific STATIC_MESH exists\n            M118  Loading 'STATIC_MESH' instead of KAMP.\n            BED_MESH_PROFILE LOAD=STATIC_MESH\n        {% else %}                                                                                                 ; Fallback to KAMP if STATIC_MESH not found\n            M118 ERROR: 'STATIC_MESH' not found! Using fallback: KAMP Adaptive Mesh.\n            BED_MESH_CLEAR                                                                                         ; Clear previous adaptive mesh\n            BED_MESH_CALIBRATE PROFILE=adaptive ADAPTIVE=1                                                         ; Start adaptive meshing\n        {% endif %}\n    {% else %}                                                                                                     ; Standard operation\n        {% if printer.toolhead.homed_axes|length < 3 %}\n            G28\n        {% endif %}\n        BED_MESH_CLEAR                                                                                             ; Clear previous adaptive mesh\n        BED_MESH_CALIBRATE PROFILE=adaptive ADAPTIVE=1                                                             ; Start adaptive meshing\n    {% endif %}\n\n    # Check if advanced mode (parameter was passed)\n    {% if hotend_target_temp %}                                                                                    ; Set hotend temperature now (prevent oozing during bed/chamber heating)\n        M109 S{hotend_target_temp}                                                                                 ; Set and wait for hotend temperature \n    {% endif %}\n\n\n[gcode_macro PRINT_END]\ngcode:\n    {% set max_x = printer.configfile.config[\"stepper_x\"][\"position_max\"]|float %}\n    {% set max_y = printer.configfile.config[\"stepper_y\"][\"position_max\"]|float %}\n    {% set max_z = printer.configfile.config[\"stepper_z\"][\"position_max\"]|float %}\n    {% set current_extruder_temp = printer.extruder.temperature|float %}\n    {% set min_extrusion_temp = printer.configfile.config[\"extruder\"][\"min_extrude_temp\"]|float %}\n    {% set z_clearance = 50 %}\n    {% set z_hop = 2  %}\n\n    {% if (printer.toolhead.position.z + z_clearance) < max_z %}\n        {% set z_hop = 2  %}\n    {% else %}\n        {% set z_hop = 0 %}\n    {% endif %}\n\n    M106 P0 S0                                                                                                      ; Turn off part cooling fan\n    M106 P2 S0                                                                                                      ; Turn off side fan\n    M106 P3 S0                                                                                                      ; Turn off activated charcoal fan\n\n    M104 S0                                                                                                         ; Turn off hotend\n    M140 S0                                                                                                         ; Turn off heated bed\n    M141 S0                                                                                                         ; Turn off heated chamber\n\n    G91                                                                                                             ; Relative positioning\n    {% if current_extruder_temp >= min_extrusion_temp + 5 %}                                                        ; Check if the hotend is hot enough to perform a retraction (with a small gap)  \n        G0 E-4.0 F300                                                                                               ; Retract filament\n    {% endif %}\n    G0 Z{z_hop} F3600                                                                                               ; Move bed down a bit\n    G90                                                                                                             ; Absolute positioning\n    G0 X{max_x/2} Y{max_y-40} F20000                                                                                ; Move nozzle to remove stringing\n    _Z_CLEARANCE DISTANCE={z_clearance}                                                                             ; Lower bed\n    M400                                                                                                            ; Wait for buffer to clear\n    G92 E0                                                                                                          ; Zero the extruder\n\n    M220 S100                                                                                                       ; Set feedrate (speed percentage) back to 100%\n    M221 S100                                                                                                       ; Set flow percentage back to 100%\n\n    SET_IDLE_TIMEOUT TIMEOUT={printer.configfile.settings.idle_timeout.timeout}                                     ; Set timeout back to configured value\n    CLEAR_PAUSE                                                                                                     ; Ensure pause state is cleared if applicable\n\n    M84                                                                                                             ; Disable steppers\n    SET_TEMPERATURE_FAN_TARGET TEMPERATURE_FAN=Mainboard_fan TARGET=45                                              ; Reset the mainboard fan temp\n    BEEP I=2 DUR=500                                                                                                ; Alert at the end of the print (if sound is enabled)\n\n\n[gcode_macro PAUSE]\nrename_existing: BASE_PAUSE\ngcode:\n    {% set z_hop = params.Z|default(30)|int %}                                                                     ; Z hop amount\n\n    {% if printer['pause_resume'].is_paused|int == 0 %}     \n        SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=zhop VALUE={z_hop}                                                ; Set Z hop variable for reference in resume macro\n        SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=etemp VALUE={printer['extruder'].target}                          ; Set hotend temperature variable for reference in resume macro\n        SAVE_GCODE_STATE NAME=PAUSE                                                                                ; Save current position for resume\n        BASE_PAUSE                                                                                                 ; Pause print\n        {% if (printer.gcode_move.position.z + z_hop) < printer.toolhead.axis_maximum.z %}                         ; Check that Z hop doesn't exceed Z max\n            G91                                                                                                    ; Use Relative positioning\n            G1 Z{z_hop} F600                                                                                       ; Raise Z up by Z hop amount\n        {% else %}\n            SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=zhop VALUE=0                                                  ; Set Z hop to 0 if exceeds max\n        {% endif %}\n        SAVE_GCODE_STATE NAME=PAUSEPARK2\n        G90                                                                                                        ; Absolute positioning\n        G1 X{printer.toolhead.axis_maximum.x/2} Y{printer.toolhead.axis_maximum.y-40} F6000                        ; Park toolhead  at rear center\n        SAVE_GCODE_STATE NAME=PAUSEPARK                                                                            ; Save parked position in case toolhead is moved during the pause (otherwise the return zhop can error)\n        M104 S0                                                                                                    ; Turn off hotend\n        SET_IDLE_TIMEOUT TIMEOUT=43200                                                                             ; Set timeout to 12 hours\n        SET_STEPPER_ENABLE STEPPER=extruder enable=0                                                               ; Disable extruder stepper\n    {% endif %}\n\n\n[gcode_macro RESUME]\nrename_existing: BASE_RESUME\nvariable_zhop: 0\nvariable_etemp: 0\ngcode:\n    {% set extrusion_length = params.E|default(2.5)|int %}                                                                        ; Hotend prime amount (in mm)\n\n    {% if printer['pause_resume'].is_paused|int == 1 %}\n        {% if \"z\" not in printer.toolhead.homed_axes %}                                                            ; check if z position is lost\n            {action_raise_error(\"ERROR: Z-axixs lost its position (Idle-Timeout)! Resume not possible - Print should be aborted.\")}\n        {% endif %}\n        \n        SET_IDLE_TIMEOUT TIMEOUT={printer.configfile.settings.idle_timeout.timeout}                                ; Set idle timeout back to configured value\n\n        # If X/Y position lost: Give Z-clearance for homing X/Y that will be done by PRIME_NOZZLE                                                                                     \n        {% if \"x\" not in printer.toolhead.homed_axes or \"y\" not in printer.toolhead.homed_axes %}                  ; If X/Y position is lost, but z is still OK\n            G91                                                                                                    ; Relative positioning\n            G1 Z5 F600                                                                                             ; 5mm clearance for safe X/Y-Homing\n            G90                                                                                                    ; Absolute positioning\n        {% endif %}\n\n        {% if etemp > 0 %}\n            M109 S{etemp|int}                                                                                      ; Wait for hotend to heat up\n        {% endif %}\n        RESTORE_GCODE_STATE NAME=PAUSEPARK MOVE=1 MOVE_SPEED=150                                                   ; Restore back to parked position in case toolhead was moved during pause (otherwise the return zhop can error)  \n        G91                                                                                                        ; Relative positioning\n        M83                                                                                                        ; Relative extruder positioning\n        {% if printer[printer.toolhead.extruder].temperature >= printer.configfile.settings.extruder.min_extrude_temp %}\n            G1  E{extrusion_length} F900                                                                                          ; Prime nozzle\n        {% endif %}  \n        RESTORE_GCODE_STATE NAME=PAUSEPARK2 MOVE=1 MOVE_SPEED=150                           \n        RESTORE_GCODE_STATE NAME=PAUSE MOVE=1 MOVE_SPEED=10                                                        ; Restore position\n        BASE_RESUME                                                                                                ; Resume print\n        G90                                                                                                        ; Absolute positioning\n    {% endif %}\n\n\n[gcode_macro CANCEL_PRINT]\nrename_existing: BASE_CANCEL_PRINT\ngcode:\n\n    {% set max_z = printer.configfile.config[\"stepper_z\"][\"position_max\"]|float %}\n    {% if (printer.toolhead.position.z + 12) < max_z %}\n        {% set z_hop = 2  %}\n    {% else %}\n        {% set z_hop = 0 %}\n    {% endif %}\n\n    G91                                                                                                            ; Relative positioning\n    G1 Z{z_hop} F600                                                                                               ; Do a tiny z-hop\n    G90                                                                                                            ; Absolute positioning\n\n    G1 X{printer.toolhead.axis_maximum.x/2} Y{printer.toolhead.axis_maximum.y-40} F12000\n    CLEAR_PAUSE\n    SDCARD_RESET_FILE\n\n    PRINT_END\n    BASE_CANCEL_PRINT\n\n\n[gcode_macro _Z_CLEARANCE]\ndescription: Lower the bed to give some clearance\nvariable_default_distance: 40.0\ngcode:\n    {% set current_z_height = printer.toolhead.position.z %}\n    {% set max_z_height = printer.toolhead.axis_maximum.z %}\n    {% set distance = params.DISTANCE|default(variable_default_distance)|float %}\n    {% set target_z_height = current_z_height + distance %}\n\n    {% set min_z_param = params.MIN_Z|default(None) %}\n    {% if min_z_param is not none %}\n        {% set min_z = min_z_param|float %}\n        {% if target_z_height < min_z %}\n            {% set target_z_height = min_z %}\n        {% endif %}\n    {% endif %}\n\n    G90                                                                                                            ; Absolute positioning\n    G1 Z{ [target_z_height, max_z_height]|min }\n\n\n########################################\n#  Filament Macros\n########################################\n[gcode_macro UNLOAD_FILAMENT]\ndescription: Unloads filament from toolhead\ngcode:\n  {% set EXTRUDER_TEMP = params.TEMP|default(230)|int %}\n  {% set CURRENT_TEMP = printer.extruder.temperature|int %}\n  {% if CURRENT_TEMP < EXTRUDER_TEMP %}\n    M109 S{EXTRUDER_TEMP}                                                                                          ; heat up the hotend\n  {% endif %}  \n  SET_STEPPER_ENABLE STEPPER=extruder ENABLE=1                                                                     ; enable extruder stepper \n  M83                                                                                                              ; set extruder to relative mode\n  G1 E5 F150                                                                                                       ; extrude a small amount to elimate soften the filament\n  G1 E-8 F1800                                                                                                     ; quickly retract a small amount to elimate stringing\n  G4 P200                                                                                                          ; pause for a short amount of time\n  G1 E-50 F300                                                                                                     ; retract slowly the rest of the way\n  M104 S0                                                                                                          ; turn off hotend\n  M400                                                                                                             ; wait for moves to finish\n  M118 Unload Complete!\n\n\n[gcode_macro LOAD_FILAMENT]\ndescription: Loads filament to toolhead\ngcode:\n  {% set EXTRUDER_TEMP = params.TEMP|default(230)|int %}\n  {% set CURRENT_TEMP = printer.extruder.temperature|int %}\n  {% if CURRENT_TEMP < EXTRUDER_TEMP %}\n    M109 S{EXTRUDER_TEMP}                                                                                          ; heat up the hotend\n  {% endif %}\n  SET_STEPPER_ENABLE STEPPER=extruder ENABLE=1                                                                     ; enable extruder stepper \n  M83                                                                                                              ; set extruder to relative mode\n  G1 E5 F120                                                                                                       ; feed filament\n  G1 E5 F300                                                                                                       ; feed filament\n  G1 E40 F600                                                                                                      ; feed filament\n  G1 E15 F300                                                                                                      ; feed filament\n  G1 E15 F120                                                                                                      ; feed filament\n  G4 P200                                                                                                          ; pause for a short amount of time\n  G1 E10 F90                                                                                                       ; feed filament\n  M104 S0                                                                                                          ; turn off hotend\n  M400                                                                                                             ; wait for moves to finish\n  M118 Load Complete!\n\n\n# Filament runout sensor enable/disable\n[gcode_macro M8029]\ngcode:\n     {% if params.D is defined %}\n       {% if (params.D|int)==1 %} \n        SET_FILAMENT_SENSOR SENSOR=filament ENABLE=1\n       {% endif %}\n       {% if (params.D|int)==0 %} \n        SET_FILAMENT_SENSOR SENSOR=filament ENABLE=0\n       {% endif %}\n     {% endif %}\n\n\n########################################\n# Fan Macros\n########################################\n# Set Fan Speed macro\n# Mainly name castings for nicer web interface names and display functionality\n[gcode_macro M106]\nrename_existing: M106.1\ngcode:\n    {% if params.P is defined %}\n      {% if params.S is defined %}\n        {% set speed = 0.003921*params.S|int %}\n        {% if (params.P|int) == 0 %}\n          M106.1 S{params.S|int}\n        {% elif (params.P|int) == 2 %}\n          SET_FAN_SPEED FAN=sidefan SPEED={speed}\n        {% elif (params.P|int) == 3 %}\n          SET_FAN_SPEED FAN=filterfan SPEED={speed}\n        {% else %}\n          SET_FAN_SPEED FAN=fan{params.P|int} SPEED={speed}\n        {% endif %}\n      {% else %}\n        {% if (params.P|int) == 0 %}\n          M106.1 S255\n        {% elif (params.P|int) == 2 %}\n          SET_FAN_SPEED FAN=sidefan SPEED=1\n        {% elif (params.P|int) == 3 %}\n          SET_FAN_SPEED FAN=filterfan SPEED=1\n        {% else %}\n          SET_FAN_SPEED FAN=fan{params.P|int} SPEED=1\n        {% endif %}\n      {% endif %}\n    {% endif %} \n\n    {% if params.T is defined %}\n      {% if (params.T|int) == -2 %}\n        {% if params.S is defined %}\n          {% set speed = 0.003921*params.S|int %}\n          SET_FAN_SPEED FAN=filterfan SPEED={speed}\n        {% else %}\n          SET_FAN_SPEED FAN=filterfan SPEED=1\n        {% endif %}\n      {% endif %}\n    {% endif %}\n\n    {% if params.P is undefined %}\n      {% if params.T is undefined %}\n        {% if params.S is defined %}\n          M106.1 S{params.S|int}\n        {% else %}\n          M106.1 S255\n        {% endif %}\n      {% endif %}\n    {% endif %}\n\n[gcode_macro M107]\nrename_existing: M107.1\ngcode:  \n    M106.1 S0\n\n\n########################################\n# Temperature Macros\n########################################\n# Wait for Hotend Temperature\n[gcode_macro M109]\nrename_existing: M109.1\ngcode:\n    #Parameters\n    {% set s = params.S|float %}\n\n    M104 {% for p in params %}{'%s%s' % (p, params[p])}{% endfor %}                                              ; Set hotend temp\n    {% if s != 0 %}\n        TEMPERATURE_WAIT SENSOR=extruder MINIMUM={s} MAXIMUM={s+1}                                               ; Wait for hotend temp (within 1 degree)\n    {% endif %}\n\n\n# PID autotune\n[gcode_macro M303]\ngcode:\n    {% if params.E is defined %}\n     {% if params.S is defined %}\n        {% if (params.E|int)==-1 %} \n         PID_CALIBRATE HEATER=heater_bed TARGET={params.S|int}\n        {% endif %}\n        {% if (params.E|int)==0 %}\n         PID_CALIBRATE HEATER=extruder TARGET={params.S|int}\n        {% endif %}\n     {% endif %}\n  {% endif %}\n\n\n# Set chamber temperature\n[gcode_macro M141]\ngcode:\n    {% if printer[\"heater_generic chamber\"] is defined %}\n        {% set chamber_target_temp = params.S|float %}\n        SET_HEATER_TEMPERATURE HEATER=chamber TARGET={([chamber_target_temp, 65]|min)}\n    {% endif %}\n\n\n# Set wait chamber temperature\n[gcode_macro M191]\ngcode:\n    {% set chamber_target_temp = params.S|float %}\n\n    {% if chamber_target_temp == 0 %}\n        M118 Chamber heater off\n    {% else %}\n        M141 S{chamber_target_temp}\n        TEMPERATURE_WAIT SENSOR=\"heater_generic chamber\" MINIMUM={([chamber_target_temp, 60]|min)-2} MAXIMUM={chamber_target_temp + 5}  \n        M118 Chamber at target temperature\n    {% endif %}\n\n\n########################################\n# Sound Macros\n########################################\n[gcode_macro BEEP]\ngcode:\n    # Parameters\n    {% set i = params.I|default(1)|int %}                                                                        ; Iterations (number of times to beep).\n    {% set dur = params.DUR|default(100)|int %}                                                                  ; Duration/wait of each beep in ms. Default 100ms.\n\n    {% if printer[\"output_pin sound\"].value|int == 1 %}\n        {% for iteration in range(i|int) %}\n            SET_PIN PIN=buzzer VALUE=1\n            G4 P{dur}\n            SET_PIN PIN=buzzer VALUE=0\n            G4 P{dur}\n        {% endfor %}\n    {% endif %}\n\n\n[gcode_macro beep_on]\ngcode:\n    SET_PIN PIN=buzzer VALUE=1\n\n\n[gcode_macro beep_off]\ngcode:\n    SET_PIN PIN=buzzer VALUE=0\n\n\n########################################\n# Z-height Macros\n########################################\n# Bed Leveling (Unified)\n[gcode_macro G29]\nvariable_k:1\ngcode:\n    {% if k|int==1 %}\n        BED_MESH_CLEAR                                                                                           ; Clear levelling data\n        BED_MESH_CALIBRATE ADAPTIVE=1 ADAPTIVE_MARGIN=5                                                          ; Start adaptive meshing\n    {% endif %}   \n\n\n# Babystep\n[gcode_macro M290]\ngcode:\n   SET_GCODE_OFFSET Z_ADJUST={params.Z}\n\n\n########################################\n# Tuning Macros\n########################################\n[gcode_macro SHAPER_CALIBRATE]\nrename_existing: RESHAPER_CALIBRATE\ngcode:\n    RESHAPER_CALIBRATE FREQ_START=30 FREQ_END=130\n\n\n# Linear Advance Factor\n[gcode_macro M900]\ngcode:\n    {% if params.K is defined %} \n          SET_PRESSURE_ADVANCE ADVANCE={params.K}\n    {% endif %}  \n    {% if params.T is defined %}    \n       SET_PRESSURE_ADVANCE SMOOTH_TIME={params.T}\n    {% endif %} \n\n\n# Set Starting Acceleration\n[gcode_macro M204]\nrename_existing: M99204\ngcode:\n    {% if params.S is defined %}\n        {% set s = params.S|float %}\n    {% endif %}\n    {% if params.P is defined %}\n    {% if params.T is defined %}\n        {% set s = [params.P|float ,params.T|float] | min %}\n    {% endif %}\n    {% endif %}\n\n    SET_VELOCITY_LIMIT ACCEL={s}\n    SET_VELOCITY_LIMIT ACCEL_TO_DECEL={s/2}\n\n\n# Bed leveling\n# For more information, see https://www.klipper3d.org/Manual_Level.html#adjusting-bed-leveling-screws-using-the-bed-probe\n[gcode_macro LEVEL_BED]\ndescription: \"Measure bed and calculate screw adjustments for manual bed leveling\"\ngcode:\n    G28                                                                                                         ; Home all\n    SCREWS_TILT_CALCULATE                                                                                       ; Perform measurements and output screw adjustments\n\n\n# Probe Calibration\n# For more information, see https://www.klipper3d.org/Probe_Calibrate.html\n[gcode_macro CALIBRATE_Z_OFFSET]\ndescription: \"Calibrate the Z offset using the probe\"\ngcode:\n    {% set max_x = printer.configfile.config[\"stepper_x\"][\"position_max\"]|float %}\n    {% set max_y = printer.configfile.config[\"stepper_y\"][\"position_max\"]|float %}\n\n    G28                                                                                                         ; Home all\n    G0 Z10                                                                                                      ; Increase z clearance\n    G0 X{max_x/2} Y{max_y-40} F6000                                                                             ; Move to bed center \n    PROBE_CALIBRATE                                                                                             ; Perform a probe calibration\n\n\n# Nozzle PID tuning\n# For more information, see https://www.klipper3d.org/Config_checks.html#calibrate-pid-settings\n[gcode_macro NOZZLE_PID_TUNE]\ndescription: \"Perform PID tuning for the nozzle heater\"\ngcode:\n    PID_CALIBRATE HEATER=extruder TARGET=220                                                                    ; PID tune the nozzle\n\n\n# Bed PID tuning\n# For more information, see https://www.klipper3d.org/Config_checks.html#calibrate-pid-settings\n[gcode_macro BED_PID_TUNE]\ndescription: \"Perform PID tuning for the bed heater\"\ngcode:\n    PID_CALIBRATE HEATER=heater_bed TARGET=80                                                                   ; PID tune the bed\n\n\n########################################\n# Macros for display functionallity\n########################################\n[gcode_macro INPUT_SHAPING_CALIBRATE]\ndescription: \"Perform Input Shaping calibration and save the results to printer.cfg\"\ngcode:\n    SHAPER_CALIBRATE                                                                                            ; Step 1: Perform the Input Shaping calibration\n    PAUSE                                                                                                       ; Step 2: Pause to allow the calibration to complete\n    SAVE_CONFIG                                                                                                 ; Step 3: Save the configuration to printer.cfg\n    RESTART                                                                                                     ; Step 4: Restart the firmware to apply the new settings\n\n"
  },
  {
    "path": "config_section/X-Plus3/printer.cfg",
    "content": "# X-Plus3 config created by Phil1988(github)/coco.33(discord) on 20.12.2024\n# For more information check out my wiki: https://github.com/Phil1988/FreeDi/wiki\n\n\n#####################################################################\n# Kinematics\n#####################################################################\n[printer]\nkinematics:corexy\nmax_velocity: 600\nmax_accel: 20000\nmax_z_velocity: 20\nmax_z_accel: 500\nsquare_corner_velocity: 8\n\n\n#####################################################################\n# Motherboard and periphery\n#####################################################################\n[temperature_sensor Mainboard_RK3328]\nsensor_type: temperature_host\nmin_temp: 10\nmax_temp: 100\n\n[mcu]\nserial: /dev/ttyS0\nrestart_method: command\nbaud: 500000\n\n[temperature_sensor Mainboard_STM32F402]\nsensor_type: temperature_mcu\nsensor_mcu: mcu\n\n[mcu Toolhead]\nserial: /dev/serial/by-id/usb-Klipper_rp2040_C5DA4D951E145858-if00\n\n[temperature_sensor Toolhead_STM32F103XE]\nsensor_type: temperature_mcu\nsensor_mcu: Toolhead\nmin_temp: 0\nmax_temp: 100\n\n\n#####################################################################\n# Features\n#####################################################################\n# For saving GCODE files\n[virtual_sdcard]\npath: ~/printer_data/gcodes\non_error_gcode: CANCEL_PRINT\n\n# For enabling pause/resume\n[pause_resume]\n\n# Activating exclude objects feature\n[display_status]\n[exclude_object]\n\n# Expanding idle timeout\n[idle_timeout]\ntimeout: 5400   ; 90min timeout\n\n# Activating GCODE arc feature\n[gcode_arcs]\nresolution: 1.0\n\n# Allowing free move (can be dangerous!)\n[force_move]\nenable_force_move: True\n\n# Activating responses\n[respond]\ndefault_type: echo\n\n#####################################################################\n# FreeDi\n#####################################################################\n[include freedi.cfg] \n\n\n#####################################################################\n# Macros\n#####################################################################\n[include macros.cfg]\n\n\n#####################################################################\n# Input shaping\n#####################################################################\n[resonance_tester]\naccel_chip:adxl345\nprobe_points:\n    140, 140, 10\naccel_per_hz: 75\nsweeping_period: 0\nmax_smoothing: 0.5\n\n[adxl345]\ncs_pin: Toolhead:gpio13\nspi_software_sclk_pin: Toolhead:gpio14\nspi_software_mosi_pin: Toolhead:gpio15\nspi_software_miso_pin: Toolhead:gpio12\naxes_map: -x, z, -y\n\n[input_shaper]\nshaper_type_x: mzv\nshaper_freq_x: 57.6\nshaper_type_y: mzv\nshaper_freq_y: 46.6\n\n\n#####################################################################\n# Hotend\n#####################################################################\n[extruder]\nstep_pin: Toolhead:gpio5\ndir_pin: Toolhead:gpio4\nenable_pin: !Toolhead:gpio10\nrotation_distance: 53.5\ngear_ratio: 1628:170\t\t\t\t\nmicrosteps: 16\nfull_steps_per_rotation: 200\nnozzle_diameter: 0.400\nfilament_diameter: 1.75\nmin_temp: 0\nmax_temp: 360\nmin_extrude_temp: 170\nsmooth_time: 0.000001\nstep_pulse_duration: 0.000002\n\nheater_pin: Toolhead:gpio0\nsensor_type:MAX6675\nsensor_pin: Toolhead:gpio17\nmax_power: 1.0\ncontrol: pid  \npid_Kp: 24.737\npid_Ki: 10.994\npid_Kd: 13.915\n\nspi_speed: 100000\nspi_software_sclk_pin: Toolhead:gpio18\nspi_software_mosi_pin: Toolhead:gpio19\nspi_software_miso_pin: Toolhead:gpio16\n\npressure_advance: 0.032\npressure_advance_smooth_time: 0.03\nmax_extrude_cross_section:500\ninstantaneous_corner_velocity: 10.000\nmax_extrude_only_distance: 500.0\nmax_extrude_only_velocity: 5000\nmax_extrude_only_accel: 2000\n\n[verify_heater extruder]\nmax_error: 120\ncheck_gain_time: 20\nhysteresis: 5\nheating_gain: 1\n\n\n#####################################################################\n# Heated bed\n#####################################################################\n[heater_bed]\nheater_pin: PC8\nsensor_type: NTC 100K MGB18-104F39050L32\nsensor_pin: PA0\nmax_power: 1.0\ncontrol: pid\npid_kp: 64.431\npid_ki: 2.845\npid_kd: 364.839\nmin_temp: -50\nmax_temp: 125\npwm_cycle_time: 0.02 # for 50Hz line power \n#pwm_cycle_time: 0.016 # for 60Hz line power\n\n[verify_heater heater_bed]\nmax_error: 200\ncheck_gain_time: 360\nhysteresis: 5\nheating_gain: 1\n\n\n#####################################################################\n# Bed mesh\n#####################################################################\n[bed_mesh]\nspeed: 150               \nhorizontal_move_z: 2.6   \nmesh_min: 28,8        \nmesh_max: 270,265     \nprobe_count: 9,9     \nalgorithm: bicubic\nbicubic_tension: 0.2\nmesh_pps: 4, 4\n\n\n#####################################################################\n# Probe\n#####################################################################\n#!# Pay attention to this section and compare it with your stock backup config\n[probe]\npin: ^!Toolhead:gpio21\nx_offset: 28\ny_offset: 4.4\nz_offset: 1.549             #!# change this to 0 if you get a \"Probe triggered prior to movement\" - Error\nspeed: 5\nsamples: 2\nsamples_result: average\nsample_retract_dist: 0.7\nsamples_tolerance: 0.08\nsamples_tolerance_retries: 3\n\n#!# This is for users of the first batches x-series with a BLtouch. Please uncomment if you have one\n#!# Pay attention to this section and compare it with your stock backup config\n#[bltouch]\n#sensor_pin: ^Toolhead:gpio21\n#control_pin: Toolhead:gpio11\n#stow_on_each_sample: False\n#x_offset: 28\n#y_offset: 4.4\n#z_offset: 0.0\n#speed: 5\n#samples: 2\n#samples_result: average\n#sample_retract_dist: 3.0\n#samples_tolerance: 0.08\n#samples_tolerance_retries:3\n\n\n#####################################################################\n# Heated chamber\n#####################################################################\n[heater_generic chamber]\nheater_pin: PB10\nmax_power:1.0\nsensor_type:NTC 100K MGB18-104F39050L32\nsensor_pin: PA1\ncontrol: watermark\nmax_delta: 0.5\nmin_temp:-100\nmax_temp:70\n\n[verify_heater chamber]\nmax_error: 300\ncheck_gain_time:480\nhysteresis: 5\nheating_gain: 1\n\n\n########################################\n# Filament runout sensor\n########################################\n[filament_switch_sensor filament]\nswitch_pin: !PC1\npause_on_runout: True\nrunout_gcode:\n            M118 Filament run out!\nevent_delay: 3.0\npause_delay: 0.5\n\n\n#####################################################################\n# Fans\n#####################################################################\n## Part cooling fan \n# [fan_generic partfan]\n# pin: Toolhead:gpio2\n# max_power: 1.0\n# cycle_time: 0.0100\n# hardware_pwm: false\n# kick_start_time: 0.200\n# off_below: 0.08\n# shutdown_speed: 0\n[fan]\npin: Toolhead:gpio2\nmax_power: 1.0\ncycle_time: 0.0100\nhardware_pwm: false\nkick_start_time: 0.200\noff_below: 0.08\nshutdown_speed: 0.0\n\n## Big side radial turbo fan\n[fan_generic sidefan]\npin: PA8\nmax_power: 1.0\ncycle_time: 0.0100\nhardware_pwm: false\nkick_start_time: 0.250\noff_below: 0.3\nshutdown_speed: 0\n\n## Activated charcoal blowing fan\n[fan_generic filterfan]\npin: PC9\nmax_power: 1.0\ncycle_time: 0.0100\nhardware_pwm: false\nkick_start_time: 0.200\noff_below: 0.3\nshutdown_speed: 0\n\n## Cold end and toolhead housing fans\n[heater_fan hotend_fan]\npin: Toolhead:gpio1\nmax_power: 1.0\nshutdown_speed:1.0\nkick_start_time: 0.5\nheater: extruder\nheater_temp: 50.0\nfan_speed: 1.0\noff_below: 0\n\n#!# Delete the next section if your stock backup config doesnt have it\n# Toolhead cooling fan\n[heater_fan hotend_fan2]\npin: Toolhead:gpio20\nmax_power: 1.0\nshutdown_speed:1.0\nkick_start_time: 0.5\nheater: extruder\nheater_temp: 50.0\nfan_speed: 1.0\noff_below: 0\n\n#!# Delete the next section if your stock backup config doesnt have it\n## Controllable Mainboard cooling fan\n[temperature_fan Mainboard_fan]\nsensor_type: temperature_host \npin: PC4        \nmax_power: 1.0  \ncycle_time: 0.01\nsensor_type: temperature_combined\nsensor_list: temperature_sensor Mainboard_RK3328, temperature_sensor Mainboard_STM32F402\ncombination_method: max                                           # use the maximum reading of the sensors\nmaximum_deviation: 999.9                                          # we don't care about the difference in temperature\nshutdown_speed: 0.0\nkick_start_time: 0.4\noff_below: 0.19\nmin_temp: 0\nmax_temp: 85.0  \ntarget_temp: 42.0\nmin_speed: 0\nmax_speed: 1.0\ncontrol: pid\npid_deriv_time: 2.0\npid_Kp: 2.0\npid_Ki: 5.0\npid_Kd: 0.5\n\n\n#####################################################################\n# Light\n#####################################################################\n## caselight LEDs\n[output_pin caselight]\npin: PC7\npwm: true\ncycle_time: 0.0100\nshutdown_value:0\nvalue:1\n\n\n#####################################################################\n# Buzzer\n#####################################################################\n## Buzzer\n[output_pin buzzer]\npin: PA2\npwm: false\nshutdown_value:0\nvalue:0\n\n[output_pin sound]\npin: PA13\nvalue:0\n\n\n#####################################################################\n# Power outage shutdown\n#####################################################################\n[output_pin pwc]\npin: PA3\npwm: False\nvalue: 1\nshutdown_value: 1\n\n\n#####################################################################\n# Drives\n#####################################################################\n[stepper_x]\nstep_pin: PB4\ndir_pin: PB3\nenable_pin: !PB5\nmicrosteps: 16\nrotation_distance: 39.94\nfull_steps_per_rotation: 200\nendstop_pin: tmc2209_stepper_x:virtual_endstop\nposition_min: -11\nposition_endstop: -11\nposition_max: 280\nhoming_speed: 40\nhoming_retract_dist: 0\nhoming_positive_dir: False\nstep_pulse_duration: 0.000002\n\n[stepper_y]\nstep_pin: PC14\ndir_pin: PC13\nenable_pin: !PC15\nmicrosteps: 16\nrotation_distance: 39.96\nfull_steps_per_rotation: 200\nendstop_pin: tmc2209_stepper_y:virtual_endstop\nposition_min: -24\nposition_endstop: -24\nposition_max: 280\nhoming_speed: 40\nhoming_retract_dist: 0\nhoming_positive_dir: False\nstep_pulse_duration: 0.000002\n\n[stepper_z]\nstep_pin: PC10\ndir_pin: PA15\nenable_pin: !PC11\nmicrosteps: 16\nrotation_distance: 8\nfull_steps_per_rotation: 200\nendstop_pin: probe:z_virtual_endstop#!PC3\nposition_max: 280\nposition_min: -2\nhoming_speed: 10\nhoming_retract_dist: 8.0\nsecond_homing_speed: 5\nhoming_positive_dir: false\nstep_pulse_duration: 0.000002\n\n\n#####################################################################\n# Steppers configuration\n#####################################################################\n[tmc2209 extruder]\nuart_pin: Toolhead:gpio6\ninterpolate: True\nrun_current: 0.714              #!# Pay attention to this value and compare it with your stock backup config\nstealthchop_threshold: 0\n\n[tmc2209 stepper_x]\nuart_pin: PD2\nrun_current:1.07                #!# Pay attention to this value and compare it with your stock backup config\ninterpolate: True\nstealthchop_threshold: 0\ndiag_pin: ^PB8\ndriver_SGTHRS: 85\n\n[tmc2209 stepper_y]\nuart_pin: PB9\nrun_current: 1.07               #!# Pay attention to this value and compare it with your stock backup config\ninterpolate: True\nstealthchop_threshold: 0\ndiag_pin: ^PC0\ndriver_SGTHRS: 85\n\n[tmc2209 stepper_z]\nuart_pin: PC5\nrun_current: 0.285              #!# Pay attention to this value and compare it with your stock backup config\ninterpolate: True\nstealthchop_threshold: 1200\n\n#####################################################################\n# Screws tilt adjust\n#####################################################################\n[screws_tilt_adjust] \nhorizontal_move_z: 5\nscrew_thread: CCW-M4\nspeed: 300\n\nscrew1: 22, 45\nscrew1_name: front left screw\nscrew2: 202, 45\nscrew2_name: front right screw\nscrew3: 202, 224\nscrew3_name: rear right screw\nscrew4: 22, 224\nscrew4_name: rear left screw\n"
  },
  {
    "path": "config_section/X-Smart3/macros.cfg",
    "content": "#####################################################################\n# Advanced CHAMBER_TEMP_CONTROLLER\n#####################################################################\n\n[gcode_macro SET_PRINT_STATS_INFO]\nrename_existing: BASE_SET_PRINT_STATS_INFO_BASE\ngcode:\n    #TIMELAPSE_TAKE_FRAME\n    BASE_SET_PRINT_STATS_INFO_BASE {rawparams}    \n    \n#####################################################################\n# Homing modification\n#####################################################################\n[gcode_macro G28]\nrename_existing: G28.1\ngcode:\n    {% set reduced_current_x = 0.6 %}\n    {% set reduced_current_y = 0.6 %}\n    {% set home_all = ('X' in rawparams.upper() and 'Y' in rawparams.upper() and 'Z' in rawparams.upper()) or \n                      ('X' not in rawparams.upper() and 'Y' not in rawparams.upper() and 'Z' not in rawparams.upper()) %}\n    {% set home_current_x = printer.configfile.settings['tmc2209 stepper_x'].run_current * reduced_current_x %}\n    {% set home_current_y = printer.configfile.settings['tmc2209 stepper_y'].run_current * reduced_current_y %}\n\n    {% set init_XY_move = 30 %}\n    #{% set y_init_move = 5 %}\n    {% set z_clearance = 2 %}\n\n    {% set home_all_final_position_x = printer.toolhead.axis_maximum.x / 2 %}\n    {% set home_all_final_position_y = printer.toolhead.axis_maximum.y - 40 %}\n    {% set home_all_final_position_z = 10 %}\n\n    # If homing should at least move X or Y axis\n    {% if home_all or 'X' in rawparams.upper() or 'Y' in rawparams.upper() %}     \n        # Check if Z is homed\n        {% if 'z' in printer.toolhead.homed_axes %}\n            {% set Z_axis_was_homed = true %}                                                                       ; Set Z_axis_was_homed to true if Z is already homed\n            G91                                                                                                     ; Use relative positioning\n            G1 Z2 F600                                                                                              ; Move bed down\n            G90                                                                                                     ; Use absolute positioning\n        {% else %}\n            {% set Z_axis_was_homed = false %}                                                                      ; Set Z_axis_was_homed to false if Z is not homed\n            FORCE_MOVE STEPPER=stepper_z DISTANCE={z_clearance} VELOCITY=10                                         ; Move bed down\n        {% endif %}\n    {% endif %}\n\n    {% if home_all or 'X' in rawparams.upper() or 'Y' in rawparams.upper() %} \n        G91                                                                                                         ; Use relative positioning\n        FORCE_MOVE STEPPER=stepper_x DISTANCE={init_XY_move} VELOCITY=40                                            ; Move X a little before homing\n        SET_KINEMATIC_POSITION X={printer.toolhead.position.x + (init_XY_move/2)}                                   ; Compensate the FORCE_MOVE position \n        SET_KINEMATIC_POSITION Y={printer.toolhead.position.y + (init_XY_move/2)}                                   ; Compensate the FORCE_MOVE position \n        G90                                                                                                         ; Use absolute positioning\n    {% endif %}\n\n    # Home Y\n    {% if home_all or 'Y' in rawparams.upper() %}\n        SET_TMC_CURRENT STEPPER=stepper_x CURRENT={home_current_y}                                                  ; Lower motor current\n        SET_TMC_CURRENT STEPPER=stepper_y CURRENT={home_current_y}                                                  ; Lower motor current\n        G28.1 Y                                                                                                     ; Home Y\n        SET_TMC_CURRENT STEPPER=stepper_x CURRENT={printer.configfile.settings['tmc2209 stepper_x'].run_current}    ; Set motor current to the previous value\n        SET_TMC_CURRENT STEPPER=stepper_y CURRENT={printer.configfile.settings['tmc2209 stepper_y'].run_current}    ; Set motor current to the previous value\n        G1 Y10 F1200                                                                                                ; Move Y-axis slightly\n    {% endif %}\n    \n    # Home X\n    {% if home_all or 'X' in rawparams.upper() %}        \n        SET_TMC_CURRENT STEPPER=stepper_x CURRENT={home_current_x}                                                  ; Lower motor current\n        SET_TMC_CURRENT STEPPER=stepper_y CURRENT={home_current_x}                                                  ; Lower motor current\n        G28.1 X                                                                                                     ; Home X\n        SET_TMC_CURRENT STEPPER=stepper_x CURRENT={printer.configfile.settings['tmc2209 stepper_x'].run_current}    ; Set motor current to the previous value\n        SET_TMC_CURRENT STEPPER=stepper_y CURRENT={printer.configfile.settings['tmc2209 stepper_y'].run_current}    ; Set motor current to the previous value\n        G1 X10 F1200                                                                                                ; Move X-axis slightly\n    {% endif %}\n\n    # Raise the bed again if only X or only Y axes were homed\n    {% if not (home_all or 'Z' in rawparams.upper()) %}\n        {% if Z_axis_was_homed %}\n            G91                                                                                                     ; Use relative positioning\n            G1 Z-2 F600                                                                                             ; Raise the bed back again\n            G90                                                                                                     ; Use absolute positioning\n        {% else %}\n            FORCE_MOVE STEPPER=stepper_z DISTANCE=-{z_clearance} VELOCITY=10                                        ; Raise the bed back again\n        {% endif %}\n    {% endif %}\n\n    # Home Z\n    {% if home_all or 'Z' in rawparams.upper() %}\n        G28.1 Z                                                                                                     ; Home Z\n        G90                                                                                                         ; Set absolute positioning\n        G1 Z{home_all_final_position_z}                                                                             ; Move bed down   \n    {% endif %}\n\n    # Move to the final position if all axes were homed\n    {% if home_all %}\n        G90                                                                                                         ; Set absolute positioning\n        G1 X{home_all_final_position_x} Y{home_all_final_position_y} Z{home_all_final_position_z} F7800             ; Move to the rear center\n    {% endif %}\n\n\n# Unconditional stop\n[gcode_macro M0]\ngcode:\n    PAUSE\n\n\n# Pause SD print\n[gcode_macro M25]\nrename_existing: M9925\ngcode:\n    PAUSE\n\n\n########################################\n# Basic Macros\n########################################\n# Flag macro to use STATIC_MESH usage instead of KAMP (needed make this function work from printjob selection on the LCD)\n[gcode_macro NEXT_PRINT_STATIC_MESH]\ndescription: Forces the NEXT print to use 'STATIC_MESH' instead of KAMP.\ngcode:\n    {% if \"STATIC_MESH\" in printer.bed_mesh.profiles %}\n        SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=force_static_mesh VALUE=True\n        {action_respond_info(\"The NEXT print will use 'STATIC_MESH'.\")}\n        M118 The NEXT print will use the STATIC_MESH.\n    {% else %}\n        {action_respond_info(\"WARNING: No mesh named 'STATIC_MESH' found. Please save one first (BED_MESH_PROFILE SAVE=STATIC_MESH).\")}\n        M118 WARNING: No mesh named STATIC_MESH found. Please save one first (BED_MESH_PROFILE SAVE=STATIC_MESH).\n    {% endif %}\n\n\n[gcode_macro PRINT_START]\n# Use PRINT_START for the slicer starting script\ndescription: Start printing\ngcode:\n    {% set bed_target_temp = params.BED|default(0)|int %}\n    {% set hotend_target_temp = params.HOTEND|default(0)|int %}\n\n    CLEAR_PAUSE                                                                                                    ; Clear existing pause states\n    BED_MESH_CLEAR                                                                                                 ; Clear previous adaptive mesh\n    SET_TEMPERATURE_FAN_TARGET TEMPERATURE_FAN=Mainboard_fan TARGET=1                                              ; Decrease the mainboard target temp to fully turn the fan on\n\n    {% set KAMP_deactivated = printer[\"gcode_macro PRINT_START\"].force_static_mesh %}                              ; Check if KAMP is deactivated for this print\n    SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=force_static_mesh VALUE=False                                    ; Auto-reset the variable immediately for the next print after this one\n\n    # Check if advanced mode (any parameter was passed)\n    {% if bed_target_temp > 0 or hotend_target_temp > 0 %}\n        {% set bed_center_x = printer.configfile.config[\"stepper_x\"][\"position_max\"]|float / 2 %}\n        {% set bed_center_y = printer.configfile.config[\"stepper_y\"][\"position_max\"]|float / 2 %}\n\n        {% set start_position_x = printer.toolhead.axis_maximum.x / 2 %}\n        {% set start_position_y = printer.toolhead.axis_maximum.y - 20 %}\n        {% set start_position_z = 10 %}\n\n        M140 S{bed_target_temp}                                                                                    ; Set bed temperature\n        G28                                                                                                        ; Home all axes\n        M190 S{bed_target_temp}                                                                                    ; Set and wait for bed temperature  \n        G90                                                                                                        ; Set absolute positioning\n        G1 X{start_position_x} Y{start_position_y} Z{start_position_z} F7800                                       ; Move to start position\n        G28 Z                                                                                                      ; Home Z again for to compensate bed expansion    \n    {% endif %}\n\n    {% if KAMP_deactivated %}\n        {% if \"STATIC_MESH\" in printer.bed_mesh.profiles %}                                                        ; Check if the spicific STATIC_MESH exists\n            M118  Loading 'STATIC_MESH' instead of KAMP.\n            BED_MESH_PROFILE LOAD=STATIC_MESH\n        {% else %}                                                                                                 ; Fallback to KAMP if STATIC_MESH not found\n            M118 ERROR: 'STATIC_MESH' not found! Using fallback: KAMP Adaptive Mesh.\n            BED_MESH_CLEAR                                                                                         ; Clear previous adaptive mesh\n            BED_MESH_CALIBRATE PROFILE=adaptive ADAPTIVE=1                                                         ; Start adaptive meshing\n        {% endif %}\n    {% else %}                                                                                                     ; Standard operation\n        {% if printer.toolhead.homed_axes|length < 3 %}\n            G28\n        {% endif %}\n        BED_MESH_CLEAR                                                                                             ; Clear previous adaptive mesh\n        BED_MESH_CALIBRATE PROFILE=adaptive ADAPTIVE=1                                                             ; Start adaptive meshing\n    {% endif %}\n\n    # Check if advanced mode (parameter was passed)\n    {% if hotend_target_temp %}                                                                                    ; Set hotend temperature now (prevent oozing during bed/chamber heating)   \n        M109 S{hotend_target_temp}                                                                                 ; Set and wait for hotend temperature \n    {% endif %}\n\n\n[gcode_macro PRINT_END]\ngcode:\n    {% set max_x = printer.configfile.config[\"stepper_x\"][\"position_max\"]|float %}\n    {% set max_y = printer.configfile.config[\"stepper_y\"][\"position_max\"]|float %}\n    {% set max_z = printer.configfile.config[\"stepper_z\"][\"position_max\"]|float %}\n        {% set current_extruder_temp = printer.extruder.temperature|float %}\n    {% set min_extrusion_temp = printer.configfile.config[\"extruder\"][\"min_extrude_temp\"]|float %}\n    {% set z_clearance = 50 %}\n    {% set z_hop = 2  %}\n\n    {% if (printer.toolhead.position.z + z_clearance) < max_z %}\n        {% set z_hop = 2  %}\n    {% else %}\n        {% set z_hop = 0 %}\n    {% endif %}\n\n    M106 P0 S0                                                                                                      ; Turn off part cooling fan\n    #M106 P2 S0                                                                                                     ; Turn off side fan - dont use for X-Smart3\n    M106 P3 S0                                                                                                      ; Turn off activated charcoal fan\n\n    M104 S0                                                                                                         ; Turn off hotend\n    M140 S0                                                                                                         ; Turn off heated bed\n    M141 S0                                                                                                         ; Turn off heated chamber\n\n    G91                                                                                                             ; Relative positioning\n    {% if current_extruder_temp >= min_extrusion_temp + 5 %}                                                        ; Check if the hotend is hot enough to perform a retraction (with a small gap)  \n        G0 E-4.0 F300                                                                                               ; Retract filament\n    {% endif %}\n    G0 Z{z_hop} F3600                                                                                               ; Move bed down a bit\n    G90                                                                                                             ; Absolute positioning\n    G0 X{max_x/2} Y{max_y-40} F20000                                                                                ; Move nozzle to remove stringing\n    _Z_CLEARANCE DISTANCE={z_clearance}                                                                             ; Lower bed\n    M400                                                                                                            ; Wait for buffer to clear\n    G92 E0                                                                                                          ; Zero the extruder\n\n    M220 S100                                                                                                       ; Set feedrate (speed percentage) back to 100%\n    M221 S100                                                                                                       ; Set flow percentage back to 100%\n\n    SET_IDLE_TIMEOUT TIMEOUT={printer.configfile.settings.idle_timeout.timeout}                                     ; Set timeout back to configured value\n    CLEAR_PAUSE                                                                                                     ; Ensure pause state is cleared if applicable\n\n    M84                                                                                                             ; Disable steppers\n    SET_TEMPERATURE_FAN_TARGET TEMPERATURE_FAN=Mainboard_fan TARGET=45                                              ; Reset the mainboard fan temp\n    BEEP I=2 DUR=500                                                                                                ; Alert at the end of the print (if sound is enabled)\n\n\n[gcode_macro PAUSE]\nrename_existing: BASE_PAUSE\ngcode:\n    {% set z_hop = params.Z|default(30)|int %}                                                                     ; Z hop amount\n\n    {% if printer['pause_resume'].is_paused|int == 0 %}     \n        SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=zhop VALUE={z_hop}                                                ; Set Z hop variable for reference in resume macro\n        SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=etemp VALUE={printer['extruder'].target}                          ; Set hotend temperature variable for reference in resume macro\n        SAVE_GCODE_STATE NAME=PAUSE                                                                                ; Save current position for resume\n        BASE_PAUSE                                                                                                 ; Pause print\n        {% if (printer.gcode_move.position.z + z_hop) < printer.toolhead.axis_maximum.z %}                         ; Check that Z hop doesn't exceed Z max\n            G91                                                                                                    ; Use Relative positioning\n            G1 Z{z_hop} F600                                                                                       ; Raise Z up by Z hop amount\n        {% else %}\n            SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=zhop VALUE=0                                                  ; Set Z hop to 0 if exceeds max\n        {% endif %}\n        SAVE_GCODE_STATE NAME=PAUSEPARK2\n        G90                                                                                                        ; Absolute positioning\n        G1 X{printer.toolhead.axis_maximum.x/2} Y{printer.toolhead.axis_maximum.y-40} F6000                        ; Park toolhead  at rear center\n        SAVE_GCODE_STATE NAME=PAUSEPARK                                                                            ; Save parked position in case toolhead is moved during the pause (otherwise the return zhop can error)\n        M104 S0                                                                                                    ; Turn off hotend\n        SET_IDLE_TIMEOUT TIMEOUT=43200                                                                             ; Set timeout to 12 hours\n        SET_STEPPER_ENABLE STEPPER=extruder enable=0                                                               ; Disable extruder stepper\n    {% endif %}\n\n\n[gcode_macro RESUME]\nrename_existing: BASE_RESUME\nvariable_zhop: 0\nvariable_etemp: 0\ngcode:\n    {% set extrusion_length = params.E|default(2.5)|int %}                                                                        ; Hotend prime amount (in mm)\n\n    {% if printer['pause_resume'].is_paused|int == 1 %}\n        \n        {% if \"z\" not in printer.toolhead.homed_axes %}                                                            ; check if z position is lost\n            {action_raise_error(\"ERROR: Z-axixs lost its position (Idle-Timeout)! Resume not possible - Print should be aborted.\")}\n        {% endif %}\n        \n        SET_IDLE_TIMEOUT TIMEOUT={printer.configfile.settings.idle_timeout.timeout}                                ; Set idle timeout back to configured value\n\n        # If X/Y position lost: Give Z-clearance for homing X/Y that will be done by PRIME_NOZZLE                                                                                     \n        {% if \"x\" not in printer.toolhead.homed_axes or \"y\" not in printer.toolhead.homed_axes %}                  ; If X/Y position is lost, but z is still OK\n            G91                                                                                                    ; Relative positioning\n            G1 Z5 F600                                                                                             ; 5mm clearance for safe X/Y-Homing\n            G90                                                                                                    ; Absolute positioning\n        {% endif %}\n\n\n        {% if etemp > 0 %}\n            M109 S{etemp|int}                                                                                      ; Wait for hotend to heat up\n        {% endif %}\n        RESTORE_GCODE_STATE NAME=PAUSEPARK MOVE=1 MOVE_SPEED=150                                                   ; Restore back to parked position in case toolhead was moved during pause (otherwise the return zhop can error)  \n        G91                                                                                                        ; Relative positioning\n        M83                                                                                                        ; Relative extruder positioning\n        {% if printer[printer.toolhead.extruder].temperature >= printer.configfile.settings.extruder.min_extrude_temp %}\n            G1  E{extrusion_length} F900                                                                                          ; Prime nozzle\n        {% endif %}  \n        RESTORE_GCODE_STATE NAME=PAUSEPARK2 MOVE=1 MOVE_SPEED=150                           \n        RESTORE_GCODE_STATE NAME=PAUSE MOVE=1 MOVE_SPEED=10                                                        ; Restore position\n        BASE_RESUME                                                                                                ; Resume print\n        G90                                                                                                        ; Absolute positioning\n    {% endif %}\n\n\n[gcode_macro CANCEL_PRINT]\nrename_existing: BASE_CANCEL_PRINT\ngcode:\n\n    {% set max_z = printer.configfile.config[\"stepper_z\"][\"position_max\"]|float %}\n    {% if (printer.toolhead.position.z + 12) < max_z %}\n        {% set z_hop = 2  %}\n    {% else %}\n        {% set z_hop = 0 %}\n    {% endif %}\n\n    G91                                                                                                            ; Relative positioning\n    G1 Z{z_hop} F600                                                                                               ; Do a tiny z-hop\n    G90                                                                                                            ; Absolute positioning\n\n    G1 X{printer.toolhead.axis_maximum.x/2} Y{printer.toolhead.axis_maximum.y-40} F12000\n    CLEAR_PAUSE\n    SDCARD_RESET_FILE\n\n    PRINT_END\n    BASE_CANCEL_PRINT\n\n\n[gcode_macro _Z_CLEARANCE]\ndescription: Lower the bed to give some clearance\nvariable_default_distance: 40.0\ngcode:\n    {% set current_z_height = printer.toolhead.position.z %}\n    {% set max_z_height = printer.toolhead.axis_maximum.z %}\n    {% set distance = params.DISTANCE|default(variable_default_distance)|float %}\n    {% set target_z_height = current_z_height + distance %}\n\n    {% set min_z_param = params.MIN_Z|default(None) %}\n    {% if min_z_param is not none %}\n        {% set min_z = min_z_param|float %}\n        {% if target_z_height < min_z %}\n            {% set target_z_height = min_z %}\n        {% endif %}\n    {% endif %}\n\n    G90                                                                                                            ; Absolute positioning\n    G1 Z{ [target_z_height, max_z_height]|min }\n\n\n########################################\n#  Filament Macros\n########################################\n[gcode_macro UNLOAD_FILAMENT]\ndescription: Unloads filament from toolhead\ngcode:\n  {% set EXTRUDER_TEMP = params.TEMP|default(230)|int %}\n  {% set CURRENT_TEMP = printer.extruder.temperature|int %}\n  {% if CURRENT_TEMP < EXTRUDER_TEMP %}\n    M109 S{EXTRUDER_TEMP}                                                                                          ; heat up the hotend\n  {% endif %}  \n  SET_STEPPER_ENABLE STEPPER=extruder ENABLE=1                                                                     ; enable extruder stepper \n  M83                                                                                                              ; set extruder to relative mode\n  G1 E5 F150                                                                                                       ; extrude a small amount to elimate soften the filament\n  G1 E-8 F1800                                                                                                     ; quickly retract a small amount to elimate stringing\n  G4 P200                                                                                                          ; pause for a short amount of time\n  G1 E-50 F300                                                                                                     ; retract slowly the rest of the way\n  M400                                                                                                             ; wait for moves to finish\n  M118 Unload Complete!\n\n\n[gcode_macro LOAD_FILAMENT]\ndescription: Loads filament to toolhead\ngcode:\n  {% set EXTRUDER_TEMP = params.TEMP|default(230)|int %}\n  {% set CURRENT_TEMP = printer.extruder.temperature|int %}\n  {% if CURRENT_TEMP < EXTRUDER_TEMP %}\n    M109 S{EXTRUDER_TEMP}                                                                                          ; heat up the hotend\n  {% endif %}\n  SET_STEPPER_ENABLE STEPPER=extruder ENABLE=1                                                                     ; enable extruder stepper \n  M83                                                                                                              ; set extruder to relative mode\n  G1 E5 F120                                                                                                       ; feed filament\n  G1 E5 F300                                                                                                       ; feed filament\n  G1 E40 F600                                                                                                      ; feed filament\n  G1 E15 F300                                                                                                      ; feed filament\n  G1 E15 F120                                                                                                      ; feed filament\n  G4 P200                                                                                                          ; pause for a short amount of time\n  G1 E10 F90                                                                                                       ; feed filament\n  M400                                                                                                             ; wait for moves to finish\n  M118 Load Complete!\n\n\n# Filament runout sensor enable/disable\n[gcode_macro M8029]\ngcode:\n     {% if params.D is defined %}\n       {% if (params.D|int)==1 %} \n        SET_FILAMENT_SENSOR SENSOR=filament ENABLE=1\n       {% endif %}\n       {% if (params.D|int)==0 %} \n        SET_FILAMENT_SENSOR SENSOR=filament ENABLE=0\n       {% endif %}\n     {% endif %}\n\n\n########################################\n# Fan Macros\n########################################\n# Set Fan Speed macro\n# Mainly name castings for nicer web interface names and display functionality\n[gcode_macro M106]\nrename_existing: M106.1\ngcode:\n    {% if params.P is defined %}\n      {% if params.S is defined %}\n        {% set speed = 0.003921*params.S|int %}\n        {% if (params.P|int) == 0 %}\n          M106.1 S{params.S|int}\n        {% elif (params.P|int) == 2 %}\n          # fix for X-Smart 3 \"missing fan2\" -> dont do anything\n        {% elif (params.P|int) == 3 %}\n          SET_FAN_SPEED FAN=filterfan SPEED={speed}\n        {% else %}\n          SET_FAN_SPEED FAN=fan{params.P|int} SPEED={speed}\n        {% endif %}\n      {% else %}\n        {% if (params.P|int) == 0 %}\n          M106.1 S255\n        {% elif (params.P|int) == 2 %}\n          # fix for X-Smart 3 \"missing fan2\" -> dont do anything\n        {% elif (params.P|int) == 3 %}\n          SET_FAN_SPEED FAN=filterfan SPEED=1\n        {% else %}\n          SET_FAN_SPEED FAN=fan{params.P|int} SPEED=1\n        {% endif %}\n      {% endif %}\n    {% endif %} \n\n    {% if params.T is defined %}\n      {% if (params.T|int) == -2 %}\n        {% if params.S is defined %}\n          {% set speed = 0.003921*params.S|int %}\n          SET_FAN_SPEED FAN=filterfan SPEED={speed}\n        {% else %}\n          SET_FAN_SPEED FAN=filterfan SPEED=1\n        {% endif %}\n      {% endif %}\n    {% endif %}\n\n    {% if params.P is undefined %}\n      {% if params.T is undefined %}\n        {% if params.S is defined %}\n          M106.1 S{params.S|int}\n        {% else %}\n          M106.1 S255\n        {% endif %}\n      {% endif %}\n    {% endif %}\n\n[gcode_macro M107]\nrename_existing: M107.1\ngcode:  \n    M106.1 S0\n\n\n########################################\n# Temperature Macros\n########################################\n# Wait for Hotend Temperature\n[gcode_macro M109]\nrename_existing: M109.1\ngcode:\n    #Parameters\n    {% set s = params.S|float %}\n    \n    M104 {% for p in params %}{'%s%s' % (p, params[p])}{% endfor %}                                              ; Set hotend temp\n    {% if s != 0 %}\n        TEMPERATURE_WAIT SENSOR=extruder MINIMUM={s} MAXIMUM={s+1}                                               ; Wait for hotend temp (within 1 degree)\n    {% endif %}\n\n\n# PID autotune\n[gcode_macro M303]\ngcode:\n    {% if params.E is defined %}\n     {% if params.S is defined %}\n        {% if (params.E|int)==-1 %} \n         PID_CALIBRATE HEATER=heater_bed TARGET={params.S|int}\n        {% endif %}\n        {% if (params.E|int)==0 %}\n         PID_CALIBRATE HEATER=extruder TARGET={params.S|int}\n        {% endif %}\n     {% endif %}\n  {% endif %}\n\n\n########################################\n# Sound Macros\n########################################\n[gcode_macro BEEP]\ngcode:\n    # Parameters\n    {% set i = params.I|default(1)|int %}                                                                        ; Iterations (number of times to beep).\n    {% set dur = params.DUR|default(100)|int %}                                                                  ; Duration/wait of each beep in ms. Default 100ms.\n\n    {% if printer[\"output_pin sound\"].value|int == 1 %}\n        {% for iteration in range(i|int) %}\n            SET_PIN PIN=buzzer VALUE=1\n            G4 P{dur}\n            SET_PIN PIN=buzzer VALUE=0\n            G4 P{dur}\n        {% endfor %}\n    {% endif %}\n\n\n[gcode_macro beep_on]\ngcode:\n    SET_PIN PIN=buzzer VALUE=1\n\n\n[gcode_macro beep_off]\ngcode:\n    SET_PIN PIN=buzzer VALUE=0\n\n\n########################################\n# Z-height Macros\n########################################\n# Bed Leveling (Unified)\n[gcode_macro G29]\nvariable_k:1\ngcode:\n    {% if k|int==1 %}\n        BED_MESH_CLEAR                                                                                           ; Clear levelling data\n        BED_MESH_CALIBRATE ADAPTIVE=1 ADAPTIVE_MARGIN=5                                                          ; Start adaptive meshing\n    {% endif %}   \n\n\n# Babystep\n[gcode_macro M290]\ngcode:\n   SET_GCODE_OFFSET Z_ADJUST={params.Z}\n\n\n########################################\n# Tuning Macros\n########################################\n[gcode_macro SHAPER_CALIBRATE]\nrename_existing: RESHAPER_CALIBRATE\ngcode:\n    RESHAPER_CALIBRATE FREQ_START=30 FREQ_END=130\n\n\n# Linear Advance Factor\n[gcode_macro M900]\ngcode:\n    {% if params.K is defined %} \n          SET_PRESSURE_ADVANCE ADVANCE={params.K}\n    {% endif %}  \n    {% if params.T is defined %}    \n       SET_PRESSURE_ADVANCE SMOOTH_TIME={params.T}\n    {% endif %} \n\n\n# Set Starting Acceleration\n[gcode_macro M204]\nrename_existing: M99204\ngcode:\n    {% if params.S is defined %}\n        {% set s = params.S|float %}\n    {% endif %}\n    {% if params.P is defined %}\n    {% if params.T is defined %}\n        {% set s = [params.P|float ,params.T|float] | min %}\n    {% endif %}\n    {% endif %}\n\n    SET_VELOCITY_LIMIT ACCEL={s}\n    SET_VELOCITY_LIMIT ACCEL_TO_DECEL={s/2}\n\n\n# Bed leveling\n# For more information, see https://www.klipper3d.org/Manual_Level.html#adjusting-bed-leveling-screws-using-the-bed-probe\n[gcode_macro LEVEL_BED]\ndescription: \"Measure bed and calculate screw adjustments for manual bed leveling\"\ngcode:\n    G28                                                                                                         ; Home all\n    SCREWS_TILT_CALCULATE  \n\n\n# Probe Calibration\n# For more information, see https://www.klipper3d.org/Probe_Calibrate.html\n[gcode_macro CALIBRATE_Z_OFFSET]\ndescription: \"Calibrate the Z offset using the probe\"\ngcode:\n    {% set max_x = printer.configfile.config[\"stepper_x\"][\"position_max\"]|float %}\n    {% set max_y = printer.configfile.config[\"stepper_y\"][\"position_max\"]|float %}\n\n    G28                                                                                                         ; Home all\n    G0 Z10                                                                                                      ; Increase z clearance\n    G0 X{max_x/2} Y{max_y-40} F6000                                                                             ; Move to bed center \n    PROBE_CALIBRATE                                                                                             ; Perform a probe calibration\n\n\n# Nozzle PID tuning\n# For more information, see https://www.klipper3d.org/Config_checks.html#calibrate-pid-settings\n[gcode_macro NOZZLE_PID_TUNE]\ndescription: \"Perform PID tuning for the nozzle heater\"\ngcode:\n    PID_CALIBRATE HEATER=extruder TARGET=220                                                                    ; PID tune the nozzle\n\n\n# Bed PID tuning\n# For more information, see https://www.klipper3d.org/Config_checks.html#calibrate-pid-settings\n[gcode_macro BED_PID_TUNE]\ndescription: \"Perform PID tuning for the bed heater\"\ngcode:\n    PID_CALIBRATE HEATER=heater_bed TARGET=80                                                                   ; PID tune the bed\n\n\n########################################\n# Macros for display functionallity\n########################################\n[gcode_macro INPUT_SHAPING_CALIBRATE]\ndescription: \"Perform Input Shaping calibration and save the results to printer.cfg\"\ngcode:\n    SHAPER_CALIBRATE                                                                                            ; Step 1: Perform the Input Shaping calibration\n    PAUSE                                                                                                       ; Step 2: Pause to allow the calibration to complete\n    SAVE_CONFIG                                                                                                 ; Step 3: Save the configuration to printer.cfg\n    RESTART                                                                                                     ; Step 4: Restart the firmware to apply the new settings\n\n"
  },
  {
    "path": "config_section/X-Smart3/printer.cfg",
    "content": "# X-Smart3 config created by Phil1988(github)/coco.33(discord) on 20.12.2024\n# For more information check out my wiki: https://github.com/Phil1988/FreeDi/wiki\n\n\n#####################################################################\n# Kinematics\n#####################################################################\n[printer]\nkinematics:corexy\nmax_velocity: 600\nmax_accel: 20000\nmax_z_velocity: 20\nmax_z_accel: 500\nsquare_corner_velocity: 8\n\n\n#####################################################################\n# Motherboard and periphery\n#####################################################################\n[temperature_sensor Mainboard_RK3328]\nsensor_type: temperature_host\nmin_temp: 10\nmax_temp: 100\n\n[mcu]\nserial: /dev/ttyS0\nrestart_method: command\nbaud: 500000\n\n[temperature_sensor Mainboard_STM32F402]\nsensor_type: temperature_mcu\nsensor_mcu: mcu\n\n[mcu Toolhead]\nserial: /dev/serial/by-id/usb-Klipper_rp2040_C5DA4D951E145858-if00\n\n[temperature_sensor Toolhead_RP2040]\nsensor_type: temperature_mcu\nsensor_mcu: Toolhead\nmin_temp: 0\nmax_temp: 100\n\n\n#####################################################################\n# Features\n#####################################################################\n# For saving GCODE files\n[virtual_sdcard]\npath: ~/printer_data/gcodes\non_error_gcode: CANCEL_PRINT\n\n# For enabling pause/resume\n[pause_resume]\n\n# Activating exclude objects feature\n[display_status]\n[exclude_object]\n\n# Expanding idle timeout\n[idle_timeout]\ntimeout: 5400   ; 90min timeout\n\n# Activating GCODE arc feature\n[gcode_arcs]\nresolution: 1.0\n\n# Allowing free move (can be dangerous!)\n[force_move]\nenable_force_move: True\n\n# Activating responses\n[respond]\ndefault_type: echo\n\n#####################################################################\n# FreeDi\n#####################################################################\n[include freedi.cfg] \n\n\n#####################################################################\n# Macros\n#####################################################################\n[include macros.cfg]\n\n\n#####################################################################\n# Input shaping\n#####################################################################\n[resonance_tester]\naccel_chip:adxl345\nprobe_points:\n    90, 90, 10 \naccel_per_hz: 75\nsweeping_period: 0\nmax_smoothing: 0.5\n    \n[adxl345]\ncs_pin: Toolhead:gpio13\nspi_software_sclk_pin: Toolhead:gpio14\nspi_software_mosi_pin: Toolhead:gpio15\nspi_software_miso_pin: Toolhead:gpio12\naxes_map: -x, z, -y\n\n[input_shaper]\nshaper_type_x: mzv\nshaper_freq_x: 57.6\nshaper_type_y: mzv\nshaper_freq_y: 46.6\n\n\n#####################################################################\n# Hotend\n#####################################################################\n[extruder]\nstep_pin: Toolhead:gpio5\ndir_pin: Toolhead:gpio4\nenable_pin: !Toolhead:gpio10\nrotation_distance: 53.5\ngear_ratio: 1628:170\t\t\t\t\nmicrosteps: 16\nfull_steps_per_rotation: 200\nnozzle_diameter: 0.400\nfilament_diameter: 1.75\nmin_temp: 0\nmax_temp: 360\nmin_extrude_temp: 170\nsmooth_time: 0.000001\nstep_pulse_duration: 0.000002\n\nheater_pin: Toolhead:gpio0\nsensor_type:MAX6675\nsensor_pin: Toolhead:gpio17\nmax_power: 1.0\ncontrol: pid  \npid_Kp: 24.737\npid_Ki: 10.994\npid_Kd: 13.915\n\nspi_speed: 100000\nspi_software_sclk_pin: Toolhead:gpio18\nspi_software_mosi_pin: Toolhead:gpio19\nspi_software_miso_pin: Toolhead:gpio16\n\npressure_advance: 0.032\npressure_advance_smooth_time: 0.03\nmax_extrude_cross_section:500\ninstantaneous_corner_velocity: 10.000\nmax_extrude_only_distance: 500.0\nmax_extrude_only_velocity: 5000\nmax_extrude_only_accel: 2000\n\n[verify_heater extruder]\nmax_error: 120\ncheck_gain_time: 20\nhysteresis: 5\nheating_gain: 1\n\n\n#####################################################################\n# Heated bed\n#####################################################################\n[heater_bed]\nheater_pin: PB10\nsensor_type: NTC 100K MGB18-104F39050L32\nsensor_pin: PA0\nmax_power: 1.0\ncontrol: pid\npid_kp: 64.431\npid_ki: 2.845\npid_kd: 364.839\nmin_temp: -50\nmax_temp: 125\npwm_cycle_time: 0.02 # for 50Hz line power \n#pwm_cycle_time: 0.016 # for 60Hz line power\n\n[verify_heater heater_bed]\nmax_error: 200\ncheck_gain_time: 60\nhysteresis: 5\nheating_gain: 1\n\n\n#####################################################################\n# Bed mesh\n#####################################################################\n[bed_mesh]\nspeed: 150               \nhorizontal_move_z: 2.6   \nmesh_min: 30,15\nmesh_max: 170,170  \nprobe_count: 7,7    \nalgorithm: bicubic\nbicubic_tension: 0.2\nmesh_pps: 4, 4\n\n\n#####################################################################\n# Probe\n#####################################################################\n#!# Pay attention to this section and compare it with your stock backup config\n[probe]\npin: ^!Toolhead:gpio21\nx_offset: 28\ny_offset: 4.4\nz_offset: 1.549             #!# change this to 0 if you get a \"Probe triggered prior to movement\" - Error\nspeed: 5\nsamples: 2\nsamples_result: average\nsample_retract_dist: 0.7\nsamples_tolerance: 0.08\nsamples_tolerance_retries: 3\n\n#!# This is for users of the first batches x-series with a BLtouch. Please uncomment if you have one\n#!# Pay attention to this section and compare it with your stock backup config\n#[bltouch]\n#sensor_pin: ^Toolhead:gpio21\n#control_pin: Toolhead:gpio11\n#stow_on_each_sample: False\n#x_offset: 28\n#y_offset: 4.4\n#z_offset: 0.0\n#speed: 5\n#samples: 2\n#samples_result: average\n#sample_retract_dist: 3.0\n#samples_tolerance: 0.08\n#samples_tolerance_retries:3\n\n\n########################################\n# Filament runout sensor\n########################################\n[filament_switch_sensor filament]\nswitch_pin: !PC1\npause_on_runout: True\nrunout_gcode:\n            M118 Filament run out!\nevent_delay: 3.0\npause_delay: 0.5\n\n\n#####################################################################\n# Fans\n#####################################################################\n## Part cooling fan \n# [fan_generic partfan]\n# pin: Toolhead:gpio2\n# max_power: 1.0\n# cycle_time: 0.0100\n# hardware_pwm: false\n# kick_start_time: 0.200\n# off_below: 0.08\n# shutdown_speed: 0\n[fan]\npin: Toolhead:gpio2\nmax_power: 1.0\ncycle_time: 0.0100\nhardware_pwm: false\nkick_start_time: 0.200\noff_below: 0.08\nshutdown_speed: 0.0\n\n## Activated charcoal blowing fan\n[fan_generic filterfan]\npin: PC9\nmax_power: 1.0\ncycle_time: 0.0100\nhardware_pwm: false\nkick_start_time: 0.200\noff_below: 0.3\nshutdown_speed: 0\n\n## Cold end and toolhead housing fans\n[heater_fan hotend_fan]\npin: Toolhead:gpio1\nmax_power: 1.0\nkick_start_time: 0.5\nheater: extruder\nheater_temp: 50.0\nfan_speed: 1.0\noff_below: 0\n\n#!# Delete the next section if your stock backup config doesnt have it\n# Toolhead cooling fan\n[heater_fan hotend_fan2]\npin: Toolhead:gpio20\nmax_power: 1.0\nshutdown_speed:1.0\nkick_start_time: 0.5\nheater: extruder\nheater_temp: 50.0\nfan_speed: 1.0\noff_below: 0\n\n#!# Delete the next section if your stock backup config doesnt have it\n## Controllable Mainboard cooling fan as a modifification for the X-Smart3 on a different port\n[temperature_fan Mainboard_fan]\nsensor_type: temperature_host \npin: PA8     \nmax_power: 1.0  \ncycle_time: 0.01\nsensor_type: temperature_combined\nsensor_list: temperature_sensor Mainboard_RK3328, temperature_sensor Mainboard_STM32F402\ncombination_method: max                                           # use the maximum reading of the sensors\nmaximum_deviation: 999.9                                          # we don't care about the difference in temperature\nshutdown_speed: 0.0\nkick_start_time: 0.4\noff_below: 0.19\nmin_temp: 0\nmax_temp: 85.0  \ntarget_temp: 42.0\nmin_speed: 0\nmax_speed: 1.0\ncontrol: pid\npid_deriv_time: 2.0\npid_Kp: 2.0\npid_Ki: 5.0\npid_Kd: 0.5\n\n\n#####################################################################\n# Light\n#####################################################################\n## caselight LEDs\n[output_pin caselight]\npin: PC7\npwm: true\ncycle_time: 0.0100\nshutdown_value:0\nvalue:1\n\n\n#####################################################################\n# Buzzer\n#####################################################################\n## Buzzer\n[output_pin buzzer]\npin: PA2\npwm: false\nshutdown_value:0\nvalue:0\n\n[output_pin sound]\npin: PA13\nvalue:0\n\n\n#####################################################################\n# Power outage shutdown\n#####################################################################\n[output_pin pwc]\npin: PA3\npwm: False\nvalue: 1\nshutdown_value: 1\n\n\n#####################################################################\n# Drives\n#####################################################################\n[stepper_x]\nstep_pin: PB4\ndir_pin: PB3\nenable_pin: !PB5\nmicrosteps: 16\nrotation_distance: 39.94\nfull_steps_per_rotation: 200\nendstop_pin: tmc2209_stepper_x:virtual_endstop\nposition_min: -5.5\nposition_endstop: -4.5\nposition_max: 177\nhoming_speed: 40\nhoming_retract_dist: 0\nhoming_positive_dir: False\nstep_pulse_duration: 0.000002\n\n[stepper_y]\nstep_pin: PC14\ndir_pin: PC13\nenable_pin: !PC15\nmicrosteps: 16\nrotation_distance: 39.96\nfull_steps_per_rotation: 200\nendstop_pin: tmc2209_stepper_y:virtual_endstop\nposition_min: -5.5\nposition_endstop: -4.5\nposition_max: 185\nhoming_speed: 40\nhoming_retract_dist: 0\nhoming_positive_dir: False\nstep_pulse_duration: 0.000002\n\n[stepper_z]\nstep_pin: PC10\ndir_pin: PA15\nenable_pin: !PC11\nmicrosteps: 16\nrotation_distance: 8\nfull_steps_per_rotation: 200\nendstop_pin: probe:z_virtual_endstop\nposition_max: 175\nposition_min: -2\nhoming_speed: 8\nhoming_retract_dist: 8.0\nsecond_homing_speed: 5\nhoming_positive_dir: false\nstep_pulse_duration: 0.000002\n\n\n#####################################################################\n# Steppers configuration\n#####################################################################\n[tmc2209 extruder]\nuart_pin: Toolhead:gpio6\ninterpolate: True\nrun_current: 0.714            #!# Pay attention to this value and compare it with your stock backup config\nstealthchop_threshold: 0\n\n[tmc2209 stepper_x]\nuart_pin: PD2\nrun_current:1.07              #!# Pay attention to this value and compare it with your stock backup config\ninterpolate: True\nstealthchop_threshold: 0\ndiag_pin: ^PB8\ndriver_SGTHRS: 85\n\n[tmc2209 stepper_y]\nuart_pin: PB9\nrun_current: 1.07             #!# Pay attention to this value and compare it with your stock backup config\ninterpolate: True\nstealthchop_threshold: 0\ndiag_pin: ^PC0\ndriver_SGTHRS: 85\n\n[tmc2209 stepper_z]\nuart_pin: PC5\nrun_current: 0.2              #!# Pay attention to this value and compare it with your stock backup config\ninterpolate: True\nstealthchop_threshold: 1200\n\n\n#####################################################################\n# Screws tilt adjust\n#####################################################################\n[screws_tilt_adjust]\nhorizontal_move_z: 5\nscrew_thread: CCW-M4\nspeed: 300\n\nscrew1: 4, 29\nscrew1_name: front left screw\nscrew2: 124, 29\nscrew2_name: front right screw\nscrew3: 124, 149\nscrew3_name: rear right screw\nscrew4: 4, 149\nscrew4_name: rear left screw"
  },
  {
    "path": "config_section/generic/crowsnest.conf",
    "content": "#### crowsnest.conf\n#### This is the default config after installation.\n#### It is also used as the default config in MainsailOS.\n#### For details on how to configure this to your needs, see:\n#### https://github.com/mainsail-crew/crowsnest/blob/master/README.md\n\n\n#####################################################################\n####                                                            #####\n####      Information about ports and according URL's           #####\n####                                                            #####\n#####################################################################\n####                                                            #####\n####    Port 8080 equals /webcam/?action=[stream/snapshot]      #####\n####    Port 8081 equals /webcam2/?action=[stream/snapshot]     #####\n####    Port 8082 equals /webcam3/?action=[stream/snapshot]     #####\n####    Port 8083 equals /webcam4/?action=[stream/snapshot]     #####\n####                                                            #####\n####    Note: These ports are default for most Mainsail         #####\n####    installations. Using any other port would involve       #####\n####    changing the proxy configuration or using URLs          #####\n####    with the specific port like                             #####\n####    http://<ip>:<port>/?action=[stream/snapshot]            #####\n####                                                            #####\n#####################################################################\n####    RTSP Stream URL: ( if enabled and supported )           #####\n####    rtsp://<ip>:<rtsp_port>/stream.h264                     #####\n#####################################################################\n\n\n[crowsnest]\nlog_path: /home/mks/printer_data/logs/crowsnest.log\nlog_level: verbose                      # Valid Options are quiet/verbose/debug\ndelete_log: true                       # Deletes log on every restart, if set to true\nno_proxy: false                         # If set to true, no reverse proxy is required. Only change this, if you know what you are doing.\n\n[cam 1]\nmode: ustreamer                         # ustreamer - Provides MJPG and snapshots. (All devices)\n                                        # camera-streamer - Provides WebRTC, MJPG and snapshots. (only RPiOS + RPi 0/1/2/3/4)\nenable_rtsp: false                      # If camera-streamer is used, this also enables usage of an RTSP server\nrtsp_port: 8554                         # Set different ports for each device!\nport: 8080                              # HTTP/MJPG stream/snapshot port\n\n# Stock X3 series, Q1 Pro and Plus4 series camera\ndevice: /dev/v4l/by-id/usb-SYX-231020-J_HD_Camera-video-index0\nresolution: 640x480\nmax_fps: 16\n\n# # Alternative Plus4 series camera\n# device: /dev/v4l/by-id/usb-icSpring_icspring_camera24091116320721-video-index0   \n# resolution: 640x480\n# max_fps: 16\n\n# # Stock X3 series camera\n# device: /dev/v4l/by-id/usb-SYX-231020-J_HD_Camera-video-index0\n# resolution: 1920x1080\n# max_fps: 16\n\n# # Sunplus camera:\n# device: /dev/v4l/by-id/usb-Sunplus_IT_Co_FHD_Camera-video-index0\n# resolution: 800x600\n# max_fps: 10\n"
  },
  {
    "path": "config_section/generic/freedi.cfg",
    "content": "#####################################################################\n# FreeDi config\n#####################################################################\n# Note: Please restart the FreeDi service after changing this file to apply the new settings.\n\n\n#####################################################################\n# Basic Setup\n#####################################################################\n[freedi]\n# Printer model. Currently supported: x-smart3, x-plus3, x-max3, q1_pro, plus4 and unknown (for autodetection)\nprinter_model: unknown\n# Baud rate for serial communication. Stock mainboard with standard firmware: 921600 | Legacy firmware: 115200\nbaudrate: 921600\n# Serial port for the LCD. Stock: /dev/ttyS1 | USB<->TTL adapter: /dev/ttyUSB0 | BTT Manta M5P: /dev/ttyS0\n# For the Plus4 if you use the USB<->TTL adapter: TX <-> A, RX <-> Y\nserial_port: /dev/ttyS1\n# URL of the printer service\nurl: 127.0.0.1\n# Port of the moonraker service. Default: 7125\nmoonraker_port: 7125\n# Port of the web user interface (Mainsail | Fluidd). Default: 80\nwebUI_port: 80\n# API key for the printer\napi_key: XXXXXX\n# Path to the Klippy socket file\nklippy_socket: /home/mks/printer_data/comms/klippy.sock\n# Specify if you want to use the stable or beta channel. Caution: beta firmwares have more potential to have bugs.\nchannel: stable\n# Enable FreeDi wizzard: True | False\nwizard: True\n\n\n#####################################################################\n# User Preferences\n#####################################################################\n# default values for on screen activation\ndefault_temp_extruder: 220\ndefault_temp_bed: 60\ndefault_temp_chamber: 45\ndefault_speed_partfan: 100\ndefault_speed_sidefan: 100\ndefault_speed_filterfan: 100\n\n# Synchronize case light with display: True | False\nsync_case_light_with_display: True\n# Default brightness of the display in %\ndefault_brightness: 100\n# Dim display: time in minutes | 0 to disable\nlcd_dim_time: 10\n# Dim display: intensity in percent\nlcd_dim_brightness: 20\n# Sleep display: time in minutes | 0 to disable\nlcd_sleep_time: 20\n\n# Default extrusion lengths for the Extruder menu (in millimeters)\n# this will be used as the default extrude value\nextruder_length_1: 10.0\nextruder_length_2: 20.0\nextruder_length_3: 50.0\n\n# Default move and extrude step lengths for Move and Move&Extrude (<-while printing) menus (in millimeters)\nmove_extrude_length_1: 0.1\nmove_extrude_length_2: 1.0\n# this will be used as the default move (move&extrude) value\nmove_extrude_length_3: 10.0\nmove_extrude_length_4: 50.0\nmove_extrude_length_5: 100.0\n\n# Preset names on the display home screen: \npreset1_name: PLA\npreset2_name: ABS\npreset3_name: PETG\npreset4_name: TPU\n\n#### not yet integrated #### \n# Enable acoustic feedback on touch events (e.g. button press): True | False\ntouch_acoustic_feedback: True\n# Toggle to install the klipper module: True | False\ninstall_klipper_module: False \n# Toggle to flash the MCU: True | False\nflash_MCU: False\n# Toggle to flash the toolhead: True | False \nflash_toolhead: False\n# Toggle to flash the display: True | False\nflash_display: False\n\n\n#####################################################################\n# FreeDi macros\n#####################################################################\n# Description: \n# This section is used to define the preset buttons on the display.\n# This gives you maximum flexiblity to replace them with your own custom macros.\n[gcode_macro PRESET_MACRO_1]\n# Preset macro 1 (default for PLA)\ngcode:\n    M104 S210                                                         ; Set extruder temp\n    M140 S60                                                          ; Set bed temp\n    M141 S0                                                           ; Set chamber temp\n\n[gcode_macro PRESET_MACRO_2]\n# Preset macro 12 (default for ABS)\ngcode:\n    M104 S250                                                         ; Set extruder temp\n    M140 S95                                                          ; Set bed temp\n    M141 S45                                                          ; Set chamber temp\n\n[gcode_macro PRESET_MACRO_3]\n# Preset macro 3 (default for PETG)\ngcode:\n    M104 S240                                                         ; Set extruder temp\n    M140 S70                                                          ; Set bed temp\n    M141 S0                                                           ; Set chamber temp\n\n[gcode_macro PRESET_MACRO_4]\n## Preset macro 4 (default for TPU)\ngcode:\n    M104 S250                                                         ; Set extruder temp\n    M140 S40                                                          ; Set bed temp\n    M141 S0                                                           ; Set chamber temp\n#####################################################################"
  },
  {
    "path": "config_section/generic/moonraker.conf",
    "content": "#####################################################################\n# Basics\n#####################################################################\n[server]\nhost: 0.0.0.0\nport: 7125\nklippy_uds_address: /home/mks/printer_data/comms/klippy.sock\n\n[authorization]\ntrusted_clients:\n    10.0.0.0/8\n    127.0.0.0/8\n    169.254.0.0/16\n    172.16.0.0/12\n    192.168.0.0/16\n    FE80::/10\n    ::1/128\ncors_domains:\n    *.lan\n    *.local\n    *://localhost\n    *://localhost:*\n    *://my.mainsail.xyz\n    *://app.fluidd.xyz\n\n\n#####################################################################\n# Features\n#####################################################################\n[octoprint_compat]\n\n[history]\n\n# For kemp, see https://github.com/kyleisah/Klipper-Adaptive-Meshing-Purging\n[file_manager]\nenable_object_processing: True\n\n[announcements]\nsubscriptions:\n  FreeDi\n\n#####################################################################\n# Update Mangers\n#####################################################################\n[update_manager]\nchannel: stable\nrefresh_interval: 168\n\n# Mainsail update_manager entry\n[update_manager mainsail]\ntype: web\nchannel: stable\nrepo: mainsail-crew/mainsail\npath: ~/mainsail\n\n# Crowsnest update_manager entry\n[update_manager crowsnest]\ntype: git_repo\npath: ~/crowsnest\norigin: https://github.com/mainsail-crew/crowsnest.git\ninstall_script: tools/pkglist.sh\n\n# FreeDi update_manager entry\n[update_manager FreeDi]\ntype: git_repo\npath: ~/FreeDi\nchannel: stable\norigin: https://github.com/Phil1988/FreeDi\nvirtualenv: ~/klippy-env\nrequirements: requirements.txt\nmanaged_services: FreeDi\ninfo_tags:\n\tdesc=FreeDi\n"
  },
  {
    "path": "config_section/template/macros.cfg",
    "content": "#####################################################################\n# Specific Plus4 macros\n#####################################################################\n#Danger Zone Y 318 -323\n[gcode_macro SET_PRINT_STATS_INFO]\nrename_existing: BASE_SET_PRINT_STATS_INFO_BASE\ngcode:\n    # To prevent the chamber heater to blow hot air directly onto the left side of the print bed \n    {% if (printer.toolhead.position.z) > 260 %}\n        M141 S0\n    {% endif %}\n    #TIMELAPSE_TAKE_FRAME\n    BASE_SET_PRINT_STATS_INFO_BASE {rawparams}\n    CHAMBER_TEMP_CONTROLLER\n\n# Safety macro that gets frequently called by SET_PRINT_STATS_INFO to prevent too high chamber temperatures\n[gcode_macro CHAMBER_TEMP_CONTROLLER]\ngcode:\n    {% set chamber_target_temp = printer['heater_generic chamber'].target %}\n    {% set chamber_temp = printer['heater_generic chamber'].temperature %}\n    {% if chamber_temp > printer.configfile.settings['heater_generic chamber'].max_temp %}\n        M106 P3 S255\n    {% else %}\n        {% if chamber_target_temp > 0 %}\n            # Allow for 3C of \"grace\" before we start ramping the exhaust fan speed\n            # This prevents the macro from fighting with the chamber heater PID algorithm\n            {% set difference = chamber_temp - (chamber_target_temp + 3) %}\n            {% if difference > 0 %}\n                {% set filterfan_speed = ([(difference * 50), 255] | min) | int %}\n                M106 P3 S{filterfan_speed}\n            {% else %}\n                M106 P3 S0\n            {% endif %}\n        {% endif %}\n    {% endif %}\n\n\n[gcode_macro CHAMBER_TEMP_CONTROLLER]\ngcode:\n    {% set chamber_target_temp = printer['heater_generic chamber'].target %}\n    {% set chamber_cfg.max_temp = printer.configfile.settings['heater_generic chamber'].max_temp %}\n    {% set chamber_temp = printer['heater_generic chamber'].temperature %}\n    {% set min_filterfan = (255 * 0.40) | int %} \n\n    {% if chamber_temp > chamber_cfg.max_temp %}\n        M106 P3 S255\n    {% elif chamber_target_temp > 0 %}\n            # Allow for 3C of \"grace\" before we start ramping the exhaust fan speed\n            # This prevents the macro from fighting with the chamber heater PID algorithm\n            {% set difference = chamber_temp - (chamber_target_temp + 3) %}\n            {% if difference > 0 %}\n                {% set raw_speed = ([(difference * 50), 255] | min) | int %}\n                {% set filterfan_speed = [raw_speed, min_filterfan] | max %}\n                M106 P3 S{filterfan_speed}\n            {% else %}\n                M106 P3 S{printjob_filterfan_speed} ; <- user defined speed that we have to extract from the PRINT_START\n            {% endif %}\n        {% endif %}\n    {% endif %}\n\n    \n[gcode_macro ENABLE_ALL_SENSOR]\ngcode:\n    ENABLE_FILAMENT_WIDTH_SENSOR\n    RESET_FILAMENT_WIDTH_SENSOR\n    query_filament_width\n    SET_FILAMENT_SENSOR SENSOR=filament_tangle_sensor ENABLE=1\n\n\n[gcode_macro DISABLE_ALL_SENSOR]\ngcode:\n    SET_FILAMENT_SENSOR SENSOR=filament_tangle_sensor ENABLE=0\n    DISABLE_FILAMENT_WIDTH_SENSOR\n\n\n[gcode_macro AUTO_LEVEL_BED]\ngcode:\n    {% set Z_max = printer.toolhead.axis_maximum.z %}\n    G28    \n    G1 Z{Z_max-30} F600\n    SET_TMC_CURRENT STEPPER=stepper_z CURRENT={printer.configfile.settings['tmc2209 stepper_z'].run_current * 0.5 }\n    SET_TMC_CURRENT STEPPER=stepper_z1 CURRENT={printer.configfile.settings['tmc2209 stepper_z1'].run_current * 0.5 }\n    G1 Z{Z_max} F600\n    SET_KINEMATIC_POSITION Z=0\n    G1 Z10 F600\n    G1 Z0 F600\n    G1 Z15 F600\n    SET_TMC_CURRENT STEPPER=stepper_z CURRENT={printer.configfile.settings['tmc2209 stepper_z'].run_current}\n    SET_TMC_CURRENT STEPPER=stepper_z1 CURRENT={printer.configfile.settings['tmc2209 stepper_z1'].run_current}\n    G28\n\n\n[gcode_macro SCREWS_TILT_CALCULATE]\nrename_existing: BASE_SCREWS_TILT_CALCULATE_BASE\ngcode:\n    { action_respond_info(\"starting screw rotation calculation...\") }\n    M141 S0             # disable chamber heater (see https://github.com/qidi-community/Plus4-Wiki/tree/main/content/chamber-heater-issue)\n    BASE_SCREWS_TILT_CALCULATE_BASE\n\n\n[gcode_macro HOME_IF_NEEDED]\ndescription: Homes X and Y if needed\ngcode:\n    {% if \"y\" not in printer.toolhead.homed_axes %}\n        G28 Y\n    {% endif %}\n    {% if \"x\" not in printer.toolhead.homed_axes %}\n        G28 X\n    {% endif %}\n    {% if \"z\" not in printer.toolhead.homed_axes %}\n        G28 Z\n    {% endif %}\n\n\n[gcode_macro CUT_FILAMENT]\ndescription: Cuts the filament\ngcode:\n    HOME_IF_NEEDED\n    \n    {% if printer.gcode_move.position.y < 20 %}\n      G1 Y40 F9000\n    {% endif %}\n    {% if printer.gcode_move.position.y > 300 %}\n      G1 Y300 F9000\n    {% endif %}\n    G1 X305 Y40 F9000\n    G1 Y20 F9000\n    G1 Y5 F3000\n    G4 P500\n    G1 Y20 F9000\n    G1 Y5 F3000\n    G4 P500\n    G1 Y20 F9000\n\n\n[gcode_macro GO_TO_POOP_SHOOT]\ndescription: Move toolhead to poop shoot\ngcode:\n    HOME_IF_NEEDED\n\n    G90\n    {% if printer.gcode_move.position.y > 300 %}\n      G1 Y300 F9000\n    {% endif %}\n\n    G1 X95 Y312 F12000\n    G1 Y316 F600\n    G1 Y320 F9000\n    G1 Y324 F600\n\n\n[gcode_macro LEAVE_POOP_SHOOT]\ndescription: Primes the nozzle with fresh filament before load/unload/print start\ngcode:\n    HOME_IF_NEEDED\n\n    {% if printer.gcode_move.position.y > 323 %}\n      G1 X95 F1200\n      G1 Y300 F1200\n    {% else %}\n        {% if printer.gcode_move.position.y < 318  %}\n            G1 X95 Y300 F1200\n        {% else %}\n            {% if (printer.gcode_move.position.x < 83 or printer.gcode_move.position.x > 106 or \n                    (printer.gcode_move.position.x >= 93 and printer.gcode_move.position.x <= 97)) %}\n                G1 Y300 F1200\n                G1 X95    \n            {% else %}\n               M118 Warning: Nozzle in dangerous position!        \n            {% endif %}\n        {% endif %}\n    {% endif %}\n\n\n[gcode_macro _SILICON_WIPE]\ndescription: Wipe on the silicon pad with custom min and max coordinates and margin\ngcode:\n    G90\n    {% if (printer.gcode_move.position.y) > 300 %}\n      G1 Y300 F600      \n    {% endif %}\n\n    G1 X95 F12000\n    G1 Y314 F9000\n    G1 Y324 F600\n\n    ; Wipe movements in X direction\n    G1 X58 F12000\n    G1 X78 F12000\n    G1 Y324\n    G1 X58 F12000\n    G1 X78 F12000\n    G1 Y323.5\n    G1 X58 F12000\n    G1 X78 F12000\n    G1 Y323\n    G1 X58 F12000\n    G1 X78 F12000\n    G1 Y322.5\n    G1 X58 F12000\n    G1 X78 F12000\n    G1 Y322\n    G1 X58 F12000\n    G1 X75 F12000\n    G1 Y321.5\n\n    ; Wipe movements in circles\n    G2 I0.8 J0.8 F600\n    G2 I0.8 J0.8 F600\n    G2 I0.8 J0.8 F600\n\n    G1 Y324 F600\n    G1 X95 F12000\n\n\n[gcode_macro _PEI_WIPE]\ndescription: Wipe on the PEI pad\ngcode:\n    # Input values for the minimum and maximum coordinates of the pad\n    {% set pad_min_coordinate_x = 111 %}\n    {% set pad_max_coordinate_x = 136 %}\n    {% set pad_min_coordinate_y = 317 %}\n    {% set pad_max_coordinate_y = 325 %}\n    {% set margin = 1.0 %} # margin from the edge of the pad\n    {% set repetitions = 3 %}\n\n    # Arc parameters and radius to keep full arc inside limits\n    {% set arc_i = 0.5 %}\n    {% set arc_j = 0.5 %}\n    {% set arc_r = ((arc_i|float)**2 + (arc_j|float)**2) ** 0.5 %}\n\n    G90 # absolute positioning\n    {% if (printer.gcode_move.position.y) < 300 %}\n      G1 Y300 F9000\n    {% endif %}\n\n    G1 X108 F9000\n\n    # Compute safe max/min positions (account for margin and arc radius)\n    {% set X_max_position = pad_max_coordinate_x - margin - arc_r %}\n    {% set Y_max_position = pad_max_coordinate_y - margin - arc_r %}\n    {% set X_min_position = pad_min_coordinate_x + margin + arc_r %}\n    {% set Y_min_position = pad_min_coordinate_y + margin + arc_r %}\n\n    # Calculate random end positions within the defined safe boundaries (0.05 mm steps)\n    {% set random_x_steps = ((X_max_position - X_min_position) * 20) | int %}\n    {% if random_x_steps < 1 %}{% set random_x_steps = 1 %}{% endif %}\n    {% set random_x = (range(0, random_x_steps) | random) / 20.0 %}\n    {% set X_move_position = X_min_position + random_x %}\n\n    {% set random_y_steps = ((Y_max_position - Y_min_position) * 20) | int %}\n    {% if random_y_steps < 1 %}{% set random_y_steps = 1 %}{% endif %}\n    {% set random_y = (range(0, random_y_steps) | random) / 20.0 %}\n    {% set Y_move_position = Y_min_position + random_y %}\n\n    # Calculate a random starting Y position within the safe range (0.1 mm steps)\n    {% set random_start_y_steps = ((Y_max_position - Y_min_position) * 10) | int %}\n    {% if random_start_y_steps < 1 %}{% set random_start_y_steps = 1 %}{% endif %}\n    {% set random_start_y = (range(0, random_start_y_steps) | random) / 10.0 + Y_min_position %}\n\n    # Move the print head to the random starting Y position\n    G1 Y{random_start_y} F500\n\n    # Wiping movements in X direction\n    {% for move in range(repetitions|int) %}\n        G1 X{X_max_position} F400\n        G1 X{X_move_position} F400\n    {% endfor %}\n\n    # Wiping movements in Y direction\n    {% for move in range(repetitions|int) %}\n        G1 Y{Y_move_position} F400\n        G1 Y{Y_max_position} F400\n    {% endfor %}\n\n    G1 X{X_move_position} Y{Y_move_position} F300\n\n    # Circular wiping movements (kept inside safe area by arc radius)\n    {% for move in range(repetitions|int) %}\n        G2 I{arc_i} J{arc_j} F500\n    {% endfor %}\n\n    # Rectangular wiping movements\n    {% for move in range(repetitions|int) %}\n        G1 Y{Y_max_position} F400\n        G1 X{X_max_position} F400\n        G1 Y{Y_move_position} F400\n        G1 X{X_move_position} F400\n    {% endfor %}\n\n\n[gcode_macro PRIME_NOZZLE]\ndescription: Primes the nozzle with fresh filament before load/unload/print start\ngcode:\n    {% set hotend_target_temp = params.HOTEND_TARGET_TEMP|default(220)|int %}\n    M106 S0\n    M104 S{hotend_target_temp}\n\n    HOME_IF_NEEDED\n\n    TEMPERATURE_WAIT SENSOR=extruder MINIMUM={hotend_target_temp-50}\n    GO_TO_POOP_SHOOT\n\n    M109 S{hotend_target_temp}\n\n    G92 E0\n    G1 E5 F50\n    G1 E50 F200\n    G92 E0\n    G1 E-0.8 F200\n    G4 P300\n\n   \n    M104 S{([hotend_target_temp-80, 150]|min)} \n    M106 S255\n    G4 P4000\n    \n    _PEI_WIPE\n    TEMPERATURE_WAIT SENSOR=extruder MAXIMUM={([hotend_target_temp-80, 150]|min)}\n    _SILICON_WIPE\n    GO_TO_POOP_SHOOT \n    M106 S0\n    LEAVE_POOP_SHOOT\n\n\n[gcode_macro M603]\ndescription: Unload filament with cutting filament\ngcode:\n    {% set hotend_target_temp = params.S|default(220)|int %}\n    {% set accel = printer.toolhead.max_accel|int %}\n    \n\tM104 S{hotend_target_temp}\n    \n    HOME_IF_NEEDED\n    M204 S10000\n    CUT_FILAMENT\n    \n    M106 S0\n    M400\n    M204 S{accel}\n    M118 Unload finished\n\n\n[gcode_macro M604]\ndescription: Load filament with priming nozzle\ngcode:\n    {% set hotend_target_temp = params.S|default(250)|int %}\n    {% set accel = printer.toolhead.max_accel|int %}\n    \n    M104 S{hotend_target_temp}\n\n    HOME_IF_NEEDED\n    M204 S10000\n    PRIME_NOZZLE hotend_target_temp={hotend_target_temp}\n\n    M106 S0\n    M400\n    M204 S{accel}\n    M118 Load finished\n\n\n#####################################################################\n# Homing modification\n#####################################################################\n[gcode_macro G28]\nrename_existing: G28.1\ngcode:\n    {% set reduced_current_x = 0.55 %}\n    {% set reduced_current_y = 0.45 %}\n    {% set home_all = ('X' in rawparams.upper() and 'Y' in rawparams.upper() and 'Z' in rawparams.upper()) or \n                      ('X' not in rawparams.upper() and 'Y' not in rawparams.upper() and 'Z' not in rawparams.upper()) %}\n    {% set home_current_x = printer.configfile.settings['tmc2240 stepper_x'].run_current * reduced_current_x %}\n    {% set home_current_y = printer.configfile.settings['tmc2240 stepper_y'].run_current * reduced_current_y %}\n\n    {% set init_XY_move = 30 %}\n    #{% set y_init_move = 5 %}\n    {% set z_clearance = 2 %}\n\n    {% set home_all_final_position_x = printer.toolhead.axis_maximum.x / 2 %}\n    {% set home_all_final_position_y = printer.toolhead.axis_maximum.y - 40 %}\n    {% set home_all_final_position_z = 20 %}\n\n\n    {% if 'x' not in printer.toolhead.homed_axes %}\n      {% set X_axis_was_homed = false %}                                                                           ; Set Z_axis_was_homed to false if Z is not homed\n    {% endif %}\n    {% if 'y' not in printer.toolhead.homed_axes %}\n      {% set Y_axis_was_homed = false %}                                                                           ; Set Z_axis_was_homed to false if Z is not homed\n    {% endif %}\n            \n    # If homing should at least move X or Y axis\n    {% if home_all or 'X' in rawparams.upper() or 'Y' in rawparams.upper() %}     \n        # Check if Z is homed\n        {% if 'z' in printer.toolhead.homed_axes %}\n            {% set Z_axis_was_homed = true %}                                                                       ; Set Z_axis_was_homed to true if Z is already homed\n            G91                                                                                                     ; Use relative positioning\n            G1 Z2 F600                                                                                              ; Move bed down\n            G90                                                                                                     ; Use absolute positioning\n        {% else %}\n            {% set Z_axis_was_homed = false %}                                                                      ; Set Z_axis_was_homed to false if Z is not homed\n            G90\n            SET_KINEMATIC_POSITION Z=0                                                                              ; To allow bed move down\n            G1 Z{z_clearance}                                                                                       ; Move bed down\n            {% if X_axis_was_homed == false %}\n              SET_KINEMATIC_POSITION SET_HOMED= CLEAR_HOMED=X                                                       ; Set X to be unhomed\n            {% endif %}\n            {% if Y_axis_was_homed == false %}\n              SET_KINEMATIC_POSITION SET_HOMED= CLEAR_HOMED=Y                                                       ; Set Y to be unhomed\n            {% endif %}            \n        {% endif %}\n    {% endif %}\n\n    {% if home_all or 'X' in rawparams.upper() or 'Y' in rawparams.upper() %} \n        FORCE_MOVE STEPPER=stepper_x DISTANCE={init_XY_move} VELOCITY=40                                            ; Move X a little before homing\n        SET_KINEMATIC_POSITION X={printer.toolhead.position.x + (init_XY_move/2)}                                   ; Compensate the FORCE_MOVE position \n        SET_KINEMATIC_POSITION Y={printer.toolhead.position.y + (init_XY_move/2)}                                   ; Compensate the FORCE_MOVE position\n        {% if X_axis_was_homed == false %}\n          SET_KINEMATIC_POSITION SET_HOMED= CLEAR_HOMED=X                                                           ; Set X to be unhomed\n        {% endif %}\n        {% if Y_axis_was_homed == false %}\n          SET_KINEMATIC_POSITION SET_HOMED= CLEAR_HOMED=Y                                                           ; Set Y to be unhomed\n        {% endif %} \n    {% endif %}\n\n    # Home Y\n    {% if home_all or 'Y' in rawparams.upper() %}\n        SET_TMC_CURRENT STEPPER=stepper_x CURRENT={home_current_x}                                                  ; Lower motor current\n        SET_TMC_CURRENT STEPPER=stepper_y CURRENT={home_current_y}                                                  ; Lower motor current\n        G28.1 Y                                                                                                     ; Home Y\n        SET_TMC_CURRENT STEPPER=stepper_x CURRENT={printer.configfile.settings['tmc2240 stepper_x'].run_current}    ; Set motor current to the previous value\n        SET_TMC_CURRENT STEPPER=stepper_y CURRENT={printer.configfile.settings['tmc2240 stepper_y'].run_current}    ; Set motor current to the previous value\n        G1 Y10 F1200                                                                                                ; Move Y-axis slightly\n    {% endif %}\n    \n    # Home X\n    {% if home_all or 'X' in rawparams.upper() %}        \n        SET_TMC_CURRENT STEPPER=stepper_x CURRENT={home_current_x}                                                  ; Lower motor current\n        SET_TMC_CURRENT STEPPER=stepper_y CURRENT={home_current_x}                                                  ; Lower motor current\n        G28.1 X                                                                                                     ; Home X\n        SET_TMC_CURRENT STEPPER=stepper_x CURRENT={printer.configfile.settings['tmc2240 stepper_x'].run_current}    ; Set motor current to the previous value\n        SET_TMC_CURRENT STEPPER=stepper_y CURRENT={printer.configfile.settings['tmc2240 stepper_y'].run_current}    ; Set motor current to the previous value\n        G1 X10 F1200                                                                                                ; Move X-axis slightly\n    {% endif %}\n\n    # Raise the bed again if only X or only Y axes were homed\n    {% if not (home_all or 'Z' in rawparams.upper()) %}\n        {% if Z_axis_was_homed %}\n            G91                                                                                                     ; Use relative positioning\n            G1 Z-2 F600                                                                                             ; Raise the bed back again\n            G90                                                                                                     ; Use absolute positioning\n        {% else %}\n            G1 Z0.1                                                                                                 ; Raise the bed back again\n            SET_STEPPER_ENABLE STEPPER=stepper_z enable=0                                                           ; Disable Z to prevent collisions\n            SET_STEPPER_ENABLE STEPPER=stepper_z1 enable=0                                                          ; Disable Z to prevent collisions\n            SET_KINEMATIC_POSITION SET_HOMED= CLEAR_HOMED=Z                                                         ; Set Z to be unhomed\n        {% endif %}\n    {% endif %}\n\n    # Home Z\n    {% if home_all or 'Z' in rawparams.upper() %}\n        G1 X{printer.toolhead.axis_maximum.x / 2} Y{printer.toolhead.axis_maximum.x / 2} F12000 \n        G28.1 Z                                                                                                     ; Home Z\n        G90                                                                                                         ; Set absolute positioning\n        G1 Z{home_all_final_position_z} F600                                                                        ; Move bed down\n    {% endif %}\n\n    # Move to the final position if all axes were homed\n    {% if home_all %}\n        G90                                                                                                         ; Set absolute positioning\n        G1 X{home_all_final_position_x} Y{home_all_final_position_y} Z{home_all_final_position_z} F7800             ; Move to the rear center\n    {% endif %}\n\n\n# Unconditional stop\n[gcode_macro M0]\ngcode:\n    PAUSE\n\n\n# Pause SD print\n[gcode_macro M25]\nrename_existing: M9925\ngcode:\n    PAUSE\n\n\n########################################\n# Basic Macros\n########################################\n\n# Flag macro to use STATIC_MESH usage instead of KAMP (needed make this function work from printjob selection on the LCD)\n[gcode_macro NEXT_PRINT_STATIC_MESH]\ndescription: Forces the NEXT print to use 'STATIC_MESH' instead of KAMP.\ngcode:\n    {% if \"STATIC_MESH\" in printer.bed_mesh.profiles %}\n        SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=force_static_mesh VALUE=True\n        {action_respond_info(\"The NEXT print will use 'STATIC_MESH'.\")}\n        M118 The NEXT print will use the STATIC_MESH.\n    {% else %}\n        {action_respond_info(\"WARNING: No mesh named 'STATIC_MESH' found. Please save one first (BED_MESH_PROFILE SAVE=STATIC_MESH).\")}\n        M118 WARNING: No mesh named STATIC_MESH found. Please save one first (BED_MESH_PROFILE SAVE=STATIC_MESH).\n    {% endif %}\n\n[gcode_macro PRINT_START]\n# Use PRINT_START for the slicer starting script\ndescription: Start printing\nvariable_force_static_mesh: False                                                                                 ; Set to True to force a static mesh instead of KAMP\ngcode:\n    {% set bed_target_temp = params.BED|int %}\n    {% set hotend_target_temp = params.HOTEND|int %}\n    {% set chamber_target_temp = params.CHAMBER|default(0)|int %}\n    {% set bed_center_x = printer.configfile.config[\"stepper_x\"][\"position_max\"]|float / 2 %}\n    {% set bed_center_y = printer.configfile.config[\"stepper_y\"][\"position_max\"]|float / 2 %}\n\n    {% set start_position_x = printer.toolhead.axis_maximum.x / 2 %}\n    {% set start_position_y = printer.toolhead.axis_maximum.y - 40 %}\n    {% set start_position_z = 10 %}\n\n    {% set KAMP_deactivated = printer[\"gcode_macro PRINT_START\"].force_static_mesh %}                              ; Check if KAMP is deactivated for this print\n    SET_GCODE_VARIABLE MACRO=PRINT_START VARIABLE=force_static_mesh VALUE=False                                    ; Auto-reset the variable immediately for the next print after this one\n\n    SET_TEMPERATURE_FAN_TARGET TEMPERATURE_FAN=Mainboard_fan TARGET=1                                              ; Decrease the mainboard target temp to fully turn the fan on\n    \n    M140 S{bed_target_temp}\n    M141 S{chamber_target_temp}\n    G28\n\n    {% if chamber_target_temp > 0 %}                                                                               ; Accelerate chamber heating by using the bed as additional heater    \n        G0 X{bed_center_x} Y{bed_center_y} Z3 F780                                                                 ; Move print bed to perfect postion to help chamber heating\n        M106 P2 S185                                                                                               ; Turn sidefan on to use bed heat and mix air\n        M106 P0 S128                                                                                               ; Turn part cooling fan on to help air mixing\n        TEMPERATURE_WAIT SENSOR=\"heater_generic chamber\" MINIMUM={chamber_target_temp - 5}                         ; Wait for chamber to heat up\n        M106 P2 S0                                                                                                 ; Turn off sidefan\n        M106 P0 S0                                                                                                 ; Turn off part cooling fan                                      \n    {% endif %}\n\n    {% if bed_target_temp !=0 %}\n      TEMPERATURE_WAIT SENSOR=heater_bed MINIMUM={bed_target_temp * 0.95} MAXIMUM={bed_target_temp * 1.05}\n    {% endif %}\n\n    M191 S{chamber_target_temp}                                                                                    ; Set and wait for chamber temperature\n    M190 S{bed_target_temp}                                                                                        ; Set and wait for bed temperature \n    G90                                                                                                            ; Set absolute positioning\n    G1 X{start_position_x} Y{start_position_y} Z{start_position_z} F7800                                           ; Move to start position\n    G28 Z                                                                                                          ; Home Z again for to compensate bed expansion  \n\n    {% if KAMP_deactivated %}\n        {% if \"STATIC_MESH\" in printer.bed_mesh.profiles %}                                                        ; Check if the spicific STATIC_MESH exists\n            M118  Loading 'STATIC_MESH' instead of KAMP.\n            BED_MESH_PROFILE LOAD=STATIC_MESH\n        {% else %}                                                                                                 ; Fallback to KAMP if STATIC_MESH not found\n            M118 ERROR: 'STATIC_MESH' not found! Using fallback: KAMP Adaptive Mesh.\n            BED_MESH_CLEAR                                                                                         ; Clear previous adaptive mesh\n            BED_MESH_CALIBRATE PROFILE=adaptive ADAPTIVE=1                                                         ; Start adaptive meshing\n        {% endif %}\n    {% else %}                                                                                                     ; Standard operation\n        {% if printer.toolhead.homed_axes|length < 3 %}\n            G28\n        {% endif %}\n        BED_MESH_CLEAR                                                                                             ; Clear previous adaptive mesh\n        BED_MESH_CALIBRATE PROFILE=adaptive ADAPTIVE=1                                                             ; Start adaptive meshing\n    {% endif %}\n\n    PRIME_NOZZLE hotend_target_temp={hotend_target_temp}\n    M109 S{hotend_target_temp}                                                                                     ; Set and wait for hotend temperature \n\n\n[gcode_macro PRINT_END]\ngcode:\n    {% set max_x = printer.configfile.config[\"stepper_x\"][\"position_max\"]|float %}\n    {% set max_y = printer.configfile.config[\"stepper_y\"][\"position_max\"]|float %}\n    {% set max_z = printer.configfile.config[\"stepper_z\"][\"position_max\"]|float %}\n    {% set z_clearance = 50 %}\n\n    {% if (printer.toolhead.position.z + z_clearance) < max_z %}\n        {% set z_hop = 2  %}\n    {% else %}\n        {% set z_hop = 0 %}\n    {% endif %}\n\n    M106 P0 S0                                                                                                      ; Turn off part cooling fan\n    M106 P2 S0                                                                                                      ; Turn off side fan\n    M106 P3 S0                                                                                                      ; Turn off activated charcoal fan\n\n    M104 S0                                                                                                         ; Turn off hotend\n    M140 S0                                                                                                         ; Turn off heated bed\n    M141 S0                                                                                                         ; Turn off heated chamber\n\n    G91                                                                                                             ; Relative positioning\n    G0 Z{z_hop} E-4.0 F3600                                                                                         ; Move nozzle up and retract filament\n    G90                                                                                                             ; Absolute positioning\n    G0 X{max_x/2} Y{max_y-40} F20000                                                                                ; Move nozzle to remove stringing\n    _Z_CLEARANCE DISTANCE={z_clearance}                                                                             ; Lower bed\n    M400                                                                                                            ; Wait for buffer to clear\n    G92 E0                                                                                                          ; Zero the extruder\n\n    M220 S100                                                                                                       ; Set feedrate (speed percentage) back to 100%\n    M221 S100                                                                                                       ; Set flow percentage back to 100%\n\n    SET_IDLE_TIMEOUT TIMEOUT={printer.configfile.settings.idle_timeout.timeout}                                     ; Set timeout back to configured value\n    CLEAR_PAUSE                                                                                                     ; Ensure pause state is cleared if applicable\n\n    M84                                                                                                             ; Disable steppers\n    SET_TEMPERATURE_FAN_TARGET TEMPERATURE_FAN=Mainboard_fan TARGET=45                                              ; Reset the mainboard fan temp\n    BEEP I=2 DUR=500                                                                                                ; Alert at the end of the print (if sound is enabled)\n\n\n[gcode_macro PAUSE]\nrename_existing: BASE_PAUSE\ngcode:\n    {% set z_hop = params.Z|default(30)|int %}                                                                     ; Z hop amount\n    \n    {% if printer['pause_resume'].is_paused|int == 0 %}     \n        SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=zhop VALUE={z_hop}                                                ; Set Z hop variable for reference in resume macro\n        SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=etemp VALUE={printer['extruder'].target}                          ; Set hotend temperature variable for reference in resume macro\n        SAVE_GCODE_STATE NAME=PAUSE                                                                                ; Save current position for resume\n        BASE_PAUSE                                                                                                 ; Pause print\n        {% if (printer.gcode_move.position.z + z_hop) < printer.toolhead.axis_maximum.z %}                         ; Check that Z hop doesn't exceed Z max\n            G91                                                                                                    ; Use Relative positioning\n            G1 Z{z_hop} F600                                                                                       ; Raise Z up by Z hop amount\n        {% else %}\n            SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=zhop VALUE=0                                                  ; Set Z hop to 0 if exceeds max\n        {% endif %}\n        SAVE_GCODE_STATE NAME=PAUSEPARK2\n        G90                                                                                                        ; Absolute positioning\n        G1 X{printer.toolhead.axis_maximum.x/2} Y{printer.toolhead.axis_maximum.y-40} F6000                        ; Park toolhead  at rear center\n        SAVE_GCODE_STATE NAME=PAUSEPARK                                                                            ; Save parked position in case toolhead is moved during the pause (otherwise the return zhop can error)\n        M104 S0                                                                                                    ; Turn off hotend\n        SET_IDLE_TIMEOUT TIMEOUT=43200                                                                             ; Set timeout to 12 hours\n        SET_STEPPER_ENABLE STEPPER=extruder enable=0                                                               ; Disable extruder stepper\n    {% endif %}\n\n\n[gcode_macro RESUME]\nrename_existing: BASE_RESUME\nvariable_zhop: 0\nvariable_etemp: 0\ngcode:\n    {% set e = params.E|default(2.5)|int %}                                                                        ; Hotend prime amount (in mm)\n\n    {% if printer['pause_resume'].is_paused|int == 1 %}\n        SET_IDLE_TIMEOUT TIMEOUT={printer.configfile.settings.idle_timeout.timeout}                                ; Set idle timeout back to configured value\n        {% if etemp > 0 %}\n            M109 S{etemp|int}                                                                                      ; Wait for hotend to heat up\n        {% endif %}\n        RESTORE_GCODE_STATE NAME=PAUSEPARK MOVE=1 MOVE_SPEED=150                                                   ; Restore back to parked position in case toolhead was moved during pause (otherwise the return zhop can error)  \n        G91                                                                                                        ; Relative positioning\n        M83                                                                                                        ; Relative extruder positioning\n        {% if printer[printer.toolhead.extruder].temperature >= printer.configfile.settings.extruder.min_extrude_temp %}\n            G1  E{e} F900                                                                                          ; Prime nozzle\n        {% endif %}  \n        RESTORE_GCODE_STATE NAME=PAUSEPARK2 MOVE=1 MOVE_SPEED=150                           \n        RESTORE_GCODE_STATE NAME=PAUSE MOVE=1 MOVE_SPEED=10                                                        ; Restore position\n        BASE_RESUME                                                                                                ; Resume print\n        G90                                                                                                        ; Absolute positioning\n    {% endif %}\n\n\n[gcode_macro CANCEL_PRINT]\nrename_existing: BASE_CANCEL_PRINT\ngcode:\n    {% set max_z = printer.configfile.config[\"stepper_z\"][\"position_max\"]|float %}\n    {% if (printer.toolhead.position.z + 12) < max_z %}\n        {% set z_hop = 2  %}\n    {% else %}\n        {% set z_hop = 0 %}\n    {% endif %}\n\n    G91                                                                                                            ; Relative positioning\n    G1 Z{z_hop} F600                                                                                               ; Do a tiny z-hop\n    G90                                                                                                            ; Absolute positioning\n\n    G1 X{printer.toolhead.axis_maximum.x/2} Y{printer.toolhead.axis_maximum.y-40} F12000\n    CLEAR_PAUSE\n    SDCARD_RESET_FILE\n\n    PRINT_END\n    BASE_CANCEL_PRINT\n\n\n[gcode_macro _Z_CLEARANCE]\ndescription: Lower the bed to give some clearance\ngcode:\n    {% set current_z_height = printer.toolhead.position.z %}\n    {% set max_z_height = printer.toolhead.axis_maximum.z %}\n    {% set target_z_height = current_z_height + params.DISTANCE|default(5)|float %}\n\n    G90                                                                                                            ; Absolute positioning\n    G1 Z { [target_z_height, max_z_height]|min }\n\n\n########################################\n#  Filament Macros\n########################################\n[gcode_macro UNLOAD_FILAMENT]\ndescription: Unloads filament from toolhead\ngcode:\n  {% set EXTRUDER_TEMP = params.TEMP|default(230)|int %}\n  {% set CURRENT_TEMP = printer.extruder.temperature|int %}\n  {% if CURRENT_TEMP < EXTRUDER_TEMP %}\n    M104 S{EXTRUDER_TEMP}                                                                                          ; heat up the hotend\n  {% endif %}\n   \n  GO_TO_POOP_SHOOT                                                                                                 ; go to poop shoot\n\n  {% if CURRENT_TEMP < EXTRUDER_TEMP %}\n    M109 S{EXTRUDER_TEMP}                                                                                          ; heat up the hotend\n  {% endif %}  \n  SET_STEPPER_ENABLE STEPPER=extruder ENABLE=1                                                                     ; enable extruder stepper \n  M83                                                                                                              ; set extruder to relative mode\n  G1 E5 F150                                                                                                       ; extrude a small amount to elimate soften the filament\n  G1 E-8 F1800                                                                                                     ; quickly retract a small amount to elimate stringing\n  G4 P200                                                                                                          ; pause for a short amount of time\n  G1 E-50 F300                                                                                                     ; retract slowly the rest of the way\n  M104 S0                                                                                                          ; turn off hotend\n  LEAVE_POOP_SHOOT                                                                                                 ; leave poop shoot\n  M400                                                                                                             ; wait for moves to finish\n  M118 Unload Complete!\n\n\n[gcode_macro LOAD_FILAMENT]\ndescription: Loads filament to toolhead\ngcode:\n  {% set EXTRUDER_TEMP = params.TEMP|default(230)|int %}\n  {% set CURRENT_TEMP = printer.extruder.temperature|int %}\n  {% if CURRENT_TEMP < EXTRUDER_TEMP %}\n    M104 S{EXTRUDER_TEMP}                                                                                          ; heat up the hotend\n  {% endif %}\n   \n  GO_TO_POOP_SHOOT                                                                                                 ; go to poop shoot\n  \n  {% if CURRENT_TEMP < EXTRUDER_TEMP %}\n    M109 S{EXTRUDER_TEMP}                                                                                          ; heat up the hotend\n  {% endif %} \n  SET_STEPPER_ENABLE STEPPER=extruder ENABLE=1                                                                     ; enable extruder stepper  \n  M83                                                                                                              ; set extruder to relative mode\n  G1 E5 F120                                                                                                       ; feed filament\n  G1 E5 F300                                                                                                       ; feed filament\n  G1 E40 F600                                                                                                      ; feed filament\n  G1 E15 F300                                                                                                      ; feed filament\n  G1 E15 F120                                                                                                      ; feed filament\n  G4 P200                                                                                                          ; pause for a short amount of time\n  G1 E10 F90                                                                                                       ; feed filament\n  M104 S0                                                                                                          ; turn off hotend\n  LEAVE_POOP_SHOOT                                                                                                 ; leave poop shoot\n  M400                                                                                                             ; wait for moves to finish\n  M118 Load Complete!\n\n\n# Filament runout sensor enable/disable\n[gcode_macro M8029]\ngcode:\n     {% if params.D is defined %}\n       {% if (params.D|int)==1 %} \n        SET_FILAMENT_SENSOR SENSOR=filament_tangle_sensor ENABLE=1\n       {% endif %}\n       {% if (params.D|int)==0 %} \n        SET_FILAMENT_SENSOR SENSOR=filament_tangle_sensor ENABLE=0\n       {% endif %}\n     {% endif %}\n\n\n########################################\n# Fan Macros\n########################################\n# Set Fan Speed macro\n# Mainly name castings for nicer web interface names and display functionality\n[gcode_macro M106]\nrename_existing: M106.1\ngcode:\n    {% if params.P is defined %}\n      {% if params.S is defined %}\n        {% set speed = 0.003921*params.S|int %}\n        {% if (params.P|int) == 0 %}\n          M106.1 S{params.S|int}\n        {% elif (params.P|int) == 2 %}\n          SET_FAN_SPEED FAN=sidefan SPEED={speed}\n        {% elif (params.P|int) == 3 %}\n          SET_FAN_SPEED FAN=filterfan SPEED={speed}\n        {% else %}\n          SET_FAN_SPEED FAN=fan{params.P|int} SPEED={speed}\n        {% endif %}\n      {% else %}\n        {% if (params.P|int) == 0 %}\n          M106.1 S255\n        {% elif (params.P|int) == 2 %}\n          SET_FAN_SPEED FAN=sidefan SPEED=1\n        {% elif (params.P|int) == 3 %}\n          SET_FAN_SPEED FAN=filterfan SPEED=1\n        {% else %}\n          SET_FAN_SPEED FAN=fan{params.P|int} SPEED=1\n        {% endif %}\n      {% endif %}\n    {% endif %} \n\n    {% if params.T is defined %}\n      {% if (params.T|int) == -2 %}\n        {% if params.S is defined %}\n          {% set speed = 0.003921*params.S|int %}\n          SET_FAN_SPEED FAN=filterfan SPEED={speed}\n        {% else %}\n          SET_FAN_SPEED FAN=filterfan SPEED=1\n        {% endif %}\n      {% endif %}\n    {% endif %}\n\n    {% if params.P is undefined %}\n      {% if params.T is undefined %}\n        {% if params.S is defined %}\n          M106.1 S{params.S|int}\n        {% else %}\n          M106.1 S255\n        {% endif %}\n      {% endif %}\n    {% endif %}\n\n[gcode_macro M107]\nrename_existing: M107.1\ngcode:  \n    M106.1 S0\n\n\n########################################\n# Temperature Macros\n########################################\n# Wait for Hotend Temperature\n[gcode_macro M109]\nrename_existing: M109.1\ngcode:\n    #Parameters\n    {% set s = params.S|float %}\n\n    M104 {% for p in params %}{'%s%s' % (p, params[p])}{% endfor %}                                              ; Set hotend temp\n    {% if s != 0 %}\n        TEMPERATURE_WAIT SENSOR=extruder MINIMUM={s} MAXIMUM={s+1}                                               ; Wait for hotend temp (within 1 degree)\n    {% endif %}\n\n\n# PID autotune\n[gcode_macro M303]\ngcode:\n    {% if params.E is defined %}\n     {% if params.S is defined %}\n        {% if (params.E|int)==-1 %} \n         PID_CALIBRATE HEATER=heater_bed TARGET={params.S|int}\n        {% endif %}\n        {% if (params.E|int)==0 %}\n         PID_CALIBRATE HEATER=extruder TARGET={params.S|int}\n        {% endif %}\n     {% endif %}\n  {% endif %}\n\n\n# Set chamber temperature\n[gcode_macro M141]\ngcode:\n    {% if printer[\"heater_generic chamber\"] is defined %}\n        {% set chamber_target_temp = params.S|float %}\n        SET_HEATER_TEMPERATURE HEATER=chamber TARGET={([chamber_target_temp, 65]|min)}\n    {% endif %}\n\n\n# Set wait chamber temperature\n[gcode_macro M191]\ngcode:\n    #Parameters\n    {% set chamber_target_temp = params.S|float %}\n\n    {% if chamber_target_temp == 0 %}\n        M118 Chamber heater off\n    {% else %}\n        M141 S{chamber_target_temp}\n        TEMPERATURE_WAIT SENSOR=\"heater_generic chamber\" MINIMUM={([chamber_target_temp, 65]|min)-2} MAXIMUM={chamber_target_temp + 5}  \n        M118 Chamber at target temperature\n    {% endif %}\n\n\n########################################\n# Sound Macros\n########################################\n[gcode_macro BEEP]\ngcode:\n    # Parameters\n    {% set i = params.I|default(1)|int %}                                                                        ; Iterations (number of times to beep).\n    {% set dur = params.DUR|default(100)|int %}                                                                  ; Duration/wait of each beep in ms. Default 100ms.\n\n    {% if printer[\"output_pin sound\"].value|int == 1 %}\n        {% for iteration in range(i|int) %}\n            SET_PIN PIN=buzzer VALUE=1\n            G4 P{dur}\n            SET_PIN PIN=buzzer VALUE=0\n            G4 P{dur}\n        {% endfor %}\n    {% endif %}\n\n\n[gcode_macro beep_on]\ngcode:\n    SET_PIN PIN=buzzer VALUE=1\n\n\n[gcode_macro beep_off]\ngcode:\n    SET_PIN PIN=buzzer VALUE=0\n\n\n########################################\n# Z-height Macros\n########################################\n# Bed Leveling (Unified)\n[gcode_macro G29]\nvariable_k:1\ngcode:\n    {% set temp = printer[\"heater_generic chamber\"].target %}\n      M141 S0\n    {% if temp > 0 %}\n      G4 P15000\n    {% endif %}\n\n    {% if k|int==1 %}\n        BED_MESH_CLEAR                                                                                           ; Clear levelling data\n        BED_MESH_CALIBRATE ADAPTIVE=1 ADAPTIVE_MARGIN=5                                                          ; Start adaptive meshing\n    {% endif %}   \n    M141 S{temp}\n\n\n# Babystep\n[gcode_macro M290]\ngcode:\n   SET_GCODE_OFFSET Z_ADJUST={params.Z}\n\n\n########################################\n# Tuning Macros\n########################################\n[gcode_macro SHAPER_CALIBRATE]\nrename_existing: RESHAPER_CALIBRATE\ngcode:\n    RESHAPER_CALIBRATE FREQ_START=30 FREQ_END=130\n\n\n# Linear Advance Factor\n[gcode_macro M900]\ngcode:\n    {% if params.K is defined %} \n          SET_PRESSURE_ADVANCE ADVANCE={params.K}\n    {% endif %}  \n    {% if params.T is defined %}    \n       SET_PRESSURE_ADVANCE SMOOTH_TIME={params.T}\n    {% endif %} \n\n\n# Set Starting Acceleration\n[gcode_macro M204]\nrename_existing: M99204\ngcode:\n    {% if params.S is defined %}\n        {% set s = params.S|float %}\n    {% endif %}\n    {% if params.P is defined %}\n    {% if params.T is defined %}\n        {% set s = [params.P|float ,params.T|float] | min %}\n    {% endif %}\n    {% endif %}\n\n    SET_VELOCITY_LIMIT ACCEL={s}\n    SET_VELOCITY_LIMIT ACCEL_TO_DECEL={s/2}\n\n\n# Bed leveling\n# For more information, see https://www.klipper3d.org/Manual_Level.html#adjusting-bed-leveling-screws-using-the-bed-probe\n[gcode_macro LEVEL_BED]\ndescription: \"Measure bed and calculate screw adjustments for manual bed leveling\"\ngcode:\n    G28                                                                                                         ; Home all\n    SCREWS_TILT_CALCULATE                                                                                       ; Perform measurements and output screw adjustments\n\n\n# Probe Calibration\n# For more information, see https://www.klipper3d.org/Probe_Calibrate.html\n[gcode_macro CALIBRATE_Z_OFFSET]\ndescription: \"Calibrate the Z offset using the probe\"\ngcode:\n    {% set max_x = printer.configfile.config[\"stepper_x\"][\"position_max\"]|float %}\n    {% set max_y = printer.configfile.config[\"stepper_y\"][\"position_max\"]|float %}\n\n    G28                                                                                                         ; Home all\n    G0 Z10                                                                                                      ; Increase z clearance\n    G0 X{max_x/2} Y{max_y-40} F6000                                                                             ; Move to bed center \n    PROBE_CALIBRATE                                                                                             ; Perform a probe calibration\n\n\n# Nozzle PID tuning\n# For more information, see https://www.klipper3d.org/Config_checks.html#calibrate-pid-settings\n[gcode_macro NOZZLE_PID_TUNE]\ndescription: \"Perform PID tuning for the nozzle heater\"\ngcode:\n    PID_CALIBRATE HEATER=extruder TARGET=220                                                                    ; PID tune the nozzle\n\n\n# Bed PID tuning\n# For more information, see https://www.klipper3d.org/Config_checks.html#calibrate-pid-settings\n[gcode_macro BED_PID_TUNE]\ndescription: \"Perform PID tuning for the bed heater\"\ngcode:\n    PID_CALIBRATE HEATER=heater_bed TARGET=80                                                                   ; PID tune the bed\n\n\n########################################\n# Macros for display functionallity\n########################################\n[gcode_macro INPUT_SHAPING_CALIBRATE]\ndescription: \"Perform Input Shaping calibration and save the results to printer.cfg\"\ngcode:\n    SHAPER_CALIBRATE                                                                                            ; Step 1: Perform the Input Shaping calibration\n    PAUSE                                                                                                       ; Step 2: Pause to allow the calibration to complete\n    SAVE_CONFIG                                                                                                 ; Step 3: Save the configuration to printer.cfg\n    RESTART                                                                                                     ; Step 4: Restart the firmware to apply the new settings\n\n\n"
  },
  {
    "path": "config_section/template/printer.cfg",
    "content": "# Plus4 config created by Phil1988(github)/coco.33(discord) on 04.05.2025\n# For more information check out my wiki: https://github.com/Phil1988/FreeDi/wiki\n\n\n#####################################################################\n# Kinematics\n#####################################################################\n[printer]\nkinematics:corexy\nmax_velocity: 600\nmax_accel: 20000\nmax_z_velocity: 20\nmax_z_accel: 500\nsquare_corner_velocity: 8\n\n\n#####################################################################\n# Motherboard and periphery\n#####################################################################\n[temperature_sensor Mainboard_RK3328]\nsensor_type: temperature_host\nmin_temp: 10\nmax_temp: 100\n\n[mcu]\nserial: /dev/ttyS0\nrestart_method: command\nbaud: 500000\n\n[temperature_sensor Mainboard_STM32F402]\nsensor_type: temperature_mcu\nsensor_mcu: mcu\n\n[mcu Toolhead]\nserial: /dev/ttyS2\nrestart_method: command\nbaud: 500000\n\n[temperature_sensor Toolhead_STM32F103XE]\nsensor_type: temperature_mcu\nsensor_mcu: Toolhead\nmin_temp: 0\nmax_temp: 100\n\n\n#####################################################################\n# Features\n#####################################################################\n# For saving GCODE files\n[virtual_sdcard]\npath: ~/printer_data/gcodes\non_error_gcode: CANCEL_PRINT\n\n# For enabling pause/resume\n[pause_resume]\n\n# Activating exclude objects feature\n[display_status]\n[exclude_object]\n\n# Expanding idle timeout\n[idle_timeout]\ntimeout: 5400   ; 90min timeout\n\n# Activating GCODE arc feature\n[gcode_arcs]\nresolution: 1.0\n\n# Allowing free move (can be dangerous!)\n[force_move]\nenable_force_move: True\n\n# Activating responses\n[respond]\ndefault_type: echo\n\n\n#####################################################################\n# FreeDi\n#####################################################################\n[include freedi.cfg] \n\n\n#####################################################################\n# Macros\n#####################################################################\n[include macros.cfg]\n\n\n#####################################################################\n# Input shaping\n#####################################################################\n[resonance_tester]\naccel_chip: adxl345\nprobe_points:\n    150, 150, 10\naccel_per_hz: 75\nsweeping_period: 0\nmax_smoothing: 0.5\n    \n[adxl345]\ncs_pin: Toolhead:PA4\nspi_software_sclk_pin: Toolhead:PA5\nspi_software_mosi_pin: Toolhead:PA7\nspi_software_miso_pin: Toolhead:PA6\naxes_map: -x, z, -y\n\n[input_shaper]\nshaper_type_x: mzv\nshaper_freq_x: 57.6\nshaper_type_y: mzv\nshaper_freq_y: 46.6\n\n\n#####################################################################\n# Hotend\n#####################################################################\n[extruder]\nstep_pin: Toolhead:PB9\ndir_pin: Toolhead:PB8\nenable_pin: !Toolhead:PC15\nrotation_distance: 53.7\ngear_ratio: 1517:170\nmicrosteps: 16\nfull_steps_per_rotation: 200\nnozzle_diameter: 0.400\nfilament_diameter: 1.75\nmin_temp: 0\nmax_temp: 360\nmin_extrude_temp: 170\nsmooth_time: 0.000001\nstep_pulse_duration: 0.000002\n\nheater_pin: Toolhead:PB3\nsensor_type: MAX6675\nsensor_pin: Toolhead:PB12\nmax_power: 1.0\ncontrol: pid  \npid_Kp: 33.879\npid_Ki: 6.453\npid_Kd: 44.467\n\nspi_speed: 100000\nspi_software_sclk_pin: Toolhead:PB13\nspi_software_mosi_pin: Toolhead:PA11\nspi_software_miso_pin: Toolhead:PB14\n\npressure_advance: 0.032\npressure_advance_smooth_time: 0.03\nmax_extrude_cross_section:500\ninstantaneous_corner_velocity: 10.000\nmax_extrude_only_distance: 1000.0\nmax_extrude_only_velocity: 5000\nmax_extrude_only_accel: 5000\n\n[verify_heater extruder]\nmax_error: 120\ncheck_gain_time:20\nhysteresis: 5\nheating_gain: 1\n\n\n#####################################################################\n# Heated bed\n#####################################################################\n[heater_bed]\nheater_pin: PB10\nsensor_type: NTC 100K MGB18-104F39050L32\nsensor_pin: PA0\nmax_power: 1.0\ncontrol: pid\npid_kp: 70.638\npid_ki: 0.671\npid_kd: 1859.554\nmin_temp: -50\nmax_temp: 125\npwm_cycle_time: 0.02 # for 50Hz line power \n#pwm_cycle_time: 0.016 # for 60Hz line power\n\n[verify_heater heater_bed]\nmax_error: 200\ncheck_gain_time: 360\nhysteresis: 5\nheating_gain: 1\n\n\n#####################################################################\n# Bed mesh\n#####################################################################\n[bed_mesh]\nspeed: 150               \nhorizontal_move_z: 2.6   \nmesh_min: 25,10\nmesh_max: 295,295   \nprobe_count: 9,9     \nalgorithm: bicubic\nbicubic_tension: 0.3\nmesh_pps: 4, 4\n\n\n#####################################################################\n# Probe\n#####################################################################\n#!# Pay attention to this section and compare it with your stock backup config\n[probe]\npin: ^!Toolhead:PA10\nx_offset: 25\ny_offset: 1.3\nz_offset: 1.00             #!# change this to 0 if you get a \"Probe triggered prior to movement\" - Error\nspeed: 5\nsamples: 2\nsamples_result: average\nsample_retract_dist: 0.7\nsamples_tolerance: 0.08\nsamples_tolerance_retries: 3\n\n# Check this for documentation https://github.com/frap129/qidi_auto_z_offset\n# Add AUTO_Z_LOAD_OFFSET to your PRINT_START macro to load the value every time you start a print. \n# If you make adujstments to the offset by micro-stepping durring a print, you can save that with AUTO_Z_SAVE_GCODE_OFFSET and SAVE_CONFIG\n\n[auto_z_offset]\npin: PC1\n# Adjust this z_offset value for a good first layer: \n# decrease if lines are squished (eg -0.2 -> -0.25)\n# increase if lines are thin/not sticking (-0.2 -> -0.15)\nz_offset: -0.2 \ncalibrated_z_offset: -1.00\nspeed: 13\nprobe_accel: 50\nsamples: 5\nsamples_result: median\nsamples_tolerance: 0.013\nsamples_tolerance_retries: 5\noffset_samples: 3\nprepare_gcode:\n   G90\n   G0 Z3\n   G91\n   SET_PIN PIN=bed_sensor VALUE=0\n   M204 S10000\n   {% set i = 6 %}\n   {% for iteration in range(i|int) %}\n       G1 Z5 F1200\n       G1 Z-5 F1200\n   {% endfor %}\n   G1 Z3\n   G90\n   SET_PIN PIN=bed_sensor VALUE=1\n\n[output_pin bed_sensor]\npin: !PA14\npwm: false\nshutdown_value:0\nvalue:0\n\n#####################################################################\n# Heated chamber\n#####################################################################\n[temperature_sensor chamber_sensor]\nsensor_type: NTC 100K MGB18-104F39050L32\nsensor_pin: PA1\n\n\n[heater_generic chamber]\nheater_pin: PC8\n#!# Caution!\n#set max_power to 0.4 for 110V\n#set max_power to 0.7 for 220V\n#set max_power to 1.0 if you are using a quality aftermarket SSR with a heat sink\nmax_power: 0.4                #!# Pay attention to this value and compare it with your stock backup config and with caution (read the comments)\n#sensor_type: NTC 100K MGB18-104F39050L32\n#sensor_pin: PA1\nsensor_type: temperature_combined\nsensor_list: temperature_sensor Toolhead_STM32F103XE, temperature_sensor Toolhead_STM32F103XE, temperature_sensor Toolhead_STM32F103XE, temperature_sensor chamber_sensor\ncombination_method: mean\nmaximum_deviation: 70\ncontrol: pid\npid_Kp: 63.418 \npid_Ki: 1.342 \npid_Kd: 749.125\nmin_temp: -100\nmax_temp: 75\n\n[verify_heater chamber]\nmax_error: 400\ncheck_gain_time: 600\nhysteresis: 5\nheating_gain: 2\n\n[temperature_sensor Chamber_Heater]\nsensor_type: NTC 100K MGB18-104F39050L32\nsensor_pin: PC2\nmin_temp: -100\nmax_temp: 140\n\n\n########################################\n# Filament sensors\n########################################\n[filament_switch_sensor filament_tangle_sensor]\nswitch_pin: PC3\npause_on_runout: True\nrunout_gcode:\n            M118 Filament tangled!\nevent_delay: 3.0\npause_delay: 0.5\n\n[hall_filament_width_sensor]\nadc1: Toolhead:PA2\nadc2: Toolhead:PA3\ncal_dia1: 1.50\ncal_dia2: 2.0\nraw_dia1: 14206\nraw_dia2: 15278\ndefault_nominal_filament_diameter: 1.75\nmax_difference: 0.00\nmeasurement_delay: 50\nenable: True\nenable_flow_compensation: False\nmeasurement_interval: 3\nlogging: False\nmin_diameter: 1.00\nuse_current_dia_while_delay: False\npause_on_runout: True\nrunout_gcode:\n            M118 Filament run out!\nevent_delay: 3.0\npause_delay: 0.5\n\n\n#####################################################################\n# Fans\n#####################################################################\n## Part cooling fan \n# [fan_generic partfan]\n# pin: Toolhead:PA8\n# max_power: 1.0\n# cycle_time: 0.0100\n# hardware_pwm: false\n# kick_start_time: 0.200\n# off_below: 0.08\n# shutdown_speed: 0\n[fan]\npin: Toolhead:PA8\nmax_power: 1.0\ncycle_time: 0.0100\nhardware_pwm: false\nkick_start_time: 0.200\noff_below: 0.08\nshutdown_speed: 0.0\n\n## Big side radial turbo fan\n[fan_generic sidefan]\npin: PA8\nmax_power: 1.0\ncycle_time: 0.0100\nhardware_pwm: false\nkick_start_time: 0.250\noff_below: 0.3\nshutdown_speed: 0\n\n## Activated charcoal blowing fan\n[fan_generic filterfan]\npin: PC9\nmax_power: 1.0\ncycle_time: 0.0100\nhardware_pwm: false\nkick_start_time: 0.200\noff_below: 0.3\nshutdown_speed: 0\n\n## Chamber heater fan\n[heater_fan chamber_heater_fan]\npin: PA4\nmax_power: 1.0\nshutdown_speed: 0\nkick_start_time: 0.5\nheater: chamber\nfan_speed: 1.0\noff_below: 0\nheater_temp: 40 \n\n## Cold end and toolhead housing fans\n[heater_fan hotend_fan]\npin: Toolhead:PB5\nmax_power: 1.0\nshutdown_speed: 1.0\nkick_start_time: 0.5\nheater: extruder\nheater_temp: 50.0\nfan_speed: 1.0\noff_below: 0\n\n# Toolhead cooling fan\n[heater_fan hotend_fan2]\npin:Toolhead: PB4\nmax_power: 1.0\nshutdown_speed: 1.0\nkick_start_time: 0.5\nheater: extruder\nheater_temp: 50.0\nfan_speed: 1.0\noff_below: 0\n\n# Toolhead cooling fan\n[heater_fan hotend_fan3]\npin:Toolhead: PB10\nmax_power: 1.0\nshutdown_speed: 1.0\nkick_start_time: 0.5\nheater: extruder\nheater_temp: 50.0\nfan_speed: 1.0\noff_below: 0\n\n#!# Delete the next section if your stock backup config doesnt have it\n## Controllable Mainboard cooling fan\n[temperature_fan Mainboard_fan]\nsensor_type: temperature_host \npin: PC4\nmax_power: 1.0  \ncycle_time: 0.01\nsensor_type: temperature_combined\nsensor_list: temperature_sensor Mainboard_RK3328, temperature_sensor Mainboard_STM32F402\ncombination_method: max                                           # use the maximum reading of the sensors\nmaximum_deviation: 999.9                                          # we don't care about the difference in temperature\nshutdown_speed: 0.0\nkick_start_time: 0.4\noff_below: 0.19\nmin_temp: 0\nmax_temp: 85.0 \ntarget_temp: 42.0\nmin_speed: 0\nmax_speed: 1.0\ncontrol: pid\npid_deriv_time: 2.0\npid_Kp: 5.0\npid_Ki: 2.5\npid_Kd: 3.5\n\n\n#####################################################################\n# Light\n#####################################################################\n## caselight LEDs\n[output_pin caselight]\npin: PC7\npwm: true\ncycle_time: 0.0100\nshutdown_value:0\nvalue:1\n\n\n#####################################################################\n# Buzzer\n#####################################################################\n## Buzzer\n[output_pin buzzer]\npin: PA2\npwm: false\nshutdown_value:0\nvalue:0\n\n[output_pin sound]\npin: Toolhead:PA1\nvalue:0\n\n\n#####################################################################\n# Power outage shutdown\n#####################################################################\n[output_pin pwc]\npin: PA3\npwm: False\nvalue: 1\nshutdown_value: 1\n\n\n#####################################################################\n# Drives\n#####################################################################\n[stepper_x]\nstep_pin: PB4\ndir_pin: !PB3\nenable_pin: !PB5\nmicrosteps: 32\nrotation_distance: 38.82\nfull_steps_per_rotation: 200 \nendstop_pin: tmc2240_stepper_x:virtual_endstop\nposition_min: -1.5\nposition_endstop: -1.5\nposition_max: 307\nhoming_speed: 55\nhoming_retract_dist:0\nhoming_positive_dir:False\nstep_pulse_duration:0.0000001\n\n[stepper_y]\nstep_pin: PC14\ndir_pin: !PC13\nenable_pin: !PC15\nmicrosteps: 32\nrotation_distance: 38.82\nfull_steps_per_rotation:200  \nendstop_pin: tmc2240_stepper_y:virtual_endstop\nposition_min: -2\nposition_endstop: -2\nposition_max: 325\nhoming_speed: 55\nhoming_retract_dist: 0\nhoming_positive_dir: False\nstep_pulse_duration: 0.0000001\n\n[stepper_z]\nstep_pin: PB1\ndir_pin: PB6\nenable_pin: !PB0\nmicrosteps: 16\nrotation_distance: 4\nfull_steps_per_rotation: 200\nendstop_pin: probe:z_virtual_endstop\nposition_max:285\nposition_min: -4\nhoming_speed: 13\nhoming_retract_dist: 8.0\nsecond_homing_speed: 5\nhoming_positive_dir: False\nstep_pulse_duration: 0.000002\n\n[stepper_z1]\nstep_pin: PC10\ndir_pin: PA15\nenable_pin: !PC11\nmicrosteps: 16\nrotation_distance: 4\nfull_steps_per_rotation: 200\nstep_pulse_duration: 0.000002\n\n#####################################################################\n# Steppers configuration\n#####################################################################\n[tmc2209 extruder]\nuart_pin: Toolhead:PC13\ninterpolate: False\nrun_current: 0.714             #!# Pay attention to this value and compare it with your stock backup config\nstealthchop_threshold: 0\nsense_resistor: 0.075\n\n[tmc2240 stepper_x]\ncs_pin: PD2\nspi_software_sclk_pin: PA5\nspi_software_mosi_pin: PA7\nspi_software_miso_pin: PA6\nspi_speed: 200000\nrun_current: 1.07               #!# Pay attention to this value and compare it with your stock backup config\ninterpolate: False\nstealthchop_threshold: 0\ndiag0_pin: !PB8\ndriver_SGT: 1\nrref: 12000\n\n[tmc2240 stepper_y]\ncs_pin: PB9\nspi_software_sclk_pin: PA5\nspi_software_mosi_pin: PA7\nspi_software_miso_pin: PA6\nspi_speed: 200000\nrun_current: 1.07              #!# Pay attention to this value and compare it with your stock backup config\ninterpolate: False\nstealthchop_threshold: 0\ndiag0_pin: !PC0\ndriver_SGT:1\nrref: 12000\n\n[tmc2209 stepper_z]\nuart_pin: PB7\nrun_current: 1.07              #!# Pay attention to this value and compare it with your stock backup config\ninterpolate: False\nstealthchop_threshold: 9999999999\ndiag_pin: ^PA13\nsense_resistor: 0.075\n\n\n[tmc2209 stepper_z1]\nuart_pin: PC5\nrun_current: 1.07              #!# Pay attention to this value and compare it with your stock backup config\ninterpolate: False\nstealthchop_threshold: 9999999999\ndiag_pin: ^PC12\nsense_resistor: 0.075\n\n#####################################################################\n# Bed tilt adjust\n#####################################################################\n[z_tilt]\nz_positions:\n    -17.5,138.5\n    335.7,138.5\n\npoints:\n    0,138.5\n    255,138.5\n\nspeed: 150\nhorizontal_move_z: 10\nretries: 5\nretry_tolerance: 0.013\n\n#####################################################################\n# Screws tilt adjust\n#####################################################################\n[screws_tilt_adjust] \nhorizontal_move_z: 5\nscrew_thread: CW-M4\nspeed: 300\n\nscrew1:0,20\nscrew1_name: Front left\nscrew2: 260,20\nscrew2_name: Front right\nscrew3: 260,280\nscrew3_name: Back right\nscrew4: 0,280\nscrew4_name: Back left\n\n"
  },
  {
    "path": "helpers/AutoFlasher.service",
    "content": "[Unit]\nDescription=Toolhead & MCU Flash Service\nAfter=klipper.service\n\n[Service]\nType=oneshot\nExecStart=/home/{{USER}}/FreeDi/helpers/klipper_auto_flasher.sh\nRemainAfterExit=true\n\n[Install]\nWantedBy=multi-user.target"
  },
  {
    "path": "helpers/FreeDi.service",
    "content": "[Unit]\nDescription=Starting the FreeDi service\nAfter=moonraker.service\n\n[Service]\nType=simple\n#User={{USER}}\nWorkingDirectory=/home/{{USER}}/FreeDi/FreeDiLCD\n# sometimes freedi starts before moonraker is finished (race condition):\nExecStartPre=/usr/bin/bash -c 'PORT=$(awk -F\": \" \"/moonraker_port/ {print \\$2; exit}\" /home/{{USER}}/printer_data/config/freedi.cfg | tr -d \"\\r\\n\"); PORT=${PORT:-7125}; while ! (echo > /dev/tcp/127.0.0.1/$PORT) 2>/dev/null; do sleep 1; done'\nExecStart=/bin/sh -c '/home/{{USER}}/klippy-env/bin/python3 /home/{{USER}}/FreeDi/FreeDiLCD/start.py'\nRestart=always\nRestartSec=5\nKillSignal=SIGINT\n\n[Install]\nWantedBy=multi-user.target\n"
  },
  {
    "path": "helpers/flashtool.py",
    "content": "#!/usr/bin/env python3\n# Script to upload software via Katapult\n#\n# Copyright (C) 2022 Eric Callahan <arksine.code@gmail.com>\n#\n# This file may be distributed under the terms of the GNU GPLv3 license.\nfrom __future__ import annotations\nimport sys\nimport os\nimport termios\nimport fcntl\nimport zlib\nimport json\nimport asyncio\nimport socket\nimport struct\nimport logging\nimport errno\nimport argparse\nimport hashlib\nimport pathlib\nimport shutil\nimport shlex\nimport contextlib\nfrom typing import Dict, List, Optional, Union, Any\nHAS_SERIAL = True\ntry:\n    from serial import Serial, SerialException\nexcept ModuleNotFoundError:\n    HAS_SERIAL = False\n    SerialException = Exception\n\ndef output_line(msg: str) -> None:\n    sys.stdout.write(msg + \"\\n\")\n    sys.stdout.flush()\n\ndef output(msg: str) -> None:\n    sys.stdout.write(msg)\n    sys.stdout.flush()\n\n# Standard crc16 ccitt, take from msgproto.py in Klipper\ndef crc16_ccitt(buf: Union[bytes, bytearray]) -> int:\n    crc = 0xffff\n    for data in buf:\n        data ^= crc & 0xff\n        data ^= (data & 0x0f) << 4\n        crc = ((data << 8) | (crc >> 8)) ^ (data >> 4) ^ (data << 3)\n    return crc & 0xFFFF\n\n\nlogging.basicConfig(level=logging.INFO)\nCAN_FMT = \"<IB3x8s\"\nCAN_READER_LIMIT = 1024 * 1024\n\n# Katapult Defs\nCMD_HEADER = b'\\x01\\x88'\nCMD_TRAILER = b'\\x99\\x03'\nBOOTLOADER_CMDS = {\n    'CONNECT': 0x11,\n    'SEND_BLOCK': 0x12,\n    'SEND_EOF': 0x13,\n    'REQUEST_BLOCK': 0x14,\n    'COMPLETE': 0x15,\n    'GET_CANBUS_ID': 0x16\n}\n\nACK_SUCCESS = 0xa0\nNACK = 0xf1\nACK_ERROR = 0xf2\nACK_BUSY = 0xf3\n\n# Klipper Admin Defs (for jumping to bootloader)\nKLIPPER_ADMIN_ID = 0x3f0\nKLIPPER_SET_NODE_CMD = 0x01\nKLIPPER_REBOOT_CMD = 0x02\n\n# CAN Admin Defs\nCANBUS_ID_ADMIN = 0x3f0\nCANBUS_ID_ADMIN_RESP = 0x3f1\nCANBUS_CMD_QUERY_UNASSIGNED = 0x00\nCANBUS_CMD_SET_NODEID = 0x11\nCANBUS_CMD_CLEAR_NODE_ID = 0x12\nCANBUS_RESP_NEED_NODEID = 0x20\nCANBUS_NODEID_OFFSET = 128\n\n# USB IDs\nKATAPULT_USB_ID = \"1d50:6177\"\nKLIPPER_USB_ID = \"1d50:614e\"\nGS_CAN_USB_ID = \"1d50:606f\"\nSERIAL_BL_REQ = b\"~ \\x1c Request Serial Bootloader!! ~\"\n\nclass FlashError(Exception):\n    pass\n\ndef get_usb_info(usb_path: pathlib.Path) -> Dict[str, Any]:\n    usb_info: Dict[str, Any] = {}\n    id_path = usb_path.joinpath(\"idVendor\")\n    prod_id_path = usb_path.joinpath(\"idProduct\")\n    mfr_path = usb_path.joinpath(\"manufacturer\")\n    prod_path = usb_path.joinpath(\"product\")\n    serial_path = usb_path.joinpath(\"serial\")\n    usb_info[\"usb_id\"] = \"\"\n    if id_path.is_file() and prod_id_path.is_file():\n        vid = id_path.read_text().strip().lower()\n        pid = prod_id_path.read_text().strip().lower()\n        usb_info[\"usb_id\"] = f\"{vid}:{pid}\"\n    usb_info[\"manufacturer\"] = \"unknown\"\n    usb_info[\"product\"] = \"unknown\"\n    usb_info[\"serial_number\"] = \"\"\n    if mfr_path.is_file():\n        usb_info[\"manufacturer\"] = mfr_path.read_text().strip().lower()\n    if prod_path.is_file():\n        usb_info[\"product\"] = prod_path.read_text().strip().lower()\n    if serial_path.is_file():\n        usb_info[\"serial_number\"] = serial_path.read_text().strip().lower()\n    return usb_info\n\ndef get_usb_path(device: pathlib.Path) -> Optional[pathlib.Path]:\n    device_path = device.resolve()\n    if not device_path.exists():\n        return None\n    sys_dev_path = pathlib.Path(\"/sys/class/tty\").joinpath(device_path.name)\n    if not sys_dev_path.exists():\n        return None\n    sys_dev_path = sys_dev_path.resolve()\n    for usb_path in sys_dev_path.parents:\n        dnum_file = usb_path.joinpath(\"devnum\")\n        bnum_file = usb_path.joinpath(\"busnum\")\n        if dnum_file.is_file() and bnum_file.is_file():\n            return usb_path\n    return None\n\ndef get_stable_usb_symlink(device: pathlib.Path) -> pathlib.Path:\n    device_path = device.resolve()\n    ser_by_path_dir = pathlib.Path(\"/dev/serial/by-path\")\n    try:\n        if ser_by_path_dir.exists():\n            for item in ser_by_path_dir.iterdir():\n                if item.samefile(device_path):\n                    return item\n    except OSError:\n        pass\n    return device_path\n\n\n#  Python Port of fasthash6\n#  Host URL: http://github.com/ztanml/fast-hash\n#  Original Copyright:\n#  Copyright (C) 2012 Zilong Tan (eric.zltan@gmail.com)\n#\n#  MIT License\n#\n#  Permission is hereby granted, free of charge, to any person\n#  obtaining a copy of this software and associated documentation\n#  files (the \"Software\"), to deal in the Software without\n#  restriction, including without limitation the rights to use, copy,\n#  modify, merge, publish, distribute, sublicense, and/or sell copies\n#  of the Software, and to permit persons to whom the Software is\n#  furnished to do so, subject to the following conditions:\n#\n#  The above copyright notice and this permission notice shall be\n#  included in all copies or substantial portions of the Software.\n#\n#  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n#  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n#  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n#  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS\n#  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN\n#  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\n#  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n#  SOFTWARE.\nMASK_64 = 0xFFFFFFFFFFFFFFFF\n\ndef mix(val: int) -> int:\n    val ^= val >> 23\n    val = (val * 0x2127599bf4325c37) & MASK_64\n    val ^= val >> 47\n    return val\n\ndef fasthash64(buffer: bytes, seed: int) -> int:\n    m = 0x880355f21e6d1965\n    h = seed ^ ((len(buffer) * m) & MASK_64)\n    long_count = len(buffer) // 8\n    remaining: bytes = buffer\n    if long_count:\n        byte_count = long_count * 8\n        buf = struct.unpack(f\"<{long_count}Q\", buffer[:byte_count])\n        for v in buf:\n            h ^= mix(v)\n            h = (h * m) & MASK_64\n        remaining = buffer[byte_count:]\n    if remaining:\n        v = 0\n        print(remaining)\n        for i in range(len(remaining), 0, -1):\n            v ^= remaining[i -1] << (8 * (i - 1))\n        h ^= mix(v)\n        h = (h * m) & MASK_64\n    return mix(h)\n\ndef convert_usbsn_to_uuid(serial_number: str) -> int:\n    seed = 0xA16231A7\n    chip_id = bytes.fromhex(serial_number)\n    result = fasthash64(chip_id, seed)\n    swapped = 0\n    # The UUID returned by Klipper firmware is byteswapped\n    for i in range(6):\n        swapped |= ((result >> (i * 8)) & 0xFF) << ((5 - i) * 8)\n    return swapped\n\nclass CanFlasher:\n    def __init__(\n        self,\n        node: CanNode,\n        fw_file: pathlib.Path\n    ) -> None:\n        self.node = node\n        self.firmware_path = fw_file\n        self.fw_sha = hashlib.sha1()\n        self.primed = False\n        self.file_size = 0\n        self.block_size = 64\n        self.block_count = 0\n        self.app_start_addr = 0\n        self.klipper_dict: Optional[Dict[str, Any]] = None\n        self._check_binary()\n\n    def _check_binary(self) -> None:\n        \"\"\"\n        Extract klipper.dict from binary\n        \"\"\"\n        fw_name = self.firmware_path.name.lower()\n        if fw_name != \"klipper.bin\" or not self.firmware_path.is_file():\n            return\n        bin_data = self.firmware_path.read_bytes()\n        klipper_dict: Dict[str, Any] = {}\n        for idx in range(len(bin_data)):\n            try:\n                uncmp_data = zlib.decompress(bin_data[idx:])\n                klipper_dict = json.loads(uncmp_data)\n            except (zlib.error, json.JSONDecodeError):\n                continue\n            if klipper_dict.get(\"app\") == \"Klipper\":\n                break\n        if klipper_dict:\n            self.klipper_dict = klipper_dict\n            ver = klipper_dict.get(\"version\", \"\")\n            bin_mcu = self.klipper_dict.get(\"config\", {}).get(\"MCU\", \"\")\n            output_line(\n                f\"Detected Klipper binary version {ver}, MCU: {bin_mcu}\"\n            )\n\n    def _build_command(self, cmd: int, payload: bytes) -> bytearray:\n        word_cnt = (len(payload) // 4) & 0xFF\n        out_cmd = bytearray(CMD_HEADER)\n        out_cmd.append(cmd)\n        out_cmd.append(word_cnt)\n        if payload:\n            out_cmd.extend(payload)\n        crc = crc16_ccitt(out_cmd[2:])\n        out_cmd.extend(struct.pack(\"<H\", crc))\n        out_cmd.extend(CMD_TRAILER)\n        return out_cmd\n\n    def prime(self) -> None:\n        # Prime with an invalid command.  This will generate an error\n        # and force double buffered USB devices to respond after the\n        # first command is sent.\n        msg = self._build_command(0x90, b\"\")\n        self.node.write(msg)\n        self.primed = True\n\n    async def connect_btl(self) -> None:\n        output_line(\"Attempting to connect to bootloader\")\n        ret = await self.send_command('CONNECT')\n        pinfo = ret[:12]\n        mcu_info = ret[12:]\n        ver_bytes: bytes\n        ver_bytes, start_addr, self.block_size = struct.unpack(\"<4sII\", pinfo)\n        self.app_start_addr = start_addr\n        self.software_version = \"?\"\n        self.proto_version = tuple([v for v in reversed(ver_bytes[:3])])\n        proto_version_str = \".\".join([str(v) for v in self.proto_version])\n        if self.block_size not in [64, 128, 256, 512]:\n            raise FlashError(\"Invalid Block Size: %d\" % (self.block_size,))\n        mcu_info = mcu_info.rstrip(b\"\\x00\")\n        if self.proto_version >= (1, 1, 0):\n            build_info = mcu_info.split(b\"\\x00\", maxsplit=1)\n            mcu_type = build_info[0].decode()\n            if len(build_info) == 2:\n                self.software_version = build_info[1].decode()\n            else:\n                output_line(\"Katapult build not reporting software version!\")\n        else:\n            mcu_type = mcu_info.decode()\n        output_line(\n            f\"Katapult Connected\\n\"\n            f\"Software Version: {self.software_version}\\n\"\n            f\"Protocol Version: {proto_version_str}\\n\"\n            f\"Block Size: {self.block_size} bytes\\n\"\n            f\"Application Start: 0x{self.app_start_addr:4X}\\n\"\n            f\"MCU type: {mcu_type}\"\n        )\n        if self.klipper_dict is not None:\n            bin_mcu = self.klipper_dict.get(\"config\", {}).get(\"MCU\", \"\")\n            if bin_mcu and bin_mcu != mcu_type:\n                raise FlashError(\n                    \"MCU returned by Katapult does not match MCU \"\n                    \"identified in klipper.bin.\\n\"\n                    f\"Katapult MCU: {mcu_type}\\n\"\n                    f\"Klipper Binary MCU: {bin_mcu}\"\n                )\n\n    async def verify_canbus_uuid(self, uuid):\n        output_line(\"Verifying canbus connection\")\n        ret = await self.send_command('GET_CANBUS_ID')\n        mcu_uuid = sum([v << ((5 - i) * 8) for i, v in enumerate(ret[:6])])\n        if mcu_uuid != uuid:\n            raise FlashError(\"UUID mismatch (%s vs %s)\" % (uuid, mcu_uuid))\n\n    async def send_command(\n        self,\n        cmdname: str,\n        payload: bytes = b\"\",\n        tries: int = 5\n    ) -> bytearray:\n        cmd = BOOTLOADER_CMDS[cmdname]\n        out_cmd = self._build_command(cmd, payload)\n        last_err = Exception()\n        while tries:\n            data = bytearray()\n            recd_len = 0\n            try:\n                self.node.write(out_cmd)\n                read_done = False\n                while not read_done:\n                    ret = await self.node.readuntil(CMD_TRAILER)\n                    data.extend(ret)\n                    while len(data) > 7:\n                        if data[:2] != CMD_HEADER:\n                            data = data[1:]\n                            continue\n                        recd_len = data[3] * 4\n                        read_done = len(data) == recd_len + 8\n                        break\n                    if self.primed and read_done:\n                        recd_len = 0\n                        data.clear()\n                        self.primed = False\n                        read_done = False\n            except asyncio.CancelledError:\n                raise\n            except asyncio.TimeoutError:\n                logging.info(\n                    f\"Response for command {cmdname} timed out, \"\n                    f\"{tries - 1} tries remaining\"\n                )\n            except Exception as e:\n                if type(e) is type(last_err) and e.args == last_err.args:\n                    last_err = e\n                    logging.exception(\"Device Read Error\")\n            else:\n                trailer = data[-2:]\n                recd_crc, = struct.unpack(\"<H\", data[-4:-2])\n                calc_crc = crc16_ccitt(data[2:-4])\n                recd_ack = data[2]\n                cmd_response = 0\n                if recd_len:\n                    cmd_response, = struct.unpack(\"<I\", data[4:8])\n                if trailer != CMD_TRAILER:\n                    logging.info(\n                        f\"Command '{cmdname}': Invalid Trailer Received \"\n                        f\"0x{trailer.hex()}\"\n                    )\n                elif recd_crc != calc_crc:\n                    logging.info(\n                        f\"Command '{cmdname}': Frame CRC Mismatch, expected: \"\n                        f\"{calc_crc}, received {recd_crc}\"\n                    )\n                elif recd_ack == ACK_ERROR:\n                    logging.info(f\"Command '{cmdname}': Received Error Response\")\n                elif recd_ack == ACK_BUSY:\n                    logging.info(f\"Command '{cmdname}': Received busy signal\")\n                    await asyncio.sleep(1.5)\n                elif recd_ack != ACK_SUCCESS:\n                    logging.info(f\"Command '{cmdname}': Received NACK\")\n                elif cmd_response != cmd:\n                    logging.info(\n                        f\"Command '{cmdname}': Acknowledged wrong command, \"\n                        f\"expected: {cmd:2x}, received: {cmd_response:2x}\"\n                    )\n                else:\n                    # Validation passed, return payload sans command\n                    if recd_len <= 4:\n                        return bytearray()\n                    return data[8:recd_len + 4]\n            tries -= 1\n            # clear the read buffer\n            try:\n                ret = await self.node.read(1024, timeout=.25)\n            except asyncio.TimeoutError:\n                pass\n            else:\n                logging.info(f\"Read Buffer Contents: {ret!r}\")\n            await asyncio.sleep(.5)\n        raise FlashError(\"Error sending command [%s] to Device\" % (cmdname))\n\n    async def send_file(self):\n        last_percent = 0\n        output_line(\"Flashing '%s'...\" % (self.firmware_path))\n        output(\"\\n[\")\n        with open(self.firmware_path, 'rb') as f:\n            f.seek(0, os.SEEK_END)\n            self.file_size = f.tell()\n            f.seek(0)\n            flash_address = self.app_start_addr\n            recd_addr = 0\n            while True:\n                buf = f.read(self.block_size)\n                if not buf:\n                    break\n                if len(buf) < self.block_size:\n                    buf += b\"\\xFF\" * (self.block_size - len(buf))\n                self.fw_sha.update(buf)\n                prefix = struct.pack(\"<I\", flash_address)\n                for _ in range(3):\n                    resp = await self.send_command('SEND_BLOCK', prefix + buf)\n                    recd_addr, = struct.unpack(\"<I\", resp)\n                    if recd_addr == flash_address:\n                        break\n                    logging.info(\n                        f\"Block write mismatch: expected: {flash_address:4X}, \"\n                        f\"received: {recd_addr:4X}\"\n                    )\n                    await asyncio.sleep(.1)\n                else:\n                    raise FlashError(\n                        f\"Flash write failed, block address 0x{recd_addr:4X}\"\n                    )\n                flash_address += self.block_size\n                self.block_count += 1\n                uploaded = self.block_count * self.block_size\n                pct = int(uploaded / float(self.file_size) * 100 + .5)\n                if pct >= last_percent + 2:\n                    last_percent += 2.\n                    output(\"#\")\n            resp = await self.send_command('SEND_EOF')\n            page_count, = struct.unpack(\"<I\", resp)\n            output_line(\"]\\n\\nWrite complete: %d pages\" % (page_count))\n\n    async def verify_file(self):\n        last_percent = 0\n        output_line(\"Verifying (block count = %d)...\" % (self.block_count,))\n        output(\"\\n[\")\n        ver_sha = hashlib.sha1()\n        for i in range(self.block_count):\n            flash_address = i * self.block_size + self.app_start_addr\n            for _ in range(3):\n                payload = struct.pack(\"<I\", flash_address)\n                resp = await self.send_command(\"REQUEST_BLOCK\", payload)\n                recd_addr, = struct.unpack(\"<I\", resp[:4])\n                if recd_addr == flash_address:\n                    break\n                logging.info(\n                    f\"Block read mismatch: expected: 0x{flash_address:4X}, \"\n                    f\"received: 0x{recd_addr}\"\n                )\n                await asyncio.sleep(.1)\n            else:\n                output_line(\"Error\")\n                raise FlashError(\"Block Request Error, block: %d\" % (i,))\n            ver_sha.update(resp[4:])\n            pct = int(i * self.block_size / float(self.file_size) * 100 + .5)\n            if pct >= last_percent + 2:\n                last_percent += 2\n                output(\"#\")\n        ver_hex = ver_sha.hexdigest().upper()\n        fw_hex = self.fw_sha.hexdigest().upper()\n        if ver_hex != fw_hex:\n            raise FlashError(\"Checksum mismatch: Expected %s, Received %s\"\n                                % (fw_hex, ver_hex))\n        output_line(\"]\\n\\nVerification Complete: SHA = %s\" % (ver_hex))\n\n    async def finish(self):\n        await self.send_command(\"COMPLETE\")\n\n\nclass CanNode:\n    def __init__(self, node_id: int, cansocket: CanSocket | SerialSocket) -> None:\n        self.node_id = node_id\n        self._reader = asyncio.StreamReader(CAN_READER_LIMIT)\n        self._cansocket = cansocket\n\n    async def read(\n        self, n: int = -1, timeout: Optional[float] = 2.\n    ) -> bytes:\n        return await asyncio.wait_for(self._reader.read(n), timeout)\n\n    async def readexactly(\n        self, n: int, timeout: Optional[float] = 2.\n    ) -> bytes:\n        return await asyncio.wait_for(self._reader.readexactly(n), timeout)\n\n    async def readuntil(\n        self, sep: bytes = b\"\\x03\", timeout: Optional[float] = 2.\n    ) -> bytes:\n        return await asyncio.wait_for(self._reader.readuntil(sep), timeout)\n\n    def write(self, payload: Union[bytes, bytearray]) -> None:\n        if isinstance(payload, bytearray):\n            payload = bytes(payload)\n        self._cansocket.send(self.node_id, payload)\n\n    async def write_with_response(\n        self,\n        payload: Union[bytearray, bytes],\n        resp_length: int,\n        timeout: Optional[float] = 2.\n    ) -> bytes:\n        self.write(payload)\n        return await self.readexactly(resp_length, timeout)\n\n    def feed_data(self, data: bytes) -> None:\n        self._reader.feed_data(data)\n\n    def close(self) -> None:\n        self._reader.feed_eof()\n\nclass BaseSocket:\n    def __init__(self, args: argparse.Namespace) -> None:\n        self._loop = asyncio.get_running_loop()\n        self._args = args\n        self._fw_path = pathlib.Path(args.firmware).expanduser().resolve()\n\n    @property\n    def is_flash_req(self) -> bool:\n        return not (\n            self.is_bootloader_req or self.is_status_req or self.is_query\n        )\n\n    @property\n    def is_bootloader_req(self) -> bool:\n        return self._args.request_bootloader\n\n    @property\n    def is_status_req(self) -> bool:\n        return self._args.status\n\n    @property\n    def is_query(self) -> bool:\n        return self._args.query\n\n    @property\n    def is_usb_can_bridge(self) -> bool:\n        return False\n\n    @property\n    def usb_serial_path(self) -> pathlib.Path:\n        raise NotImplementedError()\n\n    def _check_firmware(self) -> None:\n        if self.is_flash_req and not self._fw_path.is_file():\n            raise FlashError(\"Invalid firmware path '%s'\" % (self._fw_path))\n\n    async def run(self) -> None:\n        raise NotImplementedError()\n\n    def close(self) -> None:\n        raise NotImplementedError()\n\nclass CanSocket(BaseSocket):\n    def __init__(self, args: argparse.Namespace) -> None:\n        super().__init__(args)\n        self._uuid = 0\n        self._can_interface = args.interface\n        self._can_bridge_path: pathlib.Path | None = None\n        self._can_bridge_serial_path: pathlib.Path | None = None\n        if not self.is_query:\n            if args.uuid is None:\n                raise FlashError(\n                    \"The 'uuid' option must be specified to flash a CAN device\"\n                )\n            else:\n                intf = self._can_interface\n                self._uuid = int(args.uuid, 16)\n                self._search_canbus_bridge()\n                output_line(f\"Connecting to CAN UUID {args.uuid} on interface {intf}\")\n        self.cansock = socket.socket(socket.PF_CAN, socket.SOCK_RAW,\n                                     socket.CAN_RAW)\n        self.admin_node = CanNode(CANBUS_ID_ADMIN, self)\n        self.nodes: Dict[int, CanNode] = {\n            CANBUS_ID_ADMIN_RESP: self.admin_node\n        }\n\n        self.input_buffer = b\"\"\n        self.output_packets: List[bytes] = []\n        self.input_busy = False\n        self.output_busy = False\n        self.closed = True\n\n    @property\n    def is_usb_can_bridge(self) -> bool:\n        return self._can_bridge_path is not None\n\n    @property\n    def usb_serial_path(self) -> pathlib.Path:\n        if self._can_bridge_serial_path is not None:\n            return self._can_bridge_serial_path\n        # find tty path\n        assert self._can_bridge_path is not None\n        dir_name = self._can_bridge_path.name\n        ttys = list(self._can_bridge_path.glob(f\"{dir_name}:*/tty/tty*\"))\n        if not ttys:\n            raise FlashError(\"Failed to locate serial tty path\")\n        tty_path = pathlib.Path(\"/dev\").joinpath(ttys[0].name)\n        if not tty_path.exists():\n            raise FlashError(\"Detected tty path does not exist\")\n        self._can_bridge_serial_path = tty_path\n        return tty_path\n\n    def _handle_can_response(self) -> None:\n        try:\n            data = self.cansock.recv(4096)\n        except socket.error as e:\n            # If bad file descriptor allow connection to be\n            # closed by the data check\n            if e.errno == errno.EBADF:\n                logging.exception(\"Can Socket Read Error, closing\")\n                data = b''\n            else:\n                return\n        if not data:\n            # socket closed\n            self.close()\n            return\n        self.input_buffer += data\n        if self.input_busy:\n            return\n        self.input_busy = True\n        while len(self.input_buffer) >= 16:\n            packet = self.input_buffer[:16]\n            self._process_packet(packet)\n            self.input_buffer = self.input_buffer[16:]\n        self.input_busy = False\n\n    def _process_packet(self, packet: bytes) -> None:\n        can_id, length, data = struct.unpack(CAN_FMT, packet)\n        can_id &= socket.CAN_EFF_MASK\n        payload = data[:length]\n        node = self.nodes.get(can_id)\n        if node is not None:\n            node.feed_data(payload)\n\n    def send(self, can_id: int, payload: bytes = b\"\") -> None:\n        if can_id > 0x7FF:\n            can_id |= socket.CAN_EFF_FLAG\n        if not payload:\n            packet = struct.pack(CAN_FMT, can_id, 0, b\"\")\n            self.output_packets.append(packet)\n        else:\n            while payload:\n                length = min(len(payload), 8)\n                pkt_data = payload[:length]\n                payload = payload[length:]\n                packet = struct.pack(\n                    CAN_FMT, can_id, length, pkt_data)\n                self.output_packets.append(packet)\n        if self.output_busy:\n            return\n        self.output_busy = True\n        asyncio.create_task(self._do_can_send())\n\n    async def _do_can_send(self):\n        while self.output_packets:\n            packet = self.output_packets.pop(0)\n            try:\n                await self._loop.sock_sendall(self.cansock, packet)\n            except socket.error:\n                logging.info(\"Socket Write Error, closing\")\n                self.close()\n                break\n        self.output_busy = False\n\n    def _jump_to_bootloader(self, uuid: int):\n        output_line(\"Sending bootloader jump command...\")\n        plist = [(uuid >> ((5 - i) * 8)) & 0xFF for i in range(6)]\n        plist.insert(0, KLIPPER_REBOOT_CMD)\n        self.send(KLIPPER_ADMIN_ID, bytes(plist))\n\n    async def _query_uuids(self) -> List[int]:\n        output_line(\"Checking for Katapult nodes...\")\n        payload = bytes([CANBUS_CMD_QUERY_UNASSIGNED])\n        self.admin_node.write(payload)\n        curtime = self._loop.time()\n        endtime = curtime + 2.\n        self.uuids: List[int] = []\n        while curtime < endtime:\n            timeout = max(.1, endtime - curtime)\n            try:\n                resp = await self.admin_node.read(8, timeout)\n            except asyncio.TimeoutError:\n                continue\n            finally:\n                curtime = self._loop.time()\n            if len(resp) < 7 or resp[0] != CANBUS_RESP_NEED_NODEID:\n                continue\n            app_names = {\n                KLIPPER_SET_NODE_CMD: \"Klipper\",\n                CANBUS_CMD_SET_NODEID: \"Katapult\"\n            }\n            app = \"Unknown\"\n            if len(resp) > 7:\n                app = app_names.get(resp[7], \"Unknown\")\n            data = resp[1:7]\n            output_line(f\"Detected UUID: {data.hex()}, Application: {app}\")\n            uuid = sum([v << ((5 - i) * 8) for i, v in enumerate(data)])\n            if uuid not in self.uuids and app == \"Katapult\":\n                self.uuids.append(uuid)\n        return self.uuids\n\n    def _reset_nodes(self) -> None:\n        output_line(\"Resetting all bootloader node IDs...\")\n        payload = bytes([CANBUS_CMD_CLEAR_NODE_ID])\n        self.admin_node.write(payload)\n\n    def _set_node_id(self, uuid: int) -> CanNode:\n        # Convert ID to a list\n        plist = [(uuid >> ((5 - i) * 8)) & 0xFF for i in range(6)]\n        plist.insert(0, CANBUS_CMD_SET_NODEID)\n        node_id = len(self.nodes) + CANBUS_NODEID_OFFSET\n        plist.append(node_id)\n        payload = bytes(plist)\n        self.admin_node.write(payload)\n        decoded_id = node_id * 2 + 0x100\n        node = CanNode(decoded_id, self)\n        self.nodes[decoded_id + 1] = node\n        return node\n\n    def _search_canbus_bridge(self) -> None:\n        can_intf = self._can_interface.lower()\n        sysfs_usb_path = pathlib.Path(\"/sys/bus/usb/devices\")\n        if not sysfs_usb_path.is_dir():\n            return\n        for item in sysfs_usb_path.iterdir():\n            if not item.joinpath(\"bDeviceClass\").is_file():\n                continue\n            usb_info = get_usb_info(item)\n            if (\n                usb_info[\"usb_id\"] != GS_CAN_USB_ID or\n                usb_info[\"manufacturer\"] != \"klipper\"\n            ):\n                continue\n            if not list(item.glob(f\"{item.name}:*/net/{can_intf}\")):\n                continue\n            # Klipper GS USB Device matches\n            serial_no = usb_info[\"serial_number\"]\n            logging.info(\n                f\"Found Klipper USB-CAN bridge on {can_intf}, serial {serial_no}\"\n            )\n            if serial_no:\n                try:\n                    det_uuid = convert_usbsn_to_uuid(serial_no)\n                except Exception:\n                    output_line(\n                        f\"Failed to convert can bridge serial number {serial_no} \"\n                        f\"to a uuid for device {item.name}\"\n                    )\n                    logging.exception(\"UUID conversion failed\")\n                    return\n                logging.info(\n                    f\"Detected UUID: {det_uuid:x}, provided UUID: {self._uuid:x}\"\n                )\n                if det_uuid == self._uuid:\n                    self._can_bridge_path = item\n                    output_line(f\"Canbus Bridge detected at {item}\")\n            break\n\n    async def _wait_canbridge_reset(self) -> None:\n        if self._can_bridge_path is None:\n            return\n        output(\"Waiting for USB Reconnect.\")\n        for _ in range(8):\n            await asyncio.sleep(.5)\n            output(\".\")\n            usb_info = get_usb_info(self._can_bridge_path)\n            mfr = usb_info.get(\"manufacturer\")\n            usb_id = usb_info.get(\"usb_id\", \"\")\n            product = usb_info.get(\"product\")\n            if usb_id and usb_id != GS_CAN_USB_ID:\n                await asyncio.sleep(.5)\n                output_line(\"done\")\n                output_line(f\"Detected new USB Device: {usb_id} {mfr} {product}\")\n                if mfr == \"katapult\" or usb_id == KATAPULT_USB_ID:\n                    serial_path = self.usb_serial_path\n                    output_line(f\"Katapult detected at serial port {serial_path}\")\n                else:\n                    # Device is not Katapult, force exit\n                    self._args.request_bootloader = True\n                    output_line(\"Device is not Katapult, exiting...\")\n                break\n        else:\n            output_line(\"timed out\")\n\n    async def run(self) -> None:\n        self._check_firmware()\n        try:\n            self.cansock.bind((self._can_interface,))\n        except Exception:\n            raise FlashError(f\"Unable to bind socket to {self._can_interface}\")\n        self.closed = False\n        self.cansock.setblocking(False)\n        self._loop.add_reader(\n            self.cansock.fileno(), self._handle_can_response)\n        if self.is_flash_req or self.is_bootloader_req:\n            self._jump_to_bootloader(self._uuid)\n            if self.is_usb_can_bridge:\n                await self._wait_canbridge_reset()\n                return\n            else:\n                await asyncio.sleep(1.0)\n            if self.is_bootloader_req:\n                return\n        self._reset_nodes()\n        await asyncio.sleep(.5)\n        if self.is_query:\n            await self._query_uuids()\n            return\n        node = self._set_node_id(self._uuid)\n        flasher = CanFlasher(node, self._fw_path)\n        await asyncio.sleep(.5)\n        try:\n            await flasher.connect_btl()\n            await flasher.verify_canbus_uuid(self._uuid)\n            if not self.is_status_req:\n                await flasher.send_file()\n                await flasher.verify_file()\n        finally:\n            # always attempt to send the complete command. If\n            # there is an error it will exit the bootloader\n            # unless comms were broken\n            if self.is_flash_req:\n                await flasher.finish()\n\n    def close(self):\n        if self.closed:\n            return\n        self.closed = True\n        for node in self.nodes.values():\n            node.close()\n        self._loop.remove_reader(self.cansock.fileno())\n        self.cansock.close()\n\nclass SerialSocket(BaseSocket):\n    def __init__(self, args: argparse.Namespace) -> None:\n        super().__init__(args)\n        self._device = args.device\n        self._baud = args.baud\n        if not HAS_SERIAL:\n            ser_inst_cmd = \"pip3 install serial\"\n            if shutil.which(\"apt\") is not None:\n                ser_inst_cmd = \"sudo apt install python3-serial\"\n            raise FlashError(\n                \"The pyserial python package was not found.  To install \"\n                \"run the following command in a terminal: \\n\\n\"\n                f\"   {ser_inst_cmd}\\n\\n\"\n            )\n        if self._device is None:\n            raise FlashError(\n                \"The 'device' option must be specified to flash a device\"\n            )\n        output_line(f\"Connecting to Serial Device {self._device}, baud {self._baud}\")\n        self.serial: Optional[Serial] = None\n        self.node = CanNode(0, self)\n\n    @property\n    def is_query(self) -> bool:\n        return False\n\n    @property\n    def usb_serial_path(self) -> pathlib.Path:\n        return pathlib.Path(self._device)\n\n    def _handle_response(self) -> None:\n        assert self.serial is not None\n        try:\n            data = self.serial.read(4096)\n        except SerialException:\n            logging.exception(\"Error on serial read\")\n            self.close()\n        else:\n            self.node.feed_data(data)\n\n    def send(self, can_id: int, payload: bytes = b\"\") -> None:\n        assert self.serial is not None\n        try:\n            self.serial.write(payload)\n        except SerialException:\n            logging.exception(\"Error on serial write\")\n            self.close()\n\n    async def _lookup_proc_name(self, process_id: str) -> str:\n        has_sysctl = shutil.which(\"systemctl\") is not None\n        if has_sysctl:\n            cmd = shlex.split(f\"systemctl status {process_id}\")\n            proc = await asyncio.create_subprocess_exec(\n                *cmd,\n                stdout=asyncio.subprocess.PIPE,\n                stderr=asyncio.subprocess.PIPE\n            )\n            stdout, _ = await proc.communicate()\n            resp = stdout.strip().decode(errors=\"ignore\")\n            if resp:\n                unit = resp.split(maxsplit=2)\n                if len(unit) == 3:\n                    return f\"Systemd Unit Name: {unit[1]}\"\n        cmdline_file = pathlib.Path(f\"/proc/{process_id}/cmdline\")\n        if cmdline_file.exists():\n            res = cmdline_file.read_text().replace(\"\\x00\", \" \").strip()\n            return f\"Command Line: {res}\"\n        exe_file = pathlib.Path(f\"/proc/{process_id}/exe\")\n        if exe_file.exists():\n            return f\"Executable: {exe_file.resolve()})\"\n        return \"Name Unknown\"\n\n    async def validate_device(self, dev_strpath: str) -> None:\n        dev_path = pathlib.Path(dev_strpath)\n        if not dev_path.exists():\n            raise FlashError(f\"No Serial Device found at {dev_path}\")\n        try:\n            dev_st = dev_path.stat()\n        except PermissionError as e:\n            raise FlashError(f\"No permission to access device {dev_path}\") from e\n        dev_id = (dev_st.st_dev, dev_st.st_ino)\n        for fd_dir in pathlib.Path(\"/proc\").glob(\"*/fd\"):\n            pid = fd_dir.parent.name\n            if not pid.isdigit():\n                continue\n            with contextlib.suppress(OSError):\n                for item in fd_dir.iterdir():\n                    try:\n                        item_st = item.stat()\n                    except OSError:\n                        continue\n                    item_id = (item_st.st_dev, item_st.st_ino)\n                    if item_id == dev_id:\n                        proc_name = await self._lookup_proc_name(pid)\n                        output_line(\n                            f\"Serial device {dev_path} in use by another program.\\n\"\n                            f\"Process ID: {pid}\\n\"\n                            f\"Process {proc_name}\"\n                        )\n                        raise FlashError(f\"Serial device {dev_path} in use\")\n\n    async def _request_usb_bootloader(self, device: pathlib.Path) -> pathlib.Path:\n        output_line(f\"Requesting USB bootloader for {device}...\")\n        usb_dev_path = get_usb_path(device)\n        if usb_dev_path is None:\n            output_line(f\"Device path {device} is not a usb device\")\n            return device\n        stable_path = get_stable_usb_symlink(device)\n        usb_info = get_usb_info(usb_dev_path)\n        start_usb_id = usb_info[\"usb_id\"]\n        fd: Optional[int] = None\n        with contextlib.suppress(OSError):\n            fd = os.open(str(device), os.O_RDWR | os.O_NOCTTY | os.O_NONBLOCK)\n            dtr_data = struct.pack('I', termios.TIOCM_DTR)\n            fcntl.ioctl(fd, termios.TIOCMBIS, dtr_data)\n            t = termios.tcgetattr(fd)\n            t[4] = t[5] = termios.B1200\n            termios.tcsetattr(fd, termios.TCSANOW, t)\n            fcntl.ioctl(fd, termios.TIOCMBIC, dtr_data)\n        if fd is not None:\n            os.close(fd)\n        output(\"Waiting for USB Reconnect.\")\n        for _ in range(8):\n            await asyncio.sleep(.5)\n            output(\".\")\n            usb_info = get_usb_info(usb_dev_path)\n            mfr = usb_info.get(\"manufacturer\")\n            product = usb_info.get(\"product\")\n            usb_id = usb_info.get(\"usb_id\", \"\")\n            if usb_id and usb_id != start_usb_id:\n                await asyncio.sleep(.5)\n                output_line(\"done\")\n                output_line(f\"Detected new USB Device: {usb_id} {mfr} {product}\")\n                if mfr == \"katapult\" or usb_id == KATAPULT_USB_ID:\n                    # prefer path resolved from sysfs usb path\n                    path_match = list(\n                        usb_dev_path.glob(f\"{usb_dev_path.name}:*/tty/tty*\")\n                    )\n                    if len(path_match) == 1:\n                        det_path = pathlib.Path(f\"/dev/{path_match[0].name}\")\n                        if det_path.exists():\n                            stable_path = det_path\n                    output_line(f\"Katapult detected on {stable_path}\")\n                else:\n                    # Device is not Katapult, force exit\n                    self._args.request_bootloader = True\n                    output_line(\"Device is not Katapult, exiting...\")\n                break\n        else:\n            output_line(\"timed out\")\n        return stable_path\n\n    async def _request_serial_bootloader(self, device: str, baud: int) -> None:\n        output_line(f\"Requesting serial bootloader for device {device}...\")\n        self.serial = self._open_device(device, baud)\n        self.send(0, SERIAL_BL_REQ)\n        await asyncio.sleep(1.)\n        if self.serial is not None:\n            self.close()\n\n    def _open_device(self, device: str, baud: int) -> Serial:\n        try:\n            serial_dev = Serial(                            # type: ignore\n                baudrate=baud, timeout=0, exclusive=True\n            )\n            serial_dev.port = device\n            serial_dev.open()\n        except (OSError, IOError, SerialException) as e:\n            raise FlashError(\"Unable to open serial port: %s\" % (e,))\n        return serial_dev\n\n    def _has_double_buffering(self, product: str) -> bool:\n        if product.startswith(\"stm32\"):\n            variant = product[5:7]\n            return variant not in (\"f2\", \"f4\", \"h7\")\n        return False\n\n    async def run(self) -> None:\n        self._check_firmware()\n        device = self._device\n        await self.validate_device(device)\n        dev_path = pathlib.Path(device)\n        usb_dev_path = get_usb_path(dev_path)\n        dev_info: Dict[str, Any] = {}\n        if usb_dev_path is not None:\n            dev_info = get_usb_info(usb_dev_path)\n        usb_id = dev_info.get(\"usb_id\")\n        usb_mfr = dev_info.get(\"manufacturer\")\n        usb_prod: str = dev_info.get(\"product\", \"unknown\")\n        if usb_mfr == \"klipper\" or usb_id == KLIPPER_USB_ID:\n            # Request usb bootloader, wait for katapult\n            output_line(\"Detected USB device running Klipper\")\n            new_dpath = await self._request_usb_bootloader(dev_path)\n            device = str(new_dpath)\n            if self.is_bootloader_req:\n                return\n        elif usb_mfr == \"katapult\" or usb_id == KATAPULT_USB_ID:\n            output_line(\"Detected USB device running Katapult\")\n            if self.is_bootloader_req:\n                return\n        elif self.is_bootloader_req:\n            # Request serial bootloader and exit\n            await self._request_serial_bootloader(device, self._baud)\n            return\n        else:\n            usb_prod = \"\"\n        self.serial = self._open_device(device, self._baud)\n        self._loop.add_reader(self.serial.fileno(), self._handle_response)\n        flasher = CanFlasher(self.node, self._fw_path)\n        try:\n            if self._has_double_buffering(usb_prod):\n                # Prime the USB Connection with a dummy command.  This is\n                # necessary to get STM32 devices with usbfs double buffering\n                # to respond immediately to the connect command.\n                flasher.prime()\n            await flasher.connect_btl()\n            if not self.is_status_req:\n                await flasher.send_file()\n                await flasher.verify_file()\n        finally:\n            # always attempt to send the complete command. If\n            # there is an error it will exit the bootloader\n            # unless comms were broken\n            if self.is_flash_req:\n                await flasher.finish()\n\n    def close(self):\n        if self.serial is None:\n            return\n        self._loop.remove_reader(self.serial.fileno())\n        self.serial.close()\n        self.serial = None\n\nasync def main(args: argparse.Namespace) -> int:\n    if not args.verbose:\n        logging.getLogger().setLevel(logging.ERROR)\n    iscan = args.device is None\n    sock: CanSocket | SerialSocket | None = None\n    try:\n        if iscan:\n            sock = CanSocket(args)\n        else:\n            sock = SerialSocket(args)\n        await sock.run()\n        if sock.is_usb_can_bridge and not sock.is_bootloader_req:\n            args.device = str(sock.usb_serial_path)\n            sock.close()\n            sock = SerialSocket(args)\n            await sock.run()\n    except Exception:\n        logging.exception(\"Flash Tool Error\")\n        return 1\n    finally:\n        if sock is not None:\n            sock.close()\n    if sock is None:\n        return 1\n    if sock.is_query:\n        output_line(\"CANBus UUID Query Complete\")\n    elif sock.is_bootloader_req:\n        output_line(\"Bootloader Request Complete\")\n    elif sock.is_status_req:\n        output_line(\"Status Request Complete\")\n    else:\n        output_line(\"Programming Complete\")\n    return 0\n\n\nif __name__ == '__main__':\n    parser = argparse.ArgumentParser(\n        description=\"Katapult Flash Tool\")\n    parser.add_argument(\n        \"-d\", \"--device\", metavar='<serial device>',\n        help=\"Serial Device\"\n    )\n    parser.add_argument(\n        \"-b\", \"--baud\", default=250000, metavar='<baud rate>',\n        help=\"Serial baud rate\"\n    )\n    parser.add_argument(\n        \"-i\", \"--interface\", default=\"can0\", metavar='<can interface>',\n        help=\"Can Interface\"\n    )\n    parser.add_argument(\n        \"-f\", \"--firmware\", metavar=\"<klipper.bin>\",\n        default=\"~/klipper/out/klipper.bin\",\n        help=\"Path to Klipper firmware file\")\n    parser.add_argument(\n        \"-u\", \"--uuid\", metavar=\"<uuid>\", default=None,\n        help=\"Can device uuid\"\n    )\n    parser.add_argument(\n        \"-q\", \"--query\", action=\"store_true\",\n        help=\"Query available CAN UUIDs (CANBus Ony)\"\n    )\n    parser.add_argument(\n        \"-v\", \"--verbose\", action=\"store_true\",\n        help=\"Enable verbose responses\"\n    )\n    parser.add_argument(\n        \"-r\", \"--request-bootloader\", action=\"store_true\",\n        help=\"Requests the bootloader and exits\"\n    )\n    parser.add_argument(\n        \"-s\", \"--status\", action=\"store_true\",\n        help=\"Connect to bootloader and print status\"\n    )\n    args = parser.parse_args()\n    exit(asyncio.run(main(args)))\n"
  },
  {
    "path": "helpers/klipper_auto_flasher.sh",
    "content": "#!/bin/bash\n\n##   muss ausführbar gemacht werden mit\n##   chmod +x /home/mks/FreeDi/mainboard_and_toolhead_firmwares/hid-flash\n\n\n# Get the absolute path of the script\nscript_dir=\"$(cd \"$(dirname \"$0\")\" && pwd)\"\n\n# Define the absolute paths to the firmware files\ntoolhead_firmware_path=\"$script_dir/../mainboard_and_toolhead_firmwares/v0.12.0-289/Toolhead_RP2040.uf2\"\nhid_flash_path=\"$script_dir/../mainboard_and_toolhead_firmwares/hid-flash\"\nmcu_firmware=\"$script_dir/../mainboard_and_toolhead_firmwares/v0.12.0-289/X_4.bin\"\nserial_port=\"ttyS0\"\n\n# Find matching /dev/sd*[0-9] to see if toolhead is in boot mode\nfor device in /dev/sd*[0-9]; do\n    # Check if the device exists\n    if [ -e \"$device\" ]; then\n        # Get the size of the partition\n        size=$(lsblk | grep \"$(basename \"$device\")\" | awk '{print $4}')\n\n        # Check if the size matches exactly 128M\n        if [ \"$size\" == \"128M\" ]; then\n            echo \"Device $device size is exactly 128M\"\n            \n            # Copy (flash) the toolhead klipper firmware to the device\n            echo \"Copying firmware to $device...\"\n            sudo cp \"$toolhead_firmware_path\" \"$device\"\n\n            # Check if the copy was successful\n            if [ $? -eq 0 ]; then\n                echo \"Firmware successfully copied to $device\"\n\n                sudo service klipper stop;\n                sudo service klipper start;\n\n                # Wait for Klipper service runtime to stabilize (with timeout)\n                max_attempts=30  # Timeout after 30 seconds\n                attempt=0\n\n                while true; do\n                    runtime=$(systemctl show klipper.service --property=ActiveEnterTimestampMonotonic | awk -F'=' '{print $2}')\n                    if [ -n \"$runtime\" ] && [ \"$runtime\" -ge 5000000 ]; then\n                        echo \"Klipper service has been running for at least 5 seconds.\"\n                        break\n                    fi\n\n                    # Increment attempt counter and check for timeout\n                    attempt=$((attempt + 1))\n                    if [ \"$attempt\" -ge \"$max_attempts\" ]; then\n                        echo \"Timeout waiting for Klipper service to stabilize.\"\n                        exit 1\n                    fi\n\n                    sleep 1\n                done\n\n\n                sleep 10\n                echo \"FIRMWARE_RESTART\" | sudo tee /home/mks/printer_data/comms/klippy.serial\n                sudo service klipper stop\n\n                # Flash the MCU firmware\n                $hid_flash_path \"$mcu_firmware\" \"$serial_port\"\n\n                # Starting klipper again\n                echo \"Starting Klipper service...\"\n                sleep 3\n                if ! sudo service klipper start; then\n                    echo \"Failed to start Klipper service.\"\n                    exit 1\n                fi\n\n\n            else\n                echo \"Failed to copy firmware to $device\"\n            fi\n        else\n            echo \"Device $device size is $size (not 128M)\"\n        fi\n    else\n        echo \"Device $device not found\"\n    fi\n\ndone\n"
  },
  {
    "path": "helpers/usbmounter.sh",
    "content": "#!/bin/bash\n\nUSER=\"$1\"\nTARGET_DIR=\"/home/$USER/printer_data/gcodes\"\nARG=\"$2\"\nACTION=$(echo \"$ARG\" | cut -d'-' -f1)\nDEVICE=$(echo \"$ARG\" | cut -d'-' -f2)\n\n# Define the vendor and product IDs to ignore\nIGNORED_VENDOR_ID=\"a69c\"\nIGNORED_PRODUCT_ID=\"5721\"\n\n\n########################################################\n# filter: ignore everything smaller than 16 MiB to prevent wifi dongles from being mounted\n########################################################\nMIN_SIZE_MB=16\n\nif [[ \"$ACTION\" == \"add\" ]]; then\n    # smaller devices are likely wifi dongles\n    bytes=$(blockdev --getsize64 \"/dev/$DEVICE\" 2>/dev/null || echo 0)\n    size_mb=$(( bytes / 1024 / 1024 ))\n    if (( size_mb < MIN_SIZE_MB )); then\n        echo \"Ignoring /dev/$DEVICE (${size_mb} MiB < ${MIN_SIZE_MB} MiB ⇒ dongle in mass-storage mode)\"\n        exit 0\n    fi\n\n    # ignore ISO-9660 driver images\n    FSTYPE=$(/sbin/blkid -o value -s TYPE \"/dev/$DEVICE\" 2>/dev/null)\n    if [[ \"$FSTYPE\" == \"iso9660\" ]]; then\n        echo \"Ignoring /dev/$DEVICE (ISO-9660 driver image)\"\n        exit 0\n    fi\n\n    # ignore RPI-RP2\n    label=$(/sbin/blkid -o value -s LABEL \"/dev/$DEVICE\" 2>/dev/null)\n    if [[ \"$label\" = \"RPI-RP2\" ]]; then\n        echo \"Device /dev/$DEVICE has label RPI-RP2, not mounting.\"\n        exit 0\n    fi\n\nfi\n\n# Extract vendor and product ID from the device information\nDEVICE_VENDOR_ID=$(lsusb | grep \"$DEVICE\" | awk '{print $6}' | cut -d':' -f1)\nDEVICE_PRODUCT_ID=$(lsusb | grep \"$DEVICE\" | awk '{print $6}' | cut -d':' -f2)\n\n# Check if the device should be ignored\nif [[ \"$DEVICE_VENDOR_ID\" == \"$IGNORED_VENDOR_ID\" && \"$DEVICE_PRODUCT_ID\" == \"$IGNORED_PRODUCT_ID\" ]]; then\n    echo \"Ignoring device $DEVICE with vendor ID $DEVICE_VENDOR_ID and product ID $DEVICE_PRODUCT_ID\"\n    echo \"It's an AIC8800DC in mass storage mode, switching to wifi mode\"\n    exit 0\nfi\n\n########################################################\n\necho \"Script started: ACTION=$ACTION, DEVICE=$DEVICE\"\n\nPART_NUM=$(echo \"$DEVICE\" | grep -o '[0-9]*$')\n\n# Apply a delay if partition number > 1\nif [ \"$ACTION\" = \"add\" ] && [ \"$PART_NUM\" -gt 1 ]; then\n    DELAY=$(echo \"scale=1; ($PART_NUM - 1) * 0.2\" | bc)\n    echo \"Detected partition number $PART_NUM, sleeping for $DELAY seconds to prevent wrong detection.\"\n    sleep \"$DELAY\"\nfi\n\ncase \"$ACTION\" in\n    add)\n        echo \"Attempting to mount /dev/$DEVICE\"\n        for i in {1..10}; do\n            MOUNT_POINT=\"$TARGET_DIR/usb$i\"\n            if ! mountpoint -q \"$MOUNT_POINT\"; then\n                echo \"Using mount point: $MOUNT_POINT\"\n                mkdir -p \"$MOUNT_POINT\"\n\n                FSTYPE=$(/sbin/blkid -o value -s TYPE \"/dev/$DEVICE\" 2>&1)\n                echo \"Filesystem detected: $FSTYPE\"\n\n                case \"$FSTYPE\" in\n                    vfat)\n                        echo \"Mounting FAT32 (vfat)\"\n                        mount -t vfat -o rw,umask=000 \"/dev/$DEVICE\" \"$MOUNT_POINT\" 2>&1 || echo \"ERROR: Mount failed\" >&2\n                        ;;\n                    ntfs)\n                        echo \"Mounting NTFS\"\n                        mount -t ntfs-3g -o rw,umask=000 \"/dev/$DEVICE\" \"$MOUNT_POINT\" 2>&1 || echo \"ERROR: Mount failed\" >&2\n                        ;;\n                    ext4)\n                        echo \"Mounting EXT4\"\n                        mount -t ext4 -o rw \"/dev/$DEVICE\" \"$MOUNT_POINT\" 2>&1 || echo \"ERROR: Mount failed\" >&2\n                        ;;\n                    *)\n                        echo \"ERROR: Unsupported filesystem: $FSTYPE\" >&2\n                        rmdir \"$MOUNT_POINT\"\n                        exit 1\n                        ;;\n                esac\n\n                if mount | grep -q \"$MOUNT_POINT\"; then\n                    echo \"Mount successful: $MOUNT_POINT\"\n                    break\n                else\n                    echo \"ERROR: Mounting failed for /dev/$DEVICE\" >&2\n                    rmdir \"$MOUNT_POINT\"\n                    exit 1\n                fi\n            fi\n        done\n        ;;\n\n    remove)\n        echo \"Attempting to unmount /dev/$DEVICE\"\n        MOUNT_POINT=$(mount | grep \"/dev/$DEVICE\" | awk '{print $3}')\n        if [ -n \"$MOUNT_POINT\" ]; then\n            echo \"Unmounting from $MOUNT_POINT\"\n            umount \"/dev/$DEVICE\" 2>&1 || echo \"ERROR: Unmount failed\" >&2\n            if [ $? -eq 0 ]; then\n                echo \"Unmount successful\"\n                rmdir \"$MOUNT_POINT\"\n            fi\n        else\n            echo \"ERROR: No mount point found for /dev/$DEVICE\" >&2\n        fi\n        ;;\n\n    *)\n        echo \"ERROR: Unknown action: $ACTION\" >&2\n        exit 1\n        ;;\nesac"
  },
  {
    "path": "install/freedi_install.conf",
    "content": "################################################################################\n# FreeDi Installation Configuration\n#\n# This file contains configuration variables for the FreeDi installation script.\n# These variables define paths and settings used throughout the installation.\n#\n# Variables FREEDI_DIR, USER_HOME_DIR, USER_NAME, and USER_GROUP are set by\n# the install script and can be referenced here.\n################################################################################\n\n# FreeDi subdirectories\nFREEDI_LCD_DIR=\"${FREEDI_DIR}/FreeDiLCD\"                                                # FreeDiLCD directory\nREPO_MODULE_DIR=\"${FREEDI_DIR}/klipper_module\"                                          # klipper_module directory\nLCD_FIRMWARE_DIR=\"${FREEDI_DIR}/screen_firmwares\"                                       # screen_firmwares directory\nWIFI_DIR=\"${FREEDI_DIR}/helpers/wifi\"                                                   # wifi driver directory\nDTBO_DIR=\"${FREEDI_DIR}/helpers/dtbo\"                                                   # dtbo directory\n\n# System service\nSERVICE=\"FreeDi.service\"                                                                # FreeDi systemd service\n\n# External paths - Klipper\nKLIPPER_DIR=\"${USER_HOME_DIR}/klipper\"                                                  # klipper directory\nKLIPPER_EXTRAS_DIR=\"${KLIPPER_DIR}/klippy/extras\"                                       # klipper module directory\nKLIPPER_ENV=\"${USER_HOME_DIR}/klippy-env\"                                               # klipper virtual environment\nKLIPPER_VENV_PYTHON_BIN=\"${KLIPPER_ENV}/bin/python\"                                     # klipper python binary\nMOONRAKER_DIR=\"${USER_HOME_DIR}/moonraker\"                                              # moonraker directory\nMAINSAIL_DIR=\"${USER_HOME_DIR}/mainsail\"                                                # mainsail directory\nCROWSNEST_DIR=\"$USER_HOME_DIR/crowsnest\"                                                # crowsnest directory\nTIMELAPSE_DIR=\"$USER_HOME_DIR/timelapse\"                                                # timelapse directory\n\n# External paths - Printer data\nPRINTER_DATA_DIR=\"${USER_HOME_DIR}/printer_data\"                                        # printer data directory\nPRINTER_CONFIG_DIR=\"${PRINTER_DATA_DIR}/config\"                                         # printer config directory\nPRINTER_CONFIG=\"${PRINTER_CONFIG_DIR}/printer.cfg\"                                      # printer config file\nMOONRAKER_CONF=\"${PRINTER_CONFIG_DIR}/moonraker.conf\"                                   # moonraker config file\nMOONRAKER_ASVC=\"${PRINTER_DATA_DIR}/moonraker.asvc\"                                     # moonraker.asvc file path\n\n# Device tree binary overlay target (stock mainboard)\nDTBO_TARGET=/boot/dtb/rockchip/overlay                                                  # dtbo target directory for stock mainboard\n\n# Supported Python versions\nSUPPORTED_PYTHON_VERSIONS=(\"3.11\" \"3.13\" \"3.14\")                                        # Supported Python versions for FreeDi\n\n################################################################################\n# Don't edit below this line unless you know what you're doing.\n# The variables above are meant to be customized for your setup. The code below\n# uses those variables to perform the installation. Changing the code below may\n# break the installation process if not done correctly.\n################################################################################\n\n# Create comma-separated list of supported versions for error messages\nSUPPORTED_VERSIONS_JOINED=$(IFS=', '; echo \"${SUPPORTED_PYTHON_VERSIONS[*]}\")\n"
  },
  {
    "path": "install/packages.sh",
    "content": "#!/bin/bash\n# Installs all required apt packages for FreeDi.\n# Sourced by install.sh — expects IS_FREEDI_IMAGE, OS_CODENAME, RED, GRN, RST to be set.\n\n################################################################################\n# INSTALL APT PACKAGES\n################################################################################\n\necho \"Updating apt package lists...\"\nsudo apt-get update || { echo \"${RED}Failed to update apt package lists.${RST}\"; exit 1; }\n\n# for flashing the toolhead katapult firmware using flashtool.py\necho \"Checking if python3-serial package is already installed...\"\nif dpkg -l | grep -q python3-serial; then\n    echo \"python3-serial package is already installed. Skipping installation.\"\nelse\n    echo \"python3-serial package is not installed. Installing now...\"\n    sudo apt-get install -y python3-serial\n    if [ $? -eq 0 ]; then\n        echo \"python3-serial package installed successfully!\"\n    else\n        echo \"${RED}Failed to install python3-serial package.${RST}\"\n        exit 1\n    fi\nfi\n\n# for flashing the Plus4 toolhead klipper firmware\necho \"Checking if stlink-tools package is already installed...\"\nif dpkg -l | grep -q stlink-tools; then\n    echo \"stlink-tools package is already installed. Skipping installation.\"\nelse\n    echo \"stlink-tools package is not installed. Installing now...\"\n    sudo apt-get install -y stlink-tools\n    if [ $? -eq 0 ]; then\n        echo \"stlink-tools package installed successfully!\"\n    else\n        echo \"${RED}Failed to install stlink-tools package.${RST}\"\n        exit 1\n    fi\nfi\n\n# Input shaping dependencies (skip on FreeDi image — already included)\necho \"Installing required packages for input shaping...\"\nif [[ \"$OS_CODENAME\" == \"trixie\" ]]; then\n    # Debian 13+: libatlas3-base replaces libatlas-base-dev\n    sudo apt-get install -y libatlas3-base libopenblas-dev ntfs-3g\nelse\n    sudo apt-get install -y libatlas-base-dev libopenblas-dev ntfs-3g\nfi\nif [ $? -ne 0 ]; then\n    echo \"${RED}Error: Failed to install input shaping dependencies.${RST}\"\n    exit 1\nfi\necho \"Input shaping dependencies installed successfully.\""
  },
  {
    "path": "install/wifi.sh",
    "content": "#!/bin/bash\n\n################################################################################\n# CONFIGURE WIFI\n################################################################################\n\n# Console output\necho \"Installing WiFi...\"\n\n# Update package lists\n# Dont. Takes much time.\n#sudo apt-get update\n\n# Install usb-modeswitch\nsudo apt-get install -y usb-modeswitch || {\n    echo \"${RED}Failed to install usb-modeswitch.${RST}\"\n    exit 1\n}\n\n#install eject package for safely ejecting the AIC8800DC after flashing the firmware\nsudo apt-get install -y eject || {\n    echo \"${RED}Failed to install eject.${RST}\"\n    exit 1\n}\n\n\n# ------------------------------------------------------------------\n# Detect which USB Wi-Fi dongle is attached\n# ------------------------------------------------------------------\necho \"Detecting WiFi chip...\"\n\n# 1) Realtek RTL8188GU (needs firmware only)\ndevice_info_rtl=$(lsusb | grep -i \"RTL8188GU\")\nTARGET_FW=\"/lib/firmware/rtlwifi/rtl8710bufw_SMIC.bin\"\n\n# 2) AIC8800DC appears first as mass-storage (id 0x5721)\ndevice_info_aic_mass_storage=$(lsusb | grep -i \"a69c:5721\")\n\n# 3) AIC8800DC already switched to Wi-Fi mode (id 0x0013)\ndevice_info_aic_wifi=$(lsusb | grep -i \"2604:0013\")\n\n# Package/-deb file for AIC8800DC\nAIC_PKG=\"aic8800-dkms\"\nAIC_DEB=\"${WIFI_DIR}/${AIC_PKG}.deb\"\n\n# RTL8188GU  --------------------------------------------------------\nif [ -n \"$device_info_rtl\" ]; then\n    echo \"RTL8188GU detected.\"\n    vendor_id=$(echo \"$device_info_rtl\" | awk '{print $6}' | cut -d: -f1)\n    product_id=$(echo \"$device_info_rtl\" | awk '{print $6}' | cut -d: -f2)\n    echo \"vendor_id: $vendor_id, product_id: $product_id\"\n\n    # Switch device into WLAN mode\n    sudo usb_modeswitch -v \"$vendor_id\" -p \"$product_id\" -J\n\n    # Copy firmware only if it is not already present\n    if [ -f \"$TARGET_FW\" ]; then\n        echo \"Firmware already present – skipping copy.\"\n    else\n        if [ ! -f \"${WIFI_DIR}/rtl8710bufw_SMIC.bin\" ]; then\n            echo \"${RED}Error: firmware file ${WIFI_DIR}/rtl8710bufw_SMIC.bin not found.${RST}\"\n            exit 1\n        fi\n        sudo cp \"${WIFI_DIR}/rtl8710bufw_SMIC.bin\" \"$TARGET_FW\" || {\n            echo \"${RED}Error: failed to copy firmware.${RST}\"; exit 1; }\n    fi\n    echo \"WiFi setup for RTL8188GU finished.\"\n\n# AIC8800DC shows up as mass-storage  -------------------------------\nelif [ -n \"$device_info_aic_mass_storage\" ]; then\n    echo \"AIC8800DC detected as mass-storage device.\"\n    vendor_id=$(echo \"$device_info_aic_mass_storage\" | awk '{print $6}' | cut -d: -f1)\n    product_id=$(echo \"$device_info_aic_mass_storage\" | awk '{print $6}' | cut -d: -f2)\n    echo \"vendor_id: $vendor_id, product_id: $product_id\"\n\n    # Switch device from storage to Wi-Fi mode\n    sudo usb_modeswitch -KQ -v \"$vendor_id\" -p \"$product_id\"\n\n    # Create udev rule so that future plug-ins are switched automatically\n    echo \"Creating udev rule for automatic mode-switch...\"\n    echo \"ACTION==\\\"add\\\", ATTR{idVendor}==\\\"${vendor_id}\\\", ATTR{idProduct}==\\\"${product_id}\\\", RUN+=\\\"/usr/sbin/usb_modeswitch -v ${vendor_id} -p ${product_id} -KQ\\\"\" \\\n        | sudo tee /etc/udev/rules.d/99-usb_modeswitch.rules >/dev/null\n\n    # Reload udev rules immediately\n    sudo udevadm control --reload-rules\n\n    # Install driver only if it is NOT already present (skip on FreeDi image)\n    if [ \"$IS_FREEDI_IMAGE\" = true ] || dpkg -s \"$AIC_PKG\" >/dev/null 2>&1; then\n        if [ \"$IS_FREEDI_IMAGE\" = true ]; then\n            echo \"Running on FreeDi image; driver installation skipped.\"\n        else\n            echo \"$AIC_PKG is already installed – skipping.\"\n        fi\n    else\n        echo \"Installing package $AIC_PKG...\"\n        if [ ! -f \"$AIC_DEB\" ]; then\n            echo \"${RED}Error: driver package $AIC_DEB not found.${RST}\"\n            exit 1\n        fi\n        sudo dpkg -i \"$AIC_DEB\" || { echo \"${RED}Error: dpkg failed.${RST}\"; exit 1; }\n    fi\n    echo \"WiFi setup for AIC8800DC finished.\"\n\n# AIC8800DC already in Wi-Fi mode  ---------------------------------\nelif [ -n \"$device_info_aic_wifi\" ]; then\n    echo \"AIC8800DC detected in Wi-Fi mode.\"\n    vendor_id=$(echo \"$device_info_aic_wifi\" | awk '{print $6}' | cut -d: -f1)\n    product_id=$(echo \"$device_info_aic_wifi\" | awk '{print $6}' | cut -d: -f2)\n    echo \"vendor_id: $vendor_id, product_id: $product_id\"\n\n    # Install driver only if it is NOT already present (skip on FreeDi image as drivers are already included there)\n    if [ \"$IS_FREEDI_IMAGE\" = true ] || dpkg -s \"$AIC_PKG\" >/dev/null 2>&1; then\n        if [ \"$IS_FREEDI_IMAGE\" = true ]; then\n            echo \"Running on FreeDi image; driver installation skipped.\"\n        else\n            echo \"$AIC_PKG is already installed – skipping.\"\n        fi\n    else\n        echo \"Installing package $AIC_PKG...\"\n        if [ ! -f \"$AIC_DEB\" ]; then\n            echo \"${RED}Error: driver package $AIC_DEB not found.${RST}\"\n            exit 1\n        fi\n        sudo dpkg -i \"$AIC_DEB\" || { echo \"${RED}Error: dpkg failed.${RST}\"; exit 1; }\n    fi\n    echo \"WiFi setup for AIC8800DC finished.\"\n\n# No supported device found  ---------------------------------------\nelse\n    echo \"No supported WiFi chip detected. Please make sure the dongle is connected.\"\nfi\n"
  },
  {
    "path": "install.sh",
    "content": "#!/usr/bin/env bash\n#\n# FreeDi Installation Script\n# Installs FreeDi modules, configures services, and sets up hardware dependencies\n#\n# Usage: ./install.sh [--image-build]\n# Note: Do NOT run with sudo or as root - execute as a regular user\n#\n\n################################################################################\n# COLOR DEFINITIONS\n################################################################################\nYLW='\\033[1;33m'   # bold yellow\nRED='\\033[1;31m'   # bold red\nGRN='\\033[1;32m'   # bold green\nRST='\\033[0m'      # reset\n\n################################################################################\n# CONFIGURATION & VARIABLES\n################################################################################\n\nUSER_NAME=$(id -un)\nUSER_GROUP=$(id -gn)\nUSER_HOME_DIR=$(eval echo \"~$USER_NAME\")\nFREEDI_DIR=\"$( cd -- \"$( dirname \"${BASH_SOURCE[0]}\" )\" >/dev/null 2>&1 && pwd -P )\"\n\n# Command-line options\nIMAGE_BUILD=false\nfor arg in \"$@\"; do\n    case \"$arg\" in\n        --image-build)\n            IMAGE_BUILD=true\n            ;;\n        *)\n            printf \"%b\\n\" \"${RED}Error: Unknown argument '$arg'.${RST}\"\n            echo \"Usage: ./install.sh [--image-build]\"\n            exit 1\n            ;;\n    esac\ndone\n\n# Source configuration from separate config file\nsource \"${FREEDI_DIR}/install/freedi_install.conf\"\n\n# Find OS Release codename\nif [ -f /etc/os-release ]; then\n    . /etc/os-release\n    OS_CODENAME=\"$VERSION_CODENAME\"\nelse\n    printf \"%b\\n\" \"${RED}Cannot determine OS codename. Exiting.${RST}\"\n    echo \"Make sure you are running an Armbian-based distribution and that the /etc/os-release file exists.\"\n    exit 1\nfi\n\n# ensure python3 exists and check exact supported versions\nPY_VER=$(python3 -c 'import sys; printf = \"%d.%d\"; print(printf % (sys.version_info.major, sys.version_info.minor))' 2>/dev/null)\nif [ $? -ne 0 ] || [ -z \"$PY_VER\" ]; then\n    printf \"%b\\n\" \"${RED}Error: python3 is not installed or not working. FreeDi requires Python ${SUPPORTED_VERSIONS_JOINED}.${RST}\"; exit 1\nfi\nprintf \"%b\\n\" \"${GRN}Detected Python version: $PY_VER${RST}\"\n# Check if detected version is supported\nHAS_PYTHON_313=false\nSUPPORTED=false\nfor version in \"${SUPPORTED_PYTHON_VERSIONS[@]}\"; do\n    if [ \"$PY_VER\" = \"$version\" ]; then\n        SUPPORTED=true\n        if [ \"$version\" = \"3.13\" ]; then\n            HAS_PYTHON_313=true\n        fi\n        echo \"Using supported Python $version\"\n        break\n    fi\ndone\n\nif [ \"$SUPPORTED\" = false ]; then\n    printf \"%b\\n\" \"${RED}Error: Unsupported Python version $PY_VER. FreeDi only supports ${SUPPORTED_VERSIONS_JOINED}.${RST}\"; exit 1\nfi\n\n# check for proc to determine if we are running on a Qidi X-6 Armbian image\nDEVICE_MODEL=\"$(tr -d '\\000' </proc/device-tree/model 2>/dev/null)\"\nif [[ \"$DEVICE_MODEL\" == *\"Qidi X-6\"* ]]; then\n    IS_FREEDI_IMAGE=true\nelse\n    IS_FREEDI_IMAGE=false\nfi\n\n# -------------------------------------------------------------------------\n# Git index flags – quick reference\n#\n# --assume-unchanged <file>\n#   • File no longer appears as “modified” → working tree stays clean.\n#   • Git MAY overwrite the file when the upstream branch changes it.\n#   • Good for:\n#     local files that you have made temporary tweaks\n#     **or**\n#     files that do not exist in the remote repository (e.g. a new local symlink).\n#\n# --skip-worktree <file>\n#   • File no longer appears as “modified” → working tree stays clean.\n#   • Git will NOT touch the file on pull/merge; local version is kept.\n#   • Good for:\n#     permanently replacing a tracked file with your own copy/symlink and ensuring upstream updates never overwrite it.\n#\n# .git/info/exclude   (local ignore file)\n#   • Works like .gitignore but is **never** pushed; applies only to this local repo.\n#   • Suppresses UNTRACKED files from “git status” and “git add .”.\n#   • Has NO effect on already tracked files (for those use the flags above).\n#   • Project example: we create a new symlink\n#       klippy/extras/freedi.py\n#     which by the time did NOT exist in the upstream Klipper repo.  By adding the line\n#       klippy/extras/freedi.py\n#     to .git/info/exclude we keep the working tree clean while still allowing\n#     the file to live only on the local printer.\n# -------------------------------------------------------------------------\n\n################################################################################\n# GIT WHITELIST DEFINITIONS\n################################################################################\n# PULLABLE_FILES: Accept upstream updates (assume-unchanged)\n# BLOCKED_FILES: Keep local version (skip-worktree)\n\n# FreeDi repository files\nPULLABLE_FILES_FREEDI=(\n    \"klippy/extras/freedi.py\"\n    \"klippy/extras/auto_z_offset.py\"\n    \"FreeDiLCD/freedi_update.sh\"\n)\n\nBLOCKED_FILES_FREEDI=()\n\n# Klipper repository files (not present in upstream)\nPULLABLE_FILES_KLIPPER=(\n    \"klippy/extras/freedi.py\"\n    \"klippy/extras/auto_z_offset.py\"\n)\n\nBLOCKED_FILES_KLIPPER=()\n\n# Abort if the script is executed with sudo/root\nif [ \"$EUID\" -eq 0 ] || [ -n \"$SUDO_USER\" ]; then\n    printf \"%b\\n\" \"${RED}Error: Do NOT run this script with sudo or as root. Execute it as a regular user.${RST}\"; exit 1\nfi\n\n# Ask for mainboard type\ndialog --stdout --title \"Mainboard type\" --backtitle \"FreeDi installation\" --yesno \"Do you use the stock mainboard?\" 7 60\ndialog_exit=$?\n\nif [ $dialog_exit -eq 0 ]; then\n    # User selected \"Yes\"\n    STOCK_MAINBOARD=true\n    clear\n    sleep 1\n    echo \"Starting the installation for stock mainboard...\"\n    PREREQ_DEB=\"${FREEDI_DIR}/helpers/freedi-prerequisites-1.0-all.deb\"\n\n    if [ ! -f \"$PREREQ_DEB\" ]; then\n        printf \"%b\\n\" \"${RED}Error: Required package file not found at $PREREQ_DEB.${RST}\"; exit 1\n    fi\n\n    PREREQ_PKG=\"$(dpkg-deb -f \"$PREREQ_DEB\" Package 2>/dev/null)\"\n    if [ -z \"$PREREQ_PKG\" ]; then\n        printf \"%b\\n\" \"${RED}Error: Could not determine package name from $PREREQ_DEB.${RST}\"; exit 1\n    fi\n\n    if dpkg-query -W -f='${Status}' \"$PREREQ_PKG\" 2>/dev/null | grep -q \"install ok installed\"; then\n        echo \"Package $PREREQ_PKG is already installed. Skipping installation.\"\n    else\n        sudo dpkg -i \"$PREREQ_DEB\"\n        if [ $? -ne 0 ]; then\n            printf \"%b\\n\" \"${RED}Error: Failed to install package $PREREQ_PKG.${RST}\"; exit 1\n        fi\n    fi\nelif [ $dialog_exit -eq 1 ]; then\n    # User selected \"No\"\n    STOCK_MAINBOARD=false\n    # Show dialog with Continue/Abort options for non-stock mainboard warning\n    dialog --title \"NON-stock Mainboard Warning\" \\\n           --backtitle \"FreeDi installation\" \\\n           --yes-label \"Continue\" \\\n           --no-label \"Abort\" \\\n           --yesno \"Notice: You are using a NON-stock mainboard.\\n\\nThe script will try to complete the installation, but because of the large variety of hardware a flawless run cannot be guaranteed.\\n\\nIf problems occur, please open a ticket:\\nhttps://github.com/Phil1988/FreeDi\" 12 70\n    if [ $? -ne 0 ]; then\n        # User selected Abort\n        clear\n        printf \"%b\\n\" \"${RED}Installation cancelled by user.${RST}\"; exit 1\n    fi\nelse\n    # User cancelled or closed the dialog (typically CTRL+C or ESC)\n    printf \"%b\\n\" \"${RED}Installation cancelled by user.${RST}\"; exit 1\nfi\n\n\n################################################################################\n# PRE-FLIGHT CHECKS\n################################################################################\n\n# Klipper installation check\n# Check for klipper, moonraker and mainsail directories to determine if Klipper is installed correctly\nif [ ! -d \"$KLIPPER_DIR\" ] || [ ! -d \"$MOONRAKER_DIR\" ] || [ ! -d \"$MAINSAIL_DIR\" ] || [ ! -d \"$CROWSNEST_DIR\" ]; then\n    dialog --stdout --title \"Klipper installation missing\" --backtitle \"FreeDi installation\" --yes-label \"Yes\" --no-label \"No\" --yesno \"One or more required modules are missing (Klipper, Moonraker, Mainsail).\\n\\nShould Klipper installation via KIAUH be started?\\n\\nPlease install Klipper, Moonraker, Mainsail and Crowsnest.\" 10 70\n    klipper_dialog_exit=$?\n\n    if [ $klipper_dialog_exit -eq 0 ]; then\n        clear\n        echo \"Starting Klipper installation via KIAUH...\"\n        # Clone KIAUH installer\n        KIAUH_DIR=\"$USER_HOME_DIR/kiauh\"\n        if [ -d \"$KIAUH_DIR\" ]; then\n            echo \"KIAUH directory already exists at $KIAUH_DIR. Skipping clone.\"\n        else\n            git clone https://github.com/dw-0/kiauh.git \"$KIAUH_DIR\"\n            if [ $? -ne 0 ]; then\n                printf \"%b\\n\" \"${RED}Error: Failed to clone KIAUH repository.${RST}\"; exit 1\n            fi\n        fi\n    else\n        clear\n        printf \"%b\\n\" \"${RED}Error: Klipper directory not found at $KLIPPER_DIR. Please install Klipper first.${RST}\"; exit 1\n    fi\n    clear\n    # Run KIAUH installer\n    bash \"$KIAUH_DIR/kiauh.sh\"\nfi\n\n# Create a symbolic links for needed modules to the Klipper extras directory\nFREEDI_MODULES=(\n    \"freedi.py\"\n    \"qidi_auto_z_offset/auto_z_offset.py\"\n    #\"reverse_homing.py\"\n    #\"hall_filament_width_sensor.py\"\n)\n\nfor MODULE_PATH in \"${FREEDI_MODULES[@]}\"; do\n    MODULE_NAME=$(basename \"${MODULE_PATH}\")\n\n    echo \"Creating a symbolic link for ${MODULE_NAME} from ${REPO_MODULE_DIR}/${MODULE_PATH} to ${KLIPPER_EXTRAS_DIR} …\"\n    if ln -sf \"${REPO_MODULE_DIR}/${MODULE_PATH}\" \"${KLIPPER_EXTRAS_DIR}/${MODULE_NAME}\"; then\n        # Ensure the symlink belongs to the regular user, not root\n        chown -h \"${USER_NAME}:${USER_GROUP}\" \"${KLIPPER_EXTRAS_DIR}/${MODULE_NAME}\"\n        echo \"Successfully installed ${MODULE_NAME} to ${KLIPPER_EXTRAS_DIR}.\"\n    else\n        echo \"Error: failed to create a symbolic link for ${MODULE_NAME}.\" >&2\n        exit 1\n    fi\ndone\n\n################################################################################\n# INSTALL APT PACKAGES (externalized to install/packages.sh)\n################################################################################\n\necho \"Installing apt packages from ${FREEDI_DIR}/install/packages.sh...\"\nif [ -f \"${FREEDI_DIR}/install/packages.sh\" ]; then\n    # shellcheck source=/dev/null\n    . \"${FREEDI_DIR}/install/packages.sh\"\nelse\n    printf \"%b\\n\" \"${RED}Error: Package installation script not found at ${FREEDI_DIR}/install/packages.sh${RST}\"; exit 1\nfi\n\n################################################################################\n# GIT REPOSITORY VALIDATION & CONFIGURATION\n################################################################################\n\n# Check if the script is run inside a Git repository\nif [ ! -d \"${FREEDI_DIR}/.git\" ]; then\n    echo \"Error: Not a git repository. Please initialize the repository first.\"\n    exit 1\nfi\n\n# Ensure the Klipper extras directory exists\nif [ ! -d \"$KLIPPER_EXTRAS_DIR\" ]; then\n    echo \"Error: Klipper extras directory not found at $KLIPPER_EXTRAS_DIR.\"\n    echo \"Make sure Klipper is installed correctly.\"\n    exit 1\nfi\n\n# Wrapper to execute commands as the target user when running as root\n# Especially useful for Git operations\nrun_as_user() {\n    if [ \"$(id -u)\" -eq 0 ]; then\n        sudo -u \"$USER_NAME\" -- \"$@\"\n    else\n        \"$@\"\n    fi\n}\n\n# Helper: keep repo clean for a given list of files\n# • pullable → assume-unchanged\n# • blocked  → skip-worktree\n# • detects & clears an already recorded change (typechange, content, …)\n# • runs Git as $USER_NAME even when script is executed as root\nclean_repo() {\n    local repo=\"$1\"\n    local mode=\"$2\"\n    shift 2\n    local files=(\"$@\")\n\n    # Determine the .git directory and build absolute path to info/exclude\n    local git_dir\n    git_dir=\"$(run_as_user git -C \"$repo\" rev-parse --git-dir)\"\n    local exclude_file=\"${repo}/${git_dir}/info/exclude\"\n    echo \"Exclude file resolved to: $exclude_file\"\n\n    # Ensure the exclude file exists\n    run_as_user mkdir -p \"$(dirname \"$exclude_file\")\"\n    run_as_user touch \"$exclude_file\"\n\n    for f in \"${files[@]}\"; do\n        local full_path=\"${repo}/${f}\"\n        local st\n        st=\"$(run_as_user git -C \"$repo\" status --porcelain -- \"$f\")\"\n\n        # Warn if file/symlink is missing in working tree\n        if [ ! -e \"$full_path\" ]; then\n            printf \"%b\\n\" \"${YLW}Notice: ${f} does not exist in working tree – index/ignore rules are still applied.${RST}\"\n        fi\n\n        # ------------------------------------------------------------------\n        # CASE 1 : tracked file or type-change\n        # ------------------------------------------------------------------\n        if run_as_user git -C \"$repo\" ls-files --error-unmatch \"$f\" >/dev/null 2>&1 \\\n           || [[ $st =~ ^.?T ]]; then\n\n            # Check if this file has changes already\n            local dirty_pre=false\n            if [ -n \"$st\" ]; then\n                printf \"%b\\n\" \"${YLW}Detected changes for ${f} in index / working tree (causes dirty repo).${RST}\"\n                dirty_pre=true\n            fi\n\n            if [[ \"$mode\" == \"pullable\" ]]; then\n                if run_as_user git -C \"$repo\" update-index --assume-unchanged -- \"$f\"; then\n                    echo -e \"Git will now ignore local changes to ${f} (assume-unchanged).\"\n                else\n                    printf \"%b\\n\" \"${RED}Warning: git update-index failed for ${f} – file NOT marked.${RST}\"\n                fi\n            else\n                if run_as_user git -C \"$repo\" update-index --skip-worktree -- \"$f\"; then\n                    echo -e \"Git will keep your local version of ${f} (skip-worktree).\"\n                else\n                    printf \"%b\\n\" \"${RED}Warning: git update-index failed for ${f} – file NOT marked.${RST}\"\n                fi\n            fi\n\n            # If it was dirty, refresh index to clear existing change\n            if [ \"$dirty_pre\" = true ]; then\n                printf \"%b\\n\" \"${YLW}Cleaning index / working tree for ${f}...${RST}\"\n                run_as_user git -C \"$repo\" update-index --really-refresh -q -- \"$f\"\n                if run_as_user git -C \"$repo\" status --porcelain -- \"$f\" | grep -q .; then\n                    printf \"%b\\n\" \"${RED}Index still reports changes for ${f}!${RST}\"\n                else\n                    printf \"%b\\n\" \"${YLW}Index cleaned for ${f}.${RST}\"\n                fi\n            fi\n\n        # ------------------------------------------------------------------\n        # CASE 2 : untracked file → add to info/exclude\n        # ------------------------------------------------------------------\n        else\n            if ! grep -Fxq \"$f\" \"$exclude_file\"; then\n                if printf '%s\\n' \"$f\" | run_as_user tee -a \"$exclude_file\" >/dev/null; then\n                    echo -e \"Added ${f} to $(basename \"$exclude_file\") (untracked→exclude).\"\n                else\n                    printf \"%b\\n\" \"${RED}Warning: failed to write ${f} to $(basename \"$exclude_file\").${RST}\"\n                fi\n            else\n                echo -e \"${f} already listed in $(basename \"$exclude_file\") – skipping.\"\n            fi\n        fi\n    done\n}\n\n# Apply git whitelist configuration\necho \"Configuring git repositories for clean working tree...\"\nclean_repo \"$FREEDI_DIR\" pullable \"${PULLABLE_FILES_FREEDI[@]}\"\nclean_repo \"$FREEDI_DIR\" blocked  \"${BLOCKED_FILES_FREEDI[@]}\"\nclean_repo \"$KLIPPER_DIR\" pullable \"${PULLABLE_FILES_KLIPPER[@]}\"\nclean_repo \"$KLIPPER_DIR\" blocked  \"${BLOCKED_FILES_KLIPPER[@]}\"\n\n# Restart Klipper to load the new module\necho \"Restarting Klipper service...\"\nsudo systemctl restart klipper\n\nif [ $? -eq 0 ]; then\n    echo \"Klipper service restarted successfully.\"\n    echo \"Installation complete.\"\nelse\n    printf \"%b\\n\" \"${RED}Error: Failed to restart Klipper service.${RST}\"; exit 1\nfi\n\n################################################################################\n# STOCK MAINBOARD CONFIGURATION\n################################################################################\nif [ \"$STOCK_MAINBOARD\" = true ]; then\n\n    ### Setup serial port for LCD communication ####\n    # Console output\n    echo \"Setup dtbo for serial communication...\"\n    # Install dtbo file for serial communication\n    if [ ! -f \"${DTBO_DIR}/rockchip-mkspi-uart1.dtbo\" ]; then\n        printf \"%b\\n\" \"${RED}Error: Source file ${DTBO_DIR}/rockchip-mkspi-uart1.dtbo does not exist. Aborting.${RST}\"; exit 1\n    fi\n    sudo mkdir -p \"$DTBO_TARGET\"                                        # make sure directory exists\n    sudo cp \"${DTBO_DIR}/rockchip-mkspi-uart1.dtbo\" \"${DTBO_TARGET}/\"\n    if [ $? -ne 0 ]; then\n        printf \"%b\\n\" \"${RED}Error: Failed to copy rockchip-mkspi-uart1.dtbo. Aborting.${RST}\"; exit 1\n    fi\n    echo \"dtbo install done!\"\n\n    # Stating the modification of the armbianEnv.txt\n    echo \"Customize the armbianEnv.txt file for serial communication...\"\n    # The file to check\n    ARMBIAN_ENV_FILE=\"/boot/armbianEnv.txt\"\n    # The entry to search for\n    SEARCH_STRING_OVERLAYS=\"overlays=\"\n    # The new line to add or replace\n    NEW_LINE_OVERLAYS=\"overlays=mkspi-uart1\"\n\n    # The entry to search for\n    SEARCH_STRING_CONSOLE=\"console=\"\n    # The new line to add or replace\n    NEW_LINE_CONSOLE=\"console=none\"\n\n\n    # Check if the file exists\n    if [ ! -f \"$ARMBIAN_ENV_FILE\" ]; then\n        echo \"File $ARMBIAN_ENV_FILE does not exist.\"\n        exit 1\n    fi\n\n    # Check if the file contains the search string and perform the corresponding action\n    if [ \"$IS_FREEDI_IMAGE\" = false ]; then\n        if sudo grep -q \"^$SEARCH_STRING_OVERLAYS\" \"$ARMBIAN_ENV_FILE\"; then\n            echo \"Overlays line found. Replacing the line.\"\n            sudo sed -i \"s/^$SEARCH_STRING_OVERLAYS.*/$NEW_LINE_OVERLAYS/\" \"$ARMBIAN_ENV_FILE\"\n        else\n            echo \"Overlays line not found. Adding the line.\"\n            echo \"$NEW_LINE_OVERLAYS\" | sudo tee -a \"$ARMBIAN_ENV_FILE\" > /dev/null\n        fi\n    fi\n\n    # Check if the file contains the search string and perform the corresponding action\n    if sudo grep -q \"^$SEARCH_STRING_CONSOLE\" \"$ARMBIAN_ENV_FILE\"; then\n        echo \"Console line found. Replacing the line.\"\n        sudo sed -i \"s/^$SEARCH_STRING_CONSOLE.*/$NEW_LINE_CONSOLE/\" \"$ARMBIAN_ENV_FILE\"\n    else\n        echo \"Console line not found. Adding the line.\"\n        echo \"$NEW_LINE_CONSOLE\" | sudo tee -a \"$ARMBIAN_ENV_FILE\" > /dev/null\n    fi\n\n\n    echo \"armbianEnv.txt file modified successfully!\"\n\n\n    ### Setup udev rules for ttyS2 ###\n\n    echo \"Creating udev rules for ttyS2...\"\n    echo 'KERNEL==\"ttyS2\",MODE=\"0660\"' | sudo tee /etc/udev/rules.d/99-ttyS2.rules > /dev/null\n    echo \"udev rule for ttyS2 created.\"\n    echo \"Masking serial-getty service for ttyS2...\"\n    sudo systemctl mask serial-getty@ttyS2.service\n    echo \"serial-getty service for ttyS2 masked.\"\n    echo \"Reloading udev rules...\"\n    sudo udevadm control --reload-rules\n    echo \"udev rules reloaded.\"\n    echo \"Triggering udev events...\"\n    sudo udevadm trigger\n    echo \"udev events triggered.\"\nfi   # end of stock mainboard section\n\n################################################################################\n# CONFIGURE TOOLHEAD SERIAL PORT\n################################################################################\n\necho \"Setup the toolhead serial path in printer.cfg...\"\n\n# Check if serial devices exist\nif [ -d \"/dev/serial/by-id\" ]; then\n    # Find the first available serial devices that contain \"usb-Klipper_rp2040\" in the name\n    path=$(ls /dev/serial/by-id/* | grep \"usb-Klipper_rp2040\" | head -n 1)\n\n    if [ -n \"$path\" ]; then\n        echo \"Found serial device: $path\"\n\n        # Check if the printer.cfg file exists\n        if [ -f \"$PRINTER_CONFIG\" ]; then\n            echo \"Modifying printer.cfg\"\n\n            # Use sed to update the serial line only within the [mcu Toolhead] section\n            sudo sed -i \"/\\[mcu Toolhead\\]/,/^\\[/ {s|^serial:.*|serial: ${path}|}\" \"$PRINTER_CONFIG\"\n            echo \"Updated serial path for the toolhead in $PRINTER_CONFIG\"\n        else\n            printf \"%b\\n\" \"${RED}Error: $PRINTER_CONFIG not found!${RST}\"\n        fi\n    else\n        echo \"No serial device found in /dev/serial/by-id.\"\n    fi\nelse\n    printf \"%b\\n\" \"${RED}Error: no serial devices found in /dev/serial/by-id${RST}\"\nfi\n\n\n################################################################################\n# CONFIGURE PYTHON ENVIRONMENT\n################################################################################\n\n# Activate the Klipper virtual environment and install required Python packages\necho \"Activating Klipper virtual environment and installing Python packages...\"\n\nif [ ! -d \"$KLIPPER_ENV\" ]; then\n    printf \"%b\\n\" \"${RED}reKlippy env doesn't exist so I can't continue installation...${RST}\"; exit 1\nfi\n\nPYTHON_V=$($KLIPPER_VENV_PYTHON_BIN -c 'import sys; print(\".\".join(map(str, sys.version_info[:3])))')\nprintf \"%b\\n\" \"${GRN}Klipper environment python version: $PYTHON_V${RST}\"\n# Arrange Python requirements from requirements.txt\necho \"Arranging Python requirements...\"\n\"${KLIPPER_ENV}/bin/pip\" install --upgrade pip\n\"${KLIPPER_ENV}/bin/pip\" install -r \"${FREEDI_DIR}/requirements.txt\"\nif [ $? -ne 0 ]; then\n    printf \"%b\\n\" \"${RED}Failed to install Python requirements.${RST}\"; exit 1\nfi\necho \"Python requirements installed from requirements.txt.\"\n\n################################################################################\n# CONFIGURE MOONRAKER\n################################################################################\n\n# Adding FreeDi section to moonraker update manager\necho \"Adding FreeDi section to moonraker update manager...\"\n\n# Check if the file exists\nif [ -f \"${MOONRAKER_CONF}\" ]; then\n    echo \"Moonraker configuration file ${MOONRAKER_CONF} found\"\n\n    # Check if the section [update_manager FreeDi] exists\n    if grep -q \"^\\[update_manager FreeDi\\]\" \"${MOONRAKER_CONF}\"; then\n        echo \"The section [update_manager FreeDi] already exists in the file.\"\n    else\n        echo \"The section [update_manager FreeDi] does not exist. Adding it to the end of the file.\"\n\n        # Append the block to the end of the file\n        cat <<EOL >> \"${MOONRAKER_CONF}\"\n# FreeDi update_manager entry\n\n[update_manager FreeDi]\ntype: git_repo\npath: ~/FreeDi\nchannel: stable\norigin: https://github.com/Phil1988/FreeDi\nvirtualenv: ~/klippy-env\nrequirements: requirements.txt\nmanaged_services: FreeDi\ninfo_tags:\n    desc=FreeDi\n    sparse_dirs:\n    - FreeDiLCD\n    - screen_firmwares\n\nEOL\n        echo \"The section [update_manager FreeDi] has been added to the file.\"\n    fi\nelse\n    echo \"File does not exist: ${MOONRAKER_CONF}\"\n    exit 1\nfi\n\n# Permit Moonraker to restart FreeDi service\necho \"Permit Moonraker to restart FreeDi service...\"\n\n# Check if the file exists\nif [ -f \"${MOONRAKER_ASVC}\" ]; then\n    # Search for the string \"FreeDi\" in the file\n    if grep -Fxq \"FreeDi\" \"${MOONRAKER_ASVC}\"; then\n        echo \"\\\"FreeDi\\\" is already present in the moonraker.asvc file. No changes made.\"\n    else\n        # Append \"FreeDi\" to the end of the file\n        echo \"FreeDi\" >> \"${MOONRAKER_ASVC}\"\n        echo \"\\\"FreeDi\\\" has been added to the moonraker.asvc file.\"\n    fi\nelse\n    echo \"moonraker.asvc file not found: ${MOONRAKER_ASVC}\"\nfi\n\n\n################################################################################\n# CONFIGURE NETWORK MANAGER\n################################################################################\n\n# Console output\necho \"Changing permissions to enable nmcli commands without sudo (necessary for setting wifi via screen)...\"\n\n# Define variables\nNETWORK_MANAGER_CONF_FILE=\"/etc/NetworkManager/NetworkManager.conf\"\n\n# Add the user to the netdev group\necho \"Adding the user ${USER_NAME} to the 'netdev' group...\"\nsudo usermod -aG netdev \"${USER_NAME}\"\n\n# Check if the auth-polkit line already exists in the config file\n# Add the auth-polkit=false line after plugins=ifupdown,keyfile in the [main] section\nif grep -q '^\\[main\\]' \"$NETWORK_MANAGER_CONF_FILE\"; then\n    if ! grep -q '^auth-polkit=false' \"$NETWORK_MANAGER_CONF_FILE\"; then\n        echo \"Adding 'auth-polkit=false' to ${NETWORK_MANAGER_CONF_FILE}...\"\n        sudo sed -i '/^plugins=ifupdown,keyfile/a auth-polkit=false' \"$NETWORK_MANAGER_CONF_FILE\"\n    else\n        echo \"'auth-polkit=false' is already present in ${NETWORK_MANAGER_CONF_FILE}.\"\n    fi\nelse\n    echo \"The [main] section was not found in ${NETWORK_MANAGER_CONF_FILE}.\"\nfi\n\n# Display information\necho \"User ${USER_NAME} has been successfully configured to run nmcli commands without sudo.\"\n\n\n################################################################################\n# CONFIGURE WIFI (externalized to install/wifi.sh)\n################################################################################\n\necho \"Running WiFi setup from ${FREEDI_DIR}/install/wifi.sh...\"\nif [ \"$IS_FREEDI_IMAGE\" != true ]; then\n    if [ -f \"${FREEDI_DIR}/install/wifi.sh\" ]; then\n        . \"${FREEDI_DIR}/install/wifi.sh\"\n    else\n        printf \"%b\\n\" \"${RED}Error: WiFi setup script not found at ${FREEDI_DIR}/install/wifi.sh${RST}\"; exit 1\n    fi\nelse\n    echo \"WiFi setup skipped, OS image already supports WiFi devices.\"\nfi\n\n\n################################################################################\n# CONFIGURE USB MOUNTER SERVICE\n################################################################################\n\n# Creating udev rule\necho \"Creating udev rule...\"\n#sudo echo 'ACTION==\"add|remove\", SUBSYSTEM==\"block\", KERNEL==\"sd[a-z][0-9]*\", ENV{DEVTYPE}==\"partition\", RUN+=\"/usr/bin/systemctl start usb-mount@%E{ACTION}-%k\"' > /etc/udev/rules.d/99-usb-thumb.rules\necho 'ACTION==\"add|remove\", SUBSYSTEM==\"block\", KERNEL==\"sd[a-z][0-9]*\", ENV{DEVTYPE}==\"partition\", RUN+=\"/usr/bin/systemctl start usb-mount@%E{ACTION}-%k\"' | sudo tee /etc/udev/rules.d/99-usb-thumb.rules > /dev/null\n\necho \"Udev rule created: /etc/udev/rules.d/99-usb-thumb.rules\"\n\n# Creating systemd service file\necho \"Creating systemd service file...\"\nsudo bash -c 'cat <<EOL > /etc/systemd/system/usb-mount@.service\n[Unit]\nDescription=USB Mount Service (%i)\n\n[Service]\nType=simple\nExecStart='\"${FREEDI_DIR}\"'/helpers/usbmounter.sh '\"${USER_NAME}\"' %i\n\nEOL'\necho \"Systemd service file created: /etc/systemd/system/usb-mount@.service\"\n\n# Make the script executable\necho \"Making the usbmounter.sh executable...\"\nif [ ! -f \"${FREEDI_DIR}/helpers/usbmounter.sh\" ]; then\n    printf \"%b\\n\" \"${RED}Error: File ${FREEDI_DIR}/helpers/usbmounter.sh does not exist. Aborting.${RST}\"; exit 1\nfi\nchmod +x \"${FREEDI_DIR}/helpers/usbmounter.sh\"\nif [ $? -ne 0 ]; then\n    printf \"%b\\n\" \"${RED}Error: Failed to set executable permission for usbmounter.sh. Aborting.${RST}\"; exit 1\nfi\n\n# Reload udev and systemd\nsudo udevadm control --reload-rules\nsudo systemctl daemon-reload\necho \"Udev and systemd have been reloaded.\"\necho \"USB mounter service created successfully!\"\n\n\n################################################################################\n# CONFIGURE FREEDI SERVICE\n################################################################################\n\n# Autostart the program\necho \"Installing FreeDi service...\"\n\n# Stop running FreeDi service\necho \"Stopping FreeDi service...\"\nsudo systemctl stop FreeDi.service\necho \"FreeDi service stopped.\"\n\n# Move FreeDi.service to systemd directory\necho \"Moving FreeDi.service to /etc/systemd/system/\"\nif [ ! -f \"${FREEDI_DIR}/helpers/FreeDi.service\" ]; then\n    printf \"%b\\n\" \"${RED}Error: Source file ${FREEDI_DIR}/helpers/FreeDi.service does not exist. Aborting.${RST}\"; exit 1\nfi\nsudo cp \"${FREEDI_DIR}/helpers/FreeDi.service\" /etc/systemd/system/FreeDi.service\nif [ $? -ne 0 ]; then\n    printf \"%b\\n\" \"${RED}Error: Failed to copy FreeDi.service to /etc/systemd/system/. Aborting.${RST}\"; exit 1\nfi\necho \"FreeDi.service moved to /etc/systemd/system/\"\n\n# Setting current user in FreeDi.service\necho \"Setting user to $USER_NAME in FreeDi.service\"\nif [ ! -f /etc/systemd/system/FreeDi.service ]; then\n    printf \"%b\\n\" \"${RED}Error: File /etc/systemd/system/FreeDi.service does not exist. Aborting.${RST}\"; exit 1\nfi\nsudo sed -i \"s/{{USER}}/${USER_NAME}/g\" /etc/systemd/system/FreeDi.service\nif [ $? -ne 0 ]; then\n    printf \"%b\\n\" \"${RED}Error: Failed to replace user in /etc/systemd/system/FreeDi.service. Aborting.${RST}\"; exit 1\nfi\n\n# Enable FreeDi.service to start at boot\necho \"Enabling FreeDi.service to start at boot...\"\nsudo systemctl enable FreeDi.service\necho \"FreeDi.service enabled to start at boot!\"\n\n################################################################################\n# CONFIGURE AUTOFLASHER SERVICE\n################################################################################\n\necho \"Installing AutoFlasher.service...\"\nif [ ! -f \"${FREEDI_DIR}/helpers/AutoFlasher.service\" ]; then\n    printf \"%b\\n\" \"${RED}Error: Source file ${FREEDI_DIR}/helpers/AutoFlasher.service does not exist. Aborting.${RST}\"; exit 1\nfi\nsudo cp \"${FREEDI_DIR}/helpers/AutoFlasher.service\" /etc/systemd/system/AutoFlasher.service\nif [ $? -ne 0 ]; then\n    printf \"%b\\n\" \"${RED}Error: Failed to copy AutoFlasher.service to /etc/systemd/system/. Aborting.${RST}\"; exit 1\nfi\necho \"AutoFlasher.service installed!\"\n\n# Setting current user in AutoFlasher.service\necho \"Setting user to $USER_NAME in AutoFlasher.service\"\n\nif [ ! -f \"/etc/systemd/system/AutoFlasher.service\" ]; then\n    printf \"%b\\n\" \"${RED}Error: File /etc/systemd/system/AutoFlasher.service does not exist. Aborting.${RST}\"; exit 1\nfi\nsudo sed -i \"s/{{USER}}/${USER_NAME}/g\" /etc/systemd/system/AutoFlasher.service\nif [ $? -ne 0 ]; then\n    printf \"%b\\n\" \"${RED}Error: Failed to replace user in /etc/systemd/system/AutoFlasher.service. Aborting.${RST}\"; exit 1\nfi\n\n\n# Make the script executable\nif [ ! -f \"${FREEDI_DIR}/helpers/klipper_auto_flasher.sh\" ]; then\n    printf \"%b\\n\" \"${RED}Error: File ${FREEDI_DIR}/helpers/klipper_auto_flasher.sh does not exist. Aborting.${RST}\"; exit 1\nfi\nchmod +x \"${FREEDI_DIR}/helpers/klipper_auto_flasher.sh\"\nif [ $? -ne 0 ]; then\n    printf \"%b\\n\" \"${RED}Error: Failed to set executable permission for klipper_auto_flasher.sh. Aborting.${RST}\"; exit 1\nfi\n\n# Enable AutoFlasher.service to start at boot\necho \"Enabling AutoFlasher.service to start at boot...\"\nsudo systemctl enable AutoFlasher.service\necho \"AutoFlasher.service enabled to start at boot!\"\n\n# Make hid-flash executable\necho \"Making hid-flash executable...\"\nif [ ! -f \"${FREEDI_DIR}/helpers/hid-flash\" ]; then\n    printf \"%b\\n\" \"${RED}Error: File ${FREEDI_DIR}/helpers/hid-flash does not exist. Aborting.${RST}\"; exit 1\nfi\nchmod +x \"${FREEDI_DIR}/helpers/hid-flash\"\nif [ $? -ne 0 ]; then\n    printf \"%b\\n\" \"${RED}Error: Failed to set executable permission for hid-flash. Aborting.${RST}\"; exit 1\nfi\n\necho \"AutoFlasher.service installed!\"\n################################################################################\n# FINALIZE INSTALLATION\n################################################################################\n\n# copy files from config_section/generic to printer_data/config overwriting existing files\nif [ -d \"${FREEDI_DIR}/config_section/generic\" ]; then\n    echo \"Copying generic config section files to printer_data/config...\"\n    sudo cp -r \"${FREEDI_DIR}/config_section/generic/.\" \"$PRINTER_DATA_DIR/config/\"\n    sudo chown -R \"${USER_NAME}:${USER_GROUP}\" \"$PRINTER_DATA_DIR/config/\"\n    echo \"Generic config section files copied to printer_data/config.\"\nelse\n    printf \"%b\\n\" \"${RED}Error: Source directory ${FREEDI_DIR}/config_section/generic does not exist. Aborting.${RST}\"; exit 1\nfi\n\n# Check if crowsnest directory exists and ask if timelapse should be installed\nif [ -d \"$CROWSNEST_DIR\" ] && [ ! -d \"$TIMELAPSE_DIR\" ]; then\n    dialog --stdout --title \"Crowsnest detected\" --backtitle \"FreeDi installation\" --yes-label \"Yes\" --no-label \"No\" --yesno \"Crowsnest directory detected at $CROWSNEST_DIR. Do you want to install the moonraker timelapse module?\" 10 70\n    if [ $? -eq 0 ]; then\n        echo \"Installing timelapse module from git...\"\n        # Clone the timelapse into home directory\n        git clone https://github.com/mainsail-crew/moonraker-timelapse.git \"$TIMELAPSE_DIR\"\n        if [ $? -ne 0 ]; then\n            printf \"%b\\n\" \"${RED}Error: Failed to clone timelapse repository.${RST}\"; exit 1\n        fi\n        echo \"Timelapse module installed at $TIMELAPSE_DIR.\"\n        # execute make install for timelapse module\n        echo \"Executing make install for timelapse module...\"\n        if [ -f \"${TIMELAPSE_DIR}/Makefile\" ]; then\n            make -C \"${TIMELAPSE_DIR}\" install\n            if [ $? -ne 0 ]; then\n                printf \"%b\\n\" \"${RED}Error: Failed to execute make install for timelapse module.${RST}\"; exit 1\n            fi\n            # add timlapse update to moonraker update manager\n            echo \"Adding timelapse update to moonraker update manager...\"\n            if [ -f \"${MOONRAKER_CONF}\" ]; then\n                if grep -q \"^\\[update_manager timelapse\\]\" \"${MOONRAKER_CONF}\"; then\n                    echo \"The section [update_manager timelapse] already exists in the file.\"\n                else\n                    echo \"The section [update_manager timelapse] does not exist. Adding it to the end of the file.\"\n\n                    # Append the block to the end of the file\n                    cat <<EOL >> \"${MOONRAKER_CONF}\"\n\n# Timelapse module update_manager entry\n\n[update_manager timelapse]\ntype: git_repo\nprimary_branch: main\npath: ~/moonraker-timelapse\norigin: https://github.com/mainsail-crew/moonraker-timelapse.git\nmanaged_services: klipper moonraker\nEOL\n                    echo \"The section [update_manager timelapse] has been added to the file.\"\n                fi\n            else\n                echo \"File does not exist: ${MOONRAKER_CONF}\"\n                exit 1\n            fi\n            echo \"Timelapse module installed successfully!\"\n        else\n            printf \"%b\\n\" \"${RED}Error: Makefile not found in timelapse directory. Cannot install timelapse module.${RST}\"; exit 1\n        fi\n    else\n        echo \"Timelapse module installation skipped.\"\n    fi\nelif [ -d \"$TIMELAPSE_DIR\" ]; then\n    echo \"Timelapse directory already exists at $TIMELAPSE_DIR. Skipping timelapse module installation.\"\nfi\n\n#remove kiauh directory if it was created during this installation\nif [ -d \"$KIAUH_DIR\" ]; then\n    echo \"Removing KIAUH directory at $KIAUH_DIR...\"\n    rm -rf \"$KIAUH_DIR\"\n    if [ $? -ne 0 ]; then\n        printf \"%b\\n\" \"${RED}Error: Failed to remove KIAUH directory at $KIAUH_DIR. Please remove it manually.${RST}\"; exit 1\n    fi\nfi\n\n#remove kiauh_backups directory if it was created during this installation\nKIAUH_BACKUP_DIR=\"$USER_HOME_DIR/kiauh_backups\"\nif [ -d \"$KIAUH_BACKUP_DIR\" ]; then\n    echo \"Removing KIAUH backup directory at $KIAUH_BACKUP_DIR...\"\n    rm -rf \"$KIAUH_BACKUP_DIR\"\n    if [ $? -ne 0 ]; then\n        printf \"%b\\n\" \"${RED}Error: Failed to remove KIAUH backup directory at $KIAUH_BACKUP_DIR. Please remove it manually.${RST}\"; exit 1\n    fi\nfi\n\n# touch printer_data/config/macros.cfg to prevent potential permission issues\nif [ ! -f \"$PRINTER_DATA_DIR/config/macros.cfg\" ]; then\n    sudo touch \"$PRINTER_DATA_DIR/config/macros.cfg\"\n    sudo chown \"${USER_NAME}:${USER_GROUP}\" \"$PRINTER_DATA_DIR/config/macros.cfg\"\n    echo \"empty macros.cfg created at $PRINTER_DATA_DIR/config/macros.cfg.\"\nfi\n\n#remove moonraker.conf.backup if it was created during this installation\nMOONRAKER_CONF_BACKUP=\"${MOONRAKER_CONF}.backup\"\nif [ -f \"$MOONRAKER_CONF_BACKUP\" ]; then\n    echo \"Removing Moonraker configuration backup file at $MOONRAKER_CONF_BACKUP...\"\n    rm -f \"$MOONRAKER_CONF_BACKUP\"\n    if [ $? -ne 0 ]; then\n        printf \"%b\\n\" \"${RED}Error: Failed to remove Moonraker configuration backup file at $MOONRAKER_CONF_BACKUP. Please remove it manually.${RST}\"; exit 1\n    fi\nfi\n\n# edit /etc/systemd/system/crowsnest service to restart on failure and delay starting by 5 seconds\nif [ -f \"/etc/systemd/system/crowsnest.service\" ]; then\n    echo \"Configuring crowsnest.service to restart on failure and delay start by 5 seconds...\"\n    sudo sed -i '/\\[Service\\]/a Restart=on-failure\\nRestartSec=5' /etc/systemd/system/crowsnest.service\n    sudo sed -i '/\\[Service\\]/a ExecStartPre=/bin/sleep 5' /etc/systemd/system/crowsnest.service\n    if [ $? -ne 0 ]; then\n        printf \"%b\\n\" \"${RED}Error: Failed to configure crowsnest.service. Aborting.${RST}\"; exit 1\n    fi\n    echo \"crowsnest.service configured successfully.\"\n    sudo systemctl restart crowsnest.service\n    if [ $? -ne 0 ]; then\n        printf \"%b\\n\" \"${RED}Error: Failed to restart crowsnest.service after configuration changes. Please check the service status and logs.${RST}\"\n    else\n        echo \"crowsnest.service restarted successfully with new configuration.\"\n    fi\nelse\n    echo \"crowsnest.service not found at /etc/systemd/system/crowsnest.service. Skipping crowsnest service configuration.\"\nfi\n\necho \"Reloading systemd manager configuration...\"\nsudo systemctl daemon-reload\necho \"systemd manager configuration reloaded.\"\necho \"Starting FreeDi service...\"\nsudo systemctl start FreeDi.service\necho \"FreeDi service started!\"\nif [ \"$IMAGE_BUILD\" = true ]; then\n    echo \"Image build mode enabled:\"\n    # clear machine-id to prevent conflicts when flashing the image to multiple devices\n    echo \"Clearing /etc/machine-id...\"\n    : | sudo tee /etc/machine-id >/dev/null\n    if [ $? -ne 0 ]; then\n        printf \"%b\\n\" \"${RED}Error: Failed to clear /etc/machine-id.${RST}\"; exit 1\n    fi\n    # change sshd config to prevent root login via ssh and show last login info\n    echo \"Configuring sshd for image build...\"\n    SSHD_CONFIG=\"/etc/ssh/sshd_config\"\n    if [ -f \"$SSHD_CONFIG\" ]; then\n        sudo sed -i 's/^#\\?PermitRootLogin.*/PermitRootLogin no/' \"$SSHD_CONFIG\"\n        sudo sed -i 's/^#\\?PrintLastLog.*/PrintLastLog yes/' \"$SSHD_CONFIG\"\n        echo \"sshd configuration updated for image build.\"\n    else\n        printf \"%b\\n\" \"${RED}Error: sshd_config file not found at $SSHD_CONFIG. Aborting.${RST}\"; exit 1\n    fi\n\n    echo \"Halting system for image build finalization...\"\n    sudo halt\nelse\n    dialog --stdout --title \"Reboot required\" --backtitle \"FreeDi installation\" \\\n           --yes-label \"Reboot now\" --no-label \"Reboot later\" \\\n           --yesno \"Installation complete!\\n\\nA reboot is required for all changes to take effect.\\n\\nReboot now?\" 9 60\n    if [ $? -eq 0 ]; then\n        echo \"Rebooting system...\"\n        sudo reboot\n    else\n        clear\n        echo \"==================================================================================\"\n        printf \"%b\\n\" \"${GRN}Setup complete!${RST}\"\n        printf \"%b\\n\" \"${YLW}Please reboot your system manually for the changes to take effect.${RST}\"\n        echo \"==================================================================================\"\n    fi\nfi\n"
  },
  {
    "path": "klipper_module/freedi.py",
    "content": "# FreeDi Module for Klipper\n# This module registers a custom [FreeDi] section in the printer.cfg file\n# and loads the associated parameters.\n\nimport logging\n\nclass FreeDi:\n    def __init__(self, config):\n        # Read parameters from the configuration file\n        self.printer_model = config.get('printer_model', 'unknown')\n        self.baudrate = config.get('baudrate', 115200)\n        self.serial_port = config.get('serial_port', '/dev/ttyS1')\n        self.url = config.get('url', '127.0.0.1')\n        self.moonraker_port = config.get('moonraker_port', '7125')\n        self.webUI_port = config.get('webUI_port', '80')\n        self.api_key = config.get('api_key', 'XXXXXX')\n        self.klippy_socket = config.get('klippy_socket', '/home/mks/printer_data/comms/klippy.sock')\n        self.channel = config.get('channel', 'stable')\n        self.wizard = config.get('wizard', 'True')\n        self.preset1_name = config.get('preset1_name', 'PLA')\n        self.preset2_name = config.get('preset2_name', 'ASA')\n        self.preset3_name = config.get('preset3_name', 'PETG')\n        self.preset4_name = config.get('preset4_name', 'TPU')\n        self.default_temp_extruder = config.get('default_temp_extruder', '220')\n        self.default_temp_bed = config.get('default_temp_bed', '60')\n        self.default_temp_chamber = config.get('default_temp_chamber', '45')\n        self.default_speed_partfan = config.get('default_speed_partfan', '100')\n        self.default_speed_sidefan = config.get('default_speed_sidefan', '100')\n        self.default_speed_filterfan = config.get('default_speed_filterfan', '100')\n        self.sync_case_light_with_display = config.get('sync_case_light_with_display', 'True')\n        self.default_brightness = config.get('default_brightness', '100')\n        self.lcd_dim_time = config.get('lcd_dim_time', '10')    \n        self.lcd_dim_brightness = config.get('lcd_dim_brightness', '15')\n        self.lcd_sleep_time = config.get('lcd_sleep_time', '20')\n        self.install_klipper_module = config.get('install_klipper_module', 'False')\n        self.flash_MCU = config.get('flash_MCU', 'False')\n        self.flash_toolhead = config.get('flash_toolhead', 'False')\n        self.flash_display = config.get('flash_display', 'False')\n\n        # Default extrusion lengths for the Extruder menu (in millimeters)\n        self.extruder_length_1 = config.get('extruder_length_1', '10.0')\n        self.extruder_length_2 = config.get('extruder_length_2', '20.0')\n        self.extruder_length_3 = config.get('extruder_length_3', '50.0')\n        \n        # Default move and extrude step lengths for Move and Move&Extrude menus (in millimeters)\n        self.move_extrude_length_1 = config.get('move_extrude_length_1', '0.1')\n        self.move_extrude_length_2 = config.get('move_extrude_length_2', '1.0')\n        self.move_extrude_length_3 = config.get('move_extrude_length_3', '10.0')\n        self.move_extrude_length_4 = config.get('move_extrude_length_4', '50.0')\n        self.move_extrude_length_5 = config.get('move_extrude_length_5', '100.0')\n        \n        # Enable visual feedback on touch events\n        self.touch_acoustic_feedback = config.get('touch_acoustic_feedback', 'True')\n\n\n        # Log the loaded parameters (for debugging purposes)\n        self.log_info(f\"FreeDi loaded: printer_model={self.printer_model}, \"\n                      f\"baudrate={self.baudrate}, serial_port={self.serial_port}\")\n\n    def log_info(self, message):\n        # Use Klipper's integrated logging system to output messages\n        logging.info(message)\n\n\n# Klipper initialization function\n# This function is called when the [FreeDi] section is found in the printer.cfg\ndef load_config(config):\n    return FreeDi(config)\n\n"
  },
  {
    "path": "klipper_module/qidi_auto_z_offset/LICENSE",
    "content": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <https://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<https://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<https://www.gnu.org/licenses/why-not-lgpl.html>.\n"
  },
  {
    "path": "klipper_module/qidi_auto_z_offset/README.md",
    "content": "# Auto Z-Offset Calibration for the QIDI Q1 Pro\n\nThis is a plugin for Klipper that makes use of the QIDI Q1 Pro's bed sensors to automatically set the toolheads Z-Offset.\n\n> [!IMPORTANT]\n> This adapts changes from the QIDI Q1 stock klipper to work with mainline klipper. This is not for use with the stock Q1 firmware.\n\n### Install\n\n```\ncd ~\ngit clone https://github.com/frap129/qidi_auto_z_offset\nln -s ~/qidi_auto_z_offset/auto_z_offset.py ~/klipper/klippy/extras/auto_z_offset.py\n```\n\n### Command Reference\n\n**AUTO_Z_PROBE**: Probe Z-height at current XY position using the bed sensors\n\n**AUTO_Z_HOME_Z**: Home Z using the bed sensors as an endstop\n\n**AUTO_Z_MEASURE_OFFSET** Z-Offset measured by the inductive probe after AUTO_Z_HOME_Z\n\n**AUTO_Z_CALIBRATE**: Set the Z-Offset by averaging multiple runs of AUTO_Z_MEASURE_OFFSET\n\n**AUTO_Z_LOAD_OFFSET**: Apply the calibrated_z_offset saved in the config file\n\n**AUTO_Z_SAVE_GCODE_OFFSET**: Save the current gcode offset for z as the new calibrated_z_offset\n\n### Basic Usage\n\n`auto_z_offset` helps calibrate the z_offset of the inductive probe on the Q1 using the piezo electric sensors under the bed.\nIt allows for finetuning, saving, and loading the calibrated offset.\n\n⚠️ **NOTE** ⚠️\n`AUTO_Z_CALIBRATE` should not be used in a `PRINT_START` macro! On rare occasion, the bed sensors can fail to trigger or\ntrigger too late. If this happens when a print is started, you can end up grinding the nozzle into the bed. Instead, you\nshould calibrate it prior to your first print, and load the offset in `PRINT_START`.\n\nFirst, calibrate the z_offset:\n\n1. Heat the extruder to a reasonable temperature that wont ooze (160+)\n2. Home all axes\n3. Run `AUTO_Z_CALIBRATE`\n4. Move Z to 0\n5. Verify that you can slide a piece of paper under the nozzle\n6. Run `SAVE_CONFIG` to save the measured offset.\n   - Note, this does not modify the `z_offset` of the inductive probe in your config. This value is only used by\n     `auto_z_offset`\n\nAdd `AUTO_Z_LOAD_OFFSET` to your `PRINT_START` macro to load the value every time you start a print. If you make adujstments to\nthe offset by micro-stepping durring a print, you can save that with `AUTO_Z_SAVE_GCODE_OFFSET` and `SAVE_CONFIG`\n\n### Config Reference\n\n```\n[auto_z_offset]\npin:\n#   Pin connected to the Auto Z Offset output pin. This parameter is required.\nz_offset:\n#   The offset between measured 0 and when the bed sensors trigger.\n#   default is -0.1\nprepare_gcode:\n#   gcode script to run before probing with auto_z_offset. This is required, and an\n#   example script is provided below.\n#probe_accel:\n#   If set, limits the acceleration of the probing moves (in mm/sec^2).\n#   A sudden large acceleration at the beginning of the probing move may\n#   cause spurious probe triggering, especially if the hotend is heavy.\n#   To prevent that, it may be necessary to reduce the acceleration of\n#   the probing moves via this parameter.\n#probe_hop:\n#   The amount to hop between probing with bed sensors and probing with probe.\n#   default is 5.0, min is 4.0 to avoid triggering the probe early\n#offset_samples:\n#   The number of times to probe with bed sensors and inductive probe when running\n#   AUTO_Z_CALIBRATE. Note this is not the same as `samples`.\n#   default is 3\n#speed:\n#samples:\n#sample_retract_dist:\n#samples_result:\n#samples_tolerance:\n#samples_tolerance_retries:\n#activate_gcode:\n#deactivate_gcode:\n#deactivate_on_each_sample:\n#   See the \"probe\" section for more information on the parameters above.\n```\n\n### Example Configuration from OpenQ1\n\nThis example config also includes the control pin for the bed sensors and the config for the inductive probe. Use them as shown for the best compatiblity.\n\n```\n[output_pin bed_sensor]\npin: !U_1:PA14\nvalue:0\n\n[probe]\npin: !gpio21\nx_offset: 17.6\ny_offset: 4.4\nz_offset: 0.0\nspeed:10\nsamples: 3\nsamples_result: average\nsample_retract_dist: 4.0\nsamples_tolerance: 0.05\nsamples_tolerance_retries: 5\n\n[auto_z_offset]\npin: U_1:PC1\nz_offset: -0.1\nspeed: 10\nprobe_accel: 50\nsamples: 5\nsamples_result: average\nsamples_tolerance: 0.05\nsamples_tolerance_retries: 5\nprepare_gcode:\n    SET_PIN PIN=bed_sensor VALUE=0\n    G91\n    {% set i = 4 %}\n    {% for iteration in range(i|int) %}\n        G1 Z1 F900\n        G1 Z-1 F900\n    {% endfor %}\n    G90\n    SET_PIN PIN=bed_sensor VALUE=1\n```\n"
  },
  {
    "path": "klipper_module/qidi_auto_z_offset/auto_z_offset.py",
    "content": "# QIDI Auto Z-Offset support\n#\n# Copyright (C) 2024  Joe Maples <joe@maples.dev>\n# Copyright (C) 2021  Dmitry Butyugin <dmbutyugin@google.com>\n# Copyright (C) 2017-2021  Kevin O'Connor <kevin@koconnor.net>\n#\n# This file may be distributed under the terms of the GNU GPLv3 license.\n\nfrom operator import neg\n\nfrom . import probe\n\n\nclass AutoZOffsetCommandHelper(probe.ProbeCommandHelper):\n    def __init__(self, config, mcu_probe, query_endstop=None):\n        self.printer = config.get_printer()\n        self.name = config.get_name()\n        gcode = self.printer.lookup_object('gcode')\n        self.mcu_probe = mcu_probe\n        self.query_endstop = query_endstop\n        self.z_offset = config.getfloat(\"z_offset\", -0.1)\n        self.probe_hop = config.getfloat(\"probe_hop\", 5.0, minval=4.0)\n        self.offset_samples = config.getint(\"offset_samples\", 3, minval=1)\n        self.calibrated_z_offset = config.getfloat(\"calibrated_z_offset\", 0.0)\n        self.last_state = False\n        self.last_z_result = 0.0\n        self.last_probe_position = gcode.Coord((0., 0., 0.))\n\n        # Register commands\n        self.gcode = self.printer.lookup_object(\"gcode\")\n        self.gcode.register_command(\n            \"AUTO_Z_PROBE\",\n            self.cmd_AUTO_Z_PROBE,\n            desc=self.cmd_AUTO_Z_PROBE_help,\n        )\n        self.gcode.register_command(\n            \"AUTO_Z_HOME_Z\",\n            self.cmd_AUTO_Z_HOME_Z,\n            desc=self.cmd_AUTO_Z_HOME_Z_help,\n        )\n        self.gcode.register_command(\n            \"AUTO_Z_MEASURE_OFFSET\",\n            self.cmd_AUTO_Z_MEASURE_OFFSET,\n            desc=self.cmd_AUTO_Z_MEASURE_OFFSET_help,\n        )\n        self.gcode.register_command(\n            \"AUTO_Z_CALIBRATE\",\n            self.cmd_AUTO_Z_CALIBRATE,\n            desc=self.cmd_AUTO_Z_CALIBRATE_help,\n        )\n        self.gcode.register_command(\n            \"AUTO_Z_LOAD_OFFSET\",\n            self.cmd_AUTO_Z_LOAD_OFFSET,\n            desc=self.cmd_AUTO_Z_LOAD_OFFSET_help,\n        )\n        self.gcode.register_command(\n            \"AUTO_Z_SAVE_GCODE_OFFSET\",\n            self.cmd_AUTO_Z_SAVE_GCODE_OFFSET,\n            desc=self.cmd_AUTO_Z_SAVE_GCODE_OFFSET_help,\n        )\n\n    def _move_to_center(self, gcmd):\n        toolhead = self.printer.lookup_object(\"toolhead\")\n        params = self.mcu_probe.get_probe_params(gcmd)\n        curpos = toolhead.get_position()\n        curpos[0] = 120\n        curpos[1] = 120\n        if curpos[2] < 1.0:\n            curpos[2] = self.probe_hop\n        self._move(curpos, params[\"lift_speed\"])\n\n    def lift_probe(self, gcmd):\n        toolhead = self.printer.lookup_object(\"toolhead\")\n        params = self.mcu_probe.get_probe_params(gcmd)\n        curpos = toolhead.get_position()\n        curpos[2] += self.probe_hop\n        self._move(curpos, params[\"lift_speed\"])\n\n    cmd_AUTO_Z_PROBE_help = (\n        \"Probe Z-height at current XY position using the bed sensors\"\n    )\n\n    def cmd_AUTO_Z_PROBE(self, gcmd):\n        self._move_to_center(gcmd)\n        pos = probe.run_single_probe(self.mcu_probe, gcmd)\n        self.last_z_result = neg(pos[2]) + self.z_offset\n        gcmd.respond_info(\"Result is z=%.6f\" % self.last_z_result)\n\n    cmd_AUTO_Z_HOME_Z_help = \"Home Z using the bed sensors as an endstop\"\n\n    def cmd_AUTO_Z_HOME_Z(self, gcmd):\n        self._move_to_center(gcmd)\n        self.lift_probe(gcmd)\n        self.cmd_AUTO_Z_PROBE(gcmd)\n        toolhead = self.printer.lookup_object(\"toolhead\")\n        curpos = toolhead.get_position()\n        toolhead.set_position(\n            [curpos[0], curpos[1], self.z_offset, curpos[3]], homing_axes=(0, 1, 2)\n        )\n        self.lift_probe(gcmd)\n\n    cmd_AUTO_Z_MEASURE_OFFSET_help = (\n        \"Z-Offset measured by the inductive probe after AUTO_Z_HOME_Z\"\n    )\n\n    def cmd_AUTO_Z_MEASURE_OFFSET(self, gcmd):\n        # Use bed sensors to correct z origin\n        self.cmd_AUTO_Z_HOME_Z(gcmd)\n        gcmd.respond_info(\n            \"%s: bed sensor measured offset: z=%.6f\" % (self.name, self.last_z_result)\n        )\n\n        # Account for x/y offset of main probe\n        main_probe = self.printer.lookup_object(\"probe\")\n        toolhead = self.printer.lookup_object(\"toolhead\")\n        params = self.mcu_probe.get_probe_params(gcmd)\n        curpos = toolhead.get_position()\n        curpos[0] = 120 - main_probe.probe_offsets.x_offset\n        curpos[1] = 120 - main_probe.probe_offsets.y_offset\n        self._move(curpos, params[\"lift_speed\"])\n\n        # Use main probe to measure its own offset\n        pos = probe.run_single_probe(main_probe, gcmd)\n        gcmd.respond_info(\"%s: probe measured offset: z=%.6f\" % (self.name, pos[2]))\n        self.lift_probe(gcmd)\n        return pos[2]\n\n    cmd_AUTO_Z_CALIBRATE_help = (\n        \"Set the Z-Offset by averaging multiple runs of AUTO_Z_MEASURE_OFFSET\"\n    )\n\n    def cmd_AUTO_Z_CALIBRATE(self, gcmd):\n        # Get average measured offset over self.offset_samples number of tests\n        offset_total = 0.0\n        for _ in range(self.offset_samples):\n            offset_total += self.cmd_AUTO_Z_MEASURE_OFFSET(gcmd)\n        self.calibrated_z_offset = neg(offset_total / self.offset_samples)\n\n        # Apply calibrated offset and save to config\n        self.gcode.run_script_from_command(\n            \"SET_GCODE_OFFSET Z=%f MOVE=0\" % self.calibrated_z_offset\n        )\n        configfile = self.printer.lookup_object(\"configfile\")\n        configfile.set(\n            self.name, \"calibrated_z_offset\", \"%.6f\" % self.calibrated_z_offset\n        )\n        gcmd.respond_info(\n            \"%s: calibrated_z_offset: %.6f\\n\"\n            \"The SAVE_CONFIG command will update the printer config file\\n\"\n            \"with the above and restart the printer.\"\n            % (self.name, self.calibrated_z_offset)\n        )\n\n    cmd_AUTO_Z_LOAD_OFFSET_help = (\n        \"Apply the calibrated_z_offset saved in the config file\"\n    )\n\n    def cmd_AUTO_Z_LOAD_OFFSET(self, gcmd):\n        gcmd.respond_info(\n            \"%s: calibrated_z_offset: %.6f\" % (self.name, self.calibrated_z_offset)\n        )\n        self.gcode.run_script_from_command(\n            \"SET_GCODE_OFFSET Z=%f MOVE=0\" % self.calibrated_z_offset\n        )\n\n    cmd_AUTO_Z_SAVE_GCODE_OFFSET_help = (\n        \"Save the current gcode offset for z as the new calibrated_z_offset\"\n    )\n\n    def cmd_AUTO_Z_SAVE_GCODE_OFFSET(self, gcmd):\n        gcode_move = self.printer.lookup_object(\"gcode_move\")\n        self.calibrated_z_offset = gcode_move.homing_position[2]\n        configfile = self.printer.lookup_object(\"configfile\")\n        configfile.set(\n            self.name, \"calibrated_z_offset\", \"%.6f\" % self.calibrated_z_offset\n        )\n        gcmd.respond_info(\n            \"%s: calibrated_z_offset: %.6f\\n\"\n            \"The SAVE_CONFIG command will update the printer config file\\n\"\n            \"with the above and restart the printer.\"\n            % (self.name, self.calibrated_z_offset)\n        )\n\n\n# Homing via auto_z_offset:z_virtual_endstop\nclass HomingViaAutoZHelper(probe.HomingViaProbeHelper):\n    def __init__(self, config, mcu_probe, param_helper):\n        self.printer = config.get_printer()\n        self.mcu_probe = mcu_probe\n        self.param_helper = param_helper\n        self.multi_probe_pending = False\n        self.z_min_position = probe.lookup_minimum_z(config)\n        self.results = []\n        probe.LookupZSteppers(config, self.mcu_probe.add_stepper)\n        # Register z_virtual_endstop pin\n        self.printer.lookup_object(\"pins\").register_chip(\"auto_z_offset\", self)\n        self.printer.register_event_handler(\n            \"homing:homing_move_begin\", self._handle_homing_move_begin\n        )\n        self.printer.register_event_handler(\n            \"homing:homing_move_end\", self._handle_homing_move_end\n        )\n        self.printer.register_event_handler(\n            \"homing:home_rails_begin\", self._handle_home_rails_begin\n        )\n        self.printer.register_event_handler(\n            \"homing:home_rails_end\", self._handle_home_rails_end\n        )\n        self.printer.register_event_handler(\n            \"gcode:command_error\", self._handle_command_error\n        )\n\n\nclass AutoZOffsetEndstopWrapper:\n    def __init__(self, config):\n        self.printer = config.get_printer()\n        self.gcode = self.printer.lookup_object(\"gcode\")\n        self.probe_accel = config.getfloat(\"probe_accel\", 0.0, minval=0.0)\n        self.probe_wrapper = probe.ProbeEndstopWrapper(config)\n        # Setup prepare_gcode\n        gcode_macro = self.printer.load_object(config, \"gcode_macro\")\n        self.prepare_gcode = gcode_macro.load_template(config, \"prepare_gcode\")\n        # Wrappers\n        self.get_mcu = self.probe_wrapper.get_mcu\n        self.add_stepper = self.probe_wrapper.add_stepper\n        self.get_steppers = self.probe_wrapper.get_steppers\n        self.home_start = self.probe_wrapper.home_start\n        self.home_wait = self.probe_wrapper.home_wait\n        self.query_endstop = self.probe_wrapper.query_endstop\n        self.multi_probe_end = self.probe_wrapper.multi_probe_end\n\n    def multi_probe_begin(self):\n        self.gcode.run_script_from_command(self.prepare_gcode.render())\n        self.probe_wrapper.multi_probe_begin()\n\n    def probe_prepare(self, hmove):\n        toolhead = self.printer.lookup_object(\"toolhead\")\n        self.probe_wrapper.probe_prepare(hmove)\n        if self.probe_accel > 0.0:\n            systime = self.printer.get_reactor().monotonic()\n            toolhead_info = toolhead.get_status(systime)\n            self.old_max_accel = toolhead_info[\"max_accel\"]\n            self.gcode.run_script_from_command(\"M204 S%.3f\" % self.probe_accel)\n\n    def probe_finish(self, hmove):\n        if self.probe_accel > 0.0:\n            self.gcode.run_script_from_command(\"M204 S%.3f\" % self.old_max_accel)\n        self.probe_wrapper.probe_finish(hmove)\n\n\nclass AutoZOffsetParameterHelper(probe.ProbeParameterHelper):\n    def __init__(self, config):\n        gcode = config.get_printer().lookup_object(\"gcode\")\n        self.dummy_gcode_cmd = gcode.create_gcode_command(\"\", \"\", {})\n        # Configurable probing speeds\n        self.speed = config.getfloat(\"speed\", 5.0, above=0.0)\n        self.lift_speed = config.getfloat(\"lift_speed\", self.speed, above=0.0)\n        # Multi-sample support (for improved accuracy)\n        self.sample_count = config.getint(\"samples\", 5, minval=3)\n        self.sample_retract_dist = config.getfloat(\n            \"sample_retract_dist\", 2.0, above=0.0\n        )\n        atypes = {\"median\": \"median\", \"average\": \"average\"}\n        self.samples_result = config.getchoice(\"samples_result\", atypes, \"average\")\n        self.samples_tolerance = config.getfloat(\"samples_tolerance\", 0.100, minval=0.0)\n        self.samples_retries = config.getint(\"samples_tolerance_retries\", 0, minval=0)\n\n\nclass AutoZOffsetSessionHelper(probe.ProbeSessionHelper):\n    def __init__(self, config, param_helper, start_session_cb):\n        self.printer = config.get_printer()\n        self.param_helper = param_helper\n        self.start_session_cb = start_session_cb\n        # Session state\n        self.hw_probe_session = None\n        self.results = []\n        # Register event handlers\n        self.printer.register_event_handler(\n            \"gcode:command_error\", self._handle_command_error\n        )\n\n    def run_probe(self, gcmd):\n        if self.hw_probe_session is None:\n            self._probe_state_error()\n        params = self.param_helper.get_probe_params(gcmd)\n        toolhead = self.printer.lookup_object(\"toolhead\")\n        probexy = toolhead.get_position()[:2]\n        retries = 0\n        positions = []\n        sample_count = params[\"samples\"]\n        while len(positions) < sample_count:\n            # Probe position\n            pos = self._probe(gcmd)\n            positions.append(pos)\n            # Check samples tolerance\n            z_positions = [p[2] for p in positions]\n            if max(z_positions) - min(z_positions) > params[\"samples_tolerance\"]:\n                if retries >= params[\"samples_tolerance_retries\"]:\n                    raise gcmd.error(\"Probe samples exceed samples_tolerance\")\n                gcmd.respond_info(\"Probe samples exceed tolerance. Retrying...\")\n                retries += 1\n                positions = []\n            # Retract\n            if len(positions) < sample_count:\n                toolhead.manual_move(\n                    probexy + [pos[2] + params[\"sample_retract_dist\"]],\n                    params[\"lift_speed\"],\n                )\n        # Discard highest and lowest values\n        positions.remove(max(positions))\n        positions.remove(min(positions))\n        # Calculate result\n        epos = probe.calc_probe_z_average(positions, params[\"samples_result\"])\n        self.results.append(epos)\n\n\nclass AutoZOffsetOffsetsHelper:\n    def __init__(self, config):\n        self.x_offset = 0.0\n        self.y_offset = 0.0\n        self.z_offset = config.getfloat(\"z_offset\", 0.0)\n\n    def get_offsets(self):\n        return 0.0, 0.0, self.z_offset\n\n\nclass AutoZOffsetProbe:\n    def __init__(self, config):\n        self.printer = config.get_printer()\n        self.mcu_probe = AutoZOffsetEndstopWrapper(config)\n        self.cmd_helper = AutoZOffsetCommandHelper(\n            config, self, self.mcu_probe.query_endstop\n        )\n        self.probe_offsets = AutoZOffsetOffsetsHelper(config)\n        self.param_helper = AutoZOffsetParameterHelper(config)\n        self.homing_helper = HomingViaAutoZHelper(\n            config, self.mcu_probe, self.param_helper\n        )\n        self.probe_session = AutoZOffsetSessionHelper(\n            config, self.param_helper, self.homing_helper.start_probe_session\n        )\n\n    def get_probe_params(self, gcmd=None):\n        return self.param_helper.get_probe_params(gcmd)\n\n    def get_offsets(self):\n        return self.probe_offsets.get_offsets()\n\n    def get_status(self, eventtime):\n        return self.cmd_helper.get_status(eventtime)\n\n    def start_probe_session(self, gcmd):\n        return self.probe_session.start_probe_session(gcmd)\n\n\ndef load_config(config):\n    auto_z_offset = AutoZOffsetProbe(config)\n    config.get_printer().add_object(\"auto_z_offset\", auto_z_offset)\n    return auto_z_offset\n"
  },
  {
    "path": "presliced_z-offset_calibration_files/Plus4/z-offset_calibration_Plus4_PLA_4m4s.gcode",
    "content": "; HEADER_BLOCK_START\n; generated by OrcaSlicer 2.2.0 on 2025-06-04 at 11:43:40\n; total layer number: 1\n; filament_density: 1.24\n; filament_diameter: 1.75\n; max_z_height: 0.20\n; HEADER_BLOCK_END\n\n; THUMBNAIL_BLOCK_START\n\n;\n; thumbnail begin 240x240 1868\n; iVBORw0KGgoAAAANSUhEUgAAAPAAAADwCAYAAAA+VemSAAAFQElEQVR4Ae3dPVIkRxCA0T4Qh5CFww\n; k4Ai4O7jp4uNgYnIATcLRVjBTEwuzM9ExP/WRWvRfxOZKljajIVHUtLAsAAAAAAAAAAAAAAAAAAAAA\n; AAAAAAAAAAAAAAAAAAAAAAAAAABwzP39/a+Pj4/fu25ubv5ZgBy+H96vdv9sAeLaTdrn5+fP/cP71e\n; 7fmcYQ0KGpeyzTGAK55PB+n8YL0M+Wg7uflRo6KHF4rdTQ2G5iljq4LrigoZJT1zSGhlocXtMYCmt5\n; cE1jKKjn4f0+jRfgfBEOrpUaNoh2eK3UcIa1d8ymMQQVeeqaxnBCxsP7fRovMKPMB3c/KzVTGenwfm\n; WlZnhZLqq25oKLYY04dU1jpjDT4TWNGcaMB3c/h5iUHN4/WalJw8E9nJWa8Bze9UxjQhr581DpTGPC\n; MHW3ZxrTlcN7fd5T05yDWz4rNU04vPWyUlPN6O+Yo+SCi+JM3faZxhTh8PbLBRebObhxslJzEYc3Xl\n; ZqVtX6xWEqkwsujjJ182Qa84PPQ/kyjTF1B8g0npTDO04+N03EwR33EFupB+fwjp+VekDeMc+VaTwQ\n; U3feTOPkHF654ErIwdV+VuokHF4dy0odmIsqnZMLroBMXV2aaRyEw6utmcYdObgqlUPcmMOr0vnc1I\n; CDq5pZqStyeNUqF1yF+Tyk1pnGBZi66p1pvJHDqyi54LqAg6uoWalXOLyKnpX6AO+YlSkXXN+Yusra\n; 9NPY4VX2ppzGDq5Ga5pD7PBq1IZeqf3iMM3QkCu1qavZGmYa+zykWUs9jU1d6f/STWOHV/pZivfUDq\n; 50urArtcMrnVeoldo7ZunyQlxwmbrSdXWbxg6vVKamF1wOrlSn6iu1wyvVrcpK7R2z1K6iF1ymrtSn\n; q6exwyv1bdM0dnClWF08jd/f31P9B0qj9vLy8nvZ4unp6TPTf6g0Wlf/f/Bu/zaNpba9vb2V/S5sGk\n; tt2rwyr7m7u3O5JVWsydtoK7VUtmpT9xgrtVSmbn8jyQWXtL3dRdUSgWksXdbj42Osn5G1u+AyjaX1\n; Qv+UytfX11R/mFKrml9UbfXw8PCZ6Q9Wql26nw3tgktKNHWPccGlWQt3UbWVCy7N1O7z0O3t7a9lNK\n; axRi/9yrzGe2qN2tC/4HuflVqjNPzUPcZKrexNNXUP8blJGSv+F+6zM42VpWE+D5Xmc5OiN/3KfA6H\n; WNGa9qJqKyu1omTqbuSCSz0zdQsxjdU6F1WFueBSq4Z8xxyFaaxaWZkb8QMDVDoXVR1YqXVtpm5nVm\n; ptzdQNwucmXZJ3zEGZxlrL56Hg/MAAHcvKnIiVWl+5qErKSi1TNzkXXHMW5heHUYZpPE8uqgblPfX4\n; WZknYBqPl4uqyXhPPU6m7qRccOXO1OU/Vup8uajiB9M4R94xc5JpHDcrM2fxnjpeLqq4mJW6f6YuV7\n; FS98vUpQgXXG1zUUUVpnH9fB6iKu+p62VlphmHuFwuqujCe+rrM3XpygXXtkxdQnHBdX4uqgjJBdd6\n; fnEY4ZnGf2dlJhXvqf/kooq0Zl6pTV2GMONKbeoylFk+N3nHzNBGnsY+DzGFES+4rMxMZ4SV2kUVU8\n; u8Upu6sOS74PKLw+CADNPYRRWcEPk9tXfMcKZI09hFFWwQ4QcGuKiCK/VYqU1dKKjlSm3qQgW1Pzd5\n; xwwN1JjGVmZoqOR7aiszdHLNSm3qQgBbVmpTFwI594LLO2YI7NQ09o4ZEjj0ntrKDMnsDrGLKgAAAA\n; AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFj1L3Bw5na34ScOAAAAAElFTkSuQmCC\n; thumbnail end\n; THUMBNAIL_BLOCK_END\n\n; THUMBNAIL_BLOCK_START\n\n;\n; thumbnail begin 96x96 756\n; iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAB/klEQVR4Ae2czW2DQBCFtyAXkTZogw\n; vXXLjRAwcqoAKX5miVWFkhzM/+zux+n/SkKDceM/PWY7AxAAAAAAAAAAAAAABwxOPx+LIykJ+u677X\n; dX1Z2b8N5MM1/61xHJ90Q2L2jN+Km5CIK+a73WAgDneMZyRFxtd8VwS0J7aCQ82nGzyIUfV0gycpzS\n; egD8hh/FaMpD9KmM9IMr97nJhBGzKSmuuGklXffDdINN/tBlMrko3fqrqRpMn8qkaSrSRNpm+lOqA1\n; Vn013SDheNlkN9RU9eq6oQXz3W4wUmjJ+K2Kj6SWzX+ryEiSsseRoqwBTdV/VvJuwPxzJQlojL+vaC\n; MJ8/0VNJK073GkyCugqfr4utwNmJ9Oh92A8fm0exPsP5dlUXUhWnU4joZheGq6mGqM33aDpgurynz3\n; JrDvCdc0TS8TAuHsr2i7IQL6nuZ5TvNdAQF9ruQbUQK6oPkuBPS/+r4v8x0xAS3gKYlWAzpZ0PrSUk\n; CLfTaohW5Q8ZhijQFdLGh94eFcAWjfJwXvcaTACxoC0BTQVb81Kfm42sybkhL3SU2+tC0hoNUdL2PD\n; TxUIIHdAi9vjSCFHQFP1J6QMaMy/QcyAbj5ofeFH+wTgu0+yQWsgHncCmqpPxJXjKuZnYK8bMD4z7n\n; EV8wvBp1kAAAAAAAAAAAAAgEv8AEKg0vvlB1mPAAAAAElFTkSuQmCC\n; thumbnail end\n; THUMBNAIL_BLOCK_END\n\n; external perimeters extrusion width = 0.42mm\n; perimeters extrusion width = 0.45mm\n; infill extrusion width = 0.45mm\n; solid infill extrusion width = 0.42mm\n; top infill extrusion width = 0.42mm\n; first layer extrusion width = 0.50mm\n\n; EXECUTABLE_BLOCK_START\nEXCLUDE_OBJECT_DEFINE NAME=Cube_id_0_copy_0 CENTER=152.5,152.5 POLYGON=[[117.5,117.5],[187.5,117.5],[187.5,187.5],[117.5,187.5],[117.5,117.5]]\nM73 P0 R4\nM106 S0\nM106 P2 S0\n;TYPE:Custom\nPRINT_START BED=60 HOTEND=210 CHAMBER=0\nSET_PRINT_STATS_INFO TOTAL_LAYER=1\nM83\nM140 S60\nM104 S210\nM141 S0\nG4 P3000\nG0 X105.929 Y105.929 Z5 F6000\nG0 Z0.2 F600\nG1 E3 F1800\nG1 X190.929 E3.4 F3000\nG1 Y107.929 E0.08 F3000\nM73 P1 R4\nG1 X105.929 E3.4 F3000\nM73 P1 R4\nG1 Y190.929 E3.32 F3000\nM73 P2 R3\nG1 X107.929 E0.08 F3000\nM73 P2 R3\nG1 Y108.929 E3.28 F3000\nG1 X108.929 Z0\nM73 P3 R3\nG1 X111.929\nM73 P3 R3\nG1 Z1 F600\nSET_PRINT_STATS_INFO CURRENT_LAYER=1\nM106 P3 S255\nG90\nG21\nM83 ; use relative distances for extrusion\nSET_PRESSURE_ADVANCE ADVANCE=0.034; Override pressure advance value\nM106 S0\nM106 P2 S0\n;LAYER_CHANGE\n;Z:0.2\n;HEIGHT:0.2\n;BEFORE_LAYER_CHANGE\n;0.2\nG92 E0\n\nG1 E-.8 F1800\n;TIMELAPSE_TAKE_FRAME\n\nG92 E0\nSET_PRINT_STATS_INFO CURRENT_LAYER=1\n;_SET_FAN_SPEED_CHANGING_LAYER\nSET_VELOCITY_LIMIT ACCEL=500 ACCEL_TO_DECEL=250\nG1 X112.846 Y113.238 F15000\nG1 Z.6\nG1 Z.2\nG1 E.8 F1800\n;TYPE:Skirt\n;WIDTH:0.5\nG1 F3000\nG1 X114.438 Y111.946 E.07635\nG1 X117.5 Y111.158 E.11778\nG1 X187.5 Y111.158 E2.60723\nG1 X189.708 Y111.555 E.08357\nM73 P4 R3\nG1 X191.64 Y112.695 E.08357\nM73 P4 R3\nG1 X193.054 Y114.438 E.08357\nG1 X193.842 Y117.5 E.11778\nG1 X193.842 Y187.5 E2.60723\nG1 X193.445 Y189.708 E.08357\nM73 P5 R3\nG1 X192.305 Y191.64 E.08357\nM73 P5 R3\nG1 X190.562 Y193.054 E.08357\nG1 X187.5 Y193.842 E.11778\nG1 X117.5 Y193.842 E2.60723\nG1 X115.292 Y193.445 E.08357\nG1 X113.36 Y192.305 E.08357\nG1 X111.946 Y190.562 E.08357\nG1 X111.158 Y187.5 E.11778\nG1 X111.158 Y117.5 E2.60723\nG1 X111.555 Y115.292 E.08357\nM73 P6 R3\nG1 X112.695 Y113.36 E.08357\nM73 P6 R3\nG1 X112.815 Y113.263 E.00572\nG1 X113.148 Y113.539 F15000\nG1 F3000\nG1 X114.871 Y112.235 E.08047\nG1 X117.5 Y111.615 E.10062\nG1 X187.5 Y111.615 E2.60723\nG1 X189.624 Y112.011 E.08047\nM73 P7 R3\nG1 X191.461 Y113.148 E.08047\nM73 P7 R3\nG1 X192.765 Y114.871 E.08047\nG1 X193.385 Y117.5 E.10062\nG1 X193.385 Y187.5 E2.60723\nG1 X192.989 Y189.624 E.08047\nG1 X191.852 Y191.461 E.08047\nG1 X190.129 Y192.765 E.08047\nG1 X187.5 Y193.385 E.10062\nM73 P8 R3\nG1 X117.5 Y193.385 E2.60723\nM73 P8 R3\nG1 X115.376 Y192.989 E.08047\nG1 X113.539 Y191.852 E.08047\nG1 X112.235 Y190.129 E.08047\nG1 X111.615 Y187.5 E.10062\nG1 X111.615 Y117.5 E2.60723\nG1 X112.011 Y115.376 E.08047\nM73 P9 R3\nG1 X113.127 Y113.573 E.07898\nM73 P9 R3\nG1 X113.529 Y113.834 F15000\nG1 F3000\nG1 X113.599 Y113.725 E.00483\nG1 X115.3 Y112.538 E.07726\nG1 X117.5 Y112.072 E.08376\nG1 X187.5 Y112.072 E2.60723\nG1 X189.536 Y112.468 E.07726\nG1 X191.275 Y113.599 E.07726\nM73 P10 R3\nG1 X192.462 Y115.3 E.07726\nM73 P10 R3\nG1 X192.928 Y117.5 E.08376\nG1 X192.928 Y187.5 E2.60723\nG1 X192.532 Y189.536 E.07726\nG1 X191.401 Y191.275 E.07726\nG1 X189.7 Y192.462 E.07726\nG1 X187.5 Y192.928 E.08376\nG1 X117.5 Y192.928 E2.60723\nG1 X115.464 Y192.532 E.07726\nM73 P11 R3\nG1 X113.725 Y191.401 E.07726\nM73 P11 R3\nG1 X112.538 Y189.7 E.07726\nG1 X112.072 Y187.5 E.08376\nG1 X112.072 Y117.5 E2.60723\nG1 X112.468 Y115.464 E.07726\nG1 X113.507 Y113.867 E.07094\nM73 P12 R3\nG1 X113.9 Y114.138 F15000\nM73 P12 R3\nG1 F3000\nG1 X114.05 Y113.921 E.00981\nG1 X115.724 Y112.857 E.0739\nG1 X117.5 Y112.529 E.06726\nG1 X187.5 Y112.529 E2.60723\nG1 X189.444 Y112.925 E.0739\nG1 X191.079 Y114.05 E.0739\nG1 X192.143 Y115.724 E.0739\nG1 X192.471 Y117.5 E.06726\nG1 X192.471 Y187.5 E2.60723\nG1 X192.075 Y189.444 E.0739\nM73 P13 R3\nG1 X190.95 Y191.079 E.0739\nM73 P13 R3\nG1 X189.276 Y192.143 E.0739\nG1 X187.5 Y192.471 E.06726\nG1 X117.5 Y192.471 E2.60723\nG1 X115.556 Y192.075 E.0739\nM73 P14 R3\nG1 X113.921 Y190.95 E.0739\nM73 P14 R3\nG1 X112.857 Y189.276 E.0739\nG1 X112.529 Y187.5 E.06726\nG1 X112.529 Y117.5 E2.60723\nG1 X112.925 Y115.556 E.0739\nG1 X113.878 Y114.171 E.0626\nG1 X114.261 Y114.452 F15000\nG1 F3000\nG1 X114.499 Y114.128 E.01498\nG1 X116.142 Y113.195 E.07039\nG1 X117.5 Y112.986 E.05116\nG1 X187.5 Y112.986 E2.60723\nG1 X189.348 Y113.382 E.07039\nM73 P15 R3\nG1 X190.872 Y114.499 E.07039\nM73 P15 R3\nG1 X191.805 Y116.142 E.07039\nG1 X192.014 Y117.5 E.05116\nG1 X192.014 Y187.5 E2.60723\nG1 X191.618 Y189.348 E.07039\nM73 P16 R3\nG1 X190.501 Y190.872 E.07039\nM73 P16 R3\nG1 X188.858 Y191.805 E.07039\nG1 X187.5 Y192.014 E.05116\nG1 X117.5 Y192.014 E2.60723\nG1 X115.652 Y191.618 E.07039\nG1 X114.128 Y190.501 E.07039\nG1 X113.195 Y188.858 E.07039\nG1 X112.986 Y187.5 E.05116\nG1 X112.986 Y117.5 E2.60723\nG1 X113.382 Y115.652 E.07039\nM73 P17 R3\nG1 X114.238 Y114.485 E.05392\nM73 P17 R3\nG1 X114.608 Y114.777 F15000\nG1 F3000\nG1 X114.946 Y114.348 E.02036\nG1 X116.552 Y113.555 E.06669\nG1 X117.5 Y113.443 E.03555\nG1 X187.5 Y113.443 E2.60723\nG1 X189.246 Y113.838 E.06669\nM73 P18 R3\nG1 X190.652 Y114.946 E.06669\nM73 P18 R3\nG1 X191.445 Y116.552 E.06669\nG1 X191.557 Y117.5 E.03555\nG1 X191.557 Y187.5 E2.60723\nG1 X191.162 Y189.246 E.06669\nG1 X190.054 Y190.652 E.06669\nG1 X188.448 Y191.445 E.06669\nG1 X187.5 Y191.557 E.03555\nG1 X117.5 Y191.557 E2.60723\nG1 X115.754 Y191.162 E.06669\nM73 P19 R3\nG1 X114.348 Y190.054 E.06669\nM73 P19 R3\nG1 X113.555 Y188.448 E.06669\nG1 X113.443 Y187.5 E.03555\nG1 X113.443 Y117.5 E2.60723\nG1 X113.838 Y115.754 E.06669\nG1 X114.583 Y114.808 E.04484\nM73 P20 R3\nG1 X114.938 Y115.112 F15000\nM73 P20 R3\nG1 F3000\nG1 X115.392 Y114.582 E.02598\nG1 X117.5 Y113.9 E.08254\nG1 X187.5 Y113.9 E2.60723\nG1 X189.138 Y114.295 E.06277\nG1 X190.418 Y115.392 E.06277\nG1 X191.1 Y117.5 E.08254\nG1 X191.1 Y187.5 E2.60723\nG1 X190.705 Y189.138 E.06277\nM73 P21 R3\nG1 X189.608 Y190.418 E.06277\nM73 P21 R3\nG1 X187.5 Y191.1 E.08254\nG1 X117.5 Y191.1 E2.60723\nG1 X115.862 Y190.705 E.06277\nG1 X114.582 Y189.608 E.06277\nG1 X113.9 Y187.5 E.08254\nM73 P22 R3\nG1 X113.9 Y117.5 E2.60723\nM73 P22 R3\nG1 X114.295 Y115.862 E.06277\nG1 X114.911 Y115.142 E.0353\nG1 X115.244 Y115.457 F15000\nG1 F3000\nG1 X115.833 Y114.836 E.03191\nG1 X117.5 Y114.357 E.06459\nG1 X187.5 Y114.357 E2.60723\nG1 X189.023 Y114.751 E.05859\nM73 P23 R3\nG1 X190.164 Y115.833 E.05859\nM73 P23 R3\nG1 X190.643 Y117.5 E.06459\nG1 X190.643 Y187.5 E2.60723\nG1 X190.249 Y189.023 E.05859\nG1 X189.167 Y190.164 E.05859\nG1 X187.5 Y190.643 E.06459\nG1 X117.5 Y190.643 E2.60723\nM73 P24 R3\nG1 X115.977 Y190.249 E.05859\nM73 P24 R3\nG1 X114.836 Y189.167 E.05859\nG1 X114.357 Y187.5 E.06459\nG1 X114.357 Y117.5 E2.60723\nG1 X114.751 Y115.977 E.05859\nM73 P25 R3\nG1 X115.216 Y115.486 E.02519\nM73 P25 R3\nG1 X115.519 Y115.812 F15000\nG1 F3000\nG1 X116.27 Y115.113 E.03821\nG1 X117.5 Y114.814 E.04715\nG1 X187.5 Y114.814 E2.60723\nG1 X188.898 Y115.207 E.05408\nG1 X189.887 Y116.27 E.05408\nG1 X190.186 Y117.5 E.04715\nG1 X190.186 Y187.5 E2.60723\nG1 X189.793 Y188.898 E.05408\nM73 P26 R2\nG1 X188.73 Y189.887 E.05408\nM73 P26 R2\nG1 X187.5 Y190.186 E.04715\nG1 X117.5 Y190.186 E2.60723\nG1 X116.102 Y189.793 E.05408\nM73 P27 R2\nG1 X115.113 Y188.73 E.05408\nM73 P27 R2\nG1 X114.814 Y187.5 E.04715\nG1 X114.814 Y117.5 E2.60723\nG1 X115.207 Y116.102 E.05408\nG1 X115.49 Y115.839 E.01439\nG1 X115.751 Y116.169 F15000\nG1 F3000\nG1 X116.698 Y115.421 E.04498\nG1 X117.5 Y115.271 E.03037\nG1 X187.5 Y115.271 E2.60723\nG1 X188.761 Y115.662 E.04917\nM73 P28 R2\nG1 X189.579 Y116.698 E.04917\nM73 P28 R2\nG1 X189.729 Y117.5 E.03037\nG1 X189.729 Y187.5 E2.60723\nG1 X189.338 Y188.761 E.04917\nM73 P29 R2\nG1 X188.302 Y189.579 E.04917\nM73 P29 R2\nG1 X187.5 Y189.729 E.03037\nG1 X117.5 Y189.729 E2.60723\nG1 X116.239 Y189.338 E.04917\nG1 X115.421 Y188.302 E.04917\nG1 X115.271 Y187.5 E.03037\nG1 X115.271 Y117.5 E2.60723\nG1 X115.662 Y116.239 E.04917\nM73 P30 R2\nG1 X115.719 Y116.194 E.0027\n;WIPE_START\nM73 P30 R2\nG1 X116.698 Y115.421 E-.49904\nG1 X117.438 Y115.283 E-.30096\n;WIPE_END\nEXCLUDE_OBJECT_START NAME=Cube_id_0_copy_0\nG1 X122.751 Y120.763 Z.6 F15000\nG1 X186.186 Y186.186 Z.6\nG1 Z.2\nG1 E.8 F1800\n;TYPE:Inner wall\nG1 F3000\nG1 X118.814 Y186.186 E2.50934\nG1 X118.814 Y118.814 E2.50934\nM73 P31 R2\nG1 X186.186 Y118.814 E2.50934\nM73 P32 R2\nM73 P31 R2\nG1 X186.186 Y186.126 E2.5071\nM73 P32 R2\nG1 X186.643 Y186.643 F15000\nM73 P33 R2\nG1 F3000\nM73 P33 R2\nG1 X118.357 Y186.643 E2.54339\nG1 X118.357 Y118.357 E2.54339\nG1 X186.643 Y118.357 E2.54339\nM73 P34 R2\nG1 X186.643 Y186.583 E2.54115\nM73 P34 R2\nG1 X187.1 Y187.1 F15000\nM73 P35 R2\n;TYPE:Outer wall\nG1 F3000\nM73 P35 R2\nG1 X117.9 Y187.1 E2.57744\nG1 X117.9 Y117.9 E2.57744\nM73 P36 R2\nG1 X187.1 Y117.9 E2.57744\nM73 P36 R2\nG1 X187.1 Y187.04 E2.5752\nM73 P37 R2\n;WIPE_START\nG1 X185.1 Y187.042 E-.8\n;WIPE_END\nM73 P37 R2\nG1 X185.208 Y179.41 Z.6 F15000\nG1 X186.049 Y119.879 Z.6\nM73 P38 R2\nG1 Z.2\nM73 P38 R2\nG1 E.8 F1800\n;TYPE:Bottom surface\n;WIDTH:0.501638\nG1 F6300\nG1 X185.327 Y119.157 E.03815\nG1 X184.678 Y119.157 E.02425\nG1 X185.843 Y120.322 E.06157\nG1 X185.843 Y120.97 E.02425\nG1 X184.03 Y119.157 E.09587\nG1 X183.381 Y119.157 E.02425\nG1 X185.843 Y121.619 E.13016\nG1 X185.843 Y122.268 E.02425\nG1 X182.732 Y119.157 E.16446\nG1 X182.083 Y119.157 E.02425\nG1 X185.843 Y122.917 E.19875\nG1 X185.843 Y123.565 E.02425\nG1 X181.435 Y119.157 E.23304\nG1 X180.786 Y119.157 E.02425\nG1 X185.843 Y124.214 E.26734\nG1 X185.843 Y124.863 E.02425\nG1 X180.137 Y119.157 E.30163\nG1 X179.488 Y119.157 E.02425\nG1 X185.843 Y125.512 E.33592\nM73 P39 R2\nG1 X185.843 Y126.16 E.02425\nM73 P39 R2\nG1 X178.84 Y119.157 E.37022\nG1 X178.191 Y119.157 E.02425\nG1 X185.843 Y126.809 E.40451\nG1 X185.843 Y127.458 E.02425\nG1 X177.542 Y119.157 E.4388\nG1 X176.894 Y119.157 E.02425\nG1 X185.843 Y128.106 E.4731\nG1 X185.843 Y128.755 E.02425\nG1 X176.245 Y119.157 E.50739\nG1 X175.596 Y119.157 E.02425\nG1 X185.843 Y129.404 E.54168\nG1 X185.843 Y130.053 E.02425\nG1 X174.947 Y119.157 E.57598\nG1 X174.299 Y119.157 E.02425\nM73 P40 R2\nG1 X185.843 Y130.701 E.61027\nM73 P40 R2\nG1 X185.843 Y131.35 E.02425\nG1 X173.65 Y119.157 E.64456\nG1 X173.001 Y119.157 E.02425\nG1 X185.843 Y131.999 E.67886\nG1 X185.843 Y132.648 E.02425\nG1 X172.352 Y119.157 E.71315\nG1 X171.704 Y119.157 E.02425\nG1 X185.843 Y133.296 E.74744\nG1 X185.843 Y133.945 E.02425\nG1 X171.055 Y119.157 E.78174\nG1 X170.406 Y119.157 E.02425\nG1 X185.843 Y134.594 E.81603\nG1 X185.843 Y135.242 E.02425\nM73 P41 R2\nG1 X169.758 Y119.157 E.85033\nM73 P41 R2\nG1 X169.109 Y119.157 E.02425\nG1 X185.843 Y135.891 E.88462\nG1 X185.843 Y136.54 E.02425\nG1 X168.46 Y119.157 E.91891\nG1 X167.811 Y119.157 E.02425\nG1 X185.843 Y137.189 E.95321\nG1 X185.843 Y137.837 E.02425\nG1 X167.163 Y119.157 E.9875\nG1 X166.514 Y119.157 E.02425\nM73 P42 R2\nG1 X185.843 Y138.486 E1.02179\nM73 P42 R2\nG1 X185.843 Y139.135 E.02425\nG1 X165.865 Y119.157 E1.05609\nG1 X165.216 Y119.157 E.02425\nG1 X185.843 Y139.784 E1.09038\nG1 X185.843 Y140.432 E.02425\nG1 X164.568 Y119.157 E1.12467\nG1 X163.919 Y119.157 E.02425\nG1 X185.843 Y141.081 E1.15897\nG1 X185.843 Y141.73 E.02425\nM73 P43 R2\nG1 X163.27 Y119.157 E1.19326\nM73 P43 R2\nG1 X162.622 Y119.157 E.02425\nG1 X185.843 Y142.378 E1.22755\nG1 X185.843 Y143.027 E.02425\nG1 X161.973 Y119.157 E1.26185\nG1 X161.324 Y119.157 E.02425\nG1 X185.843 Y143.676 E1.29614\nG1 X185.843 Y144.325 E.02425\nG1 X160.675 Y119.157 E1.33043\nG1 X160.027 Y119.157 E.02425\nM73 P44 R2\nG1 X185.843 Y144.973 E1.36473\nM73 P44 R2\nG1 X185.843 Y145.622 E.02425\nG1 X159.378 Y119.157 E1.39902\nG1 X158.729 Y119.157 E.02425\nG1 X185.843 Y146.271 E1.43331\nG1 X185.843 Y146.92 E.02425\nG1 X158.08 Y119.157 E1.46761\nG1 X157.432 Y119.157 E.02425\nM73 P45 R2\nG1 X185.843 Y147.568 E1.5019\nM73 P45 R2\nG1 X185.843 Y148.217 E.02425\nG1 X156.783 Y119.157 E1.53619\nG1 X156.134 Y119.157 E.02425\nG1 X185.843 Y148.866 E1.57049\nG1 X185.843 Y149.514 E.02425\nG1 X155.486 Y119.157 E1.60478\nG1 X154.837 Y119.157 E.02425\nM73 P46 R2\nG1 X185.843 Y150.163 E1.63908\nM73 P46 R2\nG1 X185.843 Y150.812 E.02425\nG1 X154.188 Y119.157 E1.67337\nG1 X153.539 Y119.157 E.02425\nG1 X185.843 Y151.461 E1.70766\nG1 X185.843 Y152.109 E.02425\nG1 X152.891 Y119.157 E1.74196\nG1 X152.242 Y119.157 E.02425\nM73 P47 R2\nG1 X185.843 Y152.758 E1.77625\nM73 P47 R2\nG1 X185.843 Y153.407 E.02425\nG1 X151.593 Y119.157 E1.81054\nG1 X150.945 Y119.157 E.02425\nG1 X185.843 Y154.055 E1.84484\nG1 X185.843 Y154.704 E.02425\nG1 X150.296 Y119.157 E1.87913\nG1 X149.647 Y119.157 E.02425\nM73 P48 R2\nG1 X185.843 Y155.353 E1.91342\nM73 P48 R2\nG1 X185.843 Y156.002 E.02425\nG1 X148.998 Y119.157 E1.94772\nG1 X148.35 Y119.157 E.02425\nG1 X185.843 Y156.65 E1.98201\nG1 X185.843 Y157.299 E.02425\nM73 P49 R2\nG1 X147.701 Y119.157 E2.0163\nM73 P49 R2\nG1 X147.052 Y119.157 E.02425\nG1 X185.843 Y157.948 E2.0506\nG1 X185.843 Y158.597 E.02425\nG1 X146.403 Y119.157 E2.08489\nG1 X145.755 Y119.157 E.02425\nG1 X185.843 Y159.245 E2.11918\nG1 X185.843 Y159.894 E.02425\nM73 P50 R2\nG1 X145.106 Y119.157 E2.15348\nM73 P50 R2\nG1 X144.457 Y119.157 E.02425\nG1 X185.843 Y160.543 E2.18777\nG1 X185.843 Y161.191 E.02425\nG1 X143.809 Y119.157 E2.22206\nG1 X143.16 Y119.157 E.02425\nM73 P51 R1\nG1 X185.843 Y161.84 E2.25636\nM73 P51 R1\nG1 X185.843 Y162.489 E.02425\nG1 X142.511 Y119.157 E2.29065\nG1 X141.862 Y119.157 E.02425\nG1 X185.843 Y163.138 E2.32494\nG1 X185.843 Y163.786 E.02425\nM73 P52 R1\nG1 X141.214 Y119.157 E2.35924\nM73 P52 R1\nG1 X140.565 Y119.157 E.02425\nG1 X185.843 Y164.435 E2.39353\nG1 X185.843 Y165.084 E.02425\nG1 X139.916 Y119.157 E2.42783\nG1 X139.267 Y119.157 E.02425\nM73 P53 R1\nG1 X185.843 Y165.733 E2.46212\nM73 P53 R1\nG1 X185.843 Y166.381 E.02425\nG1 X138.619 Y119.157 E2.49641\nG1 X137.97 Y119.157 E.02425\nG1 X185.843 Y167.03 E2.53071\nG1 X185.843 Y167.679 E.02425\nM73 P54 R1\nG1 X137.321 Y119.157 E2.565\nM73 P54 R1\nG1 X136.673 Y119.157 E.02425\nG1 X185.843 Y168.327 E2.59929\nG1 X185.843 Y168.976 E.02425\nG1 X136.024 Y119.157 E2.63359\nG1 X135.375 Y119.157 E.02425\nM73 P55 R1\nG1 X185.843 Y169.625 E2.66788\nM73 P55 R1\nG1 X185.843 Y170.274 E.02425\nG1 X134.726 Y119.157 E2.70217\nG1 X134.078 Y119.157 E.02425\nM73 P56 R1\nG1 X185.843 Y170.922 E2.73647\nM73 P56 R1\nG1 X185.843 Y171.571 E.02425\nG1 X133.429 Y119.157 E2.77076\nG1 X132.78 Y119.157 E.02425\nG1 X185.843 Y172.22 E2.80505\nG1 X185.843 Y172.869 E.02425\nM73 P57 R1\nG1 X132.131 Y119.157 E2.83935\nM73 P57 R1\nG1 X131.483 Y119.157 E.02425\nG1 X185.843 Y173.517 E2.87364\nG1 X185.843 Y174.166 E.02425\nG1 X130.834 Y119.157 E2.90793\nG1 X130.185 Y119.157 E.02425\nM73 P58 R1\nG1 X185.843 Y174.815 E2.94223\nM73 P58 R1\nG1 X185.843 Y175.463 E.02425\nG1 X129.537 Y119.157 E2.97652\nG1 X128.888 Y119.157 E.02425\nM73 P59 R1\nG1 X185.843 Y176.112 E3.01081\nM73 P59 R1\nG1 X185.843 Y176.761 E.02425\nG1 X128.239 Y119.157 E3.04511\nG1 X127.59 Y119.157 E.02425\nG1 X185.843 Y177.41 E3.0794\nG1 X185.843 Y178.058 E.02425\nM73 P60 R1\nG1 X126.942 Y119.157 E3.1137\nM73 P60 R1\nG1 X126.293 Y119.157 E.02425\nG1 X185.843 Y178.707 E3.14799\nG1 X185.843 Y179.356 E.02425\nM73 P61 R1\nG1 X125.644 Y119.157 E3.18228\nM73 P61 R1\nG1 X124.996 Y119.157 E.02425\nG1 X185.843 Y180.004 E3.21658\nG1 X185.843 Y180.653 E.02425\nG1 X124.347 Y119.157 E3.25087\nM73 P62 R1\nG1 X123.698 Y119.157 E.02425\nM73 P62 R1\nG1 X185.843 Y181.302 E3.28516\nG1 X185.843 Y181.951 E.02425\nG1 X123.049 Y119.157 E3.31946\nG1 X122.401 Y119.157 E.02425\nM73 P63 R1\nG1 X185.843 Y182.599 E3.35375\nM73 P63 R1\nG1 X185.843 Y183.248 E.02425\nG1 X121.752 Y119.157 E3.38804\nG1 X121.103 Y119.157 E.02425\nM73 P64 R1\nG1 X185.843 Y183.897 E3.42234\nM73 P64 R1\nG1 X185.843 Y184.546 E.02425\nG1 X120.454 Y119.157 E3.45663\nG1 X119.806 Y119.157 E.02425\nM73 P65 R1\nG1 X185.843 Y185.194 E3.49092\nM73 P65 R1\nG1 X185.843 Y185.843 E.02425\nG1 X119.157 Y119.157 E3.52522\nG1 X119.157 Y119.806 E.02425\nG1 X185.194 Y185.843 E3.49093\nG1 X184.546 Y185.843 E.02425\nM73 P66 R1\nG1 X119.157 Y120.454 E3.45663\nM73 P66 R1\nG1 X119.157 Y121.103 E.02425\nG1 X183.897 Y185.843 E3.42234\nG1 X183.248 Y185.843 E.02425\nM73 P67 R1\nG1 X119.157 Y121.752 E3.38805\nM73 P67 R1\nG1 X119.157 Y122.401 E.02425\nG1 X182.599 Y185.843 E3.35375\nG1 X181.951 Y185.843 E.02425\nM73 P68 R1\nG1 X119.157 Y123.049 E3.31946\nM73 P68 R1\nG1 X119.157 Y123.698 E.02425\nG1 X181.302 Y185.843 E3.28516\nG1 X180.653 Y185.843 E.02425\nM73 P69 R1\nG1 X119.157 Y124.347 E3.25087\nM73 P69 R1\nG1 X119.157 Y124.995 E.02425\nG1 X180.005 Y185.843 E3.21658\nG1 X179.356 Y185.843 E.02425\nG1 X119.157 Y125.644 E3.18228\nG1 X119.157 Y126.293 E.02425\nM73 P70 R1\nG1 X178.707 Y185.843 E3.14799\nM73 P70 R1\nG1 X178.058 Y185.843 E.02425\nG1 X119.157 Y126.942 E3.1137\nG1 X119.157 Y127.59 E.02425\nM73 P71 R1\nG1 X177.41 Y185.843 E3.0794\nM73 P71 R1\nG1 X176.761 Y185.843 E.02425\nG1 X119.157 Y128.239 E3.04511\nG1 X119.157 Y128.888 E.02425\nG1 X176.112 Y185.843 E3.01082\nG1 X175.463 Y185.843 E.02425\nM73 P72 R1\nG1 X119.157 Y129.537 E2.97652\nM73 P72 R1\nG1 X119.157 Y130.185 E.02425\nG1 X174.815 Y185.843 E2.94223\nG1 X174.166 Y185.843 E.02425\nM73 P73 R1\nG1 X119.157 Y130.834 E2.90794\nM73 P73 R1\nG1 X119.157 Y131.483 E.02425\nG1 X173.517 Y185.843 E2.87364\nG1 X172.869 Y185.843 E.02425\nG1 X119.157 Y132.131 E2.83935\nG1 X119.157 Y132.78 E.02425\nM73 P74 R1\nG1 X172.22 Y185.843 E2.80506\nM73 P74 R1\nG1 X171.571 Y185.843 E.02425\nG1 X119.157 Y133.429 E2.77076\nG1 X119.157 Y134.078 E.02425\nM73 P75 R1\nG1 X170.922 Y185.843 E2.73647\nM73 P75 R1\nG1 X170.274 Y185.843 E.02425\nG1 X119.157 Y134.726 E2.70218\nG1 X119.157 Y135.375 E.02425\nM73 P75 R0\nG1 X169.625 Y185.843 E2.66788\nM73 P75 R0\nG1 X168.976 Y185.843 E.02425\nM73 P76 R0\nG1 X119.157 Y136.024 E2.63359\nM73 P76 R0\nG1 X119.157 Y136.673 E.02425\nG1 X168.327 Y185.843 E2.59929\nG1 X167.679 Y185.843 E.02425\nG1 X119.157 Y137.321 E2.565\nG1 X119.157 Y137.97 E.02425\nM73 P77 R0\nG1 X167.03 Y185.843 E2.53071\nM73 P77 R0\nG1 X166.381 Y185.843 E.02425\nG1 X119.157 Y138.619 E2.49641\nG1 X119.157 Y139.267 E.02425\nG1 X165.733 Y185.843 E2.46212\nG1 X165.084 Y185.843 E.02425\nM73 P78 R0\nG1 X119.157 Y139.916 E2.42783\nM73 P78 R0\nG1 X119.157 Y140.565 E.02425\nG1 X164.435 Y185.843 E2.39353\nG1 X163.786 Y185.843 E.02425\nG1 X119.157 Y141.214 E2.35924\nG1 X119.157 Y141.862 E.02425\nM73 P79 R0\nG1 X163.138 Y185.843 E2.32495\nM73 P79 R0\nG1 X162.489 Y185.843 E.02425\nG1 X119.157 Y142.511 E2.29065\nG1 X119.157 Y143.16 E.02425\nG1 X161.84 Y185.843 E2.25636\nG1 X161.191 Y185.843 E.02425\nM73 P80 R0\nG1 X119.157 Y143.809 E2.22207\nM73 P80 R0\nG1 X119.157 Y144.457 E.02425\nG1 X160.543 Y185.843 E2.18777\nG1 X159.894 Y185.843 E.02425\nG1 X119.157 Y145.106 E2.15348\nG1 X119.157 Y145.755 E.02425\nM73 P81 R0\nG1 X159.245 Y185.843 E2.11919\nM73 P81 R0\nG1 X158.597 Y185.843 E.02425\nG1 X119.157 Y146.403 E2.08489\nG1 X119.157 Y147.052 E.02425\nG1 X157.948 Y185.843 E2.0506\nG1 X157.299 Y185.843 E.02425\nM73 P82 R0\nG1 X119.157 Y147.701 E2.01631\nM73 P82 R0\nG1 X119.157 Y148.35 E.02425\nG1 X156.65 Y185.843 E1.98201\nG1 X156.002 Y185.843 E.02425\nG1 X119.157 Y148.998 E1.94772\nG1 X119.157 Y149.647 E.02425\nG1 X155.353 Y185.843 E1.91343\nG1 X154.704 Y185.843 E.02425\nM73 P83 R0\nG1 X119.157 Y150.296 E1.87913\nM73 P83 R0\nG1 X119.157 Y150.944 E.02425\nG1 X154.056 Y185.843 E1.84484\nG1 X153.407 Y185.843 E.02425\nG1 X119.157 Y151.593 E1.81054\nG1 X119.157 Y152.242 E.02425\nM73 P84 R0\nG1 X152.758 Y185.843 E1.77625\nM73 P84 R0\nG1 X152.109 Y185.843 E.02425\nG1 X119.157 Y152.891 E1.74196\nG1 X119.157 Y153.539 E.02425\nG1 X151.461 Y185.843 E1.70766\nG1 X150.812 Y185.843 E.02425\nG1 X119.157 Y154.188 E1.67337\nG1 X119.157 Y154.837 E.02425\nM73 P85 R0\nG1 X150.163 Y185.843 E1.63908\nM73 P85 R0\nG1 X149.514 Y185.843 E.02425\nG1 X119.157 Y155.486 E1.60478\nG1 X119.157 Y156.134 E.02425\nG1 X148.866 Y185.843 E1.57049\nG1 X148.217 Y185.843 E.02425\nG1 X119.157 Y156.783 E1.5362\nG1 X119.157 Y157.432 E.02425\nM73 P86 R0\nG1 X147.568 Y185.843 E1.5019\nM73 P86 R0\nG1 X146.92 Y185.843 E.02425\nG1 X119.157 Y158.08 E1.46761\nG1 X119.157 Y158.729 E.02425\nG1 X146.271 Y185.843 E1.43332\nG1 X145.622 Y185.843 E.02425\nG1 X119.157 Y159.378 E1.39902\nG1 X119.157 Y160.027 E.02425\nM73 P87 R0\nG1 X144.973 Y185.843 E1.36473\nM73 P87 R0\nG1 X144.325 Y185.843 E.02425\nG1 X119.157 Y160.675 E1.33044\nG1 X119.157 Y161.324 E.02425\nG1 X143.676 Y185.843 E1.29614\nG1 X143.027 Y185.843 E.02425\nG1 X119.157 Y161.973 E1.26185\nG1 X119.157 Y162.622 E.02425\nG1 X142.378 Y185.843 E1.22756\nM73 P88 R0\nG1 X141.73 Y185.843 E.02425\nM73 P88 R0\nG1 X119.157 Y163.27 E1.19326\nG1 X119.157 Y163.919 E.02425\nG1 X141.081 Y185.843 E1.15897\nG1 X140.432 Y185.843 E.02425\nG1 X119.157 Y164.568 E1.12468\nG1 X119.157 Y165.216 E.02425\nG1 X139.784 Y185.843 E1.09038\nG1 X139.135 Y185.843 E.02425\nM73 P89 R0\nG1 X119.157 Y165.865 E1.05609\nM73 P89 R0\nG1 X119.157 Y166.514 E.02425\nG1 X138.486 Y185.843 E1.02179\nG1 X137.837 Y185.843 E.02425\nG1 X119.157 Y167.163 E.9875\nG1 X119.157 Y167.811 E.02425\nG1 X137.189 Y185.843 E.95321\nG1 X136.54 Y185.843 E.02425\nG1 X119.157 Y168.46 E.91891\nG1 X119.157 Y169.109 E.02425\nG1 X135.891 Y185.843 E.88462\nG1 X135.242 Y185.843 E.02425\nM73 P90 R0\nG1 X119.157 Y169.758 E.85033\nM73 P90 R0\nG1 X119.157 Y170.406 E.02425\nG1 X134.594 Y185.843 E.81603\nG1 X133.945 Y185.843 E.02425\nG1 X119.157 Y171.055 E.78174\nG1 X119.157 Y171.704 E.02425\nG1 X133.296 Y185.843 E.74745\nG1 X132.648 Y185.843 E.02425\nG1 X119.157 Y172.352 E.71315\nG1 X119.157 Y173.001 E.02425\nG1 X131.999 Y185.843 E.67886\nM73 P91 R0\nG1 X131.35 Y185.843 E.02425\nM73 P91 R0\nG1 X119.157 Y173.65 E.64457\nG1 X119.157 Y174.299 E.02425\nG1 X130.701 Y185.843 E.61027\nG1 X130.053 Y185.843 E.02425\nG1 X119.157 Y174.947 E.57598\nG1 X119.157 Y175.596 E.02425\nG1 X129.404 Y185.843 E.54169\nG1 X128.755 Y185.843 E.02425\nG1 X119.157 Y176.245 E.50739\nG1 X119.157 Y176.893 E.02425\nG1 X128.107 Y185.843 E.4731\nG1 X127.458 Y185.843 E.02425\nG1 X119.157 Y177.542 E.43881\nM73 P92 R0\nG1 X119.157 Y178.191 E.02425\nM73 P92 R0\nG1 X126.809 Y185.843 E.40451\nG1 X126.16 Y185.843 E.02425\nG1 X119.157 Y178.84 E.37022\nG1 X119.157 Y179.488 E.02425\nG1 X125.512 Y185.843 E.33592\nG1 X124.863 Y185.843 E.02425\nG1 X119.157 Y180.137 E.30163\nG1 X119.157 Y180.786 E.02425\nG1 X124.214 Y185.843 E.26734\nG1 X123.565 Y185.843 E.02425\nG1 X119.157 Y181.435 E.23304\nG1 X119.157 Y182.083 E.02425\nG1 X122.917 Y185.843 E.19875\nG1 X122.268 Y185.843 E.02425\nG1 X119.157 Y182.732 E.16446\nG1 X119.157 Y183.381 E.02425\nG1 X121.619 Y185.843 E.13016\nG1 X120.971 Y185.843 E.02425\nG1 X119.157 Y184.029 E.09587\nM73 P93 R0\nG1 X119.157 Y184.678 E.02425\nM73 P93 R0\nG1 X120.322 Y185.843 E.06158\nG1 X119.673 Y185.843 E.02425\nG1 X118.951 Y185.121 E.03816\nG1 E-.22857 F1800\n;WIPE_START\nG1 F6300\nG1 X119.673 Y185.843 E-.29165\nG1 X120.322 Y185.843 E-.18535\nG1 X120.088 Y185.609 E-.09443\n;WIPE_END\nEXCLUDE_OBJECT_END NAME=Cube_id_0_copy_0\nM106 S0\nM106 P2 S0\n;TYPE:Custom\nM141 S0\nM104 S0\nM140 S0\nG1 E-3 F1800\nG0 Z3.2 F600\nG0 X0 Y0 F12000\nG1 Z150 F600\nM106 P3 S0\nM73 P100 R0\n; EXECUTABLE_BLOCK_END\n\n; filament used [mm] = 525.65\n; filament used [cm3] = 1.26\n; filament used [g] = 1.57\n; filament cost = 0.03\n; total filament used [g] = 1.57\n; total filament cost = 0.03\n; total layers count = 1\n; estimated printing time (normal mode) = 4m 4s\n\n; CONFIG_BLOCK_START\n; accel_to_decel_enable = 1\n; accel_to_decel_factor = 50%\n; activate_air_filtration = 1\n; activate_chamber_temp_control = 0\n; adaptive_bed_mesh_margin = 0\n; adaptive_pressure_advance = 0\n; adaptive_pressure_advance_bridges = 0\n; adaptive_pressure_advance_model = \"0,0,0\\n0,0,0\"\n; adaptive_pressure_advance_overhangs = 0\n; additional_cooling_fan_speed = 0\n; alternate_extra_wall = 0\n; auxiliary_fan = 1\n; bbl_calib_mark_logo = 1\n; bbl_use_printhost = 0\n; bed_custom_model = \n; bed_custom_texture = \n; bed_exclude_area = 0x305,0x302,35x302,35x305,305x305,305x305,305x305,305x20,293x20,293x0,305x0,305x20,305x305\n; bed_mesh_max = 99999,99999\n; bed_mesh_min = -99999,-99999\n; bed_mesh_probe_distance = 50,50\n; before_layer_change_gcode = ;BEFORE_LAYER_CHANGE\\n;[layer_z]\\nG92 E0\\n\n; best_object_pos = 0.5,0.5\n; bottom_shell_layers = 3\n; bottom_shell_thickness = 0\n; bottom_solid_infill_flow_ratio = 1\n; bottom_surface_pattern = monotonic\n; bridge_acceleration = 50%\n; bridge_angle = 0\n; bridge_density = 100%\n; bridge_flow = 1\n; bridge_no_support = 0\n; bridge_speed = 50\n; brim_ears_detection_length = 1\n; brim_ears_max_angle = 125\n; brim_object_gap = 0.1\n; brim_type = auto_brim\n; brim_width = 5\n; chamber_temperature = 0\n; change_extrusion_role_gcode = \n; change_filament_gcode = \n; close_fan_the_first_x_layers = 1\n; complete_print_exhaust_fan_speed = 0\n; cool_plate_temp = 60\n; cool_plate_temp_initial_layer = 60\n; cooling_tube_length = 5\n; cooling_tube_retraction = 91.5\n; counterbore_hole_bridging = none\n; curr_bed_type = High Temp Plate\n; default_acceleration = 10000\n; default_filament_colour = \"\"\n; default_filament_profile = \"Qidi Generic PLA @Qidi X-Plus 4 0.4 nozzle\"\n; default_jerk = 0\n; default_print_profile = 0.20mm Standard @Qidi XPlus4\n; deretraction_speed = 0\n; detect_narrow_internal_solid_infill = 1\n; detect_overhang_wall = 1\n; detect_thin_wall = 0\n; different_settings_to_system = only_one_wall_top;skirt_loops;wall_loops;;thumbnails\n; disable_m73 = 0\n; dont_filter_internal_bridges = disabled\n; dont_slow_down_outer_wall = 1\n; draft_shield = disabled\n; during_print_exhaust_fan_speed = 100\n; elefant_foot_compensation = 0.15\n; elefant_foot_compensation_layers = 1\n; emit_machine_limits_to_gcode = 1\n; enable_arc_fitting = 0\n; enable_filament_ramming = 1\n; enable_long_retraction_when_cut = 0\n; enable_overhang_bridge_fan = 0\n; enable_overhang_speed = 1\n; enable_pressure_advance = 1\n; enable_prime_tower = 0\n; enable_support = 0\n; enforce_support_layers = 0\n; eng_plate_temp = 60\n; eng_plate_temp_initial_layer = 60\n; ensure_vertical_shell_thickness = ensure_all\n; exclude_object = 1\n; extra_loading_move = -2\n; extra_perimeters_on_overhangs = 0\n; extruder_clearance_height_to_lid = 135\n; extruder_clearance_height_to_rod = 32\n; extruder_clearance_radius = 72\n; extruder_colour = #C0C0C0\n; extruder_offset = 0x0\n; fan_cooling_layer_time = 60\n; fan_kickstart = 0\n; fan_max_speed = 100\n; fan_min_speed = 100\n; fan_speedup_overhangs = 1\n; fan_speedup_time = 0\n; filament_colour = #C0C0C0\n; filament_cooling_final_speed = 3.4\n; filament_cooling_initial_speed = 2.2\n; filament_cooling_moves = 4\n; filament_cost = 20\n; filament_density = 1.24\n; filament_diameter = 1.75\n; filament_end_gcode = \" \"\n; filament_flow_ratio = 0.98\n; filament_ids = GFB99\n; filament_is_support = 0\n; filament_loading_speed = 28\n; filament_loading_speed_start = 3\n; filament_max_volumetric_speed = 14\n; filament_minimal_purge_on_wipe_tower = 15\n; filament_multitool_ramming = 0\n; filament_multitool_ramming_flow = 10\n; filament_multitool_ramming_volume = 10\n; filament_notes = \"\"\n; filament_ramming_parameters = \"120 100 6.6 6.8 7.2 7.6 7.9 8.2 8.7 9.4 9.9 10.0| 0.05 6.6 0.45 6.8 0.95 7.8 1.45 8.3 1.95 9.7 2.45 10 2.95 7.6 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6\"\n; filament_settings_id = \"Qidi Generic PLA @Qidi X-Plus 4 0.4 nozzle\"\n; filament_shrink = 100%\n; filament_shrinkage_compensation_z = 100%\n; filament_soluble = 0\n; filament_stamping_distance = 0\n; filament_stamping_loading_speed = 0\n; filament_start_gcode = \" \"\n; filament_toolchange_delay = 0\n; filament_type = PLA\n; filament_unloading_speed = 90\n; filament_unloading_speed_start = 100\n; filament_vendor = QIDI\n; filename_format = {input_filename_base}_{filament_type[0]}_{print_time}.gcode\n; filter_out_gap_fill = 2\n; first_layer_print_sequence = 0\n; flush_into_infill = 0\n; flush_into_objects = 0\n; flush_into_support = 1\n; flush_multiplier = 1\n; flush_volumes_matrix = 0\n; flush_volumes_vector = 140,140\n; full_fan_speed_layer = 3\n; fuzzy_skin = none\n; fuzzy_skin_first_layer = 0\n; fuzzy_skin_point_distance = 0.8\n; fuzzy_skin_thickness = 0.3\n; gap_fill_target = nowhere\n; gap_infill_speed = 250\n; gcode_add_line_number = 0\n; gcode_comments = 0\n; gcode_flavor = klipper\n; gcode_label_objects = 0\n; has_scarf_joint_seam = 0\n; head_wrap_detect_zone = \n; high_current_on_filament_swap = 0\n; hole_to_polyhole = 0\n; hole_to_polyhole_threshold = 0.01\n; hole_to_polyhole_twisted = 1\n; host_type = octoprint\n; hot_plate_temp = 60\n; hot_plate_temp_initial_layer = 60\n; idle_temperature = 0\n; independent_support_layer_height = 0\n; infill_anchor = 400%\n; infill_anchor_max = 20\n; infill_combination = 0\n; infill_combination_max_layer_height = 100%\n; infill_direction = 45\n; infill_jerk = 9\n; infill_wall_overlap = 15%\n; inherits_group = ;;\"Qidi X-Plus 4 0.4 nozzle\"\n; initial_layer_acceleration = 500\n; initial_layer_infill_speed = 105\n; initial_layer_jerk = 9\n; initial_layer_line_width = 0.5\n; initial_layer_min_bead_width = 85%\n; initial_layer_print_height = 0.2\n; initial_layer_speed = 50\n; initial_layer_travel_speed = 50%\n; inner_wall_acceleration = 5000\n; inner_wall_jerk = 9\n; inner_wall_line_width = 0.45\n; inner_wall_speed = 300\n; interface_shells = 0\n; interlocking_beam = 0\n; interlocking_beam_layer_count = 2\n; interlocking_beam_width = 0.8\n; interlocking_boundary_avoidance = 2\n; interlocking_depth = 2\n; interlocking_orientation = 22.5\n; internal_bridge_flow = 1\n; internal_bridge_speed = 50\n; internal_solid_infill_acceleration = 100%\n; internal_solid_infill_line_width = 0.42\n; internal_solid_infill_pattern = zig-zag\n; internal_solid_infill_speed = 250\n; ironing_angle = -1\n; ironing_flow = 10%\n; ironing_pattern = zig-zag\n; ironing_spacing = 0.15\n; ironing_speed = 30\n; ironing_type = no ironing\n; is_infill_first = 0\n; layer_change_gcode = G92 E0\\nSET_PRINT_STATS_INFO CURRENT_LAYER={layer_num + 1}\n; layer_height = 0.2\n; line_width = 0.42\n; long_retractions_when_cut = 0\n; machine_end_gcode = M141 S0\\nM104 S0\\nM140 S0\\nG1 E-3 F1800\\nG0 Z{min(max_print_height, max_layer_z + 3)} F600\\nG0 X0 Y0 F12000\\n{if max_layer_z < max_print_height / 2}G1 Z{max_print_height / 2 + 10} F600{else}G1 Z{min(max_print_height, max_layer_z + 3)}{endif}\n; machine_load_filament_time = 0\n; machine_max_acceleration_e = 5000\n; machine_max_acceleration_extruding = 20000\n; machine_max_acceleration_retracting = 20000\n; machine_max_acceleration_travel = 0,0\n; machine_max_acceleration_x = 20000\n; machine_max_acceleration_y = 20000\n; machine_max_acceleration_z = 500\n; machine_max_jerk_e = 4\n; machine_max_jerk_x = 9\n; machine_max_jerk_y = 9\n; machine_max_jerk_z = 4\n; machine_max_speed_e = 30\n; machine_max_speed_x = 600\n; machine_max_speed_y = 600\n; machine_max_speed_z = 20\n; machine_min_extruding_rate = 0\n; machine_min_travel_rate = 0\n; machine_pause_gcode = M0\n; machine_start_gcode = PRINT_START BED=[hot_plate_temp_initial_layer] HOTEND=[nozzle_temperature_initial_layer] CHAMBER=[chamber_temperature]\\nSET_PRINT_STATS_INFO TOTAL_LAYER=[total_layer_count]\\nM83\\nM140 S[hot_plate_temp_initial_layer]\\nM104 S[nozzle_temperature_initial_layer]\\nM141 S[chamber_temperature]\\nG4 P3000\\nG0 X{max((min(print_bed_max[0] - 12, first_layer_print_min[0] + 80) - 85), 0)} Y{max((min(print_bed_max[1] - 3, first_layer_print_min[1] + 80) - 85), 0)} Z5 F6000\\nG0 Z[initial_layer_print_height] F600\\nG1 E3 F1800\\nG1 X{(min(print_bed_max[0] - 12, first_layer_print_min[0] + 80))} E{85 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\\nG1 Y{max((min(print_bed_max[1] - 3, first_layer_print_min[1] + 80) - 85), 0) + 2} E{2 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\\nG1 X{max((min(print_bed_max[0] - 12, first_layer_print_min[0] + 80) - 85), 0)} E{85 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\\nG1 Y{max((min(print_bed_max[1] - 3, first_layer_print_min[1] + 80) - 85), 0) + 85} E{83 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\\nG1 X{max((min(print_bed_max[0] - 12, first_layer_print_min[0] + 80) - 85), 0) + 2} E{2 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\\nG1 Y{max((min(print_bed_max[1] - 3, first_layer_print_min[1] + 80) - 85), 0) + 3} E{82 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\\nG1 X{max((min(print_bed_max[0] - 12, first_layer_print_min[0] + 80) - 85), 0) + 3} Z0\\nG1 X{max((min(print_bed_max[0] - 12, first_layer_print_min[0] + 80) - 85), 0) + 6}\\nG1 Z1 F600\\nSET_PRINT_STATS_INFO CURRENT_LAYER=1\\n\n; machine_tool_change_time = 0\n; machine_unload_filament_time = 0\n; make_overhang_printable = 0\n; make_overhang_printable_angle = 55\n; make_overhang_printable_hole_size = 0\n; manual_filament_change = 0\n; max_bridge_length = 10\n; max_layer_height = 0.28\n; max_travel_detour_distance = 0\n; max_volumetric_extrusion_rate_slope = 0\n; max_volumetric_extrusion_rate_slope_segment_length = 3\n; min_bead_width = 85%\n; min_feature_size = 25%\n; min_layer_height = 0.08\n; min_length_factor = 0.5\n; min_skirt_length = 0\n; min_width_top_surface = 300%\n; minimum_sparse_infill_area = 15\n; mmu_segmented_region_interlocking_depth = 0\n; mmu_segmented_region_max_width = 0\n; notes = If you want to use Orca's chamber temperature control feature, check that printer.cfg has added the following M191 macro.\\nTo add it: go to Fluidd web interface--configuration, copy the following code to the top of the printer.cfg document, SAVE&RESATART  \\n\\n[gcode_macro M191]\\ngcode:\\n    {% set s = params.S|float %}\\n    {% if s == 0 %}\\n        # If target temperature is 0, do nothing\\n        M117 Chamber heating cancelled\\n    {% else %}\\n        SET_HEATER_TEMPERATURE HEATER=chamber_heater TARGET={s}\\n        # Orca: uncomment the following line if you want to use heat bed to assist chamber heating\\n        M140 S90\\n        TEMPERATURE_WAIT SENSOR=\\\"heater_generic chamber_heater\\\" MINIMUM={s-1} MAXIMUM={s+1}\\n        M117 Chamber at target temperature\\n    {% endif %}\n; nozzle_diameter = 0.4\n; nozzle_height = 2.5\n; nozzle_hrc = 0\n; nozzle_temperature = 210\n; nozzle_temperature_initial_layer = 210\n; nozzle_temperature_range_high = 240\n; nozzle_temperature_range_low = 190\n; nozzle_type = hardened_steel\n; nozzle_volume = 0\n; only_one_wall_first_layer = 0\n; only_one_wall_top = 0\n; ooze_prevention = 0\n; other_layers_print_sequence = 0\n; other_layers_print_sequence_nums = 0\n; outer_wall_acceleration = 3000\n; outer_wall_jerk = 9\n; outer_wall_line_width = 0.42\n; outer_wall_speed = 200\n; overhang_1_4_speed = 0\n; overhang_2_4_speed = 50\n; overhang_3_4_speed = 30\n; overhang_4_4_speed = 10\n; overhang_fan_speed = 100\n; overhang_fan_threshold = 95%\n; overhang_reverse = 0\n; overhang_reverse_internal_only = 0\n; overhang_reverse_threshold = 50%\n; overhang_speed_classic = 0\n; parking_pos_retraction = 92\n; pellet_flow_coefficient = 0.4157\n; pellet_modded_printer = 0\n; post_process = \n; precise_outer_wall = 0\n; precise_z_height = 0\n; preferred_orientation = 0\n; preheat_steps = 1\n; preheat_time = 30\n; pressure_advance = 0.034\n; prime_tower_brim_width = 3\n; prime_tower_width = 35\n; prime_volume = 45\n; print_compatible_printers = \"Qidi X-Plus 4 0.4 nozzle\"\n; print_flow_ratio = 1\n; print_order = default\n; print_sequence = by layer\n; print_settings_id = 0.20mm Standard @Qidi XPlus4\n; printable_area = 0x0,305x0,305x305,0x305\n; printable_height = 280\n; printer_model = Qidi X-Plus 4\n; printer_notes = \n; printer_settings_id = Qidi X-Plus 4 0.4 nozzle - Copy\n; printer_structure = undefine\n; printer_technology = FFF\n; printer_variant = 0.4\n; printhost_authorization_type = key\n; printhost_ssl_ignore_revoke = 0\n; printing_by_object_gcode = \n; purge_in_prime_tower = 1\n; raft_contact_distance = 0.1\n; raft_expansion = 1.5\n; raft_first_layer_density = 90%\n; raft_first_layer_expansion = 2\n; raft_layers = 0\n; reduce_crossing_wall = 0\n; reduce_fan_stop_start_freq = 1\n; reduce_infill_retraction = 1\n; required_nozzle_HRC = 0\n; resolution = 0.012\n; retract_before_wipe = 0%\n; retract_length_toolchange = 2\n; retract_lift_above = 0\n; retract_lift_below = 0\n; retract_lift_enforce = All Surfaces\n; retract_restart_extra = 0\n; retract_restart_extra_toolchange = 0\n; retract_when_changing_layer = 1\n; retraction_distances_when_cut = 18\n; retraction_length = 0.8\n; retraction_minimum_travel = 1\n; retraction_speed = 30\n; role_based_wipe_speed = 1\n; rotate_solid_infill_direction = 1\n; scan_first_layer = 0\n; scarf_angle_threshold = 155\n; scarf_joint_flow_ratio = 1\n; scarf_joint_speed = 100%\n; scarf_overhang_threshold = 40%\n; seam_gap = 15%\n; seam_position = aligned\n; seam_slope_conditional = 0\n; seam_slope_entire_loop = 0\n; seam_slope_inner_walls = 0\n; seam_slope_min_length = 20\n; seam_slope_start_height = 0\n; seam_slope_steps = 10\n; seam_slope_type = none\n; silent_mode = 0\n; single_extruder_multi_material = 1\n; single_extruder_multi_material_priming = 0\n; skirt_distance = 2\n; skirt_height = 1\n; skirt_loops = 10\n; skirt_speed = 50\n; skirt_start_angle = -135\n; skirt_type = combined\n; slice_closing_radius = 0.049\n; slicing_mode = regular\n; slow_down_for_layer_cooling = 1\n; slow_down_layer_time = 8\n; slow_down_layers = 0\n; slow_down_min_speed = 20\n; slowdown_for_curled_perimeters = 1\n; small_area_infill_flow_compensation = 0\n; small_area_infill_flow_compensation_model = 0,0;\"\\n0.2,0.4444\";\"\\n0.4,0.6145\";\"\\n0.6,0.7059\";\"\\n0.8,0.7619\";\"\\n1.5,0.8571\";\"\\n2,0.8889\";\"\\n3,0.9231\";\"\\n5,0.9520\";\"\\n10,1\"\n; small_perimeter_speed = 50%\n; small_perimeter_threshold = 4\n; solid_infill_direction = 45\n; solid_infill_filament = 1\n; sparse_infill_acceleration = 100%\n; sparse_infill_density = 15%\n; sparse_infill_filament = 1\n; sparse_infill_line_width = 0.45\n; sparse_infill_pattern = grid\n; sparse_infill_speed = 270\n; spiral_mode = 0\n; spiral_mode_max_xy_smoothing = 200%\n; spiral_mode_smooth = 0\n; staggered_inner_seams = 0\n; standby_temperature_delta = -5\n; start_end_points = 30x-3,54x245\n; support_air_filtration = 1\n; support_angle = 0\n; support_base_pattern = default\n; support_base_pattern_spacing = 2.5\n; support_bottom_interface_spacing = 0.5\n; support_bottom_z_distance = 0.2\n; support_chamber_temp_control = 1\n; support_critical_regions_only = 0\n; support_expansion = 0\n; support_filament = 0\n; support_interface_bottom_layers = 2\n; support_interface_filament = 0\n; support_interface_loop_pattern = 0\n; support_interface_not_for_body = 1\n; support_interface_pattern = auto\n; support_interface_spacing = 0.5\n; support_interface_speed = 80\n; support_interface_top_layers = 2\n; support_line_width = 0.42\n; support_material_interface_fan_speed = -1\n; support_multi_bed_types = 0\n; support_object_xy_distance = 0.35\n; support_on_build_plate_only = 0\n; support_remove_small_overhang = 1\n; support_speed = 150\n; support_style = default\n; support_threshold_angle = 30\n; support_top_z_distance = 0.2\n; support_type = normal(auto)\n; temperature_vitrification = 45\n; template_custom_gcode = \n; textured_cool_plate_temp = 40\n; textured_cool_plate_temp_initial_layer = 40\n; textured_plate_temp = 60\n; textured_plate_temp_initial_layer = 60\n; thick_bridges = 0\n; thick_internal_bridges = 1\n; thumbnails = 240x240/PNG, 96x96/PNG\n; thumbnails_format = PNG\n; time_cost = 0\n; time_lapse_gcode = ;TIMELAPSE_TAKE_FRAME\\n\n; timelapse_type = 0\n; top_bottom_infill_wall_overlap = 25%\n; top_shell_layers = 5\n; top_shell_thickness = 1\n; top_solid_infill_flow_ratio = 1\n; top_surface_acceleration = 2000\n; top_surface_jerk = 9\n; top_surface_line_width = 0.42\n; top_surface_pattern = monotonicline\n; top_surface_speed = 200\n; travel_acceleration = 10000\n; travel_jerk = 12\n; travel_slope = 3\n; travel_speed = 500\n; travel_speed_z = 0\n; tree_support_adaptive_layer_height = 1\n; tree_support_angle_slow = 25\n; tree_support_auto_brim = 1\n; tree_support_branch_angle = 45\n; tree_support_branch_angle_organic = 40\n; tree_support_branch_diameter = 2\n; tree_support_branch_diameter_angle = 5\n; tree_support_branch_diameter_double_wall = 3\n; tree_support_branch_diameter_organic = 2\n; tree_support_branch_distance = 5\n; tree_support_branch_distance_organic = 1\n; tree_support_brim_width = 3\n; tree_support_tip_diameter = 0.8\n; tree_support_top_rate = 30%\n; tree_support_wall_count = 0\n; upward_compatible_machine = \n; use_firmware_retraction = 0\n; use_relative_e_distances = 1\n; wall_direction = auto\n; wall_distribution_count = 1\n; wall_filament = 1\n; wall_generator = classic\n; wall_loops = 3\n; wall_sequence = inner wall/outer wall\n; wall_transition_angle = 10\n; wall_transition_filter_deviation = 25%\n; wall_transition_length = 100%\n; wipe = 1\n; wipe_before_external_loop = 0\n; wipe_distance = 2\n; wipe_on_loops = 0\n; wipe_speed = 80%\n; wipe_tower_bridging = 10\n; wipe_tower_cone_angle = 0\n; wipe_tower_extra_flow = 100%\n; wipe_tower_extra_spacing = 100%\n; wipe_tower_filament = 0\n; wipe_tower_max_purge_speed = 90\n; wipe_tower_no_sparse_layers = 0\n; wipe_tower_rotation_angle = 0\n; wipe_tower_x = 165.000\n; wipe_tower_x = 165\n; wipe_tower_y = 250.000\n; wipe_tower_y = 250\n; wiping_volumes_extruders = 70,70,70,70,70,70,70,70,70,70\n; xy_contour_compensation = 0\n; xy_hole_compensation = 0\n; z_hop = 0.4\n; z_hop_types = Auto Lift\n; z_offset = 0\n; first_layer_bed_temperature = 60\n; bed_shape = 0x0,305x0,305x305,0x305\n; first_layer_temperature = 210\n; first_layer_height = 0.200\n; CONFIG_BLOCK_END\n\n\n"
  },
  {
    "path": "presliced_z-offset_calibration_files/Q1_Pro/z-offset_calibration_Q1_Pro_PLA_4m6s.gcode",
    "content": "; HEADER_BLOCK_START\n; generated by OrcaSlicer 2.2.0 on 2025-06-04 at 11:47:33\n; total layer number: 1\n; filament_density: 1.24\n; filament_diameter: 1.75\n; max_z_height: 0.20\n; HEADER_BLOCK_END\n\n; THUMBNAIL_BLOCK_START\n\n;\n; thumbnail begin 140x140 1064\n; iVBORw0KGgoAAAANSUhEUgAAAIwAAACMCAYAAACuwEE+AAAC5ElEQVR4Ae3dsW3jQBAFUBbkIi53BW\n; 7DidJLlKkHBapAFbg0H2jAOIKQLXG1JGd33gM+cKmBub9Dr0QPAwAAAAAAAAAAAAAAQCovLy9/Brjn\n; 7e3t7/V6/Rwz/nuAn0yH5TvH4/FjgKlbgzIfGkcUX+4NyzSOqMTGxhib49Fh0TaJLWkVbZNcjWGxEC\n; dQc1DmcUR1Zs1hcUR1ZPyfv/agWIg7sUWraJtO7Dks2qYhEQZlHkMTVMRhmbbNQAyRB8URFUwrwzKN\n; hXgHpfdA2iahFltF2+ykp2GZts1AXT0OyjyOqEoyDMt3HFFPaH2xLY2FuECmVtE2TzIsV23zCIPycw\n; zNjGG5H0fUYFCWJvURZVjKk65tMj4u106KttEq9dNt2xiW9dLVfZRB2S7NH1GGZfs0eURlvQeKkqYW\n; Yq0SJ+HbxrDES8iF2KDET5gjyrC0k12PqK2/6C51sstCrFXaz2ZtY1j6yaptY1D6TfW2MSz9p8rjt0\n; HJNzTFR5RhyZtFR5R7IBnzUNtoFZnn17YZJ+pyuTT1A8m6eeh4ciTJ+/v7sqem19dXx1PSFP9exgKc\n; K6fT6XOo4XA4fLT0g8vyVP9tr4W4z5zP53U/K6Nt+slmN9Y+C2NYiliI20u1xbaU3w63kzDfIrAQx8\n; 7qi20pC3G8hP9ukrYxLEUsxPtl8T1QFBbi7dP8+2IcUdtk98fl2izE66Xbt1Bpm/pJ8VZNbfN8ml1s\n; S/mAVnlSv+TZ4/fj6W6xLeXx+368On7GQnw7Ye+BorAQ/49WeZAPaBmWIhkX4nSPy7X5I6Es1vtCPC\n; 62A/X1uBBrlZX11DaGZUMtt43Fdict3kdplZ218sIA90DBRD6itEpQ0RZi90CNiNA2WqUxe95HGZaG\n; bbkQW2w7scV9lFbpzFoLscW2czUXYq2SRI22MSwJlSzE7oGSW3IfpVX4cu8+yuMyN91aiLUKv5ouxB\n; 6XAQAAAAAAAAAAAAAA4KZ/Yu4wU8U/g+sAAAAASUVORK5CYII=\n; thumbnail end\n; THUMBNAIL_BLOCK_END\n\n; THUMBNAIL_BLOCK_START\n\n;\n; thumbnail begin 48x48 408\n; iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAA+UlEQVR4Ae2YwQ3DIAxFGShDdI2swY\n; VrL8zBgQmYIKO14oBEUYICBGNX/0mWqp5+/L+FQSkAAABgAtu2vUIIH2vtEX8rSez7/o7i84r/KQnE\n; jpfiU7F246zrV8XOjRbxuRtqNT3C2URqVPyySMWO1QaVtRtPdp3cDQrxUwacUnhZw5FaKX4oUmmP4V\n; JNA86h691ucBZfdUOC8LJ+PoJb5u/UaZxmnLAkwv9miPNIcXLDOdd3qIk9yEo3vPcyxedQRkr0Rjr9\n; cjNrwLXWtHdksVfKnCfcYPFOZIw5xHT9ipZ9ivUzYy1S5IPai+jH3UQa8O49BgAAALjBF4+89dX6Zn\n; pSAAAAAElFTkSuQmCC\n; thumbnail end\n; THUMBNAIL_BLOCK_END\n\n; external perimeters extrusion width = 0.42mm\n; perimeters extrusion width = 0.45mm\n; infill extrusion width = 0.45mm\n; solid infill extrusion width = 0.42mm\n; top infill extrusion width = 0.42mm\n; first layer extrusion width = 0.50mm\n\n; EXECUTABLE_BLOCK_START\nEXCLUDE_OBJECT_DEFINE NAME=Cube_id_0_copy_0 CENTER=122.5,122.5 POLYGON=[[87.5,87.5],[157.5,87.5],[157.5,157.5],[87.5,157.5],[87.5,87.5]]\nM73 P0 R4\nM106 S0\nM106 P2 S0\n;TYPE:Custom\nPRINT_START BED=60 HOTEND=210 CHAMBER=0\nM83\nM140 S60\nM104 S210\nG4 P3000\nG0 X75.9292 Y75.9292 Z5 F6000\nG0 Z0.2 F600\nG1 E3 F1800\nG1 X160.929 E3.4 F3000\nG1 Y77.9292 E0.08 F3000\nM73 P1 R4\nG1 X75.9292 E3.4 F3000\nM73 P1 R4\nG1 Y160.929 E3.32 F3000\nM73 P2 R4\nG1 X77.9292 E0.08 F3000\nM73 P2 R3\nM73 P2 R4\nG1 Y78.9292 E3.28 F3000\nM73 P2 R3\nG1 X78.9292 Z0\nM73 P3 R3\nG1 X81.9292\nM73 P3 R3\nG1 Z1 F600\nM106 P3 S255\nG90\nG21\nM83 ; use relative distances for extrusion\nSET_PRESSURE_ADVANCE ADVANCE=0.042; Override pressure advance value\nM106 S0\nM106 P2 S0\n;LAYER_CHANGE\n;Z:0.2\n;HEIGHT:0.2\n;BEFORE_LAYER_CHANGE\n;0.2\nG92 E0\n\nG1 E-.8 F1800\n;TIMELAPSE_TAKE_FRAME\n\n;BEFORE_LAYER_CHANGE\n;0.2\nLOG_Z\nG92 E0\n\n;_SET_FAN_SPEED_CHANGING_LAYER\nSET_VELOCITY_LIMIT ACCEL=500 ACCEL_TO_DECEL=250\nG1 X82.846 Y83.238 F15000\nG1 Z.6\nG1 Z.2\nG1 E.8 F1800\n;TYPE:Skirt\n;WIDTH:0.5\nG1 F3000\nG1 X84.438 Y81.946 E.07635\nG1 X87.5 Y81.158 E.11778\nG1 X157.5 Y81.158 E2.60723\nG1 X159.708 Y81.555 E.08357\nM73 P4 R3\nG1 X161.64 Y82.695 E.08357\nM73 P4 R3\nG1 X163.054 Y84.438 E.08357\nG1 X163.842 Y87.5 E.11778\nG1 X163.842 Y157.5 E2.60723\nG1 X163.445 Y159.708 E.08357\nM73 P5 R3\nG1 X162.305 Y161.64 E.08357\nM73 P5 R3\nG1 X160.562 Y163.054 E.08357\nG1 X157.5 Y163.842 E.11778\nG1 X87.5 Y163.842 E2.60723\nG1 X85.292 Y163.445 E.08357\nG1 X83.36 Y162.305 E.08357\nG1 X81.946 Y160.562 E.08357\nG1 X81.158 Y157.5 E.11778\nG1 X81.158 Y87.5 E2.60723\nG1 X81.555 Y85.292 E.08357\nM73 P6 R3\nG1 X82.695 Y83.36 E.08357\nM73 P6 R3\nG1 X82.815 Y83.263 E.00572\nG1 X83.148 Y83.539 F15000\nG1 F3000\nG1 X84.871 Y82.235 E.08047\nG1 X87.5 Y81.615 E.10062\nG1 X157.5 Y81.615 E2.60723\nG1 X159.624 Y82.011 E.08047\nM73 P7 R3\nG1 X161.461 Y83.148 E.08047\nM73 P7 R3\nG1 X162.765 Y84.871 E.08047\nG1 X163.385 Y87.5 E.10062\nG1 X163.385 Y157.5 E2.60723\nG1 X162.989 Y159.624 E.08047\nG1 X161.852 Y161.461 E.08047\nG1 X160.129 Y162.765 E.08047\nG1 X157.5 Y163.385 E.10062\nG1 X87.5 Y163.385 E2.60723\nG1 X85.376 Y162.989 E.08047\nM73 P8 R3\nG1 X83.539 Y161.852 E.08047\nM73 P8 R3\nG1 X82.235 Y160.129 E.08047\nG1 X81.615 Y157.5 E.10062\nG1 X81.615 Y87.5 E2.60723\nG1 X82.011 Y85.376 E.08047\nM73 P9 R3\nG1 X83.127 Y83.573 E.07898\nM73 P9 R3\nG1 X83.529 Y83.834 F15000\nG1 F3000\nG1 X83.599 Y83.725 E.00483\nG1 X85.3 Y82.538 E.07726\nG1 X87.5 Y82.072 E.08376\nG1 X157.5 Y82.072 E2.60723\nG1 X159.536 Y82.468 E.07726\nG1 X161.275 Y83.599 E.07726\nG1 X162.462 Y85.3 E.07726\nG1 X162.928 Y87.5 E.08376\nG1 X162.928 Y157.5 E2.60723\nG1 X162.532 Y159.536 E.07726\nM73 P10 R3\nG1 X161.401 Y161.275 E.07726\nM73 P10 R3\nG1 X159.7 Y162.462 E.07726\nG1 X157.5 Y162.928 E.08376\nG1 X87.5 Y162.928 E2.60723\nG1 X85.464 Y162.532 E.07726\nM73 P11 R3\nG1 X83.725 Y161.401 E.07726\nM73 P11 R3\nG1 X82.538 Y159.7 E.07726\nG1 X82.072 Y157.5 E.08376\nG1 X82.072 Y87.5 E2.60723\nG1 X82.468 Y85.464 E.07726\nG1 X83.507 Y83.867 E.07094\nG1 X83.9 Y84.138 F15000\nG1 F3000\nG1 X84.05 Y83.921 E.00981\nG1 X85.724 Y82.857 E.0739\nG1 X87.5 Y82.529 E.06726\nG1 X157.5 Y82.529 E2.60723\nG1 X159.444 Y82.925 E.0739\nM73 P12 R3\nG1 X161.079 Y84.05 E.0739\nM73 P12 R3\nG1 X162.143 Y85.724 E.0739\nG1 X162.471 Y87.5 E.06726\nG1 X162.471 Y157.5 E2.60723\nG1 X162.075 Y159.444 E.0739\nM73 P13 R3\nG1 X160.95 Y161.079 E.0739\nM73 P13 R3\nG1 X159.276 Y162.143 E.0739\nG1 X157.5 Y162.471 E.06726\nG1 X87.5 Y162.471 E2.60723\nG1 X85.556 Y162.075 E.0739\nG1 X83.921 Y160.95 E.0739\nG1 X82.857 Y159.276 E.0739\nG1 X82.529 Y157.5 E.06726\nG1 X82.529 Y87.5 E2.60723\nG1 X82.925 Y85.556 E.0739\nM73 P14 R3\nG1 X83.878 Y84.171 E.0626\nM73 P14 R3\nG1 X84.261 Y84.452 F15000\nG1 F3000\nG1 X84.499 Y84.128 E.01498\nG1 X86.142 Y83.195 E.07039\nG1 X87.5 Y82.986 E.05116\nG1 X157.5 Y82.986 E2.60723\nG1 X159.348 Y83.382 E.07039\nM73 P15 R3\nG1 X160.872 Y84.499 E.07039\nM73 P15 R3\nG1 X161.805 Y86.142 E.07039\nG1 X162.014 Y87.5 E.05116\nG1 X162.014 Y157.5 E2.60723\nG1 X161.618 Y159.348 E.07039\nG1 X160.501 Y160.872 E.07039\nG1 X158.858 Y161.805 E.07039\nG1 X157.5 Y162.014 E.05116\nG1 X87.5 Y162.014 E2.60723\nG1 X85.652 Y161.618 E.07039\nM73 P16 R3\nG1 X84.128 Y160.501 E.07039\nM73 P16 R3\nG1 X83.195 Y158.858 E.07039\nG1 X82.986 Y157.5 E.05116\nG1 X82.986 Y87.5 E2.60723\nG1 X83.382 Y85.652 E.07039\nM73 P17 R3\nG1 X84.238 Y84.485 E.05392\nM73 P17 R3\nG1 X84.608 Y84.777 F15000\nG1 F3000\nG1 X84.946 Y84.348 E.02036\nG1 X86.552 Y83.555 E.06669\nG1 X87.5 Y83.443 E.03555\nG1 X157.5 Y83.443 E2.60723\nG1 X159.246 Y83.838 E.06669\nG1 X160.652 Y84.946 E.06669\nG1 X161.445 Y86.552 E.06669\nG1 X161.557 Y87.5 E.03555\nG1 X161.557 Y157.5 E2.60723\nG1 X161.162 Y159.246 E.06669\nM73 P18 R3\nG1 X160.054 Y160.652 E.06669\nM73 P18 R3\nG1 X158.448 Y161.445 E.06669\nG1 X157.5 Y161.557 E.03555\nG1 X87.5 Y161.557 E2.60723\nG1 X85.754 Y161.162 E.06669\nM73 P19 R3\nG1 X84.348 Y160.054 E.06669\nM73 P19 R3\nG1 X83.555 Y158.448 E.06669\nG1 X83.443 Y157.5 E.03555\nG1 X83.443 Y87.5 E2.60723\nG1 X83.838 Y85.754 E.06669\nG1 X84.583 Y84.808 E.04484\nG1 X84.938 Y85.112 F15000\nG1 F3000\nG1 X85.392 Y84.582 E.02598\nG1 X87.5 Y83.9 E.08254\nG1 X157.5 Y83.9 E2.60723\nG1 X159.138 Y84.295 E.06277\nM73 P20 R3\nG1 X160.418 Y85.392 E.06277\nM73 P20 R3\nG1 X161.1 Y87.5 E.08254\nG1 X161.1 Y157.5 E2.60723\nG1 X160.705 Y159.138 E.06277\nM73 P21 R3\nG1 X159.608 Y160.418 E.06277\nM73 P21 R3\nG1 X157.5 Y161.1 E.08254\nG1 X87.5 Y161.1 E2.60723\nG1 X85.862 Y160.705 E.06277\nG1 X84.582 Y159.608 E.06277\nG1 X83.9 Y157.5 E.08254\nG1 X83.9 Y87.5 E2.60723\nG1 X84.295 Y85.862 E.06277\nM73 P22 R3\nG1 X84.911 Y85.142 E.0353\nM73 P22 R3\nG1 X85.244 Y85.457 F15000\nG1 F3000\nG1 X85.833 Y84.836 E.03191\nG1 X87.5 Y84.357 E.06459\nG1 X157.5 Y84.357 E2.60723\nG1 X159.023 Y84.751 E.05859\nM73 P23 R3\nG1 X160.164 Y85.833 E.05859\nM73 P23 R3\nG1 X160.643 Y87.5 E.06459\nG1 X160.643 Y157.5 E2.60723\nG1 X160.249 Y159.023 E.05859\nG1 X159.167 Y160.164 E.05859\nG1 X157.5 Y160.643 E.06459\nG1 X87.5 Y160.643 E2.60723\nG1 X85.977 Y160.249 E.05859\nM73 P24 R3\nG1 X84.836 Y159.167 E.05859\nM73 P24 R3\nG1 X84.357 Y157.5 E.06459\nG1 X84.357 Y87.5 E2.60723\nG1 X84.751 Y85.977 E.05859\nM73 P25 R3\nG1 X85.216 Y85.486 E.02519\nM73 P25 R3\nG1 X85.519 Y85.812 F15000\nG1 F3000\nG1 X86.27 Y85.113 E.03821\nG1 X87.5 Y84.814 E.04715\nG1 X157.5 Y84.814 E2.60723\nG1 X158.898 Y85.207 E.05408\nG1 X159.887 Y86.27 E.05408\nG1 X160.186 Y87.5 E.04715\nG1 X160.186 Y157.5 E2.60723\nG1 X159.793 Y158.898 E.05408\nM73 P26 R3\nG1 X158.73 Y159.887 E.05408\nM73 P26 R3\nG1 X157.5 Y160.186 E.04715\nG1 X87.5 Y160.186 E2.60723\nG1 X86.102 Y159.793 E.05408\nM73 P27 R3\nG1 X85.113 Y158.73 E.05408\nM73 P27 R3\nG1 X84.814 Y157.5 E.04715\nM73 P27 R2\nG1 X84.814 Y87.5 E2.60723\nM73 P27 R2\nG1 X85.207 Y86.102 E.05408\nG1 X85.49 Y85.839 E.01439\nG1 X85.751 Y86.169 F15000\nG1 F3000\nG1 X86.698 Y85.421 E.04498\nG1 X87.5 Y85.271 E.03037\nG1 X157.5 Y85.271 E2.60723\nG1 X158.761 Y85.662 E.04917\nM73 P28 R2\nG1 X159.579 Y86.698 E.04917\nM73 P28 R2\nG1 X159.729 Y87.5 E.03037\nG1 X159.729 Y157.5 E2.60723\nG1 X159.338 Y158.761 E.04917\nM73 P29 R2\nG1 X158.302 Y159.579 E.04917\nM73 P29 R2\nG1 X157.5 Y159.729 E.03037\nG1 X87.5 Y159.729 E2.60723\nG1 X86.239 Y159.338 E.04917\nG1 X85.421 Y158.302 E.04917\nG1 X85.271 Y157.5 E.03037\nG1 X85.271 Y87.5 E2.60723\nG1 X85.662 Y86.239 E.04917\nM73 P30 R2\nG1 X85.719 Y86.194 E.0027\n;WIPE_START\nM73 P30 R2\nG1 X86.698 Y85.421 E-.49904\nG1 X87.438 Y85.283 E-.30096\n;WIPE_END\nEXCLUDE_OBJECT_START NAME=Cube_id_0_copy_0\nG1 X92.751 Y90.763 Z.6 F15000\nG1 X156.186 Y156.186 Z.6\nG1 Z.2\nG1 E.8 F1800\n;TYPE:Inner wall\nG1 F3000\nG1 X88.814 Y156.186 E2.50934\nG1 X88.814 Y88.814 E2.50934\nM73 P31 R2\nG1 X156.186 Y88.814 E2.50934\nM73 P31 R2\nG1 X156.186 Y156.126 E2.5071\nM73 P32 R2\nG1 X156.643 Y156.643 F15000\nM73 P33 R2\nM73 P32 R2\nG1 F3000\nM73 P33 R2\nG1 X88.357 Y156.643 E2.54339\nG1 X88.357 Y88.357 E2.54339\nG1 X156.643 Y88.357 E2.54339\nM73 P34 R2\nG1 X156.643 Y156.583 E2.54115\nM73 P34 R2\nG1 X157.1 Y157.1 F15000\nM73 P35 R2\n;TYPE:Outer wall\nG1 F3000\nM73 P35 R2\nG1 X87.9 Y157.1 E2.57744\nG1 X87.9 Y87.9 E2.57744\nM73 P36 R2\nG1 X157.1 Y87.9 E2.57744\nM73 P36 R2\nG1 X157.1 Y157.04 E2.5752\nM73 P37 R2\n;WIPE_START\nG1 X155.1 Y157.042 E-.8\n;WIPE_END\nM73 P37 R2\nG1 X155.208 Y149.41 Z.6 F15000\nG1 X156.049 Y89.879 Z.6\nG1 Z.2\nM73 P38 R2\nG1 E.8 F1800\n;TYPE:Bottom surface\n;WIDTH:0.501638\nM73 P38 R2\nG1 F6300\nG1 X155.327 Y89.157 E.03815\nG1 X154.678 Y89.157 E.02425\nG1 X155.843 Y90.322 E.06157\nG1 X155.843 Y90.97 E.02425\nG1 X154.03 Y89.157 E.09587\nG1 X153.381 Y89.157 E.02425\nG1 X155.843 Y91.619 E.13016\nG1 X155.843 Y92.268 E.02425\nG1 X152.732 Y89.157 E.16446\nG1 X152.083 Y89.157 E.02425\nG1 X155.843 Y92.917 E.19875\nG1 X155.843 Y93.565 E.02425\nG1 X151.435 Y89.157 E.23304\nG1 X150.786 Y89.157 E.02425\nG1 X155.843 Y94.214 E.26734\nG1 X155.843 Y94.863 E.02425\nG1 X150.137 Y89.157 E.30163\nG1 X149.488 Y89.157 E.02425\nG1 X155.843 Y95.512 E.33592\nM73 P39 R2\nG1 X155.843 Y96.16 E.02425\nM73 P39 R2\nG1 X148.84 Y89.157 E.37022\nG1 X148.191 Y89.157 E.02425\nG1 X155.843 Y96.809 E.40451\nG1 X155.843 Y97.458 E.02425\nG1 X147.542 Y89.157 E.4388\nG1 X146.894 Y89.157 E.02425\nG1 X155.843 Y98.106 E.4731\nG1 X155.843 Y98.755 E.02425\nG1 X146.245 Y89.157 E.50739\nG1 X145.596 Y89.157 E.02425\nG1 X155.843 Y99.404 E.54168\nG1 X155.843 Y100.053 E.02425\nG1 X144.947 Y89.157 E.57598\nG1 X144.299 Y89.157 E.02425\nM73 P40 R2\nG1 X155.843 Y100.701 E.61027\nM73 P40 R2\nG1 X155.843 Y101.35 E.02425\nG1 X143.65 Y89.157 E.64456\nG1 X143.001 Y89.157 E.02425\nG1 X155.843 Y101.999 E.67886\nG1 X155.843 Y102.648 E.02425\nG1 X142.352 Y89.157 E.71315\nG1 X141.704 Y89.157 E.02425\nG1 X155.843 Y103.296 E.74744\nG1 X155.843 Y103.945 E.02425\nG1 X141.055 Y89.157 E.78174\nG1 X140.406 Y89.157 E.02425\nM73 P41 R2\nG1 X155.843 Y104.594 E.81603\nM73 P41 R2\nG1 X155.843 Y105.242 E.02425\nG1 X139.758 Y89.157 E.85033\nG1 X139.109 Y89.157 E.02425\nG1 X155.843 Y105.891 E.88462\nG1 X155.843 Y106.54 E.02425\nG1 X138.46 Y89.157 E.91891\nG1 X137.811 Y89.157 E.02425\nG1 X155.843 Y107.189 E.95321\nG1 X155.843 Y107.837 E.02425\nG1 X137.163 Y89.157 E.9875\nG1 X136.514 Y89.157 E.02425\nM73 P42 R2\nG1 X155.843 Y108.486 E1.02179\nM73 P42 R2\nG1 X155.843 Y109.135 E.02425\nG1 X135.865 Y89.157 E1.05609\nG1 X135.216 Y89.157 E.02425\nG1 X155.843 Y109.784 E1.09038\nG1 X155.843 Y110.432 E.02425\nG1 X134.568 Y89.157 E1.12467\nG1 X133.919 Y89.157 E.02425\nG1 X155.843 Y111.081 E1.15897\nG1 X155.843 Y111.73 E.02425\nM73 P43 R2\nG1 X133.27 Y89.157 E1.19326\nM73 P43 R2\nG1 X132.622 Y89.157 E.02425\nG1 X155.843 Y112.378 E1.22755\nG1 X155.843 Y113.027 E.02425\nG1 X131.973 Y89.157 E1.26185\nG1 X131.324 Y89.157 E.02425\nG1 X155.843 Y113.676 E1.29614\nG1 X155.843 Y114.325 E.02425\nM73 P44 R2\nG1 X130.675 Y89.157 E1.33043\nM73 P44 R2\nG1 X130.027 Y89.157 E.02425\nG1 X155.843 Y114.973 E1.36473\nG1 X155.843 Y115.622 E.02425\nG1 X129.378 Y89.157 E1.39902\nG1 X128.729 Y89.157 E.02425\nG1 X155.843 Y116.271 E1.43331\nG1 X155.843 Y116.92 E.02425\nM73 P45 R2\nG1 X128.08 Y89.157 E1.46761\nM73 P45 R2\nG1 X127.432 Y89.157 E.02425\nG1 X155.843 Y117.568 E1.5019\nG1 X155.843 Y118.217 E.02425\nG1 X126.783 Y89.157 E1.53619\nG1 X126.134 Y89.157 E.02425\nG1 X155.843 Y118.866 E1.57049\nG1 X155.843 Y119.514 E.02425\nM73 P46 R2\nG1 X125.486 Y89.157 E1.60478\nM73 P46 R2\nG1 X124.837 Y89.157 E.02425\nG1 X155.843 Y120.163 E1.63908\nG1 X155.843 Y120.812 E.02425\nG1 X124.188 Y89.157 E1.67337\nG1 X123.539 Y89.157 E.02425\nG1 X155.843 Y121.461 E1.70766\nG1 X155.843 Y122.109 E.02425\nM73 P47 R2\nG1 X122.891 Y89.157 E1.74196\nM73 P47 R2\nG1 X122.242 Y89.157 E.02425\nG1 X155.843 Y122.758 E1.77625\nG1 X155.843 Y123.407 E.02425\nG1 X121.593 Y89.157 E1.81054\nG1 X120.945 Y89.157 E.02425\nG1 X155.843 Y124.055 E1.84484\nG1 X155.843 Y124.704 E.02425\nM73 P48 R2\nG1 X120.296 Y89.157 E1.87913\nM73 P48 R2\nG1 X119.647 Y89.157 E.02425\nG1 X155.843 Y125.353 E1.91342\nG1 X155.843 Y126.002 E.02425\nG1 X118.998 Y89.157 E1.94772\nG1 X118.35 Y89.157 E.02425\nM73 P49 R2\nG1 X155.843 Y126.65 E1.98201\nM73 P49 R2\nG1 X155.843 Y127.299 E.02425\nG1 X117.701 Y89.157 E2.0163\nG1 X117.052 Y89.157 E.02425\nG1 X155.843 Y127.948 E2.0506\nG1 X155.843 Y128.597 E.02425\nG1 X116.403 Y89.157 E2.08489\nG1 X115.755 Y89.157 E.02425\nM73 P50 R2\nG1 X155.843 Y129.245 E2.11918\nM73 P50 R2\nG1 X155.843 Y129.894 E.02425\nG1 X115.106 Y89.157 E2.15348\nG1 X114.457 Y89.157 E.02425\nG1 X155.843 Y130.543 E2.18777\nG1 X155.843 Y131.191 E.02425\nM73 P51 R2\nG1 X113.809 Y89.157 E2.22206\nM73 P51 R2\nG1 X113.16 Y89.157 E.02425\nM73 P51 R1\nG1 X155.843 Y131.84 E2.25636\nM73 P51 R1\nG1 X155.843 Y132.489 E.02425\nG1 X112.511 Y89.157 E2.29065\nG1 X111.862 Y89.157 E.02425\nM73 P52 R1\nG1 X155.843 Y133.138 E2.32494\nM73 P52 R1\nG1 X155.843 Y133.786 E.02425\nG1 X111.214 Y89.157 E2.35924\nG1 X110.565 Y89.157 E.02425\nG1 X155.843 Y134.435 E2.39353\nG1 X155.843 Y135.084 E.02425\nM73 P53 R1\nG1 X109.916 Y89.157 E2.42783\nM73 P53 R1\nG1 X109.267 Y89.157 E.02425\nG1 X155.843 Y135.733 E2.46212\nG1 X155.843 Y136.381 E.02425\nG1 X108.619 Y89.157 E2.49641\nG1 X107.97 Y89.157 E.02425\nM73 P54 R1\nG1 X155.843 Y137.03 E2.53071\nM73 P54 R1\nG1 X155.843 Y137.679 E.02425\nG1 X107.321 Y89.157 E2.565\nG1 X106.673 Y89.157 E.02425\nG1 X155.843 Y138.327 E2.59929\nG1 X155.843 Y138.976 E.02425\nM73 P55 R1\nG1 X106.024 Y89.157 E2.63359\nM73 P55 R1\nG1 X105.375 Y89.157 E.02425\nG1 X155.843 Y139.625 E2.66788\nG1 X155.843 Y140.274 E.02425\nM73 P56 R1\nG1 X104.726 Y89.157 E2.70217\nM73 P56 R1\nG1 X104.078 Y89.157 E.02425\nG1 X155.843 Y140.922 E2.73647\nG1 X155.843 Y141.571 E.02425\nG1 X103.429 Y89.157 E2.77076\nG1 X102.78 Y89.157 E.02425\nM73 P57 R1\nG1 X155.843 Y142.22 E2.80505\nM73 P57 R1\nG1 X155.843 Y142.869 E.02425\nG1 X102.131 Y89.157 E2.83935\nG1 X101.483 Y89.157 E.02425\nG1 X155.843 Y143.517 E2.87364\nG1 X155.843 Y144.166 E.02425\nM73 P58 R1\nG1 X100.834 Y89.157 E2.90793\nM73 P58 R1\nG1 X100.185 Y89.157 E.02425\nG1 X155.843 Y144.815 E2.94223\nG1 X155.843 Y145.463 E.02425\nM73 P59 R1\nG1 X99.537 Y89.157 E2.97652\nM73 P59 R1\nG1 X98.888 Y89.157 E.02425\nG1 X155.843 Y146.112 E3.01081\nG1 X155.843 Y146.761 E.02425\nG1 X98.239 Y89.157 E3.04511\nG1 X97.59 Y89.157 E.02425\nM73 P60 R1\nG1 X155.843 Y147.41 E3.0794\nM73 P60 R1\nG1 X155.843 Y148.058 E.02425\nG1 X96.942 Y89.157 E3.1137\nG1 X96.293 Y89.157 E.02425\nM73 P61 R1\nG1 X155.843 Y148.707 E3.14799\nM73 P61 R1\nG1 X155.843 Y149.356 E.02425\nG1 X95.644 Y89.157 E3.18228\nG1 X94.996 Y89.157 E.02425\nG1 X155.843 Y150.004 E3.21658\nM73 P62 R1\nG1 X155.843 Y150.653 E.02425\nM73 P62 R1\nG1 X94.347 Y89.157 E3.25087\nG1 X93.698 Y89.157 E.02425\nG1 X155.843 Y151.302 E3.28516\nG1 X155.843 Y151.951 E.02425\nM73 P63 R1\nG1 X93.049 Y89.157 E3.31946\nM73 P63 R1\nG1 X92.401 Y89.157 E.02425\nG1 X155.843 Y152.599 E3.35375\nG1 X155.843 Y153.248 E.02425\nM73 P64 R1\nG1 X91.752 Y89.157 E3.38804\nM73 P64 R1\nG1 X91.103 Y89.157 E.02425\nG1 X155.843 Y153.897 E3.42234\nG1 X155.843 Y154.546 E.02425\nM73 P65 R1\nG1 X90.454 Y89.157 E3.45663\nM73 P65 R1\nG1 X89.806 Y89.157 E.02425\nG1 X155.843 Y155.194 E3.49092\nG1 X155.843 Y155.843 E.02425\nG1 X89.157 Y89.157 E3.52522\nG1 X89.157 Y89.806 E.02425\nM73 P66 R1\nG1 X155.194 Y155.843 E3.49093\nM73 P66 R1\nG1 X154.546 Y155.843 E.02425\nG1 X89.157 Y90.454 E3.45663\nG1 X89.157 Y91.103 E.02425\nM73 P67 R1\nG1 X153.897 Y155.843 E3.42234\nM73 P67 R1\nG1 X153.248 Y155.843 E.02425\nG1 X89.157 Y91.752 E3.38805\nG1 X89.157 Y92.401 E.02425\nM73 P68 R1\nG1 X152.599 Y155.843 E3.35375\nM73 P68 R1\nG1 X151.951 Y155.843 E.02425\nG1 X89.157 Y93.049 E3.31946\nG1 X89.157 Y93.698 E.02425\nM73 P69 R1\nG1 X151.302 Y155.843 E3.28516\nM73 P69 R1\nG1 X150.653 Y155.843 E.02425\nG1 X89.157 Y94.347 E3.25087\nG1 X89.157 Y94.995 E.02425\nG1 X150.005 Y155.843 E3.21658\nG1 X149.356 Y155.843 E.02425\nM73 P70 R1\nG1 X89.157 Y95.644 E3.18228\nM73 P70 R1\nG1 X89.157 Y96.293 E.02425\nG1 X148.707 Y155.843 E3.14799\nG1 X148.058 Y155.843 E.02425\nM73 P71 R1\nG1 X89.157 Y96.942 E3.1137\nM73 P71 R1\nG1 X89.157 Y97.59 E.02425\nG1 X147.41 Y155.843 E3.0794\nG1 X146.761 Y155.843 E.02425\nM73 P72 R1\nG1 X89.157 Y98.239 E3.04511\nM73 P72 R1\nG1 X89.157 Y98.888 E.02425\nG1 X146.112 Y155.843 E3.01082\nG1 X145.463 Y155.843 E.02425\nG1 X89.157 Y99.537 E2.97652\nG1 X89.157 Y100.185 E.02425\nM73 P73 R1\nG1 X144.815 Y155.843 E2.94223\nM73 P73 R1\nG1 X144.166 Y155.843 E.02425\nG1 X89.157 Y100.834 E2.90794\nG1 X89.157 Y101.483 E.02425\nM73 P74 R1\nG1 X143.517 Y155.843 E2.87364\nM73 P74 R1\nG1 X142.869 Y155.843 E.02425\nG1 X89.157 Y102.131 E2.83935\nG1 X89.157 Y102.78 E.02425\nG1 X142.22 Y155.843 E2.80506\nG1 X141.571 Y155.843 E.02425\nM73 P75 R1\nG1 X89.157 Y103.429 E2.77076\nM73 P75 R1\nG1 X89.157 Y104.078 E.02425\nG1 X140.922 Y155.843 E2.73647\nG1 X140.274 Y155.843 E.02425\nM73 P75 R0\nG1 X89.157 Y104.726 E2.70218\nM73 P75 R0\nG1 X89.157 Y105.375 E.02425\nM73 P76 R0\nG1 X139.625 Y155.843 E2.66788\nM73 P76 R0\nG1 X138.976 Y155.843 E.02425\nG1 X89.157 Y106.024 E2.63359\nG1 X89.157 Y106.673 E.02425\nM73 P77 R0\nG1 X138.327 Y155.843 E2.59929\nM73 P77 R0\nG1 X137.679 Y155.843 E.02425\nG1 X89.157 Y107.321 E2.565\nG1 X89.157 Y107.97 E.02425\nG1 X137.03 Y155.843 E2.53071\nG1 X136.381 Y155.843 E.02425\nM73 P78 R0\nG1 X89.157 Y108.619 E2.49641\nM73 P78 R0\nG1 X89.157 Y109.267 E.02425\nG1 X135.733 Y155.843 E2.46212\nG1 X135.084 Y155.843 E.02425\nG1 X89.157 Y109.916 E2.42783\nG1 X89.157 Y110.565 E.02425\nM73 P79 R0\nG1 X134.435 Y155.843 E2.39353\nM73 P79 R0\nG1 X133.786 Y155.843 E.02425\nG1 X89.157 Y111.214 E2.35924\nG1 X89.157 Y111.862 E.02425\nG1 X133.138 Y155.843 E2.32495\nG1 X132.489 Y155.843 E.02425\nM73 P80 R0\nG1 X89.157 Y112.511 E2.29065\nM73 P80 R0\nG1 X89.157 Y113.16 E.02425\nG1 X131.84 Y155.843 E2.25636\nG1 X131.191 Y155.843 E.02425\nG1 X89.157 Y113.809 E2.22207\nG1 X89.157 Y114.457 E.02425\nM73 P81 R0\nG1 X130.543 Y155.843 E2.18777\nM73 P81 R0\nG1 X129.894 Y155.843 E.02425\nG1 X89.157 Y115.106 E2.15348\nG1 X89.157 Y115.755 E.02425\nG1 X129.245 Y155.843 E2.11919\nG1 X128.597 Y155.843 E.02425\nM73 P82 R0\nG1 X89.157 Y116.403 E2.08489\nM73 P82 R0\nG1 X89.157 Y117.052 E.02425\nG1 X127.948 Y155.843 E2.0506\nG1 X127.299 Y155.843 E.02425\nG1 X89.157 Y117.701 E2.01631\nG1 X89.157 Y118.35 E.02425\nM73 P83 R0\nG1 X126.65 Y155.843 E1.98201\nM73 P83 R0\nG1 X126.002 Y155.843 E.02425\nG1 X89.157 Y118.998 E1.94772\nG1 X89.157 Y119.647 E.02425\nG1 X125.353 Y155.843 E1.91343\nG1 X124.704 Y155.843 E.02425\nG1 X89.157 Y120.296 E1.87913\nG1 X89.157 Y120.944 E.02425\nM73 P84 R0\nG1 X124.056 Y155.843 E1.84484\nM73 P84 R0\nG1 X123.407 Y155.843 E.02425\nG1 X89.157 Y121.593 E1.81054\nG1 X89.157 Y122.242 E.02425\nG1 X122.758 Y155.843 E1.77625\nG1 X122.109 Y155.843 E.02425\nM73 P85 R0\nG1 X89.157 Y122.891 E1.74196\nM73 P85 R0\nG1 X89.157 Y123.539 E.02425\nG1 X121.461 Y155.843 E1.70766\nG1 X120.812 Y155.843 E.02425\nG1 X89.157 Y124.188 E1.67337\nG1 X89.157 Y124.837 E.02425\nG1 X120.163 Y155.843 E1.63908\nG1 X119.514 Y155.843 E.02425\nM73 P86 R0\nG1 X89.157 Y125.486 E1.60478\nM73 P86 R0\nG1 X89.157 Y126.134 E.02425\nG1 X118.866 Y155.843 E1.57049\nG1 X118.217 Y155.843 E.02425\nG1 X89.157 Y126.783 E1.5362\nG1 X89.157 Y127.432 E.02425\nG1 X117.568 Y155.843 E1.5019\nG1 X116.92 Y155.843 E.02425\nM73 P87 R0\nG1 X89.157 Y128.08 E1.46761\nM73 P87 R0\nG1 X89.157 Y128.729 E.02425\nG1 X116.271 Y155.843 E1.43332\nG1 X115.622 Y155.843 E.02425\nG1 X89.157 Y129.378 E1.39902\nG1 X89.157 Y130.027 E.02425\nG1 X114.973 Y155.843 E1.36473\nG1 X114.325 Y155.843 E.02425\nM73 P88 R0\nG1 X89.157 Y130.675 E1.33044\nM73 P88 R0\nG1 X89.157 Y131.324 E.02425\nG1 X113.676 Y155.843 E1.29614\nG1 X113.027 Y155.843 E.02425\nG1 X89.157 Y131.973 E1.26185\nG1 X89.157 Y132.622 E.02425\nG1 X112.378 Y155.843 E1.22756\nG1 X111.73 Y155.843 E.02425\nG1 X89.157 Y133.27 E1.19326\nG1 X89.157 Y133.919 E.02425\nM73 P89 R0\nG1 X111.081 Y155.843 E1.15897\nM73 P89 R0\nG1 X110.432 Y155.843 E.02425\nG1 X89.157 Y134.568 E1.12468\nG1 X89.157 Y135.216 E.02425\nG1 X109.784 Y155.843 E1.09038\nG1 X109.135 Y155.843 E.02425\nG1 X89.157 Y135.865 E1.05609\nG1 X89.157 Y136.514 E.02425\nG1 X108.486 Y155.843 E1.02179\nM73 P90 R0\nG1 X107.837 Y155.843 E.02425\nM73 P90 R0\nG1 X89.157 Y137.163 E.9875\nG1 X89.157 Y137.811 E.02425\nG1 X107.189 Y155.843 E.95321\nG1 X106.54 Y155.843 E.02425\nG1 X89.157 Y138.46 E.91891\nG1 X89.157 Y139.109 E.02425\nG1 X105.891 Y155.843 E.88462\nG1 X105.242 Y155.843 E.02425\nG1 X89.157 Y139.758 E.85033\nG1 X89.157 Y140.406 E.02425\nM73 P91 R0\nG1 X104.594 Y155.843 E.81603\nM73 P91 R0\nG1 X103.945 Y155.843 E.02425\nG1 X89.157 Y141.055 E.78174\nG1 X89.157 Y141.704 E.02425\nG1 X103.296 Y155.843 E.74745\nG1 X102.648 Y155.843 E.02425\nG1 X89.157 Y142.352 E.71315\nG1 X89.157 Y143.001 E.02425\nG1 X101.999 Y155.843 E.67886\nG1 X101.35 Y155.843 E.02425\nG1 X89.157 Y143.65 E.64457\nG1 X89.157 Y144.299 E.02425\nM73 P92 R0\nG1 X100.701 Y155.843 E.61027\nM73 P92 R0\nG1 X100.053 Y155.843 E.02425\nG1 X89.157 Y144.947 E.57598\nG1 X89.157 Y145.596 E.02425\nG1 X99.404 Y155.843 E.54169\nG1 X98.755 Y155.843 E.02425\nG1 X89.157 Y146.245 E.50739\nG1 X89.157 Y146.893 E.02425\nG1 X98.107 Y155.843 E.4731\nG1 X97.458 Y155.843 E.02425\nG1 X89.157 Y147.542 E.43881\nG1 X89.157 Y148.191 E.02425\nG1 X96.809 Y155.843 E.40451\nM73 P93 R0\nG1 X96.16 Y155.843 E.02425\nM73 P93 R0\nG1 X89.157 Y148.84 E.37022\nG1 X89.157 Y149.488 E.02425\nG1 X95.512 Y155.843 E.33592\nG1 X94.863 Y155.843 E.02425\nG1 X89.157 Y150.137 E.30163\nG1 X89.157 Y150.786 E.02425\nG1 X94.214 Y155.843 E.26734\nG1 X93.565 Y155.843 E.02425\nG1 X89.157 Y151.435 E.23304\nG1 X89.157 Y152.083 E.02425\nG1 X92.917 Y155.843 E.19875\nG1 X92.268 Y155.843 E.02425\nG1 X89.157 Y152.732 E.16446\nG1 X89.157 Y153.381 E.02425\nG1 X91.619 Y155.843 E.13016\nG1 X90.971 Y155.843 E.02425\nG1 X89.157 Y154.029 E.09587\nG1 X89.157 Y154.678 E.02425\nG1 X90.322 Y155.843 E.06158\nM73 P94 R0\nG1 X89.673 Y155.843 E.02425\nM73 P94 R0\nG1 X88.951 Y155.121 E.03816\nG1 E-.22857 F1800\n;WIPE_START\nG1 F6300\nG1 X89.673 Y155.843 E-.29165\nG1 X90.322 Y155.843 E-.18535\nG1 X90.088 Y155.609 E-.09443\n;WIPE_END\nEXCLUDE_OBJECT_END NAME=Cube_id_0_copy_0\nM106 S0\nM106 P2 S0\n;TYPE:Custom\nM141 S0\nM104 S0\nM140 S0\nG1 E-3 F1800\nG0 Z3.2 F600\nG0 X0 Y0 F12000\nG1 Z130 F600\nM106 P3 S0\nM73 P100 R0\n; EXECUTABLE_BLOCK_END\n\n; filament used [mm] = 525.65\n; filament used [cm3] = 1.26\n; filament used [g] = 1.57\n; filament cost = 0.03\n; total filament used [g] = 1.57\n; total filament cost = 0.03\n; total layers count = 1\n; estimated printing time (normal mode) = 4m 6s\n\n; CONFIG_BLOCK_START\n; accel_to_decel_enable = 1\n; accel_to_decel_factor = 50%\n; activate_air_filtration = 1\n; activate_chamber_temp_control = 0\n; adaptive_bed_mesh_margin = 0\n; adaptive_pressure_advance = 0\n; adaptive_pressure_advance_bridges = 0\n; adaptive_pressure_advance_model = \"0,0,0\\n0,0,0\"\n; adaptive_pressure_advance_overhangs = 0\n; additional_cooling_fan_speed = 0\n; alternate_extra_wall = 0\n; auxiliary_fan = 1\n; bbl_calib_mark_logo = 1\n; bbl_use_printhost = 0\n; bed_custom_model = \n; bed_custom_texture = \n; bed_exclude_area = 25x245,25x240,115x240,115x245,208x245,208x240,245x240,245x245,208x245\n; bed_mesh_max = 99999,99999\n; bed_mesh_min = -99999,-99999\n; bed_mesh_probe_distance = 50,50\n; before_layer_change_gcode = ;BEFORE_LAYER_CHANGE\\n;[layer_z]\\nG92 E0\\n\n; best_object_pos = 0.5,0.5\n; bottom_shell_layers = 3\n; bottom_shell_thickness = 0\n; bottom_solid_infill_flow_ratio = 1\n; bottom_surface_pattern = monotonic\n; bridge_acceleration = 50%\n; bridge_angle = 0\n; bridge_density = 100%\n; bridge_flow = 1\n; bridge_no_support = 0\n; bridge_speed = 50\n; brim_ears_detection_length = 1\n; brim_ears_max_angle = 125\n; brim_object_gap = 0.1\n; brim_type = auto_brim\n; brim_width = 5\n; chamber_temperature = 0\n; change_extrusion_role_gcode = \n; change_filament_gcode = \n; close_fan_the_first_x_layers = 1\n; complete_print_exhaust_fan_speed = 0\n; cool_plate_temp = 60\n; cool_plate_temp_initial_layer = 60\n; cooling_tube_length = 5\n; cooling_tube_retraction = 91.5\n; counterbore_hole_bridging = none\n; curr_bed_type = High Temp Plate\n; default_acceleration = 10000\n; default_filament_colour = \"\"\n; default_filament_profile = \"Qidi Generic PLA @Qidi Q1 Pro 0.4 nozzle\"\n; default_jerk = 0\n; default_print_profile = 0.20mm Standard @Qidi Q1 Pro\n; deretraction_speed = 0\n; detect_narrow_internal_solid_infill = 1\n; detect_overhang_wall = 1\n; detect_thin_wall = 0\n; different_settings_to_system = only_one_wall_top;skirt_loops;wall_loops;;thumbnails\n; disable_m73 = 0\n; dont_filter_internal_bridges = disabled\n; dont_slow_down_outer_wall = 1\n; draft_shield = disabled\n; during_print_exhaust_fan_speed = 100\n; elefant_foot_compensation = 0.15\n; elefant_foot_compensation_layers = 1\n; emit_machine_limits_to_gcode = 1\n; enable_arc_fitting = 0\n; enable_filament_ramming = 1\n; enable_long_retraction_when_cut = 0\n; enable_overhang_bridge_fan = 0\n; enable_overhang_speed = 1\n; enable_pressure_advance = 1\n; enable_prime_tower = 0\n; enable_support = 0\n; enforce_support_layers = 0\n; eng_plate_temp = 60\n; eng_plate_temp_initial_layer = 60\n; ensure_vertical_shell_thickness = ensure_all\n; exclude_object = 1\n; extra_loading_move = -2\n; extra_perimeters_on_overhangs = 0\n; extruder_clearance_height_to_lid = 120\n; extruder_clearance_height_to_rod = 40\n; extruder_clearance_radius = 70\n; extruder_colour = #C0C0C0\n; extruder_offset = 0x0\n; fan_cooling_layer_time = 60\n; fan_kickstart = 0\n; fan_max_speed = 100\n; fan_min_speed = 100\n; fan_speedup_overhangs = 1\n; fan_speedup_time = 0\n; filament_colour = #C0C0C0\n; filament_cooling_final_speed = 3.4\n; filament_cooling_initial_speed = 2.2\n; filament_cooling_moves = 4\n; filament_cost = 20\n; filament_density = 1.24\n; filament_diameter = 1.75\n; filament_end_gcode = \" \"\n; filament_flow_ratio = 0.98\n; filament_ids = GFB99\n; filament_is_support = 0\n; filament_loading_speed = 28\n; filament_loading_speed_start = 3\n; filament_max_volumetric_speed = 14\n; filament_minimal_purge_on_wipe_tower = 15\n; filament_multitool_ramming = 0\n; filament_multitool_ramming_flow = 10\n; filament_multitool_ramming_volume = 10\n; filament_notes = \"\"\n; filament_ramming_parameters = \"120 100 6.6 6.8 7.2 7.6 7.9 8.2 8.7 9.4 9.9 10.0| 0.05 6.6 0.45 6.8 0.95 7.8 1.45 8.3 1.95 9.7 2.45 10 2.95 7.6 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6\"\n; filament_settings_id = \"Qidi Generic PLA @Qidi Q1 Pro 0.4 nozzle\"\n; filament_shrink = 100%\n; filament_shrinkage_compensation_z = 100%\n; filament_soluble = 0\n; filament_stamping_distance = 0\n; filament_stamping_loading_speed = 0\n; filament_start_gcode = \" \"\n; filament_toolchange_delay = 0\n; filament_type = PLA\n; filament_unloading_speed = 90\n; filament_unloading_speed_start = 100\n; filament_vendor = QIDI\n; filename_format = {input_filename_base}_{filament_type[0]}_{print_time}.gcode\n; filter_out_gap_fill = 2\n; first_layer_print_sequence = 0\n; flush_into_infill = 0\n; flush_into_objects = 0\n; flush_into_support = 1\n; flush_multiplier = 1\n; flush_volumes_matrix = 0\n; flush_volumes_vector = 140,140\n; full_fan_speed_layer = 3\n; fuzzy_skin = none\n; fuzzy_skin_first_layer = 0\n; fuzzy_skin_point_distance = 0.8\n; fuzzy_skin_thickness = 0.3\n; gap_fill_target = nowhere\n; gap_infill_speed = 250\n; gcode_add_line_number = 0\n; gcode_comments = 0\n; gcode_flavor = klipper\n; gcode_label_objects = 0\n; has_scarf_joint_seam = 0\n; head_wrap_detect_zone = \n; high_current_on_filament_swap = 0\n; hole_to_polyhole = 0\n; hole_to_polyhole_threshold = 0.01\n; hole_to_polyhole_twisted = 1\n; host_type = octoprint\n; hot_plate_temp = 60\n; hot_plate_temp_initial_layer = 60\n; idle_temperature = 0\n; independent_support_layer_height = 0\n; infill_anchor = 400%\n; infill_anchor_max = 20\n; infill_combination = 0\n; infill_combination_max_layer_height = 100%\n; infill_direction = 45\n; infill_jerk = 9\n; infill_wall_overlap = 15%\n; inherits_group = ;;\"Qidi Q1 Pro 0.4 nozzle\"\n; initial_layer_acceleration = 500\n; initial_layer_infill_speed = 105\n; initial_layer_jerk = 9\n; initial_layer_line_width = 0.5\n; initial_layer_min_bead_width = 85%\n; initial_layer_print_height = 0.2\n; initial_layer_speed = 50\n; initial_layer_travel_speed = 50%\n; inner_wall_acceleration = 5000\n; inner_wall_jerk = 9\n; inner_wall_line_width = 0.45\n; inner_wall_speed = 300\n; interface_shells = 0\n; interlocking_beam = 0\n; interlocking_beam_layer_count = 2\n; interlocking_beam_width = 0.8\n; interlocking_boundary_avoidance = 2\n; interlocking_depth = 2\n; interlocking_orientation = 22.5\n; internal_bridge_flow = 1\n; internal_bridge_speed = 50\n; internal_solid_infill_acceleration = 100%\n; internal_solid_infill_line_width = 0.42\n; internal_solid_infill_pattern = zig-zag\n; internal_solid_infill_speed = 250\n; ironing_angle = -1\n; ironing_flow = 10%\n; ironing_pattern = zig-zag\n; ironing_spacing = 0.15\n; ironing_speed = 30\n; ironing_type = no ironing\n; is_infill_first = 0\n; layer_change_gcode = ;BEFORE_LAYER_CHANGE\\n;[layer_z]\\nLOG_Z\\nG92 E0\\n\n; layer_height = 0.2\n; line_width = 0.42\n; long_retractions_when_cut = 0\n; machine_end_gcode = M141 S0\\nM104 S0\\nM140 S0\\nG1 E-3 F1800\\nG0 Z{min(max_print_height, max_layer_z + 3)} F600\\nG0 X0 Y0 F12000\\n{if max_layer_z < max_print_height / 2}G1 Z{max_print_height / 2 + 10} F600{else}G1 Z{min(max_print_height, max_layer_z + 3)}{endif}\n; machine_load_filament_time = 0\n; machine_max_acceleration_e = 5000\n; machine_max_acceleration_extruding = 20000\n; machine_max_acceleration_retracting = 5000\n; machine_max_acceleration_travel = 0,0\n; machine_max_acceleration_x = 20000\n; machine_max_acceleration_y = 20000\n; machine_max_acceleration_z = 500\n; machine_max_jerk_e = 2\n; machine_max_jerk_x = 8\n; machine_max_jerk_y = 8\n; machine_max_jerk_z = 3\n; machine_max_speed_e = 30\n; machine_max_speed_x = 600\n; machine_max_speed_y = 600\n; machine_max_speed_z = 10\n; machine_min_extruding_rate = 0\n; machine_min_travel_rate = 0\n; machine_pause_gcode = M0\n; machine_start_gcode = PRINT_START BED=[hot_plate_temp_initial_layer] HOTEND=[nozzle_temperature_initial_layer] CHAMBER=[chamber_temperature]\\nM83\\nM140 S[hot_plate_temp_initial_layer]\\nM104 S[nozzle_temperature_initial_layer]\\nG4 P3000\\nG0 X{max((min(print_bed_max[0], first_layer_print_min[0] + 80) - 85),0)} Y{max((min(print_bed_max[1] - 5, first_layer_print_min[1] + 80) - 85), 0)} Z5 F6000\\nG0 Z[initial_layer_print_height] F600\\nG1 E3 F1800\\nG1 X{(min(print_bed_max[0], first_layer_print_min[0] + 80))} E{85 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\\nG1 Y{max((min(print_bed_max[1] - 5, first_layer_print_min[1] + 80) - 85), 0) + 2} E{2 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\\nG1 X{max((min(print_bed_max[0], first_layer_print_min[0] + 80) - 85), 0)} E{85 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\\nG1 Y{max((min(print_bed_max[1] - 5, first_layer_print_min[1] + 80) - 85), 0) + 85} E{83 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\\nG1 X{max((min(print_bed_max[0], first_layer_print_min[0] + 80) - 85), 0) + 2} E{2 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\\nG1 Y{max((min(print_bed_max[1] - 5, first_layer_print_min[1] + 80) - 85), 0) + 3} E{82 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\\nG1 X{max((min(print_bed_max[0], first_layer_print_min[0] + 80) - 85), 0) + 3} Z0\\nG1 X{max((min(print_bed_max[0], first_layer_print_min[0] + 80) - 85), 0) + 6}\\nG1 Z1 F600\\n\n; machine_tool_change_time = 0\n; machine_unload_filament_time = 0\n; make_overhang_printable = 0\n; make_overhang_printable_angle = 55\n; make_overhang_printable_hole_size = 0\n; manual_filament_change = 0\n; max_bridge_length = 10\n; max_layer_height = 0.28\n; max_travel_detour_distance = 0\n; max_volumetric_extrusion_rate_slope = 0\n; max_volumetric_extrusion_rate_slope_segment_length = 3\n; min_bead_width = 85%\n; min_feature_size = 25%\n; min_layer_height = 0.08\n; min_length_factor = 0.5\n; min_skirt_length = 0\n; min_width_top_surface = 300%\n; minimum_sparse_infill_area = 15\n; mmu_segmented_region_interlocking_depth = 0\n; mmu_segmented_region_max_width = 0\n; notes = If you want to use Orca's chamber temperature control feature, check that printer.cfg has added the following M191 macro.\\nTo add it: go to Fluidd web interface--configuration, copy the following code to the top of the printer.cfg document, SAVE&RESATART  \\n\\n[gcode_macro M191]\\ngcode:\\n    {% set s = params.S|float %}\\n    {% if s == 0 %}\\n        # If target temperature is 0, do nothing\\n        M117 Chamber heating cancelled\\n    {% else %}\\n        SET_HEATER_TEMPERATURE HEATER=chamber_heater TARGET={s}\\n        # Orca: uncomment the following line if you want to use heat bed to assist chamber heating\\n        M140 S90\\n        TEMPERATURE_WAIT SENSOR=\\\"heater_generic chamber_heater\\\" MINIMUM={s-1} MAXIMUM={s+1}\\n        M117 Chamber at target temperature\\n    {% endif %}\n; nozzle_diameter = 0.4\n; nozzle_height = 2.5\n; nozzle_hrc = 0\n; nozzle_temperature = 210\n; nozzle_temperature_initial_layer = 210\n; nozzle_temperature_range_high = 240\n; nozzle_temperature_range_low = 190\n; nozzle_type = hardened_steel\n; nozzle_volume = 0\n; only_one_wall_first_layer = 0\n; only_one_wall_top = 0\n; ooze_prevention = 0\n; other_layers_print_sequence = 0\n; other_layers_print_sequence_nums = 0\n; outer_wall_acceleration = 3000\n; outer_wall_jerk = 9\n; outer_wall_line_width = 0.42\n; outer_wall_speed = 200\n; overhang_1_4_speed = 0\n; overhang_2_4_speed = 50\n; overhang_3_4_speed = 30\n; overhang_4_4_speed = 10\n; overhang_fan_speed = 100\n; overhang_fan_threshold = 95%\n; overhang_reverse = 0\n; overhang_reverse_internal_only = 0\n; overhang_reverse_threshold = 50%\n; overhang_speed_classic = 0\n; parking_pos_retraction = 92\n; pellet_flow_coefficient = 0.4157\n; pellet_modded_printer = 0\n; post_process = \n; precise_outer_wall = 0\n; precise_z_height = 0\n; preferred_orientation = 0\n; preheat_steps = 1\n; preheat_time = 30\n; pressure_advance = 0.042\n; prime_tower_brim_width = 3\n; prime_tower_width = 35\n; prime_volume = 45\n; print_compatible_printers = \"Qidi Q1 Pro 0.4 nozzle\"\n; print_flow_ratio = 1\n; print_order = default\n; print_sequence = by layer\n; print_settings_id = 0.20mm Standard @Qidi Q1 Pro\n; printable_area = 0x0,245x0,245x245,0x245\n; printable_height = 240\n; printer_model = Qidi Q1 Pro\n; printer_notes = \n; printer_settings_id = Qidi Q1 Pro 0.4 nozzle - Copy\n; printer_structure = undefine\n; printer_technology = FFF\n; printer_variant = 0.4\n; printhost_authorization_type = key\n; printhost_ssl_ignore_revoke = 0\n; printing_by_object_gcode = \n; purge_in_prime_tower = 1\n; raft_contact_distance = 0.1\n; raft_expansion = 1.5\n; raft_first_layer_density = 90%\n; raft_first_layer_expansion = 2\n; raft_layers = 0\n; reduce_crossing_wall = 0\n; reduce_fan_stop_start_freq = 1\n; reduce_infill_retraction = 1\n; required_nozzle_HRC = 0\n; resolution = 0.012\n; retract_before_wipe = 0%\n; retract_length_toolchange = 2\n; retract_lift_above = 0\n; retract_lift_below = 0\n; retract_lift_enforce = All Surfaces\n; retract_restart_extra = 0\n; retract_restart_extra_toolchange = 0\n; retract_when_changing_layer = 1\n; retraction_distances_when_cut = 18\n; retraction_length = 0.8\n; retraction_minimum_travel = 1\n; retraction_speed = 30\n; role_based_wipe_speed = 1\n; rotate_solid_infill_direction = 1\n; scan_first_layer = 0\n; scarf_angle_threshold = 155\n; scarf_joint_flow_ratio = 1\n; scarf_joint_speed = 100%\n; scarf_overhang_threshold = 40%\n; seam_gap = 15%\n; seam_position = aligned\n; seam_slope_conditional = 0\n; seam_slope_entire_loop = 0\n; seam_slope_inner_walls = 0\n; seam_slope_min_length = 20\n; seam_slope_start_height = 0\n; seam_slope_steps = 10\n; seam_slope_type = none\n; silent_mode = 0\n; single_extruder_multi_material = 1\n; single_extruder_multi_material_priming = 0\n; skirt_distance = 2\n; skirt_height = 1\n; skirt_loops = 10\n; skirt_speed = 50\n; skirt_start_angle = -135\n; skirt_type = combined\n; slice_closing_radius = 0.049\n; slicing_mode = regular\n; slow_down_for_layer_cooling = 1\n; slow_down_layer_time = 8\n; slow_down_layers = 0\n; slow_down_min_speed = 20\n; slowdown_for_curled_perimeters = 1\n; small_area_infill_flow_compensation = 0\n; small_area_infill_flow_compensation_model = 0,0;\"\\n0.2,0.4444\";\"\\n0.4,0.6145\";\"\\n0.6,0.7059\";\"\\n0.8,0.7619\";\"\\n1.5,0.8571\";\"\\n2,0.8889\";\"\\n3,0.9231\";\"\\n5,0.9520\";\"\\n10,1\"\n; small_perimeter_speed = 50%\n; small_perimeter_threshold = 4\n; solid_infill_direction = 45\n; solid_infill_filament = 1\n; sparse_infill_acceleration = 100%\n; sparse_infill_density = 15%\n; sparse_infill_filament = 1\n; sparse_infill_line_width = 0.45\n; sparse_infill_pattern = grid\n; sparse_infill_speed = 270\n; spiral_mode = 0\n; spiral_mode_max_xy_smoothing = 200%\n; spiral_mode_smooth = 0\n; staggered_inner_seams = 0\n; standby_temperature_delta = -5\n; start_end_points = 30x-3,54x245\n; support_air_filtration = 1\n; support_angle = 0\n; support_base_pattern = default\n; support_base_pattern_spacing = 2.5\n; support_bottom_interface_spacing = 0.5\n; support_bottom_z_distance = 0.2\n; support_chamber_temp_control = 1\n; support_critical_regions_only = 0\n; support_expansion = 0\n; support_filament = 0\n; support_interface_bottom_layers = 2\n; support_interface_filament = 0\n; support_interface_loop_pattern = 0\n; support_interface_not_for_body = 1\n; support_interface_pattern = auto\n; support_interface_spacing = 0.5\n; support_interface_speed = 80\n; support_interface_top_layers = 2\n; support_line_width = 0.42\n; support_material_interface_fan_speed = -1\n; support_multi_bed_types = 0\n; support_object_xy_distance = 0.35\n; support_on_build_plate_only = 0\n; support_remove_small_overhang = 1\n; support_speed = 150\n; support_style = default\n; support_threshold_angle = 30\n; support_top_z_distance = 0.2\n; support_type = normal(auto)\n; temperature_vitrification = 45\n; template_custom_gcode = \n; textured_cool_plate_temp = 40\n; textured_cool_plate_temp_initial_layer = 40\n; textured_plate_temp = 60\n; textured_plate_temp_initial_layer = 60\n; thick_bridges = 0\n; thick_internal_bridges = 1\n; thumbnails = 140x140/PNG, 48x48/PNG\n; thumbnails_format = PNG\n; time_cost = 0\n; time_lapse_gcode = ;TIMELAPSE_TAKE_FRAME\\n\n; timelapse_type = 0\n; top_bottom_infill_wall_overlap = 25%\n; top_shell_layers = 5\n; top_shell_thickness = 1\n; top_solid_infill_flow_ratio = 1\n; top_surface_acceleration = 2000\n; top_surface_jerk = 9\n; top_surface_line_width = 0.42\n; top_surface_pattern = monotonicline\n; top_surface_speed = 200\n; travel_acceleration = 10000\n; travel_jerk = 12\n; travel_slope = 3\n; travel_speed = 500\n; travel_speed_z = 0\n; tree_support_adaptive_layer_height = 1\n; tree_support_angle_slow = 25\n; tree_support_auto_brim = 1\n; tree_support_branch_angle = 45\n; tree_support_branch_angle_organic = 40\n; tree_support_branch_diameter = 2\n; tree_support_branch_diameter_angle = 5\n; tree_support_branch_diameter_double_wall = 3\n; tree_support_branch_diameter_organic = 2\n; tree_support_branch_distance = 5\n; tree_support_branch_distance_organic = 1\n; tree_support_brim_width = 3\n; tree_support_tip_diameter = 0.8\n; tree_support_top_rate = 30%\n; tree_support_wall_count = 0\n; upward_compatible_machine = \n; use_firmware_retraction = 0\n; use_relative_e_distances = 1\n; wall_direction = auto\n; wall_distribution_count = 1\n; wall_filament = 1\n; wall_generator = classic\n; wall_loops = 3\n; wall_sequence = inner wall/outer wall\n; wall_transition_angle = 10\n; wall_transition_filter_deviation = 25%\n; wall_transition_length = 100%\n; wipe = 1\n; wipe_before_external_loop = 0\n; wipe_distance = 2\n; wipe_on_loops = 0\n; wipe_speed = 80%\n; wipe_tower_bridging = 10\n; wipe_tower_cone_angle = 0\n; wipe_tower_extra_flow = 100%\n; wipe_tower_extra_spacing = 100%\n; wipe_tower_filament = 0\n; wipe_tower_max_purge_speed = 90\n; wipe_tower_no_sparse_layers = 0\n; wipe_tower_rotation_angle = 0\n; wipe_tower_x = 165.000\n; wipe_tower_x = 165\n; wipe_tower_y = 250.000\n; wipe_tower_y = 250\n; wiping_volumes_extruders = 70,70,70,70,70,70,70,70,70,70\n; xy_contour_compensation = 0\n; xy_hole_compensation = 0\n; z_hop = 0.4\n; z_hop_types = Auto Lift\n; z_offset = 0\n; first_layer_bed_temperature = 60\n; bed_shape = 0x0,245x0,245x245,0x245\n; first_layer_temperature = 210\n; first_layer_height = 0.200\n; CONFIG_BLOCK_END\n\n\n"
  },
  {
    "path": "presliced_z-offset_calibration_files/X-Max3/z-offset_calibration_X-Max3_PLA_8m46s.gcode",
    "content": "; HEADER_BLOCK_START\n; generated by OrcaSlicer 2.2.0 on 2025-06-04 at 11:46:17\n; total layer number: 1\n; filament_density: 1.24\n; filament_diameter: 1.75\n; max_z_height: 0.20\n; HEADER_BLOCK_END\n\n; THUMBNAIL_BLOCK_START\n\n;\n; thumbnail begin 240x240 1868\n; iVBORw0KGgoAAAANSUhEUgAAAPAAAADwCAYAAAA+VemSAAAFQElEQVR4Ae3dPVIkRxCA0T4Qh5CFww\n; k4Ai4O7jp4uNgYnIATcLRVjBTEwuzM9ExP/WRWvRfxOZKljajIVHUtLAsAAAAAAAAAAAAAAAAAAAAA\n; AAAAAAAAAAAAAAAAAAAAAAAAAABwzP39/a+Pj4/fu25ubv5ZgBy+H96vdv9sAeLaTdrn5+fP/cP71e\n; 7fmcYQ0KGpeyzTGAK55PB+n8YL0M+Wg7uflRo6KHF4rdTQ2G5iljq4LrigoZJT1zSGhlocXtMYCmt5\n; cE1jKKjn4f0+jRfgfBEOrpUaNoh2eK3UcIa1d8ymMQQVeeqaxnBCxsP7fRovMKPMB3c/KzVTGenwfm\n; WlZnhZLqq25oKLYY04dU1jpjDT4TWNGcaMB3c/h5iUHN4/WalJw8E9nJWa8Bze9UxjQhr581DpTGPC\n; MHW3ZxrTlcN7fd5T05yDWz4rNU04vPWyUlPN6O+Yo+SCi+JM3faZxhTh8PbLBRebObhxslJzEYc3Xl\n; ZqVtX6xWEqkwsujjJ182Qa84PPQ/kyjTF1B8g0npTDO04+N03EwR33EFupB+fwjp+VekDeMc+VaTwQ\n; U3feTOPkHF654ErIwdV+VuokHF4dy0odmIsqnZMLroBMXV2aaRyEw6utmcYdObgqlUPcmMOr0vnc1I\n; CDq5pZqStyeNUqF1yF+Tyk1pnGBZi66p1pvJHDqyi54LqAg6uoWalXOLyKnpX6AO+YlSkXXN+Yusra\n; 9NPY4VX2ppzGDq5Ga5pD7PBq1IZeqf3iMM3QkCu1qavZGmYa+zykWUs9jU1d6f/STWOHV/pZivfUDq\n; 50urArtcMrnVeoldo7ZunyQlxwmbrSdXWbxg6vVKamF1wOrlSn6iu1wyvVrcpK7R2z1K6iF1ymrtSn\n; q6exwyv1bdM0dnClWF08jd/f31P9B0qj9vLy8nvZ4unp6TPTf6g0Wlf/f/Bu/zaNpba9vb2V/S5sGk\n; tt2rwyr7m7u3O5JVWsydtoK7VUtmpT9xgrtVSmbn8jyQWXtL3dRdUSgWksXdbj42Osn5G1u+AyjaX1\n; Qv+UytfX11R/mFKrml9UbfXw8PCZ6Q9Wql26nw3tgktKNHWPccGlWQt3UbWVCy7N1O7z0O3t7a9lNK\n; axRi/9yrzGe2qN2tC/4HuflVqjNPzUPcZKrexNNXUP8blJGSv+F+6zM42VpWE+D5Xmc5OiN/3KfA6H\n; WNGa9qJqKyu1omTqbuSCSz0zdQsxjdU6F1WFueBSq4Z8xxyFaaxaWZkb8QMDVDoXVR1YqXVtpm5nVm\n; ptzdQNwucmXZJ3zEGZxlrL56Hg/MAAHcvKnIiVWl+5qErKSi1TNzkXXHMW5heHUYZpPE8uqgblPfX4\n; WZknYBqPl4uqyXhPPU6m7qRccOXO1OU/Vup8uajiB9M4R94xc5JpHDcrM2fxnjpeLqq4mJW6f6YuV7\n; FS98vUpQgXXG1zUUUVpnH9fB6iKu+p62VlphmHuFwuqujCe+rrM3XpygXXtkxdQnHBdX4uqgjJBdd6\n; fnEY4ZnGf2dlJhXvqf/kooq0Zl6pTV2GMONKbeoylFk+N3nHzNBGnsY+DzGFES+4rMxMZ4SV2kUVU8\n; u8Upu6sOS74PKLw+CADNPYRRWcEPk9tXfMcKZI09hFFWwQ4QcGuKiCK/VYqU1dKKjlSm3qQgW1Pzd5\n; xwwN1JjGVmZoqOR7aiszdHLNSm3qQgBbVmpTFwI594LLO2YI7NQ09o4ZEjj0ntrKDMnsDrGLKgAAAA\n; AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFj1L3Bw5na34ScOAAAAAElFTkSuQmCC\n; thumbnail end\n; THUMBNAIL_BLOCK_END\n\n; THUMBNAIL_BLOCK_START\n\n;\n; thumbnail begin 96x96 756\n; iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAB/klEQVR4Ae2czW2DQBCFtyAXkTZogw\n; vXXLjRAwcqoAKX5miVWFkhzM/+zux+n/SkKDceM/PWY7AxAAAAAAAAAAAAAABwxOPx+LIykJ+u677X\n; dX1Z2b8N5MM1/61xHJ90Q2L2jN+Km5CIK+a73WAgDneMZyRFxtd8VwS0J7aCQ82nGzyIUfV0gycpzS\n; egD8hh/FaMpD9KmM9IMr97nJhBGzKSmuuGklXffDdINN/tBlMrko3fqrqRpMn8qkaSrSRNpm+lOqA1\n; Vn013SDheNlkN9RU9eq6oQXz3W4wUmjJ+K2Kj6SWzX+ryEiSsseRoqwBTdV/VvJuwPxzJQlojL+vaC\n; MJ8/0VNJK073GkyCugqfr4utwNmJ9Oh92A8fm0exPsP5dlUXUhWnU4joZheGq6mGqM33aDpgurynz3\n; JrDvCdc0TS8TAuHsr2i7IQL6nuZ5TvNdAQF9ruQbUQK6oPkuBPS/+r4v8x0xAS3gKYlWAzpZ0PrSUk\n; CLfTaohW5Q8ZhijQFdLGh94eFcAWjfJwXvcaTACxoC0BTQVb81Kfm42sybkhL3SU2+tC0hoNUdL2PD\n; TxUIIHdAi9vjSCFHQFP1J6QMaMy/QcyAbj5ofeFH+wTgu0+yQWsgHncCmqpPxJXjKuZnYK8bMD4z7n\n; EV8wvBp1kAAAAAAAAAAAAAgEv8AEKg0vvlB1mPAAAAAElFTkSuQmCC\n; thumbnail end\n; THUMBNAIL_BLOCK_END\n\n; external perimeters extrusion width = 0.42mm\n; perimeters extrusion width = 0.45mm\n; infill extrusion width = 0.45mm\n; solid infill extrusion width = 0.42mm\n; top infill extrusion width = 0.42mm\n; first layer extrusion width = 0.50mm\n\n; EXECUTABLE_BLOCK_START\nEXCLUDE_OBJECT_DEFINE NAME=Cube_id_0_copy_0 CENTER=162.5,162.5 POLYGON=[[127.5,127.5],[197.5,127.5],[197.5,197.5],[127.5,197.5],[127.5,127.5]]\nM73 P0 R8\nM106 S0\nM106 P2 S0\n;TYPE:Custom\nPRINT_START\nG28\nM141 S0\nG0 Z50 F600\nM190 S60\nG28 Z\nG29; mesh bed leveling ,comment this code to close it\nG0 X0 Y0 Z50 F6000\nM73 P51 R4\nM191 S0\nM109 S210\nM106 P3 S255\nM83\nG4 P3000\nG0 X115.929 Y115.929 Z5 F6000\nM73 P52 R4\nG0 Z0.2 F600\nM73 P53 R4\nG1 E3 F1800\nG1 X200.929 E3.4 F3000\nM73 P50 R4\nG1 Y117.929 E0.08 F3000\nM73 P51 R4\nG1 X115.929 E3.4 F3000\nM73 P52 R4\nG1 Y200.929 E3.32 F3000\nM73 P53 R4\nG1 X117.929 E0.08 F3000\nM73 P54 R4\nG1 Y118.929 E3.28 F3000\nG1 X127.929 E-0.4 F3000\nG1 E0.4 F3000\nM73 P54 R3\nM106 P3 S255\nG90\nG21\nM83 ; use relative distances for extrusion\nSET_PRESSURE_ADVANCE ADVANCE=0.031; Override pressure advance value\nM106 S0\nM106 P2 S0\n;LAYER_CHANGE\n;Z:0.2\n;HEIGHT:0.2\n;BEFORE_LAYER_CHANGE\n;0.2\nG92 E0\n\nG1 E-1 F1800\n;TIMELAPSE_TAKE_FRAME\n\n;_SET_FAN_SPEED_CHANGING_LAYER\nSET_VELOCITY_LIMIT ACCEL=500 ACCEL_TO_DECEL=250\nG1 X122.846 Y123.238 F15000\nM73 P54 R4\nG1 Z.6\nG1 Z.2\nG1 E1 F1800\n;TYPE:Skirt\n;WIDTH:0.5\nM73 P54 R3\nG1 F3000\nG1 X124.438 Y121.946 E.07635\nG1 X127.5 Y121.158 E.11778\nG1 X197.5 Y121.158 E2.60723\nG1 X199.708 Y121.555 E.08357\nG1 X201.64 Y122.695 E.08357\nG1 X203.054 Y124.438 E.08357\nG1 X203.842 Y127.5 E.11778\nG1 X203.842 Y197.5 E2.60723\nG1 X203.445 Y199.708 E.08357\nM73 P55 R3\nG1 X202.305 Y201.64 E.08357\nG1 X200.562 Y203.054 E.08357\nG1 X197.5 Y203.842 E.11778\nG1 X127.5 Y203.842 E2.60723\nG1 X125.292 Y203.445 E.08357\nM73 P55 R3\nG1 X123.36 Y202.305 E.08357\nG1 X121.946 Y200.562 E.08357\nG1 X121.158 Y197.5 E.11778\nG1 X121.158 Y127.5 E2.60723\nG1 X121.555 Y125.292 E.08357\nG1 X122.695 Y123.36 E.08357\nG1 X122.815 Y123.263 E.00572\nG1 X123.148 Y123.539 F15000\nG1 F3000\nG1 X124.871 Y122.235 E.08047\nG1 X127.5 Y121.615 E.10062\nG1 X197.5 Y121.615 E2.60723\nG1 X199.624 Y122.011 E.08047\nM73 P56 R3\nG1 X201.461 Y123.148 E.08047\nG1 X202.765 Y124.871 E.08047\nG1 X203.385 Y127.5 E.10062\nG1 X203.385 Y197.5 E2.60723\nG1 X202.989 Y199.624 E.08047\nM73 P56 R3\nG1 X201.852 Y201.461 E.08047\nG1 X200.129 Y202.765 E.08047\nG1 X197.5 Y203.385 E.10062\nG1 X127.5 Y203.385 E2.60723\nG1 X125.376 Y202.989 E.08047\nG1 X123.539 Y201.852 E.08047\nG1 X122.235 Y200.129 E.08047\nG1 X121.615 Y197.5 E.10062\nG1 X121.615 Y127.5 E2.60723\nG1 X122.011 Y125.376 E.08047\nM73 P57 R3\nG1 X123.127 Y123.573 E.07898\nG1 X123.529 Y123.834 F15000\nG1 F3000\nG1 X123.599 Y123.725 E.00483\nG1 X125.3 Y122.538 E.07726\nM73 P57 R3\nG1 X127.5 Y122.072 E.08376\nG1 X197.5 Y122.072 E2.60723\nG1 X199.536 Y122.468 E.07726\nG1 X201.275 Y123.599 E.07726\nG1 X202.462 Y125.3 E.07726\nG1 X202.928 Y127.5 E.08376\nG1 X202.928 Y197.5 E2.60723\nG1 X202.532 Y199.536 E.07726\nG1 X201.401 Y201.275 E.07726\nG1 X199.7 Y202.462 E.07726\nG1 X197.5 Y202.928 E.08376\nG1 X127.5 Y202.928 E2.60723\nG1 X125.464 Y202.532 E.07726\nM73 P58 R3\nG1 X123.725 Y201.401 E.07726\nG1 X122.538 Y199.7 E.07726\nG1 X122.072 Y197.5 E.08376\nG1 X122.072 Y127.5 E2.60723\nG1 X122.468 Y125.464 E.07726\nM73 P58 R3\nG1 X123.507 Y123.867 E.07094\nG1 X123.9 Y124.138 F15000\nG1 F3000\nG1 X124.05 Y123.921 E.00981\nG1 X125.724 Y122.857 E.0739\nG1 X127.5 Y122.529 E.06726\nG1 X197.5 Y122.529 E2.60723\nG1 X199.444 Y122.925 E.0739\nG1 X201.079 Y124.05 E.0739\nG1 X202.143 Y125.724 E.0739\nG1 X202.471 Y127.5 E.06726\nG1 X202.471 Y197.5 E2.60723\nG1 X202.075 Y199.444 E.0739\nG1 X200.95 Y201.079 E.0739\nM73 P59 R3\nG1 X199.276 Y202.143 E.0739\nG1 X197.5 Y202.471 E.06726\nG1 X127.5 Y202.471 E2.60723\nG1 X125.556 Y202.075 E.0739\nG1 X123.921 Y200.95 E.0739\nM73 P59 R3\nG1 X122.857 Y199.276 E.0739\nG1 X122.529 Y197.5 E.06726\nG1 X122.529 Y127.5 E2.60723\nG1 X122.925 Y125.556 E.0739\nG1 X123.878 Y124.171 E.0626\nG1 X124.261 Y124.452 F15000\nG1 F3000\nG1 X124.499 Y124.128 E.01498\nG1 X126.142 Y123.195 E.07039\nG1 X127.5 Y122.986 E.05116\nG1 X197.5 Y122.986 E2.60723\nG1 X199.348 Y123.382 E.07039\nG1 X200.872 Y124.499 E.07039\nG1 X201.805 Y126.142 E.07039\nG1 X202.014 Y127.5 E.05116\nG1 X202.014 Y197.5 E2.60723\nG1 X201.618 Y199.348 E.07039\nM73 P60 R3\nG1 X200.501 Y200.872 E.07039\nG1 X198.858 Y201.805 E.07039\nG1 X197.5 Y202.014 E.05116\nG1 X127.5 Y202.014 E2.60723\nG1 X125.652 Y201.618 E.07039\nM73 P60 R3\nG1 X124.128 Y200.501 E.07039\nG1 X123.195 Y198.858 E.07039\nG1 X122.986 Y197.5 E.05116\nG1 X122.986 Y127.5 E2.60723\nG1 X123.382 Y125.652 E.07039\nG1 X124.238 Y124.485 E.05392\nG1 X124.608 Y124.777 F15000\nG1 F3000\nG1 X124.946 Y124.348 E.02036\nG1 X126.552 Y123.555 E.06669\nG1 X127.5 Y123.443 E.03555\nG1 X197.5 Y123.443 E2.60723\nG1 X199.246 Y123.838 E.06669\nM73 P61 R3\nG1 X200.652 Y124.946 E.06669\nG1 X201.445 Y126.552 E.06669\nG1 X201.557 Y127.5 E.03555\nG1 X201.557 Y197.5 E2.60723\nG1 X201.162 Y199.246 E.06669\nM73 P61 R3\nG1 X200.054 Y200.652 E.06669\nG1 X198.448 Y201.445 E.06669\nG1 X197.5 Y201.557 E.03555\nG1 X127.5 Y201.557 E2.60723\nG1 X125.754 Y201.162 E.06669\nG1 X124.348 Y200.054 E.06669\nG1 X123.555 Y198.448 E.06669\nG1 X123.443 Y197.5 E.03555\nG1 X123.443 Y127.5 E2.60723\nG1 X123.838 Y125.754 E.06669\nM73 P62 R3\nG1 X124.583 Y124.808 E.04484\nG1 X124.938 Y125.112 F15000\nG1 F3000\nG1 X125.392 Y124.582 E.02598\nG1 X127.5 Y123.9 E.08254\nM73 P62 R3\nG1 X197.5 Y123.9 E2.60723\nG1 X199.138 Y124.295 E.06277\nG1 X200.418 Y125.392 E.06277\nG1 X201.1 Y127.5 E.08254\nG1 X201.1 Y197.5 E2.60723\nG1 X200.705 Y199.138 E.06277\nG1 X199.608 Y200.418 E.06277\nG1 X197.5 Y201.1 E.08254\nG1 X127.5 Y201.1 E2.60723\nG1 X125.862 Y200.705 E.06277\nG1 X124.582 Y199.608 E.06277\nM73 P63 R3\nG1 X123.9 Y197.5 E.08254\nG1 X123.9 Y127.5 E2.60723\nG1 X124.295 Y125.862 E.06277\nG1 X124.911 Y125.142 E.0353\nG1 X125.244 Y125.457 F15000\nM73 P63 R3\nG1 F3000\nG1 X125.833 Y124.836 E.03191\nG1 X127.5 Y124.357 E.06459\nG1 X197.5 Y124.357 E2.60723\nG1 X199.023 Y124.751 E.05859\nG1 X200.164 Y125.833 E.05859\nG1 X200.643 Y127.5 E.06459\nG1 X200.643 Y197.5 E2.60723\nG1 X200.249 Y199.023 E.05859\nG1 X199.167 Y200.164 E.05859\nG1 X197.5 Y200.643 E.06459\nG1 X127.5 Y200.643 E2.60723\nG1 X125.977 Y200.249 E.05859\nM73 P64 R3\nG1 X124.836 Y199.167 E.05859\nG1 X124.357 Y197.5 E.06459\nG1 X124.357 Y127.5 E2.60723\nG1 X124.751 Y125.977 E.05859\nG1 X125.216 Y125.486 E.02519\nM73 P64 R3\nG1 X125.519 Y125.812 F15000\nG1 F3000\nG1 X126.27 Y125.113 E.03821\nG1 X127.5 Y124.814 E.04715\nG1 X197.5 Y124.814 E2.60723\nG1 X198.898 Y125.207 E.05408\nG1 X199.887 Y126.27 E.05408\nG1 X200.186 Y127.5 E.04715\nG1 X200.186 Y197.5 E2.60723\nG1 X199.793 Y198.898 E.05408\nM73 P65 R3\nG1 X198.73 Y199.887 E.05408\nG1 X197.5 Y200.186 E.04715\nG1 X127.5 Y200.186 E2.60723\nG1 X126.102 Y199.793 E.05408\nG1 X125.113 Y198.73 E.05408\nM73 P65 R3\nG1 X124.814 Y197.5 E.04715\nG1 X124.814 Y127.5 E2.60723\nG1 X125.207 Y126.102 E.05408\nG1 X125.49 Y125.839 E.01439\nG1 X125.751 Y126.169 F15000\nG1 F3000\nG1 X126.698 Y125.421 E.04498\nG1 X127.5 Y125.271 E.03037\nG1 X197.5 Y125.271 E2.60723\nG1 X198.761 Y125.662 E.04917\nM73 P66 R2\nG1 X199.579 Y126.698 E.04917\nG1 X199.729 Y127.5 E.03037\nG1 X199.729 Y197.5 E2.60723\nG1 X199.338 Y198.761 E.04917\nG1 X198.302 Y199.579 E.04917\nM73 P66 R2\nG1 X197.5 Y199.729 E.03037\nG1 X127.5 Y199.729 E2.60723\nG1 X126.239 Y199.338 E.04917\nG1 X125.421 Y198.302 E.04917\nG1 X125.271 Y197.5 E.03037\nG1 X125.271 Y127.5 E2.60723\nG1 X125.662 Y126.239 E.04917\nG1 X125.719 Y126.194 E.0027\nG1 E-.4 F1800\n;WIPE_START\nG1 F3000\nG1 X126.504 Y125.574 E-.6\n;WIPE_END\nEXCLUDE_OBJECT_START NAME=Cube_id_0_copy_0\nG1 X131.865 Y131.007 Z.6 F15000\nG1 X196.186 Y196.186 Z.6\nG1 Z.2\nM73 P67 R2\nG1 E1 F1800\n;TYPE:Inner wall\nG1 F3000\nG1 X128.814 Y196.186 E2.50934\nG1 X128.814 Y128.814 E2.50934\nG1 X196.186 Y128.814 E2.50934\nM73 P67 R2\nG1 X196.186 Y196.126 E2.5071\nG1 X196.643 Y196.643 F15000\nM73 P68 R2\nG1 F3000\nG1 X128.357 Y196.643 E2.54339\nG1 X128.357 Y128.357 E2.54339\nG1 X196.643 Y128.357 E2.54339\nG1 X196.643 Y196.583 E2.54115\nM73 P69 R2\nM73 P68 R2\nG1 X197.1 Y197.1 F15000\n;TYPE:Outer wall\nG1 F3000\nG1 X127.9 Y197.1 E2.57744\nG1 X127.9 Y127.9 E2.57744\nG1 X197.1 Y127.9 E2.57744\nM73 P69 R2\nG1 X197.1 Y197.04 E2.5752\nM73 P70 R2\nG1 E-.4 F1800\n;WIPE_START\nG1 F3000\nG1 X196.1 Y197.041 E-.6\n;WIPE_END\nG1 X196.094 Y189.408 Z.6 F15000\nG1 X196.049 Y129.879 Z.6\nM73 P70 R2\nG1 Z.2\nG1 E1 F1800\n;TYPE:Bottom surface\n;WIDTH:0.501638\nG1 F6300\nG1 X195.327 Y129.157 E.03815\nG1 X194.678 Y129.157 E.02425\nG1 X195.843 Y130.322 E.06157\nG1 X195.843 Y130.97 E.02425\nG1 X194.03 Y129.157 E.09587\nG1 X193.381 Y129.157 E.02425\nG1 X195.843 Y131.619 E.13016\nG1 X195.843 Y132.268 E.02425\nG1 X192.732 Y129.157 E.16446\nG1 X192.083 Y129.157 E.02425\nG1 X195.843 Y132.917 E.19875\nG1 X195.843 Y133.565 E.02425\nG1 X191.435 Y129.157 E.23304\nG1 X190.786 Y129.157 E.02425\nG1 X195.843 Y134.214 E.26734\nG1 X195.843 Y134.863 E.02425\nG1 X190.137 Y129.157 E.30163\nG1 X189.488 Y129.157 E.02425\nG1 X195.843 Y135.512 E.33592\nG1 X195.843 Y136.16 E.02425\nG1 X188.84 Y129.157 E.37022\nM73 P71 R2\nG1 X188.191 Y129.157 E.02425\nG1 X195.843 Y136.809 E.40451\nG1 X195.843 Y137.458 E.02425\nG1 X187.542 Y129.157 E.4388\nG1 X186.894 Y129.157 E.02425\nM73 P71 R2\nG1 X195.843 Y138.106 E.4731\nG1 X195.843 Y138.755 E.02425\nG1 X186.245 Y129.157 E.50739\nG1 X185.596 Y129.157 E.02425\nG1 X195.843 Y139.404 E.54168\nG1 X195.843 Y140.053 E.02425\nG1 X184.947 Y129.157 E.57598\nG1 X184.299 Y129.157 E.02425\nG1 X195.843 Y140.701 E.61027\nG1 X195.843 Y141.35 E.02425\nG1 X183.65 Y129.157 E.64456\nG1 X183.001 Y129.157 E.02425\nG1 X195.843 Y141.999 E.67886\nG1 X195.843 Y142.648 E.02425\nG1 X182.352 Y129.157 E.71315\nG1 X181.704 Y129.157 E.02425\nG1 X195.843 Y143.296 E.74744\nG1 X195.843 Y143.945 E.02425\nG1 X181.055 Y129.157 E.78174\nG1 X180.406 Y129.157 E.02425\nG1 X195.843 Y144.594 E.81603\nG1 X195.843 Y145.242 E.02425\nG1 X179.758 Y129.157 E.85033\nG1 X179.109 Y129.157 E.02425\nM73 P72 R2\nG1 X195.843 Y145.891 E.88462\nG1 X195.843 Y146.54 E.02425\nG1 X178.46 Y129.157 E.91891\nG1 X177.811 Y129.157 E.02425\nG1 X195.843 Y147.189 E.95321\nM73 P72 R2\nG1 X195.843 Y147.837 E.02425\nG1 X177.163 Y129.157 E.9875\nG1 X176.514 Y129.157 E.02425\nG1 X195.843 Y148.486 E1.02179\nG1 X195.843 Y149.135 E.02425\nG1 X175.865 Y129.157 E1.05609\nG1 X175.216 Y129.157 E.02425\nG1 X195.843 Y149.784 E1.09038\nG1 X195.843 Y150.432 E.02425\nG1 X174.568 Y129.157 E1.12467\nG1 X173.919 Y129.157 E.02425\nG1 X195.843 Y151.081 E1.15897\nG1 X195.843 Y151.73 E.02425\nG1 X173.27 Y129.157 E1.19326\nG1 X172.622 Y129.157 E.02425\nG1 X195.843 Y152.378 E1.22755\nG1 X195.843 Y153.027 E.02425\nM73 P73 R2\nG1 X171.973 Y129.157 E1.26185\nG1 X171.324 Y129.157 E.02425\nG1 X195.843 Y153.676 E1.29614\nG1 X195.843 Y154.325 E.02425\nG1 X170.675 Y129.157 E1.33043\nM73 P73 R2\nG1 X170.027 Y129.157 E.02425\nG1 X195.843 Y154.973 E1.36473\nG1 X195.843 Y155.622 E.02425\nG1 X169.378 Y129.157 E1.39902\nG1 X168.729 Y129.157 E.02425\nG1 X195.843 Y156.271 E1.43331\nG1 X195.843 Y156.92 E.02425\nG1 X168.08 Y129.157 E1.46761\nG1 X167.432 Y129.157 E.02425\nG1 X195.843 Y157.568 E1.5019\nG1 X195.843 Y158.217 E.02425\nG1 X166.783 Y129.157 E1.53619\nG1 X166.134 Y129.157 E.02425\nM73 P74 R2\nG1 X195.843 Y158.866 E1.57049\nG1 X195.843 Y159.514 E.02425\nG1 X165.486 Y129.157 E1.60478\nG1 X164.837 Y129.157 E.02425\nG1 X195.843 Y160.163 E1.63908\nM73 P74 R2\nG1 X195.843 Y160.812 E.02425\nG1 X164.188 Y129.157 E1.67337\nG1 X163.539 Y129.157 E.02425\nG1 X195.843 Y161.461 E1.70766\nG1 X195.843 Y162.109 E.02425\nG1 X162.891 Y129.157 E1.74196\nG1 X162.242 Y129.157 E.02425\nG1 X195.843 Y162.758 E1.77625\nG1 X195.843 Y163.407 E.02425\nG1 X161.593 Y129.157 E1.81054\nG1 X160.945 Y129.157 E.02425\nM73 P75 R2\nG1 X195.843 Y164.055 E1.84484\nG1 X195.843 Y164.704 E.02425\nG1 X160.296 Y129.157 E1.87913\nG1 X159.647 Y129.157 E.02425\nG1 X195.843 Y165.353 E1.91342\nM73 P75 R2\nG1 X195.843 Y166.002 E.02425\nG1 X158.998 Y129.157 E1.94772\nG1 X158.35 Y129.157 E.02425\nG1 X195.843 Y166.65 E1.98201\nG1 X195.843 Y167.299 E.02425\nG1 X157.701 Y129.157 E2.0163\nG1 X157.052 Y129.157 E.02425\nG1 X195.843 Y167.948 E2.0506\nG1 X195.843 Y168.597 E.02425\nM73 P76 R2\nG1 X156.403 Y129.157 E2.08489\nG1 X155.755 Y129.157 E.02425\nG1 X195.843 Y169.245 E2.11918\nG1 X195.843 Y169.894 E.02425\nG1 X155.106 Y129.157 E2.15348\nM73 P76 R2\nG1 X154.457 Y129.157 E.02425\nG1 X195.843 Y170.543 E2.18777\nG1 X195.843 Y171.191 E.02425\nG1 X153.809 Y129.157 E2.22206\nG1 X153.16 Y129.157 E.02425\nG1 X195.843 Y171.84 E2.25636\nG1 X195.843 Y172.489 E.02425\nG1 X152.511 Y129.157 E2.29065\nG1 X151.862 Y129.157 E.02425\nM73 P77 R2\nG1 X195.843 Y173.138 E2.32494\nG1 X195.843 Y173.786 E.02425\nG1 X151.214 Y129.157 E2.35924\nG1 X150.565 Y129.157 E.02425\nM73 P77 R1\nG1 X195.843 Y174.435 E2.39353\nM73 P77 R2\nG1 X195.843 Y175.084 E.02425\nG1 X149.916 Y129.157 E2.42783\nG1 X149.267 Y129.157 E.02425\nG1 X195.843 Y175.733 E2.46212\nM73 P77 R1\nG1 X195.843 Y176.381 E.02425\nG1 X148.619 Y129.157 E2.49641\nG1 X147.97 Y129.157 E.02425\nG1 X195.843 Y177.03 E2.53071\nM73 P78 R1\nG1 X195.843 Y177.679 E.02425\nG1 X147.321 Y129.157 E2.565\nG1 X146.673 Y129.157 E.02425\nG1 X195.843 Y178.327 E2.59929\nG1 X195.843 Y178.976 E.02425\nM73 P78 R1\nG1 X146.024 Y129.157 E2.63359\nG1 X145.375 Y129.157 E.02425\nG1 X195.843 Y179.625 E2.66788\nG1 X195.843 Y180.274 E.02425\nG1 X144.726 Y129.157 E2.70217\nG1 X144.078 Y129.157 E.02425\nM73 P79 R1\nG1 X195.843 Y180.922 E2.73647\nG1 X195.843 Y181.571 E.02425\nG1 X143.429 Y129.157 E2.77076\nG1 X142.78 Y129.157 E.02425\nG1 X195.843 Y182.22 E2.80505\nM73 P79 R1\nG1 X195.843 Y182.869 E.02425\nG1 X142.131 Y129.157 E2.83935\nG1 X141.483 Y129.157 E.02425\nG1 X195.843 Y183.517 E2.87364\nG1 X195.843 Y184.166 E.02425\nG1 X140.834 Y129.157 E2.90793\nG1 X140.185 Y129.157 E.02425\nM73 P80 R1\nG1 X195.843 Y184.815 E2.94223\nG1 X195.843 Y185.463 E.02425\nG1 X139.537 Y129.157 E2.97652\nG1 X138.888 Y129.157 E.02425\nG1 X195.843 Y186.112 E3.01081\nM73 P80 R1\nG1 X195.843 Y186.761 E.02425\nG1 X138.239 Y129.157 E3.04511\nG1 X137.59 Y129.157 E.02425\nG1 X195.843 Y187.41 E3.0794\nG1 X195.843 Y188.058 E.02425\nM73 P81 R1\nG1 X136.942 Y129.157 E3.1137\nG1 X136.293 Y129.157 E.02425\nG1 X195.843 Y188.707 E3.14799\nG1 X195.843 Y189.356 E.02425\nG1 X135.644 Y129.157 E3.18228\nM73 P81 R1\nG1 X134.996 Y129.157 E.02425\nG1 X195.843 Y190.004 E3.21658\nG1 X195.843 Y190.653 E.02425\nG1 X134.347 Y129.157 E3.25087\nG1 X133.698 Y129.157 E.02425\nM73 P82 R1\nG1 X195.843 Y191.302 E3.28516\nG1 X195.843 Y191.951 E.02425\nG1 X133.049 Y129.157 E3.31946\nG1 X132.401 Y129.157 E.02425\nG1 X195.843 Y192.599 E3.35375\nM73 P82 R1\nG1 X195.843 Y193.248 E.02425\nG1 X131.752 Y129.157 E3.38804\nG1 X131.103 Y129.157 E.02425\nG1 X195.843 Y193.897 E3.42234\nG1 X195.843 Y194.546 E.02425\nM73 P83 R1\nG1 X130.454 Y129.157 E3.45663\nG1 X129.806 Y129.157 E.02425\nG1 X195.843 Y195.194 E3.49092\nG1 X195.843 Y195.843 E.02425\nG1 X129.157 Y129.157 E3.52522\nM73 P83 R1\nG1 X129.157 Y129.806 E.02425\nG1 X195.194 Y195.843 E3.49093\nG1 X194.546 Y195.843 E.02425\nG1 X129.157 Y130.454 E3.45663\nG1 X129.157 Y131.103 E.02425\nM73 P84 R1\nG1 X193.897 Y195.843 E3.42234\nG1 X193.248 Y195.843 E.02425\nG1 X129.157 Y131.752 E3.38805\nG1 X129.157 Y132.401 E.02425\nG1 X192.599 Y195.843 E3.35375\nM73 P84 R1\nG1 X191.951 Y195.843 E.02425\nG1 X129.157 Y133.049 E3.31946\nG1 X129.157 Y133.698 E.02425\nG1 X191.302 Y195.843 E3.28516\nG1 X190.653 Y195.843 E.02425\nM73 P85 R1\nG1 X129.157 Y134.347 E3.25087\nG1 X129.157 Y134.995 E.02425\nG1 X190.005 Y195.843 E3.21658\nG1 X189.356 Y195.843 E.02425\nG1 X129.157 Y135.644 E3.18228\nM73 P85 R1\nG1 X129.157 Y136.293 E.02425\nG1 X188.707 Y195.843 E3.14799\nG1 X188.058 Y195.843 E.02425\nG1 X129.157 Y136.942 E3.1137\nG1 X129.157 Y137.59 E.02425\nM73 P86 R1\nG1 X187.41 Y195.843 E3.0794\nG1 X186.761 Y195.843 E.02425\nG1 X129.157 Y138.239 E3.04511\nG1 X129.157 Y138.888 E.02425\nG1 X186.112 Y195.843 E3.01082\nM73 P86 R1\nG1 X185.463 Y195.843 E.02425\nG1 X129.157 Y139.537 E2.97652\nG1 X129.157 Y140.185 E.02425\nG1 X184.815 Y195.843 E2.94223\nG1 X184.166 Y195.843 E.02425\nM73 P87 R1\nG1 X129.157 Y140.834 E2.90794\nG1 X129.157 Y141.483 E.02425\nG1 X183.517 Y195.843 E2.87364\nG1 X182.869 Y195.843 E.02425\nG1 X129.157 Y142.131 E2.83935\nM73 P87 R1\nG1 X129.157 Y142.78 E.02425\nG1 X182.22 Y195.843 E2.80506\nG1 X181.571 Y195.843 E.02425\nG1 X129.157 Y143.429 E2.77076\nG1 X129.157 Y144.078 E.02425\nG1 X180.922 Y195.843 E2.73647\nG1 X180.274 Y195.843 E.02425\nM73 P88 R1\nG1 X129.157 Y144.726 E2.70218\nG1 X129.157 Y145.375 E.02425\nG1 X179.625 Y195.843 E2.66788\nG1 X178.976 Y195.843 E.02425\nG1 X129.157 Y146.024 E2.63359\nM73 P88 R1\nG1 X129.157 Y146.673 E.02425\nG1 X178.327 Y195.843 E2.59929\nG1 X177.679 Y195.843 E.02425\nM73 P88 R0\nG1 X129.157 Y147.321 E2.565\nG1 X129.157 Y147.97 E.02425\nG1 X177.03 Y195.843 E2.53071\nG1 X176.381 Y195.843 E.02425\nM73 P89 R0\nG1 X129.157 Y148.619 E2.49641\nM73 P88 R0\nG1 X129.157 Y149.267 E.02425\nG1 X175.733 Y195.843 E2.46212\nG1 X175.084 Y195.843 E.02425\nG1 X129.157 Y149.916 E2.42783\nM73 P89 R0\nG1 X129.157 Y150.565 E.02425\nG1 X174.435 Y195.843 E2.39353\nG1 X173.786 Y195.843 E.02425\nG1 X129.157 Y151.214 E2.35924\nG1 X129.157 Y151.862 E.02425\nG1 X173.138 Y195.843 E2.32495\nG1 X172.489 Y195.843 E.02425\nM73 P90 R0\nG1 X129.157 Y152.511 E2.29065\nG1 X129.157 Y153.16 E.02425\nG1 X171.84 Y195.843 E2.25636\nG1 X171.191 Y195.843 E.02425\nG1 X129.157 Y153.809 E2.22207\nM73 P90 R0\nG1 X129.157 Y154.457 E.02425\nG1 X170.543 Y195.843 E2.18777\nG1 X169.894 Y195.843 E.02425\nG1 X129.157 Y155.106 E2.15348\nG1 X129.157 Y155.755 E.02425\nG1 X169.245 Y195.843 E2.11919\nG1 X168.597 Y195.843 E.02425\nG1 X129.157 Y156.403 E2.08489\nG1 X129.157 Y157.052 E.02425\nM73 P91 R0\nG1 X167.948 Y195.843 E2.0506\nG1 X167.299 Y195.843 E.02425\nG1 X129.157 Y157.701 E2.01631\nG1 X129.157 Y158.35 E.02425\nG1 X166.65 Y195.843 E1.98201\nM73 P91 R0\nG1 X166.002 Y195.843 E.02425\nG1 X129.157 Y158.998 E1.94772\nG1 X129.157 Y159.647 E.02425\nG1 X165.353 Y195.843 E1.91343\nG1 X164.704 Y195.843 E.02425\nG1 X129.157 Y160.296 E1.87913\nG1 X129.157 Y160.944 E.02425\nG1 X164.056 Y195.843 E1.84484\nG1 X163.407 Y195.843 E.02425\nM73 P92 R0\nG1 X129.157 Y161.593 E1.81054\nG1 X129.157 Y162.242 E.02425\nG1 X162.758 Y195.843 E1.77625\nG1 X162.109 Y195.843 E.02425\nG1 X129.157 Y162.891 E1.74196\nM73 P92 R0\nG1 X129.157 Y163.539 E.02425\nG1 X161.461 Y195.843 E1.70766\nG1 X160.812 Y195.843 E.02425\nG1 X129.157 Y164.188 E1.67337\nG1 X129.157 Y164.837 E.02425\nG1 X160.163 Y195.843 E1.63908\nG1 X159.514 Y195.843 E.02425\nG1 X129.157 Y165.486 E1.60478\nG1 X129.157 Y166.134 E.02425\nG1 X158.866 Y195.843 E1.57049\nG1 X158.217 Y195.843 E.02425\nM73 P93 R0\nG1 X129.157 Y166.783 E1.5362\nG1 X129.157 Y167.432 E.02425\nG1 X157.568 Y195.843 E1.5019\nG1 X156.92 Y195.843 E.02425\nG1 X129.157 Y168.08 E1.46761\nM73 P93 R0\nG1 X129.157 Y168.729 E.02425\nG1 X156.271 Y195.843 E1.43332\nG1 X155.622 Y195.843 E.02425\nG1 X129.157 Y169.378 E1.39902\nG1 X129.157 Y170.027 E.02425\nG1 X154.973 Y195.843 E1.36473\nG1 X154.325 Y195.843 E.02425\nG1 X129.157 Y170.675 E1.33044\nG1 X129.157 Y171.324 E.02425\nG1 X153.676 Y195.843 E1.29614\nG1 X153.027 Y195.843 E.02425\nG1 X129.157 Y171.973 E1.26185\nG1 X129.157 Y172.622 E.02425\nM73 P94 R0\nG1 X152.378 Y195.843 E1.22756\nG1 X151.73 Y195.843 E.02425\nG1 X129.157 Y173.27 E1.19326\nG1 X129.157 Y173.919 E.02425\nG1 X151.081 Y195.843 E1.15897\nM73 P94 R0\nG1 X150.432 Y195.843 E.02425\nG1 X129.157 Y174.568 E1.12468\nG1 X129.157 Y175.216 E.02425\nG1 X149.784 Y195.843 E1.09038\nG1 X149.135 Y195.843 E.02425\nG1 X129.157 Y175.865 E1.05609\nG1 X129.157 Y176.514 E.02425\nG1 X148.486 Y195.843 E1.02179\nG1 X147.837 Y195.843 E.02425\nG1 X129.157 Y177.163 E.9875\nG1 X129.157 Y177.811 E.02425\nG1 X147.189 Y195.843 E.95321\nG1 X146.54 Y195.843 E.02425\nG1 X129.157 Y178.46 E.91891\nG1 X129.157 Y179.109 E.02425\nG1 X145.891 Y195.843 E.88462\nG1 X145.242 Y195.843 E.02425\nM73 P95 R0\nG1 X129.157 Y179.758 E.85033\nG1 X129.157 Y180.406 E.02425\nG1 X144.594 Y195.843 E.81603\nG1 X143.945 Y195.843 E.02425\nG1 X129.157 Y181.055 E.78174\nM73 P95 R0\nG1 X129.157 Y181.704 E.02425\nG1 X143.296 Y195.843 E.74745\nG1 X142.648 Y195.843 E.02425\nG1 X129.157 Y182.352 E.71315\nG1 X129.157 Y183.001 E.02425\nG1 X141.999 Y195.843 E.67886\nG1 X141.35 Y195.843 E.02425\nG1 X129.157 Y183.65 E.64457\nG1 X129.157 Y184.299 E.02425\nG1 X140.701 Y195.843 E.61027\nG1 X140.053 Y195.843 E.02425\nG1 X129.157 Y184.947 E.57598\nG1 X129.157 Y185.596 E.02425\nG1 X139.404 Y195.843 E.54169\nG1 X138.755 Y195.843 E.02425\nG1 X129.157 Y186.245 E.50739\nG1 X129.157 Y186.893 E.02425\nG1 X138.107 Y195.843 E.4731\nG1 X137.458 Y195.843 E.02425\nG1 X129.157 Y187.542 E.43881\nG1 X129.157 Y188.191 E.02425\nG1 X136.809 Y195.843 E.40451\nM73 P96 R0\nG1 X136.16 Y195.843 E.02425\nG1 X129.157 Y188.84 E.37022\nG1 X129.157 Y189.488 E.02425\nG1 X135.512 Y195.843 E.33592\nG1 X134.863 Y195.843 E.02425\nM73 P96 R0\nG1 X129.157 Y190.137 E.30163\nG1 X129.157 Y190.786 E.02425\nG1 X134.214 Y195.843 E.26734\nG1 X133.565 Y195.843 E.02425\nG1 X129.157 Y191.435 E.23304\nG1 X129.157 Y192.083 E.02425\nG1 X132.917 Y195.843 E.19875\nG1 X132.268 Y195.843 E.02425\nG1 X129.157 Y192.732 E.16446\nG1 X129.157 Y193.381 E.02425\nG1 X131.619 Y195.843 E.13016\nG1 X130.971 Y195.843 E.02425\nG1 X129.157 Y194.029 E.09587\nG1 X129.157 Y194.678 E.02425\nG1 X130.322 Y195.843 E.06158\nG1 X129.673 Y195.843 E.02425\nG1 X128.951 Y195.121 E.03816\nG1 E-.71429 F1800\n;WIPE_START\nG1 F6300\nG1 X129.658 Y195.828 E-.28571\n;WIPE_END\nEXCLUDE_OBJECT_END NAME=Cube_id_0_copy_0\nM106 S0\nM106 P2 S0\n;TYPE:Custom\nM141 S0\nM104 S0\nM140 S0\nG1 E-3 F1800\nG0 Z3.2 F600\nG0 X0 Y0 F12000\nG1 Z167 F600\nM106 P3 S0\nM73 P100 R0\n; EXECUTABLE_BLOCK_END\n\n; filament used [mm] = 525.65\n; filament used [cm3] = 1.26\n; filament used [g] = 1.57\n; filament cost = 0.03\n; total filament used [g] = 1.57\n; total filament cost = 0.03\n; total layers count = 1\n; estimated printing time (normal mode) = 8m 46s\n\n; CONFIG_BLOCK_START\n; accel_to_decel_enable = 1\n; accel_to_decel_factor = 50%\n; activate_air_filtration = 1\n; activate_chamber_temp_control = 0\n; adaptive_bed_mesh_margin = 0\n; adaptive_pressure_advance = 0\n; adaptive_pressure_advance_bridges = 0\n; adaptive_pressure_advance_model = \"0,0,0\\n0,0,0\"\n; adaptive_pressure_advance_overhangs = 0\n; additional_cooling_fan_speed = 0\n; alternate_extra_wall = 0\n; auxiliary_fan = 1\n; bbl_calib_mark_logo = 1\n; bbl_use_printhost = 0\n; bed_custom_model = \n; bed_custom_texture = \n; bed_exclude_area = 0x0\n; bed_mesh_max = 99999,99999\n; bed_mesh_min = -99999,-99999\n; bed_mesh_probe_distance = 50,50\n; before_layer_change_gcode = ;BEFORE_LAYER_CHANGE\\n;[layer_z]\\nG92 E0\\n\n; best_object_pos = 0.5,0.5\n; bottom_shell_layers = 3\n; bottom_shell_thickness = 0\n; bottom_solid_infill_flow_ratio = 1\n; bottom_surface_pattern = monotonic\n; bridge_acceleration = 50%\n; bridge_angle = 0\n; bridge_density = 100%\n; bridge_flow = 1\n; bridge_no_support = 0\n; bridge_speed = 50\n; brim_ears_detection_length = 1\n; brim_ears_max_angle = 125\n; brim_object_gap = 0.1\n; brim_type = auto_brim\n; brim_width = 5\n; chamber_temperature = 0\n; change_extrusion_role_gcode = \n; change_filament_gcode = \n; close_fan_the_first_x_layers = 1\n; complete_print_exhaust_fan_speed = 0\n; cool_plate_temp = 60\n; cool_plate_temp_initial_layer = 60\n; cooling_tube_length = 5\n; cooling_tube_retraction = 91.5\n; counterbore_hole_bridging = none\n; curr_bed_type = High Temp Plate\n; default_acceleration = 10000\n; default_filament_colour = \"\"\n; default_filament_profile = \"Qidi Generic PLA\"\n; default_jerk = 0\n; default_print_profile = 0.20mm Standard @Qidi XMax3\n; deretraction_speed = 0\n; detect_narrow_internal_solid_infill = 1\n; detect_overhang_wall = 1\n; detect_thin_wall = 0\n; different_settings_to_system = only_one_wall_top;skirt_loops;wall_loops;;print_host;thumbnails\n; disable_m73 = 0\n; dont_filter_internal_bridges = disabled\n; dont_slow_down_outer_wall = 1\n; draft_shield = disabled\n; during_print_exhaust_fan_speed = 100\n; elefant_foot_compensation = 0.15\n; elefant_foot_compensation_layers = 1\n; emit_machine_limits_to_gcode = 1\n; enable_arc_fitting = 0\n; enable_filament_ramming = 1\n; enable_long_retraction_when_cut = 0\n; enable_overhang_bridge_fan = 0\n; enable_overhang_speed = 1\n; enable_pressure_advance = 1\n; enable_prime_tower = 0\n; enable_support = 0\n; enforce_support_layers = 0\n; eng_plate_temp = 60\n; eng_plate_temp_initial_layer = 60\n; ensure_vertical_shell_thickness = ensure_all\n; exclude_object = 1\n; extra_loading_move = -2\n; extra_perimeters_on_overhangs = 0\n; extruder_clearance_height_to_lid = 118\n; extruder_clearance_height_to_rod = 30\n; extruder_clearance_radius = 70\n; extruder_colour = #C0C0C0\n; extruder_offset = 0x0\n; fan_cooling_layer_time = 60\n; fan_kickstart = 0\n; fan_max_speed = 100\n; fan_min_speed = 100\n; fan_speedup_overhangs = 1\n; fan_speedup_time = 0\n; filament_colour = #C0C0C0\n; filament_cooling_final_speed = 3.4\n; filament_cooling_initial_speed = 2.2\n; filament_cooling_moves = 4\n; filament_cost = 20\n; filament_density = 1.24\n; filament_diameter = 1.75\n; filament_end_gcode = \" \"\n; filament_flow_ratio = 0.98\n; filament_ids = GFL99\n; filament_is_support = 0\n; filament_loading_speed = 28\n; filament_loading_speed_start = 3\n; filament_max_volumetric_speed = 14\n; filament_minimal_purge_on_wipe_tower = 15\n; filament_multitool_ramming = 0\n; filament_multitool_ramming_flow = 10\n; filament_multitool_ramming_volume = 10\n; filament_notes = \"\"\n; filament_ramming_parameters = \"120 100 6.6 6.8 7.2 7.6 7.9 8.2 8.7 9.4 9.9 10.0| 0.05 6.6 0.45 6.8 0.95 7.8 1.45 8.3 1.95 9.7 2.45 10 2.95 7.6 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6\"\n; filament_settings_id = \"Qidi Generic PLA\"\n; filament_shrink = 100%\n; filament_shrinkage_compensation_z = 100%\n; filament_soluble = 0\n; filament_stamping_distance = 0\n; filament_stamping_loading_speed = 0\n; filament_start_gcode = \" \"\n; filament_toolchange_delay = 0\n; filament_type = PLA\n; filament_unloading_speed = 90\n; filament_unloading_speed_start = 100\n; filament_vendor = QIDI\n; filename_format = {input_filename_base}_{filament_type[0]}_{print_time}.gcode\n; filter_out_gap_fill = 2\n; first_layer_print_sequence = 0\n; flush_into_infill = 0\n; flush_into_objects = 0\n; flush_into_support = 1\n; flush_multiplier = 1\n; flush_volumes_matrix = 0\n; flush_volumes_vector = 140,140\n; full_fan_speed_layer = 3\n; fuzzy_skin = none\n; fuzzy_skin_first_layer = 0\n; fuzzy_skin_point_distance = 0.8\n; fuzzy_skin_thickness = 0.3\n; gap_fill_target = nowhere\n; gap_infill_speed = 250\n; gcode_add_line_number = 0\n; gcode_comments = 0\n; gcode_flavor = klipper\n; gcode_label_objects = 0\n; has_scarf_joint_seam = 0\n; head_wrap_detect_zone = \n; high_current_on_filament_swap = 0\n; hole_to_polyhole = 0\n; hole_to_polyhole_threshold = 0.01\n; hole_to_polyhole_twisted = 1\n; host_type = octoprint\n; hot_plate_temp = 60\n; hot_plate_temp_initial_layer = 60\n; idle_temperature = 0\n; independent_support_layer_height = 0\n; infill_anchor = 400%\n; infill_anchor_max = 20\n; infill_combination = 0\n; infill_combination_max_layer_height = 100%\n; infill_direction = 45\n; infill_jerk = 9\n; infill_wall_overlap = 15%\n; inherits_group = ;;\"Qidi X-Max 3 0.4 nozzle\"\n; initial_layer_acceleration = 500\n; initial_layer_infill_speed = 105\n; initial_layer_jerk = 9\n; initial_layer_line_width = 0.5\n; initial_layer_min_bead_width = 85%\n; initial_layer_print_height = 0.2\n; initial_layer_speed = 50\n; initial_layer_travel_speed = 50%\n; inner_wall_acceleration = 5000\n; inner_wall_jerk = 9\n; inner_wall_line_width = 0.45\n; inner_wall_speed = 300\n; interface_shells = 0\n; interlocking_beam = 0\n; interlocking_beam_layer_count = 2\n; interlocking_beam_width = 0.8\n; interlocking_boundary_avoidance = 2\n; interlocking_depth = 2\n; interlocking_orientation = 22.5\n; internal_bridge_flow = 1\n; internal_bridge_speed = 50\n; internal_solid_infill_acceleration = 100%\n; internal_solid_infill_line_width = 0.42\n; internal_solid_infill_pattern = zig-zag\n; internal_solid_infill_speed = 250\n; ironing_angle = -1\n; ironing_flow = 10%\n; ironing_pattern = zig-zag\n; ironing_spacing = 0.15\n; ironing_speed = 30\n; ironing_type = no ironing\n; is_infill_first = 0\n; layer_change_gcode = \n; layer_height = 0.2\n; line_width = 0.42\n; long_retractions_when_cut = 0\n; machine_end_gcode = M141 S0\\nM104 S0\\nM140 S0\\nG1 E-3 F1800\\nG0 Z{min(max_print_height, max_layer_z + 3)} F600\\nG0 X0 Y0 F12000\\n{if max_layer_z < max_print_height / 2}G1 Z{max_print_height / 2 + 10} F600{else}G1 Z{min(max_print_height, max_layer_z + 3)}{endif}\n; machine_load_filament_time = 0\n; machine_max_acceleration_e = 5000\n; machine_max_acceleration_extruding = 20000\n; machine_max_acceleration_retracting = 5000\n; machine_max_acceleration_travel = 0,0\n; machine_max_acceleration_x = 20000\n; machine_max_acceleration_y = 20000\n; machine_max_acceleration_z = 500\n; machine_max_jerk_e = 2\n; machine_max_jerk_x = 9\n; machine_max_jerk_y = 9\n; machine_max_jerk_z = 3\n; machine_max_speed_e = 30\n; machine_max_speed_x = 600\n; machine_max_speed_y = 600\n; machine_max_speed_z = 10\n; machine_min_extruding_rate = 0\n; machine_min_travel_rate = 0\n; machine_pause_gcode = M0\n; machine_start_gcode = PRINT_START\\nG28\\nM141 S0\\nG0 Z50 F600\\nM190 S[hot_plate_temp_initial_layer]\\nG28 Z\\nG29; mesh bed leveling ,comment this code to close it\\nG0 X0 Y0 Z50 F6000\\nM191 S{overall_chamber_temperature}\\nM109 S[nozzle_temperature_initial_layer]\\nM106 P3 S255\\nM83\\nG4 P3000\\nG0 X{max((min(print_bed_max[0], first_layer_print_min[0] + 80) - 85),0)} Y{max((min(print_bed_max[1], first_layer_print_min[1] + 80) - 85),0)} Z5 F6000\\nG0 Z[initial_layer_print_height] F600\\nG1 E3 F1800\\nG1 X{(min(print_bed_max[0], first_layer_print_min[0] + 80))} E{85 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\\nG1 Y{max((min(print_bed_max[1], first_layer_print_min[1] + 80) - 85),0) + 2} E{2 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\\nG1 X{max((min(print_bed_max[0], first_layer_print_min[0] + 80) - 85),0)} E{85 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\\nG1 Y{max((min(print_bed_max[1], first_layer_print_min[1] + 80) - 85),0) + 85} E{83 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\\nG1 X{max((min(print_bed_max[0], first_layer_print_min[0] + 80) - 85),0) + 2} E{2 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\\nG1 Y{max((min(print_bed_max[1], first_layer_print_min[1] + 80) - 85),0) + 3} E{82 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\\nG1 X{max((min(print_bed_max[0], first_layer_print_min[0] + 80) - 85),0) + 12} E{-10 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\\nG1 E{10 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\\n\n; machine_tool_change_time = 0\n; machine_unload_filament_time = 0\n; make_overhang_printable = 0\n; make_overhang_printable_angle = 55\n; make_overhang_printable_hole_size = 0\n; manual_filament_change = 0\n; max_bridge_length = 10\n; max_layer_height = 0.28\n; max_travel_detour_distance = 0\n; max_volumetric_extrusion_rate_slope = 0\n; max_volumetric_extrusion_rate_slope_segment_length = 3\n; min_bead_width = 85%\n; min_feature_size = 25%\n; min_layer_height = 0.08\n; min_length_factor = 0.5\n; min_skirt_length = 0\n; min_width_top_surface = 300%\n; minimum_sparse_infill_area = 15\n; mmu_segmented_region_interlocking_depth = 0\n; mmu_segmented_region_max_width = 0\n; notes = If you want to use Orca's chamber temperature control feature, check that printer.cfg has added the following M191 macro.\\nTo add it: go to Fluidd web interface--configuration, copy the following code to the top of the printer.cfg document, SAVE&RESATART  \\n\\n[gcode_macro M191]\\ngcode:\\n    {% set s = params.S|float %}\\n    {% if s == 0 %}\\n        # If target temperature is 0, do nothing\\n        M117 Chamber heating cancelled\\n    {% else %}\\n        SET_HEATER_TEMPERATURE HEATER=chamber_heater TARGET={s}\\n        # Orca: uncomment the following line if you want to use heat bed to assist chamber heating\\n        M140 S90\\n        TEMPERATURE_WAIT SENSOR=\\\"heater_generic chamber_heater\\\" MINIMUM={s-1} MAXIMUM={s+1}\\n        M117 Chamber at target temperature\\n    {% endif %}\n; nozzle_diameter = 0.4\n; nozzle_height = 2.5\n; nozzle_hrc = 0\n; nozzle_temperature = 220\n; nozzle_temperature_initial_layer = 210\n; nozzle_temperature_range_high = 240\n; nozzle_temperature_range_low = 190\n; nozzle_type = hardened_steel\n; nozzle_volume = 0\n; only_one_wall_first_layer = 0\n; only_one_wall_top = 0\n; ooze_prevention = 0\n; other_layers_print_sequence = 0\n; other_layers_print_sequence_nums = 0\n; outer_wall_acceleration = 3000\n; outer_wall_jerk = 9\n; outer_wall_line_width = 0.42\n; outer_wall_speed = 200\n; overhang_1_4_speed = 0\n; overhang_2_4_speed = 50\n; overhang_3_4_speed = 30\n; overhang_4_4_speed = 10\n; overhang_fan_speed = 100\n; overhang_fan_threshold = 95%\n; overhang_reverse = 0\n; overhang_reverse_internal_only = 0\n; overhang_reverse_threshold = 50%\n; overhang_speed_classic = 0\n; parking_pos_retraction = 92\n; pellet_flow_coefficient = 0.4157\n; pellet_modded_printer = 0\n; post_process = \n; precise_outer_wall = 0\n; precise_z_height = 0\n; preferred_orientation = 0\n; preheat_steps = 1\n; preheat_time = 30\n; pressure_advance = 0.031\n; prime_tower_brim_width = 3\n; prime_tower_width = 35\n; prime_volume = 45\n; print_compatible_printers = \"Qidi X-Max 3 0.4 nozzle\"\n; print_flow_ratio = 1\n; print_order = default\n; print_sequence = by layer\n; print_settings_id = 0.20mm Standard @Qidi XMax3\n; printable_area = 0x0,325x0,325x325,0x325\n; printable_height = 315\n; printer_model = Qidi X-Max 3\n; printer_notes = \n; printer_settings_id = Qidi X-Max 3 0.4 nozzle - Copy\n; printer_structure = undefine\n; printer_technology = FFF\n; printer_variant = 0.4\n; printhost_authorization_type = key\n; printhost_ssl_ignore_revoke = 0\n; printing_by_object_gcode = \n; purge_in_prime_tower = 1\n; raft_contact_distance = 0.1\n; raft_expansion = 1.5\n; raft_first_layer_density = 90%\n; raft_first_layer_expansion = 2\n; raft_layers = 0\n; reduce_crossing_wall = 0\n; reduce_fan_stop_start_freq = 1\n; reduce_infill_retraction = 1\n; required_nozzle_HRC = 0\n; resolution = 0.012\n; retract_before_wipe = 0%\n; retract_length_toolchange = 2\n; retract_lift_above = 0\n; retract_lift_below = 0\n; retract_lift_enforce = All Surfaces\n; retract_restart_extra = 0\n; retract_restart_extra_toolchange = 0\n; retract_when_changing_layer = 1\n; retraction_distances_when_cut = 18\n; retraction_length = 1\n; retraction_minimum_travel = 1\n; retraction_speed = 30\n; role_based_wipe_speed = 1\n; rotate_solid_infill_direction = 1\n; scan_first_layer = 0\n; scarf_angle_threshold = 155\n; scarf_joint_flow_ratio = 1\n; scarf_joint_speed = 100%\n; scarf_overhang_threshold = 40%\n; seam_gap = 15%\n; seam_position = aligned\n; seam_slope_conditional = 0\n; seam_slope_entire_loop = 0\n; seam_slope_inner_walls = 0\n; seam_slope_min_length = 20\n; seam_slope_start_height = 0\n; seam_slope_steps = 10\n; seam_slope_type = none\n; silent_mode = 0\n; single_extruder_multi_material = 1\n; single_extruder_multi_material_priming = 0\n; skirt_distance = 2\n; skirt_height = 1\n; skirt_loops = 10\n; skirt_speed = 50\n; skirt_start_angle = -135\n; skirt_type = combined\n; slice_closing_radius = 0.049\n; slicing_mode = regular\n; slow_down_for_layer_cooling = 1\n; slow_down_layer_time = 8\n; slow_down_layers = 0\n; slow_down_min_speed = 20\n; slowdown_for_curled_perimeters = 1\n; small_area_infill_flow_compensation = 0\n; small_area_infill_flow_compensation_model = 0,0;\"\\n0.2,0.4444\";\"\\n0.4,0.6145\";\"\\n0.6,0.7059\";\"\\n0.8,0.7619\";\"\\n1.5,0.8571\";\"\\n2,0.8889\";\"\\n3,0.9231\";\"\\n5,0.9520\";\"\\n10,1\"\n; small_perimeter_speed = 50%\n; small_perimeter_threshold = 4\n; solid_infill_direction = 45\n; solid_infill_filament = 1\n; sparse_infill_acceleration = 100%\n; sparse_infill_density = 15%\n; sparse_infill_filament = 1\n; sparse_infill_line_width = 0.45\n; sparse_infill_pattern = grid\n; sparse_infill_speed = 270\n; spiral_mode = 0\n; spiral_mode_max_xy_smoothing = 200%\n; spiral_mode_smooth = 0\n; staggered_inner_seams = 0\n; standby_temperature_delta = -5\n; start_end_points = 30x-3,54x245\n; support_air_filtration = 1\n; support_angle = 0\n; support_base_pattern = default\n; support_base_pattern_spacing = 2.5\n; support_bottom_interface_spacing = 0.5\n; support_bottom_z_distance = 0.2\n; support_chamber_temp_control = 1\n; support_critical_regions_only = 0\n; support_expansion = 0\n; support_filament = 0\n; support_interface_bottom_layers = 2\n; support_interface_filament = 0\n; support_interface_loop_pattern = 0\n; support_interface_not_for_body = 1\n; support_interface_pattern = auto\n; support_interface_spacing = 0.5\n; support_interface_speed = 80\n; support_interface_top_layers = 2\n; support_line_width = 0.42\n; support_material_interface_fan_speed = -1\n; support_multi_bed_types = 0\n; support_object_xy_distance = 0.35\n; support_on_build_plate_only = 0\n; support_remove_small_overhang = 1\n; support_speed = 150\n; support_style = default\n; support_threshold_angle = 30\n; support_top_z_distance = 0.2\n; support_type = normal(auto)\n; temperature_vitrification = 45\n; template_custom_gcode = \n; textured_cool_plate_temp = 40\n; textured_cool_plate_temp_initial_layer = 40\n; textured_plate_temp = 60\n; textured_plate_temp_initial_layer = 60\n; thick_bridges = 0\n; thick_internal_bridges = 1\n; thumbnails = 240x240/PNG, 96x96/PNG\n; thumbnails_format = PNG\n; time_cost = 0\n; time_lapse_gcode = ;TIMELAPSE_TAKE_FRAME\\n\n; timelapse_type = 0\n; top_bottom_infill_wall_overlap = 25%\n; top_shell_layers = 5\n; top_shell_thickness = 1\n; top_solid_infill_flow_ratio = 1\n; top_surface_acceleration = 2000\n; top_surface_jerk = 9\n; top_surface_line_width = 0.42\n; top_surface_pattern = monotonicline\n; top_surface_speed = 200\n; travel_acceleration = 10000\n; travel_jerk = 12\n; travel_slope = 3\n; travel_speed = 500\n; travel_speed_z = 0\n; tree_support_adaptive_layer_height = 1\n; tree_support_angle_slow = 25\n; tree_support_auto_brim = 1\n; tree_support_branch_angle = 45\n; tree_support_branch_angle_organic = 40\n; tree_support_branch_diameter = 2\n; tree_support_branch_diameter_angle = 5\n; tree_support_branch_diameter_double_wall = 3\n; tree_support_branch_diameter_organic = 2\n; tree_support_branch_distance = 5\n; tree_support_branch_distance_organic = 1\n; tree_support_brim_width = 3\n; tree_support_tip_diameter = 0.8\n; tree_support_top_rate = 30%\n; tree_support_wall_count = 0\n; upward_compatible_machine = \n; use_firmware_retraction = 0\n; use_relative_e_distances = 1\n; wall_direction = auto\n; wall_distribution_count = 1\n; wall_filament = 1\n; wall_generator = classic\n; wall_loops = 3\n; wall_sequence = inner wall/outer wall\n; wall_transition_angle = 10\n; wall_transition_filter_deviation = 25%\n; wall_transition_length = 100%\n; wipe = 1\n; wipe_before_external_loop = 0\n; wipe_distance = 1\n; wipe_on_loops = 0\n; wipe_speed = 80%\n; wipe_tower_bridging = 10\n; wipe_tower_cone_angle = 0\n; wipe_tower_extra_flow = 100%\n; wipe_tower_extra_spacing = 100%\n; wipe_tower_filament = 0\n; wipe_tower_max_purge_speed = 90\n; wipe_tower_no_sparse_layers = 0\n; wipe_tower_rotation_angle = 0\n; wipe_tower_x = 165.000\n; wipe_tower_x = 165\n; wipe_tower_y = 250.000\n; wipe_tower_y = 250\n; wiping_volumes_extruders = 70,70,70,70,70,70,70,70,70,70\n; xy_contour_compensation = 0\n; xy_hole_compensation = 0\n; z_hop = 0.4\n; z_hop_types = Auto Lift\n; z_offset = 0\n; first_layer_bed_temperature = 60\n; bed_shape = 0x0,325x0,325x325,0x325\n; first_layer_temperature = 210\n; first_layer_height = 0.200\n; CONFIG_BLOCK_END\n\n\n"
  },
  {
    "path": "presliced_z-offset_calibration_files/X-Plus3/z-offset_calibration_X-Plus3_PLA_4m4s.gcode",
    "content": "; HEADER_BLOCK_START\n; generated by OrcaSlicer 2.2.0 on 2025-06-04 at 11:44:41\n; total layer number: 1\n; filament_density: 1.24\n; filament_diameter: 1.75\n; max_z_height: 0.20\n; HEADER_BLOCK_END\n\n; THUMBNAIL_BLOCK_START\n\n;\n; thumbnail begin 240x240 1868\n; iVBORw0KGgoAAAANSUhEUgAAAPAAAADwCAYAAAA+VemSAAAFQElEQVR4Ae3dPVIkRxCA0T4Qh5CFww\n; k4Ai4O7jp4uNgYnIATcLRVjBTEwuzM9ExP/WRWvRfxOZKljajIVHUtLAsAAAAAAAAAAAAAAAAAAAAA\n; AAAAAAAAAAAAAAAAAAAAAAAAAABwzP39/a+Pj4/fu25ubv5ZgBy+H96vdv9sAeLaTdrn5+fP/cP71e\n; 7fmcYQ0KGpeyzTGAK55PB+n8YL0M+Wg7uflRo6KHF4rdTQ2G5iljq4LrigoZJT1zSGhlocXtMYCmt5\n; cE1jKKjn4f0+jRfgfBEOrpUaNoh2eK3UcIa1d8ymMQQVeeqaxnBCxsP7fRovMKPMB3c/KzVTGenwfm\n; WlZnhZLqq25oKLYY04dU1jpjDT4TWNGcaMB3c/h5iUHN4/WalJw8E9nJWa8Bze9UxjQhr581DpTGPC\n; MHW3ZxrTlcN7fd5T05yDWz4rNU04vPWyUlPN6O+Yo+SCi+JM3faZxhTh8PbLBRebObhxslJzEYc3Xl\n; ZqVtX6xWEqkwsujjJ182Qa84PPQ/kyjTF1B8g0npTDO04+N03EwR33EFupB+fwjp+VekDeMc+VaTwQ\n; U3feTOPkHF654ErIwdV+VuokHF4dy0odmIsqnZMLroBMXV2aaRyEw6utmcYdObgqlUPcmMOr0vnc1I\n; CDq5pZqStyeNUqF1yF+Tyk1pnGBZi66p1pvJHDqyi54LqAg6uoWalXOLyKnpX6AO+YlSkXXN+Yusra\n; 9NPY4VX2ppzGDq5Ga5pD7PBq1IZeqf3iMM3QkCu1qavZGmYa+zykWUs9jU1d6f/STWOHV/pZivfUDq\n; 50urArtcMrnVeoldo7ZunyQlxwmbrSdXWbxg6vVKamF1wOrlSn6iu1wyvVrcpK7R2z1K6iF1ymrtSn\n; q6exwyv1bdM0dnClWF08jd/f31P9B0qj9vLy8nvZ4unp6TPTf6g0Wlf/f/Bu/zaNpba9vb2V/S5sGk\n; tt2rwyr7m7u3O5JVWsydtoK7VUtmpT9xgrtVSmbn8jyQWXtL3dRdUSgWksXdbj42Osn5G1u+AyjaX1\n; Qv+UytfX11R/mFKrml9UbfXw8PCZ6Q9Wql26nw3tgktKNHWPccGlWQt3UbWVCy7N1O7z0O3t7a9lNK\n; axRi/9yrzGe2qN2tC/4HuflVqjNPzUPcZKrexNNXUP8blJGSv+F+6zM42VpWE+D5Xmc5OiN/3KfA6H\n; WNGa9qJqKyu1omTqbuSCSz0zdQsxjdU6F1WFueBSq4Z8xxyFaaxaWZkb8QMDVDoXVR1YqXVtpm5nVm\n; ptzdQNwucmXZJ3zEGZxlrL56Hg/MAAHcvKnIiVWl+5qErKSi1TNzkXXHMW5heHUYZpPE8uqgblPfX4\n; WZknYBqPl4uqyXhPPU6m7qRccOXO1OU/Vup8uajiB9M4R94xc5JpHDcrM2fxnjpeLqq4mJW6f6YuV7\n; FS98vUpQgXXG1zUUUVpnH9fB6iKu+p62VlphmHuFwuqujCe+rrM3XpygXXtkxdQnHBdX4uqgjJBdd6\n; fnEY4ZnGf2dlJhXvqf/kooq0Zl6pTV2GMONKbeoylFk+N3nHzNBGnsY+DzGFES+4rMxMZ4SV2kUVU8\n; u8Upu6sOS74PKLw+CADNPYRRWcEPk9tXfMcKZI09hFFWwQ4QcGuKiCK/VYqU1dKKjlSm3qQgW1Pzd5\n; xwwN1JjGVmZoqOR7aiszdHLNSm3qQgBbVmpTFwI594LLO2YI7NQ09o4ZEjj0ntrKDMnsDrGLKgAAAA\n; AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFj1L3Bw5na34ScOAAAAAElFTkSuQmCC\n; thumbnail end\n; THUMBNAIL_BLOCK_END\n\n; THUMBNAIL_BLOCK_START\n\n;\n; thumbnail begin 96x96 756\n; iVBORw0KGgoAAAANSUhEUgAAAGAAAABgCAYAAADimHc4AAAB/klEQVR4Ae2czW2DQBCFtyAXkTZogw\n; vXXLjRAwcqoAKX5miVWFkhzM/+zux+n/SkKDceM/PWY7AxAAAAAAAAAAAAAABwxOPx+LIykJ+u677X\n; dX1Z2b8N5MM1/61xHJ90Q2L2jN+Km5CIK+a73WAgDneMZyRFxtd8VwS0J7aCQ82nGzyIUfV0gycpzS\n; egD8hh/FaMpD9KmM9IMr97nJhBGzKSmuuGklXffDdINN/tBlMrko3fqrqRpMn8qkaSrSRNpm+lOqA1\n; Vn013SDheNlkN9RU9eq6oQXz3W4wUmjJ+K2Kj6SWzX+ryEiSsseRoqwBTdV/VvJuwPxzJQlojL+vaC\n; MJ8/0VNJK073GkyCugqfr4utwNmJ9Oh92A8fm0exPsP5dlUXUhWnU4joZheGq6mGqM33aDpgurynz3\n; JrDvCdc0TS8TAuHsr2i7IQL6nuZ5TvNdAQF9ruQbUQK6oPkuBPS/+r4v8x0xAS3gKYlWAzpZ0PrSUk\n; CLfTaohW5Q8ZhijQFdLGh94eFcAWjfJwXvcaTACxoC0BTQVb81Kfm42sybkhL3SU2+tC0hoNUdL2PD\n; TxUIIHdAi9vjSCFHQFP1J6QMaMy/QcyAbj5ofeFH+wTgu0+yQWsgHncCmqpPxJXjKuZnYK8bMD4z7n\n; EV8wvBp1kAAAAAAAAAAAAAgEv8AEKg0vvlB1mPAAAAAElFTkSuQmCC\n; thumbnail end\n; THUMBNAIL_BLOCK_END\n\n; external perimeters extrusion width = 0.42mm\n; perimeters extrusion width = 0.45mm\n; infill extrusion width = 0.45mm\n; solid infill extrusion width = 0.42mm\n; top infill extrusion width = 0.42mm\n; first layer extrusion width = 0.50mm\n\n; EXECUTABLE_BLOCK_START\nEXCLUDE_OBJECT_DEFINE NAME=Cube_id_0_copy_0 CENTER=152.5,152.5 POLYGON=[[117.5,117.5],[187.5,117.5],[187.5,187.5],[117.5,187.5],[117.5,117.5]]\nM73 P0 R4\nM106 S0\nM106 P2 S0\n;TYPE:Custom\nPRINT_START BED=60 HOTEND=210 CHAMBER=0\nSET_PRINT_STATS_INFO TOTAL_LAYER=1\nM83\nM140 S60\nM104 S210\nM141 S0\nG4 P3000\nG0 X105.929 Y105.929 Z5 F6000\nG0 Z0.2 F600\nG1 E3 F1800\nG1 X190.929 E3.4 F3000\nG1 Y107.929 E0.08 F3000\nM73 P1 R4\nG1 X105.929 E3.4 F3000\nM73 P1 R4\nG1 Y190.929 E3.32 F3000\nM73 P2 R3\nG1 X107.929 E0.08 F3000\nM73 P2 R3\nG1 Y108.929 E3.28 F3000\nG1 X108.929 Z0\nM73 P3 R3\nG1 X111.929\nM73 P3 R3\nG1 Z1 F600\nSET_PRINT_STATS_INFO CURRENT_LAYER=1\nM106 P3 S255\nG90\nG21\nM83 ; use relative distances for extrusion\nSET_PRESSURE_ADVANCE ADVANCE=0.034; Override pressure advance value\nM106 S0\nM106 P2 S0\n;LAYER_CHANGE\n;Z:0.2\n;HEIGHT:0.2\n;BEFORE_LAYER_CHANGE\n;0.2\nG92 E0\n\nG1 E-.8 F1800\n;TIMELAPSE_TAKE_FRAME\n\nG92 E0\nSET_PRINT_STATS_INFO CURRENT_LAYER=1\n;_SET_FAN_SPEED_CHANGING_LAYER\nSET_VELOCITY_LIMIT ACCEL=500 ACCEL_TO_DECEL=250\nG1 X112.846 Y113.238 F15000\nG1 Z.6\nG1 Z.2\nG1 E.8 F1800\n;TYPE:Skirt\n;WIDTH:0.5\nG1 F3000\nG1 X114.438 Y111.946 E.07635\nG1 X117.5 Y111.158 E.11778\nG1 X187.5 Y111.158 E2.60723\nG1 X189.708 Y111.555 E.08357\nM73 P4 R3\nG1 X191.64 Y112.695 E.08357\nM73 P4 R3\nG1 X193.054 Y114.438 E.08357\nG1 X193.842 Y117.5 E.11778\nG1 X193.842 Y187.5 E2.60723\nG1 X193.445 Y189.708 E.08357\nM73 P5 R3\nG1 X192.305 Y191.64 E.08357\nM73 P5 R3\nG1 X190.562 Y193.054 E.08357\nG1 X187.5 Y193.842 E.11778\nG1 X117.5 Y193.842 E2.60723\nG1 X115.292 Y193.445 E.08357\nG1 X113.36 Y192.305 E.08357\nG1 X111.946 Y190.562 E.08357\nG1 X111.158 Y187.5 E.11778\nG1 X111.158 Y117.5 E2.60723\nG1 X111.555 Y115.292 E.08357\nM73 P6 R3\nG1 X112.695 Y113.36 E.08357\nM73 P6 R3\nG1 X112.815 Y113.263 E.00572\nG1 X113.148 Y113.539 F15000\nG1 F3000\nG1 X114.871 Y112.235 E.08047\nG1 X117.5 Y111.615 E.10062\nG1 X187.5 Y111.615 E2.60723\nG1 X189.624 Y112.011 E.08047\nM73 P7 R3\nG1 X191.461 Y113.148 E.08047\nM73 P7 R3\nG1 X192.765 Y114.871 E.08047\nG1 X193.385 Y117.5 E.10062\nG1 X193.385 Y187.5 E2.60723\nG1 X192.989 Y189.624 E.08047\nG1 X191.852 Y191.461 E.08047\nG1 X190.129 Y192.765 E.08047\nG1 X187.5 Y193.385 E.10062\nM73 P8 R3\nG1 X117.5 Y193.385 E2.60723\nM73 P8 R3\nG1 X115.376 Y192.989 E.08047\nG1 X113.539 Y191.852 E.08047\nG1 X112.235 Y190.129 E.08047\nG1 X111.615 Y187.5 E.10062\nG1 X111.615 Y117.5 E2.60723\nG1 X112.011 Y115.376 E.08047\nM73 P9 R3\nG1 X113.127 Y113.573 E.07898\nM73 P9 R3\nG1 X113.529 Y113.834 F15000\nG1 F3000\nG1 X113.599 Y113.725 E.00483\nG1 X115.3 Y112.538 E.07726\nG1 X117.5 Y112.072 E.08376\nG1 X187.5 Y112.072 E2.60723\nG1 X189.536 Y112.468 E.07726\nG1 X191.275 Y113.599 E.07726\nM73 P10 R3\nG1 X192.462 Y115.3 E.07726\nM73 P10 R3\nG1 X192.928 Y117.5 E.08376\nG1 X192.928 Y187.5 E2.60723\nG1 X192.532 Y189.536 E.07726\nG1 X191.401 Y191.275 E.07726\nG1 X189.7 Y192.462 E.07726\nG1 X187.5 Y192.928 E.08376\nG1 X117.5 Y192.928 E2.60723\nG1 X115.464 Y192.532 E.07726\nM73 P11 R3\nG1 X113.725 Y191.401 E.07726\nM73 P11 R3\nG1 X112.538 Y189.7 E.07726\nG1 X112.072 Y187.5 E.08376\nG1 X112.072 Y117.5 E2.60723\nG1 X112.468 Y115.464 E.07726\nG1 X113.507 Y113.867 E.07094\nM73 P12 R3\nG1 X113.9 Y114.138 F15000\nM73 P12 R3\nG1 F3000\nG1 X114.05 Y113.921 E.00981\nG1 X115.724 Y112.857 E.0739\nG1 X117.5 Y112.529 E.06726\nG1 X187.5 Y112.529 E2.60723\nG1 X189.444 Y112.925 E.0739\nG1 X191.079 Y114.05 E.0739\nG1 X192.143 Y115.724 E.0739\nG1 X192.471 Y117.5 E.06726\nG1 X192.471 Y187.5 E2.60723\nG1 X192.075 Y189.444 E.0739\nM73 P13 R3\nG1 X190.95 Y191.079 E.0739\nM73 P13 R3\nG1 X189.276 Y192.143 E.0739\nG1 X187.5 Y192.471 E.06726\nG1 X117.5 Y192.471 E2.60723\nG1 X115.556 Y192.075 E.0739\nM73 P14 R3\nG1 X113.921 Y190.95 E.0739\nM73 P14 R3\nG1 X112.857 Y189.276 E.0739\nG1 X112.529 Y187.5 E.06726\nG1 X112.529 Y117.5 E2.60723\nG1 X112.925 Y115.556 E.0739\nG1 X113.878 Y114.171 E.0626\nG1 X114.261 Y114.452 F15000\nG1 F3000\nG1 X114.499 Y114.128 E.01498\nG1 X116.142 Y113.195 E.07039\nG1 X117.5 Y112.986 E.05116\nG1 X187.5 Y112.986 E2.60723\nG1 X189.348 Y113.382 E.07039\nM73 P15 R3\nG1 X190.872 Y114.499 E.07039\nM73 P15 R3\nG1 X191.805 Y116.142 E.07039\nG1 X192.014 Y117.5 E.05116\nG1 X192.014 Y187.5 E2.60723\nG1 X191.618 Y189.348 E.07039\nM73 P16 R3\nG1 X190.501 Y190.872 E.07039\nM73 P16 R3\nG1 X188.858 Y191.805 E.07039\nG1 X187.5 Y192.014 E.05116\nG1 X117.5 Y192.014 E2.60723\nG1 X115.652 Y191.618 E.07039\nG1 X114.128 Y190.501 E.07039\nG1 X113.195 Y188.858 E.07039\nG1 X112.986 Y187.5 E.05116\nG1 X112.986 Y117.5 E2.60723\nG1 X113.382 Y115.652 E.07039\nM73 P17 R3\nG1 X114.238 Y114.485 E.05392\nM73 P17 R3\nG1 X114.608 Y114.777 F15000\nG1 F3000\nG1 X114.946 Y114.348 E.02036\nG1 X116.552 Y113.555 E.06669\nG1 X117.5 Y113.443 E.03555\nG1 X187.5 Y113.443 E2.60723\nG1 X189.246 Y113.838 E.06669\nM73 P18 R3\nG1 X190.652 Y114.946 E.06669\nM73 P18 R3\nG1 X191.445 Y116.552 E.06669\nG1 X191.557 Y117.5 E.03555\nG1 X191.557 Y187.5 E2.60723\nG1 X191.162 Y189.246 E.06669\nG1 X190.054 Y190.652 E.06669\nG1 X188.448 Y191.445 E.06669\nG1 X187.5 Y191.557 E.03555\nG1 X117.5 Y191.557 E2.60723\nG1 X115.754 Y191.162 E.06669\nM73 P19 R3\nG1 X114.348 Y190.054 E.06669\nM73 P19 R3\nG1 X113.555 Y188.448 E.06669\nG1 X113.443 Y187.5 E.03555\nG1 X113.443 Y117.5 E2.60723\nG1 X113.838 Y115.754 E.06669\nG1 X114.583 Y114.808 E.04484\nM73 P20 R3\nG1 X114.938 Y115.112 F15000\nM73 P20 R3\nG1 F3000\nG1 X115.392 Y114.582 E.02598\nG1 X117.5 Y113.9 E.08254\nG1 X187.5 Y113.9 E2.60723\nG1 X189.138 Y114.295 E.06277\nG1 X190.418 Y115.392 E.06277\nG1 X191.1 Y117.5 E.08254\nG1 X191.1 Y187.5 E2.60723\nG1 X190.705 Y189.138 E.06277\nM73 P21 R3\nG1 X189.608 Y190.418 E.06277\nM73 P21 R3\nG1 X187.5 Y191.1 E.08254\nG1 X117.5 Y191.1 E2.60723\nG1 X115.862 Y190.705 E.06277\nG1 X114.582 Y189.608 E.06277\nG1 X113.9 Y187.5 E.08254\nM73 P22 R3\nG1 X113.9 Y117.5 E2.60723\nM73 P22 R3\nG1 X114.295 Y115.862 E.06277\nG1 X114.911 Y115.142 E.0353\nG1 X115.244 Y115.457 F15000\nG1 F3000\nG1 X115.833 Y114.836 E.03191\nG1 X117.5 Y114.357 E.06459\nG1 X187.5 Y114.357 E2.60723\nG1 X189.023 Y114.751 E.05859\nM73 P23 R3\nG1 X190.164 Y115.833 E.05859\nM73 P23 R3\nG1 X190.643 Y117.5 E.06459\nG1 X190.643 Y187.5 E2.60723\nG1 X190.249 Y189.023 E.05859\nG1 X189.167 Y190.164 E.05859\nG1 X187.5 Y190.643 E.06459\nG1 X117.5 Y190.643 E2.60723\nM73 P24 R3\nG1 X115.977 Y190.249 E.05859\nM73 P24 R3\nG1 X114.836 Y189.167 E.05859\nG1 X114.357 Y187.5 E.06459\nG1 X114.357 Y117.5 E2.60723\nG1 X114.751 Y115.977 E.05859\nM73 P25 R3\nG1 X115.216 Y115.486 E.02519\nM73 P25 R3\nG1 X115.519 Y115.812 F15000\nG1 F3000\nG1 X116.27 Y115.113 E.03821\nG1 X117.5 Y114.814 E.04715\nG1 X187.5 Y114.814 E2.60723\nG1 X188.898 Y115.207 E.05408\nG1 X189.887 Y116.27 E.05408\nG1 X190.186 Y117.5 E.04715\nG1 X190.186 Y187.5 E2.60723\nG1 X189.793 Y188.898 E.05408\nM73 P26 R2\nG1 X188.73 Y189.887 E.05408\nM73 P26 R2\nG1 X187.5 Y190.186 E.04715\nG1 X117.5 Y190.186 E2.60723\nG1 X116.102 Y189.793 E.05408\nM73 P27 R2\nG1 X115.113 Y188.73 E.05408\nM73 P27 R2\nG1 X114.814 Y187.5 E.04715\nG1 X114.814 Y117.5 E2.60723\nG1 X115.207 Y116.102 E.05408\nG1 X115.49 Y115.839 E.01439\nG1 X115.751 Y116.169 F15000\nG1 F3000\nG1 X116.698 Y115.421 E.04498\nG1 X117.5 Y115.271 E.03037\nG1 X187.5 Y115.271 E2.60723\nG1 X188.761 Y115.662 E.04917\nM73 P28 R2\nG1 X189.579 Y116.698 E.04917\nM73 P28 R2\nG1 X189.729 Y117.5 E.03037\nG1 X189.729 Y187.5 E2.60723\nG1 X189.338 Y188.761 E.04917\nM73 P29 R2\nG1 X188.302 Y189.579 E.04917\nM73 P29 R2\nG1 X187.5 Y189.729 E.03037\nG1 X117.5 Y189.729 E2.60723\nG1 X116.239 Y189.338 E.04917\nG1 X115.421 Y188.302 E.04917\nG1 X115.271 Y187.5 E.03037\nG1 X115.271 Y117.5 E2.60723\nG1 X115.662 Y116.239 E.04917\nM73 P30 R2\nG1 X115.719 Y116.194 E.0027\n;WIPE_START\nM73 P30 R2\nG1 X116.698 Y115.421 E-.49904\nG1 X117.438 Y115.283 E-.30096\n;WIPE_END\nEXCLUDE_OBJECT_START NAME=Cube_id_0_copy_0\nG1 X122.751 Y120.763 Z.6 F15000\nG1 X186.186 Y186.186 Z.6\nG1 Z.2\nG1 E.8 F1800\n;TYPE:Inner wall\nG1 F3000\nG1 X118.814 Y186.186 E2.50934\nG1 X118.814 Y118.814 E2.50934\nM73 P31 R2\nG1 X186.186 Y118.814 E2.50934\nM73 P32 R2\nM73 P31 R2\nG1 X186.186 Y186.126 E2.5071\nM73 P32 R2\nG1 X186.643 Y186.643 F15000\nM73 P33 R2\nG1 F3000\nM73 P33 R2\nG1 X118.357 Y186.643 E2.54339\nG1 X118.357 Y118.357 E2.54339\nG1 X186.643 Y118.357 E2.54339\nM73 P34 R2\nG1 X186.643 Y186.583 E2.54115\nM73 P34 R2\nG1 X187.1 Y187.1 F15000\nM73 P35 R2\n;TYPE:Outer wall\nG1 F3000\nM73 P35 R2\nG1 X117.9 Y187.1 E2.57744\nG1 X117.9 Y117.9 E2.57744\nM73 P36 R2\nG1 X187.1 Y117.9 E2.57744\nM73 P36 R2\nG1 X187.1 Y187.04 E2.5752\nM73 P37 R2\n;WIPE_START\nG1 X185.1 Y187.042 E-.8\n;WIPE_END\nM73 P37 R2\nG1 X185.208 Y179.41 Z.6 F15000\nG1 X186.049 Y119.879 Z.6\nM73 P38 R2\nG1 Z.2\nM73 P38 R2\nG1 E.8 F1800\n;TYPE:Bottom surface\n;WIDTH:0.501638\nG1 F6300\nG1 X185.327 Y119.157 E.03815\nG1 X184.678 Y119.157 E.02425\nG1 X185.843 Y120.322 E.06157\nG1 X185.843 Y120.97 E.02425\nG1 X184.03 Y119.157 E.09587\nG1 X183.381 Y119.157 E.02425\nG1 X185.843 Y121.619 E.13016\nG1 X185.843 Y122.268 E.02425\nG1 X182.732 Y119.157 E.16446\nG1 X182.083 Y119.157 E.02425\nG1 X185.843 Y122.917 E.19875\nG1 X185.843 Y123.565 E.02425\nG1 X181.435 Y119.157 E.23304\nG1 X180.786 Y119.157 E.02425\nG1 X185.843 Y124.214 E.26734\nG1 X185.843 Y124.863 E.02425\nG1 X180.137 Y119.157 E.30163\nG1 X179.488 Y119.157 E.02425\nG1 X185.843 Y125.512 E.33592\nM73 P39 R2\nG1 X185.843 Y126.16 E.02425\nM73 P39 R2\nG1 X178.84 Y119.157 E.37022\nG1 X178.191 Y119.157 E.02425\nG1 X185.843 Y126.809 E.40451\nG1 X185.843 Y127.458 E.02425\nG1 X177.542 Y119.157 E.4388\nG1 X176.894 Y119.157 E.02425\nG1 X185.843 Y128.106 E.4731\nG1 X185.843 Y128.755 E.02425\nG1 X176.245 Y119.157 E.50739\nG1 X175.596 Y119.157 E.02425\nG1 X185.843 Y129.404 E.54168\nG1 X185.843 Y130.053 E.02425\nG1 X174.947 Y119.157 E.57598\nG1 X174.299 Y119.157 E.02425\nM73 P40 R2\nG1 X185.843 Y130.701 E.61027\nM73 P40 R2\nG1 X185.843 Y131.35 E.02425\nG1 X173.65 Y119.157 E.64456\nG1 X173.001 Y119.157 E.02425\nG1 X185.843 Y131.999 E.67886\nG1 X185.843 Y132.648 E.02425\nG1 X172.352 Y119.157 E.71315\nG1 X171.704 Y119.157 E.02425\nG1 X185.843 Y133.296 E.74744\nG1 X185.843 Y133.945 E.02425\nG1 X171.055 Y119.157 E.78174\nG1 X170.406 Y119.157 E.02425\nG1 X185.843 Y134.594 E.81603\nG1 X185.843 Y135.242 E.02425\nM73 P41 R2\nG1 X169.758 Y119.157 E.85033\nM73 P41 R2\nG1 X169.109 Y119.157 E.02425\nG1 X185.843 Y135.891 E.88462\nG1 X185.843 Y136.54 E.02425\nG1 X168.46 Y119.157 E.91891\nG1 X167.811 Y119.157 E.02425\nG1 X185.843 Y137.189 E.95321\nG1 X185.843 Y137.837 E.02425\nG1 X167.163 Y119.157 E.9875\nG1 X166.514 Y119.157 E.02425\nM73 P42 R2\nG1 X185.843 Y138.486 E1.02179\nM73 P42 R2\nG1 X185.843 Y139.135 E.02425\nG1 X165.865 Y119.157 E1.05609\nG1 X165.216 Y119.157 E.02425\nG1 X185.843 Y139.784 E1.09038\nG1 X185.843 Y140.432 E.02425\nG1 X164.568 Y119.157 E1.12467\nG1 X163.919 Y119.157 E.02425\nG1 X185.843 Y141.081 E1.15897\nG1 X185.843 Y141.73 E.02425\nM73 P43 R2\nG1 X163.27 Y119.157 E1.19326\nM73 P43 R2\nG1 X162.622 Y119.157 E.02425\nG1 X185.843 Y142.378 E1.22755\nG1 X185.843 Y143.027 E.02425\nG1 X161.973 Y119.157 E1.26185\nG1 X161.324 Y119.157 E.02425\nG1 X185.843 Y143.676 E1.29614\nG1 X185.843 Y144.325 E.02425\nG1 X160.675 Y119.157 E1.33043\nG1 X160.027 Y119.157 E.02425\nM73 P44 R2\nG1 X185.843 Y144.973 E1.36473\nM73 P44 R2\nG1 X185.843 Y145.622 E.02425\nG1 X159.378 Y119.157 E1.39902\nG1 X158.729 Y119.157 E.02425\nG1 X185.843 Y146.271 E1.43331\nG1 X185.843 Y146.92 E.02425\nG1 X158.08 Y119.157 E1.46761\nG1 X157.432 Y119.157 E.02425\nM73 P45 R2\nG1 X185.843 Y147.568 E1.5019\nM73 P45 R2\nG1 X185.843 Y148.217 E.02425\nG1 X156.783 Y119.157 E1.53619\nG1 X156.134 Y119.157 E.02425\nG1 X185.843 Y148.866 E1.57049\nG1 X185.843 Y149.514 E.02425\nG1 X155.486 Y119.157 E1.60478\nG1 X154.837 Y119.157 E.02425\nM73 P46 R2\nG1 X185.843 Y150.163 E1.63908\nM73 P46 R2\nG1 X185.843 Y150.812 E.02425\nG1 X154.188 Y119.157 E1.67337\nG1 X153.539 Y119.157 E.02425\nG1 X185.843 Y151.461 E1.70766\nG1 X185.843 Y152.109 E.02425\nG1 X152.891 Y119.157 E1.74196\nG1 X152.242 Y119.157 E.02425\nM73 P47 R2\nG1 X185.843 Y152.758 E1.77625\nM73 P47 R2\nG1 X185.843 Y153.407 E.02425\nG1 X151.593 Y119.157 E1.81054\nG1 X150.945 Y119.157 E.02425\nG1 X185.843 Y154.055 E1.84484\nG1 X185.843 Y154.704 E.02425\nG1 X150.296 Y119.157 E1.87913\nG1 X149.647 Y119.157 E.02425\nM73 P48 R2\nG1 X185.843 Y155.353 E1.91342\nM73 P48 R2\nG1 X185.843 Y156.002 E.02425\nG1 X148.998 Y119.157 E1.94772\nG1 X148.35 Y119.157 E.02425\nG1 X185.843 Y156.65 E1.98201\nG1 X185.843 Y157.299 E.02425\nM73 P49 R2\nG1 X147.701 Y119.157 E2.0163\nM73 P49 R2\nG1 X147.052 Y119.157 E.02425\nG1 X185.843 Y157.948 E2.0506\nG1 X185.843 Y158.597 E.02425\nG1 X146.403 Y119.157 E2.08489\nG1 X145.755 Y119.157 E.02425\nG1 X185.843 Y159.245 E2.11918\nG1 X185.843 Y159.894 E.02425\nM73 P50 R2\nG1 X145.106 Y119.157 E2.15348\nM73 P50 R2\nG1 X144.457 Y119.157 E.02425\nG1 X185.843 Y160.543 E2.18777\nG1 X185.843 Y161.191 E.02425\nG1 X143.809 Y119.157 E2.22206\nG1 X143.16 Y119.157 E.02425\nM73 P51 R1\nG1 X185.843 Y161.84 E2.25636\nM73 P51 R1\nG1 X185.843 Y162.489 E.02425\nG1 X142.511 Y119.157 E2.29065\nG1 X141.862 Y119.157 E.02425\nG1 X185.843 Y163.138 E2.32494\nG1 X185.843 Y163.786 E.02425\nM73 P52 R1\nG1 X141.214 Y119.157 E2.35924\nM73 P52 R1\nG1 X140.565 Y119.157 E.02425\nG1 X185.843 Y164.435 E2.39353\nG1 X185.843 Y165.084 E.02425\nG1 X139.916 Y119.157 E2.42783\nG1 X139.267 Y119.157 E.02425\nM73 P53 R1\nG1 X185.843 Y165.733 E2.46212\nM73 P53 R1\nG1 X185.843 Y166.381 E.02425\nG1 X138.619 Y119.157 E2.49641\nG1 X137.97 Y119.157 E.02425\nG1 X185.843 Y167.03 E2.53071\nG1 X185.843 Y167.679 E.02425\nM73 P54 R1\nG1 X137.321 Y119.157 E2.565\nM73 P54 R1\nG1 X136.673 Y119.157 E.02425\nG1 X185.843 Y168.327 E2.59929\nG1 X185.843 Y168.976 E.02425\nG1 X136.024 Y119.157 E2.63359\nG1 X135.375 Y119.157 E.02425\nM73 P55 R1\nG1 X185.843 Y169.625 E2.66788\nM73 P55 R1\nG1 X185.843 Y170.274 E.02425\nG1 X134.726 Y119.157 E2.70217\nG1 X134.078 Y119.157 E.02425\nM73 P56 R1\nG1 X185.843 Y170.922 E2.73647\nM73 P56 R1\nG1 X185.843 Y171.571 E.02425\nG1 X133.429 Y119.157 E2.77076\nG1 X132.78 Y119.157 E.02425\nG1 X185.843 Y172.22 E2.80505\nG1 X185.843 Y172.869 E.02425\nM73 P57 R1\nG1 X132.131 Y119.157 E2.83935\nM73 P57 R1\nG1 X131.483 Y119.157 E.02425\nG1 X185.843 Y173.517 E2.87364\nG1 X185.843 Y174.166 E.02425\nG1 X130.834 Y119.157 E2.90793\nG1 X130.185 Y119.157 E.02425\nM73 P58 R1\nG1 X185.843 Y174.815 E2.94223\nM73 P58 R1\nG1 X185.843 Y175.463 E.02425\nG1 X129.537 Y119.157 E2.97652\nG1 X128.888 Y119.157 E.02425\nM73 P59 R1\nG1 X185.843 Y176.112 E3.01081\nM73 P59 R1\nG1 X185.843 Y176.761 E.02425\nG1 X128.239 Y119.157 E3.04511\nG1 X127.59 Y119.157 E.02425\nG1 X185.843 Y177.41 E3.0794\nG1 X185.843 Y178.058 E.02425\nM73 P60 R1\nG1 X126.942 Y119.157 E3.1137\nM73 P60 R1\nG1 X126.293 Y119.157 E.02425\nG1 X185.843 Y178.707 E3.14799\nG1 X185.843 Y179.356 E.02425\nM73 P61 R1\nG1 X125.644 Y119.157 E3.18228\nM73 P61 R1\nG1 X124.996 Y119.157 E.02425\nG1 X185.843 Y180.004 E3.21658\nG1 X185.843 Y180.653 E.02425\nG1 X124.347 Y119.157 E3.25087\nM73 P62 R1\nG1 X123.698 Y119.157 E.02425\nM73 P62 R1\nG1 X185.843 Y181.302 E3.28516\nG1 X185.843 Y181.951 E.02425\nG1 X123.049 Y119.157 E3.31946\nG1 X122.401 Y119.157 E.02425\nM73 P63 R1\nG1 X185.843 Y182.599 E3.35375\nM73 P63 R1\nG1 X185.843 Y183.248 E.02425\nG1 X121.752 Y119.157 E3.38804\nG1 X121.103 Y119.157 E.02425\nM73 P64 R1\nG1 X185.843 Y183.897 E3.42234\nM73 P64 R1\nG1 X185.843 Y184.546 E.02425\nG1 X120.454 Y119.157 E3.45663\nG1 X119.806 Y119.157 E.02425\nM73 P65 R1\nG1 X185.843 Y185.194 E3.49092\nM73 P65 R1\nG1 X185.843 Y185.843 E.02425\nG1 X119.157 Y119.157 E3.52522\nG1 X119.157 Y119.806 E.02425\nG1 X185.194 Y185.843 E3.49093\nG1 X184.546 Y185.843 E.02425\nM73 P66 R1\nG1 X119.157 Y120.454 E3.45663\nM73 P66 R1\nG1 X119.157 Y121.103 E.02425\nG1 X183.897 Y185.843 E3.42234\nG1 X183.248 Y185.843 E.02425\nM73 P67 R1\nG1 X119.157 Y121.752 E3.38805\nM73 P67 R1\nG1 X119.157 Y122.401 E.02425\nG1 X182.599 Y185.843 E3.35375\nG1 X181.951 Y185.843 E.02425\nM73 P68 R1\nG1 X119.157 Y123.049 E3.31946\nM73 P68 R1\nG1 X119.157 Y123.698 E.02425\nG1 X181.302 Y185.843 E3.28516\nG1 X180.653 Y185.843 E.02425\nM73 P69 R1\nG1 X119.157 Y124.347 E3.25087\nM73 P69 R1\nG1 X119.157 Y124.995 E.02425\nG1 X180.005 Y185.843 E3.21658\nG1 X179.356 Y185.843 E.02425\nG1 X119.157 Y125.644 E3.18228\nG1 X119.157 Y126.293 E.02425\nM73 P70 R1\nG1 X178.707 Y185.843 E3.14799\nM73 P70 R1\nG1 X178.058 Y185.843 E.02425\nG1 X119.157 Y126.942 E3.1137\nG1 X119.157 Y127.59 E.02425\nM73 P71 R1\nG1 X177.41 Y185.843 E3.0794\nM73 P71 R1\nG1 X176.761 Y185.843 E.02425\nG1 X119.157 Y128.239 E3.04511\nG1 X119.157 Y128.888 E.02425\nG1 X176.112 Y185.843 E3.01082\nG1 X175.463 Y185.843 E.02425\nM73 P72 R1\nG1 X119.157 Y129.537 E2.97652\nM73 P72 R1\nG1 X119.157 Y130.185 E.02425\nG1 X174.815 Y185.843 E2.94223\nG1 X174.166 Y185.843 E.02425\nM73 P73 R1\nG1 X119.157 Y130.834 E2.90794\nM73 P73 R1\nG1 X119.157 Y131.483 E.02425\nG1 X173.517 Y185.843 E2.87364\nG1 X172.869 Y185.843 E.02425\nG1 X119.157 Y132.131 E2.83935\nG1 X119.157 Y132.78 E.02425\nM73 P74 R1\nG1 X172.22 Y185.843 E2.80506\nM73 P74 R1\nG1 X171.571 Y185.843 E.02425\nG1 X119.157 Y133.429 E2.77076\nG1 X119.157 Y134.078 E.02425\nM73 P75 R1\nG1 X170.922 Y185.843 E2.73647\nM73 P75 R1\nG1 X170.274 Y185.843 E.02425\nG1 X119.157 Y134.726 E2.70218\nG1 X119.157 Y135.375 E.02425\nM73 P75 R0\nG1 X169.625 Y185.843 E2.66788\nM73 P75 R0\nG1 X168.976 Y185.843 E.02425\nM73 P76 R0\nG1 X119.157 Y136.024 E2.63359\nM73 P76 R0\nG1 X119.157 Y136.673 E.02425\nG1 X168.327 Y185.843 E2.59929\nG1 X167.679 Y185.843 E.02425\nG1 X119.157 Y137.321 E2.565\nG1 X119.157 Y137.97 E.02425\nM73 P77 R0\nG1 X167.03 Y185.843 E2.53071\nM73 P77 R0\nG1 X166.381 Y185.843 E.02425\nG1 X119.157 Y138.619 E2.49641\nG1 X119.157 Y139.267 E.02425\nG1 X165.733 Y185.843 E2.46212\nG1 X165.084 Y185.843 E.02425\nM73 P78 R0\nG1 X119.157 Y139.916 E2.42783\nM73 P78 R0\nG1 X119.157 Y140.565 E.02425\nG1 X164.435 Y185.843 E2.39353\nG1 X163.786 Y185.843 E.02425\nG1 X119.157 Y141.214 E2.35924\nG1 X119.157 Y141.862 E.02425\nM73 P79 R0\nG1 X163.138 Y185.843 E2.32495\nM73 P79 R0\nG1 X162.489 Y185.843 E.02425\nG1 X119.157 Y142.511 E2.29065\nG1 X119.157 Y143.16 E.02425\nG1 X161.84 Y185.843 E2.25636\nG1 X161.191 Y185.843 E.02425\nM73 P80 R0\nG1 X119.157 Y143.809 E2.22207\nM73 P80 R0\nG1 X119.157 Y144.457 E.02425\nG1 X160.543 Y185.843 E2.18777\nG1 X159.894 Y185.843 E.02425\nG1 X119.157 Y145.106 E2.15348\nG1 X119.157 Y145.755 E.02425\nM73 P81 R0\nG1 X159.245 Y185.843 E2.11919\nM73 P81 R0\nG1 X158.597 Y185.843 E.02425\nG1 X119.157 Y146.403 E2.08489\nG1 X119.157 Y147.052 E.02425\nG1 X157.948 Y185.843 E2.0506\nG1 X157.299 Y185.843 E.02425\nM73 P82 R0\nG1 X119.157 Y147.701 E2.01631\nM73 P82 R0\nG1 X119.157 Y148.35 E.02425\nG1 X156.65 Y185.843 E1.98201\nG1 X156.002 Y185.843 E.02425\nG1 X119.157 Y148.998 E1.94772\nG1 X119.157 Y149.647 E.02425\nG1 X155.353 Y185.843 E1.91343\nG1 X154.704 Y185.843 E.02425\nM73 P83 R0\nG1 X119.157 Y150.296 E1.87913\nM73 P83 R0\nG1 X119.157 Y150.944 E.02425\nG1 X154.056 Y185.843 E1.84484\nG1 X153.407 Y185.843 E.02425\nG1 X119.157 Y151.593 E1.81054\nG1 X119.157 Y152.242 E.02425\nM73 P84 R0\nG1 X152.758 Y185.843 E1.77625\nM73 P84 R0\nG1 X152.109 Y185.843 E.02425\nG1 X119.157 Y152.891 E1.74196\nG1 X119.157 Y153.539 E.02425\nG1 X151.461 Y185.843 E1.70766\nG1 X150.812 Y185.843 E.02425\nG1 X119.157 Y154.188 E1.67337\nG1 X119.157 Y154.837 E.02425\nM73 P85 R0\nG1 X150.163 Y185.843 E1.63908\nM73 P85 R0\nG1 X149.514 Y185.843 E.02425\nG1 X119.157 Y155.486 E1.60478\nG1 X119.157 Y156.134 E.02425\nG1 X148.866 Y185.843 E1.57049\nG1 X148.217 Y185.843 E.02425\nG1 X119.157 Y156.783 E1.5362\nG1 X119.157 Y157.432 E.02425\nM73 P86 R0\nG1 X147.568 Y185.843 E1.5019\nM73 P86 R0\nG1 X146.92 Y185.843 E.02425\nG1 X119.157 Y158.08 E1.46761\nG1 X119.157 Y158.729 E.02425\nG1 X146.271 Y185.843 E1.43332\nG1 X145.622 Y185.843 E.02425\nG1 X119.157 Y159.378 E1.39902\nG1 X119.157 Y160.027 E.02425\nM73 P87 R0\nG1 X144.973 Y185.843 E1.36473\nM73 P87 R0\nG1 X144.325 Y185.843 E.02425\nG1 X119.157 Y160.675 E1.33044\nG1 X119.157 Y161.324 E.02425\nG1 X143.676 Y185.843 E1.29614\nG1 X143.027 Y185.843 E.02425\nG1 X119.157 Y161.973 E1.26185\nG1 X119.157 Y162.622 E.02425\nG1 X142.378 Y185.843 E1.22756\nM73 P88 R0\nG1 X141.73 Y185.843 E.02425\nM73 P88 R0\nG1 X119.157 Y163.27 E1.19326\nG1 X119.157 Y163.919 E.02425\nG1 X141.081 Y185.843 E1.15897\nG1 X140.432 Y185.843 E.02425\nG1 X119.157 Y164.568 E1.12468\nG1 X119.157 Y165.216 E.02425\nG1 X139.784 Y185.843 E1.09038\nG1 X139.135 Y185.843 E.02425\nM73 P89 R0\nG1 X119.157 Y165.865 E1.05609\nM73 P89 R0\nG1 X119.157 Y166.514 E.02425\nG1 X138.486 Y185.843 E1.02179\nG1 X137.837 Y185.843 E.02425\nG1 X119.157 Y167.163 E.9875\nG1 X119.157 Y167.811 E.02425\nG1 X137.189 Y185.843 E.95321\nG1 X136.54 Y185.843 E.02425\nG1 X119.157 Y168.46 E.91891\nG1 X119.157 Y169.109 E.02425\nG1 X135.891 Y185.843 E.88462\nG1 X135.242 Y185.843 E.02425\nM73 P90 R0\nG1 X119.157 Y169.758 E.85033\nM73 P90 R0\nG1 X119.157 Y170.406 E.02425\nG1 X134.594 Y185.843 E.81603\nG1 X133.945 Y185.843 E.02425\nG1 X119.157 Y171.055 E.78174\nG1 X119.157 Y171.704 E.02425\nG1 X133.296 Y185.843 E.74745\nG1 X132.648 Y185.843 E.02425\nG1 X119.157 Y172.352 E.71315\nG1 X119.157 Y173.001 E.02425\nG1 X131.999 Y185.843 E.67886\nM73 P91 R0\nG1 X131.35 Y185.843 E.02425\nM73 P91 R0\nG1 X119.157 Y173.65 E.64457\nG1 X119.157 Y174.299 E.02425\nG1 X130.701 Y185.843 E.61027\nG1 X130.053 Y185.843 E.02425\nG1 X119.157 Y174.947 E.57598\nG1 X119.157 Y175.596 E.02425\nG1 X129.404 Y185.843 E.54169\nG1 X128.755 Y185.843 E.02425\nG1 X119.157 Y176.245 E.50739\nG1 X119.157 Y176.893 E.02425\nG1 X128.107 Y185.843 E.4731\nG1 X127.458 Y185.843 E.02425\nG1 X119.157 Y177.542 E.43881\nM73 P92 R0\nG1 X119.157 Y178.191 E.02425\nM73 P92 R0\nG1 X126.809 Y185.843 E.40451\nG1 X126.16 Y185.843 E.02425\nG1 X119.157 Y178.84 E.37022\nG1 X119.157 Y179.488 E.02425\nG1 X125.512 Y185.843 E.33592\nG1 X124.863 Y185.843 E.02425\nG1 X119.157 Y180.137 E.30163\nG1 X119.157 Y180.786 E.02425\nG1 X124.214 Y185.843 E.26734\nG1 X123.565 Y185.843 E.02425\nG1 X119.157 Y181.435 E.23304\nG1 X119.157 Y182.083 E.02425\nG1 X122.917 Y185.843 E.19875\nG1 X122.268 Y185.843 E.02425\nG1 X119.157 Y182.732 E.16446\nG1 X119.157 Y183.381 E.02425\nG1 X121.619 Y185.843 E.13016\nG1 X120.971 Y185.843 E.02425\nG1 X119.157 Y184.029 E.09587\nM73 P93 R0\nG1 X119.157 Y184.678 E.02425\nM73 P93 R0\nG1 X120.322 Y185.843 E.06158\nG1 X119.673 Y185.843 E.02425\nG1 X118.951 Y185.121 E.03816\nG1 E-.22857 F1800\n;WIPE_START\nG1 F6300\nG1 X119.673 Y185.843 E-.29165\nG1 X120.322 Y185.843 E-.18535\nG1 X120.088 Y185.609 E-.09443\n;WIPE_END\nEXCLUDE_OBJECT_END NAME=Cube_id_0_copy_0\nM106 S0\nM106 P2 S0\n;TYPE:Custom\nM141 S0\nM104 S0\nM140 S0\nG1 E-3 F1800\nG0 Z3.2 F600\nG0 X0 Y0 F12000\nG1 Z150 F600\nM106 P3 S0\nM73 P100 R0\n; EXECUTABLE_BLOCK_END\n\n; filament used [mm] = 525.65\n; filament used [cm3] = 1.26\n; filament used [g] = 1.57\n; filament cost = 0.03\n; total filament used [g] = 1.57\n; total filament cost = 0.03\n; total layers count = 1\n; estimated printing time (normal mode) = 4m 4s\n\n; CONFIG_BLOCK_START\n; accel_to_decel_enable = 1\n; accel_to_decel_factor = 50%\n; activate_air_filtration = 1\n; activate_chamber_temp_control = 0\n; adaptive_bed_mesh_margin = 0\n; adaptive_pressure_advance = 0\n; adaptive_pressure_advance_bridges = 0\n; adaptive_pressure_advance_model = \"0,0,0\\n0,0,0\"\n; adaptive_pressure_advance_overhangs = 0\n; additional_cooling_fan_speed = 0\n; alternate_extra_wall = 0\n; auxiliary_fan = 1\n; bbl_calib_mark_logo = 1\n; bbl_use_printhost = 0\n; bed_custom_model = \n; bed_custom_texture = \n; bed_exclude_area = 0x305,0x302,35x302,35x305,305x305,305x305,305x305,305x20,293x20,293x0,305x0,305x20,305x305\n; bed_mesh_max = 99999,99999\n; bed_mesh_min = -99999,-99999\n; bed_mesh_probe_distance = 50,50\n; before_layer_change_gcode = ;BEFORE_LAYER_CHANGE\\n;[layer_z]\\nG92 E0\\n\n; best_object_pos = 0.5,0.5\n; bottom_shell_layers = 3\n; bottom_shell_thickness = 0\n; bottom_solid_infill_flow_ratio = 1\n; bottom_surface_pattern = monotonic\n; bridge_acceleration = 50%\n; bridge_angle = 0\n; bridge_density = 100%\n; bridge_flow = 1\n; bridge_no_support = 0\n; bridge_speed = 50\n; brim_ears_detection_length = 1\n; brim_ears_max_angle = 125\n; brim_object_gap = 0.1\n; brim_type = auto_brim\n; brim_width = 5\n; chamber_temperature = 0\n; change_extrusion_role_gcode = \n; change_filament_gcode = \n; close_fan_the_first_x_layers = 1\n; complete_print_exhaust_fan_speed = 0\n; cool_plate_temp = 60\n; cool_plate_temp_initial_layer = 60\n; cooling_tube_length = 5\n; cooling_tube_retraction = 91.5\n; counterbore_hole_bridging = none\n; curr_bed_type = High Temp Plate\n; default_acceleration = 10000\n; default_filament_colour = \"\"\n; default_filament_profile = \"Qidi Generic PLA @Qidi X-Plus 4 0.4 nozzle\"\n; default_jerk = 0\n; default_print_profile = 0.20mm Standard @Qidi XPlus4\n; deretraction_speed = 0\n; detect_narrow_internal_solid_infill = 1\n; detect_overhang_wall = 1\n; detect_thin_wall = 0\n; different_settings_to_system = only_one_wall_top;skirt_loops;wall_loops;;thumbnails\n; disable_m73 = 0\n; dont_filter_internal_bridges = disabled\n; dont_slow_down_outer_wall = 1\n; draft_shield = disabled\n; during_print_exhaust_fan_speed = 100\n; elefant_foot_compensation = 0.15\n; elefant_foot_compensation_layers = 1\n; emit_machine_limits_to_gcode = 1\n; enable_arc_fitting = 0\n; enable_filament_ramming = 1\n; enable_long_retraction_when_cut = 0\n; enable_overhang_bridge_fan = 0\n; enable_overhang_speed = 1\n; enable_pressure_advance = 1\n; enable_prime_tower = 0\n; enable_support = 0\n; enforce_support_layers = 0\n; eng_plate_temp = 60\n; eng_plate_temp_initial_layer = 60\n; ensure_vertical_shell_thickness = ensure_all\n; exclude_object = 1\n; extra_loading_move = -2\n; extra_perimeters_on_overhangs = 0\n; extruder_clearance_height_to_lid = 135\n; extruder_clearance_height_to_rod = 32\n; extruder_clearance_radius = 72\n; extruder_colour = #C0C0C0\n; extruder_offset = 0x0\n; fan_cooling_layer_time = 60\n; fan_kickstart = 0\n; fan_max_speed = 100\n; fan_min_speed = 100\n; fan_speedup_overhangs = 1\n; fan_speedup_time = 0\n; filament_colour = #C0C0C0\n; filament_cooling_final_speed = 3.4\n; filament_cooling_initial_speed = 2.2\n; filament_cooling_moves = 4\n; filament_cost = 20\n; filament_density = 1.24\n; filament_diameter = 1.75\n; filament_end_gcode = \" \"\n; filament_flow_ratio = 0.98\n; filament_ids = GFB99\n; filament_is_support = 0\n; filament_loading_speed = 28\n; filament_loading_speed_start = 3\n; filament_max_volumetric_speed = 14\n; filament_minimal_purge_on_wipe_tower = 15\n; filament_multitool_ramming = 0\n; filament_multitool_ramming_flow = 10\n; filament_multitool_ramming_volume = 10\n; filament_notes = \"\"\n; filament_ramming_parameters = \"120 100 6.6 6.8 7.2 7.6 7.9 8.2 8.7 9.4 9.9 10.0| 0.05 6.6 0.45 6.8 0.95 7.8 1.45 8.3 1.95 9.7 2.45 10 2.95 7.6 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6\"\n; filament_settings_id = \"Qidi Generic PLA @Qidi X-Plus 4 0.4 nozzle\"\n; filament_shrink = 100%\n; filament_shrinkage_compensation_z = 100%\n; filament_soluble = 0\n; filament_stamping_distance = 0\n; filament_stamping_loading_speed = 0\n; filament_start_gcode = \" \"\n; filament_toolchange_delay = 0\n; filament_type = PLA\n; filament_unloading_speed = 90\n; filament_unloading_speed_start = 100\n; filament_vendor = QIDI\n; filename_format = {input_filename_base}_{filament_type[0]}_{print_time}.gcode\n; filter_out_gap_fill = 2\n; first_layer_print_sequence = 0\n; flush_into_infill = 0\n; flush_into_objects = 0\n; flush_into_support = 1\n; flush_multiplier = 1\n; flush_volumes_matrix = 0\n; flush_volumes_vector = 140,140\n; full_fan_speed_layer = 3\n; fuzzy_skin = none\n; fuzzy_skin_first_layer = 0\n; fuzzy_skin_point_distance = 0.8\n; fuzzy_skin_thickness = 0.3\n; gap_fill_target = nowhere\n; gap_infill_speed = 250\n; gcode_add_line_number = 0\n; gcode_comments = 0\n; gcode_flavor = klipper\n; gcode_label_objects = 0\n; has_scarf_joint_seam = 0\n; head_wrap_detect_zone = \n; high_current_on_filament_swap = 0\n; hole_to_polyhole = 0\n; hole_to_polyhole_threshold = 0.01\n; hole_to_polyhole_twisted = 1\n; host_type = octoprint\n; hot_plate_temp = 60\n; hot_plate_temp_initial_layer = 60\n; idle_temperature = 0\n; independent_support_layer_height = 0\n; infill_anchor = 400%\n; infill_anchor_max = 20\n; infill_combination = 0\n; infill_combination_max_layer_height = 100%\n; infill_direction = 45\n; infill_jerk = 9\n; infill_wall_overlap = 15%\n; inherits_group = ;;\"Qidi X-Plus 4 0.4 nozzle\"\n; initial_layer_acceleration = 500\n; initial_layer_infill_speed = 105\n; initial_layer_jerk = 9\n; initial_layer_line_width = 0.5\n; initial_layer_min_bead_width = 85%\n; initial_layer_print_height = 0.2\n; initial_layer_speed = 50\n; initial_layer_travel_speed = 50%\n; inner_wall_acceleration = 5000\n; inner_wall_jerk = 9\n; inner_wall_line_width = 0.45\n; inner_wall_speed = 300\n; interface_shells = 0\n; interlocking_beam = 0\n; interlocking_beam_layer_count = 2\n; interlocking_beam_width = 0.8\n; interlocking_boundary_avoidance = 2\n; interlocking_depth = 2\n; interlocking_orientation = 22.5\n; internal_bridge_flow = 1\n; internal_bridge_speed = 50\n; internal_solid_infill_acceleration = 100%\n; internal_solid_infill_line_width = 0.42\n; internal_solid_infill_pattern = zig-zag\n; internal_solid_infill_speed = 250\n; ironing_angle = -1\n; ironing_flow = 10%\n; ironing_pattern = zig-zag\n; ironing_spacing = 0.15\n; ironing_speed = 30\n; ironing_type = no ironing\n; is_infill_first = 0\n; layer_change_gcode = G92 E0\\nSET_PRINT_STATS_INFO CURRENT_LAYER={layer_num + 1}\n; layer_height = 0.2\n; line_width = 0.42\n; long_retractions_when_cut = 0\n; machine_end_gcode = M141 S0\\nM104 S0\\nM140 S0\\nG1 E-3 F1800\\nG0 Z{min(max_print_height, max_layer_z + 3)} F600\\nG0 X0 Y0 F12000\\n{if max_layer_z < max_print_height / 2}G1 Z{max_print_height / 2 + 10} F600{else}G1 Z{min(max_print_height, max_layer_z + 3)}{endif}\n; machine_load_filament_time = 0\n; machine_max_acceleration_e = 5000\n; machine_max_acceleration_extruding = 20000\n; machine_max_acceleration_retracting = 20000\n; machine_max_acceleration_travel = 0,0\n; machine_max_acceleration_x = 20000\n; machine_max_acceleration_y = 20000\n; machine_max_acceleration_z = 500\n; machine_max_jerk_e = 4\n; machine_max_jerk_x = 9\n; machine_max_jerk_y = 9\n; machine_max_jerk_z = 4\n; machine_max_speed_e = 30\n; machine_max_speed_x = 600\n; machine_max_speed_y = 600\n; machine_max_speed_z = 20\n; machine_min_extruding_rate = 0\n; machine_min_travel_rate = 0\n; machine_pause_gcode = M0\n; machine_start_gcode = PRINT_START BED=[hot_plate_temp_initial_layer] HOTEND=[nozzle_temperature_initial_layer] CHAMBER=[chamber_temperature]\\nSET_PRINT_STATS_INFO TOTAL_LAYER=[total_layer_count]\\nM83\\nM140 S[hot_plate_temp_initial_layer]\\nM104 S[nozzle_temperature_initial_layer]\\nM141 S[chamber_temperature]\\nG4 P3000\\nG0 X{max((min(print_bed_max[0] - 12, first_layer_print_min[0] + 80) - 85), 0)} Y{max((min(print_bed_max[1] - 3, first_layer_print_min[1] + 80) - 85), 0)} Z5 F6000\\nG0 Z[initial_layer_print_height] F600\\nG1 E3 F1800\\nG1 X{(min(print_bed_max[0] - 12, first_layer_print_min[0] + 80))} E{85 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\\nG1 Y{max((min(print_bed_max[1] - 3, first_layer_print_min[1] + 80) - 85), 0) + 2} E{2 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\\nG1 X{max((min(print_bed_max[0] - 12, first_layer_print_min[0] + 80) - 85), 0)} E{85 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\\nG1 Y{max((min(print_bed_max[1] - 3, first_layer_print_min[1] + 80) - 85), 0) + 85} E{83 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\\nG1 X{max((min(print_bed_max[0] - 12, first_layer_print_min[0] + 80) - 85), 0) + 2} E{2 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\\nG1 Y{max((min(print_bed_max[1] - 3, first_layer_print_min[1] + 80) - 85), 0) + 3} E{82 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\\nG1 X{max((min(print_bed_max[0] - 12, first_layer_print_min[0] + 80) - 85), 0) + 3} Z0\\nG1 X{max((min(print_bed_max[0] - 12, first_layer_print_min[0] + 80) - 85), 0) + 6}\\nG1 Z1 F600\\nSET_PRINT_STATS_INFO CURRENT_LAYER=1\\n\n; machine_tool_change_time = 0\n; machine_unload_filament_time = 0\n; make_overhang_printable = 0\n; make_overhang_printable_angle = 55\n; make_overhang_printable_hole_size = 0\n; manual_filament_change = 0\n; max_bridge_length = 10\n; max_layer_height = 0.28\n; max_travel_detour_distance = 0\n; max_volumetric_extrusion_rate_slope = 0\n; max_volumetric_extrusion_rate_slope_segment_length = 3\n; min_bead_width = 85%\n; min_feature_size = 25%\n; min_layer_height = 0.08\n; min_length_factor = 0.5\n; min_skirt_length = 0\n; min_width_top_surface = 300%\n; minimum_sparse_infill_area = 15\n; mmu_segmented_region_interlocking_depth = 0\n; mmu_segmented_region_max_width = 0\n; notes = If you want to use Orca's chamber temperature control feature, check that printer.cfg has added the following M191 macro.\\nTo add it: go to Fluidd web interface--configuration, copy the following code to the top of the printer.cfg document, SAVE&RESATART  \\n\\n[gcode_macro M191]\\ngcode:\\n    {% set s = params.S|float %}\\n    {% if s == 0 %}\\n        # If target temperature is 0, do nothing\\n        M117 Chamber heating cancelled\\n    {% else %}\\n        SET_HEATER_TEMPERATURE HEATER=chamber_heater TARGET={s}\\n        # Orca: uncomment the following line if you want to use heat bed to assist chamber heating\\n        M140 S90\\n        TEMPERATURE_WAIT SENSOR=\\\"heater_generic chamber_heater\\\" MINIMUM={s-1} MAXIMUM={s+1}\\n        M117 Chamber at target temperature\\n    {% endif %}\n; nozzle_diameter = 0.4\n; nozzle_height = 2.5\n; nozzle_hrc = 0\n; nozzle_temperature = 210\n; nozzle_temperature_initial_layer = 210\n; nozzle_temperature_range_high = 240\n; nozzle_temperature_range_low = 190\n; nozzle_type = hardened_steel\n; nozzle_volume = 0\n; only_one_wall_first_layer = 0\n; only_one_wall_top = 0\n; ooze_prevention = 0\n; other_layers_print_sequence = 0\n; other_layers_print_sequence_nums = 0\n; outer_wall_acceleration = 3000\n; outer_wall_jerk = 9\n; outer_wall_line_width = 0.42\n; outer_wall_speed = 200\n; overhang_1_4_speed = 0\n; overhang_2_4_speed = 50\n; overhang_3_4_speed = 30\n; overhang_4_4_speed = 10\n; overhang_fan_speed = 100\n; overhang_fan_threshold = 95%\n; overhang_reverse = 0\n; overhang_reverse_internal_only = 0\n; overhang_reverse_threshold = 50%\n; overhang_speed_classic = 0\n; parking_pos_retraction = 92\n; pellet_flow_coefficient = 0.4157\n; pellet_modded_printer = 0\n; post_process = \n; precise_outer_wall = 0\n; precise_z_height = 0\n; preferred_orientation = 0\n; preheat_steps = 1\n; preheat_time = 30\n; pressure_advance = 0.034\n; prime_tower_brim_width = 3\n; prime_tower_width = 35\n; prime_volume = 45\n; print_compatible_printers = \"Qidi X-Plus 4 0.4 nozzle\"\n; print_flow_ratio = 1\n; print_order = default\n; print_sequence = by layer\n; print_settings_id = 0.20mm Standard @Qidi XPlus4\n; printable_area = 0x0,305x0,305x305,0x305\n; printable_height = 280\n; printer_model = Qidi X-Plus 4\n; printer_notes = \n; printer_settings_id = Qidi X-Plus 4 0.4 nozzle - Copy\n; printer_structure = undefine\n; printer_technology = FFF\n; printer_variant = 0.4\n; printhost_authorization_type = key\n; printhost_ssl_ignore_revoke = 0\n; printing_by_object_gcode = \n; purge_in_prime_tower = 1\n; raft_contact_distance = 0.1\n; raft_expansion = 1.5\n; raft_first_layer_density = 90%\n; raft_first_layer_expansion = 2\n; raft_layers = 0\n; reduce_crossing_wall = 0\n; reduce_fan_stop_start_freq = 1\n; reduce_infill_retraction = 1\n; required_nozzle_HRC = 0\n; resolution = 0.012\n; retract_before_wipe = 0%\n; retract_length_toolchange = 2\n; retract_lift_above = 0\n; retract_lift_below = 0\n; retract_lift_enforce = All Surfaces\n; retract_restart_extra = 0\n; retract_restart_extra_toolchange = 0\n; retract_when_changing_layer = 1\n; retraction_distances_when_cut = 18\n; retraction_length = 0.8\n; retraction_minimum_travel = 1\n; retraction_speed = 30\n; role_based_wipe_speed = 1\n; rotate_solid_infill_direction = 1\n; scan_first_layer = 0\n; scarf_angle_threshold = 155\n; scarf_joint_flow_ratio = 1\n; scarf_joint_speed = 100%\n; scarf_overhang_threshold = 40%\n; seam_gap = 15%\n; seam_position = aligned\n; seam_slope_conditional = 0\n; seam_slope_entire_loop = 0\n; seam_slope_inner_walls = 0\n; seam_slope_min_length = 20\n; seam_slope_start_height = 0\n; seam_slope_steps = 10\n; seam_slope_type = none\n; silent_mode = 0\n; single_extruder_multi_material = 1\n; single_extruder_multi_material_priming = 0\n; skirt_distance = 2\n; skirt_height = 1\n; skirt_loops = 10\n; skirt_speed = 50\n; skirt_start_angle = -135\n; skirt_type = combined\n; slice_closing_radius = 0.049\n; slicing_mode = regular\n; slow_down_for_layer_cooling = 1\n; slow_down_layer_time = 8\n; slow_down_layers = 0\n; slow_down_min_speed = 20\n; slowdown_for_curled_perimeters = 1\n; small_area_infill_flow_compensation = 0\n; small_area_infill_flow_compensation_model = 0,0;\"\\n0.2,0.4444\";\"\\n0.4,0.6145\";\"\\n0.6,0.7059\";\"\\n0.8,0.7619\";\"\\n1.5,0.8571\";\"\\n2,0.8889\";\"\\n3,0.9231\";\"\\n5,0.9520\";\"\\n10,1\"\n; small_perimeter_speed = 50%\n; small_perimeter_threshold = 4\n; solid_infill_direction = 45\n; solid_infill_filament = 1\n; sparse_infill_acceleration = 100%\n; sparse_infill_density = 15%\n; sparse_infill_filament = 1\n; sparse_infill_line_width = 0.45\n; sparse_infill_pattern = grid\n; sparse_infill_speed = 270\n; spiral_mode = 0\n; spiral_mode_max_xy_smoothing = 200%\n; spiral_mode_smooth = 0\n; staggered_inner_seams = 0\n; standby_temperature_delta = -5\n; start_end_points = 30x-3,54x245\n; support_air_filtration = 1\n; support_angle = 0\n; support_base_pattern = default\n; support_base_pattern_spacing = 2.5\n; support_bottom_interface_spacing = 0.5\n; support_bottom_z_distance = 0.2\n; support_chamber_temp_control = 1\n; support_critical_regions_only = 0\n; support_expansion = 0\n; support_filament = 0\n; support_interface_bottom_layers = 2\n; support_interface_filament = 0\n; support_interface_loop_pattern = 0\n; support_interface_not_for_body = 1\n; support_interface_pattern = auto\n; support_interface_spacing = 0.5\n; support_interface_speed = 80\n; support_interface_top_layers = 2\n; support_line_width = 0.42\n; support_material_interface_fan_speed = -1\n; support_multi_bed_types = 0\n; support_object_xy_distance = 0.35\n; support_on_build_plate_only = 0\n; support_remove_small_overhang = 1\n; support_speed = 150\n; support_style = default\n; support_threshold_angle = 30\n; support_top_z_distance = 0.2\n; support_type = normal(auto)\n; temperature_vitrification = 45\n; template_custom_gcode = \n; textured_cool_plate_temp = 40\n; textured_cool_plate_temp_initial_layer = 40\n; textured_plate_temp = 60\n; textured_plate_temp_initial_layer = 60\n; thick_bridges = 0\n; thick_internal_bridges = 1\n; thumbnails = 240x240/PNG, 96x96/PNG\n; thumbnails_format = PNG\n; time_cost = 0\n; time_lapse_gcode = ;TIMELAPSE_TAKE_FRAME\\n\n; timelapse_type = 0\n; top_bottom_infill_wall_overlap = 25%\n; top_shell_layers = 5\n; top_shell_thickness = 1\n; top_solid_infill_flow_ratio = 1\n; top_surface_acceleration = 2000\n; top_surface_jerk = 9\n; top_surface_line_width = 0.42\n; top_surface_pattern = monotonicline\n; top_surface_speed = 200\n; travel_acceleration = 10000\n; travel_jerk = 12\n; travel_slope = 3\n; travel_speed = 500\n; travel_speed_z = 0\n; tree_support_adaptive_layer_height = 1\n; tree_support_angle_slow = 25\n; tree_support_auto_brim = 1\n; tree_support_branch_angle = 45\n; tree_support_branch_angle_organic = 40\n; tree_support_branch_diameter = 2\n; tree_support_branch_diameter_angle = 5\n; tree_support_branch_diameter_double_wall = 3\n; tree_support_branch_diameter_organic = 2\n; tree_support_branch_distance = 5\n; tree_support_branch_distance_organic = 1\n; tree_support_brim_width = 3\n; tree_support_tip_diameter = 0.8\n; tree_support_top_rate = 30%\n; tree_support_wall_count = 0\n; upward_compatible_machine = \n; use_firmware_retraction = 0\n; use_relative_e_distances = 1\n; wall_direction = auto\n; wall_distribution_count = 1\n; wall_filament = 1\n; wall_generator = classic\n; wall_loops = 3\n; wall_sequence = inner wall/outer wall\n; wall_transition_angle = 10\n; wall_transition_filter_deviation = 25%\n; wall_transition_length = 100%\n; wipe = 1\n; wipe_before_external_loop = 0\n; wipe_distance = 2\n; wipe_on_loops = 0\n; wipe_speed = 80%\n; wipe_tower_bridging = 10\n; wipe_tower_cone_angle = 0\n; wipe_tower_extra_flow = 100%\n; wipe_tower_extra_spacing = 100%\n; wipe_tower_filament = 0\n; wipe_tower_max_purge_speed = 90\n; wipe_tower_no_sparse_layers = 0\n; wipe_tower_rotation_angle = 0\n; wipe_tower_x = 165.000\n; wipe_tower_x = 165\n; wipe_tower_y = 250.000\n; wipe_tower_y = 250\n; wiping_volumes_extruders = 70,70,70,70,70,70,70,70,70,70\n; xy_contour_compensation = 0\n; xy_hole_compensation = 0\n; z_hop = 0.4\n; z_hop_types = Auto Lift\n; z_offset = 0\n; first_layer_bed_temperature = 60\n; bed_shape = 0x0,305x0,305x305,0x305\n; first_layer_temperature = 210\n; first_layer_height = 0.200\n; CONFIG_BLOCK_END\n\n\n"
  },
  {
    "path": "presliced_z-offset_calibration_files/X-Smart3/z-offset_calibration_X-Smart3_PLA_8m38s.gcode",
    "content": "; HEADER_BLOCK_START\n; generated by OrcaSlicer 2.2.0 on 2025-06-04 at 11:42:33\n; total layer number: 1\n; filament_density: 1.24\n; filament_diameter: 1.75\n; max_z_height: 0.20\n; HEADER_BLOCK_END\n\n; THUMBNAIL_BLOCK_START\n\n;\n; thumbnail begin 140x140 1064\n; iVBORw0KGgoAAAANSUhEUgAAAIwAAACMCAYAAACuwEE+AAAC5ElEQVR4Ae3dsW3jQBAFUBbkIi53BW\n; 7DidJLlKkHBapAFbg0H2jAOIKQLXG1JGd33gM+cKmBub9Dr0QPAwAAAAAAAAAAAAAAQCovLy9/Brjn\n; 7e3t7/V6/Rwz/nuAn0yH5TvH4/FjgKlbgzIfGkcUX+4NyzSOqMTGxhib49Fh0TaJLWkVbZNcjWGxEC\n; dQc1DmcUR1Zs1hcUR1ZPyfv/agWIg7sUWraJtO7Dks2qYhEQZlHkMTVMRhmbbNQAyRB8URFUwrwzKN\n; hXgHpfdA2iahFltF2+ykp2GZts1AXT0OyjyOqEoyDMt3HFFPaH2xLY2FuECmVtE2TzIsV23zCIPycw\n; zNjGG5H0fUYFCWJvURZVjKk65tMj4u106KttEq9dNt2xiW9dLVfZRB2S7NH1GGZfs0eURlvQeKkqYW\n; Yq0SJ+HbxrDES8iF2KDET5gjyrC0k12PqK2/6C51sstCrFXaz2ZtY1j6yaptY1D6TfW2MSz9p8rjt0\n; HJNzTFR5RhyZtFR5R7IBnzUNtoFZnn17YZJ+pyuTT1A8m6eeh4ciTJ+/v7sqem19dXx1PSFP9exgKc\n; K6fT6XOo4XA4fLT0g8vyVP9tr4W4z5zP53U/K6Nt+slmN9Y+C2NYiliI20u1xbaU3w63kzDfIrAQx8\n; 7qi20pC3G8hP9ukrYxLEUsxPtl8T1QFBbi7dP8+2IcUdtk98fl2izE66Xbt1Bpm/pJ8VZNbfN8ml1s\n; S/mAVnlSv+TZ4/fj6W6xLeXx+368On7GQnw7Ye+BorAQ/49WeZAPaBmWIhkX4nSPy7X5I6Es1vtCPC\n; 62A/X1uBBrlZX11DaGZUMtt43Fdict3kdplZ218sIA90DBRD6itEpQ0RZi90CNiNA2WqUxe95HGZaG\n; bbkQW2w7scV9lFbpzFoLscW2czUXYq2SRI22MSwJlSzE7oGSW3IfpVX4cu8+yuMyN91aiLUKv5ouxB\n; 6XAQAAAAAAAAAAAAAA4KZ/Yu4wU8U/g+sAAAAASUVORK5CYII=\n; thumbnail end\n; THUMBNAIL_BLOCK_END\n\n; THUMBNAIL_BLOCK_START\n\n;\n; thumbnail begin 48x48 408\n; iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAA+UlEQVR4Ae2YwQ3DIAxFGShDdI2swY\n; VrL8zBgQmYIKO14oBEUYICBGNX/0mWqp5+/L+FQSkAAABgAtu2vUIIH2vtEX8rSez7/o7i84r/KQnE\n; jpfiU7F246zrV8XOjRbxuRtqNT3C2URqVPyySMWO1QaVtRtPdp3cDQrxUwacUnhZw5FaKX4oUmmP4V\n; JNA86h691ucBZfdUOC8LJ+PoJb5u/UaZxmnLAkwv9miPNIcXLDOdd3qIk9yEo3vPcyxedQRkr0Rjr9\n; cjNrwLXWtHdksVfKnCfcYPFOZIw5xHT9ipZ9ivUzYy1S5IPai+jH3UQa8O49BgAAALjBF4+89dX6Zn\n; pSAAAAAElFTkSuQmCC\n; thumbnail end\n; THUMBNAIL_BLOCK_END\n\n; external perimeters extrusion width = 0.42mm\n; perimeters extrusion width = 0.45mm\n; infill extrusion width = 0.45mm\n; solid infill extrusion width = 0.42mm\n; top infill extrusion width = 0.42mm\n; first layer extrusion width = 0.50mm\n\n; EXECUTABLE_BLOCK_START\nEXCLUDE_OBJECT_DEFINE NAME=Cube_id_0_copy_0 CENTER=87.5,90 POLYGON=[[52.5,55],[122.5,55],[122.5,125],[52.5,125],[52.5,55]]\nM73 P0 R8\nM106 S0\nM106 P2 S0\n;TYPE:Custom\nPRINT_START\nG28\nM141 S0\nG0 Z50 F600\nM190 S60\nG28 Z\nG29; mesh bed leveling ,comment this code to close it\nG0 X0 Y0 Z50 F6000\nM73 P52 R4\nM191 S0\nM109 S210\nM106 P3 S255\nM83\nG4 P3000\nG0 X40.9292 Y43.4292 Z5 F6000\nM73 P53 R4\nG0 Z0.2 F600\nM73 P53 R3\nG1 E3 F1800\nG1 X125.929 E3.4 F3000\nM73 P51 R4\nG1 Y45.4292 E0.08 F3000\nM73 P54 R3\nM73 P52 R4\nG1 X40.9292 E3.4 F3000\nM73 P53 R4\nG1 Y128.429 E3.32 F3000\nM73 P53 R3\nG1 X42.9292 E0.08 F3000\nG1 Y46.4292 E3.28 F3000\nG1 X52.9292 E-0.4 F3000\nM73 P55 R3\nM73 P54 R3\nG1 E0.4 F3000\nM106 P3 S255\nG90\nG21\nM83 ; use relative distances for extrusion\nSET_PRESSURE_ADVANCE ADVANCE=0.031; Override pressure advance value\nM106 S0\nM106 P2 S0\n;LAYER_CHANGE\n;Z:0.2\n;HEIGHT:0.2\n;BEFORE_LAYER_CHANGE\n;0.2\nG92 E0\n\nG1 E-.8 F1800\n;TIMELAPSE_TAKE_FRAME\n\n;_SET_FAN_SPEED_CHANGING_LAYER\nSET_VELOCITY_LIMIT ACCEL=500 ACCEL_TO_DECEL=250\nG1 X47.846 Y50.738 F15000\nG1 Z.6\nG1 Z.2\nM73 P55 R3\nG1 E.8 F1800\n;TYPE:Skirt\n;WIDTH:0.5\nG1 F3000\nG1 X49.438 Y49.446 E.07635\nG1 X52.5 Y48.658 E.11778\nG1 X122.5 Y48.658 E2.60723\nG1 X124.708 Y49.055 E.08357\nG1 X126.64 Y50.195 E.08357\nG1 X128.054 Y51.938 E.08357\nG1 X128.842 Y55 E.11778\nG1 X128.842 Y125 E2.60723\nG1 X128.445 Y127.208 E.08357\nM73 P56 R3\nG1 X127.305 Y129.14 E.08357\nG1 X125.562 Y130.554 E.08357\nG1 X122.5 Y131.342 E.11778\nG1 X52.5 Y131.342 E2.60723\nG1 X50.292 Y130.945 E.08357\nM73 P56 R3\nG1 X48.36 Y129.805 E.08357\nG1 X46.946 Y128.062 E.08357\nG1 X46.158 Y125 E.11778\nG1 X46.158 Y55 E2.60723\nG1 X46.555 Y52.792 E.08357\nG1 X47.695 Y50.86 E.08357\nG1 X47.815 Y50.763 E.00572\nG1 X48.148 Y51.039 F15000\nG1 F3000\nG1 X49.871 Y49.735 E.08047\nG1 X52.5 Y49.115 E.10062\nG1 X122.5 Y49.115 E2.60723\nG1 X124.624 Y49.511 E.08047\nM73 P57 R3\nG1 X126.461 Y50.648 E.08047\nG1 X127.765 Y52.371 E.08047\nG1 X128.385 Y55 E.10062\nG1 X128.385 Y125 E2.60723\nG1 X127.989 Y127.124 E.08047\nM73 P57 R3\nG1 X126.852 Y128.961 E.08047\nG1 X125.129 Y130.265 E.08047\nG1 X122.5 Y130.885 E.10062\nG1 X52.5 Y130.885 E2.60723\nG1 X50.376 Y130.489 E.08047\nG1 X48.539 Y129.352 E.08047\nG1 X47.235 Y127.629 E.08047\nG1 X46.615 Y125 E.10062\nG1 X46.615 Y55 E2.60723\nG1 X47.011 Y52.876 E.08047\nG1 X48.127 Y51.073 E.07898\nG1 X48.529 Y51.334 F15000\nG1 F3000\nM73 P58 R3\nG1 X48.599 Y51.225 E.00483\nG1 X50.3 Y50.038 E.07726\nG1 X52.5 Y49.572 E.08376\nG1 X122.5 Y49.572 E2.60723\nG1 X124.536 Y49.968 E.07726\nM73 P58 R3\nG1 X126.275 Y51.099 E.07726\nG1 X127.462 Y52.8 E.07726\nG1 X127.928 Y55 E.08376\nG1 X127.928 Y125 E2.60723\nG1 X127.532 Y127.036 E.07726\nG1 X126.401 Y128.775 E.07726\nG1 X124.7 Y129.962 E.07726\nG1 X122.5 Y130.428 E.08376\nG1 X52.5 Y130.428 E2.60723\nG1 X50.464 Y130.032 E.07726\nG1 X48.725 Y128.901 E.07726\nG1 X47.538 Y127.2 E.07726\nG1 X47.072 Y125 E.08376\nG1 X47.072 Y55 E2.60723\nG1 X47.468 Y52.964 E.07726\nM73 P59 R3\nG1 X48.507 Y51.367 E.07094\nG1 X48.9 Y51.638 F15000\nG1 F3000\nG1 X49.05 Y51.421 E.00981\nG1 X50.724 Y50.357 E.0739\nM73 P59 R3\nG1 X52.5 Y50.029 E.06726\nG1 X122.5 Y50.029 E2.60723\nG1 X124.444 Y50.425 E.0739\nG1 X126.079 Y51.55 E.0739\nG1 X127.143 Y53.224 E.0739\nG1 X127.471 Y55 E.06726\nG1 X127.471 Y125 E2.60723\nG1 X127.075 Y126.944 E.0739\nG1 X125.95 Y128.579 E.0739\nG1 X124.276 Y129.643 E.0739\nG1 X122.5 Y129.971 E.06726\nG1 X52.5 Y129.971 E2.60723\nG1 X50.556 Y129.575 E.0739\nM73 P60 R3\nG1 X48.921 Y128.45 E.0739\nG1 X47.857 Y126.776 E.0739\nG1 X47.529 Y125 E.06726\nG1 X47.529 Y55 E2.60723\nG1 X47.925 Y53.056 E.0739\nM73 P60 R3\nG1 X48.878 Y51.671 E.0626\nG1 X49.261 Y51.952 F15000\nG1 F3000\nG1 X49.499 Y51.628 E.01498\nG1 X51.142 Y50.695 E.07039\nG1 X52.5 Y50.486 E.05116\nG1 X122.5 Y50.486 E2.60723\nG1 X124.348 Y50.882 E.07039\nG1 X125.872 Y51.999 E.07039\nG1 X126.805 Y53.642 E.07039\nG1 X127.014 Y55 E.05116\nG1 X127.014 Y125 E2.60723\nG1 X126.618 Y126.848 E.07039\nM73 P61 R3\nG1 X125.501 Y128.372 E.07039\nG1 X123.858 Y129.305 E.07039\nG1 X122.5 Y129.514 E.05116\nG1 X52.5 Y129.514 E2.60723\nG1 X50.652 Y129.118 E.07039\nM73 P61 R3\nG1 X49.128 Y128.001 E.07039\nG1 X48.195 Y126.358 E.07039\nG1 X47.986 Y125 E.05116\nG1 X47.986 Y55 E2.60723\nG1 X48.382 Y53.152 E.07039\nG1 X49.238 Y51.985 E.05392\nG1 X49.608 Y52.277 F15000\nG1 F3000\nG1 X49.946 Y51.848 E.02036\nG1 X51.552 Y51.055 E.06669\nG1 X52.5 Y50.943 E.03555\nG1 X122.5 Y50.943 E2.60723\nG1 X124.246 Y51.338 E.06669\nM73 P62 R3\nG1 X125.652 Y52.446 E.06669\nG1 X126.445 Y54.052 E.06669\nG1 X126.557 Y55 E.03555\nG1 X126.557 Y125 E2.60723\nG1 X126.162 Y126.746 E.06669\nM73 P62 R3\nG1 X125.054 Y128.152 E.06669\nG1 X123.448 Y128.945 E.06669\nG1 X122.5 Y129.057 E.03555\nG1 X52.5 Y129.057 E2.60723\nG1 X50.754 Y128.662 E.06669\nG1 X49.348 Y127.554 E.06669\nG1 X48.555 Y125.948 E.06669\nG1 X48.443 Y125 E.03555\nG1 X48.443 Y55 E2.60723\nG1 X48.838 Y53.254 E.06669\nM73 P63 R3\nG1 X49.583 Y52.308 E.04484\nG1 X49.938 Y52.612 F15000\nG1 F3000\nG1 X50.392 Y52.082 E.02598\nG1 X52.5 Y51.4 E.08254\nM73 P63 R3\nG1 X122.5 Y51.4 E2.60723\nG1 X124.138 Y51.795 E.06277\nG1 X125.418 Y52.892 E.06277\nG1 X126.1 Y55 E.08254\nG1 X126.1 Y125 E2.60723\nG1 X125.705 Y126.638 E.06277\nG1 X124.608 Y127.918 E.06277\nG1 X122.5 Y128.6 E.08254\nG1 X52.5 Y128.6 E2.60723\nG1 X50.862 Y128.205 E.06277\nG1 X49.582 Y127.108 E.06277\nG1 X48.9 Y125 E.08254\nG1 X48.9 Y55 E2.60723\nG1 X49.295 Y53.362 E.06277\nM73 P64 R3\nG1 X49.911 Y52.642 E.0353\nG1 X50.244 Y52.957 F15000\nG1 F3000\nG1 X50.833 Y52.336 E.03191\nG1 X52.5 Y51.857 E.06459\nM73 P64 R3\nG1 X122.5 Y51.857 E2.60723\nG1 X124.023 Y52.251 E.05859\nG1 X125.164 Y53.333 E.05859\nG1 X125.643 Y55 E.06459\nG1 X125.643 Y125 E2.60723\nG1 X125.249 Y126.523 E.05859\nG1 X124.167 Y127.664 E.05859\nG1 X122.5 Y128.143 E.06459\nG1 X52.5 Y128.143 E2.60723\nG1 X50.977 Y127.749 E.05859\nM73 P65 R3\nG1 X49.836 Y126.667 E.05859\nG1 X49.357 Y125 E.06459\nG1 X49.357 Y55 E2.60723\nG1 X49.751 Y53.477 E.05859\nM73 P65 R2\nG1 X50.216 Y52.986 E.02519\nM73 P65 R3\nG1 X50.519 Y53.312 F15000\nG1 F3000\nG1 X51.27 Y52.613 E.03821\nG1 X52.5 Y52.314 E.04715\nM73 P65 R2\nG1 X122.5 Y52.314 E2.60723\nG1 X123.898 Y52.707 E.05408\nG1 X124.887 Y53.77 E.05408\nG1 X125.186 Y55 E.04715\nG1 X125.186 Y125 E2.60723\nG1 X124.793 Y126.398 E.05408\nM73 P66 R2\nG1 X123.73 Y127.387 E.05408\nG1 X122.5 Y127.686 E.04715\nG1 X52.5 Y127.686 E2.60723\nG1 X51.102 Y127.293 E.05408\nG1 X50.113 Y126.23 E.05408\nM73 P66 R2\nG1 X49.814 Y125 E.04715\nG1 X49.814 Y55 E2.60723\nG1 X50.207 Y53.602 E.05408\nG1 X50.49 Y53.339 E.01439\nG1 X50.751 Y53.669 F15000\nG1 F3000\nG1 X51.698 Y52.921 E.04498\nG1 X52.5 Y52.771 E.03037\nG1 X122.5 Y52.771 E2.60723\nG1 X123.761 Y53.162 E.04917\nG1 X124.579 Y54.198 E.04917\nM73 P67 R2\nG1 X124.729 Y55 E.03037\nG1 X124.729 Y125 E2.60723\nG1 X124.338 Y126.261 E.04917\nG1 X123.302 Y127.079 E.04917\nG1 X122.5 Y127.229 E.03037\nM73 P67 R2\nG1 X52.5 Y127.229 E2.60723\nG1 X51.239 Y126.838 E.04917\nG1 X50.421 Y125.802 E.04917\nG1 X50.271 Y125 E.03037\nG1 X50.271 Y55 E2.60723\nG1 X50.662 Y53.739 E.04917\nG1 X50.719 Y53.694 E.0027\nG1 E-.2 F1800\n;WIPE_START\nG1 F3000\nG1 X51.504 Y53.074 E-.6\n;WIPE_END\nEXCLUDE_OBJECT_START NAME=Cube_id_0_copy_0\nG1 X56.865 Y58.507 Z.6 F15000\nG1 X121.186 Y123.686 Z.6\nG1 Z.2\nM73 P68 R2\nG1 E.8 F1800\n;TYPE:Inner wall\nG1 F3000\nG1 X53.814 Y123.686 E2.50934\nG1 X53.814 Y56.314 E2.50934\nG1 X121.186 Y56.314 E2.50934\nM73 P68 R2\nG1 X121.186 Y123.626 E2.5071\nG1 X121.643 Y124.143 F15000\nM73 P69 R2\nG1 F3000\nG1 X53.357 Y124.143 E2.54339\nG1 X53.357 Y55.857 E2.54339\nG1 X121.643 Y55.857 E2.54339\nG1 X121.643 Y124.083 E2.54115\nM73 P70 R2\nM73 P69 R2\nG1 X122.1 Y124.6 F15000\n;TYPE:Outer wall\nG1 F3000\nG1 X52.9 Y124.6 E2.57744\nG1 X52.9 Y55.4 E2.57744\nG1 X122.1 Y55.4 E2.57744\nM73 P70 R2\nG1 X122.1 Y124.54 E2.5752\nM73 P71 R2\nG1 E-.2 F1800\n;WIPE_START\nG1 F3000\nG1 X121.1 Y124.541 E-.6\n;WIPE_END\nG1 X121.094 Y116.908 Z.6 F15000\nG1 X121.049 Y57.379 Z.6\nM73 P71 R2\nG1 Z.2\nG1 E.8 F1800\n;TYPE:Bottom surface\n;WIDTH:0.501638\nG1 F6300\nG1 X120.327 Y56.657 E.03815\nG1 X119.678 Y56.657 E.02425\nG1 X120.843 Y57.822 E.06157\nG1 X120.843 Y58.47 E.02425\nG1 X119.03 Y56.657 E.09587\nG1 X118.381 Y56.657 E.02425\nG1 X120.843 Y59.119 E.13016\nG1 X120.843 Y59.768 E.02425\nG1 X117.732 Y56.657 E.16446\nG1 X117.083 Y56.657 E.02425\nG1 X120.843 Y60.417 E.19875\nG1 X120.843 Y61.065 E.02425\nG1 X116.435 Y56.657 E.23304\nG1 X115.786 Y56.657 E.02425\nG1 X120.843 Y61.714 E.26734\nG1 X120.843 Y62.363 E.02425\nG1 X115.137 Y56.657 E.30163\nG1 X114.488 Y56.657 E.02425\nG1 X120.843 Y63.012 E.33592\nM73 P72 R2\nG1 X120.843 Y63.66 E.02425\nG1 X113.84 Y56.657 E.37022\nG1 X113.191 Y56.657 E.02425\nG1 X120.843 Y64.309 E.40451\nG1 X120.843 Y64.958 E.02425\nM73 P72 R2\nG1 X112.542 Y56.657 E.4388\nG1 X111.894 Y56.657 E.02425\nG1 X120.843 Y65.606 E.4731\nG1 X120.843 Y66.255 E.02425\nG1 X111.245 Y56.657 E.50739\nG1 X110.596 Y56.657 E.02425\nG1 X120.843 Y66.904 E.54168\nG1 X120.843 Y67.553 E.02425\nG1 X109.947 Y56.657 E.57598\nG1 X109.299 Y56.657 E.02425\nG1 X120.843 Y68.201 E.61027\nG1 X120.843 Y68.85 E.02425\nG1 X108.65 Y56.657 E.64456\nG1 X108.001 Y56.657 E.02425\nG1 X120.843 Y69.499 E.67886\nG1 X120.843 Y70.148 E.02425\nG1 X107.352 Y56.657 E.71315\nG1 X106.704 Y56.657 E.02425\nG1 X120.843 Y70.796 E.74744\nG1 X120.843 Y71.445 E.02425\nG1 X106.055 Y56.657 E.78174\nG1 X105.406 Y56.657 E.02425\nG1 X120.843 Y72.094 E.81603\nG1 X120.843 Y72.742 E.02425\nM73 P73 R2\nG1 X104.758 Y56.657 E.85033\nG1 X104.109 Y56.657 E.02425\nG1 X120.843 Y73.391 E.88462\nG1 X120.843 Y74.04 E.02425\nG1 X103.46 Y56.657 E.91891\nM73 P73 R2\nG1 X102.811 Y56.657 E.02425\nG1 X120.843 Y74.689 E.95321\nG1 X120.843 Y75.337 E.02425\nG1 X102.163 Y56.657 E.9875\nG1 X101.514 Y56.657 E.02425\nG1 X120.843 Y75.986 E1.02179\nG1 X120.843 Y76.635 E.02425\nG1 X100.865 Y56.657 E1.05609\nG1 X100.216 Y56.657 E.02425\nG1 X120.843 Y77.284 E1.09038\nG1 X120.843 Y77.932 E.02425\nG1 X99.568 Y56.657 E1.12467\nG1 X98.919 Y56.657 E.02425\nG1 X120.843 Y78.581 E1.15897\nG1 X120.843 Y79.23 E.02425\nG1 X98.27 Y56.657 E1.19326\nG1 X97.622 Y56.657 E.02425\nM73 P74 R2\nG1 X120.843 Y79.878 E1.22755\nG1 X120.843 Y80.527 E.02425\nG1 X96.973 Y56.657 E1.26185\nG1 X96.324 Y56.657 E.02425\nG1 X120.843 Y81.176 E1.29614\nM73 P74 R2\nG1 X120.843 Y81.825 E.02425\nG1 X95.675 Y56.657 E1.33043\nG1 X95.027 Y56.657 E.02425\nG1 X120.843 Y82.473 E1.36473\nG1 X120.843 Y83.122 E.02425\nG1 X94.378 Y56.657 E1.39902\nG1 X93.729 Y56.657 E.02425\nG1 X120.843 Y83.771 E1.43331\nG1 X120.843 Y84.42 E.02425\nG1 X93.08 Y56.657 E1.46761\nG1 X92.432 Y56.657 E.02425\nG1 X120.843 Y85.068 E1.5019\nG1 X120.843 Y85.717 E.02425\nM73 P75 R2\nG1 X91.783 Y56.657 E1.53619\nG1 X91.134 Y56.657 E.02425\nG1 X120.843 Y86.366 E1.57049\nG1 X120.843 Y87.014 E.02425\nG1 X90.486 Y56.657 E1.60478\nM73 P75 R2\nG1 X89.837 Y56.657 E.02425\nG1 X120.843 Y87.663 E1.63908\nG1 X120.843 Y88.312 E.02425\nG1 X89.188 Y56.657 E1.67337\nG1 X88.539 Y56.657 E.02425\nG1 X120.843 Y88.961 E1.70766\nG1 X120.843 Y89.609 E.02425\nG1 X87.891 Y56.657 E1.74196\nG1 X87.242 Y56.657 E.02425\nG1 X120.843 Y90.258 E1.77625\nG1 X120.843 Y90.907 E.02425\nM73 P76 R2\nG1 X86.593 Y56.657 E1.81054\nG1 X85.945 Y56.657 E.02425\nG1 X120.843 Y91.555 E1.84484\nG1 X120.843 Y92.204 E.02425\nG1 X85.296 Y56.657 E1.87913\nM73 P76 R2\nG1 X84.647 Y56.657 E.02425\nG1 X120.843 Y92.853 E1.91342\nG1 X120.843 Y93.502 E.02425\nG1 X83.998 Y56.657 E1.94772\nG1 X83.35 Y56.657 E.02425\nG1 X120.843 Y94.15 E1.98201\nG1 X120.843 Y94.799 E.02425\nG1 X82.701 Y56.657 E2.0163\nG1 X82.052 Y56.657 E.02425\nM73 P76 R1\nG1 X120.843 Y95.448 E2.0506\nM73 P77 R1\nG1 X120.843 Y96.097 E.02425\nG1 X81.403 Y56.657 E2.08489\nG1 X80.755 Y56.657 E.02425\nG1 X120.843 Y96.745 E2.11918\nM73 P76 R1\nG1 X120.843 Y97.394 E.02425\nM73 P77 R1\nG1 X80.106 Y56.657 E2.15348\nG1 X79.457 Y56.657 E.02425\nG1 X120.843 Y98.043 E2.18777\nG1 X120.843 Y98.691 E.02425\nG1 X78.809 Y56.657 E2.22206\nG1 X78.16 Y56.657 E.02425\nG1 X120.843 Y99.34 E2.25636\nG1 X120.843 Y99.989 E.02425\nM73 P78 R1\nG1 X77.511 Y56.657 E2.29065\nG1 X76.862 Y56.657 E.02425\nG1 X120.843 Y100.638 E2.32494\nG1 X120.843 Y101.286 E.02425\nG1 X76.214 Y56.657 E2.35924\nM73 P78 R1\nG1 X75.565 Y56.657 E.02425\nG1 X120.843 Y101.935 E2.39353\nG1 X120.843 Y102.584 E.02425\nG1 X74.916 Y56.657 E2.42783\nG1 X74.267 Y56.657 E.02425\nG1 X120.843 Y103.233 E2.46212\nG1 X120.843 Y103.881 E.02425\nG1 X73.619 Y56.657 E2.49641\nG1 X72.97 Y56.657 E.02425\nM73 P79 R1\nG1 X120.843 Y104.53 E2.53071\nG1 X120.843 Y105.179 E.02425\nG1 X72.321 Y56.657 E2.565\nG1 X71.673 Y56.657 E.02425\nG1 X120.843 Y105.827 E2.59929\nM73 P79 R1\nG1 X120.843 Y106.476 E.02425\nG1 X71.024 Y56.657 E2.63359\nG1 X70.375 Y56.657 E.02425\nG1 X120.843 Y107.125 E2.66788\nG1 X120.843 Y107.774 E.02425\nM73 P80 R1\nG1 X69.726 Y56.657 E2.70217\nG1 X69.078 Y56.657 E.02425\nG1 X120.843 Y108.422 E2.73647\nG1 X120.843 Y109.071 E.02425\nG1 X68.429 Y56.657 E2.77076\nM73 P80 R1\nG1 X67.78 Y56.657 E.02425\nG1 X120.843 Y109.72 E2.80505\nG1 X120.843 Y110.369 E.02425\nG1 X67.131 Y56.657 E2.83935\nG1 X66.483 Y56.657 E.02425\nG1 X120.843 Y111.017 E2.87364\nG1 X120.843 Y111.666 E.02425\nM73 P81 R1\nG1 X65.834 Y56.657 E2.90793\nG1 X65.185 Y56.657 E.02425\nG1 X120.843 Y112.315 E2.94223\nG1 X120.843 Y112.963 E.02425\nG1 X64.537 Y56.657 E2.97652\nM73 P81 R1\nG1 X63.888 Y56.657 E.02425\nG1 X120.843 Y113.612 E3.01081\nG1 X120.843 Y114.261 E.02425\nG1 X63.239 Y56.657 E3.04511\nG1 X62.59 Y56.657 E.02425\nM73 P82 R1\nG1 X120.843 Y114.91 E3.0794\nG1 X120.843 Y115.558 E.02425\nG1 X61.942 Y56.657 E3.1137\nG1 X61.293 Y56.657 E.02425\nG1 X120.843 Y116.207 E3.14799\nM73 P82 R1\nG1 X120.843 Y116.856 E.02425\nG1 X60.644 Y56.657 E3.18228\nG1 X59.996 Y56.657 E.02425\nG1 X120.843 Y117.504 E3.21658\nG1 X120.843 Y118.153 E.02425\nM73 P83 R1\nG1 X59.347 Y56.657 E3.25087\nG1 X58.698 Y56.657 E.02425\nG1 X120.843 Y118.802 E3.28516\nG1 X120.843 Y119.451 E.02425\nG1 X58.049 Y56.657 E3.31946\nM73 P83 R1\nG1 X57.401 Y56.657 E.02425\nG1 X120.843 Y120.099 E3.35375\nG1 X120.843 Y120.748 E.02425\nG1 X56.752 Y56.657 E3.38804\nG1 X56.103 Y56.657 E.02425\nM73 P84 R1\nG1 X120.843 Y121.397 E3.42234\nG1 X120.843 Y122.046 E.02425\nG1 X55.454 Y56.657 E3.45663\nG1 X54.806 Y56.657 E.02425\nG1 X120.843 Y122.694 E3.49092\nM73 P84 R1\nG1 X120.843 Y123.343 E.02425\nG1 X54.157 Y56.657 E3.52522\nG1 X54.157 Y57.306 E.02425\nG1 X120.194 Y123.343 E3.49093\nG1 X119.546 Y123.343 E.02425\nM73 P85 R1\nG1 X54.157 Y57.954 E3.45663\nG1 X54.157 Y58.603 E.02425\nG1 X118.897 Y123.343 E3.42234\nG1 X118.248 Y123.343 E.02425\nG1 X54.157 Y59.252 E3.38805\nM73 P85 R1\nG1 X54.157 Y59.901 E.02425\nG1 X117.599 Y123.343 E3.35375\nG1 X116.951 Y123.343 E.02425\nG1 X54.157 Y60.549 E3.31946\nG1 X54.157 Y61.198 E.02425\nM73 P86 R1\nG1 X116.302 Y123.343 E3.28516\nG1 X115.653 Y123.343 E.02425\nG1 X54.157 Y61.847 E3.25087\nG1 X54.157 Y62.495 E.02425\nG1 X115.005 Y123.343 E3.21658\nM73 P86 R1\nG1 X114.356 Y123.343 E.02425\nG1 X54.157 Y63.144 E3.18228\nG1 X54.157 Y63.793 E.02425\nG1 X113.707 Y123.343 E3.14799\nG1 X113.058 Y123.343 E.02425\nM73 P87 R1\nG1 X54.157 Y64.442 E3.1137\nG1 X54.157 Y65.09 E.02425\nG1 X112.41 Y123.343 E3.0794\nG1 X111.761 Y123.343 E.02425\nG1 X54.157 Y65.739 E3.04511\nM73 P87 R1\nG1 X54.157 Y66.388 E.02425\nG1 X111.112 Y123.343 E3.01082\nG1 X110.463 Y123.343 E.02425\nG1 X54.157 Y67.037 E2.97652\nG1 X54.157 Y67.685 E.02425\nM73 P88 R1\nG1 X109.815 Y123.343 E2.94223\nG1 X109.166 Y123.343 E.02425\nG1 X54.157 Y68.334 E2.90794\nG1 X54.157 Y68.983 E.02425\nG1 X108.517 Y123.343 E2.87364\nM73 P88 R1\nG1 X107.869 Y123.343 E.02425\nM73 P88 R0\nG1 X54.157 Y69.631 E2.83935\nG1 X54.157 Y70.28 E.02425\nG1 X107.22 Y123.343 E2.80506\nG1 X106.571 Y123.343 E.02425\nM73 P89 R0\nG1 X54.157 Y70.929 E2.77076\nM73 P88 R0\nG1 X54.157 Y71.578 E.02425\nG1 X105.922 Y123.343 E2.73647\nG1 X105.274 Y123.343 E.02425\nG1 X54.157 Y72.226 E2.70218\nM73 P89 R0\nG1 X54.157 Y72.875 E.02425\nG1 X104.625 Y123.343 E2.66788\nG1 X103.976 Y123.343 E.02425\nG1 X54.157 Y73.524 E2.63359\nG1 X54.157 Y74.173 E.02425\nG1 X103.327 Y123.343 E2.59929\nG1 X102.679 Y123.343 E.02425\nM73 P90 R0\nG1 X54.157 Y74.821 E2.565\nG1 X54.157 Y75.47 E.02425\nG1 X102.03 Y123.343 E2.53071\nG1 X101.381 Y123.343 E.02425\nG1 X54.157 Y76.119 E2.49641\nM73 P90 R0\nG1 X54.157 Y76.767 E.02425\nG1 X100.733 Y123.343 E2.46212\nG1 X100.084 Y123.343 E.02425\nG1 X54.157 Y77.416 E2.42783\nG1 X54.157 Y78.065 E.02425\nG1 X99.435 Y123.343 E2.39353\nG1 X98.786 Y123.343 E.02425\nM73 P91 R0\nG1 X54.157 Y78.714 E2.35924\nG1 X54.157 Y79.362 E.02425\nG1 X98.138 Y123.343 E2.32495\nG1 X97.489 Y123.343 E.02425\nG1 X54.157 Y80.011 E2.29065\nM73 P91 R0\nG1 X54.157 Y80.66 E.02425\nG1 X96.84 Y123.343 E2.25636\nG1 X96.191 Y123.343 E.02425\nG1 X54.157 Y81.309 E2.22207\nG1 X54.157 Y81.957 E.02425\nG1 X95.543 Y123.343 E2.18777\nG1 X94.894 Y123.343 E.02425\nM73 P92 R0\nG1 X54.157 Y82.606 E2.15348\nG1 X54.157 Y83.255 E.02425\nG1 X94.245 Y123.343 E2.11919\nG1 X93.597 Y123.343 E.02425\nG1 X54.157 Y83.903 E2.08489\nM73 P92 R0\nG1 X54.157 Y84.552 E.02425\nG1 X92.948 Y123.343 E2.0506\nG1 X92.299 Y123.343 E.02425\nG1 X54.157 Y85.201 E2.01631\nG1 X54.157 Y85.85 E.02425\nG1 X91.65 Y123.343 E1.98201\nG1 X91.002 Y123.343 E.02425\nG1 X54.157 Y86.498 E1.94772\nG1 X54.157 Y87.147 E.02425\nM73 P93 R0\nG1 X90.353 Y123.343 E1.91343\nG1 X89.704 Y123.343 E.02425\nG1 X54.157 Y87.796 E1.87913\nG1 X54.157 Y88.444 E.02425\nG1 X89.056 Y123.343 E1.84484\nM73 P93 R0\nG1 X88.407 Y123.343 E.02425\nG1 X54.157 Y89.093 E1.81054\nG1 X54.157 Y89.742 E.02425\nG1 X87.758 Y123.343 E1.77625\nG1 X87.109 Y123.343 E.02425\nG1 X54.157 Y90.391 E1.74196\nG1 X54.157 Y91.039 E.02425\nG1 X86.461 Y123.343 E1.70766\nG1 X85.812 Y123.343 E.02425\nG1 X54.157 Y91.688 E1.67337\nG1 X54.157 Y92.337 E.02425\nM73 P94 R0\nG1 X85.163 Y123.343 E1.63908\nG1 X84.514 Y123.343 E.02425\nG1 X54.157 Y92.986 E1.60478\nG1 X54.157 Y93.634 E.02425\nG1 X83.866 Y123.343 E1.57049\nM73 P94 R0\nG1 X83.217 Y123.343 E.02425\nG1 X54.157 Y94.283 E1.5362\nG1 X54.157 Y94.932 E.02425\nG1 X82.568 Y123.343 E1.5019\nG1 X81.92 Y123.343 E.02425\nG1 X54.157 Y95.58 E1.46761\nG1 X54.157 Y96.229 E.02425\nG1 X81.271 Y123.343 E1.43332\nG1 X80.622 Y123.343 E.02425\nG1 X54.157 Y96.878 E1.39902\nG1 X54.157 Y97.527 E.02425\nG1 X79.973 Y123.343 E1.36473\nM73 P95 R0\nG1 X79.325 Y123.343 E.02425\nG1 X54.157 Y98.175 E1.33044\nG1 X54.157 Y98.824 E.02425\nG1 X78.676 Y123.343 E1.29614\nG1 X78.027 Y123.343 E.02425\nM73 P95 R0\nG1 X54.157 Y99.473 E1.26185\nG1 X54.157 Y100.122 E.02425\nG1 X77.378 Y123.343 E1.22756\nG1 X76.73 Y123.343 E.02425\nG1 X54.157 Y100.77 E1.19326\nG1 X54.157 Y101.419 E.02425\nG1 X76.081 Y123.343 E1.15897\nG1 X75.432 Y123.343 E.02425\nG1 X54.157 Y102.068 E1.12468\nG1 X54.157 Y102.716 E.02425\nG1 X74.784 Y123.343 E1.09038\nG1 X74.135 Y123.343 E.02425\nG1 X54.157 Y103.365 E1.05609\nG1 X54.157 Y104.014 E.02425\nM73 P96 R0\nG1 X73.486 Y123.343 E1.02179\nG1 X72.837 Y123.343 E.02425\nG1 X54.157 Y104.663 E.9875\nG1 X54.157 Y105.311 E.02425\nG1 X72.189 Y123.343 E.95321\nM73 P96 R0\nG1 X71.54 Y123.343 E.02425\nG1 X54.157 Y105.96 E.91891\nG1 X54.157 Y106.609 E.02425\nG1 X70.891 Y123.343 E.88462\nG1 X70.242 Y123.343 E.02425\nG1 X54.157 Y107.258 E.85033\nG1 X54.157 Y107.906 E.02425\nG1 X69.594 Y123.343 E.81603\nG1 X68.945 Y123.343 E.02425\nG1 X54.157 Y108.555 E.78174\nG1 X54.157 Y109.204 E.02425\nG1 X68.296 Y123.343 E.74745\nG1 X67.648 Y123.343 E.02425\nG1 X54.157 Y109.852 E.71315\nG1 X54.157 Y110.501 E.02425\nG1 X66.999 Y123.343 E.67886\nG1 X66.35 Y123.343 E.02425\nG1 X54.157 Y111.15 E.64457\nG1 X54.157 Y111.799 E.02425\nM73 P97 R0\nG1 X65.701 Y123.343 E.61027\nG1 X65.053 Y123.343 E.02425\nG1 X54.157 Y112.447 E.57598\nG1 X54.157 Y113.096 E.02425\nG1 X64.404 Y123.343 E.54169\nM73 P97 R0\nG1 X63.755 Y123.343 E.02425\nG1 X54.157 Y113.745 E.50739\nG1 X54.157 Y114.393 E.02425\nG1 X63.107 Y123.343 E.4731\nG1 X62.458 Y123.343 E.02425\nG1 X54.157 Y115.042 E.43881\nG1 X54.157 Y115.691 E.02425\nG1 X61.809 Y123.343 E.40451\nG1 X61.16 Y123.343 E.02425\nG1 X54.157 Y116.34 E.37022\nG1 X54.157 Y116.988 E.02425\nG1 X60.512 Y123.343 E.33592\nG1 X59.863 Y123.343 E.02425\nG1 X54.157 Y117.637 E.30163\nG1 X54.157 Y118.286 E.02425\nG1 X59.214 Y123.343 E.26734\nG1 X58.565 Y123.343 E.02425\nG1 X54.157 Y118.935 E.23304\nG1 X54.157 Y119.583 E.02425\nG1 X57.917 Y123.343 E.19875\nG1 X57.268 Y123.343 E.02425\nG1 X54.157 Y120.232 E.16446\nG1 X54.157 Y120.881 E.02425\nG1 X56.619 Y123.343 E.13016\nG1 X55.971 Y123.343 E.02425\nG1 X54.157 Y121.529 E.09587\nG1 X54.157 Y122.178 E.02425\nG1 X55.322 Y123.343 E.06158\nG1 X54.673 Y123.343 E.02425\nG1 X53.951 Y122.621 E.03816\nG1 E-.51429 F1800\n;WIPE_START\nG1 F6300\nG1 X54.658 Y123.328 E-.28571\n;WIPE_END\nEXCLUDE_OBJECT_END NAME=Cube_id_0_copy_0\nM106 S0\nM106 P2 S0\n;TYPE:Custom\nM141 S0\nM104 S0\nM140 S0\nG1 E-3 F1800\nG0 Z3.2 F600\nG0 X0 Y0 F12000\nM73 P98 R0\nG1 Z95 F600\nM106 P3 S0\nM73 P100 R0\n; EXECUTABLE_BLOCK_END\n\n; filament used [mm] = 525.65\n; filament used [cm3] = 1.26\n; filament used [g] = 1.57\n; filament cost = 0.03\n; total filament used [g] = 1.57\n; total filament cost = 0.03\n; total layers count = 1\n; estimated printing time (normal mode) = 8m 38s\n\n; CONFIG_BLOCK_START\n; accel_to_decel_enable = 1\n; accel_to_decel_factor = 50%\n; activate_air_filtration = 1\n; activate_chamber_temp_control = 0\n; adaptive_bed_mesh_margin = 0\n; adaptive_pressure_advance = 0\n; adaptive_pressure_advance_bridges = 0\n; adaptive_pressure_advance_model = \"0,0,0\\n0,0,0\"\n; adaptive_pressure_advance_overhangs = 0\n; additional_cooling_fan_speed = 0\n; alternate_extra_wall = 0\n; auxiliary_fan = 1\n; bbl_calib_mark_logo = 1\n; bbl_use_printhost = 0\n; bed_custom_model = \n; bed_custom_texture = \n; bed_exclude_area = 0x0\n; bed_mesh_max = 99999,99999\n; bed_mesh_min = -99999,-99999\n; bed_mesh_probe_distance = 50,50\n; before_layer_change_gcode = ;BEFORE_LAYER_CHANGE\\n;[layer_z]\\nG92 E0\\n\n; best_object_pos = 0.5,0.5\n; bottom_shell_layers = 3\n; bottom_shell_thickness = 0\n; bottom_solid_infill_flow_ratio = 1\n; bottom_surface_pattern = monotonic\n; bridge_acceleration = 50%\n; bridge_angle = 0\n; bridge_density = 100%\n; bridge_flow = 1\n; bridge_no_support = 0\n; bridge_speed = 50\n; brim_ears_detection_length = 1\n; brim_ears_max_angle = 125\n; brim_object_gap = 0.1\n; brim_type = auto_brim\n; brim_width = 5\n; chamber_temperature = 0\n; change_extrusion_role_gcode = \n; change_filament_gcode = \n; close_fan_the_first_x_layers = 1\n; complete_print_exhaust_fan_speed = 0\n; cool_plate_temp = 60\n; cool_plate_temp_initial_layer = 60\n; cooling_tube_length = 5\n; cooling_tube_retraction = 91.5\n; counterbore_hole_bridging = none\n; curr_bed_type = High Temp Plate\n; default_acceleration = 10000\n; default_filament_colour = \"\"\n; default_filament_profile = \"Qidi Generic PLA\"\n; default_jerk = 0\n; default_print_profile = 0.20mm Standard @Qidi XSmart3\n; deretraction_speed = 0\n; detect_narrow_internal_solid_infill = 1\n; detect_overhang_wall = 1\n; detect_thin_wall = 0\n; different_settings_to_system = only_one_wall_top;skirt_loops;wall_loops;;thumbnails\n; disable_m73 = 0\n; dont_filter_internal_bridges = disabled\n; dont_slow_down_outer_wall = 1\n; draft_shield = disabled\n; during_print_exhaust_fan_speed = 100\n; elefant_foot_compensation = 0.15\n; elefant_foot_compensation_layers = 1\n; emit_machine_limits_to_gcode = 1\n; enable_arc_fitting = 0\n; enable_filament_ramming = 1\n; enable_long_retraction_when_cut = 0\n; enable_overhang_bridge_fan = 0\n; enable_overhang_speed = 1\n; enable_pressure_advance = 1\n; enable_prime_tower = 0\n; enable_support = 0\n; enforce_support_layers = 0\n; eng_plate_temp = 60\n; eng_plate_temp_initial_layer = 60\n; ensure_vertical_shell_thickness = ensure_all\n; exclude_object = 1\n; extra_loading_move = -2\n; extra_perimeters_on_overhangs = 0\n; extruder_clearance_height_to_lid = 140\n; extruder_clearance_height_to_rod = 36\n; extruder_clearance_radius = 65\n; extruder_colour = #C0C0C0\n; extruder_offset = 0x0\n; fan_cooling_layer_time = 60\n; fan_kickstart = 0\n; fan_max_speed = 100\n; fan_min_speed = 100\n; fan_speedup_overhangs = 1\n; fan_speedup_time = 0\n; filament_colour = #C0C0C0\n; filament_cooling_final_speed = 3.4\n; filament_cooling_initial_speed = 2.2\n; filament_cooling_moves = 4\n; filament_cost = 20\n; filament_density = 1.24\n; filament_diameter = 1.75\n; filament_end_gcode = \" \"\n; filament_flow_ratio = 0.98\n; filament_ids = GFL99\n; filament_is_support = 0\n; filament_loading_speed = 28\n; filament_loading_speed_start = 3\n; filament_max_volumetric_speed = 14\n; filament_minimal_purge_on_wipe_tower = 15\n; filament_multitool_ramming = 0\n; filament_multitool_ramming_flow = 10\n; filament_multitool_ramming_volume = 10\n; filament_notes = \"\"\n; filament_ramming_parameters = \"120 100 6.6 6.8 7.2 7.6 7.9 8.2 8.7 9.4 9.9 10.0| 0.05 6.6 0.45 6.8 0.95 7.8 1.45 8.3 1.95 9.7 2.45 10 2.95 7.6 3.45 7.6 3.95 7.6 4.45 7.6 4.95 7.6\"\n; filament_settings_id = \"Qidi Generic PLA\"\n; filament_shrink = 100%\n; filament_shrinkage_compensation_z = 100%\n; filament_soluble = 0\n; filament_stamping_distance = 0\n; filament_stamping_loading_speed = 0\n; filament_start_gcode = \" \"\n; filament_toolchange_delay = 0\n; filament_type = PLA\n; filament_unloading_speed = 90\n; filament_unloading_speed_start = 100\n; filament_vendor = QIDI\n; filename_format = {input_filename_base}_{filament_type[0]}_{print_time}.gcode\n; filter_out_gap_fill = 2\n; first_layer_print_sequence = 0\n; flush_into_infill = 0\n; flush_into_objects = 0\n; flush_into_support = 1\n; flush_multiplier = 1\n; flush_volumes_matrix = 0\n; flush_volumes_vector = 140,140\n; full_fan_speed_layer = 3\n; fuzzy_skin = none\n; fuzzy_skin_first_layer = 0\n; fuzzy_skin_point_distance = 0.8\n; fuzzy_skin_thickness = 0.3\n; gap_fill_target = nowhere\n; gap_infill_speed = 250\n; gcode_add_line_number = 0\n; gcode_comments = 0\n; gcode_flavor = klipper\n; gcode_label_objects = 0\n; has_scarf_joint_seam = 0\n; head_wrap_detect_zone = \n; high_current_on_filament_swap = 0\n; hole_to_polyhole = 0\n; hole_to_polyhole_threshold = 0.01\n; hole_to_polyhole_twisted = 1\n; host_type = octoprint\n; hot_plate_temp = 60\n; hot_plate_temp_initial_layer = 60\n; idle_temperature = 0\n; independent_support_layer_height = 0\n; infill_anchor = 400%\n; infill_anchor_max = 20\n; infill_combination = 0\n; infill_combination_max_layer_height = 100%\n; infill_direction = 45\n; infill_jerk = 9\n; infill_wall_overlap = 15%\n; inherits_group = ;;\"Qidi X-Smart 3 0.4 nozzle\"\n; initial_layer_acceleration = 500\n; initial_layer_infill_speed = 105\n; initial_layer_jerk = 9\n; initial_layer_line_width = 0.5\n; initial_layer_min_bead_width = 85%\n; initial_layer_print_height = 0.2\n; initial_layer_speed = 50\n; initial_layer_travel_speed = 50%\n; inner_wall_acceleration = 5000\n; inner_wall_jerk = 9\n; inner_wall_line_width = 0.45\n; inner_wall_speed = 300\n; interface_shells = 0\n; interlocking_beam = 0\n; interlocking_beam_layer_count = 2\n; interlocking_beam_width = 0.8\n; interlocking_boundary_avoidance = 2\n; interlocking_depth = 2\n; interlocking_orientation = 22.5\n; internal_bridge_flow = 1\n; internal_bridge_speed = 50\n; internal_solid_infill_acceleration = 100%\n; internal_solid_infill_line_width = 0.42\n; internal_solid_infill_pattern = zig-zag\n; internal_solid_infill_speed = 250\n; ironing_angle = -1\n; ironing_flow = 10%\n; ironing_pattern = zig-zag\n; ironing_spacing = 0.15\n; ironing_speed = 30\n; ironing_type = no ironing\n; is_infill_first = 0\n; layer_change_gcode = \n; layer_height = 0.2\n; line_width = 0.42\n; long_retractions_when_cut = 0\n; machine_end_gcode = M141 S0\\nM104 S0\\nM140 S0\\nG1 E-3 F1800\\nG0 Z{min(max_print_height, max_layer_z + 3)} F600\\nG0 X0 Y0 F12000\\n{if max_layer_z < max_print_height / 2}G1 Z{max_print_height / 2 + 10} F600{else}G1 Z{min(max_print_height, max_layer_z + 3)}{endif}\n; machine_load_filament_time = 0\n; machine_max_acceleration_e = 5000\n; machine_max_acceleration_extruding = 20000\n; machine_max_acceleration_retracting = 5000\n; machine_max_acceleration_travel = 0,0\n; machine_max_acceleration_x = 20000\n; machine_max_acceleration_y = 20000\n; machine_max_acceleration_z = 500\n; machine_max_jerk_e = 2\n; machine_max_jerk_x = 9\n; machine_max_jerk_y = 9\n; machine_max_jerk_z = 3\n; machine_max_speed_e = 30\n; machine_max_speed_x = 600\n; machine_max_speed_y = 600\n; machine_max_speed_z = 10\n; machine_min_extruding_rate = 0\n; machine_min_travel_rate = 0\n; machine_pause_gcode = M0\n; machine_start_gcode = PRINT_START\\nG28\\nM141 S0\\nG0 Z50 F600\\nM190 S[hot_plate_temp_initial_layer]\\nG28 Z\\nG29; mesh bed leveling ,comment this code to close it\\nG0 X0 Y0 Z50 F6000\\nM191 S{overall_chamber_temperature}\\nM109 S[nozzle_temperature_initial_layer]\\nM106 P3 S255\\nM83\\nG4 P3000\\nG0 X{max((min(print_bed_max[0], first_layer_print_min[0] + 80) - 85),0)} Y{max((min(print_bed_max[1], first_layer_print_min[1] + 80) - 85),0)} Z5 F6000\\nG0 Z[initial_layer_print_height] F600\\nG1 E3 F1800\\nG1 X{(min(print_bed_max[0], first_layer_print_min[0] + 80))} E{85 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\\nG1 Y{max((min(print_bed_max[1], first_layer_print_min[1] + 80) - 85),0) + 2} E{2 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\\nG1 X{max((min(print_bed_max[0], first_layer_print_min[0] + 80) - 85),0)} E{85 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\\nG1 Y{max((min(print_bed_max[1], first_layer_print_min[1] + 80) - 85),0) + 85} E{83 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\\nG1 X{max((min(print_bed_max[0], first_layer_print_min[0] + 80) - 85),0) + 2} E{2 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\\nG1 Y{max((min(print_bed_max[1], first_layer_print_min[1] + 80) - 85),0) + 3} E{82 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\\nG1 X{max((min(print_bed_max[0], first_layer_print_min[0] + 80) - 85),0) + 12} E{-10 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\\nG1 E{10 * 0.5 * initial_layer_print_height * nozzle_diameter[0]} F3000\\n\n; machine_tool_change_time = 0\n; machine_unload_filament_time = 0\n; make_overhang_printable = 0\n; make_overhang_printable_angle = 55\n; make_overhang_printable_hole_size = 0\n; manual_filament_change = 0\n; max_bridge_length = 10\n; max_layer_height = 0.3\n; max_travel_detour_distance = 0\n; max_volumetric_extrusion_rate_slope = 0\n; max_volumetric_extrusion_rate_slope_segment_length = 3\n; min_bead_width = 85%\n; min_feature_size = 25%\n; min_layer_height = 0.07\n; min_length_factor = 0.5\n; min_skirt_length = 0\n; min_width_top_surface = 300%\n; minimum_sparse_infill_area = 15\n; mmu_segmented_region_interlocking_depth = 0\n; mmu_segmented_region_max_width = 0\n; notes = If you want to use Orca's chamber temperature control feature, check that printer.cfg has added the following M191 macro.\\nTo add it: go to Fluidd web interface--configuration, copy the following code to the top of the printer.cfg document, SAVE&RESATART  \\n\\n[gcode_macro M191]\\ngcode:\\n    {% set s = params.S|float %}\\n    {% if s == 0 %}\\n        # If target temperature is 0, do nothing\\n        M117 Chamber heating cancelled\\n    {% else %}\\n        SET_HEATER_TEMPERATURE HEATER=chamber_heater TARGET={s}\\n        # Orca: uncomment the following line if you want to use heat bed to assist chamber heating\\n        M140 S90\\n        TEMPERATURE_WAIT SENSOR=\\\"heater_generic chamber_heater\\\" MINIMUM={s-1} MAXIMUM={s+1}\\n        M117 Chamber at target temperature\\n    {% endif %}\n; nozzle_diameter = 0.4\n; nozzle_height = 2.5\n; nozzle_hrc = 0\n; nozzle_temperature = 220\n; nozzle_temperature_initial_layer = 210\n; nozzle_temperature_range_high = 240\n; nozzle_temperature_range_low = 190\n; nozzle_type = hardened_steel\n; nozzle_volume = 0\n; only_one_wall_first_layer = 0\n; only_one_wall_top = 0\n; ooze_prevention = 0\n; other_layers_print_sequence = 0\n; other_layers_print_sequence_nums = 0\n; outer_wall_acceleration = 3000\n; outer_wall_jerk = 9\n; outer_wall_line_width = 0.42\n; outer_wall_speed = 200\n; overhang_1_4_speed = 0\n; overhang_2_4_speed = 50\n; overhang_3_4_speed = 30\n; overhang_4_4_speed = 10\n; overhang_fan_speed = 100\n; overhang_fan_threshold = 95%\n; overhang_reverse = 0\n; overhang_reverse_internal_only = 0\n; overhang_reverse_threshold = 50%\n; overhang_speed_classic = 0\n; parking_pos_retraction = 92\n; pellet_flow_coefficient = 0.4157\n; pellet_modded_printer = 0\n; post_process = \n; precise_outer_wall = 0\n; precise_z_height = 0\n; preferred_orientation = 0\n; preheat_steps = 1\n; preheat_time = 30\n; pressure_advance = 0.031\n; prime_tower_brim_width = 3\n; prime_tower_width = 35\n; prime_volume = 45\n; print_compatible_printers = \"Qidi X-Smart 3 0.4 nozzle\"\n; print_flow_ratio = 1\n; print_order = default\n; print_sequence = by layer\n; print_settings_id = 0.20mm Standard @Qidi XSmart3\n; printable_area = 0x0,175x0,175x180,0x180\n; printable_height = 170\n; printer_model = Qidi X-Smart 3\n; printer_notes = \n; printer_settings_id = Qidi X-Smart 3 0.4 nozzle - Copy\n; printer_structure = undefine\n; printer_technology = FFF\n; printer_variant = 0.4\n; printhost_authorization_type = key\n; printhost_ssl_ignore_revoke = 0\n; printing_by_object_gcode = \n; purge_in_prime_tower = 1\n; raft_contact_distance = 0.1\n; raft_expansion = 1.5\n; raft_first_layer_density = 90%\n; raft_first_layer_expansion = 2\n; raft_layers = 0\n; reduce_crossing_wall = 0\n; reduce_fan_stop_start_freq = 1\n; reduce_infill_retraction = 1\n; required_nozzle_HRC = 0\n; resolution = 0.012\n; retract_before_wipe = 0%\n; retract_length_toolchange = 2\n; retract_lift_above = 0\n; retract_lift_below = 0\n; retract_lift_enforce = All Surfaces\n; retract_restart_extra = 0\n; retract_restart_extra_toolchange = 0\n; retract_when_changing_layer = 1\n; retraction_distances_when_cut = 18\n; retraction_length = 0.8\n; retraction_minimum_travel = 1\n; retraction_speed = 30\n; role_based_wipe_speed = 1\n; rotate_solid_infill_direction = 1\n; scan_first_layer = 0\n; scarf_angle_threshold = 155\n; scarf_joint_flow_ratio = 1\n; scarf_joint_speed = 100%\n; scarf_overhang_threshold = 40%\n; seam_gap = 15%\n; seam_position = aligned\n; seam_slope_conditional = 0\n; seam_slope_entire_loop = 0\n; seam_slope_inner_walls = 0\n; seam_slope_min_length = 20\n; seam_slope_start_height = 0\n; seam_slope_steps = 10\n; seam_slope_type = none\n; silent_mode = 0\n; single_extruder_multi_material = 1\n; single_extruder_multi_material_priming = 0\n; skirt_distance = 2\n; skirt_height = 1\n; skirt_loops = 10\n; skirt_speed = 50\n; skirt_start_angle = -135\n; skirt_type = combined\n; slice_closing_radius = 0.049\n; slicing_mode = regular\n; slow_down_for_layer_cooling = 1\n; slow_down_layer_time = 8\n; slow_down_layers = 0\n; slow_down_min_speed = 20\n; slowdown_for_curled_perimeters = 1\n; small_area_infill_flow_compensation = 0\n; small_area_infill_flow_compensation_model = 0,0;\"\\n0.2,0.4444\";\"\\n0.4,0.6145\";\"\\n0.6,0.7059\";\"\\n0.8,0.7619\";\"\\n1.5,0.8571\";\"\\n2,0.8889\";\"\\n3,0.9231\";\"\\n5,0.9520\";\"\\n10,1\"\n; small_perimeter_speed = 50%\n; small_perimeter_threshold = 4\n; solid_infill_direction = 45\n; solid_infill_filament = 1\n; sparse_infill_acceleration = 100%\n; sparse_infill_density = 15%\n; sparse_infill_filament = 1\n; sparse_infill_line_width = 0.45\n; sparse_infill_pattern = grid\n; sparse_infill_speed = 270\n; spiral_mode = 0\n; spiral_mode_max_xy_smoothing = 200%\n; spiral_mode_smooth = 0\n; staggered_inner_seams = 0\n; standby_temperature_delta = -5\n; start_end_points = 30x-3,54x245\n; support_air_filtration = 1\n; support_angle = 0\n; support_base_pattern = default\n; support_base_pattern_spacing = 2.5\n; support_bottom_interface_spacing = 0.5\n; support_bottom_z_distance = 0.2\n; support_chamber_temp_control = 1\n; support_critical_regions_only = 0\n; support_expansion = 0\n; support_filament = 0\n; support_interface_bottom_layers = 2\n; support_interface_filament = 0\n; support_interface_loop_pattern = 0\n; support_interface_not_for_body = 1\n; support_interface_pattern = auto\n; support_interface_spacing = 0.5\n; support_interface_speed = 80\n; support_interface_top_layers = 2\n; support_line_width = 0.42\n; support_material_interface_fan_speed = -1\n; support_multi_bed_types = 0\n; support_object_xy_distance = 0.35\n; support_on_build_plate_only = 0\n; support_remove_small_overhang = 1\n; support_speed = 150\n; support_style = default\n; support_threshold_angle = 30\n; support_top_z_distance = 0.2\n; support_type = normal(auto)\n; temperature_vitrification = 45\n; template_custom_gcode = \n; textured_cool_plate_temp = 40\n; textured_cool_plate_temp_initial_layer = 40\n; textured_plate_temp = 60\n; textured_plate_temp_initial_layer = 60\n; thick_bridges = 0\n; thick_internal_bridges = 1\n; thumbnails = 140x140/PNG, 48x48/PNG\n; thumbnails_format = PNG\n; time_cost = 0\n; time_lapse_gcode = ;TIMELAPSE_TAKE_FRAME\\n\n; timelapse_type = 0\n; top_bottom_infill_wall_overlap = 25%\n; top_shell_layers = 5\n; top_shell_thickness = 1\n; top_solid_infill_flow_ratio = 1\n; top_surface_acceleration = 2000\n; top_surface_jerk = 9\n; top_surface_line_width = 0.42\n; top_surface_pattern = monotonicline\n; top_surface_speed = 200\n; travel_acceleration = 10000\n; travel_jerk = 12\n; travel_slope = 3\n; travel_speed = 500\n; travel_speed_z = 0\n; tree_support_adaptive_layer_height = 1\n; tree_support_angle_slow = 25\n; tree_support_auto_brim = 1\n; tree_support_branch_angle = 45\n; tree_support_branch_angle_organic = 40\n; tree_support_branch_diameter = 2\n; tree_support_branch_diameter_angle = 5\n; tree_support_branch_diameter_double_wall = 3\n; tree_support_branch_diameter_organic = 2\n; tree_support_branch_distance = 5\n; tree_support_branch_distance_organic = 1\n; tree_support_brim_width = 3\n; tree_support_tip_diameter = 0.8\n; tree_support_top_rate = 30%\n; tree_support_wall_count = 0\n; upward_compatible_machine = \n; use_firmware_retraction = 0\n; use_relative_e_distances = 1\n; wall_direction = auto\n; wall_distribution_count = 1\n; wall_filament = 1\n; wall_generator = classic\n; wall_loops = 3\n; wall_sequence = inner wall/outer wall\n; wall_transition_angle = 10\n; wall_transition_filter_deviation = 25%\n; wall_transition_length = 100%\n; wipe = 1\n; wipe_before_external_loop = 0\n; wipe_distance = 1\n; wipe_on_loops = 0\n; wipe_speed = 80%\n; wipe_tower_bridging = 10\n; wipe_tower_cone_angle = 0\n; wipe_tower_extra_flow = 100%\n; wipe_tower_extra_spacing = 100%\n; wipe_tower_filament = 0\n; wipe_tower_max_purge_speed = 90\n; wipe_tower_no_sparse_layers = 0\n; wipe_tower_rotation_angle = 0\n; wipe_tower_x = 165.000\n; wipe_tower_x = 165\n; wipe_tower_y = 250.000\n; wipe_tower_y = 250\n; wiping_volumes_extruders = 70,70,70,70,70,70,70,70,70,70\n; xy_contour_compensation = 0\n; xy_hole_compensation = 0\n; z_hop = 0.4\n; z_hop_types = Auto Lift\n; z_offset = 0\n; first_layer_bed_temperature = 60\n; bed_shape = 0x0,175x0,175x180,0x180\n; first_layer_temperature = 210\n; first_layer_height = 0.200\n; CONFIG_BLOCK_END\n\n\n"
  },
  {
    "path": "requirements.txt",
    "content": "configparser\nrequests\npyserial>=3.5\nPillow\nnumpy\nmatplotlib\npsutil\nwebsocket-client"
  },
  {
    "path": "themes/Plus4/.theme/custom.css",
    "content": ".theme--dark.v-list-item:not(.v-list-item--active):not(.v-list-item--disabled) {\n    color: #51b0ff;\n}\n\n.v-progress-circular__overlay {\n    stroke: #2b7ef5 !important;\n}\n\n.v-application .orange {\n    background-color: #2b7ef5 !important;\n    border-color: #2d76df !important;\n}\n\n.v-application .orange--text {\n    color: #FFFFFF !important;\n    caret-color: #673bd7 !important;\n}\n\n#nav-header .v-toolbar__title {\n    font-size: 24px;\n    vertical-align: middle;\n    color: white;\n    font-family: monospace;\n}\n\n.v-application .warning {\n    background-color: #0070c0 !important;\n    border-color: #0070c0 !important;\n}\n\n.v-application .primary {\n    background-color: #0070c0 !important;\n}"
  },
  {
    "path": "themes/Q1_Pro/.theme/custom.css",
    "content": ".theme--dark.v-list-item:not(.v-list-item--active):not(.v-list-item--disabled) {\n    color: #51b0ff;\n}\n\n.v-progress-circular__overlay {\n    stroke: #2b7ef5 !important;\n}\n\n.v-application .orange {\n    background-color: #2b7ef5 !important;\n    border-color: #2d76df !important;\n}\n\n.v-application .orange--text {\n    color: #FFFFFF !important;\n    caret-color: #673bd7 !important;\n}\n\n#nav-header .v-toolbar__title {\n    font-size: 24px;\n    vertical-align: middle;\n    color: white;\n    font-family: monospace;\n}\n\n.v-application .warning {\n    background-color: #0070c0 !important;\n    border-color: #0070c0 !important;\n}\n\n.v-application .primary {\n    background-color: #0070c0 !important;\n}"
  },
  {
    "path": "themes/X-Max3/.theme/custom.css",
    "content": ".theme--dark.v-list-item:not(.v-list-item--active):not(.v-list-item--disabled) {\n    color: #51b0ff;\n}\n\n.v-progress-circular__overlay {\n    stroke: #2b7ef5 !important;\n}\n\n.v-application .orange {\n    background-color: #2b7ef5 !important;\n    border-color: #2d76df !important;\n}\n\n.v-application .orange--text {\n    color: #FFFFFF !important;\n    caret-color: #673bd7 !important;\n}\n\n#nav-header .v-toolbar__title {\n    font-size: 24px;\n    vertical-align: middle;\n    color: white;\n    font-family: monospace;\n}\n\n.v-application .warning {\n    background-color: #0070c0 !important;\n    border-color: #0070c0 !important;\n}\n\n.v-application .primary {\n    background-color: #0070c0 !important;\n}"
  },
  {
    "path": "themes/X-Plus3/.theme/custom.css",
    "content": ".theme--dark.v-list-item:not(.v-list-item--active):not(.v-list-item--disabled) {\n    color: #51b0ff;\n}\n\n.v-progress-circular__overlay {\n    stroke: #2b7ef5 !important;\n}\n\n.v-application .orange {\n    background-color: #2b7ef5 !important;\n    border-color: #2d76df !important;\n}\n\n.v-application .orange--text {\n    color: #FFFFFF !important;\n    caret-color: #673bd7 !important;\n}\n\n#nav-header .v-toolbar__title {\n    font-size: 24px;\n    vertical-align: middle;\n    color: white;\n    font-family: monospace;\n}\n\n.v-application .warning {\n    background-color: #0070c0 !important;\n    border-color: #0070c0 !important;\n}\n\n.v-application .primary {\n    background-color: #0070c0 !important;\n}"
  },
  {
    "path": "themes/X-Smart3/.theme/custom.css",
    "content": ".theme--dark.v-list-item:not(.v-list-item--active):not(.v-list-item--disabled) {\n    color: #51b0ff;\n}\n\n.v-progress-circular__overlay {\n    stroke: #2b7ef5 !important;\n}\n\n.v-application .orange {\n    background-color: #2b7ef5 !important;\n    border-color: #2d76df !important;\n}\n\n.v-application .orange--text {\n    color: #FFFFFF !important;\n    caret-color: #673bd7 !important;\n}\n\n#nav-header .v-toolbar__title {\n    font-size: 24px;\n    vertical-align: middle;\n    color: white;\n    font-family: monospace;\n}\n\n.v-application .warning {\n    background-color: #0070c0 !important;\n    border-color: #0070c0 !important;\n}\n\n.v-application .primary {\n    background-color: #0070c0 !important;\n}"
  }
]