continued to break out keys
This commit is contained in:
50
keyboard.py
50
keyboard.py
@@ -73,20 +73,38 @@ class RGBLED:
|
||||
time.sleep(color_sleep_cycles[i][0])
|
||||
|
||||
|
||||
__PRESSED = const(0)
|
||||
__UNPRESSED = const(1)
|
||||
__TOGGLED_PRESSED = const(2)
|
||||
__TOGGLED_RELEASED = const(3)
|
||||
__UNTOGGLED_PRESSED = const(4)
|
||||
__DEBOUNCE = const(5)
|
||||
class LayerState:
|
||||
_NO_TOGGLED_LAYER = 0
|
||||
_NO_HELD_LAYER = None
|
||||
|
||||
toggled: int
|
||||
held: int
|
||||
|
||||
def __init__(self):
|
||||
self.toggled = self._NO_TOGGLED_LAYER
|
||||
self.held = self._NO_HELD_LAYER
|
||||
|
||||
def get(self) -> int:
|
||||
return self.held if self.held != self._NO_HELD_LAYER else self.toggled
|
||||
|
||||
def toggle(self, toggled: int):
|
||||
self.toggled = toggled
|
||||
self.held = self._NO_HELD_LAYER
|
||||
|
||||
def release_toggled(self):
|
||||
self.toggled = self._NO_TOGGLED_LAYER
|
||||
|
||||
def hold(self, held):
|
||||
self.held = held
|
||||
|
||||
def released_held(self):
|
||||
self.held = self._NO_HELD_LAYER
|
||||
|
||||
|
||||
class Keyboard:
|
||||
debug_repl: bool
|
||||
|
||||
toggled_layer: int
|
||||
held_layer: int
|
||||
previous_layers: list[int]
|
||||
layer: LayerState
|
||||
layer_colors: list[tuple[int, int, int]]
|
||||
|
||||
pressed_keys_last_cycle: set[int]
|
||||
@@ -125,6 +143,7 @@ class Keyboard:
|
||||
test_keymap(keymap, debug_repl)
|
||||
self.keymap = keymap
|
||||
self.layer_colors = layer_colors
|
||||
self.layer = LayerState()
|
||||
|
||||
self.led = RGBLED(rgb_pins)
|
||||
self.led.indicate_boot()
|
||||
@@ -175,9 +194,6 @@ class Keyboard:
|
||||
self.pressed_keys = set()
|
||||
self.pressed_keys_last_cycle = set()
|
||||
|
||||
def _get_current_layer_index(self) -> int:
|
||||
return self.held_layer if self.held_layer != None else self.toggled_layer
|
||||
|
||||
def start(self):
|
||||
if self.debug_repl:
|
||||
print("Starting keyboard")
|
||||
@@ -187,16 +203,14 @@ class Keyboard:
|
||||
print("Keyboard started")
|
||||
while True:
|
||||
for pin in self.pins:
|
||||
layer = self._get_current_layer_index()
|
||||
layer = self.layer.get()
|
||||
key = self.keymap[layer][pin.index]
|
||||
if type(key) is Hold:
|
||||
continue
|
||||
if type(key) is Toggle:
|
||||
continue
|
||||
key.handle(self, pin)
|
||||
active_layer = self.held_layer if self.held_layer != None else self.toggled_layer
|
||||
if len(self.layer_colors) >= (active_layer + 1):
|
||||
self.led.set(self.layer_colors[active_layer])
|
||||
layer = self.layer.get()
|
||||
if len(self.layer_colors) >= (layer + 1):
|
||||
self.led.set(self.layer_colors[layer])
|
||||
else:
|
||||
self.led.off()
|
||||
if self.pressed_keys != self.pressed_keys_last_cycle:
|
||||
|
||||
143
keytypes.py
143
keytypes.py
@@ -17,12 +17,10 @@ class KeyEvent:
|
||||
"""The key was released programatically, and not by an actual physical release of a button."""
|
||||
PRESSED_TOGGLED_ON = const(4)
|
||||
"""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(5)
|
||||
RELEASED_TOGGLED_ON = const(5)
|
||||
"""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(6)
|
||||
"""Key is pressed and is emulating a toggle key in OFF state"""
|
||||
DEBOUNCE = const(7)
|
||||
"""Further state changes of any kind are ignored until key has been physically released released"""
|
||||
|
||||
|
||||
class KeyEvents:
|
||||
@@ -35,25 +33,35 @@ class KeyEvents:
|
||||
|
||||
|
||||
class KeyBase:
|
||||
previous_event: int
|
||||
event: int
|
||||
allowed_events: list[KeyEvent]
|
||||
|
||||
def __init__(self, allowed_events: list[int]):
|
||||
self.allowed_events = allowed_events
|
||||
self.previous_event = KeyEvent.NO_EVENT
|
||||
self.event = KeyEvent.NO_EVENT
|
||||
|
||||
def _validate_next_event(self, event: int):
|
||||
if event is None or event not in self.allowed_events:
|
||||
raise Exception(
|
||||
f"KeyEvent with value of {event} is not a valid event for this type of key")
|
||||
|
||||
def _set_event(self, next: 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:
|
||||
return False
|
||||
self.event = next
|
||||
return True
|
||||
|
||||
def handle(self, keyboard):
|
||||
raise NotImplementedError()
|
||||
|
||||
def self_test(self, keymap: list[list[object]]):
|
||||
raise NotImplementedError()
|
||||
|
||||
def debounce(self):
|
||||
def soft_release(self, keyboard, pin):
|
||||
"""Release key programatically and wait until it's released physically before registrating additional key presses"""
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
@@ -63,16 +71,23 @@ class KeycodeBase(KeyBase):
|
||||
|
||||
def __init__(self, keycode: int):
|
||||
allowed_events = [KeyEvent.NO_EVENT,
|
||||
KeyEvent.PRESSED_, KeyEvent.RELEASED]
|
||||
KeyEvent.PRESSED_,
|
||||
KeyEvent.RELEASED,
|
||||
KeyEvent.SOFT_RELEASED]
|
||||
super().__init__(allowed_events)
|
||||
self.keycode = keycode
|
||||
|
||||
def self_test(self, keymap):
|
||||
raise NotImplementedError
|
||||
|
||||
def _consume_next_event(self, pin) -> int:
|
||||
def soft_release(self, keyboard, pin):
|
||||
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.previous_event)
|
||||
previous = int(self.event)
|
||||
next = None
|
||||
if previous == KeyEvent.NO_EVENT:
|
||||
if pin_event == PinEvent.NO_EVENT:
|
||||
@@ -95,23 +110,30 @@ class KeycodeBase(KeyBase):
|
||||
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
|
||||
|
||||
self._validate_next_event(next)
|
||||
return self._set_event(next)
|
||||
|
||||
self.previous_event = next
|
||||
return next
|
||||
|
||||
def _react_to_event(self, event: int, keyboard) -> None:
|
||||
if event == KeyEvent.NO_EVENT:
|
||||
def _handle_event(self, keyboard) -> None:
|
||||
if self.event == KeyEvent.NO_EVENT:
|
||||
return
|
||||
if event == KeyEvent.PRESSED_:
|
||||
if self.event == KeyEvent.PRESSED_:
|
||||
keyboard.add_keycode_to_report(self.keycode)
|
||||
if event == KeyEvent.RELEASED:
|
||||
if self.event == KeyEvent.RELEASED:
|
||||
keyboard.remove_keycode_from_report(self.keycode)
|
||||
if self.event == KeyEvent.SOFT_RELEASED:
|
||||
keyboard.remove_keycode_from_report(self.keycode)
|
||||
|
||||
def handle(self, keyboard, pin):
|
||||
event = self._consume_next_event(pin)
|
||||
self._react_to_event(event, keyboard)
|
||||
if not self._consume_next_event(pin):
|
||||
return
|
||||
self._handle_event(keyboard)
|
||||
|
||||
|
||||
class Keycode(KeycodeBase):
|
||||
@@ -142,24 +164,90 @@ class LayerKeyBase(KeyBase):
|
||||
|
||||
class Toggle(LayerKeyBase):
|
||||
def __init__(self, layer: int):
|
||||
allowed_events = []
|
||||
allowed_events = [
|
||||
KeyEvent.NO_EVENT,
|
||||
KeyEvent.PRESSED_TOGGLED_ON,
|
||||
KeyEvent.RELEASED_TOGGLED_ON,
|
||||
KeyEvent.PRESSED_TOGGLED_OFF,
|
||||
KeyEvent.RELEASED,
|
||||
KeyEvent.SOFT_RELEASED]
|
||||
super().__init__(layer, allowed_events)
|
||||
|
||||
def _consume_next_state(self, pin: Pin) -> KeyEvents:
|
||||
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}")
|
||||
|
||||
if previous == KeyEvent.NO_EVENT:
|
||||
if next_pin_event == PinEvent.NO_EVENT:
|
||||
pass
|
||||
next = KeyEvent.NO_EVENT
|
||||
if next_pin_event == PinEvent.PRESSED:
|
||||
pass
|
||||
next = KeyEvent.PRESSED_TOGGLED_ON
|
||||
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
|
||||
if next_pin_event == PinEvent.PRESSED:
|
||||
next = KeyEvent.NO_EVENT
|
||||
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
|
||||
if next_pin_event == PinEvent.PRESSED:
|
||||
next = KeyEvent.PRESSED_TOGGLED_OFF
|
||||
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
|
||||
if next_pin_event == PinEvent.PRESSED:
|
||||
next = KeyEvent.NO_EVENT
|
||||
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
|
||||
if next_pin_event == PinEvent.RELEASED:
|
||||
next = KeyEvent.NO_EVENT
|
||||
|
||||
return self._set_event(next)
|
||||
|
||||
def _release_all_other_keys(self, keyboard, pin: Pin):
|
||||
for layer in keyboard.keymap:
|
||||
for key in layer:
|
||||
if key is self:
|
||||
continue
|
||||
pin_of_key = keyboard.pins[layer.index(key)]
|
||||
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)
|
||||
self._release_all_other_keys(keyboard, pin)
|
||||
if self.event == KeyEvent.RELEASED_TOGGLED_ON:
|
||||
pass
|
||||
if self.event == KeyEvent.PRESSED_TOGGLED_OFF:
|
||||
keyboard.layer.release_toggled(self.layer)
|
||||
if self.event == KeyEvent.RELEASED:
|
||||
pass
|
||||
|
||||
def handle(self, keyboard):
|
||||
raise NotImplementedError()
|
||||
def handle(self, keyboard, pin: Pin):
|
||||
if not self._consume_next_event(pin):
|
||||
return
|
||||
self._handle_event(keyboard, pin)
|
||||
|
||||
def self_test(self, keymap: list[list[object]]):
|
||||
raise NotImplementedError()
|
||||
|
||||
def soft_release(self, keyboard, pin):
|
||||
pass
|
||||
|
||||
# todo: Release all keys not the same as the old layer
|
||||
# todo: Debounce old toggle when pressing new toggle
|
||||
# if type(key) is Toggle:
|
||||
@@ -198,9 +286,12 @@ class Toggle(LayerKeyBase):
|
||||
|
||||
class Hold(LayerKeyBase):
|
||||
def __init__(self, layer: int):
|
||||
allowed_events = []
|
||||
allowed_events = [KeyEvent.SOFT_RELEASED]
|
||||
super().__init__(layer, allowed_events)
|
||||
|
||||
def soft_release(self, keyboard, pin):
|
||||
pass
|
||||
|
||||
# todo: Release all keys not the same as the old layer
|
||||
# if type(key) is Hold:
|
||||
# if not currentlyPressed and previouslyDebounced:
|
||||
|
||||
Reference in New Issue
Block a user