smol_gkos/smol_gkos.ino

272 lines
7.8 KiB
Arduino
Raw Normal View History

2021-02-27 21:27:34 +00:00
#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;
enum Button { A, B, C, D, E, F, MouseUL, MouseUR, MouseDL, MouseDR };
2021-02-27 21:27:34 +00:00
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 };
// different actions that the keyboard can take
// - print a single character
// - press (and release) a key
// - toggle a modifier
enum ActionType { PrintCharacter, PressKey, ToggleModifier };
2021-02-27 21:27:34 +00:00
/*
backspace, space (keep those two first since they overlap with the rest )
g, k, o, s, w, native
*/
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
};
2021-02-27 21:27:34 +00:00
/*
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
};
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_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
};
2021-02-27 21:27:34 +00:00
byte key_pressed = 0;
byte key_pressed_total = 0;
bool chord_used = false;
bool chorded_pressed = false;
2021-02-26 21:13:24 +00:00
2021-02-26 20:54:27 +00:00
void setup() {
2021-02-27 21:27:34 +00:00
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();
2021-02-26 20:54:27 +00:00
}
void loop() {
2021-02-27 21:27:34 +00:00
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
chord_used = false;
chorded_pressed = false;
2021-02-27 21:27:34 +00:00
}
}
}
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 && !chord_used) {
2021-02-27 21:27:34 +00:00
// only register a special keypress when all keys have been released
if (key_pressed != 0)
return;
switch (special_action_target_types[special]) {
case ActionType::PrintCharacter:
Keyboard.print((char)special_action_targets[special]);
2021-02-27 21:27:34 +00:00
return;
case ActionType::PressKey:
Keyboard.press(special_action_targets[special]);
Keyboard.release(special_action_targets[special]);
2021-02-27 21:27:34 +00:00
return;
case ActionType::ToggleModifier:
2021-02-27 21:27:34 +00:00
// TODO
return;
}
}
/*
CHORDS
2021-02-27 21:27:34 +00:00
*/
bool is_chord = false;
byte chord = 0;
2021-02-27 21:27:34 +00:00
for (byte b = 0; b < 8; b++) {
if ((key_pressed_total & chords[b]) == chords[b]) {
is_chord = true;
chord = b;
chord_used = true;
2021-02-27 21:27:34 +00:00
break;
}
}
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]);
2021-02-27 21:27:34 +00:00
return;
case ActionType::PressKey:
Keyboard.press(chord_targets[chord * 4]);
Keyboard.release(chord_targets[chord * 4]);
2021-02-27 21:27:34 +00:00
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;
2021-02-27 21:27:34 +00:00
}
}
2021-02-27 21:27:34 +00:00
}
return;
2021-02-27 21:27:34 +00:00
}
/*
REGULAR KEYS
*/
switch (key) {
case Button::A:
2021-02-27 21:27:34 +00:00
Keyboard.print('a');
return;
case Button::B:
2021-02-27 21:27:34 +00:00
Keyboard.print('b');
return;
case Button::C:
2021-02-27 21:27:34 +00:00
Keyboard.print('c');
return;
case Button::D:
2021-02-27 21:27:34 +00:00
Keyboard.print('d');
return;
case Button::E:
2021-02-27 21:27:34 +00:00
Keyboard.print('e');
return;
case Button::F:
2021-02-27 21:27:34 +00:00
Keyboard.print('f');
return;
default:
return;
}
2021-02-26 20:54:27 +00:00
}