From 5a7e52ced3871db0f2ff85c9f2103956830647ec Mon Sep 17 00:00:00 2001 From: Jeff Epler Date: Fri, 5 Mar 2021 11:00:07 -0600 Subject: [PATCH] Add rotaryencoder example This example requires https://github.com/adafruit/circuitpython/pull/4329 to be merged in order to work --- examples/rotaryencoder.py | 119 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 examples/rotaryencoder.py diff --git a/examples/rotaryencoder.py b/examples/rotaryencoder.py new file mode 100644 index 0000000..0587332 --- /dev/null +++ b/examples/rotaryencoder.py @@ -0,0 +1,119 @@ +# SPDX-FileCopyrightText: 2021 Jeff Epler, written for Adafruit Industries +# +# SPDX-License-Identifier: MIT +# +# This example is adapted in part from micropython: +# https://github.com/micropython/micropython/pull/6894/files + +import adafruit_pioasm +import board +import rp2pio +import array +import digitalio + + +class IncrementalEncoder: + _state_look_up_table = array.array( + "b", + [ + # Direction = 1 + 0, # 00 to 00 + -1, # 00 to 01 + +1, # 00 to 10 + +2, # 00 to 11 + +1, # 01 to 00 + 0, # 01 to 01 + +2, # 01 to 10 + -1, # 01 to 11 + -1, # 10 to 00 + +2, # 10 to 01 + 0, # 10 to 10 + +1, # 10 to 11 + +2, # 11 to 00 + +1, # 11 to 01 + -1, # 11 to 10 + 0, # 11 to 11 + # Direction = 0 + 0, # 00 to 00 + -1, # 00 to 01 + +1, # 00 to 10 + -2, # 00 to 11 + +1, # 01 to 00 + 0, # 01 to 01 + -2, # 01 to 10 + -1, # 01 to 11 + -1, # 10 to 00 + -2, # 10 to 01 + 0, # 10 to 10 + +1, # 10 to 11 + -2, # 11 to 00 + +1, # 11 to 01 + -1, # 11 to 10 + 0, # 11 to 11 + ], + ) + + _sm_code = adafruit_pioasm.assemble( + """ + again: + in pins, 2 + mov x, isr + jmp x!=y, push_data + mov isr, null + jmp again + push_data: + push + mov y, x + """ + ) + + _sm_init = adafruit_pioasm.assemble("set y 31") + + def __init__(self, pin_a, pin_b): + if not rp2pio.pins_are_sequential([pin_a, pin_b]): + raise ValueError("Pins must be sequential") + + self._sm = rp2pio.StateMachine( + self._sm_code, + 160_000, + init=self._sm_init, + first_in_pin=pin_a, + in_pin_count=2, + pull_in_pin_up=0b11, + in_shift_right=False, + ) + + self._counter = 0 + self._direction = 0 + self._lut_index = 0 + self._buffer = bytearray(1) + + def _update_state_machine(self, state): + lut_index = self._lut_index | (state & 3) + lut = self._state_look_up_table[lut_index] + self._counter += lut + if lut: + self._direction = 1 if (lut > 0) else 0 + self._lut_index = ((lut_index << 2) & 0b1100) | (self._direction << 4) + + def deinit(self): + self._sm.deinit() + + @property + def value(self): + while self._sm.in_waiting: + self._sm.readinto(self._buffer) + self._update_state_machine(self._buffer[0]) + return self._counter + + +encoder = IncrementalEncoder(board.GP2, board.GP3) + +old_value = None +while True: + gen() + + value = encoder.value + if old_value != value: + print("Encoder:", value) + old_value = value