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 boolpull/330/head^2
							parent
							
								
									79d26f331a
								
							
						
					
					
						commit
						1a8c0dd22d
					
				| @ -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(); | ||||
| } | ||||
| @ -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 <keymap_midi.h> | ||||
| #endif | ||||
| #include "action_layer.h" | ||||
| #include "eeconfig.h" | ||||
| #include <stddef.h> | ||||
| #include <avr/io.h> | ||||
| 
 | ||||
| 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 | ||||
					Loading…
					
					
				
		Reference in new issue
	
	 Erez Zukerman
						Erez Zukerman