added hold function key
This commit is contained in:
34
keyboard.py
34
keyboard.py
@@ -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
|
||||
#
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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),
|
||||
|
||||
129
keytypes.py
129
keytypes.py
@@ -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()
|
||||
|
||||
34
tests.py
34
tests.py
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user