DennyTom's buttery_engine (#8138)
* Selectively adding pieces * Adding georgi keymap * Adding more files, fixing make * Smaller makefiles * Fixing make rules * README more inline with QMK's guidelines * Turning off buggy assert * Improving documentation based on a user feedback. * Slightly better schema * Resurrected state machine diagram
This commit is contained in:
parent
ae74922d14
commit
e409fb47f2
22 changed files with 7419 additions and 0 deletions
323
users/dennytom/chording_engine/engine.part.2
Normal file
323
users/dennytom/chording_engine/engine.part.2
Normal file
|
@ -0,0 +1,323 @@
|
|||
void single_dance(const struct Chord* self) {
|
||||
switch (*self->state) {
|
||||
case ACTIVATED:
|
||||
key_in(self->value1);
|
||||
break;
|
||||
case DEACTIVATED:
|
||||
key_out(self->value1);
|
||||
*self->state = IDLE;
|
||||
break;
|
||||
case RESTART:
|
||||
key_out(self->value1);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void key_layer_dance(const struct Chord* self) {
|
||||
switch (*self->state) {
|
||||
case ACTIVATED:
|
||||
current_pseudolayer = self->value2;
|
||||
a_key_went_through = false;
|
||||
break;
|
||||
case DEACTIVATED:
|
||||
case RESTART:
|
||||
if (!a_key_went_through) {
|
||||
tap_key(self->value1);
|
||||
}
|
||||
current_pseudolayer = self->pseudolayer;
|
||||
*self->state = IDLE; // does not have effect if the state was RESTART
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void key_mod_dance(const struct Chord* self) {
|
||||
switch (*self->state) {
|
||||
case ACTIVATED:
|
||||
key_in(self->value2);
|
||||
a_key_went_through = false;
|
||||
break;
|
||||
case DEACTIVATED:
|
||||
case RESTART:
|
||||
key_out(self->value2);
|
||||
if (!a_key_went_through) {
|
||||
tap_key(self->value1);
|
||||
}
|
||||
*self->state = IDLE; // does not have effect if the state was RESTART
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void key_key_dance(const struct Chord* self) {
|
||||
switch (*self->state) {
|
||||
case ACTIVATED:
|
||||
break;
|
||||
case DEACTIVATED:
|
||||
tap_key(self->value1);
|
||||
*self->state = IDLE;
|
||||
break;
|
||||
case FINISHED:
|
||||
case PRESS_FROM_ACTIVE:
|
||||
key_in(self->value2);
|
||||
break;
|
||||
case RESTART:
|
||||
key_out(self->value2);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void autoshift_dance_impl(const struct Chord* self) {
|
||||
switch (*self->state) {
|
||||
case ACTIVATED:
|
||||
*self->counter = 0;
|
||||
break;
|
||||
case DEACTIVATED:
|
||||
case RESTART:
|
||||
tap_key(self->value1);
|
||||
*self->state = IDLE;
|
||||
break;
|
||||
case FINISHED_FROM_ACTIVE:
|
||||
if (*self->counter == (LONG_PRESS_MULTIPLIER - 2)) {
|
||||
key_in(KC_LSFT);
|
||||
tap_key(self->value1);
|
||||
key_out(KC_LSFT);
|
||||
*self->state = IDLE;
|
||||
// the skip to IDLE is usually just a lag optimization,
|
||||
// in this case it has a logic function, on a short
|
||||
// press (still longer than a tap) the key does not get shifted
|
||||
} else {
|
||||
*self->counter += 1;
|
||||
*self->state = PRESS_FROM_ACTIVE;
|
||||
dance_timer = timer_read();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void autoshift_dance(const struct Chord* self) {
|
||||
if (autoshift_mode) {
|
||||
autoshift_dance_impl(self);
|
||||
} else {
|
||||
single_dance(self);
|
||||
}
|
||||
}
|
||||
|
||||
void autoshift_toggle(const struct Chord* self){
|
||||
if (*self->state == ACTIVATED) {
|
||||
autoshift_mode = !autoshift_mode;
|
||||
*self->state = IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
void temp_pseudolayer(const struct Chord* self) {
|
||||
switch (*self->state) {
|
||||
case ACTIVATED:
|
||||
current_pseudolayer = self->value1;
|
||||
break;
|
||||
case DEACTIVATED:
|
||||
current_pseudolayer = self->pseudolayer;
|
||||
*self->state = IDLE;
|
||||
break;
|
||||
case RESTART:
|
||||
current_pseudolayer = self->pseudolayer;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void temp_pseudolayer_alt(const struct Chord* self) {
|
||||
switch (*self->state) {
|
||||
case ACTIVATED:
|
||||
current_pseudolayer = self->value1;
|
||||
break;
|
||||
case DEACTIVATED:
|
||||
current_pseudolayer = self->value2;
|
||||
*self->state = IDLE;
|
||||
break;
|
||||
case RESTART:
|
||||
current_pseudolayer = self->value2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void perm_pseudolayer(const struct Chord* self) {
|
||||
if (*self->state == ACTIVATED) {
|
||||
current_pseudolayer = self->value1;
|
||||
*self->state = IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
void switch_layer(const struct Chord* self) {
|
||||
if (*self->state == ACTIVATED) {
|
||||
layer_move(self->value1);
|
||||
*self->state = IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
void lock(const struct Chord* self) {
|
||||
if (*self->state == ACTIVATED) {
|
||||
lock_next = true;
|
||||
*self->state = IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
void one_shot_key(const struct Chord* self) {
|
||||
switch (*self->state) {
|
||||
case ACTIVATED:
|
||||
break;
|
||||
case DEACTIVATED:
|
||||
key_in(self->value1);
|
||||
*self->state = IN_ONE_SHOT;
|
||||
break;
|
||||
case FINISHED:
|
||||
case PRESS_FROM_ACTIVE:
|
||||
key_in(self->value1);
|
||||
a_key_went_through = false;
|
||||
break;
|
||||
case RESTART:
|
||||
if (a_key_went_through) {
|
||||
key_out(self->value1);
|
||||
} else {
|
||||
*self->state = IN_ONE_SHOT;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void one_shot_layer(const struct Chord* self) {
|
||||
switch (*self->state) {
|
||||
case ACTIVATED:
|
||||
break;
|
||||
case DEACTIVATED:
|
||||
current_pseudolayer = self->value1;
|
||||
*self->state = IN_ONE_SHOT;
|
||||
break;
|
||||
case FINISHED:
|
||||
case PRESS_FROM_ACTIVE:
|
||||
current_pseudolayer = self->value1;
|
||||
a_key_went_through = false;
|
||||
break;
|
||||
case RESTART:
|
||||
if (a_key_went_through) {
|
||||
current_pseudolayer = self->pseudolayer;
|
||||
} else {
|
||||
*self->state = IN_ONE_SHOT;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void command(const struct Chord* self) {
|
||||
if (*self->state == ACTIVATED) {
|
||||
command_mode++;
|
||||
*self->state = IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
bool identical(uint16_t* buffer1, uint16_t* buffer2) {
|
||||
bool same = true;
|
||||
for (int i = 0; i < LEADER_MAX_LENGTH; i++) {
|
||||
same = same && (buffer1[i] == buffer2[i]);
|
||||
}
|
||||
return same;
|
||||
}
|
||||
|
||||
void leader(const struct Chord* self) {
|
||||
if (*self->state == ACTIVATED) {
|
||||
in_leader_mode = true;
|
||||
*self->state = IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
void dynamic_macro_record(const struct Chord* self) {
|
||||
if (*self->state == ACTIVATED) {
|
||||
for (int i = 0; i < DYNAMIC_MACRO_MAX_LENGTH; i++) {
|
||||
dynamic_macro_buffer[i] = 0;
|
||||
}
|
||||
dynamic_macro_mode = true;
|
||||
*self->state = IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
void dynamic_macro_next(const struct Chord* self) {
|
||||
if (*self->state == ACTIVATED) {
|
||||
if (dynamic_macro_mode && dynamic_macro_ind < DYNAMIC_MACRO_MAX_LENGTH) {
|
||||
dynamic_macro_buffer[dynamic_macro_ind] = 0;
|
||||
dynamic_macro_ind++;
|
||||
}
|
||||
*self->state = IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
void dynamic_macro_end(const struct Chord* self) {
|
||||
if (*self->state == ACTIVATED) {
|
||||
if (dynamic_macro_mode) {
|
||||
dynamic_macro_mode = false;
|
||||
}
|
||||
*self->state = IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
void dynamic_macro_play(const struct Chord* self) {
|
||||
if (*self->state == ACTIVATED) {
|
||||
int ind_start = 0;
|
||||
while (ind_start < DYNAMIC_MACRO_MAX_LENGTH) {
|
||||
for (int i = ind_start; i < DYNAMIC_MACRO_MAX_LENGTH; i++) {
|
||||
if (dynamic_macro_buffer[i] == 0) {
|
||||
break;
|
||||
}
|
||||
register_code(dynamic_macro_buffer[i]);
|
||||
}
|
||||
send_keyboard_report();
|
||||
wait_ms(TAP_TIMEOUT);
|
||||
for (int i = ind_start; i < DYNAMIC_MACRO_MAX_LENGTH; i++) {
|
||||
if (dynamic_macro_buffer[i] == 0) {
|
||||
ind_start = i + 1;
|
||||
break;
|
||||
}
|
||||
unregister_code(dynamic_macro_buffer[i]);
|
||||
}
|
||||
send_keyboard_report();
|
||||
}
|
||||
*self->state = IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
void string_in(const struct Chord* self) {
|
||||
if (*self->state == ACTIVATED) {
|
||||
char buffer[STRING_MAX_LENGTH];
|
||||
strcpy_P(buffer, (char*)pgm_read_word(&(strings[self->value1])));
|
||||
send_string(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
void clear(const struct Chord* self);
|
||||
|
||||
void reset_keyboard_kb(void){
|
||||
#ifdef WATCHDOG_ENABLE
|
||||
MCUSR = 0;
|
||||
wdt_disable();
|
||||
wdt_reset();
|
||||
#endif
|
||||
reset_keyboard();
|
||||
}
|
||||
|
||||
void reset(const struct Chord* self) {
|
||||
if (*self->state == ACTIVATED) {
|
||||
reset_keyboard_kb();
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue