[osx_neo2] Bugfixes and improvements to Ergodox macOS Neo2 keymap (#8154)

* Use TAPPING_TERM constant (and redefine value to 200ms)
* change TAPPING_TOGGLE to 2 to require two taps to lock in layer 4
* add support for Shift-Command 3/4/5 key combinations that are used in
  macOS Catalina
* avoid false positive tap detecion for RMOD3 when the whole sequence of
  pressing RMOD3, tapping another key and releasing RMOD3 took less than
  TAPPING_TERM milliseconds.
* replace SEND_STRING with tap_code()/tap_code16(), saving ~860 bytes in
  compiled firmware size.
This commit is contained in:
Morton Jonuschat 2020-02-13 19:30:32 -08:00 committed by GitHub
parent 9241d11dc5
commit 806cd392e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 79 additions and 41 deletions

View File

@ -0,0 +1,7 @@
#pragma once
#undef TAPPING_TERM
#define TAPPING_TERM 200
#undef TAPPING_TOGGLE
#define TAPPING_TOGGLE 2

View File

@ -5,6 +5,9 @@
// Timer to detect tap/hold on NEO_RMOD3 key // Timer to detect tap/hold on NEO_RMOD3 key
static uint16_t neo3_timer; static uint16_t neo3_timer;
// State bitmap to track which key(s) enabled NEO_3 layer // State bitmap to track which key(s) enabled NEO_3 layer
// Bit 1 = LMOD state
// Bit 2 = RMOD state
// Bit 3 = Seen other keypress
static uint8_t neo3_state = 0; static uint8_t neo3_state = 0;
// State bitmap to track key combo for CAPSLOCK // State bitmap to track key combo for CAPSLOCK
static uint8_t capslock_state = 0; static uint8_t capslock_state = 0;
@ -453,6 +456,7 @@ void tap_with_modifiers(uint16_t keycode, uint8_t force_modifiers) {
bool process_record_user_shifted(uint16_t keycode, keyrecord_t *record) { bool process_record_user_shifted(uint16_t keycode, keyrecord_t *record) {
uint8_t active_modifiers = get_mods(); uint8_t active_modifiers = get_mods();
uint8_t shifted = active_modifiers & MOD_MASK_SHIFT; uint8_t shifted = active_modifiers & MOD_MASK_SHIFT;
uint8_t command = active_modifiers & MOD_MASK_GUI;
// Early return on key release // Early return on key release
if (!record->event.pressed) { if (!record->event.pressed) {
@ -465,67 +469,81 @@ bool process_record_user_shifted(uint16_t keycode, keyrecord_t *record) {
switch (keycode) { switch (keycode) {
case NEO2_1: case NEO2_1:
// degree symbol // degree symbol
SEND_STRING(SS_DOWN(X_LALT) SS_DOWN(X_LSHIFT) SS_TAP(X_8) SS_UP(X_LSHIFT) SS_UP(X_LALT)); tap_code16(S(A(KC_8)));
break; break;
case NEO2_2: case NEO2_2:
// section symbol // section symbol
SEND_STRING(SS_DOWN(X_LALT) SS_TAP(X_6) SS_UP(X_LALT)); tap_code16(A(KC_6));
break; break;
case NEO2_3: case NEO2_3:
// There is no OSX key combination for the script small l character if (command) {
tap_code16(S(G(KC_3)));
} else {
// There is no OSX key combination for the script small l character
}
break; break;
case NEO2_4: case NEO2_4:
// right angled quote if (command) {
SEND_STRING(SS_DOWN(X_LALT) SS_DOWN(X_LSHIFT) SS_TAP(X_BSLASH) SS_UP(X_LSHIFT) SS_UP(X_LALT)); tap_code16(S(G(KC_4)));
} else {
tap_code16(S(A(KC_BSLASH)));
}
break; break;
case NEO2_5: case NEO2_5:
// left angled quote if (command) {
SEND_STRING(SS_DOWN(X_LALT) SS_TAP(X_BSLASH) SS_UP(X_LALT)); tap_code16(S(G(KC_5)));
} else {
// left angled quote
tap_code16(A(KC_BSLASH));
}
break; break;
case NEO2_6: case NEO2_6:
// dollar sign // dollar sign
SEND_STRING(SS_DOWN(X_LSHIFT) SS_TAP(X_4) SS_UP(X_LSHIFT)); tap_code16(S(KC_4));
break; break;
case NEO2_7: case NEO2_7:
// euro sign // euro sign
SEND_STRING(SS_DOWN(X_LALT) SS_DOWN(X_LSHIFT) SS_TAP(X_2) SS_UP(X_LSHIFT) SS_UP(X_LALT)); tap_code16(S(A(KC_2)));
break; break;
case NEO2_8: case NEO2_8:
// low9 double quote // low9 double quote
SEND_STRING(SS_DOWN(X_LALT) SS_DOWN(X_LSHIFT) SS_TAP(X_W) SS_UP(X_LSHIFT) SS_UP(X_LALT)); tap_code16(S(A(KC_W)));
break; break;
case NEO2_9: case NEO2_9:
// left double quote // left double quote
SEND_STRING(SS_DOWN(X_LALT) SS_TAP(X_LBRACKET) SS_UP(X_LALT)); tap_code16(A(KC_LBRACKET));
break; break;
case NEO2_0: case NEO2_0:
// right double quote // right double quote
SEND_STRING(SS_DOWN(X_LALT) SS_DOWN(X_LSHIFT) SS_TAP(X_LBRACKET) SS_UP(X_LSHIFT) SS_UP(X_LALT)); tap_code16(S(A(KC_LBRACKET)));
break; break;
case NEO2_MINUS: case NEO2_MINUS:
// em dash // em dash
SEND_STRING(SS_DOWN(X_LALT) SS_DOWN(X_LSHIFT) SS_TAP(X_MINUS) SS_UP(X_LSHIFT) SS_UP(X_LALT)); tap_code16(S(A(KC_MINUS)));
break; break;
case NEO2_COMMA: case NEO2_COMMA:
// en dash // en dash
SEND_STRING(SS_DOWN(X_LALT) SS_TAP(X_MINUS) SS_UP(X_LALT)); tap_code16(A(KC_MINUS));
break; break;
case NEO2_DOT: case NEO2_DOT:
// bullet // bullet
SEND_STRING(SS_DOWN(X_LALT) SS_TAP(X_8) SS_UP(X_LALT)); tap_code16(A(KC_8));
break; break;
case NEO2_SHARP_S: case NEO2_SHARP_S:
// german sharp s // german sharp s
SEND_STRING(SS_DOWN(X_LALT) SS_TAP(X_S) SS_UP(X_LALT)); tap_code16(S(KC_S));
break; break;
case NEO2_UE: case NEO2_UE:
SEND_STRING(SS_DOWN(X_LALT) SS_DOWN(X_U) SS_UP(X_U) SS_UP(X_LALT) SS_DOWN(X_LSHIFT) SS_TAP(X_U) SS_UP(X_LSHIFT)); tap_code16(A(KC_U));
tap_code16(S(KC_U));
break; break;
case NEO2_OE: case NEO2_OE:
SEND_STRING(SS_DOWN(X_LALT) SS_DOWN(X_U) SS_UP(X_U) SS_UP(X_LALT) SS_DOWN(X_LSHIFT) SS_TAP(X_O) SS_UP(X_LSHIFT)); tap_code16(A(KC_U));
tap_code16(S(KC_O));
break; break;
case NEO2_AE: case NEO2_AE:
SEND_STRING(SS_DOWN(X_LALT) SS_DOWN(X_U) SS_UP(X_U) SS_UP(X_LALT) SS_DOWN(X_LSHIFT) SS_TAP(X_A) SS_UP(X_LSHIFT)); tap_code16(A(KC_U));
tap_code16(S(KC_A));
break; break;
default: default:
set_mods(active_modifiers); set_mods(active_modifiers);
@ -537,56 +555,59 @@ bool process_record_user_shifted(uint16_t keycode, keyrecord_t *record) {
} else { } else {
switch (keycode) { switch (keycode) {
case NEO2_1: case NEO2_1:
SEND_STRING(SS_TAP(X_1)); tap_code(KC_1);
break; break;
case NEO2_2: case NEO2_2:
SEND_STRING(SS_TAP(X_2)); tap_code(KC_2);
break; break;
case NEO2_3: case NEO2_3:
SEND_STRING(SS_TAP(X_3)); tap_code(KC_3);
break; break;
case NEO2_4: case NEO2_4:
SEND_STRING(SS_TAP(X_4)); tap_code(KC_4);
break; break;
case NEO2_5: case NEO2_5:
SEND_STRING(SS_TAP(X_5)); tap_code(KC_5);
break; break;
case NEO2_6: case NEO2_6:
SEND_STRING(SS_TAP(X_6)); tap_code(KC_6);
break; break;
case NEO2_7: case NEO2_7:
SEND_STRING(SS_TAP(X_7)); tap_code(KC_7);
break; break;
case NEO2_8: case NEO2_8:
SEND_STRING(SS_TAP(X_8)); tap_code(KC_8);
break; break;
case NEO2_9: case NEO2_9:
SEND_STRING(SS_TAP(X_9)); tap_code(KC_9);
break; break;
case NEO2_0: case NEO2_0:
SEND_STRING(SS_TAP(X_0)); tap_code(KC_0);
break; break;
case NEO2_MINUS: case NEO2_MINUS:
SEND_STRING(SS_TAP(X_MINUS)); tap_code(KC_MINUS);
break; break;
case NEO2_COMMA: case NEO2_COMMA:
SEND_STRING(SS_TAP(X_COMMA)); tap_code(KC_COMMA);
break; break;
case NEO2_DOT: case NEO2_DOT:
SEND_STRING(SS_TAP(X_DOT)); tap_code(KC_DOT);
break; break;
case NEO2_SHARP_S: case NEO2_SHARP_S:
// german sharp s // german sharp s
SEND_STRING(SS_DOWN(X_LALT) SS_TAP(X_S) SS_UP(X_LALT)); tap_code16(A(KC_S));
break; break;
case NEO2_UE: case NEO2_UE:
SEND_STRING(SS_DOWN(X_LALT) SS_DOWN(X_U) SS_UP(X_U) SS_UP(X_LALT) SS_TAP(X_U)); tap_code16(A(KC_U));
tap_code(KC_U);
break; break;
case NEO2_OE: case NEO2_OE:
SEND_STRING(SS_DOWN(X_LALT) SS_DOWN(X_U) SS_UP(X_U) SS_UP(X_LALT) SS_TAP(X_O)); tap_code16(A(KC_U));
tap_code(KC_O);
break; break;
case NEO2_AE: case NEO2_AE:
SEND_STRING(SS_DOWN(X_LALT) SS_DOWN(X_U) SS_UP(X_U) SS_UP(X_LALT) SS_TAP(X_A)); tap_code16(A(KC_U));
tap_code(KC_A);
break; break;
default: default:
return true; return true;
@ -619,7 +640,7 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
neo3_state |= (1 << 1); neo3_state |= (1 << 1);
} else { } else {
// Turn off NEO_3 layer unless it's enabled through NEO2_RMOD3 as well. // Turn off NEO_3 layer unless it's enabled through NEO2_RMOD3 as well.
if ((neo3_state & ~(1 << 1)) == 0) { if ((neo3_state & (1 << 2)) == 0) {
layer_off(NEO_3); layer_off(NEO_3);
} }
neo3_state &= ~(1 << 1); neo3_state &= ~(1 << 1);
@ -629,28 +650,38 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) {
if (record->event.pressed) { if (record->event.pressed) {
neo3_timer = timer_read(); neo3_timer = timer_read();
neo3_state |= (1 << 2); neo3_state |= (1 << 2);
// Reset tap detection state
neo3_state &= ~(1 << 3);
layer_on(NEO_3); layer_on(NEO_3);
} else { } else {
// Turn off NEO_3 layer unless it's enabled through NEO2_LMOD3 as well. // Turn off NEO_3 layer unless it's enabled through NEO2_LMOD3 as well.
if ((neo3_state & ~(1 << 2)) == 0) { if ((neo3_state & (1 << 1)) == 0) {
layer_off(NEO_3); layer_off(NEO_3);
} }
neo3_state &= ~(1 << 2); neo3_state &= ~(1 << 2);
// Was the NEO2_RMOD3 key TAPPED? // Was the NEO2_RMOD3 key TAPPED?
if (timer_elapsed(neo3_timer) <= 150) { if (timer_elapsed(neo3_timer) <= TAPPING_TERM) {
if (neo3_state > 0) { if ((neo3_state & ~(1 << 3)) > 0) {
// We are still in NEO_3 layer, send keycode and modifiers for @ // We are still in NEO_3 layer, send keycode and modifiers for @
tap_with_modifiers(KC_2, MOD_MASK_SHIFT); tap_with_modifiers(KC_2, MOD_MASK_SHIFT);
return false; return false;
} else { } else {
// Do the normal key processing, send y // Do the normal key processing, send y
tap_with_modifiers(KC_Y, MOD_MASK_NONE); if ((neo3_state & (1 << 3)) == 0) {
tap_with_modifiers(KC_Y, MOD_MASK_NONE);
}
return false; return false;
} }
} }
} }
break; break;
default:
if (record->event.pressed && neo3_state > 0) {
// Track that we've seen a separate keypress event
neo3_state |= (1 << 3);
}
break;
} }
if ((capslock_state & MOD_MASK_SHIFT) == MOD_MASK_SHIFT) { if ((capslock_state & MOD_MASK_SHIFT) == MOD_MASK_SHIFT) {