Clean some code up; force GC on every cycle
This commit is contained in:
parent
2947f81489
commit
17094a2988
@ -50,6 +50,7 @@ import kmk.internal_state # isort:skip
|
||||
|
||||
# Thanks for sticking around. Now let's do real work, starting below
|
||||
|
||||
from kmk.kmktime import sleep_ms
|
||||
from kmk.util import intify_coordinate as ic
|
||||
|
||||
|
||||
@ -156,13 +157,18 @@ class Firmware:
|
||||
)
|
||||
|
||||
def _print_debug_cycle(self, init=False):
|
||||
pre_alloc = gc.mem_alloc()
|
||||
pre_free = gc.mem_free()
|
||||
|
||||
if self.debug_enabled:
|
||||
if init:
|
||||
print('KMKInit()')
|
||||
|
||||
print(self)
|
||||
print(self._state)
|
||||
print('GCStats(alloc={} free={})'.format(
|
||||
print('GCStats(pre_alloc={} pre_free={} alloc={} free={})'.format(
|
||||
pre_alloc,
|
||||
pre_free,
|
||||
gc.mem_alloc(),
|
||||
gc.mem_free(),
|
||||
))
|
||||
@ -222,21 +228,8 @@ class Firmware:
|
||||
self.uart.write('DEB')
|
||||
self.uart.write(message, '\n')
|
||||
|
||||
def _master_half(self):
|
||||
if self.is_master is not None:
|
||||
return self.is_master
|
||||
|
||||
# Working around https://github.com/adafruit/circuitpython/issues/1769
|
||||
try:
|
||||
self._hid_helper_inst.create_report([]).send()
|
||||
self.is_master = True
|
||||
except OSError:
|
||||
self.is_master = False
|
||||
|
||||
return self.is_master
|
||||
|
||||
def init_uart(self, pin, timeout=20):
|
||||
if self._master_half():
|
||||
if self.is_master:
|
||||
return busio.UART(tx=None, rx=pin, timeout=timeout)
|
||||
else:
|
||||
return busio.UART(tx=pin, rx=None, timeout=timeout)
|
||||
@ -250,13 +243,27 @@ class Firmware:
|
||||
self._hid_helper_inst = self.hid_helper()
|
||||
|
||||
# Split keyboard Init
|
||||
if self.split_flip and not self._master_half():
|
||||
self.col_pins = list(reversed(self.col_pins))
|
||||
if self.split_type is not None:
|
||||
try:
|
||||
# Working around https://github.com/adafruit/circuitpython/issues/1769
|
||||
self._hid_helper_inst.create_report([]).send()
|
||||
self.is_master = True
|
||||
|
||||
if self.split_side == "Left":
|
||||
self.split_master_left = self._master_half()
|
||||
elif self.split_side == "Right":
|
||||
self.split_master_left = not self._master_half()
|
||||
# Sleep 2s so master portion doesn't "appear" to boot quicker than
|
||||
# dependent portions (which will take ~2s to time out on the HID send)
|
||||
sleep_ms(2000)
|
||||
except OSError:
|
||||
self.is_master = False
|
||||
|
||||
if self.split_flip and not self.is_master:
|
||||
self.col_pins = list(reversed(self.col_pins))
|
||||
|
||||
if self.split_side == "Left":
|
||||
self.split_master_left = self.is_master
|
||||
elif self.split_side == "Right":
|
||||
self.split_master_left = not self.is_master
|
||||
else:
|
||||
self.is_master = True
|
||||
|
||||
if self.uart_pin is not None:
|
||||
self.uart = self.init_uart(self.uart_pin)
|
||||
@ -278,12 +285,17 @@ class Firmware:
|
||||
if not isinstance(k, tuple):
|
||||
del self.leader_dictionary[k]
|
||||
|
||||
gc.collect()
|
||||
self._print_debug_cycle(init=True)
|
||||
|
||||
while True:
|
||||
# Generally speaking, the less stuff GC has to clean out,
|
||||
# the faster it'll run. Start every cycle with a clean
|
||||
# garbage bin to avoid random hiccups during keypress handling
|
||||
gc.collect()
|
||||
state_changed = False
|
||||
|
||||
if self.split_type is not None and self._master_half:
|
||||
if self.split_type is not None and self.is_master:
|
||||
update = self._receive_from_slave()
|
||||
if update is not None:
|
||||
self._handle_matrix_report(update)
|
||||
@ -292,7 +304,7 @@ class Firmware:
|
||||
update = self.matrix.scan_for_changes()
|
||||
|
||||
if update is not None:
|
||||
if self._master_half():
|
||||
if self.is_master:
|
||||
self._handle_matrix_report(update)
|
||||
state_changed = True
|
||||
else:
|
||||
|
@ -144,7 +144,6 @@ class InternalState:
|
||||
return self.process_key(kc_changed, is_pressed, int_coord, (row, col))
|
||||
|
||||
def process_key(self, key, is_pressed, coord_int=None, coord_raw=None):
|
||||
|
||||
if self.tapping and not isinstance(key.meta, TapDanceKeyMeta):
|
||||
self._process_tap_dance(key, is_pressed)
|
||||
else:
|
||||
|
32
kmk/key_validators.py
Normal file
32
kmk/key_validators.py
Normal file
@ -0,0 +1,32 @@
|
||||
from kmk.types import (KeySeqSleepMeta, LayerKeyMeta, ModTapKeyMeta,
|
||||
TapDanceKeyMeta, UnicodeModeKeyMeta)
|
||||
|
||||
|
||||
def key_seq_sleep_validator(ms):
|
||||
return KeySeqSleepMeta(ms)
|
||||
|
||||
|
||||
def layer_key_validator(layer, kc=None):
|
||||
'''
|
||||
Validates the syntax (but not semantics) of a layer key call. We won't
|
||||
have access to the keymap here, so we can't verify much of anything useful
|
||||
here (like whether the target layer actually exists). The spirit of this
|
||||
existing is mostly that Python will catch extraneous args/kwargs and error
|
||||
out.
|
||||
'''
|
||||
return LayerKeyMeta(layer=layer, kc=kc)
|
||||
|
||||
|
||||
def mod_tap_validator(kc, mods=None):
|
||||
'''
|
||||
Validates that mod tap keys are correctly used
|
||||
'''
|
||||
return ModTapKeyMeta(kc=kc, mods=mods)
|
||||
|
||||
|
||||
def tap_dance_key_validator(*codes):
|
||||
return TapDanceKeyMeta(codes)
|
||||
|
||||
|
||||
def unicode_mode_key_validator(mode):
|
||||
return UnicodeModeKeyMeta(mode)
|
71
kmk/keys.py
71
kmk/keys.py
@ -1,11 +1,11 @@
|
||||
import gc
|
||||
|
||||
import kmk.handlers.layers as layers
|
||||
import kmk.handlers.modtap as modtap
|
||||
import kmk.handlers.stock as handlers
|
||||
from kmk.consts import UnicodeMode
|
||||
from kmk.types import (AttrDict, KeySeqSleepMeta, LayerKeyMeta, ModTapKeyMeta,
|
||||
TapDanceKeyMeta, UnicodeModeKeyMeta)
|
||||
from kmk.key_validators import (key_seq_sleep_validator, layer_key_validator,
|
||||
mod_tap_validator, tap_dance_key_validator,
|
||||
unicode_mode_key_validator)
|
||||
from kmk.types import AttrDict, UnicodeModeKeyMeta
|
||||
|
||||
FIRST_KMK_INTERNAL_KEY = 1000
|
||||
NEXT_AVAILABLE_KEY = 1000
|
||||
@ -367,8 +367,6 @@ def make_argumented_key(
|
||||
return _argumented_key
|
||||
|
||||
|
||||
gc.collect()
|
||||
|
||||
# Modifiers
|
||||
make_mod_key(code=0x01, names=('LEFT_CONTROL', 'LCTRL', 'LCTL'))
|
||||
make_mod_key(code=0x02, names=('LEFT_SHIFT', 'LSHIFT', 'LSFT'))
|
||||
@ -383,8 +381,6 @@ make_mod_key(code=0x07, names=('MEH',))
|
||||
# HYPR = LCTL | LALT | LSFT | LGUI
|
||||
make_mod_key(code=0x0F, names=('HYPER', 'HYPR'))
|
||||
|
||||
gc.collect()
|
||||
|
||||
# Basic ASCII letters
|
||||
make_key(code=4, names=('A',))
|
||||
make_key(code=5, names=('B',))
|
||||
@ -413,8 +409,6 @@ make_key(code=27, names=('X',))
|
||||
make_key(code=28, names=('Y',))
|
||||
make_key(code=29, names=('Z',))
|
||||
|
||||
gc.collect()
|
||||
|
||||
# Numbers
|
||||
# Aliases to play nicely with AttrDict, since KC.1 isn't a valid
|
||||
# attribute key in Python, but KC.N1 is
|
||||
@ -429,8 +423,6 @@ make_key(code=37, names=('8', 'N8'))
|
||||
make_key(code=38, names=('9', 'N9'))
|
||||
make_key(code=39, names=('0', 'N0'))
|
||||
|
||||
gc.collect()
|
||||
|
||||
# More ASCII standard keys
|
||||
make_key(code=40, names=('ENTER', 'ENT', "\n"))
|
||||
make_key(code=41, names=('ESCAPE', 'ESC'))
|
||||
@ -449,8 +441,6 @@ make_key(code=54, names=('COMMA', 'COMM', ','))
|
||||
make_key(code=55, names=('DOT', '.'))
|
||||
make_key(code=56, names=('SLASH', 'SLSH'))
|
||||
|
||||
gc.collect()
|
||||
|
||||
# Function Keys
|
||||
make_key(code=58, names=('F1',))
|
||||
make_key(code=59, names=('F2',))
|
||||
@ -477,8 +467,6 @@ make_key(code=113, names=('F22',))
|
||||
make_key(code=114, names=('F23',))
|
||||
make_key(code=115, names=('F24',))
|
||||
|
||||
gc.collect()
|
||||
|
||||
# Lock Keys, Navigation, etc.
|
||||
make_key(code=57, names=('CAPS_LOCK', 'CAPSLOCK', 'CLCK', 'CAPS'))
|
||||
# FIXME: Investigate whether this key actually works, and
|
||||
@ -501,8 +489,6 @@ make_key(code=80, names=('LEFT',))
|
||||
make_key(code=81, names=('DOWN',))
|
||||
make_key(code=82, names=('UP',))
|
||||
|
||||
gc.collect()
|
||||
|
||||
# Numpad
|
||||
make_key(code=83, names=('NUM_LOCK', 'NUMLOCK', 'NLCK'))
|
||||
# FIXME: Investigate whether this key actually works, and
|
||||
@ -528,8 +514,6 @@ make_key(code=103, names=('KP_EQUAL', 'PEQL', 'NUMPAD_EQUAL'))
|
||||
make_key(code=133, names=('KP_COMMA', 'PCMM', 'NUMPAD_COMMA'))
|
||||
make_key(code=134, names=('KP_EQUAL_AS400', 'NUMPAD_EQUAL_AS400'))
|
||||
|
||||
gc.collect()
|
||||
|
||||
# Making life better for folks on tiny keyboards especially: exposes
|
||||
# the "shifted" keys as raw keys. Under the hood we're still
|
||||
# sending Shift+(whatever key is normally pressed) to get these, so
|
||||
@ -556,8 +540,6 @@ make_shifted_key('COMMA', names=('LEFT_ANGLE_BRACKET', 'LABK', '<'))
|
||||
make_shifted_key('DOT', names=('RIGHT_ANGLE_BRACKET', 'RABK', '>'))
|
||||
make_shifted_key('SLSH', names=('QUESTION', 'QUES', '?'))
|
||||
|
||||
gc.collect()
|
||||
|
||||
# International
|
||||
make_key(code=50, names=('NONUS_HASH', 'NUHS'))
|
||||
make_key(code=100, names=('NONUS_BSLASH', 'NUBS'))
|
||||
@ -582,8 +564,6 @@ make_key(code=150, names=('LANG7',))
|
||||
make_key(code=151, names=('LANG8',))
|
||||
make_key(code=152, names=('LANG9',))
|
||||
|
||||
gc.collect()
|
||||
|
||||
# Consumer ("media") keys. Most known keys aren't supported here. A much
|
||||
# longer list used to exist in this file, but the codes were almost certainly
|
||||
# incorrect, conflicting with each other, or otherwise "weird". We'll add them
|
||||
@ -605,8 +585,6 @@ make_consumer_key(code=184, names=('MEDIA_EJECT', 'EJCT')) # 0xB8
|
||||
make_consumer_key(code=179, names=('MEDIA_FAST_FORWARD', 'MFFD')) # 0xB3
|
||||
make_consumer_key(code=180, names=('MEDIA_REWIND', 'MRWD')) # 0xB4
|
||||
|
||||
gc.collect()
|
||||
|
||||
# Internal, diagnostic, or auxiliary/enhanced keys
|
||||
|
||||
# NO and TRNS are functionally identical in how they (don't) mutate
|
||||
@ -631,18 +609,6 @@ make_key(
|
||||
on_release=handlers.passthrough,
|
||||
)
|
||||
|
||||
|
||||
def layer_key_validator(layer, kc=None):
|
||||
'''
|
||||
Validates the syntax (but not semantics) of a layer key call. We won't
|
||||
have access to the keymap here, so we can't verify much of anything useful
|
||||
here (like whether the target layer actually exists). The spirit of this
|
||||
existing is mostly that Python will catch extraneous args/kwargs and error
|
||||
out.
|
||||
'''
|
||||
return LayerKeyMeta(layer=layer, kc=kc)
|
||||
|
||||
|
||||
# Layers
|
||||
make_argumented_key(
|
||||
validator=layer_key_validator,
|
||||
@ -684,15 +650,6 @@ make_argumented_key(
|
||||
on_release=layers.tt_released,
|
||||
)
|
||||
|
||||
|
||||
def mod_tap_validator(kc, mods=None):
|
||||
'''
|
||||
Validates that mod tap keys are correctly used
|
||||
'''
|
||||
return ModTapKeyMeta(kc=kc, mods=mods)
|
||||
|
||||
|
||||
# ModTap
|
||||
make_argumented_key(
|
||||
validator=mod_tap_validator,
|
||||
names=('MT',),
|
||||
@ -700,14 +657,6 @@ make_argumented_key(
|
||||
on_release=modtap.mt_released,
|
||||
)
|
||||
|
||||
|
||||
gc.collect()
|
||||
|
||||
|
||||
def key_seq_sleep_validator(ms):
|
||||
return KeySeqSleepMeta(ms)
|
||||
|
||||
|
||||
# A dummy key to trigger a sleep_ms call in a sequence of other keys in a
|
||||
# simple sequence macro.
|
||||
make_argumented_key(
|
||||
@ -716,8 +665,6 @@ make_argumented_key(
|
||||
on_press=handlers.sleep_pressed,
|
||||
)
|
||||
|
||||
|
||||
# Switch unicode modes at runtime
|
||||
make_key(
|
||||
names=('UC_MODE_NOOP', 'UC_DISABLE'),
|
||||
meta=UnicodeModeKeyMeta(UnicodeMode.NOOP),
|
||||
@ -738,22 +685,14 @@ make_key(
|
||||
meta=UnicodeModeKeyMeta(UnicodeMode.WINC),
|
||||
on_press=handlers.uc_mode_pressed,
|
||||
)
|
||||
|
||||
|
||||
def unicode_mode_key_validator(mode):
|
||||
return UnicodeModeKeyMeta(mode)
|
||||
|
||||
|
||||
make_argumented_key(
|
||||
validator=unicode_mode_key_validator,
|
||||
names=('UC_MODE',),
|
||||
on_press=handlers.uc_mode_pressed,
|
||||
)
|
||||
|
||||
|
||||
# Tap Dance
|
||||
make_argumented_key(
|
||||
validator=lambda *codes: TapDanceKeyMeta(codes),
|
||||
validator=tap_dance_key_validator,
|
||||
names=('TAP_DANCE', 'TD'),
|
||||
on_press=handlers.td_pressed,
|
||||
on_release=handlers.td_released,
|
||||
|
Loading…
x
Reference in New Issue
Block a user