tmc2130: Use FieldHelper() to set/get driver fields
Use the field helper to simplify the bit manipulation in the driver. This also enables the extended DUMP_TMC output. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
This commit is contained in:
parent
328bd89fc1
commit
5bc47d9416
|
@ -3,12 +3,10 @@
|
|||
# Copyright (C) 2018 Kevin O'Connor <kevin@koconnor.net>
|
||||
#
|
||||
# This file may be distributed under the terms of the GNU GPLv3 license.
|
||||
import math, logging
|
||||
import math, logging, collections
|
||||
import bus
|
||||
|
||||
TMC_FREQUENCY=13200000.
|
||||
GCONF_EN_PWM_MODE=1<<2
|
||||
GCONF_DIAG1_STALL=1<<8
|
||||
|
||||
Registers = {
|
||||
"GCONF": 0x00, "GSTAT": 0x01, "IOIN": 0x04, "IHOLD_IRUN": 0x10,
|
||||
|
@ -25,6 +23,69 @@ ReadRegisters = [
|
|||
]
|
||||
|
||||
Fields = {}
|
||||
Fields["GCONF"] = {
|
||||
"I_scale_analog": 1<<0, "internal_Rsense": 1<<1, "en_pwm_mode": 1<<2,
|
||||
"enc_commutation": 1<<3, "shaft": 1<<4, "diag0_error": 1<<5,
|
||||
"diag0_otpw": 1<<6, "diag0_stall": 1<<7, "diag1_stall": 1<<8,
|
||||
"diag1_index": 1<<9, "diag1_onstate": 1<<10, "diag1_steps_skipped": 1<<11,
|
||||
"diag0_int_pushpull": 1<<12, "diag1_pushpull": 1<<13,
|
||||
"small_hysteresis": 1<<14, "stop_enable": 1<<15, "direct_mode": 1<<16,
|
||||
"test_mode": 1<<17
|
||||
}
|
||||
Fields["GSTAT"] = { "reset": 1<<0, "drv_err": 1<<1, "uv_cp": 1<<2 }
|
||||
Fields["IOIN"] = {
|
||||
"STEP": 1<<0, "DIR": 1<<1, "DCEN_CFG4": 1<<2, "DCIN_CFG5": 1<<3,
|
||||
"DRV_ENN_CFG6": 1<<4, "DCO": 1<<5, "VERSION": 0xff << 24
|
||||
}
|
||||
Fields["IHOLD_IRUN"] = {
|
||||
"IHOLD": 0x1f << 0, "IRUN": 0x1f << 8, "IHOLDDELAY": 0x0f << 16
|
||||
}
|
||||
Fields["TPOWERDOWN"] = { "TPOWERDOWN": 0xff }
|
||||
Fields["TSTEP"] = { "TSTEP": 0xfffff }
|
||||
Fields["TPWMTHRS"] = { "TPWMTHRS": 0xfffff }
|
||||
Fields["TCOOLTHRS"] = { "TCOOLTHRS": 0xfffff }
|
||||
Fields["THIGH"] = { "THIGH": 0xfffff }
|
||||
Fields["MSCNT"] = { "MSCNT": 0x3ff }
|
||||
Fields["MSCURACT"] = { "CUR_A": 0x1ff, "CUR_B": 0x1ff << 16 }
|
||||
Fields["CHOPCONF"] = {
|
||||
"toff": 0x0f, "hstrt": 0x07 << 4, "hend": 0x0f << 7, "fd3": 1<<11,
|
||||
"disfdcc": 1<<12, "rndtf": 1<<13, "chm": 1<<14, "TBL": 0x03 << 15,
|
||||
"vsense": 1<<17, "vhighfs": 1<<18, "vhighchm": 1<<19, "sync": 0x0f << 20,
|
||||
"MRES": 0x0f << 24, "intpol": 1<<28, "dedge": 1<<29, "diss2g": 1<<30
|
||||
}
|
||||
Fields["COOLCONF"] = {
|
||||
"semin": 0x0f, "seup": 0x03 << 5, "semax": 0x0f << 8, "sedn": 0x03 << 13,
|
||||
"seimin": 1<<15, "sgt": 0x7f << 16, "sfilt": 1<<24
|
||||
}
|
||||
Fields["DRV_STATUS"] = {
|
||||
"SG_RESULT": 0x3ff, "fsactive": 1<<15, "CS_ACTUAL": 0x1f << 16,
|
||||
"stallGuard": 1<<24, "ot": 1<<25, "otpw": 1<<26, "s2ga": 1<<27,
|
||||
"s2gb": 1<<28, "ola": 1<<29, "olb": 1<<30, "stst": 1<<31
|
||||
}
|
||||
Fields["PWMCONF"] = {
|
||||
"PWM_AMPL": 0xff, "PWM_GRAD": 0xff << 8, "pwm_freq": 0x03 << 16,
|
||||
"pwm_autoscale": 1<<18, "pwm_symmetric": 1<<19, "freewheel": 0x03 << 20
|
||||
}
|
||||
Fields["PWM_SCALE"] = { "PWM_SCALE": 0xff }
|
||||
Fields["LOST_STEPS"] = { "LOST_STEPS": 0xfffff }
|
||||
|
||||
FieldFormatters = {
|
||||
"I_scale_analog": (lambda v: "1(ExtVREF)" if v else ""),
|
||||
"shaft": (lambda v: "1(Reverse)" if v else ""),
|
||||
"drv_err": (lambda v: "1(ErrorShutdown!)" if v else ""),
|
||||
"uv_cp": (lambda v: "1(Undervoltage!)" if v else ""),
|
||||
"VERSION": (lambda v: "%#x" % v),
|
||||
"CUR_A": (lambda v: decode_signed_int(v, 9)),
|
||||
"CUR_B": (lambda v: decode_signed_int(v, 9)),
|
||||
"MRES": (lambda v: "%d(%dusteps)" % (v, 0x100 >> v)),
|
||||
"otpw": (lambda v: "1(OvertempWarning!)" if v else ""),
|
||||
"ot": (lambda v: "1(OvertempError!)" if v else ""),
|
||||
"s2ga": (lambda v: "1(ShortToGND_A!)" if v else ""),
|
||||
"s2gb": (lambda v: "1(ShortToGND_B!)" if v else ""),
|
||||
"ola": (lambda v: "1(OpenLoad_A!)" if v else ""),
|
||||
"olb": (lambda v: "1(OpenLoad_B!)" if v else ""),
|
||||
"sgt": (lambda v: decode_signed_int(v, 7)),
|
||||
}
|
||||
|
||||
|
||||
######################################################################
|
||||
|
@ -155,37 +216,35 @@ class TMC2130:
|
|||
gcode.register_mux_command(
|
||||
"DUMP_TMC", "STEPPER", self.name,
|
||||
self.cmd_DUMP_TMC, desc=self.cmd_DUMP_TMC_help)
|
||||
# Get config for initial driver settings
|
||||
self.fields = FieldHelper(Fields)
|
||||
interpolate = config.getboolean('interpolate', True)
|
||||
self.mres, en_pwm, sc_threshold = get_config_stealthchop(
|
||||
config, TMC_FREQUENCY)
|
||||
iholddelay = config.getint('driver_IHOLDDELAY', 8, minval=0, maxval=15)
|
||||
tpowerdown = config.getint('driver_TPOWERDOWN', 0, minval=0, maxval=255)
|
||||
blank_time_select = config.getint('driver_BLANK_TIME_SELECT', 1,
|
||||
minval=0, maxval=3)
|
||||
toff = config.getint('driver_TOFF', 4, minval=1, maxval=15)
|
||||
hend = config.getint('driver_HEND', 7, minval=0, maxval=15)
|
||||
hstrt = config.getint('driver_HSTRT', 0, minval=0, maxval=7)
|
||||
sgt = config.getint('driver_SGT', 0, minval=-64, maxval=63) & 0x7f
|
||||
pwm_scale = config.getboolean('driver_PWM_AUTOSCALE', True)
|
||||
pwm_freq = config.getint('driver_PWM_FREQ', 1, minval=0, maxval=3)
|
||||
pwm_grad = config.getint('driver_PWM_GRAD', 4, minval=0, maxval=255)
|
||||
pwm_ampl = config.getint('driver_PWM_AMPL', 128, minval=0, maxval=255)
|
||||
# Setup basic register values
|
||||
self.regs = collections.OrderedDict()
|
||||
self.fields = FieldHelper(Fields, FieldFormatters, self.regs)
|
||||
vsense, irun, ihold = get_config_current(config)
|
||||
# Configure registers
|
||||
self.reg_GCONF = en_pwm << 2
|
||||
self.set_register("GCONF", self.reg_GCONF)
|
||||
self.set_register("CHOPCONF", (
|
||||
toff | (hstrt << 4) | (hend << 7) | (blank_time_select << 15)
|
||||
| (vsense << 17) | (self.mres << 24) | (interpolate << 28)))
|
||||
self.set_register("IHOLD_IRUN",
|
||||
ihold | (irun << 8) | (iholddelay << 16))
|
||||
self.set_register("TPOWERDOWN", tpowerdown)
|
||||
self.set_register("TPWMTHRS", sc_threshold)
|
||||
self.set_register("COOLCONF", sgt << 16)
|
||||
self.set_register("PWMCONF", (
|
||||
pwm_ampl | (pwm_grad << 8) | (pwm_freq << 16) | (pwm_scale << 18)))
|
||||
self.fields.set_field("vsense", vsense)
|
||||
self.fields.set_field("IHOLD", ihold)
|
||||
self.fields.set_field("IRUN", irun)
|
||||
mres, en_pwm, thresh = get_config_stealthchop(config, TMC_FREQUENCY)
|
||||
self.fields.set_field("MRES", mres)
|
||||
self.fields.set_field("en_pwm_mode", en_pwm)
|
||||
self.fields.set_field("TPWMTHRS", thresh)
|
||||
# Allow other registers to be set from the config
|
||||
set_config_field = self.fields.set_config_field
|
||||
set_config_field(config, "toff", 4)
|
||||
set_config_field(config, "hstrt", 0)
|
||||
set_config_field(config, "hend", 7)
|
||||
set_config_field(config, "TBL", 1, "driver_BLANK_TIME_SELECT")
|
||||
set_config_field(config, "intpol", True, "interpolate")
|
||||
set_config_field(config, "IHOLDDELAY", 8)
|
||||
set_config_field(config, "TPOWERDOWN", 0)
|
||||
set_config_field(config, "PWM_AMPL", 128)
|
||||
set_config_field(config, "PWM_GRAD", 4)
|
||||
set_config_field(config, "pwm_freq", 1)
|
||||
set_config_field(config, "pwm_autoscale", True)
|
||||
sgt = config.getint('driver_SGT', 0, minval=-64, maxval=63) & 0x7f
|
||||
self.fields.set_field("sgt", sgt)
|
||||
# Send registers
|
||||
for reg_name, val in self.regs.items():
|
||||
self.set_register(reg_name, val)
|
||||
def setup_pin(self, pin_type, pin_params):
|
||||
if pin_type != 'endstop' or pin_params['pin'] != 'virtual_endstop':
|
||||
raise pins.error("tmc2130 virtual endstop only useful as endstop")
|
||||
|
@ -204,9 +263,10 @@ class TMC2130:
|
|||
(val >> 8) & 0xff, val & 0xff]
|
||||
self.spi.spi_send(data)
|
||||
def get_microsteps(self):
|
||||
return 256 >> self.mres
|
||||
return 256 >> self.fields.get_field("MRES")
|
||||
def get_phase(self):
|
||||
return (self.get_register("MSCNT") & 0x3ff) >> self.mres
|
||||
mscnt = self.fields.get_field("MSCNT", self.get_register("MSCNT"))
|
||||
return mscnt >> self.fields.get_field("MRES")
|
||||
cmd_DUMP_TMC_help = "Read and display TMC stepper driver registers"
|
||||
def cmd_DUMP_TMC(self, params):
|
||||
self.printer.lookup_object('toolhead').get_last_move_time()
|
||||
|
@ -228,6 +288,7 @@ class TMC2130VirtualEndstop:
|
|||
self.mcu_endstop = ppins.setup_pin('endstop', tmc2130.diag1_pin)
|
||||
if self.mcu_endstop.get_mcu() is not tmc2130.spi.get_mcu():
|
||||
raise pins.error("tmc2130 virtual endstop must be on same mcu")
|
||||
self.en_pwm = tmc2130.fields.get_field("en_pwm_mode")
|
||||
# Wrappers
|
||||
self.get_mcu = self.mcu_endstop.get_mcu
|
||||
self.add_stepper = self.mcu_endstop.add_stepper
|
||||
|
@ -238,14 +299,15 @@ class TMC2130VirtualEndstop:
|
|||
self.query_endstop_wait = self.mcu_endstop.query_endstop_wait
|
||||
self.TimeoutError = self.mcu_endstop.TimeoutError
|
||||
def home_prepare(self):
|
||||
gconf = self.tmc2130.reg_GCONF
|
||||
gconf &= ~GCONF_EN_PWM_MODE
|
||||
gconf |= GCONF_DIAG1_STALL
|
||||
self.tmc2130.set_register("GCONF", gconf)
|
||||
self.tmc2130.fields.set_field("en_pwm_mode", 0)
|
||||
self.tmc2130.fields.set_field("diag1_stall", 1)
|
||||
self.tmc2130.set_register("GCONF", self.tmc2130.regs['GCONF'])
|
||||
self.tmc2130.set_register("TCOOLTHRS", 0xfffff)
|
||||
self.mcu_endstop.home_prepare()
|
||||
def home_finalize(self):
|
||||
self.tmc2130.set_register("GCONF", self.tmc2130.reg_GCONF)
|
||||
self.tmc2130.fields.set_field("en_pwm_mode", self.en_pwm)
|
||||
self.tmc2130.fields.set_field("diag1_stall", 0)
|
||||
self.tmc2130.set_register("GCONF", self.tmc2130.regs['GCONF'])
|
||||
self.tmc2130.set_register("TCOOLTHRS", 0)
|
||||
self.mcu_endstop.home_finalize()
|
||||
|
||||
|
|
|
@ -168,26 +168,13 @@ Fields["PWM_AUTO"] = {
|
|||
"PWM_GRAD_AUTO": 0xff << 16
|
||||
}
|
||||
|
||||
FieldFormatters = {
|
||||
"I_scale_analog": (lambda v: "1(ExtVREF)" if v else ""),
|
||||
"shaft": (lambda v: "1(Reverse)" if v else ""),
|
||||
"drv_err": (lambda v: "1(ErrorShutdown!)" if v else ""),
|
||||
"uv_cp": (lambda v: "1(Undervoltage!)" if v else ""),
|
||||
FieldFormatters = dict(tmc2130.FieldFormatters)
|
||||
FieldFormatters.update({
|
||||
"SEL_A": (lambda v: "%d(%s)" % (v, ["TMC222x", "TMC220x"][v])),
|
||||
"VERSION": (lambda v: "%#x" % v),
|
||||
"CUR_A": (lambda v: str(tmc2130.decode_signed_int(v, 9))),
|
||||
"CUR_B": (lambda v: str(tmc2130.decode_signed_int(v, 9))),
|
||||
"MRES": (lambda v: "%d(%dusteps)" % (v, 0x100 >> v)),
|
||||
"otpw": (lambda v: "1(OvertempWarning!)" if v else ""),
|
||||
"ot": (lambda v: "1(OvertempError!)" if v else ""),
|
||||
"s2ga": (lambda v: "1(ShortToGND_A!)" if v else ""),
|
||||
"s2gb": (lambda v: "1(ShortToGND_B!)" if v else ""),
|
||||
"s2vsa": (lambda v: "1(LowSideShort_A!)" if v else ""),
|
||||
"s2vsb": (lambda v: "1(LowSideShort_B!)" if v else ""),
|
||||
"ola": (lambda v: "1(OpenLoad_A!)" if v else ""),
|
||||
"olb": (lambda v: "1(OpenLoad_B!)" if v else ""),
|
||||
"PWM_SCALE_AUTO": (lambda v: str(tmc2130.decode_signed_int(v, 9)))
|
||||
}
|
||||
"PWM_SCALE_AUTO": (lambda v: tmc2130.decode_signed_int(v, 9))
|
||||
})
|
||||
|
||||
|
||||
######################################################################
|
||||
|
|
Loading…
Reference in New Issue