Qwertz in general, german in particular

Great, thank you! Looks as if I still have to learn a lot about hacking my Model01, but I get more and more interesting hints and inspirations here which will help me to find the best way of changing my keymap and/or the keyboard’s behaviour. Since you have to change many things anyway, it is a very interesting thing to also try out different approaches and find the most suitable one for me.

Around Easter, when I will have a week off of or two, I will start work on a custom QWERTZ layout at the latest. I will report what will be happening and if I was sussessful or ran into trouble.

The Key labeled * + ~ on a german keyboard is Key_RightBracket

@jesse: I would like to provide #defines for german KeyCodes. I’m thinking about constants in the form Key_de_AUmlaut, Key_de_PlusAndAsterisk. Would an extension of key_defs_keyboard.h be the right way to do this or would you rather put it in a different header file?

5 Likes

For key defines that aren’t actually named the same as in the USB HID spec probably shouldn’t be in the same file as the official HID defines.

That said, having these aliases available would be awesome.

I think we want a new file. Maybe key_defs_keyboard_aliases.h?

I think it would make sense to have a file per language(-family?), otherwise things can quickly become unwieldy. Something like kaliedoscope/lang/de-qwertz.h?

4 Likes

If you want to try my layout proposals without getting too bogged down in the details, just clone this git repo:

And follow the instructions in README-abg.md. It’s a fork of the official quick-start repo but with a selection of keymap building blocks that you can enable and disable by commenting in and out a few #include lines. I recommend ‘merlin2’ for German.

3 Likes

Thank you so much. I am all too happy to try that, too. And if it is not ideal for me, I will certainly learn a lot from it seeing how and what you edited in the original firmware file.

If I want to change the one or other thing in it, I will have a good starting point at least. I really appreciate it. After all, you do not always have to reinvent the wheel, as we say in Germany.

In my Easter break I will take a day or so and really work on the firmware and try everything out that has been suggested to me already, and I will post here how it went. It all sounds promising!

Following the idea of @algernon I created a file ./src/kaleidoscope/lang/de-qwertz.h.

Since keydefs.h already has an #include "key_defs_aliases.h" I think that this would probably be the right place to also include the freshly created file with an #include 'kaleidoscope/lang/de_qwertz.h". Would you agree on that?

I’m currently rewriting my keyboard-layout to use my newly defined constants. Unfortunately I’m getting one error message I didn’t yet find my way around. It occurs when expanding the following macro: #define Key_de_Asterisk LSHIFT(Key_de_Plus) Maybe someone is able to point me into the right direction?

In file included from C:\Users\micha\AppData\Local\Arduino15\packages\keyboardio\hardware\avr\1.22.0\libraries\Kaleidoscope\src/Kaleidoscope.h:23:0,

                 from C:\Users\micha\Documents\Arduino\Model01-Micha-Firmware-using-de-Keys\Model01-Micha-Firmware-using-de-Keys.ino:17:

C:\Users\micha\AppData\Local\Arduino15\packages\keyboardio\hardware\avr\1.22.0\libraries\Kaleidoscope\src/key_defs.h:82:24: error: expected primary-expression before ')' token

 #define LSHIFT(k) ((Key) { k.keyCode, k.flags | SHIFT_HELD })

                        ^

C:\Users\micha\AppData\Local\Arduino15\packages\keyboardio\hardware\avr\1.22.0\libraries\Kaleidoscope-Hardware-Model01\src/Kaleidoscope-Hardware-Model01.h:226:36: note: in definition of macro 'KEYMAP_STACKED'

     {r2c0, r2c1, r2c2, r2c3, r2c4, r2c5, r2c6, r2c7, r2c8, r2c9, r2c10, r2c11, r2c12, r2c13, r2c14, r2c15}, \

                                    ^

C:\Users\micha\AppData\Local\Arduino15\packages\keyboardio\hardware\avr\1.22.0\libraries\Kaleidoscope\src/kaleidoscope/lang/de_qwertz.h:40:25: note: in expansion of macro 'LSHIFT'

 #define Key_de_Asterisk LSHIFT(Key_de_Plus)

                         ^

C:\Users\micha\Documents\Arduino\Model01-Micha-Firmware-using-de-Keys\Model01-Micha-Firmware-using-de-Keys.ino:149:113: note: in expansion of macro 'Key_de_Asterisk'

I found my mistake. I didn’t properly define Key_de_plus. It was #define Key_de_Plus instead of #define Key_de_Plus Key_RightBracket. Sorry to bother you.

I successfully modified my keyboard-layout using the newly defined constants and I’m still able to write ;).

Therefore I created a pull request Added constants for german keyboard layout #302. Please give me feedback on whether or not I should change something. I tried to adhere to the existing nomenclature as much as possible. Any feeback will be greatly appreciated.

2 Likes

Hello everyone,

I am back again in the forum and would like to report what happened so far: Yesterday I took the Model01 out of its box again and started looking into things more seriously. I tried two or three firmware forks and flashed them onto the keyboard which was very easy, by the way.

Unfortunately none of them seemed to work well enough for me. I also found that I have to learn more about the Arduino C syntax. It seems to have some conventions I am not used to, and before trying more or different tweaks, I definitely need to have a better grasp. I actually have not used the graphical Arduino environment, but got along well with a text editor. The firmware file is well documented, and many things are easy enough to understand.
The other thing, of course, is really the big question: the keyboard has relatively few keys. Where do I put all the characters so it makes good sense for typing effectively? You definitely need all the layers available. This to me seems to be the hardest thing. I need a good plan and lots of correct key definitions (downloaded them already).
I am in exactly the same situation as Christopher who started this thread, and I, too, will probably need quite a few trials and errors. So far, the Model01 not of much use for me, although a very good piece of hardware. The solutions for German layout keyboards I have seen here, are mostly based on other approaches like Neo and the like. But since a new keyboard like the Model01 is always something you have to get used to anyway, I do not want to learn two things at a time and rather prefer to stick to QWERTZ.

I have always been interested in ergonomic keyboards, and since three years I have been using the Truly Ergonomic Keyboard which is very solid and well working and a pleasure to type on. It has a couple keys more than the Model01 and an interesting mechanism to switch between layouts by DIP switches. You also can switch to German layout, of course. But you also can create a completely custom layout for yourself with a web editor and flash that one to the keyboard.

When I learned about the Model01 and saw the pictures of the prototypes, I immediately thought that I would be interested in the project and ordered my Model01. It turns out now that this one here is more challenging for the end-users from outside the English-speaking world, and I think that there should really be something useable out of the box for them, too, if this keyboard should reach a market beyond the people who do not care about doing something themselves to make it work, and who have at least some basic knowledge of how to write a little bit of code.

I am taking it as a challenge and as an opportunity to learn something new. I think I will try and write my own firmware from scratch, and this will be rather a project for the summer, because you cannot do this with an occasional spare hour here and there. It will be my own personal Summer of Code…

I will come back and tell how it went when I will have a working firmware and share it if someone is interested.

1 Like

All the layers? That means you need 32*64 = 2048 different keycodes? :wink:

1 Like

I’m curious how you guys have implemented Umlaute? I have them on my FN layer, like FN+a for an ä.

Using TapDance, one tap produces a lowercase Umlaut, two taps produce an upercase Umlaut.

I’m not particularly happy with the FN solution. It takes a little bit too long…

On a side note, I’m not using the Unicode plugin. I have installed the EurKEY Keyboard Layout by Steffen Brüntyen on Windows, it’s a Dvorak QWERTY layout with Umlaute, basically. That part at least works well enough.

I use a very similar approach, based on normal EurKEY. My umlauts are placed on the primary layer as triple tap dances in the home row. A single tap of the same key gives the original meaning.

I use a custom plugin that does the tap dances and a lot of other stuff which makes it easy to combine it with shift and OneShot shift for capital umlauts. It’s called Kaleidoscope-Papageno and I am currently working on its release.

I didn’t try the stock TapDance plugin but expect it to co-operate with shift as well.

Unfortunately, it doesn’t.

TapDance triggers a macro:

case TapDanceKey::AUml: {
  return tapDanceActionKeys(tap_count, tap_dance_action, M(MACRO_UMLAUT_A), M(MACRO_UMLAUT_CA));
}

Which translates to:

case MACRO_UMLAUT_A:
  return MACRODOWN(D(RightAlt), T(A), U(RightAlt));    

Shift is never taken into account. Neither normal Shift nor OneShot shift. I don’t know why.

I don’t know if I would use Shift for uppercase Umlaute, anyway. I think I would prefer pressing 2 keys (tapping the second one) to pressing 3 different keys. I would have to try the Shift solution to decide.

That problem may be due to the order of key matrix processing (event handler hooks). If the TapDance key is processed before the shift key, the shift key is not yet added to the current HID report (which is empty at the beginning of each cycle).

You could verify this assumption by temporarily using key (0,0) (PROG) as shift key. This would force the shift key to be processed as the very first key.

@algernon: Am I right with this assumption of order dependence? And could this maybe be solved by generally shifting tap dance action processing to the pre-clear loop hook? This might cover all cases except for TapDance actions that activate modifiers or layer changes.

Yeah, three keys is definitely too much. As I have my umlauts on the primary layer it only takes two different keys. That’s acceptable for me.

Yeah, this order dependence may very well be the root of the issue, and indeed, moving some of the TapDance stuff to pre-clear might solve it, too. As would a few other things… I’ll get there, eventually!

AFAICC, all macros and plugins that trigger additional HID reports out of event handler hooks are supposed to be affected by said order dependence. This means that all of those would need to be processed after the whole matrix scan happened to be on the safe side.

Toggling modifiers by tap dance actions does not seem to be a good idea. One-shots as TapDance actions on the other hand, makes sense. Especially one-shot layer switching seems reasonable.

But that’s all off-topic here, anyway.

1 Like

Good idea, but not quite. That key would probably work for this test, but it’s actually the second to last key processed in the top row (I’m pretty sure the last one is right control on the default layout). The keys are actually processed top to bottom, right to left, with the thumb keys first in each row on the left side, and last on the right side, and palm keys inserted in the third row of the innermost columns.

The easiest way to test for a scan-order bug is to use two keys that are side by side — the key on the right gets processed first. Or use two keys in different rows — the key that’s farther away from you gets processed first. Don’t use thumb keys, palm keys, or the innermost columns, because the order they get processed is hard to remember and in many cases, not what you would expect.

1 Like

I’m with @noseglasses & @algernon — this is almost certainly a scan order bug. It can probably be worked around by using Macros triggered by TapDance that test wasModifierKeyActive(), and adding shift to the report if either shift key was in the previous report.

1 Like

Thanks for this bit of information, I obviously did not look close enough. Are you aware of an explanation for this somewhat odd scan order?

For others who want to know where in the firmware code this information can be found, here it is:
https://github.com/keyboardio/Kaleidoscope-Hardware-Model01/blob/f56de510ae28d215a58c0964f62a01cca4d1b99f/src/Kaleidoscope-Hardware-Model01.cpp#L167

1 Like