added hold function key

This commit is contained in:
2022-01-12 18:21:56 +01:00
parent e8a5f7a4b6
commit 260d9a3483
5 changed files with 107 additions and 99 deletions

View File

@@ -97,9 +97,12 @@ class LayerState:
def hold(self, held):
self.held = held
def released_held(self):
def release_held(self):
self.held = self._NO_HELD_LAYER
def is_held(self):
return self.held is not self._NO_HELD_LAYER
class Keyboard:
debug_repl: bool
@@ -215,8 +218,6 @@ class Keyboard:
for pin in self.pins:
layer = self.layer.get()
key = self.keymap[layer][pin.index]
if type(key) is Hold:
continue
key.handle(self, pin)
layer = self.layer.get()
if len(self.layer_colors) >= (layer + 1):
@@ -261,30 +262,3 @@ class Keyboard:
if code & 0x00ff:
report_bitmap[code >> 3] |= 1 << (code & 0x7)
self.keyboard_device.send_report(report)
# Create interface for key of different type
# interface has method to handle keypress and release and gets access to key keyboards state and keyboard instance
# keyboard state should be increased with layer
# layer keys take a type, a set layer, and a color combination
# class LayerKeyType(Enum):
# hold = 1
# toggle = 2
# def handle_key(raw_keymap:list[list]]):
# for row in raw_keymap:
# for key in row:
# if key in Keycode:
# # handle as keycode
# pass
# if key.
# class LayerKey:
# type: LayerKeyType
# def __init__(self, type: LayerKeyType, layer: int):
# class KeycodeKey:
# def __init__(self):
# pass
#

View File

@@ -95,8 +95,8 @@ class SE:
PAGEDOWN = const(78)
RIGHT = const(79)
LEFT = const(80)
UP = const(81)
DOWN = const(82)
UP = const(82)
DOWN = const(81)
# Modifiers
LEFT_CTRL = const(0x0100)
LEFT_SHIFT = const(0x0200)

View File

@@ -7,8 +7,9 @@ lm = LayerManager(5)
keymap = [[
lm.hold(1), lm.toggle(2), lm.toggle(3), lm.toggle(4),
lm.toggle(0), Keycode(SE.B), Keycode(SE.C), Keycode(SE.D),
Keycode(SE.E), Keycode(SE.F), Keycode(SE.G), Keycode(SE.H),
Keycode(SE.I), Keycode(SE.J), Keycode(
Keycode(SE.LEFT), Keycode(SE.DOWN), Keycode(
SE.UP), Keycode(SE.RIGHT),
Keycode(SE.ENTER), Keycode(SE.J), Keycode(
SE.K), Modifier(SE.LEFT_SHIFT)
], [
lm.hold(1), lm.toggle(2), lm.toggle(3), lm.toggle(4),

View File

@@ -23,6 +23,24 @@ class KeyEvent:
"""Key is pressed and is emulating a toggle key in OFF state"""
def _event_to_string(event: int) -> str:
if event == KeyEvent.NO_EVENT:
return "NO EVENT"
if event == KeyEvent.PRESSED_:
return "PRESSED"
if event == KeyEvent.RELEASED:
return "RELEASED"
if event == KeyEvent.SOFT_RELEASED:
return "SOFT_RELEASED"
if event == KeyEvent.PRESSED_TOGGLED_ON:
return "PRESSED TOGGLED ON"
if event == KeyEvent.RELEASED_TOGGLED_ON:
return "RELEASED TOGGLED ON"
if event == KeyEvent.PRESSED_TOGGLED_OFF:
return "PRESSED TOGGLED OFF"
raise NotImplementedError()
class KeyEvents:
current: int
previous: int
@@ -64,7 +82,7 @@ class KeyBase:
if next_event is KeyEvent.NO_EVENT:
return False
print(
f"[{self.key_index}] next: {next_event}, current: {self.events.current}, previous: {self.events.previous}")
f"[{self.key_index}] next: {_event_to_string(next_event)}, current: {_event_to_string(self.events.current)}, previous: {_event_to_string(self.events.previous)}")
self.events.shift(next_event)
return True
@@ -177,6 +195,27 @@ class LayerKeyBase(KeyBase):
super().__init__(allowed_events)
self.layer_to_switch_to = layer
def self_test(self, keymap: list[list[KeyBase]]):
key_on_layer_to_switch_to = keymap[self.layer_to_switch_to][self.key_index]
if key_on_layer_to_switch_to is self:
return
raise Exception(
f"Toggle layer key must have an identical Toggle layer key on layer[{self.layer_to_switch_to}] key[{self.key_index}]")
def _release_all_other_keys(self, keyboard):
for layer in keyboard.keymap:
for key in layer:
if key is self:
continue
key.soft_release(keyboard)
def _release_all_other_non_toggle_keys(self, keyboard):
for layer in keyboard.keymap:
for key in layer:
if key is self or isinstance(key, Toggle):
continue
key.soft_release(keyboard)
class Toggle(LayerKeyBase):
def __init__(self, layer: int):
@@ -233,13 +272,6 @@ class Toggle(LayerKeyBase):
raise NotImplementedError()
def _release_all_other_keys(self, keyboard):
for layer in keyboard.keymap:
for key in layer:
if key is self:
continue
key.soft_release(keyboard)
def _handle_event(self, keyboard, pin):
current = self.events.current
if current == KeyEvent.PRESSED_TOGGLED_ON:
@@ -262,16 +294,12 @@ class Toggle(LayerKeyBase):
return
self._handle_event(keyboard, pin)
def self_test(self, keymap: list[list[KeyBase]]):
key_on_layer_to_switch_to = keymap[self.layer_to_switch_to][self.key_index]
if key_on_layer_to_switch_to is self:
return
raise Exception(
f"Toggle layer key must have an identical Toggle layer key on layer[{self.layer_to_switch_to}] key[{self.key_index}]")
def soft_release(self, keyboard):
pressed = self.events.current not in [
KeyEvent.RELEASED, KeyEvent.PRESSED_TOGGLED_OFF, KeyEvent.SOFT_RELEASED]
KeyEvent.RELEASED,
KeyEvent.PRESSED_TOGGLED_OFF,
KeyEvent.SOFT_RELEASED
]
if not pressed:
return
self._set_event(KeyEvent.SOFT_RELEASED)
@@ -279,26 +307,57 @@ class Toggle(LayerKeyBase):
class Hold(LayerKeyBase):
def __init__(self, layer: int):
allowed_events = [KeyEvent.SOFT_RELEASED]
allowed_events = [KeyEvent.NO_EVENT,
KeyEvent.SOFT_RELEASED,
KeyEvent.PRESSED_, KeyEvent.RELEASED]
super().__init__(layer, allowed_events)
def soft_release(self, keyboard):
pass
if self.events.current != KeyEvent.PRESSED_:
return
keyboard.layer.release_held()
# todo: Release all keys not the same as the old layer
# if type(key) is Hold:
# if not currentlyPressed and previouslyDebounced:
# self.pin_states_last_cycle[pin_index] = (
# __UNPRESSED,)
#
# if currentlyPressed and not previouslyPressed and not previouslyDebounced:
# self.held_layer = key.layer
# self.pin_states_last_cycle[pin_index] = (
# __PRESSED, key)
# continue
# if previouslyPressed and not currentlyPressed:
# self.held_layer = None
# self.pin_states_last_cycle[pin_index] = (
# __UNPRESSED,)
# continue
#
def handle(self, keyboard, pin):
if not self._consume_next_event(pin):
return
self._handle_event(keyboard)
def _consume_next_event(self, pin: Pin) -> bool:
next_pin_event = pin.read_event()
current_key_event, previous_key_event = self.events.current, self.events.previous
# handle soft release
if current_key_event == KeyEvent.SOFT_RELEASED:
if previous_key_event == KeyEvent.RELEASED:
return self._set_event(KeyEvent.RELEASED)
if next_pin_event == PinEvent.RELEASED:
return self._set_event(KeyEvent.RELEASED)
return self._set_event(KeyEvent.NO_EVENT)
# handle no-event's
if next_pin_event == PinEvent.NO_EVENT:
return self._set_event(KeyEvent.NO_EVENT)
# handle events
if current_key_event == KeyEvent.RELEASED:
if next_pin_event == PinEvent.PRESSED:
return self._set_event(KeyEvent.PRESSED_)
return self._set_event(KeyEvent.NO_EVENT)
if current_key_event == KeyEvent.PRESSED_:
if next_pin_event == PinEvent.RELEASED:
return self._set_event(KeyEvent.RELEASED)
return self._set_event(KeyEvent.NO_EVENT)
def _handle_event(self, keyboard):
current = self.events.current
if current == KeyEvent.PRESSED_:
keyboard.layer.hold(self.layer_to_switch_to)
self._release_all_other_non_toggle_keys(keyboard)
return
if current == KeyEvent.RELEASED:
keyboard.layer.release_held()
self._release_all_other_non_toggle_keys(keyboard)
return
raise NotImplementedError()

View File

@@ -6,35 +6,9 @@ def test_keymap(keymap: list[list], output: bool = False) -> None:
print("Testing keymap for errors")
for layer in keymap:
for key in layer:
if isinstance(key, Keycode) or isinstance(key, Modifier) or isinstance(key, Toggle):
print(
f"[{keymap.index(layer)}][{layer.index(key)}] {key.__class__.__name__}", end=": ")
key.self_test(keymap)
print("Valid")
continue
# if isinstance(key, Modifier):
# print(
# f"key is Modifier [{keymap.index(layer)}][{layer.index(key)}]", end=".. ")
# if key.keycode in valid_modifiers:
# print("and is valid")
# else:
# raise Exception()
# continue
# if isinstance(key, LayerKey):
# layer_key_name = key.__class__.__name__
# if output:
# print(
# f"key is {layer_key_name} [{keymap.index(layer)}][{layer.index(key)}]", end=".. ")
# key_on_layer_to_switch_to = keymap[key.layer][layer.index(key)]
# key_is_not_hold = type(
# key_on_layer_to_switch_to) is not type(key)
# hold_key_is_not_same_layer = type(
# key_on_layer_to_switch_to) is type(key) and key_on_layer_to_switch_to.layer != key.layer
# if key_is_not_hold or hold_key_is_not_same_layer:
# raise Exception(
# f"{layer_key_name} layer key on layer[{keymap.index(layer)}] key[{layer.index(key)}] must have an identical {layer_key_name} layer key on layer[{key.layer}] key[{layer.index(key)}]")
# else:
# if output:
# print("and is valid")
print(
f"[{keymap.index(layer)}][{layer.index(key)}] {key.__class__.__name__}", end=": ")
key.self_test(keymap)
print("Valid")
if output:
print("Done testing keymap")