Compare commits

..

No commits in common. "2ab8d0a68aa667c8fc8fec1f750928b3fdf6f679" and "c7de79c4e5416fd8174e995609ad9e96143e68cc" have entirely different histories.

View file

@ -3,10 +3,6 @@
#define TRACKBALL_ADDR 0x0A #define TRACKBALL_ADDR 0x0A
#define TRACKBALL_REG_LEFT 0x04 #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_A = 33;
const byte PIN_B = 32; const byte PIN_B = 32;
const byte PIN_C = 31; const byte PIN_C = 31;
@ -25,24 +21,25 @@ const byte PIN_LED3 = 3;
const byte PIN_BALL_SDA = 18; const byte PIN_BALL_SDA = 18;
const byte PIN_BALL_SCL = 19; const byte PIN_BALL_SCL = 19;
const byte PIN_BALL_INT = 11;
enum Button { A, B, C, D, E, F, MouseUL, MouseUR, MouseDL, MouseDR }; enum Button { A, B, C, D, E, F, MouseUL, MouseUR, MouseDL, MouseDR };
const int button_pins[10] = { const int button_pins[10] = {
PIN_A, PIN_B, PIN_C, PIN_D, PIN_E, PIN_F, PIN_A, PIN_B, PIN_C, PIN_D, PIN_E, PIN_F,
PIN_MOUSE_UL, PIN_MOUSE_UR, PIN_MOUSE_DL, PIN_MOUSE_DR 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 }; int button_timers[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
// different actions that the keyboard can take // different actions that the keyboard can take
// - print a single character
// - press (and release) a key // - press (and release) a key
// - toggle a modifier // - 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 char button_characters[6] = { 'a', 'b', 'c', 'd', 'e', 'f' };
const int button_characters_symbol[6] = { const char button_characters_shifted[6] = { 'A', 'B', 'C', 'D', 'E', 'F' };
KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6 const char button_characters_symbol[6] = { '1', '2', '3', '4', '5', '6' };
};
/* /*
backspace, space (keep those two first since they overlap with the rest ) 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] = { const int chord_targets[32] = {
KEY_BACKSPACE, KEY_LEFT, KEY_LEFT, KEY_HOME, KEY_BACKSPACE, KEY_LEFT, KEY_LEFT, KEY_HOME,
KEY_SPACE, KEY_RIGHT, KEY_RIGHT, KEY_END, KEY_SPACE, KEY_RIGHT, KEY_RIGHT, KEY_END,
KEY_G, KEY_H, KEY_I, KEY_J, 'g', 'h', 'i', 'j',
KEY_K, KEY_L, KEY_M, KEY_N, 'k', 'l', 'm', 'n',
KEY_O, KEY_P, KEY_Q, KEY_R, 'o', 'p', 'q', 'r',
KEY_S, KEY_T, KEY_U, KEY_V, 's', 't', 'u', 'v',
KEY_W, KEY_X, KEY_Y, KEY_Z, 'w', 'x', 'y', 'z',
0, 0, 0, 0 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] = { const int chord_targets_symbol[32] = {
KEY_BACKSPACE, KEY_LEFT, KEY_LEFT, KEY_HOME, KEY_BACKSPACE, KEY_LEFT, KEY_LEFT, KEY_HOME,
KEY_SPACE, KEY_RIGHT, KEY_RIGHT, KEY_END, KEY_SPACE, KEY_RIGHT, KEY_RIGHT, KEY_END,
KEY_0, KEY_7, KEY_8, KEY_9, '0', '7', '8', '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, };
// ( [ < { const byte chord_target_types[32] = {
KEY_9 + MASK_SHIFT, KEY_LEFT_BRACE, KEY_COMMA + MASK_SHIFT, KEY_LEFT_BRACE + MASK_SHIFT, 1, 1, 1, 1,
// ) ] > } 1, 1, 1, 1,
KEY_0 + MASK_SHIFT, KEY_RIGHT_BRACE, KEY_PERIOD + MASK_SHIFT, KEY_RIGHT_BRACE + MASK_SHIFT, 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, period, up, down, page up, page down, shift, symbol shift, switch keyset,
escape, control, alt, delete, insert, tab, enter escape, control, alt, delete, insert, tab, enter
*/ */
// TODO: add the middle specials for function keys instead of the weird symbols
const byte specials[22] = { const byte specials[22] = {
17, 51, 30, 10, 20, 12, 33, 34, 9, 36, 27, 17, 51, 30, 10, 20, 12, 33, 34, 9, 36, 27,
54, 18, 45, 63, 31, 47, 55, 62, 43, 61, 59 54, 18, 45, 63, 31, 47, 55, 62, 43, 61, 59
}; };
enum Modifier { Shift, SymbolShift, Keyset, Control, Alt }; enum Modifier { Shift, SymbolShift, Keyset, Control, Alt };
const int special_action_targets[22] = { const int special_action_targets[22] = {
// - \ / ' '-', '\\', '/', '\'', ',', '!', '?', '/', KEY_UP, KEY_DOWN, KEY_PAGE_UP,
KEY_MINUS, KEY_MINUS + MASK_ALTGR, KEY_SLASH, KEY_QUOTE, KEY_PAGE_DOWN, Modifier::Shift, Modifier::SymbolShift, Modifier::Keyset,
// , ! ? .
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_ESC, Modifier::Control, Modifier::Alt, KEY_DELETE, KEY_INSERT,
KEY_TAB, KEY_ENTER KEY_TAB, KEY_ENTER
}; };
const int special_action_targets_symbol[22] = { 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, 0, 0, 0, 0, 0, 0, 0,
0, 0 0, 0
}; };
const byte special_action_target_types[22] = { 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; byte key_pressed = 0;
@ -132,29 +137,9 @@ bool mod_shift = false;
bool mod_shift_lock = false; bool mod_shift_lock = false;
bool mod_symbol = false; bool mod_symbol = false;
bool mod_symbol_lock = false; bool mod_symbol_lock = false;
// TODO: control and alt modifiers
bool mod_control = false; bool mod_control = false;
bool mod_alt = 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() { void setup() {
pinMode(PIN_A, INPUT_PULLUP); pinMode(PIN_A, INPUT_PULLUP);
@ -173,54 +158,35 @@ void setup() {
pinMode(PIN_LED2, OUTPUT); pinMode(PIN_LED2, OUTPUT);
pinMode(PIN_LED3, OUTPUT); pinMode(PIN_LED3, OUTPUT);
// poll trackball at 10kHz Serial.begin(115200);
trackball_timer.begin(trackball_isr, 100); Serial.println("helo");
Wire.begin(); Wire.begin();
} }
void loop() { void loop() {
/*
BUTTONS
*/
for (byte b = 0; b < 10; b++) { for (byte b = 0; b < 10; b++) {
// button is pressed // button is pressed
if (!digitalRead(button_pins[b])) { if (!digitalRead(button_pins[b])) {
// increment button timer if it's not full // increment button timer if it's not full
if (button_timers[b] < debounce_time) if (button_timers[b] < debounce_time)
button_timers[b]++; button_timers[b]++;
else { // update pressed gkos keys
// update pressed gkos keys else if (b < 6) {
if (b < 6) { key_pressed |= 1 << b;
key_pressed |= 1 << b; key_pressed_total |= 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 // button is released
else { 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) { if (button_timers[b] >= debounce_time) {
// gkos key released
if (b < 6) { if (b < 6) {
key_pressed &= ~(1 << b); key_pressed &= ~(1 << b);
// check if it completed a chord // gkos key was released, check if it completed a chord
key_released(b); // clear temporary modifiers if a keypress was completed
if (key_released(b))
mod_shift = mod_symbol = mod_control = mod_alt = false;
update_leds(); update_leds();
if (key_pressed == 0) { if (key_pressed == 0) {
key_pressed_total = 0; key_pressed_total = 0;
@ -229,74 +195,14 @@ void loop() {
chorded_pressed = false; 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; 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 // returns true if a keypress was completed
void key_released(byte key) { bool key_released(byte key) {
int target = 0; int target = 0;
/* /*
@ -315,7 +221,7 @@ void key_released(byte key) {
if (is_special && !chord_used) { if (is_special && !chord_used) {
// only register a special keypress when all keys have been released // only register a special keypress when all keys have been released
if (key_pressed != 0) if (key_pressed != 0)
return; return false;
target = special_action_targets[special]; target = special_action_targets[special];
if (mod_shift || mod_shift_lock || mod_symbol || mod_symbol_lock) { 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]) { switch (special_action_target_types[special]) {
case ActionType::PrintCharacter:
Keyboard.print((char)target);
return true;
case ActionType::PressKey: case ActionType::PressKey:
press_key(target); Keyboard.press(target);
return; Keyboard.release(target);
return true;
case ActionType::ToggleModifier: case ActionType::ToggleModifier:
switch (target) { switch (target) {
case Modifier::Shift: case Modifier::Shift:
@ -339,24 +249,24 @@ void key_released(byte key) {
} else { } else {
mod_shift = true; mod_shift = true;
} }
return; return false;
case Modifier::SymbolShift: case Modifier::SymbolShift:
mod_shift = mod_shift_lock = mod_symbol_lock = false; mod_shift = mod_shift_lock = mod_symbol_lock = false;
mod_symbol = !mod_symbol; mod_symbol = !mod_symbol;
return; return false;
case Modifier::Keyset: case Modifier::Keyset:
mod_shift = mod_shift_lock = mod_symbol = false; mod_shift = mod_shift_lock = mod_symbol = false;
mod_symbol_lock = !mod_symbol_lock; mod_symbol_lock = !mod_symbol_lock;
return; return false;
case Modifier::Control: case Modifier::Control:
mod_control = !mod_control; mod_control = !mod_control;
return; return false;
case Modifier::Alt: case Modifier::Alt:
mod_alt = !mod_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 && if (!chorded_pressed && key_pressed == 0 &&
key_pressed_total == chords[chord]) { key_pressed_total == chords[chord]) {
target = chord_targets[chord * 4]; 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]; target = chord_targets_symbol[chord * 4];
press_key(target); switch (chord_target_types[chord * 4]) {
return; 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 // keys that can be chorded with
for (byte b = 0; b < 3; b++) { for (byte b = 0; b < 3; b++) {
if (key == chord_buttons[chord * 3 + b]) { if (key == chord_buttons[chord * 3 + b]) {
target = chord_targets[chord * 4 + 1 + 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]; target = chord_targets_symbol[chord * 4 + 1 + b];
// erase key from total so you can hold the chord down for // erase key from total so you can hold the chord down for
// multiple chorded keypresses // multiple chorded keypresses
key_pressed_total &= ~(1 << key); key_pressed_total &= ~(1 << key);
chorded_pressed = true; chorded_pressed = true;
press_key(target); switch (chord_target_types[chord * 4 + 1 + b]) {
return; 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 REGULAR KEYS
*/ */
// keypress if (mod_shift || mod_shift_lock)
if (mod_symbol || mod_symbol_lock) Keyboard.print(button_characters_shifted[key]);
press_key(button_characters_symbol[key]); else if (mod_symbol || mod_symbol_lock)
Keyboard.print(button_characters_symbol[key]);
else else
press_key(button_characters[key]); Keyboard.print(button_characters[key]);
return; return true;
}
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() { void update_leds() {
@ -457,12 +348,3 @@ void update_leds() {
digitalWrite(PIN_LED2, mod_symbol || mod_symbol_lock); digitalWrite(PIN_LED2, mod_symbol || mod_symbol_lock);
digitalWrite(PIN_LED3, mod_control || mod_alt); digitalWrite(PIN_LED3, mod_control || mod_alt);
} }
int sign(int num) {
if (num >= 0) return 1;
return -1;
}
void trackball_isr() {
trackball_update = true;
}