From f806133f9c0aac5092a36e4e2e23c40c653364d1 Mon Sep 17 00:00:00 2001 From: mintey Date: Sun, 28 Feb 2021 19:51:43 +0200 Subject: [PATCH] array based actions for chords instead of switch-case --- smol_gkos.ino | 300 +++++++++++++++++--------------------------------- 1 file changed, 99 insertions(+), 201 deletions(-) diff --git a/smol_gkos.ino b/smol_gkos.ino index 262d64b..c14c4b8 100644 --- a/smol_gkos.ino +++ b/smol_gkos.ino @@ -23,17 +23,7 @@ const byte PIN_BALL_SDA = 18; const byte PIN_BALL_SCL = 19; const byte PIN_BALL_INT = 11; -const byte BUTTON_A = 0; -const byte BUTTON_B = 1; -const byte BUTTON_C = 2; -const byte BUTTON_D = 3; -const byte BUTTON_E = 4; -const byte BUTTON_F = 5; -const byte BUTTON_MOUSE_UL = 6; -const byte BUTTON_MOUSE_UR = 7; -const byte BUTTON_MOUSE_DL = 8; -const byte BUTTON_MOUSE_DR = 9; - +enum Button { A, B, C, D, E, F, MouseUL, MouseUR, MouseDL, MouseDR }; const int button_pins[10] = { PIN_A, PIN_B, PIN_C, PIN_D, PIN_E, PIN_F, PIN_MOUSE_UL, PIN_MOUSE_UR, PIN_MOUSE_DL, PIN_MOUSE_DR @@ -41,12 +31,50 @@ const int button_pins[10] = { const int debounce_time = 400; int button_timers[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -// TODO: differentiate between GKOS modifiers and keyboard modifiers somehow +// different actions that the keyboard can take +// - print a single character +// - press (and release) a key +// - toggle a modifier +enum ActionType { PrintCharacter, PressKey, ToggleModifier }; + /* backspace, space (keep those two first since they overlap with the rest ) g, k, o, s, w, native */ -const byte modifiers[8] = { 7, 56, 24, 48, 3, 6, 40, 5 }; +const byte chords[8] = { 7, 56, 24, 48, 3, 6, 40, 5 }; +// buttons that can be combined with a chord for a keypress +const byte chord_buttons[24] = { + Button::D, Button::E, Button::F, + Button::A, Button::B, Button::C, + Button::A, Button::B, Button::C, + Button::A, Button::B, Button::C, + Button::D, Button::E, Button::F, + Button::D, Button::E, Button::F, + Button::A, Button::B, Button::C, + Button::D, Button::E, Button::F, +}; +// keypresses for chords in sets of 4 +// index 0 is the chord on its own, 1-3 correspond to chord_buttons +const int chord_targets[32] = { + KEY_BACKSPACE, KEY_LEFT, KEY_LEFT, KEY_HOME, + KEY_SPACE, KEY_RIGHT, KEY_RIGHT, KEY_END, + 'g', 'h', 'i', 'j', + 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', + 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', + ' ', ' ', ' ', ' ' +}; +const byte chord_target_types[32] = { + 1, 1, 1, 1, + 1, 1, 1, 1, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0 +}; /* dash, backslash, slash, apostrophe, comma, exclamation point, question mark, @@ -57,10 +85,6 @@ const byte specials[22] = { 17, 51, 30, 10, 20, 12, 33, 34, 9, 36, 27, 54, 18, 45, 63, 31, 47, 55, 62, 43, 61, 59 }; -enum SpecialType { PrintCharacter, PressKey, ToggleModifier }; -const byte special_action_types[22] = { - 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 1, 2, 2, 1, 1, 1, 1 -}; enum Modifier { Shift, SymbolShift, Keyset, Control, Alt }; const int special_action_targets[22] = { '-', '\\', '/', '\'', ',', '!', '?', '/', KEY_UP, KEY_DOWN, KEY_PAGE_UP, @@ -68,11 +92,14 @@ const int special_action_targets[22] = { KEY_ESC, Modifier::Control, Modifier::Alt, KEY_DELETE, KEY_INSERT, KEY_TAB, KEY_ENTER }; +const byte special_action_target_types[22] = { + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 1, 2, 2, 1, 1, 1, 1 +}; byte key_pressed = 0; byte key_pressed_total = 0; -bool modifier_used = false; -bool modified_pressed = false; +bool chord_used = false; +bool chorded_pressed = false; void setup() { pinMode(PIN_A, INPUT_PULLUP); @@ -121,8 +148,8 @@ void loop() { if (key_pressed == 0) { key_pressed_total = 0; // clear flags - modifier_used = false; - modified_pressed = false; + chord_used = false; + chorded_pressed = false; } } } @@ -145,229 +172,100 @@ void key_released(byte key) { } } - if (is_special && !modifier_used) { + if (is_special && !chord_used) { // only register a special keypress when all keys have been released if (key_pressed != 0) return; - switch (special_action_types[special]) { - case SpecialType::PrintCharacter: + switch (special_action_target_types[special]) { + case ActionType::PrintCharacter: Keyboard.print((char)special_action_targets[special]); return; - case SpecialType::PressKey: + case ActionType::PressKey: Keyboard.press(special_action_targets[special]); Keyboard.release(special_action_targets[special]); return; - case SpecialType::ToggleModifier: + case ActionType::ToggleModifier: // TODO return; } } /* - MODIFIERS + CHORDS */ - bool is_modifier = false; - byte modifier = 0; + bool is_chord = false; + byte chord = 0; for (byte b = 0; b < 8; b++) { - if ((key_pressed_total & modifiers[b]) == modifiers[b]) { - is_modifier = true; - modifier = b; - modifier_used = true; + if ((key_pressed_total & chords[b]) == chords[b]) { + is_chord = true; + chord = b; + chord_used = true; break; } } - if (is_modifier) { - switch (modifier) { - case 0: // backspace - if (!modified_pressed && key_pressed == 0 && - key_pressed_total == modifiers[modifier]) { - Keyboard.press(KEY_BACKSPACE); - Keyboard.release(KEY_BACKSPACE); + if (is_chord) { + // chord on its own + if (!chorded_pressed && key_pressed == 0 && + key_pressed_total == chords[chord]) { + switch (chord_target_types[chord * 4]) { + case ActionType::PrintCharacter: + Keyboard.print((char)chord_targets[chord * 4]); return; - } - if (key == BUTTON_D || key == BUTTON_E) { - Keyboard.press(KEY_LEFT); - Keyboard.release(KEY_LEFT); - key_pressed_total &= ~(1 << key); - modified_pressed = true; + case ActionType::PressKey: + Keyboard.press(chord_targets[chord * 4]); + Keyboard.release(chord_targets[chord * 4]); return; - } else if (key == BUTTON_F) { - Keyboard.press(KEY_HOME); - Keyboard.release(KEY_HOME); - key_pressed_total &= ~(1 << key); - modified_pressed = true; - return; - } - return; - case 1: // space - if (!modified_pressed && key_pressed == 0 && - key_pressed_total == modifiers[modifier]) { - Keyboard.press(KEY_SPACE); - Keyboard.release(KEY_SPACE); - return; - } - if (key == BUTTON_A || key == BUTTON_B) { - Keyboard.press(KEY_RIGHT); - Keyboard.release(KEY_RIGHT); - key_pressed_total &= ~(1 << key); - modified_pressed = true; - return; - } else if (key == BUTTON_C) { - Keyboard.press(KEY_END); - Keyboard.release(KEY_END); - key_pressed_total &= ~(1 << key); - modified_pressed = true; - return; - } - return; - case 2: // G - if (!modified_pressed && key_pressed == 0 && - key_pressed_total == modifiers[modifier]) { - Keyboard.print('g'); - return; - } - if (key == BUTTON_A) { - Keyboard.print('h'); - key_pressed_total &= ~(1 << key); - modified_pressed = true; - return; - } else if (key == BUTTON_B) { - Keyboard.print('i'); - key_pressed_total &= ~(1 << key); - modified_pressed = true; - return; - } else if (key == BUTTON_C) { - Keyboard.print('j'); - key_pressed_total &= ~(1 << key); - modified_pressed = true; - return; - } - return; - case 3: // K - if (!modified_pressed && key_pressed == 0 && - key_pressed_total == modifiers[modifier]) { - Keyboard.print('k'); - return; - } - if (key == BUTTON_A) { - Keyboard.print('l'); - key_pressed_total &= ~(1 << key); - modified_pressed = true; - return; - } else if (key == BUTTON_B) { - Keyboard.print('m'); - key_pressed_total &= ~(1 << key); - modified_pressed = true; - return; - } else if (key == BUTTON_C) { - Keyboard.print('n'); - key_pressed_total &= ~(1 << key); - modified_pressed = true; - return; - } - return; - case 4: // O - if (!modified_pressed && key_pressed == 0 && - key_pressed_total == modifiers[modifier]) { - Keyboard.print('o'); - return; - } - if (key == BUTTON_D) { - Keyboard.print('p'); - key_pressed_total &= ~(1 << key); - modified_pressed = true; - return; - } else if (key == BUTTON_E) { - Keyboard.print('q'); - key_pressed_total &= ~(1 << key); - modified_pressed = true; - return; - } else if (key == BUTTON_F) { - Keyboard.print('r'); - key_pressed_total &= ~(1 << key); - modified_pressed = true; - return; - } - return; - case 5: // S - if (!modified_pressed && key_pressed == 0 && - key_pressed_total == modifiers[modifier]) { - Keyboard.print('s'); - return; - } - if (key == BUTTON_D) { - Keyboard.print('t'); - key_pressed_total &= ~(1 << key); - modified_pressed = true; - return; - } else if (key == BUTTON_E) { - Keyboard.print('u'); - key_pressed_total &= ~(1 << key); - modified_pressed = true; - return; - } else if (key == BUTTON_F) { - Keyboard.print('v'); - key_pressed_total &= ~(1 << key); - modified_pressed = true; - return; - } - return; - case 6: // W - if (!modified_pressed && key_pressed == 0 && - key_pressed_total == modifiers[modifier]) { - Keyboard.print('w'); - return; - } - if (key == BUTTON_A) { - Keyboard.print('x'); - key_pressed_total &= ~(1 << key); - modified_pressed = true; - return; - } else if (key == BUTTON_B) { - Keyboard.print('y'); - key_pressed_total &= ~(1 << key); - modified_pressed = true; - return; - } else if (key == BUTTON_C) { - Keyboard.print('z'); - key_pressed_total &= ~(1 << key); - modified_pressed = true; - return; - } - return; - case 7: // native - // TODO - return; + } + return; } + // keys that can be chorded with + for (byte b = 0; b < 3; b++) { + if (key == chord_buttons[chord * 3 + b]) { + Serial.print(chord); + Serial.println(" pressed"); + // erase key from total so you can hold the chord down for + // multiple chorded keypresses + key_pressed_total &= ~(1 << key); + chorded_pressed = true; + switch (chord_target_types[chord * 4 + 1 + b]) { + case ActionType::PrintCharacter: + Keyboard.print((char)chord_targets[chord * 4 + 1 + b]); + return; + case ActionType::PressKey: + Keyboard.press(chord_targets[chord * 4 + 1 + b]); + Keyboard.release(chord_targets[chord * 4 + 1 + b]); + return; + } + } + } + return; } /* REGULAR KEYS */ switch (key) { - case BUTTON_A: + case Button::A: Keyboard.print('a'); return; - case BUTTON_B: + case Button::B: Keyboard.print('b'); return; - case BUTTON_C: + case Button::C: Keyboard.print('c'); return; - case BUTTON_D: + case Button::D: Keyboard.print('d'); return; - case BUTTON_E: + case Button::E: Keyboard.print('e'); return; - case BUTTON_F: + case Button::F: Keyboard.print('f'); return; default: - Serial.print("unknown key "); - Serial.println(key); return; } }