TMK keyboard firmware collection

User avatar
hasu

01 Dec 2012, 03:26

I hope that this thread becomes a place to get bug report, feedback and suggestion from community.

https://github.com/tmk/tmk_keyboard

See wiki for compiling, configuration and keymap.


Image Image Image Image Image Image Image Image Image


Features
  • Multi-layer keymap
  • Mouse key
  • System Control Key
  • Media Control Key
  • USB NKRO
  • PS/2 mouse support
  • Macro
  • Debug Console

Keyboards
https://github.com/tmk/tmk_keyboard/tre ... r/keyboard
Converters
https://github.com/tmk/tmk_keyboard/tre ... /converter TMK Products
You can get TMK products like protocol converters and keyboard controllers from here and support this project.
https://geekhack.org/index.php?board=198.0
Last edited by hasu on 18 Sep 2021, 01:53, edited 9 times in total.

HelgeG

20 Dec 2012, 03:04

I have used the code on github for my own HHKB mod, and it works perfectly. I really appreciate that you have made it available. I do have one question, and that is how to use the console mode. Where can I see the output from the console mode and interact with it?

mtl

20 Dec 2012, 05:45

hasu, thank you for the firmware and open sourcing it. It's really great. Do you have plans to support switching layers by changing the position of MX-lock switches? I was thinking of hacking that in there but didn't want to waste the effort if you were already working on it. Thanks!

HelgeG

20 Dec 2012, 12:30

I am having am issue where the mappings from the first layer I choose get "stuck". Whichever Fn-key I subsequently use to select a layer, the mappings from the first layer are applied. I am trying to figure out if this is an accidental bug that I have introduced.

User avatar
uberben

20 Dec 2012, 16:33

mtl wrote:hasu, thank you for the firmware and open sourcing it. It's really great. Do you have plans to support switching layers by changing the position of MX-lock switches? I was thinking of hacking that in there but didn't want to waste the effort if you were already working on it. Thanks!
I have dug a bit through the code and, assuming an MX-lock switch just locks in the on position as if you are holding a normal key down, you should be able to treat that key just as any other function switching key.

User avatar
damorgue

21 Dec 2012, 00:05

uberben wrote:
mtl wrote:hasu, thank you for the firmware and open sourcing it. It's really great. Do you have plans to support switching layers by changing the position of MX-lock switches? I was thinking of hacking that in there but didn't want to waste the effort if you were already working on it. Thanks!
I have dug a bit through the code and, assuming an MX-lock switch just locks in the on position as if you are holding a normal key down, you should be able to treat that key just as any other function switching key.
I know there are some interesting ideas out there where the mx lock forces its state to the OS. If the OS has caps lock on, and the mx lock isn't depressed, then it sends caps lock to change it. This prevents desyncs where the OS has caps lock turned off and the caps lock of the keyboard is depressed. I find the mx lock to be unreliable in this regards, as it can activate without physically locking for instance.

mtl

21 Dec 2012, 04:40

uberben wrote:
mtl wrote:I have dug a bit through the code and, assuming an MX-lock switch just locks in the on position as if you are holding a normal key down, you should be able to treat that key just as any other function switching key.
Thank you, uberben. :) I think I'm after something slightly different, but it doesn't look too hard to implement. The default behavior appears to let you press multiple FN keys at once, but will switch to the highest-numbered active layer when you do. I'd rather have it treat FN keys as bits of the FN layer index, so if I have 3 MX lock switches, their individual on/off states could select from 8 layers. See the assignment enabled by FN_BITFIELD (the following is from common/keyboard.c):

Code: Select all

static void layer_switch_on(uint8_t code)
{
    if (!IS_FN(code)) return;
    fn_state_bits |= FN_BIT(code);
#ifdef FN_BITFIELD
    uint8_t new_layer = keymap_fn_layer(fn_state_bits & 7);
#else
    uint8_t new_layer = (fn_state_bits ? keymap_fn_layer(biton(fn_state_bits)) : default_layer);
#endif
    if (current_layer != new_layer) {
        Kdebug("Layer Switch(on): "); Kdebug_hex(current_layer);
        Kdebug(" -> "); Kdebug_hex(new_layer); Kdebug("\n");

        clear_keyboard_but_mods();
        current_layer = new_layer;
    }
}
... and similarly for layer_switch_off(). Note the above code hasn't been tested (will report back if it works.. need to define some layers first!).

mtl

21 Dec 2012, 05:36

The change appears to work well. :D Pull request sent!

User avatar
hasu

21 Dec 2012, 07:13

HelgeG,
Currently my firmware supports only simple momentary layer switching, not toggling and bitwise switch. I'm working on new keymap/layer framework to support those features now.
I'm not sure exactly what your problem is, though, you'll come across some difficulty if you want to use other than momentary switching.

mtl,
Thanks for your patch of the bit field switching. I'll see it later.

HelgeG

21 Dec 2012, 12:30

hasu, thanks for pointing me to hid_listen. It made it a lot easier to figure out what my problem is.

If I only use Fn1, Fn2 and Fn3, everything is fine, and switching between layers works fine. Once I press Fn4, from then on any subsequent Fn key press will continue to use layer 4. The same applies to Fn5, Fn6 and Fn7

Here is the output from the keyboard debug mode where I do a quick test. First I press Fn1 to switch to layer 1. Then I press Fn4 to switch to layer 4. The next time I press Fn1 it does not activate layer 1, but activates layer 4. From now on, any Fn-press will activate layer 4 only.

Code: Select all

state: IDLE kind: 01 code: E9d    <-- Fn1 is mapped to the HHKB Fn key
Layer Switch(on): 00 -> 01        <-- Fn1 switches to layer 1
state: IDLE kind: 02 code: E9u
Layer Switch(off): 01 -> 00
FAIL SAFE: clear all keys(default layer).
state: IDLE kind: 03 code: ECd    <-- Fn4 is mapped to the P key
NEXT: IDLE -> DELAYING
Layer Switch(on): 00 -> 04        <-- Fn4 switches to layer 4
NEXT: DELAYING -> IDLE
state: IDLE kind: 06 code: 14u
FAIL SAFE: clear all keys(default layer).
state: IDLE kind: 01 code: E9d    <-- Pressing Fn1 again
Layer Switch(on): 00 -> 04        <-- Fn1 now switches to layer 4!!
state: IDLE kind: 00 code: 00u
FAIL SAFE: clear all keys(default layer).
I will try to figure out what is happening in the code to cause the layer to get "stuck" like this.

User avatar
hasu

21 Dec 2012, 14:40

It is a bug. Unexpected usage of keymap seems to cause this bug. This is also a design bug of current layer switching :(
I want to resolve this problem on coming new layer/keymap framework.

Your layer0 has Fn4 on 'P' key but it looks like layer4 has no Fn4 on that key position. To define momentary Fn4 key you must put on same Fn4 key on destination layer too.

This is not solution but maybe workaround. I'm on the road now so I can't test this patch.

Code: Select all

diff --git a/common/keyboard.c b/common/keyboard.c
index cd1ceb4..e94ebb5 100644
--- a/common/keyboard.c
+++ b/common/keyboard.c
@@ -619,6 +619,10 @@ void keyboard_task(void)
             Kdebug("FAIL SAFE: clear all keys(default layer).\n");
             clear_keyboard();
             current_layer = default_layer;
+            fn_state_bits = 0;
+            delayed_fn = (keyrecord_t){};
+            waiting_key = (keyrecord_t){};
+            NEXT(IDLE);
         }
     }

User avatar
hasu

21 Dec 2012, 15:27

damorgue wrote: I know there are some interesting ideas out there where the mx lock forces its state to the OS. If the OS has caps lock on, and the mx lock isn't depressed, then it sends caps lock to change it. This prevents desyncs where the OS has caps lock turned off and the caps lock of the keyboard is depressed. I find the mx lock to be unreliable in this regards, as it can activate without physically locking for instance.
ADB converter has similar lock switch support already. It looks like this feature can be applied to all keyboard and converter projects as build option or keymap option. I added this as issue on github, I'll work on this later when I have time. https://github.com/tmk/tmk_keyboard/issues/19

Thanks for the suggestion.

HelgeG

21 Dec 2012, 16:14

hasu wrote:Your layer0 has Fn4 on 'P' key but it looks like layer4 has no Fn4 on that key position. To define momentary Fn4 key you must put on same Fn4 key on destination layer too.
Thanks very much for the reply and for the patch. I have to say it is completely awesome to be able to program my own keyboard, and I am very grateful to you for making the code available.

HelgeG

21 Dec 2012, 16:40

Is there any easy way within the current framework to add functionality to modifier keys? Some use cases might explain better what I want:

- If I press CTRL with another key, it functions normally. If I press and release CTRL without pressing any other keys, it will trigger ESC.
- If I press LEFT SHIFT with another key, it functions normally. If I press and release LEFT SHIFT without pressing any other keys, it will trigger left parenthesis. Similarly for RIGHT SHIFT, but will trigger right parenthesis.

I currently use third party utilities to enable this functionality, but it would be great to have the actual keyboard implement it. I will try to get this done on my own, but my C is rusty.

User avatar
hasu

22 Dec 2012, 02:51

HelgeG wrote:Is there any easy way within the current framework to add functionality to modifier keys? Some use cases might explain better what I want:

- If I press CTRL with another key, it functions normally. If I press and release CTRL without pressing any other keys, it will trigger ESC.
- If I press LEFT SHIFT with another key, it functions normally. If I press and release LEFT SHIFT without pressing any other keys, it will trigger left parenthesis. Similarly for RIGHT SHIFT, but will trigger right parenthesis.
Unfortunately I don't think there is easy way to do that in current firmware. First use case is exactly what I want to do in new framework, in my case backspace like Colemak suggests instead of esc. Second one needs two codes(Shift+9/0) to register parenthesis, this usage is beyond my expectation but I'll change design to support this use case in next version.
I currently use third party utilities to enable this functionality, but it would be great to have the actual keyboard implement it. I will try to get this done on my own, but my C is rusty.
What kind of util do you use now? AHK script? I'm curious to see your script or configuration.

HelgeG

24 Dec 2012, 10:20

hasu wrote: What kind of util do you use now? AHK script? I'm curious to see your script or configuration.
I am on a Mac, so I have used two preference panes called KeyRemap4MacBook and PcKeyboardHack. With your firmware I no longer need PCKeyboardHack, but the KeyRemap4Macbook preference pane has functionality that allows changing the way modifier keys work. It has a built-in mapping for mapping CTRL to CTRL/ESC, and it also allows for user customisation through an XML file.

The mapping of SHIFT keys is as follows:

Code: Select all

      <item>
        <name>Shifts to Parentheses</name>
        <appendix>Shifts, when pressed alone, type parentheses.</appendix>
        <appendix>When used with other keys they're normal shifts.</appendix>
        <identifier>space_cadet.shifts_to_parens</identifier>
        <!-- This is the basic mapping. -->
        <autogen>--KeyOverlaidModifier-- KeyCode::SHIFT_R, ModifierFlag::SHIFT_R | ModifierFlag::NONE, KeyCode::SHIFT_R, KeyCode::KEY_0, ModifierFlag::SHIFT_L</autogen>
        <autogen>--KeyOverlaidModifier-- KeyCode::SHIFT_L, ModifierFlag::SHIFT_L | ModifierFlag::NONE, KeyCode::SHIFT_L, KeyCode::KEY_9, ModifierFlag::SHIFT_R</autogen>
        <!--
                    Remap the "rolls" of () and )( because it's too easy to hit one
                    before finishing the other, and there's no other reason to be
                    pressing both shift keys at once anyway
                -->
        <autogen>--KeyToKey-- KeyCode::SHIFT_L, ModifierFlag::SHIFT_R, KeyCode::KEY_0, ModifierFlag::SHIFT_L, KeyCode::KEY_9, ModifierFlag::SHIFT_L</autogen>
        <autogen>--KeyToKey-- KeyCode::SHIFT_R, ModifierFlag::SHIFT_L, KeyCode::KEY_9, ModifierFlag::SHIFT_L, KeyCode::KEY_0, ModifierFlag::SHIFT_L</autogen>
        <!--
                    Remap Rshift+Space to ') ', because when typing an end paren and
                    then a space I tend to hit space before I let go of rshift.
                -->
        <autogen>--KeyToKey-- KeyCode::SPACE, ModifierFlag::SHIFT_R, KeyCode::KEY_0, ModifierFlag::SHIFT_L, KeyCode::SPACE</autogen>
      </item>
I also have a mapping that translates the right option key (ALT) key to a combination of modifier keys:

Code: Select all

      <item>
        <name>Remap Right Option to Hyper</name>
        <appendix>OS X doesn't have a Hyper. This maps Right Option to Control + Shift + Option + Command.</appendix>
        <identifier>space_cadet.right_option_to_hyper</identifier>
        <autogen>--KeyToKey-- KeyCode::F19, KeyCode::COMMAND_L, ModifierFlag::OPTION_L | ModifierFlag::SHIFT_L | ModifierFlag::CONTROL_L</autogen>
      </item>
I the snippet above, the translation is from the F19 key. I used to use PCKeyboardHack to map the right option key to F19, but now this is done through the firmware, so I have uninstalled it from my machine. KeyRemap4Macbook I still use, as so far I haven't been able to replicate the functionality with the firmware.

The above mappings were inspired by a blog post written by Steve Losh.

User avatar
hasu

11 Jan 2013, 01:43

Added instructions. I hope this helps new users somewhat.

User avatar
damorgue

11 Jan 2013, 01:48

hasu wrote:
damorgue wrote: I know there are some interesting ideas out there where the mx lock forces its state to the OS. If the OS has caps lock on, and the mx lock isn't depressed, then it sends caps lock to change it. This prevents desyncs where the OS has caps lock turned off and the caps lock of the keyboard is depressed. I find the mx lock to be unreliable in this regards, as it can activate without physically locking for instance.
ADB converter has similar lock switch support already. It looks like this feature can be applied to all keyboard and converter projects as build option or keymap option. I added this as issue on github, I'll work on this later when I have time. https://github.com/tmk/tmk_keyboard/issues/19

Thanks for the suggestion.
I know you probably haven't looked at this already, so I thought I would try the already existing "LOCKING_CAPS" in your code. It doesn't work for me at all it seems. Is it just a placeholder, or how is it supposed to function as it is implemented currently?

User avatar
hasu

11 Jan 2013, 01:59

Did you try it on ADB keyboard? I think push-lock caps lock works on ADB.
Other keyboard/converters doesn't support yet at this time.

User avatar
damorgue

11 Jan 2013, 02:09

hasu wrote:Did you try it on ADB keyboard? I think push-lock caps lock works on ADB.
Other keyboard/converters doesn't support yet at this time.
Explains it. Never mind me then, carry on.

relcc

11 Jan 2013, 02:39

I just modded a KBT Pure with a Teensy and 2-button backspace replacement and used tmk_keyboard for the firmware to mimic my HHKB. I created a new keyboard PureHHKB in my copy of the repository. It works great. I'm having trouble with the debug console however. If I enable CONSOLE_ENABLE in Makefile and print_enable and debug_enable in matrix.c , what should I do to see the output. hid_listen doesnt show anything and there's no serial port available. Where does the output go?

User avatar
hasu

11 Jan 2013, 03:12

Interesting project! Can I see your keyboard somewhere?

Your configuration looks like good. If you are on Linux or something you should use 'sudo' to get access the device.
If you are on Windows try changing USB port or updating driver in 'Device Manager' to clear device driver setting/cache.

As a last resort changing VID in config.h may be useful to clear driver setting for the keyboard in OS.

relcc

11 Jan 2013, 03:37

I understand it should come up as a serial USB device. I'll try changing VID.

I'm still awaiting key caps, but the mod is described here : http://deskthority.net/keyboards-f2/kbt ... t4598.html

yeeeargh

12 Jan 2013, 13:37

hi there,

I found out that dfu-programmer provides a windows binary since the latest version. (http://sourceforge.net/projects/dfu-pro ... p/download) It works quite fine for me. Just had to rename the programm from dfu-programmer-0.5.5.exe to dfu-programmer.exe in order to make it work with the existing makefiles. Even drivers are provided (Haven't tested them jet, but they seem to be the same as the ones provided by Amtels Flip).

User avatar
hargon

14 Jan 2013, 11:16

Hi,

i have a modified pcb with a 18x8 matrix (i'll have to check whether i recall the actual size correctly because the project rested a while) i want to controll with a teensy 2.0. Until now i just had quick look on your code and wondered, how i could modify it to get a controller for this matrix. Any hints on how i have to wire the teensy and where to change the code should help me to complete the task faster. ;) Thanks!

relcc

14 Jan 2013, 11:27

You would probably have to many rows/columns for a Teensy 2.0, so you could check if you could merge columns/rows. Then you connect each row and column to an input. You can make a copy of a desired version in the keyboard section and apply your own port connections. Then you should enter the matrix for your keyboard. This is what I did for my PureHHKB mod.

User avatar
hasu

14 Jan 2013, 11:51

hargon,
You should change confhg.h and matrix.c to define how to read your matrix then edit keymap.c for your keyboard layout.

Project keyboard/macway is old but plain and still good to start with. And you may want to see the latest project keyboard/gh60 which is on 'gh60' branch, not merged into master branch yet.

User avatar
fruktstund

04 Feb 2013, 18:39

hasu, I'm here to bug you a bit again! :)

Just wondering if your firmware supports toggleable layers? With "toggleable layers" I mean something like "press and release a button to change the keyboard layout". In my case I want my Caps Lock to either work as a Control key or a Caps Lock key, depending on which computer I use the keyboard on. Currently, I need to reprogram it every time I change computers.

Maybe there already is a function like this, or a better alternative?

relcc

04 Feb 2013, 22:47

I'm experiencing heavy bbbounce on the keyboarrd. Changing the BOUNCE rate doesnt help. Isn't there a better bounce algorithm?

User avatar
hasu

05 Feb 2013, 00:51

fruktstund,
At this time it doesn't support 'toggling layer' feature but I'm working on new keymap framework which support many features including it. It is not long before making new version available.

But your problem may be solvable with changing layer by a magic command.
First you need to define one keymap with control on layer0, and other with caps lock on layer1.
You can usually use layer0 because layer0 is defualt layer, if you want to use layer1 just use magic command:
LShift + RShift + 1. You can return to layer0 with LShift + RShift + 0.
Magic keybind(LShift + RShift) may be vary on project, see config.h to check.


relcc,
Fortuately I haven't had serious bounce on Cherry and Alps so far, and not looked into debouncing algo.
Did you try adding some delay?
https://github.com/tmk/tmk_keyboard/blo ... trix.c#L98

Post Reply

Return to “Workshop”