[Keymap] Drashna's Feature madness (#6128)
* 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 matrixpull/6397/head
parent
840b9090a0
commit
d41961c9ed
@ -1,21 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
/* ws2812 RGB LED */
|
||||
#if defined(KEYBOARD_fractal)
|
||||
# define RGB_DI_PIN D2
|
||||
# undef RGBLED_NUM
|
||||
# define RGBLIGHT_ANIMATIONS
|
||||
# define RGBLED_NUM 29 // Number of LEDs
|
||||
# undef RGBLIGHT_HUE_STEP
|
||||
# define RGBLIGHT_HUE_STEP 8
|
||||
# undef RGBLIGHT_SAT_STEP
|
||||
# define RGBLIGHT_SAT_STEP 8
|
||||
# undef RGBLIGHT_VAL_STEP
|
||||
# define RGBLIGHT_VAL_STEP 8
|
||||
# define RGBLIGHT_LIMIT_VAL 175
|
||||
# define RGBLIGHT_SLEEP
|
||||
# define RGB_DI_PIN D2
|
||||
# undef RGBLED_NUM
|
||||
# define RGBLIGHT_ANIMATIONS
|
||||
# define RGBLED_NUM 29 // Number of LEDs
|
||||
# undef RGBLIGHT_HUE_STEP
|
||||
# define RGBLIGHT_HUE_STEP 8
|
||||
# undef RGBLIGHT_SAT_STEP
|
||||
# define RGBLIGHT_SAT_STEP 8
|
||||
# undef RGBLIGHT_VAL_STEP
|
||||
# define RGBLIGHT_VAL_STEP 8
|
||||
# define RGBLIGHT_LIMIT_VAL 175
|
||||
# define RGBLIGHT_SLEEP
|
||||
|
||||
# define RGBLIGHT_EFFECT_KNIGHT_OFFSET 3
|
||||
# define RGBLIGHT_EFFECT_KNIGHT_LED_NUM 14
|
||||
# define RGBLIGHT_EFFECT_KNIGHT_OFFSET 3
|
||||
# define RGBLIGHT_EFFECT_KNIGHT_LED_NUM 14
|
||||
# define B7_AUDIO
|
||||
# define NO_MUSIC_MODE
|
||||
#endif
|
||||
|
@ -0,0 +1,97 @@
|
||||
# Custom Userspace Function handlers
|
||||
|
||||
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.
|
||||
|
||||
But for a list:
|
||||
|
||||
```c
|
||||
__attribute__ ((weak))
|
||||
void matrix_init_keymap(void) {}
|
||||
|
||||
void matrix_init_user(void) {
|
||||
matrix_init_keymap();
|
||||
}
|
||||
|
||||
__attribute__((weak))
|
||||
void keyboard_post_init_keymap(void){ }
|
||||
|
||||
void keyboard_post_init_user(void){
|
||||
keyboard_post_init_keymap();
|
||||
}
|
||||
|
||||
__attribute__ ((weak))
|
||||
void matrix_scan_keymap(void) {}
|
||||
|
||||
void matrix_scan_user(void) {
|
||||
matrix_scan_keymap();
|
||||
}
|
||||
|
||||
|
||||
__attribute__ ((weak))
|
||||
bool process_record_keymap(uint16_t keycode, keyrecord_t *record) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||
return process_record_keymap(keycode, record);
|
||||
}
|
||||
|
||||
|
||||
__attribute__ ((weak))
|
||||
layer_state_t layer_state_set_keymap (layer_state_t state) {
|
||||
return state;
|
||||
}
|
||||
|
||||
layer_state_t layer_state_set_user (layer_state_t state) {
|
||||
return layer_state_set_keymap (state);
|
||||
}
|
||||
|
||||
|
||||
__attribute__ ((weak))
|
||||
void led_set_keymap(uint8_t usb_led) {}
|
||||
|
||||
void led_set_user(uint8_t usb_led) {
|
||||
led_set_keymap(usb_led);
|
||||
}
|
||||
|
||||
|
||||
__attribute__ ((weak))
|
||||
void suspend_power_down_keymap(void) {}
|
||||
|
||||
void suspend_power_down_user(void) {
|
||||
suspend_power_down_keymap();
|
||||
}
|
||||
|
||||
|
||||
__attribute__ ((weak))
|
||||
void suspend_wakeup_init_keymap(void) {}
|
||||
|
||||
void suspend_wakeup_init_user(void) {
|
||||
suspend_wakeup_init_keymap();
|
||||
}
|
||||
|
||||
|
||||
__attribute__ ((weak))
|
||||
void shutdown_keymap(void) {}
|
||||
|
||||
void shutdown_user (void) {
|
||||
shutdown_keymap();
|
||||
}
|
||||
|
||||
__attribute__ ((weak))
|
||||
void eeconfig_init_keymap(void) {}
|
||||
|
||||
void eeconfig_init_user(void) {
|
||||
eeconfig_init_keymap();
|
||||
}
|
||||
```
|
@ -0,0 +1,10 @@
|
||||
|
||||
# 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.
|
@ -0,0 +1,43 @@
|
||||
# Layer Indication Code
|
||||
|
||||
At least for RGB Light, the `layer_state_set` function is used to detect the current highest layer, and change the underglow based on that layer.
|
||||
|
||||
This works for both the regular layers, and for the default layers, too.
|
||||
|
||||
I use the sethsv variants of the commands, so that different modes can be used, as well.
|
||||
|
||||
RGB Matrix uses a custom, per board implementation, at the moment.
|
||||
|
||||
# RGB Light Startup Animation
|
||||
|
||||
On startup, if enabled, the board will cycle through the entire hue wheel, starting and ending on the default layer color.
|
||||
|
||||
```c
|
||||
void keyboard_post_init_rgb(void) {
|
||||
#if defined(RGBLIGHT_ENABLE) && defined(RGBLIGHT_STARTUP_ANIMATION)
|
||||
if (userspace_config.rgb_layer_change) { rgblight_enable_noeeprom(); }
|
||||
if (rgblight_config.enable) {
|
||||
layer_state_set_user(layer_state);
|
||||
uint16_t old_hue = rgblight_config.hue;
|
||||
rgblight_mode_noeeprom(RGBLIGHT_MODE_STATIC_LIGHT);
|
||||
for (uint16_t i = 255; i > 0; i--) {
|
||||
rgblight_sethsv_noeeprom( ( i + old_hue) % 255, 255, 255);
|
||||
matrix_scan();
|
||||
wait_ms(10);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
layer_state_set_user(layer_state);
|
||||
}
|
||||
```
|
||||
|
||||
This could probably benefit from some cleanup and better handling.
|
||||
|
||||
|
||||
# RGB Light Twinkling
|
||||
|
||||
This enables random twinkling of the LEDs when typing.
|
||||
|
||||
# RGB Light Mod Indicators
|
||||
|
||||
Allows feedback of which mods (oneshot or otherwise) are enabled.
|
@ -0,0 +1,123 @@
|
||||
# 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 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
|
||||
|
||||
#if (__has_include("secrets.h") && !defined(NO_SECRETS))
|
||||
#include "secrets.h"
|
||||
#else
|
||||
// `PROGMEM const char secret[][x]` may work better, but it takes up more space in the firmware
|
||||
// And I'm not familiar enough to know which is better or why...
|
||||
static const char * const secret[] = {
|
||||
"test1",
|
||||
"test2",
|
||||
"test3",
|
||||
"test4",
|
||||
"test5"
|
||||
};
|
||||
#endif
|
||||
|
||||
bool process_record_secrets(uint16_t keycode, keyrecord_t *record) {
|
||||
switch (keycode) {
|
||||
case KC_SECRET_1 ... KC_SECRET_5: // Secrets! Externally defined strings, not stored in repo
|
||||
if (!record->event.pressed) {
|
||||
clear_oneshot_layer_state(ONESHOT_OTHER_KEY_PRESSED);
|
||||
send_string_with_delay(secret[keycode - KC_SECRET_1], MACRO_TIMER);
|
||||
}
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
## secrets.h
|
||||
|
||||
Now, for the actual secrets! The file needs to look like
|
||||
|
||||
```c
|
||||
static const char * secrets[] = {
|
||||
"secret1",
|
||||
"secret2",
|
||||
"secret3",
|
||||
"secret4",
|
||||
"secret5"
|
||||
};
|
||||
```
|
||||
|
||||
Replacing the strings with the codes that you need.
|
||||
|
||||
## Process Record
|
||||
|
||||
In whichever file you have your `process_record_*` function in, you will want to add this to the top:
|
||||
|
||||
```c
|
||||
__attribute__ ((weak))
|
||||
bool process_record_secrets(uint16_t keycode, keyrecord_t *record) {
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
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);`
|
||||
|
||||
```c
|
||||
bool process_record_user(uint16_t keycode, keyrecord_t *record) {
|
||||
// your existing macro code here.
|
||||
return process_record_keymap(keycode, record) && process_record_secrets(keycode, record);
|
||||
}
|
||||
```
|
||||
|
||||
## rules.mk
|
||||
|
||||
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.
|
@ -0,0 +1,119 @@
|
||||
# Diablo Tap Dances
|
||||
|
||||
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:
|
||||
|
||||
```c
|
||||
#define ACTION_TAP_DANCE_DIABLO(index, keycode) { \
|
||||
.fn = { NULL, (void *)diablo_tapdance_master, NULL }, \
|
||||
.user_data = (void *)&((diable_keys_t) { index, keycode }), \
|
||||
}
|
||||
```
|
||||
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.
|
||||
void diablo_tapdance_master(qk_tap_dance_state_t *state, void *user_data) {
|
||||
diable_keys_t *diablo_keys = (diable_keys_t *)user_data;
|
||||
// Sets the keycode based on the index
|
||||
diablo_timer[diablo_keys->index].keycode = diablo_keys->keycode;
|
||||
|
||||
// if the tapdance is hit more than the number of elemints in the array, reset
|
||||
if (state->count >= (sizeof(diablo_times) / sizeof(uint8_t) ) ) {
|
||||
diablo_timer[diablo_keys->index].key_interval = 0;
|
||||
reset_tap_dance(state);
|
||||
} else { // else set the interval (tapdance count starts at 1, array starts at 0, so offset by one)
|
||||
diablo_timer[diablo_keys->index].key_interval = diablo_times[state->count - 1];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## The Magic - Part 2: The Coup de Grace
|
||||
|
||||
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.
|
||||
if ( diablo_timer[index].key_interval && timer_elapsed( diablo_timer[index].timer ) > ( diablo_timer[index].key_interval * 1000 ) ) {
|
||||
// reset the timer, since enough time has passed
|
||||
diablo_timer[index].timer = timer_read();
|
||||
// send keycode ONLY if we're on the diablo layer.
|
||||
if (IS_LAYER_ON(_DIABLO)) {
|
||||
tap_code(diablo_timer[index].keycode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
@ -0,0 +1,11 @@
|
||||
## 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:
|
||||
|
||||
`#define LAYOUT_ergodox_wrapper(...) LAYOUT_ergodox(__VA_ARGS__)`
|
||||
|
||||
Once that's been done and you've switched the keymaps to use the "wrapper", it will read the substitution blocks just fine.
|
@ -1,23 +1,23 @@
|
||||
#pragma once
|
||||
#include "quantum.h"
|
||||
#ifdef RGB_MATRIX_ENABLE
|
||||
#include "rgb_matrix.h"
|
||||
# include "rgb_matrix.h"
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
bool enabled;
|
||||
uint8_t hue;
|
||||
bool enabled;
|
||||
uint8_t hue;
|
||||
uint16_t timer;
|
||||
uint8_t life;
|
||||
uint8_t life;
|
||||
} rgblight_fadeout;
|
||||
|
||||
bool process_record_user_rgb(uint16_t keycode, keyrecord_t *record);
|
||||
void scan_rgblight_fadeout(void);
|
||||
void keyboard_post_init_rgb(void);
|
||||
void matrix_scan_rgb(void);
|
||||
bool process_record_user_rgb(uint16_t keycode, keyrecord_t *record);
|
||||
void scan_rgblight_fadeout(void);
|
||||
void keyboard_post_init_rgb(void);
|
||||
void matrix_scan_rgb(void);
|
||||
layer_state_t layer_state_set_rgb(layer_state_t state);
|
||||
layer_state_t default_layer_state_set_rgb(layer_state_t state);
|
||||
void rgblight_sethsv_default_helper(uint8_t index);
|
||||
void rgb_matrix_set_color_all( uint8_t red, uint8_t green, uint8_t blue );
|
||||
void rgblight_sethsv_default_helper(uint8_t index);
|
||||
void rgb_matrix_set_color_all(uint8_t red, uint8_t green, uint8_t blue);
|
||||
|
||||
void rgb_matrix_layer_helper (uint8_t red, uint8_t green, uint8_t blue, uint8_t led_type);
|
||||
void rgb_matrix_layer_helper(uint8_t hue, uint8_t sat, uint8_t val, uint8_t mode, uint8_t speed, uint8_t led_type);
|
||||
|
@ -1,71 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "quantum.h"
|
||||
|
||||
void send_unicode_hex_string(const char* str);
|
||||
|
||||
/* use X(n) to call the */
|
||||
#ifdef UNICODEMAP_ENABLE
|
||||
enum unicode_name {
|
||||
THINK, // thinking face 🤔
|
||||
GRIN, // grinning face 😊
|
||||
SMRK, // smirk 😏
|
||||
WEARY, // good shit 😩
|
||||
UNAMU, // unamused 😒
|
||||
|
||||
SNEK, // snke 🐍
|
||||
PENGUIN, // 🐧
|
||||
DRAGON, // 🐉
|
||||
MONKEY, // 🐒
|
||||
CHICK, // 🐥
|
||||
BOAR, // 🐗
|
||||
|
||||
OKOK, // 👌
|
||||
EFFU, // 🖕
|
||||
INUP, // 👆
|
||||
THUP, // 👍
|
||||
THDN, // 👎
|
||||
|
||||
BBB, // dat B 🅱
|
||||
POO, // poop 💩
|
||||
HUNDR, // 100 💯
|
||||
EGGPL, // EGGPLANT 🍆
|
||||
WATER, // wet 💦
|
||||
TUMBLER, // 🥃
|
||||
|
||||
LIT, // fire 🔥
|
||||
BANG, // ‽
|
||||
IRONY, // ⸮
|
||||
DEGREE // °
|
||||
};
|
||||
|
||||
|
||||
const uint32_t PROGMEM unicode_map[] = {
|
||||
[THINK] = 0x1F914,
|
||||
[GRIN] = 0x1F600,
|
||||
[BBB] = 0x1F171,
|
||||
[POO] = 0x1F4A9,
|
||||
[HUNDR] = 0x1F4AF,
|
||||
[SMRK] = 0x1F60F,
|
||||
[WEARY] = 0x1F629,
|
||||
[EGGPL] = 0x1F346,
|
||||
[WATER] = 0x1F4A6,
|
||||
[LIT] = 0x1F525,
|
||||
[UNAMU] = 0x1F612,
|
||||
[SNEK] = 0x1F40D,
|
||||
[PENGUIN] = 0x1F427,
|
||||
[BOAR] = 0x1F417,
|
||||
[MONKEY] = 0x1F412,
|
||||
[CHICK] = 0x1F425,
|
||||
[DRAGON] = 0x1F409,
|
||||
[OKOK] = 0x1F44C,
|
||||
[EFFU] = 0x1F595,
|
||||
[INUP] = 0x1F446,
|
||||
[THDN] = 0x1F44E,
|
||||
[THUP] = 0x1F44D,
|
||||
[TUMBLER] = 0x1F943,
|
||||
[BANG] = 0x0203D,
|
||||
[IRONY] = 0x02E2E,
|
||||
[DEGREE] = 0x000B0
|
||||
};
|
||||
#endif // UNICODEMAP_ENABLE
|
@ -1,65 +1,56 @@
|
||||
#include "tap_dances.h"
|
||||
|
||||
#define NUM_OF_DIABLO_KEYS 4
|
||||
// define diablo macro timer variables
|
||||
diablo_timer_t diablo_timer[NUM_OF_DIABLO_KEYS];
|
||||
|
||||
//define diablo macro timer variables
|
||||
diablo_timer_t diablo_timer[4];
|
||||
|
||||
uint8_t diablo_times[] = { 0, 0, 1, 3, 5, 10, 30 };
|
||||
|
||||
// has the correct number of seconds elapsed (as defined by diablo_times)
|
||||
bool check_dtimer(uint8_t dtimer) { return (timer_elapsed(diablo_timer[dtimer].key_time) < (diablo_timer[dtimer].timer * 1000)) ? false : true; };
|
||||
// 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};
|
||||
|
||||
// Cycle through the times for the macro, starting at 0, for disabled.
|
||||
// Max of six values, so don't exceed
|
||||
void diablo_tapdance_master(qk_tap_dance_state_t *state, void *user_data) {
|
||||
int index = (int)user_data;
|
||||
if (state->count >= 7) {
|
||||
diablo_timer[index].key_time = diablo_times[0];
|
||||
diable_keys_t *diablo_keys = (diable_keys_t *)user_data;
|
||||
// Sets the keycode based on the index
|
||||
diablo_timer[diablo_keys->index].keycode = diablo_keys->keycode;
|
||||
|
||||
// if the tapdance is hit more than the number of elemints in the array, reset
|
||||
if (state->count >= (sizeof(diablo_times) / sizeof(uint8_t))) {
|
||||
diablo_timer[diablo_keys->index].key_interval = 0;
|
||||
reset_tap_dance(state);
|
||||
} else {
|
||||
diablo_timer[index].key_time = diablo_times[state->count];
|
||||
} else { // else set the interval (tapdance count starts at 1, array starts at 0, so offset by one)
|
||||
diablo_timer[diablo_keys->index].key_interval = diablo_times[state->count - 1];
|
||||
}
|
||||
}
|
||||
|
||||
// One funtion to rule them all!!
|
||||
#define ACTION_TAP_DANCE_DIABLO(arg) { \
|
||||
// clang-format off
|
||||
// One function to rule them all!! Where the Magic Sauce lies
|
||||
#define ACTION_TAP_DANCE_DIABLO(index, keycode) { \
|
||||
.fn = { NULL, (void *)diablo_tapdance_master, NULL }, \
|
||||
.user_data = (void *)arg, \
|
||||
.user_data = (void *)&((diable_keys_t) { index, keycode }), \
|
||||
}
|
||||
// clang-format on
|
||||
|
||||
//Tap Dance Definitions
|
||||
// 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),
|
||||
[TD_D3_2] = ACTION_TAP_DANCE_DIABLO(1),
|
||||
[TD_D3_3] = ACTION_TAP_DANCE_DIABLO(2),
|
||||
[TD_D3_4] = ACTION_TAP_DANCE_DIABLO(3),
|
||||
[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),
|
||||
};
|
||||
|
||||
// Sends the key press to system, but only if on the Diablo layer
|
||||
void send_diablo_keystroke(uint8_t diablo_key) {
|
||||
if (IS_LAYER_ON(_DIABLO)) {
|
||||
switch (diablo_key) {
|
||||
case 0:
|
||||
tap_code(KC_1); break;
|
||||
case 1:
|
||||
tap_code(KC_2); break;
|
||||
case 2:
|
||||
tap_code(KC_3); break;
|
||||
case 3:
|
||||
tap_code(KC_4); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Checks each of the 4 timers/keys to see if enough time has elapsed
|
||||
// Runs the "send string" command if enough time has passed, and resets the timer.
|
||||
void run_diablo_macro_check(void) {
|
||||
uint8_t dtime;
|
||||
for (dtime = 0; dtime < 4; dtime++) {
|
||||
if (check_dtimer(dtime) && diablo_timer[dtime].key_time) {
|
||||
diablo_timer[dtime].timer = timer_read();
|
||||
send_diablo_keystroke(dtime);
|
||||
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.
|
||||
if (diablo_timer[index].key_interval && timer_elapsed(diablo_timer[index].timer) > (diablo_timer[index].key_interval * 1000)) {
|
||||
// reset the timer, since enough time has passed
|
||||
diablo_timer[index].timer = timer_read();
|
||||
// send keycode ONLY if we're on the diablo layer.
|
||||
if (IS_LAYER_ON(_DIABLO)) {
|
||||
tap_code(diablo_timer[index].keycode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,22 +1,30 @@
|
||||
#pragma once
|
||||
#include "drashna.h"
|
||||
|
||||
//define diablo macro timer variables
|
||||
// define diablo macro timer variables
|
||||
extern uint8_t diablo_times[];
|
||||
typedef struct {
|
||||
uint16_t timer;
|
||||
uint8_t key_time;
|
||||
uint8_t key_interval;
|
||||
uint8_t keycode;
|
||||
} diablo_timer_t;
|
||||
|
||||
extern diablo_timer_t diablo_timer[4];
|
||||
typedef struct {
|
||||
uint8_t index;
|
||||
uint8_t keycode;
|
||||
} diable_keys_t;
|
||||
|
||||
extern diablo_timer_t diablo_timer[];
|
||||
|
||||
void run_diablo_macro_check(void);
|
||||
|
||||
#ifdef TAP_DANCE_ENABLE
|
||||
// clang-format off
|
||||
enum {
|
||||
TD_D3_1 = 0,
|
||||
TD_D3_2,
|
||||
TD_D3_3,
|
||||
TD_D3_4
|
||||
};
|
||||
#endif // TAP_DANCE_ENABLE
|
||||
// clang-format on
|
||||
#endif // TAP_DANCE_ENABLE
|
||||
|
Loading…
Reference in new issue