continued to break out keys

This commit is contained in:
2022-01-09 17:02:10 +01:00
parent 9e96452c53
commit b75fc313c1
3 changed files with 141 additions and 91 deletions

View File

@@ -140,8 +140,8 @@ class Keyboard:
io_extenders = self.initialize_io_extenders(io_extenders_pinout)
self.pins = self.initialize_pins(io_extenders, pinout)
test_keymap(keymap, debug_repl)
self.keymap = keymap
self.keymap = self._initialize_keymap(keymap)
self.layer_colors = layer_colors
self.layer = LayerState()
@@ -150,6 +150,13 @@ class Keyboard:
if debug_repl:
print("Done initializing keyboard")
def _initialize_keymap(self, keymap: list[list[KeyBase]]) -> list[list[KeyBase]]:
test_keymap(keymap, True)
for layer in keymap:
for key in layer:
key.enrich(layer.index(key), keymap.index(layer))
return keymap
def initialize_hid(self) -> tuple[usb_hid.Device, usb_hid.Device]:
"""Initializes keyboard and media device if availabe"""
for device in usb_hid.devices:
@@ -194,6 +201,9 @@ class Keyboard:
self.pressed_keys = set()
self.pressed_keys_last_cycle = set()
def get_key(self, layer_index, key_index) -> KeyBase:
return self.keymap[layer_index][key_index]
def start(self):
if self.debug_repl:
print("Starting keyboard")

View File

@@ -1,7 +1,6 @@
from keycodes import SE
from keytypes import Hold, Keycode, Modifier, Toggle
keymap = [[
Hold(1), Toggle(2), Toggle(3), Toggle(4),
Toggle(0), Keycode(SE.B), Keycode(SE.C), Keycode(SE.D),

View File

@@ -27,31 +27,45 @@ class KeyEvents:
current: int
previous: int
def __init__(self, current: int, previous: int):
self.current = current
self.previous = previous
def __init__(self):
self.current = KeyEvent.RELEASED
self.previous = KeyEvent.RELEASED
def shift(self, next):
print(
f"next: {next}, current: {self.current}, previous: {self.previous}")
self.previous = self.current
self.current = next
class KeyBase:
event: int
events: KeyEvents
allowed_events: list[KeyEvent]
key_index: int
layer_index: int
def __init__(self, allowed_events: list[int]):
self.allowed_events = allowed_events
self.event = KeyEvent.NO_EVENT
self.events = KeyEvents()
self.key_index = None
self.layer_index = None
def _validate_next_event(self, event: int):
if event is None or event not in self.allowed_events:
def enrich(self, key_index: int, layer_index: int):
self.key_index = key_index
self.layer_index = layer_index
def _validate_next_event(self, next_event: int):
if next_event is None or next_event not in self.allowed_events:
raise Exception(
f"KeyEvent with value of {event} is not a valid event for this type of key")
f"KeyEvent with value of {next_event} is not a valid event for this type of key")
def _set_event(self, next: int) -> bool:
def _set_event(self, next_event: int) -> bool:
"""Sets previous state if new state is valid
Returns: A boolean that determines if the state was updated or not"""
self._validate_next_event(next)
if next is KeyEvent.NO_EVENT:
self._validate_next_event(next_event)
if next_event is KeyEvent.NO_EVENT:
return False
self.event = next
self.events.shift(next_event)
return True
def handle(self, keyboard):
@@ -81,53 +95,55 @@ class KeycodeBase(KeyBase):
raise NotImplementedError
def soft_release(self, keyboard, pin):
if self.events.current != KeyEvent.PRESSED_:
return
self._set_event(KeyEvent.SOFT_RELEASED)
self._handle_event(keyboard)
def _consume_next_event(self, pin) -> bool:
"""Returns: a boolean representing if the event property was updated with a new event or not"""
pin_event = pin.read_event()
previous = int(self.event)
next = None
if previous == KeyEvent.NO_EVENT:
if pin_event == PinEvent.NO_EVENT:
next = KeyEvent.NO_EVENT
if pin_event == PinEvent.RELEASED:
next = KeyEvent.RELEASED
if pin_event == PinEvent.PRESSED:
next = KeyEvent.PRESSED_
if previous == KeyEvent.RELEASED:
if pin_event == PinEvent.NO_EVENT:
next = KeyEvent.NO_EVENT
if pin_event == PinEvent.RELEASED:
next = KeyEvent.NO_EVENT
if pin_event == PinEvent.PRESSED:
next = KeyEvent.PRESSED_
if previous == KeyEvent.PRESSED_:
if pin_event == PinEvent.NO_EVENT:
next = KeyEvent.NO_EVENT
if pin_event == PinEvent.RELEASED:
next = KeyEvent.RELEASED
if pin_event == PinEvent.PRESSED:
next = KeyEvent.NO_EVENT
if previous == KeyEvent.SOFT_RELEASED:
if pin_event == PinEvent.NO_EVENT:
next = KeyEvent.NO_EVENT
if pin_event == PinEvent.RELEASED:
next = KeyEvent.RELEASED
if pin_event == PinEvent.PRESSED:
next = KeyEvent.NO_EVENT
next_pin_event = pin.read_event()
current_key_event, previous_key_event = self.events.current, self.events.previous
next_key_event = None
if current_key_event == KeyEvent.NO_EVENT:
if next_pin_event == PinEvent.NO_EVENT:
next_key_event = KeyEvent.NO_EVENT
if next_pin_event == PinEvent.RELEASED:
next_key_event = KeyEvent.RELEASED
if next_pin_event == PinEvent.PRESSED:
next_key_event = KeyEvent.PRESSED_
if current_key_event == KeyEvent.RELEASED:
if next_pin_event == PinEvent.NO_EVENT:
next_key_event = KeyEvent.NO_EVENT
if next_pin_event == PinEvent.RELEASED:
next_key_event = KeyEvent.NO_EVENT
if next_pin_event == PinEvent.PRESSED:
next_key_event = KeyEvent.PRESSED_
if current_key_event == KeyEvent.PRESSED_:
if next_pin_event == PinEvent.NO_EVENT:
next_key_event = KeyEvent.NO_EVENT
if next_pin_event == PinEvent.RELEASED:
next_key_event = KeyEvent.RELEASED
if next_pin_event == PinEvent.PRESSED:
next_key_event = KeyEvent.NO_EVENT
if current_key_event == KeyEvent.SOFT_RELEASED:
if next_pin_event == PinEvent.NO_EVENT:
next_key_event = KeyEvent.NO_EVENT
if next_pin_event == PinEvent.RELEASED:
next_key_event = KeyEvent.RELEASED
if next_pin_event == PinEvent.PRESSED:
next_key_event = KeyEvent.NO_EVENT
return self._set_event(next)
return self._set_event(next_key_event)
def _handle_event(self, keyboard) -> None:
if self.event == KeyEvent.NO_EVENT:
current = self.events.current
if current == KeyEvent.NO_EVENT:
return
if self.event == KeyEvent.PRESSED_:
if current == KeyEvent.PRESSED_:
keyboard.add_keycode_to_report(self.keycode)
if self.event == KeyEvent.RELEASED:
if current == KeyEvent.RELEASED:
keyboard.remove_keycode_from_report(self.keycode)
if self.event == KeyEvent.SOFT_RELEASED:
if current == KeyEvent.SOFT_RELEASED:
keyboard.remove_keycode_from_report(self.keycode)
def handle(self, keyboard, pin):
@@ -155,11 +171,11 @@ class Modifier(KeycodeBase):
class LayerKeyBase(KeyBase):
layer: int
layer_to_switch_to: int
def __init__(self, layer: int, allowed_events):
super().__init__(allowed_events)
self.layer = layer
self.layer_to_switch_to = layer
class Toggle(LayerKeyBase):
@@ -171,52 +187,43 @@ class Toggle(LayerKeyBase):
KeyEvent.PRESSED_TOGGLED_OFF,
KeyEvent.RELEASED,
KeyEvent.SOFT_RELEASED]
has_received_state_from = None
super().__init__(layer, allowed_events)
def _consume_next_event(self, pin: Pin) -> bool:
"""Returns: a boolean representing if the event property was updated with a new event or not"""
next_pin_event = pin.read_event()
previous = self.event
next = None
print(f"toggle stuff: {previous}")
current_key_event = self.events.current
if previous == KeyEvent.NO_EVENT:
if next_pin_event == PinEvent.NO_EVENT:
next = KeyEvent.NO_EVENT
if next_pin_event == PinEvent.NO_EVENT:
return self._set_event(KeyEvent.NO_EVENT)
if current_key_event == KeyEvent.PRESSED_TOGGLED_ON:
if next_pin_event == PinEvent.PRESSED:
next = KeyEvent.PRESSED_TOGGLED_ON
return self._set_event(KeyEvent.NO_EVENT)
if next_pin_event == PinEvent.RELEASED:
next = KeyEvent.RELEASED
if previous == KeyEvent.PRESSED_TOGGLED_ON:
if next_pin_event == PinEvent.NO_EVENT:
next = KeyEvent.NO_EVENT
return self._set_event(KeyEvent.RELEASED_TOGGLED_ON)
if current_key_event == KeyEvent.RELEASED_TOGGLED_ON:
if next_pin_event == PinEvent.PRESSED:
next = KeyEvent.NO_EVENT
return self._set_event(KeyEvent.PRESSED_TOGGLED_OFF)
if next_pin_event == PinEvent.RELEASED:
next = KeyEvent.RELEASED_TOGGLED_ON
if previous == KeyEvent.RELEASED_TOGGLED_ON:
if next_pin_event == PinEvent.NO_EVENT:
next = KeyEvent.NO_EVENT
return self._set_event(KeyEvent.NO_EVENT)
if current_key_event == KeyEvent.PRESSED_TOGGLED_OFF:
if next_pin_event == PinEvent.PRESSED:
next = KeyEvent.PRESSED_TOGGLED_OFF
return self._set_event(KeyEvent.NO_EVENT)
if next_pin_event == PinEvent.RELEASED:
next = KeyEvent.NO_EVENT
if previous == KeyEvent.PRESSED_TOGGLED_OFF:
if next_pin_event == PinEvent.NO_EVENT:
next = KeyEvent.NO_EVENT
return self._set_event(KeyEvent.RELEASED)
if current_key_event == KeyEvent.RELEASED:
if next_pin_event == PinEvent.PRESSED:
next = KeyEvent.NO_EVENT
return self._set_event(KeyEvent.PRESSED_TOGGLED_ON)
if next_pin_event == PinEvent.RELEASED:
next = KeyEvent.RELEASED
if previous == KeyEvent.RELEASED:
if next_pin_event == PinEvent.NO_EVENT:
next = KeyEvent.NO_EVENT
if next_pin_event == PinEvent.PRESSED:
next = KeyEvent.PRESSED_TOGGLED_ON
return self._set_event(KeyEvent.NO_EVENT)
if current_key_event == KeyEvent.SOFT_RELEASED:
if next_pin_event == PinEvent.RELEASED:
next = KeyEvent.NO_EVENT
return self._set_event(KeyEvent.RELEASED)
else:
return self._set_event(KeyEvent.NO_EVENT)
return self._set_event(next)
raise NotImplementedError()
def _release_all_other_keys(self, keyboard, pin: Pin):
for layer in keyboard.keymap:
@@ -227,14 +234,18 @@ class Toggle(LayerKeyBase):
key.soft_release(keyboard, pin_of_key)
def _handle_event(self, keyboard, pin):
if self.event == KeyEvent.PRESSED_TOGGLED_ON:
keyboard.layer.toggle(self.layer)
current = self.events.current
if current == KeyEvent.PRESSED_TOGGLED_ON:
keyboard.layer.toggle(self.layer_to_switch_to)
self._release_all_other_keys(keyboard, pin)
if self.event == KeyEvent.RELEASED_TOGGLED_ON:
self._swap_state(keyboard)
if current == KeyEvent.RELEASED_TOGGLED_ON:
pass
if self.event == KeyEvent.PRESSED_TOGGLED_OFF:
keyboard.layer.release_toggled(self.layer)
if self.event == KeyEvent.RELEASED:
if current == KeyEvent.PRESSED_TOGGLED_OFF:
keyboard.layer.release_toggled()
self._release_all_other_keys(keyboard, pin)
self._swap_state_back(keyboard)
if current == KeyEvent.RELEASED:
pass
def handle(self, keyboard, pin: Pin):
@@ -246,7 +257,37 @@ class Toggle(LayerKeyBase):
raise NotImplementedError()
def soft_release(self, keyboard, pin):
pass
pressed = self.events.current not in [
KeyEvent.RELEASED, KeyEvent.PRESSED_TOGGLED_OFF, KeyEvent.SOFT_RELEASED]
if not pressed:
return
print(f"releasing {keyboard}, {self.events.current}")
self.has_received_state_from = None
self._set_event(KeyEvent.SOFT_RELEASED)
def _swap_state(self, keyboard) -> None:
key_to_swap_with = keyboard.get_key(
self.layer_to_switch_to, self.key_index)
other_keys_state = key_to_swap_with._handle_on_swap_state(
self.events, (self.layer_index, self.key_index))
self.events = other_keys_state
def _swap_state_back(self, keyboard) -> None:
if not self.has_received_state_from:
return
key_to_swap_with = keyboard.get_key(
self.has_received_state_from[0], self.has_received_state_from[1])
other_keys_state = key_to_swap_with._handle_on_swap_state(
self.events, None)
self.events = other_keys_state
def _handle_on_swap_state(self, received_state: KeyEvents, indexes: tuple[int, int]) -> KeyEvents:
"""Invoked on the Toggle key that is present on the layer another Toggle key is switching to
Makes sure that the state is carried over so that pressing the button once more returns to the old layer."""
self.has_received_state_from = indexes
state_to_send_back = self.events
self.events = received_state
return state_to_send_back
# todo: Release all keys not the same as the old layer
# todo: Debounce old toggle when pressing new toggle