From 1d796a4e24311dded166f74396662251672869fd Mon Sep 17 00:00:00 2001 From: Kevin O'Connor Date: Sun, 12 Mar 2017 19:55:56 -0400 Subject: [PATCH] mcu: Support config mechanism for translating seconds to clock ticks Introduce a TICKS() macro during config parsing that will translate time in seconds to time in clock ticks. Signed-off-by: Kevin O'Connor --- docs/Firmware_Commands.md | 6 +++++- klippy/console.py | 11 ++++++----- klippy/mcu.py | 31 ++++++++++++++----------------- klippy/pins.py | 11 +++++++---- 4 files changed, 32 insertions(+), 27 deletions(-) diff --git a/docs/Firmware_Commands.md b/docs/Firmware_Commands.md index 63647c39..d6ad2d8f 100644 --- a/docs/Firmware_Commands.md +++ b/docs/Firmware_Commands.md @@ -33,7 +33,11 @@ low-level firmware uses integer encodings of the hardware pin numbers, but to make things more readable the host will translate human readable pin names (eg, "PA3") to their equivalent integer encodings. By convention, any parameter named "pin" or that has a -"_pin" suffix will use pin name translation by the host. +"_pin" suffix will use pin name translation by the host. Similarly, +several commands take time parameters specified in clock ticks. One +can specify a value for these parameters in seconds using the +"TICKS()" macro - for example "cycle_ticks=TICKS(0.001)" would result +in "cycle_ticks=16000" on a micro-controller with a 16Mhz clock. Common startup commands: diff --git a/klippy/console.py b/klippy/console.py index 81dc87b2..2552b35c 100755 --- a/klippy/console.py +++ b/klippy/console.py @@ -16,6 +16,7 @@ class KeyboardReader: self.reactor = reactor self.fd = sys.stdin.fileno() util.set_nonblock(self.fd) + self.mcu_freq = 0 self.pins = None self.data = "" reactor.register_fd(self.fd, self.process_kbd) @@ -24,15 +25,14 @@ class KeyboardReader: self.eval_globals = {} def connect(self, eventtime): self.ser.connect() + self.mcu_freq = int(self.ser.msgparser.get_constant_float('CLOCK_FREQ')) mcu = self.ser.msgparser.get_constant('MCU') self.pins = pins.get_pin_map(mcu) self.reactor.unregister_timer(self.connect_timer) return self.reactor.NEVER def update_evals(self, eventtime): - f = int(self.ser.msgparser.config.get('CLOCK_FREQ', 1)) - c = self.ser.get_clock(eventtime) - self.eval_globals['freq'] = f - self.eval_globals['clock'] = int(c) + self.eval_globals['freq'] = self.mcu_freq + self.eval_globals['clock'] = int(self.ser.get_clock(eventtime)) def set_pin_map(self, parts): mcu = self.ser.msgparser.get_constant('MCU') self.pins = pins.get_pin_map(mcu, parts[1]) @@ -60,7 +60,8 @@ class KeyboardReader: print "Eval:", line if self.pins is not None: try: - line = pins.update_command(line, self.pins).strip() + line = pins.update_command( + line, self.mcu_freq, self.pins).strip() except: print "Unable to map pin: ", line return None diff --git a/klippy/mcu.py b/klippy/mcu.py index 00eef1df..ec36f3aa 100644 --- a/klippy/mcu.py +++ b/klippy/mcu.py @@ -28,13 +28,12 @@ class MCU_stepper: step_pin, pullup, invert_step = parse_pin_extras(step_pin) dir_pin, pullup, self._invert_dir = parse_pin_extras(dir_pin) self._mcu_freq = mcu.get_mcu_freq() - min_stop_interval = int(min_stop_interval * self._mcu_freq) max_error = int(max_error * self._mcu_freq) self.commanded_position = 0 self._mcu_position_offset = 0 mcu.add_config_cmd( "config_stepper oid=%d step_pin=%s dir_pin=%s" - " min_stop_interval=%d invert_step=%d" % ( + " min_stop_interval=TICKS(%.9f) invert_step=%d" % ( self._oid, step_pin, dir_pin, min_stop_interval, invert_step)) mcu.register_stepper(self) self._step_cmd = mcu.lookup_command( @@ -233,7 +232,8 @@ class MCU_digital_out: self._cmd_queue = mcu.alloc_command_queue() mcu.add_config_cmd( "config_digital_out oid=%d pin=%s default_value=%d" - " max_duration=%d" % (self._oid, pin, self._invert, max_duration)) + " max_duration=TICKS(%f)" % ( + self._oid, pin, self._invert, max_duration)) self._set_cmd = mcu.lookup_command( "schedule_digital_out oid=%c clock=%u value=%c") self.print_to_mcu_time = mcu.print_to_mcu_time @@ -254,25 +254,26 @@ class MCU_digital_out: class MCU_pwm: PWM_MAX = 255. - def __init__(self, mcu, pin, cycle_ticks, max_duration, hard_pwm=False): + def __init__(self, mcu, pin, cycle_time, hard_cycle_ticks, max_duration): self._mcu = mcu self._oid = mcu.create_oid() pin, pullup, self._invert = parse_pin_extras(pin) self._last_clock = 0 self._mcu_freq = mcu.get_mcu_freq() self._cmd_queue = mcu.alloc_command_queue() - if hard_pwm: + if hard_cycle_ticks: mcu.add_config_cmd( "config_pwm_out oid=%d pin=%s cycle_ticks=%d default_value=%d" - " max_duration=%d" % ( - self._oid, pin, cycle_ticks, self._invert, max_duration)) + " max_duration=TICKS(%f)" % ( + self._oid, pin, hard_cycle_ticks, self._invert, + max_duration)) self._set_cmd = mcu.lookup_command( "schedule_pwm_out oid=%c clock=%u value=%c") else: mcu.add_config_cmd( - "config_soft_pwm_out oid=%d pin=%s cycle_ticks=%d" - " default_value=%d max_duration=%d" % ( - self._oid, pin, cycle_ticks, self._invert, max_duration)) + "config_soft_pwm_out oid=%d pin=%s cycle_ticks=TICKS(%f)" + " default_value=%d max_duration=TICKS(%f)" % ( + self._oid, pin, cycle_time, self._invert, max_duration)) self._set_cmd = mcu.lookup_command( "schedule_soft_pwm_out oid=%c clock=%u value=%c") self.print_to_mcu_time = mcu.print_to_mcu_time @@ -461,7 +462,8 @@ class MCU: updated_cmds = [] for cmd in self._config_cmds: try: - updated_cmds.append(pins.update_command(cmd, pnames)) + updated_cmds.append(pins.update_command( + cmd, self._mcu_freq, pnames)) except: raise self._config.error("Unable to translate pin name: %s" % ( cmd,)) @@ -531,16 +533,11 @@ class MCU: def create_endstop(self, pin, stepper): return MCU_endstop(self, pin, stepper) def create_digital_out(self, pin, max_duration=2.): - max_duration = int(max_duration * self._mcu_freq) return MCU_digital_out(self, pin, max_duration) def create_pwm(self, pin, cycle_time, hard_cycle_ticks=0, max_duration=2.): - max_duration = int(max_duration * self._mcu_freq) - if hard_cycle_ticks: - return MCU_pwm(self, pin, hard_cycle_ticks, max_duration, True) if hard_cycle_ticks < 0: return MCU_digital_out(self, pin, max_duration) - cycle_ticks = int(cycle_time * self._mcu_freq) - return MCU_pwm(self, pin, cycle_ticks, max_duration, False) + return MCU_pwm(self, pin, cycle_time, hard_cycle_ticks, max_duration) def create_adc(self, pin): return MCU_adc(self, pin) # Clock syncing diff --git a/klippy/pins.py b/klippy/pins.py index 597e59b3..a4262a4e 100644 --- a/klippy/pins.py +++ b/klippy/pins.py @@ -100,9 +100,12 @@ def get_pin_map(mcu, mapping_name=None): pins['analog%d' % (i,)] = pins[apins[i]] return pins -# Translate pin names in a firmware command +# Translate pin names and tick times in a firmware command re_pin = re.compile(r'(?P[ _]pin=)(?P[^ ]*)') -def update_command(cmd, pmap): - def fixup(m): +re_ticks = re.compile(r'TICKS\((?P[^)]*)\)') +def update_command(cmd, mcu_freq, pmap): + def pin_fixup(m): return m.group('prefix') + str(pmap[m.group('name')]) - return re_pin.sub(fixup, cmd) + def ticks_fixup(m): + return str(int(mcu_freq * float(m.group('ticks')))) + return re_ticks.sub(ticks_fixup, re_pin.sub(pin_fixup, cmd))