diff options
Diffstat (limited to 'quantum')
29 files changed, 1972 insertions, 1175 deletions
diff --git a/quantum/audio/song_list.h b/quantum/audio/song_list.h index fc6fcdeef1..8022ca6729 100644 --- a/quantum/audio/song_list.h +++ b/quantum/audio/song_list.h @@ -28,6 +28,14 @@ Q__NOTE(_E4), Q__NOTE(_C4), \ Q__NOTE(_E4), +/* Requires: PLAY_NOTE_ARRAY(..., ..., STACCATO); */ +#define IN_LIKE_FLINT \ + E__NOTE(_AS4), E__NOTE(_AS4), QD_NOTE(_B4), \ + E__NOTE(_AS4), E__NOTE(_B4), QD_NOTE(_CS4), \ + E__NOTE(_B4), E__NOTE(_CS4), QD_NOTE(_DS4), \ + E__NOTE(_CS4), E__NOTE(_B4), QD_NOTE(_AS4), \ + E__NOTE(_AS4), E__NOTE(_AS4), QD_NOTE(_B4), + #define GOODBYE_SOUND \ E__NOTE(_E7), \ E__NOTE(_A6), \ diff --git a/quantum/config_common.h b/quantum/config_common.h index 09a4fe7010..8ed5f4a106 100644 --- a/quantum/config_common.h +++ b/quantum/config_common.h @@ -45,6 +45,15 @@ #define F5 0xF5 #define F6 0xF6 #define F7 0xF7 +#define A0 0x00 +#define A1 0x01 +#define A2 0x02 +#define A3 0x03 +#define A4 0x04 +#define A5 0x05 +#define A6 0x06 +#define A7 0x07 + /* USART configuration */ #ifdef BLUETOOTH_ENABLE diff --git a/quantum/dynamic_macro.h b/quantum/dynamic_macro.h new file mode 100644 index 0000000000..a3ad61bc7e --- /dev/null +++ b/quantum/dynamic_macro.h @@ -0,0 +1,226 @@ +/* Author: Wojciech Siewierski < wojciech dot siewierski at onet dot pl > */ +#ifndef DYNAMIC_MACROS_H +#define DYNAMIC_MACROS_H + +#include "action_layer.h" + +#ifndef DYNAMIC_MACRO_SIZE +/* May be overridden with a custom value. Be aware that the effective + * macro length is half of this value: each keypress is recorded twice + * because of the down-event and up-event. This is not a bug, it's the + * intended behavior. */ +#define DYNAMIC_MACRO_SIZE 256 +#endif + +/* DYNAMIC_MACRO_RANGE must be set as the last element of user's + * "planck_keycodes" enum prior to including this header. This allows + * us to 'extend' it. + */ +enum dynamic_macro_keycodes { + DYN_REC_START1 = DYNAMIC_MACRO_RANGE, + DYN_REC_START2, + DYN_MACRO_PLAY1, + DYN_MACRO_PLAY2, +}; + +/* Blink the LEDs to notify the user about some event. */ +void dynamic_macro_led_blink(void) +{ + backlight_toggle(); + _delay_ms(100); + backlight_toggle(); +} + +/** + * Start recording of the dynamic macro. + * + * @param[out] macro_pointer The new macro buffer iterator. + * @param[in] macro_buffer The macro buffer used to initialize macro_pointer. + */ +void dynamic_macro_record_start( + keyrecord_t **macro_pointer, keyrecord_t *macro_buffer) +{ + dynamic_macro_led_blink(); + + clear_keyboard(); + layer_clear(); + *macro_pointer = macro_buffer; +} + +/** + * Play the dynamic macro. + * + * @param macro_buffer[in] The beginning of the macro buffer being played. + * @param macro_end[in] The element after the last macro buffer element. + * @param direction[in] Either +1 or -1, which way to iterate the buffer. + */ +void dynamic_macro_play( + keyrecord_t *macro_buffer, keyrecord_t *macro_end, int8_t direction) +{ + uint32_t saved_layer_state = layer_state; + + clear_keyboard(); + layer_clear(); + + while (macro_buffer != macro_end) { + process_record(macro_buffer); + macro_buffer += direction; + } + + clear_keyboard(); + + layer_state = saved_layer_state; +} + +/** + * Record a single key in a dynamic macro. + * + * @param macro_pointer[in,out] The current buffer position. + * @param macro_end2[in] The end of the other macro which shouldn't be overwritten. + * @param direction[in] Either +1 or -1, which way to iterate the buffer. + * @param record[in] The current keypress. + */ +void dynamic_macro_record_key( + keyrecord_t **macro_pointer, + keyrecord_t *macro_end2, + int8_t direction, + keyrecord_t *record) +{ + if (*macro_pointer + direction != macro_end2) { + **macro_pointer = *record; + *macro_pointer += direction; + } else { + /* Notify about the end of buffer. The blinks are paired + * because they should happen on both down and up events. */ + backlight_toggle(); + } +} + +/** + * End recording of the dynamic macro. Essentially just update the + * pointer to the end of the macro. + */ +void dynamic_macro_record_end(keyrecord_t *macro_pointer, keyrecord_t **macro_end) +{ + dynamic_macro_led_blink(); + + *macro_end = macro_pointer; +} + +/* Handle the key events related to the dynamic macros. Should be + * called from process_record_user() like this: + * + * bool process_record_user(uint16_t keycode, keyrecord_t *record) { + * if (!process_record_dynamic_macro(keycode, record)) { + * return false; + * } + * <...THE REST OF THE FUNCTION...> + * } + */ +bool process_record_dynamic_macro(uint16_t keycode, keyrecord_t *record) +{ + /* Both macros use the same buffer but read/write on different + * ends of it. + * + * Macro1 is written left-to-right starting from the beginning of + * the buffer. + * + * Macro2 is written right-to-left starting from the end of the + * buffer. + * + * ¯o_buffer macro_end + * v v + * +------------------------------------------------------------+ + * |>>>>>> MACRO1 >>>>>>| |<<<<<<<<<<<<< MACRO2 <<<<<<<<<<<<<| + * +------------------------------------------------------------+ + * ^ ^ + * r_macro_end r_macro_buffer + * + * During the recording when one macro encounters the end of the + * other macro, the recording is stopped. Apart from this, there + * are no arbitrary limits for the macros' length in relation to + * each other: for example one can either have two medium sized + * macros or one long macro and one short macro. Or even one empty + * and one using the whole buffer. + */ + static keyrecord_t macro_buffer[DYNAMIC_MACRO_SIZE]; + + /* Pointer to the first buffer element after the first macro. + * Initially points to the very beginning of the buffer since the + * macro is empty. */ + static keyrecord_t *macro_end = macro_buffer; + + /* The other end of the macro buffer. Serves as the beginning of + * the second macro. */ + static keyrecord_t *const r_macro_buffer = macro_buffer + DYNAMIC_MACRO_SIZE - 1; + + /* Like macro_end but for the second macro. */ + static keyrecord_t *r_macro_end = r_macro_buffer; + + /* A persistent pointer to the current macro position (iterator) + * used during the recording. */ + static keyrecord_t *macro_pointer = NULL; + + /* 0 - no macro is being recorded right now + * 1,2 - either macro 1 or 2 is being recorded */ + static uint8_t macro_id = 0; + + if (macro_id == 0) { + /* No macro recording in progress. */ + if (!record->event.pressed) { + switch (keycode) { + case DYN_REC_START1: + dynamic_macro_record_start(¯o_pointer, macro_buffer); + macro_id = 1; + return false; + case DYN_REC_START2: + dynamic_macro_record_start(¯o_pointer, r_macro_buffer); + macro_id = 2; + return false; + case DYN_MACRO_PLAY1: + dynamic_macro_play(macro_buffer, macro_end, +1); + return false; + case DYN_MACRO_PLAY2: + dynamic_macro_play(r_macro_buffer, r_macro_end, -1); + return false; + } + } + } else { + /* A macro is being recorded right now. */ + switch (keycode) { + case MO(_DYN): + /* Use the layer key used to access the macro recording as + * a stop button. */ + if (record->event.pressed) { /* Ignore the initial release + * just after the recoding + * starts. */ + switch (macro_id) { + case 1: + dynamic_macro_record_end(macro_pointer, ¯o_end); + break; + case 2: + dynamic_macro_record_end(macro_pointer, &r_macro_end); + break; + } + macro_id = 0; + } + return false; + default: + /* Store the key in the macro buffer and process it normally. */ + switch (macro_id) { + case 1: + dynamic_macro_record_key(¯o_pointer, r_macro_end, +1, record); + break; + case 2: + dynamic_macro_record_key(¯o_pointer, macro_end, -1, record); + break; + } + return true; + break; + } + } + + return true; +} + +#endif diff --git a/quantum/keymap.h b/quantum/keymap.h index a158651839..f2d94d75c3 100644 --- a/quantum/keymap.h +++ b/quantum/keymap.h @@ -156,16 +156,16 @@ enum quantum_keycodes { BL_INC, BL_TOGG, BL_STEP, - - // RGB functionality - RGB_TOG, - RGB_MOD, - RGB_HUI, - RGB_HUD, - RGB_SAI, - RGB_SAD, - RGB_VAI, - RGB_VAD, + + // RGB functionality + RGB_TOG, + RGB_MOD, + RGB_HUI, + RGB_HUD, + RGB_SAI, + RGB_SAD, + RGB_VAI, + RGB_VAD, // Left shift, open paren KC_LSPO, @@ -309,7 +309,7 @@ enum quantum_keycodes { #define OSL(layer) (layer | QK_ONE_SHOT_LAYER) // One-shot mod -#define OSM(layer) (layer | QK_ONE_SHOT_MOD) +#define OSM(mod) (mod | QK_ONE_SHOT_MOD) // M-od, T-ap - 256 keycode max #define MT(mod, kc) (kc | QK_MOD_TAP | ((mod & 0xF) << 8)) diff --git a/quantum/keymap_extras/keymap_russian.h b/quantum/keymap_extras/keymap_russian.h new file mode 100644 index 0000000000..237e9abde3 --- /dev/null +++ b/quantum/keymap_extras/keymap_russian.h @@ -0,0 +1,77 @@ +#ifndef KEYMAP_RUSSIAN_H +#define KEYMAP_RUSSIAN_H + +#include "keymap.h" + +// Normal Chracters // reg SHIFT +#define RU_A KC_F // а and А +#define RU_BE KC_COMM // б and Б +#define RU_VE KC_D // в and В +#define RU_GHE KC_U // г and Г +#define RU_DE KC_L // д and Д +#define RU_IE KC_T // е and Е +#define RU_IO KC_GRV // ё and Ё +#define RU_ZHE KC_SCLN // ж and Ж +#define RU_ZE KC_P // з and З +#define RU_I KC_B // и and И +#define RU_SRT_I KC_Q // й and Й +#define RU_KA KC_R // к and К +#define RU_EL KC_K // л and Л +#define RU_EM KC_V // м and М +#define RU_EN KC_Y // н and Н +#define RU_O KC_J // о and О +#define RU_PE KC_G // п and П +#define RU_ER KC_H // р and Р +#define RU_ES KC_C // с and С +#define RU_TE KC_N // т and Т +#define RU_U KC_E // у and У +#define RU_EF KC_A // ф and Ф +#define RU_HA KC_LBRC // х and Х +#define RU_TSE KC_W // ц and Ц +#define RU_CHE KC_X // ч and Ч +#define RU_SHA KC_I // ш and Ш +#define RU_SHCHA KC_O // щ and Щ +#define RU_HSIGN KC_RBRC // ъ and Ъ +#define RU_YERU KC_S // ы and Ы +#define RU_SSIGN KC_M // ь and Ь +#define RU_E KC_QUOT // э and Э +#define RU_YU KC_DOT // ю and Ю +#define RU_YA KC_Z // я and Я + +#define RU_1 KC_1 // 1 and ! +#define RU_2 KC_2 // 2 and " +#define RU_3 KC_3 // 3 and № +#define RU_4 KC_4 // 4 and ; +#define RU_5 KC_5 // 5 and % +#define RU_6 KC_6 // 6 and : +#define RU_7 KC_7 // 7 and ? +#define RU_8 KC_8 // 8 and * +#define RU_9 KC_9 // 9 and ( +#define RU_0 KC_0 // 0 and ) + +#define RU_MINS KC_MINS // - and _ +#define RU_EQL KC_EQL // = and + +#define RU_BSLS KC_BSLS // \ and / +#define RU_DOT KC_SLSH // . and , + +// Shifted Chracters +#define RU_EXLM LSFT(RU_1) // ! +#define RU_DQUT LSFT(RU_2) // " +#define RU_NMRO LSFT(RU_3) // № +#define RU_SCLN LSFT(RU_4) // ; +#define RU_PERC LSFT(RU_5) // % +#define RU_COLN LSFT(RU_6) // : +#define RU_QUES LSFT(RU_7) // ? +#define RU_ASTR LSFT(RU_8) // * +#define RU_LPRN LSFT(RU_9) // ( +#define RU_RPRN LSFT(RU_0) // ) + +#define RU_UNDR LSFT(RU_MINS) // _ +#define RU_PLUS LSFT(RU_EQL) // + +#define RU_SLSH LSFT(RU_BSLS) // / +#define RU_COMM LSFT(RU_DOT) // , + +// Alt Gr-ed characters +#define RU_RUBL RALT(RU_8) // ₽ + +#endif diff --git a/quantum/keymap_extras/keymap_unicode_cyrillic.h b/quantum/keymap_extras/keymap_unicode_cyrillic.h new file mode 100644 index 0000000000..a40626d911 --- /dev/null +++ b/quantum/keymap_extras/keymap_unicode_cyrillic.h @@ -0,0 +1,163 @@ +#ifndef KEYMAP_CYRILLIC_H +#define KEYMAP_CYRILLIC_H + +#include "keymap.h" + +/* + * This is based off of + * https://en.wikipedia.org/wiki/Cyrillic_script + * + * Unicode is iffy, a software implementation is preferred + */ + +// Capital Char russian/ukrainian/bulgarian +#define CY_A UC(0x0410) // А rus ukr bul +#define CY_BE UC(0x0411) // Б rus ukr bul +#define CY_VE UC(0x0412) // В rus ukr bul +#define CY_GHE UC(0x0413) // Г rus ukr bul +#define CY_GHEUP UC(0x0490) // Ґ ukr +#define CY_DE UC(0x0414) // Д rus ukr bul +#define CY_DJE UC(0x0402) // Ђ +#define CY_GJE UC(0x0403) // Ѓ +#define CY_IE UC(0x0415) // Е rus ukr bul +#define CY_IO UC(0x0401) // Ё rus +#define CY_UIE UC(0x0404) // Є ukr +#define CY_ZHE UC(0x0416) // Ж rus ukr bul +#define CY_ZE UC(0x0417) // З rus ukr bul +#define CY_DZE UC(0x0405) // Ѕ +#define CY_I UC(0x0418) // И rus ukr bul +#define CY_B_U_I UC(0x0406) // І ukr +#define CY_YI UC(0x0407) // Ї ukr +#define CY_SRT_I UC(0x0419) // Й rus ukr bul +#define CY_JE UC(0x0408) // Ј +#define CY_KA UC(0x041a) // К rus ukr bul +#define CY_EL UC(0x041b) // Л rus ukr bul +#define CY_LJE UC(0x0409) // Љ +#define CY_EM UC(0x041c) // М rus ukr bul +#define CY_EN UC(0x041d) // Н rus ukr bul +#define CY_NJE UC(0x040a) // Њ +#define CY_O UC(0x041e) // О rus ukr bul +#define CY_PE UC(0x041f) // П rus ukr bul +#define CY_ER UC(0x0420) // Р rus ukr bul +#define CY_ES UC(0x0421) // С rus ukr bul +#define CY_TE UC(0x0422) // Т rus ukr bul +#define CY_TSHE UC(0x040b) // Ћ +#define CY_KJE UC(0x040c) // Ќ +#define CY_U UC(0x0423) // У rus ukr bul +#define CY_SRT_U UC(0x040e) // Ў +#define CY_EF UC(0x0424) // Ф rus ukr bul +#define CY_HA UC(0x0425) // Х rus bul +#define CY_TSE UC(0x0426) // Ц rus ukr bul +#define CY_CHE UC(0x0427) // Ч rus ukr bul +#define CY_DZHE UC(0x040f) // Џ +#define CY_SHA UC(0x0428) // Ш rus ukr bul +#define CY_SHCHA UC(0x0429) // Щ rus ukr bul +#define CY_HSIGN UC(0x042a) // Ъ rus bul +#define CY_YERU UC(0x042b) // Ы rus +#define CY_SSIGN UC(0x042c) // Ь rus ukr bul +#define CY_E UC(0x042d) // Э rus +#define CY_YU UC(0x042e) // Ю rus ukr bul +#define CY_YA UC(0x042f) // Я rus ukr bul +// Important Cyrillic non-Slavic letters +#define CY_PALOCHKA UC(0x04c0) // Ӏ +#define CY_SCHWA UC(0x04d8) // Ә +#define CY_GHE_S UC(0x0492) // Ғ +#define CY_ZE_D UC(0x0498) // Ҙ +#define CY_ES_D UC(0x04aa) // Ҫ +#define CY_BR_KA UC(0x04a0) // Ҡ +#define CY_ZHE_D UC(0x0496) // Җ +#define CY_KA_D UC(0x049a) // Қ +#define CY_EN_D UC(0x04a2) // Ң +#define CY_ENGHE UC(0x04a4) // Ҥ +#define CY_BRD_O UC(0x04e8) // Ө +#define CY_STR_U UC(0x04ae) // Ү +#define CY_S_U_S UC(0x04b0) // Ұ +#define CY_SHHA UC(0x04ba) // Һ +#define CY_HA_D UC(0x04b2) // Ҳ + + +// Small +#define CY_a UC(0x0430) // a rus ukr bul +#define CY_be UC(0x0431) // б rus ukr bul +#define CY_ve UC(0x0432) // в rus ukr bul +#define CY_ghe UC(0x0433) // г rus ukr bul +#define CY_gheup UC(0x0491) // ґ ukr +#define CY_de UC(0x0434) // д rus ukr bul +#define CY_dje UC(0x0452) // ђ +#define CY_gje UC(0x0453) // ѓ +#define CY_ie UC(0x0435) // е rus ukr bul +#define CY_io UC(0x0451) // ё rus +#define CY_uie UC(0x0454) // є ukr +#define CY_zhe UC(0x0436) // ж rus ukr bul +#define CY_ze UC(0x0437) // з rus ukr bul +#define CY_dze UC(0x0455) // ѕ +#define CY_i UC(0x0438) // и rus ukr bul +#define CY_b_u_i UC(0x0456) // і ukr +#define CY_yi UC(0x0457) // ї ukr +#define CY_srt_i UC(0x0439) // й rus ukr bul +#define CY_je UC(0x0458) // ј +#define CY_ka UC(0x043a) // к rus ukr bul +#define CY_el UC(0x043b) // л rus ukr bul +#define CY_lje UC(0x0459) // љ +#define CY_em UC(0x043c) // м rus ukr bul +#define CY_en UC(0x043d) // н rus ukr bul +#define CY_nje UC(0x045a) // њ +#define CY_o UC(0x043e) // о rus ukr bul +#define CY_pe UC(0x043f) // п rus ukr bul +#define CY_er UC(0x0440) // р rus ukr bul +#define CY_es UC(0x0441) // с rus ukr bul +#define CY_te UC(0x0442) // т rus ukr bul +#define CY_tshe UC(0x045b) // ћ +#define CY_kje UC(0x045c) // ќ +#define CY_u UC(0x0443) // у rus ukr bul +#define CY_srt_u UC(0x045e) // ў +#define CY_ef UC(0x0444) // ф rus ukr bul +#define CY_ha UC(0x0445) // х rus ukr bul +#define CY_tse UC(0x0446) // ц rus ukr bul +#define CY_che UC(0x0447) // ч rus ukr bul +#define CY_dzhe UC(0x045f) // џ +#define CY_sha UC(0x0448) // ш rus ukr bul +#define CY_shcha UC(0x0449) // щ rus ukr bul +#define CY_hsign UC(0x044a) // ъ rus bul +#define CY_yeru UC(0x044b) // ы rus +#define CY_ssign UC(0x044c) // ь rus ukr bul +#define CY_e UC(0x044d) // э rus +#define CY_yu UC(0x044e) // ю rus ukr bul +#define CY_ya UC(0x044f) // я rus ukr bul +// Important Cyrillic non-Slavic letters +#define CY_palochka UC(0x04cf) // ӏ +#define CY_schwa UC(0x04d9) // ә +#define CY_ghe_s UC(0x0493) // ғ +#define CY_ze_d UC(0x0499) // ҙ +#define CY_es_d UC(0x04ab) // ҫ +#define CY_br_ka UC(0x04a1) // ҡ +#define CY_zhe_d UC(0x0497) // җ +#define CY_ka_d UC(0x049b) // қ +#define CY_en_d UC(0x04a3) // ң +#define CY_enghe UC(0x04a5) // ҥ +#define CY_brd_o UC(0x04e9) // ө +#define CY_str_u UC(0x04af) // ү +#define CY_s_u_s UC(0x04b1) // ұ +#define CY_shha UC(0x04bb) // һ +#define CY_ha_d UC(0x04b3) // ҳ + + +// Extra +#define CY_slr_ve UC(0x1c80) // ᲀ CYRILLIC SMALL LETTER ROUNDED VE +#define CY_ll_de UC(0x1c81) // ᲁ CYRILLIC SMALL LETTER LONG-LEGGED DE +#define CY_ZEMLYA UC(0xa640) // Ꙁ CYRILLIC CAPITAL LETTER ZEMLYA +#define CY_zemlya UC(0xa641) // ꙁ CYRILLIC SMALL LETTER ZEMLYA +#define CY_RV_DZE UC(0xa644) // Ꙅ CYRILLIC CAPITAL LETTER REVERSED DZE +#define CY_rv_DZE UC(0xa645) // ꙅ CYRILLIC SMALL LETTER REVERSED DZE +#define CY_slw_es UC(0x1c83) // ᲃ CYRILLIC SMALL LETTER WIDE ES +#define CY_st_te UC(0x1c84) // ᲄ CYRILLIC SMALL LETTER TALL TE +#define CY_3l_te UC(0x1c85) // ᲅ CYRILLIC SMALL LETTER THREE-LEGGED TE +#define CY_thsign UC(0x1c86) // ᲆ CYRILLIC SMALL LETTER TALL HARD SIGN +#define CY_YERUBY UC(0xa650) // Ꙑ CYRILLIC CAPITAL LETTER YERU WITH BACK YER +#define CY_yeruby UC(0xa651) // ꙑ CYRILLIC SMALL LETTER YERU WITH BACK YER +#define CY_RUBL UC(0x20bd) // ₽ +#define CY_NMRO UC(0x2116) // № + +// The letters Zje and Sje are made for other letters and accent marks + +#endif diff --git a/quantum/process_keycode/process_tap_dance.c b/quantum/process_keycode/process_tap_dance.c index d240dc2e66..07de3ecb8f 100644 --- a/quantum/process_keycode/process_tap_dance.c +++ b/quantum/process_keycode/process_tap_dance.c @@ -1,14 +1,16 @@ #include "quantum.h" +#include "action_tapping.h" -static qk_tap_dance_state_t qk_tap_dance_state; +static uint16_t last_td; +static int8_t highest_td = -1; void qk_tap_dance_pair_finished (qk_tap_dance_state_t *state, void *user_data) { qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data; if (state->count == 1) { - register_code (pair->kc1); + register_code16 (pair->kc1); } else if (state->count == 2) { - register_code (pair->kc2); + register_code16 (pair->kc2); } } @@ -16,102 +18,117 @@ void qk_tap_dance_pair_reset (qk_tap_dance_state_t *state, void *user_data) { qk_tap_dance_pair_t *pair = (qk_tap_dance_pair_t *)user_data; if (state->count == 1) { - unregister_code (pair->kc1); + unregister_code16 (pair->kc1); } else if (state->count == 2) { - unregister_code (pair->kc2); + unregister_code16 (pair->kc2); } } static inline void _process_tap_dance_action_fn (qk_tap_dance_state_t *state, - void *user_data, - qk_tap_dance_user_fn_t fn) + void *user_data, + qk_tap_dance_user_fn_t fn) { if (fn) { fn(state, user_data); } } -static inline void process_tap_dance_action_on_each_tap (qk_tap_dance_action_t action) +static inline void process_tap_dance_action_on_each_tap (qk_tap_dance_action_t *action) { - _process_tap_dance_action_fn (&qk_tap_dance_state, action.user_data, action.fn.on_each_tap); + _process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_each_tap); } -static inline void process_tap_dance_action_on_dance_finished (qk_tap_dance_action_t action) +static inline void process_tap_dance_action_on_dance_finished (qk_tap_dance_action_t *action) { - _process_tap_dance_action_fn (&qk_tap_dance_state, action.user_data, action.fn.on_dance_finished); + if (action->state.finished) + return; + action->state.finished = true; + _process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_dance_finished); } -static inline void process_tap_dance_action_on_reset (qk_tap_dance_action_t action) +static inline void process_tap_dance_action_on_reset (qk_tap_dance_action_t *action) { - _process_tap_dance_action_fn (&qk_tap_dance_state, action.user_data, action.fn.on_reset); + _process_tap_dance_action_fn (&action->state, action->user_data, action->fn.on_reset); } bool process_tap_dance(uint16_t keycode, keyrecord_t *record) { - bool r = true; uint16_t idx = keycode - QK_TAP_DANCE; - qk_tap_dance_action_t action; + qk_tap_dance_action_t *action; + + if (last_td && last_td != keycode) { + (&tap_dance_actions[last_td - QK_TAP_DANCE])->state.interrupted = true; + } switch(keycode) { case QK_TAP_DANCE ... QK_TAP_DANCE_MAX: - action = tap_dance_actions[idx]; + if ((int16_t)idx > highest_td) + highest_td = idx; + action = &tap_dance_actions[idx]; - process_tap_dance_action_on_each_tap (action); - if (qk_tap_dance_state.keycode && qk_tap_dance_state.keycode != keycode) { - process_tap_dance_action_on_dance_finished (action); - } else if (qk_tap_dance_state.active && qk_tap_dance_state.pressed) { - reset_tap_dance (&qk_tap_dance_state); - } else { - r = false; - } - - qk_tap_dance_state.active = true; - qk_tap_dance_state.pressed = record->event.pressed; + action->state.keycode = keycode; + action->state.pressed = record->event.pressed; if (record->event.pressed) { - qk_tap_dance_state.keycode = keycode; - qk_tap_dance_state.timer = timer_read (); - qk_tap_dance_state.count++; + action->state.count++; + action->state.timer = timer_read(); + + if (last_td && last_td != keycode) { + qk_tap_dance_action_t *paction = &tap_dance_actions[last_td - QK_TAP_DANCE]; + paction->state.interrupted = true; + process_tap_dance_action_on_dance_finished (paction); + reset_tap_dance (&paction->state); + } } + last_td = keycode; + break; default: - if (qk_tap_dance_state.keycode) { - // if we are here, the tap dance was interrupted by a different key - idx = qk_tap_dance_state.keycode - QK_TAP_DANCE; - action = tap_dance_actions[idx]; + if (!record->event.pressed) + return true; - process_tap_dance_action_on_each_tap (action); + if (highest_td == -1) + return true; + + for (int i = 0; i <= highest_td; i++) { + action = &tap_dance_actions[i]; + if (action->state.count == 0) + continue; + action->state.interrupted = true; process_tap_dance_action_on_dance_finished (action); - reset_tap_dance (&qk_tap_dance_state); - qk_tap_dance_state.active = false; + reset_tap_dance (&action->state); } break; } - return r; + return true; } void matrix_scan_tap_dance () { - if (qk_tap_dance_state.active && timer_elapsed (qk_tap_dance_state.timer) > TAPPING_TERM) { - // if we are here, the tap dance was timed out - uint16_t idx = qk_tap_dance_state.keycode - QK_TAP_DANCE; - qk_tap_dance_action_t action = tap_dance_actions[idx]; + if (highest_td == -1) + return; + + for (int i = 0; i <= highest_td; i++) { + qk_tap_dance_action_t *action = &tap_dance_actions[i]; - process_tap_dance_action_on_dance_finished (action); - reset_tap_dance (&qk_tap_dance_state); + if (action->state.count && timer_elapsed (action->state.timer) > TAPPING_TERM) { + process_tap_dance_action_on_dance_finished (action); + reset_tap_dance (&action->state); + } } } void reset_tap_dance (qk_tap_dance_state_t *state) { - uint16_t idx = state->keycode - QK_TAP_DANCE; - qk_tap_dance_action_t action; + qk_tap_dance_action_t *action; if (state->pressed) return; - action = tap_dance_actions[idx]; + action = &tap_dance_actions[state->keycode - QK_TAP_DANCE]; + process_tap_dance_action_on_reset (action); - state->keycode = 0; state->count = 0; - state->active = false; + state->interrupted = false; + state->finished = false; + last_td = 0; } diff --git a/quantum/process_keycode/process_tap_dance.h b/quantum/process_keycode/process_tap_dance.h index e2c74efe91..d7b857bdc6 100644 --- a/quantum/process_keycode/process_tap_dance.h +++ b/quantum/process_keycode/process_tap_dance.h @@ -11,8 +11,9 @@ typedef struct uint8_t count; uint16_t keycode; uint16_t timer; - bool active:1; - bool pressed:1; + bool interrupted; + bool pressed; + bool finished; } qk_tap_dance_state_t; #define TD(n) (QK_TAP_DANCE + n) @@ -26,6 +27,7 @@ typedef struct qk_tap_dance_user_fn_t on_dance_finished; qk_tap_dance_user_fn_t on_reset; } fn; + qk_tap_dance_state_t state; void *user_data; } qk_tap_dance_action_t; @@ -48,7 +50,7 @@ typedef struct .fn = { user_fn_on_each_tap, user_fn_on_dance_finished, user_fn_on_reset } \ } -extern const qk_tap_dance_action_t tap_dance_actions[]; +extern qk_tap_dance_action_t tap_dance_actions[]; /* To be used internally */ diff --git a/quantum/process_keycode/process_unicode.c b/quantum/process_keycode/process_unicode.c index ad5d7f86b7..06c1694f2e 100644 --- a/quantum/process_keycode/process_unicode.c +++ b/quantum/process_keycode/process_unicode.c @@ -13,45 +13,196 @@ uint16_t hex_to_keycode(uint8_t hex) } } -void set_unicode_mode(uint8_t os_target) +void set_unicode_input_mode(uint8_t os_target) { input_mode = os_target; } +__attribute__((weak)) +void unicode_input_start (void) { + switch(input_mode) { + case UC_OSX: + register_code(KC_LALT); + break; + case UC_LNX: + register_code(KC_LCTL); + register_code(KC_LSFT); + register_code(KC_U); + unregister_code(KC_U); + unregister_code(KC_LSFT); + unregister_code(KC_LCTL); + break; + case UC_WIN: + register_code(KC_LALT); + register_code(KC_PPLS); + unregister_code(KC_PPLS); + break; + } + wait_ms(UNICODE_TYPE_DELAY); +} + +__attribute__((weak)) +void unicode_input_finish (void) { + switch(input_mode) { + case UC_OSX: + case UC_WIN: + unregister_code(KC_LALT); + break; + case UC_LNX: + register_code(KC_SPC); + unregister_code(KC_SPC); + break; + } +} + +void register_hex(uint16_t hex) { + for(int i = 3; i >= 0; i--) { + uint8_t digit = ((hex >> (i*4)) & 0xF); + register_code(hex_to_keycode(digit)); + unregister_code(hex_to_keycode(digit)); + } +} + bool process_unicode(uint16_t keycode, keyrecord_t *record) { if (keycode > QK_UNICODE && record->event.pressed |