aboutsummaryrefslogtreecommitdiffstats
path: root/klippy/extras/buttons.py
diff options
context:
space:
mode:
Diffstat (limited to 'klippy/extras/buttons.py')
-rw-r--r--klippy/extras/buttons.py91
1 files changed, 91 insertions, 0 deletions
diff --git a/klippy/extras/buttons.py b/klippy/extras/buttons.py
index 9ebd3adc..b06f1f83 100644
--- a/klippy/extras/buttons.py
+++ b/klippy/extras/buttons.py
@@ -7,6 +7,10 @@ import logging
QUERY_TIME = .002
RETRANSMIT_COUNT = 50
+ADC_REPORT_TIME = 0.015
+ADC_DEBOUNCE_TIME = 0.025
+ADC_SAMPLE_TIME = 0.001
+ADC_SAMPLE_COUNT = 6
# Rotary encoder handler https://github.com/brianlow/Rotary
# Copyright 2011 Ben Buxton (bb@cactii.net).
@@ -112,6 +116,79 @@ class MCU_buttons:
self.last_button = button
+class MCU_ADC_buttons:
+ def __init__(self, printer, pin, pullup, debug=False):
+ self.reactor = printer.get_reactor()
+ self.buttons = []
+ self.last_button = None
+ self.last_pressed = None
+ self.last_debouncetime = 0
+ self.pullup = pullup
+ self.debug = debug
+ self.pin = pin
+ self.min_value = self.max_value = None
+ ppins = printer.lookup_object('pins')
+ self.mcu_adc = ppins.setup_pin('adc', self.pin)
+ self.mcu_adc.setup_minmax(ADC_SAMPLE_TIME, ADC_SAMPLE_COUNT)
+ self.mcu_adc.setup_adc_callback(ADC_REPORT_TIME, self.adc_callback)
+
+ def setup_button(self, min_value, max_value, callback):
+ if self.min_value is None:
+ self.min_value = min_value
+ else:
+ self.min_value = min(self.min_value, min_value)
+
+ if self.max_value is None:
+ self.max_value = max_value
+ else:
+ self.max_value = max(self.max_value, max_value)
+
+ self.buttons.append((min_value, max_value, callback))
+
+ def adc_callback(self, read_time, read_value):
+ adc = max(.00001, min(.99999, read_value))
+ r = self.pullup * adc / (1.0 - adc)
+ self.reactor.register_async_callback(
+ (lambda e, s=self, v=r: s.handle_button(e, v)))
+
+ def get_button(self, value):
+ if (self.min_value is not None and self.max_value is not None
+ and self.min_value <= value <= self.max_value):
+ for i, (min_value, max_value, cb) in enumerate(self.buttons):
+ if min_value < value < max_value:
+ return i
+ return None
+
+ def handle_button(self, eventtime, value):
+ btn = self.get_button(int(value))
+
+ # If the button changed, due to noise or pressing:
+ if btn != self.last_button:
+ # reset the debouncing timer
+ self.last_debouncetime = eventtime
+
+ # button debounce check & new button pressed
+ if ((eventtime - self.last_debouncetime) >= ADC_DEBOUNCE_TIME
+ and self.last_button == btn and self.last_pressed != btn):
+ # release last_pressed
+ if self.last_pressed is not None:
+ self.call_button(eventtime, self.last_pressed, False)
+ self.last_pressed = None
+ if btn is not None:
+ self.call_button(eventtime, btn, True)
+ self.last_pressed = btn
+
+ self.last_button = btn
+ if self.debug is True:
+ logging.info(
+ "analog pin: %s value: %d" % (self.pin, int(value)))
+
+ def call_button(self, eventtime, button, state):
+ if button < len(self.buttons):
+ minval, maxval, callback = self.buttons[button]
+ callback(eventtime, state)
+
+
######################################################################
# Rotary Encoders
######################################################################
@@ -138,6 +215,20 @@ class PrinterButtons:
def __init__(self, config):
self.printer = config.get_printer()
self.mcu_buttons = {}
+ self.adc_buttons = {}
+ def register_adc_button(
+ self, pin, min_val, max_val, pullup, callback, debug=False):
+ adc_buttons = self.adc_buttons.get(pin)
+ if adc_buttons is None:
+ self.adc_buttons[pin] = adc_buttons = MCU_ADC_buttons(
+ self.printer, pin, pullup, debug)
+ adc_buttons.setup_button(min_val, max_val, callback)
+ def register_adc_button_push(
+ self, pin, min_val, max_val, pullup, callback, debug=False):
+ def helper(eventtime, state, callback=callback):
+ if state:
+ callback(eventtime)
+ self.register_adc_button(pin, min_val, max_val, pullup, helper, debug)
def register_buttons(self, pins, callback):
# Parse pins
ppins = self.printer.lookup_object('pins')