|
|
@ -38,18 +38,18 @@ const Leader::dictionary_t *Leader::dictionary;
|
|
|
|
|
|
|
|
|
|
|
|
// --- actions ---
|
|
|
|
// --- actions ---
|
|
|
|
int8_t
|
|
|
|
int8_t
|
|
|
|
Leader::lookup (void) {
|
|
|
|
Leader::lookup(void) {
|
|
|
|
bool match;
|
|
|
|
bool match;
|
|
|
|
|
|
|
|
|
|
|
|
for (uint8_t seqIndex = 0; ; seqIndex++) {
|
|
|
|
for (uint8_t seqIndex = 0; ; seqIndex++) {
|
|
|
|
match = true;
|
|
|
|
match = true;
|
|
|
|
|
|
|
|
|
|
|
|
if (pgm_read_word (&(dictionary[seqIndex].sequence[0].raw)) == Key_NoKey.raw)
|
|
|
|
if (pgm_read_word(&(dictionary[seqIndex].sequence[0].raw)) == Key_NoKey.raw)
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
Key seqKey;
|
|
|
|
Key seqKey;
|
|
|
|
for (uint8_t i = 0; i <= sequencePos; i++) {
|
|
|
|
for (uint8_t i = 0; i <= sequencePos; i++) {
|
|
|
|
seqKey.raw = pgm_read_word (&(dictionary[seqIndex].sequence[i].raw));
|
|
|
|
seqKey.raw = pgm_read_word(&(dictionary[seqIndex].sequence[i].raw));
|
|
|
|
|
|
|
|
|
|
|
|
if (sequence[i].raw != seqKey.raw) {
|
|
|
|
if (sequence[i].raw != seqKey.raw) {
|
|
|
|
match = false;
|
|
|
|
match = false;
|
|
|
@ -60,7 +60,7 @@ Leader::lookup (void) {
|
|
|
|
if (!match)
|
|
|
|
if (!match)
|
|
|
|
continue;
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
|
|
seqKey.raw = pgm_read_word (&(dictionary[seqIndex].sequence[sequencePos + 1].raw));
|
|
|
|
seqKey.raw = pgm_read_word(&(dictionary[seqIndex].sequence[sequencePos + 1].raw));
|
|
|
|
if (seqKey.raw == Key_NoKey.raw) {
|
|
|
|
if (seqKey.raw == Key_NoKey.raw) {
|
|
|
|
return seqIndex;
|
|
|
|
return seqIndex;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
@ -73,52 +73,52 @@ Leader::lookup (void) {
|
|
|
|
|
|
|
|
|
|
|
|
// --- api ---
|
|
|
|
// --- api ---
|
|
|
|
|
|
|
|
|
|
|
|
Leader::Leader (void) {
|
|
|
|
Leader::Leader(void) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
void
|
|
|
|
Leader::begin (void) {
|
|
|
|
Leader::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
|
|
|
|
Leader::configure (const Leader::dictionary_t dictionary_[]) {
|
|
|
|
Leader::configure(const Leader::dictionary_t dictionary_[]) {
|
|
|
|
dictionary = dictionary_;
|
|
|
|
dictionary = dictionary_;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
void
|
|
|
|
Leader::reset (void) {
|
|
|
|
Leader::reset(void) {
|
|
|
|
sequencePos = 0;
|
|
|
|
sequencePos = 0;
|
|
|
|
sequence[0].raw = Key_NoKey.raw;
|
|
|
|
sequence[0].raw = Key_NoKey.raw;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
void
|
|
|
|
Leader::inject (Key key, uint8_t keyState) {
|
|
|
|
Leader::inject(Key key, uint8_t keyState) {
|
|
|
|
eventHandlerHook (key, 255, 255, keyState);
|
|
|
|
eventHandlerHook(key, 255, 255, keyState);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// --- hooks ---
|
|
|
|
// --- hooks ---
|
|
|
|
Key
|
|
|
|
Key
|
|
|
|
Leader::eventHandlerHook (Key mappedKey, byte row, byte col, uint8_t keyState) {
|
|
|
|
Leader::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 (isLeader (mappedKey))
|
|
|
|
if (isLeader(mappedKey))
|
|
|
|
return Key_NoKey;
|
|
|
|
return Key_NoKey;
|
|
|
|
return mappedKey;
|
|
|
|
return mappedKey;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (!isActive () && !isLeader (mappedKey))
|
|
|
|
if (!isActive() && !isLeader(mappedKey))
|
|
|
|
return mappedKey;
|
|
|
|
return mappedKey;
|
|
|
|
|
|
|
|
|
|
|
|
if (!isActive ()) {
|
|
|
|
if (!isActive()) {
|
|
|
|
// Must be a leader key!
|
|
|
|
// Must be a leader key!
|
|
|
|
|
|
|
|
|
|
|
|
if (key_toggled_off (keyState)) {
|
|
|
|
if (key_toggled_off(keyState)) {
|
|
|
|
// not active, but a leader key = start the sequence on key release!
|
|
|
|
// not active, but a leader key = start the sequence on key release!
|
|
|
|
endTime = millis () + timeOut;
|
|
|
|
endTime = millis() + timeOut;
|
|
|
|
sequencePos = 0;
|
|
|
|
sequencePos = 0;
|
|
|
|
sequence[sequencePos].raw = mappedKey.raw;
|
|
|
|
sequence[sequencePos].raw = mappedKey.raw;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -128,49 +128,49 @@ Leader::eventHandlerHook (Key mappedKey, byte row, byte col, uint8_t keyState) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// active
|
|
|
|
// active
|
|
|
|
int8_t actionIndex = lookup ();
|
|
|
|
int8_t actionIndex = lookup();
|
|
|
|
|
|
|
|
|
|
|
|
if (key_toggled_on (keyState)) {
|
|
|
|
if (key_toggled_on(keyState)) {
|
|
|
|
sequencePos++;
|
|
|
|
sequencePos++;
|
|
|
|
if (sequencePos > LEADER_MAX_SEQUENCE_LENGTH) {
|
|
|
|
if (sequencePos > LEADER_MAX_SEQUENCE_LENGTH) {
|
|
|
|
reset ();
|
|
|
|
reset();
|
|
|
|
return mappedKey;
|
|
|
|
return mappedKey;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
endTime = millis () + timeOut;
|
|
|
|
endTime = millis() + timeOut;
|
|
|
|
sequence[sequencePos].raw = mappedKey.raw;
|
|
|
|
sequence[sequencePos].raw = mappedKey.raw;
|
|
|
|
actionIndex = lookup ();
|
|
|
|
actionIndex = lookup();
|
|
|
|
|
|
|
|
|
|
|
|
if (actionIndex >= 0)
|
|
|
|
if (actionIndex >= 0)
|
|
|
|
return Key_NoKey;
|
|
|
|
return Key_NoKey;
|
|
|
|
} else if (key_is_pressed (keyState)) {
|
|
|
|
} else if (key_is_pressed(keyState)) {
|
|
|
|
// held, no need for anything here.
|
|
|
|
// held, no need for anything here.
|
|
|
|
return Key_NoKey;
|
|
|
|
return Key_NoKey;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (actionIndex == NO_MATCH) {
|
|
|
|
if (actionIndex == NO_MATCH) {
|
|
|
|
reset ();
|
|
|
|
reset();
|
|
|
|
return mappedKey;
|
|
|
|
return mappedKey;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (actionIndex == PARTIAL_MATCH) {
|
|
|
|
if (actionIndex == PARTIAL_MATCH) {
|
|
|
|
return Key_NoKey;
|
|
|
|
return Key_NoKey;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
action_t leaderAction = (action_t) pgm_read_ptr (&(dictionary[actionIndex].action));
|
|
|
|
action_t leaderAction = (action_t) pgm_read_ptr(&(dictionary[actionIndex].action));
|
|
|
|
(*leaderAction) (actionIndex);
|
|
|
|
(*leaderAction)(actionIndex);
|
|
|
|
return Key_NoKey;
|
|
|
|
return Key_NoKey;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
void
|
|
|
|
Leader::loopHook (bool postClear) {
|
|
|
|
Leader::loopHook(bool postClear) {
|
|
|
|
if (!postClear)
|
|
|
|
if (!postClear)
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
if (!isActive ())
|
|
|
|
if (!isActive())
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
if (millis () >= endTime)
|
|
|
|
if (millis() >= endTime)
|
|
|
|
reset ();
|
|
|
|
reset();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|