Skip to content

Instantly share code, notes, and snippets.

@rehael
Created March 27, 2017 21:20
Show Gist options
  • Save rehael/a9ea6fc4653f07e82466504a261e5aae to your computer and use it in GitHub Desktop.
Save rehael/a9ea6fc4653f07e82466504a261e5aae to your computer and use it in GitHub Desktop.
ProTrinketKeyboard in CM switch tester body
#include <ProTrinketKeyboard.h> // Ensure the library is installed
// Switches are connected from ground to these defined pins
const int P_CTRL = 4;
const int P_SHFT = 8;
const int P_UP = 12;
const int P_DN = 10;
const int P_LT = 9;
const int P_RT = 11;
// how many millis to wait before key repeats
const unsigned long keydelay1 = 1000;
// how many millis between key repeats
const unsigned long keydelay2 = 100;
// keystroke stabilization time - because switches chatter
const unsigned long hysteresis = 50;
// bitmap keystate
uint8_t keysstate = 0;
uint8_t prevstate = 0;
// repeater flag
uint8_t rep = 0;
// keycodes array, map for USB report_buffer
uint8_t keys[6] = {0,0,0,0,0,0};
// array size pointer
uint8_t ksz = 0;
// mods flag
uint8_t mods = 0;
// time counters
unsigned long pmil; // previous millis()
unsigned long cmil; // current millis()
// bitmask flags
enum keys {
KRT = 1, KLT = 2, KDN = 4, KUP = 8, KSH = 16, KCT = 32
};
void setup()
{
// Declare button pins as inputs
pinMode(P_CTRL, INPUT);
pinMode(P_SHFT, INPUT);
pinMode(P_UP, INPUT);
pinMode(P_DN, INPUT);
pinMode(P_LT, INPUT);
pinMode(P_RT, INPUT);
// setting input pins to high means turning on internal pull-up resistors
digitalWrite(P_CTRL, HIGH);
digitalWrite(P_SHFT, HIGH);
digitalWrite(P_UP, HIGH);
digitalWrite(P_DN, HIGH);
digitalWrite(P_LT, HIGH);
digitalWrite(P_RT, HIGH);
// remember, the buttons are active-low, they read LOW when they are not pressed
// initialize states
pmil = cmil = 0;
rep = prevstate = keysstate = mods = 0;
ksz = 0;
keys[0] = 0;
keys[1] = 0;
keys[2] = 0;
keys[3] = 0;
keys[4] = 0;
keys[5] = 0;
// start USB stuff
TrinketKeyboard.begin();
}
// get bitmask of active keys
uint8_t getKeysState() {
return (
((digitalRead(P_CTRL) == LOW) ? 0xff & KCT : 0) |
((digitalRead(P_SHFT) == LOW) ? 0xff & KSH : 0) |
((digitalRead(P_UP) == LOW) ? 0xff & KUP : 0) |
((digitalRead(P_DN) == LOW) ? 0xff & KDN : 0) |
((digitalRead(P_LT) == LOW) ? 0xff & KLT : 0) |
((digitalRead(P_RT) == LOW) ? 0xff & KRT : 0)
);
}
void sendKeys() {
/*
mods acting as mods
#define KEYCODE_MOD_RIGHT_CONTROL 0x10
#define KEYCODE_MOD_RIGHT_SHIFT 0x20
mods acting as keys
#define KEYCODE_RIGHT_CONTROL 0xE4
#define KEYCODE_RIGHT_SHIFT 0xE5
#define KEYCODE_ARROW_RIGHT 0x4F
#define KEYCODE_ARROW_LEFT 0x50
#define KEYCODE_ARROW_DOWN 0x51
#define KEYCODE_ARROW_UP 0x52
*/
mods = (keysstate & KCT ? KEYCODE_MOD_RIGHT_CONTROL : 0) |
(keysstate & KSH ? KEYCODE_MOD_RIGHT_SHIFT : 0);
ksz = 0;
if (keysstate & KUP) keys[ksz++] = KEYCODE_ARROW_UP;
if (keysstate & KDN) keys[ksz++] = KEYCODE_ARROW_DOWN;
if (keysstate & KLT) keys[ksz++] = KEYCODE_ARROW_LEFT;
if (keysstate & KRT) keys[ksz++] = KEYCODE_ARROW_RIGHT;
// workaround for a library bug not resetting the report_buffer array
for (int i = ksz; i < 6; i++) keys[i] = 0;
// FIXME: if no keys, only mods, rewrite mods to key push
// but first check if it's really needed, as DIView shows the presses just ok.
TrinketKeyboard.pressKeys(mods, keys, 6);
}
void loop()
{
TrinketKeyboard.poll();
// the poll function must be called at least once every 10 ms or cause a keystroke;
// if it is not, then the computer may think that the device
// has stopped working, and give errors
keysstate = getKeysState();
cmil = millis();
if ((keysstate != prevstate) && (cmil - pmil >= hysteresis)) {
sendKeys();
pmil = cmil;
rep = 0;
prevstate = keysstate;
}
else {
switch (rep) {
case 1:
if (cmil - pmil >= keydelay1) {
rep = 2;
sendKeys();
}
break;
case 2:
if (cmil - pmil >= keydelay2) {
pmil = cmil;
sendKeys();
}
break;
default: // rep = 0 here
rep = 1;
pmil = cmil;
break;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment