Map to special characters, Dual OS

Hello! I just got my model 01, but I’m having some problems re-mapping. By going through the wiki I managed to re-map the prog key to be escape but I’m having issues mapping to my Norwegian native keys (ÆØÅ), I did find some threads on this but most of them required more programming competence than I have. One day I’m aiming to know code but for now I’m just starting to learn PHP and this seemed a bit daunting.

Are there any quick fix ways or dumb down explanations on how I can implement ÆØÅ? I’m thinking of sticking to the US-key setup and using the ÆØÅ keys by using a modifier key (alt or fn) and pressing another key, I’m thinking about somewhere in the range of these keys ; ’ - / …
Not sure which ones would be best as allot of keys have both function and numlock mapped to them already.

I’m using Windows 10 and Linux Mint, thank you for all replies! : )

EDIT: I’ve managed to flash in a .ino file by IIdata (https://github.com/lldata/Model01-Firmware/blob/master/Model01-Firmware.ino) but it uses FN-key as modifier with compose, but neither Ubuntu or Linux Mint have the ability to use the FN-key as a compose key. I want to get this working in Linux first as it’s linux I’ll be using most from now on.

How do you input those characters on your other keyboard(s)? If it’s by means of a compose key, what key do you use for that?

All my other keyboards (two of them) are native Norwegian keyboards with those characters present by default. But as I’m starting CS studies now I want to change to a US layout and just use modifier keys for me 3 Norwegian keys (åøæ ÅØÆ). I thought of using compose key as the script seemed to use compose.

Those letters are created by the OS Norwegian keymap from keys that produce other characters in the OS US keymap.

  • US ’ / " is the same keycode as æ and Æ.
  • US ; / : is the same keycode as ø and Ø.
  • US [ / { is the same keycode as å and Å.

Typing those directly on a US keymap will require using OS-specific methods (e.g. compose or unicode hex input) as those letters don’t have their own keycodes in the low-level interface between the keyboard and the OS.

Edit: for fun, change your OS keymap to Norwegian and look at the differences between the labels on the Model01 and what gets produced.

I realize so, it would be really nice with full utf-8 support in the model 01 firmware …my problem is that the script I found requires you to use the FN key, but Linux Mint (or ubuntu) cannot do that, and I couldn’t figure out how to change that key. All my attempts failed miserable ^ ^. But really there should be an easy way for us that don’t know programming to add foreign letters any how, like you can change all the letters on the US keyboard.

I’m still using Linux Mint, but I’m just having my other keyboard next to me for øæå right now, it’s not a long term solution but works for now.

My understanding is that this is a limitation of how USB keyboards work – the spec doesn’t have keyboards sending characters, but scancodes, that the OS maps to characters or other keys, so any keyboard, regardless of how advanced, can only send some basic set of codes & has to rely on the operating system to interpret those as the appropriate thing.

3 Likes

Exactly. There is a proposal (on another thread, I can’t find it at the moment) to implement an OS keyboard driver mod that would allow the computer to receive USB HID extensions containing raw unicode characters instead of scancodes. But this is still in its infancy and would have a huge hill to climb in getting the commercial OSes to adopt.

sounds exciting! But until you guys manage to (maybe) make this USB HID extension, anyone got any suggestions on an easy way to do this in OS? I looked into doing this with compose but for my Linux Mint install I can’t find any ways to do this without having to re-map many keys on the keyboard so that I retain original function of the keys as well.

I really wanted to shift to a US layout, and I’d also much prefer being able to stick with Linux Mint instead of having to shift back to Windows, learning Bash now and I’m loving it. Any suggestion for key?

After I figure out at key combination that may work without loosing too much functionality on the US keyboard layout I can start to tinker with the script again, tried my hands on it a few times yesterday but only got errors. But then again that’s probably how you learn :slight_smile:

I have my Compose key set to Right Alt, and have a number of macros on a layer to input accented symbols (my layout does not have a dedicated Right Alt key). You could map it to, say, Scroll Lock, because that wouldn’t interfere with anything most likely, and use macros for the special chars, placed wherever you want them on the keyboard.

Does this make sense?

I personally use right-ctrl for multikey/compose, as right-alt is required for altgr (even though I rarely use it). It’s really a matter of personal taste…

1 Like

I use F13 as my Compose key, because that key doesn’t even exist on most keyboards, so basically nothing relies on it. That way, it can’t interfere with anything.

2 Likes

I couldn’t find out where the F13 key is on the Model 01 (maybe you have to program it inn?) so I decided to go for right control key as suggested by @andrewg . I’ve tried a bunch of copy paste code and written some myself but most if has failed or produced un-predicted results. This is my progress so far
https://dpaste.de/Q6GS , the changes I’ve made are on line 76-71 and 232-255.

But I don’t quite understand how it should know that those switch cases should produce ÆØÅ, I assume I’ll have to add a layer for right control key under “const Key keymaps[][ROWS][COLS] PROGMEM = {” but have been unable to do so succefully. Any tips? :slight_smile:

Yes, you’d have to add a Key_F13 to your keymap somewhere if you wanted to use that as your compose key. Not that there’s anything wrong with using Key_RightControl, of course.

It looks like you haven’t defined any keys to trigger those macros. Somewhere in your keymap, you’ll need a key defined as M(R_AE), for example. You can either do this by adding a whole new layer, which you could do by copying the QWERTY layer, and redefining the keys therein to your liking. You would also need to give it an appropriate name, and add that name to the layers enum, and define some ShiftToLayer() and/or LockLayer() keys to activate and deactivate that layer.

Alternatively, you could replace some little-used keys on one of the existing layers.

Feel like such a “noob”, but all my attempts failed.

I saw that in the example repo I posted in the top bi lldata he had a layer like this
LSHIFT(Key_0), Key_F6, Key_F7, Key_F8, Key_F9, Key_F10, Key_F11,
Key_Enter, Key_Home, LCTRL(Key_LeftArrow), Key_UpArrow, LCTRL(Key_RightArrow), M(L_AA), Key_F12,
Key_End, Key_LeftArrow, Key_DownArrow, Key_RightArrow, M(L_AE), M(L_OE),
Consumer_PlaySlashPause, Consumer_ScanNextTrack,Key_Mute, Consumer_VolumeDecrement, Consumer_VolumeIncrement, Key_Backslash, Key_Pipe,
___, ___, Key_mouseBtnL, Key_mouseBtnR,
___)
};

but how does the program know what “LSHIFT” (and what does key_0 mean) is, it only used one other time in the [FUNCTION] = KEYMAP_STACKED layer set as “LSHIFT(Key_9),”, yet the documantation on the top of that files states that the danish characters are mapped to the FN layer. I could copy the [QWERTY] layer, could I then just swap [QWERTY] with “OSM(RightControl)”, copy paste the entire [QWERTY] layer and change the keys corresponding?

Apologies for the incomplete instructions; I haven’t had much time in front of a real computer in the past few days. I’m going to try to answer some of your questions, and maybe a couple that you didn’t ask, but might be helpful anyway:

  1. How does LSHIFT() work?

Each key defined in a keymap comprises two bytes of data. For “normal” keys, one byte is the keycode sent via USB to the host computer, and the other is a set of bit flags. Five of those bit flags are used to tell Kaleidoscope if it should add a modifier (shift, control, et al) to the USB report when that key is pressed, in addition to the keycode. LSHIFT() is a C++ preprocessor macro that sets the “left shift” modifier flag in the flags byte of the Key object in the parens.

  1. What does Key_0 mean?

Key_0 is a pre-defined Key object that stores the USB keycode value for the US QWERTY 0 key. When you tap that key, you’ll get the digit 0 (if your OS keymap is US QWERTY), just like Key_A will get you a letter a (again, assuming US QWERTY).

Combining that with above, LSHIFT(Key_0) will get you the same result as holding down shift and pressing 0.

  1. What does ShiftToLayer() mean?

ShiftToLayer() is entirely different, and has nothing to do with LSHIFT(). Instead of setting a modifier flag, it sets flags telling Kaleidoscope that when that key is pressed, it should activate the specified layer. If that layer has a higher number than the current highest active layer (i.e. it comes later in the definition of keymaps), any keys defined on that layer will take precedence over keys on other active layers.

  1. What’s up with lldata’s firmware sketch?

That sketch has a few Danish characters (Æ, Ø, Å) mapped on the FUNCTION layer by means of the macros L_AA, L_AE, and L_OE. Each macro appears in three places: the macro index enum, the keymap, and the macroAction() function. Those macros are shortcuts to make it quicker and/or easier to enter commonly-used Compose key sequences.

I don’t use shortcuts like that, but I use a wide variety of compose sequences, and not frequently enough to feel that it’s particularly slow to type them. If you’re happy typing compose, a, e to get æ, then there’s no need to define anything special in your sketch. If that’s too slow or awkward for you, figure out where you want to put them in your keymap, and try setting up the macros you need on those keys by defining a key with M(L_AA) (for example).

If you’re still having trouble, I suggest posting a link to your whole sketch, and identifying exactly what you want — i.e. “I want the key labeled A on the FUNCTION layer to produce AE when I type it.” There are plenty of us here who can both help you get it working, and help explain the details of how it works from there; I know I find it much easier to understand these things when starting from a specific, complete example, rather than starting from general theory.

2 Likes

Thanks, your explanation cleared up a few things :). I created a key map in GIMP based on the one on GitHub, I’m terrible at gimp but it should be viewable. It should, in my mind, be easy to do. I just have no idea of what I’m doing.

So I want RCTRL (Right Control) to be it’s own “layer”, this layer is just like the QWERTY layer but has Æ at ;, Ø at L and Å at P. I’ve made some other modifications like making the prog key be the esc key but that I’ve pretty much figured out how to do. Also what do you guys use the any key for?

also THANK YOU for all the help so far, it’s really nice. I want the keys to be easily accessible as I use them quite allot

All I have with me is my phone right now, so I can’t (practically) write up the whole sketch for you to see, but I’ll describe what you need to do to get there:

  1. We’re going to add a new layer to the keymap, so you’ll want to choose a name for it. I’ll use BOKMAL as that name in this example.

  2. Update the enum with the layer names, adding a BOKMAL entry between QWERTY & NUMPAD. This assigns a unique index number to each layer in the list.

  3. Copy the NUMPAD layer, and replace every entry with ___ (three underscores; most of the keys in that layer are already that way). This makes the keys “transparent”, so when that layer is active, the next active layer below it “shines through”, and you’ll get key values from there. Put this new layer between QWERTY & NUMPAD, and change its name to BOKMAL.

  4. Find the keys you want to add on that new layer, and replace the ___ for those keys with M(R_AE), M(R_OE), and M(R_AA) (or whatever the appropriate names for your compose key macros are).

  5. In the QWERTY layer, replace Key_RightControl with ShiftToLayer(BOKMAL). This changes your right control key into a layer shift key (and means that it won’t work as a control key anymore — see below). Now, if you hold down the right ctrl key with the QWERTY layer on top, you’ll get access to those three keys, and the rest of the keyboard will be unchanged. If, instead, you want to switch to that layer without having to hold down the right ctrl key, define it as LockLayer(BOKMAL) on both the QWERTY and BOKMAL layers. That will mean a tap of the right ctrl key will toggle the BOKMAL layer (one tap turns it on, the next turns it off).

If you want to continue having a right control key on your new layer, you could use a different key (any, perhaps) to toggle layers with LockLayer(BOKMAL) instead.

Also, the macro you use may need some adjustment, particularly if you want both lower and uppercase (æ, ø, å & Æ, Ø, Å).

I’ll be happy to give you more detail when I get some time at my home computer.

1 Like

I also had a look at the character composition macro, and I think we can do better. I came up with this, but I haven’t had time to test it, and I need to run:

void composeTapKey(Key key, bool shift_state) {
  if (shift_state && a.keyCode >= Key_A && a.keyCode <= Key_Z) {
    kaleidoscope::hid::pressKey(Key_LeftShift);
  }
  kaleidoscope::hid::pressKey(key);
  kaleidoscope::hid::sendKeyboardReport();
  kaleidoscope::hid::releaseKey(key);
  kaleidoscope::hid::sendKeyboardReport();
}

void compose(Key a, Key b, bool shift_both = false) {
  bool lshift = kaleidoscope::hid::wasModifierKeyActive(Key_LeftShift);
  bool rshift = kaleidoscope::hid::wasModifierKeyActive(Key_RightShift);

  kaleidoscope::hid::releaseKey(Key_LeftShift);
  kaleidoscope::hid::releaseKey(Key_RightShift);

  composeTapKey(Key_RightControl);
  composeTapKey(a, shift_both && (lshift || rshift));
  composeTapKey(b, lshift || rshift);

  if (lshift)
    kaleidoscope::hid::pressKey(Key_LeftShift);
  if (rshift)
    kaleidoscope::hid::pressKey(Key_RightShift);
}

enum : byte {
  COMPOSE_AA,
  COMPOSE_AE,
  COMPOSE_OE,
};

const macro_t *macroAction(byte macro_index, byte key_state) {
  switch(macro_index) {

    case COMPOSE_AA:
      if (keyToggledOn(key_state)) {
        compose(Key_O, Key_A);
      }
      break;

    case COMPOSE_AE:
      if (keyToggledOn(key_state)) {
        compose(Key_A, Key_E, true);
      }
      break;

    case COMPOSE_OE:
      if (keyToggledOn(key_state)) {
        compose(Key_A, Key_E, true);
      }
      break;

    default:
      return MACRO_NONE;
  }

The idea is to get you correct upper and lower case characters, depending on whether or not you’re holding a shift key.

2 Likes

Sorry for the late reply, I had to do a bunch of googling to try and understand parts of your code (and go to work), compilation fails miserably though with the following errors. I’ve tried among other things adding back the macro any key in the macroes but it did not fix the problem. I also uploaded all of this to my GitLab account

https://dpaste.de/KouG <- error message
https://gitlab.com/sam_vimes/model01/blob/master/Model01-Firmware.ino <- code on GitLab

I’m at work now (I work weekends too) so did not have all the time in the world to look at this today, but thank you for your reply! I’ll try some more when I get home, but if you spot the error that’d be super too!

Hi,

EDIT: I’ve managed to flash in a .ino file by IIdata (https://github.com/lldata/Model01-Firmware/blob/master/Model01-Firmware.ino1) but it uses FN-key as modifier with compose, but neither Ubuntu or Linux Mint have the ability to use the FN-key as a compose key. I want to get this working in Linux first as it’s linux I’ll be using most from now on.

My layout uses right alt (AltGr) as the compose key. AltGr is default in WinCompose, so it should just work on windows.

On Linux you have to change AltGr to be the compose key - that must be possible.

When it works you get:
fn + p = å
fn + ; = æ
fn + ’ = ø (you’ll want to swap æ/ø, but that part is easy)

Of course my keymap has a lot more improvements that just the danish macros. And I understand, that they might seem daunting. But the default layout (especially the arrows) is really weird too in my opinion.

Make your own decision. I just wanted to clear up any misunderstandings. I think you were closer than you realize to getting it to work :wink: