Sorry, the NKRO libs I'm using are from NicoHood's HID-Project. It's available from the arduino library manager as "HID Project"
Here is the code:
#include <HID-Project.h>
#define TWO_JOYSTICKS
uint8_t modifier = 0; // Modifier key state.
uint8_t modifier_prev = 0; // Modifier key previous state.
// Nr. of the digital input [array index] to use as the modifier button.
const uint8_t modifier_input = A4;
long sample_time = 0; // The last time the input pins were sampled
// Number msecs of consecutive samples before we consider a state change.
const uint8_t debounce_ms = 10;
// Number of inputs/keys we are monitoring and emulating.
#ifdef TWO_JOYSTICKS
const uint8_t nr_of_inputs = 18;
#else
const uint8_t nr_of_inputs = 12;
#endif
// Table for the Digital inputs to scan. Connect arcade controls to these inputs
#ifdef TWO_JOYSTICKS
// E.g. Arduino Leonardo
uint8_t input_table[nr_of_inputs] = {1, 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 16, 14, 15,
A0, A1, A2, A3 };
#endif
uint8_t input_state[nr_of_inputs] = {0}; // Current state of the inputs.
uint8_t prev_input_state[nr_of_inputs] = {0}; // Previous state of the inputs.
// Age (milliseconds) input was last seen in current state.
long input_last_seen[nr_of_inputs] = {0};
#ifdef TWO_JOYSTICKS
// Normal (unmodified) keycodes to send with the associated input.
uint8_t keycode_table[nr_of_inputs] = { '5', // coin
'6', // Op panel
'q', // P1 up
'w', // P2 down
'e', // P1 left
'r', // P1 right
't', // P1 button throw
'y', // P1 button jump
'u', // P1 dash
'a', // P2 UP
's', // P2 down
'd', // P2 left
'f', // P2 right
'g', // P2 throw
'h', // p2 jump
'1', // p2 dash
'1', // p1 start
'2', // p2 start
};
#endif
void read_inputs() {
// Update and debounce the inputs.
uint8_t count = 0;
uint8_t i;
uint8_t reading;
long tstamp;
// Read all the inputs.
for (i = 0; i < nr_of_inputs; i++) {
reading = !digitalRead(input_table[i]);
tstamp = millis();
// Check if the reading is still the same as the recorded state.
if (input_state[i] == reading)
// It is the same, so update the time last seen.
input_last_seen[i] = tstamp;
else
// If input has been different for longer than the debounce time
if (input_last_seen[i] + debounce_ms < tstamp) {
input_state[i] = reading; // Change the state.
input_last_seen[i] = tstamp; // Set the new last seen time.
}
// Count how many buttons are currently pressed.
if (input_state[i] != 0)
count++;
// Turn on the LED if button is pressed.
if (count)
digitalWrite(LED_BUILTIN, HIGH);
else
digitalWrite(LED_BUILTIN, LOW);
}
// Set the modifier if button 0 is held and another button is pressed.
modifier_prev = modifier;
modifier = input_state[modifier_input] && count > 1;
// Release all the keys if we've changed the modifer state
// to make sure we are in a clean/known keyboard state.
if (modifier != modifier_prev)
NKROKeyboard.releaseAll();
}
void setup() {
uint8_t i;
for (i = 0; i < nr_of_inputs ; i++) {
pinMode(input_table[i], INPUT);
digitalWrite(input_table[i], HIGH); // Turn on internal pullup resistor
}
pinMode(LED_BUILTIN, OUTPUT); // For blinking the LED when a key is pressed
NKROKeyboard.begin();
NKROKeyboard.releaseAll();
delay(200);
}
void loop() {
uint8_t i;
uint8_t keycode;
read_inputs(); // Get the current input states.
// Loop through all the inputs.
for (i = 0; i < nr_of_inputs; i++)
// Check if the input state has changed.
if (input_state[i] != prev_input_state[i]) {
// Save the input state for later comparison.
prev_input_state[i] = input_state[i];
// If the modifier key is held, use the alternate keycode table.
keycode = keycode_table[i];
// Press or release the key depending on the state of the input.
// Only send a keycode if it is non-zero.
if (input_state[i] and keycode != 0)
NKROKeyboard.press(keycode);
else
NKROKeyboard.release(keycode);
}
}