From 53a41dcfab6225422eb10e469b6ac613ac8fae31 Mon Sep 17 00:00:00 2001 From: Ilya Zhuravlev Date: Thu, 30 Sep 2021 13:16:41 -0400 Subject: [PATCH] Add dynamic key overrides support --- builddefs/common_features.mk | 1 + quantum/dynamic_keymap.c | 41 ++++++++++++++++++++- quantum/dynamic_keymap.h | 4 +++ quantum/vial.c | 70 ++++++++++++++++++++++++++++++++++++ quantum/vial.h | 51 +++++++++++++++++++++++++- 5 files changed, 165 insertions(+), 2 deletions(-) diff --git a/builddefs/common_features.mk b/builddefs/common_features.mk index 0bc32c537c..4819f66787 100644 --- a/builddefs/common_features.mk +++ b/builddefs/common_features.mk @@ -555,6 +555,7 @@ ifeq ($(strip $(VIAL_ENABLE)), yes) QMK_SETTINGS ?= yes TAP_DANCE_ENABLE ?= yes COMBO_ENABLE ?= yes + KEY_OVERRIDE_ENABLE ?= yes SRC += $(QUANTUM_DIR)/vial.c EXTRAINCDIRS += $(KEYMAP_OUTPUT) OPT_DEFS += -DVIAL_ENABLE -DNO_DEBUG -DSERIAL_NUMBER=\"vial:f64c2b3c\" diff --git a/quantum/dynamic_keymap.c b/quantum/dynamic_keymap.c index 85f242ee8d..12df47244a 100644 --- a/quantum/dynamic_keymap.c +++ b/quantum/dynamic_keymap.c @@ -101,9 +101,18 @@ static pin_t encoders_pad_a[] = ENCODERS_PAD_A; #define VIAL_COMBO_SIZE 0 #endif +// Key overrides +#define VIAL_KEY_OVERRIDE_EEPROM_ADDR (VIAL_COMBO_EEPROM_ADDR + VIAL_COMBO_SIZE) + +#ifdef VIAL_KEY_OVERRIDE_ENABLE +#define VIAL_KEY_OVERRIDE_SIZE (sizeof(vial_key_override_entry_t) * VIAL_KEY_OVERRIDE_ENTRIES) +#else +#define VIAL_KEY_OVERRIDE_SIZE 0 +#endif + // Dynamic macro #ifndef DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR -# define DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR (VIAL_COMBO_EEPROM_ADDR + VIAL_COMBO_SIZE) +# define DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR (VIAL_KEY_OVERRIDE_EEPROM_ADDR + VIAL_KEY_OVERRIDE_SIZE) #endif // Sanity check that dynamic keymaps fit in available EEPROM @@ -246,6 +255,28 @@ int dynamic_keymap_set_combo(uint8_t index, const vial_combo_entry_t *entry) { } #endif +#ifdef VIAL_KEY_OVERRIDE_ENABLE +int dynamic_keymap_get_key_override(uint8_t index, vial_key_override_entry_t *entry) { + if (index >= VIAL_KEY_OVERRIDE_ENTRIES) + return -1; + + void *address = (void*)(VIAL_KEY_OVERRIDE_EEPROM_ADDR + index * sizeof(vial_key_override_entry_t)); + eeprom_read_block(entry, address, sizeof(vial_key_override_entry_t)); + + return 0; +} + +int dynamic_keymap_set_key_override(uint8_t index, const vial_key_override_entry_t *entry) { + if (index >= VIAL_KEY_OVERRIDE_ENTRIES) + return -1; + + void *address = (void*)(VIAL_KEY_OVERRIDE_EEPROM_ADDR + index * sizeof(vial_key_override_entry_t)); + eeprom_write_block(entry, address, sizeof(vial_key_override_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, @@ -299,6 +330,14 @@ void dynamic_keymap_reset(void) { dynamic_keymap_set_combo(i, &combo); #endif +#ifdef VIAL_KEY_OVERRIDE_ENABLE + vial_key_override_entry_t ko = { 0 }; + ko.layers = ~0; + ko.options = vial_ko_option_activation_negative_mod_up | vial_ko_option_activation_required_mod_down | vial_ko_option_activation_trigger_down; + for (size_t i = 0; i < VIAL_KEY_OVERRIDE_ENTRIES; ++i) + dynamic_keymap_set_key_override(i, &ko); +#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 023af87ea7..3d2ed4e624 100644 --- a/quantum/dynamic_keymap.h +++ b/quantum/dynamic_keymap.h @@ -46,6 +46,10 @@ int dynamic_keymap_set_tap_dance(uint8_t index, const vial_tap_dance_entry_t *en 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 +#ifdef VIAL_KEY_OVERRIDE_ENABLE +int dynamic_keymap_get_key_override(uint8_t index, vial_key_override_entry_t *entry); +int dynamic_keymap_set_key_override(uint8_t index, const vial_key_override_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/vial.c b/quantum/vial.c index da2ce56b10..6684cc856c 100644 --- a/quantum/vial.c +++ b/quantum/vial.c @@ -58,6 +58,10 @@ static void reload_tap_dance(void); static void reload_combo(void); #endif +#ifdef VIAL_KEY_OVERRIDE_ENABLE +static void reload_key_override(void); +#endif + void vial_init(void) { #ifdef VIAL_TAP_DANCE_ENABLE reload_tap_dance(); @@ -65,6 +69,9 @@ void vial_init(void) { #ifdef VIAL_COMBO_ENABLE reload_combo(); #endif +#ifdef VIAL_KEY_OVERRIDE_ENABLE + reload_key_override(); +#endif } void vial_handle_cmd(uint8_t *msg, uint8_t length) { @@ -214,6 +221,7 @@ void vial_handle_cmd(uint8_t *msg, uint8_t length) { memset(msg, 0, length); msg[0] = VIAL_TAP_DANCE_ENTRIES; msg[1] = VIAL_COMBO_ENTRIES; + msg[2] = VIAL_KEY_OVERRIDE_ENTRIES; break; } #ifdef VIAL_TAP_DANCE_ENABLE @@ -249,6 +257,23 @@ void vial_handle_cmd(uint8_t *msg, uint8_t length) { reload_combo(); break; } +#endif +#ifdef VIAL_KEY_OVERRIDE_ENABLE + case dynamic_vial_key_override_get: { + uint8_t idx = msg[3]; + vial_key_override_entry_t entry = { 0 }; + msg[0] = dynamic_keymap_get_key_override(idx, &entry); + memcpy(&msg[1], &entry, sizeof(entry)); + break; + } + case dynamic_vial_key_override_set: { + uint8_t idx = msg[3]; + vial_key_override_entry_t entry; + memcpy(&entry, &msg[4], sizeof(entry)); + msg[0] = dynamic_keymap_set_key_override(idx, &entry); + reload_key_override(); + break; + } #endif } @@ -544,3 +569,48 @@ bool process_record_vial(uint16_t keycode, keyrecord_t *record) { return true; } + +#ifdef VIAL_KEY_OVERRIDE_ENABLE +static bool vial_key_override_disabled = 0; +static key_override_t overrides[VIAL_KEY_OVERRIDE_ENTRIES] = { 0 }; +static key_override_t *override_ptrs[VIAL_KEY_OVERRIDE_ENTRIES + 1] = { 0 }; +const key_override_t **key_overrides = (const key_override_t**)override_ptrs; + +static int vial_get_key_override(uint8_t index, key_override_t *out) { + vial_key_override_entry_t entry; + int ret; + if ((ret = dynamic_keymap_get_key_override(index, &entry)) != 0) + return ret; + + memset(out, 0, sizeof(*out)); + out->trigger = entry.trigger; + out->trigger_mods = entry.trigger_mods; + out->layers = entry.layers; + out->negative_mod_mask = entry.negative_mod_mask; + out->suppressed_mods = entry.suppressed_mods; + out->replacement = entry.replacement; + out->options = 0; + uint8_t opt = entry.options; + if (opt & vial_ko_enabled) + out->enabled = NULL; + else + out->enabled = &vial_key_override_disabled; + /* right now these options match one-to-one so this isn't strictly necessary, + nevertheless future-proof the code by parsing them out to ensure "stable" abi */ + if (opt & vial_ko_option_activation_trigger_down) out->options |= ko_option_activation_trigger_down; + if (opt & vial_ko_option_activation_required_mod_down) out->options |= ko_option_activation_required_mod_down; + if (opt & vial_ko_option_activation_negative_mod_up) out->options |= ko_option_activation_negative_mod_up; + if (opt & vial_ko_option_one_mod) out->options |= ko_option_one_mod; + if (opt & vial_ko_option_no_reregister_trigger) out->options |= ko_option_no_reregister_trigger; + if (opt & vial_ko_option_no_unregister_on_other_key_down) out->options |= ko_option_no_unregister_on_other_key_down; + + return 0; +} + +static void reload_key_override(void) { + for (size_t i = 0; i < VIAL_KEY_OVERRIDE_ENTRIES; ++i) { + override_ptrs[i] = &overrides[i]; + vial_get_key_override(i, &overrides[i]); + } +} +#endif diff --git a/quantum/vial.h b/quantum/vial.h index 85d297848b..feb074ee39 100644 --- a/quantum/vial.h +++ b/quantum/vial.h @@ -59,14 +59,16 @@ enum { dynamic_vial_tap_dance_set = 0x02, dynamic_vial_combo_get = 0x03, dynamic_vial_combo_set = 0x04, + dynamic_vial_key_override_get = 0x05, + dynamic_vial_key_override_set = 0x06, }; /* Fake position in keyboard matrix, can't use 255 as that is immediately rejected by IS_NOEVENT used to send arbitrary keycodes thru process_record_quantum_helper */ #define VIAL_MATRIX_MAGIC 254 -#ifdef TAP_DANCE_ENABLE +#ifdef TAP_DANCE_ENABLE #define VIAL_TAP_DANCE_ENABLE #ifndef VIAL_TAP_DANCE_ENTRIES @@ -95,6 +97,7 @@ _Static_assert(sizeof(vial_tap_dance_entry_t) == 10, "Unexpected size of the via #define VIAL_TAP_DANCE_ENTRIES 0 #endif + #ifdef COMBO_ENABLE #define VIAL_COMBO_ENABLE @@ -127,3 +130,49 @@ _Static_assert(sizeof(vial_combo_entry_t) == 10, "Unexpected size of the vial_co #undef VIAL_COMBO_ENTRIES #define VIAL_COMBO_ENTRIES 0 #endif + + +#ifdef KEY_OVERRIDE_ENABLE +#define VIAL_KEY_OVERRIDE_ENABLE + +#include "process_key_override.h" + +#ifndef VIAL_KEY_OVERRIDE_ENTRIES + #if DYNAMIC_KEYMAP_EEPROM_MAX_ADDR > 4000 + #define VIAL_KEY_OVERRIDE_ENTRIES 32 + #elif DYNAMIC_KEYMAP_EEPROM_MAX_ADDR > 2000 + #define VIAL_KEY_OVERRIDE_ENTRIES 16 + #elif DYNAMIC_KEYMAP_EEPROM_MAX_ADDR > 1000 + #define VIAL_KEY_OVERRIDE_ENTRIES 8 + #else + #define VIAL_KEY_OVERRIDE_ENTRIES 4 + #endif +#endif + +/* the key override structure as it is stored in eeprom and transferred to vial-gui; + it is deserialized into key_override_t by vial_get_key_override */ +typedef struct { + uint16_t trigger; + uint16_t replacement; + uint16_t layers; + uint8_t trigger_mods; + uint8_t negative_mod_mask; + uint8_t suppressed_mods; + uint8_t options; +} vial_key_override_entry_t; +_Static_assert(sizeof(vial_key_override_entry_t) == 10, "Unexpected size of the vial_key_override_entry_t structure"); + +enum { + vial_ko_option_activation_trigger_down = (1 << 0), + vial_ko_option_activation_required_mod_down = (1 << 1), + vial_ko_option_activation_negative_mod_up = (1 << 2), + vial_ko_option_one_mod = (1 << 3), + vial_ko_option_no_reregister_trigger = (1 << 4), + vial_ko_option_no_unregister_on_other_key_down = (1 << 5), + vial_ko_enabled = (1 << 7), +}; + +#else +#undef VIAL_KEY_OVERRIDE_ENTRIES +#define VIAL_KEY_OVERRIDE_ENTRIES 0 +#endif