Last active
August 29, 2015 14:05
-
-
Save omaskery/7bb96a1ad9126ec332a3 to your computer and use it in GitHub Desktop.
Simple Arduino sketch that takes a table of 'mappings' that monitor input pins, with specific combinations triggering events to either momentarily or persistently assert output and/or press keyboard keys.
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
//! structure describing a mapping from input values to output events | |
typedef struct sMappingInfo | |
{ | |
// sensing | |
uint64_t InputMask; //!< what digital inputs must be high to trigger this mapping | |
// actuating | |
uint64_t AssertMask; //!< what digital outputs must be asserted when mapping is triggered | |
uint8_t AssertKey; //!< what key is pressed when mapping is triggered | |
// mapping configuration | |
uint8_t bToggleActuation; //!< whether mapping remains asserted until input event occurs again | |
} tMappingInfo; | |
//! structure describing a mapping with its current state | |
typedef struct sLiveMapping | |
{ | |
tMappingInfo Mapping; //!< the mapping used in this event | |
uint8_t bTriggered; //!< whether this mapping is currently being asserted | |
} tLiveMapping; | |
const uint8_t MaxDigitalPins = 54; //!< number of digital IO pins | |
const uint8_t MaxMappings = 1; //!< max number of input/output mappings | |
static tLiveMapping g_Mappings[MaxMappings]; //!< mappings list | |
static uint64_t g_InputMask = 0; //!< mask of all input pins | |
static uint64_t g_AssertMask = 0; //!< mask of all output pins | |
static uint64_t g_PersistantOutputs = 0; //!< all toggled outputs | |
static uint64_t g_Outputs = 0; //!< last outputs asserted | |
static uint64_t g_LastInput = 0; //!< last inputs measured | |
void setup() | |
{ | |
Serial.begin(115200); | |
Serial.print("Configuring mappings ("); | |
Serial.print(MaxMappings); | |
Serial.println("):"); | |
// some hardcoded mappings | |
g_Mappings[0].Mapping.InputMask = 1 << 2; | |
g_Mappings[0].Mapping.AssertMask = 1 << 13; | |
g_Mappings[0].Mapping.AssertKey = KEY_LEFT_SHIFT; | |
g_Mappings[0].Mapping.bToggleActuation = 1; | |
// find all input and output pins | |
for(uint8_t Index = 0; Index < MaxMappings; Index++) | |
{ | |
g_InputMask |= g_Mappings[Index].Mapping.InputMask; | |
g_AssertMask |= g_Mappings[Index].Mapping.AssertMask; | |
} | |
// configure all input and output pins | |
for(uint8_t Index = 0; Index < MaxDigitalPins; Index++) | |
{ | |
if((g_InputMask >> Index) == 1) | |
{ | |
Serial.print("\tPin "); | |
Serial.print(Index); | |
Serial.println(" is an input"); | |
pinMode(Index, INPUT); | |
} | |
else if((g_AssertMask >> Index) == 1) | |
{ | |
Serial.print("\tPin "); | |
Serial.print(Index); | |
Serial.println(" is an output"); | |
pinMode(Index, OUTPUT); | |
} | |
} | |
// enable keyboard HID support | |
Keyboard.begin(); | |
} | |
void loop() | |
{ | |
uint64_t Outputs = 0; | |
uint64_t Inputs = 0; | |
// read all input pins | |
for(uint8_t Index = 0; Index < MaxDigitalPins; Index++) | |
{ | |
if((g_InputMask >> Index) == 1) | |
{ | |
if(digitalRead(Index)) | |
{ | |
Inputs |= 1 << Index; | |
} | |
} | |
} | |
// if a key is pressed, check the mappings | |
if(Inputs != 0) | |
{ | |
for(uint8_t Index = 0; Index < MaxMappings; Index++) | |
{ | |
const uint64_t Mask = g_Mappings[Index].Mapping.InputMask; | |
// skip if this mapping has a null mask | |
if(Mask == 0) continue; | |
// skip if the inputs don't match the mapping's mask | |
if((Inputs & Mask) != Mask) continue; | |
// if this mapping is a "active while held" | |
if(g_Mappings[Index].Mapping.bToggleActuation == 0) | |
{ | |
Outputs |= g_Mappings[Index].Mapping.AssertMask; | |
if(g_Mappings[Index].Mapping.AssertKey != 0) | |
{ | |
Serial.print("Tapping key "); | |
Serial.println(g_Mappings[Index].Mapping.AssertKey, HEX); | |
Keyboard.press(g_Mappings[Index].Mapping.AssertKey); | |
Keyboard.release(g_Mappings[Index].Mapping.AssertKey); | |
} | |
} | |
// if this mapping is a "toggle when pressed" and the key was just pressed | |
else if((g_LastInput >> Index) == 0) | |
{ | |
// toggle assertion state | |
g_Mappings[Index].bTriggered = !g_Mappings[Index].bTriggered; | |
// if toggled to active assert outputs and press keys | |
if(g_Mappings[Index].bTriggered) | |
{ | |
g_PersistantOutputs |= g_Mappings[Index].Mapping.AssertMask; | |
if(g_Mappings[Index].Mapping.AssertKey != 0) | |
{ | |
Serial.print("Pressing key "); | |
Serial.println(g_Mappings[Index].Mapping.AssertKey, HEX); | |
Keyboard.press(g_Mappings[Index].Mapping.AssertKey); | |
} | |
} | |
// if toggled to inactive deassert outputs and release keys | |
else | |
{ | |
g_PersistantOutputs &= ~(g_Mappings[Index].Mapping.AssertMask); | |
if(g_Mappings[Index].Mapping.AssertKey != 0) | |
{ | |
Serial.print("Releasing key "); | |
Serial.println(g_Mappings[Index].Mapping.AssertKey, HEX); | |
Keyboard.release(g_Mappings[Index].Mapping.AssertKey); | |
} | |
} | |
} | |
} | |
} | |
// incorporate toggled outputs into the outputs for this update | |
Outputs |= g_PersistantOutputs; | |
// see if the 'new' outputs are different to the last outputs written | |
if((Outputs ^ g_Outputs) != 0) | |
{ | |
Serial.println("Updating outputs."); | |
/* | |
Serial.print("\t"); | |
Serial.println((unsigned long) Outputs, BIN); | |
Serial.print("\t"); | |
Serial.println((unsigned long) g_Outputs, BIN); | |
*/ | |
// update all output pins | |
for(uint8_t Index = 0; Index < MaxDigitalPins; Index++) | |
{ | |
if((g_AssertMask >> Index) == 1) | |
{ | |
const bool Value = (Outputs >> Index) == 1; | |
Serial.print("Setting output "); | |
Serial.print(Index); | |
Serial.println(Value ? " high" : " low"); | |
digitalWrite(Index, Value ? HIGH : LOW); | |
} | |
} | |
// remember what outputs we asserted | |
g_Outputs = Outputs; | |
} | |
// remember what inputs we saw this update | |
g_LastInput = Inputs; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment