diff --git a/keytypes.py b/keytypes.py index b732713..bcb63d5 100644 --- a/keytypes.py +++ b/keytypes.py @@ -1,100 +1,37 @@ import digitalio +from enum import Enum from micropython import const +from pin import Pin, PinEvent -class PinState: - PRESSED: int = const(0) - RELEASED: int = const(1) - - -class PinEvent: - NONE: int = const(0) - PRESSED: int = const(1) - RELEASED: int = const(2) - - -class KeyState: +class KeyState(Enum): """Interpretations of hardware pin state""" - PRESSED = const(0) + __pressed = 0 """Key is pressed""" - UNPRESSED = const(1) + __unpressed = const(1) """Key is not pressed""" - PRESSED_TOGGLED_ON = const(2) + __pressed_toggled_on = const(2) """Key is pressed and is emulating a toggle key in ON state that is not released until the physical key is released, then pressed again""" - UNPRESSED_TOGGLED_ON = const(3) + __unpressed_toggled_on = const(3) """Key is unpressed and is emulating a toggle key in ON state that is not released unit the physical key is pressed again""" - PRESSED_TOGGLED_OFF = const(4) + __pressed_toggled_off = const(4) """Key is pressed and is emulating a toggle key in OFF state""" - DEBOUNCE = const(5) + __debounce = const(5) """Further state changes of any kind are ignored until key has been physically released released""" -class KeyEvent: +class KeyEvent(Enum): """Interpretations of KeyStates as single events""" - NONE: int = const(0) + __no_event: int = const(0) """No new event has occurred""" - PRESSED = "" + __pressed = const(1) """The key was pressed""" - RELEASED: int = const(2) + __released: int = const(2) """The key was released""" - SOFT_RELEASE: int = const(3) + __soft_released: int = const(3) """The key was released programatically, and not by an actual physical release of a button.""" -class PinStates: - current: int - previous: int - - def __init__(self, current: int, previous: int): - self.current = current - self.previous = previous - - -class Pin: - index: int - hw_pin: digitalio.DigitalInOut - previous_state: int - - def __init__(self, index, hw_pin: digitalio.DigitalInOut): - self.index = index - self.hw_pin = hw_pin - self.previous_state = PinState.RELEASED - - def _consume_next_state(self) -> PinStates: - states = PinStates(int(self.hw_pin.value), int(self.previous_state)) - self.previous_state = states.current - return states - - def read_event(self) -> int: - current, previous = self._consume_next_state() - if previous == PinState.RELEASED: - if current == PinState.RELEASED: - return PinEvent.NONE - if current == PinState.PRESSED: - return PinEvent.PRESSED - if previous == PinState.PRESSED: - if current == PinState.PRESSED: - return PinEvent.NONE - if current == PinState.RELEASED: - return PinEvent.RELEASED - raise NotImplementedError() - - -class Key: - index: int - previous_state: KeyState - - def __init__(self): - pass - - def set_index(self, index) -> None: - assert 0 <= index - self.index = index - - def handle(self, keyboard): - assert self.index is not None - - class KeyStates: current: int previous: int @@ -104,6 +41,16 @@ class KeyStates: self.previous = previous +class Key: + previous_state: int + + def __init__(self): + self.previous_state = KeyState.__unpressed + + def handle(self, keyboard): + pass + + class Keycode(Key): keycode: int @@ -114,44 +61,43 @@ class Keycode(Key): def _consume_next_state(self, pin: Pin) -> KeyStates: """Interprets the changes to hardware pins as current and previous KeyState""" event = pin.read_event() - if event == PinEvent.NONE: + if event == PinEvent.no_event: return KeyStates(self.previous_state, self.previous_state) - if event == PinEvent.PRESSED: - states = KeyStates(KeyState.PRESSED, int(self.previous_state)) + if event == PinEvent.pressed: + states = KeyStates(KeyState.__pressed, int(self.previous_state)) self.previous_state = states.current return states - if event == PinEvent.RELEASED: - states = KeyStates(KeyState.UNPRESSED, int(self.previous_state)) + if event == PinEvent.released: + states = KeyStates(KeyState.__unpressed, int(self.previous_state)) self.previous_state = states.current return states raise NotImplementedError() - def _read_event(self, pin) -> KeyEvent: + def _read_event(self, pin) -> int: """Interprets the current and previous KeyState as a KeyEvent""" states = self._consume_next_state(pin) - current, previous = states - if previous == KeyState.UNPRESSED: - if current == KeyState.UNPRESSED: - return KeyEvent.NONE - if current == KeyState.PRESSED: - return KeyEvent.PRESSED - if previous == KeyState.PRESSED: - if current == KeyState.PRESSED: - return KeyEvent.NONE - if current == KeyState.UNPRESSED: - return KeyEvent.RELEASED + if states.previous == KeyState.__unpressed: + if states.current == KeyState.__unpressed: + return KeyEvent.__no_event + if states.current == KeyState.__pressed: + return KeyEvent.__pressed + if states.previous == KeyState.__pressed: + if states.current == KeyState.__pressed: + return KeyEvent.__no_event + if states.current == KeyState.__unpressed: + return KeyEvent.__released raise NotImplementedError() - def _react_to_event(self, event: KeyEvent, keyboard) -> None: - if event == KeyEvent.NONE: + def _react_to_event(self, event: int, keyboard) -> None: + if event == KeyEvent.__no_event: return - if event == KeyEvent.PRESSED: + if event == KeyEvent.__pressed: keyboard.add_keycode_to_report(self.keycode) - if event == KeyEvent.RELEASED: + if event == KeyEvent.__released: keyboard.remove_keycode_from_report(self.keycode) def handle(self, keyboard, pin): - super().handle() + super().handle(keyboard) event = self._read_event(pin) self._react_to_event(event, keyboard) diff --git a/pin.py b/pin.py new file mode 100644 index 0000000..1c1d94b --- /dev/null +++ b/pin.py @@ -0,0 +1,53 @@ +import digitalio +from micropython import const +from adafruit_blinka import Enum + + +class PinState(Enum): + PRESSED: int = 0 + RELEASED: int = 1 + + +class PinEvent(Enum): + NO_EVENT: int = 0 + PRESSED: int = 1 + RELEASED: int = 2 + + +class PinStates: + current: int + previous: int + + def __init__(self, current: int, previous: int): + self.current = current + self.previous = previous + + +class Pin: + index: int + hw_pin: digitalio.DigitalInOut + previous_state: int + + def __init__(self, index, hw_pin: digitalio.DigitalInOut): + self.index = index + self.hw_pin = hw_pin + self.previous_state = PinState.RELEASED + + def _consume_next_state(self) -> PinStates: + states = PinStates(int(self.hw_pin.value), int(self.previous_state)) + self.previous_state = states.current + return states + + def read_event(self) -> int: + states = self._consume_next_state() + if states.previous == PinState.RELEASED: + if states.current == PinState.RELEASED: + return PinEvent.NO_EVENT + if states.current == PinState.PRESSED: + return PinEvent.PRESSED + if states.previous == PinState.PRESSED: + if states.current == PinState.PRESSED: + return PinEvent.NO_EVENT + if states.current == PinState.RELEASED: + return PinEvent.RELEASED + raise NotImplementedError()