started breaking out keys

This commit is contained in:
2022-01-06 14:17:12 +01:00
parent 38c5b6e78b
commit 5476f0cd55
7 changed files with 263 additions and 144 deletions

0
.gitignore vendored Normal file → Executable file
View File

0
code.py Executable file → Normal file
View File

0
config.py Executable file → Normal file
View File

31
keyboard.py Executable file → Normal file
View File

@@ -185,8 +185,8 @@ class Keyboard:
while True: while True:
for pin in self.pins: for pin in self.pins:
pin_index = self.pins.index(pin) pin_index = self.pins.index(pin)
keycode = self.keymap[self.held_layer if self.held_layer != key = self.keymap[self.held_layer if self.held_layer !=
None else self.toggled_layer][pin_index] None else self.toggled_layer][pin_index]
previousValue = self.pin_states_last_cycle[pin_index][0] previousValue = self.pin_states_last_cycle[pin_index][0]
value = pin.value value = pin.value
currentlyPressed = value == __PRESSED currentlyPressed = value == __PRESSED
@@ -195,41 +195,43 @@ class Keyboard:
previouslyToggledReleased = previousValue == __TOGGLED_RELEASED previouslyToggledReleased = previousValue == __TOGGLED_RELEASED
previouslyUntoggledPressed = previousValue == __UNTOGGLED_PRESSED previouslyUntoggledPressed = previousValue == __UNTOGGLED_PRESSED
previouslyDebounced = previousValue == __DEBOUNCE previouslyDebounced = previousValue == __DEBOUNCE
if not isinstance(keycode, LayerKey): if not isinstance(key, LayerKey):
if currentlyPressed: if currentlyPressed:
if not previouslyPressed: if not previouslyPressed:
self.pressed_keys.add(keycode) self.pressed_keys.add(key.keycode)
else: else:
if previouslyPressed: if previouslyPressed:
try: try:
self.pressed_keys.remove(keycode) self.pressed_keys.remove(key.keycode)
# Catch silenly if same keycode is pressed twice then released # Catch silenly if same keycode is pressed twice then released
except KeyError: except KeyError:
pass pass
self.pin_states_last_cycle[pin_index] = (value,) self.pin_states_last_cycle[pin_index] = (value,)
continue continue
# TODO: Always release old key when entering new layer # todo: Release all keys not the same as the old layer
if type(keycode) is Hold: if type(key) is Hold:
if not currentlyPressed and previouslyDebounced: if not currentlyPressed and previouslyDebounced:
self.pin_states_last_cycle[pin_index] = ( self.pin_states_last_cycle[pin_index] = (
__UNPRESSED,) __UNPRESSED,)
if currentlyPressed and not previouslyPressed and not previouslyDebounced: if currentlyPressed and not previouslyPressed and not previouslyDebounced:
self.held_layer = keycode.layer self.held_layer = key.layer
self.pin_states_last_cycle[pin_index] = ( self.pin_states_last_cycle[pin_index] = (
__PRESSED, keycode) __PRESSED, key)
continue continue
if previouslyPressed and not currentlyPressed: if previouslyPressed and not currentlyPressed:
self.held_layer = None self.held_layer = None
self.pin_states_last_cycle[pin_index] = ( self.pin_states_last_cycle[pin_index] = (
__UNPRESSED,) __UNPRESSED,)
continue continue
if type(keycode) is Toggle: # todo: Release all keys not the same as the old layer
# todo: Debounce old toggle when pressing new toggle
if type(key) is Toggle:
if currentlyPressed and not previouslyToggled and not previouslyToggledReleased and not previouslyUntoggledPressed: if currentlyPressed and not previouslyToggled and not previouslyToggledReleased and not previouslyUntoggledPressed:
self.toggled_layer = keycode.layer self.toggled_layer = key.layer
self.held_layer = None self.held_layer = None
self.pin_states_last_cycle[pin_index] = ( self.pin_states_last_cycle[pin_index] = (
__TOGGLED_PRESSED, keycode) __TOGGLED_PRESSED, key)
for i in range(len(self.pin_states_last_cycle)): for i in range(len(self.pin_states_last_cycle)):
if i == pin_index or len(self.pin_states_last_cycle[i]) == 1: if i == pin_index or len(self.pin_states_last_cycle[i]) == 1:
continue continue
@@ -244,12 +246,12 @@ class Keyboard:
continue continue
if not currentlyPressed and previouslyToggled: if not currentlyPressed and previouslyToggled:
self.pin_states_last_cycle[pin_index] = ( self.pin_states_last_cycle[pin_index] = (
__TOGGLED_RELEASED, keycode) __TOGGLED_RELEASED, key)
continue continue
if currentlyPressed and previouslyToggledReleased: if currentlyPressed and previouslyToggledReleased:
self.toggled_layer = 0 self.toggled_layer = 0
self.pin_states_last_cycle[pin_index] = ( self.pin_states_last_cycle[pin_index] = (
__UNTOGGLED_PRESSED, keycode) __UNTOGGLED_PRESSED, key)
continue continue
if not currentlyPressed and previouslyUntoggledPressed: if not currentlyPressed and previouslyUntoggledPressed:
self.pin_states_last_cycle[pin_index] = ( self.pin_states_last_cycle[pin_index] = (
@@ -272,6 +274,7 @@ class Keyboard:
self.led.indicate_boot() self.led.indicate_boot()
self.start() self.start()
# todo: add boot mode
def send_nkro_report(self): def send_nkro_report(self):
"""Sends the USB HID NKRO keyboard report.""" """Sends the USB HID NKRO keyboard report."""

View File

@@ -1,144 +1,147 @@
from micropython import const from micropython import const
from keytypes import Keycode, Modifier
class SE: class SE:
# Letters # Letters
A = const(4) A = Keycode(const(4))
B = const(5) B = Keycode(const(5))
C = const(6) C = Keycode(const(6))
D = const(7) D = Keycode(const(7))
E = const(8) E = Keycode(const(8))
F = const(9) F = Keycode(const(9))
G = const(10) G = Keycode(const(10))
H = const(11) H = Keycode(const(11))
I = const(12) I = Keycode(const(12))
J = const(13) J = Keycode(const(13))
K = const(14) K = Keycode(const(14))
L = const(15) L = Keycode(const(15))
M = const(16) M = Keycode(const(16))
N = const(17) N = Keycode(const(17))
O = const(18) O = Keycode(const(18))
P = const(19) P = Keycode(const(19))
Q = const(20) Q = Keycode(const(20))
R = const(21) R = Keycode(const(21))
S = const(22) S = Keycode(const(22))
T = const(23) T = Keycode(const(23))
U = const(24) U = Keycode(const(24))
V = const(25) V = Keycode(const(25))
W = const(26) W = Keycode(const(26))
X = const(27) X = Keycode(const(27))
Y = const(28) Y = Keycode(const(28))
Z = const(29) Z = Keycode(const(29))
Å = const(47) Å = Keycode(const(47))
Ä = const(52) Ä = Keycode(const(52))
Ö = const(51) Ö = Keycode(const(51))
# Numbers # Numbers
ZERO = const(39) ZERO = Keycode(const(39))
ONE = const(30) ONE = Keycode(const(30))
TWO = const(31) TWO = Keycode(const(31))
THREE = const(32) THREE = Keycode(const(32))
FOUR = const(33) FOUR = Keycode(const(33))
FIVE = const(34) FIVE = Keycode(const(34))
SIX = const(35) SIX = Keycode(const(35))
SEVEN = const(36) SEVEN = Keycode(const(36))
EIGHT = const(37) EIGHT = Keycode(const(37))
NINE = const(38) NINE = Keycode(const(38))
# Signs # Signs
HYPHEN = const(56) # - and _ HYPHEN = Keycode(const(56)) # - and _
DOT = const(55) # . and : DOT = Keycode(const(55)) # . and :
COMMA = const(54) # , and ; COMMA = Keycode(const(54)) # , and ;
PARAGRAPH = const(53) # § and ½ PARAGRAPH = Keycode(const(53)) # § and ½
QUOTE = const(49) # ' and * QUOTE = Keycode(const(49)) # ' and *
UMLAUT = const(48) # ¨ and ~ UMLAUT = Keycode(const(48)) # ¨ and ~
TICK = const(46) # ´ and ` TICK = Keycode(const(46)) # ´ and `
PLUS = const(45) # + and ? PLUS = Keycode(const(45)) # + and ?
EQUAL = const(103) # = EQUAL = Keycode(const(103)) # =
ANGLE_BRACKET = const(100) # < and > ANGLE_BRACKET = Keycode(const(100)) # < and >
# Function keys # Function keys
F1 = const(58) F1 = Keycode(const(58))
F2 = const(59) F2 = Keycode(const(59))
F3 = const(60) F3 = Keycode(const(60))
F4 = const(61) F4 = Keycode(const(61))
F5 = const(62) F5 = Keycode(const(62))
F6 = const(63) F6 = Keycode(const(63))
F7 = const(64) F7 = Keycode(const(64))
F8 = const(65) F8 = Keycode(const(65))
F9 = const(66) F9 = Keycode(const(66))
F10 = const(67) F10 = Keycode(const(67))
F11 = const(68) F11 = Keycode(const(68))
F12 = const(69) F12 = Keycode(const(69))
PRINTSCREEN = const(70) PRINTSCREEN = Keycode(const(70))
CAPSLOCK = const(57) CAPSLOCK = Keycode(const(57))
ESCAPE = const(41) ESCAPE = Keycode(const(41))
SCROLLLOCK = const(71) SCROLLLOCK = Keycode(const(71))
PAUSEBREAK = const(72) PAUSEBREAK = Keycode(const(72))
INSERT = const(73) INSERT = Keycode(const(73))
MENU = const(101) MENU = Keycode(const(101))
# Function keys tested in gnome # Function keys tested in gnome
TOUCHPAD_TOGGLE = const(112) TOUCHPAD_TOGGLE = Keycode(const(112))
TOUCHPAD_ON = const(113) TOUCHPAD_ON = Keycode(const(113))
TOUCHPAD_OFF = const(114) TOUCHPAD_OFF = Keycode(const(114))
MIC_MUTE = const(111) MIC_MUTE = Keycode(const(111))
POWER = const(102) POWER = Keycode(const(102))
SETTINGS = const(104) SETTINGS = Keycode(const(104))
HELP = const(117) HELP = Keycode(const(117))
# Spacing # Spacing
TAB = const(43) TAB = Keycode(const(43))
SPACE = const(44) SPACE = Keycode(const(44))
ENTER = const(40) ENTER = Keycode(const(40))
# Navigation # Navigation
BACKSPACE = const(42) BACKSPACE = Keycode(const(42))
DELETE = const(76) DELETE = Keycode(const(76))
HOME = const(74) HOME = Keycode(const(74))
END = const(77) END = Keycode(const(77))
PAGEUP = const(75) PAGEUP = Keycode(const(75))
PAGEDOWN = const(78) PAGEDOWN = Keycode(const(78))
RIGHT = const(79) RIGHT = Keycode(const(79))
LEFT = const(80) LEFT = Keycode(const(80))
UP = const(81) UP = Keycode(const(81))
DOWN = const(82) DOWN = Keycode(const(82))
# Modifiers # Modifiers
LEFT_CTRL = const(0x0100) LEFT_CTRL = Modifier(const(0x0100))
LEFT_SHIFT = const(0x0200) LEFT_SHIFT = Modifier(const(0x0200))
LEFT_ALT = const(0x0400) LEFT_ALT = Modifier(const(0x0400))
LEFT_SUPER = const(0x0800) LEFT_SUPER = Modifier(const(0x0800))
RIGHT_CTRL = const(0x1000) RIGHT_CTRL = Modifier(const(0x1000))
RIGHT_SHIFT = const(0x2000) RIGHT_SHIFT = Modifier(const(0x2000))
RIGHT_ALT = const(0x4000) RIGHT_ALT = Modifier(const(0x4000))
# Others # Others
XF86_LAUNCH_5 = const(105) XF86_LAUNCH_5 = Keycode(const(105))
XF86_LAUNCH_6 = const(106) XF86_LAUNCH_6 = Keycode(const(106))
XF86_LAUNCH_7 = const(107) XF86_LAUNCH_7 = Keycode(const(107))
XF86_LAUNCH_8 = const(108) XF86_LAUNCH_8 = Keycode(const(108))
XF86_LAUNCH_9 = const(109) XF86_LAUNCH_9 = Keycode(const(109))
XF86_OPEN = const(116) XF86_OPEN = Keycode(const(116))
SUN_FRONT = const(119) SUN_FRONT = Keycode(const(119))
SUN_PROPS = const(118) SUN_PROPS = Keycode(const(118))
# Numpad # Numpad
NUM_DOT = const(99) NUM_DOT = Keycode(const(99))
NUM_0 = const(98) NUM_0 = Keycode(const(98))
NUM_1 = const(89) NUM_1 = Keycode(const(89))
NUM_2 = const(90) NUM_2 = Keycode(const(90))
NUM_3 = const(91) NUM_3 = Keycode(const(91))
NUM_4 = const(92) NUM_4 = Keycode(const(92))
NUM_5 = const(93) NUM_5 = Keycode(const(93))
NUM_6 = const(94) NUM_6 = Keycode(const(94))
NUM_7 = const(95) NUM_7 = Keycode(const(95))
NUM_8 = const(96) NUM_8 = Keycode(const(96))
NUM_9 = const(97) NUM_9 = Keycode(const(97))
NUM_ENTER = const(88) NUM_ENTER = Keycode(const(88))
NUM_PLUS = const(87) # + NUM_PLUS = Keycode(const(87)) # +
NUM_MINUS = const(86) # - NUM_MINUS = Keycode(const(86)) # -
NUM_ASTERISK = const(85) # * NUM_ASTERISK = Keycode(const(85)) # *
NUM_SLASH = const(84) # / NUM_SLASH = Keycode(const(84)) # /
NUMLOCK = const(83) NUMLOCK = Keycode(const(83))
# Need fix # Need fix
#SE_MUTE = const(-226) # Mute # SE_MUTE = const(-226) # Mute
#SE_VU = const(-233) # Volume up # SE_VU = const(-233) # Volume up
#SE_VD = const(-234) # Volume down # SE_VD = const(-234) # Volume down
# #
#SE_RR = const(-179) # Rewind # SE_RR = const(-179) # Rewind
#SE_FF = const(-180) # Fast forward # SE_FF = const(-180) # Fast forward
#SE_NT = const(-181) # Next track # SE_NT = const(-181) # Next track
#SE_PT = const(-182) # Prev track # SE_PT = const(-182) # Prev track
#SE_ST = const(-183) # Stop track # SE_ST = const(-183) # Stop track
#SE_PP = const(-205) # Play/pause # SE_PP = const(-205) # Play/pause

View File

@@ -1,8 +1,121 @@
from keyboard import Keyboard
from micropython import const
class LayerKey:
class KeyState:
"""Interpretations of hardware pin state"""
PRESSED = const(0)
"""Key is pressed"""
UNPRESSED = const(1)
"""Key is not pressed"""
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)
"""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)
"""Key is pressed and is emulating a toggle key in OFF state"""
DEBOUNCE = const(5)
"""Further state changes of any kind are ignored until key has been physically released released"""
class KeyEvent:
"""Interpretations of KeyStates as single events"""
NONE: int = const(0)
"""No new event has occurred"""
PRESSED: int = const(1)
"""The key was pressed"""
RELEASED: int = const(2)
"""The key was released"""
SOFT_RELEASE: int = const(3)
"""The key was released programatically, and not by an actual physical release of a button."""
class Key:
index: int
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 Keycode(Key):
keycode: int
def __init__(self, keycode: int):
super().__init__()
self.keycode = keycode
def __interpret_hardware_changes(self, keyboard: Keyboard) -> tuple[KeyState, KeyState]:
"""Interprets the changes to hardware pins as current and previous KeyState"""
current = keyboard.pins[self.index].value
previous = self.pin_states_last_cycle[self.index][0]
return (current, previous)
def __interpret_event(self, states: tuple[KeyState, KeyState]) -> KeyEvent:
"""Interprets the current and previous KeyState as a KeyEvent"""
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
else:
raise NotImplementedError()
def react(self, keyboard: Keyboard, event: KeyEvent) -> None:
if event == KeyEvent.NONE:
return
if event == KeyEvent.PRESSED:
keyboard.pressed_keys.add(self.keycode)
if event == KeyEvent.RELEASED:
try:
keyboard.pressed_keys.remove(self.keycode)
except KeyError:
# silently pass errors when same keycode has been issued twice
pass
keyboard.pin_states_last_cycle[self.index] = ()
def handle(self, keyboard):
super().handle()
states = self.__interpret_hardware_changes(keyboard)
event = self.__interpret_event(states)
self.react(keyboard, event)
if not isinstance(key, LayerKey):
if currentlyPressed:
if not previouslyPressed:
self.pressed_keys.add(key.keycode)
else:
if previouslyPressed:
try:
self.pressed_keys.remove(key.keycode)
# Catch silenly if same keycode is pressed twice then released
except KeyError:
pass
self.pin_states_last_cycle[pin_index] = (value,)
class Modifier(Keycode):
def __init__(self, keycode: int):
super().__init__(keycode)
class LayerKey(Key):
layer: int layer: int
def __init__(self, layer: int): def __init__(self, layer: int):
super().__init__()
self.layer = layer self.layer = layer

0
tests.py Executable file → Normal file
View File