Compare commits
4 commits
1544096980
...
908543ebd1
Author | SHA1 | Date | |
---|---|---|---|
908543ebd1 | |||
27ae56c00d | |||
17642f5c51 | |||
60ffa7635d |
1 changed files with 429 additions and 0 deletions
429
smol_gkos.ino
Normal file
429
smol_gkos.ino
Normal file
|
@ -0,0 +1,429 @@
|
|||
#include <Wire.h>
|
||||
|
||||
#define TRACKBALL_ADDR 0x0A
|
||||
#define TRACKBALL_REG_LEFT 0x04
|
||||
|
||||
const byte PIN_A = 33;
|
||||
const byte PIN_B = 32;
|
||||
const byte PIN_C = 31;
|
||||
const byte PIN_D = 24;
|
||||
const byte PIN_E = 25;
|
||||
const byte PIN_F = 26;
|
||||
|
||||
const byte PIN_MOUSE_UL = 27;
|
||||
const byte PIN_MOUSE_UR = 30;
|
||||
const byte PIN_MOUSE_DL = 28;
|
||||
const byte PIN_MOUSE_DR = 29;
|
||||
|
||||
const byte PIN_LED1 = 6;
|
||||
const byte PIN_LED2 = 1;
|
||||
const byte PIN_LED3 = 3;
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
int button_timers[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
/*
|
||||
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 };
|
||||
|
||||
/*
|
||||
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
|
||||
*/
|
||||
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
|
||||
};
|
||||
|
||||
byte key_pressed = 0;
|
||||
byte key_pressed_total = 0;
|
||||
bool modifier_used = false;
|
||||
bool modified_pressed = false;
|
||||
|
||||
void setup() {
|
||||
pinMode(PIN_A, INPUT_PULLUP);
|
||||
pinMode(PIN_B, INPUT_PULLUP);
|
||||
pinMode(PIN_C, INPUT_PULLUP);
|
||||
pinMode(PIN_D, INPUT_PULLUP);
|
||||
pinMode(PIN_E, INPUT_PULLUP);
|
||||
pinMode(PIN_F, INPUT_PULLUP);
|
||||
|
||||
pinMode(PIN_MOUSE_UL, INPUT_PULLUP);
|
||||
pinMode(PIN_MOUSE_UR, INPUT_PULLUP);
|
||||
pinMode(PIN_MOUSE_DL, INPUT_PULLUP);
|
||||
pinMode(PIN_MOUSE_DR, INPUT_PULLUP);
|
||||
|
||||
pinMode(PIN_LED1, OUTPUT);
|
||||
pinMode(PIN_LED2, OUTPUT);
|
||||
pinMode(PIN_LED3, OUTPUT);
|
||||
|
||||
Serial.begin(115200);
|
||||
Serial.println("helo");
|
||||
|
||||
Wire.begin();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
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 is released
|
||||
else {
|
||||
// if the button had been debounced, it counts as a keypress
|
||||
if (button_timers[b] >= debounce_time) {
|
||||
if (b < 6) {
|
||||
key_pressed &= ~(1 << b);
|
||||
// gkos key was released, check if it completed a chord
|
||||
key_released(b);
|
||||
if (key_pressed == 0) {
|
||||
key_pressed_total = 0;
|
||||
// clear flags
|
||||
modifier_used = false;
|
||||
modified_pressed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
button_timers[b] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void key_released(byte key) {
|
||||
/*
|
||||
SPECIALS
|
||||
*/
|
||||
bool is_special = false;
|
||||
byte special = 0;
|
||||
for (byte b = 0; b < 22; b++) {
|
||||
if (key_pressed_total == specials[b]) {
|
||||
is_special = true;
|
||||
special = b;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (is_special && !modifier_used) {
|
||||
Serial.print("special ");
|
||||
Serial.println(specials[special]);
|
||||
|
||||
// only register a special keypress when all keys have been released
|
||||
if (key_pressed != 0)
|
||||
return;
|
||||
|
||||
switch (special) {
|
||||
case 0: // dash
|
||||
Keyboard.print('-');
|
||||
return;
|
||||
case 1: // backslash
|
||||
Keyboard.print('\\');
|
||||
return;
|
||||
case 2: // slash
|
||||
Keyboard.print('/');
|
||||
return;
|
||||
case 3: // apostrophe
|
||||
Keyboard.print('\'');
|
||||
return;
|
||||
case 4: // comma
|
||||
Keyboard.print(',');
|
||||
return;
|
||||
case 5: // exclamation point
|
||||
Keyboard.print('!');
|
||||
return;
|
||||
case 6: // question mark
|
||||
Keyboard.print('?');
|
||||
return;
|
||||
case 7: // period
|
||||
Keyboard.print('.');
|
||||
return;
|
||||
case 8: // up
|
||||
Keyboard.press(KEY_UP);
|
||||
Keyboard.release(KEY_UP);
|
||||
return;
|
||||
case 9: // down
|
||||
Keyboard.press(KEY_DOWN);
|
||||
Keyboard.release(KEY_DOWN);
|
||||
return;
|
||||
case 10: // page up
|
||||
Keyboard.press(KEY_PAGE_UP);
|
||||
Keyboard.release(KEY_PAGE_UP);
|
||||
return;
|
||||
case 11: // page down
|
||||
Keyboard.press(KEY_PAGE_DOWN);
|
||||
Keyboard.release(KEY_PAGE_DOWN);
|
||||
return;
|
||||
case 12: // shift
|
||||
// TODO
|
||||
return;
|
||||
case 13: // symbol shift
|
||||
// TODO
|
||||
return;
|
||||
case 14: // switch keyset
|
||||
// TODO
|
||||
return;
|
||||
case 15: // escape
|
||||
Keyboard.press(KEY_ESC);
|
||||
Keyboard.release(KEY_ESC);
|
||||
return;
|
||||
case 16: // control
|
||||
// TODO
|
||||
return;
|
||||
case 17: // alt
|
||||
// TODO
|
||||
return;
|
||||
case 18: // delete
|
||||
Keyboard.press(KEY_DELETE);
|
||||
Keyboard.release(KEY_DELETE);
|
||||
return;
|
||||
case 19: // insert
|
||||
Keyboard.press(KEY_INSERT);
|
||||
Keyboard.release(KEY_INSERT);
|
||||
return;
|
||||
case 20: // tab
|
||||
Keyboard.press(KEY_TAB);
|
||||
Keyboard.release(KEY_TAB);
|
||||
return;
|
||||
case 21: // enter
|
||||
Keyboard.press(KEY_ENTER);
|
||||
Keyboard.release(KEY_ENTER);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
MODIFIERS
|
||||
*/
|
||||
bool is_modifier = false;
|
||||
byte modifier = 0;
|
||||
for (byte b = 0; b < 8; b++) {
|
||||
if ((key_pressed_total & modifiers[b]) == modifiers[b]) {
|
||||
is_modifier = true;
|
||||
modifier = b;
|
||||
modifier_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);
|
||||
return;
|
||||
}
|
||||
if (key == BUTTON_D || key == BUTTON_E) {
|
||||
Keyboard.press(KEY_LEFT);
|
||||
Keyboard.release(KEY_LEFT);
|
||||
key_pressed_total &= ~(1 << key);
|
||||
modified_pressed = true;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
REGULAR KEYS
|
||||
*/
|
||||
switch (key) {
|
||||
case BUTTON_A:
|
||||
Keyboard.print('a');
|
||||
return;
|
||||
case BUTTON_B:
|
||||
Keyboard.print('b');
|
||||
return;
|
||||
case BUTTON_C:
|
||||
Keyboard.print('c');
|
||||
return;
|
||||
case BUTTON_D:
|
||||
Keyboard.print('d');
|
||||
return;
|
||||
case BUTTON_E:
|
||||
Keyboard.print('e');
|
||||
return;
|
||||
case BUTTON_F:
|
||||
Keyboard.print('f');
|
||||
return;
|
||||
default:
|
||||
Serial.print("unknown key ");
|
||||
Serial.println(key);
|
||||
return;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue