diff --git a/quantum/dynamic_keymap.c b/quantum/dynamic_keymap.c index d7658c2084..2fb37cf634 100644 --- a/quantum/dynamic_keymap.c +++ b/quantum/dynamic_keymap.c @@ -86,6 +86,7 @@ static pin_t encoders_pad_a[] = ENCODERS_PAD_A; #define VIAL_QMK_SETTINGS_SIZE 0 #endif +// Tap-dance #define VIAL_TAP_DANCE_EEPROM_ADDR (VIAL_QMK_SETTINGS_EEPROM_ADDR + VIAL_QMK_SETTINGS_SIZE) #ifdef VIAL_TAP_DANCE_ENABLE @@ -94,9 +95,18 @@ static pin_t encoders_pad_a[] = ENCODERS_PAD_A; #define VIAL_TAP_DANCE_SIZE 0 #endif -// Dynamic macro starts after tap-dance +// Combos +#define VIAL_COMBO_EEPROM_ADDR (VIAL_TAP_DANCE_EEPROM_ADDR + VIAL_TAP_DANCE_SIZE) + +#ifdef VIAL_COMBO_ENABLE +#define VIAL_COMBO_SIZE (sizeof(vial_combo_entry_t) * VIAL_COMBO_ENTRIES) +#else +#define VIAL_COMBO_SIZE 0 +#endif + +// Dynamic macro #ifndef DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR -# define DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR (VIAL_TAP_DANCE_EEPROM_ADDR + VIAL_TAP_DANCE_SIZE) +# define DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR (VIAL_COMBO_EEPROM_ADDR + VIAL_COMBO_SIZE) #endif // Sanity check that dynamic keymaps fit in available EEPROM @@ -104,7 +114,7 @@ static pin_t encoders_pad_a[] = ENCODERS_PAD_A; // The keyboard should override DYNAMIC_KEYMAP_LAYER_COUNT to reduce it, // or DYNAMIC_KEYMAP_EEPROM_MAX_ADDR to increase it, *only if* the microcontroller has // more than the default. -_Static_assert(DYNAMIC_KEYMAP_EEPROM_MAX_ADDR - DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR >= 100, "Dynamic keymaps are configured to use more EEPROM than is available."); +_Static_assert(DYNAMIC_KEYMAP_EEPROM_MAX_ADDR >= DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR + 100, "Dynamic keymaps are configured to use more EEPROM than is available."); // Dynamic macros are stored after the keymaps and use what is available // up to and including DYNAMIC_KEYMAP_EEPROM_MAX_ADDR. @@ -215,6 +225,28 @@ int dynamic_keymap_set_tap_dance(uint8_t index, const vial_tap_dance_entry_t *en } #endif +#ifdef VIAL_COMBO_ENABLE +int dynamic_keymap_get_combo(uint8_t index, vial_combo_entry_t *entry) { + if (index >= VIAL_COMBO_ENTRIES) + return -1; + + void *address = (void*)(VIAL_COMBO_EEPROM_ADDR + index * sizeof(vial_combo_entry_t)); + eeprom_read_block(entry, address, sizeof(vial_combo_entry_t)); + + return 0; +} + +int dynamic_keymap_set_combo(uint8_t index, const vial_combo_entry_t *entry) { + if (index >= VIAL_COMBO_ENTRIES) + return -1; + + void *address = (void*)(VIAL_COMBO_EEPROM_ADDR + index * sizeof(vial_combo_entry_t)); + eeprom_write_block(entry, address, sizeof(vial_combo_entry_t)); + + return 0; +} +#endif + #if defined(VIAL_ENCODERS_ENABLE) && defined(VIAL_ENCODER_DEFAULT) static const uint16_t PROGMEM vial_encoder_default[] = VIAL_ENCODER_DEFAULT; _Static_assert(sizeof(vial_encoder_default)/sizeof(*vial_encoder_default) == 2 * DYNAMIC_KEYMAP_LAYER_COUNT * NUMBER_OF_ENCODERS, @@ -262,6 +294,12 @@ void dynamic_keymap_reset(void) { } #endif +#ifdef VIAL_COMBO_ENABLE + vial_combo_entry_t combo = { 0 }; + for (size_t i = 0; i < VIAL_COMBO_ENTRIES; ++i) + dynamic_keymap_set_combo(i, &combo); +#endif + #ifdef VIAL_ENABLE /* re-lock the keyboard */ vial_unlocked = vial_unlocked_prev; diff --git a/quantum/dynamic_keymap.h b/quantum/dynamic_keymap.h index 7fd092caed..5114cbe46a 100644 --- a/quantum/dynamic_keymap.h +++ b/quantum/dynamic_keymap.h @@ -38,6 +38,10 @@ void dynamic_keymap_set_qmk_settings(uint16_t offset, uint8_t value); int dynamic_keymap_get_tap_dance(uint8_t index, vial_tap_dance_entry_t *entry); int dynamic_keymap_set_tap_dance(uint8_t index, const vial_tap_dance_entry_t *entry); #endif +#ifdef VIAL_COMBO_ENABLE +int dynamic_keymap_get_combo(uint8_t index, vial_combo_entry_t *entry); +int dynamic_keymap_set_combo(uint8_t index, const vial_combo_entry_t *entry); +#endif void dynamic_keymap_reset(void); // These get/set the keycodes as stored in the EEPROM buffer // Data is big-endian 16-bit values (the keycodes) diff --git a/quantum/process_keycode/process_combo.c b/quantum/process_keycode/process_combo.c index d2f52edd2e..b844b565b4 100644 --- a/quantum/process_keycode/process_combo.c +++ b/quantum/process_keycode/process_combo.c @@ -17,6 +17,10 @@ #include "print.h" #include "process_combo.h" +#ifdef VIAL_COMBO_ENABLE +#include "dynamic_keymap.h" +#endif + #ifndef COMBO_VARIABLE_LEN __attribute__((weak)) combo_t key_combos[COMBO_COUNT] = {}; #else @@ -84,12 +88,27 @@ static inline void dump_key_buffer(bool emit) { static bool process_single_combo(combo_t *combo, uint16_t keycode, keyrecord_t *record) { uint8_t count = 0; uint16_t index = -1; +#ifdef VIAL_COMBO_ENABLE + uint8_t combo_idx = (uintptr_t)combo->keys; + vial_combo_entry_t entry; + if (dynamic_keymap_get_combo(combo_idx, &entry) != 0) + return false; + for (count = 0; count < sizeof(entry.input)/sizeof(*entry.input); ++count) { + uint16_t key = entry.input[count]; + if (key == KC_NO) break; + if (key == keycode) index = count; + } + /* must have at least 2 keys in the combo */ + if (count < 2) + return false; +#else /* Find index of keycode and number of combo keys */ for (const uint16_t *keys = combo->keys;; ++count) { uint16_t key = pgm_read_word(&keys[count]); if (keycode == key) index = count; if (COMBO_END == key) break; } +#endif /* Continue processing if not a combo key */ if (-1 == (int8_t)index) return false; diff --git a/quantum/vial.c b/quantum/vial.c index 9619fbb967..601008bd4f 100644 --- a/quantum/vial.c +++ b/quantum/vial.c @@ -58,10 +58,17 @@ _Static_assert(sizeof(vial_unlock_combo_rows) == sizeof(vial_unlock_combo_cols), static void reload_tap_dance(void); #endif +#ifdef VIAL_COMBO_ENABLE +static void init_combo(void); +#endif + void vial_init(void) { #ifdef VIAL_TAP_DANCE_ENABLE reload_tap_dance(); #endif +#ifdef VIAL_COMBO_ENABLE + init_combo(); +#endif } void vial_handle_cmd(uint8_t *msg, uint8_t length) { @@ -218,6 +225,20 @@ void vial_handle_cmd(uint8_t *msg, uint8_t length) { reload_tap_dance(); break; } + case dynamic_vial_combo_get: { + uint8_t idx = msg[3]; + vial_combo_entry_t entry = { 0 }; + msg[0] = dynamic_keymap_get_combo(idx, &entry); + memcpy(&msg[1], &entry, sizeof(entry)); + break; + } + case dynamic_vial_combo_set: { + uint8_t idx = msg[3]; + vial_combo_entry_t entry; + memcpy(&entry, &msg[4], sizeof(entry)); + msg[0] = dynamic_keymap_set_combo(idx, &entry); + break; + } } break; @@ -462,15 +483,23 @@ static void reload_tap_dance(void) { #endif #ifdef VIAL_COMBO_ENABLE -const uint16_t PROGMEM test_combo[] = {KC_X, KC_Z, COMBO_END}; -combo_t key_combos[COMBO_COUNT] = {COMBO_ACTION(test_combo)}; +combo_t key_combos[VIAL_COMBO_ENTRIES]; + +static void init_combo(void) { + for (size_t i = 0; i < VIAL_COMBO_ENTRIES; ++i) { + key_combos[i].keys = (void*)(uintptr_t)i; + } +} void process_combo_event(uint16_t combo_index, bool pressed) { - uprintf("combo event %d\n", combo_index); + vial_combo_entry_t entry; + if (dynamic_keymap_get_combo(combo_index, &entry) != 0) + return; + if (pressed) - vial_keycode_down(0x5F12); + vial_keycode_down(entry.output); else - vial_keycode_up(0x5F12); + vial_keycode_up(entry.output); } #endif diff --git a/quantum/vial.h b/quantum/vial.h index 968f878ef3..dc17bcd93e 100644 --- a/quantum/vial.h +++ b/quantum/vial.h @@ -52,6 +52,8 @@ enum { dynamic_vial_get_number_of_entries = 0x00, dynamic_vial_tap_dance_get = 0x01, dynamic_vial_tap_dance_set = 0x02, + dynamic_vial_combo_get = 0x03, + dynamic_vial_combo_set = 0x04, }; /* Fake position in keyboard matrix, can't use 255 as that is immediately rejected by IS_NOEVENT @@ -87,6 +89,12 @@ _Static_assert(sizeof(vial_tap_dance_entry_t) == 10, "Unexpected size of the via #define VIAL_COMBO_ENTRIES 16 #endif +typedef struct { + uint16_t input[4]; + uint16_t output; +} vial_combo_entry_t; +_Static_assert(sizeof(vial_combo_entry_t) == 10, "Unexpected size of the vial_combo_entry_t structure"); + /* also to catch wrong include order in e.g. process_combo.h */ #ifdef COMBO_COUNT #error COMBO_COUNT redefined - define VIAL_COMBO_ENTRIES instead