From 1a8c0dd22d6a2255511d0db6a456315541b5815b Mon Sep 17 00:00:00 2001 From: Erez Zukerman Date: Sun, 15 May 2016 00:27:32 -0400 Subject: Leader key implementation (#326) * implements leader key for planck experimental * allows override of leader timeout * adds ability to use the leader key in seq * fixes leader keycode * adds chording prototype * fixes keycode detection * moves music mode to quantum.c * disables chording by default * updates process_action functions to return bool --- quantum/keymap_common.c | 2 +- quantum/keymap_common.h | 4 +- quantum/matrix.c | 8 +-- quantum/quantum.c | 167 ++++++++++++++++++++++++++++++++++++++++++++ quantum/quantum.h | 48 +++++++++++++ quantum/quantum.mk | 3 +- quantum/template/template.c | 7 +- quantum/template/template.h | 2 +- 8 files changed, 230 insertions(+), 11 deletions(-) create mode 100644 quantum/quantum.c create mode 100644 quantum/quantum.h (limited to 'quantum') diff --git a/quantum/keymap_common.c b/quantum/keymap_common.c index 8f00f9cc3..0184770c4 100644 --- a/quantum/keymap_common.c +++ b/quantum/keymap_common.c @@ -251,7 +251,7 @@ static action_t keycode_to_action(uint16_t keycode) } eeconfig_update_keymap(keymap_config.raw); break; - case 0x5100 ... 0x5FFF: ; + case 0x5100 ... 0x56FF: ; // Layer movement shortcuts // See .h to see constraints/usage int type = (keycode >> 0x8) & 0xF; diff --git a/quantum/keymap_common.h b/quantum/keymap_common.h index 322fda498..2ad1ba6c6 100644 --- a/quantum/keymap_common.h +++ b/quantum/keymap_common.h @@ -159,7 +159,7 @@ extern const uint16_t fn_actions[]; #define S(kc) LSFT(kc) #define F(kc) FUNC(kc) -#define M(kc) kc | 0x3000 +#define M(kc) (kc | 0x3000) #define MACRODOWN(...) (record->event.pressed ? MACRO(__VA_ARGS__) : MACRO_NONE) @@ -191,6 +191,8 @@ extern const uint16_t fn_actions[]; #define RESET 0x5000 #define DEBUG 0x5001 +#define KC_LEAD 0x5014 + // MAGIC keycodes #define MAGIC_SWAP_CONTROL_CAPSLOCK 0x5002 diff --git a/quantum/matrix.c b/quantum/matrix.c index 7d70f728d..cab39e117 100644 --- a/quantum/matrix.c +++ b/quantum/matrix.c @@ -55,12 +55,12 @@ static void unselect_rows(void); static void select_row(uint8_t row); __attribute__ ((weak)) -void matrix_init_kb(void) { +void matrix_init_quantum(void) { } __attribute__ ((weak)) -void matrix_scan_kb(void) { +void matrix_scan_quantum(void) { } @@ -93,7 +93,7 @@ void matrix_init(void) matrix_debouncing[i] = 0; } - matrix_init_kb(); + matrix_init_quantum(); } @@ -157,7 +157,7 @@ uint8_t matrix_scan(void) } #endif - matrix_scan_kb(); + matrix_scan_quantum(); return 1; } diff --git a/quantum/quantum.c b/quantum/quantum.c new file mode 100644 index 000000000..e274d846f --- /dev/null +++ b/quantum/quantum.c @@ -0,0 +1,167 @@ +#include "quantum.h" + +__attribute__ ((weak)) +void matrix_init_kb(void) {} + +__attribute__ ((weak)) +void matrix_scan_kb(void) {} + +__attribute__ ((weak)) +bool process_action_kb(keyrecord_t *record) { + return true; +} + +__attribute__ ((weak)) +void leader_start(void) {} + +__attribute__ ((weak)) +void leader_end(void) {} + +#ifdef AUDIO_ENABLE + uint8_t starting_note = 0x0C; + int offset = 0; + bool music_activated = false; +#endif + +// Leader key stuff +bool leading = false; +uint16_t leader_time = 0; + +uint16_t leader_sequence[3] = {0, 0, 0}; +uint8_t leader_sequence_size = 0; + +// Chording stuff +#define CHORDING_MAX 4 +bool chording = false; + +uint8_t chord_keys[CHORDING_MAX] = {0}; +uint8_t chord_key_count = 0; +uint8_t chord_key_down = 0; + +bool keys_chord(uint8_t keys[]) { + uint8_t keys_size = sizeof(keys)/sizeof(keys[0]); + bool pass = true; + uint8_t in = 0; + for (uint8_t i = 0; i < chord_key_count; i++) { + bool found = false; + for (uint8_t j = 0; j < keys_size; j++) { + if (chord_keys[i] == (keys[j] & 0xFF)) { + in++; // detects key in chord + found = true; + break; + } + } + if (found) + continue; + if (chord_keys[i] != 0) { + pass = false; // makes sure rest are blank + } + } + return (pass && (in == keys_size)); +} + +bool process_action_quantum(keyrecord_t *record) { + + /* This gets the keycode from the key pressed */ + keypos_t key = record->event.key; + uint16_t keycode; + + #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS) + uint8_t layer; + + if (record->event.pressed) { + layer = layer_switch_get_layer(key); + update_source_layers_cache(key, layer); + } else { + layer = read_source_layers_cache(key); + } + keycode = keymap_key_to_keycode(layer, key); + #else + keycode = keymap_key_to_keycode(layer_switch_get_layer(key), key); + #endif + + #ifdef AUDIO_ENABLE + if (music_activated) { + if (record->event.pressed) { + play_note(((double)220.0)*pow(2.0, -4.0)*pow(2.0,(starting_note + SCALE[record->event.key.col + offset])/12.0+(MATRIX_ROWS - record->event.key.row)), 0xF); + } else { + stop_note(((double)220.0)*pow(2.0, -4.0)*pow(2.0,(starting_note + SCALE[record->event.key.col + offset])/12.0+(MATRIX_ROWS - record->event.key.row))); + } + if (keycode < 0xFF) // ignores all normal keycodes, but lets RAISE, LOWER, etc through + return false; + } + #endif + + + +#ifndef DISABLE_LEADER + // Leader key set-up + if (record->event.pressed) { + if (!leading && keycode == KC_LEAD) { + leader_start(); + leading = true; + leader_time = timer_read(); + leader_sequence_size = 0; + leader_sequence[0] = 0; + leader_sequence[1] = 0; + leader_sequence[2] = 0; + return false; + } + if (leading && timer_elapsed(leader_time) < LEADER_TIMEOUT) { + leader_sequence[leader_sequence_size] = keycode; + leader_sequence_size++; + return false; + } + } +#endif + +#define DISABLE_CHORDING +#ifndef DISABLE_CHORDING + + if (keycode >= 0x5700 && keycode <= 0x57FF) { + if (record->event.pressed) { + if (!chording) { + chording = true; + for (uint8_t i = 0; i < CHORDING_MAX; i++) + chord_keys[i] = 0; + chord_key_count = 0; + chord_key_down = 0; + } + chord_keys[chord_key_count] = (keycode & 0xFF); + chord_key_count++; + chord_key_down++; + return false; + } else { + if (chording) { + chord_key_down--; + if (chord_key_down == 0) { + chording = false; + // Chord Dictionary + if (keys_chord((uint8_t[]){KC_ENTER, KC_SPACE})) { + register_code(KC_A); + unregister_code(KC_A); + return false; + } + for (uint8_t i = 0; i < chord_key_count; i++) { + register_code(chord_keys[i]); + unregister_code(chord_keys[i]); + return false; + } + } + } + } + } + +#endif + + + return process_action_kb(record); +} + +void matrix_init_quantum() { + matrix_init_kb(); +} + +void matrix_scan_quantum() { + matrix_scan_kb(); +} \ No newline at end of file diff --git a/quantum/quantum.h b/quantum/quantum.h new file mode 100644 index 000000000..db726ad42 --- /dev/null +++ b/quantum/quantum.h @@ -0,0 +1,48 @@ +#ifndef QUANTUM_H +#define QUANTUM_H + +#include "matrix.h" +#include "keymap_common.h" +#ifdef BACKLIGHT_ENABLE + #include "backlight.h" +#endif +#ifdef RGBLIGHT_ENABLE + #include "rgblight.h" +#endif +#ifdef AUDIO_ENABLE + #include "audio.h" +#endif +#ifdef MIDI_ENABLE + #include +#endif +#include "action_layer.h" +#include "eeconfig.h" +#include +#include + +extern uint32_t default_layer_state; + +#ifndef NO_ACTION_LAYER + extern uint32_t layer_state; +#endif + +bool music_activated; + +void matrix_init_kb(void); +void matrix_scan_kb(void); +bool process_action_kb(keyrecord_t *record); + +void leader_start(void); +void leader_end(void); + +#ifndef LEADER_TIMEOUT + #define LEADER_TIMEOUT 200 +#endif +#define SEQ_ONE_KEY(key) if (leader_sequence[0] == (key) && leader_sequence[1] == 0 && leader_sequence[2] == 0) +#define SEQ_TWO_KEYS(key1, key2) if (leader_sequence[0] == (key1) && leader_sequence[1] == (key2) && leader_sequence[2] == 0) +#define SEQ_THREE_KEYS(key1, key2, key3) if (leader_sequence[0] == (key1) && leader_sequence[1] == (key2) && leader_sequence[2] == (key3)) + +#define LEADER_EXTERNS() extern bool leading; extern uint16_t leader_time; extern uint16_t leader_sequence[3]; extern uint8_t leader_sequence_size +#define LEADER_DICTIONARY() if (leading && timer_elapsed(leader_time) > LEADER_TIMEOUT) + +#endif \ No newline at end of file diff --git a/quantum/quantum.mk b/quantum/quantum.mk index 5f4c2f045..b45ad850a 100644 --- a/quantum/quantum.mk +++ b/quantum/quantum.mk @@ -1,7 +1,8 @@ QUANTUM_DIR = quantum # # project specific files -SRC += $(QUANTUM_DIR)/keymap_common.c \ +SRC += $(QUANTUM_DIR)/quantum.c \ + $(QUANTUM_DIR)/keymap_common.c \ $(QUANTUM_DIR)/led.c # ifdef KEYMAP_FILE diff --git a/quantum/template/template.c b/quantum/template/template.c index 6050a2d20..649072eb2 100644 --- a/quantum/template/template.c +++ b/quantum/template/template.c @@ -11,8 +11,9 @@ void matrix_scan_user(void) { } __attribute__ ((weak)) -void process_action_user(keyrecord_t *record) { +bool process_action_user(keyrecord_t *record) { // leave this function blank - it can be defined in a keymap file + return true; } __attribute__ ((weak)) @@ -34,11 +35,11 @@ void matrix_scan_kb(void) { matrix_scan_user(); } -void process_action_kb(keyrecord_t *record) { +bool process_action_kb(keyrecord_t *record) { // put your per-action keyboard code here // runs for every action, just before processing by the firmware - process_action_user(record); + return process_action_user(record); } void led_set_kb(uint8_t usb_led) { diff --git a/quantum/template/template.h b/quantum/template/template.h index 22742105a..8537e3b4b 100644 --- a/quantum/template/template.h +++ b/quantum/template/template.h @@ -24,7 +24,7 @@ void matrix_init_user(void); void matrix_scan_user(void); -void process_action_user(keyrecord_t *record); +bool process_action_user(keyrecord_t *record); void led_set_user(uint8_t usb_led); #endif -- cgit v1.2.3