Last active
February 15, 2021 00:10
-
-
Save nmorse/c5f2c5188945dac34ad47c21d57387a8 to your computer and use it in GitHub Desktop.
Simulated interrupt handler to test a rotary position algorithm (orig v1 from )
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Simulated interrupt handlers to test rotary position algorithms | |
features changing handles by entering (1 <enter> or 2 <enter>) into the console. | |
Todo: add more handler algorithms | |
""" | |
import board | |
from digitalio import DigitalInOut, Direction, Pull | |
import supervisor | |
# setup pins (a and b) for encoder | |
pin_a = DigitalInOut(board.D10) | |
pin_a.direction = Direction.INPUT | |
pin_a.pull = Pull.UP | |
pin_b = DigitalInOut(board.D9) | |
pin_b.direction = Direction.INPUT | |
pin_b.pull = Pull.UP | |
# to simulate an interrupt routine (detect pin changes) | |
last_a = -1 | |
last_b = -1 | |
class RotaryEncoderState : | |
state = 0 | |
quarter = 0 | |
position = 0 | |
rotary = RotaryEncoderState() | |
# original algorithm | |
def interrupt_handler_1 (a, b) : | |
# a | b | a<<1 | a^b | a<<1 + a^b (aka decimal grey code index) | |
# --+---+------+-----+--------------- | |
# 0 | 0 | 0 | 0 | 0 | |
# 0 | 1 | 0 | 1 | 1 | |
# 1 | 0 | 2 | 1 | 3 | |
# 1 | 1 | 2 | 0 | 2 | |
new_state = (a << 1) + (a ^ b) | |
change = (new_state - rotary.state) & 0x03 | |
# print("change", change, "state", state, "new_state", new_state) | |
if change == 1 : | |
rotary.quarter += 1 | |
print("quarter", rotary.quarter) | |
if change == 3 : | |
rotary.quarter -= 1 | |
print("quarter", rotary.quarter) | |
# ignore other state transitions | |
rotary.state = new_state | |
# logic from the atmel-samd port: provides some damping and scales movement | |
# down by 4:1. | |
if rotary.quarter >= 4: | |
rotary.position += 1 | |
rotary.quarter = 0 | |
print("+++++ position", rotary.position) | |
if rotary.quarter <= -4 : | |
rotary.position -= 1 | |
rotary.quarter = 0 | |
print("----- position", rotary.position) | |
# an alternate version that only changes position at (a=1, b=1) | |
def interrupt_handler_2 (a, b) : | |
# a | b | a<<1 | a^b | a<<1 + a^b (aka decimal grey code index) | |
# --+---+------+-----+--------------- | |
# 0 | 0 | 0 | 0 | 0 | |
# 0 | 1 | 0 | 1 | 1 | |
# 1 | 0 | 2 | 1 | 3 | |
# 1 | 1 | 2 | 0 | 2 | |
new_state = (a << 1) + (a ^ b) | |
change = (new_state - rotary.state) & 0x03 | |
# print("change", change, "state", state, "new_state", new_state) | |
if change == 1 : | |
rotary.quarter += 1 | |
print("quarter", rotary.quarter) | |
if change == 3 : | |
rotary.quarter -= 1 | |
print("quarter", rotary.quarter) | |
# ignore other state transitions | |
rotary.state = new_state | |
# logic from the atmel-samd port: provides some damping and scales movement | |
# down by 4:1. | |
if rotary.quarter != 0 and rotary.state == 2: | |
if rotary.quarter > 0 : | |
rotary.position += 1 | |
rotary.quarter = 0 | |
print("+++++ position", rotary.position) | |
else : | |
rotary.position -= 1 | |
rotary.quarter = 0 | |
print("----- position", rotary.position) | |
# which handler to use | |
handler_index = "1" | |
print("\n\nAt any time, you may enter a handler index (1 <enter> or 2 <enter>)") | |
print("Using handler: {}".format(handler_index)) | |
while True: | |
if supervisor.runtime.serial_bytes_available: | |
handler_index = input().strip() | |
if handler_index == "": | |
continue | |
if not (handler_index == "1" or handler_index == "2") : | |
print("invalid input, Enter a handler index (1 <enter> or 2 <enter>)") | |
else : | |
print("Changed to handler: {}".format(handler_index)) | |
a = int(pin_a.value) | |
b = int(pin_b.value) | |
# # invert for testing | |
# a = 0 if a == 1 else 1 | |
# b = 0 if b == 1 else 1 | |
# simulating an interupt routine (only when a or b have changed) | |
if not a == last_a or not b == last_b : | |
# print(last_a, "->", a, " | ", last_b, "->", b) | |
if handler_index == "1" : | |
interrupt_handler_1(a, b) | |
if handler_index == "2" : | |
interrupt_handler_2(a, b) | |
# simulated interupt routine house keeping | |
last_a = a | |
last_b = b |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment