# This file provides examples of Klipper G-Code macros.  The snippets
# in this file may be copied into the main printer.cfg file and
# customized.

# See docs/Config_Reference.md for a description of parameters.


######################################################################
# Start Print and End Print
######################################################################

# Replace the slicer's custom start and end g-code scripts with
# START_PRINT and END_PRINT. See docs/Slicers.md for more information on using these macros.

[gcode_macro START_PRINT]
gcode:
    {% set BED_TEMP = params.BED_TEMP|default(60)|float %}
    {% set EXTRUDER_TEMP = params.EXTRUDER_TEMP|default(190)|float %}
    # Start bed heating
    M140 S{BED_TEMP}
    # Use absolute coordinates
    G90
    # Reset the G-Code Z offset (adjust Z offset if needed)
    SET_GCODE_OFFSET Z=0.0
    # Home the printer
    G28
    # Move the nozzle near the bed
    G1 Z5 F3000
    # Move the nozzle very close to the bed
    G1 Z0.15 F300
    # Wait for bed to reach temperature
    M190 S{BED_TEMP}
    # Set and wait for nozzle to reach temperature
    M109 S{EXTRUDER_TEMP}

[gcode_macro END_PRINT]
gcode:
    # Turn off bed, extruder, and fan
    M140 S0
    M104 S0
    M106 S0
    # Move nozzle away from print while retracting
    G91
    G1 X-2 Y-2 E-3 F300
    # Raise nozzle by 10mm
    G1 Z10 F3000
    G90
    # Disable steppers
    M84


######################################################################
# Beeper
######################################################################

# M300 : Play tone. Beeper support, as commonly found on usual LCD
# displays (i.e. RepRapDiscount 2004 Smart Controller, RepRapDiscount
# 12864 Full Graphic). This defines a custom I/O pin and a custom
# GCODE macro.  Usage:
#   M300 [P<ms>] [S<Hz>]
#   P is the tone duration, S the tone frequency.
# The frequency won't be pitch perfect.

[output_pin BEEPER_pin]
pin: ar37
#   Beeper pin. This parameter must be provided.
#   ar37 is the default RAMPS/MKS pin.
pwm: True
#   A piezo beeper needs a PWM signal, a DC buzzer doesn't.
value: 0
#   Silent at power on, set to 1 if active low.
shutdown_value: 0
#   Disable at emergency shutdown (no PWM would be available anyway).
cycle_time: 0.001
#   Default PWM frequency : 0.001 = 1ms will give a tone of 1kHz
#   Although not pitch perfect.

[gcode_macro M300]
gcode:
    # Use a default 1kHz tone if S is omitted.
    {% set S = params.S|default(1000)|int %}
    # Use a 10ms duration is P is omitted.
    {% set P = params.P|default(100)|int %}
    SET_PIN PIN=BEEPER_pin VALUE=0.5 CYCLE_TIME={ 1.0/S if S > 0 else 1 }
    G4 P{P}
    SET_PIN PIN=BEEPER_pin VALUE=0


######################################################################
# Filament Change
######################################################################

# M600: Filament Change. This macro will pause the printer, move the
# tool to the change position, and retract the filament 50mm. Adjust
# the retraction settings for your own extruder. After filament has
# been changed, the print can be resumed from its previous position
# with the "RESUME" gcode.

[pause_resume]

[gcode_macro M600]
gcode:
    {% set X = params.X|default(50)|float %}
    {% set Y = params.Y|default(0)|float %}
    {% set Z = params.Z|default(10)|float %}
    SAVE_GCODE_STATE NAME=M600_state
    PAUSE
    G91
    G1 E-.8 F2700
    G1 Z{Z}
    G90
    G1 X{X} Y{Y} F3000
    G91
    G1 E-50 F1000
    RESTORE_GCODE_STATE NAME=M600_state

######################################################################
# BMP280/BME280/BME680 Environmental Sensor
######################################################################

# The macro below assumes you have a BME280 sensor_type defined in one
# of the applicable sections in printer.cfg, such as:
#
#[temperature_sensor my_sensor]
#sensor_type: BME280
#gcode_id: AMB
#
# Note the format of the parameter SENSOR in the macro below.  The BME280
# sensor status can be accessed using the format "bme280 <section_name>".
# The example section above is named "my_sensor", thus the bme280 can be
# queried as follows:
#
# QUERY_BME280 SENSOR='bme280 my_sensor'
#
# Since a default parameter is defined one could simply enter QUERY_BME280
# as well.

[gcode_macro QUERY_BME280]
gcode:
    {% set sensor = printer["bme280 my_sensor"] %}
    {action_respond_info(
        "Temperature: %.2f C\n"
        "Pressure: %.2f hPa\n"
        "Humidity: %.2f%%" % (
            sensor.temperature,
            sensor.pressure,
            sensor.humidity))}

######################################################################
# HTU21D family Environmental Sensor
######################################################################

# The macro below assumes you have a HTU21D sensor_type defined in one
# of the applicable sections in printer.cfg, such as:
#
#[temperature_sensor my_sensor]
#sensor_type: HTU21D
#
# Note the format of the parameter SENSOR in the macro below.  The HTU21D
# sensor status can be accessed using the format "htu21d <section_name>".
# The example section above is named "my_sensor", thus the htu21d can be
# queried as follows:
#
# QUERY_HTU21D SENSOR='htu21d my_sensor'
#
# Since a default parameter is defined one could simply enter QUERY_HTU21D
# as well.

[gcode_macro QUERY_HTU21D]
gcode:
    {% set sensor = printer["htu21d my_sensor"] %}
    {action_respond_info(
        "Temperature: %.2f C\n"
        "Humidity: %.2f%%" % (
            sensor.temperature,
            sensor.humidity))}

######################################################################
# Override M117 command with rawparams
######################################################################

# The macro below will override the default M117 command to echo the message.
#
# It uses the rawparams pseudo-variable that contains the full unparsed
# parameters that was passed to the M117 command.
#
# As this can include comments, we are trimming the text when a `;` or `#` is
# found, and escaping any existing `"`

[gcode_macro M117]
rename_existing: M117.1
gcode:
  {% if rawparams %}
    {% set escaped_msg = rawparams.split(';', 1)[0].split('\x23', 1)[0]|replace('"', '\\"') %}
    SET_DISPLAY_TEXT MSG="{escaped_msg}"
    RESPOND TYPE=command MSG="{escaped_msg}"
  {% else %}
    SET_DISPLAY_TEXT
  {% endif %}

# SDCard 'looping' (aka Marlin M808 commands) support
#
# Support SDCard looping
[sdcard_loop]

# 'Marlin' style M808 compatibility macro for SDCard looping
[gcode_macro M808]
gcode:
    {% if params.K is not defined and params.L is defined %}SDCARD_LOOP_BEGIN COUNT={params.L|int}{% endif %}
    {% if params.K is not defined and params.L is not defined %}SDCARD_LOOP_END{% endif %}
    {% if params.K is defined and params.L is not defined %}SDCARD_LOOP_DESIST{% endif %}

# Cancel object (aka Marlin/RRF M486 commands) support
#
# Enable object exclusion
[exclude_object]

[gcode_macro M486]
gcode:
  # Parameters known to M486 are as follows:
  #   [C<flag>] Cancel the current object
  #   [P<index>] Cancel the object with the given index
  #   [S<index>] Set the index of the current object.
  #       If the object with the given index has been canceled, this will cause
  #       the firmware to skip to the next object. The value -1 is used to
  #       indicate something that isn’t an object and shouldn’t be skipped.
  #   [T<count>] Reset the state and set the number of objects
  #   [U<index>] Un-cancel the object with the given index. This command will be
  #       ignored if the object has already been skipped

  {% if 'exclude_object' not in printer %}
    {action_raise_error("[exclude_object] is not enabled")}
  {% endif %}

  {% if 'T' in params %}
    EXCLUDE_OBJECT RESET=1

    {% for i in range(params.T | int) %}
      EXCLUDE_OBJECT_DEFINE NAME={i}
    {% endfor %}
  {% endif %}

  {% if 'C' in params %}
    EXCLUDE_OBJECT CURRENT=1
  {% endif %}

  {% if 'P' in params %}
    EXCLUDE_OBJECT NAME={params.P}
  {% endif %}

  {% if 'S' in params %}
    {% if params.S == '-1' %}
      {% if printer.exclude_object.current_object %}
        EXCLUDE_OBJECT_END NAME={printer.exclude_object.current_object}
      {% endif %}
    {% else %}
      EXCLUDE_OBJECT_START NAME={params.S}
    {% endif %}
  {% endif %}

  {% if 'U' in params %}
    EXCLUDE_OBJECT RESET=1 NAME={params.U}
  {% endif %}

######################################################################
# G130: Set digital potentiometer value
######################################################################

# The macro below uses the MCP4018 SET_DIGIPOT command to implement
# a `G130` as used on classic Mightyboard-based printers such as
# The Makerbot Replicator 2/2X.
#
# The `G130` command can be used to lower the stepper current
# during preheating and raise the current again prior to starting
# the print.  This is necessary for printers with smaller power
# supplies that needed all the power to heat the bed.
#
# This macro requires one or more [mcp4018] configuration sections:
# (x_axis_pot, y_axis_pot, z_axis_pot, a_axis_pot, b_axis_pot)
#
# Example: G130 X20 Y20 Z20 A20 B20 ; Lower stepper Vrefs while heating

[gcode_macro G130]
gcode:
  M400
  {% if ('X' in params) and ('mcp4018 x_axis_pot' in printer.configfile.config) %}
    {% set x_value = params['X']|float %}
    {% set x_axis_pot_scale = printer.configfile.config["mcp4018 x_axis_pot"].scale|float %}
    SET_DIGIPOT DIGIPOT=x_axis_pot WIPER={ x_axis_pot_scale * (x_value / 127.0)}
  {% endif %}
  {% if ('Y' in params) and ('mcp4018 y_axis_pot' in printer.configfile.config) %}
    {% set y_value = params['Y']|float %}
    {% set y_axis_pot_scale = printer.configfile.config["mcp4018 y_axis_pot"].scale|float %}
    SET_DIGIPOT DIGIPOT=y_axis_pot WIPER={ y_axis_pot_scale * (y_value / 127.0)}
  {% endif %}
  {% if ('Z' in params) and ('mcp4018 z_axis_pot' in printer.configfile.config) %}
    {% set z_value = params['Z']|float %}
    {% set z_axis_pot_scale = printer.configfile.config["mcp4018 z_axis_pot"].scale|float %}
    SET_DIGIPOT DIGIPOT=z_axis_pot WIPER={ z_axis_pot_scale * (z_value / 127.0)}
  {% endif %}
  {% if ('A' in params) and ('mcp4018 a_axis_pot' in printer.configfile.config) %}
    {% set a_value = params['A']|float %}
    {% set a_axis_pot_scale = printer.configfile.config["mcp4018 a_axis_pot"].scale|float %}
    SET_DIGIPOT DIGIPOT=a_axis_pot WIPER={ a_axis_pot_scale * (a_value / 127.0)}
  {% endif %}
  {% if ('B' in params) and ('mcp4018 b_axis_pot' in printer.configfile.config) %}
    {% set b_value = params['B']|float %}
    {% set b_axis_pot_scale = printer.configfile.config["mcp4018 b_axis_pot"].scale|float %}
    SET_DIGIPOT DIGIPOT=b_axis_pot WIPER={ b_axis_pot_scale * (b_value / 127.0)}
  {% endif %}