From 4df8a9ded15fa686adb95fb96cbf6adee931d64c Mon Sep 17 00:00:00 2001 From: Bob837217 <68859866+Bob837217@users.noreply.github.com> Date: Wed, 18 Oct 2023 10:22:53 +0100 Subject: [PATCH] Added extra construction support to Encoder.py to support pullup direction from Code.py (#891) * Added support to Encoder.py to allow GPIOEncoder to accept tuple for pin_button construction. This includes allowance for pull resistor (pullup/pulldown) customisation directly from code.py. Additionally the change preserves state generation semantics for pin_button.get_value(self) and depends upon the pull direction. The default pull direction remains as digitalio.Pull.UP * Replaced multiline ternary/conditional expression with a regular If statement for EncoderPin.get_value() as suggested in review * Prior commit failed test. Audio Mute was assigned to the encoder push button action and was activating upon keyboard USB insertion without user interaction. Fixed this error. * Implemented the reviewer suggestion for the GPIO constructor to take in an additional optional argument defaulting to Pull.UP instead of overloading the argument with a tuple. This is tested, and documented in English * Fix formatting encoder.py --------- Co-authored-by: Gordon Jamieson Co-authored-by: xs5871 <60395129+xs5871@users.noreply.github.com> --- docs/en/encoder.md | 4 ++-- kmk/modules/encoder.py | 28 +++++++++++++++++++++------- 2 files changed, 23 insertions(+), 9 deletions(-) mode change 100644 => 100755 kmk/modules/encoder.py diff --git a/docs/en/encoder.md b/docs/en/encoder.md index 84e6453d6..45eec014f 100644 --- a/docs/en/encoder.md +++ b/docs/en/encoder.md @@ -26,8 +26,8 @@ encoder_handler = EncoderHandler() keyboard.modules = [layers, holdtap, encoder_handler] ``` -2. Define the pins for each encoder: `pin_a`, `pin_b` for rotations, `pin_button` for the switch in the encoder. Set switch to `None` if the encoder's button is handled differently (as a part of matrix for example) or not at all. If you want to invert the direction of the encoder, set the 4th (optional) parameter `is_inverted` to `True`. 5th parameter is [encoder divisor](#encoder-resolution) (optional), it can be either `2` or `4`. - +2. Define the pins for each encoder: `pin_a`, `pin_b` for rotations, `pin_button` for the switch in the encoder. Set switch to `None` if the encoder's button is handled differently (as a part of matrix for example) or not at all. If you want to invert the direction of the encoder, set the 4th (optional) parameter `is_inverted` to `True`. 5th parameter is [encoder divisor](#encoder-resolution) (optional), it can be either `2` or `4`. If your encoder button pull direction is not the default of `digitalio.Pull.UP`, you may specify the 6th (optional) parameter `button_pull` as `digitalio.Pull.DOWN`. + ```python # Regular GPIO Encoder encoder_handler.pins = ( diff --git a/kmk/modules/encoder.py b/kmk/modules/encoder.py old mode 100644 new mode 100755 index c3c11f9bf..43c18b338 --- a/kmk/modules/encoder.py +++ b/kmk/modules/encoder.py @@ -112,7 +112,15 @@ def vel_report(self): class GPIOEncoder(BaseEncoder): - def __init__(self, pin_a, pin_b, pin_button=None, is_inverted=False, divisor=None): + def __init__( + self, + pin_a, + pin_b, + pin_button=None, + is_inverted=False, + divisor=None, + button_pull=digitalio.Pull.UP, + ): super().__init__(is_inverted) # Divisor can be 4 or 2 depending on whether the detent @@ -121,9 +129,10 @@ def __init__(self, pin_a, pin_b, pin_button=None, is_inverted=False, divisor=Non self.pin_a = EncoderPin(pin_a) self.pin_b = EncoderPin(pin_b) - self.pin_button = ( - EncoderPin(pin_button, button_type=True) if pin_button is not None else None - ) + if pin_button: + self.pin_button = EncoderPin(pin_button, button_type=True, pull=button_pull) + else: + self.pin_button = None self._state = (self.pin_a.get_value(), self.pin_b.get_value()) self._start_state = self._state @@ -138,9 +147,10 @@ def button_event(self): class EncoderPin: - def __init__(self, pin, button_type=False): + def __init__(self, pin, button_type=False, pull=digitalio.Pull.UP): self.pin = pin self.button_type = button_type + self.pull = pull self.prepare_pin() def prepare_pin(self): @@ -150,12 +160,16 @@ def prepare_pin(self): else: self.io = digitalio.DigitalInOut(self.pin) self.io.direction = digitalio.Direction.INPUT - self.io.pull = digitalio.Pull.UP + self.io.pull = self.pull else: self.io = None def get_value(self): - return self.io.value + io = self.io + result = io.value + if digitalio.Pull.UP != io.pull: + result = not result + return result class I2CEncoder(BaseEncoder):