From 54683c95352fabdddfc0e824a5b6e7f368760c25 Mon Sep 17 00:00:00 2001 From: lorf Date: Sun, 3 Feb 2019 07:46:27 +0700 Subject: [PATCH] tmc2208: Decode register fields in DUMP_TMC (#1156) Report values of TMC2208 register fields in DUMP_TMC command to help in tuning and diagnostics. This also adds functions to refer to register fields by name for TMC drivers and register mappings for TMC2208. Signed-off-by: Kevin O'Connor Signed-off-by: Dmitry Frolov --- klippy/extras/tmc2130.py | 36 ++++++++- klippy/extras/tmc2208.py | 155 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 189 insertions(+), 2 deletions(-) diff --git a/klippy/extras/tmc2130.py b/klippy/extras/tmc2130.py index 28d0f2dc..da089e5a 100644 --- a/klippy/extras/tmc2130.py +++ b/klippy/extras/tmc2130.py @@ -24,6 +24,40 @@ ReadRegisters = [ "CHOPCONF", "DRV_STATUS", "PWM_SCALE", "LOST_STEPS", ] +Fields = {} + + +###################################################################### +# Field helpers +###################################################################### + +# Return the position of the first bit set in a mask +def ffs(mask): + return (mask & -mask).bit_length() - 1 + +# Provide a string description of a register +def pretty_format(all_fields, reg_name, value): + fields = [ " %s=%d" % (field_name, (value & mask) >> ffs(mask)) + for field_name, mask in sorted(all_fields.get( + reg_name, {}).items(), key = lambda f: f[1]) + if value & mask ] + return "%-15s %08x%s" % (reg_name + ":", value, "".join(fields)) + +# Returns value of the register field +def get_field(all_fields, reg_name, field_name, reg_value): + mask = all_fields.get(reg_name, {})[field_name] + return (reg_value & mask) >> ffs(mask) + +# Returns register value with field bits filled with supplied field value +def set_field(all_fields, reg_name, field_name, reg_value, field_value): + mask = all_fields.get(reg_name, {})[field_name] + return (reg_value & ~mask) | ((field_value << ffs(mask)) & mask) + + +###################################################################### +# TMC2130 printer object +###################################################################### + class TMC2130: def __init__(self, config): self.printer = config.get_printer() @@ -126,7 +160,7 @@ class TMC2130: logging.info("DUMP_TMC %s", self.name) for reg_name in ReadRegisters: val = self.get_register(reg_name) - msg = "%-15s %08x" % (reg_name + ":", val) + msg = pretty_format(Fields, reg_name, val) logging.info(msg) gcode.respond_info(msg) diff --git a/klippy/extras/tmc2208.py b/klippy/extras/tmc2208.py index 96d42a42..207864c6 100644 --- a/klippy/extras/tmc2208.py +++ b/klippy/extras/tmc2208.py @@ -4,6 +4,7 @@ # # This file may be distributed under the terms of the GNU GPLv3 license. import math, logging, collections +import tmc2130 TMC_FREQUENCY=12000000. GCONF_PDN_DISABLE = 1<<6 @@ -24,6 +25,151 @@ ReadRegisters = [ "PWMCONF", "PWM_SCALE", "PWM_AUTO" ] +Fields = {} + +Fields["GCONF"] = { + "I_scale_analog": 0x01, + "internal_Rsense": 0x01 << 1, + "en_spreadCycle": 0x01 << 2, + "shaft": 0x01 << 3, + "index_otpw": 0x01 << 4, + "index_step": 0x01 << 5, + "pdn_disable": 0x01 << 6, + "mstep_reg_select": 0x01 << 7, + "multistep_filt": 0x01 << 8, + "test_mode": 0x01 << 9 +} +Fields["GSTAT"] = { + "reset": 0x01, + "drv_err": 0x01 << 1, + "uv_cp": 0x01 << 2 +} +Fields["IFCNT"] = { + "IFCNT": 0xff +} +Fields["SLAVECONF"] = { + "SENDDELAY": 0x0f << 8 +} +Fields["OTP_PROG"] = { + "OTPBIT": 0x07, + "OTPBYTE": 0x03 << 4, + "OTPMAGIC": 0xff << 8 +} +Fields["OTP_READ"] = { + "OTP_FCLKTRIM": 0x1f, + "otp_OTTRIM": 0x01 << 5, + "otp_internalRsense": 0x01 << 6, + "otp_TBL": 0x01 << 7, + "OTP_PWM_GRAD": 0x0f << 8, + "otp_pwm_autograd": 0x01 << 12, + "OTP_TPWMTHRS": 0x07 << 13, + "otp_PWM_OFS": 0x01 << 16, + "otp_PWM_REG": 0x01 << 17, + "otp_PWM_FREQ": 0x01 << 18, + "OTP_IHOLDDELAY": 0x03 << 19, + "OTP_IHOLD": 0x03 << 21, + "otp_en_spreadCycle": 0x01 << 23 +} +# IOIN mapping depends on the driver type (SEL_A field) +# TMC222x (SEL_A == 0) +Fields["IOIN@TMC222x"] = { + "PDN_UART": 0x01 << 1, + "SPREAD": 0x01 << 2, + "DIR": 0x01 << 3, + "ENN": 0x01 << 4, + "STEP": 0x01 << 5, + "MS1": 0x01 << 6, + "MS2": 0x01 << 7, + "SEL_A": 0x01 << 8, + "VERSION": 0xff << 24 +} +# TMC220x (SEL_A == 1) +Fields["IOIN@TMC220x"] = { + "ENN": 0x01, + "MS1": 0x01 << 2, + "MS2": 0x01 << 3, + "DIAG": 0x01 << 4, + "PDN_UART": 0x01 << 6, + "STEP": 0x01 << 7, + "SEL_A": 0x01 << 8, + "DIR": 0x01 << 9, + "VERSION": 0xff << 24, +} +Fields["FACTORY_CONF"] = { + "FCLKTRIM": 0x1f, + "OTTRIM": 0x03 << 8 +} +Fields["IHOLD_IRUN"] = { + "IHOLD": 0x1f, + "IRUN": 0x1f << 8, + "IHOLDDELAY": 0x0f << 16 +} +Fields["TPOWERDOWN"] = { + "TPOWERDOWN": 0xff +} +Fields["TSTEP"] = { + "TSTEP": 0xfffff +} +Fields["TPWMTHRS"] = { + "TPWMTHRS": 0xfffff +} +Fields["VACTUAL"] = { + "VACTUAL": 0xffffff +} +Fields["MSCNT"] = { + "MSCNT": 0x3ff +} +Fields["MSCURACT"] = { + "CUR_A": 0x1ff, + "CUR_B": 0x1ff << 16 +} +Fields["CHOPCONF"] = { + "toff": 0x0f, + "hstrt": 0x07 << 4, + "hend": 0x0f << 7, + "TBL": 0x03 << 15, + "vsense": 0x01 << 17, + "MRES": 0x0f << 24, + "intpol": 0x01 << 28, + "dedge": 0x01 << 29, + "diss2g": 0x01 << 30, + "diss2vs": 0x01 << 31 +} +Fields["DRV_STATUS"] = { + "otpw": 0x01, + "ot": 0x01 << 1, + "s2ga": 0x01 << 2, + "s2gb": 0x01 << 3, + "s2vsa": 0x01 << 4, + "s2vsb": 0x01 << 5, + "ola": 0x01 << 6, + "olb": 0x01 << 7, + "t120": 0x01 << 8, + "t143": 0x01 << 9, + "t150": 0x01 << 10, + "t157": 0x01 << 11, + "CS_ACTUAL": 0x1f << 16, + "stealth": 0x01 << 30, + "stst": 0x01 << 31 +} +Fields["PWMCONF"] = { + "PWM_OFS": 0xff, + "PWM_GRAD": 0xff << 8, + "pwm_freq": 0x03 << 16, + "pwm_autoscale": 0x01 << 18, + "pwm_autograd": 0x01 << 19, + "freewheel": 0x03 << 20, + "PWM_REG": 0xf << 24, + "PWM_LIM": 0xf << 28 +} +Fields["PWM_SCALE"] = { + "PWM_SCALE_SUM": 0xff, + "PWM_SCALE_AUTO": 0x1ff << 16 +} +Fields["PWM_AUTO"] = { + "PWM_OFS_AUTO": 0xff, + "PWM_GRAD_AUTO": 0xff << 16 +} ###################################################################### # TMC2208 communication @@ -199,6 +345,8 @@ class TMC2208: def get_register(self, reg_name): reg = Registers[reg_name] msg = encode_tmc2208_read(0xf5, 0x00, reg) + if self.printer.get_start_args().get('debugoutput') is not None: + return 0 for retry in range(5): params = self.tmcuart_send_cmd.send_with_response( [self.oid, msg, 10], 'tmcuart_response', self.oid) @@ -236,7 +384,12 @@ class TMC2208: val = self.get_register(reg_name) except self.printer.config_error as e: raise gcode.error(str(e)) - msg = "%-15s %08x" % (reg_name + ":", val) + # IOIN has different mappings depending on the driver type + # (SEL_A field of IOIN reg) + if reg_name is "IOIN": + drv_type = tmc2130.get_field(Fields, "IOIN@TMC222x", "SEL_A", val) + reg_name = "IOIN@TMC220x" if drv_type else "IOIN@TMC222x" + msg = tmc2130.pretty_format(Fields, reg_name, val) logging.info(msg) gcode.respond_info(msg)