vial/tap-dance: initial implementation

This commit is contained in:
Ilya Zhuravlev 2021-07-03 13:30:43 -04:00
parent 9ae8b1bc27
commit 5f4aa29c0d
6 changed files with 284 additions and 3 deletions

View file

@ -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