diff --git a/docs/Code_Overview.md b/docs/Code_Overview.md index c47d783c..73111870 100644 --- a/docs/Code_Overview.md +++ b/docs/Code_Overview.md @@ -473,9 +473,9 @@ system specified in the config file. This may differ from the bed_tilt, skew_correction) is in effect. This may differ from the actual coordinates specified in the last `G1` command if the g-code origin has been changed (eg, `G92`, `SET_GCODE_OFFSET`, `M221`). The -`M114` command (`gcode.get_status()['gcode_position']`) will report -the last g-code position relative to the current g-code coordinate -system. +`M114` command (`gcode_move.get_status()['gcode_position']`) will +report the last g-code position relative to the current g-code +coordinate system. The "gcode base" is the location of the g-code origin in cartesian coordinates relative to the coordinate system specified in the config diff --git a/docs/Config_Changes.md b/docs/Config_Changes.md index e0cc4c03..13257326 100644 --- a/docs/Config_Changes.md +++ b/docs/Config_Changes.md @@ -6,6 +6,11 @@ All dates in this document are approximate. # Changes +20200816: The gcode macro `printer.gcode` object has been renamed to +`printer.gcode_move`. Several undocumented variables in +`printer.toolhead` and `printer.gcode` have been removed. See +docs/Command_Templates.md for a list of available template variables. + 20200816: The gcode macro "action_" system has changed. Replace any calls to `printer.gcode.action_emergency_stop()` with `action_emergency_stop()`, `printer.gcode.action_respond_info()` with diff --git a/klippy/extras/bed_mesh.py b/klippy/extras/bed_mesh.py index cfc7807e..b1c0f6b8 100644 --- a/klippy/extras/bed_mesh.py +++ b/klippy/extras/bed_mesh.py @@ -87,7 +87,9 @@ class BedMesh: self.gcode.register_command( 'BED_MESH_CLEAR', self.cmd_BED_MESH_CLEAR, desc=self.cmd_BED_MESH_CLEAR_help) - self.gcode.set_move_transform(self) + # Register transform + gcode_move = self.printer.lookup_object('gcode_move') + gcode_move.set_move_transform(self) def handle_ready(self): self.toolhead = self.printer.lookup_object('toolhead') self.bmc.print_generated_points(logging.info) @@ -126,7 +128,8 @@ class BedMesh: self.z_mesh = mesh self.splitter.initialize(mesh) # cache the current position before a transform takes place - self.gcode.reset_last_position() + gcode_move = self.printer.lookup_object('gcode_move') + gcode_move.reset_last_position() def get_z_factor(self, z_pos): if z_pos >= self.fade_end: return 0. diff --git a/klippy/extras/bed_tilt.py b/klippy/extras/bed_tilt.py index dd75655a..dfcb682f 100644 --- a/klippy/extras/bed_tilt.py +++ b/klippy/extras/bed_tilt.py @@ -19,8 +19,8 @@ class BedTilt: BedTiltCalibrate(config, self) self.toolhead = None # Register move transform with g-code class - gcode = self.printer.lookup_object('gcode') - gcode.set_move_transform(self) + gcode_move = self.printer.lookup_object('gcode_move') + gcode_move.set_move_transform(self) def handle_connect(self): self.toolhead = self.printer.lookup_object('toolhead') def get_position(self): @@ -34,6 +34,8 @@ class BedTilt: self.x_adjust = x_adjust self.y_adjust = y_adjust self.z_adjust = z_adjust + gcode_move = self.printer.lookup_object('gcode_move') + gcode_move.reset_last_position() configfile = self.printer.lookup_object('configfile') configfile.set('bed_tilt', 'x_adjust', "%.6f" % (x_adjust,)) configfile.set('bed_tilt', 'y_adjust', "%.6f" % (y_adjust,)) @@ -80,7 +82,6 @@ class BedTiltCalibrate: z_adjust = (new_params['z_adjust'] - z_offset - x_adjust * offsets[0] - y_adjust * offsets[1]) self.bedtilt.update_adjust(x_adjust, y_adjust, z_adjust) - self.gcode.reset_last_position() # Log and report results logging.info("Calculated bed_tilt parameters: %s", new_params) for pos in positions: diff --git a/klippy/extras/display/display.cfg b/klippy/extras/display/display.cfg index 35a68dd7..a6377914 100644 --- a/klippy/extras/display/display.cfg +++ b/klippy/extras/display/display.cfg @@ -83,7 +83,7 @@ text: { render("_heater_temperature", param_heater_name="heater_bed") } position: 1, 10 text: ~feedrate~ - { "{:>4.0%}".format(printer.gcode.speed_factor) } + { "{:>4.0%}".format(printer.gcode_move.speed_factor) } [display_data _default_16x4 print_progress] position: 2, 0 @@ -164,7 +164,7 @@ text: position: 2, 0 text: ~feedrate~ - { "{:^4.0%}".format(printer.gcode.speed_factor) } + { "{:^4.0%}".format(printer.gcode_move.speed_factor) } [display_data _default_20x4 print_progress] position: 2, 8 diff --git a/klippy/extras/display/menu.cfg b/klippy/extras/display/menu.cfg index 8ac61c4e..77009a1d 100644 --- a/klippy/extras/display/menu.cfg +++ b/klippy/extras/display/menu.cfg @@ -96,7 +96,7 @@ name: Tune [menu __main __tune __speed] type: input name: Speed: {'%3d' % (menu.input*100)}% -input: {printer.gcode.speed_factor} +input: {printer.gcode_move.speed_factor} input_min: 0 input_max: 2 input_step: 0.01 @@ -107,7 +107,7 @@ gcode: [menu __main __tune __flow] type: input name: Flow: {'%3d' % (menu.input*100)}% -input: {printer.gcode.extrude_factor} +input: {printer.gcode_move.extrude_factor} input_min: 0 input_max: 2 input_step: 0.01 @@ -118,7 +118,7 @@ gcode: [menu __main __tune __offsetz] type: input name: Offset Z:{'%05.3f' % menu.input} -input: {printer.gcode.homing_origin.z} +input: {printer.gcode_move.homing_origin.z} input_min: -5 input_max: 5 input_step: 0.005 @@ -260,7 +260,7 @@ name: Move 10mm [menu __main __control __move_10mm __axis_x] type: input name: Move X:{'%05.1f' % menu.input} -input: {printer.gcode.gcode_position.x} +input: {printer.gcode_move.gcode_position.x} input_min: 0 input_max: 200 input_step: 10.0 @@ -273,7 +273,7 @@ gcode: [menu __main __control __move_10mm __axis_y] type: input name: Move Y:{'%05.1f' % menu.input} -input: {printer.gcode.gcode_position.y} +input: {printer.gcode_move.gcode_position.y} input_min: 0 input_max: 200 input_step: 10.0 @@ -287,7 +287,7 @@ gcode: type: input enable: {not printer.idle_timeout.state == "Printing"} name: Move Z:{'%05.1f' % menu.input} -input: {printer.gcode.gcode_position.z} +input: {printer.gcode_move.gcode_position.z} input_min: 0 input_max: 200 input_step: 10.0 @@ -320,7 +320,7 @@ name: Move 1mm [menu __main __control __move_1mm __axis_x] type: input name: Move X:{'%05.1f' % menu.input} -input: {printer.gcode.gcode_position.x} +input: {printer.gcode_move.gcode_position.x} input_min: 0 input_max: 200 input_step: 1.0 @@ -333,7 +333,7 @@ gcode: [menu __main __control __move_1mm __axis_y] type: input name: Move Y:{'%05.1f' % menu.input} -input: {printer.gcode.gcode_position.y} +input: {printer.gcode_move.gcode_position.y} input_min: 0 input_max: 200 input_step: 1.0 @@ -347,7 +347,7 @@ gcode: type: input enable: {not printer.idle_timeout.state == "Printing"} name: Move Z:{'%05.1f' % menu.input} -input: {printer.gcode.gcode_position.z} +input: {printer.gcode_move.gcode_position.z} input_min: 0 input_max: 200 input_step: 1.0 @@ -380,7 +380,7 @@ name: Move 0.1mm [menu __main __control __move_01mm __axis_x] type: input name: Move X:{'%05.1f' % menu.input} -input: {printer.gcode.gcode_position.x} +input: {printer.gcode_move.gcode_position.x} input_min: 0 input_max: 200 input_step: 0.1 @@ -393,7 +393,7 @@ gcode: [menu __main __control __move_01mm __axis_y] type: input name: Move Y:{'%05.1f' % menu.input} -input: {printer.gcode.gcode_position.y} +input: {printer.gcode_move.gcode_position.y} input_min: 0 input_max: 200 input_step: 0.1 @@ -407,7 +407,7 @@ gcode: type: input enable: {not printer.idle_timeout.state == "Printing"} name: Move Z:{'%05.1f' % menu.input} -input: {printer.gcode.gcode_position.z} +input: {printer.gcode_move.gcode_position.z} input_min: 0 input_max: 200 input_step: 0.1 @@ -677,7 +677,7 @@ gcode: [menu __main __setup __calib __delta_calib_man __move_z] type: input name: Move Z: {'%03.2f' % menu.input} -input: {printer.gcode.gcode_position.z} +input: {printer.gcode_move.gcode_position.z} input_step: 1 realtime: True gcode: diff --git a/klippy/extras/gcode_arcs.py b/klippy/extras/gcode_arcs.py index 13a02697..ad973562 100644 --- a/klippy/extras/gcode_arcs.py +++ b/klippy/extras/gcode_arcs.py @@ -17,14 +17,15 @@ class ArcSupport: self.printer = config.get_printer() self.mm_per_arc_segment = config.getfloat('resolution', 1., above=0.0) + self.gcode_move = self.printer.lookup_object('gcode_move') self.gcode = self.printer.lookup_object('gcode') self.gcode.register_command("G2", self.cmd_G2) self.gcode.register_command("G3", self.cmd_G2) def cmd_G2(self, gcmd): - gcodestatus = self.gcode.get_status() + gcodestatus = self.gcode_move.get_status() if not gcodestatus['absolute_coordinates']: - raise self.gcode.error("G2/G3 does not support relative move mode") + raise gcmd.error("G2/G3 does not support relative move mode") currentPos = gcodestatus['gcode_position'] # Parse parameters @@ -60,7 +61,7 @@ class ArcSupport: if asF is not None: g1_params['F'] = asF g1_gcmd = self.gcode.create_gcode_command("G1", "G1", g1_params) - self.gcode.cmd_G1(g1_gcmd) + self.gcode_move.cmd_G1(g1_gcmd) # function planArc() originates from marlin plan_arc() # https://github.com/MarlinFirmware/Marlin diff --git a/klippy/extras/homing_override.py b/klippy/extras/homing_override.py index d7a9a874..9d683537 100644 --- a/klippy/extras/homing_override.py +++ b/klippy/extras/homing_override.py @@ -32,14 +32,14 @@ class HomingOverride: if no_axis: override = True else: - # check if we home an axsis which needs the override + # check if we home an axis which needs the override override = False for axis in self.axes: if gcmd.get(axis, None) is not None: override = True if not override: - self.gcode.cmd_G28(gcmd) + self.prev_G28(gcmd) return # Calculate forced position (if configured) diff --git a/klippy/extras/print_stats.py b/klippy/extras/print_stats.py index 1a3fcb22..67bb2f33 100644 --- a/klippy/extras/print_stats.py +++ b/klippy/extras/print_stats.py @@ -7,11 +7,11 @@ class PrintStats: def __init__(self, config): printer = config.get_printer() - self.gcode = printer.lookup_object('gcode') + self.gcode_move = printer.lookup_object('gcode_move') self.reactor = printer.get_reactor() self.reset() def _update_filament_usage(self, eventtime): - gc_status = self.gcode.get_status(eventtime) + gc_status = self.gcode_move.get_status(eventtime) cur_epos = gc_status['position'].e self.filament_used += (cur_epos - self.last_epos) \ / gc_status['extrude_factor'] @@ -29,7 +29,7 @@ class PrintStats: self.prev_pause_duration += pause_duration self.last_pause_time = None # Reset last e-position - gc_status = self.gcode.get_status(curtime) + gc_status = self.gcode_move.get_status(curtime) self.last_epos = gc_status['position'].e self.state = "printing" self.error_message = "" diff --git a/klippy/extras/skew_correction.py b/klippy/extras/skew_correction.py index afb68bbb..9a0ee2ad 100644 --- a/klippy/extras/skew_correction.py +++ b/klippy/extras/skew_correction.py @@ -40,8 +40,8 @@ class PrinterSkew: gcode.register_command('SKEW_PROFILE', self.cmd_SKEW_PROFILE, desc=self.cmd_SKEW_PROFILE_help) def _handle_ready(self): - gcode = self.printer.lookup_object('gcode') - self.next_transform = gcode.set_move_transform(self, force=True) + gcode_move = self.printer.lookup_object('gcode_move') + self.next_transform = gcode_move.set_move_transform(self, force=True) def _load_storage(self, config): stored_profs = config.get_prefix_sections(self.name) # Remove primary skew_correction section, as it is not a stored profile @@ -73,8 +73,8 @@ class PrinterSkew: self.xy_factor = xy_factor self.xz_factor = xz_factor self.yz_factor = yz_factor - gcode = self.printer.lookup_object('gcode') - gcode.reset_last_position() + gcode_move = self.printer.lookup_object('gcode_move') + gcode_move.reset_last_position() cmd_GET_CURRENT_SKEW_help = "Report current printer skew" def cmd_GET_CURRENT_SKEW(self, gcmd): out = "Current Printer Skew:" diff --git a/klippy/extras/tuning_tower.py b/klippy/extras/tuning_tower.py index 87a0093d..e16192d5 100644 --- a/klippy/extras/tuning_tower.py +++ b/klippy/extras/tuning_tower.py @@ -15,6 +15,7 @@ class TuningTower: self.last_z = self.start = self.factor = self.band = 0. self.last_command_value = None self.command_fmt = "" + self.gcode_move = self.printer.lookup_object("gcode_move") # Register command self.gcode = self.printer.lookup_object("gcode") self.gcode.register_command("TUNING_TOWER", self.cmd_TUNING_TOWER, @@ -34,7 +35,8 @@ class TuningTower: self.command_fmt = "%s %s%%.9f" % (command, parameter) else: self.command_fmt = "%s %s=%%.9f" % (command, parameter) - self.normal_transform = self.gcode.set_move_transform(self, force=True) + nt = self.gcode_move.set_move_transform(self, force=True) + self.normal_transform = nt self.last_z = -99999999.9 self.last_command_value = None self.get_position() @@ -59,7 +61,7 @@ class TuningTower: self.end_test() else: # Process update - gcode_z = self.gcode.get_status()['gcode_position'].z + gcode_z = self.gcode_move.get_status()['gcode_position'].z newval = self.calc_value(gcode_z) self.last_z = z if newval != self.last_command_value: @@ -71,7 +73,7 @@ class TuningTower: normal_transform.move(newpos, speed) def end_test(self): self.gcode.respond_info("Ending tuning test mode") - self.gcode.set_move_transform(self.normal_transform, force=True) + self.gcode_move.set_move_transform(self.normal_transform, force=True) self.normal_transform = None def load_config(config): diff --git a/klippy/extras/virtual_sdcard.py b/klippy/extras/virtual_sdcard.py index 7ab58654..699add31 100644 --- a/klippy/extras/virtual_sdcard.py +++ b/klippy/extras/virtual_sdcard.py @@ -24,7 +24,6 @@ class VirtualSD: self.work_timer = None # Register commands self.gcode = printer.lookup_object('gcode') - self.gcode.register_command('M21', None) for cmd in ['M20', 'M21', 'M23', 'M24', 'M25', 'M26', 'M27']: self.gcode.register_command(cmd, getattr(self, 'cmd_' + cmd)) for cmd in ['M28', 'M29', 'M30']: diff --git a/klippy/gcode.py b/klippy/gcode.py index c86549ff..ec5439de 100644 --- a/klippy/gcode.py +++ b/klippy/gcode.py @@ -66,8 +66,8 @@ class GCodeCommand: return self.get(name, default, parser=float, minval=minval, maxval=maxval, above=above, below=below) -# Parse and handle G-Code commands -class GCodeParser: +# Parse and dispatch G-Code commands +class GCodeDispatch: error = homing.CommandError def __init__(self, printer): self.printer = printer @@ -76,12 +76,6 @@ class GCodeParser: printer.register_event_handler("klippy:shutdown", self._handle_shutdown) printer.register_event_handler("klippy:disconnect", self._handle_disconnect) - printer.register_event_handler("toolhead:set_position", - self.reset_last_position) - printer.register_event_handler("toolhead:manual_move", - self.reset_last_position) - printer.register_event_handler("extruder:activate_extruder", - self._handle_activate_extruder) # Command handling self.is_printer_ready = False self.mutex = printer.get_reactor().mutex() @@ -90,26 +84,13 @@ class GCodeParser: self.ready_gcode_handlers = {} self.mux_commands = {} self.gcode_help = {} - for cmd in self.all_handlers: + # Register commands needed before config file is loaded + handlers = ['M110', 'M112', 'M115', + 'RESTART', 'FIRMWARE_RESTART', 'ECHO', 'STATUS', 'HELP'] + for cmd in handlers: func = getattr(self, 'cmd_' + cmd) - wnr = getattr(self, 'cmd_' + cmd + '_when_not_ready', False) desc = getattr(self, 'cmd_' + cmd + '_help', None) - self.register_command(cmd, func, wnr, desc) - for a in getattr(self, 'cmd_' + cmd + '_aliases', []): - self.register_command(a, func, wnr) - # G-Code coordinate manipulation - self.absolute_coord = self.absolute_extrude = True - self.base_position = [0.0, 0.0, 0.0, 0.0] - self.last_position = [0.0, 0.0, 0.0, 0.0] - self.homing_position = [0.0, 0.0, 0.0, 0.0] - self.speed = 25. - self.speed_factor = 1. / 60. - self.extrude_factor = 1. - # G-Code state - self.saved_states = {} - self.move_transform = self.move_with_transform = None - self.position_with_transform = (lambda: [0., 0., 0., 0.]) - self.toolhead = None + self.register_command(cmd, func, True, desc) def is_traditional_gcode(self, cmd): # A "traditional" g-code command is a letter and followed by a number try: @@ -156,44 +137,6 @@ class GCodeParser: return dict(self.gcode_help) def register_output_handler(self, cb): self.output_callbacks.append(cb) - def set_move_transform(self, transform, force=False): - if self.move_transform is not None and not force: - raise self.printer.config_error( - "G-Code move transform already specified") - old_transform = self.move_transform - if old_transform is None: - old_transform = self.toolhead - self.move_transform = transform - self.move_with_transform = transform.move - self.position_with_transform = transform.get_position - return old_transform - def _get_gcode_position(self): - p = [lp - bp for lp, bp in zip(self.last_position, self.base_position)] - p[3] /= self.extrude_factor - return p - def _get_gcode_speed(self): - return self.speed / self.speed_factor - def _get_gcode_speed_override(self): - return self.speed_factor * 60. - def get_status(self, eventtime=None): - move_position = self._get_gcode_position() - return { - 'speed_factor': self._get_gcode_speed_override(), - 'speed': self._get_gcode_speed(), - 'extrude_factor': self.extrude_factor, - 'absolute_coordinates': self.absolute_coord, - 'absolute_extrude': self.absolute_extrude, - 'homing_origin': homing.Coord(*self.homing_position), - 'position': homing.Coord(*self.last_position), - 'gcode_position': homing.Coord(*move_position), - } - def dump_state(self): - return ("gcode state: absolute_coord=%s absolute_extrude=%s" - " base_position=%s last_position=%s homing_position=%s" - " speed_factor=%s extrude_factor=%s speed=%s" - % (self.absolute_coord, self.absolute_extrude, - self.base_position, self.last_position, self.homing_position, - self.speed_factor, self.extrude_factor, self.speed)) def _handle_shutdown(self): if not self.is_printer_ready: return @@ -205,18 +148,7 @@ class GCodeParser: def _handle_ready(self): self.is_printer_ready = True self.gcode_handlers = self.ready_gcode_handlers - self.toolhead = self.printer.lookup_object('toolhead') - if self.move_transform is None: - self.move_with_transform = self.toolhead.move - self.position_with_transform = self.toolhead.get_position self._respond_state("Ready") - def _handle_activate_extruder(self): - self.reset_last_position() - self.extrude_factor = 1. - self.base_position[3] = self.last_position[3] - def reset_last_position(self): - if self.is_printer_ready: - self.last_position = self.position_with_transform() # Parse input into commands args_r = re.compile('([A-Z_]+|[A-Z*/])') def _process_commands(self, commands, need_ack=True): @@ -245,7 +177,6 @@ class GCodeParser: handler(gcmd) except self.error as e: self._respond_error(str(e)) - self.reset_last_position() self.printer.send_event("gcode:command_error") if not need_ack: raise @@ -313,6 +244,9 @@ class GCodeParser: # Don't warn about temperature requests when not ready gcmd.ack("T:0") return + if cmd == 'M21': + # Don't warn about sd card init when not ready + return if not self.is_printer_ready: raise gcmd.error(self.printer.get_state_message()[0]) return @@ -343,14 +277,151 @@ class GCodeParser: raise gcmd.error("The value '%s' is not valid for %s" % (key_param, key)) values[key_param](gcmd) - all_handlers = [ - 'G1', 'G28', - 'G20', 'M82', 'M83', 'G90', 'G91', 'G92', 'M114', 'M220', 'M221', - 'SET_GCODE_OFFSET', 'SAVE_GCODE_STATE', 'RESTORE_GCODE_STATE', - 'M112', 'M115', 'IGNORE', 'GET_POSITION', - 'RESTART', 'FIRMWARE_RESTART', 'ECHO', 'STATUS', 'HELP'] + # Low-level G-Code commands that are needed before the config file is loaded + def cmd_M110(self, gcmd): + # Set Current Line Number + pass + def cmd_M112(self, gcmd): + # Emergency Stop + self.printer.invoke_shutdown("Shutdown due to M112 command") + def cmd_M115(self, gcmd): + # Get Firmware Version and Capabilities + software_version = self.printer.get_start_args().get('software_version') + kw = {"FIRMWARE_NAME": "Klipper", "FIRMWARE_VERSION": software_version} + gcmd.ack(" ".join(["%s:%s" % (k, v) for k, v in kw.items()])) + def request_restart(self, result): + if self.is_printer_ready: + toolhead = self.printer.lookup_object('toolhead') + print_time = toolhead.get_last_move_time() + if result == 'exit': + logging.info("Exiting (print time %.3fs)" % (print_time,)) + self.printer.send_event("gcode:request_restart", print_time) + toolhead.dwell(0.500) + toolhead.wait_moves() + self.printer.request_exit(result) + cmd_RESTART_help = "Reload config file and restart host software" + def cmd_RESTART(self, gcmd): + self.request_restart('restart') + cmd_FIRMWARE_RESTART_help = "Restart firmware, host, and reload config" + def cmd_FIRMWARE_RESTART(self, gcmd): + self.request_restart('firmware_restart') + def cmd_ECHO(self, gcmd): + gcmd.respond_info(gcmd.get_commandline(), log=False) + cmd_STATUS_help = "Report the printer status" + def cmd_STATUS(self, gcmd): + if self.is_printer_ready: + self._respond_state("Ready") + return + msg = self.printer.get_state_message()[0] + msg = msg.rstrip() + "\nKlipper state: Not ready" + raise gcmd.error(msg) + def cmd_HELP(self, gcmd): + cmdhelp = [] + if not self.is_printer_ready: + cmdhelp.append("Printer is not ready - not all commands available.") + cmdhelp.append("Available extended commands:") + for cmd in sorted(self.gcode_handlers): + if cmd in self.gcode_help: + cmdhelp.append("%-10s: %s" % (cmd, self.gcode_help[cmd])) + gcmd.respond_info("\n".join(cmdhelp), log=False) + +# G1 movement commands (and associated coordinate manipulation) +class GCodeMove: + def __init__(self, printer): + self.printer = printer + printer.register_event_handler("klippy:ready", self._handle_ready) + printer.register_event_handler("klippy:shutdown", self._handle_shutdown) + printer.register_event_handler("toolhead:set_position", + self.reset_last_position) + printer.register_event_handler("toolhead:manual_move", + self.reset_last_position) + printer.register_event_handler("gcode:command_error", + self.reset_last_position) + printer.register_event_handler("extruder:activate_extruder", + self._handle_activate_extruder) + self.is_printer_ready = False + # Register g-code commands + gcode = self.printer.lookup_object('gcode') + handlers = [ + 'G1', 'G28', 'G20', 'G21', + 'M82', 'M83', 'G90', 'G91', 'G92', 'M220', 'M221', + 'SET_GCODE_OFFSET', 'SAVE_GCODE_STATE', 'RESTORE_GCODE_STATE', + ] + for cmd in handlers: + func = getattr(self, 'cmd_' + cmd) + desc = getattr(self, 'cmd_' + cmd + '_help', None) + gcode.register_command(cmd, func, False, desc) + gcode.register_command('G0', self.cmd_G1) + gcode.register_command('M114', self.cmd_M114, True) + gcode.register_command('GET_POSITION', self.cmd_GET_POSITION, True) + # G-Code coordinate manipulation + self.absolute_coord = self.absolute_extrude = True + self.base_position = [0.0, 0.0, 0.0, 0.0] + self.last_position = [0.0, 0.0, 0.0, 0.0] + self.homing_position = [0.0, 0.0, 0.0, 0.0] + self.speed = 25. + self.speed_factor = 1. / 60. + self.extrude_factor = 1. + # G-Code state + self.saved_states = {} + self.move_transform = self.move_with_transform = None + self.position_with_transform = (lambda: [0., 0., 0., 0.]) + def _handle_ready(self): + self.is_printer_ready = True + if self.move_transform is None: + toolhead = self.printer.lookup_object('toolhead') + self.move_with_transform = toolhead.move + self.position_with_transform = toolhead.get_position + def _handle_shutdown(self): + if not self.is_printer_ready: + return + self.is_printer_ready = False + logging.info("gcode state: absolute_coord=%s absolute_extrude=%s" + " base_position=%s last_position=%s homing_position=%s" + " speed_factor=%s extrude_factor=%s speed=%s", + self.absolute_coord, self.absolute_extrude, + self.base_position, self.last_position, + self.homing_position, self.speed_factor, + self.extrude_factor, self.speed) + def _handle_activate_extruder(self): + self.reset_last_position() + self.extrude_factor = 1. + self.base_position[3] = self.last_position[3] + def set_move_transform(self, transform, force=False): + if self.move_transform is not None and not force: + raise self.printer.config_error( + "G-Code move transform already specified") + old_transform = self.move_transform + if old_transform is None: + old_transform = self.printer.lookup_object('toolhead', None) + self.move_transform = transform + self.move_with_transform = transform.move + self.position_with_transform = transform.get_position + return old_transform + def _get_gcode_position(self): + p = [lp - bp for lp, bp in zip(self.last_position, self.base_position)] + p[3] /= self.extrude_factor + return p + def _get_gcode_speed(self): + return self.speed / self.speed_factor + def _get_gcode_speed_override(self): + return self.speed_factor * 60. + def get_status(self, eventtime=None): + move_position = self._get_gcode_position() + return { + 'speed_factor': self._get_gcode_speed_override(), + 'speed': self._get_gcode_speed(), + 'extrude_factor': self.extrude_factor, + 'absolute_coordinates': self.absolute_coord, + 'absolute_extrude': self.absolute_extrude, + 'homing_origin': homing.Coord(*self.homing_position), + 'position': homing.Coord(*self.last_position), + 'gcode_position': homing.Coord(*move_position), + } + def reset_last_position(self): + if self.is_printer_ready: + self.last_position = self.position_with_transform() # G-Code movement commands - cmd_G1_aliases = ['G0'] def cmd_G1(self, gcmd): # Move params = gcmd._params @@ -391,8 +462,6 @@ class GCodeParser: if not axes: axes = [0, 1, 2] homing_state = homing.Homing(self.printer) - if self.is_fileinput: - homing_state.set_no_verify_retract() homing_state.home_axes(axes) for axis in homing_state.get_axes(): self.base_position[axis] = self.homing_position[axis] @@ -400,6 +469,9 @@ class GCodeParser: def cmd_G20(self, gcmd): # Set units to inches raise gcmd.error('Machine does not support G20 (inches) command') + def cmd_G21(self, gcmd): + # Set units to millimeters + pass def cmd_M82(self, gcmd): # Use absolute distances for extrusion self.absolute_extrude = True @@ -422,7 +494,6 @@ class GCodeParser: self.base_position[i] = self.last_position[i] - offset if offsets == [None, None, None, None]: self.base_position = list(self.last_position) - cmd_M114_when_not_ready = True def cmd_M114(self, gcmd): # Get Current Position p = self._get_gcode_position() @@ -493,28 +564,11 @@ class GCodeParser: speed = gcmd.get_float('MOVE_SPEED', self.speed, above=0.) self.last_position[:3] = state['last_position'][:3] self.move_with_transform(self.last_position, speed) - # G-Code miscellaneous commands - cmd_M112_when_not_ready = True - def cmd_M112(self, gcmd): - # Emergency Stop - self.printer.invoke_shutdown("Shutdown due to M112 command") - cmd_M115_when_not_ready = True - def cmd_M115(self, gcmd): - # Get Firmware Version and Capabilities - software_version = self.printer.get_start_args().get('software_version') - kw = {"FIRMWARE_NAME": "Klipper", "FIRMWARE_VERSION": software_version} - gcmd.ack(" ".join(["%s:%s" % (k, v) for k, v in kw.items()])) - cmd_IGNORE_when_not_ready = True - cmd_IGNORE_aliases = ["G21", "M110", "M21"] - def cmd_IGNORE(self, gcmd): - # Commands that are just silently accepted - pass - cmd_GET_POSITION_when_not_ready = True def cmd_GET_POSITION(self, gcmd): - if self.toolhead is None: - self.cmd_default(gcmd) - return - kin = self.toolhead.get_kinematics() + toolhead = self.printer.lookup_object('toolhead', None) + if toolhead is None: + raise gcmd.error("Printer not ready") + kin = toolhead.get_kinematics() steppers = kin.get_steppers() mcu_pos = " ".join(["%s:%d" % (s.get_name(), s.get_mcu_position()) for s in steppers]) @@ -525,7 +579,7 @@ class GCodeParser: kin_pos = " ".join(["%s:%.6f" % (a, v) for a, v in zip("XYZ", kin.calc_tag_position())]) toolhead_pos = " ".join(["%s:%.6f" % (a, v) for a, v in zip( - "XYZE", self.toolhead.get_position())]) + "XYZE", toolhead.get_position())]) gcode_pos = " ".join(["%s:%.6f" % (a, v) for a, v in zip("XYZE", self.last_position)]) base_pos = " ".join(["%s:%.6f" % (a, v) @@ -541,45 +595,6 @@ class GCodeParser: "gcode homing: %s" % (mcu_pos, stepper_pos, kin_pos, toolhead_pos, gcode_pos, base_pos, homing_pos)) - def request_restart(self, result): - if self.is_printer_ready: - print_time = self.toolhead.get_last_move_time() - if result == 'exit': - logging.info("Exiting (print time %.3fs)" % (print_time,)) - self.printer.send_event("gcode:request_restart", print_time) - self.toolhead.dwell(0.500) - self.toolhead.wait_moves() - self.printer.request_exit(result) - cmd_RESTART_when_not_ready = True - cmd_RESTART_help = "Reload config file and restart host software" - def cmd_RESTART(self, gcmd): - self.request_restart('restart') - cmd_FIRMWARE_RESTART_when_not_ready = True - cmd_FIRMWARE_RESTART_help = "Restart firmware, host, and reload config" - def cmd_FIRMWARE_RESTART(self, gcmd): - self.request_restart('firmware_restart') - cmd_ECHO_when_not_ready = True - def cmd_ECHO(self, gcmd): - gcmd.respond_info(gcmd.get_commandline(), log=False) - cmd_STATUS_when_not_ready = True - cmd_STATUS_help = "Report the printer status" - def cmd_STATUS(self, gcmd): - if self.is_printer_ready: - self._respond_state("Ready") - return - msg = self.printer.get_state_message()[0] - msg = msg.rstrip() + "\nKlipper state: Not ready" - raise gcmd.error(msg) - cmd_HELP_when_not_ready = True - def cmd_HELP(self, gcmd): - cmdhelp = [] - if not self.is_printer_ready: - cmdhelp.append("Printer is not ready - not all commands available.") - cmdhelp.append("Available extended commands:") - for cmd in sorted(self.gcode_handlers): - if cmd in self.gcode_help: - cmdhelp.append("%-10s: %s" % (cmd, self.gcode_help[cmd])) - gcmd.respond_info("\n".join(cmdhelp), log=False) # Support reading gcode from a pseudo-tty interface class GCodeIO: @@ -611,11 +626,9 @@ class GCodeIO: self._process_data) def _dump_debug(self): out = [] - out.append("Dumping gcode input %d blocks" % ( - len(self.input_log),)) + out.append("Dumping gcode input %d blocks" % (len(self.input_log),)) for eventtime, data in self.input_log: out.append("Read %f: %s" % (eventtime, repr(data))) - out.append(self.gcode.dump_state()) logging.info("\n".join(out)) def _handle_shutdown(self): if not self.is_printer_ready: @@ -682,5 +695,6 @@ class GCodeIO: return False, "gcodein=%d" % (self.bytes_read,) def add_early_printer_objects(printer): - printer.add_object('gcode', GCodeParser(printer)) + printer.add_object('gcode', GCodeDispatch(printer)) + printer.add_object('gcode_move', GCodeMove(printer)) printer.add_object('gcode_io', GCodeIO(printer)) diff --git a/klippy/homing.py b/klippy/homing.py index 66af8aca..cc808cc1 100644 --- a/klippy/homing.py +++ b/klippy/homing.py @@ -15,8 +15,8 @@ class Homing: self.toolhead = printer.lookup_object('toolhead') self.changed_axes = [] self.verify_retract = True - def set_no_verify_retract(self): - self.verify_retract = False + if self.printer.get_start_args().get("debuginput"): + self.verify_retract = False def set_axes(self, axes): self.changed_axes = axes def get_axes(self): diff --git a/test/klippy/macros.cfg b/test/klippy/macros.cfg index e4c9ba16..5604b507 100644 --- a/test/klippy/macros.cfg +++ b/test/klippy/macros.cfg @@ -73,7 +73,7 @@ gcode: [gcode_macro TEST_expression] gcode: - {% if printer.gcode.gcode_position.x != 0.0 %} + {% if printer.gcode_move.gcode_position.x != 0.0 %} M112 {% else %} { action_respond_info("TEST_expression") } @@ -108,7 +108,7 @@ gcode: [gcode_macro TEST_in] gcode: - {% if "abc" in printer or "gcode" not in printer %} + {% if "abc" in printer or "toolhead" not in printer %} M112 {% endif %}