summary refs log tree commit diff
path: root/users/drashna
diff options
context:
space:
mode:
authorDrashna Jaelre <drashna@live.com>2022-05-30 22:02:55 -0700
committerGitHub <noreply@github.com>2022-05-30 22:02:55 -0700
commitcda343acbe45826225edac75eaa63216bf76d874 (patch)
tree398a14c907baa8e6521fc9d001a4619289e1d7a3 /users/drashna
parentb554e4b612d24109ce714554a306043a01382cbd (diff)
[Keymap] Drashna update for post Q2 merge (#17241)
Diffstat (limited to 'users/drashna')
-rw-r--r--users/drashna/autocorrect_data.h5
-rw-r--r--users/drashna/callbacks.c3
-rw-r--r--users/drashna/callbacks.h3
-rw-r--r--users/drashna/config.h14
-rw-r--r--users/drashna/keyrecords/autocorrection/autocorrection.c292
-rw-r--r--users/drashna/keyrecords/autocorrection/autocorrection.h9
-rwxr-xr-xusers/drashna/keyrecords/autocorrection/make_autocorrection_data.py186
-rw-r--r--users/drashna/keyrecords/caps_word.c139
-rw-r--r--users/drashna/keyrecords/caps_word.h85
-rw-r--r--users/drashna/keyrecords/keycodes.md5
-rw-r--r--users/drashna/keyrecords/process_records.c72
-rw-r--r--users/drashna/keyrecords/process_records.h11
-rw-r--r--users/drashna/keyrecords/secrets.md17
-rw-r--r--users/drashna/keyrecords/unicode.c21
-rw-r--r--users/drashna/keyrecords/unicode.h16
-rw-r--r--users/drashna/oled/oled_stuff.c135
-rw-r--r--users/drashna/oled/oled_stuff.h9
-rw-r--r--users/drashna/oled/sh110x.c19
-rw-r--r--users/drashna/pointing/pointing.c4
-rw-r--r--users/drashna/rgb/rgb_matrix_stuff.c3
-rw-r--r--users/drashna/rules.mk12
-rw-r--r--users/drashna/split/transport_sync.c3
-rw-r--r--users/drashna/split/transport_sync.h13
-rw-r--r--users/drashna/template.c15
-rw-r--r--users/drashna/template.h4
25 files changed, 510 insertions, 585 deletions
diff --git a/users/drashna/autocorrect_data.h b/users/drashna/autocorrect_data.h
new file mode 100644
index 0000000000..bcb5858aa8
--- /dev/null
+++ b/users/drashna/autocorrect_data.h
@@ -0,0 +1,5 @@
+#if __has_include("../qmk_secrets/autocorrection_data.h")
+#    include "../qmk_secrets/autocorrection_data.h"
+#else
+#    include "autocorrect_data_default.h"
+#endif
diff --git a/users/drashna/callbacks.c b/users/drashna/callbacks.c
index c11a381dee..0ceb1aebe5 100644
--- a/users/drashna/callbacks.c
+++ b/users/drashna/callbacks.c
@@ -87,6 +87,9 @@ void suspend_power_down_user(void) {
 
 __attribute__((weak)) void suspend_wakeup_init_keymap(void) {}
 void                       suspend_wakeup_init_user(void) {
+#ifdef OLED_ENABLE
+        oled_timer_reset();
+#endif
     suspend_wakeup_init_keymap();
 }
 
diff --git a/users/drashna/callbacks.h b/users/drashna/callbacks.h
index 5fe5f6a808..f6ac6b88de 100644
--- a/users/drashna/callbacks.h
+++ b/users/drashna/callbacks.h
@@ -23,6 +23,3 @@ void matrix_init_unicode(void);
 #ifdef SPLIT_KEYBOARD
 void matrix_slave_scan_keymap(void);
 #endif
-#ifdef CAPS_WORD_ENABLE
-#    include "keyrecords/caps_word.h"
-#endif
diff --git a/users/drashna/config.h b/users/drashna/config.h
index 4551c3504f..4a34f5d66a 100644
--- a/users/drashna/config.h
+++ b/users/drashna/config.h
@@ -37,9 +37,9 @@
 // #    define WPM_LAUNCH_CONTROL
 // #    define WPM_ALLOW_COUNT_REGRESSOIN
 // #    define WPM_UNFILTERED
-#    define WPM_SAMPLE_SECONDS      6
+#    define WPM_SAMPLE_SECONDS      10
 #    define WPM_SAMPLE_PERIODS      50
-#    define WPM_ESTIMATED_WORD_SIZE 6
+#    define WPM_ESTIMATED_WORD_SIZE 5
 #endif
 
 #ifdef AUDIO_ENABLE
@@ -291,6 +291,12 @@
 #    ifndef OLED_BRIGHTNESS
 #        define OLED_BRIGHTNESS 50
 #    endif
-#    undef OLED_UPDATE_INTERVAL
-#    define OLED_UPDATE_INTERVAL 100
+#    if !defined(STM32F4XX)
+#        undef OLED_UPDATE_INTERVAL
+#        define OLED_UPDATE_INTERVAL 75
+#    endif
 #endif
+
+#define ENABLE_COMPILE_KEYCODE
+
+#define BOTH_SHIFTS_TURNS_ON_CAPS_WORD
diff --git a/users/drashna/keyrecords/autocorrection/autocorrection.c b/users/drashna/keyrecords/autocorrection/autocorrection.c
index c7e938a341..682d6fd49c 100644
--- a/users/drashna/keyrecords/autocorrection/autocorrection.c
+++ b/users/drashna/keyrecords/autocorrection/autocorrection.c
@@ -10,6 +10,13 @@
 #    pragma GCC push_options
 #    pragma GCC optimize("O0")
 #    include "autocorrection_data.h"
+#    ifndef AUTOCORRECTION_MIN_LENGTH
+#        define AUTOCORRECTION_MIN_LENGTH AUTOCORRECT_MIN_LENGTH
+#    endif
+#    ifndef AUTOCORRECTION_MAX_LENGTH
+#        define AUTOCORRECTION_MAX_LENGTH AUTOCORRECT_MAX_LENGTH
+#    endif
+#    define autocorrection_data autocorrect_data
 #    if AUTOCORRECTION_MIN_LENGTH < 4
 #        error Minimum Length is too short and may cause overflows
 #    endif
@@ -17,6 +24,138 @@
 #        error Dictionary size excees maximum size permitted
 #    endif
 
+static uint8_t typo_buffer[AUTOCORRECT_MAX_LENGTH] = {KC_SPC};
+static uint8_t typo_buffer_size                    = 1;
+
+/**
+ * @brief function for querying the enabled state of autocorrect
+ *
+ * @return true if enabled
+ * @return false if disabled
+ */
+bool autocorrect_is_enabled(void) {
+    return userspace_config.autocorrection;
+}
+
+/**
+ * @brief Enables autocorrect and saves state to eeprom
+ *
+ */
+void autocorrect_enable(void) {
+    userspace_config.autocorrection = true;
+    eeconfig_update_user(userspace_config.raw);
+}
+
+/**
+ * @brief Disables autocorrect and saves state to eeprom
+ *
+ */
+void autocorrect_disable(void) {
+    userspace_config.autocorrection = false;
+    typo_buffer_size                 = 0;
+    eeconfig_update_user(userspace_config.raw);
+}
+
+/**
+ * @brief Toggles autocorrect's status and save state to eeprom
+ *
+ */
+void autocorrect_toggle(void) {
+    userspace_config.autocorrection = !userspace_config.autocorrection;
+    typo_buffer_size                 = 0;
+    eeconfig_update_user(userspace_config.raw);
+}
+
+/**
+ * @brief handler for determining if autocorrect should process keypress
+ *
+ * @param keycode Keycode registered by matrix press, per keymap
+ * @param record keyrecord_t structure
+ * @param typo_buffer_size passed along to allow resetting of autocorrect buffer
+ * @param mods allow processing of mod status
+ * @return true Allow autocorection
+ * @return false Stop processing and escape from autocorrect.
+ */
+__attribute__((weak)) bool process_autocorrect_user(uint16_t *keycode, keyrecord_t *record, uint8_t *typo_buffer_size, uint8_t *mods) {
+    // See quantum_keycodes.h for reference on these matched ranges.
+    switch (*keycode) {
+        // Exclude these keycodes from processing.
+        case KC_LSFT:
+        case KC_RSFT:
+        case KC_CAPS:
+        case QK_TO ... QK_ONE_SHOT_LAYER_MAX:
+        case QK_LAYER_TAP_TOGGLE ... QK_LAYER_MOD_MAX:
+        case QK_ONE_SHOT_MOD ... QK_ONE_SHOT_MOD_MAX:
+            return false;
+
+        // Mask for base keycode from shifted keys.
+        case QK_LSFT ... QK_LSFT + 255:
+        case QK_RSFT ... QK_RSFT + 255:
+            if (*keycode >= QK_LSFT && *keycode <= (QK_LSFT + 255)) {
+                *mods |= MOD_LSFT;
+            } else {
+                *mods |= MOD_RSFT;
+            }
+            *keycode &= 0xFF; // Get the basic keycode.
+            return true;
+#ifndef NO_ACTION_TAPPING
+        // Exclude tap-hold keys when they are held down
+        // and mask for base keycode when they are tapped.
+        case QK_LAYER_TAP ... QK_LAYER_TAP_MAX:
+#    ifdef NO_ACTION_LAYER
+            // Exclude Layer Tap, if layers are disabled
+            // but action tapping is still enabled.
+            return false;
+#    endif
+        case QK_MOD_TAP ... QK_MOD_TAP_MAX:
+            // Exclude hold keycode
+            if (!record->tap.count) {
+                return false;
+            }
+            *keycode &= 0xFF;
+            break;
+#else
+        case QK_MOD_TAP ... QK_MOD_TAP_MAX:
+        case QK_LAYER_TAP ... QK_LAYER_TAP_MAX:
+            // Exclude if disabled
+            return false;
+#endif
+        // Exclude swap hands keys when they are held down
+        // and mask for base keycode when they are tapped.
+        case QK_SWAP_HANDS ... QK_SWAP_HANDS_MAX:
+#ifdef SWAP_HANDS_ENABLE
+            if (*keycode >= 0x56F0 || !record->tap.count) {
+                return false;
+            }
+            *keycode &= 0xFF;
+            break;
+#else
+            // Exclude if disabled
+            return false;
+#endif
+    }
+
+    // Disable autocorrect while a mod other than shift is active.
+    if ((*mods & ~MOD_MASK_SHIFT) != 0) {
+        *typo_buffer_size = 0;
+        return false;
+    }
+
+    return true;
+}
+
+/**
+ * @brief handling for when autocorrection has been triggered
+ *
+ * @param backspaces number of characters to remove
+ * @param str pointer to PROGMEM string to replace mistyped seletion with
+ * @return true apply correction
+ * @return false user handled replacement
+ */
+__attribute__((weak)) bool apply_autocorrect(uint8_t backspaces, const char *str) {
+    return true;
+}
+
 /**
  * @brief Process handler for autocorrect feature
  *
@@ -25,131 +164,124 @@
  * @return true Continue processing keycodes, and send to host
  * @return false Stop processing keycodes, and don't send to host
  */
-bool process_autocorrection(uint16_t keycode, keyrecord_t* record) {
-    static uint8_t typo_buffer[AUTOCORRECTION_MAX_LENGTH] = {KC_SPC};
-    static uint8_t typo_buffer_size                       = 1;
+bool process_autocorrection(uint16_t keycode, keyrecord_t *record) {
+    uint8_t mods = get_mods();
+#ifndef NO_ACTION_ONESHOT
+    mods |= get_oneshot_mods();
+#endif
 
-    if (keycode == AUTO_CTN) {
-        if (record->event.pressed) {
-            typo_buffer_size = 0;
-            userspace_config.autocorrection ^= 1;
-            eeconfig_update_user(userspace_config.raw);
+    if ((keycode >= AUTOCORRECT_ON && keycode <= AUTOCORRECT_TOGGLE) && record->event.pressed) {
+        if (keycode == AUTOCORRECT_ON) {
+            autocorrect_enable();
+        } else if (keycode == AUTOCORRECT_OFF) {
+            autocorrect_disable();
+        } else if (keycode == AUTOCORRECT_TOGGLE) {
+            autocorrect_toggle();
+        } else {
+            return true;
         }
+
         return false;
     }
 
-    if (!userspace_config.autocorrection) {
+    if (!autocorrect_is_enabled()) {
         typo_buffer_size = 0;
         return true;
     }
 
+    if (!record->event.pressed) {
+        return true;
+    }
+
+    // autocorrect keycode verification and extraction
+    if (!process_autocorrect_user(&keycode, record, &typo_buffer_size, &mods)) {
+        return true;
+    }
+
+    // keycode buffer check
     switch (keycode) {
-        case KC_LSFT:
-        case KC_RSFT:
-            return true;
-#    ifndef NO_ACTION_TAPPING
-        case QK_MOD_TAP ... QK_MOD_TAP_MAX:
-            if (((keycode >> 8) & 0xF) == MOD_LSFT) {
-                return true;
-            }
-#        ifndef NO_ACTION_LAYER
-        case QK_LAYER_TAP ... QK_LAYER_TAP_MAX:
-#        endif
-            if (record->event.pressed || !record->tap.count) {
-                return true;
-            }
-            keycode &= 0xFF;
+        case KC_A ... KC_Z:
+            // process normally
             break;
-#    endif
-#    ifdef SWAP_HANDS_ENABLE
-        case QK_SWAP_HANDS ... QK_SWAP_HANDS_MAX:
-            if (keycode >= 0x56F0 || record->event.pressed || !record->tap.count) {
-                return true;
-            }
-            keycode &= 0xFF;
+        case KC_1 ... KC_0:
+        case KC_TAB ... KC_SEMICOLON:
+        case KC_GRAVE ... KC_SLASH:
+            // Set a word boundary if space, period, digit, etc. is pressed.
+            keycode = KC_SPC;
             break;
-#    endif
-#    ifndef NO_ACTION_ONESHOT
-        case QK_ONE_SHOT_MOD ... QK_ONE_SHOT_MOD_MAX:
-            if ((keycode & 0xF) == MOD_LSFT) {
-                return true;
-            }
-#    endif
-        default:
-            // Disable autocorrection while a mod other than shift is active.
-            if (((get_mods() | get_oneshot_mods()) & ~MOD_MASK_SHIFT) != 0) {
-                typo_buffer_size = 0;
-                return true;
-            }
-            if (!record->event.pressed) {
-                return true;
-            }
-    }
-
-    // Subtract buffer for Backspace key, reset for other non-alpha.
-    if (!(KC_A <= keycode && keycode <= KC_Z)) {
-        if (keycode == KC_BSPC) {
+        case KC_ENTER:
+            // Behave more conservatively for the enter key. Reset, so that enter
+            // can't be used on a word ending.
+            typo_buffer_size = 0;
+            keycode          = KC_SPC;
+            break;
+        case KC_BSPC:
             // Remove last character from the buffer.
             if (typo_buffer_size > 0) {
                 --typo_buffer_size;
             }
             return true;
-        } else if (KC_1 <= keycode && keycode <= KC_SLSH && keycode != KC_ESC) {
-            // Set a word boundary if space, period, digit, etc. is pressed.
-            // Behave more conservatively for the enter key. Reset, so that enter
-            // can't be used on a word ending.
-            if (keycode == KC_ENT || (keycode == KC_MINUS && (get_mods() | get_oneshot_mods()) & MOD_MASK_SHIFT)) {
-                typo_buffer_size = 0;
+        case KC_QUOTE:
+            // Treat " (shifted ') as a word boundary.
+            if ((mods & MOD_MASK_SHIFT) != 0) {
+                keycode = KC_SPC;
             }
-            keycode = KC_SPC;
-        } else {
+            break;
+        default:
             // Clear state if some other non-alpha key is pressed.
             typo_buffer_size = 0;
             return true;
-        }
     }
 
     // Rotate oldest character if buffer is full.
-    if (typo_buffer_size >= AUTOCORRECTION_MAX_LENGTH) {
-        memmove(typo_buffer, typo_buffer + 1, AUTOCORRECTION_MAX_LENGTH - 1);
-        typo_buffer_size = AUTOCORRECTION_MAX_LENGTH - 1;
+    if (typo_buffer_size >= AUTOCORRECT_MAX_LENGTH) {
+        memmove(typo_buffer, typo_buffer + 1, AUTOCORRECT_MAX_LENGTH - 1);
+        typo_buffer_size = AUTOCORRECT_MAX_LENGTH - 1;
     }
 
     // Append `keycode` to buffer.
     typo_buffer[typo_buffer_size++] = keycode;
     // Return if buffer is smaller than the shortest word.
-    if (typo_buffer_size < AUTOCORRECTION_MIN_LENGTH) {
+    if (typo_buffer_size < AUTOCORRECT_MIN_LENGTH) {
         return true;
     }
 
-    // Check for typo in buffer using a trie stored in `autocorrection_data`.
+    // Check for typo in buffer using a trie stored in `autocorrect_data`.
     uint16_t state = 0;
-    uint8_t  code  = pgm_read_byte(autocorrection_data + state);
-    for (uint8_t i = typo_buffer_size - 1; i >= 0; --i) {
+    uint8_t  code  = pgm_read_byte(autocorrect_data + state);
+    for (int8_t i = typo_buffer_size - 1; i >= 0; --i) {
         uint8_t const key_i = typo_buffer[i];
 
-        if (code & 64) {  // Check for match in node with multiple children.
+        if (code & 64) { // Check for match in node with multiple children.
             code &= 63;
-            for (; code != key_i; code = pgm_read_byte(autocorrection_data + (state += 3))) {
+            for (; code != key_i; code = pgm_read_byte(autocorrect_data + (state += 3))) {
                 if (!code) return true;
             }
             // Follow link to child node.
-            state = (pgm_read_byte(autocorrection_data + state + 1) | pgm_read_byte(autocorrection_data + state + 2) << 8);
+            state = (pgm_read_byte(autocorrect_data + state + 1) | pgm_read_byte(autocorrect_data + state + 2) << 8);
             // Check for match in node with single child.
         } else if (code != key_i) {
             return true;
-        } else if (!(code = pgm_read_byte(autocorrection_data + (++state)))) {
+        } else if (!(code = pgm_read_byte(autocorrect_data + (++state)))) {
             ++state;
         }
 
-        code = pgm_read_byte(autocorrection_data + state);
+        // Stop if `state` becomes an invalid index. This should not normally
+        // happen, it is a safeguard in case of a bug, data corruption, etc.
+        if (state >= DICTIONARY_SIZE) {
+            return true;
+        }
+
+        code = pgm_read_byte(autocorrect_data + state);
 
-        if (code & 128) {  // A typo was found! Apply autocorrection.
-            const uint8_t backspaces = code & 63;
-            for (uint8_t i = 0; i < backspaces; ++i) {
-                tap_code(KC_BSPC);
+        if (code & 128) { // A typo was found! Apply autocorrect.
+            const uint8_t backspaces = (code & 63) + !record->event.pressed;
+            if (apply_autocorrect(backspaces, (char const *)(autocorrect_data + state + 1))) {
+                for (uint8_t i = 0; i < backspaces; ++i) {
+                    tap_code(KC_BSPC);
+                }
+                send_string_P((char const *)(autocorrect_data + state + 1));
             }
-            send_string_P((char const*)(autocorrection_data + state + 1));
 
             if (keycode == KC_SPC) {
                 typo_buffer[0]   = KC_SPC;
@@ -166,5 +298,7 @@ bool process_autocorrection(uint16_t keycode, keyrecord_t* record) {
 #    pragma GCC pop_options
 #else
 #    pragma message "Warning!!! Autocorrect is not corretly setup!"
-bool process_autocorrection(uint16_t keycode, keyrecord_t* record) { return true; }
+bool process_autocorrection(uint16_t keycode, keyrecord_t* record) {
+    return true;
+}
 #endif
diff --git a/users/drashna/keyrecords/autocorrection/autocorrection.h b/users/drashna/keyrecords/autocorrection/autocorrection.h
index cea93159ae..8946b91f1f 100644
--- a/users/drashna/keyrecords/autocorrection/autocorrection.h
+++ b/users/drashna/keyrecords/autocorrection/autocorrection.h
@@ -7,4 +7,11 @@
 
 #include "drashna.h"
 
-bool process_autocorrection(uint16_t keycode, keyrecord_t* record);
+bool process_autocorrection(uint16_t keycode, keyrecord_t *record);
+bool process_autocorrect_user(uint16_t *keycode, keyrecord_t *record, uint8_t *typo_buffer_size, uint8_t *mods);
+bool apply_autocorrect(uint8_t backspaces, const char *str);
+
+bool autocorrect_is_enabled(void);
+void autocorrect_enable(void);
+void autocorrect_disable(void);
+void autocorrect_toggle(void);
diff --git a/users/drashna/keyrecords/autocorrection/make_autocorrection_data.py b/users/drashna/keyrecords/autocorrection/make_autocorrection_data.py
index 54fd9ba594..0dd9b78b9c 100755
--- a/users/drashna/keyrecords/autocorrection/make_autocorrection_data.py
+++ b/users/drashna/keyrecords/autocorrection/make_autocorrection_data.py
@@ -1,4 +1,4 @@
-# Copyright 2021 Google LLC
+# Copyright 2021-2022 Google LLC
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
@@ -29,6 +29,7 @@ Each line of the dict file defines one typo and its correction with the syntax
 Example:
 
   :thier        -> their
+  dosen't       -> doesn't
   fitler        -> filter
   lenght        -> length
   ouput         -> output
@@ -42,7 +43,7 @@ https://getreuer.info/posts/keyboards/autocorrection
 
 import sys
 import textwrap
-from typing import Any, Dict, List, Tuple
+from typing import Any, Dict, Iterator, List, Tuple
 
 try:
   from english_words import english_words_lower_alpha_set as CORRECT_WORDS
@@ -51,85 +52,67 @@ except ImportError:
         'correctly spelled word. To check for this, install the english_words '
         'package and rerun this script:\n\n  pip install english_words\n')
   # Use a minimal word list as a fallback.
-  CORRECT_WORDS = ('information', 'available', 'international', 'language',
-                   'loosest', 'reference', 'wealthier', 'entertainment',
-                   'association', 'provides', 'technology', 'statehood')
+  CORRECT_WORDS = ('apparent', 'association', 'available', 'classification',
+                   'effect', 'entertainment', 'fantastic', 'information',
+                   'integrate', 'international', 'language', 'loosest',
+                   'manual', 'nothing', 'provides', 'reference', 'statehood',
+                   'technology', 'virtually', 'wealthier', 'wonderful')
 
 KC_A = 4
 KC_SPC = 0x2c
+KC_QUOT = 0x34
+
+TYPO_CHARS = dict(
+  [
+    ("'", KC_QUOT),
+    (':', KC_SPC),  # "Word break" character.
+  ] +
+  # Characters a-z.
+  [(chr(c), c + KC_A - ord('a')) for c in range(ord('a'), ord('z') + 1)]
+)
+
 
 def parse_file(file_name: str) -> List[Tuple[str, str]]:
   """Parses autocorrections dictionary file.
 
   Each line of the file defines one typo and its correction with the syntax
   "typo -> correction". Blank lines or lines starting with '#' are ignored. The
-  function validates that typos only have characters a-z and that typos are not
-  substrings of other typos, otherwise the longer typo would never trigger.
+  function validates that typos only have characters in TYPO_CHARS, that
+  typos are not substrings of other typos, and checking that typos don't trigger
+  on CORRECT_WORDS.
 
   Args:
     file_name: String, path of the autocorrections dictionary.
   Returns:
     List of (typo, correction) tuples.
   """
-
+  correct_words = ('information', 'available', 'international', 'language', 'loosest', 'reference', 'wealthier', 'entertainment', 'association', 'provides', 'technology', 'statehood')
   autocorrections = []
   typos = set()
-  line_number = 0
-  for line in open(file_name, 'rt'):
-    line_number += 1
-    line = line.strip()
-    if line and line[0] != '#':
-      # Parse syntax "typo -> correction", using strip to ignore indenting.
-      tokens = [token.strip() for token in line.split('->', 1)]
-      if len(tokens) != 2 or not tokens[0]:
-        print(f'Error:{line_number}: Invalid syntax: "{line}"')
+  for line_number, typo, correction in parse_file_lines(file_name):
+    if typo in typos:
+      print(f'Warning:{line_number}: Ignoring duplicate typo: "{typo}"')
+      continue
+
+    # Check that `typo` is valid.
+    if not(all([c in TYPO_CHARS for c in typo])):
+      print(f'Error:{line_number}: Typo "{typo}" has '
+            'characters other than ' + ''.join(TYPO_CHARS.keys()))
+      sys.exit(1)
+    for other_typo in typos:
+      if typo in other_typo or other_typo in typo:
+        print(f'Error:{line_number}: Typos may not be substrings of one '
+              f'another, otherwise the longer typo would never trigger: '
+              f'"{typo}" vs. "{other_typo}".')
         sys.exit(1)
+    if len(typo) < 5:
+      print(f'Warning:{line_number}: It is suggested that typos are at '
+            f'least 5 characters long to avoid false triggers: "{typo}"')
 
-      typo, correction = tokens
-      typo = typo.lower()  # Force typos to lowercase.
-      typo = typo.replace(' ', ':')
-
-      if typo in typos:
-        print(f'Warning:{line_number}: Ignoring duplicate typo: "{typo}"')
-        continue
+    check_typo_against_dictionary(typo, line_number, correct_words)
 
-      # Check that `typo` is valid.
-      if not(all([ord('a') <= ord(c) <= ord('z') or c == ':' for c in typo])):
-        print(f'Error:{line_number}: Typo "{typo}" has '
-              'characters other than a-z and :.')
-        sys.exit(1)
-      for other_typo in typos:
-        if typo in other_typo or other_typo in typo:
-          print(f'Error:{line_number}: Typos may not be substrings of one '
-                f'another, otherwise the longer typo would never trigger: '
-                f'"{typo}" vs. "{other_typo}".')
-          sys.exit(1)
-      if len(typo) < 5:
-        print(f'Warning:{line_number}: It is suggested that typos are at '
-              f'least 5 characters long to avoid false triggers: "{typo}"')
-
-      if typo.startswith(':') and typo.endswith(':'):
-        if typo[1:-1] in CORRECT_WORDS:
-          print(f'Warning:{line_number}: Typo "{typo}" is a correctly spelled '
-                'dictionary word.')
-      elif typo.startswith(':') and not typo.endswith(':'):
-        for word in CORRECT_WORDS:
-          if word.startswith(typo[1:]):
-            print(f'Warning:{line_number}: Typo "{typo}" would falsely trigger '
-                  f'on correctly spelled word "{word}".')
-      elif not typo.startswith(':') and typo.endswith(':'):
-        for word in CORRECT_WORDS:
-          if word.endswith(typo[:-1]):
-            print(f'Warning:{line_number}: Typo "{typo}" would falsely trigger '
-                  f'on correctly spelled word "{word}".')
-      elif not typo.startswith(':') and not typo.endswith(':'):
-        for word in CORRECT_WORDS:
-          if typo in word:
-            print(f'Warning:{line_number}: Typo "{typo}" would falsely trigger '
-                  f'on correctly spelled word "{word}".')
-
-      autocorrections.append((typo, correction))
-      typos.add(typo)
+    autocorrections.append((typo, correction))
+    typos.add(typo)
 
   return autocorrections
 
@@ -152,6 +135,47 @@ def make_trie(autocorrections: List[Tuple[str, str]]) -> Dict[str, Any]:
   return trie
 
 
+def parse_file_lines(file_name: str) -> Iterator[Tuple[int, str, str]]:
+  """Parses lines read from `file_name` into typo-correction pairs."""
+
+  line_number = 0
+  for line in open(file_name, 'rt'):
+    line_number += 1
+    line = line.strip()
+    if line and line[0] != '#':
+      # Parse syntax "typo -> correction", using strip to ignore indenting.
+      tokens = [token.strip() for token in line.split('->', 1)]
+      if len(tokens) != 2 or not tokens[0]:
+        print(f'Error:{line_number}: Invalid syntax: "{line}"')
+        sys.exit(1)
+
+      typo, correction = tokens
+      typo = typo.lower()  # Force typos to lowercase.
+      typo = typo.replace(' ', ':')
+
+      yield line_number, typo, correction
+
+
+def check_typo_against_dictionary(typo: str, line_number: int, correct_words) -> None:
+  """Checks `typo` against English dictionary words."""
+
+  if typo.startswith(':') and typo.endswith(':'):
+    if typo[1:-1] in correct_words:
+      print(f'Warning:{line_number}: Typo "{typo}" is a correctly spelled dictionary word.')
+  elif typo.startswith(':') and not typo.endswith(':'):
+    for word in correct_words:
+      if word.startswith(typo[1:]):
+            print(f'Warning:{line_number}: Typo "{typo}" would falsely trigger on correctly spelled word "{word}".')
+  elif not typo.startswith(':') and typo.endswith(':'):
+    for word in correct_words:
+      if word.endswith(typo[:-1]):
+            print(f'Warning:{line_number}: Typo "{typo}" would falsely trigger on correctly spelled word "{word}".')
+  elif not typo.startswith(':') and not typo.endswith(':'):
+    for word in correct_words:
+      if typo in word:
+        print(f'Warning:{line_number}: Typo "{typo}" would falsely trigger on correctly spelled word "{word}".')
+
+
 def serialize_trie(autocorrections: List[Tuple[str, str]],
                    trie: Dict[str, Any]) -> List[int]:
   """Serializes trie and correction data in a form readable by the C code.
@@ -165,7 +189,7 @@ def serialize_trie(autocorrections: List[Tuple[str, str]],
   table = []
 
   # Traverse trie in depth first order.
-  def traverse(trie_node):
+  def traverse(trie_node: Dict[str, Any]) -> Dict[str, Any]:
     if 'LEAF' in trie_node:  # Handle a leaf trie node.
       typo, correction = trie_node['LEAF']
       word_boundary_ending = typo[-1] == ':'
@@ -200,37 +224,35 @@ def serialize_trie(autocorrections: List[Tuple[str, str]],
 
   traverse(trie)
 
-  def serialize(e):
-    def kc_code(c):
-      if ord('a') <= ord(c) <= ord('z'):
-        return ord(c) - ord('a') + KC_A
-      elif c == ':':
-        return KC_SPC
-      else:
-        raise ValueError(f'Invalid character: {c}')
-
-    encode_link = lambda link: [link['byte_offset'] & 255,
-                                link['byte_offset'] >> 8]
-
+  def serialize(e: Dict[str, Any]) -> List[int]:
     if not e['links']:  # Handle a leaf table entry.
       return e['data']
     elif len(e['links']) == 1:  # Handle a chain table entry.
-      return list(map(kc_code, e['chars'])) + [0] #+ encode_link(e['links'][0]))
+      return [TYPO_CHARS[c] for c in e['chars']] + [0]
     else:  # Handle a branch table entry.
       data = []
       for c, link in zip(e['chars'], e['links']):
-        data += [kc_code(c) | (0 if data else 64)] + encode_link(link)
+        data += [TYPO_CHARS[c] | (0 if data else 64)] + encode_link(link)
       return data + [0]
 
   byte_offset = 0
   for e in table:  # To encode links, first compute byte offset of each entry.
     e['byte_offset'] = byte_offset
     byte_offset += len(serialize(e))
-    assert 0 <= byte_offset <= 0xffff
 
   return [b for e in table for b in serialize(e)]  # Serialize final table.
 
 
+def encode_link(link: Dict[str, Any]) -> List[int]:
+  """Encodes a node link as two bytes."""
+  byte_offset = link['byte_offset']
+  if not (0 <= byte_offset <= 0xffff):
+    print('Error: The autocorrection table is too large, a node link exceeds '
+          '64KB limit. Try reducing the autocorrection dict to fewer entries.')
+    sys.exit(1)
+  return [byte_offset & 255, byte_offset >> 8]
+
+
 def write_generated_code(autocorrections: List[Tuple[str, str]],
                          data: List[int],
                          file_name: str) -> None:
@@ -242,7 +264,10 @@ def write_generated_code(autocorrections: List[Tuple[str, str]],
     file_name: String, path of the output C file.
   """
   assert all(0 <= b <= 255 for b in data)
-  typo_len = lambda e: len(e[0])
+
+  def typo_len(e: Tuple[str, str]) -> int:
+    return len(e[0])
+
   min_typo = min(autocorrections, key=typo_len)[0]
   max_typo = max(autocorrections, key=typo_len)[0]
   generated_code = ''.join([
@@ -252,9 +277,8 @@ def write_generated_code(autocorrections: List[Tuple[str, str]],
                    for typo, correction in autocorrections)),
     f'\n#define AUTOCORRECTION_MIN_LENGTH {len(min_typo)}  // "{min_typo}"\n',
     f'#define AUTOCORRECTION_MAX_LENGTH {len(max_typo)}  // "{max_typo}"\n\n',
-    f'#define DICTIONARY_SIZE {len(data)}\n\n',
-    textwrap.fill('static const uint8_t autocorrection_data[DICTIONARY_SIZE] PROGMEM = {%s};' % (
-      ', '.join(map(str, data))), width=120, subsequent_indent='    '),
+    textwrap.fill('static const uint8_t autocorrection_data[%d] PROGMEM = {%s};' % (
+      len(data), ', '.join(map(str, data))), width=80, subsequent_indent='  '),
     '\n\n'])
 
   with open(file_name, 'wt') as f:
diff --git a/users/drashna/keyrecords/caps_word.c b/users/drashna/keyrecords/caps_word.c
deleted file mode 100644
index a152b2387b..0000000000
--- a/users/drashna/keyrecords/caps_word.c
+++ /dev/null
@@ -1,139 +0,0 @@
-#include "caps_word.h"
-
-static bool caps_word_active = false;
-
-#if CAPS_WORD_IDLE_TIMEOUT > 0
-#    if CAPS_WORD_IDLE_TIMEOUT < 100 || CAPS_WORD_IDLE_TIMEOUT > 30000
-// Constrain timeout to a sensible range. With the 16-bit timer, the longest
-// representable timeout is 32768 ms, rounded here to 30000 ms = half a minute.
-#        error "caps_word: CAPS_WORD_IDLE_TIMEOUT must be between 100 and 30000 ms"
-#    endif
-
-static uint16_t idle_timer = 0;
-
-void caps_word_task(void) {
-    if (caps_word_active && timer_expired(timer_read(), idle_timer)) {
-        caps_word_set(false);
-    }
-}
-#endif // CAPS_WORD_IDLE_TIMEOUT > 0
-
-bool process_caps_word(uint16_t keycode, keyrecord_t* record) {
-#ifndef NO_ACTION_ONESHOT
-    const uint8_t mods = get_mods() | get_oneshot_mods();
-#else
-    const uint8_t mods = get_mods();
-#endif // NO_ACTION_ONESHOT
-
-    if (!caps_word_active) {
-        // Pressing both shift keys at the same time enables caps word.
-        if ((mods & MOD_MASK_SHIFT) == MOD_MASK_SHIFT) {
-            caps_word_set(true); // Activate Caps Word.
-            return false;
-        }
-        return true;
-    } else {
-#if CAPS_WORD_IDLE_TIMEOUT > 0
-        idle_timer = record->event.time + CAPS_WORD_IDLE_TIMEOUT;
-#endif // CAPS_WORD_IDLE_TIMEOUT > 0
-    }
-
-    if (!record->event.pressed) {
-        return true;
-    }
-
-    if (!(mods & ~MOD_MASK_SHIFT)) {
-        switch (keycode) {
-            // Ignore MO, TO, TG, TT, and OSL layer switch keys.
-            case QK_MOMENTARY ... QK_MOMENTARY_MAX:
-            case QK_TO ... QK_TO_MAX:
-            case QK_TOGGLE_LAYER ... QK_TOGGLE_LAYER_MAX:
-            case QK_LAYER_TAP_TOGGLE ... QK_LAYER_TAP_TOGGLE_MAX:
-            case QK_ONE_SHOT_LAYER ... QK_ONE_SHOT_LAYER_MAX:
-                return true;
-
-#ifndef NO_ACTION_TAPPING
-            case QK_MOD_TAP ... QK_MOD_TAP_MAX:
-                if (record->tap.count == 0) {
-                    // Deactivate if a mod becomes active through holding a mod-tap key.
-                    caps_word_set(false);
-                    return true;
-                }
-                keycode &= 0xff;
-                break;
-
-#    ifndef NO_ACTION_LAYER
-            case QK_LAYER_TAP ... QK_LAYER_TAP_MAX:
-#    endif // NO_ACTION_LAYER
-                if (record->tap.count == 0) {
-                    return true;
-                }
-                keycode &= 0xff;
-                break;
-#endif // NO_ACTION_TAPPING
-
-#ifdef SWAP_HANDS_ENABLE
-            case QK_SWAP_HANDS ... QK_SWAP_HANDS_MAX:
-                if (keycode > 0x56F0 || record->tap.count == 0) {
-                    return true;
-                }
-                keycode &= 0xff;
-                break;
-#endif // SWAP_HANDS_ENABLE
-        }
-
-        if (caps_word_press_user(keycode)) {
-            return true;
-        }
-    }
-
-    caps_word_set(false); // Deactivate Caps Word.
-    return true;
-}
-
-void caps_word_set(bool active) {
-    if (active != caps_word_active) {
-        if (active) {
-            clear_mods();
-#ifndef NO_ACTION_ONESHOT
-            clear_oneshot_mods();
-#endif // NO_ACTION_ONESHOT
-#if CAPS_WORD_IDLE_TIMEOUT > 0
-            idle_timer = timer_read() + CAPS_WORD_IDLE_TIMEOUT;
-#endif // CAPS_WORD_IDLE_TIMEOUT > 0
-        } else if ((get_weak_mods() & MOD_BIT(KC_LSFT)) != 0) {
-            // If the weak shift mod is still on, turn it off and send an update to
-            // the host computer.
-            del_weak_mods(MOD_BIT(KC_LSFT));
-            send_keyboard_report();
-        }
-
-        caps_word_active = active;
-        caps_word_set_user(active);
-    }
-}
-
-bool caps_word_get(void) {
-    return caps_word_active;
-}
-
-__attribute__((weak)) void caps_word_set_user(bool active) {}
-
-__attribute__((weak)) bool caps_word_press_user(uint16_t keycode) {
-    switch (keycode) {
-        // Keycodes that continue Caps Word, with shift applied.
-        case KC_A ... KC_Z:
-            add_weak_mods(MOD_BIT(KC_LSFT)); // Apply shift to the next key.
-            return true;
-
-        // Keycodes that continue Caps Word, without shifting.
-        case KC_1 ... KC_0:
-        case KC_BSPC:
-        case KC_MINS:
-        case KC_UNDS:
-            return true;
-
-        default:
-            return false; // Deactivate Caps Word.
-    }
-}
diff --git a/users/drashna/keyrecords/caps_word.h b/users/drashna/keyrecords/caps_word.h
deleted file mode 100644
index 4279d7e831..0000000000
--- a/users/drashna/keyrecords/caps_word.h
+++ /dev/null
@@ -1,85 +0,0 @@
-// Copyright 2021 Google LLC.
-// SPDX-License-Identifier: Apache-2.0
-
-#pragma once
-
-#include "drashna.h"
-
-// Call this function from `process_record_user()` to implement Caps Word.
-bool process_caps_word(uint16_t keycode, keyrecord_t* record);
-
-// If CAPS_WORD_IDLE_TIMEOUT is set, call `caps_word_task()` from
-// `matrix_scan_user()` as described above.
-//
-// If CAPS_WORD_IDLE_TIMEOUT isn't set, calling this function has no effect (but
-// will still compile).
-#if CAPS_WORD_IDLE_TIMEOUT > 0
-void caps_word_task(void);
-#else
-static inline void caps_word_task(void) {}
-#endif
-
-// Activates or deactivates Caps Word. For instance activate Caps Word with a
-// combo by defining a `COMBO_ACTION` that calls `caps_word_set(true)`:
-//
-// void process_combo_event(uint16_t combo_index, bool pressed) {
-//   switch(combo_index) {
-//     case CAPS_COMBO:
-//       if (pressed) {
-//         caps_word_set(true);  // Activate Caps Word.
-//       }
-//       break;
-//
-//     // Other combos...
-//   }
-// }
-void caps_word_set(bool active);
-
-// Returns whether Caps Word is currently active.
-bool caps_word_get(void);
-
-// An optional callback that gets called when Caps Word turns on or off. This is
-// useful to represent the current Caps Word state, e.g. by setting an LED or
-// playing a sound. In your keymap, define
-//
-//   void caps_word_set_user(bool active) {
-//     if (active) {
-//       // Do something when Caps Word activates.
-//     } else {
-//       // Do something when Caps Word deactivates.
-//     }
-//   }
-void caps_word_set_user(bool active);
-
-// An optional callback which is called on every key press while Caps Word is
-// active. When the key should be shifted (that is, a letter key), the callback
-// should call `add_weak_mods(MOD_BIT(KC_LSFT))` to shift the key. The callback
-// also determines whether the key should continue Caps Word. Returning true
-// continues the current "word", while returning false is "word breaking" and
-// deactivates Caps Word. The default callback is
-//
-//   bool caps_word_press_user(uint16_t keycode) {
-//     switch (keycode) {
-//       // Keycodes that continue Caps Word, with shift applied.
-//       case KC_A ... KC_Z:
-//         add_weak_mods(MOD_BIT(KC_LSFT));  // Apply shift to the next key.
-//         return true;
-//
-//       // Keycodes that continue Caps Word, without shifting.
-//       case KC_1 ... KC_0:
-//       case KC_BSPC:
-//       case KC_MINS:
-//       case KC_UNDS:
-//         return true;
-//
-//       default:
-//         return false;  // Deactivate Caps Word.
-//     }
-//   }
-//
-// To customize, copy the above function into your keymap and add/remove
-// keycodes to the above cases.
-//
-// NOTE: Outside of this callback, you can use `caps_word_set(false)` to
-// deactivate Caps Word.
-bool caps_word_press_user(uint16_t keycode);
diff --git a/users/drashna/keyrecords/keycodes.md b/users/drashna/keyrecords/keycodes.md
index 348c68e46c..bb5b65a77c 100644
--- a/users/drashna/keyrecords/keycodes.md
+++ b/users/drashna/keyrecords/keycodes.md
@@ -5,14 +5,9 @@ Keycodes are defined in the `process_record.h` file and need to be included in t
 
 A bunch of macros are present and are only included on boards that are not the Ergodox EZ or Orthodox, as they are not needed for those boards. 
 
-* `KC_MAKE` - outputs `qmk compile -kb (keyboard) -km (keymap)` and enter, to start compiling the currenct keyboard.  This uses generated variables to always use the current keyboard and keymap.  Will work with any keyboard and any keymap.
-  * If you are holding shift, it will use `qmk flash` instead of `qmk compile`.
-  * If `MAKE_BOOTLOADER` is defined, it will always use `qmk flash` instead of `qmk compile`.
 * `DEFAULT_LAYER_1` ... `DEFAULT_LAYER_4` - This sets layer 0-3 as the default layer, and writes that to eeprom, and plays a chime. 
 * `VRSN`, outputs the keyboard, keymap, commit and date info.  Eg:
   * `handwired/tractyl_manuform/5x6_right/f411/drashna @ 0.15.9-162-g087d08, Built on: 2021-12-19-21:10:26`
 *  `KC_DIABLO_CLEAR` - clears the diablo tapdance status.
 * `KC_CCCV` - Copy on hold, paste on tap.
 * `KEYLOCK` - This unloads the host driver, and prevents any data from being sent to the host. Hitting it again loads the driver, back. 
-* `REBOOT` - Uses watchdog timer on AVR, and `NVIC_SystemReset()` on ChibiOS to reset the board, without jumping to the bootloader.
-* `EEP_RST` - Overrides the default behavior, disables EEPROM (which will trigger a reset on init), and reboots the keyboard as per `REBOOT` keycode. 
diff --git a/users/drashna/keyrecords/process_records.c b/users/drashna/keyrecords/process_records.c
index 99267d88a8..240156e816 100644
--- a/users/drashna/keyrecords/process_records.c
+++ b/users/drashna/keyrecords/process_records.c
@@ -3,9 +3,6 @@
 
 #include "drashna.h"
 #include "version.h"
-#ifdef CAPS_WORD_ENABLE
-#    include "caps_word.h"
-#endif
 #ifdef AUTOCORRECTION_ENABLE
 #    include "autocorrection/autocorrection.h"
 #endif
@@ -37,6 +34,15 @@ __attribute__((weak)) bool process_record_secrets(uint16_t keycode, keyrecord_t
  * @return false Stop process keycode and do not send to host
  */
 bool process_record_user(uint16_t keycode, keyrecord_t *record) {
+#ifdef ENCODER_ENABLE // some debouncing for weird issues
+    if (IS_ENCODEREVENT(record->event)) {
+        static bool ignore_first = true;
+        if (ignore_first) {
+            ignore_first = false;
+            return false;
+        }
+    }
+#endif
     // If console is enabled, it will print the matrix position and status of each key pressed
 #ifdef KEYLOGGER_ENABLE
     uprintf("KL: kc: 0x%04X, col: %2u, row: %2u, pressed: %b, time: %5u, int: %b, count: %u\n", keycode, record->event.key.col, record->event.key.row, record->event.pressed, record->event.time, record->tap.interrupted, record->tap.count);
@@ -58,9 +64,6 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
 #if defined(CUSTOM_POINTING_DEVICE)
           && process_record_pointing(keycode, record)
 #endif
-#ifdef CAPS_WORD_ENABLE
-          && process_caps_word(keycode, record)
-#endif
 #ifdef AUTOCORRECTION_ENABLE
           && process_autocorrection(keycode, record)
 #endif
@@ -87,33 +90,6 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
             }
             break;
 
-        case KC_MAKE:  // Compiles the firmware, and adds the flash command based on keyboard bootloader
-            if (!record->event.pressed) {
-#ifndef MAKE_BOOTLOADER
-                uint8_t temp_mod = mod_config(get_mods());
-                uint8_t temp_osm = mod_config(get_oneshot_mods());
-                clear_mods();
-                clear_oneshot_mods();
-#endif
-                send_string_with_delay_P(PSTR("qmk"), TAP_CODE_DELAY);
-#ifndef MAKE_BOOTLOADER
-                if ((temp_mod | temp_osm) & MOD_MASK_SHIFT)
-#endif
-                {
-                    send_string_with_delay_P(PSTR(" flash "), TAP_CODE_DELAY);
-#ifndef MAKE_BOOTLOADER
-                } else {
-                    send_string_with_delay_P(PSTR(" compile "), TAP_CODE_DELAY);
-#endif
-                }
-                send_string_with_delay_P(PSTR("-kb " QMK_KEYBOARD " -km " QMK_KEYMAP), TAP_CODE_DELAY);
-#ifdef CONVERT_TO_PROTON_C
-                send_string_with_delay_P(PSTR(" -e CTPC=yes"), TAP_CODE_DELAY);
-#endif
-                send_string_with_delay_P(PSTR(SS_TAP(X_ENTER)), TAP_CODE_DELAY);
-            }
-            break;
-
         case VRSN:  // Prints firmware version
             if (record->event.pressed) {
                 send_string_with_delay_P(PSTR(QMK_KEYBOARD "/" QMK_KEYMAP " @ " QMK_VERSION ", Built on: " QMK_BUILDDATE), TAP_CODE_DELAY);
@@ -148,13 +124,19 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
                 dprintf("rgblight layer change [EEPROM]: %u\n", userspace_config.rgb_layer_change);
                 eeconfig_update_user(userspace_config.raw);
                 if (userspace_config.rgb_layer_change) {
-#    if defined(CUSTOM_RGBLIGHT) && defined(CUSTOM_RGB_MATRIX)
+#    if defined(CUSTOM_RGB_MATRIX)
+                    rgb_matrix_set_flags(LED_FLAG_UNDERGLOW | LED_FLAG_KEYLIGHT | LED_FLAG_INDICATOR);
+#        if defined(CUSTOM_RGBLIGHT)
                     rgblight_enable_noeeprom();
+#        endif
 #    endif
-                    layer_state_set(layer_state);  // This is needed to immediately set the layer color (looks better)
-#    if defined(CUSTOM_RGBLIGHT) && defined(CUSTOM_RGB_MATRIX)
+                    layer_state_set(layer_state); // This is needed to immediately set the layer color (looks better)
+#    if defined(CUSTOM_RGB_MATRIX)
                 } else {
+                    rgb_matrix_set_flags(LED_FLAG_ALL);
+#        if defined(CUSTOM_RGBLIGHT)
                     rgblight_disable_noeeprom();
+#        endif
 #    endif
                 }
             }
@@ -218,23 +200,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
             }
             break;
         }
-        case EEP_RST:
-            if (record->event.pressed) {
-                eeconfig_disable();
-                shutdown_user();
-#ifdef __AVR__
-                wdt_enable(WDTO_250MS);
-#else
-                NVIC_SystemReset();
-#endif
-            }
-            return false;
-        case REBOOT:
-            if (record->event.pressed) {
-                software_reset();
-            }
-            return false;
-    }
+     }
     return true;
 }
 
diff --git a/users/drashna/keyrecords/process_records.h b/users/drashna/keyrecords/process_records.h
index 5ca2966131..e83e4ce308 100644
--- a/users/drashna/keyrecords/process_records.h
+++ b/users/drashna/keyrecords/process_records.h
@@ -21,7 +21,6 @@ enum userspace_custom_keycodes {
     KC_DVORAK,                                // Sets default layer to DVORAK
     LAST_DEFAULT_LAYER_KEYCODE = KC_DVORAK,   // Sets default layer to WORKMAN
     KC_DIABLO_CLEAR,                          // Clears all Diablo Timers
-    KC_MAKE,                                  // Run keyboard's customized make command
     KC_RGB_T,                                 // Toggles RGB Layer Indication mode
     RGB_IDL,                                  // RGB Idling animations
     KC_SECRET_1,                              // test1
@@ -46,8 +45,9 @@ enum userspace_custom_keycodes {
     KC_AUSSIE,
     KC_ZALGO,
     KC_ACCEL,
-    AUTO_CTN,                                 // Toggle Autocorrect status
-    REBOOT,
+    AUTOCORRECT_ON,
+    AUTOCORRECT_OFF,
+    AUTOCORRECT_TOGGLE,
     NEW_SAFE_RANGE                            // use "NEWPLACEHOLDER for keymap specific codes
 };
 
@@ -95,9 +95,6 @@ bool process_record_unicode(uint16_t keycode, keyrecord_t *record);
 #    endif
 #endif
 
-#define KC_RESET RESET
-#define KC_RST   KC_RESET
-
 #ifdef SWAP_HANDS_ENABLE
 #    define KC_C1R3 SH_T(KC_TAB)
 #elif defined(DRASHNA_LP)
@@ -130,7 +127,7 @@ bool process_record_unicode(uint16_t keycode, keyrecord_t *record);
 
 #define MG_NKRO MAGIC_TOGGLE_NKRO
 
-
+#define AUTO_CTN AUTOCORRECT_TOGGLE
 /*
 Custom Keycodes for Diablo 3 layer
 But since TD() doesn't work when tap dance is disabled
diff --git a/users/drashna/keyrecords/secrets.md b/users/drashna/keyrecords/secrets.md
index a9408dc2ef..3c40fa41b3 100644
--- a/users/drashna/keyrecords/secrets.md
+++ b/users/drashna/keyrecords/secrets.md
@@ -24,14 +24,12 @@ secrets.h
 Here is the magic. This handles including the "secrets", and adding the custom macros to send them. 
 
 ```c
-#include "drashna.h"  // replace with your keymap's "h" file, or whatever file stores the keycodes
+#include QMK_KEYBOARD_H
 
 #if (__has_include("secrets.h") && !defined(NO_SECRETS))
 #include "secrets.h"
 #else
-// `PROGMEM const char secret[][x]` may work better, but it takes up more space in the firmware
-// And I'm not familiar enough to know which is better or why...
-static const char * const secret[] = {
+static const char * const secrets[] = {
   "test1",
   "test2",
   "test3",
@@ -43,9 +41,10 @@ static const char * const secret[] = {
 bool process_record_secrets(uint16_t keycode, keyrecord_t *record) {
   switch (keycode) {
     case KC_SECRET_1 ... KC_SECRET_5: // Secrets!  Externally defined strings, not stored in repo
-      if (!record->event.pressed) {
-        clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
-        send_string_with_delay(secret[keycode - KC_SECRET_1], MACRO_TIMER);
+      if (record->event.pressed) {
+        clear_mods();
+        clear_oneshot_mods();
+        send_string_with_delay(secrets[keycode - KC_SECRET_1], MACRO_TIMER);
       }
       return false;
       break;
@@ -59,7 +58,7 @@ bool process_record_secrets(uint16_t keycode, keyrecord_t *record) {
 Now, for the actual secrets!  The file needs to look like 
 
 ```c
-static const char *  secrets[] = {
+static const char * secrets[] = {
   "secret1",
   "secret2",
   "secret3",
@@ -96,7 +95,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
 
 Here, you want your `/users/<name>/rules.mk` file to "detect" the existence of the `secrets.c` file, and only add it if the file exists.  
 
-Additionally, to ensure that it's not added or processed in any way, it checks to see if `NO_SECRETS` is set. This way, if you run `make keyboard:name NO_SECRETS=yes`, it will remove the feature altogether. 
+Additionally, to ensure that it's not added or processed in any way, it checks to see if `NO_SECRETS` is set. This way, if you run `qmk compile -kb keyboard -km name -e NO_SECRETS=yes`, it will remove the feature altogether. 
 
 ```make
 ifneq ($(strip $(NO_SECRETS)), yes)
diff --git a/users/drashna/keyrecords/unicode.c b/users/drashna/keyrecords/unicode.c
index af87ee2a61..c1fe8df2c3 100644
--- a/users/drashna/keyrecords/unicode.c
+++ b/users/drashna/keyrecords/unicode.c
@@ -4,9 +4,10 @@
 // SPDX-License-Identifier: GPL-2.0-or-later
 
 #include "drashna.h"
+#include "unicode.h"
 #include "process_unicode_common.h"
 
-uint16_t typing_mode = KC_NOMODE;
+uint8_t typing_mode = UCTM_NO_MODE;
 
 /**
  * @brief Registers the unicode keystrokes based on desired unicode
@@ -242,10 +243,10 @@ bool process_record_unicode(uint16_t keycode, keyrecord_t *record) {
             break;
         case KC_NOMODE ... KC_ZALGO:
             if (record->event.pressed) {
-                if (typing_mode != keycode) {
-                    typing_mode = keycode;
+                if (typing_mode != keycode - KC_NOMODE) {
+                    typing_mode = keycode - KC_NOMODE;
                 } else {
-                    typing_mode = KC_NOMODE;
+                    typing_mode = UCTM_NO_MODE;
                 }
             }
             break;
@@ -259,19 +260,19 @@ bool process_record_unicode(uint16_t keycode, keyrecord_t *record) {
         keycode &= 0xFF;
     }
 
-    if (typing_mode == KC_WIDE) {
+    if (typing_mode == UCTM_WIDE) {
         if (((KC_A <= keycode) && (keycode <= KC_0)) || keycode == KC_SPACE) {
             return process_record_glyph_replacement(keycode, record, unicode_range_translator_wide);
         }
-    } else if (typing_mode == KC_SCRIPT) {
+    } else if (typing_mode == UCTM_SCRIPT) {
         if (((KC_A <= keycode) && (keycode <= KC_0)) || keycode == KC_SPACE) {
             return process_record_glyph_replacement(keycode, record, unicode_range_translator_script);
         }
-    } else if (typing_mode == KC_BLOCKS) {
+    } else if (typing_mode == UCTM_BLOCKS) {
         if (((KC_A <= keycode) && (keycode <= KC_0)) || keycode == KC_SPACE) {
             return process_record_glyph_replacement(keycode, record, unicode_range_translator_boxes);
         }
-    } else if (typing_mode == KC_REGIONAL) {
+    } else if (typing_mode == UCTM_REGIONAL) {
         if (((KC_A <= keycode) && (keycode <= KC_0)) || keycode == KC_SPACE) {
             if (!process_record_glyph_replacement(keycode, record, unicode_range_translator_regional)) {
                 wait_us(500);
@@ -279,9 +280,9 @@ bool process_record_unicode(uint16_t keycode, keyrecord_t *record) {
                 return false;
             }
         }
-    } else if (typing_mode == KC_AUSSIE) {
+    } else if (typing_mode == UCTM_AUSSIE) {
         return process_record_aussie(keycode, record);
-    } else if (typing_mode == KC_ZALGO) {
+    } else if (typing_mode == UCTM_ZALGO) {
         return process_record_zalgo(keycode, record);
     }
     return true;
diff --git a/users/drashna/keyrecords/unicode.h b/users/drashna/keyrecords/unicode.h
new file mode 100644
index 0000000000..dd261d3406
--- /dev/null
+++ b/users/drashna/keyrecords/unicode.h
@@ -0,0 +1,16 @@
+// Copyright 2020 Christopher Courtney, aka Drashna Jael're  (@drashna) <drashna@live.com>
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+enum unicode_typing_mode {
+    UCTM_NO_MODE,
+    UCTM_WIDE,
+    UCTM_SCRIPT,
+    UCTM_BLOCKS,
+    UCTM_REGIONAL,
+    UCTM_AUSSIE,
+    UCTM_ZALGO,
+};
+
+extern uint8_t typing_mode;
diff --git a/users/drashna/oled/oled_stuff.c b/users/drashna/oled/oled_stuff.c
index 2a26b8b638..8c76897fba 100644
--- a/users/drashna/oled/oled_stuff.c
+++ b/users/drashna/oled/oled_stuff.c
@@ -18,19 +18,23 @@
 #include "drashna.h"
 #ifdef UNICODE_COMMON_ENABLE
 #    include "process_unicode_common.h"
+#    include "keyrecords/unicode.h"
+#endif
+#ifdef AUDIO_CLICKY
+#    include "process_clicky.h"
+#endif
+#if defined(AUTOCORRECTION_ENABLE)
+#    include "keyrecords/autocorrection/autocorrection.h"
 #endif
-#    ifdef AUDIO_CLICKY
-#        include "process_clicky.h"
-#    endif
 #include <string.h>
 
 extern bool host_driver_disabled;
 
-uint32_t                  oled_timer                        = 0;
-char                      keylog_str[OLED_KEYLOGGER_LENGTH] = {0};
-static uint16_t           log_timer                         = 0;
+uint32_t        oled_timer                        = 0;
+char            keylog_str[OLED_KEYLOGGER_LENGTH] = {0};
+static uint16_t log_timer                         = 0;
 #ifdef OLED_DISPLAY_VERBOSE
-static const char PROGMEM display_border[3]                 = {0x0, 0xFF, 0x0};
+static const char PROGMEM display_border[3] = {0x0, 0xFF, 0x0};
 #endif
 
 deferred_token kittoken;
@@ -100,12 +104,15 @@ void add_keylog(uint16_t keycode, keyrecord_t *record) {
  */
 bool process_record_user_oled(uint16_t keycode, keyrecord_t *record) {
     if (record->event.pressed) {
-        oled_timer = timer_read32();
+        oled_timer_reset();
         add_keylog(keycode, record);
     }
     return true;
 }
 
+void oled_timer_reset(void) {
+    oled_timer = timer_read32();
+}
 /**
  * @brief Renders keylogger buffer to oled
  *
@@ -262,9 +269,8 @@ void render_layer_state(void) {
         }
     };
 
-
     // clang-format on
-    uint8_t layer_is[4] = { 0, 4, 4, 4};
+    uint8_t layer_is[4] = {0, 4, 4, 4};
     if (layer_state_is(_ADJUST)) {
         layer_is[0] = 3;
     } else if (layer_state_is(_RAISE)) {
@@ -280,7 +286,6 @@ void render_layer_state(void) {
         layer_is[2] = 5;
     }
 
-
     oled_set_cursor(1, 2);
     oled_write_raw_P(tri_layer_image[layer_is[0]][0], sizeof(tri_layer_image[0][0]));
     oled_set_cursor(5, 2);
@@ -322,7 +327,7 @@ void render_layer_state(void) {
  *
  * @param led_usb_state Current keyboard led state
  */
-void render_keylock_status(uint8_t led_usb_state) {
+void render_keylock_status(led_t led_usb_state) {
 #if defined(OLED_DISPLAY_VERBOSE)
     oled_set_cursor(1, 6);
 #endif
@@ -330,12 +335,12 @@ void render_keylock_status(uint8_t led_usb_state) {
 #if !defined(OLED_DISPLAY_VERBOSE)
     oled_write_P(PSTR(" "), false);
 #endif
-    oled_write_P(PSTR(OLED_RENDER_LOCK_NUML), led_usb_state & (1 << USB_LED_NUM_LOCK));
+    oled_write_P(PSTR(OLED_RENDER_LOCK_NUML), led_usb_state.num_lock);
     oled_write_P(PSTR(" "), false);
-    oled_write_P(PSTR(OLED_RENDER_LOCK_CAPS), led_usb_state & (1 << USB_LED_CAPS_LOCK));
+    oled_write_P(PSTR(OLED_RENDER_LOCK_CAPS), led_usb_state.caps_lock);
 #if defined(OLED_DISPLAY_VERBOSE)
     oled_write_P(PSTR(" "), false);
-    oled_write_P(PSTR(OLED_RENDER_LOCK_SCLK), led_usb_state & (1 << USB_LED_SCROLL_LOCK));
+    oled_write_P(PSTR(OLED_RENDER_LOCK_SCLK), led_usb_state.scroll_lock);
 #endif
 }
 
@@ -417,15 +422,14 @@ void render_bootmagic_status(void) {
         oled_write_P(logo[0][0], !is_bootmagic_on);
     }
 #ifndef OLED_DISPLAY_VERBOSE
-    oled_write_P(PSTR(" "), false);
     oled_write_P(logo[1][1], is_bootmagic_on);
     oled_write_P(logo[0][1], !is_bootmagic_on);
 #endif
     oled_write_P(PSTR(" "), false);
     oled_write_P(PSTR(OLED_RENDER_BOOTMAGIC_NKRO), keymap_config.nkro);
     oled_write_P(PSTR(" "), false);
-#ifdef AUTOCORRECTION_ENABLE
-    oled_write_P(PSTR("CRCT"), userspace_config.autocorrection);
+#if defined(AUTOCORRECTION_ENABLE) || defined(AUTOCORRECT_ENABLE)
+    oled_write_P(PSTR("CRCT"), autocorrect_is_enabled());
     oled_write_P(PSTR(" "), false);
 #else
     oled_write_P(PSTR(OLED_RENDER_BOOTMAGIC_NOGUI), keymap_config.no_gui);
@@ -439,7 +443,7 @@ void render_bootmagic_status(void) {
     }
 #endif
     oled_write_P(PSTR(" "), false);
-    oled_write_P(PSTR(OLED_RENDER_BOOTMAGIC_ONESHOT), !is_oneshot_enabled());
+    oled_write_P(PSTR(OLED_RENDER_BOOTMAGIC_ONESHOT), is_oneshot_enabled());
 #ifdef SWAP_HANDS_ENABLE
     oled_write_P(PSTR(" "), false);
     oled_write_P(PSTR(OLED_RENDER_BOOTMAGIC_SWAP), swap_hands);
@@ -461,7 +465,7 @@ void render_user_status(void) {
     l_is_clicky_on = user_state.audio_clicky_enable;
 #        endif
 #    else
-    is_audio_on  = is_audio_on();
+    is_audio_on    = is_audio_on();
 #        ifdef AUDIO_CLICKY
     l_is_clicky_on = is_clicky_on();
 #        endif
@@ -501,7 +505,7 @@ void render_user_status(void) {
     static const char PROGMEM cat_mode[2][3] = {{0xF8, 0xF9, 0}, {0xF6, 0xF7, 0}};
     oled_write_P(cat_mode[0], host_driver_disabled);
 #if defined(UNICODE_COMMON_ENABLE)
-    static const char PROGMEM uc_mod_status[5][3] = {{0xEC, 0xED, 0},  {0x20, 0x20, 0},  {0x20, 0x20, 0}, {0x20, 0x20, 0}, {0xEA, 0xEB, 0}};
+    static const char PROGMEM uc_mod_status[5][3] = {{0xEC, 0xED, 0}, {0x20, 0x20, 0}, {0x20, 0x20, 0}, {0x20, 0x20, 0}, {0xEA, 0xEB, 0}};
     oled_write_P(uc_mod_status[get_unicode_input_mode()], false);
 #endif
     if (userspace_config.nuke_switch) {
@@ -549,9 +553,9 @@ void render_wpm_graph(uint8_t max_lines_graph, uint8_t vertical_offset) {
     uint8_t         currwpm = get_current_wpm();
     float           max_wpm = OLED_WPM_GRAPH_MAX_WPM;
 
-    if (timer_elapsed(timer) > OLED_WPM_GRAPH_REFRESH_INTERVAL) {                                  // check if it's been long enough before refreshing graph
-        x = (max_lines_graph - 1) - ((currwpm / max_wpm) * (max_lines_graph - 1));  // main calculation to plot graph line
-        for (uint8_t i = 0; i <= OLED_WPM_GRAPH_GRAPH_LINE_THICKNESS - 1; i++) {                   // first draw actual value line
+    if (timer_elapsed(timer) > OLED_WPM_GRAPH_REFRESH_INTERVAL) {                  // check if it's been long enough before refreshing graph
+        x = (max_lines_graph - 1) - ((currwpm / max_wpm) * (max_lines_graph - 1)); // main calculation to plot graph line
+        for (uint8_t i = 0; i <= OLED_WPM_GRAPH_GRAPH_LINE_THICKNESS - 1; i++) {   // first draw actual value line
             oled_write_pixel(3, x + i + vertical_offset, true);
         }
 #    ifdef OLED_WPM_GRAPH_VERTICAL_LINE
@@ -577,20 +581,11 @@ void render_wpm_graph(uint8_t max_lines_graph, uint8_t vertical_offset) {
             }
         }
 #    endif
-        oled_pan(false);  // then move the entire graph one pixel to the right
-        static const char PROGMEM display_border[3] = {0x0, 0xFF, 0x0};
-        for (uint8_t i = 0; i < 7; i++) {
-            oled_set_cursor(0, i + 8);
-            oled_write_raw_P(display_border, sizeof(display_border));
-            oled_set_cursor(21, i + 8);
-            oled_write_raw_P(display_border, sizeof(display_border));
-        }
-        static const char PROGMEM footer_image[] = {0, 3, 4, 8, 16, 32, 64, 128, 128, 128, 128, 128, 128, 128, 192, 224, 240, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 240, 224, 192, 128, 128, 128, 128, 128, 128, 128, 64, 32, 16, 8, 4, 3, 0};
-        oled_set_cursor(0, 15);
-
-        oled_write_raw_P(footer_image, sizeof(footer_image));
-
-        timer = timer_read();  // refresh the timer for the next iteration
+#    include <math.h>
+        uint8_t y_start  = ceil(vertical_offset / 8);
+        uint8_t y_length = y_start + ceil(max_lines_graph / 8);
+        oled_pan_section(false, y_start, y_length, 3, 125); // then move the entire graph one pixel to the right
+        timer = timer_read();                               // refresh the timer for the next iteration
     }
 #endif
 }
@@ -617,13 +612,13 @@ __attribute__((weak)) void oled_driver_render_logo_right(void) {
 
 // WPM-responsive animation stuff here
 #define OLED_SLEEP_FRAMES 2
-#define OLED_SLEEP_SPEED 10  // below this wpm value your animation will idle
+#define OLED_SLEEP_SPEED 10 // below this wpm value your animation will idle
 
-#define OLED_WAKE_FRAMES 2                // uncomment if >1
-#define OLED_WAKE_SPEED OLED_SLEEP_SPEED  // below this wpm value your animation will idle
+#define OLED_WAKE_FRAMES 2               // uncomment if >1
+#define OLED_WAKE_SPEED OLED_SLEEP_SPEED // below this wpm value your animation will idle
 
 #define OLED_KAKI_FRAMES 3
-#define OLED_KAKI_SPEED 40  // above this wpm value typing animation to triggere
+#define OLED_KAKI_SPEED 40 // above this wpm value typing animation to triggere
 
 #define OLED_RTOGI_FRAMES 2
 //#define OLED_LTOGI_FRAMES 2
@@ -781,25 +776,13 @@ void oled_driver_render_logo_left(void) {
 #    if (defined(KEYBOARD_bastardkb_charybdis) || defined(KEYBOARD_handwired_tractyl_manuform)) && defined(POINTING_DEVICE_ENABLE)
     render_pointing_dpi_status(charybdis_get_pointer_sniping_enabled() ? charybdis_get_pointer_sniping_dpi() : charybdis_get_pointer_default_dpi(), 1);
 
-// credit and thanks to jaspertandy on discord for these images
-    static const char PROGMEM mouse_logo[3][2][16] = {
-        // mouse icon
-        {
-            {   0,   0,   0, 252,   2,   2,   2,  58,   2,   2,   2, 252,   0,   0,   0,   0 },
-            {   0,   0,  63,  96,  64,  64,  64,  64,  64,  64,  64,  96,  63,   0,   0,   0 }
-        },
-        // crosshair icon
-        {
-            { 128, 240, 136, 228, 146, 138, 202, 127, 202, 138, 146, 228, 136, 240, 128,   0 },
-            {   0,   7,   8,  19,  36,  40,  41, 127,  41,  40,  36,  19,   8,   7,   0,   0 }
-        },
-        // dragscroll icon
-        {
-            {   0,   0, 112, 136, 156,   2,  15,   1,  15,   2, 140,  68,  56,   0,   0,   0 },
-            {   0,   0,   2,   6,  15,  28,  60, 124,  60,  28,  15,   6,   2,   0,   0,   0 }
-        }
-    };
-
+    // credit and thanks to jaspertandy on discord for these images
+    static const char PROGMEM mouse_logo[3][2][16] = {// mouse icon
+                                                      {{0, 0, 0, 252, 2, 2, 2, 58, 2, 2, 2, 252, 0, 0, 0, 0}, {0, 0, 63, 96, 64, 64, 64, 64, 64, 64, 64, 96, 63, 0, 0, 0}},
+                                                      // crosshair icon
+                                                      {{128, 240, 136, 228, 146, 138, 202, 127, 202, 138, 146, 228, 136, 240, 128, 0}, {0, 7, 8, 19, 36, 40, 41, 127, 41, 40, 36, 19, 8, 7, 0, 0}},
+                                                      // dragscroll icon
+                                                      {{0, 0, 112, 136, 156, 2, 15, 1, 15, 2, 140, 68, 56, 0, 0, 0}, {0, 0, 2, 6, 15, 28, 60, 124, 60, 28, 15, 6, 2, 0, 0, 0}}};
 
     uint8_t image_index = 0;
 #        ifdef OLED_DISPLAY_TEST
@@ -847,7 +830,7 @@ void render_status_right(void) {
 #if !defined(OLED_DISPLAY_VERBOSE) && defined(WPM_ENABLE) && !defined(CONVERT_TO_PROTON_C)
     render_wpm(2);
 #endif
-    render_keylock_status(host_keyboard_leds());
+    render_keylock_status(host_keyboard_led_state());
 }
 
 void render_status_left(void) {
@@ -860,9 +843,11 @@ void render_status_left(void) {
     render_keylogger_status();
 }
 
-__attribute__((weak)) void oled_render_large_display(void) {}
+__attribute__((weak)) void oled_render_large_display(bool side) {}
 
-__attribute__((weak)) oled_rotation_t oled_init_keymap(oled_rotation_t rotation) { return rotation; }
+__attribute__((weak)) oled_rotation_t oled_init_keymap(oled_rotation_t rotation) {
+    return rotation;
+}
 
 oled_rotation_t oled_init_user(oled_rotation_t rotation) {
     if (is_keyboard_master()) {
@@ -876,10 +861,11 @@ oled_rotation_t oled_init_user(oled_rotation_t rotation) {
     return oled_init_keymap(rotation);
 }
 
-__attribute__((weak)) bool oled_task_keymap(void) { return true; }
+__attribute__((weak)) bool oled_task_keymap(void) {
+    return true;
+}
 
 bool oled_task_user(void) {
-
     if (is_keyboard_master()) {
 #ifndef OLED_DISPLAY_TEST
         if (timer_elapsed32(oled_timer) > 60000) {
@@ -896,29 +882,29 @@ bool oled_task_user(void) {
         return false;
     }
 
-#if defined(OLED_DISPLAY_128X128)
-    oled_set_cursor(0, 7);
-    oled_render_large_display();
-#endif
-
 #if defined(OLED_DISPLAY_VERBOSE)
     static const char PROGMEM header_image[] = {
         0, 192, 32, 16, 8, 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, 3, 7, 15, 31, 63, 127, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 127, 63, 31, 15, 7, 3, 1, 1, 1, 1, 1, 1, 1, 1, 2, 4, 8, 16, 32, 192, 0,
         //         0,255,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  3,  7, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,  7,  3,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,255,  0
     };
-    static const char PROGMEM footer_image[] = {0, 3, 4, 8, 16, 32, 64, 128, 128, 128, 128, 128, 128, 128, 192, 224, 240, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 240, 224, 192, 128, 128, 128, 128, 128, 128, 128, 64, 32, 16, 8, 4, 3, 0};
-    oled_set_cursor(0, 0);
     oled_write_raw_P(header_image, sizeof(header_image));
-    oled_set_cursor(0, 1);
 #endif
 
 #ifndef OLED_DISPLAY_TEST
     if (is_keyboard_left()) {
 #endif
         render_status_left();
+#if defined(OLED_DISPLAY_128X128)
+        oled_set_cursor(0, 7);
+        oled_render_large_display(true);
+#endif
 #ifndef OLED_DISPLAY_TEST
     } else {
         render_status_right();
+#    if defined(OLED_DISPLAY_128X128)
+        oled_set_cursor(0, 7);
+        oled_render_large_display(false);
+#    endif
     }
 #endif
 
@@ -936,6 +922,7 @@ bool oled_task_user(void) {
         oled_write_raw_P(display_border, sizeof(display_border));
     }
 
+    static const char PROGMEM footer_image[] = {0, 3, 4, 8, 16, 32, 64, 128, 128, 128, 128, 128, 128, 128, 192, 224, 240, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 240, 224, 192, 128, 128, 128, 128, 128, 128, 128, 64, 32, 16, 8, 4, 3, 0};
     oled_set_cursor(0, num_of_rows);
     oled_write_raw_P(footer_image, sizeof(footer_image));
 #endif
diff --git a/users/drashna/oled/oled_stuff.h b/users/drashna/oled/oled_stuff.h
index 7245f6131c..4dea4b7be4 100644
--- a/users/drashna/oled/oled_stuff.h
+++ b/users/drashna/oled/oled_stuff.h
@@ -23,11 +23,11 @@ extern deferred_token kittoken;
 void            oled_driver_render_logo(void);
 bool            process_record_user_oled(uint16_t keycode, keyrecord_t *record);
 oled_rotation_t oled_init_keymap(oled_rotation_t rotation);
-extern uint32_t oled_timer;
+void            oled_timer_reset(void);
 void            render_keylogger_status(void);
 void            render_default_layer_state(void);
 void            render_layer_state(void);
-void            render_keylock_status(uint8_t led_usb_state);
+void            render_keylock_status(led_t led_usb_state);
 void            render_matrix_scan_rate(uint8_t padding);
 void            render_mod_status(uint8_t modifiers);
 void            render_bootmagic_status(void);
@@ -37,9 +37,12 @@ void            render_wpm(uint8_t padding);
 void            render_pointing_dpi_status(uint16_t cpi, uint8_t padding);
 void            oled_driver_render_logo_left(void);
 void            oled_driver_render_logo_right(void);
-void            oled_render_large_display(void);
+void            oled_render_large_display(bool side);
 void render_wpm_graph(uint8_t max_lines_graph, uint8_t vertical_offset);
 
+void oled_pan_section(bool left, uint16_t y_start, uint16_t y_end, uint16_t x_start, uint16_t x_end);
+
+
 #if defined(OLED_DISPLAY_128X128) || defined(OLED_DISPLAY_128X64)
 #    define OLED_DISPLAY_VERBOSE
 
diff --git a/users/drashna/oled/sh110x.c b/users/drashna/oled/sh110x.c
index cfdae1db16..aa081ca732 100644
--- a/users/drashna/oled/sh110x.c
+++ b/users/drashna/oled/sh110x.c
@@ -521,6 +521,25 @@ void oled_pan(bool left) {
     oled_dirty = OLED_ALL_BLOCKS_MASK;
 }
 
+void oled_pan_section(bool left, uint16_t y_start, uint16_t y_end, uint16_t x_start, uint16_t x_end) {
+    uint16_t i = 0;
+    for (uint16_t y = y_start; y < y_end; y++) {
+        if (left) {
+            for (uint16_t x = x_start; x < x_end - 1; x++) {
+                i              = y * OLED_DISPLAY_WIDTH + x;
+                oled_buffer[i] = oled_buffer[i + 1];
+                oled_dirty |= ((OLED_BLOCK_TYPE)1 << (i / OLED_BLOCK_SIZE));
+            }
+        } else {
+            for (uint16_t x = x_end - 1; x > 0; x--) {
+                i              = y * OLED_DISPLAY_WIDTH + x;
+                oled_buffer[i] = oled_buffer[i - 1];
+                oled_dirty |= ((OLED_BLOCK_TYPE)1 << (i / OLED_BLOCK_SIZE));
+            }
+        }
+    }
+}
+
 oled_buffer_reader_t oled_read_raw(uint16_t start_index) {
     if (start_index > OLED_MATRIX_SIZE) start_index = OLED_MATRIX_SIZE;
     oled_buffer_reader_t ret_reader;
diff --git a/users/drashna/pointing/pointing.c b/users/drashna/pointing/pointing.c
index 2e313ba574..551034ff45 100644
--- a/users/drashna/pointing/pointing.c
+++ b/users/drashna/pointing/pointing.c
@@ -29,7 +29,7 @@ report_mouse_t pointing_device_task_user(report_mouse_t mouse_report) {
     if (x != 0 && y != 0) {
         mouse_timer = timer_read();
 #ifdef OLED_ENABLE
-        oled_timer = timer_read32();
+        oled_timer_reset();
 #endif
         if (timer_elapsed(mouse_debounce_timer) > TAP_CHECK) {
             if (enable_acceleration) {
@@ -94,8 +94,10 @@ bool process_record_pointing(uint16_t keycode, keyrecord_t* record) {
             record->event.pressed ? mouse_keycode_tracker++ : mouse_keycode_tracker--;
             mouse_timer = timer_read();
             break;
+#if 0
         case QK_ONE_SHOT_MOD ... QK_ONE_SHOT_MOD_MAX:
             break;
+#endif
         case QK_MOD_TAP ... QK_MOD_TAP_MAX:
             if (record->event.pressed || !record->tap.count) {
                 break;
diff --git a/users/drashna/rgb/rgb_matrix_stuff.c b/users/drashna/rgb/rgb_matrix_stuff.c
index e6d631466d..36a7502733 100644
--- a/users/drashna/rgb/rgb_matrix_stuff.c
+++ b/users/drashna/rgb/rgb_matrix_stuff.c
@@ -57,6 +57,9 @@ void keyboard_post_init_rgb_matrix(void) {
         rgb_matrix_mode_noeeprom(RGB_MATRIX_REST_MODE);
     }
 #endif
+    if (userspace_config.rgb_layer_change) {
+        rgb_matrix_set_flags(LED_FLAG_UNDERGLOW | LED_FLAG_KEYLIGHT | LED_FLAG_INDICATOR);
+    }
 }
 
 bool process_record_user_rgb_matrix(uint16_t keycode, keyrecord_t *record) {
diff --git a/users/drashna/rules.mk b/users/drashna/rules.mk
index 12fa956b7d..b96e8a532b 100644
--- a/users/drashna/rules.mk
+++ b/users/drashna/rules.mk
@@ -13,8 +13,9 @@ GRAVE_ESC_ENABLE      = no
 # DEBUG_MATRIX_SCAN_RATE_ENABLE = api
 
 ifneq ($(strip $(NO_SECRETS)), yes)
-    ifneq ("$(wildcard $(USER_PATH)/keyrecords/secrets.c)","")
-        SRC += $(USER_PATH)/keyrecords/secrets.c
+    ifneq ("$(wildcard $(USER_PATH)/../../../qmk_secrets/secrets.c)","")
+        SRC += $(USER_PATH)/../../../qmk_secrets/secrets.c
+        SECURE_ENABLE = yes
     endif
     ifeq ($(strip $(NO_SECRETS)), lite)
         OPT_DEFS += -DNO_SECRETS
@@ -102,6 +103,7 @@ ifeq ($(strip $(POINTING_DEVICE_ENABLE)), yes)
     ifeq ($(strip $(CUSTOM_POINTING_DEVICE)), yes)
         SRC += $(USER_PATH)/pointing/pointing.c
         OPT_DEFS += -DCUSTOM_POINTING_DEVICE
+        OPT_DEFS += -DMOUSE_EXT_REPORT
     endif
 endif
 
@@ -119,9 +121,3 @@ ifeq ($(strip $(AUTOCORRECTION_ENABLE)), yes)
     SRC += $(USER_PATH)/keyrecords/autocorrection/autocorrection.c
     OPT_DEFS += -DAUTOCORRECTION_ENABLE
 endif
-
-CAPS_WORD_ENABLE ?= no
-ifeq ($(strip $(CAPS_WORD_ENABLE)), yes)
-    SRC += $(USER_PATH)/keyrecords/caps_word.c
-    OPT_DEFS += -DCAPS_WORD_ENABLE
-endif
diff --git a/users/drashna/split/transport_sync.c b/users/drashna/split/transport_sync.c
index 539a18900c..38df8fda3f 100644
--- a/users/drashna/split/transport_sync.c
+++ b/users/drashna/split/transport_sync.c
@@ -11,6 +11,7 @@
 #ifdef UNICODE_COMMON_ENABLE
 #    include "process_unicode_common.h"
 extern unicode_config_t unicode_config;
+#    include "keyrecords/unicode.h"
 #endif
 #ifdef AUDIO_ENABLE
 #    include "audio.h"
@@ -97,6 +98,7 @@ void user_transport_update(void) {
 #endif
 #ifdef UNICODE_COMMON_ENABLE
         user_state.unicode_mode = unicode_config.input_mode;
+        user_state.unicode_typing_mode = typing_mode;
 #endif
 #ifdef SWAP_HANDS_ENABLE
         user_state.swap_hands = swap_hands;
@@ -110,6 +112,7 @@ void user_transport_update(void) {
         user_state.raw       = transport_user_state;
 #ifdef UNICODE_COMMON_ENABLE
         unicode_config.input_mode = user_state.unicode_mode;
+        typing_mode = user_state.unicode_typing_mode;
 #endif
 #if defined(CUSTOM_POINTING_DEVICE)
         tap_toggling = user_state.tap_toggling;
diff --git a/users/drashna/split/transport_sync.h b/users/drashna/split/transport_sync.h
index f38fdcf1ef..77e5140eda 100644
--- a/users/drashna/split/transport_sync.h
+++ b/users/drashna/split/transport_sync.h
@@ -12,12 +12,13 @@ extern char keylog_str[OLED_KEYLOGGER_LENGTH];
 typedef union {
     uint32_t raw;
     struct {
-        bool audio_enable         :1;
-        bool audio_clicky_enable  :1;
-        bool tap_toggling         :1;
-        uint8_t unicode_mode      :3;
-        bool swap_hands           :1;
-        bool host_driver_disabled :1;
+        bool audio_enable           :1;
+        bool audio_clicky_enable    :1;
+        bool tap_toggling           :1;
+        uint8_t unicode_mode        :3;
+        bool swap_hands             :1;
+        bool host_driver_disabled   :1;
+        uint8_t unicode_typing_mode :3;
     };
 } user_runtime_config_t;
 
diff --git a/users/drashna/template.c b/users/drashna/template.c
index c4a62c6448..c032bd1ce3 100644
--- a/users/drashna/template.c
+++ b/users/drashna/template.c
@@ -25,21 +25,6 @@ __attribute__((weak)) bool process_record_keymap(uint16_t keycode, keyrecord_t *
 // And use "NEWPLACEHOLDER" for new safe range
 bool process_record_user(uint16_t keycode, keyrecord_t *record) {
     switch (keycode) {
-        case KC_MAKE:
-            if (!record->event.pressed) {
-                SEND_STRING("make " QMK_KEYBOARD ":" QMK_KEYMAP
-#if (defined(BOOTLOADER_DFU) || defined(BOOTLOADER_LUFA_DFU) || defined(BOOTLOADER_QMK_DFU))
-                            ":dfu"
-#elif defined(BOOTLOADER_HALFKAY)
-                            ":teensy"
-#elif defined(BOOTLOADER_CATERINA)
-                            ":avrdude"
-#endif
-                            SS_TAP(X_ENTER));
-            }
-            return false;
-            break;
-
         case VRSN:
             if (record->event.pressed) {
                 SEND_STRING(QMK_KEYBOARD "/" QMK_KEYMAP " @ " QMK_VERSION);
diff --git a/users/drashna/template.h b/users/drashna/template.h
index 26ac98edb9..bb08bb3e41 100644
--- a/users/drashna/template.h
+++ b/users/drashna/template.h
@@ -12,7 +12,7 @@
 
 enum custom_keycodes {
     VRSN = SAFE_RANGE,  // can always be here
-    KC_MAKE,
-    KC_RESET,
+    QK_MAKE,
+    QK_BOOT,
     NEWPLACEHOLDER  // use "NEWPLACEHOLDER for keymap specific codes
 };