Skip to content

Instantly share code, notes, and snippets.

@lionicsheriff
Created August 19, 2014 15:19
Show Gist options
  • Save lionicsheriff/84cfcd832c30228760c6 to your computer and use it in GitHub Desktop.
Save lionicsheriff/84cfcd832c30228760c6 to your computer and use it in GitHub Desktop.
The start of a chorded keyboard for the arduino.
// 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