create users/datagrok (#7653)
authorMichael F. Lamb <mike@datagrok.org>
Mon, 27 Jan 2020 04:26:40 +0000 (20:26 -0800)
committerridingqwerty <george.g.koenig@gmail.com>
Mon, 27 Jan 2020 04:26:40 +0000 (23:26 -0500)
* users/datagrok: add shared functions

* users/datagrok: improve base-layer selection feature

* users/datagrok: add README.md

users/datagrok/README.md [new file with mode: 0644]
users/datagrok/feature_cdeq.c [new file with mode: 0644]
users/datagrok/feature_cdeq.h [new file with mode: 0644]
users/datagrok/feature_default_layers_selector.c [new file with mode: 0644]
users/datagrok/feature_default_layers_selector.h [new file with mode: 0644]

diff --git a/users/datagrok/README.md b/users/datagrok/README.md
new file mode 100644 (file)
index 0000000..0d58c04
--- /dev/null
@@ -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 (file)
index 0000000..c1796ab
--- /dev/null
@@ -0,0 +1,47 @@
+// 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.
+//
+// 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 (file)
index 0000000..ff3509b
--- /dev/null
@@ -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 (file)
index 0000000..c83c773
--- /dev/null
@@ -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 (file)
index 0000000..37d82de
--- /dev/null
@@ -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);