|
|
@ -21,28 +21,28 @@
|
|
|
|
using namespace KaleidoscopePlugins::Ranges;
|
|
|
|
using namespace KaleidoscopePlugins::Ranges;
|
|
|
|
|
|
|
|
|
|
|
|
namespace KaleidoscopePlugins {
|
|
|
|
namespace KaleidoscopePlugins {
|
|
|
|
// --- state ---
|
|
|
|
// --- state ---
|
|
|
|
uint32_t TapDance::endTime;
|
|
|
|
uint32_t TapDance::endTime;
|
|
|
|
uint16_t TapDance::timeOut = 200;
|
|
|
|
uint16_t TapDance::timeOut = 200;
|
|
|
|
uint8_t TapDance::tapCount[16];
|
|
|
|
uint8_t TapDance::tapCount[16];
|
|
|
|
uint16_t TapDance::pressedState;
|
|
|
|
uint16_t TapDance::pressedState;
|
|
|
|
uint16_t TapDance::triggeredState;
|
|
|
|
uint16_t TapDance::triggeredState;
|
|
|
|
uint16_t TapDance::releaseNextState;
|
|
|
|
uint16_t TapDance::releaseNextState;
|
|
|
|
Key TapDance::lastTapDanceKey;
|
|
|
|
Key TapDance::lastTapDanceKey;
|
|
|
|
byte TapDance::lastTapDanceRow;
|
|
|
|
byte TapDance::lastTapDanceRow;
|
|
|
|
byte TapDance::lastTapDanceCol;
|
|
|
|
byte TapDance::lastTapDanceCol;
|
|
|
|
|
|
|
|
|
|
|
|
// --- helpers ---
|
|
|
|
// --- helpers ---
|
|
|
|
|
|
|
|
|
|
|
|
#define isTapDance(k) (k.raw >= TD_FIRST && k.raw <= TD_LAST)
|
|
|
|
#define isTapDance(k) (k.raw >= TD_FIRST && k.raw <= TD_LAST)
|
|
|
|
#define isInSeq(k) (lastTapDanceKey.raw == k.raw)
|
|
|
|
#define isInSeq(k) (lastTapDanceKey.raw == k.raw)
|
|
|
|
#define stillHeld(idx) (tapCount[idx])
|
|
|
|
#define stillHeld(idx) (tapCount[idx])
|
|
|
|
#define isActive() (lastTapDanceKey.raw != Key_NoKey.raw)
|
|
|
|
#define isActive() (lastTapDanceKey.raw != Key_NoKey.raw)
|
|
|
|
|
|
|
|
|
|
|
|
// --- actions ---
|
|
|
|
// --- actions ---
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
void
|
|
|
|
TapDance::interrupt (void) {
|
|
|
|
TapDance::interrupt (void) {
|
|
|
|
uint8_t idx = lastTapDanceKey.raw - TD_FIRST;
|
|
|
|
uint8_t idx = lastTapDanceKey.raw - TD_FIRST;
|
|
|
|
|
|
|
|
|
|
|
|
tapDanceAction (idx, lastTapDanceRow, lastTapDanceCol, tapCount[idx], Interrupt);
|
|
|
|
tapDanceAction (idx, lastTapDanceRow, lastTapDanceCol, tapCount[idx], Interrupt);
|
|
|
@ -51,28 +51,28 @@ namespace KaleidoscopePlugins {
|
|
|
|
endTime = 0;
|
|
|
|
endTime = 0;
|
|
|
|
|
|
|
|
|
|
|
|
if (bitRead (pressedState, idx))
|
|
|
|
if (bitRead (pressedState, idx))
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
release (idx);
|
|
|
|
release (idx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
void
|
|
|
|
TapDance::timeout (void) {
|
|
|
|
TapDance::timeout (void) {
|
|
|
|
uint8_t idx = lastTapDanceKey.raw - TD_FIRST;
|
|
|
|
uint8_t idx = lastTapDanceKey.raw - TD_FIRST;
|
|
|
|
|
|
|
|
|
|
|
|
tapDanceAction (idx, lastTapDanceRow, lastTapDanceCol, tapCount[idx], Timeout);
|
|
|
|
tapDanceAction (idx, lastTapDanceRow, lastTapDanceCol, tapCount[idx], Timeout);
|
|
|
|
bitWrite (triggeredState, idx, 1);
|
|
|
|
bitWrite (triggeredState, idx, 1);
|
|
|
|
|
|
|
|
|
|
|
|
if (bitRead (pressedState, idx))
|
|
|
|
if (bitRead (pressedState, idx))
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
lastTapDanceKey.raw = Key_NoKey.raw;
|
|
|
|
lastTapDanceKey.raw = Key_NoKey.raw;
|
|
|
|
|
|
|
|
|
|
|
|
release (idx);
|
|
|
|
release (idx);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Key
|
|
|
|
Key
|
|
|
|
TapDance::release (uint8_t tapDanceIndex) {
|
|
|
|
TapDance::release (uint8_t tapDanceIndex) {
|
|
|
|
endTime = 0;
|
|
|
|
endTime = 0;
|
|
|
|
lastTapDanceKey.raw = Key_NoKey.raw;
|
|
|
|
lastTapDanceKey.raw = Key_NoKey.raw;
|
|
|
|
|
|
|
|
|
|
|
@ -80,10 +80,10 @@ namespace KaleidoscopePlugins {
|
|
|
|
bitClear (triggeredState, tapDanceIndex);
|
|
|
|
bitClear (triggeredState, tapDanceIndex);
|
|
|
|
bitWrite (releaseNextState, tapDanceIndex, 1);
|
|
|
|
bitWrite (releaseNextState, tapDanceIndex, 1);
|
|
|
|
return Key_NoKey;
|
|
|
|
return Key_NoKey;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Key
|
|
|
|
Key
|
|
|
|
TapDance::tap (void) {
|
|
|
|
TapDance::tap (void) {
|
|
|
|
uint8_t idx = lastTapDanceKey.raw - TD_FIRST;
|
|
|
|
uint8_t idx = lastTapDanceKey.raw - TD_FIRST;
|
|
|
|
|
|
|
|
|
|
|
|
tapCount[idx]++;
|
|
|
|
tapCount[idx]++;
|
|
|
@ -92,101 +92,101 @@ namespace KaleidoscopePlugins {
|
|
|
|
tapDanceAction (idx, lastTapDanceRow, lastTapDanceCol, tapCount[idx], Tap);
|
|
|
|
tapDanceAction (idx, lastTapDanceRow, lastTapDanceCol, tapCount[idx], Tap);
|
|
|
|
|
|
|
|
|
|
|
|
return Key_NoKey;
|
|
|
|
return Key_NoKey;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// --- api ---
|
|
|
|
// --- api ---
|
|
|
|
|
|
|
|
|
|
|
|
TapDance::TapDance (void) {
|
|
|
|
TapDance::TapDance (void) {
|
|
|
|
lastTapDanceKey.raw = Key_NoKey.raw;
|
|
|
|
lastTapDanceKey.raw = Key_NoKey.raw;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
void
|
|
|
|
TapDance::begin (void) {
|
|
|
|
TapDance::begin (void) {
|
|
|
|
event_handler_hook_use (this->eventHandlerHook);
|
|
|
|
event_handler_hook_use (this->eventHandlerHook);
|
|
|
|
loop_hook_use (this->loopHook);
|
|
|
|
loop_hook_use (this->loopHook);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
void
|
|
|
|
TapDance::actionKeys (uint8_t tapCount, ActionType tapDanceAction, uint8_t maxKeys, const Key tapKeys[]) {
|
|
|
|
TapDance::actionKeys (uint8_t tapCount, ActionType tapDanceAction, uint8_t maxKeys, const Key tapKeys[]) {
|
|
|
|
if (tapCount > maxKeys)
|
|
|
|
if (tapCount > maxKeys)
|
|
|
|
tapCount = maxKeys;
|
|
|
|
tapCount = maxKeys;
|
|
|
|
|
|
|
|
|
|
|
|
Key key;
|
|
|
|
Key key;
|
|
|
|
key.raw = pgm_read_word (&(tapKeys[tapCount - 1].raw));
|
|
|
|
key.raw = pgm_read_word (&(tapKeys[tapCount - 1].raw));
|
|
|
|
|
|
|
|
|
|
|
|
switch (tapDanceAction) {
|
|
|
|
switch (tapDanceAction) {
|
|
|
|
case Tap:
|
|
|
|
case Tap:
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
case Interrupt:
|
|
|
|
case Interrupt:
|
|
|
|
case Timeout:
|
|
|
|
case Timeout:
|
|
|
|
handle_keyswitch_event (key, lastTapDanceRow, lastTapDanceCol, IS_PRESSED | INJECTED);
|
|
|
|
handle_keyswitch_event (key, lastTapDanceRow, lastTapDanceCol, IS_PRESSED | INJECTED);
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
case Hold:
|
|
|
|
case Hold:
|
|
|
|
handle_keyswitch_event (key, lastTapDanceRow, lastTapDanceCol, IS_PRESSED | WAS_PRESSED | INJECTED);
|
|
|
|
handle_keyswitch_event (key, lastTapDanceRow, lastTapDanceCol, IS_PRESSED | WAS_PRESSED | INJECTED);
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
case Release:
|
|
|
|
case Release:
|
|
|
|
Keyboard.sendReport ();
|
|
|
|
Keyboard.sendReport ();
|
|
|
|
handle_keyswitch_event (key, lastTapDanceRow, lastTapDanceCol, WAS_PRESSED | INJECTED);
|
|
|
|
handle_keyswitch_event (key, lastTapDanceRow, lastTapDanceCol, WAS_PRESSED | INJECTED);
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// --- hooks ---
|
|
|
|
// --- hooks ---
|
|
|
|
|
|
|
|
|
|
|
|
Key
|
|
|
|
Key
|
|
|
|
TapDance::eventHandlerHook (Key mappedKey, byte row, byte col, uint8_t keyState) {
|
|
|
|
TapDance::eventHandlerHook (Key mappedKey, byte row, byte col, uint8_t keyState) {
|
|
|
|
if (keyState & INJECTED)
|
|
|
|
if (keyState & INJECTED)
|
|
|
|
return mappedKey;
|
|
|
|
return mappedKey;
|
|
|
|
|
|
|
|
|
|
|
|
if (!key_is_pressed (keyState) && !key_was_pressed (keyState)) {
|
|
|
|
if (!key_is_pressed (keyState) && !key_was_pressed (keyState)) {
|
|
|
|
if (isTapDance (mappedKey))
|
|
|
|
if (isTapDance (mappedKey))
|
|
|
|
return Key_NoKey;
|
|
|
|
return Key_NoKey;
|
|
|
|
return mappedKey;
|
|
|
|
return mappedKey;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!isTapDance (mappedKey)) {
|
|
|
|
if (!isTapDance (mappedKey)) {
|
|
|
|
if (!isActive ())
|
|
|
|
if (!isActive ())
|
|
|
|
return mappedKey;
|
|
|
|
return mappedKey;
|
|
|
|
|
|
|
|
|
|
|
|
if (key_toggled_on (keyState))
|
|
|
|
if (key_toggled_on (keyState))
|
|
|
|
interrupt ();
|
|
|
|
interrupt ();
|
|
|
|
|
|
|
|
|
|
|
|
return mappedKey;
|
|
|
|
return mappedKey;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t tapDanceIndex = mappedKey.raw - TD_FIRST;
|
|
|
|
uint8_t tapDanceIndex = mappedKey.raw - TD_FIRST;
|
|
|
|
|
|
|
|
|
|
|
|
if (key_toggled_off (keyState))
|
|
|
|
if (key_toggled_off (keyState))
|
|
|
|
bitClear (pressedState, tapDanceIndex);
|
|
|
|
bitClear (pressedState, tapDanceIndex);
|
|
|
|
|
|
|
|
|
|
|
|
if (!isInSeq (mappedKey)) {
|
|
|
|
if (!isInSeq (mappedKey)) {
|
|
|
|
if (!isActive ()) {
|
|
|
|
if (!isActive ()) {
|
|
|
|
if (bitRead (triggeredState, tapDanceIndex)) {
|
|
|
|
if (bitRead (triggeredState, tapDanceIndex)) {
|
|
|
|
if (key_toggled_off (keyState))
|
|
|
|
if (key_toggled_off (keyState))
|
|
|
|
return release (tapDanceIndex);
|
|
|
|
return release (tapDanceIndex);
|
|
|
|
return Key_NoKey;
|
|
|
|
return Key_NoKey;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
lastTapDanceKey.raw = mappedKey.raw;
|
|
|
|
|
|
|
|
lastTapDanceRow = row;
|
|
|
|
|
|
|
|
lastTapDanceCol = col;
|
|
|
|
|
|
|
|
return tap ();
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
if (key_toggled_off (keyState) && stillHeld (tapDanceIndex)) {
|
|
|
|
|
|
|
|
return release (tapDanceIndex);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!key_toggled_on (keyState))
|
|
|
|
|
|
|
|
return Key_NoKey;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
interrupt ();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
lastTapDanceKey.raw = mappedKey.raw;
|
|
|
|
|
|
|
|
lastTapDanceRow = row;
|
|
|
|
|
|
|
|
lastTapDanceCol = col;
|
|
|
|
|
|
|
|
return tap ();
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
if (key_toggled_off (keyState) && stillHeld (tapDanceIndex)) {
|
|
|
|
|
|
|
|
return release (tapDanceIndex);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!key_toggled_on (keyState))
|
|
|
|
|
|
|
|
return Key_NoKey;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
interrupt ();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// in sequence
|
|
|
|
// in sequence
|
|
|
|
|
|
|
|
|
|
|
|
if (key_toggled_off (keyState))
|
|
|
|
if (key_toggled_off (keyState))
|
|
|
|
return Key_NoKey;
|
|
|
|
return Key_NoKey;
|
|
|
|
|
|
|
|
|
|
|
|
lastTapDanceKey.raw = mappedKey.raw;
|
|
|
|
lastTapDanceKey.raw = mappedKey.raw;
|
|
|
|
lastTapDanceRow = row;
|
|
|
|
lastTapDanceRow = row;
|
|
|
@ -194,34 +194,34 @@ namespace KaleidoscopePlugins {
|
|
|
|
bitSet (pressedState, tapDanceIndex);
|
|
|
|
bitSet (pressedState, tapDanceIndex);
|
|
|
|
|
|
|
|
|
|
|
|
if (key_toggled_on (keyState))
|
|
|
|
if (key_toggled_on (keyState))
|
|
|
|
return tap ();
|
|
|
|
return tap ();
|
|
|
|
|
|
|
|
|
|
|
|
if (bitRead (triggeredState, tapDanceIndex))
|
|
|
|
if (bitRead (triggeredState, tapDanceIndex))
|
|
|
|
tapDanceAction (tapDanceIndex, row, col, tapCount[tapDanceIndex], Hold);
|
|
|
|
tapDanceAction (tapDanceIndex, row, col, tapCount[tapDanceIndex], Hold);
|
|
|
|
|
|
|
|
|
|
|
|
return Key_NoKey;
|
|
|
|
return Key_NoKey;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
void
|
|
|
|
TapDance::loopHook (bool postClear) {
|
|
|
|
TapDance::loopHook (bool postClear) {
|
|
|
|
if (!postClear)
|
|
|
|
if (!postClear)
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
for (uint8_t i = 0; i < 16; i++) {
|
|
|
|
for (uint8_t i = 0; i < 16; i++) {
|
|
|
|
if (!bitRead (releaseNextState, i))
|
|
|
|
if (!bitRead (releaseNextState, i))
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
tapDanceAction (i, lastTapDanceRow, lastTapDanceCol, tapCount[i], Release);
|
|
|
|
tapDanceAction (i, lastTapDanceRow, lastTapDanceCol, tapCount[i], Release);
|
|
|
|
tapCount[i] = 0;
|
|
|
|
tapCount[i] = 0;
|
|
|
|
bitClear (releaseNextState, i);
|
|
|
|
bitClear (releaseNextState, i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!isActive ())
|
|
|
|
if (!isActive ())
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
if (endTime && millis () > endTime)
|
|
|
|
if (endTime && millis () > endTime)
|
|
|
|
timeout();
|
|
|
|
timeout();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
__attribute__((weak))
|
|
|
|
__attribute__((weak))
|
|
|
|