#include QMK_KEYBOARD_H #include "layers.h" #include "keymap_extras/keymap_neo2.h" /* * audax_osx - neo2 for macOS via the *software* neo2 keyboard layout. * * Unlike the sibling `audax_osx_neo2` layout (which emulates neo2 in firmware * on top of a US/ABC-Extended macOS layout), this layout expects the neo2 * layout to be installed on the Mac itself: * * - neo2-layout-osx (.keylayout / .bundle) provides base, shift and Mod3. * * The base/Mod3 keys send *positional* scancodes (the NE_* aliases from * keymap_extras/keymap_neo2.h); the OS neo2 layout produces those characters. * See readme.md for the macOS/Karabiner setup. * * --------------------------------------------------------------------------- * neo2 layer switching: * * Mod3 (layer 3, symbols): held on both Mod3 keys, which send '#' (NE_L3R / * KC_NUHS); the OS neo2 .keylayout turns '#' into Mod3. The canonical * neo2 Mod3-left is CapsLock, but macOS intercepts CapsLock, so it does * NOT act as Mod3 unless Karabiner remaps caps_lock -> '#'. Sending '#' * from both keys works out of the box. * * Mod4 (layer 4, cursor + numpad): provided as a FIRMWARE layer (NEO_4), * held via the right-thumb Enter key (NEO_ENT_M4). Kept in firmware - * not the OS neo2 Mod4 - so the cursor keys auto-repeat when held, like * the Linux `audax` layout. Mod4 special characters (ordinals, GBP, ...) * are omitted; add them to NEO_4 if you need them. * --------------------------------------------------------------------------- */ // Custom keycodes. enum custom_keycodes { // Right Mod3 key: hold = Mod3 (sends NE_L3R / '#'), tap = ss (neo2 native). NEO_L3R_SS = SAFE_RANGE, // Right-thumb Enter: tap = Enter, hold = the firmware Mod4 layer (NEO_4). NEO_ENT_M4 }; const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { /* NEO_1: neo2 base layer (positional scancodes) * * The character legend below is what the *OS neo2 layout* produces for each * key; the firmware only sends the matching physical scancode. * * ,--------------------------------------------------. ,--------------------------------------------------. * | ESC | 1/° | 2/§ | 3/ | 4/» | 5/« | MPLY | | MNXT | 6/$ | 7/€ | 8/„ | 9/“ | 0/” | -/— | * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------| * | TAB | X | V | L | C | W | FKEYS| | RCTL | K | H | G | F | Q | Y | * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------| * | Mod3-L | CTL/U| ALT/I| GUI/A| E | O |------| |------| S | N | R | T | D | #/ß M3R| * |--------+------+------+------+------+------| LALT | | MOD4 |------+------+------+------+------+--------| * | LSHIFT | Ü | Ö | Ä | P | Z | | | | B | M | , | . | J | SFT/ESC| * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------' * | Home | PGUP | PGDN | End | S(G(a)) | Left | Down | Up | Right| RGUI | * `----------------------------------' `----------------------------------' * ,-------------. ,-------------. * |G(TAB)|G(S(T))| |A(G(Lft))|A(G(Rgt))| * ,------|------|------| |------+------+------. * | | | Ins | |A(G(Home))| MO | | * | Space|Bksp |------| |------|FKEYS | Enter| * | | | LCTL | | | |/Mod4 | * `--------------------' `--------------------' */ [NEO_1] = LAYOUT_ergodox( // left hand side - main KC_ESC, NE_1, NE_2, NE_3, NE_4, NE_5, KC_MPLY, KC_TAB, NE_X, NE_V, NE_L, NE_C, NE_W, MO(FKEYS), NE_L3R, LCTL_T(NE_U), LALT_T(NE_I), LGUI_T(NE_A), NE_E, NE_O, /* --- */ // Mod3-left: send '#' like Mod3-right (macOS intercepts CapsLock, so NE_L3L is unreliable) KC_LSFT, NE_UDIA, NE_ODIA, NE_ADIA, NE_P, NE_Z, KC_LALT, KC_HOME, KC_PGUP, KC_PGDN, KC_END, LSFT(LGUI(NE_A)), /* --- */ /* --- */ // left hand side - thumb cluster /* --- */ LGUI(KC_TAB), LGUI(LSFT(KC_TAB)), /* KC_SPACE */ /* KC_BSPC */ KC_INS, KC_SPACE, KC_BSPC, KC_LCTL, // right hand side - main KC_MNXT, NE_6, NE_7, NE_8, NE_9, NE_0, NE_MINS, KC_RCTL, NE_K, NE_H, NE_G, NE_F, NE_Q, NE_Y, /* --- */ NE_S, NE_N, NE_R, NE_T, NE_D, NEO_L3R_SS, MO(NEO_4), NE_B, NE_M, NE_COMM, NE_DOT, NE_J, RSFT_T(KC_ESC), /* --- */ /* --- */ KC_LEFT, KC_DOWN, KC_UP, KC_RIGHT, KC_RGUI, // right hand side - thumb cluster LALT(LGUI(KC_LEFT)), LALT(LGUI(KC_RIGHT)), /* --- */ LALT(LGUI(KC_HOME)), /* --- */ /* --- */ MO(FKEYS), KC_SPACE, NEO_ENT_M4 ), /* NEO_4: Mod4 - cursor block (left) + numpad (right) * * Firmware layer with real keycodes so the cursor keys auto-repeat when held. * Held via the right-thumb Enter key. neo2 Mod4 special characters (ordinals, * GBP, inverted !/?, ...) are omitted as KC_NO. * * ,--------------------------------------------------. ,--------------------------------------------------. * | ---- | ---- | ---- | ---- | ---- | ---- | | | | ---- | Tab | / | * | - | ---- | * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------| * | | PgUp | Bsp | Up | Del | PgDn | | | | ---- | 7 | 8 | 9 | + | ---- | * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------| * | | Home | Left | Down | Right| End |------| |------| ---- | 4 | 5 | 6 | , | . | * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------| * | | Esc | Tab | Ins |Return| ---- | | | | ---- | 1 | 2 | 3 | ---- | | * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------' * | | | | | | | 0 | | | | | * `----------------------------------' `----------------------------------' * ,-------------. ,-------------. * | | | | | | * ,------|------|------| |------+------+------. * | | | | | | | | * | | Del |------| |------| | | * | | | | | | | | * `--------------------' `--------------------' */ [NEO_4] = LAYOUT_ergodox( // left hand side - main KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, KC_NO, _______, _______, KC_PGUP, KC_BSPC, KC_UP, KC_DELETE, KC_PGDN, _______, _______, KC_HOME, KC_LEFT, KC_DOWN, KC_RIGHT, KC_END, /* --- */ _______, KC_ESCAPE, KC_TAB, KC_INSERT, KC_ENTER, KC_NO, _______, _______, _______, _______, _______, _______, /* --- */ /* --- */ // left hand side - thumb cluster /* --- */ _______, _______, /* --- */ /* --- */ _______, _______, KC_DEL, _______, // right hand side - main _______, KC_NO, KC_TAB, KC_KP_SLASH, KC_KP_ASTERISK, KC_KP_MINUS, KC_NO, _______, KC_NO, KC_KP_7, KC_KP_8, KC_KP_9, KC_KP_PLUS, KC_NO, /* --- */ KC_NO, KC_KP_4, KC_KP_5, KC_KP_6, KC_KP_COMMA, KC_KP_DOT, _______, KC_NO, KC_KP_1, KC_KP_2, KC_KP_3, KC_NO, _______, /* --- */ /* --- */ _______, KC_KP_0, _______, _______, _______, // right hand side - thumb cluster _______, _______, /* --- */ _______, /* --- */ /* --- */ _______, _______, _______ ), /* FKEYS: Function and media keys * * ,--------------------------------------------------. ,--------------------------------------------------. * | Prev | F1 | F2 | F3 | F4 | F5 | F11 | | F12 | F6 | F7 | F8 | F9 | F10 | | * |--------+------+------+------+------+-------------| |------+------+------+------+------+------+--------| * | Play | | | | | | | | | | | | | | | * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------| * | Next | | | | | |------| |------| | | | | | | * |--------+------+------+------+------+------| | | |------+------+------+------+------+--------| * | | | | | | | | | | | | |VolDn | Mute | VolUp | * `--------+------+------+------+------+-------------' `-------------+------+------+------+------+--------' * | | | | | | | | | | | | * `----------------------------------' `----------------------------------' */ [FKEYS] = LAYOUT_ergodox( // left hand side - main KC_MEDIA_REWIND, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F11, KC_MEDIA_PLAY_PAUSE, _______, _______, _______, _______, _______, _______, KC_MEDIA_FAST_FORWARD, _______, _______, _______, _______, _______, /* --- */ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, /* --- */ /* --- */ // left hand side - thumb cluster /* --- */ _______, _______, /* --- */ /* --- */ _______, _______, _______, _______, // right hand side - main KC_F12, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, _______, _______, _______, _______, _______, _______, _______, _______, /* --- */ _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, KC_AUDIO_VOL_DOWN, KC_AUDIO_MUTE, KC_AUDIO_VOL_UP, /* --- */ /* --- */ _______, _______, _______, _______, _______, // right hand side - thumb cluster _______, _______, /* --- */ _______, /* --- */ /* --- */ _______, _______, _______ ), }; // Tracks the tap/hold state of the right Mod3 key so it can send ss on a tap // while acting as the neo2 Mod3 modifier on a hold. static bool l3r_held = false; static bool l3r_used_as_mod3 = false; // Tracks the tap/hold state of the right-thumb Enter/Mod4 key: a pure tap emits // Enter, a hold turns on the NEO_4 (Mod4) layer. static bool ent_held = false; static bool ent_used = false; // Runs for each key down or up event. bool process_record_user(uint16_t keycode, keyrecord_t *record) { switch (keycode) { case NEO_L3R_SS: if (record->event.pressed) { // Engage neo2 Mod3 (the '#' / non-US-# scancode) for as long as held. register_code(NE_L3R); l3r_held = true; l3r_used_as_mod3 = false; } else { unregister_code(NE_L3R); l3r_held = false; // Nothing else was pressed while held -> it was a tap: send ss. if (!l3r_used_as_mod3) { tap_code(NE_SS); } } return false; case NEO_ENT_M4: if (record->event.pressed) { // Hold = neo2 Mod4 as a firmware layer, so its cursor keys auto-repeat. // (Enter+Backspace = Delete too: NEO_4 maps that thumb key to KC_DEL.) layer_on(NEO_4); ent_held = true; ent_used = false; } else { layer_off(NEO_4); ent_held = false; // Nothing else was pressed while held -> it was a tap: send Enter. if (!ent_used) { tap_code(KC_ENT); } } return false; default: break; } // A separate keypress while a hold-key is held means that key is acting as a // modifier/layer, so its own release must not emit its tap code. if (record->event.pressed) { if (l3r_held) { l3r_used_as_mod3 = true; } if (ent_held) { ent_used = true; } } return true; } // Runs constantly in the background, in a loop. Lights an LED on the FKEYS layer. void matrix_scan_user(void) { uint8_t layer = get_highest_layer(layer_state); ergodox_board_led_off(); ergodox_right_led_1_off(); ergodox_right_led_2_off(); ergodox_right_led_3_off(); if (layer == FKEYS) { ergodox_right_led_1_on(); } }