Files
qmk/layouts/community/ergodox/audax_osx/keymap.c
Jens Kadenbach 85ef39b09d
Some checks failed
Automatic Approve / automatic_approve (push) Has been cancelled
Update API Data / api_data (push) Has been cancelled
CI Builds / CI Build (default) (push) Has been cancelled
CI Builds / CI Build (via) (push) Has been cancelled
CLI CI / test (push) Has been cancelled
Update develop after master merge / develop_update (push) Has been cancelled
Lint Format / lint (push) Has been cancelled
Regenerate Files / regen (push) Has been cancelled
Unit Tests / test (push) Has been cancelled
Close stale issues and PRs / stale (push) Has been cancelled
Add audax_osx ErgoDox layout for macOS software neo2
neo2 for macOS via the installed software neo2 keyboard layout instead of firmware emulation. The base layer and Mod3 send positional NE_* scancodes that the OS neo2 layout translates; Mod4 (cursor and numpad) is a firmware layer so its keys auto-repeat. Keeps the audax_osx_neo2 key arrangement, home-row mods, macOS shortcuts and media/function layer. The right Mod3 key taps to the neo2 sharp-s; a dedicated right-hand Mod4 key and the Enter thumb both reach the Mod4 layer.
2026-07-20 18:05:50 +02:00

260 lines
15 KiB
C

#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();
}
}