X-Git-Url: https://git.ayoreis.com/Adafruit_Blinka-hackapet.git/blobdiff_plain/a66c05d143cab78dc36ea119e7de17897d75bfe2..refs/heads/main:/src/rotaryio.py?ds=sidebyside diff --git a/src/rotaryio.py b/src/rotaryio.py index 7c30332..b8bf4cb 100644 --- a/src/rotaryio.py +++ b/src/rotaryio.py @@ -9,129 +9,18 @@ See `CircuitPython:rotaryio` in CircuitPython for more details. * Author(s): Melissa LeBlanc-Williams """ -from __future__ import annotations -import threading -import microcontroller -import digitalio - -# Define the state transition table for the quadrature encoder -transitions = [ - 0, # 00 -> 00 no movement - -1, # 00 -> 01 3/4 ccw (11 detent) or 1/4 ccw (00 at detent) - +1, # 00 -> 10 3/4 cw or 1/4 cw - 0, # 00 -> 11 non-Gray-code transition - +1, # 01 -> 00 2/4 or 4/4 cw - 0, # 01 -> 01 no movement - 0, # 01 -> 10 non-Gray-code transition - -1, # 01 -> 11 4/4 or 2/4 ccw - -1, # 10 -> 00 2/4 or 4/4 ccw - 0, # 10 -> 01 non-Gray-code transition - 0, # 10 -> 10 no movement - +1, # 10 -> 11 4/4 or 2/4 cw - 0, # 11 -> 00 non-Gray-code transition - +1, # 11 -> 01 1/4 or 3/4 cw - -1, # 11 -> 10 1/4 or 3/4 ccw - 0, # 11 -> 11 no movement -] - - -class IncrementalEncoder: - """ - IncrementalEncoder determines the relative rotational position based on two series of - pulses. It assumes that the encoder’s common pin(s) are connected to ground,and enables - pull-ups on pin_a and pin_b. - - Create an IncrementalEncoder object associated with the given pins. It tracks the - positional state of an incremental rotary encoder (also known as a quadrature encoder.) - Position is relative to the position when the object is constructed. - """ - - def __init__( - self, pin_a: microcontroller.Pin, pin_b: microcontroller.Pin, divisor: int = 4 - ): - """ - Create an IncrementalEncoder object associated with the given pins. It tracks the - positional state of an incremental rotary encoder (also known as a quadrature encoder.) - Position is relative to the position when the object is constructed. - - :param microcontroller.Pin pin_a: The first pin connected to the encoder. - :param microcontroller.Pin pin_b: The second pin connected to the encoder. - :param int divisor: The number of pulses per encoder step. Default is 4. - """ - self._pin_a = digitalio.DigitalInOut(pin_a) - self._pin_a.switch_to_input(pull=digitalio.Pull.UP) - self._pin_b = digitalio.DigitalInOut(pin_b) - self._pin_b.switch_to_input(pull=digitalio.Pull.UP) - self._position = 0 - self._last_state = 0 - self._divisor = divisor - self._sub_count = 0 - self._poll_thread = threading.Thread(target=self._polling_loop, daemon=True) - self._poll_thread.start() - - def deinit(self): - """Deinitializes the IncrementalEncoder and releases any hardware resources for reuse.""" - self._pin_a.deinit() - self._pin_b.deinit() - if self._poll_thread.is_alive(): - self._poll_thread.join() - - def __enter__(self) -> IncrementalEncoder: - """No-op used by Context Managers.""" - return self - - def __exit__(self, _type, _value, _traceback): - """ - Automatically deinitializes when exiting a context. See - :ref:`lifetime-and-contextmanagers` for more info. - """ - self.deinit() - - @property - def divisor(self) -> int: - """The divisor of the quadrature signal. Use 1 for encoders without detents, or encoders - with 4 detents per cycle. Use 2 for encoders with 2 detents per cycle. Use 4 for encoders - with 1 detent per cycle.""" - return self._divisor - - @divisor.setter - def divisor(self, value: int): - self._divisor = value - - @property - def position(self) -> int: - """The current position in terms of pulses. The number of pulses per rotation is defined - by the specific hardware and by the divisor.""" - return self._position - - @position.setter - def position(self, value: int): - self._position = value - - def _get_pin_state(self) -> int: - """Returns the current state of the pins.""" - return self._pin_a.value << 1 | self._pin_b.value - - def _polling_loop(self): - while True: - self._poll_encoder() - - def _poll_encoder(self): - # Check the state of the pins - # if either pin has changed, update the state - new_state = self._get_pin_state() - if new_state != self._last_state: - self._state_update(new_state) - self._last_state = new_state - - def _state_update(self, new_state: int): - new_state &= 3 - index = self._last_state << 2 | new_state - sub_increment = transitions[index] - self._sub_count += sub_increment - if self._sub_count >= self._divisor: - self._position += 1 - self._sub_count = 0 - elif self._sub_count <= -self._divisor: - self._position -= 1 - self._sub_count = 0 +from adafruit_blinka.agnostic import detector + +# pylint: disable=unused-import + +# Import any board specific modules here +if detector.board.any_raspberry_pi_5_board: + from adafruit_blinka.microcontroller.bcm283x.rotaryio import IncrementalEncoder +elif detector.board.any_embedded_linux: + # fall back to the generic linux implementation + from adafruit_blinka.microcontroller.generic_linux.rotaryio import ( + IncrementalEncoder, + ) +else: + # For non-Linux Boards, threading likely will work in the same way + raise NotImplementedError("Board not supported")