Extend maximum number of backlight levels to 31 (#6351)
[jackhill/qmk/firmware.git] / docs / feature_userspace.md
CommitLineData
7b0356d1 1# Userspace: Sharing Code Between Keymaps
06f196c5
JH
2
3If you use more than one keyboard with a similar keymap, you might see the benefit in being able to share code between them. Create your own folder in `users/` named the same as your keymap (ideally your github username, `<name>`) with the following structure:
4
5* `/users/<name>/` (added to the path automatically)
162a67cb 6 * `readme.md` (optional, recommended)
06f196c5 7 * `rules.mk` (included automatically)
fa47f5fb 8 * `config.h` (included automatically)
06f196c5
JH
9 * `<name>.h` (optional)
10 * `<name>.c` (optional)
fa47f5fb
DJ
11 * `cool_rgb_stuff.c` (optional)
12 * `cool_rgb_stuff.h` (optional)
06f196c5 13
06f196c5
JH
14
15All this only happens when you build a keymap named `<name>`, like this:
16
17 make planck:<name>
18
bb53635f 19For example,
06f196c5
JH
20
21 make planck:jack
22
fa47f5fb 23Will include the `/users/jack/` folder in the path, along with `/users/jack/rules.mk`.
06f196c5 24
fa47f5fb 25!> This `name` can be [overridden](#override-default-userspace), if needed.
162a67cb 26
fa47f5fb
DJ
27## `Rules.mk`
28
29The `rules.mk` is one of the two files that gets processed automatically. This is how you add additional source files (such as `<name>.c`) will be added when compiling.
5ca9aecf 30
fa47f5fb 31It's highly recommended that you use `<name>.c` as the default source file to be added. And to add it, you need to add it the SRC in `rules.mk` like this:
162a67cb 32
fa47f5fb
DJ
33 SRC += <name>.c
34
35Additional files may be added in the same way - it's recommended you have one named `<name>`.c/.h to start off with, though.
36
37The `/users/<name>/rules.mk` file will be included in the build _after_ the `rules.mk` from your keymap. This allows you to have features in your userspace `rules.mk` that depend on individual QMK features that may or may not be available on a specific keyboard.
38
39For example, if you have RGB control features shared between all your keyboards that support RGB lighting, you can add support for that if the RGBLIGHT feature is enabled:
e9755521 40```make
fa47f5fb
DJ
41ifeq ($(strip $(RGBLIGHT_ENABLE)), yes)
42 # Include my fancy rgb functions source here
43 SRC += cool_rgb_stuff.c
e9755521
FS
44endif
45```
fa47f5fb
DJ
46
47Alternatively, you can `define RGB_ENABLE` in your keymap's `rules.mk` and then check for the variable in your userspace's `rules.mk` like this:
e9755521 48```make
fa47f5fb
DJ
49ifdef RGB_ENABLE
50 # Include my fancy rgb functions source here
51 SRC += cool_rgb_stuff.c
e9755521
FS
52endif
53```
e9755521 54
fa47f5fb
DJ
55### Override default userspace
56
57By default the userspace used will be the same as the keymap name. In some situations this isn't desirable. For instance, if you use the [layout](feature_layouts.md) feature you can't use the same name for different keymaps (e.g. ANSI and ISO). You can name your layouts `mylayout-ansi` and `mylayout-iso` and add the following line to your layout's `rules.mk`:
58
59```
60USER_NAME := mylayout
61```
62
63This is also useful if you have multiple different keyboards with different features physically present on the board (such as one with RGB Lights, and one with Audio, or different number of LEDs, or connected to a different PIN on the controller).
64
65## Configuration Options (`config.h`)
66
67Additionally, `config.h` here will be processed like the same file in your keymap folder. This is handled separately from the `<name>.h` file.
68
69The reason for this, is that `<name>.h` won't be added in time to add settings (such as `#define TAPPING_TERM 100`), and including the `<name.h>` file in any `config.h` files will result in compile issues.
70
71!>You should use the `config.h` for [configuration options](config_options.md), and the `<name>.h` file for user or keymap specific settings (such as the enum for layer or keycodes)
72
73
74## Readme (`readme.md`)
06f196c5
JH
75
76Please include authorship (your name, github username, email), and optionally [a license that's GPL compatible](https://www.gnu.org/licenses/license-list.html#GPLCompatibleLicenses).
77
fa47f5fb
DJ
78You can use this as a template:
79```
80Copyright <year> <name> <email> @<github_username>
81
82This program is free software: you can redistribute it and/or modify
83it under the terms of the GNU General Public License as published by
84the Free Software Foundation, either version 2 of the License, or
85(at your option) any later version.
86
87This program is distributed in the hope that it will be useful,
88but WITHOUT ANY WARRANTY; without even the implied warranty of
89MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
90GNU General Public License for more details.
91
92You should have received a copy of the GNU General Public License
93along with this program. If not, see <http://www.gnu.org/licenses/>.
94```
95
96You'd want to replace the year, name, email and github username with your info.
97
98Additionally, this is a good place to document your code, if you wish to share it with others.
99
100# Examples
101
102For a brief example, checkout [`/users/_example/`](https://github.com/qmk/qmk_firmware/tree/master/users/drashna).
f1b2d46e 103For a more complicated example, checkout [`/users/drashna/`](https://github.com/qmk/qmk_firmware/tree/master/users/drashna)'s userspace.
fa47f5fb
DJ
104
105
106## Customized Functions
107
108QMK has a bunch of [functions](custom_quantum_functions.md) that have [`_quantum`, `_kb`, and `_user` versions](custom_quantum_functions.md#a-word-on-core-vs-keyboards-vs-keymap) that you can use. You will pretty much always want to use the user version of these functions. But the problem is that if you use them in your userspace, then you don't have a version that you can use in your keymap.
109
110However, you can actually add support for keymap version, so that you can use it in both your userspace and your keymap!
162a67cb 111
162a67cb 112
b541369c 113For instance, let's look at the `layer_state_set_user()` function. You can enable the [Tri Layer State](ref_functions.md#olkb-tri-layers) functionality on all of your boards, while also retaining the Tri Layer functionality in your `keymap.c` files.
fa47f5fb
DJ
114
115In your `<name.c>` file, you'd want to add this:
162a67cb 116```c
fa47f5fb
DJ
117__attribute__ ((weak))
118uint32_t layer_state_set_keymap (uint32_t state) {
119 return state;
120}
121
122uint32_t layer_state_set_user (uint32_t state) {
123 state = update_tri_layer_state(state, 2, 3, 5);
124 return layer_state_set_keymap (state);
125}
126```
f1b2d46e 127The `__attribute__ ((weak))` part tells the compiler that this is a placeholder function that can then be replaced by a version in your `keymap.c`. That way, you don't need to add it to your `keymap.c`, but if you do, you won't get any conflicts because the function is the same name.
162a67cb 128
fa47f5fb 129The `_keymap` part here doesn't matter, it just needs to be something other than `_quantum`, `_kb`, or `_user`, since those are already in use. So you could use `layer_state_set_mine`, `layer_state_set_fn`, or anything else.
162a67cb 130
fa47f5fb
DJ
131You can see a list of this and other common functions in [`template.c`](https://github.com/qmk/qmk_firmware/blob/master/users/drashna/template.c) in [`users/drashna`](https://github.com/qmk/qmk_firmware/tree/master/users/drashna).
132
133## Custom Features
134
135Since the Userspace feature can support a staggering number of boards, you may have boards that you want to enable certain functionality for, but not for others. And you can actually create "features" that you can enable or disable in your own userspace.
136
137For instance, if you wanted to have a bunch of macros available, but only on certain boards (to save space), you could "hide" them being a `#ifdef MACROS_ENABLED`, and then enable it per board. To do this, add this to your rules.mk
138```make
139ifeq ($(strip $(MACROS_ENABLED)), yes)
140 OPT_DEFS += -DMACROS_ENABLED
141endif
162a67cb 142```
f1b2d46e 143The `OPT_DEFS` setting causes `MACROS_ENABLED` to be defined for your keyboards (note the `-D` in front of the name), and you could use `#ifdef MACROS_ENABLED` to check the status in your c/h files, and handle that code based on that.
162a67cb 144
fa47f5fb 145Then you add `MACROS_ENABLED = yes` to the `rules.mk` for you keymap to enable this feature and the code in your userspace.
162a67cb 146
fa47f5fb
DJ
147And in your `process_record_user` function, you'd do something like this:
148```c
149bool process_record_user(uint16_t keycode, keyrecord_t *record) {
150 switch (keycode) {
151#ifdef MACROS_ENABLED
152 case MACRO1:
153 if (!record->event.pressed) {
154 SEND_STRING("This is macro 1!");
155 }
156 break;
157 case MACRO2:
158 if (!record->event.pressed) {
159 SEND_STRING("This is macro 2!");
160 }
161 break;
162#endif
163 }
164 return true;
165}
166```
06f196c5 167
3c15c48e 168
fa47f5fb 169## Consolidated Macros
3c15c48e 170
fa47f5fb 171If you wanted to consolidate macros and other functions into your userspace for all of your keymaps, you can do that. This builds upon the [Customized Functions](#customized-functions) example above. This lets you maintain a bunch of macros that are shared between the different keyboards, and allow for keyboard specific macros, too.
3c15c48e 172
af37bb2f 173First, you'd want to go through all of your `keymap.c` files and replace `process_record_user` with `process_record_keymap` instead. This way, you can still use keyboard specific codes on those boards, and use your custom "global" keycodes as well. You'll also want to replace `SAFE_RANGE` with `NEW_SAFE_RANGE` so that you wont have any overlapping keycodes
3c15c48e 174
175Then add `#include <name.h>` to all of your keymap.c files. This allows you to use these new keycodes without having to redefine them in each keymap.
176
177Once you've done that, you'll want to set the keycode definitions that you need to the `<name>.h` file. For instance:
fa47f5fb
DJ
178```c
179#pragma once
3c15c48e 180
181#include "quantum.h"
fa47f5fb
DJ
182#include "action.h"
183#include "version.h"
3c15c48e 184
bb53635f 185// Define all of
3c15c48e 186enum custom_keycodes {
187 KC_MAKE = SAFE_RANGE,
188 NEW_SAFE_RANGE //use "NEW_SAFE_RANGE" for keymap specific codes
189};
3c15c48e 190```
191
192Now you want to create the `<name>.c` file, and add this content to it:
193
fa47f5fb 194```c
3c15c48e 195#include "<name>.h"
3c15c48e 196
197__attribute__ ((weak))
198bool process_record_keymap(uint16_t keycode, keyrecord_t *record) {
199 return true;
200}
201
202bool process_record_user(uint16_t keycode, keyrecord_t *record) {
203 switch (keycode) {
3d446c60
DJ
204 case KC_MAKE: // Compiles the firmware, and adds the flash command based on keyboard bootloader
205 if (!record->event.pressed) {
206 uint8_t temp_mod = get_mods();
207 uint8_t temp_osm = get_oneshot_mods();
208 clear_mods(); clear_oneshot_mods();
209 SEND_STRING("make " QMK_KEYBOARD ":" QMK_KEYMAP);
210 #ifndef FLASH_BOOTLOADER
211 if ( (temp_mod | temp_osm) & MOD_MASK_SHIFT )
212 #endif
213 { //
214 #if defined(__arm__) // only run for ARM boards
215 SEND_STRING(":dfu-util");
216 #elif defined(BOOTLOADER_DFU) // only run for DFU boards
217 SEND_STRING(":dfu");
218 #elif defined(BOOTLOADER_HALFKAY) // only run for teensy boards
219 SEND_STRING(":teensy");
220 #elif defined(BOOTLOADER_CATERINA) // only run for Pro Micros
221 SEND_STRING(":avrdude");
222 #endif // bootloader options
223 }
224 if ( (temp_mod | temp_osm) & MOD_MASK_CTRL) {
225 SEND_STRING(" -j8 --output-sync");
226 }
227 SEND_STRING(SS_TAP(X_ENTER));
228 set_mods(temp_mod);
229 }
230 break;
231
3c15c48e 232 }
233 return process_record_keymap(keycode, record);
234}
235```
236
3d446c60
DJ
237For boards that may not have a shift button (such as on a macro pad), we need a way to always include the bootloader option. To do that, add the following to the `rules.mk` in your userspace folder:
238
239```make
240ifeq ($(strip $(FLASH_BOOTLOADER)), yes)
241 OPT_DEFS += -DFLASH_BOOTLOADER
242endif
243```
244
f1b2d46e 245This will add a new `KC_MAKE` keycode that can be used in any of your keymaps. And this keycode will output `make <keyboard>:<keymap>`, making frequent compiling easier. And this will work with any keyboard and any keymap as it will output the current boards info, so that you don't have to type this out every time.
3c15c48e 246
3d446c60 247Also, holding `shift` will add the appropriate flashing command (`:dfu`, `:teensy`, `:avrdude`, `:dfu-util`) for a majority of keyboards. Holding `control` will add some commands that will speed up compiling time by processing multiple files at once.
5ca9aecf 248
3d446c60 249And for the boards that lack a shift key, or that you want to always attempt the flashing part, you can add `FLASH_BOOTLOADER = yes` to the `rules.mk` of that keymap.
5ca9aecf 250
3d446c60 251?> This should flash the newly compiled firmware automatically, using the correct utility, based on the bootloader settings (or default to just generating the HEX file). However, it should be noted that this may not work on all systems. AVRDUDE doesn't work on WSL, namely. And this doesn't support BootloadHID or mdloader.