From ec0f7eda734688de86b2c0b1bc3e140230ee8358 Mon Sep 17 00:00:00 2001 From: mintey Date: Tue, 2 Mar 2021 20:37:31 +0200 Subject: [PATCH] modifier keys and mousegit diff --cached --- smol_gkos.ino | 310 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 207 insertions(+), 103 deletions(-) diff --git a/smol_gkos.ino b/smol_gkos.ino index 6fd3864..e13fa69 100644 --- a/smol_gkos.ino +++ b/smol_gkos.ino @@ -3,6 +3,10 @@ #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; @@ -21,25 +25,24 @@ 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 = 400; +const int debounce_time = 50; 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 { PrintCharacter, PressKey, ToggleModifier }; +enum ActionType { PressKey, ToggleModifier }; -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' }; +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 +}; /* backspace, space (keep those two first since they overlap with the rest ) @@ -62,44 +65,27 @@ 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, - 'g', 'h', 'i', 'j', - 'k', 'l', 'm', 'n', - 'o', 'p', 'q', 'r', - 's', 't', 'u', 'v', - 'w', 'x', 'y', 'z', + 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, 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, - '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 + 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, }; /* @@ -107,25 +93,34 @@ 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_UP, KEY_DOWN, KEY_PAGE_UP, - KEY_PAGE_DOWN, Modifier::Shift, Modifier::SymbolShift, Modifier::Keyset, +// - \ / ' + 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_ESC, Modifier::Control, Modifier::Alt, KEY_DELETE, KEY_INSERT, KEY_TAB, KEY_ENTER }; const int special_action_targets_symbol[22] = { - '_', '\`', 0, '\"', ';', '|', '~', ':', 0, 0, 0, +// _ ` ´ " + 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 }; 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 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0 }; byte key_pressed = 0; @@ -137,9 +132,23 @@ 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 mouse_scroll_sensitivity = 10; +int mouse_scroll_dist = 0; +bool mouse_middle_pressed = false; +bool mouse_scrolled = false; void setup() { pinMode(PIN_A, INPUT_PULLUP); @@ -158,35 +167,55 @@ void setup() { pinMode(PIN_LED2, OUTPUT); pinMode(PIN_LED3, OUTPUT); - Serial.begin(115200); - Serial.println("helo"); + // poll trackball at 100Hz + trackball_timer.begin(trackball_isr, 1000); + Serial.begin(115200); 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]++; - // update pressed gkos keys - else if (b < 6) { - key_pressed |= 1 << b; - key_pressed_total |= 1 << b; + 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 is released else { - // if the button had been debounced, it counts as a keypress + // if the button had been debounced, it counts as a press if (button_timers[b] >= debounce_time) { + // gkos key released if (b < 6) { key_pressed &= ~(1 << 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; + // check if it completed a chord + key_released(b); update_leds(); if (key_pressed == 0) { key_pressed_total = 0; @@ -195,14 +224,65 @@ 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; + 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; + 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(sign(mouse_x) * mouse_x * mouse_x, + sign(mouse_y) * mouse_y * mouse_y); + } + + trackball_update = false; + } + interrupts(); } // returns true if a keypress was completed -bool key_released(byte key) { +void key_released(byte key) { int target = 0; /* @@ -221,7 +301,7 @@ bool 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 false; + return; target = special_action_targets[special]; if (mod_shift || mod_shift_lock || mod_symbol || mod_symbol_lock) { @@ -230,13 +310,9 @@ bool key_released(byte key) { } switch (special_action_target_types[special]) { - case ActionType::PrintCharacter: - Keyboard.print((char)target); - return true; case ActionType::PressKey: - Keyboard.press(target); - Keyboard.release(target); - return true; + press_key(target); + return; case ActionType::ToggleModifier: switch (target) { case Modifier::Shift: @@ -249,24 +325,24 @@ bool key_released(byte key) { } else { mod_shift = true; } - return false; + return; case Modifier::SymbolShift: mod_shift = mod_shift_lock = mod_symbol_lock = false; mod_symbol = !mod_symbol; - return false; + return; case Modifier::Keyset: mod_shift = mod_shift_lock = mod_symbol = false; mod_symbol_lock = !mod_symbol_lock; - return false; + return; case Modifier::Control: mod_control = !mod_control; - return false; + return; case Modifier::Alt: mod_alt = !mod_alt; - return false; + return; } } - return false; + return; } /* @@ -288,59 +364,78 @@ bool key_released(byte key) { if (!chorded_pressed && key_pressed == 0 && key_pressed_total == chords[chord]) { target = chord_targets[chord * 4]; - if (mod_shift || mod_shift_lock) - target = chord_targets_shifted[chord * 4]; - else if (mod_symbol || mod_symbol_lock) + if (mod_symbol || mod_symbol_lock) target = chord_targets_symbol[chord * 4]; - 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; + press_key(target); + return; } // 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_shift || mod_shift_lock) - target = chord_targets_shifted[chord * 4 + 1 + b]; - else if (mod_symbol || mod_symbol_lock) + 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; - 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; - } + press_key(target); + return; } } - return false; + return; } /* REGULAR KEYS */ - 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]); + // keypress + if (mod_symbol || mod_symbol_lock) + press_key(button_characters_symbol[key]); else - Keyboard.print(button_characters[key]); - return true; + 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; } void update_leds() { @@ -348,3 +443,12 @@ 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; +}