vial/tap-dance: initial implementation
This commit is contained in:
parent
9ae8b1bc27
commit
5f4aa29c0d
@ -453,6 +453,7 @@ ifeq ($(strip $(VIA_ENABLE)), yes)
|
||||
endif
|
||||
|
||||
ifeq ($(strip $(VIAL_ENABLE)), yes)
|
||||
TAP_DANCE_ENABLE ?= yes
|
||||
SRC += $(QUANTUM_DIR)/vial.c
|
||||
EXTRAINCDIRS += $(KEYMAP_OUTPUT)
|
||||
OPT_DEFS += -DVIAL_ENABLE -DNO_DEBUG
|
||||
|
@ -78,7 +78,7 @@ static pin_t encoders_pad_a[] = ENCODERS_PAD_A;
|
||||
|
||||
#define VIAL_QMK_SETTINGS_EEPROM_ADDR (VIAL_ENCODERS_EEPROM_ADDR + VIAL_ENCODERS_SIZE)
|
||||
|
||||
// QMK settings area is just past encoders, or dynamic keymaps if encoders aren't enabled
|
||||
// QMK settings area is just past encoders
|
||||
#ifdef QMK_SETTINGS
|
||||
#include "qmk_settings.h"
|
||||
#define VIAL_QMK_SETTINGS_SIZE (sizeof(qmk_settings_t))
|
||||
@ -86,9 +86,17 @@ static pin_t encoders_pad_a[] = ENCODERS_PAD_A;
|
||||
#define VIAL_QMK_SETTINGS_SIZE 0
|
||||
#endif
|
||||
|
||||
// Dynamic macro starts after encoders, or dynamic keymaps if encoders aren't enabled
|
||||
#define VIAL_TAP_DANCE_EEPROM_ADDR (VIAL_QMK_SETTINGS_EEPROM_ADDR + VIAL_QMK_SETTINGS_SIZE)
|
||||
|
||||
#ifdef VIAL_TAP_DANCE_ENABLE
|
||||
#define VIAL_TAP_DANCE_SIZE (sizeof(vial_tap_dance_entry_t) * VIAL_TAP_DANCE_ENTRIES)
|
||||
#else
|
||||
#define VIAL_TAP_DANCE_SIZE 0
|
||||
#endif
|
||||
|
||||
// Dynamic macro starts after tap-dance
|
||||
#ifndef DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR
|
||||
# define DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR (VIAL_QMK_SETTINGS_EEPROM_ADDR + VIAL_QMK_SETTINGS_SIZE)
|
||||
# define DYNAMIC_KEYMAP_MACRO_EEPROM_ADDR (VIAL_TAP_DANCE_EEPROM_ADDR + VIAL_TAP_DANCE_SIZE)
|
||||
#endif
|
||||
|
||||
// Sanity check that dynamic keymaps fit in available EEPROM
|
||||
@ -185,6 +193,28 @@ void dynamic_keymap_set_qmk_settings(uint16_t offset, uint8_t value) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef VIAL_TAP_DANCE_ENABLE
|
||||
int dynamic_keymap_get_tap_dance(uint8_t index, vial_tap_dance_entry_t *entry) {
|
||||
if (index >= VIAL_TAP_DANCE_ENTRIES)
|
||||
return -1;
|
||||
|
||||
void *address = (void*)(VIAL_TAP_DANCE_EEPROM_ADDR + index * sizeof(vial_tap_dance_entry_t));
|
||||
eeprom_read_block(entry, address, sizeof(vial_tap_dance_entry_t));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dynamic_keymap_set_tap_dance(uint8_t index, const vial_tap_dance_entry_t *entry) {
|
||||
if (index >= VIAL_TAP_DANCE_ENTRIES)
|
||||
return -1;
|
||||
|
||||
void *address = (void*)(VIAL_TAP_DANCE_EEPROM_ADDR + index * sizeof(vial_tap_dance_entry_t));
|
||||
eeprom_write_block(entry, address, sizeof(vial_tap_dance_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,
|
||||
@ -225,6 +255,13 @@ void dynamic_keymap_reset(void) {
|
||||
qmk_settings_reset();
|
||||
#endif
|
||||
|
||||
#ifdef VIAL_TAP_DANCE_ENABLE
|
||||
vial_tap_dance_entry_t td = { KC_NO, KC_NO, KC_NO, KC_NO, TAPPING_TERM };
|
||||
for (size_t i = 0; i < VIAL_TAP_DANCE_ENTRIES; ++i) {
|
||||
dynamic_keymap_set_tap_dance(i, &td);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef VIAL_ENABLE
|
||||
/* re-lock the keyboard */
|
||||
vial_unlocked = vial_unlocked_prev;
|
||||
|
@ -34,6 +34,10 @@ void dynamic_keymap_set_encoder(uint8_t layer, uint8_t idx, uint8_t dir, uint16_
|
||||
uint8_t dynamic_keymap_get_qmk_settings(uint16_t offset);
|
||||
void dynamic_keymap_set_qmk_settings(uint16_t offset, uint8_t value);
|
||||
#endif
|
||||
#ifdef VIAL_TAP_DANCE_ENABLE
|
||||
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
|
||||
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)
|
||||
|
203
quantum/vial.c
203
quantum/vial.c
@ -54,6 +54,16 @@ _Static_assert(sizeof(vial_unlock_combo_rows) == sizeof(vial_unlock_combo_cols),
|
||||
#include "qmk_settings.h"
|
||||
#endif
|
||||
|
||||
#ifdef VIAL_TAP_DANCE_ENABLE
|
||||
static void reload_tap_dance(void);
|
||||
#endif
|
||||
|
||||
void vial_init(void) {
|
||||
#ifdef VIAL_TAP_DANCE_ENABLE
|
||||
reload_tap_dance();
|
||||
#endif
|
||||
}
|
||||
|
||||
void vial_handle_cmd(uint8_t *msg, uint8_t length) {
|
||||
/* All packets must be fixed 32 bytes */
|
||||
if (length != VIAL_RAW_EPSIZE)
|
||||
@ -185,6 +195,32 @@ void vial_handle_cmd(uint8_t *msg, uint8_t length) {
|
||||
qmk_settings_reset();
|
||||
break;
|
||||
}
|
||||
case vial_dynamic_entry_op: {
|
||||
switch (msg[2]) {
|
||||
case dynamic_vial_get_number_of_entries: {
|
||||
memset(msg, 0, length);
|
||||
msg[0] = VIAL_TAP_DANCE_ENTRIES;
|
||||
break;
|
||||
}
|
||||
case dynamic_vial_tap_dance_get: {
|
||||
uint8_t idx = msg[3];
|
||||
vial_tap_dance_entry_t td = { 0 };
|
||||
msg[0] = dynamic_keymap_get_tap_dance(idx, &td);
|
||||
memcpy(&msg[1], &td, sizeof(td));
|
||||
break;
|
||||
}
|
||||
case dynamic_vial_tap_dance_set: {
|
||||
uint8_t idx = msg[3];
|
||||
vial_tap_dance_entry_t td;
|
||||
memcpy(&td, &msg[4], sizeof(td));
|
||||
msg[0] = dynamic_keymap_set_tap_dance(idx, &td);
|
||||
reload_tap_dance();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -242,3 +278,170 @@ bool vial_encoder_update(uint8_t index, bool clockwise) {
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef VIAL_TAP_DANCE_ENABLE
|
||||
#include "process_tap_dance.h"
|
||||
|
||||
/* based on ZSA configurator generated code */
|
||||
|
||||
enum {
|
||||
SINGLE_TAP = 1,
|
||||
SINGLE_HOLD,
|
||||
DOUBLE_TAP,
|
||||
DOUBLE_HOLD,
|
||||
DOUBLE_SINGLE_TAP,
|
||||
MORE_TAPS
|
||||
};
|
||||
|
||||
static uint8_t dance_state[VIAL_TAP_DANCE_ENTRIES];
|
||||
static vial_tap_dance_entry_t td_entry;
|
||||
|
||||
static uint8_t dance_step(qk_tap_dance_state_t *state) {
|
||||
if (state->count == 1) {
|
||||
if (state->interrupted || !state->pressed) return SINGLE_TAP;
|
||||
else return SINGLE_HOLD;
|
||||
} else if (state->count == 2) {
|
||||
if (state->interrupted) return DOUBLE_SINGLE_TAP;
|
||||
else if (state->pressed) return DOUBLE_HOLD;
|
||||
else return DOUBLE_TAP;
|
||||
}
|
||||
return MORE_TAPS;
|
||||
}
|
||||
|
||||
static void on_dance(qk_tap_dance_state_t *state, void *user_data) {
|
||||
uint8_t index = (uintptr_t)user_data;
|
||||
if (dynamic_keymap_get_tap_dance(index, &td_entry) != 0)
|
||||
return;
|
||||
uint16_t kc = td_entry.on_tap;
|
||||
if (kc) {
|
||||
if (state->count == 3) {
|
||||
tap_code16(kc);
|
||||
tap_code16(kc);
|
||||
tap_code16(kc);
|
||||
} else if (state->count > 3) {
|
||||
tap_code16(kc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void on_dance_finished(qk_tap_dance_state_t *state, void *user_data) {
|
||||
uint8_t index = (uintptr_t)user_data;
|
||||
if (dynamic_keymap_get_tap_dance(index, &td_entry) != 0)
|
||||
return;
|
||||
dance_state[index] = dance_step(state);
|
||||
switch (dance_state[index]) {
|
||||
case SINGLE_TAP: {
|
||||
if (td_entry.on_tap)
|
||||
register_code16(td_entry.on_tap);
|
||||
break;
|
||||
}
|
||||
case SINGLE_HOLD: {
|
||||
if (td_entry.on_hold)
|
||||
register_code16(td_entry.on_hold);
|
||||
else if (td_entry.on_tap)
|
||||
register_code16(td_entry.on_tap);
|
||||
break;
|
||||
}
|
||||
case DOUBLE_TAP: {
|
||||
if (td_entry.on_double_tap) {
|
||||
register_code16(td_entry.on_double_tap);
|
||||
} else if (td_entry.on_tap) {
|
||||
register_code16(td_entry.on_tap);
|
||||
register_code16(td_entry.on_tap);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DOUBLE_HOLD: {
|
||||
if (td_entry.on_tap_hold) {
|
||||
register_code16(td_entry.on_tap_hold);
|
||||
} else {
|
||||
if (td_entry.on_tap) {
|
||||
tap_code16(td_entry.on_tap);
|
||||
if (td_entry.on_hold)
|
||||
register_code16(td_entry.on_hold);
|
||||
else
|
||||
register_code16(td_entry.on_tap);
|
||||
} else if (td_entry.on_hold) {
|
||||
register_code16(td_entry.on_hold);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DOUBLE_SINGLE_TAP: {
|
||||
if (td_entry.on_tap) {
|
||||
tap_code16(td_entry.on_tap);
|
||||
register_code16(td_entry.on_tap);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void on_dance_reset(qk_tap_dance_state_t *state, void *user_data) {
|
||||
uint8_t index = (uintptr_t)user_data;
|
||||
if (dynamic_keymap_get_tap_dance(index, &td_entry) != 0)
|
||||
return;
|
||||
wait_ms(10);
|
||||
switch (dance_state[index]) {
|
||||
case SINGLE_TAP: {
|
||||
if (td_entry.on_tap)
|
||||
unregister_code16(td_entry.on_tap);
|
||||
break;
|
||||
}
|
||||
case SINGLE_HOLD: {
|
||||
if (td_entry.on_hold)
|
||||
unregister_code16(td_entry.on_hold);
|
||||
else if (td_entry.on_tap)
|
||||
unregister_code16(td_entry.on_tap);
|
||||
break;
|
||||
}
|
||||
case DOUBLE_TAP: {
|
||||
if (td_entry.on_double_tap) {
|
||||
unregister_code16(td_entry.on_double_tap);
|
||||
} else if (td_entry.on_tap) {
|
||||
unregister_code16(td_entry.on_tap);
|
||||
unregister_code16(td_entry.on_tap);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DOUBLE_HOLD: {
|
||||
if (td_entry.on_tap_hold) {
|
||||
unregister_code16(td_entry.on_tap_hold);
|
||||
} else {
|
||||
if (td_entry.on_tap) {
|
||||
if (td_entry.on_hold)
|
||||
unregister_code16(td_entry.on_hold);
|
||||
else
|
||||
unregister_code16(td_entry.on_tap);
|
||||
} else if (td_entry.on_hold) {
|
||||
unregister_code16(td_entry.on_hold);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DOUBLE_SINGLE_TAP: {
|
||||
if (td_entry.on_tap) {
|
||||
unregister_code16(td_entry.on_tap);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
dance_state[index] = 0;
|
||||
}
|
||||
|
||||
qk_tap_dance_action_t tap_dance_actions[VIAL_TAP_DANCE_ENTRIES];
|
||||
|
||||
/* Load timings from eeprom into custom_tapping_term */
|
||||
static void reload_tap_dance(void) {
|
||||
for (size_t i = 0; i < VIAL_TAP_DANCE_ENTRIES; ++i) {
|
||||
vial_tap_dance_entry_t td;
|
||||
tap_dance_actions[i].fn.on_each_tap = on_dance;
|
||||
tap_dance_actions[i].fn.on_dance_finished = on_dance_finished;
|
||||
tap_dance_actions[i].fn.on_reset = on_dance_reset;
|
||||
tap_dance_actions[i].user_data = (void*)i;
|
||||
if (dynamic_keymap_get_tap_dance(i, &td) == 0) {
|
||||
tap_dance_actions[i].custom_tapping_term = td.custom_tapping_term;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#define VIAL_PROTOCOL_VERSION ((uint32_t)0x00000004)
|
||||
|
||||
void vial_init(void);
|
||||
void vial_handle_cmd(uint8_t *data, uint8_t length);
|
||||
|
||||
#ifdef VIAL_ENCODERS_ENABLE
|
||||
@ -44,7 +45,36 @@ enum {
|
||||
vial_qmk_settings_get = 0x0A,
|
||||
vial_qmk_settings_set = 0x0B,
|
||||
vial_qmk_settings_reset = 0x0C,
|
||||
vial_dynamic_entry_op = 0x0D, /* operate on tapdance, combos, etc */
|
||||
};
|
||||
|
||||
enum {
|
||||
dynamic_vial_get_number_of_entries = 0x00,
|
||||
dynamic_vial_tap_dance_get = 0x01,
|
||||
dynamic_vial_tap_dance_set = 0x02,
|
||||
};
|
||||
|
||||
/* Fake encoder position in keyboard matrix, can't use 255 as that is immediately rejected by IS_NOEVENT */
|
||||
#define VIAL_ENCODER_MATRIX_MAGIC 254
|
||||
|
||||
#ifdef TAP_DANCE_ENABLE
|
||||
|
||||
#define VIAL_TAP_DANCE_ENABLE
|
||||
|
||||
#ifndef VIAL_TAP_DANCE_ENTRIES
|
||||
#define VIAL_TAP_DANCE_ENTRIES 16
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
uint16_t on_tap;
|
||||
uint16_t on_hold;
|
||||
uint16_t on_double_tap;
|
||||
uint16_t on_tap_hold;
|
||||
uint16_t custom_tapping_term;
|
||||
} vial_tap_dance_entry_t;
|
||||
_Static_assert(sizeof(vial_tap_dance_entry_t) == 10, "Unexpected size of the vial_tap_dance_entry_t structure");
|
||||
|
||||
#else
|
||||
#undef VIAL_TAP_DANCE_ENTRIES
|
||||
#define VIAL_TAP_DANCE_ENTRIES 0
|
||||
#endif
|
||||
|
@ -103,6 +103,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#ifdef QMK_SETTINGS
|
||||
# include "qmk_settings.h"
|
||||
#endif
|
||||
#ifdef VIAL_ENABLE
|
||||
# include "vial.h"
|
||||
#endif
|
||||
|
||||
static uint32_t last_input_modification_time = 0;
|
||||
uint32_t last_input_activity_time(void) { return last_input_modification_time; }
|
||||
@ -246,6 +249,9 @@ void keyboard_setup(void) {
|
||||
#ifdef EEPROM_DRIVER
|
||||
eeprom_driver_init();
|
||||
#endif
|
||||
#ifdef VIAL_ENABLE
|
||||
vial_init();
|
||||
#endif
|
||||
#ifdef QMK_SETTINGS
|
||||
qmk_settings_init();
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user