mirror of https://github.com/Desuuuu/klipper.git
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 <kevin@koconnor.net>
This commit is contained in:
parent
8e6d5efdac
commit
1d796a4e24
|
@ -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
|
but to make things more readable the host will translate human
|
||||||
readable pin names (eg, "PA3") to their equivalent integer
|
readable pin names (eg, "PA3") to their equivalent integer
|
||||||
encodings. By convention, any parameter named "pin" or that has a
|
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:
|
Common startup commands:
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ class KeyboardReader:
|
||||||
self.reactor = reactor
|
self.reactor = reactor
|
||||||
self.fd = sys.stdin.fileno()
|
self.fd = sys.stdin.fileno()
|
||||||
util.set_nonblock(self.fd)
|
util.set_nonblock(self.fd)
|
||||||
|
self.mcu_freq = 0
|
||||||
self.pins = None
|
self.pins = None
|
||||||
self.data = ""
|
self.data = ""
|
||||||
reactor.register_fd(self.fd, self.process_kbd)
|
reactor.register_fd(self.fd, self.process_kbd)
|
||||||
|
@ -24,15 +25,14 @@ class KeyboardReader:
|
||||||
self.eval_globals = {}
|
self.eval_globals = {}
|
||||||
def connect(self, eventtime):
|
def connect(self, eventtime):
|
||||||
self.ser.connect()
|
self.ser.connect()
|
||||||
|
self.mcu_freq = int(self.ser.msgparser.get_constant_float('CLOCK_FREQ'))
|
||||||
mcu = self.ser.msgparser.get_constant('MCU')
|
mcu = self.ser.msgparser.get_constant('MCU')
|
||||||
self.pins = pins.get_pin_map(mcu)
|
self.pins = pins.get_pin_map(mcu)
|
||||||
self.reactor.unregister_timer(self.connect_timer)
|
self.reactor.unregister_timer(self.connect_timer)
|
||||||
return self.reactor.NEVER
|
return self.reactor.NEVER
|
||||||
def update_evals(self, eventtime):
|
def update_evals(self, eventtime):
|
||||||
f = int(self.ser.msgparser.config.get('CLOCK_FREQ', 1))
|
self.eval_globals['freq'] = self.mcu_freq
|
||||||
c = self.ser.get_clock(eventtime)
|
self.eval_globals['clock'] = int(self.ser.get_clock(eventtime))
|
||||||
self.eval_globals['freq'] = f
|
|
||||||
self.eval_globals['clock'] = int(c)
|
|
||||||
def set_pin_map(self, parts):
|
def set_pin_map(self, parts):
|
||||||
mcu = self.ser.msgparser.get_constant('MCU')
|
mcu = self.ser.msgparser.get_constant('MCU')
|
||||||
self.pins = pins.get_pin_map(mcu, parts[1])
|
self.pins = pins.get_pin_map(mcu, parts[1])
|
||||||
|
@ -60,7 +60,8 @@ class KeyboardReader:
|
||||||
print "Eval:", line
|
print "Eval:", line
|
||||||
if self.pins is not None:
|
if self.pins is not None:
|
||||||
try:
|
try:
|
||||||
line = pins.update_command(line, self.pins).strip()
|
line = pins.update_command(
|
||||||
|
line, self.mcu_freq, self.pins).strip()
|
||||||
except:
|
except:
|
||||||
print "Unable to map pin: ", line
|
print "Unable to map pin: ", line
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -28,13 +28,12 @@ class MCU_stepper:
|
||||||
step_pin, pullup, invert_step = parse_pin_extras(step_pin)
|
step_pin, pullup, invert_step = parse_pin_extras(step_pin)
|
||||||
dir_pin, pullup, self._invert_dir = parse_pin_extras(dir_pin)
|
dir_pin, pullup, self._invert_dir = parse_pin_extras(dir_pin)
|
||||||
self._mcu_freq = mcu.get_mcu_freq()
|
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)
|
max_error = int(max_error * self._mcu_freq)
|
||||||
self.commanded_position = 0
|
self.commanded_position = 0
|
||||||
self._mcu_position_offset = 0
|
self._mcu_position_offset = 0
|
||||||
mcu.add_config_cmd(
|
mcu.add_config_cmd(
|
||||||
"config_stepper oid=%d step_pin=%s dir_pin=%s"
|
"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))
|
self._oid, step_pin, dir_pin, min_stop_interval, invert_step))
|
||||||
mcu.register_stepper(self)
|
mcu.register_stepper(self)
|
||||||
self._step_cmd = mcu.lookup_command(
|
self._step_cmd = mcu.lookup_command(
|
||||||
|
@ -233,7 +232,8 @@ class MCU_digital_out:
|
||||||
self._cmd_queue = mcu.alloc_command_queue()
|
self._cmd_queue = mcu.alloc_command_queue()
|
||||||
mcu.add_config_cmd(
|
mcu.add_config_cmd(
|
||||||
"config_digital_out oid=%d pin=%s default_value=%d"
|
"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(
|
self._set_cmd = mcu.lookup_command(
|
||||||
"schedule_digital_out oid=%c clock=%u value=%c")
|
"schedule_digital_out oid=%c clock=%u value=%c")
|
||||||
self.print_to_mcu_time = mcu.print_to_mcu_time
|
self.print_to_mcu_time = mcu.print_to_mcu_time
|
||||||
|
@ -254,25 +254,26 @@ class MCU_digital_out:
|
||||||
|
|
||||||
class MCU_pwm:
|
class MCU_pwm:
|
||||||
PWM_MAX = 255.
|
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._mcu = mcu
|
||||||
self._oid = mcu.create_oid()
|
self._oid = mcu.create_oid()
|
||||||
pin, pullup, self._invert = parse_pin_extras(pin)
|
pin, pullup, self._invert = parse_pin_extras(pin)
|
||||||
self._last_clock = 0
|
self._last_clock = 0
|
||||||
self._mcu_freq = mcu.get_mcu_freq()
|
self._mcu_freq = mcu.get_mcu_freq()
|
||||||
self._cmd_queue = mcu.alloc_command_queue()
|
self._cmd_queue = mcu.alloc_command_queue()
|
||||||
if hard_pwm:
|
if hard_cycle_ticks:
|
||||||
mcu.add_config_cmd(
|
mcu.add_config_cmd(
|
||||||
"config_pwm_out oid=%d pin=%s cycle_ticks=%d default_value=%d"
|
"config_pwm_out oid=%d pin=%s cycle_ticks=%d default_value=%d"
|
||||||
" max_duration=%d" % (
|
" max_duration=TICKS(%f)" % (
|
||||||
self._oid, pin, cycle_ticks, self._invert, max_duration))
|
self._oid, pin, hard_cycle_ticks, self._invert,
|
||||||
|
max_duration))
|
||||||
self._set_cmd = mcu.lookup_command(
|
self._set_cmd = mcu.lookup_command(
|
||||||
"schedule_pwm_out oid=%c clock=%u value=%c")
|
"schedule_pwm_out oid=%c clock=%u value=%c")
|
||||||
else:
|
else:
|
||||||
mcu.add_config_cmd(
|
mcu.add_config_cmd(
|
||||||
"config_soft_pwm_out oid=%d pin=%s cycle_ticks=%d"
|
"config_soft_pwm_out oid=%d pin=%s cycle_ticks=TICKS(%f)"
|
||||||
" default_value=%d max_duration=%d" % (
|
" default_value=%d max_duration=TICKS(%f)" % (
|
||||||
self._oid, pin, cycle_ticks, self._invert, max_duration))
|
self._oid, pin, cycle_time, self._invert, max_duration))
|
||||||
self._set_cmd = mcu.lookup_command(
|
self._set_cmd = mcu.lookup_command(
|
||||||
"schedule_soft_pwm_out oid=%c clock=%u value=%c")
|
"schedule_soft_pwm_out oid=%c clock=%u value=%c")
|
||||||
self.print_to_mcu_time = mcu.print_to_mcu_time
|
self.print_to_mcu_time = mcu.print_to_mcu_time
|
||||||
|
@ -461,7 +462,8 @@ class MCU:
|
||||||
updated_cmds = []
|
updated_cmds = []
|
||||||
for cmd in self._config_cmds:
|
for cmd in self._config_cmds:
|
||||||
try:
|
try:
|
||||||
updated_cmds.append(pins.update_command(cmd, pnames))
|
updated_cmds.append(pins.update_command(
|
||||||
|
cmd, self._mcu_freq, pnames))
|
||||||
except:
|
except:
|
||||||
raise self._config.error("Unable to translate pin name: %s" % (
|
raise self._config.error("Unable to translate pin name: %s" % (
|
||||||
cmd,))
|
cmd,))
|
||||||
|
@ -531,16 +533,11 @@ class MCU:
|
||||||
def create_endstop(self, pin, stepper):
|
def create_endstop(self, pin, stepper):
|
||||||
return MCU_endstop(self, pin, stepper)
|
return MCU_endstop(self, pin, stepper)
|
||||||
def create_digital_out(self, pin, max_duration=2.):
|
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)
|
return MCU_digital_out(self, pin, max_duration)
|
||||||
def create_pwm(self, pin, cycle_time, hard_cycle_ticks=0, max_duration=2.):
|
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:
|
if hard_cycle_ticks < 0:
|
||||||
return MCU_digital_out(self, pin, max_duration)
|
return MCU_digital_out(self, pin, max_duration)
|
||||||
cycle_ticks = int(cycle_time * self._mcu_freq)
|
return MCU_pwm(self, pin, cycle_time, hard_cycle_ticks, max_duration)
|
||||||
return MCU_pwm(self, pin, cycle_ticks, max_duration, False)
|
|
||||||
def create_adc(self, pin):
|
def create_adc(self, pin):
|
||||||
return MCU_adc(self, pin)
|
return MCU_adc(self, pin)
|
||||||
# Clock syncing
|
# Clock syncing
|
||||||
|
|
|
@ -100,9 +100,12 @@ def get_pin_map(mcu, mapping_name=None):
|
||||||
pins['analog%d' % (i,)] = pins[apins[i]]
|
pins['analog%d' % (i,)] = pins[apins[i]]
|
||||||
return pins
|
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<prefix>[ _]pin=)(?P<name>[^ ]*)')
|
re_pin = re.compile(r'(?P<prefix>[ _]pin=)(?P<name>[^ ]*)')
|
||||||
def update_command(cmd, pmap):
|
re_ticks = re.compile(r'TICKS\((?P<ticks>[^)]*)\)')
|
||||||
def fixup(m):
|
def update_command(cmd, mcu_freq, pmap):
|
||||||
|
def pin_fixup(m):
|
||||||
return m.group('prefix') + str(pmap[m.group('name')])
|
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))
|
||||||
|
|
Loading…
Reference in New Issue