Page 1 of 1

Help needed with tmk firmware layout

Posted: 13 Jul 2016, 21:31
by kitten_paw
Hi,

I am trying to create a couple of layers for the tmk firmware with an ISO 105 key keyboard. I am using the German keymap on my system, where I have to use RALT+8 to get the [ character, RALT+0 to get } and so on. This is extremely annoying for programming, of course, which is why I've been using the US keymap when programming and switching back and forth.

Now my idea is that I'd like to have a "programming layer" that basically mimics the US layout when active. For example when I press the ü key I want to get ü on the default layer and [ on the programming layer, without having to change the system keymap. I know I can achieve this for a single key by making ü a FN key with ACTION_MODS_KEY, but this means a) that I have to waste a function key and b) that I can't use shift+ü to get { (at least I don't know how).

So basically my question is, how can I set up the KEYMAP that my programming layer sends the correct keycodes on the German keymap to mimic the US keymap?

[edit]
I created my intended layer layout here: http://www.keyboard-layout-editor.com/# ... 522d221037
The black labels are the default layer, the red key toggles the programming layer, and the red labels are the characters that I want to get when the programming layer is active (upper labels are Shift+key), without having to change the keymap in the OS. I hope this makes a little more sense now.

Posted: 14 Jul 2016, 15:11
by kitten_paw
So, for now I have implemented it using FN keys and MACROs, thanks to the tmk github wiki. I think it's an ugly solution, but it works. So here's my keymap that, when using a German OS keymap has German layout on the default layer and a US layout on two seperate programming layers. Maybe somebody finds this useful.

Code: Select all


const uint8_t PROGMEM keymaps[][MATRIX_COLS][MATRIX_ROWS] = {
    /* Layer 0: Standard ANSI layer */
    KEYMAP(\
         ESC, F1,  F2,  F3,  F4,  F5,  F6,  F7,  F8,  F9,  F10, F11,  F12,        PSCR,SLCK,PAUS,                         \
         GRV, 1,   2,   3,   4,   5,   6,   7,   8,   9,   0,   MINS, EQL,BSPC,   INS, HOME,PGUP,    NLCK,PSLS,PAST,PMNS, \
         TAB, Q,   W,   E,   R,   T,   Y,   U,   I,   O,   P,   LBRC,RBRC,BSLS,   DEL, END, PGDN,    P7,  P8,  P9,  PPLS, \
         RALT,A,   S,   D,   F,   G,   H,   J,   K,   L,   SCLN,QUOT,      ENT,                      P4,  P5,  P6,        \
         LSFT,NUBS,Z,   X,   C,   V,   B,   N,   M,   COMM,DOT, SLSH,     RSFT,        UP,           P1,  P2,  P3,  PENT, \
         LCTL,LGUI,LALT,               SPC,                FN0, FN1,  FN2,RCTL,   LEFT,DOWN,RGHT,    P0,  PDOT),          \
    /* Layer 1: programming layer 1*/
    KEYMAP(\
          ESC,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,SLSH,FN11,TRNS,   TRNS,TRNS,TRNS,    TRNS,TRNS,TRNS,TRNS, \
         TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,FN12,FN13,FN16,   TRNS,TRNS,TRNS,    TRNS,TRNS,TRNS,TRNS, \
         TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,FN14,FN15,     TRNS,                      TRNS,TRNS,TRNS,      \
         FN26,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,FN17,     TRNS,        TRNS,         TRNS,TRNS,TRNS,TRNS, \
         TRNS,TRNS,TRNS,               TRNS,               TRNS,TRNS,TRNS,TRNS,   TRNS,TRNS,TRNS,    TRNS,TRNS),
    /* Layer 2: programming layer 2*/
    KEYMAP(\
          ESC,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,FN18,RBRC,TRNS,   TRNS,TRNS,TRNS,    TRNS,TRNS,TRNS,TRNS, \
         TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,FN19,FN20,FN23,   TRNS,TRNS,TRNS,    TRNS,TRNS,TRNS,TRNS, \
         TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,FN21,FN22,     TRNS,                      TRNS,TRNS,TRNS,      \
         TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,TRNS,NUBS,FN24,FN25,     TRNS,        TRNS,         TRNS,TRNS,TRNS,TRNS, \
         TRNS,TRNS,TRNS,               TRNS,               TRNS,TRNS,TRNS,TRNS,   TRNS,TRNS,TRNS,    TRNS,TRNS),
    /* Layer 3: media layer */
    KEYMAP(\
          FN3,  NO,  NO,  NO,  NO,  NO,  NO,  NO,  NO,  NO,  NO,  NO,  NO,        MPRV,MPLY,MNXT,                         \
           NO,  NO,  NO,  NO,  NO,  NO,  NO,  NO,  NO,  NO,  NO,  NO,  NO,  NO,     NO,  NO,VOLU,      NO,  NO,  NO,  NO, \
           NO,  NO,  NO,  NO,  NO,  NO,  NO,  NO,  NO,  NO,  NO,  NO,  NO,  NO,     NO,MUTE,VOLD,      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,  NO, \
           NO,  NO,  NO,                 NO,                 NO,  NO,  NO,  NO,     NO,  NO,  NO,      NO,  NO),
    /* Layer 4: Mouse layer */
    KEYMAP(\
          FN3,  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,  NO,  NO,MS_U,  NO,  NO,  NO,  NO,  NO,  NO,  NO,  NO,  NO,  NO,     NO,  NO,  NO,      NO,  NO,  NO,  NO, \
           NO,  NO,MS_L,MS_D,MS_R,  NO,WH_L,WH_D,WH_U,WH_R,  NO,  NO,       NO,                        NO,  NO,  NO,      \
           NO,  NO,  NO,  NO,  NO,  NO,  NO,BTN2,BTN3,  NO,  NO,  NO,       NO,          NO,           NO,  NO,  NO,  NO, \
           NO,  NO,  NO,               BTN1,                 NO,  NO,  NO,  NO,     NO,  NO,  NO,      NO,  NO)

};
enum macro_id {
    UNDERSCORE,
    EQUAL,
    RBRACE_L,
    CBRACE_L,
    RBRACE_R,
    CBRACE_R,
    SEMICOLON,
    COLON,
    APOSTROPHE,
    QUOTE,
    BACKSLASH,
    PIPE,
    GREATERTHAN,
    SLASH,
    QUESTION
};

static const uint16_t PROGMEM fn_actions[] = {
    [0] = ACTION_LAYER_TOGGLE(4),
    [1] = ACTION_LAYER_TOGGLE(1),
    [2] = ACTION_LAYER_MOMENTARY(3),
    [3] = ACTION_LAYER_SET_CLEAR(0),
    [11] = ACTION_MACRO(EQUAL),
    [12] = ACTION_MACRO(RBRACE_L),
    [13] = ACTION_MACRO(RBRACE_R),
    [14] = ACTION_MACRO(SEMICOLON),
    [15] = ACTION_MACRO(APOSTROPHE),
    [16] = ACTION_MACRO(BACKSLASH),
    [17] = ACTION_MACRO(SLASH),
    [18] = ACTION_MACRO(UNDERSCORE),
    [19] = ACTION_MACRO(CBRACE_L),
    [20] = ACTION_MACRO(CBRACE_R),
    [21] = ACTION_MACRO(COLON),
    [22] = ACTION_MACRO(QUOTE),
    [23] = ACTION_MACRO(PIPE),
    [24] = ACTION_MACRO(GREATERTHAN),
    [25] = ACTION_MACRO(QUESTION),
    [26] = ACTION_LAYER_MOMENTARY(2)
};

const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt)
{
    keyevent_t event = record->event;
    //uint8_t tap_count = record->tap_count;

    switch (id) {
        case EQUAL:
            return (event.pressed ?
                    MACRO( D(LSHIFT), T(0), U(LSHIFT), END ) :
                    MACRO( END ) );
        case RBRACE_L:
            return (event.pressed ?
                    MACRO( D(RALT), T(8), U(RALT), END ) :
                    MACRO( END ) );
        case RBRACE_R:
            return (event.pressed ?
                    MACRO( D(RALT), T(9), U(RALT), END ) :
                    MACRO( END ) );
        case SEMICOLON:
            return (event.pressed ?
                    MACRO( D(LSHIFT), T(COMM), U(LSHIFT), END ):
                    MACRO( END ) );
        case APOSTROPHE:
            return (event.pressed ?
                    MACRO( D(LSHIFT), T(BSLS), U(LSHIFT), END ):
                    MACRO( END ) );
        case BACKSLASH:
            return (event.pressed ?
                    MACRO( D(RALT), T(MINS), U(RALT), END ):
                    MACRO( END ) );
        case SLASH:
            return (event.pressed ?
                    MACRO( D(LSHIFT), T(7), U(LSHIFT), END ) :
                    MACRO( END ) );
        case UNDERSCORE:
            return (event.pressed ?
                    MACRO( D(LSHIFT), T(SLSH), U(LSHIFT), END ) :
                    MACRO( END ) );
        case CBRACE_L:
            return (event.pressed ?
                    MACRO( D(RALT), T(7), U(RALT), END ) :
                    MACRO( END ) );
        case CBRACE_R:
            return (event.pressed ?
                    MACRO( D(RALT), T(0), U(RALT), END ) :
                    MACRO( END ) );
        case COLON:
            return (event.pressed ?
                    MACRO( D(LSHIFT), T(DOT), U(LSHIFT), END ) :
                    MACRO( END ) );
        case QUOTE:
            return (event.pressed ?
                    MACRO( D(LSHIFT), T(2), U(LSHIFT), END ) :
                    MACRO( END ) );
        case PIPE:
            return (event.pressed ?
                    MACRO( D(RALT), T(NUBS), U(RALT), END ) :
                    MACRO( END ) );
        case GREATERTHAN:
            return (event.pressed ?
                    MACRO( D(LSHIFT), T(NUBS), U(LSHIFT), END ) :
                    MACRO( END ) );
        case QUESTION:
            return (event.pressed ?
                    MACRO( D(LSHIFT), T(MINS), U(LSHIFT), END ) :
                    MACRO( END ) );
    }
    return MACRO_NONE;
}

Posted: 14 Jul 2016, 15:43
by amospalla
Yes, that is the correct way to do it, using fn_actions. The only drawback is that you are limited to 32, but if these are enough for you then it's ok.

Here is my config, maybe you find something useful there for any other purpose. The thing I found the most difficult was creating 4 different layers and switching between them with a shortcut.