diff options
author | Kevin O'Connor <kevin@koconnor.net> | 2017-08-21 11:25:26 -0400 |
---|---|---|
committer | Kevin O'Connor <kevin@koconnor.net> | 2017-08-25 20:38:55 -0400 |
commit | ec7990796a1a554869452530f84a91dff9f58c43 (patch) | |
tree | 5cb3288c32143800c796892bc2806e7874cfcdcb /klippy/mcu.py | |
parent | 268834e4aedac2e435e778802353e767d6b8abe3 (diff) | |
download | kutter-ec7990796a1a554869452530f84a91dff9f58c43.tar.gz kutter-ec7990796a1a554869452530f84a91dff9f58c43.tar.xz kutter-ec7990796a1a554869452530f84a91dff9f58c43.zip |
pins: Support registering arbitrary chips that supply configurable pins
Allow multiple chips to provide pin mappings (not just the main mcu
chip). Move the pin parsing from the mcu.py code to pins.py and
support mapping from pin descriptions to their corresponding chips and
parameters.
Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
Diffstat (limited to 'klippy/mcu.py')
-rw-r--r-- | klippy/mcu.py | 142 |
1 files changed, 76 insertions, 66 deletions
diff --git a/klippy/mcu.py b/klippy/mcu.py index aa35f76d..3190a325 100644 --- a/klippy/mcu.py +++ b/klippy/mcu.py @@ -9,24 +9,15 @@ import serialhdl, pins, chelper class error(Exception): pass -def parse_pin_extras(pin, can_pullup=False): - pullup = invert = 0 - if can_pullup and pin.startswith('^'): - pullup = 1 - pin = pin[1:].strip() - if pin.startswith('!'): - invert = 1 - pin = pin[1:].strip() - return pin, pullup, invert - STEPCOMPRESS_ERROR_RET = -989898989 class MCU_stepper: - def __init__(self, mcu, step_pin, dir_pin): + def __init__(self, mcu, pin_params): self._mcu = mcu self._oid = mcu.create_oid(self) - self._step_pin, pullup, self._invert_step = parse_pin_extras(step_pin) - self._dir_pin, pullup, self._invert_dir = parse_pin_extras(dir_pin) + self._step_pin = pin_params['pin'] + self._invert_step = pin_params['invert'] + self._dir_pin = self._invert_dir = None self._commanded_pos = 0 self._step_dist = self._inv_step_dist = 1. self._velocity_factor = self._accel_factor = 0. @@ -36,9 +27,14 @@ class MCU_stepper: self._ffi_lib = self._stepqueue = None self.print_to_mcu_time = mcu.print_to_mcu_time self.system_to_mcu_time = mcu.system_to_mcu_time - def set_min_stop_interval(self, min_stop_interval): + def setup_dir_pin(self, pin_params): + if pin_params['chip'] is not self._mcu: + raise pins.error("Stepper dir pin must be on same mcu as step pin") + self._dir_pin = pin_params['pin'] + self._invert_dir = pin_params['invert'] + def setup_min_stop_interval(self, min_stop_interval): self._min_stop_interval = min_stop_interval - def set_step_distance(self, step_dist): + def setup_step_distance(self, step_dist): self._step_dist = step_dist self._inv_step_dist = 1. / step_dist def build_config(self): @@ -144,12 +140,13 @@ class MCU_stepper: class MCU_endstop: error = error RETRY_QUERY = 1.000 - def __init__(self, mcu, pin): + def __init__(self, mcu, pin_params): self._mcu = mcu self._oid = mcu.create_oid(self) self._steppers = [] - self._pin, self._pullup, self._invert = parse_pin_extras( - pin, can_pullup=True) + self._pin = pin_params['pin'] + self._pullup = pin_params['pullup'] + self._invert = pin_params['invert'] self._cmd_queue = mcu.alloc_command_queue() self._home_cmd = self._query_cmd = None self._homing = False @@ -240,23 +237,27 @@ class MCU_endstop: return self._last_state.get('pin', self._invert) ^ self._invert class MCU_digital_out: - def __init__(self, mcu, pin, max_duration): + def __init__(self, mcu, pin_params): self._mcu = mcu self._oid = mcu.create_oid(self) - pin, pullup, self._invert = parse_pin_extras(pin) + self._pin = pin_params['pin'] + self._invert = pin_params['invert'] + self._max_duration = 2. self._last_clock = 0 self._last_value = None self._mcu_freq = 0. self._cmd_queue = mcu.alloc_command_queue() - mcu.add_config_cmd( - "config_digital_out oid=%d pin=%s default_value=%d" - " max_duration=TICKS(%f)" % ( - self._oid, pin, self._invert, max_duration)) self._set_cmd = None self.print_to_mcu_time = mcu.print_to_mcu_time self.system_to_mcu_time = mcu.system_to_mcu_time + def setup_max_duration(self, max_duration): + self._max_duration = max_duration def build_config(self): self._mcu_freq = self._mcu.get_mcu_freq() + self._mcu.add_config_cmd( + "config_digital_out oid=%d pin=%s default_value=%d" + " max_duration=TICKS(%f)" % ( + self._oid, self._pin, self._invert, self._max_duration)) self._set_cmd = self._mcu.lookup_command( "schedule_digital_out oid=%c clock=%u value=%c") def set_digital(self, mcu_time, value): @@ -275,37 +276,49 @@ class MCU_digital_out: self.set_digital(mcu_time, dval) class MCU_pwm: - def __init__(self, mcu, pin, cycle_time, hard_cycle_ticks, max_duration): + def __init__(self, mcu, pin_params): self._mcu = mcu - self._hard_cycle_ticks = hard_cycle_ticks + self._hard_pwm = False + self._cycle_time = 0.100 + self._max_duration = 2. self._oid = mcu.create_oid(self) - pin, pullup, self._invert = parse_pin_extras(pin) + self._pin = pin_params['pin'] + self._invert = pin_params['invert'] self._last_clock = 0 self._mcu_freq = 0. self._pwm_max = 0. self._cmd_queue = mcu.alloc_command_queue() - if hard_cycle_ticks: - mcu.add_config_cmd( - "config_pwm_out oid=%d pin=%s cycle_ticks=%d default_value=%d" - " max_duration=TICKS(%f)" % ( - self._oid, pin, hard_cycle_ticks, self._invert, - max_duration)) - else: - mcu.add_config_cmd( - "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 = None self.print_to_mcu_time = mcu.print_to_mcu_time self.system_to_mcu_time = mcu.system_to_mcu_time + def setup_max_duration(self, max_duration): + self._max_duration = max_duration + def setup_cycle_time(self, cycle_time): + self._cycle_time = cycle_time + self._hard_pwm = False + def setup_hard_pwm(self, hard_cycle_ticks): + if not hard_cycle_ticks: + return + self._cycle_time = hard_cycle_ticks + self._hard_pwm = True def build_config(self): self._mcu_freq = self._mcu.get_mcu_freq() - if self._hard_cycle_ticks: + if self._hard_pwm: + self._mcu.add_config_cmd( + "config_pwm_out oid=%d pin=%s cycle_ticks=%d default_value=%d" + " max_duration=TICKS(%f)" % ( + self._oid, self._pin, self._cycle_time, self._invert, + self._max_duration)) self._pwm_max = self._mcu.serial.msgparser.get_constant_float( "PWM_MAX") self._set_cmd = self._mcu.lookup_command( "schedule_pwm_out oid=%c clock=%u value=%hu") else: + self._mcu.add_config_cmd( + "config_soft_pwm_out oid=%d pin=%s cycle_ticks=TICKS(%f)" + " default_value=%d max_duration=TICKS(%f)" % ( + self._oid, self._pin, self._cycle_time, self._invert, + self._max_duration)) self._pwm_max = self._mcu.serial.msgparser.get_constant_float( "SOFT_PWM_MAX") self._set_cmd = self._mcu.lookup_command( @@ -321,8 +334,9 @@ class MCU_pwm: self._last_clock = clock class MCU_adc: - def __init__(self, mcu, pin): + def __init__(self, mcu, pin_params): self._mcu = mcu + self._pin = pin_params['pin'] self._oid = mcu.create_oid(self) self._min_sample = self._max_sample = 0. self._sample_time = self._report_time = 0. @@ -332,20 +346,23 @@ class MCU_adc: self._inv_max_adc = 0. self._mcu_freq = 0. self._cmd_queue = mcu.alloc_command_queue() - mcu.add_config_cmd("config_analog_in oid=%d pin=%s" % (self._oid, pin)) self._query_cmd = None mcu.add_init_callback(self._init_callback) - self._query_cmd = None + def setup_minmax(self, sample_time, sample_count, minval=0., maxval=1.): + self._sample_time = sample_time + self._sample_count = sample_count + self._min_sample = minval + self._max_sample = maxval + def setup_adc_callback(self, report_time, callback): + self._report_time = report_time + self._callback = callback def build_config(self): self._mcu_freq = self._mcu.get_mcu_freq() + self._mcu.add_config_cmd("config_analog_in oid=%d pin=%s" % ( + self._oid, self._pin)) self._query_cmd = self._mcu.lookup_command( "query_analog_in oid=%c clock=%u sample_ticks=%u sample_count=%c" " rest_ticks=%u min_value=%hu max_value=%hu") - def set_minmax(self, sample_time, sample_count, minval=0., maxval=1.): - self._sample_time = sample_time - self._sample_count = sample_count - self._min_sample = minval - self._max_sample = maxval def _init_callback(self): if not self._sample_count: return @@ -370,9 +387,6 @@ class MCU_adc: last_read_time = (next_clock - self._report_clock) / self._mcu_freq if self._callback is not None: self._callback(last_read_time, last_value) - def set_adc_callback(self, report_time, callback): - self._report_time = report_time - self._callback = callback class MCU: error = error @@ -398,7 +412,7 @@ class MCU: # Config building if printer.bglogger is not None: printer.bglogger.set_rollover_info("mcu", None) - self._config_error = config.error + pins.get_printer_pins(printer).register_chip("mcu", self) self._emergency_stop_cmd = self._reset_cmd = None self._oids = [] self._config_cmds = [] @@ -564,8 +578,7 @@ class MCU: updated_cmds.append(pins.update_command( cmd, self._mcu_freq, pnames)) except: - raise self._config_error("Unable to translate pin name: %s" % ( - cmd,)) + raise pins.error("Unable to translate pin name: %s" % (cmd,)) self._config_cmds = updated_cmds # Calculate config CRC @@ -617,6 +630,13 @@ class MCU: for cb in self._init_callbacks: cb() # Config creation helpers + def setup_pin(self, pin_params): + pcs = {'stepper': MCU_stepper, 'endstop': MCU_endstop, + 'digital_out': MCU_digital_out, 'pwm': MCU_pwm, 'adc': MCU_adc} + pin_type = pin_params['type'] + if pin_type not in pcs: + raise pins.error("pin type %s not supported on mcu" % (pin_type,)) + return pcs[pin_type](self, pin_params) def create_oid(self, oid): self._oids.append(oid) return len(self._oids) - 1 @@ -634,19 +654,6 @@ class MCU: return self.serial.msgparser.lookup_command(msgformat) def create_command(self, msg): return self.serial.msgparser.create_command(msg) - # Wrappers for mcu object creation - def create_stepper(self, step_pin, dir_pin): - return MCU_stepper(self, step_pin, dir_pin) - def create_endstop(self, pin): - return MCU_endstop(self, pin) - def create_digital_out(self, pin, max_duration=2.): - return MCU_digital_out(self, pin, max_duration) - def create_pwm(self, pin, cycle_time, hard_cycle_ticks=0, max_duration=2.): - if hard_cycle_ticks < 0: - return MCU_digital_out(self, pin, max_duration) - return MCU_pwm(self, pin, cycle_time, hard_cycle_ticks, max_duration) - def create_adc(self, pin): - return MCU_adc(self, pin) # Clock syncing def set_print_start_time(self, eventtime): clock = self.serial.get_clock(eventtime) @@ -687,3 +694,6 @@ class MCU: return self._printer.reactor.monotonic() def __del__(self): self.disconnect() + +def add_printer_objects(printer, config): + printer.add_object('mcu', MCU(printer, config.getsection('mcu'))) |