summaryrefslogtreecommitdiff
path: root/users
diff options
context:
space:
mode:
authorEric Gebhart <e.a.gebhart@gmail.com>2018-06-08 19:06:25 +0200
committerDrashna Jaelre <drashna@live.com>2018-06-08 10:06:25 -0700
commit984621835d929b79a22ef33c0a4e602adb1ecc5b (patch)
tree11637c54105b229f3127b019ff0cc962926fb770 /users
parent03c9deb7456d84a8d8cc31496ae2736305bbafd3 (diff)
Keyboard that works on Qwerty or Bepo OS keyboards. (#3149)
* New layout. * new dvorak bepo layout. * first commit of new ergodox_ez dvorak keyboard for qwerty and bepo.
Diffstat (limited to 'users')
-rwxr-xr-xusers/ericgebhart/config.h33
-rw-r--r--users/ericgebhart/ericgebhart.c637
-rw-r--r--users/ericgebhart/ericgebhart.h429
-rwxr-xr-xusers/ericgebhart/flash-ergodox1
-rw-r--r--users/ericgebhart/readme.md124
-rwxr-xr-xusers/ericgebhart/rules.mk18
-rwxr-xr-xusers/ericgebhart/switch-kbd74
7 files changed, 1316 insertions, 0 deletions
diff --git a/users/ericgebhart/config.h b/users/ericgebhart/config.h
new file mode 100755
index 0000000000..934c3debba
--- /dev/null
+++ b/users/ericgebhart/config.h
@@ -0,0 +1,33 @@
+#ifndef USERSPACE_CONFIG_H
+#define USERSPACE_CONFIG_H
+
+#include "../../config.h"
+
+// Sets good default for the speed of the mouse.
+#undef MOUSEKEY_INTERVAL
+#undef MOUSEKEY_DELAY
+#undef MOUSEKEY_TIME_TO_MAX
+#undef MOUSEKEY_MAX_SPEED
+
+#define MOUSEKEY_INTERVAL 20
+#define MOUSEKEY_DELAY 100
+#define MOUSEKEY_TIME_TO_MAX 60
+#define MOUSEKEY_MAX_SPEED 7
+
+#undef MOUSEKEY_WHEEL_MAX_SPEED
+#undef MOUSEKEY_WHEEL_TIME_TO_MAX
+#undef MOUSEKEY_WHEEL_DELAY
+
+#define MOUSEKEY_WHEEL_MAX_SPEED 5
+#define MOUSEKEY_WHEEL_TIME_TO_MAX 60
+#define MOUSEKEY_WHEEL_DELAY 100
+
+#undef TAPPING_TOGGLE
+#undef TAPPING_TERM
+#undef IGNORE_MOD_TAP_INTERRUPT
+
+#define TAPPING_TOGGLE 1
+#define TAPPING_TERM 200
+#define IGNORE_MOD_TAP_INTERRUPT
+
+#endif
diff --git a/users/ericgebhart/ericgebhart.c b/users/ericgebhart/ericgebhart.c
new file mode 100644
index 0000000000..69aa450e0a
--- /dev/null
+++ b/users/ericgebhart/ericgebhart.c
@@ -0,0 +1,637 @@
+/*
+ Copyright 2018 Eric Gebhart <e.a.gebhart@gmail.com>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include "ericgebhart.h"
+
+#include "quantum.h"
+#include "version.h"
+#include "action.h"
+#include "action_layer.h"
+#include "process_keycode/process_tap_dance.h"
+#include "keymap_bepo.h"
+
+float tone_copy[][2] = SONG(SCROLL_LOCK_ON_SOUND);
+float tone_paste[][2] = SONG(SCROLL_LOCK_OFF_SOUND);
+
+static uint16_t copy_paste_timer;
+userspace_config_t userspace_config;
+
+void tap(uint16_t keycode){ register_code(keycode); unregister_code(keycode); };
+
+
+// Add reconfigurable functions here, for keymap customization
+// This allows for a global, userspace functions, and continued
+// customization of the keymap. Use _keymap instead of _user
+// functions in the keymaps
+__attribute__ ((weak))
+void matrix_init_keymap(void) {}
+
+__attribute__ ((weak))
+void matrix_scan_keymap(void) {}
+
+__attribute__ ((weak))
+bool process_record_keymap(uint16_t keycode, keyrecord_t *record) {
+ return true;
+}
+
+__attribute__ ((weak))
+bool process_record_secrets(uint16_t keycode, keyrecord_t *record) {
+ return true;
+}
+
+__attribute__ ((weak))
+uint32_t layer_state_set_keymap (uint32_t state) {
+ return state;
+}
+
+__attribute__ ((weak))
+void led_set_keymap(uint8_t usb_led) {}
+
+// Runs just one time when the keyboard initializes.
+void matrix_init_user(void) {
+ //ACTION_DEFAULT_LAYER_SET(DVORAK) ;
+}
+
+// check default layerstate to see which layer we are on.
+// if (biton32(layer_state) == _DIABLO) { --- current layer
+// if (biton32(default_layer_state) == _DIABLO) { --- current default layer
+// check for left shift on.
+// if (mods & MOD_BIT(KC_LSFT)) register_code(KC_LSFT);
+
+static void switch_default_layer(uint8_t layer) {
+ default_layer_set(1UL<<layer);
+ clear_keyboard();
+}
+
+// so the keyboard remembers which layer it's in after power disconnect.
+/*
+ uint32_t default_layer_state_set_kb(uint32_t state) {
+ eeconfig_update_default_layer(state);
+ return state;
+ }
+*/
+
+// These are the keys for dvorak on bepo. column one is the keycode and mods for
+// the unshifted key, the second column is the keycode and mods for the shifted key.
+// GR is Good Range. It subtracts SAFE_RANGE from the keycode so we can make a
+// reasnably sized array without difficulties. The macro is for the constant declarations
+// the function is for when we use it.
+const uint8_t key_translations[][2][2] = {
+ [GR(DB_1)] = {{BP_DQOT, MOD_LSFT}, {BP_DCRC, MOD_LSFT}},
+ [GR(DB_2)] = {{BP_LGIL, MOD_LSFT}, {BP_AT, MOD_NONE}},
+ [GR(DB_3)] = {{BP_RGIL, MOD_LSFT}, {BP_DLR, MOD_LSFT}},
+ [GR(DB_4)] = {{BP_LPRN, MOD_LSFT}, {BP_DLR, MOD_NONE}},
+ [GR(DB_5)] = {{BP_RPRN, MOD_LSFT}, {BP_PERC, MOD_NONE}},
+ [GR(DB_6)] = {{BP_AT, MOD_LSFT}, {BP_AT, MOD_BIT(KC_RALT)}},
+ [GR(DB_7)] = {{BP_PLUS, MOD_LSFT}, {BP_P, MOD_BIT(KC_RALT)}},
+ [GR(DB_8)] = {{BP_MINS, MOD_LSFT}, {BP_ASTR, MOD_NONE}},
+ [GR(DB_9)] = {{BP_SLASH, MOD_LSFT}, {BP_LPRN, MOD_NONE}},
+ [GR(DB_0)] = {{BP_ASTR, MOD_LSFT}, {BP_RPRN, MOD_NONE}},
+ [GR(DB_GRV)] = {{BP_PERC, MOD_LSFT}, {BP_K, MOD_BIT(KC_RALT)}},
+ [GR(DB_SCOLON)] = {{BP_COMM, MOD_LSFT}, {BP_DOT, MOD_LSFT}},
+ [GR(DB_SLASH)] = {{BP_SLASH, MOD_NONE}, {BP_APOS, MOD_LSFT}},
+ [GR(DB_BACKSLASH)] = {{BP_AGRV, MOD_BIT(KC_RALT)}, {BP_B, MOD_BIT(KC_RALT)}},
+ [GR(DB_EQL)] = {{BP_EQL, MOD_NONE}, {BP_PLUS, MOD_NONE}},
+ [GR(DB_COMM)] = {{BP_COMMA, MOD_NONE}, {BP_LGIL, MOD_BIT(KC_RALT)}},
+ [GR(DB_DOT)] = {{BP_DOT, MOD_NONE}, {BP_RGIL, MOD_BIT(KC_RALT)}},
+ [GR(DB_QUOT)] = {{BP_APOS, MOD_NONE}, {BP_DQOT, MOD_NONE}},
+ [GR(DB_MINUS)] = {{BP_MINUS, MOD_NONE}, {KC_SPC, MOD_BIT(KC_RALT)}},
+ [GR(DB_LPRN)] = {{BP_LPRN, MOD_NONE}, {BP_LPRN, MOD_BIT(KC_RALT)}},
+ [GR(DB_RPRN)] = {{BP_RPRN, MOD_NONE}, {BP_RPRN, MOD_BIT(KC_RALT)}},
+ [GR(DB_LBRC)] = {{BP_Y, MOD_BIT(KC_RALT)}, {BP_LPRN, MOD_BIT(KC_RALT)}},
+ [GR(DB_RBRC)] = {{BP_X, MOD_BIT(KC_RALT)}, {BP_RPRN, MOD_BIT(KC_RALT)}},
+ // For the symbol layer
+ [GR(DB_HASH)] = {{BP_DLR, MOD_LSFT}, {BP_DLR, MOD_LSFT}},
+ [GR(DB_LCBR)] = {{BP_LPRN, MOD_BIT(KC_RALT)}, {BP_LPRN, MOD_BIT(KC_RALT)}},
+ [GR(DB_RCBR)] = {{BP_LPRN, MOD_BIT(KC_RALT)}, {BP_RPRN, MOD_BIT(KC_RALT)}},
+ [GR(DB_PIPE)] = {{BP_B, MOD_BIT(KC_RALT)}, {BP_B, MOD_BIT(KC_RALT)}},
+ [GR(DB_TILD)] = {{BP_K, MOD_BIT(KC_RALT)}, {BP_K, MOD_BIT(KC_RALT)}},
+ [GR(DB_CIRC)] = {{BP_AT, MOD_BIT(KC_RALT)}, {BP_AT, MOD_BIT(KC_RALT)}},
+ [GR(DB_LESS)] = {{BP_LGIL, MOD_BIT(KC_RALT)}, {BP_LGIL, MOD_BIT(KC_RALT)}},
+ [GR(DB_GRTR)] = {{BP_RGIL, MOD_BIT(KC_RALT)}, {BP_RGIL, MOD_BIT(KC_RALT)}},
+
+
+};
+
+
+uint8_t gr(uint8_t kc){
+ return (kc - SAFE_RANGE);
+}
+// send the right keycode for the right mod.
+// remove the mods we are taking care of,
+// send our keycodes then restore them.
+// all so we can make dvorak keys from bepo keycodes.
+void send_keycode(uint8_t kc){
+ uint8_t tmp_mods = get_mods();
+ bool is_shifted = ( tmp_mods & (MOD_BIT(KC_LSFT)|MOD_BIT(KC_RSFT)) );
+ //uint8_t key[2][2] = key_translations[GR(kc)];
+ // need to turn of the shift if it is on.
+ unregister_mods((MOD_BIT(KC_LSFT)|MOD_BIT(KC_RSFT)));
+ if(is_shifted){
+ register_mods(SHIFTED_MODS(kc));
+ register_code(SHIFTED_KEY(kc));
+ unregister_code(SHIFTED_KEY(kc));
+ unregister_mods(SHIFTED_MODS(kc));
+ } else{
+ register_mods(UNSHIFTED_MODS(kc));
+ register_code(UNSHIFTED_KEY(kc));
+ unregister_code(UNSHIFTED_KEY(kc));
+ unregister_mods(UNSHIFTED_MODS(kc));
+ }
+ clear_mods();
+ register_mods(tmp_mods);
+}
+
+
+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
+#ifdef KEYLOGGER_ENABLE
+xprintf("KL: row: %u, column: %u, pressed: %u\n", record->event.key.col, record->event.key.row, record->event.pressed);
+#endif //KEYLOGGER_ENABLE
+
+// still dont know how to make #&_ And RALT is not ALTGR, That isn't working in the bepo keyboard
+// either. No {} either probably for the same reasons. ALtGR is the key to some of these.
+ switch (keycode) {
+ // Handle the key translations for Dvorak on bepo. It's best if these are the first
+ // enums after SAFE_RANGE.
+ case DB_1:
+ case DB_2:
+ case DB_3:
+ case DB_4:
+ case DB_5:
+ case DB_6:
+ case DB_7:
+ case DB_8:
+ case DB_9:
+ case DB_0:
+ case DB_GRV:
+ case DB_SCOLON:
+ case DB_SLASH:
+ case DB_BACKSLASH:
+ case DB_EQL:
+ case DB_DOT:
+ case DB_COMM:
+ case DB_QUOT:
+ case DB_MINUS:
+ case DB_LPRN:
+ case DB_RPRN:
+ case DB_LBRC:
+ case DB_RBRC:
+ if(record->event.pressed)
+ send_keycode(keycode);
+ unregister_code(keycode);
+ break;
+
+ case KC_QWERTY:
+ if (record->event.pressed) {
+ set_single_persistent_default_layer(QWERTY);
+ }
+ return false;
+ break;
+ case KC_COLEMAK:
+ if (record->event.pressed) {
+ set_single_persistent_default_layer(COLEMAK);
+ }
+ return false;
+ break;
+ case KC_DVORAK:
+ if (record->event.pressed) {
+ set_single_persistent_default_layer(DVORAK);
+ }
+ return false;
+ break;
+ case KC_WORKMAN:
+ if (record->event.pressed) {
+ set_single_persistent_default_layer(WORKMAN);
+ }
+ return false;
+ break;
+
+ case KC_MAKE: // Compiles the firmware, and adds the flash command based on keyboard bootloader
+ if (!record->event.pressed) {
+ SEND_STRING("make " QMK_KEYBOARD ":" QMK_KEYMAP
+#if (defined(BOOTLOADER_DFU) || defined(BOOTLOADER_LUFA_DFU) || defined(BOOTLOADER_QMK_DFU))
+ ":dfu"
+#elif defined(BOOTLOADER_HALFKAY)
+ ":teensy"
+#elif defined(BOOTLOADER_CATERINA)
+ ":avrdude"
+#endif // bootloader options
+ SS_TAP(X_ENTER));
+ }
+ return false;
+ break;
+
+
+ case KC_RESET: // Custom RESET code
+ if (!record->event.pressed) {
+ reset_keyboard();
+ }
+ return false;
+ break;
+
+
+ case EPRM: // Resets EEPROM
+ if (record->event.pressed) {
+ eeconfig_init();
+ default_layer_set(1UL<<eeconfig_read_default_layer());
+ layer_state_set(layer_state);
+ }
+ return false;
+ break;
+ case VRSN: // Prints firmware version
+ if (record->event.pressed) {
+ SEND_STRING(QMK_KEYBOARD "/" QMK_KEYMAP " @ " QMK_VERSION ", Built on: " QMK_BUILDDATE);
+ }
+ return false;
+ break;
+
+ /* Code has been depreciated
+ 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(decoy_secret[keycode - KC_SECRET_1]);
+ }
+ return false;
+ break;
+ */
+
+ // These are a serious of gaming macros.
+ // Only enables for the viterbi, basically,
+ // to save on firmware space, since it's limited.
+#ifdef MACROS_ENABLED
+ case KC_OVERWATCH: // Toggle's if we hit "ENTER" or "BACKSPACE" to input macros
+ if (record->event.pressed) { userspace_config.is_overwatch ^= 1; eeprom_update_byte(EECONFIG_USERSPACE, userspace_config.raw); }
+ return false; break;
+#endif // MACROS_ENABLED
+
+ case KC_CCCV: // One key copy/paste
+ if(record->event.pressed){
+ copy_paste_timer = timer_read();
+ } else {
+ if (timer_elapsed(copy_paste_timer) > TAPPING_TERM) { // Hold, copy
+ register_code(KC_LCTL);
+ tap(KC_C);
+ unregister_code(KC_LCTL);
+#ifdef AUDIO_ENABLE
+ PLAY_SONG(tone_copy);
+#endif
+ } else { // Tap, paste
+ register_code(KC_LCTL);
+ tap(KC_V);
+ unregister_code(KC_LCTL);
+#ifdef AUDIO_ENABLE
+ PLAY_SONG(tone_paste);
+#endif
+ }
+ }
+ return false;
+ break;
+ case CLICKY_TOGGLE:
+#ifdef AUDIO_CLICKY
+ userspace_config.clicky_enable = clicky_enable;
+ eeprom_update_byte(EECONFIG_USERSPACE, userspace_config.raw);
+#endif
+ break;
+#ifdef UNICODE_ENABLE
+ case UC_FLIP: // (╯°□°)╯ ︵ ┻━┻
+ if (record->event.pressed) {
+ register_code(KC_RSFT);
+ tap(KC_9);
+ unregister_code(KC_RSFT);
+ process_unicode((0x256F | QK_UNICODE), record); // Arm
+ process_unicode((0x00B0 | QK_UNICODE), record); // Eye
+ process_unicode((0x25A1 | QK_UNICODE), record); // Mouth
+ process_unicode((0x00B0 | QK_UNICODE), record); // Eye
+ register_code(KC_RSFT);
+ tap(KC_0);
+ unregister_code(KC_RSFT);
+ process_unicode((0x256F | QK_UNICODE), record); // Arm
+ tap(KC_SPC);
+ process_unicode((0x0361 | QK_UNICODE), record); // Flippy
+ tap(KC_SPC);
+ process_unicode((0x253B | QK_UNICODE), record); // Table
+ process_unicode((0x2501 | QK_UNICODE), record); // Table
+ process_unicode((0x253B | QK_UNICODE), record); // Table
+ }
+ return false;
+ break;
+#endif // UNICODE_ENABLE
+
+}
+
+return true;
+ // return process_record_keymap(keycode, record) && process_record_secrets(keycode, record);
+}
+
+void tap_dance_mouse_btns (qk_tap_dance_state_t *state, void *user_data) {
+ switch(state->count){
+ case 1:
+ register_code(KC_BTN1);
+ break;
+ case 2:
+ register_code(KC_BTN2);
+ break;
+ case 3:
+ register_code(KC_BTN3);
+ break;
+ case 4:
+ register_code(KC_BTN4);
+ break;
+ case 5:
+ register_code(KC_BTN5);
+ break;
+ default:
+ break;
+ }
+ reset_tap_dance(state);
+}
+
+// counting on all the qwerty layers to be less than dvorak_on_bepo
+int on_qwerty(){
+ uint8_t deflayer = (biton32(default_layer_state));
+ return (deflayer < DVORAK_ON_BEPO);
+}
+
+void tap_dance_df_bepo_layers_switch (qk_tap_dance_state_t *state, void *user_data) {
+ switch(state->count){
+ case 1:
+ switch_default_layer(DVORAK_ON_BEPO);
+ break;
+ case 2:
+ switch_default_layer(BEPO);
+ break;
+ case 3:
+ layer_invert(LAYERS);
+ break;
+ default:
+ break;
+ }
+ reset_tap_dance(state);
+}
+
+void tap_dance_layer_switch (qk_tap_dance_state_t *state, void *user_data) {
+ switch(state->count){
+ case 1:
+ if(on_qwerty())
+ layer_invert(SYMB);
+ else
+ layer_invert(SYMB_ON_BEPO);
+ break;
+ case 2:
+ layer_invert(MDIA);
+ break;
+ case 3:
+ layer_invert(LAYERS);
+ default:
+ break;
+ }
+ reset_tap_dance(state);
+}
+
+void tap_dance_default_layer_switch (qk_tap_dance_state_t *state, void *user_data) {
+ switch(state->count){
+ case 1:
+ switch_default_layer(DVORAK);
+ break;
+ case 2:
+ switch_default_layer(DVORAK_ON_BEPO);
+ break;
+ case 3:
+ switch_default_layer(BEPO);
+ break;
+ default:
+ break;
+ }
+ reset_tap_dance(state);
+}
+
+// switch the default layer to another qwerty based layer.
+void switch_default_layer_on_qwerty(int count) {
+ switch(count){
+ case 1:
+ switch_default_layer(DVORAK);
+ break;
+ case 2:
+ switch_default_layer(QWERTY);
+ break;
+ case 3:
+ switch_default_layer(COLEMAK);
+ break;
+ case 4:
+ switch_default_layer(WORKMAN);
+ break;
+ case 5:
+ switch_default_layer(NORMAN);
+ break;
+ default:
+ switch_default_layer(DVORAK);
+ break;
+ }
+}
+
+// switch the default layer to another bepo based layer.
+void switch_default_layer_on_bepo(int count) {
+ switch(count){
+ case 1:
+ switch_default_layer(DVORAK_ON_BEPO);
+ break;
+ case 2:
+ switch_default_layer(BEPO);
+ break;
+ default:
+ switch_default_layer(DVORAK_ON_BEPO);
+ break;
+ }
+}
+
+
+// tap to change the default layer. Distinguishes between layers that are based on
+// a qwerty software keyboard and a bepo software keyboard.
+// if shifted, choose layers based on the other software keyboard, otherwise choose only
+// layers that work on the current software keyboard.
+void tap_dance_default_os_layer_switch (qk_tap_dance_state_t *state, void *user_data) {
+ //uint8_t shifted = (get_mods() & MOD_BIT(KC_LSFT|KC_RSFT));
+ bool shifted = ( keyboard_report->mods & (MOD_BIT(KC_LSFT)|MOD_BIT(KC_RSFT)) );
+ int qwerty = on_qwerty();
+
+
+ // shifted, choose between layers on the other software keyboard
+ if(shifted){
+ if (qwerty)
+ switch_default_layer_on_bepo(state->count);
+ else
+ switch_default_layer_on_qwerty(state->count);
+
+ // not shifted, choose between layers on the same software keyboard
+ } else {
+ if (qwerty)
+ switch_default_layer_on_qwerty(state->count);
+ else
+ switch_default_layer_on_bepo(state->count);
+ }
+
+ reset_tap_dance(state);
+}
+
+
+/* Return an integer that corresponds to what kind of tap dance should be executed.
+ *
+ * How to figure out tap dance state: interrupted and pressed.
+ *
+ * Interrupted: If the state of a dance dance is "interrupted", that means that another key has been hit
+ * under the tapping term. This is typically indicitive that you are trying to "tap" the key.
+ *
+ * Pressed: Whether or not the key is still being pressed. If this value is true, that means the tapping term
+ * has ended, but the key is still being pressed down. This generally means the key is being "held".
+ *
+ * One thing that is currenlty not possible with qmk software in regards to tap dance is to mimic the "permissive hold"
+ * feature. In general, advanced tap dances do not work well if they are used with commonly typed letters.
+ * For example "A". Tap dances are best used on non-letter keys that are not hit while typing letters.
+ *
+ * Good places to put an advanced tap dance:
+ * z,q,x,j,k,v,b, any function key, home/end, comma, semi-colon
+ *
+ * Criteria for "good placement" of a tap dance key:
+ * Not a key that is hit frequently in a sentence
+ * Not a key that is used frequently to double tap, for example 'tab' is often double tapped in a terminal, or
+ * in a web form. So 'tab' would be a poor choice for a tap dance.
+ * Letters used in common words as a double. For example 'p' in 'pepper'. If a tap dance function existed on the
+ * letter 'p', the word 'pepper' would be quite frustating to type.
+ *
+ * For the third point, there does exist the 'DOUBLE_SINGLE_TAP', however this is not fully tested
+ *
+ */
+int cur_dance (qk_tap_dance_state_t *state) {
+ if (state->count == 1) {
+ if (state->interrupted || !state->pressed) return SINGLE_TAP;
+ //key has not been interrupted, but they key is still held. Means you want to send a 'HOLD'.
+ else return SINGLE_HOLD;
+ }
+ else if (state->count == 2) {
+ /*
+ * DOUBLE_SINGLE_TAP is to distinguish between typing "pepper", and actually wanting a double tap
+ * action when hitting 'pp'. Suggested use case for this return value is when you want to send two
+ * keystrokes of the key, and not the 'double tap' action/macro.
+ */
+ if (state->interrupted) return DOUBLE_SINGLE_TAP;
+ else if (state->pressed) return DOUBLE_HOLD;
+ else return DOUBLE_TAP;
+ }
+ //Assumes no one is trying to type the same letter three times (at least not quickly).
+ //If your tap dance key is 'KC_W', and you want to type "www." quickly - then you will need to add
+ //an exception here to return a 'TRIPLE_SINGLE_TAP', and define that enum just like 'DOUBLE_SINGLE_TAP'
+ if (state->count == 3) {
+ if (state->interrupted || !state->pressed) return TRIPLE_TAP;
+ else return TRIPLE_HOLD;
+ }
+ else return 8; //magic number. At some point this method will expand to work for more presses
+}
+//instanalize an instance of 'tap' for the 'x' tap dance.
+static tdtap xtap_state = {
+ .is_press_action = true,
+ .state = 0
+};
+/*
+ This so I can have a single key that acts like LGUI in DVORAK no
+ matter which keymap is my current default.
+ It also allows for the
+ shift gui and ctl gui, on the same key, So the same key is Escape,
+ and the mostcommon modifiers in my xmonad control keymap, while also
+ insuring that dvorak is active for the xmonad command key
+ Single tap = ESC
+ tap and hold = dvorak with L_GUI
+ double tap = One shot dvorak layer with LSFT LGUI mods
+ double hold = dvorak with LCTL LGUI
+ double single tap = esc.
+*/
+int get_xmonad_layer(){
+ int qwerty = on_qwerty();
+
+ if (qwerty)
+ return(XMONAD);
+ else
+ return(XMONAD_FR);
+}
+
+
+void x_finished (qk_tap_dance_state_t *state, void *user_data) {
+ int xmonad_layer = get_xmonad_layer();
+ xtap_state.state = cur_dance(state);
+ switch (xtap_state.state) {
+ case SINGLE_TAP:
+ register_code(KC_ESC);
+ break;
+ case SINGLE_HOLD:
+ layer_on(xmonad_layer);
+ set_oneshot_mods (MOD_LGUI);
+ //set_oneshot_layer (DVORAK, ONESHOT_START);
+ break;
+ case DOUBLE_TAP:
+ set_oneshot_mods ((MOD_LCTL | MOD_LGUI));
+ layer_on (xmonad_layer);
+ set_oneshot_layer (xmonad_layer, ONESHOT_START);
+ break;
+ case DOUBLE_HOLD:
+ set_oneshot_mods (MOD_LSFT | MOD_LGUI);
+ if (xmonad_layer != -1)
+ layer_on(xmonad_layer);
+ break;
+ case DOUBLE_SINGLE_TAP:
+ register_code(KC_ESC);
+ unregister_code(KC_ESC);
+ register_code(KC_ESC);
+ //Last case is for fast typing. Assuming your key is `f`:
+ //For example, when typing the word `buffer`, and you want to make sure that you send `ff` and not `Esc`.
+ //In order to type `ff` when typing fast, the next character will have to be hit within the `TAPPING_TERM`, which by default is 200ms.
+ }
+}
+
+void x_reset (qk_tap_dance_state_t *state, void *user_data) {
+ int xmonad_layer = get_xmonad_layer();
+ switch (xtap_state.state) {
+ case SINGLE_TAP:
+ unregister_code(KC_ESC);
+ break;
+ case SINGLE_HOLD:
+ layer_off(xmonad_layer);
+ break;
+ case DOUBLE_TAP:
+ set_oneshot_layer (xmonad_layer, ONESHOT_PRESSED);
+ break;
+ case DOUBLE_HOLD:
+ layer_off(xmonad_layer);
+ break;
+ case DOUBLE_SINGLE_TAP:
+ unregister_code(KC_ESC);
+ }
+ xtap_state.state = 0;
+}
+
+//Tap Dance Definitions
+qk_tap_dance_action_t tap_dance_actions[] = {
+ //Tap once for Esc, twice for Caps Lock
+ [TD_ESC_CAPS] = ACTION_TAP_DANCE_DOUBLE(KC_ESC, KC_CAPS),
+ [TD_TAB_BKTAB] = ACTION_TAP_DANCE_DOUBLE(KC_TAB, LSFT(KC_TAB)),
+ [TD_MDIA_SYMB] = ACTION_TAP_DANCE_FN(tap_dance_layer_switch),
+ [TD_DVORAK_BEPO] = ACTION_TAP_DANCE_FN(tap_dance_df_bepo_layers_switch),
+ [TD_DEF_LAYER_SW] = ACTION_TAP_DANCE_FN(tap_dance_default_layer_switch),
+ [TD_DEF_OS_LAYER_SW] = ACTION_TAP_DANCE_FN(tap_dance_default_os_layer_switch),
+ [TD_HOME_END] = ACTION_TAP_DANCE_DOUBLE(KC_HOME, KC_END),
+ [TD_XMONAD_ESC] = ACTION_TAP_DANCE_FN_ADVANCED(NULL, x_finished, x_reset),
+ [TD_MOUSE_BTNS] = ACTION_TAP_DANCE_FN(tap_dance_mouse_btns)
+};
diff --git a/users/ericgebhart/ericgebhart.h b/users/ericgebhart/ericgebhart.h
new file mode 100644
index 0000000000..6eb11ddfc0
--- /dev/null
+++ b/users/ericgebhart/ericgebhart.h
@@ -0,0 +1,429 @@
+/*
+ Copyright 2018 Eric Gebhart <e.a.gebhart@gmail.com>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+#include QMK_KEYBOARD_H
+
+#ifndef ericgebhart
+#define ericgebhart
+
+#include "quantum.h"
+#include "process_keycode/process_tap_dance.h"
+
+
+void tap(uint16_t keycode);
+bool process_record_secrets(uint16_t keycode, keyrecord_t *record);
+
+
+#define EECONFIG_USERSPACE (uint8_t *)19
+
+typedef union {
+ uint8_t raw;
+ struct {
+ bool clicky_enable :1;
+ bool rgb_layer_change :1;
+ bool is_overwatch :1;
+ bool nuke_switch :1;
+ };
+} userspace_config_t;
+
+#define ___ KC_TRNS
+#define XXX KC_NO
+
+// The most portable copy/paste keys (windows (mostly), linux, and some terminal emulators).
+#define MK_CUT LSFT(KC_DEL) // shift + delete
+#define MK_COPY LCTL(KC_INS) // ctrl + insert
+#define MK_PASTE LSFT(KC_INS) // shift + insert
+
+
+#define DVORAK 0 // dvorak layout (default)
+#define QWERTY 1
+#define COLEMAK 2
+#define WORKMAN 3
+#define NORMAN 4
+// bepo layers
+#define DVORAK_ON_BEPO 6 // dvorak layout (default)
+#define BEPO 7 // Bepo
+// non-default layers
+#define SYMB 8 // symbols and numbers
+#define SYMB_ON_BEPO 9 // symbols and numbers
+#define MDIA 10 // mouse knd media eys
+#define LAYERS 11 // layers and right mousekeys.
+#define XMONAD 12 // xmonad ie. dvorak.
+#define XMONAD_FR 13 // xmonad ie. dvorak.
+
+
+// for the creation of dvorak keys on an Bepo keyboard at the OS layer.
+
+// so we can create an array of reasonable size
+// for our translation keys. We have to create a
+// good range of numbers
+#define GR(x) (x-SAFE_RANGE)
+
+uint8_t gr(uint8_t);
+void send_keycode(uint8_t);
+
+#define MOD_NONE 0x00
+
+// indexs for the keycode translation table.
+#define UNSHIFTED_KEY(key) key_translations[gr(key)][0][0]
+#define UNSHIFTED_MODS(key) key_translations[gr(key)][0][1]
+#define SHIFTED_KEY(key) key_translations[gr(key)][1][0]
+#define SHIFTED_MODS(key) key_translations[gr(key)][1][1]
+
+
+enum userspace_custom_keycodes {
+ // keep the keycodes using the send_key function close to SAFE_RANGE
+ // so the array of keycodes remains a reasonbale size.
+ DB_1 = SAFE_RANGE, // can always be here
+ DB_2,
+ DB_3,
+ DB_4,
+ DB_5,
+ DB_6,
+ DB_7,
+ DB_8,
+ DB_9,
+ DB_0,
+ DB_GRV,
+ DB_SCOLON,
+ DB_SLASH,
+ DB_BACKSLASH,
+ DB_EQL,
+ DB_DOT,
+ DB_COMM,
+ DB_QUOT,
+ DB_MINUS,
+ DB_RPRN,
+ DB_LPRN,
+ DB_RBRC,
+ DB_LBRC,
+ // for symbols layer
+ DB_HASH,
+ DB_LCBR,
+ DB_RCBR,
+ DB_PIPE,
+ DB_TILD,
+ DB_CIRC,
+ DB_LESS,
+ DB_GRTR,
+ // End of dvorak on bepo translation keys.
+
+ EPRM,
+ VRSN,
+ KC_DVORAK_ON_BEPO,
+ KC_BEPO,
+ KC_NORMAN,
+ KC_QWERTY,
+ KC_COLEMAK,
+ KC_DVORAK,
+ KC_WORKMAN,
+ KC_MAKE,
+ KC_RESET,
+ KC_RGB_T,
+ KC_SECRET_1,
+ KC_SECRET_2,
+ KC_SECRET_3,
+ KC_SECRET_4,
+ KC_SECRET_5,
+ KC_CCCV
+};
+
+#define SFTGUI_T(kc) { MT(MOD_LGUI | MOD_LSFT, kc) }
+#define SFT_GUI_ESC MT(MOD_LSFT | MOD_LGUI, KC_PGDN) // shift LGUI or Escape.
+#define ALT_ENT ALT_T(KC_ENT) // Alt or enter
+#define CTL_SPC CTL_T(KC_SPC) // ctrl or space
+#define CTL_BSPC CTL_T(KC_BSPC) // ctrl or backspace
+#define ALT_DEL ALT_T(KC_DEL) // Alt or delete
+#define GUI_ESC GUI_T(KC_ESC) // Gui or escape
+#define ALGR_SYMB ALGR_T(TG(SYMB)) // Alt gre or toggle symbol layer
+
+#define KC_SFT_T_U SFT_T(KC_U)
+#define KC_SFT_T_H SFT_T(KC_H)
+#define KC_LT_SYMB_I LT(SYMB, KC_I)
+#define KC_LT_SYMB_D LT(SYMB, KC_D)
+
+// for dvorak on bepo
+#define BP_SFT_T_U SFT_T(BP_U)
+#define BP_SFT_T_H SFT_T(BP_H)
+#define BP_LT_SYMB_D LT(SYMB, BP_D)
+
+
+// for bepo on bepo
+#define BP_SFT_T_T SFT_T(BP_T)
+#define BP_LT_SYMB_C LT(SYMB_ON_BEPO, BP_C)
+#define BP_LT_SYMB_I LT(SYMB_ON_BEPO, BP_I)
+#define BP_SFT_T_E SFT_T(BP_E)
+#define BP_SFT_T_ECRC SFT_T(BP_ECRC)
+#define BP_SFT_T_CCED SFT_T(BP_CCED)
+#define BP_LT_SYMB_COMM LT(SYMB,BP_COMM)
+
+// OSM keycodes, to keep things clean and easy to change
+#define KC_MLSF OSM(MOD_LSFT)
+#define KC_MRSF OSM(MOD_RSFT)
+#define OS_LGUI OSM(MOD_LGUI)
+#define OS_RGUI OSM(MOD_RGUI)
+#define OS_LSFT OSM(MOD_LSFT)
+#define OS_RSFT OSM(MOD_RSFT)
+#define OS_LCTL OSM(MOD_LCTL)
+#define OS_RCTL OSM(MOD_RCTL)
+#define OS_LALT OSM(MOD_LALT)
+#define OS_RALT OSM(MOD_RALT)
+#define ALT_APP ALT_T(KC_APP)
+
+#define MG_NKRO MAGIC_TOGGLE_NKRO
+
+
+//// TAP DANCE
+
+typedef struct {
+ bool is_press_action;
+ int state;
+} tdtap;
+
+enum {
+ SINGLE_TAP = 1,
+ SINGLE_HOLD = 2,
+ DOUBLE_TAP = 3,
+ DOUBLE_HOLD = 4,
+ DOUBLE_SINGLE_TAP = 5, //send two single taps
+ TRIPLE_TAP = 6,
+ TRIPLE_HOLD = 7
+ };
+
+ //Tap Dance Declarations
+ enum {
+ TD_ESC_CAPS = 0,
+ TD_TAB_BKTAB = 1,
+ TD_MDIA_SYMB = 2,
+ TD_HOME_END = 3,
+ TD_XMONAD_ESC = 4,
+ TD_DEF_LAYER_SW = 5,
+ TD_DEF_OS_LAYER_SW = 6,
+ TD_MOUSE_BTNS = 7,
+ TD_DVORAK_BEPO = 8
+ };
+
+
+// Tap dance
+#define TAB_BKTAB TD(TD_TAB_BKTAB) // Tab or backtab tapdance.
+#define MDIA_SYMB TD(TD_MDIA_SYMB) // MDIA or Symb layer tapdance toggle.
+#define DEF_LAYER_SW TD(TD_DEF_LAYER_SW) // dvorak, dvorak_on_bepo, bepo default layer
+#define DEF_OS_LAYER_SW TD(TD_DEF_OS_LAYER_SW) // dvorak, dvorak_on_bepo, bepo default layer
+#define HOME_END TD(TD_HOME_END) // home or end tapdance.
+#define XMONAD_ESC TD(TD_XMONAD_ESC) // Escape, dvorak, media or symb. - tap and hold tap dance. 1-4
+#define DVORAK_ET_BEPO TD(TD_DVORAK_BEPO) // Escape, dvorak, media or symb. - tap and hold tap dance. 1-4
+#define TDMOUSE_BTNS TD(TD_MOUSE_BTNS) // hmmm. 1-5
+
+
+int on_qwerty(void);
+int get_xmonad_layer(void);
+int cur_dance (qk_tap_dance_state_t *state);
+
+//for the x tap dance. Put it here so it can be used in any keymap
+void x_finished (qk_tap_dance_state_t *state, void *user_data);
+void x_reset (qk_tap_dance_state_t *state, void *user_data);
+
+
+// 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 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.
+
+// 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(...) LAYOUT(__VA_ARGS__)
+#define LAYOUT_wrapper(...) LAYOUT(__VA_ARGS__)
+
+//Dvorak on a qwerty software layer in the OS
+#define ___DVORAK_L1___ KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y
+#define ___DVORAK_L2___ KC_A, KC_O, KC_E, KC_SFT_T_U, KC_LT_SYMB_I
+#define ___DVORAK_L3___ KC_SCLN, KC_Q, KC_J, KC_K, KC_X
+
+#define ___DVORAK_R1___ KC_F, KC_G, KC_C, KC_R, KC_L
+#define ___DVORAK_R2___ KC_LT_SYMB_D, KC_SFT_T_H, KC_T, KC_N, KC_S
+#define ___DVORAK_R3___ KC_B, KC_M, KC_W, KC_V, KC_Z
+
+
+// Dvorak on fr-bepo software layer in the OS.
+// for dvorak and all the other qwerty like keyboards on bepo
+#define ___NUMBER_BEPO_L___ DB_1, DB_2, DB_3, DB_4, DB_5
+#define ___NUMBER_BEPO_R___ DB_6, DB_7, DB_8, DB_9, DB_0
+
+#define ___DVORAK_FR_L1___ DB_QUOT, DB_COMM, DB_DOT, BP_P, BP_Y
+#define ___DVORAK_FR_L2___ BP_A, BP_O, BP_E, BP_SFT_T_U, BP_LT_SYMB_I
+#define ___DVORAK_FR_L3___ DB_SCOLON, BP_Q, BP_J, BP_K, BP_X
+
+#define ___DVORAK_FR_R1___ BP_F, BP_G, BP_C, BP_R, BP_L
+#define ___DVORAK_FR_R2___ BP_LT_SYMB_D, BP_SFT_T_H, BP_T, BP_N, BP_S
+#define ___DVORAK_FR_R3___ BP_B, BP_M, BP_W, BP_V, BP_Z
+
+
+// Bepo on fr-bepo software layer
+// for bepo on bepo
+#define ___SYMBOL_BEPO_L___ /* BP_DLR */ BP_DQOT, BP_LGIL, BP_RGIL, BP_LPRN, BP_RPRN
+#define ___SYMBOL_BEPO_R___ BP_AT, BP_PLUS, BP_MINS, BP_SLASH, BP_ASTR /* BP_EQL, BP_PERC */
+
+#define ___BEPO_FR_L1___ BP_B, BP_ECUT, BP_P, BP_O, BP_EGRV
+#define ___BEPO_FR_L2___ BP_A, BP_U, BP_I, BP_SFT_T_E, BP_LT_SYMB_COMM
+#define ___BEPO_FR_L3___ /*BP_ECRC*/ BP_AGRV, BP_Y, BP_X, BP_DOT, BP_K
+
+#define ___BEPO_FR_R1___ /* BP_DCRC*/ BP_V, BP_D, BP_L, BP_J, BP_Z //, BP_W
+#define ___BEPO_FR_R2___ /* BP_C */ BP_SFT_T_T, BP_S, BP_R, BP_N, BP_M //BP_CCED
+#define ___BEPO_FR_R3___ BP_APOS, BP_Q, BP_G, BP_H, BP_F
+
+// the bottom rows for keyboards on bepo.
+#define ___ERGODOX_BOTTOM_RIGHT_FR___ KC_UP, KC_DOWN, DB_BACKSLASH, LCTL(BP_V), LCTL(BP_C)
+#define ___ERGODOX_BOTTOM_LEFT_FR___ LCTL(BP_C), LCTL(BP_V), KC_INS, KC_LEFT, KC_RIGHT
+
+// Since we have 7 default layouts (QWERTY, DVORAK, COLEMAK and WORKMAN, NORMAN,
+// 2 of them based on a Bepo software keyboard, --- DVORAK_ON_BEPO and BEPO),
+// 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___ LCTL(KC_C), LCTL(KC_V), KC_INS, KC_LEFT, KC_RIGHT
+#define ___ERGODOX_BOTTOM_RIGHT___ KC_UP, KC_DOWN, KC_BSLASH, LCTL(KC_V), LCTL(KC_C)
+
+#define ___ERGODOX_THUMB_LEFT___ \
+ KC_RALT, ALGR_SYMB, \
+ HOME_END, \
+ CTL_BSPC, ALT_DEL, XMONAD_ESC
+
+#define ___ERGODOX_THUMB_RIGHT___ \
+ ALGR_SYMB, TD_MOUSE_BTNS, \
+ KC_PGUP, \
+ KC_PGDN, ALT_ENT, CTL_SPC
+
+#define ___ERGODOX_TRANS_THUMBS___ \
+ ___, ___, \
+ ___, \
+ ___, ___, ___ \
+
+#define ___ERGODOX_TRANS_BOTTOM___ \
+ ___,___,___,___,___
+
+#define ___ERGODOX_TRANS_6_ROW___ \
+ ___,___,___,___,___,___
+
+
+
+// Qwerty based layers that I don't really use.
+#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
+#define ___QWERTY_L3___ KC_Z, KC_X, KC_C, KC_V, KC_B
+
+#define ___QWERTY_R1___ KC_Y, KC_U, KC_I, KC_O, KC_P
+#define ___QWERTY_R2___ KC_H, KC_J, KC_K, KC_L, KC_SCLN
+#define ___QWERTY_R3___ KC_N, KC_M, KC_COMM, KC_DOT, KC_SLASH
+
+
+#define ___COLEMAK_L1___ KC_Q, KC_W, KC_F, KC_P, KC_G
+#define ___COLEMAK_L2___ KC_A, KC_R, KC_S, KC_T, KC_D
+#define ___COLEMAK_L3___ KC_Z, KC_X, KC_C, KC_V, KC_B
+
+#define ___COLEMAK_R1___ KC_J, KC_L, KC_U, KC_Y, KC_SCLN
+#define ___COLEMAK_R2___ KC_H, KC_N, KC_E, KC_I, KC_O
+#define ___COLEMAK_R3___ KC_K, KC_M, KC_COMM, KC_DOT, 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_M, KC_N, KC_E, KC_I, KC_O
+#define ___COLEMAK_MOD_DH_R3___ KC_K, KC_H, KC_COMM, KC_DOT, KC_SLASH
+
+
+#define ___WORKMAN_L1___ KC_Q, KC_D, KC_R, KC_W, KC_B
+#define ___WORKMAN_L2___ KC_A, KC_S, KC_H, KC_T, KC_G
+#define ___WORKMAN_L3___ KC_Z, KC_X, KC_M, KC_C, KC_V
+
+#define ___WORKMAN_R1___ KC_J, KC_F, KC_U, KC_P, KC_SCLN
+#define ___WORKMAN_R2___ KC_Y, KC_N, KC_E, KC_O, KC_I
+#define ___WORKMAN_R3___ KC_K, KC_L, KC_COMM, KC_DOT, KC_SLASH
+
+
+#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___ 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_Y, KC_N, KC_I, KC_O, KC_U
+#define ___NORMAN_R3___ KC_P, KC_M, KC_COMM, KC_DOT, KC_SLASH
+
+
+// For the top rows. Numbers for most things, symbols for Bepo.
+
+// for everything on qwerty.
+#define ___NUMBER_L___ KC_1, KC_2, KC_3, KC_4, KC_5
+#define ___NUMBER_R___ KC_6, KC_7, KC_8, KC_9, KC_0
+
+// function key rows, works for everyone.
+#define ___FUNC_L___ KC_F1, KC_F2, KC_F3, KC_F4, KC_F5
+#define ___FUNC_R___ KC_F6, KC_F7, KC_F8, KC_F9, KC_F10
+
+
+// Rows for the auxillary layers.
+
+// The symbol layer is for qwerty. I need another one for Bepo...
+
+// the KC_P? codes don't work for me. I don't use those shifted values anyway.
+#define ___KEYPAD_1___ KC_7, KC_8, KC_9, KC_PSLS
+#define ___KEYPAD_2___ KC_4, KC_5, KC_6, KC_PAST
+#define ___KEYPAD_3___ KC_1, KC_2, KC_3, KC_PMNS
+#define ___KEYPAD_4___ KC_0, KC_DOT, KC_PEQL, KC_PPLS
+
+#define ___KEYPAD_1_BP___ DB_7, DB_8, DB_9, BP_SLASH
+#define ___KEYPAD_2_BP___ DB_4, DB_5, DB_6, BP_ASTR
+#define ___KEYPAD_3_BP___ DB_1, DB_2, DB_3, DB_MINUS
+#define ___KEYPAD_4_BP___ DB_0, DB_DOT, DB_EQL, BP_PLUS
+
+#define ___SYMBOLS_1___ KC_EXLM, KC_AT, KC_LCBR, KC_RCBR, KC_PIPE
+#define ___SYMBOLS_2___ KC_HASH, KC_DLR, KC_LPRN, KC_RPRN, KC_GRV
+#define ___SYMBOLS_3___ KC_PERC, KC_CIRC, KC_LBRC, KC_RBRC, KC_TILD
+
+#define ___SYMBOLS_1_BP___ KC_EXLM, BP_AT, DB_LCBR, DB_RCBR, DB_PIPE
+#define ___SYMBOLS_2_BP___ DB_HASH, BP_DLR, DB_LPRN, DB_RPRN, DB_GRV
+#define ___SYMBOLS_3_BP___ BP_PERC, DB_CIRC, DB_LBRC, DB_RBRC, DB_TILD
+
+#define ___MOUSE_LDUR___ KC_MS_L, KC_MS_D, KC_MS_U, KC_MS_R
+#define ___MWHEEL_LDUR___ KC_WH_L, KC_WH_D, KC_WH_U, KC_WH_R
+#define ___MOUSE_BTNS_R___ KC_BTN1, KC_BTN2, KC_BTN3, KC_BTN4, KC_BTN5
+#define ___MOUSE_BTNS_L___ KC_BTN5, KC_BTN4, KC_BTN3, KC_BTN2, KC_BTN1
+#define ___MOUSE_ACCL_012___ KC_ACL0, KC_ACL1, KC_ACL2
+
+#define ___MUTE_PLAY_STOP___ KC_MUTE, KC_MPLY, KC_MSTP
+#define ___VI_ARROWS___ KC_LEFT, KC_DOWN, KC_UP, KC_RIGHT
+
+#define ___LAYERS_L1___ DF(BEPO), DF(DVORAK_ON_BEPO)
+#define ___LAYERS_L2___ DF(COLEMAK), DF(DVORAK)
+#define ___LAYERS_L3___ DF(QWERTY), DF(NORMAN), DF(WORKMAN)
+#define ___LAYERS_L4___ TO(MDIA), TO(SYMB_ON_BEPO), TO(SYMB)
+
+
+#endif
diff --git a/users/ericgebhart/flash-ergodox b/users/ericgebhart/flash-ergodox
new file mode 100755
index 0000000000..945b2b605a
--- /dev/null
+++ b/users/ericgebhart/flash-ergodox
@@ -0,0 +1 @@
+teensy-loader-cli -mmcu=atmega32u4 -w $1
diff --git a/users/ericgebhart/readme.md b/users/ericgebhart/readme.md
new file mode 100644
index 0000000000..cd57735c2c
--- /dev/null
+++ b/users/ericgebhart/readme.md
@@ -0,0 +1,124 @@
+Overview
+========
+
+This is my personal userspace. Most of my code exists here. I only have one keymap, and that
+is for an ergodox_ez. There are a lot of layers, 7 of them are default layers. I primarily use
+dvorak and Bepo. I've been using emacs in vi mode for over 23 years. I also us Xmonad as my
+window manager, additionally I've been using a Kinesis advantage keyboard in dvorak for over 20
+years. All of those things tend to color the layouts I have.
+
+The Bepo layer needs some love. It is true to the layout at Bepo.fr, but I find it a little
+cumbersome, and I miss some of my favorite keys.
+
+There are 2 dvorak layers, one for a qwerty OS keyboard, and one for a Bepo OS keyboard.
+There is a symbol/keypad layer for bepo and qwerty. And of course there is a mouse/media layer.
+There are 2 Xmonad layers one for qwerty and one for Bepo. Layer selection happens automatically
+based on your current default layer. I use 2 tap dance keys for layer selection.
+
+There are also Qwerty, Colemak, Workman and Norman layers for qwerty.
+
+
+Keyboard Layout Templates
+-------------------------
+
+I borrowed the idea for the keyboard defines and some of the definitions from @drashna.
+I think it is an awesome idea, It makes consistency between layout definitions so much easier.
+@drashna had this to say about it.
+
+
+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.
+
+Credit goes to @jola5 for first implementing this awesome idea.
+
+
+Custom Keycodes
+---------------
+
+Keycodes are defined in the ericgebhart.h file and need to be included in the keymap.c files, so that they can be used there. The keymap.c file has very little in it, the most important thing to see there are the keys that are at the ends of each row, ie. the 1st and last key on each row is defined there.
+Everything else is in ericgebhart.h.
+
+Layer Indication
+----------------
+
+The ergodox_ez only has 3 leds, layer indication is pretty lame.
+Currently the first led lights up if the default layer is not qwerty. The symbol and media layers get
+the other 2 leds, and all the leds light up if you are on the "layers" layer.
+I hope I can figure out how to make it better, but I just don't see a way with 3 leds and 11 layers.
+
+
+BEPO vs Qwerty Layers
+---------------------
+
+There are 7 base layers. Dvorak, qwerty, Colemak, Workman, and Norman work on a Qwerty software layer on the OS. Dvorak_on_bepo and Bepo both work on a Bepo software layer on the os.
+Dvorak on qwerty is the default. There is a function in ericgebhart.c which will allow the keyboard
+to persist it's default layer through power down. It is currently commented out.
+
+I don't actually use Qwerty, but it seemed like I should have it,
+@drashna had it along with Colemak, Workman and Norman so I added them
+to my existing dvorak and bepo definitions.
+
+There are two tap dance functions that allow switching the default layers
+and the overlay layers.
+
+The default layers switch according to the current OS keyboard of the current Default layer.
+Shifting the key, causes the selection to use the other OS keyboard selections. ie,
+if you are on qwerty, you get dvorak, qwerty, colemak, workman and norman. If you shift it you get
+dvorak on bepo and bepo. If you are not on qwerty the unshifted taps get dvorak and bepo on bepo.
+
+The other tap dance for layers is for the symbol, mouse and layers layers. The layers layer is just a
+safety layer, knowing I can get to if I screw something up...
+
+XMonad
+---------------------
+
+Additionally there is an advanced tap dance called XMONAD_ESC. One tap is Escape, tap and hold is
+LGUI with the proper XMONAD layer, it is essentially dvorak, for the
+given OS layer. 2 taps is Shift lgui with xmonad, and 2 taps and hold
+is Control LGUI with Xmonad. This allows for the finger patterns for
+Xmonad to remain the same regarless of the keyboard in use. The hold
+versions allow for secondary menu selection in Xmonad, the 2 tap function
+must be for a key that is in the top level keymap of Xmonad. This is how
+many people use xmonad so it's not a real problem. There are plenty of
+keys combinations to choose from with these choices. The function can
+be expanded to 3 taps and 3 tap and hold, and on and on....
+
+I have a few other special keys, for momentary symbols or shift on the home row of each hand.
+
+Also, after using a kinesis for many years I'm very accustomed to the
+space, enter, backspace and delete keys on the thumbs. I've added control
+and alt as a secondary function. These are also the Control and Alt keys
+if held down.
+
+Tap Dance
+--------------------
+
+Additionally there are other tap dance functions, tab-backtab, home-end as well as I few I'm not actually using.
+
+Building and flashing
+-----------------------
+
+```make ergodox_z:ericgebhart``` will compile the code.
+
+I use the teensy-loader cli so that's all I know. There is a script here called flash_ergodox
+
+Use it like this,
+
+```flash-ergodox <path to your hex file>```
+
+then use a paperclip to push the reset button on your keyboard.
+
+Switching the OS keyboard
+-------------------------
+
+This varies from system to system. I use Arch Linux, so I use ```setxkbmap```.
+I've included a helper script which makes it easy to switch between EN and FR Bepo,
+called switch-kbd.
+
diff --git a/users/ericgebhart/rules.mk b/users/ericgebhart/rules.mk
new file mode 100755
index 0000000000..2572d21118
--- /dev/null
+++ b/users/ericgebhart/rules.mk
@@ -0,0 +1,18 @@
+USER_NAME := ericgebhart
+SRC += ericgebhart.c
+
+MOUSEKEY_ENABLE = yes # Mouse keys
+EXTRAKEY_ENABLE = yes # Audio control and System control
+COMMAND_ENABLE = yes # Commands for debug and configuration
+NKRO_ENABLE = yes # USB Nkey Rollover - for issues, see github.com/tmk/tmk_keyboard/wiki/FAQ#nkro-doesnt-work
+SWAP_HANDS_ENABLE= yes # Allow swapping hands of keyboard
+KEY_LOCK_ENABLE = yes # Enable the KC_LOCK key
+TAP_DANCE_ENABLE = yes # Enable the tap dance feature.
+CONSOLE_ENABLE = yes # Console for debug
+
+BOOTMAGIC_ENABLE = no # Virtual DIP switch configuration
+UNICODE_ENABLE = no
+SLEEP_LED_ENABLE = no
+API_SYSEX_ENABLE = no
+RGBLIGHT_ENABLE = no
+RGBLIGHT_ANIMATION = no
diff --git a/users/ericgebhart/switch-kbd b/users/ericgebhart/switch-kbd
new file mode 100755
index 0000000000..4401967a0f
--- /dev/null
+++ b/users/ericgebhart/switch-kbd
@@ -0,0 +1,74 @@
+#!/usr/bin/env zsh
+
+# Switch the keyboard to en-us by default, bepo, or en-dvorak.
+
+help(){
+ print 'switch-kbd - helper for setxkbmap'
+ print ' '
+ print 'Change the keyboard to en-us, fr-bepo, or en-dvorak.'
+ print 'Uses setxkbmap, so the change only affects the current'
+ print 'session. This mainly to avoid using a toggle key.'
+ print ' '
+ print ' -b Bepo'
+ print ' -d Dvorak'
+ print ' -n do not execute'
+ print ' -h help text.'
+ print ' '
+ print ' The default is to set the keyboard to en-us.'
+ exit
+}
+
+layout="-layout us"
+variant=""
+let "execute = 1"
+let "verose = 0"
+
+# $opt will hold the current option
+local opt
+while getopts bdnvh opt; do
+ # loop continues till options finished
+ # see which pattern $opt matches...
+ case $opt in
+ (b)
+ layout="-layout fr"
+ variant="-variant bepo"
+ ;;
+
+ (d)
+ layout="-layout en"
+ variant="-variant dvorak"
+ ;;
+ (n)
+ let "execute = 0"
+ ;;
+ (v)
+ let "verbose = 1"
+ ;;
+ (h)
+ help
+ ;;
+ # matches a question mark
+ # (and nothing else, see text)
+ (\?)
+ print "Bad option:" $*
+ print " "
+ help
+ return 1
+ ;;
+ esac
+done
+(( OPTIND > 1 )) && shift $(( OPTIND - 1 ))
+##print Remaining arguments are: $*
+
+mycommand='setxkbmap '${layout}' '${variant}
+
+if [[ ( $verbose -ne 0 ) ]]; then;
+ print "setxkbmap Command:" $mycommand
+fi
+
+if [[ ( $execute -ne 0 ) ]]
+then;
+ eval $mycommand
+else;
+ print "did not execute"
+fi