continued to break out keys and pins
This commit is contained in:
31
config.py
31
config.py
@@ -3,6 +3,7 @@
|
||||
import board
|
||||
from keyboard import Hold, Toggle
|
||||
from keycodes import SE
|
||||
from keytypes import Keycode, Modifier
|
||||
|
||||
io_extenders_pinout = [(0x20, board.GP1, board.GP0)]
|
||||
|
||||
@@ -15,29 +16,29 @@ pinout: tuple[int, int] = [
|
||||
|
||||
keymap = [[
|
||||
Hold(1), Toggle(2), Toggle(3), Toggle(4),
|
||||
Toggle(0), SE.B, SE.C, SE.D,
|
||||
SE.E, SE.F, SE.G, SE.H,
|
||||
SE.I, SE.J, SE.K, SE.L
|
||||
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(SE.K), Keycode(SE.L)
|
||||
], [
|
||||
Hold(1), Toggle(2), Toggle(3), Toggle(4),
|
||||
SE.ONE, Hold(1), SE.C, SE.D,
|
||||
SE.E, SE.F, SE.G, SE.H,
|
||||
SE.BACKSPACE, SE.J, SE.K, SE.L
|
||||
Keycode(SE.ONE), Hold(1), Keycode(SE.C), Keycode(SE.D),
|
||||
Keycode(SE.E), Keycode(SE.F), Keycode(SE.G), Keycode(SE.H),
|
||||
Keycode(SE.BACKSPACE), Keycode(SE.J), Keycode(SE.K), Keycode(SE.L)
|
||||
], [
|
||||
Hold(1), Toggle(2), Toggle(3), Toggle(4),
|
||||
SE.A, Hold(1), Hold(2), SE.D,
|
||||
SE.E, SE.F, SE.G, SE.H,
|
||||
SE.I, SE.J, SE.K, SE.L
|
||||
Keycode(SE.A), Hold(1), Hold(2), Keycode(SE.D),
|
||||
Keycode(SE.E), Keycode(SE.F), Keycode(SE.G), Keycode(SE.H),
|
||||
Keycode(SE.I), Keycode(SE.J), Keycode(SE.K), Keycode(SE.L)
|
||||
], [
|
||||
Hold(1), Toggle(2), Toggle(3), Toggle(4),
|
||||
SE.A, SE.B, Hold(2), Hold(3),
|
||||
SE.E, SE.F, SE.G, SE.H,
|
||||
SE.I, SE.J, SE.K, SE.L
|
||||
Keycode(SE.A), Keycode(SE.B), Hold(2), Hold(3),
|
||||
Keycode(SE.E), Keycode(SE.F), Keycode(SE.G), Keycode(SE.H),
|
||||
Keycode(SE.I), Keycode(SE.J), Keycode(SE.K), Keycode(SE.L)
|
||||
], [
|
||||
Hold(1), Toggle(2), Toggle(3), Toggle(4),
|
||||
SE.A, SE.B, SE.C, Hold(3),
|
||||
SE.E, SE.F, SE.G, SE.H,
|
||||
SE.I, SE.J, SE.K, SE.LEFT_ALT
|
||||
Keycode(SE.A), Keycode(SE.B), Keycode(SE.C), Hold(3),
|
||||
Keycode(SE.E), Keycode(SE.F), Keycode(SE.G), Keycode(SE.H),
|
||||
Keycode(SE.I), Keycode(SE.J), Keycode(SE.K), Modifier(SE.LEFT_ALT)
|
||||
]]
|
||||
|
||||
layer_colors = [(255, 255, 255), (0, 255, 0), (0, 0, 255),
|
||||
|
||||
117
keyboard.py
117
keyboard.py
@@ -7,7 +7,7 @@ import usb_hid
|
||||
import pwmio
|
||||
import time
|
||||
from micropython import const
|
||||
from keytypes import LayerKey, Toggle, Hold
|
||||
from keytypes import Key, LayerKey, Pin, Toggle, Hold
|
||||
|
||||
|
||||
__RED = (255, 0, 0)
|
||||
@@ -92,10 +92,9 @@ class Keyboard:
|
||||
pressed_keys_last_cycle: set[int]
|
||||
pressed_keys: set[int]
|
||||
|
||||
pins: list[digitalio.DigitalInOut]
|
||||
pin_states_last_cycle: list[int]
|
||||
pins: list[Pin]
|
||||
|
||||
keymap: list[list[int]]
|
||||
keymap: list[list[Key]]
|
||||
|
||||
keyboard_device: usb_hid.Device
|
||||
led: RGBLED
|
||||
@@ -104,7 +103,7 @@ class Keyboard:
|
||||
self,
|
||||
io_extenders_pinout: list[tuple[int, int, int]],
|
||||
pinout: list[tuple[int, int]],
|
||||
keymap: list[list[int]],
|
||||
keymap: list[list[Key]],
|
||||
rgb_pins: tuple[int, int, int],
|
||||
layer_colors: list[tuple[int, int, int]],
|
||||
debug_repl: bool = False):
|
||||
@@ -158,105 +157,43 @@ class Keyboard:
|
||||
raise ValueError("No io extenders were initialized")
|
||||
return io_extenders
|
||||
|
||||
def initialize_pins(self, io_extenders: list[MCP23017], pinouts: list[tuple[int, int]]) -> list[DigitalInOut]:
|
||||
def initialize_pins(self, io_extenders: list[MCP23017], pinouts: list[tuple[int, int]]) -> list[Pin]:
|
||||
pins = []
|
||||
for pinout in pinouts:
|
||||
io_extender_index, pin_number = pinout
|
||||
io_extender = io_extenders[io_extender_index]
|
||||
pin_index = pinouts.index(pinout)
|
||||
pin = io_extender.get_pin(pin_number)
|
||||
pin.direction = digitalio.Direction.INPUT
|
||||
pin.pull = digitalio.Pull.UP
|
||||
pins.append(pin)
|
||||
pins.append(Pin(pin_index, pin))
|
||||
return pins
|
||||
|
||||
def _initialize_session_values(self):
|
||||
self.toggled_layer = 0
|
||||
self.held_layer = None
|
||||
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")
|
||||
try:
|
||||
self.toggled_layer = 0
|
||||
self.held_layer = None
|
||||
self.pressed_keys = set()
|
||||
self.pressed_keys_last_cycle = set()
|
||||
self.pin_states_last_cycle = []
|
||||
for pin in self.pins:
|
||||
self.pin_states_last_cycle.append((__UNPRESSED,))
|
||||
self._initialize_session_values()
|
||||
if self.debug_repl:
|
||||
print("Keyboard started")
|
||||
while True:
|
||||
for pin in self.pins:
|
||||
pin_index = self.pins.index(pin)
|
||||
key = self.keymap[self.held_layer if self.held_layer !=
|
||||
None else self.toggled_layer][pin_index]
|
||||
previousValue = self.pin_states_last_cycle[pin_index][0]
|
||||
value = pin.value
|
||||
currentlyPressed = value == __PRESSED
|
||||
previouslyPressed = previousValue == __PRESSED
|
||||
previouslyToggled = previousValue == __TOGGLED_PRESSED
|
||||
previouslyToggledReleased = previousValue == __TOGGLED_RELEASED
|
||||
previouslyUntoggledPressed = previousValue == __UNTOGGLED_PRESSED
|
||||
previouslyDebounced = previousValue == __DEBOUNCE
|
||||
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,)
|
||||
continue
|
||||
# todo: Release all keys not the same as the old layer
|
||||
layer = self._get_current_layer_index()
|
||||
key = self.keymap[layer][pin.index]
|
||||
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
|
||||
# todo: Release all keys not the same as the old layer
|
||||
# todo: Debounce old toggle when pressing new toggle
|
||||
continue
|
||||
if type(key) is Toggle:
|
||||
if currentlyPressed and not previouslyToggled and not previouslyToggledReleased and not previouslyUntoggledPressed:
|
||||
self.toggled_layer = key.layer
|
||||
self.held_layer = None
|
||||
self.pin_states_last_cycle[pin_index] = (
|
||||
__TOGGLED_PRESSED, key)
|
||||
for i in range(len(self.pin_states_last_cycle)):
|
||||
if i == pin_index or len(self.pin_states_last_cycle[i]) == 1:
|
||||
continue
|
||||
value, last_keycode = self.pin_states_last_cycle[i]
|
||||
if type(last_keycode) is Toggle:
|
||||
self.pin_states_last_cycle[i] = (
|
||||
__UNPRESSED,)
|
||||
if type(last_keycode) is Hold:
|
||||
self.held_layer = None
|
||||
self.pin_states_last_cycle[i] = (
|
||||
__DEBOUNCE,)
|
||||
continue
|
||||
if not currentlyPressed and previouslyToggled:
|
||||
self.pin_states_last_cycle[pin_index] = (
|
||||
__TOGGLED_RELEASED, key)
|
||||
continue
|
||||
if currentlyPressed and previouslyToggledReleased:
|
||||
self.toggled_layer = 0
|
||||
self.pin_states_last_cycle[pin_index] = (
|
||||
__UNTOGGLED_PRESSED, key)
|
||||
continue
|
||||
if not currentlyPressed and previouslyUntoggledPressed:
|
||||
self.pin_states_last_cycle[pin_index] = (
|
||||
__UNPRESSED,)
|
||||
continue
|
||||
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])
|
||||
@@ -274,6 +211,16 @@ class Keyboard:
|
||||
self.led.indicate_boot()
|
||||
self.start()
|
||||
|
||||
def add_keycode_to_report(self, keycode: int):
|
||||
self.pressed_keys.add(keycode)
|
||||
|
||||
def remove_keycode_from_report(self, keycode: int):
|
||||
try:
|
||||
self.pressed_keys.remove(keycode)
|
||||
except KeyError:
|
||||
# silently pass errors when same keycode has been issued twice
|
||||
pass
|
||||
|
||||
# todo: add boot mode
|
||||
def send_nkro_report(self):
|
||||
"""Sends the USB HID NKRO keyboard report."""
|
||||
|
||||
241
keycodes.py
241
keycodes.py
@@ -1,138 +1,137 @@
|
||||
from micropython import const
|
||||
from keytypes import Keycode, Modifier
|
||||
|
||||
|
||||
class SE:
|
||||
# Letters
|
||||
A = Keycode(const(4))
|
||||
B = Keycode(const(5))
|
||||
C = Keycode(const(6))
|
||||
D = Keycode(const(7))
|
||||
E = Keycode(const(8))
|
||||
F = Keycode(const(9))
|
||||
G = Keycode(const(10))
|
||||
H = Keycode(const(11))
|
||||
I = Keycode(const(12))
|
||||
J = Keycode(const(13))
|
||||
K = Keycode(const(14))
|
||||
L = Keycode(const(15))
|
||||
M = Keycode(const(16))
|
||||
N = Keycode(const(17))
|
||||
O = Keycode(const(18))
|
||||
P = Keycode(const(19))
|
||||
Q = Keycode(const(20))
|
||||
R = Keycode(const(21))
|
||||
S = Keycode(const(22))
|
||||
T = Keycode(const(23))
|
||||
U = Keycode(const(24))
|
||||
V = Keycode(const(25))
|
||||
W = Keycode(const(26))
|
||||
X = Keycode(const(27))
|
||||
Y = Keycode(const(28))
|
||||
Z = Keycode(const(29))
|
||||
Å = Keycode(const(47))
|
||||
Ä = Keycode(const(52))
|
||||
Ö = Keycode(const(51))
|
||||
A = const(4)
|
||||
B = const(5)
|
||||
C = const(6)
|
||||
D = const(7)
|
||||
E = const(8)
|
||||
F = const(9)
|
||||
G = const(10)
|
||||
H = const(11)
|
||||
I = const(12)
|
||||
J = const(13)
|
||||
K = const(14)
|
||||
L = const(15)
|
||||
M = const(16)
|
||||
N = const(17)
|
||||
O = const(18)
|
||||
P = const(19)
|
||||
Q = const(20)
|
||||
R = const(21)
|
||||
S = const(22)
|
||||
T = const(23)
|
||||
U = const(24)
|
||||
V = const(25)
|
||||
W = const(26)
|
||||
X = const(27)
|
||||
Y = const(28)
|
||||
Z = const(29)
|
||||
Å = const(47)
|
||||
Ä = const(52)
|
||||
Ö = const(51)
|
||||
# Numbers
|
||||
ZERO = Keycode(const(39))
|
||||
ONE = Keycode(const(30))
|
||||
TWO = Keycode(const(31))
|
||||
THREE = Keycode(const(32))
|
||||
FOUR = Keycode(const(33))
|
||||
FIVE = Keycode(const(34))
|
||||
SIX = Keycode(const(35))
|
||||
SEVEN = Keycode(const(36))
|
||||
EIGHT = Keycode(const(37))
|
||||
NINE = Keycode(const(38))
|
||||
ZERO = const(39)
|
||||
ONE = const(30)
|
||||
TWO = const(31)
|
||||
THREE = const(32)
|
||||
FOUR = const(33)
|
||||
FIVE = const(34)
|
||||
SIX = const(35)
|
||||
SEVEN = const(36)
|
||||
EIGHT = const(37)
|
||||
NINE = const(38)
|
||||
# Signs
|
||||
HYPHEN = Keycode(const(56)) # - and _
|
||||
DOT = Keycode(const(55)) # . and :
|
||||
COMMA = Keycode(const(54)) # , and ;
|
||||
PARAGRAPH = Keycode(const(53)) # § and ½
|
||||
QUOTE = Keycode(const(49)) # ' and *
|
||||
UMLAUT = Keycode(const(48)) # ¨ and ~
|
||||
TICK = Keycode(const(46)) # ´ and `
|
||||
PLUS = Keycode(const(45)) # + and ?
|
||||
EQUAL = Keycode(const(103)) # =
|
||||
ANGLE_BRACKET = Keycode(const(100)) # < and >
|
||||
HYPHEN = const(56) # - and _
|
||||
DOT = const(55) # . and :
|
||||
COMMA = const(54) # , and ;
|
||||
PARAGRAPH = const(53) # § and ½
|
||||
QUOTE = const(49) # ' and *
|
||||
UMLAUT = const(48) # ¨ and ~
|
||||
TICK = const(46) # ´ and `
|
||||
PLUS = const(45) # + and ?
|
||||
EQUAL = const(103) # =
|
||||
ANGLE_BRACKET = const(100) # < and >
|
||||
# Function keys
|
||||
F1 = Keycode(const(58))
|
||||
F2 = Keycode(const(59))
|
||||
F3 = Keycode(const(60))
|
||||
F4 = Keycode(const(61))
|
||||
F5 = Keycode(const(62))
|
||||
F6 = Keycode(const(63))
|
||||
F7 = Keycode(const(64))
|
||||
F8 = Keycode(const(65))
|
||||
F9 = Keycode(const(66))
|
||||
F10 = Keycode(const(67))
|
||||
F11 = Keycode(const(68))
|
||||
F12 = Keycode(const(69))
|
||||
PRINTSCREEN = Keycode(const(70))
|
||||
CAPSLOCK = Keycode(const(57))
|
||||
ESCAPE = Keycode(const(41))
|
||||
SCROLLLOCK = Keycode(const(71))
|
||||
PAUSEBREAK = Keycode(const(72))
|
||||
INSERT = Keycode(const(73))
|
||||
MENU = Keycode(const(101))
|
||||
F1 = const(58)
|
||||
F2 = const(59)
|
||||
F3 = const(60)
|
||||
F4 = const(61)
|
||||
F5 = const(62)
|
||||
F6 = const(63)
|
||||
F7 = const(64)
|
||||
F8 = const(65)
|
||||
F9 = const(66)
|
||||
F10 = const(67)
|
||||
F11 = const(68)
|
||||
F12 = const(69)
|
||||
PRINTSCREEN = const(70)
|
||||
CAPSLOCK = const(57)
|
||||
ESCAPE = const(41)
|
||||
SCROLLLOCK = const(71)
|
||||
PAUSEBREAK = const(72)
|
||||
INSERT = const(73)
|
||||
MENU = const(101)
|
||||
# Function keys tested in gnome
|
||||
TOUCHPAD_TOGGLE = Keycode(const(112))
|
||||
TOUCHPAD_ON = Keycode(const(113))
|
||||
TOUCHPAD_OFF = Keycode(const(114))
|
||||
MIC_MUTE = Keycode(const(111))
|
||||
POWER = Keycode(const(102))
|
||||
SETTINGS = Keycode(const(104))
|
||||
HELP = Keycode(const(117))
|
||||
TOUCHPAD_TOGGLE = const(112)
|
||||
TOUCHPAD_ON = const(113)
|
||||
TOUCHPAD_OFF = const(114)
|
||||
MIC_MUTE = const(111)
|
||||
POWER = const(102)
|
||||
SETTINGS = const(104)
|
||||
HELP = const(117)
|
||||
# Spacing
|
||||
TAB = Keycode(const(43))
|
||||
SPACE = Keycode(const(44))
|
||||
ENTER = Keycode(const(40))
|
||||
TAB = const(43)
|
||||
SPACE = const(44)
|
||||
ENTER = const(40)
|
||||
# Navigation
|
||||
BACKSPACE = Keycode(const(42))
|
||||
DELETE = Keycode(const(76))
|
||||
HOME = Keycode(const(74))
|
||||
END = Keycode(const(77))
|
||||
PAGEUP = Keycode(const(75))
|
||||
PAGEDOWN = Keycode(const(78))
|
||||
RIGHT = Keycode(const(79))
|
||||
LEFT = Keycode(const(80))
|
||||
UP = Keycode(const(81))
|
||||
DOWN = Keycode(const(82))
|
||||
BACKSPACE = const(42)
|
||||
DELETE = const(76)
|
||||
HOME = const(74)
|
||||
END = const(77)
|
||||
PAGEUP = const(75)
|
||||
PAGEDOWN = const(78)
|
||||
RIGHT = const(79)
|
||||
LEFT = const(80)
|
||||
UP = const(81)
|
||||
DOWN = const(82)
|
||||
# Modifiers
|
||||
LEFT_CTRL = Modifier(const(0x0100))
|
||||
LEFT_SHIFT = Modifier(const(0x0200))
|
||||
LEFT_ALT = Modifier(const(0x0400))
|
||||
LEFT_SUPER = Modifier(const(0x0800))
|
||||
RIGHT_CTRL = Modifier(const(0x1000))
|
||||
RIGHT_SHIFT = Modifier(const(0x2000))
|
||||
RIGHT_ALT = Modifier(const(0x4000))
|
||||
LEFT_CTRL = const(0x0100)
|
||||
LEFT_SHIFT = const(0x0200)
|
||||
LEFT_ALT = const(0x0400)
|
||||
LEFT_SUPER = const(0x0800)
|
||||
RIGHT_CTRL = const(0x1000)
|
||||
RIGHT_SHIFT = const(0x2000)
|
||||
RIGHT_ALT = const(0x4000)
|
||||
# Others
|
||||
XF86_LAUNCH_5 = Keycode(const(105))
|
||||
XF86_LAUNCH_6 = Keycode(const(106))
|
||||
XF86_LAUNCH_7 = Keycode(const(107))
|
||||
XF86_LAUNCH_8 = Keycode(const(108))
|
||||
XF86_LAUNCH_9 = Keycode(const(109))
|
||||
XF86_OPEN = Keycode(const(116))
|
||||
SUN_FRONT = Keycode(const(119))
|
||||
SUN_PROPS = Keycode(const(118))
|
||||
XF86_LAUNCH_5 = const(105)
|
||||
XF86_LAUNCH_6 = const(106)
|
||||
XF86_LAUNCH_7 = const(107)
|
||||
XF86_LAUNCH_8 = const(108)
|
||||
XF86_LAUNCH_9 = const(109)
|
||||
XF86_OPEN = const(116)
|
||||
SUN_FRONT = const(119)
|
||||
SUN_PROPS = const(118)
|
||||
# Numpad
|
||||
NUM_DOT = Keycode(const(99))
|
||||
NUM_0 = Keycode(const(98))
|
||||
NUM_1 = Keycode(const(89))
|
||||
NUM_2 = Keycode(const(90))
|
||||
NUM_3 = Keycode(const(91))
|
||||
NUM_4 = Keycode(const(92))
|
||||
NUM_5 = Keycode(const(93))
|
||||
NUM_6 = Keycode(const(94))
|
||||
NUM_7 = Keycode(const(95))
|
||||
NUM_8 = Keycode(const(96))
|
||||
NUM_9 = Keycode(const(97))
|
||||
NUM_ENTER = Keycode(const(88))
|
||||
NUM_PLUS = Keycode(const(87)) # +
|
||||
NUM_MINUS = Keycode(const(86)) # -
|
||||
NUM_ASTERISK = Keycode(const(85)) # *
|
||||
NUM_SLASH = Keycode(const(84)) # /
|
||||
NUMLOCK = Keycode(const(83))
|
||||
NUM_DOT = const(99)
|
||||
NUM_0 = const(98)
|
||||
NUM_1 = const(89)
|
||||
NUM_2 = const(90)
|
||||
NUM_3 = const(91)
|
||||
NUM_4 = const(92)
|
||||
NUM_5 = const(93)
|
||||
NUM_6 = const(94)
|
||||
NUM_7 = const(95)
|
||||
NUM_8 = const(96)
|
||||
NUM_9 = const(97)
|
||||
NUM_ENTER = const(88)
|
||||
NUM_PLUS = const(87) # +
|
||||
NUM_MINUS = const(86) # -
|
||||
NUM_ASTERISK = const(85) # *
|
||||
NUM_SLASH = const(84) # /
|
||||
NUMLOCK = const(83)
|
||||
|
||||
# Need fix
|
||||
# SE_MUTE = const(-226) # Mute
|
||||
|
||||
171
keytypes.py
171
keytypes.py
@@ -1,7 +1,18 @@
|
||||
from keyboard import Keyboard
|
||||
import digitalio
|
||||
from micropython import const
|
||||
|
||||
|
||||
class PinState:
|
||||
PRESSED: int = const(0)
|
||||
RELEASED: int = const(1)
|
||||
|
||||
|
||||
class PinEvent:
|
||||
NONE: int = const(0)
|
||||
PRESSED: int = const(1)
|
||||
RELEASED: int = const(2)
|
||||
|
||||
|
||||
class KeyState:
|
||||
"""Interpretations of hardware pin state"""
|
||||
PRESSED = const(0)
|
||||
@@ -22,7 +33,7 @@ class KeyEvent:
|
||||
"""Interpretations of KeyStates as single events"""
|
||||
NONE: int = const(0)
|
||||
"""No new event has occurred"""
|
||||
PRESSED: int = const(1)
|
||||
PRESSED = ""
|
||||
"""The key was pressed"""
|
||||
RELEASED: int = const(2)
|
||||
"""The key was released"""
|
||||
@@ -30,8 +41,48 @@ class KeyEvent:
|
||||
"""The key was released programatically, and not by an actual physical release of a button."""
|
||||
|
||||
|
||||
class PinStates:
|
||||
current: int
|
||||
previous: int
|
||||
|
||||
def __init__(self, current: int, previous: int):
|
||||
self.current = current
|
||||
self.previous = previous
|
||||
|
||||
|
||||
class Pin:
|
||||
index: int
|
||||
hw_pin: digitalio.DigitalInOut
|
||||
previous_state: int
|
||||
|
||||
def __init__(self, index, hw_pin: digitalio.DigitalInOut):
|
||||
self.index = index
|
||||
self.hw_pin = hw_pin
|
||||
self.previous_state = PinState.RELEASED
|
||||
|
||||
def _consume_next_state(self) -> PinStates:
|
||||
states = PinStates(int(self.hw_pin.value), int(self.previous_state))
|
||||
self.previous_state = states.current
|
||||
return states
|
||||
|
||||
def read_event(self) -> int:
|
||||
current, previous = self._consume_next_state()
|
||||
if previous == PinState.RELEASED:
|
||||
if current == PinState.RELEASED:
|
||||
return PinEvent.NONE
|
||||
if current == PinState.PRESSED:
|
||||
return PinEvent.PRESSED
|
||||
if previous == PinState.PRESSED:
|
||||
if current == PinState.PRESSED:
|
||||
return PinEvent.NONE
|
||||
if current == PinState.RELEASED:
|
||||
return PinEvent.RELEASED
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
class Key:
|
||||
index: int
|
||||
previous_state: KeyState
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
@@ -44,6 +95,15 @@ class Key:
|
||||
assert self.index is not None
|
||||
|
||||
|
||||
class KeyStates:
|
||||
current: int
|
||||
previous: int
|
||||
|
||||
def __init__(self, current: int, previous: int):
|
||||
self.current = current
|
||||
self.previous = previous
|
||||
|
||||
|
||||
class Keycode(Key):
|
||||
keycode: int
|
||||
|
||||
@@ -51,14 +111,24 @@ class Keycode(Key):
|
||||
super().__init__()
|
||||
self.keycode = keycode
|
||||
|
||||
def __interpret_hardware_changes(self, keyboard: Keyboard) -> tuple[KeyState, KeyState]:
|
||||
def _consume_next_state(self, pin: Pin) -> KeyStates:
|
||||
"""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)
|
||||
event = pin.read_event()
|
||||
if event == PinEvent.NONE:
|
||||
return KeyStates(self.previous_state, self.previous_state)
|
||||
if event == PinEvent.PRESSED:
|
||||
states = KeyStates(KeyState.PRESSED, int(self.previous_state))
|
||||
self.previous_state = states.current
|
||||
return states
|
||||
if event == PinEvent.RELEASED:
|
||||
states = KeyStates(KeyState.UNPRESSED, int(self.previous_state))
|
||||
self.previous_state = states.current
|
||||
return states
|
||||
raise NotImplementedError()
|
||||
|
||||
def __interpret_event(self, states: tuple[KeyState, KeyState]) -> KeyEvent:
|
||||
def _read_event(self, pin) -> KeyEvent:
|
||||
"""Interprets the current and previous KeyState as a KeyEvent"""
|
||||
states = self._consume_next_state(pin)
|
||||
current, previous = states
|
||||
if previous == KeyState.UNPRESSED:
|
||||
if current == KeyState.UNPRESSED:
|
||||
@@ -70,40 +140,20 @@ class Keycode(Key):
|
||||
return KeyEvent.NONE
|
||||
if current == KeyState.UNPRESSED:
|
||||
return KeyEvent.RELEASED
|
||||
else:
|
||||
raise NotImplementedError()
|
||||
raise NotImplementedError()
|
||||
|
||||
def react(self, keyboard: Keyboard, event: KeyEvent) -> None:
|
||||
def _react_to_event(self, event: KeyEvent, keyboard) -> None:
|
||||
if event == KeyEvent.NONE:
|
||||
return
|
||||
if event == KeyEvent.PRESSED:
|
||||
keyboard.pressed_keys.add(self.keycode)
|
||||
keyboard.add_keycode_to_report(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] = ()
|
||||
keyboard.remove_keycode_from_report(self.keycode)
|
||||
|
||||
def handle(self, keyboard):
|
||||
def handle(self, keyboard, pin):
|
||||
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,)
|
||||
event = self._read_event(pin)
|
||||
self._react_to_event(event, keyboard)
|
||||
|
||||
|
||||
class Modifier(Keycode):
|
||||
@@ -123,7 +173,60 @@ class Toggle(LayerKey):
|
||||
def __init__(self, layer: int):
|
||||
super().__init__(layer)
|
||||
|
||||
# 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:
|
||||
# self.toggled_layer = key.layer
|
||||
# self.held_layer = None
|
||||
# self.pin_states_last_cycle[pin_index] = (
|
||||
# __TOGGLED_PRESSED, key)
|
||||
# for i in range(len(self.pin_states_last_cycle)):
|
||||
# if i == pin_index or len(self.pin_states_last_cycle[i]) == 1:
|
||||
# continue
|
||||
# value, last_keycode = self.pin_states_last_cycle[i]
|
||||
# if type(last_keycode) is Toggle:
|
||||
# self.pin_states_last_cycle[i] = (
|
||||
# __UNPRESSED,)
|
||||
# if type(last_keycode) is Hold:
|
||||
# self.held_layer = None
|
||||
# self.pin_states_last_cycle[i] = (
|
||||
# __DEBOUNCE,)
|
||||
# continue
|
||||
# if not currentlyPressed and previouslyToggled:
|
||||
# self.pin_states_last_cycle[pin_index] = (
|
||||
# __TOGGLED_RELEASED, key)
|
||||
# continue
|
||||
# if currentlyPressed and previouslyToggledReleased:
|
||||
# self.toggled_layer = 0
|
||||
# self.pin_states_last_cycle[pin_index] = (
|
||||
# __UNTOGGLED_PRESSED, key)
|
||||
# continue
|
||||
# if not currentlyPressed and previouslyUntoggledPressed:
|
||||
# self.pin_states_last_cycle[pin_index] = (
|
||||
# __UNPRESSED,)
|
||||
# continue
|
||||
#
|
||||
|
||||
|
||||
class Hold(LayerKey):
|
||||
def __init__(self, layer: int):
|
||||
super().__init__(layer)
|
||||
|
||||
# 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
|
||||
#
|
||||
|
||||
Reference in New Issue
Block a user