diff options
author | Drashna Jaelre <drashna@live.com> | 2018-03-25 13:01:15 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-03-25 13:01:15 -0700 |
commit | 0c665696d7b498bd278d05eed3b52c1fac89ff29 (patch) | |
tree | a14f3ca315d4e9d044163b219d78d34e48f3eb7f /users/drashna | |
parent | a09a042b8fe6a0369a7c479168492125efa24e59 (diff) | |
download | qmk_firmware-0c665696d7b498bd278d05eed3b52c1fac89ff29.tar.gz qmk_firmware-0c665696d7b498bd278d05eed3b52c1fac89ff29.zip |
Update to drashna files (#2587)
* Add Colemak Mod-DH vars
* Add Norman Layot vars
* Set Shift Indicator to include CAPS Lock as well
* Change MEH to GUI
* Add Enter to Macro layer
* Switch raise and lower layers to make more sense (to me)
* Replace unused quote on Ergodox
* Add One Shot defines
* Dim indicator LEDs
* Add short codes for KC_SECRET
* Fix typos
* Update OLKB code in userspace
* Add global userspace config.h
* add compile fix
* Automatically include from userspace
* update readme
* Re-add QMK Scan loop
* Add EEPROM reset code to all keymaps
* Shorten fauxclick sound
* Use layouts instead of keymap, when possible
* Add OSM detection to ergodox
* Convert Viterbi to LAYOUT macro
* Clean up game macros
* Because I accidently removed the C6 AUDIO define from my viterbi... Whoops
* Minor formatting
* Fix Woodpad because it's still there
* Move Ergodox keymap into layouts folder
* Add build date to version macro
* Remove PREVENT_STUCK_MODIFIERS from config
Diffstat (limited to 'users/drashna')
-rw-r--r-- | users/drashna/config.h | 61 | ||||
-rw-r--r-- | users/drashna/drashna.c | 125 | ||||
-rw-r--r-- | users/drashna/drashna.h | 64 | ||||
-rw-r--r-- | users/drashna/readme.md | 27 | ||||
-rw-r--r-- | users/drashna/rules.mk | 4 |
5 files changed, 177 insertions, 104 deletions
diff --git a/users/drashna/config.h b/users/drashna/config.h new file mode 100644 index 0000000000..f33721d23d --- /dev/null +++ b/users/drashna/config.h @@ -0,0 +1,61 @@ +#ifndef USERSPACE_CONFIG_H +#define USERSPACE_CONFIG_H + + +#ifdef AUDIO_ENABLE +#define STARTUP_SONG SONG(IMPERIAL_MARCH) +#define GOODBYE_SONG SONG(SONIC_RING) +#define DEFAULT_LAYER_SONGS { SONG(QWERTY_SOUND), \ + SONG(COLEMAK_SOUND), \ + SONG(DVORAK_SOUND), \ + SONG(PLOVER_SOUND) \ + } +#endif + +#ifdef RGBLIGHT_ENABLE +#define RGBLIGHT_SLEEP +#endif // RGBLIGHT_ENABLE + + + +#ifndef ONESHOT_TAP_TOGGLE +#define ONESHOT_TAP_TOGGLE 2 +#endif // !ONESHOT_TAP_TOGGLE + +#ifndef ONESHOT_TIMEOUT +#define ONESHOT_TIMEOUT 3000 +#endif// !ONESHOT_TIMEOUT + +#ifndef QMK_KEYS_PER_SCAN +#define QMK_KEYS_PER_SCAN 4 +#endif // !QMK_KEYS_PER_SCAN + + + +// this makes it possible to do rolling combos (zx) with keys that +// convert to other keys on hold (z becomes ctrl when you hold it, +// and when this option isn't enabled, z rapidly followed by x +// actually sends Ctrl-x. That's bad.) +#define IGNORE_MOD_TAP_INTERRUPT +#undef PERMISSIVE_HOLD +#undef PREVENT_STUCK_MODIFIERS + +#ifndef TAPPING_TOGGLE +#define TAPPING_TOGGLE 1 +#endif + +#ifdef TAPPING_TERM +#undef TAPPING_TERM +#endif +#define TAPPING_TERM 150 + + +// Disable action_get_macro and fn_actions, since we don't use these +// and it saves on space in the firmware. +#define NO_ACTION_MACRO +#define NO_ACTION_FUNCTION + + + +#endif // !USERSPACE_CONFIG_H + diff --git a/users/drashna/drashna.c b/users/drashna/drashna.c index 678570958b..09b3891dd7 100644 --- a/users/drashna/drashna.c +++ b/users/drashna/drashna.c @@ -22,7 +22,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #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 familar enough to know which is better or why... +// And I'm not familiar enough to know which is better or why... PROGMEM const char secret[][64] = { "test1", "test2", @@ -32,20 +32,13 @@ PROGMEM const char secret[][64] = { }; #endif -#ifdef AUDIO_ENABLE -float tone_qwerty[][2] = SONG(QWERTY_SOUND); -float tone_dvorak[][2] = SONG(DVORAK_SOUND); -float tone_colemak[][2] = SONG(COLEMAK_SOUND); -float tone_workman[][2] = SONG(PLOVER_SOUND); -float tone_hackstartup[][2] = SONG(ONE_UP_SOUND); -#endif #ifdef FAUXCLICKY_ENABLE float fauxclicky_pressed_note[2] = MUSICAL_NOTE(_A6, 2); // (_D4, 0.25); float fauxclicky_released_note[2] = MUSICAL_NOTE(_A6, 2); // (_C4, 0.125); #else -float fauxclicky_pressed[][2] = SONG(E__NOTE(_A6)); // change to your tastes -float fauxclicky_released[][2] = SONG(E__NOTE(_A6)); // change to your tastes +float fauxclicky_pressed[][2] = SONG(S__NOTE(_A6)); // change to your tastes +float fauxclicky_released[][2] = SONG(S__NOTE(_A6)); // change to your tastes #endif bool faux_click_enabled = false; @@ -191,7 +184,7 @@ void matrix_init_user(void) { #endif matrix_init_keymap(); } -// No global matrix scan code, so just run keymap's matix +// No global matrix scan code, so just run keymap's matrix // scan function void matrix_scan_user(void) { #ifdef TAP_DANCE_ENABLE // Run Diablo 3 macro checking code. @@ -202,17 +195,20 @@ void matrix_scan_user(void) { // This block is for all of the gaming macros, as they were all doing // the same thing, but with differring text sent. -void send_game_macro(const char *str) { - clear_keyboard(); - register_code(is_overwatch ? KC_BSPC : KC_ENTER); - unregister_code(is_overwatch ? KC_BSPC : KC_ENTER); - wait_ms(50); - send_string(str); - register_code(KC_ENTER); - unregister_code(KC_ENTER); +bool send_game_macro(const char *str, keyrecord_t *record, bool override) { + if (!record->event.pressed || override) { + clear_keyboard(); + register_code(is_overwatch ? KC_BSPC : KC_ENTER); + unregister_code(is_overwatch ? KC_BSPC : KC_ENTER); + wait_ms(50); + send_string(str); + register_code(KC_ENTER); + unregister_code(KC_ENTER); + } + if (override) wait_ms(3000); + return false; } - // Sent the default layer void persistent_default_layer_set(uint16_t default_layer) { eeconfig_update_default_layer(default_layer); @@ -221,7 +217,7 @@ void persistent_default_layer_set(uint16_t default_layer) { // Defines actions tor my global custom keycodes. Defined in drashna.h file -// Then runs the _keymap's recod handier if not processed here +// Then runs the _keymap's record handier if not processed here bool process_record_user(uint16_t keycode, keyrecord_t *record) { // If console is enabled, it will print the matrix position and status of each key pressed @@ -230,7 +226,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) { #endif //CONSOLE_ENABLE // Run custom faux click code, but only if faux clicky is enabled -#ifdef AUDIO_ENABLE +#ifdef AUDIO_ENABLE if ( (faux_click_enabled && keycode != KC_FXCL) || (!faux_click_enabled && keycode == KC_FXCL) ) { if (record->event.pressed) { PLAY_SONG(fauxclicky_pressed); @@ -245,37 +241,25 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) { switch (keycode) { case KC_QWERTY: if (record->event.pressed) { -#ifdef AUDIO_ENABLE - PLAY_SONG(tone_qwerty); -#endif //AUDIO_ENABLE - persistent_default_layer_set(1UL << _QWERTY); + set_single_persistent_default_layer(_QWERTY); } return false; break; case KC_COLEMAK: if (record->event.pressed) { -#ifdef AUDIO_ENABLE - PLAY_SONG(tone_colemak); -#endif //AUDIO_ENABLE - persistent_default_layer_set(1UL << _COLEMAK); + set_single_persistent_default_layer(_COLEMAK); } return false; break; case KC_DVORAK: if (record->event.pressed) { -#ifdef AUDIO_ENABLE - PLAY_SONG(tone_dvorak); -#endif //AUDIO_ENABLE - persistent_default_layer_set(1UL << _DVORAK); + set_single_persistent_default_layer(_DVORAK); } return false; break; case KC_WORKMAN: if (record->event.pressed) { -#ifdef AUDIO_ENABLE - PLAY_SONG(tone_workman); -#endif //AUDIO_ENABLE - persistent_default_layer_set(1UL << _WORKMAN); + set_single_persistent_default_layer(_WORKMAN); } return false; break; @@ -328,7 +312,9 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) { } return false; break; - case KC_RESET: // Custom RESET code that setr RGBLights to RED + + + case KC_RESET: // Custom RESET code that sets RGBLights to RED if (!record->event.pressed) { #ifdef RGBLIGHT_ENABLE rgblight_enable(); @@ -339,6 +325,8 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) { } return false; break; + + case EPRM: // Resets EEPROM if (record->event.pressed) { eeconfig_init(); @@ -347,11 +335,13 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) { break; case VRSN: // Prints firmware version if (record->event.pressed) { - SEND_STRING(QMK_KEYBOARD "/" QMK_KEYMAP " @ " QMK_VERSION); + SEND_STRING(QMK_KEYBOARD "/" QMK_KEYMAP " @ " QMK_VERSION ", Built on: " QMK_BUILDDATE); } return false; break; - case KC_SECRET_1 ... KC_SECRET_5: // Custom + + + 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_P(secret[keycode - KC_SECRET_1]); @@ -364,61 +354,42 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) { // Only enables for the viterbi, basically, // to save on firmware space, since it's limited. #if !(defined(KEYBOARD_orthodox_rev1) || defined(KEYBOARD_orthodox_rev3) || defined(KEYBOARD_ergodox_ez)) - - case KC_OVERWATCH: // Toggle's if we hit "ENTER" or "BACKSPACE" to input macros if (record->event.pressed) { is_overwatch = !is_overwatch; } #ifdef RGBLIGHT_ENABLE is_overwatch ? rgblight_mode(17) : rgblight_mode(18); #endif //RGBLIGHT_ENABLE - return false; - break; - - case KC_SALT: - if (!record->event.pressed) { send_game_macro("Salt, salt, salt..."); } return false; break; + case KC_SALT: + return send_game_macro("Salt, salt, salt...", record, false); case KC_MORESALT: - if (!record->event.pressed) { send_game_macro("Please sir, can I have some more salt?!"); } - return false; break; + return send_game_macro("Please sir, can I have some more salt?!", record, false); case KC_SALTHARD: - if (!record->event.pressed) { send_game_macro("Your salt only makes me harder, and even more aggressive!"); } - return false; break; + return send_game_macro("Your salt only makes me harder, and even more aggressive!", record, false); case KC_GOODGAME: - if (!record->event.pressed) { send_game_macro("Good game, everyone!"); } - return false; break; + return send_game_macro("Good game, everyone!", record, false); case KC_GLHF: - if (!record->event.pressed) { send_game_macro("Good luck, have fun!!!"); } - return false; break; + return send_game_macro("Good luck, have fun!!!", record, false); case KC_SYMM: - if (!record->event.pressed) { send_game_macro("Left click to win!"); } - return false; break; + return send_game_macro("Left click to win!", record, false); case KC_JUSTGAME: - if (!record->event.pressed) { send_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."); } - return false; break; + return send_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); case KC_TORB: - if (!record->event.pressed) { send_game_macro("That was positively riveting!"); } - return false; break; + return send_game_macro("That was positively riveting!", record, false); case KC_AIM: - if (!record->event.pressed) { - send_game_macro("That aim is absolutely amazing. It's almost like you're a machine!"); - wait_ms(3000); - send_game_macro("Wait! That aim is TOO good! You're clearly using an aim hack! CHEATER!"); - } - return false; break; + send_game_macro("That aim is absolutely amazing. It's almost like you're a machine!", record, true); + return send_game_macro("Wait! That aim is TOO good! You're clearly using an aim hack! CHEATER!", record, false); case KC_C9: - if (!record->event.pressed) { send_game_macro("OMG!!! C9!!!"); } - return false; break; + return send_game_macro("OMG!!! C9!!!", record, false); case KC_GGEZ: - if (!record->event.pressed) { send_game_macro("That was a fantastic game, though it was a bit easy. Try harder next time!"); } - return false; break; + return send_game_macro("That was a fantastic game, though it was a bit easy. Try harder next time!", record, false); #endif // !(defined(KEYBOARD_orthodox_rev1) || defined(KEYBOARD_orthodox_rev3) || defined(KEYBOARD_ergodox_ez)) #ifdef TAP_DANCE_ENABLE - case KC_DIABLO_CLEAR: // reset all Diable timers, disabling them + case KC_DIABLO_CLEAR: // reset all Diablo timers, disabling them if (record->event.pressed) { uint8_t dtime; - for (dtime = 0; dtime < 4; dtime++) { diablo_key_time[dtime] = diablo_times[0]; } @@ -437,14 +408,14 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) { if (record->event.pressed) { rgb_layer_change = !rgb_layer_change; if (rgb_layer_change) { - layer_state_set(layer_state); // This is needed to immediately set the layer color (looks beetter) + layer_state_set(layer_state); // This is needed to immediately set the layer color (looks better) } } #endif // RGBLIGHT_ENABLE return false; break; #ifdef RGBLIGHT_ENABLE case RGB_MODE_FORWARD ... RGB_MODE_GRADIENT: // quantum_keycodes.h L400 for definitions - if (record->event.pressed) { //This disrables layer indication, as it's assumed that if you're changing this ... you want that disabled + if (record->event.pressed) { //This disables layer indication, as it's assumed that if you're changing this ... you want that disabled rgb_layer_change = false; } return true; break; @@ -534,7 +505,7 @@ uint32_t layer_state_set_user(uint32_t state) { // Any custom LED code goes here. // So far, I only have keyboard specific code, -// So nothing goes here. +// So nothing goes here. void led_set_user(uint8_t usb_led) { led_set_keymap(usb_led); } diff --git a/users/drashna/drashna.h b/users/drashna/drashna.h index 8a022cd14b..0df9abb468 100644 --- a/users/drashna/drashna.h +++ b/users/drashna/drashna.h @@ -17,10 +17,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. #ifndef USERSPACE #define USERSPACE - #include "quantum.h" -// Define layer names +// Define layer names #define _QWERTY 0 #define _NUMLOCK 0 #define _COLEMAK 1 @@ -118,6 +117,12 @@ enum userspace_custom_keycodes { NEW_SAFE_RANGE //use "NEWPLACEHOLDER for keymap specific codes }; +#define KC_SEC1 KC_SECRET_1 +#define KC_SEC2 KC_SECRET_2 +#define KC_SEC3 KC_SECRET_3 +#define KC_SEC4 KC_SECRET_4 +#define KC_SEC5 KC_SECRET_5 + #ifdef TAP_DANCE_ENABLE enum { TD_D3_1 = 0, @@ -129,8 +134,8 @@ enum { // Custom Keycodes for Diablo 3 layer -// But since TD() doesn't work when tapdance is disabled -// We use custom codes here, so we can substituet the right stuff +// But since TD() doesn't work when tap dance is disabled +// We use custom codes here, so we can substitute the right stuff #ifdef TAP_DANCE_ENABLE #define KC_D3_1 TD(TD_D3_1) #define KC_D3_2 TD(TD_D3_2) @@ -146,26 +151,10 @@ enum { // OSM keycodes, to keep things clean and easy to change #define KC_MLSF OSM(MOD_LSFT) #define KC_MRSF OSM(MOD_RSFT) -#define ONESHOT_TIMEOUT 3000 - -#define QMK_KEYS_PER_SCAN 8 -#ifdef RGBLIGHT_ENABLE -#define RGBLIGHT_SLEEP -#endif // RGBLIGHT_ENABLE -// this makes it possible to do rolling combos (zx) with keys that -// convert to other keys on hold (z becomes ctrl when you hold it, -// and when this option isn't enabled, z rapidly followed by x -// actually sends Ctrl-x. That's bad.) -#define IGNORE_MOD_TAP_INTERRUPT -// Disable action_get_macro and fn_actions, since we don't use these -// and it saves on space in the firmware. -#define NO_ACTION_MACRO -#define NO_ACTION_FUNCTION - -// If we're still using the official Faux Clicky feature, substituet codes +// If we're still using the official Faux Clicky feature, substitute codes // so that we don't have any unused/blank keys. #ifdef FAUXCLICKY_ENABLE #define AUD_ON FC_ON @@ -177,23 +166,27 @@ enum { -// Since our quirky block definitions are basically a list of comma separated -// arguments, we need a wrapper in order for these definitions to be +// Since our quirky block definitions are basically a list of comma separated +// arguments, we need a wrapper in order for these definitions to be // expanded before being used as arguments to the LAYOUT_xxx macro. +#if (!defined(LAYOUT) && defined(KEYMAP)) +#define LAYOUT KEYMAP +#endif + #define LAYOUT_ergodox_wrapper(...) LAYOUT_ergodox(__VA_ARGS__) #define LAYOUT_ergodox_pretty_wrapper(...) LAYOUT_ergodox_pretty(__VA_ARGS__) -#define KEYMAP_wrapper(...) KEYMAP(__VA_ARGS__) +#define KEYMAP_wrapper(...) LAYOUT(__VA_ARGS__) // Blocks for each of the four major keyboard layouts // Organized so we can quickly adapt and modify all of them // at once, rather than for each keyboard, one at a time. -// And this allows wor much cleaner blocks in the keymaps. +// And this allows for much cleaner blocks in the keymaps. // For instance Tap/Hold for Control on all of the layouts // NOTE: These are all the same length. If you do a search/replace // then you need to add/remove underscores to keep the -// lengths consistent. +// lengths consistent. #define _________________QWERTY_L1_________________ KC_Q, KC_W, KC_E, KC_R, KC_T #define _________________QWERTY_L2_________________ KC_A, KC_S, KC_D, KC_F, KC_G @@ -212,6 +205,14 @@ enum { #define _________________COLEMAK_R2________________ KC_H, KC_N, KC_E, KC_I, KC_O #define _________________COLEMAK_R3________________ KC_K, KC_M, KC_COMM, KC_DOT, CTL_T(KC_SLASH) +#define ______________COLEMAK_MOD_DH_L1____________ KC_Q, KC_W, KC_F, KC_P, KC_B +#define ______________COLEMAK_MOD_DH_L2____________ KC_A, KC_R, KC_S, KC_T, KC_G +#define ______________COLEMAK_MOD_DH_L3____________ CTL_T(KC_Z), KC_X, KC_C, KC_D, KC_V + +#define ______________COLEMAK_MOD_DH_R1____________ KC_J, KC_L, KC_U, KC_Y, KC_SCLN +#define ______________COLEMAK_MOD_DH_R2____________ KC_K, KC_N, KC_E, KC_I, KC_O +#define ______________COLEMAK_MOD_DH_R3____________ KC_M, KC_H, KC_COMM, KC_DOT, CTL_T(KC_SLASH) + #define _________________DVORAK_L1_________________ KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y #define _________________DVORAK_L2_________________ KC_A, KC_O, KC_E, KC_U, KC_I @@ -231,12 +232,21 @@ enum { #define _________________WORKMAN_R3________________ KC_B, KC_M, KC_W, KC_V, CTL_T(KC_Z) +#define _________________NORMAN_L1_________________ KC_Q, KC_W, KC_D, KC_F, KC_K +#define _________________NORMAN_L2_________________ KC_A, KC_S, KC_E, KC_T, KC_G +#define _________________NORMAN_L3_________________ CTL_T(KC_Z), KC_X, KC_C, KC_V, KC_B + +#define _________________NORMAN_R1_________________ KC_J, KC_U, KC_R, KC_L, KC_SCLN +#define _________________NORMAN_R2_________________ KC_J, KC_N, KC_I, KC_O, KC_U +#define _________________NORMAN_R3_________________ KC_P, KC_M, KC_COMM, KC_DOT, CTL_T(KC_SLASH) + + // Since we have 4 default layouts (QWERTY, DVORAK, COLEMAK and WORKMAN), // this allows us to quickly modify the bottom row for all of the layouts // so we don't have to alter it 4 times and hope that we haven't missed // anything -#define ___________ERGODOX_BOTTOM_LEFT_____________ KC_QUOT, KC_MEH, KC_LBRC, KC_RBRC +#define ___________ERGODOX_BOTTOM_LEFT_____________ KC_MEH, KC_LGUI, KC_LBRC, KC_RBRC #define ___________ERGODOX_BOTTOM_RIGHT____________ KC_LEFT, KC_DOWN, KC_UP, KC_RGHT diff --git a/users/drashna/readme.md b/users/drashna/readme.md index 92792fb97a..2229a3fe09 100644 --- a/users/drashna/readme.md +++ b/users/drashna/readme.md @@ -3,6 +3,33 @@ Overview This is my personal userspace file. Most of my code exists here, as it's heavily shared. +Userspace Config.h +------------------ + +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. + +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. + +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: + +``` +ifneq ("$(wildcard users/$(KEYMAP)/config.h)","") + CONFIG_H += users/$(KEYMAP)/config.h +endif +``` + +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. + +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: + +``` +#ifndef USERSPACE_CONFIG_H +#define USERSPACE_CONFIG_H + +// put stuff here + +#endif +``` Custom userspace handlers ------------------------- diff --git a/users/drashna/rules.mk b/users/drashna/rules.mk index ab2ab607d4..6d9f0664ea 100644 --- a/users/drashna/rules.mk +++ b/users/drashna/rules.mk @@ -1,3 +1,7 @@ SRC += drashna.c EXTRAFLAGS += -flto + +ifneq ("$(wildcard users/$(KEYMAP)/config.h)","") + CONFIG_H += users/$(KEYMAP)/config.h +endif |