-1

I'm having some trouble with the HID-Project using my arduino micro as a keyboard. I'm using the BootKeyboard API, I want to be able to store and recall keycodes from EEPROM eventually, but as it stands my project is storing keycodes in an array and recalling them from the array to send them. Having read through a lot of the source, I have found an enum in the file
HID-APIs\ImprovedKeylayouts.h

looking at the enum my data types to store the keycodes need to be uint8_t, so i have defined:

uint8_t keycode; // my working variable to hold the keycode
uint8_t keycodes    [9][9] = {0}; // my array to store all the keycodes

if i define the keycode in the array using:

keycodes[0][0] = KEY_LEFT_SHIFT;

then to recall a code from the array i use

keycode = keycodes[0][0];

doing this:

BootKeyboard.press(keycode);
BootKeyboard.release(keycode);

nothing gets received on the computer (i have a python script i use to monitor keypresses)
However if i use:

BootKeyboard.press(KEY_LEFT_SHIFT);
BootKeyboard.release(KEY_LEFT_SHIFT);

which skips the use of the keycode variable (type uint8_t) it works as expected.

Why does this happen? and short of a massive switch/case or huge stack of if's, how can i get around this?

EDIT:
ok so after some more digging I think I've worked out why it's happening, but not a good workaround.
The BootKeyboard class has no press/release method, these are inherited from DefaultKeyboardAPI, the definitions being:

inline size_t press(ConsumerKeycode k);
inline size_t release(ConsumerKeycode k);

ConsumerKeycode is another enum defined in HID-Project\src\HID-APIs\ConsumerAPI.h

DefaultKeyboardAPI inherits two press/release methods from KeyboardAPI:

inline size_t press(KeyboardKeycode k);
inline size_t release(KeyboardKeycode k);

inline size_t press(uint8_t k);
inline size_t release(uint8_t k);

So the compiler is using argument based lookup to determine which function to call. when I use the name from the enum, it calls the enum based function and works as expected, however if I save the enum value into a variable it casts it to an int, so when I call the press/release methods the int base function is called.

The problem is that the int based function looks to see if the key is in the asciimap, and does nothing if not, obviously special keys such as shift/control do not appear in the asciimap, so nothing happens.

but I cannot see a way to circumvent this behavior without modifying the library itself...

  • In your example above, you're passing the whole keycode array (a uint8_t[][]), not a single uint8_t. Maybe that's the issue? – uint128_t Feb 22 '16 at 19:32
  • 1
    no? i'm extracting the single uint8_t from the array at position [index1][index2] – James Kent Feb 22 '16 at 19:42
  • however if I save the enum value into a variable it casts it to an int - what variable? Please post a Minimal, Complete, and Verifiable example - not a snippet. – Nick Gammon Feb 23 '16 at 4:02
  • The keycode variable which is of type uint8_t my example includes all the detail? – James Kent Feb 23 '16 at 6:41
  • Sorry, I thought you were passing the entire keycode array in the .press/.release method because your variables are keycode and keycodes. I don't actually see why you need keycode, why not try directly referencing the keycode array e.g. BootKeyboard.press(keycodes[0][0]); – uint128_t Feb 23 '16 at 16:04
0

Its difficult to tell without the code, but I suspect you are using the same variable name twice. One, which you are allocating the value to, is going out of scope before you read from it. The other, which is at a wider scope, doesn't have a useful value and you are reading from that. Of cause that's just a wild shot in the dark because there is no real code.

  • they are all global variables, for speed reasons i'm declaring my variables in global namespace rather then re declaring them inside the loop over and over again, there are not going out of scope, i am confident that the reason i have stated in my edit is why, but without heavily modifying the library i cannot see a solution. – James Kent Feb 23 '16 at 9:50
  • Damn that would have been the easy fix. Looking again at what you have said in you workaround why are you defining keycodes[][] as _uint_8 and not KeyboardKeycode keycodes[][]? – Code Gorilla Feb 23 '16 at 10:37
  • KeyboardKeycode is an enum, trying to do that gives me a compiler error... – James Kent Feb 23 '16 at 10:51
  • personally i'd rather the library was modified to allow a raw keycode method, so i'm going to look into doing this, i know it's a bit of an odd requirement so the maintainer may not want to merge the changes, but i think it's the only way i can do what i want. – James Kent Feb 23 '16 at 10:53
  • I've now modified the library (heavily) to suit my purposes, I Removed the previously defined functions that take uint8_t as an argument, and then changed the functions that take KeyboardKeycode to use uint8_t, I can now use raw numbers rather then the symbols defined in the enum, and at some point i will do the same for ConsumerKeycode which used uint16_t for the enum. However I don't think I will submit it back to the maintainer as it's less clear to understand which function is actually being called for a given argument. I will post more details this evening. – James Kent Feb 23 '16 at 13:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.