Эх сурвалжийг харах

[Keymap] Unicode and Pointing Device and Autocorect for drashna keymaps (#15415)

Drashna Jaelre 3 жил өмнө
parent
commit
3fa592a402
45 өөрчлөгдсөн 815 нэмэгдсэн , 187 устгасан
  1. 28 1
      keyboards/handwired/tractyl_manuform/5x6_right/f411/f411.c
  2. 3 2
      keyboards/handwired/tractyl_manuform/5x6_right/f411/readme.md
  3. 3 118
      keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/keymap.c
  4. 2 1
      keyboards/handwired/tractyl_manuform/tm_sync.c
  5. 2 0
      keyboards/handwired/tractyl_manuform/tractyl_manuform.c
  6. 16 16
      keyboards/keebio/iris/keymaps/drashna/rules.mk
  7. 1 1
      keyboards/moonlander/keymaps/drashna/keymap.c
  8. 1 1
      keyboards/orthodox/keymaps/drashna/rules.mk
  9. 1 1
      keyboards/splitkb/zima/keymaps/drashna/config.h
  10. 5 5
      layouts/community/ergodox/drashna/rules.mk
  11. 1 0
      layouts/community/ortho_5x12/drashna/rules.mk
  12. 1 0
      layouts/community/split_3x6_3/drashna/rules.mk
  13. 2 2
      users/drashna/config.h
  14. 9 1
      users/drashna/drashna.c
  15. 11 10
      users/drashna/drashna.h
  16. 143 0
      users/drashna/keyrecords/autocorrection/autocorrection.c
  17. 10 0
      users/drashna/keyrecords/autocorrection/autocorrection.h
  18. 273 0
      users/drashna/keyrecords/autocorrection/make_autocorrection_data.py
  19. 69 0
      users/drashna/keyrecords/caps_word.c
  20. 8 0
      users/drashna/keyrecords/caps_word.h
  21. 16 1
      users/drashna/keyrecords/process_records.c
  22. 5 2
      users/drashna/keyrecords/process_records.h
  23. 0 0
      users/drashna/keyrecords/tap_dances.c
  24. 0 0
      users/drashna/keyrecords/tap_dances.h
  25. 8 3
      users/drashna/keyrecords/unicode.c
  26. 0 0
      users/drashna/keyrecords/wrappers.h
  27. 0 0
      users/drashna/oled/drashna_font.h
  28. 6 2
      users/drashna/oled/oled_stuff.c
  29. 0 0
      users/drashna/oled/oled_stuff.h
  30. 136 0
      users/drashna/pointing/pointing.c
  31. 23 0
      users/drashna/pointing/pointing.h
  32. 6 6
      users/drashna/readme.md
  33. 0 0
      users/drashna/readme/handlers.md
  34. 0 0
      users/drashna/readme/keycodes.md
  35. 0 0
      users/drashna/readme/rgb.md
  36. 0 0
      users/drashna/readme/secrets.md
  37. 0 0
      users/drashna/readme/tap_dance.md
  38. 0 0
      users/drashna/readme/wrappers.md
  39. 0 0
      users/drashna/rgb/rgb_matrix_stuff.c
  40. 0 0
      users/drashna/rgb/rgb_matrix_stuff.h
  41. 0 0
      users/drashna/rgb/rgb_stuff.c
  42. 0 0
      users/drashna/rgb/rgb_stuff.h
  43. 26 14
      users/drashna/rules.mk
  44. 0 0
      users/drashna/split/transport_sync.c
  45. 0 0
      users/drashna/split/transport_sync.h

+ 28 - 1
keyboards/handwired/tractyl_manuform/5x6_right/f411/f411.c

@@ -16,7 +16,7 @@
 
 
 #include "f411.h"
 #include "f411.h"
 
 
-void matrix_init_sub_kb(void) { setPinInputHigh(A0); }
+void keyboard_pre_init_sub(void) { setPinInputHigh(A0); }
 
 
 void matrix_scan_sub_kb(void) {
 void matrix_scan_sub_kb(void) {
     if (!readPin(A0)) {
     if (!readPin(A0)) {
@@ -24,6 +24,33 @@ void matrix_scan_sub_kb(void) {
     }
     }
 }
 }
 
 
+void bootmagic_lite(void) {
+    // We need multiple scans because debouncing can't be turned off.
+    matrix_scan();
+#if defined(DEBOUNCE) && DEBOUNCE > 0
+    wait_ms(DEBOUNCE * 2);
+#else
+    wait_ms(30);
+#endif
+    matrix_scan();
+
+    uint8_t row = BOOTMAGIC_LITE_ROW;
+    uint8_t col = BOOTMAGIC_LITE_COLUMN;
+
+#if defined(SPLIT_KEYBOARD) && defined(BOOTMAGIC_LITE_ROW_RIGHT) && defined(BOOTMAGIC_LITE_COLUMN_RIGHT)
+    if (!is_keyboard_left()) {
+        row = BOOTMAGIC_LITE_ROW_RIGHT;
+        col = BOOTMAGIC_LITE_COLUMN_RIGHT;
+    }
+#endif
+
+    if (matrix_get_row(row) & (1 << col) || !readPin(A0)) {
+        eeconfig_disable();
+        bootloader_jump();
+    }
+}
+
+
 #ifdef USB_VBUS_PIN
 #ifdef USB_VBUS_PIN
 bool usb_vbus_state(void) {
 bool usb_vbus_state(void) {
     setPinInputLow(USB_VBUS_PIN);
     setPinInputLow(USB_VBUS_PIN);

+ 3 - 2
keyboards/handwired/tractyl_manuform/5x6_right/f411/readme.md

@@ -1,7 +1,7 @@
 # Drashna's Blackpill Tractyl Manuform (5x6) with a right side trackball
 # Drashna's Blackpill Tractyl Manuform (5x6) with a right side trackball
 
 
 * System Timer on TIM5
 * System Timer on TIM5
-* ~~VBUS mod, using PB10~~ (*doesn't seem to work for me*)
+* VBUS mod, using PB10 -- does work, but not on my tractyl... bad soldering probably
 * Split Hand Pin, using PC14
 * Split Hand Pin, using PC14
 * Full Duplex Serial/USART using PA2 and PA3 on USART2
 * Full Duplex Serial/USART using PA2 and PA3 on USART2
 * PWM Audio using PB1 and TIM3 and GPT on TIM4
 * PWM Audio using PB1 and TIM3 and GPT on TIM4
@@ -12,7 +12,8 @@
 * SSD1306 OLED display (128x64) using PB8-PB9 on I2C1
 * SSD1306 OLED display (128x64) using PB8-PB9 on I2C1
 * Pull-up resistor (22k) on PA10 to fix reset issue.
 * Pull-up resistor (22k) on PA10 to fix reset issue.
 * Pull-up resistor (5.1k) on PA1 for WS2812 LED support, and wire it's VCC to the 5V pin.
 * Pull-up resistor (5.1k) on PA1 for WS2812 LED support, and wire it's VCC to the 5V pin.
-* Pins PA9, PA11, A12 are not useable because they're used for USB connection, and can't be shared. 
+* Pins PA9 is meant for VBUS sense, and has an internal pulldown resistor. A 5.1k pullup resistor can work (but should be avoided)
+* Pins PA11 and A12 are not useable because they're used for USB connection, and can't be shared. 
 * Pin PB2 is used by BOOT1, and is unusable
 * Pin PB2 is used by BOOT1, and is unusable
 
 
 ## Keyboard Info
 ## Keyboard Info

+ 3 - 118
keyboards/handwired/tractyl_manuform/5x6_right/keymaps/drashna/keymap.c

@@ -16,11 +16,6 @@
 
 
 #include "drashna.h"
 #include "drashna.h"
 
 
-enum tractyl_keycodes {
-    KC_ACCEL = NEW_SAFE_RANGE,
-};
-
-bool enable_acceleration = false;
 // clang-format off
 // clang-format off
 #define LAYOUT_5x6_right_wrapper(...) LAYOUT_5x6_right(__VA_ARGS__)
 #define LAYOUT_5x6_right_wrapper(...) LAYOUT_5x6_right(__VA_ARGS__)
 #define LAYOUT_5x6_right_base( \
 #define LAYOUT_5x6_right_base( \
@@ -129,10 +124,10 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
         VRSN,    _________________ADJUST_L1_________________,                      _________________ADJUST_R1_________________, EEP_RST,
         VRSN,    _________________ADJUST_L1_________________,                      _________________ADJUST_R1_________________, EEP_RST,
         KEYLOCK, _________________ADJUST_L2_________________,                      _________________ADJUST_R2_________________, TG_MODS,
         KEYLOCK, _________________ADJUST_L2_________________,                      _________________ADJUST_R2_________________, TG_MODS,
         UC_MOD,  _________________ADJUST_L3_________________,                      _________________ADJUST_R3_________________, KC_MPLY,
         UC_MOD,  _________________ADJUST_L3_________________,                      _________________ADJUST_R3_________________, KC_MPLY,
-                          HPT_DWLI, HPT_DWLD,                                                        TG_GAME, TG_DBLO,
-                                            HPT_TOG, HPT_BUZ,                               KC_NUKE,
+                   TG(_DIABLOII), AUTO_CTN,                                                          TG_GAME, TG_DBLO,
+                                            _______, _______,                               KC_NUKE,
                                                      _______, _______,             _______,
                                                      _______, _______,             _______,
-                                                     _______, TG(_DIABLOII),KC_NUKE, _______
+                                                     _______, _______,    KC_NUKE, _______
     ),
     ),
 };
 };
 
 
@@ -169,116 +164,6 @@ bool encoder_update_user(uint8_t index, bool clockwise) {
 }
 }
 #endif
 #endif
 
 
-#ifdef POINTING_DEVICE_ENABLE
-static uint16_t mouse_timer           = 0;
-static uint16_t mouse_debounce_timer  = 0;
-static uint8_t  mouse_keycode_tracker = 0;
-bool            tap_toggling          = false;
-
-#    ifdef TAPPING_TERM_PER_KEY
-#        define TAP_CHECK get_tapping_term(KC_BTN1, NULL)
-#    else
-#        ifndef TAPPING_TERM
-#            define TAPPING_TERM 200
-#        endif
-#        define TAP_CHECK TAPPING_TERM
-#    endif
-
-report_mouse_t pointing_device_task_user(report_mouse_t mouse_report) {
-    int8_t x = mouse_report.x, y = mouse_report.y;
-    mouse_report.x = 0;
-    mouse_report.y = 0;
-
-    if (x != 0 && y != 0) {
-        mouse_timer = timer_read();
-#    ifdef OLED_ENABLE
-        oled_timer = timer_read32();
-#    endif
-        if (timer_elapsed(mouse_debounce_timer) > TAP_CHECK) {
-            if (enable_acceleration) {
-                x = (x > 0 ? x * x / 16 + x : -x * x / 16 + x);
-                y = (y > 0 ? y * y / 16 + y : -y * y / 16 + y);
-            }
-            mouse_report.x = x;
-            mouse_report.y = y;
-            if (!layer_state_is(_MOUSE)) {
-                layer_on(_MOUSE);
-            }
-        }
-    }
-    return mouse_report;
-}
-
-void matrix_scan_keymap(void) {
-    if (timer_elapsed(mouse_timer) > 650 && layer_state_is(_MOUSE) && !mouse_keycode_tracker && !tap_toggling) {
-        layer_off(_MOUSE);
-    }
-    if (tap_toggling) {
-        if (!layer_state_is(_MOUSE)) {
-            layer_on(_MOUSE);
-        }
-    }
-}
-
-bool process_record_keymap(uint16_t keycode, keyrecord_t* record) {
-    switch (keycode) {
-        case TT(_MOUSE):
-            if (record->event.pressed) {
-                mouse_keycode_tracker++;
-            } else {
-#    if TAPPING_TOGGLE != 0
-                if (record->tap.count == TAPPING_TOGGLE) {
-                    tap_toggling ^= 1;
-#        if TAPPING_TOGGLE == 1
-                    if (!tap_toggling) mouse_keycode_tracker -= record->tap.count + 1;
-#        else
-                    if (!tap_toggling) mouse_keycode_tracker -= record->tap.count;
-#        endif
-                } else {
-                    mouse_keycode_tracker--;
-                }
-#    endif
-            }
-            mouse_timer = timer_read();
-            break;
-        case TG(_MOUSE):
-            if (record->event.pressed) {
-                tap_toggling ^= 1;
-            }
-            break;
-        case MO(_MOUSE):
-        case DPI_CONFIG:
-        case KC_MS_UP ... KC_MS_WH_RIGHT:
-            record->event.pressed ? mouse_keycode_tracker++ : mouse_keycode_tracker--;
-            mouse_timer = timer_read();
-        case KC_ACCEL:
-            enable_acceleration = record->event.pressed;
-            break;
-        default:
-            if (IS_NOEVENT(record->event)) break;
-            if ((keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX) && (((keycode >> 0x8) & 0xF) == _MOUSE)) {
-                record->event.pressed ? mouse_keycode_tracker++ : mouse_keycode_tracker--;
-                mouse_timer = timer_read();
-                break;
-            }
-            if (layer_state_is(_MOUSE) && !mouse_keycode_tracker) {
-                layer_off(_MOUSE);
-            }
-            mouse_keycode_tracker = 0;
-            mouse_debounce_timer  = timer_read();
-            break;
-    }
-    return true;
-}
-
-layer_state_t layer_state_set_keymap(layer_state_t state) {
-    if (layer_state_cmp(state, _GAMEPAD) || layer_state_cmp(state, _DIABLO)) {
-        state |= ((layer_state_t)1 << _MOUSE);
-    }
-    return state;
-}
-#endif
-
 #ifdef OLED_ENABLE
 #ifdef OLED_ENABLE
 // WPM-responsive animation stuff here
 // WPM-responsive animation stuff here
 #    define SLEEP_FRAMES 2
 #    define SLEEP_FRAMES 2

+ 2 - 1
keyboards/handwired/tractyl_manuform/tm_sync.c

@@ -1,5 +1,6 @@
 /* Copyright 2020 Christopher Courtney, aka Drashna Jael're  (@drashna) <drashna@live.com>
 /* Copyright 2020 Christopher Courtney, aka Drashna Jael're  (@drashna) <drashna@live.com>
- *
+ * Copyright 2021 Dasky (@daskygit)
+
  * This program is free software: you can redistribute it and/or modify
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation, either version 2 of the License, or
  * the Free Software Foundation, either version 2 of the License, or

+ 2 - 0
keyboards/handwired/tractyl_manuform/tractyl_manuform.c

@@ -70,6 +70,7 @@ bool process_record_kb(uint16_t keycode, keyrecord_t* record) {
     return true;
     return true;
 }
 }
 __attribute__((weak)) void keyboard_pre_init_sync(void) {}
 __attribute__((weak)) void keyboard_pre_init_sync(void) {}
+__attribute__((weak)) void keyboard_pre_init_sub(void) {}
 void                       keyboard_pre_init_kb(void) {
 void                       keyboard_pre_init_kb(void) {
     // debug_enable  = true;
     // debug_enable  = true;
     // debug_matrix  = true;
     // debug_matrix  = true;
@@ -82,6 +83,7 @@ void                       keyboard_pre_init_kb(void) {
     writePin(DEBUG_LED_PIN, !debug_enable);
     writePin(DEBUG_LED_PIN, !debug_enable);
 #endif
 #endif
 
 
+    keyboard_pre_init_sub();
     keyboard_pre_init_sync();
     keyboard_pre_init_sync();
     keyboard_pre_init_user();
     keyboard_pre_init_user();
 }
 }

+ 16 - 16
keyboards/keebio/iris/keymaps/drashna/rules.mk

@@ -1,17 +1,17 @@
-BOOTMAGIC_ENABLE = no       # Enable Bootmagic Lite
-MOUSEKEY_ENABLE   = no       # Mouse keys(+4700)
-EXTRAKEY_ENABLE   = yes       # Audio control and System control(+450)
-CONSOLE_ENABLE    = no         # Console for debug(+400)
-COMMAND_ENABLE    = no        # Commands for debug and configuration
-TAP_DANCE_ENABLE  = no
-RGBLIGHT_ENABLE   = yes
-AUDIO_ENABLE      = no
-NKRO_ENABLE       = yes
-BACKLIGHT_ENABLE  = no
-SWAP_HANDS_ENABLE = no
-SPACE_CADET_ENABLE = no
-
-INDICATOR_LIGHTS  = no
-RGBLIGHT_STARTUP_ANIMATION = no
-
+BOOTMAGIC_ENABLE   = no       # Enable Bootmagic Lite
+MOUSEKEY_ENABLE    = no       # Mouse keys
+EXTRAKEY_ENABLE    = yes      # Audio control and System control
+CONSOLE_ENABLE     = no       # Console for debug
+COMMAND_ENABLE     = no       # Commands for debug and configuration
+TAP_DANCE_ENABLE   = no
+RGBLIGHT_ENABLE    = yes
+AUDIO_ENABLE       = no
+NKRO_ENABLE        = yes
+BACKLIGHT_ENABLE   = no
+SWAP_HANDS_ENABLE  = no
 BOOTLOADER        = qmk-dfu
 BOOTLOADER        = qmk-dfu
+
+INDICATOR_LIGHTS            = no
+RGBLIGHT_STARTUP_ANIMATION  = no
+CUSTOM_UNICODE_ENABLE       = no
+CUSTOM_SPLIT_TRANSPORT_SYNC = no

+ 1 - 1
keyboards/moonlander/keymaps/drashna/keymap.c

@@ -110,7 +110,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
         VRSN,    _________________ADJUST_L1_________________, TG(_DIABLOII),  _______, _________________ADJUST_R1_________________, EEP_RST,
         VRSN,    _________________ADJUST_L1_________________, TG(_DIABLOII),  _______, _________________ADJUST_R1_________________, EEP_RST,
         KEYLOCK, _________________ADJUST_L2_________________, _______,        _______, _________________ADJUST_R2_________________, RGB_IDL,
         KEYLOCK, _________________ADJUST_L2_________________, _______,        _______, _________________ADJUST_R2_________________, RGB_IDL,
         UC_MOD,  _________________ADJUST_L3_________________,                          _________________ADJUST_R3_________________, TG_MODS,
         UC_MOD,  _________________ADJUST_L3_________________,                          _________________ADJUST_R3_________________, TG_MODS,
-        _______, _______, _______, _______, _______,          _______,        _______,          _______, _______, _______, _______, KC_PAUS,
+        _______, _______, _______, _______, _______,          _______,        _______,          _______, _______, _______, _______, AUTO_CTN,
                                             _______, _______, _______,        _______, _______, _______
                                             _______, _______, _______,        _______, _______, _______
     ),
     ),
 };
 };

+ 1 - 1
keyboards/orthodox/keymaps/drashna/rules.mk

@@ -11,6 +11,6 @@ SPACE_CADET_ENABLE = no
 
 
 INDICATOR_LIGHTS  = yes
 INDICATOR_LIGHTS  = yes
 RGBLIGHT_STARTUP_ANIMATION = yes
 RGBLIGHT_STARTUP_ANIMATION = yes
-
+CUSTOM_UNICODE_ENABLE = no
 
 
 BOOTLOADER        = qmk-dfu
 BOOTLOADER        = qmk-dfu

+ 1 - 1
keyboards/splitkb/zima/keymaps/drashna/config.h

@@ -17,7 +17,7 @@
 
 
 #pragma once
 #pragma once
 
 
-#define OLED_FONT_H "users/drashna/drashna_font.h"
+#define OLED_FONT_H "users/drashna/oled/drashna_font.h"
 #define OLED_UPDATE_INTERVAL 15
 #define OLED_UPDATE_INTERVAL 15
 #define OLED_DISABLE_TIMEOUT
 #define OLED_DISABLE_TIMEOUT
 #define OLED_FONT_END 255
 #define OLED_FONT_END 255

+ 5 - 5
layouts/community/ergodox/drashna/rules.mk

@@ -1,4 +1,4 @@
-BOOTMAGIC_ENABLE = yes      # Enable Bootmagic Lite
+BOOTMAGIC_ENABLE   = yes      # Enable Bootmagic Lite
 TAP_DANCE_ENABLE   = no
 TAP_DANCE_ENABLE   = no
 COMMAND_ENABLE     = no  # Commands for debug and configuration
 COMMAND_ENABLE     = no  # Commands for debug and configuration
 CONSOLE_ENABLE     = no
 CONSOLE_ENABLE     = no
@@ -9,12 +9,12 @@ ifeq ($(strip $(KEYBOARD)), ergodox_ez)
     RGB_MATRIX_ENABLE          = yes
     RGB_MATRIX_ENABLE          = yes
     INDICATOR_LIGHTS           = no
     INDICATOR_LIGHTS           = no
     RGBLIGHT_STARTUP_ANIMATION = yes
     RGBLIGHT_STARTUP_ANIMATION = yes
-    PIMORONI_TRACKBALL_ENABLE  = yes
+    PIMORONI_TRACKBALL_ENABLE  = no
     MOUSEKEY_ENABLE            = no
     MOUSEKEY_ENABLE            = no
 endif
 endif
 
 
-UNICODE_ENABLE     = no
-UNICDOEMAP_ENABLE  = no
-
+UNICODE_ENABLE        = no
+UNICDOEMAP_ENABLE     = no
+CUSTOM_UNICODE_ENABLE = no
 
 
 DEBOUNCE_TYPE     = sym_eager_pr
 DEBOUNCE_TYPE     = sym_eager_pr

+ 1 - 0
layouts/community/ortho_5x12/drashna/rules.mk

@@ -14,4 +14,5 @@ ifeq ($(strip $(KEYBOARD)), fractal)
     RGBLIGHT_ENABLE             = yes
     RGBLIGHT_ENABLE             = yes
     RGBLIGHT_STARTUP_ANIMATION  = yes
     RGBLIGHT_STARTUP_ANIMATION  = yes
     BOOTLOADER                  = qmk-dfu
     BOOTLOADER                  = qmk-dfu
+    CUSTOM_UNICODE_ENABLE       = no
 endif
 endif

+ 1 - 0
layouts/community/split_3x6_3/drashna/rules.mk

@@ -32,6 +32,7 @@ ifeq ($(strip $(CTPC)), yes)
     SWAP_HANDS_ENABLE = yes
     SWAP_HANDS_ENABLE = yes
     WPM_ENABLE = yes
     WPM_ENABLE = yes
 else
 else
+    CUSTOM_UNICODE_ENABLE = no
     BOOTLOADER = qmk-hid
     BOOTLOADER = qmk-hid
     BOOTLOADER_SIZE = 512
     BOOTLOADER_SIZE = 512
 endif
 endif

+ 2 - 2
users/drashna/config.h

@@ -77,7 +77,7 @@
 #    endif
 #    endif
 #endif  // !AUDIO_ENABLE
 #endif  // !AUDIO_ENABLE
 
 
-#define UNICODE_SELECTED_MODES UC_WIN, UC_MAC
+#define UNICODE_SELECTED_MODES UC_WINC, UC_MAC
 
 
 #ifdef RGBLIGHT_ENABLE
 #ifdef RGBLIGHT_ENABLE
 #    define RGBLIGHT_SLEEP
 #    define RGBLIGHT_SLEEP
@@ -200,7 +200,7 @@
 #    ifdef OLED_FONT_H
 #    ifdef OLED_FONT_H
 #        undef OLED_FONT_H
 #        undef OLED_FONT_H
 #    endif
 #    endif
-#    define OLED_FONT_H   "drashna_font.h"
+#    define OLED_FONT_H   "oled/drashna_font.h"
 #    define OLED_FONT_END 255
 #    define OLED_FONT_END 255
 // #    define OLED_FONT_5X5
 // #    define OLED_FONT_5X5
 // #    define OLED_FONT_AZTECH
 // #    define OLED_FONT_AZTECH

+ 9 - 1
users/drashna/drashna.c

@@ -70,7 +70,9 @@ void                       matrix_init_user(void) {
     DDRB &= ~(1 << 0);
     DDRB &= ~(1 << 0);
     PORTB &= ~(1 << 0);
     PORTB &= ~(1 << 0);
 #endif
 #endif
-
+#ifdef CUSTOM_UNICODE_ENABLE
+    matrix_init_unicode();
+#endif
     matrix_init_secret();
     matrix_init_secret();
     matrix_init_keymap();
     matrix_init_keymap();
 }
 }
@@ -152,6 +154,9 @@ void                       matrix_scan_user(void) {
 #if defined(RGB_MATRIX_ENABLE)
 #if defined(RGB_MATRIX_ENABLE)
     matrix_scan_rgb_matrix();
     matrix_scan_rgb_matrix();
 #endif
 #endif
+#if defined(POINTING_DEVICE_ENABLE)
+    matrix_scan_pointing();
+#endif
 
 
     matrix_scan_secret();
     matrix_scan_secret();
 
 
@@ -171,6 +176,9 @@ layer_state_t                       layer_state_set_user(layer_state_t state) {
     }
     }
 
 
     state = update_tri_layer_state(state, _RAISE, _LOWER, _ADJUST);
     state = update_tri_layer_state(state, _RAISE, _LOWER, _ADJUST);
+#if defined(POINTING_DEVICE_ENABLE)
+    state = layer_state_set_pointing(state);
+#endif
 #if defined(RGBLIGHT_ENABLE)
 #if defined(RGBLIGHT_ENABLE)
     state = layer_state_set_rgb_light(state);
     state = layer_state_set_rgb_light(state);
 #endif  // RGBLIGHT_ENABLE
 #endif  // RGBLIGHT_ENABLE

+ 11 - 10
users/drashna/drashna.h

@@ -18,25 +18,25 @@
 #include QMK_KEYBOARD_H
 #include QMK_KEYBOARD_H
 
 
 #include "eeprom.h"
 #include "eeprom.h"
-#include "wrappers.h"
-#include "process_records.h"
+#include "keyrecords/wrappers.h"
+#include "keyrecords/process_records.h"
 #ifdef TAP_DANCE_ENABLE
 #ifdef TAP_DANCE_ENABLE
-#    include "tap_dances.h"
+#    include "keyrecords/tap_dances.h"
 #endif  // TAP_DANCE_ENABLE
 #endif  // TAP_DANCE_ENABLE
 #if defined(RGBLIGHT_ENABLE)
 #if defined(RGBLIGHT_ENABLE)
-#    include "rgb_stuff.h"
+#    include "rgb/rgb_stuff.h"
 #endif
 #endif
 #if defined(RGB_MATRIX_ENABLE)
 #if defined(RGB_MATRIX_ENABLE)
-#    include "rgb_matrix_stuff.h"
+#    include "rgb/rgb_matrix_stuff.h"
 #endif
 #endif
 #if defined(OLED_ENABLE)
 #if defined(OLED_ENABLE)
-#    include "oled_stuff.h"
-#endif
-#if defined(PIMORONI_TRACKBALL_ENABLE)
-#    include "drivers/sensors/pimoroni_trackball.h"
+#    include "oled/oled_stuff.h"
 #endif
 #endif
 #ifdef SPLIT_KEYBOARD
 #ifdef SPLIT_KEYBOARD
-#    include "transport_sync.h"
+#    include "split/transport_sync.h"
+#endif
+#ifdef POINTING_DEVICE_ENABLE
+#    include "pointing/pointing.h"
 #endif
 #endif
 
 
 /* Define layer names */
 /* Define layer names */
@@ -113,6 +113,7 @@ typedef union {
         bool    nuke_switch          :1;
         bool    nuke_switch          :1;
         bool    swapped_numbers      :1;
         bool    swapped_numbers      :1;
         bool    rgb_matrix_idle_anim :1;
         bool    rgb_matrix_idle_anim :1;
+        bool    autocorrection       :1;
     };
     };
 } userspace_config_t;
 } userspace_config_t;
 // clang-format on
 // clang-format on

+ 143 - 0
users/drashna/keyrecords/autocorrection/autocorrection.c

@@ -0,0 +1,143 @@
+// Copyright 2021 Google LLC
+// Copyright 2022 @filterpaper
+// SPDX-License-Identifier: Apache-2.0
+// Original source: https://getreuer.info/posts/keyboards/autocorrection
+
+#include "autocorrection.h"
+#include <string.h>
+
+#if __has_include("autocorrection_data.h")
+#    include "autocorrection_data.h"
+#    if AUTOCORRECTION_MIN_LENGTH < 4
+#        error Minimum Length is too short and may cause overflows
+#    endif
+
+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;
+
+    if (keycode == AUTO_CTN) {
+        if (record->event.pressed) {
+            typo_buffer_size = 0;
+            userspace_config.autocorrection ^= 1;
+            eeconfig_update_user(userspace_config.raw);
+        }
+        return false;
+    }
+
+    if (!userspace_config.autocorrection) {
+        typo_buffer_size = 0;
+        return true;
+    }
+
+    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;
+            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:
+            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) {
+            // 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) {
+                typo_buffer_size = 0;
+            }
+            keycode = KC_SPC;
+        } else {
+            // 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;
+    }
+
+    // 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) {
+        return true;
+    }
+
+    // Check for typo in buffer using a trie stored in `autocorrection_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 const key_i = typo_buffer[i];
+
+        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))) {
+                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);
+            // Check for match in node with single child.
+        } else if (code != key_i) {
+            return true;
+        } else if (!(code = pgm_read_byte(autocorrection_data + (++state)))) {
+            ++state;
+        }
+
+        code = pgm_read_byte(autocorrection_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);
+            }
+            send_string_P((char const*)(autocorrection_data + state + 1));
+
+            if (keycode == KC_SPC) {
+                typo_buffer[0]   = KC_SPC;
+                typo_buffer_size = 1;
+                return true;
+            } else {
+                typo_buffer_size = 0;
+                return false;
+            }
+        }
+    }
+    return true;
+}
+#else
+#    pragma message "Warning!!! Autocorrect is not corretly setup!"
+bool process_autocorrection(uint16_t keycode, keyrecord_t* record) { return true; }
+#endif

+ 10 - 0
users/drashna/keyrecords/autocorrection/autocorrection.h

@@ -0,0 +1,10 @@
+// Copyright 2021 Google LLC
+// Copyright 2022 @filterpaper
+// SPDX-License-Identifier: Apache-2.0
+// Original source: https://getreuer.info/posts/keyboards/autocorrection
+
+#pragma once
+
+#include "drashna.h"
+
+bool process_autocorrection(uint16_t keycode, keyrecord_t* record);

+ 273 - 0
users/drashna/keyrecords/autocorrection/make_autocorrection_data.py

@@ -0,0 +1,273 @@
+# Copyright 2021 Google LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Python program to make autocorrection_data.h.
+
+This program reads "autocorrection_dict.txt" and generates a C source file
+"autocorrection_data.h" with a serialized trie embedded as an array. Run this
+program without arguments like
+
+$ python3 make_autocorrection_data.py
+
+Or to read from a different typo dict file, pass it as the first argument like
+
+$ python3 make_autocorrection_data.py dict.txt
+
+Each line of the dict file defines one typo and its correction with the syntax
+"typo -> correction". Blank lines or lines starting with '#' are ignored.
+Example:
+
+  :thier        -> their
+  fitler        -> filter
+  lenght        -> length
+  ouput         -> output
+  widht         -> width
+
+See autocorrection_dict_extra.txt for a larger example.
+
+For full documentation, see
+https://getreuer.info/posts/keyboards/autocorrection
+"""
+
+import sys
+import textwrap
+from typing import Any, Dict, List, Tuple
+
+try:
+  from english_words import english_words_lower_alpha_set as CORRECT_WORDS
+except ImportError:
+  print('Autocorrection will falsely trigger when a typo is a substring of a '
+        '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')
+
+KC_A = 4
+KC_SPC = 0x2c
+
+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.
+
+  Args:
+    file_name: String, path of the autocorrections dictionary.
+  Returns:
+    List of (typo, correction) tuples.
+  """
+
+  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}"')
+        sys.exit(1)
+
+      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 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)
+
+  return autocorrections
+
+
+def make_trie(autocorrections: List[Tuple[str, str]]) -> Dict[str, Any]:
+  """Makes a trie from the the typos, writing in reverse.
+
+  Args:
+    autocorrections: List of (typo, correction) tuples.
+  Returns:
+    Dict of dict, representing the trie.
+  """
+  trie = {}
+  for typo, correction in autocorrections:
+    node = trie
+    for letter in typo[::-1]:
+      node = node.setdefault(letter, {})
+    node['LEAF'] = (typo, correction)
+
+  return trie
+
+
+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.
+
+  Args:
+    autocorrections: List of (typo, correction) tuples.
+    trie: Dict of dicts.
+  Returns:
+    List of ints in the range 0-255.
+  """
+  table = []
+
+  # Traverse trie in depth first order.
+  def traverse(trie_node):
+    if 'LEAF' in trie_node:  # Handle a leaf trie node.
+      typo, correction = trie_node['LEAF']
+      word_boundary_ending = typo[-1] == ':'
+      typo = typo.strip(':')
+      i = 0  # Make the autocorrection data for this entry and serialize it.
+      while i < min(len(typo), len(correction)) and typo[i] == correction[i]:
+        i += 1
+      backspaces = len(typo) - i - 1 + word_boundary_ending
+      assert 0 <= backspaces <= 63
+      correction = correction[i:]
+      data = [backspaces + 128] + list(bytes(correction, 'ascii')) + [0]
+
+      entry = {'data': data, 'links': [], 'byte_offset': 0}
+      table.append(entry)
+    elif len(trie_node) == 1:  # Handle trie node with a single child.
+      c, trie_node = next(iter(trie_node.items()))
+      entry = {'chars': c, 'byte_offset': 0}
+
+      # It's common for a trie to have long chains of single-child nodes. We
+      # find the whole chain so that we can serialize it more efficiently.
+      while len(trie_node) == 1 and 'LEAF' not in trie_node:
+        c, trie_node = next(iter(trie_node.items()))
+        entry['chars'] += c
+
+      table.append(entry)
+      entry['links'] = [traverse(trie_node)]
+    else:  # Handle trie node with multiple children.
+      entry = {'chars': ''.join(sorted(trie_node.keys())), 'byte_offset': 0}
+      table.append(entry)
+      entry['links'] = [traverse(trie_node[c]) for c in entry['chars']]
+    return entry
+
+  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]
+
+    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]))
+    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)
+      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 write_generated_code(autocorrections: List[Tuple[str, str]],
+                         data: List[int],
+                         file_name: str) -> None:
+  """Writes autocorrection data as generated C code to `file_name`.
+
+  Args:
+    autocorrections: List of (typo, correction) tuples.
+    data: List of ints in 0-255, the serialized trie.
+    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])
+  min_typo = min(autocorrections, key=typo_len)[0]
+  max_typo = max(autocorrections, key=typo_len)[0]
+  generated_code = ''.join([
+    '// Generated code.\n\n',
+    f'// Autocorrection dictionary ({len(autocorrections)} entries):\n',
+    ''.join(sorted(f'//   {typo:<{len(max_typo)}} -> {correction}\n'
+                   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',
+    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:
+    f.write(generated_code)
+
+
+def main(argv):
+  dict_file = argv[1] if len(argv) > 1 else 'autocorrection_dict.txt'
+  autocorrections = parse_file(dict_file)
+  trie = make_trie(autocorrections)
+  data = serialize_trie(autocorrections, trie)
+  print(f'Processed %d autocorrection entries to table with %d bytes.'
+        % (len(autocorrections), len(data)))
+  write_generated_code(autocorrections, data, 'autocorrection_data.h')
+
+if __name__ == '__main__':
+  main(sys.argv)

+ 69 - 0
users/drashna/keyrecords/caps_word.c

@@ -0,0 +1,69 @@
+// Copyright 2021 Google LLC.
+// SPDX-License-Identifier: Apache-2.0
+
+#include "caps_word.h"
+
+bool caps_word_enabled = false;
+bool caps_word_shifted = false;
+
+bool process_caps_word(uint16_t keycode, keyrecord_t* record) {
+    if (!caps_word_enabled) {
+        // Pressing both shift keys at the same time enables caps word.
+        if (((get_mods() | get_oneshot_mods()) & MOD_MASK_SHIFT) == MOD_MASK_SHIFT) {
+            clear_mods();
+            clear_oneshot_mods();
+            caps_word_shifted = false;
+            caps_word_enabled = true;
+            return false;
+        }
+        return true;
+    }
+
+    if (!record->event.pressed) {
+        return true;
+    }
+
+    if (!((get_mods() | get_oneshot_mods()) & ~MOD_MASK_SHIFT)) {
+        switch (keycode) {
+            case QK_MOD_TAP ... QK_MOD_TAP_MAX:
+            case QK_LAYER_TAP ... QK_LAYER_TAP_MAX:
+                // Earlier return if this has not been considered tapped yet.
+                if (record->tap.count == 0) {
+                    return true;
+                }
+                // Get the base tapping keycode of a mod- or layer-tap key.
+                keycode &= 0xff;
+        }
+
+        switch (keycode) {
+            // Letter keys should be shifted.
+            case KC_A ... KC_Z:
+                if (!caps_word_shifted) {
+                    register_code(KC_LSFT);
+                }
+                caps_word_shifted = true;
+                return true;
+
+            // Keycodes that continue caps word but shouldn't get shifted.
+            case KC_1 ... KC_0:
+            case KC_BSPC:
+            case KC_MINS:
+            case KC_UNDS:
+                if (caps_word_shifted) {
+                    unregister_code(KC_LSFT);
+                }
+                caps_word_shifted = false;
+                return true;
+
+                // Any other keycode disables caps word.
+        }
+    }
+
+    // Disable caps word.
+    caps_word_enabled = false;
+    if (caps_word_shifted) {
+        unregister_code(KC_LSFT);
+    }
+    caps_word_shifted = false;
+    return true;
+}

+ 8 - 0
users/drashna/keyrecords/caps_word.h

@@ -0,0 +1,8 @@
+// Copyright 2021 Google LLC.
+// SPDX-License-Identifier: Apache-2.0
+
+#pragma once
+
+#include "drashna.h"
+
+bool process_caps_word(uint16_t keycode, keyrecord_t* record);

+ 16 - 1
users/drashna/process_records.c → users/drashna/keyrecords/process_records.c

@@ -16,6 +16,12 @@
 
 
 #include "drashna.h"
 #include "drashna.h"
 #include "version.h"
 #include "version.h"
+#ifdef CAPS_WORD_ENABLE
+#    include "caps_word.h"
+#endif
+#ifdef AUTOCORRECTION_ENABLE
+#    include "autocorrection/autocorrection.h"
+#endif
 
 
 uint16_t copy_paste_timer;
 uint16_t copy_paste_timer;
 bool     host_driver_disabled = false;
 bool     host_driver_disabled = false;
@@ -42,6 +48,15 @@ bool                       process_record_user(uint16_t keycode, keyrecord_t *re
 #endif
 #endif
 #ifdef CUSTOM_UNICODE_ENABLE
 #ifdef CUSTOM_UNICODE_ENABLE
           && process_record_unicode(keycode, record)
           && process_record_unicode(keycode, record)
+#endif
+#if defined(POINTING_DEVICE_ENABLE)
+          && process_record_pointing(keycode, record)
+#endif
+#ifdef CAPS_WORD_ENABLE
+          && process_caps_word(keycode, record)
+#endif
+#ifdef AUTOCORRECTION_ENABLE
+          && process_autocorrection(keycode, record)
 #endif
 #endif
           && true)) {
           && true)) {
         return false;
         return false;
@@ -196,7 +211,7 @@ bool                       process_record_user(uint16_t keycode, keyrecord_t *re
                 }
                 }
             }
             }
             break;
             break;
-            }
+        }
     }
     }
     return true;
     return true;
 }
 }

+ 5 - 2
users/drashna/process_records.h → users/drashna/keyrecords/process_records.h

@@ -17,7 +17,7 @@
 #pragma once
 #pragma once
 #include "drashna.h"
 #include "drashna.h"
 
 
-#if defined(KEYBOARD_handwired_tractyl_manuform_5x6_right)
+#if defined(KEYBOARD_handwired_tractyl_manuform)
 #    define PLACEHOLDER_SAFE_RANGE KEYMAP_SAFE_RANGE
 #    define PLACEHOLDER_SAFE_RANGE KEYMAP_SAFE_RANGE
 #else
 #else
 #    define PLACEHOLDER_SAFE_RANGE SAFE_RANGE
 #    define PLACEHOLDER_SAFE_RANGE SAFE_RANGE
@@ -56,7 +56,9 @@ enum userspace_custom_keycodes {
     KC_REGIONAL,
     KC_REGIONAL,
     KC_AUSSIE,
     KC_AUSSIE,
     KC_ZALGO,
     KC_ZALGO,
-    NEW_SAFE_RANGE  // use "NEWPLACEHOLDER for keymap specific codes
+    KC_ACCEL,
+    AUTO_CTN,                                 // Toggle Autocorrect status
+    NEW_SAFE_RANGE                            // use "NEWPLACEHOLDER for keymap specific codes
 };
 };
 
 
 bool process_record_secrets(uint16_t keycode, keyrecord_t *record);
 bool process_record_secrets(uint16_t keycode, keyrecord_t *record);
@@ -64,6 +66,7 @@ bool process_record_keymap(uint16_t keycode, keyrecord_t *record);
 void post_process_record_keymap(uint16_t keycode, keyrecord_t *record);
 void post_process_record_keymap(uint16_t keycode, keyrecord_t *record);
 #ifdef CUSTOM_UNICODE_ENABLE
 #ifdef CUSTOM_UNICODE_ENABLE
 bool process_record_unicode(uint16_t keycode, keyrecord_t *record);
 bool process_record_unicode(uint16_t keycode, keyrecord_t *record);
+void matrix_init_unicode(void);
 #endif
 #endif
 
 
 #define LOWER     MO(_LOWER)
 #define LOWER     MO(_LOWER)

+ 0 - 0
users/drashna/tap_dances.c → users/drashna/keyrecords/tap_dances.c


+ 0 - 0
users/drashna/tap_dances.h → users/drashna/keyrecords/tap_dances.h


+ 8 - 3
users/drashna/unicoooode.c → users/drashna/keyrecords/unicode.c

@@ -1,5 +1,6 @@
-/* Copyright 2020 @tzarc
- *           2021 Christopher Courtney, aka Drashna Jael're  (@drashna) <drashna@live.com>
+/* Copyright 2020 @ridingqwerty
+ * Copyright 2020 @tzarc
+ * Copyright 2021 Christopher Courtney, aka Drashna Jael're  (@drashna) <drashna@live.com>
  *
  *
  * This program is free software: you can redistribute it and/or modify
  * This program is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * it under the terms of the GNU General Public License as published by
@@ -278,5 +279,9 @@ bool process_record_unicode(uint16_t keycode, keyrecord_t *record) {
     } else if (typing_mode == KC_ZALGO) {
     } else if (typing_mode == KC_ZALGO) {
         return process_record_zalgo(keycode, record);
         return process_record_zalgo(keycode, record);
     }
     }
-    return true;
+    return process_unicode_common(keycode, record);
+}
+
+void matrix_init_unicode(void) {
+    unicode_input_mode_init();
 }
 }

+ 0 - 0
users/drashna/wrappers.h → users/drashna/keyrecords/wrappers.h


+ 0 - 0
users/drashna/drashna_font.h → users/drashna/oled/drashna_font.h


+ 6 - 2
users/drashna/oled_stuff.c → users/drashna/oled/oled_stuff.c

@@ -234,7 +234,11 @@ void render_bootmagic_status(void) {
     oled_write_P(PSTR(" "), false);
     oled_write_P(PSTR(" "), false);
     oled_write_P(PSTR(OLED_RENDER_BOOTMAGIC_NKRO), keymap_config.nkro);
     oled_write_P(PSTR(OLED_RENDER_BOOTMAGIC_NKRO), keymap_config.nkro);
     oled_write_P(PSTR(" "), false);
     oled_write_P(PSTR(" "), false);
+#ifdef AUTOCORRECTION_ENABLE
+    oled_write_P(PSTR("CRCT"), userspace_config.autocorrection);
+#else
     oled_write_P(PSTR(OLED_RENDER_BOOTMAGIC_NOGUI), keymap_config.no_gui);
     oled_write_P(PSTR(OLED_RENDER_BOOTMAGIC_NOGUI), keymap_config.no_gui);
+#endif
 #ifdef OLED_DISPLAY_128X64
 #ifdef OLED_DISPLAY_128X64
     oled_advance_page(true);
     oled_advance_page(true);
     oled_write_P(PSTR("Magic"), false);
     oled_write_P(PSTR("Magic"), false);
@@ -344,7 +348,7 @@ void render_wpm(uint8_t padding) {
 #endif
 #endif
 }
 }
 
 
-#if defined(KEYBOARD_handwired_tractyl_manuform_5x6_right)
+#if defined(KEYBOARD_handwired_tractyl_manuform) || defined(KEYBOARD_bastardkb_charybdis)
 extern kb_config_data_t kb_config;
 extern kb_config_data_t kb_config;
 void                    render_pointing_dpi_status(uint8_t padding) {
 void                    render_pointing_dpi_status(uint8_t padding) {
     oled_write_P(PSTR("CPI:"), false);
     oled_write_P(PSTR("CPI:"), false);
@@ -377,7 +381,7 @@ __attribute__((weak)) void oled_driver_render_logo_left(void) {
     render_wpm(0);
     render_wpm(0);
 #    endif
 #    endif
     oled_write_P(PSTR("  "), false);
     oled_write_P(PSTR("  "), false);
-#    if defined(KEYBOARD_handwired_tractyl_manuform_5x6_right)
+#    if defined(KEYBOARD_handwired_tractyl_manuform) || defined(KEYBOARD_bastardkb_charybdis)
     render_pointing_dpi_status(1);
     render_pointing_dpi_status(1);
 #    endif
 #    endif
     oled_set_cursor(0, 4);
     oled_set_cursor(0, 4);

+ 0 - 0
users/drashna/oled_stuff.h → users/drashna/oled/oled_stuff.h


+ 136 - 0
users/drashna/pointing/pointing.c

@@ -0,0 +1,136 @@
+/* Copyright 2020 Christopher Courtney, aka Drashna Jael're  (@drashna) <drashna@live.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "pointing.h"
+
+static uint16_t mouse_timer           = 0;
+static uint16_t mouse_debounce_timer  = 0;
+static uint8_t  mouse_keycode_tracker = 0;
+bool            tap_toggling = false, enable_acceleration = false;
+
+#ifdef TAPPING_TERM_PER_KEY
+#    define TAP_CHECK get_tapping_term(KC_BTN1, NULL)
+#else
+#    ifndef TAPPING_TERM
+#        define TAPPING_TERM 200
+#    endif
+#    define TAP_CHECK TAPPING_TERM
+#endif
+
+__attribute__((weak)) report_mouse_t pointing_device_task_keymap(report_mouse_t mouse_report) {
+    return mouse_report;
+}
+
+report_mouse_t pointing_device_task_user(report_mouse_t mouse_report) {
+    int8_t x = mouse_report.x, y = mouse_report.y;
+    mouse_report.x = 0;
+    mouse_report.y = 0;
+
+    if (x != 0 && y != 0) {
+        mouse_timer = timer_read();
+#ifdef OLED_ENABLE
+        oled_timer = timer_read32();
+#endif
+        if (timer_elapsed(mouse_debounce_timer) > TAP_CHECK) {
+            if (enable_acceleration) {
+                x = (x > 0 ? x * x / 16 + x : -x * x / 16 + x);
+                y = (y > 0 ? y * y / 16 + y : -y * y / 16 + y);
+            }
+            mouse_report.x = x;
+            mouse_report.y = y;
+            if (!layer_state_is(_MOUSE)) {
+                layer_on(_MOUSE);
+            }
+        }
+    }
+    return pointing_device_task_keymap(mouse_report);
+}
+
+void matrix_scan_pointing(void) {
+    if (timer_elapsed(mouse_timer) > 650 && layer_state_is(_MOUSE) && !mouse_keycode_tracker && !tap_toggling) {
+        layer_off(_MOUSE);
+    }
+    if (tap_toggling) {
+        if (!layer_state_is(_MOUSE)) {
+            layer_on(_MOUSE);
+        }
+    }
+}
+
+bool process_record_pointing(uint16_t keycode, keyrecord_t* record) {
+    switch (keycode) {
+        case TT(_MOUSE):
+            if (record->event.pressed) {
+                mouse_keycode_tracker++;
+            } else {
+#if TAPPING_TOGGLE != 0
+                if (record->tap.count == TAPPING_TOGGLE) {
+                    tap_toggling ^= 1;
+#    if TAPPING_TOGGLE == 1
+                    if (!tap_toggling) mouse_keycode_tracker -= record->tap.count + 1;
+#    else
+                    if (!tap_toggling) mouse_keycode_tracker -= record->tap.count;
+#    endif
+                } else {
+                    mouse_keycode_tracker--;
+                }
+#endif
+            }
+            mouse_timer = timer_read();
+            break;
+        case TG(_MOUSE):
+            if (record->event.pressed) {
+                tap_toggling ^= 1;
+            }
+            break;
+        case MO(_MOUSE):
+#if defined(KEYBOARD_ploopy) || defined(KEYBOARD_handwired_tractyl_manuform)
+        case DPI_CONFIG:
+#elif defined(KEYBOARD_bastardkb_charybdis)
+        case SAFE_RANGE ... (CHARYBDIS_SAFE_RANGE-1):
+#endif
+        case KC_MS_UP ... KC_MS_WH_RIGHT:
+            record->event.pressed ? mouse_keycode_tracker++ : mouse_keycode_tracker--;
+            mouse_timer = timer_read();
+            break;
+        case KC_ACCEL:
+            enable_acceleration = record->event.pressed;
+            record->event.pressed ? mouse_keycode_tracker++ : mouse_keycode_tracker--;
+            mouse_timer = timer_read();
+            break;
+        default:
+            if (IS_NOEVENT(record->event)) break;
+            if ((keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX) && (((keycode >> 0x8) & 0xF) == _MOUSE)) {
+                record->event.pressed ? mouse_keycode_tracker++ : mouse_keycode_tracker--;
+                mouse_timer = timer_read();
+                break;
+            }
+            if (layer_state_is(_MOUSE) && !mouse_keycode_tracker) {
+                layer_off(_MOUSE);
+            }
+            mouse_keycode_tracker = 0;
+            mouse_debounce_timer  = timer_read();
+            break;
+    }
+    return true;
+}
+
+layer_state_t layer_state_set_pointing(layer_state_t state) {
+    if (layer_state_cmp(state, _GAMEPAD) || layer_state_cmp(state, _DIABLO)) {
+        state |= ((layer_state_t)1 << _MOUSE);
+    }
+    return state;
+}

+ 23 - 0
users/drashna/pointing/pointing.h

@@ -0,0 +1,23 @@
+/* Copyright 2020 Christopher Courtney, aka Drashna Jael're  (@drashna) <drashna@live.com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "drashna.h"
+
+report_mouse_t pointing_device_task_keymap(report_mouse_t mouse_report);
+void           matrix_scan_pointing(void);
+bool           process_record_pointing(uint16_t keycode, keyrecord_t* record);
+layer_state_t  layer_state_set_pointing(layer_state_t state);
+extern bool    tap_toggling, enable_acceleration;

+ 6 - 6
users/drashna/readme.md

@@ -2,12 +2,12 @@
 
 
 This is my personal userspace file.  Most of my code exists here, as it's heavily shared.
 This is my personal userspace file.  Most of my code exists here, as it's heavily shared.
 
 
-* [RGB Customization](readme_rgb.md)
-* [Diablo Tap Dancing](readme_tap_dance.md)
-* [Keymap Wrappers](readme_wrappers.md)
-* [Custom Function Handlers](readme_handlers.md)
-* [Secret Macros](readme_secrets.md)
-* [Custom Keycodes](readme_keycodes.md)
+* [RGB Customization](readme/rgb.md)
+* [Diablo Tap Dancing](readme/tap_dance.md)
+* [Keymap Wrappers](readme/wrappers.md)
+* [Custom Function Handlers](readme/handlers.md)
+* [Secret Macros](readme/secrets.md)
+* [Custom Keycodes](readme/keycodes.md)
 
 
 
 
 ## Pro Micro Hacking
 ## Pro Micro Hacking

+ 0 - 0
users/drashna/readme_handlers.md → users/drashna/readme/handlers.md


+ 0 - 0
users/drashna/readme_keycodes.md → users/drashna/readme/keycodes.md


+ 0 - 0
users/drashna/readme_rgb.md → users/drashna/readme/rgb.md


+ 0 - 0
users/drashna/readme_secrets.md → users/drashna/readme/secrets.md


+ 0 - 0
users/drashna/readme_tap_dance.md → users/drashna/readme/tap_dance.md


+ 0 - 0
users/drashna/readme_wrappers.md → users/drashna/readme/wrappers.md


+ 0 - 0
users/drashna/rgb_matrix_stuff.c → users/drashna/rgb/rgb_matrix_stuff.c


+ 0 - 0
users/drashna/rgb_matrix_stuff.h → users/drashna/rgb/rgb_matrix_stuff.h


+ 0 - 0
users/drashna/rgb_stuff.c → users/drashna/rgb/rgb_stuff.c


+ 0 - 0
users/drashna/rgb_stuff.h → users/drashna/rgb/rgb_stuff.h


+ 26 - 14
users/drashna/rules.mk

@@ -1,5 +1,5 @@
 SRC += $(USER_PATH)/drashna.c \
 SRC += $(USER_PATH)/drashna.c \
-       $(USER_PATH)/process_records.c
+       $(USER_PATH)/keyrecords/process_records.c
 
 
 ifneq ($(PLATFORM),CHIBIOS)
 ifneq ($(PLATFORM),CHIBIOS)
     ifneq ($(strip $(LTO_SUPPORTED)), no)
     ifneq ($(strip $(LTO_SUPPORTED)), no)
@@ -10,8 +10,8 @@ SPACE_CADET_ENABLE    = no
 GRAVE_ESC_ENABLE      = no
 GRAVE_ESC_ENABLE      = no
 
 
 ifneq ($(strip $(NO_SECRETS)), yes)
 ifneq ($(strip $(NO_SECRETS)), yes)
-    ifneq ("$(wildcard $(USER_PATH)/secrets.c)","")
-        SRC += $(USER_PATH)/secrets.c
+    ifneq ("$(wildcard $(USER_PATH)/keyrecords/secrets.c)","")
+        SRC += $(USER_PATH)/keyrecords/secrets.c
     endif
     endif
     ifeq ($(strip $(NO_SECRETS)), lite)
     ifeq ($(strip $(NO_SECRETS)), lite)
         OPT_DEFS += -DNO_SECRETS
         OPT_DEFS += -DNO_SECRETS
@@ -25,20 +25,20 @@ ifeq ($(strip $(CUSTOM_UNICODE_ENABLE)), yes)
     UCIS_ENABLE           = no
     UCIS_ENABLE           = no
     UNICODE_COMMON        = yes
     UNICODE_COMMON        = yes
     OPT_DEFS += -DCUSTOM_UNICODE_ENABLE
     OPT_DEFS += -DCUSTOM_UNICODE_ENABLE
-    SRC += unicoooode.c
+    SRC += $(USER_PATH)/keyrecords/unicode.c
 endif
 endif
 
 
 CUSTOM_TAP_DANCE ?= yes
 CUSTOM_TAP_DANCE ?= yes
 ifeq ($(strip $(CUSTOM_TAP_DANCE)), yes)
 ifeq ($(strip $(CUSTOM_TAP_DANCE)), yes)
     ifeq ($(strip $(TAP_DANCE_ENABLE)), yes)
     ifeq ($(strip $(TAP_DANCE_ENABLE)), yes)
-        SRC += $(USER_PATH)/tap_dances.c
+        SRC += $(USER_PATH)/keyrecords/tap_dances.c
     endif
     endif
 endif
 endif
 
 
 CUSTOM_RGBLIGHT ?= yes
 CUSTOM_RGBLIGHT ?= yes
 ifeq ($(strip $(RGBLIGHT_ENABLE)), yes)
 ifeq ($(strip $(RGBLIGHT_ENABLE)), yes)
     ifeq ($(strip $(CUSTOM_RGBLIGHT)), yes)
     ifeq ($(strip $(CUSTOM_RGBLIGHT)), yes)
-        SRC += $(USER_PATH)/rgb_stuff.c
+        SRC += $(USER_PATH)/rgb/rgb_stuff.c
         ifeq ($(strip $(RGBLIGHT_NOEEPROM)), yes)
         ifeq ($(strip $(RGBLIGHT_NOEEPROM)), yes)
             OPT_DEFS += -DRGBLIGHT_NOEEPROM
             OPT_DEFS += -DRGBLIGHT_NOEEPROM
         endif
         endif
@@ -51,7 +51,7 @@ endif
 CUSTOM_RGB_MATRIX ?= yes
 CUSTOM_RGB_MATRIX ?= yes
 ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes)
 ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes)
     ifeq ($(strip $(CUSTOM_RGB_MATRIX)), yes)
     ifeq ($(strip $(CUSTOM_RGB_MATRIX)), yes)
-        SRC += $(USER_PATH)/rgb_matrix_stuff.c
+        SRC += $(USER_PATH)/rgb/rgb_matrix_stuff.c
     endif
     endif
 endif
 endif
 
 
@@ -76,24 +76,36 @@ endif
 CUSTOM_OLED_DRIVER ?= yes
 CUSTOM_OLED_DRIVER ?= yes
 ifeq ($(strip $(OLED_ENABLE)), yes)
 ifeq ($(strip $(OLED_ENABLE)), yes)
     ifeq ($(strip $(CUSTOM_OLED_DRIVER)), yes)
     ifeq ($(strip $(CUSTOM_OLED_DRIVER)), yes)
-        SRC += $(USER_PATH)/oled_stuff.c
+        SRC += $(USER_PATH)/oled/oled_stuff.c
         OPT_DEFS += -DCUSTOM_OLED_DRIVER_CODE
         OPT_DEFS += -DCUSTOM_OLED_DRIVER_CODE
     endif
     endif
 endif
 endif
 
 
-ifeq ($(strip $(PIMORONI_TRACKBALL_ENABLE)), yes)
-    POINTING_DEVICE_ENABLE := yes
-    OPT_DEFS += -DPIMORONI_TRACKBALL_ENABLE
-    SRC += drivers/sensors/pimoroni_trackball.c
-    QUANTUM_LIB_SRC += i2c_master.c
+CUSTOM_POINTING_DEVICE ?= yes
+ifeq ($(strip $(POINTING_DEVICE_ENABLE)), yes)
+    ifeq ($(strip $(CUSTOM_POINTING_DEVICE)), yes)
+        SRC += $(USER_PATH)/pointing/pointing.c
+    endif
 endif
 endif
 
 
 CUSTOM_SPLIT_TRANSPORT_SYNC ?= yes
 CUSTOM_SPLIT_TRANSPORT_SYNC ?= yes
 ifeq ($(strip $(CUSTOM_SPLIT_TRANSPORT_SYNC)), yes)
 ifeq ($(strip $(CUSTOM_SPLIT_TRANSPORT_SYNC)), yes)
     ifeq ($(strip $(SPLIT_KEYBOARD)), yes)
     ifeq ($(strip $(SPLIT_KEYBOARD)), yes)
-        QUANTUM_LIB_SRC += $(USER_PATH)/transport_sync.c
+        QUANTUM_LIB_SRC += $(USER_PATH)/split/transport_sync.c
         OPT_DEFS += -DCUSTOM_SPLIT_TRANSPORT_SYNC
         OPT_DEFS += -DCUSTOM_SPLIT_TRANSPORT_SYNC
     endif
     endif
 endif
 endif
 
 
 # DEBUG_MATRIX_SCAN_RATE_ENABLE = api
 # DEBUG_MATRIX_SCAN_RATE_ENABLE = api
+
+AUTOCORRECTION_ENABLE ?= yes
+ifeq ($(strip $(AUTOCORRECTION_ENABLE)), yes)
+    SRC += $(USER_PATH)/keyrecords/autocorrection/autocorrection.c
+    OPT_DEFS += -DAUTOCORRECTION_ENABLE
+endif
+
+CAPS_WORD_ENABLE ?= yes
+ifeq ($(strip $(CAPS_WORD_ENABLE)), yes)
+    SRC += $(USER_PATH)/keyrecords/caps_word.c
+    OPT_DEFS += -DCAPS_WORD_ENABLE
+endif

+ 0 - 0
users/drashna/transport_sync.c → users/drashna/split/transport_sync.c


+ 0 - 0
users/drashna/transport_sync.h → users/drashna/split/transport_sync.h