Created
August 19, 2014 15:19
-
-
Save lionicsheriff/84cfcd832c30228760c6 to your computer and use it in GitHub Desktop.
The start of a chorded keyboard for the arduino.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// set up flags for the buttons | |
#define b1 B0000001 | |
#define b2 B0000010 | |
#define b3 B0000100 | |
#define b4 B0001000 | |
#define b5 B0010000 | |
#define b6 B0100000 | |
#define b7 B1000000 | |
// make pin numbers easier to notice | |
#define p1 1 | |
#define p2 2 | |
#define p3 3 | |
#define p4 4 | |
#define p5 5 | |
#define p6 6 | |
#define p7 7 | |
#define p8 8 | |
// map buttons to fingers (and thumbs) | |
// makes it easier to read the input array | |
#define f1 b1 | |
#define f2 b2 | |
#define f3 b3 | |
#define f4 b4 | |
#define t1 b5 | |
#define t2 b6 | |
#define t3 b7 | |
typedef struct { | |
int Pin; | |
int Flag; | |
} Button; | |
void setupPins(Button buttons[], int length); | |
void setupButtonMap(char keymap[]); | |
void outputKey(); | |
int getPressedButtons(Button buttons[], int length); | |
bool anyButtonPressed(Button buttons[], int length); | |
int chordStarted = 0; | |
// how often the input is checked (in milliseconds) | |
// the lower it is the more responsive the keyboard is | |
const int inputFrequency = 10; | |
// how many times the input gets checked before | |
// accepting a chord | |
// the higher it is the easier it is to reset a chord, | |
// but the output rate decreases | |
const int chordLength = 100; | |
// inputs to listen on | |
Button buttons[] = { | |
// normal keys | |
{p2, f1}, | |
{p3, f2}, | |
{p4, f3}, | |
{p5, f4}, | |
// modifier keys (e.g. shift, ctrl, alt) | |
// by keeping them together at the end we | |
// can separate them from normal keys easily | |
{p6, t1}, | |
{p7, t2}, | |
{p8, t3} | |
}; | |
const int buttonsLength = sizeof(buttons) / sizeof(Button); | |
const int numOfModifiers = 3; | |
// storage for all the possible key combos | |
// modifiers are treated separately | |
char buttonMap[f1|f2|f3|f4] = {0}; | |
void setupPins(Button buttons[], int length) { | |
for(int i = 0; i < length; i++){ | |
pinMode(buttons[i].Pin, INPUT); | |
Serial.write("Init pin: "); | |
Serial.print(buttons[i].Pin, DEC); | |
Serial.write("\n"); | |
} | |
} | |
void setupButtonMap(char keymap[]) { | |
keymap[b1] = 'a'; | |
keymap[b1|b2] = 'n'; | |
keymap[b2] = 'r'; | |
keymap[b2|b3] = 'e'; | |
keymap[b3] = 's'; | |
keymap[b4] = 't'; | |
keymap[b4|b3] = 'h'; | |
} | |
int getPressedButtons(Button buttons[], int length){ | |
int pressed = 0; | |
for(int i = 0; i < length; i++){ | |
int val = digitalRead(buttons[i].Pin); | |
if (val != 0) { | |
pressed |= buttons[i].Flag; | |
} | |
} | |
return pressed; | |
} | |
bool anyButtonPressed(Button buttons[], int length){ | |
for(int i = 0; i < length; i++){ | |
int val = digitalRead(buttons[i].Pin); | |
if (val != 0) return true; | |
} | |
return false; | |
} | |
void outputKey(){ | |
int pressedButtons = getPressedButtons(buttons, buttonsLength); | |
if (pressedButtons == 0) return; | |
// extract the modifiers | |
bool mod1 = pressedButtons & t1; | |
bool mod2 = pressedButtons & t2; | |
bool mod3 = pressedButtons & t3; | |
pressedButtons &= ~(t1|t2|t3); | |
// | |
char mapped = buttonMap[pressedButtons]; | |
if(mapped != 0){ | |
Serial.print("Pressed: "); | |
Serial.print(pressedButtons, DEC); | |
Serial.print(" ("); | |
if(mod1)Serial.print("M1+"); | |
if(mod2)Serial.print("M2+"); | |
if(mod3)Serial.print("M3+"); | |
Serial.print(mapped); | |
Serial.print(") @"); | |
Serial.println(millis(), DEC); | |
} else { | |
Serial.print("Pressed: "); | |
Serial.print(pressedButtons, DEC); | |
Serial.print(" ("); | |
if(mod1)Serial.print("M1+"); | |
if(mod2)Serial.print("M2+"); | |
if(mod3)Serial.print("M3+"); | |
Serial.print("<null>) @"); | |
Serial.println(millis(), DEC); | |
} | |
} | |
void setup() { | |
setupPins(buttons, buttonsLength); | |
setupButtonMap(buttonMap); | |
} | |
void loop() { | |
bool buttonsPressed = anyButtonPressed(buttons, buttonsLength - numOfModifiers); // skip the modifiers | |
if(buttonsPressed && chordStarted < chordLength){ | |
//Serial.println("(chording)"); | |
chordStarted++; | |
} else if (buttonsPressed) { | |
outputKey(); | |
chordStarted = 0; | |
} else { | |
//Serial.println("(empty)"); | |
chordStarted = 0; | |
} | |
delay(inputFrequency); | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment