Skip to content

Instantly share code, notes, and snippets.

@edvb

edvb/Keyboard.ino

Last active Aug 31, 2020
Embed
What would you like to do?
// Teensy 2.0 has the LED on pin 11
// Teensy++ 2.0 has the LED on pin 6
// Teensy 3.0 has the LED on pin 13
const int ledPin = 13;
#define ROWS 5
#define COLS 2
/* TODO remove need for */
#define LAYERS 2
#define ROW_PINS { B0, B1, B3, B2, D5 }
#define COL_PINS { C0, D1, C5, C7, C6, C4, C3, D7, A13, A12, D0, B17, D6, B16 }
#define LAYOUT( \
k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, k0c, k0d, \
k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b, k1c, k1d, \
k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, k2b, k2c, \
k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k3a, k3b, \
k40, k41, k42, k43, k44, k45, k46, k47, k48, k49, k4a, k4b \
) \
{ \
{ k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, k0c, k0d }, \
{ k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b, k1c, k1d }, \
{ k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, k2b, KC_NO, k2c }, \
{ k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k3a, KC_NO, KC_NO, k3b }, \
{ k43, k41, k42, k40, k44, k45, k46, k47, KC_NO, k48, k49, k4a, KC_NO, k4b } \
}
char layout[][ROWS][COLS] = {
[0] = LAYOUT(
KC_ESC, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS, KC_EQL, KC_BSPC,
KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, KC_RBRC, KC_BSLS,
KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, KC_ENT,
KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_LSFT,
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_BTN1, KC_BTN3, KC_BTN3, KC_SPC, KC_LALT, '^', KC_MENU, KC_LCTL),
};
#include "config.h"
bool toggleBind = false;
int currLayer = 0;
int prevLayer = 0;
int desiredLayer = 1;
byte row[ROWS] = ROW_PINS;
byte col[COLS] = COL_PINS;
int key[] = {0,0,0,0,0,0};
char mod[] = {0,0};
void setup()
{
pinMode(ledPin, OUTPUT);
for (int c = 0; c < COLS; c++) /* columns are written to as outputs */
pinMode(col[c], OUTPUT);
for (int r = 0; r < ROWS; r++) /* rows are read from as inputs */
pinMode(row[r], INPUT);
}
/* collects the currently pressed keys and stores them until
* they can be passed to the computer */
void setKey(char keypress)
{
/* look for unused keys in the buffer */
int i, j;
for (i = 0; key[i] != 0; i++);
for (j = 0; mod[j] != 0; j++);
/* catch modifiers */
switch (keypress) {
case 176: mod[j] = KEY_LEFT_CTRL; break;
case 177: mod[j] = KEY_LEFT_ALT; break;
case 178: mod[j] = KEY_LEFT_SHIFT; break;
default: key[i] = keypress;
}
if (holdKey('^')) /* Prevent setting layer key into set_key or set_modifier */
return;
/* hold keypresses in buffer */
Keyboard.set_modifier(mod[0]|mod[1]);
Keyboard.set_key1(key[0]);
Keyboard.set_key2(key[1]);
Keyboard.set_key3(key[2]);
Keyboard.set_key4(key[3]);
Keyboard.set_key5(key[4]);
Keyboard.set_key6(key[5]);
}
/* sends the depressed keys and clears the buffer */
void sendKey()
{
Keyboard.send_now();
memset(key, 0, 6);
memset(mod, 0, 2);
Keyboard.set_modifier(mod[0]);
Keyboard.set_key1(key[0]);
Keyboard.set_key2(key[1]);
Keyboard.set_key3(key[2]);
Keyboard.set_key4(key[3]);
Keyboard.set_key5(key[4]);
Keyboard.set_key6(key[5]);
}
/* detects when a key is held down */
bool holdKey(char keypress)
{
for (int i = 0; i < 6; i++)
if (key[i] == keypress)
return true;
return false;
}
/* change to the next layer, looping back around when needed */
void cycleLayer()
{
if (currLayer == LAYERS - 1) /* reached maximum layer, going back to first layer */
currLayer = 0;
else
currLayer++; /* increments to the next layer */
}
/* toggles between two layers, the curret layer and desired layer */
void toggleLayer(char keyHeld, int desLayer)
{
if (holdKey(keyHeld)) {
prevLayer = currLayer; /* Saves previous layer */
currLayer = desLayer; /* Desired layer */
} else {
currLayer = prevLayer; /* Returns to previous layer */
}
}
/* macro sequence */
void ctrlAltDel()
{
/* Using CTRL+ALT+KEYPAD_0 as example */
setKey(KEYPAD_0);
setKey(176);
setKey(177);
sendKey();
}
/* goes to desired layer when keyHeld is pressed, returns to previous layer when released */
void holdLayer(char keyHeld, int desLayer){
if (holdKey(keyHeld)) {
if (!toggleBind) { // Saves the previous layer, using boolean to prevent updating prevLayer more than once
prevLayer = currLayer;
toggleBind = 1;
}
currLayer = desLayer; // Desire layer
} else {
if (toggleBind)
toggleBind = !toggleBind; // Resets boolean
currLayer = prevLayer; // Returns to previous layer
}
}
void loop() {
for (int c = 0; c < COLS; c++) {
digitalWrite(col[c], HIGH);
for (int r = 0; r < ROWS; r++) {
if (digitalRead(row[r])) {
// Triggers macro function when '#' is pressed, can be any other char defined in layout[][][]
if(layout[currLayer][r][c] == '#')
ctrlAltDel(); // Performs macro function
else
setKey(layout[currLayer][r][c]);
}
}
digitalWrite(col[c], LOW);
}
/* if the fn layer key is held, it changes the layer to the desired layer, when released, returns to previous layer */
holdLayer('^', desiredLayer);
/* now that all of the keys have been polled it is time to send them out */
sendKey();
delay(5);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.