Keyboard Layout

Hi, I was wondering if there is any way to change the default US keyboard layout for Arduino Micro and Leonardo(since they are capable of emulating a HID keyboard). The Teensy allows you to choose your layout so the characters dont change(when I want to type "/" I get "-"). Does anyone knows how to modify the libraries to accept spanish keyboards?

I have the exact same problem, have you found a solution for this?

The keyboard layout (the "key mapping") is "defined" in file HID.cpp

You can find it (like) here:

...<userName>\Applicationdata\Arduino15\packages\arduino\hardware\avr\<ArduinoVersionNumber>\cores\arduino\HID.cpp

The path is dependent on your operating system and (maybe) Arduino IDE version number.
Some folders may be "hidden" (so set your system to show all folders).

Make a copy of HID.cpp (for backup).
Open the file with a text editor and search for:

const uint8_t _asciimap[128] =

This is the ASCII mapping.
Change values to get the keys you need (you have to experiment). :slight_smile:

I had success to change the keyboard layout to German.
With Spanish keyboard layout you are on your own and you have to experiment :slight_smile:

Hey I'm having a slight issue with this because I can't find the HID.cpp file in the folder. I was wondering about having the wrong folder, the closest folder I could find to the one you pointed out was C:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino.

The path may be dependent on the operating system and the Arduino IDE version.
Some folders may be "hidden" (so you have to set your system to show all folders).
You may finde more than one "HID.cpp" file on different places.

You are on the right track if you can find the "ASCII mapping" array:

const uint8_t _asciimap[128] =

and if changes show effect.
Example: change the code of letter "a" to letter "s". After that make a sketch that writes "aaaa" with Keyboard.print("aaaa"); and your Arduino Micro (or Leonardo) should evoke "ssss" on your pc.

Hi uxomm,
könntest du mir die layout (german) datei zu schicken? Das währe sehr hilfreich. Danke
Email : sabrina.fedel@web.de

Hi :slight_smile:

I also stumbled upon this issue myself when playing around with the HID keyboard example on my Arduino Micro.
It is absolutely true that the default scan codes found in the _asciimap[128] table in file c:\Program Files (x86)\Arduino\libraries\Keyboard\src\keyboard.cpp, is based on the US standard keyboard layout.

So I also got characters not corresponding to what a was sending from the HID keyboard, when visualizing the result in a Notepad. For instance the damn backslash ('\') would appear like this '

I'm running danish keyboard layout on my Windows 10, so when changing that to a US layout, under language settings in the control panel, everything was suddenly printed in an expected maner - a send backslash from the Arduino, gave a backslash in the Notepad editor.

So what to do when you dont use US layout - well - remap the _asciimap[128], so it corresponds to a desired language (spanish, german, danish, dutch... you name it)

How to tell what HEX-values to put in for at certain character?
Well I haven't figured that out yet - i mean: where are the language specific tables for scan codes for a certain language.

So a tried something else...

  1. I kept my desired language setting on Windows (Danish keyboard layout)
  2. I then created a loop that would call a custom function I made in the keyboard.cpp that would do one simple thing, namely send values representing scan codes. No more ascii-interpretation at this point...
    This function i purely pieces from the existing Press() and release() functionality - basically I removed that asciimap-lookup functionality...
size_t Keyboard_::extract(uint8_t k)
{
 uint8_t i;
 // Add k to the key report only if it's not already present
// and if there is an empty slot.
 _keyReport.modifiers = 0;
 
if (_keyReport.keys[0] != k && _keyReport.keys[1] != k && 
_keyReport.keys[2] != k && _keyReport.keys[3] != k &&
_keyReport.keys[4] != k && _keyReport.keys[5] != k) {

for (i=0; i<6; i++) {
if (_keyReport.keys[i] == 0x00) {
_keyReport.keys[i] = k;
break;
}
}
if (i == 6) {
setWriteError();
return 0;
} 
}
sendReport(&_keyReport);
 
 delay(10);
 
  // Test the key report to see if k is present.  Clear it if it exists.
// Check all positions in case the key is present more than once (which it shouldn't be)
for (i=0; i<6; i++) {
if (0 != k && _keyReport.keys[i] == k) {
_keyReport.keys[i] = 0x00;
}
}

sendReport(&_keyReport);
return 1;
 
}
  1. I observe what the output is in Notepad, when the HID keyboard is typing stuff.
    Be aware that a pure loop through range from 0x00 to 0x7f will result in different stuff that is not
    only characters (print screen, scroll lock, etc.).

Conclusion:
So for instance would a '+' sign in my keyboard layout configuration (danish) show in the notepad when the loop reached scan code 0x2D, where it in the original US layout was 0x2E|SHIFT (Keyboard.cpp _asciiMap[128])
Replacing 0x2E|SHIFT with 0x2D would represent how I remapped the US scan code for '+' to what it would be in a danish layout (danish scan code for '+')

Cas_2000:
How to tell what HEX-values to put in for at certain character? Well I haven't figured that out yet - i mean: where are the language specific tables for scan codes for a certain language.

The original post says:

sebast124:
The Teensy allows you to choose your layout so the characters dont change(when I want to type "/" I get "-").

I would guess from that the tables will be found somewhere in the Teensy library sources.

Be warned that the existing Arduino library does not support the "AltGr" key in the lookup table, only Shift. If you need any characters that require the AltGr shift you are in for some major changes.

You can find the HID key codes here: http://www.usb.org/developers/hidpage/Hut1_12v2.pdf

I know this is an old post, but it is simply not enough to edit the asciimap. If you look into the code you Will find that you are restricted to the 128 characters asciimap and uint8_t, which means you cannot Hope to parse your special characters without fundementally changing the Keyboard class. If we take your danish characters æøå they are All multicharacters and they simply cannot fit into a uint8_t. If you are not up to rewrithing the class (or use another lib) your Best Hope is to find some ascii substitution characters for those.