diff --git a/smol_gkos.ino b/smol_gkos.ino index f3c8dd8..6fd3864 100644 --- a/smol_gkos.ino +++ b/smol_gkos.ino @@ -3,10 +3,6 @@ #define TRACKBALL_ADDR 0x0A #define TRACKBALL_REG_LEFT 0x04 -// using my own masks here since the inbuilt ones conflict with arrow keys etc. -#define MASK_SHIFT 0x100 -#define MASK_ALTGR 0x200 - const byte PIN_A = 33; const byte PIN_B = 32; const byte PIN_C = 31; @@ -25,24 +21,25 @@ const byte PIN_LED3 = 3; const byte PIN_BALL_SDA = 18; const byte PIN_BALL_SCL = 19; +const byte PIN_BALL_INT = 11; 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 }; -const int debounce_time = 50; +const int debounce_time = 400; int button_timers[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // different actions that the keyboard can take +// - print a single character // - press (and release) a key // - toggle a modifier -enum ActionType { PressKey, ToggleModifier }; +enum ActionType { PrintCharacter, PressKey, ToggleModifier }; -const int button_characters[6] = { KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F }; -const int button_characters_symbol[6] = { - KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6 -}; +const char button_characters[6] = { 'a', 'b', 'c', 'd', 'e', 'f' }; +const char button_characters_shifted[6] = { 'A', 'B', 'C', 'D', 'E', 'F' }; +const char button_characters_symbol[6] = { '1', '2', '3', '4', '5', '6' }; /* backspace, space (keep those two first since they overlap with the rest ) @@ -65,27 +62,44 @@ const byte chord_buttons[24] = { const int chord_targets[32] = { KEY_BACKSPACE, KEY_LEFT, KEY_LEFT, KEY_HOME, KEY_SPACE, KEY_RIGHT, KEY_RIGHT, KEY_END, - KEY_G, KEY_H, KEY_I, KEY_J, - KEY_K, KEY_L, KEY_M, KEY_N, - KEY_O, KEY_P, KEY_Q, KEY_R, - KEY_S, KEY_T, KEY_U, KEY_V, - KEY_W, KEY_X, KEY_Y, KEY_Z, + 'g', 'h', 'i', 'j', + 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', + 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', 0, 0, 0, 0 }; +const int chord_targets_shifted[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', + 0, 0, 0, 0 +}; +// TODO: check that all the symbols work +// TODO: match symbols to keypresses in the keyboard layout const int chord_targets_symbol[32] = { KEY_BACKSPACE, KEY_LEFT, KEY_LEFT, KEY_HOME, KEY_SPACE, KEY_RIGHT, KEY_RIGHT, KEY_END, - KEY_0, KEY_7, KEY_8, KEY_9, -// # @ ½ & - KEY_BACKSLASH, KEY_QUOTE + MASK_SHIFT, KEY_5 + MASK_ALTGR, KEY_7 + MASK_SHIFT, -// + % = ^ - KEY_EQUAL + MASK_SHIFT, KEY_5 + MASK_SHIFT, KEY_EQUAL, KEY_6 + MASK_SHIFT, -// * $ € £ - KEY_8 + MASK_SHIFT, KEY_4 + MASK_SHIFT, KEY_4 + MASK_ALTGR, KEY_3 + MASK_SHIFT, -// ( [ < { - KEY_9 + MASK_SHIFT, KEY_LEFT_BRACE, KEY_COMMA + MASK_SHIFT, KEY_LEFT_BRACE + MASK_SHIFT, -// ) ] > } - KEY_0 + MASK_SHIFT, KEY_RIGHT_BRACE, KEY_PERIOD + MASK_SHIFT, KEY_RIGHT_BRACE + MASK_SHIFT, + '0', '7', '8', '9', + '#', '@', '½', '&', + '+', '%', '=', '^', + '*', '$', '€', '£', + '(', '[', '<', '{', + ')', ']', '>', '}' +}; +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 }; /* @@ -93,34 +107,25 @@ dash, backslash, slash, apostrophe, comma, exclamation point, question mark, period, up, down, page up, page down, shift, symbol shift, switch keyset, escape, control, alt, delete, insert, tab, enter */ -// TODO: add the middle specials for function keys instead of the weird symbols 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 Modifier { Shift, SymbolShift, Keyset, Control, Alt }; const int special_action_targets[22] = { -// - \ / ' - KEY_MINUS, KEY_MINUS + MASK_ALTGR, KEY_SLASH, KEY_QUOTE, -// , ! ? . - KEY_COMMA, KEY_1 + MASK_SHIFT, KEY_SLASH + MASK_SHIFT, KEY_PERIOD, - KEY_UP, KEY_DOWN, KEY_PAGE_UP, KEY_PAGE_DOWN, - Modifier::Shift, Modifier::SymbolShift, Modifier::Keyset, + '-', '\\', '/', '\'', ',', '!', '?', '/', KEY_UP, KEY_DOWN, KEY_PAGE_UP, + KEY_PAGE_DOWN, Modifier::Shift, Modifier::SymbolShift, Modifier::Keyset, KEY_ESC, Modifier::Control, Modifier::Alt, KEY_DELETE, KEY_INSERT, KEY_TAB, KEY_ENTER }; const int special_action_targets_symbol[22] = { -// _ ` ´ " - KEY_MINUS + MASK_SHIFT, KEY_TILDE, KEY_SEMICOLON + MASK_ALTGR, KEY_2 + MASK_SHIFT, -// ; | ~ : - KEY_SEMICOLON, KEY_TILDE + MASK_ALTGR, KEY_BACKSLASH + MASK_SHIFT, KEY_SEMICOLON + MASK_SHIFT, + '_', '\`', 0, '\"', ';', '|', '~', ':', 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; const byte special_action_target_types[22] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0 + 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; @@ -132,29 +137,9 @@ bool mod_shift = false; bool mod_shift_lock = false; bool mod_symbol = false; bool mod_symbol_lock = false; +// TODO: control and alt modifiers bool mod_control = false; bool mod_alt = false; -bool mod_altgr = false; - -IntervalTimer trackball_timer; -volatile bool trackball_update = false; - -byte mouse_up = 0; -byte mouse_down = 0; -byte mouse_left = 0; -byte mouse_right = 0; -bool mouse_button = false; - -const int num_mouse_samples = 10; -int current_mouse_sample = 0; -int mouse_movement_sample = 0; -float mouse_acceleration = 0.0f; -const float mouse_accel_factor = 0.7f; - -const int mouse_scroll_sensitivity = 6; -int mouse_scroll_dist = 0; -bool mouse_middle_pressed = false; -bool mouse_scrolled = false; void setup() { pinMode(PIN_A, INPUT_PULLUP); @@ -173,54 +158,35 @@ void setup() { pinMode(PIN_LED2, OUTPUT); pinMode(PIN_LED3, OUTPUT); - // poll trackball at 10kHz - trackball_timer.begin(trackball_isr, 100); + Serial.begin(115200); + Serial.println("helo"); Wire.begin(); } void loop() { - /* - BUTTONS - */ for (byte b = 0; b < 10; b++) { // button is pressed if (!digitalRead(button_pins[b])) { // increment button timer if it's not full if (button_timers[b] < debounce_time) - button_timers[b]++; - else { - // update pressed gkos keys - if (b < 6) { - key_pressed |= 1 << b; - key_pressed_total |= 1 << b; - } - // update pressed mouse keys - else { - switch (b) { - case Button::MouseUL: - Mouse.press(MOUSE_LEFT); - break; - case Button::MouseUR: - Mouse.press(MOUSE_RIGHT); - break; - case Button::MouseDL: - case Button::MouseDR: - mouse_middle_pressed = true; - break; - } - } + button_timers[b]++; + // update pressed gkos keys + else if (b < 6) { + key_pressed |= 1 << b; + key_pressed_total |= 1 << b; } } // button is released else { - // if the button had been debounced, it counts as a press + // if the button had been debounced, it counts as a keypress if (button_timers[b] >= debounce_time) { - // gkos key released if (b < 6) { key_pressed &= ~(1 << b); - // check if it completed a chord - key_released(b); + // gkos key was released, check if it completed a chord + // clear temporary modifiers if a keypress was completed + if (key_released(b)) + mod_shift = mod_symbol = mod_control = mod_alt = false; update_leds(); if (key_pressed == 0) { key_pressed_total = 0; @@ -229,74 +195,14 @@ void loop() { chorded_pressed = false; } } - // mouse button released - else { - switch (b) { - case Button::MouseUL: - Mouse.release(MOUSE_LEFT); - break; - case Button::MouseUR: - Mouse.release(MOUSE_RIGHT); - break; - case Button::MouseDL: - case Button::MouseDR: - if (!mouse_scrolled) - Mouse.click(MOUSE_MIDDLE); - mouse_middle_pressed = mouse_scrolled = false; - mouse_scroll_dist = 0; - break; - } - } } button_timers[b] = 0; } } - - /* - TRACKBALL - */ - noInterrupts(); - if (trackball_update) { - Wire.beginTransmission(TRACKBALL_ADDR); - Wire.write(TRACKBALL_REG_LEFT); - Wire.endTransmission(); - - Wire.requestFrom(TRACKBALL_ADDR, 5); - mouse_left = Wire.read(); - mouse_right = Wire.read(); - mouse_up = Wire.read(); - mouse_down = Wire.read(); - mouse_button = Wire.read(); - - int mouse_x = mouse_right - mouse_left; - int mouse_y = mouse_down - mouse_up; - - mouse_movement_sample += abs(mouse_x) + abs(mouse_y); - current_mouse_sample++; - if (current_mouse_sample > num_mouse_samples) { - current_mouse_sample = 0; - mouse_acceleration = 1.0f + mouse_movement_sample * mouse_accel_factor; - mouse_movement_sample = 0; - } - - if (mouse_middle_pressed) { - mouse_scroll_dist += mouse_y; - if (abs(mouse_scroll_dist) > mouse_scroll_sensitivity) { - Mouse.scroll(mouse_scroll_dist % mouse_scroll_sensitivity); - mouse_scroll_dist %= mouse_scroll_sensitivity; - mouse_scrolled = true; - } - } else { - Mouse.move(mouse_x * mouse_acceleration, mouse_y * mouse_acceleration); - } - - trackball_update = false; - } - interrupts(); } // returns true if a keypress was completed -void key_released(byte key) { +bool key_released(byte key) { int target = 0; /* @@ -315,7 +221,7 @@ void key_released(byte key) { if (is_special && !chord_used) { // only register a special keypress when all keys have been released if (key_pressed != 0) - return; + return false; target = special_action_targets[special]; if (mod_shift || mod_shift_lock || mod_symbol || mod_symbol_lock) { @@ -324,9 +230,13 @@ void key_released(byte key) { } switch (special_action_target_types[special]) { + case ActionType::PrintCharacter: + Keyboard.print((char)target); + return true; case ActionType::PressKey: - press_key(target); - return; + Keyboard.press(target); + Keyboard.release(target); + return true; case ActionType::ToggleModifier: switch (target) { case Modifier::Shift: @@ -339,24 +249,24 @@ void key_released(byte key) { } else { mod_shift = true; } - return; + return false; case Modifier::SymbolShift: mod_shift = mod_shift_lock = mod_symbol_lock = false; mod_symbol = !mod_symbol; - return; + return false; case Modifier::Keyset: mod_shift = mod_shift_lock = mod_symbol = false; mod_symbol_lock = !mod_symbol_lock; - return; + return false; case Modifier::Control: mod_control = !mod_control; - return; + return false; case Modifier::Alt: mod_alt = !mod_alt; - return; + return false; } } - return; + return false; } /* @@ -378,78 +288,59 @@ void key_released(byte key) { if (!chorded_pressed && key_pressed == 0 && key_pressed_total == chords[chord]) { target = chord_targets[chord * 4]; - if (mod_symbol || mod_symbol_lock) + if (mod_shift || mod_shift_lock) + target = chord_targets_shifted[chord * 4]; + else if (mod_symbol || mod_symbol_lock) target = chord_targets_symbol[chord * 4]; - press_key(target); - return; + switch (chord_target_types[chord * 4]) { + case ActionType::PrintCharacter: + Keyboard.print((char)target); + return true; + case ActionType::PressKey: + Keyboard.press(target); + Keyboard.release(target); + return true; + } + return false; } // keys that can be chorded with for (byte b = 0; b < 3; b++) { if (key == chord_buttons[chord * 3 + b]) { target = chord_targets[chord * 4 + 1 + b]; - if (mod_symbol || mod_symbol_lock) + if (mod_shift || mod_shift_lock) + target = chord_targets_shifted[chord * 4 + 1 + b]; + else if (mod_symbol || mod_symbol_lock) target = chord_targets_symbol[chord * 4 + 1 + b]; // erase key from total so you can hold the chord down for // multiple chorded keypresses key_pressed_total &= ~(1 << key); chorded_pressed = true; - press_key(target); - return; + switch (chord_target_types[chord * 4 + 1 + b]) { + case ActionType::PrintCharacter: + Keyboard.print((char)target); + return true; + case ActionType::PressKey: + Keyboard.press(target); + Keyboard.release(target); + return true; + } } } - return; + return false; } /* REGULAR KEYS */ - // keypress - if (mod_symbol || mod_symbol_lock) - press_key(button_characters_symbol[key]); + if (mod_shift || mod_shift_lock) + Keyboard.print(button_characters_shifted[key]); + else if (mod_symbol || mod_symbol_lock) + Keyboard.print(button_characters_symbol[key]); else - press_key(button_characters[key]); - return; -} - -void press_key(int key) { - // check if modifiers need to be forced - if (key & MASK_SHIFT) { - mod_shift = true; - key &= ~(MASK_SHIFT); - } - if (key & MASK_ALTGR) { - mod_altgr = true; - key &= ~(MASK_ALTGR); - } - - // modifiers - if (mod_shift || mod_shift_lock) - Keyboard.press(KEY_LEFT_SHIFT); - if (mod_control) - Keyboard.press(KEY_LEFT_CTRL); - if (mod_alt) - Keyboard.press(KEY_LEFT_ALT); - if (mod_altgr) - Keyboard.press(KEY_RIGHT_ALT); - - // keypress - Keyboard.press(key); - Keyboard.release(key); - - // release modifiers - if (mod_shift || mod_shift_lock) - Keyboard.release(KEY_LEFT_SHIFT); - if (mod_control) - Keyboard.release(KEY_LEFT_CTRL); - if (mod_alt) - Keyboard.release(KEY_LEFT_ALT); - if (mod_altgr) - Keyboard.release(KEY_RIGHT_ALT); - - // clear temporary modifiers - mod_shift = mod_symbol = mod_control = mod_alt = mod_altgr = false; + Keyboard.print(button_characters[key]); + return true; } void update_leds() { @@ -457,12 +348,3 @@ void update_leds() { digitalWrite(PIN_LED2, mod_symbol || mod_symbol_lock); digitalWrite(PIN_LED3, mod_control || mod_alt); } - -int sign(int num) { - if (num >= 0) return 1; - return -1; -} - -void trackball_isr() { - trackball_update = true; -}