From 57239e3163bcf0ae7644e373042a6896b71fdaa9 Mon Sep 17 00:00:00 2001 From: Josh Klar Date: Sat, 29 Dec 2018 06:03:31 -0800 Subject: [PATCH] Everything necessary to get this to boot finally. Planck types! --- Makefile | 14 +++- boot.py | 3 + kmk/firmware.py | 5 ++ kmk/handlers/sequences.py | 6 +- kmk/handlers/stock.py | 13 +-- kmk/keycodes.py | 68 ++++++++++++--- kmk/macros/unicode.py | 4 +- kmk/mcus/circuitpython_samd51.py | 2 + user_keymaps/klardotsh/klarank_featherm4.py | 91 +++++++++++---------- 9 files changed, 138 insertions(+), 68 deletions(-) create mode 100755 boot.py diff --git a/Makefile b/Makefile index 22a01e9..ddc34ed 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ AMPY_DELAY ?= 1.5 ARDUINO ?= /usr/share/arduino PIPENV ?= $(shell which pipenv) -all: copy-kmk copy-keymap +all: copy-kmk copy-bootpy copy-keymap .docker_base: Dockerfile_base @echo "===> Building Docker base image kmkfw/base:${DOCKER_BASE_TAG}" @@ -78,6 +78,18 @@ copy-kmk: echo "**** MOUNTPOINT must be defined (wherever your CIRCUITPY drive is mounted) ****" && exit 1 endif +ifdef MOUNTPOINT +$(MOUNTPOINT)/kmk/boot.py: boot.py + @echo "===> Copying required boot.py" + @rsync -rh boot.py $(MOUNTPOINT)/ + @sync + +copy-bootpy: $(MOUNTPOINT)/kmk/boot.py +else +copy-bootpy: + echo "**** MOUNTPOINT must be defined (wherever your CIRCUITPY drive is mounted) ****" && exit 1 +endif + ifdef MOUNTPOINT ifndef USER_KEYMAP $(MOUNTPOINT)/main.py: diff --git a/boot.py b/boot.py new file mode 100755 index 0000000..dd14a28 --- /dev/null +++ b/boot.py @@ -0,0 +1,3 @@ +import supervisor + +supervisor.set_next_stack_limit(4096 + 1024) diff --git a/kmk/firmware.py b/kmk/firmware.py index ac8f3b8..a98f23c 100644 --- a/kmk/firmware.py +++ b/kmk/firmware.py @@ -20,6 +20,11 @@ import collections # isort:skip import kmk.consts # isort:skip import kmk.kmktime # isort:skip import kmk.types # isort:skip +import kmk.util # isort:skip + +# Now handlers that will be used in keycodes later +import kmk.handlers.layers +import kmk.handlers.stock # Now stuff that depends on the above (and so on) import kmk.keycodes # isort:skip diff --git a/kmk/handlers/sequences.py b/kmk/handlers/sequences.py index c218a5f..d015196 100644 --- a/kmk/handlers/sequences.py +++ b/kmk/handlers/sequences.py @@ -1,4 +1,5 @@ -from kmk.keycodes import ALL_KEYS, KC, make_key +from kmk.keycodes import KC, make_key +from kmk.handlers.stock import passthrough from kmk.types import KeySequenceMeta @@ -23,6 +24,7 @@ def simple_key_sequence(seq): return make_key( meta=KeySequenceMeta(seq), on_press=sequence_press_handler, + on_release=passthrough, ) @@ -30,7 +32,7 @@ def send_string(message): seq = [] for char in message: - kc = ALL_KEYS[char] + kc = KC[char] if char.isupper(): kc = KC.LSHIFT(kc) diff --git a/kmk/handlers/stock.py b/kmk/handlers/stock.py index e117dd5..3ad69c4 100644 --- a/kmk/handlers/stock.py +++ b/kmk/handlers/stock.py @@ -7,19 +7,22 @@ def passthrough(key, state, *args, **kwargs): def default_pressed(key, state, KC, coord_int=None, coord_raw=None): + state.hid_pending = True + if coord_int is not None: state.coord_keys_pressed[coord_int] = key - state.add_key(key) + state.keys_pressed.add(key) return state def default_released(key, state, KC, coord_int=None, coord_raw=None): - state.remove_key(key) + state.hid_pending = True + state.keys_pressed.discard(key) if coord_int is not None: - state.keys_pressed.discard(key.coord_keys_pressed.get(coord_int, None)) + state.keys_pressed.discard(state.coord_keys_pressed.get(coord_int, None)) state.coord_keys_pressed[coord_int] = None return state @@ -81,9 +84,9 @@ def leader_pressed(key, state, *args, **kwargs): return state._begin_leader_mode() -def tap_dance_pressed(key, state, *args, **kwargs): +def td_pressed(key, state, *args, **kwargs): return state._process_tap_dance(key, True) -def tap_dance_released(key, state, *args, **kwargs): +def td_released(key, state, *args, **kwargs): return state._process_tap_dance(key, False) diff --git a/kmk/keycodes.py b/kmk/keycodes.py index 2d0d528..3866a55 100644 --- a/kmk/keycodes.py +++ b/kmk/keycodes.py @@ -1,3 +1,5 @@ +import gc + import kmk.handlers.layers as layers import kmk.handlers.stock as handlers from kmk.consts import UnicodeMode @@ -13,8 +15,7 @@ KEYCODE_CONSUMER = 2 # Global state, will be filled in througout this file, and # anywhere the user creates custom keys -ALL_KEYS = {} -KC = AttrDict(ALL_KEYS) +KC = AttrDict() def generate_leader_dictionary_seq(string): @@ -134,11 +135,11 @@ def register_key_names(key, names=tuple()): # NOQA ''' for name in names: - ALL_KEYS[name] = key + KC[name] = key if len(name) == 1: - ALL_KEYS[name.upper()] = key - ALL_KEYS[name.lower()] = key + KC[name.upper()] = key + KC[name.lower()] = key return key @@ -193,7 +194,7 @@ def make_mod_key(*args, **kwargs): def make_shifted_key(target_name, names=tuple()): # NOQA - key = KC.LSFT(ALL_KEYS[target_name]) + key = KC.LSFT(KC[target_name]) register_key_names(key, names) @@ -208,18 +209,29 @@ def make_consumer_key(*args, **kwargs): # is almost certainly the best plan here def make_argumented_key( validator=lambda *validator_args, **validator_kwargs: object(), + names=tuple(), # NOQA *constructor_args, **constructor_kwargs, ): + global NEXT_AVAILABLE_KEYCODE + def _argumented_key(*user_args, **user_kwargs): + global NEXT_AVAILABLE_KEYCODE + meta = validator(*user_args, **user_kwargs) if meta: - return Keycode( + key = Keycode( + NEXT_AVAILABLE_KEYCODE, meta=meta, *constructor_args, **constructor_kwargs, ) + + NEXT_AVAILABLE_KEYCODE += 1 + + return key + else: raise ValueError( 'Argumented key validator failed for unknown reasons. ' @@ -227,6 +239,13 @@ def make_argumented_key( 'should have been raised.', ) + for name in names: + KC[name] = _argumented_key + + return _argumented_key + + +gc.collect() # Modifiers make_mod_key(code=0x01, names=('LEFT_CONTROL', 'LCTRL', 'LCTL')) @@ -242,6 +261,8 @@ 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',)) @@ -270,6 +291,8 @@ 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 @@ -284,6 +307,8 @@ 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')) @@ -302,6 +327,8 @@ 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',)) @@ -313,8 +340,8 @@ make_key(code=64, names=('F7',)) make_key(code=65, names=('F8',)) make_key(code=66, names=('F9',)) make_key(code=67, names=('F10',)) -make_key(code=68, names=('F10',)) -make_key(code=69, names=('F10',)) +make_key(code=68, names=('F11',)) +make_key(code=69, names=('F12',)) make_key(code=104, names=('F13',)) make_key(code=105, names=('F14',)) make_key(code=106, names=('F15',)) @@ -328,6 +355,8 @@ 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 @@ -350,6 +379,8 @@ 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 @@ -375,6 +406,8 @@ 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 @@ -401,6 +434,8 @@ 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')) @@ -424,6 +459,8 @@ 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 @@ -445,6 +482,8 @@ 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 @@ -465,7 +504,7 @@ make_key(names=('GESC',), on_press=handlers.gesc_pressed, on_release=handlers.ge make_key( names=('LEADER', 'LEAD'), on_press=handlers.leader_pressed, - on_release=handlers.leader_released, + on_release=handlers.passthrough, ) @@ -491,7 +530,7 @@ make_argumented_key( validator=layer_key_validator, names=('DF',), on_press=layers.df_pressed, - on_release=layers.df_released, + on_release=handlers.passthrough, ) make_argumented_key( validator=layer_key_validator, @@ -509,13 +548,13 @@ make_argumented_key( validator=layer_key_validator, names=('TG',), on_press=layers.tg_pressed, - on_release=layers.tg_released, + on_release=handlers.passthrough, ) make_argumented_key( validator=layer_key_validator, names=('TO',), on_press=layers.to_pressed, - on_release=layers.to_released, + on_release=handlers.passthrough, ) make_argumented_key( validator=layer_key_validator, @@ -525,6 +564,9 @@ make_argumented_key( ) +gc.collect() + + def key_seq_sleep_validator(ms): return KeySeqSleepMeta(ms) diff --git a/kmk/macros/unicode.py b/kmk/macros/unicode.py index f95f014..a670e32 100644 --- a/kmk/macros/unicode.py +++ b/kmk/macros/unicode.py @@ -1,5 +1,5 @@ from kmk.consts import UnicodeMode -from kmk.keycodes import ALL_KEYS, KC, Macro +from kmk.keycodes import KC, Macro from kmk.macros.simple import simple_key_sequence from kmk.types import AttrDict from kmk.util import get_wide_ordinal @@ -45,7 +45,7 @@ def generate_codepoint_keysym_seq(codepoint, expected_length=4): seq = [KC.N0 for _ in range(max(len(codepoint), expected_length))] for idx, codepoint_fragment in enumerate(reversed(codepoint)): - seq[-(idx + 1)] = ALL_KEYS.get(codepoint_fragment) + seq[-(idx + 1)] = KC.get(codepoint_fragment) return seq diff --git a/kmk/mcus/circuitpython_samd51.py b/kmk/mcus/circuitpython_samd51.py index 7957f26..1d6518f 100644 --- a/kmk/mcus/circuitpython_samd51.py +++ b/kmk/mcus/circuitpython_samd51.py @@ -1,6 +1,8 @@ from kmk.firmware import Firmware as _Firmware from kmk.hid import CircuitPythonUSB_HID +import kmk.keycodes + class Firmware(_Firmware): hid_helper = CircuitPythonUSB_HID diff --git a/user_keymaps/klardotsh/klarank_featherm4.py b/user_keymaps/klardotsh/klarank_featherm4.py index ae2f397..8aceb70 100644 --- a/user_keymaps/klardotsh/klarank_featherm4.py +++ b/user_keymaps/klardotsh/klarank_featherm4.py @@ -1,9 +1,10 @@ from kmk.boards.klarank import Firmware from kmk.consts import LeaderMode, UnicodeMode from kmk.keycodes import KC -from kmk.keycodes import generate_leader_dictionary_seq as glds -from kmk.macros.simple import send_string -from kmk.macros.unicode import compile_unicode_string_sequences as cuss + +# from kmk.keycodes import generate_leader_dictionary_seq as glds +# from kmk.macros.simple import send_string +# from kmk.macros.unicode import compile_unicode_string_sequences as cuss keyboard = Firmware() @@ -11,55 +12,55 @@ keyboard.debug_enabled = True keyboard.unicode_mode = UnicodeMode.LINUX keyboard.tap_time = 750 -emoticons = cuss({ - # Emojis - 'BEER': r'🍺', - 'BEER_TOAST': r'🍻', - 'FACE_CUTE_SMILE': r'😊', - 'FACE_HEART_EYES': r'😍', - 'FACE_JOY': r'πŸ˜‚', - 'FACE_SWEAT_SMILE': r'πŸ˜…', - 'FACE_THINKING': r'πŸ€”', - 'FIRE': r'πŸ”₯', - 'FLAG_CA': r'πŸ‡¨πŸ‡¦', - 'FLAG_US': r'πŸ‡ΊπŸ‡Έ', - 'HAND_CLAP': r'πŸ‘', - 'HAND_HORNS': r'🀘', - 'HAND_OK': r'πŸ‘Œ', - 'HAND_THUMB_DOWN': r'πŸ‘Ž', - 'HAND_THUMB_UP': r'πŸ‘', - 'HAND_WAVE': r'πŸ‘‹', - 'HEART': r'❀️', - 'MAPLE_LEAF': r'🍁', - 'POOP': r'πŸ’©', - 'TADA': r'πŸŽ‰', +# emoticons = cuss({ +# # Emojis +# 'BEER': r'🍺', +# 'BEER_TOAST': r'🍻', +# 'FACE_CUTE_SMILE': r'😊', +# 'FACE_HEART_EYES': r'😍', +# 'FACE_JOY': r'πŸ˜‚', +# 'FACE_SWEAT_SMILE': r'πŸ˜…', +# 'FACE_THINKING': r'πŸ€”', +# 'FIRE': r'πŸ”₯', +# 'FLAG_CA': r'πŸ‡¨πŸ‡¦', +# 'FLAG_US': r'πŸ‡ΊπŸ‡Έ', +# 'HAND_CLAP': r'πŸ‘', +# 'HAND_HORNS': r'🀘', +# 'HAND_OK': r'πŸ‘Œ', +# 'HAND_THUMB_DOWN': r'πŸ‘Ž', +# 'HAND_THUMB_UP': r'πŸ‘', +# 'HAND_WAVE': r'πŸ‘‹', +# 'HEART': r'❀️', +# 'MAPLE_LEAF': r'🍁', +# 'POOP': r'πŸ’©', +# 'TADA': r'πŸŽ‰', +# +# # Emoticons, but fancier +# 'ANGRY_TABLE_FLIP': r'(γƒŽΰ² η—Šΰ² )γƒŽε½‘β”»β”β”»', +# 'CELEBRATORY_GLITTER': r'+q:.οΎŸγƒ½(Β΄βˆ€ο½‘)οΎ‰οΎŸ.:q+゚゚+q:.οΎŸγƒ½(*Β΄βˆ€)οΎ‰οΎŸ.:q+゚', +# 'SHRUGGIE': r'Β―\_(ツ)_/Β―', +# 'TABLE_FLIP': r'(β•―Β°β–‘Β°οΌ‰β•―οΈ΅ ┻━┻', +# }) - # Emoticons, but fancier - 'ANGRY_TABLE_FLIP': r'(γƒŽΰ² η—Šΰ² )γƒŽε½‘β”»β”β”»', - 'CELEBRATORY_GLITTER': r'+q:.οΎŸγƒ½(Β΄βˆ€ο½‘)οΎ‰οΎŸ.:q+゚゚+q:.οΎŸγƒ½(*Β΄βˆ€)οΎ‰οΎŸ.:q+゚', - 'SHRUGGIE': r'Β―\_(ツ)_/Β―', - 'TABLE_FLIP': r'(β•―Β°β–‘Β°οΌ‰β•―οΈ΅ ┻━┻', -}) - -WPM = send_string("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Bibendum arcu vitae elementum curabitur vitae nunc sed. Facilisis sed odio morbi quis.") - -keyboard.leader_mode = LeaderMode.TIMEOUT -keyboard.leader_dictionary = { - glds('hello'): send_string('hello world from kmk macros'), - glds('wpm'): WPM, - glds('atf'): emoticons.ANGRY_TABLE_FLIP, - glds('tf'): emoticons.TABLE_FLIP, - glds('fca'): emoticons.FLAG_CA, - glds('fus'): emoticons.FLAG_US, - glds('cel'): emoticons.CELEBRATORY_GLITTER, -} +# WPM = send_string("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Bibendum arcu vitae elementum curabitur vitae nunc sed. Facilisis sed odio morbi quis.") +# +# keyboard.leader_mode = LeaderMode.TIMEOUT +# keyboard.leader_dictionary = { +# glds('hello'): send_string('hello world from kmk macros'), +# glds('wpm'): WPM, +# glds('atf'): emoticons.ANGRY_TABLE_FLIP, +# glds('tf'): emoticons.TABLE_FLIP, +# glds('fca'): emoticons.FLAG_CA, +# glds('fus'): emoticons.FLAG_US, +# glds('cel'): emoticons.CELEBRATORY_GLITTER, +# } _______ = KC.TRNS xxxxxxx = KC.NO HELLA_TD = KC.TD( KC.A, KC.B, - send_string('macros in a tap dance? I think yes'), + # send_string('macros in a tap dance? I think yes'), KC.TG(1), )