NKRO Keyboard Stuck using Ascii Keys only

I'll try to make a long story short here. I have a small project that I am using an arduino leonardo with. I already modified an existing project to fit my needs until i realized it was built using the standard arduino keyboard libs and i require a few more keys using nkro. I am using this to control an indie game we have developed and placed in an arcade machine. Because of the action in the game, more simultaneous inputs beyond 6 are needed.

I finally managed to get NicoHood's NKRO code crudely implemented into my code but so far I'm only able to use ASCII keys. Attempting to use enter, F1-F12 spit out the following error

warning: narrowing conversion of '17746' from 'int' to 'uint8_t {aka unsigned char}' inside { } [-Wnarrowing]
};
warning: large integer implicitly truncated to unsigned type [-Woverflow]

I've attached my code here so anyone can see (and use it if it works for you) Any help you could give me would be greatly appreciated.

edit: pasting code here looked a little weird so i posted it to pastebin

https://pastebin.com/Ak9L76iR

Any help you can give me would be greatly appreciated.

Wrong decision, we (at least me) don't load anything from temporary storage servers. That's simply because any visitor looking at this thread in one year won't see that content and doesn't understand what's going on.
Post your code here and use code tags (the </> button in the editor) to make it look pretty!

A link would have helped. Don't expect us to search for every piece of software you found anywhere in the Internet.

A hint: you have to provide a KeyboardKeycode types value to the methods of the NKROKeyboard.

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);
    }
}

As I assumed you just provide ASCII codes to the methods. Change to scancodes (called KeyboardKeycode as a type in that library) and you can provide any key you want. Of course you loose the keyboard layout functionality of the library but that shouldn't be a problem for your use-case I guess.

1 Like

Thanks for the response. I tried using KeyboardKeycode and using the examples in the ImprovedKeyLayouts.h but i get all sorts of strange behaviors. For example, Using 'KEY_ENTER' gives me Shift+R at the same time.

Do you use it explictly?

p.e.

NKROKeyboard.add(KeyboardKeycode(KEY_ENTER));

1 Like

pylon

I knew i was missing something small and mundane. I had a closer look at that snippet and modified it to run in the existing NKROKeyboard.press and .release routine and came up with
NKROKeyboard.press(KeyboardKeycode(Keycode));

So far it seems to work. I just need to give it a whirl on the cabinet and make sure all the buttons work. I'll post back with some results soon.

1 Like

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.