From 5fb95c5f94d6c939dfea2fc716ef818d6242b918 Mon Sep 17 00:00:00 2001 From: "Michael F. Lamb" Date: Sun, 26 Jan 2020 20:26:40 -0800 Subject: [PATCH] create users/datagrok (#7653) * users/datagrok: add shared functions * users/datagrok: improve base-layer selection feature * users/datagrok: add README.md --- users/datagrok/README.md | 63 +++++++++++++++++ users/datagrok/feature_cdeq.c | 47 +++++++++++++ users/datagrok/feature_cdeq.h | 2 + .../feature_default_layers_selector.c | 46 +++++++++++++ .../feature_default_layers_selector.h | 69 +++++++++++++++++++ 5 files changed, 227 insertions(+) create mode 100644 users/datagrok/README.md create mode 100644 users/datagrok/feature_cdeq.c create mode 100644 users/datagrok/feature_cdeq.h create mode 100644 users/datagrok/feature_default_layers_selector.c create mode 100644 users/datagrok/feature_default_layers_selector.h diff --git a/users/datagrok/README.md b/users/datagrok/README.md new file mode 100644 index 000000000..0d58c04e7 --- /dev/null +++ b/users/datagrok/README.md @@ -0,0 +1,63 @@ +# datagrok's QMK user-space code + +## cdeq "comma dot exclamation question" + +This is a hack to place `question mark` on `shift-comma` and `exclamation mark` on `shift-period`. + +When using an operating system configured for a US/qwerty layout this replaces the angle brackets `<` `>` with `?` `!`. This helps on small keyboards to keep symbols for prose co-located in one layer, and symbols for programming in another. + +It's a "hack" because the "proper" way to accomplish this would be to edit the operating system's keymap. + +### setup + +in your `keymap.c`: + + #include "feature_cdeq.h" + + bool process_record_user(uint16_t keycode, keyrecord_t *record) { + return process_record_cdeq(keycode, record); + } + +in your `rules.mk`, + + SRC += feature_cdeq.c + +### examples + +- atreus:datagrok +- bm43a:datagrok +- mitosis:datagrok + +## base layer selector + +Defines a keycode `KF_LAYO` to rotate between available default layers. + +`Shift`+`KF_LAYO` makes the currently selected one persistent across reboots. + +This is useful if you'd like your keyboard to support and toggle between QWERTY, Dvorak, Colemak, Workman, and other layouts while keeping a common arrangement of modifier and function keys. + +Since toggling layouts seems like something one does infrequently, I wanted to be able to operate this feature with a single key, instead of one for each layer like planck:default or bootmagic. + +### setup + +in your `keymap.c`: + + #define KF_LAYO SAFE_RANGE + #include "feature_default_layers_selector.h" + const uint8_t highest_base_layer = 4; + + bool process_record_user(uint16_t keycode, keyrecord_t *record) { + return \ + process_record_save_default_layer(keycode, record) && \ + process_record_select_default_layer(keycode, record); + } + +in your `rules.mk`, + + SRC += feature_default_layers_selector.c + +### examples + +- atreus:datagrok +- bm43a:datagrok +- mitosis:datagrok diff --git a/users/datagrok/feature_cdeq.c b/users/datagrok/feature_cdeq.c new file mode 100644 index 000000000..c1796ab22 --- /dev/null +++ b/users/datagrok/feature_cdeq.c @@ -0,0 +1,47 @@ +// This is a hack to place on and on , when using an operating system configured for a +// US/qwerty layout. +// +// cdeq = "comma dot exclamation question" + +#include QMK_KEYBOARD_H + +bool comm_shifted = false; +bool ques_shifted = false; + +bool process_record_cdeq(uint16_t keycode, keyrecord_t *record) { + uint8_t shifted; + uint16_t s_keycode; + bool *k_shifted; + + switch (keycode) { + case KC_COMM: + s_keycode = KC_SLSH; + k_shifted = &comm_shifted; + break; + case KC_DOT: + s_keycode = KC_1; + k_shifted = &ques_shifted; + break; + default: + return true; + } + + shifted = get_mods() & (MOD_BIT(KC_LSHIFT)|MOD_BIT(KC_RSHIFT)); + + // Keydown. If shift is currently pressed, register its alternate keycode. + if (record->event.pressed && shifted) { + *k_shifted = true; + register_code(s_keycode); + return false; + // Keyup. If shift was pressed back when the key was pressed, unregister + // its alternate keycode. + } else if (!(record->event.pressed) && *k_shifted) { + *k_shifted = false; + unregister_code(s_keycode); + return false; + // Otherwise, behave as normal. + } else { + return true; + } +} diff --git a/users/datagrok/feature_cdeq.h b/users/datagrok/feature_cdeq.h new file mode 100644 index 000000000..ff3509b4d --- /dev/null +++ b/users/datagrok/feature_cdeq.h @@ -0,0 +1,2 @@ +#include QMK_KEYBOARD_H +bool process_record_cdeq(uint16_t keycode, keyrecord_t *record); diff --git a/users/datagrok/feature_default_layers_selector.c b/users/datagrok/feature_default_layers_selector.c new file mode 100644 index 000000000..c83c773f8 --- /dev/null +++ b/users/datagrok/feature_default_layers_selector.c @@ -0,0 +1,46 @@ +#include "feature_default_layers_selector.h" + +#ifdef AUDIO_ENABLE +#include "audio.h" +#ifdef DEFAULT_LAYER_SONGS +extern float default_layer_songs[][16][2]; +#endif +#endif + +bool process_record_save_default_layer(uint16_t keycode, keyrecord_t *record) { + +#if defined(AUDIO_ENABLE) + float saved_song[][2] = SONG(COIN_SOUND); +#endif + + if (!(keycode == KF_LAYO + && record->event.pressed + && get_mods() & (MOD_BIT(KC_LSHIFT)|MOD_BIT(KC_RSHIFT)))) { + return true; + } + + eeconfig_update_default_layer(default_layer_state); +#if defined(AUDIO_ENABLE) + PLAY_SONG(saved_song); +#endif + return false; +} + +bool process_record_select_default_layer(uint16_t keycode, keyrecord_t *record) { + if (!(keycode == KF_LAYO + && record->event.pressed)) { + return true; + } + if (!default_layer_state) { + default_layer_set(2); + } else { + default_layer_set( + (((1U<<(highest_base_layer+1))-1) & (default_layer_state<<1)) + | (default_layer_state>>highest_base_layer)); + } + led_set(host_keyboard_leds()); +#if defined(AUDIO_ENABLE) && defined(DEFAULT_LAYER_SONGS) + PLAY_SONG(default_layer_songs[get_highest_layer(default_layer_state)]); +#endif + return false; +} diff --git a/users/datagrok/feature_default_layers_selector.h b/users/datagrok/feature_default_layers_selector.h new file mode 100644 index 000000000..37d82de82 --- /dev/null +++ b/users/datagrok/feature_default_layers_selector.h @@ -0,0 +1,69 @@ +#include QMK_KEYBOARD_H + +/* + Define a keycode KF_LAYO to rotate between available default layers. + Shift+KF_LAYO makes the current one persistent. + + To use: + + in your keymap.c, define KF_LAYO so it does not conflict with anything else. + then include this header and set highest_base_layer. + + #define KF_LAYO SAFE_RANGE + #include "feature_default_layers_selector.h" + + const uint8_t highest_base_layer = 4; // the index + + and in your rules.mk, + + SRC += feature_default_layers_selector.c +*/ + +/* + See https://docs.qmk.fm/#/keymap for docs about layers including the concept + of "base" or "default" layers. + + This is broken into two functions so that: + + - If you don't want to store the default layer state in eeprom, don't call + process_record_save_default_layer. + + - If you have your own mechanism for setting the default layer state (to one + or multiple layers), do that instead of process_record_select_default_layer. + + If you call both functions, call process_record_save_default_layer first. + + The QMK docs seem to assume that you will have only one layer as your + default layer at any time, but the source code actually supports an arbitrary + default_layer_state (composition of layers) + + quantum has "set_single_persistent_default_layer" but that writes to eeprom + every time you change your default layer preference. i wanted a behavior + instead which lets you switch default layers all you want, then store the + current configuration once you're happy with it. that way if you get into an + unusable state you can just unplug and replug your keyboard to escape from it. + + this code assumes: + + 1. each default layer state that you would select among consists of a single + layer, which we will call a "base" layer. + + 2. all your "base" layers are stored contiguously at the bottom of your + keymaps[] stack, and there are no non-"base" layers mixed in. + + 3. you have a maximum of 8 "base" layers. that is, the highest base layer is + index 7. + + while 16 and 32 bit platforms might allow default_layer_state to include more + and higher-numbered layers, eeconfig_update_default_layer saves only the first + 8 bits of default_layer_state to eeprom. + +*/ + +#ifndef KF_LAYO +#define KF_LAYO SAFE_RANGE +#endif + +const uint8_t highest_base_layer; +bool process_record_save_default_layer(uint16_t keycode, keyrecord_t *record); +bool process_record_select_default_layer(uint16_t keycode, keyrecord_t *record);