* Fix my Tap Dance issues after I broke them
* Cleanup and organization of userspace documentation
As well as some additional cleanup of functions due to review of documentation.
* Enable Tapdance on Glow and remove more animations
* Revert to Eager PR debouncing
* Add better check for startup animation
* Move where RGB Matrix defines are listed
* Limit RGB Matrix max val
* Update keyboard for Iris Rev 3 conflicts
* Enable encoder support on planck ez
* Remove is_master check from corne\'s OLED code
* Overhaul OLED screens for my Corne
* One last removal
* Show RGB valu On both sides
* Updates for OLED display info
* Fix compile issues for rgb config
* Disabled Space Cadet for all drashna keymaps
* Fix OLED Screen configs
* Minor OLED Tweaks
* Revert some Iris changes
* Fix song include
* Handle MAKE macro for the Corne boards better
* Add super hacky-hack for eeconfig initialization
* Add audio support for Fractal since Elite Cs support it
* Add defines for keycode steps
* Add White layout
* Update Corne RGB info
* Add fun effects to layer indication for RGB Matrix enabled boards
* Use proper define for product name detection
* Update formatting
* Use custom timeout mechanism for OLED timeout
* Fix up OLED screen HSV code for new HSV structure
* Better handle turning off RGB Matrix when sleeping
* Disable MultiSplash Animation
* Change Iris back to using serial
* Why was RGB disabled?!?!?!
* Limit val in rgb_matrix_layer_helper function
* Remove EECONFIG setting for RGB matrix
returnsend_game_macro("Good luck, have fun!!!",record,false);
caseKC_SYMM:
returnsend_game_macro("Left click to win!",record,false);
caseKC_JUSTGAME:
returnsend_game_macro("It may be a game, but if you don't want to actually try, please go play AI, so that people that actually want to take the game seriously and \"get good\" have a place to do so without trolls like you throwing games.",record,false);
caseKC_TORB:
returnsend_game_macro("That was positively riveting!",record,false);
caseKC_AIM:
send_game_macro("That aim is absolutely amazing. It's almost like you're a machine!",record,true);
returnsend_game_macro("Wait! That aim is TOO good! You're clearly using an aim hack! CHEATER!",record,false);
returnsend_game_macro("Good luck, have fun!!!",record,false);
caseKC_SYMM:
returnsend_game_macro("Left click to win!",record,false);
caseKC_JUSTGAME:
returnsend_game_macro("It may be a game, but if you don't want to actually try, please go play AI, so that people that actually want to take the game seriously and \"get good\" have a place to do so without trolls like you throwing games.",record,false);
caseKC_TORB:
returnsend_game_macro("That was positively riveting!",record,false);
caseKC_AIM:
send_game_macro("That aim is absolutely amazing. It's almost like you're a machine!",record,true);
returnsend_game_macro("Wait! That aim is TOO good! You're clearly using an aim hack! CHEATER!",record,false);
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.
## Custom userspace handlers
* [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)
Specifically QMK works by using customized handlers for everything. This allows for multiple levels of customization.
`matrix_scan` calls `matrix_scan_quantum`, which alls `matrix_scan_kb`, which calls `matrix_scan_user`.
`process_record` calls a bunch of stuff, but eventually calls `process_record_kb` which calls `process_record_user`
The same goes for `matrix_init`, `layer_state_set`, `led_set`, and a few other functions.
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.
This allows for keyboard specific configuration while maintaining the ability to customize the board.
My [Ergodox EZ Keymap](https://github.com/qmk/qmk_firmware/blob/master/layouts/community/ergodox/drashna/keymap.c#L297) is a good example of this, as it uses the LEDs as modifier indicators.
## Keyboard Layout Templates
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.
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.
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:
Once that's been done and you've switched the keymaps to use the "wrapper", it will read the substitution blocks just fine.
Credit goes to @jola5 for first implementing this awesome idea.
## Custom Keycodes
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.
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.
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).
This also includes a modified RESET keycode as well, that sets the underglow to red.
## Layer Indication
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.
Since this is done via userspace, it is the same between all systems.
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.
Also. I use `rgblight_sethsv` since it works with animation modes (that support it).
## Diablo Layer
This layer has some special handling.
When Tap Dances are enabled, this layer has the ability to "spam" keypresses.
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).
Tappind once disables this, and switching layers temporarily disables this, until you switch back to the layer.
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.
## Secret Macros
With help from gitter and Colinta, this adds the ability to add hidden macros from other users.
First, I have several files that are hidden/excluded from Git/GitHub. These contain everything needed for the macros. To hide these files, open `.git/info/exclude` and add `secrets.c` and `secrets.h` to that file, below the comments.
And this requires `KC_SECRET_1` through `KC_SECRET_5` to be defined in your `<name>.h` file to define the keycodes for the new macros.
This is so that the function can be called here, and replaced in the `secrets.c` file, and so it won't error out if it doesn't exist.
And then, in the `process_record_user` function, assuming you have `return process_record_keymap(keycode, record)` here, you'll want to replace the "final" return with the following. Otherwise, you want to replace the `return true;` with `return process_record_secrets(keycode, 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. To do so, add this block:
```make
ifneq ("$(wildcard $(USER_PATH)/secrets.c)","")
SRC += secrets.c
endif
```
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:
```make
ifeq ($(strip $(NO_SECRETS)), yes)
OPT_DEFS += -DNO_SECRETS
endif
```
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.
## Pro Micro Hacking
## Pro Micro Hacking
Well, you can get the QMK DFU bootloader working on the ProMicro. But you need to change fuses.
What worked to get into the firmware properly was:
```
Low: 0x5E High: 0xD9 Extended: 0xC3 Lock: 0x3F
```
The reason that there was some issues before, is that JTAG was still enabled, and using some of the pins that the keyboard uses. Disabling JTAG (either by fuse, or modifying the matrix code for splits fixes the issue).
And for reference, if you want to go back to caterina, the default fuse settings I believe were:
```
Low: 0xFF High: 0xD8 Extended: 0xC3 Lock: 0x3F
```
See [this thread](https://www.reddit.com/r/olkb/comments/8sxgzb/replace_pro_micro_bootloader_with_qmk_dfu/) for details on how to flash QMK DFU to Pro Micros.
Specifically QMK works by using customized handlers for everything. This allows for multiple levels of customization.
`matrix_scan` calls `matrix_scan_quantum`, which calls `matrix_scan_kb`, which calls `matrix_scan_user`.
`process_record` calls a bunch of stuff, but eventually calls `process_record_kb` which calls `process_record_user`
The same goes for `matrix_init`, `layer_state_set`, `led_set`, and a few other functions.
All (most) `_user` functions are handled here, in the userspace instead. To allow keyboard specific configuration, I've created `_keymap` functions that can be called by the keymap.c files instead.
This allows for keyboard specific configuration while maintaining the ability to customize the board.
My [Ergodox EZ Keymap](https://github.com/qmk/qmk_firmware/blob/master/layouts/community/ergodox/drashna/keymap.c) is a good example of this, as it uses the LEDs as modifier indicators.
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.
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.
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).
This also includes a modified RESET keycode as well, that sets the underglow to red.
With help from gitter and Colinta, this adds the ability to add hidden macros from other users.
First, I have several files that are hidden/excluded from Git/GitHub. These contain everything needed for the macros. To hide these files, open `.git/info/exclude` and add `secrets.c` and `secrets.h` to that file, below the comments.
And this requires `KC_SECRET_1` through `KC_SECRET_5` to be added in your keycode enum (usually in your `<name>.h` file) the keycodes for the new macros.
## Git Exclusion
To prevent `git` from seeing, or committing the secret files, you can exclude them. What's the point of having secrets if they're posted on GitHub for everyone to see!?!
You can do this with the `.git/info/exclude` file, so that it's only ignored locally. Unfortunately, that means it's not consistently handled on each system.
However, if you create a `.gitignore` file in the same folder, you keep things consistent between every system that the code is checked out on.
```c
secrets.c
secrets.h
```
## secrets.c
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
This is so that the function can be called here, and replaced in the `secrets.c` file, and so it won't error out if it doesn't exist.
And then, in the `process_record_user` function, assuming you have `return process_record_keymap(keycode, record)` here, you'll want to replace the "final" return with the following. Otherwise, you want to replace the `return true;` with `return process_record_secrets(keycode, 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.
```make
ifneq ($(strip $(NO_SECRETS)), yes)
ifneq ("$(wildcard $(USER_PATH)/secrets.c)","")
SRC += secrets.c
endif
endif
```
Alternately, 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:
```make
ifneq ("$(wildcard $(USER_PATH)/secrets.c)","")
SRC += secrets.c
endif
ifeq ($(strip $(NO_SECRETS)), yes)
OPT_DEFS += -DNO_SECRETS
endif
```
## Extras
Additionally, because this file isn't present in the repo at all, you could add additional functionality that nobody else will see.
My [Tap Dance](https://github.com/qmk/qmk_firmware/blob/master/users/drashna/tap_dances.c) file includes the tap dance declarations, and everything needed for them.
This is used for making Diablo 3 much easier to plan, especially at high rift levels.
This works by using Tap Dances. The taps don't actually "do anything". Instead, it sets up the interval for how often to send specific keypresses. As you can tell, this makes automating things very easy.
For critics that think this is cheating, just search "[diablo 3 num lock auto cast](http://lmgtfy.com/?q=diablo+3+numlock+autocast)". This is just a simpler method, that doesn't require a numpad.
## Custom Tap Dance Type
The real fun here is that the tap dances use a custom defined Tap Dance type:
This lets me set an index and keycode for the tap dance. This isn't the cool part yet, but this allows for the really cool stuff.
The Index is needed because I don't know how to handle it otherwise.
## The Actual Dances
These are the custom defined dances that I'm using. It sets up everything for later, using the above custom dance type.
```c
//Tap Dance Definitions, sets the index and the keycode.
qk_tap_dance_action_t tap_dance_actions[] = {
// tap once to disable, and more to enable timed micros
[TD_D3_1] = ACTION_TAP_DANCE_DIABLO(0, KC_1),
[TD_D3_2] = ACTION_TAP_DANCE_DIABLO(1, KC_2),
[TD_D3_3] = ACTION_TAP_DANCE_DIABLO(2, KC_3),
[TD_D3_4] = ACTION_TAP_DANCE_DIABLO(3, KC_4),
};
```
## Custom Data Structures
First, to get this all working, there are a couple of things that need to be set up. In a header file (or you could put it into the keymap), you need to create a couple of custom structures:
```c
typedef struct {
uint16_t timer;
uint8_t key_interval;
uint8_t keycode;
} diablo_timer_t;
typedef struct {
uint8_t index;
uint8_t keycode;
} diable_keys_t;
```
The first structure is for tracking each key that is being used. The second is to pass data from the Tap Dance action array to the actual function that we will need.
## Custom Arrays
To facilitate things, you will need a couple of arrays in your `c` file.
```c
//define diablo macro timer variables
diablo_timer_t diablo_timer[4];
// Set the default intervals. Always start with 0 so that it will disable on first hit.
// Otherwise, you will need to hit a bunch of times, or hit the "clear" command
uint8_t diablo_times[] = { 0, 1, 3, 5, 10, 30 };
```
The first one (`diablo_timer`) is what keeps track of the timer used for the keys, the interval that it uses, and the actual keycode. This makes managing it a lot easier.
The second array is a list of predefined intervals, in seconds. You can add more here, or remove entries. It doesn't matter how long the array is, as this is computed automatically.
## The Magic - Part 1: Master function
The first part of the magic here is the `diablo_tapdance_master` function. The Tap Dance feature calls this function, directly, and passes some data to the function. Namely, it passes the array of the index and the keycode (`diablo_keys_t` from above). This sets the keycode and the interval for the specific index of `diabolo_timer` based on the number of taps. If you hit it more than the number of items in the array, then it zeroes out the interval, disabling it.
```c
// Cycle through the times for the macro, starting at 0, for disabled.
The real core here is the `run_diablo_macro_check()` function. You need to call this from `matrix_scan_user`, as this handles the timer check.
Specifically, it runs a check for each index of the timer. It checks to see if it's enabled, and if enough time has passed. If enough time has passed, it resets the timer, and will tap the keycode that you set for that index, but only if the Diablo layer is enabled.
```c
// Checks each of the 4 timers/keys to see if enough time has elapsed
void run_diablo_macro_check(void) {
for (uint8_t index = 0; index <NUM_OF_DIABLO_KEYS;index++){
// if key_interval is 0, it's disabled, so only run if it's set. If it's set, check the timer.
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.
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.
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: