From 1fe80fec92b0de21125514e22fdb49b910ba4f19 Mon Sep 17 00:00:00 2001 From: Josh Klar Date: Fri, 12 Jul 2019 15:16:33 -0700 Subject: [PATCH 1/4] Clean up and standardize print() debug stuff --- kmk/firmware.py | 82 ++++++++++++++++++++++++++++++++++++++----- kmk/handlers/stock.py | 4 +-- kmk/hid.py | 6 ++++ kmk/internal_state.py | 59 ++++++++++++++++++++----------- 4 files changed, 121 insertions(+), 30 deletions(-) diff --git a/kmk/firmware.py b/kmk/firmware.py index 907005b..8e37cb7 100644 --- a/kmk/firmware.py +++ b/kmk/firmware.py @@ -15,16 +15,18 @@ # chain to import _every single thing_ KMK eventually uses in a normal # workflow, in order from fewest to least nested dependencies. -# First, stuff that has no dependencies, or only C/MPY deps +# First, system-provided deps +import busio # isort:skip import collections # isort:skip +import gc # isort:skip +import supervisor # isort:skip + +# Now "light" KMK stuff with few/no external deps import kmk.consts # isort:skip import kmk.kmktime # isort:skip import kmk.types # isort:skip import kmk.util # isort:skip -import busio # isort:skip - -import supervisor # isort:skip from kmk.consts import LeaderMode, UnicodeMode # isort:skip from kmk.hid import USB_HID # isort:skip from kmk.internal_state import InternalState # isort:skip @@ -100,6 +102,71 @@ class Firmware: self._state = InternalState(self) + def __repr__(self): + return ( + 'Firmware(' + 'debug_enabled={} ' + 'keymap=truncated ' + 'coord_mapping=truncated ' + 'row_pins=truncated ' + 'col_pins=truncated ' + 'diode_orientation={} ' + 'matrix_scanner={} ' + 'unicode_mode={} ' + 'tap_time={} ' + 'leader_mode={} ' + 'leader_dictionary=truncated ' + 'leader_timeout={} ' + 'hid_helper={} ' + 'extra_data_pin={} ' + 'split_offsets={} ' + 'split_flip={} ' + 'split_side={} ' + 'split_type={} ' + 'split_master_left={} ' + 'is_master={} ' + 'uart={} ' + 'uart_flip={} ' + 'uart_pin={}' + ')' + ).format( + self.debug_enabled, + # self.keymap, + # self.coord_mapping, + # self.row_pins, + # self.col_pins, + self.diode_orientation, + self.matrix_scanner, + self.unicode_mode, + self.tap_time, + self.leader_mode, + # self.leader_dictionary, + self.leader_timeout, + self.hid_helper.__name__, + self.extra_data_pin, + self.split_offsets, + self.split_flip, + self.split_side, + self.split_type, + self.split_master_left, + self.is_master, + self.uart, + self.uart_flip, + self.uart_pin, + ) + + def _print_debug_cycle(self, init=False): + if self.debug_enabled: + if init: + print('KMKInit()') + + print(self) + print(self._state) + print('GCStats(alloc={} free={})'.format( + gc.mem_alloc(), + gc.mem_free(), + )) + def _send_hid(self): self._hid_helper_inst.create_report(self._state.keys_pressed).send() self._state.resolve_hid() @@ -211,8 +278,7 @@ class Firmware: if not isinstance(k, tuple): del self.leader_dictionary[k] - if self.debug_enabled: - print("Firin' lazers. Keyboard is booted.") + self._print_debug_cycle(init=True) while True: state_changed = False @@ -246,5 +312,5 @@ class Firmware: if self._state.hid_pending: self._send_hid() - if self.debug_enabled and state_changed: - print('New State: {}'.format(self._state._to_dict())) + if state_changed: + self._print_debug_cycle() diff --git a/kmk/handlers/stock.py b/kmk/handlers/stock.py index db37c66..8bd8fd8 100644 --- a/kmk/handlers/stock.py +++ b/kmk/handlers/stock.py @@ -38,9 +38,9 @@ def bootloader(*args, **kwargs): def debug_pressed(key, state, KC, *args, **kwargs): if state.config.debug_enabled: - print('Disabling debug mode, bye!') + print('DebugDisable()') else: - print('Enabling debug mode. Welcome to the jungle.') + print('DebugEnable()') state.config.debug_enabled = not state.config.debug_enabled diff --git a/kmk/hid.py b/kmk/hid.py index 41c5b1b..a8ca71d 100644 --- a/kmk/hid.py +++ b/kmk/hid.py @@ -21,6 +21,12 @@ class USB_HID: self.post_init() + def __repr__(self): + return '{}(REPORT_BYTES={})'.format( + self.__class__.__name__, + self.REPORT_BYTES, + ) + def post_init(self): pass diff --git a/kmk/internal_state.py b/kmk/internal_state.py index d1edb9e..8212cbc 100644 --- a/kmk/internal_state.py +++ b/kmk/internal_state.py @@ -30,21 +30,37 @@ class InternalState: self.config = config def __repr__(self): - return 'InternalState({})'.format(self._to_dict()) - - def _to_dict(self): - ret = { - 'keys_pressed': self.keys_pressed, - 'active_layers': self.active_layers, - 'leader_mode_history': self.leader_mode_history, - 'leader_mode': self.config.leader_mode, - 'start_time': self.start_time, - 'tapping': self.tapping, - 'tap_dance_counts': self.tap_dance_counts, - 'timeouts': self.timeouts, - } - - return ret + return ( + 'InternalState(' + 'keys_pressed={} ' + 'coord_keys_pressed={} ' + 'leader_pending={} ' + 'leader_last_len={} ' + 'hid_pending={} ' + 'leader_mode_history={} ' + 'active_layers={} ' + 'reversed_active_layers={} ' + 'start_time={} ' + 'timeouts={} ' + 'tapping={} ' + 'tap_dance_counts={} ' + 'tap_side_effects={}' + ')' + ).format( + self.keys_pressed, + self.coord_keys_pressed, + self.leader_pending, + self.leader_last_len, + self.hid_pending, + self.leader_mode_history, + self.active_layers, + self.reversed_active_layers, + self.start_time, + self.timeouts, + self.tapping, + self.tap_dance_counts, + self.tap_side_effects, + ) def _find_key_in_map(self, row, col): ic = intify_coordinate(row, col) @@ -54,7 +70,7 @@ class InternalState: except ValueError: if self.config.debug_enabled: print( - 'No coord_mapping index for value {}, row={} col={}'.format( + 'CoordMappingNotFound(ic={}, row={}, col={})'.format( ic, row, col, @@ -72,7 +88,7 @@ class InternalState: continue if self.config.debug_enabled: - print('Resolved key: {}'.format(layer_key)) + print('KeyResolution(key={})'.format(layer_key)) return layer_key @@ -112,20 +128,23 @@ class InternalState: def matrix_changed(self, row, col, is_pressed): if self.config.debug_enabled: - print('Matrix changed (col, row, pressed?): {}, {}, {}'.format( - col, row, is_pressed, + print('MatrixChange(col={} row={} pressed={})'.format( + col, + row, + is_pressed, )) int_coord = intify_coordinate(row, col) kc_changed = self._find_key_in_map(row, col) if kc_changed is None: - print('No key accessible for col, row: {}, {}'.format(row, col)) + print('MatrixUndefinedCoordinate(col={} row={})'.format(col, row)) return self 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: From 2947f814894e57203b16b8e8b651e17f0b5bcb10 Mon Sep 17 00:00:00 2001 From: Josh Klar Date: Fri, 12 Jul 2019 15:31:27 -0700 Subject: [PATCH 2/4] Remove pointless reversed_active_layers/active_layers difference --- kmk/handlers/layers.py | 43 +++++++++++++++++++++++------------------- kmk/internal_state.py | 12 ++++++------ 2 files changed, 30 insertions(+), 25 deletions(-) diff --git a/kmk/handlers/layers.py b/kmk/handlers/layers.py index d436318..06a193f 100644 --- a/kmk/handlers/layers.py +++ b/kmk/handlers/layers.py @@ -3,24 +3,31 @@ from kmk.kmktime import ticks_diff, ticks_ms def df_pressed(key, state, *args, **kwargs): """Switches the default layer""" - state.active_layers[0] = key.meta.layer - state.reversed_active_layers = list(reversed(state.active_layers)) + state.active_layers[-1] = key.meta.layer return state def mo_pressed(key, state, *args, **kwargs): """Momentarily activates layer, switches off when you let go""" - state.active_layers.append(key.meta.layer) - state.reversed_active_layers = list(reversed(state.active_layers)) + state.active_layers.insert(0, key.meta.layer) return state def mo_released(key, state, KC, *args, **kwargs): - state.active_layers = [ - layer for layer in state.active_layers - if layer != key.meta.layer - ] - state.reversed_active_layers = list(reversed(state.active_layers)) + # remove the first instance of the target layer + # from the active list + # under almost all normal use cases, this will + # disable the layer (but preserve it if it was triggered + # as a default layer, etc.) + # this also resolves an issue where using DF() on a layer + # triggered by MO() and then defaulting to the MO()'s layer + # would result in no layers active + try: + del_idx = state.active_layers.index(key.meta.layer) + del state.active_layers[del_idx] + except ValueError: + pass + return state @@ -62,23 +69,21 @@ def lt_released(key, state, *args, **kwargs): def tg_pressed(key, state, *args, **kwargs): """Toggles the layer (enables it if not active, and vise versa)""" - if key.meta.layer in state.active_layers: - state.active_layers = [ - layer for layer in state.active_layers - if layer != key.meta.layer - ] - else: - state.active_layers.append(key.meta.layer) - state.reversed_active_layers = list(reversed(state.active_layers)) + # See mo_released for implementation details around this + try: + del_idx = state.active_layers.index(key.meta.layer) + del state.active_layers[del_idx] + except ValueError: + state.active_layers.insert(0, key.meta.layer) return state def to_pressed(key, state, *args, **kwargs): """Activates layer and deactivates all other layers""" - state.active_layers = [key.meta.layer] - state.reversed_active_layers = list(reversed(state.active_layers)) + state.active_layers.clear() + state.active_layers.insert(0, key.meta.layer) return state diff --git a/kmk/internal_state.py b/kmk/internal_state.py index 8212cbc..292ff11 100644 --- a/kmk/internal_state.py +++ b/kmk/internal_state.py @@ -12,8 +12,12 @@ class InternalState: leader_last_len = 0 hid_pending = False leader_mode_history = [] + + # this should almost always be PREpended to, replaces + # former use of reversed_active_layers which had pointless + # overhead (the underlying list was never used anyway) active_layers = [0] - reversed_active_layers = list(reversed(active_layers)) + start_time = { 'lt': None, 'tg': None, @@ -39,7 +43,6 @@ class InternalState: 'hid_pending={} ' 'leader_mode_history={} ' 'active_layers={} ' - 'reversed_active_layers={} ' 'start_time={} ' 'timeouts={} ' 'tapping={} ' @@ -54,7 +57,6 @@ class InternalState: self.hid_pending, self.leader_mode_history, self.active_layers, - self.reversed_active_layers, self.start_time, self.timeouts, self.tapping, @@ -79,9 +81,7 @@ class InternalState: return None - # Later-added layers have priority. Sift through the layers - # in reverse order until we find a valid keycode object - for layer in self.reversed_active_layers: + for layer in self.active_layers: layer_key = self.config.keymap[layer][idx] if not layer_key or layer_key == KC.TRNS: From 17094a29888b0de01821967cb6fa75680fc96abb Mon Sep 17 00:00:00 2001 From: Josh Klar Date: Fri, 12 Jul 2019 16:38:50 -0700 Subject: [PATCH 3/4] Clean some code up; force GC on every cycle --- kmk/firmware.py | 58 +++++++++++++++++++++-------------- kmk/internal_state.py | 1 - kmk/key_validators.py | 32 +++++++++++++++++++ kmk/keys.py | 71 +++---------------------------------------- 4 files changed, 72 insertions(+), 90 deletions(-) create mode 100644 kmk/key_validators.py diff --git a/kmk/firmware.py b/kmk/firmware.py index 8e37cb7..dba794d 100644 --- a/kmk/firmware.py +++ b/kmk/firmware.py @@ -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: diff --git a/kmk/internal_state.py b/kmk/internal_state.py index 292ff11..a50e399 100644 --- a/kmk/internal_state.py +++ b/kmk/internal_state.py @@ -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: diff --git a/kmk/key_validators.py b/kmk/key_validators.py new file mode 100644 index 0000000..bff9bfd --- /dev/null +++ b/kmk/key_validators.py @@ -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) diff --git a/kmk/keys.py b/kmk/keys.py index 2571b76..9607454 100644 --- a/kmk/keys.py +++ b/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, From 350c2438ad09e45dfa5e6e4569fbbda082b0fc72 Mon Sep 17 00:00:00 2001 From: Josh Klar Date: Fri, 12 Jul 2019 16:54:38 -0700 Subject: [PATCH 4/4] Disable GC on every cycle, too much lag --- kmk/firmware.py | 4 ---- user_keymaps/klardotsh/kitsym4_iris.py | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/kmk/firmware.py b/kmk/firmware.py index dba794d..b831482 100644 --- a/kmk/firmware.py +++ b/kmk/firmware.py @@ -289,10 +289,6 @@ class Firmware: 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.is_master: diff --git a/user_keymaps/klardotsh/kitsym4_iris.py b/user_keymaps/klardotsh/kitsym4_iris.py index 9b7f425..1f1380f 100644 --- a/user_keymaps/klardotsh/kitsym4_iris.py +++ b/user_keymaps/klardotsh/kitsym4_iris.py @@ -6,7 +6,7 @@ from kmk.keys import KC keyboard = Firmware() -keyboard.debug_enabled = True +keyboard.debug_enabled = False keyboard.unicode_mode = UnicodeMode.LINUX keyboard.tap_time = 750