I finally got around to playing with the ErgoDox port of the TMK firmware. I'm still working on finalizing my own layout, but I've created a Dvorak layout based on Ben Blazak's dvorak-kinesis-mod layout.
I've also added the ability to hit both shift keys to toggle capslock (most of the code starts at line 363), and it's part of the keymap_dvorak.h below. Once I figure out github, I'll send cub-uanic a pull request:
static const uint8_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
// ........................................................................
// Layer0: default, dvorak in keyboard, qwerty in OS;
// Based on Ben Blazak's dvorak-kinesis-mod layout.
//
// left hand
// ,--------------------------------------------------.
// | = + | 1 ! | 2 @ | 3 # | 4 $ | 5 % | Esc |
// |--------+------+------+------+------+-------------|
// | Tab | ' " | , < | . > | p P | y Y | +L2 |
// |--------+------+------+------+------+------| |
// | CapsLk | a A | o O | e E | u U | i I |------|
// |--------+------+------+------+------+------| ~L2 |
// |LSft2Cap| ; : | q Q | j J | k K | x X | |
// `--------+------+------+------+------+-------------'
// | LGui | ` ~ | \ | | Left | Rght |
// `----------------------------------'
// ,-------------.
// | LCtl | LAlt |
// ,------|------|------|
// | | | Home |
// | BkSp | Del |------|
// | | | End |
// `--------------------'
//
// right hand
// ,--------------------------------------------------.
// | +L1 | 6 ^ | 7 & | 8 * | 9 ( | 0 ) | - _ |
// |------+------+------+------+------+------+--------|
// | +L2 | f F | g G | c C | r R | l L | / ? |
// | |------+------+------+------+------+--------|
// |------| d D | h H | t T | n N | s S | \ | |
// | ~L2 |------+------+------+------+------+--------|
// | | b B | m M | w W | v V | z Z |RSft2Cap|
// `-------------+------+------+------+------+--------'
// | Up | Down | [ { | ] } | RGui |
// `----------------------------------'
// ,-------------.
// | RAlt | RCtl |
// |------+------+------.
// | PgUp | | |
// |------| Entr | Spce |
// | PgDn | | |
// `--------------------'
//
KEYMAP( // Layer0: default, dvorak in keyboard, qwerty in OS;
// Based on Ben Blazak's dvorak-kinesis-mod layout.
// left hand
EQL, 1, 2, 3, 4, 5, ESC,
TAB, QUOT, COMM, DOT, P, Y, FN2,
CAPS, A, O, E, U, I,
FN29, SCLN, Q, J, K, X, FN4,
LGUI, GRV, BSLS, LEFT, RGHT,
LCTL, LALT,
HOME,
BSPC, DEL, END,
// right hand
FN1, 6, 7, 8, 9, 0, MINS,
FN2, F, G, C, R, L, SLSH,
D, H, T, N, S, BSLS,
FN4, B, M, W, V, Z, FN30,
UP, DOWN, LBRC, RBRC, RGUI,
RALT, RCTL,
PGUP,
PGDN, ENT, SPC
),
// ........................................................................
// Layer1: number pad;
// Based on Ben Blazak's dvorak-kinesis-mod layout.
//
// left hand
// ,--------------------------------------------------.
// | = + | 1 ! | 2 @ | 3 # | 4 $ | 5 % | Esc |
// |--------+------+------+------+------+-------------|
// | Tab | ' " | , < | . > | p P | y Y | +L2 |
// |--------+------+------+------+------+------| |
// | | a A | o O | e E | u U | i I |------|
// |--------+------+------+------+------+------| ~L2 |
// |LSft2Cap| ; : | q Q | j J | k K | x X | |
// `--------+------+------+------+------+-------------'
// | LGui | Ins | \ | | Left | Rght |
// `----------------------------------'
// ,-------------.
// | LCtl | LAlt |
// ,------|------|------|
// | | | Home |
// | BkSp | Del |------|
// | | | End |
// `--------------------'
//
// right hand
// ,--------------------------------------------------.
// | -L1 | | NmLk | Kp / | Kp * | Kp - | ScrLk |
// |------+------+------+------+------+------+--------|
// | +L2 | | Kp 7 | Kp 8 | Kp 9 | Kp + | PrtScn |
// | |------+------+------+------+------+--------|
// |------| | Kp 4 | Kp 5 | Kp 6 | Kp + | Pause |
// | ~L2 |------+------+------+------+------+--------|
// | | | Kp 1 | Kp 2 | Kp 3 | KEnt |RSft2Cap|
// `-------------+------+------+------+------+--------'
// | Kp 0 | Kp 0 | Kp . | KEnt | |
// `----------------------------------'
// ,-------------.
// | RAlt | RCtl |
// |------+------+------.
// | PgUp | | |
// |------| Entr | Spce |
// | PgDn | | |
// `--------------------'
//
KEYMAP( // Layer1: number pad;
// Based on Ben Blazak's dvorak-kinesis-mod layout.
// left hand
TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS,
TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS,
NO, TRNS, TRNS, TRNS, TRNS, TRNS,
TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS,
TRNS, INS, TRNS, TRNS, TRNS,
TRNS, TRNS,
TRNS,
TRNS, TRNS, TRNS,
// right hand
TRNS, NO, NLCK, PSLS, PAST, PMNS, SLCK,
TRNS, NO, P7, P8, P9, PPLS, PSCR,
NO, P4, P5, P6, PPLS, PAUS,
TRNS, NO, P1, P2, P3, PENT, TRNS,
P0, P0, PDOT, PENT, NO,
TRNS, TRNS,
TRNS,
TRNS, TRNS, TRNS
),
// ........................................................................
// Layer2: symbols and function keys;
// Based on Ben Blazak's dvorak-kinesis-mod layout.
//
// left hand
// ,--------------------------------------------------.
// | = + | F1 | F2 | F3 | F4 | F5 | F11 |
// |--------+------+------+------+------+-------------|
// | Tab | { | } | [ { | ] } | | -L2 |
// |--------+------+------+------+------+------| |
// | CapsLk | ; : | / ? | - _ | 0 ) | : |------|
// |--------+------+------+------+------+------| ~L3 |
// |LSft2Cap| 6 ^ | 7 & | 8 * | 9 ( | + | |
// `--------+------+------+------+------+-------------'
// | LGui | ` ~ | \ | | Left | Rght |
// `----------------------------------'
// ,-------------.
// | LCtl | LAlt |
// ,------|------|------|
// | | | Home |
// | BkSp | Del |------|
// | | | End |
// `--------------------'
//
// right hand
// ,--------------------------------------------------.
// | F12 | F6 | F7 | F8 | F9 | F0 | Power |
// |------+------+------+------+------+------+--------|
// | +L2 | | _ | < | > | $ | Vol Up |
// | |------+------+------+------+------+--------|
// |------| \ | | 1 ! | ( | ) | = + | Vol Dn |
// | ~L3 |------+------+------+------+------+--------|
// | | * | 2 @ | 3 # | 4 $ | 5 % | Mute |
// `-------------+------+------+------+------+--------'
// | Up | Down | [ { | ] } | RGui |
// `----------------------------------'
// ,-------------.
// | RAlt | RCtl |
// |------+------+------.
// | PgUp | | |
// |------| Entr | Spce |
// | PgDn | | |
// `--------------------'
//
KEYMAP( // Layer2: symbols and function keys;
// Based on Ben Blazak's dvorak-kinesis-mod layout.
// left hand
TRNS, F1, F2, F3, F4, F5, F11,
TRNS, FN5, FN6, LBRC, RBRC, NO, TRNS,
TRNS, SCLN, SLSH, MINS, 0, FN7,
TRNS, 6, 7, 8, 9, FN8, FN3,
TRNS, TRNS, TRNS, TRNS, TRNS,
TRNS, TRNS,
TRNS,
TRNS, TRNS, TRNS,
// right hand
F12, F6, F7, F8, F9, F10, POWER,
TRNS, NO, FN9, FN10, FN11, FN12, _VOLUP,
BSLS, 1, FN13, FN14, EQL, _VOLDOWN,
FN3, FN15, 2, 3, 4, 5, _MUTE,
TRNS, TRNS, TRNS, TRNS, TRNS,
TRNS, TRNS,
TRNS,
TRNS, TRNS, TRNS
),
// ........................................................................
// Layer3: keyboard functions
// Based on Ben Blazak's dvorak-kinesis-mod layout.
//
// left hand
// ,--------------------------------------------------.
// | Teensy | | | | | | |
// |--------+------+------+------+------+-------------|
// | | | | | | | |
// |--------+------+------+------+------+------| |
// | | | | | | |------|
// |--------+------+------+------+------+------| |
// | | | | | | | |
// `--------+------+------+------+------+-------------'
// | | | | | |
// `----------------------------------'
// ,-------------.
// | | |
// ,------|------|------|
// | | | |
// | | |------|
// | | | |
// `--------------------'
//
// right hand
// ,--------------------------------------------------.
// | +L0 | | | | | | |
// |------+------+------+------+------+------+--------|
// | | | | | | | |
// | |------+------+------+------+------+--------|
// |------| | | | | | |
// | |------+------+------+------+------+--------|
// | | | | | | | |
// `-------------+------+------+------+------+--------'
// | | | | | |
// `----------------------------------'
// ,-------------.
// | | |
// |------+------+------.
// | | | |
// |------| | |
// | | | |
// `--------------------'
//
KEYMAP( // Layer3: keyboard functions
// Based on Ben Blazak's dvorak-kinesis-mod layout.
// left hand
FN31, NO, NO, NO, NO, NO, NO,
NO, NO, NO, NO, NO, NO, NO,
NO, NO, NO, NO, NO, NO,
NO, NO, NO, NO, NO, NO, NO,
NO, NO, NO, NO, NO,
NO, NO,
NO,
NO, NO, NO,
// right hand
FN0, NO, NO, NO, NO, NO, NO,
NO, NO, NO, NO, NO, NO, NO,
NO, NO, NO, NO, NO, NO,
NO, NO, NO, NO, NO, NO, NO,
NO, NO, NO, NO, NO,
NO, NO,
NO,
NO, NO, NO
),
/*
// templates to copy from
KEYMAP( // LayerN: transparent on edges + hard-defined thumb keys,
// all others are empty
// left hand
TRNS, NO, NO, NO, NO, NO, NO,
TRNS, NO, NO, NO, NO, NO, TRNS,
TRNS, NO, NO, NO, NO, NO,
TRNS, NO, NO, NO, NO, NO, TRNS,
TRNS, TRNS, TRNS, LALT, LGUI,
TRNS, TRNS,
TRNS,
LCTL, LSFT, TRNS,
// right hand
NO, NO, NO, NO, NO, NO, TRNS,
TRNS, NO, NO, NO, NO, NO, TRNS,
NO, NO, NO, NO, NO, TRNS,
TRNS, NO, NO, NO, NO, NO, TRNS,
RGUI, RALT, TRNS, TRNS, TRNS,
TRNS, TRNS,
TRNS,
TRNS, RSFT, RCTL
),
KEYMAP( // LayerN: fully transparent
// left hand
TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS,
TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS,
TRNS, TRNS, TRNS, TRNS, TRNS, TRNS,
TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS,
TRNS, TRNS, TRNS, TRNS, TRNS,
TRNS, TRNS,
TRNS,
TRNS, TRNS, TRNS,
// right hand
TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS,
TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS,
TRNS, TRNS, TRNS, TRNS, TRNS, TRNS,
TRNS, TRNS, TRNS, TRNS, TRNS, TRNS, TRNS,
TRNS, TRNS, TRNS, TRNS, TRNS,
TRNS, TRNS,
TRNS,
TRNS, TRNS, TRNS
),
*/
};
/* id for user defined functions & macros */
enum function_id {
TEENSY_KEY,
// CUSTOM_KEY,
LSFT_2_CAP,
RSFT_2_CAP,
};
/*
* Fn action definition
*/
static const uint16_t PROGMEM fn_actions[] = {
[0] = ACTION_LAYER_SET(0, ON_PRESS), // FN0 = Set Layer0
[1] = ACTION_LAYER_TOGGLE(1), // FN1 = Toggle Layer1
[2] = ACTION_LAYER_TOGGLE(2), // FN2 = Toggle Layer2
[3] = ACTION_LAYER_MOMENTARY(3), // FN3 = Momentary Layer3
[4] = ACTION_LAYER_MOMENTARY(2), // FN4 = Momentary Layer2
[5] = ACTION_MODS_KEY(MOD_LSFT, KC_LBRACKET), // FN5 = shift+[ -> {
[6] = ACTION_MODS_KEY(MOD_LSFT, KC_RBRACKET), // FN6 = shift+] -> }
[7] = ACTION_MODS_KEY(MOD_LSFT, KC_SCOLON), // FN7 = shift+; -> :
[8] = ACTION_MODS_KEY(MOD_LSFT, KC_EQUAL), // FN8 = shift+= -> +
[9] = ACTION_MODS_KEY(MOD_LSFT, KC_MINUS), // FN9 = shift+- -> _
[10] = ACTION_MODS_KEY(MOD_LSFT, KC_COMMA), // FN10 = shift+, -> <
[11] = ACTION_MODS_KEY(MOD_LSFT, KC_DOT), // FN11 = shift+. -> >
[12] = ACTION_MODS_KEY(MOD_LSFT, KC_4), // FN12 = shift+4 -> $
[13] = ACTION_MODS_KEY(MOD_LSFT, KC_9), // FN13 = shift+9 -> (
[14] = ACTION_MODS_KEY(MOD_LSFT, KC_0), // FN14 = shift+0 -> )
[15] = ACTION_MODS_KEY(MOD_LSFT, KC_8), // FN15 = shift+8 -> *
[29] = ACTION_FUNCTION(LSFT_2_CAP), // FN29 = Toggle CapsLock
// if both Shifts hit
[30] = ACTION_FUNCTION(RSFT_2_CAP), // FN30 = Toggle CapsLock
// if both Shifts hit
[31] = ACTION_FUNCTION(TEENSY_KEY), // FN31 = Teensy bootloader
};
void action_function(keyrecord_t *record, uint8_t id, uint8_t opt)
{
// print("action_function called\n");
// print("id = "); phex(id); print("\n");
// print("opt = "); phex(opt); print("\n");
if (id == TEENSY_KEY) {
clear_keyboard();
print("\n\nJump to bootloader... ");
_delay_ms(50);
bootloader_jump(); // should not return
print("not supported.\n");
}
// Toggle capslock when pressing both left and right shift keys
//
if (id == LSFT_2_CAP || id == RSFT_2_CAP) {
uint8_t curr_weak_mods = 0;
// Set weak_mods value for each shift key
//
if (id == LSFT_2_CAP) {
dprintf("->left shift: %u\n", id);
curr_weak_mods = MOD_BIT(KC_LSHIFT);
} else {
dprintf("->right shift: %u\n", id);
curr_weak_mods = MOD_BIT(KC_RSHIFT);
}
if (record->event.pressed) {
// Get the previous weak_mods value
//
uint8_t prev_weak_mods = get_weak_mods();
dprintf("-->prev_weak_mods: %u\n", prev_weak_mods);
// When a shift key is pressed, check previous weak_mods value.
// If 0, then no shift key is held down.
// If not 0, then at least one shift key is held down.
//
if (prev_weak_mods != 0) {
// Toggle capslock if more than one shift key is pressed.
//
dprintf("--->press, toggle capslock\n");
add_key(KC_CAPSLOCK);
send_keyboard_report();
del_key(KC_CAPSLOCK);
send_keyboard_report();
} else {
// Set the appropriate weak_mods value if just one shift
// key is pressed.
//
dprintf("--->press, curr_weak_mods: %u\n", curr_weak_mods);
add_weak_mods(curr_weak_mods);
send_keyboard_report();
}
} else {
// Unset the weak_mods value when shift key is released.
//
dprintf("--->release, curr_weak_mods: %u\n", curr_weak_mods);
del_weak_mods(curr_weak_mods);
send_keyboard_report();
}
}
/*
* just an example of custom key implementation
* not really needed with custom keymap_fn_to_action(),
* because it will allow you to have 32 FN** keys on EACH layer
*
keyevent_t event = record->event;
if (id == CUSTOM_KEY) {
uint8_t layer = biton32(layer_state);
uint8_t col = event.key.col;
uint8_t row = event.key.row;
uint8_t handled = 0;
if (event.pressed) {
if (layer == XXX && col == XXX && row == XXX) {
action_macro_play(
MACRO(
...........
END)
);
handled++;
}
}
}
if (!handled) {
print("custom key not handled");
print(": layer "); pdec(layer);
print(", col "); pdec(col);
print(", row "); pdec(row);
print("\n");
}
}
*/
}
/*
* Translates Fn keycode to action.
*
* Allows for more than 32 Fn keycodes. This will provide up to 32 Fn
* keycodes per layer.
*
* This overrides the keymap_fn_to_action() function found at the end of
* keymap.c with an #if defined.
*
static const uint16_t PROGMEM fn_actions_1[] = {
[1] = ACTION_LAYER_TOGGLE(1), // FN1 = Toggle Layer1
[2] = ACTION_LAYER_TOGGLE(2), // FN2 = Toggle Layer2
[4] = ACTION_LAYER_MOMENTARY(2), // FN4 = Momentary Layer2
[29] = ACTION_FUNCTION(LSFT_2_CAP), // FN29 = Toggle CapsLock
// if both Shifts hit
[30] = ACTION_FUNCTION(RSFT_2_CAP), // FN30 = Toggle CapsLock
// if both Shifts hit
};
static const uint16_t PROGMEM fn_actions_2[] = {
[2] = ACTION_LAYER_TOGGLE(2), // FN2 = Toggle Layer2
[3] = ACTION_LAYER_MOMENTARY(3), // FN3 = Momentary Layer3
[5] = ACTION_MODS_KEY(MOD_LSFT, KC_LBRACKET), // FN5 = shift+[ -> {
[6] = ACTION_MODS_KEY(MOD_LSFT, KC_RBRACKET), // FN6 = shift+] -> }
[7] = ACTION_MODS_KEY(MOD_LSFT, KC_SCOLON), // FN7 = shift+; -> :
[8] = ACTION_MODS_KEY(MOD_LSFT, KC_EQUAL), // FN8 = shift+= -> +
[9] = ACTION_MODS_KEY(MOD_LSFT, KC_MINUS), // FN9 = shift+- -> _
[10] = ACTION_MODS_KEY(MOD_LSFT, KC_COMMA), // FN10 = shift+, -> <
[11] = ACTION_MODS_KEY(MOD_LSFT, KC_DOT), // FN11 = shift+. -> >
[12] = ACTION_MODS_KEY(MOD_LSFT, KC_4), // FN12 = shift+4 -> $
[13] = ACTION_MODS_KEY(MOD_LSFT, KC_9), // FN13 = shift+9 -> (
[14] = ACTION_MODS_KEY(MOD_LSFT, KC_0), // FN14 = shift+0 -> )
[15] = ACTION_MODS_KEY(MOD_LSFT, KC_8), // FN15 = shift+8 -> *
[29] = ACTION_FUNCTION(LSFT_2_CAP), // FN29 = Toggle CapsLock
// if both Shifts hit
[30] = ACTION_FUNCTION(RSFT_2_CAP), // FN30 = Toggle CapsLock
// if both Shifts hit
};
// Layer3: keyboard functions
// Based on Ben Blazak's dvorak-kinesis-mod layout.
static const uint16_t PROGMEM fn_actions_3[] = {
[0] = ACTION_LAYER_SET(0, ON_PRESS), // FN0 = Set Layer0
[31] = ACTION_FUNCTION(TEENSY_KEY), // FN31 = Teensy bootloader
};
#define FN_ACTIONS_SIZE (sizeof(fn_actions) / sizeof(fn_actions[0]))
#define FN_ACTIONS_1_SIZE (sizeof(fn_actions_1) / sizeof(fn_actions_1[0]))
#define FN_ACTIONS_2_SIZE (sizeof(fn_actions_2) / sizeof(fn_actions_2[0]))
#define FN_ACTIONS_3_SIZE (sizeof(fn_actions_3) / sizeof(fn_actions_3[0]))
action_t keymap_fn_to_action(uint8_t keycode)
{
uint8_t layer = biton32(layer_state);
action_t action;
action.code = ACTION_NO;
if (layer == 1 && FN_INDEX(keycode) < FN_ACTIONS_1_SIZE) {
action.code = pgm_read_word(&fn_actions_1[FN_INDEX(keycode)]);
}
if (layer == 2 && FN_INDEX(keycode) < FN_ACTIONS_2_SIZE) {
action.code = pgm_read_word(&fn_actions_2[FN_INDEX(keycode)]);
}
if (layer == 3 && FN_INDEX(keycode) < FN_ACTIONS_3_SIZE) {
action.code = pgm_read_word(&fn_actions_3[FN_INDEX(keycode)]);
}
// By default, use fn_actions from default layer 0.
// This is needed to get mapping for same key, that was used switch
// to some layer, to have possibility to switch layers back
if (action.code == ACTION_NO && FN_INDEX(keycode) < FN_ACTIONS_SIZE) {
action.code = pgm_read_word(&fn_actions[FN_INDEX(keycode)]);
}
return action;
}
*/