]> git.donarmstrong.com Git - qmk_firmware.git/blob - users/drashna/readme.md
Update to Drashna Keymaps and Userspace (#2650)
[qmk_firmware.git] / users / drashna / readme.md
1 Overview
2 ========
3
4 This is my personal userspace file.  Most of my code exists here, as it's heavily shared. 
5
6 Userspace Config.h
7 ------------------
8
9 By default, the userspace feature doesn't include a `config.h` file the way that that keyboards, revisions, keymaps and layouts handle them.  This means that if you want global configurations via userspace, it's very difficult to implement.  
10
11 The reason for using seperate files here is that the `drashna.h` file doesn't get called in such a way that will actually define QMK settings.  Additionally, attempting to add it to the `config.h` files has issues. Namely, the `drashna.h` file requires the `quantum.h` file... but including this to the `config.h` attemps to redefines a bunch of settings and breaks the firmare.  Removing the `quantum.h` include means that a number of data structures no longer get added, and the `SAFE_RANGE` value is no longer defined, as well.  So we need both a `config.h` for global config, and we need a seperate h file for local settings. 
12
13 However, the `rules.mk` file is included when building the firmware.  So we can hijack that process to "manually" add a `config.h`. To do so, you would need to add the following to the `rules.mk` in your userspace:
14
15 ```c
16 ifneq ("$(wildcard users/$(KEYMAP)/config.h)","")
17     CONFIG_H += users/$(KEYMAP)/config.h
18 endif
19 ```
20
21 You can replace `$(KEYMAP)` with your name, but it's not necessary. This checks for the existence of `/users/<name>/config.h`, and if it exists, includes it like every other `config.h` file, allowing you to make global `config.h` settings. 
22
23 As for the `config.h` file, you want to make sure that it has an "ifdef" in it to make sure it's only used once.  So you want something like this: 
24
25 ```c
26 #ifndef USERSPACE_CONFIG_H
27 #define USERSPACE_CONFIG_H
28
29 // put stuff here 
30
31 #endif
32 ```
33
34 Custom userspace handlers
35 -------------------------
36
37 Specifically QMK works by using customized handlers for everything. This allows for multiple levels of customization.
38
39 `matrix_scan` calls `matrix_scan_quantum`, which alls `matrix_scan_kb`, which calls `matrix_scan_user`. 
40 `process_record` calls a bunch of stuff, but eventually calls `process_record_kb` which calls `process_record_user`
41 The same goes for `matrix_init`, `layer_state_set`, `led_set`, and a few other functions.  
42
43 All (most) `_user` functions are handled here instead.  To allow keyboard specific configuration, I've created `_keymap` functions that can be called by the keymap.c files instead.
44
45 This allows for keyboard specific configuration while maintaining the ability to customize the board. 
46
47 My [Ergodox EZ Keymap](https://github.com/qmk/qmk_firmware/blob/master/keyboards/ergodox_ez/keymaps/drashna/keymap.c#L399) is a good example of this, as it uses the LEDs as modifier indicators.
48
49
50 Keyboard Layout Templates
51 -------------------------
52
53 This borrows from @jola5's "Not quite neo" code.  This allows me to maintain blocks of keymaps in the userspace, so that I can modify the userspace, and this is reflected in all of the keyboards that use it, at once. 
54
55 This makes adding tap/hold mods, or other special keycodes or functions to all keyboards super easy, as it's done to all of them at once. 
56
57 The caveat here is that the keymap needs a processor/wrapper, as it doesn't like the substitutions.  However, this is as simple as just pushing it through a define. For instance: 
58
59 `#define LAYOUT_ergodox_wrapper(...)   LAYOUT_ergodox(__VA_ARGS__)`
60
61 Once that's been done and you've switched the keymaps to use the "wrapper", it will read the substitution blocks just fine. 
62
63 Credit goes to @jola5 for first implementing this awesome idea.
64
65
66 Custom Keycodes
67 ---------------
68
69 Keycodes are defined in the drashna.h file and need to be included in the keymap.c files, so that they can be used there. 
70
71 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. 
72
73 Included is a custom macro for compiling my keyboards.  This includes the bootloader target (`:teensy`, `:avrdude`, or `:dfu`), and keeps RGBLIGHT, AUDIO and/or FAUXCLICKY enabled, if it previously was (regardless of the rules file).
74
75 This also includes a modified RESET keycode as well, that sets the underglow to red. 
76
77 Layer Indication
78 ----------------
79
80 This uses the `layer_state_set_*` command to change the layer color, to indicate which layer it is on.  This includes the default keymap, as well.
81
82 Since this is done via userspace, it is the same between all systems. 
83
84 Additionally, there is a custom keycode to toggle layer indication. And all RGB keycodes disable layer indication by default, as well.  This way, I can leave special effects doing when I want.
85
86 Also. I use `rgblight_sethsv` since it works with animation modes (that support it).
87
88
89 Diablo Layer
90 ------------
91
92 This layer has some special handling.
93
94 When Tap Dances are enabled, this layer has the ability to "spam" keypresses.  
95
96 For instance, tapping the TD "1" twice causes the layer to hit "1" ever 1 second (appoximately).  This is useful for auto-hotkeying skills (such as bone armor or devour).
97
98 Tappind once disables this, and switching layers temporarily disables this, until you switch back to the layer. 
99
100 For critics that think this is cheating, search "diablo 3 num lock auto cast".  This is just a simpler method, since I no longer own a normal (non QMK) numpad. 
101
102 Secret Macros
103 -------------
104
105 With help from gitter and Colinta, this adds the ability to add hidden strings to be used for macros.
106
107 I have a number of long strings that I need to use that are semi-private.  This uses the `__has_include` function to check for the file. If it exists, then it includes the custom text. Otherwise, it uses some default values. 
108
109 If you would *also* like to take advantage of this feature, you'll first want to make sure your "secrets" file isn't included in the repo.  Open `.git/info/exclude` and add `secrets.h` to that file, below the comments.
110
111 ###### .git/info/exclude
112 ```
113 # git ls-files --others --exclude-from=.git/info/exclude
114 # Lines that start with '#' are comments.
115 # For a project mostly in C, the following would be a good set of
116 # exclude patterns (uncomment them if you want to use them):
117 # *.[oa]
118 # *~
119 /users/drashna/secrets.h
120 ```
121
122 Then you can create this file and add your macro strings to it:
123
124 ###### secrets.h
125 ```c
126 PROGMEM const char secret[][64] = {
127   "secret1",
128   "secret2",
129   "secret3",
130   "secret4",
131   "secret5"
132 };
133 ```
134
135 Replacing the strings with the codes that you need.
136
137 In the `<name>.c` file, you will want to add this to the top: 
138
139 ```c
140
141 #if (__has_include("secrets.h") && !defined(NO_SECRETS))
142 #include "secrets.h"
143 #else
144 // `PROGMEM const char secret[][x]` may work better, but it takes up more space in the firmware
145 // And I'm not familiar enough to know which is better or why...
146 PROGMEM const char secret[][64] = {
147   "test1",
148   "test2",
149   "test3",
150   "test4",
151   "test5"
152 };
153 #endif
154 ```
155
156 And then, in the `process_record_user` function, you'll want to add this block:
157 ```c
158   case KC_SECRET_1 ... KC_SECRET_5:
159     if (!record->event.pressed) {
160       send_string_P(secret[keycode - KC_SECRET_1]);
161     }
162     return false;
163     break;
164 ```
165
166 And this requires `KC_SECRET_1` through `KC_SECRET_5` to be defined in your `<name>.h` file fo the new macros, as well.
167
168 Additionally, if you want to make sure that you can disable the function without messing with the file, you need to add this to your `/users/<name>/rules.mk`, so that it catches the flag:
169 ```c
170 ifeq ($(strip $(NO_SECRETS)), yes)
171     OPT_DEFS += -DNO_SECRETS
172 endif
173 ```
174
175 Then, if you run `make keyboard:name NO_SECRETS=yes`, it will default to the test strings in your `<name>.c` file, rather than reading from your file.