summary refs log tree commit diff
path: root/assets/printer
diff options
context:
space:
mode:
Diffstat (limited to 'assets/printer')
-rw-r--r--assets/printer/firmware.cfg110
-rw-r--r--assets/printer/mainsail.cfg313
-rw-r--r--assets/printer/printer.cfg159
3 files changed, 582 insertions, 0 deletions
diff --git a/assets/printer/firmware.cfg b/assets/printer/firmware.cfg
new file mode 100644
index 0000000..dd5a878
--- /dev/null
+++ b/assets/printer/firmware.cfg
@@ -0,0 +1,110 @@
+CONFIG_LOW_LEVEL_OPTIONS=y
+# CONFIG_MACH_AVR is not set
+# CONFIG_MACH_ATSAM is not set
+# CONFIG_MACH_ATSAMD is not set
+# CONFIG_MACH_LPC176X is not set
+CONFIG_MACH_STM32=y
+# CONFIG_MACH_HC32F460 is not set
+# CONFIG_MACH_RP2040 is not set
+# CONFIG_MACH_PRU is not set
+# CONFIG_MACH_AR100 is not set
+# CONFIG_MACH_LINUX is not set
+# CONFIG_MACH_SIMU is not set
+CONFIG_BOARD_DIRECTORY="stm32"
+CONFIG_MCU="stm32f103xe"
+CONFIG_CLOCK_FREQ=72000000
+CONFIG_SERIAL=y
+CONFIG_FLASH_SIZE=0x10000
+CONFIG_FLASH_BOOT_ADDRESS=0x8000000
+CONFIG_RAM_START=0x20000000
+CONFIG_RAM_SIZE=0x5000
+CONFIG_STACK_SIZE=512
+CONFIG_FLASH_APPLICATION_ADDRESS=0x8008000
+CONFIG_STM32_SELECT=y
+CONFIG_MACH_STM32F103=y
+# CONFIG_MACH_STM32F207 is not set
+# CONFIG_MACH_STM32F401 is not set
+# CONFIG_MACH_STM32F405 is not set
+# CONFIG_MACH_STM32F407 is not set
+# CONFIG_MACH_STM32F429 is not set
+# CONFIG_MACH_STM32F446 is not set
+# CONFIG_MACH_STM32F765 is not set
+# CONFIG_MACH_STM32F031 is not set
+# CONFIG_MACH_STM32F042 is not set
+# CONFIG_MACH_STM32F070 is not set
+# CONFIG_MACH_STM32F072 is not set
+# CONFIG_MACH_STM32G070 is not set
+# CONFIG_MACH_STM32G071 is not set
+# CONFIG_MACH_STM32G0B0 is not set
+# CONFIG_MACH_STM32G0B1 is not set
+# CONFIG_MACH_STM32G431 is not set
+# CONFIG_MACH_STM32G474 is not set
+# CONFIG_MACH_STM32H723 is not set
+# CONFIG_MACH_STM32H743 is not set
+# CONFIG_MACH_STM32H750 is not set
+# CONFIG_MACH_STM32L412 is not set
+# CONFIG_MACH_N32G452 is not set
+# CONFIG_MACH_N32G455 is not set
+# CONFIG_MACH_STM32F103x6 is not set
+CONFIG_MACH_STM32F1=y
+CONFIG_HAVE_STM32_USBFS=y
+CONFIG_HAVE_STM32_CANBUS=y
+CONFIG_STM32F103GD_DISABLE_SWD=y
+CONFIG_STM32_DFU_ROM_ADDRESS=0
+# CONFIG_STM32_FLASH_START_2000 is not set
+# CONFIG_STM32_FLASH_START_5000 is not set
+# CONFIG_STM32_FLASH_START_7000 is not set
+CONFIG_STM32_FLASH_START_8000=y
+# CONFIG_STM32_FLASH_START_8800 is not set
+# CONFIG_STM32_FLASH_START_9000 is not set
+# CONFIG_STM32_FLASH_START_10000 is not set
+# CONFIG_STM32_FLASH_START_800 is not set
+# CONFIG_STM32_FLASH_START_1000 is not set
+# CONFIG_STM32_FLASH_START_4000 is not set
+# CONFIG_STM32_FLASH_START_0000 is not set
+CONFIG_STM32_CLOCK_REF_8M=y
+# CONFIG_STM32_CLOCK_REF_12M is not set
+# CONFIG_STM32_CLOCK_REF_16M is not set
+# CONFIG_STM32_CLOCK_REF_20M is not set
+# CONFIG_STM32_CLOCK_REF_24M is not set
+# CONFIG_STM32_CLOCK_REF_25M is not set
+# CONFIG_STM32_CLOCK_REF_INTERNAL is not set
+CONFIG_CLOCK_REF_FREQ=8000000
+CONFIG_STM32F0_TRIM=16
+# CONFIG_STM32_USB_PA11_PA12 is not set
+CONFIG_STM32_SERIAL_USART1=y
+# CONFIG_STM32_SERIAL_USART1_ALT_PB7_PB6 is not set
+# CONFIG_STM32_SERIAL_USART2 is not set
+# CONFIG_STM32_SERIAL_USART2_ALT_PD6_PD5 is not set
+# CONFIG_STM32_SERIAL_USART3 is not set
+# CONFIG_STM32_SERIAL_USART3_ALT_PD9_PD8 is not set
+# CONFIG_STM32_CANBUS_PA11_PA12 is not set
+# CONFIG_STM32_CANBUS_PA11_PB9 is not set
+# CONFIG_STM32_MMENU_CANBUS_PB8_PB9 is not set
+# CONFIG_STM32_MMENU_CANBUS_PD0_PD1 is not set
+CONFIG_SERIAL_BAUD=250000
+CONFIG_USB_VENDOR_ID=0x1d50
+CONFIG_USB_DEVICE_ID=0x614e
+CONFIG_USB_SERIAL_NUMBER="12345"
+CONFIG_WANT_GPIO_BITBANGING=y
+CONFIG_WANT_DISPLAYS=y
+CONFIG_WANT_SENSORS=y
+CONFIG_WANT_LIS2DW=y
+CONFIG_WANT_LDC1612=y
+CONFIG_WANT_HX71X=y
+CONFIG_WANT_ADS1220=y
+CONFIG_WANT_SOFTWARE_I2C=y
+CONFIG_WANT_SOFTWARE_SPI=y
+CONFIG_NEED_SENSOR_BULK=y
+CONFIG_CANBUS_FREQUENCY=1000000
+CONFIG_INITIAL_PINS=""
+CONFIG_HAVE_GPIO=y
+CONFIG_HAVE_GPIO_ADC=y
+CONFIG_HAVE_GPIO_SPI=y
+CONFIG_HAVE_GPIO_I2C=y
+CONFIG_HAVE_GPIO_HARD_PWM=y
+CONFIG_HAVE_STRICT_TIMING=y
+CONFIG_HAVE_CHIPID=y
+CONFIG_HAVE_STEPPER_BOTH_EDGE=y
+CONFIG_HAVE_BOOTLOADER_REQUEST=y
+CONFIG_INLINE_STEPPER_HACK=y
diff --git a/assets/printer/mainsail.cfg b/assets/printer/mainsail.cfg
new file mode 100644
index 0000000..201a6c2
--- /dev/null
+++ b/assets/printer/mainsail.cfg
@@ -0,0 +1,313 @@
+## Client klipper macro definitions
+##
+## Copyright (C) 2022 Alex Zellner <alexander.zellner@googlemail.com>
+##
+## This file may be distributed under the terms of the GNU GPLv3 license
+##
+## !!! This file is read-only. Maybe the used editor indicates that. !!!
+##
+## Customization:
+##   1) copy the gcode_macro _CLIENT_VARIABLE (see below) to your printer.cfg
+##   2) remove the comment mark (#) from all lines
+##   3) change any value in there to your needs
+##
+## Use the PAUSE macro direct in your M600:
+##  e.g. with a different park position front left and a minimal height of 50 
+##    [gcode_macro M600]
+##    description: Filament change
+##    gcode: PAUSE X=10 Y=10 Z_MIN=50
+##  Z_MIN will park the toolhead at a minimum of 50 mm above to bed to make it easier for you to swap filament.
+##
+## Client variable macro for your printer.cfg
+#[gcode_macro _CLIENT_VARIABLE]
+#variable_use_custom_pos   : False ; use custom park coordinates for x,y [True/False]
+#variable_custom_park_x    : 0.0   ; custom x position; value must be within your defined min and max of X
+#variable_custom_park_y    : 0.0   ; custom y position; value must be within your defined min and max of Y
+#variable_custom_park_dz   : 2.0   ; custom dz value; the value in mm to lift the nozzle when move to park position
+#variable_retract          : 1.0   ; the value to retract while PAUSE
+#variable_cancel_retract   : 5.0   ; the value to retract while CANCEL_PRINT
+#variable_speed_retract    : 35.0  ; retract speed in mm/s
+#variable_unretract        : 1.0   ; the value to unretract while RESUME
+#variable_speed_unretract  : 35.0  ; unretract speed in mm/s
+#variable_speed_hop        : 15.0  ; z move speed in mm/s
+#variable_speed_move       : 100.0 ; move speed in mm/s
+#variable_park_at_cancel   : False ; allow to move the toolhead to park while execute CANCEL_PRINT [True/False]
+#variable_park_at_cancel_x : None  ; different park position during CANCEL_PRINT [None/Position as Float]; park_at_cancel must be True
+#variable_park_at_cancel_y : None  ; different park position during CANCEL_PRINT [None/Position as Float]; park_at_cancel must be True
+## !!! Caution [firmware_retraction] must be defined in the printer.cfg if you set use_fw_retract: True !!!
+#variable_use_fw_retract   : False ; use fw_retraction instead of the manual version [True/False]
+#variable_idle_timeout     : 0     ; time in sec until idle_timeout kicks in. Value 0 means that no value will be set or restored
+#variable_runout_sensor    : ""    ; If a sensor is defined, it will be used to cancel the execution of RESUME in case no filament is detected.
+##                                   Specify the config name of the runout sensor e.g "filament_switch_sensor runout". Hint use the same as in your printer.cfg
+## !!! Custom macros, please use with care and review the section of the corresponding macro.
+## These macros are for simple operations like setting a status LED. Please make sure your macro does not interfere with the basic macro functions.
+## Only  single line commands are supported, please create a macro if you need more than one command.
+#variable_user_pause_macro : ""    ; Everything inside the "" will be executed after the klipper base pause (PAUSE_BASE) function
+#variable_user_resume_macro: ""    ; Everything inside the "" will be executed before the klipper base resume (RESUME_BASE) function
+#variable_user_cancel_macro: ""    ; Everything inside the "" will be executed before the klipper base cancel (CANCEL_PRINT_BASE) function
+#gcode:
+
+[virtual_sdcard]
+path: /srv/klipper/gcodes
+on_error_gcode: CANCEL_PRINT
+
+[pause_resume]
+#recover_velocity: 50.
+#   When capture/restore is enabled, the speed at which to return to
+#   the captured position (in mm/s). Default is 50.0 mm/s.
+
+[display_status]
+
+[respond]
+
+[gcode_macro CANCEL_PRINT]
+description: Cancel the actual running print
+rename_existing: CANCEL_PRINT_BASE
+gcode:
+  ##### get user parameters or use default #####
+  {% set client = printer['gcode_macro _CLIENT_VARIABLE']|default({}) %}
+  {% set allow_park = client.park_at_cancel|default(false)|lower == 'true' %}
+  {% set retract = client.cancel_retract|default(5.0)|abs %}
+  ##### define park position #####
+  {% set park_x = "" if (client.park_at_cancel_x|default(none) is none)
+            else "X=" ~ client.park_at_cancel_x %}
+  {% set park_y = "" if (client.park_at_cancel_y|default(none) is none)
+            else "Y=" ~ client.park_at_cancel_y %}
+  {% set custom_park = park_x|length > 0 or park_y|length > 0 %}
+  ##### end of definitions #####
+  # restore idle_timeout time if needed
+  {% if printer['gcode_macro RESUME'].restore_idle_timeout > 0 %}
+    SET_IDLE_TIMEOUT TIMEOUT={printer['gcode_macro RESUME'].restore_idle_timeout}
+  {% endif %}
+  {% if (custom_park or not printer.pause_resume.is_paused) and allow_park %} _TOOLHEAD_PARK_PAUSE_CANCEL {park_x} {park_y} {% endif %}
+  _CLIENT_RETRACT LENGTH={retract}
+  TURN_OFF_HEATERS
+  M106 S0
+  {client.user_cancel_macro|default("")}
+  SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=idle_state VALUE=False
+  # clear pause_next_layer and pause_at_layer as preparation for next print
+  SET_PAUSE_NEXT_LAYER ENABLE=0
+  SET_PAUSE_AT_LAYER ENABLE=0 LAYER=0
+  CANCEL_PRINT_BASE
+
+[gcode_macro PAUSE]
+description: Pause the actual running print
+rename_existing: PAUSE_BASE
+gcode:
+  ##### get user parameters or use default ##### 
+  {% set client = printer['gcode_macro _CLIENT_VARIABLE']|default({}) %}
+  {% set idle_timeout = client.idle_timeout|default(0) %}
+  {% set temp = printer[printer.toolhead.extruder].target if printer.toolhead.extruder != '' else 0 %}
+  {% set restore = False if printer.toolhead.extruder == ''
+              else True  if params.RESTORE|default(1)|int == 1 else False %}
+  ##### end of definitions #####
+  SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=last_extruder_temp VALUE="{{'restore': restore, 'temp': temp}}"
+  # set a new idle_timeout value
+  {% if idle_timeout > 0 %}
+    SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=restore_idle_timeout VALUE={printer.configfile.settings.idle_timeout.timeout}
+    SET_IDLE_TIMEOUT TIMEOUT={idle_timeout}
+  {% endif %}
+  PAUSE_BASE
+  {client.user_pause_macro|default("")}
+  _TOOLHEAD_PARK_PAUSE_CANCEL {rawparams}
+
+[gcode_macro RESUME]
+description: Resume the actual running print
+rename_existing: RESUME_BASE
+variable_last_extruder_temp: {'restore': False, 'temp': 0}
+variable_restore_idle_timeout: 0
+variable_idle_state: False
+gcode:
+  ##### get user parameters or use default #####
+  {% set client = printer['gcode_macro _CLIENT_VARIABLE']|default({}) %}
+  {% set velocity = printer.configfile.settings.pause_resume.recover_velocity %}
+  {% set sp_move = client.speed_move|default(velocity) %}
+  {% set runout_resume = True if client.runout_sensor|default("") == ""     # no runout
+                    else True if not printer[client.runout_sensor].enabled  # sensor is disabled
+                    else printer[client.runout_sensor].filament_detected %} # sensor status
+  {% set can_extrude = True if printer.toolhead.extruder == ''           # no extruder defined in config
+                  else printer[printer.toolhead.extruder].can_extrude %} # status of active extruder
+  {% set do_resume = False %}
+  {% set prompt_txt = [] %}
+  ##### end of definitions #####
+  #### Printer comming from timeout idle state ####
+  {% if printer.idle_timeout.state|upper == "IDLE" or idle_state %}
+    SET_GCODE_VARIABLE MACRO=RESUME VARIABLE=idle_state VALUE=False
+    {% if last_extruder_temp.restore %}
+      # we need to use the unicode (\u00B0) for the ° as py2 env's would throw an error otherwise 
+      RESPOND TYPE=echo MSG='{"Restoring \"%s\" temperature to %3.1f\u00B0C, this may take some time" % (printer.toolhead.extruder, last_extruder_temp.temp) }'
+      M109 S{last_extruder_temp.temp}
+      {% set do_resume = True %}
+    {% elif can_extrude %}
+      {% set do_resume = True %}
+    {% else %} 
+      RESPOND TYPE=error MSG='{"Resume aborted !!! \"%s\" not hot enough, please heat up again and press RESUME" % printer.toolhead.extruder}'
+      {% set _d = prompt_txt.append("\"%s\" not hot enough, please heat up again and press RESUME" % printer.toolhead.extruder) %}
+    {% endif %}
+  #### Printer comming out of regular PAUSE state ####
+  {% elif can_extrude %}
+    {% set do_resume = True %}
+  {% else %}
+    RESPOND TYPE=error MSG='{"Resume aborted !!! \"%s\" not hot enough, please heat up again and press RESUME" % printer.toolhead.extruder}'
+    {% set _d = prompt_txt.append("\"%s\" not hot enough, please heat up again and press RESUME" % printer.toolhead.extruder) %}
+  {% endif %}
+  {% if runout_resume %}
+    {% if do_resume %}
+      {% if restore_idle_timeout > 0 %} SET_IDLE_TIMEOUT TIMEOUT={restore_idle_timeout} {% endif %} # restore idle_timeout time
+      {client.user_resume_macro|default("")}
+      _CLIENT_EXTRUDE
+      RESUME_BASE VELOCITY={params.VELOCITY|default(sp_move)}
+    {% endif %}
+  {% else %}
+    RESPOND TYPE=error MSG='{"Resume aborted !!! \"%s\" detects no filament, please load filament and press RESUME" % (client.runout_sensor.split(" "))[1]}'
+    {% set _d = prompt_txt.append("\"%s\" detects no filament, please load filament and press RESUME" % (client.runout_sensor.split(" "))[1]) %}
+  {% endif %}
+  ##### Generate User Information box in case of abort #####
+  {% if not (runout_resume and do_resume) %} 
+    RESPOND TYPE=command MSG="action:prompt_begin RESUME aborted !!!"
+    {% for element in prompt_txt %}
+      RESPOND TYPE=command MSG='{"action:prompt_text %s" % element}' 
+    {% endfor %}
+    RESPOND TYPE=command MSG="action:prompt_footer_button Ok|RESPOND TYPE=command MSG=action:prompt_end|info"
+    RESPOND TYPE=command MSG="action:prompt_show"
+  {% endif %}
+  
+# Usage: SET_PAUSE_NEXT_LAYER [ENABLE=[0|1]] [MACRO=<name>]
+[gcode_macro SET_PAUSE_NEXT_LAYER]
+description: Enable a pause if the next layer is reached
+gcode:
+  {% set pause_next_layer = printer['gcode_macro SET_PRINT_STATS_INFO'].pause_next_layer %}
+  {% set ENABLE = params.ENABLE|default(1)|int != 0 %}
+  {% set MACRO = params.MACRO|default(pause_next_layer.call, True) %}
+  SET_GCODE_VARIABLE MACRO=SET_PRINT_STATS_INFO VARIABLE=pause_next_layer VALUE="{{ 'enable': ENABLE, 'call': MACRO }}"
+
+# Usage: SET_PAUSE_AT_LAYER [ENABLE=[0|1]] [LAYER=<number>] [MACRO=<name>]
+[gcode_macro SET_PAUSE_AT_LAYER]
+description: Enable/disable a pause if a given layer number is reached
+gcode:
+  {% set pause_at_layer = printer['gcode_macro SET_PRINT_STATS_INFO'].pause_at_layer %}
+  {% set ENABLE = params.ENABLE|int != 0 if params.ENABLE is defined
+             else params.LAYER is defined %}
+  {% set LAYER = params.LAYER|default(pause_at_layer.layer)|int %}
+  {% set MACRO = params.MACRO|default(pause_at_layer.call, True) %}
+  SET_GCODE_VARIABLE MACRO=SET_PRINT_STATS_INFO VARIABLE=pause_at_layer VALUE="{{ 'enable': ENABLE, 'layer': LAYER, 'call': MACRO }}"
+
+# Usage: SET_PRINT_STATS_INFO [TOTAL_LAYER=<total_layer_count>] [CURRENT_LAYER= <current_layer>]
+[gcode_macro SET_PRINT_STATS_INFO]
+rename_existing: SET_PRINT_STATS_INFO_BASE
+description: Overwrite, to get pause_next_layer and pause_at_layer feature
+variable_pause_next_layer: { 'enable': False, 'call': "PAUSE" }
+variable_pause_at_layer  : { 'enable': False, 'layer': 0, 'call': "PAUSE" }
+gcode:
+  {% if pause_next_layer.enable %}
+    RESPOND TYPE=echo MSG='{"%s, forced by pause_next_layer" % pause_next_layer.call}'
+    {pause_next_layer.call} ; execute the given gcode to pause, should be either M600 or PAUSE
+    SET_PAUSE_NEXT_LAYER ENABLE=0
+  {% elif pause_at_layer.enable and params.CURRENT_LAYER is defined and params.CURRENT_LAYER|int == pause_at_layer.layer %}
+    RESPOND TYPE=echo MSG='{"%s, forced by pause_at_layer [%d]" % (pause_at_layer.call, pause_at_layer.layer)}'
+    {pause_at_layer.call} ; execute the given gcode to pause, should be either M600 or PAUSE
+    SET_PAUSE_AT_LAYER ENABLE=0
+  {% endif %}
+  SET_PRINT_STATS_INFO_BASE {rawparams}
+  
+##### internal use #####
+[gcode_macro _TOOLHEAD_PARK_PAUSE_CANCEL]
+description: Helper: park toolhead used in PAUSE and CANCEL_PRINT
+gcode:
+  ##### get user parameters or use default #####
+  {% set client = printer['gcode_macro _CLIENT_VARIABLE']|default({}) %}
+  {% set velocity = printer.configfile.settings.pause_resume.recover_velocity %}
+  {% set use_custom     = client.use_custom_pos|default(false)|lower == 'true' %}
+  {% set custom_park_x  = client.custom_park_x|default(0.0) %}
+  {% set custom_park_y  = client.custom_park_y|default(0.0) %}
+  {% set park_dz        = client.custom_park_dz|default(2.0)|abs %}
+  {% set sp_hop         = client.speed_hop|default(15) * 60 %}
+  {% set sp_move        = client.speed_move|default(velocity) * 60 %}
+  ##### get config and toolhead values #####
+  {% set origin    = printer.gcode_move.homing_origin %}
+  {% set act       = printer.gcode_move.gcode_position %}
+  {% set max       = printer.toolhead.axis_maximum %}
+  {% set cone      = printer.toolhead.cone_start_z|default(max.z) %} ; height as long the toolhead can reach max and min of an delta
+  {% set round_bed = True if printer.configfile.settings.printer.kinematics is in ['delta','polar','rotary_delta','winch']
+                else False %}
+  ##### define park position #####
+  {% set z_min = params.Z_MIN|default(0)|float %}
+  {% set z_park = [[(act.z + park_dz), z_min]|max, (max.z - origin.z)]|min %}
+  {% set x_park = params.X       if params.X is defined
+             else custom_park_x  if use_custom
+             else 0.0            if round_bed
+             else (max.x - 5.0) %}
+  {% set y_park = params.Y       if params.Y is defined
+             else custom_park_y  if use_custom
+             else (max.y - 5.0)  if round_bed and z_park < cone
+             else 0.0            if round_bed
+             else (max.y - 5.0) %}
+  ##### end of definitions #####
+  _CLIENT_RETRACT
+  {% if "xyz" in printer.toolhead.homed_axes %}
+    G90
+    G1 Z{z_park} F{sp_hop}
+    G1 X{x_park} Y{y_park} F{sp_move}
+    {% if not printer.gcode_move.absolute_coordinates %} G91 {% endif %}
+  {% else %}
+    RESPOND TYPE=echo MSG='Printer not homed'
+  {% endif %}
+  
+[gcode_macro _CLIENT_EXTRUDE]
+description: Extrudes, if the extruder is hot enough
+gcode:
+  ##### get user parameters or use default #####
+  {% set client = printer['gcode_macro _CLIENT_VARIABLE']|default({}) %}
+  {% set use_fw_retract = (client.use_fw_retract|default(false)|lower == 'true') and (printer.firmware_retraction is defined) %}
+  {% set length = params.LENGTH|default(client.unretract)|default(1.0)|float %}
+  {% set speed = params.SPEED|default(client.speed_unretract)|default(35) %}
+  {% set absolute_extrude = printer.gcode_move.absolute_extrude %}
+  ##### end of definitions #####
+  {% if printer.toolhead.extruder != '' %}
+    {% if printer[printer.toolhead.extruder].can_extrude %}
+      {% if use_fw_retract %}
+        {% if length < 0 %}
+          G10
+        {% else %}
+          G11
+        {% endif %}
+      {% else %}
+        M83
+        G1 E{length} F{(speed|float|abs) * 60}
+        {% if absolute_extrude %}
+          M82
+        {% endif %}
+      {% endif %}
+    {% else %}
+      RESPOND TYPE=echo MSG='{"\"%s\" not hot enough" % printer.toolhead.extruder}'
+    {% endif %}
+  {% endif %}
+
+[gcode_macro _CLIENT_RETRACT]
+description: Retracts, if the extruder is hot enough
+gcode:
+  {% set client = printer['gcode_macro _CLIENT_VARIABLE']|default({}) %}
+  {% set length = params.LENGTH|default(client.retract)|default(1.0)|float %}
+  {% set speed = params.SPEED|default(client.speed_retract)|default(35) %}
+
+  _CLIENT_EXTRUDE LENGTH=-{length|float|abs} SPEED={speed|float|abs}
+
+[gcode_macro _CLIENT_LINEAR_MOVE]
+description: Linear move with save and restore of the gcode state
+gcode:
+  {% set x_move = "X" ~ params.X if params.X is defined else "" %}
+  {% set y_move = "Y" ~ params.Y if params.Y is defined else "" %}
+  {% set z_move = "Z" ~ params.Z if params.Z is defined else "" %}
+  {% set e_move = "E" ~ params.E if params.E is defined else "" %}
+  {% set rate = "F" ~ params.F if params.F is defined else "" %}
+  {% set ABSOLUTE = params.ABSOLUTE | default(0) | int != 0 %}
+  {% set ABSOLUTE_E = params.ABSOLUTE_E | default(0) | int != 0 %}
+  SAVE_GCODE_STATE NAME=_client_movement
+  {% if x_move or y_move or z_move %}
+    G9{ 0 if ABSOLUTE else 1 }
+  {% endif %}
+  {% if e_move %}
+    M8{ 2 if ABSOLUTE_E else 3 }
+  {% endif %}
+  G1 { x_move } { y_move } { z_move } { e_move } { rate }
+  RESTORE_GCODE_STATE NAME=_client_movement
diff --git a/assets/printer/printer.cfg b/assets/printer/printer.cfg
new file mode 100644
index 0000000..a98cb2b
--- /dev/null
+++ b/assets/printer/printer.cfg
@@ -0,0 +1,159 @@
+# This file contains a configuration for the Anycubic Vyper printer from 2021.
+# It uses a clone of the STM32F103 chip named GD32F103.
+# There are 2 Mainboard versions out there v0.0.5 and v0.0.6, this config has
+# been tested with the v0.0.6 only. It should probably work for v0.0.5 as well
+# since there are no different changes in the Anycubic Marlin firmware.
+# The LCD is not supported yet (might work, but didn't try yet).
+#
+# To create the Firmware you need to use the following configuration:
+#     - Micro-controller: STM32
+#     - Processor model: STM32F103
+#     - Bootloader offset: 32KiB
+#     - Communication interface: Serial (on USART1 PA10/PA9)
+#
+# To install the Firmware rename the klipper bin to `main_board_20xxxxxx.bin`
+# and copy it to an SD Card.
+# Power off the Printer, insert the SD Card and power it on.
+# It should beep several times and the LCD should be stuck on the Splash screen.
+# Now you should be able to connect to the Printer, you might need to change
+# the mcu/serial setting in this config according to your set up.
+#
+# If you want to revert the Firmware back to Marlin you simply need to flash it
+# with a anycubic firmware through the SD Card
+
+[stepper_x]
+step_pin: PC2
+dir_pin: PB9
+enable_pin: !PC3
+microsteps: 16
+rotation_distance: 40
+endstop_pin: !PA7
+position_min: -3
+position_endstop: -3
+position_max: 245
+homing_speed: 30.0
+
+[stepper_y]
+step_pin: PB8
+dir_pin: PB7
+enable_pin: !PC13
+microsteps: 16
+rotation_distance: 32
+endstop_pin: !PC5
+position_min: -17
+position_endstop: -17
+position_max: 245
+homing_speed: 30.0
+
+[stepper_z]
+step_pin: PB6
+dir_pin: !PB5
+enable_pin: !PC14
+microsteps: 16
+rotation_distance: 8
+endstop_pin: PB2
+position_endstop: 0.0
+position_max: 260
+position_min: -3
+homing_speed: 5.0
+
+[stepper_z1]
+step_pin: PC0
+dir_pin: !PC1
+enable_pin: !PC15
+microsteps: 16
+rotation_distance: 8
+endstop_pin: PC6
+
+[extruder]
+step_pin: PB4
+dir_pin: !PB3
+enable_pin: !PA15
+microsteps: 16
+rotation_distance: 22.76500  #has to be calibrated by everyone, official document: diameter = 7.25
+gear_ratio: 50:17
+full_steps_per_rotation: 200
+nozzle_diameter: 0.400
+filament_diameter: 1.750
+heater_pin: PA1
+sensor_type: ATC Semitec 104GT-2
+sensor_pin: PC4
+control: pid
+pid_kp: 28.937
+pid_ki: 1.295
+pid_kd: 161.688
+min_temp: 0
+max_temp: 260
+
+[heater_fan extruder_fan]
+pin: PB1
+
+[heater_bed]
+heater_pin: PA4
+sensor_type: EPCOS 100K B57560G104F
+sensor_pin: PB0
+control: pid
+pid_kp: 67.648
+pid_ki: 1.044
+pid_kd: 1095.893
+min_temp: 0
+max_temp: 110
+
+[fan]
+pin: PA0
+
+[controller_fan controller_fan]
+pin: PA14
+stepper: stepper_x,stepper_y,stepper_z,stepper_z1
+
+[probe]
+pin: !PB12
+z_offset: 0
+activate_gcode:
+    probe_reset
+
+[output_pin BEEPER_PIN]
+pin: PB15
+pwm: True
+value: 0
+shutdown_value: 0
+cycle_time: 0.001
+scale: 1
+
+[output_pin probe_reset_pin]
+pin: PB13
+
+[output_pin LED]
+pin: mcu:PA13
+pwm: False
+value: 0
+
+[bed_mesh]
+mesh_min: 15,15
+mesh_max: 230, 230
+
+[filament_switch_sensor runout]
+pause_on_runout: True
+switch_pin: PA5
+
+[mcu]
+serial: /dev/ttyUSB0
+restart_method: command
+
+[safe_z_home]
+home_xy_position: -3,-17
+z_hop: 10
+
+[printer]
+kinematics: cartesian
+max_velocity: 300
+max_accel: 3000
+max_z_velocity: 10
+max_z_accel: 100
+
+[gcode_macro probe_reset]
+gcode:
+    SET_PIN PIN=probe_reset_pin VALUE=0
+    G4 P300
+    SET_PIN PIN=probe_reset_pin VALUE=1
+    G4 P100